From 7a6fc1653679ee1c40eca337922457476cfd88a3 Mon Sep 17 00:00:00 2001 From: Sahitya Tummala Date: Wed, 6 Dec 2017 08:52:36 +0530 Subject: [PATCH 001/508] defconfig: msm8937: Disable unnecessary configs Disable unnecessary configs to reduce memory foot print. Change-Id: Iafd3af46a1a42c82274d014a7e6bce8e562fabda Signed-off-by: Sahitya Tummala --- arch/arm/configs/msm8937-perf_defconfig | 4 ---- arch/arm/configs/msm8937_defconfig | 4 ---- 2 files changed, 8 deletions(-) diff --git a/arch/arm/configs/msm8937-perf_defconfig b/arch/arm/configs/msm8937-perf_defconfig index f20f0be1bde0b..d5472ffcc804d 100644 --- a/arch/arm/configs/msm8937-perf_defconfig +++ b/arch/arm/configs/msm8937-perf_defconfig @@ -580,10 +580,6 @@ CONFIG_PWM_QPNP=y CONFIG_ARM_GIC_PANIC_HANDLER=y CONFIG_SENSORS_SSC=y CONFIG_MSM_TZ_LOG=y -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set CONFIG_EXT4_FS=y CONFIG_EXT4_FS_SECURITY=y CONFIG_QUOTA=y diff --git a/arch/arm/configs/msm8937_defconfig b/arch/arm/configs/msm8937_defconfig index d3b2be06142b5..e83bbabd7822d 100644 --- a/arch/arm/configs/msm8937_defconfig +++ b/arch/arm/configs/msm8937_defconfig @@ -612,10 +612,6 @@ CONFIG_CORESIGHT_REMOTE_ETM=y CONFIG_CORESIGHT_QPDI=y CONFIG_SENSORS_SSC=y CONFIG_MSM_TZ_LOG=y -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set CONFIG_EXT4_FS=y CONFIG_EXT4_FS_SECURITY=y CONFIG_QUOTA=y From c4cf8be226f2f9ec6c61309dc683b329fd44c50d Mon Sep 17 00:00:00 2001 From: Kishor PK Date: Mon, 1 Jan 2018 14:48:51 +0530 Subject: [PATCH 002/508] defconfig: msm8909: Enable CONFIG_MSM_FORCE_WDOG_BITE_ON_PANIC Enable this option to trigger a watchdog bite during kernel panic so that we can get the context of all the online CPUs in 8909. Change-Id: I9ba6c91dbf09a22118fdb01d7a92e07087a1dad8 Signed-off-by: Kishor PK --- arch/arm/configs/msm8909-perf_defconfig | 1 + arch/arm/configs/msm8909_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/msm8909-perf_defconfig b/arch/arm/configs/msm8909-perf_defconfig index 06f39157a96c8..de404e9497fac 100644 --- a/arch/arm/configs/msm8909-perf_defconfig +++ b/arch/arm/configs/msm8909-perf_defconfig @@ -461,6 +461,7 @@ CONFIG_MSM_MEMORY_DUMP_V2=y CONFIG_MSM_BOOT_STATS=y CONFIG_MSM_COMMON_LOG=y CONFIG_MSM_WATCHDOG_V2=y +CONFIG_MSM_FORCE_WDOG_BITE_ON_PANIC=y CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y CONFIG_MSM_RUN_QUEUE_STATS=y CONFIG_MSM_SCM=y diff --git a/arch/arm/configs/msm8909_defconfig b/arch/arm/configs/msm8909_defconfig index b01d1e8264c13..564310f040ff4 100644 --- a/arch/arm/configs/msm8909_defconfig +++ b/arch/arm/configs/msm8909_defconfig @@ -472,6 +472,7 @@ CONFIG_MSM_MEMORY_DUMP_V2=y CONFIG_MSM_BOOT_STATS=y CONFIG_MSM_COMMON_LOG=y CONFIG_MSM_WATCHDOG_V2=y +CONFIG_MSM_FORCE_WDOG_BITE_ON_PANIC=y CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y CONFIG_MSM_RUN_QUEUE_STATS=y CONFIG_MSM_SCM=y From d06db60b2e94025caef325be5d484449ab46cb16 Mon Sep 17 00:00:00 2001 From: Michael Adisumarta Date: Wed, 1 Nov 2017 18:16:48 -0700 Subject: [PATCH 003/508] msm: ipa: dynamic memory leak fix This is a fix for dynamic memory leak seen with incorrectly allocating memory of a different size than with intended size. Change-Id: I821442ee6728ea90ceab7644e194f4e06369333a Acked-by: Jyothi Jayanthi Signed-off-by: Michael Adisumarta --- drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c index 477d8427f9cf3..9ceced0c924fa 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c @@ -616,8 +616,9 @@ static void ipa_save_uc_smmu_mapping_pa(int res_idx, phys_addr_t pa, unsigned long iova, size_t len) { IPADBG("--res_idx=%d pa=0x%pa iova=0x%lx sz=0x%zx\n", res_idx, - &pa, iova, len); - wdi_res[res_idx].res = kzalloc(sizeof(struct ipa_wdi_res), GFP_KERNEL); + &pa, iova, len); + wdi_res[res_idx].res = kzalloc(sizeof(*wdi_res[res_idx].res), + GFP_KERNEL); if (!wdi_res[res_idx].res) BUG(); wdi_res[res_idx].nents = 1; @@ -643,7 +644,8 @@ static void ipa_save_uc_smmu_mapping_sgt(int res_idx, struct sg_table *sgt, return; } - wdi_res[res_idx].res = kcalloc(sgt->nents, sizeof(struct ipa_wdi_res), + wdi_res[res_idx].res = kcalloc(sgt->nents, + sizeof(*wdi_res[res_idx].res), GFP_KERNEL); if (!wdi_res[res_idx].res) BUG(); From a3c656f760ec1ca4405793cadf729baf4f48d963 Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Wed, 27 Dec 2017 17:08:29 +0530 Subject: [PATCH 004/508] msm: ais: sensor: actuator: avoid accessing out of bound memory Issue: When total_steps is updated, after that, copy_from_user fails with an error, then, i2c_reg_tbl is not allocated. In this case, when calling msm_actuator_parse_i2c_params, it lead to out-of-bound memory write. Fix: 1) Assign total_steps to zero when error from copying. 2) Add NULL pointer check for i2c tbl. 3) Fixing the issue where the function can return with an error code leaving "a_ctrl->i2c_reg_tbl" and "a_ctrl->total_steps" out of sync. Change-Id: Ia01851c8c5fda3a466cada885cae5c0651857b16 Signed-off-by: Rahul Sharma --- .../msm/ais/sensor/actuator/msm_actuator.c | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/ais/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/ais/sensor/actuator/msm_actuator.c index 933541962e079..f68d031a9dcd8 100644 --- a/drivers/media/platform/msm/ais/sensor/actuator/msm_actuator.c +++ b/drivers/media/platform/msm/ais/sensor/actuator/msm_actuator.c @@ -56,6 +56,10 @@ static int32_t msm_actuator_piezo_set_default_focus( struct msm_camera_i2c_reg_setting reg_setting; CDBG("Enter\n"); + if (a_ctrl->i2c_reg_tbl == NULL) { + pr_err("failed. i2c reg tabl is NULL"); + return -EFAULT; + } if (a_ctrl->curr_step_pos != 0) { a_ctrl->i2c_tbl_index = 0; @@ -539,6 +543,12 @@ static int32_t msm_actuator_piezo_move_focus( return -EFAULT; } + + if (a_ctrl->i2c_reg_tbl == NULL) { + pr_err("failed. i2c reg tabl is NULL"); + return -EFAULT; + } + if (dest_step_position > a_ctrl->total_steps) { pr_err("Step pos greater than total steps = %d\n", dest_step_position); @@ -596,6 +606,12 @@ static int32_t msm_actuator_move_focus( pr_err("Invalid direction = %d\n", dir); return -EFAULT; } + + if (a_ctrl->i2c_reg_tbl == NULL) { + pr_err("failed. i2c reg tabl is NULL"); + return -EFAULT; + } + if (dest_step_pos > a_ctrl->total_steps) { pr_err("Step pos greater than total steps = %d\n", dest_step_pos); @@ -1179,7 +1195,8 @@ static int32_t msm_actuator_set_position( } if (!a_ctrl || !a_ctrl->func_tbl || - !a_ctrl->func_tbl->actuator_parse_i2c_params) { + !a_ctrl->func_tbl->actuator_parse_i2c_params || + !a_ctrl->i2c_reg_tbl) { pr_err("failed. NULL actuator pointers."); return -EFAULT; } @@ -1291,7 +1308,6 @@ static int32_t msm_actuator_set_param(struct msm_actuator_ctrl_t *a_ctrl, a_ctrl->region_size = set_info->af_tuning_params.region_size; a_ctrl->pwd_step = set_info->af_tuning_params.pwd_step; - a_ctrl->total_steps = set_info->af_tuning_params.total_steps; if (copy_from_user(&a_ctrl->region_params, (void *)set_info->af_tuning_params.region_params, @@ -1306,7 +1322,6 @@ static int32_t msm_actuator_set_param(struct msm_actuator_ctrl_t *a_ctrl, cci_client->sid = set_info->actuator_params.i2c_addr >> 1; cci_client->retries = 3; - cci_client->id_map = 0; cci_client->cci_i2c_master = a_ctrl->cci_master; cci_client->i2c_freq_mode = set_info->actuator_params.i2c_freq_mode; @@ -1339,6 +1354,8 @@ static int32_t msm_actuator_set_param(struct msm_actuator_ctrl_t *a_ctrl, return -ENOMEM; } + a_ctrl->total_steps = set_info->af_tuning_params.total_steps; + if (copy_from_user(&a_ctrl->reg_tbl, (void *)set_info->actuator_params.reg_tbl_params, a_ctrl->reg_tbl_size * From b6959f75408476781f072cb6ece830e002ef1c3c Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Fri, 12 Jan 2018 13:32:37 +0530 Subject: [PATCH 005/508] msm: ipa: Fix to unsigned integer underflow Added code changes to fix the unsigned integer underflow leads to accessing unmapped memory. Change-Id: I8148aebd3597ec6ae8c184199afe816f3d80636e Acked-by: Ashok Vuyyuru Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c | 12 ++++++++++-- drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c index 4c4a97f52987d..16bff82a116dd 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1445,7 +1445,11 @@ static ssize_t ipa_read_nat4(struct file *file, pr_err("Table Size:%d\n", ipa_ctx->nat_mem.size_base_tables); - pr_err("Expansion Table Size:%d\n", + if (!ipa_ctx->nat_mem.size_expansion_tables) + pr_err("Expansion Table Size:%d\n", + ipa_ctx->nat_mem.size_expansion_tables); + else + pr_err("Expansion Table Size:%d\n", ipa_ctx->nat_mem.size_expansion_tables-1); if (!ipa_ctx->nat_mem.is_sys_mem) @@ -1460,6 +1464,8 @@ static ssize_t ipa_read_nat4(struct file *file, pr_err("\nBase Table:\n"); } else { + if (!ipa_ctx->nat_mem.size_expansion_tables) + continue; tbl_size = ipa_ctx->nat_mem.size_expansion_tables-1; base_tbl = (u32 *)ipa_ctx->nat_mem.ipv4_expansion_rules_addr; @@ -1559,6 +1565,8 @@ static ssize_t ipa_read_nat4(struct file *file, pr_err("\nIndex Table:\n"); } else { + if (!ipa_ctx->nat_mem.size_expansion_tables) + continue; tbl_size = ipa_ctx->nat_mem.size_expansion_tables-1; indx_tbl = (u32 *)ipa_ctx->nat_mem.index_table_expansion_addr; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index 25159acf6e9b6..33b0e2187bc28 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1430,7 +1430,11 @@ static ssize_t ipa3_read_nat4(struct file *file, pr_err("Table Size:%d\n", ipa3_ctx->nat_mem.size_base_tables); - pr_err("Expansion Table Size:%d\n", + if (!ipa3_ctx->nat_mem.size_expansion_tables) + pr_err("Expansion Table Size:%d\n", + ipa3_ctx->nat_mem.size_expansion_tables); + else + pr_err("Expansion Table Size:%d\n", ipa3_ctx->nat_mem.size_expansion_tables-1); if (!ipa3_ctx->nat_mem.is_sys_mem) @@ -1445,6 +1449,8 @@ static ssize_t ipa3_read_nat4(struct file *file, pr_err("\nBase Table:\n"); } else { + if (!ipa3_ctx->nat_mem.size_expansion_tables) + continue; tbl_size = ipa3_ctx->nat_mem.size_expansion_tables-1; base_tbl = (u32 *)ipa3_ctx->nat_mem.ipv4_expansion_rules_addr; @@ -1544,6 +1550,8 @@ static ssize_t ipa3_read_nat4(struct file *file, pr_err("\nIndex Table:\n"); } else { + if (!ipa3_ctx->nat_mem.size_expansion_tables) + continue; tbl_size = ipa3_ctx->nat_mem.size_expansion_tables-1; indx_tbl = (u32 *)ipa3_ctx->nat_mem.index_table_expansion_addr; From 1c3106052d682cc46155173f596a91e1d2a8d0f2 Mon Sep 17 00:00:00 2001 From: Raghavendra Rao Ananta Date: Thu, 11 Jan 2018 17:33:07 -0800 Subject: [PATCH 006/508] perf: Avoid cpu hotplug during event deletion The event will not be successfully deleted if there was a CPU hotplug going on. The change prevents that from happening. Moreover, the change also disables the ARM PMU irq when the CPU is coming down. This is due to the reason that the deletion of perf event depends on freeing the irqs, which would happen if the irq is disabled in the first place. Change-Id: Ifc3860f723f76d1560e2c9d3fd507e5ead20462a Signed-off-by: Raghavendra Rao Ananta --- arch/arm/include/asm/pmu.h | 1 + arch/arm/kernel/perf_event_cpu.c | 23 ++++++++++++++++++----- kernel/events/core.c | 3 +++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index 0b648c541293b..f86ef1f1e2235 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h @@ -102,6 +102,7 @@ struct arm_pmu { int (*request_irq)(struct arm_pmu *, irq_handler_t handler); void (*free_irq)(struct arm_pmu *); int (*map_event)(struct perf_event *event); + int percpu_irq; int num_events; atomic_t active_events; struct mutex reserve_mutex; diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c index e7418fe4cd9b3..6f2a3959ac4b0 100644 --- a/arch/arm/kernel/perf_event_cpu.c +++ b/arch/arm/kernel/perf_event_cpu.c @@ -200,15 +200,27 @@ static void cpu_pmu_init(struct arm_pmu *cpu_pmu) static int cpu_pmu_notify(struct notifier_block *b, unsigned long action, void *hcpu) { - if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING) + unsigned long masked_action = action & ~CPU_TASKS_FROZEN; + + if (!cpu_pmu) return NOTIFY_DONE; - if (cpu_pmu && cpu_pmu->reset) - cpu_pmu->reset(cpu_pmu); - else + if ((masked_action != CPU_DYING) && + (masked_action != CPU_STARTING)) return NOTIFY_DONE; - return NOTIFY_OK; + switch (masked_action) { + case CPU_DYING: + if (cpu_pmu->plat_device) + disable_percpu_irq(cpu_pmu->percpu_irq); + break; + case CPU_STARTING: + if (cpu_pmu->reset) + cpu_pmu->reset(cpu_pmu); + break; + } + + return NOTIFY_DONE; } static struct notifier_block cpu_pmu_hotplug_notifier = { @@ -312,6 +324,7 @@ static int cpu_pmu_device_probe(struct platform_device *pdev) cpu_pmu = pmu; cpu_pmu->plat_device = pdev; + cpu_pmu->percpu_irq = platform_get_irq(pdev, 0); if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) { init_fn = of_id->data; diff --git a/kernel/events/core.c b/kernel/events/core.c index 34f41e7d492c4..51d742c84bb4a 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3626,7 +3626,10 @@ static int perf_release(struct inode *inode, struct file *file) if ((event->state == PERF_EVENT_STATE_OFF) && event->attr.constraint_duplicate) event->state = PERF_EVENT_STATE_ACTIVE; + + get_online_cpus(); put_event(file->private_data); + put_online_cpus(); return 0; } From 951fa4a0ef8e68fb99d7038d89e935fd8b794911 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 1 Feb 2017 11:48:58 +0000 Subject: [PATCH 007/508] BACKPORT: arm64: Add CNTVCT_EL0 trap handler Since people seem to make a point in breaking the userspace visible counter, we have no choice but to trap the access. Add the required handler. Acked-by: Thomas Gleixner Acked-by: Mark Rutland Signed-off-by: Marc Zyngier (cherry picked from commit 6126ce0588eb5a0752d5c8b5796a7fca324fd887) Change-Id: I0705f47c85a78040df38df18f51a4a22500b904d Signed-off-by: Neeraj Upadhyay --- arch/arm64/include/asm/esr.h | 37 ++++++++++++++++++++++++++++++++++++ arch/arm64/kernel/entry.S | 12 +++++++++++- arch/arm64/kernel/traps.c | 19 ++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index 7cff572082d0e..311eacfd42243 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -134,6 +134,43 @@ #define ESR_ELx_COND_MASK (UL(0xF) << ESR_ELx_COND_SHIFT) #define ESR_ELx_WFx_ISS_WFE (UL(1) << 0) +/* ISS field definitions for System instruction traps */ +#define ESR_ELx_SYS64_ISS_RES0_SHIFT 22 +#define ESR_ELx_SYS64_ISS_RES0_MASK (UL(0x7) << ESR_ELx_SYS64_ISS_RES0_SHIFT) +#define ESR_ELx_SYS64_ISS_DIR_MASK 0x1 +#define ESR_ELx_SYS64_ISS_DIR_READ 0x1 +#define ESR_ELx_SYS64_ISS_DIR_WRITE 0x0 + +#define ESR_ELx_SYS64_ISS_RT_SHIFT 5 +#define ESR_ELx_SYS64_ISS_RT_MASK (UL(0x1f) << ESR_ELx_SYS64_ISS_RT_SHIFT) +#define ESR_ELx_SYS64_ISS_CRM_SHIFT 1 +#define ESR_ELx_SYS64_ISS_CRM_MASK (UL(0xf) << ESR_ELx_SYS64_ISS_CRM_SHIFT) +#define ESR_ELx_SYS64_ISS_CRN_SHIFT 10 +#define ESR_ELx_SYS64_ISS_CRN_MASK (UL(0xf) << ESR_ELx_SYS64_ISS_CRN_SHIFT) +#define ESR_ELx_SYS64_ISS_OP1_SHIFT 14 +#define ESR_ELx_SYS64_ISS_OP1_MASK (UL(0x7) << ESR_ELx_SYS64_ISS_OP1_SHIFT) +#define ESR_ELx_SYS64_ISS_OP2_SHIFT 17 +#define ESR_ELx_SYS64_ISS_OP2_MASK (UL(0x7) << ESR_ELx_SYS64_ISS_OP2_SHIFT) +#define ESR_ELx_SYS64_ISS_OP0_SHIFT 20 +#define ESR_ELx_SYS64_ISS_OP0_MASK (UL(0x3) << ESR_ELx_SYS64_ISS_OP0_SHIFT) +#define ESR_ELx_SYS64_ISS_SYS_MASK (ESR_ELx_SYS64_ISS_OP0_MASK | \ + ESR_ELx_SYS64_ISS_OP1_MASK | \ + ESR_ELx_SYS64_ISS_OP2_MASK | \ + ESR_ELx_SYS64_ISS_CRN_MASK | \ + ESR_ELx_SYS64_ISS_CRM_MASK) +#define ESR_ELx_SYS64_ISS_SYS_VAL(op0, op1, op2, crn, crm) \ + (((op0) << ESR_ELx_SYS64_ISS_OP0_SHIFT) | \ + ((op1) << ESR_ELx_SYS64_ISS_OP1_SHIFT) | \ + ((op2) << ESR_ELx_SYS64_ISS_OP2_SHIFT) | \ + ((crn) << ESR_ELx_SYS64_ISS_CRN_SHIFT) | \ + ((crm) << ESR_ELx_SYS64_ISS_CRM_SHIFT)) + +#define ESR_ELx_SYS64_ISS_SYS_OP_MASK (ESR_ELx_SYS64_ISS_SYS_MASK | \ + ESR_ELx_SYS64_ISS_DIR_MASK) + +#define ESR_ELx_SYS64_ISS_SYS_CNTVCT (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \ + ESR_ELx_SYS64_ISS_DIR_READ) + #ifndef __ASSEMBLY__ #include diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 9adad63e4bf89..4c58ac76bc8c8 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -484,7 +484,7 @@ el0_sync: cmp x24, #ESR_ELx_EC_FP_EXC64 // FP/ASIMD exception b.eq el0_fpsimd_exc cmp x24, #ESR_ELx_EC_SYS64 // configurable trap - b.eq el0_undef + b.eq el0_sys cmp x24, #ESR_ELx_EC_SP_ALIGN // stack alignment exception b.eq el0_sp_pc cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception @@ -621,6 +621,16 @@ el0_undef: mov x0, sp bl do_undefinstr b ret_to_user +el0_sys: + /* + * System instructions, for trapped cache maintenance instructions + */ + enable_dbg_and_irq + ct_user_exit + mov x0, x25 + mov x1, sp + bl do_sysinstr + b ret_to_user el0_dbg: /* * Debug exception handling diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index bef6100f5c55d..4e983fa2e8fa2 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -399,6 +399,25 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) arm64_notify_die("Oops - undefined instruction", regs, &info, 0); } +static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) +{ + int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; + + if (rt != 31) + regs->regs[rt] = arch_counter_get_cntvct(); + regs->pc += 4; +} + +asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs) +{ + if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTVCT) { + cntvct_read_handler(esr, regs); + return; + } + + do_undefinstr(regs); +} + long compat_arm_syscall(struct pt_regs *regs); asmlinkage long do_ni_syscall(struct pt_regs *regs) From e5b705d283670bc0ae589e42e6bf8eedb102e221 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 24 Apr 2017 09:04:03 +0100 Subject: [PATCH 008/508] BACKPORT: arm64: Add CNTFRQ_EL0 trap handler We now trap accesses to CNTVCT_EL0 when the counter is broken enough to require the kernel to mediate the access. But it turns out that some existing userspace (such as OpenMPI) do probe for the counter frequency, leading to an UNDEF exception as CNTVCT_EL0 and CNTFRQ_EL0 share the same control bit. The fix is to handle the exception the same way we do for CNTVCT_EL0. Fixes: a86bd139f2ae ("arm64: arch_timer: Enable CNTVCT_EL0 trap if workaround is enabled") Reported-by: Hanjun Guo Tested-by: Hanjun Guo Reviewed-by: Hanjun Guo Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas (cherry picked from commit 9842119a238bfb92cbab63258dabb54f0e7b111b) Change-Id: I1bde5dc8f2fbdc94f66bc6606b88ad1817788080 Signed-off-by: Neeraj Upadhyay --- arch/arm64/include/asm/esr.h | 3 +++ arch/arm64/kernel/traps.c | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index 311eacfd42243..f1d9b6261f554 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -171,6 +171,9 @@ #define ESR_ELx_SYS64_ISS_SYS_CNTVCT (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \ ESR_ELx_SYS64_ISS_DIR_READ) +#define ESR_ELx_SYS64_ISS_SYS_CNTFRQ (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 0, 14, 0) | \ + ESR_ELx_SYS64_ISS_DIR_READ) + #ifndef __ASSEMBLY__ #include diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 4e983fa2e8fa2..fe4f786242ded 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -408,11 +408,23 @@ static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) regs->pc += 4; } +static void cntfrq_read_handler(unsigned int esr, struct pt_regs *regs) +{ + int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; + + if (rt != 31) + regs->regs[rt] = read_sysreg(cntfrq_el0); + regs->pc += 4; +} + asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs) { if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTVCT) { cntvct_read_handler(esr, regs); return; + } else if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTFRQ) { + cntfrq_read_handler(esr, regs); + return; } do_undefinstr(regs); From 6813e80342de2f10b4bbbc407992726c09ca8387 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Wed, 4 Oct 2017 09:31:34 -0700 Subject: [PATCH 009/508] arm64: issue isb when trapping CNTVCT_EL0 access Change-Id: I6005a6e944494257bfc2243fde2f7a09c3fd76c6 Signed-off-by: Neeraj Upadhyay --- arch/arm64/kernel/traps.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index fe4f786242ded..b42991af2e289 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -403,6 +404,7 @@ static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) { int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; + isb(); if (rt != 31) regs->regs[rt] = arch_counter_get_cntvct(); regs->pc += 4; From 905d0bbc5d92f0d34502951ea38f57d9495e2b14 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Tue, 19 Sep 2017 10:55:17 -0700 Subject: [PATCH 010/508] clocksource: arch_timer: make virtual counter access configurable Change-Id: Ibdb1fd768b748002b90bfc165612c12c8311f8a2 Signed-off-by: Neeraj Upadhyay --- drivers/clocksource/Kconfig | 8 ++++++++ drivers/clocksource/arm_arch_timer.c | 8 ++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 90420600e1eb1..2a6b2a8e15788 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -110,6 +110,14 @@ config ARM_ARCH_TIMER_EVTSTREAM This must be disabled for hardware validation purposes to detect any hardware anomalies of missing events. +config ARM_ARCH_TIMER_VCT_ACCESS + bool "Support for ARM architected timer virtual counter access in userspace" + default !ARM64 + depends on ARM_ARCH_TIMER + help + This option enables support for reading the ARM architected timer's + virtual counter in userspace. + config ARM_GLOBAL_TIMER bool select CLKSRC_OF if OF diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 0f69d44258c8b..891b07e4ac953 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -340,8 +340,12 @@ static void arch_counter_set_user_access(void) | ARCH_TIMER_VIRT_EVT_EN); /* Enable user access to the virtual and physical counters */ - cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN | ARCH_TIMER_USR_PCT_ACCESS_EN - | ARCH_TIMER_USR_VT_ACCESS_EN; + cntkctl |= ARCH_TIMER_USR_PCT_ACCESS_EN | ARCH_TIMER_USR_VT_ACCESS_EN; + + if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_VCT_ACCESS)) + cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; + else + cntkctl &= ~ARCH_TIMER_USR_VCT_ACCESS_EN; arch_timer_set_cntkctl(cntkctl); } From 4a0b6deeafa43c0b024c02fdfe7daa51bcaf3c56 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Fri, 19 Jan 2018 02:32:17 +0530 Subject: [PATCH 011/508] msm:ipa: Return mux id only for valid interface Currently value of MAX_NUM_OF_MUX_CHANNEL is 10 but number of valid interfaces is 8. So empty interface is also getting mux id. Return mux id only for valid interfaces. Change-Id: I7852df0aa0ccee781c1bf6857a4183b99194f3ee Acked-by: Pooja Kumari Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c | 4 ++-- drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c index eeadac12d203f..3c965ae10f51c 100644 --- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -758,7 +758,7 @@ static int find_vchannel_name_index(const char *vchannel_name) { int i; - for (i = 0; i < MAX_NUM_OF_MUX_CHANNEL; i++) { + for (i = 0; i < rmnet_index; i++) { if (0 == strcmp(mux_channel[i].vchannel_name, vchannel_name)) return i; } diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index c4fcd332f4bd2..1a5bea9a3c17b 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -783,7 +783,7 @@ static int find_vchannel_name_index(const char *vchannel_name) { int i; - for (i = 0; i < MAX_NUM_OF_MUX_CHANNEL; i++) { + for (i = 0; i < rmnet_ipa3_ctx->rmnet_index; i++) { if (0 == strcmp(rmnet_ipa3_ctx->mux_channel[i].vchannel_name, vchannel_name)) return i; From 6549e80ee8d5311ef7cbbf40c3438832ccbbe083 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Tue, 23 Jan 2018 13:29:44 +0530 Subject: [PATCH 012/508] wlan: Disable aggregation in BTC SCO if gNumBuffBTCSco is 1 Aggregation buff size of 1 is not handled by firmware and thus limit the gNumBuffBTCSco values to greater than 1 and consider 1 as aggregation disabled. Change-Id: I48218314dce4bac908930f289e080fad3cfa1a39 CRs-Fixed: 2177897 --- CORE/HDD/inc/wlan_hdd_cfg.h | 7 +++++-- CORE/HDD/src/wlan_hdd_cfg.c | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index e14d5e0ddb161..049df4e84d4b1 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -3160,15 +3160,18 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ /* * gNumBuffBTCSco is used to set block ack buffer size for - * aggregation during SCO. If this is set to 0, aggregation + * aggregation during SCO. If this is set to 0 or 1, aggregation * during SCO feature is disabled. To enable aggregation - * during SCO, gNumBuffBTCSco should be set to non zero value. + * during SCO, gNumBuffBTCSco should be set to be greater than 1. */ +#define CFG_NUM_BUFF_BTC_SCO_INVALID 1 + #define CFG_NUM_BUFF_BTC_SCO_NAME "gNumBuffBTCSco" #define CFG_NUM_BUFF_BTC_SCO_MIN (0) #define CFG_NUM_BUFF_BTC_SCO_MAX (10) #define CFG_NUM_BUFF_BTC_SCO_DEFAULT (0) + /* Value for ENABLE_POWERSAVE_OFFLOAD*/ #define CFG_ENABLE_POWERSAVE_OFFLOAD_NAME "gEnablePowerSaveOffload" #define CFG_ENABLE_POWERSAVE_OFFLOAD_MIN (1) diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index 6fe904bd1bae6..0292ba099e5b5 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -6676,6 +6676,9 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) true) != VOS_STATUS_SUCCESS) vos_mem_set(smeConfig->csrConfig.agg_btc_sco_oui, VENDOR_AP_OUI_SIZE, 0); + /* Disable aggrigation if value is 0 or 1 (CFG_NUM_BUFF_BTC_SCO_INVALID) */ + if (pHddCtx->cfg_ini->num_buff_aggr_btc_sco == CFG_NUM_BUFF_BTC_SCO_INVALID) + pHddCtx->cfg_ini->num_buff_aggr_btc_sco = CFG_NUM_BUFF_BTC_SCO_MIN; smeConfig->csrConfig.num_ba_buff_btc_sco = pHddCtx->cfg_ini->num_buff_aggr_btc_sco; smeConfig->csrConfig.num_ba_buff = From 0632f364dbca394c609a8746cab05054b81bd198 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Tue, 20 Dec 2016 17:08:10 +0800 Subject: [PATCH 013/508] ASoC: msm: qdspv2: add spin lock to protect ac ac could get freed during the execution of q6asm_callback. And kernel panic happens. Add spinlock to protect ac to avoid kernel panic. Change-Id: Ie49c8a3979231552ba7d5f207aab0d95ffdc2a72 Signed-off-by: Meng Wang --- sound/soc/msm/qdsp6v2/q6asm.c | 144 ++++++++++++++++++++++++++-------- 1 file changed, 113 insertions(+), 31 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 83ae40c8ca27a..5abc1ffbe1f33 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * Author: Brian Swetland * * This software is licensed under the terms of the GNU General Public @@ -60,8 +60,13 @@ struct asm_mmap { }; static struct asm_mmap this_mmap; + +struct audio_session { + struct audio_client *ac; + spinlock_t session_lock; +}; /* session id: 0 reserved */ -static struct audio_client *session[SESSION_MAX+1]; +static struct audio_session session[SESSION_MAX + 1]; struct asm_no_wait_node { struct list_head list; @@ -399,9 +404,10 @@ int q6asm_mmap_apr_dereg(void) static int q6asm_session_alloc(struct audio_client *ac) { int n; + for (n = 1; n <= SESSION_MAX; n++) { - if (!session[n]) { - session[n] = ac; + if (!session[n].ac) { + session[n].ac = ac; return n; } } @@ -409,28 +415,41 @@ static int q6asm_session_alloc(struct audio_client *ac) return -ENOMEM; } -static bool q6asm_is_valid_audio_client(struct audio_client *ac) +static unsigned int q6asm_get_session_id_from_audio_client( + struct audio_client *ac) { - int n; + unsigned int n; + for (n = 1; n <= SESSION_MAX; n++) { - if (session[n] == ac) - return 1; + if (session[n].ac == ac) + return n; } return 0; } +static bool q6asm_is_valid_audio_client(struct audio_client *ac) +{ + return q6asm_get_session_id_from_audio_client(ac) ? 1 : 0; +} + static void q6asm_session_free(struct audio_client *ac) { struct list_head *ptr, *next; struct asm_no_wait_node *node; unsigned long flags; + unsigned long session_flags; + int session_id; pr_debug("%s: sessionid[%d]\n", __func__, ac->session); + session_id = ac->session; rtac_remove_popp_from_adm_devices(ac->session); - session[ac->session] = 0; + spin_lock_irqsave(&(session[session_id].session_lock), session_flags); + session[ac->session].ac = NULL; ac->session = 0; ac->perf_mode = LEGACY_PCM_MODE; ac->fptr_cache_ops = NULL; + ac->cb = NULL; + ac->priv = NULL; spin_lock_irqsave(&ac->no_wait_que_spinlock, flags); list_for_each_safe(ptr, next, &ac->no_wait_que) { @@ -439,6 +458,10 @@ static void q6asm_session_free(struct audio_client *ac) kfree(node); } spin_unlock_irqrestore(&ac->no_wait_que_spinlock, flags); + + kfree(ac); + spin_unlock_irqrestore(&(session[session_id].session_lock), + session_flags); return; } @@ -997,8 +1020,6 @@ void q6asm_audio_client_free(struct audio_client *ac) pr_debug("%s: APR De-Register\n", __func__); /*done:*/ - kfree(ac); - ac = NULL; mutex_unlock(&session_lock); return; @@ -1067,6 +1088,7 @@ struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv) if (n <= 0) { pr_err("%s: ASM Session alloc fail n=%d\n", __func__, n); mutex_unlock(&session_lock); + kfree(ac); goto fail_session; } ac->session = n; @@ -1146,7 +1168,6 @@ struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv) fail_apr1: q6asm_session_free(ac); fail_session: - kfree(ac); return NULL; } @@ -1161,11 +1182,11 @@ struct audio_client *q6asm_get_audio_client(int session_id) goto err; } - if (!session[session_id]) { + if (!(session[session_id].ac)) { pr_err("%s: session not active: %d\n", __func__, session_id); goto err; } - return session[session_id]; + return session[session_id].ac; err: return NULL; } @@ -1370,6 +1391,7 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) uint32_t i = IN; uint32_t *payload; unsigned long dsp_flags; + unsigned long flags; struct asm_buffer_node *buf_node = NULL; struct list_head *ptr, *next; @@ -1418,9 +1440,16 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) return 0; } sid = (data->token >> 8) & 0x0F; + if ((sid > 0 && sid <= SESSION_MAX)) + spin_lock_irqsave(&(session[sid].session_lock), flags); + ac = q6asm_get_audio_client(sid); if (!ac) { pr_debug("%s: session[%d] already freed\n", __func__, sid); + if ((sid > 0 && + sid <= SESSION_MAX)) + spin_unlock_irqrestore( + &(session[sid].session_lock), flags); return 0; } @@ -1470,6 +1499,10 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) __func__, payload[0]); break; } + if ((sid > 0 && + sid <= SESSION_MAX)) + spin_unlock_irqrestore( + &(session[sid].session_lock), flags); return 0; } @@ -1505,6 +1538,10 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) if (ac->cb) ac->cb(data->opcode, data->token, data->payload, ac->priv); + if ((sid > 0 && sid <= SESSION_MAX)) + spin_unlock_irqrestore( + &(session[sid].session_lock), flags); + return 0; } @@ -1583,7 +1620,8 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) uint32_t *payload; uint32_t wakeup_flag = 1; int32_t ret = 0; - + unsigned long flags; + int session_id; if (ac == NULL) { pr_err("%s: ac NULL\n", __func__); @@ -1593,15 +1631,21 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) pr_err("%s: data NULL\n", __func__); return -EINVAL; } - if (!q6asm_is_valid_audio_client(ac)) { - pr_err("%s: audio client pointer is invalid, ac = %pK\n", - __func__, ac); + + session_id = q6asm_get_session_id_from_audio_client(ac); + if (session_id <= 0) { + pr_err("%s: Session ID is invalid, session = %d\n", __func__, + session_id); return -EINVAL; } - if (ac->session <= 0 || ac->session > 8) { - pr_err("%s: Session ID is invalid, session = %d\n", __func__, - ac->session); + spin_lock_irqsave(&(session[session_id].session_lock), flags); + + if (!q6asm_is_valid_audio_client(ac)) { + pr_err("%s: audio client pointer is invalid, ac = %pK\n", + __func__, ac); + spin_unlock_irqrestore( + &(session[session_id].session_lock), flags); return -EINVAL; } @@ -1616,7 +1660,6 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) } if (data->opcode == RESET_EVENTS) { - mutex_lock(&ac->cmd_lock); atomic_set(&ac->reset, 1); if (ac->apr == NULL) ac->apr = ac->apr2; @@ -1633,7 +1676,8 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) atomic_set(&ac->cmd_state_pp, 0); wake_up(&ac->time_wait); wake_up(&ac->cmd_wait); - mutex_unlock(&ac->cmd_lock); + spin_unlock_irqrestore( + &(session[session_id].session_lock), flags); return 0; } @@ -1644,9 +1688,16 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) data->dest_port); if ((data->opcode != ASM_DATA_EVENT_RENDERED_EOS) && (data->opcode != ASM_DATA_EVENT_EOS) && - (data->opcode != ASM_SESSION_EVENT_RX_UNDERFLOW)) + (data->opcode != ASM_SESSION_EVENT_RX_UNDERFLOW)) { + if (payload == NULL) { + pr_err("%s: payload is null\n", __func__); + spin_unlock_irqrestore( + &(session[session_id].session_lock), flags); + return -EINVAL; + } dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x] opcode 0x%x\n", __func__, payload[0], payload[1], data->opcode); + } if (data->opcode == APR_BASIC_RSP_RESULT) { token = data->token; switch (payload[0]) { @@ -1668,6 +1719,8 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) ret = q6asm_is_valid_session(data, priv); if (ret != 0) { pr_err("%s: session invalid %d\n", __func__, ret); + spin_unlock_irqrestore( + &(session[session_id].session_lock), flags); return ret; } case ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2: @@ -1702,6 +1755,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) payload[1]); wake_up(&ac->cmd_wait); } + spin_unlock_irqrestore( + &(session[session_id].session_lock), + flags); return 0; } if (payload[0] == ASM_STREAM_CMD_SET_PP_PARAMS_V2) { @@ -1731,6 +1787,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) atomic_set(&ac->mem_state, payload[1]); wake_up(&ac->mem_wait); } + spin_unlock_irqrestore( + &(session[session_id].session_lock), + flags); return 0; } if (atomic_read(&ac->mem_state) && wakeup_flag) { @@ -1767,6 +1826,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) __func__, payload[0]); break; } + + spin_unlock_irqrestore( + &(session[session_id].session_lock), flags); return 0; } @@ -1780,6 +1842,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) if (port->buf == NULL) { pr_err("%s: Unexpected Write Done\n", __func__); + spin_unlock_irqrestore( + &(session[session_id].session_lock), + flags); return -EINVAL; } spin_lock_irqsave(&port->dsp_lock, dsp_flags); @@ -1793,6 +1858,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) __func__, payload[0], payload[1]); spin_unlock_irqrestore(&port->dsp_lock, dsp_flags); + spin_unlock_irqrestore( + &(session[session_id].session_lock), + flags); return -EINVAL; } token = data->token; @@ -1864,6 +1932,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) if (ac->io_mode & SYNC_IO_MODE) { if (port->buf == NULL) { pr_err("%s: Unexpected Write Done\n", __func__); + spin_unlock_irqrestore( + &(session[session_id].session_lock), + flags); return -EINVAL; } spin_lock_irqsave(&port->dsp_lock, dsp_flags); @@ -1950,7 +2021,8 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) if (ac->cb) ac->cb(data->opcode, data->token, data->payload, ac->priv); - + spin_unlock_irqrestore( + &(session[session_id].session_lock), flags); return 0; } @@ -2126,11 +2198,16 @@ int q6asm_is_dsp_buf_avail(int dir, struct audio_client *ac) static void __q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg, uint32_t stream_id) { + unsigned long flags; + dev_vdbg(ac->dev, "%s: pkt_size=%d cmd_flg=%d session=%d stream_id=%d\n", __func__, pkt_size, cmd_flg, ac->session, stream_id); mutex_lock(&ac->cmd_lock); + spin_lock_irqsave(&(session[ac->session].session_lock), flags); if (ac->apr == NULL) { pr_err("%s: AC APR handle NULL", __func__); + spin_unlock_irqrestore( + &(session[ac->session].session_lock), flags); mutex_unlock(&ac->cmd_lock); return; } @@ -2148,6 +2225,8 @@ static void __q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, hdr->token = ac->session; } hdr->pkt_size = pkt_size; + spin_unlock_irqrestore( + &(session[ac->session].session_lock), flags); mutex_unlock(&ac->cmd_lock); return; } @@ -7553,7 +7632,7 @@ int q6asm_get_apr_service_id(int session_id) return -EINVAL; } - return ((struct apr_svc *)session[session_id]->apr)->id; + return ((struct apr_svc *)(session[session_id].ac)->apr)->id; } int q6asm_get_asm_topology(int session_id) @@ -7564,12 +7643,12 @@ int q6asm_get_asm_topology(int session_id) pr_err("%s: invalid session_id = %d\n", __func__, session_id); goto done; } - if (session[session_id] == NULL) { + if (session[session_id].ac == NULL) { pr_err("%s: session not created for session id = %d\n", __func__, session_id); goto done; } - topology = session[session_id]->topology; + topology = (session[session_id].ac)->topology; done: return topology; } @@ -7582,12 +7661,12 @@ int q6asm_get_asm_app_type(int session_id) pr_err("%s: invalid session_id = %d\n", __func__, session_id); goto done; } - if (session[session_id] == NULL) { + if (session[session_id].ac == NULL) { pr_err("%s: session not created for session id = %d\n", __func__, session_id); goto done; } - app_type = session[session_id]->app_type; + app_type = (session[session_id].ac)->app_type; done: return app_type; } @@ -7944,7 +8023,10 @@ static int __init q6asm_init(void) int lcnt, ret; pr_debug("%s:\n", __func__); - memset(session, 0, sizeof(session)); + memset(session, 0, sizeof(struct audio_session) * + (SESSION_MAX + 1)); + for (lcnt = 0; lcnt <= SESSION_MAX; lcnt++) + spin_lock_init(&(session[lcnt].session_lock)); set_custom_topology = 1; /*setup common client used for cal mem map */ From c8621cfadd362450d9665ac28de249c190b29fcc Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Sirasanagandla Date: Thu, 23 Nov 2017 14:20:01 +0530 Subject: [PATCH 014/508] msm: wlan: Update regulatory database Remove 160 MHz band-width support for VN as per master sheet. CRs-Fixed: 2145374 Change-Id: Id0cda10bf3343bccda5eea08ae5369754bb40edb Signed-off-by: Rajeev Kumar Sirasanagandla --- net/wireless/db.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/wireless/db.txt b/net/wireless/db.txt index e423dd9e931cb..9675fbd3a17d1 100644 --- a/net/wireless/db.txt +++ b/net/wireless/db.txt @@ -1438,9 +1438,9 @@ country VI: DFS-FCC country VN: DFS-FCC (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (24), AUTO-BW - (5250 - 5330 @ 80), (24), DFS, AUTO-BW - (5490 - 5730 @ 160), (24), DFS + (5170 - 5250 @ 80), (24) + (5250 - 5330 @ 80), (24), DFS + (5490 - 5730 @ 80), (24), DFS (5735 - 5835 @ 80), (30) country VU: DFS-FCC From 4c5be6d392144ae985950ba9cd6922027ab188d6 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Tue, 23 Jan 2018 18:44:22 +0530 Subject: [PATCH 015/508] wlan: Free FW caps object after unregistering interrupts Presently, variable holding FW caps is freed prior to unregistering interrupts. But as DXE RX ISR access this variable, there is a possibility of accessing the variable after it's freed. Free variable holding FW caps after interrupts are deregistered. Change-Id: Ic25202063eb1f425ce57d01328fc9766dd8b7f8a CRs-Fixed: 2177131 --- CORE/WDI/CP/src/wlan_qct_wdi.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c index d3db18d404981..3a57b30bc0745 100644 --- a/CORE/WDI/CP/src/wlan_qct_wdi.c +++ b/CORE/WDI/CP/src/wlan_qct_wdi.c @@ -2555,12 +2555,6 @@ WDI_Stop /*We have completed cleaning unlock now*/ wpalMutexRelease(&pWDICtx->wptMutex); - /* Free the global variables */ - wpalMemoryFree(gpHostWlanFeatCaps); - wpalMemoryFree(gpFwWlanFeatCaps); - gpHostWlanFeatCaps = NULL; - gpFwWlanFeatCaps = NULL; - /*------------------------------------------------------------------------ Fill in Event data and post to the Main FSM ------------------------------------------------------------------------*/ @@ -8544,7 +8538,7 @@ WDI_ProcessStopReq wpt_uint8* pSendBuffer = NULL; wpt_uint16 usDataOffset = 0; wpt_uint16 usSendSize = 0; - wpt_status status; + wpt_status status = WDI_STATUS_E_FAILURE; tHalMacStopReqMsg halStopReq; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ @@ -8558,7 +8552,7 @@ WDI_ProcessStopReq WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, "%s: Invalid parameters", __func__); WDI_ASSERT(0); - goto failRequest; + goto free_wlan_feat_caps; } /*----------------------------------------------------------------------- @@ -8573,7 +8567,7 @@ WDI_ProcessStopReq "Unable to get send buffer in stop req %pK %pK %pK", pEventData, pwdiStopParams, wdiStopRspCb); WDI_ASSERT(0); - goto failRequest; + goto free_wlan_feat_caps; } /*----------------------------------------------------------------------- @@ -8633,17 +8627,22 @@ WDI_ProcessStopReq /*------------------------------------------------------------------------- Send Stop Request to HAL -------------------------------------------------------------------------*/ - return WDI_SendMsg( pWDICtx, pSendBuffer, usSendSize, + status = WDI_SendMsg( pWDICtx, pSendBuffer, usSendSize, wdiStopRspCb, pEventData->pUserData, WDI_STOP_RESP); - + goto free_wlan_feat_caps; fail: // Release the message buffer so we don't leak wpalMemoryFree(pSendBuffer); -failRequest: - //WDA should have failure check to avoid the memory leak - return WDI_STATUS_E_FAILURE; +free_wlan_feat_caps: + /* Free global wlan feature caps variables */ + wpalMemoryFree(gpHostWlanFeatCaps); + wpalMemoryFree(gpFwWlanFeatCaps); + gpHostWlanFeatCaps = NULL; + gpFwWlanFeatCaps = NULL; + //WDA should have failure check to avoid the memory leak + return status; }/*WDI_ProcessStopReq*/ /** @@ -17031,6 +17030,7 @@ WDI_ProcessStopRsp /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ wdiStopRspCb = (WDI_StopRspCb)pWDICtx->pfncRspCB; + /*------------------------------------------------------------------------- Sanity check -------------------------------------------------------------------------*/ From 6ad23f9bc084ed4464589ec89953cfd61540ce9c Mon Sep 17 00:00:00 2001 From: Rashi Bindra Date: Wed, 3 Jan 2018 16:16:38 +0530 Subject: [PATCH 016/508] ARM: dts: msm: Add support for FHD+ Video mode panel on msm8953 Add changes to add panel init sequence, on/off commands and other panel properties for FHD+ Video Mode Panel. Change-Id: Icb72bc4c9300a753de741155cb292d7b5a5f9325 Signed-off-by: Rashi Bindra --- ...si-panel-lgd-incell-sw49106-fhd-video.dtsi | 115 ++++++++++++++++++ arch/arm/boot/dts/qcom/msm8953-cdp.dtsi | 10 +- .../boot/dts/qcom/msm8953-mdss-panels.dtsi | 13 +- arch/arm/boot/dts/qcom/msm8953-mtp.dtsi | 10 +- 4 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 arch/arm/boot/dts/qcom/dsi-panel-lgd-incell-sw49106-fhd-video.dtsi diff --git a/arch/arm/boot/dts/qcom/dsi-panel-lgd-incell-sw49106-fhd-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-lgd-incell-sw49106-fhd-video.dtsi new file mode 100644 index 0000000000000..8db5317f2106e --- /dev/null +++ b/arch/arm/boot/dts/qcom/dsi-panel-lgd-incell-sw49106-fhd-video.dtsi @@ -0,0 +1,115 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_lgd_incell_sw49106_fhd_video: + qcom,mdss_dsi_lgd_incell_sw49106_fhd_video { + qcom,mdss-dsi-panel-name = + "lgd incell sw49106 fhd video"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <2160>; + qcom,mdss-dsi-h-front-porch = <8>; + qcom,mdss-dsi-h-back-porch = <8>; + qcom,mdss-dsi-h-pulse-width = <4>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <92>; + qcom,mdss-dsi-v-front-porch = <170>; + qcom,mdss-dsi-v-pulse-width = <1>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-h-sync-pulse = <0>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-panel-timings = [F8 3C 28 00 6E 72 2E + 40 30 03 04 00]; + qcom,mdss-dsi-t-clk-post = <0x02>; + qcom,mdss-dsi-t-clk-pre = <0x2D>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-on-command = [05 01 00 00 0B 00 02 35 00 + 15 01 00 00 00 00 02 36 00 + 15 01 00 00 00 00 02 51 FF + 15 01 00 00 00 00 02 53 24 + 15 01 00 00 00 00 02 55 80 + 39 01 00 00 00 00 02 B0 AC + 39 01 00 00 00 00 06 B1 46 00 80 14 85 + 39 01 00 00 00 00 08 B3 05 08 14 00 1C 00 02 + 39 01 00 00 00 00 10 B4 83 08 00 04 04 04 04 00 + 00 00 00 00 00 00 00 + 39 01 00 00 00 00 13 B5 03 1E 0B 02 29 00 00 00 + 00 04 00 24 00 10 10 10 10 00 + 39 01 00 00 00 00 0A B6 00 72 39 13 08 67 00 60 46 + 39 01 00 00 00 00 05 B7 00 50 37 04 + 39 01 00 00 00 00 0C B8 70 38 14 ED 08 04 00 01 + 0A A0 00 + 39 01 00 00 00 00 06 C0 8A 8F 18 C1 12 + 39 01 00 00 00 00 07 C1 01 00 30 C2 C7 0F + 39 01 00 00 00 00 03 C2 2A 00 + 39 01 00 00 00 00 07 C3 05 0E 0E 50 88 09 + 39 01 00 00 00 00 04 C4 A2 E8 F4 + 39 01 00 00 00 00 05 C5 C2 2A 4E 08 + 39 01 00 00 00 00 03 C6 15 01 + 39 01 00 00 00 00 07 CA 00 00 03 84 55 F5 + 39 01 00 00 00 00 03 CB 3F A0 + 39 01 00 00 00 00 09 CC F0 03 10 55 11 FC 34 34 + 39 01 00 00 00 00 07 CD 11 50 50 90 00 F3 + 39 01 00 00 00 00 07 CE A0 28 28 34 00 AB + 39 01 00 00 00 00 10 D0 10 1B 22 2A 35 42 4A 53 4D + 44 34 23 10 03 81 + 39 01 00 00 00 00 10 D1 09 15 1C 25 31 3F 47 52 4F + 45 34 22 0E 01 83 + 39 01 00 00 00 00 10 D2 10 1B 22 29 34 41 49 52 4E + 44 34 23 10 03 81 + 39 01 00 00 00 00 10 D3 09 15 1C 24 30 3E 46 51 50 + 45 34 22 0E 01 83 + 39 01 00 00 00 00 10 D4 10 1B 22 2A 35 42 4A 53 4D + 44 34 23 10 03 81 + 39 01 00 00 00 00 10 D5 09 15 1C 25 31 3F 47 52 4F + 45 34 22 0E 01 83 + 39 01 00 00 00 00 0D E5 24 23 11 10 00 0A 08 06 04 + 11 0E 23 + 39 01 00 00 00 00 0D E6 24 23 11 10 01 0B 09 07 05 + 11 0E 23 + 39 01 00 00 00 00 07 E7 15 16 17 18 19 1A + 39 01 00 00 00 00 07 E8 1B 1C 1D 1E 1F 20 + 39 01 00 00 00 00 05 ED 00 01 53 0C + 39 01 00 00 00 00 03 F0 B2 00 + 39 01 00 00 00 00 05 F2 01 00 17 00 + 39 01 00 00 64 00 07 F3 00 50 90 C9 00 01 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 05 00 02 29 00]; + qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00 + 05 01 00 00 64 00 02 10 00]; + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 200>, <0 200>, <1 200>; + qcom,mdss-dsi-tx-eot-append; + qcom,mdss-dsi-post-init-delay = <1>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8953-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8953-cdp.dtsi index cadf277b61bae..01d462da5a9ea 100644 --- a/arch/arm/boot/dts/qcom/msm8953-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-cdp.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -216,6 +216,14 @@ qcom,mdss-dsi-pan-fps-update = "dfps_immediate_clk_mode"; }; +&dsi_lgd_incell_sw49106_fhd_video { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + qcom,mdss-dsi-min-refresh-rate = <48>; + qcom,mdss-dsi-max-refresh-rate = <60>; + qcom,mdss-dsi-pan-enable-dynamic-fps; + qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp"; +}; + &blsp1_uart0 { status = "ok"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/qcom/msm8953-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/msm8953-mdss-panels.dtsi index 4fa5cd19a17cf..aedcc94e27e1d 100644 --- a/arch/arm/boot/dts/qcom/msm8953-mdss-panels.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-mdss-panels.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -23,6 +23,7 @@ #include "dsi-panel-truly-wuxga-video.dtsi" #include "dsi-panel-lt8912-480p-video.dtsi" #include "dsi-panel-lt8912-1080p-video.dtsi" +#include "dsi-panel-lgd-incell-sw49106-fhd-video.dtsi" &soc { dsi_panel_pwr_supply: dsi_panel_pwr_supply { @@ -104,3 +105,13 @@ 24 1f 08 09 05 03 04 a0 24 1c 08 09 05 03 04 a0]; }; + +&dsi_lgd_incell_sw49106_fhd_video { + qcom,mdss-dsi-panel-timings-phy-v2 = [24 1F 08 09 05 03 04 a0 + 24 1F 08 09 05 03 04 a0 + 24 1F 08 09 05 03 04 a0 + 24 1F 08 09 05 03 04 a0 + 24 1B 08 09 05 03 04 a0]; + qcom,mdss-dsi-t-clk-post = <0x0d>; + qcom,mdss-dsi-t-clk-pre = <0x30>; +}; diff --git a/arch/arm/boot/dts/qcom/msm8953-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8953-mtp.dtsi index af1d61ae20b4f..d805dd67b87db 100644 --- a/arch/arm/boot/dts/qcom/msm8953-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-mtp.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -173,6 +173,14 @@ qcom,panel-roi-alignment = <2 2 4 2 1080 2>; }; +&dsi_lgd_incell_sw49106_fhd_video { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + qcom,mdss-dsi-min-refresh-rate = <48>; + qcom,mdss-dsi-max-refresh-rate = <60>; + qcom,mdss-dsi-pan-enable-dynamic-fps; + qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp"; +}; + &blsp1_uart0 { status = "ok"; pinctrl-names = "default"; From d5744a1ee24312c67e38c7b5c990c772803c7920 Mon Sep 17 00:00:00 2001 From: Neeraj Upadhyay Date: Fri, 5 Jan 2018 11:03:42 +0530 Subject: [PATCH 017/508] clocksource: arch_timer: Disable user access to the physical counter Disable user access to physical counter. This reverts commit 63cb2598d5ba ("clocksource: arch_timer: Enable user access to the physical counter"). This could potentially break the userspace applications using physical counters; but all those usages should move to using virtual counter, to get the timing information. Change-Id: I653816a93515507a400ff23dbaa4442bf614a79b Signed-off-by: Neeraj Upadhyay --- drivers/clocksource/arm_arch_timer.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 891b07e4ac953..ef939675c9ca5 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -334,13 +334,14 @@ static void arch_counter_set_user_access(void) { u32 cntkctl = arch_timer_get_cntkctl(); - /* Disable user access to the timers */ + /* Disable user access to the timers and the physical counter */ /* Also disable virtual event stream */ cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN - | ARCH_TIMER_VIRT_EVT_EN); + | ARCH_TIMER_VIRT_EVT_EN + | ARCH_TIMER_USR_PCT_ACCESS_EN); - /* Enable user access to the virtual and physical counters */ - cntkctl |= ARCH_TIMER_USR_PCT_ACCESS_EN | ARCH_TIMER_USR_VT_ACCESS_EN; + /* Enable user access to the virtual counter */ + cntkctl |= ARCH_TIMER_USR_VT_ACCESS_EN; if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_VCT_ACCESS)) cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; From 209a6836a0ba373738aa0d37f6237acbb693bfaf Mon Sep 17 00:00:00 2001 From: Saranya Chidura Date: Thu, 13 Apr 2017 11:16:07 +0530 Subject: [PATCH 018/508] defconfig: msm: add coresight config for perf on apq8053 Add the CORESIGHT CONFIG options for perf defconfig on APQ8053. Change-Id: I3f6192660e5c22d29c9536e4cfca95a494b05f28 Signed-off-by: Saranya Chidura --- arch/arm64/configs/apq8053_IoE-perf_defconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/configs/apq8053_IoE-perf_defconfig b/arch/arm64/configs/apq8053_IoE-perf_defconfig index cc1d1e38c7e21..ab2556f6703f0 100644 --- a/arch/arm64/configs/apq8053_IoE-perf_defconfig +++ b/arch/arm64/configs/apq8053_IoE-perf_defconfig @@ -552,6 +552,17 @@ CONFIG_PWM=y CONFIG_PWM_QPNP=y CONFIG_ARM_GIC_PANIC_HANDLER=y CONFIG_ARM_GIC_V3_ACL=y +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_EVENT=y +CONFIG_CORESIGHT_FUSE=y +CONFIG_CORESIGHT_CTI=y +CONFIG_CORESIGHT_CTI_SAVE_DISABLE=y +CONFIG_CORESIGHT_TMC=y +CONFIG_CORESIGHT_TPIU=y +CONFIG_CORESIGHT_FUNNEL=y +CONFIG_CORESIGHT_REPLICATOR=y +CONFIG_CORESIGHT_STM=y +CONFIG_CORESIGHT_HWEVENT=y CONFIG_SENSORS_SSC=y CONFIG_MSM_TZ_LOG=y CONFIG_EXT4_FS=y From d54215652429371a8850bf036f12648053b3517e Mon Sep 17 00:00:00 2001 From: "Padma, Santhosh Kumar" Date: Wed, 24 Jan 2018 19:57:40 +0530 Subject: [PATCH 019/508] wlan: Fix stack corruption in beacon table mode Currently driver sends beacon report for each channel recursively in beacon table mode. There is a chance that variables on stack can exceed allocated stack size which can lead to corruption of stack. Remove unnecessary variables which are not required for beacon table mode to fix this issue. Change-Id: I9aa35e7da916f5d4c6380862d292b44c254c9334 CRs-Fixed: 2178720 --- CORE/SME/src/rrm/sme_rrm.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/CORE/SME/src/rrm/sme_rrm.c b/CORE/SME/src/rrm/sme_rrm.c index af18b4f41ec93..102dc5f63dc83 100644 --- a/CORE/SME/src/rrm/sme_rrm.c +++ b/CORE/SME/src/rrm/sme_rrm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014, 2016,2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -710,12 +710,8 @@ static eHalStatus sme_RrmScanRequestCallback(tHalHandle halHandle, void *pContex --------------------------------------------------------------------------*/ eHalStatus sme_RrmIssueScanReq( tpAniSirGlobal pMac ) { - //Issue scan request. - tCsrScanRequest scanRequest; - v_U32_t scanId = 0; eHalStatus status = eHAL_STATUS_SUCCESS; tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; - tANI_U32 sessionId; tSirScanType scanType; if ((pSmeRrmContext->currentIndex) >= pSmeRrmContext->channelList.numOfChannels) @@ -729,6 +725,9 @@ eHalStatus sme_RrmIssueScanReq( tpAniSirGlobal pMac ) if ((eSIR_ACTIVE_SCAN == scanType) || (eSIR_PASSIVE_SCAN == scanType)) { + tCsrScanRequest scanRequest; + v_U32_t scanId = 0; + tANI_U32 sessionId; #if defined WLAN_VOWIFI_DEBUG smsLog( pMac, LOGE, "Issue scan request " ); #endif From 307d4895868236ac0a746f8f3450eb6f938d007d Mon Sep 17 00:00:00 2001 From: Nachiket Kukade Date: Tue, 23 Jan 2018 23:36:25 +0530 Subject: [PATCH 020/508] wlan: Add maximum bound check on WPA RSN IE length In set_ie after receiving DOT11F_EID_RSN, WPA RSN IE is copied from source without a check on the given IE length. A malicious IE length can cause buffer overflow. Apply the same logic from Id159d307e8f9c1de720d4553a7c29f23cbd28571 that was applied under DOT11F_EID_WPA. This adds maximum bound check on WPA RSN IE length. Change-Id: I04f980fe44328b1a3f6a6d4854228cc4c9f1a1c7 CRs-Fixed: 2177210 --- CORE/HDD/src/wlan_hdd_cfg80211.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index f4269e4673296..dd14f10b3febc 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -15753,6 +15753,12 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, } /* end of if (WLAN_HDD_IBSS == pAdapter->device_mode) */ break; case DOT11F_EID_RSN: + if (eLen > (MAX_WPA_RSN_IE_LEN - 2)) { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid WPA RSN IE length[%d], exceeds %d bytes", + __func__, eLen, MAX_WPA_RSN_IE_LEN - 2); + VOS_ASSERT(0); + return -EINVAL; + } hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2); memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN ); memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/); From 6d819813df7c8e3d2de409c4eeda07478828c156 Mon Sep 17 00:00:00 2001 From: Archana Sriram Date: Wed, 24 Jan 2018 13:20:26 +0530 Subject: [PATCH 021/508] ARM: dts: msm: Enable bus control for GPU on msm8909 Enabled bus control for GPU on msm8909 so that devfreq governor is used to vote on behalf of GPU through bw voting device gpubw-dev instead of GPU directly voting on msm-bus through grp3d device. Change-Id: I0a7dabdfd23f5a3122a270449ee1cc46f328847d Signed-off-by: Archana Sriram --- arch/arm/boot/dts/qcom/msm8909-gpu.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi index 9f4a397188dea..ba87d663a8d43 100644 --- a/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -74,6 +74,7 @@ /* Bus Scale Settings */ qcom,gpubw-dev = <&gpubw>; + qcom,bus-control; qcom,msm-bus,name = "grp3d"; qcom,msm-bus,num-cases = <4>; qcom,msm-bus,num-paths = <1>; From 25b51b764dede42f93a256bff6ea263ccd402fa3 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 6 Dec 2017 10:42:10 +0000 Subject: [PATCH 022/508] arm64: SW PAN: Point saved ttbr0 at the zero page when switching to init_mm update_saved_ttbr0 mandates that mm->pgd is not swapper, since swapper contains kernel mappings and should never be installed into ttbr0. However, this means that callers must avoid passing the init_mm to update_saved_ttbr0 which in turn can cause the saved ttbr0 value to be out-of-date in the context of the idle thread. For example, EFI runtime services may leave the saved ttbr0 pointing at the EFI page table, and kernel threads may end up with stale references to freed page tables. This patch changes update_saved_ttbr0 so that the init_mm points the saved ttbr0 value to the empty zero page, which always exists and never contains valid translations. EFI and switch can then call into update_saved_ttbr0 unconditionally. Change-Id: I664095969fbd4d0b546f30aa4c312769e708d6de Cc: Mark Rutland Cc: Ard Biesheuvel Cc: Vinayak Menon Cc: Fixes: 39bc88e5e38e9b21 ("arm64: Disable TTBR0_EL1 during normal kernel execution") Reviewed-by: Catalin Marinas Reviewed-by: Mark Rutland Reported-by: Vinayak Menon Signed-off-by: Will Deacon Git-commit: 0adbdfde8cfc9415aeed2a4955d2d17b3bd9bf13 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [vinmenon: changes in arch/arm64/include/asm/efi.h moved to arch/arm64/kernel/efi.c as the affected function is moved] Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/mmu_context.h | 22 +++++++++++++--------- arch/arm64/kernel/efi.c | 4 +--- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h index 0802f08919aaf..4cb8e290b3176 100644 --- a/arch/arm64/include/asm/mmu_context.h +++ b/arch/arm64/include/asm/mmu_context.h @@ -127,11 +127,17 @@ enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) static inline void update_saved_ttbr0(struct task_struct *tsk, struct mm_struct *mm) { - if (system_uses_ttbr0_pan()) { - BUG_ON(mm->pgd == swapper_pg_dir); - task_thread_info(tsk)->ttbr0 = - virt_to_phys(mm->pgd) | ASID(mm) << 48; - } + u64 ttbr; + + if (!system_uses_ttbr0_pan()) + return; + + if (mm == &init_mm) + ttbr = __pa_symbol(empty_zero_page); + else + ttbr = virt_to_phys(mm->pgd) | ASID(mm) << 48; + + task_thread_info(tsk)->ttbr0 = ttbr; } #else static inline void update_saved_ttbr0(struct task_struct *tsk, @@ -167,11 +173,9 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, * Update the saved TTBR0_EL1 of the scheduled-in task as the previous * value may have not been initialised yet (activate_mm caller) or the * ASID has changed since the last run (following the context switch - * of another thread of the same process). Avoid setting the reserved - * TTBR0_EL1 to swapper_pg_dir (init_mm; e.g. via idle_task_exit). + * of another thread of the same process). */ - if (next != &init_mm) - update_saved_ttbr0(tsk, next); + update_saved_ttbr0(tsk, next); } #define deactivate_mm(tsk,mm) do { } while (0) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 7d13642092d10..0e4f402578ee8 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -356,11 +356,9 @@ static void efi_set_pgd(struct mm_struct *mm) * Defer the switch to the current thread's TTBR0_EL1 * until uaccess_enable(). Restore the current * thread's saved ttbr0 corresponding to its active_mm - * (if different from init_mm). */ cpu_set_reserved_ttbr0(); - if (current->active_mm != &init_mm) - update_saved_ttbr0(current, current->active_mm); + update_saved_ttbr0(current, current->active_mm); } } } From 7a4a594dadd72082842dbb4970655dc5fdc0730b Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 6 Dec 2017 10:51:12 +0000 Subject: [PATCH 023/508] arm64: SW PAN: Update saved ttbr0 value on enter_lazy_tlb enter_lazy_tlb is called when a kernel thread rides on the back of another mm, due to a context switch or an explicit call to unuse_mm where a call to switch_mm is elided. In these cases, it's important to keep the saved ttbr value up to date with the active mm, otherwise we can end up with a stale value which points to a potentially freed page table. This patch implements enter_lazy_tlb for arm64, so that the saved ttbr0 is kept up-to-date with the active mm for kernel threads. Change-Id: I6e5c50542ff2645c46e8801685f7a43e6773c3d2 Cc: Mark Rutland Cc: Ard Biesheuvel Cc: Vinayak Menon Cc: Fixes: 39bc88e5e38e9b21 ("arm64: Disable TTBR0_EL1 during normal kernel execution") Reviewed-by: Catalin Marinas Reviewed-by: Mark Rutland Reported-by: Vinayak Menon Signed-off-by: Will Deacon Git-commit: d96cc49bff5a7735576cc6f6f111f875d101cec8 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/mmu_context.h | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h index 4cb8e290b3176..1f7dcb26bdfa2 100644 --- a/arch/arm64/include/asm/mmu_context.h +++ b/arch/arm64/include/asm/mmu_context.h @@ -109,20 +109,6 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu); #define init_new_context(tsk,mm) ({ atomic64_set(&(mm)->context.id, 0); 0; }) -/* - * This is called when "tsk" is about to enter lazy TLB mode. - * - * mm: describes the currently active mm context - * tsk: task which is entering lazy tlb - * cpu: cpu number which is entering lazy tlb - * - * tsk->mm will be NULL - */ -static inline void -enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) -{ -} - #ifdef CONFIG_ARM64_SW_TTBR0_PAN static inline void update_saved_ttbr0(struct task_struct *tsk, struct mm_struct *mm) @@ -146,6 +132,16 @@ static inline void update_saved_ttbr0(struct task_struct *tsk, } #endif +static inline void +enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) +{ + /* + * We don't actually care about the ttbr0 mapping, so point it at the + * zero page. + */ + update_saved_ttbr0(tsk, &init_mm); +} + static inline void __switch_mm(struct mm_struct *next) { unsigned int cpu = smp_processor_id(); From 94fbcb28e27aeb4dad5facc0a2d064a4c648bb60 Mon Sep 17 00:00:00 2001 From: Jitendra Sharma Date: Wed, 10 Jan 2018 17:59:48 +0530 Subject: [PATCH 024/508] defconfig: msm: Enable SYSMON communication interface for sdx To provide communication among multiple subsystems, enable SYSMON communication interface. Change-Id: I077b7086fad7ee8a8ba311e2292b478b1a785a57 Signed-off-by: Jitendra Sharma --- arch/arm/configs/sdx-perf_defconfig | 1 + arch/arm/configs/sdx_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/sdx-perf_defconfig b/arch/arm/configs/sdx-perf_defconfig index 12742ac5cc094..8b99d8fdcd63b 100644 --- a/arch/arm/configs/sdx-perf_defconfig +++ b/arch/arm/configs/sdx-perf_defconfig @@ -364,6 +364,7 @@ CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y CONFIG_MSM_GLINK_PKT=y CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_SYSMON_COMM=y CONFIG_MSM_PIL=y CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_MSM_PIL_MSS_QDSP6V5=y diff --git a/arch/arm/configs/sdx_defconfig b/arch/arm/configs/sdx_defconfig index 0a2a51c5859df..e62191dff06f6 100644 --- a/arch/arm/configs/sdx_defconfig +++ b/arch/arm/configs/sdx_defconfig @@ -375,6 +375,7 @@ CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y CONFIG_MSM_GLINK_PKT=y CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_SYSMON_COMM=y CONFIG_MSM_PIL=y CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_MSM_PIL_MSS_QDSP6V5=y From 5b21a9c07b4f300a5148fb309e6a434096824988 Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Sirasanagandla Date: Mon, 8 Jan 2018 17:05:11 +0530 Subject: [PATCH 025/508] wlan: Modify wlan driver to support msm-4.9 kernel Upgrade wlan driver to support msm-4.9 kernel and also maintain backward compatibility with previous kernel versions. Change-Id: Iaae91fe559bfba05b1da4be9b9ef9a12d6f9df28 CRs-Fixed: 2180168 --- Android.mk | 19 ++ CORE/HDD/inc/bap_hdd_misc.h | 5 +- CORE/HDD/inc/wlan_hdd_cfg80211.h | 12 +- CORE/HDD/inc/wlan_hdd_main.h | 33 ++- CORE/HDD/inc/wlan_hdd_p2p.h | 66 ++++- CORE/HDD/inc/wlan_hdd_tx_rx.h | 23 +- CORE/HDD/src/wlan_hdd_assoc.c | 64 ++++- CORE/HDD/src/wlan_hdd_cfg80211.c | 241 ++++++++++++++----- CORE/HDD/src/wlan_hdd_early_suspend.c | 9 +- CORE/HDD/src/wlan_hdd_hostapd.c | 6 +- CORE/HDD/src/wlan_hdd_main.c | 99 +++++++- CORE/HDD/src/wlan_hdd_p2p.c | 191 +++++++++++---- CORE/HDD/src/wlan_hdd_softap_tx_rx.c | 6 +- CORE/HDD/src/wlan_hdd_tx_rx.c | 10 +- CORE/SME/src/csr/csrApiRoam.c | 4 + CORE/SME/src/csr/csrNeighborRoam.c | 6 +- CORE/SVC/src/logging/wlan_logging_sock_svc.c | 14 +- CORE/VOSS/inc/i_vos_lock.h | 15 +- CORE/VOSS/inc/vos_api.h | 15 +- CORE/VOSS/inc/vos_lock.h | 10 +- CORE/VOSS/inc/vos_utils.h | 11 +- CORE/VOSS/src/vos_lock.c | 84 ++++++- CORE/VOSS/src/vos_nvitem.c | 66 ++--- CORE/VOSS/src/vos_sched.h | 10 +- CORE/VOSS/src/vos_utils.c | 14 +- CORE/WDI/WPAL/src/wlan_qct_pal_timer.c | 5 +- Kbuild | 21 +- 27 files changed, 850 insertions(+), 209 deletions(-) diff --git a/Android.mk b/Android.mk index de0c7354aea9c..179d4cb636252 100644 --- a/Android.mk +++ b/Android.mk @@ -48,7 +48,11 @@ ifeq ($(WLAN_PROPRIETARY),1) WLAN_BLD_DIR := vendor/qcom/proprietary/wlan else ifneq ($(TARGET_SUPPORTS_WEARABLES),true) +ifneq ($(ANDROID_BUILD_TOP),) + WLAN_BLD_DIR := $(ANDROID_BUILD_TOP)/vendor/qcom/opensource/wlan +else WLAN_BLD_DIR := vendor/qcom/opensource/wlan +endif else WLAN_BLD_DIR := device/qcom/msm8909w/opensource/wlan endif @@ -115,7 +119,17 @@ endif ########################################################### # This is set once per LOCAL_PATH, not per (kernel) module + +ifneq ($(TARGET_SUPPORTS_WEARABLES),true) +ifneq ($(ANDROID_BUILD_TOP),) +KBUILD_OPTIONS := WLAN_ROOT=$(WLAN_BLD_DIR)/prima +endif +endif + +ifeq ($(KBUILD_OPTIONS),) KBUILD_OPTIONS := WLAN_ROOT=$(KERNEL_TO_BUILD_ROOT_OFFSET)$(WLAN_BLD_DIR)/prima +endif + # We are actually building wlan.ko here, as per the # requirement we are specifying _wlan.ko as LOCAL_MODULE. # This means we need to rename the module to _wlan.ko @@ -125,8 +139,13 @@ KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) KBUILD_OPTIONS += $(WLAN_SELECT) +ifeq ($(KERNEL_TO_BUILD_ROOT_OFFSET),../../) +VERSION=$(shell grep -w "VERSION =" $(TOP)/kernel/msm-$(TARGET_KERNEL_VERSION)/Makefile | sed 's/^VERSION = //' ) +PATCHLEVEL=$(shell grep -w "PATCHLEVEL =" $(TOP)/kernel/msm-$(TARGET_KERNEL_VERSION)/Makefile | sed 's/^PATCHLEVEL = //' ) +else VERSION=$(shell grep -w "VERSION =" $(TOP)/kernel/Makefile | sed 's/^VERSION = //' ) PATCHLEVEL=$(shell grep -w "PATCHLEVEL =" $(TOP)/kernel/Makefile | sed 's/^PATCHLEVEL = //' ) +endif include $(CLEAR_VARS) LOCAL_MODULE := $(WLAN_CHIPSET)_wlan.ko diff --git a/CORE/HDD/inc/bap_hdd_misc.h b/CORE/HDD/inc/bap_hdd_misc.h index b373760f0b461..4ac93b6571f15 100644 --- a/CORE/HDD/inc/bap_hdd_misc.h +++ b/CORE/HDD/inc/bap_hdd_misc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -28,6 +28,8 @@ #if !defined( BAP_HDD_MISC_H ) #define BAP_HDD_MISC_H +#ifdef WLAN_BTAMP_FEATURE + /**=========================================================================== \file BAP_HDD_MISC.h @@ -136,4 +138,5 @@ VOS_STATUS WLANBAP_StopAmp(void); --------------------------------------------------------------------------*/ v_BOOL_t WLANBAP_AmpSessionOn(void); +#endif #endif // end #if !defined( BAP_HDD_MISC_H ) diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h index b7312b9f6afaa..0d0f71b7b020c 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -105,6 +105,12 @@ #define CHANNEL_SWITCH_SUPPORTED #endif +#if defined(CFG80211_DEL_STA_V2) || \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) || \ + defined(WITH_BACKPORTS) +#define USE_CFG80211_DEL_STA_V2 +#endif + #define MAX_CHANNEL NUM_2_4GHZ_CHANNELS + NUM_5GHZ_CHANNELS #define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \ @@ -1643,7 +1649,9 @@ void wlan_hdd_cfg80211_oemdata_callback(void *ctx, const tANI_U16 evType, void *pMsg, tANI_U32 evLen); #endif /* FEATURE_OEM_DATA_SUPPORT */ -#if !(defined (SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) +#if !(defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) && \ + (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && \ + !(defined(WITH_BACKPORTS)) static inline struct sk_buff * backported_cfg80211_vendor_event_alloc(struct wiphy *wiphy, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0)) @@ -1702,7 +1710,7 @@ struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_list( struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter, tSirBssDescription *bss_desc); -#ifdef CFG80211_DEL_STA_V2 +#ifdef USE_CFG80211_DEL_STA_V2 int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *param); diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index f001f77709a01..3bd74fca482c4 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -54,9 +54,15 @@ #include #include #include -#ifdef WLAN_OPEN_SOURCE + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && \ + defined(WLAN_OPEN_SOURCE) +#include +#include +#else #include #endif + #include #ifdef FEATURE_WLAN_TDLS #include "wlan_hdd_tdls.h" @@ -72,6 +78,17 @@ #define LIBRA_CARD_INSERT_DETECT_MAX_COUNT 5 #define LIBRA_CARD_REMOVE_DETECT_MAX_COUNT 5 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)) || \ + defined(CFG80211_REMOVE_IEEE80211_BACKPORT) +#define HDD_NL80211_BAND_2GHZ NL80211_BAND_2GHZ +#define HDD_NL80211_BAND_5GHZ NL80211_BAND_5GHZ +#define HDD_NUM_NL80211_BANDS NUM_NL80211_BANDS +#else +#define HDD_NL80211_BAND_2GHZ IEEE80211_BAND_2GHZ +#define HDD_NL80211_BAND_5GHZ IEEE80211_BAND_5GHZ +#define HDD_NUM_NL80211_BANDS ((enum nl80211_band)IEEE80211_NUM_BANDS) +#endif + /** Number of Tx Queues. This should be same as the one * used in TL WLANTL_NUM_TX_QUEUES */ #define NUM_TX_QUEUES 5 @@ -2294,4 +2311,18 @@ int wlan_hdd_check_and_stop_mon(hdd_adapter_t *sta_adapter, bool wait); */ bool hdd_is_sta_sap_scc_allowed_on_dfs_chan(hdd_context_t *hdd_ctx); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)) +static inline int +hdd_wlan_nla_put_u64(struct sk_buff *skb, int attrtype, u64 value) +{ + return nla_put_u64(skb, attrtype, value); +} +#else +static inline int +hdd_wlan_nla_put_u64(struct sk_buff *skb, int attrtype, u64 value) +{ + return nla_put_u64_64bit(skb, attrtype, value, NL80211_ATTR_PAD); +} +#endif + #endif // end #if !defined( WLAN_HDD_MAIN_H ) diff --git a/CORE/HDD/inc/wlan_hdd_p2p.h b/CORE/HDD/inc/wlan_hdd_p2p.h index 4e733f039fc1f..fef8e1095cdaf 100644 --- a/CORE/HDD/inc/wlan_hdd_p2p.h +++ b/CORE/HDD/inc/wlan_hdd_p2p.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2017-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -172,24 +172,66 @@ int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev, const u8 *buf, size_t len, u64 *cookie ); #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) +struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + struct vif_params *params); + +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || \ + defined(WITH_BACKPORTS) +/** + * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper + * @wiphy: wiphy pointer + * @name: User-visible name of the interface + * @name_assign_type: the name of assign type of the netdev + * @nl80211_iftype: (virtual) interface types + * @flags: monitor mode configuration flags (not used) + * @vif_params: virtual interface parameters (not used) + * + * Return: the pointer of wireless dev, otherwise ERR_PTR. + */ +struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params); + +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) +/** + * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper + * @wiphy: wiphy pointer + * @name: User-visible name of the interface + * @nl80211_iftype: (virtual) interface types + * @flags: monitor mode configuration flags (not used) + * @vif_params: virtual interface parameters (not used) + * + * Return: the pointer of wireless dev, otherwise ERR_PTR. + */ +struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) -struct wireless_dev* wlan_hdd_add_virtual_intf( - struct wiphy *wiphy, const char *name, - enum nl80211_iftype type, - u32 *flags, struct vif_params *params ); #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) struct wireless_dev* wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name, enum nl80211_iftype type, u32 *flags, struct vif_params *params ); + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) -struct net_device* wlan_hdd_add_virtual_intf( - struct wiphy *wiphy, char *name, enum nl80211_iftype type, - u32 *flags, struct vif_params *params ); +struct net_device* wlan_hdd_add_virtual_intf(struct wiphy *wiphy, + char *name, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params); + #else -int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name, - enum nl80211_iftype type, - u32 *flags, struct vif_params *params ); +int wlan_hdd_add_virtual_intf(struct wiphy *wiphy, char *name, + enum nl80211_iftype type, + u32 *flags, struct vif_params *params); #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) diff --git a/CORE/HDD/inc/wlan_hdd_tx_rx.h b/CORE/HDD/inc/wlan_hdd_tx_rx.h index 06c5accb2ff83..052149b0c1619 100644 --- a/CORE/HDD/inc/wlan_hdd_tx_rx.h +++ b/CORE/HDD/inc/wlan_hdd_tx_rx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2015, 2017-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -410,4 +410,25 @@ static inline void wlan_hdd_log_eapol(struct sk_buff *skb, */ void hdd_rx_fwd_eapol(v_VOID_t *vosContext, vos_pkt_t *pVosPacket); +/* + * As of the 4.7 kernel, net_device->trans_start is removed. Create shims to + * support compiling against older versions of the kernel. + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)) +static inline void netif_trans_update(struct net_device *dev) +{ + dev->trans_start = jiffies; +} + +#define TX_TIMEOUT_TRACE(dev, module_id) VOS_TRACE( \ + module_id, VOS_TRACE_LEVEL_ERROR, \ + "%s: Transmission timeout occurred jiffies %lu trans_start %lu", \ + __func__, jiffies, dev->trans_start) +#else +#define TX_TIMEOUT_TRACE(dev, module_id) VOS_TRACE( \ + module_id, VOS_TRACE_LEVEL_ERROR, \ + "%s: Transmission timeout occurred jiffies %lu", \ + __func__, jiffies) +#endif + #endif // end #if !defined( WLAN_HDD_TX_RX_H ) diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c index 9c84d8459da76..94e773d8e7ca5 100644 --- a/CORE/HDD/src/wlan_hdd_assoc.c +++ b/CORE/HDD/src/wlan_hdd_assoc.c @@ -68,6 +68,57 @@ #include #include "sapInternal.h" +#if defined CFG80211_ROAMED_API_UNIFIED || \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) +/** + * hdd_send_roamed_ind() - send roamed indication to cfg80211 + * @dev: network device + * @bss: cfg80211 roamed bss pointer + * @req_ie: IEs used in reassociation request + * @req_ie_len: Length of the @req_ie + * @resp_ie: IEs received in successful reassociation response + * @resp_ie_len: Length of @resp_ie + * + * Return: none + */ +static void hdd_send_roamed_ind(struct net_device *dev, + struct cfg80211_bss *bss, const uint8_t *req_ie, + size_t req_ie_len, const uint8_t *resp_ie, + size_t resp_ie_len) +{ + struct cfg80211_roam_info info = {0}; + + info.bss = bss; + info.req_ie = req_ie; + info.req_ie_len = req_ie_len; + info.resp_ie = resp_ie; + info.resp_ie_len = resp_ie_len; + + cfg80211_roamed(dev, &info, GFP_KERNEL); +} +#else +/** + * hdd_send_roamed_ind() - send roamed indication to cfg80211 + * @dev: network device + * @bss: cfg80211 roamed bss pointer + * @req_ie: IEs used in reassociation request + * @req_ie_len: Length of the @req_ie + * @resp_ie: IEs received in successful reassociation response + * @resp_ie_len: Length of @resp_ie + * + * Return: none + */ +static inline void hdd_send_roamed_ind(struct net_device *dev, + struct cfg80211_bss *bss, + const uint8_t *req_ie, size_t req_ie_len, + const uint8_t *resp_ie, + size_t resp_ie_len) +{ + cfg80211_roamed_bss(dev, bss, req_ie, req_ie_len, resp_ie, resp_ie_len, + GFP_KERNEL); +} +#endif + v_BOOL_t mibIsDot11DesiredBssTypeInfrastructure( hdd_adapter_t *pAdapter ); struct ether_addr @@ -2127,9 +2178,9 @@ static void hdd_SendReAssocEvent(struct net_device *dev, hdd_adapter_t *pAdapter chan, pCsrRoamInfo->bssid, &roam_profile.SSID.ssId[0], roam_profile.SSID.length); - cfg80211_roamed_bss(dev, bss, + hdd_send_roamed_ind(dev, bss, reqRsnIe, reqRsnLength, - rspRsnIe, rspRsnLength,GFP_KERNEL); + rspRsnIe, rspRsnLength); done: kfree(rspRsnIe); @@ -2418,10 +2469,9 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs chan, pRoamInfo->bssid, pRoamInfo->u.pConnectedProfile->SSID.ssId, pRoamInfo->u.pConnectedProfile->SSID.length); - cfg80211_roamed_bss(dev, roam_bss, + hdd_send_roamed_ind(dev, roam_bss, pFTAssocReq, assocReqlen, - pFTAssocRsp, assocRsplen, - GFP_KERNEL); + pFTAssocRsp, assocRsplen); } if (sme_GetFTPTKState(WLAN_HDD_GET_HAL_CTX(pAdapter))) { @@ -2843,10 +2893,10 @@ static void hdd_RoamIbssIndicationHandler( hdd_adapter_t *pAdapter, if (chan_no <= 14) freq = ieee80211_channel_to_frequency(chan_no, - IEEE80211_BAND_2GHZ); + HDD_NL80211_BAND_2GHZ); else freq = ieee80211_channel_to_frequency(chan_no, - IEEE80211_BAND_5GHZ); + HDD_NL80211_BAND_5GHZ); chan = ieee80211_get_channel(pAdapter->wdev.wiphy, freq); diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index dd14f10b3febc..a3ef1946adc31 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -63,6 +63,7 @@ #include #include #include +#include #include #include #include @@ -110,7 +111,7 @@ ((uintptr_t)OFFSET_OF( tSirBssDescription, ieFields))) #define HDD2GHZCHAN(freq, chan, flag) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = HDD_NL80211_BAND_2GHZ, \ .center_freq = (freq), \ .hw_value = (chan),\ .flags = (flag), \ @@ -119,7 +120,7 @@ } #define HDD5GHZCHAN(freq, chan, flag) { \ - .band = IEEE80211_BAND_5GHZ, \ + .band = HDD_NL80211_BAND_5GHZ, \ .center_freq = (freq), \ .hw_value = (chan),\ .flags = (flag), \ @@ -208,12 +209,6 @@ static const u32 hdd_cipher_suites[] = #endif }; -static inline int is_broadcast_ether_addr(const u8 *addr) -{ - return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && - (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); -} - const static struct ieee80211_channel hdd_channels_2_4_GHZ[] = { HDD2GHZCHAN(2412, 1, 0) , @@ -302,7 +297,7 @@ static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ = { .channels = NULL, .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ), - .band = IEEE80211_BAND_2GHZ, + .band = HDD_NL80211_BAND_2GHZ, .bitrates = g_mode_rates, .n_bitrates = g_mode_rates_size, .ht_cap.ht_supported = 1, @@ -321,7 +316,7 @@ static struct ieee80211_supported_band wlan_hdd_band_5_GHZ = { .channels = NULL, .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ), - .band = IEEE80211_BAND_5GHZ, + .band = HDD_NL80211_BAND_5GHZ, .bitrates = a_mode_rates, .n_bitrates = a_mode_rates_size, .ht_cap.ht_supported = 1, @@ -2072,7 +2067,7 @@ static v_BOOL_t put_wifi_iface_stats(hdd_adapter_t *pAdapter, nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_GUARD_TIME, pWifiIfaceStat->leakyApStat.rx_leak_window) || - nla_put_u64(vendor_event, + hdd_wlan_nla_put_u64(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_AVERAGE_TSF_OFFSET, pWifiIfaceStat->leakyApStat.avg_bcn_spread)) { @@ -3660,7 +3655,7 @@ static void wlan_hdd_cfg80211_extscan_cached_results_ind(void *ctx, goto fail; } - if (nla_put_u64(skb, + if (hdd_wlan_nla_put_u64(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP, pSirWifiScanResult->ts) ) { @@ -3853,7 +3848,7 @@ static void wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx, if (!ap) goto fail; - if (nla_put_u64(skb, + if (hdd_wlan_nla_put_u64(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP, pData->bssHotlist[i].ts) || nla_put(skb, @@ -3966,7 +3961,7 @@ static void wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx, hddLog(VOS_TRACE_LEVEL_INFO, "IE Length (%u)", pData->ieLength); if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID, pData->requestId) || - nla_put_u64(skb, + hdd_wlan_nla_put_u64(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP, pData->ap.ts) || nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID, @@ -4687,7 +4682,7 @@ static int __wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy, { num_chan_new = 0; for (i = 0; i < num_channels; i++) - for (j = 0; j < IEEE80211_NUM_BANDS; j++) { + for (j = 0; j < HDD_NUM_NL80211_BANDS; j++) { if (wiphy->bands[j] == NULL) continue; for (k = 0; k < wiphy->bands[j]->n_channels; k++) { @@ -7645,16 +7640,25 @@ static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy, if (!(rate_flags & eHAL_TX_RATE_LEGACY)) { if (rate_flags & eHAL_TX_RATE_VHT80) { final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && \ + !defined(WITH_BACKPORTS) final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; +#endif } else if (rate_flags & eHAL_TX_RATE_VHT40) { final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && \ + !defined(WITH_BACKPORTS) final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; +#endif } else if (rate_flags & eHAL_TX_RATE_VHT20) { final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS; } else if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) { final_rate_flags |= RATE_INFO_FLAGS_MCS; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && \ + !defined(WITH_BACKPORTS) if (rate_flags & eHAL_TX_RATE_HT40) final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; +#endif } if (rate_flags & eHAL_TX_RATE_SGI) { @@ -8815,7 +8819,7 @@ int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand) ENTER(); - for (i = 0; i < IEEE80211_NUM_BANDS; i++) + for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) { if (NULL == wiphy->bands[i]) @@ -8832,12 +8836,12 @@ int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand) channelEnabledState = vos_nv_getChannelEnabledState( band->channels[j].hw_value); - if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) // 5G only + if (HDD_NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) // 5G only { band->channels[j].flags |= IEEE80211_CHAN_DISABLED; continue; } - else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == eBand) // 2G only + else if (HDD_NL80211_BAND_5GHZ == i && eCSR_BAND_24 == eBand) // 2G only { band->channels[j].flags |= IEEE80211_CHAN_DISABLED; continue; @@ -9013,38 +9017,38 @@ int wlan_hdd_cfg80211_init(struct device *dev, * wiphy flags don't get reset because of static memory. * It's better not to store channel in static memory. */ - wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; - wiphy->bands[IEEE80211_BAND_2GHZ]->channels = + wiphy->bands[HDD_NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; + wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels = (struct ieee80211_channel *)vos_mem_malloc(sizeof(hdd_channels_2_4_GHZ)); - if (wiphy->bands[IEEE80211_BAND_2GHZ]->channels == NULL) + if (wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels == NULL) { hddLog(VOS_TRACE_LEVEL_ERROR, FL("Not enough memory to allocate channels")); return -ENOMEM; } - vos_mem_copy(wiphy->bands[IEEE80211_BAND_2GHZ]->channels, + vos_mem_copy(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels, &hdd_channels_2_4_GHZ[0], sizeof(hdd_channels_2_4_GHZ)); if (true == hdd_is_5g_supported(pHddCtx)) { - wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; - wiphy->bands[IEEE80211_BAND_5GHZ]->channels = + wiphy->bands[HDD_NL80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels = (struct ieee80211_channel *)vos_mem_malloc(sizeof(hdd_channels_5_GHZ)); - if (wiphy->bands[IEEE80211_BAND_5GHZ]->channels == NULL) + if (wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels == NULL) { hddLog(VOS_TRACE_LEVEL_ERROR, FL("Not enough memory to allocate channels")); - vos_mem_free(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); - wiphy->bands[IEEE80211_BAND_2GHZ]->channels = NULL; + vos_mem_free(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels); + wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels = NULL; return -ENOMEM; } - vos_mem_copy(wiphy->bands[IEEE80211_BAND_5GHZ]->channels, + vos_mem_copy(wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels, &hdd_channels_5_GHZ[0], sizeof(hdd_channels_5_GHZ)); } - for (i = 0; i < IEEE80211_NUM_BANDS; i++) + for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) { if (NULL == wiphy->bands[i]) @@ -9058,7 +9062,7 @@ int wlan_hdd_cfg80211_init(struct device *dev, { struct ieee80211_supported_band *band = wiphy->bands[i]; - if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == pCfg->nBandCapability) // 5G only + if (HDD_NL80211_BAND_2GHZ == i && eCSR_BAND_5G == pCfg->nBandCapability) // 5G only { // Enable social channels for P2P if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq)) @@ -9067,7 +9071,7 @@ int wlan_hdd_cfg80211_init(struct device *dev, band->channels[j].flags |= IEEE80211_CHAN_DISABLED; continue; } - else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == pCfg->nBandCapability) // 2G only + else if (HDD_NL80211_BAND_5GHZ == i && eCSR_BAND_24 == pCfg->nBandCapability) // 2G only { band->channels[j].flags |= IEEE80211_CHAN_DISABLED; continue; @@ -9130,14 +9134,14 @@ void wlan_hdd_cfg80211_update_reg_info(struct wiphy *wiphy) } if ((defaultCountryCode[0]== 'U') && (defaultCountryCode[1]=='S')) { - if (NULL == wiphy->bands[IEEE80211_BAND_5GHZ]) + if (NULL == wiphy->bands[HDD_NL80211_BAND_5GHZ]) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[IEEE80211_BAND_5GHZ] is NULL",__func__ ); + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[HDD_NL80211_BAND_5GHZ] is NULL",__func__ ); return; } - for (j = 0; j < wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels; j++) + for (j = 0; j < wiphy->bands[HDD_NL80211_BAND_5GHZ]->n_channels; j++) { - struct ieee80211_supported_band *band = wiphy->bands[IEEE80211_BAND_5GHZ]; + struct ieee80211_supported_band *band = wiphy->bands[HDD_NL80211_BAND_5GHZ]; // Mark UNII -1 band channel as passive if (WLAN_HDD_CHANNEL_IN_UNII_1_BAND(band->channels[j].center_freq)) band->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN; @@ -9959,12 +9963,12 @@ VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int chann if (channel <= ARRAY_SIZE(hdd_channels_2_4_GHZ)) { freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_2GHZ); + HDD_NL80211_BAND_2GHZ); } else { freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_5GHZ); + HDD_NL80211_BAND_5GHZ); } #else freq = ieee80211_channel_to_frequency(channel); @@ -10323,7 +10327,7 @@ void hdd_update_indoor_channel(hdd_context_t *hdd_ctx, hddLog(VOS_TRACE_LEVEL_INFO, "disable: %d", disable); wiphy = hdd_ctx->wiphy; - for (band_num = 0; band_num < IEEE80211_NUM_BANDS; band_num++) { + for (band_num = 0; band_num < HDD_NUM_NL80211_BANDS; band_num++) { if (wiphy->bands[band_num] == NULL) continue; @@ -13465,11 +13469,11 @@ static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss( #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38)) if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ)) { - freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ); + freq = ieee80211_channel_to_frequency(chan_no, HDD_NL80211_BAND_2GHZ); } else { - freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ); + freq = ieee80211_channel_to_frequency(chan_no, HDD_NL80211_BAND_5GHZ); } #else freq = ieee80211_channel_to_frequency(chan_no); @@ -13635,15 +13639,15 @@ wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38)) if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) && - (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) + (wiphy->bands[HDD_NL80211_BAND_2GHZ] != NULL)) { - freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ); + freq = ieee80211_channel_to_frequency(chan_no, HDD_NL80211_BAND_2GHZ); } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) && - (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) + (wiphy->bands[HDD_NL80211_BAND_5GHZ] != NULL)) { - freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ); + freq = ieee80211_channel_to_frequency(chan_no, HDD_NL80211_BAND_5GHZ); } else { @@ -14060,6 +14064,71 @@ static inline bool wlan_hdd_cfg80211_validate_scan_req(struct } #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)) +/** + * hdd_cfg80211_scan_done() - Scan completed callback to cfg80211 + * @adapter: Pointer to the adapter + * @req : Scan request + * @aborted : true scan aborted false scan success + * + * This function notifies scan done to cfg80211 + * + * Return: none + */ +static void hdd_cfg80211_scan_done(hdd_adapter_t *adapter, + struct cfg80211_scan_request *req, + bool aborted) +{ + struct cfg80211_scan_info info = { + .aborted = aborted + }; + + if (adapter->dev->flags & IFF_UP) + cfg80211_scan_done(req, &info); + else + hddLog(LOGW, + FL("IFF_UP flag reset for %s"), adapter->dev->name); +} +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) +/** + * hdd_cfg80211_scan_done() - Scan completed callback to cfg80211 + * @adapter: Pointer to the adapter + * @req : Scan request + * @aborted : true scan aborted false scan success + * + * This function notifies scan done to cfg80211 + * + * Return: none + */ +static void hdd_cfg80211_scan_done(hdd_adapter_t *adapter, + struct cfg80211_scan_request *req, + bool aborted) +{ + if (adapter->dev->flags & IFF_UP) + cfg80211_scan_done(req, aborted); + else + hddLog(LOGW, + FL("IFF_UP flag reset for %s"), adapter->dev->name); +} +#else +/** + * hdd_cfg80211_scan_done() - Scan completed callback to cfg80211 + * @adapter: Pointer to the adapter + * @req : Scan request + * @aborted : true scan aborted false scan success + * + * This function notifies scan done to cfg80211 + * + * Return: none + */ +static void hdd_cfg80211_scan_done(hdd_adapter_t *adapter, + struct cfg80211_scan_request *req, + bool aborted) +{ + cfg80211_scan_done(req, aborted); +} +#endif + #define NET_DEV_IS_IFF_UP(pAdapter) (pAdapter->dev->flags & IFF_UP) /* * FUNCTION: hdd_cfg80211_scan_done_callback @@ -14227,7 +14296,7 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, if (NET_DEV_IS_IFF_UP(pAdapter) && wlan_hdd_cfg80211_validate_scan_req(req, pHddCtx)) #endif - cfg80211_scan_done(req, aborted); + hdd_cfg80211_scan_done(pAdapter, req, aborted); complete(&pScanInfo->abortscan_event_var); @@ -14727,7 +14796,7 @@ int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy, if (0 > ret) hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__); - cfg80211_scan_done(request, eCSR_SCAN_SUCCESS); + hdd_cfg80211_scan_done(pAdapter, request, eCSR_SCAN_SUCCESS); status = eHAL_STATUS_SUCCESS; goto free_mem; @@ -17346,10 +17415,18 @@ static void wlan_hdd_fill_summary_stats(tCsrSummaryStatsInfo *stats, info->tx_failed += stats->fail_cnt[i]; } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && \ + !defined(WITH_BACKPORTS) info->filled |= STATION_INFO_TX_PACKETS | STATION_INFO_TX_RETRIES | STATION_INFO_TX_FAILED | STATION_INFO_RX_PACKETS; +#else + info->filled |= BIT(NL80211_STA_INFO_TX_PACKETS) | + BIT(NL80211_STA_INFO_TX_RETRIES) | + BIT(NL80211_STA_INFO_TX_FAILED) | + BIT(NL80211_STA_INFO_RX_PACKETS); +#endif } /** @@ -17368,6 +17445,21 @@ wlan_hdd_sap_get_sta_rssi(hdd_adapter_t *adapter, uint8_t staid, s8 *rssi) WLANTL_GetSAPStaRSSi(pVosContext, staid, rssi); } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && \ + !defined(WITH_BACKPORTS) +static inline void wlan_hdd_fill_station_info_signal(struct station_info + *sinfo) +{ + sinfo->filled |= STATION_INFO_SIGNAL; +} +#else +static inline void wlan_hdd_fill_station_info_signal(struct station_info + *sinfo) +{ + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); +} +#endif + /** * wlan_hdd_get_sap_stats() - get aggregate SAP stats * @adapter: sap adapter to get stats for @@ -17408,7 +17500,7 @@ wlan_hdd_get_sap_stats(hdd_adapter_t *adapter, if (staid < WLAN_MAX_STA_COUNT && !bc_mac_addr) { wlan_hdd_sap_get_sta_rssi(adapter, staid, &info->signal); - info->filled |= STATION_INFO_SIGNAL; + wlan_hdd_fill_station_info_signal(info); } wlan_hdd_fill_summary_stats(&adapter->hdd_stats.summary_stat, info); @@ -17490,7 +17582,7 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_devic wlan_hdd_get_snr(pAdapter, &snr); pHddStaCtx->conn_info.signal = sinfo->signal; pHddStaCtx->conn_info.noise = pHddStaCtx->conn_info.signal - snr; - sinfo->filled |= STATION_INFO_SIGNAL; + wlan_hdd_fill_station_info_signal(sinfo); /*overwrite rate_flags if MAX link-speed need to be reported*/ if ((eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed) || @@ -17770,12 +17862,22 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_devic if (rate_flags & eHAL_TX_RATE_VHT80) { sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || \ + defined(WITH_BACKPORTS) + sinfo->txrate.bw = RATE_INFO_BW_80; +#else sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; +#endif } else if (rate_flags & eHAL_TX_RATE_VHT40) { sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || \ + defined(WITH_BACKPORTS) + sinfo->txrate.bw = RATE_INFO_BW_40; +#else sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; +#endif } else if (rate_flags & eHAL_TX_RATE_VHT20) { @@ -17787,7 +17889,12 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_devic sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; if (rate_flags & eHAL_TX_RATE_HT40) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || \ + defined(WITH_BACKPORTS) + sinfo->txrate.bw = RATE_INFO_BW_40; +#else sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; +#endif } } if (rate_flags & eHAL_TX_RATE_SGI) @@ -17835,12 +17942,22 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_devic } if (rate_flags & eHAL_TX_RATE_HT40) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || \ + defined(WITH_BACKPORTS) + sinfo->txrate.bw = RATE_INFO_BW_40; +#else sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; +#endif } #ifdef WLAN_FEATURE_11AC else if (rate_flags & eHAL_TX_RATE_VHT80) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || \ + defined(WITH_BACKPORTS) + sinfo->txrate.bw = RATE_INFO_BW_80; +#else sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; +#endif } #endif /* WLAN_FEATURE_11AC */ #ifdef LINKSPEED_DEBUG_ENABLED @@ -17850,7 +17967,13 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_devic #endif //LINKSPEED_DEBUG_ENABLED } } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && \ + !defined(WITH_BACKPORTS) sinfo->filled |= STATION_INFO_TX_BITRATE; +#else + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); +#endif sinfo->tx_packets = pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] + @@ -17870,13 +17993,21 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_devic pAdapter->hdd_stats.summary_stat.fail_cnt[2] + pAdapter->hdd_stats.summary_stat.fail_cnt[3]; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && \ + !defined(WITH_BACKPORTS) sinfo->filled |= + STATION_INFO_RX_PACKETS | STATION_INFO_TX_PACKETS | STATION_INFO_TX_RETRIES | STATION_INFO_TX_FAILED; +#else + sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS) | + BIT(NL80211_STA_INFO_TX_PACKETS) | + BIT(NL80211_STA_INFO_TX_RETRIES) | + BIT(NL80211_STA_INFO_TX_FAILED); +#endif sinfo->rx_packets = pAdapter->hdd_stats.summary_stat.rx_frm_cnt; - sinfo->filled |= STATION_INFO_RX_PACKETS; vos_mem_copy(&pHddStaCtx->conn_info.txrate, &sinfo->txrate, sizeof(sinfo->txrate)); @@ -18171,7 +18302,7 @@ static int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, return 0; } -#ifdef CFG80211_DEL_STA_V2 +#ifdef USE_CFG80211_DEL_STA_V2 int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *param) @@ -18190,7 +18321,7 @@ int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, vos_ssr_protect(__func__); -#ifdef CFG80211_DEL_STA_V2 +#ifdef USE_CFG80211_DEL_STA_V2 if (NULL == param) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid argumet passed", __func__); vos_ssr_unprotect(__func__); @@ -19201,7 +19332,8 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, u16 status_code, u32 peer_capability, const u8 *buf, size_t len) #else /* TDLS_MGMT_VERSION2 */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || \ + defined(WITH_BACKPORTS) static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, const u8 *peer, u8 action_code, @@ -19616,7 +19748,8 @@ static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *d dialog_token, status_code, peer_capability, buf, len); #else /* TDLS_MGMT_VERSION2 */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || \ + defined(WITH_BACKPORTS) ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code, dialog_token, status_code, peer_capability, initiator, @@ -21050,7 +21183,7 @@ static int __wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy, hdd_wlan_get_freq(channel, &freq); - for (i = 0; i < IEEE80211_NUM_BANDS; i++) + for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) { if (NULL == wiphy->bands[i]) { diff --git a/CORE/HDD/src/wlan_hdd_early_suspend.c b/CORE/HDD/src/wlan_hdd_early_suspend.c index 6057705401680..375adab62bf7a 100644 --- a/CORE/HDD/src/wlan_hdd_early_suspend.c +++ b/CORE/HDD/src/wlan_hdd_early_suspend.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -43,7 +43,14 @@ #include #include #include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && \ + defined(WLAN_OPEN_SOURCE) +#include +#include +#else #include +#endif #include "halTypes.h" #include "sme_Api.h" diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index 0806e67e65bc0..faa0fe60053a9 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -1383,7 +1383,7 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa hddLog(LOGE, FL("Failed to start AP inactivity timer")); } #ifdef WLAN_OPEN_SOURCE - if (wake_lock_active(&pHddCtx->sap_wake_lock)) + if (vos_wake_lock_active(&pHddCtx->sap_wake_lock)) { vos_wake_lock_release(&pHddCtx->sap_wake_lock, WIFI_POWER_EVENT_WAKELOCK_SAP); @@ -1410,7 +1410,9 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa staInfo->assoc_req_ies = (const u8 *)&pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.ies[0]; staInfo->assoc_req_ies_len = iesLen; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,31)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,31)) && \ + ((LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && \ + !defined(WITH_BACKPORTS)) staInfo->filled |= STATION_INFO_ASSOC_REQ_IES; #endif cfg80211_new_sta(dev, diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 7739afaefa877..46da26c57bff7 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -9754,7 +9754,7 @@ static void wlan_hdd_restart_sap(hdd_adapter_t *ap_adapter) hdd_hostapd_state_t *pHostapdState; VOS_STATUS vos_status; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(ap_adapter); -#ifdef CFG80211_DEL_STA_V2 +#ifdef USE_CFG80211_DEL_STA_V2 struct station_del_parameters delStaParams; #endif tsap_Config_t *pConfig; @@ -9764,7 +9764,7 @@ static void wlan_hdd_restart_sap(hdd_adapter_t *ap_adapter) mutex_lock(&pHddCtx->sap_lock); if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) { -#ifdef CFG80211_DEL_STA_V2 +#ifdef USE_CFG80211_DEL_STA_V2 delStaParams.mac = NULL; delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4; delStaParams.reason_code = eCsrForcedDeauthSta; @@ -10182,6 +10182,74 @@ struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy, } #endif +#if defined(CFG80211_CONNECT_BSS) || \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) || \ + defined (CFG80211_CONNECT_TIMEOUT_REASON_CODE) +/** + * hdd_connect_bss() - helper function to send connection status to supplicant + * @dev: network device + * @bssid: bssid to which we want to associate + * @bss: information about connected bss + * @req_ie: Request Information Element + * @req_ie_len: len of the req IE + * @resp_ie: Response IE + * @resp_ie_len: len of ht response IE + * @status: status + * @gfp: Kernel Flag + * + * This is a helper function to send connection status to supplicant + * and gets invoked from wrapper API + * + * Return: Void + */ +static void hdd_connect_bss(struct net_device *dev, + const u8 *bssid, + struct cfg80211_bss *bss, + const u8 *req_ie, + size_t req_ie_len, + const u8 *resp_ie, + size_t resp_ie_len, + u16 status, + gfp_t gfp) +{ + cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len, + resp_ie, resp_ie_len, status, gfp, NL80211_TIMEOUT_UNSPECIFIED); +} +#else +/** + * hdd_connect_bss() - helper function to send connection status to supplicant + * @dev: network device + * @bssid: bssid to which we want to associate + * @bss: information about connected bss + * @req_ie: Request Information Element + * @req_ie_len: len of the req IE + * @resp_ie: Response IE + * @resp_ie_len: len of ht response IE + * @status: status + * @gfp: Kernel Flag + * + * This is a helper function to send connection status to supplicant + * and gets invoked from wrapper API + * + * Return: Void + */ +static void hdd_connect_bss(struct net_device *dev, + const u8 *bssid, + struct cfg80211_bss *bss, + const u8 *req_ie, + size_t req_ie_len, + const u8 *resp_ie, + size_t resp_ie_len, + u16 status, + gfp_t gfp) +{ + cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len, + resp_ie, resp_ie_len, status, gfp); +} +#endif + /** * hdd_connect_result() - API to send connection status to supplicant * @dev: network device @@ -10198,7 +10266,6 @@ struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy, * * Return: Void */ -#if defined CFG80211_CONNECT_BSS void hdd_connect_result(struct net_device *dev, const u8 *bssid, tCsrRoamInfo *roam_info, @@ -10219,10 +10286,10 @@ void hdd_connect_result(struct net_device *dev, if (chan_no <= 14) freq = ieee80211_channel_to_frequency(chan_no, - IEEE80211_BAND_2GHZ); + HDD_NL80211_BAND_2GHZ); else freq = ieee80211_channel_to_frequency(chan_no, - IEEE80211_BAND_5GHZ); + HDD_NL80211_BAND_5GHZ); chan = ieee80211_get_channel(padapter->wdev.wiphy, freq); bss = hdd_get_bss_entry(padapter->wdev.wiphy, @@ -10231,10 +10298,26 @@ void hdd_connect_result(struct net_device *dev, roam_info->u.pConnectedProfile->SSID.length); } - cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len, - resp_ie, resp_ie_len, status, gfp); + hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie, resp_ie_len, + status, gfp); } #else +/** + * hdd_connect_result() - API to send connection status to supplicant + * @dev: network device + * @bssid: bssid to which we want to associate + * @roam_info: information about connected bss + * @req_ie: Request Information Element + * @req_ie_len: len of the req IE + * @resp_ie: Response IE + * @resp_ie_len: len of ht response IE + * @status: status + * @gfp: Kernel Flag + * + * The API is a wrapper to send connection status to supplicant + * + * Return: Void + */ void hdd_connect_result(struct net_device *dev, const u8 *bssid, tCsrRoamInfo *roam_info, @@ -11115,7 +11198,7 @@ void wlan_hdd_mon_close(hdd_context_t *pHddCtx) void hdd_wlan_free_wiphy_channels(struct wiphy *wiphy) { int i =0; - for (i = 0; i < IEEE80211_NUM_BANDS; i++) + for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) { if (NULL != wiphy->bands[i] && (NULL != wiphy->bands[i]->channels)) diff --git a/CORE/HDD/src/wlan_hdd_p2p.c b/CORE/HDD/src/wlan_hdd_p2p.c index eb2d98c807820..0b47a919badc1 100644 --- a/CORE/HDD/src/wlan_hdd_p2p.c +++ b/CORE/HDD/src/wlan_hdd_p2p.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -2253,23 +2253,30 @@ wlan_hdd_add_monitor_check(hdd_context_t *hdd_ctx, hdd_adapter_t **adapter, return 0; } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) -struct wireless_dev* __wlan_hdd_add_virtual_intf( - struct wiphy *wiphy, const char *name, - enum nl80211_iftype type, - u32 *flags, struct vif_params *params ) -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) -struct wireless_dev* __wlan_hdd_add_virtual_intf( - struct wiphy *wiphy, char *name, enum nl80211_iftype type, - u32 *flags, struct vif_params *params ) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) +static struct wireless_dev * +__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) -struct net_device* __wlan_hdd_add_virtual_intf( - struct wiphy *wiphy, char *name, enum nl80211_iftype type, - u32 *flags, struct vif_params *params ) +static struct net_device * +__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) #else -int __wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name, - enum nl80211_iftype type, - u32 *flags, struct vif_params *params ) +static int +__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) #endif { hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); @@ -2393,47 +2400,129 @@ int __wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name, #endif } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) -struct wireless_dev* wlan_hdd_add_virtual_intf( - struct wiphy *wiphy, const char *name, - enum nl80211_iftype type, - u32 *flags, struct vif_params *params ) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) +struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + struct vif_params *params) +{ + struct wireless_dev *wdev; + + vos_ssr_protect(__func__); + wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, + type, ¶ms->flags, params); + vos_ssr_unprotect(__func__); + + return wdev; +} +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || \ + defined(WITH_BACKPORTS) +/** + * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper + * @wiphy: wiphy pointer + * @name: User-visible name of the interface + * @name_assign_type: the name of assign type of the netdev + * @nl80211_iftype: (virtual) interface types + * @flags: monitor mode configuration flags (not used) + * @vif_params: virtual interface parameters (not used) + * + * Return: the pointer of wireless dev, otherwise ERR_PTR. + */ +struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) +{ + struct wireless_dev *wdev; + + vos_ssr_protect(__func__); + wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, + type, flags, params); + vos_ssr_unprotect(__func__); + return wdev; + +} +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) +/** + * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper + * @wiphy: wiphy pointer + * @name: User-visible name of the interface + * @nl80211_iftype: (virtual) interface types + * @flags: monitor mode configuration flags (not used) + * @vif_params: virtual interface parameters (not used) + * + * Return: the pointer of wireless dev, otherwise ERR_PTR. + */ +struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) +{ + struct wireless_dev *wdev; + unsigned char name_assign_type = 0; + + vos_ssr_protect(__func__); + wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type, + type, flags, params); + vos_ssr_unprotect(__func__); + return wdev; + +} + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) struct wireless_dev* wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name, enum nl80211_iftype type, u32 *flags, struct vif_params *params ) -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) -struct net_device* wlan_hdd_add_virtual_intf( - struct wiphy *wiphy, char *name, enum nl80211_iftype type, - u32 *flags, struct vif_params *params ) -#else -int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name, - enum nl80211_iftype type, - u32 *flags, struct vif_params *params ) -#endif { -#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))) - struct wireless_dev* wdev; -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) - struct net_device* ndev; -#else - int ret; -#endif - vos_ssr_protect(__func__); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) - wdev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params); - vos_ssr_unprotect(__func__); - return wdev; + struct wireless_dev *wdev; + unsigned char name_assign_type = 0; + + vos_ssr_protect(__func__); + wdev = __wlan_hdd_add_virtual_intf(wiphy, (const char *)name, + name_assign_type, + type, flags, params); + vos_ssr_unprotect(__func__); + return wdev; + +} + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) - ndev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params); - vos_ssr_unprotect(__func__); - return ndev; +struct net_device* wlan_hdd_add_virtual_intf(struct wiphy *wiphy, + char *name, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) +{ + struct net_device *ndev; + unsigned char name_assign_type = 0; + + vos_ssr_protect(__func__); + ndev = __wlan_hdd_add_virtual_intf(wiphy, (const char *)name, name_assign_type, + type, flags, params); + vos_ssr_unprotect(__func__); + return wdev; + +} #else - ret = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params); - vos_ssr_unprotect(__func__); - return ret; -#endif +int wlan_hdd_add_virtual_intf(struct wiphy *wiphy, char *name, + enum nl80211_iftype type, + u32 *flags, struct vif_params *params) +{ + int ret; + unsigned char name_assign_type = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_add_virtual_intf(wiphy, (const char *)name, name_assign_type, + type, flags, params); + vos_ssr_unprotect(__func__); + + return ret; } +#endif /** * hdd_delete_adapter() - stop and close adapter @@ -2723,12 +2812,12 @@ void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, if( rxChan <= MAX_NO_OF_2_4_CHANNELS ) { freq = ieee80211_channel_to_frequency( rxChan, - IEEE80211_BAND_2GHZ); + HDD_NL80211_BAND_2GHZ); } else { freq = ieee80211_channel_to_frequency( rxChan, - IEEE80211_BAND_5GHZ); + HDD_NL80211_BAND_5GHZ); } cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); diff --git a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c index 69d4c38b20674..d7f8e92be325d 100644 --- a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c +++ b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c @@ -573,7 +573,7 @@ int __hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) goto xmit_done; } } - dev->trans_start = jiffies; + netif_trans_update(dev); VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_LOW, "%s: exit", __func__); @@ -756,9 +756,7 @@ void __hdd_softap_tx_timeout(struct net_device *dev) int status = 0; hdd_context_t *pHddCtx; - VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, - "%s: Transmission timeout occurred jiffies %lu dev->trans_start %lu", - __func__, jiffies, dev->trans_start); + TX_TIMEOUT_TRACE(dev, VOS_MODULE_ID_HDD_DATA); if ( NULL == pAdapter ) { diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c index 21125ac6300b1..fd4306da6daab 100644 --- a/CORE/HDD/src/wlan_hdd_tx_rx.c +++ b/CORE/HDD/src/wlan_hdd_tx_rx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -787,7 +787,7 @@ void hdd_dump_dhcp_pkt(struct sk_buff *skb, int path) } } - dev->trans_start = jiffies; + netif_trans_update(dev); return NETDEV_TX_OK; } @@ -1097,7 +1097,7 @@ int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } } - dev->trans_start = jiffies; + netif_trans_update(dev); return NETDEV_TX_OK; } @@ -1154,9 +1154,7 @@ void __hdd_tx_timeout(struct net_device *dev) v_ULONG_t diff_in_jiffies = 0; hdd_station_ctx_t *pHddStaCtx = NULL; - VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, - "%s: Transmission timeout occurred jiffies %lu dev->trans_start %lu", - __func__,jiffies,dev->trans_start); + TX_TIMEOUT_TRACE(dev, VOS_MODULE_ID_HDD_DATA); if ( NULL == pAdapter ) { diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c index 5e09368c93058..acdbc6ddc9375 100644 --- a/CORE/SME/src/csr/csrApiRoam.c +++ b/CORE/SME/src/csr/csrApiRoam.c @@ -270,7 +270,9 @@ void csrRoamJoinRetryTimerHandler(void *pv); #endif void limInitOperatingClasses( tHalHandle hHal ); extern void SysProcessMmhMsg(tpAniSirGlobal pMac, tSirMsgQ* pMsg); +#ifdef WLAN_BTAMP_FEATURE extern void btampEstablishLogLinkHdlr(void* pMsg); +#endif static void csrSerDesUnpackDiassocRsp(tANI_U8 *pBuf, tSirSmeDisassocRsp *pRsp); void csrReinitPreauthCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand); @@ -11042,7 +11044,9 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) case eWNI_SME_BTAMP_LOG_LINK_IND: smsLog( pMac, LOG1, FL("Establish logical link req from HCI serialized through MC thread")); +#ifdef WLAN_BTAMP_FEATURE btampEstablishLogLinkHdlr( pSirMsg ); +#endif break; case eWNI_SME_RSSI_IND: smsLog( pMac, LOG1, FL("RSSI indication from TL serialized through MC thread")); diff --git a/CORE/SME/src/csr/csrNeighborRoam.c b/CORE/SME/src/csr/csrNeighborRoam.c index 8e98c5908b3ac..86632693ce4cb 100644 --- a/CORE/SME/src/csr/csrNeighborRoam.c +++ b/CORE/SME/src/csr/csrNeighborRoam.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1540,7 +1540,7 @@ static tANI_BOOLEAN csrNeighborRoamProcessScanResults(tpAniSirGlobal pMac, VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, FL("Scan result: BSSID "MAC_ADDRESS_STR" (Rssi %ld, Ch:%d)"), MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId), - abs(pScanResult->BssDescriptor.rssi), + (long)abs(pScanResult->BssDescriptor.rssi), pScanResult->BssDescriptor.channelId); if ((VOS_TRUE == vos_mem_compare(pScanResult->BssDescriptor.bssId, @@ -1787,7 +1787,7 @@ static tANI_BOOLEAN csrNeighborRoamProcessScanResults(tpAniSirGlobal pMac, { VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: [INFOLOG] potential candidate to roam immediately (diff=%ld, expected=%d)", - __func__, abs(abs(CurrAPRssi) - abs(pScanResult->BssDescriptor.rssi)), + __func__, (long)abs(abs(CurrAPRssi) - abs(pScanResult->BssDescriptor.rssi)), immediateRoamRssiDiff); roamNow = eANI_BOOLEAN_TRUE; } diff --git a/CORE/SVC/src/logging/wlan_logging_sock_svc.c b/CORE/SVC/src/logging/wlan_logging_sock_svc.c index 3ff9664229d3c..fd4898231f787 100644 --- a/CORE/SVC/src/logging/wlan_logging_sock_svc.c +++ b/CORE/SVC/src/logging/wlan_logging_sock_svc.c @@ -1,5 +1,5 @@ /* -* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved. +* Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -598,7 +598,7 @@ int wlan_log_to_user(VOS_TRACE_LEVEL log_level, char *to_be_sent, int length) local_time = (u32)(tv.tv_sec - (sys_tz.tz_minuteswest * 60)); rtc_time_to_tm(local_time, &tm); /* Firmware Time Stamp */ - qtimer_ticks = arch_counter_get_cntpct(); + qtimer_ticks = __vos_get_log_timestamp(); tlen = snprintf(tbuf, sizeof(tbuf), "[%02d:%02d:%02d.%06lu] [%016llX]" " [%.5s] ", tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec, @@ -1410,6 +1410,7 @@ int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf, int i, j = 0; unsigned long irq_flag; bool failure = FALSE; + struct log_msg *temp; pr_info("%s: Initalizing FEConsoleLog = %d NumBuff = %d\n", __func__, log_fe_to_console, num_buf); @@ -1501,10 +1502,12 @@ int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf, pr_err("%s: Could not Create LogMsg Thread Controller", __func__); spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag); - vfree(gplog_msg); + temp = gplog_msg; gplog_msg = NULL; gwlan_logging.pcur_node = NULL; spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag); + vfree(temp); + temp = NULL; return -ENOMEM; } wake_up_process(gwlan_logging.thread); @@ -1566,6 +1569,7 @@ int wlan_logging_sock_deactivate_svc(void) { unsigned long irq_flag; int i; + struct log_msg *temp; if (!gplog_msg) return 0; @@ -1582,10 +1586,12 @@ int wlan_logging_sock_deactivate_svc(void) wait_for_completion(&gwlan_logging.shutdown_comp); spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag); - vfree(gplog_msg); + temp = gplog_msg; gplog_msg = NULL; gwlan_logging.pcur_node = NULL; spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag); + vfree(temp); + temp = NULL; spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag); /* free allocated skb */ diff --git a/CORE/VOSS/inc/i_vos_lock.h b/CORE/VOSS/inc/i_vos_lock.h index 0a6610318152c..cc213f7d8e88f 100644 --- a/CORE/VOSS/inc/i_vos_lock.h +++ b/CORE/VOSS/inc/i_vos_lock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2015, 2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -46,11 +46,15 @@ #include #include #include -#if defined(WLAN_OPEN_SOURCE) + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && \ + defined(WLAN_OPEN_SOURCE) +#include +#include +#else #include #endif - /*-------------------------------------------------------------------------- Preprocessor definitions and constants ------------------------------------------------------------------------*/ @@ -73,12 +77,15 @@ typedef struct vos_lock_s typedef spinlock_t vos_spin_lock_t; #if defined(WLAN_OPEN_SOURCE) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) +typedef struct wakeup_source vos_wake_lock_t; +#else typedef struct wake_lock vos_wake_lock_t; +#endif #else typedef int vos_wake_lock_t; #endif - /*------------------------------------------------------------------------- Function declarations and documenation ------------------------------------------------------------------------*/ diff --git a/CORE/VOSS/inc/vos_api.h b/CORE/VOSS/inc/vos_api.h index 9754fcc3a1ae7..d6c17c5caf10e 100644 --- a/CORE/VOSS/inc/vos_api.h +++ b/CORE/VOSS/inc/vos_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -74,6 +74,7 @@ #include #include #include +#include /** * enum userspace_log_level - Log level at userspace @@ -545,4 +546,16 @@ v_U16_t vos_get_rate_from_rateidx(uint32 rateindex); */ v_BOOL_t vos_check_monitor_state(void); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +static inline uint64_t __vos_get_log_timestamp(void) +{ + return arch_counter_get_cntvct(); +} +#else +static inline uint64_t __vos_get_log_timestamp(void) +{ + return arch_counter_get_cntpct(); +} +#endif /* LINUX_VERSION_CODE */ + #endif // if !defined __VOS_NVITEM_H diff --git a/CORE/VOSS/inc/vos_lock.h b/CORE/VOSS/inc/vos_lock.h index 9cce9503ac55d..14dcd6819b302 100644 --- a/CORE/VOSS/inc/vos_lock.h +++ b/CORE/VOSS/inc/vos_lock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2015, 2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -307,4 +307,12 @@ VOS_STATUS vos_wake_lock_release(vos_wake_lock_t *pLock, uint32_t reason); ------------------------------------------------------------------------*/ VOS_STATUS vos_wake_lock_destroy(vos_wake_lock_t *pLock); +/** + * vos_wake_lock_active() - Check for wake lock state + * @lock: lock to be checked + * + * Return: If active return true else false + */ +bool vos_wake_lock_active(vos_wake_lock_t *lock); + #endif // __VOSS_LOCK_H diff --git a/CORE/VOSS/inc/vos_utils.h b/CORE/VOSS/inc/vos_utils.h index 59ce11261cc4d..ddb77f4d9fdb4 100644 --- a/CORE/VOSS/inc/vos_utils.h +++ b/CORE/VOSS/inc/vos_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016, 2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -76,11 +76,14 @@ Function declarations and documenation ------------------------------------------------------------------------*/ +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,19,0)) || \ + defined(WLAN_BTAMP_FEATURE) + VOS_STATUS vos_crypto_init( v_U32_t *phCryptProv ); VOS_STATUS vos_crypto_deinit( v_U32_t hCryptProv ); - +#endif /** * vos_rand_get_bytes @@ -97,6 +100,8 @@ VOS_STATUS vos_crypto_deinit( v_U32_t hCryptProv ); */ VOS_STATUS vos_rand_get_bytes( v_U32_t handle, v_U8_t *pbBuf, v_U32_t numBytes ); +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,19,0)) || \ + defined(WLAN_BTAMP_FEATURE) /** * vos_sha1_hmac_str @@ -169,6 +174,8 @@ VOS_STATUS vos_decrypt_AES(v_U32_t cryptHandle, /* Handle */ v_U8_t *pDecrypted, v_U8_t *pKey); /* pointer to authentication key */ +#endif + v_U8_t vos_chan_to_band(v_U32_t chan); void vos_get_wlan_unsafe_channel(v_U16_t *unsafeChannelList, v_U16_t buffer_size, v_U16_t *unsafeChannelCount); diff --git a/CORE/VOSS/src/vos_lock.c b/CORE/VOSS/src/vos_lock.c index 60e0c3dae1406..aaa9e50076b16 100644 --- a/CORE/VOSS/src/vos_lock.c +++ b/CORE/VOSS/src/vos_lock.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2015, 2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -482,6 +482,14 @@ VOS_STATUS vos_spin_lock_destroy(vos_spin_lock_t *pLock) return VOS_STATUS_SUCCESS; } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && \ + defined(WLAN_OPEN_SOURCE) +VOS_STATUS vos_wake_lock_init(vos_wake_lock_t *pLock, const char *name) +{ + wakeup_source_init(pLock, name); + return VOS_STATUS_SUCCESS; +} +#else /*-------------------------------------------------------------------------- \brief vos_wake_lock_init() - initializes a vOSS wake lock @@ -499,8 +507,18 @@ VOS_STATUS vos_wake_lock_init(vos_wake_lock_t *pLock, const char *name) #endif return VOS_STATUS_SUCCESS; } +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && \ + defined(WLAN_OPEN_SOURCE) +static const char *vos_wake_lock_name(vos_wake_lock_t *pLock) +{ + if (pLock->name) + return pLock->name; + return "UNNAMED_WAKELOCK"; +} +#else /*-------------------------------------------------------------------------- * vos_wake_lock_name() - This function returns the name of the wakelock * @pLock: Pointer to the wakelock @@ -521,7 +539,19 @@ static const char* vos_wake_lock_name(vos_wake_lock_t *pLock) return "UNNAMED_WAKELOCK"; #endif } +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && \ + defined(WLAN_OPEN_SOURCE) +VOS_STATUS vos_wake_lock_acquire(vos_wake_lock_t *pLock, uint32_t reason) +{ + vos_log_wlock_diag(reason, vos_wake_lock_name(pLock), + WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_TAKEN); + __pm_stay_awake(pLock); + return VOS_STATUS_SUCCESS; +} +#else /*-------------------------------------------------------------------------- \brief vos_wake_lock_acquire() - acquires a wake lock @@ -545,7 +575,21 @@ VOS_STATUS vos_wake_lock_acquire(vos_wake_lock_t *pLock, return VOS_STATUS_SUCCESS; } +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && \ + defined(WLAN_OPEN_SOURCE) +VOS_STATUS vos_wake_lock_timeout_release(vos_wake_lock_t *pLock, v_U32_t msec, + uint32_t reason) +{ + /* + * Wakelock for Rx is frequent. + * It is reported only during active debug + */ + __pm_wakeup_event(pLock, msec); + return VOS_STATUS_SUCCESS; +} +#else /*-------------------------------------------------------------------------- \brief vos_wake_lock_timeout_release() - release a wake lock with a timeout @@ -577,7 +621,19 @@ VOS_STATUS vos_wake_lock_timeout_release(vos_wake_lock_t *pLock, return VOS_STATUS_SUCCESS; } +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && \ + defined(WLAN_OPEN_SOURCE) +VOS_STATUS vos_wake_lock_release(vos_wake_lock_t *pLock, uint32_t reason) +{ + vos_log_wlock_diag(reason, vos_wake_lock_name(pLock), + WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_RELEASED); + __pm_relax(pLock); + return VOS_STATUS_SUCCESS; +} +#else /*-------------------------------------------------------------------------- \brief vos_wake_lock_release() - releases a wake lock @@ -602,7 +658,16 @@ VOS_STATUS vos_wake_lock_release(vos_wake_lock_t *pLock, uint32_t reason) } +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && \ + defined(WLAN_OPEN_SOURCE) +VOS_STATUS vos_wake_lock_destroy(vos_wake_lock_t *pLock) +{ + wakeup_source_trash(pLock); + return VOS_STATUS_SUCCESS; +} +#else /*-------------------------------------------------------------------------- \brief vos_wake_lock_destroy() - destroys a wake lock @@ -620,3 +685,20 @@ VOS_STATUS vos_wake_lock_destroy(vos_wake_lock_t *pLock) #endif return VOS_STATUS_SUCCESS; } +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && \ + defined(WLAN_OPEN_SOURCE) +bool vos_wake_lock_active(vos_wake_lock_t *lock) +{ + return lock->active; +} +#else +bool vos_wake_lock_active(vos_wake_lock_t *lock) +{ +#if defined(WLAN_OPEN_SOURCE) + return wake_lock_active(lock); +#endif + return false; +} +#endif diff --git a/CORE/VOSS/src/vos_nvitem.c b/CORE/VOSS/src/vos_nvitem.c index 307c594c62e82..ae26eff2ed4e7 100644 --- a/CORE/VOSS/src/vos_nvitem.c +++ b/CORE/VOSS/src/vos_nvitem.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -2820,11 +2820,11 @@ static int create_crda_regulatory_entry(struct wiphy *wiphy, /* 20MHz channels */ if (nBandCapability == eCSR_BAND_24) pr_info("BandCapability is set to 2G only.\n"); - for (i=0,m=0;ibands[i] == NULL) { @@ -3296,7 +3296,7 @@ v_BOOL_t vos_is_channel_valid_for_vht80(v_U32_t chan) if (chan <= RF_CHAN_14) return VOS_FALSE; - band = IEEE80211_BAND_5GHZ; + band = HDD_NL80211_BAND_5GHZ; freq = vos_chan_to_freq(chan); wiphy = pHddCtx->wiphy; @@ -3587,7 +3587,7 @@ int vos_update_nv_table_from_wiphy_band(void *hdd_ctx, hdd_context_t *pHddCtx = (hdd_context_t *)hdd_ctx; struct wiphy *wiphy = (struct wiphy *)pwiphy; - for (i = 0, m = 0; ibands[i] == NULL) @@ -3608,9 +3608,9 @@ int vos_update_nv_table_from_wiphy_band(void *hdd_ctx, for (j = 0; j < wiphy->bands[i]->n_channels; j++) { - if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == nBandCapability) + if (HDD_NL80211_BAND_2GHZ == i && eCSR_BAND_5G == nBandCapability) wiphy->bands[i]->channels[j].flags |= IEEE80211_CHAN_DISABLED; - else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == nBandCapability) + else if (HDD_NL80211_BAND_5GHZ == i && eCSR_BAND_24 == nBandCapability) wiphy->bands[i]->channels[j].flags |= IEEE80211_CHAN_DISABLED; /* k = (m + j) is internal current channel index for 20MHz channel @@ -4141,19 +4141,19 @@ int __wlan_hdd_linux_reg_notifier(struct wiphy *wiphy, (request->initiator == NL80211_REGDOM_SET_BY_USER)) { if ( pHddCtx->cfg_ini->gEnableStrictRegulatoryForFCC && - wiphy->bands[IEEE80211_BAND_5GHZ]) + wiphy->bands[HDD_NL80211_BAND_5GHZ]) { - for (j=0; jbands[IEEE80211_BAND_5GHZ]->n_channels; j++) + for (j=0; jbands[HDD_NL80211_BAND_5GHZ]->n_channels; j++) { // UNII-1 band channels are passive when domain is FCC. - if ((wiphy->bands[IEEE80211_BAND_5GHZ ]->channels[j].center_freq == 5180 || - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5200 || - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5220 || - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5240) && + if ((wiphy->bands[HDD_NL80211_BAND_5GHZ ]->channels[j].center_freq == 5180 || + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5200 || + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5220 || + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5240) && ((request->alpha2[0]== 'U'&& request->alpha2[1]=='S') && pHddCtx->nEnableStrictRegulatoryForFCC)) { - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN; + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN; } } } @@ -4249,7 +4249,7 @@ VOS_STATUS vos_init_wiphy_from_nv_bin(void) temp_reg_domain = cur_reg_domain = reg_domain; m = 0; - for (i = 0; i < IEEE80211_NUM_BANDS; i++) + for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) { if (wiphy->bands[i] == NULL) @@ -4655,7 +4655,7 @@ int __wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, settings. iwiphy->bands doesn't seem to set ht40 flags in kernel correctly, this may be fixed by later kernel */ - for (i = 0, m = 0; i < IEEE80211_NUM_BANDS; i++) + for (i = 0, m = 0; i < HDD_NUM_NL80211_BANDS; i++) { if (NULL == wiphy->bands[i]) { @@ -4680,7 +4680,7 @@ int __wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, // k = (m + j) is internal current channel index for 20MHz channel // n is internal channel index for corresponding 40MHz channel k = m + j; - if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == nBandCapability) // 5G only + if (HDD_NL80211_BAND_2GHZ == i && eCSR_BAND_5G == nBandCapability) // 5G only { // Enable social channels for P2P if ((2412 == wiphy->bands[i]->channels[j].center_freq || @@ -4696,7 +4696,7 @@ int __wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, } continue; } - else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == nBandCapability) // 2G only + else if (HDD_NL80211_BAND_5GHZ == i && eCSR_BAND_24 == nBandCapability) // 2G only { wiphy->bands[i]->channels[j].flags |= IEEE80211_CHAN_DISABLED; continue; @@ -4752,34 +4752,34 @@ int __wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, IOCTL operation is inactive */ if ( pHddCtx->cfg_ini->gEnableStrictRegulatoryForFCC && - wiphy->bands[IEEE80211_BAND_5GHZ]) + wiphy->bands[HDD_NL80211_BAND_5GHZ]) { - for (j=0; jbands[IEEE80211_BAND_5GHZ]->n_channels; j++) + for (j=0; jbands[HDD_NL80211_BAND_5GHZ]->n_channels; j++) { // UNII-1 band channels are passive when domain is FCC. - if ((wiphy->bands[IEEE80211_BAND_5GHZ ]->channels[j].center_freq == 5180 || - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5200 || - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5220 || - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5240) && + if ((wiphy->bands[HDD_NL80211_BAND_5GHZ ]->channels[j].center_freq == 5180 || + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5200 || + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5220 || + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5240) && ((domainIdCurrent == REGDOMAIN_FCC) && pHddCtx->nEnableStrictRegulatoryForFCC)) { - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN; + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN; } - else if ((wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5180 || - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5200 || - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5220 || - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5240) && + else if ((wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5180 || + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5200 || + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5220 || + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5240) && ((domainIdCurrent != REGDOMAIN_FCC) || !pHddCtx->nEnableStrictRegulatoryForFCC)) { - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; } //Marking channels 52-144 as Radar channels if they are enabled - k = wiphy->bands[IEEE80211_BAND_2GHZ]->n_channels + j; + k = wiphy->bands[HDD_NL80211_BAND_2GHZ]->n_channels + j; - if ((wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5260 || + if ((wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5260 || wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5280 || wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5300 || wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5320 || diff --git a/CORE/VOSS/src/vos_sched.h b/CORE/VOSS/src/vos_sched.h index 09b8038e1a904..0e5d612a5a981 100644 --- a/CORE/VOSS/src/vos_sched.h +++ b/CORE/VOSS/src/vos_sched.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -73,7 +73,15 @@ #include "i_vos_types.h" #include "i_vos_packet.h" #include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && \ + defined(WLAN_OPEN_SOURCE) +#include +#include +#else #include +#endif + #include diff --git a/CORE/VOSS/src/vos_utils.c b/CORE/VOSS/src/vos_utils.c index 879c376e18c00..9f36857b30226 100644 --- a/CORE/VOSS/src/vos_utils.c +++ b/CORE/VOSS/src/vos_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016, 2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -80,18 +80,20 @@ /*---------------------------------------------------------------------------- * Global Data Definitions * -------------------------------------------------------------------------*/ + +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,19,0)) || \ + defined(WLAN_BTAMP_FEATURE) extern struct crypto_ahash *wcnss_wlan_crypto_alloc_ahash(const char *alg_name, unsigned int type, unsigned int mask); - extern int wcnss_wlan_crypto_ahash_digest(struct ahash_request *req); extern void wcnss_wlan_crypto_free_ahash(struct crypto_ahash *tfm); extern int wcnss_wlan_crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen); extern struct crypto_ablkcipher *wcnss_wlan_crypto_alloc_ablkcipher(const char *alg_name, u32 type, u32 mask); -extern void wcnss_wlan_ablkcipher_request_free(struct ablkcipher_request *req); extern void wcnss_wlan_crypto_free_ablkcipher(struct crypto_ablkcipher *tfm); +extern void wcnss_wlan_ablkcipher_request_free(struct ablkcipher_request *req); /*---------------------------------------------------------------------------- * Static Variable Definitions @@ -142,6 +144,8 @@ VOS_STATUS vos_crypto_deinit( v_U32_t hCryptProv ) return ( uResult ); } +#endif + /*-------------------------------------------------------------------------- \brief vos_rand_get_bytes() - Generates random byte @@ -192,6 +196,8 @@ VOS_STATUS vos_rand_get_bytes( v_U32_t cryptHandle, v_U8_t *pbBuf, v_U32_t numBy } +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,19,0)) || \ + defined(WLAN_BTAMP_FEATURE) /** * vos_sha1_hmac_str * @@ -719,6 +725,8 @@ VOS_STATUS vos_decrypt_AES(v_U32_t cryptHandle, /* Handle */ return VOS_STATUS_SUCCESS; } +#endif + v_U8_t vos_chan_to_band(v_U32_t chan) { if (chan <= VOS_24_GHZ_CHANNEL_14) diff --git a/CORE/WDI/WPAL/src/wlan_qct_pal_timer.c b/CORE/WDI/WPAL/src/wlan_qct_pal_timer.c index 5e6e33aa25eb9..3b2107d2af2ca 100644 --- a/CORE/WDI/WPAL/src/wlan_qct_pal_timer.c +++ b/CORE/WDI/WPAL/src/wlan_qct_pal_timer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2017-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -40,6 +40,7 @@ #include "wlan_qct_pal_trace.h" #include "wlan_qct_os_status.h" #include "vos_threads.h" +#include "vos_api.h" #include #if defined(ANI_OS_TYPE_ANDROID) @@ -218,7 +219,7 @@ wpt_uint32 wpalGetSystemTime(void) #if defined(ANI_OS_TYPE_ANDROID) wpt_uint64 wpalGetArchCounterTime(void) { - return arch_counter_get_cntpct(); + return __vos_get_log_timestamp(); }/*wpalGetArchCounterTime*/ #else wpt_uint64 wpalGetArchCounterTime(void) diff --git a/Kbuild b/Kbuild index dfa683e678407..baadf2982f169 100644 --- a/Kbuild +++ b/Kbuild @@ -88,6 +88,8 @@ HAVE_CFG80211 := 0 endif endif + +ifeq ($(CONFIG_PRIMA_WLAN_BTAMP),y) ############ BAP ############ BAP_DIR := CORE/BAP BAP_INC_DIR := $(BAP_DIR)/inc @@ -116,6 +118,7 @@ BAP_OBJS := $(BAP_SRC_DIR)/bapApiData.o \ $(BAP_SRC_DIR)/bapRsnTxRx.o \ $(BAP_SRC_DIR)/btampFsm.o \ $(BAP_SRC_DIR)/btampHCI.o +endif ############ DXE ############ DXE_DIR := CORE/DXE @@ -136,8 +139,7 @@ HDD_SRC_DIR := $(HDD_DIR)/src HDD_INC := -I$(WLAN_ROOT)/$(HDD_INC_DIR) \ -I$(WLAN_ROOT)/$(HDD_SRC_DIR) -HDD_OBJS := $(HDD_SRC_DIR)/bap_hdd_main.o \ - $(HDD_SRC_DIR)/wlan_hdd_assoc.o \ +HDD_OBJS := $(HDD_SRC_DIR)/wlan_hdd_assoc.o \ $(HDD_SRC_DIR)/wlan_hdd_cfg.o \ $(HDD_SRC_DIR)/wlan_hdd_debugfs.o \ $(HDD_SRC_DIR)/wlan_hdd_dev_pwr.o \ @@ -156,6 +158,10 @@ HDD_OBJS := $(HDD_SRC_DIR)/bap_hdd_main.o \ $(HDD_SRC_DIR)/wlan_hdd_wmm.o \ $(HDD_SRC_DIR)/wlan_hdd_wowl.o +ifeq ($(CONFIG_PRIMA_WLAN_BTAMP),y) +HDD_OBJS += $(HDD_SRC_DIR)/bap_hdd_main.o +endif + ifeq ($(HAVE_CFG80211),1) HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_cfg80211.o \ $(HDD_SRC_DIR)/wlan_hdd_p2p.o @@ -500,8 +506,7 @@ RIVA_INC := -I$(WLAN_ROOT)/riva/inc LINUX_INC := -Iinclude/linux -INCS := $(BAP_INC) \ - $(DXE_INC) \ +INCS := $(DXE_INC) \ $(HDD_INC) \ $(LINUX_INC) \ $(MAC_INC) \ @@ -515,6 +520,10 @@ INCS := $(BAP_INC) \ $(WDA_INC) \ $(WDI_INC) +ifeq ($(CONFIG_PRIMA_WLAN_BTAMP),y) +INCS += $(BAP_INC) +endif + OBJS := $(BAP_OBJS) \ $(DXE_OBJS) \ $(HDD_OBJS) \ @@ -528,6 +537,10 @@ OBJS := $(BAP_OBJS) \ $(WDA_OBJS) \ $(WDI_OBJS) +ifeq ($(CONFIG_PRIMA_WLAN_BTAMP),y) +OBJS += $(BAP_OBJS) +endif + EXTRA_CFLAGS += $(INCS) EXTRA_CFLAGS += -fno-pic From 6ed92325a8ebbef586a0fab4c8582b99d68c6dec Mon Sep 17 00:00:00 2001 From: Tejaswi Tanikella Date: Tue, 23 Jan 2018 17:04:21 +0530 Subject: [PATCH 026/508] net: ping: check if length is non-zero before copy In ping_common_sendmsg icmphdr is copied from the iovec. If there is no payload, calling csum_partial_copy_fromiovecend() can cause stack out of bounds when offset is zero and iov->iov_len is zero. BUG: KASAN: stack-out-of-bounds in csum_partial_copy_fromiovecend+0xc4/0x3f4 at addr ffffffc04cd7bd78 Read of size 8 by task WiFiArpStateMac/2306 page:ffffffba43fd4490 count:0 mapcount:0 mapping: (null) index:0x0 flags: 0x0() page dumped because: kasan: bad access detected [] dump_backtrace+0x0/0x200 [] show_stack+0x14/0x1c [] dump_stack+0x80/0xa4 [] kasan_report+0x3c0/0x508 [] __asan_load8+0x24/0x70 [] csum_partial_copy_fromiovecend+0xc4/0x3f4 [] ping_getfrag+0x58/0xf0 [] __ip_append_data.isra.2+0x8a4/0xe64 [] ip_append_data.part.3+0xd0/0xf0 [] ip_append_data+0x1c/0x30 [] ping_v4_sendmsg+0x5b0/0x700 [] inet_sendmsg+0xe0/0x128 [] sock_sendmsg+0x13c/0x190 [] SyS_sendto+0x194/0x20 Change-Id: Ia4dc47611ed2172cdc504920c20b8fec8c324c91 Acked-by: Sharath Chandra Vurukala Signed-off-by: Tejaswi Tanikella --- net/ipv4/ping.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 397be62e30a14..420e51112e60f 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -611,9 +611,12 @@ int ping_getfrag(void *from, char *to, if (offset == 0) { if (fraglen < sizeof(struct icmphdr)) BUG(); - if (csum_partial_copy_fromiovecend(to + sizeof(struct icmphdr), - pfh->iov, 0, fraglen - sizeof(struct icmphdr), - &pfh->wcheck)) + if ((fraglen - sizeof(struct icmphdr)) && + csum_partial_copy_fromiovecend + (to + sizeof(struct icmphdr), + pfh->iov, 0, + fraglen - sizeof(struct icmphdr), + &pfh->wcheck)) return -EFAULT; } else if (offset < sizeof(struct icmphdr)) { BUG(); From 2e45e7d936d049d97b6e6f45e43cef36e03731cf Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Mon, 29 Jan 2018 14:43:14 +0530 Subject: [PATCH 027/508] wlan: Disconnect the connected sta, when added in into blacklist Driver doesnt disconnect the connected sta, when the sta is added into blacklist and thus the sta remains connected even after being added into blacklist. As fix disconnect the sta, when it is added in into blacklist. Change-Id: I9d7f33a58c77f08e27f759c8c53cbb4f03b81a14 CRs-Fixed: 2180113 --- CORE/SAP/src/sapModule.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/CORE/SAP/src/sapModule.c b/CORE/SAP/src/sapModule.c index 971ea3ddc80ca..e4a1e9a3c93af 100644 --- a/CORE/SAP/src/sapModule.c +++ b/CORE/SAP/src/sapModule.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1192,6 +1192,8 @@ WLANSAP_ModifyACL MAC_ADDR_ARRAY(pPeerStaMac)); } else { + struct tagCsrDelStaParams delStaParams; + if (staInWhiteList) { //remove it from white list before adding to the white list @@ -1199,6 +1201,15 @@ WLANSAP_ModifyACL "Present in white list so first remove from it"); sapRemoveMacFromACL(pSapCtx->acceptMacList, &pSapCtx->nAcceptMac, staWLIndex); } + /* + * If we are adding a client to the black list; + * if its connected, send deauth + */ + WLANSAP_PopulateDelStaParams(pPeerStaMac, + eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, + SIR_MAC_MGMT_DEAUTH >> 4, + &delStaParams); + WLANSAP_DeauthSta(pSapCtx->pvosGCtx, &delStaParams); VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "... Now add to black list"); sapAddMacToACL(pSapCtx->denyMacList, &pSapCtx->nDenyMac, pPeerStaMac); From 77089a8d902c9b1ae4d86f87a0cbce5fa79ba803 Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Fri, 10 Nov 2017 14:20:32 -0800 Subject: [PATCH 028/508] usb: f_gsi: Use required RNDIS IAD descriptors with full speed descriptors gsi_eth_fs_function is array of pointers to set of RNDIS interface related descriptors. gsi_eth_fs_function's first descriptor is pointing itself instead of required RNDIS IAD descriptor. This results into out-of-bound read access while copying these set of descriptors with usb_copy_descriptors() API. Fix this issue by using required RNDIS IAD descriptor here. Change-Id: Ic604221febc43eb8a22d8de99fb8cead74e13b41 Signed-off-by: Mayank Rana --- drivers/usb/gadget/function/f_gsi.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h index 2a4944cb128f6..c64b8f8328b28 100644 --- a/drivers/usb/gadget/function/f_gsi.h +++ b/drivers/usb/gadget/function/f_gsi.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. - + * Copyright (c) 2015-2016, 2018 The Linux Foundation. All rights reserved. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. @@ -519,7 +519,7 @@ static struct usb_endpoint_descriptor rndis_gsi_fs_out_desc = { }; static struct usb_descriptor_header *gsi_eth_fs_function[] = { - (struct usb_descriptor_header *) &gsi_eth_fs_function, + (struct usb_descriptor_header *) &rndis_gsi_iad_descriptor, /* control interface matches ACM, not Ethernet */ (struct usb_descriptor_header *) &rndis_gsi_control_intf, (struct usb_descriptor_header *) &rndis_gsi_header_desc, From a3519994293fbb976bd7cf3b4c2e37aad182590e Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Tue, 16 Jan 2018 14:51:15 +0530 Subject: [PATCH 029/508] dwc3: debugfs: Add check for length before copy data from userspace Add boundary check before copying data from userspace buffer to dwc3 local buffer. The third parameter passed to copy_from_user() should be minimum of the two values between userpsace buffer size count and (local_buffer size - 1). The last one byte in local_buffer should be reserved for null terminator. Change-Id: I9b2e3db4d5ad6b5f14515cadafa6264f9e8b786c Signed-off-by: Vijayavardhan Vennapusa --- drivers/usb/dwc3/debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index fb252ecc9a971..9beaebc0eb806 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -634,7 +634,7 @@ static ssize_t dwc3_store_ep_num(struct file *file, const char __user *ubuf, unsigned int num, dir, temp; unsigned long flags; - if (copy_from_user(kbuf, ubuf, count > 10 ? 10 : count)) + if (copy_from_user(kbuf, ubuf, min_t(size_t, sizeof(kbuf) - 1, count))) return -EFAULT; if (sscanf(kbuf, "%u %u", &num, &dir) != 2) From a56f8b17dad1365b7f35e5d8765dcef83c0604da Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Sirasanagandla Date: Wed, 31 Jan 2018 17:33:38 +0530 Subject: [PATCH 030/508] wlan: Disable channels 120, 124, 128 in strict FCC Regd In Strict FCC regulatory domain, channels 120, 124 and 128 should be disabled in wiphy channel flags as per NV table when gEnableStrictRegulatoryForFCC is enabled, but these flags are overwritten by cfg80211 regulatory implementation due to regulatory_hint of driver. To fix this, disable respective channels in Strict FCC in __wlan_hdd_linux_reg_notifier(). Change-Id: I7fb30a1cb76df02d756c48209922025e59d6b2be CRs-Fixed: 2181543 --- CORE/VOSS/src/vos_nvitem.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CORE/VOSS/src/vos_nvitem.c b/CORE/VOSS/src/vos_nvitem.c index ae26eff2ed4e7..df980c51ade22 100644 --- a/CORE/VOSS/src/vos_nvitem.c +++ b/CORE/VOSS/src/vos_nvitem.c @@ -3965,6 +3965,34 @@ static int create_linux_regulatory_entry(struct wiphy *wiphy, } +static void +wlan_hdd_disable_fcc_5600_5640(hdd_context_t *hdd_ctx, struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_channel *channels; + uint32_t no_channels; + uint32_t i; + + if (cur_reg_domain != REGDOMAIN_FCC || + !hdd_ctx->cfg_ini->gEnableStrictRegulatoryForFCC || + !wiphy->bands[HDD_NL80211_BAND_5GHZ]) + return; + + channels = wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels; + no_channels = wiphy->bands[HDD_NL80211_BAND_5GHZ]->n_channels; + + for (i = 0; i < no_channels; i++) { + if (channels[i].center_freq != 5600 && + channels[i].center_freq != 5620 && + channels[i].center_freq != 5640) + continue; + + channels[i].flags |= IEEE80211_CHAN_DISABLED; + if (request->initiator == NL80211_REGDOM_SET_BY_DRIVER) + channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; + } +} + /* * Function: wlan_hdd_linux_reg_notifier * This function is called from cfg80211 core to provide regulatory settings @@ -4157,6 +4185,8 @@ int __wlan_hdd_linux_reg_notifier(struct wiphy *wiphy, } } } + + wlan_hdd_disable_fcc_5600_5640(pHddCtx, wiphy, request); } do_comp: if ((request->initiator == NL80211_REGDOM_SET_BY_DRIVER) || From 94016e8d521874f4df212192af55eee049763add Mon Sep 17 00:00:00 2001 From: Xiaoyu Ye Date: Mon, 15 Jan 2018 16:10:30 -0800 Subject: [PATCH 031/508] ASoC: wcd_cpe_core: add size check for WDSP ELF files Add size check to make sure the data sizes from WDSP ELF metadata and the split firmware ELF are the same. Change-Id: Ic2f7dc04dfc95608302cba23461c519378619db0 Signed-off-by: Xiaoyu Ye --- sound/soc/codecs/wcd_cpe_core.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wcd_cpe_core.c b/sound/soc/codecs/wcd_cpe_core.c index 0f680b2f03625..c43638f7cc1d1 100644 --- a/sound/soc/codecs/wcd_cpe_core.c +++ b/sound/soc/codecs/wcd_cpe_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -337,6 +337,14 @@ static int wcd_cpe_load_each_segment(struct wcd_cpe_core *core, goto done; } + if (phdr->p_filesz != split_fw->size) { + dev_err(core->dev, + "%s: %s size mismatch, phdr_size: 0x%x fw_size: 0x%zx", + __func__, split_fname, phdr->p_filesz, split_fw->size); + ret = -EINVAL; + goto done; + } + segment->cpe_addr = phdr->p_paddr; segment->size = phdr->p_filesz; segment->data = (u8 *) split_fw->data; From e6ecbd373f2d1943bc4a197b81e9eb1919287d0a Mon Sep 17 00:00:00 2001 From: Vijayanand Jitta Date: Mon, 29 Jan 2018 10:44:39 +0530 Subject: [PATCH 032/508] ARM: dts: msm: Reduce modem carveout size for apq8053 Reduce modem carveout size from 30 MB to 24 MB due to modem optimizations for apq8053. Change-Id: Ifdd10ed187fb2ec3fc88a198ee8f7e5aa5732a61 Signed-off-by: Vijayanand Jitta --- arch/arm/boot/dts/qcom/apq8053-iot-memory.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/qcom/apq8053-iot-memory.dtsi b/arch/arm/boot/dts/qcom/apq8053-iot-memory.dtsi index f6e26b223bf02..4a6f4a39cd495 100644 --- a/arch/arm/boot/dts/qcom/apq8053-iot-memory.dtsi +++ b/arch/arm/boot/dts/qcom/apq8053-iot-memory.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -12,14 +12,14 @@ */ &modem_mem { - reg = <0x0 0x86c00000 0x0 0x1e00000>; + reg = <0x0 0x86c00000 0x0 0x1800000>; }; &adsp_fw_mem { - reg = <0x0 0x88a00000 0x0 0x1100000>; + reg = <0x0 0x88400000 0x0 0x1100000>; }; &wcnss_fw_mem { - reg = <0x0 0x89b00000 0x0 0x700000>; + reg = <0x0 0x89500000 0x0 0x700000>; }; From bd0cf7b2c4f2e6a2432611270f97cfb36653404c Mon Sep 17 00:00:00 2001 From: Divya Ojha Date: Thu, 25 Aug 2016 15:25:51 +0530 Subject: [PATCH 033/508] ARM: dts: msm: update micbias type for 8937/53/17 CDP 8937/53/17 CDP uses external bias resistor. Hence change micbias type to external. CRs-fixed: 1045680 Change-Id: I7ca26e9b37e5730e8c8b7b1640fb7c55ad2fe532 Signed-off-by: Divya Ojha --- arch/arm/boot/dts/qcom/msm8917-audio-cdp.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8937-audio-cdp.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8953-audio-cdp.dtsi | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8917-audio-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8917-audio-cdp.dtsi index a0de690d101c1..02b8f5bf0221d 100644 --- a/arch/arm/boot/dts/qcom/msm8917-audio-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8917-audio-cdp.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -13,7 +13,7 @@ &int_codec { status = "okay"; - qcom,msm-hs-micbias-type = "internal"; + qcom,msm-hs-micbias-type = "external"; asoc-wsa-codec-names = "wsa881x-i2c-codec.2-000f"; asoc-wsa-codec-prefixes = "SpkrMono"; diff --git a/arch/arm/boot/dts/qcom/msm8937-audio-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8937-audio-cdp.dtsi index c181a81d77417..c97c40963059f 100644 --- a/arch/arm/boot/dts/qcom/msm8937-audio-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8937-audio-cdp.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -13,7 +13,7 @@ &int_codec { status = "okay"; - qcom,msm-hs-micbias-type = "internal"; + qcom,msm-hs-micbias-type = "external"; asoc-wsa-codec-names = "wsa881x-i2c-codec.2-000f"; asoc-wsa-codec-prefixes = "SpkrMono"; diff --git a/arch/arm/boot/dts/qcom/msm8953-audio-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8953-audio-cdp.dtsi index 91eb8c6e2bfe0..0452b5aaad931 100644 --- a/arch/arm/boot/dts/qcom/msm8953-audio-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-audio-cdp.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -13,7 +13,7 @@ &int_codec { status = "okay"; - qcom,msm-hs-micbias-type = "internal"; + qcom,msm-hs-micbias-type = "external"; }; &pm8953_diangu_dig { From 44e3a1c7f5d88e6e5f830bf690944e3e6c6f9c96 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 26 Nov 2015 14:00:47 +0200 Subject: [PATCH 034/508] mmc: sdio: Fix invalid vdd in voltage switch power cycle [ Upstream commit d9bfbb95ed598a09cf336adb0f190ee0ff802f0d ] The 'ocr' parameter passed to mmc_set_signal_voltage() defines the power-on voltage used when power cycling after a failure to set the voltage. However, in the case of mmc_sdio_init_card(), the value passed has the R4_18V_PRESENT flag set which is not valid for power-on and results in an invalid vdd. Fix by passing the card's ocr value which does not have the flag. Signed-off-by: Adrian Hunter Cc: stable@vger.kernel.org # v3.13+ Signed-off-by: Ulf Hansson Signed-off-by: Sasha Levin Git-commit: e6cbcb008a279d7794fba01799ecfb6be391484f Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git Change-Id: I1d49eed013cabd918e18450593fd4a7dcdf03ef9 Signed-off-by: Veerabhadrarao Badiganti --- drivers/mmc/core/sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 486d7c427e3a5..5651cf63f8bd7 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -742,7 +742,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, */ if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) { err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, - ocr); + ocr_card); if (err == -EAGAIN) { sdio_reset(host); mmc_go_idle(host); From 19813af06fdc4193a8d80be2ccbcd15e8bcdec30 Mon Sep 17 00:00:00 2001 From: Ganesh Kondabattini Date: Thu, 25 Jan 2018 17:32:44 +0530 Subject: [PATCH 035/508] wlan: Disconnect STA interface if it is on indoor channel If force scc is enabled for STA+SAP concurrency and SAP not allowed on indoor channels then STA should be disconnected first if it is on indoor channel before starting the SAP. CRs-Fixed: 2178961 Change-Id: If0985b559030b44834df851e170f320c7f942036 --- CORE/HDD/src/wlan_hdd_cfg80211.c | 297 ++++++++++++++++++------------- 1 file changed, 171 insertions(+), 126 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index a3ef1946adc31..21895be2e4f54 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -10347,6 +10347,173 @@ void hdd_update_indoor_channel(hdd_context_t *hdd_ctx, EXIT(); } +/* + * FUNCTION: wlan_hdd_disconnect + * This function is used to issue a disconnect request to SME + */ +int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason ) +{ + int status, result = 0; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + long ret; + eConnectionState prev_conn_state; + uint32_t wait_time = WLAN_WAIT_TIME_DISCONNECT; + + ENTER(); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + { + return status; + } + /* Indicate sme of disconnect so that in progress connection or preauth + * can be aborted + */ + sme_abortConnection(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId); + pHddCtx->isAmpAllowed = VOS_TRUE; + + /* Need to apply spin lock before decreasing active sessions + * as there can be chance for double decrement if context switch + * Calls hdd_DisConnectHandler. + */ + + prev_conn_state = pHddStaCtx->conn_info.connState; + + spin_lock_bh(&pAdapter->lock_for_active_session); + if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) + { + wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode); + } + hdd_connSetConnectionState( pHddStaCtx, eConnectionState_Disconnecting ); + spin_unlock_bh(&pAdapter->lock_for_active_session); + vos_flush_delayed_work(&pHddCtx->ecsa_chan_change_work); + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL( "Set HDD connState to eConnectionState_Disconnecting" )); + + INIT_COMPLETION(pAdapter->disconnect_comp_var); + + /* + * stop tx queues before deleting STA/BSS context from the firmware. + * tx has to be disabled because the firmware can get busy dropping + * the tx frames after BSS/STA has been deleted and will not send + * back a response resulting in WDI timeout + */ + hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues")); + netif_tx_disable(pAdapter->dev); + netif_carrier_off(pAdapter->dev); + + wlan_hdd_check_and_stop_mon(pAdapter, true); + + /*issue disconnect*/ + status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, reason); + if((eHAL_STATUS_CMD_NOT_QUEUED == status) && + prev_conn_state != eConnectionState_Connecting) + { + hddLog(LOG1, + FL("status = %d, already disconnected"), status); + result = 0; + /* + * Wait here instead of returning directly. This will block the + * next connect command and allow processing of the disconnect + * in SME else we might hit some race conditions leading to SME + * and HDD out of sync. As disconnect is already in progress, + * wait here for 1 sec instead of 5 sec. + */ + wait_time = WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS; + goto wait_for_disconnect; + } + /* + * Wait here instead of returning directly, this will block the next + * connect command and allow processing of the scan for ssid and + * the previous connect command in CSR. Else we might hit some + * race conditions leading to SME and HDD out of sync. + */ + else if(eHAL_STATUS_CMD_NOT_QUEUED == status) + { + hddLog(LOG1, + FL("Already disconnected or connect was in sme/roam pending list and removed by disconnect")); + } + else if ( 0 != status ) + { + hddLog(LOGE, + FL("csrRoamDisconnect failure, returned %d"), + (int)status); + result = -EINVAL; + goto disconnected; + } +wait_for_disconnect: + ret = wait_for_completion_timeout(&pAdapter->disconnect_comp_var, + msecs_to_jiffies(wait_time)); + if (!ret && (eHAL_STATUS_CMD_NOT_QUEUED != status)) + { + hddLog(LOGE, + "%s: Failed to disconnect, timed out", __func__); + result = -ETIMEDOUT; + } +disconnected: + hddLog(LOG1, + FL("Set HDD connState to eConnectionState_NotConnected")); + pHddStaCtx->conn_info.connState = eConnectionState_NotConnected; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + /* Sending disconnect event to userspace for kernel version < 3.11 + * is handled by __cfg80211_disconnect call to __cfg80211_disconnected + */ + hddLog(LOG1, FL("Send disconnected event to userspace")); + + wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true, + WLAN_REASON_UNSPECIFIED); +#endif + + EXIT(); + return result; +} + +/* + * hdd_check_and_disconnect_sta_on_invalid_channel() - Disconnect STA if it is + * on indoor channel + * @hdd_ctx: pointer to hdd context + * + * STA should be disconnected before starting the SAP if it is on indoor + * channel. + * + * Return: void + */ +void hdd_check_and_disconnect_sta_on_invalid_channel(hdd_context_t *hdd_ctx) +{ + + hdd_adapter_t *sta_adapter; + tANI_U8 sta_chan; + + sta_chan = hdd_get_operating_channel(hdd_ctx, WLAN_HDD_INFRA_STATION); + + if (!sta_chan) { + hddLog(LOG1, FL("STA not connected")); + return; + } + + hddLog(LOG1, FL("STA connected on chan %hu"), sta_chan); + + if (sme_IsChannelValid(hdd_ctx->hHal, sta_chan)) { + hddLog(LOG1, FL("STA connected on chan %hu and it is valid"), + sta_chan); + return; + } + + sta_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION); + + if (!sta_adapter) { + hddLog(LOG1, FL("STA adapter doesn't exist")); + return; + } + + hddLog(LOG1, FL("chan %hu not valid, issue disconnect"), sta_chan); + /* Issue Disconnect request */ + wlan_hdd_disconnect(sta_adapter, eCSR_DISCONNECT_REASON_DEAUTH); +} #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, @@ -10399,6 +10566,10 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, FL("Can't start BSS: update channel list failed")); return eHAL_STATUS_FAILURE; } + + /* check if STA is on indoor channel */ + if (hdd_is_sta_sap_scc_allowed_on_dfs_chan(pHddCtx)) + hdd_check_and_disconnect_sta_on_invalid_channel(pHddCtx); } pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); @@ -16422,132 +16593,6 @@ static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, return ret; } -/* - * FUNCTION: wlan_hdd_disconnect - * This function is used to issue a disconnect request to SME - */ -int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason ) -{ - int status, result = 0; - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - long ret; - eConnectionState prev_conn_state; - uint32_t wait_time = WLAN_WAIT_TIME_DISCONNECT; - - ENTER(); - - status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) - { - return status; - } - /* Indicate sme of disconnect so that in progress connection or preauth - * can be aborted - */ - sme_abortConnection(WLAN_HDD_GET_HAL_CTX(pAdapter), - pAdapter->sessionId); - pHddCtx->isAmpAllowed = VOS_TRUE; - - /* Need to apply spin lock before decreasing active sessions - * as there can be chance for double decrement if context switch - * Calls hdd_DisConnectHandler. - */ - - prev_conn_state = pHddStaCtx->conn_info.connState; - - spin_lock_bh(&pAdapter->lock_for_active_session); - if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) - { - wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode); - } - hdd_connSetConnectionState( pHddStaCtx, eConnectionState_Disconnecting ); - spin_unlock_bh(&pAdapter->lock_for_active_session); - vos_flush_delayed_work(&pHddCtx->ecsa_chan_change_work); - - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - FL( "Set HDD connState to eConnectionState_Disconnecting" )); - - INIT_COMPLETION(pAdapter->disconnect_comp_var); - - /* - * stop tx queues before deleting STA/BSS context from the firmware. - * tx has to be disabled because the firmware can get busy dropping - * the tx frames after BSS/STA has been deleted and will not send - * back a response resulting in WDI timeout - */ - hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues")); - netif_tx_disable(pAdapter->dev); - netif_carrier_off(pAdapter->dev); - - wlan_hdd_check_and_stop_mon(pAdapter, true); - - /*issue disconnect*/ - status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), - pAdapter->sessionId, reason); - if((eHAL_STATUS_CMD_NOT_QUEUED == status) && - prev_conn_state != eConnectionState_Connecting) - { - hddLog(LOG1, - FL("status = %d, already disconnected"), status); - result = 0; - /* - * Wait here instead of returning directly. This will block the - * next connect command and allow processing of the disconnect - * in SME else we might hit some race conditions leading to SME - * and HDD out of sync. As disconnect is already in progress, - * wait here for 1 sec instead of 5 sec. - */ - wait_time = WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS; - goto wait_for_disconnect; - } - /* - * Wait here instead of returning directly, this will block the next - * connect command and allow processing of the scan for ssid and - * the previous connect command in CSR. Else we might hit some - * race conditions leading to SME and HDD out of sync. - */ - else if(eHAL_STATUS_CMD_NOT_QUEUED == status) - { - hddLog(LOG1, - FL("Already disconnected or connect was in sme/roam pending list and removed by disconnect")); - } - else if ( 0 != status ) - { - hddLog(LOGE, - FL("csrRoamDisconnect failure, returned %d"), - (int)status); - result = -EINVAL; - goto disconnected; - } -wait_for_disconnect: - ret = wait_for_completion_timeout(&pAdapter->disconnect_comp_var, - msecs_to_jiffies(wait_time)); - if (!ret && (eHAL_STATUS_CMD_NOT_QUEUED != status)) - { - hddLog(LOGE, - "%s: Failed to disconnect, timed out", __func__); - result = -ETIMEDOUT; - } -disconnected: - hddLog(LOG1, - FL("Set HDD connState to eConnectionState_NotConnected")); - pHddStaCtx->conn_info.connState = eConnectionState_NotConnected; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) - /* Sending disconnect event to userspace for kernel version < 3.11 - * is handled by __cfg80211_disconnect call to __cfg80211_disconnected - */ - hddLog(LOG1, FL("Send disconnected event to userspace")); - - wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true, - WLAN_REASON_UNSPECIFIED); -#endif - - EXIT(); - return result; -} - - /* * FUNCTION: __wlan_hdd_cfg80211_disconnect * This function is used to issue a disconnect request to SME From d18f0b3b18ea2bd1188e694d5dbd476195291f49 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Tue, 23 Jan 2018 17:33:02 +0530 Subject: [PATCH 036/508] msm: ipa: dynamic memory leak fix This is a fix for dynamic memory leak seen with incorrectly allocating memory of a different size than with intended size. Change-Id: I350719dadad9fd5c7f35a334e81c8d9f2298f888 Acked-by: Jyothi Jayanthi Acked-by: Ashok Vuyyuru Signed-off-by: Michael Adisumarta Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c index f7ac631dbb1f2..797f616c69df1 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -581,7 +581,8 @@ static void ipa_save_uc_smmu_mapping_pa(int res_idx, phys_addr_t pa, { IPADBG("--res_idx=%d pa=0x%pa iova=0x%lx sz=0x%zx\n", res_idx, &pa, iova, len); - wdi_res[res_idx].res = kzalloc(sizeof(struct ipa_wdi_res), GFP_KERNEL); + wdi_res[res_idx].res = kzalloc(sizeof(*wdi_res[res_idx].res), + GFP_KERNEL); if (!wdi_res[res_idx].res) BUG(); wdi_res[res_idx].nents = 1; @@ -607,8 +608,8 @@ static void ipa_save_uc_smmu_mapping_sgt(int res_idx, struct sg_table *sgt, return; } - wdi_res[res_idx].res = kcalloc(sgt->nents, sizeof(struct ipa_wdi_res), - GFP_KERNEL); + wdi_res[res_idx].res = kcalloc(sgt->nents, + sizeof(*wdi_res[res_idx].res), GFP_KERNEL); if (!wdi_res[res_idx].res) BUG(); wdi_res[res_idx].nents = sgt->nents; From 446b0f3c9d5af5f8546745c2bc111da6d58444cb Mon Sep 17 00:00:00 2001 From: DingXiang Date: Tue, 2 Feb 2016 12:29:18 +0800 Subject: [PATCH 037/508] dm snapshot: disallow the COW and origin devices from being identical Otherwise loading a "snapshot" table using the same device for the origin and COW devices, e.g.: echo "0 20971520 snapshot 253:3 253:3 P 8" | dmsetup create snap will trigger: BUG: unable to handle kernel NULL pointer dereference at 0000000000000098 [ 1958.979934] IP: [] dm_exception_store_set_chunk_size+0x7a/0x110 [dm_snapshot] [ 1958.989655] PGD 0 [ 1958.991903] Oops: 0000 [#1] SMP ... [ 1959.059647] CPU: 9 PID: 3556 Comm: dmsetup Tainted: G IO 4.5.0-rc5.snitm+ #150 ... [ 1959.083517] task: ffff8800b9660c80 ti: ffff88032a954000 task.ti: ffff88032a954000 [ 1959.091865] RIP: 0010:[] [] dm_exception_store_set_chunk_size+0x7a/0x110 [dm_snapshot] [ 1959.104295] RSP: 0018:ffff88032a957b30 EFLAGS: 00010246 [ 1959.110219] RAX: 0000000000000000 RBX: 0000000000000008 RCX: 0000000000000001 [ 1959.118180] RDX: 0000000000000000 RSI: 0000000000000008 RDI: ffff880329334a00 [ 1959.126141] RBP: ffff88032a957b50 R08: 0000000000000000 R09: 0000000000000001 [ 1959.134102] R10: 000000000000000a R11: f000000000000000 R12: ffff880330884d80 [ 1959.142061] R13: 0000000000000008 R14: ffffc90001c13088 R15: ffff880330884d80 [ 1959.150021] FS: 00007f8926ba3840(0000) GS:ffff880333440000(0000) knlGS:0000000000000000 [ 1959.159047] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1959.165456] CR2: 0000000000000098 CR3: 000000032f48b000 CR4: 00000000000006e0 [ 1959.173415] Stack: [ 1959.175656] ffffc90001c13040 ffff880329334a00 ffff880330884ed0 ffff88032a957bdc [ 1959.183946] ffff88032a957bb8 ffffffffa040f225 ffff880329334a30 ffff880300000000 [ 1959.192233] ffffffffa04133e0 ffff880329334b30 0000000830884d58 00000000569c58cf [ 1959.200521] Call Trace: [ 1959.203248] [] dm_exception_store_create+0x1d5/0x240 [dm_snapshot] [ 1959.211986] [] snapshot_ctr+0x140/0x630 [dm_snapshot] [ 1959.219469] [] ? dm_split_args+0x64/0x150 [dm_mod] [ 1959.226656] [] dm_table_add_target+0x177/0x440 [dm_mod] [ 1959.234328] [] table_load+0x143/0x370 [dm_mod] [ 1959.241129] [] ? retrieve_status+0x1b0/0x1b0 [dm_mod] [ 1959.248607] [] ctl_ioctl+0x255/0x4d0 [dm_mod] [ 1959.255307] [] ? memzero_explicit+0x12/0x20 [ 1959.261816] [] dm_ctl_ioctl+0x13/0x20 [dm_mod] [ 1959.268615] [] do_vfs_ioctl+0xa6/0x5c0 [ 1959.274637] [] ? __audit_syscall_entry+0xaf/0x100 [ 1959.281726] [] ? do_audit_syscall_entry+0x66/0x70 [ 1959.288814] [] SyS_ioctl+0x79/0x90 [ 1959.294450] [] entry_SYSCALL_64_fastpath+0x12/0x71 ... [ 1959.323277] RIP [] dm_exception_store_set_chunk_size+0x7a/0x110 [dm_snapshot] [ 1959.333090] RSP [ 1959.336978] CR2: 0000000000000098 [ 1959.344121] ---[ end trace b049991ccad1169e ]--- Change-Id: I03c690de6c1a2431adbaf000f6be1579d7be1b31 Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1195899 Cc: stable@vger.kernel.org Signed-off-by: Ding Xiang Signed-off-by: Mike Snitzer Git-commit: 4df2bf466a9c9c92f40d27c4aa9120f4e8227bfc Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Sachin Grover --- drivers/md/dm-snap.c | 9 ++++++++ drivers/md/dm-table.c | 41 ++++++++++++++++++++--------------- include/linux/device-mapper.h | 2 ++ 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index b91b39caf7a9f..81567634628a3 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -1099,6 +1099,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) int i; int r = -EINVAL; char *origin_path, *cow_path; + dev_t origin_dev, cow_dev; unsigned args_used, num_flush_bios = 1; fmode_t origin_mode = FMODE_READ; @@ -1129,11 +1130,19 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) ti->error = "Cannot get origin device"; goto bad_origin; } + origin_dev = s->origin->bdev->bd_dev; cow_path = argv[0]; argv++; argc--; + cow_dev = dm_get_dev_t(cow_path); + if (cow_dev && cow_dev == origin_dev) { + ti->error = "COW device cannot be the same as origin device"; + r = -EINVAL; + goto bad_cow; + } + r = dm_get_device(ti, cow_path, dm_table_get_mode(ti->table), &s->cow); if (r) { ti->error = "Cannot get COW device"; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 0f778784937d1..9642b379eb829 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -363,6 +363,26 @@ static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, return 0; } +/* + * Convert the path to a device + */ +dev_t dm_get_dev_t(const char *path) +{ + dev_t uninitialized_var(dev); + struct block_device *bdev; + + bdev = lookup_bdev(path); + if (IS_ERR(bdev)) + dev = name_to_dev_t(path); + else { + dev = bdev->bd_dev; + bdput(bdev); + } + + return dev; +} +EXPORT_SYMBOL_GPL(dm_get_dev_t); + /* * Add a device to the list, or just increment the usage count if * it's already present. @@ -371,28 +391,15 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode, struct dm_dev **result) { int r; - dev_t uninitialized_var(dev); + dev_t dev; struct dm_dev_internal *dd; - unsigned int major, minor; struct dm_table *t = ti->table; - char dummy; BUG_ON(!t); - if (sscanf(path, "%u:%u%c", &major, &minor, &dummy) == 2) { - /* Extract the major/minor numbers */ - dev = MKDEV(major, minor); - if (MAJOR(dev) != major || MINOR(dev) != minor) - return -EOVERFLOW; - } else { - /* convert the path to a device */ - struct block_device *bdev = lookup_bdev(path); - - if (IS_ERR(bdev)) - return PTR_ERR(bdev); - dev = bdev->bd_dev; - bdput(bdev); - } + dev = dm_get_dev_t(path); + if (!dev) + return -ENODEV; dd = find_device(&t->devices, dev); if (!dd) { diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 965cdf7f1ab01..082ec600c51e3 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -121,6 +121,8 @@ struct dm_dev { char name[16]; }; +dev_t dm_get_dev_t(const char *path); + /* * Constructors should call these functions to ensure destination devices * are opened/closed correctly. From f20db918b97f617356efe2794b9d720011e60ded Mon Sep 17 00:00:00 2001 From: Sachin Grover Date: Tue, 30 Jan 2018 15:19:13 +0530 Subject: [PATCH 038/508] defconfig: Add dm-verity related configs Add configs to support verity on apq8053. Change-Id: Icdcd89400dc7081d99205e9d2da09f664493be9d Signed-off-by: Sachin Grover --- arch/arm64/configs/apq8053_IoE-perf_defconfig | 6 +++++- arch/arm64/configs/msmcortex_defconfig | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/apq8053_IoE-perf_defconfig b/arch/arm64/configs/apq8053_IoE-perf_defconfig index ab2556f6703f0..beb2ade960326 100644 --- a/arch/arm64/configs/apq8053_IoE-perf_defconfig +++ b/arch/arm64/configs/apq8053_IoE-perf_defconfig @@ -245,12 +245,15 @@ CONFIG_SCSI_UFSHCD_PLATFORM=y CONFIG_SCSI_UFS_QCOM=y CONFIG_SCSI_UFS_QCOM_ICE=y CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=y CONFIG_DM_REQ_CRYPT=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y -CONFIG_DM_VERITY_FEC=y +CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE=1 +CONFIG_DM_ANDROID_VERITY=y CONFIG_NETDEVICES=y CONFIG_DUMMY=y CONFIG_TUN=y @@ -589,6 +592,7 @@ CONFIG_IPC_LOGGING=y CONFIG_CPU_FREQ_SWITCH_PROFILER=y CONFIG_DEBUG_SET_MODULE_RONX=y CONFIG_DEBUG_RODATA=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y CONFIG_LSM_MMAP_MIN_ADDR=4096 diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig index e71da71c255eb..6777866406915 100644 --- a/arch/arm64/configs/msmcortex_defconfig +++ b/arch/arm64/configs/msmcortex_defconfig @@ -254,12 +254,15 @@ CONFIG_SCSI_UFSHCD_PLATFORM=y CONFIG_SCSI_UFS_QCOM=y CONFIG_SCSI_UFS_QCOM_ICE=y CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=y CONFIG_DM_REQ_CRYPT=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y -CONFIG_DM_VERITY_FEC=y +CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE=1 +CONFIG_DM_ANDROID_VERITY=y CONFIG_NETDEVICES=y CONFIG_DUMMY=y CONFIG_TUN=y @@ -682,6 +685,7 @@ CONFIG_PANIC_ON_DATA_CORRUPTION=y CONFIG_DEBUG_SET_MODULE_RONX=y CONFIG_FREE_PAGES_RDONLY=y CONFIG_DEBUG_RODATA=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y From c121a4f765dd4c1807d0656fcd3219a2f1c28c38 Mon Sep 17 00:00:00 2001 From: Sachin Grover Date: Tue, 6 Feb 2018 12:56:26 +0530 Subject: [PATCH 039/508] defconfig: arm: Add dm-verity related configs Add configs to support verity on 32 bit apq8053. Change-Id: Iafaa4f49dd7f904905819b2a01487957d35b8f9d Signed-off-by: Sachin Grover --- arch/arm/configs/apq8053_IoE-perf_defconfig | 5 +++++ arch/arm/configs/msmcortex_defconfig | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/arch/arm/configs/apq8053_IoE-perf_defconfig b/arch/arm/configs/apq8053_IoE-perf_defconfig index fc40c2785112f..e816739bd31f0 100644 --- a/arch/arm/configs/apq8053_IoE-perf_defconfig +++ b/arch/arm/configs/apq8053_IoE-perf_defconfig @@ -250,11 +250,15 @@ CONFIG_SCSI_UFSHCD_PLATFORM=y CONFIG_SCSI_UFS_QCOM=y CONFIG_SCSI_UFS_QCOM_ICE=y CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=y CONFIG_DM_REQ_CRYPT=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE=1 +CONFIG_DM_ANDROID_VERITY=y CONFIG_DM_VERITY_FEC=y CONFIG_NETDEVICES=y CONFIG_DUMMY=y @@ -587,6 +591,7 @@ CONFIG_TIMER_STATS=y CONFIG_IPC_LOGGING=y CONFIG_CPU_FREQ_SWITCH_PROFILER=y CONFIG_DEBUG_SET_MODULE_RONX=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y CONFIG_LSM_MMAP_MIN_ADDR=4096 diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig index 97bf81865344f..1357b17ef3bb4 100644 --- a/arch/arm/configs/msmcortex_defconfig +++ b/arch/arm/configs/msmcortex_defconfig @@ -255,10 +255,14 @@ CONFIG_SCSI_UFSHCD_PLATFORM=y CONFIG_SCSI_UFS_QCOM=y CONFIG_SCSI_UFS_QCOM_ICE=y CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=y CONFIG_DM_REQ_CRYPT=y CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE=1 +CONFIG_DM_ANDROID_VERITY=y CONFIG_DM_VERITY_FEC=y CONFIG_NETDEVICES=y CONFIG_DUMMY=y @@ -647,6 +651,7 @@ CONFIG_LKDTM=y CONFIG_PANIC_ON_DATA_CORRUPTION=y CONFIG_DEBUG_USER=y CONFIG_DEBUG_SET_MODULE_RONX=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y From 75a45d15617896c163da060b230a82111ddbbd4a Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Tue, 6 Feb 2018 15:14:15 +0530 Subject: [PATCH 040/508] wlan: During GET_SNR IOCTL, do uninterruptible wait on completion variable On receiving GET_SNR IOCTL, HDD sends SME indication, with callback and local object, which holds completion variable and then wait on completion variable, which can be interruptible. As wait on completion variable is interruptible, there is a possibility of some task to interrupt, leading wait to exit and there by losing local object, which is accessed by callback(invoked on receiving SNR value), leading to out-of-bound issue. To mitigate this issue, while processing GET_SNR IOCTL, change wait on completion variable from interruptible to non-interruptible. Change-Id: I5ffbccc2fb80db639bb9e3656da1625ed8fc315c CRs-Fixed: 2184849 --- CORE/HDD/src/wlan_hdd_wext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 0aed5fc204aae..9459131730419 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -1227,7 +1227,7 @@ VOS_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, v_S7_t *snr) else { /* request was sent -- wait for the response */ - lrc = wait_for_completion_interruptible_timeout(&context.completion, + lrc = wait_for_completion_timeout(&context.completion, msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); if (lrc <= 0) { From 9575ee0b56219f58aa44e7d61f8394490a6e5fd2 Mon Sep 17 00:00:00 2001 From: "Padma, Santhosh Kumar" Date: Mon, 5 Feb 2018 18:05:01 +0530 Subject: [PATCH 041/508] wlan: Avoid buffer overflow qcacld-2.0 to prima propagation Add max check for probe request length against max length of probe request buffer to avoid buffer overflow. Change-Id: Ie0fad7443b2c749c66bb9ad662625a16d3a840c3 CRs-Fixed: 2184098 --- CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c b/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c index a3d8ef423d58c..a5b497add5db3 100644 --- a/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c +++ b/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -798,6 +798,10 @@ limSendSmeProbeReqInd(tpAniSirGlobal pMac, MTRACE(macTrace(pMac, TRACE_CODE_TX_SME_MSG, psessionEntry->peSessionId, msgQ.type)); + + if (ProbeReqIELen > sizeof(pSirSmeProbeReqInd->WPSPBCProbeReq.probeReqIE)) + ProbeReqIELen = sizeof(pSirSmeProbeReqInd->WPSPBCProbeReq.probeReqIE); + pSirSmeProbeReqInd->WPSPBCProbeReq.probeReqIELen = (tANI_U16)ProbeReqIELen; vos_mem_copy(pSirSmeProbeReqInd->WPSPBCProbeReq.probeReqIE, pProbeReqIE, ProbeReqIELen); From e5650256fcdde0bc5e458ba80f7841383bde378e Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Tue, 6 Feb 2018 15:14:15 +0530 Subject: [PATCH 042/508] wlan: During GET_SNR IOCTL, do uninterruptible wait on completion variable On receiving GET_SNR IOCTL, HDD sends SME indication, with callback and local object, which holds completion variable and then wait on completion variable, which can be interruptible. As wait on completion variable is interruptible, there is a possibility of some task to interrupt, leading wait to exit and there by losing local object, which is accessed by callback(invoked on receiving SNR value), leading to out-of-bound issue. To mitigate this issue, while processing GET_SNR IOCTL, change wait on completion variable from interruptible to non-interruptible. Change-Id: I5ffbccc2fb80db639bb9e3656da1625ed8fc315c CRs-Fixed: 2184849 --- CORE/HDD/src/wlan_hdd_wext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 0aed5fc204aae..9459131730419 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -1227,7 +1227,7 @@ VOS_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, v_S7_t *snr) else { /* request was sent -- wait for the response */ - lrc = wait_for_completion_interruptible_timeout(&context.completion, + lrc = wait_for_completion_timeout(&context.completion, msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); if (lrc <= 0) { From 04438afe597f44dfef60ac1a94863cb520bec0b7 Mon Sep 17 00:00:00 2001 From: Jitendra Sharma Date: Fri, 12 Jan 2018 11:55:55 +0530 Subject: [PATCH 043/508] Revert "ARM: dts: msm: Remove modem wdog property for SDX20" This reverts commit 1d218311b7d435809a6e1a6c1d851c04aa96caa9. Reverting this as now changes will be made to register modem wdog in HLOS side Change-Id: Iac20aba15cdf02ba7a15575d1166fff25b1920a5 Signed-off-by: Jitendra Sharma --- arch/arm/boot/dts/qcom/sdx20.dtsi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/qcom/sdx20.dtsi b/arch/arm/boot/dts/qcom/sdx20.dtsi index f45a695cebf6c..811eef6f2755e 100644 --- a/arch/arm/boot/dts/qcom/sdx20.dtsi +++ b/arch/arm/boot/dts/qcom/sdx20.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -392,7 +392,6 @@ &mss { /delete-property/qcom,qdsp6v61-1-1; qcom,qdsp6v62-1-4; - /delete-property/interrupts; }; &mhi_device { From cc71d68faef28d73954fc11487f59ee40ff0eda2 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Tue, 13 Sep 2016 11:16:06 +0100 Subject: [PATCH 044/508] UPSTREAM: arm64: tlbflush.h: add __tlbi() macro As with dsb() and isb(), add a __tlbi() helper so that we can avoid distracting asm boilerplate every time we want a TLBI. As some TLBI operations take an argument while others do not, some pre-processor is used to handle these two cases with different assembly blocks. The existing tlbflush.h code is moved over to use the helper. Signed-off-by: Mark Rutland Cc: Catalin Marinas Cc: Marc Zyngier [ rename helper to __tlbi, update comment and commit log ] Signed-off-by: Punit Agrawal Reviewed-by: Will Deacon Signed-off-by: Will Deacon (cherry picked from commit db68f3e7594aca77632d56c449bd36c6c931d59a) Signed-off-by: Greg Hackmann Change-Id: I9fc215c78f2ae648e4df6ba7189cec7e453800e4 Git-Commit: e0c5ba8cd917ff1bd7d6ea3925359b96650ecdfc Git-repo: git://android.googlesource.com/kernel/common.git [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/tlbflush.h | 38 +++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h index d937f518120f3..0e0fe68d21568 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h @@ -24,6 +24,24 @@ #include #include +/* + * Raw TLBI operations. + * + * Where necessary, use the __tlbi() macro to avoid asm() + * boilerplate. Drivers and most kernel code should use the TLB + * management routines in preference to the macro below. + * + * The macro can be used as __tlbi(op) or __tlbi(op, arg), depending + * on whether a particular TLBI operation takes an argument or + * not. The macros handles invoking the asm with or without the + * register argument as appropriate. + */ +#define __TLBI_0(op, arg) asm ("tlbi " #op) +#define __TLBI_1(op, arg) asm ("tlbi " #op ", %0" : : "r" (arg)) +#define __TLBI_N(op, arg, n, ...) __TLBI_##n(op, arg) + +#define __tlbi(op, ...) __TLBI_N(op, ##__VA_ARGS__, 1, 0) + /* * TLB Management * ============== @@ -66,7 +84,7 @@ static inline void local_flush_tlb_all(void) { dsb(nshst); - asm("tlbi vmalle1"); + __tlbi(vmalle1); dsb(nsh); isb(); } @@ -74,7 +92,7 @@ static inline void local_flush_tlb_all(void) static inline void flush_tlb_all(void) { dsb(ishst); - asm("tlbi vmalle1is"); + __tlbi(vmalle1is); dsb(ish); isb(); } @@ -83,14 +101,14 @@ static inline void flush_tlb_mm(struct mm_struct *mm) { #ifdef CONFIG_ARCH_MSM8994_V1_TLBI_WA dsb(); - asm("tlbi vmalle1is"); + __tlbi(vmalle1is); dsb(); isb(); #else unsigned long asid = (unsigned long)ASID(mm) << 48; dsb(ishst); - asm("tlbi aside1is, %0" : : "r" (asid)); + __tlbi(aside1is, asid); dsb(ish); #endif } @@ -100,7 +118,7 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, { #ifdef CONFIG_ARCH_MSM8994_V1_TLBI_WA dsb(); - asm("tlbi vmalle1is"); + __tlbi(vmalle1is); dsb(); isb(); #else @@ -108,7 +126,7 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, ((unsigned long)ASID(vma->vm_mm) << 48); dsb(ishst); - asm("tlbi vale1is, %0" : : "r" (addr)); + __tlbi(vale1is, addr); dsb(ish); #endif } @@ -137,9 +155,9 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, dsb(ishst); for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) { if (last_level) - asm("tlbi vale1is, %0" : : "r"(addr)); + __tlbi(vale1is, addr); else - asm("tlbi vae1is, %0" : : "r"(addr)); + __tlbi(vae1is, addr); } dsb(ish); } @@ -164,7 +182,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end dsb(ishst); for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) - asm("tlbi vaae1is, %0" : : "r"(addr)); + __tlbi(vaae1is, addr); dsb(ish); isb(); } @@ -178,7 +196,7 @@ static inline void __flush_tlb_pgtable(struct mm_struct *mm, { unsigned long addr = uaddr >> 12 | (ASID(mm) << 48); - asm("tlbi vae1is, %0" : : "r" (addr)); + __tlbi(vae1is, addr); dsb(ish); } From c739bd64d237fb3e11b526b33c52588098e4efee Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 19 Jul 2017 17:24:49 +0100 Subject: [PATCH 045/508] UPSTREAM: arm64: factor out entry stack manipulation In subsequent patches, we will detect stack overflow in our exception entry code, by verifying the SP after it has been decremented to make space for the exception regs. This verification code is small, and we can minimize its impact by placing it directly in the vectors. To avoid redundant modification of the SP, we also need to move the initial decrement of the SP into the vectors. As a preparatory step, this patch introduces kernel_ventry, which performs this decrement, and updates the entry code accordingly. Subsequent patches will fold SP verification into kernel_ventry. There should be no functional change as a result of this patch. Signed-off-by: Ard Biesheuvel [Mark: turn into prep patch, expand commit msg] Signed-off-by: Mark Rutland Reviewed-by: Will Deacon Tested-by: Laura Abbott Cc: Catalin Marinas Cc: James Morse (cherry picked from commit b11e5759bfac0c474d95ec4780b1566350e64cad) Signed-off-by: Greg Hackmann Change-Id: I1a1d01327c005ec1b92e939f122557a86893e01c Git-Commit: 1ee4be715741bbfbf5dd194da3958e7a4ea87807 Git-repo: git://android.googlesource.com/kernel/common.git [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- arch/arm64/kernel/entry.S | 47 ++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 4c58ac76bc8c8..952ec3b6f756a 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -69,8 +69,13 @@ #define BAD_FIQ 2 #define BAD_ERROR 3 - .macro kernel_entry, el, regsize = 64 + .macro kernel_ventry label + .align 7 sub sp, sp, #S_FRAME_SIZE + b \label + .endm + + .macro kernel_entry, el, regsize = 64 .if \regsize == 32 mov w0, w0 // zero upper 32 bits of x0 .endif @@ -270,31 +275,31 @@ tsk .req x28 // current thread_info .align 11 ENTRY(vectors) - ventry el1_sync_invalid // Synchronous EL1t - ventry el1_irq_invalid // IRQ EL1t - ventry el1_fiq_invalid // FIQ EL1t - ventry el1_error_invalid // Error EL1t + kernel_ventry el1_sync_invalid // Synchronous EL1t + kernel_ventry el1_irq_invalid // IRQ EL1t + kernel_ventry el1_fiq_invalid // FIQ EL1t + kernel_ventry el1_error_invalid // Error EL1t - ventry el1_sync // Synchronous EL1h - ventry el1_irq // IRQ EL1h - ventry el1_fiq_invalid // FIQ EL1h - ventry el1_error_invalid // Error EL1h + kernel_ventry el1_sync // Synchronous EL1h + kernel_ventry el1_irq // IRQ EL1h + kernel_ventry el1_fiq_invalid // FIQ EL1h + kernel_ventry el1_error_invalid // Error EL1h - ventry el0_sync // Synchronous 64-bit EL0 - ventry el0_irq // IRQ 64-bit EL0 - ventry el0_fiq_invalid // FIQ 64-bit EL0 - ventry el0_error_invalid // Error 64-bit EL0 + kernel_ventry el0_sync // Synchronous 64-bit EL0 + kernel_ventry el0_irq // IRQ 64-bit EL0 + kernel_ventry el0_fiq_invalid // FIQ 64-bit EL0 + kernel_ventry el0_error_invalid // Error 64-bit EL0 #ifdef CONFIG_COMPAT - ventry el0_sync_compat // Synchronous 32-bit EL0 - ventry el0_irq_compat // IRQ 32-bit EL0 - ventry el0_fiq_invalid_compat // FIQ 32-bit EL0 - ventry el0_error_invalid_compat // Error 32-bit EL0 + kernel_ventry el0_sync_compat // Synchronous 32-bit EL0 + kernel_ventry el0_irq_compat // IRQ 32-bit EL0 + kernel_ventry el0_fiq_invalid_compat // FIQ 32-bit EL0 + kernel_ventry el0_error_invalid_compat // Error 32-bit EL0 #else - ventry el0_sync_invalid // Synchronous 32-bit EL0 - ventry el0_irq_invalid // IRQ 32-bit EL0 - ventry el0_fiq_invalid // FIQ 32-bit EL0 - ventry el0_error_invalid // Error 32-bit EL0 + kernel_ventry el0_sync_invalid // Synchronous 32-bit EL0 + kernel_ventry el0_irq_invalid // IRQ 32-bit EL0 + kernel_ventry el0_fiq_invalid // FIQ 32-bit EL0 + kernel_ventry el0_error_invalid // Error 32-bit EL0 #endif END(vectors) From c46c9020649aed91d4cad3cd2b876cb9bcb1c14c Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 26 Nov 2015 13:49:39 +0000 Subject: [PATCH 046/508] UPSTREAM: arm64: mm: keep reserved ASIDs in sync with mm after multiple rollovers Under some unusual context-switching patterns, it is possible to end up with multiple threads from the same mm running concurrently with different ASIDs: 1. CPU x schedules task t with mm p containing ASID a and generation g This task doesn't block and the CPU doesn't context switch. So: * per_cpu(active_asid, x) = {g,a} * p->context.id = {g,a} 2. Some other CPU generates an ASID rollover. The global generation is now (g + 1). CPU x is still running t, with no context switch and so per_cpu(reserved_asid, x) = {g,a} 3. CPU y schedules task t', which shares mm p with t. The generation mismatches, so we take the slowpath and hit the reserved ASID from CPU x. p is then updated so that p->context.id = {g + 1,a} 4. CPU y schedules some other task u, which has an mm != p. 5. Some other CPU generates *another* CPU rollover. The global generation is now (g + 2). CPU x is still running t, with no context switch and so per_cpu(reserved_asid, x) = {g,a}. 6. CPU y once again schedules task t', but now *fails* to hit the reserved ASID from CPU x because of the generation mismatch. This results in a new ASID being allocated, despite the fact that t is still running on CPU x with the same mm. Consequently, TLBIs (e.g. as a result of CoW) will not be synchronised between the two threads. This patch fixes the problem by updating all of the matching reserved ASIDs when we hit on the slowpath (i.e. in step 3 above). This keeps the reserved ASIDs in-sync with the mm and avoids the problem. Reported-by: Tony Thompson Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas (cherry picked from commit 0ebea8088095f1c18c1d1de284ccc4c479ca21c1) Signed-off-by: Greg Hackmann Change-Id: Ib8bb01f3349e3f2b2cba433c09a0303d2e1ef799 Git-Commit: 6e0432e6d0844d05427166f0f7a3edad37362535 Git-repo: git://android.googlesource.com/kernel/common.git [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- arch/arm64/mm/context.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c index 43cff0e6f52ed..25128089c386b 100644 --- a/arch/arm64/mm/context.c +++ b/arch/arm64/mm/context.c @@ -76,13 +76,28 @@ static void flush_context(unsigned int cpu) __flush_icache_all(); } -static int is_reserved_asid(u64 asid) +static bool check_update_reserved_asid(u64 asid, u64 newasid) { int cpu; - for_each_possible_cpu(cpu) - if (per_cpu(reserved_asids, cpu) == asid) - return 1; - return 0; + bool hit = false; + + /* + * Iterate over the set of reserved ASIDs looking for a match. + * If we find one, then we can update our mm to use newasid + * (i.e. the same ASID in the current generation) but we can't + * exit the loop early, since we need to ensure that all copies + * of the old ASID are updated to reflect the mm. Failure to do + * so could result in us missing the reserved ASID in a future + * generation. + */ + for_each_possible_cpu(cpu) { + if (per_cpu(reserved_asids, cpu) == asid) { + hit = true; + per_cpu(reserved_asids, cpu) = newasid; + } + } + + return hit; } static u64 new_context(struct mm_struct *mm, unsigned int cpu) @@ -92,12 +107,14 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) u64 generation = atomic64_read(&asid_generation); if (asid != 0) { + u64 newasid = generation | (asid & ~ASID_MASK); + /* * If our current ASID was active during a rollover, we * can continue to use it and this was just a false alarm. */ - if (is_reserved_asid(asid)) - return generation | (asid & ~ASID_MASK); + if (check_update_reserved_asid(asid, newasid)) + return newasid; /* * We had a valid ASID in a previous life, so try to re-use @@ -105,7 +122,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) */ asid &= ~ASID_MASK; if (!__test_and_set_bit(asid, asid_map)) - goto bump_gen; + return newasid; } /* @@ -129,10 +146,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) set_asid: __set_bit(asid, asid_map); cur_idx = asid; - -bump_gen: - asid |= generation; - return asid; + return asid | generation; } void check_and_switch_context(struct mm_struct *mm, unsigned int cpu) From 2c80f7739d2252abb882a4c41bfa9e84e60b8064 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 18 Apr 2016 17:09:44 +0200 Subject: [PATCH 047/508] UPSTREAM: arm64: introduce mov_q macro to move a constant into a 64-bit register Implement a macro mov_q that can be used to move an immediate constant into a 64-bit register, using between 2 and 4 movz/movk instructions (depending on the operand) Acked-by: Catalin Marinas Signed-off-by: Ard Biesheuvel Signed-off-by: Will Deacon (cherry picked from commit 30b5ba5cf333cc650e474eaf2cc1ae91bc7cf89f) Signed-off-by: Greg Hackmann Change-Id: Ib7db6db569cfda7ce19bb2f9fc4cf336e862cd1d Git-Commit: 76ec6821bd1f90a316904ed189ba7bf7988025c1 Git-repo: git://android.googlesource.com/kernel/common.git Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/assembler.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index c66a176f4ee8d..34381f3809436 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -321,4 +321,24 @@ lr .req x30 // link register mrs \rd, sp_el0 .endm + /* + * mov_q - move an immediate constant into a 64-bit register using + * between 2 and 4 movz/movk instructions (depending on the + * magnitude and sign of the operand) + */ + .macro mov_q, reg, val + .if (((\val) >> 31) == 0 || ((\val) >> 31) == 0x1ffffffff) + movz \reg, :abs_g1_s:\val + .else + .if (((\val) >> 47) == 0 || ((\val) >> 47) == 0x1ffff) + movz \reg, :abs_g2_s:\val + .else + movz \reg, :abs_g3:\val + movk \reg, :abs_g2_nc:\val + .endif + movk \reg, :abs_g1_nc:\val + .endif + movk \reg, :abs_g0_nc:\val + .endm + #endif /* __ASM_ASSEMBLER_H */ From b33d84b08172dab223249326055289f996a3a399 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 9 Nov 2015 09:55:46 +0100 Subject: [PATCH 048/508] BACKPORT: arm64: fix R/O permissions of FDT mapping The mapping permissions of the FDT are set to 'PAGE_KERNEL | PTE_RDONLY' in an attempt to map the FDT as read-only. However, not only does this break at build time under STRICT_MM_TYPECHECKS (since the two terms are of different types in that case), it also results in both the PTE_WRITE and PTE_RDONLY attributes to be set, which means the region is still writable under ARMv8.1 DBM (and an attempted write will simply clear the PT_RDONLY bit). So instead, define PAGE_KERNEL_RO (which already has an established meaning across architectures) and use that instead. Signed-off-by: Ard Biesheuvel Signed-off-by: Catalin Marinas (cherry picked from commit fb226c3d7c77b4f99cee675795cc0e70937c56ee) [ghackmann@google.com: only take the PAGE_KERNEL_RO definition, since the FDT mapping code in question doesn't exist in 3.18] Signed-off-by: Greg Hackmann Change-Id: I9c0e0e342f94bd76cff34643aa9f9a9327b43fb5 Git-Commit: e906a21034395aaee1c38cafed3bd44ad76cdb5d Git-repo: git://android.googlesource.com/kernel/common.git Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/pgtable.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 0ee178f2ece73..395f5a23a2f0a 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -78,6 +78,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val); #define _PAGE_DEFAULT (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) #define PAGE_KERNEL __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE) +#define PAGE_KERNEL_RO __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_RDONLY) #define PAGE_KERNEL_EXEC __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE) #define PAGE_HYP __pgprot(_PAGE_DEFAULT | PTE_HYP) From 13a57d4b24e2b62f830cd47ba6d9e50aa8270f75 Mon Sep 17 00:00:00 2001 From: Anurag Chouhan Date: Thu, 8 Feb 2018 13:08:05 +0530 Subject: [PATCH 049/508] wlan: Add support to build wlan for msm-4.9 Change the local module path based on the kernel module out path is defined or not CRs-Fixed: 2186467 Change-Id: Iebe89434b02a3326003178dac11cc04cb2989b25 --- Android.mk | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Android.mk b/Android.mk index 179d4cb636252..1576d0945059e 100644 --- a/Android.mk +++ b/Android.mk @@ -153,9 +153,13 @@ LOCAL_MODULE_KBUILD_NAME := wlan.ko LOCAL_MODULE_TAGS := debug LOCAL_MODULE_DEBUG_ENABLE := true ifeq ($(PRODUCT_VENDOR_MOVE_ENABLED), true) -LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/modules/$(WLAN_CHIPSET) + ifeq ($(WIFI_DRIVER_INSTALL_TO_KERNEL_OUT),true) + LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) + else + LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/modules/$(WLAN_CHIPSET) + endif else -LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/modules/$(WLAN_CHIPSET) + LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/modules/$(WLAN_CHIPSET) endif # PRODUCT_VENDOR_MOVE_ENABLED include $(DLKM_DIR)/AndroidKernelModule.mk ########################################################### From 5c51481c4a22bbe6b00cd8404e48455156675d4c Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 10 Aug 2017 12:56:18 +0100 Subject: [PATCH 050/508] FROMLIST: arm64: mm: Use non-global mappings for kernel space In preparation for unmapping the kernel whilst running in userspace, make the kernel mappings non-global so we can avoid expensive TLB invalidation on kernel exit to userspace. Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit e046eb0c9bf26d94be9e4592c00c7a78b0fa9bfd) [ghackmann@google.com: apply pgtable-prot.h changes to pgtable.h instead] Signed-off-by: Greg Hackmann Change-Id: I3f3f0ee0194f315f301f239e05e31ffe0fb733ad Git-Commit: b92b29768a633895b09f1df0cfd11ea4cdcc8343 Git-repo: git://android.googlesource.com/kernel/common.git [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/kernel-pgtable.h | 12 ++++++++++-- arch/arm64/include/asm/pgtable.h | 17 +++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h index d06d7f06a5838..865887934504d 100644 --- a/arch/arm64/include/asm/kernel-pgtable.h +++ b/arch/arm64/include/asm/kernel-pgtable.h @@ -61,8 +61,16 @@ /* * Initial memory map attributes. */ -#define SWAPPER_PTE_FLAGS (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) -#define SWAPPER_PMD_FLAGS (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) +#define _SWAPPER_PTE_FLAGS (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) +#define _SWAPPER_PMD_FLAGS (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) + +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +#define SWAPPER_PTE_FLAGS (_SWAPPER_PTE_FLAGS | PTE_NG) +#define SWAPPER_PMD_FLAGS (_SWAPPER_PMD_FLAGS | PMD_SECT_NG) +#else +#define SWAPPER_PTE_FLAGS _SWAPPER_PTE_FLAGS +#define SWAPPER_PMD_FLAGS _SWAPPER_PMD_FLAGS +#endif #ifdef CONFIG_ARM64_64K_PAGES #define SWAPPER_MM_MMUFLAGS (PTE_ATTRINDX(MT_NORMAL) | SWAPPER_PTE_FLAGS) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 395f5a23a2f0a..eb6b0692d59b1 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -63,8 +63,16 @@ extern void __pmd_error(const char *file, int line, unsigned long val); extern void __pud_error(const char *file, int line, unsigned long val); extern void __pgd_error(const char *file, int line, unsigned long val); -#define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) -#define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) +#define _PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) +#define _PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) + +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +#define PROT_DEFAULT (_PROT_DEFAULT | PTE_NG) +#define PROT_SECT_DEFAULT (_PROT_SECT_DEFAULT | PMD_SECT_NG) +#else +#define PROT_DEFAULT _PROT_DEFAULT +#define PROT_SECT_DEFAULT _PROT_SECT_DEFAULT +#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ #define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRnE)) #define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE)) @@ -76,18 +84,19 @@ extern void __pgd_error(const char *file, int line, unsigned long val); #define PROT_SECT_NORMAL_EXEC (PROT_SECT_DEFAULT | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL)) #define _PAGE_DEFAULT (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) +#define _HYP_PAGE_DEFAULT (_PAGE_DEFAULT & ~PTE_NG) #define PAGE_KERNEL __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE) #define PAGE_KERNEL_RO __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_RDONLY) #define PAGE_KERNEL_EXEC __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE) -#define PAGE_HYP __pgprot(_PAGE_DEFAULT | PTE_HYP) +#define PAGE_HYP __pgprot(_HYP_PAGE_DEFAULT | PTE_HYP) #define PAGE_HYP_DEVICE __pgprot(PROT_DEVICE_nGnRE | PTE_HYP) #define PAGE_S2 __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY) #define PAGE_S2_DEVICE __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_UXN) -#define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE | PTE_PXN | PTE_UXN) +#define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE | PTE_NG | PTE_PXN | PTE_UXN) #define PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE) #define PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE) #define PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) From 2d481109663d2db548acf5ccf7e6844ac68b89fb Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 10 Aug 2017 13:04:48 +0100 Subject: [PATCH 051/508] FROMLIST: arm64: mm: Temporarily disable ARM64_SW_TTBR0_PAN We're about to rework the way ASIDs are allocated, switch_mm is implemented and low-level kernel entry/exit is handled, so keep the ARM64_SW_TTBR0_PAN code out of the way whilst we do the heavy lifting. It will be re-enabled in a subsequent patch. Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit 376133b7edc20f237a42e4c72415cc9e8c0a9704) Signed-off-by: Greg Hackmann Change-Id: I9ae16925550c34c36f2fa414830d06dc1457b626 Git-Commit: 735e1554285ab9fb564a96642849571f9c7e85b7 Git-repo: git://android.googlesource.com/kernel/common.git Signed-off-by: Vinayak Menon --- arch/arm64/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 0444366b29d75..65af6d7045edd 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -871,6 +871,7 @@ endif config ARM64_SW_TTBR0_PAN bool "Emulate Privileged Access Never using TTBR0_EL1 switching" + depends on BROKEN # Temporary while switch_mm is reworked help Enabling this option prevents the kernel from accessing user-space memory directly by pointing TTBR0_EL1 to a reserved From 6ab3fe2a679d7c7fc2d1cdc84d5609945b28538d Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 10 Aug 2017 13:19:09 +0100 Subject: [PATCH 052/508] FROMLIST: arm64: mm: Move ASID from TTBR0 to TTBR1 In preparation for mapping kernelspace and userspace with different ASIDs, move the ASID to TTBR1 and update switch_mm to context-switch TTBR0 via an invalid mapping (the zero page). Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit 7655abb953860485940d4de74fb45a8192149bb6) [ghackmann@google.com: adjust context] Signed-off-by: Greg Hackmann Change-Id: I374cd4154416e27a7c9d2a968dfc896f4bfc2763 Git-Commit: 6de449786ee41fb95db207ef68cf865ca8929218 Git-repo: git://android.googlesource.com/kernel/common.git [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/mmu_context.h | 7 +++++++ arch/arm64/include/asm/pgtable-hwdef.h | 2 ++ arch/arm64/include/asm/proc-fns.h | 6 ------ arch/arm64/mm/proc.S | 9 ++++++--- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h index 1f7dcb26bdfa2..2156ee710274b 100644 --- a/arch/arm64/include/asm/mmu_context.h +++ b/arch/arm64/include/asm/mmu_context.h @@ -63,6 +63,13 @@ static inline void cpu_set_reserved_ttbr0(void) : "r" (ttbr)); } +static inline void cpu_switch_mm(pgd_t *pgd, struct mm_struct *mm) +{ + BUG_ON(pgd == swapper_pg_dir); + cpu_set_reserved_ttbr0(); + cpu_do_switch_mm(virt_to_phys(pgd),mm); +} + /* * TCR.T0SZ value to use when the ID map is active. Usually equals * TCR_T0SZ(VA_BITS), unless system RAM is positioned very high in diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h index 5e50782f625dd..bfe379d13b835 100644 --- a/arch/arm64/include/asm/pgtable-hwdef.h +++ b/arch/arm64/include/asm/pgtable-hwdef.h @@ -164,6 +164,8 @@ #define TCR_TG1_16K (UL(1) << 30) #define TCR_TG1_4K (UL(2) << 30) #define TCR_TG1_64K (UL(3) << 30) + +#define TCR_A1 (UL(1) << 22) #define TCR_ASID16 (UL(1) << 36) #define TCR_TBI0 (UL(1) << 37) diff --git a/arch/arm64/include/asm/proc-fns.h b/arch/arm64/include/asm/proc-fns.h index b5240e8687844..d35dcebb121e7 100644 --- a/arch/arm64/include/asm/proc-fns.h +++ b/arch/arm64/include/asm/proc-fns.h @@ -35,12 +35,6 @@ extern u64 cpu_do_resume(phys_addr_t ptr, u64 idmap_ttbr); #include -#define cpu_switch_mm(pgd,mm) \ -do { \ - BUG_ON(pgd == swapper_pg_dir); \ - cpu_do_switch_mm(virt_to_phys(pgd),mm); \ -} while (0) - #define cpu_get_pgd() \ ({ \ unsigned long pg; \ diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index d579089a1649d..3cbf35a958218 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -127,9 +127,12 @@ ENDPROC(cpu_do_resume) * - pgd_phys - physical address of new TTB */ ENTRY(cpu_do_switch_mm) + mrs x2, ttbr1_el1 mmid x1, x1 // get mm->context.id - bfi x0, x1, #48, #16 // set the ASID - msr ttbr0_el1, x0 // set TTBR0 + bfi x2, x1, #48, #16 // set the ASID + msr ttbr1_el1, x2 // in TTBR1 (since TCR.A1 is set) + isb + msr ttbr0_el1, x0 // now update TTBR0 isb ret ENDPROC(cpu_do_switch_mm) @@ -182,7 +185,7 @@ ENTRY(__cpu_setup) * both user and kernel. */ ldr x10, =TCR_TxSZ(VA_BITS) | TCR_CACHE_FLAGS | TCR_SMP_FLAGS | \ - TCR_TG_FLAGS | TCR_ASID16 | TCR_TBI0 + TCR_TG_FLAGS | TCR_ASID16 | TCR_TBI0 | TCR_A1 tcr_set_idmap_t0sz x10, x9 /* From c5dfc5b5f9cdcf5df7b31ba2f3d2ac659f05b0ed Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 10 Aug 2017 13:58:16 +0100 Subject: [PATCH 053/508] FROMLIST: arm64: mm: Fix and re-enable ARM64_SW_TTBR0_PAN With the ASID now installed in TTBR1, we can re-enable ARM64_SW_TTBR0_PAN by ensuring that we switch to a reserved ASID of zero when disabling user access and restore the active user ASID on the uaccess enable path. Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit 27a921e75711d924617269e0ba4adb8bae9fd0d1) [ghackmann@google.com: adjust context, applying asm-uaccess.h changes to uaccess.h] Signed-off-by: Greg Hackmann Change-Id: Iec7bff74f0605cea58793f2d1cb0d6546fa571e2 Git-Commit: 4ea2126b109f510b78d03b051980634b16451c2c Git-repo: git://android.googlesource.com/kernel/common.git [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- arch/arm64/Kconfig | 1 - arch/arm64/include/asm/uaccess.h | 46 +++++++++++++++++++++++--------- arch/arm64/kernel/entry.S | 4 +-- arch/arm64/lib/clear_user.S | 2 +- arch/arm64/lib/copy_from_user.S | 2 +- arch/arm64/lib/copy_in_user.S | 2 +- arch/arm64/lib/copy_to_user.S | 2 +- arch/arm64/mm/cache.S | 2 +- arch/arm64/xen/hypercall.S | 2 +- 9 files changed, 42 insertions(+), 21 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 65af6d7045edd..0444366b29d75 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -871,7 +871,6 @@ endif config ARM64_SW_TTBR0_PAN bool "Emulate Privileged Access Never using TTBR0_EL1 switching" - depends on BROKEN # Temporary while switch_mm is reworked help Enabling this option prevents the kernel from accessing user-space memory directly by pointing TTBR0_EL1 to a reserved diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 21963026efd0c..cfef719287d92 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -136,15 +136,19 @@ static inline void __uaccess_ttbr0_disable(void) { unsigned long ttbr; + ttbr = read_sysreg(ttbr1_el1); /* reserved_ttbr0 placed at the end of swapper_pg_dir */ - ttbr = read_sysreg(ttbr1_el1) + SWAPPER_DIR_SIZE; - write_sysreg(ttbr, ttbr0_el1); + write_sysreg(ttbr + SWAPPER_DIR_SIZE, ttbr0_el1); + isb(); + /* Set reserved ASID */ + ttbr &= ~(0xffffUL << 48); + write_sysreg(ttbr, ttbr1_el1); isb(); } static inline void __uaccess_ttbr0_enable(void) { - unsigned long flags; + unsigned long flags, ttbr0, ttbr1; /* * Disable interrupts to avoid preemption between reading the 'ttbr0' @@ -152,7 +156,16 @@ static inline void __uaccess_ttbr0_enable(void) * roll-over and an update of 'ttbr0'. */ local_irq_save(flags); - write_sysreg(current_thread_info()->ttbr0, ttbr0_el1); + ttbr0 = current_thread_info()->ttbr0; + + /* Restore active ASID */ + ttbr1 = read_sysreg(ttbr1_el1); + ttbr1 |= ttbr0 & (0xffffUL << 48); + write_sysreg(ttbr1, ttbr1_el1); + isb(); + + /* Restore user page table */ + write_sysreg(ttbr0, ttbr0_el1); isb(); local_irq_restore(flags); } @@ -440,11 +453,20 @@ extern __must_check long strnlen_user(const char __user *str, long n); add \tmp1, \tmp1, #SWAPPER_DIR_SIZE // reserved_ttbr0 at the end of swapper_pg_dir msr ttbr0_el1, \tmp1 // set reserved TTBR0_EL1 isb + sub \tmp1, \tmp1, #SWAPPER_DIR_SIZE + bic \tmp1, \tmp1, #(0xffff << 48) + msr ttbr1_el1, \tmp1 // set reserved ASID + isb .endm - .macro __uaccess_ttbr0_enable, tmp1 + .macro __uaccess_ttbr0_enable, tmp1, tmp2 get_thread_info \tmp1 ldr \tmp1, [\tmp1, #TSK_TI_TTBR0] // load saved TTBR0_EL1 + mrs \tmp2, ttbr1_el1 + extr \tmp2, \tmp2, \tmp1, #48 + ror \tmp2, \tmp2, #16 + msr ttbr1_el1, \tmp2 // set the active ASID + isb msr ttbr0_el1, \tmp1 // set the non-PAN TTBR0_EL1 isb .endm @@ -455,18 +477,18 @@ alternative_if_not ARM64_HAS_PAN alternative_else_nop_endif .endm - .macro uaccess_ttbr0_enable, tmp1, tmp2 + .macro uaccess_ttbr0_enable, tmp1, tmp2, tmp3 alternative_if_not ARM64_HAS_PAN - save_and_disable_irq \tmp2 // avoid preemption - __uaccess_ttbr0_enable \tmp1 - restore_irq \tmp2 + save_and_disable_irq \tmp3 // avoid preemption + __uaccess_ttbr0_enable \tmp1, \tmp2 + restore_irq \tmp3 alternative_else_nop_endif .endm #else .macro uaccess_ttbr0_disable, tmp1 .endm - .macro uaccess_ttbr0_enable, tmp1, tmp2 + .macro uaccess_ttbr0_enable, tmp1, tmp2, tmp3 .endm #endif @@ -480,8 +502,8 @@ alternative_if ARM64_ALT_PAN_NOT_UAO alternative_else_nop_endif .endm - .macro uaccess_enable_not_uao, tmp1, tmp2 - uaccess_ttbr0_enable \tmp1, \tmp2 + .macro uaccess_enable_not_uao, tmp1, tmp2, tmp3 + uaccess_ttbr0_enable \tmp1, \tmp2, \tmp3 alternative_if ARM64_ALT_PAN_NOT_UAO SET_PSTATE_PAN(0) alternative_else_nop_endif diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 952ec3b6f756a..8c02d08dc7943 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -129,7 +129,7 @@ alternative_if ARM64_HAS_PAN alternative_else_nop_endif .if \el != 0 - mrs x21, ttbr0_el1 + mrs x21, ttbr1_el1 tst x21, #0xffff << 48 // Check for the reserved ASID orr x23, x23, #PSR_PAN_BIT // Set the emulated PAN in the saved SPSR b.eq 1f // TTBR0 access already disabled @@ -193,7 +193,7 @@ alternative_else_nop_endif tbnz x22, #22, 1f // Skip re-enabling TTBR0 access if the PSR_PAN_BIT is set .endif - __uaccess_ttbr0_enable x0 + __uaccess_ttbr0_enable x0, x1 1: .if \el != 0 and x22, x22, #~PSR_PAN_BIT // ARMv8.0 CPUs do not understand this bit diff --git a/arch/arm64/lib/clear_user.S b/arch/arm64/lib/clear_user.S index d7150e30438ae..dd65ca253eb4e 100644 --- a/arch/arm64/lib/clear_user.S +++ b/arch/arm64/lib/clear_user.S @@ -30,7 +30,7 @@ * Alignment fixed up by hardware. */ ENTRY(__clear_user) - uaccess_enable_not_uao x2, x3 + uaccess_enable_not_uao x2, x3, x4 mov x2, x1 // save the size for fixup return subs x1, x1, #8 b.mi 2f diff --git a/arch/arm64/lib/copy_from_user.S b/arch/arm64/lib/copy_from_user.S index 90154f3f7f2ae..1ff23f81e2426 100644 --- a/arch/arm64/lib/copy_from_user.S +++ b/arch/arm64/lib/copy_from_user.S @@ -64,7 +64,7 @@ end .req x5 ENTRY(__arch_copy_from_user) - uaccess_enable_not_uao x3, x4 + uaccess_enable_not_uao x3, x4, x5 add end, x0, x2 #include "copy_template.S" uaccess_disable_not_uao x3 diff --git a/arch/arm64/lib/copy_in_user.S b/arch/arm64/lib/copy_in_user.S index 718b1c4e2f85a..074d52fcd75ba 100644 --- a/arch/arm64/lib/copy_in_user.S +++ b/arch/arm64/lib/copy_in_user.S @@ -65,7 +65,7 @@ end .req x5 ENTRY(__copy_in_user) - uaccess_enable_not_uao x3, x4 + uaccess_enable_not_uao x3, x4, x5 add end, x0, x2 #include "copy_template.S" uaccess_disable_not_uao x3 diff --git a/arch/arm64/lib/copy_to_user.S b/arch/arm64/lib/copy_to_user.S index e99e31c9acac8..67118444cde0c 100644 --- a/arch/arm64/lib/copy_to_user.S +++ b/arch/arm64/lib/copy_to_user.S @@ -63,7 +63,7 @@ end .req x5 ENTRY(__arch_copy_to_user) - uaccess_enable_not_uao x3, x4 + uaccess_enable_not_uao x3, x4, x5 add end, x0, x2 #include "copy_template.S" uaccess_disable_not_uao x3 diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S index 4f71e90bf7a53..98134de8dec7d 100644 --- a/arch/arm64/mm/cache.S +++ b/arch/arm64/mm/cache.S @@ -158,7 +158,7 @@ ENTRY(flush_icache_range) * - end - virtual end address of region */ ENTRY(__flush_cache_user_range) - uaccess_ttbr0_enable x2, x3 + uaccess_ttbr0_enable x2, x3, x4 dcache_line_size x2, x3 sub x3, x2, #1 bic x4, x0, x3 diff --git a/arch/arm64/xen/hypercall.S b/arch/arm64/xen/hypercall.S index b96db5dafec48..27b38711023b5 100644 --- a/arch/arm64/xen/hypercall.S +++ b/arch/arm64/xen/hypercall.S @@ -98,7 +98,7 @@ ENTRY(privcmd_call) * need the explicit uaccess_enable/disable if the TTBR0 PAN emulation * is enabled (it implies that hardware UAO and PAN disabled). */ - uaccess_ttbr0_enable x6, x7 + uaccess_ttbr0_enable x6, x7, x8 hvc XEN_IMM /* From 99afa69a17a76eb975fa86b37566d26575f58d9c Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 10 Aug 2017 14:10:28 +0100 Subject: [PATCH 054/508] FROMLIST: arm64: mm: Allocate ASIDs in pairs In preparation for separate kernel/user ASIDs, allocate them in pairs for each mm_struct. The bottom bit distinguishes the two: if it is set, then the ASID will map only userspace. Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit 0c8ea531b7740754cf374ca8b7510655f569c5e3) [ghackmann@google.com: adjust context] Signed-off-by: Greg Hackmann Change-Id: Ie9dd8ca183007c486ef13fd3c560223d263bef4b Git-Commit: b7032349724a4bd7da6e6426f8742db8fc6095aa Git-repo: git://android.googlesource.com/kernel/common.git Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/mmu.h | 2 ++ arch/arm64/mm/context.c | 25 +++++++++++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index 539194f0b4a06..8b051b4fcaa5a 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -16,6 +16,8 @@ #ifndef __ASM_MMU_H #define __ASM_MMU_H +#define USER_ASID_FLAG (UL(1) << 48) + typedef struct { atomic64_t id; void *vdso; diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c index 25128089c386b..10d68e438a372 100644 --- a/arch/arm64/mm/context.c +++ b/arch/arm64/mm/context.c @@ -38,7 +38,16 @@ static cpumask_t tlb_flush_pending; #define ASID_MASK (~GENMASK(asid_bits - 1, 0)) #define ASID_FIRST_VERSION (1UL << asid_bits) -#define NUM_USER_ASIDS ASID_FIRST_VERSION + +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +#define NUM_USER_ASIDS (ASID_FIRST_VERSION >> 1) +#define asid2idx(asid) (((asid) & ~ASID_MASK) >> 1) +#define idx2asid(idx) (((idx) << 1) & ~ASID_MASK) +#else +#define NUM_USER_ASIDS (ASID_FIRST_VERSION) +#define asid2idx(asid) ((asid) & ~ASID_MASK) +#define idx2asid(idx) asid2idx(idx) +#endif static void flush_context(unsigned int cpu) { @@ -65,7 +74,7 @@ static void flush_context(unsigned int cpu) */ if (asid == 0) asid = per_cpu(reserved_asids, i); - __set_bit(asid & ~ASID_MASK, asid_map); + __set_bit(asid2idx(asid), asid_map); per_cpu(reserved_asids, i) = asid; } @@ -120,16 +129,16 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) * We had a valid ASID in a previous life, so try to re-use * it if possible. */ - asid &= ~ASID_MASK; - if (!__test_and_set_bit(asid, asid_map)) + if (!__test_and_set_bit(asid2idx(asid), asid_map)) return newasid; } /* * Allocate a free ASID. If we can't find one, take a note of the - * currently active ASIDs and mark the TLBs as requiring flushes. - * We always count from ASID #1, as we use ASID #0 when setting a - * reserved TTBR0 for the init_mm. + * currently active ASIDs and mark the TLBs as requiring flushes. We + * always count from ASID #2 (index 1), as we use ASID #0 when setting + * a reserved TTBR0 for the init_mm and we allocate ASIDs in even/odd + * pairs. */ asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, cur_idx); if (asid != NUM_USER_ASIDS) @@ -146,7 +155,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) set_asid: __set_bit(asid, asid_map); cur_idx = asid; - return asid | generation; + return idx2asid(asid) | generation; } void check_and_switch_context(struct mm_struct *mm, unsigned int cpu) From aefacd69b82e4f079630f881f5f303ddd167ea2d Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 14 Nov 2017 13:58:08 +0000 Subject: [PATCH 055/508] FROMLIST: arm64: mm: Add arm64_kernel_unmapped_at_el0 helper In order for code such as TLB invalidation to operate efficiently when the decision to map the kernel at EL0 is determined at runtime, this patch introduces a helper function, arm64_kernel_unmapped_at_el0, to determine whether or not the kernel is mapped whilst running in userspace. Currently, this just reports the value of CONFIG_UNMAP_KERNEL_AT_EL0, but will later be hooked up to a fake CPU capability using a static key. Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit fc0e1299da548b32440051f58f08e0c1eb7edd0b) Signed-off-by: Greg Hackmann Change-Id: I5f8c15e5f8ba0c521d0ed7515c003598bf3d7cf8 Git-Commit: 1434f49fc0dae1dc85f22f92d21e189422370185 Git-repo: git://android.googlesource.com/kernel/common.git [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/mmu.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index 8b051b4fcaa5a..d943896670662 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -18,6 +18,8 @@ #define USER_ASID_FLAG (UL(1) << 48) +#ifndef __ASSEMBLY__ + typedef struct { atomic64_t id; void *vdso; @@ -30,6 +32,11 @@ typedef struct { */ #define ASID(mm) ((mm)->context.id.counter & 0xffff) +static inline bool arm64_kernel_unmapped_at_el0(void) +{ + return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0); +} + extern void paging_init(void); extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt); extern void init_mem_pgprot(void); @@ -38,4 +45,5 @@ extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot); +#endif /* !__ASSEMBLY__ */ #endif From 7be2d191fb2c391cca4ccaa94ead2760276369cd Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 10 Aug 2017 14:13:33 +0100 Subject: [PATCH 056/508] FROMLIST: arm64: mm: Invalidate both kernel and user ASIDs when performing TLBI Since an mm has both a kernel and a user ASID, we need to ensure that broadcast TLB maintenance targets both address spaces so that things like CoW continue to work with the uaccess primitives in the kernel. Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit 9b0de864b5bc298ea53005ad812f3386f81aee9c) Signed-off-by: Greg Hackmann Change-Id: I1f665f7b609872424071ecef14d6fab2b2d721ea Git-Commit: eed2e002366647f8aefb9dc938a402294e16396d Git-repo: git://android.googlesource.com/kernel/common.git [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/tlbflush.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h index 0e0fe68d21568..0cfeecfa60ab7 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h @@ -23,6 +23,7 @@ #include #include +#include /* * Raw TLBI operations. @@ -42,6 +43,11 @@ #define __tlbi(op, ...) __TLBI_N(op, ##__VA_ARGS__, 1, 0) +#define __tlbi_user(op, arg) do { \ + if (arm64_kernel_unmapped_at_el0()) \ + __tlbi(op, (arg) | USER_ASID_FLAG); \ +} while (0) + /* * TLB Management * ============== @@ -109,6 +115,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm) dsb(ishst); __tlbi(aside1is, asid); + __tlbi_user(aside1is, asid); dsb(ish); #endif } @@ -127,6 +134,7 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, dsb(ishst); __tlbi(vale1is, addr); + __tlbi_user(vale1is, addr); dsb(ish); #endif } @@ -154,10 +162,13 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, dsb(ishst); for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) { - if (last_level) + if (last_level) { __tlbi(vale1is, addr); - else + __tlbi_user(vale1is, addr); + } else { __tlbi(vae1is, addr); + __tlbi_user(vae1is, addr); + } } dsb(ish); } @@ -197,6 +208,7 @@ static inline void __flush_tlb_pgtable(struct mm_struct *mm, unsigned long addr = uaddr >> 12 | (ASID(mm) << 48); __tlbi(vae1is, addr); + __tlbi_user(vae1is, addr); dsb(ish); } From c874c378e7b39b2b892902c846159e0c9a71ae14 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 14 Nov 2017 14:07:40 +0000 Subject: [PATCH 057/508] FROMLIST: arm64: entry: Add exception trampoline page for exceptions from EL0 To allow unmapping of the kernel whilst running at EL0, we need to point the exception vectors at an entry trampoline that can map/unmap the kernel on entry/exit respectively. This patch adds the trampoline page, although it is not yet plugged into the vector table and is therefore unused. Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit c7b9adaf85f818d747eeff5145eb4095ccd587fb) [ghackmann@google.com: adjust context] Signed-off-by: Greg Hackmann Change-Id: Ib74f0a15fb60db15f0b7f85d3007c1c60f8ff04e Git-Commit: 6415b1f83e554dc76816cbb76ed20e4e73633f33 Git-repo: git://android.googlesource.com/kernel/common.git [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- arch/arm64/kernel/entry.S | 85 +++++++++++++++++++++++++++++++++ arch/arm64/kernel/vmlinux.lds.S | 17 +++++++ 2 files changed, 102 insertions(+) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 8c02d08dc7943..2e01afebab287 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -858,6 +859,90 @@ __ni_sys_trace: bl do_ni_syscall b __sys_trace_return +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +/* + * Exception vectors trampoline. + */ + .pushsection ".entry.tramp.text", "ax" + + .macro tramp_map_kernel, tmp + mrs \tmp, ttbr1_el1 + sub \tmp, \tmp, #(SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE) + bic \tmp, \tmp, #USER_ASID_FLAG + msr ttbr1_el1, \tmp + .endm + + .macro tramp_unmap_kernel, tmp + mrs \tmp, ttbr1_el1 + add \tmp, \tmp, #(SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE) + orr \tmp, \tmp, #USER_ASID_FLAG + msr ttbr1_el1, \tmp + /* + * We avoid running the post_ttbr_update_workaround here because the + * user and kernel ASIDs don't have conflicting mappings, so any + * "blessing" as described in: + * + * http://lkml.kernel.org/r/56BB848A.6060603@caviumnetworks.com + * + * will not hurt correctness. Whilst this may partially defeat the + * point of using split ASIDs in the first place, it avoids + * the hit of invalidating the entire I-cache on every return to + * userspace. + */ + .endm + + .macro tramp_ventry, regsize = 64 + .align 7 +1: + .if \regsize == 64 + msr tpidrro_el0, x30 // Restored in kernel_ventry + .endif + tramp_map_kernel x30 + ldr x30, =vectors + prfm plil1strm, [x30, #(1b - tramp_vectors)] + msr vbar_el1, x30 + add x30, x30, #(1b - tramp_vectors) + isb + br x30 + .endm + + .macro tramp_exit, regsize = 64 + adr x30, tramp_vectors + msr vbar_el1, x30 + tramp_unmap_kernel x30 + .if \regsize == 64 + mrs x30, far_el1 + .endif + eret + .endm + + .align 11 +ENTRY(tramp_vectors) + .space 0x400 + + tramp_ventry + tramp_ventry + tramp_ventry + tramp_ventry + + tramp_ventry 32 + tramp_ventry 32 + tramp_ventry 32 + tramp_ventry 32 +END(tramp_vectors) + +ENTRY(tramp_exit_native) + tramp_exit +END(tramp_exit_native) + +ENTRY(tramp_exit_compat) + tramp_exit 32 +END(tramp_exit_compat) + + .ltorg + .popsection // .entry.tramp.text +#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ + /* * Special system call wrappers. */ diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index a38f929fc6d0e..1ded30f007b42 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -40,6 +40,17 @@ jiffies = jiffies_64; *(.hyp.text) \ VMLINUX_SYMBOL(__hyp_text_end) = .; +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +#define TRAMP_TEXT \ + . = ALIGN(PAGE_SIZE); \ + VMLINUX_SYMBOL(__entry_tramp_text_start) = .; \ + *(.entry.tramp.text) \ + . = ALIGN(PAGE_SIZE); \ + VMLINUX_SYMBOL(__entry_tramp_text_end) = .; +#else +#define TRAMP_TEXT +#endif + /* * The size of the PE/COFF section that covers the kernel image, which * runs from stext to _edata, must be a round multiple of the PE/COFF @@ -97,6 +108,7 @@ SECTIONS SCHED_TEXT LOCK_TEXT HYPERVISOR_TEXT + TRAMP_TEXT *(.fixup) *(.gnu.warning) . = ALIGN(16); @@ -167,6 +179,11 @@ SECTIONS . += RESERVED_TTBR0_SIZE; #endif +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 + tramp_pg_dir = .; + . += PAGE_SIZE; +#endif + _end = .; STABS_DEBUG From 16dc301b7ca580843986b9b29dfa5b3f93d261b2 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 14 Nov 2017 14:14:17 +0000 Subject: [PATCH 058/508] FROMLIST: arm64: mm: Map entry trampoline into trampoline and kernel page tables The exception entry trampoline needs to be mapped at the same virtual address in both the trampoline page table (which maps nothing else) and also the kernel page table, so that we can swizzle TTBR1_EL1 on exceptions from and return to EL0. This patch maps the trampoline at a fixed virtual address in the fixmap area of the kernel virtual address space, which allows the kernel proper to be randomized with respect to the trampoline when KASLR is enabled. Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit 51a0048beb449682d632d0af52a515adb9f9882e) [ghackmann@google.com: - adjust context - tweak __create_pgd_mapping() call to match 3.18 APIs - expand definition of PGD_SIZE, which is private to pgd.c in 3.18] - open-code pgd_pgtable_alloc(), based on version in 4.9] Signed-off-by: Greg Hackmann Change-Id: I85f681757feeb43c6cb55fce10a619e24d31c9bd Git-Commit: 771dd6d68c7b40528926d01fb1d6a8a47416e83c Git-repo: git://android.googlesource.com/kernel/common.git [vinmenon@codeaurora.org: fixes for force pages feature] Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/fixmap.h | 4 ++++ arch/arm64/include/asm/pgtable.h | 1 + arch/arm64/kernel/asm-offsets.c | 5 +++++ arch/arm64/mm/mmu.c | 37 ++++++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+) diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h index defa0ff982509..cc9b9a6a238c5 100644 --- a/arch/arm64/include/asm/fixmap.h +++ b/arch/arm64/include/asm/fixmap.h @@ -33,6 +33,10 @@ enum fixed_addresses { FIX_HOLE, FIX_EARLYCON_MEM_BASE, +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 + FIX_ENTRY_TRAMP_TEXT, +#define TRAMP_VALIAS (__fix_to_virt(FIX_ENTRY_TRAMP_TEXT)) +#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ __end_of_permanent_fixed_addresses, /* diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index eb6b0692d59b1..705a01da6a960 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -487,6 +487,7 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; +extern pgd_t tramp_pg_dir[PTRS_PER_PGD]; /* * Encode and decode a swap entry: diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 92a5d25bff1ad..a865573461e1a 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -164,6 +165,10 @@ int main(void) DEFINE(SLEEP_SAVE_SP_SZ, sizeof(struct sleep_save_sp)); DEFINE(SLEEP_SAVE_SP_PHYS, offsetof(struct sleep_save_sp, save_ptr_stash_phys)); DEFINE(SLEEP_SAVE_SP_VIRT, offsetof(struct sleep_save_sp, save_ptr_stash)); +#endif + BLANK(); +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 + DEFINE(TRAMP_VALIAS, TRAMP_VALIAS); #endif return 0; } diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index c7c81ab26c95b..b5d7dbc41e499 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -670,6 +670,43 @@ void fixup_init(void) PAGE_KERNEL); } +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +static void __init *pgd_pgtable_alloc(unsigned long size) +{ + void *ptr; + BUG_ON(size != PAGE_SIZE); + + ptr = (void *)__get_free_page(PGALLOC_GFP); + if (!ptr || !pgtable_page_ctor(virt_to_page(ptr))) + BUG(); + + /* Ensure the zeroed page is visible to the page table walker */ + dsb(ishst); + return ptr; +} + +static int __init map_entry_trampoline(void) +{ + extern char __entry_tramp_text_start[]; + + pgprot_t prot = PAGE_KERNEL_EXEC; + phys_addr_t pa_start = __pa_symbol(__entry_tramp_text_start); + + /* The trampoline is always mapped and can therefore be global */ + pgprot_val(prot) &= ~PTE_NG; + + /* Map only the text into the trampoline page table */ + memset(tramp_pg_dir, 0, PTRS_PER_PGD * sizeof(pgd_t)); + __create_mapping(NULL, tramp_pg_dir + pgd_index(TRAMP_VALIAS), pa_start, + TRAMP_VALIAS, PAGE_SIZE, prot, pgd_pgtable_alloc, false); + + /* ...as well as the kernel page table */ + __set_fixmap(FIX_ENTRY_TRAMP_TEXT, pa_start, prot); + return 0; +} +core_initcall(map_entry_trampoline); +#endif + /* * paging_init() sets up the page tables, initialises the zone memory * maps and sets up the zero page. From e1a2e7b25ea615519458252fe836bc7d2cffa2da Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 14 Nov 2017 14:20:21 +0000 Subject: [PATCH 059/508] FROMLIST: arm64: entry: Explicitly pass exception level to kernel_ventry macro We will need to treat exceptions from EL0 differently in kernel_ventry, so rework the macro to take the exception level as an argument and construct the branch target using that. Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit 5b1f7fe41909cde40decad9f0e8ee585777a0538) [ghackmann@google.com: adjust context and kernel entry point names] Signed-off-by: Greg Hackmann Change-Id: I264359bfbac842d1673edd939c4997a3f68714b9 Git-Commit: eb8401717f414fba0530373960a02fb1c2fad54f Git-repo: git://android.googlesource.com/kernel/common.git [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- arch/arm64/kernel/entry.S | 44 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 2e01afebab287..c69a43e0fdacd 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -70,10 +70,10 @@ #define BAD_FIQ 2 #define BAD_ERROR 3 - .macro kernel_ventry label + .macro kernel_ventry, el, label, regsize = 64 .align 7 sub sp, sp, #S_FRAME_SIZE - b \label + b el\()\el\()_\label .endm .macro kernel_entry, el, regsize = 64 @@ -276,31 +276,31 @@ tsk .req x28 // current thread_info .align 11 ENTRY(vectors) - kernel_ventry el1_sync_invalid // Synchronous EL1t - kernel_ventry el1_irq_invalid // IRQ EL1t - kernel_ventry el1_fiq_invalid // FIQ EL1t - kernel_ventry el1_error_invalid // Error EL1t + kernel_ventry 1, sync_invalid // Synchronous EL1t + kernel_ventry 1, irq_invalid // IRQ EL1t + kernel_ventry 1, fiq_invalid // FIQ EL1t + kernel_ventry 1, error_invalid // Error EL1t - kernel_ventry el1_sync // Synchronous EL1h - kernel_ventry el1_irq // IRQ EL1h - kernel_ventry el1_fiq_invalid // FIQ EL1h - kernel_ventry el1_error_invalid // Error EL1h + kernel_ventry 1, sync // Synchronous EL1h + kernel_ventry 1, irq // IRQ EL1h + kernel_ventry 1, fiq_invalid // FIQ EL1h + kernel_ventry 1, error_invalid // Error EL1h - kernel_ventry el0_sync // Synchronous 64-bit EL0 - kernel_ventry el0_irq // IRQ 64-bit EL0 - kernel_ventry el0_fiq_invalid // FIQ 64-bit EL0 - kernel_ventry el0_error_invalid // Error 64-bit EL0 + kernel_ventry 0, sync // Synchronous 64-bit EL0 + kernel_ventry 0, irq // IRQ 64-bit EL0 + kernel_ventry 0, fiq_invalid // FIQ 64-bit EL0 + kernel_ventry 0, error_invalid // Error 64-bit EL0 #ifdef CONFIG_COMPAT - kernel_ventry el0_sync_compat // Synchronous 32-bit EL0 - kernel_ventry el0_irq_compat // IRQ 32-bit EL0 - kernel_ventry el0_fiq_invalid_compat // FIQ 32-bit EL0 - kernel_ventry el0_error_invalid_compat // Error 32-bit EL0 + kernel_ventry 0, sync_compat, 32 // Synchronous 32-bit EL0 + kernel_ventry 0, irq_compat, 32 // IRQ 32-bit EL0 + kernel_ventry 0, fiq_invalid_compat, 32 // FIQ 32-bit EL0 + kernel_ventry 0, error_invalid_compat, 32 // Error 32-bit EL0 #else - kernel_ventry el0_sync_invalid // Synchronous 32-bit EL0 - kernel_ventry el0_irq_invalid // IRQ 32-bit EL0 - kernel_ventry el0_fiq_invalid // FIQ 32-bit EL0 - kernel_ventry el0_error_invalid // Error 32-bit EL0 + kernel_ventry 0, sync_invalid, 32 // Synchronous 32-bit EL0 + kernel_ventry 0, irq_invalid, 32 // IRQ 32-bit EL0 + kernel_ventry 0, fiq_invalid, 32 // FIQ 32-bit EL0 + kernel_ventry 0, error_invalid, 32 // Error 32-bit EL0 #endif END(vectors) From 5a9b2052bfc853403efef0cda48905c4e0f7aa2d Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 14 Nov 2017 14:24:29 +0000 Subject: [PATCH 060/508] FROMLIST: arm64: entry: Hook up entry trampoline to exception vectors Hook up the entry trampoline to our exception vectors so that all exceptions from and returns to EL0 go via the trampoline, which swizzles the vector base register accordingly. Transitioning to and from the kernel clobbers x30, so we use tpidrro_el0 and far_el1 as scratch registers for native tasks. Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit 4bf3286d29f3a88425d8d8cd53428cbb8f865f04) [ghackmann@google.com: adjust context, replacing alternative_if_not ARM64_WORKAROUND_845719 block with upstream version] Signed-off-by: Greg Hackmann Change-Id: I0f50f6ce0e28f2ca8d98a93c96809adf71a2f5e4 Git-Commit: 5ed26716ffb768970fe8ffbd68b050ce10a62431 Git-repo: git://android.googlesource.com/kernel/common.git Signed-off-by: Vinayak Menon --- arch/arm64/kernel/entry.S | 49 ++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index c69a43e0fdacd..303802c62dec2 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -72,10 +72,26 @@ .macro kernel_ventry, el, label, regsize = 64 .align 7 +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 + .if \el == 0 + .if \regsize == 64 + mrs x30, tpidrro_el0 + msr tpidrro_el0, xzr + .else + mov x30, xzr + .endif + .endif +#endif + sub sp, sp, #S_FRAME_SIZE b el\()\el\()_\label .endm + .macro tramp_alias, dst, sym + mov_q \dst, TRAMP_VALIAS + add \dst, \dst, #(\sym - .entry.tramp.text) + .endm + .macro kernel_entry, el, regsize = 64 .if \regsize == 32 mov w0, w0 // zero upper 32 bits of x0 @@ -205,24 +221,20 @@ alternative_else_nop_endif .if \el == 0 ldr x23, [sp, #S_SP] // load return stack pointer msr sp_el0, x23 + tst x22, #PSR_MODE32_BIT // native task? + b.eq 3f + #ifdef CONFIG_ARM64_ERRATUM_845719 -alternative_if_not ARM64_WORKAROUND_845719 - nop - nop -#ifdef CONFIG_PID_IN_CONTEXTIDR - nop -#endif -alternative_else - tbz x22, #4, 1f +alternative_if ARM64_WORKAROUND_845719 #ifdef CONFIG_PID_IN_CONTEXTIDR mrs x29, contextidr_el1 msr contextidr_el1, x29 #else msr contextidr_el1, xzr #endif -1: -alternative_endif +alternative_else_nop_endif #endif +3: .endif msr elr_el1, x21 // set up the return data @@ -244,7 +256,22 @@ alternative_endif ldp x28, x29, [sp, #16 * 14] ldr lr, [sp, #S_LR] add sp, sp, #S_FRAME_SIZE // restore sp - eret // return to kernel + +#ifndef CONFIG_UNMAP_KERNEL_AT_EL0 + eret +#else + .if \el == 0 + bne 4f + msr far_el1, x30 + tramp_alias x30, tramp_exit_native + br x30 +4: + tramp_alias x30, tramp_exit_compat + br x30 + .else + eret + .endif +#endif .endm /* From 9234f16b1a616c8d63ee7f07854d4a7b4ce5ccd1 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 14 Nov 2017 14:29:19 +0000 Subject: [PATCH 061/508] FROMLIST: arm64: erratum: Work around Falkor erratum #E1003 in trampoline code We rely on an atomic swizzling of TTBR1 when transitioning from the entry trampoline to the kernel proper on an exception. We can't rely on this atomicity in the face of Falkor erratum #E1003, so on affected cores we can issue a TLB invalidation to invalidate the walk cache prior to jumping into the kernel. There is still the possibility of a TLB conflict here due to conflicting walk cache entries prior to the invalidation, but this doesn't appear to be the case on these CPUs in practice. Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit d1777e686ad10ba7c594304429c6045fb79255a1) [ghackmann@google.com: replace runtime alternative_if with a compile-time check for Code Aurora's out-of-tree CONFIG_ARCH_MSM8996. Kryo needs this workaround too, and 4.4 doesn't have any of the upstream Falkor errata infrastructure needed to detect this at boot time.] Signed-off-by: Greg Hackmann Change-Id: I22423d93396d012e4326f2b56e4da39c27aaa665 Git-Commit: 1766a613ec0c59cb5f463364a20b74596c636768 Git-repo: git://android.googlesource.com/kernel/common.git Signed-off-by: Vinayak Menon --- arch/arm64/kernel/entry.S | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 303802c62dec2..035e07223ce2d 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -897,6 +897,16 @@ __ni_sys_trace: sub \tmp, \tmp, #(SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE) bic \tmp, \tmp, #USER_ASID_FLAG msr ttbr1_el1, \tmp +#ifdef CONFIG_ARCH_MSM8996 + /* ASID already in \tmp[63:48] */ + movk \tmp, #:abs_g2_nc:(TRAMP_VALIAS >> 12) + movk \tmp, #:abs_g1_nc:(TRAMP_VALIAS >> 12) + /* 2MB boundary containing the vectors, so we nobble the walk cache */ + movk \tmp, #:abs_g0_nc:((TRAMP_VALIAS & ~(SZ_2M - 1)) >> 12) + isb + tlbi vae1, \tmp + dsb nsh +#endif /* CONFIG_ARCH_MSM8996 */ .endm .macro tramp_unmap_kernel, tmp From 6e0e4dfcfcf53e81a290c36a9200aa5da85ab85e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 14 Nov 2017 14:33:28 +0000 Subject: [PATCH 062/508] FROMLIST: arm64: tls: Avoid unconditional zeroing of tpidrro_el0 for native tasks When unmapping the kernel at EL0, we use tpidrro_el0 as a scratch register during exception entry from native tasks and subsequently zero it in the kernel_ventry macro. We can therefore avoid zeroing tpidrro_el0 in the context-switch path for native tasks using the entry trampoline. Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit 18011eac28c7cb31c87b86b7d0e5b01894405c7f) [ghackmann@google.com: - adjust context - replace task_user_tls() accessor with equivalent field from 3.18] Signed-off-by: Greg Hackmann Change-Id: Ib1ffb34e6f3a722ca111a8fb1811cbc79ffd22fe Git-Commit: f47c91dcfa2accf4fd04a39398acbdc1237ca87e Git-repo: git://android.googlesource.com/kernel/common.git [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- arch/arm64/kernel/process.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 9c478de7032bc..f11d7e4b375bb 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -357,25 +357,18 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start, static void tls_thread_switch(struct task_struct *next) { - unsigned long tpidr, tpidrro; - if (!is_compat_task()) { + unsigned long tpidr; asm("mrs %0, tpidr_el0" : "=r" (tpidr)); current->thread.tp_value = tpidr; } - if (is_compat_thread(task_thread_info(next))) { - tpidr = 0; - tpidrro = next->thread.tp_value; - } else { - tpidr = next->thread.tp_value; - tpidrro = 0; - } + if (is_compat_thread(task_thread_info(next))) + write_sysreg(next->thread.tp_value, tpidrro_el0); + else if (!arm64_kernel_unmapped_at_el0()) + write_sysreg(0, tpidrro_el0); - asm( - " msr tpidr_el0, %0\n" - " msr tpidrro_el0, %1" - : : "r" (tpidr), "r" (tpidrro)); + write_sysreg(next->thread.tp_value, tpidr_el0); } /* Restore the UAO state depending on next's addr_limit */ From f2bcdf8c377e3a7a5c3948681167578321645552 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 14 Nov 2017 14:38:19 +0000 Subject: [PATCH 063/508] FROMLIST: arm64: entry: Add fake CPU feature for unmapping the kernel at EL0 Allow explicit disabling of the entry trampoline on the kernel command line (kpti=off) by adding a fake CPU feature (ARM64_UNMAP_KERNEL_AT_EL0) that can be used to toggle the alternative sequences in our entry code and avoid use of the trampoline altogether if desired. This also allows us to make use of a static key in arm64_kernel_unmapped_at_el0(). Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit ea1e3de85e94d711f63437c04624aa0e8de5c8b3) [ghackmann@google.com: - adjust context - apply cpucaps.h changes to cpufeature.h - replace cpus_have_const_cap() with cpus_have_cap(), and include the header that declares it - tweak unmap_kernel_at_el0() declaration to match 3.18 APIs] Signed-off-by: Greg Hackmann Change-Id: Iae8a237330d5d66188eb76199fd139c0fb7ba97f Git-Commit: 2b4c5c1fdab1aa2ef29514eb71920c8fe77aa62b Git-repo: git://android.googlesource.com/kernel/common.git Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/cpufeature.h | 3 ++- arch/arm64/include/asm/mmu.h | 5 +++- arch/arm64/kernel/cpufeature.c | 39 +++++++++++++++++++++++++++++ arch/arm64/kernel/entry.S | 9 ++++--- 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index a0789bfc4ac65..ba6983e901d53 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -29,8 +29,9 @@ #define ARM64_HAS_PAN 4 #define ARM64_HAS_UAO 5 #define ARM64_ALT_PAN_NOT_UAO 6 +#define ARM64_UNMAP_KERNEL_AT_EL0 23 -#define ARM64_NCAPS 7 +#define ARM64_NCAPS 24 #ifndef __ASSEMBLY__ diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index d943896670662..bdd3fdc9b2439 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -20,6 +20,8 @@ #ifndef __ASSEMBLY__ +#include + typedef struct { atomic64_t id; void *vdso; @@ -34,7 +36,8 @@ typedef struct { static inline bool arm64_kernel_unmapped_at_el0(void) { - return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0); + return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0) && + cpus_have_cap(ARM64_UNMAP_KERNEL_AT_EL0); } extern void paging_init(void); diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 58347534d765b..ec7e68c2c73fa 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -617,6 +617,39 @@ has_cpuid_feature(const struct arm64_cpu_capabilities *entry) return feature_matches(val, entry); } +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */ + +static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry) +{ + /* Forced on command line? */ + if (__kpti_forced) { + pr_info_once("kernel page table isolation forced %s by command line option\n", + __kpti_forced > 0 ? "ON" : "OFF"); + return __kpti_forced > 0; + } + + /* Useful for KASLR robustness */ + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) + return true; + + return false; +} + +static int __init parse_kpti(char *str) +{ + bool enabled; + int ret = strtobool(str, &enabled); + + if (ret) + return ret; + + __kpti_forced = enabled ? 1 : -1; + return 0; +} +__setup("kpti=", parse_kpti); +#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ + static const struct arm64_cpu_capabilities arm64_features[] = { { .desc = "GIC system register CPU interface", @@ -654,6 +687,12 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .matches = cpufeature_pan_not_uao, }, #endif /* CONFIG_ARM64_PAN */ +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 + { + .capability = ARM64_UNMAP_KERNEL_AT_EL0, + .matches = unmap_kernel_at_el0, + }, +#endif {}, }; diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 035e07223ce2d..6296e59be9c96 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -73,6 +73,7 @@ .macro kernel_ventry, el, label, regsize = 64 .align 7 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +alternative_if ARM64_UNMAP_KERNEL_AT_EL0 .if \el == 0 .if \regsize == 64 mrs x30, tpidrro_el0 @@ -81,6 +82,7 @@ mov x30, xzr .endif .endif +alternative_else_nop_endif #endif sub sp, sp, #S_FRAME_SIZE @@ -257,10 +259,9 @@ alternative_else_nop_endif ldr lr, [sp, #S_LR] add sp, sp, #S_FRAME_SIZE // restore sp -#ifndef CONFIG_UNMAP_KERNEL_AT_EL0 - eret -#else .if \el == 0 +alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0 +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 bne 4f msr far_el1, x30 tramp_alias x30, tramp_exit_native @@ -268,10 +269,10 @@ alternative_else_nop_endif 4: tramp_alias x30, tramp_exit_compat br x30 +#endif .else eret .endif -#endif .endm /* From 3459d10510700c40c0cce817359a78e1742b2250 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 14 Nov 2017 14:41:01 +0000 Subject: [PATCH 064/508] FROMLIST: arm64: Kconfig: Add CONFIG_UNMAP_KERNEL_AT_EL0 Add a Kconfig entry to control use of the entry trampoline, which allows us to unmap the kernel whilst running in userspace and improve the robustness of KASLR. Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit 084eb77cd3a81134d02500977dc0ecc9277dc97d) Signed-off-by: Greg Hackmann Change-Id: Iff788c61b8a993088ed41d6251363e767dfa4e71 Git-Commit: 3ec3abcbf78fa2ab4251c5fdbffc2bafff922204 Git-repo: git://android.googlesource.com/kernel/common.git Signed-off-by: Vinayak Menon --- arch/arm64/Kconfig | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 0444366b29d75..33f309a5bda50 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -801,6 +801,19 @@ config FORCE_MAX_ZONEORDER default "14" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE) default "11" +config UNMAP_KERNEL_AT_EL0 + bool "Unmap kernel when running in userspace (aka \"KAISER\")" + default y + help + Some attacks against KASLR make use of the timing difference between + a permission fault which could arise from a page table entry that is + present in the TLB, and a translation fault which always requires a + page table walk. This option defends against these attacks by unmapping + the kernel whilst running in userspace, therefore forcing translation + faults for all of kernel space. + + If unsure, say Y. + menuconfig ARMV8_DEPRECATED bool "Emulate deprecated/obsolete ARMv8 instructions" depends on COMPAT From cf4324bbc4a119d4d46b8969bb0aaf6bbc5bead2 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 1 Dec 2017 17:33:48 +0000 Subject: [PATCH 065/508] FROMLIST: arm64: mm: Introduce TTBR_ASID_MASK for getting at the ASID in the TTBR There are now a handful of open-coded masks to extract the ASID from a TTBR value, so introduce a TTBR_ASID_MASK and use that instead. Suggested-by: Mark Rutland Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit b519538dfefc2f8478a1bcb458459c861d431784) [ghackmann@google.com: adjust context, applying asm-uaccess.h changes to uaccess.h instead] Signed-off-by: Greg Hackmann Change-Id: Ia600fb2e89a40fd4e9e0b2efca9b09f166ad73ec Git-Commit: 7b87b5746ca28b470af1dc2f019c252e7619cd3a Git-repo: git://android.googlesource.com/kernel/common.git Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/mmu.h | 1 + arch/arm64/include/asm/uaccess.h | 7 ++++--- arch/arm64/kernel/entry.S | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index bdd3fdc9b2439..2fbe8cc639c73 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -17,6 +17,7 @@ #define __ASM_MMU_H #define USER_ASID_FLAG (UL(1) << 48) +#define TTBR_ASID_MASK (UL(0xffff) << 48) #ifndef __ASSEMBLY__ diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index cfef719287d92..e7cb0e6cbdaa8 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -20,6 +20,7 @@ #include #include +#include #include #ifndef __ASSEMBLY__ @@ -141,7 +142,7 @@ static inline void __uaccess_ttbr0_disable(void) write_sysreg(ttbr + SWAPPER_DIR_SIZE, ttbr0_el1); isb(); /* Set reserved ASID */ - ttbr &= ~(0xffffUL << 48); + ttbr &= ~TTBR_ASID_MASK; write_sysreg(ttbr, ttbr1_el1); isb(); } @@ -160,7 +161,7 @@ static inline void __uaccess_ttbr0_enable(void) /* Restore active ASID */ ttbr1 = read_sysreg(ttbr1_el1); - ttbr1 |= ttbr0 & (0xffffUL << 48); + ttbr1 |= ttbr0 & TTBR_ASID_MASK; write_sysreg(ttbr1, ttbr1_el1); isb(); @@ -454,7 +455,7 @@ extern __must_check long strnlen_user(const char __user *str, long n); msr ttbr0_el1, \tmp1 // set reserved TTBR0_EL1 isb sub \tmp1, \tmp1, #SWAPPER_DIR_SIZE - bic \tmp1, \tmp1, #(0xffff << 48) + bic \tmp1, \tmp1, #TTBR_ASID_MASK msr ttbr1_el1, \tmp1 // set reserved ASID isb .endm diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 6296e59be9c96..cd623e28b2dc3 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -149,7 +149,7 @@ alternative_else_nop_endif .if \el != 0 mrs x21, ttbr1_el1 - tst x21, #0xffff << 48 // Check for the reserved ASID + tst x21, #TTBR_ASID_MASK // Check for the reserved ASID orr x23, x23, #PSR_PAN_BIT // Set the emulated PAN in the saved SPSR b.eq 1f // TTBR0 access already disabled and x23, x23, #~PSR_PAN_BIT // Clear the emulated PAN in the saved SPSR From 17658ae14d5f434581d3cd238471f4cf51167b6f Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 6 Dec 2017 11:24:02 +0000 Subject: [PATCH 066/508] FROMLIST: arm64: kaslr: Put kernel vectors address in separate data page The literal pool entry for identifying the vectors base is the only piece of information in the trampoline page that identifies the true location of the kernel. This patch moves it into a page-aligned region of the .rodata section and maps this adjacent to the trampoline text via an additional fixmap entry, which protects against any accidental leakage of the trampoline contents. Suggested-by: Ard Biesheuvel Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit 6c27c4082f4f70b9f41df4d0adf51128b40351df) [ghackmann@google.com: - adjust context - replace ARM64_WORKAROUND_QCOM_FALKOR_E1003 alternative with compile-time CONFIG_ARCH_MSM8996 check] Signed-off-by: Greg Hackmann Change-Id: Id96c1b0eaca8d2ff2e91320ac13d76b18d05fdd5 Git-Commit: 90523e83073be8fe4b6afd6de4f8467bc0c4dc86 Git-repo: git://android.googlesource.com/kernel/common.git Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/fixmap.h | 1 + arch/arm64/kernel/entry.S | 16 ++++++++++++++++ arch/arm64/kernel/vmlinux.lds.S | 4 ++++ arch/arm64/mm/mmu.c | 10 +++++++++- 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h index cc9b9a6a238c5..6c5bf65c6f4a9 100644 --- a/arch/arm64/include/asm/fixmap.h +++ b/arch/arm64/include/asm/fixmap.h @@ -34,6 +34,7 @@ enum fixed_addresses { FIX_HOLE, FIX_EARLYCON_MEM_BASE, #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 + FIX_ENTRY_TRAMP_DATA, FIX_ENTRY_TRAMP_TEXT, #define TRAMP_VALIAS (__fix_to_virt(FIX_ENTRY_TRAMP_TEXT)) #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index cd623e28b2dc3..9a78650f64b22 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -936,7 +936,15 @@ __ni_sys_trace: msr tpidrro_el0, x30 // Restored in kernel_ventry .endif tramp_map_kernel x30 +#ifdef CONFIG_RANDOMIZE_BASE + adr x30, tramp_vectors + PAGE_SIZE +#ifndef CONFIG_ARCH_MSM8996 + isb +#endif + ldr x30, [x30] +#else ldr x30, =vectors +#endif prfm plil1strm, [x30, #(1b - tramp_vectors)] msr vbar_el1, x30 add x30, x30, #(1b - tramp_vectors) @@ -979,6 +987,14 @@ END(tramp_exit_compat) .ltorg .popsection // .entry.tramp.text +#ifdef CONFIG_RANDOMIZE_BASE + .pushsection ".rodata", "a" + .align PAGE_SHIFT + .globl __entry_tramp_data_start +__entry_tramp_data_start: + .quad vectors + .popsection // .rodata +#endif /* CONFIG_RANDOMIZE_BASE */ #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ /* diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 1ded30f007b42..de800b0cc5459 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -197,6 +197,10 @@ SECTIONS ASSERT(((__hyp_idmap_text_start + PAGE_SIZE) > __hyp_idmap_text_end), "HYP init code too big") +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) == PAGE_SIZE, + "Entry trampoline text too big") +#endif /* * If padding is applied before .head.text, virt<->phys conversions will fail. */ diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index b5d7dbc41e499..17b6b4021b20f 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -700,8 +700,16 @@ static int __init map_entry_trampoline(void) __create_mapping(NULL, tramp_pg_dir + pgd_index(TRAMP_VALIAS), pa_start, TRAMP_VALIAS, PAGE_SIZE, prot, pgd_pgtable_alloc, false); - /* ...as well as the kernel page table */ + /* Map both the text and data into the kernel page table */ __set_fixmap(FIX_ENTRY_TRAMP_TEXT, pa_start, prot); + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { + extern char __entry_tramp_data_start[]; + + __set_fixmap(FIX_ENTRY_TRAMP_DATA, + __pa_symbol(__entry_tramp_data_start), + PAGE_KERNEL_RO); + } + return 0; } core_initcall(map_entry_trampoline); From f42c3641def8da6853bcf7410302b9f6db8b167b Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 14 Nov 2017 16:15:59 +0000 Subject: [PATCH 067/508] arm64: use RET instruction for exiting the trampoline Speculation attacks against the entry trampoline can potentially resteer the speculative instruction stream through the indirect branch and into arbitrary gadgets within the kernel. This patch defends against these attacks by forcing a misprediction through the return stack: a dummy BL instruction loads an entry into the stack, so that the predicted program flow of the subsequent RET instruction is to a branch-to-self instruction which is finally resolved as a branch to the kernel vectors with speculation suppressed. Signed-off-by: Will Deacon Signed-off-by: Greg Kroah-Hartman Change-Id: Ief67c5d2c48cbc8cf8506a79e396d0d36df2fd51 Git-Commit: 5baaf50ec1ec2b93291afd2ee9b84a82b3ad30c9 Git-repo: git://android.googlesource.com/kernel/common.git Signed-off-by: Vinayak Menon --- arch/arm64/kernel/entry.S | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 9a78650f64b22..6c28b1e8608ce 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -935,6 +935,9 @@ __ni_sys_trace: .if \regsize == 64 msr tpidrro_el0, x30 // Restored in kernel_ventry .endif + bl 2f + b . +2: tramp_map_kernel x30 #ifdef CONFIG_RANDOMIZE_BASE adr x30, tramp_vectors + PAGE_SIZE @@ -949,7 +952,7 @@ __ni_sys_trace: msr vbar_el1, x30 add x30, x30, #(1b - tramp_vectors) isb - br x30 + ret .endm .macro tramp_exit, regsize = 64 From c75b58589c0330d4fa6ee3c1d35f01e7e503ae0c Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 14 Nov 2017 16:19:39 +0000 Subject: [PATCH 068/508] arm64: Kconfig: Reword UNMAP_KERNEL_AT_EL0 kconfig entry Although CONFIG_UNMAP_KERNEL_AT_EL0 does make KASLR more robust, it's actually more useful as a mitigation against speculation attacks that can leak arbitrary kernel data to userspace through speculation. Reword the Kconfig help message to reflect this, and make the option depend on EXPERT so that it is on by default for the majority of users. Signed-off-by: Will Deacon Signed-off-by: Greg Kroah-Hartman Change-Id: I2056d452aa0015384a5b09a67b0a22e548b42e1e Git-Commit: 2897537bc331dba2c79238a18d62d11fd372a2a9 Git-repo: git://android.googlesource.com/kernel/common.git [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- arch/arm64/Kconfig | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 33f309a5bda50..0625f78596bba 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -802,15 +802,14 @@ config FORCE_MAX_ZONEORDER default "11" config UNMAP_KERNEL_AT_EL0 - bool "Unmap kernel when running in userspace (aka \"KAISER\")" + bool "Unmap kernel when running in userspace (aka \"KAISER\")" if EXPERT default y help - Some attacks against KASLR make use of the timing difference between - a permission fault which could arise from a page table entry that is - present in the TLB, and a translation fault which always requires a - page table walk. This option defends against these attacks by unmapping - the kernel whilst running in userspace, therefore forcing translation - faults for all of kernel space. + Speculation attacks against some high-performance processors can + be used to bypass MMU permission checks and leak kernel data to + userspace. This can be defended against by unmapping the kernel + when running in userspace, mapping it back in on exception entry + via a trampoline page in the vector table. If unsure, say Y. From 5e329e4788e004deeebed7cdeaa586a7205c4c4a Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 2 Jan 2018 18:19:39 +0000 Subject: [PATCH 069/508] FROMLIST: arm64: Move post_ttbr_update_workaround to C code We will soon need to invoke a CPU-specific function pointer after changing page tables, so move post_ttbr_update_workaround out into C code to make this possible. Signed-off-by: Marc Zyngier Signed-off-by: Will Deacon (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit 400a169447ad2268b023637a118fba27246bcc19) Change-Id: Ic21e59001470a2e88db7291eb5f6393f8a64a7dd [ghackmann@google.com: 3.18 doesn't support CPUs that need the Cavium errata, so for now post_ttbr_update_workaround() is an empty stub that will be used in a later patch series.] Signed-off-by: Greg Hackmann Git-Commit: 0bfb4642f8e8a37d18595bb6067f38fe4b38b425 Git-repo: git://android.googlesource.com/kernel/common.git Signed-off-by: Vinayak Menon --- arch/arm64/kernel/entry.S | 10 ++++++++++ arch/arm64/mm/context.c | 5 +++++ arch/arm64/mm/proc.S | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 6c28b1e8608ce..f5689e9ac0aa3 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -213,6 +213,16 @@ alternative_else_nop_endif .endif __uaccess_ttbr0_enable x0, x1 + + .if \el == 0 + /* + * Enable errata workarounds only if returning to user. The only + * workaround currently required for TTBR0_EL1 changes are for the + * Cavium erratum 27456 (broadcast TLBI instructions may cause I-cache + * corruption). + */ + bl post_ttbr_update_workaround + .endif 1: .if \el != 0 and x22, x22, #~PSR_PAN_BIT // ARMv8.0 CPUs do not understand this bit diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c index 10d68e438a372..cc3664b088dec 100644 --- a/arch/arm64/mm/context.c +++ b/arch/arm64/mm/context.c @@ -199,6 +199,11 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu) cpu_switch_mm(mm->pgd, mm); } +/* Errata workaround post TTBRx_EL1 update. */ +asmlinkage void post_ttbr_update_workaround(void) +{ +} + static int asids_init(void) { int fld = cpuid_feature_extract_field(read_cpuid(SYS_ID_AA64MMFR0_EL1), 4); diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index 3cbf35a958218..b3b4e8ee8e54d 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -134,7 +134,7 @@ ENTRY(cpu_do_switch_mm) isb msr ttbr0_el1, x0 // now update TTBR0 isb - ret + b post_ttbr_update_workaround // Back to C code... ENDPROC(cpu_do_switch_mm) .section ".text.init", #alloc, #execinstr From d19bcc64aa2085e6a025e306984dd527baf42613 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 10 Jan 2018 13:18:30 +0000 Subject: [PATCH 070/508] FROMLIST: arm64: kpti: Fix the interaction between ASID switching and software PAN With ARM64_SW_TTBR0_PAN enabled, the exception entry code checks the active ASID to decide whether user access was enabled (non-zero ASID) when the exception was taken. On return from exception, if user access was previously disabled, it re-instates TTBR0_EL1 from the per-thread saved value (updated in switch_mm() or efi_set_pgd()). Commit 7655abb95386 ("arm64: mm: Move ASID from TTBR0 to TTBR1") makes a TTBR0_EL1 + ASID switching non-atomic. Subsequently, commit 27a921e75711 ("arm64: mm: Fix and re-enable ARM64_SW_TTBR0_PAN") changes the __uaccess_ttbr0_disable() function and asm macro to first write the reserved TTBR0_EL1 followed by the ASID=0 update in TTBR1_EL1. If an exception occurs between these two, the exception return code will re-instate a valid TTBR0_EL1. Similar scenario can happen in cpu_switch_mm() between setting the reserved TTBR0_EL1 and the ASID update in cpu_do_switch_mm(). This patch reverts the entry.S check for ASID == 0 to TTBR0_EL1 and disables the interrupts around the TTBR0_EL1 and ASID switching code in __uaccess_ttbr0_disable(). It also ensures that, when returning from the EFI runtime services, efi_set_pgd() doesn't leave a non-zero ASID in TTBR1_EL1 by using uaccess_ttbr0_{enable,disable}. The accesses to current_thread_info()->ttbr0 are updated to use READ_ONCE/WRITE_ONCE. As a safety measure, __uaccess_ttbr0_enable() always masks out any existing non-zero ASID TTBR1_EL1 before writing in the new ASID. Fixes: 27a921e75711 ("arm64: mm: Fix and re-enable ARM64_SW_TTBR0_PAN") Acked-by: Will Deacon Reported-by: Ard Biesheuvel Tested-by: Ard Biesheuvel Reviewed-by: James Morse Tested-by: James Morse Co-developed-by: Marc Zyngier Signed-off-by: Catalin Marinas (cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git commit 6b88a32c7af68895134872cdec3b6bfdb532d94e) Change-Id: I1597fe926e4d7fc0f2c19dc63efbd359b5033796 [ghackmann@google.com: - adjust context - apply asm-uaccess.h changes to uaccess.h, and efi.h changes to efi.c] Signed-off-by: Greg Hackmann Git-Commit: cf43f2035a3f491b9977999909a76b1444b2be0c Git-repo: git://android.googlesource.com/kernel/common.git [vinmenon@codeaurora.org: changes to mmu_context.h and efi.c due to extra SW PAN fixes on this branch] Signed-off-by: Vinayak Menon --- arch/arm64/include/asm/mmu_context.h | 4 +++- arch/arm64/include/asm/uaccess.h | 21 +++++++++++++-------- arch/arm64/kernel/efi.c | 12 +++++++----- arch/arm64/kernel/entry.S | 2 +- arch/arm64/lib/clear_user.S | 2 +- arch/arm64/lib/copy_from_user.S | 2 +- arch/arm64/lib/copy_in_user.S | 2 +- arch/arm64/lib/copy_to_user.S | 2 +- arch/arm64/mm/cache.S | 2 +- arch/arm64/mm/proc.S | 3 +++ arch/arm64/xen/hypercall.S | 2 +- 11 files changed, 33 insertions(+), 21 deletions(-) diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h index 2156ee710274b..3c092a7c54821 100644 --- a/arch/arm64/include/asm/mmu_context.h +++ b/arch/arm64/include/asm/mmu_context.h @@ -130,7 +130,7 @@ static inline void update_saved_ttbr0(struct task_struct *tsk, else ttbr = virt_to_phys(mm->pgd) | ASID(mm) << 48; - task_thread_info(tsk)->ttbr0 = ttbr; + WRITE_ONCE(task_thread_info(tsk)->ttbr0, ttbr); } #else static inline void update_saved_ttbr0(struct task_struct *tsk, @@ -184,4 +184,6 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, #define deactivate_mm(tsk,mm) do { } while (0) #define activate_mm(prev,next) switch_mm(prev, next, current) +void post_ttbr_update_workaround(void); + #endif diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index e7cb0e6cbdaa8..998ca85840dff 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -135,16 +135,18 @@ static inline void set_fs(mm_segment_t fs) #ifdef CONFIG_ARM64_SW_TTBR0_PAN static inline void __uaccess_ttbr0_disable(void) { - unsigned long ttbr; + unsigned long flags, ttbr; + local_irq_save(flags); ttbr = read_sysreg(ttbr1_el1); + ttbr &= ~TTBR_ASID_MASK; /* reserved_ttbr0 placed at the end of swapper_pg_dir */ write_sysreg(ttbr + SWAPPER_DIR_SIZE, ttbr0_el1); isb(); /* Set reserved ASID */ - ttbr &= ~TTBR_ASID_MASK; write_sysreg(ttbr, ttbr1_el1); isb(); + local_irq_restore(flags); } static inline void __uaccess_ttbr0_enable(void) @@ -157,10 +159,11 @@ static inline void __uaccess_ttbr0_enable(void) * roll-over and an update of 'ttbr0'. */ local_irq_save(flags); - ttbr0 = current_thread_info()->ttbr0; + ttbr0 = READ_ONCE(current_thread_info()->ttbr0); /* Restore active ASID */ ttbr1 = read_sysreg(ttbr1_el1); + ttbr1 &= ~TTBR_ASID_MASK; /* safety measure */ ttbr1 |= ttbr0 & TTBR_ASID_MASK; write_sysreg(ttbr1, ttbr1_el1); isb(); @@ -451,11 +454,11 @@ extern __must_check long strnlen_user(const char __user *str, long n); #ifdef CONFIG_ARM64_SW_TTBR0_PAN .macro __uaccess_ttbr0_disable, tmp1 mrs \tmp1, ttbr1_el1 // swapper_pg_dir + bic \tmp1, \tmp1, #TTBR_ASID_MASK add \tmp1, \tmp1, #SWAPPER_DIR_SIZE // reserved_ttbr0 at the end of swapper_pg_dir msr ttbr0_el1, \tmp1 // set reserved TTBR0_EL1 isb sub \tmp1, \tmp1, #SWAPPER_DIR_SIZE - bic \tmp1, \tmp1, #TTBR_ASID_MASK msr ttbr1_el1, \tmp1 // set reserved ASID isb .endm @@ -472,9 +475,11 @@ extern __must_check long strnlen_user(const char __user *str, long n); isb .endm - .macro uaccess_ttbr0_disable, tmp1 + .macro uaccess_ttbr0_disable, tmp1, tmp2 alternative_if_not ARM64_HAS_PAN + save_and_disable_irq \tmp2 // avoid preemption __uaccess_ttbr0_disable \tmp1 + restore_irq \tmp2 alternative_else_nop_endif .endm @@ -486,7 +491,7 @@ alternative_if_not ARM64_HAS_PAN alternative_else_nop_endif .endm #else - .macro uaccess_ttbr0_disable, tmp1 + .macro uaccess_ttbr0_disable, tmp1, tmp2 .endm .macro uaccess_ttbr0_enable, tmp1, tmp2, tmp3 @@ -496,8 +501,8 @@ alternative_else_nop_endif /* * These macros are no-ops when UAO is present. */ - .macro uaccess_disable_not_uao, tmp1 - uaccess_ttbr0_disable \tmp1 + .macro uaccess_disable_not_uao, tmp1, tmp2 + uaccess_ttbr0_disable \tmp1, \tmp2 alternative_if ARM64_ALT_PAN_NOT_UAO SET_PSTATE_PAN(1) alternative_else_nop_endif diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 0e4f402578ee8..df060c5da8d4b 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -345,19 +345,21 @@ static void efi_set_pgd(struct mm_struct *mm) if (mm != current->active_mm) { /* * Update the current thread's saved ttbr0 since it is - * restored as part of a return from exception. Set - * the hardware TTBR0_EL1 using cpu_switch_mm() - * directly to enable potential errata workarounds. + * restored as part of a return from exception. Enable + * access to the valid TTBR0_EL1 and invoke the errata + * workaround directly since there is no return from + * exception when invoking the EFI run-time services. */ update_saved_ttbr0(current, mm); - cpu_switch_mm(mm->pgd, mm); + uaccess_ttbr0_enable(); + post_ttbr_update_workaround(); } else { /* * Defer the switch to the current thread's TTBR0_EL1 * until uaccess_enable(). Restore the current * thread's saved ttbr0 corresponding to its active_mm */ - cpu_set_reserved_ttbr0(); + uaccess_ttbr0_disable(); update_saved_ttbr0(current, current->active_mm); } } diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index f5689e9ac0aa3..a86ba11be6345 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -148,7 +148,7 @@ alternative_if ARM64_HAS_PAN alternative_else_nop_endif .if \el != 0 - mrs x21, ttbr1_el1 + mrs x21, ttbr0_el1 tst x21, #TTBR_ASID_MASK // Check for the reserved ASID orr x23, x23, #PSR_PAN_BIT // Set the emulated PAN in the saved SPSR b.eq 1f // TTBR0 access already disabled diff --git a/arch/arm64/lib/clear_user.S b/arch/arm64/lib/clear_user.S index dd65ca253eb4e..07c7ad97ee281 100644 --- a/arch/arm64/lib/clear_user.S +++ b/arch/arm64/lib/clear_user.S @@ -50,7 +50,7 @@ uao_user_alternative 9f, strh, sttrh, wzr, x0, 2 b.mi 5f uao_user_alternative 9f, strb, sttrb, wzr, x0, 0 5: mov x0, #0 - uaccess_disable_not_uao x2 + uaccess_disable_not_uao x2, x3 ret ENDPROC(__clear_user) diff --git a/arch/arm64/lib/copy_from_user.S b/arch/arm64/lib/copy_from_user.S index 1ff23f81e2426..683adc358be7d 100644 --- a/arch/arm64/lib/copy_from_user.S +++ b/arch/arm64/lib/copy_from_user.S @@ -67,7 +67,7 @@ ENTRY(__arch_copy_from_user) uaccess_enable_not_uao x3, x4, x5 add end, x0, x2 #include "copy_template.S" - uaccess_disable_not_uao x3 + uaccess_disable_not_uao x3, x4 mov x0, #0 // Nothing to copy ret ENDPROC(__arch_copy_from_user) diff --git a/arch/arm64/lib/copy_in_user.S b/arch/arm64/lib/copy_in_user.S index 074d52fcd75ba..e8bfaf19f778f 100644 --- a/arch/arm64/lib/copy_in_user.S +++ b/arch/arm64/lib/copy_in_user.S @@ -68,7 +68,7 @@ ENTRY(__copy_in_user) uaccess_enable_not_uao x3, x4, x5 add end, x0, x2 #include "copy_template.S" - uaccess_disable_not_uao x3 + uaccess_disable_not_uao x3, x4 mov x0, #0 ret ENDPROC(__copy_in_user) diff --git a/arch/arm64/lib/copy_to_user.S b/arch/arm64/lib/copy_to_user.S index 67118444cde0c..f6cfcc0441de6 100644 --- a/arch/arm64/lib/copy_to_user.S +++ b/arch/arm64/lib/copy_to_user.S @@ -66,7 +66,7 @@ ENTRY(__arch_copy_to_user) uaccess_enable_not_uao x3, x4, x5 add end, x0, x2 #include "copy_template.S" - uaccess_disable_not_uao x3 + uaccess_disable_not_uao x3, x4 mov x0, #0 ret ENDPROC(__arch_copy_to_user) diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S index 98134de8dec7d..a8850de00235f 100644 --- a/arch/arm64/mm/cache.S +++ b/arch/arm64/mm/cache.S @@ -180,7 +180,7 @@ USER(9f, ic ivau, x4 ) // invalidate I line PoU 9: // ignore any faulting cache operation dsb ish isb - uaccess_ttbr0_disable x1 + uaccess_ttbr0_disable x1, x2 ret ENDPROC(flush_icache_range) ENDPROC(__flush_cache_user_range) diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index b3b4e8ee8e54d..b6245c71bd07b 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -129,6 +129,9 @@ ENDPROC(cpu_do_resume) ENTRY(cpu_do_switch_mm) mrs x2, ttbr1_el1 mmid x1, x1 // get mm->context.id +#ifdef CONFIG_ARM64_SW_TTBR0_PAN + bfi x0, x1, #48, #16 // set the ASID field in TTBR0 +#endif bfi x2, x1, #48, #16 // set the ASID msr ttbr1_el1, x2 // in TTBR1 (since TCR.A1 is set) isb diff --git a/arch/arm64/xen/hypercall.S b/arch/arm64/xen/hypercall.S index 27b38711023b5..a396beb7829bb 100644 --- a/arch/arm64/xen/hypercall.S +++ b/arch/arm64/xen/hypercall.S @@ -104,6 +104,6 @@ ENTRY(privcmd_call) /* * Disable userspace access from kernel once the hyp call completed. */ - uaccess_ttbr0_disable x6 + uaccess_ttbr0_disable x6, x7 ret ENDPROC(privcmd_call); From f74ce3ccc730252e6d2656e3267529ef04166a7d Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Tue, 6 Feb 2018 10:07:54 +0530 Subject: [PATCH 071/508] ARM: dts: msm: enable kpti on msm8996 and msm8996pro Pass the kernel command line argument 'kpti=1' to enable Kernel Page Table Isolation feature on msm8996 and msm8996pro. Change-Id: I6f7753caf0d293ada27d7da898ae277fa8781b00 Signed-off-by: Vinayak Menon --- arch/arm/boot/dts/qcom/msm8996.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8996pro.dtsi | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi index 8bcbeb8d55853..7eaf564f12fb3 100644 --- a/arch/arm/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -21,7 +21,7 @@ interrupt-parent = <&intc>; chosen { - bootargs = "sched_enable_hmp=1 sched_enable_power_aware=1 app_setting.use_32bit_app_setting=1"; + bootargs = "sched_enable_hmp=1 sched_enable_power_aware=1 app_setting.use_32bit_app_setting=1 kpti=1"; }; aliases { diff --git a/arch/arm/boot/dts/qcom/msm8996pro.dtsi b/arch/arm/boot/dts/qcom/msm8996pro.dtsi index 1bf22f160dffc..ef42824b119bb 100644 --- a/arch/arm/boot/dts/qcom/msm8996pro.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996pro.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -22,7 +22,7 @@ qcom,msm-id = <305 0x10000>; chosen { - bootargs = "sched_enable_hmp=1 sched_enable_power_aware=1 app_setting.use_32bit_app_setting_pro=1"; + bootargs = "sched_enable_hmp=1 sched_enable_power_aware=1 app_setting.use_32bit_app_setting_pro=1 kpti=1"; }; }; From 8701da3776fdd9487ba40ba5cf710e4f92d59530 Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Sirasanagandla Date: Mon, 5 Feb 2018 16:59:08 +0530 Subject: [PATCH 072/508] wlan: Redirect third party rx traffic to monitor interface In STA + Monitor SCC, firmware can indicate third party rx traffic to host with valid sta_id. To handle this, add check for addr1 index and redirect traffic to monitor interface if index is 254. Note: Third party traffic here refers to data frames in which unicast DA is other than self-sta mac address. Change-Id: I5ab4e259e91a9276dadade37ea4bacacfa6d7b75 CRs-Fixed: 2184141 --- CORE/TL/src/wlan_qct_tl.c | 35 ++++++++++++++++++------- CORE/WDA/inc/wlan_qct_wda.h | 5 +++- CORE/WDI/DP/inc/wlan_qct_wdi_ds.h | 3 ++- CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c | 3 ++- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c index dd995b6ebac08..91f1ba63ca485 100644 --- a/CORE/TL/src/wlan_qct_tl.c +++ b/CORE/TL/src/wlan_qct_tl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -6176,13 +6176,24 @@ static bool WLANTL_StaMonRX(WLANTL_CbType* pTLCb, vos_pkt_t *pFrame, tpSirMacMgmtHdr pHdr = NULL; v_MACADDR_t *peerMacAddr = NULL; uint8_t i = 0; - - if (vos_check_monitor_state() == false || WLANTL_STA_ID_MONIFACE(sta_id) == 0) - return false; + uint8_t addr1_index = WDA_GET_RX_ADDR1_IDX(pRxMetadata); + bool tp_data = false; pHdr = (tpSirMacMgmtHdr)pRxMetadata->mpduHeaderPtr; + peerMacAddr = (v_MACADDR_t *)pHdr->da; + + if (vos_check_monitor_state() == false) + return false; + + if ((addr1_index == 254) && + WLANTL_IS_DATA_FRAME(WDA_GET_RX_TYPE_SUBTYPE(pRxMetadata)) && + !pRxMetadata->bcast) { + tp_data = true; + } else if (WLANTL_STA_ID_MONIFACE(sta_id) == 0) { + return false; + } - if (WLANTL_IS_MGMT_FRAME(WDA_GET_RX_TYPE_SUBTYPE(pRxMetadata))) { + if (WLANTL_IS_MGMT_FRAME(WDA_GET_RX_TYPE_SUBTYPE(pRxMetadata)) || tp_data) { if (pRxMetadata->bcast) return false; @@ -6196,15 +6207,21 @@ static bool WLANTL_StaMonRX(WLANTL_CbType* pTLCb, vos_pkt_t *pFrame, break; } - if (i == WLAN_MAX_STA_COUNT) + if (i == WLAN_MAX_STA_COUNT) { + if (tp_data) + return true; + return false; + } pClientSTA = pTLCb->atlSTAClients[i]; - peerMacAddr = (v_MACADDR_t *)pHdr->da; if (vos_is_macaddr_equal(peerMacAddr, - &pClientSTA->wSTADesc.vSelfMACAddress) || - vos_is_macaddr_equal(peerMacAddr, &pTLCb->spoofMacAddr.spoofMac)) + &pClientSTA->wSTADesc.vSelfMACAddress)) + return false; + + if (vos_is_macaddr_equal(peerMacAddr, &pTLCb->spoofMacAddr.spoofMac) && + !tp_data) return false; } diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h index 25ee44f99e604..9a9a76522b9ee 100644 --- a/CORE/WDA/inc/wlan_qct_wda.h +++ b/CORE/WDA/inc/wlan_qct_wda.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -722,6 +722,9 @@ tBssSystemRole wdaGetGlobalSystemRole(tpAniSirGlobal pMac); /* WDA_GET_RX_ADDR3_IDX ******************************************************/ # define WDA_GET_RX_ADDR3_IDX(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->addr3Idx) +/* WDA_GET_RX_ADDR1_IDX ******************************************************/ +# define WDA_GET_RX_ADDR1_IDX(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->addr1Idx) + /* WDA_GET_RX_CH *************************************************************/ # define WDA_GET_RX_CH(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->rxChannel) diff --git a/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h b/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h index 4f88b99f6c05c..5745f2ec03b38 100644 --- a/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h +++ b/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2016-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -176,6 +176,7 @@ typedef struct #endif wpt_uint32 loggingData; wpt_uint32 indType; + wpt_uint8 addr1Idx; } WDI_DS_RxMetaInfoType; typedef struct sPktMetaInfo diff --git a/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c b/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c index 3708bfbdcabef..bc1828228906c 100644 --- a/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c +++ b/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -856,6 +856,7 @@ wpt_status WDTS_RxPacket (void *pContext, wpt_packet *pFrame, WDTS_ChannelType c pRxMetadata->fc = isFcBd; pRxMetadata->staId = WDI_RX_BD_GET_STA_ID(pBDHeader); pRxMetadata->addr3Idx = WDI_RX_BD_GET_ADDR3_IDX(pBDHeader); + pRxMetadata->addr1Idx = WDI_RX_BD_GET_ADDR1_IDX(pBDHeader); pRxMetadata->rxChannel = WDI_RX_BD_GET_RX_CHANNEL(pBDHeader); pRxMetadata->rfBand = WDI_RX_BD_GET_RFBAND(pBDHeader); pRxMetadata->rtsf = WDI_RX_BD_GET_RTSF(pBDHeader); From 26d3efb7040b0bafe9de3a01022ad462459037f8 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Tue, 30 Jan 2018 15:43:36 +0530 Subject: [PATCH 073/508] msm: ADSPRPC: Use ID in response to get context pointer Send context ID in rpc header instead of context pointer. Validate context ID received in response and get context pointer. Change-Id: I9cfd10d0c1b25c3085b8e15c7ca1c8ff214bf10d Acked-by: Viswanatham Paduchuri Signed-off-by: Tharun Kumar Merugu --- drivers/char/adsprpc.c | 77 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 11 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index dc65d6f239151..9d8b0eead6879 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -66,6 +66,8 @@ #define NUM_CHANNELS 3 /*1 compute 1 cpz 1 mdsp*/ #define NUM_SESSIONS 8 /*8 compute*/ #define FASTRPC_CTX_MAGIC (0xbeeddeed) +#define FASTRPC_CTX_MAX (256) +#define FASTRPC_CTXID_MASK (0xFF0) #define IS_CACHE_ALIGNED(x) (((x) & ((L1_CACHE_BYTES)-1)) == 0) @@ -155,6 +157,7 @@ struct smq_invoke_ctx { struct overlap **overps; struct smq_msg msg; unsigned int magic; + uint64_t ctxid; }; struct fastrpc_ctx_lst { @@ -218,6 +221,8 @@ struct fastrpc_apps { struct device *dev; struct device *modem_cma_dev; bool glink; + spinlock_t ctxlock; + struct smq_invoke_ctx *ctxtable[FASTRPC_CTX_MAX]; }; struct fastrpc_mmap { @@ -790,7 +795,8 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, struct fastrpc_ioctl_invoke_fd *invokefd, struct smq_invoke_ctx **po) { - int err = 0, bufs, size = 0; + int err = 0, bufs, ii, size = 0; + struct fastrpc_apps *me = &gfa; struct smq_invoke_ctx *ctx = NULL; struct fastrpc_ctx_lst *clst = &fl->clst; struct fastrpc_ioctl_invoke *invoke = &invokefd->inv; @@ -841,6 +847,21 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, hlist_add_head(&ctx->hn, &clst->pending); spin_unlock(&fl->hlock); + spin_lock(&me->ctxlock); + for (ii = 0; ii < FASTRPC_CTX_MAX; ii++) { + if (!me->ctxtable[ii]) { + me->ctxtable[ii] = ctx; + ctx->ctxid = (ptr_to_uint64(ctx) & ~0xFFF)|(ii << 4); + break; + } + } + spin_unlock(&me->ctxlock); + VERIFY(err, ii < FASTRPC_CTX_MAX); + if (err) { + pr_err("adsprpc: out of context memory\n"); + goto bail; + } + *po = ctx; bail: if (ctx && err) @@ -862,6 +883,7 @@ static void context_save_interrupted(struct smq_invoke_ctx *ctx) static void context_free(struct smq_invoke_ctx *ctx) { int i; + struct fastrpc_apps *me = &gfa; int nbufs = REMOTE_SCALARS_INBUFS(ctx->sc) + REMOTE_SCALARS_OUTBUFS(ctx->sc); spin_lock(&ctx->fl->hlock); @@ -871,6 +893,17 @@ static void context_free(struct smq_invoke_ctx *ctx) fastrpc_mmap_free(ctx->maps[i]); fastrpc_buf_free(ctx->buf, 1); ctx->magic = 0; + ctx->ctxid = 0; + + spin_lock(&me->ctxlock); + for (i = 0; i < FASTRPC_CTX_MAX; i++) { + if (me->ctxtable[i] == ctx) { + me->ctxtable[i] = NULL; + break; + } + } + spin_unlock(&me->ctxlock); + kfree(ctx); } @@ -1269,7 +1302,7 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx, msg->tid = current->pid; if (kernel) msg->pid = 0; - msg->invoke.header.ctx = ptr_to_uint64(ctx); + msg->invoke.header.ctx = ctx->ctxid; msg->invoke.header.handle = handle; msg->invoke.header.sc = ctx->sc; msg->invoke.page.addr = ctx->buf ? ctx->buf->phys : 0; @@ -1295,20 +1328,31 @@ static void fastrpc_smd_read_handler(int cid) { struct fastrpc_apps *me = &gfa; struct smq_invoke_rsp rsp = {0}; - struct smq_invoke_ctx *ctx; int ret = 0, err = 0; + uint32_t index; do { ret = smd_read_from_cb(me->channel[cid].chan, &rsp, sizeof(rsp)); if (ret != sizeof(rsp)) break; - ctx = (struct smq_invoke_ctx *)(uint64_to_ptr(rsp.ctx)); - VERIFY(err, (ctx && ctx->magic == FASTRPC_CTX_MAGIC)); + index = (uint32_t)((rsp.ctx & FASTRPC_CTXID_MASK) >> 4); + VERIFY(err, index < FASTRPC_CTX_MAX); if (err) goto bail; - context_notify_user(uint64_to_ptr(rsp.ctx), rsp.retval); + + VERIFY(err, !IS_ERR_OR_NULL(me->ctxtable[index])); + if (err) + goto bail; + + VERIFY(err, ((me->ctxtable[index]->ctxid == (rsp.ctx)) && + me->ctxtable[index]->magic == FASTRPC_CTX_MAGIC)); + if (err) + goto bail; + + context_notify_user(me->ctxtable[index], rsp.retval); } while (ret == sizeof(rsp)); + bail: if (err) pr_err("adsprpc: invalid response or context\n"); @@ -1338,6 +1382,7 @@ static void fastrpc_init(struct fastrpc_apps *me) INIT_HLIST_HEAD(&me->drivers); INIT_HLIST_HEAD(&me->fls); spin_lock_init(&me->hlock); + spin_lock_init(&me->ctxlock); mutex_init(&me->smd_mutex); me->channel = &gcinfo[0]; for (i = 0; i < NUM_CHANNELS; i++) { @@ -1870,19 +1915,29 @@ static void fastrpc_glink_notify_rx(void *handle, const void *priv, const void *pkt_priv, const void *ptr, size_t size) { struct smq_invoke_rsp *rsp = (struct smq_invoke_rsp *)ptr; - struct smq_invoke_ctx *ctx; + struct fastrpc_apps *me = &gfa; + uint32_t index; int err = 0; VERIFY(err, (rsp && size >= sizeof(*rsp))); if (err) goto bail; - ctx = (struct smq_invoke_ctx *)(uint64_to_ptr(rsp->ctx)); - VERIFY(err, (ctx && ctx->magic == FASTRPC_CTX_MAGIC)); + index = (uint32_t)((rsp->ctx & FASTRPC_CTXID_MASK) >> 4); + VERIFY(err, index < FASTRPC_CTX_MAX); + if (err) + goto bail; + + VERIFY(err, !IS_ERR_OR_NULL(me->ctxtable[index])); + if (err) + goto bail; + + VERIFY(err, ((me->ctxtable[index]->ctxid == (rsp->ctx)) && + me->ctxtable[index]->magic == FASTRPC_CTX_MAGIC)); if (err) goto bail; - context_notify_user(ctx, rsp->retval); + context_notify_user(me->ctxtable[index], rsp->retval); bail: if (err) pr_err("adsprpc: invalid response or context\n"); From 9465aa90ba421bafef2a94f0d7a09efe0cf9c44e Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Mon, 15 Jan 2018 18:43:33 +0800 Subject: [PATCH 074/508] ASoC: msm: qdsp6v2: update backend name Some backend names are not there. Delete them from current be_name. When the return value of adm_populate_channel_weight is 0, it should keep running, not return error. Change-Id: I447b81d6edfc89db6cb3742c1719e745c6071c12 Signed-off-by: Meng Wang --- sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c | 56 ++++++++++------------ sound/soc/msm/qdsp6v2/q6adm.c | 4 +- 2 files changed, 27 insertions(+), 33 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 049e77f4e8969..cf5c8fa32b126 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -2318,37 +2318,31 @@ static const char *const be_name[] = { "INT_FM_RX", "INT_FM_TX", "AFE_PCM_RX", "AFE_PCM_TX", "AUXPCM_RX", "AUXPCM_TX", "VOICE_PLAYBACK_TX", "VOICE2_PLAYBACK_TX", "INCALL_RECORD_RX", "INCALL_RECORD_TX", "MI2S_RX", "MI2S_TX", -"SEC_I2S_RX", "SLIM_1_RX", "SLIM_1_TX", "SLIM_2_RX", -"SLIM_2_TX", "SLIM_3_RX", "SLIM_3_TX", "SLIM_4_RX", -"SLIM_4_TX", "SLIM_5_RX", "SLIM_5_TX", "SLIM_6_RX", -"SLIM_6_TX", "SLIM_7_RX", "SLIM_7_TX", "SLIM_8_RX", -"SLIM_8_TX", "EXTPROC_RX", "EXTPROC_TX", "EXPROC_EC_TX", -"QUAT_MI2S_RX", "QUAT_MI2S_TX", "SECOND_MI2S_RX", "SECOND_MI2S_TX", -"PRI_MI2S_RX", "PRI_MI2S_TX", "TERT_MI2S_RX", "TERT_MI2S_TX", -"AUDIO_I2S_RX", "SEC_AUXPCM_RX", "SEC_AUXPCM_TX", "SPDIF_RX", -"SECOND_MI2S_RX_SD1", "QUIN_MI2S_RX", "QUIN_MI2S_TX", "SENARY_MI2S_TX", -"PRI_TDM_RX_0", "PRI_TDM_TX_0", "PRI_TDM_RX_1", "PRI_TDM_TX_1", -"PRI_TDM_RX_2", "PRI_TDM_TX_2", "PRI_TDM_RX_3", "PRI_TDM_TX_3", -"PRI_TDM_RX_4", "PRI_TDM_TX_4", "PRI_TDM_RX_5", "PRI_TDM_TX_5", -"PRI_TDM_RX_6", "PRI_TDM_TX_6", "PRI_TDM_RX_7", "PRI_TDM_TX_7", -"SEC_TDM_RX_0", "SEC_TDM_TX_0", "SEC_TDM_RX_1", "SEC_TDM_TX_1", -"SEC_TDM_RX_2", "SEC_TDM_TX_2", "SEC_TDM_RX_3", "SEC_TDM_TX_3", -"SEC_TDM_RX_4", "SEC_TDM_TX_4", "SEC_TDM_RX_5", "SEC_TDM_TX_5", -"SEC_TDM_RX_6", "SEC_TDM_TX_6", "SEC_TDM_RX_7", "SEC_TDM_TX_7", -"TERT_TDM_RX_0", "TERT_TDM_TX_0", "TERT_TDM_RX_1", "TERT_TDM_TX_1", -"TERT_TDM_RX_2", "TERT_TDM_TX_2", "TERT_TDM_RX_3", "TERT_TDM_TX_3", -"TERT_TDM_RX_4", "TERT_TDM_TX_4", "TERT_TDM_RX_5", "TERT_TDM_TX_5", -"TERT_TDM_RX_6", "TERT_TDM_TX_6", "TERT_TDM_RX_7", "TERT_TDM_TX_7", -"QUAT_TDM_RX_0", "QUAT_TDM_TX_0", "QUAT_TDM_RX_1", "QUAT_TDM_TX_1", -"QUAT_TDM_RX_2", "QUAT_TDM_TX_2", "QUAT_TDM_RX_3", "QUAT_TDM_TX_3", -"QUAT_TDM_RX_4", "QUAT_TDM_TX_4", "QUAT_TDM_RX_5", "QUAT_TDM_TX_5", -"QUAT_TDM_RX_6", "QUAT_TDM_TX_6", "QUAT_TDM_RX_7", "QUAT_TDM_TX_7", -"INT_BT_A2DP_RX", "USB_RX", "USB_TX", "DISPLAY_PORT_RX", -"TERT_AUXPCM_RX", "TERT_AUXPCM_TX", "QUAT_AUXPCM_RX", "QUAT_AUXPCM_TX", -"INT0_MI2S_RX", "INT0_MI2S_TX", "INT1_MI2S_RX", "INT1_MI2S_TX", -"INT2_MI2S_RX", "INT2_MI2S_TX", "INT3_MI2S_RX", "INT3_MI2S_TX", -"INT4_MI2S_RX", "INT4_MI2S_TX", "INT5_MI2S_RX", "INT5_MI2S_TX", -"INT6_MI2S_RX", "INT6_MI2S_TX" +"SEC_I2S_RX", "SLIM_1_RX", "SLIM_1_TX", "SLIM_4_RX", +"SLIM_4_TX", "SLIM_3_RX", "SLIM_3_TX", "SLIM_5_TX", +"EXTPROC_RX", "EXTPROC_TX", "EXPROC_EC_TX", "QUAT_MI2S_RX", +"QUAT_MI2S_TX", "SECOND_MI2S_RX", "SECOND_MI2S_TX", "PRI_MI2S_RX", +"PRI_MI2S_TX", "TERT_MI2S_RX", "TERT_MI2S_TX", "AUDIO_I2S_RX", +"SEC_AUXPCM_RX", "SEC_AUXPCM_TX", "SLIM_6_RX", "SLIM_6_TX", +"SPDIF_RX", "SECOND_MI2S_RX_SD1", "SLIM_5_RX", "QUIN_MI2S_RX", +"QUIN_MI2S_TX", "SENARY_MI2S_TX", "PRI_TDM_RX_0", "PRI_TDM_TX_0", +"PRI_TDM_RX_1", "PRI_TDM_TX_1", "PRI_TDM_RX_2", "PRI_TDM_TX_2", +"PRI_TDM_RX_3", "PRI_TDM_TX_3", "PRI_TDM_RX_4", "PRI_TDM_TX_4", +"PRI_TDM_RX_5", "PRI_TDM_TX_5", "PRI_TDM_RX_6", "PRI_TDM_TX_6", +"PRI_TDM_RX_7", "PRI_TDM_TX_7", "SEC_TDM_RX_0", "SEC_TDM_TX_0", +"SEC_TDM_RX_1", "SEC_TDM_TX_1", "SEC_TDM_RX_2", "SEC_TDM_TX_2", +"SEC_TDM_RX_3", "SEC_TDM_TX_3", "SEC_TDM_RX_4", "SEC_TDM_TX_4", +"SEC_TDM_RX_5", "SEC_TDM_TX_5", "SEC_TDM_RX_6", "SEC_TDM_TX_6", +"SEC_TDM_RX_7", "SEC_TDM_TX_7", "TERT_TDM_RX_0", "TERT_TDM_TX_0", +"TERT_TDM_RX_1", "TERT_TDM_TX_1", "TERT_TDM_RX_2", "TERT_TDM_TX_2", +"TERT_TDM_RX_3", "TERT_TDM_TX_3", "TERT_TDM_RX_4", "TERT_TDM_TX_4", +"TERT_TDM_RX_5", "TERT_TDM_TX_5", "TERT_TDM_RX_6", "TERT_TDM_TX_6", +"TERT_TDM_RX_7", "TERT_TDM_TX_7", "QUAT_TDM_RX_0", "QUAT_TDM_TX_0", +"QUAT_TDM_RX_1", "QUAT_TDM_TX_1", "QUAT_TDM_RX_2", "QUAT_TDM_TX_2", +"QUAT_TDM_RX_3", "QUAT_TDM_TX_3", "QUAT_TDM_RX_4", "QUAT_TDM_TX_4", +"QUAT_TDM_RX_5", "QUAT_TDM_TX_5", "QUAT_TDM_RX_6", "QUAT_TDM_TX_6", +"QUAT_TDM_RX_7", "QUAT_TDM_TX_7", "INT_BT_A2DP_RX", "SLIM_2_TX", +"AFE_LOOPBACK_TX" }; static SOC_ENUM_SINGLE_DECL(mm1_channel_mux, diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c index f1917e703d896..6c31314bf548b 100644 --- a/sound/soc/msm/qdsp6v2/q6adm.c +++ b/sound/soc/msm/qdsp6v2/q6adm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -721,7 +721,7 @@ int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id, index = index + ch_mixer->input_channels[channel_index]; ret = adm_populate_channel_weight(&adm_pspd_params[index], ch_mixer, channel_index); - if (!ret) { + if (ret) { pr_err("%s: fail to get channel weight with error %d\n", __func__, ret); goto fail_cmd; From afb4605c2ff7b3634a97048b916d6516bd17bdab Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Fri, 9 Feb 2018 14:10:04 +0530 Subject: [PATCH 075/508] wlan: Fix corruption of Beacon Frame due to probe resp template While sending probe response template to HAL, SIR_MAX_PACKET_SIZE (2048) is used to check the max length of probe response whole buffer size is SCH_MAX_PROBE_RESP_SIZE (512) assigned during schInitGlobals. So if the size of probe response template is greater than SCH_MAX_PROBE_RESP_SIZE (512), the memcopy was corrupting the beacon buffer and thus this corrupted beacon buffer was sent to firmware which result in assert. To fix this set SCH_MAX_PROBE_RESP_SIZE to 2048 and add sanity check for beacon length while sending it to firmware. Change-Id: I4e358c0cc2796adf25a5eaaef1307191a322561a CRs-Fixed: 2187806 --- CORE/MAC/src/pe/include/schGlobal.h | 4 ++-- CORE/MAC/src/pe/lim/limSendManagementFrames.c | 8 ++++---- CORE/MAC/src/pe/sch/schApi.c | 10 +++++----- CORE/WDA/src/wlan_qct_wda.c | 16 +++++++++++++--- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/CORE/MAC/src/pe/include/schGlobal.h b/CORE/MAC/src/pe/include/schGlobal.h index 7bfcede922c03..ba823bb6ee7dd 100644 --- a/CORE/MAC/src/pe/include/schGlobal.h +++ b/CORE/MAC/src/pe/include/schGlobal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -79,7 +79,7 @@ /// Maximum allowable size of a beacon frame #define SCH_MAX_BEACON_SIZE 512 -#define SCH_MAX_PROBE_RESP_SIZE 512 +#define SCH_MAX_PROBE_RESP_SIZE 2048 struct schMisc { diff --git a/CORE/MAC/src/pe/lim/limSendManagementFrames.c b/CORE/MAC/src/pe/lim/limSendManagementFrames.c index 24b04deb3349d..294735fb6c31b 100644 --- a/CORE/MAC/src/pe/lim/limSendManagementFrames.c +++ b/CORE/MAC/src/pe/lim/limSendManagementFrames.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -871,7 +871,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, return; } if (addnIE1Len <= WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && addnIE1Len && - (nBytes + addnIE1Len) <= SIR_MAX_PACKET_SIZE) + (nBytes + addnIE1Len) <= SCH_MAX_PROBE_RESP_SIZE) { if ( eSIR_SUCCESS != wlan_cfgGetStr(pMac, WNI_CFG_PROBE_RSP_ADDNIE_DATA1, &addIE[0], @@ -895,7 +895,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, return; } if (addnIE2Len <= WNI_CFG_PROBE_RSP_ADDNIE_DATA2_LEN && addnIE2Len && - (nBytes + addnIE2Len) <= SIR_MAX_PACKET_SIZE) + (nBytes + addnIE2Len) <= SCH_MAX_PROBE_RESP_SIZE) { if ( eSIR_SUCCESS != wlan_cfgGetStr(pMac, WNI_CFG_PROBE_RSP_ADDNIE_DATA2, &addIE[addnIE1Len], @@ -919,7 +919,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, return; } if (addnIE3Len <= WNI_CFG_PROBE_RSP_ADDNIE_DATA3_LEN && addnIE3Len && - (nBytes + addnIE3Len) <= SIR_MAX_PACKET_SIZE) + (nBytes + addnIE3Len) <= SCH_MAX_PROBE_RESP_SIZE) { if ( eSIR_SUCCESS != wlan_cfgGetStr(pMac, WNI_CFG_PROBE_RSP_ADDNIE_DATA3, diff --git a/CORE/MAC/src/pe/sch/schApi.c b/CORE/MAC/src/pe/sch/schApi.c index 6357be7f89fdb..a19ff22c8c882 100644 --- a/CORE/MAC/src/pe/sch/schApi.c +++ b/CORE/MAC/src/pe/sch/schApi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -456,7 +456,7 @@ tANI_U32 limSendProbeRspTemplateToHal(tpAniSirGlobal pMac,tpPESession psessionEn } if (addnIE1Len && addnIE1Len <= WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && - (nBytes + addnIE1Len) <= SIR_MAX_PACKET_SIZE) + (nBytes + addnIE1Len) <= SCH_MAX_PROBE_RESP_SIZE) { if ( eSIR_SUCCESS != wlan_cfgGetStr(pMac, WNI_CFG_PROBE_RSP_ADDNIE_DATA1, &addIE[0], @@ -470,7 +470,7 @@ tANI_U32 limSendProbeRspTemplateToHal(tpAniSirGlobal pMac,tpPESession psessionEn } if (addnIE2Len && addnIE2Len <= WNI_CFG_PROBE_RSP_ADDNIE_DATA2_LEN && - (nBytes + addnIE1Len + addnIE2Len) <= SIR_MAX_PACKET_SIZE) + (nBytes + addnIE1Len + addnIE2Len) <= SCH_MAX_PROBE_RESP_SIZE) { if ( eSIR_SUCCESS != wlan_cfgGetStr(pMac, WNI_CFG_PROBE_RSP_ADDNIE_DATA2, @@ -485,7 +485,7 @@ tANI_U32 limSendProbeRspTemplateToHal(tpAniSirGlobal pMac,tpPESession psessionEn } if (addnIE3Len && addnIE3Len <= WNI_CFG_PROBE_RSP_ADDNIE_DATA3_LEN && - (nBytes + totalAddnIeLen) <= SIR_MAX_PACKET_SIZE) + (nBytes + totalAddnIeLen) <= SCH_MAX_PROBE_RESP_SIZE) { if ( eSIR_SUCCESS != wlan_cfgGetStr(pMac, WNI_CFG_PROBE_RSP_ADDNIE_DATA3, @@ -503,7 +503,7 @@ tANI_U32 limSendProbeRspTemplateToHal(tpAniSirGlobal pMac,tpPESession psessionEn if (addnIEPresent) { - if ((nBytes + totalAddnIeLen) <= SIR_MAX_PACKET_SIZE ) + if ((nBytes + totalAddnIeLen) <= SCH_MAX_PROBE_RESP_SIZE) nBytes += totalAddnIeLen; else addnIEPresent = false; //Dont include the IE. diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c index 9575cd3fbbeac..d991cf26917eb 100644 --- a/CORE/WDA/src/wlan_qct_wda.c +++ b/CORE/WDA/src/wlan_qct_wda.c @@ -8611,9 +8611,18 @@ VOS_STATUS WDA_ProcessSendBeacon(tWDA_CbContext *pWDA, WDI_Status status = WDI_STATUS_SUCCESS ; WDI_SendBeaconParamsType wdiSendBeaconReqParam; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "------> %s " ,__func__); + "------> %s beaconLength %d" , + __func__, pSendbeaconParams->beaconLength); vos_mem_copy(wdiSendBeaconReqParam.wdiSendBeaconParamsInfo.macBSSID, pSendbeaconParams->bssId, sizeof(tSirMacAddr)); + + if (pSendbeaconParams->beaconLength > WDI_BEACON_TEMPLATE_SIZE) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: length %d greater than WDI_BEACON_TEMPLATE_SIZE" , + __func__, pSendbeaconParams->beaconLength); + VOS_ASSERT(0); + pSendbeaconParams->beaconLength = WDI_BEACON_TEMPLATE_SIZE; + } wdiSendBeaconReqParam.wdiSendBeaconParamsInfo.beaconLength = pSendbeaconParams->beaconLength; wdiSendBeaconReqParam.wdiSendBeaconParamsInfo.timIeOffset = @@ -8668,8 +8677,9 @@ VOS_STATUS WDA_ProcessUpdateProbeRspTemplate(tWDA_CbContext *pWDA, WDI_Status status = WDI_STATUS_SUCCESS; WDI_UpdateProbeRspTemplateParamsType *wdiSendProbeRspParam = vos_mem_malloc(sizeof(WDI_UpdateProbeRspTemplateParamsType)); - VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "------> %s " ,__func__); + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "------> %s probeRespTemplateLen %d" ,__func__, + pSendProbeRspParams->probeRespTemplateLen); if (!wdiSendProbeRspParam) { From fd04fefe167121fb9097ddbe402a88c8c5e2955e Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Fri, 2 Feb 2018 18:50:18 +0530 Subject: [PATCH 076/508] msm: ais: Synchronize v4l2 subscribe and unsubscribe event Serializing msm_subscribe_event and msm_unsubscribe_event to prevent possibility of use-after-free if same event is unsubcribed before v4l2 subscribe and unsubscribe event. Change-Id: Ia5ba7aa1338982b3a99616a2981e415c28f8b4a6 Signed-off-by: Rahul Sharma --- drivers/media/platform/msm/ais/camera/camera.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/ais/camera/camera.c b/drivers/media/platform/msm/ais/camera/camera.c index bd82033fe5e68..ddb89ff07ab71 100644 --- a/drivers/media/platform/msm/ais/camera/camera.c +++ b/drivers/media/platform/msm/ais/camera/camera.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -462,7 +462,9 @@ static int camera_v4l2_subscribe_event(struct v4l2_fh *fh, int rc = 0; struct camera_v4l2_private *sp = fh_to_private(fh); + mutex_lock(&sp->lock); rc = v4l2_event_subscribe(&sp->fh, sub, 5, NULL); + mutex_unlock(&sp->lock); return rc; } @@ -473,7 +475,9 @@ static int camera_v4l2_unsubscribe_event(struct v4l2_fh *fh, int rc = 0; struct camera_v4l2_private *sp = fh_to_private(fh); + mutex_lock(&sp->lock); rc = v4l2_event_unsubscribe(&sp->fh, sub); + mutex_unlock(&sp->lock); return rc; } From 809d743b2b38c03eece066d74975e5f3c8082cef Mon Sep 17 00:00:00 2001 From: Meera Gande Date: Mon, 22 Jan 2018 18:15:02 +0530 Subject: [PATCH 077/508] mm-camera2:isp2: Handle use after free buffer In the code, start_fetch can try to access the buffer pointer variable after free, as the same pointer can be freed at RELEASE_BUF call at the same time. Change-Id: Ic83f22336504cf67afe12131f791eee25477f011 Signed-off-by: Meera Gande --- drivers/media/platform/msm/camera_v2/isp/msm_isp40.c | 2 ++ drivers/media/platform/msm/camera_v2/isp/msm_isp44.c | 5 ++++- drivers/media/platform/msm/camera_v2/isp/msm_isp46.c | 4 +++- drivers/media/platform/msm/camera_v2/isp/msm_isp47.c | 4 +++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c index e9393f08e085c..0d7d83902be1e 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c @@ -1112,8 +1112,10 @@ static int msm_vfe40_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev, fe_cfg->stream_id); vfe_dev->fetch_engine_info.bufq_handle = bufq_handle; + mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); + mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc < 0 || !buf) { pr_err("%s: No fetch buffer rc= %d buf= %pK\n", __func__, rc, buf); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c index 090a5a6584ef3..aa4690d1e28a9 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -879,8 +879,11 @@ static int msm_vfe44_fetch_engine_start(struct vfe_device *vfe_dev, vfe_dev->buf_mgr, fe_cfg->session_id, fe_cfg->stream_id); vfe_dev->fetch_engine_info.bufq_handle = bufq_handle; + + mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); + mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc < 0) { pr_err("%s: No fetch buffer\n", __func__); return -EINVAL; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c index eae645b93bef7..5f4588711a024 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -824,8 +824,10 @@ static int msm_vfe46_start_fetch_engine(struct vfe_device *vfe_dev, fe_cfg->stream_id); vfe_dev->fetch_engine_info.bufq_handle = bufq_handle; + mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); + mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc < 0 || !buf) { pr_err("%s: No fetch buffer rc= %d buf= %pK\n", __func__, rc, buf); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c index 7bb003b66def7..fdf9d0c442da0 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1113,8 +1113,10 @@ int msm_vfe47_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev, fe_cfg->stream_id); vfe_dev->fetch_engine_info.bufq_handle = bufq_handle; + mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); + mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc < 0 || !buf) { pr_err("%s: No fetch buffer rc= %d buf= %pK\n", __func__, rc, buf); From f0a86d246d4a4403aec00567ed99d1b47d857ec4 Mon Sep 17 00:00:00 2001 From: Haibin Liu Date: Thu, 28 Dec 2017 20:42:37 +0800 Subject: [PATCH 078/508] msm: sensor: actuator: fix out of bound read for region params Issue: the region index is not validated against the region size. this cause out-of-bound read on the KASAN kernel. Fix: Add restriction that region index smaller than region size. CRs-Fixed: 2153841 Change-Id: I141bba45662769f0661c947fb642c2671578f32e Signed-off-by: Haibin Liu --- .../platform/msm/camera_v2/sensor/actuator/msm_actuator.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c index 7f1c7ebfb55df..fbeb531f8d301 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -638,6 +638,8 @@ static int32_t msm_actuator_move_focus( a_ctrl->curr_step_pos, dest_step_pos, curr_lens_pos); while (a_ctrl->curr_step_pos != dest_step_pos) { + if (a_ctrl->curr_region_index >= a_ctrl->region_size) + break; step_boundary = a_ctrl->region_params[a_ctrl->curr_region_index]. step_bound[dir]; From 48b6dc3e3df445485096a5050f1ff54bb2dc241f Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Fri, 2 Feb 2018 17:48:00 +0530 Subject: [PATCH 079/508] msm: ais: sensor: Fix out of bound read for region params The region index is not validated against the region size. This causes out-of-bound read on the KASAN kernel. Hence adding restriction that region index is smaller than region size. Change-Id: I3ebccee89f6e48a84389eb3b9055bc6e09e0310b Signed-off-by: Rahul Sharma --- drivers/media/platform/msm/ais/sensor/actuator/msm_actuator.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/ais/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/ais/sensor/actuator/msm_actuator.c index f68d031a9dcd8..f1ba57a340380 100644 --- a/drivers/media/platform/msm/ais/sensor/actuator/msm_actuator.c +++ b/drivers/media/platform/msm/ais/sensor/actuator/msm_actuator.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -646,6 +646,8 @@ static int32_t msm_actuator_move_focus( a_ctrl->curr_step_pos, dest_step_pos, curr_lens_pos); while (a_ctrl->curr_step_pos != dest_step_pos) { + if (a_ctrl->curr_region_index >= a_ctrl->region_size) + break; step_boundary = a_ctrl->region_params[a_ctrl->curr_region_index]. step_bound[dir]; From f31f65ce1380e425ccadd4a3e985800ecf7294df Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Tue, 30 Jan 2018 19:51:27 +0530 Subject: [PATCH 080/508] wlan: Resolve accessing free object while processing scan done callback During interface down, kernel invokes cfg80211_scan_done() to free kernel allocated scan request(scan_req) object. If scan_done callback is invoked during interface down(or vice-versa), then there is a possibility of driver to dereference scan_req object after it's freed, while updating last_scan_channelList. To resolve the race condition, update last_scan_channellist on receiving scan request itself. Change-Id: Iad2619cd967f213d9450295bc07549c75f69eaf8 CRs-Fixed: 2181016 --- CORE/HDD/inc/wlan_hdd_main.h | 1 + CORE/HDD/src/wlan_hdd_cfg80211.c | 34 +++++++++++++++++++------------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index 3bd74fca482c4..15327de5e1347 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -1041,6 +1041,7 @@ typedef struct hdd_scaninfo_s v_TIME_t last_scan_timestamp; tANI_U8 last_scan_channelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; tANI_U8 last_scan_numChannels; + bool no_cck; }hdd_scaninfo_t; diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 21895be2e4f54..05a6b0920a8a5 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -14317,7 +14317,6 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, int ret = 0; bool aborted = false; long waitRet = 0; - tANI_U8 i; hdd_context_t *pHddCtx; ENTER(); @@ -14437,21 +14436,22 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, * is needed or not on station interface. If last station * scan time and new station scan time is less then * last_scan_timestamp ; driver will return cached scan. + * Also only last_scan_timestamp is updated here last_scan_channellist + * is updated on receiving scan request itself to make sure kernel + * allocated scan request(scan_req) object is not dereferenced here, + * because interface down, where kernel frees scan_req, may happen any + * time while driver is processing scan_done_callback. So it's better + * not to access scan_req in this routine. */ - if (req->no_cck == FALSE && status == eCSR_SCAN_SUCCESS) // no_cck will be set during p2p find - { - pScanInfo->last_scan_timestamp = vos_timer_get_system_time(); - - if ( req->n_channels ) - { - for (i = 0; i < req->n_channels ; i++ ) - { - pHddCtx->scan_info.last_scan_channelList[i] = req->channels[i]->hw_value; - } - /* store no of channel scanned */ - pHddCtx->scan_info.last_scan_numChannels= req->n_channels; + if (pScanInfo->no_cck == FALSE) { // no_cck will be set during p2p find + if (status == eCSR_SCAN_SUCCESS) + pScanInfo->last_scan_timestamp = vos_timer_get_system_time(); + else { + vos_mem_zero(pHddCtx->scan_info.last_scan_channelList, + sizeof(pHddCtx->scan_info.last_scan_channelList)); + pHddCtx->scan_info.last_scan_numChannels = 0; + pScanInfo->last_scan_timestamp = 0; } - } /* @@ -15180,6 +15180,12 @@ int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy, pScanInfo->sessionId = pAdapter->sessionId; pAdapter->request = request; pScanInfo->scanId = scanId; + pScanInfo->no_cck = request->no_cck; + pHddCtx->scan_info.last_scan_numChannels = request->n_channels; + for (i = 0; i < pHddCtx->scan_info.last_scan_numChannels; i++) { + pHddCtx->scan_info.last_scan_channelList[i] = + request->channels[i]->hw_value; + } complete(&pScanInfo->scan_req_completion_event); From dad8d26568a74604468313c21dc85e90804623c2 Mon Sep 17 00:00:00 2001 From: puneet Date: Tue, 5 Dec 2017 17:07:36 +0530 Subject: [PATCH 081/508] ARM: dts: msm: add internal pull up for I2C1 on MDM9650 TTP Since there is no external pull up for I2C1 instance, add the pinctrl changes to enable the internal pull up without which there can be timeout/arb_lost error. Change-Id: Ief9a06a83f84b791948f691e0621829786eed4d8 Signed-off-by: puneet Signed-off-by: Abinaya P --- arch/arm/boot/dts/qcom/mdm9650-ttp.dts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/qcom/mdm9650-ttp.dts b/arch/arm/boot/dts/qcom/mdm9650-ttp.dts index 8db7dc55dfaee..8a951ffb004fc 100644 --- a/arch/arm/boot/dts/qcom/mdm9650-ttp.dts +++ b/arch/arm/boot/dts/qcom/mdm9650-ttp.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -47,6 +47,17 @@ }; &soc { + tlmm_pinmux: pinctrl@1000000 { + i2c_1 { + i2c_1_active { + config { + pins = "gpio2", "gpio3"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + }; usb_detect { compatible = "qcom,gpio-usbdetect"; interrupt-parent = <&spmi_bus>; From 9b1aae1d51baf4cc0ac51da60ea8eda948a04dab Mon Sep 17 00:00:00 2001 From: Archana Sriram Date: Fri, 9 Feb 2018 17:50:19 +0530 Subject: [PATCH 082/508] msm: kgsl: Fix reading lm_sequence in _execute_reg_sequence() Added proper checks while reading lm_sequence array so that it is not accessed beyond lm_size. CRs-Fixed: 2175951 Change-Id: I639b07fba275aad0f62cc03fa11201c126e24812 Signed-off-by: Archana Sriram --- drivers/gpu/msm/adreno_a5xx.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 813e0cb9cb430..4156f493fd015 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1265,31 +1265,27 @@ static int _execute_reg_sequence(struct adreno_device *adreno_dev, /* todo double check the reg writes */ while ((cur - opcode) < length) { - switch (cur[0]) { - /* Write a 32 bit value to a 64 bit reg */ - case 1: + if (cur[0] == 1 && ((cur + 4) - opcode) <= length) { + /* Write a 32 bit value to a 64 bit reg */ reg = cur[2]; reg = (reg << 32) | cur[1]; kgsl_regwrite(KGSL_DEVICE(adreno_dev), reg, cur[3]); cur += 4; - break; - /* Write a 64 bit value to a 64 bit reg */ - case 2: + } else if (cur[0] == 2 && ((cur + 5) - opcode) <= length) { + /* Write a 64 bit value to a 64 bit reg */ reg = cur[2]; reg = (reg << 32) | cur[1]; val = cur[4]; val = (val << 32) | cur[3]; kgsl_regwrite(KGSL_DEVICE(adreno_dev), reg, val); cur += 5; - break; - /* Delay for X usec */ - case 3: + } else if (cur[0] == 3 && ((cur + 2) - opcode) <= length) { + /* Delay for X usec */ udelay(cur[1]); cur += 2; - break; - default: + } else return -EINVAL; - } } + } return 0; } From f2900658d3f1d6d69a0cede700a28de8495a963c Mon Sep 17 00:00:00 2001 From: David Dai Date: Mon, 25 Sep 2017 15:16:23 -0700 Subject: [PATCH 083/508] dev_freq: devfreq_spdm: add null terminator to prevent OOB access Add null terminator to end of buffered copied from user to prevent over reading. Change-Id: I80cfcb087ea2c335fd65d8fcdaf372c7d34a533d Signed-off-by: David Dai --- drivers/devfreq/devfreq_spdm_debugfs.c | 62 ++++++++++++++++++++------ 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/drivers/devfreq/devfreq_spdm_debugfs.c b/drivers/devfreq/devfreq_spdm_debugfs.c index 94e94f3bbc1c7..1d6a581341a5f 100644 --- a/drivers/devfreq/devfreq_spdm_debugfs.c +++ b/drivers/devfreq/devfreq_spdm_debugfs.c @@ -34,7 +34,7 @@ static ssize_t enable_write(struct file *file, const char __user *data, int i; int next_idx; - if (size > sizeof(buf)) + if (size > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, data, size)) { @@ -42,6 +42,8 @@ static ssize_t enable_write(struct file *file, const char __user *data, size = -EINVAL; } + buf[size] = '\0'; + if (sscanf(buf, "%u\n", &i) != 1) { size = -EINVAL; goto err; @@ -105,7 +107,7 @@ static ssize_t pl_write(struct file *file, const char __user *data, int ext_status = 0; int i; - if (size > sizeof(buf)) + if (size > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, data, size)) { @@ -113,6 +115,8 @@ static ssize_t pl_write(struct file *file, const char __user *data, goto out; } + buf[size] = '\0'; + if (sscanf(buf, "%u %u\n", &spdm_data->config_data.pl_freqs[0], &spdm_data->config_data.pl_freqs[1]) != 2) { size = -EINVAL; @@ -164,7 +168,7 @@ static ssize_t rejrate_low_write(struct file *file, const char __user *data, struct spdm_args desc = { { 0 } }; int ext_status = 0; - if (size > sizeof(buf)) + if (size > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, data, size)) { @@ -172,6 +176,8 @@ static ssize_t rejrate_low_write(struct file *file, const char __user *data, goto out; } + buf[size] = '\0'; + if (sscanf(buf, "%u %u\n", &spdm_data->config_data.reject_rate[0], &spdm_data->config_data.reject_rate[1]) != 2) { size = -EINVAL; @@ -224,13 +230,16 @@ static ssize_t rejrate_med_write(struct file *file, const char __user *data, struct spdm_args desc = { { 0 } }; int ext_status = 0; - if (size > sizeof(buf)) + if (size > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, data, size)) { size = -EINVAL; goto out; } + + buf[size] = '\0'; + if (sscanf(buf, "%u %u\n", &spdm_data->config_data.reject_rate[2], &spdm_data->config_data.reject_rate[3]) != 2) { size = -EINVAL; @@ -282,13 +291,16 @@ static ssize_t rejrate_high_write(struct file *file, const char __user *data, struct spdm_args desc = { { 0 } }; int ext_status = 0; - if (size > sizeof(buf)) + if (size > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, data, size)) { size = -EINVAL; goto out; } + + buf[size] = '\0'; + if (sscanf(buf, "%u %u\n", &spdm_data->config_data.reject_rate[4], &spdm_data->config_data.reject_rate[5]) != 2) { size = -EINVAL; @@ -340,13 +352,16 @@ static ssize_t resptime_low_write(struct file *file, const char __user *data, struct spdm_args desc = { { 0 } }; int ext_status = 0; - if (size > sizeof(buf)) + if (size > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, data, size)) { size = -EINVAL; goto out; } + + buf[size] = '\0'; + if (sscanf(buf, "%u %u\n", &spdm_data->config_data.response_time_us[0], &spdm_data->config_data.response_time_us[1]) != 2) { size = -EINVAL; @@ -398,13 +413,16 @@ static ssize_t resptime_med_write(struct file *file, const char __user *data, struct spdm_args desc = { { 0 } }; int ext_status = 0; - if (size > sizeof(buf)) + if (size > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, data, size)) { size = -EINVAL; goto out; } + + buf[size] = '\0'; + if (sscanf(buf, "%u %u\n", &spdm_data->config_data.response_time_us[2], &spdm_data->config_data.response_time_us[3]) != 2) { size = -EINVAL; @@ -456,13 +474,16 @@ static ssize_t resptime_high_write(struct file *file, const char __user *data, struct spdm_args desc = { { 0 } }; int ext_status = 0; - if (size > sizeof(buf)) + if (size > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, data, size)) { size = -EINVAL; goto out; } + + buf[size] = '\0'; + if (sscanf(buf, "%u %u\n", &spdm_data->config_data.response_time_us[4], &spdm_data->config_data.response_time_us[5]) != 2) { size = -EINVAL; @@ -515,13 +536,16 @@ static ssize_t cciresptime_low_write(struct file *file, struct spdm_args desc = { { 0 } }; int ext_status = 0; - if (size > sizeof(buf)) + if (size > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, data, size)) { size = -EINVAL; goto out; } + + buf[size] = '\0'; + if (sscanf(buf, "%u %u\n", &spdm_data->config_data.cci_response_time_us[0], &spdm_data->config_data.cci_response_time_us[1]) != 2) { @@ -575,13 +599,16 @@ static ssize_t cciresptime_med_write(struct file *file, struct spdm_args desc = { { 0 } }; int ext_status = 0; - if (size > sizeof(buf)) + if (size > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, data, size)) { size = -EINVAL; goto out; } + + buf[size] = '\0'; + if (sscanf(buf, "%u %u\n", &spdm_data->config_data.cci_response_time_us[2], &spdm_data->config_data.cci_response_time_us[3]) != 2) { @@ -635,13 +662,16 @@ static ssize_t cciresptime_high_write(struct file *file, struct spdm_args desc = { { 0 } }; int ext_status = 0; - if (size > sizeof(buf)) + if (size > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, data, size)) { size = -EINVAL; goto out; } + + buf[size] = '\0'; + if (sscanf(buf, "%u %u\n", &spdm_data->config_data.cci_response_time_us[4], &spdm_data->config_data.cci_response_time_us[5]) != 2){ @@ -694,13 +724,16 @@ static ssize_t cci_max_write(struct file *file, const char __user *data, struct spdm_args desc = { { 0 } }; int ext_status = 0; - if (size > sizeof(buf)) + if (size > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, data, size)) { size = -EINVAL; goto out; } + + buf[size] = '\0'; + if (sscanf(buf, "%u\n", &spdm_data->config_data.max_cci_freq) != 1) { size = -EINVAL; goto out; @@ -748,13 +781,16 @@ static ssize_t vote_cfg_write(struct file *file, const char __user *data, struct spdm_args desc = { { 0 } }; int ext_status = 0; - if (size > sizeof(buf)) + if (size > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, data, size)) { size = -EINVAL; goto out; } + + buf[size] = '\0'; + if (sscanf(buf, "%u %u %u %u\n", &spdm_data->config_data.upstep, &spdm_data->config_data.downstep, &spdm_data->config_data.max_vote, From 5c41200a2399251c90abdee7a6d70036ca629e01 Mon Sep 17 00:00:00 2001 From: Gustavo Solaira Date: Tue, 6 Feb 2018 21:19:12 -0800 Subject: [PATCH 084/508] ARM: dts: msm: Disable K61 SPI-CAN on mdm9650 CV2X Disable K61 SPI-CAN device node on mdm9650 CV2X boards. Change-Id: If7b9be932d4211134f9c3291e2fdc718ec3aa484 Signed-off-by: Gustavo Solaira --- arch/arm/boot/dts/qcom/mdm9650-cv2x.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/qcom/mdm9650-cv2x.dtsi b/arch/arm/boot/dts/qcom/mdm9650-cv2x.dtsi index 0dde4a007dfe9..c3ac4c86222c3 100644 --- a/arch/arm/boot/dts/qcom/mdm9650-cv2x.dtsi +++ b/arch/arm/boot/dts/qcom/mdm9650-cv2x.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -102,6 +102,7 @@ pinctrl-names = "active", "sleep"; pinctrl-0 = <&can_rst_on>; pinctrl-1 = <&can_rst_off>; + status = "disabled"; }; }; From f9e785730b21f63ad673eec7dfc3aea0f09eda7e Mon Sep 17 00:00:00 2001 From: Gustavo Solaira Date: Fri, 9 Feb 2018 11:38:35 -0800 Subject: [PATCH 085/508] ARM: dts: msm: Remove unneeded sharedmem definition in mdm9650 CV2X Remove unneeded definition in mdm9650 CV2X since it's not needed for NAND based targets. Change-Id: I1131a875978b833f594dd51569903aca8a289f5a Signed-off-by: Gustavo Solaira --- arch/arm/boot/dts/qcom/mdm9650-v1.1-nand-cv2x.dts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/qcom/mdm9650-v1.1-nand-cv2x.dts b/arch/arm/boot/dts/qcom/mdm9650-v1.1-nand-cv2x.dts index 6443c2b4ed324..4632607302662 100644 --- a/arch/arm/boot/dts/qcom/mdm9650-v1.1-nand-cv2x.dts +++ b/arch/arm/boot/dts/qcom/mdm9650-v1.1-nand-cv2x.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -18,11 +18,4 @@ model = "Qualcomm Technologies, Inc. MDM 9650 v1.1 CV2X"; compatible = "qcom,mdm9650-ttp", "qcom,mdm9650", "qcom,ttp"; qcom,board-id = <0x1e 1>, <0x1e 0x101>; - - qcom,rmtfs_sharedmem@0 { - compatible = "qcom,sharedmem-uio"; - reg = <0x0 0x00100000>; - reg-names = "rmtfs"; - qcom,client-id = <0x00000001>; - }; }; From c032f7de56590416fea6309921f3cd45141c92e7 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Wed, 31 Jan 2018 15:51:05 +0530 Subject: [PATCH 086/508] msm: ipa: rndis: Fine tune threshold for rndis/ecm Fine tune rndis/ecm low threshold for better performance. Change-Id: Ib9165a4656a3acfdf9c400590e6b7371eacd895c Signed-off-by: Mohammed Javid --- drivers/net/ethernet/msm/ecm_ipa.c | 4 ++-- drivers/net/ethernet/msm/rndis_ipa.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/msm/ecm_ipa.c b/drivers/net/ethernet/msm/ecm_ipa.c index 80ea7ef497cb0..cd22429ced6d9 100644 --- a/drivers/net/ethernet/msm/ecm_ipa.c +++ b/drivers/net/ethernet/msm/ecm_ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -25,7 +25,7 @@ #define ECM_IPA_IPV6_HDR_NAME "ecm_eth_ipv6" #define INACTIVITY_MSEC_DELAY 100 #define DEFAULT_OUTSTANDING_HIGH 64 -#define DEFAULT_OUTSTANDING_LOW 32 +#define DEFAULT_OUTSTANDING_LOW 48 #define DEBUGFS_TEMP_BUF_SIZE 4 #define TX_TIMEOUT (5 * HZ) diff --git a/drivers/net/ethernet/msm/rndis_ipa.c b/drivers/net/ethernet/msm/rndis_ipa.c index 179e7081cb40d..be346a92ff59e 100644 --- a/drivers/net/ethernet/msm/rndis_ipa.c +++ b/drivers/net/ethernet/msm/rndis_ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -41,7 +41,7 @@ #define IPA_TO_USB_CLIENT IPA_CLIENT_USB_CONS #define INACTIVITY_MSEC_DELAY 100 #define DEFAULT_OUTSTANDING_HIGH 64 -#define DEFAULT_OUTSTANDING_LOW 32 +#define DEFAULT_OUTSTANDING_LOW 48 #define DEBUGFS_TEMP_BUF_SIZE 4 #define RNDIS_IPA_PKT_TYPE 0x00000001 #define RNDIS_IPA_DFLT_RT_HDL 0 From 11effc6b611f5d64305d916aabdbafc7798de4be Mon Sep 17 00:00:00 2001 From: smanag Date: Tue, 14 Nov 2017 14:57:57 +0530 Subject: [PATCH 087/508] drivers: soc: Synchronize apr callback and voice svc release Issue is seen when apr callback is received while voice_svc_release is in process of freeing the driver private data. Avoid invalid access of private data pointer by putting the callback and release functions in the same locked context. Change-Id: I93af13cab0a3c7e653a9bc9fa7f4f86bfa0502df Signed-off-by: smanag --- drivers/soc/qcom/qdsp6v2/voice_svc.c | 42 ++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c index fe54589744061..40204e104031b 100644 --- a/drivers/soc/qcom/qdsp6v2/voice_svc.c +++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -67,7 +68,11 @@ static void *dummy_q6_mvm; static void *dummy_q6_cvs; dev_t device_num; +static spinlock_t voicesvc_lock; +static bool is_released; static int voice_svc_dummy_reg(void); +static int voice_svc_dummy_dereg(void); + static int32_t qdsp_dummy_apr_callback(struct apr_client_data *data, void *priv); @@ -82,10 +87,16 @@ static int32_t qdsp_apr_callback(struct apr_client_data *data, void *priv) return -EINVAL; } + spin_lock(&voicesvc_lock); + if (is_released) { + spin_unlock(&voicesvc_lock); + return 0; + } prtd = (struct voice_svc_prvt *)priv; if (prtd == NULL) { pr_err("%s: private data is NULL\n", __func__); + spin_unlock(&voicesvc_lock); return -EINVAL; } @@ -128,6 +139,7 @@ static int32_t qdsp_apr_callback(struct apr_client_data *data, void *priv) spin_unlock_irqrestore(&prtd->response_lock, spin_flags); + spin_unlock(&voicesvc_lock); return -ENOMEM; } @@ -156,6 +168,7 @@ static int32_t qdsp_apr_callback(struct apr_client_data *data, void *priv) __func__); } + spin_unlock(&voicesvc_lock); return 0; } @@ -614,6 +627,21 @@ static int voice_svc_dummy_reg() return -EINVAL; } +static int voice_svc_dummy_dereg(void) +{ + pr_debug("%s\n", __func__); + if (dummy_q6_mvm != NULL) { + apr_deregister(dummy_q6_mvm); + dummy_q6_mvm = NULL; + } + + if (dummy_q6_cvs != NULL) { + apr_deregister(dummy_q6_cvs); + dummy_q6_cvs = NULL; + } + return 0; +} + static int voice_svc_open(struct inode *inode, struct file *file) { struct voice_svc_prvt *prtd = NULL; @@ -637,6 +665,7 @@ static int voice_svc_open(struct inode *inode, struct file *file) mutex_init(&prtd->response_mutex_lock); file->private_data = (void *)prtd; + is_released = 0; /* Current APR implementation doesn't support session based * multiple service registrations. The apr_deregister() * function sets the destination and client IDs to zero, if @@ -669,6 +698,11 @@ static int voice_svc_release(struct inode *inode, struct file *file) goto done; } + mutex_lock(&prtd->response_mutex_lock); + if (reg_dummy_sess) { + voice_svc_dummy_dereg(); + reg_dummy_sess = 0; + } if (prtd->apr_q6_cvs != NULL) { svc_name = VOICE_SVC_MVM_STR; handle = &prtd->apr_q6_cvs; @@ -685,7 +719,6 @@ static int voice_svc_release(struct inode *inode, struct file *file) pr_err("%s: Failed to dereg MVM %d\n", __func__, ret); } - mutex_lock(&prtd->response_mutex_lock); spin_lock_irqsave(&prtd->response_lock, spin_flags); while (!list_empty(&prtd->response_queue)) { @@ -703,9 +736,11 @@ static int voice_svc_release(struct inode *inode, struct file *file) mutex_destroy(&prtd->response_mutex_lock); + spin_lock(&voicesvc_lock); kfree(file->private_data); file->private_data = NULL; - + is_released = 1; + spin_unlock(&voicesvc_lock); done: return ret; } @@ -774,6 +809,7 @@ static int voice_svc_probe(struct platform_device *pdev) goto add_err; } pr_debug("%s: Device created\n", __func__); + spin_lock_init(&voicesvc_lock); goto done; add_err: From ff4a2773869fff1a9dd9cda3f8fcd7f50b4b55ea Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 28 Jun 2016 18:07:30 +0100 Subject: [PATCH 088/508] arm64: errata: Calling enable functions for CPU errata too Currently we call the (optional) enable function for CPU _features_ only. As CPU _errata_ descriptions share the same data structure and having an enable function is useful for errata as well (for instance to set bits in SCTLR), lets call it when enumerating erratas too. Change-Id: If9eff7dd87d7ebcf8ee44ae0cc326f91e2c16af8 Signed-off-by: Andre Przywara Reviewed-by: Suzuki K Poulose Signed-off-by: Catalin Marinas Git-commit: 8e2318521bf5837dae093413f81292b59d49d030 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux [neeraju@codeaurora.org: resolve trivial merge conflicts] Signed-off-by: Neeraj Upadhyay --- arch/arm64/include/asm/cpufeature.h | 2 ++ arch/arm64/kernel/cpu_errata.c | 5 +++++ arch/arm64/kernel/cpufeature.c | 4 ++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index ba6983e901d53..81e39e9e1f02a 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -162,7 +162,9 @@ void __init setup_cpu_features(void); void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps, const char *info); +void enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps); void check_local_cpu_errata(void); +void __init enable_errata_workarounds(void); #ifdef CONFIG_HOTPLUG_CPU void verify_local_cpu_capabilities(void); diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 807d1c1de9db1..efcf303b047a0 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -97,3 +97,8 @@ void check_local_cpu_errata(void) { update_cpu_capabilities(arm64_errata, "enabling workaround for"); } + +void __init enable_errata_workarounds(void) +{ + enable_cpu_capabilities(arm64_errata); +} diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index ec7e68c2c73fa..a51301773ef00 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -799,8 +799,7 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps, * Run through the enabled capabilities and enable() it on all active * CPUs */ -static void __init -enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps) +void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps) { int i; @@ -954,6 +953,7 @@ void __init setup_cpu_features(void) /* Set the CPU feature capabilies */ setup_feature_capabilities(); setup_cpu_hwcaps(); + enable_errata_workarounds(); /* Advertise that we have computed the system capabilities */ set_sys_caps_initialised(); From 92725fdcefe19947dce5299c2fa9067ee2546b01 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jan 2018 21:37:25 +0000 Subject: [PATCH 089/508] arm64: cpufeature: Pass capability structure to ->enable callback In order to invoke the CPU capability ->matches callback from the ->enable callback for applying local-CPU workarounds, we need a handle on the capability structure. This patch passes a pointer to the capability structure to the ->enable callback. Change-Id: I5f83f1002dd35a4a8f77abe8d0204cef96c37398 Signed-off-by: Will Deacon Git-commit: 0a0d111d40fd1dc588cc590fab6b55d86ddc71d3 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux [neeraju@codeaurora.org: resolve trivial merge conflicts] Signed-off-by: Neeraj Upadhyay --- arch/arm64/kernel/cpufeature.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index a51301773ef00..ddd84dfd406b7 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -805,7 +805,7 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps) for (i = 0; caps[i].matches; i++) if (caps[i].enable && cpus_have_cap(caps[i].capability)) - on_each_cpu(caps[i].enable, NULL, true); + on_each_cpu(caps[i].enable, (void *)&(caps[i]), true); } #ifdef CONFIG_HOTPLUG_CPU @@ -920,7 +920,7 @@ void verify_local_cpu_capabilities(void) if (!feature_matches(__raw_read_system_reg(caps[i].sys_reg), &caps[i])) fail_incapable_cpu("arm64_features", &caps[i]); if (caps[i].enable) - caps[i].enable(NULL); + caps[i].enable((void *)&(caps[i])); } for (i = 0, caps = arm64_hwcaps; caps[i].matches; i++) { From dc0dc3e977cea71f6a22a21706a3c9c8de344e60 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 1 Feb 2017 14:38:46 +0000 Subject: [PATCH 090/508] arm64: cpu_errata: Allow an erratum to be match for all revisions of a core Some minor erratum may not be fixed in further revisions of a core, leading to a situation where the workaround needs to be updated each time an updated core is released. Introduce a MIDR_ALL_VERSIONS match helper that will work for all versions of that MIDR, once and for all. Change-Id: I5e7a8bfea94ad5984d605ca244eb447182928a07 Acked-by: Thomas Gleixner Acked-by: Mark Rutland Acked-by: Daniel Lezcano Reviewed-by: Suzuki K Poulose Signed-off-by: Marc Zyngier Git-commit: 06f1494f837da8997d670a1ba87add7963b08922 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux Signed-off-by: Neeraj Upadhyay --- arch/arm64/kernel/cpu_errata.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 807d1c1de9db1..0efd79592017c 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -47,6 +47,12 @@ is_affected_midr_range(const struct arm64_cpu_capabilities *entry) .midr_range_min = min, \ .midr_range_max = max +#define MIDR_ALL_VERSIONS(model) \ + .matches = is_affected_midr_range, \ + .midr_model = model, \ + .midr_range_min = 0, \ + .midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK) + const struct arm64_cpu_capabilities arm64_errata[] = { #if defined(CONFIG_ARM64_ERRATUM_826319) || \ defined(CONFIG_ARM64_ERRATUM_827319) || \ From f763322f0e2e497c6d96aabe74736cb67724e6fd Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 3 Jan 2018 11:17:58 +0000 Subject: [PATCH 091/508] arm64: Add skeleton to harden the branch predictor against aliasing attacks Aliasing attacks against CPU branch predictors can allow an attacker to redirect speculative control flow on some CPUs and potentially divulge information from one context to another. This patch adds initial skeleton code behind a new Kconfig option to enable implementation-specific mitigations against these attacks for CPUs that are affected. Change-Id: I778641a6a2658cded427204a8c2b01dc6b6b9579 Co-developed-by: Marc Zyngier Signed-off-by: Will Deacon Git-commit: 0f15adbb2861ce6f75ccfc5a92b19eae0ef327d0 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux [neeraju@codeaurora.org: Fix merge conflicts and build failures due to missing includes and api changes in new kernels] Signed-off-by: Neeraj Upadhyay --- arch/arm64/Kconfig | 17 +++++++ arch/arm64/include/asm/cpufeature.h | 1 + arch/arm64/include/asm/mmu.h | 40 +++++++++++++++ arch/arm64/include/asm/sysreg.h | 1 + arch/arm64/kernel/Makefile | 4 ++ arch/arm64/kernel/bpi.S | 55 +++++++++++++++++++++ arch/arm64/kernel/cpu_errata.c | 76 +++++++++++++++++++++++++++++ arch/arm64/kernel/cpufeature.c | 1 + arch/arm64/kernel/entry.S | 8 +-- arch/arm64/mm/context.c | 1 + arch/arm64/mm/fault.c | 16 ++++++ 11 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 arch/arm64/kernel/bpi.S diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 0625f78596bba..ce5afcf34f829 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -813,6 +813,23 @@ config UNMAP_KERNEL_AT_EL0 If unsure, say Y. +config HARDEN_BRANCH_PREDICTOR + bool "Harden the branch predictor against aliasing attacks" if EXPERT + default y + help + Speculation attacks against some high-performance processors rely on + being able to manipulate the branch predictor for a victim context by + executing aliasing branches in the attacker context. Such attacks + can be partially mitigated against by clearing internal branch + predictor state and limiting the prediction logic in some situations. + + This config option will take CPU-specific actions to harden the + branch predictor against aliasing attacks and may rely on specific + instruction sequences or control bits being set by the system + firmware. + + If unsure, say Y. + menuconfig ARMV8_DEPRECATED bool "Emulate deprecated/obsolete ARMv8 instructions" depends on COMPAT diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 81e39e9e1f02a..cacf6c74c7f2e 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -29,6 +29,7 @@ #define ARM64_HAS_PAN 4 #define ARM64_HAS_UAO 5 #define ARM64_ALT_PAN_NOT_UAO 6 +#define ARM64_HARDEN_BRANCH_PREDICTOR 7 #define ARM64_UNMAP_KERNEL_AT_EL0 23 #define ARM64_NCAPS 24 diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index 2fbe8cc639c73..1cd927890ad1c 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -21,7 +21,10 @@ #ifndef __ASSEMBLY__ +#include + #include +#include typedef struct { atomic64_t id; @@ -41,6 +44,43 @@ static inline bool arm64_kernel_unmapped_at_el0(void) cpus_have_cap(ARM64_UNMAP_KERNEL_AT_EL0); } +typedef void (*bp_hardening_cb_t)(void); + +struct bp_hardening_data { + int hyp_vectors_slot; + bp_hardening_cb_t fn; +}; + +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR +extern char __bp_harden_hyp_vecs_start[], __bp_harden_hyp_vecs_end[]; + +DECLARE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data); + +static inline struct bp_hardening_data *arm64_get_bp_hardening_data(void) +{ + return this_cpu_ptr(&bp_hardening_data); +} + +static inline void arm64_apply_bp_hardening(void) +{ + struct bp_hardening_data *d; + + if (!cpus_have_cap(ARM64_HARDEN_BRANCH_PREDICTOR)) + return; + + d = arm64_get_bp_hardening_data(); + if (d->fn) + d->fn(); +} +#else +static inline struct bp_hardening_data *arm64_get_bp_hardening_data(void) +{ + return NULL; +} + +static inline void arm64_apply_bp_hardening(void) { } +#endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ + extern void paging_init(void); extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt); extern void init_mem_pgprot(void); diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 0cc436bf726b5..3e4294cb3c53b 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -101,6 +101,7 @@ #define ID_AA64ISAR0_AES_SHIFT 4 /* id_aa64pfr0 */ +#define ID_AA64PFR0_CSV2_SHIFT 56 #define ID_AA64PFR0_GIC_SHIFT 24 #define ID_AA64PFR0_ASIMD_SHIFT 20 #define ID_AA64PFR0_FP_SHIFT 16 diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 20540372d224d..47a98a5976339 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -42,6 +42,10 @@ arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o arm64-obj-$(CONFIG_MSM_APP_API) += app_api.o arm64-obj-$(CONFIG_MSM_APP_SETTINGS) += app_setting.o +ifeq ($(CONFIG_KVM),y) +arm64-obj-$(CONFIG_HARDEN_BRANCH_PREDICTOR) += bpi.o +endif + obj-y += $(arm64-obj-y) vdso/ obj-m += $(arm64-obj-m) head-y := head.o diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S new file mode 100644 index 0000000000000..06a931eb26737 --- /dev/null +++ b/arch/arm64/kernel/bpi.S @@ -0,0 +1,55 @@ +/* + * Contains CPU specific branch predictor invalidation sequences + * + * Copyright (C) 2018 ARM Ltd. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +.macro ventry target + .rept 31 + nop + .endr + b \target +.endm + +.macro vectors target + ventry \target + 0x000 + ventry \target + 0x080 + ventry \target + 0x100 + ventry \target + 0x180 + + ventry \target + 0x200 + ventry \target + 0x280 + ventry \target + 0x300 + ventry \target + 0x380 + + ventry \target + 0x400 + ventry \target + 0x480 + ventry \target + 0x500 + ventry \target + 0x580 + + ventry \target + 0x600 + ventry \target + 0x680 + ventry \target + 0x700 + ventry \target + 0x780 +.endm + + .align 11 +ENTRY(__bp_harden_hyp_vecs_start) + .rept 4 + vectors __kvm_hyp_vector + .endr +ENTRY(__bp_harden_hyp_vecs_end) diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index efcf303b047a0..499a67de18500 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -41,6 +41,82 @@ is_affected_midr_range(const struct arm64_cpu_capabilities *entry) return (midr >= entry->midr_range_min && midr <= entry->midr_range_max); } +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR +#include +#include + +DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data); + +#ifdef CONFIG_KVM +static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start, + const char *hyp_vecs_end) +{ + void *dst = lm_alias(__bp_harden_hyp_vecs_start + slot * SZ_2K); + int i; + + for (i = 0; i < SZ_2K; i += 0x80) + memcpy(dst + i, hyp_vecs_start, hyp_vecs_end - hyp_vecs_start); + + flush_icache_range((uintptr_t)dst, (uintptr_t)dst + SZ_2K); +} + +static void __install_bp_hardening_cb(bp_hardening_cb_t fn, + const char *hyp_vecs_start, + const char *hyp_vecs_end) +{ + static int last_slot = -1; + static DEFINE_SPINLOCK(bp_lock); + int cpu, slot = -1; + + spin_lock(&bp_lock); + for_each_possible_cpu(cpu) { + if (per_cpu(bp_hardening_data.fn, cpu) == fn) { + slot = per_cpu(bp_hardening_data.hyp_vectors_slot, cpu); + break; + } + } + + if (slot == -1) { + last_slot++; + BUG_ON(((__bp_harden_hyp_vecs_end - __bp_harden_hyp_vecs_start) + / SZ_2K) <= last_slot); + slot = last_slot; + __copy_hyp_vect_bpi(slot, hyp_vecs_start, hyp_vecs_end); + } + + __this_cpu_write(bp_hardening_data.hyp_vectors_slot, slot); + __this_cpu_write(bp_hardening_data.fn, fn); + spin_unlock(&bp_lock); +} +#else +static void __maybe_unused +__install_bp_hardening_cb(bp_hardening_cb_t fn, + const char *hyp_vecs_start, + const char *hyp_vecs_end) +{ + __this_cpu_write(bp_hardening_data.fn, fn); +} +#endif /* CONFIG_KVM */ + +static void __maybe_unused +install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry, + bp_hardening_cb_t fn, + const char *hyp_vecs_start, + const char *hyp_vecs_end) +{ + u64 pfr0; + + if (!entry->matches(entry)) + return; + + pfr0 = read_cpuid(SYS_ID_AA64PFR0_EL1); + if (cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_CSV2_SHIFT)) + return; + + __install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end); +} +#endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ + #define MIDR_RANGE(model, min, max) \ .matches = is_affected_midr_range, \ .midr_model = model, \ diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index ddd84dfd406b7..52c8f3cb8e332 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -87,6 +87,7 @@ static struct arm64_ftr_bits ftr_id_aa64isar0[] = { static struct arm64_ftr_bits ftr_id_aa64pfr0[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 28, 4, 0), + ARM64_FTR_BITS(FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV2_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64PFR0_GIC_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI), ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI), diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index a86ba11be6345..709f8cf0af8e1 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -603,13 +603,15 @@ el0_ia: * Instruction abort handling */ mrs x26, far_el1 - // enable interrupts before calling the main handler - enable_dbg_and_irq + enable_dbg +#ifdef CONFIG_TRACE_IRQFLAGS + bl trace_hardirqs_off +#endif ct_user_exit mov x0, x26 mov x1, x25 mov x2, sp - bl do_mem_abort + bl do_el0_ia_bp_hardening b ret_to_user el0_fpsimd_acc: /* diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c index cc3664b088dec..9758b3d3e0a37 100644 --- a/arch/arm64/mm/context.c +++ b/arch/arm64/mm/context.c @@ -202,6 +202,7 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu) /* Errata workaround post TTBRx_EL1 update. */ asmlinkage void post_ttbr_update_workaround(void) { + arm64_apply_bp_hardening(); } static int asids_init(void) diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index c7fbe5b134058..fd8f918abf7a9 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -515,6 +515,22 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, arm64_notify_die("", regs, &info, esr); } +asmlinkage void __exception do_el0_ia_bp_hardening(unsigned long addr, + unsigned int esr, + struct pt_regs *regs) +{ + /* + * We've taken an instruction abort from userspace and not yet + * re-enabled IRQs. If the address is a kernel address, apply + * BP hardening prior to enabling IRQs and pre-emption. + */ + if (addr > TASK_SIZE) + arm64_apply_bp_hardening(); + + local_irq_enable(); + do_mem_abort(addr, esr, regs); +} + /* * Handle stack alignment exceptions. */ From e7f1e34246850d61c56e0f85487d93726d8cd23c Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 2 Jan 2018 21:45:41 +0000 Subject: [PATCH 092/508] drivers/firmware: Expose psci_get_version through psci_ops structure Entry into recent versions of ARM Trusted Firmware will invalidate the CPU branch predictor state in order to protect against aliasing attacks. This patch exposes the PSCI "VERSION" function via psci_ops, so that it can be invoked outside of the PSCI driver where necessary. Change-Id: Ibe7995e9a311eb7da441d3c65dfdf71e9de3b33c Acked-by: Lorenzo Pieralisi Signed-off-by: Will Deacon Git-commit: d68e3ba5303f7e1099f51fdcd155f5263da8569b Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux [neeraju@codeaurora.org: resolve merge conflicts due to missing files] Signed-off-by: Neeraj Upadhyay --- arch/arm64/include/asm/psci.h | 20 ++++++++++++++++++++ arch/arm64/kernel/psci.c | 22 ++++------------------ 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h index e5312ea0ec1a5..fabf108437266 100644 --- a/arch/arm64/include/asm/psci.h +++ b/arch/arm64/include/asm/psci.h @@ -16,4 +16,24 @@ int psci_init(void); +struct psci_power_state { + u16 id; + u8 type; + u8 affinity_level; +}; + +struct psci_operations { + int (*get_version)(void); + int (*cpu_suspend)(unsigned long state_id, + unsigned long entry_point); + int (*cpu_off)(struct psci_power_state state); + int (*cpu_on)(unsigned long cpuid, unsigned long entry_point); + int (*migrate)(unsigned long cpuid); + int (*affinity_info)(unsigned long target_affinity, + unsigned long lowest_affinity_level); + int (*migrate_info_type)(void); +}; + +extern struct psci_operations psci_ops; + #endif /* __ASM_PSCI_H */ diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c index 892728b303d82..42bab2bd7ca49 100644 --- a/arch/arm64/kernel/psci.c +++ b/arch/arm64/kernel/psci.c @@ -38,24 +38,7 @@ #define PSCI_POWER_STATE_BIT BIT(30) -struct psci_power_state { - u16 id; - u8 type; - u8 affinity_level; -}; - -struct psci_operations { - int (*cpu_suspend)(unsigned long state_id, - unsigned long entry_point); - int (*cpu_off)(struct psci_power_state state); - int (*cpu_on)(unsigned long cpuid, unsigned long entry_point); - int (*migrate)(unsigned long cpuid); - int (*affinity_info)(unsigned long target_affinity, - unsigned long lowest_affinity_level); - int (*migrate_info_type)(void); -}; - -static struct psci_operations psci_ops; +struct psci_operations psci_ops; static int (*invoke_psci_fn)(u64, u64, u64, u64); typedef int (*psci_initcall_t)(const struct device_node *); @@ -307,6 +290,7 @@ static int __init psci_1_0_init(struct device_node *np) } pr_info("Using standard PSCI v0.2 function IDs\n"); + psci_ops.get_version = psci_get_version; psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN64_CPU_SUSPEND; psci_ops.cpu_suspend = psci_cpu_suspend; @@ -360,6 +344,7 @@ static int __init psci_0_2_init(struct device_node *np) } pr_info("Using standard PSCI v0.2 function IDs\n"); + psci_ops.get_version = psci_get_version; psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN64_CPU_SUSPEND; psci_ops.cpu_suspend = psci_cpu_suspend; @@ -402,6 +387,7 @@ static int __init psci_0_1_init(struct device_node *np) goto out_put_node; pr_info("Using PSCI v0.1 Function IDs from DT\n"); + psci_ops.get_version = psci_get_version; if (!of_property_read_u32(np, "cpu_suspend", &id)) { psci_function_id[PSCI_FN_CPU_SUSPEND] = id; From 413501211245b65a22777001ab21e2d16da46170 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 3 Jan 2018 12:46:21 +0000 Subject: [PATCH 093/508] arm64: Implement branch predictor hardening for affected Cortex-A CPUs Cortex-A57, A72, A73 and A75 are susceptible to branch predictor aliasing and can theoretically be attacked by malicious code. This patch implements a PSCI-based mitigation for these CPUs when available. The call into firmware will invalidate the branch predictor state, preventing any malicious entries from affecting other victim contexts. Change-Id: I08acb4a1436709aee7e57ad5e14b37f1a8738038 Co-developed-by: Marc Zyngier Signed-off-by: Will Deacon Git-commit: aa6acde65e03186b5add8151e1ffe36c3c62639b Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux [neeraju@codeaurora.org: resolve merge conflicts. Implement PSCI-based mitigation only for Cortex-A57] Signed-off-by: Neeraj Upadhyay --- arch/arm64/kernel/bpi.S | 24 ++++++++++++++++++++++++ arch/arm64/kernel/cpu_errata.c | 33 +++++++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S index 06a931eb26737..dec95bd82e319 100644 --- a/arch/arm64/kernel/bpi.S +++ b/arch/arm64/kernel/bpi.S @@ -53,3 +53,27 @@ ENTRY(__bp_harden_hyp_vecs_start) vectors __kvm_hyp_vector .endr ENTRY(__bp_harden_hyp_vecs_end) +ENTRY(__psci_hyp_bp_inval_start) + sub sp, sp, #(8 * 18) + stp x16, x17, [sp, #(16 * 0)] + stp x14, x15, [sp, #(16 * 1)] + stp x12, x13, [sp, #(16 * 2)] + stp x10, x11, [sp, #(16 * 3)] + stp x8, x9, [sp, #(16 * 4)] + stp x6, x7, [sp, #(16 * 5)] + stp x4, x5, [sp, #(16 * 6)] + stp x2, x3, [sp, #(16 * 7)] + stp x0, x1, [sp, #(16 * 8)] + mov x0, #0x84000000 + smc #0 + ldp x16, x17, [sp, #(16 * 0)] + ldp x14, x15, [sp, #(16 * 1)] + ldp x12, x13, [sp, #(16 * 2)] + ldp x10, x11, [sp, #(16 * 3)] + ldp x8, x9, [sp, #(16 * 4)] + ldp x6, x7, [sp, #(16 * 5)] + ldp x4, x5, [sp, #(16 * 6)] + ldp x2, x3, [sp, #(16 * 7)] + ldp x0, x1, [sp, #(16 * 8)] + add sp, sp, #(8 * 18) +ENTRY(__psci_hyp_bp_inval_end) diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 561faa3d2e63d..834af5d6478e6 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -48,6 +48,8 @@ is_affected_midr_range(const struct arm64_cpu_capabilities *entry) DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data); #ifdef CONFIG_KVM +extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[]; + static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start, const char *hyp_vecs_end) { @@ -89,10 +91,12 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn, spin_unlock(&bp_lock); } #else -static void __maybe_unused -__install_bp_hardening_cb(bp_hardening_cb_t fn, - const char *hyp_vecs_start, - const char *hyp_vecs_end) +#define __psci_hyp_bp_inval_start NULL +#define __psci_hyp_bp_inval_end NULL + +static void __install_bp_hardening_cb(bp_hardening_cb_t fn, + const char *hyp_vecs_start, + const char *hyp_vecs_end) { __this_cpu_write(bp_hardening_data.fn, fn); } @@ -115,6 +119,20 @@ install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry, __install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end); } + +#include + +static void enable_psci_bp_hardening(void *data) +{ + const struct arm64_cpu_capabilities *entry = data; + + if (psci_ops.get_version) + install_bp_hardening_cb(entry, + (bp_hardening_cb_t)psci_ops.get_version, + __psci_hyp_bp_inval_start, + __psci_hyp_bp_inval_end); + +} #endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ #define MIDR_RANGE(model, min, max) \ @@ -170,6 +188,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = { .capability = ARM64_WORKAROUND_845719, MIDR_RANGE(MIDR_KRYO2XX_SILVER, 0xA00004, 0xA00004), }, +#endif +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR + { + .capability = ARM64_HARDEN_BRANCH_PREDICTOR, + MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), + .enable = enable_psci_bp_hardening, + }, #endif { } From 16995f67b59d2703a4fb69be45326b56921a9a9f Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 13 Dec 2017 14:19:37 -0800 Subject: [PATCH 094/508] arm64: cpu_errata: Add Kryo to Falkor 1003 errata The Kryo CPUs are also affected by the Falkor 1003 errata, so we need to do the same workaround on Kryo CPUs. The MIDR is slightly more complicated here, where the PART number is not always the same when looking at all the bits from 15 to 4. Drop the lower 8 bits and just look at the top 4 to see if it's '2' and then consider those as Kryo CPUs. This covers all the combinations without having to list them all out. Change-Id: I076e583462e6b71172e9d7dc282703eb8a52499d Fixes: 38fd94b0275c ("arm64: Work around Falkor erratum 1003") Acked-by: Will Deacon Signed-off-by: Stephen Boyd Signed-off-by: Catalin Marinas Git-commit: bb48711800e6d7aedbf4dfd3367e0ab1270a6bea Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux [neeraju@codeaurora.org: resolve merge conflicts. Take only the Kryo MIDR definition part.] Signed-off-by: Neeraj Upadhyay --- arch/arm64/include/asm/cputype.h | 1 + arch/arm64/kernel/cpu_errata.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index d0edb7774b682..6b3982df94efb 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -71,6 +71,7 @@ #define ARM_CPU_PART_CORTEX_A72 0xD08 #define ARM_CPU_PART_KRYO2XX_GOLD 0x800 #define ARM_CPU_PART_KRYO2XX_SILVER 0x801 +#define QCOM_CPU_PART_KRYO 0x200 #define APM_CPU_PART_POTENZA 0x000 diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 834af5d6478e6..2ffdac0b34271 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -24,6 +24,7 @@ #define MIDR_CORTEX_A53 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) #define MIDR_CORTEX_A57 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57) #define MIDR_KRYO2XX_SILVER MIDR_CPU_PART(ARM_CPU_IMP_QCOM, ARM_CPU_PART_KRYO2XX_SILVER) +#define MIDR_QCOM_KRYO MIDR_CPU_PART(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO) #define CPU_MODEL_MASK (MIDR_IMPLEMENTOR_MASK | MIDR_PARTNUM_MASK | \ MIDR_ARCHITECTURE_MASK) @@ -41,6 +42,18 @@ is_affected_midr_range(const struct arm64_cpu_capabilities *entry) return (midr >= entry->midr_range_min && midr <= entry->midr_range_max); } +static bool __maybe_unused +is_kryo_midr(const struct arm64_cpu_capabilities *entry) +{ + u32 model; + + model = read_cpuid_id(); + model &= MIDR_IMPLEMENTOR_MASK | (0xf00 << MIDR_PARTNUM_SHIFT) | + MIDR_ARCHITECTURE_MASK; + + return model == entry->midr_model; +} + #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR #include #include From 115d0767dad5852d388820ae534585f965ad9dbe Mon Sep 17 00:00:00 2001 From: Shanker Donthineni Date: Fri, 5 Jan 2018 14:28:59 -0600 Subject: [PATCH 095/508] arm64: Implement branch predictor hardening for Falkor Falkor is susceptible to branch predictor aliasing and can theoretically be attacked by malicious code. This patch implements a mitigation for these attacks, preventing any malicious entries from affecting other victim contexts. Change-Id: Ieb49196c23582c3174f778891ff2ab7cdc96be54 Signed-off-by: Shanker Donthineni [will: fix label name when !CONFIG_KVM and remove references to MIDR_FALKOR] Signed-off-by: Will Deacon Git-commit: ec82b567a74fbdffdf418d4bb381d55f6a9096af Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux [neeraju@codeaurora.org: resolve merge conflicts. Take only qcom_link_stack_sanitization() definition] Signed-off-by: Neeraj Upadhyay --- arch/arm64/kernel/cpu_errata.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 2ffdac0b34271..db1a5cd232868 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -146,6 +146,19 @@ static void enable_psci_bp_hardening(void *data) __psci_hyp_bp_inval_end); } + +static void __maybe_unused qcom_link_stack_sanitization(void) +{ + u64 tmp; + + asm volatile("mov %0, x30 \n" + ".rept 16 \n" + "bl . + 4 \n" + ".endr \n" + "mov x30, %0 \n" + : "=&r" (tmp)); +} + #endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ #define MIDR_RANGE(model, min, max) \ From 2403a874a7d1c92dc603a577b485fe7b936b75bb Mon Sep 17 00:00:00 2001 From: Neeraj Upadhyay Date: Mon, 8 Jan 2018 19:58:29 +0530 Subject: [PATCH 096/508] arm64: Add BTAC/LinkStack sanitizations for Kryo Kryo cores are exposed to two vulnerabilities due to subroutine return (called LINK-STACK) and branch target predictors. These two issues can be mitigated through software workarounds. Kernel: - Apply LINK-STACK mitigation which is issue 16 nested BL instructions on process context switch 'cpu_do_switch_mm()' where ASID changes. - Apply psci based branch predictor invalidation. Change-Id: I983a12dabcd45e3ec757732a44fc567c12228d8b Signed-off-by: Neeraj Upadhyay --- arch/arm64/kernel/cpu_errata.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index db1a5cd232868..37e278e4fd989 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -147,7 +147,7 @@ static void enable_psci_bp_hardening(void *data) } -static void __maybe_unused qcom_link_stack_sanitization(void) +static void qcom_link_stack_sanitization(void) { u64 tmp; @@ -159,6 +159,22 @@ static void __maybe_unused qcom_link_stack_sanitization(void) : "=&r" (tmp)); } +static void qcom_bp_hardening(void) +{ + qcom_link_stack_sanitization(); + if (psci_ops.get_version) + psci_ops.get_version(); +} + +static void enable_qcom_bp_hardening(void *data) +{ + const struct arm64_cpu_capabilities *entry = data; + + install_bp_hardening_cb(entry, + (bp_hardening_cb_t)qcom_bp_hardening, + __psci_hyp_bp_inval_start, + __psci_hyp_bp_inval_end); +} #endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ #define MIDR_RANGE(model, min, max) \ @@ -221,6 +237,12 @@ const struct arm64_cpu_capabilities arm64_errata[] = { MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), .enable = enable_psci_bp_hardening, }, + { + .capability = ARM64_HARDEN_BRANCH_PREDICTOR, + .midr_model = MIDR_QCOM_KRYO, + .matches = is_kryo_midr, + .enable = enable_qcom_bp_hardening, + }, #endif { } From afcfc272bc2662367f45dcdf8f270b709576ea1a Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Thu, 28 Dec 2017 10:04:53 +0800 Subject: [PATCH 097/508] power_supply: Add REAL_TYPE power_supply_property Add REAL_TYPE power_supply property to record the real time charger type. Change-Id: I5fb2e3e3e782bcac0f8dd6071a830bcf370ebbd4 Signed-off-by: Fenglin Wu --- drivers/power/power_supply_sysfs.c | 4 +++- include/linux/power_supply.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 45d1bef8a1ea8..0fd9357b0cea4 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -114,7 +114,8 @@ static ssize_t power_supply_show_property(struct device *dev, return sprintf(buf, "%s\n", technology_text[value.intval]); else if (off == POWER_SUPPLY_PROP_CAPACITY_LEVEL) return sprintf(buf, "%s\n", capacity_level_text[value.intval]); - else if (off == POWER_SUPPLY_PROP_TYPE) + else if (off == POWER_SUPPLY_PROP_TYPE || + off == POWER_SUPPLY_PROP_REAL_TYPE) return sprintf(buf, "%s\n", type_text[value.intval]); else if (off == POWER_SUPPLY_PROP_SCOPE) return sprintf(buf, "%s\n", scope_text[value.intval]); @@ -305,6 +306,7 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(die_health), POWER_SUPPLY_ATTR(connector_health), POWER_SUPPLY_ATTR(hw_current_max), + POWER_SUPPLY_ATTR(real_type), /* Local extensions of type int64_t */ POWER_SUPPLY_ATTR(charge_counter_ext), /* Properties of type `const char *' */ diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 1377722fd63a9..7d3c3df658860 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -259,6 +259,7 @@ enum power_supply_property { POWER_SUPPLY_PROP_DIE_HEALTH, POWER_SUPPLY_PROP_CONNECTOR_HEALTH, POWER_SUPPLY_PROP_HW_CURRENT_MAX, + POWER_SUPPLY_PROP_REAL_TYPE, /* Local extensions of type int64_t */ POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT, /* Properties of type `const char *' */ From 73e857e0d991e31d39113c3b099dc379ecbc8e56 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Mon, 15 Jan 2018 10:27:14 +0800 Subject: [PATCH 098/508] power: qpnp-smbcharger: Report charger types in REAL_TYPE property Use POWER_SUPPLY_PROP_REAL_TYPE property to report charger types between charger and USB drivers. Update usb_psy POWER_SUPPLY_PROP_TYPE property to POWER_SUPPLY_TYPE_USB_DCP if it is HVDCP/HVDCP3 type and ignore reporting POWER_SUPPLY_TYPE_UNKNOWN. This helps the battery HAL to recongize HVDCP/HVDCP3 as AC chargers. Change-Id: Id0116608270dd8c608136d5dede5a09f3538e128 Signed-off-by: Fenglin Wu --- drivers/power/qpnp-smbcharger.c | 13 +++++++---- drivers/usb/dwc3/dwc3-msm.c | 34 ++++++++++++++++++++++------ drivers/usb/phy/phy-msm-usb.c | 39 +++++++++++++++++++++++++-------- include/linux/usb/msm_hsusb.h | 3 ++- 4 files changed, 68 insertions(+), 21 deletions(-) diff --git a/drivers/power/qpnp-smbcharger.c b/drivers/power/qpnp-smbcharger.c index 328877a87951a..696f2e3320909 100644 --- a/drivers/power/qpnp-smbcharger.c +++ b/drivers/power/qpnp-smbcharger.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -4653,6 +4653,7 @@ static int smbchg_change_usb_supply_type(struct smbchg_chip *chip, enum power_supply_type type) { int rc, current_limit_ma; + union power_supply_propval propval; /* * if the type is not unknown, set the type before changing ICL vote @@ -4691,8 +4692,12 @@ static int smbchg_change_usb_supply_type(struct smbchg_chip *chip, goto out; } - if (!chip->skip_usb_notification) - power_supply_set_supply_type(chip->usb_psy, type); + if (!chip->skip_usb_notification) { + propval.intval = type; + chip->usb_psy->set_property(chip->usb_psy, + POWER_SUPPLY_PROP_REAL_TYPE, + &propval); + } /* * otherwise if it is unknown, remove vote @@ -6064,7 +6069,7 @@ static void smbchg_external_power_changed(struct power_supply *psy) current_limit = prop.intval / 1000; rc = chip->usb_psy->get_property(chip->usb_psy, - POWER_SUPPLY_PROP_TYPE, &prop); + POWER_SUPPLY_PROP_REAL_TYPE, &prop); read_usb_type(chip, &usb_type_name, &usb_supply_type); diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 3b553decbf43f..de2a90887e74f 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -238,6 +238,7 @@ struct dwc3_msm { u32 bus_perf_client; struct msm_bus_scale_pdata *bus_scale_table; struct power_supply usb_psy; + enum power_supply_type usb_supply_type; unsigned int online; bool in_host_mode; unsigned int voltage_max; @@ -2511,6 +2512,9 @@ static int dwc3_msm_power_get_property_usb(struct power_supply *psy, case POWER_SUPPLY_PROP_ONLINE: val->intval = mdwc->online; break; + case POWER_SUPPLY_PROP_REAL_TYPE: + val->intval = mdwc->usb_supply_type; + break; case POWER_SUPPLY_PROP_TYPE: val->intval = psy->type; break; @@ -2619,10 +2623,22 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy, mdwc->bc1p2_current_max); } break; - case POWER_SUPPLY_PROP_TYPE: - psy->type = val->intval; - - switch (psy->type) { + case POWER_SUPPLY_PROP_REAL_TYPE: + mdwc->usb_supply_type = val->intval; + /* + * Update TYPE property to DCP for HVDCP/HVDCP3 charger types + * so that they can be recongized as AC chargers by healthd. + * Don't report UNKNOWN charger type to prevent healthd missing + * detecting this power_supply status change. + */ + if (mdwc->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP_3 + || mdwc->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP) + psy->type = POWER_SUPPLY_TYPE_USB_DCP; + else if (mdwc->usb_supply_type == POWER_SUPPLY_TYPE_UNKNOWN) + psy->type = POWER_SUPPLY_TYPE_USB; + else + psy->type = mdwc->usb_supply_type; + switch (mdwc->usb_supply_type) { case POWER_SUPPLY_TYPE_USB: mdwc->chg_type = DWC3_SDP_CHARGER; mdwc->voltage_max = MICRO_5V; @@ -2674,7 +2690,7 @@ dwc3_msm_property_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_PRESENT: case POWER_SUPPLY_PROP_VOLTAGE_MAX: case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX: - case POWER_SUPPLY_PROP_TYPE: + case POWER_SUPPLY_PROP_REAL_TYPE: return 1; default: break; @@ -2698,6 +2714,7 @@ static enum power_supply_property dwc3_msm_pm_power_props_usb[] = { POWER_SUPPLY_PROP_TYPE, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_USB_OTG, + POWER_SUPPLY_PROP_REAL_TYPE, }; static irqreturn_t dwc3_pmic_id_irq(int irq, void *data) @@ -3754,6 +3771,7 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on) static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA) { enum power_supply_type power_supply_type; + union power_supply_propval propval; if (mdwc->charging_disabled) return 0; @@ -3778,7 +3796,9 @@ static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA) else power_supply_type = POWER_SUPPLY_TYPE_UNKNOWN; - power_supply_set_supply_type(&mdwc->usb_psy, power_supply_type); + propval.intval = power_supply_type; + mdwc->usb_psy.set_property(&mdwc->usb_psy, + POWER_SUPPLY_PROP_REAL_TYPE, &propval); skip_psy_type: diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index da957a95a6c2f..20280e8b0eabd 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2017, Linux Foundation. All rights reserved. +/* Copyright (c) 2009-2018, Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1715,7 +1715,7 @@ static void msm_otg_notify_host_mode(struct msm_otg *motg, bool host_mode) static int msm_otg_notify_chg_type(struct msm_otg *motg) { static int charger_type; - + union power_supply_propval propval; /* * TODO * Unify OTG driver charger types and power supply charger types @@ -1742,7 +1742,10 @@ static int msm_otg_notify_chg_type(struct msm_otg *motg) pr_debug("setting usb power supply type %d\n", charger_type); msm_otg_dbg_log_event(&motg->phy, "SET USB PWR SUPPLY TYPE", motg->chg_type, charger_type); - power_supply_set_supply_type(psy, charger_type); + + propval.intval = charger_type; + psy->set_property(psy, POWER_SUPPLY_PROP_REAL_TYPE, &propval); + return 0; } @@ -3525,6 +3528,9 @@ static int otg_power_get_property_usb(struct power_supply *psy, case POWER_SUPPLY_PROP_ONLINE: val->intval = motg->online; break; + case POWER_SUPPLY_PROP_REAL_TYPE: + val->intval = motg->usb_supply_type; + break; case POWER_SUPPLY_PROP_TYPE: val->intval = psy->type; break; @@ -3550,7 +3556,8 @@ static int otg_power_set_property_usb(struct power_supply *psy, struct msm_otg *motg = container_of(psy, struct msm_otg, usb_psy); struct msm_otg_platform_data *pdata = motg->pdata; - msm_otg_dbg_log_event(&motg->phy, "SET PWR PROPERTY", psp, psy->type); + msm_otg_dbg_log_event(&motg->phy, "SET PWR PROPERTY", + psp, motg->usb_supply_type); switch (psp) { case POWER_SUPPLY_PROP_USB_OTG: motg->id_state = val->intval ? USB_ID_GROUND : USB_ID_FLOAT; @@ -3594,9 +3601,21 @@ static int otg_power_set_property_usb(struct power_supply *psy, msm_otg_notify_charger(motg, motg->bc1p2_current_max); } break; - case POWER_SUPPLY_PROP_TYPE: - psy->type = val->intval; - + case POWER_SUPPLY_PROP_REAL_TYPE: + motg->usb_supply_type = val->intval; + /* + * Update TYPE property to DCP for HVDCP/HVDCP3 charger types + * so that they can be recongized as AC chargers by healthd. + * Don't report UNKNOWN charger type to prevent healthd missing + * detecting this power_supply status change. + */ + if (motg->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP_3 + || motg->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP) + psy->type = POWER_SUPPLY_TYPE_USB_DCP; + else if (motg->usb_supply_type == POWER_SUPPLY_TYPE_UNKNOWN) + psy->type = POWER_SUPPLY_TYPE_USB; + else + psy->type = motg->usb_supply_type; /* * If charger detection is done by the USB driver, * motg->chg_type is already assigned in the @@ -3611,7 +3630,7 @@ static int otg_power_set_property_usb(struct power_supply *psy, if (motg->chg_state == USB_CHG_STATE_DETECTED) break; - switch (psy->type) { + switch (motg->usb_supply_type) { case POWER_SUPPLY_TYPE_USB: motg->chg_type = USB_SDP_CHARGER; motg->voltage_max = MICRO_5V; @@ -3650,7 +3669,7 @@ static int otg_power_set_property_usb(struct power_supply *psy, dev_dbg(motg->phy.dev, "%s: charger type = %s\n", __func__, chg_to_string(motg->chg_type)); msm_otg_dbg_log_event(&motg->phy, "SET CHARGER TYPE ", - motg->chg_type, psy->type); + motg->chg_type, motg->usb_supply_type); break; case POWER_SUPPLY_PROP_HEALTH: if (val->intval > POWER_SUPPLY_HEALTH_HOT) @@ -3678,6 +3697,7 @@ static int otg_power_property_is_writeable_usb(struct power_supply *psy, case POWER_SUPPLY_PROP_DP_DM: case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX: case POWER_SUPPLY_PROP_USB_OTG: + case POWER_SUPPLY_PROP_REAL_TYPE: return 1; default: break; @@ -3702,6 +3722,7 @@ static enum power_supply_property otg_pm_power_props_usb[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_DP_DM, POWER_SUPPLY_PROP_USB_OTG, + POWER_SUPPLY_PROP_REAL_TYPE, }; const struct file_operations msm_otg_bus_fops = { diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index 049f312603ad8..7414d3984561e 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h @@ -2,7 +2,7 @@ * * Copyright (C) 2008 Google, Inc. * Author: Brian Swetland - * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2009-2018, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -523,6 +523,7 @@ struct msm_otg { #define PHY_REGULATORS_LPM BIT(4) int reset_counter; struct power_supply usb_psy; + enum power_supply_type usb_supply_type; unsigned int online; unsigned int host_mode; unsigned int voltage_max; From 8e83f023409591b26300c19566562adb95479601 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Fri, 27 Jan 2017 22:28:21 +0530 Subject: [PATCH 099/508] msm: vidc: Handle perf mode configuration Host will set the Venus firmware in below modes 1. If the load of current video session exceeds the venus capability, video driver sets power save mode for that session. 2. If an usecase is recommended to run in power save mode to get power benefits, video driver configures the session in power save mode. 3. If any V4L2 client makes an explicit call to configure the usecase in a certain perf mode, video driver sets the same to venus firmware, unless restricted by core capability. CRs-Fixed: 1106972 Change-Id: Ib8be6c9af1508389edc9cb6444531c6e711b6a11 Signed-off-by: Vikash Garodia Signed-off-by: Sanjay Singh --- .../bindings/media/video/msm-vidc.txt | 4 ++ drivers/media/platform/msm/vidc/msm_venc.c | 46 ++++++++++++------- .../platform/msm/vidc/msm_vidc_res_parse.c | 7 +++ .../platform/msm/vidc/msm_vidc_resources.h | 1 + include/uapi/linux/v4l2-controls.h | 3 ++ 5 files changed, 44 insertions(+), 17 deletions(-) diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt index 8086847127bed..a6dba96a6d705 100644 --- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt +++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt @@ -136,6 +136,9 @@ value is typically max(latencies of every cluster at all power levels) + 1 - qcom,max-secure-instances = An int containing max number of concurrent secure instances supported, accounting for venus and system wide limitations like memory, performance etc. +- qcom,power-conf = Indicates the value at which or beyond, a video session + is configured in low power mode to have power benefits. Value is defined + interms of HxW of the video session beyond which power benefit is desired. [Second level nodes] Context Banks @@ -229,6 +232,7 @@ Example: qcom,qdss-presets = <0xFC307000 0x1000>, <0xFC322000 0x1000>; qcom,max-hw-load = <1224450>; /* 4k @ 30 + 1080p @ 30*/ + qcom,power-conf = <8294400>; /* WxH - 3840*2160 */ qcom,never-unload-fw; clock-names = "foo_clk", "bar_clk", "baz_clk"; qcom,clock-configs = <0x3 0x1 0x0>; diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index 0343e3f087fa2..835c8bbc883f9 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -1169,9 +1169,9 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = { .id = V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE, .name = "Set Encoder performance mode", .type = V4L2_CTRL_TYPE_INTEGER, - .minimum = V4L2_MPEG_VIDC_VIDEO_PERF_MAX_QUALITY, + .minimum = V4L2_MPEG_VIDC_VIDEO_PERF_UNINIT, .maximum = V4L2_MPEG_VIDC_VIDEO_PERF_POWER_SAVE, - .default_value = V4L2_MPEG_VIDC_VIDEO_PERF_MAX_QUALITY, + .default_value = V4L2_MPEG_VIDC_VIDEO_PERF_UNINIT, .step = 1, .qmenu = NULL, }, @@ -1785,9 +1785,10 @@ static int msm_venc_toggle_hier_p(struct msm_vidc_inst *inst, int layers) static inline int msm_venc_power_save_mode_enable(struct msm_vidc_inst *inst) { - u32 rc = 0; - u32 prop_id = 0, power_save_min = 0, power_save_max = 0, inst_load = 0; + u32 rc = 0, height = 0, width = 0; + u32 prop_id = 0, hq_max = 0, power_conf = 0, inst_load = 0; void *pdata = NULL; + bool set_by_client = false, enable_low_power = false; struct hfi_device *hdev = NULL; enum hal_perf_mode venc_mode; enum load_calc_quirks quirks = LOAD_CALC_IGNORE_TURBO_LOAD | @@ -1798,24 +1799,38 @@ static inline int msm_venc_power_save_mode_enable(struct msm_vidc_inst *inst) return -EINVAL; } + hdev = inst->core->device; inst_load = msm_comm_get_inst_load(inst, quirks); - power_save_min = inst->capability.mbs_per_sec_power_save.min; - power_save_max = inst->capability.mbs_per_sec_power_save.max; + hq_max = inst->capability.mbs_per_sec.max; + power_conf = inst->core->resources.power_conf; + height = inst->prop.height[CAPTURE_PORT]; + width = inst->prop.width[CAPTURE_PORT]; - dprintk(VIDC_DBG, - "Power Save Mode min mb's %d max mb's %d inst load %d\n", - power_save_min, power_save_max, inst_load); + switch (msm_comm_g_ctrl_for_id(inst, + V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE)) { + case V4L2_MPEG_VIDC_VIDEO_PERF_MAX_QUALITY: + case V4L2_MPEG_VIDC_VIDEO_PERF_POWER_SAVE: + set_by_client = true; + break; + } - if (!power_save_min || !power_save_max) - return rc; + if (inst_load > hq_max) { + dprintk(VIDC_INFO, "Setting low power w.r.t core limitation\n"); + enable_low_power = true; + } else if (!set_by_client) { + if (power_conf && width * height >= power_conf) { + dprintk(VIDC_INFO, + "Setting low power w.r.t system power recommendation\n"); + enable_low_power = true; + } + } - hdev = inst->core->device; - if (inst_load >= power_save_min) { + if (enable_low_power) { prop_id = HAL_CONFIG_VENC_PERF_MODE; venc_mode = HAL_PERF_MODE_POWER_SAVE; pdata = &venc_mode; rc = call_hfi_op(hdev, session_set_property, - (void *)inst->session, prop_id, pdata); + (void *)inst->session, prop_id, pdata); if (rc) { dprintk(VIDC_ERR, "%s: Failed to set power save mode for inst: %pK\n", @@ -3451,9 +3466,6 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) break; } pdata = &venc_mode; - - msm_dcvs_enc_set_power_save_mode(inst, - ctrl->val == V4L2_MPEG_VIDC_VIDEO_PERF_POWER_SAVE); break; case V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS: if (inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_HEVC) { diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c index 56c191dee781a..d509ba52dda60 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c @@ -1184,6 +1184,13 @@ int read_platform_resources_from_dt( goto err_load_max_hw_load; } + rc = of_property_read_u32(pdev->dev.of_node, "qcom,power-conf", + &res->power_conf); + if (rc) { + dprintk(VIDC_DBG, + "Failed to read power configuration: %d\n", rc); + } + rc = msm_vidc_populate_legacy_context_bank(res); if (rc) { dprintk(VIDC_ERR, diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h index 37057b5437d00..03549750908cb 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h @@ -174,6 +174,7 @@ struct msm_vidc_platform_resources { uint32_t imem_size; enum imem_type imem_type; uint32_t max_load; + uint32_t power_conf; struct platform_device *pdev; struct regulator_set regulator_set; struct clock_set clock_set; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 1260110225a99..6005ca501abe6 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -1053,6 +1053,9 @@ enum vl42_mpeg_vidc_video_h264_svc_nal { (V4L2_CID_MPEG_MSM_VIDC_BASE + 68) enum v4l2_mpeg_vidc_video_perf_mode { +#define V4L2_MPEG_VIDC_VIDEO_PERF_UNINIT \ + V4L2_MPEG_VIDC_VIDEO_PERF_UNINIT + V4L2_MPEG_VIDC_VIDEO_PERF_UNINIT = 0, V4L2_MPEG_VIDC_VIDEO_PERF_MAX_QUALITY = 1, V4L2_MPEG_VIDC_VIDEO_PERF_POWER_SAVE = 2 }; From 33f9492c9496e7ed01d3c6c58bb417f0a5bc3b0f Mon Sep 17 00:00:00 2001 From: Carter Cooper Date: Wed, 17 Jan 2018 09:49:00 -0700 Subject: [PATCH 100/508] msm: kgsl: Properly remove ref count on gpuobj_sync failure The user can pass bad data into kgsl_ioctl_gpuobj_sync(). If _copy_from_user() fails do to bad data, undo any current references taken through this ioctl call. Change-Id: I56195520b9dadba20ee419658fc2cbb282b8449c Signed-off-by: Carter Cooper Signed-off-by: samit vats --- drivers/gpu/msm/kgsl.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index a58d6e8b2080f..9d65f81d68172 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2839,7 +2839,7 @@ long kgsl_ioctl_gpuobj_sync(struct kgsl_device_private *dev_priv, long ret = 0; bool full_flush = false; uint64_t size = 0; - int i, count = 0; + int i; void __user *ptr; if (param->count == 0 || param->count > 128) @@ -2851,8 +2851,8 @@ long kgsl_ioctl_gpuobj_sync(struct kgsl_device_private *dev_priv, entries = kzalloc(param->count * sizeof(*entries), GFP_KERNEL); if (entries == NULL) { - ret = -ENOMEM; - goto out; + kfree(objs); + return -ENOMEM; } ptr = to_user_ptr(param->objs); @@ -2869,36 +2869,32 @@ long kgsl_ioctl_gpuobj_sync(struct kgsl_device_private *dev_priv, if (entries[i] == NULL) continue; - count++; - if (!(objs[i].op & KGSL_GPUMEM_CACHE_RANGE)) size += entries[i]->memdesc.size; else if (objs[i].offset < entries[i]->memdesc.size) size += (entries[i]->memdesc.size - objs[i].offset); full_flush = check_full_flush(size, objs[i].op); - if (full_flush) - break; + if (full_flush) { + trace_kgsl_mem_sync_full_cache(i, size); + flush_cache_all(); + goto out; + } ptr += sizeof(*objs); } - if (full_flush) { - trace_kgsl_mem_sync_full_cache(count, size); - flush_cache_all(); - } else { - for (i = 0; !ret && i < param->count; i++) - if (entries[i]) - ret = _kgsl_gpumem_sync_cache(entries[i], - objs[i].offset, objs[i].length, - objs[i].op); - } + for (i = 0; !ret && i < param->count; i++) + if (entries[i]) + ret = _kgsl_gpumem_sync_cache(entries[i], + objs[i].offset, objs[i].length, + objs[i].op); +out: for (i = 0; i < param->count; i++) if (entries[i]) kgsl_mem_entry_put(entries[i]); -out: kfree(entries); kfree(objs); From f984f62a46ec04c44aed621d78c40c587c537f2e Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 30 Jan 2018 13:03:00 +0530 Subject: [PATCH 101/508] crypto: algif_skcipher - Load TX SG list after waiting We need to load the TX SG list in sendmsg(2) after waiting for incoming data, not before. connoro@google.com: backport to 3.18,where the relevant logic is located in skcipher_recvmsg() rather than skcipher_recvmsg_sync() Change-Id: I4e18b385fe50c844cd62a2eb20122036ea4dfe09 Git-commit: 36c84b22ac8aa041cbdfbe48a55ebb32e3521704 Git-repo: https://android.googlesource.com/kernel/common.git Reported-by: Dmitry Vyukov Signed-off-by: Herbert Xu Tested-by: Dmitry Vyukov Signed-off-by: Connor O'Brien Signed-off-by: Greg Kroah-Hartman Signed-off-by: Kishor PK --- crypto/algif_skcipher.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index d2cacc7f079f8..cbbccfdae1600 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -446,12 +446,6 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock, char __user *from = iov->iov_base; while (seglen) { - sgl = list_first_entry(&ctx->tsgl, - struct skcipher_sg_list, list); - sg = sgl->sg; - - while (!sg->length) - sg++; used = ctx->used; if (!used) { @@ -473,6 +467,12 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock, err = -EINVAL; if (!used) goto free; + sgl = list_first_entry(&ctx->tsgl, + struct skcipher_sg_list, list); + sg = sgl->sg; + + while (!sg->length) + sg++; ablkcipher_request_set_crypt(&ctx->req, sg, ctx->rsgl.sg, used, From a1eb4aa3cb55a4a0fd7d379c4a215e30eb6f308a Mon Sep 17 00:00:00 2001 From: Wei Li Date: Thu, 25 Jan 2018 14:42:50 +0530 Subject: [PATCH 102/508] angler: remove 'reboot edl' interface for security Removed edl interface for security reasons. BUG: 63100473 Change-Id: I9bdcb6b9794e2bc59c6557b6160cf964cc61265c Git-commit: 6bf0876eb2a65282d796620ef2c640a86a61df82 Git-repo: https://android.googlesource.com/kernel/common.git Signed-off-by: Kishor PK --- drivers/power/reset/msm-poweroff.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index cb66ee5e3a9cf..0123fbf309048 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -152,6 +152,7 @@ static bool get_dload_mode(void) return dload_mode_enabled; } +#if 0 static void enable_emergency_dload_mode(void) { int ret; @@ -176,6 +177,7 @@ static void enable_emergency_dload_mode(void) if (ret) pr_err("Failed to set secure EDLOAD mode: %d\n", ret); } +#endif static int dload_set(const char *val, struct kernel_param *kp) { @@ -330,8 +332,10 @@ static void msm_restart_prepare(const char *cmd) if (!ret) __raw_writel(0x6f656d00 | (code & 0xff), restart_reason); +#if 0 } else if (!strncmp(cmd, "edl", 3)) { enable_emergency_dload_mode(); +#endif } else { __raw_writel(0x77665501, restart_reason); } From d0fb9ef535ef1ff52425228749293b7c72e49783 Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Tue, 28 Nov 2017 18:22:11 -0800 Subject: [PATCH 103/508] ANDROID: qtaguid: Fix the UAF probelm with tag_ref_tree When multiple threads is trying to tag/delete the same socket at the same time, there is a chance the tag_ref_entry of the target socket to be null before the uid_tag_data entry is freed. It is caused by the ctrl_cmd_tag function where it doesn't correctly grab the spinlocks when tagging a socket. Signed-off-by: Chenbo Feng Bug: 65853158 Change-Id: I5d89885918054cf835370a52bff2d693362ac5f0 Git-repo: https://android.googlesource.com/kernel/msm Git-commit: a6661da56dc61b67cc65222b71896a775ceb17be Signed-off-by: Dennis Cagle --- net/netfilter/xt_qtaguid.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c index e26c08d8b3ef8..441ac3d903985 100644 --- a/net/netfilter/xt_qtaguid.c +++ b/net/netfilter/xt_qtaguid.c @@ -518,13 +518,11 @@ static struct tag_ref *get_tag_ref(tag_t full_tag, DR_DEBUG("qtaguid: get_tag_ref(0x%llx)\n", full_tag); - spin_lock_bh(&uid_tag_data_tree_lock); tr_entry = lookup_tag_ref(full_tag, &utd_entry); BUG_ON(IS_ERR_OR_NULL(utd_entry)); if (!tr_entry) tr_entry = new_tag_ref(full_tag, utd_entry); - spin_unlock_bh(&uid_tag_data_tree_lock); if (utd_res) *utd_res = utd_entry; DR_DEBUG("qtaguid: get_tag_ref(0x%llx) utd=%p tr=%p\n", @@ -2020,6 +2018,7 @@ static int ctrl_cmd_delete(const char *input) /* Delete socket tags */ spin_lock_bh(&sock_tag_list_lock); + spin_lock_bh(&uid_tag_data_tree_lock); node = rb_first(&sock_tag_tree); while (node) { st_entry = rb_entry(node, struct sock_tag, sock_node); @@ -2049,6 +2048,7 @@ static int ctrl_cmd_delete(const char *input) list_del(&st_entry->list); } } + spin_unlock_bh(&uid_tag_data_tree_lock); spin_unlock_bh(&sock_tag_list_lock); sock_tag_tree_erase(&st_to_free_tree); @@ -2258,10 +2258,12 @@ static int ctrl_cmd_tag(const char *input) full_tag = combine_atag_with_uid(acct_tag, uid_int); spin_lock_bh(&sock_tag_list_lock); + spin_lock_bh(&uid_tag_data_tree_lock); sock_tag_entry = get_sock_stat_nl(el_socket->sk); tag_ref_entry = get_tag_ref(full_tag, &uid_tag_data_entry); if (IS_ERR(tag_ref_entry)) { res = PTR_ERR(tag_ref_entry); + spin_unlock_bh(&uid_tag_data_tree_lock); spin_unlock_bh(&sock_tag_list_lock); goto err_put; } @@ -2288,9 +2290,14 @@ static int ctrl_cmd_tag(const char *input) pr_err("qtaguid: ctrl_tag(%s): " "socket tag alloc failed\n", input); + BUG_ON(tag_ref_entry->num_sock_tags <= 0); + tag_ref_entry->num_sock_tags--; + free_tag_ref_from_utd_entry(tag_ref_entry, + uid_tag_data_entry); + spin_unlock_bh(&uid_tag_data_tree_lock); spin_unlock_bh(&sock_tag_list_lock); res = -ENOMEM; - goto err_tag_unref_put; + goto err_put; } /* * Hold the sk refcount here to make sure the sk pointer cannot @@ -2300,7 +2307,6 @@ static int ctrl_cmd_tag(const char *input) sock_tag_entry->sk = el_socket->sk; sock_tag_entry->pid = current->tgid; sock_tag_entry->tag = combine_atag_with_uid(acct_tag, uid_int); - spin_lock_bh(&uid_tag_data_tree_lock); pqd_entry = proc_qtu_data_tree_search( &proc_qtu_data_tree, current->tgid); /* @@ -2318,11 +2324,11 @@ static int ctrl_cmd_tag(const char *input) else list_add(&sock_tag_entry->list, &pqd_entry->sock_tag_list); - spin_unlock_bh(&uid_tag_data_tree_lock); sock_tag_tree_insert(sock_tag_entry, &sock_tag_tree); atomic64_inc(&qtu_events.sockets_tagged); } + spin_unlock_bh(&uid_tag_data_tree_lock); spin_unlock_bh(&sock_tag_list_lock); /* We keep the ref to the sk until it is untagged */ CT_DEBUG("qtaguid: ctrl_tag(%s): done st@%pk ...->sk_refcnt=%d\n", @@ -2331,10 +2337,6 @@ static int ctrl_cmd_tag(const char *input) sockfd_put(el_socket); return 0; -err_tag_unref_put: - BUG_ON(tag_ref_entry->num_sock_tags <= 0); - tag_ref_entry->num_sock_tags--; - free_tag_ref_from_utd_entry(tag_ref_entry, uid_tag_data_entry); err_put: CT_DEBUG("qtaguid: ctrl_tag(%s): done. ...->sk_refcnt=%d\n", input, atomic_read(&el_socket->sk->sk_refcnt) - 1); From 10ab8293da3849b14e5efb4a0fc83f24aa73eade Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 9 Oct 2017 11:09:20 +0200 Subject: [PATCH 104/508] ALSA: seq: Fix use-after-free at creating a port commit 71105998845fb012937332fe2e806d443c09e026 upstream. There is a potential race window opened at creating and deleting a port via ioctl, as spotted by fuzzing. snd_seq_create_port() creates a port object and returns its pointer, but it doesn't take the refcount, thus it can be deleted immediately by another thread. Meanwhile, snd_seq_ioctl_create_port() still calls the function snd_seq_system_client_ev_port_start() with the created port object that is being deleted, and this triggers use-after-free like: BUG: KASAN: use-after-free in snd_seq_ioctl_create_port+0x504/0x630 [snd_seq] at addr ffff8801f2241cb1 ============================================================================= BUG kmalloc-512 (Tainted: G B ): kasan: bad access detected ----------------------------------------------------------------------------- INFO: Allocated in snd_seq_create_port+0x94/0x9b0 [snd_seq] age=1 cpu=3 pid=4511 ___slab_alloc+0x425/0x460 __slab_alloc+0x20/0x40 kmem_cache_alloc_trace+0x150/0x190 snd_seq_create_port+0x94/0x9b0 [snd_seq] snd_seq_ioctl_create_port+0xd1/0x630 [snd_seq] snd_seq_do_ioctl+0x11c/0x190 [snd_seq] snd_seq_ioctl+0x40/0x80 [snd_seq] do_vfs_ioctl+0x54b/0xda0 SyS_ioctl+0x79/0x90 entry_SYSCALL_64_fastpath+0x16/0x75 INFO: Freed in port_delete+0x136/0x1a0 [snd_seq] age=1 cpu=2 pid=4717 __slab_free+0x204/0x310 kfree+0x15f/0x180 port_delete+0x136/0x1a0 [snd_seq] snd_seq_delete_port+0x235/0x350 [snd_seq] snd_seq_ioctl_delete_port+0xc8/0x180 [snd_seq] snd_seq_do_ioctl+0x11c/0x190 [snd_seq] snd_seq_ioctl+0x40/0x80 [snd_seq] do_vfs_ioctl+0x54b/0xda0 SyS_ioctl+0x79/0x90 entry_SYSCALL_64_fastpath+0x16/0x75 Call Trace: [] dump_stack+0x63/0x82 [] print_trailer+0xfb/0x160 [] object_err+0x34/0x40 [] kasan_report.part.2+0x223/0x520 [] ? snd_seq_ioctl_create_port+0x504/0x630 [snd_seq] [] __asan_report_load1_noabort+0x2e/0x30 [] snd_seq_ioctl_create_port+0x504/0x630 [snd_seq] [] ? snd_seq_ioctl_delete_port+0x180/0x180 [snd_seq] [] ? taskstats_exit+0xbc0/0xbc0 [] snd_seq_do_ioctl+0x11c/0x190 [snd_seq] [] snd_seq_ioctl+0x40/0x80 [snd_seq] [] ? acct_account_cputime+0x63/0x80 [] do_vfs_ioctl+0x54b/0xda0 ..... We may fix this in a few different ways, and in this patch, it's fixed simply by taking the refcount properly at snd_seq_create_port() and letting the caller unref the object after use. Also, there is another potential use-after-free by sprintf() call in snd_seq_create_port(), and this is moved inside the lock. This fix covers CVE-2017-15265. Change-Id: Ie430b35a73063929d037d93b777901f223fc4b5b Git-commit: 23709ae9b61429502fcd4686e7a97333f3b3544a Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git Reported-and-tested-by: Michael23 Yu Suggested-by: Linus Torvalds Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman Signed-off-by: Srinivasa Rao Kuppala --- sound/core/seq/seq_clientmgr.c | 6 +++++- sound/core/seq/seq_ports.c | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 4a240416b830a..41347ad1c4d53 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1260,6 +1260,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, struct snd_seq_client_port *port; struct snd_seq_port_info info; struct snd_seq_port_callback *callback; + int port_idx; if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; @@ -1273,7 +1274,9 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, return -ENOMEM; if (client->type == USER_CLIENT && info.kernel) { - snd_seq_delete_port(client, port->addr.port); + port_idx = port->addr.port; + snd_seq_port_unlock(port); + snd_seq_delete_port(client, port_idx); return -EINVAL; } if (client->type == KERNEL_CLIENT) { @@ -1295,6 +1298,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, snd_seq_set_port_info(port, &info); snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); + snd_seq_port_unlock(port); if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 9c1c8d50f593e..1ddae911255c4 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -122,7 +122,9 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp) } -/* create a port, port number is returned (-1 on failure) */ +/* create a port, port number is returned (-1 on failure); + * the caller needs to unref the port via snd_seq_port_unlock() appropriately + */ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, int port) { @@ -151,6 +153,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, snd_use_lock_init(&new_port->use_lock); port_subs_info_init(&new_port->c_src); port_subs_info_init(&new_port->c_dest); + snd_use_lock_use(&new_port->use_lock); num = port >= 0 ? port : 0; mutex_lock(&client->ports_mutex); @@ -165,9 +168,9 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, list_add_tail(&new_port->list, &p->list); client->num_ports++; new_port->addr.port = num; /* store the port number in the port */ + sprintf(new_port->name, "port-%d", num); write_unlock_irqrestore(&client->ports_lock, flags); mutex_unlock(&client->ports_mutex); - sprintf(new_port->name, "port-%d", num); return new_port; } From b68f2a9039dee58229778a01f1521b3fc696b529 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Tue, 31 Oct 2017 16:55:26 -0700 Subject: [PATCH 105/508] ANDROID: sound: rawmidi: Hold lock around realloc The SNDRV_RAWMIDI_STREAM_{OUTPUT,INPUT} ioctls may reallocate runtime->buffer while other kernel threads are accessing it. If the underlying krealloc() call frees the original buffer, then this can turn into a use-after-free. Most of these accesses happen while the thread is holding runtime->lock, and can be fixed by just holding the same lock while replacing runtime->buffer, however we can't hold this spinlock while snd_rawmidi_kernel_{read1,write1} are copying to/from userspace. We need to add and acquire a new mutex to prevent this from happening concurrently with reallocation. We hold this mutex during the entire reallocation process, to also prevent multiple concurrent reallocations leading to a double-free. Signed-off-by: Daniel Rosenberg bug: 64315347 Change-Id: I05764d4f1a38f373eb7c0ac1c98607ee5ff0eded [dcagle@codeaurora.org: Resolve trivial merge conflict] Git-repo: https://android.googlesource.com/kernel/msm Git-commit: d7193540482d11ff0ad3a07fc18717811641c6eb Signed-off-by: Dennis Cagle --- include/sound/rawmidi.h | 1 + sound/core/rawmidi.c | 44 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index 5bd2bfbf6dd11..0afad5cd6253a 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h @@ -77,6 +77,7 @@ struct snd_rawmidi_runtime { size_t xruns; /* over/underruns counter */ /* misc */ spinlock_t lock; + struct mutex realloc_mutex; wait_queue_head_t sleep; /* event handler (new bytes, input only) */ void (*event)(struct snd_rawmidi_substream *substream); diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 857741431fc63..b0781266572a4 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -115,6 +115,7 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) return -ENOMEM; runtime->substream = substream; spin_lock_init(&runtime->lock); + mutex_init(&runtime->realloc_mutex); init_waitqueue_head(&runtime->sleep); INIT_WORK(&runtime->event_work, snd_rawmidi_input_event_work); runtime->event = NULL; @@ -637,8 +638,10 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, struct snd_rawmidi_params * params) { char *newbuf; + char *oldbuf; struct snd_rawmidi_runtime *runtime = substream->runtime; - + unsigned long flags; + if (substream->append && substream->use_count > 1) return -EBUSY; snd_rawmidi_drain_output(substream); @@ -649,13 +652,22 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, return -EINVAL; } if (params->buffer_size != runtime->buffer_size) { - newbuf = krealloc(runtime->buffer, params->buffer_size, + mutex_lock(&runtime->realloc_mutex); + newbuf = __krealloc(runtime->buffer, params->buffer_size, GFP_KERNEL); - if (!newbuf) + if (!newbuf) { + mutex_unlock(&runtime->realloc_mutex); return -ENOMEM; + } + spin_lock_irqsave(&runtime->lock, flags); + oldbuf = runtime->buffer; runtime->buffer = newbuf; runtime->buffer_size = params->buffer_size; runtime->avail = runtime->buffer_size; + spin_unlock_irqrestore(&runtime->lock, flags); + if (oldbuf != newbuf) + kfree(oldbuf); + mutex_unlock(&runtime->realloc_mutex); } runtime->avail_min = params->avail_min; substream->active_sensing = !params->no_active_sensing; @@ -667,7 +679,9 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, struct snd_rawmidi_params * params) { char *newbuf; + char *oldbuf; struct snd_rawmidi_runtime *runtime = substream->runtime; + unsigned long flags; snd_rawmidi_drain_input(substream); if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) { @@ -677,12 +691,21 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, return -EINVAL; } if (params->buffer_size != runtime->buffer_size) { - newbuf = krealloc(runtime->buffer, params->buffer_size, + mutex_lock(&runtime->realloc_mutex); + newbuf = __krealloc(runtime->buffer, params->buffer_size, GFP_KERNEL); - if (!newbuf) + if (!newbuf) { + mutex_unlock(&runtime->realloc_mutex); return -ENOMEM; + } + spin_lock_irqsave(&runtime->lock, flags); + oldbuf = runtime->buffer; runtime->buffer = newbuf; runtime->buffer_size = params->buffer_size; + spin_unlock_irqrestore(&runtime->lock, flags); + if (oldbuf != newbuf) + kfree(oldbuf); + mutex_unlock(&runtime->realloc_mutex); } runtime->avail_min = params->avail_min; return 0; @@ -955,6 +978,8 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream, unsigned long appl_ptr; spin_lock_irqsave(&runtime->lock, flags); + if (userbuf) + mutex_lock(&runtime->realloc_mutex); while (count > 0 && runtime->avail) { count1 = runtime->buffer_size - runtime->appl_ptr; if (count1 > count) @@ -974,6 +999,7 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream, spin_unlock_irqrestore(&runtime->lock, flags); if (copy_to_user(userbuf + result, runtime->buffer + appl_ptr, count1)) { + mutex_unlock(&runtime->realloc_mutex); return result > 0 ? result : -EFAULT; } spin_lock_irqsave(&runtime->lock, flags); @@ -982,6 +1008,8 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream, count -= count1; } spin_unlock_irqrestore(&runtime->lock, flags); + if (userbuf) + mutex_unlock(&runtime->realloc_mutex); return result; } @@ -1246,10 +1274,14 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream, return -EINVAL; result = 0; + if (userbuf) + mutex_lock(&runtime->realloc_mutex); spin_lock_irqsave(&runtime->lock, flags); if (substream->append) { if ((long)runtime->avail < count) { spin_unlock_irqrestore(&runtime->lock, flags); + if (userbuf) + mutex_unlock(&runtime->realloc_mutex); return -EAGAIN; } } @@ -1285,6 +1317,8 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream, __end: count1 = runtime->avail < runtime->buffer_size; spin_unlock_irqrestore(&runtime->lock, flags); + if (userbuf) + mutex_unlock(&runtime->realloc_mutex); if (count1) snd_rawmidi_output_trigger(substream, 1); return result; From bb8d2302d8089b80a309bd600a7e823086aa639f Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Thu, 22 Feb 2018 00:37:26 +0530 Subject: [PATCH 106/508] wlan: Cache last connection info Currently last connection info is not getting cached, so when GETBSSINFO command comes information is extracted from current conn_info which does not contain all the information required as this information is cleared after disconnection. To address this issue cache the connection info before clearing it. Change-Id: I3ec13264f97e7a4d0dc4699b463074062d087e82 CRs-Fixed: 2188187 --- CORE/HDD/inc/wlan_hdd_main.h | 2 + CORE/HDD/src/wlan_hdd_assoc.c | 3 + CORE/HDD/src/wlan_hdd_cfg80211.c | 104 ++++++++++++++++++------------- 3 files changed, 64 insertions(+), 45 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index 15327de5e1347..fdb877f34f176 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -828,6 +828,8 @@ struct hdd_station_ctx /**Connection information*/ connection_info_t conn_info; + connection_info_t cache_conn_info; + roaming_info_t roam_info; #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c index 94e773d8e7ca5..4e1b9439da7a4 100644 --- a/CORE/HDD/src/wlan_hdd_assoc.c +++ b/CORE/HDD/src/wlan_hdd_assoc.c @@ -795,6 +795,9 @@ static void hdd_save_bss_info(hdd_adapter_t *adapter, } else { hdd_sta_ctx->conn_info.conn_flag.vht_op_present = false; } + /* Cache last connection info */ + vos_mem_copy(&hdd_sta_ctx->cache_conn_info, &hdd_sta_ctx->conn_info, + sizeof(connection_info_t)); } void hdd_connSaveConnectInfo( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, eCsrRoamBssType eBssType ) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 05a6b0920a8a5..c955cae2fc8d7 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -984,7 +984,8 @@ static int32_t hdd_add_tx_bitrate(struct sk_buff *skb, if (!nla_attr) goto fail; /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ - bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate); + bitrate = cfg80211_calculate_bitrate( + &hdd_sta_ctx->cache_conn_info.txrate); /* report 16-bit bitrate only if we can */ bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0; @@ -999,7 +1000,7 @@ static int32_t hdd_add_tx_bitrate(struct sk_buff *skb, goto fail; } if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS, - hdd_sta_ctx->conn_info.txrate.nss)) { + hdd_sta_ctx->cache_conn_info.txrate.nss)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); goto fail; } @@ -1026,7 +1027,7 @@ static int32_t hdd_add_sta_info(struct sk_buff *skb, if (!nla_attr) goto fail; if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL, - (hdd_sta_ctx->conn_info.signal + 100))) { + (hdd_sta_ctx->cache_conn_info.signal + 100))) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); goto fail; } @@ -1056,9 +1057,9 @@ static int32_t hdd_add_survey_info(struct sk_buff *skb, if (!nla_attr) goto fail; if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY, - hdd_sta_ctx->conn_info.freq) || + hdd_sta_ctx->cache_conn_info.freq) || nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE, - (hdd_sta_ctx->conn_info.noise + 100))) { + (hdd_sta_ctx->cache_conn_info.noise + 100))) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); goto fail; } @@ -1087,11 +1088,14 @@ hdd_add_link_standard_info(struct sk_buff *skb, goto fail; if (nla_put(skb, NL80211_ATTR_SSID, - hdd_sta_ctx->conn_info.SSID.SSID.length, - hdd_sta_ctx->conn_info.SSID.SSID.ssId)) { + hdd_sta_ctx->cache_conn_info.SSID.SSID.length, + hdd_sta_ctx->cache_conn_info.SSID.SSID.ssId)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); goto fail; } + if (nla_put(skb, NL80211_ATTR_MAC, VOS_MAC_ADDR_SIZE, + hdd_sta_ctx->cache_conn_info.bssId)) + goto fail; if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO)) goto fail; if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO)) @@ -1119,17 +1123,17 @@ hdd_add_ap_standard_info(struct sk_buff *skb, nla_attr = nla_nest_start(skb, idx); if (!nla_attr) goto fail; - if (hdd_sta_ctx->conn_info.conn_flag.vht_present) + if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_present) if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY, - sizeof(hdd_sta_ctx->conn_info.vht_caps), - &hdd_sta_ctx->conn_info.vht_caps)) { + sizeof(hdd_sta_ctx->cache_conn_info.vht_caps), + &hdd_sta_ctx->cache_conn_info.vht_caps)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); goto fail; } - if (hdd_sta_ctx->conn_info.conn_flag.ht_present) + if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_present) if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY, - sizeof(hdd_sta_ctx->conn_info.ht_caps), - &hdd_sta_ctx->conn_info.ht_caps)) { + sizeof(hdd_sta_ctx->cache_conn_info.ht_caps), + &hdd_sta_ctx->cache_conn_info.ht_caps)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); goto fail; } @@ -1157,28 +1161,33 @@ static int hdd_get_station_info(hdd_context_t *hdd_ctx, hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); nl_buf_len = NLMSG_HDRLEN; - nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) + - sizeof(hdd_sta_ctx->conn_info.freq) + - sizeof(hdd_sta_ctx->conn_info.noise) + - sizeof(hdd_sta_ctx->conn_info.signal) + + + nl_buf_len += sizeof(hdd_sta_ctx->cache_conn_info.SSID.SSID.length) + + VOS_MAC_ADDR_SIZE + + sizeof(hdd_sta_ctx->cache_conn_info.freq) + + sizeof(hdd_sta_ctx->cache_conn_info.noise) + + sizeof(hdd_sta_ctx->cache_conn_info.signal) + (sizeof(uint32_t) * 2) + - sizeof(hdd_sta_ctx->conn_info.txrate.nss) + - sizeof(hdd_sta_ctx->conn_info.roam_count) + - sizeof(hdd_sta_ctx->conn_info.authType) + - sizeof(hdd_sta_ctx->conn_info.dot11Mode); - if (hdd_sta_ctx->conn_info.conn_flag.vht_present) - nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps); - if (hdd_sta_ctx->conn_info.conn_flag.ht_present) - nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps); - if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) { - tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie); - nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - + sizeof(hdd_sta_ctx->cache_conn_info.txrate.nss) + + sizeof(hdd_sta_ctx->cache_conn_info.roam_count) + + sizeof(hdd_sta_ctx->cache_conn_info.authType) + + sizeof(hdd_sta_ctx->cache_conn_info.dot11Mode); + if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_present) + nl_buf_len += sizeof(hdd_sta_ctx->cache_conn_info.vht_caps); + if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_present) + nl_buf_len += sizeof(hdd_sta_ctx->cache_conn_info.ht_caps); + if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present) { + tmp_hs20 = (uint8_t *)&(hdd_sta_ctx-> + cache_conn_info.hs20vendor_ie); + nl_buf_len += + (sizeof(hdd_sta_ctx->cache_conn_info.hs20vendor_ie) - 1); } - if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present) - nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation); - if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present) - nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation); + if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_op_present) + nl_buf_len += sizeof(hdd_sta_ctx->cache_conn_info.ht_operation); + if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present) + nl_buf_len += + sizeof(hdd_sta_ctx->cache_conn_info.vht_operation); skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len); @@ -1199,34 +1208,35 @@ static int hdd_get_station_info(hdd_context_t *hdd_ctx, goto fail; } if (nla_put_u32(skb, INFO_ROAM_COUNT, - hdd_sta_ctx->conn_info.roam_count) || + hdd_sta_ctx->cache_conn_info.roam_count) || nla_put_u32(skb, INFO_AKM, hdd_convert_auth_type( - hdd_sta_ctx->conn_info.authType)) || + hdd_sta_ctx->cache_conn_info.authType)) || nla_put_u32(skb, WLAN802_11_MODE, hdd_convert_dot11mode( - hdd_sta_ctx->conn_info.dot11Mode))) { + hdd_sta_ctx->cache_conn_info.dot11Mode))) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); goto fail; } - if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present) + if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_op_present) if (nla_put(skb, HT_OPERATION, - (sizeof(hdd_sta_ctx->conn_info.ht_operation)), - &hdd_sta_ctx->conn_info.ht_operation)) { + (sizeof(hdd_sta_ctx->cache_conn_info.ht_operation)), + &hdd_sta_ctx->cache_conn_info.ht_operation)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); goto fail; } - if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present) + if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present) if (nla_put(skb, VHT_OPERATION, - (sizeof(hdd_sta_ctx->conn_info.vht_operation)), - &hdd_sta_ctx->conn_info.vht_operation)) { + (sizeof(hdd_sta_ctx-> + cache_conn_info.vht_operation)), + &hdd_sta_ctx->cache_conn_info.vht_operation)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); goto fail; } - if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) + if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present) if (nla_put(skb, AP_INFO_HS20_INDICATION, - (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1), - tmp_hs20 + 1)) { + (sizeof(hdd_sta_ctx->cache_conn_info.hs20vendor_ie) + - 1), tmp_hs20 + 1)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); goto fail; } @@ -16821,7 +16831,6 @@ static int wlan_hdd_cfg80211_set_privacy_ibss( pWextState->roamProfile.AuthType.authType[0] = pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; - if (params->privacy) { /* Security enabled IBSS, At this time there is no information available @@ -17632,7 +17641,9 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_devic wlan_hdd_get_rssi(pAdapter, &sinfo->signal); wlan_hdd_get_snr(pAdapter, &snr); pHddStaCtx->conn_info.signal = sinfo->signal; + pHddStaCtx->cache_conn_info.signal = sinfo->signal; pHddStaCtx->conn_info.noise = pHddStaCtx->conn_info.signal - snr; + pHddStaCtx->cache_conn_info.noise = pHddStaCtx->conn_info.noise; wlan_hdd_fill_station_info_signal(sinfo); /*overwrite rate_flags if MAX link-speed need to be reported*/ @@ -18062,6 +18073,9 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_devic vos_mem_copy(&pHddStaCtx->conn_info.txrate, &sinfo->txrate, sizeof(sinfo->txrate)); + vos_mem_copy(&pHddStaCtx->cache_conn_info.txrate, + &sinfo->txrate, sizeof(sinfo->txrate)); + if (rate_flags & eHAL_TX_RATE_LEGACY) hddLog(LOG1, FL("Reporting RSSI:%d legacy rate %d pkt cnt tx %d rx %d"), sinfo->signal, sinfo->txrate.legacy, sinfo->tx_packets, From 07d424c142ae720347fcbaf02fa1432f6066142f Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Thu, 28 Dec 2017 10:04:53 +0800 Subject: [PATCH 107/508] power_supply: Add REAL_TYPE power_supply_property Add REAL_TYPE power_supply property to record the real time charger type. Change-Id: I5fb2e3e3e782bcac0f8dd6071a830bcf370ebbd4 Signed-off-by: Fenglin Wu --- drivers/power/power_supply_sysfs.c | 4 +++- include/linux/power_supply.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 45d1bef8a1ea8..0fd9357b0cea4 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -114,7 +114,8 @@ static ssize_t power_supply_show_property(struct device *dev, return sprintf(buf, "%s\n", technology_text[value.intval]); else if (off == POWER_SUPPLY_PROP_CAPACITY_LEVEL) return sprintf(buf, "%s\n", capacity_level_text[value.intval]); - else if (off == POWER_SUPPLY_PROP_TYPE) + else if (off == POWER_SUPPLY_PROP_TYPE || + off == POWER_SUPPLY_PROP_REAL_TYPE) return sprintf(buf, "%s\n", type_text[value.intval]); else if (off == POWER_SUPPLY_PROP_SCOPE) return sprintf(buf, "%s\n", scope_text[value.intval]); @@ -305,6 +306,7 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(die_health), POWER_SUPPLY_ATTR(connector_health), POWER_SUPPLY_ATTR(hw_current_max), + POWER_SUPPLY_ATTR(real_type), /* Local extensions of type int64_t */ POWER_SUPPLY_ATTR(charge_counter_ext), /* Properties of type `const char *' */ diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 1377722fd63a9..7d3c3df658860 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -259,6 +259,7 @@ enum power_supply_property { POWER_SUPPLY_PROP_DIE_HEALTH, POWER_SUPPLY_PROP_CONNECTOR_HEALTH, POWER_SUPPLY_PROP_HW_CURRENT_MAX, + POWER_SUPPLY_PROP_REAL_TYPE, /* Local extensions of type int64_t */ POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT, /* Properties of type `const char *' */ From 9dbf8291e20493ff380440ed96406ed3ff065ab1 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Mon, 15 Jan 2018 10:27:14 +0800 Subject: [PATCH 108/508] power: qpnp-smbcharger: Report charger types in REAL_TYPE property Use POWER_SUPPLY_PROP_REAL_TYPE property to report charger types between charger and USB drivers. Update usb_psy POWER_SUPPLY_PROP_TYPE property to POWER_SUPPLY_TYPE_USB_DCP if it is HVDCP/HVDCP3 type and ignore reporting POWER_SUPPLY_TYPE_UNKNOWN. This helps the battery HAL to recongize HVDCP/HVDCP3 as AC chargers. Change-Id: Id0116608270dd8c608136d5dede5a09f3538e128 Signed-off-by: Fenglin Wu --- drivers/power/qpnp-smbcharger.c | 13 +++++++---- drivers/usb/dwc3/dwc3-msm.c | 34 ++++++++++++++++++++++------ drivers/usb/phy/phy-msm-usb.c | 39 +++++++++++++++++++++++++-------- include/linux/usb/msm_hsusb.h | 3 ++- 4 files changed, 68 insertions(+), 21 deletions(-) diff --git a/drivers/power/qpnp-smbcharger.c b/drivers/power/qpnp-smbcharger.c index 8120fb1514d2c..473c314683796 100644 --- a/drivers/power/qpnp-smbcharger.c +++ b/drivers/power/qpnp-smbcharger.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -4660,6 +4660,7 @@ static int smbchg_change_usb_supply_type(struct smbchg_chip *chip, enum power_supply_type type) { int rc, current_limit_ma; + union power_supply_propval propval; /* * if the type is not unknown, set the type before changing ICL vote @@ -4698,8 +4699,12 @@ static int smbchg_change_usb_supply_type(struct smbchg_chip *chip, goto out; } - if (!chip->skip_usb_notification) - power_supply_set_supply_type(chip->usb_psy, type); + if (!chip->skip_usb_notification) { + propval.intval = type; + chip->usb_psy->set_property(chip->usb_psy, + POWER_SUPPLY_PROP_REAL_TYPE, + &propval); + } /* * otherwise if it is unknown, remove vote @@ -6071,7 +6076,7 @@ static void smbchg_external_power_changed(struct power_supply *psy) current_limit = prop.intval / 1000; rc = chip->usb_psy->get_property(chip->usb_psy, - POWER_SUPPLY_PROP_TYPE, &prop); + POWER_SUPPLY_PROP_REAL_TYPE, &prop); read_usb_type(chip, &usb_type_name, &usb_supply_type); diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 3b553decbf43f..de2a90887e74f 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -238,6 +238,7 @@ struct dwc3_msm { u32 bus_perf_client; struct msm_bus_scale_pdata *bus_scale_table; struct power_supply usb_psy; + enum power_supply_type usb_supply_type; unsigned int online; bool in_host_mode; unsigned int voltage_max; @@ -2511,6 +2512,9 @@ static int dwc3_msm_power_get_property_usb(struct power_supply *psy, case POWER_SUPPLY_PROP_ONLINE: val->intval = mdwc->online; break; + case POWER_SUPPLY_PROP_REAL_TYPE: + val->intval = mdwc->usb_supply_type; + break; case POWER_SUPPLY_PROP_TYPE: val->intval = psy->type; break; @@ -2619,10 +2623,22 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy, mdwc->bc1p2_current_max); } break; - case POWER_SUPPLY_PROP_TYPE: - psy->type = val->intval; - - switch (psy->type) { + case POWER_SUPPLY_PROP_REAL_TYPE: + mdwc->usb_supply_type = val->intval; + /* + * Update TYPE property to DCP for HVDCP/HVDCP3 charger types + * so that they can be recongized as AC chargers by healthd. + * Don't report UNKNOWN charger type to prevent healthd missing + * detecting this power_supply status change. + */ + if (mdwc->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP_3 + || mdwc->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP) + psy->type = POWER_SUPPLY_TYPE_USB_DCP; + else if (mdwc->usb_supply_type == POWER_SUPPLY_TYPE_UNKNOWN) + psy->type = POWER_SUPPLY_TYPE_USB; + else + psy->type = mdwc->usb_supply_type; + switch (mdwc->usb_supply_type) { case POWER_SUPPLY_TYPE_USB: mdwc->chg_type = DWC3_SDP_CHARGER; mdwc->voltage_max = MICRO_5V; @@ -2674,7 +2690,7 @@ dwc3_msm_property_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_PRESENT: case POWER_SUPPLY_PROP_VOLTAGE_MAX: case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX: - case POWER_SUPPLY_PROP_TYPE: + case POWER_SUPPLY_PROP_REAL_TYPE: return 1; default: break; @@ -2698,6 +2714,7 @@ static enum power_supply_property dwc3_msm_pm_power_props_usb[] = { POWER_SUPPLY_PROP_TYPE, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_USB_OTG, + POWER_SUPPLY_PROP_REAL_TYPE, }; static irqreturn_t dwc3_pmic_id_irq(int irq, void *data) @@ -3754,6 +3771,7 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on) static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA) { enum power_supply_type power_supply_type; + union power_supply_propval propval; if (mdwc->charging_disabled) return 0; @@ -3778,7 +3796,9 @@ static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA) else power_supply_type = POWER_SUPPLY_TYPE_UNKNOWN; - power_supply_set_supply_type(&mdwc->usb_psy, power_supply_type); + propval.intval = power_supply_type; + mdwc->usb_psy.set_property(&mdwc->usb_psy, + POWER_SUPPLY_PROP_REAL_TYPE, &propval); skip_psy_type: diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index da957a95a6c2f..20280e8b0eabd 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2017, Linux Foundation. All rights reserved. +/* Copyright (c) 2009-2018, Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1715,7 +1715,7 @@ static void msm_otg_notify_host_mode(struct msm_otg *motg, bool host_mode) static int msm_otg_notify_chg_type(struct msm_otg *motg) { static int charger_type; - + union power_supply_propval propval; /* * TODO * Unify OTG driver charger types and power supply charger types @@ -1742,7 +1742,10 @@ static int msm_otg_notify_chg_type(struct msm_otg *motg) pr_debug("setting usb power supply type %d\n", charger_type); msm_otg_dbg_log_event(&motg->phy, "SET USB PWR SUPPLY TYPE", motg->chg_type, charger_type); - power_supply_set_supply_type(psy, charger_type); + + propval.intval = charger_type; + psy->set_property(psy, POWER_SUPPLY_PROP_REAL_TYPE, &propval); + return 0; } @@ -3525,6 +3528,9 @@ static int otg_power_get_property_usb(struct power_supply *psy, case POWER_SUPPLY_PROP_ONLINE: val->intval = motg->online; break; + case POWER_SUPPLY_PROP_REAL_TYPE: + val->intval = motg->usb_supply_type; + break; case POWER_SUPPLY_PROP_TYPE: val->intval = psy->type; break; @@ -3550,7 +3556,8 @@ static int otg_power_set_property_usb(struct power_supply *psy, struct msm_otg *motg = container_of(psy, struct msm_otg, usb_psy); struct msm_otg_platform_data *pdata = motg->pdata; - msm_otg_dbg_log_event(&motg->phy, "SET PWR PROPERTY", psp, psy->type); + msm_otg_dbg_log_event(&motg->phy, "SET PWR PROPERTY", + psp, motg->usb_supply_type); switch (psp) { case POWER_SUPPLY_PROP_USB_OTG: motg->id_state = val->intval ? USB_ID_GROUND : USB_ID_FLOAT; @@ -3594,9 +3601,21 @@ static int otg_power_set_property_usb(struct power_supply *psy, msm_otg_notify_charger(motg, motg->bc1p2_current_max); } break; - case POWER_SUPPLY_PROP_TYPE: - psy->type = val->intval; - + case POWER_SUPPLY_PROP_REAL_TYPE: + motg->usb_supply_type = val->intval; + /* + * Update TYPE property to DCP for HVDCP/HVDCP3 charger types + * so that they can be recongized as AC chargers by healthd. + * Don't report UNKNOWN charger type to prevent healthd missing + * detecting this power_supply status change. + */ + if (motg->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP_3 + || motg->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP) + psy->type = POWER_SUPPLY_TYPE_USB_DCP; + else if (motg->usb_supply_type == POWER_SUPPLY_TYPE_UNKNOWN) + psy->type = POWER_SUPPLY_TYPE_USB; + else + psy->type = motg->usb_supply_type; /* * If charger detection is done by the USB driver, * motg->chg_type is already assigned in the @@ -3611,7 +3630,7 @@ static int otg_power_set_property_usb(struct power_supply *psy, if (motg->chg_state == USB_CHG_STATE_DETECTED) break; - switch (psy->type) { + switch (motg->usb_supply_type) { case POWER_SUPPLY_TYPE_USB: motg->chg_type = USB_SDP_CHARGER; motg->voltage_max = MICRO_5V; @@ -3650,7 +3669,7 @@ static int otg_power_set_property_usb(struct power_supply *psy, dev_dbg(motg->phy.dev, "%s: charger type = %s\n", __func__, chg_to_string(motg->chg_type)); msm_otg_dbg_log_event(&motg->phy, "SET CHARGER TYPE ", - motg->chg_type, psy->type); + motg->chg_type, motg->usb_supply_type); break; case POWER_SUPPLY_PROP_HEALTH: if (val->intval > POWER_SUPPLY_HEALTH_HOT) @@ -3678,6 +3697,7 @@ static int otg_power_property_is_writeable_usb(struct power_supply *psy, case POWER_SUPPLY_PROP_DP_DM: case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX: case POWER_SUPPLY_PROP_USB_OTG: + case POWER_SUPPLY_PROP_REAL_TYPE: return 1; default: break; @@ -3702,6 +3722,7 @@ static enum power_supply_property otg_pm_power_props_usb[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_DP_DM, POWER_SUPPLY_PROP_USB_OTG, + POWER_SUPPLY_PROP_REAL_TYPE, }; const struct file_operations msm_otg_bus_fops = { diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index 049f312603ad8..7414d3984561e 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h @@ -2,7 +2,7 @@ * * Copyright (C) 2008 Google, Inc. * Author: Brian Swetland - * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2009-2018, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -523,6 +523,7 @@ struct msm_otg { #define PHY_REGULATORS_LPM BIT(4) int reset_counter; struct power_supply usb_psy; + enum power_supply_type usb_supply_type; unsigned int online; unsigned int host_mode; unsigned int voltage_max; From d19b1e6936917448aaa9616272497c8c8aff7012 Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Wed, 31 Jan 2018 14:49:37 +0200 Subject: [PATCH 109/508] msm: ipa: Prevent deletion of the default route rule The first APPS default routing table rule is installed at the IPA driver initialization. To prevent routing exception, this rule cannot be deleted by user application. This change prevents deleting this rule. Change-Id: Ia27434fd24a15fea5956018a1271b11bbe227df7 CRs-fixed: 2165859 Signed-off-by: Ghanim Fodi --- drivers/platform/msm/ipa/ipa_v2/ipa_rt.c | 11 ++++++++++- drivers/platform/msm/ipa/ipa_v3/ipa_rt.c | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c index 293a60a60881e..4a68b96ca89a9 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1143,6 +1143,15 @@ int __ipa_del_rt_rule(u32 rule_hdl) return -EINVAL; } + if (!strcmp(entry->tbl->name, IPA_DFLT_RT_TBL_NAME)) { + IPADBG("Deleting rule from default rt table idx=%u\n", + entry->tbl->idx); + if (entry->tbl->rule_cnt == 1) { + IPAERR_RL("Default tbl last rule cannot be deleted\n"); + return -EINVAL; + } + } + if (entry->hdr) __ipa_release_hdr(entry->hdr->id); else if (entry->proc_ctx) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c index 0072a98bbd6c1..f9c08cae466fc 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1456,6 +1456,15 @@ int __ipa3_del_rt_rule(u32 rule_hdl) return -EINVAL; } + if (!strcmp(entry->tbl->name, IPA_DFLT_RT_TBL_NAME)) { + IPADBG("Deleting rule from default rt table idx=%u\n", + entry->tbl->idx); + if (entry->tbl->rule_cnt == 1) { + IPAERR_RL("Default tbl last rule cannot be deleted\n"); + return -EINVAL; + } + } + if (entry->hdr) __ipa3_release_hdr(entry->hdr->id); else if (entry->proc_ctx) From 7cf413c798b8da34e960dbdf8cd57f4891d801c6 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Fri, 19 Jan 2018 18:56:51 +0530 Subject: [PATCH 110/508] msm: ipa: Fix to add string NULL terminator Missing null terminator to userspcae provided string leads to strlen buffer overflow in strlcpy function. Added code changes to fix string NULL terminator issue. Change-Id: I3f9d5f22fbb26f68de12370bc5e07a4e6bc2ced9 Acked-by: Ashok Vuyyuru Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c | 1 + drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c index 3c965ae10f51c..9253782ad6a9d 100644 --- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c @@ -1608,6 +1608,7 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) IPAWANERR("Failed to allocate memory.\n"); return -ENOMEM; } + extend_ioctl_data.u.if_name[IFNAMSIZ-1] = '\0'; len = sizeof(wan_msg->upstream_ifname) > sizeof(extend_ioctl_data.u.if_name) ? sizeof(extend_ioctl_data.u.if_name) : diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index 1a5bea9a3c17b..28a495eb16996 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -1699,6 +1699,7 @@ static int ipa3_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) IPAWANERR("Failed to allocate memory.\n"); return -ENOMEM; } + extend_ioctl_data.u.if_name[IFNAMSIZ-1] = '\0'; len = sizeof(wan_msg->upstream_ifname) > sizeof(extend_ioctl_data.u.if_name) ? sizeof(extend_ioctl_data.u.if_name) : From 7c9c3503a97aafa6c3676aeb9e02e1e9e33f94a7 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 26 Feb 2018 15:41:14 +0530 Subject: [PATCH 111/508] wlan: Fix uninitialized variable access In WDI_ProcessSetAllowedActionFramesInd, driver use variable usLen without initialization during allocation of message buffer. This can result in usage of uninitialized variable. Initialize usLen before usage to fix this issue. Change-Id: I5e782b5ef5e726845fda978b03afeb5c2ded49fd CRs-Fixed: 2195838 --- CORE/WDI/CP/src/wlan_qct_wdi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c index 3a57b30bc0745..6e5069f4d970f 100644 --- a/CORE/WDI/CP/src/wlan_qct_wdi.c +++ b/CORE/WDI/CP/src/wlan_qct_wdi.c @@ -38974,6 +38974,10 @@ WDI_Status WDI_ProcessSetAllowedActionFramesInd(WDI_ControlBlockType *pWDICtx, WDI_ASSERT(0); return WDI_STATUS_E_FAILURE; } + /*----------------------------------------------------------------------- + Get message buffer + -----------------------------------------------------------------------*/ + usLen = sizeof(tHalAllowedActionFrames); if ((WDI_STATUS_SUCCESS != WDI_GetMessageBuffer(pWDICtx, WDI_SET_ALLOWED_ACTION_FRAMES_IND, From 447a1215315e6025282bec021e6f051dc3909956 Mon Sep 17 00:00:00 2001 From: Hardik Arya Date: Wed, 17 Jan 2018 21:03:52 +0530 Subject: [PATCH 112/508] diag: Validate copying length against source buffer length There a possibility of out-of-bound read because of not validating source buffer length against length that about to be copied. The patch adds proper check for validating length before copying data CRs-Fixed: 2163793 Change-Id: I7c93839d0c4d83024ce23a0ce494d09dd08567a9 Signed-off-by: Hardik Arya --- drivers/char/diag/diag_dci.c | 89 ++++++++++++++++++++++++++---------- 1 file changed, 66 insertions(+), 23 deletions(-) diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index 37cc6c7774213..5c810cbf9d016 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1108,18 +1108,31 @@ void extract_dci_events(unsigned char *buf, int len, int data_source, int token) struct list_head *start, *temp; struct diag_dci_client_tbl *entry = NULL; - length = *(uint16_t *)(buf + 1); /* total length of event series */ - if (length == 0) { - pr_err("diag: Incoming dci event length is invalid\n"); + if (!buf) { + pr_err("diag: In %s buffer is NULL\n", __func__); return; } /* - * Move directly to the start of the event series. 1 byte for - * event code and 2 bytes for the length field. + * 1 byte for event code and 2 bytes for the length field. * The length field indicates the total length removing the cmd_code * and the lenght field. The event parsing in that case should happen * till the end. */ + if (len < 3) { + pr_err("diag: In %s invalid len: %d\n", __func__, len); + return; + } + length = *(uint16_t *)(buf + 1); /* total length of event series */ + if ((length == 0) || (len != (length + 3))) { + pr_err("diag: Incoming dci event length: %d is invalid\n", + length); + return; + } + /* + * Move directly to the start of the event series. + * The event parsing should happen from start of event + * series till the end. + */ temp_len = 3; while (temp_len < length) { event_id_packet = *(uint16_t *)(buf + temp_len); @@ -1136,30 +1149,60 @@ void extract_dci_events(unsigned char *buf, int len, int data_source, int token) * necessary. */ timestamp_len = 8; - memcpy(timestamp, buf + temp_len + 2, timestamp_len); + if ((temp_len + timestamp_len + 2) <= len) + memcpy(timestamp, buf + temp_len + 2, + timestamp_len); + else { + pr_err("diag: Invalid length in %s, len: %d, temp_len: %d", + __func__, len, temp_len); + return; + } } /* 13th and 14th bit represent the payload length */ if (((event_id_packet & 0x6000) >> 13) == 3) { payload_len_field = 1; - payload_len = *(uint8_t *) + if ((temp_len + timestamp_len + 3) <= len) { + payload_len = *(uint8_t *) (buf + temp_len + 2 + timestamp_len); - if (payload_len < (MAX_EVENT_SIZE - 13)) { - /* copy the payload length and the payload */ + } else { + pr_err("diag: Invalid length in %s, len: %d, temp_len: %d", + __func__, len, temp_len); + return; + } + if ((payload_len < (MAX_EVENT_SIZE - 13)) && + ((temp_len + timestamp_len + payload_len + 3) <= len)) { + /* + * Copy the payload length and the payload + * after skipping temp_len bytes for already + * parsed packet, timestamp_len for timestamp + * buffer, 2 bytes for event_id_packet. + */ memcpy(event_data + 12, buf + temp_len + 2 + timestamp_len, 1); memcpy(event_data + 13, buf + temp_len + 2 + timestamp_len + 1, payload_len); } else { - pr_err("diag: event > %d, payload_len = %d\n", - (MAX_EVENT_SIZE - 13), payload_len); + pr_err("diag: event > %d, payload_len = %d, temp_len = %d\n", + (MAX_EVENT_SIZE - 13), payload_len, temp_len); return; } } else { payload_len_field = 0; payload_len = (event_id_packet & 0x6000) >> 13; - /* copy the payload */ - memcpy(event_data + 12, buf + temp_len + 2 + + /* + * Copy the payload after skipping temp_len bytes + * for already parsed packet, timestamp_len for + * timestamp buffer, 2 bytes for event_id_packet. + */ + if ((payload_len < (MAX_EVENT_SIZE - 12)) && + ((temp_len + timestamp_len + payload_len + 2) <= len)) + memcpy(event_data + 12, buf + temp_len + 2 + timestamp_len, payload_len); + else { + pr_err("diag: event > %d, payload_len = %d, temp_len = %d\n", + (MAX_EVENT_SIZE - 12), payload_len, temp_len); + return; + } } /* Before copying the data to userspace, check if we are still @@ -1277,19 +1320,19 @@ void extract_dci_log(unsigned char *buf, int len, int data_source, int token) pr_err("diag: In %s buffer is NULL\n", __func__); return; } - - /* The first six bytes for the incoming log packet contains - * Command code (2), the length of the packet (2) and the length - * of the log (2) + /* + * The first eight bytes for the incoming log packet contains + * Command code (2), the length of the packet (2), the length + * of the log (2) and log code (2) */ - log_code = *(uint16_t *)(buf + 6); - read_bytes += sizeof(uint16_t) + 6; - if (read_bytes > len) { - pr_err("diag: Invalid length in %s, len: %d, read: %d", - __func__, len, read_bytes); + if (len < 8) { + pr_err("diag: In %s invalid len: %d\n", __func__, len); return; } + log_code = *(uint16_t *)(buf + 6); + read_bytes += sizeof(uint16_t) + 6; + /* parse through log mask table of each client and check mask */ mutex_lock(&driver->dci_mutex); list_for_each_safe(start, temp, &driver->dci_client_list) { From 58a3e7f77510ee45439ef80240772ac932340bc1 Mon Sep 17 00:00:00 2001 From: Vaishnavi Kommaraju Date: Fri, 19 Jan 2018 17:31:10 +0530 Subject: [PATCH 113/508] ASoC: wcd_cpe_core: Add mutex lock for CPE session Add mutex lock to ensure atomic access to core handle in CPE alloc and dealloc sessions. CRs-Fixed: 2169403 Change-Id: I7e046f349cc56ee06706cf15651dac3fdfe9d9a6 Signed-off-by: Vaishnavi Kommaraju --- sound/soc/codecs/wcd_cpe_core.c | 11 +++++++++++ sound/soc/codecs/wcd_cpe_core.h | 5 ++++- sound/soc/codecs/wcd_cpe_services.c | 4 +++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wcd_cpe_core.c b/sound/soc/codecs/wcd_cpe_core.c index c43638f7cc1d1..72b0f876b10ef 100644 --- a/sound/soc/codecs/wcd_cpe_core.c +++ b/sound/soc/codecs/wcd_cpe_core.c @@ -1953,6 +1953,7 @@ struct wcd_cpe_core *wcd_cpe_init(const char *img_fname, init_completion(&core->online_compl); init_waitqueue_head(&core->ssr_entry.offline_poll_wait); mutex_init(&core->ssr_lock); + mutex_init(&core->session_lock); core->cpe_users = 0; core->cpe_clk_ref = 0; @@ -3406,6 +3407,7 @@ static struct cpe_lsm_session *wcd_cpe_alloc_lsm_session( * If this is the first session to be allocated, * only then register the afe service. */ + WCD_CPE_GRAB_LOCK(&core->session_lock, "session_lock"); if (!wcd_cpe_lsm_session_active()) afe_register_service = true; @@ -3420,6 +3422,7 @@ static struct cpe_lsm_session *wcd_cpe_alloc_lsm_session( dev_err(core->dev, "%s: max allowed sessions already allocated\n", __func__); + WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); return NULL; } @@ -3428,6 +3431,7 @@ static struct cpe_lsm_session *wcd_cpe_alloc_lsm_session( dev_err(core->dev, "%s: Failed to enable cpe, err = %d\n", __func__, ret); + WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); return NULL; } @@ -3474,6 +3478,8 @@ static struct cpe_lsm_session *wcd_cpe_alloc_lsm_session( init_completion(&session->cmd_comp); lsm_sessions[session_id] = session; + + WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); return session; err_afe_mode_cmd: @@ -3488,6 +3494,7 @@ static struct cpe_lsm_session *wcd_cpe_alloc_lsm_session( err_session_alloc: wcd_cpe_vote(core, false); + WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); return NULL; } @@ -3637,9 +3644,11 @@ static int wcd_cpe_dealloc_lsm_session(void *core_handle, struct wcd_cpe_core *core = core_handle; int ret = 0; + WCD_CPE_GRAB_LOCK(&core->session_lock, "session_lock"); if (!session) { dev_err(core->dev, "%s: Invalid lsm session\n", __func__); + WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); return -EINVAL; } @@ -3650,6 +3659,7 @@ static int wcd_cpe_dealloc_lsm_session(void *core_handle, "%s: Wrong session id %d max allowed = %d\n", __func__, session->id, WCD_CPE_LSM_MAX_SESSIONS); + WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); return -EINVAL; } @@ -3670,6 +3680,7 @@ static int wcd_cpe_dealloc_lsm_session(void *core_handle, "%s: Failed to un-vote cpe, err = %d\n", __func__, ret); + WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); return ret; } diff --git a/sound/soc/codecs/wcd_cpe_core.h b/sound/soc/codecs/wcd_cpe_core.h index 77027d58b178f..d534b5caee08f 100644 --- a/sound/soc/codecs/wcd_cpe_core.h +++ b/sound/soc/codecs/wcd_cpe_core.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -169,6 +169,9 @@ struct wcd_cpe_core { /* mutex to protect cpe ssr status variables */ struct mutex ssr_lock; + /* mutex to protect cpe session status variables */ + struct mutex session_lock; + /* Store the calibration data needed for cpe */ struct cal_type_data *cal_data[WCD_CPE_LSM_CAL_MAX]; diff --git a/sound/soc/codecs/wcd_cpe_services.c b/sound/soc/codecs/wcd_cpe_services.c index 3fff18e49d10c..845b4f85782a8 100644 --- a/sound/soc/codecs/wcd_cpe_services.c +++ b/sound/soc/codecs/wcd_cpe_services.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -615,8 +615,10 @@ static enum cpe_svc_result cpe_deregister_generic(struct cpe_info *t_info, return CPE_SVC_INVALID_HANDLE; } + CPE_SVC_GRAB_LOCK(&cpe_d.cpe_svc_lock, "cpe_svc"); list_del(&(n->list)); kfree(reg_handle); + CPE_SVC_REL_LOCK(&cpe_d.cpe_svc_lock, "cpe_svc"); return CPE_SVC_SUCCESS; } From be74537da8f8271425bab65fd51159718f13d45b Mon Sep 17 00:00:00 2001 From: Sanjay Singh Date: Tue, 20 Feb 2018 11:42:04 +0530 Subject: [PATCH 114/508] ARM: dts: msm: Define power configuration for msm8996 and msm8998 Power configuration is a value measured as HxW of a video session. If the resolution of current video session meets this value, the session will be configured in low power mode to get power benefits. CRs-Fixed: 1106972 Change-Id: Ibe4eba7a76a070b1bc02caff89cfb871993043c2 Signed-off-by: Sanjay Singh --- arch/arm/boot/dts/qcom/msm8996-vidc.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/qcom/msm8996-vidc.dtsi b/arch/arm/boot/dts/qcom/msm8996-vidc.dtsi index 3ed55f9d86719..4cfe0c5adef6a 100644 --- a/arch/arm/boot/dts/qcom/msm8996-vidc.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-vidc.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2015, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,6 +32,7 @@ <0x0818C000 0x2000>, <0x0818E000 0x2000>; qcom,max-hw-load = <2563200>; /* Full 4k @ 60 + 1080p @ 60 */ + qcom,power-conf = <8294400>; /* WxH - 3840*2160 */ qcom,firmware-name = "venus"; qcom,imem-size = <524288>; /* 512 kB */ qcom,never-unload-fw; From 4726af1d191852d53948acc52eed80c688b7aee4 Mon Sep 17 00:00:00 2001 From: Veerabhadrarao Badiganti Date: Thu, 8 Jun 2017 23:04:42 +0530 Subject: [PATCH 115/508] mmc: core: Ignore CRC errors with CMD13 while executing tuning While executing tuning in case CMD19 fails, the driver sends CMD13 multiple times to ensure the card is ready to receive the next tuning command. If this status command fails with CRC error, it will trigger tuning. This will result in back to back tuning multiple times. To avoid this situation, ignore CRCs error generated with CMD13 while executing tuning. Change-Id: Ife338768264ebebebc655fe11874e905abdf7482 Signed-off-by: Veerabhadrarao Badiganti --- drivers/mmc/core/host.c | 2 ++ drivers/mmc/host/sdhci.c | 6 ++++++ include/linux/mmc/host.h | 2 ++ 3 files changed, 10 insertions(+) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 5b6b252ded57f..c69d138e2a6af 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -319,6 +319,7 @@ void mmc_retune_enable(struct mmc_host *host) mod_timer(&host->retune_timer, jiffies + host->retune_period * HZ); } +EXPORT_SYMBOL(mmc_retune_enable); void mmc_retune_disable(struct mmc_host *host) { @@ -327,6 +328,7 @@ void mmc_retune_disable(struct mmc_host *host) host->retune_now = 0; host->need_retune = 0; } +EXPORT_SYMBOL(mmc_retune_disable); void mmc_retune_timer_stop(struct mmc_host *host) { diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 5ab646ad04860..a84caa267da49 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2456,7 +2456,13 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) if (host->ops->platform_execute_tuning) { spin_unlock_irqrestore(&host->lock, flags); + /* + * Make sure re-tuning won't get triggered for the CRC errors + * occurred while executing tuning + */ + mmc_retune_disable(mmc); err = host->ops->platform_execute_tuning(host, opcode); + mmc_retune_enable(mmc); sdhci_runtime_pm_put(host); return err; } diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index e6e54e3fd6f28..3c354aeb69bcb 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -833,6 +833,8 @@ static inline bool mmc_card_hs400(struct mmc_card *card) return card->host->ios.timing == MMC_TIMING_MMC_HS400; } +void mmc_retune_enable(struct mmc_host *host); +void mmc_retune_disable(struct mmc_host *host); void mmc_retune_timer_stop(struct mmc_host *host); static inline void mmc_retune_needed(struct mmc_host *host) From eafe644528c584996651a7c16e9a3308673298b5 Mon Sep 17 00:00:00 2001 From: Sreelakshmi Gownipalli Date: Mon, 29 Jan 2018 13:17:13 -0800 Subject: [PATCH 116/508] diag: Add conditional check for len in dci_process_ctrl_status() Add correct conditional check for len in dci_process_ctrl_status() to prevent buffer overflow. Change-Id: Id73ed1c8b104428eceef0544ce2858160cc08fd2 Signed-off-by: Sreelakshmi Gownipalli --- drivers/char/diag/diag_dci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index 37cc6c7774213..845fd5e906679 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -831,7 +831,7 @@ static void dci_process_ctrl_status(unsigned char *buf, int len, int token) read_len += sizeof(struct diag_ctrl_dci_status); for (i = 0; i < header->count; i++) { - if (read_len > len) { + if (read_len > (len - 2)) { pr_err("diag: In %s, Invalid length len: %d\n", __func__, len); return; From bd3cbdbc70eaf6a6b0faba403f7db62b611089fb Mon Sep 17 00:00:00 2001 From: Siddartha Mohanadoss Date: Tue, 28 Nov 2017 15:15:20 -0800 Subject: [PATCH 117/508] msm: mhi_dev: Update channel state on start command After receiving channel start command update channel state. This prevents channel read to fail after a channel reset followed by start command. Change-Id: Id534a4c65e8f5bba02fff814c1d763635ff9fb7e Signed-off-by: Siddartha Mohanadoss --- drivers/platform/msm/mhi_dev/mhi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 14cd067933ea8..a2fe9017152a6 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -963,6 +963,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, /* set the channel to running */ mhi->ch_ctx_cache[ch_id].ch_state = MHI_DEV_CH_STATE_RUNNING; + mhi->ch[ch_id].state = MHI_DEV_CH_STARTED; mhi->ch[ch_id].ch_id = ch_id; mhi->ch[ch_id].ring = &mhi->ring[mhi->ch_ring_start + ch_id]; mhi->ch[ch_id].ch_type = mhi->ch_ctx_cache[ch_id].ch_type; From 8963e2d291deb51c3fbc6206fa69fb8f545dbfa5 Mon Sep 17 00:00:00 2001 From: Siddartha Mohanadoss Date: Fri, 13 Oct 2017 11:00:08 -0700 Subject: [PATCH 118/508] msm: mhi_dev: Add UCI channel Add MBIM channels 12 and 13 among the UCI channel lists so these are exposed as device nodes for MBIM clients to transfer data. Change-Id: I1f8dbc94cde39adc3a13297c4ceb2060e7991d81 Signed-off-by: Siddartha Mohanadoss --- drivers/platform/msm/mhi_dev/mhi_uci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c index 41b1b03a37cc1..924bf04685861 100644 --- a/drivers/platform/msm/mhi_dev/mhi_uci.c +++ b/drivers/platform/msm/mhi_dev/mhi_uci.c @@ -710,6 +710,8 @@ static int uci_init_client_attributes(struct mhi_uci_ctxt_t *uci_ctxt) case MHI_CLIENT_SAHARA_IN: case MHI_CLIENT_EFS_OUT: case MHI_CLIENT_EFS_IN: + case MHI_CLIENT_MBIM_OUT: + case MHI_CLIENT_MBIM_IN: case MHI_CLIENT_QMI_OUT: case MHI_CLIENT_QMI_IN: case MHI_CLIENT_IP_CTRL_0_OUT: From ce4596281d2727f91805da211014138617cddb24 Mon Sep 17 00:00:00 2001 From: Siddartha Mohanadoss Date: Tue, 6 Feb 2018 16:54:54 -0800 Subject: [PATCH 119/508] msm: mhi_dev: Update ring cache logic When MHI (modem host interface) device receives a ring start command do not cache the ring. Cache the ring after a doorbell for the channel is received. This avoid scenario where host has added elements to the transfer ring and updated the write offset as part of start command. Currently device caches the ring to maintain copies of the write and read offset but in the process updates the write offset without calling the client callback indicating there is data. Also fix updating the wrap around condition when caching the ring. Change-Id: Iac0aa9fa97c0075cea1431f7e22e3d916532a37a Signed-off-by: Siddartha Mohanadoss --- drivers/platform/msm/mhi_dev/mhi_ring.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi_ring.c b/drivers/platform/msm/mhi_dev/mhi_ring.c index c4f2803dab83c..785d6d00568d6 100644 --- a/drivers/platform/msm/mhi_dev/mhi_ring.c +++ b/drivers/platform/msm/mhi_dev/mhi_ring.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -71,9 +71,7 @@ int mhi_dev_fetch_ring_elements(struct mhi_dev_ring *ring, host_addr.device_va = ring->ring_shadow.device_va; host_addr.host_pa = ring->ring_shadow.host_pa; host_addr.virt_addr = &ring->ring_cache[0]; - host_addr.phy_addr = (ring->ring_cache_dma_handle + - sizeof(union mhi_dev_ring_element_type) * - start); + host_addr.phy_addr = ring->ring_cache_dma_handle; host_addr.size = (end * sizeof(union mhi_dev_ring_element_type)); mhi_dev_read_from_host(ring->mhi_dev, &host_addr); @@ -386,7 +384,7 @@ int mhi_ring_start(struct mhi_dev_ring *ring, union mhi_dev_ring_ctx *ctx, ring->ring_ctx_shadow = ring->ring_ctx; - if (ring->type != RING_TYPE_ER) { + if (ring->type != RING_TYPE_ER || ring->type != RING_TYPE_CH) { rc = mhi_dev_cache_ring(ring, wr_offset); if (rc) return rc; From b4626d09323c50d8715f21a7588dc53538669080 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 26 Feb 2018 18:16:30 +0530 Subject: [PATCH 120/508] wlan: Fix Null pointer dereference Check session_entry is equal to NULL in Host driver before de-reference it. Fix is to add return status and do required cleanup in case session_entry is NULL. Change-Id: If42d8e1e4df68e6148f497cda6b12d7454158996 CRs-Fixed: 2195907 --- .../MAC/src/pe/lim/limProcessSmeReqMessages.c | 5 +++++ CORE/MAC/src/pe/lim/limUtils.c | 11 ++++++++++- CORE/MAC/src/pe/lim/lim_mbb.c | 19 +++++++++++-------- CORE/SME/src/csr/csr_roam_mbb.c | 16 +++++++++++++++- 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c index a4bb4046131e7..5276aa4224c6b 100644 --- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c +++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c @@ -4142,6 +4142,11 @@ __lim_process_sme_assoc_offload_cnf(tpAniSirGlobal pmac, eLIM_CNF_WAIT_TIMER, aid); } + else + { + limLog(pmac, LOGE, FL("NULL sta_ds")); + goto end; + } if (assoc_cnf.statusCode == eSIR_SME_SUCCESS) { sta_ds->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; diff --git a/CORE/MAC/src/pe/lim/limUtils.c b/CORE/MAC/src/pe/lim/limUtils.c index 3bd1466edc081..af86449f48a00 100644 --- a/CORE/MAC/src/pe/lim/limUtils.c +++ b/CORE/MAC/src/pe/lim/limUtils.c @@ -9044,6 +9044,11 @@ _sap_offload_parse_sta_vht(tpAniSirGlobal pmac, tpSirAssocReq assoc_req) { tpPESession session_entry = limIsApSessionActive(pmac); + if (session_entry == NULL) + { + limLog(pmac, LOGE, FL("Invalid Session Entry")); + goto error; + } if (IS_DOT11_MODE_HT(session_entry->dot11mode) && assoc_req->HTCaps.present && assoc_req->wmeInfoPresent) @@ -9168,7 +9173,11 @@ static void tHalBitVal qos_mode; tHalBitVal wsm_mode, wme_mode; tpPESession session_entry = limIsApSessionActive(pmac); - + if (session_entry == NULL) + { + limLog(pmac, LOGE, FL("Invalid Session Entry")); + return; + } limGetQosMode(session_entry, &qos_mode); sta_ds->qosMode = eANI_BOOLEAN_FALSE; sta_ds->lleEnabled = eANI_BOOLEAN_FALSE; diff --git a/CORE/MAC/src/pe/lim/lim_mbb.c b/CORE/MAC/src/pe/lim/lim_mbb.c index fdf18a2e4bd4b..9cd3501fbc196 100644 --- a/CORE/MAC/src/pe/lim/lim_mbb.c +++ b/CORE/MAC/src/pe/lim/lim_mbb.c @@ -63,6 +63,10 @@ void lim_post_pre_auth_reassoc_rsp(tpAniSirGlobal mac, tANI_U16 rsp_len = sizeof(tSirFTPreAuthRsp); tpPESession session_entry_con_ap; tpDphHashNode sta_ds = NULL; + if (session_entry == NULL) { + limLog(mac, LOGE, FL("Invalid Session Entry")); + return; + } pre_auth_rsp = (tpSirFTPreAuthRsp)vos_mem_malloc(rsp_len); if (NULL == pre_auth_rsp) { @@ -77,9 +81,7 @@ void lim_post_pre_auth_reassoc_rsp(tpAniSirGlobal mac, pre_auth_rsp->length = (tANI_U16)rsp_len; pre_auth_rsp->status = status; pre_auth_rsp->reason = reason; - - if (session_entry) - pre_auth_rsp->smeSessionId = session_entry->smeSessionId; + pre_auth_rsp->smeSessionId = session_entry->smeSessionId; /* The bssid of the AP we are sending Auth1 to. */ if (mac->ft.ftPEContext.pFTPreAuthReq) @@ -668,7 +670,7 @@ void lim_handle_reassoc_mbb_success(tpAniSirGlobal mac, limLog(mac, LOGE, FL("session does not exist for given BSSID" MAC_ADDRESS_STR), MAC_ADDR_ARRAY(mac->ft.ftPEContext.pFTPreAuthReq->currbssId)); - goto end; + goto cleanup; } session_entry->smeSessionId = session_entry_con_ap->smeSessionId; @@ -681,7 +683,7 @@ void lim_handle_reassoc_mbb_success(tpAniSirGlobal mac, limLog(mac, LOGE, FL("sta_ds NULL for given BSSID" MAC_ADDRESS_STR), MAC_ADDR_ARRAY(mac->ft.ftPEContext.pFTPreAuthReq->currbssId)); - goto end; + goto cleanup; } /* @@ -698,9 +700,9 @@ void lim_handle_reassoc_mbb_success(tpAniSirGlobal mac, if (ret_code == eSIR_SUCCESS) return; -end: /* Connected AP lim cleanup.*/ lim_cleanup_connected_ap(mac, sta_ds_connected_ap, session_entry_con_ap); +cleanup: /* * eHAL_STATUS_INVALID_PARAMETER is used * so that full cleanup is triggered. @@ -721,7 +723,7 @@ void lim_handle_reassoc_mbb_success(tpAniSirGlobal mac, static inline void lim_process_preauth_mbb_result(tpAniSirGlobal mac, eHalStatus status, tANI_U32 *data) { - tpPESession session_entry, ft_session_entry; + tpPESession session_entry, ft_session_entry = NULL; tpDphHashNode sta_ds; tAddBssParams *add_bss_params; tSirSmeJoinReq *reassoc_req; @@ -853,7 +855,8 @@ static inline void lim_process_preauth_mbb_result(tpAniSirGlobal mac, return; end: - lim_handle_reassoc_mbb_fail(mac, ft_session_entry); + if (ft_session_entry) + lim_handle_reassoc_mbb_fail(mac, ft_session_entry); } /* diff --git a/CORE/SME/src/csr/csr_roam_mbb.c b/CORE/SME/src/csr/csr_roam_mbb.c index f70172217ae2f..de81060fb962b 100644 --- a/CORE/SME/src/csr/csr_roam_mbb.c +++ b/CORE/SME/src/csr/csr_roam_mbb.c @@ -74,6 +74,11 @@ eHalStatus csr_roam_issue_preauth_reassoc_req(tHalHandle hal, &mac->roam.neighborRoamInfo; eHalStatus status; + if (session == NULL) { + smsLog(mac, LOGE, FL("Invalid Session ID %d"), session_id); + return eHAL_STATUS_FAILURE; + } + auth_req_len = sizeof(tSirFTPreAuthReq); pre_auth_req = (tpSirFTPreAuthReq)vos_mem_malloc(auth_req_len); if (NULL == pre_auth_req) { @@ -453,7 +458,11 @@ eHalStatus csr_update_roamed_info_mbb(tHalHandle hal, /* Get profile */ session = CSR_GET_SESSION(mac, sme_session_id); - + if (session == NULL) { + smsLog(mac, LOGE, + FL("Invalid Session ID %d"), sme_session_id); + return eHAL_STATUS_FAILURE; + } profile = vos_mem_malloc(sizeof(*profile)); if (NULL == profile) { smsLog(mac, LOGE, FL("Memory allocation failure for profile")); @@ -749,6 +758,11 @@ void csr_roam_preauth_rsp_mbb_processor(tHalHandle hal, } session = CSR_GET_SESSION(mac, pre_auth_rsp->smeSessionId); + if (session == NULL) { + smsLog(mac, LOGE, + FL("Invalid Session ID %d"), pre_auth_rsp->smeSessionId); + return; + } if (session->abortConnection) { smsLog(mac, LOGE, FL("Disconnect in progress, stop preauth/reassoc timer")); From d6c0d4afae7a46061782663756510727f62b7714 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Thu, 1 Mar 2018 15:00:48 +0800 Subject: [PATCH 121/508] power: smb1351-charger: Report charger types in REAL_TYPE Commit eca542a92350 ("power: qpnp-smbcharger: Report charger types in REAL_TYPE property") changes to use POWER_SUPPLY_PROP_REAL_TYPE property to report charger types between charger driver and USB driver, so change the same in this driver to make sure USB driver could get the correct charger type notification when it is used as the main charger. Change-Id: Id83dd378cfc808d787d5b5de20a92ed507557803 Signed-off-by: Fenglin Wu --- drivers/power/smb1351-charger.c | 56 ++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/drivers/power/smb1351-charger.c b/drivers/power/smb1351-charger.c index d45c4dc5e8aca..5380d2cb70195 100644 --- a/drivers/power/smb1351-charger.c +++ b/drivers/power/smb1351-charger.c @@ -2888,6 +2888,28 @@ static void smb1351_rerun_apsd_work(struct work_struct *work) smb1351_relax(&chip->smb1351_ws, RERUN_APSD); } +static int smb1351_notify_usb_supply_type(struct smb1351_charger *chip, + enum power_supply_type type) +{ + int rc; + union power_supply_propval pval = {0, }; + + pval.intval = type; + rc = chip->usb_psy->set_property(chip->usb_psy, + POWER_SUPPLY_PROP_REAL_TYPE, &pval); + if (rc < 0) { + if (rc == -EINVAL) { + rc = chip->usb_psy->set_property(chip->usb_psy, + POWER_SUPPLY_PROP_TYPE, &pval); + if (!rc) + return 0; + } + pr_err("notify charger type to usb_psy failed, rc=%d\n", rc); + } + + return rc; +} + static void smb1351_hvdcp_det_work(struct work_struct *work) { int rc; @@ -2907,8 +2929,8 @@ static void smb1351_hvdcp_det_work(struct work_struct *work) is_hvdcp = !!(reg & (HVDCP_SEL_5V | HVDCP_SEL_9V | HVDCP_SEL_12V)); if (is_hvdcp) { pr_debug("HVDCP detected; notifying USB PSY\n"); - power_supply_set_supply_type(chip->usb_psy, - POWER_SUPPLY_TYPE_USB_HVDCP); + smb1351_notify_usb_supply_type(chip, + POWER_SUPPLY_TYPE_USB_HVDCP); } end: smb1351_relax(&chip->smb1351_ws, HVDCP_DETECT); @@ -2963,7 +2985,7 @@ static int smb1351_apsd_complete_handler(struct smb1351_charger *chip, msecs_to_jiffies(HVDCP_NOTIFY_MS)); } } - power_supply_set_supply_type(chip->usb_psy, type); + smb1351_notify_usb_supply_type(chip, type); /* * SMB is now done sampling the D+/D- lines, * indicate USB driver @@ -3015,8 +3037,7 @@ static void smb1351_chg_remove_work(struct work_struct *work) pr_debug("set parallel charger un-present!\n"); power_supply_set_present(parallel_psy, false); } - power_supply_set_supply_type(chip->usb_psy, - POWER_SUPPLY_TYPE_UNKNOWN); + smb1351_notify_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN); power_supply_set_present(chip->usb_psy, chip->chg_present); pr_debug("Set usb psy dp=r dm=r\n"); @@ -3057,8 +3078,8 @@ static int smb1351_usbin_uv_handler(struct smb1351_charger *chip, u8 status) chip->chg_present = true; pr_debug("updating usb_psy present=%d\n", chip->chg_present); - power_supply_set_supply_type(chip->usb_psy, - POWER_SUPPLY_TYPE_USB); + smb1351_notify_usb_supply_type(chip, + POWER_SUPPLY_TYPE_USB); power_supply_set_present(chip->usb_psy, chip->chg_present); /* set parallel slave PRESENT */ @@ -3075,8 +3096,8 @@ static int smb1351_usbin_uv_handler(struct smb1351_charger *chip, u8 status) /* clear parallel slave PRESENT */ if (parallel_psy && chip->parallel.slave_detected) power_supply_set_present(parallel_psy, false); - power_supply_set_supply_type(chip->usb_psy, - POWER_SUPPLY_TYPE_UNKNOWN); + smb1351_notify_usb_supply_type(chip, + POWER_SUPPLY_TYPE_UNKNOWN); power_supply_set_present(chip->usb_psy, chip->chg_present); pr_debug("updating usb_psy present=%d\n", @@ -3127,8 +3148,7 @@ static int smb1351_usbin_ov_handler(struct smb1351_charger *chip, u8 status) /* clear parallel slave PRESENT */ if (parallel_psy && chip->parallel.slave_detected) power_supply_set_present(parallel_psy, false); - power_supply_set_supply_type(chip->usb_psy, - POWER_SUPPLY_TYPE_UNKNOWN); + smb1351_notify_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN); power_supply_set_present(chip->usb_psy, chip->chg_present); } else { chip->usbin_ov = false; @@ -3649,11 +3669,19 @@ static int smb1351_update_usb_supply_icl(struct smb1351_charger *chip) union power_supply_propval pval = {0, }; rc = chip->usb_psy->get_property(chip->usb_psy, - POWER_SUPPLY_PROP_TYPE, &pval); - if (rc) { - pr_err("Get USB supply type failed, rc=%d\n", rc); + POWER_SUPPLY_PROP_REAL_TYPE, &pval); + if (rc == -EINVAL) { + rc = chip->usb_psy->get_property(chip->usb_psy, + POWER_SUPPLY_PROP_TYPE, &pval); + if (rc < 0) { + pr_err("Get USB supply TYPE failed, rc=%d\n", rc); + return rc; + } + } else if (rc < 0) { + pr_err("Get USB supply REAL_TYPE failed, rc=%d\n", rc); return rc; } + type = pval.intval; chip->usb_psy_type = type; rc = chip->usb_psy->get_property(chip->usb_psy, From 41b487f9f5694f339c48c4b8c9ab9edc66f698d6 Mon Sep 17 00:00:00 2001 From: Meera Gande Date: Fri, 2 Mar 2018 15:02:36 +0530 Subject: [PATCH 122/508] msm:camera:isp: Remove unwanted register update At some cases, if register update is not issued from user space, due to the register update at frame drop config, partial settings may be applied. Remove the unwanted register update at frame drop configuration. Change-Id: I717a6c29ae997a3702510f41ef833ec72053b3df Signed-off-by: Meera Gande --- drivers/media/platform/msm/camera_v2/isp/msm_isp40.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c index 0d7d83902be1e..e042ce9b527df 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c @@ -889,8 +889,6 @@ static void msm_vfe40_cfg_framedrop(void __iomem *vfe_base, msm_camera_io_w(temp | (framedrop_period - 1) << 2, vfe_base + VFE40_WM_BASE(stream_info->wm[i]) + 0xC); } - - msm_camera_io_w_mb(0x1, vfe_base + 0x378); } static void msm_vfe40_clear_framedrop(struct vfe_device *vfe_dev, From 4a1bdb7a6779fdca58c60e0ea32895bec2874d78 Mon Sep 17 00:00:00 2001 From: Sreelakshmi Gownipalli Date: Tue, 23 Jan 2018 13:11:41 -0800 Subject: [PATCH 123/508] diag: Protect the decrement of number of diag clients In diagchar_open() protect the decrement of number of diag clients so that there will be no race conditions while reading the value from other functions. Change-Id: I0e2fb5331eec9c7bba39e7d881b69559256833a3 Signed-off-by: Sreelakshmi Gownipalli --- drivers/char/diag/diagchar_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index e5795fd0c61c8..d053013566e6b 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -373,8 +373,8 @@ static int diagchar_open(struct inode *inode, struct file *file) return -ENOMEM; fail: - mutex_unlock(&driver->diagchar_mutex); driver->num_clients--; + mutex_unlock(&driver->diagchar_mutex); pr_err_ratelimited("diag: Insufficient memory for new client"); return -ENOMEM; } From 7ef35efec3ee96588938284ae8bcfd1de3971ee5 Mon Sep 17 00:00:00 2001 From: Vijay Viswanath Date: Mon, 11 Dec 2017 10:50:29 +0530 Subject: [PATCH 124/508] mmc: cmdq-hci: Change unnecessary pr_err logs to pr_debug Now that CMDQ device and driver are stable, Change unnecessary pr_err logs to pr_debug. Also use %pK instead of %p while printing addresses to avoid leaking of kernel addresses. Change-Id: I95683ffe0410daef86dd9a376f5769d8f40ae990 Signed-off-by: Vijay Viswanath --- drivers/mmc/host/cmdq_hci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c index 7e079e628c20e..00bc37c1f8910 100644 --- a/drivers/mmc/host/cmdq_hci.c +++ b/drivers/mmc/host/cmdq_hci.c @@ -331,7 +331,7 @@ static int cmdq_host_alloc_tdl(struct cmdq_host *cq_host) if (!cq_host->desc_base || !cq_host->trans_desc_base) return -ENOMEM; - pr_info("desc-base: 0x%p trans-base: 0x%p\n desc_dma 0x%llx trans_dma: 0x%llx\n", + pr_debug("desc-base: 0x%pK trans-base: 0x%pK\n desc_dma 0x%llx trans_dma: 0x%llx\n", cq_host->desc_base, cq_host->trans_desc_base, (unsigned long long)cq_host->desc_dma_base, (unsigned long long) cq_host->trans_desc_dma_base); From 319972463381b307f45dd63885735ba022ca9df6 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 26 Feb 2018 14:17:02 +0530 Subject: [PATCH 125/508] wlan: Fix uninitialized memory access In WDA_ProcessKeepAliveReq, if packet type is either SIR_KEEP_ALIVE_UNSOLICIT_ARP_RSP or SIR_KEEP_ALIVE_NULL_PKT, then allocated memory is initialized otherwise uninitialized. This can result in uninitialized memory access for packets other than above types. Reset allocated memory to fix this issue. Change-Id: Iaf09226ff68d9b4f4473dbb27796d52caea91310 CRs-Fixed: 2195742 --- CORE/WDA/src/wlan_qct_wda.c | 1 + 1 file changed, 1 insertion(+) diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c index d991cf26917eb..f27cefd4f610f 100644 --- a/CORE/WDA/src/wlan_qct_wda.c +++ b/CORE/WDA/src/wlan_qct_wda.c @@ -12412,6 +12412,7 @@ VOS_STATUS WDA_ProcessKeepAliveReq(tWDA_CbContext *pWDA, sizeof(WDI_KeepAliveReqParamsType)) ; tWDA_ReqParams *pWdaParams; + vos_mem_zero(wdiKeepAliveInfo, sizeof(WDI_KeepAliveReqParamsType)); VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "------> %s " ,__func__); if(NULL == wdiKeepAliveInfo) From 0c827a612d31a55bdc27486205414634ffffb786 Mon Sep 17 00:00:00 2001 From: Vijay Viswanath Date: Fri, 5 Jan 2018 10:40:28 +0530 Subject: [PATCH 126/508] mmc: sdhci: Avoid leaking kernel addresses Use %pK instead of %p in debug logs so that kernel addresses don't get leaked when debug logs are dynamically enabled. Change-Id: I3c0df8a8db6643ab547d8599dd03b54030f76ece Signed-off-by: Vijay Viswanath --- drivers/mmc/host/sdhci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 5ab646ad04860..1cc4a09971e5c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2985,12 +2985,12 @@ static void sdhci_show_adma_error(struct sdhci_host *host) if (host->flags & SDHCI_USE_ADMA_64BIT) { __le64 *dma = (__le64 *)(desc + 4); - pr_info("%s: %p: DMA %llx, LEN 0x%04x, Attr=0x%02x\n", + pr_info("%s: %pK: DMA %llx, LEN 0x%04x, Attr=0x%02x\n", name, desc, (long long)le64_to_cpu(*dma), le16_to_cpu(*len), attr); } else { __le32 *dma = (__le32 *)(desc + 4); - pr_info("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", + pr_info("%s: %pK: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr); } From 907d4d975e553ab1d04be3661f13846107b469a9 Mon Sep 17 00:00:00 2001 From: Vijay Viswanath Date: Fri, 5 Jan 2018 11:22:03 +0530 Subject: [PATCH 127/508] mmc: sdhci-msm: Remove printing tlmm physical address Remove the debug log which leaks physical address, eventhough tlmm is no longer used. Change-Id: Ie6968c46ea063e9192e2ccef053107ee7d8f5775 Signed-off-by: Vijay Viswanath --- drivers/mmc/host/sdhci-msm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 57284d270a5a6..0de2f3965b55f 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -2,7 +2,7 @@ * drivers/mmc/host/sdhci-msm.c - Qualcomm MSM SDHCI Platform * driver source file * - * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -4157,8 +4157,6 @@ static int sdhci_msm_probe(struct platform_device *pdev) goto vreg_deinit; } writel_relaxed(readl_relaxed(tlmm_mem) | 0x2, tlmm_mem); - dev_dbg(&pdev->dev, "tlmm reg %pa value 0x%08x\n", - &tlmm_memres->start, readl_relaxed(tlmm_mem)); } /* From 9becfd0740dfea016434735127606fd17a4b0a6e Mon Sep 17 00:00:00 2001 From: Vijay Viswanath Date: Mon, 11 Dec 2017 10:52:49 +0530 Subject: [PATCH 128/508] mmc: sdhci-msm: Avoid leaking kernel address from mmc platform driver Remove printing the address of sdhci_msm driver variables to avoid leaking the kernel addresses. This is no longer required as the sdhci_msm driver has become stable. Change-Id: I88d9d66d9d00adad8ec79df689ae80f4aae97b7e Signed-off-by: Vijay Viswanath --- drivers/mmc/host/sdhci-msm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 57284d270a5a6..6a3542cf08a3b 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -3657,11 +3657,10 @@ void sdhci_msm_pm_qos_cpu_init(struct sdhci_host *host, group->latency = latency[i].latency[SDHCI_PERFORMANCE_MODE]; pm_qos_add_request(&group->req, PM_QOS_CPU_DMA_LATENCY, group->latency); - pr_info("%s (): voted for group #%d (mask=0x%lx) latency=%d (0x%p)\n", + pr_info("%s (): voted for group #%d (mask=0x%lx) latency=%d\n", __func__, i, group->req.cpus_affine.bits[0], - group->latency, - &latency[i].latency[SDHCI_PERFORMANCE_MODE]); + group->latency); } msm_host->pm_qos_prev_cpu = -1; msm_host->pm_qos_group_enable = true; From 9eea095bb9aace02d2f53c43c2615221383b0412 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Fri, 23 Feb 2018 16:31:46 +0530 Subject: [PATCH 129/508] msm: kgsl: Correct memory type update in IOCTL_KGSL_GPUOBJ_SET_INFO A bad user can pass memory type parameter value greater than 255. Limit the memory type value to valid range before updating memory descriptor flags to avoid incorrect flag update. Change-Id: I23ce69584d1e2c9969583461ee942c5046e7cdbc Signed-off-by: Deepak Kumar --- drivers/gpu/msm/kgsl.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 9d65f81d68172..510a5ef1d49dd 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -3170,6 +3170,7 @@ long kgsl_ioctl_gpuobj_set_info(struct kgsl_device_private *dev_priv, struct kgsl_process_private *private = dev_priv->process_priv; struct kgsl_gpuobj_set_info *param = data; struct kgsl_mem_entry *entry; + int ret = 0; if (param->id == 0) return -EINVAL; @@ -3182,12 +3183,16 @@ long kgsl_ioctl_gpuobj_set_info(struct kgsl_device_private *dev_priv, copy_metadata(entry, param->metadata, param->metadata_len); if (param->flags & KGSL_GPUOBJ_SET_INFO_TYPE) { - entry->memdesc.flags &= ~((uint64_t) KGSL_MEMTYPE_MASK); - entry->memdesc.flags |= param->type << KGSL_MEMTYPE_SHIFT; + if (param->type <= (KGSL_MEMTYPE_MASK >> KGSL_MEMTYPE_SHIFT)) { + entry->memdesc.flags &= ~((uint64_t) KGSL_MEMTYPE_MASK); + entry->memdesc.flags |= (uint64_t)((param->type << + KGSL_MEMTYPE_SHIFT) & KGSL_MEMTYPE_MASK); + } else + ret = -EINVAL; } kgsl_mem_entry_put(entry); - return 0; + return ret; } long kgsl_ioctl_cff_syncmem(struct kgsl_device_private *dev_priv, From 40804e5a2b7d1427659cedb0eee29a477c9d0be1 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Mon, 26 Feb 2018 15:47:54 +0530 Subject: [PATCH 130/508] wlan: Return failure if input arguments are invalid Presently, in vos_nv_readMultiMacAddress(), though input arguments are validated, return is missing if arguments are invalid, this may lead to NULL pointer de-reference or buffer overflow issue. Return if vos_nv_readMultiMacAddress() receives invalid input arguments. Change-Id: I4375ca3653737891a444803539be99ae25cd8257 CRs-Fixed: 2195820 --- CORE/VOSS/src/vos_nvitem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CORE/VOSS/src/vos_nvitem.c b/CORE/VOSS/src/vos_nvitem.c index df980c51ade22..1b6f1b83a1ec4 100644 --- a/CORE/VOSS/src/vos_nvitem.c +++ b/CORE/VOSS/src/vos_nvitem.c @@ -1762,6 +1762,8 @@ VOS_STATUS vos_nv_readMultiMacAddress( v_U8_t *pMacAddress, VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, " Invalid Parameter from NV Client macCount %d, pMacAddress %pK", macCount, pMacAddress); + + return VOS_STATUS_E_INVAL; } status = vos_nv_read( VNV_FIELD_IMAGE, &fieldImage, NULL, From 8d4b8ebd9e9daae060124063da538173f4930772 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Mon, 26 Feb 2018 16:14:10 +0530 Subject: [PATCH 131/508] wlan: Add cfg_ini NULL check before dereferencing Do cfg_ini NULL check before dereferencing the same to access any ini parameter. Change-Id: I041439b3933f016740a209632335e7574c9af5f3 CRs-Fixed: 2195850 --- CORE/HDD/src/wlan_hdd_assoc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c index 4e1b9439da7a4..857527a693f35 100644 --- a/CORE/HDD/src/wlan_hdd_assoc.c +++ b/CORE/HDD/src/wlan_hdd_assoc.c @@ -2795,7 +2795,7 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs hddLog(VOS_TRACE_LEVEL_INFO,"Restart Sap as SAP channel is %d " "and STA channel is %d", pHostapdAdapter->sessionCtx.ap.operatingChannel, (int)pRoamInfo->pBssDesc->channelId); - if (pHddCtx->cfg_ini->force_scc_with_ecsa) + if (pHddCtx->cfg_ini && pHddCtx->cfg_ini->force_scc_with_ecsa) { hdd_schedule_ecsa_chan_change_work(pHddCtx, pAdapter->sessionId); @@ -2803,7 +2803,8 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs else { hdd_hostapd_stop(pHostapdAdapter->dev); - if (pHddCtx->cfg_ini->enable_sap_auth_offload) + if (pHddCtx->cfg_ini && + pHddCtx->cfg_ini->enable_sap_auth_offload) hdd_force_scc_restart_sap(pHostapdAdapter, pHddCtx, (int)pRoamInfo->pBssDesc->channelId); } From 8f528c7641ecfaa9ead34f3e6c2ecbc6c95b2d17 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Mon, 26 Feb 2018 16:49:25 +0530 Subject: [PATCH 132/508] wlan: Get HDD context after validating adapter In hdd_get_nud_stats_cb(), validate adapter before dereferencing the same to retrieve HDD context. Change-Id: I23c53fc85df6c4fdc4c9a4c9a3bb67a72a007c3f CRs-Fixed: 2195868 --- CORE/HDD/src/wlan_hdd_cfg80211.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index c955cae2fc8d7..529766147d58e 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -8166,7 +8166,7 @@ static void hdd_get_nud_stats_cb(void *data, rsp_stats *rsp) { hdd_adapter_t *adapter = (hdd_adapter_t *)data; - hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + hdd_context_t *hdd_ctx; struct hdd_nud_stats_context *context; int status; @@ -8175,13 +8175,14 @@ static void hdd_get_nud_stats_cb(void *data, rsp_stats *rsp) if (NULL == adapter) return; - status = wlan_hdd_validate_context(hdd_ctx); - if (0 != status) { + if (!rsp) { + hddLog(LOGE, FL("data is null")); return; } - if (!rsp) { - hddLog(LOGE, FL("data is null")); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { return; } From be7ff0ce9a9e22b3f91e828dd1fed9d0a2ee9d17 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Mon, 26 Feb 2018 18:20:09 +0530 Subject: [PATCH 133/508] wlan: Validate adapter before accessing 'hddArpStats' To resolve possible NULL pointer dereference, validate adapter before dereferencing it to access 'hddArpStats'. Change-Id: I72742814c3cf81771876314d951e2567b3dff37e CRs-Fixed: 2195913 --- CORE/VOSS/src/vos_api.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c index 11e118fdc6a16..fc10b55035f00 100644 --- a/CORE/VOSS/src/vos_api.c +++ b/CORE/VOSS/src/vos_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -3830,7 +3830,7 @@ void vos_update_arp_fw_tx_delivered(void) { v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); hdd_context_t *pHddCtx = NULL; - hdd_adapter_t * pAdapter; + hdd_adapter_t * pAdapter = NULL; hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; uint8_t status; @@ -3857,8 +3857,8 @@ void vos_update_arp_fw_tx_delivered(void) status = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext); pAdapterNode = pNext; } - - pAdapter->hdd_stats.hddArpStats.tx_host_fw_sent++; + if (pAdapter) + pAdapter->hdd_stats.hddArpStats.tx_host_fw_sent++; } /** @@ -3871,7 +3871,7 @@ void vos_update_arp_rx_drop_reorder(void) { v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); hdd_context_t *pHddCtx = NULL; - hdd_adapter_t * pAdapter; + hdd_adapter_t * pAdapter = NULL; hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; uint8_t status; @@ -3899,7 +3899,8 @@ void vos_update_arp_rx_drop_reorder(void) pAdapterNode = pNext; } - pAdapter->hdd_stats.hddArpStats.rx_host_drop_reorder++; + if (pAdapter) + pAdapter->hdd_stats.hddArpStats.rx_host_drop_reorder++; } v_BOOL_t vos_check_monitor_state(void) From b4537b84dc3ca98be625f587d72756224cce329e Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Fri, 2 Mar 2018 12:20:38 +0530 Subject: [PATCH 134/508] wlan: Fix CPU soft lock up during workqueue cancellation Propagation from qcacld-2.0 to prima. ipv4 and ipv6 workqueues are initialized in open adapter for STA and P2P modes but not for AP mode. The workqueues are cancelled in stop adapter. The cancel_work_sync may be called on AP adapter workqueue also, if just in time, the AP adapter mode has changed to STA mode, for example during hostapd stop etc. This can cause the cancel_work_sync to continuously loop since INIT_WORK has not been called, finally raising CPU stuck. There is no harm in calling INIT_WORK on any workqueue since it only makes sure that in cases as above there is no undeterministic behaviour. Fix cancel_work_sync issues by initializing ipv4 and ipv6 workqueues. Change-Id: Ief8dd0c797dd1492fa30ca4e41da9e583548e21d CRs-Fixed: 2198947 --- CORE/HDD/src/wlan_hdd_main.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 46da26c57bff7..4fbd76158e4e8 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -9064,6 +9064,16 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, hdd_set_conparam( 1 ); + // Workqueue which gets scheduled in IPv4 notification callback. + vos_init_work(&pAdapter->ipv4NotifierWorkQueue, + hdd_ipv4_notifier_work_queue); + +#ifdef WLAN_NS_OFFLOAD + // Workqueue which gets scheduled in IPv6 notification callback. + vos_init_work(&pAdapter->ipv6NotifierWorkQueue, + hdd_ipv6_notifier_work_queue); +#endif + if (WLAN_HDD_P2P_GO == session_type) { /* Initialize the work queue to @@ -9724,6 +9734,12 @@ VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, pAdapter->sessionCtx.ap.beacon = NULL; } mutex_unlock(&pHddCtx->sap_lock); + +#ifdef WLAN_NS_OFFLOAD + vos_flush_work(&pAdapter->ipv6NotifierWorkQueue); +#endif + vos_flush_work(&pAdapter->ipv4NotifierWorkQueue); + break; case WLAN_HDD_MONITOR: From eb8aab8f64e316b4c27a638c541718f93ae4cb29 Mon Sep 17 00:00:00 2001 From: Vignesh Viswanathan Date: Fri, 23 Feb 2018 18:52:42 +0530 Subject: [PATCH 135/508] wlan: Reallocate skb before reusing in wlan_logging pkt_stats filled list In wlan_queue_pkt_stats_for_app, if the pkt_stat_free_list is empty, the current node is taken from the head of pkt_stat_filled_list, detached from the list and skb is set for re-use. This current node is reattached back to the tail of the pkt_stat_filled_list for the next log. This could lead to skb tail overrun as skb is not reset before re-use. Free the existing skb allocated to the pkt_stat_filled_list head and allocate again to have a clean skb. Change-Id: I6bb5de71c8bed062022622cb5394b20d61d35545 CRs-Fixed: 2195551 --- CORE/SVC/src/logging/wlan_logging_sock_svc.c | 115 +++++++++++++++---- 1 file changed, 92 insertions(+), 23 deletions(-) diff --git a/CORE/SVC/src/logging/wlan_logging_sock_svc.c b/CORE/SVC/src/logging/wlan_logging_sock_svc.c index fd4898231f787..ed5f63226981a 100644 --- a/CORE/SVC/src/logging/wlan_logging_sock_svc.c +++ b/CORE/SVC/src/logging/wlan_logging_sock_svc.c @@ -193,6 +193,7 @@ struct wlan_logging { struct fw_mem_dump_logging fw_mem_dump_ctx; int pkt_stat_num_buf; unsigned int pkt_stat_drop_cnt; + unsigned int malloc_fail_count; struct list_head pkt_stat_free_list; struct list_head pkt_stat_filled_list; struct pkt_stats_msg *pkt_stats_pcur_node; @@ -407,34 +408,51 @@ bool wlan_isPktStatsEnabled(void) /* Need to call this with spin_lock acquired */ -static int wlan_queue_pkt_stats_for_app(void) +static int wlan_queue_pkt_stats_for_app(struct sk_buff *skb_to_free) { int ret = 0; + struct sk_buff *skb_new = NULL; + struct pkt_stats_msg *tmp_node = NULL; - list_add_tail(&gwlan_logging.pkt_stats_pcur_node->node, + if (!list_empty(&gwlan_logging.pkt_stat_free_list)) { + /* Add current node to end of filled list */ + list_add_tail(&gwlan_logging.pkt_stats_pcur_node->node, &gwlan_logging.pkt_stat_filled_list); - if (!list_empty(&gwlan_logging.pkt_stat_free_list)) { /* Get buffer from free list */ gwlan_logging.pkt_stats_pcur_node = - (struct pkt_stats_msg *)(gwlan_logging.pkt_stat_free_list.next); + (struct pkt_stats_msg *)(gwlan_logging. + pkt_stat_free_list.next); list_del_init(gwlan_logging.pkt_stat_free_list.next); } else if (!list_empty(&gwlan_logging.pkt_stat_filled_list)) { - /* Get buffer from filled list */ - /* This condition will drop the packet from being + /* + * Get buffer from filled list, free the skb and allocate a + * new skb so that the current node has a clean skb + */ + tmp_node = (struct pkt_stats_msg *)(gwlan_logging. + pkt_stat_filled_list.next); + + skb_new = dev_alloc_skb(MAX_PKTSTATS_LOG_LENGTH); + if (skb_new == NULL) { + /* Print error for every 512 malloc fails */ + gwlan_logging.malloc_fail_count++; + return -ENOMEM; + } + skb_to_free = tmp_node->skb; + tmp_node->skb = skb_new; + + /* + * This condition will drop the packet from being * indicated to app */ - gwlan_logging.pkt_stats_pcur_node = - (struct pkt_stats_msg *)(gwlan_logging.pkt_stat_filled_list.next); ++gwlan_logging.pkt_stat_drop_cnt; - /* print every 64th drop count */ - if (vos_is_multicast_logging() && - (!(gwlan_logging.pkt_stat_drop_cnt % 0x40))) { - pr_err("%s: drop_count = %u filled_length = %d\n", - __func__, gwlan_logging.pkt_stat_drop_cnt, - gwlan_logging.pkt_stats_pcur_node->skb->len); - } - list_del_init(gwlan_logging.pkt_stat_filled_list.next); + + /* Add current node to end of filled list */ + list_add_tail(&gwlan_logging.pkt_stats_pcur_node->node, + &gwlan_logging.pkt_stat_filled_list); + + gwlan_logging.pkt_stats_pcur_node = tmp_node; + list_del_init((struct list_head *) tmp_node); ret = 1; } @@ -450,7 +468,9 @@ int wlan_pkt_stats_to_user(void *perPktStat) unsigned long flags; tx_rx_pkt_stats rx_tx_stats; int total_log_len = 0; + int ret = 0; struct sk_buff *ptr; + struct sk_buff *skb_to_free = NULL; tpSirMacMgmtHdr hdr; uint32 rateIdx; @@ -526,19 +546,42 @@ int wlan_pkt_stats_to_user(void *perPktStat) return -EIO; } - ; - - /* Check if we can accomodate more log into current node/buffer */ + /* Check if we can accomodate more log into current node/buffer */ if (total_log_len + sizeof(vos_log_pktlog_info) + sizeof(tAniNlHdr) >= - skb_tailroom(gwlan_logging.pkt_stats_pcur_node->skb)) { + skb_tailroom(gwlan_logging.pkt_stats_pcur_node->skb)) { + ret = wlan_queue_pkt_stats_for_app(skb_to_free); + if (ret == -ENOMEM) { + spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, + flags); + /* Print every 64 malloc fails */ + if (!(gwlan_logging.malloc_fail_count % 64)) + pr_err("%s: dev_alloc_skb() failed for msg size[%d]", + __func__, MAX_PKTSTATS_LOG_LENGTH); + return ret; + } wake_up_thread = true; - wlan_queue_pkt_stats_for_app(); } ptr = gwlan_logging.pkt_stats_pcur_node->skb; - vos_mem_copy(skb_put(ptr, total_log_len), &rx_tx_stats, total_log_len); spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags); + + /* + * If ret is non-zero and not ENOMEM, we have re-allocated from + * filled list, free the older skb and print every 64th drop count + */ + if (ret) { + if (skb_to_free) + dev_kfree_skb(skb_to_free); + + /* print every 64th drop count */ + if (vos_is_multicast_logging() && + (!(gwlan_logging.pkt_stat_drop_cnt % 0x40))) { + pr_err("%s: drop_count = %u\n", + __func__, gwlan_logging.pkt_stat_drop_cnt); + } + } + /* Wakeup logger thread */ if ((true == wake_up_thread)) { /* If there is logger app registered wakeup the logging @@ -554,11 +597,37 @@ int wlan_pkt_stats_to_user(void *perPktStat) void wlan_disable_and_flush_pkt_stats() { unsigned long flags; + int ret = 0; + struct sk_buff *skb_to_free = NULL; + + spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags); if(gwlan_logging.pkt_stats_pcur_node->skb->len){ - wlan_queue_pkt_stats_for_app(); + ret = wlan_queue_pkt_stats_for_app(skb_to_free); } spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags); + + /* + * If ret is non-zero and not ENOMEM, we have re-allocated from + * filled list, free the older skb and print every 64th drop count + */ + if (ret == -ENOMEM) { + /* Print every 64 malloc fails */ + if (!(gwlan_logging.malloc_fail_count % 64)) + pr_err("%s: dev_alloc_skb() failed for msg size[%d]", + __func__, MAX_PKTSTATS_LOG_LENGTH); + } else if (ret) { + if (skb_to_free) + dev_kfree_skb(skb_to_free); + + /* print every 64th drop count */ + if (vos_is_multicast_logging() && + (!(gwlan_logging.pkt_stat_drop_cnt % 0x40))) { + pr_err("%s: drop_count = %u\n", + __func__, gwlan_logging.pkt_stat_drop_cnt); + } + } + set_bit(HOST_PKT_STATS_POST, &gwlan_logging.event_flag); wake_up_interruptible(&gwlan_logging.wait_queue); } From ed0d3d062cf9cc4b8798ea53994758dff8da0749 Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Fri, 23 Feb 2018 16:10:46 +0530 Subject: [PATCH 136/508] wlan: Activate max channel timer at scan start In current logic, only min channel timer is activated on scan start which is deactivated on receiving probe resp or beacon. On receiving probe resp or beacon, max channel timer is activated. This will result in dwell time to be 20msecs due to not receiving beacons or between 40-60msecs depending on when beacons or probe response is received. Fix is to activate both max and min channel timer at scan start so that dwell time will be between 20-40msecs. Change-Id: I6f90bb80ebafe8de989a56a6cfe43c93b733c1cc CRs-Fixed: 2195789 --- CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c | 17 ++++++++++++++++- CORE/MAC/src/pe/lim/limScanResultUtils.c | 12 +----------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c b/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c index 6af70367d0821..bc6cb0a848ea1 100644 --- a/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c +++ b/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -524,6 +524,16 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) // Initialize max timer too limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); + if (tx_timer_activate(&pMac->lim.limTimers.gLimMaxChannelTimer) != + TX_SUCCESS) + { + limLog(pMac, LOGE, FL("could not start max channel timer")); + limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); + limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); + limSendHalEndScanReq(pMac, channelNum, + eLIM_HAL_END_SCAN_WAIT_STATE); + return; + } #if defined WLAN_FEATURE_VOWIFI } else @@ -4040,6 +4050,11 @@ limProcessMinChannelTimeout(tpAniSirGlobal pMac) pMac->lim.limTimers.gLimPeriodicProbeReqTimer.sessionId = 0xff; limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); limDeactivateAndChangeTimer(pMac, eLIM_PERIODIC_PROBE_REQ_TIMER); + /* + * Deactivate Max Channel timer as well since no probe resp/beacons + * are received. + */ + limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); pMac->lim.probeCounter = 0; if (pMac->lim.gLimCurrentScanChannelId <= (tANI_U32)(pMac->lim.gpLimMlmScanReq->channelList.numChannels - 1)) diff --git a/CORE/MAC/src/pe/lim/limScanResultUtils.c b/CORE/MAC/src/pe/lim/limScanResultUtils.c index 9937f38478914..90b5ae020bb49 100644 --- a/CORE/MAC/src/pe/lim/limScanResultUtils.c +++ b/CORE/MAC/src/pe/lim/limScanResultUtils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014, 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2014, 2016-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -80,18 +80,8 @@ limDeactivateMinChannelTimerDuringScan(tpAniSirGlobal pMac) * Beacon/Probe Response is received during active scanning. * Deactivate MIN channel timer if running. */ - limDeactivateAndChangeTimer(pMac,eLIM_MIN_CHANNEL_TIMER); - if (tx_timer_activate(&pMac->lim.limTimers.gLimMaxChannelTimer) - == TX_TIMER_ERROR) - { - /// Could not activate max channel timer. - // Log error - limLog(pMac,LOGP, FL("could not activate max channel timer")); - limCompleteMlmScan(pMac, eSIR_SME_RESOURCES_UNAVAILABLE); - return TX_TIMER_ERROR; - } } return eSIR_SUCCESS; } /*** end limDeactivateMinChannelTimerDuringScan() ***/ From 7bc4e17d2875684636940af5ff1c7a9522f5500b Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Thu, 1 Mar 2018 15:18:33 +0530 Subject: [PATCH 137/508] wlan: Set max size of beacon and probe resp template to 384 Max size for probe response template used by driver is 2048 but firmware max allowed length for template is 384 which will result in memory corruption when probe resp template sent by host exceeds 384. Fix is to set max size for both beacon and probe resp template to 384. Change-Id: Iaa8c80fc7cf738c09a17f1d29a1ef70223da27d4 CRs-Fixed: 2198940 --- CORE/MAC/src/pe/include/schGlobal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CORE/MAC/src/pe/include/schGlobal.h b/CORE/MAC/src/pe/include/schGlobal.h index ba823bb6ee7dd..e7a83778060ab 100644 --- a/CORE/MAC/src/pe/include/schGlobal.h +++ b/CORE/MAC/src/pe/include/schGlobal.h @@ -77,9 +77,9 @@ //****************** MISC defs ********************************* /// Maximum allowable size of a beacon frame -#define SCH_MAX_BEACON_SIZE 512 +#define SCH_MAX_BEACON_SIZE 384 -#define SCH_MAX_PROBE_RESP_SIZE 2048 +#define SCH_MAX_PROBE_RESP_SIZE 384 struct schMisc { From 80cc0d3c680ef59dc2df849bf0ec765f46f84573 Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Tue, 3 Oct 2017 17:32:18 +0300 Subject: [PATCH 138/508] msm: ipa3: Explicitly enable IPA DMA for IPA MHI Enable IPA DMA explicitly from IPA MHI as IPA MHI uses IPA DMA block. Change-Id: I3daebf7c0b353612502523799d3b396cdde1f1d0 Signed-off-by: Ghanim Fodi --- .../msm/ipa/ipa_clients/ipa_mhi_client.c | 27 +- drivers/platform/msm/ipa/ipa_v3/ipa.c | 36 ++- drivers/platform/msm/ipa/ipa_v3/ipa_dma.c | 233 +++++++++++++++--- drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 2 + drivers/platform/msm/ipa/test/ipa_test_dma.c | 104 +++++++- drivers/platform/msm/ipa/test/ipa_test_mhi.c | 28 +-- 6 files changed, 342 insertions(+), 88 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c index 2e92a0e2b358a..de944ec0fd096 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c @@ -182,6 +182,12 @@ static int ipa_mhi_read_write_host(enum ipa_mhi_dma_dir dir, void *dev_addr, return -ENOMEM; } + res = ipa_dma_enable(); + if (res) { + IPA_MHI_ERR("failed to enable IPA DMA rc=%d\n", res); + goto fail_dma_enable; + } + if (dir == IPA_MHI_DMA_FROM_HOST) { res = ipa_dma_sync_memcpy(mem.phys_base, host_addr, size); @@ -203,8 +209,7 @@ static int ipa_mhi_read_write_host(enum ipa_mhi_dma_dir dir, void *dev_addr, goto fail_memcopy; } } - dma_free_coherent(pdev, mem.size, mem.base, - mem.phys_base); + goto dma_succeed; } else { void *host_ptr; @@ -227,9 +232,14 @@ static int ipa_mhi_read_write_host(enum ipa_mhi_dma_dir dir, void *dev_addr, IPA_MHI_FUNC_EXIT(); return 0; +dma_succeed: + IPA_MHI_FUNC_EXIT(); + res = 0; fail_memcopy: - dma_free_coherent(ipa_get_dma_dev(), mem.size, mem.base, - mem.phys_base); + if (ipa_dma_disable()) + IPA_MHI_ERR("failed to disable IPA DMA\n"); +fail_dma_enable: + dma_free_coherent(pdev, mem.size, mem.base, mem.phys_base); return res; } @@ -2408,6 +2418,7 @@ void ipa_mhi_destroy(void) goto fail; } + ipa_dma_destroy(); ipa_mhi_debugfs_destroy(); destroy_workqueue(ipa_mhi_client_ctx->wq); kfree(ipa_mhi_client_ctx); @@ -2500,6 +2511,12 @@ int ipa_mhi_init(struct ipa_mhi_init_params *params) goto fail_create_wq; } + res = ipa_dma_init(); + if (res) { + IPA_MHI_ERR("failed to init ipa dma %d\n", res); + goto fail_dma_init; + } + /* Create PROD in IPA RM */ memset(&mhi_prod_params, 0, sizeof(mhi_prod_params)); mhi_prod_params.name = IPA_RM_RESOURCE_MHI_PROD; @@ -2557,6 +2574,8 @@ int ipa_mhi_init(struct ipa_mhi_init_params *params) fail_perf_rm_prod: ipa_rm_delete_resource(IPA_RM_RESOURCE_MHI_PROD); fail_create_rm_prod: + ipa_dma_destroy(); +fail_dma_init: destroy_workqueue(ipa_mhi_client_ctx->wq); fail_create_wq: kfree(ipa_mhi_client_ctx); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index feab287f57242..d7bb93b5644a0 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -5255,7 +5255,7 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, if (result) { IPAERR("Failed to alloc pkt_init payload\n"); result = -ENODEV; - goto fail_create_apps_resource; + goto fail_allok_pkt_init; } if (ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5) @@ -5266,6 +5266,13 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, init_completion(&ipa3_ctx->init_completion_obj); init_completion(&ipa3_ctx->uc_loaded_completion_obj); + result = ipa3_dma_setup(); + if (result) { + IPAERR("Failed to setup IPA DMA\n"); + result = -ENODEV; + goto fail_ipa_dma_setup; + } + /* * For GSI, we can't register the GSI driver yet, as it expects * the GSI FW to be up and running before the registration. @@ -5280,7 +5287,7 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, if (result) { IPAERR("gsi pre FW loading config failed\n"); result = -ENODEV; - goto fail_ipa_init_interrupts; + goto fail_gsi_pre_fw_load_init; } } } else { @@ -5291,7 +5298,7 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, result = ipa3_post_init(resource_p, ipa_dev); if (result) { IPAERR("ipa3_post_init failed\n"); - goto fail_ipa_post_init; + goto fail_gsi_pre_fw_load_init; } } @@ -5311,13 +5318,13 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, return 0; + + fail_cdev_add: -fail_ipa_post_init: - if (ipa3_bus_scale_table) { - msm_bus_cl_clear_pdata(ipa3_bus_scale_table); - ipa3_bus_scale_table = NULL; - } -fail_ipa_init_interrupts: +fail_gsi_pre_fw_load_init: + ipa3_dma_shutdown(); +fail_ipa_dma_setup: +fail_allok_pkt_init: ipa_rm_delete_resource(IPA_RM_RESOURCE_APPS_CONS); fail_create_apps_resource: ipa_rm_exit(); @@ -5362,18 +5369,21 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, fail_create_transport_wq: destroy_workqueue(ipa3_ctx->power_mgmt_wq); fail_init_hw: + ipahal_destroy(); +fail_ipahal: iounmap(ipa3_ctx->mmio); fail_remap: ipa3_disable_clks(); -fail_init_active_client: ipa3_active_clients_log_destroy(); +fail_init_active_client: fail_clk: if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_VIRTUAL) msm_bus_scale_unregister_client(ipa3_ctx->ipa_bus_hdl); -fail_ipahal: - ipa3_bus_scale_table = NULL; fail_bus_reg: - ipahal_destroy(); + if (ipa3_bus_scale_table) { + msm_bus_cl_clear_pdata(ipa3_bus_scale_table); + ipa3_bus_scale_table = NULL; + } fail_bind: kfree(ipa3_ctx->ctrl); fail_mem_ctrl: diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c index 51c11d6e6b76d..feeb7361fd278 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c @@ -81,7 +81,7 @@ static void ipa3_dma_debugfs_destroy(void) {} /** * struct ipa3_dma_ctx -IPADMA driver context information - * @is_enabled:is ipa_dma enabled? + * @enable_ref_cnt: ipa dma enable reference count * @destroy_pending: destroy ipa_dma after handling all pending memcpy * @ipa_dma_xfer_wrapper_cache: cache of ipa3_dma_xfer_wrapper structs * @sync_lock: lock for synchronisation in sync_memcpy @@ -100,7 +100,7 @@ static void ipa3_dma_debugfs_destroy(void) {} * @total_uc_memcpy: total number of uc memcpy (statistics) */ struct ipa3_dma_ctx { - bool is_enabled; + unsigned enable_ref_cnt; bool destroy_pending; struct kmem_cache *ipa_dma_xfer_wrapper_cache; struct mutex sync_lock; @@ -125,6 +125,70 @@ struct ipa3_dma_ctx { }; static struct ipa3_dma_ctx *ipa3_dma_ctx; +/** + * struct ipa3_dma_init_refcnt_ctrl -IPADMA driver init control information + * @ref_cnt: reference count for initialization operations + * @lock: lock for the reference count + */ +struct ipa3_dma_init_refcnt_ctrl { + unsigned ref_cnt; + struct mutex lock; +}; +static struct ipa3_dma_init_refcnt_ctrl *ipa3_dma_init_refcnt_ctrl; + +/** + * ipa3_dma_setup() - One time setup for IPA DMA + * + * This function should be called once to setup ipa dma + * by creating the init reference count controller + * + * Return codes: 0: success + * Negative value: failure + */ +int ipa3_dma_setup(void) +{ + IPADMA_FUNC_ENTRY(); + + if (ipa3_dma_init_refcnt_ctrl) { + IPADMA_ERR("Setup already done\n"); + return -EFAULT; + } + + ipa3_dma_init_refcnt_ctrl = + kzalloc(sizeof(*(ipa3_dma_init_refcnt_ctrl)), GFP_KERNEL); + + if (!ipa3_dma_init_refcnt_ctrl) { + IPADMA_ERR("kzalloc error.\n"); + return -ENOMEM; + } + + mutex_init(&ipa3_dma_init_refcnt_ctrl->lock); + + IPADMA_FUNC_EXIT(); + return 0; +} + +/** + * ipa3_dma_shutdown() - Clear setup operations. + * + * Cleanup for the setup function. + * Should be called during IPA driver unloading. + * It assumes all ipa_dma operations are done and ipa_dma is destroyed. + * + * Return codes: None. + */ +void ipa3_dma_shutdown(void) +{ + IPADMA_FUNC_ENTRY(); + + if (!ipa3_dma_init_refcnt_ctrl) + return; + + kfree(ipa3_dma_init_refcnt_ctrl); + ipa3_dma_init_refcnt_ctrl = NULL; + + IPADMA_FUNC_EXIT(); +} /** * ipa3_dma_init() -Initialize IPADMA. @@ -133,8 +197,10 @@ static struct ipa3_dma_ctx *ipa3_dma_ctx; * MEMCPY_DMA_SYNC_PROD ->MEMCPY_DMA_SYNC_CONS * MEMCPY_DMA_ASYNC_PROD->MEMCPY_DMA_SYNC_CONS * + * Can be executed several times (re-entrant) + * * Return codes: 0: success - * -EFAULT: IPADMA is already initialized + * -EFAULT: Mismatch between context existence and init ref_cnt * -EINVAL: IPA driver is not initialized * -ENOMEM: allocating memory error * -EPERM: pipe connection failed @@ -149,21 +215,43 @@ int ipa3_dma_init(void) IPADMA_FUNC_ENTRY(); + if (!ipa3_dma_init_refcnt_ctrl) { + IPADMA_ERR("Setup isn't done yet!\n"); + return -EINVAL; + } + + mutex_lock(&ipa3_dma_init_refcnt_ctrl->lock); + if (ipa3_dma_init_refcnt_ctrl->ref_cnt > 0) { + IPADMA_DBG("Already initialized refcnt=%d\n", + ipa3_dma_init_refcnt_ctrl->ref_cnt); + if (!ipa3_dma_ctx) { + IPADMA_ERR("Context missing. refcnt=%d\n", + ipa3_dma_init_refcnt_ctrl->ref_cnt); + res = -EFAULT; + } else { + ipa3_dma_init_refcnt_ctrl->ref_cnt++; + } + goto init_unlock; + } + if (ipa3_dma_ctx) { - IPADMA_ERR("Already initialized.\n"); - return -EFAULT; + IPADMA_ERR("Context already exist\n"); + res = -EFAULT; + goto init_unlock; } if (!ipa3_is_ready()) { IPADMA_ERR("IPA is not ready yet\n"); - return -EINVAL; + res = -EINVAL; + goto init_unlock; } ipa_dma_ctx_t = kzalloc(sizeof(*(ipa3_dma_ctx)), GFP_KERNEL); if (!ipa_dma_ctx_t) { IPADMA_ERR("kzalloc error.\n"); - return -ENOMEM; + res = -ENOMEM; + goto init_unlock; } ipa_dma_ctx_t->ipa_dma_xfer_wrapper_cache = @@ -180,7 +268,7 @@ int ipa3_dma_init(void) mutex_init(&ipa_dma_ctx_t->sync_lock); spin_lock_init(&ipa_dma_ctx_t->pending_lock); init_completion(&ipa_dma_ctx_t->done); - ipa_dma_ctx_t->is_enabled = false; + ipa_dma_ctx_t->enable_ref_cnt = 0; ipa_dma_ctx_t->destroy_pending = false; atomic_set(&ipa_dma_ctx_t->async_memcpy_pending_cnt, 0); atomic_set(&ipa_dma_ctx_t->sync_memcpy_pending_cnt, 0); @@ -294,10 +382,12 @@ int ipa3_dma_init(void) } ipa3_dma_debugfs_init(); ipa3_dma_ctx = ipa_dma_ctx_t; + ipa3_dma_init_refcnt_ctrl->ref_cnt = 1; IPADMA_DBG("ASYNC MEMCPY pipes are connected\n"); IPADMA_FUNC_EXIT(); - return res; + goto init_unlock; + fail_async_cons: ipa3_teardown_sys_pipe(ipa_dma_ctx_t->ipa_dma_async_prod_hdl); fail_async_prod: @@ -313,6 +403,8 @@ int ipa3_dma_init(void) fail_mem_ctrl: kfree(ipa_dma_ctx_t); ipa3_dma_ctx = NULL; +init_unlock: + mutex_unlock(&ipa3_dma_init_refcnt_ctrl->lock); return res; } @@ -320,26 +412,29 @@ int ipa3_dma_init(void) /** * ipa3_dma_enable() -Vote for IPA clocks. * + * Can be executed several times (re-entrant) + * *Return codes: 0: success * -EINVAL: IPADMA is not initialized - * -EPERM: Operation not permitted as ipa_dma is already - * enabled */ int ipa3_dma_enable(void) { IPADMA_FUNC_ENTRY(); - if (ipa3_dma_ctx == NULL) { + if ((ipa3_dma_ctx == NULL) || + (ipa3_dma_init_refcnt_ctrl->ref_cnt < 1)) { IPADMA_ERR("IPADMA isn't initialized, can't enable\n"); - return -EPERM; + return -EINVAL; } mutex_lock(&ipa3_dma_ctx->enable_lock); - if (ipa3_dma_ctx->is_enabled) { - IPADMA_ERR("Already enabled.\n"); + if (ipa3_dma_ctx->enable_ref_cnt > 0) { + IPADMA_ERR("Already enabled refcnt=%d\n", + ipa3_dma_ctx->enable_ref_cnt); + ipa3_dma_ctx->enable_ref_cnt++; mutex_unlock(&ipa3_dma_ctx->enable_lock); - return -EPERM; + return 0; } IPA_ACTIVE_CLIENTS_INC_SPECIAL("DMA"); - ipa3_dma_ctx->is_enabled = true; + ipa3_dma_ctx->enable_ref_cnt = 1; mutex_unlock(&ipa3_dma_ctx->enable_lock); IPADMA_FUNC_EXIT(); @@ -379,32 +474,45 @@ static bool ipa3_dma_work_pending(void) int ipa3_dma_disable(void) { unsigned long flags; + int res = 0; + bool dec_clks = false; IPADMA_FUNC_ENTRY(); - if (ipa3_dma_ctx == NULL) { + if ((ipa3_dma_ctx == NULL) || + (ipa3_dma_init_refcnt_ctrl->ref_cnt < 1)) { IPADMA_ERR("IPADMA isn't initialized, can't disable\n"); - return -EPERM; + return -EINVAL; } mutex_lock(&ipa3_dma_ctx->enable_lock); spin_lock_irqsave(&ipa3_dma_ctx->pending_lock, flags); - if (!ipa3_dma_ctx->is_enabled) { - IPADMA_ERR("Already disabled.\n"); - spin_unlock_irqrestore(&ipa3_dma_ctx->pending_lock, flags); - mutex_unlock(&ipa3_dma_ctx->enable_lock); - return -EPERM; + if (ipa3_dma_ctx->enable_ref_cnt > 1) { + IPADMA_DBG("Multiple enablement done. refcnt=%d\n", + ipa3_dma_ctx->enable_ref_cnt); + ipa3_dma_ctx->enable_ref_cnt--; + goto completed; + } + + if (ipa3_dma_ctx->enable_ref_cnt == 0) { + IPADMA_ERR("Already disabled\n"); + res = -EPERM; + goto completed; } + if (ipa3_dma_work_pending()) { IPADMA_ERR("There is pending work, can't disable.\n"); - spin_unlock_irqrestore(&ipa3_dma_ctx->pending_lock, flags); - mutex_unlock(&ipa3_dma_ctx->enable_lock); - return -EFAULT; + res = -EFAULT; + goto completed; } - ipa3_dma_ctx->is_enabled = false; + ipa3_dma_ctx->enable_ref_cnt = 0; + dec_clks = true; + IPADMA_FUNC_EXIT(); + +completed: spin_unlock_irqrestore(&ipa3_dma_ctx->pending_lock, flags); - IPA_ACTIVE_CLIENTS_DEC_SPECIAL("DMA"); + if (dec_clks) + IPA_ACTIVE_CLIENTS_DEC_SPECIAL("DMA"); mutex_unlock(&ipa3_dma_ctx->enable_lock); - IPADMA_FUNC_EXIT(); - return 0; + return res; } /** @@ -460,7 +568,7 @@ int ipa3_dma_sync_memcpy(u64 dest, u64 src, int len) } } spin_lock_irqsave(&ipa3_dma_ctx->pending_lock, flags); - if (!ipa3_dma_ctx->is_enabled) { + if (!ipa3_dma_ctx->enable_ref_cnt) { IPADMA_ERR("can't memcpy, IPADMA isn't enabled\n"); spin_unlock_irqrestore(&ipa3_dma_ctx->pending_lock, flags); return -EPERM; @@ -751,7 +859,7 @@ int ipa3_dma_async_memcpy(u64 dest, u64 src, int len, return -EINVAL; } spin_lock_irqsave(&ipa3_dma_ctx->pending_lock, flags); - if (!ipa3_dma_ctx->is_enabled) { + if (!ipa3_dma_ctx->enable_ref_cnt) { IPADMA_ERR("can't memcpy, IPA_DMA isn't enabled\n"); spin_unlock_irqrestore(&ipa3_dma_ctx->pending_lock, flags); return -EPERM; @@ -956,7 +1064,7 @@ int ipa3_dma_uc_memcpy(phys_addr_t dest, phys_addr_t src, int len) } spin_lock_irqsave(&ipa3_dma_ctx->pending_lock, flags); - if (!ipa3_dma_ctx->is_enabled) { + if (!ipa3_dma_ctx->enable_ref_cnt) { IPADMA_ERR("can't memcpy, IPADMA isn't enabled\n"); spin_unlock_irqrestore(&ipa3_dma_ctx->pending_lock, flags); return -EPERM; @@ -990,17 +1098,36 @@ void ipa3_dma_destroy(void) int res = 0; IPADMA_FUNC_ENTRY(); - if (!ipa3_dma_ctx) { - IPADMA_ERR("IPADMA isn't initialized\n"); + + if (!ipa3_dma_init_refcnt_ctrl) { + IPADMA_ERR("Setup isn't done\n"); return; } + mutex_lock(&ipa3_dma_init_refcnt_ctrl->lock); + if (ipa3_dma_init_refcnt_ctrl->ref_cnt > 1) { + IPADMA_DBG("Multiple initialization done. refcnt=%d\n", + ipa3_dma_init_refcnt_ctrl->ref_cnt); + ipa3_dma_init_refcnt_ctrl->ref_cnt--; + goto completed; + } + + if ((!ipa3_dma_ctx) || (ipa3_dma_init_refcnt_ctrl->ref_cnt == 0)) { + IPADMA_ERR("IPADMA isn't initialized ctx=%pK\n", ipa3_dma_ctx); + goto completed; + } + if (ipa3_dma_work_pending()) { ipa3_dma_ctx->destroy_pending = true; IPADMA_DBG("There are pending memcpy, wait for completion\n"); wait_for_completion(&ipa3_dma_ctx->done); } + if (ipa3_dma_ctx->enable_ref_cnt > 0) { + IPADMA_ERR("IPADMA still enabled\n"); + goto completed; + } + res = ipa3_teardown_sys_pipe(ipa3_dma_ctx->ipa_dma_async_cons_hdl); if (res) IPADMA_ERR("teardown IPADMA ASYNC CONS failed\n"); @@ -1026,7 +1153,11 @@ void ipa3_dma_destroy(void) kfree(ipa3_dma_ctx); ipa3_dma_ctx = NULL; + ipa3_dma_init_refcnt_ctrl->ref_cnt = 0; IPADMA_FUNC_EXIT(); + +completed: + mutex_unlock(&ipa3_dma_init_refcnt_ctrl->lock); } /** @@ -1089,15 +1220,31 @@ static ssize_t ipa3_dma_debugfs_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { int nbytes = 0; + + if (!ipa3_dma_init_refcnt_ctrl) { + nbytes += scnprintf(&dbg_buff[nbytes], + IPADMA_MAX_MSG_LEN - nbytes, + "Setup was not done\n"); + goto completed; + + } + if (!ipa3_dma_ctx) { nbytes += scnprintf(&dbg_buff[nbytes], IPADMA_MAX_MSG_LEN - nbytes, - "Not initialized\n"); + "Status:\n Not initialized (ref_cnt=%d)\n", + ipa3_dma_init_refcnt_ctrl->ref_cnt); } else { nbytes += scnprintf(&dbg_buff[nbytes], IPADMA_MAX_MSG_LEN - nbytes, - "Status:\n IPADMA is %s\n", - (ipa3_dma_ctx->is_enabled) ? "Enabled" : "Disabled"); + "Status:\n Initialized (ref_cnt=%d)\n", + ipa3_dma_init_refcnt_ctrl->ref_cnt); + nbytes += scnprintf(&dbg_buff[nbytes], + IPADMA_MAX_MSG_LEN - nbytes, + " %s (ref_cnt=%d)\n", + (ipa3_dma_ctx->enable_ref_cnt > 0) ? + "Enabled" : "Disabled", + ipa3_dma_ctx->enable_ref_cnt); nbytes += scnprintf(&dbg_buff[nbytes], IPADMA_MAX_MSG_LEN - nbytes, "Statistics:\n total sync memcpy: %d\n ", @@ -1106,19 +1253,25 @@ static ssize_t ipa3_dma_debugfs_read(struct file *file, char __user *ubuf, IPADMA_MAX_MSG_LEN - nbytes, "total async memcpy: %d\n ", atomic_read(&ipa3_dma_ctx->total_async_memcpy)); + nbytes += scnprintf(&dbg_buff[nbytes], + IPADMA_MAX_MSG_LEN - nbytes, + "total uc memcpy: %d\n ", + atomic_read(&ipa3_dma_ctx->total_uc_memcpy)); nbytes += scnprintf(&dbg_buff[nbytes], IPADMA_MAX_MSG_LEN - nbytes, "pending sync memcpy jobs: %d\n ", atomic_read(&ipa3_dma_ctx->sync_memcpy_pending_cnt)); nbytes += scnprintf(&dbg_buff[nbytes], IPADMA_MAX_MSG_LEN - nbytes, - "pending async memcpy jobs: %d\n", + "pending async memcpy jobs: %d\n ", atomic_read(&ipa3_dma_ctx->async_memcpy_pending_cnt)); nbytes += scnprintf(&dbg_buff[nbytes], IPADMA_MAX_MSG_LEN - nbytes, "pending uc memcpy jobs: %d\n", atomic_read(&ipa3_dma_ctx->uc_memcpy_pending_cnt)); } + +completed: return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes); } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index a9935aeb7dbc4..7425442fe2b9d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -2016,6 +2016,8 @@ void ipa3_uc_register_handlers(enum ipa3_hw_features feature, struct ipa3_uc_hdlrs *hdlrs); int ipa3_create_nat_device(void); int ipa3_uc_notify_clk_state(bool enabled); +int ipa3_dma_setup(void); +void ipa3_dma_shutdown(void); void ipa3_dma_async_memcpy_notify_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data); diff --git a/drivers/platform/msm/ipa/test/ipa_test_dma.c b/drivers/platform/msm/ipa/test/ipa_test_dma.c index a7762c2a2c94f..3e06b86265bab 100644 --- a/drivers/platform/msm/ipa/test/ipa_test_dma.c +++ b/drivers/platform/msm/ipa/test/ipa_test_dma.c @@ -364,11 +364,11 @@ static int ipa_test_dma_sync_async_memcpy(int size) } /** - * TEST: test control API - enable/disable dma + * TEST: test enable/disable dma * 1. enable dma * 2. disable dma */ -static int ipa_test_dma_control_api(void *priv) +static int ipa_test_dma_enable_disable(void *priv) { int rc; @@ -391,6 +391,92 @@ static int ipa_test_dma_control_api(void *priv) return 0; } +/** + * TEST: test init/enable/disable/destroy dma + * 1. init dma + * 2. enable dma + * 3. disable dma + * 4. destroy dma + */ +static int ipa_test_dma_init_enbl_disable_destroy(void *priv) +{ + int rc; + + IPA_UT_LOG("Test Start\n"); + + rc = ipa_dma_init(); + if (rc) { + IPA_UT_LOG("DMA Init failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail init dma"); + return rc; + } + + rc = ipa_dma_enable(); + if (rc) { + ipa_dma_destroy(); + IPA_UT_LOG("DMA enable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail enable dma"); + return rc; + } + + rc = ipa_dma_disable(); + if (rc) { + IPA_UT_LOG("DMA disable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail disable dma"); + return rc; + } + + ipa_dma_destroy(); + + return 0; +} + +/** + * TEST: test enablex2/disablex2 dma + * 1. enable dma + * 2. enable dma + * 3. disable dma + * 4. disable dma + */ +static int ipa_test_dma_enblx2_disablex2(void *priv) +{ + int rc; + + IPA_UT_LOG("Test Start\n"); + + rc = ipa_dma_enable(); + if (rc) { + ipa_dma_destroy(); + IPA_UT_LOG("DMA enable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail enable dma"); + return rc; + } + + rc = ipa_dma_enable(); + if (rc) { + ipa_dma_destroy(); + IPA_UT_LOG("DMA enable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail enable dma"); + return rc; + } + + rc = ipa_dma_disable(); + if (rc) { + IPA_UT_LOG("DMA disable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail disable dma"); + return rc; + } + + rc = ipa_dma_disable(); + if (rc) { + IPA_UT_LOG("DMA disable failed rc=%d\n", rc); + IPA_UT_TEST_FAIL_REPORT("fail disable dma"); + return rc; + } + + return 0; +} + /** * TEST: memcpy before dma enable * @@ -999,9 +1085,17 @@ static int ipa_test_dma_sync_memcpy_max_pkt_size(void *priv) IPA_UT_DEFINE_SUITE_START(dma, "DMA for GSI", ipa_test_dma_setup, ipa_test_dma_teardown) { - IPA_UT_ADD_TEST(control_api, - "Control API", - ipa_test_dma_control_api, + IPA_UT_ADD_TEST(init_enable_disable_destroy, + "Init->Enable->Disable->Destroy", + ipa_test_dma_enable_disable, + true, IPA_HW_v3_0, IPA_HW_MAX), + IPA_UT_ADD_TEST(initx2_enable_disable_destroyx2, + "Initx2->Enable->Disable->Destroyx2", + ipa_test_dma_init_enbl_disable_destroy, + true, IPA_HW_v3_0, IPA_HW_MAX), + IPA_UT_ADD_TEST(init_enablex2_disablex2_destroy, + "Init->Enablex2->Disablex2->Destroy", + ipa_test_dma_enblx2_disablex2, true, IPA_HW_v3_0, IPA_HW_MAX), IPA_UT_ADD_TEST(memcpy_before_enable, "Call memcpy before dma enable and expect it to fail", diff --git a/drivers/platform/msm/ipa/test/ipa_test_mhi.c b/drivers/platform/msm/ipa/test/ipa_test_mhi.c index 462d5bbe1f40e..43c8b3a818c38 100644 --- a/drivers/platform/msm/ipa/test/ipa_test_mhi.c +++ b/drivers/platform/msm/ipa/test/ipa_test_mhi.c @@ -868,7 +868,7 @@ static int ipa_test_mhi_suite_teardown(void *priv) * * To be run during tests * 1. MHI init (Ready state) - * 2. Conditional MHO start and connect (M0 state) + * 2. Conditional MHI start and connect (M0 state) */ static int ipa_mhi_test_initialize_driver(bool skip_start_and_conn) { @@ -879,7 +879,6 @@ static int ipa_mhi_test_initialize_driver(bool skip_start_and_conn) struct ipa_mhi_connect_params cons_params; struct ipa_mhi_mmio_register_set *p_mmio; struct ipa_mhi_channel_context_array *p_ch_ctx_array; - bool is_dma; u64 phys_addr; IPA_UT_LOG("Entry\n"); @@ -912,29 +911,6 @@ static int ipa_mhi_test_initialize_driver(bool skip_start_and_conn) return -ETIME; } - if (ipa_mhi_is_using_dma(&is_dma)) { - IPA_UT_LOG("is_dma checkign failed. Is MHI loaded?\n"); - IPA_UT_TEST_FAIL_REPORT("failed checking using dma"); - return -EPERM; - } - - if (is_dma) { - IPA_UT_LOG("init ipa_dma\n"); - rc = ipa_dma_init(); - if (rc && rc != -EFAULT) { - IPA_UT_LOG("ipa_dma_init failed, %d\n", rc); - IPA_UT_TEST_FAIL_REPORT("failed init dma"); - return rc; - } - IPA_UT_LOG("enable ipa_dma\n"); - rc = ipa_dma_enable(); - if (rc && rc != -EPERM) { - IPA_UT_LOG("ipa_dma_enable failed, %d\n", rc); - IPA_UT_TEST_FAIL_REPORT("failed enable dma"); - return rc; - } - } - if (!skip_start_and_conn) { memset(&start_params, 0, sizeof(start_params)); start_params.channel_context_array_addr = p_mmio->ccabap; @@ -1545,7 +1521,7 @@ static int ipa_mhi_test_suspend(bool force, bool should_success) } if (!should_success && rc != -EAGAIN) { - IPA_UT_LOG("ipa_mhi_suspenddid not return -EAGAIN fail %d\n", + IPA_UT_LOG("ipa_mhi_suspend did not return -EAGAIN fail %d\n", rc); IPA_UT_TEST_FAIL_REPORT("suspend succeeded unexpectedly"); return -EFAULT; From 20467ef02cae4a1f83eb7b1c206d2e433ee83290 Mon Sep 17 00:00:00 2001 From: Kaushal Kumar Date: Tue, 6 Mar 2018 15:59:40 +0530 Subject: [PATCH 139/508] ARM: dts: msm: Disable build of msm8996-v2 CDP boards Disable build of msm8996-v2 and apq8096-v2 CDP board variants since they are no longer in active use. This is being done to free up some static space from DT blob. Change-Id: I997759c34891a7289088c852f3b7c18973961741 Signed-off-by: Kaushal Kumar --- arch/arm/boot/dts/qcom/Makefile | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index 9f502ef4a0cef..3ad60c5e033b7 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -1,10 +1,6 @@ -dtb-$(CONFIG_ARCH_MSM8996) += msm8996-v2-pmi8994-cdp.dtb \ - msm8996-v2-pmi8994-mtp.dtb \ - msm8996-v2-pmi8994-pmk8001-cdp.dtb \ +dtb-$(CONFIG_ARCH_MSM8996) += msm8996-v2-pmi8994-mtp.dtb \ msm8996-v2-pmi8994-pmk8001-mtp.dtb \ - msm8996-v2-pmi8994-pm8004-cdp.dtb \ msm8996-v2-pmi8994-pm8004-mtp.dtb \ - msm8996-v2-pmi8994-pm8004-pmk8001-cdp.dtb \ msm8996-v2-pmi8994-pm8004-pmk8001-mtp.dtb \ msm8996-v2-fluid.dtb \ msm8996-v2-liquid.dtb \ @@ -85,11 +81,7 @@ dtb-$(CONFIG_ARCH_MSM8996) += msm8996-v2-pmi8994-cdp.dtb \ msm8996-v3.0-fluid.dtb \ msm8996-v3.0-liquid.dtb \ msm8996-v3.0-dtp.dtb \ - apq8096-v2-pmi8994-cdp.dtb \ apq8096-v2-pmi8994-mtp.dtb \ - apq8096-v2-pmi8994-pmk8001-cdp.dtb \ - apq8096-v2-pmi8994-pm8004-cdp.dtb \ - apq8096-v2-pmi8994-pm8004-pmk8001-cdp.dtb \ apq8096-v2-liquid.dtb \ apq8096-v2-dragonboard.dtb \ apq8096-v2-auto-dragonboard.dtb \ From 522076d129a5ac61102b05face074df61afc451c Mon Sep 17 00:00:00 2001 From: Amey Bhat Date: Wed, 7 Mar 2018 14:25:09 +0530 Subject: [PATCH 140/508] soc: qcom: socinfo: Added support for MDM9150 Updated required MSM and CPU ID to support MDM9150 target. Change-Id: Ifa9c75ac18820555d7bcfad2abc18e90aa594e55 Signed-off-by: Amey Bhat --- drivers/soc/qcom/socinfo.c | 5 ++++- include/soc/qcom/socinfo.h | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index f1441ff9f76d1..a2ecbb330b3af 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2009-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -597,6 +597,9 @@ static struct msm_soc_info cpu_of_id[] = { /* MSM8940 IDs */ [313] = {MSM_CPU_8940, "MSM8940"}, + /* MDM9150 IDs */ + [359] = {MSM_CPU_9150, "MDM9150"}, + /* Uninitialized IDs are not known to run Linux. MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are considered as unknown CPU. */ diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h index 749523d006264..60719263e5e17 100644 --- a/include/soc/qcom/socinfo.h +++ b/include/soc/qcom/socinfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2009-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -215,6 +215,7 @@ enum msm_cpu { MSM_CPU_9650, MSM_CPU_COBALT, SDX_CPU_20, + MSM_CPU_9150, }; struct msm_soc_info { From eef0e45d561c01e93f15d6f4ebf173384288f617 Mon Sep 17 00:00:00 2001 From: Amey Bhat Date: Wed, 7 Mar 2018 13:06:37 +0530 Subject: [PATCH 141/508] ARM: dts: msm: Add support for MDM9150 Updated required MSM and CPU ID to support MDM9150 target. Change-Id: Ia8a787fe9f2ca9f7c840ef583f292f1a95c48d36 Signed-off-by: Amey Bhat --- arch/arm/boot/dts/qcom/mdm9650-v1.1.dtsi | 2 +- arch/arm/boot/dts/qcom/mdm9650.dtsi | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/qcom/mdm9650-v1.1.dtsi b/arch/arm/boot/dts/qcom/mdm9650-v1.1.dtsi index a22960e722d41..3e6b9e09afb52 100644 --- a/arch/arm/boot/dts/qcom/mdm9650-v1.1.dtsi +++ b/arch/arm/boot/dts/qcom/mdm9650-v1.1.dtsi @@ -16,5 +16,5 @@ model = "Qualcomm Technologies, Inc. MDM 9650 v1.1"; compatible = "qcom,mdm9650"; qcom,msm-id = <279 0x10001>, <284 0x10001>, <285 0x10001>, - <286 0x10001>, <283 0x10001>; + <286 0x10001>, <283 0x10001>, <359 0x10001>; }; diff --git a/arch/arm/boot/dts/qcom/mdm9650.dtsi b/arch/arm/boot/dts/qcom/mdm9650.dtsi index bac9292eebf93..2d46a23ce20e3 100644 --- a/arch/arm/boot/dts/qcom/mdm9650.dtsi +++ b/arch/arm/boot/dts/qcom/mdm9650.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -19,7 +19,7 @@ model = "Qualcomm Technologies, Inc. MDM 9650"; compatible = "qcom,mdm9650"; qcom,msm-id = <279 0x10000>, <284 0x10000>, <285 0x10000>, - <286 0x10000>, <283 0x10000>; + <286 0x10000>, <283 0x10000>, <359 0x10000>; interrupt-parent = <&intc>; reserved-memory { From 5d076c44fa2c35bb8b4a1522162b7285719bb012 Mon Sep 17 00:00:00 2001 From: Gustavo Solaira Date: Tue, 6 Mar 2018 10:21:49 -0800 Subject: [PATCH 142/508] Revert "ARM: dts: msm: Disable K61 SPI-CAN on mdm9650 CV2X" This reverts commit a58fcc2e1cd9b49c5f8e77299473da0d9e384b7e. Reverted because support for K61 SPI-CAN is being added back on the platform. Change-Id: I420c9248774d30db1331d82ca4c9fa1b0a62feb5 Signed-off-by: Gustavo Solaira --- arch/arm/boot/dts/qcom/mdm9650-cv2x.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/qcom/mdm9650-cv2x.dtsi b/arch/arm/boot/dts/qcom/mdm9650-cv2x.dtsi index c3ac4c86222c3..50901501edffe 100644 --- a/arch/arm/boot/dts/qcom/mdm9650-cv2x.dtsi +++ b/arch/arm/boot/dts/qcom/mdm9650-cv2x.dtsi @@ -102,7 +102,6 @@ pinctrl-names = "active", "sleep"; pinctrl-0 = <&can_rst_on>; pinctrl-1 = <&can_rst_off>; - status = "disabled"; }; }; From f0d0ba15bea76578ce9c8cfc27c4700ada1f7f7d Mon Sep 17 00:00:00 2001 From: Anurag Chouhan Date: Fri, 9 Feb 2018 15:13:43 +0530 Subject: [PATCH 143/508] wlan: Add vendor event to get the driver hang reason Add Vendor Event to get the driver hang reason indicating to the user space that the driver has detected an internal failure. This event carries the information indicating the reason that triggered this detection. CRs-Fixed: 2184455 Change-Id: Icb8900d96431bd249fea213a4043897e7f7b0195 --- CORE/DXE/src/wlan_qct_dxe.c | 19 ++--- CORE/HDD/inc/wlan_hdd_cfg80211.h | 67 +++++++++++++++++ CORE/HDD/src/wlan_hdd_cfg80211.c | 101 +++++++++++++++++++++++++- CORE/HDD/src/wlan_hdd_early_suspend.c | 20 +++++ CORE/SME/src/sme_common/sme_Api.c | 4 +- CORE/TL/src/wlan_qct_tl.c | 2 +- CORE/VOSS/inc/vos_api.h | 38 +++++++++- CORE/VOSS/src/vos_api.c | 50 +++++++++++-- CORE/VOSS/src/vos_sched.h | 2 + CORE/WDA/src/wlan_qct_wda.c | 4 +- CORE/WDI/CP/src/wlan_qct_wdi.c | 8 +- CORE/WDI/WPAL/inc/wlan_qct_pal_api.h | 6 +- CORE/WDI/WPAL/src/wlan_qct_pal_api.c | 8 +- 13 files changed, 296 insertions(+), 33 deletions(-) diff --git a/CORE/DXE/src/wlan_qct_dxe.c b/CORE/DXE/src/wlan_qct_dxe.c index 6d87f2a91a152..8514bb5eadced 100644 --- a/CORE/DXE/src/wlan_qct_dxe.c +++ b/CORE/DXE/src/wlan_qct_dxe.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -64,6 +64,7 @@ when who what, where, why #include "wlan_qct_dxe.h" #include "wlan_qct_dxe_i.h" #include "wlan_qct_pal_device.h" +#include "vos_api.h" /*---------------------------------------------------------------------------- * Local Definitions @@ -1714,7 +1715,7 @@ void dxeRXResourceAvailableTimerExpHandler if (NULL != dxeCtxt) dxeCtxt->driverReloadInProcessing = eWLAN_PAL_TRUE; - wpalWlanReload(); + wpalWlanReload(VOS_DXE_FAILURE); if (NULL != usrData) dxeStartSSRTimer((WLANDXE_CtrlBlkType *)usrData); @@ -2414,7 +2415,7 @@ static wpt_status dxeRXFrameReady HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "RX successive empty interrupt, Could not find invalidated DESC reload driver"); dxeCtxt->driverReloadInProcessing = eWLAN_PAL_TRUE; - wpalWlanReload(); + wpalWlanReload(VOS_DXE_FAILURE); dxeStartSSRTimer(dxeCtxt); } } @@ -2743,7 +2744,7 @@ void dxeRXEventHandler if (eWLAN_PAL_STATUS_SUCCESS != dxeErrHandler(channelCb, chHighStat)) { dxeCtxt->driverReloadInProcessing = eWLAN_PAL_TRUE; - wpalWlanReload(); + wpalWlanReload(VOS_DXE_FAILURE); dxeStartSSRTimer(dxeCtxt); } } @@ -2798,7 +2799,7 @@ void dxeRXEventHandler dxeErrHandler(channelCb, chLowStat)) { dxeCtxt->driverReloadInProcessing = eWLAN_PAL_TRUE; - wpalWlanReload(); + wpalWlanReload(VOS_DXE_FAILURE); dxeStartSSRTimer(dxeCtxt); } } @@ -2850,7 +2851,7 @@ void dxeRXEventHandler dxeErrHandler(channelCb, chLogRxStat)) { dxeCtxt->driverReloadInProcessing = eWLAN_PAL_TRUE; - wpalWlanReload(); + wpalWlanReload(VOS_DXE_FAILURE); dxeStartSSRTimer(dxeCtxt); } @@ -2904,7 +2905,7 @@ void dxeRXEventHandler dxeErrHandler(channelCb, chLogRxFwStat)) { dxeCtxt->driverReloadInProcessing = eWLAN_PAL_TRUE; - wpalWlanReload(); + wpalWlanReload(VOS_DXE_FAILURE); dxeStartSSRTimer(dxeCtxt); } @@ -4102,7 +4103,7 @@ void dxeTXEventHandler dxeErrHandler(channelCb, chStat)) { dxeCtxt->driverReloadInProcessing = eWLAN_PAL_TRUE; - wpalWlanReload(); + wpalWlanReload(VOS_DXE_FAILURE); dxeStartSSRTimer(dxeCtxt); } bEnableISR = 1; @@ -4159,7 +4160,7 @@ void dxeTXEventHandler dxeErrHandler(channelCb, chStat)) { dxeCtxt->driverReloadInProcessing = eWLAN_PAL_TRUE; - wpalWlanReload(); + wpalWlanReload(VOS_DXE_FAILURE); dxeStartSSRTimer(dxeCtxt); } bEnableISR = 1; diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h index 0d0f71b7b020c..2e3f2a8fc8335 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -220,6 +220,62 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET = 149, /* Get the NUD stats, represented by the enum qca_attr_nud_stats_get */ QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET = 150, + /* + * Event indicating to the user space that the driver has detected an + * internal failure. This event carries the information indicating the + * reason that triggered this detection. The attributes for this + * command are defined in enum qca_wlan_vendor_attr_hang. + */ + QCA_NL80211_VENDOR_SUBCMD_HANG = 157, +}; + +enum qca_wlan_vendor_hang_reason { + /* Unspecified reason */ + QCA_WLAN_HANG_REASON_UNSPECIFIED = 0, + /* No Map for the MAC entry for the received frame */ + QCA_WLAN_HANG_RX_HASH_NO_ENTRY_FOUND = 1, + /* peer deletion timeout happened */ + QCA_WLAN_HANG_PEER_DELETION_TIMEDOUT = 2, + /* peer unmap timeout */ + QCA_WLAN_HANG_PEER_UNMAP_TIMEDOUT = 3, + /* Scan request timed out */ + QCA_WLAN_HANG_SCAN_REQ_EXPIRED = 4, + /* Consecutive Scan attempt failures */ + QCA_WLAN_HANG_SCAN_ATTEMPT_FAILURES = 5, + /* Unable to get the message buffer */ + QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE = 6, + /* Current command processing is timedout */ + QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT = 7, + /* Timeout for an ACK from FW for suspend request */ + QCA_WLAN_HANG_SUSPEND_TIMEOUT = 8, + /* Timeout for an ACK from FW for resume request */ + QCA_WLAN_HANG_RESUME_TIMEOUT = 9, + /* Transmission timeout for consecutive data frames */ + QCA_WLAN_HANG_TRANSMISSIONS_TIMEOUT = 10, + /* Timeout for the TX completion status of data frame */ + QCA_WLAN_HANG_TX_COMPLETE_TIMEOUT = 11, + /* DXE failure for tx/Rx, DXE resource unavailability */ + QCA_WLAN_HANG_DXE_FAILURE = 12, + /* WMI pending commands exceed the maximum count */ + QCA_WLAN_HANG_WMI_EXCEED_MAX_PENDING_CMDS = 13, + /* WDI failure for commands, WDI resource unavailability */ + QCA_WLAN_HANG_WDI_FAILURE = 14, +}; + +/** + * enum qca_wlan_vendor_attr_hang - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_HANG. + */ +enum qca_wlan_vendor_attr_hang { + QCA_WLAN_VENDOR_ATTR_HANG_INVALID = 0, + /* + * Reason for the Hang - Represented by enum + * qca_wlan_vendor_hang_reason. + */ + QCA_WLAN_VENDOR_ATTR_HANG_REASON = 1, + QCA_WLAN_VENDOR_ATTR_HANG_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_HANG_MAX = + QCA_WLAN_VENDOR_ATTR_HANG_AFTER_LAST - 1, }; /** @@ -418,6 +474,7 @@ enum qca_nl80211_vendor_subcmds_index { QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX, QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX, QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX, + QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX, }; /** @@ -1665,6 +1722,16 @@ backported_cfg80211_vendor_event_alloc(struct wiphy *wiphy, #define cfg80211_vendor_event_alloc backported_cfg80211_vendor_event_alloc #endif +/** + * wlan_hdd_send_hang_reason_event() - Send hang reason to the userspace + * @hdd_ctx: Pointer to hdd context + * @reason: cds recovery reason + * + * Return: 0 on success or failure reason + */ +int wlan_hdd_send_hang_reason_event(hdd_context_t *hdd_ctx, + unsigned int reason); + /** * enum qca_wlan_vendor_attr_memory_dump - values for memory dump attributes * @QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_INVALID - Invalid diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 529766147d58e..55df656770c68 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -651,6 +651,101 @@ int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx, } #endif /* FEATURE_WLAN_CH_AVOID */ +/* + * define short names for the global vendor params + * used by QCA_NL80211_VENDOR_SUBCMD_HANG + */ +#define HANG_REASON_INDEX QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX + +/** + * hdd_convert_hang_reason() - Convert cds recovery reason to vendor specific + * hang reason + * @reason: cds recovery reason + * + * Return: Vendor specific reason code + */ +static enum qca_wlan_vendor_hang_reason +hdd_convert_hang_reason(enum vos_hang_reason reason) +{ + unsigned int ret_val; + + switch (reason) { + case VOS_GET_MSG_BUFF_FAILURE: + ret_val = QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE; + break; + case VOS_ACTIVE_LIST_TIMEOUT: + ret_val = QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT; + break; + case VOS_SCAN_REQ_EXPIRED: + ret_val = QCA_WLAN_HANG_SCAN_REQ_EXPIRED; + break; + case VOS_TRANSMISSIONS_TIMEOUT: + ret_val = QCA_WLAN_HANG_TRANSMISSIONS_TIMEOUT; + break; + case VOS_DXE_FAILURE: + ret_val = QCA_WLAN_HANG_DXE_FAILURE; + break; + case VOS_WDI_FAILURE: + ret_val = QCA_WLAN_HANG_WDI_FAILURE; + break; + case VOS_REASON_UNSPECIFIED: + default: + ret_val = QCA_WLAN_HANG_REASON_UNSPECIFIED; + } + return ret_val; +} + +/** + * wlan_hdd_send_hang_reason_event() - Send hang reason to the userspace + * @hdd_ctx: Pointer to hdd context + * @reason: cds recovery reason + * + * Return: 0 on success or failure reason + */ +int wlan_hdd_send_hang_reason_event(hdd_context_t *hdd_ctx, + enum vos_hang_reason reason) +{ + struct sk_buff *vendor_event; + enum qca_wlan_vendor_hang_reason hang_reason; + + ENTER(); + + if (!hdd_ctx) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "HDD context is null"); + return -EINVAL; + } + + vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) + NULL, +#endif + sizeof(unsigned int), + HANG_REASON_INDEX, + GFP_KERNEL); + if (!vendor_event) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "cfg80211_vendor_event_alloc failed"); + return -ENOMEM; + } + + hang_reason = hdd_convert_hang_reason(reason); + + if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON, + (unsigned int) hang_reason)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "QCA_WLAN_VENDOR_ATTR_HANG_REASON put fail"); + kfree_skb(vendor_event); + return -EINVAL; + } + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + + EXIT(); + return 0; +} +#undef HANG_REASON_INDEX + /* * FUNCTION: __wlan_hdd_cfg80211_nan_request * This is called when wlan driver needs to send vendor specific @@ -8763,6 +8858,10 @@ struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = .vendor_id = QCA_NL80211_VENDOR_ID, .subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET, }, + [QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_HANG, + }, }; /* @@ -14825,7 +14924,7 @@ int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy, else { hddLog(LOGE, FL("Triggering SSR")); - vos_wlanRestart(); + vos_wlanRestart(VOS_SCAN_REQ_EXPIRED); } } } diff --git a/CORE/HDD/src/wlan_hdd_early_suspend.c b/CORE/HDD/src/wlan_hdd_early_suspend.c index 375adab62bf7a..f54e4148e9432 100644 --- a/CORE/HDD/src/wlan_hdd_early_suspend.c +++ b/CORE/HDD/src/wlan_hdd_early_suspend.c @@ -2221,6 +2221,25 @@ static inline void hdd_wlan_ssr_shutdown_event(void) }; #endif +/** + * hdd_send_hang_reason() - Send hang reason to the userspace + * + * Return: None + */ +static void hdd_send_hang_reason(hdd_context_t *hdd_ctx) +{ + unsigned int reason = 0; + + if(!hdd_ctx) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__); + return; + } + + vos_get_recovery_reason(&reason); + vos_reset_recovery_reason(); + wlan_hdd_send_hang_reason_event(hdd_ctx, reason); +} + /* the HDD interface to WLAN driver shutdown, * the primary shutdown function in SSR */ @@ -2407,6 +2426,7 @@ VOS_STATUS hdd_wlan_shutdown(void) __func__); } hdd_wlan_ssr_shutdown_event(); + hdd_send_hang_reason(pHddCtx); hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete" ,__func__); return VOS_STATUS_SUCCESS; diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c index fd5f1db43ae95..272a76f1fe3ba 100644 --- a/CORE/SME/src/sme_common/sme_Api.c +++ b/CORE/SME/src/sme_common/sme_Api.c @@ -483,7 +483,7 @@ tSmeCmd *smeGetCommandBuffer( tpAniSirGlobal pMac ) else { /* Trigger SSR */ - vos_wlanRestart(); + vos_wlanRestart(VOS_GET_MSG_BUFF_FAILURE); } } @@ -12801,7 +12801,7 @@ void activeListCmdTimeoutHandle(void *userData) if (!(vos_isLoadUnloadInProgress() || vos_is_logp_in_progress(VOS_MODULE_ID_SME, NULL))) { - vos_wlanRestart(); + vos_wlanRestart(VOS_ACTIVE_LIST_TIMEOUT); } } } diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c index 91f1ba63ca485..6846f66efb1c3 100644 --- a/CORE/TL/src/wlan_qct_tl.c +++ b/CORE/TL/src/wlan_qct_tl.c @@ -7822,7 +7822,7 @@ WLANTL_FatalErrorHandler * Issue SSR. vos_wlanRestart has tight checks to make sure that * we do not send an FIQ if previous FIQ is not processed */ - vos_wlanRestart(); + vos_wlanRestart(VOS_REASON_UNSPECIFIED); } /*========================================================================== diff --git a/CORE/VOSS/inc/vos_api.h b/CORE/VOSS/inc/vos_api.h index d6c17c5caf10e..b1287b5552446 100644 --- a/CORE/VOSS/inc/vos_api.h +++ b/CORE/VOSS/inc/vos_api.h @@ -220,6 +220,26 @@ typedef enum VOS_WDI_WRITE, } vos_wdi_trace_event_type; +/** + * enum vos_hang_reason - host hang/ssr reason + * @VOS_REASON_UNSPECIFIED: Unspecified reason + * @VOS_GET_MSG_BUFF_FAILURE: Unable to get the message buffer + * @VOS_ACTIVE_LIST_TIMEOUT: Current command processing is timedout + * @VOS_SCAN_REQ_EXPIRED: Scan request timed out + * @VOS_TRANSMISSIONS_TIMEOUT: transmission timed out + * @VOS_DXE_FAILURE: dxe failure + * @VOS_WDI_FAILURE: wdi failure + */ +enum vos_hang_reason { + VOS_REASON_UNSPECIFIED = 0, + VOS_GET_MSG_BUFF_FAILURE = 1, + VOS_ACTIVE_LIST_TIMEOUT = 2, + VOS_SCAN_REQ_EXPIRED = 3, + VOS_TRANSMISSIONS_TIMEOUT = 4, + VOS_DXE_FAILURE = 5, + VOS_WDI_FAILURE = 6, +}; + /*------------------------------------------------------------------------- Function declarations and documenation ------------------------------------------------------------------------*/ @@ -459,13 +479,13 @@ VOS_STATUS vos_wlanReInit(void); Note that this API will not initiate any RIVA subsystem restart. @param - NONE + reason: vos_hang_reason @return VOS_STATUS_SUCCESS - Operation completed successfully. VOS_STATUS_E_FAILURE - Operation failed. */ -VOS_STATUS vos_wlanRestart(void); +VOS_STATUS vos_wlanRestart(enum vos_hang_reason reason); /** @brief vos_fwDumpReq() @@ -558,4 +578,18 @@ static inline uint64_t __vos_get_log_timestamp(void) } #endif /* LINUX_VERSION_CODE */ +/** + * vos_get_recovery_reason() - get self recovery reason + * @reason: recovery reason + * + * Return: None + */ +void vos_get_recovery_reason(enum vos_hang_reason *reason); + +/** + * vos_reset_recovery_reason() - reset the reason to unspecified + * + * Return: None + */ +void vos_reset_recovery_reason(void); #endif // if !defined __VOS_NVITEM_H diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c index fc10b55035f00..6dd7f8cd7f889 100644 --- a/CORE/VOSS/src/vos_api.c +++ b/CORE/VOSS/src/vos_api.c @@ -1775,7 +1775,7 @@ void vos_send_fatal_event_done(void) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "Do SSR for reason_code=%d", reason_code); - vos_wlanRestart(); + vos_wlanRestart(VOS_GET_MSG_BUFF_FAILURE); } } @@ -2864,7 +2864,7 @@ VOS_STATUS vos_wlanReInit(void) The function wlan_hdd_restart_driver protects against re-entrant calls. @param - NONE + reason: recovery reason @return VOS_STATUS_SUCCESS - Operation completed successfully. VOS_STATUS_E_FAILURE - Operation failed. @@ -2873,11 +2873,11 @@ VOS_STATUS vos_wlanReInit(void) */ -VOS_STATUS vos_wlanRestart(void) +VOS_STATUS vos_wlanRestart(enum vos_hang_reason reason) { VOS_STATUS vstatus; hdd_context_t *pHddCtx = NULL; - v_CONTEXT_t pVosContext = NULL; + VosContextType *pVosContext = NULL; /* Check whether driver load unload is in progress */ if(vos_is_load_unload_in_progress( VOS_MODULE_ID_VOSS, NULL)) @@ -2894,7 +2894,8 @@ VOS_STATUS vos_wlanRestart(void) "%s: Global VOS context is Null", __func__); return VOS_STATUS_E_FAILURE; } - + pVosContext->recovery_reason = reason; + /* Get the HDD context */ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); if(!pHddCtx) { @@ -2908,6 +2909,45 @@ VOS_STATUS vos_wlanRestart(void) return vstatus; } +/** + * vos_get_recovery_reason() - get self recovery reason + * @reason: recovery reason + * + * Return: None + */ +void vos_get_recovery_reason(enum vos_hang_reason *reason) +{ + VosContextType *pVosContext = NULL; + + pVosContext = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL); + if(!pVosContext) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Global VOS context is Null", __func__); + return; + } + + *reason = pVosContext->recovery_reason; +} + +/** + * vos_reset_recovery_reason() - reset the reason to unspecified + * + * Return: None + */ +void vos_reset_recovery_reason(void) +{ + VosContextType *pVosContext = NULL; + + pVosContext = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL); + if(!pVosContext) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Global VOS context is Null", __func__); + return; + } + + pVosContext->recovery_reason = VOS_REASON_UNSPECIFIED; +} + /** @brief vos_fwDumpReq() diff --git a/CORE/VOSS/src/vos_sched.h b/CORE/VOSS/src/vos_sched.h index 0e5d612a5a981..3a92a65498c3d 100644 --- a/CORE/VOSS/src/vos_sched.h +++ b/CORE/VOSS/src/vos_sched.h @@ -83,6 +83,7 @@ #endif #include +#include #define TX_POST_EVENT 0x000 @@ -375,6 +376,7 @@ typedef struct _VosContextType spinlock_t wdthread_work_lock; bool snoc_high_freq_voting; spinlock_t freq_voting_lock; + enum vos_hang_reason recovery_reason; } VosContextType, *pVosContextType; diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c index f27cefd4f610f..6c3c9932979c5 100644 --- a/CORE/WDA/src/wlan_qct_wda.c +++ b/CORE/WDA/src/wlan_qct_wda.c @@ -9869,7 +9869,7 @@ void WDA_ExitImpsReqCallback(WDI_Status status, void* pUserData) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, FL("reload wlan driver")); - wpalWlanReload(); + wpalWlanReload(VOS_WDI_FAILURE); } } return; @@ -15038,7 +15038,7 @@ VOS_STATUS WDA_TxPacket(tWDA_CbContext *pWDA, { VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, "%s: Request system recovery", __func__); - vos_wlanRestart(); + vos_wlanRestart(VOS_TRANSMISSIONS_TIMEOUT); } status = VOS_STATUS_E_FAILURE; } diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c index 6e5069f4d970f..4b4ebd0a98a4e 100644 --- a/CORE/WDI/CP/src/wlan_qct_wdi.c +++ b/CORE/WDI/CP/src/wlan_qct_wdi.c @@ -16943,7 +16943,7 @@ WDI_ProcessStartRsp wdiStartRspCb( &wdiRspParams, pWDICtx->pRspCBUserData); WDI_DetectedDeviceError(pWDICtx, wdiRspParams.wdiStatus); - wpalWlanReload(); + wpalWlanReload(VOS_WDI_FAILURE); /*Although the response is an error - it was processed by our function so as far as the caller is concerned this is a succesful reponse processing*/ @@ -17079,7 +17079,7 @@ WDI_ProcessStopRsp halMacStopRspMsg.stopRspParams.status); WDI_DetectedDeviceError( pWDICtx, WDI_ERR_BASIC_OP_FAILURE); - wpalWlanReload(); + wpalWlanReload(VOS_WDI_FAILURE); wpalMutexRelease(&pWDICtx->wptMutex); return WDI_STATUS_E_FAILURE; @@ -23073,7 +23073,7 @@ WDI_RXMsgCTSCB WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "Invalid packet received from HAL - catastrophic failure"); WDI_DetectedDeviceError( pWDICtx, WDI_ERR_INVALID_RSP_FMT); - wpalWlanReload(); + wpalWlanReload(VOS_WDI_FAILURE); return; } @@ -23600,7 +23600,7 @@ WDI_ResponseTimerCB } #else WDI_DetectedDeviceError(pWDICtx, WDI_ERR_BASIC_OP_FAILURE); - wpalWlanReload(); + wpalWlanReload(VOS_WDI_FAILURE); #endif } else diff --git a/CORE/WDI/WPAL/inc/wlan_qct_pal_api.h b/CORE/WDI/WPAL/inc/wlan_qct_pal_api.h index aeacf6f58a024..7998a4075ca45 100644 --- a/CORE/WDI/WPAL/inc/wlan_qct_pal_api.h +++ b/CORE/WDI/WPAL/inc/wlan_qct_pal_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015,2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2015,2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -309,11 +309,11 @@ wpt_status wpalRivaSubystemRestart(void); wpalWlanReload - Initiate WLAN Driver reload Param: - None + reason: hang reason Return: NONE ---------------------------------------------------------------------------*/ -void wpalWlanReload(void); +void wpalWlanReload(wpt_uint32 reason); /*--------------------------------------------------------------------------- wpalWcnssResetIntr - Trigger the reset FIQ to Riva diff --git a/CORE/WDI/WPAL/src/wlan_qct_pal_api.c b/CORE/WDI/WPAL/src/wlan_qct_pal_api.c index a6019cbdbbf55..79c3ef31bd93c 100644 --- a/CORE/WDI/WPAL/src/wlan_qct_pal_api.c +++ b/CORE/WDI/WPAL/src/wlan_qct_pal_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012,2014-2015,2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012,2014-2015,2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -389,13 +389,13 @@ wpt_status wpalRivaSubystemRestart(void) wpalWlanReload - Initiate WLAN Driver reload Param: - None + reason: hang reason Return: NONE ---------------------------------------------------------------------------*/ -void wpalWlanReload(void) +void wpalWlanReload(enum vos_hang_reason reason) { - vos_wlanRestart(); + vos_wlanRestart(reason); return; } From 28a6abf74757f1d8d8dd177258bc306122e0f520 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Fri, 27 Jan 2017 22:28:21 +0530 Subject: [PATCH 144/508] msm: vidc: Handle perf mode configuration Host will set the Venus firmware in below modes 1. If the load of current video session exceeds the venus capability, video driver sets power save mode for that session. 2. If an usecase is recommended to run in power save mode to get power benefits, video driver configures the session in power save mode. 3. If any V4L2 client makes an explicit call to configure the usecase in a certain perf mode, video driver sets the same to venus firmware, unless restricted by core capability. CRs-Fixed: 1106972 Change-Id: Ib8be6c9af1508389edc9cb6444531c6e711b6a11 Signed-off-by: Vikash Garodia Signed-off-by: Sanjay Singh From f8a25409e68bd57a1ab447ad4814a061a5d9ac5b Mon Sep 17 00:00:00 2001 From: Sanjay Singh Date: Tue, 20 Feb 2018 11:42:04 +0530 Subject: [PATCH 145/508] ARM: dts: msm: Define power configuration for msm8996 and msm8998 Power configuration is a value measured as HxW of a video session. If the resolution of current video session meets this value, the session will be configured in low power mode to get power benefits. CRs-Fixed: 1106972 Change-Id: Ibe4eba7a76a070b1bc02caff89cfb871993043c2 Signed-off-by: Sanjay Singh --- arch/arm/boot/dts/qcom/msm8996-vidc.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/qcom/msm8996-vidc.dtsi b/arch/arm/boot/dts/qcom/msm8996-vidc.dtsi index 3ed55f9d86719..4cfe0c5adef6a 100644 --- a/arch/arm/boot/dts/qcom/msm8996-vidc.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-vidc.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2015, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,6 +32,7 @@ <0x0818C000 0x2000>, <0x0818E000 0x2000>; qcom,max-hw-load = <2563200>; /* Full 4k @ 60 + 1080p @ 60 */ + qcom,power-conf = <8294400>; /* WxH - 3840*2160 */ qcom,firmware-name = "venus"; qcom,imem-size = <524288>; /* 512 kB */ qcom,never-unload-fw; From c0d6330537cfe68d8bb34a93146fd398346fdba8 Mon Sep 17 00:00:00 2001 From: Kishor PK Date: Thu, 8 Mar 2018 15:18:50 +0530 Subject: [PATCH 146/508] Revert "remove 'reboot edl' interface for security" This reverts commit a1eb4aa3cb55a4a0fd7d379c4a215e30eb6f308a. Change-Id: I13f3e644019d48889714548a6d4396052c5b57b9 Signed-off-by: Kishor PK --- drivers/power/reset/msm-poweroff.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index 0123fbf309048..b10dc24730acf 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -152,7 +152,6 @@ static bool get_dload_mode(void) return dload_mode_enabled; } -#if 0 static void enable_emergency_dload_mode(void) { int ret; @@ -177,7 +176,6 @@ static void enable_emergency_dload_mode(void) if (ret) pr_err("Failed to set secure EDLOAD mode: %d\n", ret); } -#endif static int dload_set(const char *val, struct kernel_param *kp) { @@ -332,10 +330,8 @@ static void msm_restart_prepare(const char *cmd) if (!ret) __raw_writel(0x6f656d00 | (code & 0xff), restart_reason); -#if 0 } else if (!strncmp(cmd, "edl", 3)) { enable_emergency_dload_mode(); -#endif } else { __raw_writel(0x77665501, restart_reason); } From 76d85816f2b2d9e0dca9c863982cb9bc526817cd Mon Sep 17 00:00:00 2001 From: Shadab Naseem Date: Thu, 28 Dec 2017 16:02:51 +0530 Subject: [PATCH 147/508] socinfo: msm: Add soc id for SDA450 Add soc id for SDA450 in socinfo drive. SDA450 is APQ version of SDM450. Change-Id: Ia70e52b7ba4696e8cf705712402e75fecd445fcd Signed-off-by: Shadab Naseem --- drivers/soc/qcom/socinfo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index f1441ff9f76d1..01cfd08c5deeb 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -561,6 +561,8 @@ static struct msm_soc_info cpu_of_id[] = { /* SDM450 ID */ [338] = {MSM_CPU_SDM450, "SDM450"}, + [351] = {MSM_CPU_SDM450, "SDA450"}, + /* 9607 IDs */ [290] = {MSM_CPU_9607, "MDM9607"}, From bf015f23ec3cd9b41d06da3c376d14db33fb4d7f Mon Sep 17 00:00:00 2001 From: Shadab Naseem Date: Fri, 29 Dec 2017 15:43:25 +0530 Subject: [PATCH 148/508] ARM: dts: msm: Add DT support for SDA450 with PMI8950 Add device tree support for SDA450 with PMI8950 for mtp and cdp board. Change-Id: I486380e95720ccd3a804d7873d387354d2e3b06e Signed-off-by: Shadab Naseem --- .../devicetree/bindings/arm/msm/msm.txt | 6 + arch/arm/boot/dts/qcom/Makefile | 4 +- arch/arm/boot/dts/qcom/sda450-cdp.dts | 31 +++++ arch/arm/boot/dts/qcom/sda450-mtp.dts | 47 +++++++ arch/arm/boot/dts/qcom/sda450.dtsi | 120 ++++++++++++++++++ arch/arm/mach-msm/board-sdm450.c | 3 +- 6 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 arch/arm/boot/dts/qcom/sda450-cdp.dts create mode 100644 arch/arm/boot/dts/qcom/sda450-mtp.dts create mode 100644 arch/arm/boot/dts/qcom/sda450.dtsi diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt index 31dae6d25193d..05c4f95901210 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm.txt @@ -104,6 +104,9 @@ SoCs: - SDM450 compatible = "qcom,sdm450" +- SDA450 + compatible = "qcom,sda450" + - MSM8937 compatible = "qcom,msm8937" @@ -306,6 +309,9 @@ compatible = "qcom,msm8953-qrd-sku3" compatible = "qcom,sdm450-cdp" compatible = "qcom,sdm450-mtp" compatible = "qcom,sdm450-qrd" +compatible = "qcom,sda450-cdp" +compatible = "qcom,sda450-mtp" +compatible = "qcom,sda450-qrd" compatible = "qcom,mdm9640-cdp" compatible = "qcom,mdm9640-mtp" compatible = "qcom,mdm9640-rumi" diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index 9f502ef4a0cef..f1fe1b3ba7295 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -284,7 +284,9 @@ dtb-$(CONFIG_ARCH_SDM450) += sdm450-rcm.dtb \ sdm450-qrd.dtb \ sdm450-pmi8940-mtp.dtb \ sdm450-pmi8937-mtp.dtb \ - sdm450-iot-mtp.dtb + sdm450-iot-mtp.dtb \ + sda450-cdp.dtb \ + sda450-mtp.dtb dtb-$(CONFIG_ARCH_MDM9607) += mdm9607-rumi.dtb \ mdm9607-cdp.dtb \ diff --git a/arch/arm/boot/dts/qcom/sda450-cdp.dts b/arch/arm/boot/dts/qcom/sda450-cdp.dts new file mode 100644 index 0000000000000..bda8ae02d9d00 --- /dev/null +++ b/arch/arm/boot/dts/qcom/sda450-cdp.dts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "sda450.dtsi" +#include "msm-pmi8950.dtsi" +#include "msm8953-cdp.dtsi" +#include "msm8953-pmi8950.dtsi" +#include "msm8953-camera-sensor-cdp.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SDA450 + PMI8950 CDP"; + compatible = "qcom,sda450-cdp", "qcom,sda450", "qcom,cdp"; + qcom,board-id = <1 0>; +}; + +&pmi8950_charger { + qcom,external-typec; + qcom,typec-psy-name = "typec"; +}; diff --git a/arch/arm/boot/dts/qcom/sda450-mtp.dts b/arch/arm/boot/dts/qcom/sda450-mtp.dts new file mode 100644 index 0000000000000..8567a484ad131 --- /dev/null +++ b/arch/arm/boot/dts/qcom/sda450-mtp.dts @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "sda450.dtsi" +#include "msm-pmi8950.dtsi" +#include "msm8953-mtp.dtsi" +#include "msm8953-pmi8950.dtsi" +#include "msm8953-camera-sensor-mtp.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SDA450 + PMI8950 MTP"; + compatible = "qcom,sda450-mtp", "qcom,sda450", "qcom,mtp"; + qcom,board-id = <8 0>; + qcom,pmic-id = <0x010016 0x010011 0x0 0x0>; +}; + +/{ + mtp_batterydata: qcom,battery-data { + qcom,batt-id-range-pct = <15>; + #include "batterydata-itech-3000mah.dtsi" + #include "batterydata-ascent-3450mAh.dtsi" + }; +}; + +&pmi8950_fg { + qcom,battery-data = <&mtp_batterydata>; +}; + +&pmi8950_charger { + qcom,battery-data = <&mtp_batterydata>; + qcom,chg-led-sw-controls; + qcom,chg-led-support; + qcom,external-typec; + qcom,typec-psy-name = "typec"; +}; diff --git a/arch/arm/boot/dts/qcom/sda450.dtsi b/arch/arm/boot/dts/qcom/sda450.dtsi new file mode 100644 index 0000000000000..7089bb45f52e4 --- /dev/null +++ b/arch/arm/boot/dts/qcom/sda450.dtsi @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "skeleton64.dtsi" +#include "msm8953.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SDA450"; + compatible = "qcom,sda450"; + qcom,msm-id = <351 0x0>; + interrupt-parent = <&intc>; + + soc: soc { }; +}; + +&clock_gcc_gfx { + compatible = "qcom,gcc-gfx-sdm450"; + qcom,gfxfreq-corner = + < 0 0 >, + < 133330000 1 >, /* Min SVS */ + < 216000000 2 >, /* Low SVS */ + < 320000000 3 >, /* SVS */ + < 400000000 4 >, /* SVS Plus */ + < 510000000 5 >, /* NOM */ + < 560000000 6 >, /* Nom Plus */ + < 600000000 7 >; /* Turbo */ +}; + +/* GPU Overrides*/ +&msm_gpu { + + /delete-node/qcom,gpu-pwrlevels; + + qcom,gpu-pwrlevels { + #address-cells = <1>; + #size-cells = <0>; + + compatible = "qcom,gpu-pwrlevels"; + + /* TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <600000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <10>; + qcom,bus-max = <10>; + }; + + /* NOM+ */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <560000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <8>; + qcom,bus-max = <10>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <510000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <6>; + qcom,bus-max = <10>; + }; + + /* SVS+ */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <400000000>; + qcom,bus-freq = <7>; + qcom,bus-min = <5>; + qcom,bus-max = <8>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <320000000>; + qcom,bus-freq = <4>; + qcom,bus-min = <2>; + qcom,bus-max = <6>; + }; + + /* Low SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <216000000>; + qcom,bus-freq = <1>; + qcom,bus-min = <1>; + qcom,bus-max = <4>; + }; + + /* Min SVS */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <133300000>; + qcom,bus-freq = <1>; + qcom,bus-min = <1>; + qcom,bus-max = <4>; + }; + /* XO */ + qcom,gpu-pwrlevel@7 { + reg = <7>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + }; + }; +}; diff --git a/arch/arm/mach-msm/board-sdm450.c b/arch/arm/mach-msm/board-sdm450.c index 92bc036325781..05311de79a302 100644 --- a/arch/arm/mach-msm/board-sdm450.c +++ b/arch/arm/mach-msm/board-sdm450.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -17,6 +17,7 @@ static const char *sdm450_dt_match[] __initconst = { "qcom,sdm450", + "qcom,sda450", NULL }; From ec306c6cfef9bb3f31876d2a8a75a8060559c721 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 26 Feb 2018 17:31:49 +0530 Subject: [PATCH 149/508] wlan: Fix possible buffer overflow If channel index is greater than the max limit (MAX_BSS_IN_NEIGHBOR_RPT), then it can result in out of bound access. Also, if numChannels in scan request is greater than SIR_ESE_MAX_MEAS_IE_REQS, then it can result in out of bound access in limSendHalStartScanOffloadReq. Add a check on index variable against MAX_BSS_IN_NEIGHBOR_RPT in csrNeighborRoamCreateChanListFromNeighborReport and limit the value of pScanReq->channelList.numChannels to SIR_ESE_MAX_MEAS_IE_REQS in limSendHalStartScanOffloadReq to make sure numChannel should not exceed the max limit. Change-Id: Ic602443125cc30535018d23bd3f941307888c37e CRs-Fixed: 2195886 --- CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c | 2 ++ CORE/SME/src/csr/csrNeighborRoam.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c index 5276aa4224c6b..59934c6d0f6c9 100644 --- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c +++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c @@ -1121,6 +1121,8 @@ static eHalStatus limSendHalStartScanOffloadReq(tpAniSirGlobal pMac, tSirMsgQ msg; tANI_U16 i, len; tSirRetStatus rc = eSIR_SUCCESS; + if (pScanReq->channelList.numChannels > SIR_ESE_MAX_MEAS_IE_REQS) + pScanReq->channelList.numChannels = SIR_ESE_MAX_MEAS_IE_REQS; /* The tSirScanOffloadReq will reserve the space for first channel, so allocate the memory for (numChannels - 1) and uIEFieldLen */ diff --git a/CORE/SME/src/csr/csrNeighborRoam.c b/CORE/SME/src/csr/csrNeighborRoam.c index 86632693ce4cb..e1c5d1acbcedd 100644 --- a/CORE/SME/src/csr/csrNeighborRoam.c +++ b/CORE/SME/src/csr/csrNeighborRoam.c @@ -3392,7 +3392,7 @@ VOS_STATUS csrNeighborRoamCreateChanListFromNeighborReport(tpAniSirGlobal pMac) break; } - if (i == numChannels) + if (i == numChannels && i < MAX_BSS_IN_NEIGHBOR_RPT) { if (pNeighborBssDesc->pNeighborBssDescription->channel) { From 93032a375e3ab69ea7953e804214dfdc41b1f3bb Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 26 Feb 2018 15:06:23 +0530 Subject: [PATCH 150/508] wlan: Fix uninitialized variable access WDA_ProcessFwrMemDumpReq invokes WDI_FwrMemDumpReq to get fwr mem dump. WDI_FwrMemDumpReq returns status of type WDI_Status. The variable used to store return status of WDI_FwrMemDumpReq should be of type WDI_Status. Instead, it is of type VOS_STATUS. Fix is to assign return status of WDI_FwrMemDumpReq to a variable of type WDI_Status. Change-Id: If550e0c89b3924309249948631dc4408bab9581a CRs-Fixed: 2195799 --- CORE/WDA/src/wlan_qct_wda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c index 6c3c9932979c5..8e22428747e1f 100644 --- a/CORE/WDA/src/wlan_qct_wda.c +++ b/CORE/WDA/src/wlan_qct_wda.c @@ -15854,7 +15854,7 @@ VOS_STATUS WDA_ProcessFwrMemDumpReq(tWDA_CbContext * pWDA, /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pFwrMemDumpReq; - status = WDI_FwrMemDumpReq(pWdiFwrMemDumpReq, + wstatus = WDI_FwrMemDumpReq(pWdiFwrMemDumpReq, (WDI_FwrMemDumpCb)WDA_FwrMemDumpRespCallback, pWdaParams); From ac7ba3ca555bdca88ad6a44dc00b17416d5abdd0 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 26 Feb 2018 10:53:51 +0530 Subject: [PATCH 151/508] wlan: Fix NULL pointer de-reference In WDA_ProcessWlanSuspendInd and WDA_Process_apfind_set_cmd, driver references pointer returned by vos_mem_malloc without validation. This can result in NULL pointer access. Fix is to validate pointer variable returned by 'vos_mem_malloc' before dereferencing it. Change-Id: I909588c11a83096b3767ba039e1dddd3a3395fad CRs-Fixed: 2195663 --- CORE/WDA/src/wlan_qct_wda.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c index 8e22428747e1f..33ed775597a93 100644 --- a/CORE/WDA/src/wlan_qct_wda.c +++ b/CORE/WDA/src/wlan_qct_wda.c @@ -11634,9 +11634,11 @@ VOS_STATUS WDA_ProcessWlanSuspendInd(tWDA_CbContext *pWDA, wdiSuspendParams.wdiReqStatusCB = WDA_ProcessWlanSuspendIndCallback; pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)); - if (!pWdaParams) + if (!pWdaParams) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, - "%s memory allocation failed" ,__func__); + "%s memory allocation failed" ,__func__); + return VOS_STATUS_E_FAILURE; + } pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pWlanSuspendParam; wdiSuspendParams.pUserData = pWdaParams; @@ -15550,6 +15552,11 @@ VOS_STATUS WDA_Process_apfind_set_cmd(tWDA_CbContext *pWDA, wdi_ap_find_cmd = (struct WDI_APFind_cmd *)vos_mem_malloc( sizeof(struct hal_apfind_request) + ap_find_req->request_data_len); + if (!wdi_ap_find_cmd) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s memory allocation failed" ,__func__); + return VOS_STATUS_E_FAILURE; + } wdi_ap_find_cmd->data_len = ap_find_req->request_data_len; vos_mem_copy(wdi_ap_find_cmd->data, ap_find_req->request_data, From c43a5fc4862b26a8c123ce84f77cece6c7ffd129 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Mon, 12 Mar 2018 14:02:32 +0530 Subject: [PATCH 152/508] wlan: Initialize adapter to NULL in hdd_rx_fwd_eapol In hdd_rx_fwd_eapol(), initialize adapter to NULL to make sure uninitialized adapter is not accessed. Change-Id: Id9bb72805f26c6955f012506fcb5fa27bf2af098 CRs-Fixed: 2203863 --- CORE/HDD/src/wlan_hdd_tx_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c index fd4306da6daab..f643e30cbf740 100644 --- a/CORE/HDD/src/wlan_hdd_tx_rx.c +++ b/CORE/HDD/src/wlan_hdd_tx_rx.c @@ -3064,7 +3064,7 @@ void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx) void hdd_rx_fwd_eapol(v_VOID_t *vosContext, vos_pkt_t *pVosPacket) { hdd_context_t *pHddCtx = NULL; - hdd_adapter_t * pAdapter; + hdd_adapter_t * pAdapter = NULL; hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; struct sk_buff *skb = NULL; uint8_t proto_type; From 392e44561638ce18e47459f51008f96b3b300658 Mon Sep 17 00:00:00 2001 From: gaurank kathpalia Date: Mon, 26 Feb 2018 15:40:30 +0530 Subject: [PATCH 153/508] wlan: Fix pointer dereference KW issues in connect path Fix KW issues which may cause pointer deference in multiple paths Also check for memory allocation failures. Change-Id: I852cb8a58703602fe9a127a822c900971d4bea4d CRs-Fixed: 2197165 --- CORE/MAC/src/pe/lim/lim_mbb.c | 16 ++++++++++++---- CORE/SAP/src/sapFsm.c | 1 + CORE/SAP/src/sapModule.c | 15 +++++---------- CORE/SYS/legacy/src/utils/src/parserApi.c | 8 +++++++- CORE/VOSS/src/vos_api.c | 5 ++--- 5 files changed, 27 insertions(+), 18 deletions(-) diff --git a/CORE/MAC/src/pe/lim/lim_mbb.c b/CORE/MAC/src/pe/lim/lim_mbb.c index 9cd3501fbc196..3a96871790b13 100644 --- a/CORE/MAC/src/pe/lim/lim_mbb.c +++ b/CORE/MAC/src/pe/lim/lim_mbb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -765,6 +765,7 @@ static inline void lim_process_preauth_mbb_result(tpAniSirGlobal mac, { limLog(mac, LOGE, FL("call to AllocateMemory failed for pReassocReq")); + vos_mem_free(reassoc_req); goto end; } vos_mem_set((void *) pReassocReq, nSize, 0); @@ -775,13 +776,13 @@ static inline void lim_process_preauth_mbb_result(tpAniSirGlobal mac, { limLog(mac, LOGE, FL("received SME_REASSOC_REQ with invalid data")); + vos_mem_free(reassoc_req); goto end; } ft_session_entry = mac->ft.ftPEContext.pftSessionEntry; ft_session_entry->pLimReAssocReq = pReassocReq; - vos_mem_free(reassoc_req); add_bss_params = mac->ft.ftPEContext.pAddBssReq; @@ -789,6 +790,7 @@ static inline void lim_process_preauth_mbb_result(tpAniSirGlobal mac, if (NULL == mlm_reassoc_req) { limLog(mac, LOGE, FL("call to AllocateMemory failed for mlmReassocReq")); + vos_mem_free(reassoc_req); goto end; } @@ -800,11 +802,13 @@ static inline void lim_process_preauth_mbb_result(tpAniSirGlobal mac, if (cfgGetCapabilityInfo(mac, &caps, ft_session_entry) != eSIR_SUCCESS) { limLog(mac, LOGE, FL("could not retrieve Capabilities value")); vos_mem_free(mlm_reassoc_req); + vos_mem_free(reassoc_req); goto end; } lim_update_caps_info_for_bss(mac, &caps, reassoc_req->bssDescription.capabilityInfo); + vos_mem_free(reassoc_req); limLog(mac, LOG1, FL("Capabilities info Reassoc: 0x%X"), caps); @@ -1275,7 +1279,6 @@ void lim_process_sta_mlm_del_sta_rsp_mbb(tpAniSirGlobal mac, vos_mem_free(del_sta_params); lim_msg->bodyptr = NULL; } - /* Connected AP lim cleanup.*/ lim_cleanup_connected_ap(mac, sta_ds, session_entry); @@ -1334,6 +1337,8 @@ void lim_cleanup_rx_path_mbb(tpAniSirGlobal mac, void lim_cleanup_connected_ap(tpAniSirGlobal mac, tpDphHashNode sta_ds, tpPESession session_entry) { + if (!sta_ds || !session_entry) + return; lim_cleanup_rx_path_mbb(mac, sta_ds, session_entry); limDeleteDphHashEntry(mac, sta_ds->staAddr, sta_ds->assocId, session_entry); @@ -1437,7 +1442,6 @@ void lim_process_sta_mlm_del_bss_rsp_mbb(tpAniSirGlobal mac, vos_mem_free(delbss_params); lim_msg->bodyptr = NULL; } - lim_cleanup_connected_ap(mac, sta_ds, session_entry); ft_session_entry = peFindSessionByBssid(mac, @@ -1564,6 +1568,10 @@ void lim_process_sta_mlm_add_bss_rsp_mbb(tpAniSirGlobal mac, if(add_bss_params == 0) goto end; + if (!sta_ds) { + limLog(mac, LOGE, FL("DPH Entry for STA missing")); + goto end; + } limLog(mac, LOG1, FL("Add BSS RSP received. Status:%d"), add_bss_params->status); diff --git a/CORE/SAP/src/sapFsm.c b/CORE/SAP/src/sapFsm.c index 8871079e27c50..fde794e0f345a 100644 --- a/CORE/SAP/src/sapFsm.c +++ b/CORE/SAP/src/sapFsm.c @@ -1261,6 +1261,7 @@ sapFsm VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, NULL hHal in state %s, msg %d", __func__, "eSAP_STARTING", msg); + return eHAL_STATUS_INVALID_PARAMETER; } vosStatus = sme_roam_csa_ie_request(hHal, sapContext->bssid, sapContext->ecsa_info.new_channel, diff --git a/CORE/SAP/src/sapModule.c b/CORE/SAP/src/sapModule.c index e4a1e9a3c93af..20febb52328e9 100644 --- a/CORE/SAP/src/sapModule.c +++ b/CORE/SAP/src/sapModule.c @@ -558,25 +558,20 @@ VOS_STATUS WLANSAP_get_sessionId ) { ptSapContext pSapCtx = NULL; - VOS_STATUS status = VOS_STATUS_SUCCESS; - pSapCtx = VOS_GET_SAP_CB(pvosGCtx); if ( NULL == pSapCtx ) { VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Invalid SAP pointer from pvosGCtx", __func__); - status = VOS_STATUS_E_INVAL; + return VOS_STATUS_E_INVAL; } - if (pSapCtx->sapsMachine == eSAP_STARTED) { - *sessionId = pSapCtx->sessionId; - status = VOS_STATUS_SUCCESS; - } - else - status = VOS_STATUS_E_FAILURE; + if (pSapCtx->sapsMachine != eSAP_STARTED) + return VOS_STATUS_E_FAILURE; - return status; + *sessionId = pSapCtx->sessionId; + return VOS_STATUS_SUCCESS; } /*========================================================================== FUNCTION WLANSAP_StartBss diff --git a/CORE/SYS/legacy/src/utils/src/parserApi.c b/CORE/SYS/legacy/src/utils/src/parserApi.c index bf8458b7c8c56..99833a4c358a3 100644 --- a/CORE/SYS/legacy/src/utils/src/parserApi.c +++ b/CORE/SYS/legacy/src/utils/src/parserApi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -5607,6 +5607,12 @@ sap_auth_offload_update_rsn_ie( tpAniSirGlobal pmac, { tDot11fIERSN *pdot11f_rsn; pdot11f_rsn = vos_mem_malloc(sizeof(tDot11fIERSN)); + if (!pdot11f_rsn) { + dot11fLog(pmac, LOGE, + FL("Memory allocation failes for RSN IE")); + return; + } + vos_mem_set(pdot11f_rsn, sizeof(tDot11fIERSN), 0); /* Assign RSN IE for Software AP Authentication offload security */ if (pmac->sap_auth_offload && pmac->sap_auth_offload_sec_type) diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c index 6dd7f8cd7f889..36621232cce5f 100644 --- a/CORE/VOSS/src/vos_api.c +++ b/CORE/VOSS/src/vos_api.c @@ -3898,7 +3898,7 @@ void vos_update_arp_fw_tx_delivered(void) pAdapterNode = pNext; } if (pAdapter) - pAdapter->hdd_stats.hddArpStats.tx_host_fw_sent++; + pAdapter->hdd_stats.hddArpStats.tx_host_fw_sent++; } /** @@ -3938,9 +3938,8 @@ void vos_update_arp_rx_drop_reorder(void) status = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext); pAdapterNode = pNext; } - if (pAdapter) - pAdapter->hdd_stats.hddArpStats.rx_host_drop_reorder++; + pAdapter->hdd_stats.hddArpStats.rx_host_drop_reorder++; } v_BOOL_t vos_check_monitor_state(void) From 32d092bed41441a97799d91c135de8aa90156bdf Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Tue, 20 Feb 2018 21:43:57 +0530 Subject: [PATCH 154/508] wlan: Add support to disable channel list Add support to disable channel list received with command "SET_DISABLE_CHANNEL_LIST". As part of this command, number of channels and list of that many channels should be given. If the interface is up on any of the channel from the list first disconnect the interface and then disable all the channels from the list now start the interface on the new channel. Change-Id: I3c7810bfde78878a3e60570a13bf2741e1da599b CRs-Fixed: 2197579 --- CORE/HDD/inc/wlan_hdd_cfg80211.h | 9 + CORE/HDD/inc/wlan_hdd_main.h | 23 +++ CORE/HDD/src/wlan_hdd_cfg80211.c | 182 ++++++++++++++++++- CORE/HDD/src/wlan_hdd_hostapd.c | 26 +++ CORE/HDD/src/wlan_hdd_main.c | 256 +++++++++++++++++++++++++++ CORE/HDD/src/wlan_hdd_softap_tx_rx.c | 3 + CORE/VOSS/inc/vos_nvitem.h | 11 ++ CORE/VOSS/src/vos_nvitem.c | 33 ++++ 8 files changed, 538 insertions(+), 5 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h index 2e3f2a8fc8335..059dfe495eafd 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -1650,6 +1650,15 @@ extern void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext void* wlan_hdd_change_country_code_cb(void *pAdapter); void hdd_select_cbmode( hdd_adapter_t *pAdapter,v_U8_t operationChannel); +/* + * wlan_hdd_restore_channels() Restore the channels which were cached + * and disabled in __wlan_hdd_disable_channels api. + * @hdd_ctx: Pointer to the HDD context + * + * @Return: 0 on success, Error code on failure + */ +int wlan_hdd_restore_channels(hdd_context_t *pHddCtx); + /* * hdd_update_indoor_channel() - enable/disable indoor channel * @hdd_ctx: hdd context diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index fdb877f34f176..b6db4a17740ce 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -1558,6 +1558,17 @@ struct hdd_offloaded_packets_ctx /** Adapter stucture definition */ +struct hdd_cache_channel_info { + int channel_num; + int reg_status; + int wiphy_status; +}; + +struct hdd_cache_channels { + int num_channels; + struct hdd_cache_channel_info *channel_info; +}; + struct hdd_context_s { /** Global VOS context */ @@ -1844,6 +1855,9 @@ struct hdd_context_s v_BOOL_t roaming_ini_original; uint32_t track_arp_ip; + + struct hdd_cache_channels *orginal_channels; + struct mutex cache_channel_lock; }; typedef enum { @@ -2328,4 +2342,13 @@ hdd_wlan_nla_put_u64(struct sk_buff *skb, int attrtype, u64 value) } #endif +/* + * hdd_parse_disable_chn_cmd() - Parse the channel list received + * in command. + * @adapter: pointer to hdd adapter + * + * @return: 0 on success, Error code on failure + */ +int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr); + #endif // end #if !defined( WLAN_HDD_MAIN_H ) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 55df656770c68..1de07394b7e77 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -10625,6 +10625,165 @@ void hdd_check_and_disconnect_sta_on_invalid_channel(hdd_context_t *hdd_ctx) wlan_hdd_disconnect(sta_adapter, eCSR_DISCONNECT_REASON_DEAUTH); } +int wlan_hdd_restore_channels(hdd_context_t *hdd_ctx) +{ + struct hdd_cache_channels *cache_chann; + struct wiphy *wiphy; + int freq, status, rfChannel; + int i, band_num, channel_num; + struct ieee80211_channel *wiphy_channel; + + ENTER(); + + if (!hdd_ctx) { + hddLog(VOS_TRACE_LEVEL_FATAL, "HDD Context is NULL"); + return -EINVAL; + } + + wiphy = hdd_ctx->wiphy; + + mutex_lock(&hdd_ctx->cache_channel_lock); + + cache_chann = hdd_ctx->orginal_channels; + + if (!cache_chann || !cache_chann->num_channels) { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s channel list is NULL or num channels are zero", + __func__); + mutex_unlock(&hdd_ctx->cache_channel_lock); + return -EINVAL; + } + + for (i = 0; i < cache_chann->num_channels; i++) { + status = hdd_wlan_get_freq( + cache_chann->channel_info[i].channel_num, + &freq); + + for (band_num = 0; band_num < IEEE80211_NUM_BANDS; band_num++) { + for (channel_num = 0; channel_num < + wiphy->bands[band_num]->n_channels; + channel_num++) { + wiphy_channel = &(wiphy->bands[band_num]-> + channels[channel_num]); + if (wiphy_channel->center_freq == freq) { + rfChannel = wiphy_channel->hw_value; + /* + *Restore the orginal states + *of the channels + */ + vos_nv_set_channel_state( + rfChannel, + cache_chann-> + channel_info[i].reg_status); + wiphy_channel->flags = + cache_chann-> + channel_info[i].wiphy_status; + break; + } + } + if (channel_num < wiphy->bands[band_num]->n_channels) + break; + } + } + + mutex_unlock(&hdd_ctx->cache_channel_lock); + + status = sme_update_channel_list((tpAniSirGlobal)hdd_ctx->hHal); + if (status) + hddLog(VOS_TRACE_LEVEL_ERROR, "Can't Restore channel list"); + EXIT(); + + return 0; +} + +/* + * wlan_hdd_disable_channels() - Cache the the channels + * and current state of the channels from the channel list + * received in the command and disable the channels on the + * wiphy and NV table. + * @hdd_ctx: Pointer to hdd context + * + * @return: 0 on success, Error code on failure + */ + +static int wlan_hdd_disable_channels(hdd_context_t *hdd_ctx) +{ + struct hdd_cache_channels *cache_chann; + struct wiphy *wiphy; + int freq, status, rfChannel; + int i, band_num, band_ch_num; + struct ieee80211_channel *wiphy_channel; + + if (!hdd_ctx) { + hddLog(VOS_TRACE_LEVEL_FATAL, "HDD Context is NULL"); + return -EINVAL; + } + + wiphy = hdd_ctx->wiphy; + + mutex_lock(&hdd_ctx->cache_channel_lock); + cache_chann = hdd_ctx->orginal_channels; + + if (!cache_chann || !cache_chann->num_channels) { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s channel list is NULL or num channels are zero", + __func__); + mutex_unlock(&hdd_ctx->cache_channel_lock); + return -EINVAL; + } + + for (i = 0; i < cache_chann->num_channels; i++) { + status = hdd_wlan_get_freq( + cache_chann->channel_info[i].channel_num, + &freq); + + for (band_num = 0; band_num < IEEE80211_NUM_BANDS; + band_num++) { + for (band_ch_num = 0; band_ch_num < + wiphy->bands[band_num]->n_channels; + band_ch_num++) { + wiphy_channel = &(wiphy->bands[band_num]-> + channels[band_ch_num]); + if (wiphy_channel->center_freq == freq) { + rfChannel = wiphy_channel->hw_value; + /* + * Cache the current states of + * the channels + */ + cache_chann-> + channel_info[i].reg_status = + vos_nv_getChannelEnabledState( + rfChannel); + + cache_chann-> + channel_info[i].wiphy_status = + wiphy_channel->flags; + hddLog(VOS_TRACE_LEVEL_INFO, + "Disable channel %d reg_stat %d wiphy_stat 0x%x", + cache_chann-> + channel_info[i].channel_num, + cache_chann-> + channel_info[i].reg_status, + wiphy_channel->flags); + + vos_nv_set_channel_state( + rfChannel, + NV_CHANNEL_DISABLE); + wiphy_channel->flags |= + IEEE80211_CHAN_DISABLED; + break; + } + } + if (band_ch_num < wiphy->bands[band_num]->n_channels) + break; + } + } + + mutex_unlock(&hdd_ctx->cache_channel_lock); + sme_update_channel_list((tpAniSirGlobal)hdd_ctx->hHal); + return 0; +} + #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, struct beacon_parameters *params) @@ -10682,6 +10841,12 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, hdd_check_and_disconnect_sta_on_invalid_channel(pHddCtx); } + if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP) { + /* Disable the channels received in command SET_DISABLE_CHANNEL_LIST*/ + wlan_hdd_disable_channels(pHddCtx); + hdd_check_and_disconnect_sta_on_invalid_channel(pHddCtx); + } + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig; @@ -10738,7 +10903,8 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Channel [%d]", __func__, pConfig->channel); - return -EINVAL; + ret = -EINVAL; + goto error; } pConfig->user_config_channel = pConfig->channel; } @@ -10803,7 +10969,8 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE)) { hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***"); - return -EINVAL; + ret = -EINVAL; + goto error; } else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0) { @@ -10929,7 +11096,8 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, if (pConfig->RSNWPAReqIELength > sizeof(pConfig->RSNWPAReqIE)) { hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***"); - return -EINVAL; + ret = -EINVAL; + goto error; } pConfig->SSIDinfo.ssidHidden = VOS_FALSE; @@ -11057,7 +11225,8 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter)) { hddLog(LOGE, FL("SAP Not able to set AP IEs")); - return -EINVAL; + ret = -EINVAL; + goto error; } //Uapsd Enabled Bit @@ -11098,7 +11267,8 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, if (vos_max_concurrent_connections_reached()) { hddLog(VOS_TRACE_LEVEL_INFO, FL("Reached max concurrent connections")); - return -EINVAL; + ret = -EINVAL; + goto error; } pConfig->persona = pHostapdAdapter->device_mode; @@ -11274,6 +11444,8 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, return 0; error: + if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP) + wlan_hdd_restore_channels(pHddCtx); /* Revert the indoor to passive marking if START BSS fails */ if (iniConfig->disable_indoor_channel) { hdd_update_indoor_channel(pHddCtx, false); diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index faa0fe60053a9..87d3d6dadd70f 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -462,6 +462,32 @@ static int hdd_hostapd_driver_command(hdd_adapter_t *pAdapter, ret = hdd_enable_disable_ca_event(pHddCtx, command, 16); } + /* + * command should be a string having format + * SET_DISABLE_CHANNEL_LIST + * + */ + else if (strncmp(command, "SET_DISABLE_CHANNEL_LIST", 24) == 0) { + tANI_U8 *ptr = command; + + ret = hdd_drv_cmd_validate(command, 24); + if (ret) + goto exit; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + " Received Command to disable Channels for in %s", + __func__); + ret = hdd_parse_disable_chan_cmd(pAdapter, ptr); + } + + else { + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_UNSUPPORTED_IOCTL, + pAdapter->sessionId, 0)); + hddLog(VOS_TRACE_LEVEL_WARN, FL("Unsupported GUI command %s"), + command); + } + exit: if (command) { diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 4fbd76158e4e8..fee2bc2413ee1 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -3200,6 +3200,242 @@ static inline void hdd_assign_reassoc_handoff(tCsrHandoffRequest *handoffInfo) } #endif +/** + * wlan_hdd_free_cache_channels() - Free the cache channels list + * @hdd_ctx: Pointer to HDD context + * + * Return: None + */ + +static void wlan_hdd_free_cache_channels(hdd_context_t *hdd_ctx) +{ + mutex_lock(&hdd_ctx->cache_channel_lock); + hdd_ctx->orginal_channels->num_channels = 0; + vos_mem_free(hdd_ctx->orginal_channels->channel_info); + hdd_ctx->orginal_channels->channel_info = NULL; + vos_mem_free(hdd_ctx->orginal_channels); + hdd_ctx->orginal_channels = NULL; + mutex_unlock(&hdd_ctx->cache_channel_lock); +} + +/** + * hdd_alloc_chan_cache() - Allocate the memory to cache the channel + * info for the channels received in command SET_DISABLE_CHANNEL_LIST + * @hdd_ctx: Pointer to HDD context + * @num_chan: Number of channels for which memory needs to + * be allocated + * + * Return: 0 on success and error code on failure + */ + +int hdd_alloc_chan_cache(hdd_context_t *hdd_ctx, int num_chan) +{ + if (NULL == hdd_ctx->orginal_channels) { + hdd_ctx->orginal_channels = + vos_mem_malloc(sizeof(struct hdd_cache_channels)); + if (NULL == hdd_ctx->orginal_channels) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "In %s, VOS_MALLOC_ERR", __func__); + return -EINVAL; + } + hdd_ctx->orginal_channels->num_channels = num_chan; + hdd_ctx->orginal_channels->channel_info = + vos_mem_malloc(num_chan * + sizeof(struct hdd_cache_channel_info)); + if (NULL == hdd_ctx->orginal_channels->channel_info) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "In %s, VOS_MALLOC_ERR", __func__); + hdd_ctx->orginal_channels->num_channels = 0; + vos_mem_free(hdd_ctx->orginal_channels); + hdd_ctx->orginal_channels = NULL; + return -EINVAL; + } + } else { + /* Same command comes multiple times */ + struct hdd_cache_channel_info *temp_chan_info; + + if (hdd_ctx->orginal_channels->num_channels + num_chan > + MAX_CHANNEL) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid Number of channel received", + __func__); + return -EINVAL; + } + + temp_chan_info = vos_mem_malloc(( + hdd_ctx->orginal_channels-> + num_channels + num_chan) * + sizeof(struct hdd_cache_channel_info)); + if (NULL == temp_chan_info) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "In %s, VOS_MALLOC_ERR", + __func__); + return -EINVAL; + } + + vos_mem_copy(temp_chan_info, hdd_ctx->orginal_channels-> + channel_info, hdd_ctx->orginal_channels-> + num_channels * + sizeof(struct hdd_cache_channel_info)); + + hdd_ctx->orginal_channels->num_channels += num_chan; + vos_mem_free(hdd_ctx->orginal_channels->channel_info); + hdd_ctx->orginal_channels->channel_info = temp_chan_info; + temp_chan_info = NULL; + } + return 0; + +} + + +int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr) +{ + v_PVOID_t pvosGCtx = vos_get_global_context(VOS_MODULE_ID_HDD, NULL); + hdd_context_t *hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, pvosGCtx); + tANI_U8 *param; + int j, tempInt, index = 0, ret = 0; + + if (NULL == pvosGCtx) { + hddLog(VOS_TRACE_LEVEL_FATAL, + "VOS Global Context is NULL"); + return -EINVAL; + } + + if (NULL == hdd_ctx) { + hddLog(VOS_TRACE_LEVEL_FATAL, "HDD Context is NULL"); + return -EINVAL; + } + + param = strchr(ptr, ' '); + /*no argument after the command*/ + if (NULL == param) + return -EINVAL; + + /*no space after the command*/ + else if (SPACE_ASCII_VALUE != *param) + return -EINVAL; + + param++; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param)) + param++; + + /*no argument followed by spaces*/ + if ('\0' == *param) + return -EINVAL; + + /*getting the first argument ie the number of channels*/ + if (sscanf(param, "%d ", &tempInt) != 1) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Cannot get number of channels from input", + __func__); + return -EINVAL; + } + + if (tempInt < 0 || tempInt > MAX_CHANNEL) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid Number of channel received", __func__); + return -EINVAL; + } + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Number of channel to disable are: %d", + __func__, tempInt); + + if (!tempInt) { + if (!wlan_hdd_restore_channels(hdd_ctx)) { + /* + * Free the cache channels only when the command is + * received with num channels as 0 + */ + wlan_hdd_free_cache_channels(hdd_ctx); + } + return 0; + } + + mutex_lock(&hdd_ctx->cache_channel_lock); + if (hdd_alloc_chan_cache(hdd_ctx, tempInt)) { + ret = -ENOMEM; + goto parse_done; + } + index = hdd_ctx->orginal_channels->num_channels - tempInt; + + for (j = index; j < hdd_ctx->orginal_channels->num_channels; j++) { + /* + * param pointing to the beginning of first space + * after number of channels + */ + param = strpbrk(param, " "); + /*no channel list after the number of channels argument*/ + if (NULL == param) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s, Invalid No of channel provided in the list", + __func__); + ret = -EINVAL; + goto parse_done; + } + + param++; + + /*removing empty space*/ + while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param)) + param++; + + if ('\0' == *param) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s, No channel is provided in the list", + __func__); + ret = -EINVAL; + goto parse_done; + + } + + if (sscanf(param, "%d ", &tempInt) != 1) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Cannot read channel number", + __func__); + ret = -EINVAL; + goto parse_done; + + } + + if (!IS_CHANNEL_VALID(tempInt)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid channel number received", + __func__); + ret = -EINVAL; + goto parse_done; + + } + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: channel[%d] = %d", __func__, + j, tempInt); + hdd_ctx->orginal_channels->channel_info[j].channel_num = + tempInt; + } + + /*extra arguments check*/ + param = strchr(param, ' '); + if (NULL != param) { + while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param)) + param++; + + if ('\0' != *param) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid argument received", __func__); + ret = -EINVAL; + goto parse_done; + } + } + +parse_done: + mutex_unlock(&hdd_ctx->cache_channel_lock); + EXIT(); + + return ret; +} + static int hdd_driver_command(hdd_adapter_t *pAdapter, hdd_priv_data_t *ppriv_data) { @@ -6258,6 +6494,25 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, ret = hdd_enable_disable_ca_event(pHddCtx, command, 16); } + /* + * command should be a string having format + * SET_DISABLE_CHANNEL_LIST + * + */ + else if (strncmp(command, "SET_DISABLE_CHANNEL_LIST", 24) == 0) { + tANI_U8 *ptr = command; + ret = hdd_drv_cmd_validate(command, 24); + if (ret) + goto exit; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + " Received Command to disable Channels %s", + __func__); + ret = hdd_parse_disable_chan_cmd(pAdapter, ptr); + if (ret) + goto exit; + } + else { MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_UNSUPPORTED_IOCTL, @@ -13407,6 +13662,7 @@ int hdd_wlan_startup(struct device *dev ) hdd_assoc_registerFwdEapolCB(pVosContext); + mutex_init(&pHddCtx->cache_channel_lock); goto success; err_open_cesium_nl_sock: diff --git a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c index d7f8e92be325d..12e2b9417ca40 100644 --- a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c +++ b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c @@ -2127,6 +2127,9 @@ VOS_STATUS hdd_softap_stop_bss( hdd_adapter_t *pAdapter) } } + if (pAdapter->device_mode == WLAN_HDD_SOFTAP) + wlan_hdd_restore_channels(pHddCtx); + /* Mark the indoor channel (passive) to enable */ if (pHddCtx->cfg_ini->disable_indoor_channel) { hdd_update_indoor_channel(pHddCtx, false); diff --git a/CORE/VOSS/inc/vos_nvitem.h b/CORE/VOSS/inc/vos_nvitem.h index c180d1ce3e004..3880855fa2e93 100644 --- a/CORE/VOSS/inc/vos_nvitem.h +++ b/CORE/VOSS/inc/vos_nvitem.h @@ -736,6 +736,17 @@ eNVChannelEnabledType vos_nv_getChannelEnabledState v_U32_t rfChannel ); +/* + *vos_nv_set_Channel_state - API to set the channel state in NV table + *@rfChannel - input channel enum + *@channel_state - state of the channel to be set + * enabled + * disabled + * DFS + * Return - Void + */ +void vos_nv_set_channel_state(v_U32_t rfChannel, int channel_state); + VOS_STATUS vos_init_wiphy_from_nv_bin(void); /**------------------------------------------------------------------------ diff --git a/CORE/VOSS/src/vos_nvitem.c b/CORE/VOSS/src/vos_nvitem.c index 1b6f1b83a1ec4..cf7aef935b542 100644 --- a/CORE/VOSS/src/vos_nvitem.c +++ b/CORE/VOSS/src/vos_nvitem.c @@ -2634,6 +2634,39 @@ VOS_STATUS vos_nv_setNVEncodedBuffer(v_U8_t *pNvBuffer, v_SIZE_t size) return VOS_STATUS_SUCCESS; } +/* + *vos_nv_set_Channel_state - API to set the channel state in NV table + *@rfChannel - input channel enum + *@channel_state - state of the channel to be set + * enabled + * disabled + * DFS + * Return - Void + */ +void vos_nv_set_channel_state(v_U32_t rfChannel, int channel_state) +{ + v_U32_t channelLoop; + eRfChannels channelEnum = INVALID_RF_CHANNEL; + + for (channelLoop = 0; channelLoop <= RF_CHAN_165; channelLoop++) { + if (rfChannels[channelLoop].channelNum == rfChannel) { + channelEnum = (eRfChannels)channelLoop; + break; + } + } + + if (INVALID_RF_CHANNEL == channelEnum) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "vos_nv_set_channel_state, invalid channel %d", + rfChannel); + return; + } + + pnvEFSTable-> + halnv.tables.regDomains[temp_reg_domain].channels[channelEnum].enabled = + channel_state; +} + /**------------------------------------------------------------------------ \brief vos_nv_getChannelEnabledState - \param rfChannel - input channel enum to know evabled state From b31fa3b3b15692f4eca42949bab7f3bf8d684e3a Mon Sep 17 00:00:00 2001 From: Sravan Kumar Kairam Date: Mon, 12 Mar 2018 15:44:11 +0530 Subject: [PATCH 155/508] wlan: Add protective check before dereference Add protective check before pointer dereference. Change-Id: I93075980ad0bcc8e7069b7413ec0c2bf5bea9abb CRs-Fixed: 2203941 --- CORE/TL/src/wlan_qct_tl.c | 4 ++-- CORE/TL/src/wlan_qct_tl_ba.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c index 6846f66efb1c3..845a58d3f0a81 100644 --- a/CORE/TL/src/wlan_qct_tl.c +++ b/CORE/TL/src/wlan_qct_tl.c @@ -14483,8 +14483,8 @@ void WLANTL_RegisterFwdEapol(v_PVOID_t pvosGCtx, WLANTL_CbType* pTLCb = NULL; pTLCb = VOS_GET_TL_CB(pvosGCtx); - pTLCb->pfnEapolFwd = pfnFwdEapol; - + if (pTLCb) + pTLCb->pfnEapolFwd = pfnFwdEapol; } /** diff --git a/CORE/TL/src/wlan_qct_tl_ba.c b/CORE/TL/src/wlan_qct_tl_ba.c index 166e6d6d91bf4..f65ed038dae4d 100644 --- a/CORE/TL/src/wlan_qct_tl_ba.c +++ b/CORE/TL/src/wlan_qct_tl_ba.c @@ -132,7 +132,7 @@ v_VOID_t WLANTL_ReorderingAgingTimerExpierCB WDI_DS_RxMetaInfoType *pRxMetadata; vos_pkt_t *pCurrent; vos_pkt_t *pNext; - v_S15_t seq; + v_S15_t seq = 0; v_U32_t cIndex; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ From bcfe528385d89ffd54a176f74eb9aad27decbf66 Mon Sep 17 00:00:00 2001 From: gaurank kathpalia Date: Mon, 12 Mar 2018 13:59:14 +0530 Subject: [PATCH 156/508] wlan: Fix pointer dereference KW issues in connect path Fix KW issues which may cause pointer deference in multiple paths Also check for memory allocation failures. Change-Id: I439fdfbe4e1f66df1c5286485f612d3adb9fc475 CRs-Fixed: 2203866 --- CORE/SAP/src/sapApiLinkCntl.c | 50 ++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/CORE/SAP/src/sapApiLinkCntl.c b/CORE/SAP/src/sapApiLinkCntl.c index 146d4e3587400..a34e5cd5575a5 100644 --- a/CORE/SAP/src/sapApiLinkCntl.c +++ b/CORE/SAP/src/sapApiLinkCntl.c @@ -1474,18 +1474,22 @@ WLANSAP_RoamCallback FL( "CSR roamResult = %s (%d)"), "eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND", roamResult); + if (!pCsrRoamInfo) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("pCsrRoamInfo NULL " )); + halStatus = eHAL_STATUS_FAILURE; + break; + } sapContext->nStaWPARSnReqIeLength = pCsrRoamInfo->rsnIELen; if(sapContext->nStaWPARSnReqIeLength) vos_mem_copy( sapContext->pStaWpaRsnReqIE, pCsrRoamInfo->prsnIE, sapContext->nStaWPARSnReqIeLength); - sapContext->nStaAddIeLength = pCsrRoamInfo->addIELen; if(sapContext->nStaAddIeLength) vos_mem_copy( sapContext->pStaAddIE, pCsrRoamInfo->paddIE, sapContext->nStaAddIeLength); - sapContext->SapQosCfg.WmmIsEnabled = pCsrRoamInfo->wmmEnabledSta; // MAC filtering vosStatus = sapIsPeerMacAllowed(sapContext, (v_U8_t *)pCsrRoamInfo->peerMac); @@ -1520,8 +1524,15 @@ WLANSAP_RoamCallback FL("CSR roamResult = %s (%d)"), "eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF", roamResult); + if (!pCsrRoamInfo) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("pCsrRoamInfo NULL " )); + halStatus = eHAL_STATUS_FAILURE; + break; + } + + sapContext->nStaWPARSnReqIeLength = pCsrRoamInfo->rsnIELen; - sapContext->nStaWPARSnReqIeLength = pCsrRoamInfo->rsnIELen; if (sapContext->nStaWPARSnReqIeLength) vos_mem_copy( sapContext->pStaWpaRsnReqIE, pCsrRoamInfo->prsnIE, sapContext->nStaWPARSnReqIeLength); @@ -1556,7 +1567,8 @@ WLANSAP_RoamCallback "eCSR_ROAM_RESULT_DISASSOC_IND", roamResult); #ifdef WLAN_FEATURE_AP_HT40_24G - sapRemoveHT40IntolerantSta(sapContext, pCsrRoamInfo); + if (pCsrRoamInfo) + sapRemoveHT40IntolerantSta(sapContext, pCsrRoamInfo); #endif /* Fill in the event structure */ vosStatus = sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_STA_DISASSOC_EVENT, (v_PVOID_t)eSAP_STATUS_SUCCESS); @@ -1573,7 +1585,13 @@ WLANSAP_RoamCallback roamResult); /* Fill in the event structure */ //TODO: support for group key MIC failure event to be handled - vosStatus = sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_STA_MIC_FAILURE_EVENT,(v_PVOID_t) NULL); + if (!pCsrRoamInfo) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("pCsrRoamInfo NULL " )); + halStatus = eHAL_STATUS_FAILURE; + break; + } + vosStatus = sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_STA_MIC_FAILURE_EVENT,(v_PVOID_t) NULL); if(!VOS_IS_STATUS_SUCCESS(vosStatus)) { halStatus = eHAL_STATUS_FAILURE; @@ -1587,7 +1605,13 @@ WLANSAP_RoamCallback roamResult); /* Fill in the event structure */ //TODO: support for unicast key MIC failure event to be handled - vosStatus = sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_STA_MIC_FAILURE_EVENT,(v_PVOID_t) NULL); + if (!pCsrRoamInfo) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("pCsrRoamInfo NULL " )); + halStatus = eHAL_STATUS_FAILURE; + break; + } + vosStatus = sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_STA_MIC_FAILURE_EVENT,(v_PVOID_t) NULL); if(!VOS_IS_STATUS_SUCCESS(vosStatus)) { halStatus = eHAL_STATUS_FAILURE; @@ -1661,7 +1685,13 @@ WLANSAP_RoamCallback roamResult); /* Fill in the event structure */ //TODO: support for group key MIC failure event to be handled - vosStatus = sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_WPS_PBC_PROBE_REQ_EVENT,(v_PVOID_t) NULL); + if (!pCsrRoamInfo) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("pCsrRoamInfo NULL " )); + halStatus = eHAL_STATUS_FAILURE; + break; + } + vosStatus = sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_WPS_PBC_PROBE_REQ_EVENT,(v_PVOID_t) NULL); if(!VOS_IS_STATUS_SUCCESS(vosStatus)) { halStatus = eHAL_STATUS_FAILURE; @@ -1674,11 +1704,13 @@ WLANSAP_RoamCallback "eCSR_ROAM_RESULT_FORCED", roamResult); #ifdef WLAN_FEATURE_AP_HT40_24G - sapRemoveHT40IntolerantSta(sapContext, pCsrRoamInfo); + if (pCsrRoamInfo) + sapRemoveHT40IntolerantSta(sapContext, pCsrRoamInfo); #endif //This event can be used to inform hdd about user triggered disassoc event /* Fill in the event structure */ - sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_STA_DISASSOC_EVENT, (v_PVOID_t)eSAP_STATUS_SUCCESS); + if (pCsrRoamInfo) + sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_STA_DISASSOC_EVENT, (v_PVOID_t)eSAP_STATUS_SUCCESS); break; case eCSR_ROAM_RESULT_NONE: From 9c9f1c1a23609d4c1db4459937716b5b305c2cdc Mon Sep 17 00:00:00 2001 From: Himanshu Agarwal Date: Mon, 12 Feb 2018 19:38:09 +0530 Subject: [PATCH 157/508] wlan: Free assoc responses while doing lim cleanup In case when tx confirmation for assoc response is not coming from fw and driver unload happens, all the assoc responses from the list should be freed while doing lim cleanup. But in limDestroyAssocRspCompletiontionList(), assoc responses in the list does not get freed causing memory leak. Free assoc responses while doing lim cleanup in limDestroyAssocRspCompletiontionList(). Change-Id: I476a044dcd84b08c6c03ea11ada60e88383e4048 CRs-Fixed: 2188215 --- CORE/MAC/src/pe/lim/limApi.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c index d8137ff06be1d..988eec33f6768 100644 --- a/CORE/MAC/src/pe/lim/limApi.c +++ b/CORE/MAC/src/pe/lim/limApi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -712,6 +712,16 @@ limInitAssocRspCompletiontionList(tpAniSirGlobal pMac) static void limDestroyAssocRspCompletiontionList(tpAniSirGlobal pMac) { + assoc_rsp_tx_context *pAssocRspCtx; + + while(vos_list_remove_front(&pMac->assoc_rsp_completion_list, + (vos_list_node_t**)&pAssocRspCtx) == VOS_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + FL("Fixing leak! Deallocating pAssocRspCtx node %lu"), + (unsigned long)pAssocRspCtx); + vos_mem_free(pAssocRspCtx); + } vos_list_destroy(&pMac->assoc_rsp_completion_list); } From 852449b2e185ae15011c82473320099136ed2be8 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Thu, 8 Mar 2018 13:21:10 +0530 Subject: [PATCH 158/508] wlan: Send STA authorized status to supplicant for AP Propagation from qcacld-3.0 to prima. Currently there is no support from driver to send STA authorized event to supplicant. Use QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES vendor command to send STA authorized event to supplicant. Change-Id: I46416949f04dd28a1713cbebf1f7d0e84b5efda2 CRs-Fixed: 2202232 --- CORE/HDD/inc/wlan_hdd_cfg80211.h | 19 +++++++++ CORE/HDD/src/wlan_hdd_cfg80211.c | 61 ++++++++++++++++++++++++++++ CORE/HDD/src/wlan_hdd_softap_tx_rx.c | 5 ++- 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h index 059dfe495eafd..7d47327b46d30 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -475,6 +475,7 @@ enum qca_nl80211_vendor_subcmds_index { QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX, QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX, QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX, + QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX, }; /** @@ -1377,6 +1378,10 @@ enum qca_wlan_vendor_attr_link_properties { QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS = 2, /* Unsigned 32bit value for operating frequency */ QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ = 3, + /* Unsigned 32bit value for STA flags*/ + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS = 4, + /* An array of 6 Unsigned 8bit values for the STA MAC address*/ + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_MAC = 5, /* KEEP LAST */ QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_AFTER_LAST, @@ -1803,4 +1808,18 @@ int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, int wlan_hdd_cfg80211_update_apies(hdd_adapter_t *pHostapdAdapter); int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter); void wlan_hdd_sap_get_sta_rssi(hdd_adapter_t *adapter, uint8_t staid, s8 *rssi); + +/* + *wlan_hdd_send_sta_authorized_event: Function to send station authorized + *event to user space in case of SAP + *@pAdapter: Pointer to the adapter + *@pHddCtx: HDD Context + *@mac_addr: MAC address of the STA for whic the Authorized event needs to + * be sent + *This api is used to send station authorized event to user space + */ +VOS_STATUS wlan_hdd_send_sta_authorized_event(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + const v_MACADDR_t *mac_addr); + #endif diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 1de07394b7e77..bb8347c6cef2a 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -8862,6 +8862,10 @@ struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = .vendor_id = QCA_NL80211_VENDOR_ID, .subcmd = QCA_NL80211_VENDOR_SUBCMD_HANG, }, + [QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES, + }, }; /* @@ -12768,6 +12772,59 @@ static int wlan_hdd_tdls_add_station(struct wiphy *wiphy, } #endif +VOS_STATUS wlan_hdd_send_sta_authorized_event( + hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + const v_MACADDR_t *mac_addr) +{ + struct sk_buff *vendor_event; + uint32_t sta_flags = 0; + VOS_STATUS status; + + ENTER(); + + if (!hdd_ctx) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is null")); + return -EINVAL; + } + + vendor_event = + cfg80211_vendor_event_alloc( + hdd_ctx->wiphy, &adapter->wdev, sizeof(sta_flags) + + VOS_MAC_ADDR_SIZE + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX, + GFP_KERNEL); + if (!vendor_event) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("cfg80211_vendor_event_alloc failed")); + return -EINVAL; + } + + sta_flags |= BIT(NL80211_STA_FLAG_AUTHORIZED); + + status = nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS, + sta_flags); + if (status) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("STA flag put fails")); + kfree_skb(vendor_event); + return VOS_STATUS_E_FAILURE; + } + status = nla_put(vendor_event, + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_MAC, + VOS_MAC_ADDR_SIZE, mac_addr->bytes); + if (status) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("STA MAC put fails")); + kfree_skb(vendor_event); + return VOS_STATUS_E_FAILURE; + } + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + + EXIT(); + return 0; +} + static int __wlan_hdd_change_station(struct wiphy *wiphy, struct net_device *dev, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0)) @@ -12835,6 +12892,10 @@ static int __wlan_hdd_change_station(struct wiphy *wiphy, "%s: Not able to change TL state to AUTHENTICATED", __func__); return -EINVAL; } + status = wlan_hdd_send_sta_authorized_event(pAdapter, pHddCtx, + &STAMacAddress); + if (status != VOS_STATUS_SUCCESS) + return -EINVAL; } } else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) diff --git a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c index 12e2b9417ca40..b5cb8b3c759ac 100644 --- a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c +++ b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c @@ -2031,7 +2031,10 @@ VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter, pSapCtx->aStaInfo[staId].tlSTAState = WLANTL_STA_AUTHENTICATED; pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_TRUE; - } + if (!vos_is_macaddr_broadcast(pPeerMacAddress)) + vosStatus = wlan_hdd_send_sta_authorized_event(pAdapter, pHddCtx, + pPeerMacAddress); + } else { From 10e17cfd7f298e46955f8612452895dae995933f Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Mon, 12 Mar 2018 14:34:22 +0530 Subject: [PATCH 159/508] wlan: Fix race between STA connect and SAP channel switch If SAP channel change is in progress and STA connect req is received driver ends up sending two change channel req to firmware. As WDA and WDI is not sessionized to handle two back to back channel change req the ADD BSS req is dropped and no response for ADD BSS is sent to LIM. This result in roam command timeout. The fix adds logic to - Flush channel change workqueue when STA connection is requested. - Wait for channel change to complete when STA connection is requested OR SAP is turned off. - Check for DFS channel of SAP if STA conenction fails as during connect driver flush the channel change workqueue. Change-Id: I8b67538178ccd866a1a9430ed55a6fa8d5dbfd40 CRs-Fixed: 2204574 --- CORE/HDD/inc/wlan_hdd_main.h | 12 ++++++ CORE/HDD/src/wlan_hdd_assoc.c | 20 ++++++++- CORE/HDD/src/wlan_hdd_cfg80211.c | 26 +++++++++++- CORE/HDD/src/wlan_hdd_hostapd.c | 18 +++++++- CORE/HDD/src/wlan_hdd_main.c | 73 ++++++++++++++++++++++++++------ CORE/SAP/src/sapApiLinkCntl.c | 5 ++- CORE/SAP/src/sapInternal.h | 33 +++++++++++++++ CORE/SAP/src/sapModule.c | 54 +++++++++++++++++++++-- 8 files changed, 218 insertions(+), 23 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index b6db4a17740ce..2a3058e454db3 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -74,6 +74,10 @@ /*--------------------------------------------------------------------------- Preprocessor definitions and constants -------------------------------------------------------------------------*/ + +/* SAP channel change wait time in ms */ +#define HDD_SAP_CHAN_CNG_WAIT_TIME 1500 + /** Number of attempts to detect/remove card */ #define LIBRA_CARD_INSERT_DETECT_MAX_COUNT 5 #define LIBRA_CARD_REMOVE_DETECT_MAX_COUNT 5 @@ -2317,6 +2321,14 @@ void hdd_restore_roaming(hdd_context_t *hdd_ctx); int wlan_hdd_check_and_stop_mon(hdd_adapter_t *sta_adapter, bool wait); +/** + * hdd_wait_for_ecsa_complete() - wait if ecsa is in progress + * @hdd_ctx: hdd context + * + * Return: int. + */ +int hdd_wait_for_ecsa_complete(hdd_context_t *hdd_ctx); + /** * hdd_is_sta_sap_scc_allowed_on_dfs_chan() - check if sta+sap scc allowed on * dfs chan diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c index 857527a693f35..44000f6c83ea9 100644 --- a/CORE/HDD/src/wlan_hdd_assoc.c +++ b/CORE/HDD/src/wlan_hdd_assoc.c @@ -162,6 +162,12 @@ v_U8_t ccpRSNOui08[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x05 }; /* The time after add bss, in which SAP should start ECSA to move to SCC */ #define ECSA_SCC_CHAN_CHANGE_DEFER_INTERVAL 1500 +/* + * Time in ms after disconnect, in which the SAP should move to non DFS channel. + * This will avoid multiple SAP channel switch if disconnet is followed by + * connect. + */ +#define ECSA_DFS_CHAN_CHANGE_DEFER_TIME 200 #ifdef WLAN_FEATURE_11W void hdd_indicateUnprotMgmtFrame(hdd_adapter_t *pAdapter, @@ -1601,18 +1607,24 @@ static void hdd_check_and_move_if_sap_is_on_dfs_chan(hdd_context_t *hdd_ctx, return; } + if (sap_ctx->sapsMachine != eSAP_STARTED) { + hddLog(LOG1, FL("SAP is not in eSAP_STARTED state")); + return; + } + chan_state = vos_nv_getChannelEnabledState(sap_ctx->channel); hddLog(LOG1, "SAP is operating on channel (%hu), chan_state %d", sap_ctx->channel, chan_state); - if (vos_nv_getChannelEnabledState(sap_ctx->channel) != NV_CHANNEL_DFS) { hddLog(LOG1, "SAP is on non DFS channel. nothing to do"); return; } + hddLog(LOG1, "Schedule workqueue to move the SAP to non DFS channel"); - schedule_delayed_work(&hdd_ctx->ecsa_chan_change_work, 0); + schedule_delayed_work(&hdd_ctx->ecsa_chan_change_work, + msecs_to_jiffies(ECSA_DFS_CHAN_CHANGE_DEFER_TIME)); } } @@ -2812,6 +2824,10 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs } } } + else if (roamStatus == eCSR_ROAM_ASSOCIATION_FAILURE) + { + hdd_check_and_move_if_sap_is_on_dfs_chan(pHddCtx, pAdapter); + } return eHAL_STATUS_SUCCESS; } diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index bb8347c6cef2a..ea392395949d2 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -11692,6 +11692,8 @@ static int __wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy, mutex_lock(&pHddCtx->sap_lock); if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags)) { + vos_flush_delayed_work(&pHddCtx->ecsa_chan_change_work); + hdd_wait_for_ecsa_complete(pHddCtx); if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) ) { hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); @@ -15800,7 +15802,10 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, FL("Set HDD connState to eConnectionState_Connecting")); hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), eConnectionState_Connecting); + vos_flush_delayed_work(&pHddCtx->ecsa_chan_change_work); + hdd_wait_for_ecsa_complete(pHddCtx); } + status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, pRoamProfile, &roamId); @@ -21897,6 +21902,7 @@ static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy, hdd_context_t *hdd_ctx; uint8_t channel; int ret; + ptSapContext sap_ctx; v_CONTEXT_t vos_ctx; hddLog(LOGE, FL("Set Freq %d"), csa_params->chandef.chan->center_freq); @@ -21912,13 +21918,29 @@ static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy, return -EINVAL; } - if ((WLAN_HDD_SOFTAP != adapter->device_mode) && - (WLAN_HDD_P2P_GO != adapter->device_mode)) + if (WLAN_HDD_SOFTAP != adapter->device_mode) return -ENOTSUPP; + sap_ctx = VOS_GET_SAP_CB(vos_ctx); + if (!sap_ctx) { + hddLog(LOGE, FL("sap_ctx is NULL")); + return -EINVAL; + } + + ret = wlansap_chk_n_set_chan_change_in_progress(sap_ctx); + if (ret) + return ret; + + INIT_COMPLETION(sap_ctx->ecsa_info.chan_switch_comp); + channel = vos_freq_to_chan(csa_params->chandef.chan->center_freq); ret = wlansap_set_channel_change(vos_ctx, channel, false); + if (ret) { + wlansap_reset_chan_change_in_progress(sap_ctx); + complete(&sap_ctx->ecsa_info.chan_switch_comp); + } + return ret; } diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index 87d3d6dadd70f..63e76bce21a32 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -2471,11 +2471,25 @@ static __iw_softap_setparam(struct net_device *dev, break; } case QCSAP_PARAM_SET_CHANNEL_CHANGE: - if ((WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) || - (WLAN_HDD_P2P_GO == pHostapdAdapter->device_mode)) { + if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) { + ptSapContext sap_ctx; + + sap_ctx = VOS_GET_SAP_CB(pVosContext); + if (!sap_ctx) { + hddLog(LOGE, FL("sap_ctx is NULL")); + return -EINVAL; + } + ret = wlansap_chk_n_set_chan_change_in_progress(sap_ctx); + if (ret) + return ret; + INIT_COMPLETION(sap_ctx->ecsa_info.chan_switch_comp); hddLog(LOG1, FL("ET Channel Change to new channel= %d"), set_value); ret = wlansap_set_channel_change(pVosContext, set_value, false); + if (ret) { + wlansap_reset_chan_change_in_progress(sap_ctx); + complete(&sap_ctx->ecsa_info.chan_switch_comp); + } } else { hddLog(LOGE, FL("Channel %d Change Failed, Device in not in SAP/GO mode"), set_value); diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index fee2bc2413ee1..ea33d3ad19097 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -10212,28 +10212,38 @@ __hdd_force_scc_with_ecsa_handle(struct work_struct *work) hddLog(LOGE, FL("sta_adapter is NULL")); return; } - sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter); + if (wlansap_chk_n_set_chan_change_in_progress(sap_ctx)) + return; + INIT_COMPLETION(sap_ctx->ecsa_info.chan_switch_comp); + + sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter); if (sta_ctx->conn_info.connState != eConnectionState_Associated) { - chan_state = vos_nv_getChannelEnabledState(sap_ctx->channel); - hddLog(LOG1, FL("sta not in connected state %d, sta_sap_scc_on_dfs_chan %d, chan_state %d"), - sta_ctx->conn_info.connState, sta_sap_scc_on_dfs_chan, - chan_state); - if (sta_sap_scc_on_dfs_chan && + if (sta_ctx->conn_info.connState == eConnectionState_NotConnected) { + chan_state = vos_nv_getChannelEnabledState(sap_ctx->channel); + hddLog(LOG1, FL("sta not in connected state %d, sta_sap_scc_on_dfs_chan %d, chan_state %d"), + sta_ctx->conn_info.connState, sta_sap_scc_on_dfs_chan, + chan_state); + if (sta_sap_scc_on_dfs_chan && (chan_state == NV_CHANNEL_DFS)) { - hddLog(LOG1, FL("Switch SAP to user configured channel")); - target_channel = sap_config->user_config_channel; - goto switch_channel; - + hddLog(LOGE, FL("Switch SAP to user configured channel")); + target_channel = sap_config->user_config_channel; + goto switch_channel; + } } - return; + goto abort; } target_channel = sta_ctx->conn_info.operationChannel; switch_channel: hddLog(LOGE, FL("Switch SAP to %d channel"), target_channel); - wlansap_set_channel_change(vos_ctx, target_channel, true); + if (!wlansap_set_channel_change(vos_ctx, target_channel, true)) + return; + +abort: + wlansap_reset_chan_change_in_progress(sap_ctx); + complete(&sap_ctx->ecsa_info.chan_switch_comp); } /** @@ -10253,6 +10263,45 @@ hdd_force_scc_with_ecsa_handle(struct work_struct *work) vos_ssr_unprotect(__func__); } +int hdd_wait_for_ecsa_complete(hdd_context_t *hdd_ctx) +{ + int ret; + ptSapContext sap_ctx = NULL; + v_CONTEXT_t vos_ctx; + + vos_ctx = hdd_ctx->pvosContext; + if (!vos_ctx) { + hddLog(LOGE, FL("vos_ctx is NULL")); + return 0; + } + + sap_ctx = VOS_GET_SAP_CB(vos_ctx); + if (!sap_ctx) { + hddLog(LOG1, FL("sap_ctx is NULL")); + return 0; + } + if(!sap_ctx->isSapSessionOpen) { + hddLog(LOG1, FL("sap session not opened, SAP in state %d"), + sap_ctx->sapsMachine); + return 0; + } + + if (!wlansap_get_change_in_progress(sap_ctx)) { + hddLog(LOG1, FL("channel switch not in progress")); + return 0; + } + ret = wait_for_completion_timeout(&sap_ctx->ecsa_info.chan_switch_comp, + msecs_to_jiffies(HDD_SAP_CHAN_CNG_WAIT_TIME)); + if (!ret) + { + hddLog(LOGE, FL("Timeout waiting for SAP channel switch")); + return ret; + } + + return 0; +} + + /** * hdd_is_sta_sap_scc_allowed_on_dfs_chan() - check if sta+sap scc allowed on * dfs chan diff --git a/CORE/SAP/src/sapApiLinkCntl.c b/CORE/SAP/src/sapApiLinkCntl.c index a34e5cd5575a5..5e905499df855 100644 --- a/CORE/SAP/src/sapApiLinkCntl.c +++ b/CORE/SAP/src/sapApiLinkCntl.c @@ -1215,7 +1215,6 @@ static VOS_STATUS sap_roam_process_ch_change_resp(ptSapContext sap_ctx, FL("sapdfs: from state eSAP_DISCONNECTING => eSAP_STARTING on sapctx[%pK]"), sap_ctx); sap_ctx->sapsMachine = eSAP_STARTING; - sap_ctx->ecsa_info.channel_switch_in_progress = false; sap_event.event = eSAP_MAC_START_BSS_SUCCESS; sap_event.params = csr_roam_info; sap_event.u1 = eCSR_ROAM_INFRA_IND; @@ -1223,6 +1222,10 @@ static VOS_STATUS sap_roam_process_ch_change_resp(ptSapContext sap_ctx, /* Handle the event */ status = sapFsm(sap_ctx, &sap_event); + + wlansap_reset_chan_change_in_progress(sap_ctx); + complete(&sap_ctx->ecsa_info.chan_switch_comp); + return status; } diff --git a/CORE/SAP/src/sapInternal.h b/CORE/SAP/src/sapInternal.h index d679580a9da20..a7e3fb929386f 100644 --- a/CORE/SAP/src/sapInternal.h +++ b/CORE/SAP/src/sapInternal.h @@ -208,12 +208,16 @@ struct hdd_cache_sta_info{ /** * struct ecsa_info - structure to store ecsa info + * @ecsa_lock: ecsa lock * @new_channel: new channel to which switch is requested * @channel_switch_in_progress: check if channel switch is in progress + * @chan_switch_comp: channel switch comp var */ struct ecsa_info { + spinlock_t ecsa_lock; uint8_t new_channel; bool channel_switch_in_progress; + struct completion chan_switch_comp; }; typedef struct sSapContext { @@ -945,6 +949,35 @@ struct hdd_cache_sta_info *hdd_get_cache_stainfo( struct hdd_cache_sta_info *astainfo, u8 *mac_addr); +/** + * wlansap_chk_n_set_chan_change_in_progress() - + * check if chan change is in progress and set it if not + * + * @sap_ctx: sap context + * + * Return: 0 if channel change is not in progress else error + */ +int wlansap_chk_n_set_chan_change_in_progress(ptSapContext sap_ctx); +/** + * wlansap_reset_chan_change_in_progress() - reset channel change in progress + * + * @sap_ctx: sap context + * + * Return: 0 if channel change is reset else error + */ +int wlansap_reset_chan_change_in_progress(ptSapContext sap_ctx); + +/** + * wlansap_get_change_in_progress() - get channel change in progress + * + * @sap_ctx: sap context + * + * Return: true if channel change in progress else false + */ +bool wlansap_get_change_in_progress(ptSapContext sap_ctx); + + + #ifdef __cplusplus } #endif diff --git a/CORE/SAP/src/sapModule.c b/CORE/SAP/src/sapModule.c index 20febb52328e9..6268e7de0e9bc 100644 --- a/CORE/SAP/src/sapModule.c +++ b/CORE/SAP/src/sapModule.c @@ -173,6 +173,15 @@ WLANSAP_Open return VOS_STATUS_E_FAULT; } + if (!VOS_IS_STATUS_SUCCESS( + vos_spin_lock_init(&pSapCtx->ecsa_info.ecsa_lock))) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "WLANSAP_Start failed init ecsa_lock"); + vos_free_context(pvosGCtx, VOS_MODULE_ID_SAP, pSapCtx); + return VOS_STATUS_E_FAULT; + } + // Setup the "link back" to the VOSS context pSapCtx->pvosGCtx = pvosGCtx; @@ -639,6 +648,7 @@ WLANSAP_StartBss pSapCtx->scanBandPreference = pConfig->scanBandPreference; pSapCtx->acsBandSwitchThreshold = pConfig->acsBandSwitchThreshold; pSapCtx->pUsrContext = pUsrContext; + init_completion(&pSapCtx->ecsa_info.chan_switch_comp); //Set the BSSID to your "self MAC Addr" read the mac address from Configuation ITEM received from HDD pSapCtx->csrRoamProfile.BSSIDs.numOfBSSIDs = 1; @@ -2494,6 +2504,41 @@ static bool wlansap_validate_phy_mode(uint32_t phy_mode, uint32_t channel) return true; } +int wlansap_chk_n_set_chan_change_in_progress(ptSapContext sap_ctx) +{ + vos_spin_lock_acquire(&sap_ctx->ecsa_info.ecsa_lock); + if (sap_ctx->ecsa_info.channel_switch_in_progress) { + vos_spin_lock_release(&sap_ctx->ecsa_info.ecsa_lock); + hddLog(LOGE, FL("channel switch already in progress")); + return -EALREADY; + } + sap_ctx->ecsa_info.channel_switch_in_progress = true; + vos_spin_lock_release(&sap_ctx->ecsa_info.ecsa_lock); + + return 0; +} + +int wlansap_reset_chan_change_in_progress(ptSapContext sap_ctx) +{ + vos_spin_lock_acquire(&sap_ctx->ecsa_info.ecsa_lock); + sap_ctx->ecsa_info.channel_switch_in_progress = false; + vos_spin_lock_release(&sap_ctx->ecsa_info.ecsa_lock); + + return 0; +} + +bool wlansap_get_change_in_progress(ptSapContext sap_ctx) +{ + bool value; + + vos_spin_lock_acquire(&sap_ctx->ecsa_info.ecsa_lock); + value = sap_ctx->ecsa_info.channel_switch_in_progress; + vos_spin_lock_release(&sap_ctx->ecsa_info.ecsa_lock); + + return value; +} + + int wlansap_set_channel_change(v_PVOID_t vos_ctx, uint32_t new_channel, bool allow_dfs_chan) { @@ -2526,10 +2571,12 @@ int wlansap_set_channel_change(v_PVOID_t vos_ctx, hddLog(LOGE, FL("channel %d already set"), new_channel); return -EALREADY; } - if (sap_ctx->ecsa_info.channel_switch_in_progress) { - hddLog(LOGE, FL("channel switch already in progress ignore")); - return -EALREADY; + + if(!wlansap_get_change_in_progress(sap_ctx)) { + hddLog(LOGE, FL("channel_switch_in_progress should be set before calling channel change")); + return -EINVAL; } + chan_state = vos_nv_getChannelEnabledState(new_channel); if ((chan_state == NV_CHANNEL_DISABLE) || (chan_state == NV_CHANNEL_INVALID)) { @@ -2549,7 +2596,6 @@ int wlansap_set_channel_change(v_PVOID_t vos_ctx, } sap_ctx->ecsa_info.new_channel = new_channel; - sap_ctx->ecsa_info.channel_switch_in_progress = true; /* * Post the eSAP_CHANNEL_SWITCH_ANNOUNCEMENT_START * to SAP state machine to process the channel From a6edfc2e2338b39953d8cb4b922d7f2090168fac Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Fri, 9 Mar 2018 20:46:04 +0530 Subject: [PATCH 160/508] wlan: Set max size of probe resp template to 700 Max size for probe response template used by driver is 384 but firmware max allowed length for template is 700 as two beaconing interfaces are not supported. With 384 size the additional IE are not sent in probe resp. Fix is to set max size for probe resp template to 700. Beacon len is reverted to original length of 500. Change-Id: Ic5ad9f16a7a45c9e735eac086ee61330b02a1e17 CRs-Fixed: 2198940 --- CORE/MAC/src/pe/include/schGlobal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CORE/MAC/src/pe/include/schGlobal.h b/CORE/MAC/src/pe/include/schGlobal.h index e7a83778060ab..48baf89b0c484 100644 --- a/CORE/MAC/src/pe/include/schGlobal.h +++ b/CORE/MAC/src/pe/include/schGlobal.h @@ -77,9 +77,9 @@ //****************** MISC defs ********************************* /// Maximum allowable size of a beacon frame -#define SCH_MAX_BEACON_SIZE 384 +#define SCH_MAX_BEACON_SIZE 500 -#define SCH_MAX_PROBE_RESP_SIZE 384 +#define SCH_MAX_PROBE_RESP_SIZE 700 struct schMisc { From 0f3b73b456a36bf6fdc10ac82b6a87ecdfb00633 Mon Sep 17 00:00:00 2001 From: Animesh Kishore Date: Fri, 23 Feb 2018 18:04:28 +0530 Subject: [PATCH 161/508] msm: mdss: Fix scalar LUT handling Add lock to serialize access between userspace and kernel. Fix error handling for LUT allocation. Change-Id: Ie86a8eb3e2a11852ae16d87ebc851afb6566732f Signed-off-by: Animesh Kishore --- drivers/video/msm/mdss/mdss.h | 9 ++++- drivers/video/msm/mdss/mdss_mdp.c | 4 ++- drivers/video/msm/mdss/mdss_mdp_overlay.c | 40 +++++++++++++++-------- drivers/video/msm/mdss/mdss_mdp_pp.c | 9 ++++- 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h index e44ca678cd22c..9dab8170d6cf4 100644 --- a/drivers/video/msm/mdss/mdss.h +++ b/drivers/video/msm/mdss/mdss.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -232,6 +232,13 @@ struct mdss_scaler_block { u32 *dest_scaler_off; u32 *dest_scaler_lut_off; struct mdss_mdp_qseed3_lut_tbl lut_tbl; + + /* + * Lock is mainly to serialize access to LUT. + * LUT values come asynchronously from userspace + * via ioctl. + */ + struct mutex scaler_lock; }; struct mdss_data_type; diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c index f12a8db73a4ed..393c229483415 100644 --- a/drivers/video/msm/mdss/mdss_mdp.c +++ b/drivers/video/msm/mdss/mdss_mdp.c @@ -1,7 +1,7 @@ /* * MDSS MDP Interface (used by framebuffer core) * - * Copyright (c) 2007-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2007-2018, The Linux Foundation. All rights reserved. * Copyright (C) 2007 Google Incorporated * * This software is licensed under the terms of the GNU General Public @@ -2081,6 +2081,8 @@ static u32 mdss_mdp_scaler_init(struct mdss_data_type *mdata, return -EINVAL; } + mutex_init(&mdata->scaler_off->scaler_lock); + return 0; } diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c index 0f3e4385a788f..0a99acba594b0 100644 --- a/drivers/video/msm/mdss/mdss_mdp_overlay.c +++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -6789,14 +6789,18 @@ static int mdss_mdp_scaler_lut_init(struct mdss_data_type *mdata, if (!mdata->scaler_off) return -EFAULT; + mutex_lock(&mdata->scaler_off->scaler_lock); + qseed3_lut_tbl = &mdata->scaler_off->lut_tbl; if ((lut_tbl->dir_lut_size != DIR_LUT_IDX * DIR_LUT_COEFFS * sizeof(uint32_t)) || (lut_tbl->cir_lut_size != CIR_LUT_IDX * CIR_LUT_COEFFS * sizeof(uint32_t)) || (lut_tbl->sep_lut_size != - SEP_LUT_IDX * SEP_LUT_COEFFS * sizeof(uint32_t))) - return -EINVAL; + SEP_LUT_IDX * SEP_LUT_COEFFS * sizeof(uint32_t))) { + mutex_unlock(&mdata->scaler_off->scaler_lock); + return -EINVAL; + } if (!qseed3_lut_tbl->dir_lut) { qseed3_lut_tbl->dir_lut = devm_kzalloc(&mdata->pdev->dev, @@ -6804,7 +6808,7 @@ static int mdss_mdp_scaler_lut_init(struct mdss_data_type *mdata, GFP_KERNEL); if (!qseed3_lut_tbl->dir_lut) { ret = -ENOMEM; - goto fail; + goto err; } } @@ -6814,7 +6818,7 @@ static int mdss_mdp_scaler_lut_init(struct mdss_data_type *mdata, GFP_KERNEL); if (!qseed3_lut_tbl->cir_lut) { ret = -ENOMEM; - goto fail; + goto fail_free_dir_lut; } } @@ -6824,44 +6828,52 @@ static int mdss_mdp_scaler_lut_init(struct mdss_data_type *mdata, GFP_KERNEL); if (!qseed3_lut_tbl->sep_lut) { ret = -ENOMEM; - goto fail; + goto fail_free_cir_lut; } } /* Invalidate before updating */ qseed3_lut_tbl->valid = false; - if (copy_from_user(qseed3_lut_tbl->dir_lut, (void *)(unsigned long)lut_tbl->dir_lut, lut_tbl->dir_lut_size)) { ret = -EINVAL; - goto err; + goto fail_free_sep_lut; } if (copy_from_user(qseed3_lut_tbl->cir_lut, (void *)(unsigned long)lut_tbl->cir_lut, lut_tbl->cir_lut_size)) { ret = -EINVAL; - goto err; + goto fail_free_sep_lut; } if (copy_from_user(qseed3_lut_tbl->sep_lut, (void *)(unsigned long)lut_tbl->sep_lut, lut_tbl->sep_lut_size)) { ret = -EINVAL; - goto err; + goto fail_free_sep_lut; } qseed3_lut_tbl->valid = true; + mutex_unlock(&mdata->scaler_off->scaler_lock); + return ret; -fail: - kfree(qseed3_lut_tbl->dir_lut); - kfree(qseed3_lut_tbl->cir_lut); - kfree(qseed3_lut_tbl->sep_lut); +fail_free_sep_lut: + devm_kfree(&mdata->pdev->dev, qseed3_lut_tbl->sep_lut); +fail_free_cir_lut: + devm_kfree(&mdata->pdev->dev, qseed3_lut_tbl->cir_lut); +fail_free_dir_lut: + devm_kfree(&mdata->pdev->dev, qseed3_lut_tbl->dir_lut); err: + qseed3_lut_tbl->dir_lut = NULL; + qseed3_lut_tbl->cir_lut = NULL; + qseed3_lut_tbl->sep_lut = NULL; qseed3_lut_tbl->valid = false; + mutex_unlock(&mdata->scaler_off->scaler_lock); + return ret; } diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c index 964a5929d65a5..9644a5c4f6d31 100644 --- a/drivers/video/msm/mdss/mdss_mdp_pp.c +++ b/drivers/video/msm/mdss/mdss_mdp_pp.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1576,11 +1576,16 @@ int mdss_mdp_scaler_lut_cfg(struct mdp_scale_data_v2 *scaler, }; mdata = mdss_mdp_get_mdata(); + + mutex_lock(&mdata->scaler_off->scaler_lock); + lut_tbl = &mdata->scaler_off->lut_tbl; if ((!lut_tbl) || (!lut_tbl->valid)) { + mutex_unlock(&mdata->scaler_off->scaler_lock); pr_err("%s:Invalid QSEED3 LUT TABLE\n", __func__); return -EINVAL; } + if ((scaler->lut_flag & SCALER_LUT_DIR_WR) || (scaler->lut_flag & SCALER_LUT_Y_CIR_WR) || (scaler->lut_flag & SCALER_LUT_UV_CIR_WR) || @@ -1631,6 +1636,8 @@ int mdss_mdp_scaler_lut_cfg(struct mdp_scale_data_v2 *scaler, writel_relaxed(BIT(0), MDSS_MDP_REG_SCALER_COEF_LUT_CTRL + offset); + mutex_unlock(&mdata->scaler_off->scaler_lock); + return 0; } From 72c2c34cbe2d56b41272da005322fba97ff31e43 Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Mon, 5 Mar 2018 19:49:05 +0530 Subject: [PATCH 162/508] wlan: Add WLAN HAL support for VOWIFIMODE driver command Add WLAN HAL support for sending VOWIFIMODE command in the case when connected to 2.4GHz band. Change-Id: I29c904d4d57837d613ee13d0e4d8fbab001c0ccd CRs-Fixed: 2203713 --- riva/inc/wlan_hal_msg.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/riva/inc/wlan_hal_msg.h b/riva/inc/wlan_hal_msg.h index b37e63c02db3d..e245f0e92a2b7 100644 --- a/riva/inc/wlan_hal_msg.h +++ b/riva/inc/wlan_hal_msg.h @@ -628,6 +628,8 @@ typedef enum WLAN_HAL_FW_GET_ARP_STATS_REQ = 356, WLAN_HAL_FW_GET_ARP_STATS_RSP = 357, + WLAN_HAL_VOWIFI_IND = 360, + WLAN_HAL_MSG_MAX = WLAN_HAL_MSG_TYPE_MAX_ENUM_SIZE }tHalHostMsgType; @@ -8187,6 +8189,21 @@ typedef PACKED_PRE struct PACKED_POST tHalAllowedActionFrames allowedActionFrames; }tHalAllowedActionFramesReqInd, *tpHalAllowedActionFramesReqInd; +/*---------------------------------------------------------------- + WLAN_HAL_VOWIFI_IND +-----------------------------------------------------------------*/ +typedef PACKED_PRE struct PACKED_POST +{ + /* 0 implies VoWifi call ended, 1 implies VoWifi call started */ + tANI_U8 enable; +} tHalVoWiFiIndParams, *tpHalVoWiFiIndParams; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + tHalVoWiFiIndParams voWiFiIndParams; +} tHalVoWiFiInd, * tpHalVoWiFiInd; + /*-------------------------------------------------------------------------- * WLAN_HAL_LL_SET_STATS_REQ *---------------------------------------------------------------------------*/ From a465f9e37bc00e57e01c40e14ea9d3f9394821dd Mon Sep 17 00:00:00 2001 From: Balachandra C S Date: Tue, 6 Mar 2018 18:58:28 +0530 Subject: [PATCH 163/508] drivers: net: can: Unified driver for CAN controller Create a single CAN driver for all the supported CAN controllers - nxp mpc5746c and renesas rh850. Change-Id: I3770aae1adf4ccafd5132f6b57ddc050a93c7c0f Signed-off-by: Balachandra C S --- .../devicetree/bindings/net/can/qti-can.txt | 48 + drivers/net/can/spi/Kconfig | 6 + drivers/net/can/spi/Makefile | 1 + drivers/net/can/spi/qti-can.c | 1455 +++++++++++++++++ 4 files changed, 1510 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/can/qti-can.txt create mode 100644 drivers/net/can/spi/qti-can.c diff --git a/Documentation/devicetree/bindings/net/can/qti-can.txt b/Documentation/devicetree/bindings/net/can/qti-can.txt new file mode 100644 index 0000000000000..c494cc846d971 --- /dev/null +++ b/Documentation/devicetree/bindings/net/can/qti-can.txt @@ -0,0 +1,48 @@ +* QTI CAN driver * + +Required properties: + - compatible: Should be "qcom,renesas,rh850" or "qcom,nxp,mpc5746c". + - reg: Should contain SPI chip select. + - interrupt-parent: Should specify interrupt controller for the interrupt. + - interrupts: Should contain IRQ line for the CAN controller. + - spi-max-frequency: Should contain maximum spi clock frequency for slave device + - qcom,clk-freq-mhz : The frequency at which the CAN clock should be configured. + - qcom,max-can-channels : Maximum number of CAN channels supported by the controller. + +Optional properties: + - qcom,reset-gpio: Reference to the GPIO connected to the reset input. + - pinctrl-names : Names corresponding to the numbered pinctrl states. + - pinctrl-0 : This explains the active state of the GPIO line. + - pinctrl-1 : This explains the suspend state of the GPIO line. + - qcom,bits-per-word: Indicate how many bits are in a SPI frame. e.g.: 8, 16, 32. + Default to 16. + - qcom,reset-delay-msec: Delay in milliseconds to be applied after resetting the chip. + This is applicable only if the reset-gpio is specified. Default value is 1 ms. + - qcom,support-can-fd: Whether CAN FD mode is supported or not. + - qcom,can-fw-cmd-timeout-req: Whether a timeout is required if we don't get a response from + the firmware after flash write. + - qcom,can-fw-cmd-timeout-ms: The duration after which timeout will happen if we don't get a + response from the firmware. + - qcom,rem-all-buffering-timeout-ms: The duration after which timeout will happen if we don't get a + response from the firmware while trying to remove all the buffered frames IDs from flash. + +Example: + +can-controller@0 { + compatible = "qcom,nxp,mpc5746c"; + reg = <0>; + spi-max-frequency = <9600000>; + interrupt-parent = <&tlmm_pinmux>; + interrupts = <87 0>; + qcom,reset-gpio = <&tlmm_pinmux 89 0x1>; + qcom,clk-freq-mhz = <20000000>; + qcom,max-can-channels = <2>; + qcom,bits-per-word = <8>; + qcom,reset-delay-msec = <150>; + qcom,can-fw-cmd-timeout-req; + qcom,can-fw-cmd-timeout-ms = <400>; + qcom,rem-all-buffering-timeout-ms = <2000>; + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&can_rst_on>; + pinctrl-1 = <&can_rst_off>; +}; diff --git a/drivers/net/can/spi/Kconfig b/drivers/net/can/spi/Kconfig index 5b315573387e4..e6b3862230b99 100644 --- a/drivers/net/can/spi/Kconfig +++ b/drivers/net/can/spi/Kconfig @@ -18,4 +18,10 @@ config CAN_K61 depends on SPI ---help--- Driver for the Freescale K61 SPI CAN controllers. + +config QTI_CAN + tristate "Unified driver for QTI CAN controllers" + depends on SPI + ---help--- + Unified driver for QTI CAN controllers. endmenu diff --git a/drivers/net/can/spi/Makefile b/drivers/net/can/spi/Makefile index 375a6cbfbb670..c1951ccc00345 100644 --- a/drivers/net/can/spi/Makefile +++ b/drivers/net/can/spi/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_CAN_MCP251X) += mcp251x.o obj-$(CONFIG_CAN_RH850) += rh850.o obj-${CONFIG_CAN_K61} += k61.o +obj-$(CONFIG_QTI_CAN) += qti-can.o diff --git a/drivers/net/can/spi/qti-can.c b/drivers/net/can/spi/qti-can.c new file mode 100644 index 0000000000000..69a3159d34b1c --- /dev/null +++ b/drivers/net/can/spi/qti-can.c @@ -0,0 +1,1455 @@ +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG_QTI_CAN 0 +#if DEBUG_QTI_CAN == 1 +#define LOGDI(...) dev_info(&priv_data->spidev->dev, __VA_ARGS__) +#define LOGNI(...) netdev_info(netdev, __VA_ARGS__) +#else +#define LOGDI(...) dev_dbg(&priv_data->spidev->dev, __VA_ARGS__) +#define LOGNI(...) netdev_dbg(netdev, __VA_ARGS__) +#endif +#define LOGDE(...) dev_err(&priv_data->spidev->dev, __VA_ARGS__) +#define LOGNE(...) netdev_err(netdev, __VA_ARGS__) + +#define MAX_TX_BUFFERS 1 +#define XFER_BUFFER_SIZE 64 +#define RX_ASSEMBLY_BUFFER_SIZE 128 +#define QTI_CAN_FW_QUERY_RETRY_COUNT 3 +#define DRIVER_MODE_RAW_FRAMES 0 +#define DRIVER_MODE_PROPERTIES 1 +#define DRIVER_MODE_AMB 2 +#define QUERY_FIRMWARE_TIMEOUT_MS 1 + +struct qti_can { + struct net_device **netdev; + struct spi_device *spidev; + struct mutex spi_lock; /* SPI device lock */ + struct workqueue_struct *tx_wq; + char *tx_buf, *rx_buf; + int xfer_length; + atomic_t msg_seq; + char *assembly_buffer; + u8 assembly_buffer_size; + atomic_t netif_queue_stop; + struct completion response_completion; + int wait_cmd; + int cmd_result; + int driver_mode; + int clk_freq_mhz; + int max_can_channels; + int bits_per_word; + int reset_delay_msec; + int reset; + bool support_can_fd; + bool can_fw_cmd_timeout_req; + u32 rem_all_buffering_timeout_ms; + u32 can_fw_cmd_timeout_ms; +}; + +struct qti_can_netdev_privdata { + struct can_priv can; + struct qti_can *qti_can; + u8 netdev_index; +}; + +struct qti_can_tx_work { + struct work_struct work; + struct sk_buff *skb; + struct net_device *netdev; +}; + +/* Message definitions */ +struct spi_mosi { /* TLV for MOSI line */ + u8 cmd; + u8 len; + u16 seq; + u8 data[]; +} __packed; + +struct spi_miso { /* TLV for MISO line */ + u8 cmd; + u8 len; + u16 seq; /* should match seq field from request, or 0 for unsols */ + u8 data[]; +} __packed; + +#define CMD_GET_FW_VERSION 0x81 +#define CMD_CAN_SEND_FRAME 0x82 +#define CMD_CAN_ADD_FILTER 0x83 +#define CMD_CAN_REMOVE_FILTER 0x84 +#define CMD_CAN_RECEIVE_FRAME 0x85 +#define CMD_CAN_CONFIG_BIT_TIMING 0x86 +#define CMD_CAN_DATA_BUFF_ADD 0x87 +#define CMD_CAN_DATA_BUFF_REMOVE 0X88 +#define CMD_CAN_RELEASE_BUFFER 0x89 +#define CMD_CAN_DATA_BUFF_REMOVE_ALL 0x8A +#define CMD_PROPERTY_WRITE 0x8B +#define CMD_PROPERTY_READ 0x8C +#define CMD_GET_FW_BR_VERSION 0x95 +#define CMD_BEGIN_FIRMWARE_UPGRADE 0x96 +#define CMD_FIRMWARE_UPGRADE_DATA 0x97 +#define CMD_END_FIRMWARE_UPGRADE 0x98 +#define CMD_BEGIN_BOOT_ROM_UPGRADE 0x99 +#define CMD_BOOT_ROM_UPGRADE_DATA 0x9A +#define CMD_END_BOOT_ROM_UPGRADE 0x9B + +#define IOCTL_RELEASE_CAN_BUFFER (SIOCDEVPRIVATE + 0) +#define IOCTL_ENABLE_BUFFERING (SIOCDEVPRIVATE + 1) +#define IOCTL_ADD_FRAME_FILTER (SIOCDEVPRIVATE + 2) +#define IOCTL_REMOVE_FRAME_FILTER (SIOCDEVPRIVATE + 3) +#define IOCTL_DISABLE_BUFFERING (SIOCDEVPRIVATE + 5) +#define IOCTL_DISABLE_ALL_BUFFERING (SIOCDEVPRIVATE + 6) +#define IOCTL_GET_FW_BR_VERSION (SIOCDEVPRIVATE + 7) +#define IOCTL_BEGIN_FIRMWARE_UPGRADE (SIOCDEVPRIVATE + 8) +#define IOCTL_FIRMWARE_UPGRADE_DATA (SIOCDEVPRIVATE + 9) +#define IOCTL_END_FIRMWARE_UPGRADE (SIOCDEVPRIVATE + 10) +#define IOCTL_BEGIN_BOOT_ROM_UPGRADE (SIOCDEVPRIVATE + 11) +#define IOCTL_BOOT_ROM_UPGRADE_DATA (SIOCDEVPRIVATE + 12) +#define IOCTL_END_BOOT_ROM_UPGRADE (SIOCDEVPRIVATE + 13) + +#define IFR_DATA_OFFSET 0x100 +struct can_fw_resp { + u8 maj; + u8 min; + u8 ver[48]; +} __packed; + +struct can_write_req { + u8 can_if; + u32 mid; + u8 dlc; + u8 data[8]; +} __packed; + +struct can_write_resp { + u8 err; +} __packed; + +struct can_filter_req { + u8 can_if; + u32 mid; + u32 mask; +} __packed; + +struct can_add_filter_resp { + u8 err; +} __packed; + +struct can_receive_frame { + u8 can_if; + u32 ts; + u32 mid; + u8 dlc; + u8 data[8]; +} __packed; + +struct can_config_bit_timing { + u8 can_if; + u32 prop_seg; + u32 phase_seg1; + u32 phase_seg2; + u32 sjw; + u32 brp; +} __packed; + +static struct can_bittiming_const rh850_bittiming_const = { + .name = "qti_can", + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 16, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 70, + .brp_inc = 1, +}; + +static struct can_bittiming_const flexcan_bittiming_const = { + .name = "qti_can", + .tseg1_min = 4, + .tseg1_max = 16, + .tseg2_min = 2, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 256, + .brp_inc = 1, +}; + +static struct can_bittiming_const qti_can_bittiming_const; + +static struct can_bittiming_const qti_can_data_bittiming_const = { + .name = "qti_can", + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 16, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 70, + .brp_inc = 1, +}; + +struct vehicle_property { + int id; + u64 ts; + int zone; + int val_type; + u32 data_len; + union { + u8 bval; + int val; + int val_arr[4]; + float f_value; + float float_arr[4]; + u8 str[36]; + }; +} __packed; + +struct qti_can_release_can_buffer { + u8 enable; +} __packed; + +struct qti_can_buffer { + u8 can_if; + u32 mid; + u32 mask; +} __packed; + +struct can_fw_br_resp { + u8 maj; + u8 min; + u8 ver[32]; + u8 br_maj; + u8 br_min; + u8 curr_exec_mode; +} __packed; + +struct qti_can_ioctl_req { + u8 len; + u8 data[64]; +} __packed; + +static int qti_can_rx_message(struct qti_can *priv_data); + +static irqreturn_t qti_can_irq(int irq, void *priv) +{ + struct qti_can *priv_data = priv; + + LOGDI("qti_can_irq\n"); + qti_can_rx_message(priv_data); + return IRQ_HANDLED; +} + +static void qti_can_receive_frame(struct qti_can *priv_data, + struct can_receive_frame *frame) +{ + struct can_frame *cf; + struct sk_buff *skb; + struct skb_shared_hwtstamps *skt; + ktime_t nsec; + struct net_device *netdev; + int i; + struct device *dev; + + dev = &priv_data->spidev->dev; + if (frame->can_if >= priv_data->max_can_channels) { + LOGDE("qti_can rcv error. Channel is %d\n", frame->can_if); + return; + } + + netdev = priv_data->netdev[frame->can_if]; + skb = alloc_can_skb(netdev, &cf); + if (skb == NULL) { + LOGDE("skb alloc failed. frame->can_if %d\n", frame->can_if); + return; + } + + LOGDI("rcv frame %d %d %x %d %x %x %x %x %x %x %x %x\n", + frame->can_if, frame->ts, frame->mid, frame->dlc, + frame->data[0], frame->data[1], frame->data[2], frame->data[3], + frame->data[4], frame->data[5], frame->data[6], frame->data[7]); + cf->can_id = le32_to_cpu(frame->mid); + cf->can_dlc = get_can_dlc(frame->dlc); + + for (i = 0; i < cf->can_dlc; i++) + cf->data[i] = frame->data[i]; + + nsec = ms_to_ktime(le32_to_cpu(frame->ts)); + skt = skb_hwtstamps(skb); + skt->hwtstamp = nsec; + LOGDI(" hwtstamp %lld\n", ktime_to_ms(skt->hwtstamp)); + skb->tstamp = nsec; + netif_rx(skb); + netdev->stats.rx_packets++; +} + +static void qti_can_receive_property(struct qti_can *priv_data, + struct vehicle_property *property) +{ + struct canfd_frame *cfd; + u8 *p; + struct sk_buff *skb; + struct skb_shared_hwtstamps *skt; + ktime_t nsec; + struct net_device *netdev; + struct device *dev; + int i; + + /* can0 as the channel with properties */ + dev = &priv_data->spidev->dev; + netdev = priv_data->netdev[0]; + skb = alloc_canfd_skb(netdev, &cfd); + if (skb == NULL) { + LOGDE("skb alloc failed. frame->can_if %d\n", 0); + return; + } + + LOGDI("rcv property:0x%x data:%2x %2x %2x %2x", property->id, + property->str[0], property->str[1], + property->str[2], property->str[3]); + cfd->can_id = 0x00; + cfd->len = sizeof(struct vehicle_property); + + p = (u8 *)property; + for (i = 0; i < cfd->len; i++) + cfd->data[i] = p[i]; + + nsec = ns_to_ktime(le64_to_cpu(property->ts)); + skt = skb_hwtstamps(skb); + skt->hwtstamp = nsec; + LOGDI(" hwtstamp %lld\n", ktime_to_ms(skt->hwtstamp)); + skb->tstamp = nsec; + netif_rx(skb); + netdev->stats.rx_packets++; +} + +static int qti_can_process_response(struct qti_can *priv_data, + struct spi_miso *resp, int length) +{ + int ret = 0; + + LOGDI("<%x %2d [%d]\n", resp->cmd, resp->len, resp->seq); + if (resp->cmd == CMD_CAN_RECEIVE_FRAME) { + struct can_receive_frame *frame = + (struct can_receive_frame *)&resp->data; + if (resp->len > length) { + LOGDE("Error. This should never happen\n"); + LOGDE("process_response: Saving %d bytes\n", length); + memcpy(priv_data->assembly_buffer, (char *)resp, + length); + priv_data->assembly_buffer_size = length; + } else { + qti_can_receive_frame(priv_data, frame); + } + } else if (resp->cmd == CMD_PROPERTY_READ) { + struct vehicle_property *property = + (struct vehicle_property *)&resp->data; + if (resp->len > length) { + LOGDE("Error. This should never happen\n"); + LOGDE("process_response: Saving %d bytes\n", length); + memcpy(priv_data->assembly_buffer, (char *)resp, + length); + priv_data->assembly_buffer_size = length; + } else { + qti_can_receive_property(priv_data, property); + } + } else if (resp->cmd == CMD_GET_FW_VERSION) { + struct can_fw_resp *fw_resp = (struct can_fw_resp *)resp->data; + + dev_info(&priv_data->spidev->dev, "fw %d.%d", + fw_resp->maj, fw_resp->min); + dev_info(&priv_data->spidev->dev, "fw string %s", + fw_resp->ver); + } else if (resp->cmd == CMD_GET_FW_BR_VERSION) { + struct can_fw_br_resp *fw_resp = + (struct can_fw_br_resp *)resp->data; + dev_info(&priv_data->spidev->dev, "fw_can %d.%d", + fw_resp->maj, fw_resp->min); + dev_info(&priv_data->spidev->dev, "fw string %s", + fw_resp->ver); + dev_info(&priv_data->spidev->dev, "fw_br %d.%d exec_mode %d", + fw_resp->br_maj, fw_resp->br_min, + fw_resp->curr_exec_mode); + ret = fw_resp->curr_exec_mode << 28; + ret |= (fw_resp->br_maj & 0xF) << 24; + ret |= (fw_resp->br_min & 0xFF) << 16; + ret |= (fw_resp->maj & 0xF) << 8; + ret |= (fw_resp->min & 0xFF); + } + + if (resp->cmd == priv_data->wait_cmd) { + priv_data->cmd_result = ret; + complete(&priv_data->response_completion); + } + return ret; +} + +static int qti_can_process_rx(struct qti_can *priv_data, char *rx_buf) +{ + struct spi_miso *resp; + struct device *dev; + int length_processed = 0, actual_length = priv_data->xfer_length; + int ret = 0; + + dev = &priv_data->spidev->dev; + while (length_processed < actual_length) { + int length_left = actual_length - length_processed; + int length = 0; /* length of consumed chunk */ + void *data; + + if (priv_data->assembly_buffer_size > 0) { + LOGDI("callback: Reassembling %d bytes\n", + priv_data->assembly_buffer_size); + /* should copy just 1 byte instead, since cmd should */ + /* already been copied as being first byte */ + memcpy(priv_data->assembly_buffer + + priv_data->assembly_buffer_size, + rx_buf, 2); + data = priv_data->assembly_buffer; + resp = (struct spi_miso *)data; + length = resp->len + sizeof(*resp) + - priv_data->assembly_buffer_size; + if (length > 0) + memcpy(priv_data->assembly_buffer + + priv_data->assembly_buffer_size, + rx_buf, length); + length_left += priv_data->assembly_buffer_size; + priv_data->assembly_buffer_size = 0; + } else { + data = rx_buf + length_processed; + resp = (struct spi_miso *)data; + if (resp->cmd == 0) { + /* special case. ignore cmd==0 */ + length_processed += 1; + continue; + } + length = resp->len + sizeof(struct spi_miso); + } + LOGDI("processing. p %d -> l %d (t %d)\n", + length_processed, length_left, priv_data->xfer_length); + length_processed += length; + if (length_left >= sizeof(*resp) && + resp->len + sizeof(*resp) <= length_left) { + struct spi_miso *resp = + (struct spi_miso *)data; + ret = qti_can_process_response(priv_data, resp, + length_left); + } else if (length_left > 0) { + /* Not full message. Store however much we have for */ + /* later assembly */ + LOGDI("callback: Storing %d bytes of response\n", + length_left); + memcpy(priv_data->assembly_buffer, data, length_left); + priv_data->assembly_buffer_size = length_left; + break; + } + } + return ret; +} + +static int qti_can_do_spi_transaction(struct qti_can *priv_data) +{ + struct spi_device *spi; + struct spi_transfer *xfer; + struct spi_message *msg; + struct device *dev; + int ret; + + spi = priv_data->spidev; + dev = &spi->dev; + msg = devm_kzalloc(&spi->dev, sizeof(*msg), GFP_KERNEL); + xfer = devm_kzalloc(&spi->dev, sizeof(*xfer), GFP_KERNEL); + if ((NULL == xfer) || (NULL == msg)) + return -ENOMEM; + LOGDI(">%x %2d [%d]\n", priv_data->tx_buf[0], + priv_data->tx_buf[1], priv_data->tx_buf[2]); + spi_message_init(msg); + spi_message_add_tail(xfer, msg); + xfer->tx_buf = priv_data->tx_buf; + xfer->rx_buf = priv_data->rx_buf; + xfer->len = priv_data->xfer_length; + xfer->bits_per_word = priv_data->bits_per_word; + ret = spi_sync(spi, msg); + LOGDI("spi_sync ret %d data %x %x %x %x %x %x %x %x\n", ret, + priv_data->rx_buf[0], priv_data->rx_buf[1], + priv_data->rx_buf[2], priv_data->rx_buf[3], + priv_data->rx_buf[4], priv_data->rx_buf[5], + priv_data->rx_buf[6], priv_data->rx_buf[7]); + + if (ret == 0) + qti_can_process_rx(priv_data, priv_data->rx_buf); + devm_kfree(&spi->dev, msg); + devm_kfree(&spi->dev, xfer); + return ret; +} + +static int qti_can_rx_message(struct qti_can *priv_data) +{ + char *tx_buf, *rx_buf; + int ret; + + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + ret = qti_can_do_spi_transaction(priv_data); + mutex_unlock(&priv_data->spi_lock); + + return ret; +} + +static int qti_can_query_firmware_version(struct qti_can *priv_data) +{ + char *tx_buf, *rx_buf; + int ret; + struct spi_mosi *req; + + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + req = (struct spi_mosi *)tx_buf; + req->cmd = CMD_GET_FW_VERSION; + req->len = 0; + req->seq = atomic_inc_return(&priv_data->msg_seq); + + priv_data->wait_cmd = CMD_GET_FW_VERSION; + priv_data->cmd_result = -1; + reinit_completion(&priv_data->response_completion); + + ret = qti_can_do_spi_transaction(priv_data); + mutex_unlock(&priv_data->spi_lock); + + if (ret == 0) { + wait_for_completion_interruptible_timeout( + &priv_data->response_completion, + msecs_to_jiffies(QUERY_FIRMWARE_TIMEOUT_MS)); + ret = priv_data->cmd_result; + } + + return ret; +} + +static int qti_can_set_bitrate(struct net_device *netdev) +{ + char *tx_buf, *rx_buf; + int ret; + struct spi_mosi *req; + struct can_config_bit_timing *req_d; + struct qti_can *priv_data; + struct can_priv *priv = netdev_priv(netdev); + struct qti_can_netdev_privdata *qti_can_priv; + + qti_can_priv = netdev_priv(netdev); + priv_data = qti_can_priv->qti_can; + + netdev_info(netdev, "ch%i, bitrate setting>%i", + qti_can_priv->netdev_index, priv->bittiming.bitrate); + LOGNI("sjw>%i brp>%i ph_sg1>%i ph_sg2>%i smpl_pt>%i tq>%i pr_seg>%i", + priv->bittiming.sjw, priv->bittiming.brp, + priv->bittiming.phase_seg1, + priv->bittiming.phase_seg2, + priv->bittiming.sample_point, + priv->bittiming.tq, priv->bittiming.prop_seg); + + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + req = (struct spi_mosi *)tx_buf; + req->cmd = CMD_CAN_CONFIG_BIT_TIMING; + req->len = sizeof(struct can_config_bit_timing); + req->seq = atomic_inc_return(&priv_data->msg_seq); + req_d = (struct can_config_bit_timing *)req->data; + req_d->can_if = qti_can_priv->netdev_index; + req_d->prop_seg = priv->bittiming.prop_seg; + req_d->phase_seg1 = priv->bittiming.phase_seg1; + req_d->phase_seg2 = priv->bittiming.phase_seg2; + req_d->sjw = priv->bittiming.sjw; + req_d->brp = priv->bittiming.brp; + ret = qti_can_do_spi_transaction(priv_data); + mutex_unlock(&priv_data->spi_lock); + + return ret; +} + +static int qti_can_write(struct qti_can *priv_data, + int can_channel, struct canfd_frame *cf) +{ + char *tx_buf, *rx_buf; + int ret, i; + struct spi_mosi *req; + struct can_write_req *req_d; + struct net_device *netdev; + + if (can_channel < 0 || can_channel >= priv_data->max_can_channels) { + LOGDE("qti_can_write error. Channel is %d\n", can_channel); + return -EINVAL; + } + + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + req = (struct spi_mosi *)tx_buf; + if (priv_data->driver_mode == DRIVER_MODE_RAW_FRAMES) { + req->cmd = CMD_CAN_SEND_FRAME; + req->len = sizeof(struct can_write_req) + 8; + req->seq = atomic_inc_return(&priv_data->msg_seq); + + req_d = (struct can_write_req *)req->data; + req_d->can_if = can_channel; + req_d->mid = cf->can_id; + req_d->dlc = cf->len; + + for (i = 0; i < cf->len; i++) + req_d->data[i] = cf->data[i]; + } else if (priv_data->driver_mode == DRIVER_MODE_PROPERTIES || + priv_data->driver_mode == DRIVER_MODE_AMB) { + req->cmd = CMD_PROPERTY_WRITE; + req->len = sizeof(struct vehicle_property); + req->seq = atomic_inc_return(&priv_data->msg_seq); + for (i = 0; i < cf->len; i++) + req->data[i] = cf->data[i]; + } else { + LOGDE("qti_can_write: wrong driver mode %i", + priv_data->driver_mode); + } + + ret = qti_can_do_spi_transaction(priv_data); + netdev = priv_data->netdev[can_channel]; + netdev->stats.tx_packets++; + mutex_unlock(&priv_data->spi_lock); + + return ret; +} + +static int qti_can_netdev_open(struct net_device *netdev) +{ + int err; + + LOGNI("Open"); + err = open_candev(netdev); + if (err) + return err; + + netif_start_queue(netdev); + + return 0; +} + +static int qti_can_netdev_close(struct net_device *netdev) +{ + LOGNI("Close"); + + netif_stop_queue(netdev); + close_candev(netdev); + return 0; +} + +static void qti_can_send_can_frame(struct work_struct *ws) +{ + struct qti_can_tx_work *tx_work; + struct canfd_frame *cf; + struct qti_can *priv_data; + struct net_device *netdev; + struct qti_can_netdev_privdata *netdev_priv_data; + int can_channel; + + tx_work = container_of(ws, struct qti_can_tx_work, work); + netdev = tx_work->netdev; + netdev_priv_data = netdev_priv(netdev); + priv_data = netdev_priv_data->qti_can; + can_channel = netdev_priv_data->netdev_index; + + LOGDI("send_can_frame ws %pK\n", ws); + LOGDI("send_can_frame tx %pK\n", tx_work); + + cf = (struct canfd_frame *)tx_work->skb->data; + qti_can_write(priv_data, can_channel, cf); + + dev_kfree_skb(tx_work->skb); + kfree(tx_work); +} + +static netdev_tx_t qti_can_netdev_start_xmit( + struct sk_buff *skb, struct net_device *netdev) +{ + struct qti_can_netdev_privdata *netdev_priv_data = netdev_priv(netdev); + struct qti_can *priv_data = netdev_priv_data->qti_can; + struct qti_can_tx_work *tx_work; + + LOGNI("netdev_start_xmit"); + if (can_dropped_invalid_skb(netdev, skb)) { + LOGNE("Dropping invalid can frame\n"); + return NETDEV_TX_OK; + } + tx_work = kzalloc(sizeof(*tx_work), GFP_ATOMIC); + if (NULL == tx_work) + return NETDEV_TX_OK; + INIT_WORK(&tx_work->work, qti_can_send_can_frame); + tx_work->netdev = netdev; + tx_work->skb = skb; + queue_work(priv_data->tx_wq, &tx_work->work); + + return NETDEV_TX_OK; +} + +static int qti_can_send_release_can_buffer_cmd(struct net_device *netdev) +{ + char *tx_buf, *rx_buf; + int ret; + struct spi_mosi *req; + struct qti_can *priv_data; + struct qti_can_netdev_privdata *netdev_priv_data; + int *mode; + + netdev_priv_data = netdev_priv(netdev); + priv_data = netdev_priv_data->qti_can; + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + req = (struct spi_mosi *)tx_buf; + req->cmd = CMD_CAN_RELEASE_BUFFER; + req->len = sizeof(int); + req->seq = atomic_inc_return(&priv_data->msg_seq); + mode = (int *)req->data; + *mode = priv_data->driver_mode; + + ret = qti_can_do_spi_transaction(priv_data); + mutex_unlock(&priv_data->spi_lock); + return ret; +} + +static int qti_can_data_buffering(struct net_device *netdev, + struct ifreq *ifr, int cmd) +{ + char *tx_buf, *rx_buf; + int ret; + u32 timeout; + struct spi_mosi *req; + struct qti_can_buffer *enable_buffering; + struct qti_can_buffer *add_request; + struct qti_can *priv_data; + struct qti_can_netdev_privdata *netdev_priv_data; + struct spi_device *spi; + + netdev_priv_data = netdev_priv(netdev); + priv_data = netdev_priv_data->qti_can; + spi = priv_data->spidev; + timeout = priv_data->can_fw_cmd_timeout_ms; + + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + if (!ifr) + return -EINVAL; + add_request = devm_kzalloc(&spi->dev, + sizeof(struct qti_can_buffer), + GFP_KERNEL); + if (!add_request) + return -ENOMEM; + + if (copy_from_user(add_request, ifr->ifr_data, + sizeof(struct qti_can_buffer))) { + devm_kfree(&spi->dev, add_request); + return -EFAULT; + } + + req = (struct spi_mosi *)tx_buf; + if (IOCTL_ENABLE_BUFFERING == cmd) + req->cmd = CMD_CAN_DATA_BUFF_ADD; + else + req->cmd = CMD_CAN_DATA_BUFF_REMOVE; + req->len = sizeof(struct qti_can_buffer); + req->seq = atomic_inc_return(&priv_data->msg_seq); + + enable_buffering = (struct qti_can_buffer *)req->data; + enable_buffering->can_if = add_request->can_if; + enable_buffering->mid = add_request->mid; + enable_buffering->mask = add_request->mask; + + if (priv_data->can_fw_cmd_timeout_req) { + priv_data->wait_cmd = req->cmd; + priv_data->cmd_result = -1; + reinit_completion(&priv_data->response_completion); + } + + ret = qti_can_do_spi_transaction(priv_data); + devm_kfree(&spi->dev, add_request); + mutex_unlock(&priv_data->spi_lock); + + if (ret == 0 && priv_data->can_fw_cmd_timeout_req) { + LOGDI("qti_can_data_buffering ready to wait for response\n"); + ret = wait_for_completion_interruptible_timeout( + &priv_data->response_completion, + msecs_to_jiffies(timeout)); + ret = priv_data->cmd_result; + } + return ret; +} + +static int qti_can_remove_all_buffering(struct net_device *netdev) +{ + char *tx_buf, *rx_buf; + int ret; + u32 timeout; + struct spi_mosi *req; + struct qti_can *priv_data; + struct qti_can_netdev_privdata *netdev_priv_data; + + netdev_priv_data = netdev_priv(netdev); + priv_data = netdev_priv_data->qti_can; + timeout = priv_data->rem_all_buffering_timeout_ms; + + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + req = (struct spi_mosi *)tx_buf; + req->cmd = CMD_CAN_DATA_BUFF_REMOVE_ALL; + req->len = 0; + req->seq = atomic_inc_return(&priv_data->msg_seq); + + if (priv_data->can_fw_cmd_timeout_req) { + priv_data->wait_cmd = req->cmd; + priv_data->cmd_result = -1; + reinit_completion(&priv_data->response_completion); + } + + ret = qti_can_do_spi_transaction(priv_data); + mutex_unlock(&priv_data->spi_lock); + + if (ret == 0 && priv_data->can_fw_cmd_timeout_req) { + LOGDI("qti_can_remove_all_buffering wait for response\n"); + ret = wait_for_completion_interruptible_timeout( + &priv_data->response_completion, + msecs_to_jiffies(timeout)); + ret = priv_data->cmd_result; + } + + return ret; +} + +static int qti_can_frame_filter(struct net_device *netdev, + struct ifreq *ifr, int cmd) +{ + char *tx_buf, *rx_buf; + int ret; + struct spi_mosi *req; + struct can_filter_req *add_filter; + struct can_filter_req *filter_request; + struct qti_can *priv_data; + struct qti_can_netdev_privdata *netdev_priv_data; + struct spi_device *spi; + + netdev_priv_data = netdev_priv(netdev); + priv_data = netdev_priv_data->qti_can; + spi = priv_data->spidev; + + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + if (!ifr) + return -EINVAL; + + filter_request = + devm_kzalloc(&spi->dev, sizeof(struct can_filter_req), + GFP_KERNEL); + if (!filter_request) + return -ENOMEM; + + if (copy_from_user(filter_request, ifr->ifr_data, + sizeof(struct can_filter_req))) { + devm_kfree(&spi->dev, filter_request); + return -EFAULT; + } + + req = (struct spi_mosi *)tx_buf; + if (IOCTL_ADD_FRAME_FILTER == cmd) + req->cmd = CMD_CAN_ADD_FILTER; + else + req->cmd = CMD_CAN_REMOVE_FILTER; + + req->len = sizeof(struct can_filter_req); + req->seq = atomic_inc_return(&priv_data->msg_seq); + + add_filter = (struct can_filter_req *)req->data; + add_filter->can_if = filter_request->can_if; + add_filter->mid = filter_request->mid; + add_filter->mask = filter_request->mask; + + ret = qti_can_do_spi_transaction(priv_data); + devm_kfree(&spi->dev, filter_request); + mutex_unlock(&priv_data->spi_lock); + return ret; +} + +static int qti_can_send_spi_locked(struct qti_can *priv_data, int cmd, int len, + u8 *data) +{ + char *tx_buf, *rx_buf; + struct spi_mosi *req; + int ret; + + LOGDI("qti_can_send_spi_locked\n"); + + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + req = (struct spi_mosi *)tx_buf; + req->cmd = cmd; + req->len = len; + req->seq = atomic_inc_return(&priv_data->msg_seq); + + if (unlikely(len > 64)) + return -EINVAL; + memcpy(req->data, data, len); + + ret = qti_can_do_spi_transaction(priv_data); + return ret; +} + +static int qti_can_convert_ioctl_cmd_to_spi_cmd(int ioctl_cmd) +{ + switch (ioctl_cmd) { + case IOCTL_GET_FW_BR_VERSION: + return CMD_GET_FW_BR_VERSION; + case IOCTL_BEGIN_FIRMWARE_UPGRADE: + return CMD_BEGIN_FIRMWARE_UPGRADE; + case IOCTL_FIRMWARE_UPGRADE_DATA: + return CMD_FIRMWARE_UPGRADE_DATA; + case IOCTL_END_FIRMWARE_UPGRADE: + return CMD_END_FIRMWARE_UPGRADE; + case IOCTL_BEGIN_BOOT_ROM_UPGRADE: + return CMD_BEGIN_BOOT_ROM_UPGRADE; + case IOCTL_BOOT_ROM_UPGRADE_DATA: + return CMD_BOOT_ROM_UPGRADE_DATA; + case IOCTL_END_BOOT_ROM_UPGRADE: + return CMD_END_BOOT_ROM_UPGRADE; + } + return -EINVAL; +} + +static int qti_can_do_blocking_ioctl(struct net_device *netdev, + struct ifreq *ifr, int cmd) +{ + int spi_cmd, ret; + + struct qti_can *priv_data; + struct qti_can_netdev_privdata *netdev_priv_data; + struct qti_can_ioctl_req *ioctl_data = NULL; + struct spi_device *spi; + int len = 0; + u8 *data = NULL; + + netdev_priv_data = netdev_priv(netdev); + priv_data = netdev_priv_data->qti_can; + spi = priv_data->spidev; + + spi_cmd = qti_can_convert_ioctl_cmd_to_spi_cmd(cmd); + LOGDI("qti_can_do_blocking_ioctl spi_cmd %x\n", spi_cmd); + if (spi_cmd < 0) { + LOGDE("qti_can_do_blocking_ioctl wrong command %d\n", cmd); + return spi_cmd; + } + + if (!ifr) + return -EINVAL; + + mutex_lock(&priv_data->spi_lock); + if (spi_cmd == CMD_FIRMWARE_UPGRADE_DATA || + spi_cmd == CMD_BOOT_ROM_UPGRADE_DATA) { + ioctl_data = + devm_kzalloc(&spi->dev, + sizeof(struct qti_can_ioctl_req), + GFP_KERNEL); + if (!ioctl_data) + return -ENOMEM; + + if (copy_from_user(ioctl_data, ifr->ifr_data, + sizeof(struct qti_can_ioctl_req))) { + devm_kfree(&spi->dev, ioctl_data); + return -EFAULT; + } + + /* Regular NULL check will fail here as ioctl_data is at + * some offset + */ + if ((void *)ioctl_data > (void *)0x100) { + len = ioctl_data->len; + data = ioctl_data->data; + } + } + LOGDI("qti_can_do_blocking_ioctl len %d\n", len); + + priv_data->wait_cmd = spi_cmd; + priv_data->cmd_result = -1; + reinit_completion(&priv_data->response_completion); + + ret = qti_can_send_spi_locked(priv_data, spi_cmd, len, data); + if (ioctl_data) + devm_kfree(&spi->dev, ioctl_data); + mutex_unlock(&priv_data->spi_lock); + + if (ret == 0) { + LOGDI("qti_can_do_blocking_ioctl ready to wait for response\n"); + wait_for_completion_interruptible_timeout( + &priv_data->response_completion, + 5 * HZ); + ret = priv_data->cmd_result; + } + return ret; +} + +static int qti_can_netdev_do_ioctl(struct net_device *netdev, + struct ifreq *ifr, int cmd) +{ + struct qti_can *priv_data; + struct qti_can_netdev_privdata *netdev_priv_data; + int *mode; + int ret = -EINVAL; + struct spi_device *spi; + + netdev_priv_data = netdev_priv(netdev); + priv_data = netdev_priv_data->qti_can; + spi = priv_data->spidev; + LOGDI("qti_can_netdev_do_ioctl %x\n", cmd); + + switch (cmd) { + case IOCTL_RELEASE_CAN_BUFFER: + if (!ifr) + return -EINVAL; + + /* Regular NULL check will fail here as ioctl_data is at + * some offset + */ + if (ifr->ifr_data > (void __user *)IFR_DATA_OFFSET) { + mutex_lock(&priv_data->spi_lock); + mode = devm_kzalloc(&spi->dev, sizeof(int), GFP_KERNEL); + if (!mode) + return -ENOMEM; + if (copy_from_user(mode, ifr->ifr_data, sizeof(int))) { + devm_kfree(&spi->dev, mode); + return -EFAULT; + } + priv_data->driver_mode = *mode; + LOGDE("qti_can_driver_mode %d\n", + priv_data->driver_mode); + devm_kfree(&spi->dev, mode); + mutex_unlock(&priv_data->spi_lock); + } + qti_can_send_release_can_buffer_cmd(netdev); + ret = 0; + break; + case IOCTL_ENABLE_BUFFERING: + case IOCTL_DISABLE_BUFFERING: + qti_can_data_buffering(netdev, ifr, cmd); + ret = 0; + break; + case IOCTL_DISABLE_ALL_BUFFERING: + qti_can_remove_all_buffering(netdev); + ret = 0; + break; + case IOCTL_ADD_FRAME_FILTER: + case IOCTL_REMOVE_FRAME_FILTER: + qti_can_frame_filter(netdev, ifr, cmd); + ret = 0; + break; + case IOCTL_GET_FW_BR_VERSION: + case IOCTL_BEGIN_FIRMWARE_UPGRADE: + case IOCTL_FIRMWARE_UPGRADE_DATA: + case IOCTL_END_FIRMWARE_UPGRADE: + case IOCTL_BEGIN_BOOT_ROM_UPGRADE: + case IOCTL_BOOT_ROM_UPGRADE_DATA: + case IOCTL_END_BOOT_ROM_UPGRADE: + ret = qti_can_do_blocking_ioctl(netdev, ifr, cmd); + break; + } + LOGDI("qti_can_netdev_do_ioctl ret %d\n", ret); + + return ret; +} + +static const struct net_device_ops qti_can_netdev_ops = { + .ndo_open = qti_can_netdev_open, + .ndo_stop = qti_can_netdev_close, + .ndo_start_xmit = qti_can_netdev_start_xmit, + .ndo_do_ioctl = qti_can_netdev_do_ioctl, +}; + +static int qti_can_create_netdev(struct spi_device *spi, + struct qti_can *priv_data, int index) +{ + struct net_device *netdev; + struct qti_can_netdev_privdata *netdev_priv_data; + + LOGDI("qti_can_create_netdev %d\n", index); + if (index < 0 || index >= priv_data->max_can_channels) { + LOGDE("qti_can_create_netdev wrong index %d\n", index); + return -EINVAL; + } + netdev = alloc_candev(sizeof(*netdev_priv_data), MAX_TX_BUFFERS); + if (!netdev) { + LOGDE("Couldn't alloc candev\n"); + return -ENOMEM; + } + + netdev->mtu = CANFD_MTU; + + netdev_priv_data = netdev_priv(netdev); + netdev_priv_data->qti_can = priv_data; + netdev_priv_data->netdev_index = index; + + priv_data->netdev[index] = netdev; + + netdev->netdev_ops = &qti_can_netdev_ops; + SET_NETDEV_DEV(netdev, &spi->dev); + netdev_priv_data->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_LISTENONLY; + if (priv_data->support_can_fd) + netdev_priv_data->can.ctrlmode_supported |= CAN_CTRLMODE_FD; + netdev_priv_data->can.bittiming_const = &qti_can_bittiming_const; + netdev_priv_data->can.data_bittiming_const = + &qti_can_data_bittiming_const; + netdev_priv_data->can.clock.freq = priv_data->clk_freq_mhz; + netdev_priv_data->can.do_set_bittiming = qti_can_set_bitrate; + + return 0; +} + +static struct qti_can *qti_can_create_priv_data(struct spi_device *spi) +{ + struct qti_can *priv_data; + int err; + struct device *dev; + + dev = &spi->dev; + priv_data = kzalloc(sizeof(*priv_data), GFP_KERNEL); + if (!priv_data) { + err = -ENOMEM; + return NULL; + } + spi_set_drvdata(spi, priv_data); + atomic_set(&priv_data->netif_queue_stop, 0); + priv_data->spidev = spi; + priv_data->assembly_buffer = kzalloc(RX_ASSEMBLY_BUFFER_SIZE, + GFP_KERNEL); + if (!priv_data->assembly_buffer) { + err = -ENOMEM; + goto cleanup_privdata; + } + + priv_data->tx_wq = alloc_workqueue("qti_can_tx_wq", 0, 0); + if (!priv_data->tx_wq) { + LOGDE("Couldn't alloc workqueue\n"); + err = -ENOMEM; + goto cleanup_privdata; + } + + priv_data->tx_buf = kzalloc(XFER_BUFFER_SIZE, + GFP_KERNEL); + priv_data->rx_buf = kzalloc(XFER_BUFFER_SIZE, + GFP_KERNEL); + if (!priv_data->tx_buf || !priv_data->rx_buf) { + LOGDE("Couldn't alloc tx or rx buffers\n"); + err = -ENOMEM; + goto cleanup_privdata; + } + priv_data->xfer_length = 0; + priv_data->driver_mode = DRIVER_MODE_RAW_FRAMES; + + mutex_init(&priv_data->spi_lock); + atomic_set(&priv_data->msg_seq, 0); + init_completion(&priv_data->response_completion); + return priv_data; + +cleanup_privdata: + if (priv_data) { + if (priv_data->tx_wq) + destroy_workqueue(priv_data->tx_wq); + kfree(priv_data->rx_buf); + kfree(priv_data->tx_buf); + kfree(priv_data->assembly_buffer); + kfree(priv_data); + } + return NULL; +} + +static const struct of_device_id qti_can_match_table[] = { + { .compatible = "qcom,renesas,rh850" }, + { .compatible = "qcom,nxp,mpc5746c" }, + { } +}; + +static int qti_can_probe(struct spi_device *spi) +{ + int err, retry = 0, query_err = -1, i; + struct qti_can *priv_data = NULL; + struct device *dev; + + dev = &spi->dev; + dev_info(dev, "qti_can_probe"); + + err = spi_setup(spi); + if (err) { + dev_err(dev, "spi_setup failed: %d", err); + return err; + } + + priv_data = qti_can_create_priv_data(spi); + if (!priv_data) { + dev_err(dev, "Failed to create qti_can priv_data\n"); + err = -ENOMEM; + return err; + } + dev_info(dev, "qti_can_probe created priv_data"); + + err = of_property_read_u32(spi->dev.of_node, "qcom,clk-freq-mhz", + &priv_data->clk_freq_mhz); + if (err) { + LOGDE("DT property: qcom,clk-freq-hz not defined\n"); + return err; + } + + err = of_property_read_u32(spi->dev.of_node, "qcom,max-can-channels", + &priv_data->max_can_channels); + if (err) { + LOGDE("DT property: qcom,max-can-channels not defined\n"); + return err; + } + + err = of_property_read_u32(spi->dev.of_node, "qcom,bits-per-word", + &priv_data->bits_per_word); + if (err) + priv_data->bits_per_word = 16; + + err = of_property_read_u32(spi->dev.of_node, "qcom,reset-delay-msec", + &priv_data->reset_delay_msec); + if (err) + priv_data->reset_delay_msec = 1; + + priv_data->can_fw_cmd_timeout_req = + of_property_read_bool(spi->dev.of_node, + "qcom,can-fw-cmd-timeout-req"); + + err = of_property_read_u32(spi->dev.of_node, + "qcom,can-fw-cmd-timeout-ms", + &priv_data->can_fw_cmd_timeout_ms); + if (err) + priv_data->can_fw_cmd_timeout_ms = 0; + + err = of_property_read_u32(spi->dev.of_node, + "qcom,rem-all-buffering-timeout-ms", + &priv_data->rem_all_buffering_timeout_ms); + if (err) + priv_data->rem_all_buffering_timeout_ms = 0; + + priv_data->reset = of_get_named_gpio(spi->dev.of_node, + "qcom,reset-gpio", 0); + + if (gpio_is_valid(priv_data->reset)) { + err = gpio_request(priv_data->reset, "qti-can-reset"); + if (err < 0) { + LOGDE("failed to request gpio %d: %d\n", + priv_data->reset, err); + return err; + } + + gpio_direction_output(priv_data->reset, 0); + udelay(1); + gpio_direction_output(priv_data->reset, 1); + msleep(priv_data->reset_delay_msec); + } + + priv_data->support_can_fd = of_property_read_bool(spi->dev.of_node, + "support-can-fd"); + + if (of_device_is_compatible(spi->dev.of_node, "qcom,nxp,mpc5746c")) + qti_can_bittiming_const = flexcan_bittiming_const; + else if (of_device_is_compatible(spi->dev.of_node, + "qcom,renesas,rh850")) + qti_can_bittiming_const = rh850_bittiming_const; + + priv_data->netdev = kzalloc(sizeof(priv_data->netdev[0]) * + priv_data->max_can_channels, + GFP_KERNEL); + if (!priv_data->netdev) { + err = -ENOMEM; + return err; + } + + for (i = 0; i < priv_data->max_can_channels; i++) { + err = qti_can_create_netdev(spi, priv_data, i); + if (err) { + LOGDE("Failed to create CAN device: %d", err); + goto cleanup_candev; + } + + err = register_candev(priv_data->netdev[i]); + if (err) { + LOGDE("Failed to register CAN device: %d", err); + goto unregister_candev; + } + } + + err = request_threaded_irq(spi->irq, NULL, qti_can_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "qti-can", priv_data); + if (err) { + LOGDE("Failed to request irq: %d", err); + goto unregister_candev; + } + dev_info(dev, "Request irq %d ret %d\n", spi->irq, err); + + while ((query_err != 0) && (retry < QTI_CAN_FW_QUERY_RETRY_COUNT)) { + query_err = qti_can_query_firmware_version(priv_data); + priv_data->assembly_buffer_size = 0; + retry++; + } + + if (query_err) { + LOGDE("QTI CAN probe failed\n"); + err = -ENODEV; + goto free_irq; + } + return 0; + +free_irq: + free_irq(spi->irq, priv_data); +unregister_candev: + for (i = 0; i < priv_data->max_can_channels; i++) + unregister_candev(priv_data->netdev[i]); +cleanup_candev: + if (priv_data) { + for (i = 0; i < priv_data->max_can_channels; i++) { + if (priv_data->netdev[i]) + free_candev(priv_data->netdev[i]); + } + if (priv_data->tx_wq) + destroy_workqueue(priv_data->tx_wq); + kfree(priv_data->rx_buf); + kfree(priv_data->tx_buf); + kfree(priv_data->assembly_buffer); + kfree(priv_data->netdev); + kfree(priv_data); + } + return err; +} + +static int qti_can_remove(struct spi_device *spi) +{ + struct qti_can *priv_data = spi_get_drvdata(spi); + int i; + + LOGDI("qti_can_remove\n"); + for (i = 0; i < priv_data->max_can_channels; i++) { + unregister_candev(priv_data->netdev[i]); + free_candev(priv_data->netdev[i]); + } + destroy_workqueue(priv_data->tx_wq); + kfree(priv_data->rx_buf); + kfree(priv_data->tx_buf); + kfree(priv_data->assembly_buffer); + kfree(priv_data->netdev); + kfree(priv_data); + return 0; +} + +#ifdef CONFIG_PM +static int qti_can_suspend(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + + enable_irq_wake(spi->irq); + return 0; +} + +static int qti_can_resume(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + struct qti_can *priv_data = spi_get_drvdata(spi); + + disable_irq_wake(spi->irq); + qti_can_rx_message(priv_data); + return 0; +} + +static const struct dev_pm_ops qti_can_dev_pm_ops = { + .suspend = qti_can_suspend, + .resume = qti_can_resume, +}; +#endif + +static struct spi_driver qti_can_driver = { + .driver = { + .name = "qti-can", + .of_match_table = qti_can_match_table, + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &qti_can_dev_pm_ops, +#endif + }, + .probe = qti_can_probe, + .remove = qti_can_remove, +}; +module_spi_driver(qti_can_driver); + +MODULE_DESCRIPTION("QTI CAN controller module"); +MODULE_LICENSE("GPL v2"); From 72eb8a715adc30400436412a56667553eef0b322 Mon Sep 17 00:00:00 2001 From: Abinaya P Date: Tue, 2 Jan 2018 14:46:24 +0530 Subject: [PATCH 164/508] ARM: dts: msm: Add DT changes for QTI CAN driver for MDM9650 and APQ8096 Add CAN device for MDM9650, APQ8096 and msm8996 auto variants using the QTI CAN driver for nxp mpc5746 and Renesas RH850. Change-Id: I501dbd29bf3e9eb7300244c0f51dfa051a72ec08 Signed-off-by: Abinaya P Signed-off-by: Balachandra C S --- .../boot/dts/qcom/apq8096-v2-auto-dragonboard.dts | 8 ++++++-- arch/arm/boot/dts/qcom/apq8096-v3-auto-adp.dts | 8 ++++++-- arch/arm/boot/dts/qcom/apq8096-v3-auto-cdp.dts | 8 ++++++-- .../boot/dts/qcom/apq8096-v3-auto-dragonboard.dts | 8 ++++++-- arch/arm/boot/dts/qcom/apq8096pro-auto-cdp.dts | 8 ++++++-- .../boot/dts/qcom/apq8096pro-v1.1-auto-adp.dts | 8 ++++++-- .../boot/dts/qcom/apq8096pro-v1.1-auto-cdp.dts | 8 ++++++-- arch/arm/boot/dts/qcom/mdm9650-ccard.dtsi | 15 ++++++++++----- arch/arm/boot/dts/qcom/msm8996-v3-auto-adp.dts | 8 ++++++-- arch/arm/boot/dts/qcom/msm8996-v3-auto-cdp.dts | 8 ++++++-- .../boot/dts/qcom/msm8996-v3-pm8004-agave-adp.dts | 8 ++++++-- arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts | 8 ++++++-- arch/arm/boot/dts/qcom/msm8996pro-auto-cdp.dts | 8 ++++++-- .../boot/dts/qcom/msm8996pro-v1.1-auto-cdp.dts | 8 ++++++-- 14 files changed, 88 insertions(+), 31 deletions(-) diff --git a/arch/arm/boot/dts/qcom/apq8096-v2-auto-dragonboard.dts b/arch/arm/boot/dts/qcom/apq8096-v2-auto-dragonboard.dts index d200bf718de28..c21b6d6cbc9e1 100644 --- a/arch/arm/boot/dts/qcom/apq8096-v2-auto-dragonboard.dts +++ b/arch/arm/boot/dts/qcom/apq8096-v2-auto-dragonboard.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -27,10 +27,14 @@ &spi_9 { status = "ok"; can-controller@0 { - compatible = "renesas,rh850"; + compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; interrupts = <127 0>; spi-max-frequency = <5000000>; + qcom,clk-freq-mhz = <16000000>; + qcom,max-can-channels = <4>; + qcom,bits-per-word = <8>; + qcom,support-can-fd; }; }; diff --git a/arch/arm/boot/dts/qcom/apq8096-v3-auto-adp.dts b/arch/arm/boot/dts/qcom/apq8096-v3-auto-adp.dts index a91ec5eeb2e74..74bb21eedf10e 100644 --- a/arch/arm/boot/dts/qcom/apq8096-v3-auto-adp.dts +++ b/arch/arm/boot/dts/qcom/apq8096-v3-auto-adp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -27,11 +27,15 @@ &spi_9 { status = "ok"; can-controller@0 { - compatible = "renesas,rh850"; + compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; interrupts = <122 0>; spi-max-frequency = <5000000>; + qcom,clk-freq-mhz = <16000000>; + qcom,max-can-channels = <4>; + qcom,bits-per-word = <8>; + qcom,support-can-fd; }; }; diff --git a/arch/arm/boot/dts/qcom/apq8096-v3-auto-cdp.dts b/arch/arm/boot/dts/qcom/apq8096-v3-auto-cdp.dts index e59003f2d3161..82030c493f8d1 100644 --- a/arch/arm/boot/dts/qcom/apq8096-v3-auto-cdp.dts +++ b/arch/arm/boot/dts/qcom/apq8096-v3-auto-cdp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -35,10 +35,14 @@ &spi_9 { status = "ok"; can-controller@0 { - compatible = "renesas,rh850"; + compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; interrupts = <127 0>; spi-max-frequency = <5000000>; + qcom,clk-freq-mhz = <16000000>; + qcom,max-can-channels = <4>; + qcom,bits-per-word = <8>; + qcom,support-can-fd; }; }; diff --git a/arch/arm/boot/dts/qcom/apq8096-v3-auto-dragonboard.dts b/arch/arm/boot/dts/qcom/apq8096-v3-auto-dragonboard.dts index 0638332f57f87..cd02dacbdcee9 100644 --- a/arch/arm/boot/dts/qcom/apq8096-v3-auto-dragonboard.dts +++ b/arch/arm/boot/dts/qcom/apq8096-v3-auto-dragonboard.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -27,11 +27,15 @@ &spi_9 { status = "ok"; can-controller@0 { - compatible = "renesas,rh850"; + compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; interrupts = <127 0>; spi-max-frequency = <5000000>; + qcom,clk-freq-mhz = <16000000>; + qcom,max-can-channels = <4>; + qcom,bits-per-word = <8>; + qcom,support-can-fd; }; }; diff --git a/arch/arm/boot/dts/qcom/apq8096pro-auto-cdp.dts b/arch/arm/boot/dts/qcom/apq8096pro-auto-cdp.dts index d438bbe828ed1..e2d4f2b9babe2 100644 --- a/arch/arm/boot/dts/qcom/apq8096pro-auto-cdp.dts +++ b/arch/arm/boot/dts/qcom/apq8096pro-auto-cdp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -27,11 +27,15 @@ &spi_9 { status = "ok"; can-controller@0 { - compatible = "renesas,rh850"; + compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; interrupts = <127 0>; spi-max-frequency = <5000000>; + qcom,clk-freq-mhz = <16000000>; + qcom,max-can-channels = <4>; + qcom,bits-per-word = <8>; + qcom,support-can-fd; }; }; diff --git a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp.dts b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp.dts index 497f3f10fe24f..fdea81eb93224 100644 --- a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp.dts +++ b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -28,11 +28,15 @@ &spi_9 { status = "ok"; can-controller@0 { - compatible = "renesas,rh850"; + compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; interrupts = <122 0>; spi-max-frequency = <5000000>; + qcom,clk-freq-mhz = <16000000>; + qcom,max-can-channels = <4>; + qcom,bits-per-word = <8>; + qcom,support-can-fd; }; }; diff --git a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-cdp.dts b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-cdp.dts index 2c54dfe19e182..d5eb6031e3787 100644 --- a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-cdp.dts +++ b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-cdp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -27,11 +27,15 @@ &spi_9 { status = "ok"; can-controller@0 { - compatible = "renesas,rh850"; + compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; interrupts = <127 0>; spi-max-frequency = <5000000>; + qcom,clk-freq-mhz = <16000000>; + qcom,max-can-channels = <4>; + qcom,bits-per-word = <8>; + qcom,support-can-fd; }; }; diff --git a/arch/arm/boot/dts/qcom/mdm9650-ccard.dtsi b/arch/arm/boot/dts/qcom/mdm9650-ccard.dtsi index 03b3bd4cfcd0f..3ab680127d643 100644 --- a/arch/arm/boot/dts/qcom/mdm9650-ccard.dtsi +++ b/arch/arm/boot/dts/qcom/mdm9650-ccard.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -609,14 +609,19 @@ /delete-property/ qcom,use-bam; can-controller@0 { - compatible = "nxp,mpc5746c"; + compatible = "qcom,nxp,mpc5746c"; reg = <0>; spi-max-frequency = <9600000>; interrupt-parent = <&tlmm_pinmux>; interrupts = <87 0>; - reset-gpio = <&tlmm_pinmux 89 0x1>; - bits-per-word = <8>; - reset-delay-msec = <100>; + qcom,reset-gpio = <&tlmm_pinmux 89 0x1>; + qcom,clk-freq-mhz = <20000000>; + qcom,max-can-channels = <1>; + qcom,bits-per-word = <8>; + qcom,reset-delay-msec = <200>; + qcom,can-fw-cmd-timeout-req; + qcom,can-fw-cmd-timeout-ms = <400>; + qcom,rem-all-buffering-timeout-ms = <2000>; pinctrl-names = "active", "sleep"; pinctrl-0 = <&can_rst_on>; pinctrl-1 = <&can_rst_off>; diff --git a/arch/arm/boot/dts/qcom/msm8996-v3-auto-adp.dts b/arch/arm/boot/dts/qcom/msm8996-v3-auto-adp.dts index 68956d71b74de..d4cf58f9b8eae 100644 --- a/arch/arm/boot/dts/qcom/msm8996-v3-auto-adp.dts +++ b/arch/arm/boot/dts/qcom/msm8996-v3-auto-adp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -28,11 +28,15 @@ &spi_9 { status = "ok"; can-controller@0 { - compatible = "renesas,rh850"; + compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; interrupts = <122 0>; spi-max-frequency = <5000000>; + qcom,clk-freq-mhz = <16000000>; + qcom,max-can-channels = <4>; + qcom,bits-per-word = <8>; + qcom,support-can-fd; }; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-v3-auto-cdp.dts b/arch/arm/boot/dts/qcom/msm8996-v3-auto-cdp.dts index 8ca2b30b37798..33daf9d6f0e70 100644 --- a/arch/arm/boot/dts/qcom/msm8996-v3-auto-cdp.dts +++ b/arch/arm/boot/dts/qcom/msm8996-v3-auto-cdp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -40,10 +40,14 @@ &spi_9 { status = "ok"; can-controller@0 { - compatible = "renesas,rh850"; + compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; interrupts = <127 0>; spi-max-frequency = <5000000>; + qcom,clk-freq-mhz = <16000000>; + qcom,max-can-channels = <4>; + qcom,bits-per-word = <8>; + qcom,support-can-fd; }; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-v3-pm8004-agave-adp.dts b/arch/arm/boot/dts/qcom/msm8996-v3-pm8004-agave-adp.dts index 1d7cc028336bc..d84b0d781b291 100644 --- a/arch/arm/boot/dts/qcom/msm8996-v3-pm8004-agave-adp.dts +++ b/arch/arm/boot/dts/qcom/msm8996-v3-pm8004-agave-adp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -25,11 +25,15 @@ &spi_9 { status = "ok"; can-controller@0 { - compatible = "renesas,rh850"; + compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; interrupts = <122 0>; spi-max-frequency = <5000000>; + qcom,clk-freq-mhz = <16000000>; + qcom,max-can-channels = <4>; + qcom,bits-per-word = <8>; + qcom,support-can-fd; }; }; diff --git a/arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts b/arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts index 7f6f3d5d4a4cb..15b00af5f0f42 100644 --- a/arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts +++ b/arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -28,11 +28,15 @@ &spi_9 { status = "ok"; can-controller@0 { - compatible = "renesas,rh850"; + compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; interrupts = <122 0>; spi-max-frequency = <5000000>; + qcom,clk-freq-mhz = <16000000>; + qcom,max-can-channels = <4>; + qcom,bits-per-word = <8>; + qcom,support-can-fd; }; }; diff --git a/arch/arm/boot/dts/qcom/msm8996pro-auto-cdp.dts b/arch/arm/boot/dts/qcom/msm8996pro-auto-cdp.dts index e104be7c2742f..4a78a2fef835e 100644 --- a/arch/arm/boot/dts/qcom/msm8996pro-auto-cdp.dts +++ b/arch/arm/boot/dts/qcom/msm8996pro-auto-cdp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -27,11 +27,15 @@ &spi_9 { status = "ok"; can-controller@0 { - compatible = "renesas,rh850"; + compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; interrupts = <127 0>; spi-max-frequency = <5000000>; + qcom,clk-freq-mhz = <16000000>; + qcom,max-can-channels = <4>; + qcom,bits-per-word = <8>; + qcom,support-can-fd; }; }; diff --git a/arch/arm/boot/dts/qcom/msm8996pro-v1.1-auto-cdp.dts b/arch/arm/boot/dts/qcom/msm8996pro-v1.1-auto-cdp.dts index 06d040aa6bcb5..d75f56d12291b 100644 --- a/arch/arm/boot/dts/qcom/msm8996pro-v1.1-auto-cdp.dts +++ b/arch/arm/boot/dts/qcom/msm8996pro-v1.1-auto-cdp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -27,11 +27,15 @@ &spi_9 { status = "ok"; can-controller@0 { - compatible = "renesas,rh850"; + compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; interrupts = <127 0>; spi-max-frequency = <5000000>; + qcom,clk-freq-mhz = <16000000>; + qcom,max-can-channels = <4>; + qcom,bits-per-word = <8>; + qcom,support-can-fd; }; }; From 2f7b4b25071184d05b9bd3d24e276c096d61e5cf Mon Sep 17 00:00:00 2001 From: Balachandra C S Date: Tue, 6 Mar 2018 18:29:29 +0530 Subject: [PATCH 165/508] net: can: Remove the RH850 CAN driver Remove RH850 driver as the unified QTI CAN controller driver will replace it supporting multiple vendor's CAN controllers. Change-Id: I1b9791b9b1a84ccb6f6d7fbfaca72be6cc7dd25f Signed-off-by: Balachandra C S --- .../devicetree/bindings/net/can/rh850-can.txt | 21 - arch/arm64/configs/msm-auto-perf_defconfig | 1 - arch/arm64/configs/msm-auto_defconfig | 1 - drivers/net/can/spi/Kconfig | 6 - drivers/net/can/spi/Makefile | 1 - drivers/net/can/spi/rh850.c | 1199 ----------------- 6 files changed, 1229 deletions(-) delete mode 100644 Documentation/devicetree/bindings/net/can/rh850-can.txt delete mode 100644 drivers/net/can/spi/rh850.c diff --git a/Documentation/devicetree/bindings/net/can/rh850-can.txt b/Documentation/devicetree/bindings/net/can/rh850-can.txt deleted file mode 100644 index f16171e5b855f..0000000000000 --- a/Documentation/devicetree/bindings/net/can/rh850-can.txt +++ /dev/null @@ -1,21 +0,0 @@ -* Renesas RH850 CAN * - -This driver implements spi slave protocol for rh850 can controller - -Required properties: - - compatible: Should be "renesas,rh850" - - reg: Should contain spi chip select - - interrupt-parent: Should specify interrupt controller for the interrupt - - interrupts: Should contain IRQ line for the CAN controller - - spi-max-frequency: Should contain maximum spi clock frequency for - slave device - -Example: - - can-controller@0 { - compatible = "renesas,rh850"; - reg = <0>; - interrupt-parent = <&tlmm>; - interrupts = <127 0>; - spi-max-frequency = <5000000>; - }; diff --git a/arch/arm64/configs/msm-auto-perf_defconfig b/arch/arm64/configs/msm-auto-perf_defconfig index 7009811101da3..3db3d67f6f9c3 100644 --- a/arch/arm64/configs/msm-auto-perf_defconfig +++ b/arch/arm64/configs/msm-auto-perf_defconfig @@ -213,7 +213,6 @@ CONFIG_RMNET_DATA_DEBUG_PKT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_CAN=y CONFIG_CAN_VCAN=y -CONFIG_CAN_RH850=y CONFIG_CAN_PEAK_USB=y CONFIG_BT=y CONFIG_BT_RFCOMM=y diff --git a/arch/arm64/configs/msm-auto_defconfig b/arch/arm64/configs/msm-auto_defconfig index 987ed4f8e46cb..636b90fa033c0 100644 --- a/arch/arm64/configs/msm-auto_defconfig +++ b/arch/arm64/configs/msm-auto_defconfig @@ -214,7 +214,6 @@ CONFIG_RMNET_DATA_DEBUG_PKT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_CAN=y CONFIG_CAN_VCAN=y -CONFIG_CAN_RH850=y CONFIG_CAN_PEAK_USB=y CONFIG_BT=y CONFIG_BT_RFCOMM=y diff --git a/drivers/net/can/spi/Kconfig b/drivers/net/can/spi/Kconfig index e6b3862230b99..a11c5d93ca34f 100644 --- a/drivers/net/can/spi/Kconfig +++ b/drivers/net/can/spi/Kconfig @@ -7,12 +7,6 @@ config CAN_MCP251X ---help--- Driver for the Microchip MCP251x SPI CAN controllers. -config CAN_RH850 - tristate "Renesas RH850 SPI CAN controller" - depends on HAS_DMA - ---help--- - Driver for the Renesas RH850 SPI CAN controller. - config CAN_K61 tristate "Freescale K61 SPI CAN controllers" depends on SPI diff --git a/drivers/net/can/spi/Makefile b/drivers/net/can/spi/Makefile index c1951ccc00345..d4fcb03a3a88c 100644 --- a/drivers/net/can/spi/Makefile +++ b/drivers/net/can/spi/Makefile @@ -4,6 +4,5 @@ obj-$(CONFIG_CAN_MCP251X) += mcp251x.o -obj-$(CONFIG_CAN_RH850) += rh850.o obj-${CONFIG_CAN_K61} += k61.o obj-$(CONFIG_QTI_CAN) += qti-can.o diff --git a/drivers/net/can/spi/rh850.c b/drivers/net/can/spi/rh850.c deleted file mode 100644 index 62857ec445a26..0000000000000 --- a/drivers/net/can/spi/rh850.c +++ /dev/null @@ -1,1199 +0,0 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEBUG_RH850 0 -#if DEBUG_RH850 == 1 -#define LOGDI(...) dev_info(&priv_data->spidev->dev, __VA_ARGS__) -#define LOGNI(...) netdev_info(netdev, __VA_ARGS__) -#else -#define LOGDI(...) -#define LOGNI(...) -#endif -#define LOGDE(...) dev_err(&priv_data->spidev->dev, __VA_ARGS__) -#define LOGNE(...) netdev_err(netdev, __VA_ARGS__) - -#define MAX_TX_BUFFERS 1 -#define XFER_BUFFER_SIZE 64 -#define RX_ASSEMBLY_BUFFER_SIZE 128 -#define RH850_CLOCK 16000000 -#define RH850_MAX_CHANNELS 4 -#define DRIVER_MODE_RAW_FRAMES 0 -#define DRIVER_MODE_PROPERTIES 1 -#define DRIVER_MODE_AMB 2 - -struct rh850_can { - struct net_device *netdev[RH850_MAX_CHANNELS]; - struct spi_device *spidev; - - struct mutex spi_lock; /* SPI device lock */ - - struct workqueue_struct *tx_wq; - char *tx_buf, *rx_buf; - int xfer_length; - atomic_t msg_seq; - - char *assembly_buffer; - u8 assembly_buffer_size; - atomic_t netif_queue_stop; - struct completion response_completion; - int wait_cmd; - int cmd_result; - int driver_mode; -}; - -struct rh850_netdev_privdata { - struct can_priv can; - struct rh850_can *rh850_can; - u8 netdev_index; -}; - -struct rh850_tx_work { - struct work_struct work; - struct sk_buff *skb; - struct net_device *netdev; -}; - -/* Message definitions */ -struct spi_mosi { /* TLV for MOSI line */ - u8 cmd; - u8 len; - u16 seq; - u8 data[]; -} __packed; - -struct spi_miso { /* TLV for MISO line */ - u8 cmd; - u8 len; - u16 seq; /* should match seq field from request, or 0 for unsols */ - u8 data[]; -} __packed; - -#define CMD_GET_FW_VERSION 0x81 -#define CMD_CAN_SEND_FRAME 0x82 -#define CMD_CAN_ADD_FILTER 0x83 -#define CMD_CAN_REMOVE_FILTER 0x84 -#define CMD_CAN_RECEIVE_FRAME 0x85 -#define CMD_CAN_CONFIG_BIT_TIMING 0x86 - -#define CMD_CAN_DATA_BUFF_ADD 0x87 -#define CMD_CAN_DATA_BUFF_REMOVE 0X88 -#define CMD_CAN_RELEASE_BUFFER 0x89 -#define CMD_CAN_DATA_BUFF_REMOVE_ALL 0x8A -#define CMD_PROPERTY_WRITE 0x8B -#define CMD_PROPERTY_READ 0x8C - -#define CMD_GET_FW_BR_VERSION 0x95 -#define CMD_BEGIN_FIRMWARE_UPGRADE 0x96 -#define CMD_FIRMWARE_UPGRADE_DATA 0x97 -#define CMD_END_FIRMWARE_UPGRADE 0x98 -#define CMD_BEGIN_BOOT_ROM_UPGRADE 0x99 -#define CMD_BOOT_ROM_UPGRADE_DATA 0x9A -#define CMD_END_BOOT_ROM_UPGRADE 0x9B - -#define IOCTL_RELEASE_CAN_BUFFER (SIOCDEVPRIVATE + 0) -#define IOCTL_ENABLE_BUFFERING (SIOCDEVPRIVATE + 1) -#define IOCTL_ADD_FRAME_FILTER (SIOCDEVPRIVATE + 2) -#define IOCTL_REMOVE_FRAME_FILTER (SIOCDEVPRIVATE + 3) -#define IOCTL_DISABLE_BUFFERING (SIOCDEVPRIVATE + 5) -#define IOCTL_DISABLE_ALL_BUFFERING (SIOCDEVPRIVATE + 6) -#define IOCTL_GET_FW_BR_VERSION (SIOCDEVPRIVATE + 7) -#define IOCTL_BEGIN_FIRMWARE_UPGRADE (SIOCDEVPRIVATE + 8) -#define IOCTL_FIRMWARE_UPGRADE_DATA (SIOCDEVPRIVATE + 9) -#define IOCTL_END_FIRMWARE_UPGRADE (SIOCDEVPRIVATE + 10) -#define IOCTL_BEGIN_BOOT_ROM_UPGRADE (SIOCDEVPRIVATE + 11) -#define IOCTL_BOOT_ROM_UPGRADE_DATA (SIOCDEVPRIVATE + 12) -#define IOCTL_END_BOOT_ROM_UPGRADE (SIOCDEVPRIVATE + 13) - -struct can_fw_resp { - u8 maj; - u8 min; - u8 ver[32]; -} __packed; - -struct can_write_req { - u8 can_if; - u32 mid; - u8 dlc; - u8 data[]; -} __packed; - -struct can_write_resp { - u8 err; -} __packed; - -struct can_add_filter_req { - u8 can_if; - u32 mid; - u32 mask; -} __packed; - -struct can_add_filter_resp { - u8 err; -} __packed; - -struct can_remove_filter_req { - u8 can_if; - u32 mid; - u32 mask; -} __packed; - -struct can_receive_frame { - u8 can_if; - u32 ts; - u32 mid; - u8 dlc; - u8 data[]; -} __packed; - -struct can_config_bit_timing { - u8 can_if; - u32 brp; - u32 tseg1; - u32 tseg2; - u32 sjw; -} __packed; - -struct vehicle_property { - int id; - u64 ts; - int zone; - int val_type; - u32 data_len; - union { - u8 bval; - int val; - int val_arr[4]; - float f_value; - float float_arr[4]; - u8 str[36]; - }; -} __packed; - -/* IOCTL messages */ -struct rh850_release_can_buffer { - u8 enable; -} __packed; - -struct rh850_add_can_buffer { - u8 can_if; - u32 mid; - u32 mask; -} __packed; - -struct rh850_delete_can_buffer { - u8 can_if; - u32 mid; - u32 mask; -} __packed; - -struct can_fw_br_resp { - u8 maj; - u8 min; - u8 ver[32]; - u8 br_maj; - u8 br_min; - u8 curr_exec_mode; -} __packed; - -struct rh850_ioctl_req { - u8 len; - u8 data[]; -} __packed; - -static struct can_bittiming_const rh850_bittiming_const = { - .name = "rh850", - .tseg1_min = 1, - .tseg1_max = 16, - .tseg2_min = 1, - .tseg2_max = 16, - .sjw_max = 4, - .brp_min = 1, - .brp_max = 70, - .brp_inc = 1, -}; - -static struct can_bittiming_const rh850_data_bittiming_const = { - .name = "rh850", - .tseg1_min = 1, - .tseg1_max = 16, - .tseg2_min = 1, - .tseg2_max = 16, - .sjw_max = 4, - .brp_min = 1, - .brp_max = 70, - .brp_inc = 1, -}; - -static int rh850_rx_message(struct rh850_can *priv_data); - -static irqreturn_t rh850_irq(int irq, void *priv) -{ - struct rh850_can *priv_data = priv; - - LOGDI("rh850_irq\n"); - rh850_rx_message(priv_data); - return IRQ_HANDLED; -} - -static void rh850_receive_frame(struct rh850_can *priv_data, - struct can_receive_frame *frame) -{ - struct can_frame *cf; - struct sk_buff *skb; - struct skb_shared_hwtstamps *skt; - struct timeval tv; - static int msec; - struct net_device *netdev; - int i; - if (frame->can_if >= RH850_MAX_CHANNELS) { - LOGDE("rh850 rcv error. Channel is %d\n", frame->can_if); - return; - } - netdev = priv_data->netdev[frame->can_if]; - skb = alloc_can_skb(netdev, &cf); - if (skb == NULL) { - LOGDE("skb alloc failed. frame->can_if %d\n", frame->can_if); - return; - } - - LOGDI("rcv frame %d %d %x %d %x %x %x %x %x %x %x %x\n", - frame->can_if, frame->ts, frame->mid, frame->dlc, frame->data[0], - frame->data[1], frame->data[2], frame->data[3], frame->data[4], - frame->data[5], frame->data[6], frame->data[7]); - cf->can_id = le32_to_cpu(frame->mid); - cf->can_dlc = get_can_dlc(frame->dlc); - - for (i = 0; i < cf->can_dlc; i++) - cf->data[i] = frame->data[i]; - - msec = le32_to_cpu(frame->ts); - tv.tv_sec = msec / 1000; - tv.tv_usec = (msec - tv.tv_sec * 1000) * 1000; - skt = skb_hwtstamps(skb); - skt->hwtstamp = timeval_to_ktime(tv); - LOGDI(" hwtstamp %lld\n", ktime_to_ms(skt->hwtstamp)); - skb->tstamp = timeval_to_ktime(tv); - netif_rx(skb); - netdev->stats.rx_packets++; -} - -static void rh850_receive_property(struct rh850_can *priv_data, - struct vehicle_property *property) -{ - struct canfd_frame *cfd; - u8 *p; - struct sk_buff *skb; - struct skb_shared_hwtstamps *skt; - struct timeval tv; - static u64 nanosec; - struct net_device *netdev; - int i; - - /* can0 as the channel with properties */ - netdev = priv_data->netdev[0]; - skb = alloc_canfd_skb(netdev, &cfd); - if (skb == NULL) { - LOGDE("skb alloc failed. frame->can_if %d\n", 0); - return; - } - - LOGDI("rcv property:0x%x data:%2x %2x %2x %2x", - property->id, property->str[0], property->str[1], - property->str[2], property->str[3]); - cfd->can_id = 0x00; - cfd->len = sizeof(struct vehicle_property); - - p = (u8 *)property; - for (i = 0; i < cfd->len; i++) - cfd->data[i] = p[i]; - - nanosec = le64_to_cpu(property->ts); - tv.tv_sec = (int)(nanosec / 1000000000); - tv.tv_usec = (int)(nanosec - (u64)tv.tv_sec * 1000000000) / 1000; - skt = skb_hwtstamps(skb); - skt->hwtstamp = timeval_to_ktime(tv); - LOGDI(" hwtstamp %lld\n", ktime_to_ms(skt->hwtstamp)); - skb->tstamp = timeval_to_ktime(tv); - netif_rx(skb); - netdev->stats.rx_packets++; -} - -static int rh850_process_response(struct rh850_can *priv_data, - struct spi_miso *resp, int length) -{ - int ret = 0; - LOGDI("<%x %2d [%d]\n", resp->cmd, resp->len, resp->seq); - if (resp->cmd == CMD_CAN_RECEIVE_FRAME) { - struct can_receive_frame *frame = - (struct can_receive_frame *)&resp->data; - if (resp->len > length) { - LOGDE("Error. This should never happen\n"); - LOGDE("process_response: Saving %d bytes\n", - length); - memcpy(priv_data->assembly_buffer, (char *)resp, - length); - priv_data->assembly_buffer_size = length; - } else { - rh850_receive_frame(priv_data, frame); - } - } else if (resp->cmd == CMD_PROPERTY_READ) { - struct vehicle_property *property = - (struct vehicle_property *)&resp->data; - if (resp->len > length) { - LOGDE("Error. This should never happen\n"); - LOGDE("process_response: Saving %d bytes\n", - length); - memcpy(priv_data->assembly_buffer, (char *)resp, - length); - priv_data->assembly_buffer_size = length; - } else { - rh850_receive_property(priv_data, property); - } - } else if (resp->cmd == CMD_GET_FW_VERSION) { - struct can_fw_resp *fw_resp = (struct can_fw_resp *)resp->data; - dev_info(&priv_data->spidev->dev, "fw %d.%d", - fw_resp->maj, fw_resp->min); - dev_info(&priv_data->spidev->dev, "fw string %s", - fw_resp->ver); - } else if (resp->cmd == CMD_GET_FW_BR_VERSION) { - struct can_fw_br_resp *fw_resp = - (struct can_fw_br_resp *)resp->data; - - dev_info(&priv_data->spidev->dev, "fw_can %d.%d", - fw_resp->maj, fw_resp->min); - dev_info(&priv_data->spidev->dev, "fw string %s", - fw_resp->ver); - dev_info(&priv_data->spidev->dev, "fw_br %d.%d exec_mode %d", - fw_resp->br_maj, fw_resp->br_min, - fw_resp->curr_exec_mode); - ret = fw_resp->curr_exec_mode << 28; - ret |= (fw_resp->br_maj & 0xF) << 24; - ret |= (fw_resp->br_min & 0xFF) << 16; - ret |= (fw_resp->maj & 0xF) << 8; - ret |= (fw_resp->min & 0xFF); - } - - if (resp->cmd == priv_data->wait_cmd) { - priv_data->cmd_result = ret; - complete(&priv_data->response_completion); - } - return ret; -} - -static int rh850_process_rx(struct rh850_can *priv_data, char *rx_buf) -{ - struct spi_miso *resp; - int length_processed = 0, actual_length = priv_data->xfer_length; - int ret = 0; - - while (length_processed < actual_length) { - int length_left = actual_length - length_processed; - int length = 0; /* length of consumed chunk */ - void *data; - - if (priv_data->assembly_buffer_size > 0) { - LOGDI("callback: Reassembling %d bytes\n", - priv_data->assembly_buffer_size); - /* should copy just 1 byte instead, since cmd should */ - /* already been copied as being first byte */ - memcpy(priv_data->assembly_buffer + - priv_data->assembly_buffer_size, - rx_buf, 2); - data = priv_data->assembly_buffer; - resp = (struct spi_miso *)data; - length = resp->len + sizeof(*resp) - - priv_data->assembly_buffer_size; - if (length > 0) - memcpy(priv_data->assembly_buffer + - priv_data->assembly_buffer_size, - rx_buf, length); - length_left += priv_data->assembly_buffer_size; - priv_data->assembly_buffer_size = 0; - } else { - data = rx_buf + length_processed; - resp = (struct spi_miso *)data; - if (resp->cmd == 0) { - /* special case. ignore cmd==0 */ - length_processed += 1; - continue; - } - length = resp->len + sizeof(struct spi_miso); - } - LOGDI("processing. p %d -> l %d (t %d)\n", - length_processed, length_left, priv_data->xfer_length); - length_processed += length; - if (length_left >= sizeof(*resp) && - resp->len + sizeof(*resp) <= length_left) { - struct spi_miso *resp = - (struct spi_miso *)data; - ret = rh850_process_response(priv_data, resp, - length_left); - } else if (length_left > 0) { - /* Not full message. Store however much we have for */ - /* later assembly */ - LOGDI("callback: Storing %d bytes of response\n", - length_left); - memcpy(priv_data->assembly_buffer, data, length_left); - priv_data->assembly_buffer_size = length_left; - break; - } - } - return ret; -} - -static int rh850_do_spi_transaction(struct rh850_can *priv_data) -{ - struct spi_device *spi; - struct spi_transfer *xfer; - struct spi_message *msg; - int ret; - - spi = priv_data->spidev; - xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); - msg = kzalloc(sizeof(*msg), GFP_KERNEL); - if (xfer == 0 || msg == 0) - return -ENOMEM; - LOGDI(">%x %2d [%d]\n", priv_data->tx_buf[0], - priv_data->tx_buf[1], priv_data->tx_buf[2]); - spi_message_init(msg); - spi_message_add_tail(xfer, msg); - xfer->tx_buf = priv_data->tx_buf; - xfer->rx_buf = priv_data->rx_buf; - xfer->len = priv_data->xfer_length; - ret = spi_sync(spi, msg); - LOGDI("spi_sync ret %d data %x %x %x %x %x %x %x %x\n", ret, - priv_data->rx_buf[0], priv_data->rx_buf[1], priv_data->rx_buf[2], - priv_data->rx_buf[3], priv_data->rx_buf[4], priv_data->rx_buf[5], - priv_data->rx_buf[6], priv_data->rx_buf[7]); - if (ret == 0) - ret = rh850_process_rx(priv_data, priv_data->rx_buf); - kfree(msg); - kfree(xfer); - return ret; -} - -static int rh850_rx_message(struct rh850_can *priv_data) -{ - char *tx_buf, *rx_buf; - int ret; - - mutex_lock(&priv_data->spi_lock); - tx_buf = priv_data->tx_buf; - rx_buf = priv_data->rx_buf; - memset(tx_buf, 0, XFER_BUFFER_SIZE); - memset(rx_buf, 0, XFER_BUFFER_SIZE); - priv_data->xfer_length = XFER_BUFFER_SIZE; - - ret = rh850_do_spi_transaction(priv_data); - mutex_unlock(&priv_data->spi_lock); - - return ret; -} - -static int rh850_query_firmware_version(struct rh850_can *priv_data) -{ - char *tx_buf, *rx_buf; - int ret; - struct spi_mosi *req; - - mutex_lock(&priv_data->spi_lock); - tx_buf = priv_data->tx_buf; - rx_buf = priv_data->rx_buf; - memset(tx_buf, 0, XFER_BUFFER_SIZE); - memset(rx_buf, 0, XFER_BUFFER_SIZE); - priv_data->xfer_length = XFER_BUFFER_SIZE; - - req = (struct spi_mosi *)tx_buf; - req->cmd = CMD_GET_FW_VERSION; - req->len = 0; - req->seq = atomic_inc_return(&priv_data->msg_seq); - - ret = rh850_do_spi_transaction(priv_data); - mutex_unlock(&priv_data->spi_lock); - - return ret; -} - -static int rh850_set_bitrate(struct net_device *netdev) -{ - char *tx_buf, *rx_buf; - int ret; - struct spi_mosi *req; - struct can_config_bit_timing *req_d; - struct rh850_can *priv_data; - struct can_priv *priv = netdev_priv(netdev); - struct rh850_netdev_privdata *rh850_priv; - - rh850_priv = netdev_priv(netdev); - priv_data = rh850_priv->rh850_can; - - netdev_info(netdev, "ch%i, bitrate setting>%i", - rh850_priv->netdev_index, priv->bittiming.bitrate); - LOGNI("sjw>%i brp>%i ph_sg1>%i ph_sg2>%i smpl_pt>%i tq>%i pr_seg>%i", - priv->bittiming.sjw, priv->bittiming.brp, - priv->bittiming.phase_seg1, - priv->bittiming.phase_seg2, - priv->bittiming.sample_point, - priv->bittiming.tq, priv->bittiming.prop_seg); - - mutex_lock(&priv_data->spi_lock); - tx_buf = priv_data->tx_buf; - rx_buf = priv_data->rx_buf; - memset(tx_buf, 0, XFER_BUFFER_SIZE); - memset(rx_buf, 0, XFER_BUFFER_SIZE); - priv_data->xfer_length = XFER_BUFFER_SIZE; - - req = (struct spi_mosi *)tx_buf; - req->cmd = CMD_CAN_CONFIG_BIT_TIMING; - req->len = sizeof(struct can_config_bit_timing); - req->seq = atomic_inc_return(&priv_data->msg_seq); - req_d = (struct can_config_bit_timing *)req->data; - req_d->can_if = rh850_priv->netdev_index; - req_d->brp = priv->bittiming.brp; - req_d->tseg1 = priv->bittiming.phase_seg1 + priv->bittiming.prop_seg; - req_d->tseg2 = priv->bittiming.phase_seg2; - req_d->sjw = priv->bittiming.sjw; - - ret = rh850_do_spi_transaction(priv_data); - mutex_unlock(&priv_data->spi_lock); - - return ret; -} - -static int rh850_can_write(struct rh850_can *priv_data, - int can_channel, struct canfd_frame *cf) -{ - char *tx_buf, *rx_buf; - int ret, i; - struct spi_mosi *req; - struct can_write_req *req_d; - struct net_device *netdev; - - if (can_channel < 0 || can_channel >= RH850_MAX_CHANNELS) { - LOGDE("rh850_can_write error. Channel is %d\n", can_channel); - return -EINVAL; - } - - mutex_lock(&priv_data->spi_lock); - tx_buf = priv_data->tx_buf; - rx_buf = priv_data->rx_buf; - memset(tx_buf, 0, XFER_BUFFER_SIZE); - memset(rx_buf, 0, XFER_BUFFER_SIZE); - priv_data->xfer_length = XFER_BUFFER_SIZE; - - req = (struct spi_mosi *)tx_buf; - if (priv_data->driver_mode == DRIVER_MODE_RAW_FRAMES) { - req->cmd = CMD_CAN_SEND_FRAME; - req->len = sizeof(struct can_write_req) + 8; - req->seq = atomic_inc_return(&priv_data->msg_seq); - - req_d = (struct can_write_req *)req->data; - req_d->can_if = can_channel; - req_d->mid = cf->can_id; - req_d->dlc = cf->len; - - for (i = 0; i < cf->len; i++) - req_d->data[i] = cf->data[i]; - } else if (priv_data->driver_mode == DRIVER_MODE_PROPERTIES || - priv_data->driver_mode == DRIVER_MODE_AMB) { - req->cmd = CMD_PROPERTY_WRITE; - req->len = sizeof(struct vehicle_property); - req->seq = atomic_inc_return(&priv_data->msg_seq); - for (i = 0; i < cf->len; i++) - req->data[i] = cf->data[i]; - } else { - LOGDE("rh850_can_write: wrong driver mode %i", - priv_data->driver_mode); - } - - ret = rh850_do_spi_transaction(priv_data); - netdev = priv_data->netdev[can_channel]; - netdev->stats.tx_packets++; - mutex_unlock(&priv_data->spi_lock); - - return ret; -} - -static int rh850_netdev_open(struct net_device *netdev) -{ - int err; - - LOGNI("Open"); - err = open_candev(netdev); - if (err) - return err; - - netif_start_queue(netdev); - - return 0; -} - -static int rh850_netdev_close(struct net_device *netdev) -{ - LOGNI("Close"); - - netif_stop_queue(netdev); - close_candev(netdev); - return 0; -} - -static void rh850_send_can_frame(struct work_struct *ws) -{ - struct rh850_tx_work *tx_work; - struct canfd_frame *cf; - struct rh850_can *priv_data; - struct net_device *netdev; - struct rh850_netdev_privdata *netdev_priv_data; - int can_channel; - - tx_work = container_of(ws, struct rh850_tx_work, work); - netdev = tx_work->netdev; - netdev_priv_data = netdev_priv(netdev); - priv_data = netdev_priv_data->rh850_can; - can_channel = netdev_priv_data->netdev_index; - LOGDI("send_can_frame ws %p\n", ws); - LOGDI("send_can_frame tx %p\n", tx_work); - - cf = (struct canfd_frame *)tx_work->skb->data; - rh850_can_write(priv_data, can_channel, cf); - - dev_kfree_skb(tx_work->skb); - kfree(tx_work); -} - -static netdev_tx_t rh850_netdev_start_xmit( - struct sk_buff *skb, struct net_device *netdev) -{ - struct rh850_netdev_privdata *netdev_priv_data = netdev_priv(netdev); - struct rh850_can *priv_data = netdev_priv_data->rh850_can; - struct rh850_tx_work *tx_work; - - LOGNI("netdev_start_xmit"); - if (can_dropped_invalid_skb(netdev, skb)) { - LOGNE("Dropping invalid can frame\n"); - return NETDEV_TX_OK; - } - tx_work = kzalloc(sizeof(*tx_work), GFP_ATOMIC); - if (tx_work == 0) - return NETDEV_TX_OK; - INIT_WORK(&tx_work->work, rh850_send_can_frame); - tx_work->netdev = netdev; - tx_work->skb = skb; - queue_work(priv_data->tx_wq, &tx_work->work); - - return NETDEV_TX_OK; -} - -static int rh850_send_release_can_buffer_cmd(struct net_device *netdev) -{ - char *tx_buf, *rx_buf; - int ret; - struct spi_mosi *req; - struct rh850_can *priv_data; - struct rh850_netdev_privdata *netdev_priv_data; - int *mode; - - netdev_priv_data = netdev_priv(netdev); - priv_data = netdev_priv_data->rh850_can; - mutex_lock(&priv_data->spi_lock); - tx_buf = priv_data->tx_buf; - rx_buf = priv_data->rx_buf; - memset(tx_buf, 0, XFER_BUFFER_SIZE); - memset(rx_buf, 0, XFER_BUFFER_SIZE); - priv_data->xfer_length = XFER_BUFFER_SIZE; - - req = (struct spi_mosi *)tx_buf; - req->cmd = CMD_CAN_RELEASE_BUFFER; - req->len = sizeof(int); - req->seq = atomic_inc_return(&priv_data->msg_seq); - mode = (int *)req->data; - *mode = priv_data->driver_mode; - - ret = rh850_do_spi_transaction(priv_data); - mutex_unlock(&priv_data->spi_lock); - - return ret; -} - -static int rh850_data_buffering(struct net_device *netdev, - struct ifreq *ifr, int cmd) -{ - char *tx_buf, *rx_buf; - int ret; - struct spi_mosi *req; - struct rh850_add_can_buffer *enable_buffering; - struct rh850_add_can_buffer *add_request; - struct rh850_can *priv_data; - struct rh850_netdev_privdata *netdev_priv_data; - - netdev_priv_data = netdev_priv(netdev); - priv_data = netdev_priv_data->rh850_can; - - mutex_lock(&priv_data->spi_lock); - tx_buf = priv_data->tx_buf; - rx_buf = priv_data->rx_buf; - memset(tx_buf, 0, XFER_BUFFER_SIZE); - memset(rx_buf, 0, XFER_BUFFER_SIZE); - priv_data->xfer_length = XFER_BUFFER_SIZE; - - add_request = ifr->ifr_data; - req = (struct spi_mosi *)tx_buf; - if (IOCTL_ENABLE_BUFFERING == cmd) - req->cmd = CMD_CAN_DATA_BUFF_ADD; - else - req->cmd = CMD_CAN_DATA_BUFF_REMOVE; - req->len = sizeof(struct rh850_add_can_buffer); - req->seq = atomic_inc_return(&priv_data->msg_seq); - - enable_buffering = (struct rh850_add_can_buffer *)req->data; - enable_buffering->can_if = add_request->can_if; - enable_buffering->mid = add_request->mid; - enable_buffering->mask = add_request->mask; - - ret = rh850_do_spi_transaction(priv_data); - mutex_unlock(&priv_data->spi_lock); - - return ret; -} - -static int rh850_remove_all_buffering(struct net_device *netdev) -{ - char *tx_buf, *rx_buf; - int ret; - struct spi_mosi *req; - struct rh850_can *priv_data; - struct rh850_netdev_privdata *netdev_priv_data; - - netdev_priv_data = netdev_priv(netdev); - priv_data = netdev_priv_data->rh850_can; - - mutex_lock(&priv_data->spi_lock); - tx_buf = priv_data->tx_buf; - rx_buf = priv_data->rx_buf; - memset(tx_buf, 0, XFER_BUFFER_SIZE); - memset(rx_buf, 0, XFER_BUFFER_SIZE); - priv_data->xfer_length = XFER_BUFFER_SIZE; - - req = (struct spi_mosi *)tx_buf; - req->cmd = CMD_CAN_DATA_BUFF_REMOVE_ALL; - req->len = 0; - req->seq = atomic_inc_return(&priv_data->msg_seq); - - ret = rh850_do_spi_transaction(priv_data); - mutex_unlock(&priv_data->spi_lock); - - return ret; -} - -static int rh850_frame_filter(struct net_device *netdev, - struct ifreq *ifr, int cmd) -{ - char *tx_buf, *rx_buf; - int ret; - struct spi_mosi *req; - struct can_add_filter_req *add_filter; - struct can_add_filter_req *filter_request; - struct rh850_can *priv_data; - struct rh850_netdev_privdata *netdev_priv_data; - - netdev_priv_data = netdev_priv(netdev); - priv_data = netdev_priv_data->rh850_can; - - mutex_lock(&priv_data->spi_lock); - tx_buf = priv_data->tx_buf; - rx_buf = priv_data->rx_buf; - memset(tx_buf, 0, XFER_BUFFER_SIZE); - memset(rx_buf, 0, XFER_BUFFER_SIZE); - priv_data->xfer_length = XFER_BUFFER_SIZE; - - filter_request = ifr->ifr_data; - req = (struct spi_mosi *)tx_buf; - if (IOCTL_ADD_FRAME_FILTER == cmd) - req->cmd = CMD_CAN_ADD_FILTER; - else - req->cmd = CMD_CAN_REMOVE_FILTER; - req->len = sizeof(struct can_add_filter_req); - req->seq = atomic_inc_return(&priv_data->msg_seq); - - add_filter = (struct can_add_filter_req *)req->data; - add_filter->can_if = filter_request->can_if; - add_filter->mid = filter_request->mid; - add_filter->mask = filter_request->mask; - - ret = rh850_do_spi_transaction(priv_data); - mutex_unlock(&priv_data->spi_lock); - - return ret; -} - -static int rh850_send_spi_locked(struct rh850_can *priv_data, int cmd, int len, - u8 *data) -{ - char *tx_buf, *rx_buf; - struct spi_mosi *req; - int ret; - - LOGDI("rh850_send_spi_locked\n"); - - tx_buf = priv_data->tx_buf; - rx_buf = priv_data->rx_buf; - memset(tx_buf, 0, XFER_BUFFER_SIZE); - memset(rx_buf, 0, XFER_BUFFER_SIZE); - priv_data->xfer_length = XFER_BUFFER_SIZE; - - req = (struct spi_mosi *)tx_buf; - req->cmd = cmd; - req->len = len; - req->seq = atomic_inc_return(&priv_data->msg_seq); - - if (unlikely(len > 64)) - return -EINVAL; - memcpy(req->data, data, len); - - ret = rh850_do_spi_transaction(priv_data); - return ret; -} - -static int rh850_convert_ioctl_cmd_to_spi_cmd(int ioctl_cmd) -{ - switch (ioctl_cmd) { - case IOCTL_GET_FW_BR_VERSION: - return CMD_GET_FW_BR_VERSION; - case IOCTL_BEGIN_FIRMWARE_UPGRADE: - return CMD_BEGIN_FIRMWARE_UPGRADE; - case IOCTL_FIRMWARE_UPGRADE_DATA: - return CMD_FIRMWARE_UPGRADE_DATA; - case IOCTL_END_FIRMWARE_UPGRADE: - return CMD_END_FIRMWARE_UPGRADE; - case IOCTL_BEGIN_BOOT_ROM_UPGRADE: - return CMD_BEGIN_BOOT_ROM_UPGRADE; - case IOCTL_BOOT_ROM_UPGRADE_DATA: - return CMD_BOOT_ROM_UPGRADE_DATA; - case IOCTL_END_BOOT_ROM_UPGRADE: - return CMD_END_BOOT_ROM_UPGRADE; - } - return -EINVAL; -} - -static int rh850_do_blocking_ioctl(struct net_device *netdev, - struct ifreq *ifr, int cmd) -{ - int spi_cmd, ret; - - struct rh850_can *priv_data; - struct rh850_netdev_privdata *netdev_priv_data; - struct rh850_ioctl_req *ioctl_data; - int len = 0; - u8 *data = NULL; - - netdev_priv_data = netdev_priv(netdev); - priv_data = netdev_priv_data->rh850_can; - - spi_cmd = rh850_convert_ioctl_cmd_to_spi_cmd(cmd); - LOGDI("rh850_do_blocking_ioctl spi_cmd %x\n", spi_cmd); - if (spi_cmd < 0) { - LOGDE("rh850_do_blocking_ioctl wrong command %d\n", cmd); - return spi_cmd; - } - if (ifr == NULL) - return -EINVAL; - ioctl_data = ifr->ifr_data; - /* Regular NULL check fails here as ioctl_data is at some offset */ - if ((void *)ioctl_data > (void *)0x100) { - len = ioctl_data->len; - data = ioctl_data->data; - } - LOGDI("rh850_do_blocking_ioctl len %d\n", len); - mutex_lock(&priv_data->spi_lock); - - priv_data->wait_cmd = spi_cmd; - priv_data->cmd_result = -1; - reinit_completion(&priv_data->response_completion); - - ret = rh850_send_spi_locked(priv_data, spi_cmd, len, data); - mutex_unlock(&priv_data->spi_lock); - - if (ret == 0) { - LOGDI("rh850_do_blocking_ioctl ready to wait for response\n"); - wait_for_completion_interruptible_timeout( - &priv_data->response_completion, 5 * HZ); - ret = priv_data->cmd_result; - } - return ret; -} - -static int rh850_netdev_do_ioctl(struct net_device *netdev, - struct ifreq *ifr, int cmd) -{ - struct rh850_can *priv_data; - struct rh850_netdev_privdata *netdev_priv_data; - int *mode; - int ret = -EINVAL; - - netdev_priv_data = netdev_priv(netdev); - priv_data = netdev_priv_data->rh850_can; - LOGDI("rh850_netdev_do_ioctl %x\n", cmd); - - switch (cmd) { - case IOCTL_RELEASE_CAN_BUFFER: - if (ifr->ifr_data > (void *)0x100) { - mode = ifr->ifr_data; - priv_data->driver_mode = *mode; - } - LOGDE("rh850_driver_mode %d\n", priv_data->driver_mode); - rh850_send_release_can_buffer_cmd(netdev); - ret = 0; - break; - case IOCTL_ENABLE_BUFFERING: - case IOCTL_DISABLE_BUFFERING: - rh850_data_buffering(netdev, ifr, cmd); - ret = 0; - break; - case IOCTL_DISABLE_ALL_BUFFERING: - rh850_remove_all_buffering(netdev); - ret = 0; - break; - case IOCTL_ADD_FRAME_FILTER: - case IOCTL_REMOVE_FRAME_FILTER: - rh850_frame_filter(netdev, ifr, cmd); - ret = 0; - break; - case IOCTL_GET_FW_BR_VERSION: - case IOCTL_BEGIN_FIRMWARE_UPGRADE: - case IOCTL_FIRMWARE_UPGRADE_DATA: - case IOCTL_END_FIRMWARE_UPGRADE: - case IOCTL_BEGIN_BOOT_ROM_UPGRADE: - case IOCTL_BOOT_ROM_UPGRADE_DATA: - case IOCTL_END_BOOT_ROM_UPGRADE: - ret = rh850_do_blocking_ioctl(netdev, ifr, cmd); - break; - } - LOGDI("rh850_netdev_do_ioctl ret %d\n", ret); - - return ret; -} - -static const struct net_device_ops rh850_netdev_ops = { - .ndo_open = rh850_netdev_open, - .ndo_stop = rh850_netdev_close, - .ndo_start_xmit = rh850_netdev_start_xmit, - .ndo_do_ioctl = rh850_netdev_do_ioctl, -}; - -static int rh850_create_netdev(struct spi_device *spi, - struct rh850_can *priv_data, int index) -{ - struct net_device *netdev; - struct rh850_netdev_privdata *netdev_priv_data; - - LOGDI("rh850_create_netdev %d\n", index); - if (index < 0 || index >= RH850_MAX_CHANNELS) { - LOGDE("rh850_create_netdev wrong index %d\n", index); - return -EINVAL; - } - netdev = alloc_candev(sizeof(*netdev_priv_data), MAX_TX_BUFFERS); - if (!netdev) { - LOGDE("Couldn't alloc candev\n"); - return -ENOMEM; - } - - netdev->mtu = CANFD_MTU; - - netdev_priv_data = netdev_priv(netdev); - netdev_priv_data->rh850_can = priv_data; - netdev_priv_data->netdev_index = index; - - priv_data->netdev[index] = netdev; - - netdev->netdev_ops = &rh850_netdev_ops; - SET_NETDEV_DEV(netdev, &spi->dev); - netdev_priv_data->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | - CAN_CTRLMODE_LISTENONLY | - CAN_CTRLMODE_FD; - netdev_priv_data->can.bittiming_const = &rh850_bittiming_const; - netdev_priv_data->can.data_bittiming_const = - &rh850_data_bittiming_const; - netdev_priv_data->can.clock.freq = RH850_CLOCK; - netdev_priv_data->can.do_set_bittiming = rh850_set_bitrate; - - return 0; -} - -static struct rh850_can *rh850_create_priv_data(struct spi_device *spi) -{ - struct rh850_can *priv_data; - int err; - struct device *dev; - - dev = &spi->dev; - priv_data = kzalloc(sizeof(*priv_data), GFP_KERNEL); - if (!priv_data) { - dev_err(dev, "Couldn't alloc rh850_can\n"); - return 0; - } - spi_set_drvdata(spi, priv_data); - atomic_set(&priv_data->netif_queue_stop, 0); - priv_data->spidev = spi; - priv_data->assembly_buffer = kzalloc(RX_ASSEMBLY_BUFFER_SIZE, - GFP_KERNEL); - if (!priv_data->assembly_buffer) { - err = -ENOMEM; - goto cleanup_privdata; - } - - priv_data->tx_wq = alloc_workqueue("rh850_tx_wq", 0, 0); - if (!priv_data->tx_wq) { - dev_err(dev, "Couldn't alloc workqueue\n"); - err = -ENOMEM; - goto cleanup_privdata; - } - - priv_data->tx_buf = kzalloc(XFER_BUFFER_SIZE, GFP_KERNEL); - priv_data->rx_buf = kzalloc(XFER_BUFFER_SIZE, GFP_KERNEL); - if (!priv_data->tx_buf || !priv_data->rx_buf) { - dev_err(dev, "Couldn't alloc tx or rx buffers\n"); - err = -ENOMEM; - goto cleanup_privdata; - } - priv_data->xfer_length = 0; - priv_data->driver_mode = DRIVER_MODE_RAW_FRAMES; - - mutex_init(&priv_data->spi_lock); - atomic_set(&priv_data->msg_seq, 0); - init_completion(&priv_data->response_completion); - return priv_data; - -cleanup_privdata: - if (priv_data) { - if (priv_data->tx_wq) - destroy_workqueue(priv_data->tx_wq); - kfree(priv_data->rx_buf); - kfree(priv_data->tx_buf); - kfree(priv_data->assembly_buffer); - kfree(priv_data); - } - return 0; -} - -static int rh850_probe(struct spi_device *spi) -{ - int err, i; - struct rh850_can *priv_data; - struct device *dev; - - dev = &spi->dev; - dev_info(dev, "rh850_probe"); - - err = spi_setup(spi); - if (err) { - dev_err(dev, "spi_setup failed: %d", err); - return err; - } - - priv_data = rh850_create_priv_data(spi); - if (!priv_data) { - dev_err(dev, "Failed to create rh850_can priv_data\n"); - err = -ENOMEM; - return err; - } - dev_info(dev, "rh850_probe created priv_data"); - for (i = 0; i < RH850_MAX_CHANNELS; i++) { - err = rh850_create_netdev(spi, priv_data, i); - if (err) { - dev_err(dev, "Failed to create CAN device: %d", err); - goto cleanup_candev; - } - - err = register_candev(priv_data->netdev[i]); - if (err) { - dev_err(dev, "Failed to register CAN device: %d", err); - goto unregister_candev; - } - } - - err = request_threaded_irq(spi->irq, NULL, rh850_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "rh850", priv_data); - if (err) { - dev_err(dev, "Failed to request irq: %d", err); - goto unregister_candev; - } - dev_info(dev, "Request irq %d ret %d\n", spi->irq, err); - - rh850_query_firmware_version(priv_data); - return 0; - -unregister_candev: - for (i = 0; i < RH850_MAX_CHANNELS; i++) - unregister_candev(priv_data->netdev[i]); -cleanup_candev: - if (priv_data) { - for (i = 0; i < RH850_MAX_CHANNELS; i++) { - if (priv_data->netdev[i]) - free_candev(priv_data->netdev[i]); - } - if (priv_data->tx_wq) - destroy_workqueue(priv_data->tx_wq); - kfree(priv_data->rx_buf); - kfree(priv_data->tx_buf); - kfree(priv_data->assembly_buffer); - kfree(priv_data); - } - return err; -} - -static int rh850_remove(struct spi_device *spi) -{ - struct rh850_can *priv_data = spi_get_drvdata(spi); - int i; - - LOGDI("rh850_remove\n"); - for (i = 0; i < RH850_MAX_CHANNELS; i++) { - unregister_candev(priv_data->netdev[i]); - free_candev(priv_data->netdev[i]); - } - destroy_workqueue(priv_data->tx_wq); - kfree(priv_data->assembly_buffer); - kfree(priv_data->rx_buf); - kfree(priv_data->tx_buf); - kfree(priv_data); - return 0; -} - -static const struct of_device_id rh850_match_table[] = { - { .compatible = "renesas,rh850" }, - { } -}; - -static struct spi_driver rh850_driver = { - .driver = { - .name = "rh850", - .of_match_table = rh850_match_table, - .owner = THIS_MODULE, - }, - .probe = rh850_probe, - .remove = rh850_remove, -}; -module_spi_driver(rh850_driver); - -MODULE_DESCRIPTION("RH850 SPI-CAN module"); -MODULE_LICENSE("GPL v2"); From acecea412b70594a092e36ed3c640d75ddf6c359 Mon Sep 17 00:00:00 2001 From: Balachandra C S Date: Tue, 6 Mar 2018 19:38:26 +0530 Subject: [PATCH 166/508] Modify k61 driver to remove support for mpc5746c CAN card mpc5746c CAN driver will be supported by the unified driver qti-can. Change-Id: I6743604c1298b9705ac3550b96c9dae04d5137bd Signed-off-by: Balachandra C S --- Documentation/devicetree/bindings/net/can/k61-can.txt | 2 +- drivers/net/can/spi/k61.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/net/can/k61-can.txt b/Documentation/devicetree/bindings/net/can/k61-can.txt index ea4a7b4ae035b..ea9a3bc5cce0c 100644 --- a/Documentation/devicetree/bindings/net/can/k61-can.txt +++ b/Documentation/devicetree/bindings/net/can/k61-can.txt @@ -3,7 +3,7 @@ This driver implements SPI slave protocol for Freescale K61 CAN controller. Required properties: - - compatible: Should be "fsl,k61" or "nxp,mpc5746c". + - compatible: Should be "fsl,k61". - reg: Should contain SPI chip select. - interrupt-parent: Should specify interrupt controller for the interrupt. - interrupts: Should contain IRQ line for the CAN controller. diff --git a/drivers/net/can/spi/k61.c b/drivers/net/can/spi/k61.c index d38d3cd58e7b3..4668d40a16125 100644 --- a/drivers/net/can/spi/k61.c +++ b/drivers/net/can/spi/k61.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -917,7 +917,6 @@ static int k61_remove(struct spi_device *spi) static const struct of_device_id k61_match_table[] = { { .compatible = "fsl,k61" }, - { .compatible = "nxp,mpc5746c" }, { } }; From 20bf8fcdbb68ae10b834df33debe50a643f83b95 Mon Sep 17 00:00:00 2001 From: Balachandra C S Date: Tue, 6 Mar 2018 19:07:54 +0530 Subject: [PATCH 167/508] defconfig: mdm9650: Add QTI_CAN config option Enable QTI CAN driver with CONFIG_QTI_CAN option in defconfig file. Change-Id: Ieaed761f846d0c06c30c914ac45b4c9ba86bddca Signed-off-by: Balachandra C S --- arch/arm/configs/mdm-perf_defconfig | 1 + arch/arm/configs/mdm_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/mdm-perf_defconfig b/arch/arm/configs/mdm-perf_defconfig index 08d6a2a3dd795..4ab05a534f26d 100644 --- a/arch/arm/configs/mdm-perf_defconfig +++ b/arch/arm/configs/mdm-perf_defconfig @@ -161,6 +161,7 @@ CONFIG_RMNET_DATA_DEBUG_PKT=y CONFIG_CAN=y CONFIG_CAN_VCAN=y CONFIG_CAN_K61=y +CONFIG_QTI_CAN=y CONFIG_BT=y CONFIG_BT_RFCOMM=y CONFIG_BT_RFCOMM_TTY=y diff --git a/arch/arm/configs/mdm_defconfig b/arch/arm/configs/mdm_defconfig index aedfec1ba664d..898400ad78d43 100644 --- a/arch/arm/configs/mdm_defconfig +++ b/arch/arm/configs/mdm_defconfig @@ -161,6 +161,7 @@ CONFIG_RMNET_DATA_DEBUG_PKT=y CONFIG_CAN=y CONFIG_CAN_VCAN=y CONFIG_CAN_K61=y +CONFIG_QTI_CAN=y CONFIG_BT=y CONFIG_BT_RFCOMM=y CONFIG_BT_RFCOMM_TTY=y From f96583bf1c9c0df7a384571d6284ca297ea82b37 Mon Sep 17 00:00:00 2001 From: Balachandra C S Date: Thu, 8 Mar 2018 13:02:35 +0530 Subject: [PATCH 168/508] defconfig: msm-auto: Add qti can driver support Enable qti can driver support in msm-auto_defconfg and msm-auto-perf_defconfig. Change-Id: I8cc9616f5a0a6fd41f9e2220fd726ef351ef5104 Signed-off-by: Balachandra C S --- arch/arm64/configs/msm-auto-perf_defconfig | 1 + arch/arm64/configs/msm-auto_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/msm-auto-perf_defconfig b/arch/arm64/configs/msm-auto-perf_defconfig index 3db3d67f6f9c3..72af00e39cba7 100644 --- a/arch/arm64/configs/msm-auto-perf_defconfig +++ b/arch/arm64/configs/msm-auto-perf_defconfig @@ -213,6 +213,7 @@ CONFIG_RMNET_DATA_DEBUG_PKT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_CAN=y CONFIG_CAN_VCAN=y +CONFIG_QTI_CAN=y CONFIG_CAN_PEAK_USB=y CONFIG_BT=y CONFIG_BT_RFCOMM=y diff --git a/arch/arm64/configs/msm-auto_defconfig b/arch/arm64/configs/msm-auto_defconfig index 636b90fa033c0..390cfc4aa1e5c 100644 --- a/arch/arm64/configs/msm-auto_defconfig +++ b/arch/arm64/configs/msm-auto_defconfig @@ -214,6 +214,7 @@ CONFIG_RMNET_DATA_DEBUG_PKT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_CAN=y CONFIG_CAN_VCAN=y +CONFIG_QTI_CAN=y CONFIG_CAN_PEAK_USB=y CONFIG_BT=y CONFIG_BT_RFCOMM=y From a27ad2f1b10e1c7e498cbed6a2ac8a17cc0e5eb9 Mon Sep 17 00:00:00 2001 From: Karthikeyan Mani Date: Tue, 6 Mar 2018 11:04:49 -0800 Subject: [PATCH 169/508] ASoC: msm: qdsp6v2: check for buffer size before read Check for debugfs ops buf size passed before reading to eliminate the possibility of reading out of bounds. Change-Id: I28fd60ce93256b6b0bad62b449092a891cc15463 Signed-off-by: Karthikeyan Mani --- sound/soc/msm/qdsp6v2/q6asm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 5abc1ffbe1f33..aef23da39326d 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -148,6 +148,11 @@ static ssize_t audio_output_latency_dbgfs_read(struct file *file, pr_err("%s: out_buffer is null\n", __func__); return 0; } + if (count < OUT_BUFFER_SIZE) { + pr_err("%s: read size %d exceeds buf size %zd\n", __func__, + OUT_BUFFER_SIZE, count); + return 0; + } snprintf(out_buffer, OUT_BUFFER_SIZE, "%ld,%ld,%ld,%ld,%ld,%ld,",\ out_cold_tv.tv_sec, out_cold_tv.tv_usec, out_warm_tv.tv_sec,\ out_warm_tv.tv_usec, out_cont_tv.tv_sec, out_cont_tv.tv_usec); @@ -201,6 +206,11 @@ static ssize_t audio_input_latency_dbgfs_read(struct file *file, pr_err("%s: in_buffer is null\n", __func__); return 0; } + if (count < IN_BUFFER_SIZE) { + pr_err("%s: read size %d exceeds buf size %zd\n", __func__, + IN_BUFFER_SIZE, count); + return 0; + } snprintf(in_buffer, IN_BUFFER_SIZE, "%ld,%ld,",\ in_cont_tv.tv_sec, in_cont_tv.tv_usec); return simple_read_from_buffer(buf, IN_BUFFER_SIZE, ppos, From 8ae38bb8616cddaa8ee328f8d32d4dde4b90540c Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Wed, 7 Mar 2018 18:59:30 +0530 Subject: [PATCH 170/508] wlan: Implement GET_DISABLE_CHANNEL_LIST driver command Implement GET_DISABLE_CHANNEL_LIST driver command to get disable channel list programed by SET_DISABLE_CHANNEL_LIST driver command. Change-Id: Ib741e1cd23cef105314325aaec86feb50f36a181 CRs-Fixed: 2201755 --- CORE/HDD/inc/wlan_hdd_main.h | 12 ++++++ CORE/HDD/src/wlan_hdd_hostapd.c | 26 +++++++++++++ CORE/HDD/src/wlan_hdd_main.c | 66 +++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index 2a3058e454db3..fefbb0b7ba223 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -2363,4 +2363,16 @@ hdd_wlan_nla_put_u64(struct sk_buff *skb, int attrtype, u64 value) */ int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr); +/* + * hdd_parse_disable_chn_cmd() - get disable channel list + * in command. + * @hdd_ctx: hdd context + * @buf: buffer to hold disable channel list + * @buf_len: buffer length + * + * @return: length of data copied to buf + */ +int hdd_get_disable_ch_list(hdd_context_t *hdd_ctx, tANI_U8 *buf, + tANI_U8 buf_len); + #endif // end #if !defined( WLAN_HDD_MAIN_H ) diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index 63e76bce21a32..20c34af352e21 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -479,7 +479,33 @@ static int hdd_hostapd_driver_command(hdd_adapter_t *pAdapter, __func__); ret = hdd_parse_disable_chan_cmd(pAdapter, ptr); } + else if (strncmp(command, "GET_DISABLE_CHANNEL_LIST", 24) == 0) { + char extra[128] = {0}; + int len; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + " Received Command to get disable Channels list %s", + __func__); + + len = hdd_get_disable_ch_list(pHddCtx, extra, sizeof(extra)); + if (len == 0) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("disable channel list are not yet programed")); + ret = -EINVAL; + goto exit; + } + + len = VOS_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("data:%s"), extra); + } else { MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_UNSUPPORTED_IOCTL, diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index ea33d3ad19097..9199439a99b78 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -3436,6 +3436,46 @@ int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr) return ret; } +int hdd_get_disable_ch_list(hdd_context_t *hdd_ctx, tANI_U8 *buf, + tANI_U8 buf_len) +{ + struct hdd_cache_channel_info *ch_list; + unsigned char i, num_ch; + int len = 0; + + mutex_lock(&hdd_ctx->cache_channel_lock); + if (hdd_ctx->orginal_channels && + hdd_ctx->orginal_channels->num_channels) { + num_ch = hdd_ctx->orginal_channels->num_channels; + + if (num_ch == 0) { + mutex_unlock(&hdd_ctx->cache_channel_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("no disable channels programed")); + return 0; + } + + len = scnprintf(buf, buf_len, "%s %hhu", + "GET_DISABLE_CHANNEL_LIST", num_ch); + + ch_list = hdd_ctx->orginal_channels->channel_info; + if (!ch_list) { + mutex_unlock(&hdd_ctx->cache_channel_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("disable channel list is NULL")); + return 0; + } + + for (i = 0; (i < num_ch) && len <= buf_len; i++) { + len += scnprintf(buf + len, buf_len - len, + " %d", ch_list[i].channel_num); + } + } + mutex_unlock(&hdd_ctx->cache_channel_lock); + + return len; +} + static int hdd_driver_command(hdd_adapter_t *pAdapter, hdd_priv_data_t *ppriv_data) { @@ -6512,7 +6552,33 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, if (ret) goto exit; } + else if (strncmp(command, "GET_DISABLE_CHANNEL_LIST", 24) == 0) { + char extra[128] = {0}; + int len; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + " Received Command to get disable Channels list %s", + __func__); + + len = hdd_get_disable_ch_list(pHddCtx, extra, sizeof(extra)); + if (len == 0) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("disable channel list are not yet programed")); + ret = -EINVAL; + goto exit; + } + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("data:%s"), extra); + } else { MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_UNSUPPORTED_IOCTL, From 066859074377f4c05e89b0196b93bcf02f8b0cdb Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 3 Aug 2016 12:04:51 -0700 Subject: [PATCH 171/508] PM / devfreq: memlat: Remove kfree() on probe fails Memory allocated with devm_kzalloc() is automatically freed if the probe function fails and returns an error code. So there is no need to free cpu_grp explicitly for the failure cases that might come up after it is allocated. Additionally calls to devm_kzalloc() must be accompanied by devm_kfree() if memory deallocation is necessary. For these reasons remove the kfree(cpu_grp) from the probe function. Change-Id: Ic4838fd58d40d283ac301facc64b06813eb3bd7d Signed-off-by: Rohit Gupta --- drivers/devfreq/arm-memlat-mon.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/devfreq/arm-memlat-mon.c b/drivers/devfreq/arm-memlat-mon.c index 370d7d95042b1..4fb0a5ffda50f 100644 --- a/drivers/devfreq/arm-memlat-mon.c +++ b/drivers/devfreq/arm-memlat-mon.c @@ -311,19 +311,19 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev) hw->of_node = of_parse_phandle(dev->of_node, "qcom,target-dev", 0); if (!hw->of_node) { dev_err(dev, "Couldn't find a target device\n"); - goto err_out; + return -ENODEV; } if (get_mask_from_dev_handle(pdev, &cpu_grp->cpus)) { dev_err(dev, "CPU list is empty\n"); - goto err_out; + return -ENODEV; } hw->num_cores = cpumask_weight(&cpu_grp->cpus); hw->core_stats = devm_kzalloc(dev, hw->num_cores * sizeof(*(hw->core_stats)), GFP_KERNEL); if (!hw->core_stats) - goto err_out; + return -ENOMEM; for_each_cpu(cpu, &cpu_grp->cpus) hw->core_stats[cpu - cpumask_first(&cpu_grp->cpus)].id = cpu; @@ -335,14 +335,10 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev) ret = register_memlat(dev, hw); if (ret) { pr_err("Mem Latency Gov registration failed\n"); - goto err_out; + return ret; } return 0; - -err_out: - kfree(cpu_grp); - return -EINVAL; } static struct of_device_id match_table[] = { From 17b649aab1158fd6ad5583d527270779cabe972f Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Sirasanagandla Date: Mon, 19 Mar 2018 16:58:30 +0530 Subject: [PATCH 172/508] wlan: Use HDD indexes to access wiphy band info To make pronto driver to work with msm-4.9 kernel, use: HDD_NL80211_BAND_2GHZ, HDD_NL80211_BAND_5GHZ and HDD_NUM_NL80211_BANDS, instead of IEEE80211_BAND_2GHZ, IEEE80211_BAND_5GHZ and IEEE80211_NUM_BANDS respectively. Change-Id: I19f7e55e86eb6e0a551de3879ff842569caf2aa4 CRs-Fixed: 2208312 --- CORE/HDD/src/wlan_hdd_cfg80211.c | 5 +++-- CORE/VOSS/src/vos_nvitem.c | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index ea392395949d2..40a6177ae8d58 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -10663,7 +10663,8 @@ int wlan_hdd_restore_channels(hdd_context_t *hdd_ctx) cache_chann->channel_info[i].channel_num, &freq); - for (band_num = 0; band_num < IEEE80211_NUM_BANDS; band_num++) { + for (band_num = 0; band_num < HDD_NUM_NL80211_BANDS; + band_num++) { for (channel_num = 0; channel_num < wiphy->bands[band_num]->n_channels; channel_num++) { @@ -10741,7 +10742,7 @@ static int wlan_hdd_disable_channels(hdd_context_t *hdd_ctx) cache_chann->channel_info[i].channel_num, &freq); - for (band_num = 0; band_num < IEEE80211_NUM_BANDS; + for (band_num = 0; band_num < HDD_NUM_NL80211_BANDS; band_num++) { for (band_ch_num = 0; band_ch_num < wiphy->bands[band_num]->n_channels; diff --git a/CORE/VOSS/src/vos_nvitem.c b/CORE/VOSS/src/vos_nvitem.c index cf7aef935b542..175bb82cb5115 100644 --- a/CORE/VOSS/src/vos_nvitem.c +++ b/CORE/VOSS/src/vos_nvitem.c @@ -4845,15 +4845,15 @@ int __wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, k = wiphy->bands[HDD_NL80211_BAND_2GHZ]->n_channels + j; if ((wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5260 || - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5280 || - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5300 || - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5320 || - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5500 || - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5520) && + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5280 || + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5300 || + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5320 || + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5500 || + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].center_freq == 5520) && ((regChannels[k].enabled == NV_CHANNEL_ENABLE) || (regChannels[k].enabled == NV_CHANNEL_DFS))) { - wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].flags |= IEEE80211_CHAN_RADAR; + wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels[j].flags |= IEEE80211_CHAN_RADAR; } } } From c16b97fb54a31cbe8c750f5a16f6861191f00c49 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Mon, 14 Aug 2017 10:44:59 -0700 Subject: [PATCH 173/508] ipv6: release rt6->rt6i_idev properly during ifdown When a dst is created by addrconf_dst_alloc() for a host route or an anycast route, dst->dev points to loopback dev while rt6->rt6i_idev points to a real device. When the real device goes down, the current cleanup code only checks for dst->dev and assumes rt6->rt6i_idev->dev is the same. This causes the refcount leak on the real device in the above situation. This patch makes sure to always release the refcount taken on rt6->rt6i_idev during dst_dev_put(). Change-Id: Id3d07aebb85432298179c6846986540e2f8b13a9 Fixes: 587fea741134 ("ipv6: mark DST_NOGC and remove the operation of dst_free()") Reported-by: John Stultz Tested-by: John Stultz Tested-by: Martin KaFai Lau Signed-off-by: Wei Wang Signed-off-by: Martin KaFai Lau Acked-by: David Ahern Signed-off-by: David S. Miller Git-commit: e5645f51ba99738b0e5d708edf9c6454f33b9310 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Acked-by: Sharath Chandra Vurukala Signed-off-by: Tejaswi Tanikella --- net/ipv6/route.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 223aa4292c1be..55fcfe3c9a3d4 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -349,14 +349,11 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, struct net_device *loopback_dev = dev_net(dev)->loopback_dev; - if (dev != loopback_dev) { - if (idev && idev->dev == dev) { - struct inet6_dev *loopback_idev = - in6_dev_get(loopback_dev); - if (loopback_idev) { - rt->rt6i_idev = loopback_idev; - in6_dev_put(idev); - } + if (idev && idev->dev != loopback_dev) { + struct inet6_dev *loopback_idev = in6_dev_get(loopback_dev); + if (loopback_idev) { + rt->rt6i_idev = loopback_idev; + in6_dev_put(idev); } } } From fe30834d0cc3884c5d25a5878d98ccbd1520968d Mon Sep 17 00:00:00 2001 From: Siena Richard Date: Tue, 30 Aug 2016 18:06:44 -0700 Subject: [PATCH 174/508] msm: qdsp6v2: update CVD version CVD version is updated to 2.3 on ADSP. Update the mapping table in voice driver to allow CVD version 2.3 to be recognized and used. Change-Id: Id6d1c960dc720e8013eb9ba1f07af7662b576e37 CRs-Fixed: 1060201 Signed-off-by: Siena Richard --- sound/soc/msm/qdsp6v2/q6voice.c | 1 + sound/soc/msm/qdsp6v2/q6voice.h | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c index 8292f474a3574..506611d869725 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.c +++ b/sound/soc/msm/qdsp6v2/q6voice.c @@ -48,6 +48,7 @@ struct cvd_version_table cvd_version_table_mapping[CVD_INT_VERSION_MAX] = { {CVD_VERSION_0_0, CVD_INT_VERSION_0_0}, {CVD_VERSION_2_1, CVD_INT_VERSION_2_1}, {CVD_VERSION_2_2, CVD_INT_VERSION_2_2}, + {CVD_VERSION_2_3, CVD_INT_VERSION_2_3}, }; static struct common_data common; diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h index a4c3a4be19ee5..71c0e80464ef0 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.h +++ b/sound/soc/msm/qdsp6v2/q6voice.h @@ -42,12 +42,14 @@ #define CVD_VERSION_0_0 "0.0" #define CVD_VERSION_2_1 "2.1" #define CVD_VERSION_2_2 "2.2" +#define CVD_VERSION_2_3 "2.3" #define CVD_INT_VERSION_DEFAULT 0 #define CVD_INT_VERSION_0_0 1 #define CVD_INT_VERSION_2_1 2 #define CVD_INT_VERSION_2_2 3 -#define CVD_INT_VERSION_LAST CVD_INT_VERSION_2_2 +#define CVD_INT_VERSION_2_3 4 +#define CVD_INT_VERSION_LAST CVD_INT_VERSION_2_3 #define CVD_INT_VERSION_MAX (CVD_INT_VERSION_LAST + 1) struct cvd_version_table { From 2b85a2656108c59fadc948462601c82f90bff7c9 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Tue, 20 Mar 2018 08:20:33 +0800 Subject: [PATCH 175/508] platform: msm: gpio-usbdetect: Report charger types in REAL_TYPE Commit eca542a92350 ("power: qpnp-smbcharger: Report charger types in REAL_TYPE property") changes to use POWER_SUPPLY_PROP_REAL_TYPE property to report charger types between charger driver and USB driver, so change the same in this driver to make sure USB driver could get the correct charger type notification. Change-Id: Ia70e9a376a494c6c9d8905ff4017996eecc8d503 Signed-off-by: Fenglin Wu --- drivers/platform/msm/gpio-usbdetect.c | 28 ++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/platform/msm/gpio-usbdetect.c b/drivers/platform/msm/gpio-usbdetect.c index f0d033cf1eeca..f9afd7f62ce49 100644 --- a/drivers/platform/msm/gpio-usbdetect.c +++ b/drivers/platform/msm/gpio-usbdetect.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -173,6 +173,28 @@ static irqreturn_t gpio_usbdetect_vbus_irq(int irq, void *data) return IRQ_HANDLED; } +static int gpio_usbdetect_notify_usb_type(struct gpio_usbdetect *usb, + enum power_supply_type type) +{ + int rc; + union power_supply_propval pval = {0, }; + + pval.intval = type; + rc = usb->usb_psy->set_property(usb->usb_psy, + POWER_SUPPLY_PROP_REAL_TYPE, &pval); + if (rc < 0) { + if (rc == -EINVAL) { + rc = usb->usb_psy->set_property(usb->usb_psy, + POWER_SUPPLY_PROP_TYPE, &pval); + if (!rc) + return 0; + } + pr_err("notify charger type to usb_psy failed, rc=%d\n", rc); + } + + return rc; +} + static void gpio_usbdetect_chg_work(struct work_struct *w) { struct gpio_usbdetect *usb = container_of(w, struct gpio_usbdetect, @@ -183,13 +205,13 @@ static void gpio_usbdetect_chg_work(struct work_struct *w) power_supply_set_usb_otg(usb->usb_psy, 0); if (!usb->disable_device_mode) { - power_supply_set_supply_type(usb->usb_psy, + gpio_usbdetect_notify_usb_type(usb, POWER_SUPPLY_TYPE_USB); power_supply_set_present(usb->usb_psy, usb->vbus); } } else { /* notify gpio_state = LOW as disconnect */ - power_supply_set_supply_type(usb->usb_psy, + gpio_usbdetect_notify_usb_type(usb, POWER_SUPPLY_TYPE_UNKNOWN); power_supply_set_present(usb->usb_psy, usb->vbus); From 4433576cc847936fe9d018cd61c909923167d0ad Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Thu, 25 Jan 2018 11:57:25 +0530 Subject: [PATCH 176/508] phy-msm-qusb-v2: Add change_dpdm callback for USB2 PHY Add change_dpdm callback for phy-msmqusb-v2.c driver so that PMIC calls this callback before charger detection through USB power supply. This is required to remove pull downs from QUSB2 PHY to avoid interference while PMIC doing charger detection. Change-Id: If155230f151154188d2a61d96f29622ea40baf49 Signed-off-by: Vijayavardhan Vennapusa --- drivers/usb/phy/phy-msm-qusb-v2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c index 27cb9d4650aef..65ca1b8913cc5 100644 --- a/drivers/usb/phy/phy-msm-qusb-v2.c +++ b/drivers/usb/phy/phy-msm-qusb-v2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1046,6 +1046,7 @@ static int qusb_phy_probe(struct platform_device *pdev) qphy->phy.init = qusb_phy_init; qphy->phy.set_suspend = qusb_phy_set_suspend; qphy->phy.shutdown = qusb_phy_shutdown; + qphy->phy.change_dpdm = qusb_phy_update_dpdm; qphy->phy.type = USB_PHY_TYPE_USB2; qphy->phy.notify_connect = qusb_phy_notify_connect; qphy->phy.notify_disconnect = qusb_phy_notify_disconnect; From e0c08ca69311d7cdd4a9c690406bedb1e69a9a87 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Wed, 14 Mar 2018 16:03:34 +0530 Subject: [PATCH 177/508] ARM: dts: msm: Disable IPA in SDA450 IPA needs to be kept disabled in SDA450 platform. Change-Id: Ib481332fd0020535d91e09b2379d4bd41d0a514b Acked-by: Ashok Vuyyuru Signed-off-by: Mohammed Javid --- arch/arm/boot/dts/qcom/sda450.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/qcom/sda450.dtsi b/arch/arm/boot/dts/qcom/sda450.dtsi index 7089bb45f52e4..4fa84e2e88b6d 100644 --- a/arch/arm/boot/dts/qcom/sda450.dtsi +++ b/arch/arm/boot/dts/qcom/sda450.dtsi @@ -118,3 +118,13 @@ }; }; }; + +&soc { + qcom,rmnet-ipa { + status = "disabled"; + }; +}; + +&ipa_hw { + status = "disabled"; +}; From 6641489072fb5414a18c964c913a163c043f296e Mon Sep 17 00:00:00 2001 From: gaurank kathpalia Date: Wed, 21 Mar 2018 20:24:39 +0530 Subject: [PATCH 178/508] wlan: Prioritize connection req frames in pe queue If there are many beacon/probe received and posted to pe queue the connection req frames may get delayed and thus effect the connection. This may also lead to connection failures. To avoid this prioritize the connection req frames in pe queue. Also ignore auth frame if same seq no frame is received after sending assoc resp in case of SAP Change-Id: I025701fa389000aff13d5e14b40f641e977ff640 CRs-Fixed: 2210853 --- CORE/MAC/src/include/dphGlobal.h | 7 +++++- CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c | 22 ++++++++++++++++--- CORE/MAC/src/pe/lim/limProcessAuthFrame.c | 8 +++---- CORE/SYS/legacy/src/system/src/sysEntryFunc.c | 21 +++++++++++++++--- 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/CORE/MAC/src/include/dphGlobal.h b/CORE/MAC/src/include/dphGlobal.h index e6e7d98878e8b..8ceb23df39ae5 100644 --- a/CORE/MAC/src/include/dphGlobal.h +++ b/CORE/MAC/src/include/dphGlobal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2013, 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2013, 2016-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -425,8 +425,13 @@ typedef struct sDphHashNode tANI_U32 curTxMpduCnt; + /// Previous Sequence number of auth packet + tANI_U16 PrevAuthSeqno; + /// Previous Sequence number of assoc packet + + tANI_U16 PrevAssocSeqno; /// number of consecutive TIMs sent without response diff --git a/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c b/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c index 7b6666c61e8f6..427300d903aae 100644 --- a/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c +++ b/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2017-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -173,6 +173,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 *pBody; tANI_U16 peerIdx, temp; tANI_U32 val; + tANI_U16 prevAuthSeqno = 0xFFFF; tANI_S32 framelen; tSirRetStatus status; tpSirMacMgmtHdr pHdr; @@ -219,7 +220,6 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, WDA_GET_RX_MPDU_DATA(pRxPacketInfo), framelen); return; } - /* * If a STA is already present in DPH and it * is initiating a Assoc re-transmit, do not @@ -233,7 +233,8 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, &psessionEntry->dph.dphHashTable); if (NULL != pStaDs) { - if (pHdr->fc.retry > 0) + if (pStaDs->PrevAssocSeqno == ((pHdr->seqControl.seqNumHi << 4) | + (pHdr->seqControl.seqNumLo))) { /* Ignore the Retry */ limLog(pMac, LOGE, @@ -889,6 +890,11 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, /// Delete 'pre-auth' context of STA authType = pStaPreAuthContext->authType; + + /// Store the previous auth frame's seq no + prevAuthSeqno = pStaPreAuthContext->seqNo; + + limDeletePreAuthNode(pMac, pHdr->sa); // All is well. Assign AID (after else part) @@ -1129,6 +1135,16 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, goto error; } + /// Store the previous auth frame's seq no + if (prevAuthSeqno != 0xFFFF) + { + pStaDs->PrevAuthSeqno = prevAuthSeqno; + } + /// Store the current assoc seq no + pStaDs->PrevAssocSeqno = ((pHdr->seqControl.seqNumHi << 4) | + (pHdr->seqControl.seqNumLo)); + limLog(pMac, LOG1, FL("Prev auth seq no %d Prev Assoc seq no. %d"), + pStaDs->PrevAuthSeqno, pStaDs->PrevAssocSeqno); sendIndToSme: diff --git a/CORE/MAC/src/pe/lim/limProcessAuthFrame.c b/CORE/MAC/src/pe/lim/limProcessAuthFrame.c index 3112f7bfb2173..894549f781a3c 100644 --- a/CORE/MAC/src/pe/lim/limProcessAuthFrame.c +++ b/CORE/MAC/src/pe/lim/limProcessAuthFrame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015, 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2015, 2017-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -676,11 +676,11 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse * SA-Query procedure determines that the original SA is * invalid. */ - if (isConnected + if (isConnected && pStaDs->PrevAuthSeqno != currSeqNo #ifdef WLAN_FEATURE_11W && !pStaDs->rmfEnabled #endif - ) + ) { limLog(pMac, LOGE, FL("STA is already connected but received auth frame" @@ -699,7 +699,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse if (pAuthNode) { /// Pre-auth context exists for the STA - if (pHdr->fc.retry == 0 || pAuthNode->seqNo != currSeqNo) + if (pAuthNode->seqNo != currSeqNo) { /** * STA is initiating brand-new Authentication diff --git a/CORE/SYS/legacy/src/system/src/sysEntryFunc.c b/CORE/SYS/legacy/src/system/src/sysEntryFunc.c index ffa574ab136e2..baee990211cce 100644 --- a/CORE/SYS/legacy/src/system/src/sysEntryFunc.c +++ b/CORE/SYS/legacy/src/system/src/sysEntryFunc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014, 2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -145,8 +145,23 @@ sysBbtProcessMessageCore(tpAniSirGlobal pMac, tpSirMsgQ pMsg, tANI_U32 type, MTRACE(macTrace(pMac, TRACE_CODE_RX_MGMT_DROP, NO_SESSION, dropReason);) goto fail; } - //Post the message to PE Queue - ret = (tSirRetStatus) limPostMsgApi(pMac, pMsg); + /* + * Post the message to PE Queue. Prioritize the + * Auth and assoc frames. + */ + if ((subType == SIR_MAC_MGMT_AUTH) || + (subType == SIR_MAC_MGMT_ASSOC_RSP) || + (subType == SIR_MAC_MGMT_REASSOC_RSP) || + (subType == SIR_MAC_MGMT_ASSOC_REQ) || + (subType == SIR_MAC_MGMT_REASSOC_REQ)) + { + ret = (tSirRetStatus) limPostMsgApiHighPri(pMac, pMsg); + } + else + { + //Post the message to PE Queue + ret = (tSirRetStatus) limPostMsgApi(pMac, pMsg); + } if (ret != eSIR_SUCCESS) { PELOGE(sysLog(pMac, LOGE, FL("posting to LIM2 failed, ret %d\n"), ret);) From a478f3f528e3523d91addd4795af4fbc47e6e4ef Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Wed, 20 Dec 2017 16:59:11 -0800 Subject: [PATCH 179/508] ANDROID: sdcardfs: notify lower file of opens fsnotify_open is not called within dentry_open, so we need to call it ourselves. Change-Id: Ia7f323b3d615e6ca5574e114e8a5d7973fb4c119 Signed-off-by: Daniel Rosenberg Bug: 70706497 --- fs/sdcardfs/file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c index 0fe08c7856a5e..0c6e4659d4e6a 100644 --- a/fs/sdcardfs/file.c +++ b/fs/sdcardfs/file.c @@ -18,6 +18,7 @@ * General Public License. */ +#include #include "sdcardfs.h" #ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE #include @@ -259,6 +260,7 @@ static int sdcardfs_open(struct inode *inode, struct file *file) fput(lower_file); /* fput calls dput for lower_dentry */ } } else { + fsnotify_open(lower_file); sdcardfs_set_lower_file(file, lower_file); } From ef9b0fa63ba101b51bf8f2e8f4c6789927ba6dec Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Tue, 2 Jan 2018 14:44:49 -0800 Subject: [PATCH 180/508] ANDROID: sdcardfs: Add default_normal option The default_normal option causes mounts with the gid set to AID_SDCARD_RW to have user specific gids, as in the normal case. Signed-off-by: Daniel Rosenberg Change-Id: I9619b8ac55f41415df943484dc8db1ea986cef6f Bug: 64672411 --- fs/sdcardfs/main.c | 6 ++++++ fs/sdcardfs/sdcardfs.h | 3 ++- fs/sdcardfs/super.c | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c index edb77a91974f1..50e186b833412 100644 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -33,6 +33,7 @@ enum { Opt_userid, Opt_reserved_mb, Opt_gid_derivation, + Opt_default_normal, Opt_err, }; @@ -45,6 +46,7 @@ static const match_table_t sdcardfs_tokens = { {Opt_userid, "userid=%d"}, {Opt_multiuser, "multiuser"}, {Opt_gid_derivation, "derive_gid"}, + {Opt_default_normal, "default_normal"}, {Opt_reserved_mb, "reserved_mb=%u"}, {Opt_err, NULL} }; @@ -68,6 +70,7 @@ static int parse_options(struct super_block *sb, char *options, int silent, opts->reserved_mb = 0; /* by default, gid derivation is off */ opts->gid_derivation = false; + vfsopts->default_normal = false; *debug = 0; @@ -122,6 +125,8 @@ static int parse_options(struct super_block *sb, char *options, int silent, case Opt_gid_derivation: opts->gid_derivation = true; break; + case Opt_default_normal: + vfsopts->default_normal = true; /* unknown option */ default: if (!silent) @@ -175,6 +180,7 @@ int parse_options_remount(struct super_block *sb, char *options, int silent, return 0; vfsopts->mask = option; break; + case Opt_default_normal: case Opt_multiuser: case Opt_userid: case Opt_fsuid: diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h index 39490322c6098..5ef5ddfc725ef 100644 --- a/fs/sdcardfs/sdcardfs.h +++ b/fs/sdcardfs/sdcardfs.h @@ -226,6 +226,7 @@ struct sdcardfs_mount_options { struct sdcardfs_vfsmount_options { gid_t gid; mode_t mask; + bool default_normal; }; extern int parse_options_remount(struct super_block *sb, char *options, int silent, @@ -417,7 +418,7 @@ static inline int get_gid(struct vfsmount *mnt, { struct sdcardfs_vfsmount_options *opts = mnt->data; - if (opts->gid == AID_SDCARD_RW) + if (opts->gid == AID_SDCARD_RW && !opts->default_normal) /* As an optimization, certain trusted system components only run * as owner but operate across all users. Since we're now handing * out the sdcard_rw GID only to trusted apps, we're okay relaxing diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c index b89947d878e33..a28b40f5adc83 100644 --- a/fs/sdcardfs/super.c +++ b/fs/sdcardfs/super.c @@ -304,6 +304,8 @@ static int sdcardfs_show_options(struct vfsmount *mnt, struct seq_file *m, seq_printf(m, ",userid=%u", opts->fs_user_id); if (opts->gid_derivation) seq_puts(m, ",derive_gid"); + if (vfsopts->default_normal) + seq_puts(m, ",default_normal"); if (opts->reserved_mb != 0) seq_printf(m, ",reserved=%uMB", opts->reserved_mb); From 0990498c9c184fb4ea34d9c725dcc9acc10d3399 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Mon, 8 Jan 2018 13:57:36 -0800 Subject: [PATCH 181/508] ANDROID: sdcardfs: Fix missing break on default_normal Signed-off-by: Daniel Rosenberg Bug: 64672411 Change-Id: I98796df95dc9846adb77a11f49a1a254fb1618b1 --- fs/sdcardfs/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c index 50e186b833412..89ca921913552 100644 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -127,6 +127,7 @@ static int parse_options(struct super_block *sb, char *options, int silent, break; case Opt_default_normal: vfsopts->default_normal = true; + break; /* unknown option */ default: if (!silent) From c7cf5b498fd7c83ae0aff2cdb6e90cec20dfde72 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Thu, 18 Jan 2018 16:17:16 -0800 Subject: [PATCH 182/508] ANDROID: sdcardfs: Move default_normal to superblock Moving default_normal from mount info to superblock info as it doesn't need to change between mount points. Signed-off-by: Daniel Rosenberg Bug: 72158116 Change-Id: I16c6a0577c601b4f7566269f7e189fcf697afd4e --- fs/sdcardfs/inode.c | 7 ++++--- fs/sdcardfs/main.c | 4 ++-- fs/sdcardfs/sdcardfs.h | 10 ++++++---- fs/sdcardfs/super.c | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 36d54d6fa16d7..f33ab0aa7944c 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -643,7 +643,7 @@ static int sdcardfs_permission(struct vfsmount *mnt, struct inode *inode, int ma */ copy_attrs(&tmp, inode); tmp.i_uid = make_kuid(&init_user_ns, top->d_uid); - tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, top)); + tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, inode->i_sb, top)); tmp.i_mode = (inode->i_mode & S_IFMT) | get_mode(mnt, SDCARDFS_I(inode), top); data_put(top); @@ -720,7 +720,7 @@ static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct */ copy_attrs(&tmp, inode); tmp.i_uid = make_kuid(&init_user_ns, top->d_uid); - tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, top)); + tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, dentry->d_sb, top)); tmp.i_mode = (inode->i_mode & S_IFMT) | get_mode(mnt, SDCARDFS_I(inode), top); tmp.i_size = i_size_read(inode); @@ -821,6 +821,7 @@ static int sdcardfs_fillattr(struct vfsmount *mnt, { struct sdcardfs_inode_info *info = SDCARDFS_I(inode); struct sdcardfs_inode_data *top = top_data_get(info); + struct super_block *sb = inode->i_sb; if (!top) return -EINVAL; @@ -830,7 +831,7 @@ static int sdcardfs_fillattr(struct vfsmount *mnt, stat->mode = (inode->i_mode & S_IFMT) | get_mode(mnt, info, top); stat->nlink = inode->i_nlink; stat->uid = make_kuid(&init_user_ns, top->d_uid); - stat->gid = make_kgid(&init_user_ns, get_gid(mnt, top)); + stat->gid = make_kgid(&init_user_ns, get_gid(mnt, sb, top)); stat->rdev = inode->i_rdev; stat->size = i_size_read(inode); stat->atime = inode->i_atime; diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c index 89ca921913552..379037e2f70dd 100644 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -70,7 +70,7 @@ static int parse_options(struct super_block *sb, char *options, int silent, opts->reserved_mb = 0; /* by default, gid derivation is off */ opts->gid_derivation = false; - vfsopts->default_normal = false; + opts->default_normal = false; *debug = 0; @@ -126,7 +126,7 @@ static int parse_options(struct super_block *sb, char *options, int silent, opts->gid_derivation = true; break; case Opt_default_normal: - vfsopts->default_normal = true; + opts->default_normal = true; break; /* unknown option */ default: diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h index 5ef5ddfc725ef..13855986a02b6 100644 --- a/fs/sdcardfs/sdcardfs.h +++ b/fs/sdcardfs/sdcardfs.h @@ -220,13 +220,13 @@ struct sdcardfs_mount_options { userid_t fs_user_id; bool multiuser; bool gid_derivation; + bool default_normal; unsigned int reserved_mb; }; struct sdcardfs_vfsmount_options { gid_t gid; mode_t mask; - bool default_normal; }; extern int parse_options_remount(struct super_block *sb, char *options, int silent, @@ -414,11 +414,13 @@ static inline void set_top(struct sdcardfs_inode_info *info, } static inline int get_gid(struct vfsmount *mnt, + struct super_block *sb, struct sdcardfs_inode_data *data) { - struct sdcardfs_vfsmount_options *opts = mnt->data; + struct sdcardfs_vfsmount_options *vfsopts = mnt->data; + struct sdcardfs_sb_info *sbi = SDCARDFS_SB(sb); - if (opts->gid == AID_SDCARD_RW && !opts->default_normal) + if (vfsopts->gid == AID_SDCARD_RW && !sbi->options.default_normal) /* As an optimization, certain trusted system components only run * as owner but operate across all users. Since we're now handing * out the sdcard_rw GID only to trusted apps, we're okay relaxing @@ -427,7 +429,7 @@ static inline int get_gid(struct vfsmount *mnt, */ return AID_SDCARD_RW; else - return multiuser_get_uid(data->userid, opts->gid); + return multiuser_get_uid(data->userid, vfsopts->gid); } static inline int get_mode(struct vfsmount *mnt, diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c index a28b40f5adc83..87d6f836592e8 100644 --- a/fs/sdcardfs/super.c +++ b/fs/sdcardfs/super.c @@ -304,7 +304,7 @@ static int sdcardfs_show_options(struct vfsmount *mnt, struct seq_file *m, seq_printf(m, ",userid=%u", opts->fs_user_id); if (opts->gid_derivation) seq_puts(m, ",derive_gid"); - if (vfsopts->default_normal) + if (opts->default_normal) seq_puts(m, ",default_normal"); if (opts->reserved_mb != 0) seq_printf(m, ",reserved=%uMB", opts->reserved_mb); From c43245f96d4f1060e0cd3e9a7647adb248f4a7ce Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Tue, 23 Jan 2018 14:34:38 -0800 Subject: [PATCH 183/508] ANDROID: xattr: Pass EOPNOTSUPP to permission2 The permission call for xattr operations happens regardless of whether or not the xattr functions are implemented. The xattr functions currently don't have support for permission2. Passing EOPNOTSUPP as the mount point in xattr_permission allows us to return EOPNOTSUPP early in permission2, if the filesystem supports it. Change-Id: I9d07e4cd633cf40af60450ffbff7ac5c1b4e8c2c Signed-off-by: Daniel Rosenberg Bug: 35848445 --- fs/sdcardfs/inode.c | 2 ++ fs/xattr.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index f33ab0aa7944c..5ed714d66b3a6 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -627,6 +627,8 @@ static int sdcardfs_permission(struct vfsmount *mnt, struct inode *inode, int ma struct inode tmp; struct sdcardfs_inode_data *top = top_data_get(SDCARDFS_I(inode)); + if (IS_ERR(mnt)) + return PTR_ERR(mnt); if (!top) return -EINVAL; diff --git a/fs/xattr.c b/fs/xattr.c index 2ac964e32daf4..af43163e2ad9a 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -70,7 +70,7 @@ xattr_permission(struct inode *inode, const char *name, int mask) return -EPERM; } - return inode_permission(inode, mask); + return inode_permission2(ERR_PTR(-EOPNOTSUPP), inode, mask); } /** From 1492f9a01502280a9d084200202ebbd2b3b37c40 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Mon, 29 Jan 2018 21:31:21 -0800 Subject: [PATCH 184/508] ANDROID: sdcardfs: Use lower getattr times/size We now use the lower filesystem's getattr for time and size related information. Change-Id: I3dd05614a0c2837a13eeb033444fbdf070ddce2a Signed-off-by: Daniel Rosenberg Bug: 72007585 --- fs/sdcardfs/inode.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 5ed714d66b3a6..6f04a18ad503f 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -818,8 +818,8 @@ static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct return err; } -static int sdcardfs_fillattr(struct vfsmount *mnt, - struct inode *inode, struct kstat *stat) +static int sdcardfs_fillattr(struct vfsmount *mnt, struct inode *inode, + struct kstat *lower_stat, struct kstat *stat) { struct sdcardfs_inode_info *info = SDCARDFS_I(inode); struct sdcardfs_inode_data *top = top_data_get(info); @@ -835,12 +835,12 @@ static int sdcardfs_fillattr(struct vfsmount *mnt, stat->uid = make_kuid(&init_user_ns, top->d_uid); stat->gid = make_kgid(&init_user_ns, get_gid(mnt, sb, top)); stat->rdev = inode->i_rdev; - stat->size = i_size_read(inode); - stat->atime = inode->i_atime; - stat->mtime = inode->i_mtime; - stat->ctime = inode->i_ctime; - stat->blksize = (1 << inode->i_blkbits); - stat->blocks = inode->i_blocks; + stat->size = lower_stat->size; + stat->atime = lower_stat->atime; + stat->mtime = lower_stat->mtime; + stat->ctime = lower_stat->ctime; + stat->blksize = lower_stat->blksize; + stat->blocks = lower_stat->blocks; data_put(top); return 0; } @@ -866,8 +866,7 @@ static int sdcardfs_getattr(struct vfsmount *mnt, struct dentry *dentry, goto out; sdcardfs_copy_and_fix_attrs(dentry->d_inode, lower_path.dentry->d_inode); - err = sdcardfs_fillattr(mnt, dentry->d_inode, stat); - stat->blocks = lower_stat.blocks; + err = sdcardfs_fillattr(mnt, dentry->d_inode, &lower_stat, stat); out: sdcardfs_put_lower_path(dentry, &lower_path); return err; From 1fcd78ac556119a40a0fda5ee46621a99c6d20ca Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Tue, 23 Jan 2018 17:51:26 -0800 Subject: [PATCH 185/508] Revert "ANDROID: sdcardfs: notify lower file of opens" This reverts commit fd825dd8ffd9c4873f80438c3030dd21c204512d. Instead of calling notify within sdcardfs, which reverse the order of notifications during an open with truncate, we'll make fs_notify worry about it. Change-Id: Ic634401c0f223500066300a4df8b1453a0b35b60 Bug: 70706497 Signed-off-by: Daniel Rosenberg --- fs/sdcardfs/file.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c index 0c6e4659d4e6a..0fe08c7856a5e 100644 --- a/fs/sdcardfs/file.c +++ b/fs/sdcardfs/file.c @@ -18,7 +18,6 @@ * General Public License. */ -#include #include "sdcardfs.h" #ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE #include @@ -260,7 +259,6 @@ static int sdcardfs_open(struct inode *inode, struct file *file) fput(lower_file); /* fput calls dput for lower_dentry */ } } else { - fsnotify_open(lower_file); sdcardfs_set_lower_file(file, lower_file); } From 330a1fdb39fe669c5cb4482e3dd2dcfc5583b385 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Thu, 1 Feb 2018 16:52:22 -0800 Subject: [PATCH 186/508] ANDROID: sdcardfs: Protect set_top If the top is changed while we're attempting to use it, it's possible that the reference will be put while we are in the process of grabbing a reference. Now we grab a spinlock to protect grabbing our reference count. Additionally, we now set the inode_info's top value to point to it's own data when initializing, which makes tracking changes easier. Change-Id: If15748c786ce4c0480ab8c5051a92523aff284d2 Signed-off-by: Daniel Rosenberg --- fs/sdcardfs/derived_perm.c | 28 +++++++++++++--------------- fs/sdcardfs/main.c | 6 ++---- fs/sdcardfs/sdcardfs.h | 26 ++++++++++++++++++-------- fs/sdcardfs/super.c | 3 +++ 4 files changed, 36 insertions(+), 27 deletions(-) diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c index bb625735ec2a7..c12da349758f0 100644 --- a/fs/sdcardfs/derived_perm.c +++ b/fs/sdcardfs/derived_perm.c @@ -32,23 +32,20 @@ static void inherit_derived_state(struct inode *parent, struct inode *child) ci->data->under_android = pi->data->under_android; ci->data->under_cache = pi->data->under_cache; ci->data->under_obb = pi->data->under_obb; - set_top(ci, pi->top_data); } /* helper function for derived state */ void setup_derived_state(struct inode *inode, perm_t perm, userid_t userid, - uid_t uid, bool under_android, - struct sdcardfs_inode_data *top) + uid_t uid) { struct sdcardfs_inode_info *info = SDCARDFS_I(inode); info->data->perm = perm; info->data->userid = userid; info->data->d_uid = uid; - info->data->under_android = under_android; + info->data->under_android = false; info->data->under_cache = false; info->data->under_obb = false; - set_top(info, top); } /* While renaming, there is a point where we want the path from dentry, @@ -58,8 +55,8 @@ void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, const struct qstr *name) { struct sdcardfs_inode_info *info = SDCARDFS_I(dentry->d_inode); - struct sdcardfs_inode_data *parent_data = - SDCARDFS_I(parent->d_inode)->data; + struct sdcardfs_inode_info *parent_info = SDCARDFS_I(parent->d_inode); + struct sdcardfs_inode_data *parent_data = parent_info->data; appid_t appid; unsigned long user_num; int err; @@ -80,13 +77,15 @@ void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, inherit_derived_state(parent->d_inode, dentry->d_inode); /* Files don't get special labels */ - if (!S_ISDIR(dentry->d_inode->i_mode)) + if (!S_ISDIR(dentry->d_inode->i_mode)) { + set_top(info, parent_info); return; + } /* Derive custom permissions based on parent and current node */ switch (parent_data->perm) { case PERM_INHERIT: case PERM_ANDROID_PACKAGE_CACHE: - /* Already inherited above */ + set_top(info, parent_info); break; case PERM_PRE_ROOT: /* Legacy internal layout places users at top level */ @@ -96,7 +95,6 @@ void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, info->data->userid = 0; else info->data->userid = user_num; - set_top(info, info->data); break; case PERM_ROOT: /* Assume masked off by default. */ @@ -104,24 +102,24 @@ void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, /* App-specific directories inside; let anyone traverse */ info->data->perm = PERM_ANDROID; info->data->under_android = true; - set_top(info, info->data); + } else { + set_top(info, parent_info); } break; case PERM_ANDROID: if (qstr_case_eq(name, &q_data)) { /* App-specific directories inside; let anyone traverse */ info->data->perm = PERM_ANDROID_DATA; - set_top(info, info->data); } else if (qstr_case_eq(name, &q_obb)) { /* App-specific directories inside; let anyone traverse */ info->data->perm = PERM_ANDROID_OBB; info->data->under_obb = true; - set_top(info, info->data); /* Single OBB directory is always shared */ } else if (qstr_case_eq(name, &q_media)) { /* App-specific directories inside; let anyone traverse */ info->data->perm = PERM_ANDROID_MEDIA; - set_top(info, info->data); + } else { + set_top(info, parent_info); } break; case PERM_ANDROID_OBB: @@ -132,13 +130,13 @@ void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, if (appid != 0 && !is_excluded(name->name, parent_data->userid)) info->data->d_uid = multiuser_get_uid(parent_data->userid, appid); - set_top(info, info->data); break; case PERM_ANDROID_PACKAGE: if (qstr_case_eq(name, &q_cache)) { info->data->perm = PERM_ANDROID_PACKAGE_CACHE; info->data->under_cache = true; } + set_top(info, parent_info); break; } } diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c index 379037e2f70dd..1c00f0fc0ca52 100644 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -341,13 +341,11 @@ static int sdcardfs_read_super(struct vfsmount *mnt, struct super_block *sb, mutex_lock(&sdcardfs_super_list_lock); if (sb_info->options.multiuser) { setup_derived_state(sb->s_root->d_inode, PERM_PRE_ROOT, - sb_info->options.fs_user_id, AID_ROOT, - false, SDCARDFS_I(sb->s_root->d_inode)->data); + sb_info->options.fs_user_id, AID_ROOT); snprintf(sb_info->obbpath_s, PATH_MAX, "%s/obb", dev_name); } else { setup_derived_state(sb->s_root->d_inode, PERM_ROOT, - sb_info->options.fs_user_id, AID_ROOT, - false, SDCARDFS_I(sb->s_root->d_inode)->data); + sb_info->options.fs_user_id, AID_ROOT); snprintf(sb_info->obbpath_s, PATH_MAX, "%s/Android/obb", dev_name); } fixup_tmp_permissions(sb->s_root->d_inode); diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h index 13855986a02b6..cc587ec85116e 100644 --- a/fs/sdcardfs/sdcardfs.h +++ b/fs/sdcardfs/sdcardfs.h @@ -201,6 +201,7 @@ struct sdcardfs_inode_info { struct sdcardfs_inode_data *data; /* top folder for ownership */ + spinlock_t top_lock; struct sdcardfs_inode_data *top_data; struct inode vfs_inode; @@ -380,7 +381,12 @@ static inline struct sdcardfs_inode_data *data_get( static inline struct sdcardfs_inode_data *top_data_get( struct sdcardfs_inode_info *info) { - return data_get(info->top_data); + struct sdcardfs_inode_data *top_data; + + spin_lock(&info->top_lock); + top_data = data_get(info->top_data); + spin_unlock(&info->top_lock); + return top_data; } extern void data_release(struct kref *ref); @@ -402,15 +408,20 @@ static inline void release_own_data(struct sdcardfs_inode_info *info) } static inline void set_top(struct sdcardfs_inode_info *info, - struct sdcardfs_inode_data *top) + struct sdcardfs_inode_info *top_owner) { - struct sdcardfs_inode_data *old_top = info->top_data; + struct sdcardfs_inode_data *old_top; + struct sdcardfs_inode_data *new_top = NULL; + + if (top_owner) + new_top = top_data_get(top_owner); - if (top) - data_get(top); - info->top_data = top; + spin_lock(&info->top_lock); + old_top = info->top_data; + info->top_data = new_top; if (old_top) data_put(old_top); + spin_unlock(&info->top_lock); } static inline int get_gid(struct vfsmount *mnt, @@ -516,8 +527,7 @@ struct limit_search { }; extern void setup_derived_state(struct inode *inode, perm_t perm, - userid_t userid, uid_t uid, bool under_android, - struct sdcardfs_inode_data *top); + userid_t userid, uid_t uid); extern void get_derived_permission(struct dentry *parent, struct dentry *dentry); extern void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, const struct qstr *name); extern void fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit); diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c index 87d6f836592e8..cffcdb11cb8ac 100644 --- a/fs/sdcardfs/super.c +++ b/fs/sdcardfs/super.c @@ -215,6 +215,9 @@ static struct inode *sdcardfs_alloc_inode(struct super_block *sb) i->data = d; kref_init(&d->refcount); + i->top_data = d; + spin_lock_init(&i->top_lock); + kref_get(&d->refcount); i->vfs_inode.i_version = 1; return &i->vfs_inode; From 711b1307cd7037025c46d48a125db3d16be14d6e Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Tue, 20 Feb 2018 20:25:45 -0800 Subject: [PATCH 187/508] ANDROID: sdcardfs: Hold i_mutex for i_size_write When we call i_size_write, we must be holding i_mutex to avoid possible lockups on 32 bit/SMP architectures. This is not necessary on 64 bit architectures. Change-Id: Ic3b946507c54d81b5c9046f9b57d25d4b0f9feef Signed-off-by: Daniel Rosenberg Bug: 73287721 --- fs/sdcardfs/file.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c index 0fe08c7856a5e..15f7a72f15819 100644 --- a/fs/sdcardfs/file.c +++ b/fs/sdcardfs/file.c @@ -62,6 +62,7 @@ static ssize_t sdcardfs_write(struct file *file, const char __user *buf, int err; struct file *lower_file; struct dentry *dentry = file->f_path.dentry; + struct inode *inode = dentry->d_inode; /* check disk space */ if (!check_min_free_space(dentry, count, 0)) { @@ -73,10 +74,12 @@ static ssize_t sdcardfs_write(struct file *file, const char __user *buf, err = vfs_write(lower_file, buf, count, ppos); /* update our inode times+sizes upon a successful lower write */ if (err >= 0) { - fsstack_copy_inode_size(dentry->d_inode, - file_inode(lower_file)); - fsstack_copy_attr_times(dentry->d_inode, - file_inode(lower_file)); + if (sizeof(loff_t) > sizeof(long)) + mutex_lock(&inode->i_mutex); + fsstack_copy_inode_size(inode, file_inode(lower_file)); + fsstack_copy_attr_times(inode, file_inode(lower_file)); + if (sizeof(loff_t) > sizeof(long)) + mutex_unlock(&inode->i_mutex); } return err; @@ -391,6 +394,7 @@ ssize_t sdcardfs_write_iter(struct kiocb *iocb, struct iov_iter *iter) { int err; struct file *file = iocb->ki_filp, *lower_file; + struct inode *inode = file->f_path.dentry->d_inode; lower_file = sdcardfs_lower_file(file); if (!lower_file->f_op->write_iter) { @@ -405,10 +409,12 @@ ssize_t sdcardfs_write_iter(struct kiocb *iocb, struct iov_iter *iter) fput(lower_file); /* update upper inode times/sizes as needed */ if (err >= 0 || err == -EIOCBQUEUED) { - fsstack_copy_inode_size(file->f_path.dentry->d_inode, - file_inode(lower_file)); - fsstack_copy_attr_times(file->f_path.dentry->d_inode, - file_inode(lower_file)); + if (sizeof(loff_t) > sizeof(long)) + mutex_lock(&inode->i_mutex); + fsstack_copy_inode_size(inode, file_inode(lower_file)); + fsstack_copy_attr_times(inode, file_inode(lower_file)); + if (sizeof(loff_t) > sizeof(long)) + mutex_unlock(&inode->i_mutex); } out: return err; From 5f65cc0e7298a9655e3119c3d3aa385a20d677af Mon Sep 17 00:00:00 2001 From: Ritesh Harjani Date: Mon, 4 Dec 2017 09:51:07 +0530 Subject: [PATCH 188/508] ANDROID: sdcardfs: Set num in extension_details during make_item Without this patch when you delete an extension from configfs it still exists in the hash table data structures and we are unable to delete it or change it's group. This happens because during deletion the key & value is taken from extension_details, and was not properly set. Fix it by this patch. Change-Id: I7c20cb1ab4d99e6aceadcb5ef850f0bb47f18be8 Signed-off-by: Ritesh Harjani Signed-off-by: Daniel Rosenberg Bug: 73055997 --- fs/sdcardfs/packagelist.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/sdcardfs/packagelist.c b/fs/sdcardfs/packagelist.c index d552dde9c1309..74542e9087251 100644 --- a/fs/sdcardfs/packagelist.c +++ b/fs/sdcardfs/packagelist.c @@ -645,6 +645,7 @@ static struct config_item *extension_details_make_item(struct config_group *grou return ERR_PTR(-ENOMEM); } qstr_init(&extension_details->name, tmp); + extension_details->num = extensions_value->num; ret = insert_ext_gid_entry(&extension_details->name, extensions_value->num); if (ret) { From 2c5f33580c915878990cb7fac1c69ac40db9ca92 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Fri, 23 Mar 2018 13:49:02 +0530 Subject: [PATCH 189/508] drivers: platform: Add xiaomi 8953 support --- drivers/platform/Kconfig | 1 + drivers/platform/xiaomi/Kconfig | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 drivers/platform/xiaomi/Kconfig diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig index b9b5ac01a0bfb..832b358d5ee8f 100644 --- a/drivers/platform/Kconfig +++ b/drivers/platform/Kconfig @@ -7,4 +7,5 @@ source "drivers/platform/chrome/Kconfig" if ARCH_MSM source "drivers/platform/msm/Kconfig" +source "drivers/platform/xiaomi/Kconfig" endif diff --git a/drivers/platform/xiaomi/Kconfig b/drivers/platform/xiaomi/Kconfig new file mode 100644 index 0000000000000..cbd081fcd2362 --- /dev/null +++ b/drivers/platform/xiaomi/Kconfig @@ -0,0 +1,23 @@ +# Xiaomi configuration options + +config MACH_XIAOMI_MSM8953 + bool "Xiaomi MSM8953" + depends on ARCH_MSM8953 + help + Support for MSM8953 Xiaomi variants + +menu "Xiaomi board selection" + +config MACH_XIAOMI_MIDO + bool "Mido board" + select MACH_XIAOMI_MSM8953 + help + Support for Xiaomi Redmi note 3 + +config MACH_XIAOMI_TISSOT + bool "Tissot board" + select MACH_XIAOMI_MSM8953 + help + Support for Xiomi MI A1 tissot + +endmenu From 6f463d31de09e214f6c30553ba68ad2e38fb4376 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Sat, 20 May 2017 12:39:30 +0000 Subject: [PATCH 190/508] Revert "msm: isp: Add support for VFE resolution limit" This reverts commit ebdc70c8efc13e523fcc42bb0a582f0f0febafdc. --- drivers/media/platform/msm/camera_v2/isp/msm_isp.h | 2 ++ .../media/platform/msm/camera_v2/isp/msm_isp47.c | 4 ++++ .../media/platform/msm/camera_v2/isp/msm_isp_util.c | 2 ++ include/uapi/media/msmb_isp.h | 13 +++++++++++++ 4 files changed, 21 insertions(+) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index d223401d8688e..b6202335d4c1d 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -770,7 +770,9 @@ struct vfe_device { uint32_t is_split; uint32_t dual_vfe_enable; unsigned long page_fault_addr; +#ifndef CONFIG_MACH_XIAOMI_MIDO uint32_t vfe_hw_limit; +#endif /* Debug variables */ int dump_reg; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c index fdf9d0c442da0..f8cdb36f0bf5a 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -2598,8 +2598,10 @@ int msm_vfe47_enable_regulators(struct vfe_device *vfe_dev, int enable) int msm_vfe47_get_platform_data(struct vfe_device *vfe_dev) { int rc = 0; +#ifndef CONFIG_MACH_XIAOMI_MIDO void __iomem *vfe_fuse_base; uint32_t vfe_fuse_base_size; +#endif vfe_dev->vfe_base = msm_camera_get_reg_base(vfe_dev->pdev, "vfe", 0); if (!vfe_dev->vfe_base) @@ -2624,6 +2626,7 @@ int msm_vfe47_get_platform_data(struct vfe_device *vfe_dev) rc = -ENOMEM; goto get_res_fail; } +#ifndef CONFIG_MACH_XIAOMI_MIDO vfe_dev->vfe_hw_limit = 0; vfe_fuse_base = msm_camera_get_reg_base(vfe_dev->pdev, "vfe_fuse", 0); @@ -2636,6 +2639,7 @@ int msm_vfe47_get_platform_data(struct vfe_device *vfe_dev) msm_camera_put_reg_base(vfe_dev->pdev, vfe_fuse_base, "vfe_fuse", 0); } +#endif rc = vfe_dev->hw_info->vfe_ops.platform_ops.get_regulators(vfe_dev); if (rc) goto get_regulator_fail; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index a78dec3337385..710a403113e98 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -1423,6 +1423,7 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, vfe_dev->vfe_ub_policy = *cfg_data; break; } +#ifndef CONFIG_MACH_XIAOMI_MIDO case GET_VFE_HW_LIMIT: { uint32_t *hw_limit = NULL; @@ -1437,6 +1438,7 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, *hw_limit = vfe_dev->vfe_hw_limit; break; } +#endif } return 0; } diff --git a/include/uapi/media/msmb_isp.h b/include/uapi/media/msmb_isp.h index 429e35339a0a2..8e4880d548d4d 100644 --- a/include/uapi/media/msmb_isp.h +++ b/include/uapi/media/msmb_isp.h @@ -24,7 +24,9 @@ #define ISP_STATS_STREAM_BIT 0x80000000 +#ifndef CONFIG_MACH_XIAOMI_MIDO #define VFE_HW_LIMIT 1 +#endif struct msm_vfe_cfg_cmd_list; @@ -502,7 +504,9 @@ enum msm_vfe_reg_cfg_type { VFE_HW_UPDATE_UNLOCK, SET_WM_UB_SIZE, SET_UB_POLICY, +#ifndef CONFIG_MACH_XIAOMI_MIDO GET_VFE_HW_LIMIT, +#endif }; struct msm_vfe_cfg_cmd2 { @@ -959,7 +963,9 @@ enum msm_isp_ioctl_cmd_code { MSM_ISP_FETCH_ENG_MULTI_PASS_START, MSM_ISP_MAP_BUF_START_MULTI_PASS_FE, MSM_ISP_CFG_HW_STATE, +#ifndef CONFIG_MACH_XIAOMI_MIDO MSM_ISP_AHB_CLK_CFG, +#endif MSM_ISP_UPDATE_FE_FRAME_ID, MSM_ISP_RESTART_FE, MSM_ISP32_REQUEST_STREAM, @@ -1077,6 +1083,11 @@ enum msm_isp_ioctl_cmd_code { _IOWR('V', MSM_ISP_UNMAP_BUF, \ struct msm_isp_unmap_buf_req) +#ifdef CONFIG_MACH_XIAOMI_MIDO +#define VIDIOC_MSM_ISP_AHB_CLK_CFG \ + _IOWR('V', BASE_VIDIOC_PRIVATE+25, struct msm_isp_ahb_clk_cfg) +#endif + #define VIDIOC_MSM_ISP_FETCH_ENG_MULTI_PASS_START \ _IOWR('V', MSM_ISP_FETCH_ENG_MULTI_PASS_START, \ struct msm_vfe_fetch_eng_multi_pass_start) @@ -1089,8 +1100,10 @@ enum msm_isp_ioctl_cmd_code { _IOWR('V', MSM_ISP_CFG_HW_STATE, \ struct msm_vfe_axi_stream_cfg_cmd) +#ifndef CONFIG_MACH_XIAOMI_MIDO #define VIDIOC_MSM_ISP_AHB_CLK_CFG \ _IOWR('V', MSM_ISP_AHB_CLK_CFG, struct msm_isp_ahb_clk_cfg) +#endif #define VIDIOC_MSM_ISP_BUF_DONE \ _IOWR('V', BASE_VIDIOC_PRIVATE+21, struct msm_isp32_event_data) From ff33ffedb08def98773b7aeda50737889f811694 Mon Sep 17 00:00:00 2001 From: Shadab Naseem Date: Tue, 5 Dec 2017 11:37:47 +0530 Subject: [PATCH 191/508] ARM: dts: msm: Add device tree support for apq8009 Dragon Board Add device tree support for apq8009 IOT dragon board for 1GB variant. Change-Id: I4f2c25c86a080df9c8204e7f2035d22ccb4f4333 Signed-off-by: Shadab Naseem --- arch/arm/boot/dts/qcom/Makefile | 3 +- arch/arm/boot/dts/qcom/apq8009-dragon.dts | 123 ++++++++++++++++++++++ 2 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/qcom/apq8009-dragon.dts diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index acd211987297b..53ea8bb11d0d3 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -347,7 +347,8 @@ dtb-$(CONFIG_ARCH_MSM8909) += msm8909-pm8916-mtp.dtb \ msm8909-1gb-mtp.dtb \ msm8909-1gb-rcm.dtb \ msm8909-pm8916-1gb-rcm.dtb \ - msm8909-1gb-cdp.dtb + msm8909-1gb-cdp.dtb \ + apq8009-dragon.dtb ifeq ($(CONFIG_ARM64),y) always := $(dtb-y) diff --git a/arch/arm/boot/dts/qcom/apq8009-dragon.dts b/arch/arm/boot/dts/qcom/apq8009-dragon.dts new file mode 100644 index 0000000000000..fb21bfee01f42 --- /dev/null +++ b/arch/arm/boot/dts/qcom/apq8009-dragon.dts @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "msm8909-mtp.dtsi" +#include "msm8909-pm8916.dtsi" +#include "msm8909-pm8916-mtp.dtsi" +#include "apq8009-audio-external_codec.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. APQ8009 Dragon Board"; + compatible = "qcom,apq8009-mtp", "qcom,apq8009", "qcom,mtp"; + qcom,msm-id = <265 2>; + qcom,board-id= <32 0x0>; +}; + +&soc { + ext-codec { + qcom,msm-mbhc-hphl-swh = <0>; + qcom,audio-routing = + "AIF4 VI", "MCLK", + "RX_BIAS", "MCLK", + "MADINPUT", "MCLK", + "AMIC2", "MIC BIAS2", + "MIC BIAS2", "Headset Mic", + "DMIC0", "MIC BIAS1", + "MIC BIAS1", "Digital Mic0", + "DMIC1", "MIC BIAS1", + "MIC BIAS1", "Digital Mic1", + "DMIC2", "MIC BIAS3", + "MIC BIAS3", "Digital Mic2", + "DMIC3", "MIC BIAS3", + "MIC BIAS3", "Digital Mic3", + "SpkrLeft IN", "SPK1 OUT", + "SpkrRight IN", "SPK2 OUT"; + }; + + sound-9335 { + status = "disabled"; + }; + + i2c@78b8000 { + wcd9xxx_codec@d { + status = "disabled"; + }; + }; + + vph_pwr_vreg: vph_pwr_vreg { + compatible = "regulator-fixed"; + status = "ok"; + regulator-name = "vph_pwr"; + regulator-always-on; + }; + + mdss_mdp: qcom,mdss_mdp@1a00000 { + status = "disabled"; + }; +}; + +&sdhc_2 { + status = "disabled"; +}; + +&usb_otg { + interrupts = <0 134 0>,<0 140 0>,<0 136 0>; + interrupt-names = "core_irq", "async_irq", "phy_irq"; + qcom,hsusb-otg-mode = <3>; + qcom,switch-vbus-w-id; + vbus_otg-supply = <&vph_pwr_vreg>; +}; + +&external_image_mem { + reg = <0x0 0x87a00000 0x0 0x0600000>; +}; + +&modem_adsp_mem { + reg = <0x0 0x88000000 0x0 0x01e00000>; +}; + +&peripheral_mem { + reg = <0x0 0x89e00000 0x0 0x0700000>; +}; + +&i2c_4 { + smb1360_otg_supply: smb1360-chg-fg@14 { + compatible = "qcom,smb1360-chg-fg"; + reg = <0x14>; + interrupt-parent = <&msm_gpio>; + interrupts = <58 8>; + pinctrl-names = "default"; + pinctrl-0 = <&smb_int_default>; + qcom,charging-disabled; + qcom,empty-soc-disabled; + qcom,chg-inhibit-disabled; + qcom,float-voltage-mv = <4200>; + qcom,iterm-ma = <200>; + qcom,recharge-thresh-mv = <100>; + qcom,thermal-mitigation = <1500 700 600 0>; + regulator-name = "smb1360_otg_vreg"; + status= "disabled"; + }; +}; + +&pm8916_chg { + status = "ok"; + qcom,use-external-charger; +}; + +&pm8916_bms { + status = "ok"; + qcom,disable-bms; +}; From 284ceb10f83c7dc9b972b00821fc2562375fdbf8 Mon Sep 17 00:00:00 2001 From: AnilKumar Chimata Date: Mon, 25 Sep 2017 13:07:07 +0530 Subject: [PATCH 192/508] init: Update CMDLINE buffer length Update cmdline buffer length to accommodate for AVB2.0 boot arguments. Change-Id: Id877cfb23c30d90c826582a33cb10cc9ac8dd3b0 Signed-off-by: AnilKumar Chimata --- arch/arm/include/uapi/asm/setup.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/include/uapi/asm/setup.h b/arch/arm/include/uapi/asm/setup.h index 979ff40164040..b4d1bea21a2d2 100644 --- a/arch/arm/include/uapi/asm/setup.h +++ b/arch/arm/include/uapi/asm/setup.h @@ -16,7 +16,7 @@ #include -#define COMMAND_LINE_SIZE 1024 +#define COMMAND_LINE_SIZE 2048 /* The list ends with an ATAG_NONE node. */ #define ATAG_NONE 0x00000000 From e3047916aa3ab053814095926b5aee5f8299978a Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Sat, 20 May 2017 15:57:28 +0000 Subject: [PATCH 193/508] Revert "msm: camera: isp: Handle standby mode for B+M" This reverts commit 12895349181eee37f58049a5f6c6872bf585e81c. --- .../msm/camera_v2/isp/msm_isp_axi_util.c | 22 +++++++++++++++++-- .../msm/camera_v2/isp/msm_isp_axi_util.h | 2 ++ .../platform/msm/camera_v2/isp/msm_isp_util.c | 2 ++ include/uapi/media/msmb_isp.h | 8 +++++-- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index bd27839576f96..bbf53214c64b6 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -2299,10 +2299,18 @@ static void msm_isp_update_camif_output_count( /*Factor in Q2 format*/ #define ISP_DEFAULT_FORMAT_FACTOR 6 #define ISP_BUS_UTILIZATION_FACTOR 6 + +#ifdef CONFIG_MACH_XIAOMI_MIDO +static int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev) +#else int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev, enum msm_vfe_hw_state hw_state) +#endif { - int i, rc = 0, frame_src, ms_type; + int i, rc = 0; +#ifndef CONFIG_MACH_XIAOMI_MIDO + int frame_src, ms_type; +#endif struct msm_vfe_axi_stream *stream_info; struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; uint64_t total_pix_bandwidth = 0, total_rdi_bandwidth = 0; @@ -2313,6 +2321,7 @@ int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev, for (i = 0; i < VFE_AXI_SRC_MAX; i++) { stream_info = &axi_data->stream_info[i]; +#ifndef CONFIG_MACH_XIAOMI_MIDO frame_src = SRC_TO_INTF(stream_info->stream_src); ms_type = vfe_dev->axi_data.src_info[frame_src]. dual_hw_ms_info.dual_hw_ms_type; @@ -2321,6 +2330,7 @@ int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev, ISP_VFE0 + vfe_dev->pdev->id, 0, 0); return rc; } +#endif if (stream_info->state == ACTIVE || stream_info->state == START_PENDING) { @@ -2962,7 +2972,11 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev, } } } +#ifdef CONFIG_MACH_XIAOMI_MIDO + msm_isp_update_stream_bandwidth(vfe_dev); +#else msm_isp_update_stream_bandwidth(vfe_dev, stream_cfg_cmd->hw_state); +#endif vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev, vfe_dev->vfe_base, wm_reload_mask); msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd); @@ -3167,7 +3181,11 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev, } msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd); - msm_isp_update_stream_bandwidth(vfe_dev, stream_cfg_cmd->hw_state); +#ifdef CONFIG_MACH_XIAOMI_MIDO + msm_isp_update_stream_bandwidth(vfe_dev); +#else + msm_isp_update_stream_bandwidth(vfe_dev, stream_cfg_cmd->hw_state); +#endif for (i = 0; i < stream_cfg_cmd->num_streams; i++) { stream_info = &axi_data->stream_info[ diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h index f0df706952126..8eca196fcd87c 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h @@ -52,8 +52,10 @@ void msm_isp_reset_framedrop(struct vfe_device *vfe_dev, int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg); void msm_isp_get_avtimer_ts(struct msm_isp_timestamp *time_stamp); int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg); +#ifndef CONFIG_MACH_XIAOMI_MIDO int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev, enum msm_vfe_hw_state hw_state); +#endif int msm_isp_release_axi_stream(struct vfe_device *vfe_dev, void *arg); int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg); void msm_isp_axi_cfg_update(struct vfe_device *vfe_dev, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 710a403113e98..b09e998ff48b5 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -887,12 +887,14 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, rc = msm_isp_cfg_axi_stream(vfe_dev, arg); mutex_unlock(&vfe_dev->core_mutex); break; +#ifndef CONFIG_MACH_XIAOMI_MIDO case VIDIOC_MSM_ISP_CFG_HW_STATE: mutex_lock(&vfe_dev->core_mutex); rc = msm_isp_update_stream_bandwidth(vfe_dev, *(enum msm_vfe_hw_state *)arg); mutex_unlock(&vfe_dev->core_mutex); break; +#endif case VIDIOC_MSM_ISP_AXI_HALT: mutex_lock(&vfe_dev->core_mutex); rc = msm_isp_axi_halt(vfe_dev, arg); diff --git a/include/uapi/media/msmb_isp.h b/include/uapi/media/msmb_isp.h index 8e4880d548d4d..80248a25629c0 100644 --- a/include/uapi/media/msmb_isp.h +++ b/include/uapi/media/msmb_isp.h @@ -369,18 +369,22 @@ enum msm_vfe_axi_stream_cmd { STOP_IMMEDIATELY, }; +#ifndef CONFIG_MACH_XIAOMI_MIDO enum msm_vfe_hw_state { HW_STATE_NONE, HW_STATE_SLEEP, HW_STATE_AWAKE, }; +#endif struct msm_vfe_axi_stream_cfg_cmd { uint8_t num_streams; uint32_t stream_handle[VFE_AXI_SRC_MAX]; enum msm_vfe_axi_stream_cmd cmd; uint8_t sync_frame_id_src; +#ifndef CONFIG_MACH_XIAOMI_MIDO enum msm_vfe_hw_state hw_state; +#endif }; enum msm_vfe_axi_stream_update_type { @@ -962,8 +966,8 @@ enum msm_isp_ioctl_cmd_code { MSM_ISP_UNMAP_BUF, MSM_ISP_FETCH_ENG_MULTI_PASS_START, MSM_ISP_MAP_BUF_START_MULTI_PASS_FE, - MSM_ISP_CFG_HW_STATE, #ifndef CONFIG_MACH_XIAOMI_MIDO + MSM_ISP_CFG_HW_STATE, MSM_ISP_AHB_CLK_CFG, #endif MSM_ISP_UPDATE_FE_FRAME_ID, @@ -1096,11 +1100,11 @@ enum msm_isp_ioctl_cmd_code { _IOWR('V', MSM_ISP_MAP_BUF_START_MULTI_PASS_FE, \ struct msm_vfe_fetch_eng_multi_pass_start) +#ifndef CONFIG_MACH_XIAOMI_MIDO #define VIDIOC_MSM_ISP_CFG_HW_STATE \ _IOWR('V', MSM_ISP_CFG_HW_STATE, \ struct msm_vfe_axi_stream_cfg_cmd) -#ifndef CONFIG_MACH_XIAOMI_MIDO #define VIDIOC_MSM_ISP_AHB_CLK_CFG \ _IOWR('V', MSM_ISP_AHB_CLK_CFG, struct msm_isp_ahb_clk_cfg) #endif From 31be7456f0b534f5ba61366c463a143b53454828 Mon Sep 17 00:00:00 2001 From: LuK1337 Date: Fri, 23 Mar 2018 14:30:42 +0530 Subject: [PATCH 194/508] Revert "msm: camera: Bypass redundant creation of video node in stereo" This reverts commit 363d7dc. Change-Id: I54dd567763b7130653e3b0148398cdcad670ab3 --- .../platform/msm/camera_v2/sensor/msm_sensor.h | 2 ++ .../msm/camera_v2/sensor/msm_sensor_driver.c | 14 ++++++++++++++ include/media/msm_cam_sensor.h | 2 ++ include/uapi/media/msm_camsensor_sdk.h | 4 ++++ 4 files changed, 22 insertions(+) diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h index 8f55f453bf036..5eedd79269431 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h @@ -89,7 +89,9 @@ struct msm_sensor_ctrl_t { uint32_t set_mclk_23880000; uint8_t is_csid_tg_mode; uint32_t is_secure; +#ifndef CONFIG_MACH_XIAOMI_MIDO uint8_t bypass_video_node_creation; +#endif }; int msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void __user *argp); diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c index 20d7b9f9b1cb3..cc5d44c69d114 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c @@ -86,13 +86,17 @@ static int32_t msm_sensor_driver_create_i2c_v4l_subdev struct i2c_client *client = s_ctrl->sensor_i2c_client->client; CDBG("%s %s I2c probe succeeded\n", __func__, client->name); +#ifndef CONFIG_MACH_XIAOMI_MIDO if (0 == s_ctrl->bypass_video_node_creation) { +#endif rc = camera_init_v4l2(&client->dev, &session_id); if (rc < 0) { pr_err("failed: camera_init_i2c_v4l2 rc %d", rc); return rc; } +#ifndef CONFIG_MACH_XIAOMI_MIDO } +#endif CDBG("%s rc %d session_id %d\n", __func__, rc, session_id); snprintf(s_ctrl->msm_sd.sd.name, @@ -130,13 +134,17 @@ static int32_t msm_sensor_driver_create_v4l_subdev int32_t rc = 0; uint32_t session_id = 0; +#ifndef CONFIG_MACH_XIAOMI_MIDO if (0 == s_ctrl->bypass_video_node_creation) { +#endif rc = camera_init_v4l2(&s_ctrl->pdev->dev, &session_id); if (rc < 0) { pr_err("failed: camera_init_v4l2 rc %d", rc); return rc; } +#ifndef CONFIG_MACH_XIAOMI_MIDO } +#endif CDBG("rc %d session_id %d", rc, session_id); s_ctrl->sensordata->sensor_info->session_id = session_id; @@ -756,8 +764,10 @@ int32_t msm_sensor_driver_probe(void *setting, slave_info32->sensor_init_params; slave_info->output_format = slave_info32->output_format; +#ifndef CONFIG_MACH_XIAOMI_MIDO slave_info->bypass_video_node_creation = !!slave_info32->bypass_video_node_creation; +#endif kfree(slave_info32); } else #endif @@ -800,8 +810,10 @@ int32_t msm_sensor_driver_probe(void *setting, slave_info->sensor_init_params.position); CDBG("mount %d", slave_info->sensor_init_params.sensor_mount_angle); +#ifndef CONFIG_MACH_XIAOMI_MIDO CDBG("bypass video node creation %d", slave_info->bypass_video_node_creation); +#endif /* Validate camera id */ if (slave_info->camera_id >= MAX_CAMERAS) { pr_err("failed: invalid camera id %d max %d", @@ -968,8 +980,10 @@ int32_t msm_sensor_driver_probe(void *setting, pr_err("%s probe succeeded", slave_info->sensor_name); +#ifndef CONFIG_MACH_XIAOMI_MIDO s_ctrl->bypass_video_node_creation = slave_info->bypass_video_node_creation; +#endif /* * Update the subdevice id of flash-src based on availability in kernel. diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h index 762f1c51620cd..9674fd73754a5 100644 --- a/include/media/msm_cam_sensor.h +++ b/include/media/msm_cam_sensor.h @@ -41,7 +41,9 @@ struct msm_camera_sensor_slave_info32 { uint8_t is_init_params_valid; struct msm_sensor_init_params sensor_init_params; enum msm_sensor_output_format_t output_format; +#ifndef CONFIG_MACH_XIAOMI_MIDO uint8_t bypass_video_node_creation; +#endif }; struct msm_camera_csid_lut_params32 { diff --git a/include/uapi/media/msm_camsensor_sdk.h b/include/uapi/media/msm_camsensor_sdk.h index 83927c614e913..c841a18deaf71 100644 --- a/include/uapi/media/msm_camsensor_sdk.h +++ b/include/uapi/media/msm_camsensor_sdk.h @@ -48,7 +48,9 @@ #define MSM_EEPROM_MEMORY_MAP_MAX_SIZE 80 #define MSM_EEPROM_MAX_MEM_MAP_CNT 8 +#ifndef CONFIG_MACH_XIAOMI_MIDO #define MSM_SENSOR_BYPASS_VIDEO_NODE 1 +#endif enum msm_sensor_camera_id_t { CAMERA_0, @@ -302,7 +304,9 @@ struct msm_camera_sensor_slave_info { unsigned char is_init_params_valid; struct msm_sensor_init_params sensor_init_params; enum msm_sensor_output_format_t output_format; +#ifndef CONFIG_MACH_XIAOMI_MIDO uint8_t bypass_video_node_creation; +#endif }; struct msm_camera_i2c_reg_array { From 787050096d5122e6a33c9f4bc6622cbbe2b9e1d0 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Tue, 2 Jan 2018 13:25:51 +0530 Subject: [PATCH 195/508] arch: arm: boot: Add overlayed mido dtsi --- arch/arm/boot/dts/qcom/Makefile | 4 + .../batterydata-qrd-coslight-4v4-4100mah.dtsi | 61 ++ .../batterydata-qrd-desay-4v4-4100mah.dtsi | 62 ++ ...erydata-qrd-desay-lisheng-4v4-4100mah.dtsi | 60 ++ .../batterydata-qrd-sunwoda-4v4-4100mah.dtsi | 62 ++ ...tterydata-qrd-sunwoda-ATL-4v4-4100mah.dtsi | 60 ++ .../mido/dsi-panel-ili9885-boe-fhd-video.dtsi | 80 ++ .../mido/dsi-panel-nt35532-fhd-video.dtsi | 90 ++ .../mido/dsi-panel-nt35596-fhd-video.dtsi | 87 ++ .../dsi-panel-nt35596-tianma-fhd-video.dtsi | 93 ++ .../mido/dsi-panel-otm1911-fhd-video.dtsi | 136 +++ .../mido/dsi-panel-r63350-ebbg-fhd-video.dtsi | 77 ++ .../boot/dts/qcom/mido/msm-audio-mido.dtsi | 34 + .../mido/msm8953-camera-sensor-qrd-mido.dtsi | 931 ++++++++++++++++++ .../dts/qcom/mido/msm8953-display-mido.dtsi | 99 ++ .../dts/qcom/mido/msm8953-general-mido.dtsi | 532 ++++++++++ .../dts/qcom/mido/msm8953-memory-mido.dtsi | 28 + arch/arm/boot/dts/qcom/mido/msm8953-mido.dtsi | 19 + .../dts/qcom/mido/msm8953-pinctrl-mido.dtsi | 117 +++ .../boot/dts/qcom/msm8953-qrd-sku3-mido.dts | 69 ++ 20 files changed, 2701 insertions(+) create mode 100644 arch/arm/boot/dts/qcom/mido/batterydata-qrd-coslight-4v4-4100mah.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/batterydata-qrd-desay-4v4-4100mah.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/batterydata-qrd-desay-lisheng-4v4-4100mah.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/batterydata-qrd-sunwoda-4v4-4100mah.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/batterydata-qrd-sunwoda-ATL-4v4-4100mah.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/dsi-panel-ili9885-boe-fhd-video.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/dsi-panel-nt35532-fhd-video.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/dsi-panel-nt35596-fhd-video.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/dsi-panel-nt35596-tianma-fhd-video.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/dsi-panel-otm1911-fhd-video.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/dsi-panel-r63350-ebbg-fhd-video.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/msm-audio-mido.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/msm8953-camera-sensor-qrd-mido.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/msm8953-display-mido.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/msm8953-general-mido.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/msm8953-memory-mido.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/msm8953-mido.dtsi create mode 100644 arch/arm/boot/dts/qcom/mido/msm8953-pinctrl-mido.dtsi create mode 100644 arch/arm/boot/dts/qcom/msm8953-qrd-sku3-mido.dts diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index f1fe1b3ba7295..1604e8aea450d 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -253,6 +253,9 @@ dtb-$(CONFIG_ARCH_MSM8940) += msm8940-pmi8937-cdp.dtb \ msm8940-pmi8940-rcm.dtb \ msm8940-pmi8940-qrd-sku7.dtb +ifeq ($(CONFIG_MACH_XIAOMI_MSM8953),y) +dtb-$(CONFIG_MACH_XIAOMI_MIDO) += msm8953-qrd-sku3-mido.dtb +else dtb-$(CONFIG_ARCH_MSM8953) += msm8953-sim.dtb \ msm8953-rumi.dtb \ msm8953-cdp.dtb \ @@ -277,6 +280,7 @@ dtb-$(CONFIG_ARCH_MSM8953) += msm8953-sim.dtb \ msm8953-pmi8937-mtp.dtb \ msm8953-pmi8940-ext-codec-mtp.dtb \ msm8953-pmi8937-ext-codec-mtp.dtb +endif dtb-$(CONFIG_ARCH_SDM450) += sdm450-rcm.dtb \ sdm450-cdp.dtb \ diff --git a/arch/arm/boot/dts/qcom/mido/batterydata-qrd-coslight-4v4-4100mah.dtsi b/arch/arm/boot/dts/qcom/mido/batterydata-qrd-coslight-4v4-4100mah.dtsi new file mode 100644 index 0000000000000..0d848a01c785b --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/batterydata-qrd-coslight-4v4-4100mah.dtsi @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +qcom,2786095_mido_coslight_4100mah_averaged_masterslave_feb3rd2017 { + qcom,max-voltage-uv = <4400000>; + qcom,nom-batt-capacity-mah = <4100>; + qcom,batt-id-kohm = <50>; + qcom,battery-beta = <3435>; + qcom,battery-type = "qrd_msm8953_coslight_4100mah"; + qcom,chg-rslow-comp-c1 = <3439671>; + qcom,chg-rslow-comp-c2 = <5394943>; + qcom,chg-rs-to-rslow = <823652>; + qcom,chg-rslow-comp-thr = <0xAE>; + qcom,checksum = <0xF02E>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + DF 83 B4 7C + E0 80 A2 76 + 56 83 B7 5E + DF 82 41 8E + 40 82 BC 98 + C2 B6 78 C2 + 57 17 EA 83 + B7 7C CA 80 + 59 76 4F 83 + 37 6B 71 78 + EE 86 41 82 + FA 99 50 BD + 65 CA 55 0D + 07 10 F0 58 + 14 70 DA FC + 05 3E F6 35 + FE 12 00 00 + 3B 3D 7B 30 + 92 45 00 00 + 00 00 00 00 + 00 00 00 00 + 7B 6A 86 69 + 1C 68 1C 7B + 0C 6C 60 60 + 63 6A F6 7A + BF 64 C1 58 + C0 84 BB 7E + 1B C9 61 20 + 5F A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/mido/batterydata-qrd-desay-4v4-4100mah.dtsi b/arch/arm/boot/dts/qcom/mido/batterydata-qrd-desay-4v4-4100mah.dtsi new file mode 100644 index 0000000000000..bfcd7a82fd534 --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/batterydata-qrd-desay-4v4-4100mah.dtsi @@ -0,0 +1,62 @@ +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +qcom,2508175_bn41hdesay_4100mah_averaged_masterslave_jun27th2016 { + qcom,max-voltage-uv = <4400000>; + qcom,nom-batt-capacity-mah = <4100>; + qcom,batt-id-kohm = <82>; + qcom,battery-beta = <3435>; + qcom,battery-type = "qrd_msm8953_desay_4100mah"; + qcom,fastchg-current-ma = <2000>; + qcom,fg-cc-cv-threshold-mv = <4390>; + qcom,chg-rslow-comp-c1 = <2760396>; + qcom,chg-rslow-comp-c2 = <3348384>; + qcom,chg-rs-to-rslow = <870409>; + qcom,chg-rslow-comp-thr = <0x99>; + qcom,checksum = <0xFA46>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + DE 83 BE 7C + 15 81 58 77 + 62 83 13 74 + 3F 89 50 94 + 1D 82 DE 99 + AC BC 0C C9 + 56 10 10 88 + A4 7E 60 82 + D2 7C 48 83 + 30 72 2E 75 + 75 6D 4E 82 + 80 99 A9 BC + 5C C9 5E 0C + C9 0F 82 5A + 14 70 DA FC + 20 2F 05 46 + 07 41 00 00 + FF 4C 56 3B + AF 41 00 00 + 00 00 00 00 + 00 00 00 00 + 4D 70 1A 6A + C9 74 9E 89 + 9F 77 D2 70 + A3 58 9F 81 + 91 74 A5 68 + 7D 66 B5 9B + 2F 05 63 F3 + 64 A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/mido/batterydata-qrd-desay-lisheng-4v4-4100mah.dtsi b/arch/arm/boot/dts/qcom/mido/batterydata-qrd-desay-lisheng-4v4-4100mah.dtsi new file mode 100644 index 0000000000000..edf1c49195b5f --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/batterydata-qrd-desay-lisheng-4v4-4100mah.dtsi @@ -0,0 +1,60 @@ +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +qcom,2781148_mido_desay_4100mah_averaged_masterslave_feb3rd2017 { + qcom,max-voltage-uv = <4400000>; + qcom,nom-batt-capacity-mah = <4100>; + qcom,batt-id-kohm = <62>; + qcom,battery-beta = <3435>; + qcom,battery-type = "batterydata-qrd-desay-lisheng-4v4-4100mah"; + qcom,chg-rslow-comp-c1 = <2747468>; + qcom,chg-rslow-comp-c2 = <3764702>; + qcom,chg-rs-to-rslow = <770184>; + qcom,chg-rslow-comp-thr = <0xA2>; + qcom,checksum = <0x3826>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + F0 83 6D 7D + 90 81 15 7C + 5C 83 50 67 + 0E 83 A6 8D + 22 82 AE 9A + 28 BE B5 CB + 5A 0E FC 83 + 78 7D 8C 81 + 0B 7C 62 83 + D4 65 5D 88 + 2D 94 57 82 + BB 99 28 BD + 42 CA 52 0D + 2A 10 98 59 + 14 70 DA FC + 09 44 6E 3D + AF 39 00 00 + 23 47 66 38 + AF 31 00 00 + 00 00 00 00 + 00 00 00 00 + 28 6B 33 6A + E6 70 BF 88 + 0C 74 27 69 + 7B 5A 38 80 + 26 6E 19 68 + 25 6E 46 A1 + 1D D3 5A 1B + 5C A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/mido/batterydata-qrd-sunwoda-4v4-4100mah.dtsi b/arch/arm/boot/dts/qcom/mido/batterydata-qrd-sunwoda-4v4-4100mah.dtsi new file mode 100644 index 0000000000000..1d9d574af37d7 --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/batterydata-qrd-sunwoda-4v4-4100mah.dtsi @@ -0,0 +1,62 @@ +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +qcom,qrd_msm8953_id1_4100mah { + qcom,max-voltage-uv = <4400000>; + qcom,nom-batt-capacity-mah = <4100>; + qcom,batt-id-kohm = <33>; + qcom,battery-beta = <3435>; + qcom,battery-type = "qrd_msm8953_sunwoda_4100mah"; + qcom,fastchg-current-ma = <2000>; + qcom,fg-cc-cv-threshold-mv = <4390>; + qcom,chg-rslow-comp-c1 = <3047055>; + qcom,chg-rslow-comp-c2 = <3708812>; + qcom,chg-rs-to-rslow = <1708063>; + qcom,chg-rslow-comp-thr = <0x99>; + qcom,checksum = <0x6FF9>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + DC 83 9E 7C + CD 80 80 76 + 60 83 FD 6E + 04 89 50 94 + 38 82 24 99 + C7 B7 F4 C3 + 56 0F 06 88 + F9 7D BA 81 + 0F 7C 54 83 + B3 69 2B 7A + FE 87 4B 82 + DA 99 33 BD + 45 CA 58 0D + 13 10 39 58 + 14 70 DA FC + 3A 36 CF 46 + 1E 42 00 00 + 5D 46 C4 3B + 0A 44 00 00 + 00 00 00 00 + 00 00 00 00 + AD 72 EE 70 + 73 58 12 88 + E9 75 4D 68 + 47 61 B0 7A + 24 74 10 53 + 19 74 5B AA + 23 44 69 3E + 67 A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/mido/batterydata-qrd-sunwoda-ATL-4v4-4100mah.dtsi b/arch/arm/boot/dts/qcom/mido/batterydata-qrd-sunwoda-ATL-4v4-4100mah.dtsi new file mode 100644 index 0000000000000..61cda9f8bd5a1 --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/batterydata-qrd-sunwoda-ATL-4v4-4100mah.dtsi @@ -0,0 +1,60 @@ +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +qcom,2728170_mido_sunwoda_4100mah_averaged_masterslave_jan3rd2017 { + qcom,max-voltage-uv = <4400000>; + qcom,nom-batt-capacity-mah = <4100>; + qcom,batt-id-kohm = <40>; + qcom,battery-beta = <3435>; + qcom,battery-type = "qrd_msm8953_sunwoda_atl_4100mah"; + qcom,chg-rslow-comp-c1 = <3159320>; + qcom,chg-rslow-comp-c2 = <4074348>; + qcom,chg-rs-to-rslow = <921524>; + qcom,chg-rslow-comp-thr = <0x9C>; + qcom,checksum = <0xDC57>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + DC 83 AD 7C + 04 81 2F 77 + 5E 83 68 6E + C6 88 02 94 + 34 82 87 99 + 7C BC F0 C8 + 57 0F 11 88 + BA 7E 69 82 + D1 7C 48 83 + 1C 72 05 75 + 09 6D 53 82 + 5A 99 80 BC + 1E C9 60 0C + EC 0F E8 59 + 14 70 DA FC + 59 32 B3 45 + 5F 28 00 00 + 05 47 6C 38 + 6E 33 00 00 + 00 00 00 00 + 00 00 00 00 + 8A 70 78 6A + BA 7E 25 88 + 28 7C B2 71 + DF 6C 90 78 + 2E 74 DB 68 + FD 5B BA A1 + 32 86 68 DC + 66 A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/mido/dsi-panel-ili9885-boe-fhd-video.dtsi b/arch/arm/boot/dts/qcom/mido/dsi-panel-ili9885-boe-fhd-video.dtsi new file mode 100644 index 0000000000000..23e867f025244 --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/dsi-panel-ili9885-boe-fhd-video.dtsi @@ -0,0 +1,80 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_ili9885_boe_fhd_vid: qcom,mdss_dsi_ili9885_boe_fhd_video { + qcom,mdss-dsi-panel-name = "ili9885 boe fhd video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <1920>; + qcom,mdss-dsi-h-front-porch = <100>; + qcom,mdss-dsi-h-back-porch = <64>; + qcom,mdss-dsi-h-pulse-width = <16>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <12>; + qcom,mdss-dsi-v-front-porch = <44>; + qcom,mdss-dsi-v-pulse-width = <2>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [29 01 00 00 00 00 02 35 00 + 29 01 00 00 00 00 03 51 0F ff + 29 01 00 00 00 00 02 53 2c + 29 01 00 00 00 00 02 55 00 + 29 01 00 00 78 00 02 11 00 + 29 01 00 00 05 00 02 29 00 + ]; + qcom,mdss-dsi-off-command = [05 01 00 00 14 00 02 28 00 + 05 01 00 00 78 00 02 10 00]; + + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_hs_mode"; + + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-t-clk-post = <0x0d>; + qcom,mdss-dsi-t-clk-pre = <0x30>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>; + qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A + 06 01 00 01 05 00 01 0F + 06 01 00 01 05 00 01 E5 + 06 01 00 01 05 00 01 D5]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1 1 4 5>; + qcom,mdss-dsi-panel-status-valid-params = <1 1 4 5>; + qcom,mdss-dsi-panel-status-value = <0x9C 0xC0 0xf6 0xf6 0x6d 0x34 0x8b 0x00 0x00 0x00 0x01>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/mido/dsi-panel-nt35532-fhd-video.dtsi b/arch/arm/boot/dts/qcom/mido/dsi-panel-nt35532-fhd-video.dtsi new file mode 100644 index 0000000000000..7cc89fd66c2ae --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/dsi-panel-nt35532-fhd-video.dtsi @@ -0,0 +1,90 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_nt35532_fhd_vid: qcom,mdss_dsi_nt35532_fhd_video { + qcom,mdss-dsi-panel-name = "nt35532 fhd video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <1920>; + qcom,mdss-dsi-h-front-porch = <124>; + qcom,mdss-dsi-h-back-porch = <64>; + qcom,mdss-dsi-h-pulse-width = <16>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <12>; + qcom,mdss-dsi-v-front-porch = <7>; + qcom,mdss-dsi-v-pulse-width = <2>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [29 01 00 00 01 00 02 ff 04 + 29 01 00 00 00 00 02 fb 01 + 29 01 00 00 00 00 02 08 05 + 29 01 00 00 01 00 02 ff 05 + 29 01 00 00 00 00 02 fb 01 + 29 01 00 00 00 00 02 d6 22 + 29 01 00 00 00 00 02 ff 00 + 29 01 00 00 00 00 02 fb 01 + 29 01 00 00 00 00 02 35 00 + 29 01 00 00 00 00 02 51 ff + 29 01 00 00 00 00 02 53 2c + 29 01 00 00 00 00 02 55 00 + 29 01 00 00 00 00 02 d3 0E + 29 01 00 00 00 00 02 d4 07 + 29 01 00 00 78 00 02 11 00 + 29 01 00 00 14 00 02 29 00]; + qcom,mdss-dsi-off-command = [29 01 00 00 00 00 02 ff 00 + 05 01 00 00 14 00 02 28 00 + 05 01 00 00 3C 00 02 10 00 + 29 01 00 00 00 00 02 ff 00 + 29 01 00 00 14 00 02 4F 01]; + + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_hs_mode"; + + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33 + 22 27 1e 03 04 00]; + qcom,mdss-dsi-t-clk-post = <0x0d>; + qcom,mdss-dsi-t-clk-pre = <0x30>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>; + qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-value = <0x9C>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/mido/dsi-panel-nt35596-fhd-video.dtsi b/arch/arm/boot/dts/qcom/mido/dsi-panel-nt35596-fhd-video.dtsi new file mode 100644 index 0000000000000..56f74322340bf --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/dsi-panel-nt35596-fhd-video.dtsi @@ -0,0 +1,87 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_nt35596_fhd_vid: qcom,mdss_dsi_nt35596_fhd_video { + qcom,mdss-dsi-panel-name = "nt35596 fhd video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <1920>; + qcom,mdss-dsi-h-front-porch = <128>; + qcom,mdss-dsi-h-back-porch = <64>; + qcom,mdss-dsi-h-pulse-width = <16>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <10>; + qcom,mdss-dsi-v-front-porch = <9>; + qcom,mdss-dsi-v-pulse-width = <2>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [29 01 00 00 01 00 02 ff 00 + 29 01 00 00 00 00 02 fb 01 + 29 01 00 00 00 00 02 35 00 + 29 01 00 00 00 00 02 36 00 + 29 01 00 00 00 00 02 51 ff + 29 01 00 00 00 00 02 53 2c + 29 01 00 00 00 00 02 55 00 + 29 01 00 00 00 00 02 d3 0C + 29 01 00 00 00 00 02 d4 09 + 29 01 00 00 00 00 02 ff 01 + 29 01 00 00 00 00 02 fb 01 + 29 01 00 00 00 00 02 72 21 + 29 01 00 00 00 00 02 FF 05 + 29 01 00 00 00 00 02 Fb 01 + 29 01 00 00 00 00 02 e7 80 + 29 01 00 00 00 00 02 FF 00 + 29 01 00 00 78 00 02 11 00 + 29 01 00 00 14 00 02 29 00]; + qcom,mdss-dsi-off-command = [05 01 00 00 14 00 02 28 00 + 05 01 00 00 78 00 02 10 00]; + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; //burst_mode non_burst_sync_event + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-t-clk-post = <0x0d>; + qcom,mdss-dsi-t-clk-pre = <0x30>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 5>, <0 5>, <1 5>, <0 5>, <1 20>; + qcom,mdss-dsi-tx-eot-append; + qcom,esd-check-enabled; + qcom,mdss-dsi-lp11-init; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-valid-params = <1>; + qcom,mdss-dsi-panel-status-value = <0x9c>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/mido/dsi-panel-nt35596-tianma-fhd-video.dtsi b/arch/arm/boot/dts/qcom/mido/dsi-panel-nt35596-tianma-fhd-video.dtsi new file mode 100644 index 0000000000000..f3e3cb020ee14 --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/dsi-panel-nt35596-tianma-fhd-video.dtsi @@ -0,0 +1,93 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_nt35596_tianma_fhd_vid: qcom,mdss_dsi_nt35596_tianma_fhd_video { + qcom,mdss-dsi-panel-name = "nt35596 tianma fhd video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <1920>; + qcom,mdss-dsi-h-front-porch = <96>; + qcom,mdss-dsi-h-back-porch = <64>; + qcom,mdss-dsi-h-pulse-width = <16>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <4>; + qcom,mdss-dsi-v-front-porch = <14>; + qcom,mdss-dsi-v-pulse-width = <2>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [29 01 00 00 01 00 02 ff 04 + 29 01 00 00 00 00 02 fb 01 + 29 01 00 00 00 00 02 08 05 + 29 01 00 00 01 00 02 ff 00 + 29 01 00 00 00 00 02 fb 01 + 29 01 00 00 00 00 02 35 00 + 29 01 00 00 00 00 02 36 00 + 29 01 00 00 00 00 02 51 ff + 29 01 00 00 00 00 02 53 2c + 29 01 00 00 00 00 02 55 00 + 29 01 00 00 00 00 02 d3 06 + 29 01 00 00 00 00 02 d4 0e + 29 01 00 00 00 00 02 ff 01 + 29 01 00 00 00 00 02 fb 01 + 29 01 00 00 00 00 02 72 21 + 29 01 00 00 00 00 02 6D 33 + 29 01 00 00 00 00 02 FF 05 + 29 01 00 00 00 00 02 Fb 01 + 29 01 00 00 00 00 02 E7 80 + 29 01 00 00 00 00 02 FF 00 + 29 01 00 00 78 00 02 11 00 + 29 01 00 00 14 00 02 29 00]; + qcom,mdss-dsi-off-command = [29 01 00 00 00 00 02 FF 00 + 05 01 00 00 14 00 02 28 00 + 05 01 00 00 3C 00 02 10 00]; + + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_hs_mode"; + + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-t-clk-post = <0x0d>; + qcom,mdss-dsi-t-clk-pre = <0x2f>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 5>, <0 5>, <1 5>, <0 5>, <1 20>; + qcom,mdss-dsi-tx-eot-append; + qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-value = <0x9C>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/mido/dsi-panel-otm1911-fhd-video.dtsi b/arch/arm/boot/dts/qcom/mido/dsi-panel-otm1911-fhd-video.dtsi new file mode 100644 index 0000000000000..3ea3836a68e96 --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/dsi-panel-otm1911-fhd-video.dtsi @@ -0,0 +1,136 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_otm1911_fhd_vid: qcom,mdss_dsi_otm1911_fhd_video { + qcom,mdss-dsi-panel-name = "otm1911 fhd video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <1920>; + qcom,mdss-dsi-h-front-porch = <24>; + qcom,mdss-dsi-h-back-porch = <24>; + qcom,mdss-dsi-h-pulse-width = <20>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <6>; + qcom,mdss-dsi-v-front-porch = <14>; + qcom,mdss-dsi-v-pulse-width = <2>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [ + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 04 FF 19 11 01 + 39 01 00 00 00 00 02 00 80 + 39 01 00 00 00 00 03 FF 19 11 + 39 01 00 00 00 00 02 00 C0 + 39 01 00 00 00 00 0D CB FE F4 F4 F4 00 00 00 00 F4 07 00 00 + + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 E0 00 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 26 E1 d6 de fa 1e 40 37 55 87 b1 55 95 c7 f0 15 95 41 68 dd 06 + 9a 2b 52 72 99 aa ca d3 07 42 fa 66 8a c5 ef ff ff 03 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 26 E2 d6 de fc 1e 40 34 4d 7d a9 55 8c b4 e1 05 95 31 59 cc f4 + 5a 17 40 5f 80 aa ad b8 e7 27 ea 4b 6d aa e5 ff ff 03 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 26 E3 00 26 72 b3 00 da 02 46 7e 54 6f a2 d4 fe 55 2f 5a d0 fb + 5a 21 4a 69 8f aa c0 c8 f8 36 ea 5d 80 c0 ee ff ff 03 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 26 E4 a5 b2 d4 f6 00 0e 2f 68 91 55 78 aa d4 fb 55 2a 52 c7 f0 + 5a 14 3b 5a 7e aa a9 af db 1a ea 3f 64 a3 e3 ff ff 03 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 26 E5 ba c4 e3 02 40 1b 3d 73 9b 55 83 b6 e2 08 95 38 60 d7 00 + 9a 26 4d 6d 91 aa c9 d7 10 4a fa 6c 8f c7 f0 ff ff 03 + + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 26 E6 52 43 57 72 55 81 8f ae d0 55 b0 d3 f8 1a 95 40 66 d8 ff + 5a 21 4b 69 90 aa b7 c3 fa 39 ea 58 7a b2 e7 ff ff 03 + + 39 01 00 00 00 00 02 00 80 + 39 01 00 00 00 00 07 D8 03 fc 04 00 03 ff + 39 01 00 00 00 00 02 00 90 + 39 01 00 00 00 00 07 D8 03 c6 03 e3 04 00 + 39 01 00 00 00 00 02 00 A0 + 39 01 00 00 00 00 07 D8 04 00 03 e4 03 bf + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 00 A0 + 39 01 00 00 00 00 0d D6 0f 10 0f 14 18 12 10 0d 0e 12 12 11 + 39 01 00 00 00 00 02 00 B0 + 39 01 00 00 00 00 0d D6 97 8d ce 91 df e5 b3 99 8f 8a 92 9a + 39 01 00 00 00 00 02 00 C0 + 39 01 00 00 00 00 0d D6 90 89 9a 8d 80 85 a3 91 8a 87 8c 91 + 39 01 00 00 00 00 02 00 D0 + 39 01 00 00 00 00 0d D6 89 98 9a 85 85 8e 91 88 85 83 86 89 + + 39 01 00 00 00 00 02 00 80 + 39 01 00 00 00 00 0d ca ab a5 a1 9c 98 94 90 8d 8a 87 84 82 + 39 01 00 00 00 00 02 00 90 + 39 01 00 00 00 00 0a ca f8 ff 00 fc ff cc fa ff 66 + + 39 01 00 00 00 00 02 00 b0 + 39 01 00 00 00 00 02 ca 03 + + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 2c + 39 01 00 00 00 00 02 55 00 + + 39 01 00 00 78 00 02 11 00 + 39 01 00 00 14 00 02 29 00]; + qcom,mdss-dsi-off-command = [ + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 04 FF 19 11 01 + 39 01 00 00 00 00 02 00 80 + 39 01 00 00 00 00 03 FF 19 11 + 39 01 00 00 00 00 02 00 90 + 39 01 00 00 00 00 02 b3 34 + 39 01 00 00 32 00 02 28 00 + 39 01 00 00 78 00 02 10 00 + ]; + + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-t-clk-post = <0x0d>; + qcom,mdss-dsi-t-clk-pre = <0x2d>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-value = <0x9C>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/mido/dsi-panel-r63350-ebbg-fhd-video.dtsi b/arch/arm/boot/dts/qcom/mido/dsi-panel-r63350-ebbg-fhd-video.dtsi new file mode 100644 index 0000000000000..f2ac8177424be --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/dsi-panel-r63350-ebbg-fhd-video.dtsi @@ -0,0 +1,77 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_r63350_ebbg_fhd_vid: qcom,mdss_dsi_r63350_ebbg_fhd_video { + qcom,mdss-dsi-panel-name = "r63350_ebbg fhd video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <1920>; + qcom,mdss-dsi-h-front-porch = <100>; + qcom,mdss-dsi-h-back-porch = <84>; + qcom,mdss-dsi-h-pulse-width = <24>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <3>; + qcom,mdss-dsi-v-front-porch = <16>; + qcom,mdss-dsi-v-pulse-width = <5>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [ + 29 01 00 00 00 00 02 B0 04 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 2c + 39 01 00 00 00 00 02 55 00 + ]; + qcom,mdss-dsi-off-command = [05 01 00 00 14 00 02 28 00 + 05 01 00 00 78 00 02 10 00]; + + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_hs_mode"; + + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + + qcom,mdss-dsi-t-clk-post = <0x0d>; + qcom,mdss-dsi-t-clk-pre = <0x30>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>; + qcom,mdss-dsi-tx-eot-append; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-valid-params = <1>; + qcom,mdss-dsi-panel-status-value = <0x9c>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/mido/msm-audio-mido.dtsi b/arch/arm/boot/dts/qcom/mido/msm-audio-mido.dtsi new file mode 100644 index 0000000000000..7a7af1c830065 --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/msm-audio-mido.dtsi @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&int_codec { + status = "ok"; + /* already defined in msm8953-audio.dtsi */ + qcom,msm-hs-micbias-type = "internal"; + qcom,msm-spk-ext-pa = <&tlmm 96 0>; + qcom,audio-routing = + "RX_BIAS", "MCLK", + "SPK_RX_BIAS", "MCLK", + "INT_LDO_H", "MCLK", + "MIC BIAS External", "Handset Mic", + "MIC BIAS Internal2", "Headset Mic", + "MIC BIAS External", "Secondary Mic", + "AMIC1", "MIC BIAS External", + "AMIC2", "MIC BIAS Internal2", + "AMIC3", "MIC BIAS External"; + /delete-property/asoc-wsa-codec-names; + /delete-property/asoc-wsa-codec-prefixes; + /delete-property/msm-vdd-wsa-switch-supply; + /delete-property/qcom,msm-vdd-wsa-switch-voltage; + /delete-property/qcom,msm-vdd-wsa-switch-current; +}; diff --git a/arch/arm/boot/dts/qcom/mido/msm8953-camera-sensor-qrd-mido.dtsi b/arch/arm/boot/dts/qcom/mido/msm8953-camera-sensor-qrd-mido.dtsi new file mode 100644 index 0000000000000..8f3c8635f05f6 --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/msm8953-camera-sensor-qrd-mido.dtsi @@ -0,0 +1,931 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + led_flash0: qcom,camera-flash { + cell-index = <0>; + compatible = "qcom,camera-flash"; + qcom,flash-type = <1>; + qcom,flash-source = <&pmi8950_flash0 &pmi8950_flash1>; + qcom,torch-source = <&pmi8950_torch0 &pmi8950_torch1>; + qcom,switch-source = <&pmi8950_switch>; + }; +}; + +&cci { + eeprom0: qcom,eeprom@0 { + cell-index = <0>; + reg = <0x0>; + qcom,eeprom-name = "qtech_s5k3l8"; + compatible = "qcom,eeprom"; + + qcom,slave-addr = <0xA0>; + qcom,cci-master = <0>; + qcom,num-blocks = <6>; + + qcom,page0 = <0 0 0 0 0 0>; + qcom,poll0 = <0 0 0 0 0 0>; + qcom,saddr0 = <0xA0>; + qcom,mem0 = <5 0x0000 2 0 1 0>; + + qcom,page1 = <0 0 0 0 0 0>; + qcom,poll1 = <0 0 0 0 0 0>; + qcom,saddr1 = <0xA0>; + qcom,mem1 = <6 0x000C 2 0 1 0>; + + qcom,page2 = <0 0 0 0 0 0>; + qcom,poll2 = <0 0 0 0 0 0>; + qcom,saddr2 = <0xA0>; + qcom,mem2 = <13 0x0019 2 0 1 0>; + + qcom,page3 = <0 0 0 0 0 0>; + qcom,poll3 = <0 0 0 0 0 0>; + qcom,saddr3 = <0xA0>; + qcom,mem3 = <1769 0x0027 2 0 1 0>; + + qcom,page4 = <0 0 0 0 0 0>; + qcom,poll4 = <0 0 0 0 0 0>; + qcom,saddr4 = <0xA0>; + qcom,mem4 = <899 0x0711 2 0 1 0>; + + qcom,page5 = <0 0 0 0 0 0>; + qcom,poll5 = <0 0 0 0 0 0>; + qcom,saddr5 = <0xA0>; + qcom,mem5 = <3 0x0D99 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l2>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", "cam_vaf"; + qcom,cam-vreg-type = <0 1 0 0>; + qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 80000 100000>; + qcom,gpio-no-mux = <0>; + gpios = <&tlmm 26 0>, + <&tlmm 40 0>, + <&tlmm 39 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_STANDBY0"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio","cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 1 1 1 1>; + + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <19200000 0>; + }; + + eeprom1: qcom,eeprom@1 { + cell-index = <1>; + reg = <0x1>; + qcom,eeprom-name = "ofilm_s5k3l8"; + compatible = "qcom,eeprom"; + + qcom,slave-addr = <0xB0>; + qcom,cci-master = <0>; + qcom,num-blocks = <9>; + + qcom,page0 = <0 0 0 0 0 0>; + qcom,poll0 = <0 0 0 0 0 0>; + qcom,saddr0 = <0xB0>; + qcom,mem0 = <1 0x0000 2 0 1 0>; + + qcom,page1 = <0 0 0 0 0 0>; + qcom,poll1 = <0 0 0 0 0 0>; + qcom,saddr1 = <0xB0>; + qcom,mem1 = <1 0x000B 2 0 1 0>; + + qcom,page2 = <0 0 0 0 0 0>; + qcom,poll2 = <0 0 0 0 0 0>; + qcom,saddr2 = <0xB0>; + qcom,mem2 = <3 0x0015 2 0 1 0>; + + qcom,page3 = <0 0 0 0 0 0>; + qcom,poll3 = <0 0 0 0 0 0>; + qcom,saddr3 = <0xB0>; + qcom,mem3 = <5 0x0019 2 0 1 0>; + + qcom,page4 = <0 0 0 0 0 0>; + qcom,poll4 = <0 0 0 0 0 0>; + qcom,saddr4 = <0xB0>; + qcom,mem4 = <1 0x0021 2 0 1 0>; + + qcom,page5 = <0 0 0 0 0 0>; + qcom,poll5 = <0 0 0 0 0 0>; + qcom,saddr5 = <0xB0>; + qcom,mem5 = <6 0x002A 2 0 1 0>; + + qcom,page6 = <0 0 0 0 0 0>; + qcom,poll6 = <0 0 0 0 0 0>; + qcom,saddr6 = <0xB0>; + qcom,mem6 = <6 0x0038 2 0 1 0>; + + qcom,page7 = <0 0 0 0 0 0>; + qcom,poll7 = <0 0 0 0 0 0>; + qcom,saddr7 = <0xB0>; + qcom,mem7 = <1769 0x003F 2 0 1 0>; + + qcom,page8 = <0 0 0 0 0 0>; + qcom,poll8 = <0 0 0 0 0 0>; + qcom,saddr8 = <0xB0>; + qcom,mem8 = <901 0x0729 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l2>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", "cam_vaf"; + qcom,cam-vreg-type = <0 1 0 0>; + qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 80000 100000>; + qcom,gpio-no-mux = <0>; + gpios = <&tlmm 26 0>, + <&tlmm 40 0>, + <&tlmm 39 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_STANDBY0"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio","cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 1 1 1 1>; + + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <19200000 0>; + }; + + eeprom2: qcom,eeprom@2 { + cell-index = <2>; + reg = <0x2>; + qcom,eeprom-name = "sunny_s5k3l8"; + compatible = "qcom,eeprom"; + + qcom,slave-addr = <0xB0>; + qcom,cci-master = <0>; + qcom,num-blocks = <7>; + + qcom,page0 = <0 0 0 0 0 0>; + qcom,poll0 = <0 0 0 0 0 0>; + qcom,saddr0 = <0xB0>; + qcom,mem0 = <2 0x0000 2 0 1 0>; + + qcom,page1 = <0 0 0 0 0 0>; + qcom,poll1 = <0 0 0 0 0 0>; + qcom,saddr1 = <0xB0>; + qcom,mem1 = <3 0x0005 2 0 1 0>; + + qcom,page2 = <0 0 0 0 0 0>; + qcom,poll2 = <0 0 0 0 0 0>; + qcom,saddr2 = <0xB0>; + qcom,mem2 = <5 0x000C 2 0 1 0>; + + qcom,page3 = <0 0 0 0 0 0>; + qcom,poll3 = <0 0 0 0 0 0>; + qcom,saddr3 = <0xB0>; + qcom,mem3 = <7 0x0019 2 0 1 0>; + + qcom,page4 = <0 0 0 0 0 0>; + qcom,poll4 = <0 0 0 0 0 0>; + qcom,saddr4 = <0xB0>; + qcom,mem4 = <1769 0x0027 2 0 1 0>; + + qcom,page5 = <0 0 0 0 0 0>; + qcom,poll5 = <0 0 0 0 0 0>; + qcom,saddr5 = <0xB0>; + qcom,mem5 = <899 0x0711 2 0 1 0>; + + qcom,page6 = <0 0 0 0 0 0>; + qcom,poll6 = <0 0 0 0 0 0>; + qcom,saddr6 = <0xB0>; + qcom,mem6 = <3 0x0D99 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l2>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", "cam_vaf"; + qcom,cam-vreg-type = <0 1 0 0>; + qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 80000 100000>; + qcom,gpio-no-mux = <0>; + gpios = <&tlmm 26 0>, + <&tlmm 40 0>, + <&tlmm 39 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_STANDBY0"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio","cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 1 1 1 1>; + + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <19200000 0>; + /delete-property/ qcom,sensor-mode; /* xiaomi deleted */ + }; + + eeprom3: qcom,eeprom@3 { + cell-index = <3>; + reg = <0x3>; + compatible = "qcom,eeprom"; + qcom,cci-master = <1>; + + qcom,eeprom-name = "qtech_s5k5e8"; + qcom,slave-addr = <0x20>; + qcom,num-blocks = <8>; + + qcom,page0 = <1 0x0A02 2 0x4 1 0>; + qcom,pageen0 = <1 0x0A00 2 0x1 1 0>; + qcom,poll0 = <0 0x0 2 0 1 0>; + qcom,mem0 = <64 0x0A04 2 0 1 0>; + + qcom,page1 = <1 0x0A02 2 0x5 1 0>; + qcom,pageen1 = <1 0x0A00 2 0x1 1 0>; + qcom,poll1 = <0 0x0 2 0 1 0>; + qcom,mem1 = <64 0x0A04 2 0 1 0>; + + qcom,page2 = <1 0x0A02 2 0x6 1 0>; + qcom,pageen2 = <1 0x0A00 2 0x1 1 0>; + qcom,poll2 = <0 0x0 2 0 1 0>; + qcom,mem2 = <64 0x0A04 2 0 1 0>; + + qcom,page3 = <1 0x0A02 2 0x7 1 0>; + qcom,pageen3 = <1 0x0A00 2 0x1 1 0>; + qcom,poll3 = <0 0x0 2 0 1 0>; + qcom,mem3 = <64 0x0A04 2 0 1 0>; + + qcom,page4 = <1 0x0A02 2 0x8 1 0>; + qcom,pageen4 = <1 0x0A00 2 0x1 1 0>; + qcom,poll4 = <0 0x0 2 0 1 0>; + qcom,mem4 = <64 0x0A04 2 0 1 0>; + + qcom,page5 = <1 0x0A02 2 0x9 1 0>; + qcom,pageen5 = <1 0x0A00 2 0x1 1 0>; + qcom,poll5 = <0 0x0 2 0 1 0>; + qcom,mem5 = <64 0x0A04 2 0 1 0>; + + qcom,page6 = <1 0x0A02 2 0xA 1 0>; + qcom,pageen6 = <1 0x0A00 2 0x1 1 0>; + qcom,poll6 = <0 0x0 2 0 1 0>; + qcom,mem6 = <64 0x0A04 2 0 1 0>; + + qcom,page7 = <1 0x0A02 2 0xE 1 0>; + qcom,pageen7 = <1 0x0A00 2 0x1 1 0>; + qcom,poll7 = <0 0x0 2 0 1 0>; + qcom,mem7 = <2 0x0A04 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l23>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", "cam_vaf"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 80000 100000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front1_default>; + pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front1_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 129 0>, + <&tlmm 130 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_STANDBY2"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 10 1 1>; + + status = "ok"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <19200000 0>; + }; + + eeprom4: qcom,eeprom@4 { + cell-index = <4>; + reg = <0x4>; + compatible = "qcom,eeprom"; + qcom,cci-master = <1>; + + qcom,eeprom-name = "sunny_s5k5e8"; + qcom,slave-addr = <0x20>; + qcom,num-blocks = <8>; + + qcom,page0 = <1 0x0A02 2 0x4 1 0>; + qcom,pageen0 = <1 0x0A00 2 0x1 1 0>; + qcom,poll0 = <0 0x0 2 0 1 0>; + qcom,mem0 = <64 0x0A04 2 0 1 0>; + + qcom,page1 = <1 0x0A02 2 0x5 1 0>; + qcom,pageen1 = <1 0x0A00 2 0x1 1 0>; + qcom,poll1 = <0 0x0 2 0 1 0>; + qcom,mem1 = <64 0x0A04 2 0 1 0>; + + qcom,page2 = <1 0x0A02 2 0x6 1 0>; + qcom,pageen2 = <1 0x0A00 2 0x1 1 0>; + qcom,poll2 = <0 0x0 2 0 1 0>; + qcom,mem2 = <64 0x0A04 2 0 1 0>; + + qcom,page3 = <1 0x0A02 2 0x7 1 0>; + qcom,pageen3 = <1 0x0A00 2 0x1 1 0>; + qcom,poll3 = <0 0x0 2 0 1 0>; + qcom,mem3 = <64 0x0A04 2 0 1 0>; + + qcom,page4 = <1 0x0A02 2 0x8 1 0>; + qcom,pageen4 = <1 0x0A00 2 0x1 1 0>; + qcom,poll4 = <0 0x0 2 0 1 0>; + qcom,mem4 = <64 0x0A04 2 0 1 0>; + + qcom,page5 = <1 0x0A02 2 0x9 1 0>; + qcom,pageen5 = <1 0x0A00 2 0x1 1 0>; + qcom,poll5 = <0 0x0 2 0 1 0>; + qcom,mem5 = <64 0x0A04 2 0 1 0>; + + qcom,page6 = <1 0x0A02 2 0xA 1 0>; + qcom,pageen6 = <1 0x0A00 2 0x1 1 0>; + qcom,poll6 = <0 0x0 2 0 1 0>; + qcom,mem6 = <64 0x0A04 2 0 1 0>; + + qcom,page7 = <1 0x0A02 2 0xE 1 0>; + qcom,pageen7 = <1 0x0A00 2 0x1 1 0>; + qcom,poll7 = <0 0x0 2 0 1 0>; + qcom,mem7 = <2 0x0A04 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l23>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", "cam_vaf"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 80000 100000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front1_default>; + pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front1_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 129 0>, + <&tlmm 130 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_STANDBY2"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 10 1 1>; + + status = "ok"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <19200000 0>; + }; + + eeprom5: qcom,eeprom@5 { + cell-index = <5>; + reg = <0x5>; + compatible = "qcom,eeprom"; + qcom,cci-master = <1>; + + qcom,eeprom-name = "ofilm_s5k5e8"; + qcom,slave-addr = <0x5A>; + qcom,num-blocks = <8>; + + qcom,page0 = <1 0x0A02 2 0x4 1 0>; + qcom,pageen0 = <1 0x0A00 2 0x1 1 0>; + qcom,poll0 = <0 0x0 2 0 1 0>; + qcom,mem0 = <64 0x0A04 2 0 1 0>; + + qcom,page1 = <1 0x0A02 2 0x5 1 0>; + qcom,pageen1 = <1 0x0A00 2 0x1 1 0>; + qcom,poll1 = <0 0x0 2 0 1 0>; + qcom,mem1 = <64 0x0A04 2 0 1 0>; + + qcom,page2 = <1 0x0A02 2 0x6 1 0>; + qcom,pageen2 = <1 0x0A00 2 0x1 1 0>; + qcom,poll2 = <0 0x0 2 0 1 0>; + qcom,mem2 = <64 0x0A04 2 0 1 0>; + + qcom,page3 = <1 0x0A02 2 0x7 1 0>; + qcom,pageen3 = <1 0x0A00 2 0x1 1 0>; + qcom,poll3 = <0 0x0 2 0 1 0>; + qcom,mem3 = <64 0x0A04 2 0 1 0>; + + qcom,page4 = <1 0x0A02 2 0x8 1 0>; + qcom,pageen4 = <1 0x0A00 2 0x1 1 0>; + qcom,poll4 = <0 0x0 2 0 1 0>; + qcom,mem4 = <64 0x0A04 2 0 1 0>; + + qcom,page5 = <1 0x0A02 2 0x9 1 0>; + qcom,pageen5 = <1 0x0A00 2 0x1 1 0>; + qcom,poll5 = <0 0x0 2 0 1 0>; + qcom,mem5 = <64 0x0A04 2 0 1 0>; + + qcom,page6 = <1 0x0A02 2 0xA 1 0>; + qcom,pageen6 = <1 0x0A00 2 0x1 1 0>; + qcom,poll6 = <0 0x0 2 0 1 0>; + qcom,mem6 = <64 0x0A04 2 0 1 0>; + + qcom,page7 = <1 0x0A02 2 0xE 1 0>; + qcom,pageen7 = <1 0x0A00 2 0x1 1 0>; + qcom,poll7 = <0 0x0 2 0 1 0>; + qcom,mem7 = <2 0x0A04 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l23>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", "cam_vaf"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 80000 100000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front1_default>; + pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front1_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 129 0>, + <&tlmm 130 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_STANDBY2"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 10 1 1>; + + status = "ok"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <19200000 0>; + }; + + eeprom6: qcom,eeprom@6 { + cell-index = <6>; + reg = <0x6>; + qcom,eeprom-name = "ofilm_imx258"; + compatible = "qcom,eeprom"; + + qcom,slave-addr = <0xB0>; + qcom,cci-master = <0>; + qcom,num-blocks = <8>; + + qcom,page0 = <0 0 0 0 0 0>; + qcom,poll0 = <0 0 0 0 0 0>; + qcom,saddr0 = <0xB0>; + qcom,mem0 = <1024 0x0000 2 0 1 0>; + + qcom,page1 = <0 0 0 0 0 0>; + qcom,poll1 = <0 0 0 0 0 0>; + qcom,saddr1 = <0xB0>; + qcom,mem1 = <1024 0x0400 2 0 1 0>; + + qcom,page2 = <0 0 0 0 0 0>; + qcom,poll2 = <0 0 0 0 0 0>; + qcom,saddr2 = <0xB0>; + qcom,mem2 = <1024 0x0800 2 0 1 0>; + + qcom,page3 = <0 0 0 0 0 0>; + qcom,poll3 = <0 0 0 0 0 0>; + qcom,saddr3 = <0xB0>; + qcom,mem3 = <1024 0x0C00 2 0 1 0>; + + qcom,page4 = <0 0 0 0 0 0>; + qcom,poll4 = <0 0 0 0 0 0>; + qcom,saddr4 = <0xB0>; + qcom,mem4 = <1024 0x1000 2 0 1 0>; + + qcom,page5 = <0 0 0 0 0 0>; + qcom,poll5 = <0 0 0 0 0 0>; + qcom,saddr5 = <0xB0>; + qcom,mem5 = <1024 0x1400 2 0 1 0>; + + qcom,page6 = <0 0 0 0 0 0>; + qcom,poll6 = <0 0 0 0 0 0>; + qcom,saddr6 = <0xB0>; + qcom,mem6 = <1024 0x1800 2 0 1 0>; + + qcom,page7 = <0 0 0 0 0 0>; + qcom,poll7 = <0 0 0 0 0 0>; + qcom,saddr7 = <0xB0>; + qcom,mem7 = <1024 0x1C00 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l2>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", "cam_vaf"; + qcom,cam-vreg-type = <0 1 0 0>; + qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 80000 100000>; + qcom,gpio-no-mux = <0>; + gpios = <&tlmm 26 0>, + <&tlmm 40 0>, + <&tlmm 39 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_STANDBY0"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio","cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 1 1 1 1>; + + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <19200000 0>; + }; + + eeprom7: qcom,eeprom@7 { + cell-index = <7>; + reg = <0x7>; + qcom,eeprom-name = "qtech_imx258"; + compatible = "qcom,eeprom"; + + qcom,slave-addr = <0xA0>; + qcom,cci-master = <0>; + qcom,num-blocks = <8>; + + qcom,page0 = <0 0 0 0 0 0>; + qcom,poll0 = <0 0 0 0 0 0>; + qcom,saddr0 = <0xA0>; + qcom,mem0 = <1024 0x0000 2 0 1 0>; + + qcom,page1 = <0 0 0 0 0 0>; + qcom,poll1 = <0 0 0 0 0 0>; + qcom,saddr1 = <0xA0>; + qcom,mem1 = <1024 0x0400 2 0 1 0>; + + qcom,page2 = <0 0 0 0 0 0>; + qcom,poll2 = <0 0 0 0 0 0>; + qcom,saddr2 = <0xA0>; + qcom,mem2 = <1024 0x0800 2 0 1 0>; + + qcom,page3 = <0 0 0 0 0 0>; + qcom,poll3 = <0 0 0 0 0 0>; + qcom,saddr3 = <0xA0>; + qcom,mem3 = <1024 0x0C00 2 0 1 0>; + + qcom,page4 = <0 0 0 0 0 0>; + qcom,poll4 = <0 0 0 0 0 0>; + qcom,saddr4 = <0xA0>; + qcom,mem4 = <1024 0x1000 2 0 1 0>; + + qcom,page5 = <0 0 0 0 0 0>; + qcom,poll5 = <0 0 0 0 0 0>; + qcom,saddr5 = <0xA0>; + qcom,mem5 = <1024 0x1400 2 0 1 0>; + + qcom,page6 = <0 0 0 0 0 0>; + qcom,poll6 = <0 0 0 0 0 0>; + qcom,saddr6 = <0xA0>; + qcom,mem6 = <1024 0x1800 2 0 1 0>; + + qcom,page7 = <0 0 0 0 0 0>; + qcom,poll7 = <0 0 0 0 0 0>; + qcom,saddr7 = <0xA0>; + qcom,mem7 = <1024 0x1C00 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l2>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", "cam_vaf"; + qcom,cam-vreg-type = <0 1 0 0>; + qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 80000 100000>; + qcom,gpio-no-mux = <0>; + gpios = <&tlmm 26 0>, + <&tlmm 40 0>, + <&tlmm 39 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_STANDBY0"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio","cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 1 1 1 1>; + + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <19200000 0>; + }; + + eeprom8: qcom,eeprom@8 { + cell-index = <8>; + reg = <0x8>; + qcom,eeprom-name = "sunny_imx258"; + compatible = "qcom,eeprom"; + + qcom,slave-addr = <0xB0>; + qcom,cci-master = <0>; + qcom,num-blocks = <8>; + + qcom,page0 = <0 0 0 0 0 0>; + qcom,poll0 = <0 0 0 0 0 0>; + qcom,saddr0 = <0xB0>; + qcom,mem0 = <1024 0x0000 2 0 1 0>; + + qcom,page1 = <0 0 0 0 0 0>; + qcom,poll1 = <0 0 0 0 0 0>; + qcom,saddr1 = <0xB0>; + qcom,mem1 = <1024 0x0400 2 0 1 0>; + + qcom,page2 = <0 0 0 0 0 0>; + qcom,poll2 = <0 0 0 0 0 0>; + qcom,saddr2 = <0xB0>; + qcom,mem2 = <1024 0x0800 2 0 1 0>; + + qcom,page3 = <0 0 0 0 0 0>; + qcom,poll3 = <0 0 0 0 0 0>; + qcom,saddr3 = <0xB0>; + qcom,mem3 = <1024 0x0C00 2 0 1 0>; + + qcom,page4 = <0 0 0 0 0 0>; + qcom,poll4 = <0 0 0 0 0 0>; + qcom,saddr4 = <0xB0>; + qcom,mem4 = <1024 0x1000 2 0 1 0>; + + qcom,page5 = <0 0 0 0 0 0>; + qcom,poll5 = <0 0 0 0 0 0>; + qcom,saddr5 = <0xB0>; + qcom,mem5 = <1024 0x1400 2 0 1 0>; + + qcom,page6 = <0 0 0 0 0 0>; + qcom,poll6 = <0 0 0 0 0 0>; + qcom,saddr6 = <0xB0>; + qcom,mem6 = <1024 0x1800 2 0 1 0>; + + qcom,page7 = <0 0 0 0 0 0>; + qcom,poll7 = <0 0 0 0 0 0>; + qcom,saddr7 = <0xB0>; + qcom,mem7 = <1024 0x1C00 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l2>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", "cam_vaf"; + qcom,cam-vreg-type = <0 1 0 0>; + qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 80000 100000>; + qcom,gpio-no-mux = <0>; + gpios = <&tlmm 26 0>, + <&tlmm 40 0>, + <&tlmm 39 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_STANDBY0"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio","cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 1 1 1 1>; + + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <19200000 0>; + }; + + eeprom9: qcom,eeprom@9 { + cell-index = <9>; + reg = <0x9>; + qcom,eeprom-name = "qtech_ov13855"; + compatible = "qcom,eeprom"; + + qcom,slave-addr = <0xA0>; + qcom,cci-master = <0>; + qcom,num-blocks = <8>; + + qcom,page0 = <0 0 0 0 0 0>; + qcom,poll0 = <0 0 0 0 0 0>; + qcom,saddr0 = <0xA0>; + qcom,mem0 = <1024 0x0000 2 0 1 0>; + + qcom,page1 = <0 0 0 0 0 0>; + qcom,poll1 = <0 0 0 0 0 0>; + qcom,saddr1 = <0xA0>; + qcom,mem1 = <1024 0x0400 2 0 1 0>; + + qcom,page2 = <0 0 0 0 0 0>; + qcom,poll2 = <0 0 0 0 0 0>; + qcom,saddr2 = <0xA0>; + qcom,mem2 = <1024 0x0800 2 0 1 0>; + + qcom,page3 = <0 0 0 0 0 0>; + qcom,poll3 = <0 0 0 0 0 0>; + qcom,saddr3 = <0xA0>; + qcom,mem3 = <1024 0x0C00 2 0 1 0>; + + qcom,page4 = <0 0 0 0 0 0>; + qcom,poll4 = <0 0 0 0 0 0>; + qcom,saddr4 = <0xA0>; + qcom,mem4 = <1024 0x1000 2 0 1 0>; + + qcom,page5 = <0 0 0 0 0 0>; + qcom,poll5 = <0 0 0 0 0 0>; + qcom,saddr5 = <0xA0>; + qcom,mem5 = <1024 0x1400 2 0 1 0>; + + qcom,page6 = <0 0 0 0 0 0>; + qcom,poll6 = <0 0 0 0 0 0>; + qcom,saddr6 = <0xA0>; + qcom,mem6 = <1024 0x1800 2 0 1 0>; + + qcom,page7 = <0 0 0 0 0 0>; + qcom,poll7 = <0 0 0 0 0 0>; + qcom,saddr7 = <0xA0>; + qcom,mem7 = <1024 0x1C00 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l2>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", "cam_vaf"; + qcom,cam-vreg-type = <0 1 0 0>; + qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 80000 100000>; + qcom,gpio-no-mux = <0>; + gpios = <&tlmm 26 0>, + <&tlmm 40 0>, + <&tlmm 39 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_STANDBY0"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio","cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 1 1 1 1>; + + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <19200000 0>; + }; + + qcom,camera@0 { + qcom,eeprom-src = <&eeprom0 &eeprom1 &eeprom2 &eeprom6 &eeprom7 &eeprom8>; + }; + + qcom,camera@1 { + qcom,csiphy-sd-index = <0>; + qcom,csid-sd-index = <0>; + qcom,eeprom-src = <&eeprom9>; + qcom,actuator-src = <&actuator0>; + qcom,led-flash-src = <&led_flash0>; + cam_vdig-supply = <&pm8953_l2>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000>; + qcom,cam-vreg-op-mode = <200000 0 80000>; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default>; + pinctrl-1 = <&cam_sensor_mclk0_sleep + &cam_sensor_rear_sleep>; + gpios = <&tlmm 26 0>, + <&tlmm 40 0>, + <&tlmm 39 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_STANDBY0"; + qcom,sensor-position = <0>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + qcom,clock-rates = <19200000 0>; + + /delete-property/ cam_vaf-supply; + }; + + qcom,camera@2 { + qcom,eeprom-src = <&eeprom3 &eeprom4 &eeprom5>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/mido/msm8953-display-mido.dtsi b/arch/arm/boot/dts/qcom/mido/msm8953-display-mido.dtsi new file mode 100644 index 0000000000000..78528f5389f14 --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/msm8953-display-mido.dtsi @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "dsi-panel-nt35532-fhd-video.dtsi" +#include "dsi-panel-nt35596-fhd-video.dtsi" +#include "dsi-panel-nt35596-tianma-fhd-video.dtsi" +#include "dsi-panel-otm1911-fhd-video.dtsi" +#include "dsi-panel-r63350-ebbg-fhd-video.dtsi" +#include "dsi-panel-ili9885-boe-fhd-video.dtsi" + +&dsi_nt35532_fhd_vid { + qcom,mdss-dsi-panel-timings-phy-v2 = [24 1f 08 09 05 03 04 a0 + 24 1f 08 09 05 03 04 a0 + 24 1f 08 09 05 03 04 a0 + 24 1f 08 09 05 03 04 a0 + 24 1b 08 09 05 03 04 a0]; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&dsi_nt35596_fhd_vid { + qcom,mdss-dsi-panel-timings-phy-v2 = [24 1f 08 09 05 03 04 a0 + 24 1f 08 09 05 03 04 a0 + 24 1f 08 09 05 03 04 a0 + 24 1f 08 09 05 03 04 a0 + 24 1b 08 08 05 03 04 a0]; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&dsi_nt35596_tianma_fhd_vid { + qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 08 09 05 03 04 a0 + 23 1e 08 09 05 03 04 a0 + 23 1e 08 09 05 03 04 a0 + 23 1e 08 09 05 03 04 a0 + 23 1a 08 09 05 03 04 a0]; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&dsi_otm1911_fhd_vid { + qcom,mdss-dsi-panel-timings-phy-v2 = [23 1E 07 08 05 03 04 a0 + 23 1E 07 08 05 03 04 a0 + 23 1E 07 08 05 03 04 a0 + 23 1E 07 08 05 03 04 a0 + 23 18 07 08 05 03 04 a0]; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&dsi_r63350_ebbg_fhd_vid { + qcom,mdss-dsi-panel-timings-phy-v2 = [24 1f 08 09 05 03 04 a0 + 24 1f 08 09 05 03 04 a0 + 24 1f 08 09 05 03 04 a0 + 24 1f 08 09 05 03 04 a0 + 24 1b 08 09 05 03 04 a0]; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&dsi_ili9885_boe_fhd_vid { + qcom,mdss-dsi-panel-timings-phy-v2 = [24 1f 08 09 05 03 04 a0 + 24 1f 08 09 05 03 04 a0 + 24 1f 08 09 05 03 04 a0 + 24 1f 08 09 05 03 04 a0 + 24 1B 08 09 05 03 04 a0]; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&mdss_dsi0 { + qcom,dsi-pref-prim-pan = <&dsi_nt35596_fhd_vid>; +}; + +&mdss_dsi0_pll { + /delete-property/ qcom,dsi-pll-ssc-en; + /delete-property/ qcom,dsi-pll-ssc-mode; +}; + +&mdss_dsi1_pll { + /delete-property/ qcom,dsi-pll-ssc-en; + /delete-property/ qcom,dsi-pll-ssc-mode; +}; + +&mdss_te_active { + mux { + function = "gpio"; + }; +}; + +&mdss_te_suspend { + mux { + function = "gpio"; + }; +}; diff --git a/arch/arm/boot/dts/qcom/mido/msm8953-general-mido.dtsi b/arch/arm/boot/dts/qcom/mido/msm8953-general-mido.dtsi new file mode 100644 index 0000000000000..390a28aabde03 --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/msm8953-general-mido.dtsi @@ -0,0 +1,532 @@ +/* Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&spmi_bus { + qcom,pm8953@0 { + qcom,power-on@800 { + qcom,store-hard-reset-reason; + qcom,pon_1 { + qcom,support-reset = <1>; + qcom,s1-timer = <6720>; + qcom,s2-timer = <0>; + qcom,s2-type = <7>; + }; + qcom,pon_3 { + qcom,pon-type = <3>; + qcom,support-reset = <1>; + qcom,s1-timer = <6720>; + qcom,s2-timer = <2000>; + qcom,s2-type = <7>; + qcom,pull-up = <1>; + }; + }; + qcom,leds@a100 { + status = "okay"; + compatible = "qcom,leds-qpnp"; + reg = <0xa100 0x100>; + label = "mpp"; + qcom,led_mpp_2 { + label = "mpp"; + linux,name = "button-backlight"; + linux,default-trigger = "none"; + qcom,default-state = "off"; + qcom,max-current = <5>; + qcom,current-setting = <5>; + qcom,id = <6>; + qcom,mode = "manual"; + qcom,source-sel = <1>; + qcom,mode-ctrl = <0x61>; + }; + }; + /delete-node/ qcom,pm8953_typec@bf00; + }; + + qcom,pmi8950@2 { + qcom,leds@a100 { + compatible = "qcom,leds-qpnp"; + reg = <0xa100 0x100>; + label = "mpp"; + /delete-node/ qcom,led_mpp_2; + }; + }; +}; + +&pm8953_gpios { + gpio@c700 { + status = "ok"; + qcom,master-en = <0>; + }; +}; + +&pmi8950_gpios { + gpio@c000 { + qcom,mode = <1>; + qcom,pull = <4>; + qcom,src-sel = <2>; + qcom,master-en = <1>; + qcom,out-strength = <2>; + status = "okay"; + }; +}; + +&qrd_batterydata { + qcom,batt-id-range-pct = <5>; + #include "batterydata-qrd-sunwoda-4v4-4100mah.dtsi" + #include "batterydata-qrd-sunwoda-ATL-4v4-4100mah.dtsi" + #include "batterydata-qrd-coslight-4v4-4100mah.dtsi" + #include "batterydata-qrd-desay-lisheng-4v4-4100mah.dtsi" + #include "batterydata-qrd-desay-4v4-4100mah.dtsi" + /delete-node/ qcom,qrd_msm8937_sku1_2920mah; + +}; + + +&pmi8950_charger { + qcom,float-voltage-mv = <4400>; + qcom,resume-delta-mv = <50>; + qcom,charge-unknown-battery; + qcom,override-usb-current; + qcom,fastchg-current-comp = <1200>; + qcom,float-voltage-comp = <16>; + qcom,thermal-mitigation = <3000 2500 2000 2000 1000 500 0>; + /delete-property/ qcom,parallel-usb-min-current-ma; + /delete-property/ qcom,parallel-usb-9v-min-current-ma; + /delete-property/ qcom,parallel-allowed-lowering-ma; + /delete-property/ qcom,chg-led-sw-controls; + /delete-property/ qcom,chg-led-support; + /delete-property/ qcom,external-typec; + /delete-property/ qcom,typec-psy-name; + /delete-property/ qcom,autoadjust-vfloat; +}; + +&pmi8950_fg { + qcom,resume-soc = <99>; + qcom,fg-cutoff-voltage-mv = <3400>; + qcom,fg-cc-cv-threshold-mv = <4380>; + qcom,fg-vbat-estimate-diff-mv = <200>; + qcom,thermal-coefficients = [c8 86 c1 50 d3 37]; + qcom,cold-bat-decidegc = <0>; + qcom,cool-bat-decidegc = <150>; + qcom,warm-bat-decidegc = <450>; + qcom,fg-restore-batt-info; + +}; + +&pmi8950_pwm { + status = "okay"; +}; + +&wled { + /delete-property/ qcom,en-ext-pfet-sc-pro; +}; + +&flash_led { + pmi8950_flash1: qcom,flash_1 { + label = "flash"; + qcom,led-name = "led:flash_1"; + qcom,default-led-trigger = "flash1_trigger"; + qcom,max-current = <1000>; + qcom,duration = <1280>; + qcom,id = <1>; + qcom,current = <625>; + }; + + pmi8950_torch1: qcom,torch_1 { + label = "torch"; + qcom,led-name = "led:torch_1"; + qcom,default-led-trigger = "torch1_trigger"; + qcom,max-current = <200>; + qcom,id = <1>; + qcom,current = <120>; + }; +}; + +&pmi_haptic { + qcom,vmax-mv = <3000>; +}; + +&soc { + qcom,mpm@601d4 { + qcom,gpio-map = <3 38 >, + <4 1 >, + <5 5 >, + <6 9 >, + <8 37>, + <9 36>, + <10 13>, + <11 35>, + <12 17>, + <13 21>, + <14 54>, + <15 34>, + <16 31>, + <17 58>, + <18 28>, + <19 42>, + <20 25>, + <21 12>, + <22 43>, + <23 44>, + <24 45>, + <25 46>, + <26 48>, + <27 65>, + <28 93>, + <29 97>, + <30 63>, + <31 70>, + <32 71>, + <33 72>, + <34 81>, + <35 85>, + <36 90>, + <50 67>, + <51 73>, + <52 74>, + <53 62>, + <59 59>, + <60 60>, + <61 61>, + <62 86>, + <63 87>, + <64 91>, + <65 129>, + <66 130>, + <67 131>, + <68 132>, + <69 133>, + <70 137>, + <71 138>, + <72 139>, + <73 140>, + <74 141>, + <0xff 24>, /* added by xiaomi */ + <0xff 88>; + }; + sn_fuse: snfuse@0xa4128 { + compatible = "qcom,sn-fuse"; + reg = <0xa4128 0x4>; + reg-names = "sn-base"; + }; + + qcom_seecom: qseecom@84a00000 { /* renamed from caf qseecom@85b00000 */ + compatible = "qcom,qseecom"; + reg = <0x84a00000 0x1900000>; /* changed by xiaomi */ + reg-names = "secapp-region"; + qcom,hlos-num-ce-hw-instances = <1>; + qcom,hlos-ce-hw-instance = <0>; + qcom,qsee-ce-hw-instance = <0>; + qcom,disk-encrypt-pipe-pair = <2>; + qcom,support-fde; + qcom,msm-bus,name = "qseecom-noc"; + qcom,msm-bus,num-cases = <4>; + qcom,msm-bus,num-paths = <1>; + qcom,support-bus-scaling; + qcom,msm-bus,vectors-KBps = + <55 512 0 0>, + <55 512 0 0>, + <55 512 120000 1200000>, + <55 512 393600 3936000>; + clocks = <&clock_gcc clk_crypto_clk_src>, + <&clock_gcc clk_gcc_crypto_clk>, + <&clock_gcc clk_gcc_crypto_ahb_clk>, + <&clock_gcc clk_gcc_crypto_axi_clk>; + clock-names = "core_clk_src", "core_clk", + "iface_clk", "bus_clk"; + qcom,ce-opp-freq = <100000000>; + }; + + /delete-node/ qseecom@85b00000; + + pwm_ir { + compatible = "pwm-ir"; + pwms = <&pmi8950_pwm 0 0>; + reg-id = "vdd"; + vdd-supply = <&pm8953_l8>; + }; + + goodix_fp { + compatible = "goodix,fingerprint"; + spi-max-frequency = <1000000>; + input-device-name = "gf3208"; + interrupt-parent = <&tlmm>; + interrupts = <9 0x0>; + + goodix,gpio_reset = <&tlmm 140 0>; + goodix,gpio_irq = <&tlmm 48 0>; + + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup1_spi_apps_clk>; + + pinctrl-names = "goodixfp_spi_active", + "goodixfp_reset_reset", + "goodixfp_reset_active", + "goodixfp_irq_active"; + + pinctrl-0 = <&goodix_spi_active>; + pinctrl-1 = <&goodix_reset_reset>; + pinctrl-2 = <&goodix_reset_active>; + pinctrl-3 = <&goodix_irq_active>; + }; + + fpc1020 { + compatible = "fpc,fpc1020"; + spi-max-frequency = <1000000>; + input-device-name = "fpc1020"; + interrupt-parent = <&tlmm>; + interrupts = <9 0x0>; + + fpc,gpio_rst = <&tlmm 140 0>; + fpc,gpio_irq = <&tlmm 48 0>; + + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup1_spi_apps_clk>; + + pinctrl-names = "fpc1020_spi_active", + "fpc1020_reset_reset", + "fpc1020_reset_active", + "fpc1020_irq_active"; + + pinctrl-0 = <&fpc_spi_active>; + pinctrl-1 = <&fpc_reset_reset>; + pinctrl-2 = <&fpc_reset_active>; + pinctrl-3 = <&fpc_irq_active>; + }; + + i2c@78b7000 { + focaltech@38 { + compatible = "focaltech,5435"; + reg = <0x38>; + interrupt-parent = <&tlmm>; + interrupts = <65 0x2>; + vdd-supply = <&pm8953_l10>; + vcc_i2c-supply = <&pm8953_l6>; + /* pins used by touchscreen */ + pinctrl-names = "pmx_ts_active","pmx_ts_suspend", + "pmx_ts_release"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + pinctrl-2 = <&ts_release>; + focaltech,name = "ft5435"; + focaltech,family-id = <0x54>; + focaltech,reset-gpio = <&tlmm 64 0x0>; + focaltech,irq-gpio = <&tlmm 65 0x2008>; + focaltech,display-coords = <0 0 1080 1920>; + focaltech,panel-coords = <0 0 1080 1920>; + focaltech,no-force-update; + focaltech,i2c-pull-up; + focaltech,group-id = <1>; + focaltech,hard-reset-delay-ms = <200>; + focaltech,soft-reset-delay-ms = <200>; + focaltech,num-max-touches = <10>; + focaltech,fw-delay-aa-ms = <2>; + focaltech,fw-delay-55-ms = <2>; + focaltech,fw-upgrade-id1 = <0x54>; + focaltech,fw-upgrade-id2 = <0x2c>; + focaltech,fw-delay-readid-ms = <10>; + focaltech,fw-delay-era-flsh-ms = <2000>; + focaltech,fw-auto-cal; + focaltech,fw-vkey-support; + focaltech,resume-in-workqueue; + focaltech,num-virtual-key = <3>; + focal,virtual_key_1 = <172 500 2040>;/*home*/ + focal,virtual_key_2 = <139 200 2040>;/*menu*/ + focal,virtual_key_3 = <158 800 2040>;/*back*/ + }; + + imagis@50 { + compatible = "imagis,ist30xx-ts"; + reg = <0x50>; + interrupt-parent = <&tlmm>; + interrupts = <65 0x2>; + vdd-supply = <&pm8953_l10>; + vcc_i2c-supply = <&pm8953_l6>; + /* pins used by touchscreen */ + pinctrl-names = "pmx_ts_active","pmx_ts_suspend", + "pmx_ts_release"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + pinctrl-2 = <&ts_release>; + imagis,reset-gpio = <&tlmm 64 0x0>; + imagis,irq-gpio = <&tlmm 65 0x2008>; + imagis,i2c-pull-up; + }; + + goodix_ts@14 { + compatible = "goodix,gt9xx"; + reg = <0x14>; + interrupt-parent = <&tlmm>; + interrupts = <65 0x0>; + pinctrl-names = "pmx_ts_active","pmx_ts_suspend", + "pmx_ts_release"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + pinctrl-2 = <&ts_release>; + vdd_ana-supply = <&pm8953_l10>; + vcc_i2c-supply = <&pm8953_l6>; + goodix,rst-gpio = <&tlmm 64 0x0>; + goodix,irq-gpio = <&tlmm 65 0x2008>; + goodix,cfg-group0 = [45 38 04 80 07 0A 35 41 01 0A + 26 0B 5A 32 05 05 00 00 00 00 + 00 00 05 14 14 26 14 8C 2E 0E + 4A 4C F4 0A F4 0A 00 BA 33 11 + 00 00 00 00 00 05 03 28 78 96 + 3A 1E 5A 8F 90 03 00 00 00 04 + CE 21 00 B0 29 28 98 34 00 87 + 41 60 7B 51 00 7B 18 38 60 00 + F0 55 40 AA A0 27 00 04 53 00 + 00 00 00 00 00 02 00 00 00 00 + 00 00 00 00 00 00 3C 00 00 00 + 00 28 02 04 06 08 0A 0C 0E 10 + 12 14 16 18 1A 1C 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 + 00 00 00 02 04 06 08 0A 0C 0F + 10 12 13 14 16 18 1C 1D 1E 1F + 20 21 22 24 26 28 29 2A 00 00 + 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 23 01]; + goodix,cfg-group1 = [49 38 04 80 07 0A 3D 49 01 48 + 50 0F 50 41 03 65 00 00 00 00 + 00 00 0F 16 1A 23 14 87 27 DD + 50 52 E7 07 E7 07 00 42 33 91 + 0A 00 00 00 00 83 C4 14 14 C8 + 02 3C 64 8F D0 03 05 1E 00 04 + 93 3F 00 8A 46 00 82 4D 00 7C + 55 00 76 5F 00 76 18 38 60 00 + F7 55 40 99 99 17 00 00 D1 00 + 00 00 00 00 00 02 00 00 05 28 + 00 00 00 00 00 28 64 00 00 00 + 00 50 0C 0B 0A 09 08 07 06 05 + 04 03 02 01 00 0D 0E 0F 10 11 + 12 13 14 15 16 17 18 19 1A FF + FF FF 29 28 24 22 20 1F 1E 0A + 08 06 05 04 02 00 FF FF FF 00 + 00 00 00 00 00 00 00 00 28 32 + 3C 10 23 28 0F 00 00 00 00 00 + 00 00 0F 4B 00 00 00 00 00 00 + 1E 50 00 00 00 05 00 00 00 00 + 01 14 78 1A 19 3C 28 00 00 00 + 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 83 01]; + }; + + }; + + i2c@78b6000 { /* BLSP1 QUP3 */ + aw2013@45 { + compatible = "awinic,aw2013"; + reg = <0x45>; + vdd-supply = <&pm8953_l10>; + vcc-supply = <&pm8953_l5>; + + aw2013,red { + aw2013,name = "red"; + aw2013,id = <0>; + aw2013,max-brightness = <150>; + aw2013,max-current = <1>; + aw2013,rise-time-ms = <3>; + aw2013,hold-time-ms = <1>; + aw2013,fall-time-ms = <3>; + aw2013,off-time-ms = <3>; + }; + + aw2013,green { + aw2013,name = "green"; + aw2013,id = <1>; + aw2013,max-brightness = <150>; + aw2013,max-current = <1>; + aw2013,rise-time-ms = <3>; + aw2013,hold-time-ms = <1>; + aw2013,fall-time-ms = <3>; + aw2013,off-time-ms = <3>; + }; + + aw2013,blue { + aw2013,name = "blue"; + aw2013,id = <2>; + aw2013,max-brightness = <150>; + aw2013,max-current = <1>; + aw2013,rise-time-ms = <3>; + aw2013,hold-time-ms = <1>; + aw2013,fall-time-ms = <3>; + aw2013,off-time-ms = <3>; + }; + }; + }; +}; + +&usb3 { + qcom,detect-dpdm-floating; +}; + +&qusb_phy { + qcom,qusb-phy-init-seq = <0xF8 0x80 + 0x53 0x84 /* changed by xiaomi */ + 0x93 0x88 /* changed by xiaomi */ + 0xCf 0x8C /* changed by xiaomi */ + 0x14 0x9C + 0x30 0x08 + 0x79 0x0C + 0x21 0x10 + 0x00 0x90 + 0x9F 0x1C + 0x00 0x18>; +}; + + +&pm8953_diangu_dig { + status = "ok"; +}; + +&pm8953_diangu_analog { + status = "ok"; +}; + +&ext_codec { + status = "disabled"; +}; + +&slim_msm { + status = "disabled"; +}; + +&dai_slim { + status = "disabled"; +}; + +&clock_audio { + status = "disabled"; +}; + +&wcd9335 { + status = "disabled"; +}; + +&wcd_rst_gpio { + status = "disabled"; +}; + +&wcd9xxx_intc { + status = "disabled"; +}; + +&firmware { + android { + fstab { + vendor { + dev = "/dev/block/platform/soc/7824900.sdhci/by-name/cust"; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom/mido/msm8953-memory-mido.dtsi b/arch/arm/boot/dts/qcom/mido/msm8953-memory-mido.dtsi new file mode 100644 index 0000000000000..5d94757650eda --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/msm8953-memory-mido.dtsi @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&other_ext_mem { + reg = <0x0 0x84A00000 0x0 0x1E00000>; +}; + +/ { + reserved-memory { + pstore_reserve_mem: pstore_reserve_mem_region@0 { + linux,reserve-contiguous-region; + linux,reserve-region; + linux,remove-completely; + reg = <0x0 0x9ff00000 0x0 0x00100000>; + label = "pstore_reserve_mem"; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom/mido/msm8953-mido.dtsi b/arch/arm/boot/dts/qcom/mido/msm8953-mido.dtsi new file mode 100644 index 0000000000000..fae20843be834 --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/msm8953-mido.dtsi @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "msm-audio-mido.dtsi" +#include "msm8953-general-mido.dtsi" +#include "msm8953-display-mido.dtsi" +#include "msm8953-camera-sensor-qrd-mido.dtsi" +#include "msm8953-pinctrl-mido.dtsi" +#include "msm8953-memory-mido.dtsi" diff --git a/arch/arm/boot/dts/qcom/mido/msm8953-pinctrl-mido.dtsi b/arch/arm/boot/dts/qcom/mido/msm8953-pinctrl-mido.dtsi new file mode 100644 index 0000000000000..2c672aed4304c --- /dev/null +++ b/arch/arm/boot/dts/qcom/mido/msm8953-pinctrl-mido.dtsi @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + tlmm: pinctrl@1000000 { + goodix_spi_active: goodix_spi_active{ + mux { + pins = "gpio135", "gpio136", "gpio137", "gpio138"; + function = "blsp_spi6"; + }; + config { + pins = "gpio135", "gpio136", "gpio137", "gpio138"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; + goodix_reset_reset: goodix_reset_reset{ + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable = <0>; + output-low; + }; + }; + goodix_reset_active: goodix_reset_active{ + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable = <0>; + output-high; + }; + }; + goodix_irq_active: goodix_irq_active { + mux { + pins = "gpio48"; + function = "gpio"; + }; + config { + pins = "gpio48"; + drive-strength = <2>; + bias-disable = <0>; + input-enable; + }; + }; + + /* fingerprint pin function */ + fpc_spi_active: fpc_spi_active { + mux { + pins = "gpio135", "gpio136", "gpio137", "gpio138"; + function = "blsp_spi7"; + }; + + config { + pins = "gpio135", "gpio136", "gpio137", "gpio138"; + drive-strength = <2>; + bias-disable; + }; + }; + fpc_reset_reset: fpc_reset_reset { + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable; + output-low; + }; + }; + fpc_reset_active: fpc_reset_active { + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + fpc_irq_active: fpc_irq_active { + mux { + pins = "gpio48"; + function = "gpio"; + }; + config { + pins = "gpio48"; + drive-strength = <2>; + bias-disable; + input-enable; + }; + }; + + }; + +}; + diff --git a/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-mido.dts b/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-mido.dts new file mode 100644 index 0000000000000..a70d79e84ef91 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-mido.dts @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "msm8953.dtsi" +#include "msm-pmi8950.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. MSM8953 + PMI8950 QRD SKU3"; + compatible = "qcom,msm8953-qrd-sku3", + "qcom,msm8953-qrd", "qcom,msm8953", "qcom,qrd"; + qcom,board-id= <0x0b 0>; +}; + +&soc { + led_flash0: qcom,camera-flash { + cell-index = <0>; + compatible = "qcom,camera-flash"; + qcom,flash-type = <1>; + qcom,flash-source = <&pmi8950_flash0 &pmi8950_flash1>; + qcom,torch-source = <&pmi8950_torch0 &pmi8950_torch1>; + qcom,switch-source = <&pmi8950_switch>; + }; +}; + +#include "msm8953-qrd-sku3.dtsi" + +&usb3 { + vbus_dwc3-supply = <&smbcharger_charger_otg>; +}; + +&mdss_dsi1 { + lab-supply = <&lab_regulator>; + ibb-supply = <&ibb_regulator>; +}; + +&dsi_panel_pwr_supply { + qcom,panel-supply-entry@2 { + reg = <2>; + qcom,supply-name = "lab"; + qcom,supply-min-voltage = <4600000>; + qcom,supply-max-voltage = <6000000>; + qcom,supply-enable-load = <100000>; + qcom,supply-disable-load = <100>; + }; + + qcom,panel-supply-entry@3 { + reg = <3>; + qcom,supply-name = "ibb"; + qcom,supply-min-voltage = <4600000>; + qcom,supply-max-voltage = <6000000>; + qcom,supply-enable-load = <100000>; + qcom,supply-disable-load = <100>; + qcom,supply-post-on-sleep = <10>; + }; +}; + +#include "mido/msm8953-mido.dtsi" From f777a1cdde5274d28e80a0f6ee52a41518f6385a Mon Sep 17 00:00:00 2001 From: Vitaliy Tomin Date: Fri, 23 Mar 2018 13:10:10 +0800 Subject: [PATCH 196/508] arch: arm: boot: Add overlayed tissot dtsi --- arch/arm/boot/dts/qcom/Makefile | 1 + .../boot/dts/qcom/msm8953-qrd-sku3-tissot.dts | 70 +++ .../batterydata-qrd-coslight-3000mAh.dtsi | 48 ++ .../tissot/batterydata-qrd-scud-3000mAh.dtsi | 48 ++ ...batterydata-qrd-sunwoda-liwei-3000mAh.dtsi | 48 ++ .../tissot/dsi-panel-ft8716-fhd-video.dtsi | 194 ++++++++ .../tissot/dsi-panel-ili7807-fhd-video.dtsi | 97 ++++ .../tissot/dsi-panel-otm1911-fhd-video.dtsi | 83 ++++ .../dts/qcom/tissot/msm-audio-tissot.dtsi | 48 ++ .../dts/qcom/tissot/msm-pm8953-tissot.dtsi | 41 ++ .../dts/qcom/tissot/msm-pmi8950-tissot.dtsi | 75 +++ .../dts/qcom/tissot/msm8953-audio-tissot.dtsi | 119 +++++ .../msm8953-camera-sensor-qrd-tissot.dtsi | 444 ++++++++++++++++++ .../qcom/tissot/msm8953-pinctrl-tissot.dtsi | 348 ++++++++++++++ .../dts/qcom/tissot/msm8953-pm-tissot.dtsi | 144 ++++++ .../msm8953-qrd-sku3-tissot-overlay.dtsi | 14 + .../qcom/tissot/msm8953-qrd-sku3-tissot.dtsi | 56 +++ .../dts/qcom/tissot/msm8953-qrd-tissot.dtsi | 294 ++++++++++++ .../qcom/tissot/msm8953-regulator-tissot.dtsi | 50 ++ .../boot/dts/qcom/tissot/msm8953-tissot.dtsi | 128 +++++ 20 files changed, 2350 insertions(+) create mode 100644 arch/arm/boot/dts/qcom/msm8953-qrd-sku3-tissot.dts create mode 100644 arch/arm/boot/dts/qcom/tissot/batterydata-qrd-coslight-3000mAh.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/batterydata-qrd-scud-3000mAh.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/batterydata-qrd-sunwoda-liwei-3000mAh.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/dsi-panel-ft8716-fhd-video.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/dsi-panel-ili7807-fhd-video.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/dsi-panel-otm1911-fhd-video.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/msm-audio-tissot.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/msm-pm8953-tissot.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/msm-pmi8950-tissot.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/msm8953-audio-tissot.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/msm8953-camera-sensor-qrd-tissot.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/msm8953-pinctrl-tissot.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/msm8953-pm-tissot.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/msm8953-qrd-sku3-tissot-overlay.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/msm8953-qrd-sku3-tissot.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/msm8953-qrd-tissot.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/msm8953-regulator-tissot.dtsi create mode 100644 arch/arm/boot/dts/qcom/tissot/msm8953-tissot.dtsi diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index 1604e8aea450d..aa2360d26e729 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -255,6 +255,7 @@ dtb-$(CONFIG_ARCH_MSM8940) += msm8940-pmi8937-cdp.dtb \ ifeq ($(CONFIG_MACH_XIAOMI_MSM8953),y) dtb-$(CONFIG_MACH_XIAOMI_MIDO) += msm8953-qrd-sku3-mido.dtb +dtb-$(CONFIG_MACH_XIAOMI_TISSOT) += msm8953-qrd-sku3-tissot.dtb else dtb-$(CONFIG_ARCH_MSM8953) += msm8953-sim.dtb \ msm8953-rumi.dtb \ diff --git a/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-tissot.dts b/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-tissot.dts new file mode 100644 index 0000000000000..5bad15a52e1dd --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-tissot.dts @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "msm8953.dtsi" +#include "msm-pmi8950.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. MSM8953 + PMI8950 QRD SKU3"; + compatible = "qcom,msm8953-qrd-sku3", + "qcom,msm8953-qrd", "qcom,msm8953", "qcom,qrd"; + qcom,board-id= <0x1000b 0>; +}; + +&soc { + led_flash0: qcom,camera-flash { + cell-index = <0>; + compatible = "qcom,camera-flash"; + qcom,flash-type = <1>; + qcom,flash-source = <&pmi8950_flash0 &pmi8950_flash1>; + qcom,torch-source = <&pmi8950_torch0 &pmi8950_torch1>; + qcom,switch-source = <&pmi8950_switch>; + }; +}; + +#include "msm8953-qrd-sku3.dtsi" + +&usb3 { + vbus_dwc3-supply = <&smbcharger_charger_otg>; +}; + +&mdss_dsi1 { + lab-supply = <&lab_regulator>; + ibb-supply = <&ibb_regulator>; +}; + +&dsi_panel_pwr_supply { + qcom,panel-supply-entry@2 { + reg = <2>; + qcom,supply-name = "lab"; + qcom,supply-min-voltage = <4600000>; + qcom,supply-max-voltage = <6000000>; + qcom,supply-enable-load = <100000>; + qcom,supply-disable-load = <100>; + }; + + qcom,panel-supply-entry@3 { + reg = <3>; + qcom,supply-name = "ibb"; + qcom,supply-min-voltage = <4600000>; + qcom,supply-max-voltage = <6000000>; + qcom,supply-enable-load = <100000>; + qcom,supply-disable-load = <100>; + qcom,supply-post-on-sleep = <10>; + }; +}; + + +#include "tissot/msm8953-qrd-sku3-tissot-overlay.dtsi" \ No newline at end of file diff --git a/arch/arm/boot/dts/qcom/tissot/batterydata-qrd-coslight-3000mAh.dtsi b/arch/arm/boot/dts/qcom/tissot/batterydata-qrd-coslight-3000mAh.dtsi new file mode 100644 index 0000000000000..bffc08d47d8d8 --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/batterydata-qrd-coslight-3000mAh.dtsi @@ -0,0 +1,48 @@ + +qcom,2760942_huaqin_d2cos_3080mah_averaged_masterslave_jan16th2017 { + qcom,max-voltage-uv = <4380000>; + qcom,nom-batt-capacity-mah = <3080>; + qcom,batt-id-kohm = <50>; + qcom,battery-beta = <3380>; + qcom,battery-type = "battey_qrd_coslight_3080mah"; + qcom,chg-rslow-comp-c1 = <3969816>; + qcom,chg-rslow-comp-c2 = <7140145>; + qcom,chg-rs-to-rslow = <997019>; + qcom,chg-rslow-comp-thr = <0xB8>; + qcom,checksum = <0x5DAD>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + E2 83 DF 7C + 10 81 12 77 + 65 83 51 74 + 74 89 94 94 + 33 82 B0 99 + A5 BC 1D C9 + 55 10 02 88 + 9A 7D 74 81 + 8D 77 4E 83 + CD 70 15 61 + CD 7E 4F 82 + 9D 99 DF BC + B5 C9 59 0C + 24 0C 15 59 + 14 70 B2 FD + A4 3F 23 3D + 6E 33 00 00 + 35 46 01 38 + FE 12 00 00 + 00 00 00 00 + 00 00 00 00 + 97 6B B4 6A + EF 60 0B 81 + 92 6E 72 60 + 3E 59 C0 79 + 5B 6D 56 5B + 18 7F 64 9A + 18 E9 61 55 + 5F A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/tissot/batterydata-qrd-scud-3000mAh.dtsi b/arch/arm/boot/dts/qcom/tissot/batterydata-qrd-scud-3000mAh.dtsi new file mode 100644 index 0000000000000..ee6bfa161959a --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/batterydata-qrd-scud-3000mAh.dtsi @@ -0,0 +1,48 @@ + +qcom,3002485_huaqin_d2scud_3080mah_averaged_masterslave_jul3rd2017 { + qcom,max-voltage-uv = <4380000>; + qcom,nom-batt-capacity-mah = <3080>; + qcom,batt-id-kohm = <24>; + qcom,battery-beta = <3380>; + qcom,battery-type = "huaqin_d2_scud_3080mah"; + qcom,chg-rslow-comp-c1 = <4675933>; + qcom,chg-rslow-comp-c2 = <9539708>; + qcom,chg-rs-to-rslow = <1472887>; + qcom,chg-rslow-comp-thr = <0xC1>; + qcom,checksum = <0xF351>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + D2 83 3D 7C + 9C 80 55 76 + 51 83 10 4A + C5 81 7F 8D + 13 82 DF 9A + 4F BE E4 CB + 56 0E E3 83 + 2E 7C 65 80 + B3 75 56 83 + 16 68 93 80 + 48 8D 45 82 + 22 9A 9D BD + F0 CA 53 0D + 2C 0C F9 59 + 14 70 A5 FD + AE 41 1E 47 + 7A 44 00 00 + 3A 46 15 3A + FD 36 00 00 + 00 00 00 00 + 00 00 00 00 + BB 73 8D 70 + 34 8C 21 7C + F5 7D C2 73 + FE 6E D4 70 + C6 75 BE 69 + 92 66 50 A0 + 3B 47 60 2A + 5D A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/tissot/batterydata-qrd-sunwoda-liwei-3000mAh.dtsi b/arch/arm/boot/dts/qcom/tissot/batterydata-qrd-sunwoda-liwei-3000mAh.dtsi new file mode 100644 index 0000000000000..79b6c4944f73a --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/batterydata-qrd-sunwoda-liwei-3000mAh.dtsi @@ -0,0 +1,48 @@ + +qcom,2881955_huaqin_d2sunwoda_3000mah_averaged_masterslave_apr18th2017 { + qcom,max-voltage-uv = <4380000>; + qcom,nom-batt-capacity-mah = <3000>; + qcom,batt-id-kohm = <77>; + qcom,battery-beta = <3380>; + qcom,battery-type = "batterydata-qrd-sunwoda-liwei"; + qcom,chg-rslow-comp-c1 = <3772651>; + qcom,chg-rslow-comp-c2 = <6125204>; + qcom,chg-rs-to-rslow = <1306828>; + qcom,chg-rslow-comp-thr = <0xB1>; + qcom,checksum = <0xA973>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + F6 83 B0 7D + C4 81 42 7C + 53 83 3C 59 + 2D 80 42 87 + 1B 82 80 9A + C5 BD 09 CB + 5B 0E 16 88 + 29 7F D2 82 + 3F 7D 4A 83 + E6 71 A0 74 + 71 6D 5A 82 + 24 99 3C BC + B5 C8 5E 0E + 2C 0C 91 59 + 14 70 B2 FD + 2E 24 7D 44 + FE 1A 00 00 + D9 47 CD 23 + FE 32 00 00 + 00 00 00 00 + 00 00 00 00 + 9B 71 66 70 + 86 7C CD 88 + 22 77 09 70 + E0 74 77 71 + BB 74 79 68 + 54 6E 0A AA + 20 D7 62 EB + 64 A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/tissot/dsi-panel-ft8716-fhd-video.dtsi b/arch/arm/boot/dts/qcom/tissot/dsi-panel-ft8716-fhd-video.dtsi new file mode 100644 index 0000000000000..7e7284310d193 --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/dsi-panel-ft8716-fhd-video.dtsi @@ -0,0 +1,194 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_ft8716_fhd_vid: qcom,mdss_dsi_ft8716_fhd_video { + qcom,mdss-dsi-panel-name = "ft8716 fhd video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <1920>; + qcom,mdss-dsi-h-front-porch = <32>; + qcom,mdss-dsi-h-back-porch = <32>; + qcom,mdss-dsi-h-pulse-width = <4>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <16>; + qcom,mdss-dsi-v-front-porch = <16>; + qcom,mdss-dsi-v-pulse-width = <2>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [ + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 04 FF 87 16 01 + 39 01 00 00 00 00 02 00 80 + 39 01 00 00 00 00 03 FF 87 16 + 39 01 00 00 00 00 02 00 80 + 39 01 00 00 00 00 0D D8 80 81 80 00 00 00 01 01 01 01 01 01 + 39 01 00 00 00 00 02 00 90 + 39 01 00 00 00 00 0D D8 00 01 02 01 01 02 01 02 02 02 02 01 + 39 01 00 00 00 00 02 00 A0 + 39 01 00 00 00 00 0D D8 00 01 03 06 08 0b 0e 12 15 17 1a 18 + 39 01 00 00 00 00 02 00 B0 + 39 01 00 00 00 00 0D D8 80 80 80 82 83 85 88 89 8b 8e 8f 8e + 39 01 00 00 00 00 02 00 C0 + 39 01 00 00 00 00 0D D8 82 85 85 86 89 8c 90 93 97 9b 9e 9c + 39 01 00 00 00 00 02 00 D0 + 39 01 00 00 00 00 0D D8 02 04 05 06 09 0c 0e 12 14 17 19 18 + 39 01 00 00 00 00 02 00 E0 + 39 01 00 00 00 00 04 D8 ff f4 f7 + 39 01 00 00 00 00 02 00 C0 + 39 01 00 00 00 00 02 D7 01 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 00 A0 + 39 01 00 00 00 00 0D D6 0a 08 0a 14 1d 16 16 17 0e 12 13 14 + 39 01 00 00 00 00 02 00 B0 + 39 01 00 00 00 00 0D D6 ae ae c8 a9 c9 bf 9a 9a af ab 92 99 + 39 01 00 00 00 00 02 00 C0 + 39 01 00 00 00 00 0D D6 8d 8d b0 9c b0 ab 77 77 96 9c 8c 91 + 39 01 00 00 00 00 02 00 D0 + 39 01 00 00 00 00 0D D6 aa aa 98 8e 99 73 6f 74 8a 92 86 8a + 39 01 00 00 00 00 02 00 81 + 39 01 00 00 00 00 0A CA 7f ff b9 ff b9 ff 00 00 00 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 10 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 b0 bb bb 9b dc bb ab a9 88 88 88 56 55 55 55 55 55 55 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 11 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 b0 ba ab 8c eb ba aa 9a 88 88 88 67 66 56 55 55 55 55 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 12 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 b0 b9 ab 8b db ba 9a 9a 88 88 88 67 66 66 66 56 55 55 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 13 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 a0 aa 9b 8c d9 ba 9a 99 88 88 88 67 66 66 66 66 66 55 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 14 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 a0 a9 9b 8b d9 aa aa 98 88 88 88 68 66 66 66 66 66 66 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 15 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 a0 a9 8a 8c c9 9a 9a 99 88 88 88 78 77 66 66 66 66 66 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 16 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 a0 99 8a 9b c8 9a a9 89 88 88 88 78 77 77 67 66 66 66 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 17 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 90 9a 89 9b b8 a9 99 8a 88 88 88 78 77 77 77 67 66 66 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 18 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 90 99 8a 8a b8 a9 99 89 88 88 88 78 77 77 77 77 77 66 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 19 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 90 99 89 8a b8 99 89 8a 88 88 88 78 77 77 77 77 77 77 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 1A + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 80 99 89 8a a8 99 89 99 88 88 88 88 78 77 77 77 77 77 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 1B + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 80 a8 98 89 a8 98 89 99 88 88 88 88 88 78 77 77 77 77 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 1C + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 80 98 89 89 98 89 89 89 88 88 88 88 88 88 88 77 77 77 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 1D + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 80 98 98 98 97 98 88 89 88 88 88 88 88 88 88 88 77 77 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 1E + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 80 88 89 88 88 89 98 88 88 88 88 88 88 88 88 88 88 77 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 1F + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 13 C7 80 88 88 98 97 88 88 88 88 88 88 88 88 88 88 88 88 88 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 C6 00 + 39 01 00 00 00 00 02 00 b0 + 39 01 00 00 00 00 02 ca 00 + 39 01 00 00 00 00 02 00 b2 + 39 01 00 00 00 00 02 ca 04 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 2C + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 78 00 02 11 00 + 39 01 00 00 14 00 02 29 00]; + qcom,mdss-dsi-off-command = [39 01 00 00 14 00 02 28 00 + 39 01 00 00 78 00 02 10 00 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 04 FF 87 16 01 + 39 01 00 00 00 00 02 00 80 + 39 01 00 00 00 00 03 FF 87 16 + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 05 F7 5a a5 87 16]; + qcom,mdss-dsi-panel-timings-phy-v2 = [23 1E 07 08 05 03 04 a0 + 23 1E 07 08 05 03 04 a0 + 23 1E 07 08 05 03 04 a0 + 23 1E 07 08 05 03 04 a0 + 23 18 07 08 05 03 04 a0]; + + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-cold_gamma-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-warm_gamma-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-default_gamma-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-CABC_on-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CABC_off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CE_on-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CE_off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33 + 22 27 1e 03 04 00]; + qcom,mdss-dsi-t-clk-post = <0x0d>; + qcom,mdss-dsi-t-clk-pre = <0x2F>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-value = <0x9C>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/tissot/dsi-panel-ili7807-fhd-video.dtsi b/arch/arm/boot/dts/qcom/tissot/dsi-panel-ili7807-fhd-video.dtsi new file mode 100644 index 0000000000000..43db322e4f575 --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/dsi-panel-ili7807-fhd-video.dtsi @@ -0,0 +1,97 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_ili7807_fhd_vid: qcom,mdss_dsi_ili7807_fhd_video { + qcom,mdss-dsi-panel-name = "ili7807 fhd video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <1920>; + qcom,mdss-dsi-h-front-porch = <84>; + qcom,mdss-dsi-h-back-porch = <80>; + qcom,mdss-dsi-h-pulse-width = <24>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <16>; + qcom,mdss-dsi-v-front-porch = <22>; + qcom,mdss-dsi-v-pulse-width = <8>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [39 01 00 00 00 00 04 ff 78 07 05 + 39 01 00 00 00 00 02 03 60 + 39 01 00 00 00 00 02 04 03 + 39 01 00 00 00 00 02 00 34 + 39 01 00 00 00 00 04 ff 78 07 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 00 00 03 51 0f ff + 39 01 00 00 00 00 02 53 2c + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 78 00 02 11 00 + 39 01 00 00 00 00 04 ff 78 07 06 + 39 01 00 00 00 00 02 B2 22 + 39 01 00 00 00 00 02 A2 07 + 39 01 00 00 00 00 02 A3 1E + 39 01 00 00 00 00 04 ff 78 07 01 + 39 01 00 00 00 00 02 65 04 + 39 01 00 00 00 00 02 66 04 + 39 01 00 00 00 00 02 6d 04 + 39 01 00 00 00 00 04 ff 78 07 00 + 39 01 00 00 14 00 02 29 00]; + qcom,mdss-dsi-off-command = [39 01 00 00 00 00 04 ff 78 07 00 + 39 01 00 00 14 00 02 28 00 + 39 01 00 00 78 00 02 10 00 + 39 01 00 00 00 00 04 ff 78 07 01 + 39 01 00 00 00 00 02 58 01]; + qcom,mdss-dsi-panel-timings-phy-v2 = [24 1F 08 09 05 03 04 a0 + 24 1F 08 09 05 03 04 a0 + 24 1F 08 09 05 03 04 a0 + 24 1F 08 09 05 03 04 a0 + 24 1B 08 09 05 03 04 a0]; + + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33 + 22 27 1e 03 04 00]; + qcom,mdss-dsi-t-clk-post = <0x0d>; + qcom,mdss-dsi-t-clk-pre = <0x30>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-value = <0x9C>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/tissot/dsi-panel-otm1911-fhd-video.dtsi b/arch/arm/boot/dts/qcom/tissot/dsi-panel-otm1911-fhd-video.dtsi new file mode 100644 index 0000000000000..3ef36b4fa8979 --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/dsi-panel-otm1911-fhd-video.dtsi @@ -0,0 +1,83 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_otm1911_fhd_vid: qcom,mdss_dsi_otm1911_fhd_video { + qcom,mdss-dsi-panel-name = "otm1911 fhd video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <1920>; + qcom,mdss-dsi-h-front-porch = <24>; + qcom,mdss-dsi-h-back-porch = <24>; + qcom,mdss-dsi-h-pulse-width = <20>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <6>; + qcom,mdss-dsi-v-front-porch = <14>; + qcom,mdss-dsi-v-pulse-width = <2>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [ + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 2c + 39 01 00 00 00 00 02 55 00 + + 39 01 00 00 78 00 02 11 00 + 39 01 00 00 14 00 02 29 00]; + + qcom,mdss-dsi-off-command = [39 01 00 00 32 00 02 28 00 + 39 01 00 00 78 00 02 10 00 + ]; + qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 07 08 05 03 04 a0 + 23 1e 07 08 05 03 04 a0 + 23 1e 07 08 05 03 04 a0 + 23 1e 07 08 05 03 04 a0 + 23 18 07 08 05 03 04 a0]; + + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33 + 22 27 1e 03 04 00]; + qcom,mdss-dsi-t-clk-post = <0x0d>; + qcom,mdss-dsi-t-clk-pre = <0x2e>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-value = <0x9C>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/tissot/msm-audio-tissot.dtsi b/arch/arm/boot/dts/qcom/tissot/msm-audio-tissot.dtsi new file mode 100644 index 0000000000000..127489430f45e --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/msm-audio-tissot.dtsi @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + + int_codec: sound { + status = "ok"; + qcom,msm-hs-micbias-type = "internal"; + qcom,audio-routing = + "RX_BIAS", "MCLK", + "SPK_RX_BIAS", "MCLK", + "INT_LDO_H", "MCLK", + "MIC BIAS External", "Handset Mic", + "MIC BIAS Internal2", "Headset Mic", + "MIC BIAS External", "Secondary Mic", + "AMIC1", "MIC BIAS External", + "AMIC2", "MIC BIAS Internal2", + "AMIC3", "MIC BIAS External"; + /delete-property/ qcom,hdmi-dba-codec-rx; + + }; + + i2c@78b6000 { + spkamp@3a {/* max98927 smartpa device*/ + compatible = "maxim,max98927L"; + status = "okay"; + reg = <0x3a>; + mono_stereo_mode = <0>; + interleave_mode = <0>; + vmon-l-slot = <1>; + imon-l-slot = <1>; + vmon-r-slot = <1>; + imon-r-slot = <1>; + maxim,98927-reset-gpio = <&tlmm 86 0>; + }; + }; +}; + diff --git a/arch/arm/boot/dts/qcom/tissot/msm-pm8953-tissot.dtsi b/arch/arm/boot/dts/qcom/tissot/msm-pm8953-tissot.dtsi new file mode 100644 index 0000000000000..489d2150451dd --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/msm-pm8953-tissot.dtsi @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&spmi_bus { + + qcom,pm8953@0 { + + qcom,power-on@800 { + qcom,store-hard-reset-reason; + + qcom,pon_1 { + qcom,support-reset = <1>; + qcom,s1-timer = <6720>; + qcom,s2-timer = <0>; + qcom,s2-type = <7>; + }; + + qcom,pon_3 { + qcom,pon-type = <3>; + qcom,support-reset = <1>; + qcom,pull-up = <1>; + qcom,s1-timer = <3072>; + qcom,s2-timer = <2000>; + qcom,s2-type = <1>; + qcom,use-bark; + }; + }; + + }; + +}; diff --git a/arch/arm/boot/dts/qcom/tissot/msm-pmi8950-tissot.dtsi b/arch/arm/boot/dts/qcom/tissot/msm-pmi8950-tissot.dtsi new file mode 100644 index 0000000000000..5379526b1852c --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/msm-pmi8950-tissot.dtsi @@ -0,0 +1,75 @@ +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +&spmi_bus { + + qcom,pmi8950@2 { + pmi8950_vadc: vadc@3100 { + chan@10 { + label = "pcba_vadc"; + reg = <0x10>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; //1:1 + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <1>; + qcom,fast-avg-setup = <2>; + }; + }; + + pmi8950_mpps: mpps { + mpp@a000 { + qcom,mode = <4>; /* AIN input */ + qcom,invert = <1>; /* Enable MPP */ + com,ain-route = <0>; /* AMUX 5 */ + qcom,master-en = <1>; + qcom,src-sel = <0>; /* Function constant */ + status = "okay"; + }; + }; + + pmi8950_charger: qcom,qpnp-smbcharger { + qcom,iterm-ma = <200>; + qcom,float-voltage-mv = <4380>; + qcom,resume-delta-mv = <50>; + qcom,charge-unknown-battery; + /delete-property/ qcom,autoadjust-vfloat; + qcom,override-usb-current; + qcom,fastchg-current-comp = <900>; + qcom,float-voltage-comp = <15>; + + }; + + pmi8950_fg: qcom,fg { + /delete-property/ qcom,resume-soc; + qcom,resume-soc-raw = <254>; + qcom,fg-iterm-ma = <3000>; + qcom,fg-chg-iterm-ma = <200>; + qcom,fg-cutoff-voltage-mv = <3400>; + qcom,irq-volt-empty-mv = <3100>; + qcom,fg-use-vbat-low-empty-soc; + qcom,hold-soc-while-full; + qcom,fg-cc-cv-threshold-mv =<4370>; + qcom,vbat-estimate-diff-mv = <250>; + + }; + }; + + qcom,pmi8950@3 { + wled: qcom,leds@d800 { + qcom,en-cabc; + }; + + }; +}; diff --git a/arch/arm/boot/dts/qcom/tissot/msm8953-audio-tissot.dtsi b/arch/arm/boot/dts/qcom/tissot/msm8953-audio-tissot.dtsi new file mode 100644 index 0000000000000..99ed089d01c2b --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/msm8953-audio-tissot.dtsi @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +&int_codec { + qcom,msm-spk-ext-pa = <&tlmm 141 0>; + qcom,msm-mbhc-hphl-swh = <1>; + qcom,msm-mbhc-gnd-swh = <1>; + + qcom,msm-gpios = + "pri_i2s", + "ext_pa_gpio", + "quin_i2s", + "comp_gpio"; + qcom,pinctrl-names = + "all_off", + "pri_i2s_act", + "ext_pa_gpio_act", + "pri_i2s_ext_pa_gpio_act", + "quin_act", + "quin_pri_i2s_act", + "quin_ext_pa_gpio_act", + "quin_ext_pa_gpio_pri_i2s_act", + "comp_gpio_act", + "comp_gpio_pri_i2s_act", + "comp_gpio_ext_pa_gpio_act", + "comp_gpio_pri_i2s_ext_pa_gpio_act", + "comp_gpio_quin_act", + "comp_gpio_quin_pri_i2s_act", + "comp_gpio_quin_ext_pa_gpio_act", + "comp_gpio_quin_ext_pa_gpio_pri_i2s_act"; + + + pinctrl-names = + "all_off", + "pri_i2s_act", + "ext_pa_gpio_act", + "pri_i2s_ext_pa_gpio_act", + "quin_act", + "quin_pri_i2s_act", + "quin_ext_pa_gpio_act", + "quin_ext_pa_gpio_pri_i2s_act", + "comp_gpio_act", + "comp_gpio_pri_i2s_act", + "comp_gpio_ext_pa_gpio_act", + "comp_gpio_pri_i2s_ext_pa_gpio_act", + "comp_gpio_quin_act", + "comp_gpio_quin_pri_i2s_act", + "comp_gpio_quin_ext_pa_gpio_act", + "comp_gpio_quin_ext_pa_gpio_pri_i2s_act"; + + pinctrl-0 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_sus &cross_conn_det_sus + &pri_tlmm_lines_sus &pri_tlmm_ws_sus &ext_pa_power_off>; + pinctrl-1 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_act &ext_pa_power_off + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-2 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_sus &ext_pa_power_on + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-3 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_act &ext_pa_power_on + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-4 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_sus &ext_pa_power_off + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-5 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_act &ext_pa_power_off + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-6 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_sus &ext_pa_power_on + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-7 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_act &ext_pa_power_on + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-8 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_sus &ext_pa_power_off + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-9 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_act &ext_pa_power_off + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-10 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_sus &ext_pa_power_on + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-11 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_act &ext_pa_power_on + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-12 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_sus &ext_pa_power_off + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-13 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_act &ext_pa_power_off + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-14 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_sus &ext_pa_power_on + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-15 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_act &ext_pa_power_on + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + + /delete-property/ asoc-wsa-codec-names; + /delete-property/ asoc-wsa-codec-prefixes; + + /delete-property/ msm-vdd-wsa-switch-supply; + /delete-property/ qcom,cdc-us-euro-gpios; + /delete-property/ qcom,msm-vdd-wsa-switch-voltage; + /delete-property/ qcom,msm-vdd-wsa-switch-current; +}; + diff --git a/arch/arm/boot/dts/qcom/tissot/msm8953-camera-sensor-qrd-tissot.dtsi b/arch/arm/boot/dts/qcom/tissot/msm8953-camera-sensor-qrd-tissot.dtsi new file mode 100644 index 0000000000000..04f653353b01e --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/msm8953-camera-sensor-qrd-tissot.dtsi @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&cci { + actuator1: qcom,actuator@1 { + cell-index = <1>; + reg = <0x1>; + compatible = "qcom,actuator"; + qcom,cci-master = <1>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vaf"; + qcom,cam-vreg-min-voltage = <2850000>; + qcom,cam-vreg-max-voltage = <2850000>; + qcom,cam-vreg-op-mode = <80000>; + }; + + /delete-node/ qcom,eeprom@0; + + eeprom2: qcom,eeprom@2 { + cell-index = <2>; + reg = <0x2>; + compatible = "qcom,eeprom"; + qcom,cci-master = <1>; + + qcom,eeprom-name = "ofilm_s5k5e8"; + qcom,slave-addr = <0x5A>; + qcom,num-blocks = <8>; + + qcom,page0 = <1 0x0A02 2 0x4 1 0>; + qcom,pageen0 = <1 0x0A00 2 0x1 1 0>; + qcom,poll0 = <0 0x0 2 0 1 0>; + qcom,mem0 = <64 0x0A04 2 0 1 0>; + + qcom,page1 = <1 0x0A02 2 0x5 1 0>; + qcom,pageen1 = <1 0x0A00 2 0x1 1 0>; + qcom,poll1 = <0 0x0 2 0 1 0>; + qcom,mem1 = <64 0x0A04 2 0 1 0>; + + qcom,page2 = <1 0x0A02 2 0x6 1 0>; + qcom,pageen2 = <1 0x0A00 2 0x1 1 0>; + qcom,poll2 = <0 0x0 2 0 1 0>; + qcom,mem2 = <64 0x0A04 2 0 1 0>; + + qcom,page3 = <1 0x0A02 2 0x7 1 0>; + qcom,pageen3 = <1 0x0A00 2 0x1 1 0>; + qcom,poll3 = <0 0x0 2 0 1 0>; + qcom,mem3 = <64 0x0A04 2 0 1 0>; + + qcom,page4 = <1 0x0A02 2 0x8 1 0>; + qcom,pageen4 = <1 0x0A00 2 0x1 1 0>; + qcom,poll4 = <0 0x0 2 0 1 0>; + qcom,mem4 = <64 0x0A04 2 0 1 0>; + + qcom,page5 = <1 0x0A02 2 0x9 1 0>; + qcom,pageen5 = <1 0x0A00 2 0x1 1 0>; + qcom,poll5 = <0 0x0 2 0 1 0>; + qcom,mem5 = <64 0x0A04 2 0 1 0>; + + qcom,page6 = <1 0x0A02 2 0xA 1 0>; + qcom,pageen6 = <1 0x0A00 2 0x1 1 0>; + qcom,poll6 = <0 0x0 2 0 1 0>; + qcom,mem6 = <64 0x0A04 2 0 1 0>; + + qcom,page7 = <1 0x0A02 2 0xE 1 0>; + qcom,pageen7 = <1 0x0A00 2 0x1 1 0>; + qcom,poll7 = <0 0x0 2 0 1 0>; + qcom,mem7 = <2 0x0A04 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l23>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000>; + qcom,cam-vreg-op-mode = <105000 0 80000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front1_default>; + pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front1_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 129 0>; + qcom,gpio-reset = <1>; + qcom,gpio-req-tbl-num = <0 1>; + qcom,gpio-req-tbl-flags = <1 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "cam_vana", + "cam_vdig", "cam_vio", "sensor_cam_mclk", "sensor_gpio_reset"; + qcom,cam-power-seq-cfg-val = <0 1 1 1 24000000 1>; + qcom,cam-power-seq-delay = <1 0 0 0 10 1>; + + status = "ok"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + /delete-property/ qcom,sensor-mode; + /delete-property/ qcom,gpio-standby; + }; + + eeprom3: qcom,eeprom@3 { + cell-index = <3>; + reg = <0x3>; + compatible = "qcom,eeprom"; + qcom,cci-master = <1>; + + qcom,eeprom-name = "qtech_ov5675"; + qcom,slave-addr = <0x20>; + + qcom,num-blocks = <10>; + qcom,page0 = <1 0x0100 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0 1 1>; + qcom,mem0 = <0 0x0 2 0 1 0>; + + qcom,page1 = <1 0x5001 2 0x02 1 1>; + qcom,poll1 = <0 0x0 2 0 1 1>; + qcom,mem1 = <0 0x0 2 0 1 0>; + + qcom,page2 = <1 0x3d84 2 0xc0 1 1>; + qcom,poll2 = <0 0x0 2 0 1 1>; + qcom,mem2 = <0 0x0 2 0 1 0>; + + qcom,page3 = <1 0x3d88 2 0x70 1 1>; + qcom,poll3 = <0 0x0 2 0 1 1>; + qcom,mem3 = <0 0x0 2 0 1 0>; + + qcom,page4 = <1 0x3d89 2 0x10 1 1>; + qcom,poll4 = <0 0x0 2 0 1 1>; + qcom,mem4 = <0 0x0 2 0 1 0>; + + qcom,page5 = <1 0x3d8a 2 0x70 1 0>; + qcom,poll5 = <0 0x0 2 0 1 1>; + qcom,mem5 = <0 0x0 2 0 1 0>; + + qcom,page6 = <1 0x3d8b 2 0x29 1 10>; + qcom,poll6 = <0 0x0 2 0 1 1>; + qcom,mem6 = <0 0x0 2 0 1 0>; + + qcom,page7 = <1 0x3d81 2 0x01 1 10>; + qcom,poll7 = <0 0x0 2 0 1 1>; + qcom,mem7 = <0 0x0 2 0 1 0>; + + qcom,page8 = <0 0x0 2 0 1 0>; + qcom,poll8 = <0 0x0 2 0 1 1>; + qcom,mem8 = <40 0x7010 2 0 1 5>; + + qcom,page9 = <1 0x5001 2 0x03 1 5>; + qcom,pageen9 = <1 0x0100 2 0x00 1 5>; + qcom,poll9 = <0 0x0 2 0 1 1>; + qcom,mem9 = <0 0x0 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l23>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000>; + qcom,cam-vreg-op-mode = <105000 0 80000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front1_default>; + pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front1_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 129 0>; + qcom,gpio-reset = <1>; + qcom,gpio-req-tbl-num = <0 1>; + qcom,gpio-req-tbl-flags = <1 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "cam_vana", + "cam_vdig", "cam_vio", "sensor_cam_mclk", "sensor_gpio_reset"; + qcom,cam-power-seq-cfg-val = <0 1 1 1 24000000 1>; + qcom,cam-power-seq-delay = <1 0 0 0 10 1>; + + status = "ok"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom6: qcom,eeprom@6 { + cell-index = <6>; + qcom,eeprom-name = "arc_ov12a10"; + compatible = "qcom,eeprom"; + qcom,slave-addr = <0xb0>; + qcom,cci-master = <0>; + reg = <0x6>; + qcom,num-blocks = <1>; + qcom,page0 = <0 0x0 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0x0 1 0>; + qcom,mem0 = <7015 0x0 2 0x0 1 0>; + + cam_vio-supply = <&pm8953_l6>; + cam_vdig-supply = <&pm8953_l2>; + cam_vaf-supply = <&pm8953_l17>; + cam_vana-supply = <&pm8953_l22>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf", + "cam_vana"; + qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>; + qcom,cam-vreg-max-voltage = <0 1200000 2850000 2800000>; + qcom,cam-vreg-op-mode = <0 105000 100000 80000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default + &cam_sensor_rear_vana>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep + &cam_sensor_rear_vana_sleep>; + gpios = <&tlmm 26 0>, + <&tlmm 33 0>, + <&tlmm 62 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vana = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VANA"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio", "cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 0 10 1 1>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom7: qcom,eeprom@7 { + cell-index = <7>; + qcom,eeprom-name = "arc_ov13880"; + compatible = "qcom,eeprom"; + qcom,slave-addr = <0xa0>; + qcom,cci-master = <1>; + reg = <0x7>; + qcom,num-blocks = <1>; + qcom,page0 = <0 0x0 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0x0 1 0>; + qcom,mem0 = <7015 0x0 2 0x0 1 0>; + cam_vdig-supply = <&pm8953_l2>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", + "cam_vaf"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-op-mode = <200000 0 80000 100000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_default + &cam_sensor_front_default>; + pinctrl-1 = <&cam_sensor_mclk2_sleep + &cam_sensor_front_sleep>; + gpios = <&tlmm 28 0>, + <&tlmm 41 0>; + qcom,gpio-reset = <1>; + qcom,gpio-req-tbl-num = <0 1>; + qcom,gpio-req-tbl-flags = <1 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio", "cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 0 10 1 1>; + status = "ok"; + clocks = <&clock_gcc clk_mclk2_clk_src>, + <&clock_gcc clk_gcc_camss_mclk2_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom8: qcom,eeprom@8 { + cell-index = <8>; + qcom,eeprom-name = "arc_ofilm_ov12a10"; + compatible = "qcom,eeprom"; + qcom,slave-addr = <0xb0>; + qcom,cci-master = <0>; + reg = <0x8>; + qcom,num-blocks = <1>; + qcom,page0 = <0 0x0 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0x0 1 0>; + qcom,mem0 = <7015 0x0 2 0x0 1 0>; + + cam_vio-supply = <&pm8953_l6>; + cam_vdig-supply = <&pm8953_l2>; + cam_vaf-supply = <&pm8953_l17>; + cam_vana-supply = <&pm8953_l22>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf", + "cam_vana"; + qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>; + qcom,cam-vreg-max-voltage = <0 1200000 2850000 2800000>; + qcom,cam-vreg-op-mode = <0 105000 100000 80000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default + &cam_sensor_rear_vana>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep + &cam_sensor_rear_vana_sleep>; + gpios = <&tlmm 26 0>, + <&tlmm 33 0>, + <&tlmm 62 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vana = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VANA"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio", "cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 0 10 1 1>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom9: qcom,eeprom@9 { + cell-index = <9>; + qcom,eeprom-name = "arc_ofilm_ov13880"; + compatible = "qcom,eeprom"; + qcom,slave-addr = <0xa0>; + qcom,cci-master = <1>; + reg = <0x9>; + qcom,num-blocks = <1>; + qcom,page0 = <0 0x0 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0x0 1 0>; + qcom,mem0 = <7015 0x0 2 0x0 1 0>; + cam_vdig-supply = <&pm8953_l2>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", + "cam_vaf"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>; + qcom,cam-vreg-op-mode = <200000 0 80000 100000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_default + &cam_sensor_front_default>; + pinctrl-1 = <&cam_sensor_mclk2_sleep + &cam_sensor_front_sleep>; + gpios = <&tlmm 28 0>, + <&tlmm 41 0>; + qcom,gpio-reset = <1>; + qcom,gpio-req-tbl-num = <0 1>; + qcom,gpio-req-tbl-flags = <1 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio", "cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 0 10 1 1>; + status = "ok"; + clocks = <&clock_gcc clk_mclk2_clk_src>, + <&clock_gcc clk_gcc_camss_mclk2_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + qcom,camera@0 { + qcom,eeprom-src = <&eeprom6 &eeprom8>; + qcom,actuator-src = <&actuator0>; + cam_vdig-supply = <&pm8953_l2>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf", + "cam_vana"; + qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>; + qcom,cam-vreg-max-voltage = <0 1200000 2850000 2800000>; + qcom,cam-vreg-op-mode = <0 105000 100000 80000>; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default + &cam_sensor_rear_vana>; + pinctrl-1 = <&cam_sensor_mclk0_sleep + &cam_sensor_rear_sleep + &cam_sensor_rear_vana_sleep>; + gpios = <&tlmm 26 0>, + <&tlmm 33 0>, + <&tlmm 62 0>; + /delete-property/ qcom,gpio-standby; + qcom,gpio-vana = <2>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VANA"; + }; + + qcom,camera@1 { + qcom,led-flash-src = <&led_flash0>; + qcom,eeprom-src = <&eeprom7 &eeprom9>; + qcom,actuator-src = <&actuator1>; + cam_vdig-supply = <&pm8953_l2>; + gpios = <&tlmm 28 0>, + <&tlmm 41 0>; + qcom,gpio-req-tbl-num = <0 1>; + qcom,gpio-req-tbl-flags = <1 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1"; + qcom,sensor-position = <0>; + qcom,cci-master = <1>; + status = "ok"; + clocks = <&clock_gcc clk_mclk2_clk_src>, + <&clock_gcc clk_gcc_camss_mclk2_clk>; + /delete-property/ qcom,gpio-standby; + }; + + qcom,camera@2 { + qcom,eeprom-src = <&eeprom2 &eeprom3>; + cam_vana-supply = <&pm8953_l22>; + gpios = <&tlmm 27 0>, + <&tlmm 129 0>; + /delete-property/ qcom,gpio-standby; + qcom,gpio-req-tbl-num = <0 1>; + qcom,gpio-req-tbl-flags = <1 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2"; + }; +}; diff --git a/arch/arm/boot/dts/qcom/tissot/msm8953-pinctrl-tissot.dtsi b/arch/arm/boot/dts/qcom/tissot/msm8953-pinctrl-tissot.dtsi new file mode 100644 index 0000000000000..7075113adde48 --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/msm8953-pinctrl-tissot.dtsi @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + tlmm: pinctrl@1000000 { + cam_sensor_rear_default: cam_sensor_rear_default { + /* RESET, STANDBY */ + mux { + pins = "gpio33", "gpio39"; + }; + + config { + pins = "gpio33","gpio39"; + }; + }; + + cam_sensor_rear_sleep: cam_sensor_rear_sleep { + /* RESET, STANDBY */ + mux { + pins = "gpio33","gpio39"; + }; + + config { + pins = "gpio33","gpio39"; + }; + }; + + /delete-node/ cam_sensor_ir_cut_default; + /delete-node/ cam_sensor_ir_cut_sleep; + /delete-node/ cam_sensor_rear_default1; + /delete-node/ cam_sensor_rear_sleep1; + + cam_sensor_rear_vana: cam_sensor_rear_vdig { + /* VDIG */ + mux { + pins = "gpio62"; + }; + + config { + pins = "gpio62"; + }; + }; + + cam_sensor_rear_vana_sleep: cam_sensor_rear_vdig_sleep { + /* VDIG */ + mux { + pins = "gpio62"; + }; + + config { + pins = "gpio62"; + }; + }; + + /delete-node/ cam_sensor_rear_vdig1; + /delete-node/ cam_sensor_rear_vdig_sleep1; + + cam_sensor_front_default: cam_sensor_front_default { + /* RESET, STANDBY */ + mux { + pins = "gpio41","gpio132"; + }; + + config { + pins = "gpio41","gpio132"; + }; + }; + + cam_sensor_front_sleep: cam_sensor_front_sleep { + /* RESET, STANDBY */ + mux { + pins = "gpio41","gpio132"; + }; + + config { + pins = "gpio41","gpio132"; + }; + }; + + cam_sensor_front1_default: cam_sensor_front1_default { + /* RESET, STANDBY */ + mux { + pins = "gpio129"; + }; + + config { + pins = "gpio129"; + }; + }; + + cam_sensor_front1_sleep: cam_sensor_front1_sleep { + /* RESET, STANDBY */ + mux { + pins = "gpio129"; + }; + + config { + pins = "gpio129"; + }; + }; + + goodix_spi_active: goodix_spi_active{ + mux { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + function = "blsp_spi5"; + }; + config { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; + goodix_reset_reset: goodix_reset_reset{ + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable = <0>; + output-low; + }; + }; + goodix_reset_active: goodix_reset_active{ + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable = <0>; + output-high; + }; + }; + goodix_irq_active: goodix_irq_active { + mux { + pins = "gpio48"; + function = "gpio"; + }; + config { + pins = "gpio48"; + drive-strength = <2>; + bias-disable = <0>; + input-enable; + }; + }; + + fpc_spi_active: fpc_spi_active { + mux { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + function = "blsp_spi7"; + }; + + config { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + drive-strength = <2>; + bias-disable; + }; + }; + fpc_reset_reset: fpc_reset_reset { + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable; + output-low; + }; + }; + fpc_reset_active: fpc_reset_active { + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + fpc_irq_active: fpc_irq_active { + mux { + pins = "gpio48"; + function = "gpio"; + }; + config { + pins = "gpio48"; + drive-strength = <2>; + bias-disable; + input-enable; + }; + }; + + cdc_ext_pa_gpio_ctrl { + ext_pa_power_off:ext_pa_power_off{ + mux { + pins = "gpio141"; + function = "gpio"; + }; + config { + pins = "gpio141"; + drive-strength = <16>; + bias-disable; + output-low; + }; + }; + ext_pa_power_on:ext_pa_power_on{ + mux { + pins = "gpio141"; + function = "gpio"; + }; + config { + pins = "gpio141"; + drive-strength = <16>; + bias-pull-down; + output-high; + }; + }; + }; + + pri-tlmm-lines { + pri_tlmm_lines_act: pri_tlmm_lines_act { + mux { + pins = "gpio88", "gpio91", "gpio93"; + }; + + config { + pins = "gpio88", "gpio91", "gpio93"; + }; + }; + + pri_tlmm_lines_sus: pri_tlmm_lines_sus { + mux { + pins = "gpio88", "gpio91", "gpio93"; + }; + + config { + pins = "gpio88", "gpio91", "gpio93"; + }; + }; + }; + + spi6 { + spi6_default: spi6_default { + /* active state */ + mux { + /* MOSI, MISO, CLK */ + pins = "gpio20", "gpio21", "gpio23"; + function = "blsp_spi6"; + }; + + config { + pins = "gpio20", "gpio21", "gpio23"; + drive-strength = <12>; /* 12 MA */ + bias-disable = <0>; /* No PULL */ + }; + }; + + spi6_sleep: spi6_sleep { + /* suspended state */ + mux { + /* MOSI, MISO, CLK */ + pins = "gpio20", "gpio21", "gpio23"; + function = "gpio"; + }; + + config { + pins = "gpio20", "gpio21", "gpio23"; + drive-strength = <2>; /* 2 MA */ + bias-pull-down; /* PULL Down */ + }; + }; + + spi6_cs0_active: cs0_active { + /* CS */ + mux { + pins = "gpio22"; + function = "blsp_spi6"; + }; + + config { + pins = "gpio22"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; + + spi6_cs0_sleep: cs0_sleep { + /* CS */ + mux { + pins = "gpio22"; + function = "gpio"; + }; + + config { + pins = "gpio22"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; + }; + + pmx_ts_int_suspend { + synaptic_int_suspend: synaptic_int_suspend { + mux { + pins = "gpio65"; + function = "gpio"; + }; + + config { + pins = "gpio65"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + pmx_ts_reset_active { + synaptic_reset_suspend: synaptic_reset_suspend { + mux { + pins = "gpio64"; + function = "gpio"; + }; + + config { + pins = "gpio64"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom/tissot/msm8953-pm-tissot.dtsi b/arch/arm/boot/dts/qcom/tissot/msm8953-pm-tissot.dtsi new file mode 100644 index 0000000000000..d103f8cc1aef7 --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/msm8953-pm-tissot.dtsi @@ -0,0 +1,144 @@ +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +&soc { + qcom,mpm@601d4 { + qcom,gic-map = <2 216>, /* tsens_upper_lower_int */ + <58 168>, /* qusb2phy_dmse_hv -> hs_phy_irq*/ + <49 168>, /* qusb2phy_dpse_hv -> hs_phy_irq*/ + <37 252>, /* qmp_usb3_lfps_rxterm_irq -> ss_phy_irq */ + <53 104>, /* mdss_irq */ + <88 222>, /* ee0_krait_hlos_spmi_periph_irq */ + <0xff 18>, /* APC_qgicQTmrSecPhysIrptReq */ + <0xff 19>, /* APC_qgicQTmrNonSecPhysIrptReq */ + <0xff 20>, /* qgicQTmrVirtIrptReq */ + <0xff 23>, /* apss_hm */ + <0xff 35>, /* WDT_barkInt */ + <0xff 39>, /* arch_mem_timer */ + <0xff 40>, /* qtmr_phy_irq[0] */ + <0xff 47>, /* rbif_irq[0] */ + <0xff 54>, /* gladiator-error */ + <0xff 56>, /* q6_wdog_expired_irq */ + <0xff 57>, /* mss_to_apps_irq(0) */ + <0xff 58>, /* mss_to_apps_irq(1) */ + <0xff 59>, /* mss_to_apps_irq(2) */ + <0xff 60>, /* mss_to_apps_irq(3) */ + <0xff 61>, /* mss_a2_bam_irq */ + <0xff 65>, /* o_gc_sys_irq[0] */ + <0xff 69>, /* vbif_irpt */ + <0xff 73>, /* app_tcu_gbl_flt_irpt_ns */ + <0xff 74>, /* smmu_bus_intr[2] */ + <0xff 75>, /* smmu_bus_intr[3] */ + <0xff 78>, /* smmu_bus_intr[5] */ + <0xff 79>, /* smmu_bus_intr[6] */ + <0xff 85>, /* smmu_bus_intr[31] */ + <0xff 86>, /* smmu_bus_intr[32] */ + <0xff 90>, /* smmu_bus_intr[33] */ + <0xff 92>, /* smmu_bus_intr[34] */ + <0xff 93>, /* smmu_bus_intr[35] */ + <0xff 97>, /* smmu_bus_intr[10] */ + <0xff 102>, /* smmu_bus_intr[14] */ + <0xff 108>, /* smmu_bus_intr[36] */ + <0xff 109>, /* smmu_bus_intr[37] */ + <0xff 112>, /* smmu_bus_intr[38] */ + <0xff 114>, /* qdsd_intr_out */ + <0xff 126>, /* app_tcu_cxt_irpt_vec[11] */ + <0xff 128>, /* blsp1_peripheral_irq[3] */ + <0xff 131>, /* qup_irq */ + <0xff 136>, /* app_tcu_cxt_irpt_vec[15] */ + <0xff 137>, /* app_tcu_cxt_irpt_vec[16] */ + <0xff 138>, /* app_tcu_cxt_irpt_vec[17] */ + <0xff 139>, /* uart_dm_intr */ + <0xff 140>, /* uart_dm_intr */ + <0xff 141>, /* app_tcu_cxt_irpt_vec[18] */ + <0xff 142>, /* smmu_bus_intr[47] */ + <0xff 143>, /* smmu_bus_intr[48] */ + <0xff 144>, /* smmu_bus_intr[49] */ + <0xff 145>, /* smmu_bus_intr[50] */ + <0xff 146>, /* smmu_bus_intr[51] */ + <0xff 147>, /* smmu_bus_intr[52] */ + <0xff 148>, /* smmu_bus_intr[53] */ + <0xff 149>, /* smmu_bus_intr[54] */ + <0xff 150>, /* smmu_bus_intr[55] */ + <0xff 151>, /* smmu_bus_intr[56] */ + <0xff 152>, /* smmu_bus_intr[57] */ + <0xff 153>, /* smmu_bus_intr[58] */ + <0xff 155>, /* sdc1_irq(0) */ + <0xff 157>, /* sdc2_irq(0) */ + <0xff 166>, /* usb30_pwr_evnt_irq */ + <0xff 167>, /* usb30_bam_irq[0] */ + <0xff 170>, /* sdc1_pwr_cmd_irq */ + <0xff 172>, /* usb30_ctrl_irq[0] */ + <0xff 173>, /* o_wcss_apss_smd_hi */ + <0xff 174>, /* o_wcss_apss_smd_med */ + <0xff 175>, /* o_wcss_apss_smd_low */ + <0xff 176>, /* o_wcss_apss_smsm_irq */ + <0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */ + <0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */ + <0xff 179>, /* o_wcss_apss_asic_intr */ + <0xff 181>, /* o_wcss_apss_wdog_bite_and_reset_rdy */ + <0xff 188>, /* lpass_irq_out_apcs(0) */ + <0xff 189>, /* lpass_irq_out_apcs(1) */ + <0xff 190>, /* lpass_irq_out_apcs(2) */ + <0xff 191>, /* lpass_irq_out_apcs(3) */ + <0xff 192>, /* lpass_irq_out_apcs(4) */ + <0xff 193>, /* lpass_irq_out_apcs(5) */ + <0xff 194>, /* lpass_irq_out_apcs(6) */ + <0xff 195>, /* lpass_irq_out_apcs(7) */ + <0xff 196>, /* lpass_irq_out_apcs(8) */ + <0xff 197>, /* lpass_irq_out_apcs(9) */ + <0xff 198>, /* coresight-tmc-etr interrupt */ + <0xff 200>, /* rpm_ipc(4) */ + <0xff 201>, /* rpm_ipc(5) */ + <0xff 202>, /* rpm_ipc(6) */ + <0xff 203>, /* rpm_ipc(7) */ + <0xff 204>, /* rpm_ipc(24) */ + <0xff 205>, /* rpm_ipc(25) */ + <0xff 206>, /* rpm_ipc(26) */ + <0xff 207>, /* rpm_ipc(27) */ + <0xff 212>, /* lpass_slimbus_bam_ee1_irq */ + <0xff 215>, /* o_bimc_intr[0] */ + <0xff 224>, /* spdm_realtime_irq[1] */ + <0xff 231>, /* arm-smmu global fault */ + <0xff 239>, /* crypto_bam_irq[1]*/ + <0xff 240>, /* summary_irq_kpss */ + <0xff 253>, /* sdc2_pwr_cmd_irq */ + <0xff 257>, /* osmmu_Cirpt[0] */ + <0xff 260>, /* ipa_irq[0] */ + <0xff 262>, /* ipa_bam_irq[0] */ + <0xff 263>, /* ipa_bam_irq[2] */ + <0xff 264>, /* arm-smmu context fault */ + <0xff 269>, /* rpm_wdog_expired_irq */ + <0xff 270>, /* blsp1_bam_irq[0] */ + <0xff 271>, /* blsp1_bam_irq[0] */ /* added by xiaomi */ + <0xff 273>, /* smmu_bus_intr[18] */ + <0xff 274>, /* smmu_bus_intr[19] */ + <0xff 275>, /* rpm_ipc(30) */ + <0xff 276>, /* rpm_ipc(31) */ + <0xff 285>, /* app_tcu_cxt_irpt_vec[0] */ + <0xff 286>, /* app_tcu_cxt_irpt_vec[1] */ + <0xff 287>, /* app_tcu_cxt_irpt_vec[2] */ + <0xff 305>, /* L2_EXTERRIRQ_C0 */ + <0xff 306>, /* L2_EXTERRIRQ_C1 */ + <0xff 307>, /* L2_INTERRIRQ_C0 */ + <0xff 308>, /* L2_INTERRIRQ_C1 */ + <0xff 314>, /* CCISAW_svicInt */ + <0xff 321>, /* q6ss_irq_out(4) */ + <0xff 322>, /* q6ss_irq_out(5) */ + <0xff 323>, /* q6ss_irq_out(6) */ + <0xff 325>, /* q6ss_wdog_exp_irq */ + <0xff 344>, /* sdcc_ice_nonsec_level_irq */ + <0xff 346>; /* tsens_critical_int */ + }; +}; diff --git a/arch/arm/boot/dts/qcom/tissot/msm8953-qrd-sku3-tissot-overlay.dtsi b/arch/arm/boot/dts/qcom/tissot/msm8953-qrd-sku3-tissot-overlay.dtsi new file mode 100644 index 0000000000000..cd607df677e68 --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/msm8953-qrd-sku3-tissot-overlay.dtsi @@ -0,0 +1,14 @@ +#include "msm-audio-tissot.dtsi" +#include "msm-pm8953-tissot.dtsi" +#include "msm-pmi8950-tissot.dtsi" +#include "msm8953-pinctrl-tissot.dtsi" +#include "msm8953-audio-tissot.dtsi" +#include "msm8953-camera-sensor-qrd-tissot.dtsi" +#include "dsi-panel-otm1911-fhd-video.dtsi" +#include "dsi-panel-ft8716-fhd-video.dtsi" +#include "dsi-panel-ili7807-fhd-video.dtsi" +#include "msm8953-pm-tissot.dtsi" +#include "msm8953-qrd-sku3-tissot.dtsi" +#include "msm8953-tissot.dtsi" +#include "msm8953-qrd-tissot.dtsi" +#include "msm8953-regulator-tissot.dtsi" diff --git a/arch/arm/boot/dts/qcom/tissot/msm8953-qrd-sku3-tissot.dtsi b/arch/arm/boot/dts/qcom/tissot/msm8953-qrd-sku3-tissot.dtsi new file mode 100644 index 0000000000000..25f3021c3dc64 --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/msm8953-qrd-sku3-tissot.dtsi @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_dsi0 { + qcom,dsi-pref-prim-pan = <&dsi_otm1911_fhd_vid>; +}; + +&int_codec { + status = "ok"; +}; + +&pm8953_diangu_dig { + status = "ok"; +}; + +&pm8953_diangu_analog { + status = "ok"; +}; + +&ext_codec { + status = "disable"; +}; + +&slim_msm { + status = "disable"; +}; + +&dai_slim { + status = "disable"; +}; + +&wcd9xxx_intc { + status = "disable"; +}; + +&clock_audio { + status = "disable"; +}; + +&wcd9335 { + status = "disable"; +}; + +&wcd_rst_gpio { + status = "disable"; +}; diff --git a/arch/arm/boot/dts/qcom/tissot/msm8953-qrd-tissot.dtsi b/arch/arm/boot/dts/qcom/tissot/msm8953-qrd-tissot.dtsi new file mode 100644 index 0000000000000..306dc2811fd2a --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/msm8953-qrd-tissot.dtsi @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +&soc { + goodix_fp { + compatible = "goodix,fingerprint"; + spi-max-frequency = <1000000>; + input-device-name = "gf3208"; + interrupt-parent = <&tlmm>; + interrupts = <9 0x0>; + + goodix,gpio_reset = <&tlmm 140 0>; + goodix,gpio_irq = <&tlmm 48 0>; + + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup1_spi_apps_clk>; + + pinctrl-names = "goodixfp_spi_active", + "goodixfp_reset_reset", + "goodixfp_reset_active", + "goodixfp_irq_active"; + + pinctrl-0 = <&goodix_spi_active>; + pinctrl-1 = <&goodix_reset_reset>; + pinctrl-2 = <&goodix_reset_active>; + pinctrl-3 = <&goodix_irq_active>; + }; + fpc1020 { + compatible = "fpc,fpc1020"; + spi-max-frequency = <1000000>; + input-device-name = "fpc1020"; + interrupt-parent = <&tlmm>; + interrupts = <9 0x0>; + + fpc,gpio_rst = <&tlmm 140 0>; + fpc,gpio_irq = <&tlmm 48 0>; + + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup1_spi_apps_clk>; + + pinctrl-names = "fpc1020_spi_active", + "fpc1020_reset_reset", + "fpc1020_reset_active", + "fpc1020_irq_active"; + + pinctrl-0 = <&fpc_spi_active>; + pinctrl-1 = <&fpc_reset_reset>; + pinctrl-2 = <&fpc_reset_active>; + pinctrl-3 = <&fpc_irq_active>; + }; + + i2c@78b7000 { /* BLSP1 QUP3 */ + /delete-node/ synaptics@4b; + focaltech@38 { + compatible = "focaltech,5435"; + reg = <0x38>; + interrupt-parent = <&tlmm>; + interrupts = <65 0x2>; + vdd-supply = <&pm8953_l10>; + vcc_i2c-supply = <&pm8953_l6>; + /* pins used by touchscreen */ + pinctrl-names = "pmx_ts_active","pmx_ts_suspend", + "pmx_ts_release"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + pinctrl-2 = <&ts_release>; + focaltech,name = "ft5435"; + focaltech,family-id = <0x54>; + focaltech,reset-gpio = <&tlmm 64 0x0>; + focaltech,irq-gpio = <&tlmm 65 0x2008>; + focaltech,display-coords = <0 0 1080 1920>; + focaltech,panel-coords = <0 0 1080 1920>; + focaltech,no-force-update; + focaltech,i2c-pull-up; + focaltech,group-id = <1>; + focaltech,hard-reset-delay-ms = <200>; + focaltech,soft-reset-delay-ms = <200>; + focaltech,num-max-touches = <10>; + focaltech,fw-delay-aa-ms = <2>; + focaltech,fw-delay-55-ms = <2>; + focaltech,fw-upgrade-id1 = <0x54>; + focaltech,fw-upgrade-id2 = <0x2c>; + focaltech,fw-delay-readid-ms = <10>; + focaltech,fw-delay-era-flsh-ms = <2000>; + focaltech,fw-auto-cal; + focaltech,fw-vkey-support; + focaltech,resume-in-workqueue; + focaltech,num-virtual-key = <3>; + focal,virtual_key_1 = <172 500 2040>;/*home*/ + focal,virtual_key_2 = <139 200 2040>;/*menu*/ + focal,virtual_key_3 = <158 800 2040>;/*back*/ + }; + focaltech@40{ + compatible = "focaltech,fts"; + reg = <0x40>; + interrupt-parent = <&tlmm>; + interrupts = <65 0x02>; + focaltech,reset-gpio = <&tlmm 64 0x0>; + focaltech,irq-gpio = <&tlmm 65 0x0>; + focaltech,max-touch-number = <10>; + focaltech,display-coords = <0 0 1080 1920>; + + focaltech,have-key; + focaltech,key-number = <3>; + focaltech,keys = <139 172 158>; + focaltech,key-y-coord = <2034>; + focaltech,key-x-coords = <900 540 180>; + }; + synaptics_dsx@20 { + compatible = "synaptics,dsx-i2c"; + reg = <0x20>; + interrupt-parent = <&tlmm>; + interrupts = <65 0x2>; + vdd-supply = <&pm8953_l10>; + avdd-supply = <&pm8953_l6>; + pinctrl-names = "pmx_ts_active", "pmx_ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&synaptic_int_suspend &synaptic_reset_suspend>; + synaptics,pwr-reg-name = "avdd"; + synaptics,bus-reg-name = "vdd"; + synaptics,ub-i2c-addr = <0x2c>; + synaptics,irq-gpio = <&tlmm 65 0x2008>; /* IRQF_ONESHOT | IRQF_TRIGGER_LOW */ + synaptics,rst-gpio = <&tlmm 64 0x0>; + synaptics,irq-on-state = <0>; + synaptics,power-delay-ms = <200>; + synaptics,reset-delay-ms = <200>; + synaptics,reset-on-state = <0>; + synaptics,reset-active-ms = <20>; + synaptics,cap-button-codes = <139 172 158>; + }; + }; + + i2c@78b6000 { /* BLSP1 QUP3 */ + aw2013@45 { + compatible = "awinic,aw2013"; + reg = <0x45>; + vdd-supply = <&pm8953_l10>; + vcc-supply = <&pm8953_l5>; + + aw2013,red { + aw2013,name = "red"; + aw2013,id = <0>; + aw2013,max-brightness = <150>; + aw2013,max-current = <1>; + aw2013,rise-time-ms = <3>; + aw2013,hold-time-ms = <1>; + aw2013,fall-time-ms = <3>; + aw2013,off-time-ms = <3>; + }; + aw2013,green { + aw2013,name = "green"; + aw2013,id = <1>; + aw2013,max-brightness = <150>; + aw2013,max-current = <1>; + aw2013,rise-time-ms = <3>; + aw2013,hold-time-ms = <1>; + aw2013,fall-time-ms = <3>; + aw2013,off-time-ms = <3>; + }; + aw2013,blue { + aw2013,name = "blue"; + aw2013,id = <2>; + aw2013,max-brightness = <150>; + aw2013,max-current = <1>; + aw2013,rise-time-ms = <3>; + aw2013,hold-time-ms = <1>; + aw2013,fall-time-ms = <3>; + aw2013,off-time-ms = <3>; + }; + }; + }; +}; + +&spi_6 { + status = "ok"; + peel_ir@0 { + compatible = "peel_ir"; + reg = <0x0>; + spi-max-frequency = <19200000>; + vdd-supply = <&pm8953_l8>; + peel_ir,reg-id = "vdd"; + peel_ir,lr-gpio = <73>; + peel_ir,lr-gpio-valid = <0>; + peel_ir,spi-bpw = <32>; + peel_ir,spi-clk-speed = <960000>; + peel_ir,spi-mode = <0>; + peel_ir,peel-field = <2345>; + status = "ok"; + }; +}; + +&spmi_bus { + qcom,pm8953@0 { + qcom,leds@a100 { + status = "okay"; + compatible = "qcom,leds-qpnp"; + reg = <0xa100 0x100>; + label = "mpp"; + qcom,led_mpp_2 { + label = "mpp"; + linux,name = "button-backlight"; + linux,default-trigger = "none"; + qcom,default-state = "off"; + qcom,max-current = <10>; + qcom,current-setting = <5>; + qcom,id = <6>; + qcom,mode = "manual"; + qcom,source-sel = <1>; + qcom,mode-ctrl = <0x61>; + }; + }; + }; + + qcom,pmi8950@2 { + qcom,leds@a100 { + compatible = "qcom,leds-qpnp"; + reg = <0xa100 0x100>; + label = "mpp"; + status = "disable"; + /delete-node/ qcom,led_mpp_2; + }; + }; +}; + +/ { + qrd_batterydata: qcom,battery-data { + qcom,batt-id-range-pct = <20>; + /delete-node/ qcom,qrd_msm8937_sku1_2920mah; + #include "batterydata-qrd-coslight-3000mAh.dtsi" + #include "batterydata-qrd-scud-3000mAh.dtsi" + #include "batterydata-qrd-sunwoda-liwei-3000mAh.dtsi" + }; +}; + + +&pmi8950_charger { + /delete-property/ qcom,chg-led-sw-controls; + /delete-property/ qcom,chg-led-support; + /delete-property/ qcom,external-typec; + /delete-property/ qcom,typec-psy-name; + qcom,thermal-mitigation = <3000 2500 2000 1000 1000 500 0>; +}; + +&pmi8950_fg { + qcom,thermal-coefficients = [c8 86 c1 50 d3 37]; + qcom,cold-bat-decidegc = <0>; + qcom,cool-bat-decidegc = <150>; + qcom,warm-bat-decidegc = <450>; +}; + +&sdhc_2 { + cd-gpios = <&tlmm 133 0x0>; +}; + +&flash_led { + pmi8950_flash1: qcom,flash_1 { + label = "flash"; + qcom,led-name = "led:flash_1"; + qcom,default-led-trigger = + "flash1_trigger"; + qcom,max-current = <1000>; + qcom,duration = <1280>; + qcom,id = <1>; + qcom,current = <625>; + }; + pmi8950_torch1: qcom,torch_1 { + label = "torch"; + qcom,led-name = "led:torch_1"; + qcom,default-led-trigger = + "torch1_trigger"; + qcom,max-current = <200>; + qcom,id = <1>; + qcom,current = <120>; + }; +}; + +&led_flash0{ + qcom,flash-source = <&pmi8950_flash0 &pmi8950_flash1>; + qcom,torch-source = <&pmi8950_torch0 &pmi8950_torch1>; +}; + diff --git a/arch/arm/boot/dts/qcom/tissot/msm8953-regulator-tissot.dtsi b/arch/arm/boot/dts/qcom/tissot/msm8953-regulator-tissot.dtsi new file mode 100644 index 0000000000000..764b90bdfc0c4 --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/msm8953-regulator-tissot.dtsi @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +&rpm_bus { + rpm-regulator-ldoa1 { + pm8953_l1: regulator-l1 { + regulator-max-microvolt = <1000000>; + }; + }; + + rpm-regulator-ldoa2 { + pm8953_l2: regulator-l2 { + regulator-min-microvolt = <1200000>; + qcom,init-voltage = <1200000>; + }; + }; + + rpm-regulator-ldoa17 { + pm8953_l17: regulator-l17 { + regulator-min-microvolt = <2750000>; + qcom,init-voltage = <2800000>; + }; + }; + + rpm-regulator-ldoa22 { + pm8953_l22: regulator-l22 { + regulator-max-microvolt = <2800000>; + }; + }; + + rpm-regulator-ldoa23 { + pm8953_l23: regulator-l23 { + regulator-min-microvolt = <1200000>; + qcom,init-voltage = <120000>; + }; + }; +}; + diff --git a/arch/arm/boot/dts/qcom/tissot/msm8953-tissot.dtsi b/arch/arm/boot/dts/qcom/tissot/msm8953-tissot.dtsi new file mode 100644 index 0000000000000..905fc9b332bb7 --- /dev/null +++ b/arch/arm/boot/dts/qcom/tissot/msm8953-tissot.dtsi @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +/ { + firmware: firmware { + android { + fstab { + vendor { + status = "disable"; + }; + system { + fsmgr_flags = "wait,slotselect"; + status = "disable"; + }; + + }; + }; + }; + + reserved-memory { + other_ext_mem: other_ext_region@0 { + reg = <0x0 0x84A00000 0x0 0x1E00000>; + }; + + adsp_fw_mem: adsp_fw_region@0 { + reg = <0x0 0x8d600000 0x0 0x1200000>; + }; + + wcnss_fw_mem: wcnss_fw_region@0 { + reg = <0x0 0x8e800000 0x0 0x700000>; + }; + + pstore_reserve_mem: pstore_reserve_mem_region@0 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x9ff00000 0x0 0x00100000>; + }; + }; + + aliases { + spi6 = &spi_6; + }; + + +}; + + +&soc { + spi_6: spi@7af6000 { /* BLSP2 QUP2 */ + compatible = "qcom,spi-qup-v2"; + #address-cells = <1>; + #size-cells = <0>; + reg-names = "spi_physical", "spi_bam_physical"; + reg = <0x7af6000 0x600>, + <0x7ac4000 0x1f000>; + interrupt-names = "spi_irq", "spi_bam_irq"; + interrupts = <0 300 0>, <0 239 0>; + spi-max-frequency = <50000000>; + pinctrl-names = "spi_default", "spi_sleep"; + pinctrl-0 = <&spi6_default &spi6_cs0_active>; + pinctrl-1 = <&spi6_sleep &spi6_cs0_sleep>; + clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>, + <&clock_gcc clk_gcc_blsp2_qup2_spi_apps_clk>; + clock-names = "iface_clk", "core_clk"; + qcom,infinite-mode = <0>; + qcom,use-bam; + qcom,use-pinctrl; + qcom,ver-reg-exists; + qcom,bam-consumer-pipe-index = <6>; + qcom,bam-producer-pipe-index = <7>; + qcom,master-id = <84>; + }; + + sn_fuse: snfuse@0xa4128 { + compatible = "qcom,sn-fuse"; + reg = <0xa4128 0x4>; + reg-names = "sn-base"; + }; + + /delete-node/ qseecom@85b00000; + + qcom_seecom: qseecom@84A00000 { + compatible = "qcom,qseecom"; + reg = <0x84A00000 0x1900000>; + reg-names = "secapp-region"; + qcom,hlos-num-ce-hw-instances = <1>; + qcom,hlos-ce-hw-instance = <0>; + qcom,qsee-ce-hw-instance = <0>; + qcom,disk-encrypt-pipe-pair = <2>; + qcom,support-fde; + qcom,msm-bus,name = "qseecom-noc"; + qcom,msm-bus,num-cases = <4>; + qcom,msm-bus,num-paths = <1>; + qcom,support-bus-scaling; + qcom,msm-bus,vectors-KBps = + <55 512 0 0>, + <55 512 0 0>, + <55 512 120000 1200000>, + <55 512 393600 3936000>; + clocks = <&clock_gcc clk_crypto_clk_src>, + <&clock_gcc clk_gcc_crypto_clk>, + <&clock_gcc clk_gcc_crypto_ahb_clk>, + <&clock_gcc clk_gcc_crypto_axi_clk>; + clock-names = "core_clk_src", "core_clk", + "iface_clk", "bus_clk"; + qcom,ce-opp-freq = <100000000>; + }; + + usb3: ssusb@7000000{ + qcom,detect-dpdm-floating; + }; + +}; + From b0ebebfb805b858c8126375a91c78bc7dcc0cd3b Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Tue, 2 Jan 2018 14:36:58 +0530 Subject: [PATCH 197/508] drivers: video: mdss: Import mido changes --- drivers/video/msm/mdss/mdss_dsi.c | 70 ++++++++++++++++++++++++ drivers/video/msm/mdss/mdss_dsi.h | 6 ++ drivers/video/msm/mdss/mdss_dsi_host.c | 23 ++++++++ drivers/video/msm/mdss/mdss_dsi_panel.c | 4 ++ drivers/video/msm/mdss/mdss_dsi_status.c | 7 +++ 5 files changed, 110 insertions(+) diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c index d786ee88866e4..0b4a5a24c4b9e 100644 --- a/drivers/video/msm/mdss/mdss_dsi.c +++ b/drivers/video/msm/mdss/mdss_dsi.c @@ -45,6 +45,10 @@ static struct mdss_dsi_data *mdss_dsi_res; static struct pm_qos_request mdss_dsi_pm_qos_request; +#ifdef CONFIG_MACH_XIAOMI_MIDO +int panel_suspend_reset_flag = 0; +#endif + static void mdss_dsi_pm_qos_add_request(struct mdss_dsi_ctrl_pdata *ctrl_pdata) { struct irq_info *irq_info; @@ -295,6 +299,14 @@ static int mdss_dsi_panel_power_off(struct mdss_panel_data *pdata) if (mdss_dsi_pinctrl_set_state(ctrl_pdata, false)) pr_debug("reset disable: pinctrl not enabled\n"); +#ifdef CONFIG_MACH_XIAOMI_MIDO + if (2 == panel_suspend_reset_flag) + msleep(1); //dealy 2ms + + if (3 == panel_suspend_reset_flag) + msleep(4); //delay 4ms +#endif + ret = msm_dss_enable_vreg( ctrl_pdata->panel_power_data.vreg_config, ctrl_pdata->panel_power_data.num_vreg, 0); @@ -2893,6 +2905,14 @@ static struct device_node *mdss_dsi_find_panel_of_node( if (!strcmp(panel_name, NONE_PANEL)) goto exit; +#ifdef CONFIG_MACH_XIAOMI_MIDO + if (!strcmp(panel_name, "qcom,mdss_dsi_otm1911_fhd_video")) + panel_suspend_reset_flag = 2; + + if (!strcmp(panel_name, "qcom,mdss_dsi_ili9885_boe_fhd_video")) + panel_suspend_reset_flag = 3; +#endif + mdss_node = of_parse_phandle(pdev->dev.of_node, "qcom,mdss-mdp", 0); if (!mdss_node) { @@ -4064,6 +4084,50 @@ static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev, } +#ifdef CONFIG_MACH_XIAOMI_MIDO +u32 te_count; +static irqreturn_t te_interrupt(int irq, void *data) +{ + disable_irq_nosync(irq); + + te_count++; + + enable_irq(irq); + return IRQ_HANDLED; +} + +int init_te_irq(struct mdss_dsi_ctrl_pdata *ctrl_pdata) +{ + int rc = -1; + int irq; + if (gpio_is_valid(ctrl_pdata->disp_te_gpio)) { + rc = gpio_request(ctrl_pdata->disp_te_gpio, "te-gpio"); + if (rc < 0) { + pr_err("%s: gpio_request fail rc=%d\n", __func__, rc); + return rc ; + } + rc = gpio_direction_input(ctrl_pdata->disp_te_gpio); + if (rc < 0) { + pr_err("%s: gpio_direction_input fail rc=%d\n", __func__, rc); + return rc ; + } + irq = gpio_to_irq(ctrl_pdata->disp_te_gpio); + pr_err("%s:liujia irq = %d\n", __func__, irq); + rc = request_threaded_irq(irq, te_interrupt, NULL, + IRQF_TRIGGER_RISING|IRQF_ONESHOT, + "te-irq", ctrl_pdata); + if (rc < 0) { + pr_err("%s: request_irq fail rc=%d\n", __func__, rc); + return rc ; + } + } else { + pr_err("%s:liujia irq gpio not provided\n", __func__); + return rc ; + } + return 0; +} +#endif + static int mdss_dsi_parse_gpio_params(struct platform_device *ctrl_pdev, struct mdss_dsi_ctrl_pdata *ctrl_pdata) { @@ -4228,6 +4292,12 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev, ctrl_pdata->check_status = mdss_dsi_reg_status_check; else if (ctrl_pdata->status_mode == ESD_BTA) ctrl_pdata->check_status = mdss_dsi_bta_status_check; +#ifdef CONFIG_MACH_XIAOMI_MIDO + else if (ctrl_pdata->status_mode == ESD_TE_NT35596) { + ctrl_pdata->check_status = mdss_dsi_TE_NT35596_check; + init_te_irq(ctrl_pdata); + } +#endif if (ctrl_pdata->status_mode == ESD_MAX) { pr_err("%s: Using default BTA for ESD check\n", __func__); diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h index 6d6757ff592eb..d41e33acf7989 100644 --- a/drivers/video/msm/mdss/mdss_dsi.h +++ b/drivers/video/msm/mdss/mdss_dsi.h @@ -107,6 +107,9 @@ enum dsi_panel_status_mode { ESD_BTA, ESD_REG, ESD_REG_NT35596, +#ifdef CONFIG_MACH_XIAOMI_MIDO + ESD_TE_NT35596, +#endif ESD_TE, ESD_MAX, }; @@ -644,6 +647,9 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp); void mdss_dsi_cmdlist_kickoff(int intf); int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl); int mdss_dsi_reg_status_check(struct mdss_dsi_ctrl_pdata *ctrl); +#ifdef CONFIG_MACH_XIAOMI_MIDO +int mdss_dsi_TE_NT35596_check(struct mdss_dsi_ctrl_pdata *ctrl); +#endif bool __mdss_dsi_clk_enabled(struct mdss_dsi_ctrl_pdata *ctrl, u8 clk_type); void mdss_dsi_ctrl_setup(struct mdss_dsi_ctrl_pdata *ctrl); bool mdss_dsi_dln0_phy_err(struct mdss_dsi_ctrl_pdata *ctrl, bool print_en); diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c index 799a4e6ce3711..28f34ae4305b8 100644 --- a/drivers/video/msm/mdss/mdss_dsi_host.c +++ b/drivers/video/msm/mdss/mdss_dsi_host.c @@ -1215,6 +1215,29 @@ int mdss_dsi_reg_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata) return ret; } +#ifdef CONFIG_MACH_XIAOMI_MIDO +extern u32 te_count; +static u32 te_count_old = 1; + +int mdss_dsi_TE_NT35596_check (struct mdss_dsi_ctrl_pdata *ctrl_pdata) +{ + int ret = 1; + + if (te_count_old != te_count) { + + te_count_old = te_count; + } else { + ret = 0; + pr_err("liujia te_count doesnt add as time"); + } + if (te_count >= 10000) + te_count = 0; + + return ret; + +} +#endif + void mdss_dsi_dsc_config(struct mdss_dsi_ctrl_pdata *ctrl, struct dsc_desc *dsc) { u32 data, offset; diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c index 37a4f20cc2af5..85eb00ccf5a0e 100644 --- a/drivers/video/msm/mdss/mdss_dsi_panel.c +++ b/drivers/video/msm/mdss/mdss_dsi_panel.c @@ -1933,6 +1933,10 @@ static void mdss_dsi_parse_esd_params(struct device_node *np, pr_err("TE-ESD not valid for video mode\n"); goto error; } +#ifdef CONFIG_MACH_XIAOMI_MIDO + } else if (!strcmp(string, "TE_check_NT35596")) { + ctrl->status_mode = ESD_TE_NT35596; +#endif } else { pr_err("No valid panel-status-check-mode string\n"); goto error; diff --git a/drivers/video/msm/mdss/mdss_dsi_status.c b/drivers/video/msm/mdss/mdss_dsi_status.c index fce62350ab6a5..fc19242a87378 100644 --- a/drivers/video/msm/mdss/mdss_dsi_status.c +++ b/drivers/video/msm/mdss/mdss_dsi_status.c @@ -31,10 +31,17 @@ #include "mdss_panel.h" #include "mdss_mdp.h" +#ifdef CONFIG_MACH_XIAOMI_MIDO +#define STATUS_CHECK_INTERVAL_MS 2000 +#define STATUS_CHECK_INTERVAL_MIN_MS 200 +#define DSI_STATUS_CHECK_INIT -1 +#define DSI_STATUS_CHECK_DISABLE 0 +#else #define STATUS_CHECK_INTERVAL_MS 5000 #define STATUS_CHECK_INTERVAL_MIN_MS 50 #define DSI_STATUS_CHECK_INIT -1 #define DSI_STATUS_CHECK_DISABLE 1 +#endif static uint32_t interval = STATUS_CHECK_INTERVAL_MS; static int32_t dsi_status_disable = DSI_STATUS_CHECK_INIT; From 28654294d0dbc916e56b7a64ebc181c9597385d8 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Mon, 19 Mar 2018 19:19:27 +0530 Subject: [PATCH 198/508] driver: video: mdss: Import tissot changes --- drivers/video/fbdev/core/fbmem.c | 16 +++ drivers/video/msm/mdss/mdss_dsi.c | 78 +++++++++--- drivers/video/msm/mdss/mdss_dsi.h | 4 + drivers/video/msm/mdss/mdss_dsi_panel.c | 24 +++- drivers/video/msm/mdss/mdss_fb.c | 153 ++++++++++++++++++++++++ drivers/video/msm/mdss/mdss_fb.h | 4 + include/linux/fb.h | 3 + include/linux/mdss_io_util.h | 3 + 8 files changed, 268 insertions(+), 17 deletions(-) diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 2a708dd2eceed..ec86cd558b043 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1061,6 +1061,14 @@ fb_blank(struct fb_info *info, int blank) if (blank > FB_BLANK_POWERDOWN) blank = FB_BLANK_POWERDOWN; +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (info->blank == blank) { + if (info->fbops->fb_blank) + ret = info->fbops->fb_blank(blank, info); + return ret; + } +#endif + event.info = info; event.data = ␣ @@ -1080,6 +1088,11 @@ fb_blank(struct fb_info *info, int blank) fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK, &event); } +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (!ret) + info->blank = blank; +#endif + return ret; } EXPORT_SYMBOL(fb_blank); @@ -1641,6 +1654,9 @@ static int do_register_framebuffer(struct fb_info *fb_info) if (!registered_fb[i]) break; fb_info->node = i; +#ifdef CONFIG_MACH_XIAOMI_TISSOT + fb_info->blank = -1; +#endif atomic_set(&fb_info->count, 1); mutex_init(&fb_info->lock); mutex_init(&fb_info->mm_lock); diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c index 0b4a5a24c4b9e..693793428095c 100644 --- a/drivers/video/msm/mdss/mdss_dsi.c +++ b/drivers/video/msm/mdss/mdss_dsi.c @@ -45,8 +45,9 @@ static struct mdss_dsi_data *mdss_dsi_res; static struct pm_qos_request mdss_dsi_pm_qos_request; -#ifdef CONFIG_MACH_XIAOMI_MIDO +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) int panel_suspend_reset_flag = 0; +int panel_suspend_power_flag = 0; #endif static void mdss_dsi_pm_qos_add_request(struct mdss_dsi_ctrl_pdata *ctrl_pdata) @@ -276,7 +277,12 @@ static int mdss_dsi_regulator_init(struct platform_device *pdev, return rc; } -static int mdss_dsi_panel_power_off(struct mdss_panel_data *pdata) +#ifdef CONFIG_MACH_XIAOMI_TISSOT +extern int ft8716_suspend; +extern int ft8716_gesture_func_on; +int acc_vreg = 0; +#endif +int mdss_dsi_panel_power_off(struct mdss_panel_data *pdata) { int ret = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; @@ -303,17 +309,36 @@ static int mdss_dsi_panel_power_off(struct mdss_panel_data *pdata) if (2 == panel_suspend_reset_flag) msleep(1); //dealy 2ms - if (3 == panel_suspend_reset_flag) + if (4 == panel_suspend_reset_flag) msleep(4); //delay 4ms #endif - ret = msm_dss_enable_vreg( +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if ((panel_suspend_power_flag != 3) && acc_vreg) { +#endif + ret = msm_dss_enable_vreg( ctrl_pdata->panel_power_data.vreg_config, ctrl_pdata->panel_power_data.num_vreg, 0); - if (ret) - pr_err("%s: failed to disable vregs for %s\n", +#ifdef CONFIG_MACH_XIAOMI_TISSOT + acc_vreg--; +#endif + if (ret) + pr_err("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_PANEL_PM)); +#ifdef CONFIG_MACH_XIAOMI_TISSOT + } else { + if (!ft8716_gesture_func_on && ft8716_suspend && acc_vreg) { + ret = msm_dss_enable_vreg( + ctrl_pdata->panel_power_data.vreg_config, + ctrl_pdata->panel_power_data.num_vreg, 0); + acc_vreg--; + if (ret) + pr_err("%s: failed to disable vregs for %s\n", + __func__, __mdss_dsi_pm_name(DSI_PANEL_PM)); + } + } +#endif end: return ret; } @@ -331,14 +356,23 @@ static int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata) ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); - ret = msm_dss_enable_vreg( +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (!acc_vreg) { +#endif + ret = msm_dss_enable_vreg( ctrl_pdata->panel_power_data.vreg_config, ctrl_pdata->panel_power_data.num_vreg, 1); - if (ret) { - pr_err("%s: failed to enable vregs for %s\n", - __func__, __mdss_dsi_pm_name(DSI_PANEL_PM)); - return ret; +#ifdef CONFIG_MACH_XIAOMI_TISSOT + acc_vreg++; +#endif + if (ret) { + pr_err("%s: failed to enable vregs for %s\n", + __func__, __mdss_dsi_pm_name(DSI_PANEL_PM)); + return ret; + } +#ifdef CONFIG_MACH_XIAOMI_TISSOT } +#endif /* * If continuous splash screen feature is enabled, then we need to @@ -2905,12 +2939,18 @@ static struct device_node *mdss_dsi_find_panel_of_node( if (!strcmp(panel_name, NONE_PANEL)) goto exit; -#ifdef CONFIG_MACH_XIAOMI_MIDO - if (!strcmp(panel_name, "qcom,mdss_dsi_otm1911_fhd_video")) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) + if (!strcmp(panel_name, "qcom,mdss_dsi_td4310_fhd_video")) { + panel_suspend_reset_flag = 1; + panel_suspend_power_flag = 1; + } else if (!strcmp(panel_name, "qcom,mdss_dsi_otm1911_fhd_video")) { panel_suspend_reset_flag = 2; - - if (!strcmp(panel_name, "qcom,mdss_dsi_ili9885_boe_fhd_video")) + panel_suspend_power_flag = 2; + } else if (!strcmp(panel_name, "qcom,mdss_dsi_ft8716_fhd_video")) { panel_suspend_reset_flag = 3; + panel_suspend_power_flag = 3; + } else if (!strcmp(panel_name, "qcom,mdss_dsi_ili9885_boe_fhd_video")) + panel_suspend_reset_flag = 4; #endif mdss_node = of_parse_phandle(pdev->dev.of_node, @@ -3187,6 +3227,10 @@ static int mdss_dsi_get_bridge_chip_params(struct mdss_panel_info *pinfo, return rc; } +#ifdef CONFIG_MACH_XIAOMI_TISSOT +struct mdss_panel_data *panel_data; +#endif + static int mdss_dsi_ctrl_probe(struct platform_device *pdev) { int rc = 0; @@ -3280,6 +3324,10 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev) ctrl_pdata->bklt_ctrl = UNKNOWN_CTRL; } +#ifdef CONFIG_MACH_XIAOMI_TISSOT + panel_data = &ctrl_pdata->panel_data; +#endif + rc = dsi_panel_device_register(pdev, dsi_pan_node, ctrl_pdata); if (rc) { pr_err("%s: dsi panel dev reg failed\n", __func__); diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h index d41e33acf7989..06d8b918aa52a 100644 --- a/drivers/video/msm/mdss/mdss_dsi.h +++ b/drivers/video/msm/mdss/mdss_dsi.h @@ -230,6 +230,10 @@ extern struct device dsi_dev; extern u32 dsi_irq; extern struct mdss_dsi_ctrl_pdata *ctrl_list[]; +#ifdef CONFIG_MACH_XIAOMI_TISSOT +extern int ft8716_gesture_func_on; +#endif + enum { DSI_CTRL_0, DSI_CTRL_1, diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c index 85eb00ccf5a0e..67be02e8c0501 100644 --- a/drivers/video/msm/mdss/mdss_dsi_panel.c +++ b/drivers/video/msm/mdss/mdss_dsi_panel.c @@ -180,7 +180,7 @@ static void mdss_dsi_panel_apply_settings(struct mdss_dsi_ctrl_pdata *ctrl, mdss_dsi_cmdlist_put(ctrl, &cmdreq); } -static void mdss_dsi_panel_cmds_send(struct mdss_dsi_ctrl_pdata *ctrl, +void mdss_dsi_panel_cmds_send(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_panel_cmds *pcmds, u32 flags) { struct dcs_cmd_req cmdreq; @@ -339,6 +339,11 @@ static int mdss_dsi_request_gpios(struct mdss_dsi_ctrl_pdata *ctrl_pdata) return rc; } +#ifdef CONFIG_MACH_XIAOMI_TISSOT +extern int ft8716_suspend; +extern int panel_suspend_reset_flag; +#endif + int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable) { struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; @@ -480,7 +485,22 @@ int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable) gpio_set_value((ctrl_pdata->disp_en_gpio), 0); gpio_free(ctrl_pdata->disp_en_gpio); } - gpio_set_value((ctrl_pdata->rst_gpio), 0); + +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (panel_suspend_reset_flag == 2 || (panel_suspend_reset_flag == 3 && ft8716_gesture_func_on == 0) + || ft8716_suspend) { + gpio_set_value((ctrl_pdata->rst_gpio), 1); + mdelay(10); + gpio_set_value((ctrl_pdata->rst_gpio), 0); + mdelay(10); + gpio_set_value((ctrl_pdata->rst_gpio), 1); + mdelay(10); + gpio_set_value((ctrl_pdata->rst_gpio), 0); + mdelay(10); + } else +#endif + gpio_set_value((ctrl_pdata->rst_gpio), 0); + gpio_free(ctrl_pdata->rst_gpio); if (gpio_is_valid(ctrl_pdata->mode_gpio)) gpio_free(ctrl_pdata->mode_gpio); diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index 489da4344ec77..d884fe5573bf0 100644 --- a/drivers/video/msm/mdss/mdss_fb.c +++ b/drivers/video/msm/mdss/mdss_fb.c @@ -48,6 +48,10 @@ #include #include #include +#ifdef CONFIG_MACH_XIAOMI_TISSOT +#include +#include +#endif #include "mdss_fb.h" #include "mdss_mdp_splash_logo.h" #define CREATE_TRACE_POINTS @@ -122,6 +126,36 @@ static int mdss_fb_send_panel_event(struct msm_fb_data_type *mfd, int event, void *arg); static void mdss_fb_set_mdp_sync_pt_threshold(struct msm_fb_data_type *mfd, int type); +#ifdef CONFIG_MACH_XIAOMI_TISSOT +#define WAIT_RESUME_TIMEOUT 200 +struct fb_info *prim_fbi; +static struct delayed_work prim_panel_work; +static atomic_t prim_panel_is_on; +static struct wake_lock prim_panel_wakelock; +static void prim_panel_off_delayed_work(struct work_struct *work) +{ +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + console_lock(); +#endif + if (!lock_fb_info(prim_fbi)) { +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + console_unlock(); +#endif + return; + } + if (atomic_read(&prim_panel_is_on)) { + fb_blank(prim_fbi, FB_BLANK_POWERDOWN); + atomic_set(&prim_panel_is_on, false); + wake_unlock(&prim_panel_wakelock); + } + + unlock_fb_info(prim_fbi); +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + console_unlock(); +#endif +} +#endif + void mdss_fb_no_update_notify_timer_cb(unsigned long data) { struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data; @@ -1379,6 +1413,14 @@ static int mdss_fb_remove(struct platform_device *pdev) mdss_fb_remove_sysfs(mfd); +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (mfd->panel_info && mfd->panel_info->is_prim_panel) { + atomic_set(&prim_panel_is_on, false); + cancel_delayed_work_sync(&prim_panel_work); + wake_lock_destroy(&prim_panel_wakelock); + } +#endif + pm_runtime_disable(mfd->fbi->dev); if (mfd->key != MFD_KEY) @@ -1552,6 +1594,32 @@ static int mdss_fb_resume(struct platform_device *pdev) #endif #ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_MACH_XIAOMI_TISSOT +static int mdss_fb_pm_prepare(struct device *dev) +{ + struct msm_fb_data_type *mfd = dev_get_drvdata(dev); + + if (!mfd) + return -ENODEV; + if (mfd->panel_info->is_prim_panel) + atomic_inc(&mfd->resume_pending); + return 0; +} + +static void mdss_fb_pm_complete(struct device *dev) +{ + struct msm_fb_data_type *mfd = dev_get_drvdata(dev); + + if (!mfd) + return; + if (mfd->panel_info->is_prim_panel) { + atomic_set(&mfd->resume_pending, 0); + wake_up_all(&mfd->resume_wait_q); + } + return; +} +#endif + static int mdss_fb_pm_suspend(struct device *dev) { struct msm_fb_data_type *mfd = dev_get_drvdata(dev); @@ -1586,6 +1654,10 @@ static int mdss_fb_pm_resume(struct device *dev) #endif static const struct dev_pm_ops mdss_fb_pm_ops = { +#ifdef CONFIG_MACH_XIAOMI_TISSOT + .prepare = mdss_fb_pm_prepare, + .complete = mdss_fb_pm_complete, +#endif SET_SYSTEM_SLEEP_PM_OPS(mdss_fb_pm_suspend, mdss_fb_pm_resume) }; @@ -2027,6 +2099,16 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info) struct mdss_panel_data *pdata; struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if ((info == prim_fbi) && (blank_mode == FB_BLANK_UNBLANK) && + atomic_read(&prim_panel_is_on)) { + atomic_set(&prim_panel_is_on, false); + wake_unlock(&prim_panel_wakelock); + cancel_delayed_work_sync(&prim_panel_work); + return 0; + } +#endif + ret = mdss_fb_pan_idle(mfd); if (ret) { pr_warn("mdss_fb_pan_idle for fb%d failed. ret=%d\n", @@ -2655,6 +2737,9 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) atomic_set(&mfd->commits_pending, 0); atomic_set(&mfd->ioctl_ref_cnt, 0); atomic_set(&mfd->kickoff_pending, 0); +#ifdef CONFIG_MACH_XIAOMI_TISSOT + atomic_set(&mfd->resume_pending, 0); +#endif init_timer(&mfd->no_update.timer); mfd->no_update.timer.function = mdss_fb_no_update_notify_timer_cb; @@ -2670,6 +2755,9 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) init_waitqueue_head(&mfd->idle_wait_q); init_waitqueue_head(&mfd->ioctl_q); init_waitqueue_head(&mfd->kickoff_wait_q); +#ifdef CONFIG_MACH_XIAOMI_TISSOT + init_waitqueue_head(&mfd->resume_wait_q); +#endif ret = fb_alloc_cmap(&fbi->cmap, 256, 0); if (ret) @@ -2687,6 +2775,14 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) mdss_panel_debugfs_init(panel_info, panel_name); pr_info("FrameBuffer[%d] %dx%d registered successfully!\n", mfd->index, fbi->var.xres, fbi->var.yres); +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (panel_info->is_prim_panel) { + prim_fbi = fbi; + atomic_set(&prim_panel_is_on, false); + INIT_DELAYED_WORK(&prim_panel_work, prim_panel_off_delayed_work); + wake_lock_init(&prim_panel_wakelock, WAKE_LOCK_SUSPEND, "prim_panel_wakelock"); + } +#endif return 0; } @@ -5080,6 +5176,63 @@ void mdss_fb_report_panel_dead(struct msm_fb_data_type *mfd) pr_err("Panel has gone bad, sending uevent - %s\n", envp[0]); } +#ifdef CONFIG_MACH_XIAOMI_TISSOT +/* + * mdss_prim_panel_fb_unblank() - Unblank primary panel FB + * @timeout : >0 blank primary panel FB after timeout (ms) + */ +int mdss_prim_panel_fb_unblank(int timeout) +{ + int ret = 0; + struct msm_fb_data_type *mfd = NULL; + + if (prim_fbi) { + mfd = (struct msm_fb_data_type *)prim_fbi->par; + ret = wait_event_timeout(mfd->resume_wait_q, + !atomic_read(&mfd->resume_pending), + msecs_to_jiffies(WAIT_RESUME_TIMEOUT)); + if (!ret) { + pr_info("Primary fb resume timeout\n"); + return -ETIMEDOUT; + } +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + console_lock(); +#endif + if (!lock_fb_info(prim_fbi)) { +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + console_unlock(); +#endif + return -ENODEV; + } + if (prim_fbi->blank == FB_BLANK_UNBLANK) { + unlock_fb_info(prim_fbi); +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + console_unlock(); +#endif + return 0; + } + wake_lock(&prim_panel_wakelock); + ret = fb_blank(prim_fbi, FB_BLANK_UNBLANK); + if (!ret) { + atomic_set(&prim_panel_is_on, true); + if (timeout > 0) { + schedule_delayed_work(&prim_panel_work, msecs_to_jiffies(timeout)); + } else + wake_unlock(&prim_panel_wakelock); + } else + wake_unlock(&prim_panel_wakelock); + unlock_fb_info(prim_fbi); +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + console_unlock(); +#endif + return ret; + } + + pr_err("primary panel is not existed\n"); + return -EINVAL; +} +#endif + /* * mdss_fb_calc_fps() - Calculates fps value. diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h index 0b5528a195bd2..7bc2afd096462 100644 --- a/drivers/video/msm/mdss/mdss_fb.h +++ b/drivers/video/msm/mdss/mdss_fb.h @@ -332,6 +332,10 @@ struct msm_fb_data_type { struct task_struct *disp_thread; atomic_t commits_pending; atomic_t kickoff_pending; +#ifdef CONFIG_MACH_XIAOMI_TISSOT + atomic_t resume_pending; + wait_queue_head_t resume_wait_q; +#endif wait_queue_head_t commit_wait_q; wait_queue_head_t idle_wait_q; wait_queue_head_t kickoff_wait_q; diff --git a/include/linux/fb.h b/include/linux/fb.h index 3cde50f14de03..f637c1dd06a54 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -503,6 +503,9 @@ struct fb_info { } *apertures; bool skip_vt_switch; /* no VT switch on suspend/resume required */ +#ifdef CONFIG_MACH_XIAOMI_TISSOT + int blank; +#endif }; static inline struct apertures_struct *alloc_apertures(unsigned int max_num) { diff --git a/include/linux/mdss_io_util.h b/include/linux/mdss_io_util.h index 4a399762cf505..7031fbcc81a50 100644 --- a/include/linux/mdss_io_util.h +++ b/include/linux/mdss_io_util.h @@ -117,5 +117,8 @@ int mdss_i2c_byte_read(struct i2c_client *client, uint8_t slave_addr, uint8_t reg_offset, uint8_t *read_buf); int mdss_i2c_byte_write(struct i2c_client *client, uint8_t slave_addr, uint8_t reg_offset, uint8_t *value); +#ifdef CONFIG_MACH_XIAOMI_TISSOT +int mdss_prim_panel_fb_unblank(int timeout); +#endif #endif /* __MDSS_IO_UTIL_H__ */ From b21703eedee1244a056855d578fac7e8dccb91f5 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Tue, 2 Jan 2018 14:48:40 +0530 Subject: [PATCH 199/508] drivers: media: camera_v2: Import mido changes --- drivers/clk/msm/clock-gcc-8953.c | 3 +++ .../camera_v2/sensor/actuator/msm_actuator.c | 17 +++++++++++++++++ .../platform/msm/camera_v2/sensor/cci/msm_cci.c | 4 ++++ .../msm/camera_v2/sensor/csid/msm_csid.c | 4 ++++ .../msm/camera_v2/sensor/eeprom/msm_eeprom.c | 14 ++++++++++++++ 5 files changed, 42 insertions(+) diff --git a/drivers/clk/msm/clock-gcc-8953.c b/drivers/clk/msm/clock-gcc-8953.c index 64f409bda7710..725dba3bac940 100644 --- a/drivers/clk/msm/clock-gcc-8953.c +++ b/drivers/clk/msm/clock-gcc-8953.c @@ -1177,6 +1177,9 @@ static struct rcg_clk camss_gp1_clk_src = { }; static struct clk_freq_tbl ftbl_mclk0_clk_src[] = { +#ifdef CONFIG_MACH_XIAOMI_MIDO + F( 19200000, xo, 1, 0, 0), +#endif F( 24000000, gpll6_main_div2, 1, 2, 45), F( 33330000, gpll0_main_div2, 12, 0, 0), F( 36610000, gpll6, 1, 2, 59), diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c index fbeb531f8d301..c8d24981b70e3 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c @@ -30,6 +30,11 @@ DEFINE_MSM_MUTEX(msm_actuator_mutex); #define PARK_LENS_MID_STEP 5 #define PARK_LENS_SMALL_STEP 3 #define MAX_QVALUE 4096 +#ifdef CONFIG_MACH_XIAOMI_MIDO +#define PARK_LENS_QUIET_UPPER_CODE 400 +#define PARK_LENS_QUIET_LOWER_CODE 200 +#define PARK_LENS_QUIET_STEP 25 +#endif static struct v4l2_file_operations msm_actuator_v4l2_subdev_fops; static int32_t msm_actuator_power_up(struct msm_actuator_ctrl_t *a_ctrl); @@ -833,6 +838,16 @@ static int32_t msm_actuator_park_lens(struct msm_actuator_ctrl_t *a_ctrl) next_lens_pos = a_ctrl->step_position_table[a_ctrl->curr_step_pos]; while (next_lens_pos) { /* conditions which help to reduce park lens time */ +#ifdef CONFIG_MACH_XIAOMI_MIDO + if (next_lens_pos > PARK_LENS_QUIET_UPPER_CODE) + next_lens_pos = PARK_LENS_QUIET_UPPER_CODE; + else { + if (next_lens_pos > PARK_LENS_QUIET_LOWER_CODE) + next_lens_pos -= PARK_LENS_QUIET_STEP; + else + next_lens_pos = 0; + } +#else if (next_lens_pos > (a_ctrl->park_lens.max_step * PARK_LENS_LONG_STEP)) { next_lens_pos = next_lens_pos - @@ -854,6 +869,8 @@ static int32_t msm_actuator_park_lens(struct msm_actuator_ctrl_t *a_ctrl) (next_lens_pos - a_ctrl->park_lens. max_step) : 0; } +#endif + a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl, next_lens_pos, a_ctrl->park_lens.hw_params, a_ctrl->park_lens.damping_delay); diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c index 859a7c3c64260..048439310ea7f 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c +++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c @@ -32,7 +32,11 @@ #define CYCLES_PER_MICRO_SEC_DEFAULT 4915 #define CCI_MAX_DELAY 1000000 +#ifdef CONFIG_MACH_XIAOMI_MIDO +#define CCI_TIMEOUT msecs_to_jiffies(800) +#else #define CCI_TIMEOUT msecs_to_jiffies(500) +#endif /* TODO move this somewhere else */ #define MSM_CCI_DRV_NAME "msm_cci" diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c index e851c56000329..062788ae72333 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c +++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c @@ -62,7 +62,11 @@ #define FALSE 0 #define MAX_LANE_COUNT 4 +#ifdef CONFIG_MACH_XIAOMI_MIDO +#define CSID_TIMEOUT msecs_to_jiffies(500) +#else #define CSID_TIMEOUT msecs_to_jiffies(100) +#endif #undef CDBG #define CDBG(fmt, args...) pr_debug(fmt, ##args) diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c index dd2f9192e32f7..01fbd1834c3ac 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c +++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c @@ -151,6 +151,9 @@ static int read_eeprom_memory(struct msm_eeprom_ctrl_t *e_ctrl, struct msm_eeprom_memory_map_t *emap = block->map; struct msm_eeprom_board_info *eb_info; uint8_t *memptr = block->mapdata; +#if (defined CONFIG_MACH_XIAOMI_MIDO) + uint8_t sensor_id[2] = {0}; +#endif if (!e_ctrl) { pr_err("%s e_ctrl is NULL", __func__); @@ -159,6 +162,17 @@ static int read_eeprom_memory(struct msm_eeprom_ctrl_t *e_ctrl, eb_info = e_ctrl->eboard_info; +#if (defined CONFIG_MACH_XIAOMI_MIDO) + e_ctrl->i2c_client.addr_type = 2; + rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_read_seq( + &(e_ctrl->i2c_client), 0x0000, + sensor_id, 2); + if (rc < 0) { + pr_err("%s error\n", __func__); + return rc; + } +#endif + for (j = 0; j < block->num_map; j++) { if (emap[j].saddr.addr) { eb_info->i2c_slaveaddr = emap[j].saddr.addr; From 0cb584d01852e3721d282956f492c2a106d818c6 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Wed, 21 Mar 2018 14:51:57 +0530 Subject: [PATCH 200/508] drivers: media: camera_v2: Import tissot changes --- .../msm/camera_v2/sensor/eeprom/msm_eeprom.c | 44 ++++++++++++++++++- .../msm/camera_v2/sensor/msm_sensor_init.c | 4 ++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c index 01fbd1834c3ac..610258b00f939 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c +++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c @@ -151,7 +151,7 @@ static int read_eeprom_memory(struct msm_eeprom_ctrl_t *e_ctrl, struct msm_eeprom_memory_map_t *emap = block->map; struct msm_eeprom_board_info *eb_info; uint8_t *memptr = block->mapdata; -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) uint8_t sensor_id[2] = {0}; #endif @@ -162,7 +162,7 @@ static int read_eeprom_memory(struct msm_eeprom_ctrl_t *e_ctrl, eb_info = e_ctrl->eboard_info; -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) e_ctrl->i2c_client.addr_type = 2; rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_read_seq( &(e_ctrl->i2c_client), 0x0000, @@ -187,7 +187,17 @@ static int read_eeprom_memory(struct msm_eeprom_ctrl_t *e_ctrl, rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_write( &(e_ctrl->i2c_client), emap[j].page.addr, emap[j].page.data, emap[j].page.data_t); + +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (emap[j].page.delay > 20) + msleep(emap[j].page.delay); + else if (emap[j].page.delay) + usleep_range(emap[j].page.delay * 1000, + (emap[j].page.delay * 1000) + 1000); +#else msleep(emap[j].page.delay); +#endif + if (rc < 0) { pr_err("%s: page write failed\n", __func__); return rc; @@ -198,7 +208,17 @@ static int read_eeprom_memory(struct msm_eeprom_ctrl_t *e_ctrl, rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_write( &(e_ctrl->i2c_client), emap[j].pageen.addr, emap[j].pageen.data, emap[j].pageen.data_t); + +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (emap[j].pageen.delay > 20) msleep(emap[j].pageen.delay); + else if (emap[j].pageen.delay) + usleep_range(emap[j].pageen.delay * 1000, + (emap[j].pageen.delay * 1000) + 1000); +#else + msleep(emap[j].pageen.delay); +#endif + if (rc < 0) { pr_err("%s: page enable failed\n", __func__); return rc; @@ -379,7 +399,17 @@ static int eeprom_parse_memory_map(struct msm_eeprom_ctrl_t *e_ctrl, eeprom_map->mem_settings[i].reg_addr, eeprom_map->mem_settings[i].reg_data, eeprom_map->mem_settings[i].data_type); + +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (eeprom_map->mem_settings[i].delay > 20) + msleep(eeprom_map->mem_settings[i].delay); + else if (eeprom_map->mem_settings[i].delay) + usleep_range(eeprom_map->mem_settings[i].delay * 1000, + (eeprom_map->mem_settings[i].delay * 1000) + 1000); +#else msleep(eeprom_map->mem_settings[i].delay); +#endif + if (rc < 0) { pr_err("%s: page write failed\n", __func__); @@ -411,7 +441,17 @@ static int eeprom_parse_memory_map(struct msm_eeprom_ctrl_t *e_ctrl, eeprom_map->mem_settings[i].reg_addr, memptr, eeprom_map->mem_settings[i].reg_data); + +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (eeprom_map->mem_settings[i].delay > 20) + msleep(eeprom_map->mem_settings[i].delay); + else if (eeprom_map->mem_settings[i].delay) + usleep_range(eeprom_map->mem_settings[i].delay * 1000, + (eeprom_map->mem_settings[i].delay * 1000) + 1000); +#else msleep(eeprom_map->mem_settings[i].delay); +#endif + if (rc < 0) { pr_err("%s: read failed\n", __func__); diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c index 9af43f4edb8d8..9181d29ce37c5 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c @@ -42,7 +42,11 @@ static const struct v4l2_subdev_internal_ops msm_sensor_init_internal_ops; static int msm_sensor_wait_for_probe_done(struct msm_sensor_init_t *s_init) { int rc; +#ifdef CONFIG_MACH_XIAOMI_TISSOT + int tm = 30000; +#else int tm = 10000; +#endif if (s_init->module_init_status == 1) { CDBG("msm_cam_get_module_init_status -2\n"); return 0; From b1c493f3461c427699849709060b4ce8f3944452 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Fri, 29 Dec 2017 17:57:30 +0530 Subject: [PATCH 201/508] drivers: input: fingerprint: Import mido drivers --- drivers/input/Kconfig | 2 + drivers/input/Makefile | 1 + drivers/input/fingerprint/Kconfig | 6 + drivers/input/fingerprint/Makefile | 2 + drivers/input/fingerprint/fpc_mido/Kconfig | 5 + drivers/input/fingerprint/fpc_mido/Makefile | 1 + .../input/fingerprint/fpc_mido/fpc1020_tee.c | 636 ++++++++++++ drivers/input/fingerprint/goodix_mido/Kconfig | 5 + .../input/fingerprint/goodix_mido/Makefile | 1 + .../input/fingerprint/goodix_mido/gf_spi.c | 906 ++++++++++++++++++ .../input/fingerprint/goodix_mido/gf_spi.h | 106 ++ .../input/fingerprint/goodix_mido/netlink.c | 87 ++ .../input/fingerprint/goodix_mido/platform.c | 202 ++++ 13 files changed, 1960 insertions(+) create mode 100644 drivers/input/fingerprint/Kconfig create mode 100644 drivers/input/fingerprint/Makefile create mode 100644 drivers/input/fingerprint/fpc_mido/Kconfig create mode 100644 drivers/input/fingerprint/fpc_mido/Makefile create mode 100644 drivers/input/fingerprint/fpc_mido/fpc1020_tee.c create mode 100644 drivers/input/fingerprint/goodix_mido/Kconfig create mode 100644 drivers/input/fingerprint/goodix_mido/Makefile create mode 100644 drivers/input/fingerprint/goodix_mido/gf_spi.c create mode 100644 drivers/input/fingerprint/goodix_mido/gf_spi.h create mode 100644 drivers/input/fingerprint/goodix_mido/netlink.c create mode 100644 drivers/input/fingerprint/goodix_mido/platform.c diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 1819769051f3c..9b12c334b8e24 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -208,6 +208,8 @@ source "drivers/input/touchscreen/Kconfig" source "drivers/input/misc/Kconfig" +source "drivers/input/fingerprint/Kconfig" + endif menu "Hardware I/O ports" diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 93289a43536ea..d7fa8a6a795ff 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_INPUT_MOUSE) += mouse/ obj-$(CONFIG_INPUT_JOYSTICK) += joystick/ obj-$(CONFIG_INPUT_TABLET) += tablet/ obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ +obj-$(CONFIG_INPUT_FINGERPRINT) += fingerprint/ obj-$(CONFIG_INPUT_MISC) += misc/ obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o diff --git a/drivers/input/fingerprint/Kconfig b/drivers/input/fingerprint/Kconfig new file mode 100644 index 0000000000000..9331a96068b6f --- /dev/null +++ b/drivers/input/fingerprint/Kconfig @@ -0,0 +1,6 @@ +config INPUT_FINGERPRINT + tristate "Fingerprint driver support" + help + Say Y here to enable goodix fingerprint driver support! +source "drivers/input/fingerprint/goodix_mido/Kconfig" +source "drivers/input/fingerprint/fpc_mido/Kconfig" diff --git a/drivers/input/fingerprint/Makefile b/drivers/input/fingerprint/Makefile new file mode 100644 index 0000000000000..262e1a88912b1 --- /dev/null +++ b/drivers/input/fingerprint/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_FINGERPRINT_GOODIX_GF3208_MIDO) += goodix_mido/ +obj-$(CONFIG_FINGERPRINT_FPC1020_MIDO) += fpc_mido/ diff --git a/drivers/input/fingerprint/fpc_mido/Kconfig b/drivers/input/fingerprint/fpc_mido/Kconfig new file mode 100644 index 0000000000000..62c17d2cfc413 --- /dev/null +++ b/drivers/input/fingerprint/fpc_mido/Kconfig @@ -0,0 +1,5 @@ +config FINGERPRINT_FPC1020_MIDO + tristate "FingerPrint Cards fingerprint driver support" + depends on INPUT_FINGERPRINT + help + Say Y here to enable fpc fingerprint driver support! diff --git a/drivers/input/fingerprint/fpc_mido/Makefile b/drivers/input/fingerprint/fpc_mido/Makefile new file mode 100644 index 0000000000000..47c31a5655923 --- /dev/null +++ b/drivers/input/fingerprint/fpc_mido/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_FINGERPRINT_FPC1020_MIDO) += fpc1020_tee.o diff --git a/drivers/input/fingerprint/fpc_mido/fpc1020_tee.c b/drivers/input/fingerprint/fpc_mido/fpc1020_tee.c new file mode 100644 index 0000000000000..19f9fbbd842e4 --- /dev/null +++ b/drivers/input/fingerprint/fpc_mido/fpc1020_tee.c @@ -0,0 +1,636 @@ +/* + * FPC1020 Fingerprint sensor device driver + * + * This driver will control the platform resources that the FPC fingerprint + * sensor needs to operate. The major things are probing the sensor to check + * that it is actually connected and let the Kernel know this and with that also + * enabling and disabling of regulators, enabling and disabling of platform + * clocks, controlling GPIOs such as SPI chip select, sensor reset line, sensor + * IRQ line, MISO and MOSI lines. + * + * The driver will expose most of its available functionality in sysfs which + * enables dynamic control of these features from eg. a user space process. + * + * The sensor's IRQ events will be pushed to Kernel's event handling system and + * are exposed in the drivers event node. This makes it possible for a user + * space process to poll the input node and receive IRQ events easily. Usually + * this node is available under /dev/input/eventX where 'X' is a number given by + * the event system. A user space process will need to traverse all the event + * nodes and ask for its parent's name (through EVIOCGNAME) which should match + * the value in device tree named input-device-name. + * + * This driver will NOT send any SPI commands to the sensor it only controls the + * electrical parts. + * + * + * Copyright (c) 2015 Fingerprint Cards AB + * Copyright (C) 2017 XiaoMi, Inc. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FPC1020_RESET_LOW_US 1000 +#define FPC1020_RESET_HIGH1_US 100 +#define FPC1020_RESET_HIGH2_US 1250 +#define PWR_ON_STEP_SLEEP 100 +#define PWR_ON_STEP_RANGE1 100 +#define PWR_ON_STEP_RANGE2 900 +#define FPC_TTW_HOLD_TIME 1000 +#define NUM_PARAMS_REG_ENABLE_SET 2 + +static const char * const pctl_names[] = { + + "fpc1020_reset_reset", + "fpc1020_reset_active", + "fpc1020_irq_active", +}; + +struct fpc1020_data { + struct device *dev; + struct pinctrl *fingerprint_pinctrl; + struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)]; +#ifdef LINUX_CONTROL_SPI_CLK + u32 max_speed_hz; + struct clk *iface_clk; + struct clk *core_clk; +#endif + + struct wake_lock ttw_wl; + int irq_gpio; + int rst_gpio; + struct mutex lock; + bool prepared; + bool wakeup_enabled; + bool compatible_enabled; +#ifdef LINUX_CONTROL_SPI_CLK + bool clocks_enabled; + bool clocks_suspended; +#endif +}; + +static irqreturn_t fpc1020_irq_handler(int irq, void *handle); +static int fpc1020_request_named_gpio(struct fpc1020_data *fpc1020, + const char *label, int *gpio); +static int hw_reset(struct fpc1020_data *fpc1020); + +#ifdef LINUX_CONTROL_SPI_CLK +static int set_clks(struct fpc1020_data *fpc1020, bool enable) +{ + int rc = 0; + mutex_lock(&fpc1020->lock); + + if (enable == fpc1020->clocks_enabled) + goto out; + + if (enable) { + rc = clk_set_rate(fpc1020->core_clk, fpc1020->max_speed_hz); + if (rc) { + dev_err(fpc1020->dev, + "%s: Error setting clk_rate: %u, %d\n", + __func__, fpc1020->max_speed_hz, + rc); + goto out; + } + rc = clk_prepare_enable(fpc1020->core_clk); + if (rc) { + dev_err(fpc1020->dev, + "%s: Error enabling core clk: %d\n", + __func__, rc); + goto out; + } + + rc = clk_prepare_enable(fpc1020->iface_clk); + if (rc) { + dev_err(fpc1020->dev, + "%s: Error enabling iface clk: %d\n", + __func__, rc); + clk_disable_unprepare(fpc1020->core_clk); + goto out; + } + dev_dbg(fpc1020->dev, "%s ok. clk rate %u hz\n", __func__, + fpc1020->max_speed_hz); + + fpc1020->clocks_enabled = true; + } else { + clk_disable_unprepare(fpc1020->iface_clk); + clk_disable_unprepare(fpc1020->core_clk); + fpc1020->clocks_enabled = false; + } + +out: + mutex_unlock(&fpc1020->lock); + return rc; +} + +static ssize_t clk_enable_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + return set_clks(fpc1020, (*buf == '1')) ? : count; +} + +static DEVICE_ATTR(clk_enable, S_IWUSR, NULL, clk_enable_set); +#endif +/** + * Will try to select the set of pins (GPIOS) defined in a pin control node of + * the device tree named @p name. + * + * The node can contain several eg. GPIOs that is controlled when selecting it. + * The node may activate or deactivate the pins it contains, the action is + * defined in the device tree node itself and not here. The states used + * internally is fetched at probe time. + * + * @see pctl_names + * @see fpc1020_probe + */ +static int select_pin_ctl(struct fpc1020_data *fpc1020, const char *name) +{ + size_t i; + int rc; + struct device *dev = fpc1020->dev; + for (i = 0; i < ARRAY_SIZE(fpc1020->pinctrl_state); i++) { + const char *n = pctl_names[i]; + if (!strncmp(n, name, strlen(n))) { + rc = pinctrl_select_state(fpc1020->fingerprint_pinctrl, + fpc1020->pinctrl_state[i]); + if (rc) + dev_err(dev, "cannot select '%s'\n", name); + else + dev_dbg(dev, "Selected '%s'\n", name); + goto exit; + } + } + rc = -EINVAL; + dev_err(dev, "%s:'%s' not found\n", __func__, name); +exit: + return rc; +} + +static ssize_t pinctl_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + int rc = select_pin_ctl(fpc1020, buf); + return rc ? rc : count; +} +static DEVICE_ATTR(pinctl_set, S_IWUSR, NULL, pinctl_set); + +static int hw_reset(struct fpc1020_data *fpc1020) +{ + int irq_gpio; + struct device *dev = fpc1020->dev; + + int rc = select_pin_ctl(fpc1020, "fpc1020_reset_active"); + if (rc) + goto exit; + usleep_range(FPC1020_RESET_HIGH1_US, FPC1020_RESET_HIGH1_US + 100); + + rc = select_pin_ctl(fpc1020, "fpc1020_reset_reset"); + if (rc) + goto exit; + usleep_range(FPC1020_RESET_LOW_US, FPC1020_RESET_LOW_US + 100); + + rc = select_pin_ctl(fpc1020, "fpc1020_reset_active"); + if (rc) + goto exit; + usleep_range(FPC1020_RESET_HIGH1_US, FPC1020_RESET_HIGH1_US + 100); + + irq_gpio = gpio_get_value(fpc1020->irq_gpio); + dev_info(dev, "IRQ after reset %d\n", irq_gpio); +exit: + return rc; +} + +static ssize_t hw_reset_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc; + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + + if (!strncmp(buf, "reset", strlen("reset"))) + rc = hw_reset(fpc1020); + else + return -EINVAL; + return rc ? rc : count; +} +static DEVICE_ATTR(hw_reset, S_IWUSR, NULL, hw_reset_set); + +/** + * Will setup clocks, GPIOs, and regulators to correctly initialize the touch + * sensor to be ready for work. + * + * In the correct order according to the sensor spec this function will + * enable/disable regulators, SPI platform clocks, and reset line, all to set + * the sensor in a correct power on or off state "electrical" wise. + * + * @see spi_prepare_set + * @note This function will not send any commands to the sensor it will only + * control it "electrically". + */ +static int device_prepare(struct fpc1020_data *fpc1020, bool enable) +{ + int rc; + + mutex_lock(&fpc1020->lock); + if (enable && !fpc1020->prepared) { + fpc1020->prepared = true; + select_pin_ctl(fpc1020, "fpc1020_reset_reset"); + + usleep_range(PWR_ON_STEP_SLEEP, PWR_ON_STEP_RANGE2); + + (void)select_pin_ctl(fpc1020, "fpc1020_reset_active"); + usleep_range(PWR_ON_STEP_SLEEP, PWR_ON_STEP_RANGE1); + } else if (!enable && fpc1020->prepared) { + rc = 0; + + (void)select_pin_ctl(fpc1020, "fpc1020_reset_reset"); + usleep_range(PWR_ON_STEP_SLEEP, PWR_ON_STEP_RANGE2); + + fpc1020->prepared = false; + } else { + rc = 0; + } + mutex_unlock(&fpc1020->lock); + return rc; +} + +static ssize_t spi_prepare_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc; + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + + if (!strncmp(buf, "enable", strlen("enable"))) + rc = device_prepare(fpc1020, true); + else if (!strncmp(buf, "disable", strlen("disable"))) + rc = device_prepare(fpc1020, false); + else + return -EINVAL; + return rc ? rc : count; +} +static DEVICE_ATTR(spi_prepare, S_IWUSR, NULL, spi_prepare_set); + +/** + * sysfs node for controlling whether the driver is allowed + * to wake up the platform on interrupt. + */ +static ssize_t wakeup_enable_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + + if (!strncmp(buf, "enable", strlen("enable"))) { + fpc1020->wakeup_enabled = true; + smp_wmb(); + } else if (!strncmp(buf, "disable", strlen("disable"))) { + fpc1020->wakeup_enabled = false; + smp_wmb(); + } else + return -EINVAL; + + return count; +} +static DEVICE_ATTR(wakeup_enable, S_IWUSR, NULL, wakeup_enable_set); + + +/** + * sysf node to check the interrupt status of the sensor, the interrupt + * handler should perform sysf_notify to allow userland to poll the node. + */ +static ssize_t irq_get(struct device *device, + struct device_attribute *attribute, + char *buffer) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(device); + int irq = gpio_get_value(fpc1020->irq_gpio); + return scnprintf(buffer, PAGE_SIZE, "%i\n", irq); +} + + +/** + * writing to the irq node will just drop a printk message + * and return success, used for latency measurement. + */ +static ssize_t irq_ack(struct device *device, + struct device_attribute *attribute, + const char *buffer, size_t count) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(device); + dev_dbg(fpc1020->dev, "%s\n", __func__); + return count; +} + +static DEVICE_ATTR(irq, S_IRUSR | S_IWUSR, irq_get, irq_ack); + +static ssize_t compatible_all_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc; + int i; + int irqf; + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + dev_err(dev, "compatible all enter %d\n", fpc1020->compatible_enabled); + if (!strncmp(buf, "enable", strlen("enable")) && fpc1020->compatible_enabled != 1) { + rc = fpc1020_request_named_gpio(fpc1020, "fpc,gpio_irq", + &fpc1020->irq_gpio); + if (rc) + goto exit; + + rc = fpc1020_request_named_gpio(fpc1020, "fpc,gpio_rst", + &fpc1020->rst_gpio); + if (rc) + goto exit; + fpc1020->fingerprint_pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(fpc1020->fingerprint_pinctrl)) { + if (PTR_ERR(fpc1020->fingerprint_pinctrl) == -EPROBE_DEFER) { + dev_info(dev, "pinctrl not ready\n"); + rc = -EPROBE_DEFER; + goto exit; + } + dev_err(dev, "Target does not use pinctrl\n"); + fpc1020->fingerprint_pinctrl = NULL; + rc = -EINVAL; + goto exit; + } + + for (i = 0; i < ARRAY_SIZE(fpc1020->pinctrl_state); i++) { + const char *n = pctl_names[i]; + struct pinctrl_state *state = + pinctrl_lookup_state(fpc1020->fingerprint_pinctrl, n); + if (IS_ERR(state)) { + dev_err(dev, "cannot find '%s'\n", n); + rc = -EINVAL; + goto exit; + } + dev_info(dev, "found pin control %s\n", n); + fpc1020->pinctrl_state[i] = state; + } + rc = select_pin_ctl(fpc1020, "fpc1020_reset_reset"); + if (rc) + goto exit; + rc = select_pin_ctl(fpc1020, "fpc1020_irq_active"); + if (rc) + goto exit; + irqf = IRQF_TRIGGER_RISING | IRQF_ONESHOT; + if (of_property_read_bool(dev->of_node, "fpc,enable-wakeup")) { + irqf |= IRQF_NO_SUSPEND; + device_init_wakeup(dev, 1); + } + rc = devm_request_threaded_irq(dev, gpio_to_irq(fpc1020->irq_gpio), + NULL, fpc1020_irq_handler, irqf, + dev_name(dev), fpc1020); + if (rc) { + dev_err(dev, "could not request irq %d\n", + gpio_to_irq(fpc1020->irq_gpio)); + goto exit; + } + dev_dbg(dev, "requested irq %d\n", gpio_to_irq(fpc1020->irq_gpio)); + + /* Request that the interrupt should be wakeable */ + enable_irq_wake(gpio_to_irq(fpc1020->irq_gpio)); + fpc1020->compatible_enabled = 1; + if (of_property_read_bool(dev->of_node, "fpc,enable-on-boot")) { + dev_info(dev, "Enabling hardware\n"); + (void)device_prepare(fpc1020, true); +#ifdef LINUX_CONTROL_SPI_CLK + (void)set_clks(fpc1020, false); +#endif + } + } else if (!strncmp(buf, "disable", strlen("disable")) && fpc1020->compatible_enabled != 0) { + if (gpio_is_valid(fpc1020->irq_gpio)) { + devm_gpio_free(dev, fpc1020->irq_gpio); + pr_info("remove irq_gpio success\n"); + } + if (gpio_is_valid(fpc1020->rst_gpio)) { + devm_gpio_free(dev, fpc1020->rst_gpio); + pr_info("remove rst_gpio success\n"); + } + devm_free_irq(dev, gpio_to_irq(fpc1020->irq_gpio), fpc1020); + fpc1020->compatible_enabled = 0; + } + hw_reset(fpc1020); + return count; +exit: + return -EINVAL; +} +static DEVICE_ATTR(compatible_all, S_IWUSR, NULL, compatible_all_set); + +static struct attribute *attributes[] = { + &dev_attr_pinctl_set.attr, + &dev_attr_spi_prepare.attr, + &dev_attr_hw_reset.attr, + &dev_attr_wakeup_enable.attr, + &dev_attr_compatible_all.attr, +#ifdef LINUX_CONTROL_SPI_CLK + &dev_attr_clk_enable.attr, +#endif + &dev_attr_irq.attr, + NULL +}; + +static const struct attribute_group attribute_group = { + .attrs = attributes, +}; + +static irqreturn_t fpc1020_irq_handler(int irq, void *handle) +{ + struct fpc1020_data *fpc1020 = handle; + dev_dbg(fpc1020->dev, "%s\n", __func__); + + /* Make sure 'wakeup_enabled' is updated before using it + ** since this is interrupt context (other thread...) */ + smp_rmb(); + + if (fpc1020->wakeup_enabled) { + wake_lock_timeout(&fpc1020->ttw_wl, + msecs_to_jiffies(FPC_TTW_HOLD_TIME)); + } + + sysfs_notify(&fpc1020->dev->kobj, NULL, dev_attr_irq.attr.name); + + return IRQ_HANDLED; +} + +static int fpc1020_request_named_gpio(struct fpc1020_data *fpc1020, + const char *label, int *gpio) +{ + struct device *dev = fpc1020->dev; + struct device_node *np = dev->of_node; + int rc = of_get_named_gpio(np, label, 0); + if (rc < 0) { + dev_err(dev, "failed to get '%s'\n", label); + return rc; + } + *gpio = rc; + rc = devm_gpio_request(dev, *gpio, label); + if (rc) { + dev_err(dev, "failed to request gpio %d\n", *gpio); + return rc; + } + dev_dbg(dev, "%s %d\n", label, *gpio); + return 0; +} + +static int fpc1020_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int rc = 0; + + struct device_node *np = dev->of_node; + + struct fpc1020_data *fpc1020 = devm_kzalloc(dev, sizeof(*fpc1020), + GFP_KERNEL); + if (!fpc1020) { + dev_err(dev, + "failed to allocate memory for struct fpc1020_data\n"); + rc = -ENOMEM; + goto exit; + } + + fpc1020->dev = dev; + dev_set_drvdata(dev, fpc1020); + + if (!np) { + dev_err(dev, "no of node found\n"); + rc = -EINVAL; + goto exit; + } + + +#ifdef LINUX_CONTROL_SPI_CLK + if (of_property_read_u32(dev->of_node, "fpc,spi-max-frequency", &fpc1020->max_speed_hz)) { + fpc1020->max_speed_hz = 4800000; + dev_err(dev, "%s: Failed to get spi-max-frequency\n", __func__); + } + + fpc1020->iface_clk = clk_get(dev, "iface_clk"); + if (IS_ERR(fpc1020->iface_clk)) { + dev_err(dev, "%s: Failed to get iface_clk\n", __func__); + rc = -EINVAL; + goto exit; + } + + fpc1020->core_clk = clk_get(dev, "core_clk"); + if (IS_ERR(fpc1020->core_clk)) { + dev_err(dev, "%s: Failed to get core_clk\n", __func__); + rc = -EINVAL; + goto exit; + } +#endif + + fpc1020->wakeup_enabled = false; +#ifdef LINUX_CONTROL_SPI_CLK + fpc1020->clocks_enabled = false; + fpc1020->clocks_suspended = false; +#endif + + mutex_init(&fpc1020->lock); + + wake_lock_init(&fpc1020->ttw_wl, WAKE_LOCK_SUSPEND, "fpc_ttw_wl"); + + rc = sysfs_create_group(&dev->kobj, &attribute_group); + if (rc) { + dev_err(dev, "could not create sysfs\n"); + goto exit; + } + + dev_info(dev, "%s: ok\n", __func__); +exit: + return rc; +} + +static int fpc1020_remove(struct platform_device *pdev) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(&pdev->dev); + + sysfs_remove_group(&pdev->dev.kobj, &attribute_group); + mutex_destroy(&fpc1020->lock); + wake_lock_destroy(&fpc1020->ttw_wl); + dev_info(&pdev->dev, "%s\n", __func__); + return 0; +} + +#ifdef LINUX_CONTROL_SPI_CLK +static int fpc1020_suspend(struct device *dev) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + + fpc1020->clocks_suspended = fpc1020->clocks_enabled; + set_clks(fpc1020, false); + return 0; +} + +static int fpc1020_resume(struct device *dev) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + + if (fpc1020->clocks_suspended) + set_clks(fpc1020, true); + + return 0; +} + +static const struct dev_pm_ops fpc1020_pm_ops = { + .suspend = fpc1020_suspend, + .resume = fpc1020_resume, +}; +#endif + +static struct of_device_id fpc1020_of_match[] = { + { .compatible = "fpc,fpc1020", }, + {} +}; +MODULE_DEVICE_TABLE(of, fpc1020_of_match); + +static struct platform_driver fpc1020_driver = { + .driver = { + .name = "fpc1020", + .owner = THIS_MODULE, + .of_match_table = fpc1020_of_match, +#ifdef LINUX_CONTROL_SPI_CLK + .pm = &fpc1020_pm_ops, +#endif + }, + .probe = fpc1020_probe, + .remove = fpc1020_remove, +}; + +static int __init fpc1020_init(void) +{ + int rc = platform_driver_register(&fpc1020_driver); + if (!rc) + pr_info("%s OK\n", __func__); + else + pr_err("%s %d\n", __func__, rc); + return rc; +} + +static void __exit fpc1020_exit(void) +{ + pr_info("%s\n", __func__); + platform_driver_unregister(&fpc1020_driver); +} + +module_init(fpc1020_init); +module_exit(fpc1020_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Aleksej Makarov"); +MODULE_AUTHOR("Henrik Tillman "); +MODULE_DESCRIPTION("FPC1020 Fingerprint sensor device driver."); diff --git a/drivers/input/fingerprint/goodix_mido/Kconfig b/drivers/input/fingerprint/goodix_mido/Kconfig new file mode 100644 index 0000000000000..6e55948f03ad9 --- /dev/null +++ b/drivers/input/fingerprint/goodix_mido/Kconfig @@ -0,0 +1,5 @@ +config FINGERPRINT_GOODIX_GF3208_MIDO + tristate "Goodix GF3208 fingerprint driver support" + depends on INPUT_FINGERPRINT + help + Say Y here to enable goodix fingerprint driver support! diff --git a/drivers/input/fingerprint/goodix_mido/Makefile b/drivers/input/fingerprint/goodix_mido/Makefile new file mode 100644 index 0000000000000..fa048cfb054c0 --- /dev/null +++ b/drivers/input/fingerprint/goodix_mido/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_FINGERPRINT_GOODIX_GF3208_MIDO) += gf_spi.o platform.o netlink.o diff --git a/drivers/input/fingerprint/goodix_mido/gf_spi.c b/drivers/input/fingerprint/goodix_mido/gf_spi.c new file mode 100644 index 0000000000000..49e5a2a0844cd --- /dev/null +++ b/drivers/input/fingerprint/goodix_mido/gf_spi.c @@ -0,0 +1,906 @@ + /*Simple synchronous userspace interface to SPI devices + * + * Copyright (C) 2006 SWAPP + * Andrea Paterniani + * Copyright (C) 2007 David Brownell (simplification, cleanup) + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gf_spi.h" + +#if defined(USE_SPI_BUS) +#include +#include +#elif defined(USE_PLATFORM_BUS) +#include +#endif + +#define GF_SPIDEV_NAME "goodix,fingerprint" +/*device name after register in charater*/ +#define GF_DEV_NAME "goodix_fp" +#define GF_INPUT_NAME "gf3208" /*"goodix_fp" */ + +#define CHRD_DRIVER_NAME "goodix_fp_spi" +#define CLASS_NAME "goodix_fp" +#define SPIDEV_MAJOR 225 /* assigned */ +#define N_SPI_MINORS 32 /* ... up to 256 */ + + +struct gf_key_map key_map[] = { + { "POWER", KEY_POWER }, + { "HOME" , KEY_HOME }, + { "MENU" , KEY_MENU }, + { "BACK" , KEY_BACK }, + { "UP" , KEY_UP }, + { "DOWN" , KEY_DOWN }, + { "LEFT" , KEY_LEFT }, + { "RIGHT", KEY_RIGHT }, + { "FORCE", KEY_F9 }, + { "CLICK", KEY_F19 }, + { "CAMERA", KEY_CAMERA }, +}; + +/**************************debug******************************/ +#define GF_DEBUG +/*#undef GF_DEBUG*/ + +#ifdef GF_DEBUG +#define gf_dbg(fmt, args...) do { \ + pr_warn("gf:" fmt, ##args);\ + } while (0) +#define FUNC_ENTRY() pr_warn("gf:%s, entry\n", __func__) +#define FUNC_EXIT() pr_warn("gf:%s, exit\n", __func__) +#else +#define gf_dbg(fmt, args...) +#define FUNC_ENTRY() +#define FUNC_EXIT() +#endif + +/*Global variables*/ +/*static MODE g_mode = GF_IMAGE_MODE;*/ +static DECLARE_BITMAP(minors, N_SPI_MINORS); +static LIST_HEAD(device_list); +static DEFINE_MUTEX(device_list_lock); +static struct gf_dev gf; +static struct class *gf_class; +static int driver_init_partial(struct gf_dev *gf_dev); + +static void gf_enable_irq(struct gf_dev *gf_dev) +{ + if (gf_dev->irq_enabled) { + pr_warn("IRQ has been enabled.\n"); + } else { + enable_irq(gf_dev->irq); + gf_dev->irq_enabled = 1; + } +} + +static void gf_disable_irq(struct gf_dev *gf_dev) +{ + if (gf_dev->irq_enabled) { + gf_dev->irq_enabled = 0; + disable_irq(gf_dev->irq); + } else { + pr_warn("IRQ has been disabled.\n"); + } +} + +#ifdef AP_CONTROL_CLK +static long spi_clk_max_rate(struct clk *clk, unsigned long rate) +{ + long lowest_available, nearest_low, step_size, cur; + long step_direction = -1; + long guess = rate; + int max_steps = 10; + + cur = clk_round_rate(clk, rate); + if (cur == rate) + return rate; + + /* if we got here then: cur > rate */ + lowest_available = clk_round_rate(clk, 0); + if (lowest_available > rate) + return -EINVAL; + + step_size = (rate - lowest_available) >> 1; + nearest_low = lowest_available; + + while (max_steps-- && step_size) { + guess += step_size * step_direction; + cur = clk_round_rate(clk, guess); + + if ((cur < rate) && (cur > nearest_low)) + nearest_low = cur; + /* + * if we stepped too far, then start stepping in the other + * direction with half the step size + */ + if (((cur > rate) && (step_direction > 0)) + || ((cur < rate) && (step_direction < 0))) { + step_direction = -step_direction; + step_size >>= 1; + } + } + return nearest_low; +} + +static void spi_clock_set(struct gf_dev *gf_dev, int speed) +{ + long rate; + int rc; + + rate = spi_clk_max_rate(gf_dev->core_clk, speed); + if (rate < 0) { + pr_info("%s: no match found for requested clock frequency:%d", + __func__, speed); + return; + } + + rc = clk_set_rate(gf_dev->core_clk, rate); +} + +static int gfspi_ioctl_clk_init(struct gf_dev *data) +{ + pr_debug("%s: enter\n", __func__); + + data->clk_enabled = 0; + data->core_clk = clk_get(&data->spi->dev, "core_clk"); + if (IS_ERR_OR_NULL(data->core_clk)) { + pr_err("%s: fail to get core_clk\n", __func__); + return -EPERM; + } + data->iface_clk = clk_get(&data->spi->dev, "iface_clk"); + if (IS_ERR_OR_NULL(data->iface_clk)) { + pr_err("%s: fail to get iface_clk\n", __func__); + clk_put(data->core_clk); + data->core_clk = NULL; + return -ENOENT; + } + return 0; +} + +static int gfspi_ioctl_clk_enable(struct gf_dev *data) +{ + int err; + + pr_debug("%s: enter\n", __func__); + + if (data->clk_enabled) + return 0; + + err = clk_prepare_enable(data->core_clk); + if (err) { + pr_err("%s: fail to enable core_clk\n", __func__); + return -EPERM; + } + + err = clk_prepare_enable(data->iface_clk); + if (err) { + pr_err("%s: fail to enable iface_clk\n", __func__); + clk_disable_unprepare(data->core_clk); + return -ENOENT; + } + + data->clk_enabled = 1; + + return 0; +} + +static int gfspi_ioctl_clk_disable(struct gf_dev *data) +{ + pr_debug("%s: enter\n", __func__); + + if (!data->clk_enabled) + return 0; + + clk_disable_unprepare(data->core_clk); + clk_disable_unprepare(data->iface_clk); + data->clk_enabled = 0; + + return 0; +} + +static int gfspi_ioctl_clk_uninit(struct gf_dev *data) +{ + pr_debug("%s: enter\n", __func__); + + if (data->clk_enabled) + gfspi_ioctl_clk_disable(data); + + if (!IS_ERR_OR_NULL(data->core_clk)) { + clk_put(data->core_clk); + data->core_clk = NULL; + } + + if (!IS_ERR_OR_NULL(data->iface_clk)) { + clk_put(data->iface_clk); + data->iface_clk = NULL; + } + + return 0; +} +#endif + +static long gf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct gf_dev *gf_dev = &gf; + struct gf_key gf_key = { 0 }; + int retval = 0; + int i; +#ifdef AP_CONTROL_CLK + unsigned int speed = 0; +#endif + FUNC_ENTRY(); + if (_IOC_TYPE(cmd) != GF_IOC_MAGIC) + return -ENODEV; + + if (_IOC_DIR(cmd) & _IOC_READ) + retval = + !access_ok(VERIFY_WRITE, (void __user *)arg, + _IOC_SIZE(cmd)); + if ((retval == 0) && (_IOC_DIR(cmd) & _IOC_WRITE)) + retval = + !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); + if (retval) + return -EFAULT; + + if (gf_dev->device_available == 0) { + if ((cmd == GF_IOC_POWER_ON) || (cmd == GF_IOC_POWER_OFF) || (cmd == GF_IOC_ENABLE_GPIO)) + pr_info("power cmd\n"); + else { + pr_info("Sensor is power off currently. \n"); + return -ENODEV; + } + } + + switch (cmd) { + case GF_IOC_ENABLE_GPIO: + driver_init_partial(gf_dev); + break; + case GF_IOC_RELEASE_GPIO: + gf_cleanup(gf_dev); + break; + case GF_IOC_DISABLE_IRQ: + gf_disable_irq(gf_dev); + break; + case GF_IOC_ENABLE_IRQ: + gf_enable_irq(gf_dev); + break; + case GF_IOC_SETSPEED: +#ifdef AP_CONTROL_CLK + retval = __get_user(speed, (u32 __user *) arg); + if (retval == 0) { + if (speed > 8 * 1000 * 1000) { + pr_warn("Set speed:%d is larger than 8Mbps.\n", speed); + } else { + spi_clock_set(gf_dev, speed); + } + } else { + pr_warn("Failed to get speed from user. retval = %d\n", retval); + } +#else + pr_info("This kernel doesn't support control clk in AP\n"); +#endif + break; + case GF_IOC_RESET: + gf_hw_reset(gf_dev, 3); + break; + case GF_IOC_COOLBOOT: + gf_power_off(gf_dev); + mdelay(5); + gf_power_on(gf_dev); + break; + case GF_IOC_SENDKEY: + if (copy_from_user + (&gf_key, (struct gf_key *)arg, sizeof(struct gf_key))) { + pr_warn("Failed to copy data from user space.\n"); + retval = -EFAULT; + break; + } + + for (i = 0; i < ARRAY_SIZE(key_map); i++) { + if (key_map[i].val == gf_key.key) { + if (KEY_CAMERA == gf_key.key) { + printk("lihao send camera key!\n"); + input_report_key(gf_dev->input, KEY_SELECT, gf_key.value); + input_sync(gf_dev->input); + } else { + input_report_key(gf_dev->input, gf_key.key, gf_key.value); + input_sync(gf_dev->input); + } + break; + } + } + + if (i == ARRAY_SIZE(key_map)) { + pr_warn("key %d not support yet \n", gf_key.key); + retval = -EFAULT; + } + + break; + case GF_IOC_CLK_READY: +#ifdef AP_CONTROL_CLK + gfspi_ioctl_clk_enable(gf_dev); +#else + pr_info("Doesn't support control clock.\n"); +#endif + break; + case GF_IOC_CLK_UNREADY: +#ifdef AP_CONTROL_CLK + gfspi_ioctl_clk_disable(gf_dev); +#else + pr_info("Doesn't support control clock.\n"); +#endif + break; + case GF_IOC_PM_FBCABCK: + __put_user(gf_dev->fb_black, (u8 __user *) arg); + break; + case GF_IOC_POWER_ON: + if (gf_dev->device_available == 1) + pr_info("Sensor has already powered-on.\n"); + else + gf_power_on(gf_dev); + gf_dev->device_available = 1; + break; + case GF_IOC_POWER_OFF: + if (gf_dev->device_available == 0) + pr_info("Sensor has already powered-off.\n"); + else + gf_power_off(gf_dev); + gf_dev->device_available = 0; + break; + default: + gf_dbg("Unsupport cmd:0x%x\n", cmd); + break; + } + + FUNC_EXIT(); + return retval; +} + +#ifdef CONFIG_COMPAT +static long +gf_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return gf_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); +} +#endif /*CONFIG_COMPAT*/ + +static irqreturn_t gf_irq(int irq, void *handle) +{ + +#if defined(GF_NETLINK_ENABLE) + + struct gf_dev *gf_dev = &gf; + char temp = GF_NET_EVENT_IRQ; + gf_dbg("enter irq %s\n", __func__); + + wake_lock_timeout(&gf_dev->ttw_wl, msecs_to_jiffies(1000)); + + sendnlmsg(&temp); +#elif defined (GF_FASYNC) + + struct gf_dev *gf_dev = &gf; + if (gf_dev->async) + kill_fasync(&gf_dev->async, SIGIO, POLL_IN); +#endif + + return IRQ_HANDLED; + +} + +static int driver_init_partial(struct gf_dev *gf_dev) +{ + int ret = 0; + FUNC_ENTRY(); + pr_warn("--------driver_init_partial start.--------\n"); + + gf_dev->device_available = 1; + + if (gf_parse_dts(gf_dev)) + goto error; + + gf_dev->irq = gf_irq_num(gf_dev); + ret = devm_request_threaded_irq(&gf_dev->spi->dev, + gf_dev->irq, + NULL, + gf_irq, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "gf", gf_dev); + if (ret) { + pr_err("Could not request irq %d\n", gpio_to_irq(gf_dev->irq_gpio)); + goto error; + } + if (!ret) { + enable_irq_wake(gf_dev->irq); + gf_enable_irq(gf_dev); + gf_disable_irq(gf_dev); + } + gf_hw_reset(gf_dev, 360); + + FUNC_EXIT(); + return 0; + +error: + + gf_cleanup(gf_dev); + + gf_dev->device_available = 0; + + return -EPERM; + + +} +static int gf_open(struct inode *inode, struct file *filp) +{ + struct gf_dev *gf_dev; + int status = -ENXIO; + + FUNC_ENTRY(); + mutex_lock(&device_list_lock); + + list_for_each_entry(gf_dev, &device_list, device_entry) { + if (gf_dev->devt == inode->i_rdev) { + gf_dbg("Found\n"); + status = 0; + break; + } + } + + if (status == 0) { + if (status == 0) { + gf_dev->users++; + filp->private_data = gf_dev; + nonseekable_open(inode, filp); + gf_dbg("Succeed to open device. irq = %d\n", + gf_dev->irq); + /*power the sensor*/ + gf_dev->device_available = 1; + } + } else { + gf_dbg("No device for minor %d\n", iminor(inode)); + } + mutex_unlock(&device_list_lock); + FUNC_EXIT(); + return status; +} + +#ifdef GF_FASYNC +static int gf_fasync(int fd, struct file *filp, int mode) +{ + struct gf_dev *gf_dev = filp->private_data; + int ret; + + FUNC_ENTRY(); + ret = fasync_helper(fd, filp, mode, &gf_dev->async); + FUNC_EXIT(); + gf_dbg("ret = %d\n", ret); + return ret; +} +#endif + +static int gf_release(struct inode *inode, struct file *filp) +{ + struct gf_dev *gf_dev; + int status = 0; + + FUNC_ENTRY(); + mutex_lock(&device_list_lock); + gf_dev = filp->private_data; + filp->private_data = NULL; + + gf_dev->users--; + if (!gf_dev->users) { + + gf_dbg("disble_irq. irq = %d\n", gf_dev->irq); + gf_disable_irq(gf_dev); + + + devm_free_irq(&gf_dev->spi->dev, gf_dev->irq, gf_dev); + + + + /*power off the sensor*/ + gf_dev->device_available = 0; + gf_power_off(gf_dev); + } + mutex_unlock(&device_list_lock); + FUNC_EXIT(); + + return status; +} + +static const struct file_operations gf_fops = { + .owner = THIS_MODULE, + /* REVISIT switch to aio primitives, so that userspace + * gets more complete API coverage. It'll simplify things + * too, except for the locking. + */ + .unlocked_ioctl = gf_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = gf_compat_ioctl, +#endif /*CONFIG_COMPAT*/ + .open = gf_open, + .release = gf_release, +#ifdef GF_FASYNC + .fasync = gf_fasync, +#endif +}; + +static int goodix_fb_state_chg_callback(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct gf_dev *gf_dev; + struct fb_event *evdata = data; + unsigned int blank; + +#if defined(GF_NETLINK_ENABLE) + char temp = 0; +#endif + + if (val != FB_EARLY_EVENT_BLANK) + return 0; + pr_info("[info] %s go to the goodix_fb_state_chg_callback value = %d\n", + __func__, (int)val); + gf_dev = container_of(nb, struct gf_dev, notifier); + if (evdata && evdata->data && val == FB_EARLY_EVENT_BLANK && gf_dev) { + blank = *(int *)(evdata->data); + switch (blank) { + case FB_BLANK_POWERDOWN: + if (gf_dev->device_available == 1) { + gf_dev->fb_black = 1; +#if defined(GF_NETLINK_ENABLE) + temp = GF_NET_EVENT_FB_BLACK; + sendnlmsg(&temp); +#elif defined (GF_FASYNC) + if (gf_dev->async) { + kill_fasync(&gf_dev->async, SIGIO, + POLL_IN); + } +#endif + /*device unavailable */ + + } + break; + case FB_BLANK_UNBLANK: + if (gf_dev->device_available == 1) { + gf_dev->fb_black = 0; +#if defined(GF_NETLINK_ENABLE) + temp = GF_NET_EVENT_FB_UNBLACK; + sendnlmsg(&temp); +#elif defined (GF_FASYNC) + if (gf_dev->async) { + kill_fasync(&gf_dev->async, SIGIO, + POLL_IN); + } +#endif + /*device available */ + + } + break; + default: + pr_info("%s defalut\n", __func__); + break; + } + } + return NOTIFY_OK; +} + +static struct notifier_block goodix_noti_block = { + .notifier_call = goodix_fb_state_chg_callback, +}; + +static void gf_reg_key_kernel(struct gf_dev *gf_dev) +{ + int i; + + set_bit(EV_KEY, gf_dev->input->evbit); + for (i = 0; i < ARRAY_SIZE(key_map); i++) { + set_bit(key_map[i].val, gf_dev->input->keybit); + } + set_bit(KEY_SELECT, gf_dev->input->keybit); + gf_dev->input->name = GF_INPUT_NAME; + if (input_register_device(gf_dev->input)) + pr_warn("Failed to register GF as input device.\n"); +} + + +#if defined(USE_SPI_BUS) +static int gf_probe(struct spi_device *spi) +#elif defined(USE_PLATFORM_BUS) +static int gf_probe(struct platform_device *pdev) +#endif +{ + struct gf_dev *gf_dev = &gf; + int status = -EINVAL; + unsigned long minor; + + FUNC_ENTRY(); + + pr_warn("--------gf_probe start.--------\n"); + /* Initialize the driver data */ + INIT_LIST_HEAD(&gf_dev->device_entry); + +#if defined(USE_SPI_BUS) + gf_dev->spi = spi; +#elif defined(USE_PLATFORM_BUS) + gf_dev->spi = pdev; +#endif + + gf_dev->irq_gpio = -EINVAL; + gf_dev->reset_gpio = -EINVAL; + gf_dev->pwr_gpio = -EINVAL; + gf_dev->device_available = 0; + gf_dev->fb_black = 0; + gf_dev->irq_enabled = 0; + gf_dev->fingerprint_pinctrl = NULL; + + /* If we can allocate a minor number, hook up this device. + * Reusing minors is fine so long as udev or mdev is working. + */ + mutex_lock(&device_list_lock); + minor = find_first_zero_bit(minors, N_SPI_MINORS); + if (minor < N_SPI_MINORS) { + struct device *dev; + + gf_dev->devt = MKDEV(SPIDEV_MAJOR, minor); + dev = device_create(gf_class, &gf_dev->spi->dev, gf_dev->devt, + gf_dev, GF_DEV_NAME); + status = IS_ERR(dev) ? PTR_ERR(dev) : 0; + } else { + dev_dbg(&gf_dev->spi->dev, "no minor number available!\n"); + status = -ENODEV; + } + + if (status == 0) { + set_bit(minor, minors); + list_add(&gf_dev->device_entry, &device_list); + } else { + gf_dev->devt = 0; + } + mutex_unlock(&device_list_lock); + + if (status == 0) { + /*input device subsystem */ + gf_dev->input = input_allocate_device(); + if (gf_dev->input == NULL) { + dev_dbg(&gf_dev->input->dev, + "Faile to allocate input device.\n"); + status = -ENOMEM; + goto error; + } +#ifdef AP_CONTROL_CLK + pr_info("Get the clk resource.\n"); + /* Enable spi clock */ + if (gfspi_ioctl_clk_init(gf_dev)) + goto gfspi_probe_clk_init_failed; + + + if (gfspi_ioctl_clk_enable(gf_dev)) + goto gfspi_probe_clk_enable_failed; + + spi_clock_set(gf_dev, 4.8*1000*1000); +#endif + + gf_dev->notifier = goodix_noti_block; + fb_register_client(&gf_dev->notifier); + gf_reg_key_kernel(gf_dev); + + wake_lock_init(&gf_dev->ttw_wl, WAKE_LOCK_SUSPEND, "goodix_ttw_wl"); + } + + pr_warn("--------gf_probe end---OK.--------\n"); + return status; + +error: + gf_cleanup(gf_dev); + gf_dev->device_available = 0; + if (gf_dev->devt != 0) { + pr_info("Err: status = %d\n", status); + mutex_lock(&device_list_lock); + list_del(&gf_dev->device_entry); + device_destroy(gf_class, gf_dev->devt); + clear_bit(MINOR(gf_dev->devt), minors); + mutex_unlock(&device_list_lock); + +#ifdef AP_CONTROL_CLK +gfspi_probe_clk_enable_failed: + gfspi_ioctl_clk_uninit(gf_dev); +gfspi_probe_clk_init_failed: +#endif + if (gf_dev->input != NULL) + input_unregister_device(gf_dev->input); + } + + FUNC_EXIT(); + return status; +} + +#if defined(USE_SPI_BUS) +static int gf_remove(struct spi_device *spi) +#elif defined(USE_PLATFORM_BUS) +static int gf_remove(struct platform_device *pdev) +#endif +{ + struct gf_dev *gf_dev = &gf; + FUNC_ENTRY(); + + /* make sure ops on existing fds can abort cleanly */ + if (gf_dev->irq) + free_irq(gf_dev->irq, gf_dev); + + if (gf_dev->input != NULL) + input_unregister_device(gf_dev->input); + input_free_device(gf_dev->input); + + /* prevent new opens */ + mutex_lock(&device_list_lock); + list_del(&gf_dev->device_entry); + device_destroy(gf_class, gf_dev->devt); + clear_bit(MINOR(gf_dev->devt), minors); + if (gf_dev->users == 0) + kfree(gf_dev); + + mutex_unlock(&device_list_lock); + + wake_lock_destroy(&gf_dev->ttw_wl); + + FUNC_EXIT(); + return 0; +} + +#if defined(USE_SPI_BUS) +static int gf_suspend(struct spi_device *spi, pm_message_t mesg) +#elif defined(USE_PLATFORM_BUS) +static int gf_suspend(struct platform_device *pdev, pm_message_t state) +#endif +{ + + gf_dbg("gf_suspend_test.\n"); + return 0; +} + +#if defined(USE_SPI_BUS) +static int gf_resume(struct spi_device *spi) +#elif defined(USE_PLATFORM_BUS) +static int gf_resume(struct platform_device *pdev) +#endif +{ + gf_dbg("gf_resume_test.\n"); + return 0; +} + +static struct of_device_id gx_match_table[] = { + {.compatible = GF_SPIDEV_NAME,}, + {}, +}; + +#if defined(USE_SPI_BUS) +static struct spi_driver gf_driver = { +#elif defined(USE_PLATFORM_BUS) +static struct platform_driver gf_driver = { +#endif + .driver = { + .name = GF_DEV_NAME, + .owner = THIS_MODULE, +#if defined(USE_SPI_BUS) + +#endif + .of_match_table = gx_match_table, + }, + .probe = gf_probe, + .remove = gf_remove, + .suspend = gf_suspend, + .resume = gf_resume, +}; + +static int __init gf_init(void) +{ + int status; + FUNC_ENTRY(); + + pr_warn("--------gf_init start.--------\n"); + /* Claim our 256 reserved device numbers. Then register a class + * that will key udev/mdev to add/remove /dev nodes. Last, register + * the driver which manages those device numbers. + */ + + BUILD_BUG_ON(N_SPI_MINORS > 256); + status = register_chrdev(SPIDEV_MAJOR, CHRD_DRIVER_NAME, &gf_fops); + if (status < 0) { + pr_warn("Failed to register char device!\n"); + FUNC_EXIT(); + return status; + } + gf_class = class_create(THIS_MODULE, CLASS_NAME); + if (IS_ERR(gf_class)) { + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name); + pr_warn("Failed to create class.\n"); + FUNC_EXIT(); + return PTR_ERR(gf_class); + } +#if defined(USE_PLATFORM_BUS) + status = platform_driver_register(&gf_driver); +#elif defined(USE_SPI_BUS) + status = spi_register_driver(&gf_driver); +#endif + if (status < 0) { + class_destroy(gf_class); + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name); + pr_warn("Failed to register SPI driver.\n"); + } + +#ifdef GF_NETLINK_ENABLE + netlink_init(); +#endif + pr_info(" status = 0x%x\n", status); + FUNC_EXIT(); + + pr_warn("--------gf_init end---OK.--------\n"); + return 0; +} + +module_init(gf_init); + +static void __exit gf_exit(void) +{ + FUNC_ENTRY(); +#ifdef GF_NETLINK_ENABLE + netlink_exit(); +#endif +#if defined(USE_PLATFORM_BUS) + platform_driver_unregister(&gf_driver); +#elif defined(USE_SPI_BUS) + spi_unregister_driver(&gf_driver); +#endif + class_destroy(gf_class); + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name); + FUNC_EXIT(); +} + +module_exit(gf_exit); + +MODULE_AUTHOR("Jiangtao Yi, "); +MODULE_DESCRIPTION("User mode SPI device interface"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:gf-spi"); diff --git a/drivers/input/fingerprint/goodix_mido/gf_spi.h b/drivers/input/fingerprint/goodix_mido/gf_spi.h new file mode 100644 index 0000000000000..577e88444b641 --- /dev/null +++ b/drivers/input/fingerprint/goodix_mido/gf_spi.h @@ -0,0 +1,106 @@ +#ifndef __GF_SPI_H +#define __GF_SPI_H + +#include +#include +#include +/**********************************************************/ +enum FP_MODE{ + GF_IMAGE_MODE = 0, + GF_KEY_MODE, + GF_SLEEP_MODE, + GF_FF_MODE, + GF_DEBUG_MODE = 0x56 +}; + +struct gf_key { + unsigned int key; + int value; +}; + + +struct gf_key_map { + char *name; + unsigned short val; +}; + +#define GF_IOC_MAGIC 'G' +#define GF_IOC_DISABLE_IRQ _IO(GF_IOC_MAGIC, 0) +#define GF_IOC_ENABLE_IRQ _IO(GF_IOC_MAGIC, 1) +#define GF_IOC_SETSPEED _IOW(GF_IOC_MAGIC, 2, unsigned int) +#define GF_IOC_RESET _IO(GF_IOC_MAGIC, 3) +#define GF_IOC_COOLBOOT _IO(GF_IOC_MAGIC, 4) +#define GF_IOC_SENDKEY _IOW(GF_IOC_MAGIC, 5, struct gf_key) +#define GF_IOC_CLK_READY _IO(GF_IOC_MAGIC, 6) +#define GF_IOC_CLK_UNREADY _IO(GF_IOC_MAGIC, 7) +#define GF_IOC_PM_FBCABCK _IO(GF_IOC_MAGIC, 8) +#define GF_IOC_POWER_ON _IO(GF_IOC_MAGIC, 9) +#define GF_IOC_POWER_OFF _IO(GF_IOC_MAGIC, 10) +#define GF_IOC_ENABLE_GPIO _IO(GF_IOC_MAGIC, 11) +#define GF_IOC_RELEASE_GPIO _IO(GF_IOC_MAGIC, 12) + +#define GF_IOC_MAXNR 13 + + +#define USE_PLATFORM_BUS 1 + + +#define GF_NETLINK_ENABLE 1 +#define GF_NET_EVENT_IRQ 0 +#define GF_NET_EVENT_FB_BLACK 1 +#define GF_NET_EVENT_FB_UNBLACK 2 + + +static const char * const pctl_names[] = { + + "goodixfp_reset_reset", + "goodixfp_reset_active", + "goodixfp_irq_active", +}; + + +struct gf_dev { + dev_t devt; + struct list_head device_entry; +#if defined(USE_SPI_BUS) + struct spi_device *spi; +#elif defined(USE_PLATFORM_BUS) + struct platform_device *spi; +#endif + struct clk *core_clk; + struct clk *iface_clk; + + struct pinctrl *fingerprint_pinctrl; + struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)]; + + struct input_dev *input; + /* buffer is NULL unless this device is open (users > 0) */ + unsigned users; + signed irq_gpio; + signed reset_gpio; + signed pwr_gpio; + int irq; + int irq_enabled; + int clk_enabled; +#ifdef GF_FASYNC + struct fasync_struct *async; +#endif + struct notifier_block notifier; + char device_available; + char fb_black; + struct wake_lock ttw_wl; +}; + +int gf_parse_dts(struct gf_dev *gf_dev); +void gf_cleanup(struct gf_dev *gf_dev); + +int gf_power_on(struct gf_dev *gf_dev); +int gf_power_off(struct gf_dev *gf_dev); + +int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms); +int gf_irq_num(struct gf_dev *gf_dev); + +void sendnlmsg(char *message); +int netlink_init(void); +void netlink_exit(void); +#endif /*__GF_SPI_H*/ diff --git a/drivers/input/fingerprint/goodix_mido/netlink.c b/drivers/input/fingerprint/goodix_mido/netlink.c new file mode 100644 index 0000000000000..24b03024c5b99 --- /dev/null +++ b/drivers/input/fingerprint/goodix_mido/netlink.c @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include +#include +#include + +#define NETLINK_TEST 25 +#define MAX_MSGSIZE 4 * 1024 +int stringlength(char *s); +void sendnlmsg(char *message); +int pid; +int err; +struct sock *nl_sk = NULL; +int flag = 0; + +struct gf_uk_channel { + int channel_id; + int reserved; + char buf[3*1024]; + int len; +}; + +void sendnlmsg(char *message) +{ + struct sk_buff *skb_1; + struct nlmsghdr *nlh; + int len = NLMSG_SPACE(MAX_MSGSIZE); + int slen = 0; + if (!message || !nl_sk) + return ; + skb_1 = alloc_skb(len, GFP_KERNEL); + if (!skb_1) + printk(KERN_ERR "my_net_link:alloc_skb_1 error\n"); + slen = strlen(message); + nlh = nlmsg_put(skb_1, 0, 0, 0, MAX_MSGSIZE, 0); + + NETLINK_CB(skb_1).portid = 0; + NETLINK_CB(skb_1).dst_group = 0; + + message[slen] = '\0'; + memcpy(NLMSG_DATA(nlh), message, slen+1); + + netlink_unicast(nl_sk, skb_1, pid, MSG_DONTWAIT); +} + +void nl_data_ready(struct sk_buff *__skb) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + char str[100]; + skb = skb_get (__skb); + if (skb->len >= NLMSG_SPACE(0)) { + nlh = nlmsg_hdr(skb); + memcpy(str, NLMSG_DATA(nlh), sizeof(str)); + pid = nlh->nlmsg_pid; + kfree_skb(skb); + } +} + +int netlink_init(void) +{ + struct netlink_kernel_cfg netlink_cfg; + netlink_cfg.groups = 0; + netlink_cfg.flags = 0; + netlink_cfg.input = nl_data_ready; + netlink_cfg.cb_mutex = NULL; + + nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, &netlink_cfg); + + if (!nl_sk) { + printk(KERN_ERR "my_net_link: create netlink socket error.\n"); + return 1; + } + + return 0; +} + +void netlink_exit(void) +{ + if (nl_sk != NULL) { + sock_release(nl_sk->sk_socket); + } + + printk("my_net_link: self module exited\n"); +} diff --git a/drivers/input/fingerprint/goodix_mido/platform.c b/drivers/input/fingerprint/goodix_mido/platform.c new file mode 100644 index 0000000000000..a5b39e4eaac9f --- /dev/null +++ b/drivers/input/fingerprint/goodix_mido/platform.c @@ -0,0 +1,202 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gf_spi.h" + +#if defined(USE_SPI_BUS) +#include +#include +#elif defined(USE_PLATFORM_BUS) +#include +#endif + +#define gf_dbg(fmt, args...) do { \ + pr_warn("gf:" fmt, ##args);\ + } while (0) + + +static int gf3208_request_named_gpio(struct gf_dev *gf_dev, const char *label, int *gpio) +{ + struct device *dev = &gf_dev->spi->dev; + struct device_node *np = dev->of_node; + int rc = of_get_named_gpio(np, label, 0); + if (rc < 0) { + dev_err(dev, "failed to get '%s'\n", label); + return rc; + } + *gpio = rc; + rc = devm_gpio_request(dev, *gpio, label); + if (rc) { + dev_err(dev, "failed to request gpio %d\n", *gpio); + return rc; + } + dev_err(dev, "%s %d\n", label, *gpio); + return 0; +} + +static int select_pin_ctl(struct gf_dev *gf_dev, const char *name) +{ + size_t i; + int rc; + struct device *dev = &gf_dev->spi->dev; + + for (i = 0; i < ARRAY_SIZE(gf_dev->pinctrl_state); i++) { + const char *n = pctl_names[i]; + if (!strncmp(n, name, strlen(n))) { + rc = pinctrl_select_state(gf_dev->fingerprint_pinctrl, gf_dev->pinctrl_state[i]); + + if (rc) + dev_err(dev, "cannot select '%s'\n", name); + else + dev_err(dev, "Selected '%s'\n", name); + goto exit; + } + } + rc = -EINVAL; + dev_err(dev, "%s:'%s' not found\n", __func__, name); +exit: + return rc; +} + + +/*GPIO pins reference.*/ +int gf_parse_dts(struct gf_dev *gf_dev) +{ + int rc = 0; + int i = 0; + pr_warn("--------gf_parse_dts start.--------\n"); + + /*get reset resource*/ + rc = gf3208_request_named_gpio(gf_dev, "goodix,gpio_reset", &gf_dev->reset_gpio); + if (rc) { + gf_dbg("Failed to request RESET GPIO. rc = %d\n", rc); + return -EPERM; + } + + /*get irq resourece*/ + rc = gf3208_request_named_gpio(gf_dev, "goodix,gpio_irq", &gf_dev->irq_gpio); + if (rc) { + + gf_dbg("Failed to request IRQ GPIO. rc = %d\n", rc); + return -EPERM; + } + + + gf_dev->fingerprint_pinctrl = devm_pinctrl_get(&gf_dev->spi->dev); + for (i = 0; i < ARRAY_SIZE(gf_dev->pinctrl_state); i++) { + const char *n = pctl_names[i]; + struct pinctrl_state *state = + pinctrl_lookup_state(gf_dev->fingerprint_pinctrl, n); + if (IS_ERR(state)) { + pr_err("cannot find '%s'\n", n); + rc = -EINVAL; + } + pr_info("found pin control %s\n", n); + gf_dev->pinctrl_state[i] = state; + } + + rc = select_pin_ctl(gf_dev, "goodixfp_reset_active"); + if (rc) + goto exit; + rc = select_pin_ctl(gf_dev, "goodixfp_irq_active"); + if (rc) + goto exit; + + pr_warn("--------gf_parse_dts end---OK.--------\n"); + +exit: + return rc; + +} + +void gf_cleanup(struct gf_dev *gf_dev) +{ + gf_dbg("[info] enter%s\n", __func__); + + if (gpio_is_valid(gf_dev->irq_gpio)) { + devm_gpio_free(&gf_dev->spi->dev, gf_dev->irq_gpio); + gf_dbg("remove irq_gpio success\n"); + } + + if (gpio_is_valid(gf_dev->reset_gpio)) { + + devm_gpio_free(&gf_dev->spi->dev, gf_dev->reset_gpio); + gf_dbg("remove reset_gpio success\n"); + } + + if (gf_dev->fingerprint_pinctrl != NULL) { + devm_pinctrl_put(gf_dev->fingerprint_pinctrl); + gf_dev->fingerprint_pinctrl = NULL; + + gf_dbg("gx fingerprint_pinctrl release success\n"); + } +} + +/*power management*/ +int gf_power_on(struct gf_dev *gf_dev) +{ + int rc = 0; + msleep(10); + pr_info("---- power on ok ----\n"); + + return rc; +} + +int gf_power_off(struct gf_dev *gf_dev) +{ + int rc = 0; + pr_info("---- power off ----\n"); + return rc; +} + +static int hw_reset(struct gf_dev *gf_dev) +{ + int irq_gpio; + struct device *dev = &gf_dev->spi->dev; + + int rc = select_pin_ctl(gf_dev, "goodixfp_reset_reset"); + if (rc) + goto exit; + mdelay(3); + + rc = select_pin_ctl(gf_dev, "goodixfp_reset_active"); + if (rc) + goto exit; + + irq_gpio = gpio_get_value(gf_dev->irq_gpio); + dev_info(dev, "IRQ after reset %d\n", irq_gpio); +exit: + return rc; +} + + +/******************************************************************** + *CPU output low level in RST pin to reset GF. This is the MUST action for GF. + *Take care of this function. IO Pin driver strength / glitch and so on. + ********************************************************************/ +int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms) +{ + if (gf_dev == NULL) { + pr_info("Input buff is NULL.\n"); + return -EPERM; + } + hw_reset(gf_dev); + mdelay(delay_ms); + return 0; +} + +int gf_irq_num(struct gf_dev *gf_dev) +{ + if (gf_dev == NULL) { + pr_info("Input buff is NULL.\n"); + return -EPERM; + } else { + return gpio_to_irq(gf_dev->irq_gpio); + } +} + From d894b9afe29e821f48f2fe05158b289e1846ecfe Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Mon, 19 Mar 2018 20:39:04 +0530 Subject: [PATCH 202/508] drivers: input: fingerprint: Import tissot drivers --- drivers/input/fingerprint/Kconfig | 2 + drivers/input/fingerprint/Makefile | 2 + drivers/input/fingerprint/fpc_tissot/Kconfig | 5 + drivers/input/fingerprint/fpc_tissot/Makefile | 1 + .../fingerprint/fpc_tissot/fpc1020_tee.c | 767 ++++++++++++ .../input/fingerprint/goodix_tissot/Kconfig | 5 + .../input/fingerprint/goodix_tissot/Makefile | 1 + .../input/fingerprint/goodix_tissot/gf_spi.c | 1038 +++++++++++++++++ .../input/fingerprint/goodix_tissot/gf_spi.h | 163 +++ .../input/fingerprint/goodix_tissot/netlink.c | 108 ++ .../fingerprint/goodix_tissot/platform.c | 202 ++++ include/uapi/linux/input-event-codes.h | 7 + 12 files changed, 2301 insertions(+) create mode 100644 drivers/input/fingerprint/fpc_tissot/Kconfig create mode 100644 drivers/input/fingerprint/fpc_tissot/Makefile create mode 100644 drivers/input/fingerprint/fpc_tissot/fpc1020_tee.c create mode 100644 drivers/input/fingerprint/goodix_tissot/Kconfig create mode 100644 drivers/input/fingerprint/goodix_tissot/Makefile create mode 100644 drivers/input/fingerprint/goodix_tissot/gf_spi.c create mode 100644 drivers/input/fingerprint/goodix_tissot/gf_spi.h create mode 100644 drivers/input/fingerprint/goodix_tissot/netlink.c create mode 100644 drivers/input/fingerprint/goodix_tissot/platform.c diff --git a/drivers/input/fingerprint/Kconfig b/drivers/input/fingerprint/Kconfig index 9331a96068b6f..687363bf446e1 100644 --- a/drivers/input/fingerprint/Kconfig +++ b/drivers/input/fingerprint/Kconfig @@ -4,3 +4,5 @@ config INPUT_FINGERPRINT Say Y here to enable goodix fingerprint driver support! source "drivers/input/fingerprint/goodix_mido/Kconfig" source "drivers/input/fingerprint/fpc_mido/Kconfig" +source "drivers/input/fingerprint/goodix_tissot/Kconfig" +source "drivers/input/fingerprint/fpc_tissot/Kconfig" diff --git a/drivers/input/fingerprint/Makefile b/drivers/input/fingerprint/Makefile index 262e1a88912b1..45278f6272734 100644 --- a/drivers/input/fingerprint/Makefile +++ b/drivers/input/fingerprint/Makefile @@ -1,2 +1,4 @@ obj-$(CONFIG_FINGERPRINT_GOODIX_GF3208_MIDO) += goodix_mido/ obj-$(CONFIG_FINGERPRINT_FPC1020_MIDO) += fpc_mido/ +obj-$(CONFIG_FINGERPRINT_GOODIX_GF3208_TISSOT) += goodix_tissot/ +obj-$(CONFIG_FINGERPRINT_FPC1020_TISSOT) += fpc_tissot/ diff --git a/drivers/input/fingerprint/fpc_tissot/Kconfig b/drivers/input/fingerprint/fpc_tissot/Kconfig new file mode 100644 index 0000000000000..9e8988ec847fd --- /dev/null +++ b/drivers/input/fingerprint/fpc_tissot/Kconfig @@ -0,0 +1,5 @@ +config FINGERPRINT_FPC1020_TISSOT + tristate "FingerPrint Cards fingerprint driver support" + depends on INPUT_FINGERPRINT + help + Say Y here to enable fpc fingerprint driver support! diff --git a/drivers/input/fingerprint/fpc_tissot/Makefile b/drivers/input/fingerprint/fpc_tissot/Makefile new file mode 100644 index 0000000000000..abe10c3ac3cd2 --- /dev/null +++ b/drivers/input/fingerprint/fpc_tissot/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_FINGERPRINT_FPC1020_TISSOT) += fpc1020_tee.o diff --git a/drivers/input/fingerprint/fpc_tissot/fpc1020_tee.c b/drivers/input/fingerprint/fpc_tissot/fpc1020_tee.c new file mode 100644 index 0000000000000..362bb9c2097d8 --- /dev/null +++ b/drivers/input/fingerprint/fpc_tissot/fpc1020_tee.c @@ -0,0 +1,767 @@ +/* + * FPC1020 Fingerprint sensor device driver + * + * This driver will control the platform resources that the FPC fingerprint + * sensor needs to operate. The major things are probing the sensor to check + * that it is actually connected and let the Kernel know this and with that also + * enabling and disabling of regulators, controlling GPIOs such as sensor reset + * line, sensor IRQ line. + * + * The driver will expose most of its available functionality in sysfs which + * enables dynamic control of these features from eg. a user space process. + * + * The sensor's IRQ events will be pushed to Kernel's event handling system and + * are exposed in the drivers event node. + * + * This driver will NOT send any commands to the sensor it only controls the + * electrical parts. + * + * + * Copyright (c) 2015 Fingerprint Cards AB + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FPC_TTW_HOLD_TIME 2000 +#define FP_UNLOCK_REJECTION_TIMEOUT (FPC_TTW_HOLD_TIME - 500) + +#define RESET_LOW_SLEEP_MIN_US 5000 +#define RESET_LOW_SLEEP_MAX_US (RESET_LOW_SLEEP_MIN_US + 100) +#define RESET_HIGH_SLEEP1_MIN_US 100 +#define RESET_HIGH_SLEEP1_MAX_US (RESET_HIGH_SLEEP1_MIN_US + 100) +#define RESET_HIGH_SLEEP2_MIN_US 5000 +#define RESET_HIGH_SLEEP2_MAX_US (RESET_HIGH_SLEEP2_MIN_US + 100) +#define PWR_ON_SLEEP_MIN_US 100 +#define PWR_ON_SLEEP_MAX_US (PWR_ON_SLEEP_MIN_US + 900) + +#define NUM_PARAMS_REG_ENABLE_SET 2 + +static const char * const pctl_names[] = { + "fpc1020_reset_reset", + "fpc1020_reset_active", + "fpc1020_irq_active", +}; + +struct vreg_config { + char *name; + unsigned long vmin; + unsigned long vmax; + int ua_load; +}; + +static const struct vreg_config const vreg_conf[] = { + { "vdd_ana", 1800000UL, 1800000UL, 6000, }, + { "vcc_spi", 1800000UL, 1800000UL, 10, }, + { "vdd_io", 1800000UL, 1800000UL, 6000, }, +}; + +struct fpc1020_data { + struct device *dev; + + struct pinctrl *fingerprint_pinctrl; + struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)]; + struct regulator *vreg[ARRAY_SIZE(vreg_conf)]; + + struct wake_lock ttw_wl; + int irq_gpio; + int rst_gpio; + struct mutex lock; /* To set/get exported values in sysfs */ + bool prepared; + bool compatible_enabled; + atomic_t wakeup_enabled; /* Used both in ISR and non-ISR */ + struct notifier_block fb_notifier; + bool fb_black; + bool wait_finger_down; + struct work_struct work; +}; + +static irqreturn_t fpc1020_irq_handler(int irq, void *handle); +static int fpc1020_request_named_gpio(struct fpc1020_data *fpc1020, + const char *label, int *gpio); +static int hw_reset(struct fpc1020_data *fpc1020); + +static int vreg_setup(struct fpc1020_data *fpc1020, const char *name, + bool enable) +{ + size_t i; + int rc; + struct regulator *vreg; + struct device *dev = fpc1020->dev; + + for (i = 0; i < ARRAY_SIZE(fpc1020->vreg); i++) { + const char *n = vreg_conf[i].name; + + if (!strncmp(n, name, strlen(n))) + goto found; + } + + dev_err(dev, "Regulator %s not found\n", name); + + return -EINVAL; + +found: + vreg = fpc1020->vreg[i]; + if (enable) { + if (!vreg) { + vreg = regulator_get(dev, name); + if (IS_ERR(vreg)) { + dev_err(dev, "Unable to get %s\n", name); + return PTR_ERR(vreg); + } + } + + if (regulator_count_voltages(vreg) > 0) { + rc = regulator_set_voltage(vreg, vreg_conf[i].vmin, + vreg_conf[i].vmax); + if (rc) + dev_err(dev, + "Unable to set voltage on %s, %d\n", + name, rc); + } + + rc = regulator_set_optimum_mode(vreg, vreg_conf[i].ua_load); + if (rc < 0) + dev_err(dev, "Unable to set current on %s, %d\n", + name, rc); + + rc = regulator_enable(vreg); + if (rc) { + dev_err(dev, "error enabling %s: %d\n", name, rc); + regulator_put(vreg); + vreg = NULL; + } + fpc1020->vreg[i] = vreg; + } else { + if (vreg) { + if (regulator_is_enabled(vreg)) { + regulator_disable(vreg); + dev_dbg(dev, "disabled %s\n", name); + } + regulator_put(vreg); + fpc1020->vreg[i] = NULL; + } + rc = 0; + } + + return rc; +} + +/** + * sysfs node for controlling clocks. + * + * This is disabled in platform variant of this driver but kept for + * backwards compatibility. Only prints a debug print that it is + * disabled. + */ +static ssize_t clk_enable_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + dev_dbg(dev, + "clk_enable sysfs node not enabled in platform driver\n"); + + return count; +} +static DEVICE_ATTR(clk_enable, S_IWUSR, NULL, clk_enable_set); + +/** + * Will try to select the set of pins (GPIOS) defined in a pin control node of + * the device tree named @p name. + * + * The node can contain several eg. GPIOs that is controlled when selecting it. + * The node may activate or deactivate the pins it contains, the action is + * defined in the device tree node itself and not here. The states used + * internally is fetched at probe time. + * + * @see pctl_names + * @see fpc1020_probe + */ +static int select_pin_ctl(struct fpc1020_data *fpc1020, const char *name) +{ + size_t i; + int rc; + struct device *dev = fpc1020->dev; + + for (i = 0; i < ARRAY_SIZE(fpc1020->pinctrl_state); i++) { + const char *n = pctl_names[i]; + + if (!strncmp(n, name, strlen(n))) { + rc = pinctrl_select_state(fpc1020->fingerprint_pinctrl, + fpc1020->pinctrl_state[i]); + if (rc) + dev_err(dev, "cannot select '%s'\n", name); + else + dev_dbg(dev, "Selected '%s'\n", name); + goto exit; + } + } + + rc = -EINVAL; + dev_err(dev, "%s:'%s' not found\n", __func__, name); + +exit: + return rc; +} + +static ssize_t pinctl_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + int rc; + + mutex_lock(&fpc1020->lock); + rc = select_pin_ctl(fpc1020, buf); + mutex_unlock(&fpc1020->lock); + + return rc ? rc : count; +} +static DEVICE_ATTR(pinctl_set, S_IWUSR, NULL, pinctl_set); + +static ssize_t regulator_enable_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + char op; + char name[16]; + int rc; + bool enable; + + if (NUM_PARAMS_REG_ENABLE_SET != sscanf(buf, "%15[^,],%c", name, &op)) + return -EINVAL; + if (op == 'e') + enable = true; + else if (op == 'd') + enable = false; + else + return -EINVAL; + + mutex_lock(&fpc1020->lock); + rc = vreg_setup(fpc1020, name, enable); + mutex_unlock(&fpc1020->lock); + + return rc ? rc : count; +} +static DEVICE_ATTR(regulator_enable, S_IWUSR, NULL, regulator_enable_set); + +static int hw_reset(struct fpc1020_data *fpc1020) +{ + int irq_gpio; + struct device *dev = fpc1020->dev; + int rc = select_pin_ctl(fpc1020, "fpc1020_reset_active"); + + if (rc) + goto exit; + usleep_range(RESET_HIGH_SLEEP1_MIN_US, RESET_HIGH_SLEEP1_MAX_US); + + rc = select_pin_ctl(fpc1020, "fpc1020_reset_reset"); + if (rc) + goto exit; + usleep_range(RESET_LOW_SLEEP_MIN_US, RESET_LOW_SLEEP_MAX_US); + + rc = select_pin_ctl(fpc1020, "fpc1020_reset_active"); + if (rc) + goto exit; + usleep_range(RESET_HIGH_SLEEP2_MIN_US, RESET_HIGH_SLEEP2_MAX_US); + + irq_gpio = gpio_get_value(fpc1020->irq_gpio); + dev_info(dev, "IRQ after reset %d\n", irq_gpio); + +exit: + return rc; +} + +static ssize_t hw_reset_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc; + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + + if (!strncmp(buf, "reset", strlen("reset"))) { + mutex_lock(&fpc1020->lock); + rc = hw_reset(fpc1020); + mutex_unlock(&fpc1020->lock); + } else { + return -EINVAL; + } + + return rc ? rc : count; +} +static DEVICE_ATTR(hw_reset, S_IWUSR, NULL, hw_reset_set); + +/** + * Will setup GPIOs, and regulators to correctly initialize the touch sensor to + * be ready for work. + * + * In the correct order according to the sensor spec this function will + * enable/disable regulators, and reset line, all to set the sensor in a + * correct power on or off state "electrical" wise. + * + * @see device_prepare_set + * @note This function will not send any commands to the sensor it will only + * control it "electrically". + */ +static int device_prepare(struct fpc1020_data *fpc1020, bool enable) +{ + int rc; + + mutex_lock(&fpc1020->lock); + if (enable && !fpc1020->prepared) { + fpc1020->prepared = true; + select_pin_ctl(fpc1020, "fpc1020_reset_reset"); + + rc = vreg_setup(fpc1020, "vcc_spi", true); + if (rc) + goto exit; + + rc = vreg_setup(fpc1020, "vdd_io", true); + if (rc) + goto exit_1; + + rc = vreg_setup(fpc1020, "vdd_ana", true); + if (rc) + goto exit_2; + + usleep_range(PWR_ON_SLEEP_MIN_US, PWR_ON_SLEEP_MAX_US); + + /* As we can't control chip select here the other part of the + * sensor driver eg. the TEE driver needs to do a _SOFT_ reset + * on the sensor after power up to be sure that the sensor is + * in a good state after power up. Okeyed by ASIC. */ + + (void)select_pin_ctl(fpc1020, "fpc1020_reset_active"); + } else if (!enable && fpc1020->prepared) { + rc = 0; + (void)select_pin_ctl(fpc1020, "fpc1020_reset_reset"); + + usleep_range(PWR_ON_SLEEP_MIN_US, PWR_ON_SLEEP_MAX_US); + + (void)vreg_setup(fpc1020, "vdd_ana", false); +exit_2: + (void)vreg_setup(fpc1020, "vdd_io", false); +exit_1: + (void)vreg_setup(fpc1020, "vcc_spi", false); +exit: + fpc1020->prepared = false; + } else { + rc = 0; + } + mutex_unlock(&fpc1020->lock); + + return rc; +} + +/** + * sysfs node to enable/disable (power up/power down) the touch sensor + * + * @see device_prepare + */ +static ssize_t device_prepare_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc; + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + + if (!strncmp(buf, "enable", strlen("enable"))) + rc = device_prepare(fpc1020, true); + else if (!strncmp(buf, "disable", strlen("disable"))) + rc = device_prepare(fpc1020, false); + else + return -EINVAL; + + return rc ? rc : count; +} +static DEVICE_ATTR(device_prepare, S_IWUSR, NULL, device_prepare_set); + +/** + * sysfs node for controlling whether the driver is allowed + * to wake up the platform on interrupt. + */ +static ssize_t wakeup_enable_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + ssize_t ret = count; + + mutex_lock(&fpc1020->lock); + if (!strncmp(buf, "enable", strlen("enable"))) + atomic_set(&fpc1020->wakeup_enabled, 1); + else if (!strncmp(buf, "disable", strlen("disable"))) + atomic_set(&fpc1020->wakeup_enabled, 0); + else + ret = -EINVAL; + mutex_unlock(&fpc1020->lock); + + return ret; +} +static DEVICE_ATTR(wakeup_enable, S_IWUSR, NULL, wakeup_enable_set); + +/** + * sysf node to check the interrupt status of the sensor, the interrupt + * handler should perform sysf_notify to allow userland to poll the node. + */ +static ssize_t irq_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + int irq = gpio_get_value(fpc1020->irq_gpio); + + return scnprintf(buf, PAGE_SIZE, "%i\n", irq); +} + +/** + * writing to the irq node will just drop a printk message + * and return success, used for latency measurement. + */ +static ssize_t irq_ack(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + + dev_dbg(fpc1020->dev, "%s\n", __func__); + + return count; +} +static DEVICE_ATTR(irq, S_IRUSR | S_IWUSR, irq_get, irq_ack); + +static ssize_t fingerdown_wait_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + + dev_err(fpc1020->dev, "%s\n", __func__); + if (!strncmp(buf, "enable", strlen("enable"))) + fpc1020->wait_finger_down = true; + else if (!strncmp(buf, "disable", strlen("disable"))) + fpc1020->wait_finger_down = false; + else + return -EINVAL; + + return count; +} +static DEVICE_ATTR(fingerdown_wait, S_IWUSR, NULL, fingerdown_wait_set); + +static ssize_t compatible_all_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc; + int i; + int irqf; + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + dev_err(dev, "compatible all enter %d\n", fpc1020->compatible_enabled); + if (!strncmp(buf, "enable", strlen("enable")) && fpc1020->compatible_enabled != 1) { + rc = fpc1020_request_named_gpio(fpc1020, "fpc,gpio_irq", + &fpc1020->irq_gpio); + if (rc) + goto exit; + + rc = fpc1020_request_named_gpio(fpc1020, "fpc,gpio_rst", + &fpc1020->rst_gpio); + dev_err(dev, "fpc request reset result = %d\n", rc); + if (rc) + goto exit; + fpc1020->fingerprint_pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(fpc1020->fingerprint_pinctrl)) { + if (PTR_ERR(fpc1020->fingerprint_pinctrl) == -EPROBE_DEFER) { + dev_info(dev, "pinctrl not ready\n"); + rc = -EPROBE_DEFER; + goto exit; + } + dev_err(dev, "Target does not use pinctrl\n"); + fpc1020->fingerprint_pinctrl = NULL; + rc = -EINVAL; + goto exit; + } + + for (i = 0; i < ARRAY_SIZE(fpc1020->pinctrl_state); i++) { + const char *n = pctl_names[i]; + struct pinctrl_state *state = + pinctrl_lookup_state(fpc1020->fingerprint_pinctrl, n); + if (IS_ERR(state)) { + dev_err(dev, "cannot find '%s'\n", n); + rc = -EINVAL; + goto exit; + } + dev_info(dev, "found pin control %s\n", n); + fpc1020->pinctrl_state[i] = state; + } + rc = select_pin_ctl(fpc1020, "fpc1020_reset_reset"); + if (rc) + goto exit; + rc = select_pin_ctl(fpc1020, "fpc1020_irq_active"); + if (rc) + goto exit; + irqf = IRQF_TRIGGER_RISING | IRQF_ONESHOT; + if (of_property_read_bool(dev->of_node, "fpc,enable-wakeup")) { + irqf |= IRQF_NO_SUSPEND; + device_init_wakeup(dev, 1); + } + rc = devm_request_threaded_irq(dev, gpio_to_irq(fpc1020->irq_gpio), + NULL, fpc1020_irq_handler, irqf, + dev_name(dev), fpc1020); + if (rc) { + dev_err(dev, "could not request irq %d\n", + gpio_to_irq(fpc1020->irq_gpio)); + goto exit; + } + dev_dbg(dev, "requested irq %d\n", gpio_to_irq(fpc1020->irq_gpio)); + + /* Request that the interrupt should be wakeable */ + enable_irq_wake(gpio_to_irq(fpc1020->irq_gpio)); + fpc1020->compatible_enabled = 1; + if (of_property_read_bool(dev->of_node, "fpc,enable-on-boot")) { + dev_info(dev, "Enabling hardware\n"); + (void)device_prepare(fpc1020, true); +#ifdef LINUX_CONTROL_SPI_CLK + (void)set_clks(fpc1020, false); +#endif + } + } else if (!strncmp(buf, "disable", strlen("disable")) && fpc1020->compatible_enabled != 0) { + if (gpio_is_valid(fpc1020->irq_gpio)) { + devm_gpio_free(dev, fpc1020->irq_gpio); + pr_info("remove irq_gpio success\n"); + } + if (gpio_is_valid(fpc1020->rst_gpio)) { + devm_gpio_free(dev, fpc1020->rst_gpio); + pr_info("remove rst_gpio success\n"); + } + devm_free_irq(dev, gpio_to_irq(fpc1020->irq_gpio), fpc1020); + fpc1020->compatible_enabled = 0; + } + hw_reset(fpc1020); + return count; +exit: + return -EINVAL; +} +static DEVICE_ATTR(compatible_all, S_IWUSR, NULL, compatible_all_set); + +static struct attribute *attributes[] = { + &dev_attr_pinctl_set.attr, + &dev_attr_device_prepare.attr, + &dev_attr_regulator_enable.attr, + &dev_attr_hw_reset.attr, + &dev_attr_wakeup_enable.attr, + &dev_attr_clk_enable.attr, + &dev_attr_irq.attr, + &dev_attr_fingerdown_wait.attr, + &dev_attr_compatible_all.attr, + NULL +}; + +static const struct attribute_group attribute_group = { + .attrs = attributes, +}; + +static void notification_work(struct work_struct *work) +{ + mdss_prim_panel_fb_unblank(FP_UNLOCK_REJECTION_TIMEOUT); + printk("unblank\n"); +} + +static irqreturn_t fpc1020_irq_handler(int irq, void *handle) +{ + struct fpc1020_data *fpc1020 = handle; + + dev_err(fpc1020->dev, "%s\n", __func__); + + if (atomic_read(&fpc1020->wakeup_enabled)) { + wake_lock_timeout(&fpc1020->ttw_wl, + msecs_to_jiffies(FPC_TTW_HOLD_TIME)); + } + + sysfs_notify(&fpc1020->dev->kobj, NULL, dev_attr_irq.attr.name); + if (fpc1020->wait_finger_down && fpc1020->fb_black) { + printk("%s enter\n", __func__); + fpc1020->wait_finger_down = false; + schedule_work(&fpc1020->work); + } + + return IRQ_HANDLED; +} + +static int fpc1020_request_named_gpio(struct fpc1020_data *fpc1020, + const char *label, int *gpio) +{ + struct device *dev = fpc1020->dev; + struct device_node *np = dev->of_node; + int rc = of_get_named_gpio(np, label, 0); + + if (rc < 0) { + dev_err(dev, "failed to get '%s'\n", label); + return rc; + } + *gpio = rc; + + rc = devm_gpio_request(dev, *gpio, label); + if (rc) { + dev_err(dev, "failed to request gpio %d\n", *gpio); + return rc; + } + dev_dbg(dev, "%s %d\n", label, *gpio); + + return 0; +} + +static int fpc_fb_notif_callback(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct fpc1020_data *fpc1020 = container_of(nb, struct fpc1020_data, + fb_notifier); + struct fb_event *evdata = data; + unsigned int blank; + + if (!fpc1020) + return 0; + + if (val != FB_EVENT_BLANK) + return 0; + + printk("[info] %s value = %d\n", __func__, (int)val); + + if (evdata && evdata->data && val == FB_EVENT_BLANK) { + blank = *(int *)(evdata->data); + switch (blank) { + case FB_BLANK_POWERDOWN: + fpc1020->fb_black = true; + break; + case FB_BLANK_UNBLANK: + fpc1020->fb_black = false; + break; + default: + printk("%s defalut\n", __func__); + break; + } + } + return NOTIFY_OK; +} + +static struct notifier_block fpc_notif_block = { + .notifier_call = fpc_fb_notif_callback, +}; + +static int fpc1020_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int rc = 0; + + struct device_node *np = dev->of_node; + struct fpc1020_data *fpc1020 = devm_kzalloc(dev, sizeof(*fpc1020), + GFP_KERNEL); + + if (!fpc1020) { + dev_err(dev, + "failed to allocate memory for struct fpc1020_data\n"); + rc = -ENOMEM; + goto exit; + } + + fpc1020->dev = dev; + platform_set_drvdata(pdev, fpc1020); + + if (!np) { + dev_err(dev, "no of node found\n"); + rc = -EINVAL; + goto exit; + } + + mutex_init(&fpc1020->lock); + wake_lock_init(&fpc1020->ttw_wl, WAKE_LOCK_SUSPEND, "fpc_ttw_wl"); + + rc = sysfs_create_group(&dev->kobj, &attribute_group); + if (rc) { + dev_err(dev, "could not create sysfs\n"); + goto exit; + } + + + + + + dev_err(dev, "%s: ok\n", __func__); + fpc1020->fb_black = false; + fpc1020->wait_finger_down = false; + INIT_WORK(&fpc1020->work, notification_work); + fpc1020->fb_notifier = fpc_notif_block; + fb_register_client(&fpc1020->fb_notifier); + +exit: + return rc; +} + +static int fpc1020_remove(struct platform_device *pdev) +{ + struct fpc1020_data *fpc1020 = platform_get_drvdata(pdev); + + fb_unregister_client(&fpc1020->fb_notifier); + sysfs_remove_group(&pdev->dev.kobj, &attribute_group); + mutex_destroy(&fpc1020->lock); + wake_lock_destroy(&fpc1020->ttw_wl); + (void)vreg_setup(fpc1020, "vdd_ana", false); + (void)vreg_setup(fpc1020, "vdd_io", false); + (void)vreg_setup(fpc1020, "vcc_spi", false); + dev_info(&pdev->dev, "%s\n", __func__); + + return 0; +} + +static struct of_device_id fpc1020_of_match[] = { + { .compatible = "fpc,fpc1020", }, + {} +}; +MODULE_DEVICE_TABLE(of, fpc1020_of_match); + +static struct platform_driver fpc1020_driver = { + .driver = { + .name = "fpc1020", + .owner = THIS_MODULE, + .of_match_table = fpc1020_of_match, + }, + .probe = fpc1020_probe, + .remove = fpc1020_remove, +}; + +static int __init fpc1020_init(void) +{ + int rc = platform_driver_register(&fpc1020_driver); + + if (!rc) + pr_info("%s OK\n", __func__); + else + pr_err("%s %d\n", __func__, rc); + + return rc; +} + +static void __exit fpc1020_exit(void) +{ + pr_info("%s\n", __func__); + platform_driver_unregister(&fpc1020_driver); +} + +module_init(fpc1020_init); +module_exit(fpc1020_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Aleksej Makarov"); +MODULE_AUTHOR("Henrik Tillman "); +MODULE_DESCRIPTION("FPC1020 Fingerprint sensor device driver."); diff --git a/drivers/input/fingerprint/goodix_tissot/Kconfig b/drivers/input/fingerprint/goodix_tissot/Kconfig new file mode 100644 index 0000000000000..a1c4dcc475137 --- /dev/null +++ b/drivers/input/fingerprint/goodix_tissot/Kconfig @@ -0,0 +1,5 @@ +config FINGERPRINT_GOODIX_GF3208_TISSOT + tristate "Goodix GF3208 fingerprint driver support" + depends on INPUT_FINGERPRINT + help + Say Y here to enable goodix fingerprint driver support! diff --git a/drivers/input/fingerprint/goodix_tissot/Makefile b/drivers/input/fingerprint/goodix_tissot/Makefile new file mode 100644 index 0000000000000..71805f78ffca0 --- /dev/null +++ b/drivers/input/fingerprint/goodix_tissot/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_FINGERPRINT_GOODIX_GF3208_TISSOT) += gf_spi.o platform.o netlink.o diff --git a/drivers/input/fingerprint/goodix_tissot/gf_spi.c b/drivers/input/fingerprint/goodix_tissot/gf_spi.c new file mode 100644 index 0000000000000..7de9dc766fe8f --- /dev/null +++ b/drivers/input/fingerprint/goodix_tissot/gf_spi.c @@ -0,0 +1,1038 @@ +/*Simple synchronous userspace interface to SPI devices + * + * Copyright (C) 2006 SWAPP + * Andrea Paterniani + * Copyright (C) 2007 David Brownell (simplification, cleanup) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gf_spi.h" + +#if defined(USE_SPI_BUS) +#include +#include +#elif defined(USE_PLATFORM_BUS) +#include +#endif + +#define WAKELOCK_HOLD_TIME 2000 /* in ms */ +#define FP_UNLOCK_REJECTION_TIMEOUT (WAKELOCK_HOLD_TIME - 500) + +#define GF_SPIDEV_NAME "goodix,fingerprint" +/*device name after register in charater*/ +#define GF_DEV_NAME "goodix_fp" +#define GF_INPUT_NAME "gf3208" /*"goodix_fp" */ + +#define CHRD_DRIVER_NAME "goodix_fp_spi" +#define CLASS_NAME "goodix_fp" +#define SPIDEV_MAJOR 225 /* assigned */ +#define N_SPI_MINORS 32 /* ... up to 256 */ + +#define GF_INPUT_HOME_KEY KEY_HOMEPAGE /* KEY_HOME */ +#define GF_INPUT_MENU_KEY KEY_MENU +#define GF_INPUT_BACK_KEY KEY_BACK +#define GF_INPUT_FF_KEY KEY_POWER +#define GF_INPUT_CAMERA_KEY KEY_CAMERA +#define GF_INPUT_OTHER_KEY KEY_VOLUMEDOWN /* temporary key value for capture use */ +#define GF_NAV_UP_KEY KEY_GESTURE_NAV_UP +#define GF_NAV_DOWN_KEY KEY_GESTURE_NAV_DOWN +#define GF_NAV_LEFT_KEY KEY_GESTURE_NAV_LEFT +#define GF_NAV_RIGHT_KEY KEY_GESTURE_NAV_RIGHT + +#define GF_CLICK_KEY 114 +#define GF_DOUBLE_CLICK_KEY 115 +#define GF_LONG_PRESS_KEY 217 + +struct gf_key_map key_map[] = { { "POWER", KEY_POWER }, { "HOME", KEY_HOME }, { + "MENU", KEY_MENU }, { "BACK", KEY_BACK }, { "UP", KEY_UP }, { "DOWN", +KEY_DOWN }, { "LEFT", KEY_LEFT }, { "RIGHT", KEY_RIGHT }, { "FORCE", +KEY_F9 }, { "CLICK", KEY_F19 }, }; + +/**************************debug******************************/ +/*Global variables*/ +/*static MODE g_mode = GF_IMAGE_MODE;*/ +static DECLARE_BITMAP(minors, N_SPI_MINORS); +static LIST_HEAD(device_list); +static DEFINE_MUTEX(device_list_lock); +static struct gf_dev gf; +static struct wake_lock fp_wakelock; +static int driver_init_partial(struct gf_dev *gf_dev); +static void nav_event_input(struct gf_dev *gf_dev, gf_nav_event_t nav_event); + +static void gf_enable_irq(struct gf_dev *gf_dev) +{ + if (gf_dev->irq_enabled) { + pr_warn("IRQ has been enabled.\n"); + } else { + enable_irq_wake(gf_dev->irq); + gf_dev->irq_enabled = 1; + } +} + +static void gf_disable_irq(struct gf_dev *gf_dev) +{ + if (gf_dev->irq_enabled) { + gf_dev->irq_enabled = 0; + disable_irq_wake(gf_dev->irq); + } else { + pr_warn("IRQ has been disabled.\n"); + } +} + +#ifdef AP_CONTROL_CLK +static long spi_clk_max_rate(struct clk *clk, unsigned long rate) +{ + long lowest_available, nearest_low, step_size, cur; + long step_direction = -1; + long guess = rate; + int max_steps = 10; + + cur = clk_round_rate(clk, rate); + if (cur == rate) + return rate; + + /* if we got here then: cur > rate */ + lowest_available = clk_round_rate(clk, 0); + if (lowest_available > rate) + return -EINVAL; + + step_size = (rate - lowest_available) >> 1; + nearest_low = lowest_available; + + while (max_steps-- && step_size) { + guess += step_size * step_direction; + cur = clk_round_rate(clk, guess); + + if ((cur < rate) && (cur > nearest_low)) + nearest_low = cur; + /* + * if we stepped too far, then start stepping in the other + * direction with half the step size + */ + if (((cur > rate) && (step_direction > 0)) + || ((cur < rate) && (step_direction < 0))) { + step_direction = -step_direction; + step_size >>= 1; + } + } + return nearest_low; +} + +static void spi_clock_set(struct gf_dev *gf_dev, int speed) +{ + long rate; + int rc; + + rate = spi_clk_max_rate(gf_dev->core_clk, speed); + if (rate < 0) { + pr_info("%s: no match found for requested clock frequency:%d", __func__, + speed); + return; + } + + rc = clk_set_rate(gf_dev->core_clk, rate); +} + +static int gfspi_ioctl_clk_init(struct gf_dev *data) +{ + pr_debug("%s: enter\n", __func__); + + data->clk_enabled = 0; + data->core_clk = clk_get(&data->spi->dev, "core_clk"); + if (IS_ERR_OR_NULL(data->core_clk)) { + pr_err("%s: fail to get core_clk\n", __func__); + return -EPERM; + } + data->iface_clk = clk_get(&data->spi->dev, "iface_clk"); + if (IS_ERR_OR_NULL(data->iface_clk)) { + pr_err("%s: fail to get iface_clk\n", __func__); + clk_put(data->core_clk); + data->core_clk = NULL; + return -ENOENT; + } + return 0; +} + +static int gfspi_ioctl_clk_enable(struct gf_dev *data) +{ + int err; + + pr_debug("%s: enter\n", __func__); + + if (data->clk_enabled) + return 0; + + err = clk_prepare_enable(data->core_clk); + if (err) { + pr_err("%s: fail to enable core_clk\n", __func__); + return -EPERM; + } + + err = clk_prepare_enable(data->iface_clk); + if (err) { + pr_err("%s: fail to enable iface_clk\n", __func__); + clk_disable_unprepare(data->core_clk); + return -ENOENT; + } + + data->clk_enabled = 1; + + return 0; +} + +static int gfspi_ioctl_clk_disable(struct gf_dev *data) +{ + pr_debug("%s: enter\n", __func__); + + if (!data->clk_enabled) + return 0; + + clk_disable_unprepare(data->core_clk); + clk_disable_unprepare(data->iface_clk); + data->clk_enabled = 0; + + return 0; +} + +static int gfspi_ioctl_clk_uninit(struct gf_dev *data) +{ + pr_debug("%s: enter\n", __func__); + + if (data->clk_enabled) + gfspi_ioctl_clk_disable(data); + + if (!IS_ERR_OR_NULL(data->core_clk)) { + clk_put(data->core_clk); + data->core_clk = NULL; + } + + if (!IS_ERR_OR_NULL(data->iface_clk)) { + clk_put(data->iface_clk); + data->iface_clk = NULL; + } + + return 0; +} +#endif + +static long gf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct gf_dev *gf_dev = &gf; + struct gf_key gf_key; + int retval = 0; + + u8 netlink_route = NETLINK_TEST; + struct gf_ioc_chip_info info; + uint32_t key_event; + +#if defined(SUPPORT_NAV_EVENT) + gf_nav_event_t nav_event = GF_NAV_NONE; +#endif + + pr_info("gf_ioctl cmd:0x%x \n", cmd); + + + + + if (_IOC_TYPE(cmd) != GF_IOC_MAGIC) + return -ENODEV; + + if (_IOC_DIR(cmd) & _IOC_READ) + retval = !access_ok(VERIFY_WRITE, (void __user *) arg, _IOC_SIZE(cmd)); + if ((retval == 0) && (_IOC_DIR(cmd) & _IOC_WRITE)) + retval = !access_ok(VERIFY_READ, (void __user *) arg, _IOC_SIZE(cmd)); + if (retval) + return -EFAULT; + + if (gf_dev->device_available == 0) { + if ((cmd == GF_IOC_ENABLE_POWER) || (cmd == GF_IOC_DISABLE_POWER)) { + pr_info("power cmd\n"); + } else { + pr_info("Sensor is power off currently. \n"); + return -ENODEV; + } + } + + switch (cmd) { + case GF_IOC_INIT: + pr_info("%s GF_IOC_INIT .\n", __func__); + if (copy_to_user((void __user *) arg, (void *) &netlink_route, + sizeof(u8))) { + retval = -EFAULT; + break; + } + break; + case GF_IOC_EXIT: + pr_info("%s GF_IOC_EXIT .\n", __func__); + break; + case GF_IOC_DISABLE_IRQ: + pr_info("%s GF_IOC_DISABEL_IRQ .\n", __func__); + gf_disable_irq(gf_dev); + break; + case GF_IOC_ENABLE_IRQ: + pr_info("%s GF_IOC_ENABLE_IRQ .\n", __func__); + gf_enable_irq(gf_dev); + break; + pr_info("This kernel doesn't support control clk in AP\n"); + + break; + case GF_IOC_RESET: + pr_info("%s GF_IOC_RESET. \n", __func__); + gf_hw_reset(gf_dev, 3); + break; + case GF_IOC_ENABLE_GPIO: + pr_info("%s GF_IOC_ENABLE_GPIO. \n", __func__); + driver_init_partial(gf_dev); + break; + case GF_IOC_RELEASE_GPIO: + pr_info("%s GF_IOC_RELEASE_GPIO. \n", __func__); + gf_disable_irq(gf_dev); + devm_free_irq(&gf_dev->spi->dev, gf_dev->irq, gf_dev); + gf_cleanup(gf_dev); + break; + case GF_IOC_INPUT_KEY_EVENT: + pr_info("%s GF_IOC_INPUT_KEY_EVENT. \n", __func__); + if (copy_from_user(&gf_key, (struct gf_key *) arg, + sizeof(struct gf_key))) { + pr_info("Failed to copy input key event from user to kernel\n"); + retval = -EFAULT; + break; + } + + if (GF_KEY_HOME == gf_key.key) { + key_event = KEY_SELECT; + } else if (GF_KEY_POWER == gf_key.key) { + key_event = GF_INPUT_FF_KEY; + } else if (GF_KEY_CAPTURE == gf_key.key) { + key_event = GF_INPUT_CAMERA_KEY; + } else if (GF_KEY_LONG_PRESS == gf_key.key) { + key_event = GF_LONG_PRESS_KEY; + } else if (GF_KEY_DOUBLE_TAP == gf_key.key) { + key_event = GF_DOUBLE_CLICK_KEY; + } else if (GF_KEY_TAP == gf_key.key) { + key_event = GF_CLICK_KEY; + } else { + /* add special key define */ + key_event = gf_key.key; + } + pr_info("%s: received key event[%d], key=%d, value=%d\n", __func__, + key_event, gf_key.key, gf_key.value); + + if ((GF_KEY_POWER == gf_key.key || GF_KEY_CAPTURE == gf_key.key) + && (gf_key.value == 1)) { + input_report_key(gf_dev->input, key_event, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, key_event, 0); + input_sync(gf_dev->input); + } else if (GF_KEY_UP == gf_key.key) { + input_report_key(gf_dev->input, GF_NAV_UP_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_UP_KEY, 0); + input_sync(gf_dev->input); + } else if (GF_KEY_DOWN == gf_key.key) { + input_report_key(gf_dev->input, GF_NAV_DOWN_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_DOWN_KEY, 0); + input_sync(gf_dev->input); + } else if (GF_KEY_RIGHT == gf_key.key) { + input_report_key(gf_dev->input, GF_NAV_RIGHT_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_RIGHT_KEY, 0); + input_sync(gf_dev->input); + } else if (GF_KEY_LEFT == gf_key.key) { + input_report_key(gf_dev->input, GF_NAV_LEFT_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_LEFT_KEY, 0); + input_sync(gf_dev->input); + } else if ((GF_KEY_POWER != gf_key.key) + && (GF_KEY_CAPTURE != gf_key.key)) { + input_report_key(gf_dev->input, key_event, gf_key.value); + input_sync(gf_dev->input); + } + break; + case GF_IOC_ENABLE_SPI_CLK: + + +#ifdef AP_CONTROL_CLK + gfspi_ioctl_clk_enable(gf_dev); +#else + + +#endif + break; + case GF_IOC_DISABLE_SPI_CLK: + + +#ifdef AP_CONTROL_CLK + gfspi_ioctl_clk_disable(gf_dev); +#else + + +#endif + break; + case GF_IOC_ENABLE_POWER: + pr_info("%s GF_IOC_ENABLE_POWER. \n", __func__); + if (gf_dev->device_available == 1) + pr_info("Sensor has already powered-on.\n"); + else + gf_power_on(gf_dev); + gf_dev->device_available = 1; + break; + case GF_IOC_DISABLE_POWER: + pr_info("%s GF_IOC_DISABLE_POWER. \n", __func__); + if (gf_dev->device_available == 0) + pr_info("Sensor has already powered-off.\n"); + else + gf_power_off(gf_dev); + gf_dev->device_available = 0; + break; + case GF_IOC_ENTER_SLEEP_MODE: + pr_info("%s GF_IOC_ENTER_SLEEP_MODE. \n", __func__); + break; + case GF_IOC_GET_FW_INFO: + pr_info("%s GF_IOC_GET_FW_INFO. \n", __func__); + break; + case GF_IOC_REMOVE: + pr_info("%s GF_IOC_REMOVE. \n", __func__); + break; + case GF_IOC_CHIP_INFO: + pr_info("%s GF_IOC_CHIP_INFO. \n", __func__); + if (copy_from_user(&info, (struct gf_ioc_chip_info *) arg, + sizeof(struct gf_ioc_chip_info))) { + retval = -EFAULT; + break; + } + pr_info(" vendor_id : 0x%x \n", info.vendor_id); + pr_info(" mode : 0x%x \n", info.mode); + pr_info(" operation: 0x%x \n", info.operation); + break; + +#if defined(SUPPORT_NAV_EVENT) + case GF_IOC_NAV_EVENT: + pr_debug("%s GF_IOC_NAV_EVENT\n", __func__); + if (copy_from_user(&nav_event, (gf_nav_event_t *)arg, sizeof(gf_nav_event_t))) { + pr_info("Failed to copy nav event from user to kernel\n"); + retval = -EFAULT; + break; + } + + nav_event_input(gf_dev, nav_event); + break; +#endif + + default: + pr_info("Unsupport cmd:0x%x \n", cmd); + break; + } + + return retval; +} + +static void nav_event_input(struct gf_dev *gf_dev, gf_nav_event_t nav_event) +{ + uint32_t nav_input = 0; + + switch (nav_event) { + case GF_NAV_FINGER_DOWN: + pr_debug("%s nav finger down\n", __func__); + break; + + case GF_NAV_FINGER_UP: + + pr_debug("%s nav finger up\n", __func__); + break; + + case GF_NAV_DOWN: + input_report_key(gf_dev->input, GF_NAV_UP_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_UP_KEY, 0); + input_sync(gf_dev->input); + pr_debug("%s nav up\n", __func__); + break; + + case GF_NAV_UP: + input_report_key(gf_dev->input, GF_NAV_DOWN_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_DOWN_KEY, 0); + input_sync(gf_dev->input); + pr_debug("%s nav down\n", __func__); + break; + + case GF_NAV_LEFT: + input_report_key(gf_dev->input, GF_NAV_RIGHT_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_RIGHT_KEY, 0); + input_sync(gf_dev->input); + pr_debug("%s nav right\n", __func__); + break; + + case GF_NAV_RIGHT: + input_report_key(gf_dev->input, GF_NAV_LEFT_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_LEFT_KEY, 0); + input_sync(gf_dev->input); + pr_debug("%s nav left\n", __func__); + break; + + case GF_NAV_CLICK: + + pr_debug("%s nav click\n", __func__); + break; + + case GF_NAV_HEAVY: + nav_input = GF_NAV_INPUT_HEAVY; + pr_debug("%s nav heavy\n", __func__); + break; + + case GF_NAV_LONG_PRESS: + nav_input = GF_NAV_INPUT_LONG_PRESS; + pr_debug("%s nav long press\n", __func__); + break; + + case GF_NAV_DOUBLE_CLICK: + nav_input = GF_NAV_INPUT_DOUBLE_CLICK; + pr_debug("%s nav double click\n", __func__); + break; + + default: + pr_warn("%s unknown nav event: %d\n", __func__, nav_event); + break; + } + +} + +#ifdef CONFIG_COMPAT +static long +gf_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return gf_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); +} +#endif /*CONFIG_COMPAT*/ + +static void notification_work(struct work_struct *work) +{ + mdss_prim_panel_fb_unblank(FP_UNLOCK_REJECTION_TIMEOUT); + pr_debug("unblank\n"); +} + +static irqreturn_t gf_irq(int irq, void *handle) +{ +#if defined(GF_NETLINK_ENABLE) + struct gf_dev *gf_dev = &gf; + char temp = GF_NET_EVENT_IRQ; + wake_lock_timeout(&fp_wakelock, msecs_to_jiffies(WAKELOCK_HOLD_TIME)); + sendnlmsg(&temp); + if ((gf_dev->wait_finger_down == true) && (gf_dev->device_available == 1) && (gf_dev->fb_black == 1)) { + gf_dev->wait_finger_down = false; + schedule_work(&gf_dev->work); + } +#elif defined (GF_FASYNC) + struct gf_dev *gf_dev = &gf; + if (gf_dev->async) + kill_fasync(&gf_dev->async, SIGIO, POLL_IN); +#endif + + return IRQ_HANDLED; +} + +static int gf_open(struct inode *inode, struct file *filp) +{ + struct gf_dev *gf_dev; + int status = -ENXIO; + + mutex_lock(&device_list_lock); + + list_for_each_entry(gf_dev, &device_list, device_entry) { + if (gf_dev->devt == inode->i_rdev) { + pr_info("Found\n"); + status = 0; + break; + } + } + + if (status == 0) { + if (status == 0) { + gf_dev->users++; + filp->private_data = gf_dev; + nonseekable_open(inode, filp); + pr_info("Succeed to open device. irq = %d\n", gf_dev->irq); + gf_dev->device_available = 1; + } + } else { + pr_info("No device for minor %d\n", iminor(inode)); + } + mutex_unlock(&device_list_lock); + return status; +} + +#ifdef GF_FASYNC +static int gf_fasync(int fd, struct file *filp, int mode) +{ + struct gf_dev *gf_dev = filp->private_data; + int ret; + + ret = fasync_helper(fd, filp, mode, &gf_dev->async); + pr_info("ret = %d\n", ret); + return ret; +} +#endif + +static int gf_release(struct inode *inode, struct file *filp) +{ + struct gf_dev *gf_dev; + int status = 0; + + mutex_lock(&device_list_lock); + gf_dev = filp->private_data; + filp->private_data = NULL; + + /*last close?? */ + gf_dev->users--; + if (!gf_dev->users) { + + + pr_info("disble_irq. irq = %d\n", gf_dev->irq); + gf_disable_irq(gf_dev); + + devm_free_irq(&gf_dev->spi->dev, gf_dev->irq, gf_dev); + gf_dev->device_available = 0; + gf_power_off(gf_dev); + } + mutex_unlock(&device_list_lock); + return status; +} + +static const struct file_operations gf_fops = { .owner = THIS_MODULE, +/* REVISIT switch to aio primitives, so that userspace + * gets more complete API coverage. It'll simplify things + * too, except for the locking. + */ +.unlocked_ioctl = gf_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = gf_compat_ioctl, +#endif /*CONFIG_COMPAT*/ + .open = gf_open, .release = gf_release, +#ifdef GF_FASYNC + .fasync = gf_fasync, +#endif + }; + +static int goodix_fb_state_chg_callback(struct notifier_block *nb, + unsigned long val, void *data) { + struct gf_dev *gf_dev; + struct fb_event *evdata = data; + unsigned int blank; + char temp = 0; + + printk("SXF Enter %s val = %d \n ", __func__, (int)val); + if (val != FB_EVENT_BLANK) + return 0; + + dump_stack(); + + gf_dev = container_of(nb, struct gf_dev, notifier); + if (evdata && evdata->data && val == FB_EVENT_BLANK && gf_dev) { + blank = *(int *) (evdata->data); + printk("SXF_blank = %d\n", blank); + switch (blank) { + case FB_BLANK_POWERDOWN: + if (gf_dev->device_available == 1) { + gf_dev->fb_black = 1; + gf_dev->wait_finger_down = true; +#if defined(GF_NETLINK_ENABLE) + temp = GF_NET_EVENT_FB_BLACK; + sendnlmsg(&temp); +#elif defined (GF_FASYNC) + if (gf_dev->async) { + kill_fasync(&gf_dev->async, SIGIO, + POLL_IN); + } +#endif + /*device unavailable */ + + } + break; + case FB_BLANK_UNBLANK: + printk("SXF-FB_BLANK_UNBLANK \n"); + if (gf_dev->device_available == 1) { + gf_dev->fb_black = 0; +#if defined(GF_NETLINK_ENABLE) + temp = GF_NET_EVENT_FB_UNBLACK; + sendnlmsg(&temp); +#elif defined (GF_FASYNC) + if (gf_dev->async) { + kill_fasync(&gf_dev->async, SIGIO, + POLL_IN); + } +#endif + /*device available */ + + } + break; + default: + pr_info("%s defalut\n", __func__); + break; + } + } + printk("SXF Exit %s\n ", __func__); + return NOTIFY_OK; +} + +static struct notifier_block goodix_noti_block = { .notifier_call = + goodix_fb_state_chg_callback, }; + +static void gf_reg_key_kernel(struct gf_dev *gf_dev) +{ + int i; + + set_bit(EV_KEY, gf_dev->input->evbit); + for (i = 0; i < ARRAY_SIZE(key_map); i++) { + set_bit(key_map[i].val, gf_dev->input->keybit); + } + + set_bit(KEY_SELECT, gf_dev->input->keybit); + + gf_dev->input->name = GF_INPUT_NAME; + if (input_register_device(gf_dev->input)) + pr_warn("Failed to register GF as input device.\n"); +} + +static int driver_init_partial(struct gf_dev *gf_dev) +{ + int ret = 0; + + pr_warn("--------driver_init_partial start.--------\n"); + + gf_dev->device_available = 1; + + if (gf_parse_dts(gf_dev)) + goto error; + + gf_dev->irq = gf_irq_num(gf_dev); + ret = devm_request_threaded_irq(&gf_dev->spi->dev, + gf_dev->irq, + NULL, + gf_irq, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "gf", gf_dev); + if (ret) { + pr_err("Could not request irq %d\n", gpio_to_irq(gf_dev->irq_gpio)); + goto error; + } + if (!ret) { + + gf_enable_irq(gf_dev); + gf_disable_irq(gf_dev); + } + + gf_hw_reset(gf_dev, 10); + + + return 0; + +error: + + gf_cleanup(gf_dev); + + gf_dev->device_available = 0; + + return -EPERM; + + +} + + + + +static struct class *gf_class; +#if defined(USE_SPI_BUS) +static int gf_probe(struct spi_device *spi) +#elif defined(USE_PLATFORM_BUS) +static int gf_probe(struct platform_device *pdev) +#endif +{ + struct gf_dev *gf_dev = &gf; + int status = -EINVAL; + unsigned long minor; + + + printk("%s %d \n", __func__, __LINE__); + /* Initialize the driver data */ + INIT_LIST_HEAD(&gf_dev->device_entry); +#if defined(USE_SPI_BUS) + gf_dev->spi = spi; +#elif defined(USE_PLATFORM_BUS) + gf_dev->spi = pdev; +#endif + gf_dev->irq_gpio = -EINVAL; + gf_dev->reset_gpio = -EINVAL; + gf_dev->pwr_gpio = -EINVAL; + gf_dev->device_available = 0; + gf_dev->fb_black = 0; + gf_dev->irq_enabled = 0; + gf_dev->fingerprint_pinctrl = NULL; + gf_dev->wait_finger_down = false; + INIT_WORK(&gf_dev->work, notification_work); + + /* If we can allocate a minor number, hook up this device. + * Reusing minors is fine so long as udev or mdev is working. + */ + mutex_lock(&device_list_lock); + minor = find_first_zero_bit(minors, N_SPI_MINORS); + if (minor < N_SPI_MINORS) { + struct device *dev; + + gf_dev->devt = MKDEV(SPIDEV_MAJOR, minor); + dev = device_create(gf_class, &gf_dev->spi->dev, gf_dev->devt, gf_dev, + GF_DEV_NAME); + status = IS_ERR(dev) ? PTR_ERR(dev) : 0; + } else { + dev_dbg(&gf_dev->spi->dev, "no minor number available!\n"); + status = -ENODEV; + } + + + if (status == 0) { + set_bit(minor, minors); + list_add(&gf_dev->device_entry, &device_list); + } else { + gf_dev->devt = 0; + } + mutex_unlock(&device_list_lock); + + + if (status == 0) { + /*input device subsystem */ + + gf_dev->input = input_allocate_device(); + if (gf_dev->input == NULL) { + pr_info("%s, Failed to allocate input device.\n", __func__); + status = -ENOMEM; + goto error; + } + + __set_bit(EV_KEY, gf_dev->input->evbit); + __set_bit(GF_INPUT_HOME_KEY, gf_dev->input->keybit); + + __set_bit(GF_INPUT_MENU_KEY, gf_dev->input->keybit); + __set_bit(GF_INPUT_BACK_KEY, gf_dev->input->keybit); + __set_bit(GF_INPUT_FF_KEY, gf_dev->input->keybit); + + __set_bit(GF_NAV_UP_KEY, gf_dev->input->keybit); + __set_bit(GF_NAV_DOWN_KEY, gf_dev->input->keybit); + __set_bit(GF_NAV_RIGHT_KEY, gf_dev->input->keybit); + __set_bit(GF_NAV_LEFT_KEY, gf_dev->input->keybit); + __set_bit(GF_INPUT_CAMERA_KEY, gf_dev->input->keybit); + __set_bit(GF_CLICK_KEY, gf_dev->input->keybit); + __set_bit(GF_DOUBLE_CLICK_KEY, gf_dev->input->keybit); + __set_bit(GF_LONG_PRESS_KEY, gf_dev->input->keybit); + } +#ifdef AP_CONTROL_CLK + pr_info("Get the clk resource.\n"); + /* Enable spi clock */ + if (gfspi_ioctl_clk_init(gf_dev)) + goto gfspi_probe_clk_init_failed; + + if (gfspi_ioctl_clk_enable(gf_dev)) + goto gfspi_probe_clk_enable_failed; + + spi_clock_set(gf_dev, 1000000); +#endif + + + gf_dev->notifier = goodix_noti_block; + fb_register_client(&gf_dev->notifier); + gf_reg_key_kernel(gf_dev); + + wake_lock_init(&fp_wakelock, WAKE_LOCK_SUSPEND, "fp_wakelock"); + + printk("%s %d end, status = %d\n", __func__, __LINE__, status); + + return status; + + error: gf_cleanup(gf_dev); + gf_dev->device_available = 0; + if (gf_dev->devt != 0) { + pr_info("Err: status = %d\n", status); + mutex_lock(&device_list_lock); + list_del(&gf_dev->device_entry); + device_destroy(gf_class, gf_dev->devt); + clear_bit(MINOR(gf_dev->devt), minors); + mutex_unlock(&device_list_lock); +#ifdef AP_CONTROL_CLK + gfspi_probe_clk_enable_failed: gfspi_ioctl_clk_uninit(gf_dev); + gfspi_probe_clk_init_failed: +#endif + if (gf_dev->input != NULL) + input_unregister_device(gf_dev->input); + } + + return status; +} + +#if defined(USE_SPI_BUS) +static int gf_remove(struct spi_device *spi) +#elif defined(USE_PLATFORM_BUS) +static int gf_remove(struct platform_device *pdev) +#endif +{ + struct gf_dev *gf_dev = &gf; + + /* make sure ops on existing fds can abort cleanly */ + if (gf_dev->irq) + free_irq(gf_dev->irq, gf_dev); + + if (gf_dev->input != NULL) + input_unregister_device(gf_dev->input); + input_free_device(gf_dev->input); + + /* prevent new opens */ + mutex_lock(&device_list_lock); + list_del(&gf_dev->device_entry); + device_destroy(gf_class, gf_dev->devt); + clear_bit(MINOR(gf_dev->devt), minors); + if (gf_dev->users == 0) + gf_cleanup(gf_dev); + + fb_unregister_client(&gf_dev->notifier); + mutex_unlock(&device_list_lock); +wake_lock_destroy(&fp_wakelock); + return 0; +} + +#if defined(USE_SPI_BUS) +static int gf_suspend(struct spi_device *spi, pm_message_t mesg) +#elif defined(USE_PLATFORM_BUS) +static int gf_suspend(struct platform_device *pdev, pm_message_t state) +#endif +{ + pr_info(KERN_ERR "gf_suspend_test.\n"); + return 0; +} + +#if defined(USE_SPI_BUS) +static int gf_resume(struct spi_device *spi) +#elif defined(USE_PLATFORM_BUS) +static int gf_resume(struct platform_device *pdev) +#endif +{ + pr_info(KERN_ERR "gf_resume_test.\n"); + return 0; +} + +static struct of_device_id gx_match_table[] = { + { .compatible = GF_SPIDEV_NAME, }, { }, }; + +#if defined(USE_SPI_BUS) +static struct spi_driver gf_driver = { +#elif defined(USE_PLATFORM_BUS) + static struct platform_driver gf_driver = { +#endif + .driver = { .name = GF_DEV_NAME, .owner = THIS_MODULE, +#if defined(USE_SPI_BUS) + +#endif + .of_match_table = gx_match_table, }, .probe = gf_probe, + .remove = gf_remove, .suspend = gf_suspend, .resume = gf_resume, }; + +static int __init gf_init(void) +{ + int status; + + /* Claim our 256 reserved device numbers. Then register a class + * that will key udev/mdev to add/remove /dev nodes. Last, register + * the driver which manages those device numbers. + */ + + BUILD_BUG_ON(N_SPI_MINORS > 256); + status = register_chrdev(SPIDEV_MAJOR, CHRD_DRIVER_NAME, &gf_fops); + if (status < 0) { + pr_warn("Failed to register char device!\n"); + return status; + } + gf_class = class_create(THIS_MODULE, CLASS_NAME); + if (IS_ERR(gf_class)) { + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name); + pr_warn("Failed to create class.\n"); + return PTR_ERR(gf_class); + } +#if defined(USE_PLATFORM_BUS) + status = platform_driver_register(&gf_driver); +#elif defined(USE_SPI_BUS) + status = spi_register_driver(&gf_driver); +#endif + if (status < 0) { + class_destroy(gf_class); + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name); + pr_warn("Failed to register SPI driver.\n"); + } + +#ifdef GF_NETLINK_ENABLE + netlink_init(); +#endif + pr_info(" status = 0x%x\n", status); + return 0; +} + +module_init(gf_init); + +static void __exit gf_exit(void) +{ +#ifdef GF_NETLINK_ENABLE + netlink_exit(); +#endif +#if defined(USE_PLATFORM_BUS) + platform_driver_unregister(&gf_driver); +#elif defined(USE_SPI_BUS) + spi_unregister_driver(&gf_driver); +#endif + class_destroy(gf_class); + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name); +} + +module_exit(gf_exit); + +MODULE_AUTHOR("Jiangtao Yi, "); +MODULE_DESCRIPTION("User mode SPI device interface"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:gf-spi"); diff --git a/drivers/input/fingerprint/goodix_tissot/gf_spi.h b/drivers/input/fingerprint/goodix_tissot/gf_spi.h new file mode 100644 index 0000000000000..7d0aff266ffeb --- /dev/null +++ b/drivers/input/fingerprint/goodix_tissot/gf_spi.h @@ -0,0 +1,163 @@ +#ifndef __GF_SPI_H +#define __GF_SPI_H + +#include +#include +/**********************************************************/ +enum FP_MODE { + GF_IMAGE_MODE = 0, + GF_KEY_MODE, + GF_SLEEP_MODE, + GF_FF_MODE, + GF_DEBUG_MODE = 0x56 +}; + +#define SUPPORT_NAV_EVENT +#if defined(SUPPORT_NAV_EVENT) + +#define GF_NAV_INPUT_DOUBLE_CLICK KEY_VOLUMEUP +#define GF_NAV_INPUT_LONG_PRESS KEY_SEARCH +#define GF_NAV_INPUT_HEAVY KEY_CHAT +#endif + + +#if defined(SUPPORT_NAV_EVENT) +typedef enum gf_nav_event { + GF_NAV_NONE = 0, + GF_NAV_FINGER_UP, + GF_NAV_FINGER_DOWN, + GF_NAV_UP, + GF_NAV_DOWN, + GF_NAV_LEFT, + GF_NAV_RIGHT, + GF_NAV_CLICK, + GF_NAV_HEAVY, + GF_NAV_LONG_PRESS, + GF_NAV_DOUBLE_CLICK, +} gf_nav_event_t; +#endif + +typedef enum gf_key_event { + GF_KEY_NONE = 0, + GF_KEY_HOME, + GF_KEY_POWER, + GF_KEY_MENU, + GF_KEY_BACK, + GF_KEY_CAPTURE, + GF_KEY_UP, + GF_KEY_DOWN, + GF_KEY_RIGHT, + GF_KEY_LEFT, + GF_KEY_TAP, + GF_KEY_HEAVY, + GF_KEY_LONG_PRESS, + GF_KEY_DOUBLE_TAP +} gf_key_event_t; + +struct gf_key { + enum gf_key_event key; + uint32_t value; /* key down = 1, key up = 0 */ +}; + +struct gf_key_map { + char *name; + unsigned short val; +}; + +struct gf_ioc_chip_info { + unsigned char vendor_id; + unsigned char mode; + unsigned char operation; + unsigned char reserved[5]; +}; + +#define GF_IOC_MAGIC 'g' +#define GF_IOC_INIT _IOR(GF_IOC_MAGIC, 0, uint8_t) +#define GF_IOC_EXIT _IO(GF_IOC_MAGIC, 1) +#define GF_IOC_RESET _IO(GF_IOC_MAGIC, 2) +#define GF_IOC_ENABLE_IRQ _IO(GF_IOC_MAGIC, 3) +#define GF_IOC_DISABLE_IRQ _IO(GF_IOC_MAGIC, 4) +#define GF_IOC_ENABLE_SPI_CLK _IOW(GF_IOC_MAGIC, 5, uint32_t) +#define GF_IOC_DISABLE_SPI_CLK _IO(GF_IOC_MAGIC, 6) +#define GF_IOC_ENABLE_POWER _IO(GF_IOC_MAGIC, 7) +#define GF_IOC_DISABLE_POWER _IO(GF_IOC_MAGIC, 8) +#define GF_IOC_INPUT_KEY_EVENT _IOW(GF_IOC_MAGIC, 9, struct gf_key) +#define GF_IOC_ENTER_SLEEP_MODE _IO(GF_IOC_MAGIC, 10) +#define GF_IOC_GET_FW_INFO _IOR(GF_IOC_MAGIC, 11, uint8_t) +#define GF_IOC_REMOVE _IO(GF_IOC_MAGIC, 12) +#define GF_IOC_CHIP_INFO _IOR(GF_IOC_MAGIC, 13, struct gf_ioc_chip_info) +#define GF_IOC_ENABLE_GPIO _IO(GF_IOC_MAGIC, 15) +#define GF_IOC_RELEASE_GPIO _IO(GF_IOC_MAGIC, 16) + +#if defined(SUPPORT_NAV_EVENT) +#define GF_IOC_NAV_EVENT _IOW(GF_IOC_MAGIC, 14, gf_nav_event_t) +#define GF_IOC_MAXNR 15 /* THIS MACRO IS NOT USED NOW... */ +#else +#define GF_IOC_MAXNR 14 /* THIS MACRO IS NOT USED NOW... */ +#endif + + +#define USE_PLATFORM_BUS 1 + + +#define GF_NETLINK_ENABLE 1 +#define GF_NET_EVENT_IRQ 1 +#define GF_NET_EVENT_FB_BLACK 2 +#define GF_NET_EVENT_FB_UNBLACK 3 +#define NETLINK_TEST 25 + + +static const char * const pctl_names[] = { + + "goodixfp_reset_reset", + "goodixfp_reset_active", + "goodixfp_irq_active", +}; + +struct gf_dev { + dev_t devt; + struct list_head device_entry; +#if defined(USE_SPI_BUS) + struct spi_device *spi; +#elif defined(USE_PLATFORM_BUS) + struct platform_device *spi; +#endif + struct clk *core_clk; + struct clk *iface_clk; + + struct pinctrl *fingerprint_pinctrl; + struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)]; + + struct input_dev *input; + /* buffer is NULL unless this device is open (users > 0) */ + unsigned users; + signed irq_gpio; + signed reset_gpio; + signed pwr_gpio; + int irq; + int irq_enabled; + int clk_enabled; +#ifdef GF_FASYNC + struct fasync_struct *async; +#endif + struct notifier_block notifier; + char device_available; + char fb_black; + char wait_finger_down; + struct work_struct work; + +}; + +int gf_parse_dts(struct gf_dev *gf_dev); +void gf_cleanup(struct gf_dev *gf_dev); + +int gf_power_on(struct gf_dev *gf_dev); +int gf_power_off(struct gf_dev *gf_dev); + +int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms); +int gf_irq_num(struct gf_dev *gf_dev); + +void sendnlmsg(char *message); +int netlink_init(void); +void netlink_exit(void); +#endif /*__GF_SPI_H*/ diff --git a/drivers/input/fingerprint/goodix_tissot/netlink.c b/drivers/input/fingerprint/goodix_tissot/netlink.c new file mode 100644 index 0000000000000..09bb4fbc3c257 --- /dev/null +++ b/drivers/input/fingerprint/goodix_tissot/netlink.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include +#include + +#define NETLINK_TEST 25 +#define MAX_MSGSIZE 32 +int stringlength(char *s); +void sendnlmsg(char *message); +int pid; +int err; +struct sock *nl_sk = NULL; +int flag = 0; + + +struct gf_uk_channel{ + int channel_id; + int reserved; + char buf[3*1024]; + int len; +}; + + +void sendnlmsg(char *message) +{ + struct sk_buff *skb_1; + struct nlmsghdr *nlh; + int len = NLMSG_SPACE(MAX_MSGSIZE); + int slen = 0; + int ret = 0; + if (!message || !nl_sk || !pid) { + return ; + } + skb_1 = alloc_skb(len, GFP_KERNEL); + if (!skb_1) { + printk(KERN_ERR "my_net_link:alloc_skb_1 error\n"); + } + slen = strlen(message); + nlh = nlmsg_put(skb_1, 0, 0, 0, MAX_MSGSIZE, 0); + + NETLINK_CB(skb_1).portid = 0; + NETLINK_CB(skb_1).dst_group = 0; + + message[slen] = '\0'; + memcpy(NLMSG_DATA(nlh), message, slen+1); + + + ret = netlink_unicast(nl_sk, skb_1, pid, MSG_DONTWAIT); + if (!ret) { + + printk("send msg from kernel to usespace failed ret 0x%x \n", ret); + } +} + +void nl_data_ready(struct sk_buff *__skb) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + char str[100]; + skb = skb_get (__skb); + if (skb->len >= NLMSG_SPACE(0)) { + nlh = nlmsg_hdr(skb); + + memcpy(str, NLMSG_DATA(nlh), sizeof(str)); + pid = nlh->nlmsg_pid; + + if (pid) + printk("Message pid %d received:%s\n", pid, str) ; + kfree_skb(skb); + } + +} + +int netlink_init(void) +{ + struct netlink_kernel_cfg netlink_cfg; + memset(&netlink_cfg, 0, sizeof(struct netlink_kernel_cfg)); + + netlink_cfg.groups = 0; + netlink_cfg.flags = 0; + netlink_cfg.input = nl_data_ready; + netlink_cfg.cb_mutex = NULL; + + + nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, + &netlink_cfg); + + if (!nl_sk) { + printk(KERN_ERR "my_net_link: create netlink socket error.\n"); + return 1; + } + + return 0; +} + +void netlink_exit(void) +{ + if (nl_sk != NULL) { + netlink_kernel_release(nl_sk); + nl_sk = NULL; + } + + printk("my_net_link: self module exited\n"); +} + diff --git a/drivers/input/fingerprint/goodix_tissot/platform.c b/drivers/input/fingerprint/goodix_tissot/platform.c new file mode 100644 index 0000000000000..424b971531009 --- /dev/null +++ b/drivers/input/fingerprint/goodix_tissot/platform.c @@ -0,0 +1,202 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gf_spi.h" + +#if defined(USE_SPI_BUS) +#include +#include +#elif defined(USE_PLATFORM_BUS) +#include +#endif + +#define gf_dbg(fmt, args...) do { \ + pr_warn("gf:" fmt, ##args);\ + } while (0) + + +static int gf3208_request_named_gpio(struct gf_dev *gf_dev, const char *label, int *gpio) +{ + struct device *dev = &gf_dev->spi->dev; + struct device_node *np = dev->of_node; + int rc = of_get_named_gpio(np, label, 0); + if (rc < 0) { + dev_err(dev, "failed to get '%s'\n", label); + return rc; + } + *gpio = rc; + rc = devm_gpio_request(dev, *gpio, label); + if (rc) { + dev_err(dev, "failed to request gpio %d\n", *gpio); + return rc; + } + dev_err(dev, "%s %d\n", label, *gpio); + return 0; +} + +static int select_pin_ctl(struct gf_dev *gf_dev, const char *name) +{ + size_t i; + int rc; + struct device *dev = &gf_dev->spi->dev; + + for (i = 0; i < ARRAY_SIZE(gf_dev->pinctrl_state); i++) { + const char *n = pctl_names[i]; + if (!strncmp(n, name, strlen(n))) { + rc = pinctrl_select_state(gf_dev->fingerprint_pinctrl, gf_dev->pinctrl_state[i]); + + if (rc) + dev_err(dev, "cannot select '%s'\n", name); + else + dev_err(dev, "Selected '%s'\n", name); + goto exit; + } + } + rc = -EINVAL; + dev_err(dev, "%s:'%s' not found\n", __func__, name); +exit: + return rc; +} + + +/*GPIO pins reference.*/ +int gf_parse_dts(struct gf_dev *gf_dev) +{ + int rc = 0; + int i = 0; + pr_warn("--------gf_parse_dts start haijun.--------\n"); + + /*get reset resource*/ + rc = gf3208_request_named_gpio(gf_dev, "goodix,gpio_reset", &gf_dev->reset_gpio); + if (rc) { + gf_dbg("Failed to request RESET GPIO. rc = %d\n", rc); + return -EPERM; + } + + /*get irq resourece*/ + rc = gf3208_request_named_gpio(gf_dev, "goodix,gpio_irq", &gf_dev->irq_gpio); + if (rc) { + gf_dbg("Failed to request IRQ GPIO. rc = %d\n", rc); + return -EPERM; + } + + + gf_dev->fingerprint_pinctrl = devm_pinctrl_get(&gf_dev->spi->dev); + for (i = 0; i < ARRAY_SIZE(gf_dev->pinctrl_state); i++) { + const char *n = pctl_names[i]; + struct pinctrl_state *state = + pinctrl_lookup_state(gf_dev->fingerprint_pinctrl, n); + if (IS_ERR(state)) { + pr_err("cannot find '%s'\n", n); + rc = -EINVAL; + } + pr_info("found pin control %s\n", n); + gf_dev->pinctrl_state[i] = state; + } + + rc = select_pin_ctl(gf_dev, "goodixfp_reset_active"); + if (rc) + goto exit; + rc = select_pin_ctl(gf_dev, "goodixfp_irq_active"); + if (rc) + goto exit; + pr_warn("--------gf_parse_dts end---OK.--------\n"); + +exit: + return rc; + + +} + +void gf_cleanup(struct gf_dev *gf_dev) +{ + gf_dbg("[info] enter%s\n", __func__); + + if (gpio_is_valid(gf_dev->irq_gpio)) { + + devm_gpio_free(&gf_dev->spi->dev, gf_dev->irq_gpio); + gf_dbg("remove irq_gpio success\n"); + } + + if (gpio_is_valid(gf_dev->reset_gpio)) { + + devm_gpio_free(&gf_dev->spi->dev, gf_dev->reset_gpio); + gf_dbg("remove reset_gpio success\n"); + } + + if (gf_dev->fingerprint_pinctrl != NULL) { + devm_pinctrl_put(gf_dev->fingerprint_pinctrl); + gf_dev->fingerprint_pinctrl = NULL; + + gf_dbg("gx fingerprint_pinctrl release success\n"); + } +} + +/*power management*/ +int gf_power_on(struct gf_dev *gf_dev) +{ + int rc = 0; + msleep(10); + pr_info("---- power on ok ----\n"); + + return rc; +} + +int gf_power_off(struct gf_dev *gf_dev) +{ + int rc = 0; + pr_info("---- power off ----\n"); + return rc; +} + +static int hw_reset(struct gf_dev *gf_dev) +{ + int irq_gpio; + struct device *dev = &gf_dev->spi->dev; + + int rc = select_pin_ctl(gf_dev, "goodixfp_reset_reset"); + if (rc) + goto exit; + mdelay(3); + + rc = select_pin_ctl(gf_dev, "goodixfp_reset_active"); + if (rc) + goto exit; + + irq_gpio = gpio_get_value(gf_dev->irq_gpio); + dev_info(dev, "IRQ after reset %d\n", irq_gpio); +exit: + return rc; +} + + +/******************************************************************** + *CPU output low level in RST pin to reset GF. This is the MUST action for GF. + *Take care of this function. IO Pin driver strength / glitch and so on. + ********************************************************************/ +int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms) +{ + if (gf_dev == NULL) { + pr_info("Input buff is NULL.\n"); + return -EPERM; + } + hw_reset(gf_dev); + mdelay(delay_ms); + return 0; +} + +int gf_irq_num(struct gf_dev *gf_dev) +{ + if (gf_dev == NULL) { + pr_info("Input buff is NULL.\n"); + return -EPERM; + } else { + return gpio_to_irq(gf_dev->irq_gpio); + } +} + diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h index a8e046b8b0245..0d124da1c271e 100644 --- a/include/uapi/linux/input-event-codes.h +++ b/include/uapi/linux/input-event-codes.h @@ -274,6 +274,13 @@ #define KEY_F23 193 #define KEY_F24 194 +#ifdef CONFIG_MACH_XIAOMI_TISSOT +#define KEY_GESTURE_NAV_UP 195 +#define KEY_GESTURE_NAV_DOWN 196 +#define KEY_GESTURE_NAV_LEFT 197 +#define KEY_GESTURE_NAV_RIGHT 198 +#endif + #define KEY_PLAYCD 200 #define KEY_PAUSECD 201 #define KEY_PROG3 202 From d2c99426234f1dde6b7edd9473b1e0b3cabe1883 Mon Sep 17 00:00:00 2001 From: Vitaliy Tomin Date: Fri, 19 May 2017 16:44:44 +0800 Subject: [PATCH 203/508] drivers: input: touchscreen: Add ft5346, ist3038c and gt9xx mido drivers * unused firmwares dropped for all * test code for ft5346 droped * added code to qpnp-smbcharger to notify touchscreen about charger connection --- drivers/gpio/gpiolib.c | 31 +- drivers/input/touchscreen/Kconfig | 36 + drivers/input/touchscreen/Makefile | 3 + ...12_C6_FT5435_Biel0x3b_Ver0a_20170119_app.i | 3186 ++++ ...2_C6_FT5435_Ofilm0x51_Ver0a_20170119_app.i | 3186 ++++ drivers/input/touchscreen/ft5435/Makefile | 7 + drivers/input/touchscreen/ft5435/ft5435_ts.c | 4294 +++++ drivers/input/touchscreen/ft5435/ft5435_ts.h | 93 + .../input/touchscreen/ft5435/mcap_test_lib.h | 26 + drivers/input/touchscreen/gt9xx_mido/Makefile | 8 + .../touchscreen/gt9xx_mido/goodix_tool.c | 531 + drivers/input/touchscreen/gt9xx_mido/gt9xx.c | 3317 ++++ drivers/input/touchscreen/gt9xx_mido/gt9xx.h | 403 + .../touchscreen/gt9xx_mido/gt9xx_firmware.h | 13557 ++++++++++++++++ .../touchscreen/gt9xx_mido/gt9xx_update.c | 3177 ++++ .../ist3038c/IST3038C1_00000C6GFF_VER000007.h | 4054 +++++ drivers/input/touchscreen/ist3038c/Makefile | 7 + drivers/input/touchscreen/ist3038c/ist30xxc.c | 2341 +++ drivers/input/touchscreen/ist3038c/ist30xxc.h | 606 + .../touchscreen/ist3038c/ist30xxc_cmcs.c | 2106 +++ .../touchscreen/ist3038c/ist30xxc_cmcs.h | 154 + .../touchscreen/ist3038c/ist30xxc_cmcs_bin.h | 756 + .../touchscreen/ist3038c/ist30xxc_fw_v02_t1.h | 4054 +++++ .../touchscreen/ist3038c/ist30xxc_misc.c | 2325 +++ .../touchscreen/ist3038c/ist30xxc_misc.h | 53 + .../input/touchscreen/ist3038c/ist30xxc_sys.c | 493 + .../touchscreen/ist3038c/ist30xxc_tracking.c | 222 + .../touchscreen/ist3038c/ist30xxc_tracking.h | 44 + .../touchscreen/ist3038c/ist30xxc_update.c | 1623 ++ .../touchscreen/ist3038c/ist30xxc_update.h | 95 + drivers/power/qpnp-smbcharger.c | 27 + 31 files changed, 50810 insertions(+), 5 deletions(-) create mode 100644 drivers/input/touchscreen/ft5435/HQ_AL1512_C6_FT5435_Biel0x3b_Ver0a_20170119_app.i create mode 100644 drivers/input/touchscreen/ft5435/HQ_AL1512_C6_FT5435_Ofilm0x51_Ver0a_20170119_app.i create mode 100644 drivers/input/touchscreen/ft5435/Makefile create mode 100644 drivers/input/touchscreen/ft5435/ft5435_ts.c create mode 100644 drivers/input/touchscreen/ft5435/ft5435_ts.h create mode 100644 drivers/input/touchscreen/ft5435/mcap_test_lib.h create mode 100644 drivers/input/touchscreen/gt9xx_mido/Makefile create mode 100644 drivers/input/touchscreen/gt9xx_mido/goodix_tool.c create mode 100644 drivers/input/touchscreen/gt9xx_mido/gt9xx.c create mode 100644 drivers/input/touchscreen/gt9xx_mido/gt9xx.h create mode 100644 drivers/input/touchscreen/gt9xx_mido/gt9xx_firmware.h create mode 100644 drivers/input/touchscreen/gt9xx_mido/gt9xx_update.c create mode 100644 drivers/input/touchscreen/ist3038c/IST3038C1_00000C6GFF_VER000007.h create mode 100644 drivers/input/touchscreen/ist3038c/Makefile create mode 100644 drivers/input/touchscreen/ist3038c/ist30xxc.c create mode 100644 drivers/input/touchscreen/ist3038c/ist30xxc.h create mode 100644 drivers/input/touchscreen/ist3038c/ist30xxc_cmcs.c create mode 100644 drivers/input/touchscreen/ist3038c/ist30xxc_cmcs.h create mode 100644 drivers/input/touchscreen/ist3038c/ist30xxc_cmcs_bin.h create mode 100644 drivers/input/touchscreen/ist3038c/ist30xxc_fw_v02_t1.h create mode 100644 drivers/input/touchscreen/ist3038c/ist30xxc_misc.c create mode 100644 drivers/input/touchscreen/ist3038c/ist30xxc_misc.h create mode 100644 drivers/input/touchscreen/ist3038c/ist30xxc_sys.c create mode 100644 drivers/input/touchscreen/ist3038c/ist30xxc_tracking.c create mode 100644 drivers/input/touchscreen/ist3038c/ist30xxc_tracking.h create mode 100644 drivers/input/touchscreen/ist3038c/ist30xxc_update.c create mode 100644 drivers/input/touchscreen/ist3038c/ist30xxc_update.h diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 164ee9b4646b0..3fce85caf9a90 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -63,8 +63,17 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label) /** * Convert a GPIO number to its descriptor */ +#ifdef CONFIG_TOUCHSCREEN_GT9XX_MIDO +static int special_irq; +#endif struct gpio_desc *gpio_to_desc(unsigned gpio) { +#ifdef CONFIG_TOUCHSCREEN_GT9XX_MIDO + if (gpio == 65) + special_irq = 1; + else + special_irq = 0; +#endif if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio)) return NULL; else @@ -984,18 +993,30 @@ int gpiod_direction_input(struct gpio_desc *desc) } EXPORT_SYMBOL_GPL(gpiod_direction_input); +#ifdef CONFIG_TOUCHSCREEN_GT9XX_MIDO +extern int gt9xx_flag; +#endif + static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) { struct gpio_chip *chip; int status = -EINVAL; /* GPIOs used for IRQs shall not be set as output */ - if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) { - gpiod_err(desc, - "%s: tried to set a GPIO tied to an IRQ as output\n", - __func__); - return -EIO; +#ifdef CONFIG_TOUCHSCREEN_GT9XX_MIDO + if ((special_irq == 1) && (gt9xx_flag == 1)) { + printk("[GPIO]set GPIO_65 as irq output\n"); + } else{ +#endif + if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) { + gpiod_err(desc, + "%s: tried to set a GPIO tied to an IRQ as output\n", + __func__); + return -EIO; + } +#ifdef CONFIG_TOUCHSCREEN_GT9XX_MIDO } +#endif /* Open drain pin should not be driven to 1 */ if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index dd9b928e36948..b3f8454ec7963 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -547,6 +547,32 @@ config TOUCHSCREEN_EDT_FT5X06 To compile this driver as a module, choose M here: the module will be called edt-ft5x06. +config TOUCHSCREEN_FT5435 + tristate "FocalTech touchscreens" + depends on I2C + help + Say Y here if you have a ft5435 touchscreen. + Ft5435 controllers are multi touch controllers which can + report 5 touches at a time. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called ft5435_ts. + +config TOUCHSCREEN_IST3038C + tristate "imagies touchscreens" + depends on I2C + help + Say Y here if you have a ist3038c touchscreen. + Ft5x06 controllers are multi touch controllers which can + report 5 touches at a time. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called ist3038c_ts. + config TOUCHSCREEN_MIGOR tristate "Renesas MIGO-R touchscreen" depends on SH_MIGOR && I2C @@ -1123,6 +1149,16 @@ config TOUCHSCREEN_GT9XX If unsure, say N. +config TOUCHSCREEN_GT9XX_MIDO + bool "Goodix touchpanel GT9xx series" + depends on I2C + help + Say Y here if you have a Goodix GT9xx mido touchscreen. + Gt9xx controllers are multi touch controllers which can + report 5 touches at a time. + + If unsure, say N. + config TOUCHSCREEN_MAXIM_STI tristate "Maxim based STI touchscreens" depends on SPI_MASTER diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index be0eb9b34f5b6..4792092e6c3d5 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -89,4 +89,7 @@ obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += synaptics_i2c_rmi4.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV) += synaptics_rmi_dev.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE) += synaptics_fw_update.o +obj-$(CONFIG_TOUCHSCREEN_FT5435) += ft5435/ +obj-$(CONFIG_TOUCHSCREEN_IST3038C) += ist3038c/ obj-$(CONFIG_TOUCHSCREEN_GT9XX) += gt9xx/ +obj-$(CONFIG_TOUCHSCREEN_GT9XX_MIDO) += gt9xx_mido/ diff --git a/drivers/input/touchscreen/ft5435/HQ_AL1512_C6_FT5435_Biel0x3b_Ver0a_20170119_app.i b/drivers/input/touchscreen/ft5435/HQ_AL1512_C6_FT5435_Biel0x3b_Ver0a_20170119_app.i new file mode 100644 index 0000000000000..b407af8140cf1 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/HQ_AL1512_C6_FT5435_Biel0x3b_Ver0a_20170119_app.i @@ -0,0 +1,3186 @@ +0x2, 0x1f,0xd2,0x2, 0xb6,0x1a,0xeb,0xaa,0x8, 0x22,0x22,0x2, 0x0, 0x49,0xb4,0x2, +0x4, 0xa9,0xb7,0xea,0x22,0x24,0xff,0xa9,0x97,0xea,0x22,0x2, 0x50,0x32,0xb4,0x2, +0x4, 0xa9,0xb6,0xea,0x22,0x24,0xff,0xa9,0x96,0xea,0x22,0x2, 0x68,0x4, 0x7f,0x60, +0xa9,0xc2,0xea,0x74,0x1, 0x12,0x13,0x96,0x7f,0x6, 0x12,0x5, 0xb4,0x7f,0x6, 0x2, +0x9, 0xa1,0x22,0x2, 0x68,0x20,0x2, 0x26,0x11,0x32,0x32,0x2, 0x0, 0x4a,0x12,0x10, +0xa2,0x2, 0x13,0x79,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x2, 0x0, 0x76,0x1, 0x2, +0x4, 0x8, 0x10,0x20,0x40,0x80,0xf5,0xfd,0xe5,0xfe,0x22,0x2, 0x0, 0x5a,0xd2,0x1, +0x2, 0x37,0xa6,0x2, 0x10,0x52,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b, +0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0xf, 0x7e,0xf, 0x39,0xc9, +0x69,0x30,0x0, 0x4, 0x7a,0x73,0x39,0xd9,0x7e,0x73,0x39,0xd9,0xa, 0x37,0x5e,0x34, +0x0, 0x4, 0x68,0x4, 0xd2,0xe, 0x80,0x2, 0xc2,0xe, 0x7e,0x34,0x0, 0x1f,0x79,0x30, +0x0, 0x4, 0xc2,0xc3,0x12,0x12,0x9e,0x12,0x69,0x5, 0x7e,0x1f,0x39,0xc9,0x69,0x31, +0x0, 0x2, 0x5e,0x34,0x0, 0x40,0x68,0x2e,0x6c,0xaa,0x7e,0x10,0x2, 0xac,0x1a,0x7e, +0x1f,0x39,0xc9,0x7f,0x71,0x2d,0xf0,0x69,0x17,0x0, 0x9c,0x59,0x10,0x39,0xcd,0xb, +0xa0,0xbe,0xa0,0x3, 0x78,0xe4,0x69,0x11,0x0, 0xa4,0x7a,0x17,0x39,0xd5,0x69,0x31, +0x0, 0xa2,0x7a,0x37,0x39,0xd3,0xa9,0xc1,0xc4,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda, +0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7d,0x13, +0x7e,0x1f,0x39,0xf8,0x1b,0x1a,0x10,0xc2,0xc6,0xd2,0xee,0x22,0xff,0xff,0x54,0x2c, +0xca,0x79,0x7f,0x50,0x7c,0xeb,0x7e,0x34,0x0, 0x24,0x7e,0x8, 0x0, 0x2c,0x7e,0x24, +0x0, 0x2, 0x12,0x63,0x62,0xe5,0x2c,0xbe,0xb0,0x0, 0x38,0x2, 0x21,0x4a,0xe5,0x2c, +0xbe,0xb0,0x76,0x28,0x2, 0x21,0x4a,0x7e,0xe1,0x2c,0xbe,0xe0,0x76,0x38,0x2, 0x21, +0x78,0x7e,0x34,0x1e,0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x79,0x35,0x0, +0x4, 0xbe,0xe0,0x81,0x68,0x2, 0x21,0x71,0x74,0x23,0x7a,0x5b,0xb0,0x74,0x1c,0x61, +0x84,0x74,0x1, 0x7a,0x5b,0xb0,0x61,0x84,0x7c,0xbe,0x14,0xbe,0xb0,0x75,0x40,0x2, +0x61,0x33,0x7e,0xa0,0x3, 0xa4,0x2e,0x54,0x1, 0x8c,0x89,0x54,0x2, 0x2, 0xfb,0x2, +0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xed,0x2, 0x2, +0xfb,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x25,0x2, 0x3, 0x33,0x2, 0x3, 0x9, 0x2, +0x2, 0xfb,0x2, 0x3, 0x17,0x2, 0x3, 0x17,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x41,0xfb,0x7e,0x34,0x1e, +0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1d,0xe2,0x61,0x3f,0x7e,0x34,0x1e,0x19,0x79, +0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x61,0x3f,0x7e,0x34,0x1e,0x19,0x79,0x35,0x0, +0x2, 0x7e,0x34,0x1d,0xb2,0x61,0x3f,0x7e,0x34,0x1d,0x96,0x79,0x35,0x0, 0x2, 0x7e, +0x34,0x1d,0xc6,0x61,0x3f,0x7e,0x34,0x1e,0xa, 0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1d, +0xf1,0x61,0x3f,0x7e,0x34,0x1e,0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x79, +0x35,0x0, 0x4, 0xbe,0xe0,0x16,0x28,0x2, 0x61,0x4e,0x7c,0xfe,0x61,0x62,0x7e,0xf0, +0x16,0xbe,0xe0,0x72,0x50,0x2, 0x61,0x62,0xa, 0x3e,0x9e,0x34,0x0, 0x72,0xb, 0x34, +0x2c,0xf7,0x7e,0x70,0x3, 0xac,0x7f,0x7d,0x23,0x2e,0x24,0x1e,0x69,0x7a,0x51,0x82, +0x7a,0x41,0x83,0xe4,0x93,0x7a,0x5b,0xb0,0x2e,0x34,0x1e,0x6a,0x7a,0x71,0x82,0x7a, +0x61,0x83,0xe4,0x93,0x39,0xb5,0x0, 0x1, 0xda,0x79,0x22,0xca,0x3b,0x7f,0x30,0x74, +0x1, 0x12,0x13,0xde,0x29,0x73,0x0, 0xf3,0x2e,0x70,0xff,0x92,0x1, 0x29,0xb3,0x0, +0xf4,0x12,0x13,0xaf,0x7f,0x3, 0x12,0xd, 0x72,0x7f,0x3, 0x12,0x6, 0xba,0x29,0x73, +0x0, 0xa, 0xa, 0x37,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x24,0x29,0x73,0x0, 0xa3, +0xa, 0x27,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24, +0x69,0x33,0x0, 0xff,0x4d,0x32,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x2, 0x29,0x73, +0x0, 0xa, 0xa, 0x47,0x29,0x73,0x0, 0x5, 0xa, 0x57,0x9d,0x54,0xf5,0x34,0x29,0xb3, +0x0, 0xa5,0x70,0xb, 0x29,0xb3,0x0, 0xf8,0x29,0x73,0x0, 0xf7,0x12,0xb, 0xad,0x29, +0x73,0x0, 0xa5,0x2e,0x70,0xff,0x92,0x1, 0xe5,0x34,0x12,0xb, 0x1e,0x69,0x33,0x0, +0xfd,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x28,0x69,0x23,0x0, 0xfb,0x3e,0x24,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x29,0x73,0x0, 0xfa,0xa, 0x37,0x2d, +0x32,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x2a,0x29,0x73,0x0, 0xf9,0xa, 0x37,0x7e, +0xf, 0x39,0xc9,0x79,0x30,0x0, 0x2c,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x39,0xc9,0x79, +0x30,0x0, 0x34,0x7e,0x34,0x1, 0xb, 0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x2e,0x29, +0x73,0x0, 0x5, 0xa, 0x37,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x10,0x69,0x33,0x0, +0xa8,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x1c,0x69,0x33,0x0, 0xaa,0x7e,0xf, 0x39, +0xc9,0x79,0x30,0x0, 0x1e,0x6c,0xaa,0x7e,0x50,0x2, 0xac,0x5a,0x69,0x13,0x1, 0x1, +0x2d,0x12,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0x7e,0xf, 0x39,0xc9,0x2d,0x12,0x79, +0x30,0x0, 0x44,0xb, 0xa0,0xbe,0xa0,0xc, 0x40,0xdd,0xda,0x3b,0x22,0xca,0xf8,0x7f, +0x70,0x7e,0x7b,0xf0,0x29,0x77,0x0, 0x1, 0xbc,0x7f,0x28,0x2, 0x7c,0xf7,0x69,0x17, +0x0, 0x6, 0x6d,0x0, 0x7e,0x34,0x0, 0xf2,0x74,0xff,0x12,0x20,0xe8,0x7f,0x7, 0x12, +0xe, 0xed,0xa9,0xd6,0xcb,0x6c,0xaa,0x80,0x2d,0x6c,0x77,0x80,0x1f,0x7e,0x10,0xb, +0xac,0x1a,0xa, 0x17,0x2d,0x1, 0x3e,0x4, 0x69,0x17,0x0, 0x6, 0x2d,0x10,0x6d,0x0, +0xb, 0xa, 0x20,0x6e,0x24,0xff,0xff,0x1b,0xa, 0x20,0xb, 0x70,0x29,0x67,0x0, 0x1, +0xbc,0x67,0x38,0xd9,0xb, 0xa0,0x7e,0x7b,0x60,0xbc,0x6a,0x38,0xcc,0x69,0x37,0x0, +0x6, 0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, 0x4, 0x7c,0x4f,0x6c,0x55,0xa, 0x3f,0x2d, +0x32,0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b, +0x1a,0x10,0x7e,0x34,0x0, 0xd0,0x12,0xf, 0x45,0x6c,0xaa,0xbe,0xa0,0x4, 0x50,0x18, +0x7e,0x70,0x4, 0xac,0x7a,0x7c,0xb7,0x7e,0x1f,0x33,0xfc,0x69,0x41,0x0, 0x26,0x60, +0x42,0x1e,0x44,0x14,0x78,0xfb,0x80,0x3b,0xbe,0xa0,0x8, 0x50,0x1b,0xa, 0x3a,0x1b, +0x36,0x3e,0x34,0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x33,0xfc,0x69,0x41,0x0, 0x28,0x60, +0x22,0x1e,0x44,0x14,0x78,0xfb,0x80,0x1b,0xa, 0x3a,0x9e,0x34,0x0, 0x8, 0x3e,0x34, +0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x33,0xfc,0x69,0x41,0x0, 0x2a,0x60,0x5, 0x1e,0x44, +0x14,0x78,0xfb,0x5e,0x44,0x0, 0xf, 0x7e,0x50,0x2, 0xac,0x5a,0x69,0x37,0x0, 0x6, +0x2d,0x32,0x6d,0x22,0x1b,0x1a,0x40,0xb, 0xa0,0xbe,0xa0,0xb, 0x40,0x8d,0xa9,0xc6, +0xcb,0xda,0xf8,0x22,0x29,0x70,0x0, 0x96,0x29,0x90,0x0, 0x98,0x29,0x60,0x0, 0x97, +0x29,0x80,0x0, 0x8d,0xbe,0x80,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe,0x80,0x8, +0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x80,0x10,0x38,0x5, 0x7e,0xa0,0x2, 0x80, +0xd, 0xbe,0x80,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, 0xbe,0x90, +0x3, 0x28,0x3, 0x7e,0x90,0x3, 0xbe,0x80,0x3f,0x28,0x3, 0x7e,0x80,0x3f,0xbe,0x60, +0x1, 0x28,0x3, 0x7e,0x60,0x1, 0xbe,0x70,0x2, 0x28,0x2, 0x6c,0x77,0xa, 0x28,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x7c,0x89,0x6c,0x99,0x3e,0x44,0x3e, +0x44,0x3e,0x44,0x2d,0x42,0xa, 0x26,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d, +0x24,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x2d,0x32,0x7e,0x7f,0x39,0xf8,0x79,0x37,0x0, +0x2, 0x29,0xb0,0x0, 0x8c,0x7c,0x4b,0x6c,0x55,0x29,0xb0,0x0, 0x8b,0xa, 0x3b,0x2d, +0x32,0x7e,0x7f,0x39,0xc1,0x79,0x37,0x0, 0x80,0x69,0x30,0x0, 0xa0,0x7e,0x7f,0x39, +0xf8,0x79,0x37,0x0, 0xc, 0x69,0x30,0x0, 0x9e,0x5e,0x34,0xe0,0xf, 0x29,0xb0,0x0, +0x8c,0xa, 0x2b,0x1b,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d,0x32,0x7e, +0x7f,0x39,0xc1,0x79,0x37,0x0, 0x82,0xa, 0x2a,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e, +0x24,0x29,0xb0,0x0, 0x99,0xa, 0x3b,0x2d,0x32,0x7e,0x7f,0x39,0xf8,0x79,0x37,0x0, +0x6, 0x69,0x30,0x0, 0x9c,0x7e,0x7f,0x39,0xf8,0x79,0x37,0x0, 0x8, 0x69,0x30,0x0, +0x9a,0x7e,0xf, 0x39,0xf8,0x79,0x30,0x0, 0xa, 0x22,0x7f,0x60,0x74,0x1, 0x12,0x13, +0xde,0x29,0x36,0x0, 0xf5,0x29,0x26,0x0, 0xa3,0x29,0x16,0x0, 0xa4,0xbe,0x20,0x2, +0x28,0x3, 0x7e,0x20,0x2, 0xbe,0x10,0x40,0x28,0x3, 0x7e,0x10,0x40,0x7e,0x34,0x0, +0x4, 0x7c,0xb2,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0x7, 0xa, 0x31,0x7e,0x2f, +0x39,0xc9,0x79,0x32,0x0, 0x12,0x7c,0x73,0xac,0x70,0xa, 0x21,0x12,0x1e,0xb9,0x7c, +0x27,0xa, 0x32,0x7e,0x2f,0x39,0xc9,0x79,0x32,0x0, 0x14,0x7c,0x73,0xac,0x70,0x29, +0x26,0x0, 0xf6,0xa, 0x22,0xad,0x32,0xa, 0x21,0x8d,0x32,0x7d,0x43,0x7c,0x73,0xac, +0x70,0xa, 0x21,0x12,0x1e,0xb9,0x7c,0xa7,0x7c,0x2a,0x7c,0xb9,0x2c,0xab,0xbe,0xa0, +0xc, 0x50,0x3, 0x7e,0xa0,0xc, 0xbe,0x20,0xc, 0x50,0x3, 0x7e,0x20,0xc, 0xa, 0x20, +0xa, 0x31,0x12,0x1e,0xb9,0x7d,0xe3,0xa, 0x3a,0xb, 0x34,0xad,0x3e,0xb, 0x34,0xbe, +0x34,0x2, 0x0, 0x40,0x4, 0x7e,0x34,0x1, 0xff,0x29,0x46,0x0, 0xf7,0x7e,0x50,0x2, +0xac,0x45,0xa, 0xf2,0xad,0xfe,0x2d,0x2f,0xb, 0x24,0xbe,0x24,0x2, 0x0, 0x40,0x4, +0x7e,0x24,0x1, 0xff,0xa, 0x13,0x7e,0x7f,0x39,0xc9,0x79,0x17,0x0, 0xa, 0x1e,0x24, +0x7c,0x45,0x6c,0x55,0x1e,0x34,0x2d,0x32,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0xc, +0xa, 0x3a,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30, +0x0, 0x4, 0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f, +0x33,0xfc,0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x33,0xfc,0x79,0x32, +0x0, 0x8, 0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d, +0x32,0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e, +0xf, 0x33,0xfc,0x79,0x30,0x0, 0xe, 0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xe0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xb2,0x86,0x22,0xff,0xff, +0x7f,0x21,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x4, 0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, +0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0x6, 0x69,0x30,0x0, +0x6, 0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0x8, 0x29,0x70,0x0, 0x1, 0x7c,0x47,0x6c, +0x55,0x7e,0xb, 0x70,0xa, 0x37,0x2d,0x32,0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0xc, +0x29,0x70,0x0, 0x2, 0xa, 0x37,0x1b,0x34,0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0xa, +0x69,0x30,0x0, 0xa, 0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0xe, 0x69,0x30,0x0, 0xc, +0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0x10,0x69,0x30,0x0, 0xe, 0x7e,0x7f,0x33,0xfc, +0x79,0x37,0x0, 0x12,0x29,0x70,0x0, 0x3, 0x7c,0x27,0x6c,0x33,0x7e,0x1f,0x33,0xfc, +0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xa0,0x12,0xf, 0x45,0x7e,0x1f,0x33,0xfc,0x69,0x11, +0x0, 0x1a,0x7a,0x2b,0x30,0x69,0x11,0x0, 0x1c,0x39,0x32,0x0, 0x1, 0x69,0x11,0x0, +0x16,0x79,0x12,0x0, 0x2, 0x69,0x11,0x0, 0x18,0x79,0x12,0x0, 0x4, 0x69,0x11,0x0, +0x22,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x24,0x79,0x12,0x0, 0x8, 0x69,0x11,0x0, +0x1e,0x79,0x12,0x0, 0xa, 0x69,0x31,0x0, 0x20,0x79,0x32,0x0, 0xc, 0xa9,0xc6,0xcb, +0x22,0xca,0x3b,0x7c,0x57,0x7c,0x4b,0x5e,0x40,0x3, 0x69,0x30,0x0, 0x4, 0x5e,0x60, +0x3f,0x6c,0xaa,0xa, 0x4a,0x69,0xf0,0x0, 0xa, 0x69,0xe0,0x0, 0x8, 0x2d,0xf4,0x7e, +0x7b,0xb0,0xa, 0xfb,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0xa, 0xea,0x69,0xd0, +0x0, 0xe, 0x69,0xc0,0x0, 0xc, 0x2d,0xde,0x7e,0x6b,0xb0,0xa, 0x4b,0x2d,0x4f,0x7e, +0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, 0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0, +0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x39,0xf4,0x2d,0xfd,0x79,0x47,0x1, 0x8c,0xb, 0xa0, +0xbe,0xa0,0xe, 0x78,0xae,0x6c,0xaa,0x7e,0x90,0x2, 0xac,0x9a,0x69,0xf0,0x0, 0x2, +0xb, 0xa, 0xe0,0x2d,0xf4,0xb, 0x7a,0x40,0x7e,0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, +0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0,0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x39, +0xf4,0x2d,0xfd,0x79,0x47,0x1, 0x80,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xc9,0x7e,0x90, +0xf0,0xac,0x94,0x74,0x28,0xac,0xb5,0x7d,0xf5,0x2d,0xf4,0x7e,0x2f,0x39,0xf4,0x2d, +0x5f,0x79,0x32,0x1, 0x88,0x69,0x30,0x0, 0x6, 0x7e,0x30,0xf0,0xac,0x34,0x74,0x28, +0xac,0x5b,0x2d,0x21,0x7e,0xf, 0x39,0xf4,0x2d,0x12,0x79,0x30,0x1, 0x8a,0xda,0x3b, +0x22,0x29,0x60,0x0, 0xb, 0xa, 0x46,0x29,0x60,0x0, 0x4, 0xa, 0x26,0x2d,0x24,0x7c, +0x65,0x29,0xb0,0x0, 0x6, 0xbc,0xb6,0x28,0x2, 0x7c,0x6b,0x29,0x70,0x0, 0x5, 0x29, +0xb0,0x0, 0x7, 0xbc,0xb7,0x28,0x2, 0x7c,0x7b,0x6c,0xaa,0x6d,0x22,0x7e,0x90,0x2, +0xac,0x9a,0x7e,0x7f,0x39,0xc1,0x2d,0xf4,0x79,0x27,0x0, 0x2, 0xb, 0xa0,0xbe,0xa0, +0x23,0x78,0xea,0x6c,0xaa,0x80,0x55,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x57,0x0, +0x4c,0xbe,0x50,0x23,0x50,0x23,0x29,0x47,0x0, 0xb4,0xa, 0xd4,0x7d,0x4d,0x7c,0x89, +0x6c,0x99,0x7d,0xd4,0x7e,0x90,0x2, 0xac,0x95,0x7e,0x7f,0x39,0xc1,0x2d,0xf4,0xb, +0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xa, 0x4a,0x7f,0x70,0x2d,0xf4,0x29, +0x47,0x0, 0x4c,0xa, 0xd4,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x39,0xc1,0x2d,0xf4, +0xb, 0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0xa0,0xbc,0x6a,0x38,0xa7, +0x6c,0xaa,0x80,0x1d,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x67,0x0, 0x6f,0xa, 0x46, +0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x39,0xc1,0x2d,0xf2,0x79,0x47,0x0, 0x48,0xb, +0xa0,0xbc,0x7a,0x38,0xdf,0x22,0x7c,0x7b,0x7e,0x7f,0x39,0xc9,0x69,0x47,0x0, 0xc, +0x6c,0x88,0x3e,0x44,0x69,0x7, 0x0, 0xa, 0x69,0x57,0x0, 0x2, 0x1e,0x54,0x1e,0x54, +0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, 0x3, 0x7e,0x14, +0x0, 0x4, 0x70,0x2, 0x41,0x9b,0x3e,0x14,0x14,0x78,0xfb,0x7c,0xa3,0xa, 0xda,0xad, +0xd0,0x7d,0xcd,0x6d,0x11,0x79,0x17,0x0, 0x8c,0x7c,0xb7,0x70,0x2, 0x41,0xb4,0x1e, +0xd4,0x14,0x78,0xfb,0xbe,0xd4,0x1, 0x0, 0x38,0x2, 0x41,0xc2,0x7e,0xd4,0x1, 0x0, +0x41,0xce,0xbe,0xd4,0x0, 0x10,0x40,0x2, 0x41,0xce,0x7e,0xd4,0x0, 0x10,0x7d,0x3d, +0x12,0x12,0x6a,0xa, 0x1b,0x7e,0x1f,0x39,0xc9,0x79,0x11,0x0, 0x90,0x7e,0x1f,0x39, +0xc9,0x79,0xd1,0x0, 0x8e,0x7e,0x7f,0x39,0xc9,0x69,0x37,0x0, 0x8, 0xad,0x3c,0x8d, +0x3d,0x79,0x37,0x0, 0x92,0x7e,0x14,0x0, 0x6, 0x7e,0x1f,0x39,0xc9,0x79,0x11,0x0, +0x94,0x7d,0x24,0x9d,0x20,0xa, 0x3a,0xad,0x32,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, +0x96,0x7e,0x34,0x0, 0x10,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x98,0x22,0x7c,0x5b, +0x7e,0xf, 0x39,0xc9,0x69,0x40,0x0, 0x22,0x30,0x1, 0x6b,0x6d,0xff,0x7d,0x3f,0xbe, +0x50,0x10,0x28,0x2e,0x7e,0x54,0xff,0xff,0x79,0x50,0x0, 0x42,0x9e,0x50,0x10,0x6c, +0xaa,0x80,0x11,0x7e,0xe4,0x0, 0x1, 0x7c,0xba,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb, +0x2d,0x3e,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e,0x6f,0x39,0xc9,0x79,0x36,0x0, 0x40, +0x80,0x25,0x79,0xf0,0x0, 0x40,0x6c,0xaa,0x80,0x11,0x7e,0xf4,0x0, 0x1, 0x7c,0xba, +0x60,0x5, 0x3e,0xf4,0x14,0x78,0xfb,0x2d,0x3f,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e, +0x7f,0x39,0xc9,0x79,0x37,0x0, 0x42,0x7d,0x34,0x2e,0x34,0x0, 0xc, 0x7e,0x7f,0x39, +0xc9,0x79,0x37,0x0, 0x16,0x22,0x6d,0x33,0x79,0x30,0x0, 0x40,0x7e,0xf, 0x39,0xc9, +0x79,0x30,0x0, 0x42,0x7e,0x1f,0x39,0xc9,0x79,0x41,0x0, 0x16,0x22,0x7c,0x17,0x7c, +0x3b,0x6d,0x33,0x7e,0x2f,0x39,0xc9,0x79,0x32,0x0, 0x40,0x7e,0x2f,0x39,0xc9,0x79, +0x32,0x0, 0x42,0x7e,0x7f,0x39,0xc9,0x69,0x57,0x0, 0x12,0x7c,0xab,0x69,0x37,0x0, +0x2, 0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x5e, +0x34,0x0, 0x3, 0x7c,0xb7,0x7e,0x44,0x0, 0x4, 0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb, +0x7c,0x29,0xa, 0x22,0xa, 0x3a,0x12,0x1e,0xb9,0xa, 0x23,0x2d,0x32,0x7c,0xb7,0x7c, +0x61,0x6c,0x77,0xa, 0xb, 0x1e,0x4, 0x2d,0x3, 0x79,0x7, 0x0, 0xc, 0x7c,0x73,0xac, +0x72,0xa, 0x2a,0x12,0x1e,0xb9,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x16,0x6d,0x33, +0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x6, +0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x33,0xfc, +0x79,0x32,0x0, 0x8, 0x29,0x70,0x0, 0x2, 0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x3, +0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0xc, 0x7e,0xb, 0x70,0x7c, +0x47,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, +0xa, 0x29,0x70,0x0, 0x4, 0xa, 0x37,0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0xe, 0x29, +0xb0,0x0, 0x5, 0x54,0x1, 0x7c,0x2b,0x6c,0x33,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xc0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xca,0x79,0x7c,0xab,0x5e, +0xa0,0x3, 0x6c,0x77,0x7e,0x50,0x2, 0xac,0x57,0x69,0xd0,0x0, 0xe, 0x69,0xc0,0x0, +0xc, 0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d, +0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e,0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e, +0x7f,0x39,0xf4,0x2d,0xf2,0x79,0x47,0x2, 0x54,0xb, 0x70,0xbe,0x70,0xe, 0x40,0xc4, +0x69,0x40,0x0, 0x4, 0x7e,0xf0,0xf0,0xac,0xfa,0x7e,0x1f,0x39,0xf4,0x2d,0x37,0x79, +0x41,0x2, 0x50,0x69,0x30,0x0, 0x6, 0x74,0xf0,0xa4,0x7e,0xf, 0x39,0xf4,0x2d,0x15, +0x79,0x30,0x2, 0x52,0xda,0x79,0x22,0xa9,0xd6,0xcb,0xc2,0x1e,0x69,0x30,0x0, 0x4, +0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f,0x33,0xfc, +0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0x8, +0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e, +0x2f,0x33,0xfc,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e,0x2f,0x33, +0xfc,0x79,0x32,0x0, 0xe, 0x29,0xb0,0x0, 0x3, 0x54,0x1, 0xa, 0x5b,0x7c,0xab,0xe4, +0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x50,0x69,0x30,0x0, 0xa, 0x12,0xf, 0x45,0xa9,0xc6, +0xcb,0x22,0x69,0x30,0x0, 0xae,0x7e,0x2f,0x39,0xc9,0x79,0x32,0x0, 0x6, 0x29,0x50, +0x0, 0xa6,0xa, 0x55,0x7d,0x23,0x1e,0x24,0x9d,0x25,0x7e,0x2f,0x39,0xc9,0x79,0x22, +0x0, 0x18,0x7d,0x23,0x1e,0x24,0x1b,0x25,0x7e,0x2f,0x39,0xc9,0x79,0x22,0x0, 0x38, +0x69,0x20,0x0, 0xfd,0x1e,0x34,0x9d,0x32,0x9e,0x34,0x0, 0xa, 0x7e,0x2f,0x39,0xc9, +0x79,0x32,0x0, 0x26,0x29,0x70,0x0, 0xa7,0xa, 0x37,0x7e,0x2f,0x39,0xc9,0x79,0x32, +0x0, 0x1a,0x29,0x70,0x0, 0xb, 0xa, 0x27,0x29,0x70,0x0, 0x4, 0x2d,0x32,0x7e,0x2f, +0x39,0xc9,0x79,0x32,0x0, 0x8, 0x2, 0x9, 0xa1,0xca,0x3b,0xf5,0x24,0x7f,0x41,0x7f, +0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0xe5,0x24,0xbe,0xb0,0x23,0x28, +0x3, 0x75,0x24,0x23,0x6c,0xaa,0x80,0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b, +0xb0,0xbe,0xb1,0x26,0x40,0xd, 0x74,0x23,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, +0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, 0x3b,0x2e,0x35,0x28,0x7a,0x71,0x82,0x7a,0x61, +0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13,0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24, +0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22,0xa9,0xd6,0xcb,0x69,0x20,0x0, 0x4, 0x7e,0x2f, +0x33,0xfc,0x79,0x22,0x0, 0x4, 0x69,0x20,0x0, 0x8, 0x7e,0x2f,0x33,0xfc,0x79,0x22, +0x0, 0x8, 0x7e,0xb, 0x50,0xa, 0x55,0x7c,0xab,0xe4,0x29,0x50,0x0, 0x1, 0xa, 0x25, +0x2d,0x25,0x7e,0x2f,0x33,0xfc,0x79,0x22,0x0, 0xc, 0x29,0x50,0x0, 0x2, 0xa, 0x25, +0x7e,0xf, 0x33,0xfc,0x79,0x20,0x0, 0xe, 0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, 0xa, +0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x40,0x12,0xf, 0x45, +0xa9,0xc6,0xcb,0x22,0x7c,0xab,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x39,0xf8,0x79,0x30, +0x0, 0xe, 0xc2,0x1d,0xe4,0x7a,0xb3,0x39,0xf3,0x5e,0xa0,0x3, 0xa, 0x1a,0x3e,0x14, +0x7e,0x1f,0x39,0xc1,0x1b,0x1a,0x10,0x7e,0xf, 0x39,0xc1,0x2e,0x14,0x0, 0x84,0xb, +0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x74,0x1, 0x12,0x13,0x56,0x7e,0xf, 0x39, +0xf8,0xb, 0xa, 0x30,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xa9,0xd3,0xcd,0x7e,0xf, 0x39, +0xf8,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x22,0x7f,0x10,0xa9, +0xd6,0xcb,0x69,0x11,0x0, 0x2, 0x7e,0x2f,0x33,0xfc,0x79,0x12,0x0, 0x4, 0x69,0x11, +0x0, 0x4, 0x7e,0x2f,0x33,0xfc,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x6, 0x7e,0x2f, +0x33,0xfc,0x79,0x12,0x0, 0x8, 0x7e,0x1b,0x30,0xa, 0x3, 0x7e,0x14,0x1, 0x0, 0xad, +0x10,0x29,0x71,0x0, 0x1, 0xa, 0x37,0x2d,0x31,0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, +0xc, 0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x60,0x12,0xf, +0x45,0xa9,0xc6,0xcb,0x22,0xa9,0xd7,0xcb,0x7d,0x23,0x4e,0x50,0x1, 0x7e,0xf, 0x33, +0xfc,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x80,0x1e,0x7e,0xf, 0x33,0xfc,0xb, +0xa, 0x30,0x7d,0x23,0x5e,0x24,0x0, 0x8, 0xbe,0x24,0x0, 0x8, 0x78,0xb, 0xa9,0xd7, +0xcb,0x4e,0x70,0x4, 0x1b,0xa, 0x30,0xd2,0x1e,0x7e,0xf, 0x33,0xfc,0xb, 0xa, 0x30, +0x7d,0x23,0x5e,0x24,0x80,0x0, 0xbe,0x24,0x80,0x0, 0x78,0xcf,0x4e,0x60,0x40,0x1b, +0xa, 0x30,0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10,0x22,0xca,0x3b,0xf5,0x24, +0x7f,0x41,0x7f,0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0x6c,0xaa,0x80, +0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0xbe,0xb1,0x27,0x40,0xd, 0x74, +0x1c,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, 0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, +0x3b,0x2e,0x35,0x2a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13, +0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24,0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22, +0x5, 0x63,0x31,0x20,0x18,0x13,0xf, 0xd, 0xc, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, +0xca,0xf8,0x7d,0xe2,0x7d,0xd3,0x7c,0xfb,0xbe,0x30,0x1, 0x28,0x6, 0x7e,0xf4,0x0, +0x10,0x80,0xf, 0xbe,0x30,0x0, 0x28,0x6, 0x7e,0xf4,0x0, 0x8, 0x80,0x4, 0x7e,0xf4, +0x0, 0x4, 0x7d,0x1f,0x6d,0x0, 0x6d,0x33,0x7e,0x24,0x0, 0x10,0x12,0x1f,0x58,0x7f, +0x1, 0x7d,0x3d,0x6d,0x22,0x12,0x1e,0xeb,0x7d,0x1e,0x12,0x1f,0x5, 0x74,0x4, 0xac, +0xbf,0x7e,0xf, 0x39,0xc9,0x2d,0x15,0x79,0x30,0x0, 0x82,0x79,0x20,0x0, 0x80,0xda, +0xf8,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, +0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0x1d,0x7e,0xf, 0x39,0xf8,0xb, 0xa, 0x30,0x7c, +0x57,0x7a,0x53,0x39,0xf3,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xc2,0xc6,0x6d,0x33,0x7e, +0xf, 0x39,0xf8,0x79,0x30,0x0, 0xe, 0x12,0x12,0x9e,0x12,0x69,0x5, 0xd0,0x82,0xd0, +0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda, +0x7b,0x32,0x74,0x3, 0x12,0x13,0x56,0xa9,0xd1,0xc4,0x7e,0xf, 0x39,0xc1,0x2e,0x14, +0x0, 0x84,0xb, 0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x7e,0x14,0x0, 0x1, 0x7e, +0x1f,0x39,0xc1,0x1b,0x1a,0x10,0x7e,0xf, 0x39,0xc9,0xb, 0x16,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0xc2,0xf, 0xe4,0x7a,0xb3,0x39,0xd9,0x7e,0x1f,0x39,0xc1, +0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0x74,0x2, 0x2, 0x13,0x56,0x7c,0x6b, +0x6c,0xaa,0x80,0x17,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x39,0xf4,0x2d,0xf4,0xb, +0x7a,0x20,0x7f,0x70,0x2d,0xf4,0x1b,0x7a,0x20,0xb, 0xa0,0xbc,0x7a,0x38,0xe5,0x6c, +0xaa,0x80,0x20,0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x39,0xf4,0x2d,0xf2,0x69,0x27, +0x0, 0x38,0xa, 0xf7,0xa, 0x4a,0x2d,0x4f,0x3e,0x44,0x7f,0x70,0x2d,0xf4,0x1b,0x7a, +0x20,0xb, 0xa0,0xbc,0x6a,0x38,0xdc,0x22,0xca,0x79,0x7c,0xab,0x5e,0xa0,0x3, 0x6c, +0x77,0x7e,0x50,0x2, 0xac,0x57,0x7f,0x60,0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6, +0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e, +0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e,0x7f,0x39,0xf4,0x2d,0xf2,0x79,0x47,0x2, 0x54, +0xb, 0x70,0xbe,0x70,0xe, 0x40,0xca,0xda,0x79,0x22,0x29,0x50,0x0, 0xf5,0xac,0x5b, +0x7e,0xf, 0x39,0xc9,0x69,0x30,0x0, 0xc, 0xa, 0x56,0x3e,0x54,0xbe,0x24,0x2, 0x0, +0x40,0x4, 0x7e,0x24,0x1, 0xff,0xbd,0x25,0x28,0x1f,0x2e,0x14,0x0, 0xc, 0x6c,0x66, +0x1b,0xa, 0x30,0x1e,0x24,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x39,0xc9,0x2e,0x14,0x0, +0xc, 0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50, +0x28,0xac,0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d, +0x24,0x7e,0x7f,0x39,0xf4,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x44,0xa, 0x4a,0x7f, +0x60,0x2d,0xd4,0x7e,0x6b,0xb0,0x7c,0x8b,0x6c,0x99,0x4d,0x24,0x79,0x27,0x1, 0x8c, +0xb, 0xa0,0xbe,0xa0,0xe, 0x40,0xc7,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50,0x28,0xac, +0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d,0x24,0x7e, +0x7f,0x39,0xf4,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x55,0xa, 0x4a,0x7f,0x60,0x2d, +0xd4,0x7e,0x6b,0xb0,0xa, 0x4b,0x4d,0x24,0x79,0x27,0x1, 0x8c,0xb, 0xa0,0xbe,0xa0, +0xe, 0x40,0xc9,0x22,0xa9,0xd6,0xcb,0x54,0x3f,0x5e,0x70,0x1f,0x7c,0x2b,0x6c,0x33, +0x3e,0x14,0x3e,0x14,0x2e,0x14,0x0, 0x5, 0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34, +0x3e,0x34,0x3e,0x34,0x2d,0x31,0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, 0x2, 0x7e,0xf, +0x33,0xfc,0x79,0x20,0x0, 0x14,0xa9,0xc6,0xcb,0x22,0x7d,0x23,0x6c,0x66,0x7e,0x30, +0x2, 0xac,0x36,0x2e,0x14,0x20,0x99,0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4,0x93,0xa, +0x1b,0xbd,0x12,0x28,0x7, 0xb, 0x60,0xbe,0x60,0x14,0x40,0xe2,0x7e,0x70,0x2, 0xac, +0x67,0x2e,0x34,0x20,0x9a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x7e,0xf, +0x39,0xc1,0x2e,0x14,0x0, 0x84,0xb, 0xa, 0x30,0x5e,0x70,0xdf,0x1b,0xa, 0x30,0x74, +0x3, 0x12,0x13,0x56,0x7e,0x14,0x0, 0x3, 0x7e,0x1f,0x39,0xc1,0x1b,0x1a,0x10,0x7e, +0x1f,0x39,0xc1,0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0xe4,0x2, 0x13,0x56, +0x2e,0x34,0x4, 0x0, 0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x60,0x7e,0x34,0x4, 0x0, +0x9d,0x32,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x62,0x7e,0x34,0x0, 0x1, 0x7e,0xf, +0x39,0xc9,0x79,0x30,0x0, 0x64,0xa, 0x3b,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x66, +0x22,0x7c,0xa5,0xbe,0x34,0x0, 0x0, 0x28,0x10,0xa, 0x1b,0x3e,0x14,0x7d,0x23,0x7c, +0x45,0x6c,0x55,0x2d,0x21,0xa, 0x3a,0x80,0x8, 0xa, 0x2b,0x3e,0x24,0x7c,0x67,0x6c, +0x77,0x2d,0x32,0x7e,0xf, 0x39,0xf8,0x79,0x30,0x0, 0x4, 0x22,0x7c,0xa7,0x7e,0x1f, +0x39,0xc1,0x69,0x41,0x0, 0x8a,0x5e,0x44,0x10,0xf, 0xa, 0x1a,0x3e,0x14,0x3e,0x14, +0x3e,0x14,0x3e,0x14,0xa, 0x5b,0xc4,0x23,0x54,0xe0,0x7c,0xab,0xe4,0x2d,0x51,0x4d, +0x45,0x79,0x41,0x0, 0x8a,0x22,0x7e,0xf, 0x39,0xc1,0x69,0x30,0x0, 0x84,0x5e,0x70, +0xe7,0x1b,0xb1,0x68,0xc, 0x14,0x68,0xc, 0xb, 0xb1,0x78,0x5, 0x4e,0x70,0x10,0x80, +0x3, 0x4e,0x70,0x8, 0x79,0x30,0x0, 0x84,0x22,0x7e,0x34,0x0, 0x1f,0x7e,0xf, 0x39, +0xc9,0x79,0x30,0x0, 0x4, 0xa9,0xd2,0xcd,0x7e,0xf, 0x39,0xc9,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0x22,0xbe,0xb0,0x0, 0x28,0xa, 0xa9,0xd7,0xca,0xa9,0xd3, +0xcb,0xa9,0xd2,0xcb,0x22,0xa9,0xc7,0xca,0xa9,0xc3,0xcb,0xa9,0xc2,0xcb,0x22,0x30, +0x1, 0xa, 0x54,0x3, 0xa, 0x3b,0x2e,0x34,0x2, 0x0, 0x80,0x2, 0x6d,0x33,0x7e,0xf, +0x39,0xc9,0x79,0x30,0x0, 0x3a,0x22,0x7e,0xf, 0x39,0xc1,0x69,0x30,0x0, 0x8a,0x60, +0x5, 0x4e,0x60,0x10,0x80,0x3, 0x5e,0x60,0xef,0x79,0x30,0x0, 0x8a,0x22,0xbe,0xb0, +0x0, 0x28,0x9, 0xa9,0xd6,0xca,0xd2,0xcd,0xa9,0xd1,0xcb,0x22,0xa9,0xc6,0xca,0xc2, +0xcd,0xa9,0xc1,0xcb,0x22,0x7e,0x34,0x0, 0xf, 0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, +0x4, 0xc2,0xc3,0xd2,0xeb,0x22,0x6, 0xe, 0x15,0x1a,0x1f,0x26,0x2b,0x2d,0x2e,0x2f, +0x2c,0x2a,0x24,0x1f,0x1a,0x14,0xf, 0x8, 0x3, 0x3, 0x6, 0xb, 0x10,0x15,0x1c,0x22, +0x28,0x2d,0x34,0x39,0x3d,0x40,0xe, 0x3, 0x0, 0x0, 0x0, 0x3, 0x8, 0xc, 0x11,0x16, +0x1c,0x23,0x2b,0x32,0x37,0x3c,0x40,0x45,0x4a,0x4d,0x4c,0x4b,0x4a,0x48,0x46,0x46, +0x45,0x45,0x44,0x44,0x43,0x44,0x45,0x78,0x65,0x55,0x2, 0xd, 0x14,0x1b,0x21,0x25, +0x2b,0x31,0x37,0x36,0x33,0x2d,0x28,0x20,0x19,0x14,0xd, 0x8, 0x1, 0x2, 0x5, 0xb, +0x10,0x18,0x1e,0x23,0x2a,0x30,0x35,0x3a,0x3e,0x3f,0x0, 0x1, 0x1, 0x0, 0x0, 0x0, +0x0, 0x0, 0x1, 0x4, 0x9, 0xf, 0x15,0x1d,0x24,0x2a,0x30,0x35,0x3b,0x3e,0x3f,0x40, +0x3f,0x3e,0x3d,0x3d,0x3c,0x3c,0x3b,0x3b,0x39,0x37,0x1a,0x2d,0x65,0x55,0x1b,0x29, +0x27,0x1e,0x14,0x11,0x1a,0x26,0x2e,0x37,0x3d,0x3f,0x3d,0x37,0x2e,0x21,0x16,0xc, +0x5, 0x1, 0x0, 0x0, 0x1, 0x3, 0xa, 0x13,0x1d,0x26,0x2e,0x33,0x38,0x3a,0x16,0x21, +0x2b,0x32,0x30,0x2a,0x27,0x2a,0x2f,0x2d,0x24,0x1a,0x10,0x7, 0x1, 0x0, 0x2, 0x7, +0x10,0x19,0x23,0x2d,0x36,0x41,0x49,0x4c,0x4a,0x45,0x3c,0x34,0x2a,0x27,0x51,0x71, +0x50,0x55,0x28,0x12,0x11,0x18,0x23,0x29,0x2b,0x2a,0x2e,0x35,0x3c,0x3e,0x3f,0x39, +0x31,0x28,0x1e,0x15,0xe, 0x6, 0x3, 0x1, 0x0, 0x0, 0x3, 0xc, 0x16,0x20,0x2b,0x32, +0x37,0x39,0x20,0x29,0x32,0x37,0x31,0x28,0x21,0x2a,0x31,0x2d,0x23,0x1b,0x13,0x8, +0x1, 0x0, 0x1, 0x5, 0xc, 0x18,0x20,0x29,0x34,0x3e,0x47,0x4f,0x50,0x4d,0x45,0x3c, +0x34,0x31,0x26,0xcb,0x50,0x55,0x1d,0x2f,0x2c,0x25,0x1a,0x1b,0x20,0x29,0x31,0x31, +0x2e,0x2d,0x35,0x3d,0x3f,0x3d,0x38,0x2c,0x22,0x15,0xd, 0x6, 0x1, 0x0, 0x1, 0x6, +0x10,0x1b,0x24,0x2f,0x38,0x3d,0xd, 0x1b,0x27,0x31,0x32,0x28,0x1e,0x14,0x15,0x1d, +0x28,0x31,0x34,0x2a,0x1f,0x14,0x9, 0x1, 0x0, 0x4, 0xd, 0x17,0x21,0x2c,0x35,0x40, +0x47,0x47,0x44,0x3c,0x34,0x30,0x1b,0x82,0x50,0x55,0x19,0x2e,0x2a,0x1f,0x18,0x1b, +0x22,0x2d,0x30,0x2e,0x2e,0x35,0x3d,0x3f,0x3d,0x3a,0x2f,0x24,0x18,0xf, 0x7, 0x1, +0x0, 0x0, 0x3, 0xb, 0x16,0x1e,0x29,0x32,0x3a,0x3d,0x11,0x1f,0x28,0x32,0x30,0x26, +0x1b,0x14,0x1c,0x25,0x2e,0x35,0x2e,0x23,0x19,0x11,0x4, 0x0, 0x1, 0x8, 0x10,0x1c, +0x25,0x30,0x38,0x40,0x42,0x3f,0x39,0x32,0x2c,0x27,0xc0,0xd1,0x50,0x55,0x18,0x2c, +0x29,0x1e,0x14,0x13,0x16,0x1e,0x29,0x30,0x2e,0x2c,0x2b,0x37,0x3d,0x3f,0x3e,0x39, +0x30,0x25,0x1b,0x10,0x8, 0x1, 0x0, 0x2, 0x9, 0x13,0x1f,0x2d,0x38,0x3c,0x11,0x1a, +0x23,0x2f,0x33,0x29,0x20,0x16,0xe, 0x13,0x1d,0x28,0x32,0x31,0x28,0x1e,0x16,0xb, +0x2, 0x0, 0x1, 0x8, 0x12,0x1e,0x29,0x33,0x3b,0x3f,0x3c,0x32,0x29,0x26,0x30,0x6e, +0x50,0x55,0x16,0x2b,0x24,0x17,0xd, 0xa, 0xe, 0x15,0x24,0x28,0x25,0x23,0x2b,0x36, +0x3b,0x3d,0x3b,0x37,0x2b,0x20,0x15,0xb, 0x4, 0x0, 0x0, 0x3, 0xe, 0x19,0x27,0x33, +0x3d,0x3f,0x13,0x21,0x2e,0x37,0x3a,0x31,0x27,0x1c,0x13,0x1c,0x28,0x34,0x3e,0x37, +0x2d,0x22,0x18,0xc, 0x1, 0x0, 0x3, 0xd, 0x18,0x25,0x31,0x3c,0x47,0x48,0x42,0x38, +0x2e,0x2a,0x31,0x62,0x50,0x55,0x35,0x2e,0x27,0x22,0x1f,0x1b,0x16,0x10,0xc, 0x8, +0x6, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x3, 0x6, 0xb, 0xe, 0x12,0x17,0x1d,0x22,0x26, +0x2a,0x30,0x35,0x39,0x3d,0x3f,0x0, 0x0, 0x1, 0x4, 0x6, 0x8, 0xb, 0x10,0x16,0x1b, +0x1f,0x23,0x28,0x2d,0x32,0x36,0x3b,0x40,0x44,0x48,0x4a,0x4b,0x4c,0x4b,0x4a,0x48, +0x46,0x43,0x40,0x3e,0x3c,0x3a,0x3c,0x9c,0x34,0x55,0x9, 0x17,0x1d,0x26,0x2e,0x37, +0x3c,0x3f,0x3b,0x33,0x2b,0x22,0x1a,0x11,0xb, 0x5, 0x3, 0x1, 0x1, 0x0, 0x0, 0x0, +0x1, 0x6, 0xa, 0x11,0x19,0x22,0x2a,0x32,0x39,0x3d,0x30,0x30,0x2f,0x2c,0x26,0x1e, +0x17,0xd, 0x5, 0x0, 0x0, 0x1, 0x6, 0xe, 0x15,0x1e,0x26,0x2c,0x32,0x3a,0x41,0x48, +0x50,0x5b,0x61,0x64,0x64,0x60,0x5b,0x56,0x51,0x4f,0xd8,0x2c,0x33,0x55,0x26,0x1c, +0x19,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x17,0x17,0x15,0xf, 0x9, 0x4, 0x1, 0x0, +0x0, 0x0, 0x0, 0x1, 0x4, 0xb, 0x12,0x18,0x1f,0x28,0x31,0x37,0x3c,0x40,0x1, 0x7, +0xe, 0x14,0x1c,0x23,0x2c,0x34,0x3e,0x44,0x4c,0x54,0x5b,0x60,0x5d,0x55,0x4f,0x49, +0x43,0x3d,0x38,0x32,0x2b,0x26,0x22,0x1f,0x1e,0x1c,0x1c,0x1c,0x1c,0x1d,0x66,0x54, +0x74,0x55,0x3e,0x2c,0x21,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d, +0x1e,0x1e,0x1d,0x1a,0x11,0xc, 0x7, 0x2, 0x0, 0x0, 0x3, 0xa, 0x12,0x1c,0x23,0x2c, +0x38,0x40,0xc, 0x0, 0x6, 0xf, 0x17,0x22,0x29,0x32,0x3b,0x41,0x47,0x4f,0x55,0x5c, +0x66,0x71,0x79,0x3e,0x76,0x6d,0x64,0x5a,0x52,0x4b,0x42,0x39,0x35,0x33,0x32,0x32, +0x31,0x31,0xf3,0xdb,0x74,0x55,0x9, 0x7, 0x6, 0x6, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, +0x3, 0x2, 0x2, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xa, 0x10,0x14,0x1b,0x22, +0x28,0x2e,0x34,0x39,0x3d,0x40,0x0, 0xb, 0x11,0x16,0x1b,0x22,0x28,0x2c,0x33,0x39, +0x40,0x46,0x4d,0x52,0x56,0x5c,0x61,0x68,0x6d,0x73,0x73,0x71,0x71,0x71,0x70,0x70, +0x6f,0x6f,0x6f,0x6f,0x6d,0x6e,0x79,0x80,0x44,0x55,0x17,0x13,0x12,0x12,0x11,0x10, +0xf, 0xd, 0xc, 0xb, 0x9, 0x8, 0x7, 0x4, 0x3, 0x2, 0x1, 0x0, 0x0, 0x0, 0x1, 0x4, +0xb, 0x10,0x16,0x1d,0x24,0x29,0x31,0x39,0x3d,0x40,0x0, 0xe, 0x16,0x1a,0x1f,0x24, +0x29,0x2e,0x33,0x38,0x3e,0x43,0x47,0x50,0x55,0x59,0x62,0x69,0x6e,0x75,0x7c,0xff, +0x7d,0x7c,0x79,0x73,0x6d,0x68,0x60,0x5a,0x57,0x56,0x5d,0x8, 0x44,0x55,0x0, 0x7, +0xb, 0xd, 0x10,0x12,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x19,0x1c,0x1e,0x20,0x22, +0x23,0x25,0x27,0x29,0x2b,0x30,0x32,0x33,0x35,0x38,0x39,0x3b,0x3d,0x3f,0x3e,0x29, +0x1f,0x18,0xf, 0x7, 0x6, 0xc, 0x12,0x1d,0x25,0x2d,0x36,0x3e,0x3b,0x35,0x2c,0x26, +0x20,0x19,0x11,0xa, 0x3, 0x3, 0x9, 0x10,0x18,0x24,0x2c,0x33,0x3a,0x3e,0x60,0x9b, +0x32,0x55,0x0, 0x5, 0x5, 0x5, 0x4, 0x3, 0x2, 0x3, 0x5, 0x7, 0xa, 0xe, 0x11,0x19, +0x1b,0x1c,0x1d,0x1c,0x1c,0x1d,0x1f,0x22,0x25,0x2a,0x31,0x33,0x35,0x37,0x38,0x39, +0x3c,0x40,0x0, 0x12,0x1c,0x24,0x2b,0x34,0x3c,0x39,0x2f,0x29,0x21,0x16,0xf, 0xd, +0x14,0x1e,0x2a,0x33,0x31,0x27,0x20,0x18,0x10,0x7, 0xa, 0x10,0x1a,0x26,0x2f,0x37, +0x3d,0x3f,0xfb,0x8f,0x32,0x55,0x2c,0x23,0x1f,0x19,0x13,0xc, 0x7, 0x3, 0x0, 0x0, +0x0, 0x1, 0x5, 0xa, 0xf, 0x16,0x1d,0x23,0x2a,0x30,0x36,0x3b,0x3e,0x40,0x3f,0x3e, +0x3b,0x38,0x33,0x2f,0x2b,0x28,0x9, 0x1, 0x0, 0x1, 0x3, 0x9, 0xe, 0x14,0x1b,0x21, +0x27,0x2e,0x36,0x3b,0x3e,0x41,0x41,0x40,0x3d,0x3a,0x36,0x2f,0x2b,0x26,0x20,0x1c, +0x16,0x10,0xc, 0xa, 0x9, 0xb, 0x36,0xdc,0x30,0x55,0x1a,0x9, 0x5, 0x1, 0x0, 0x0, +0x0, 0x2, 0x5, 0x9, 0xf, 0x16,0x1c,0x22,0x2a,0x31,0x36,0x39,0x3c,0x3e,0x3f,0x3f, +0x3d,0x38,0x30,0x27,0x1f,0x18,0x12,0xb, 0x6, 0x5, 0x7, 0x12,0x19,0x22,0x2c,0x36, +0x3f,0x49,0x53,0x5c,0x63,0x66,0x64,0x5f,0x58,0x4c,0x43,0x3d,0x34,0x2b,0x22,0x1b, +0x15,0xb, 0x4, 0x0, 0x0, 0x1, 0x4, 0xb, 0x13,0x18,0xf1,0xc, 0x30,0x55,0x18,0x2c, +0x34,0x39,0x3c,0x3d,0x3f,0x3f,0x3f,0x3d,0x3b,0x36,0x30,0x2a,0x24,0x1c,0x16,0xd, +0x6, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x5, 0x9, 0xf, 0x17,0x1e,0x24,0x1, 0x2, +0x8, 0xe, 0x14,0x1a,0x21,0x28,0x30,0x37,0x40,0x49,0x50,0x55,0x59,0x5c,0x5c,0x58, +0x51,0x48,0x3f,0x38,0x31,0x2b,0x25,0x1d,0x17,0x11,0xa, 0x4, 0x1, 0x1, 0x9d,0xbf, +0x30,0x55,0x16,0x7, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4, 0x8, 0xe, 0x16,0x1f,0x28, +0x30,0x38,0x3c,0x3e,0x3f,0x40,0x3f,0x3f,0x3d,0x3b,0x37,0x32,0x2c,0x25,0x1d,0x16, +0xf, 0xc, 0x53,0x46,0x3e,0x35,0x2e,0x27,0x20,0x1a,0x14,0xd, 0x6, 0x1, 0x0, 0x0, +0x3, 0xa, 0x13,0x1a,0x20,0x27,0x2d,0x33,0x3a,0x40,0x48,0x4f,0x54,0x58,0x5a,0x5a, +0x58,0x57,0xc6,0x55,0x30,0x55,0x7, 0x1, 0x4, 0xa, 0x10,0x18,0x20,0x2a,0x32,0x38, +0x3c,0x3e,0x3f,0x3e,0x3d,0x3b,0x39,0x35,0x30,0x27,0x21,0x19,0x12,0xb, 0x6, 0x3, +0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x1d,0x12,0x9, 0x5, 0x1, 0x0, 0x0, 0x1, 0x5, +0xd, 0x17,0x20,0x2a,0x32,0x3b,0x45,0x4e,0x58,0x63,0x69,0x6b,0x6a,0x64,0x5d,0x57, +0x4f,0x47,0x40,0x38,0x32,0x2f,0x1a,0xb5,0x30,0x55,0x21,0x13,0xc, 0x8, 0x5, 0x2, +0x1, 0x0, 0x0, 0x1, 0x3, 0x8, 0xf, 0x17,0x1e,0x24,0x2b,0x32,0x39,0x3d,0x3e,0x3f, +0x3f,0x3d,0x3a,0x36,0x30,0x29,0x21,0x1a,0x16,0x13,0x5, 0x9, 0xe, 0x14,0x1a,0x22, +0x29,0x30,0x38,0x3f,0x47,0x4d,0x51,0x51,0x4f,0x4d,0x49,0x42,0x39,0x31,0x2b,0x25, +0x1e,0x17,0x10,0x8, 0x3, 0x0, 0x0, 0x1, 0x3, 0x5, 0xaf,0x13,0x30,0x55,0x38,0x3f, +0x3d,0x3a,0x36,0x2e,0x26,0x1f,0x14,0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, +0x9, 0xe, 0x14,0x1c,0x23,0x2a,0x34,0x38,0x3a,0x3b,0x3d,0x3d,0x3d,0x3d,0x29,0x1a, +0x10,0x9, 0x4, 0x0, 0x0, 0x1, 0x4, 0xc, 0x14,0x1c,0x22,0x28,0x2f,0x37,0x3f,0x47, +0x4f,0x56,0x5a,0x5b,0x59,0x56,0x4e,0x47,0x40,0x37,0x30,0x28,0x22,0x1f,0x2a,0xa9, +0x30,0x55,0x3e,0x3b,0x38,0x33,0x2b,0x24,0x1d,0x16,0x10,0x7, 0x3, 0x1, 0x0, 0x0, +0x0, 0x1, 0x1, 0x3, 0x6, 0xc, 0x15,0x1c,0x23,0x29,0x2f,0x35,0x38,0x3b,0x3c,0x3e, +0x3f,0x3f,0x1f,0x10,0xa, 0x6, 0x0, 0x0, 0x0, 0x2, 0x4, 0xc, 0x12,0x18,0x1e,0x25, +0x2c,0x35,0x3c,0x42,0x4a,0x51,0x56,0x56,0x53,0x4e,0x49,0x40,0x3a,0x33,0x2c,0x25, +0x1f,0x1c,0xf9,0xa2,0x30,0x55,0x1f,0x2b,0x31,0x35,0x38,0x3b,0x3e,0x3f,0x3f,0x3d, +0x3a,0x34,0x2d,0x27,0x23,0x1d,0x17,0x10,0x9, 0x4, 0x1, 0x0, 0x0, 0x1, 0x3, 0x6, +0xa, 0xf, 0x15,0x1b,0x20,0x23,0x45,0x42,0x3e,0x38,0x34,0x2d,0x24,0x1c,0x15,0x11, +0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x3, 0x7, 0xd, 0x12,0x18,0x20,0x28,0x30,0x36, +0x3c,0x42,0x47,0x48,0x49,0x4a,0x65,0x9d,0x30,0x55,0x1c,0x2a,0x33,0x39,0x3c,0x3e, +0x3f,0x3f,0x3e,0x3d,0x3a,0x35,0x2e,0x28,0x23,0x1c,0x15,0xf, 0x9, 0x4, 0x1, 0x0, +0x0, 0x1, 0x1, 0x4, 0x8, 0xd, 0x13,0x19,0x1e,0x22,0x40,0x3e,0x3a,0x33,0x2f,0x29, +0x22,0x1b,0x15,0x10,0xa, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x5, 0xa, 0x11,0x17,0x1c, +0x24,0x2a,0x30,0x35,0x3b,0x40,0x43,0x44,0x45,0x45,0xcb,0xc6,0x30,0x55,0x5, 0x3, +0x4, 0x7, 0xa, 0x10,0x17,0x21,0x28,0x2e,0x33,0x38,0x3c,0x3e,0x3f,0x3f,0x3e,0x3b, +0x38,0x31,0x29,0x21,0x18,0xf, 0x9, 0x4, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26,0x35, +0x3d,0x45,0x4b,0x51,0x53,0x52,0x4f,0x4c,0x46,0x41,0x3b,0x34,0x2e,0x25,0x1e,0x17, +0x11,0x9, 0x3, 0x0, 0x0, 0x2, 0x6, 0xc, 0x12,0x18,0x1e,0x24,0x2c,0x31,0xf4,0xb6, +0x30,0x55,0xa, 0x5, 0x5, 0x5, 0x8, 0xf, 0x16,0x20,0x29,0x31,0x36,0x3a,0x3c,0x3e, +0x3f,0x3f,0x3e,0x3c,0x3a,0x33,0x2d,0x24,0x1c,0x14,0xf, 0x8, 0x4, 0x0, 0x0, 0x0, +0x1, 0x2, 0x35,0x46,0x4e,0x56,0x5d,0x65,0x68,0x66,0x60,0x57,0x4f,0x47,0x3f,0x37, +0x2e,0x25,0x1e,0x16,0x10,0x6, 0x2, 0x0, 0x1, 0x5, 0xb, 0x15,0x1d,0x28,0x2f,0x39, +0x41,0x45,0xf0,0xbc,0x30,0x55,0x7, 0x3, 0x3, 0x3, 0x4, 0x7, 0xf, 0x17,0x20,0x28, +0x30,0x36,0x3b,0x3d,0x3f,0x3f,0x3d,0x39,0x36,0x2d,0x25,0x1d,0x16,0xd, 0x8, 0x2, +0x0, 0x0, 0x1, 0x2, 0x3, 0x5, 0x2e,0x3f,0x48,0x50,0x59,0x5f,0x67,0x68,0x63,0x5d, +0x52,0x4a,0x3e,0x35,0x2b,0x20,0x18,0x10,0xa, 0x3, 0x0, 0x0, 0x1, 0x7, 0xe, 0x19, +0x22,0x2b,0x31,0x3a,0x42,0x47,0xef,0xc9,0x30,0x55,0x3b,0x3c,0x3c,0x3b,0x39,0x36, +0x2f,0x27,0x21,0x19,0x11,0xb, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x4, 0x6, 0xa, 0x10, +0x16,0x1f,0x26,0x2d,0x33,0x39,0x3c,0x3e,0x3f,0x3f,0x22,0x31,0x3b,0x41,0x47,0x4d, +0x56,0x59,0x5a,0x58,0x55,0x51,0x4b,0x43,0x3d,0x35,0x29,0x20,0x18,0x11,0x9, 0x3, +0x0, 0x0, 0x1, 0x3, 0x7, 0xf, 0x15,0x1b,0x21,0x26,0x2b,0xa0,0x30,0x55,0x37,0x38, +0x37,0x34,0x2d,0x26,0x1c,0x16,0xe, 0x9, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, +0xa, 0x10,0x17,0x20,0x26,0x2e,0x35,0x3a,0x3c,0x3e,0x3f,0x3f,0x3e,0x3e,0x30,0x40, +0x49,0x50,0x59,0x5e,0x60,0x5d,0x56,0x50,0x47,0x41,0x39,0x33,0x2a,0x20,0x1a,0x10, +0xa, 0x5, 0x1, 0x0, 0x0, 0x3, 0x8, 0x10,0x17,0x1f,0x25,0x2f,0x38,0x3c,0x37,0xc3, +0x30,0x55,0x3b,0x3d,0x3d,0x3b,0x38,0x32,0x27,0x1c,0x13,0xe, 0x8, 0x3, 0x0, 0x0, +0x0, 0x1, 0x3, 0x7, 0xb, 0x12,0x18,0x20,0x28,0x31,0x39,0x3d,0x3f,0x40,0x3f,0x3f, +0x3e,0x3e,0x33,0x45,0x4e,0x57,0x5d,0x65,0x6c,0x6a,0x66,0x63,0x5c,0x53,0x4a,0x40, +0x38,0x2e,0x25,0x1a,0x11,0x8, 0x4, 0x0, 0x0, 0x2, 0x9, 0x10,0x19,0x21,0x2a,0x32, +0x39,0x3e,0x7, 0x90,0x30,0x55,0x39,0x2b,0x24,0x1c,0x15,0xe, 0x9, 0x6, 0x5, 0x6, +0x9, 0x10,0x19,0x22,0x27,0x2e,0x35,0x3b,0x3e,0x3f,0x3d,0x38,0x32,0x2c,0x26,0x1f, +0x19,0x13,0xb, 0x5, 0x1, 0x0, 0x6, 0x0, 0x1, 0x2, 0x6, 0xb, 0x11,0x17,0x1d,0x24, +0x2a,0x2f,0x32,0x34,0x35,0x36,0x37,0x3b,0x41,0x47,0x4e,0x56,0x5d,0x61,0x64,0x65, +0x65,0x63,0x60,0x5c,0x57,0x54,0xd1,0x4a,0x46,0x55,0x0, 0x1, 0x3, 0x5, 0x7, 0x8, +0xa, 0xb, 0xc, 0xe, 0xf, 0x11,0x12,0x14,0x16,0x1a,0x1e,0x22,0x24,0x27,0x2a,0x2c, +0x2e,0x31,0x33,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x3f,0x1, 0xe, 0x14,0x1b,0x23,0x28, +0x2e,0x35,0x3a,0x40,0x48,0x4f,0x56,0x5d,0x62,0x61,0x5a,0x53,0x4e,0x47,0x40,0x3b, +0x35,0x2d,0x29,0x22,0x1b,0x17,0x10,0x9, 0x5, 0x1, 0x6d,0x7d,0x54,0x55,0x0, 0x2, +0x3, 0x5, 0x6, 0x8, 0xb, 0x10,0x13,0x16,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x22,0x22, +0x22,0x22,0x23,0x25,0x28,0x2e,0x31,0x34,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x6, 0x17, +0x20,0x27,0x30,0x38,0x3e,0x39,0x32,0x2b,0x25,0x1e,0x18,0x10,0x9, 0x9, 0x10,0x18, +0x1f,0x26,0x2f,0x36,0x3c,0x38,0x2f,0x27,0x1f,0x18,0xf, 0x8, 0x1, 0x2, 0xc7,0x75, +0x31,0x55,0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x8, 0xd, 0x12,0x15,0x17,0x18,0x1a, +0x1b,0x1c,0x1d,0x1d,0x1e,0x1f,0x22,0x27,0x2e,0x35,0x38,0x3b,0x3d,0x3e,0x3f,0x40, +0x3f,0x3e,0x6, 0x15,0x1b,0x23,0x29,0x2f,0x37,0x3c,0x37,0x2e,0x27,0x20,0x1a,0x13, +0xe, 0x14,0x1a,0x21,0x27,0x2f,0x38,0x3f,0x3d,0x35,0x2e,0x26,0x20,0x18,0x11,0xb, +0x3, 0x0, 0x67,0x3f,0x31,0x55,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, +0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x1c,0x1d,0x1e,0x1f,0x20, +0x21,0x22,0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xe, +0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x0, 0x1, 0x2, 0x3, 0x4, 0x1c,0x1d,0x1e, +0x1f,0x20,0x0, 0x1, 0x2, 0x3, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, +0x18,0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x6, 0x5, 0x4, 0x3, 0x2, 0x1, +0x0, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16, +0x17,0x18,0x19,0x1a,0x1b,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, +0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, +0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x1, 0x1, 0x10,0x1c,0x2, 0x10, +0x1c,0x0, 0x1, 0x1, 0x4, 0xf, 0x1c,0x0, 0x1, 0x1, 0x6, 0x1b,0xf, 0x7, 0xe, 0x1c, +0x8, 0x23,0x15,0x0, 0x1, 0x1, 0xa, 0x10,0x19,0xb, 0x14,0x1c,0xc, 0xf, 0x18,0x0, +0x1, 0x1, 0xe, 0x23,0x15,0xf, 0xd, 0x19,0x0, 0x1, 0x1, 0x11,0xd, 0x14,0x12,0x10, +0x19,0x13,0x1c,0x10,0x14,0x1a,0x10,0x15,0x10,0x19,0x16,0x23,0x1c,0x72,0x23,0x15, +0x73,0x23,0x1c,0x74,0x23,0x1c,0x75,0xe, 0x1c,0xc2,0xd5,0x7c,0xb4,0x30,0xe7,0x8, +0xb2,0xd5,0x6e,0x24,0xff,0xff,0xb, 0x24,0x7c,0xb6,0x30,0xe7,0x12,0xb2,0xd5,0x6e, +0x34,0xff,0xff,0xb, 0x34,0x8d,0x32,0x6e,0x24,0xff,0xff,0xb, 0x24,0x80,0x2, 0x8d, +0x32,0x30,0xd5,0x6, 0x6e,0x34,0xff,0xff,0xb, 0x34,0x22,0x7d,0x51,0xad,0x3, 0x7d, +0x2, 0x7d,0x21,0xad,0x5, 0x2d,0x12,0xad,0x35,0x2d,0x21,0x22,0x7d,0x2, 0xad,0x31, +0xad,0x10,0x2d,0x21,0x22,0x6d,0x0, 0x74,0x10,0x4d,0x0, 0x78,0xb, 0x4d,0x22,0x78, +0x27,0x8d,0x31,0x7d,0x12,0x6d,0x22,0x22,0x7d,0x43,0x7d,0x32,0x6d,0x22,0x2f,0x11, +0x2d,0x44,0x50,0x2, 0xa5,0xf, 0xbf,0x10,0x40,0x4, 0x9f,0x10,0xb, 0x90,0x14,0x78, +0xed,0x7f,0x1, 0x6d,0x22,0x7d,0x34,0x22,0x7d,0x41,0x7d,0x13,0x8d,0x24,0x7d,0x2, +0x2f,0x0, 0x40,0x4, 0xbd,0x4, 0x40,0x4, 0x9d,0x4, 0xb, 0x14,0x14,0x78,0xf1,0x7d, +0x23,0x7d,0x31,0x7d,0x10,0x6d,0x0, 0x22,0xc2,0xd5,0x7c,0xb0,0x30,0xe7,0x8, 0xb2, +0xd5,0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x7c,0xb4,0x30,0xe7,0x13,0xb2,0xd5,0x9f,0x22, +0x9f,0x21,0x7f,0x12,0x12,0x1f,0x7, 0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x80,0x3, 0x12, +0x1f,0x7, 0x30,0xd5,0x6, 0x9f,0x22,0x9f,0x21,0x7f,0x12,0x22,0x6c,0xaa,0x4d,0x11, +0x68,0x1a,0x1e,0x54,0x68,0xe, 0xb, 0x38,0x20,0x1b,0x18,0x20,0xb, 0x35,0xb, 0x15, +0x1b,0x54,0x78,0xf2,0x50,0x6, 0x7e,0x39,0x40,0x7a,0x19,0x40,0x22,0x6c,0xaa,0x4d, +0x11,0x68,0x1e,0x1e,0x54,0x50,0xc, 0x7e,0x1b,0x0, 0x7a,0x19,0x0, 0x68,0x12,0xb, +0x1c,0xb, 0x14,0xb, 0x1a,0x0, 0x1b,0x18,0x0, 0xb, 0x1d,0xb, 0x15,0x1b,0x54,0x78, +0xf2,0x22,0x75,0x84,0x1, 0x7e,0x44,0x3f,0xff,0xe4,0x7a,0x49,0xb0,0x1b,0x44,0x78, +0xf9,0x7e,0xf8,0x3a,0x10,0x75,0xc, 0x0, 0x75,0xd, 0x0, 0x75,0xe, 0x2, 0x75,0xf, +0x0, 0xc2,0x8, 0xc2,0x9, 0x75,0x1d,0x0, 0xc2,0x10,0xc2,0x11,0xc2,0x13,0x75,0x1e, +0x0, 0x75,0x1f,0x0, 0xc2,0xa, 0xc2,0xb, 0x75,0x5a,0x0, 0xc2,0x15,0x75,0x5b,0x0, +0xc2,0x17,0x75,0x5c,0x0, 0xc2,0x18,0xc2,0x19,0xc2,0x1a,0x75,0x5d,0x0, 0xc2,0xc, +0x75,0x1b,0x0, 0x75,0x1c,0x64,0xc2,0x1b,0xc2,0x1c,0x75,0x5e,0x0, 0xd2,0x5, 0xd2, +0x6, 0xd2,0x7, 0xd2,0x1d,0xc2,0xe, 0xd2,0xf, 0x7e,0x4, 0x0, 0xff,0x7e,0x14,0x21, +0x1a,0xb, 0xa, 0x40,0x5d,0x44,0x68,0x1a,0x69,0x20,0x0, 0x2, 0xb, 0xe, 0xb, 0x44, +0x80,0xa, 0x7e,0xb, 0xb0,0x7a,0x29,0xb0,0xb, 0x24,0xb, 0xc, 0x1b,0x44,0x78,0xf2, +0x80,0xdf,0x2, 0x28,0x9, 0x0, 0x0, 0x0, 0x47,0x0, 0xcb,0x1, 0x0, 0x0, 0x10,0xfd, +0xc7,0xfb,0x7e,0xfb,0xfb,0x1, 0xbb,0xc, 0x9e,0x19,0x0, 0x21,0x45,0x0, 0xe, 0x1, +0xf, 0x2, 0x10,0x3, 0x11,0x4, 0x12,0x5, 0x13,0x6, 0x14,0x7, 0x15,0x8, 0x16,0x9, +0x17,0xa, 0x18,0xb, 0x19,0xc, 0x1a,0xd, 0x1b,0xdf,0x22,0xc3,0x21,0xa9,0x20,0x94, +0x1f,0x81,0x1e,0x70,0x1d,0x62,0x1c,0x55,0x1b,0x4a,0x1a,0x41,0x19,0x38,0x18,0x31, +0x17,0x2b,0x16,0x25,0x15,0x21,0x14,0x1c,0x13,0x19,0x12,0x16,0x11,0x13,0x10,0x11, +0xf, 0x10,0xe, 0xca,0xf8,0x7f,0x20,0x80,0xa, 0x7e,0x1b,0xf0,0x7a,0x2b,0xf0,0xb, +0x34,0xb, 0x54,0x69,0xff,0xff,0xfc,0x7d,0xef,0x1b,0xe4,0x79,0xef,0xff,0xfc,0x4d, +0xff,0x78,0xe6,0x7f,0x10,0xda,0xf8,0x22,0x7d,0x43,0x7f,0x10,0x80,0x7, 0x1b,0x44, +0x7a,0xb, 0xb0,0xb, 0x14,0x4d,0x44,0x78,0xf5,0x22,0xff,0x0, 0x1, 0x2, 0x0, 0xff, +0x1, 0x2, 0x0, 0x1, 0xff,0x2, 0x0, 0x1, 0x2, 0xff,0x7d,0x23,0xbe,0x24,0x0, 0x0, +0x48,0x3, 0x7d,0x32,0x22,0x6d,0x33,0x9d,0x32,0x22,0x0, 0x4, 0x32,0xe5,0x0, 0x0, +0x0, 0x0, 0x0, 0x1, 0x3, 0xff,0x1, 0x0, 0x1, 0x25,0xf6,0x1, 0x0, 0x1, 0x38,0x9c, +0x0, 0x0, 0x2, 0x38,0xee,0x0, 0x0, 0x0, 0x2, 0x38,0xf0,0x0, 0x0, 0x0, 0x1, 0x38, +0xf2,0x0, 0x0, 0x1, 0x37,0xe1,0xff,0x0, 0x1, 0x34,0x4f,0x0, 0x0, 0x1, 0x3a,0xe, +0x0, 0x0, 0x1, 0x34,0x8b,0x0, 0x0, 0x2, 0x34,0xb4,0x0, 0x0, 0x0, 0x1, 0x34,0xb6, +0x0, 0x0, 0x1, 0x34,0xc4,0x0, 0x0, 0x1, 0x34,0xc5,0x0, 0x0, 0x1, 0x34,0xda,0x0, +0x0, 0x1, 0x34,0xdb,0x0, 0x0, 0x1, 0x35,0x54,0x0, 0x0, 0x1, 0x35,0x55,0x1, 0x0, +0x1, 0x35,0x56,0x0, 0x0, 0x3c,0x36,0xe9,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x37,0x61,0x0, 0x0, 0x1, 0x37,0x62,0x0, 0x0, 0x1, +0x37,0x63,0x0, 0x0, 0x1, 0x36,0xe2,0x1, 0x0, 0x2, 0x36,0xe5,0x0, 0x0, 0x0, 0x1, +0x2f,0xa9,0x0, 0x0, 0x1, 0x2f,0xaa,0x0, 0x0, 0x1, 0x2f,0xab,0x0, 0x0, 0x1, 0x37, +0x66,0x1, 0x0, 0x1, 0x37,0xe0,0x0, 0x0, 0x1, 0x3a,0xf, 0x0, 0x0, 0x6, 0x39,0xfc, +0x3f,0x1f,0x50,0x11,0x20,0x10,0x0, 0x1, 0x3a,0x2, 0x24,0x0, 0x1, 0x3a,0x9, 0x0, +0x0, 0x1, 0x3a,0xa, 0x0, 0x0, 0x1, 0x3a,0xb, 0x0, 0x0, 0x1, 0x3a,0xc, 0x0, 0x0, +0x1, 0x3a,0xd, 0x0, 0x0, 0x1, 0x0, 0x5f,0x0, 0x0, 0x1, 0x3, 0xfc,0x0, 0x0, 0x1, +0x31,0xcd,0x0, 0x0, 0x2, 0x31,0xee,0x0, 0x0, 0x0, 0x1, 0x32,0x2c,0x0, 0x0, 0x4, +0x38,0x41,0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3a,0x3, 0x0, 0x0, 0x1, 0x3a,0x4, 0x0, +0x0, 0x2, 0x3a,0x5, 0x0, 0x0, 0x0, 0x1, 0x3a,0x7, 0x64,0x0, 0x1, 0x3a,0x8, 0x0, +0x0, 0x1, 0x3a,0x10,0x0, 0x0, 0x1, 0x3, 0xfd,0x0, 0x0, 0x1, 0x3, 0xfe,0x0, 0x0, +0x2, 0x2b,0xb9,0x2b,0xbf,0x0, 0x1, 0x2f,0x7f,0x2, 0x0, 0x1, 0x2f,0xa8,0x0, 0x0, +0x1, 0x39,0x3f,0xff,0x0, 0x1, 0x39,0x40,0x0, 0x0, 0x1, 0x39,0x41,0x0, 0x0, 0x1, +0x39,0x42,0x40,0x0, 0x1, 0x39,0x43,0x40,0x0, 0x1, 0x39,0xde,0x0, 0x0, 0x4, 0x39, +0xf4,0x0, 0x0, 0x50,0x0, 0x0, 0x4, 0x39,0xf8,0x0, 0x0, 0x64,0x0, 0x0, 0x4, 0x39, +0xc1,0x0, 0x0, 0x6c,0x0, 0x0, 0x4, 0x39,0xc5,0x0, 0x0, 0x68,0xc0,0x0, 0x4, 0x39, +0xc9,0x0, 0x0, 0x68,0x0, 0x0, 0x4, 0x39,0xda,0x0, 0x0, 0x40,0x0, 0x0, 0x4, 0x33, +0xfc,0x0, 0x0, 0x60,0x0, 0x0, 0x0, 0x3, 0x84,0x0, 0xd, 0x1, 0xf4,0x2, 0xbc,0x0, +0xd, 0x1, 0x4a,0x2, 0x58,0x0, 0xc, 0x0, 0xc8,0x1, 0xf4,0x0, 0xb, 0x0, 0xa0,0x1, +0x90,0x0, 0x9, 0x0, 0x50,0x0, 0xc8,0x0, 0x7, 0x0, 0x1e,0x0, 0x3c,0x0, 0x14,0x0, +0x18,0x0, 0xe, 0x1c,0x23,0x5, 0xdc,0x0, 0x32,0x3, 0xe8,0x0, 0x28,0x0, 0x0, 0x0, +0x1e,0x12,0x31,0xa9,0x12,0x23,0x91,0x12,0x23,0x5c,0x12,0x24,0x36,0x2, 0x23,0x20, +0x12,0x23,0x31,0x7e,0xb3,0x2b,0xf, 0x12,0x57,0xfc,0x74,0x1, 0x7a,0xb3,0x37,0x6a, +0x22,0x12,0xab,0x26,0x74,0x1, 0x7a,0xb3,0x37,0x66,0x22,0x12,0x23,0xc8,0x12,0x28, +0x2b,0x12,0x58,0xef,0x12,0x31,0xa9,0x12,0x23,0xc8,0x12,0x23,0x91,0x12,0xc6,0x6e, +0x12,0x23,0x5c,0x12,0x24,0x36,0x12,0x24,0x66,0x2, 0x23,0x20,0x12,0x59,0x38,0x12, +0x23,0xae,0x2, 0x23,0x65,0x7e,0x34,0x0, 0x3, 0x6d,0x22,0x2, 0x23,0x6e,0x7d,0x43, +0x7e,0xa3,0x34,0x38,0xbe,0xa0,0x5, 0x50,0x16,0x7e,0x70,0x4, 0xac,0x7a,0x59,0x43, +0x34,0x3b,0x59,0x23,0x34,0x3d,0x7c,0xba,0x4, 0x7a,0xb3,0x34,0x38,0xc3,0x22,0xd3, +0x22,0x12,0x36,0xad,0x12,0x69,0x83,0x2, 0x23,0x9a,0x30,0x13,0x10,0x12,0x57,0x8e, +0x50,0x3, 0x12,0x51,0xf9,0x12,0x69,0xa9,0x12,0x55,0xae,0xc2,0x13,0x22,0x6d,0x33, +0x7e,0x24,0x6, 0xfc,0x12,0x23,0x6e,0x7e,0x34,0x0, 0x1, 0x7e,0x24,0x7, 0x7a,0x2, +0x23,0x6e,0x74,0x1, 0x7a,0xb3,0x38,0xa1,0x7e,0x34,0xd, 0xac,0x6d,0x22,0x7a,0x27, +0x33,0xeb,0x7a,0x37,0x33,0xed,0x22,0xca,0xf8,0x7e,0xf3,0x38,0xa1,0xbe,0xf0,0x5, +0x78,0xb, 0x74,0x1, 0x7a,0xb3,0x38,0xa1,0x12,0x0, 0xa, 0x80,0x40,0xbe,0xf0,0x4, +0x78,0xd, 0x12,0x23,0xc2,0xe4,0x7a,0xb3,0x2b,0x2, 0x12,0x36,0xad,0x80,0x2e,0xbe, +0xf0,0x6, 0x78,0x13,0x12,0x23,0xc2,0x12,0x3b,0xd3,0xe4,0x7a,0xb3,0x2b,0x1e,0x12, +0x69,0x83,0x12,0xc6,0xd0,0x80,0x16,0xbe,0xf0,0x7, 0x78,0x17,0x12,0x23,0xc2,0x12, +0x69,0x78,0x50,0xfb,0x12,0x6a,0xb8,0x12,0x23,0x9a,0x12,0x24,0x36,0x74,0x2, 0x7a, +0xb3,0x38,0xa1,0xda,0xf8,0x22,0xe4,0x7a,0xb3,0x34,0x3a,0x7a,0xb3,0x34,0x39,0x12, +0x3f,0xd2,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x2, 0x74,0x3, 0x7a,0xb3,0x34,0x3a,0x22, +0x12,0xc6,0x6e,0x12,0x4a,0x2e,0x7a,0x37,0x3a,0x5, 0x12,0x23,0xc8,0x12,0x23,0x91, +0x12,0x24,0x36,0x2, 0x24,0x66,0x74,0xa, 0x7a,0xb3,0x34,0x89,0xe4,0x7a,0xb3,0x34, +0x8a,0x7e,0x8, 0x34,0x8c,0x7e,0x34,0x0, 0xa, 0x74,0xa, 0x12,0x20,0xe8,0x7e,0x8, +0x34,0x96,0x7e,0x34,0x0, 0xa, 0xe4,0x2, 0x20,0xe8,0xca,0x3b,0x12,0x69,0x78,0x50, +0xfb,0x7e,0xf3,0x2b,0xf, 0x7c,0xbf,0x12,0x8b,0x38,0x12,0xb8,0xc9,0x7e,0xb3,0x2b, +0x1f,0xf5,0x28,0x7e,0xc3,0x2b,0x20,0x7e,0xb3,0x38,0x9, 0xb4,0x1, 0xf, 0x12,0x51, +0xbf,0x7e,0xb3,0x16,0x91,0x70,0x6, 0x12,0x24,0x36,0xc3,0xa1,0x86,0x12,0x25,0x89, +0x3e,0x34,0xca,0x39,0x7e,0x18,0x6, 0xfc,0x7e,0x8, 0x4, 0x7e,0x12,0x20,0xc3,0x1b, +0xfd,0x12,0x25,0x89,0x3e,0x34,0xca,0x39,0x7e,0x18,0x7, 0x7a,0x7e,0x8, 0x4, 0x0, +0x12,0x20,0xc3,0x1b,0xfd,0x7e,0xb3,0x38,0x9, 0xb4,0x3, 0x7, 0x12,0xa5,0x25,0x7a, +0x37,0x38,0xe4,0x74,0x1, 0x7a,0xb3,0x16,0x90,0x12,0x23,0x91,0x12,0xa5,0x16,0x12, +0x50,0xd8,0xe4,0x12,0x13,0xde,0x12,0x24,0x36,0x7e,0x8, 0x4, 0x7e,0x7a,0xd, 0x29, +0x7e,0x18,0x6, 0x76,0x7e,0xb3,0x2b,0x72,0x12,0xb9,0xea,0x7e,0x8, 0x4, 0x0, 0x7a, +0xd, 0x29,0x7e,0x18,0x5, 0xf8,0x7e,0xb3,0x25,0xf0,0x12,0xb9,0xea,0x7e,0xd3,0x2b, +0x1f,0x7e,0xe3,0x2b,0x20,0xe5,0x28,0x7a,0xb3,0x2b,0x1f,0x7a,0xc3,0x2b,0x20,0x7e, +0x34,0x8, 0xa, 0x7e,0x4, 0xd, 0xc8,0x7d,0x20,0x7d,0x10,0x12,0x56,0x2d,0x7a,0xd3, +0x2b,0x1f,0x7a,0xe3,0x2b,0x20,0x7c,0xbf,0x12,0x8a,0xbb,0x12,0xa4,0x16,0x7e,0xb3, +0x3a,0x8, 0x4, 0x7a,0xb3,0x3a,0x8, 0x7e,0x73,0x3a,0x8, 0xbe,0x70,0xfa,0x28,0x6, +0x74,0x64,0x7a,0xb3,0x3a,0x8, 0x7e,0xb3,0x16,0x90,0x60,0x9, 0x7e,0xb3,0x16,0x91, +0x60,0x3, 0xd3,0x80,0x1, 0xc3,0xda,0x3b,0x22,0x7e,0x73,0x2a,0x74,0xa, 0x27,0x7e, +0x73,0x2a,0x73,0xa, 0x37,0x2d,0x32,0x22,0x12,0x3a,0xc6,0x7e,0xb3,0x38,0x9, 0xb4, +0x3, 0x69,0x12,0xb8,0x28,0x12,0x2f,0xe7,0x12,0x2d,0x59,0x7e,0xb3,0x38,0x9d,0x30, +0xe7,0xe9,0x12,0x24,0x8a,0x12,0x25,0x89,0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, 0x0, +0x7e,0x8, 0x4, 0xfc,0x12,0x20,0xc3,0x1b,0xfd,0x12,0x25,0x89,0x3e,0x34,0xca,0x39, +0x7e,0x18,0x4, 0x7e,0x7e,0x8, 0x5, 0x7a,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0xb3,0x2b, +0x1d,0xb4,0x1, 0x15,0x12,0x67,0x6c,0x12,0x85,0xfd,0x12,0x44,0xaf,0x12,0x6a,0xc3, +0x12,0x77,0x1d,0x12,0x26,0x1b,0x12,0x3f,0xfa,0x12,0x3b,0x8, 0x12,0xad,0x82,0x7e, +0xb3,0x38,0x9d,0x54,0x7f,0x7a,0xb3,0x38,0x9d,0x80,0x90,0x12,0x6a,0x6d,0x2, 0x0, +0x46,0xe4,0x7a,0xb3,0x2b,0x2, 0x7a,0xb3,0x2b,0x1e,0x22,0x12,0x73,0x74,0x12,0x75, +0x4a,0x12,0x75,0x4a,0x12,0x8c,0xdb,0x12,0xa1,0xc1,0x12,0x88,0x7e,0x12,0x75,0x4a, +0x12,0x92,0xe7,0x12,0x75,0x4a,0x12,0x96,0xc8,0x12,0x75,0x4a,0x2, 0x26,0x3f,0xca, +0x3b,0x75,0x24,0x0, 0x6c,0xcc,0x6c,0xdd,0x7e,0xc4,0x0, 0x3c,0xca,0xc9,0x7e,0x18, +0x37,0x25,0x7e,0x8, 0x36,0xe9,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0xf3,0x28,0x84,0xa, +0xcf,0x3e,0xc4,0xca,0xc9,0x7e,0x18,0x26,0xfa,0x7e,0x8, 0x1f,0x34,0x12,0x20,0xc3, +0x1b,0xfd,0x6c,0x88,0x6c,0xee,0xe1,0x13,0x7e,0xc4,0x3, 0xff,0x7e,0xc0,0xff,0x6c, +0x99,0x80,0x4c,0x74,0x2, 0xac,0xb9,0x9, 0xb5,0x1f,0x34,0xbe,0xb0,0xff,0x68,0x3d, +0x7c,0xb9,0x12,0x88,0x65,0x60,0x36,0x74,0x2, 0xac,0xb9,0x9, 0x75,0x1f,0x35,0xa, +0x27,0x74,0x2, 0xac,0xbe,0x9, 0x75,0x37,0x26,0x12,0x96,0xa4,0x7d,0x13,0x74,0x2, +0xac,0xb9,0x9, 0x75,0x1f,0x34,0xa, 0x27,0x74,0x2, 0xac,0xbe,0x9, 0x75,0x37,0x25, +0x12,0x96,0xa4,0x2d,0x13,0xbd,0xc1,0x28,0x4, 0x7d,0xc1,0x7c,0xc9,0xb, 0x90,0xbc, +0xf9,0x38,0xb0,0xbe,0xc0,0xff,0x68,0x39,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x1f, +0x34,0x9, 0x73,0x1f,0x35,0x12,0x6d,0xcb,0xbe,0x37,0x2a,0x5a,0x48,0x23,0x7e,0x70, +0x2, 0xac,0x7c,0x9, 0x53,0x1f,0x34,0x74,0x2, 0xac,0xbd,0x19,0x55,0x1f,0x70,0x9, +0x53,0x1f,0x35,0x19,0x55,0x1f,0x71,0x74,0xff,0x19,0xb3,0x1f,0x34,0xb, 0x80,0xb, +0xd0,0xb, 0xe0,0x7e,0x73,0x36,0xe8,0xbc,0x7e,0x28,0x2, 0xc1,0x78,0x7c,0xe8,0x80, +0x6d,0x6d,0xdd,0x7e,0x80,0xff,0x6c,0x99,0x80,0x3c,0x7c,0xb9,0x12,0x88,0x65,0x60, +0x33,0x12,0xc6,0x99,0xbe,0xb0,0xff,0x68,0x2b,0x9, 0x73,0x1f,0x35,0x12,0x6f,0x81, +0x7f,0x71,0xb, 0x7a,0x50,0xbe,0x54,0x0, 0x0, 0x58,0x5, 0x6d,0x55,0x1b,0x7a,0x50, +0xb, 0x7a,0xc0,0xbd,0xcd,0x8, 0xd, 0x12,0xc6,0x99,0xf5,0x24,0x9, 0xc3,0x1f,0x35, +0x7d,0xdc,0x7c,0x89,0xb, 0x90,0xbc,0xf9,0x38,0xc0,0xbe,0x80,0xff,0x68,0x1d,0x7e, +0x71,0x24,0x74,0x2, 0xac,0xbd,0x19,0x75,0x1f,0x70,0x19,0xc5,0x1f,0x71,0x7e,0xa0, +0xff,0x7e,0x70,0x2, 0xac,0x78,0x19,0xa3,0x1f,0x34,0xb, 0xd0,0xb, 0xe0,0xbe,0xe0, +0xa, 0x40,0x8e,0x7e,0x34,0x0, 0x3c,0xca,0x39,0x7e,0x18,0x1f,0x70,0x7e,0x8, 0x1f, +0x34,0x12,0x20,0xc3,0x1b,0xfd,0x7c,0xfd,0x7e,0x8, 0x37,0x25,0x7e,0x34,0x0, 0x14, +0x74,0xff,0x12,0x20,0xe8,0xbe,0xf0,0x0, 0x28,0x35,0xa, 0x3f,0x3e,0x34,0xca,0x39, +0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x26,0xfa,0x12,0x20,0xc3,0x1b,0xfd,0xa, 0x3f,0x3e, +0x34,0xca,0x39,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x37,0x25,0x12,0x20,0xc3,0x1b,0xfd, +0x6c,0xee,0x80,0x7, 0x7c,0xbe,0x12,0x76,0xfb,0xb, 0xe0,0xbc,0xfe,0x38,0xf5,0x7a, +0xf3,0x36,0xe8,0x7a,0xf3,0x28,0x84,0x7e,0x73,0x28,0x84,0xbe,0x70,0xa, 0x28,0x6, +0x74,0xa, 0x7a,0xb3,0x28,0x84,0xda,0x3b,0x22,0x12,0x28,0x2b,0x12,0x62,0xf6,0x12, +0x58,0xef,0x12,0x23,0x11,0x7e,0xb3,0x38,0x9, 0x24,0xfd,0x68,0x9, 0xb, 0xb1,0x78, +0xf4,0x12,0x40,0x98,0x80,0xef,0x12,0x25,0x98,0x80,0xea,0xe4,0x12,0xb6,0xbd,0x12, +0xb7,0xaa,0x12,0x2f,0xe7,0x12,0xb8,0x21,0x12,0x28,0x6e,0x12,0xb6,0x6b,0x12,0xb7, +0xc1,0x12,0x0, 0x9, 0x12,0xb7,0xcd,0x12,0x68,0xad,0x12,0xb7,0xdd,0xd2,0xaf,0x12, +0xb7,0x3c,0x12,0x64,0x46,0x12,0x2a,0x98,0x12,0xb7,0x2, 0x7e,0x8, 0x33,0xef,0x12, +0xb8,0x41,0x74,0xe, 0x7e,0x70,0x19,0x7e,0x24,0xff,0xff,0x2, 0x12,0x34,0xa9,0xd5, +0xcb,0x74,0x2, 0x7e,0x70,0x3f,0x12,0x28,0xba,0x74,0xf, 0x12,0x0, 0x66,0x7c,0x7b, +0x74,0xf, 0x5e,0x70,0xfe,0x12,0x28,0xba,0x74,0xc, 0x12,0x0, 0x66,0x54,0x7f,0x68, +0x8, 0x74,0xc, 0x7e,0x70,0xf8,0x12,0x28,0xba,0x7e,0x70,0x72,0x74,0xe, 0x12,0x28, +0xba,0x74,0x7, 0x12,0x0, 0x66,0x7c,0x7b,0x5e,0x70,0xfb,0x74,0x7, 0x2, 0x28,0xb0, +0x12,0x28,0xba,0x75,0xfd,0xff,0xa9,0xc5,0xcb,0x22,0xf5,0xfd,0x7a,0x71,0xfe,0x22, +0xca,0x79,0x7d,0xd3,0x7e,0x80,0xe, 0x7e,0xf0,0x28,0x12,0x2f,0xe7,0xa9,0xd0,0xc4, +0xa9,0xd5,0xcb,0x74,0x7, 0x12,0x0, 0x66,0xf5,0x24,0x74,0x7, 0x7e,0x70,0xf, 0x12, +0x28,0xb0,0x7e,0x54,0x0, 0x78,0x7e,0x1f,0x39,0xc5,0x79,0x51,0x0, 0x6, 0x7e,0x54, +0x0, 0x80,0x7e,0x1f,0x39,0xc5,0x79,0x51,0x0, 0x8, 0x7e,0x54,0x0, 0xc, 0x7e,0x1f, +0x39,0xc5,0x79,0x51,0x0, 0x10,0xbe,0xd4,0x0, 0x2, 0x78,0x7, 0x12,0x2a,0x7d,0x44, +0x1, 0x80,0x1c,0x12,0x2a,0x7d,0x44,0x8, 0x1b,0x1a,0x50,0x4d,0xdd,0x7e,0x1f,0x39, +0xc5,0x78,0x7, 0x12,0x2a,0x81,0x54,0xfb,0x80,0x5, 0x12,0x2a,0x81,0x44,0x4, 0x1b, +0x1a,0x50,0x7e,0x1f,0x39,0xc1,0x69,0xe1,0x0, 0x84,0x69,0x51,0x0, 0x90,0x7d,0xf5, +0x2e,0x34,0x0, 0x90,0x5e,0xa0,0xf6,0x1b,0x1a,0x50,0x7e,0xb3,0x38,0x13,0xbe,0xb0, +0x6, 0x40,0x3, 0xb4,0xff,0xe, 0x12,0x2a,0x8c,0x54,0xe6,0x12,0x2a,0x89,0x4e,0x54, +0x1, 0xa4,0x80,0xc, 0x12,0x2a,0x8c,0x5e,0x54,0xfe,0xe6,0x12,0x2a,0x89,0x44,0xa4, +0x1b,0x1a,0x50,0xbe,0xd4,0x0, 0x2, 0x78,0x26,0x12,0x2f,0x3, 0x5e,0x34,0x0, 0xf, +0x1b,0xa, 0x30,0x12,0x2f,0x3, 0x4e,0x70,0x50,0x1b,0xa, 0x30,0x7e,0x34,0x0, 0x2, +0x12,0x2d,0x3a,0x12,0x2d,0x13,0x12,0x2c,0xf0,0x7a,0x37,0x32,0xe9,0x41,0x3a,0x6c, +0xee,0x41,0x34,0x4c,0xee,0x78,0x4, 0x6c,0x99,0x80,0x2b,0xbc,0x8e,0x40,0x12,0xa, +0xce,0x9, 0x9c,0x2a,0xb8,0xbe,0x90,0x23,0x40,0x3, 0x7e,0x90,0x22,0xb, 0x90,0x80, +0x15,0xa, 0x38,0xa, 0xce,0x9d,0xc3,0x9, 0x9c,0x2a,0xdb,0xbe,0x90,0x1c,0x40,0x3, +0x7e,0x90,0x1b,0x2e,0x90,0x24,0x12,0x2a,0x7d,0x5e,0x54,0x0, 0xf, 0x1b,0x1a,0x50, +0xa, 0xc9,0x3e,0xc4,0x3e,0xc4,0x3e,0xc4,0x3e,0xc4,0x12,0x2a,0x7d,0x4d,0x5c,0x1b, +0x1a,0x50,0xe5,0xe, 0x60,0x7, 0xe5,0xe, 0xbe,0xb0,0x64,0x28,0x6, 0x7e,0x34,0x0, +0x2, 0x80,0x4, 0xe5,0xe, 0xa, 0x3b,0x12,0x2d,0x3a,0x12,0x2d,0x13,0xbe,0xd4,0x0, +0x1, 0x78,0x10,0x12,0x2d,0x13,0x12,0x2c,0xf0,0x74,0x2, 0xac,0xbe,0x59,0x35,0x32, +0xeb,0x80,0xf, 0x12,0x2c,0xf0,0xa, 0x5f,0xa, 0x2e,0x2d,0x25,0x3e,0x24,0x59,0x32, +0x32,0xeb,0xb, 0xe0,0xbc,0xfe,0x28,0x2, 0x21,0xa3,0xa9,0xd5,0xcb,0x74,0x7, 0x7e, +0x71,0x24,0x12,0x28,0xb0,0xa9,0xc0,0xc4,0x7e,0x1f,0x39,0xc1,0x79,0xe1,0x0, 0x84, +0x7e,0x1f,0x39,0xc1,0x79,0xf1,0x0, 0x90,0x6d,0x33,0x7e,0xf, 0x39,0xc5,0x79,0x30, +0x0, 0x6, 0x7e,0xf, 0x39,0xc5,0x79,0x30,0x0, 0x8, 0x7e,0xf, 0x39,0xc5,0x79,0x30, +0x0, 0x10,0x7e,0xf, 0x39,0xc5,0x79,0x30,0x0, 0xe, 0xda,0x79,0x22,0x7e,0x1f,0x39, +0xc5,0x2e,0x34,0x0, 0xe, 0xb, 0x1a,0x50,0x22,0x1b,0x1a,0x50,0x7e,0x1f,0x39,0xc1, +0x2e,0x34,0x0, 0x84,0xb, 0x1a,0x50,0x22,0x6d,0x33,0x7e,0x8, 0x0, 0x24,0x7e,0x24, +0x0, 0x12,0x12,0x63,0x62,0xe5,0x34,0x20,0xe7,0x1b,0xa9,0xd5,0xcb,0x74,0x3, 0x7e, +0x71,0x27,0x12,0x28,0xba,0x74,0xb, 0x7e,0x71,0x2f,0x12,0x28,0xba,0x74,0xc, 0x7e, +0x71,0x30,0x12,0x28,0xb0,0x22,0xca,0xf8,0x7c,0xab,0xbe,0xa0,0x34,0x38,0x2, 0x61, +0xd7,0xbe,0xa0,0x35,0x78,0x6, 0x7e,0xb3,0x2b,0x10,0x81,0xed,0xbe,0xa0,0x36,0x68, +0x5, 0xbe,0xa0,0x37,0x78,0x1d,0x7e,0x35,0x8, 0x7d,0x23,0xb, 0x24,0x7a,0x25,0x8, +0x2e,0x37,0x32,0xe3,0x7e,0x39,0xb0,0xbe,0xa0,0x37,0x68,0x2, 0x81,0xed,0x75,0x1a, +0x36,0x81,0xed,0xbe,0xa0,0x38,0x68,0x5, 0xbe,0xa0,0x39,0x78,0x1b,0x7e,0xf3,0x38, +0xc1,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc1,0xbe,0xa0,0x39,0x78,0x3, 0x75,0x1a,0x38, +0xa, 0x3f,0x9, 0xb3,0x2b,0x21,0x81,0xed,0xbe,0xa0,0x3a,0x68,0x5, 0xbe,0xa0,0x3b, +0x78,0x1b,0x7e,0xf3,0x38,0xc3,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc3,0xbe,0xa0,0x3b, +0x78,0x3, 0x75,0x1a,0x3a,0xa, 0x3f,0x9, 0xb3,0x2b,0x44,0x81,0xed,0xbe,0xa0,0xfb, +0x78,0x6, 0x7e,0xb3,0x2b,0x12,0x81,0xed,0xbe,0xa0,0x5e,0x78,0x26,0x7e,0xf, 0x39, +0xc1,0x69,0x30,0x0, 0x8e,0xa, 0x56,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, +0x1, 0x3, 0x3, 0x54,0xc0,0xa, 0x36,0x5e,0x34,0x0, 0x3, 0x7c,0xa7,0x4c,0xba,0x44, +0x80,0x81,0xed,0xbe,0xa0,0x3c,0x68,0x5, 0xbe,0xa0,0x3d,0x78,0x1b,0x7e,0xf3,0x38, +0xc5,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc5,0xbe,0xa0,0x3d,0x78,0x3, 0x75,0x1a,0x3c, +0xa, 0x3f,0x9, 0xb3,0x2a,0x7a,0x81,0xed,0xbe,0xa0,0x3e,0x68,0x5, 0xbe,0xa0,0x3f, +0x78,0x1b,0x7e,0xf3,0x38,0xc7,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc7,0xbe,0xa0,0x3f, +0x78,0x3, 0x75,0x1a,0x3e,0xa, 0x3f,0x9, 0xb3,0x2a,0x9d,0x81,0xed,0xbe,0xa0,0x40, +0x40,0xd, 0xbe,0xa0,0x4d,0x38,0x8, 0xa, 0x3a,0x9, 0xb3,0x38,0x9d,0x81,0xed,0xbe, +0xa0,0x4e,0x68,0x5, 0xbe,0xa0,0x4f,0x78,0x1e,0x7e,0xf3,0x38,0xe2,0x7c,0xbf,0x4, +0x7a,0xb3,0x38,0xe2,0xbe,0xa0,0x4f,0x78,0x3, 0x75,0x1a,0x4e,0xa, 0x3f,0x2e,0x37, +0x32,0xe1,0x7e,0x39,0xb0,0x81,0xed,0xbe,0xa0,0x51,0x68,0x5, 0xbe,0xa0,0x52,0x78, +0x28,0x7e,0x14,0x60,0x0, 0x6d,0x0, 0x2e,0x4, 0x0, 0xff,0x7e,0xb3,0x38,0xed,0xa, +0x3b,0x6d,0x22,0x2f,0x10,0x7e,0x1b,0x70,0x4, 0x7a,0xb3,0x38,0xed,0xbe,0xa0,0x52, +0x78,0x3, 0x75,0x1a,0x51,0x7c,0xb7,0x81,0xed,0xbe,0xa0,0x5c,0x68,0x5, 0xbe,0xa0, +0x5d,0x78,0x1a,0x7e,0xf3,0x38,0xb6,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xb6,0xbe,0xa0, +0x5d,0x78,0x3, 0x75,0x1a,0x5c,0x7c,0xbf,0x12,0xad,0x2, 0x81,0xed,0xbe,0xa0,0x60, +0x40,0xd, 0xbe,0xa0,0x6c,0x38,0x8, 0xa, 0x3a,0x9, 0xb3,0x33,0x8f,0x80,0x7e,0xbe, +0xa0,0x6d,0x78,0x4, 0xe5,0xe, 0x80,0x75,0xbe,0xa0,0xf4,0x68,0x5, 0xbe,0xa0,0xf5, +0x78,0x18,0x7e,0x35,0xa, 0x7d,0x23,0xb, 0x24,0x7a,0x25,0xa, 0x9, 0xb3,0x32,0xe9, +0xbe,0xa0,0xf5,0x78,0x58,0x75,0x1a,0xf4,0x80,0x53,0xbe,0xa0,0xf0,0x68,0x5, 0xbe, +0xa0,0xf1,0x78,0x9, 0x7c,0x1a,0x2e,0x10,0x20,0xa5,0xe7,0x80,0x40,0xbe,0xa0,0xf2, +0x68,0x5, 0xbe,0xa0,0xf3,0x78,0x1b,0x7e,0x15,0x10,0x3e,0x14,0x7e,0x1f,0x32,0xe5, +0x2d,0x31,0xb, 0x1a,0x30,0xbe,0xa0,0xf2,0x78,0x4, 0xa, 0x56,0x80,0x1f,0x7d,0x53, +0x80,0x1b,0xbe,0xa0,0xf6,0x78,0x4, 0xe5,0xf, 0x80,0x12,0xbe,0xa0,0xf7,0x78,0x4, +0x74,0x32,0x80,0x9, 0xbe,0xa0,0xfd,0x78,0x3, 0xe4,0x80,0x1, 0xe4,0xda,0xf8,0x22, +0x7e,0xf, 0x39,0xc5,0x69,0x30,0x0, 0xa, 0x7d,0x23,0x6d,0x33,0x69,0x10,0x0, 0xc, +0x6d,0x0, 0x2f,0x10,0x74,0x7, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14, +0x78,0xf4,0x22,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x39,0xc5,0x79,0x30,0x0, 0x4, 0x7e, +0xf, 0x39,0xc5,0x69,0x30,0x0, 0x12,0x5e,0x34,0x0, 0x1, 0x68,0xf2,0x7e,0x34,0x0, +0x1, 0x79,0x30,0x0, 0x12,0x22,0x7e,0x34,0x0, 0x1, 0x7d,0x23,0x80,0x12,0x7e,0x30, +0x4, 0x80,0x5, 0x74,0xfa,0x12,0x2f,0x39,0x7c,0x23,0x1b,0x30,0xa5,0xba,0x0, 0xf3, +0x7d,0x32,0x1b,0x24,0x4d,0x33,0x78,0xe6,0x22,0x30,0x8, 0x3b,0xc2,0x8, 0x12,0x23, +0xd7,0x7e,0x73,0x38,0xa2,0x7a,0x73,0x2a,0x4d,0x7e,0x73,0x38,0xa3,0x7a,0x73,0x2b, +0x1d,0x7e,0x73,0x38,0xa3,0x7a,0x73,0x2b,0x1, 0x7e,0xb3,0x38,0xa4,0x60,0x18,0x7e, +0x34,0x0, 0x2, 0x12,0x28,0xc0,0x7e,0x34,0x0, 0x1, 0x12,0x28,0xc0,0x6d,0x33,0x12, +0x28,0xc0,0xe4,0x7a,0xb3,0x38,0xa4,0x12,0x36,0x2d,0x2, 0x2d,0x9d,0xe5,0xc, 0x70, +0x2, 0xc1,0xbc,0xe5,0xc, 0x30,0xe0,0x10,0x53,0xc, 0xfe,0x12,0xaa,0xc5,0x12,0x64, +0xdf,0x7e,0x8, 0x2a,0x6d,0x12,0x9, 0xa1,0xe5,0xc, 0x30,0xe1,0x6, 0x53,0xc, 0xfd, +0x12,0xbb,0x4c,0xe5,0xc, 0x30,0xe2,0x2f,0x53,0xc, 0xfb,0x7e,0xb3,0x2b,0x12,0x60, +0x9, 0x7e,0x8, 0x2a,0x6d,0x12,0x6, 0xba,0x80,0xb, 0x7e,0xb3,0x2b,0x65,0x7e,0x73, +0x2b,0x64,0x12,0xb, 0xad,0x7e,0x73,0x2b,0x12,0x2e,0x70,0xff,0x92,0x1, 0x74,0x19, +0x9e,0xb3,0x2a,0x77,0x12,0xb, 0x1e,0xe5,0xc, 0x30,0xe3,0x4a,0x53,0xc, 0xf7,0x7e, +0x73,0x38,0xcf,0x7a,0x73,0x2b,0xf, 0x12,0x8b,0x16,0x7a,0xb3,0x0, 0x5f,0xbe,0xb0, +0xff,0x68,0xb, 0x43,0xc, 0x20,0x7e,0x73,0x0, 0x5f,0x7a,0x73,0x38,0xa7,0x12,0x51, +0x36,0x12,0x3f,0xeb,0x7e,0x73,0x38,0xd0,0xbe,0x73,0x2b,0x62,0x68,0x6, 0x7a,0x73, +0x2b,0x62,0xd2,0x10,0x30,0x10,0x9, 0xc2,0x10,0x12,0x57,0xd5,0xe4,0x12,0xa, 0x66, +0x12,0x23,0x31,0x12,0x57,0xf8,0xe5,0xc, 0x30,0xe4,0xf, 0x53,0xc, 0xef,0x7e,0x43, +0x38,0xd1,0x7e,0x50,0xa, 0xac,0x45,0x12,0x3a,0xf8,0xe5,0xc, 0x30,0xe6,0x4e,0x53, +0xc, 0xbf,0x7e,0x73,0x38,0xbd,0xbe,0x70,0x7, 0x28,0x6, 0x74,0x7, 0x7a,0xb3,0x38, +0xbd,0xa9,0xd5,0xcb,0x74,0xe, 0x12,0x0, 0x66,0x7c,0x7b,0x5e,0x70,0xf, 0x7e,0x63, +0x38,0xbd,0xa, 0x26,0x2e,0x24,0x0, 0x3, 0x12,0x7f,0x9, 0x7c,0x65,0x4c,0x76,0x74, +0xe, 0x12,0x28,0xba,0x12,0x0, 0x66,0x12,0x28,0xb3,0x7e,0x73,0x38,0xc0,0x7a,0x73, +0x2b,0x14,0x7e,0x73,0x38,0xbf,0x7a,0x73,0x2b,0x1f,0x12,0xc6,0xd0,0xe5,0xc, 0x30, +0xe5,0xa, 0x53,0xc, 0xdf,0x7e,0xb3,0x38,0xa7,0x2, 0x3b,0x46,0x22,0x24,0xab,0x68, +0x10,0x24,0xef,0x68,0x1c,0x24,0xde,0x68,0x26,0x24,0xde,0x78,0x2f,0x74,0x5, 0x80, +0x2d,0x7e,0xb3,0x3, 0xff,0xb4,0x5, 0x2a,0x12,0x2d,0x36,0x12,0xb6,0x75,0x2, 0xb8, +0xe, 0x7e,0xb3,0x3, 0xff,0xb4,0x5, 0x1a,0x12,0x2d,0x36,0x75,0xe9,0xff,0x22,0x7e, +0xb3,0x3, 0xff,0xb4,0x5, 0xc, 0x12,0x2d,0x36,0x2, 0xb8,0x8, 0x74,0x1, 0x7a,0xb3, +0x3, 0xff,0x22,0x7e,0xf, 0x39,0xc5,0x2e,0x14,0x0, 0xe, 0xb, 0xa, 0x30,0x22,0x7c, +0x6b,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x28,0xba,0x7a,0x61,0xfc,0x12,0x28,0xb3,0x12, +0xb7,0x2, 0xd2,0x0, 0x12,0xb6,0xee,0x12,0x2f,0xee,0x12,0x13,0xde,0x2, 0x13,0x96, +0x74,0x4, 0x7d,0x30,0x12,0x2f,0x58,0x74,0x14,0x7c,0xab,0x80,0xe, 0x7e,0x70,0x3, +0x80,0x1, 0x0, 0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, 0xf7,0x7c,0x6a,0x1b,0xa0,0xa5, +0xbe,0x0, 0xea,0x22,0x74,0x2, 0x7d,0x3f,0x7d,0x23,0x7c,0x6b,0xa, 0x14,0x7c,0x73, +0x7d,0x52,0x7c,0xab,0x7e,0xb3,0x3a,0x10,0xb4,0xa5,0x3c,0x12,0x64,0x8d,0x75,0xb5, +0x1, 0xa9,0x36,0xb3,0xfc,0x12,0x2f,0xa8,0xa9,0x36,0xb3,0xfc,0x12,0x2f,0xa8,0xa9, +0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3, +0x7a,0x71,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0xa1,0xb5,0xa9,0x36,0xb3, +0xfc,0xa9,0xc6,0xb3,0xa9,0xd2,0xb4,0x22,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0x22,0x12, +0xc7,0x9, 0xc2,0x0, 0x12,0xb6,0xf9,0xc2,0x2, 0x12,0x2f,0xde,0xc2,0x0, 0x12,0xb6, +0xee,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x0, 0x66,0x7a,0x1b,0xb0,0x74,0xf, 0x6c,0x77, +0x12,0x28,0xba,0xe5,0xfc,0x7a,0xb, 0xb0,0x43,0xfc,0x10,0x2, 0x28,0xb3,0xa9,0xd0, +0xce,0xa2,0x2, 0xa9,0x91,0xc9,0x22,0x7e,0x34,0x3, 0xe8,0x2, 0x23,0xcc,0xd2,0x2, +0x12,0x2f,0xde,0x74,0x1, 0x22,0x12,0xc6,0xd9,0xb4,0x1, 0x19,0xca,0x39,0x7e,0x18, +0x38,0xdd,0x7e,0x8, 0x25,0xee,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x1f,0x25,0xf2,0x7e, +0xf, 0x25,0xee,0x80,0x17,0xca,0x39,0x7e,0x18,0x38,0xdd,0x7e,0x8, 0x2b,0x70,0x12, +0x20,0xc3,0x1b,0xfd,0x7e,0x1f,0x2b,0x74,0x7e,0xf, 0x2b,0x70,0x2, 0x30,0x2f,0x7a, +0x1f,0x2a,0xfc,0x7a,0xf, 0x2a,0xf8,0x22,0x7a,0xb3,0x2b,0x0, 0x70,0x19,0x7e,0x1f, +0x2b,0x74,0x7e,0xf, 0x2b,0x70,0x12,0x30,0x2f,0x7e,0x18,0x6, 0x76,0x7a,0x1f,0x6, +0xf4,0x7e,0x18,0x4, 0x7e,0x80,0x15,0xb4,0x1, 0x16,0x7e,0x1f,0x25,0xf2,0x7e,0xf, +0x25,0xee,0x12,0x30,0x2f,0x12,0x5d,0xd5,0x7e,0x18,0x4, 0x0, 0x7a,0x1f,0x6, 0xf8, +0x22,0x74,0x1, 0x12,0x0, 0x1e,0xe4,0x12,0x30,0x38,0x12,0x30,0x89,0xe4,0x12,0x0, +0x1e,0x74,0x1, 0x12,0x30,0x38,0x2, 0x30,0x89,0xca,0x3b,0x7e,0xd3,0x2a,0x73,0x7e, +0xc3,0x2a,0x74,0x7e,0x8, 0x1f,0x44,0x12,0xb9,0xa7,0x7e,0x8, 0x1f,0x8a,0x7e,0x34, +0x0, 0x46,0x12,0x20,0xe8,0x7e,0x8, 0x1f,0xd0,0x7e,0x34,0x0, 0xa, 0xe4,0x12,0x20, +0xe8,0x7e,0x8, 0x1f,0xda,0x7e,0x34,0x0, 0xa, 0x12,0x20,0xe8,0x7e,0xf3,0x2a,0xfc, +0x7e,0x18,0x2a,0xdc,0x7a,0x1d,0x24,0x7e,0x18,0x1f,0xd0,0x7a,0x1d,0x28,0x7c,0xbd, +0x7c,0x7c,0x7e,0x8, 0x2a,0xb9,0x12,0x31,0xdf,0x6c,0xee,0x80,0x2b,0xa, 0x3e,0x9, +0xa3,0x2a,0xdc,0xa, 0x3a,0x2e,0x34,0x20,0x7d,0x12,0x88,0x5c,0x7c,0xab,0xbe,0xa0, +0x1c,0x50,0x13,0xa, 0x3e,0x12,0x31,0xa1,0xa, 0x4a,0x19,0xb4,0x1f,0x44,0x7e,0xb3, +0x2a,0xfb,0x19,0xb4,0x1f,0x8a,0xb, 0xe0,0xbc,0xce,0x38,0xd1,0x6c,0xee,0x80,0x24, +0xa, 0x3e,0x9, 0xa3,0x2a,0xb9,0xbe,0xa0,0x23,0x50,0x17,0xa, 0x2e,0xa, 0x3c,0x2d, +0x32,0x12,0x31,0xa1,0xa, 0x4a,0x19,0xb4,0x1f,0x60,0x7e,0xb3,0x2a,0xfb,0x19,0xb4, +0x1f,0xa6,0xb, 0xe0,0xbc,0xde,0x38,0xd8,0x7e,0xb3,0x2a,0xfd,0x7e,0x8, 0x1f,0xe4, +0x60,0x9, 0x7e,0x18,0x1f,0xd0,0x12,0x7e,0x45,0x80,0x3, 0x12,0xbb,0x3b,0x6c,0xee, +0x7e,0x18,0x1f,0xe4,0x7a,0x1f,0x1f,0x34,0x74,0x2, 0xac,0xbe,0x49,0x35,0x1f,0xd0, +0x7a,0x37,0x1f,0x38,0x74,0x2, 0xac,0xbe,0x49,0x35,0x1f,0xda,0x7a,0x37,0x1f,0x3a, +0x7e,0x70,0xe, 0xac,0x7e,0x2e,0x34,0x1f,0x44,0x6d,0x22,0x7a,0x1f,0x1f,0x3c,0x7e, +0x70,0xe, 0xac,0x7e,0x2e,0x34,0x1f,0x8a,0x7a,0x1f,0x1f,0x40,0x7e,0x8, 0x1f,0x34, +0x7c,0xbf,0x7c,0x7e,0x12,0x8, 0xd1,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xb2,0xda,0x3b, +0x22,0x2e,0x37,0x2a,0xfe,0x7e,0x39,0xb0,0x22,0x74,0x1, 0x7a,0xb3,0x38,0x9, 0x12, +0x57,0xd5,0x12,0x13,0xf5,0x12,0xba,0xb3,0xe4,0x12,0xa, 0x66,0x7e,0x24,0x3, 0xd4, +0x12,0x3a,0xf8,0x74,0x1, 0x12,0x30,0x38,0x12,0xc6,0xf2,0x7e,0x34,0xd0,0xc, 0x12, +0x1, 0xe, 0x12,0x30,0x71,0x7e,0x34,0x0, 0x1, 0xe4,0x6c,0x55,0x2, 0x13,0x1, 0x7c, +0x57,0x7c,0xab,0x6c,0x77,0x80,0x4b,0xa, 0x47,0x7e,0x7d,0x24,0x2d,0xf4,0x7e,0x7b, +0x60,0xa, 0x46,0x2e,0x44,0x20,0x7d,0x12,0xc6,0xb6,0x7c,0x6b,0xbe,0x60,0xd, 0x38, +0x12,0x7e,0xd4,0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0xd4,0x14,0x78,0xfb,0x7e,0x7d, +0x28,0x80,0x15,0x9e,0x60,0xe, 0x7e,0xd4,0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0xd4, +0x14,0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40, +0xb, 0x70,0xbc,0x57,0x38,0xb1,0x6c,0x77,0x80,0x58,0xa, 0x27,0x7f,0x70,0x2d,0xf2, +0x7e,0x7b,0x60,0xbe,0x60,0xd, 0x38,0x11,0x12,0x32,0x97,0x60,0x5, 0x3e,0x44,0x14, +0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf6,0x80,0x2f,0xbe,0x60,0x1b,0x38,0x16,0x9e,0x60, +0xe, 0x12,0x32,0x97,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x2e,0xf4, +0x0, 0x6, 0x80,0x14,0x9e,0x60,0x1c,0x12,0x32,0x97,0x60,0x5, 0x3e,0x44,0x14,0x78, +0xfb,0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x8, 0xb, 0x7a,0x20,0x4d,0x24,0x1b,0x7a,0x20, +0xb, 0x70,0xbc,0xa7,0x38,0xa4,0x22,0x7e,0x44,0x0, 0x1, 0x7c,0xb6,0x22,0x7c,0x96, +0x7c,0xa7,0x12,0x30,0x38,0x7c,0xba,0x12,0x13,0xc7,0x74,0xa, 0x12,0x2f,0x39,0x7c, +0xb9,0x12,0x0, 0x1e,0x2, 0x32,0xb7,0xca,0x3b,0x7e,0xe3,0x2a,0x74,0x7e,0xf3,0x2a, +0xfa,0x74,0x1, 0x7a,0xb3,0x2a,0xfa,0x12,0x35,0xfd,0x12,0xc6,0xc8,0x12,0x25,0x89, +0x7e,0x17,0x2a,0xfe,0x6d,0x0, 0x12,0x20,0xe8,0x7e,0xd0,0x7, 0x12,0x2f,0xe7,0x6c, +0xcc,0x80,0x19,0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb, +0x7c,0x67,0x12,0x36,0x98,0x4c,0x76,0x7a,0x29,0x70,0xb, 0xc0,0x12,0x34,0x64,0xa, +0x3c,0xbd,0x32,0x48,0xde,0x12,0x34,0x73,0x30,0x1d,0xfd,0x12,0xc6,0xac,0x7e,0xb3, +0x2a,0x73,0x7c,0x7e,0x12,0x37,0x66,0x6c,0xcc,0x80,0x29,0x74,0x2, 0xac,0xbc,0x49, +0x35,0x6, 0xfc,0xbe,0x34,0x15,0x40,0x50,0x19,0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60, +0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0xb7,0x64,0xff,0x12,0x36,0x98,0x5c,0x7b,0x7a, +0x29,0x70,0xb, 0xc0,0x12,0x34,0x64,0xa, 0x3c,0xbd,0x32,0x48,0xce,0x1b,0xd0,0xbe, +0xd0,0x0, 0x58,0x88,0x12,0x33,0xe6,0x74,0x2, 0x12,0xc6,0xe2,0x12,0x33,0x6e,0x74, +0x2, 0x12,0x0, 0x1e,0x7a,0xf3,0x2a,0xfa,0x12,0x35,0xfd,0xda,0x3b,0x22,0xca,0x79, +0x7c,0xfb,0x7e,0x8, 0x24,0xf2,0x12,0xb9,0xa7,0x7e,0xa3,0x2a,0x73,0x7e,0x73,0x2a, +0x74,0x6c,0xee,0x80,0x1d,0xa, 0x2e,0x9, 0x62,0x2a,0xdc,0xa, 0x26,0x12,0x67,0x43, +0x7c,0x6b,0xbe,0x60,0x1c,0x50,0x9, 0xa, 0x2e,0x12,0x36,0x8e,0x19,0xb2,0x24,0xf2, +0xb, 0xe0,0xbc,0x7e,0x38,0xdf,0x6c,0xee,0x80,0x1a,0xa, 0x2e,0x9, 0x62,0x2a,0xb9, +0xbe,0x60,0x23,0x50,0xd, 0xa, 0x1e,0xa, 0x27,0x2d,0x21,0x12,0x36,0x8e,0x19,0xb2, +0x25,0xe, 0xb, 0xe0,0xbc,0xae,0x38,0xe2,0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e, +0x14,0x24,0xf2,0x6d,0x0, 0x7c,0xbf,0x7c,0x7e,0x12,0x11,0xba,0xb, 0xe0,0xbe,0xe0, +0x5, 0x40,0xe7,0xda,0x79,0x22,0xca,0xd8,0xca,0x79,0x7e,0xf0,0xa, 0x74,0x1, 0x7a, +0xb3,0x2a,0xfa,0x12,0x25,0x89,0x7c,0xe7,0x80,0x5d,0x12,0x2f,0xe7,0x12,0x34,0x73, +0x30,0x1d,0xfd,0x12,0xc6,0xac,0x12,0x37,0x5e,0x6c,0xdd,0x80,0x3d,0x7e,0x50,0x2, +0xac,0x5d,0x49,0x32,0x6, 0xfc,0xbe,0x34,0x14,0x78,0x50,0x14,0xa, 0x1d,0x2e,0x17, +0x2a,0xfe,0x7e,0x19,0xb0,0xbe,0xb0,0x0, 0x28,0x1e,0x14,0x7a,0x19,0xb0,0x80,0x18, +0xbe,0x34,0x19,0x28,0x28,0x10,0xa, 0x3d,0x12,0x31,0xa1,0xbe,0xb0,0xff,0x68,0x8, +0x4, 0x7a,0x39,0xb0,0x80,0x2, 0x1b,0xe0,0xb, 0xd0,0x12,0x34,0x64,0xa, 0x3d,0xbd, +0x32,0x48,0xba,0x4c,0xee,0x68,0x8, 0x7c,0xaf,0x1b,0xf0,0x4c,0xaa,0x78,0x9b,0xda, +0x79,0xda,0xd8,0x22,0x7e,0x73,0x2a,0x74,0xa, 0x37,0x7e,0x53,0x2a,0x73,0xa, 0x25, +0x2d,0x23,0x22,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0xfc,0x12,0x33,0x6e,0x74, +0x2, 0x12,0x0, 0x1e,0x74,0x5, 0x7e,0x70,0x9b,0x12,0x13,0x2c,0x12,0x34,0x96,0x7e, +0xb3,0x2a,0xfc,0x2, 0xe, 0x94,0x6c,0xaa,0x80,0x22,0xa, 0x3a,0x9, 0x73,0x2a,0xdc, +0x2e,0x34,0x20,0x7d,0x12,0x88,0x5c,0x7c,0x7b,0xa, 0x47,0x7e,0x50,0x2, 0xac,0x5a, +0x7e,0xf, 0x39,0xc1,0x2d,0x12,0x79,0x40,0x0, 0x48,0xb, 0xa0,0x7e,0x63,0x2a,0x74, +0xbc,0x6a,0x38,0xd6,0x22,0xca,0x3b,0x7e,0xb3,0x38,0x7, 0xb4,0x1, 0x2, 0x80,0x2, +0xa1,0xfa,0x6c,0xcc,0x6c,0xdd,0x7e,0xb3,0x38,0x32,0xb4,0x1, 0x8, 0x7e,0xe0,0x10, +0x7e,0xf0,0x32,0x80,0x6, 0x7e,0xe0,0xa, 0x7e,0xf0,0x1e,0x12,0x87,0xf3,0x7d,0xf3, +0x12,0x69,0x78,0x50,0xfb,0x74,0x1, 0x7a,0xb3,0x39,0x87,0x12,0x30,0x38,0x12,0x13, +0xc7,0x12,0x0, 0x1e,0x74,0xa, 0x12,0x2f,0x39,0x12,0xc6,0xc8,0x7e,0xe7,0x2b,0xd, +0x7a,0xe5,0x25,0x7e,0xb3,0x2a,0xfa,0xf5,0x24,0x74,0x4, 0x7a,0xb3,0x2a,0xfa,0x7e, +0xe7,0x2b,0xd, 0x5e,0xe4,0x0, 0x3f,0x7a,0xe7,0x2b,0xd, 0x7e,0xb3,0x2a,0xfa,0x12, +0xba,0x42,0x7c,0x7b,0x74,0x6, 0xac,0x7b,0x7e,0x24,0x0, 0x4, 0x12,0x1e,0xb9,0x7d, +0x23,0x7d,0x3f,0x12,0x7e,0x3c,0xad,0x32,0x7a,0x37,0x2b,0x7, 0x12,0x35,0xfd,0x12, +0x8f,0xf5,0xa1,0xdb,0x12,0x2f,0xe7,0x30,0x11,0x2, 0xa1,0xe1,0x7c,0xbe,0x12,0x88, +0x4c,0x12,0x34,0x84,0x80,0xf, 0x80,0x7, 0x12,0x37,0x6e,0xe4,0x12,0x49,0xe7,0x20, +0x93,0xf6,0x12,0x37,0xb7,0x30,0x1d,0xf7,0x30,0x1c,0xf4,0xd2,0x1, 0x12,0x37,0xa6, +0xe4,0x12,0x13,0xde,0xb, 0xc0,0x12,0x83,0xf3,0x12,0x90,0x3d,0x7e,0xa3,0x39,0x86, +0x4c,0xaa,0x78,0x6, 0x74,0x1, 0x7a,0xb3,0x39,0x87,0x4c,0xaa,0x68,0xb, 0x7e,0xb3, +0x38,0x32,0x70,0x5, 0xe4,0x7a,0xb3,0x39,0x86,0x12,0x36,0xa2,0x78,0x18,0x7e,0xb3, +0x39,0x86,0x60,0x12,0xe4,0x7a,0xb3,0x39,0x86,0x7a,0xb3,0x2a,0x2, 0x7a,0xb3,0x2a, +0x3, 0x7e,0xd0,0x1, 0x80,0x1b,0x12,0x36,0xa2,0x68,0x10,0x7e,0xb3,0x39,0x86,0x70, +0xa, 0x7e,0xd0,0x1, 0xe4,0x7a,0xb3,0x38,0x7, 0x80,0x6, 0xbc,0xfc,0x28,0x2, 0xa1, +0x54,0xe4,0x7a,0xb3,0x2b,0x4, 0x7e,0x35,0x25,0x7a,0x37,0x2b,0xd, 0xe5,0x24,0x7a, +0xb3,0x2a,0xfa,0x4c,0xdd,0x68,0x3, 0x12,0x24,0x36,0xda,0x3b,0x22,0x7e,0x8, 0x2a, +0x6d,0x2, 0x5, 0xb4,0x7e,0xd7,0x2b,0xd, 0xbe,0xb0,0x1, 0x28,0x2, 0xe4,0x22,0x12, +0x65,0x47,0x12,0x35,0xfd,0x7a,0xd7,0x2b,0xd, 0x7e,0x73,0x2a,0xfa,0x12,0x46,0xb2, +0xe4,0x7e,0x50,0x1, 0x12,0x13,0x1, 0x12,0x34,0x84,0x74,0x1, 0x22,0xe5,0xd, 0x60, +0x5c,0xe5,0xd, 0x30,0xe0,0x6, 0x53,0xd, 0xfe,0x12,0x35,0xfd,0xe5,0xd, 0x30,0xe1, +0x14,0x53,0xd, 0xfd,0x7e,0xb3,0x38,0xe1,0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x12, +0xc6,0xe2,0x12,0xb9,0x31,0xe5,0xd, 0x30,0xe2,0x33,0x53,0xd, 0xfb,0xe4,0x7a,0xb3, +0x38,0xe2,0x7e,0xb3,0x38,0xe1,0x70,0xf, 0x74,0x1, 0x12,0x0, 0x1e,0x7e,0x1f,0x2b, +0x74,0x7e,0xf, 0x2b,0x70,0x80,0xc, 0xe4,0x12,0x0, 0x1e,0x7e,0x1f,0x25,0xf2,0x7e, +0xf, 0x25,0xee,0x12,0x30,0x2f,0x7e,0xb3,0x2a,0xfc,0x2, 0x33,0x6e,0x22,0x2e,0x27, +0x2a,0xfe,0x7e,0x29,0xb0,0xa, 0x26,0x22,0xa, 0x2c,0x2e,0x27,0x2a,0xfe,0x7e,0x29, +0x70,0x22,0x7e,0x73,0x39,0xf3,0xa, 0x37,0x5e,0x34,0x0, 0x2, 0x22,0x7e,0xb3,0x2b, +0x2, 0x70,0x41,0x12,0x69,0x78,0x50,0xfb,0xe4,0x6c,0x77,0x6c,0x66,0x12,0x32,0x9e, +0x7e,0x8, 0x6, 0xfc,0x7e,0x1f,0x6, 0xf4,0x7e,0xb3,0x2b,0x72,0x12,0x36,0xf5,0x74, +0x1, 0x7e,0x70,0x1, 0x7e,0x60,0x1, 0x12,0x32,0x9e,0x7e,0x8, 0x7, 0x7a,0x7e,0x1f, +0x6, 0xf4,0x7e,0xb3,0x25,0xf0,0x12,0x36,0xf5,0x74,0x2, 0x7a,0xb3,0x2b,0x2, 0xe4, +0x7a,0xb3,0x16,0x90,0x22,0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7f,0x51,0x7f,0x40,0x7f, +0x15,0x12,0x65,0x54,0x12,0xc6,0xf2,0x7e,0xe0,0x1, 0x12,0x34,0x84,0x30,0x1d,0xfd, +0x74,0x2, 0x12,0x0, 0x1e,0x7f,0x4, 0x12,0x37,0x5e,0x6c,0xdd,0x80,0x18,0x74,0x2, +0xac,0xbd,0x7f,0x14,0x2d,0x35,0xb, 0x1a,0x20,0x74,0x2, 0xac,0xbd,0x7f,0x5, 0x2d, +0x15,0x12,0xc6,0xbf,0xb, 0xd0,0x7e,0x73,0x2a,0x74,0xa, 0x7, 0x7e,0x63,0x2a,0x73, +0xa, 0x16,0x2d,0x10,0xa, 0x2d,0xbd,0x21,0x48,0xd4,0x1b,0xe0,0x78,0xbc,0x7f,0x5, +0x7c,0xbf,0x2e,0x73,0x2a,0x73,0x12,0xb9,0xb0,0xda,0x79,0xda,0xd8,0x22,0x7e,0xb3, +0x2a,0x73,0x7e,0x73,0x2a,0x74,0x12,0x10,0xee,0x74,0x2, 0x2, 0x0, 0x1e,0x74,0x81, +0x7a,0xb3,0x3a,0x3, 0x22,0x80,0x1d,0x12,0x37,0x6e,0x12,0x49,0x8a,0x68,0x5, 0xc2, +0x1, 0x12,0x37,0xa6,0x7e,0xb3,0x34,0x3a,0xbe,0xb0,0x2, 0x68,0x18,0x20,0x1c,0x15, +0xe4,0x12,0x49,0xe7,0x20,0x93,0xe0,0x12,0x37,0x6e,0xa9,0xd1,0xcd,0xa9,0xc5,0xea, +0x74,0x2, 0x2, 0x49,0xe7,0x22,0x30,0x1, 0x6, 0x12,0x2f,0xee,0x2, 0x13,0x96,0x12, +0xc7,0x9, 0xc2,0x2, 0x2, 0x2f,0xde,0x30,0x1d,0x5, 0xc2,0x1, 0x12,0x37,0xa6,0xa9, +0xd1,0xcd,0xa9,0xc5,0xea,0x30,0x1c,0x3, 0x20,0x1d,0x14,0x12,0x37,0x6e,0xa9,0xd0, +0xce,0xa9,0xc4,0xc9,0x74,0x2, 0x12,0x49,0xe7,0xa9,0xd0,0xce,0xa9,0xd4,0xc9,0xa9, +0xc1,0xcd,0xd2,0x1, 0x2, 0x37,0xa6,0xca,0xf8,0x7c,0x6b,0xa5,0xbe,0x0, 0xa, 0x7c, +0xb7,0x12,0x68,0x27,0xd2,0x8, 0x2, 0x3a,0x6a,0xa5,0xbe,0x1, 0x3d,0x7a,0x73,0x38, +0x9e,0xa5,0xbf,0xad,0x2, 0x80,0x2f,0xa5,0xbf,0xae,0x4, 0xd2,0x9, 0x41,0x6a,0xa5, +0xbf,0xaa,0x5, 0x12,0x3a,0xef,0x80,0x1e,0xa5,0xbf,0xab,0xa, 0x7e,0x34,0x5, 0x7a, +0x7a,0x37,0x32,0xe3,0x80,0x10,0xa5,0xbf,0xac,0x2, 0x80,0x2, 0x41,0x6a,0x7e,0x34, +0x4, 0xfc,0x7a,0x37,0x32,0xe3,0x6d,0x33,0x1, 0xe6,0xbe,0x60,0x4, 0x40,0x20,0xbe, +0x60,0x8, 0x38,0x1b,0x12,0x3a,0x6d,0xa5,0xbe,0x7, 0x7, 0x6d,0x33,0x7a,0x35,0xa, +0x41,0x6a,0xa5,0xbe,0x8, 0x2, 0x80,0x2, 0x41,0x6a,0x12,0x7, 0xfb,0x41,0x6a,0xa5, +0xbe,0xa, 0x9, 0x43,0xc, 0x20,0x7a,0x73,0x38,0xa7,0x41,0x6a,0xa5,0xbe,0xb, 0x8, +0x12,0x3a,0x6d,0x12,0x3a,0xba,0x41,0x6a,0xbe,0x60,0x1b,0x40,0x7, 0xbe,0x60,0x1c, +0x38,0x2, 0x41,0x2, 0xbe,0x60,0x1e,0x40,0xd, 0xbe,0x60,0x23,0x38,0x8, 0x12,0x3a, +0x6f,0x43,0xc, 0x40,0x41,0x6a,0xbe,0x60,0x15,0x40,0x1a,0xbe,0x60,0x18,0x38,0x15, +0x12,0x3a,0x6f,0xd2,0x8, 0xa5,0xbe,0x15,0x2, 0x80,0x2, 0x41,0x6a,0x74,0x7, 0x7a, +0xb3,0x38,0xa1,0x41,0x6a,0xa5,0xbe,0x19,0x7, 0xe4,0x7a,0xb3,0x38,0xb6,0x41,0x6a, +0xbe,0x60,0x24,0x40,0x7, 0xbe,0x60,0x2c,0x38,0x2, 0x41,0x2, 0xa5,0xbe,0x2d,0x1b, +0x12,0x3a,0x6f,0x20,0x9, 0x2, 0x41,0x6a,0x7e,0x63,0x38,0xc9,0x7c,0x46,0x6c,0x55, +0xa, 0x37,0x2d,0x32,0x3e,0x34,0x7a,0x35,0x8, 0x41,0x6a,0xbe,0x60,0x2f,0x40,0xa, +0xbe,0x60,0x33,0x38,0x5, 0x43,0xc, 0x8, 0x41,0x2, 0xa5,0xbe,0x34,0xf, 0x43,0xc, +0x10,0xbe,0x70,0x64,0x38,0x2, 0x41,0x2, 0x7e,0x70,0x64,0x41,0x2, 0xbe,0x60,0x38, +0x68,0x4, 0xa5,0xbe,0x39,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x38,0xc2,0x7c,0xbf,0x4, +0x7a,0xb3,0x38,0xc2,0xa, 0x2f,0x19,0x72,0x2b,0x21,0xa5,0xbe,0x39,0x2, 0x80,0x2, +0x41,0x6a,0x75,0x1a,0x38,0x41,0x6a,0xbe,0x60,0x3a,0x68,0x4, 0xa5,0xbe,0x3b,0x21, +0x43,0xc, 0x2, 0x7e,0xf3,0x38,0xc4,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc4,0xa, 0x2f, +0x19,0x72,0x2b,0x44,0xa5,0xbe,0x3b,0x2, 0x80,0x2, 0x41,0x6a,0x75,0x1a,0x3a,0x41, +0x6a,0xa5,0xbe,0xfb,0x9, 0x43,0xc, 0x4, 0x7a,0x73,0x2b,0x12,0x41,0x6a,0xa5,0xbe, +0x50,0x6, 0x7a,0x73,0x38,0xed,0x41,0x6a,0xbe,0x60,0x3c,0x68,0x4, 0xa5,0xbe,0x3d, +0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x38,0xc6,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc6,0xa, +0x2f,0x19,0x72,0x2a,0x7a,0xa5,0xbe,0x3d,0x2, 0x80,0x2, 0x41,0x6a,0x75,0x1a,0x3c, +0x41,0x6a,0xbe,0x60,0x3e,0x68,0x4, 0xa5,0xbe,0x3f,0x21,0x43,0xc, 0x1, 0x7e,0xf3, +0x38,0xc8,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc8,0xa, 0x2f,0x19,0x72,0x2a,0x9d,0xa5, +0xbe,0x3f,0x2, 0x80,0x2, 0x41,0x6a,0x75,0x1a,0x3e,0x41,0x6a,0xbe,0x60,0x40,0x40, +0xd, 0xbe,0x60,0x42,0x38,0x8, 0x12,0x3a,0x6f,0x75,0xd, 0x1, 0x80,0xa, 0xa5,0xbe, +0x43,0xb, 0x12,0x3a,0x6f,0x75,0xd, 0x2, 0x12,0x2f,0xf6,0x80,0x7d,0xa5,0xbe,0x44, +0x8, 0x12,0x3a,0x6f,0x12,0x3a,0x76,0x80,0x71,0xbe,0x60,0x45,0x68,0x4, 0xa5,0xbe, +0x46,0x5, 0x12,0x3a,0x6f,0x80,0x63,0xbe,0x60,0x4e,0x68,0x4, 0xa5,0xbe,0x4f,0x20, +0x43,0xd, 0x4, 0x7e,0xf3,0x38,0xe3,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xe3,0xa, 0x2f, +0x2e,0x27,0x32,0xe1,0x7a,0x29,0x70,0xa5,0xbe,0x4f,0x3f,0x75,0x1a,0x4e,0x80,0x3a, +0xa5,0xbe,0x6d,0x5, 0x7a,0x71,0xe, 0x80,0x31,0xbe,0x60,0xf0,0x40,0x25,0xbe,0x60, +0xf3,0x38,0x20,0x7c,0x16,0x2e,0x10,0x20,0x7c,0xb7,0xa5,0xf7,0xa5,0xbe,0xf3,0x1a, +0x7e,0x15,0x12,0x7e,0x5, 0x10,0x3e,0x4, 0x7e,0x1f,0x32,0xe5,0x2d,0x30,0x1b,0x1a, +0x10,0x80,0x7, 0xa5,0xbe,0xf6,0x3, 0x7a,0x71,0xf, 0xda,0xf8,0x22,0xd2,0x8, 0xa, +0x26,0x19,0x72,0x38,0x9d,0x22,0x12,0xc6,0xd9,0xb4,0x1, 0x1c,0xca,0x39,0x7e,0x18, +0x25,0xee,0x7e,0x8, 0x38,0xdd,0x12,0x20,0xc3,0x1b,0xfd,0x12,0x3a,0xbd,0x7e,0x1f, +0x25,0xf2,0x7e,0xf, 0x25,0xee,0x80,0x1f,0xca,0x39,0x7e,0x18,0x2b,0x70,0x7e,0x8, +0x38,0xdd,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x37,0x2b,0x76,0x7a,0x37,0x32,0xe1,0x7e, +0x1f,0x2b,0x74,0x7e,0xf, 0x2b,0x70,0x2, 0x30,0x2f,0xb2,0x82,0x22,0x7e,0x37,0x25, +0xf4,0x7a,0x37,0x32,0xe1,0x22,0x12,0x3a,0xef,0x12,0x3a,0xbd,0x6d,0x33,0x7a,0x35, +0xa, 0x12,0x3b,0x25,0x12,0x3a,0xff,0x74,0x50,0x7a,0xb3,0x38,0xd1,0x7e,0x24,0x3, +0x20,0x12,0x3a,0xf8,0xe4,0x12,0xc6,0x70,0x6d,0x33,0x7a,0x37,0x3a,0x5, 0x22,0x7e, +0x34,0xd, 0xc8,0x7a,0x37,0x32,0xe3,0x22,0x7d,0x32,0x74,0xfa,0x2, 0x12,0xd0,0x7e, +0x73,0x2b,0x62,0x7a,0x73,0x38,0xd0,0x22,0xa2,0xe, 0xe4,0x33,0x7a,0xb3,0x38,0xcb, +0x7e,0x73,0x38,0xcf,0xbe,0x73,0x2b,0xf, 0x68,0xa, 0xe5,0xc, 0x70,0x6, 0x12,0x3b, +0x25,0x12,0x3a,0xff,0x22,0x7e,0x73,0x2b,0xf, 0x7a,0x73,0x38,0xcf,0x7e,0x73,0x2b, +0x1f,0x7a,0x73,0x38,0xbf,0x7e,0x73,0x2b,0x20,0x7a,0x73,0x38,0xbe,0x7e,0x73,0x2b, +0x14,0x7a,0x73,0x38,0xc0,0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0x7e,0xa0,0x4, 0xbe, +0xd0,0x80,0x78,0x18,0x7e,0xe0,0xff,0x6c,0xff,0x80,0xb, 0x12,0x3b,0xae,0x38,0x4, +0x7c,0xeb,0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38,0xf1,0x80,0x1a,0xbe,0xd0,0x81,0x78, +0x15,0x6c,0xee,0x6c,0xff,0x80,0xb, 0x12,0x3b,0xae,0x40,0x4, 0x7c,0xeb,0x7c,0xdf, +0xb, 0xf0,0xbc,0xaf,0x38,0xf1,0xbc,0xad,0x38,0x2, 0x6c,0xdd,0x7c,0xbd,0x12,0x51, +0x89,0x12,0x3b,0x3d,0x12,0x3f,0x95,0x12,0x3b,0xca,0x7e,0x73,0x2b,0xf, 0x7a,0x73, +0x38,0xcf,0x12,0x3a,0xff,0x7a,0xd3,0x38,0xa7,0xda,0x79,0xda,0xd8,0x22,0x7e,0x90, +0x5, 0xac,0x9f,0x9, 0xb4,0x26,0x33,0xbc,0xbe,0x22,0x30,0x0, 0x3, 0x12,0x3b,0x3d, +0xa2,0x1, 0x92,0x2, 0x12,0x3c,0x88,0x2, 0x3b,0xca,0x7e,0x73,0x2b,0x20,0x7a,0x73, +0x38,0xbe,0x22,0x74,0x40,0x7a,0xb3,0x2b,0x20,0x12,0x57,0x8e,0x50,0x9, 0xd2,0x0, +0xd2,0x1, 0x12,0x3b,0xba,0x80,0x1c,0x74,0x1, 0x12,0x3c,0xc, 0x7e,0x43,0x38,0xbc, +0x7e,0x50,0x64,0xac,0x45,0x12,0x80,0x27,0x7a,0xb3,0x2b,0x1f,0x7e,0xf, 0x39,0xda, +0x12,0x3e,0xfb,0x12,0x3b,0xca,0x12,0x3f,0x95,0x2, 0x3b,0x3d,0xca,0x3b,0x7c,0xdb, +0xe4,0x7a,0xb3,0x2b,0x14,0x12,0x3f,0xeb,0x7e,0xc0,0xa, 0x12,0x3f,0xa5,0x30,0xf, +0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x1f,0x39,0xda,0x12,0x83,0x93,0x7d,0x73,0xbe, +0x74,0xff,0xff,0x78,0x9, 0x12,0x3c,0x7c,0x2e,0x34,0x0, 0x3, 0x80,0x18,0xbe,0x74, +0x80,0x0, 0x28,0x7, 0x12,0x3c,0x7c,0xb, 0x35,0x80,0xb, 0xbe,0x74,0x40,0x0, 0x28, +0xc, 0x12,0x3c,0x7c,0xb, 0x34,0x1b,0xa, 0x30,0x1b,0xc0,0x78,0xbe,0xbe,0xd0,0x1, +0x78,0x9, 0x7e,0x1f,0x39,0xda,0x12,0x80,0x46,0x7d,0x73,0x7e,0x1f,0x39,0xc9,0x69, +0x31,0x0, 0x1a,0x7a,0x73,0x2b,0x14,0x7d,0x37,0xda,0x3b,0x22,0x7e,0xf, 0x39,0xc9, +0x2e,0x14,0x0, 0x1a,0xb, 0xa, 0x30,0x22,0xca,0x3b,0x7e,0x34,0xff,0xff,0x7a,0x35, +0x34,0x7e,0xb3,0x38,0xb2,0xf5,0x29,0x7e,0xb3,0x2a,0x6d,0xf5,0x2a,0x7e,0xb3,0x2a, +0x6e,0xf5,0x2b,0x7e,0xb3,0x2a,0x70,0xf5,0x2c,0x7e,0xb3,0x2a,0x6f,0xf5,0x2d,0x7e, +0x34,0x27,0x10,0x7a,0x35,0x2e,0x7e,0x18,0x40,0x0, 0x7a,0x1d,0x30,0x12,0x3f,0x9e, +0x30,0xf, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x8, 0x34,0x0, 0x12,0x3f,0xf2,0x6c, +0xff,0x80,0x34,0x9f,0x77,0x6c,0xee,0x80,0x19,0x7e,0x11,0x2b,0xac,0x1e,0x3e,0x4, +0x7e,0x30,0x2, 0xac,0x3f,0x2d,0x10,0x7e,0x1d,0x30,0x2d,0x31,0xb, 0x1a,0x30,0x12, +0x3e,0xf4,0xe5,0x2d,0xbc,0xbe,0x38,0xe1,0xe5,0x2d,0x12,0x3f,0x6b,0x74,0x2, 0xac, +0xbf,0x59,0x35,0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xc6,0x7e,0x34,0x10, +0x0, 0x7e,0xa1,0x2b,0x74,0x2, 0xa4,0x59,0x35,0x33,0xfe,0x6c,0xff,0x80,0x72,0x9f, +0x77,0x6c,0xee,0x80,0x12,0x12,0xc6,0x47,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60, +0x80,0x14,0x78,0xf4,0x12,0x3e,0xf4,0xe5,0x29,0xbc,0xbe,0x38,0xe8,0xe5,0x29,0x12, +0x3f,0x6b,0x74,0x4, 0xac,0xbf,0x59,0x35,0x3, 0x70,0xe5,0x29,0xbe,0xb1,0x2c,0x50, +0x32,0x9f,0x77,0x7e,0xe1,0x29,0x80,0x12,0x12,0xc6,0x47,0x1e,0x34,0x1e,0x24,0x50, +0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x12,0x3e,0xf4,0xe5,0x2c,0xbc,0xbe,0x38,0xe8, +0xe5,0x29,0xa, 0x3b,0x6d,0x22,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x9f,0x1, 0x12,0x3f, +0x6f,0x80,0x4, 0x7e,0x34,0x10,0x0, 0x74,0x4, 0xac,0xbf,0x59,0x35,0x3, 0x72,0xb, +0xf0,0xe5,0x2d,0xbc,0xbf,0x38,0x88,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x7e,0x78,0x0, +0xcc,0x12,0x3f,0x8d,0x80,0x2e,0x74,0x2, 0xac,0xbf,0x49,0x25,0x34,0x0, 0xa, 0x5f, +0xad,0x53,0x7e,0x14,0x10,0x0, 0x9d,0x15,0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e,0x4, +0x50,0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x2, 0xac,0xbf,0x59,0x25, +0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xcc,0xe5,0x2a,0xa, 0x1b,0x6d,0x0, +0x12,0x3f,0x8d,0x80,0x5c,0x74,0x4, 0xac,0xbf,0x49,0x25,0x3, 0x70,0xa, 0x1f,0xad, +0x13,0x7e,0xf4,0x10,0x0, 0x9d,0xf1,0xad,0xf2,0x74,0xc, 0x1e,0xf4,0x1e,0xe4,0x50, +0x4, 0x4e,0xf4,0x80,0x0, 0x14,0x78,0xf3,0x7d,0x2f,0x74,0x4, 0xac,0xbf,0x59,0x25, +0x3, 0x70,0xe5,0x29,0xbe,0xb1,0x2c,0x50,0x26,0x74,0x4, 0xac,0xbf,0x49,0x25,0x3, +0x72,0x2e,0x14,0x10,0x0, 0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e,0x4, 0x50,0x3, 0x4e, +0x20,0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x4, 0xac,0xbf,0x59,0x25,0x3, 0x72,0xb, +0xf0,0xe5,0x2a,0xbc,0xbf,0x38,0x9e,0x7e,0x73,0x38,0xb4,0xa, 0x37,0x6d,0x22,0x74, +0xc, 0x2f,0x11,0x14,0x78,0xfb,0x7e,0xf4,0x0, 0x64,0x7d,0x1f,0x12,0x1f,0x5, 0x7d, +0xe3,0x7a,0xe5,0x34,0x7e,0x73,0x38,0xb5,0xa, 0x37,0x6d,0x22,0x74,0xc, 0x2f,0x11, +0x14,0x78,0xfb,0x7d,0x1f,0x12,0x1f,0x5, 0x7d,0x63,0x6c,0xff,0x80,0x20,0x74,0x2, +0xac,0xbf,0x49,0x45,0x34,0x0, 0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35, +0x34,0x0, 0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65,0x34,0x0, 0xb, 0xf0,0xe5,0x2c, +0xbc,0xbf,0x38,0xda,0x6c,0xff,0x80,0x3a,0x74,0x4, 0xac,0xbf,0x49,0x45,0x3, 0x70, +0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35,0x3, 0x70,0x80,0x8, 0xbd,0x46, +0x50,0x4, 0x59,0x65,0x3, 0x70,0x49,0x45,0x3, 0x72,0xbe,0x45,0x34,0x28,0x9, 0x7e, +0x35,0x34,0x59,0x35,0x3, 0x72,0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65,0x3, 0x72, +0xb, 0xf0,0xe5,0x2a,0xbc,0xbf,0x38,0xc0,0x30,0x2, 0x6, 0x7e,0xd, 0x30,0x12,0x3e, +0xfb,0xda,0x3b,0x22,0x6d,0x22,0x2f,0x71,0xb, 0xe0,0x22,0x12,0x3f,0x5, 0xb, 0x34, +0x7a,0x73,0x2b,0x20,0x22,0xca,0x79,0x7f,0x10,0x9f,0x0, 0x6c,0xaa,0xa, 0x4a,0x2e, +0x44,0x60,0xac,0x12,0xc6,0xb6,0x7c,0x9b,0x7e,0xf3,0x2a,0x6e,0xac,0xf9,0x7e,0xb3, +0x2a,0x70,0xa, 0xfb,0x2d,0xf7,0x7d,0xef,0x3e,0xe4,0x7f,0x61,0x2d,0xde,0xb, 0x6a, +0xd0,0x6d,0xcc,0x2f,0x6, 0xb, 0xa0,0xbe,0xa0,0x3, 0x78,0xd1,0xbe,0x8, 0x0, 0x0, +0x78,0x2, 0xb, 0xc, 0x7e,0x54,0x0, 0x3, 0x7f,0x10,0x7d,0x15,0x12,0x1f,0x5, 0x7f, +0x1, 0xb, 0xc, 0x7e,0x34,0xc4,0x0, 0x7e,0x24,0x0, 0x9, 0x12,0x1f,0x7, 0xbe,0x34, +0x0, 0xfa,0x28,0x4, 0x7e,0x34,0x0, 0xfa,0xda,0x79,0x22,0xa, 0x1b,0x6d,0x0, 0x7f, +0x17,0x12,0x1f,0x7, 0x7f,0x71,0x7e,0x25,0x2e,0x74,0xc, 0x7d,0x13,0x7d,0x32,0x6d, +0x22,0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0xb, 0x14,0x2, 0x1f,0x5, 0x7f,0x17,0x12, +0x1f,0x7, 0x6c,0xff,0x22,0x7e,0x73,0x2b,0x1f,0x7a,0x73,0x38,0xbf,0x22,0x7e,0x8, +0x2a,0x6d,0x12,0xd, 0x72,0xe4,0x12,0x0, 0xe, 0x74,0x1, 0x7e,0x70,0x99,0x12,0x13, +0x2c,0x2, 0x0, 0x4e,0xb4,0x3, 0x5, 0x12,0x3f,0xc4,0x80,0x2, 0xe4,0x22,0x12,0x3f, +0xa9,0x74,0x1, 0x22,0x12,0xc6,0xa3,0xe4,0x12,0x0, 0xe, 0x7e,0x8, 0x2a,0x6d,0x2, +0xd, 0x72,0x12,0x69,0x6f,0x38,0x2, 0xe4,0x22,0x12,0x69,0x67,0x49,0x55,0x34,0x3b, +0xbe,0xb0,0x2, 0x38,0x3, 0x2, 0x36,0x4, 0x2, 0x3f,0xb4,0x7e,0x8, 0x2a,0x6d,0x2, +0xd, 0x72,0x7e,0x34,0x0, 0x38,0xe4,0x2, 0x20,0xe8,0xca,0xd8,0xca,0x79,0x7e,0x73, +0x2a,0x6e,0x7e,0xf3,0x2a,0x6d,0xac,0xf7,0x7d,0x37,0x3e,0x34,0x7e,0x8, 0x1f,0x34, +0xe4,0x12,0x20,0xe8,0x7e,0xb3,0x38,0xb8,0xb4,0x1, 0x64,0x7e,0x73,0x38,0xb9,0xbe, +0x70,0x0, 0x28,0x5b,0x6c,0xdd,0x80,0x3c,0x12,0x2f,0xe7,0x12,0x24,0x8a,0x6d,0x33, +0x80,0x28,0x7e,0x35,0x24,0x3e,0x34,0x49,0x33,0xd, 0xc8,0x12,0x21,0xa, 0x7a,0x35, +0x26,0x7e,0x35,0x24,0x7d,0x13,0x3e,0x14,0x49,0x21,0x1f,0x34,0xbe,0x25,0x26,0x58, +0x7, 0x7e,0x25,0x26,0x59,0x21,0x1f,0x34,0xb, 0x34,0x7a,0x35,0x24,0xbe,0x75,0x24, +0x38,0xd0,0xb, 0xd0,0x7e,0x73,0x38,0xb9,0xbc,0x7d,0x38,0xbc,0x7d,0x37,0x3e,0x34, +0xca,0x39,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0xd, 0xc8,0x12,0x20,0xc3,0x1b,0xfd,0xda, +0x79,0xda,0xd8,0x22,0x7e,0xb3,0x38,0x6, 0xb4,0x1, 0x4, 0xe4,0x2, 0x40,0x90,0x22, +0x70,0x3, 0xd2,0x86,0x22,0xc2,0x86,0x22,0x12,0x24,0x50,0x12,0x67,0xf4,0x7e,0xb3, +0x38,0x9, 0xb4,0x1, 0x67,0x12,0xb8,0x28,0x12,0x4f,0xc5,0x12,0x88,0x7, 0x12,0x46, +0x4b,0x12,0x24,0x8a,0x50,0xe5,0x12,0x67,0x6c,0x12,0x85,0xfd,0x7e,0xb3,0x38,0x6, +0xb4,0x1, 0x4, 0xe4,0x12,0x40,0x90,0x12,0x44,0xaf,0x12,0x44,0x6c,0x40,0xcc,0x12, +0x6a,0xc3,0x12,0x44,0x6c,0x40,0xc4,0x12,0x77,0x1d,0x12,0x26,0x1b,0x12,0x47,0xc8, +0x12,0x44,0xdd,0x12,0x6f,0xf1,0x12,0x92,0x54,0x12,0x59,0xe3,0x12,0x7d,0x5a,0x12, +0x78,0x8e,0x12,0x7f,0xf6,0x12,0x79,0xe9,0x12,0x97,0xf6,0x12,0x4d,0x91,0x12,0x41, +0x12,0x12,0x4f,0xf7,0x12,0x49,0x92,0x12,0x48,0x28,0x80,0x8f,0x12,0x6a,0x6d,0x2, +0x40,0x84,0xca,0x3b,0x75,0x24,0x0, 0x6c,0xff,0x12,0x43,0x2a,0x75,0x28,0x3, 0x6c, +0xee,0x7e,0x48,0x29,0xbc,0x7e,0xb3,0x2a,0xb, 0x70,0xe, 0x7e,0xb3,0x2a,0x7, 0x70, +0x8, 0x7e,0xb3,0x2a,0x8, 0x70,0x2, 0x41,0xff,0x30,0x12,0x6, 0x7e,0x68,0x35,0xd1, +0x80,0x4, 0x7e,0x68,0x35,0x93,0x7f,0x6, 0x12,0x68,0xfc,0x7e,0x73,0x2a,0x4, 0x7a, +0x6b,0x70,0x6c,0xdd,0x41,0xb0,0x74,0x9, 0xac,0xbd,0x9, 0xc5,0x29,0xc, 0x7c,0xbc, +0x54,0xf, 0x12,0x44,0x62,0xf5,0x28,0x7c,0xbc,0x54,0xf0,0xbe,0xb0,0x0, 0x28,0x2, +0x41,0xae,0xe5,0x28,0xbe,0xb0,0x3, 0x78,0x2, 0x41,0xae,0x7e,0x8, 0x0, 0x28,0x7c, +0xbc,0x12,0x9f,0xac,0x50,0x2, 0x41,0xae,0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x29,0xd, +0xf5,0x25,0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x29,0xe, 0xc4,0x54,0xf0,0xf5,0x26,0x7e, +0x73,0x2a,0x4d,0xbc,0x7c,0x28,0x54,0x7e,0xb3,0x2a,0x9, 0x70,0x2a,0x75,0x29,0xf, +0x7e,0x8, 0x0, 0x25,0xa, 0x3c,0x2e,0x34,0x35,0x7f,0x6d,0x22,0x74,0x1, 0x12,0x46, +0x9, 0x75,0x29,0x20,0x7e,0x8, 0x0, 0x26,0xa, 0x3c,0x2e,0x34,0x35,0x89,0x6d,0x22, +0x74,0x10,0x12,0x46,0x9, 0x80,0xe, 0xa, 0x3c,0x9, 0xb3,0x35,0x7f,0xf5,0x25,0x9, +0xb3,0x35,0x89,0xf5,0x26,0xa, 0x3c,0x12,0x44,0x64,0xb4,0x1, 0xe, 0xe4,0xa, 0x3c, +0x19,0xb3,0x35,0x7f,0x19,0xb3,0x35,0x89,0x12,0x43,0x2a,0x7e,0xb3,0x2a,0x64,0xb4, +0xff,0x13,0x75,0x25,0x0, 0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x29,0xc, 0xbe,0xb0,0xff, +0x68,0x3, 0x75,0x25,0x1, 0x7e,0x90,0x9, 0xac,0x9d,0x49,0xb4,0x29,0x8, 0x49,0xa4, +0x29,0xa, 0xe5,0x28,0xb4,0x1, 0x27,0x75,0x27,0x0, 0x7e,0x71,0x27,0x74,0x9, 0xac, +0x7b,0x9, 0xb3,0x36,0x13,0x54,0xf, 0xbc,0xbc,0x78,0xa, 0x49,0xb3,0x36,0xf, 0x49, +0xa3,0x36,0x11,0x80,0x9, 0x5, 0x27,0xe5,0x27,0xbe,0xb0,0xa, 0x40,0xdc,0x5e,0xb4, +0xf, 0xff,0x5e,0xa4,0xf, 0xff,0x9, 0x74,0x29,0xc, 0xa, 0x57,0xc4,0x54,0xf0,0x7c, +0xab,0xe4,0x2d,0xa5,0xbe,0x70,0xff,0x68,0x16,0xe5,0x28,0xbe,0xb0,0x1, 0x68,0x2, +0x5, 0x24,0xb, 0xf0,0xe5,0x28,0xa, 0x5b,0x12,0x7f,0x90,0x2d,0xb5,0x80,0x4, 0x2e, +0xb4,0xc0,0x0, 0x7e,0x70,0x6, 0xac,0x7e,0x7f,0x6, 0x2d,0x13,0x79,0xb0,0x0, 0x2, +0x7f,0x6, 0x2d,0x13,0x79,0xa0,0x0, 0x4, 0xe5,0x25,0x7f,0x6, 0x2d,0x13,0x39,0xb0, +0x0, 0x6, 0xe5,0x26,0x2d,0x3d,0x7d,0x2c,0x39,0xb1,0x0, 0x7, 0xb, 0xe0,0xb, 0xd0, +0x7e,0x73,0x2a,0x4d,0xbc,0x7d,0x28,0x2, 0x21,0x56,0xe5,0x24,0x39,0xb6,0x0, 0x1, +0x7e,0xb3,0x38,0x32,0xb4,0x1, 0x9, 0x7e,0xb3,0x2a,0x8, 0xb4,0x1, 0x17,0x80,0xd, +0xbe,0xf0,0x0, 0x38,0x6, 0x7e,0xb3,0x2a,0x8, 0x60,0xa, 0xb2,0x12,0x12,0x68,0x52, +0x74,0x1, 0x12,0x40,0x90,0x7e,0xb3,0x2a,0x7, 0x60,0x5, 0x7f,0x4, 0x12,0x59,0xb1, +0xe4,0x7a,0xb3,0x2a,0xb, 0x7a,0xb3,0x2a,0x7, 0x7a,0xb3,0x2a,0x8, 0x80,0x4, 0xe4, +0x12,0x40,0x90,0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18,0x29,0x8, 0x7e,0x8, 0x36, +0xf, 0x12,0x20,0xc3,0x1b,0xfd,0x4c,0xff,0x78,0xd, 0x7e,0x8, 0x36,0xf, 0x7e,0x34, +0x0, 0x5a,0x74,0xff,0x12,0x20,0xe8,0xda,0x3b,0x22,0x75,0x25,0x0, 0x75,0x26,0x0, +0x22,0xca,0x3b,0x6c,0xff,0x7e,0xb3,0x2a,0x6f,0xf5,0x29,0x7e,0xe3,0x2a,0x70,0x6c, +0xdd,0x7e,0xb3,0x16,0x91,0xbe,0xb0,0x1, 0x68,0xf, 0x60,0x2, 0x81,0x52,0x7e,0xb3, +0x28,0x84,0xb4,0x1, 0x2, 0x80,0x2, 0x81,0x52,0x6c,0xcc,0x81,0x44,0x12,0x97,0xd4, +0xf5,0x27,0x9, 0xb3,0x26,0xfb,0xf5,0x28,0x75,0x25,0x2, 0x75,0x26,0x2, 0x12,0xa1, +0xbe,0x50,0x6, 0x75,0x25,0x3, 0x75,0x26,0x3, 0x7c,0xbc,0x12,0x70,0x47,0xd2,0x0, +0x12,0x67,0xa3,0xe5,0x27,0x60,0xe, 0xe5,0x29,0xa, 0x2b,0x1b,0x24,0xe5,0x27,0xa, +0x3b,0xbd,0x32,0x48,0x3, 0x75,0x25,0x1, 0xe5,0x28,0x60,0xc, 0xa, 0x2e,0x1b,0x24, +0xe5,0x28,0xa, 0x3b,0xbd,0x32,0x48,0x3, 0x75,0x26,0x1, 0x75,0x24,0x0, 0x80,0x6a, +0xe5,0x24,0xbc,0xbc,0x68,0x62,0x12,0xb5,0x9b,0x7a,0xa1,0x2a,0x9, 0xb3,0x26,0xfb, +0xf5,0x2b,0xa, 0x2a,0xe5,0x27,0x12,0x44,0x5b,0xbe,0x34,0x0, 0x3, 0x18,0x11,0x12, +0x44,0x55,0xbe,0x34,0x0, 0x3, 0x18,0x8, 0x75,0x25,0x1, 0x75,0x26,0x1, 0x80,0x3f, +0xe5,0x2a,0xa, 0x2b,0xe5,0x27,0x12,0x44,0x5b,0xbe,0x34,0x0, 0x8, 0x18,0xf, 0xe5, +0x2a,0xa, 0x2b,0xe5,0x27,0x12,0x44,0x5b,0xbe,0x34,0x0, 0x3, 0x18,0x12,0x12,0x44, +0x55,0xbe,0x34,0x0, 0x8, 0x18,0x11,0x12,0x44,0x55,0xbe,0x34,0x0, 0x3, 0x8, 0x8, +0x75,0x25,0x2, 0x75,0x26,0x2, 0x80,0x7, 0x5, 0x24,0x12,0x8f,0xd6,0x38,0x91,0xe5, +0x27,0x7e,0x71,0x28,0x12,0x88,0xe8,0x50,0x6, 0x12,0x44,0x84,0x12,0x43,0x2a,0xe5, +0x25,0x7e,0x71,0x26,0x7c,0x6c,0x7c,0x5f,0x7c,0x4d,0x12,0x80,0xa3,0x12,0x44,0x84, +0xb, 0xf0,0xb, 0xc0,0x7e,0x73,0x28,0x84,0xbc,0x7c,0x28,0x2, 0x61,0x5d,0x7a,0xf3, +0x28,0x84,0xda,0x3b,0x22,0xe5,0x2b,0xa, 0x2b,0xe5,0x28,0xa, 0x3b,0x9d,0x32,0x2, +0x21,0xa, 0xa, 0x3b,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0x22,0xc2,0x0, 0x7e,0xb3, +0x16,0x91,0x60,0x6, 0x7e,0xb3,0x16,0x90,0x70,0x7, 0x12,0x97,0xcc,0x28,0x2, 0xd2, +0x0, 0xa2,0x0, 0x22,0x6c,0x33,0x6c,0x22,0x80,0x1c,0x7c,0xb2,0x12,0x67,0x50,0x50, +0x13,0x7c,0xb2,0x12,0x67,0x98,0x7d,0x3, 0x12,0x67,0xda,0x49,0x55,0x39,0xe9,0x7d, +0x40,0x12,0xc6,0x79,0xb, 0x20,0x7e,0x73,0x2a,0x75,0xbc,0x72,0x38,0xdc,0x22,0x12, +0x45,0xb8,0x12,0x44,0xc1,0x12,0x44,0xcc,0x30,0x16,0x5, 0x12,0x44,0x84,0xc2,0x16, +0x22,0x2, 0x44,0xc4,0x7e,0x73,0x2a,0x6b,0x2e,0x70,0xff,0x22,0x12,0x44,0xc4,0x40, +0xb, 0x12,0xab,0x58,0xe4,0x7a,0xb3,0x3, 0xfd,0x2, 0x45,0xbe,0x22,0xca,0x3b,0x7e, +0x73,0x38,0x26,0xa, 0x37,0x6d,0x22,0x7a,0x1d,0x26,0x7e,0x33,0x38,0x28,0xa, 0xf3, +0x6d,0xee,0x7a,0x7d,0x2a,0x7e,0x33,0x38,0x27,0xa, 0x93,0x6d,0x88,0x7e,0x33,0x38, +0x29,0xa, 0x73,0x6d,0x66,0x7e,0x44,0x4, 0x38,0x7d,0x14,0x12,0x1e,0xfc,0x12,0x45, +0xb1,0x7a,0x1d,0x26,0x7e,0x54,0x7, 0x80,0x7f,0x17,0x7d,0x15,0x12,0x1e,0xfc,0x12, +0x45,0xb1,0x7a,0x1d,0x2a,0x7f,0x14,0x7d,0x14,0x12,0x1e,0xfc,0x12,0x45,0xb1,0x7f, +0x41,0x7f,0x13,0x7d,0x15,0x12,0x1e,0xfc,0x7c,0xf6,0x7c,0xe5,0xa, 0x64,0x12,0x44, +0xc4,0x50,0x60,0x7e,0xb3,0x16,0x91,0xb4,0x1, 0x59,0x75,0x2e,0x0, 0x80,0x4b,0x7e, +0xa1,0x2e,0x74,0x9, 0xa4,0x49,0x35,0x27,0x76,0x12,0x7a,0xa2,0x7a,0x35,0x24,0x7e, +0xa1,0x2e,0x74,0x9, 0xa4,0x49,0x35,0x27,0x78,0x12,0x78,0xeb,0x7d,0xa3,0x7e,0x35, +0x24,0x6d,0x22,0x7e,0xd, 0x26,0xbf,0x10,0x40,0x17,0x7d,0x5a,0x6d,0x44,0x7e,0xd, +0x2a,0xbf,0x20,0x40,0xc, 0xbf,0x14,0x38,0x8, 0x7d,0x3a,0x6d,0x22,0xbf,0x13,0x28, +0x7, 0xe5,0x2e,0x6c,0x77,0x12,0x73,0x2e,0x5, 0x2e,0x7e,0x73,0x28,0x84,0xbe,0x71, +0x2e,0x38,0xac,0xda,0x3b,0x22,0x9d,0x32,0x12,0x21,0xa, 0x7d,0x13,0x7d,0x30,0xad, +0x31,0x7c,0x76,0x7c,0x65,0xa, 0x24,0x22,0x12,0x47,0xcb,0x2, 0x45,0xbe,0xe4,0x7a, +0xb3,0x28,0x93,0x12,0xa3,0x3f,0x12,0xbc,0x1a,0x7e,0xb3,0x16,0x91,0xb4,0x1, 0x8, +0x7e,0x73,0x28,0x84,0x7a,0x73,0x28,0x92,0x7e,0x18,0x4, 0xfc,0x7a,0x1f,0x6, 0xf8, +0x12,0x5d,0xd5,0x12,0x89,0x37,0x12,0x86,0x47,0x7e,0xb3,0x16,0x90,0xb4,0x1, 0x18, +0x7e,0x73,0x26,0x83,0x7a,0x73,0x26,0xf3,0x7e,0x73,0x26,0x85,0x7a,0x73,0x26,0xf5, +0x7e,0x73,0x26,0x84,0x7a,0x73,0x26,0xf4,0x22,0x7c,0x9b,0x7f,0x71,0x7e,0x7b,0x80, +0x4c,0x88,0x78,0x7, 0x7e,0xb, 0x90,0x7a,0x7b,0x90,0x22,0xa, 0x28,0x7e,0xb, 0x80, +0xa, 0x38,0x9d,0x32,0x12,0x21,0xa, 0xe5,0x29,0xa, 0x2b,0xbd,0x32,0x8, 0x15,0x7e, +0x7b,0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x7c,0xba,0x28,0x4, 0x2c,0xb9,0x80,0x2, 0x9c, +0xb9,0x7a,0x7b,0xb0,0x7e,0x7b,0x70,0x7a,0xb, 0x70,0x22,0x7e,0x24,0x37,0xe2,0x30, +0x11,0x54,0xc2,0x11,0x9, 0x72,0x0, 0x2, 0x12,0x46,0xa7,0x7a,0x37,0x2a,0x4f,0x9, +0x72,0x0, 0x3, 0x12,0x46,0xa7,0x7a,0x37,0x2a,0x51,0x9, 0x72,0x0, 0x4, 0x12,0x46, +0xa7,0x7a,0x37,0x2a,0x53,0x7e,0x29,0x70,0x12,0x46,0xb2,0x7a,0x37,0x2a,0x5a,0x9, +0x72,0x0, 0x1, 0x12,0x46,0xb2,0x7a,0x37,0x2a,0x5c,0x9, 0x72,0x0, 0x5, 0x12,0x46, +0xa7,0x7a,0x37,0x2a,0x62,0x9, 0x72,0x0, 0x41,0xbe,0x73,0x2a,0x6b,0x68,0x7, 0x7a, +0x73,0x2a,0x6b,0x2, 0x47,0xda,0x22,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x3e, +0x34,0x22,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x22,0x7e,0x30,0x64,0x7e,0x20,0x64,0x6c, +0x11,0x80,0x4a,0xa, 0x31,0xb, 0x34,0x7c,0x7, 0x80,0x38,0x7e,0x70,0x2, 0xac,0x70, +0x9, 0xb3,0x26,0xfa,0x12,0x47,0x2e,0x9, 0xb3,0x26,0xfa,0x12,0x44,0x5b,0x7c,0x97, +0x7e,0x70,0x2, 0xac,0x70,0x9, 0xb3,0x26,0xfb,0x12,0x47,0x2e,0x9, 0xb3,0x26,0xfb, +0x12,0x44,0x5b,0x7c,0x87,0xbc,0x39,0x28,0x2, 0x7c,0x39,0xbc,0x28,0x28,0x2, 0x7c, +0x28,0xb, 0x0, 0x7e,0xb3,0x28,0x84,0xbc,0xb0,0x38,0xc0,0xb, 0x10,0x7e,0xb3,0x28, +0x84,0xbc,0xb1,0x38,0xae,0xa5,0xbb,0x64,0x2, 0x6c,0x33,0xa5,0xba,0x64,0x2, 0x6c, +0x22,0xbc,0x23,0x28,0x4, 0x7c,0xa2,0x80,0x2, 0x7c,0xa3,0x7c,0xba,0x22,0xa, 0x2b, +0x7e,0x70,0x2, 0xac,0x71,0x22,0xca,0x79,0x7c,0xe5,0x7c,0xfb,0x7e,0xe4,0xff,0xfc, +0x7c,0xb4,0x12,0xa0,0x0, 0x7d,0x3, 0x74,0x9, 0xac,0xbf,0x12,0x7f,0xa8,0x12,0x45, +0xa6,0x7d,0x13,0x5e,0x30,0xfc,0x7e,0x70,0x9, 0xac,0x7f,0x49,0xf3,0x29,0x62,0x74, +0x9, 0xac,0xbe,0x49,0x25,0x28,0xae,0xbd,0x2f,0x28,0xf, 0x7d,0x53,0x2e,0x54,0x29, +0x62,0x7d,0x2f,0x2d,0x21,0x1b,0x58,0x20,0x80,0x9, 0x2e,0x34,0x29,0x62,0x9d,0xf1, +0x1b,0x38,0xf0,0x74,0x9, 0xac,0xbf,0x49,0x25,0x29,0x64,0x74,0x9, 0xac,0xbe,0x49, +0x35,0x28,0xb0,0x12,0x45,0xa6,0x7d,0x13,0x5d,0x1e,0x7e,0x50,0x9, 0xac,0x5f,0x49, +0x32,0x29,0x64,0x74,0x9, 0xac,0xbe,0x49,0x5, 0x28,0xb0,0xbd,0x3, 0x28,0xd, 0x7d, +0x2, 0x2e,0x4, 0x29,0x64,0x2d,0x13,0x1b,0x8, 0x10,0x80,0x9, 0x2e,0x24,0x29,0x64, +0x9d,0x31,0x1b,0x28,0x30,0xda,0x79,0x22,0x2, 0x43,0x31,0x12,0x47,0xe2,0x2, 0x47, +0xd1,0x12,0x44,0xc4,0x50,0x3, 0x2, 0x48,0x9, 0x22,0x12,0x44,0xc4,0xd2,0x1a,0x2, +0x26,0x11,0x12,0x5d,0xde,0x7e,0x34,0x0, 0x78,0x7a,0x37,0x2a,0x5c,0x7e,0x34,0xff, +0x6a,0x7a,0x37,0x2a,0x5e,0x2, 0x47,0xf8,0x7e,0x34,0x0, 0xfa,0x7a,0x37,0x2a,0x4f, +0x7a,0x37,0x2a,0x51,0x7a,0x37,0x2a,0x53,0x22,0x7e,0x34,0x0, 0x32,0x7a,0x37,0x2a, +0x5a,0x7e,0x34,0x0, 0x28,0x7a,0x37,0x2a,0x5c,0x7e,0x34,0x0, 0x78,0x7a,0x37,0x2a, +0x4f,0x7e,0x34,0x0, 0x64,0x2, 0x48,0x0, 0x7e,0x8, 0x38,0xf4,0x12,0x48,0x5c,0x7e, +0x8, 0x38,0xfc,0x12,0x48,0x5c,0x12,0x48,0x71,0x12,0x48,0x78,0x2, 0x48,0x3f,0x7e, +0x37,0x38,0xf4,0xbe,0x34,0x0, 0x0, 0x28,0x12,0x7e,0x73,0x3a,0x8, 0xbe,0x70,0x5, +0x50,0x9, 0x7e,0xb3,0x38,0x32,0x70,0x3, 0x12,0x48,0x7f,0x22,0xb, 0xa, 0x30,0xe5, +0x5e,0xa, 0x2b,0xbd,0x32,0x28,0x4, 0x9d,0x32,0x80,0x2, 0x6d,0x33,0x1b,0xa, 0x30, +0x22,0x7e,0x8, 0x2b,0xb7,0x2, 0x48,0x5c,0x7e,0x8, 0x39,0xe7,0x2, 0x48,0x5c,0x6d, +0x33,0x7a,0x37,0x39,0x84,0x74,0x1, 0x7a,0xb3,0x38,0x7, 0x22,0x7e,0xb3,0x38,0x7, +0x14,0x68,0x51,0x14,0x78,0x2, 0x21,0x20,0x14,0x68,0x61,0x24,0x3, 0x78,0x79,0x12, +0x49,0x26,0x38,0x8, 0x30,0x14,0xf, 0x12,0x4f,0xd4,0x68,0xa, 0x12,0x4a,0x2e,0xe4, +0x7a,0xb3,0x39,0x86,0x80,0x6a,0x7e,0xb3,0x37,0xe8,0x30,0xe0,0x63,0x7e,0x73,0x37, +0xe9,0xa, 0x27,0x7e,0x34,0x4, 0x0, 0xad,0x32,0x7e,0xb3,0x38,0x32,0xb4,0x1, 0x4, +0x7e,0x34,0x5, 0xf4,0xbe,0x37,0x39,0x84,0x50,0x46,0x12,0x48,0x7f,0xe4,0x7a,0xb3, +0x39,0x88,0x80,0x3c,0x12,0x49,0x26,0x28,0x32,0xe4,0x7a,0xb3,0x38,0x7, 0x7e,0xb3, +0x39,0x86,0xb4,0x1, 0x3, 0x12,0x48,0x85,0xd2,0x1c,0x80,0x1f,0x74,0xff,0x7a,0xb3, +0x37,0xe1,0x12,0x4f,0xc5,0x12,0x49,0xb2,0x12,0x23,0x3b,0xe4,0x7a,0xb3,0x38,0x7, +0x7a,0xb3,0x3a,0x8, 0xd2,0x1c,0x80,0x8, 0x12,0x48,0x85,0xe4,0x7a,0xb3,0x3a,0x8, +0x12,0x49,0x2e,0x2, 0x34,0xc5,0x7e,0x73,0x2a,0x2, 0xbe,0x70,0x0, 0x22,0x74,0x1, +0x12,0x49,0x4d,0x20,0x1c,0x6, 0x12,0x49,0x70,0x12,0x0, 0x6e,0x7e,0xb3,0x34,0x3a, +0xb4,0x1, 0x6, 0x12,0x49,0x56,0x12,0x0, 0x6e,0xe4,0x2, 0x49,0x4d,0xbe,0xb0,0x8, +0x50,0x3, 0x12,0x4f,0xdc,0x22,0x74,0xc8,0x7a,0xb3,0x3a,0x7, 0xc2,0x1c,0x80,0xa, +0x12,0x37,0x75,0x30,0x1c,0x4, 0x75,0xe9,0xff,0x22,0x12,0x49,0x8a,0x68,0xf1,0x22, +0xd2,0x0, 0x80,0x12,0x30,0x0, 0xc, 0x12,0x49,0x8a,0x68,0x7, 0xc2,0x0, 0xc2,0x1, +0x12,0x37,0xa6,0x12,0x37,0x75,0x30,0x1c,0xeb,0x22,0x7e,0xb3,0x34,0x3a,0xbe,0xb0, +0x1, 0x22,0x12,0x48,0x8c,0x7e,0x73,0x37,0xe1,0xbe,0x70,0xff,0x68,0x13,0xbe,0x73, +0x38,0x7, 0x68,0xd, 0x7a,0x73,0x38,0x7, 0x74,0xff,0x7a,0xb3,0x37,0xe1,0x2, 0x48, +0x8c,0x22,0x12,0x37,0x6e,0x12,0x49,0xde,0x75,0xcd,0x0, 0xa9,0xd6,0xeb,0xa9,0xd7, +0xcd,0xc2,0xce,0x12,0x4f,0xee,0x12,0x2f,0xaf,0x74,0x1, 0x12,0x49,0xe7,0xa9,0xc6, +0xeb,0xa9,0xc7,0xcd,0xd2,0xce,0xe5,0x25,0x7e,0x71,0x24,0x2, 0x2f,0xf, 0x12,0x49, +0x8a,0x68,0xfb,0x20,0x93,0xfd,0x22,0x7c,0xab,0x7e,0xb3,0x3a,0x3, 0xb4,0x81,0x38, +0x4c,0xaa,0x78,0x5, 0xa9,0xd0,0x87,0x80,0x29,0xbe,0xa0,0x1, 0x78,0xf, 0xc2,0xaf, +0xa9,0xd0,0xce,0xa9,0xc7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf,0x80,0x15,0xbe,0xa0,0x2, +0x78,0x16,0xc2,0xaf,0x20,0x93,0x9, 0xa9,0xd0,0xce,0xa9,0xd7,0xc9,0xa9,0xd1,0x87, +0xd2,0xaf,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe4,0x7a,0xb3,0x3a,0x3, 0x22,0x6d,0x33, +0x7a,0x37,0x39,0x84,0x22,0xca,0xf8,0x7e,0xa3,0x2a,0x2, 0x7e,0x73,0x2a,0x3, 0xbe, +0xa0,0x1, 0x38,0x21,0xbe,0x70,0x1, 0x38,0x1c,0x7e,0x27,0x28,0x86,0xbe,0x24,0x0, +0x1e,0x28,0x2, 0x80,0x10,0x7e,0xf3,0x2f,0x80,0x4c,0xff,0x68,0x17,0x7e,0x27,0x2b, +0xb7,0x4d,0x22,0x78,0xf, 0x12,0x4a,0x2e,0x74,0x1, 0x7a,0xb3,0x39,0x86,0x7a,0xb3, +0x38,0x7, 0x80,0x36,0x4c,0xaa,0x78,0x37,0xa5,0xbf,0x1, 0x33,0x7e,0x37,0x2b,0xb7, +0x7a,0x37,0x2f,0x82,0x7e,0xb3,0x2f,0x80,0xb4,0x3, 0x1f,0x7e,0x37,0x2b,0xb7,0xbe, +0x34,0x0, 0x0, 0x28,0x15,0x74,0x4, 0x7a,0xb3,0x2f,0x80,0x7e,0x37,0x2f,0x98,0x7e, +0x27,0x2f,0x9a,0x12,0x4b,0x3e,0x61,0x37,0x80,0x0, 0x12,0xbe,0x2f,0x61,0x37,0x7e, +0x63,0x34,0x88,0x7e,0x50,0x9, 0xac,0x56,0x49,0xc2,0x29,0x8, 0x49,0xd2,0x29,0xa, +0x4c,0xff,0x78,0x1b,0xa5,0xbf,0x0, 0x43,0xbe,0xa0,0x1, 0x78,0x3e,0x7d,0x3c,0x7d, +0x2d,0x12,0xbd,0xcd,0x12,0x4b,0x3a,0x74,0x1, 0x7a,0xb3,0x2f,0x80,0x80,0x2c,0xbe, +0xf0,0x1, 0x78,0x1a,0x12,0x4c,0x76,0xbe,0x34,0x0, 0x64,0x38,0x9, 0x12,0x4c,0x1, +0xbe,0x34,0x0, 0xa0,0x28,0x15,0x74,0x3, 0x7a,0xb3,0x2f,0x80,0x80,0x5, 0xbe,0xf0, +0x3, 0x78,0x8, 0x7a,0xc7,0x2f,0x98,0x7a,0xd7,0x2f,0x9a,0x7e,0xb3,0x2f,0x80,0x60, +0x26,0x7d,0x3c,0x7d,0x2d,0x7e,0x17,0x2b,0xbb,0x7e,0x7, 0x2b,0xbd,0x12,0x4b,0xe9, +0xa, 0x2b,0x7e,0x73,0x2f,0x7f,0xa, 0x37,0xbd,0x32,0x58,0xb, 0x12,0x4b,0x3a,0x7a, +0xc7,0x2b,0xbb,0x7a,0xd7,0x2b,0xbd,0xda,0xf8,0x22,0x7d,0x3c,0x7d,0x2d,0x7d,0x42, +0x7d,0x13,0x7d,0x24,0x12,0x4f,0x6a,0x7d,0x31,0x12,0x4c,0xa, 0x2, 0x4b,0x4f,0x7e, +0x3, 0x2f,0xa8,0xbe,0x0, 0xf0,0x50,0x2, 0x61,0xe8,0x61,0xdd,0x6c,0x99,0x7e,0xb3, +0x2f,0x7f,0xbe,0xb0,0x20,0x50,0x5, 0x4, 0x7a,0xb3,0x2f,0x7f,0x7e,0x1f,0x2b,0xbf, +0x7a,0x1f,0x1f,0x34,0x7e,0x80,0x1, 0x80,0x49,0x74,0x4, 0xac,0xb8,0x49,0x35,0x2b, +0xbf,0x49,0x25,0x2b,0xc1,0x7e,0x17,0x1f,0x34,0x7e,0x7, 0x1f,0x36,0x12,0x4b,0xe9, +0x7c,0x1b,0x7e,0x3, 0x2f,0x7f,0xbc,0x1, 0x38,0x26,0xb, 0x90,0x7e,0x70,0x4, 0xac, +0x78,0x2e,0x34,0x2b,0xbf,0x7e,0x14,0x1f,0x34,0x74,0x4, 0x12,0x1f,0x8c,0x7e,0x34, +0x1f,0x34,0x7e,0x30,0x4, 0xac,0x39,0x2e,0x14,0x2b,0xbf,0x74,0x4, 0x12,0x1f,0x8c, +0xb, 0x80,0x7e,0x3, 0x2f,0xa8,0xbc,0x8, 0x38,0xaf,0xa, 0x59,0xb, 0x54,0x7c,0xb, +0x7a,0x3, 0x2f,0xa8,0x7e,0x3, 0x2f,0x7f,0xbe,0x0, 0x20,0x50,0xb, 0x7e,0x3, 0x2f, +0xa8,0xbe,0x0, 0xec,0x40,0x2, 0x61,0x5c,0x22,0x7d,0x51,0x7d,0x12,0x9d,0x35,0x12, +0x21,0xa, 0x7c,0xa7,0x12,0x4f,0xe, 0x7c,0xb7,0xbc,0xba,0x50,0x3, 0x7c,0xba,0x22, +0x22,0x7e,0x37,0x2f,0x96,0x9e,0x37,0x2f,0x8e,0x22,0x7e,0x17,0x2f,0x90,0xbd,0x13, +0x28,0xa, 0x7a,0x37,0x2f,0x90,0x7a,0x27,0x2f,0x92,0x80,0x10,0x7e,0x17,0x2f,0x88, +0xbd,0x13,0x50,0x8, 0x7a,0x37,0x2f,0x88,0x7a,0x27,0x2f,0x8a,0x7e,0x17,0x2f,0x8e, +0xbd,0x12,0x28,0xa, 0x7a,0x27,0x2f,0x8e,0x7a,0x37,0x2f,0x8c,0x80,0x10,0x7e,0x17, +0x2f,0x96,0xbd,0x12,0x50,0x8, 0x7a,0x27,0x2f,0x96,0x7a,0x37,0x2f,0x94,0x7e,0xb3, +0x2f,0xa8,0xb4,0xa, 0xf, 0x12,0x4c,0x76,0x7a,0x37,0x2f,0xa0,0x12,0x4c,0x1, 0x7a, +0x37,0x2f,0xa2,0x22,0xb4,0x14,0xe, 0x12,0x4c,0x76,0x7a,0x37,0x2f,0xa4,0x12,0x4c, +0x1, 0x7a,0x37,0x2f,0xa6,0x22,0x7e,0x37,0x2f,0x88,0x9e,0x37,0x2f,0x90,0x22,0x12, +0x4c,0x76,0x7a,0x37,0x2f,0x9c,0x12,0x4c,0x1, 0x7a,0x37,0x2f,0x9e,0x12,0x4d,0xd0, +0x60,0x1, 0x22,0x7e,0x73,0x2f,0xa8,0xa, 0x37,0x7a,0x35,0x24,0x7e,0x8, 0x2b,0xbf, +0x7e,0x18,0x2f,0x80,0x2, 0x4c,0xa7,0xca,0xf8,0x7e,0x45,0x24,0x7c,0xb9,0x7a,0xb3, +0x39,0x40,0x74,0xff,0x7a,0xb3,0x39,0x3f,0x6d,0x55,0x80,0x19,0x7d,0xf5,0x3e,0xf4, +0x12,0x4f,0x17,0x7d,0xe5,0x3e,0xe4,0x59,0xfe,0x1f,0x34,0x69,0xf6,0x0, 0x2, 0x59, +0xfe,0x21,0x14,0xb, 0x54,0xbd,0x45,0x38,0xe3,0x7e,0x33,0x39,0x40,0xbe,0x30,0x4, +0x38,0x2, 0xa1,0x69,0x69,0xf1,0x0, 0x1c,0x69,0x11,0x0, 0x1e,0xbd,0x1f,0x18,0x19, +0x4d,0x11,0x78,0x4, 0x7e,0x14,0x0, 0x1, 0x7d,0x3f,0x7d,0x21,0x12,0x1e,0xb9,0x7c, +0xf7,0x74,0x40,0x7a,0xb3,0x39,0x43,0x80,0x43,0x4d,0xff,0x78,0x4, 0x7e,0xf4,0x0, +0x1, 0x7d,0x31,0x7d,0x2f,0x12,0x1e,0xb9,0x7c,0xf7,0x74,0x80,0x7a,0xb3,0x39,0x43, +0x7d,0xf, 0x2d,0xf, 0xbd,0x1, 0x8, 0x24,0x1a,0x2, 0x1a,0x0, 0x7e,0x73,0x39,0x43, +0xa, 0x37,0x6d,0x22,0x12,0x1e,0xeb,0x7d,0x5f,0x1a,0x4a,0x1a,0x48,0x7d,0x1f,0x1a, +0x2, 0x1a,0x0, 0x2f,0x2, 0x12,0x1f,0x7, 0x7a,0x73,0x39,0x43,0xbe,0xf0,0x5, 0x58, +0x14,0x12,0x4d,0x88,0x12,0xc1,0xd5,0x12,0x4d,0x88,0x12,0xc3,0x7c,0x12,0x4d,0x88, +0x12,0xc2,0xc0,0x80,0xa, 0x74,0x7d,0x80,0x2, 0x74,0x7f,0x7a,0xb3,0x39,0x3f,0xe4, +0x7a,0xb3,0x39,0x40,0x7e,0x73,0x3a,0x2, 0xbe,0x73,0x39,0x3f,0x48,0x6, 0x7e,0xb3, +0x39,0x41,0x80,0x1, 0xe4,0xda,0xf8,0x22,0x7e,0x8, 0x1f,0x34,0x7e,0x18,0x21,0x14, +0x22,0x7e,0xb3,0x38,0x32,0x70,0x6, 0x12,0x4d,0xca,0x2, 0x4f,0xbf,0x12,0x4a,0x35, +0x12,0xbd,0xc2,0x50,0xa, 0x12,0x4c,0x7f,0x7c,0x3b,0x12,0x4d,0xca,0x80,0x5, 0x12, +0xc5,0x1f,0x7c,0x3b,0x4c,0x33,0x68,0x11,0x7c,0xb3,0x12,0xbd,0x46,0x60,0xa, 0x7a, +0x33,0x38,0x35,0x74,0x1, 0x7a,0xb3,0x2a,0x8, 0x22,0xe4,0x7a,0xb3,0x2f,0x80,0x22, +0xca,0xf8,0x6c,0xff,0x7e,0xb7,0x2f,0x9c,0x7e,0xc7,0x2f,0x9e,0x7e,0x97,0x2f,0x84, +0x7e,0xd7,0x2f,0x86,0x7e,0xa7,0x2f,0x98,0x7e,0xe7,0x2f,0x9a,0xe4,0x7e,0x73,0x2f, +0xa8,0x1b,0x70,0x7d,0x2b,0x7d,0x1c,0x12,0x4e,0xc2,0x70,0x2, 0xc1,0xbd,0x7e,0x73, +0x2f,0xa8,0xbe,0x70,0xa, 0x28,0x13,0xe4,0x7e,0x70,0x9, 0x7e,0x27,0x2f,0xa0,0x7e, +0x17,0x2f,0xa2,0x12,0x4e,0xc2,0x70,0x2, 0xc1,0xbd,0x7e,0x73,0x2f,0xa8,0xbe,0x70, +0x14,0x28,0x13,0xe4,0x7e,0x70,0x13,0x7e,0x27,0x2f,0xa4,0x7e,0x17,0x2f,0xa6,0x12, +0x4e,0xc2,0x70,0x2, 0xc1,0xbd,0xbe,0xc4,0x0, 0xf0,0x50,0x2d,0xbe,0xb4,0x1, 0xe, +0x28,0x27,0x7e,0xb3,0x2f,0x81,0x70,0x21,0x12,0x4f,0x5, 0x28,0x1c,0xbe,0xf4,0x13, +0x4c,0x50,0x16,0x7d,0xfc,0x3e,0xf4,0xbd,0xfb,0x50,0x62,0xbd,0xa9,0x50,0x5, 0x7e, +0xf0,0x20,0x80,0x59,0x7e,0xf0,0x21,0x80,0x54,0xbe,0xb4,0x0, 0x87,0x50,0x4e,0xbe, +0xc4,0x1, 0xe0,0x28,0x48,0x7e,0xb3,0x2f,0x81,0x70,0x42,0x12,0x4f,0x5, 0x28,0x3d, +0xbe,0xf4,0x13,0x4c,0x50,0x37,0x7d,0xfb,0x3e,0xf4,0xbd,0xfc,0x50,0x2f,0xbd,0xed, +0x50,0x5, 0x7e,0xf0,0x22,0x80,0x26,0x12,0x4f,0x8b,0x49,0x35,0x2b,0xbb,0x49,0x15, +0x2b,0xbd,0x49,0x25,0x2b,0xab,0x49,0x5, 0x2b,0xad,0x9d,0x10,0xbe,0x14,0x0, 0x20, +0x18,0x8, 0x9d,0x32,0xbe,0x34,0x0, 0x10,0x58,0x3, 0x7e,0xf0,0x23,0x7c,0xbf,0xda, +0xf8,0x22,0x7d,0x41,0x7d,0x2, 0x7c,0x37,0x7c,0x2b,0x74,0x4, 0xac,0xb2,0x49,0x35, +0x2b,0xbf,0x49,0xf5,0x2b,0xc1,0x74,0x4, 0xac,0xb3,0x49,0x25,0x2b,0xbf,0x49,0x55, +0x2b,0xc1,0x12,0x4f,0xcc,0x7d,0x3f,0x9d,0x35,0x12,0x21,0xa, 0x9d,0x34,0x12,0x21, +0xa, 0xbe,0x34,0x0, 0x4d,0x58,0xc, 0x12,0x4f,0xe, 0xbe,0x34,0x0, 0x4d,0x58,0x3, +0x74,0x1, 0x22,0xe4,0x22,0x7e,0xf7,0x2f,0x82,0xbe,0xf4,0xf, 0xa0,0x22,0x7d,0x31, +0x9d,0x30,0x2, 0x21,0xa, 0x7d,0xf4,0x3e,0xf4,0x7f,0x60,0x2d,0xdf,0xb, 0x6a,0xf0, +0x22,0x7c,0xab,0x6d,0x44,0x80,0x29,0x4c,0xaa,0x68,0x11,0x12,0x4f,0x58,0x60,0x5, +0x3e,0xe4,0x14,0x78,0xfb,0x12,0x4f,0x15,0x2d,0xfe,0x80,0xf, 0x12,0x4f,0x58,0x60, +0x5, 0x3e,0xe4,0x14,0x78,0xfb,0x12,0x4f,0x15,0x9d,0xfe,0x1b,0x6a,0xf0,0xb, 0x44, +0x7e,0xf5,0x29,0xbd,0xf4,0x38,0xd0,0x22,0x7f,0x71,0x2d,0xf4,0x7e,0x7b,0xb0,0x1a, +0xeb,0x7f,0x61,0x2e,0xd5,0x29,0x7e,0x6b,0xb0,0x22,0x7e,0xa3,0x2f,0xa8,0xbe,0xa0, +0xf0,0x50,0x17,0x74,0x4, 0xa4,0x59,0x35,0x2b,0xbf,0x12,0x4f,0x8b,0x59,0x25,0x2b, +0xc1,0x7e,0xb3,0x2f,0xa8,0x4, 0x7a,0xb3,0x2f,0xa8,0x22,0x7e,0xa3,0x2f,0xa8,0x74, +0x4, 0xa4,0x22,0x7c,0x7b,0x7e,0x63,0x2a,0x71,0xa, 0x6, 0x2e,0x4, 0x0, 0x3, 0x7e, +0x63,0x2a,0x6e,0xa, 0x16,0xad,0x10,0x7d,0x21,0x12,0x4f,0xe5,0xa, 0x26,0x7a,0x25, +0x29,0x74,0x1d,0xac,0x7b,0x2e,0x34,0x38,0x45,0x6d,0x22,0xe4,0x2, 0x4f,0x21,0xe4, +0x7a,0xb3,0x39,0xde,0x22,0x7e,0x34,0x0, 0xc8,0x2, 0x23,0xcc,0x9d,0x32,0x12,0x21, +0xa, 0x7d,0x13,0x22,0x7e,0xb3,0x38,0x32,0xbe,0xb0,0x1, 0x22,0xa, 0x5b,0x2e,0x54, +0x0, 0x8, 0xf5,0xcc,0x22,0x3e,0x24,0x7e,0xf, 0x39,0xda,0x2d,0x12,0x22,0x7e,0x8, +0x0, 0x25,0x7e,0x18,0x0, 0x24,0x22,0x7e,0x73,0x28,0x93,0x7a,0x73,0x28,0x94,0x7e, +0x73,0x2a,0x2, 0x7a,0x73,0x2a,0x3, 0xe4,0x7a,0xb3,0x2a,0x6, 0x22,0x7e,0x37,0x33, +0xeb,0xb, 0x34,0x7a,0x37,0x33,0xeb,0x7e,0x37,0x33,0xed,0xbe,0x37,0x33,0xeb,0x28, +0x3, 0x2, 0x50,0x28,0x22,0x2, 0x50,0xd, 0xe5,0x9a,0x60,0x5, 0xd2,0x9c,0xa9,0xd6, +0xdf,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, +0xc0,0xd0,0xc0,0x83,0xc0,0x82,0x12,0x50,0x25,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda, +0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7e,0x23, +0x2b,0xf, 0x7e,0x33,0x38,0xce,0xac,0x23,0x2e,0x14,0x1, 0xf4,0xbe,0x14,0x0, 0xa, +0x50,0x4, 0x7e,0x14,0x0, 0xa, 0x7e,0x63,0x2b,0x10,0xbe,0x14,0xf, 0x3c,0x40,0x4, +0x7e,0x14,0xf, 0x3c,0xbe,0x14,0x7, 0x8, 0x40,0x3, 0xe4,0x80,0x2, 0x74,0x1, 0x7a, +0xb3,0x2b,0x10,0x7e,0x73,0x2b,0x10,0xbc,0x76,0x68,0x2, 0xd2,0x10,0x7e,0x24,0x1, +0xf4,0x7d,0x31,0x8d,0x32,0x7c,0x17,0xbe,0x10,0x7, 0x28,0x3, 0x7e,0x10,0x7, 0x7e, +0x1f,0x39,0xc1,0x69,0x51,0x0, 0x86,0x54,0x1f,0xa, 0x1, 0x3e,0x4, 0x3e,0x4, 0x3e, +0x4, 0x3e,0x4, 0x3e,0x4, 0x2d,0x5, 0x79,0x1, 0x0, 0x86,0x6d,0x0, 0x7e,0x34,0xb8, +0x0, 0x7e,0x24,0x0, 0xb, 0x2, 0x1f,0x58,0x7e,0xa3,0x0, 0x5f,0xbe,0xa0,0xff,0x68, +0x48,0xbe,0xa3,0x3, 0xfc,0x68,0x42,0x74,0x5, 0xa4,0x12,0x57,0x7c,0x12,0x51,0x2a, +0x12,0x55,0x70,0x12,0x51,0x2a,0x12,0x55,0x67,0x12,0x57,0x8e,0x50,0x9, 0x7e,0xb3, +0x0, 0x5f,0x12,0x55,0x79,0x80,0x6, 0x12,0x51,0x2a,0x12,0x54,0x6a,0x12,0x51,0x36, +0x12,0x54,0x63,0x7e,0x73,0x2b,0x14,0xa, 0x37,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, +0x1a,0x7e,0x73,0x0, 0x5f,0x7a,0x73,0x3, 0xfc,0x22,0x7e,0xa3,0x0, 0x5f,0x74,0x5, +0xa4,0x22,0x7a,0xb3,0x2b,0xf, 0x12,0x50,0x5e,0x7a,0x37,0x2b,0x1b,0x22,0x12,0x51, +0x32,0x30,0x10,0xc, 0xc2,0x10,0x12,0x57,0xd5,0x30,0x0, 0x4, 0xe4,0x12,0xa, 0x66, +0x30,0x0, 0x9, 0x12,0xab,0x26,0x12,0x57,0xf8,0x2, 0x57,0x9f,0x22,0x7e,0xb, 0x70, +0x7a,0x73,0x2b,0xf, 0x29,0x70,0x0, 0x4, 0x7a,0x73,0x2b,0x62,0x29,0x70,0x0, 0x1, +0x7a,0x73,0x2b,0x14,0x29,0x70,0x0, 0x3, 0x7a,0x73,0x2b,0x20,0x12,0x51,0x36,0x12, +0x54,0x63,0xd2,0x0, 0xc2,0x1, 0x2, 0x3b,0xba,0xca,0xf8,0x7c,0xfb,0x74,0x5, 0xac, +0xbf,0x12,0x57,0x7c,0x12,0x55,0x70,0x12,0x54,0x6a,0x12,0x55,0x67,0x7a,0xf3,0x0, +0x5f,0x7c,0xbf,0x12,0x55,0x79,0x12,0x51,0x36,0x74,0x5, 0xac,0xbf,0x9, 0xb5,0x26, +0x37,0x12,0x57,0xba,0x12,0x23,0x23,0xe4,0x7a,0xb3,0x16,0x91,0xda,0xf8,0x22,0x7e, +0xb3,0x37,0x66,0x60,0x6, 0x14,0x7a,0xb3,0x37,0x66,0x22,0x12,0xa7,0xf9,0x7e,0xb3, +0x37,0xed,0x70,0xe, 0x7e,0xb3,0x3a,0xf, 0xb4,0x1, 0x7, 0xe4,0x12,0x51,0x89,0x12, +0x57,0xee,0x12,0x54,0x27,0x12,0xa9,0x2d,0x7e,0xa3,0x37,0xed,0x7a,0xa3,0x3a,0xf, +0xbe,0xb0,0xff,0x68,0x3, 0x2, 0x51,0x89,0x22,0xca,0xf8,0x6c,0xff,0x7e,0x73,0x0, +0x5f,0xbc,0x7f,0x68,0x2a,0x7e,0x30,0x5, 0xac,0x3f,0x12,0x52,0x6f,0xca,0x39,0x7e, +0x30,0x38,0xac,0x3f,0x12,0x52,0x88,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c, +0xca,0x39,0x7e,0x30,0x8c,0xac,0x3f,0x12,0x52,0x7d,0x12,0x20,0xc3,0x1b,0xfd,0xb, +0xf0,0xbe,0xf0,0x4, 0x40,0xc7,0x7e,0x23,0x0, 0x5f,0x7e,0x30,0x5, 0xac,0x23,0x12, +0x52,0x6f,0xca,0x39,0x7e,0x23,0x0, 0x5f,0x7e,0x30,0x38,0xac,0x23,0x12,0x52,0x88, +0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x23,0x0, 0x5f,0x7e, +0x30,0x8c,0xac,0x23,0x12,0x52,0x7d,0x12,0x20,0xc3,0x1b,0xfd,0xda,0xf8,0x22,0x2e, +0x14,0x26,0x33,0x6d,0x0, 0x12,0x51,0x5d,0x7e,0x34,0x0, 0x38,0x22,0x2e,0x14,0x1, +0x40,0x6d,0x0, 0x7e,0x18,0x3, 0x70,0x22,0x2e,0x14,0x0, 0x60,0x6d,0x0, 0x7e,0x18, +0x34,0x0, 0x22,0xca,0xd8,0xca,0x79,0x7e,0xd0,0xe, 0x7e,0xe0,0x19,0x7e,0x73,0x2a, +0x74,0xbe,0x70,0x19,0x28,0x4, 0x7c,0xf7,0x80,0x2, 0x7c,0xfe,0x7a,0xd3,0x2a,0x6d, +0x7a,0xe3,0x2a,0x6e,0x7a,0xd3,0x2a,0x71,0x7a,0xe3,0x2a,0x72,0x7a,0xd3,0x2a,0x73, +0x7a,0xe3,0x2a,0x74,0x74,0x1, 0x7a,0xb3,0x2a,0x77,0x7a,0xd3,0x2a,0x6f,0xa, 0x3e, +0x1b,0x34,0x7a,0x73,0x2a,0x70,0x74,0x5, 0x7a,0xb3,0x2a,0x78,0x74,0xff,0x7a,0xb3, +0x2a,0x79,0xa, 0x3d,0xca,0x39,0x7e,0x34,0x60,0x52,0x7e,0x24,0x0, 0xff,0x7e,0x8, +0x2a,0x7a,0x12,0x20,0xc3,0x1b,0xfd,0xa, 0x3f,0xca,0x39,0x7e,0x34,0x60,0x75,0x7e, +0x24,0x0, 0xff,0x7e,0x8, 0x2a,0x9d,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x23, +0xca,0x39,0x7e,0x34,0x60,0xd8,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x21,0x12,0x20, +0xc3,0x1b,0xfd,0x12,0xaa,0xc5,0x12,0x64,0xdf,0x7a,0xd3,0x2a,0x75,0x7a,0xe3,0x2a, +0x76,0x12,0x5d,0x7e,0x74,0x1, 0x12,0x30,0x38,0xe4,0x7a,0xb3,0x2b,0x1, 0x7a,0xb3, +0x2b,0x2, 0x12,0x62,0xab,0x7a,0x37,0x2b,0xd, 0x74,0x3, 0x7a,0xb3,0x2b,0x3, 0xe4, +0x7a,0xb3,0x2b,0x4, 0x74,0x2, 0x7a,0xb3,0x2b,0x5, 0x7e,0x34,0x0, 0xfa,0x7a,0x37, +0x2b,0x7, 0x74,0x4, 0x7a,0xb3,0x2b,0x6, 0x7e,0x34,0x0, 0xf, 0x7a,0x37,0x2b,0x9, +0x7e,0x34,0x20,0x5f,0x7a,0x37,0x2b,0xb, 0x74,0x20,0x7a,0xb3,0x2b,0x62,0x74,0x1, +0x7a,0xb3,0x2b,0x10,0x74,0x20,0x7a,0xb3,0x2b,0x11,0x74,0x4, 0x7a,0xb3,0x2b,0x13, +0x74,0x1e,0x12,0x51,0x32,0xe4,0x7a,0xb3,0x2b,0x1d,0x7a,0xb3,0x2b,0x1e,0x7e,0x34, +0x1, 0xf4,0x7a,0x37,0x2b,0x19,0x74,0x1, 0x7a,0xb3,0x2b,0x12,0x74,0x56,0x7a,0xb3, +0x2b,0x20,0x74,0x4f,0x7a,0xb3,0x2b,0x1f,0x6d,0x33,0x7a,0x37,0x2b,0x15,0x7a,0x37, +0x2b,0x17,0x74,0x3, 0x7a,0xb3,0x2b,0x14,0x7e,0x34,0x0, 0x30,0x7a,0x37,0x2b,0x6a, +0x7a,0xb3,0x2b,0x67,0x7e,0x34,0x0, 0x5, 0x7a,0x37,0x2b,0x68,0xe4,0x7a,0xb3,0x2b, +0x66,0x7e,0x34,0x4, 0x6d,0x7a,0x37,0x2b,0x6c,0x74,0x1, 0x7a,0xb3,0x2b,0x63,0x74, +0x4, 0x7a,0xb3,0x2b,0x64,0xe4,0x7a,0xb3,0x2b,0x65,0x74,0x1, 0x7a,0xb3,0x2b,0x60, +0xe4,0x7a,0xb3,0x2b,0x61,0x7e,0x34,0x20,0x65,0x7a,0x37,0x2b,0x6e,0xa, 0x3e,0xca, +0x39,0x7e,0x34,0x60,0xfb,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x44,0x12,0x20,0xc3, +0x1b,0xfd,0xda,0x79,0xda,0xd8,0x22,0x12,0xa7,0x37,0x2, 0x54,0x2d,0x7e,0xb3,0x37, +0x69,0x60,0xf, 0x74,0x1, 0x7a,0xb3,0x37,0x71,0x7e,0xb3,0x37,0xdf,0x70,0x3, 0x12, +0xa7,0xd0,0x7e,0xb3,0x37,0x71,0xb4,0x1, 0xc, 0x74,0x3, 0x7a,0xb3,0x34,0xc3,0x7e, +0x34,0x14,0x0, 0x80,0x9, 0xe4,0x7a,0xb3,0x34,0xc3,0x7e,0x34,0xa, 0x0, 0x7a,0x37, +0x2a,0x62,0x22,0x7e,0x8, 0x2a,0x6d,0x2, 0x3, 0x8b,0x9, 0x75,0x26,0x35,0x7a,0x73, +0x2b,0x1f,0x22,0xca,0x3b,0x7a,0xd, 0x2e,0x7c,0xcb,0x7e,0xb3,0x2b,0x1d,0xf5,0x32, +0x7e,0xb3,0x2b,0xf, 0xf5,0x33,0x7e,0xd3,0x2b,0x14,0x7e,0xe3,0x2b,0x1f,0x7e,0xf3, +0x2b,0x20,0x7e,0x34,0x0, 0x38,0xca,0x39,0x7e,0x18,0x34,0x0, 0x7e,0x8, 0x24,0xf2, +0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x18,0x3, 0x70,0x7e, +0x8, 0x25,0x2a,0x12,0x20,0xc3,0x1b,0xfd,0x7c,0xbc,0x12,0x55,0x79,0x74,0x1, 0x7a, +0xb3,0x2b,0x1d,0x74,0x5, 0xac,0xbc,0x12,0x55,0x70,0x74,0x5, 0xac,0xbc,0x12,0x54, +0x6a,0x74,0x5, 0xac,0xbc,0x12,0x55,0x67,0x74,0x5, 0xac,0xbc,0x9, 0x75,0x26,0x37, +0xbe,0x73,0x2b,0x62,0x68,0x6, 0x7a,0x73,0x2b,0x62,0xd2,0x10,0xc2,0x0, 0x12,0x57, +0x85,0x12,0x51,0x3e,0x12,0x3f,0x9e,0x30,0xf, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e, +0x14,0x40,0x0, 0x7d,0x31,0x7e,0x2f,0x13,0x86,0x7d,0x25,0x7e,0x4, 0xd, 0xc8,0x12, +0x56,0x2d,0x12,0x57,0xe5,0xa4,0x7a,0x55,0x34,0x7e,0xd, 0x2e,0x7e,0x18,0xd, 0xc8, +0x12,0x5d,0xf1,0x12,0xb5,0xa7,0xe5,0x32,0x7a,0xb3,0x2b,0x1d,0xe5,0x33,0x7a,0xb3, +0x2b,0xf, 0x7a,0xd3,0x2b,0x14,0x7a,0xe3,0x2b,0x1f,0x7a,0xf3,0x2b,0x20,0x7e,0x34, +0x0, 0x38,0xca,0x39,0x7e,0x18,0x24,0xf2,0x7e,0x8, 0x34,0x0, 0x12,0x20,0xc3,0x1b, +0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x18,0x25,0x2a,0x7e,0x8, 0x3, 0x70,0x12, +0x20,0xc3,0x1b,0xfd,0xda,0x3b,0x22,0x9, 0x75,0x26,0x36,0x7a,0x73,0x2b,0x20,0x22, +0x9, 0x75,0x26,0x34,0x7a,0x73,0x2b,0x14,0x22,0xca,0xf8,0x7c,0xfb,0x7e,0x34,0x0, +0x38,0xca,0x39,0xac,0x7f,0x2e,0x34,0x0, 0x60,0x6d,0x22,0x7e,0x8, 0x34,0x0, 0x12, +0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0xac,0x7f,0x2e,0x34,0x1, 0x40, +0x6d,0x22,0x7e,0x8, 0x3, 0x70,0x12,0x20,0xc3,0x1b,0xfd,0xda,0xf8,0x22,0xca,0x3b, +0x7e,0xb3,0x2b,0xf, 0x7a,0xb3,0x1f,0x33,0x7e,0xf3,0x2b,0x62,0x12,0x8b,0x1a,0x7c, +0xdb,0xbe,0xd0,0xff,0x68,0x64,0x6c,0xcc,0x12,0x57,0x85,0xf5,0x29,0x7e,0x73,0x2b, +0xf, 0xbe,0x71,0x29,0x68,0x36,0x7e,0x70,0x4, 0xac,0x7d,0xa, 0x2c,0x12,0x88,0x56, +0x7c,0xeb,0xbe,0xe0,0x2, 0x38,0x43,0xa, 0xe, 0x7e,0x14,0x2, 0xe0,0xad,0x10,0x2e, +0x14,0x16,0x93,0x6d,0x0, 0x7a,0xd, 0x2a,0x7e,0x70,0x1d,0xac,0x7e,0x2e,0x34,0x38, +0x45,0x6d,0x22,0x7a,0x1f,0x38,0x41,0x7c,0xbc,0x12,0x54,0x73,0xb, 0xc0,0xbe,0xc0, +0x4, 0x40,0xb5,0x7e,0x73,0x2b,0x62,0xbc,0x7f,0x68,0x6, 0x7a,0xf3,0x2b,0x62,0xd2, +0x10,0xd2,0x0, 0x7e,0xb3,0x1f,0x33,0x12,0x51,0x3e,0xda,0x3b,0x22,0x7e,0xb3,0x2a, +0x6d,0xca,0x3b,0x7c,0xdb,0x7a,0x5, 0x38,0x7d,0x71,0x7a,0x25,0x36,0x7a,0x35,0x34, +0x12,0x57,0x8e,0x50,0x7b,0x6c,0xcc,0x80,0x13,0x7e,0x73,0x2a,0x6e,0x12,0x57,0x57, +0x12,0x57,0x3d,0x7e,0x34,0x34,0x0, 0x12,0x57,0x60,0xb, 0xc0,0x12,0x57,0x75,0x38, +0xe8,0x6c,0xcc,0x80,0x55,0x7e,0xa3,0x2a,0x6e,0x7c,0x7a,0x12,0x57,0x57,0x75,0x3a, +0x0, 0x80,0x27,0x7e,0xb3,0x38,0xb2,0xbe,0xb1,0x3a,0x7e,0x70,0x4, 0x28,0x8, 0xac, +0x7c,0x49,0x43,0x3, 0x70,0x80,0x6, 0xac,0x7c,0x49,0x43,0x3, 0x72,0x7e,0x71,0x3a, +0x74,0x2, 0xac,0x7b,0x59,0x43,0x34,0x50,0x5, 0x3a,0x7e,0xb3,0x2a,0x70,0xbe,0xb1, +0x3a,0x38,0xd0,0x7e,0x34,0x10,0x0, 0x74,0x2, 0xa4,0x59,0x35,0x34,0x4e,0x12,0x57, +0x3d,0x7e,0x34,0x34,0x50,0x12,0x57,0x60,0xb, 0xc0,0xbc,0xdc,0x38,0xa7,0x80,0x2c, +0x7a,0xd3,0x25,0xb6,0x7e,0x73,0x2a,0x70,0x7a,0x73,0x25,0xb7,0xe4,0x7a,0xb3,0x25, +0xb9,0x74,0x6, 0x7a,0xb3,0x25,0xb8,0x7a,0x77,0x25,0xba,0x7a,0x77,0x25,0xbe,0x7e, +0x8, 0x25,0xb6,0x7e,0x73,0x2b,0x1f,0xa, 0x37,0x12,0xe, 0x37,0x7d,0x37,0x12,0x6f, +0xfa,0x7e,0x35,0x38,0x7a,0x37,0x25,0xbe,0xe4,0x7a,0xb3,0x25,0xb8,0x12,0x57,0x4e, +0x7a,0xd3,0x25,0xb6,0x7e,0xb3,0x2b,0x1d,0x70,0xf, 0xe4,0x7a,0xb3,0x25,0xb9,0x7a, +0x77,0x25,0xba,0x7e,0x34,0x0, 0x20,0x80,0x16,0x74,0x1, 0x7a,0xb3,0x25,0xb9,0x7e, +0x35,0x34,0x7a,0x37,0x25,0xba,0x7e,0x35,0x36,0x7a,0x37,0x25,0xbc,0x6d,0x33,0x7a, +0x37,0x25,0xc0,0x7e,0x8, 0x25,0xb6,0x12,0xd, 0x7, 0xda,0x3b,0x22,0x74,0xc, 0x7a, +0xb3,0x25,0xb8,0x74,0x1, 0x7a,0xb3,0x25,0xb6,0xe4,0x7a,0xb3,0x25,0xb9,0x7e,0x73, +0x2a,0x6e,0x7a,0x73,0x25,0xb7,0x22,0xac,0x7c,0x3e,0x34,0x7d,0xf7,0x2d,0xf3,0x22, +0x7a,0x37,0x25,0xba,0x7d,0x3f,0x7a,0x37,0x25,0xbc,0x7a,0x37,0x25,0xbe,0x7e,0x8, +0x25,0xb6,0x2, 0x7, 0x9b,0x7e,0x73,0x2a,0x6f,0xbc,0x7c,0x22,0x9, 0x75,0x26,0x33, +0x7a,0x73,0x2b,0xf, 0x22,0x74,0x5, 0xac,0xbc,0x9, 0xb5,0x26,0x33,0x22,0x7e,0xb3, +0x38,0x9, 0xb4,0x3, 0x8, 0x7e,0xb3,0x38,0xb3,0x70,0x2, 0xc3,0x22,0xd3,0x22,0x12, +0xa7,0xf9,0x6d,0x33,0x7a,0x37,0x37,0xdd,0x6c,0xaa,0x12,0xaa,0x88,0xb, 0xa0,0xbe, +0xa0,0x4, 0x40,0xf6,0xe4,0x7a,0xb3,0x37,0x72,0x22,0x7e,0xa3,0x2b,0x62,0xbc,0xab, +0x68,0x6, 0x7a,0xb3,0x2b,0x62,0xd2,0x10,0x30,0x10,0x9, 0xc2,0x10,0x12,0x57,0xd5, +0xe4,0x2, 0xa, 0x66,0x22,0x7e,0x8, 0x2a,0x6d,0x12,0x3, 0x8b,0x7e,0x8, 0x2a,0x6d, +0x74,0x3, 0x2, 0x11,0x7a,0x7e,0xa3,0x2a,0x6e,0x7e,0xb3,0x2a,0x6d,0x22,0xe4,0x7a, +0xb3,0x37,0x69,0x7a,0xb3,0x37,0x71,0x22,0x7e,0xb3,0x2b,0xf, 0xca,0x3b,0x7c,0xeb, +0x6c,0xff,0x7e,0xc4,0x1, 0xf4,0x7e,0x73,0x38,0xce,0xa, 0xb7,0x7e,0xb3,0x2b,0x10, +0xf5,0x34,0x75,0x35,0x4, 0xe4,0x7a,0xb3,0x37,0x72,0xa, 0x3e,0xad,0x3b,0x7d,0xa3, +0x2d,0xac,0x6c,0xdd,0x7e,0xa3,0x37,0x72,0xbe,0xa1,0x35,0x40,0x2, 0x80,0x19,0xbe, +0xa0,0x0, 0x28,0x19,0x74,0x5, 0xa4,0x9, 0x75,0x26,0x33,0xbc,0x7e,0x78,0xe, 0xe5, +0x35,0x14,0xbe,0xb3,0x37,0x72,0x78,0x5, 0xe4,0x7a,0xb3,0x37,0x72,0x7e,0xc3,0x37, +0x72,0x80,0x3a,0x7e,0xb3,0x37,0x72,0x4, 0x7a,0xb3,0x37,0x72,0x74,0x5, 0xac,0xbc, +0x9, 0x75,0x26,0x33,0xbc,0x7e,0x68,0x23,0xa, 0xdd,0x19,0xcd,0x37,0x76,0xa, 0x97, +0xad,0x9b,0x2d,0x9c,0x7c,0xad,0xb, 0xd0,0x7c,0xba,0x7d,0x39,0x7d,0x2a,0x7e,0x31, +0x34,0x12,0x10,0x0, 0xb, 0xf0,0xbe,0xf0,0x3, 0x50,0x8, 0xb, 0xc0,0xe5,0x35,0xbc, +0xbc,0x38,0xc0,0x7a,0xf3,0x37,0x73,0xda,0x3b,0x22,0x74,0xa, 0x7a,0xb3,0x2a,0x4d, +0x74,0x10,0x7a,0xb3,0x2a,0x4e,0x12,0x47,0xf8,0x7a,0x37,0x2a,0x55,0x74,0x14,0x7a, +0xb3,0x2a,0x59,0x12,0x5d,0xde,0x7e,0x24,0x0, 0x78,0x7a,0x27,0x2a,0x5c,0x7e,0x24, +0xff,0x6a,0x7a,0x27,0x2a,0x5e,0x7a,0x37,0x2a,0x60,0xe4,0x7a,0xb3,0x2a,0x64,0x74, +0x4, 0x7a,0xb3,0x2a,0x65,0x7e,0x34,0x0, 0x64,0x7a,0x37,0x2a,0x66,0x7e,0x34,0xa, +0x0, 0x7a,0x37,0x2a,0x62,0xe4,0x7a,0xb3,0x2a,0x6b,0x7a,0xb3,0x16,0x92,0x22,0x12, +0x5c,0x95,0x12,0x52,0x93,0x12,0x0, 0x42,0x12,0x5d,0xd5,0x7e,0x18,0x4, 0x0, 0x7a, +0x1f,0x6, 0xf8,0x7e,0xf, 0x6, 0xf8,0x7e,0x1f,0x6, 0xf4,0x12,0x65,0x54,0x7e,0x18, +0x8, 0xa, 0x7a,0x1f,0x13,0x86,0x7e,0x18,0xd, 0xc8,0x7a,0x1f,0x13,0x8a,0x7e,0xf, +0x13,0x8a,0x7e,0x1f,0x13,0x86,0x12,0x5f,0xd5,0x12,0x59,0x46,0x12,0x58,0x9a,0x12, +0x64,0xb0,0x12,0x59,0x8e,0x2, 0x59,0x38,0xe4,0x7a,0xb3,0x34,0x38,0x7a,0xb3,0x34, +0x39,0x7a,0xb3,0x34,0x3a,0x22,0x2, 0x59,0x49,0x7e,0x34,0x0, 0xfa,0x7a,0x37,0x28, +0x95,0x7e,0x34,0x2, 0x26,0x7a,0x37,0x28,0x99,0x7e,0x34,0x0, 0x96,0x7a,0x37,0x28, +0x97,0x7a,0x37,0x28,0x9b,0x7e,0x34,0x0, 0x50,0x7a,0x37,0x28,0x9d,0x7e,0x34,0x0, +0x2b,0x7a,0x37,0x28,0x9f,0x12,0x5f,0xc8,0x74,0x1, 0x7a,0xb3,0x28,0xa5,0xe4,0x7a, +0xb3,0x28,0xa8,0x7e,0x8, 0x25,0xf7,0x7e,0x34,0x0, 0x3c,0x2, 0x20,0xe8,0x7e,0x8, +0x28,0xae,0x7e,0x34,0x1, 0xe, 0x74,0xff,0x12,0x20,0xe8,0x12,0x5f,0xbc,0x7e,0x8, +0x29,0xbc,0x12,0x59,0xb1,0x7e,0x8, 0x2a,0x2, 0x7e,0x34,0x0, 0xb, 0xe4,0x2, 0x20, +0xe8,0x6c,0xaa,0x74,0x3, 0x12,0x5d,0xe7,0x7f,0x10,0x2d,0x34,0x39,0xb1,0x0, 0xa, +0x12,0x59,0xd9,0x7f,0x70,0x2d,0xf3,0x79,0x47,0x0, 0x14,0x2d,0x31,0x79,0x41,0x0, +0x28,0xb, 0xa0,0xbe,0xa0,0xa, 0x40,0xdb,0x22,0x7e,0x44,0x7f,0xff,0x7e,0x70,0x2, +0xac,0x7a,0x22,0xca,0xf8,0x7e,0x68,0x29,0xbc,0x6c,0xaa,0x7e,0x70,0xff,0x12,0x5c, +0x74,0xe4,0xa, 0x4a,0x19,0xb4,0x1f,0x34,0x74,0xff,0x19,0xb4,0x1f,0x46,0x19,0xb4, +0x1f,0x50,0xb, 0xa0,0xbe,0xa0,0xa, 0x78,0xe2,0x7e,0x73,0x2a,0x2, 0xa5,0xbf,0x0, +0x21,0x7e,0xb3,0x34,0x4f,0x70,0x2, 0x61,0xe2,0x6c,0xaa,0x7e,0x44,0x7f,0xff,0x12, +0x5c,0x7e,0x79,0x40,0x0, 0x14,0x12,0x5c,0x6b,0xb, 0xa0,0xbe,0xa0,0xa, 0x78,0xeb, +0x61,0xe2,0x7e,0xb3,0x34,0x4f,0x70,0x3d,0xbe,0x70,0x0, 0x28,0x38,0x6c,0xaa,0x80, +0x2a,0x7e,0x90,0x9, 0xac,0x9a,0x49,0x34,0x28,0xae,0x12,0x5c,0x7e,0x79,0x30,0x0, +0x14,0x49,0x34,0x28,0xb0,0x7f,0x6, 0x2d,0x12,0x79,0x30,0x0, 0x28,0x74,0x1, 0xa, +0x3a,0x19,0xb3,0x1f,0x34,0x19,0xa4,0x28,0xb2,0xb, 0xa0,0x7e,0xb3,0x2a,0x2, 0xbc, +0xba,0x38,0xce,0x61,0xe2,0x6c,0xaa,0x12,0x59,0xd9,0x3e,0x34,0x59,0x43,0x15,0x4e, +0x59,0x43,0x15,0x50,0x59,0x43,0x15,0x76,0x59,0x43,0x15,0x78,0xb, 0xa0,0xbe,0xa0, +0xa, 0x78,0xe4,0x6c,0xaa,0x80,0x3b,0x6c,0xff,0x7e,0x70,0x2, 0xac,0x7f,0x7f,0x6, +0x2d,0x13,0x69,0x30,0x0, 0x14,0xbe,0x34,0x7f,0xff,0x68,0x1d,0xa, 0x4f,0x9, 0xb4, +0x1f,0x50,0xb4,0xff,0x14,0x12,0x5c,0x63,0x59,0x32,0x15,0x4e,0x69,0x30,0x0, 0x28, +0x59,0x32,0x15,0x50,0x12,0x5c,0x88,0x80,0x7, 0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0xc9, +0xb, 0xa0,0x7e,0xb3,0x34,0x4f,0xbc,0xba,0x38,0xbd,0x6c,0xaa,0xa, 0x3a,0x9, 0xb3, +0x1f,0x46,0xb4,0xff,0x17,0x6c,0xff,0xa, 0x4f,0x9, 0xb4,0x1f,0x50,0xb4,0xff,0x5, +0x12,0x5c,0x88,0x80,0x7, 0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0xeb,0xb, 0xa0,0xbe,0xa0, +0xa, 0x78,0xd9,0x6c,0xaa,0x80,0x1a,0x7e,0x70,0x9, 0xac,0x7a,0x49,0x43,0x28,0xae, +0x12,0x5c,0x63,0x59,0x42,0x15,0x76,0x49,0x33,0x28,0xb0,0x59,0x32,0x15,0x78,0xb, +0xa0,0x7e,0xb3,0x2a,0x2, 0xbc,0xba,0x38,0xde,0x7e,0x34,0x15,0x4e,0x7a,0x37,0x1f, +0x40,0x7e,0x34,0x15,0x76,0x7a,0x37,0x1f,0x42,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f, +0x44,0x7e,0x73,0x34,0x4f,0x7a,0x73,0x1f,0x3e,0x7e,0x73,0x2a,0x2, 0x7a,0x73,0x1f, +0x3f,0x7e,0x8, 0x1f,0x3e,0x12,0x4, 0xad,0x6c,0xaa,0x80,0x57,0x7e,0x70,0xff,0x6c, +0xff,0x7e,0x50,0x2, 0xac,0x5f,0x49,0x12,0x15,0x9e,0xa, 0x2a,0xbd,0x21,0x78,0x8, +0xa, 0x3f,0x9, 0x73,0x1f,0x46,0x80,0x7, 0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0xe2,0xbe, +0x70,0xff,0x68,0x2d,0x12,0x5c,0x74,0x74,0x1, 0xa, 0x47,0x19,0xb4,0x1f,0x34,0x7e, +0x90,0x9, 0xac,0x9a,0x49,0x24,0x28,0xae,0x7e,0x30,0x2, 0xac,0x37,0x2d,0x1d,0x7d, +0xc, 0x79,0x20,0x0, 0x14,0x49,0x44,0x28,0xb0,0x7e,0x50,0x2, 0xac,0x57,0x12,0x5c, +0x6b,0xb, 0xa0,0x7e,0x63,0x2a,0x2, 0xbc,0x6a,0x38,0xa1,0x6c,0xaa,0xa, 0x3a,0x9, +0xb3,0x1f,0x34,0xbe,0xb0,0x1, 0x68,0x13,0x12,0x59,0xd9,0x7f,0x6, 0x2d,0x13,0x79, +0x40,0x0, 0x14,0x2d,0x3d,0x7d,0x2c,0x79,0x41,0x0, 0x28,0xb, 0xa0,0xbe,0xa0,0xa, +0x78,0xdb,0x7e,0xf3,0x2a,0x2, 0x7a,0xf3,0x34,0x4f,0x6c,0xaa,0xa, 0x3a,0x9, 0xb3, +0x1f,0x34,0xb4,0x1, 0x2c,0x12,0x5c,0x5c,0x29,0xb1,0x0, 0xa, 0xb4,0x1, 0x6, 0x74, +0x3, 0x39,0xb1,0x0, 0xa, 0x12,0x5c,0x5c,0x29,0x31,0x0, 0xa, 0xa5,0xbb,0x3, 0x6, +0xe4,0x7a,0x1b,0xb0,0x80,0x32,0xa5,0xbb,0x0, 0x2e,0x74,0x2, 0x7a,0x1b,0xb0,0x80, +0x27,0x12,0x5c,0x5c,0x29,0xb1,0x0, 0xa, 0xbe,0xb0,0x2, 0x68,0x2, 0x70,0x14,0x74, +0x1, 0x7a,0x1b,0xb0,0x7c,0x2f,0xb, 0xf0,0x7e,0x30,0x9, 0xac,0x23,0x19,0xa1,0x28, +0xb2,0x80,0x5, 0x74,0x3, 0x7a,0x1b,0xb0,0x12,0x5c,0x5c,0x7e,0x1b,0xb0,0x39,0xb1, +0x0, 0xa, 0xb, 0xa0,0xbe,0xa0,0xa, 0x40,0x93,0xda,0xf8,0x22,0xa, 0x3a,0x2d,0x3d, +0x7d,0x2c,0x22,0x7e,0x50,0x2, 0xac,0x5a,0x3e,0x24,0x22,0x7f,0x6, 0x2d,0x12,0x79, +0x40,0x0, 0x28,0x22,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x72,0x28,0xb2,0x22,0x7e,0x50, +0x2, 0xac,0x5a,0x7f,0x6, 0x2d,0x12,0x22,0xa, 0x3a,0x19,0xf3,0x1f,0x46,0x74,0x1, +0x19,0xb4,0x1f,0x50,0x22,0xe4,0x7a,0xb3,0x38,0x9d,0x7a,0xb3,0x38,0x9e,0x74,0xe, +0x7a,0xb3,0x38,0x9f,0x74,0x19,0x7a,0xb3,0x38,0xa0,0xe4,0x7a,0xb3,0x38,0xa1,0x74, +0xa, 0x7a,0xb3,0x38,0xa2,0xe4,0x7a,0xb3,0x38,0xa3,0x7a,0xb3,0x38,0xa4,0x74,0x1, +0x7a,0xb3,0x38,0xa6,0x74,0x25,0x7a,0xb3,0x38,0xaa,0x74,0x3e,0x7a,0xb3,0x38,0xab, +0x74,0x64,0x7a,0xb3,0x38,0xbc,0x74,0x4, 0x7a,0xb3,0x38,0xbd,0xe4,0x7a,0xb3,0x38, +0xa9,0x74,0x4f,0x7a,0xb3,0x38,0xbf,0x74,0x56,0x7a,0xb3,0x38,0xbe,0x74,0x3, 0x7a, +0xb3,0x38,0xc0,0x74,0x40,0x7a,0xb3,0x38,0xbb,0xe4,0x7a,0xb3,0x38,0xb6,0x74,0xfa, +0x7a,0xb3,0x38,0xb4,0x74,0x1e,0x7a,0xb3,0x38,0xb5,0x74,0x1, 0x7a,0xb3,0x38,0xb3, +0x74,0xd, 0x7a,0xb3,0x38,0xb2,0x74,0x1, 0x7a,0xb3,0x38,0xb7,0xe4,0x7a,0xb3,0x38, +0xb8,0x7a,0xb3,0x38,0xb9,0x7e,0x8, 0x38,0xc1,0x7e,0x34,0x0, 0x2c,0x12,0x20,0xe8, +0x74,0x1, 0x7a,0xb3,0x38,0xcc,0x74,0xf4,0x7a,0xb3,0x38,0xcd,0x74,0x19,0x7a,0xb3, +0x38,0xce,0x74,0x1e,0x7a,0xb3,0x38,0xcf,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x12,0x5d, +0xcc,0x7e,0x8, 0x38,0xdd,0x12,0x20,0xc3,0x1b,0xfd,0x74,0x5, 0x7a,0xb3,0x38,0xea, +0x74,0x1, 0x7a,0xb3,0x38,0xe1,0x7e,0x34,0x0, 0x28,0xca,0x39,0x7e,0x34,0x61,0xdb, +0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x26,0x33,0x12,0x20,0xc3,0x1b,0xfd,0x22,0x7e,0x34, +0x0, 0x4, 0xca,0x39,0x7e,0x34,0x61,0x2d,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x70, +0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x2a,0xe, 0x7a,0x37,0x2b,0x76,0xe4,0x7a,0xb3, +0x2b,0x74,0x7a,0xb3,0x2b,0x75,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x12,0x5d,0xcc,0x7e, +0x8, 0x25,0xee,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x2b,0x78,0x7a,0x37,0x25,0xf4, +0xe4,0x7a,0xb3,0x25,0xf2,0x74,0x1, 0x7a,0xb3,0x25,0xf3,0x22,0x7e,0x34,0x61,0x29, +0x7e,0x24,0x0, 0xff,0x22,0x7e,0x18,0x5, 0xf8,0x7a,0x1f,0x6, 0xf4,0x22,0x7e,0x34, +0x0, 0x96,0x7a,0x37,0x2a,0x5a,0x22,0xa, 0x4a,0x7f,0x10,0x2d,0x34,0x7a,0x1b,0xb0, +0x22,0xca,0xf8,0x7f,0x71,0x6d,0xdd,0x6c,0xaa,0x7e,0xf0,0x80,0xc2,0x0, 0x6d,0x44, +0x80,0x32,0x12,0x5e,0x92,0x12,0x5e,0xa3,0xbd,0x3d,0x48,0x26,0x12,0x5e,0x92,0xb, +0x1a,0x30,0xbe,0x34,0x0, 0x0, 0x8, 0x4, 0xd2,0x0, 0x80,0x9, 0x12,0x21,0xa, 0xbd, +0x3d,0x68,0x2, 0xc2,0x0, 0x7d,0x34,0x3e,0x34,0x2d,0x3f,0x7d,0x2e,0x12,0x5e,0xa3, +0x7d,0xd3,0xb, 0x44,0x7e,0xc5,0x34,0xbd,0xc4,0x38,0xc7,0x30,0x0, 0xc, 0x7e,0xf0, +0x7f,0x80,0x7, 0xb, 0xa0,0xbe,0xa0,0x8, 0x50,0x11,0x7c,0xba,0x7d,0x3d,0x60,0x5, +0xe, 0x34,0x14,0x78,0xfb,0xa, 0xcf,0xbd,0x3c,0x18,0xe8,0x7f,0x10,0x2e,0x35,0x34, +0x7a,0x1b,0xa0,0x6d,0x44,0x80,0x21,0x7d,0x54,0x3e,0x54,0x7f,0x17,0x2d,0x35,0xb, +0x1a,0x30,0x7f,0x60,0x2e,0xd5,0x34,0x7e,0x6b,0xb0,0x60,0x5, 0xe, 0x34,0x14,0x78, +0xfb,0x7c,0xb7,0x12,0x5d,0xe9,0xb, 0x44,0x7e,0x55,0x34,0xbd,0x54,0x38,0xd8,0xda, +0xf8,0x22,0x7d,0xc4,0x3e,0xc4,0x7f,0x17,0x2d,0x3c,0x22,0x74,0x2, 0xac,0xbe,0x7f, +0x17,0x2d,0x35,0xb, 0x1a,0x30,0x2, 0x21,0xa, 0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7f, +0x70,0xc2,0x0, 0x6c,0xdd,0x6d,0xdd,0x7e,0x34,0x23,0x5, 0x7e,0x24,0x0, 0xff,0x7e, +0x14,0x1f,0x7a,0x74,0xc, 0x12,0x1f,0xad,0x6d,0x11,0x7e,0x4, 0x7f,0xff,0x6c,0xee, +0x80,0x13,0x12,0x5e,0x9b,0x7d,0xc3,0xbd,0xdc,0x50,0x2, 0x7d,0xdc,0xbd,0xc, 0x28, +0x2, 0x7d,0xc, 0xb, 0xe0,0xbc,0xfe,0x38,0xe9,0xbe,0xd4,0x0, 0x1e,0x58,0xa, 0x7e, +0xb3,0x28,0x94,0x70,0x4, 0x6d,0x33,0xe1,0xa4,0xbe,0xd4,0x4, 0xb0,0x8, 0x2, 0xd2, +0x0, 0x6c,0xee,0x74,0x4, 0xac,0xbe,0x49,0x45,0x1f,0x7a,0xbd,0x4d,0x58,0x6, 0x49, +0xd5,0x1f,0x7c,0x80,0x7, 0xb, 0xe0,0xbe,0xe0,0x3, 0x40,0xe7,0xbe,0xe0,0x3, 0x78, +0x4, 0x6d,0x33,0x80,0x7f,0xbd,0xd, 0x8, 0x5, 0x30,0x0, 0x2, 0x7d,0xd0,0x9f,0x55, +0x6c,0xee,0x80,0xb, 0x12,0x5e,0x9b,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xe0,0xbc, +0xfe,0x38,0xf1,0xa, 0x1f,0x12,0x5f,0xb2,0x9f,0x55,0x6c,0xee,0x80,0x1d,0x12,0x5f, +0xa9,0xb, 0x1a,0x90,0x7d,0x39,0x12,0x21,0xa, 0x7d,0xc3,0xbd,0x1c,0x28,0xa, 0x7d, +0x39,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xd0,0xb, 0xe0,0xbc,0xfe,0x38,0xdf,0x6d, +0x11,0xbe,0xd0,0x0, 0x28,0x5, 0xa, 0x1d,0x12,0x5f,0xb2,0xbd,0x1d,0x8, 0x4, 0x7d, +0x1d,0x80,0xa, 0x6d,0x0, 0x9d,0xd, 0xbd,0x1, 0x8, 0x2, 0x7d,0x10,0x6c,0xee,0x80, +0xd, 0x12,0x5f,0xa9,0xb, 0x1a,0x0, 0x9d,0x1, 0x1b,0x1a,0x0, 0xb, 0xe0,0xbc,0xfe, +0x38,0xef,0x7d,0x31,0xda,0x79,0xda,0xd8,0x22,0x74,0x2, 0xac,0xbe,0x7f,0x17,0x2d, +0x35,0x22,0x6d,0x0, 0x7f,0x15,0x12,0x1f,0x58,0x7d,0x13,0x22,0x7e,0x8, 0x34,0xb7, +0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x20,0xe8,0x7e,0x34,0x0, 0x4, 0x7a,0x37,0x28,0xa1, +0x7a,0x37,0x28,0xa3,0x22,0x7f,0x60,0x7e,0xa3,0x2a,0x6d,0x7e,0xb3,0x2a,0x6e,0xa4, +0x7d,0xf5,0x3e,0xf4,0x7f,0x1, 0x7d,0x3f,0xe4,0x12,0x20,0xe8,0x7f,0x6, 0x7d,0x3f, +0x12,0x20,0xe8,0x7a,0xb3,0x16,0x91,0x22,0x7e,0xb3,0x2a,0x73,0xbc,0xba,0x22,0xff, +0x70,0x8f,0x0, 0xff,0x3b,0xc4,0x5a,0xa5,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x31,0x36,0x31,0x1, 0xc6,0x1, 0x31,0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0xa, 0xf5,0x43,0x36,0x5f,0x42,0x69,0x65,0x6c,0x5f,0x57,0x0, 0x0, 0x0, 0x0, 0x0, +0xe, 0x19,0x6, 0x5, 0x4, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x3, 0x2, 0x1, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16, +0x17,0x18,0xb, 0x5, 0xa, 0x4, 0x9, 0x3, 0x8, 0x2, 0x7, 0x1, 0x6, 0x0, 0x0, 0x0, +0x0, 0x5, 0x0, 0x4, 0xff,0x23,0x1c,0x2, 0xdf,0xa, 0x1e,0xa, 0x64,0x14,0x10,0x0, +0x4, 0x0, 0x64,0xd, 0xac,0x0, 0xc8,0x3, 0x1, 0x0, 0x0, 0x18,0x2, 0x7, 0xb, 0x0, +0x0, 0x0, 0x96,0x0, 0xf0,0x1, 0xcc,0x2, 0x8a,0x3, 0x48,0x3, 0xa2,0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc8,0x1, 0xf4,0x3, 0x20,0x0, 0x0, 0x0, 0x0, 0x7, +0xf8,0x0, 0x14,0x1, 0x19,0x1e,0x1, 0xf4,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x0, 0x4, 0x4f,0x20,0x1, 0x20,0x3, 0x0, 0x0, +0x0, 0x0, 0x1, 0xf4,0x56,0x40,0xe, 0x19,0x27,0x1c,0xf, 0x6, 0x60,0x1c,0xf, 0x6, +0x70,0x8, 0x10,0x4, 0x20,0x1, 0x0, 0x4, 0x38,0x44,0x44,0x2, 0x36,0x2, 0x4a,0x1, +0x39,0x1, 0x3b,0x7, 0x80,0x4a,0x4d,0x2, 0x57,0x2, 0x52,0x1, 0x44,0x1, 0x43,0x0, +0x96,0x0, 0x78,0x0, 0x96,0x0, 0xfa,0x0, 0x7d,0x0, 0xfa,0x0, 0xfa,0xa, 0x0, 0x0, +0xa8,0xa, 0x10,0x1e,0x32,0x1, 0xf, 0xb, 0x1e,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22,0x15, +0x0, 0x1, 0x54,0x1, 0x0, 0xa, 0x1, 0x3b,0x1, 0x14,0x0, 0x5a,0x1, 0x1, 0xe, 0x0, +0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55,0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x96, +0x2, 0x26,0x0, 0x50,0x0, 0x2b,0x0, 0x4, 0x0, 0x4, 0x1, 0x4, 0x1, 0x90,0x0, 0xc8, +0x0, 0x50,0x1, 0xf4,0x0, 0x96,0x1, 0x2c,0x1, 0x2c,0x4, 0x1e,0x3, 0x4f,0x56,0x20, +0x25,0x3, 0x51,0x5b,0x20,0x2a,0x3, 0x54,0x5e,0x20,0x3c,0x2, 0x52,0x76,0x20,0x1e, +0x3, 0x4f,0x56,0x20,0x1e,0x3, 0x4f,0x56,0x20,0x1e,0x3, 0x4f,0x56,0x20,0x1e,0x3, +0x4f,0x56,0x20,0x4, 0x5, 0xf, 0x10,0x11,0x12,0x13,0x4, 0x0, 0xbb,0x4, 0xe2,0x2d, +0x0, 0xc8,0x1, 0x5e,0x0, 0x64,0x0, 0x64,0x0, 0x96,0x0, 0x64,0xb, 0xb8,0x8, 0x5, +0x6, 0x80,0x1, 0x90,0x1, 0x2c,0x1, 0xc2,0x3, 0x20,0xf, 0xa0,0x1, 0x3, 0x20,0x4, +0xb0,0x3, 0x20,0x1, 0x2, 0x2, 0x4, 0x4, 0x6, 0x40,0x0, 0xf0,0x0, 0xc8,0x1, 0x40, +0x1, 0x40,0x1, 0x2c,0x1, 0x18,0x0, 0xfa,0x1, 0x40,0x1, 0x40,0x1, 0x7c,0x0, 0x32, +0x0, 0x28,0x0, 0x78,0x0, 0x64,0x0, 0x64,0x0, 0x78,0x0, 0x78,0x14,0xa, 0x0, 0x50, +0x3, 0xe8,0x0, 0x50,0x7, 0x30,0x0, 0x14,0x1, 0xf4,0x1, 0xf4,0x3, 0x20,0x0, 0x64, +0x0, 0x4d,0x0, 0x1e,0x0, 0x80,0x1, 0xe, 0x0, 0xf0,0x0, 0x3c,0x3, 0xe8,0x1, 0xe0, +0x0, 0x87,0x0, 0x3c,0x3, 0xe8,0x0, 0x20,0x4, 0x18,0x0, 0x0, 0x7, 0x80,0x0, 0x64, +0x0, 0xa0,0x0, 0xa0,0x13,0x88,0x1, 0x2c,0x0, 0xa0,0x0, 0xa0,0x10,0x0, 0xc, 0x0, +0xb, 0xc, 0x5, 0x6, 0x8, 0x9, 0x6, 0x6, 0xc, 0x64,0xc8,0x6d,0x33,0x6c,0xaa,0x80, +0x14,0xa, 0x2a,0x9, 0xb2,0x2a,0xdc,0x54,0x1, 0x78,0x5, 0x4e,0x70,0x1, 0x80,0x3, +0x4e,0x70,0x10,0xb, 0xa0,0x7e,0x53,0x2a,0x74,0xbc,0x5a,0x38,0xe4,0x6c,0xaa,0x80, +0x1f,0xa, 0x2a,0x9, 0xb2,0x2a,0xb9,0xbe,0xb0,0xd, 0x38,0x5, 0x4e,0x70,0xc0,0x80, +0xd, 0xbe,0xb0,0x1b,0x38,0x5, 0x4e,0x60,0x8, 0x80,0x3, 0x4e,0x60,0x50,0xb, 0xa0, +0x12,0x5f,0xf8,0x38,0xdc,0x22,0x7e,0x54,0x0, 0x54,0x7e,0x44,0x0, 0xff,0x69,0x32, +0x0, 0x4, 0x69,0x22,0x0, 0x2, 0xb, 0x2a,0x10,0x7a,0x1d,0x26,0x7a,0x15,0x24,0x7e, +0x34,0x0, 0x20,0x7e,0x8, 0x0, 0x24,0x7e,0x24,0x0, 0x6, 0x12,0x63,0x62,0x74,0x25, +0x7a,0xb3,0x37,0xe2,0x74,0x1e,0x7a,0xb3,0x37,0xe3,0x74,0xf, 0x7a,0xb3,0x37,0xe4, +0x7a,0xb3,0x37,0xe5,0x7a,0xb3,0x37,0xe6,0x74,0xa0,0x7a,0xb3,0x37,0xe7,0x7e,0x34, +0x0, 0x59,0xca,0x39,0x7e,0x34,0x61,0x65,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x37,0xe8, +0x12,0x20,0xc3,0x1b,0xfd,0xe5,0x25,0x7a,0xb3,0x38,0x13,0xe5,0x28,0x7a,0xb3,0x38, +0x2, 0x22,0x7d,0x42,0x7f,0x60,0x7d,0x3, 0x12,0x64,0x60,0x74,0x2, 0x12,0x63,0x9c, +0x7d,0xf3,0x4e,0xf4,0x0, 0x1, 0x4e,0xf4,0x0, 0xa, 0x12,0x2f,0x54,0x7a,0x45,0x36, +0x7d,0x30,0x6d,0x22,0x7f,0x6, 0x12,0x64,0x2, 0x5e,0xf4,0xff,0xfd,0x12,0x2f,0x54, +0x2, 0x63,0x93,0xa9,0xc5,0xca,0xe4,0x7a,0xb3,0x3a,0x10,0x22,0x7c,0x6b,0x6c,0x77, +0x6c,0xaa,0x7e,0xb3,0x3a,0x10,0xb4,0xa5,0x46,0x12,0x64,0x8d,0x75,0xb5,0x5, 0xa9, +0x36,0xb3,0xfc,0x12,0x2f,0xa8,0xa9,0x36,0xb3,0xfc,0x12,0x2f,0xa8,0xa9,0x36,0xb3, +0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36,0xb3,0xfc,0x12,0x2f,0xa8,0xa9,0x36, +0xb3,0xfc,0x12,0x2f,0xa8,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7e,0x71,0xb5,0x75, +0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7e,0xa1,0xb5,0xa9,0xd2,0xb4,0x7c, +0x47,0x6c,0x55,0xa, 0x3a,0x4d,0x32,0x22,0x74,0x6, 0x12,0x63,0x9c,0x7d,0x3, 0x6c, +0x11,0x22,0x12,0x64,0x10,0x7e,0x35,0x36,0x12,0x64,0x94,0xa9,0xd2,0xb4,0xd3,0x22, +0x7d,0x52,0xf5,0x3a,0x7c,0xb6,0x7c,0xa5,0xa, 0x44,0xf5,0x39,0x7f,0x21,0xf5,0x38, +0xa9,0xc2,0xb4,0x74,0xb, 0x12,0x64,0x3b,0xe5,0x3a,0x12,0x64,0x3b,0xe5,0x39,0x12, +0x64,0x3b,0xe5,0x38,0x12,0x64,0x3b,0xe4,0x2, 0x64,0x3b,0xf5,0xb5,0xa9,0x36,0xb3, +0xfc,0xa9,0xc6,0xb3,0xd3,0x22,0xd2,0xc8,0x43,0xed,0xf, 0xc2,0xea,0x75,0xb3,0x13, +0xa9,0xd1,0xb4,0xa9,0xc0,0xb4,0x12,0x64,0x60,0xe4,0x12,0x64,0x70,0x2, 0x63,0x93, +0xa9,0xd5,0xca,0xa9,0xd1,0xea,0xa9,0xc1,0xea,0x74,0xa5,0x7a,0xb3,0x3a,0x10,0x22, +0xca,0xf8,0x7c,0xfb,0x74,0x2, 0x12,0x63,0x9c,0x4c,0xff,0x78,0x5, 0x5e,0x70,0xdf, +0x80,0x3, 0x4e,0x70,0x20,0x74,0x2, 0x12,0x2f,0x58,0xda,0xf8,0x22,0xa9,0xc2,0xb4, +0xa9,0xc6,0xb3,0x22,0x6d,0x22,0x80,0x13,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9, +0xc6,0xb3,0xe5,0xb5,0x7a,0xb, 0xb0,0xb, 0x14,0xb, 0x24,0xbd,0x32,0x38,0xe9,0x22, +0x7e,0x8, 0x26,0x5b,0x7e,0x34,0x2, 0x3a,0xe4,0x12,0x20,0xe8,0x7e,0x8, 0x26,0x8c, +0x7e,0x34,0x0, 0xc8,0x74,0xff,0x12,0x20,0xe8,0x7e,0x8, 0x26,0xb4,0x7e,0x34,0x0, +0xc8,0x12,0x20,0xe8,0x7e,0x8, 0x27,0x76,0x7e,0x34,0x1, 0xe, 0x2, 0x20,0xe8,0xca, +0xf8,0x7e,0x73,0x2a,0x78,0xa, 0x47,0x7e,0x73,0x2a,0x71,0xa, 0x57,0x2d,0x54,0x7e, +0xa3,0x2a,0x73,0xbc,0xab,0x28,0x2, 0x7c,0xba,0x7e,0xf3,0x2a,0x72,0x7e,0xa3,0x2a, +0x74,0xbc,0xaf,0x28,0x2, 0x7c,0xfa,0x75,0x25,0x15,0x7e,0x8, 0x2a,0xb9,0x7e,0x18, +0x2a,0x7a,0x12,0xd, 0xd9,0x75,0x25,0x15,0x7e,0x8, 0x2a,0xdc,0x7e,0x18,0x2a,0x9d, +0x7c,0xbf,0x12,0xf, 0x9c,0xda,0xf8,0x22,0x7a,0xb3,0x2b,0x0, 0x70,0xa, 0x7e,0x1f, +0x2b,0x74,0x7e,0xf, 0x2b,0x70,0x80,0xb, 0xb4,0x1, 0xb, 0x7e,0x1f,0x25,0xf2,0x7e, +0xf, 0x25,0xee,0x12,0x30,0x2f,0x22,0x7c,0xab,0x12,0x65,0x28,0x7c,0xba,0x12,0x13, +0xc7,0x2, 0x0, 0x1e,0x7f,0x70,0x7e,0x33,0x2a,0x74,0xa, 0x43,0x7e,0x33,0x2a,0x73, +0xa, 0x53,0x2d,0x54,0x3e,0x54,0x7c,0xab,0xe4,0x7a,0xb3,0x16,0x90,0x7f,0x1, 0xa, +0x3a,0x12,0x20,0xe8,0x7f,0x7, 0xa, 0x3a,0x2, 0x20,0xe8,0x7e,0xa3,0x2f,0xa8,0x7e, +0x70,0x4, 0xac,0x7a,0xb, 0x34,0xbe,0x37,0x38,0xee,0x40,0x39,0x7e,0x37,0x38,0xee, +0xb, 0x34,0x7a,0x37,0x38,0xee,0xbe,0x34,0x0, 0x1, 0x78,0x5, 0x7e,0xb3,0x38,0x35, +0x22,0xbe,0x34,0x0, 0x2, 0x78,0x3, 0x7c,0xba,0x22,0xbe,0x34,0x0, 0x2, 0x50,0x9, +0x7d,0x23,0x1b,0x25,0x9, 0xb2,0x39,0xfc,0x22,0x9e,0x34,0x0, 0x3, 0x2e,0x37,0x2b, +0xb9,0x7e,0x39,0xb0,0x22,0x74,0xff,0x22,0x70,0x5, 0x7e,0xb3,0x38,0x9d,0x22,0xbe, +0xb0,0x3, 0x38,0x15,0x75,0x1d,0x0, 0x30,0x12,0x6, 0x7e,0x18,0x35,0x93,0x80,0x4, +0x7e,0x18,0x35,0xd1,0x7a,0x1d,0x14,0x80,0x8, 0xbe,0xb0,0x5e,0x38,0x10,0x75,0x1d, +0x0, 0xa, 0x1b,0x7e,0x1d,0x14,0x2d,0x31,0x1b,0x34,0x7e,0x1b,0xb0,0x22,0xbe,0xb0, +0xd3,0x68,0x3, 0xb4,0xd4,0x10,0xb4,0xd3,0x8, 0x6d,0x33,0x7a,0x37,0x38,0xee,0x80, +0x2, 0x15,0x1a,0x2, 0x65,0x7b,0xbe,0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x3, 0x2, 0x66, +0xc6,0xbe,0xb0,0x80,0x40,0xc, 0xbe,0xb0,0xdf,0x38,0x7, 0xa, 0x3b,0x9, 0xb3,0x37, +0x62,0x22,0xb4,0xfc,0x5, 0x7e,0xb3,0x38,0x9, 0x22,0xb4,0xfd,0x17,0x6c,0xaa,0x7e, +0xb3,0x28,0xa8,0x60,0x3, 0x4e,0xa0,0x1, 0x7e,0xb3,0x37,0x71,0x60,0x3, 0x4e,0xa0, +0x2, 0x7c,0xba,0x22,0xb4,0xfe,0x5, 0x7e,0xb3,0x2b,0xf, 0x22,0x74,0xff,0x22,0x7c, +0x7b,0x6c,0xaa,0x12,0x66,0xbe,0x78,0x9, 0x7c,0xb7,0x12,0x65,0xc8,0x7c,0xab,0x80, +0xa, 0xb4,0x4, 0x7, 0x7c,0xb7,0x12,0x2a,0xc6,0x7c,0xab,0x7c,0xba,0x22,0x30,0x90, +0x19,0xc2,0x90,0xe5,0x18,0x70,0x9, 0x75,0x18,0x1, 0xe5,0x91,0xf5,0x1a,0x80,0x11, +0x7e,0x71,0x91,0xe5,0x1a,0x12,0x66,0xa9,0x5, 0x1a,0x30,0x91,0xb, 0xc2,0x91,0x5, +0x1a,0xe5,0x1a,0x12,0x66,0x5f,0xf5,0x91,0x22,0x7c,0x6b,0x12,0x66,0xbe,0x78,0x5, +0x7c,0xb6,0x2, 0x66,0xf8,0xb4,0x4, 0x5, 0x7c,0xb6,0x2, 0x37,0xe7,0x22,0x7e,0xb3, +0x38,0x9d,0xc4,0x54,0x7, 0x22,0xb4,0xeb,0x5, 0xe4,0x7a,0xb3,0x38,0xf3,0x7e,0x73, +0x38,0xf3,0xa, 0x27,0x2e,0x24,0x0, 0x6, 0x12,0x67,0x47,0x7c,0xab,0x7c,0xb7,0x4, +0x7a,0xb3,0x38,0xf3,0xb4,0x3, 0xb, 0xe4,0x7a,0xb3,0x38,0xf3,0x6d,0x33,0x7a,0x37, +0x38,0xf0,0x75,0x1a,0xeb,0x7c,0xba,0x22,0x7c,0xa7,0x7c,0x3b,0xa5,0xbb,0x0, 0x7, +0x7c,0xba,0x12,0x68,0x27,0x80,0x2c,0xbe,0x30,0xeb,0x68,0x4, 0xa5,0xbb,0xec,0x9, +0x7c,0xb3,0x7c,0x7a,0x12,0x68,0x71,0x80,0x1a,0xbe,0x30,0x80,0x40,0x15,0xbe,0x30, +0xdf,0x38,0x10,0x7c,0xb3,0x24,0x80,0x7c,0x7a,0x12,0x71,0x62,0xa5,0xbb,0x8f,0x3, +0x75,0x19,0x1, 0xa5,0xbb,0xfc,0x5, 0x7c,0xba,0x2, 0x2e,0xbd,0x74,0x1, 0x7a,0xb3, +0x3, 0xff,0x22,0x2e,0x24,0x20,0x7d,0x7a,0x51,0x82,0x7a,0x41,0x83,0xe4,0x93,0x22, +0x7c,0xab,0x6c,0x77,0xa, 0x27,0x2e,0x24,0x60,0xac,0x12,0x67,0x47,0xbc,0xba,0x78, +0x2, 0xd3,0x22,0xb, 0x70,0xbe,0x70,0x3, 0x40,0xea,0xc3,0x22,0x6c,0x33,0x80,0x1f, +0x7c,0xb3,0x12,0x67,0x50,0x40,0x16,0x7c,0xb3,0x12,0x67,0x98,0x7d,0x43,0x6d,0x55, +0x7d,0x4, 0x3e,0x4, 0x7e,0x1f,0x13,0x8a,0x2d,0x30,0x1b,0x1a,0x50,0xb, 0x30,0x7e, +0x23,0x2a,0x75,0xbc,0x23,0x38,0xd9,0x22,0x7e,0x73,0x2a,0x6e,0xac,0x7b,0x2e,0x34, +0x0, 0x18,0x22,0x6c,0x33,0x6c,0x22,0x80,0x28,0x7c,0xb2,0x12,0x67,0x50,0x50,0x1f, +0x7c,0xb2,0x12,0x67,0x98,0x3e,0x34,0x7e,0x7f,0x13,0x8a,0x2d,0xf3,0xb, 0x7a,0x30, +0x12,0x67,0xda,0x59,0x35,0x39,0xe9,0x30,0x0, 0x5, 0x6d,0x33,0x1b,0x7a,0x30,0xb, +0x20,0x7e,0x73,0x2a,0x75,0xbc,0x72,0x38,0xd0,0x22,0x7c,0xa3,0xb, 0x30,0x74,0x2, +0xa4,0x22,0x7c,0xab,0x7c,0xb7,0xb4,0x18,0x9, 0x7c,0xba,0x12,0x67,0x50,0x50,0x2, +0xd3,0x22,0xc3,0x22,0x7e,0xa3,0x38,0x9c,0x7c,0xba,0x4, 0x7a,0xb3,0x38,0x9c,0x7a, +0xa3,0x37,0xf3,0x22,0xca,0x7b,0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0x83,0xc0,0x82, +0x12,0x66,0x7e,0xd0,0x82,0xd0,0x83,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x7b,0x32, +0xa9,0xc0,0x93,0x75,0x18,0x0, 0x32,0x7a,0xb3,0x38,0x9d,0xc4,0x54,0x7, 0xbe,0xb0, +0x4, 0x68,0x3, 0xb4,0x2, 0x4, 0x74,0x3, 0x80,0x7, 0x60,0x3, 0xb4,0x1, 0x7, 0x74, +0x1, 0x7a,0xb3,0x38,0x9, 0x22,0x74,0x1, 0x7a,0xb3,0x38,0x9, 0xe4,0x7a,0xb3,0x38, +0x9d,0x22,0x7e,0xb3,0x38,0xf2,0x4, 0x7a,0xb3,0x38,0xf2,0xe5,0x19,0xb4,0x1, 0x8, +0xe4,0x7a,0xb3,0x38,0xf2,0x75,0x19,0x0, 0x7e,0x73,0x38,0xf2,0x7a,0x73,0x37,0xf1, +0x22,0xbe,0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x33,0x7e,0x27,0x38,0xf0,0x4d,0x22,0x78, +0xe, 0xa5,0xbf,0xaa,0xa, 0x7e,0x24,0x0, 0x1, 0x7a,0x27,0x38,0xf0,0x15,0x1a,0x7e, +0x27,0x38,0xf0,0xbe,0x24,0x0, 0x1, 0x78,0x10,0xa5,0xbf,0x9, 0x6, 0x7e,0x34,0x0, +0x2, 0x80,0x2, 0x6d,0x33,0x7a,0x37,0x38,0xf0,0x75,0x1a,0xea,0x22,0xe4,0x7a,0xb3, +0x38,0x9d,0x7e,0x8, 0x35,0x93,0x12,0x68,0xfc,0x7e,0x8, 0x35,0xd1,0x7e,0x34,0x0, +0x3e,0x12,0x20,0xe8,0x7e,0x18,0x35,0x93,0x7a,0x1d,0x14,0x12,0x68,0xde,0x2, 0x68, +0xd1,0x75,0x18,0x0, 0x75,0x1a,0x0, 0x7e,0xb3,0x38,0x9d,0xf5,0x91,0x22,0x2, 0x68, +0xe1,0x90,0x60,0x0, 0xe4,0x93,0x54,0xfe,0x75,0x91,0x0, 0xc2,0x90,0xc2,0x91,0xc2, +0xc9,0x54,0xfe,0xf5,0x92,0xd2,0xe8,0xc2,0xc0,0xd2,0xad,0x22,0x7e,0x34,0x0, 0x3e, +0x74,0xff,0x2, 0x20,0xe8,0x30,0x1d,0x8, 0x74,0x5, 0x7e,0x70,0x99,0x12,0x13,0x2c, +0x7e,0xb3,0x34,0x3a,0xb4,0x1, 0x4f,0x12,0x69,0x67,0x49,0x35,0x34,0x3b,0x49,0x15, +0x34,0x3d,0x6d,0x0, 0xbe,0x8, 0x0, 0x0, 0x68,0x1a,0xbe,0x70,0x0, 0x40,0x15,0xbe, +0x70,0x2, 0x38,0x10,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0x73,0x7e,0x73,0x2a, +0x74,0x12,0x10,0xee,0x7e,0xb3,0x34,0x39,0x4, 0x7a,0xb3,0x34,0x39,0x12,0x69,0x6f, +0x28,0xe, 0x12,0x3f,0xd2,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x6, 0x74,0x3, 0x80,0x2, +0x74,0x2, 0x7a,0xb3,0x34,0x3a,0x22,0x7e,0xa3,0x34,0x39,0x74,0x4, 0xa4,0x22,0x7e, +0x73,0x34,0x38,0xbe,0x73,0x34,0x39,0x22,0x7e,0xb3,0x34,0x3a,0xb4,0x1, 0x2, 0xc3, +0x22,0xd3,0x22,0x7e,0xb3,0x2b,0x1e,0x70,0x1f,0x12,0x2f,0xe7,0x12,0x69,0x78,0x50, +0xfb,0x12,0x69,0xa9,0x12,0x6a,0xb8,0x20,0x13,0x3, 0x12,0x55,0xae,0x74,0x2, 0x7a, +0xb3,0x2b,0x1e,0xe4,0x7a,0xb3,0x16,0x91,0x22,0x7e,0xf, 0x13,0x8a,0x7e,0x18,0x8, +0xa, 0xca,0x3b,0x7a,0x1d,0x29,0x7f,0x30,0x12,0x57,0xe5,0xa4,0x7a,0x55,0x31,0x7e, +0xb3,0x2b,0x1d,0xf5,0x2e,0xe4,0x7a,0xb3,0x2b,0x1d,0x7f,0x3, 0x7e,0x1d,0x29,0x12, +0x5f,0xd5,0x12,0xc6,0xa3,0x12,0x3f,0xeb,0x75,0x2d,0x0, 0x12,0x3f,0xa5,0x30,0xf, +0xfd,0x74,0x1, 0x12,0x6a,0x73,0x7e,0x14,0x40,0x0, 0x7d,0x21,0x7d,0x7, 0x12,0x56, +0x2d,0x12,0x6a,0x2e,0x6d,0x33,0x80,0x19,0x7e,0x35,0x2f,0x3e,0x34,0x7f,0x3, 0x2d, +0x13,0xb, 0xa, 0x20,0x7e,0xd, 0x29,0x2d,0x13,0x12,0xc6,0xbf,0x7e,0x35,0x2f,0xb, +0x34,0x7a,0x35,0x2f,0x7e,0x35,0x31,0xbe,0x35,0x2f,0x38,0xdc,0x5, 0x2d,0xe5,0x2d, +0xbe,0xb0,0x1, 0x40,0xb6,0xe5,0x2e,0x7a,0xb3,0x2b,0x1d,0xda,0x3b,0x22,0x7e,0xa3, +0x2a,0x6e,0xa, 0x3a,0x3e,0x34,0x7e,0x8, 0x13,0x8e,0xe4,0x12,0x20,0xe8,0x7e,0xb3, +0x2a,0x71,0x12,0xb9,0x19,0x7d,0x43,0x6c,0x77,0x80,0x1d,0xa, 0x27,0x2d,0x24,0x12, +0x4f,0xe5,0xb, 0xa, 0x0, 0x7e,0x30,0x2, 0xac,0x37,0x2e,0x14,0x13,0x8e,0xb, 0x18, +0x20,0x2d,0x20,0x1b,0x18,0x20,0xb, 0x70,0xbc,0xa7,0x38,0xdf,0x22,0x12,0x69,0x78, +0x50,0xfb,0x22,0x12,0x0, 0xe, 0x7e,0x1f,0x13,0x86,0x22,0x7e,0x8, 0x24,0xf2,0x7e, +0x34,0x0, 0xc, 0xe4,0x12,0x20,0xe8,0x12,0xa4,0x5f,0x12,0xa4,0x56,0xa9,0xd1,0xcb, +0x12,0x6a,0x73,0x7a,0x37,0x24,0xf6,0x7e,0x1f,0x39,0xda,0x7a,0x37,0x24,0xf8,0x7e, +0x1f,0x13,0x86,0x7a,0x37,0x24,0xfa,0x6d,0x33,0x12,0xb9,0x10,0x2, 0xd, 0x7, 0x12, +0xa5,0xef,0x12,0x6a,0x7b,0x2, 0x6a,0xb8,0x12,0x57,0x8e,0x50,0x3, 0xd2,0x13,0x22, +0xc2,0x13,0x22,0x12,0x75,0xd2,0x12,0x6b,0x17,0x12,0xad,0xc9,0x12,0x6c,0x68,0x7e, +0xb3,0x38,0x7, 0xb4,0x1, 0x7, 0x7e,0x34,0x0, 0x14,0x12,0x5f,0xcc,0x7e,0xb3,0x3a, +0xe, 0x60,0x7, 0x14,0x7a,0xb3,0x3a,0xe, 0x80,0x6, 0x7e,0xb3,0x28,0xac,0x60,0xc, +0x12,0x6a,0xaf,0x12,0x57,0x9f,0x12,0xb5,0xf1,0x12,0x9e,0x4f,0x7e,0xb3,0x34,0xb6, +0x60,0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x7e,0xb3,0x28,0xad,0x60,0x9, 0x12,0xbb,0x95, +0x12,0xa4,0x68,0x2, 0xaa,0x3c,0x22,0x7e,0x90,0x1, 0x12,0x5f,0xc8,0x7e,0xf4,0x0, +0x96,0xe4,0x7a,0xb3,0x28,0xac,0x12,0x6c,0x48,0x7e,0x34,0xfe,0x89,0x7e,0x27,0x7, +0xfe,0xbe,0x24,0xfd,0x12,0x58,0x1c,0x7e,0xe7,0x7, 0xfc,0xbd,0xe3,0x58,0x14,0x6d, +0xee,0x9e,0xe7,0x2a,0x5a,0xbe,0xe7,0x28,0x8e,0x8, 0x8, 0x12,0xac,0x93,0x60,0x3, +0x12,0xa6,0x2e,0x12,0xa6,0x3d,0x40,0x5, 0xe4,0x7a,0xb3,0x28,0xa8,0x12,0xc7,0x1, +0x68,0x6, 0x7e,0xb3,0x3a,0xc, 0x60,0x7, 0xe4,0x7a,0xb3,0x28,0xad,0x80,0x65,0x12, +0x6c,0x4f,0x28,0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x30,0x14,0x5, 0xe4,0x7a,0xb3,0x28, +0xad,0x12,0xa6,0x7b,0x50,0xa, 0x12,0x6c,0x48,0x12,0x6c,0x85,0x7c,0x9b,0x80,0x17, +0x7e,0xb3,0x26,0x84,0x70,0x11,0x7e,0xb3,0x26,0x85,0x70,0xb, 0x12,0x6c,0x4f,0x28, +0x6, 0x7e,0x90,0x3, 0x12,0x6c,0x48,0x7e,0xe7,0x7, 0xfa,0xbe,0xe4,0x5, 0xdc,0x8, +0x17,0x12,0x6c,0x4f,0x28,0x12,0x6d,0xee,0x9d,0xef,0xbe,0xe7,0x28,0x8e,0x58,0x8, +0x12,0x6c,0x5a,0xe4,0x7a,0xb3,0x28,0xad,0x74,0x4, 0xac,0xb9,0x7a,0x57,0x28,0xa1, +0x7a,0x57,0x28,0xa3,0x12,0x6c,0x57,0x50,0xd, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0x76, +0xe0,0x28,0x3, 0x12,0x6c,0x5a,0x7e,0xe7,0x28,0x8a,0xbd,0xef,0x8, 0x1f,0x7e,0x24, +0x0, 0x2, 0x7d,0x3f,0x12,0x1e,0xb9,0x6e,0x34,0xff,0xff,0xb, 0x34,0xbe,0x37,0x28, +0x8e,0x58,0xa, 0x12,0x6c,0x57,0x50,0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0x6c,0xe8, +0xb4,0x1, 0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0xa5,0x95,0x7e,0xb3,0x2f,0xa9,0xbe, +0xb0,0x0, 0x28,0x23,0x14,0x7a,0xb3,0x2f,0xa9,0x70,0x1c,0xe4,0x7a,0xb3,0x28,0xad, +0x74,0x1, 0x7a,0xb3,0x28,0xac,0xe4,0x7a,0xb3,0x16,0x91,0x7a,0xb3,0x16,0x90,0x7a, +0xb3,0x28,0x84,0x7a,0xb3,0x26,0x83,0x22,0x74,0x1, 0x7a,0xb3,0x28,0xad,0x22,0x7e, +0x83,0x28,0x84,0xbe,0x80,0x0, 0x22,0xa2,0x17,0x22,0xe4,0x7a,0xb3,0x2f,0xa9,0x7a, +0xb3,0x28,0xac,0x74,0x2, 0x2, 0x26,0x12,0x12,0xab,0xcd,0x60,0x17,0x12,0x6c,0x48, +0x7e,0x37,0x28,0xa1,0x3e,0x34,0x7a,0x37,0x28,0xa1,0x7e,0x37,0x28,0xa3,0x3e,0x34, +0x7a,0x37,0x28,0xa3,0x22,0x7e,0xa0,0x1, 0x7e,0x47,0x7, 0xf8,0x7e,0x4, 0x0, 0xfa, +0xbe,0x44,0xfd,0x12,0x58,0x12,0x7e,0xb3,0x28,0xac,0x60,0x7, 0xe4,0x7a,0xb3,0x28, +0xad,0x80,0x38,0x7e,0xa0,0x5, 0x80,0x33,0x7e,0x34,0xff,0xfb,0xad,0x30,0x7e,0x14, +0x0, 0x2, 0x12,0x6c,0xe0,0x8, 0x5, 0x7e,0xa0,0x4, 0x80,0x1f,0x7e,0x34,0xff,0xfc, +0x12,0x6c,0xde,0x8, 0x5, 0x7e,0xa0,0x3, 0x80,0x11,0x7e,0x34,0xff,0xfd,0x12,0x6c, +0xde,0x8, 0x5, 0x7e,0xa0,0x2, 0x80,0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0xad,0x30, +0x7d,0x21,0x12,0x1e,0xb9,0xbd,0x34,0x22,0xca,0x3b,0x12,0x9a,0xbf,0x38,0x2, 0xa1, +0xab,0x7e,0xc3,0x2f,0xac,0x4c,0xcc,0x78,0x3d,0x7a,0xb3,0x2f,0xac,0xe4,0x7a,0xb3, +0x2f,0xae,0x6c,0xaa,0x80,0x26,0x12,0x6d,0xb6,0x7e,0x70,0x2, 0xac,0x7a,0x9, 0xd3, +0x26,0xfa,0x9, 0xe3,0x26,0xfb,0x7a,0x49,0xd0,0x19,0xe4,0x0, 0x1, 0x74,0x1, 0x19, +0xb4,0x0, 0x8, 0x12,0x6d,0xc0,0x59,0x34,0x0, 0x2, 0xb, 0xa0,0x7e,0xb3,0x28,0x84, +0xbc,0xba,0x38,0xd2,0x80,0x7b,0x7c,0xfc,0x6c,0xaa,0x80,0x31,0x12,0x6d,0xb6,0x7e, +0x49,0xd0,0x9, 0xe4,0x0, 0x1, 0x9, 0xb4,0x0, 0x8, 0x70,0x4, 0x1b,0xf0,0x80,0x1b, +0x12,0x6d,0xc0,0x7d,0x23,0x49,0x34,0x0, 0x2, 0x12,0xa1,0xb6,0xbe,0xf4,0x0, 0x23, +0x8, 0x9, 0x74,0x5, 0x19,0xb4,0x0, 0x8, 0x75,0x5c,0x1, 0xb, 0xa0,0xbc,0xfa,0x38, +0xcb,0x4c,0xff,0x78,0x2, 0x80,0x26,0x7e,0x73,0x2f,0xae,0xbe,0x70,0x4, 0x40,0x22, +0x6c,0xaa,0x80,0xe, 0x12,0x6d,0xb6,0x9, 0xb4,0x0, 0x8, 0xbe,0xb0,0x5, 0x68,0x6, +0xb, 0xa0,0xbc,0xfa,0x38,0xee,0xbc,0xfa,0x78,0x3, 0x75,0x5c,0x0, 0x12,0x6f,0x5d, +0x80,0xf, 0x7c,0xb7,0x4, 0x7a,0xb3,0x2f,0xae,0x80,0x6, 0x12,0x6f,0x5d,0x75,0x5c, +0x0, 0xe5,0x5c,0xda,0x3b,0x22,0x7e,0x90,0x9, 0xac,0x9a,0x2e,0x44,0x2f,0xaf,0x22, +0x7c,0xbd,0x7c,0x7e,0x2, 0x6d,0xcb,0x7c,0xba,0x7c,0x79,0x12,0x6f,0x81,0xb, 0x1a, +0x30,0x22,0x7c,0xbd,0x7c,0x7e,0x7f,0x4, 0xca,0x3b,0x7f,0x70,0x7c,0xe7,0x7c,0xdb, +0x7e,0xc0,0x4, 0x7e,0xb3,0x2a,0x6d,0xf5,0x26,0x7e,0xb3,0x2a,0x6e,0xf5,0x25,0x7e, +0xd4,0x0, 0xc8,0x6c,0xff,0x12,0x6f,0x7d,0xe5,0x26,0xa, 0x1b,0x1b,0x14,0xa, 0xcd, +0xbd,0xc1,0x58,0x14,0xe5,0x25,0xa, 0x1b,0x1b,0x14,0xa, 0xce,0xbd,0xc1,0x58,0x8, +0x4c,0xee,0x68,0x4, 0x4c,0xdd,0x78,0x3, 0x4e,0xf0,0x10,0xb, 0x1a,0xc0,0xbe,0xc4, +0x0, 0xc8,0x8, 0xc, 0x7e,0x17,0x28,0x8a,0xbe,0x14,0x3, 0x20,0x8, 0x2, 0xe1,0x1c, +0xbe,0xc4,0x0, 0x64,0x8, 0xc, 0x7e,0xc7,0x28,0x8a,0xbe,0xc4,0x3, 0x20,0x58,0x2, +0xe1,0x1c,0x6c,0xaa,0x7c,0x8d,0x80,0x1c,0x7c,0x9e,0xbe,0x80,0x0, 0x48,0x11,0x7e, +0xb3,0x2a,0x6d,0xbc,0xb8,0x8, 0x9, 0x12,0x6f,0x53,0x58,0x14,0xb, 0xa0,0x80,0x2, +0xb, 0xa0,0x1b,0x80,0x1a,0x2c,0x1a,0x3d,0x9d,0x32,0x1a,0xc8,0xbd,0xc3,0x18,0xd8, +0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x1, 0xe1,0x1c,0x6c,0xaa,0x7c,0x8d,0x80,0x1c,0x7c, +0x9e,0xbe,0x80,0x0, 0x48,0x11,0x7e,0xb3,0x2a,0x6d,0xbc,0xb8,0x8, 0x9, 0x12,0x6f, +0x53,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0xb, 0x80,0x1a,0x2c,0x1a,0x3d,0x2d, +0x32,0x1a,0xc8,0xbd,0xc3,0x48,0xd8,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x2, 0x80,0x6c, +0x6c,0xaa,0x7c,0x9e,0x80,0x1c,0x7c,0x8d,0xbe,0x90,0x0, 0x48,0x11,0x7e,0xb3,0x2a, +0x6e,0xbc,0xb9,0x8, 0x9, 0x12,0x6f,0x53,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0, +0x1b,0x90,0x1a,0x2c,0x1a,0x3e,0x9d,0x32,0x1a,0xc9,0xbd,0xc3,0x18,0xd8,0xbc,0xca, +0x18,0x5, 0x4e,0xf0,0x4, 0x80,0x35,0x6c,0xaa,0x7c,0x9e,0x80,0x1c,0x7c,0x8d,0xbe, +0x90,0x0, 0x48,0x11,0x7e,0xb3,0x2a,0x6e,0xbc,0xb9,0x8, 0x9, 0x12,0x6f,0x53,0x58, +0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0xb, 0x90,0x1a,0x2c,0x1a,0x3e,0x2d,0x32,0x1a, +0xc9,0xbd,0xc3,0x48,0xd8,0xbc,0xca,0x18,0x3, 0x4e,0xf0,0x8, 0x4c,0xff,0x68,0x2e, +0x7e,0x7b,0xb0,0xbc,0xbd,0x40,0x3, 0x7a,0x7b,0xd0,0x29,0xb7,0x0, 0x2, 0xbc,0xbd, +0x38,0x4, 0x39,0xd7,0x0, 0x2, 0x29,0xb7,0x0, 0x1, 0xbc,0xbe,0x40,0x4, 0x39,0xe7, +0x0, 0x1, 0x29,0xb7,0x0, 0x3, 0xbc,0xbe,0x38,0x4, 0x39,0xe7,0x0, 0x3, 0x7c,0xbf, +0xda,0x3b,0x22,0x7c,0xb8,0x7c,0x79,0x12,0x6d,0xcb,0xbd,0x3d,0x22,0xe4,0x7a,0xb3, +0x2f,0xad,0x7a,0xb3,0x2f,0xac,0x7a,0xb3,0x2f,0xae,0x22,0x7c,0xab,0x7e,0x70,0x2, +0xac,0x7a,0x9, 0xb3,0x26,0xfa,0x9, 0x73,0x26,0xfb,0x2, 0x6d,0xcb,0x7c,0xbd,0x7c, +0x7e,0x7e,0x13,0x2a,0x6e,0xac,0x1b,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x37,0x2d,0x10, +0x7e,0x1f,0x13,0x8a,0x2d,0x31,0x22,0xca,0x79,0x6c,0xff,0x7e,0xd7,0x2a,0x5a,0x6c, +0xee,0x80,0x3e,0x12,0x7f,0xfc,0x50,0x4, 0x7e,0xd7,0x2a,0x5c,0x7c,0xbe,0x12,0x6f, +0x6b,0xbd,0x3d,0x48,0x2a,0x7c,0xbe,0x12,0x88,0x65,0x60,0x23,0x7e,0xc4,0x0, 0x9, +0xca,0xc9,0x7e,0x70,0x9, 0xac,0x7e,0x2e,0x34,0x27,0x76,0x6d,0x22,0x7e,0x30,0x9, +0xac,0x3f,0x2e,0x14,0x28,0xae,0x6d,0x0, 0x12,0x20,0xc3,0x1b,0xfd,0xb, 0xf0,0xb, +0xe0,0x12,0x97,0xbe,0x38,0xbd,0x7a,0x73,0x28,0x93,0x7a,0xf3,0x2a,0x2, 0xda,0x79, +0x22,0x2, 0x6f,0x97,0x7e,0x70,0x18,0x2, 0x6d,0xcb,0x7d,0xf3,0x6d,0xee,0x6c,0x99, +0x80,0x3c,0x7c,0xb9,0x12,0x67,0x98,0x7d,0xd3,0x7d,0xcd,0x3e,0xc4,0x7f,0x57,0x2d, +0xbc,0xb, 0x5a,0x10,0x1a,0x2, 0x1a,0x0, 0x7e,0x83,0x2b,0x20,0xa, 0x98,0x6d,0x88, +0x7f,0x10,0x7f,0x4, 0x12,0x1e,0xeb,0x74,0x6, 0x7f,0x1, 0x1e,0x14,0x1e,0x4, 0x50, +0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0xc1,0x1b,0x5a,0xc0,0xb, 0x90,0x7e,0x83, +0x2a,0x75,0xbc,0x89,0x38,0xbc,0x22,0xca,0x79,0x7c,0x5b,0x7e,0x43,0x28,0x84,0xbe, +0x40,0x1, 0x28,0x2, 0x21,0x56,0x7e,0xa3,0x2a,0x6e,0x7e,0x70,0x2, 0xac,0x75,0x9, +0xf3,0x26,0xfa,0x9, 0xe3,0x26,0xfb,0x7c,0xbf,0x7c,0x7e,0x12,0x6f,0x81,0x7f,0x51, +0x7c,0x1e,0x7c,0x3f,0x7e,0x3, 0x2a,0x70,0x7e,0x23,0x2a,0x6f,0xa, 0x3a,0x6d,0xdd, +0x9d,0xd3,0xa, 0x9a,0xa, 0xc0,0x1b,0xc5,0xa, 0x51,0xbd,0x5c,0x58,0x2, 0x21,0x56, +0xa, 0x53,0x1b,0x54,0xbe,0x54,0x0, 0x0, 0x48,0x55,0x7c,0xb3,0x14,0x12,0x67,0x50, +0x50,0x4d,0x7c,0xb3,0x14,0x12,0x67,0x98,0x7d,0xe3,0x7d,0x5e,0x12,0x71,0x59,0xb, +0x1a,0xf0,0x7d,0x5d,0x3e,0x54,0x7f,0x15,0x2d,0x35,0xb, 0x1a,0x80,0xbe,0xf4,0x0, +0x0, 0x8, 0x11,0x9d,0x8f,0xbe,0x84,0x0, 0x0, 0x58,0x4, 0x6d,0x55,0x80,0x2, 0x7d, +0x58,0x1b,0x1a,0x50,0x7c,0xb0,0x24,0xfe,0xbc,0xb1,0x78,0x13,0x7d,0x4e,0x1b,0x44, +0x7d,0x54,0x12,0x71,0x59,0xb, 0x1a,0x50,0xbd,0x58,0x8, 0x3, 0x1b,0x1a,0x80,0xa, +0x83,0xb, 0x84,0xa, 0x52,0xbd,0x85,0x58,0x5d,0x7c,0xb3,0x4, 0x12,0x67,0x50,0x50, +0x55,0x7c,0xb3,0x4, 0x12,0x67,0x98,0x7d,0xe3,0x7d,0x1e,0x3e,0x14,0x7e,0x1f,0x13, +0x8a,0x7f,0x61,0x2d,0xd1,0xb, 0x6a,0xf0,0x7d,0x19,0x3e,0x14,0x7f,0x65,0x2d,0xd1, +0xb, 0x6a,0x10,0xbe,0xf4,0x0, 0x0, 0x8, 0x11,0x9d,0x1f,0xbe,0x14,0x0, 0x0, 0x58, +0x4, 0x6d,0x55,0x80,0x2, 0x7d,0x51,0x1b,0x6a,0x50,0x7c,0xb0,0x24,0xfe,0xbc,0xb1, +0x78,0x14,0x7d,0x4e,0x1b,0x44,0x7d,0x4, 0x3e,0x4, 0x2d,0x30,0xb, 0x1a,0x0, 0xbd, +0x1, 0x8, 0x3, 0x1b,0x1a,0x10,0xda,0x79,0x22,0x3e,0x54,0x7e,0x1f,0x13,0x8a,0x2d, +0x35,0x22,0x7c,0x6b,0x2e,0x60,0xdd,0x68,0x26,0x2e,0x60,0xfd,0x68,0x21,0x1b,0x61, +0x68,0x1d,0x1b,0x62,0x68,0x19,0x1b,0x61,0x68,0x15,0x1b,0x60,0x68,0x11,0x2e,0x60, +0xa, 0x78,0x4, 0x7a,0x73,0x37,0xe1,0xa, 0x2b,0x19,0x72,0x37,0xe2,0xd2,0x11,0x22, +0xca,0x79,0x6c,0xaa,0x6c,0xee,0x6d,0xdd,0x7e,0xe4,0x7f,0xff,0x7e,0xf0,0x1, 0x80, +0x28,0xa, 0xff,0x7e,0xb3,0x2a,0x6e,0xa, 0xcb,0x2d,0xcf,0x3e,0xc4,0x49,0xfc,0x4, +0xfc,0xbe,0xf4,0x1, 0xf4,0x8, 0x10,0xb, 0xa0,0xbd,0xfd,0x8, 0x4, 0x7d,0xdf,0x80, +0x6, 0xbd,0xfe,0x58,0x2, 0x7d,0xef,0xb, 0xf0,0x7e,0xb3,0x2a,0x6f,0xa, 0xcb,0x1b, +0xc4,0xa, 0xff,0xbd,0xfc,0x48,0xca,0x74,0x2, 0x12,0x6f,0xf4,0x7d,0xf3,0x74,0x7, +0x12,0x6f,0xf4,0x7d,0x43,0x74,0xb, 0x12,0x6f,0xf4,0xbe,0xa0,0xc, 0x78,0x1f,0x7d, +0x2d,0x9d,0x2e,0xbe,0x24,0x7, 0xd0,0x58,0x15,0xbe,0xf4,0x0, 0x50,0x8, 0xf, 0xbe, +0x44,0x0, 0x64,0x8, 0x9, 0xbe,0x34,0x0, 0x50,0x8, 0x3, 0x7e,0xe0,0x1, 0x7e,0xb3, +0x37,0xee,0xb4,0x1, 0xc, 0x74,0xc, 0x6c,0x77,0x12,0x71,0x62,0x6c,0xee,0x12,0x72, +0xfd,0xbe,0xe0,0x1, 0x78,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x7a,0xb3,0x34,0xb6,0xb4, +0x1, 0x34,0x7e,0xb3,0x34,0xc5,0xbe,0xb0,0x8, 0x50,0x1a,0x4, 0x7a,0xb3,0x34,0xc5, +0x7e,0x73,0x34,0xc5,0xbe,0x70,0x3, 0x28,0xc, 0x74,0x8, 0x7a,0xb3,0x34,0xc5,0x74, +0x1, 0x7a,0xb3,0x34,0x8b,0x7e,0x73,0x34,0xc5,0xbe,0x70,0x8, 0x40,0x8, 0x12,0x72, +0xc2,0x60,0x3, 0x12,0x73,0x12,0x7e,0x73,0x34,0xb6,0xbe,0x70,0x0, 0x38,0x5, 0x12, +0x72,0xc2,0x70,0x39,0x6c,0xff,0x80,0x30,0x7c,0xbf,0x12,0x8b,0xef,0x60,0x23,0x7e, +0xb3,0x34,0xda,0x4, 0x12,0x73,0x26,0x7e,0x73,0x34,0xda,0xbe,0x70,0x5, 0x40,0x16, +0x12,0x72,0xfd,0xe4,0x7a,0xb3,0x34,0xda,0x7a,0xb3,0x34,0xc5,0x7a,0xb3,0x34,0x8b, +0x80,0x4, 0xe4,0x12,0x73,0x26,0xb, 0xf0,0x12,0x73,0x6d,0x38,0xcb,0x12,0x72,0xc2, +0x70,0xc, 0x12,0x76,0xe0,0x28,0x4, 0x74,0x5, 0x80,0x4, 0xe4,0x80,0x1, 0xe4,0xda, +0x79,0x22,0x7e,0xb3,0x38,0x32,0xb4,0x1, 0x3, 0x74,0x1, 0x22,0x7e,0x34,0xd7,0x0, +0x12,0x72,0xf5,0x70,0x1b,0x7e,0x34,0xd7,0x1, 0x12,0x72,0xf5,0x70,0x12,0x7e,0x34, +0xd7,0x2, 0x12,0x72,0xf5,0x70,0x9, 0x7e,0x34,0xd7,0x3, 0x12,0x72,0xf5,0x60,0x2, +0xe4,0x22,0x74,0x1, 0x22,0x7e,0x24,0x0, 0xff,0x7e,0x1b,0xb0,0x22,0xe4,0x12,0x77, +0x11,0x12,0x77,0x9, 0x12,0x77,0x1, 0x2, 0x73,0xa, 0x7e,0x34,0xd7,0x3, 0x7a,0x1b, +0xb0,0x22,0x74,0x55,0x12,0x77,0x11,0x74,0xaa,0x12,0x77,0x9, 0x74,0x55,0x12,0x77, +0x1, 0x74,0xaa,0x2, 0x73,0xa, 0x7a,0xb3,0x34,0xda,0x7c,0xbf,0x6c,0x77,0x7c,0x67, +0x7c,0x7b,0xc4,0x23,0x54,0x1f,0x7c,0xab,0x7c,0xb7,0x54,0x7, 0xa, 0x2b,0x2e,0x24, +0x0, 0x5e,0x12,0x67,0x47,0x7c,0x7b,0x4c,0x66,0x68,0xf, 0xa, 0x2a,0x2e,0x24,0x27, +0x72,0x7e,0x29,0xb0,0x4c,0xb7,0x7a,0x29,0xb0,0x22,0x7c,0xb7,0x64,0xff,0xa, 0x2a, +0x2e,0x24,0x27,0x72,0x7e,0x29,0x70,0x5c,0x7b,0x7a,0x29,0x70,0x22,0x7e,0x73,0x28, +0x84,0xbc,0x7f,0x22,0xca,0xd8,0xca,0x79,0xc2,0x0, 0x6d,0x88,0x7a,0x87,0x39,0x3d, +0xe4,0x7a,0xb3,0x1f,0x58,0xe5,0x1f,0xbe,0xb0,0xff,0x50,0x2, 0x5, 0x1f,0x7e,0xb3, +0x28,0x84,0x60,0xa, 0x7e,0x87,0x7, 0xfa,0xbe,0x84,0x0, 0xfa,0x58,0xa, 0xc2,0x14, +0x6d,0x88,0x7a,0x87,0x38,0xfe,0x81,0x97,0x12,0x91,0xe1,0x60,0x10,0x7e,0x84,0x0, +0x64,0x7a,0x87,0x38,0xf4,0x7e,0x84,0x0, 0x2d,0x7a,0x87,0x38,0xfe,0x7e,0x87,0x38, +0xf4,0x4d,0x88,0x68,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xa9,0x6c,0xff,0x80,0x76,0xe4, +0xa, 0x3f,0x19,0xb3,0x1f,0x34,0x12,0x75,0x14,0x7e,0x8, 0x1f,0x52,0x7c,0xbd,0x7c, +0x7e,0x12,0x90,0x9c,0x7d,0x93,0x7e,0x87,0x38,0xfe,0xbd,0x89,0x50,0x4, 0x7a,0x97, +0x38,0xfe,0x7e,0x87,0x39,0x3d,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x39,0x3d,0xe5,0x1f, +0xbe,0xb0,0x5, 0x38,0x1f,0x7e,0x8, 0x39,0x0, 0x12,0x75,0x8c,0x50,0x7, 0x12,0x75, +0xb, 0xd2,0x0, 0x80,0x2e,0x7e,0x8, 0x39,0x0, 0x7e,0x18,0x1f,0x52,0x12,0x77,0x42, +0x50,0x21,0x80,0xf, 0xbe,0x94,0x0, 0x2d,0x40,0x19,0x7e,0x8, 0x1f,0x52,0x12,0x90, +0x4d,0x50,0x10,0x12,0x75,0xb, 0x7e,0x8, 0x1f,0x58,0x7e,0x18,0x1f,0x52,0x12,0x91, +0xbb,0xd2,0x0, 0xb, 0xf0,0x12,0x73,0x6d,0x38,0x85,0x30,0x0, 0x30,0x6c,0xff,0x80, +0x1c,0x12,0x75,0x14,0x7e,0x8, 0x1f,0x58,0x12,0x75,0x8c,0x40,0x9, 0xa, 0x3f,0x9, +0xb3,0x1f,0x34,0xb4,0x1, 0x5, 0x7c,0xbf,0x12,0x74,0xeb,0xb, 0xf0,0x12,0x73,0x6d, +0x38,0xdf,0x75,0x1f,0x0, 0x7e,0x34,0x0, 0x64,0x7a,0x37,0x38,0xf4,0x7e,0x63,0x1f, +0x58,0x7e,0x70,0x6, 0xac,0x67,0xb, 0x34,0xca,0x39,0x7e,0x18,0x1f,0x58,0x7e,0x8, +0x39,0x0, 0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x37,0x38,0xf4,0x4d,0x33,0x78,0x26,0x7e, +0x37,0x38,0xfe,0xbe,0x34,0x0, 0x2d,0x40,0x30,0x7e,0x37,0x39,0x3d,0xbe,0x34,0x0, +0x16,0x40,0x26,0x7e,0x73,0x26,0xf7,0xbe,0x70,0xc, 0x28,0x1d,0x7e,0x73,0x26,0xf6, +0xbe,0x70,0x7, 0x28,0x14,0x6c,0xff,0x80,0x7, 0x7c,0xbf,0x12,0x74,0xeb,0xb, 0xf0, +0x12,0x73,0x6d,0x38,0xf4,0xd2,0x0, 0x80,0x6, 0x6d,0x33,0x7a,0x37,0x38,0xfe,0xa2, +0x0, 0x92,0x14,0x12,0x77,0x2b,0xda,0x79,0xda,0xd8,0x22,0x7c,0xab,0x7e,0xb3,0x3a, +0xc, 0x70,0x17,0x7e,0xb3,0x28,0xa8,0x70,0x11,0x12,0x4f,0xd4,0x68,0xc, 0x12,0x90, +0x35,0x68,0x7, 0x7c,0xba,0x6c,0x77,0x2, 0x73,0x2e,0x22,0x74,0x1, 0xa, 0x8f,0x19, +0xb8,0x1f,0x34,0x22,0x74,0x2, 0xac,0xbf,0x9, 0xd5,0x26,0xfa,0x9, 0xe5,0x26,0xfb, +0x22,0xca,0xf8,0x6c,0xff,0x80,0x18,0x7c,0xbf,0x12,0x6f,0x6b,0xbe,0x37,0x2a,0x5c, +0x58,0xb, 0x12,0x73,0x2a,0x7e,0x70,0x2, 0xac,0x7f,0x12,0x8f,0xa4,0xb, 0xf0,0x12, +0x73,0x6d,0x38,0xe3,0x12,0x75,0x4a,0xda,0xf8,0x22,0xca,0x79,0x6c,0xff,0x6c,0xee, +0x80,0x2e,0x7c,0xbe,0x12,0x88,0x65,0x60,0x25,0x7e,0x34,0x0, 0x2, 0xca,0x39,0xac, +0x7e,0x2e,0x34,0x26,0xfa,0x6d,0x22,0x7e,0x30,0x2, 0xac,0x3f,0x2e,0x14,0x26,0xfa, +0x6d,0x0, 0x12,0x20,0xc3,0x1b,0xfd,0x7c,0xbf,0x12,0x76,0xfb,0xb, 0xf0,0xb, 0xe0, +0x12,0x97,0xbe,0x38,0xcd,0x7a,0xf3,0x28,0x84,0xda,0x79,0x22,0x7c,0xbd,0x7c,0x7e, +0x7c,0x6b,0xc2,0x1, 0x6c,0xaa,0x80,0x30,0x7e,0x50,0x6, 0xac,0x5a,0x7f,0x70,0x2d, +0xf2,0xb, 0xf4,0x29,0xb7,0x0, 0x2, 0xbc,0xb6,0x40,0x1b,0x7e,0x7b,0xb0,0xbc,0xb6, +0x38,0x14,0x29,0xb7,0x0, 0x3, 0xbc,0xb7,0x40,0xc, 0x29,0xb7,0x0, 0x1, 0xbc,0xb7, +0x38,0x4, 0xd2,0x1, 0x80,0x9, 0xb, 0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x38,0xc9,0xa2, +0x1, 0x22,0xca,0xd8,0xca,0x79,0x7e,0xa3,0x2a,0x6e,0x7e,0x47,0x28,0x99,0xe4,0x7a, +0xb3,0x28,0xa6,0x7e,0xb3,0x26,0xf0,0xbe,0xb0,0x0, 0x28,0x48,0x12,0x9e,0x47,0x28, +0x43,0x6c,0xff,0x80,0x3b,0x7e,0x50,0x2, 0xac,0x5f,0x9, 0xd2,0x27,0x36,0x9, 0xe2, +0x27,0x37,0x7e,0x50,0x2, 0xac,0x5e,0x49,0x12,0x4, 0xfc,0x6d,0x22,0x9e,0x27,0x2a, +0x53,0xbd,0x12,0x58,0x19,0x12,0x76,0xe8,0x49,0x12,0x4, 0xfc,0x6d,0x22,0x9e,0x27, +0x2a,0x51,0xbd,0x12,0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x28,0xa6,0x80,0x6, 0xb, 0xf0, +0xbc,0x7f,0x38,0xc1,0xe4,0x7a,0xb3,0x28,0xa7,0x7e,0xb3,0x26,0x83,0x70,0x40,0x12, +0x76,0xe0,0x28,0x3b,0x6c,0xff,0x80,0x33,0x7e,0x50,0x2, 0xac,0x5f,0x9, 0xd2,0x26, +0xfa,0x9, 0xe2,0x26,0xfb,0x12,0x76,0xe8,0x49,0x2, 0x5, 0x7a,0x6d,0x11,0x9d,0x14, +0xbd,0x1, 0x48,0xd, 0x7e,0x10,0x2, 0xac,0x1e,0x49,0x20,0x5, 0x7a,0xbd,0x21,0x58, +0x8, 0x74,0x1, 0x7a,0xb3,0x28,0xa7,0x80,0x6, 0xb, 0xf0,0xbc,0x7f,0x38,0xc9,0x12, +0x9c,0xbc,0xe4,0x7a,0xb3,0x28,0xa9,0x7e,0x37,0x28,0x88,0x2e,0x37,0x28,0x86,0xbe, +0x37,0x28,0x9f,0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xa9,0x74,0x1, 0x7a,0xb3,0x28, +0xaa,0x6c,0xff,0x80,0x1f,0x12,0x76,0xf1,0x49,0x25,0x25,0xf7,0x7d,0x43,0x9d,0x42, +0x7d,0x34,0x12,0x21,0xa, 0xbe,0x37,0x28,0x9d,0x8, 0x7, 0xe4,0x7a,0xb3,0x28,0xaa, +0x80,0x7, 0xb, 0xf0,0x12,0x73,0x6d,0x38,0xdc,0x6c,0xff,0x80,0x9, 0x12,0x76,0xf1, +0x59,0x35,0x25,0xf7,0xb, 0xf0,0x12,0x73,0x6d,0x38,0xf2,0xda,0x79,0xda,0xd8,0x22, +0x7e,0x73,0x28,0x84,0xbe,0x70,0x0, 0x22,0xa, 0x1d,0xa, 0x2a,0x2d,0x21,0x3e,0x24, +0x22,0x7c,0xbf,0x12,0x6f,0x6b,0x74,0x2, 0xac,0xbf,0x22,0x7e,0x70,0x1, 0x2, 0x73, +0x2e,0x7e,0x34,0xd7,0x2, 0x7a,0x1b,0xb0,0x22,0x7e,0x34,0xd7,0x1, 0x7a,0x1b,0xb0, +0x22,0x7e,0x34,0xd7,0x0, 0x7e,0x24,0x0, 0xff,0x7a,0x1b,0xb0,0x22,0x12,0x77,0x74, +0x12,0x8d,0x9b,0x12,0x71,0x90,0x7a,0xb3,0x2a,0xc, 0x22,0x30,0x14,0x13,0x12,0xc7, +0x1, 0x68,0x6, 0x7e,0xb3,0x3a,0xc, 0x60,0x8, 0x7e,0x34,0xb, 0xb8,0x7a,0x37,0x38, +0xfc,0x22,0x7f,0x61,0x7f,0x50,0x7e,0x6b,0x90,0x80,0x1f,0x29,0x86,0x0, 0x1, 0x80, +0xf, 0x7f,0x5, 0x7c,0xb9,0x7c,0x78,0x12,0x75,0x90,0x50,0x2, 0xd3,0x22,0xb, 0x80, +0x29,0x76,0x0, 0x3, 0xbc,0x78,0x50,0xe9,0xb, 0x90,0x29,0x76,0x0, 0x2, 0xbc,0x79, +0x50,0xd9,0xc3,0x22,0x7e,0xa3,0x28,0x84,0xe4,0x7a,0xb3,0x34,0xb7,0x6c,0x33,0x80, +0x3d,0x7e,0x70,0x2, 0xac,0x73,0x9, 0x23,0x26,0xfb,0x7e,0x10,0x1, 0x6c,0x0, 0x80, +0x27,0xbc,0x3, 0x68,0x21,0x7e,0x70,0x2, 0xac,0x70,0x9, 0x93,0x26,0xfb,0xa, 0x29, +0xa, 0x32,0x12,0x82,0xcd,0x18,0x2, 0xb, 0x10,0xbe,0x10,0x2, 0x40,0x8, 0x74,0x2, +0x7a,0xb3,0x34,0xb7,0x80,0x6, 0xb, 0x0, 0xbc,0xa0,0x38,0xd5,0xb, 0x30,0xbc,0xa3, +0x38,0xbf,0x2, 0x77,0xc5,0xca,0xf8,0x7e,0x33,0x28,0x84,0x6c,0x22,0x80,0x3f,0x74, +0x2, 0xac,0xb2,0x9, 0x15,0x26,0xfa,0x9, 0x5, 0x26,0xfb,0x7e,0xa0,0x1, 0x6c,0x99, +0x80,0x26,0xbc,0x92,0x68,0x20,0x12,0x8f,0xde,0x9, 0xf3,0x26,0xfb,0xa, 0x28,0xa, +0x31,0x12,0x82,0xcd,0x18,0xb, 0xa, 0x2f,0xa, 0x30,0x12,0x82,0xcd,0x8, 0x2, 0xb, +0xa0,0xbe,0xa0,0x3, 0x50,0x6, 0xb, 0x90,0xbc,0x39,0x38,0xd6,0xb, 0x20,0xbc,0x32, +0x38,0xbd,0x7e,0xb3,0x35,0x54,0xbe,0xb0,0x0, 0x28,0x12,0x14,0x7a,0xb3,0x35,0x54, +0xbe,0xb0,0x14,0x28,0x8, 0x7e,0x34,0x0, 0x8c,0x7a,0x37,0x2a,0x5a,0x7e,0xb3,0x37, +0xed,0x70,0x58,0x7e,0xb3,0x3a,0xc, 0x70,0x52,0x7e,0xb3,0x37,0x71,0x70,0x4c,0x7e, +0x37,0x38,0xfe,0xbe,0x34,0x0, 0x14,0x50,0x42,0x7e,0x37,0x28,0x8a,0xbe,0x34,0x3, +0x20,0x58,0x38,0x7e,0xb3,0x28,0x84,0xbe,0xb0,0x3, 0x40,0x2f,0xbe,0xa0,0x3, 0x40, +0x2a,0x7e,0xb3,0x26,0x85,0xbe,0xb0,0x3, 0x50,0x9, 0x7e,0xb3,0x26,0x84,0xbe,0xb0, +0x3, 0x40,0x18,0x7e,0xb3,0x26,0xf6,0xbe,0xb0,0x8, 0x50,0x9, 0x7e,0xb3,0x26,0xf7, +0xbe,0xb0,0x8, 0x40,0x6, 0x74,0x1e,0x7a,0xb3,0x35,0x54,0xda,0xf8,0x22,0xca,0xf8, +0x7e,0xa3,0x2a,0x2, 0x4c,0xaa,0x78,0x11,0x7e,0xb3,0x2a,0x3, 0xbe,0xb0,0x0, 0x28, +0x13,0x74,0x1, 0x7a,0xb3,0x2a,0x7, 0x80,0xb, 0xbe,0xa0,0x0, 0x28,0x6, 0x74,0x1, +0x7a,0xb3,0x2a,0xb, 0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18,0x28,0xae,0x7e,0x8, +0x29,0x8, 0x12,0x20,0xc3,0x1b,0xfd,0x6c,0xff,0x12,0x7d,0x51,0x12,0x7a,0xa2,0x74, +0x9, 0xac,0xbf,0x59,0x35,0x29,0x8, 0x49,0x35,0x28,0xb0,0x12,0x78,0xeb,0x12,0x79, +0xe0,0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0xe1,0xda,0xf8,0x22,0x7d,0xf3,0x9f,0x11,0x7e, +0x44,0x7, 0x80,0x12,0x7b,0x74,0x7d,0xd5,0x1b,0xd4,0xbe,0xf4,0x0, 0x3f,0x38,0x1f, +0x7e,0x24,0x0, 0x3f,0x9d,0x2f,0x7e,0x34,0x2, 0x57,0x12,0x79,0xc5,0xbe,0x18,0x0, +0x4a,0x40,0x4, 0x7e,0x18,0x0, 0x4a,0x7e,0x8, 0x0, 0x4a,0x9f,0x1, 0x7f,0x10,0x7d, +0x5d,0x9e,0x54,0x0, 0x3f,0xbd,0x5f,0x38,0x1f,0x12,0x79,0xd7,0x40,0x1a,0x7d,0x3d, +0x9e,0x34,0x0, 0x40,0x12,0x79,0xbd,0xbe,0x18,0x0, 0x4d,0x40,0x4, 0x7e,0x18,0x0, +0x4c,0x12,0x79,0xce,0x2f,0x10,0x80,0x14,0x12,0x79,0xd7,0x50,0xf, 0x7d,0x3d,0x9e, +0x34,0x0, 0x20,0x12,0x79,0xbd,0x7d,0x14,0x6d,0x0, 0x2f,0x10,0xbe,0xf4,0x0, 0x3f, +0x28,0x5a,0xbd,0x5f,0x28,0x56,0x7d,0xed,0xb, 0xe4,0x1e,0xe4,0x7d,0x5e,0x1b,0x54, +0xbd,0x5f,0x40,0xc, 0x7d,0x35,0x9d,0x3f,0x6d,0x22,0x7e,0x14,0x1, 0x44,0x80,0xa, +0x7d,0x3f,0x9d,0x3e,0x6d,0x22,0x7e,0x14,0x1, 0x43,0x12,0x1e,0xfc,0x12,0x79,0xc7, +0xbd,0x5f,0x7d,0x14,0x40,0xc, 0x1e,0x14,0x1b,0x14,0x6d,0x0, 0x9f,0x1, 0x7f,0x10, +0x80,0x6, 0x1e,0x14,0x6d,0x0, 0x2f,0x10,0xbe,0x18,0x0, 0x4a,0x50,0x5, 0x7e,0x18, +0x0, 0x4a,0x22,0x12,0x79,0xce,0xbf,0x10,0x28,0x2, 0x7f,0x10,0x22,0x7d,0x2f,0x9d, +0x23,0x7e,0x34,0x2, 0x52,0xad,0x23,0x7c,0x76,0x7c,0x65,0x1a,0x24,0x22,0x7d,0x14, +0x6d,0x0, 0x9e,0x8, 0x0, 0x4d,0x22,0x7d,0xed,0x9e,0xe4,0x0, 0xb, 0xbd,0xef,0x22, +0x74,0x9, 0xac,0xbf,0x59,0x35,0x29,0xa, 0x22,0xca,0xd8,0xca,0x79,0x7e,0x44,0x7, +0x80,0x6c,0xff,0x7e,0x70,0x9, 0xac,0x7f,0x9, 0xe3,0x29,0xc, 0x5e,0xe0,0xf, 0x49, +0xc3,0x29,0xa, 0x7d,0x24,0x2e,0x24,0x0, 0x14,0xbd,0xc2,0x40,0x3f,0x49,0xd3,0x29, +0x8, 0x7d,0x3d,0x12,0xa4,0xe5,0x7c,0xdb,0xbe,0xd0,0x3, 0x40,0xe, 0x7d,0x34,0x1b, +0x34,0x12,0x79,0xe0,0x7c,0xbe,0x12,0x7a,0x77,0x80,0x40,0x7e,0x70,0x2, 0xac,0x7d, +0x2e,0x34,0x60,0xc5,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xd0,0x74,0x9, 0xac,0xbf,0x59, +0xd5,0x29,0x8, 0x7e,0x34,0x7, 0xf8,0x12,0x79,0xe0,0x80,0x1f,0xbd,0xc4,0x40,0x1b, +0x7d,0x54,0x2e,0x54,0x0, 0xa, 0xbd,0xc5,0x40,0x5, 0x7c,0xbe,0x12,0x7a,0x77,0x7d, +0xc4,0x1b,0xc4,0x74,0x9, 0xac,0xbf,0x59,0xc5,0x29,0xa, 0xb, 0xf0,0xbe,0xf0,0xa, +0x40,0x81,0xda,0x79,0xda,0xd8,0x22,0x7c,0xab,0x7e,0x8, 0x29,0xbc,0xbe,0xa0,0xa, +0x50,0x1f,0xa, 0x3a,0x7f,0x70,0x2d,0xf3,0x7e,0x7b,0xb0,0xb4,0x2, 0x4, 0x74,0x1, +0x80,0x2, 0x74,0x3, 0x7a,0x7b,0xb0,0x74,0x3, 0x2d,0x31,0x7d,0x20,0x39,0xb1,0x0, +0xa, 0x22,0x7d,0xd3,0x7e,0x44,0x4, 0x38,0x7e,0xa3,0x2a,0x6f,0x74,0x40,0xa4,0x7d, +0xb5,0x1b,0xb4,0xbe,0xd4,0x0, 0x3f,0x38,0x1d,0x7e,0xe4,0x0, 0x3f,0x9d,0xed,0x7e, +0xf4,0x2, 0x36,0x12,0x7b,0x61,0x40,0x4, 0x7e,0x78,0x0, 0x44,0x7e,0x18,0x0, 0x44, +0x9f,0x17,0x7f,0x71,0x80,0x7f,0x7d,0x5b,0x9e,0x54,0x0, 0x3f,0xbd,0x5d,0x38,0x18, +0x7d,0xed,0x9d,0xe5,0x7e,0xf4,0x2, 0x4a,0x12,0x7b,0x61,0x40,0x4, 0x7e,0x78,0x0, +0x43,0x12,0x7b,0x58,0x2f,0x71,0x80,0x5d,0x7d,0xcb,0xb, 0xc4,0x1e,0xc4,0x7d,0x5c, +0x1b,0x54,0xbd,0x5d,0x40,0xc, 0x7d,0xf5,0x9d,0xfd,0x6d,0xee,0x7e,0x14,0x1, 0x39, +0x80,0xa, 0x7d,0xfd,0x9d,0xfc,0x6d,0xee,0x7e,0x14,0x1, 0x3b,0x7f,0x17,0x12,0x1e, +0xfc,0x7f,0x71,0x12,0x45,0xb1,0x7f,0x71,0xbd,0x5d,0x7d,0x34,0x40,0xc, 0x1e,0x34, +0x1b,0x34,0x6d,0x22,0x9f,0x17,0x7f,0x71,0x80,0x6, 0x1e,0x34,0x6d,0x22,0x2f,0x71, +0xbe,0x78,0x0, 0x44,0x50,0x6, 0x7e,0x78,0x0, 0x44,0x80,0x9, 0x12,0x7b,0x58,0xbf, +0x71,0x28,0x2, 0x7f,0x71,0x7d,0x3f,0x22,0x7d,0x34,0x9e,0x34,0x0, 0x44,0x6d,0x22, +0x22,0xad,0xfe,0x6d,0xee,0x7d,0x3f,0x7d,0x2e,0x7c,0x76,0x7c,0x65,0x7f,0x71,0xbe, +0x78,0x0, 0x44,0x22,0x7e,0xa3,0x2a,0x70,0x74,0x40,0xa4,0x22,0xca,0x3b,0x6d,0x0, +0x7e,0xe3,0x2a,0x2, 0x4c,0xee,0x78,0x20,0x6c,0xff,0x6d,0x11,0x74,0x2, 0xac,0xbf, +0x12,0x7d,0x46,0xac,0x3f,0x19,0xa1,0x34,0xe0,0x74,0x2, 0xa, 0x1f,0x19,0xb1,0x35, +0x4a,0xb, 0xf0,0xbe,0xf0,0xa, 0x78,0xe2,0x12,0x7d,0xb3,0x7e,0x24,0x0, 0x14,0xad, +0x32,0x7d,0x43,0x2e,0x44,0x3, 0x20,0x6c,0xff,0xa1,0x18,0x74,0x9, 0xac,0xbf,0x9, +0xd5,0x28,0xb2,0x5e,0xd0,0xf, 0xbe,0xd0,0xa, 0x40,0x2, 0xa1,0x16,0xa, 0x1d,0x9, +0xb1,0x29,0xbc,0xbe,0xb0,0x1, 0x78,0x2, 0x81,0xff,0x75,0x24,0x0, 0x7e,0x71,0x24, +0x74,0x9, 0xac,0x7b,0x9, 0xc3,0x34,0xe0,0xbc,0xcd,0x68,0x2, 0x81,0xf2,0x12,0x7b, +0x74,0x7d,0xf5,0x9e,0xf4,0x0, 0x20,0x2e,0xf4,0x0, 0x14,0x49,0x23,0x34,0xde,0xbd, +0x2f,0x28,0xe, 0x74,0x9, 0xac,0xbf,0x49,0x15,0x28,0xb0,0xbd,0x1f,0x38,0x2, 0x81, +0x9e,0x74,0x9, 0xac,0xbf,0x49,0x35,0x28,0xb0,0x9d,0x32,0x12,0x21,0xa, 0x7d,0x3, +0x7e,0xa1,0x24,0x74,0x9, 0xa4,0x49,0x25,0x34,0xdc,0x12,0x7d,0x51,0x9d,0x32,0x12, +0x21,0xa, 0x2d,0x3, 0xa, 0x1c,0x9, 0xa1,0x35,0x4a,0xbe,0xa0,0x0, 0x28,0x17,0x7e, +0x30,0x2, 0xac,0x3c,0x59,0x1, 0x35,0x36,0xa, 0x1c,0x2e,0x14,0x35,0x4a,0x7c,0xba, +0x14,0x7a,0x19,0xb0,0xa1,0x16,0x74,0x2, 0xac,0xbc,0x49,0x15,0x35,0x36,0xbe,0x14, +0x0, 0x32,0x28,0x8, 0x7d,0xe1,0x2d,0xe4,0xbd,0xe0,0x40,0x20,0xbe,0x14,0x0, 0x32, +0x28,0x8, 0xbe,0x4, 0x0, 0x32,0x28,0x2, 0x80,0x72,0x7d,0xe1,0x2e,0xe4,0x0, 0x32, +0xbd,0xe0,0x50,0x8, 0xbe,0x14,0x0, 0x32,0x28,0x2, 0x80,0x60,0xbe,0x4, 0x0, 0xa0, +0x28,0x56,0xa, 0x1d,0x9, 0xb1,0x29,0xbc,0x70,0x4, 0x74,0x3, 0x80,0x2, 0x74,0x1, +0xa, 0x1d,0x19,0xb1,0x29,0xbc,0x74,0x3, 0xa, 0x1c,0x19,0xb1,0x29,0xc6,0xbe,0xe0, +0x0, 0x28,0x63,0x1b,0xe0,0x7e,0x70,0x9, 0xac,0x7f,0x2e,0x34,0x28,0xae,0x7e,0x14, +0x1f,0x34,0x74,0x9, 0x12,0x1f,0x8c,0x7e,0x70,0x9, 0xac,0x7e,0x12,0x7f,0xa0,0xac, +0x3f,0x12,0x7d,0x3d,0x7e,0x34,0x1f,0x34,0x7e,0x30,0x9, 0xac,0x3e,0x12,0x7d,0x3d, +0x1b,0xf0,0x74,0x2, 0xac,0xbc,0x80,0x4, 0x74,0x2, 0xac,0xbc,0x59,0x5, 0x35,0x36, +0x80,0x24,0x5, 0x24,0xe5,0x24,0xbe,0xb0,0xa, 0x50,0x2, 0x61,0xdd,0x80,0x17,0x6d, +0x11,0x74,0x2, 0xac,0xbd,0x12,0x7d,0x46,0xac,0x3d,0x19,0xa1,0x34,0xe0,0x74,0x2, +0xa, 0x1d,0x19,0xb1,0x35,0x4a,0xb, 0xf0,0xbc,0xef,0x28,0x2, 0x61,0xbb,0xe4,0x7a, +0xb3,0x16,0x92,0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18,0x28,0xae,0x7e,0x8, 0x34, +0xdc,0x12,0x20,0xc3,0x1b,0xfd,0x7a,0xe3,0x2a,0x2, 0xda,0x3b,0x22,0x2e,0x14,0x28, +0xae,0x74,0x9, 0x2, 0x1f,0x8c,0x59,0x15,0x35,0x36,0x7e,0xa0,0xff,0x7e,0x30,0x9, +0x22,0x74,0x9, 0xac,0xbf,0x49,0x35,0x28,0xae,0x22,0x7e,0xb3,0x38,0x32,0x70,0x3, +0x12,0x7b,0x7c,0x2, 0x7d,0x66,0xca,0x79,0x7e,0xf3,0x2a,0x2, 0x7e,0xe3,0x2a,0x3, +0x7c,0xbf,0x7c,0x7e,0x12,0x7e,0x9f,0x7c,0xbf,0x12,0x9e,0x59,0x4c,0xee,0x78,0x15, +0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18,0x28,0xae,0x7e,0x8, 0x29,0x62,0x12,0x20, +0xc3,0x1b,0xfd,0x80,0xb, 0x7e,0xb3,0x2a,0x9, 0x70,0x5, 0x7c,0xbf,0x12,0x7f,0x12, +0x7c,0xbf,0x12,0x7d,0xeb,0xbe,0xf0,0x0, 0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x2a,0xb, +0xda,0x79,0x22,0x7e,0x73,0x2a,0x3, 0xbe,0x73,0x2a,0x2, 0x78,0x13,0x12,0x7f,0x98, +0x40,0xe, 0x7e,0x37,0x34,0xb4,0xbe,0x34,0x0, 0x14,0x38,0xe, 0xb, 0x34,0x80,0x6, +0x7e,0x37,0x34,0xb4,0x1e,0x34,0x7a,0x37,0x34,0xb4,0x7e,0xb3,0x2a,0x2, 0x70,0x6, +0x6d,0x33,0x7a,0x37,0x34,0xb4,0x7e,0x37,0x34,0xb4,0x22,0x6c,0xaa,0x7e,0x50,0x9, +0xac,0x5a,0x49,0x32,0x29,0x62,0x12,0x7e,0x3c,0x59,0x32,0x28,0xae,0x7e,0x50,0x9, +0xac,0x5a,0x49,0x32,0x29,0x64,0x12,0x7e,0x3c,0x59,0x32,0x28,0xb0,0x7e,0x90,0x9, +0xac,0x9a,0x9, 0xb4,0x29,0x66,0x19,0xb4,0x28,0xb2,0x7e,0x90,0x9, 0xac,0x9a,0x9, +0xb4,0x29,0x67,0x19,0xb4,0x28,0xb3,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x68, +0x19,0xb4,0x28,0xb4,0xb, 0xa0,0xbe,0xa0,0xa, 0x40,0xb2,0x22,0x1e,0x34,0x1e,0x34, +0x1e,0x34,0x1e,0x34,0x22,0x7f,0x71,0x69,0x37,0x0, 0x2, 0x7d,0x53,0x12,0x7f,0x90, +0xb, 0x7a,0x20,0x2d,0x25,0x1b,0xa, 0x20,0x69,0x27,0x0, 0x4, 0x7d,0x52,0xc4,0x54, +0xf0,0x7c,0xab,0xe4,0x1e,0x34,0x1e,0x34,0x2d,0x35,0x79,0x30,0x0, 0x2, 0x69,0x37, +0x0, 0x6, 0x7d,0x53,0x7c,0xab,0xe4,0x3e,0x54,0x3e,0x54,0x1e,0x24,0x1e,0x24,0x1e, +0x24,0x1e,0x24,0x2d,0x25,0x79,0x20,0x0, 0x4, 0x69,0x27,0x0, 0x8, 0x7c,0x45,0x6c, +0x55,0x12,0x7e,0x3c,0x1e,0x34,0x1e,0x34,0x2d,0x32,0x79,0x30,0x0, 0x6, 0x22,0x7c, +0x67,0x7c,0x7b,0xa5,0xbf,0x0, 0x17,0xbe,0x60,0x0, 0x28,0xf, 0x74,0x1, 0x7a,0xb3, +0x2a,0x7, 0xe4,0x7a,0xb3,0x2a,0x9, 0x7a,0xb3,0x2a,0xa, 0x2, 0x7f,0xb5,0xa5,0xbe, +0x0, 0x1b,0x6c,0xaa,0x7e,0x60,0xff,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x62,0x29,0x66, +0xb, 0xa0,0xbe,0xa0,0xa, 0x78,0xf0,0x74,0x1, 0x7a,0xb3,0x2a,0x6, 0x6c,0xaa,0x80, +0x20,0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x28,0xae,0x12,0x7f,0x6, 0x1b,0x18,0x20, +0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x28,0xb0,0x12,0x7f,0x6, 0x1b,0x18,0x20,0xb, +0xa0,0xbc,0x7a,0x38,0xdc,0x22,0xb, 0x18,0x20,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e, +0x24,0x22,0xca,0x3b,0x7c,0xfb,0x6c,0xee,0x80,0x6c,0x6c,0xdd,0x74,0x9, 0xac,0xbd, +0x9, 0x45,0x29,0x66,0x7e,0x70,0x9, 0xac,0x7e,0x9, 0x53,0x28,0xb2,0xbc,0x45,0x68, +0x7, 0xb, 0xd0,0xbe,0xd0,0xa, 0x40,0xe4,0xbe,0xd0,0xa, 0x50,0x4d,0x74,0x9, 0xac, +0xbd,0x9, 0xc5,0x29,0x66,0x49,0x25,0x29,0x64,0x49,0x33,0x28,0xb0,0x12,0x4f,0xcc, +0x74,0x9, 0xac,0xbd,0x12,0x7f,0xa8,0x9d,0x32,0x12,0x21,0xa, 0x2d,0x31,0x7a,0x35, +0x24,0xa, 0x3c,0x9, 0xb3,0x29,0xbc,0xb4,0x1, 0xe, 0x6d,0x33,0x74,0x2, 0xac,0xbc, +0x59,0x35,0x34,0xa0,0x59,0x35,0x34,0xc6,0x7e,0x35,0x24,0x7c,0xbd,0x7c,0x5e,0x7c, +0x4c,0x12,0x7f,0x8d,0xb, 0xe0,0xbc,0xfe,0x38,0x90,0xda,0x3b,0x22,0x2, 0x47,0x36, +0x3, 0x3, 0x54,0xc0,0x7c,0xab,0xe4,0x22,0x7e,0x73,0x2a,0x2, 0xbe,0x70,0x1, 0x22, +0x2e,0x34,0x28,0xae,0x7e,0x30,0x9, 0x22,0x49,0x25,0x29,0x62,0x74,0x9, 0xac,0xbe, +0x49,0x35,0x28,0xae,0x22,0x7e,0x8, 0x34,0xc6,0x7e,0x34,0x0, 0x14,0xe4,0x12,0x20, +0xe8,0x7e,0x8, 0x34,0xa0,0x7e,0x34,0x0, 0x14,0x2, 0x20,0xe8,0x7e,0xb3,0x2a,0x9, +0x70,0x23,0x7e,0xb3,0x34,0xb7,0xb4,0x2, 0x9, 0x12,0x7f,0x98,0x28,0x4, 0x74,0x3, +0x80,0x1, 0xe4,0x7a,0xb3,0x34,0xc2,0x7e,0x73,0x34,0xc3,0xbe,0x73,0x34,0xc2,0x28, +0x4, 0x7a,0x73,0x34,0xc2,0x22,0x12,0xa0,0x50,0x2, 0x7f,0xcc,0x7e,0xb3,0x2a,0x3, +0xb4,0x1, 0x22,0x7e,0xb3,0x28,0x84,0xb4,0x1, 0x1b,0x7e,0xb3,0x28,0xa8,0x70,0x15, +0x7e,0xb3,0x26,0x83,0xb4,0x1, 0xe, 0x7e,0xb3,0x28,0x85,0x70,0x8, 0x7e,0xb3,0x2a, +0x68,0x70,0x2, 0xd3,0x22,0xc3,0x22,0x7d,0x13,0x7d,0x32,0x6d,0x22,0x74,0x6, 0x2f, +0x11,0x14,0x78,0xfb,0xb, 0x14,0x12,0x1f,0x5, 0x7d,0x53,0xbe,0x54,0x0, 0xff,0x28, +0x4, 0x7e,0x54,0x0, 0x40,0x22,0xca,0xf8,0x7e,0xf3,0x2a,0x70,0x7a,0x37,0x1f,0x3a, +0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x3c,0xe4,0x7a,0xb3,0x1f,0x34,0x7a,0xb3,0x1f, +0x35,0x7e,0x73,0x2a,0x6f,0x7a,0x73,0x1f,0x36,0x7a,0xf3,0x1f,0x37,0x7a,0xb3,0x1f, +0x38,0x7a,0xb3,0x1f,0x39,0x7e,0x8, 0x1f,0x34,0x12,0x80,0x9b,0x6d,0x22,0x7d,0x3, +0x6d,0x11,0x7e,0x37,0x15,0xa0,0x2f,0x10,0x7e,0x33,0x1f,0x36,0x6d,0x0, 0x12,0x1f, +0x7, 0xa, 0x1f,0x6d,0x0, 0x12,0x1f,0x7, 0xda,0xf8,0x22,0x12,0xc, 0x29,0x7e,0x37, +0x15,0x9e,0x22,0xca,0x3b,0x7c,0xc4,0x7c,0xf6,0x7c,0xe7,0x7c,0xdb,0x74,0x9, 0xac, +0xb5,0x7d,0x95,0x2e,0x94,0x27,0x76,0x6d,0x88,0x7e,0xe7,0x2a,0x66,0xe4,0x39,0xb4, +0x0, 0x6, 0x7e,0x70,0x2, 0xac,0x7f,0x9, 0xb3,0x26,0xfa,0xf5,0x35,0x9, 0xb3,0x26, +0xfb,0xf5,0x36,0x7e,0x73,0x2a,0x6e,0x7c,0x6e,0x7e,0x8, 0x0, 0x39,0x12,0x82,0xe6, +0xf5,0x37,0xe5,0x35,0x7e,0x73,0x2a,0x6d,0x7c,0x6d,0x7e,0x8, 0x0, 0x38,0x12,0x82, +0xe6,0x7c,0xab,0xe5,0x38,0x7e,0x71,0x39,0x12,0x6f,0x81,0x7d,0xf3,0x7a,0xf5,0x41, +0x7e,0xf4,0x15,0x9e,0x7a,0xf5,0x43,0x85,0x38,0x3b,0x85,0x39,0x3c,0x7a,0xa1,0x3d, +0x85,0x37,0x3e,0x7e,0xb3,0x2a,0x59,0xf5,0x3f,0x75,0x40,0x0, 0xbe,0xc0,0x1, 0x78, +0x8, 0xe5,0x3f,0x1e,0xb0,0x1e,0xb0,0xf5,0x3f,0x7e,0x8, 0x0, 0x3b,0x12,0x80,0x9b, +0x7d,0x23,0x6d,0x33,0x7e,0xb7,0x15,0xa0,0x6d,0xaa,0x2f,0x51,0x7e,0x37,0x15,0xa2, +0x6d,0x22,0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x15,0xa4,0x2f,0x10,0x7a,0x1d,0x2c,0x7e, +0x37,0x15,0xa6,0x6d,0x22,0x7d,0x3, 0x7e,0x37,0x15,0xa8,0x2f,0x10,0x7a,0x1d,0x30, +0x7f,0x65,0xa, 0x3d,0xe5,0x35,0xa, 0xfb,0x9d,0xf3,0x7d,0x3f,0x7c,0xc7,0x41,0x48, +0xa, 0x4e,0xe5,0x36,0xa, 0x5b,0x9d,0x54,0xf5,0x34,0x41,0x32,0xbe,0xc0,0x0, 0x58, +0x2, 0x41,0x30,0x7e,0x73,0x2a,0x6d,0xbc,0x7c,0x18,0x2, 0x41,0x30,0xe5,0x34,0xbe, +0xb0,0x0, 0x58,0x2, 0x41,0x30,0x7e,0x73,0x2a,0x6e,0xbe,0x71,0x34,0x18,0x2, 0x41, +0x30,0x7c,0xbc,0x7e,0x71,0x34,0x12,0x6d,0xcb,0x7e,0x53,0x2a,0x59,0xa, 0x25,0x7d, +0xf3,0x9d,0xf2,0xbe,0xf4,0x0, 0x0, 0x8, 0x77,0xbd,0xef,0x18,0xd, 0x7f,0x14,0x2e, +0x34,0x0, 0x6, 0x7e,0x1b,0xb0,0x4, 0x7a,0x1b,0xb0,0xe5,0x35,0xa, 0x2b,0x1a,0x3c, +0x12,0x82,0xcd,0x18,0xd, 0xe5,0x36,0xa, 0x2b,0xe5,0x34,0x1a,0x3b,0x12,0x82,0xcd, +0x8, 0x4e,0x7c,0xbc,0x7e,0x71,0x34,0x7c,0x6f,0x12,0x83,0x39,0xf5,0x3a,0xb4,0x2, +0x6, 0x7d,0x3f,0xe, 0x34,0x9d,0xf3,0xe5,0x3a,0xbe,0xb0,0x2, 0x68,0x5, 0xe5,0x3a, +0xb4,0x1, 0x2d,0x12,0x82,0xbe,0x1a,0x1c,0x12,0x82,0xc5,0x7e,0x1d,0x2c,0x9f,0x10, +0x7a,0x1d,0x2c,0x12,0x82,0xbe,0xe5,0x34,0x1a,0x1b,0x12,0x82,0xc5,0x7e,0x1d,0x30, +0x9f,0x10,0x7a,0x1d,0x30,0x12,0x82,0xbe,0x9f,0x51,0x1a,0x26,0x1a,0x24,0x9f,0x61, +0x5, 0x34,0xa, 0x2e,0xe5,0x36,0xa, 0x3b,0x2d,0x32,0x1a,0x27,0xe5,0x34,0x1a,0x3b, +0xbd,0x32,0x18,0x2, 0x21,0x7c,0xb, 0xc0,0xa, 0x2d,0xe5,0x35,0xa, 0x3b,0x2d,0x32, +0x1a,0x37,0x1a,0xfc,0xbd,0xf3,0x18,0x2, 0x21,0x70,0xbe,0x58,0x0, 0x0, 0x78,0x2, +0xb, 0x5c,0xbe,0x68,0x0, 0x0, 0x78,0x2, 0xb, 0x6c,0x7e,0x1d,0x2c,0x7f,0x5, 0x12, +0x82,0xd7,0x1b,0x4a,0x30,0x7e,0x1d,0x30,0x7f,0x6, 0x12,0x82,0xd7,0x79,0x34,0x0, +0x2, 0x7e,0xb3,0x2a,0x65,0x60,0xd, 0x1e,0xd4,0x1e,0xc4,0x50,0x4, 0x4e,0xd4,0x80, +0x0, 0x14,0x78,0xf3,0xbe,0x68,0x0, 0x7f,0x28,0x4, 0x7e,0x68,0x0, 0x7f,0x7d,0x3d, +0x39,0x74,0x0, 0x5, 0x74,0x9, 0xac,0xbf,0x9, 0x75,0x27,0x7c,0x39,0x74,0x0, 0x6, +0xbe,0x70,0xf, 0x28,0x6, 0x74,0xf, 0x39,0xb4,0x0, 0x6, 0xda,0x3b,0x22,0x7d,0x3f, +0x1a,0x26,0x1a,0x24,0x22,0x1a,0x2, 0x12,0x1e,0xeb,0x7f,0x1, 0x22,0x9d,0x32,0x12, +0x21,0xa, 0xbe,0x34,0x0, 0x1, 0x22,0x74,0x6, 0x2f,0x11,0x14,0x78,0xfb,0x12,0x1f, +0x7, 0x2e,0x18,0x0, 0x20,0x22,0xca,0xf8,0x7c,0xf6,0x7c,0x87,0x7c,0x9b,0xa, 0x2f, +0x7d,0x32,0x3e,0x34,0xb, 0x34,0x7c,0xb7,0xbc,0xf9,0x38,0x14,0xa, 0xf8,0x1b,0xf4, +0xa, 0x3f,0x9d,0xf3,0xa, 0x39,0xbd,0x3f,0x18,0x6, 0x7c,0xab,0xa, 0x39,0x80,0x1d, +0xbc,0xf9,0x28,0xd, 0xa, 0x39,0xa, 0x5f,0x2d,0x53,0xb, 0x54,0x7c,0xab,0xe4,0x80, +0x10,0xa, 0x3f,0xa, 0x58,0x2d,0x53,0xa, 0x39,0x9d,0x53,0x7c,0xab,0x9d,0x32,0x7c, +0xb7,0x7a,0xb, 0xb0,0x7c,0xba,0xda,0xf8,0x22,0x7c,0xa6,0x7c,0x37,0x7c,0x2b,0xe4, +0x6c,0x11,0x80,0x46,0xbc,0xa1,0x68,0x40,0x1a,0x41,0x3e,0x44,0x9, 0x4, 0x26,0xfb, +0xa, 0x20,0xa, 0x33,0x9d,0x32,0x12,0x21,0xa, 0x7c,0x7, 0x1a,0x41,0x3e,0x44,0x9, +0x74,0x26,0xfa,0xa, 0x27,0xa, 0x32,0x9d,0x32,0x12,0x21,0xa, 0x7c,0x97,0xbe,0x90, +0x1, 0x18,0x8, 0xbe,0x0, 0x1, 0x18,0x3, 0x74,0x1, 0x22,0xbe,0x90,0x2, 0x18,0x8, +0xbe,0x0, 0x2, 0x18,0x3, 0x74,0x2, 0x22,0xb, 0x10,0x7e,0x83,0x28,0x84,0xbc,0x81, +0x18,0xb2,0x22,0x7a,0x37,0x1f,0x38,0x7e,0x34,0x15,0xa8,0x7a,0x37,0x1f,0x3c,0x7e, +0x34,0x15,0x9e,0x7a,0x37,0x1f,0x3a,0x7e,0x73,0x2a,0x6f,0x7a,0x73,0x1f,0x35,0x7e, +0x73,0x2a,0x70,0x7a,0x73,0x1f,0x34,0x7e,0x37,0x2a,0x5c,0x7a,0x37,0x1f,0x3e,0x7e, +0x37,0x2a,0x5e,0x7a,0x37,0x1f,0x40,0x7e,0x37,0x2a,0x60,0x7a,0x37,0x1f,0x42,0x74, +0x1, 0x7a,0xb3,0x1f,0x36,0x7a,0xb3,0x1f,0x37,0x7e,0x8, 0x1f,0x34,0x7e,0x18,0x1f, +0x44,0x12,0x8, 0x0, 0x7e,0x37,0x1f,0x4e,0x7e,0x27,0x1f,0x4a,0xbd,0x23,0x28,0x2, +0x7d,0x32,0x22,0xca,0x3b,0x7e,0x8, 0x1f,0x34,0x12,0x3f,0xf2,0x7e,0x1f,0x39,0xf4, +0x7a,0x1d,0x27,0x7e,0xb3,0x2a,0x74,0xf5,0x2e,0x7e,0xb3,0x39,0x87,0xb4,0x1, 0x6, +0x7e,0x38,0x39,0x89,0x80,0x4, 0x7e,0x38,0x5, 0xf8,0x6d,0x33,0x7a,0x35,0x2b,0x74, +0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x39,0x88,0x70,0xe, 0x7e,0xb3,0x39,0x86,0x70,0x8, +0x74,0x1, 0x7a,0xb3,0x39,0x88,0x81,0xb8,0x7e,0xb3,0x39,0x88,0x70,0x6, 0x74,0x1, +0x7a,0xb3,0x39,0x88,0x7e,0xb3,0x39,0x87,0xb4,0x1, 0x14,0x75,0x2d,0x0, 0x80,0x6, +0x12,0x84,0xfa,0x12,0x85,0x8, 0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xf3,0x80,0x18,0x75, +0x2d,0x0, 0x80,0xc, 0x12,0x84,0xfa,0x3e,0x24,0x3e,0x24,0x1e,0x24,0x12,0x85,0x8, +0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xed,0x7e,0x34,0x0, 0xfa,0x7a,0x35,0x2f,0x7e,0x18, +0x1f,0x34,0x7f,0x1, 0x12,0x85,0x19,0x75,0x2d,0x0, 0x80,0x10,0x12,0x84,0xed,0xbe, +0x35,0x2b,0x8, 0x6, 0x12,0x84,0xed,0x7a,0x35,0x2b,0x5, 0x2d,0xe5,0x2e,0xbe,0xb1, +0x2d,0x38,0xe9,0x12,0x84,0xe5,0x40,0x25,0x7e,0xb3,0x39,0x87,0xb4,0x1, 0x1e,0x5, +0x1e,0xe5,0x1e,0xbe,0xb0,0xa, 0x40,0x15,0x75,0x1e,0x0, 0xe5,0x2e,0xa, 0x3b,0x3e, +0x34,0xca,0x39,0x7e,0x1d,0x27,0x7f,0x3, 0x12,0x20,0xc3,0x1b,0xfd,0x74,0x2, 0x12, +0x0, 0x1e,0x12,0x84,0xe5,0x50,0xb, 0x74,0x2, 0x7a,0xb3,0x39,0xf3,0xe4,0x7a,0xb3, +0x39,0x88,0xda,0x3b,0x22,0x7e,0x37,0x2b,0x7, 0xbe,0x35,0x2b,0x22,0x7e,0xa1,0x2d, +0x74,0x2, 0xa4,0x49,0x35,0x1f,0x34,0x2, 0x21,0xa, 0x7e,0xa1,0x2d,0x74,0x2, 0xa4, +0x7f,0x13,0x2d,0x35,0xb, 0x1a,0x20,0x22,0x7e,0xd, 0x27,0x2d,0x15,0xb, 0xa, 0x30, +0x9d,0x32,0x59,0x35,0x1f,0x34,0x5, 0x2d,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e, +0x73,0x2a,0x6e,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7f,0x16,0x7f,0x5, 0x12,0x20,0xc3, +0x1b,0xfd,0x6c,0xdd,0x12,0x87,0xb8,0x7a,0xb3,0x1f,0x6c,0x6c,0xcc,0x80,0x45,0x12, +0x85,0xbf,0x78,0x3e,0x12,0x87,0xc0,0xb, 0x1a,0xe0,0x7d,0x3f,0x12,0x21,0xa, 0x7d, +0x13,0x7d,0x3e,0x12,0x21,0xa, 0xbd,0x31,0x58,0x2, 0x7d,0xfe,0xbe,0xe5,0x2f,0x8, +0x5, 0x7e,0xe5,0x2f,0x80,0xb, 0x6d,0x33,0x9e,0x35,0x2f,0xbd,0x3e,0x8, 0x2, 0x7d, +0xe3,0x7d,0x3e,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1f,0x6c,0x4, 0x7a,0xb3, +0x1f,0x6c,0xb, 0xc0,0x7e,0x73,0x2a,0x70,0xbc,0x7c,0x38,0xb3,0x7e,0x73,0x1f,0x6c, +0x4c,0x77,0x68,0x1f,0x12,0x87,0xc9,0xbd,0x3e,0x8, 0x2, 0x7d,0x7f,0x6c,0xcc,0x80, +0xa, 0x12,0x85,0xbf,0x78,0x3, 0x12,0x87,0xde,0xb, 0xc0,0x7e,0x73,0x2a,0x70,0xbc, +0x7c,0x38,0xee,0xb, 0xd0,0xbe,0xd0,0x2, 0x50,0x2, 0xa1,0x34,0xda,0x3b,0x22,0xa, +0xec,0x9, 0x7e,0x2a,0xdc,0xa, 0x37,0x5e,0x34,0x0, 0x1, 0xa, 0xed,0xbd,0x3e,0x22, +0xca,0x3b,0x7f,0x31,0x7a,0xd, 0x24,0x7e,0x35,0x28,0x7a,0x35,0x2f,0x7e,0xd, 0x24, +0x7f,0x13,0x12,0x85,0x19,0x7e,0x35,0x28,0x7a,0x35,0x2a,0x12,0x86,0x3f,0x7e,0xd, +0x24,0x2d,0x15,0x7f,0x13,0x2d,0x35,0x12,0xa2,0x54,0xda,0x3b,0x22,0x7e,0x37,0x2a, +0x4f,0x1e,0x34,0x7a,0x35,0x28,0x7e,0x8, 0x4, 0xfc,0x7e,0x18,0x4, 0x0, 0x12,0x85, +0xd0,0x7e,0x37,0x28,0x99,0xe, 0x34,0x7a,0x35,0x28,0x7e,0x8, 0x5, 0x7a,0x7e,0x18, +0x4, 0x7e,0x12,0x85,0xd0,0x12,0xa4,0xb9,0x12,0xa3,0xb3,0x2, 0x86,0x2e,0xe4,0x7a, +0xb3,0x3, 0xfe,0x7e,0xb3,0x28,0xa8,0x60,0x5, 0xe4,0x7a,0xb3,0x3, 0xfe,0x22,0x7e, +0xa3,0x2a,0x74,0x74,0x2, 0xa4,0x22,0xca,0x3b,0x7e,0x44,0x7f,0xff,0x7d,0x14,0x7d, +0x4, 0x6d,0x22,0x7d,0x32,0x7d,0xb4,0x6c,0xee,0x6c,0xff,0x7e,0x68,0x4, 0xfc,0x7e, +0x78,0x5, 0x7a,0xe4,0x7a,0xb3,0x8, 0x8, 0x7a,0xb3,0x8, 0x9, 0x7a,0xb3,0x26,0xf6, +0x7a,0xb3,0x26,0xf8,0x7a,0xb3,0x26,0xf7,0x7a,0xb3,0x26,0xf9,0x6c,0xaa,0x80,0x5c, +0x12,0x87,0x9e,0xbd,0xa1,0x58,0x2, 0x7d,0x1a,0xbd,0xa3,0x8, 0x2, 0x7d,0x3a,0x7e, +0xd0,0x2, 0xac,0xda,0x7f,0x47,0x2d,0x96,0xb, 0x4a,0xa0,0xbd,0xab,0x58,0x2, 0x7d, +0xba,0x12,0x87,0x9e,0x7e,0x87,0x2a,0x53,0x7e,0x94,0x0, 0x3, 0xad,0x98,0xbd,0xa9, +0x8, 0x2, 0xb, 0xe0,0x12,0x87,0x9e,0xbe,0xa4,0x0, 0x64,0x8, 0xb, 0x7e,0xb3,0x26, +0xf7,0x4, 0x7a,0xb3,0x26,0xf7,0x80,0x12,0x12,0x87,0x9e,0xbe,0xa4,0xff,0x9c,0x58, +0x9, 0x7e,0xb3,0x26,0xf9,0x4, 0x7a,0xb3,0x26,0xf9,0xb, 0xa0,0x7e,0xb3,0x2a,0x74, +0xbc,0xba,0x38,0x9c,0x7a,0x17,0x7, 0xfe,0x7a,0x37,0x8, 0x2, 0x7a,0xe3,0x8, 0x9, +0x7a,0xb7,0x8, 0x6, 0x12,0x86,0x3f,0x2d,0xd5,0x6c,0xaa,0x80,0x53,0x12,0x87,0xab, +0xbd,0xb0,0x58,0x2, 0x7d,0xb, 0xbd,0xb2,0x8, 0x2, 0x7d,0x2b,0x7e,0xd0,0x2, 0xac, +0xda,0x7f,0x56,0x2d,0xb6,0xb, 0x5a,0x90,0x7e,0xa7,0x2a,0x51,0x7e,0xb4,0x0, 0x3, +0xad,0xba,0xbd,0x9b,0x8, 0x2, 0xb, 0xf0,0x12,0x87,0xab,0xbe,0xb4,0x0, 0x64,0x8, +0xb, 0x7e,0xb3,0x26,0xf6,0x4, 0x7a,0xb3,0x26,0xf6,0x80,0x12,0x12,0x87,0xab,0xbe, +0xb4,0xff,0x9c,0x58,0x9, 0x7e,0xb3,0x26,0xf8,0x4, 0x7a,0xb3,0x26,0xf8,0xb, 0xa0, +0x12,0x5f,0xf8,0x38,0xa8,0x7a,0x7, 0x7, 0xfc,0x7a,0x27,0x8, 0x0, 0x7a,0xf3,0x8, +0x8, 0x12,0x86,0x3f,0x2d,0xf5,0x6c,0xaa,0x80,0x14,0x7e,0xf0,0x2, 0xac,0xfa,0x7f, +0x67,0x2d,0xd7,0xb, 0x6a,0xd0,0xbd,0xd4,0x58,0x2, 0x7d,0x4d,0xb, 0xa0,0x12,0x5f, +0xf8,0x38,0xe7,0x7a,0x47,0x8, 0x4, 0xbd,0x1, 0x58,0x2, 0x7d,0x10,0x7a,0x17,0x7, +0xf8,0xbd,0x32,0x58,0x2, 0x7d,0x32,0x7a,0x37,0x7, 0xfa,0xda,0x3b,0x22,0x7e,0xd0, +0x2, 0xac,0xda,0x7f,0x46,0x2d,0x96,0xb, 0x4a,0xa0,0x22,0x7e,0xd0,0x2, 0xac,0xda, +0x7f,0x56,0x2d,0xb6,0xb, 0x5a,0xb0,0x22,0x7e,0xf4,0x7f,0xff,0x9f,0x44,0xe4,0x22, +0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d,0x35,0x22,0xa, 0x17,0x6d,0x0, 0x7f,0x14,0x12, +0x1f,0x58,0x7d,0x73,0x12,0x21,0xa, 0x7d,0xe3,0x7d,0x3f,0x2, 0x21,0xa, 0x74,0x2, +0xac,0xbc,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0xe0,0x9d,0xe7,0x7f,0x15,0x2d,0x35,0x1b, +0x1a,0xe0,0x22,0x7e,0x24,0x0, 0x7d,0x12,0x90,0xd, 0x50,0x8, 0x7e,0x27,0x2a,0x4f, +0x1e,0x24,0x1e,0x24,0x7d,0x32,0x22,0x7e,0xb3,0x38,0x7, 0x70,0x2e,0x7e,0x73,0x37, +0xea,0xbe,0x70,0x10,0x40,0x2, 0x6c,0x77,0x7e,0xb3,0x38,0x32,0xb4,0x1, 0x3, 0x7e, +0x70,0x6, 0xa, 0x37,0x2e,0x34,0xf, 0xf0,0x12,0x88,0x5c,0x7c,0xab,0xe5,0x5e,0xa, +0x3b,0x2e,0x37,0x39,0x84,0x7a,0x37,0x39,0x84,0x80,0xc, 0x7e,0xa3,0x37,0xeb,0xbe, +0xa0,0x7f,0x28,0x3, 0x7e,0xa0,0x7f,0x7c,0xba,0x2, 0x88,0x4c,0x75,0x5e,0x0, 0x7a, +0xb3,0x3a,0x7, 0xc2,0x1c,0x22,0x2d,0x32,0x2e,0x34,0x20,0xfa,0x7a,0x71,0x82,0x7a, +0x61,0x83,0xe4,0x93,0x22,0x7c,0x7b,0x12,0x89,0x30,0x9, 0xa2,0x27,0x72,0x7c,0xb7, +0x54,0x7, 0xa, 0x3b,0x2e,0x34,0x0, 0x5e,0x12,0x88,0x5c,0x5c,0xba,0x22,0x6c,0x0, +0x6c,0x11,0x80,0x13,0x7c,0xb1,0x12,0x88,0x65,0x60,0xa, 0x12,0x88,0xd8,0x40,0x5, +0x7e,0x0, 0x1, 0x80,0xa, 0xb, 0x10,0x7e,0x73,0x28,0x84,0xbc,0x71,0x38,0xe5,0x7c, +0xb0,0x6c,0x77,0x12,0x88,0xf1,0xbe,0x0, 0x1, 0x68,0xb, 0x7c,0xb0,0x7e,0x70,0x1, +0x12,0x88,0xf1,0xb4,0x1, 0x21,0x6c,0x11,0x80,0x15,0x7c,0xb1,0x12,0x88,0x65,0x60, +0xc, 0x12,0x88,0xd8,0x50,0x7, 0x7c,0xb1,0x6c,0x77,0x12,0x73,0x2e,0xb, 0x10,0x7e, +0x3, 0x28,0x84,0xbc,0x1, 0x38,0xe3,0x22,0x74,0x2, 0xac,0xb1,0x9, 0x25,0x26,0xfa, +0x9, 0x35,0x26,0xfb,0x7c,0xb2,0x7c,0x73,0x7c,0xb7,0xb4,0x18,0x2, 0xd3,0x22,0xc3, +0x22,0x7c,0xab,0xa5,0xbf,0x0, 0xc, 0x7e,0xb3,0x37,0x61,0x7a,0xb3,0x37,0x62,0x7a, +0xa3,0x37,0x61,0x7e,0xb3,0x37,0x62,0x60,0x4, 0x74,0x8, 0x80,0xd, 0x7e,0xb3,0x28, +0x84,0x70,0xb, 0x7e,0xb3,0x37,0x63,0x60,0x5, 0x14,0x7a,0xb3,0x37,0x63,0x7e,0x73, +0x37,0x63,0xbe,0x70,0x0, 0x28,0x3, 0x74,0x1, 0x22,0xe4,0x22,0x7c,0xa5,0x7c,0xb7, +0xc4,0x23,0x54,0x1f,0xa, 0x2b,0x22,0x7e,0x8, 0x26,0x86,0x7e,0x34,0x0, 0x3, 0xe4, +0x12,0x20,0xe8,0x7e,0x8, 0x26,0x89,0x12,0x8f,0xc7,0x7a,0xb3,0x26,0x83,0x7a,0xb3, +0x26,0x84,0x7a,0xb3,0x26,0x85,0x7a,0xb3,0x26,0xf0,0x7a,0xb3,0x26,0xf1,0x7a,0xb3, +0x26,0xf2,0x7e,0x18,0x26,0x6f,0x12,0x8a,0x92,0x6c,0x55,0x12,0x89,0xf9,0x7a,0xb3, +0x26,0x85,0x7e,0x18,0x26,0x5b,0x12,0x8a,0xa2,0x6c,0x55,0x12,0x89,0xf9,0x7a,0xb3, +0x26,0x84,0x6c,0x77,0x80,0x14,0x12,0x8a,0x7e,0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb, +0x12,0x89,0x2c,0x2e,0x24,0x26,0x86,0x12,0x8a,0x87,0x7e,0x63,0x26,0x84,0xbc,0x67, +0x38,0xe4,0x6c,0x77,0x80,0x14,0x12,0x8a,0x7e,0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb, +0x12,0x89,0x2c,0x2e,0x24,0x26,0x89,0x12,0x8a,0x87,0x7e,0xa3,0x26,0x85,0xbc,0xa7, +0x38,0xe4,0x7e,0xb3,0x26,0x84,0xa4,0x7a,0xb3,0x26,0x83,0x7e,0x18,0x26,0xe6,0x12, +0x8a,0x92,0x7e,0x50,0x1, 0x12,0x89,0xf9,0x7a,0xb3,0x26,0xf2,0x7e,0x18,0x26,0xdc, +0x12,0x8a,0xa2,0x7e,0x50,0x1, 0x12,0x89,0xf9,0x7c,0xab,0x7a,0xa3,0x26,0xf1,0x7e, +0xb3,0x26,0xf2,0xa4,0x7a,0xb3,0x26,0xf0,0x22,0xca,0x69,0xca,0xf8,0x7c,0x4b,0x6c, +0xaa,0x6d,0xff,0x6c,0xff,0x80,0x6c,0x7e,0xd0,0x2, 0xac,0xdf,0x7f,0x60,0x2d,0xd6, +0xb, 0x6a,0xe0,0x4c,0x55,0x68,0x6, 0x6e,0xe4,0xff,0xff,0xb, 0xe4,0xbd,0x3e,0x58, +0x50,0x4c,0xff,0x78,0x8, 0x6d,0x44,0x69,0xf0,0x0, 0x2, 0x80,0x1b,0x7c,0xb4,0x14, +0xbc,0xbf,0x7f,0x56,0x78,0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x6d,0xff,0x80,0x9, 0x1b, +0xb5,0xb, 0x5a,0x40,0x69,0xf6,0x0, 0x2, 0x4c,0x55,0x68,0xc, 0x6e,0x44,0xff,0xff, +0xb, 0x44,0x6e,0xf4,0xff,0xff,0xb, 0xf4,0xbd,0x4e,0x58,0x15,0xbd,0xfe,0x18,0x11, +0xa, 0xba,0x7e,0x6d,0x24,0x2d,0xdb,0x7a,0x6b,0xf0,0xb, 0xa0,0xbe,0xa0,0xa, 0x50, +0x6, 0xb, 0xf0,0xbc,0x4f,0x38,0x90,0x7c,0xba,0xda,0xf8,0xda,0x69,0x22,0x7c,0xb7, +0x54,0x7, 0x7e,0x24,0x0, 0x1, 0x22,0x7e,0x29,0x60,0x4c,0x6a,0x7a,0x29,0x60,0xb, +0x70,0x22,0x7a,0x1d,0x24,0x7e,0xf, 0x6, 0xf8,0x7e,0xb3,0x2a,0x6e,0x7e,0x37,0x2a, +0x53,0x22,0x7a,0x1d,0x24,0x7e,0xa3,0x2a,0x6e,0x74,0x2, 0xa4,0x7e,0xf, 0x6, 0xf8, +0x2d,0x15,0x7e,0xb3,0x2a,0x6d,0x7e,0x37,0x2a,0x51,0x22,0x7c,0x2b,0x7e,0xb3,0x1f, +0x33,0xbc,0x2b,0x68,0x50,0x12,0x8b,0x1a,0x7c,0x3b,0x7c,0xb2,0x12,0x8b,0x1a,0x7c, +0xab,0xbe,0x30,0xff,0x68,0x3f,0xbe,0xa0,0xff,0x68,0x3a,0x7e,0x70,0x4, 0xac,0x73, +0xa, 0x2a,0x12,0x88,0x56,0xbe,0xb0,0x2, 0x38,0x2b,0xa, 0x2b,0x7e,0x34,0x2, 0xe0, +0xad,0x32,0x2e,0x34,0x16,0x93,0x6d,0x22,0x30,0x1b,0x3, 0x2, 0x4f,0x93,0x7e,0xb3, +0x2b,0x1d,0xb4,0x1, 0x10,0x12,0x57,0xe5,0xa4,0x7a,0x55,0x29,0x7e,0x8, 0xd, 0xc8, +0x74,0x1, 0x2, 0x4f,0x21,0x22,0x7e,0xb3,0x2b,0xf, 0x7c,0xab,0x6c,0x77,0x7e,0x50, +0x5, 0xac,0x57,0x9, 0x62,0x26,0x33,0xbc,0x6a,0x78,0x3, 0x7c,0xb7,0x22,0xb, 0x70, +0xbe,0x70,0x4, 0x40,0xe9,0x74,0xff,0x22,0x7c,0xab,0x12,0x8f,0xce,0xd2,0x1b,0x7c, +0xba,0x12,0x8a,0xbb,0xc2,0x1b,0x22,0xca,0x3b,0x7e,0xb3,0x2a,0x74,0xf5,0x27,0x12, +0x6c,0x57,0x50,0x2, 0x61,0xd9,0x6d,0x33,0x9e,0x37,0x2a,0x4f,0x3e,0x34,0xbe,0x37, +0x7, 0xf8,0x18,0x75,0x7e,0xb3,0x16,0x92,0x70,0x6f,0x7e,0xb3,0x28,0xa8,0xb4,0x1, +0x59,0x7e,0x77,0x2a,0x51,0x7e,0x67,0x2a,0x53,0x75,0x24,0x0, 0x80,0x47,0xe5,0x24, +0x12,0x88,0x65,0x60,0x3e,0x12,0x8b,0xdc,0x12,0x8f,0xe8,0x7e,0xb3,0x2a,0x3, 0xb4, +0x1, 0x9, 0xe5,0x26,0xb4,0x18,0x4, 0xe, 0x64,0xe, 0x74,0x7e,0xa1,0x26,0x74,0x2, +0xa4,0x49,0x35,0x4, 0xfc,0xbd,0x36,0x48,0xd, 0xe5,0x25,0xa, 0x2b,0xe5,0x27,0x12, +0x8b,0xe4,0xbd,0x37,0x58,0xd, 0xe5,0x24,0x6c,0x77,0x12,0x73,0x2e,0x12,0x8b,0xdc, +0x12,0x8f,0xa4,0x5, 0x24,0x12,0x8f,0xd6,0x38,0xb4,0x7e,0xb3,0x2a,0x68,0x70,0x9, +0x7e,0xb3,0x2a,0x6b,0x70,0x3, 0x12,0x9a,0x76,0xda,0x3b,0x22,0x7e,0x71,0x24,0x74, +0x2, 0xac,0x7b,0x22,0xa, 0x3b,0x2d,0x32,0x3e,0x34,0x49,0x33,0x4, 0xfc,0x22,0xca, +0xf8,0x7c,0xfb,0x6d,0xdd,0x7c,0xbf,0x12,0x98,0x93,0x7d,0xe3,0x7c,0xbf,0x12,0x6f, +0x6b,0x7d,0xf3,0x74,0x2, 0xac,0xbf,0x9, 0x95,0x26,0xfb,0x7c,0xbf,0x12,0x8f,0x82, +0x40,0x2, 0x81,0xc0,0x74,0x2, 0xac,0xbf,0x9, 0xa5,0x26,0xfa,0xbe,0xa0,0x0, 0x28, +0xa, 0x7c,0xba,0x14,0x7c,0x79,0x12,0x6d,0xcb,0x7d,0xd3,0x12,0x8c,0xce,0x58,0x6, +0x7c,0xba,0x4, 0x12,0x8f,0x67,0x7e,0x24,0x0, 0x2, 0x12,0x8f,0x5f,0xbe,0xa0,0x0, +0x28,0x4e,0x12,0x8c,0xce,0x58,0x49,0xbe,0x90,0x0, 0x28,0x44,0xbe,0x90,0x0, 0x28, +0x3f,0xbe,0xf4,0x0, 0xc8,0x8, 0x39,0x7d,0x3d,0x3e,0x34,0x3e,0x34,0xbd,0x3f,0x8, +0x2f,0x12,0x8c,0xc4,0xbe,0x34,0x1, 0x2c,0x8, 0x26,0xa, 0x2a,0x7e,0xb3,0x2a,0x74, +0x12,0x8b,0xe4,0xbe,0x34,0x1, 0x90,0x8, 0x17,0xbe,0xf4,0x1, 0x5e,0x58,0xd, 0x7e, +0x34,0x0, 0x3, 0xad,0x3e,0xbd,0x3f,0x8, 0x3, 0xe4,0x80,0x35,0x74,0x1, 0x80,0x31, +0xbe,0x90,0x18,0x78,0x2b,0xbe,0xf4,0x0, 0xc8,0x8, 0x25,0x12,0x8c,0xc4,0xbe,0x34, +0x0, 0xc8,0x8, 0x1c,0xa, 0x2a,0x7e,0x73,0x2a,0x74,0xa, 0x37,0x12,0x8b,0xe6,0xbe, +0x34,0x0, 0xc8,0x8, 0xb, 0x7e,0xb3,0x28,0x84,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x1, +0xe4,0xda,0xf8,0x22,0x7e,0x70,0x2, 0xac,0x79,0x49,0x33,0x4, 0xfc,0x22,0x7e,0xb3, +0x2a,0x6f,0xa, 0x3b,0x1b,0x34,0xa, 0xca,0xbd,0xc3,0x22,0x12,0xa2,0x3d,0x12,0x9a, +0xed,0x12,0x8b,0x47,0x12,0x99,0xd6,0x2, 0x8c,0xea,0xca,0x3b,0x12,0x75,0x4a,0x7e, +0xb3,0x28,0x84,0x60,0x6, 0x7e,0xb3,0x36,0xe2,0x60,0x9, 0xe4,0x7a,0xb3,0x36,0xe4, +0x7a,0xb3,0x36,0x69,0x7e,0xb3,0x36,0xe2,0x70,0x5d,0x6c,0x99,0x80,0x51,0x12,0x8d, +0x92,0x9, 0xf5,0x26,0xfb,0x7c,0xb9,0x12,0x8f,0x82,0x40,0x41,0x6c,0xee,0x80,0x35, +0x74,0x2, 0xac,0xbe,0x9, 0xd5,0x36,0x6a,0x9, 0xc5,0x36,0x6b,0xa, 0x28,0xa, 0x3d, +0x12,0x8d,0x8a,0x78,0x1e,0xa, 0x2f,0xa, 0x3c,0x12,0x8d,0x8a,0x78,0x15,0x7c,0xb9, +0x12,0x6f,0x6b,0xbe,0x34,0x3, 0x20,0x58,0xa, 0x12,0x8f,0x58,0x7c,0xb8,0x7c,0x7f, +0x12,0x8f,0xac,0xb, 0xe0,0x7e,0x73,0x36,0xe4,0xbc,0x7e,0x38,0xc3,0xb, 0x90,0x7e, +0x73,0x28,0x84,0xbc,0x79,0x38,0xa7,0x7e,0x73,0x36,0x69,0x7a,0x73,0x36,0xe4,0xa, +0x37,0x3e,0x34,0xca,0x39,0x7e,0x18,0x36,0xa6,0x7e,0x8, 0x36,0x6a,0x12,0x20,0xc3, +0x1b,0xfd,0xe4,0x7a,0xb3,0x36,0xe2,0xda,0x3b,0x22,0x9d,0x32,0x12,0x21,0xa, 0x4d, +0x33,0x22,0x74,0x2, 0xac,0xb9,0x9, 0x85,0x26,0xfa,0x22,0xca,0x3b,0x7e,0xb3,0x2a, +0x6f,0xf5,0x26,0x7e,0xa3,0x2a,0x70,0x7e,0xb3,0x28,0x84,0xf5,0x24,0x70,0x2, 0xe1, +0x4c,0x7e,0x8, 0x1f,0x34,0x7e,0x34,0x3, 0xd4,0xe4,0x12,0x20,0xe8,0x7e,0x8, 0x23, +0x8, 0x7e,0x34,0x0, 0x23,0x12,0x20,0xe8,0x6c,0x99,0x80,0x5a,0x12,0x8f,0xde,0x9, +0xe3,0x26,0xfb,0x1a,0x68,0x1b,0x65,0x80,0x41,0xbe,0xd0,0x0, 0x48,0x3a,0xe5,0x26, +0xbc,0xbd,0x8, 0x34,0x74,0x1, 0x1a,0xcd,0x19,0xbc,0x23,0x8, 0x1a,0xce,0x1b,0xc5, +0x7d,0x3c,0x7c,0xf7,0x80,0x18,0xbe,0xf0,0x0, 0x48,0x11,0xbc,0xaf,0x8, 0xd, 0x74, +0x1, 0x12,0x8f,0x4f,0x1a,0xcf,0x2d,0xc3,0x19,0xbc,0x1f,0x34,0xb, 0xf0,0x1a,0x3e, +0xb, 0x35,0x1a,0xcf,0xbd,0xc3,0x8, 0xde,0xb, 0xd0,0x1a,0x38,0xb, 0x35,0x1a,0xcd, +0xbd,0xc3,0x8, 0xb5,0xb, 0x90,0xe5,0x24,0xbc,0xb9,0x38,0xa0,0x6c,0xdd,0x80,0x71, +0x1a,0xcd,0x9, 0xbc,0x23,0x8, 0x60,0x67,0x6d,0xdd,0x75,0x25,0x0, 0x7e,0xb3,0x2a, +0x6e,0xa, 0x2b,0x1a,0x3d,0xad,0x32,0x7d,0xc3,0x3e,0xc4,0x7e,0x7f,0x13,0x8a,0x6c, +0x99,0x80,0x16,0x12,0x8f,0x4f,0xa, 0xc9,0x2d,0xc3,0x9, 0xbc,0x1f,0x34,0x70,0x7, +0x7c,0xbd,0x12,0x8f,0x67,0x5, 0x25,0xb, 0x90,0xbc,0xa9,0x38,0xe6,0xe5,0x25,0x60, +0x2e,0xe5,0x25,0x1a,0x2b,0x12,0x8f,0x5f,0x6c,0xff,0x80,0x1f,0x12,0x8f,0x4f,0x1a, +0xcf,0x2d,0xc3,0x9, 0xbc,0x1f,0x34,0xb4,0x1, 0xf, 0x7c,0xbd,0x7c,0x7f,0x12,0x6f, +0x81,0xb, 0x1a,0xc0,0x9d,0xcd,0x1b,0x1a,0xc0,0xb, 0xf0,0xbc,0xaf,0x18,0xdd,0xb, +0xd0,0xe5,0x26,0xbc,0xbd,0x18,0x89,0x6c,0x99,0xe1,0x44,0x12,0x8d,0x92,0x9, 0xe5, +0x26,0xfb,0x7c,0xb8,0x7c,0x7e,0x12,0x6f,0x81,0x7f,0x71,0x4c,0x88,0x78,0xc, 0x12, +0x8f,0x78,0x2d,0x35,0x12,0x8f,0x6f,0x8, 0x62,0x80,0x51,0xe5,0x26,0x14,0xbc,0xb8, +0x78,0xc, 0x12,0x8f,0x78,0x9d,0x35,0x12,0x8f,0x6f,0x8, 0x4f,0x80,0x31,0xe5,0x26, +0xa, 0xcb,0x1b,0xc4,0x1a,0x58,0xbd,0x5c,0x58,0x41,0x7e,0xa3,0x2a,0x6e,0x7e,0x30, +0x2, 0xac,0x3a,0x7f,0x17,0x9d,0x31,0xb, 0x1a,0x30,0x74,0x2, 0xa4,0x7f,0x7, 0x2d, +0x15,0xb, 0xa, 0xc0,0xbd,0x3c,0x8, 0xd, 0xb, 0x7a,0x50,0xbd,0x35,0x8, 0x1c,0x1a, +0x58,0x1b,0x54,0x80,0xb, 0xb, 0x7a,0x50,0xbd,0xc5,0x8, 0xf, 0x1a,0x58,0xb, 0x54, +0x7c,0xab,0x7e,0x70,0x2, 0xac,0x79,0x19,0xa3,0x26,0xfa,0x12,0x8d,0x92,0x7c,0xb8, +0x7c,0x7e,0x12,0x6d,0xcb,0x7d,0xc3,0x7e,0x57,0x2a,0x5a,0xbd,0x5c,0x8, 0x3, 0x12, +0x8f,0x58,0xb, 0x90,0xe5,0x24,0xbc,0xb9,0x28,0x2, 0xc1,0xab,0xda,0x3b,0x22,0x1a, +0x2d,0x7e,0x34,0x0, 0x1c,0xad,0x32,0x22,0x7c,0xb9,0x6c,0x77,0x2, 0x73,0x2e,0x7d, +0x3d,0x12,0x1e,0xb9,0x7d,0xd3,0x22,0x7c,0x79,0x12,0x6d,0xcb,0x2d,0xd3,0x22,0xb, +0x1a,0xc0,0xb, 0x7a,0x50,0xbd,0xc5,0x22,0x7e,0xa3,0x2a,0x6e,0x74,0x2, 0xa4,0x7f, +0x17,0x22,0x7c,0x4b,0x74,0x2, 0xac,0xb4,0x9, 0x55,0x26,0xfa,0x9, 0x65,0x26,0xfb, +0x7e,0x73,0x28,0x8c,0xbc,0x75,0x78,0xa, 0x7e,0x73,0x28,0x8d,0xbc,0x76,0x78,0x2, +0xd3,0x22,0xc3,0x22,0x9, 0xb3,0x26,0xfa,0x9, 0x73,0x26,0xfb,0x7c,0x6b,0x7e,0xa3, +0x36,0x69,0x7e,0x50,0x2, 0xac,0x5a,0x19,0x62,0x36,0xa6,0x19,0x72,0x36,0xa7,0x7c, +0xba,0x4, 0x7a,0xb3,0x36,0x69,0x22,0x7e,0x34,0x0, 0x3, 0x2, 0x20,0xe8,0xa9,0xd1, +0xcb,0x74,0x1, 0x2, 0x0, 0xe, 0x7e,0x73,0x28,0x84,0xbe,0x71,0x24,0x22,0x7e,0x70, +0x2, 0xac,0x79,0x9, 0x83,0x26,0xfa,0x22,0x9, 0xb3,0x26,0xfa,0xf5,0x25,0x9, 0xb3, +0x26,0xfb,0xf5,0x26,0x22,0x12,0x90,0xd, 0x50,0x12,0x7e,0x37,0x2b,0x7, 0xbe,0x34, +0x1, 0x2c,0x28,0x8, 0x7e,0x34,0x1, 0x2c,0x7a,0x37,0x2b,0x7, 0x22,0xc2,0x0, 0x12, +0x90,0x35,0x68,0x7, 0x7e,0xb3,0x2a,0x68,0xb4,0x1, 0x17,0x7e,0xb3,0x37,0x71,0x70, +0x11,0x12,0x44,0xc4,0x40,0xa, 0x7e,0x37,0x28,0x8a,0xbe,0x34,0x1, 0x90,0x58,0x2, +0xd2,0x0, 0xa2,0x0, 0x22,0x7e,0xb3,0x2a,0x6b,0xbe,0xb0,0x1, 0x22,0x7e,0xb3,0x39, +0x87,0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x7a,0xb3,0x39,0x87,0x22,0x7f,0x20,0xc2, +0x1, 0x7e,0x2b,0x60,0x29,0x72,0x0, 0x2, 0x9c,0x76,0x1a,0x37,0x12,0x21,0xa, 0x7c, +0x27,0x29,0x72,0x0, 0x1, 0x29,0x32,0x0, 0x3, 0x9c,0x37,0x1a,0x33,0x12,0x21,0xa, +0x7c,0x37,0x1a,0x23,0x1a,0x32,0x9d,0x32,0x12,0x21,0xa, 0x7c,0x67,0x7c,0x72,0xbc, +0x32,0x58,0x2, 0x7c,0x73,0xbe,0x60,0x5, 0x18,0x5, 0xbe,0x70,0x6, 0x58,0x8, 0x7e, +0x37,0x38,0xf4,0x4d,0x33,0x68,0x2, 0xd2,0x1, 0xa2,0x1, 0x22,0xca,0x3b,0x7c,0xc7, +0x7c,0xfb,0x7f,0x40,0x6d,0xbb,0x7e,0xa3,0x2a,0x6d,0x7e,0x73,0x2a,0x6e,0x4c,0xcc, +0x78,0x5, 0x7e,0xc0,0x1, 0x80,0xd, 0x7c,0xb7,0x14,0xbc,0xbc,0x78,0x6, 0xa, 0x6c, +0x1b,0x65,0x7c,0xcd,0x4c,0xff,0x78,0x5, 0x7e,0xf0,0x1, 0x80,0xb, 0x7c,0xba,0x14, +0xbc,0xbf,0x78,0x4, 0xa, 0x7f,0x1b,0x75,0x7f,0x4, 0x7e,0x34,0x0, 0x6, 0xe4,0x12, +0x20,0xe8,0x7e,0x73,0x2a,0x6d,0xa, 0x37,0x1b,0x34,0x7a,0x4b,0x70,0x7e,0x73,0x2a, +0x6e,0xa, 0x37,0x1b,0x34,0x39,0x74,0x0, 0x1, 0x7c,0xec,0x80,0x1d,0x75,0x24,0x0, +0x7c,0xdf,0x80,0xb, 0x12,0x6d,0xd2,0x70,0xb, 0x5, 0x24,0xb, 0xb4,0x1b,0xd0,0xbe, +0xd0,0x0, 0x58,0xf0,0xe5,0x24,0x60,0x7, 0x1b,0xe0,0xbe,0xe0,0x0, 0x58,0xde,0x7c, +0xec,0x80,0x26,0x75,0x24,0x0, 0x1a,0xaf,0xb, 0xa4,0x7d,0x3a,0x7c,0xd7,0x80,0xb, +0x12,0x6d,0xd2,0x70,0xe, 0x5, 0x24,0xb, 0xb4,0xb, 0xd0,0x7e,0x73,0x2a,0x6d,0xbc, +0x7d,0x18,0xed,0xe5,0x24,0x60,0x7, 0x1b,0xe0,0xbe,0xe0,0x0, 0x58,0xd5,0x12,0x91, +0xb2,0x80,0x1d,0x75,0x24,0x0, 0x7c,0xdf,0x80,0xb, 0x12,0x6d,0xd2,0x70,0xb, 0x5, +0x24,0xb, 0xb4,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0xf0,0xe5,0x24,0x60,0xa, 0xb, 0xe0, +0x7e,0x73,0x2a,0x6e,0xbc,0x7e,0x18,0xdb,0x12,0x91,0xb2,0x80,0x22,0x75,0x24,0x0, +0x1a,0x6f,0xb, 0x64,0x80,0xb, 0x12,0x6d,0xd2,0x70,0xe, 0x5, 0x24,0xb, 0xb4,0xb, +0xd0,0x7e,0x73,0x2a,0x6d,0xbc,0x7d,0x18,0xed,0xe5,0x24,0x60,0xa, 0xb, 0xe0,0x7e, +0x73,0x2a,0x6e,0xbc,0x7e,0x18,0xd6,0x7d,0x3b,0x39,0x74,0x0, 0x5, 0x7d,0x3b,0xda, +0x3b,0x22,0x1a,0xac,0xb, 0xa4,0x7d,0x3a,0x7c,0xe7,0x22,0x7f,0x60,0x7e,0x6b,0xa0, +0xbe,0xa0,0xa, 0x50,0x1b,0x7e,0x14,0x0, 0x6, 0xca,0x19,0x74,0x6, 0xa4,0x7f,0x6, +0x2d,0x15,0xb, 0x14,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x6b,0xb0,0x4, 0x7a,0x6b,0xb0, +0x22,0xe4,0x7e,0x63,0x2a,0x6e,0x7e,0x73,0x2a,0x6d,0xac,0x76,0x7d,0x13,0x1e,0x14, +0x7e,0x27,0x28,0x88,0x2e,0x27,0x28,0x86,0xbd,0x21,0x38,0xa, 0x1e,0x34,0x1e,0x34, +0xbe,0x37,0x28,0x86,0x50,0x14,0x7e,0xa3,0x26,0xf7,0xbe,0xa0,0xc, 0x28,0xb, 0x7e, +0xa3,0x26,0xf6,0xbe,0xa0,0x7, 0x28,0x2, 0x74,0x1, 0x22,0x7e,0xa3,0x2a,0x3, 0xbe, +0xa0,0x0, 0x38,0x2f,0xbe,0xa3,0x2a,0x2, 0x50,0x19,0x7e,0xb3,0x2a,0xc, 0xbe,0xb3, +0x35,0x56,0x28,0x14,0x7e,0xb3,0x35,0x56,0x4, 0x7a,0xb3,0x35,0x56,0x7a,0xa3,0x2a, +0x2, 0x80,0x5, 0xe4,0x7a,0xb3,0x35,0x56,0x7e,0xb3,0x2a,0x2, 0x70,0x5, 0xe4,0x7a, +0xb3,0x2a,0xb, 0x22,0x12,0x92,0x5a,0x2, 0x92,0x1b,0x7e,0xb3,0x2a,0x2, 0x70,0x29, +0x12,0x92,0x93,0x28,0x24,0x7e,0xb3,0x34,0xdb,0x70,0x18,0x12,0x92,0x9b,0x7e,0x73, +0x2a,0x3, 0x7a,0x73,0x2a,0x2, 0x74,0x1, 0x7a,0xb3,0x2a,0x9, 0x7e,0xb3,0x34,0xdb, +0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x34,0xdb,0x22,0xe4,0x7a,0xb3,0x34,0xdb,0x7a,0xb3, +0x2a,0x9, 0x22,0x7e,0x73,0x2a,0x3, 0xbe,0x70,0x0, 0x22,0x7e,0x34,0x0, 0x3c,0xca, +0x39,0x7e,0x18,0x36,0xe9,0x7e,0x8, 0x37,0x25,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x73, +0x28,0x94,0x7a,0x73,0x36,0xe8,0x7a,0x73,0x28,0x93,0x22,0x12,0x92,0x93,0x28,0x8, +0x7e,0xb3,0x28,0x84,0x70,0x2, 0xf5,0x1b,0x7e,0xb3,0x28,0x84,0x70,0x18,0xe5,0x1b, +0xbe,0xb0,0xfa,0x50,0x2, 0x5, 0x1b,0xe5,0x1b,0xbe,0xb0,0x5, 0x40,0x8, 0xe4,0x7a, +0xb3,0x32,0x2c,0x75,0x1b,0xfa,0x22,0xca,0x79,0xc2,0x0, 0x7e,0xf0,0x3, 0x12,0x92, +0xbb,0x7e,0xe3,0x2a,0x3, 0x7e,0x34,0x1f,0x34,0x7a,0x37,0x31,0xee,0x12,0x97,0xcc, +0x38,0x2, 0x61,0xc0,0x12,0x93,0xf5,0x92,0xd, 0x12,0x93,0xc9,0x7c,0xbf,0x12,0xae, +0x2d,0x4c,0xee,0x68,0xe, 0x7e,0xa3,0x31,0xcb,0x4c,0xaa,0x78,0xa, 0x7e,0xb3,0x31, +0xcc,0x70,0x4, 0xd2,0x0, 0x80,0x25,0xbe,0xe0,0x1, 0x28,0xb, 0xe5,0x1c,0xbe,0xb0, +0x8, 0x28,0x4, 0xd2,0x0, 0x80,0x15,0xd2,0x0, 0x7e,0xb3,0x28,0x84,0xbc,0xbe,0x78, +0xb, 0x20,0xd, 0x8, 0x4c,0xaa,0x78,0x4, 0x6c,0xff,0xc2,0x0, 0x20,0x0, 0x5, 0x7c, +0xbf,0x12,0xae,0x2d,0x7e,0x8, 0x31,0xd0,0x12,0xb4,0x20,0x7a,0xb3,0x31,0xcf,0xbe, +0xb3,0x28,0x84,0x50,0x3a,0x7e,0x33,0x31,0xcf,0x80,0x26,0x7e,0x70,0x2, 0xac,0x73, +0x9, 0x23,0x31,0xf0,0x9, 0x13,0x31,0xf1,0x2e,0x37,0x31,0xee,0xb, 0x38,0x50,0x7e, +0x93,0x2a,0x6e,0xac,0x92,0xa, 0x31,0x2d,0x43,0x12,0xc6,0x79,0x7c,0xb3,0x12,0x76, +0xfb,0x7c,0x3, 0x1b,0x30,0xa5,0xb8,0x0, 0xd2,0x74,0x1, 0x7a,0xb3,0x31,0xcd,0x7e, +0xa3,0x31,0xcf,0x7a,0xa3,0x28,0x84,0x74,0x2, 0xa4,0xca,0x59,0x7e,0x18,0x31,0xf0, +0x7e,0x8, 0x26,0xfa,0x12,0x20,0xc3,0x1b,0xfd,0x12,0x46,0xb9,0xf5,0x1c,0x80,0x6, +0x75,0x1c,0x64,0x12,0x97,0xde,0xda,0x79,0x22,0x6c,0xaa,0x12,0x97,0xea,0x12,0x93, +0xeb,0x54,0xfe,0x12,0x93,0xe8,0x54,0x7, 0x12,0x93,0xe8,0x54,0xfb,0x7a,0xb, 0xb0, +0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xe4,0x22,0x7a,0xb, 0xb0,0x7f,0x1, 0x2e,0x14,0x0, +0x5, 0x7e,0xb, 0xb0,0x22,0xca,0x3b,0x7e,0xe3,0x28,0x84,0x6c,0xdd,0x6c,0xff,0x74, +0x6, 0xac,0xbd,0x12,0x97,0x6e,0x30,0xe0,0x37,0x6c,0xcc,0x80,0x27,0x12,0x97,0xd4, +0x7a,0xb3,0x1f,0x70,0x9, 0xa3,0x26,0xfb,0x7a,0xa3,0x1f,0x71,0x7f,0x7, 0x12,0x94, +0x4b,0x50,0xf, 0x7f,0x7, 0x7e,0xb3,0x1f,0x71,0x6c,0x77,0x12,0x94,0x4e,0x50,0x2, +0xb, 0xf0,0xb, 0xc0,0xbc,0xec,0x38,0xd5,0xbe,0xf0,0x2, 0x40,0x3, 0xd3,0x80,0x8, +0xb, 0xd0,0xbe,0xd0,0x1e,0x40,0xb6,0xc3,0xda,0x3b,0x22,0x7e,0x70,0x1, 0x7c,0x87, +0x7c,0x9b,0x29,0xa0,0x0, 0x3, 0x29,0x60,0x0, 0x1, 0x7e,0x70,0x1, 0xbe,0x80,0x1, +0x78,0x7, 0x29,0xa0,0x0, 0x2, 0x7e,0xb, 0x60,0xa, 0x7, 0xa, 0x29,0x2d,0x2, 0xa, +0x16,0xbd,0x1, 0x48,0xc, 0xa, 0x17,0xa, 0x3a,0x2d,0x31,0xbd,0x23,0x18,0x2, 0xd3, +0x22,0xc3,0x22,0xca,0x3b,0x7c,0xf5,0x7c,0xe6,0x7c,0xd7,0x7c,0xcb,0x75,0x54,0x0, +0x7e,0xa1,0x54,0x74,0x6, 0xa4,0x12,0x97,0x6e,0x30,0xe1,0x2e,0x7f,0x7, 0x7c,0xbc, +0x12,0x96,0xab,0x50,0x25,0x7f,0x7, 0x7c,0xbe,0x12,0x94,0x4b,0x50,0x1c,0x7f,0x7, +0x7c,0xbd,0x6c,0x77,0x12,0x94,0x4e,0x50,0x11,0x7f,0x7, 0x7c,0xbf,0x6c,0x77,0x12, +0x94,0x4e,0x50,0x6, 0x29,0xb7,0x0, 0x4, 0x80,0xa, 0x5, 0x54,0xe5,0x54,0xbe,0xb0, +0x1e,0x40,0xbd,0xe4,0xda,0x3b,0x22,0xca,0x79,0x7f,0x70,0x7e,0xb4,0xff,0xff,0x6c, +0xee,0xc2,0x1, 0xc2,0x2, 0x29,0x67,0x0, 0x2, 0x7e,0x7b,0x70,0xbc,0x76,0x78,0xe, +0x29,0x67,0x0, 0x3, 0x29,0x77,0x0, 0x1, 0xbc,0x76,0x78,0x2, 0xd2,0x2, 0x6c,0xff, +0x12,0x96,0xbb,0x6d,0xaa,0x29,0xb6,0x0, 0x5, 0x20,0xe1,0x2, 0xa1,0x91,0x7f,0x6, +0x7e,0x7b,0xb0,0x12,0x96,0xab,0x50,0x2d,0x7f,0x6, 0x29,0xb7,0x0, 0x2, 0x12,0x96, +0xab,0x50,0x22,0x7f,0x6, 0x29,0xb7,0x0, 0x1, 0x6c,0x77,0x12,0x94,0x4e,0x50,0x15, +0x7f,0x6, 0x29,0xb7,0x0, 0x3, 0x6c,0x77,0x12,0x94,0x4e,0x50,0x8, 0x7c,0xef,0xd2, +0x1, 0x6d,0xbb,0x80,0x55,0x7e,0x6b,0x70,0xa, 0x27,0x7e,0x7b,0x70,0x12,0x96,0xa4, +0x2d,0xa3,0x29,0x76,0x0, 0x2, 0xa, 0x27,0x29,0x77,0x0, 0x2, 0x12,0x96,0xa4,0x2d, +0xa3,0x29,0x76,0x0, 0x1, 0xa, 0x27,0x29,0x77,0x0, 0x1, 0x12,0x96,0xa4,0x2d,0xa3, +0x29,0x76,0x0, 0x3, 0xa, 0x27,0x29,0x77,0x0, 0x3, 0x12,0x96,0xa4,0x2d,0xa3,0xbd, +0xab,0x50,0x4, 0x7d,0xba,0x7c,0xef,0xbe,0xa4,0x0, 0x4, 0x38,0x4, 0xd2,0x1, 0x80, +0x9, 0xb, 0xf0,0xbe,0xf0,0x1e,0x50,0x2, 0xa1,0x0, 0x20,0x1, 0xb, 0x20,0x2, 0x8, +0xbe,0xb4,0x0, 0x8, 0x50,0x2, 0xd2,0x1, 0x20,0x1, 0x2, 0xc1,0x52,0x74,0x6, 0xac, +0xbe,0x12,0x96,0xbf,0x29,0x76,0x0, 0x5, 0x7c,0xb7,0xc4,0x23,0x54,0x1f,0xbe,0xb0, +0x1f,0x50,0x16,0x7f,0x6, 0x2e,0x14,0x0, 0x5, 0x7c,0x67,0x2e,0x60,0x8, 0x5e,0x60, +0xf8,0x5e,0x70,0x7, 0x4c,0x76,0x7a,0xb, 0x70,0x20,0x2, 0x11,0x29,0xb6,0x0, 0x4, +0xbe,0xb0,0xfa,0x50,0x8, 0x7f,0x16,0xb, 0x36,0x4, 0x7a,0x1b,0xb0,0x29,0x67,0x0, +0x3, 0x29,0x76,0x0, 0x3, 0xbc,0x76,0x28,0x6, 0x29,0x76,0x0, 0x3, 0x80,0x4, 0x29, +0x77,0x0, 0x3, 0x39,0x76,0x0, 0x3, 0x29,0x67,0x0, 0x2, 0x29,0x76,0x0, 0x2, 0xbc, +0x76,0x28,0x6, 0x29,0x76,0x0, 0x2, 0x80,0x4, 0x29,0x77,0x0, 0x2, 0x39,0x76,0x0, +0x2, 0x29,0x67,0x0, 0x1, 0x29,0x76,0x0, 0x1, 0xbc,0x76,0x50,0x6, 0x29,0x76,0x0, +0x1, 0x80,0x4, 0x29,0x77,0x0, 0x1, 0x39,0x76,0x0, 0x1, 0x7e,0x7b,0x60,0x7e,0x6b, +0x70,0xbc,0x76,0x50,0x5, 0x7e,0x6b,0x70,0x80,0x3, 0x7e,0x7b,0x70,0x7a,0x6b,0x70, +0x80,0x31,0x6c,0xff,0x74,0x6, 0xac,0xbf,0x9, 0xb5,0x32,0x32,0x30,0xe1,0x7, 0xb, +0xf0,0xbe,0xf0,0x1e,0x40,0xee,0xbe,0xf0,0x1e,0x50,0x33,0x74,0x1, 0x39,0xb7,0x0, +0x4, 0x12,0x96,0xbb,0x7e,0x34,0x0, 0x6, 0xca,0x39,0x7f,0x17,0x7f,0x6, 0x12,0x20, +0xc3,0x1b,0xfd,0x12,0x96,0xb1,0x44,0x1, 0x7a,0x1b,0xb0,0x12,0x96,0xb1,0x44,0x2, +0x7a,0x1b,0xb0,0x30,0x2, 0x8, 0x12,0x96,0xb1,0x44,0x4, 0x7a,0x1b,0xb0,0xda,0x79, +0x22,0x7e,0x39,0x70,0xa, 0x37,0x9d,0x32,0x2, 0x21,0xa, 0x7e,0x70,0x1, 0x2, 0x94, +0x4e,0x7f,0x16,0x2e,0x34,0x0, 0x5, 0x7e,0x1b,0xb0,0x22,0x74,0x6, 0xac,0xbf,0x7d, +0xd5,0x2e,0xd4,0x32,0x2d,0x6d,0xcc,0x22,0xca,0xf8,0x7e,0xd4,0x0, 0x7, 0x7e,0xb3, +0x28,0x84,0x70,0x8, 0xf5,0x5a,0xc2,0xa, 0xc2,0xb, 0x80,0x7d,0xbe,0xb0,0x2, 0x38, +0x72,0xb4,0x2, 0x28,0x7e,0x73,0x26,0xfc,0xa, 0x27,0x7e,0x73,0x26,0xfa,0x12,0x96, +0xa4,0xbe,0x34,0x0, 0x5, 0x58,0x15,0x7e,0x73,0x26,0xfd,0xa, 0x27,0x7e,0x73,0x26, +0xfb,0x12,0x96,0xa4,0xbe,0x34,0x0, 0x5, 0x58,0x2, 0x80,0x5a,0x6c,0xff,0x80,0x3c, +0x7c,0xbf,0x12,0x97,0x7b,0x1a,0x4b,0x7c,0xbf,0x12,0x6f,0x6b,0x7d,0xc3,0xbe,0xc4, +0x2, 0x58,0x58,0x4, 0x7e,0xd4,0x0, 0x6, 0x7d,0x5d,0x3e,0x54,0xbd,0x54,0x58,0x4, +0xd2,0xb, 0x80,0xa, 0x7d,0x5d,0xe, 0x54,0xbd,0x54,0x48,0x2, 0xc2,0xb, 0x20,0xb, +0x4, 0xbd,0xd4,0x58,0x5, 0x75,0x5a,0x28,0x80,0xf, 0xb, 0xf0,0x12,0x73,0x6d,0x38, +0xbf,0x80,0x6, 0xe5,0x5a,0x24,0xfb,0xf5,0x5a,0xe5,0x5a,0xbe,0xb0,0x0, 0x8, 0x6, +0xd2,0xa, 0x15,0x5a,0x80,0x5, 0x75,0x5a,0x0, 0xc2,0xa, 0xda,0xf8,0x22,0x7d,0xf5, +0x2e,0xf4,0x32,0x2d,0x6d,0xee,0x29,0xb7,0x0, 0x5, 0x22,0xca,0xf8,0x7c,0xfb,0x7e, +0x70,0x2, 0x12,0x99,0xd, 0x7f,0x71,0x7c,0xbf,0x12,0x6f,0x6b,0x12,0x97,0xc5,0x7f, +0x17,0x12,0x1f,0x58,0x7c,0xb7,0xda,0xf8,0x22,0xca,0xd8,0xca,0x79,0x6c,0xff,0x6c, +0xee,0x80,0xf, 0x7c,0xbe,0x12,0x97,0x7b,0x7c,0xdb,0xbc,0xfd,0x58,0x2, 0x7c,0xfd, +0xb, 0xe0,0x12,0x97,0xbe,0x38,0xec,0x7c,0xbf,0xda,0x79,0xda,0xd8,0x22,0x7e,0x73, +0x28,0x84,0xbc,0x7e,0x22,0x7d,0x13,0x1a,0x2, 0x1a,0x0, 0x22,0x7e,0x73,0x28,0x84, +0xbe,0x70,0x1, 0x22,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x26,0xfa,0x22,0x7e,0x8, +0x32,0x2d,0x7e,0x34,0x0, 0xb4,0xe4,0x2, 0x20,0xe8,0x7e,0x70,0x6, 0xac,0x7a,0x2e, +0x34,0x32,0x2d,0x6d,0x22,0x22,0x7e,0xa3,0x2a,0x2, 0x7e,0xb3,0x38,0x32,0x70,0x5, +0x7a,0xb3,0x34,0xc4,0x22,0xe4,0x7a,0xb3,0x34,0x88,0x6c,0x77,0x80,0x78,0x7e,0x90, +0x9, 0xac,0x97,0x9, 0x64,0x29,0xc, 0x7c,0xb6,0x54,0xf, 0xa, 0x2b,0x9, 0x52,0x29, +0xbc,0x4c,0x55,0x68,0xa, 0xa5,0xbd,0x2, 0x5b,0x7e,0xb3,0x34,0xc4,0x70,0x55,0x49, +0x14,0x29,0x8, 0xbe,0x14,0x0, 0x64,0x28,0x10,0xbe,0x14,0x3, 0xd4,0x50,0xa, 0x49, +0x14,0x29,0xa, 0xbe,0x14,0x0, 0x64,0x38,0x3b,0x7e,0xb3,0x34,0x88,0xbc,0xb7,0x40, +0x5, 0x4, 0x7a,0xb3,0x34,0x88,0x7e,0xb3,0x2a,0x2, 0x14,0x7a,0xb3,0x2a,0x2, 0x7e, +0x40,0xff,0x7e,0x30,0x9, 0xac,0x37,0x19,0x41,0x29,0xc, 0x74,0x3, 0xa, 0x46,0x19, +0xb4,0x29,0xbc,0x19,0xb4,0x29,0xc6,0xa5,0xbd,0x2, 0x9, 0x7e,0xb3,0x2a,0x3, 0x14, +0x7a,0xb3,0x2a,0x3, 0xb, 0x70,0xbc,0xa7,0x38,0x84,0x7e,0x73,0x38,0x32,0x7a,0x73, +0x34,0xc4,0x22,0xca,0x79,0x7c,0x8b,0x6c,0xaa,0x9f,0x77,0x12,0x99,0xc8,0x1a,0x79, +0x1b,0x74,0x80,0x41,0x1a,0x38,0x1b,0x34,0x7c,0xe7,0x80,0x2d,0xbc,0x9f,0x78,0x4, +0xbc,0x8e,0x68,0x23,0xbe,0xf0,0x0, 0x48,0x1e,0x7e,0xb3,0x2a,0x6f,0xbc,0xbf,0x8, +0x16,0xbe,0xe0,0x0, 0x48,0x11,0x7e,0xb3,0x2a,0x70,0xbc,0xbe,0x8, 0x9, 0x7c,0xbf, +0x7c,0x7e,0x12,0x99,0x3, 0xb, 0xa0,0xb, 0xe0,0x1a,0x28,0xb, 0x24,0x1a,0x3e,0xbd, +0x32,0x8, 0xc9,0xb, 0xf0,0x1a,0x29,0xb, 0x24,0x1a,0x3f,0xbd,0x32,0x8, 0xb5,0x4c, +0xaa,0x78,0x4, 0x6d,0x33,0x80,0x9, 0xa, 0x1a,0x6d,0x0, 0x7f,0x17,0x12,0x1f,0x58, +0xda,0x79,0x22,0x12,0x6d,0xcb,0x1a,0x26,0x1a,0x24,0x2f,0x71,0x22,0xca,0x79,0x7c, +0xa7,0x7c,0x8b,0x7e,0xb3,0x2a,0x6f,0x7a,0xb3,0x1f,0x9a,0x7e,0xb3,0x2a,0x70,0x7a, +0xb3,0x1f,0x9b,0x12,0x99,0xc8,0x9f,0x77,0x1a,0x3a,0x1a,0x79,0x9d,0x73,0x21,0xb5, +0x7a,0xf1,0x58,0xbe,0xf0,0x0, 0x58,0xe, 0x1a,0x3f,0x1a,0x29,0x9d,0x23,0x1a,0x39, +0x2d,0x32,0x7c,0xb7,0xf5,0x58,0x7e,0xb3,0x1f,0x9a,0xbc,0xbf,0x18,0xe, 0x1a,0x39, +0x1a,0x2f,0x9d,0x23,0x1a,0x39,0x9d,0x32,0x7c,0xb7,0xf5,0x58,0x1a,0x2a,0x1a,0x38, +0x9d,0x32,0x7c,0xb7,0xf5,0x57,0x80,0x3d,0x85,0x57,0x59,0xe5,0x57,0xbe,0xb0,0x0, +0x58,0x10,0xe5,0x57,0x1a,0x3b,0x1a,0x28,0x9d,0x23,0x1a,0x38,0x2d,0x32,0x7c,0xb7, +0xf5,0x59,0x7e,0xb3,0x1f,0x9b,0xbe,0xb1,0x57,0x18,0x10,0x1a,0x38,0xe5,0x57,0x1a, +0x2b,0x9d,0x23,0x1a,0x38,0x9d,0x32,0x7c,0xb7,0xf5,0x59,0xe5,0x58,0x7e,0x71,0x59, +0x12,0x99,0x3, 0x5, 0x57,0x1a,0x3a,0x1a,0x28,0x2d,0x23,0xe5,0x57,0x1a,0x3b,0xbd, +0x32,0x8, 0xb5,0xb, 0xf0,0x1a,0x3a,0x1a,0x29,0x2d,0x23,0x1a,0x3f,0xbd,0x32,0x18, +0x2, 0x21,0x30,0x7f,0x17,0xda,0x79,0x22,0x7e,0x70,0x2, 0xac,0x78,0x9, 0x93,0x26, +0xfa,0x9, 0x83,0x26,0xfb,0x22,0xca,0xd8,0xca,0x79,0x7e,0xf4,0x3, 0x20,0x7d,0x7f, +0x12,0x9a,0xc7,0x50,0x2, 0x41,0x6a,0x7a,0xf5,0x2a,0x7e,0xb3,0x28,0xa8,0xb4,0x1, +0x4, 0x7e,0x74,0x4, 0xb0,0x7e,0x37,0x28,0x8a,0xbe,0x34,0x4, 0x4c,0x8, 0x6b,0x6c, +0xdd,0x80,0x5f,0xc2,0x0, 0x7c,0xbd,0x12,0x6f,0x6b,0x7a,0x35,0x26,0x7c,0xbd,0x7e, +0x70,0x1, 0x12,0x99,0xd, 0x7a,0x35,0x24,0x9e,0x35,0x26,0x7a,0x35,0x24,0x7e,0x35, +0x26,0x3e,0x34,0x3e,0x34,0x12,0x9a,0x6f,0x7a,0x35,0x28,0xbe,0x75,0x28,0x58,0x3, +0x7a,0x75,0x28,0x7e,0x35,0x28,0xbe,0x35,0x24,0x8, 0xa, 0x7e,0x35,0x2a,0xbe,0x35, +0x26,0x8, 0x2, 0xd2,0x0, 0x7c,0xbd,0x12,0x8f,0x82,0x50,0x2, 0xc2,0x0, 0x30,0x0, +0xf, 0x7c,0xbd,0x6c,0x77,0x12,0x73,0x2e,0x7e,0x70,0x2, 0xac,0x7d,0x12,0x8f,0xa4, +0xb, 0xd0,0x7e,0x73,0x28,0x84,0xbc,0x7d,0x38,0x99,0xda,0x79,0xda,0xd8,0x22,0x7e, +0x24,0x0, 0x2, 0x2, 0x1e,0xb9,0x7e,0xa0,0x1, 0x7e,0x37,0x2a,0x4f,0x12,0x9a,0xbf, +0x28,0x35,0x6d,0x22,0x9d,0x23,0xbe,0x27,0x7, 0xf8,0x58,0x2b,0x12,0x9a,0x6f,0xbe, +0x37,0x7, 0xfa,0x8, 0x22,0xe4,0x7a,0xb3,0x28,0x84,0x7e,0xb3,0x2a,0x3, 0x70,0x17, +0x7e,0xb3,0x38,0x9, 0xb4,0x1, 0x10,0x6c,0xaa,0x5, 0x5b,0xe5,0x5b,0xbe,0xb0,0x10, +0x28,0x5, 0xd2,0x15,0x75,0x5b,0x0, 0x4c,0xaa,0x68,0x3, 0x75,0x5b,0x0, 0x22,0x7e, +0xb3,0x28,0x84,0xbe,0xb0,0x0, 0x22,0x6c,0x99,0x6c,0x88,0x80,0xf, 0x7c,0xb8,0x12, +0x6f,0x6b,0xbe,0x34,0x1, 0xf4,0x8, 0x2, 0xb, 0x90,0xb, 0x80,0x7e,0x73,0x28,0x84, +0xbc,0x78,0x38,0xe9,0xbe,0x90,0x1, 0x38,0x2, 0xc3,0x22,0xd3,0x22,0xca,0x3b,0x7e, +0x77,0x2a,0x5c,0x12,0x9b,0x83,0x7d,0x63,0x3e,0x34,0x3e,0x34,0x7e,0xe4,0x0, 0xa, +0x12,0x9b,0x7b,0x7e,0xb3,0x28,0xa8,0x60,0xf, 0x7e,0x37,0x36,0xe5,0xbd,0x36,0x48, +0x7, 0x3e,0x34,0x3e,0x34,0x12,0x9b,0x7b,0xbe,0x64,0x4, 0x4c,0x8, 0xf, 0x12,0x9a, +0xc7,0x50,0x6, 0x7e,0xb3,0x28,0xa8,0x60,0x4, 0x74,0xa, 0x80,0x13,0x7e,0xb3,0x28, +0xa8,0x60,0xc, 0x7e,0xb3,0x36,0xe3,0xbe,0xb0,0x0, 0x28,0x8, 0x14,0x80,0x1, 0xe4, +0x7a,0xb3,0x36,0xe3,0x7e,0xe7,0x2a,0x5c,0x7d,0x3e,0x12,0x46,0xab,0x7e,0x53,0x36, +0xe3,0xbe,0x50,0x0, 0x28,0x12,0xbd,0x3f,0x58,0x4, 0x7d,0xf3,0x80,0x6, 0xbd,0xef, +0x8, 0x2, 0x7d,0xfe,0x7a,0xf7,0x2a,0x5c,0x12,0x97,0xcc,0x28,0x3, 0x12,0x75,0x21, +0x7a,0x67,0x36,0xe5,0x7a,0x77,0x2a,0x5c,0xda,0x3b,0x22,0x7d,0x2e,0x12,0x1e,0xb9, +0x7d,0xf3,0x22,0xca,0x3b,0x6d,0x44,0x7e,0xf3,0x28,0x84,0x6c,0xee,0x80,0x24,0x7c, +0xbe,0x12,0x88,0x65,0x60,0x1b,0x74,0x2, 0xac,0xbe,0x9, 0xd5,0x26,0xfa,0x9, 0xc5, +0x26,0xfb,0x7c,0xbd,0x7c,0x7c,0x12,0x6d,0xcb,0x7d,0xf3,0xbd,0x4f,0x58,0x2, 0x7d, +0x4f,0xb, 0xe0,0xbc,0xfe,0x38,0xd8,0x7d,0x34,0xda,0x3b,0x22,0xca,0x79,0x6c,0xff, +0x9f,0x77,0x7f,0x67,0x6d,0xbb,0x7e,0xa3,0x2a,0x70,0x7e,0xe3,0x2a,0x6f,0x7e,0xa7, +0x28,0x97,0x7e,0x8, 0x1f,0x34,0x7e,0x34,0x0, 0x1c,0xe4,0x12,0x20,0xe8,0x7e,0x8, +0x1f,0x50,0x7e,0x34,0x0, 0x1c,0x12,0x20,0xe8,0x6c,0x99,0x80,0x41,0x7e,0x50,0x2, +0xac,0x59,0x49,0x32,0x5, 0x7a,0xbe,0x34,0x0, 0xfa,0x8, 0x12,0x49,0x12,0x4, 0xfc, +0xbd,0x1a,0x58,0xa, 0x74,0x1, 0xa, 0x19,0x19,0xb1,0x1f,0x34,0x80,0x1e,0xbe,0x34, +0x0, 0xfa,0x8, 0x18,0x49,0x32,0x4, 0xfc,0xbe,0x34,0x0, 0xfa,0x8, 0xe, 0xbd,0x3b, +0x8, 0x2, 0x7d,0xb3,0x74,0x1, 0xa, 0x39,0x19,0xb3,0x1f,0x50,0xb, 0x90,0xbc,0xa9, +0x38,0xbb,0x6c,0x99,0x80,0x27,0xa, 0xa9,0x9, 0xba,0x1f,0x34,0xb4,0x1, 0x1c,0x6c, +0x88,0x80,0x14,0x7c,0xb8,0x7c,0x79,0x12,0x6d,0xcb,0x12,0x21,0xa, 0xbe,0x34,0x0, +0xfa,0x8, 0x2, 0xb, 0xf0,0xb, 0x80,0xbc,0xe8,0x38,0xe8,0xb, 0x90,0xbc,0xa9,0x38, +0xd5,0xbe,0xf0,0x1, 0x28,0x52,0xbe,0xb4,0x3, 0xe8,0x8, 0x4, 0x74,0x1, 0x80,0x49, +0x6c,0x99,0x80,0x21,0xa, 0x39,0x9, 0xb3,0x1f,0x50,0xb4,0x1, 0x16,0x7e,0x70,0x2, +0xac,0x79,0x49,0x13,0x5, 0x7a,0x1a,0x2, 0x1a,0x0, 0x2f,0x60,0x49,0x33,0x4, 0xfc, +0x12,0x99,0x6, 0xb, 0x90,0xbc,0xa9,0x38,0xdb,0x74,0x2, 0x7f,0x16,0x1e,0x34,0xe, +0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7e,0x14,0x0, 0x5, 0x12,0x1e,0xfc, +0xbf,0x71,0x8, 0x4, 0x74,0x1, 0x80,0x1, 0xe4,0xda,0x79,0x22,0xca,0x3b,0x6c,0xaa, +0xc2,0x0, 0x7e,0x97,0x28,0x99,0x7e,0x87,0x28,0x97,0x7e,0xb3,0x28,0xa5,0x14,0x68, +0x19,0x14,0x68,0x1e,0x24,0xc2,0x68,0x8, 0x24,0xfb,0x68,0xe, 0x24,0x45,0x78,0x26, +0x7e,0xe3,0x2a,0x6e,0x7e,0xd3,0x2a,0x6d,0x80,0x20,0x6c,0xee,0x7e,0xd3,0x2a,0x6e, +0x80,0x18,0x6c,0xee,0x7e,0xb3,0x2a,0x6d,0xa, 0x2b,0x7e,0xb3,0x2a,0x6e,0xa, 0x3b, +0x2d,0x32,0x7c,0xd7,0x80,0x4, 0x6c,0xee,0x6c,0xdd,0x6c,0xff,0x80,0xf, 0x12,0x9e, +0x3a,0x6d,0x33,0x9d,0x39,0xbd,0x23,0x58,0x2, 0xb, 0xa0,0xb, 0xf0,0xbc,0xdf,0x38, +0xed,0x4c,0xaa,0x78,0x3c,0x7e,0xb3,0x26,0x85,0x70,0x25,0x7e,0xb3,0x26,0x84,0x70, +0x1f,0x6c,0xff,0x80,0x15,0x12,0x9e,0x3a,0xbd,0x29,0x8, 0xc, 0x49,0x33,0x4, 0xfc, +0xbd,0x38,0x58,0x4, 0xd2,0x0, 0x80,0x19,0xb, 0xf0,0xbc,0xdf,0x38,0xe7,0x80,0x11, +0x12,0x9b,0xbc,0xa, 0x8b,0x4d,0x88,0x68,0x8, 0x12,0x76,0xe0,0x28,0x3, 0x12,0x9e, +0x2d,0x6c,0xcc,0x12,0x76,0xe0,0x38,0x5, 0x12,0x9e,0x47,0x28,0x69,0x7e,0xb3,0x28, +0xa7,0xb4,0x1, 0x9, 0x7e,0xb3,0x28,0xaa,0xbe,0xb0,0x1, 0x68,0x59,0x7e,0xb3,0x28, +0xa8,0xb4,0x1, 0x52,0x6c,0xff,0x80,0x1d,0x7e,0x70,0x2, 0xac,0x7f,0x9, 0xa3,0x26, +0xfa,0x9, 0x93,0x26,0xfb,0x12,0x6d,0xc7,0xbe,0x34,0x0, 0xc8,0x8, 0x5, 0x7e,0xc0, +0x1, 0x80,0xa, 0xb, 0xf0,0x7e,0xb3,0x28,0x84,0xbc,0xbf,0x38,0xdb,0x6c,0xff,0x80, +0x1d,0x7e,0x70,0x2, 0xac,0x7f,0x9, 0xa3,0x27,0x36,0x9, 0x93,0x27,0x37,0x12,0x6d, +0xc7,0xbe,0x34,0xff,0x38,0x58,0x5, 0x7e,0xc0,0x1, 0x80,0xa, 0xb, 0xf0,0x7e,0xb3, +0x28,0x85,0xbc,0xbf,0x38,0xdb,0x4c,0xcc,0x78,0x29,0x6c,0xff,0x80,0x21,0xa, 0x3f, +0xa, 0x2e,0x2d,0x23,0x3e,0x24,0x49,0x32,0x5, 0x7a,0xbd,0x39,0x8, 0xf, 0x49,0x82, +0x4, 0xfc,0x3e,0x84,0xbd,0x38,0x8, 0x5, 0x7e,0xc0,0x1, 0x80,0x6, 0xb, 0xf0,0xbc, +0xdf,0x38,0xdb,0x30,0x0, 0x15,0x7e,0xb3,0x3a,0xc, 0x4, 0x7a,0xb3,0x3a,0xc, 0x7e, +0x73,0x3a,0xc, 0xbe,0x70,0xa, 0x28,0x3, 0x12,0x9e,0x2d,0x4c,0xcc,0x78,0xb, 0x7e, +0xb3,0x28,0xa8,0x60,0x2, 0xd2,0x19,0x12,0x9e,0x4f,0xda,0x3b,0x22,0x74,0xa, 0x7a, +0xb3,0x3a,0xc, 0x74,0x1, 0x7a,0xb3,0x28,0xa8,0x22,0xa, 0x2f,0xa, 0x3e,0x2d,0x32, +0x3e,0x34,0x49,0x23,0x5, 0x7a,0x22,0x7e,0x73,0x28,0x85,0xbe,0x70,0x0, 0x22,0xe4, +0x7a,0xb3,0x28,0xa8,0x7a,0xb3,0x3a,0xc, 0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0x7e, +0xf0,0xa, 0x6c,0x11,0x80,0x21,0x7e,0x0, 0xff,0x74,0x9, 0xac,0xb1,0x19,0x5, 0x1f, +0x38,0x7e,0x34,0x7f,0xff,0x74,0x9, 0xac,0xb1,0x59,0x35,0x1f,0x34,0x74,0x9, 0xac, +0xb1,0x59,0x35,0x1f,0x36,0xb, 0x10,0xbc,0xf1,0x38,0xdb,0xe4,0x6c,0x77,0x7c,0x6d, +0x12,0x9f,0xa2,0x7c,0x7d,0x7c,0x6f,0x12,0x9f,0xa2,0x6c,0x0, 0x80,0x39,0x6c,0xee, +0x80,0x16,0x74,0x9, 0xac,0xbe,0x9, 0x65,0x1f,0x38,0x74,0x9, 0xac,0xb0,0x9, 0x75, +0x28,0xb2,0xbc,0x76,0x68,0x6, 0xb, 0xe0,0xbc,0x1e,0x38,0xe6,0xbc,0x1e,0x78,0x15, +0x7e,0x70,0x9, 0xac,0x70,0x12,0x7f,0xa0,0xac,0x31,0x2e,0x14,0x1f,0x34,0x74,0x9, +0x12,0x1f,0x8c,0xb, 0x10,0xb, 0x0, 0xbc,0xf0,0x38,0xc3,0x74,0x9, 0xac,0xbf,0xca, +0x59,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x29,0x62,0x12,0x20,0xc3,0x1b,0xfd,0xda,0x79, +0xda,0xd8,0x22,0xca,0x3b,0x7c,0x46,0x7c,0xab,0x6c,0x66,0x7c,0x57,0xe1,0x84,0x7e, +0xf0,0x9, 0xac,0xf6,0x9, 0x87,0x29,0x66,0x7c,0x98,0x7e,0xd0,0x9, 0xac,0xd5,0x9, +0xb6,0x28,0xb2,0xbc,0xb9,0x78,0x6b,0xbe,0x90,0xff,0x68,0x66,0x12,0x9f,0x98,0x39, +0x87,0x0, 0x4, 0xa, 0xf9,0x9, 0xbf,0x29,0xbc,0x7e,0xf0,0x9, 0x70,0xc, 0xac,0xf5, +0x7d,0x97,0x2e,0x94,0x28,0xae,0x6d,0x88,0x80,0xa, 0xac,0xf6,0x7d,0x97,0x2e,0x94, +0x29,0x62,0x6d,0x88,0xb, 0x4a,0xd0,0x12,0x9f,0x98,0x1b,0x7a,0xd0,0x69,0xf4,0x0, +0x2, 0x7e,0xf0,0x9, 0xac,0xfa,0x7f,0x60,0x2d,0xd7,0x79,0xf6,0x0, 0x2, 0x7e,0xf0, +0x9, 0xac,0xf5,0x9, 0x87,0x28,0xb3,0x12,0x9f,0x98,0x39,0x87,0x0, 0x5, 0x7e,0xf0, +0x9, 0xac,0xf5,0x9, 0x87,0x28,0xb4,0x12,0x9f,0x98,0x39,0x87,0x0, 0x6, 0xb, 0xa0, +0x80,0x8, 0xb, 0x50,0xbc,0x45,0x28,0x2, 0xc1,0xff,0xb, 0x60,0xbe,0x60,0xa, 0x50, +0x2, 0xc1,0xfb,0x7c,0xba,0xda,0x3b,0x22,0x7e,0xf0,0x9, 0xac,0xfa,0x7f,0x70,0x2d, +0xf7,0x22,0x7e,0x8, 0x1f,0x34,0x12,0x9e,0xf3,0x7c,0x1b,0x22,0x7c,0xab,0x7e,0xb, +0xb0,0x60,0x3, 0xb4,0x2, 0x31,0xa, 0x4a,0x9, 0x74,0x34,0xb8,0xbe,0x73,0x34,0xc2, +0x50,0xe, 0x7d,0x24,0x2e,0x24,0x34,0xb8,0x7c,0xb7,0x4, 0x7a,0x29,0xb0,0xd3,0x22, +0xbe,0x73,0x34,0xc2,0x40,0x9, 0xbe,0x70,0xff,0x68,0x4, 0xe4,0x7a,0xb, 0xb0,0x74, +0xff,0x19,0xb4,0x34,0xb8,0x80,0x17,0xa, 0x3a,0x9, 0xb3,0x34,0xb8,0xbe,0xb0,0xff, +0x68,0x7, 0xe4,0x19,0xb3,0x34,0xb8,0xd3,0x22,0xe4,0x19,0xb3,0x34,0xb8,0xc3,0x22, +0xca,0xf8,0x7c,0xfb,0x7d,0xf3,0x7e,0x17,0x2a,0x62,0xbd,0x13,0x38,0x6, 0x7e,0x34, +0x1, 0x0, 0x80,0x15,0x6d,0x22,0x7c,0x56,0x7c,0x67,0x6c,0x77,0x12,0x1f,0x5, 0xbe, +0x34,0x0, 0x10,0x50,0x4, 0x7e,0x34,0x0, 0x10,0x74,0x2, 0xac,0xbf,0x49,0x25,0x34, +0xc6,0xbd,0x2f,0x28,0x6, 0x49,0x35,0x34,0xa0,0x80,0x4, 0x59,0x35,0x34,0xa0,0x59, +0xf5,0x34,0xc6,0xbe,0x34,0x1, 0x0, 0x28,0x4, 0x7e,0x34,0x1, 0x0, 0xda,0xf8,0x22, +0xca,0x69,0xca,0xf8,0x7e,0xa3,0x2a,0x2, 0x7e,0x8, 0x29,0xbc,0x4c,0xaa,0x78,0x5, +0x12,0x24,0x66,0x21,0x9d,0x6c,0x99,0x7e,0x70,0x9, 0xac,0x79,0x9, 0x83,0x29,0xc, +0xbe,0x80,0xff,0x78,0x2, 0x21,0x94,0xa, 0x28,0x9, 0xb2,0x34,0x8c,0x7a,0xb3,0x34, +0x89,0x9, 0xb2,0x34,0x96,0x7a,0xb3,0x34,0x8a,0x7f,0x60,0x2d,0xd2,0x7e,0x6b,0xf0, +0xbe,0xf0,0x2, 0x68,0x2, 0x21,0x57,0x12,0xa1,0xac,0x49,0x33,0x29,0x8, 0x12,0xa1, +0xb6,0x7e,0x70,0x4, 0xac,0x78,0x49,0x23,0x35,0x59,0x12,0xa1,0xa2,0x9d,0x32,0x12, +0x21,0xa, 0x7d,0xe3,0x7e,0x73,0x34,0x89,0xa, 0x27,0xbd,0x2f,0x28,0x55,0xbd,0x2e, +0x28,0x51,0x12,0xa1,0xac,0x7e,0xd0,0x9, 0xac,0xd9,0x59,0x26,0x29,0x8, 0x7e,0x50, +0x4, 0xac,0x58,0x49,0x22,0x35,0x59,0x7e,0xd0,0x9, 0xac,0xd9,0x59,0x26,0x29,0xa, +0xbe,0xa0,0x0, 0x28,0x2, 0x1b,0xa0,0x4c,0xaa,0x78,0x5c,0x7e,0xb3,0x34,0x8a,0x4, +0x7a,0xb3,0x34,0x8a,0x7e,0x63,0x34,0x8a,0xbe,0x60,0x32,0x40,0x4a,0x74,0x1e,0x7a, +0xb3,0x34,0x8a,0x7e,0xb3,0x34,0x89,0xbe,0xb0,0x6, 0x50,0x3b,0x4, 0x7a,0xb3,0x34, +0x89,0x80,0x34,0x7e,0x50,0x9, 0xac,0x59,0x49,0xb2,0x29,0x8, 0x7e,0xd0,0x4, 0xac, +0xd8,0x59,0xb6,0x35,0x57,0x49,0x22,0x29,0xa, 0x59,0x26,0x35,0x59,0xbe,0x70,0xa, +0x40,0x4, 0x74,0x6, 0x80,0x8, 0xbe,0x70,0x1, 0x28,0x7, 0x7c,0xb7,0x14,0x7a,0xb3, +0x34,0x89,0xe4,0x7a,0xb3,0x34,0x8a,0x7e,0xb3,0x34,0x89,0xa, 0x38,0x19,0xb3,0x34, +0x8c,0x7e,0xb3,0x34,0x8a,0x80,0x37,0x4c,0xff,0x78,0x1b,0x7e,0x70,0x9, 0xac,0x79, +0x49,0x33,0x29,0x8, 0x7e,0x50,0x4, 0xac,0x58,0x59,0x32,0x35,0x57,0x12,0xa1,0xa2, +0x59,0x32,0x35,0x59,0x80,0x1e,0x7e,0x6b,0xb0,0xb4,0x1, 0x18,0x7e,0xb3,0x2a,0x2, +0xbe,0xb0,0x0, 0x28,0xf, 0x74,0xa, 0xa, 0x38,0x19,0xb3,0x34,0x8c,0xe4,0xa, 0x38, +0x19,0xb3,0x34,0x96,0xb, 0x90,0xbe,0x90,0xa, 0x68,0x2, 0x1, 0x67,0xda,0xf8,0xda, +0x69,0x22,0x7e,0x70,0x9, 0xac,0x79,0x49,0x33,0x29,0xa, 0x22,0x7e,0x50,0x4, 0xac, +0x58,0x49,0x22,0x35,0x57,0x22,0x9d,0x32,0x12,0x21,0xa, 0x7d,0xf3,0x22,0xa2,0xa, +0x22,0xca,0x79,0x6c,0x88,0x80,0x6b,0x74,0x2, 0xac,0xb8,0x9, 0xf5,0x26,0xfa,0x9, +0x75,0x26,0xfb,0x7a,0x71,0x24,0x7c,0xbf,0x12,0x67,0xe2,0x50,0x53,0x6c,0xee,0x80, +0x4a,0xbc,0xe8,0x68,0x44,0x7e,0x70,0x2, 0xac,0x7e,0x12,0x8f,0xe8,0x6c,0x99,0x7e, +0xb3,0x2a,0x70,0x14,0xbe,0xb1,0x26,0x78,0x10,0xa, 0x2f,0xe5,0x25,0x12,0x44,0x5b, +0xbe,0x34,0x0, 0x1, 0x18,0x3, 0x7e,0x90,0x1, 0xbe,0x90,0x1, 0x78,0x1b,0x7c,0xbe, +0x12,0x6f,0x6b,0x7d,0xf3,0x7c,0xb8,0x12,0x6f,0x6b,0xbd,0x3f,0x8, 0x4, 0x7c,0xbe, +0x80,0x2, 0x7c,0xb8,0x6c,0x77,0x12,0x73,0x2e,0xb, 0xe0,0x12,0x97,0xbe,0x38,0xb1, +0xb, 0x80,0x7e,0x73,0x28,0x84,0xbc,0x78,0x38,0x8d,0xda,0x79,0x22,0xe4,0x7a,0xb3, +0x36,0x69,0x7e,0xb3,0x28,0x84,0x60,0x6, 0x7e,0xb3,0x36,0xe2,0x60,0x5, 0xe4,0x7a, +0xb3,0x36,0xe4,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x14,0x23,0x1, 0x7e,0x4, +0x0, 0xff,0x69,0x30,0x0, 0x2, 0xb, 0xa, 0x20,0x7a,0x1d,0x2c,0x7e,0x73,0x2a,0x6d, +0xa, 0x37,0x3e,0x34,0xca,0x39,0x7f,0x16,0x7f,0x5, 0x12,0x20,0xc3,0x1b,0xfd,0x6c, +0xdd,0x12,0x87,0xb8,0x7a,0xb3,0x1f,0x34,0x6c,0xcc,0x80,0x4a,0x12,0xa3,0x2f,0x40, +0x43,0x12,0xa3,0x25,0x50,0x3e,0x12,0x87,0xc0,0xb, 0x1a,0x10,0x7d,0x3f,0x12,0x21, +0xa, 0x7d,0x3, 0x7d,0x31,0x12,0x21,0xa, 0xbd,0x30,0x58,0x2, 0x7d,0xf1,0xbe,0x15, +0x2a,0x8, 0x5, 0x7e,0x15,0x2a,0x80,0xb, 0x6d,0x0, 0x9e,0x5, 0x2a,0xbd,0x1, 0x8, +0x2, 0x7d,0x10,0x7d,0x31,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1f,0x34,0x4, +0x7a,0xb3,0x1f,0x34,0xb, 0xc0,0x12,0x57,0x75,0x38,0xb1,0x7e,0x73,0x1f,0x34,0x4c, +0x77,0x68,0x36,0x12,0x87,0xc9,0xbd,0x3e,0x8, 0x2, 0x7d,0x7f,0xbe,0x75,0x2a,0x8, +0x5, 0x7e,0x75,0x2a,0x80,0xb, 0x6d,0xee,0x9e,0xe5,0x2a,0xbd,0xe7,0x8, 0x2, 0x7d, +0x7e,0x6c,0xcc,0x80,0xf, 0x12,0xa3,0x2f,0x40,0x8, 0x12,0xa3,0x25,0x50,0x3, 0x12, +0x87,0xde,0xb, 0xc0,0x12,0x57,0x75,0x38,0xec,0xb, 0xd0,0xbe,0xd0,0x3, 0x50,0x2, +0x41,0x81,0xda,0x3b,0x22,0x7c,0x1d,0x2e,0x10,0x2d,0xa5,0xe7,0xbc,0xab,0x22,0xa, +0xec,0x9, 0xae,0x2a,0xb9,0x7c,0x1d,0x2e,0x10,0x2c,0xa5,0xe7,0xbc,0xab,0x22,0xca, +0x79,0x7e,0xb3,0x3, 0xfd,0x60,0x5f,0x7e,0xb3,0x2a,0x68,0x60,0x59,0x7e,0xf3,0x2a, +0x6f,0x7e,0xe3,0x2a,0x70,0x7e,0x1f,0x13,0x8a,0x7a,0x1d,0x24,0x74,0x2, 0xac,0xbe, +0x2d,0x35,0x1b,0x35,0x6c,0xaa,0x80,0xf, 0xb, 0x1a,0x40,0x7e,0x30,0x2, 0xac,0x3a, +0x59,0x41,0x1f,0x34,0x12,0xa3,0xa9,0xbc,0xfa,0x38,0xed,0x7e,0x8, 0x1f,0x34,0x7c, +0xbf,0x12,0x5e,0xa9,0x74,0x2, 0xac,0xbe,0x7e,0x1d,0x24,0x2d,0x35,0x1b,0x35,0x6c, +0xaa,0x80,0xf, 0x7e,0x30,0x2, 0xac,0x3a,0x49,0x11,0x1f,0x34,0x1b,0x1a,0x10,0x12, +0xa3,0xa9,0xbc,0xfa,0x38,0xed,0xda,0x79,0x22,0x7e,0x30,0x2, 0xac,0x3e,0x2d,0x31, +0xb, 0xa0,0x22,0x7e,0x63,0x2a,0x6e,0xc2,0x16,0x6c,0x33,0x80,0x48,0x7c,0x96,0xac, +0x93,0x2e,0x44,0x0, 0x17,0x7d,0x4, 0xb, 0x4, 0x7d,0x54,0x3e,0x54,0x7e,0x7f,0x13, +0x8a,0x2d,0xf5,0xb, 0x7a,0x50,0xbe,0x57,0x2a,0x5a,0x8, 0x27,0x7c,0xb3,0x12,0x67, +0x50,0x50,0x20,0x7d,0x50,0x3e,0x54,0x7e,0x7f,0x13,0x8a,0x7f,0x67,0x2d,0xd5,0xb, +0x6a,0x20,0x7d,0x54,0x3e,0x54,0x2d,0xf5,0xb, 0x7a,0x50,0xbd,0x52,0x8, 0x4, 0xd2, +0x16,0x80,0xa, 0xb, 0x30,0x7e,0x73,0x2a,0x75,0xbc,0x73,0x38,0xb0,0x30,0x16,0x5, +0xd2,0x0, 0x2, 0x67,0xa3,0x22,0x7e,0xb3,0x2b,0x1d,0xb4,0x1, 0x31,0x12,0xa4,0x4f, +0x7e,0x1f,0x39,0xda,0x7a,0x37,0x24,0xfa,0x7e,0x34,0xd, 0xc8,0x7a,0x37,0x24,0xf6, +0x12,0xa4,0x56,0x12,0xa4,0x5f,0xe4,0x7a,0xb3,0x24,0xf5,0x7e,0x34,0x0, 0x20,0x7a, +0x37,0x24,0xfc,0x7a,0xb3,0x24,0xf4,0x7e,0x8, 0x24,0xf2,0x2, 0xd, 0x7, 0x22,0xa9, +0xd1,0xcb,0xe4,0x2, 0x0, 0xe, 0x7e,0x73,0x2a,0x6d,0x7a,0x73,0x24,0xf2,0x22,0x7e, +0x73,0x2a,0x6e,0x7a,0x73,0x24,0xf3,0x22,0x7e,0x43,0x2a,0x6e,0x7e,0x53,0x2a,0x6d, +0xac,0x54,0x7e,0x17,0x28,0xa1,0x12,0xa4,0x4f,0x6d,0x0, 0x80,0x37,0x7d,0x40,0x3e, +0x44,0x7e,0x7f,0x39,0xda,0x2d,0xf4,0xb, 0x7a,0x30,0xbd,0x13,0x58,0x10,0x7d,0xf4, +0x2e,0xf4,0x8, 0xa, 0xb, 0xf8,0x50,0x9d,0x51,0x1b,0xf8,0x50,0x80,0x14,0x6d,0x55, +0x9d,0x51,0xbd,0x53,0x8, 0xc, 0x2e,0x44,0x8, 0xa, 0xb, 0x48,0x50,0x2d,0x51,0x1b, +0x48,0x50,0xb, 0x4, 0xbd,0x20,0x38,0xc5,0x22,0xca,0x3b,0x7e,0xf3,0x2a,0x6e,0x7e, +0xe3,0x2a,0x6f,0x7e,0xd3,0x2a,0x70,0x6c,0xcc,0x80,0x13,0x7c,0x7c,0xac,0x7f,0x3e, +0x34,0x7e,0xf, 0x13,0x8a,0x2d,0x13,0x7c,0xbd,0x12,0x5e,0xa9,0xb, 0xc0,0xbc,0xec, +0x38,0xe9,0xda,0x3b,0x22,0x6c,0xaa,0x7e,0x30,0x4, 0xac,0x3a,0x7d,0xf1,0x2e,0xf4, +0x60,0xb1,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x20,0xbd,0x23,0x38,0xf, 0x2e,0x14,0x60, +0xb3,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20,0xbd,0x23,0x50,0x7, 0xb, 0xa0,0xbe,0xa0, +0x3, 0x40,0xd4,0x7c,0xba,0x22,0x12,0xa5,0x25,0xbe,0x34,0x4, 0xe2,0x28,0x3, 0xd2, +0x17,0x22,0xc2,0x17,0x22,0x6d,0x11,0xe4,0x12,0x0, 0x1e,0x6c,0xaa,0x80,0x5b,0x7e, +0x10,0x2, 0xac,0x1a,0x7e,0x7f,0x39,0xf4,0x2d,0xf0,0x69,0x27,0x1, 0x0, 0x69,0x37, +0x0, 0x80,0x9d,0x32,0x12,0x21,0xa, 0xbd,0x31,0x28,0x16,0x7e,0x70,0x2, 0xac,0x7a, +0x7e,0xf, 0x39,0xf4,0x2d,0x13,0x69,0x20,0x1, 0x0, 0x69,0x30,0x0, 0x80,0x12,0x4f, +0xcc,0x7e,0x10,0x2, 0xac,0x1a,0x7e,0x1f,0x39,0xf4,0x2d,0x30,0x69,0x1, 0x0, 0x80, +0xbe,0x4, 0x7f,0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff,0x69,0x1, 0x1, 0x0, 0xbe,0x4, +0x7f,0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xbc,0xba, +0x38,0x9d,0x7d,0x31,0x22,0x7e,0x60,0x4, 0x7e,0x27,0x3a,0x5, 0xbe,0x24,0x3, 0xe8, +0x28,0x3, 0x7e,0x60,0x8, 0x7e,0xb3,0x28,0xac,0xb4,0x1, 0x1a,0x7e,0x73,0x2f,0xaa, +0xbc,0x76,0x50,0xf, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0x6c,0x5a,0x7e,0xb3,0x2f,0xaa, +0x4, 0x80,0x4, 0xe4,0x80,0x1, 0xe4,0x7a,0xb3,0x2f,0xaa,0x7e,0xb3,0x28,0xad,0xb4, +0x1, 0x17,0x7e,0xa3,0x2f,0xab,0xbe,0xa0,0x5, 0x50,0xa, 0xe4,0x7a,0xb3,0x28,0xad, +0x7c,0xba,0x4, 0x80,0x5, 0x74,0x5, 0x80,0x1, 0xe4,0x7a,0xb3,0x2f,0xab,0x22,0x6c, +0xaa,0x80,0x26,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12,0x5, 0xf8,0x49,0x32,0x4, 0x0, +0x2d,0x31,0x59,0x32,0x5, 0xf8,0x30,0x6, 0xe, 0x49,0x12,0x4, 0x7e,0x49,0x32,0x6, +0x76,0x2d,0x31,0x59,0x32,0x6, 0x76,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xa, 0x3b,0x7e, +0xb3,0x2a,0x73,0xa, 0x2b,0x2d,0x23,0xa, 0x3a,0xbd,0x32,0x48,0xc6,0x22,0x74,0x2, +0x7a,0xb3,0x2f,0xa9,0x74,0x1, 0x7a,0xb3,0x28,0xac,0x2, 0x26,0x11,0xd2,0x0, 0x6c, +0xaa,0x6c,0x77,0x80,0x1f,0x7e,0x63,0x2a,0x6e,0xa, 0x16,0xa, 0x27,0x2d,0x21,0x7c, +0x65,0x7e,0x50,0x2, 0xac,0x56,0x49,0x22,0x5, 0x7a,0xbe,0x24,0xfe,0xc, 0x58,0x2, +0xb, 0xa0,0xb, 0x70,0x7e,0xb3,0x2a,0x6d,0xbc,0xb7,0x38,0xd9,0xa, 0x2b,0x1e,0x24, +0xa, 0x3a,0xbd,0x32,0x8, 0x2, 0xc2,0x0, 0xa2,0x0, 0x22,0x7e,0x63,0x2a,0x6f,0x7e, +0xa3,0x2a,0x70,0x7e,0x70,0x1, 0x80,0x15,0xa, 0x17,0x7e,0xb3,0x2a,0x6e,0xa, 0x2b, +0x2d,0x21,0x3e,0x24,0x12,0xa6,0xc6,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x16,0x1b, +0x14,0xa, 0x27,0xbd,0x21,0x48,0xe1,0x7e,0x70,0x2, 0x80,0xe, 0x7e,0x50,0x2, 0xac, +0x57,0x12,0xa6,0xc6,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x1a,0x1b,0x15,0xa, 0x27, +0xbd,0x21,0x48,0xe8,0xc3,0x22,0x49,0x22,0x4, 0xfc,0xbe,0x24,0xff,0x6, 0x22,0x7e, +0xb3,0x37,0x75,0xb4,0x1, 0x3, 0x2, 0xa7,0x26,0x7e,0xb3,0x37,0xdb,0x4, 0x7a,0xb3, +0x37,0xdb,0x7e,0xb3,0x37,0x69,0xb4,0x2, 0x18,0x7e,0xb3,0x37,0xda,0x4, 0x7a,0xb3, +0x37,0xda,0xb4,0x1, 0x6, 0x74,0x1, 0x7a,0xb3,0x37,0xdb,0x74,0x1, 0x7a,0xb3,0x37, +0x69,0x7e,0x73,0x37,0xda,0xbe,0x70,0x3, 0x40,0xf, 0x74,0x1, 0x7a,0xb3,0x37,0x75, +0x12,0xa7,0x26,0x12,0xa7,0xd0,0x12,0xa7,0x2d,0x7e,0x73,0x37,0xdb,0xbe,0x70,0xa, +0x28,0x3, 0x2, 0xa7,0x2d,0x22,0x74,0x2, 0x7a,0xb3,0x37,0x69,0x22,0xe4,0x7a,0xb3, +0x37,0xdb,0x7a,0xb3,0x37,0xda,0x22,0x7e,0x73,0x37,0x69,0x7a,0x73,0x37,0xdf,0x7e, +0x47,0x39,0xd7,0xbe,0x44,0x0, 0x64,0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x37,0x69,0xbe, +0x44,0x0, 0xc8,0x28,0x8, 0xe4,0x7a,0xb3,0x37,0x67,0x12,0xa7,0x26,0x7e,0x57,0x37, +0x6f,0xbd,0x54,0x50,0x4, 0x7a,0x47,0x37,0x6f,0x12,0xa7,0xc8,0x38,0xa, 0x12,0xa7, +0xc0,0x38,0x5, 0x12,0xa7,0xb8,0x28,0x34,0x12,0xa6,0xcf,0xbe,0x44,0x0, 0x32,0x50, +0x21,0x7e,0xb3,0x37,0x67,0x4, 0x7a,0xb3,0x37,0x67,0x7e,0x73,0x37,0x67,0xbe,0x70, +0x32,0x28,0x14,0x74,0x32,0x7a,0xb3,0x37,0x67,0x12,0x57,0xee,0x7a,0xb3,0x37,0xdc, +0x80,0x5, 0xe4,0x7a,0xb3,0x37,0x67,0x7d,0x34,0x2, 0xa8,0x35,0x2, 0xa7,0xaf,0x12, +0xa7,0x2d,0xe4,0x7a,0xb3,0x37,0x75,0x22,0x7e,0x73,0x26,0xf5,0xbe,0x70,0x0, 0x22, +0x7e,0x73,0x26,0xf4,0xbe,0x70,0x0, 0x22,0x7e,0x73,0x28,0x92,0xbe,0x70,0x0, 0x22, +0xe4,0x7a,0xb3,0x37,0x67,0x6d,0x33,0x6c,0xaa,0x7e,0x50,0xc, 0xac,0x5a,0x59,0x32, +0x37,0x7e,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xf0,0xe4,0x7a,0xb3,0x37,0x68,0x6d,0x33, +0x7a,0x37,0x37,0x6f,0x7a,0x37,0x37,0x64,0x22,0x7e,0x37,0x39,0xd3,0x12,0x7e,0x3c, +0x7a,0x37,0x37,0xdd,0x6c,0xaa,0x80,0x24,0xbe,0xa0,0x4, 0x50,0x27,0xa, 0x3a,0x9, +0x63,0x37,0x76,0xbe,0x60,0x4, 0x50,0x12,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x42,0x39, +0xcd,0x7e,0x70,0xc, 0xac,0x67,0x59,0x43,0x37,0x80,0xb, 0xa0,0x7e,0xb3,0x37,0x73, +0xbc,0xba,0x38,0xd4,0x22,0xbe,0x34,0x1, 0xf4,0x28,0xd, 0x7e,0x53,0x37,0xdc,0xbe, +0x50,0x8, 0x50,0x3f,0x74,0x8, 0x80,0x37,0xbe,0x34,0x1, 0x90,0x28,0xd, 0x7e,0x53, +0x37,0xdc,0xbe,0x50,0x6, 0x50,0x2c,0x74,0x6, 0x80,0x24,0xbe,0x34,0x1, 0x2c,0x28, +0xd, 0x7e,0x53,0x37,0xdc,0xbe,0x50,0x4, 0x50,0x19,0x74,0x4, 0x80,0x11,0xbe,0x34, +0x0, 0xc8,0x28,0xf, 0x7e,0x73,0x37,0xdc,0xbe,0x70,0x2, 0x50,0x6, 0x74,0x2, 0x7a, +0xb3,0x37,0xdc,0x7e,0xb3,0x37,0xdc,0xbe,0xb0,0x0, 0x28,0x19,0x14,0x7a,0xb3,0x37, +0xdc,0x74,0x1, 0x7a,0xb3,0x16,0x92,0x7e,0x73,0x37,0xdc,0xbe,0x70,0x4, 0x28,0x5, +0xe4,0x7a,0xb3,0x16,0x91,0x22,0x7c,0x3b,0x7e,0x44,0xff,0xff,0x6c,0x22,0x80,0x2a, +0x12,0xa9,0x1f,0x68,0x23,0x7e,0x70,0xc, 0xac,0x72,0x12,0xaa,0x2f,0x7d,0x23,0x7e, +0x70,0xc, 0xac,0x72,0x59,0x23,0x37,0x82,0x49,0x3, 0x37,0x82,0x49,0x23,0x37,0x7e, +0xbd,0x20,0x50,0x4, 0x59,0x3, 0x37,0x7e,0xb, 0x20,0xbc,0x32,0x50,0xd2,0x6c,0xaa, +0x6c,0x22,0x80,0x18,0x12,0xa9,0x1f,0x68,0x11,0x7e,0x70,0xc, 0xac,0x72,0x49,0x3, +0x37,0x7e,0xbd,0x4, 0x50,0x4, 0x7d,0x40,0x7c,0xa2,0xb, 0x20,0xbc,0x32,0x50,0xe4, +0x7e,0x37,0x37,0x64,0xbe,0x37,0x37,0xdd,0x50,0x8, 0x7e,0x37,0x37,0xdd,0x7a,0x37, +0x37,0x64,0x12,0xaa,0x25,0x4d,0x33,0x78,0x3, 0x7e,0xa0,0xff,0x7c,0xba,0x22,0x7e, +0x10,0x5, 0xac,0x12,0x9, 0xb0,0x26,0x33,0xbe,0xb3,0x2b,0xf, 0x22,0xca,0x79,0x7e, +0xf0,0xff,0x12,0xaa,0x96,0x7e,0xb3,0x37,0x6b,0xb4,0x1, 0x8, 0x12,0x6a,0xaf,0xe4, +0x7a,0xb3,0x37,0x6b,0x7e,0xb3,0x37,0x6a,0x60,0x4, 0x74,0xff,0x41,0x22,0x7e,0xb3, +0x37,0x69,0xb4,0x2, 0x2, 0x80,0x2, 0x41,0x16,0x12,0xa7,0xc8,0x38,0xc, 0x12,0xa7, +0xc0,0x38,0x7, 0x12,0xa7,0xb8,0x38,0x2, 0x41,0x16,0x74,0x3, 0x12,0xa8,0xa6,0x7c, +0xeb,0x7e,0xb3,0x37,0x68,0x4, 0x7a,0xb3,0x37,0x68,0x74,0x3, 0x12,0xa8,0xa6,0x7c, +0xab,0xbe,0xa0,0xff,0x68,0x23,0xbe,0xe0,0xff,0x68,0x1c,0x7e,0x30,0xc, 0xac,0x3e, +0x49,0x21,0x37,0x7e,0xbe,0x24,0x1, 0xf4,0x28,0xf, 0x12,0xaa,0x25,0x3e,0x34,0xbd, +0x23,0x28,0x6, 0x7c,0xea,0x80,0x2, 0x7c,0xea,0xbe,0xe0,0xff,0x78,0x11,0xe4,0x7a, +0xb3,0x37,0x68,0x7a,0xb3,0x37,0x69,0x7a,0xb3,0x37,0x75,0x74,0xff,0x80,0x63,0x7e, +0x73,0x37,0x68,0xbe,0x70,0x4, 0x28,0x4e,0x74,0xc, 0xac,0xbe,0x49,0x35,0x37,0x7e, +0xbe,0x34,0x1, 0xf4,0x50,0x37,0x7e,0x37,0x37,0x64,0xbe,0x34,0x1, 0x2c,0x38,0xa, +0x7e,0x37,0x37,0x6f,0xbe,0x34,0x1, 0x2c,0x28,0x23,0x74,0x5, 0xac,0xbe,0x9, 0x75, +0x26,0x33,0xbe,0x73,0x2b,0xf, 0x68,0x15,0x7c,0xfe,0xbe,0xf0,0x4, 0x50,0x8, 0x12, +0x8b,0x16,0xbe,0xb0,0x4, 0x40,0x6, 0x74,0x1, 0x7a,0xb3,0x37,0x6b,0xe4,0x7a,0xb3, +0x37,0x75,0x7a,0xb3,0x37,0x69,0xbe,0xf0,0xff,0x68,0x5, 0xe4,0x7a,0xb3,0x37,0x68, +0x7c,0xbf,0xda,0x79,0x22,0x7e,0x70,0xc, 0xac,0x7a,0x49,0x33,0x37,0x7e,0x22,0x49, +0x23,0x37,0x84,0x49,0x33,0x37,0x80,0x9d,0x32,0x2, 0x21,0xa, 0x6c,0xaa,0x7e,0x70, +0xc, 0xac,0x7a,0x12,0xaa,0x2f,0xbe,0x34,0x3, 0xe8,0x8, 0x5, 0x12,0xaa,0x88,0x80, +0x2f,0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x37,0x84,0x49,0x12,0x37,0x80,0xbd,0x13, +0x28,0xf, 0x7d,0x2, 0x2e,0x4, 0x37,0x84,0x7d,0x13,0xb, 0x15,0x1b,0x8, 0x10,0x80, +0xf, 0xbe,0x34,0x0, 0x2, 0x28,0x9, 0x2e,0x24,0x37,0x84,0x1b,0x35,0x1b,0x28,0x30, +0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xb7,0x22,0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x37, +0x80,0x59,0x32,0x37,0x84,0x22,0x7e,0xb3,0x37,0x6a,0xb4,0x1, 0x27,0x7e,0xb3,0x37, +0xe0,0x4, 0x7a,0xb3,0x37,0xe0,0x7e,0x73,0x37,0xe0,0xbe,0x70,0x3, 0x40,0x15,0x12, +0x57,0x9f,0x7e,0x73,0x37,0xe0,0xbe,0x70,0x6, 0x40,0x9, 0xe4,0x7a,0xb3,0x37,0xe0, +0x7a,0xb3,0x37,0x6a,0x22,0x12,0x4f,0xee,0x12,0xaa,0xfe,0x7e,0x8, 0x2a,0x88,0x7e, +0xb3,0x2a,0x87,0x12,0xaa,0xf7,0x7e,0x8, 0x2b,0x2f,0x7e,0xb3,0x2b,0x2e,0x12,0xaa, +0xf7,0x7e,0x8, 0x2a,0x8a,0xe5,0x25,0x12,0x8f,0xc7,0x7e,0x8, 0x2b,0x31,0xe5,0x24, +0x7e,0x34,0x0, 0x3, 0x2, 0x20,0xe8,0x7e,0x34,0x0, 0x2, 0x2, 0x20,0xe8,0x6c,0xaa, +0xe4,0xa, 0x4b,0x9, 0x94,0x2a,0x7a,0xbc,0x9a,0x68,0x6, 0x4, 0xbe,0xb0,0xe, 0x40, +0xf0,0xbe,0xb0,0xe, 0x68,0x7, 0xb, 0xa0,0xbe,0xa0,0x23,0x40,0xe3,0x7a,0xb, 0xa0, +0x74,0x6e,0x7a,0x1b,0xb0,0x22,0x7e,0x8, 0x37,0x7a,0x7e,0x34,0x0, 0x60,0xe4,0x12, +0x20,0xe8,0x6c,0xaa,0x7e,0x44,0xff,0xff,0x7e,0x70,0xc, 0xac,0x7a,0x59,0x43,0x37, +0x7c,0x59,0x43,0x37,0x84,0xb, 0xa0,0xbe,0xa0,0x8, 0x40,0xe8,0x7e,0x8, 0x37,0x68, +0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x20,0xe8,0x12,0x47,0xe2,0x7e,0xb3,0x37,0x71,0xbe, +0xb0,0x1, 0x68,0x6, 0x7e,0xb3,0x37,0xed,0x60,0x10,0x7e,0x34,0x0, 0xf0,0x7a,0x37, +0x2a,0x5a,0x7e,0x34,0x0, 0xc8,0x7a,0x37,0x2a,0x5c,0x7e,0xb3,0x28,0xa8,0xb4,0x1, +0x24,0x7e,0x34,0x1, 0x18,0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x0, 0xfa,0x7a,0x37,0x2a, +0x5c,0x7e,0x34,0x1, 0x40,0x7a,0x37,0x2a,0x4f,0x7a,0x37,0x2a,0x51,0x7e,0x34,0x1, +0x7c,0x7a,0x37,0x2a,0x53,0x7e,0xb3,0x2a,0x2, 0x70,0x21,0x7e,0x27,0x2a,0x5a,0x7d, +0x32,0x7e,0x14,0x0, 0x4, 0xad,0x13,0x7d,0x31,0x12,0x7e,0x3c,0xbe,0x34,0x0, 0x50, +0x28,0x4, 0x7e,0x34,0x0, 0x50,0x2d,0x32,0x7a,0x37,0x2a,0x5a,0x22,0x6d,0x33,0x7d, +0x23,0x7d,0x3, 0x6c,0x33,0x80,0x45,0x6c,0x22,0x80,0x37,0x7e,0xb3,0x2a,0x6e,0xac, +0xb3,0xa, 0x42,0x2d,0x54,0x7d,0x45,0x3e,0x44,0x7e,0x7f,0x13,0x8a,0x2d,0xf4,0xb, +0x7a,0x40,0xbe,0x44,0x0, 0x32,0x8, 0x8, 0xbe,0x44,0x2, 0x58,0x58,0x2, 0xb, 0x24, +0xbe,0x44,0xff,0xce,0x58,0x8, 0xbe,0x44,0xfd,0xa8,0x8, 0x2, 0xb, 0x4, 0xb, 0x34, +0xb, 0x21,0x7e,0x93,0x2a,0x6e,0xbc,0x92,0x38,0xc1,0xb, 0x31,0x7e,0xb3,0x2a,0x6d, +0xbc,0xb3,0x38,0xb3,0x7e,0x54,0x0, 0x6, 0xad,0x53,0x7d,0x15,0x1e,0x14,0x1e,0x14, +0x1e,0x14,0x12,0x7e,0x3e,0xbd,0x12,0x50,0x22,0xbd,0x30,0x28,0x1e,0xe4,0x7a,0xb3, +0x3a,0x9, 0x7e,0xb3,0x3a,0xa, 0xbe,0xb0,0x5, 0x50,0x7, 0x4, 0x7a,0xb3,0x3a,0xa, +0x80,0x3c,0xe4,0x7a,0xb3,0x3a,0xa, 0x74,0x1, 0x80,0x2f,0xbd,0x10,0x50,0x22,0xbd, +0x32,0x28,0x1e,0xe4,0x7a,0xb3,0x3a,0xa, 0x7e,0xb3,0x3a,0x9, 0xbe,0xb0,0x5, 0x50, +0x7, 0x4, 0x7a,0xb3,0x3a,0x9, 0x80,0x16,0xe4,0x7a,0xb3,0x3a,0x9, 0x74,0x2, 0x80, +0x9, 0xe4,0x7a,0xb3,0x3a,0x9, 0x7a,0xb3,0x3a,0xa, 0x7a,0xb3,0x3a,0xb, 0x7e,0xb3, +0x3a,0xb, 0x22,0x6c,0x66,0x7e,0xb3,0x28,0xa8,0xb4,0x1, 0x63,0x7e,0x73,0x26,0xf2, +0xbe,0x70,0x0, 0x28,0x5a,0x6c,0x33,0x80,0x4e,0xa, 0x23,0x9, 0x72,0x26,0xe6,0x7e, +0xb3,0x2a,0x6e,0x14,0xbc,0x7b,0x78,0x3d,0x6c,0x22,0x80,0x27,0x7c,0xb2,0x7c,0x73, +0x12,0x67,0xe2,0x50,0x1c,0xa, 0x22,0x7e,0x73,0x2a,0x6e,0xa, 0x7, 0x2d,0x2, 0x3e, +0x4, 0x49,0x20,0x4, 0xfc,0x6d,0x0, 0x9e,0x7, 0x2a,0x4f,0xbd,0x20,0x58,0x2, 0xb, +0x60,0xb, 0x20,0x7e,0x73,0x2a,0x6d,0xbc,0x72,0x38,0xd1,0xbe,0x60,0x0, 0x28,0x3, +0x74,0x1, 0x22,0xe4,0x22,0xb, 0x30,0x7e,0x73,0x26,0xf2,0xbc,0x73,0x38,0xaa,0x74, +0x1, 0x22,0x7c,0xab,0xbe,0xa0,0x0, 0x40,0x11,0x7e,0xb3,0x2a,0x6e,0xbc,0xba,0x28, +0x9, 0x74,0x2, 0xa4,0x49,0x25,0x34,0x0, 0x80,0x51,0x7e,0x13,0x2a,0x6e,0xbc,0x1a, +0x38,0x1c,0x7e,0x3, 0x2a,0x6d,0xa, 0x10,0xa, 0x21,0x2d,0x12,0xa, 0x3a,0xbd,0x31, +0x58,0xc, 0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23,0x3, 0x70,0x80,0x2d,0x7e,0x3, +0x2a,0x6d,0xa, 0x20,0xa, 0x11,0x7d,0x41,0x2d,0x42,0xa, 0x3a,0xbd,0x34,0x48,0x19, +0x7e,0x10,0x2, 0xac,0x1, 0x2d,0x1, 0xbd,0x30,0x58,0xe, 0x9d,0x31,0x9d,0x32,0x3e, +0x34,0x3e,0x34,0x49,0x23,0x3, 0x72,0x80,0x2, 0xe4,0x22,0x7e,0x34,0x0, 0x64,0xad, +0x23,0x74,0xc, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7c, +0xb7,0x22,0xca,0xf8,0x80,0x38,0x7c,0xbf,0x12,0xad,0x2, 0xa, 0x1b,0x7e,0x63,0x2a, +0x6e,0x7e,0x70,0x2, 0xac,0x67,0x7e,0x10,0x2, 0xac,0x1f,0x2d,0x3, 0x7e,0x1f,0x13, +0x8a,0x2d,0x30,0x12,0xad,0xc1,0x9d,0x35,0x1b,0x1a,0x10,0xb, 0xf0,0x12,0xad,0xc1, +0x7e,0x73,0x2a,0x6e,0xa, 0x27,0x2d,0x25,0xa, 0x3f,0xbd,0x32,0x48,0xc8,0xda,0xf8, +0x22,0x7e,0xa3,0x2a,0x6d,0x74,0x2, 0xa4,0x22,0xc2,0x0, 0x12,0x44,0xc4,0x50,0x42, +0x6c,0xaa,0x80,0x30,0x7e,0x50,0x2, 0xac,0x5a,0x9, 0x72,0x26,0xfa,0x9, 0x62,0x26, +0xfb,0xbe,0x70,0x0, 0x40,0x1c,0x7e,0xb3,0x2a,0x6f,0xa, 0x1b,0x1b,0x14,0xa, 0x27, +0xbd,0x21,0x18,0xe, 0xbe,0x60,0x0, 0x40,0x9, 0xbe,0x60,0xf, 0x38,0x4, 0xd2,0x0, +0x80,0xa, 0xb, 0xa0,0x7e,0xb3,0x28,0x84,0xbc,0xba,0x38,0xc8,0x20,0x0, 0x3, 0x12, +0x6c,0x48,0x30,0x1a,0x14,0x5, 0x5d,0xe5,0x5d,0xbe,0xb0,0x50,0x50,0x7, 0x7e,0x34, +0x0, 0x8, 0x2, 0x5f,0xcc,0xc2,0x1a,0x80,0x0, 0x75,0x5d,0x0, 0x22,0xca,0x3b,0x7c, +0xfb,0x75,0x3d,0x0, 0x7e,0xb3,0x2a,0x6f,0xf5,0x42,0x7e,0xb3,0x2a,0x70,0xf5,0x43, +0x75,0x44,0x28,0x7e,0xd3,0x28,0x84,0xe4,0x7a,0xb3,0x31,0xcf,0x7a,0xb3,0x31,0xcb, +0x7a,0xb3,0x31,0xcc,0x7e,0x8, 0x31,0xd0,0x7e,0x34,0x0, 0x1e,0x12,0x20,0xe8,0x7e, +0x8, 0x31,0xf0,0x7e,0x34,0x0, 0x3c,0x12,0x20,0xe8,0xbe,0xd0,0x2, 0x50,0x3, 0x2, +0xb2,0x15,0x6c,0xcc,0x2, 0xb2,0xe, 0x12,0x97,0xd4,0xf5,0x24,0x9, 0xb3,0x26,0xfb, +0xf5,0x25,0x4c,0xcc,0x68,0x8, 0xa, 0x3c,0x9, 0xb3,0x31,0xd0,0x70,0xa, 0xa, 0x3c, +0xb, 0x34,0xa, 0x2c,0x19,0x72,0x31,0xd0,0x7c,0xbd,0x14,0xbc,0xbc,0x78,0x3, 0x2, +0xb2,0x15,0xa, 0x5c,0xb, 0x54,0xf5,0x2e,0x2, 0xb2,0x4, 0x7e,0x71,0x2e,0x12,0xb5, +0x9e,0x7a,0xa1,0x26,0x9, 0xb3,0x26,0xfb,0xf5,0x27,0xa, 0x2a,0xe5,0x24,0x12,0x44, +0x5b,0x7c,0xb7,0xf5,0x28,0xe5,0x27,0xa, 0x2b,0xe5,0x25,0x12,0x44,0x5b,0x7c,0xb7, +0xf5,0x29,0xe5,0x28,0xbe,0xb0,0x5, 0x40,0x3, 0x2, 0xb2,0x2, 0xe5,0x29,0xbe,0xb0, +0x5, 0x40,0x3, 0x2, 0xb2,0x2, 0x12,0xb2,0x18,0x12,0x94,0x83,0x7a,0xb3,0x31,0xce, +0x85,0x25,0x54,0x85,0x26,0x55,0x85,0x27,0x56,0x7e,0x8, 0x0, 0x31,0x7e,0x18,0x0, +0x33,0xe5,0x24,0x12,0xb3,0x37,0x75,0x3d,0x0, 0x6c,0xee,0x75,0x30,0x0, 0xe5,0x24, +0x7e,0x71,0x25,0x12,0x6d,0xcb,0x7a,0x35,0x35,0xe5,0x26,0x7e,0x71,0x27,0x12,0x6d, +0xcb,0x7a,0x35,0x37,0x7e,0x35,0x35,0xbe,0x35,0x37,0x8, 0x5, 0x7e,0x35,0x37,0x80, +0x3, 0x7e,0x35,0x35,0x7a,0x35,0x3b,0xe, 0x34,0x7a,0x35,0x39,0xe5,0x28,0xbe,0xb0, +0x1, 0x38,0x2e,0xe5,0x29,0xbe,0xb0,0x1, 0x38,0x27,0x7c,0xbf,0x30,0xe1,0x22,0xe5, +0x26,0x7e,0x71,0x25,0x12,0x6d,0xcb,0x7d,0x43,0xe5,0x24,0x7e,0x71,0x27,0x12,0x6d, +0xcb,0x2d,0x34,0xbe,0x35,0x39,0x18,0x3, 0x2, 0xb1,0x99,0x75,0x30,0x1, 0x2, 0xb1, +0x99,0xe5,0x28,0xbe,0xb0,0x1, 0x38,0xa, 0xe5,0x29,0xbe,0xb0,0x1, 0x38,0x3, 0x2, +0xb1,0x99,0xe5,0x28,0xbe,0xb0,0x5, 0x40,0x3, 0x2, 0xb1,0x99,0xe5,0x29,0xbe,0xb0, +0x5, 0x40,0x3, 0x2, 0xb1,0x99,0x7c,0xbf,0x20,0xe0,0x3, 0x2, 0xb1,0x99,0x6d,0x33, +0x7a,0x35,0x4d,0x75,0x4f,0x0, 0x7a,0x35,0x50,0x75,0x52,0x0, 0xc2,0x2, 0xc2,0x3, +0xe5,0x26,0xbe,0xb1,0x24,0x28,0x4, 0xe5,0x24,0x80,0x2, 0xe5,0x26,0xf5,0x2a,0xe5, +0x26,0xbe,0xb1,0x24,0x50,0x4, 0xe5,0x24,0x80,0x2, 0xe5,0x26,0xf5,0x2c,0xe5,0x27, +0xbe,0xb1,0x25,0x28,0x4, 0xe5,0x25,0x80,0x2, 0xe5,0x27,0xf5,0x2b,0xe5,0x27,0xbe, +0xb1,0x25,0x50,0x4, 0xe5,0x25,0x80,0x2, 0xe5,0x27,0xf5,0x2d,0xe5,0x2c,0xbe,0xb1, +0x2a,0x78,0x29,0xd2,0x2, 0xe5,0x2a,0x60,0x8, 0xe5,0x42,0x14,0xbe,0xb1,0x2a,0x78, +0x2, 0xd2,0x3, 0xe5,0x2a,0xbe,0xb0,0x0, 0x28,0x2, 0x15,0x2a,0xe5,0x42,0xa, 0x2b, +0x1b,0x24,0xe5,0x2c,0xa, 0x3b,0xbd,0x32,0x58,0x2, 0x5, 0x2c,0xe5,0x2d,0xbe,0xb1, +0x2b,0x78,0x29,0xd2,0x2, 0xe5,0x2b,0x60,0x8, 0xe5,0x43,0x14,0xbe,0xb1,0x2b,0x78, +0x2, 0xd2,0x3, 0xe5,0x2b,0xbe,0xb0,0x0, 0x28,0x2, 0x15,0x2b,0xe5,0x43,0xa, 0x2b, +0x1b,0x24,0xe5,0x2d,0xa, 0x3b,0xbd,0x32,0x58,0x2, 0x5, 0x2d,0x85,0x2a,0x3e,0x80, +0x5b,0x85,0x2b,0x3f,0x80,0x4d,0xe5,0x3e,0x7e,0x71,0x3f,0x12,0x6d,0xcb,0x7a,0x35, +0x40,0xe5,0x2a,0xbe,0xb1,0x3e,0x68,0x15,0xe5,0x2c,0xbe,0xb1,0x3e,0x68,0xe, 0xe5, +0x2b,0xbe,0xb1,0x3f,0x68,0x7, 0xe5,0x2d,0xbe,0xb1,0x3f,0x78,0xd, 0x7e,0x35,0x40, +0x2e,0x35,0x4d,0x7a,0x35,0x4d,0x5, 0x4f,0x80,0x17,0x5, 0x52,0x7e,0x35,0x40,0x2e, +0x35,0x50,0x7a,0x35,0x50,0x7e,0x35,0x33,0xbe,0x35,0x40,0x58,0x2, 0x5, 0x3d,0xb, +0xe0,0x5, 0x3f,0xe5,0x2d,0xbe,0xb1,0x3f,0x50,0xac,0x5, 0x3e,0xe5,0x2c,0xbe,0xb1, +0x3e,0x50,0x9e,0xe5,0x2c,0x7e,0x71,0x2b,0x12,0x6d,0xcb,0x7e,0x45,0x4d,0x9d,0x43, +0xe5,0x2a,0x7e,0x71,0x2d,0x12,0x6d,0xcb,0x9d,0x43,0xe5,0x2a,0x7e,0x71,0x2b,0x12, +0x6d,0xcb,0x9d,0x43,0xe5,0x2c,0x7e,0x71,0x2d,0x12,0x6d,0xcb,0x7d,0x23,0x7d,0x34, +0x9d,0x32,0x7a,0x35,0x4d,0x7e,0x35,0x37,0x2e,0x35,0x35,0x7a,0x35,0x39,0x30,0x2, +0x10,0x20,0x3, 0xd, 0x7e,0x35,0x4d,0x9e,0x35,0x39,0x7a,0x35,0x4d,0x15,0x4f,0x15, +0x4f,0xe5,0x4f,0xbe,0xb0,0x4, 0x28,0x6, 0xe5,0x4f,0x24,0xfc,0xf5,0x4f,0x7e,0x35, +0x4d,0xbe,0x34,0x0, 0x0, 0x58,0x5, 0x6d,0x33,0x7a,0x35,0x4d,0x75,0x44,0x28,0xe5, +0x42,0x14,0xbe,0xb1,0x24,0x68,0xd, 0xbe,0xb1,0x26,0x68,0x8, 0xe5,0x24,0x60,0x4, +0xe5,0x26,0x70,0x8, 0x12,0xb3,0x2f,0x28,0x3, 0x75,0x44,0x2c,0x7e,0x15,0x50,0x1a, +0x2, 0x1a,0x0, 0x7e,0x35,0x4d,0x1a,0x26,0x1a,0x24,0x2f,0x10,0xe5,0x44,0xa, 0x1b, +0x6d,0x0, 0x12,0x1e,0xeb,0x7f,0x71,0x7a,0x7d,0x45,0x7e,0x15,0x39,0x1a,0x2, 0x1a, +0x0, 0x7e,0x35,0x31,0x1a,0x26,0x1a,0x24,0x12,0x1e,0xeb,0xe5,0x52,0xa, 0xdb,0x6d, +0xcc,0xe5,0x4f,0xa, 0x1b,0x6d,0x0, 0x2f,0x6, 0x12,0x1e,0xeb,0x7a,0x1d,0x49,0xbf, +0x71,0x8, 0x3, 0x75,0x30,0x2, 0xc2,0x1, 0x20,0xc, 0xe, 0x12,0xb2,0x18,0x12,0xb2, +0x24,0x92,0x1, 0x20,0x1, 0x3, 0x75,0x30,0x0, 0xe5,0x30,0xbe,0xb0,0x0, 0x28,0x62, +0xe5,0x30,0xa, 0x3b,0x2e,0x34,0x31,0xca,0x7e,0x39,0xb0,0x4, 0x7a,0x39,0xb0,0xe5, +0x2e,0xa, 0x3b,0x9, 0xa3,0x31,0xd0,0x4c,0xaa,0x78,0xc, 0xa, 0x2c,0x9, 0xb2,0x31, +0xd0,0x19,0xb3,0x31,0xd0,0x80,0x3b,0xa, 0x2c,0x9, 0xb2,0x31,0xd0,0xf5,0x53,0xbc, +0xba,0x28,0x3, 0x7a,0xa1,0x53,0x75,0x2f,0x0, 0x80,0x22,0x9, 0x33,0x31,0xd0,0xe5, +0x2f,0xa, 0x2b,0x9, 0x22,0x31,0xd0,0xbc,0x23,0x68,0xa, 0xa, 0xc, 0x9, 0x30,0x31, +0xd0,0xbc,0x23,0x78,0x6, 0xe5,0x53,0x19,0xb2,0x31,0xd0,0x5, 0x2f,0xbe,0xd1,0x2f, +0x38,0xd9,0x5, 0x2e,0xbe,0xd1,0x2e,0x28,0x3, 0x2, 0xae,0xab,0xb, 0xc0,0xbc,0xdc, +0x28,0x3, 0x2, 0xae,0x77,0xda,0x3b,0x22,0xe5,0x24,0x7e,0x71,0x25,0x7e,0x61,0x26, +0x7e,0x51,0x27,0x22,0x12,0xb2,0x50,0x92,0x4, 0x30,0x4, 0xc, 0x7e,0xb3,0x32,0x2c, +0xbe,0xb0,0xfa,0x50,0x11,0x4, 0x80,0xa, 0x7e,0xb3,0x32,0x2c,0xbe,0xb0,0x0, 0x28, +0x5, 0x14,0x7a,0xb3,0x32,0x2c,0x7e,0xb3,0x32,0x2c,0x70,0x2, 0xc3,0x22,0xd3,0x22, +0xca,0x3b,0x7c,0x45,0x7c,0x6, 0x7c,0x57,0x7c,0x1b,0x7e,0x34,0x4, 0xfc,0x7e,0xb3, +0x26,0x83,0x7e,0xf3,0x2a,0x6e,0x7c,0x31,0x7c,0xe0,0x7c,0x25,0x7c,0xa4,0xbc,0x1, +0x50,0x4, 0x7c,0x30,0x7c,0xe1,0xbc,0x45,0x50,0x4, 0x7c,0x24,0x7c,0xa5,0xbe,0xb0, +0x1, 0x50,0x2, 0x61,0x15,0x7e,0x90,0x2, 0xac,0x9f,0x7e,0x50,0x2, 0xac,0x53,0x2d, +0x24,0x2d,0x23,0xb, 0x28,0x20,0x7e,0x10,0x2, 0xac,0x1e,0x2d,0x4, 0x2d,0x3, 0xb, +0x8, 0x40,0xa, 0x3, 0xb, 0x4, 0x7c,0x31,0x80,0x28,0x7e,0xd0,0x2, 0xac,0xdf,0x7e, +0x10,0x2, 0xac,0x13,0x2d,0x6, 0x12,0xb3,0x19,0x58,0x15,0xad,0xf4,0xbd,0xdf,0x58, +0xf, 0xbe,0x24,0x0, 0x0, 0x8, 0x9, 0xbe,0x44,0x0, 0x0, 0x8, 0x3, 0xc3,0x80,0x46, +0xb, 0x30,0xbc,0xe3,0x38,0xd4,0x7e,0x50,0x2, 0xac,0x52,0x2d,0x23,0xb, 0x28,0x20, +0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x43,0xb, 0x48,0x40,0xa, 0x12,0xb, 0x14,0x80,0x21, +0x7e,0x10,0x2, 0xac,0x13,0x12,0xb3,0x19,0x58,0x15,0xad,0xf4,0xbd,0xdf,0x58,0xf, +0xbe,0x24,0x0, 0x0, 0x8, 0x9, 0xbe,0x44,0x0, 0x0, 0x8, 0x3, 0xc3,0x80,0x7, 0xb, +0x30,0xbc,0xa3,0x38,0xdb,0xd3,0xda,0x3b,0x22,0x2d,0x3, 0xb, 0x8, 0x0, 0x7e,0xf4, +0x0, 0x9, 0x7d,0xb2,0xad,0xbf,0x7e,0xd4,0x0, 0xa, 0xad,0xd0,0xbd,0xdb,0x22,0x7e, +0x73,0x31,0xce,0xbe,0x70,0x5, 0x22,0xca,0xf8,0x7c,0xfb,0x7f,0x61,0x7f,0x50,0x7e, +0x34,0x22,0xd7,0x7e,0x24,0x0, 0xff,0x7e,0x14,0x1f,0x70,0x74,0x2a,0x12,0x1f,0xad, +0x7e,0x48,0x1f,0x70,0x12,0xb3,0xc6,0x92,0xc, 0x7c,0xbf,0x7e,0x71,0x54,0x12,0x6d, +0xcb,0x7d,0x43,0xe5,0x55,0x7e,0x71,0x56,0x12,0x6d,0xcb,0x2d,0x34,0xe, 0x34,0x7f, +0x4, 0x7e,0x50,0x7, 0xb, 0xa, 0x50,0xbd,0x53,0x58,0x10,0x69,0x30,0x0, 0x2, 0x1b, +0x5a,0x30,0x69,0x30,0x0, 0x4, 0x1b,0x6a,0x30,0x80,0x8, 0x2e,0x14,0x0, 0x6, 0x1b, +0x50,0x78,0xe1,0x12,0xb3,0x2f,0x28,0x2b,0xb, 0x5a,0x20,0x7e,0x34,0x0, 0xd, 0xad, +0x32,0x7e,0x24,0x0, 0x10,0x12,0x1e,0xb9,0x1b,0x5a,0x30,0xb, 0x6a,0x30,0x1a,0x26, +0x1a,0x24,0x7e,0x14,0x0, 0xd, 0x12,0x1e,0xfc,0x7e,0x8, 0x0, 0x10,0x12,0x1f,0x58, +0x1b,0x6a,0x30,0xda,0xf8,0x22,0x7e,0x37,0x28,0x8a,0xbe,0x34,0x2, 0x58,0x8, 0xa, +0x12,0x97,0x99,0xbe,0xb0,0x8, 0x48,0x2, 0xd3,0x22,0xc3,0x22,0x6c,0xaa,0x12,0x97, +0xea,0x29,0x81,0x0, 0x5, 0x7c,0x98,0x5e,0x90,0x1, 0x3e,0x90,0x7f,0x1, 0x2e,0x14, +0x0, 0x5, 0x7c,0xb8,0x54,0xfd,0x4c,0xb9,0x7a,0xb, 0xb0,0x29,0xb1,0x0, 0x5, 0x30, +0xe0,0x16,0x30,0xe2,0x13,0xc4,0x23,0x54,0x1f,0xb4,0x1, 0xc, 0x7f,0x1, 0xb, 0x16, +0x7e,0xb, 0xb0,0x1e,0xb0,0x7a,0xb, 0xb0,0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xbf,0x22, +0xca,0x3b,0x7f,0x40,0x7e,0xe3,0x28,0x84,0x6c,0xdd,0x7e,0xc0,0x1, 0x80,0x1a,0xa, +0x3d,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0x60,0xa, 0x2c,0x7f,0x4, 0x2d,0x12,0x7e,0xb, +0x70,0xbc,0x76,0x40,0x2, 0x7c,0xdc,0xb, 0xc0,0xbc,0xec,0x38,0xe2,0xa, 0x3d,0x2d, +0x39,0x7d,0x28,0x7e,0x1b,0xd0,0x6c,0xff,0x7e,0xc0,0x1, 0xa1,0x85,0x75,0x2d,0x0, +0x6d,0x33,0x7a,0x35,0x2e,0x7a,0x35,0x25,0x7a,0x35,0x27,0x7e,0x18,0x1f,0x70,0x7a, +0x1d,0x29,0x74,0xff,0x7e,0x34,0x1f,0x71,0x7e,0x24,0x0, 0x0, 0x7a,0x1b,0xb0,0x7e, +0x1d,0x29,0x7a,0x1b,0xb0,0xe4,0x7e,0x1d,0x29,0x39,0xb1,0x0, 0x3, 0x7e,0x1d,0x29, +0x39,0xb1,0x0, 0x2, 0x7e,0x1d,0x29,0x12,0x96,0xb3,0x44,0x1, 0x7a,0x1b,0xb0,0x75, +0x24,0x0, 0x80,0x6c,0x12,0xb5,0x9b,0x9, 0x93,0x26,0xfb,0xe5,0x24,0x12,0x44,0x62, +0xbc,0xbc,0x78,0x5a,0x5, 0x2d,0xa, 0x3a,0x2e,0x35,0x25,0x7a,0x35,0x25,0xa, 0x39, +0x2e,0x35,0x27,0x7a,0x35,0x27,0x12,0x6d,0xc7,0xbe,0x35,0x2e,0x8, 0x6, 0x12,0x6d, +0xc7,0x7a,0x35,0x2e,0x7e,0x1d,0x29,0x7e,0x1b,0xb0,0xbc,0xba,0x28,0x3, 0x7a,0x1b, +0xa0,0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x2, 0xbc,0xba,0x50,0x4, 0x39,0xa1,0x0, 0x2, +0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x1, 0xbc,0xb9,0x28,0x4, 0x39,0x91,0x0, 0x1, 0x7e, +0x1d,0x29,0x29,0xb1,0x0, 0x3, 0xbc,0xb9,0x50,0x4, 0x39,0x91,0x0, 0x3, 0x5, 0x24, +0xbe,0xe1,0x24,0x38,0x8f,0xe5,0x2d,0xbe,0xb0,0x0, 0x28,0x67,0x7e,0xd, 0x29,0x12, +0x94,0xd7,0xe5,0x2d,0xa, 0x2b,0x7e,0x15,0x25,0x8d,0x12,0x7a,0x15,0x25,0x7e,0x35, +0x27,0x8d,0x32,0x7a,0x35,0x27,0x7e,0x55,0x25,0x12,0xb5,0x93,0x19,0xa3,0x31,0xf0, +0x7e,0x55,0x27,0x12,0xb5,0x93,0x19,0xa3,0x31,0xf1,0x7e,0x37,0x28,0x8a,0xbe,0x35, +0x2e,0x78,0xe, 0x7e,0x35,0x25,0x7a,0x73,0x28,0x8c,0x7e,0x35,0x27,0x7a,0x73,0x28, +0x8d,0x7e,0x37,0x31,0xee,0x4d,0x33,0x68,0x18,0x7e,0x55,0x25,0x7e,0x35,0x27,0x12, +0x6d,0xcb,0x7e,0x25,0x2e,0x7e,0x70,0x2, 0xac,0x7f,0x2e,0x37,0x31,0xee,0x1b,0x38, +0x20,0xb, 0xf0,0xb, 0xc0,0xbc,0xdc,0x40,0x2, 0x81,0x5d,0x12,0xb3,0xdc,0x7c,0xbf, +0xda,0x3b,0x22,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7f,0x22,0x7e,0x71,0x24,0x74,0x2, +0xac,0x7b,0x9, 0xa3,0x26,0xfa,0x22,0x7e,0x73,0x2a,0x71,0xa, 0x17,0x2e,0x14,0x0, +0x3, 0x7e,0xa3,0x2a,0x6e,0xa, 0x3a,0xad,0x13,0x7d,0x21,0x6c,0x33,0x80,0x20,0xa, +0x3, 0x2d,0x2, 0x3e,0x4, 0x7e,0x7f,0x39,0xda,0x2d,0xf0,0xb, 0x7a,0x0, 0x7e,0x90, +0x2, 0xac,0x93,0x49,0xf4,0x13,0x8e,0x9d,0xf, 0x59,0x4, 0x25,0xb6,0xb, 0x30,0xbc, +0xa3,0x38,0xdc,0x7a,0x35,0x34,0x7e,0xf, 0x38,0x41,0x7e,0x18,0x25,0xb6,0x2, 0x5d, +0xf1,0x6c,0xaa,0x80,0x1c,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12,0x13,0xc6,0x49,0x32, +0x13,0x8e,0xbd,0x31,0x28,0x9, 0x2e,0x24,0x13,0x8e,0x9d,0x31,0x1b,0x28,0x30,0xb, +0xa0,0x7e,0xb3,0x2a,0x6e,0xbc,0xba,0x38,0xdc,0x22,0xca,0x78,0xa9,0x31,0xe5,0x6, +0xa9,0xd5,0xea,0xa9,0xc5,0xea,0xa9,0x30,0xe5,0x19,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e, +0x5, 0x5e,0x7e,0x73,0x3a,0x7, 0xbe,0x71,0x5e,0x38,0x2, 0xd2,0x1c,0xa9,0xd0,0x9e, +0xa9,0xd7,0x9e,0xa9,0x34,0xe5,0x5, 0xa9,0xc4,0xcd,0xc2,0x95,0xa9,0x32,0xe5,0x3, +0xa9,0xc2,0xcd,0xa9,0x33,0xe5,0x3, 0xa9,0xc3,0xcd,0xa9,0x37,0xe5,0x3, 0xa9,0xc7, +0xcd,0xa9,0x36,0xe5,0x3, 0xa9,0xc6,0xcd,0xda,0x78,0x32,0xc2,0x9a,0xa9,0xd4,0xa6, +0xc2,0x88,0xd2,0xa8,0x22,0x7e,0x14,0xd7,0xe8,0x7e,0x4, 0x0, 0xff,0x7e,0x34,0x47, +0x52,0x7e,0x24,0x55,0x50,0x79,0x30,0x0, 0x2, 0x1b,0xa, 0x20,0x7e,0x34,0x45,0x20, +0x7e,0x24,0x41,0x44,0x79,0x30,0x0, 0x6, 0x79,0x20,0x0, 0x4, 0x7e,0x34,0x99,0x33, +0x7e,0x24,0x66,0xcc,0x79,0x30,0x0, 0xa, 0x79,0x20,0x0, 0x8, 0x7e,0x34,0x41,0x47, +0x7e,0x24,0x46,0x4c,0x79,0x30,0x0, 0xe, 0x79,0x20,0x0, 0xc, 0x22,0xa9,0xc4,0xca, +0xa9,0xc5,0xca,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0x4f,0xdc,0xa9,0xd0,0xce,0xa9,0xc0, +0xc9,0xd2,0x2, 0x12,0x2f,0xde,0xa9,0xc2,0xea,0x75,0xc1,0x6, 0x75,0xc2,0xc, 0xd2, +0x0, 0x12,0xb6,0xee,0xa9,0xc1,0xc4,0xa9,0xd2,0xc4,0xa9,0xc2,0xe1,0x22,0xa2,0x0, +0xa9,0x97,0xc1,0xa2,0x0, 0xa9,0x97,0xc2,0x22,0xa9,0xd0,0xce,0xa2,0x0, 0xa9,0x95, +0xc9,0x22,0xca,0xf8,0xa2,0xaf,0xe4,0x33,0x7c,0xfb,0xd2,0x0, 0x12,0xb6,0xf9,0xa9, +0xd0,0xcb,0xc2,0xaf,0xa9,0xd0,0x9e,0x75,0x9d,0x0, 0xa9,0xd0,0x9e,0x75,0x9c,0x20, +0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0xa9,0xd0,0xcd,0x74,0x41,0x12,0x2f,0x39,0xa9,0xd0, +0x9e,0xa9,0xd7,0x9e,0x2e,0xf0,0xff,0x92,0xaf,0xda,0xf8,0x22,0xa9,0xd5,0xcb,0x74, +0x10,0x12,0x0, 0x66,0x7c,0x7b,0x12,0x28,0xb3,0x30,0xe7,0x3, 0x7e,0x70,0x2, 0xd2, +0xcd,0x7e,0x24,0x0, 0xef,0x7e,0xf, 0x39,0xc1,0x79,0x20,0x0, 0x84,0x7e,0x24,0x20, +0x5f,0x7e,0xf, 0x39,0xc1,0x79,0x20,0x0, 0x82,0x7e,0x24,0x41,0x0, 0x7e,0xf, 0x39, +0xc1,0x79,0x20,0x0, 0x90,0x7c,0x67,0x6c,0x77,0x2e,0x34,0x0, 0xc1,0x7e,0xf, 0x39, +0xc1,0x79,0x30,0x0, 0x86,0x7e,0x34,0x29,0x90,0x7e,0xf, 0x39,0xc1,0x79,0x30,0x0, +0x8a,0x7e,0x34,0x6a,0xd1,0x7e,0xf, 0x39,0xc1,0x79,0x30,0x0, 0x8c,0x7e,0x34,0x3, +0x61,0x7e,0xf, 0x39,0xc1,0x79,0x30,0x0, 0x8e,0x22,0xa9,0xc6,0xeb,0xa9,0xd6,0xac, +0xa9,0xd6,0xec,0xd2,0x86,0xa9,0xc2,0xeb,0xa9,0xd2,0xac,0xa9,0xd2,0xec,0xd2,0x82, +0x22,0x75,0x9a,0x2f,0xa9,0xd1,0x99,0xd2,0x9c,0xa9,0xd6,0xdf,0x22,0xc2,0x8e,0x43, +0x89,0x20,0x75,0x8d,0x1, 0x75,0x8b,0x0, 0xd2,0x8e,0xd2,0xab,0x22,0x75,0xb7,0x0, +0x75,0xb8,0x0, 0x75,0xf7,0x0, 0x75,0xf8,0x0, 0xa9,0xd0,0xb7,0xd2,0xb8,0xa9,0xd5, +0xb7,0xd2,0xbd,0xa9,0xd0,0xf7,0xd2,0xf8,0xa9,0xc1,0xb7,0xc2,0xb9,0xa9,0xc3,0xb7, +0xc2,0xbb,0xa9,0xc6,0xb7,0xc2,0xbe,0x22,0x75,0xe7,0x6b,0x2, 0xb8,0xe, 0xe4,0x7e, +0x34,0xd7,0xfc,0x12,0x77,0x15,0x7e,0x34,0xd7,0xfd,0x7a,0x1b,0xb0,0x75,0xe9,0xff, +0x22,0xa9,0xd0,0x99,0xa9,0xc6,0xdf,0x22,0x7e,0x37,0x3a,0x5, 0xb, 0x34,0x7a,0x37, +0x3a,0x5, 0xbe,0x34,0xff,0x0, 0x40,0x8, 0x7e,0x34,0xff,0x0, 0x7a,0x37,0x3a,0x5, +0x22,0xd2,0xc9,0x75,0xf2,0x30,0x75,0xf3,0x80,0x75,0xf4,0xc, 0x75,0xf5,0x1, 0x6c, +0xaa,0xe5,0xf5,0x54,0x80,0xb4,0x80,0xf9,0xe5,0xf6,0x12,0x5d,0xe7,0xb, 0xa0,0xbe, +0xa0,0xd, 0x40,0xed,0xc2,0xc9,0x22,0x2, 0xb8,0x6a,0x6d,0x11,0x12,0x57,0xe5,0x12, +0xb9,0x19,0x7d,0x3, 0x7e,0x78,0x13,0x8e,0x6c,0x99,0x80,0x17,0x12,0xb8,0xb9,0x7e, +0x50,0x2, 0xac,0x59,0x7f,0x57,0x2d,0xb2,0xb, 0x5a,0x30,0x9d,0x3d,0x59,0x32,0x13, +0xc6,0xb, 0x90,0xbc,0xa9,0x38,0xe5,0x6c,0x99,0x80,0x17,0x12,0xb8,0xb9,0x7e,0x70, +0x2, 0xac,0x79,0x2d,0x3f,0x7d,0x2e,0x12,0xb9,0x24,0xbd,0x1b,0x58,0x2, 0x7d,0x1b, +0xb, 0x90,0xbc,0xa9,0x38,0xe5,0x7d,0x31,0x22,0xa, 0xd9,0x2d,0xd0,0x3e,0xd4,0x7e, +0x1f,0x39,0xda,0x2d,0x3d,0xb, 0x1a,0xd0,0x22,0x12,0x8f,0xce,0x7e,0x34,0xd, 0xc8, +0x7e,0xb3,0x2a,0x6d,0x12,0xb8,0xe5,0x12,0xb8,0x67,0x7a,0x37,0x39,0xd7,0x74,0x1, +0x7a,0xb3,0x16,0x91,0x22,0x7a,0xb3,0x24,0xf2,0x7e,0x53,0x2a,0x6e,0x7a,0x53,0x24, +0xf3,0x7a,0x37,0x24,0xfa,0xe4,0x7a,0xb3,0x24,0xf4,0x7a,0xb3,0x24,0xf5,0x7e,0x34, +0x40,0x0, 0x7a,0x37,0x24,0xf6,0x7e,0x34,0x0, 0x20,0x12,0xb9,0x10,0x2, 0xd, 0x7, +0x7a,0x37,0x24,0xfc,0x7e,0x8, 0x24,0xf2,0x22,0xa, 0x2b,0x2e,0x24,0x0, 0x3, 0xa, +0x3a,0xad,0x32,0x22,0xb, 0x1a,0xc0,0x7d,0x3d,0x9d,0x3c,0x12,0x21,0xa, 0x7d,0xb3, +0x22,0xca,0x79,0x7c,0xfb,0x7e,0x8, 0x1f,0x34,0x12,0xb9,0xa7,0x7e,0xa3,0x2a,0x73, +0x7e,0x63,0x2a,0x74,0x6c,0xee,0x80,0x1e,0xa, 0x2e,0x9, 0x72,0x2a,0xdc,0xbe,0x70, +0x1c,0x50,0x11,0xa, 0x27,0x12,0x67,0x43,0x7c,0x7b,0x7e,0xb3,0x2a,0xfb,0xa, 0x27, +0x19,0xb2,0x1f,0x34,0xb, 0xe0,0xbc,0x6e,0x38,0xde,0x6c,0xee,0x80,0x17,0xa, 0x3e, +0x9, 0x73,0x2a,0xb9,0xbe,0x70,0x23,0x50,0xa, 0x7e,0x63,0x2a,0xfb,0xa, 0x27,0x19, +0x62,0x1f,0x50,0xb, 0xe0,0xbc,0xae,0x38,0xe5,0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e, +0x2e,0x14,0x1f,0x34,0x6d,0x0, 0x7c,0xbf,0x7c,0x7e,0x12,0x11,0xf8,0xb, 0xe0,0xbe, +0xe0,0x5, 0x40,0xe7,0xda,0x79,0x22,0x7e,0x34,0x0, 0x46,0x74,0x3f,0x2, 0x20,0xe8, +0xca,0xd8,0xca,0x79,0x7c,0xf7,0x7f,0x70,0x12,0xba,0x42,0x7c,0xeb,0x6c,0xdd,0x80, +0x20,0x74,0x2, 0xac,0xbd,0x7f,0x67,0x2d,0xd5,0xb, 0x6a,0x30,0x6d,0x22,0x74,0x4, +0x2f,0x11,0x14,0x78,0xfb,0xa, 0x1e,0x6d,0x0, 0x12,0x1f,0x7, 0x1b,0x6a,0x30,0xb, +0xd0,0xbc,0xfd,0x38,0xdc,0xda,0x79,0xda,0xd8,0x22,0xca,0x79,0x7f,0x51,0x7f,0x40, +0x7e,0xa3,0x2a,0x74,0xa, 0x3a,0x7e,0xa3,0x2a,0x73,0xa, 0x7a,0x2d,0x73,0x7e,0xd, +0x29,0x7c,0x7f,0x12,0xb9,0xb0,0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x1d,0x29,0x7f, +0x4, 0x12,0x20,0xc3,0x1b,0xfd,0x7e,0xb3,0x2b,0x1, 0xb4,0x1, 0x22,0x6c,0xaa,0x80, +0x1a,0x7e,0x70,0x2, 0xac,0x7a,0x7f,0x5, 0x2d,0x13,0xb, 0xa, 0x20,0x7f,0x4, 0x2d, +0x13,0xb, 0xa, 0x30,0x9d,0x32,0x1b,0xa, 0x30,0xb, 0xa0,0xbc,0xfa,0x38,0xe2,0xda, +0x79,0x22,0x7c,0x7b,0xa5,0xbf,0x0, 0x3, 0x74,0x10,0x22,0xbe,0x70,0x4, 0x38,0x4, +0x6c,0xaa,0x80,0x21,0xbe,0x70,0x8, 0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x70, +0x10,0x38,0x5, 0x7e,0xa0,0x2, 0x80,0xd, 0xbe,0x70,0x20,0x38,0x5, 0x7e,0xa0,0x3, +0x80,0x3, 0x7e,0xa0,0x4, 0xa, 0x47,0x3e,0x44,0x3e,0x44,0x3e,0x44,0x7c,0xba,0x60, +0x5, 0x1e,0x44,0x14,0x78,0xfb,0x7c,0xb9,0x22,0x7c,0xab,0x9f,0x11,0x30,0x0, 0x22, +0x6c,0x99,0x80,0x1a,0xa, 0xf9,0x2d,0xf1,0x7d,0xe0,0x7e,0x7b,0xb0,0x7e,0x78,0x0, +0x1, 0x60,0x5, 0x2f,0x77,0x14,0x78,0xfb,0x4d,0x3f,0x4d,0x2e,0xb, 0x90,0xbc,0xa9, +0x38,0xe2,0x22,0xca,0xf8,0x7e,0xf0,0x19,0x7e,0x8, 0x1f,0x34,0x12,0xbb,0x3b,0x7e, +0x8, 0x1f,0x3c,0x12,0xbb,0x43,0xd2,0x0, 0x7e,0x8, 0x2a,0xdc,0x74,0x19,0x12,0xba, +0x89,0x7e,0x8, 0x1f,0x34,0x7a,0xf, 0x1f,0x58,0x7f,0x1, 0x7a,0x17,0x1f,0x5c,0x7d, +0x32,0x7a,0x37,0x1f,0x5e,0x7e,0x18,0x1f,0x3c,0x7a,0x1f,0x1f,0x64,0x6c,0x77,0x80, +0xe, 0x12,0xbb,0x8b,0x50,0x7, 0x12,0xbb,0x82,0x19,0x51,0x1f,0x3c,0xb, 0x70,0xbc, +0xf7,0x38,0xee,0x12,0xbb,0x28,0xe4,0x12,0xbb,0x30,0xe4,0x12,0xc, 0x9b,0x6d,0x33, +0x7a,0x37,0x1f,0x5c,0x7a,0x37,0x1f,0x5e,0x12,0xbb,0x28,0x74,0x1, 0x12,0xbb,0x30, +0x74,0x1, 0x12,0xc, 0x9b,0xda,0xf8,0x22,0xa9,0xc6,0xea,0x7e,0x8, 0x1f,0x58,0x22, +0x12,0xc, 0x9b,0xa9,0xd6,0xea,0x7e,0x8, 0x1f,0x58,0x22,0x7e,0x34,0x0, 0x8, 0xe4, +0x2, 0x20,0xe8,0x7e,0x34,0x0, 0x1c,0x74,0x3f,0x2, 0x20,0xe8,0x7e,0x8, 0x1f,0x34, +0x12,0xbb,0x43,0x6c,0x77,0x80,0xe, 0x12,0xbb,0x8b,0x50,0x7, 0x12,0xbb,0x82,0x19, +0x51,0x1f,0x34,0xb, 0x70,0x7e,0x53,0x2a,0x6e,0xbc,0x57,0x38,0xea,0xa9,0xc6,0xea, +0x7e,0x8, 0x1f,0x34,0xe4,0x12,0x11,0x38,0xa9,0xd6,0xea,0x7e,0x8, 0x1f,0x34,0x2, +0x11,0x38,0xa, 0x27,0x9, 0x52,0x2b,0x44,0xa, 0x16,0x22,0xa, 0x27,0x9, 0x62,0x2a, +0xdc,0xbe,0x60,0x1c,0x22,0x7e,0x27,0x28,0xa3,0x6d,0x11,0x9d,0x12,0x6c,0xaa,0x80, +0x64,0x30,0x5, 0x2e,0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x5, 0xf8,0x49,0x4, 0x4, +0x0, 0xbd,0x2, 0x8, 0x11,0x7e,0xb3,0x25,0xf6,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3, +0x59,0xf4,0x5, 0xf8,0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, +0x5, 0xf8,0x30,0x7, 0x2e,0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x6, 0x76,0x49,0x4, +0x4, 0x7e,0xbd,0x2, 0x8, 0x11,0x7e,0xb3,0x25,0xf6,0xb4,0x1, 0x16,0x7d,0xf2,0x2d, +0xf3,0x59,0xf4,0x6, 0x76,0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59, +0x4, 0x6, 0x76,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xa, 0xb, 0x7e,0xb3,0x2a,0x73,0xa, +0x4b,0x2d,0x40,0xa, 0xa, 0xbd,0x4, 0x48,0x88,0x22,0xe4,0x6c,0x33,0xa, 0x33,0x19, +0xb3,0x27,0x72,0xb, 0x30,0xa5,0xbb,0x4, 0xf4,0xe4,0x7a,0xb3,0x28,0x84,0x7a,0xb3, +0x28,0x85,0x6d,0x33,0x7a,0x37,0x28,0x86,0x7a,0x37,0x28,0x88,0x7a,0x37,0x28,0x8a, +0x7a,0x37,0x28,0x8e,0x7e,0xd4,0x1f,0x36,0x5e,0xd4,0xff,0xfe,0x6d,0xcc,0x7e,0x1f, +0x13,0x8a,0x7a,0x37,0x1f,0x76,0x7d,0x3d,0x7a,0x37,0x1f,0x7a,0x7e,0x34,0x15,0x9e, +0x7a,0x37,0x1f,0x78,0x7e,0x73,0x2a,0x6d,0x7a,0x73,0x1f,0x73,0x7e,0x73,0x2a,0x6e, +0x7a,0x73,0x1f,0x72,0x7e,0x37,0x2a,0x5c,0x7a,0x37,0x1f,0x7c,0x7e,0x37,0x2a,0x5e, +0x7a,0x37,0x1f,0x7e,0x7e,0x37,0x2a,0x60,0x7a,0x37,0x1f,0x80,0x74,0x1e,0x7a,0xb3, +0x1f,0x74,0x7e,0x73,0x3, 0xfe,0x7a,0x73,0x1f,0x75,0x7e,0x8, 0x1f,0x72,0x7e,0x18, +0x1f,0x82,0x12,0x8, 0x0, 0x7e,0x73,0x1f,0x82,0x7a,0x73,0x28,0x84,0x7e,0x73,0x1f, +0x83,0x7a,0x73,0x28,0x85,0x7e,0x37,0x1f,0x84,0x7a,0x37,0x28,0x86,0x7e,0x37,0x1f, +0x86,0x7a,0x37,0x28,0x88,0x7e,0x37,0x1f,0x8c,0x7a,0x37,0x28,0x8a,0x7e,0x37,0x1f, +0x8e,0x7d,0x23,0x7a,0x53,0x28,0x8c,0xa, 0x36,0x7a,0x73,0x28,0x8d,0x7e,0x37,0x1f, +0x88,0x7a,0x37,0x28,0x8e,0x7e,0x37,0x1f,0x8a,0x7d,0x23,0x7a,0x53,0x28,0x90,0xa, +0x36,0x7a,0x73,0x28,0x91,0x6c,0x33,0x80,0x1d,0x7c,0xb3,0x12,0x76,0xfb,0x74,0x2, +0xac,0xb3,0x49,0x45,0x15,0x9e,0xa, 0x38,0x7c,0x27,0x19,0x25,0x26,0xfa,0x7c,0x29, +0x19,0x25,0x26,0xfb,0xb, 0x30,0x7e,0x23,0x28,0x84,0xbc,0x23,0x38,0xdb,0x6c,0x33, +0x80,0x1b,0x74,0x2, 0xac,0xb3,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0x40,0xa, 0x38,0x7c, +0x27,0x19,0x25,0x27,0x36,0x7c,0x29,0x19,0x25,0x27,0x37,0xb, 0x30,0x7e,0x23,0x28, +0x85,0xbc,0x23,0x38,0xdd,0x22,0x7c,0x7b,0xa, 0x57,0x9e,0x54,0x0, 0x20,0xe, 0x54, +0xe, 0x54,0xe, 0x54,0xe, 0x54,0x7c,0xab,0x7c,0x67,0x5e,0x60,0xf0,0xa5,0xbe,0x20, +0x1d,0x7c,0xb7,0x54,0xf, 0x7e,0x24,0x0, 0x1, 0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb, +0x7e,0x73,0x39,0xfc,0xa, 0x47,0x5d,0x42,0x7e,0x73,0x38,0x33,0x80,0x36,0xa5,0xbe, +0x30,0x18,0x12,0xbd,0xb9,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7e,0x53,0x39,0xfd, +0xa, 0x45,0x5d,0x43,0x7e,0x73,0x38,0x34,0x80,0x1a,0x12,0xbd,0xb9,0x60,0x5, 0x3e, +0x34,0x14,0x78,0xfb,0xa, 0x2a,0x9, 0xb2,0x39,0xfc,0xa, 0x4b,0x5d,0x43,0xa, 0x5a, +0x9, 0x75,0x38,0x35,0xa, 0x57,0x5d,0x54,0x22,0x7c,0xb7,0x54,0xf, 0x7e,0x34,0x0, +0x1, 0x22,0x7e,0xb3,0x2f,0x80,0xb4,0x4, 0x2, 0xd3,0x22,0xc3,0x22,0x7d,0xf2,0x7d, +0xe3,0x7e,0x8, 0x2f,0x80,0x7e,0x34,0x0, 0x28,0xe4,0x12,0x20,0xe8,0x7e,0x8, 0x2b, +0xbf,0x7e,0x34,0x3, 0xc0,0x12,0x20,0xe8,0x7a,0xb3,0x38,0x35,0x7e,0x34,0x13,0x88, +0x7a,0x37,0x2b,0xb7,0x7a,0xe7,0x2f,0x84,0x7a,0xf7,0x2f,0x86,0x7a,0xe7,0x2f,0x88, +0x7a,0xe7,0x2f,0x8c,0x7a,0xe7,0x2f,0x90,0x7a,0xe7,0x2f,0x94,0x7a,0xf7,0x2f,0x8a, +0x7a,0xf7,0x2f,0x8e,0x7a,0xf7,0x2f,0x92,0x7a,0xf7,0x2f,0x96,0x7a,0xe7,0x2b,0xbb, +0x7a,0xf7,0x2b,0xbd,0x7a,0xb3,0x2f,0xa8,0x74,0x2, 0x7a,0xb3,0x2f,0x7f,0x22,0x74, +0xfe,0x7a,0xb3,0x38,0x35,0xe4,0x7a,0xb3,0x2f,0x80,0x22,0xca,0x3b,0xf5,0x2a,0x7f, +0x31,0x7a,0xd, 0x26,0xe4,0x7a,0xb3,0x22,0xf6,0x7a,0xb3,0x22,0xf7,0x7a,0xb3,0x22, +0xf8,0x7e,0x34,0x3, 0xe8,0x7a,0x37,0x22,0xfd,0x74,0x3c,0x7a,0xb3,0x22,0xf5,0x75, +0x2f,0x46,0x75,0x2b,0x0, 0x2, 0xc0,0x38,0x12,0xc0,0x74,0x28,0x1e,0x7e,0x34,0x0, +0x44,0xca,0x39,0x7e,0x71,0x2b,0x74,0x44,0xac,0x7b,0x2e,0x34,0x14,0x6, 0x7e,0x24, +0x0, 0xff,0x7e,0x8, 0x22,0xff,0x12,0x20,0xc3,0x1b,0xfd,0x6d,0x33,0x7a,0x37,0x22, +0xf9,0x7a,0x35,0x30,0x7a,0x37,0x22,0xfb,0x7a,0x35,0x32,0x7a,0x35,0x34,0x7e,0x34, +0x22,0xff,0x7a,0x35,0x36,0x7e,0x34,0x23,0x1f,0x7a,0x35,0x38,0x75,0x2c,0x0, 0x80, +0x59,0xe5,0x2c,0xa, 0x3b,0x7e,0xd, 0x26,0x12,0xc6,0xea,0x2e,0x35,0x36,0x12,0x96, +0xa1,0x7d,0xd3,0x7e,0xc7,0x22,0xfb,0xbd,0xcd,0x58,0x4, 0x7a,0xd7,0x22,0xfb,0xe5, +0x2c,0xa, 0x3b,0x7f,0x3, 0x12,0xc6,0xea,0x2e,0x35,0x38,0x12,0x96,0xa1,0x7d,0xc3, +0x7e,0x35,0x32,0xbd,0x3c,0x58,0x3, 0x7a,0xc5,0x32,0x7e,0x37,0x22,0xf9,0x2d,0x3d, +0x7a,0x37,0x22,0xf9,0x7d,0x3c,0x2e,0x35,0x30,0x7a,0x35,0x30,0x2d,0xcd,0x7e,0x35, +0x34,0xbd,0x3c,0x58,0x3, 0x7a,0xc5,0x34,0x5, 0x2c,0xe5,0x2a,0xbe,0xb1,0x2c,0x38, +0xa0,0xe5,0x2a,0xb4,0xa, 0x2d,0x7e,0x37,0x22,0xfb,0xbe,0x34,0x0, 0x40,0x48,0xc, +0x7e,0x25,0x32,0xbe,0x24,0x0, 0x40,0x48,0x3, 0x2, 0xc0,0x36,0xbe,0x34,0x0, 0x60, +0x8, 0x3, 0x2, 0xc0,0x36,0x7e,0x35,0x32,0xbe,0x34,0x0, 0x60,0x8, 0x3, 0x2, 0xc0, +0x36,0x80,0x2b,0x7e,0x37,0x22,0xfb,0xbe,0x34,0x0, 0x20,0x8, 0xc, 0x7e,0x25,0x32, +0xbe,0x24,0x0, 0x20,0x8, 0x3, 0x2, 0xc0,0x36,0xbe,0x34,0x0, 0x30,0x8, 0x3, 0x2, +0xc0,0x36,0x7e,0x35,0x32,0xbe,0x34,0x0, 0x30,0x8, 0x3, 0x2, 0xc0,0x36,0x7e,0xa3, +0x39,0x42,0x74,0xc, 0xa4,0xbe,0x57,0x22,0xf9,0x58,0x3, 0x2, 0xc0,0x36,0x7e,0xa3, +0x39,0x43,0x74,0xc, 0xa4,0xbe,0x55,0x30,0x58,0x3, 0x2, 0xc0,0x36,0x7e,0x15,0x36, +0x6d,0x0, 0x7e,0x1d,0x26,0xe5,0x2a,0x12,0xc0,0x7c,0x7a,0xb3,0x22,0xf4,0x7e,0x15, +0x38,0x6d,0x0, 0x7f,0x13,0xe5,0x2a,0x12,0xc0,0x7c,0xf5,0x2d,0x7e,0x73,0x22,0xf5, +0xbe,0x73,0x22,0xf4,0x28,0x3, 0x2, 0xc0,0x36,0xbe,0x71,0x2d,0x38,0x78,0xe5,0x2d, +0x7e,0x31,0x2d,0xac,0x3b,0x1a,0x2, 0x1a,0x0, 0x7e,0x73,0x22,0xf4,0xac,0x77,0x1a, +0x26,0x1a,0x24,0x2f,0x10,0xe5,0x2d,0xa, 0x5b,0x6d,0x44,0x7e,0x33,0x22,0xf4,0xa, +0x13,0x6d,0x0, 0x2f,0x2, 0x12,0x1f,0x7, 0x7c,0xb7,0xf5,0x2e,0xe5,0x2f,0xbe,0xb1, +0x2e,0x38,0x43,0x7e,0x37,0x22,0xfb,0x2e,0x35,0x32,0x2e,0x35,0x34,0x7a,0x35,0x3a, +0xe5,0x2e,0xa, 0x2b,0x7e,0x34,0x0, 0x64,0x9d,0x32,0x3e,0x34,0x2e,0x35,0x3a,0x7a, +0x35,0x3a,0x7e,0x37,0x22,0xfd,0xbe,0x35,0x3a,0x8, 0x1b,0x7e,0x35,0x3a,0x7a,0x37, +0x22,0xfd,0xe5,0x2e,0x7a,0xb3,0x22,0xf7,0x7e,0x73,0x23,0x41,0x7a,0x73,0x22,0xf8, +0xe5,0x2b,0x7a,0xb3,0x22,0xf6,0x5, 0x2b,0x12,0xc0,0x74,0x28,0x3, 0x2, 0xbe,0x68, +0x7e,0xa3,0x22,0xf7,0xbe,0xa1,0x2f,0x40,0x20,0x7e,0xb3,0x22,0xf8,0xbe,0xb0,0x0, +0x28,0x17,0xbe,0xb0,0xff,0x50,0x12,0x7e,0x73,0x22,0xf6,0xa, 0x37,0xb, 0x34,0x7a, +0x73,0x39,0x3f,0x7a,0xb3,0x39,0x41,0x80,0x6, 0x74,0x7c,0x7a,0xb3,0x39,0x3f,0x7c, +0xba,0xda,0x3b,0x22,0x7e,0x73,0x3a,0x2, 0xbe,0x71,0x2b,0x22,0xca,0x3b,0x7c,0xfb, +0x7f,0x61,0x7f,0x40,0x9f,0x11,0x7f,0x51,0x7f,0x71,0x7a,0x1d,0x3c,0x7a,0x1d,0x40, +0x7a,0x1d,0x44,0xbe,0xf0,0xa, 0x78,0x6, 0x7e,0x54,0x1, 0x3c,0x80,0x4, 0x7e,0x54, +0x2, 0x35,0x7a,0x57,0x23,0x43,0x6c,0xee,0x80,0x60,0xa, 0x5e,0x7f,0x14,0x12,0xc1, +0xcd,0x7a,0x55,0x4a,0xa, 0x5e,0x7f,0x16,0x12,0xc1,0xcd,0x7a,0x55,0x48,0x7e,0x35, +0x48,0x12,0x97,0xc5,0x2f,0x50,0x7e,0x65,0x4a,0x7d,0x16,0x1a,0x2, 0x1a,0x0, 0x2f, +0x70,0x12,0x97,0xc5,0x12,0xc1,0xc3,0x7e,0x1d,0x3c,0x2f,0x10,0x7a,0x1d,0x3c,0x7d, +0x16,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x4a,0x12,0xc1,0xc3,0x7e,0x1d,0x40,0x2f,0x10, +0x7a,0x1d,0x40,0x7e,0x15,0x4a,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x48,0x12,0xc1,0xc3, +0x7e,0x1d,0x44,0x2f,0x10,0x7a,0x1d,0x44,0xb, 0xe0,0xbc,0xfe,0x38,0x9c,0xa, 0xdf, +0x6d,0xcc,0x7f,0x15,0x7f,0x6, 0x12,0x1f,0x58,0x7f,0x51,0x7f,0x17,0x7f,0x6, 0x12, +0x1f,0x58,0x7f,0x71,0x7e,0x94,0x0, 0x64,0x7e,0x1d,0x3c,0x7d,0x19,0x12,0x1e,0xfc, +0x7e,0x87,0x23,0x43,0x7d,0x18,0x7d,0xd8,0x1a,0x12,0x1a,0xc2,0x7f,0x6, 0x12,0x1f, +0x58,0x7a,0x1d,0x3c,0x7e,0x1d,0x40,0x7d,0x19,0x12,0x1e,0xfc,0x7f,0x6, 0x12,0x1f, +0x58,0x7a,0x1d,0x40,0x7e,0x1d,0x44,0x7d,0x19,0x12,0x1e,0xfc,0x7d,0x18,0x1a,0x2, +0x1a,0x0, 0x12,0x1f,0x58,0x7a,0x1d,0x44,0x7f,0x15,0x7f,0x7, 0x12,0x1e,0xeb,0x7e, +0x6d,0x44,0x9f,0x61,0x7f,0x15,0x7f,0x5, 0x12,0x1e,0xeb,0x7e,0x5d,0x3c,0x9f,0x51, +0x7f,0x17,0x7f,0x7, 0x12,0x1e,0xeb,0x7e,0x7d,0x40,0x9f,0x71,0xbe,0x58,0x0, 0x0, +0x68,0x6, 0xbe,0x78,0x0, 0x0, 0x78,0x6, 0x7e,0x44,0x0, 0x64,0x80,0x18,0x7f,0x16, +0x7d,0x19,0x12,0x1e,0xfc,0x7f,0x5, 0x12,0x1f,0x58,0x7f,0x6, 0x12,0x1e,0xeb,0x7f, +0x7, 0x12,0x1f,0x58,0x7d,0x43,0xbe,0x44,0x0, 0x0, 0x18,0x2, 0x6d,0x44,0x7c,0xb9, +0xda,0x3b,0x22,0x1a,0x26,0x1a,0x24,0x12,0x1e,0xeb,0x7f,0x1, 0x22,0x2d,0x35,0x7e, +0x1b,0x70,0xa, 0x57,0x22,0xca,0xf8,0x7f,0x51,0x7f,0x40,0x7e,0x37,0x2f,0x90,0x7a, +0x35,0x2a,0x7e,0x37,0x2f,0x8e,0x7a,0x35,0x2c,0x7e,0x37,0x2f,0x9c,0x7a,0x35,0x26, +0x7e,0x37,0x2f,0x9e,0x7a,0x35,0x28,0x6c,0xff,0x80,0x1e,0x7e,0x34,0x0, 0x26,0x7e, +0x14,0x0, 0x2f,0x74,0x9, 0x12,0x1f,0x8c,0x74,0x2, 0xac,0xbf,0x7f,0x4, 0x2d,0x15, +0x7f,0x15,0x2d,0x35,0x12,0xc2,0x24,0xb, 0xf0,0x7e,0x73,0x39,0x40,0xbc,0x7f,0x38, +0xda,0xda,0xf8,0x22,0x7f,0x71,0x7f,0x60,0x7e,0x35,0x2f,0xbe,0x34,0x0, 0x0, 0x38, +0x7, 0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x2f,0x7e,0x35,0x31,0xbe,0x34,0x0, 0x0, 0x38, +0x7, 0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x31,0xb, 0x6a,0x30,0x9e,0x35,0x33,0x6d,0x22, +0x7e,0x33,0x39,0x42,0x12,0xc2,0x79,0x7e,0x15,0x2f,0x12,0x1f,0x5, 0x1b,0x6a,0x30, +0xb, 0x7a,0x30,0x9e,0x35,0x35,0x6d,0x22,0x7e,0x33,0x39,0x43,0x12,0xc2,0x79,0x7e, +0x15,0x31,0x12,0x1f,0x5, 0x1b,0x7a,0x30,0x22,0xa, 0x13,0x6d,0x0, 0x2, 0x1e,0xeb, +0xca,0x79,0x6c,0xaa,0x7e,0x90,0x2, 0xac,0x9a,0x7f,0x70,0x2d,0xf4,0xb, 0x7a,0xf0, +0x7d,0x7f,0x7c,0xbf,0xa, 0xfa,0x19,0xbf,0x39,0x44,0x7f,0x71,0x2d,0xf4,0xb, 0x7a, +0x40,0x7c,0xb9,0xa, 0x4a,0x19,0xb4,0x39,0x64,0xb, 0xa0,0xbe,0xa0,0x20,0x40,0xd4, +0x7e,0x8, 0x39,0x44,0x7e,0x18,0x39,0x64,0x74,0x20,0x12,0xbe,0x3b,0xda,0x79,0x22, +0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x73,0x39,0x40,0xbe,0x70,0x20,0x40,0x52,0x7e, +0xf0,0x2, 0x80,0x3c,0xa, 0x3f,0x6d,0x22,0x74,0x5, 0x2f,0x11,0x14,0x78,0xfb,0x7e, +0x33,0x39,0x40,0xa, 0x13,0x6d,0x0, 0x12,0x1f,0x7, 0x7c,0xe7,0xbe,0xe0,0x2, 0x50, +0x3, 0x7e,0xe0,0x2, 0xa, 0x6f,0x1b,0x64,0xa, 0x3e,0x1b,0x34,0x7c,0xc7,0x7f,0x5, +0x7c,0xbd,0x12,0xc3,0x2a,0x7f,0x6, 0x7c,0xbd,0x7c,0x7c,0x12,0xc3,0x2a,0xb, 0xf0, +0x7e,0x73,0x39,0x40,0xbc,0x7f,0x50,0xbc,0x7f,0x5, 0x7f,0x16,0x12,0xc2,0x80,0x80, +0x6, 0x74,0x7e,0x7a,0xb3,0x39,0x3f,0xda,0x3b,0x22,0x7c,0x97,0x7c,0xab,0x7f,0x10, +0x7e,0x30,0x2, 0xac,0x3a,0x2d,0x13,0x7d,0x2, 0xb, 0xa, 0x10,0x7e,0x10,0x2, 0xac, +0x19,0x7f,0x71,0x2d,0xf0,0xb, 0x7a,0x0, 0x7c,0x21,0xa5,0xba,0x0, 0x14,0xa, 0x3, +0x1b,0x7a,0x0, 0xbc,0x9a,0x68,0x24,0x6d,0x44,0x74,0x2, 0xa4,0x2d,0x35,0x1b,0x1a, +0x40,0x22,0xbc,0x9a,0x68,0x15,0xa, 0x2, 0xa, 0x13,0x2d,0x10,0xe, 0x14,0x1b,0x7a, +0x10,0x6d,0x11,0x74,0x2, 0xa4,0x2d,0x35,0x1b,0x1a,0x10,0x22,0xca,0x3b,0x7f,0x71, +0x7e,0x60,0x1, 0xb, 0xa, 0x20,0xb, 0x7a,0x50,0x7c,0x4b,0x7a,0x53,0x22,0xf4,0x7a, +0x43,0x23,0xe4,0x7e,0x70,0x1, 0x7e,0xa0,0x1, 0x81,0x9d,0x7e,0x90,0x2, 0xac,0x9a, +0x7f,0x60,0x2d,0xd4,0xb, 0x6a,0xd0,0x7d,0x7d,0x7c,0xbf,0xf5,0x26,0x7f,0x67,0x2d, +0xd4,0xb, 0x6a,0x40,0xa, 0xd5,0xa, 0xbb,0x7d,0xab,0x9d,0xad,0x7d,0x7a,0x7c,0x8f, +0xbe,0x80,0x0, 0x58,0x5, 0x6e,0x80,0xff,0xb, 0x80,0xa, 0xa4,0xa, 0x79,0x9d,0x7a, +0xbe,0xf0,0x0, 0x58,0x5, 0x6e,0xf0,0xff,0xb, 0xf0,0xbe,0x80,0x2, 0x58,0x7, 0xbe, +0xf0,0x2, 0x58,0x2, 0x81,0x9b,0xbe,0x60,0x0, 0x18,0x2, 0x81,0x83,0xbe,0x70,0xec, +0x28,0x2, 0x81,0xa7,0xbe,0x80,0x8, 0x58,0x5, 0xbe,0xf0,0x8, 0x48,0x61,0xa, 0xa7, +0xb, 0xa4,0x7d,0x6a,0x7c,0x7d,0xa, 0xa5,0x2d,0xab,0x12,0xc4,0xeb,0x19,0xba,0x22, +0xf4,0xa, 0xd9,0xa, 0xa4,0x2d,0xad,0x12,0xc4,0xeb,0x19,0xba,0x23,0xe4,0x9, 0xba, +0x22,0xf4,0xa, 0xdb,0xa, 0xc5,0x2d,0xcd,0xe, 0xc4,0x7d,0x6c,0x7c,0xbd,0xa, 0xc7, +0x19,0xbc,0x22,0xf3,0x9, 0xbc,0x23,0xe4,0xa, 0xcb,0xa, 0xa4,0x2d,0xac,0x12,0xc4, +0xeb,0x19,0xba,0x23,0xe3,0x2d,0xdb,0x12,0xc4,0xe2,0x19,0xbd,0x22,0xf5,0xa, 0xd9, +0x12,0xc4,0xe0,0x19,0xbd,0x23,0xe5,0xb, 0xd5,0x7d,0x6d,0x7c,0x7d,0x80,0x24,0xbe, +0x80,0x4, 0x58,0x5, 0xbe,0xf0,0x4, 0x48,0x1a,0xe5,0x26,0xa, 0xcb,0xa, 0xd5,0x12, +0xc4,0xe0,0x19,0xbd,0x22,0xf4,0xa, 0xc9,0xa, 0xd4,0x12,0xc4,0xe0,0x19,0xbd,0x23, +0xe4,0xb, 0x70,0xbe,0x70,0xf0,0x50,0x1f,0x7e,0x51,0x26,0x7c,0x49,0xe5,0x26,0xa, +0xd7,0x19,0xbd,0x22,0xf4,0x19,0x9d,0x23,0xe4,0xb, 0x70,0xb, 0xa0,0x7e,0xb3,0x39, +0x40,0xbc,0xba,0x28,0x2, 0x61,0x9b,0x7a,0x73,0x39,0x40,0x7e,0xa0,0x1, 0x80,0x25, +0xa, 0x3a,0x9, 0xb3,0x22,0xf4,0xa, 0x2b,0x7e,0x70,0x2, 0xac,0x7a,0x7f,0x60,0x2d, +0xd3,0x1b,0x6a,0x20,0xa, 0x2a,0x9, 0xb2,0x23,0xe4,0xa, 0x4b,0x2d,0x3f,0x7d,0x2e, +0x1b,0x1a,0x40,0xb, 0xa0,0x7e,0xb3,0x39,0x40,0xbc,0xba,0x38,0xd3,0xda,0x3b,0x22, +0x2d,0xdc,0xe, 0xd4,0x7d,0x6d,0x7c,0xbd,0xa, 0xd7,0x22,0xe, 0xa4,0x7d,0x6a,0x7c, +0xbd,0xa, 0xa7,0x22,0x7d,0x13,0x3e,0x14,0x3e,0x14,0x3e,0x14,0x7e,0x37,0x39,0xe3, +0x9e,0x37,0x39,0xdf,0x12,0x21,0xa, 0xbd,0x31,0x38,0x12,0x7e,0x37,0x39,0xe5,0x9e, +0x37,0x39,0xe1,0x12,0x21,0xa, 0xbd,0x31,0x38,0x3, 0x74,0x1, 0x22,0xe4,0x22,0xca, +0x79,0x6c,0xaa,0x6d,0x11,0x7d,0x41,0x7d,0x1, 0x7e,0xe3,0x2a,0x2, 0x7e,0xf3,0x2a, +0x3, 0x7e,0x73,0x39,0xde,0x4c,0x77,0x68,0x11,0x7e,0x27,0x39,0xe7,0x4d,0x22,0x78, +0x2, 0xc1,0x10,0xbe,0xe0,0x1, 0x28,0x2, 0xc1,0x10,0xbe,0xe0,0x1, 0x78,0x38,0xbe, +0x70,0x4, 0x78,0x2, 0xc1,0x10,0x7e,0x63,0x34,0x88,0x7e,0x10,0x9, 0xac,0x16,0x49, +0x40,0x29,0x8, 0x49,0x0, 0x29,0xa, 0xbe,0x44,0x0, 0x6e,0x50,0x2, 0xc1,0x10,0xbe, +0x44,0x3, 0x7a,0x28,0x2, 0xc1,0x10,0xbe,0x4, 0x0, 0x6e,0x50,0x2, 0xc1,0x10,0xbe, +0x4, 0x6, 0xc2,0x28,0x2, 0xc1,0x10,0x7c,0xb7,0x14,0x68,0x2b,0x14,0x68,0x51,0x14, +0x68,0x25,0x14,0x68,0x78,0xb, 0xb2,0x78,0x77,0xbe,0xe0,0x1, 0x68,0x2, 0xc1,0x1f, +0x4c,0xff,0x78,0x7b,0x74,0x1, 0x7a,0xb3,0x39,0xde,0x12,0xc6,0x35,0x7e,0x24,0x1, +0xf4,0x7a,0x27,0x39,0xe7,0x80,0x68,0x4c,0xee,0x78,0x17,0xa5,0xbf,0x1, 0x7, 0x74, +0x2, 0x12,0xc6,0x2c,0x80,0x41,0x74,0x4, 0x7a,0xb3,0x39,0xde,0x7e,0x34,0x0, 0x64, +0x80,0x35,0x12,0xc6,0x3e,0x7e,0x34,0x0, 0xa, 0x12,0xc6,0x24,0x68,0x32,0x80,0x3f, +0xbe,0xe0,0x1, 0x78,0x3a,0x4c,0xff,0x78,0x36,0x12,0xc6,0x3e,0x7e,0x37,0x39,0xe7, +0xbe,0x34,0x1, 0xe0,0x38,0x1a,0x7e,0x34,0x0, 0x14,0x12,0xc6,0x24,0x68,0x11,0x12, +0xc6,0x35,0x74,0x3, 0x12,0xc6,0x2c,0x7a,0x37,0x39,0xe7,0x80,0x12,0x7e,0xa0,0x24, +0xe4,0x7a,0xb3,0x39,0xde,0x6d,0x33,0x7a,0x37,0x39,0xe7,0x7c,0xba,0x80,0x2, 0x7c, +0xba,0xda,0x79,0x22,0x12,0xc4,0xf4,0xa, 0x1b,0x4d,0x11,0x22,0x7a,0xb3,0x39,0xde, +0x7e,0x34,0x1, 0xf4,0x22,0x7a,0x47,0x39,0xdf,0x7a,0x7, 0x39,0xe1,0x22,0x7a,0x47, +0x39,0xe3,0x7a,0x7, 0x39,0xe5,0x22,0x7e,0x11,0x2b,0xac,0x1f,0x3e,0x4, 0x7e,0x30, +0x2, 0xac,0x3e,0x2d,0x10,0x7e,0x1d,0x30,0x2d,0x31,0xb, 0x1a,0x20,0x7a,0x27,0x24, +0xf2,0x74,0x2, 0xac,0xbe,0x49,0x35,0x34,0x0, 0xad,0x23,0x74,0xc, 0x22,0x74,0x1, +0x7a,0xb3,0x2b,0x1, 0x7a,0xb3,0x2b,0x1d,0x22,0x3e,0x44,0x7e,0x1f,0x13,0x8a,0x2d, +0x34,0x1b,0x1a,0x50,0x22,0xa, 0x47,0x7f,0x70,0x2d,0xf4,0x7e,0x7b,0x60,0x22,0x74, +0x6, 0x7d,0x30,0x12,0x2f,0x58,0x6c,0x11,0x22,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xb3, +0x1f,0x34,0x22,0x74,0x1, 0x12,0x13,0xde,0xe4,0x2, 0x0, 0x1e,0x74,0x2, 0x12,0x0, +0x1e,0x7e,0x8, 0x6, 0xfc,0x22,0x7a,0x91,0x82,0x7a,0x81,0x83,0xe4,0x93,0x22,0xb, +0xa, 0x30,0x2d,0x32,0x1b,0xa, 0x30,0x22,0x6d,0x33,0xe4,0x6c,0x55,0x2, 0x13,0x1, +0x7e,0x73,0x38,0xbe,0x7a,0x73,0x2b,0x20,0x22,0x7e,0xb3,0x38,0xe1,0x7e,0x34,0x0, +0x4, 0x22,0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0xfc,0x22,0x2d,0x13,0x7e,0xb, 0x50,0xa, +0x25,0x22,0x7e,0x8, 0x2a,0x6d,0x2, 0x0, 0x2e,0x12,0x2f,0x58,0x74,0x6, 0x7d,0x30, +0x22,0x7e,0xb3,0x28,0xa8,0xbe,0xb0,0x1, 0x22,0xe4,0x12,0x13,0xde,0x2, 0x13,0x96, +0xc7,0x10,0x38,0xef,0xa2,0x5d,0xa, 0x3b, diff --git a/drivers/input/touchscreen/ft5435/HQ_AL1512_C6_FT5435_Ofilm0x51_Ver0a_20170119_app.i b/drivers/input/touchscreen/ft5435/HQ_AL1512_C6_FT5435_Ofilm0x51_Ver0a_20170119_app.i new file mode 100644 index 0000000000000..d5bf7cda4de03 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/HQ_AL1512_C6_FT5435_Ofilm0x51_Ver0a_20170119_app.i @@ -0,0 +1,3186 @@ +0x2, 0x1f,0xd2,0x2, 0xb6,0x1a,0xeb,0xaa,0x8, 0x22,0x22,0x2, 0x0, 0x49,0xb4,0x2, +0x4, 0xa9,0xb7,0xea,0x22,0x24,0xff,0xa9,0x97,0xea,0x22,0x2, 0x50,0x32,0xb4,0x2, +0x4, 0xa9,0xb6,0xea,0x22,0x24,0xff,0xa9,0x96,0xea,0x22,0x2, 0x68,0x4, 0x7f,0x60, +0xa9,0xc2,0xea,0x74,0x1, 0x12,0x13,0x96,0x7f,0x6, 0x12,0x5, 0xb4,0x7f,0x6, 0x2, +0x9, 0xa1,0x22,0x2, 0x68,0x20,0x2, 0x26,0x11,0x32,0x32,0x2, 0x0, 0x4a,0x12,0x10, +0xa2,0x2, 0x13,0x79,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x2, 0x0, 0x76,0x1, 0x2, +0x4, 0x8, 0x10,0x20,0x40,0x80,0xf5,0xfd,0xe5,0xfe,0x22,0x2, 0x0, 0x5a,0xd2,0x1, +0x2, 0x37,0xa6,0x2, 0x10,0x52,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b, +0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0xf, 0x7e,0xf, 0x39,0xc9, +0x69,0x30,0x0, 0x4, 0x7a,0x73,0x39,0xd9,0x7e,0x73,0x39,0xd9,0xa, 0x37,0x5e,0x34, +0x0, 0x4, 0x68,0x4, 0xd2,0xe, 0x80,0x2, 0xc2,0xe, 0x7e,0x34,0x0, 0x1f,0x79,0x30, +0x0, 0x4, 0xc2,0xc3,0x12,0x12,0x9e,0x12,0x69,0x5, 0x7e,0x1f,0x39,0xc9,0x69,0x31, +0x0, 0x2, 0x5e,0x34,0x0, 0x40,0x68,0x2e,0x6c,0xaa,0x7e,0x10,0x2, 0xac,0x1a,0x7e, +0x1f,0x39,0xc9,0x7f,0x71,0x2d,0xf0,0x69,0x17,0x0, 0x9c,0x59,0x10,0x39,0xcd,0xb, +0xa0,0xbe,0xa0,0x3, 0x78,0xe4,0x69,0x11,0x0, 0xa4,0x7a,0x17,0x39,0xd5,0x69,0x31, +0x0, 0xa2,0x7a,0x37,0x39,0xd3,0xa9,0xc1,0xc4,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda, +0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7d,0x13, +0x7e,0x1f,0x39,0xf8,0x1b,0x1a,0x10,0xc2,0xc6,0xd2,0xee,0x22,0xff,0xff,0x54,0x2c, +0xca,0x79,0x7f,0x50,0x7c,0xeb,0x7e,0x34,0x0, 0x24,0x7e,0x8, 0x0, 0x2c,0x7e,0x24, +0x0, 0x2, 0x12,0x63,0x62,0xe5,0x2c,0xbe,0xb0,0x0, 0x38,0x2, 0x21,0x4a,0xe5,0x2c, +0xbe,0xb0,0x76,0x28,0x2, 0x21,0x4a,0x7e,0xe1,0x2c,0xbe,0xe0,0x76,0x38,0x2, 0x21, +0x78,0x7e,0x34,0x1e,0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x79,0x35,0x0, +0x4, 0xbe,0xe0,0x81,0x68,0x2, 0x21,0x71,0x74,0x23,0x7a,0x5b,0xb0,0x74,0x1c,0x61, +0x84,0x74,0x1, 0x7a,0x5b,0xb0,0x61,0x84,0x7c,0xbe,0x14,0xbe,0xb0,0x75,0x40,0x2, +0x61,0x33,0x7e,0xa0,0x3, 0xa4,0x2e,0x54,0x1, 0x8c,0x89,0x54,0x2, 0x2, 0xfb,0x2, +0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xed,0x2, 0x2, +0xfb,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x25,0x2, 0x3, 0x33,0x2, 0x3, 0x9, 0x2, +0x2, 0xfb,0x2, 0x3, 0x17,0x2, 0x3, 0x17,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x41,0xfb,0x7e,0x34,0x1e, +0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1d,0xe2,0x61,0x3f,0x7e,0x34,0x1e,0x19,0x79, +0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x61,0x3f,0x7e,0x34,0x1e,0x19,0x79,0x35,0x0, +0x2, 0x7e,0x34,0x1d,0xb2,0x61,0x3f,0x7e,0x34,0x1d,0x96,0x79,0x35,0x0, 0x2, 0x7e, +0x34,0x1d,0xc6,0x61,0x3f,0x7e,0x34,0x1e,0xa, 0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1d, +0xf1,0x61,0x3f,0x7e,0x34,0x1e,0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x79, +0x35,0x0, 0x4, 0xbe,0xe0,0x16,0x28,0x2, 0x61,0x4e,0x7c,0xfe,0x61,0x62,0x7e,0xf0, +0x16,0xbe,0xe0,0x72,0x50,0x2, 0x61,0x62,0xa, 0x3e,0x9e,0x34,0x0, 0x72,0xb, 0x34, +0x2c,0xf7,0x7e,0x70,0x3, 0xac,0x7f,0x7d,0x23,0x2e,0x24,0x1e,0x69,0x7a,0x51,0x82, +0x7a,0x41,0x83,0xe4,0x93,0x7a,0x5b,0xb0,0x2e,0x34,0x1e,0x6a,0x7a,0x71,0x82,0x7a, +0x61,0x83,0xe4,0x93,0x39,0xb5,0x0, 0x1, 0xda,0x79,0x22,0xca,0x3b,0x7f,0x30,0x74, +0x1, 0x12,0x13,0xde,0x29,0x73,0x0, 0xf3,0x2e,0x70,0xff,0x92,0x1, 0x29,0xb3,0x0, +0xf4,0x12,0x13,0xaf,0x7f,0x3, 0x12,0xd, 0x72,0x7f,0x3, 0x12,0x6, 0xba,0x29,0x73, +0x0, 0xa, 0xa, 0x37,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x24,0x29,0x73,0x0, 0xa3, +0xa, 0x27,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24, +0x69,0x33,0x0, 0xff,0x4d,0x32,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x2, 0x29,0x73, +0x0, 0xa, 0xa, 0x47,0x29,0x73,0x0, 0x5, 0xa, 0x57,0x9d,0x54,0xf5,0x34,0x29,0xb3, +0x0, 0xa5,0x70,0xb, 0x29,0xb3,0x0, 0xf8,0x29,0x73,0x0, 0xf7,0x12,0xb, 0xad,0x29, +0x73,0x0, 0xa5,0x2e,0x70,0xff,0x92,0x1, 0xe5,0x34,0x12,0xb, 0x1e,0x69,0x33,0x0, +0xfd,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x28,0x69,0x23,0x0, 0xfb,0x3e,0x24,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x29,0x73,0x0, 0xfa,0xa, 0x37,0x2d, +0x32,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x2a,0x29,0x73,0x0, 0xf9,0xa, 0x37,0x7e, +0xf, 0x39,0xc9,0x79,0x30,0x0, 0x2c,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x39,0xc9,0x79, +0x30,0x0, 0x34,0x7e,0x34,0x1, 0xb, 0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x2e,0x29, +0x73,0x0, 0x5, 0xa, 0x37,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x10,0x69,0x33,0x0, +0xa8,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x1c,0x69,0x33,0x0, 0xaa,0x7e,0xf, 0x39, +0xc9,0x79,0x30,0x0, 0x1e,0x6c,0xaa,0x7e,0x50,0x2, 0xac,0x5a,0x69,0x13,0x1, 0x1, +0x2d,0x12,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0x7e,0xf, 0x39,0xc9,0x2d,0x12,0x79, +0x30,0x0, 0x44,0xb, 0xa0,0xbe,0xa0,0xc, 0x40,0xdd,0xda,0x3b,0x22,0xca,0xf8,0x7f, +0x70,0x7e,0x7b,0xf0,0x29,0x77,0x0, 0x1, 0xbc,0x7f,0x28,0x2, 0x7c,0xf7,0x69,0x17, +0x0, 0x6, 0x6d,0x0, 0x7e,0x34,0x0, 0xf2,0x74,0xff,0x12,0x20,0xe8,0x7f,0x7, 0x12, +0xe, 0xed,0xa9,0xd6,0xcb,0x6c,0xaa,0x80,0x2d,0x6c,0x77,0x80,0x1f,0x7e,0x10,0xb, +0xac,0x1a,0xa, 0x17,0x2d,0x1, 0x3e,0x4, 0x69,0x17,0x0, 0x6, 0x2d,0x10,0x6d,0x0, +0xb, 0xa, 0x20,0x6e,0x24,0xff,0xff,0x1b,0xa, 0x20,0xb, 0x70,0x29,0x67,0x0, 0x1, +0xbc,0x67,0x38,0xd9,0xb, 0xa0,0x7e,0x7b,0x60,0xbc,0x6a,0x38,0xcc,0x69,0x37,0x0, +0x6, 0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, 0x4, 0x7c,0x4f,0x6c,0x55,0xa, 0x3f,0x2d, +0x32,0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b, +0x1a,0x10,0x7e,0x34,0x0, 0xd0,0x12,0xf, 0x45,0x6c,0xaa,0xbe,0xa0,0x4, 0x50,0x18, +0x7e,0x70,0x4, 0xac,0x7a,0x7c,0xb7,0x7e,0x1f,0x33,0xfc,0x69,0x41,0x0, 0x26,0x60, +0x42,0x1e,0x44,0x14,0x78,0xfb,0x80,0x3b,0xbe,0xa0,0x8, 0x50,0x1b,0xa, 0x3a,0x1b, +0x36,0x3e,0x34,0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x33,0xfc,0x69,0x41,0x0, 0x28,0x60, +0x22,0x1e,0x44,0x14,0x78,0xfb,0x80,0x1b,0xa, 0x3a,0x9e,0x34,0x0, 0x8, 0x3e,0x34, +0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x33,0xfc,0x69,0x41,0x0, 0x2a,0x60,0x5, 0x1e,0x44, +0x14,0x78,0xfb,0x5e,0x44,0x0, 0xf, 0x7e,0x50,0x2, 0xac,0x5a,0x69,0x37,0x0, 0x6, +0x2d,0x32,0x6d,0x22,0x1b,0x1a,0x40,0xb, 0xa0,0xbe,0xa0,0xb, 0x40,0x8d,0xa9,0xc6, +0xcb,0xda,0xf8,0x22,0x29,0x70,0x0, 0x96,0x29,0x90,0x0, 0x98,0x29,0x60,0x0, 0x97, +0x29,0x80,0x0, 0x8d,0xbe,0x80,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe,0x80,0x8, +0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x80,0x10,0x38,0x5, 0x7e,0xa0,0x2, 0x80, +0xd, 0xbe,0x80,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, 0xbe,0x90, +0x3, 0x28,0x3, 0x7e,0x90,0x3, 0xbe,0x80,0x3f,0x28,0x3, 0x7e,0x80,0x3f,0xbe,0x60, +0x1, 0x28,0x3, 0x7e,0x60,0x1, 0xbe,0x70,0x2, 0x28,0x2, 0x6c,0x77,0xa, 0x28,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x7c,0x89,0x6c,0x99,0x3e,0x44,0x3e, +0x44,0x3e,0x44,0x2d,0x42,0xa, 0x26,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d, +0x24,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x2d,0x32,0x7e,0x7f,0x39,0xf8,0x79,0x37,0x0, +0x2, 0x29,0xb0,0x0, 0x8c,0x7c,0x4b,0x6c,0x55,0x29,0xb0,0x0, 0x8b,0xa, 0x3b,0x2d, +0x32,0x7e,0x7f,0x39,0xc1,0x79,0x37,0x0, 0x80,0x69,0x30,0x0, 0xa0,0x7e,0x7f,0x39, +0xf8,0x79,0x37,0x0, 0xc, 0x69,0x30,0x0, 0x9e,0x5e,0x34,0xe0,0xf, 0x29,0xb0,0x0, +0x8c,0xa, 0x2b,0x1b,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d,0x32,0x7e, +0x7f,0x39,0xc1,0x79,0x37,0x0, 0x82,0xa, 0x2a,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e, +0x24,0x29,0xb0,0x0, 0x99,0xa, 0x3b,0x2d,0x32,0x7e,0x7f,0x39,0xf8,0x79,0x37,0x0, +0x6, 0x69,0x30,0x0, 0x9c,0x7e,0x7f,0x39,0xf8,0x79,0x37,0x0, 0x8, 0x69,0x30,0x0, +0x9a,0x7e,0xf, 0x39,0xf8,0x79,0x30,0x0, 0xa, 0x22,0x7f,0x60,0x74,0x1, 0x12,0x13, +0xde,0x29,0x36,0x0, 0xf5,0x29,0x26,0x0, 0xa3,0x29,0x16,0x0, 0xa4,0xbe,0x20,0x2, +0x28,0x3, 0x7e,0x20,0x2, 0xbe,0x10,0x40,0x28,0x3, 0x7e,0x10,0x40,0x7e,0x34,0x0, +0x4, 0x7c,0xb2,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0x7, 0xa, 0x31,0x7e,0x2f, +0x39,0xc9,0x79,0x32,0x0, 0x12,0x7c,0x73,0xac,0x70,0xa, 0x21,0x12,0x1e,0xb9,0x7c, +0x27,0xa, 0x32,0x7e,0x2f,0x39,0xc9,0x79,0x32,0x0, 0x14,0x7c,0x73,0xac,0x70,0x29, +0x26,0x0, 0xf6,0xa, 0x22,0xad,0x32,0xa, 0x21,0x8d,0x32,0x7d,0x43,0x7c,0x73,0xac, +0x70,0xa, 0x21,0x12,0x1e,0xb9,0x7c,0xa7,0x7c,0x2a,0x7c,0xb9,0x2c,0xab,0xbe,0xa0, +0xc, 0x50,0x3, 0x7e,0xa0,0xc, 0xbe,0x20,0xc, 0x50,0x3, 0x7e,0x20,0xc, 0xa, 0x20, +0xa, 0x31,0x12,0x1e,0xb9,0x7d,0xe3,0xa, 0x3a,0xb, 0x34,0xad,0x3e,0xb, 0x34,0xbe, +0x34,0x2, 0x0, 0x40,0x4, 0x7e,0x34,0x1, 0xff,0x29,0x46,0x0, 0xf7,0x7e,0x50,0x2, +0xac,0x45,0xa, 0xf2,0xad,0xfe,0x2d,0x2f,0xb, 0x24,0xbe,0x24,0x2, 0x0, 0x40,0x4, +0x7e,0x24,0x1, 0xff,0xa, 0x13,0x7e,0x7f,0x39,0xc9,0x79,0x17,0x0, 0xa, 0x1e,0x24, +0x7c,0x45,0x6c,0x55,0x1e,0x34,0x2d,0x32,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0xc, +0xa, 0x3a,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30, +0x0, 0x4, 0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f, +0x33,0xfc,0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x33,0xfc,0x79,0x32, +0x0, 0x8, 0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d, +0x32,0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e, +0xf, 0x33,0xfc,0x79,0x30,0x0, 0xe, 0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xe0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xb2,0x86,0x22,0xff,0xff, +0x7f,0x21,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x4, 0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, +0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0x6, 0x69,0x30,0x0, +0x6, 0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0x8, 0x29,0x70,0x0, 0x1, 0x7c,0x47,0x6c, +0x55,0x7e,0xb, 0x70,0xa, 0x37,0x2d,0x32,0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0xc, +0x29,0x70,0x0, 0x2, 0xa, 0x37,0x1b,0x34,0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0xa, +0x69,0x30,0x0, 0xa, 0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0xe, 0x69,0x30,0x0, 0xc, +0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0x10,0x69,0x30,0x0, 0xe, 0x7e,0x7f,0x33,0xfc, +0x79,0x37,0x0, 0x12,0x29,0x70,0x0, 0x3, 0x7c,0x27,0x6c,0x33,0x7e,0x1f,0x33,0xfc, +0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xa0,0x12,0xf, 0x45,0x7e,0x1f,0x33,0xfc,0x69,0x11, +0x0, 0x1a,0x7a,0x2b,0x30,0x69,0x11,0x0, 0x1c,0x39,0x32,0x0, 0x1, 0x69,0x11,0x0, +0x16,0x79,0x12,0x0, 0x2, 0x69,0x11,0x0, 0x18,0x79,0x12,0x0, 0x4, 0x69,0x11,0x0, +0x22,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x24,0x79,0x12,0x0, 0x8, 0x69,0x11,0x0, +0x1e,0x79,0x12,0x0, 0xa, 0x69,0x31,0x0, 0x20,0x79,0x32,0x0, 0xc, 0xa9,0xc6,0xcb, +0x22,0xca,0x3b,0x7c,0x57,0x7c,0x4b,0x5e,0x40,0x3, 0x69,0x30,0x0, 0x4, 0x5e,0x60, +0x3f,0x6c,0xaa,0xa, 0x4a,0x69,0xf0,0x0, 0xa, 0x69,0xe0,0x0, 0x8, 0x2d,0xf4,0x7e, +0x7b,0xb0,0xa, 0xfb,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0xa, 0xea,0x69,0xd0, +0x0, 0xe, 0x69,0xc0,0x0, 0xc, 0x2d,0xde,0x7e,0x6b,0xb0,0xa, 0x4b,0x2d,0x4f,0x7e, +0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, 0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0, +0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x39,0xf4,0x2d,0xfd,0x79,0x47,0x1, 0x8c,0xb, 0xa0, +0xbe,0xa0,0xe, 0x78,0xae,0x6c,0xaa,0x7e,0x90,0x2, 0xac,0x9a,0x69,0xf0,0x0, 0x2, +0xb, 0xa, 0xe0,0x2d,0xf4,0xb, 0x7a,0x40,0x7e,0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, +0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0,0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x39, +0xf4,0x2d,0xfd,0x79,0x47,0x1, 0x80,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xc9,0x7e,0x90, +0xf0,0xac,0x94,0x74,0x28,0xac,0xb5,0x7d,0xf5,0x2d,0xf4,0x7e,0x2f,0x39,0xf4,0x2d, +0x5f,0x79,0x32,0x1, 0x88,0x69,0x30,0x0, 0x6, 0x7e,0x30,0xf0,0xac,0x34,0x74,0x28, +0xac,0x5b,0x2d,0x21,0x7e,0xf, 0x39,0xf4,0x2d,0x12,0x79,0x30,0x1, 0x8a,0xda,0x3b, +0x22,0x29,0x60,0x0, 0xb, 0xa, 0x46,0x29,0x60,0x0, 0x4, 0xa, 0x26,0x2d,0x24,0x7c, +0x65,0x29,0xb0,0x0, 0x6, 0xbc,0xb6,0x28,0x2, 0x7c,0x6b,0x29,0x70,0x0, 0x5, 0x29, +0xb0,0x0, 0x7, 0xbc,0xb7,0x28,0x2, 0x7c,0x7b,0x6c,0xaa,0x6d,0x22,0x7e,0x90,0x2, +0xac,0x9a,0x7e,0x7f,0x39,0xc1,0x2d,0xf4,0x79,0x27,0x0, 0x2, 0xb, 0xa0,0xbe,0xa0, +0x23,0x78,0xea,0x6c,0xaa,0x80,0x55,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x57,0x0, +0x4c,0xbe,0x50,0x23,0x50,0x23,0x29,0x47,0x0, 0xb4,0xa, 0xd4,0x7d,0x4d,0x7c,0x89, +0x6c,0x99,0x7d,0xd4,0x7e,0x90,0x2, 0xac,0x95,0x7e,0x7f,0x39,0xc1,0x2d,0xf4,0xb, +0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xa, 0x4a,0x7f,0x70,0x2d,0xf4,0x29, +0x47,0x0, 0x4c,0xa, 0xd4,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x39,0xc1,0x2d,0xf4, +0xb, 0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0xa0,0xbc,0x6a,0x38,0xa7, +0x6c,0xaa,0x80,0x1d,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x67,0x0, 0x6f,0xa, 0x46, +0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x39,0xc1,0x2d,0xf2,0x79,0x47,0x0, 0x48,0xb, +0xa0,0xbc,0x7a,0x38,0xdf,0x22,0x7c,0x7b,0x7e,0x7f,0x39,0xc9,0x69,0x47,0x0, 0xc, +0x6c,0x88,0x3e,0x44,0x69,0x7, 0x0, 0xa, 0x69,0x57,0x0, 0x2, 0x1e,0x54,0x1e,0x54, +0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, 0x3, 0x7e,0x14, +0x0, 0x4, 0x70,0x2, 0x41,0x9b,0x3e,0x14,0x14,0x78,0xfb,0x7c,0xa3,0xa, 0xda,0xad, +0xd0,0x7d,0xcd,0x6d,0x11,0x79,0x17,0x0, 0x8c,0x7c,0xb7,0x70,0x2, 0x41,0xb4,0x1e, +0xd4,0x14,0x78,0xfb,0xbe,0xd4,0x1, 0x0, 0x38,0x2, 0x41,0xc2,0x7e,0xd4,0x1, 0x0, +0x41,0xce,0xbe,0xd4,0x0, 0x10,0x40,0x2, 0x41,0xce,0x7e,0xd4,0x0, 0x10,0x7d,0x3d, +0x12,0x12,0x6a,0xa, 0x1b,0x7e,0x1f,0x39,0xc9,0x79,0x11,0x0, 0x90,0x7e,0x1f,0x39, +0xc9,0x79,0xd1,0x0, 0x8e,0x7e,0x7f,0x39,0xc9,0x69,0x37,0x0, 0x8, 0xad,0x3c,0x8d, +0x3d,0x79,0x37,0x0, 0x92,0x7e,0x14,0x0, 0x6, 0x7e,0x1f,0x39,0xc9,0x79,0x11,0x0, +0x94,0x7d,0x24,0x9d,0x20,0xa, 0x3a,0xad,0x32,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, +0x96,0x7e,0x34,0x0, 0x10,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x98,0x22,0x7c,0x5b, +0x7e,0xf, 0x39,0xc9,0x69,0x40,0x0, 0x22,0x30,0x1, 0x6b,0x6d,0xff,0x7d,0x3f,0xbe, +0x50,0x10,0x28,0x2e,0x7e,0x54,0xff,0xff,0x79,0x50,0x0, 0x42,0x9e,0x50,0x10,0x6c, +0xaa,0x80,0x11,0x7e,0xe4,0x0, 0x1, 0x7c,0xba,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb, +0x2d,0x3e,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e,0x6f,0x39,0xc9,0x79,0x36,0x0, 0x40, +0x80,0x25,0x79,0xf0,0x0, 0x40,0x6c,0xaa,0x80,0x11,0x7e,0xf4,0x0, 0x1, 0x7c,0xba, +0x60,0x5, 0x3e,0xf4,0x14,0x78,0xfb,0x2d,0x3f,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e, +0x7f,0x39,0xc9,0x79,0x37,0x0, 0x42,0x7d,0x34,0x2e,0x34,0x0, 0xc, 0x7e,0x7f,0x39, +0xc9,0x79,0x37,0x0, 0x16,0x22,0x6d,0x33,0x79,0x30,0x0, 0x40,0x7e,0xf, 0x39,0xc9, +0x79,0x30,0x0, 0x42,0x7e,0x1f,0x39,0xc9,0x79,0x41,0x0, 0x16,0x22,0x7c,0x17,0x7c, +0x3b,0x6d,0x33,0x7e,0x2f,0x39,0xc9,0x79,0x32,0x0, 0x40,0x7e,0x2f,0x39,0xc9,0x79, +0x32,0x0, 0x42,0x7e,0x7f,0x39,0xc9,0x69,0x57,0x0, 0x12,0x7c,0xab,0x69,0x37,0x0, +0x2, 0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x5e, +0x34,0x0, 0x3, 0x7c,0xb7,0x7e,0x44,0x0, 0x4, 0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb, +0x7c,0x29,0xa, 0x22,0xa, 0x3a,0x12,0x1e,0xb9,0xa, 0x23,0x2d,0x32,0x7c,0xb7,0x7c, +0x61,0x6c,0x77,0xa, 0xb, 0x1e,0x4, 0x2d,0x3, 0x79,0x7, 0x0, 0xc, 0x7c,0x73,0xac, +0x72,0xa, 0x2a,0x12,0x1e,0xb9,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x16,0x6d,0x33, +0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x6, +0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x33,0xfc, +0x79,0x32,0x0, 0x8, 0x29,0x70,0x0, 0x2, 0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x3, +0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0xc, 0x7e,0xb, 0x70,0x7c, +0x47,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, +0xa, 0x29,0x70,0x0, 0x4, 0xa, 0x37,0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0xe, 0x29, +0xb0,0x0, 0x5, 0x54,0x1, 0x7c,0x2b,0x6c,0x33,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xc0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xca,0x79,0x7c,0xab,0x5e, +0xa0,0x3, 0x6c,0x77,0x7e,0x50,0x2, 0xac,0x57,0x69,0xd0,0x0, 0xe, 0x69,0xc0,0x0, +0xc, 0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d, +0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e,0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e, +0x7f,0x39,0xf4,0x2d,0xf2,0x79,0x47,0x2, 0x54,0xb, 0x70,0xbe,0x70,0xe, 0x40,0xc4, +0x69,0x40,0x0, 0x4, 0x7e,0xf0,0xf0,0xac,0xfa,0x7e,0x1f,0x39,0xf4,0x2d,0x37,0x79, +0x41,0x2, 0x50,0x69,0x30,0x0, 0x6, 0x74,0xf0,0xa4,0x7e,0xf, 0x39,0xf4,0x2d,0x15, +0x79,0x30,0x2, 0x52,0xda,0x79,0x22,0xa9,0xd6,0xcb,0xc2,0x1e,0x69,0x30,0x0, 0x4, +0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f,0x33,0xfc, +0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0x8, +0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e, +0x2f,0x33,0xfc,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e,0x2f,0x33, +0xfc,0x79,0x32,0x0, 0xe, 0x29,0xb0,0x0, 0x3, 0x54,0x1, 0xa, 0x5b,0x7c,0xab,0xe4, +0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x50,0x69,0x30,0x0, 0xa, 0x12,0xf, 0x45,0xa9,0xc6, +0xcb,0x22,0x69,0x30,0x0, 0xae,0x7e,0x2f,0x39,0xc9,0x79,0x32,0x0, 0x6, 0x29,0x50, +0x0, 0xa6,0xa, 0x55,0x7d,0x23,0x1e,0x24,0x9d,0x25,0x7e,0x2f,0x39,0xc9,0x79,0x22, +0x0, 0x18,0x7d,0x23,0x1e,0x24,0x1b,0x25,0x7e,0x2f,0x39,0xc9,0x79,0x22,0x0, 0x38, +0x69,0x20,0x0, 0xfd,0x1e,0x34,0x9d,0x32,0x9e,0x34,0x0, 0xa, 0x7e,0x2f,0x39,0xc9, +0x79,0x32,0x0, 0x26,0x29,0x70,0x0, 0xa7,0xa, 0x37,0x7e,0x2f,0x39,0xc9,0x79,0x32, +0x0, 0x1a,0x29,0x70,0x0, 0xb, 0xa, 0x27,0x29,0x70,0x0, 0x4, 0x2d,0x32,0x7e,0x2f, +0x39,0xc9,0x79,0x32,0x0, 0x8, 0x2, 0x9, 0xa1,0xca,0x3b,0xf5,0x24,0x7f,0x41,0x7f, +0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0xe5,0x24,0xbe,0xb0,0x23,0x28, +0x3, 0x75,0x24,0x23,0x6c,0xaa,0x80,0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b, +0xb0,0xbe,0xb1,0x26,0x40,0xd, 0x74,0x23,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, +0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, 0x3b,0x2e,0x35,0x28,0x7a,0x71,0x82,0x7a,0x61, +0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13,0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24, +0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22,0xa9,0xd6,0xcb,0x69,0x20,0x0, 0x4, 0x7e,0x2f, +0x33,0xfc,0x79,0x22,0x0, 0x4, 0x69,0x20,0x0, 0x8, 0x7e,0x2f,0x33,0xfc,0x79,0x22, +0x0, 0x8, 0x7e,0xb, 0x50,0xa, 0x55,0x7c,0xab,0xe4,0x29,0x50,0x0, 0x1, 0xa, 0x25, +0x2d,0x25,0x7e,0x2f,0x33,0xfc,0x79,0x22,0x0, 0xc, 0x29,0x50,0x0, 0x2, 0xa, 0x25, +0x7e,0xf, 0x33,0xfc,0x79,0x20,0x0, 0xe, 0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, 0xa, +0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x40,0x12,0xf, 0x45, +0xa9,0xc6,0xcb,0x22,0x7c,0xab,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x39,0xf8,0x79,0x30, +0x0, 0xe, 0xc2,0x1d,0xe4,0x7a,0xb3,0x39,0xf3,0x5e,0xa0,0x3, 0xa, 0x1a,0x3e,0x14, +0x7e,0x1f,0x39,0xc1,0x1b,0x1a,0x10,0x7e,0xf, 0x39,0xc1,0x2e,0x14,0x0, 0x84,0xb, +0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x74,0x1, 0x12,0x13,0x56,0x7e,0xf, 0x39, +0xf8,0xb, 0xa, 0x30,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xa9,0xd3,0xcd,0x7e,0xf, 0x39, +0xf8,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x22,0x7f,0x10,0xa9, +0xd6,0xcb,0x69,0x11,0x0, 0x2, 0x7e,0x2f,0x33,0xfc,0x79,0x12,0x0, 0x4, 0x69,0x11, +0x0, 0x4, 0x7e,0x2f,0x33,0xfc,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x6, 0x7e,0x2f, +0x33,0xfc,0x79,0x12,0x0, 0x8, 0x7e,0x1b,0x30,0xa, 0x3, 0x7e,0x14,0x1, 0x0, 0xad, +0x10,0x29,0x71,0x0, 0x1, 0xa, 0x37,0x2d,0x31,0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, +0xc, 0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x60,0x12,0xf, +0x45,0xa9,0xc6,0xcb,0x22,0xa9,0xd7,0xcb,0x7d,0x23,0x4e,0x50,0x1, 0x7e,0xf, 0x33, +0xfc,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x80,0x1e,0x7e,0xf, 0x33,0xfc,0xb, +0xa, 0x30,0x7d,0x23,0x5e,0x24,0x0, 0x8, 0xbe,0x24,0x0, 0x8, 0x78,0xb, 0xa9,0xd7, +0xcb,0x4e,0x70,0x4, 0x1b,0xa, 0x30,0xd2,0x1e,0x7e,0xf, 0x33,0xfc,0xb, 0xa, 0x30, +0x7d,0x23,0x5e,0x24,0x80,0x0, 0xbe,0x24,0x80,0x0, 0x78,0xcf,0x4e,0x60,0x40,0x1b, +0xa, 0x30,0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10,0x22,0xca,0x3b,0xf5,0x24, +0x7f,0x41,0x7f,0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0x6c,0xaa,0x80, +0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0xbe,0xb1,0x27,0x40,0xd, 0x74, +0x1c,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, 0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, +0x3b,0x2e,0x35,0x2a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13, +0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24,0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22, +0x5, 0x63,0x31,0x20,0x18,0x13,0xf, 0xd, 0xc, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, +0xca,0xf8,0x7d,0xe2,0x7d,0xd3,0x7c,0xfb,0xbe,0x30,0x1, 0x28,0x6, 0x7e,0xf4,0x0, +0x10,0x80,0xf, 0xbe,0x30,0x0, 0x28,0x6, 0x7e,0xf4,0x0, 0x8, 0x80,0x4, 0x7e,0xf4, +0x0, 0x4, 0x7d,0x1f,0x6d,0x0, 0x6d,0x33,0x7e,0x24,0x0, 0x10,0x12,0x1f,0x58,0x7f, +0x1, 0x7d,0x3d,0x6d,0x22,0x12,0x1e,0xeb,0x7d,0x1e,0x12,0x1f,0x5, 0x74,0x4, 0xac, +0xbf,0x7e,0xf, 0x39,0xc9,0x2d,0x15,0x79,0x30,0x0, 0x82,0x79,0x20,0x0, 0x80,0xda, +0xf8,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, +0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0x1d,0x7e,0xf, 0x39,0xf8,0xb, 0xa, 0x30,0x7c, +0x57,0x7a,0x53,0x39,0xf3,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xc2,0xc6,0x6d,0x33,0x7e, +0xf, 0x39,0xf8,0x79,0x30,0x0, 0xe, 0x12,0x12,0x9e,0x12,0x69,0x5, 0xd0,0x82,0xd0, +0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda, +0x7b,0x32,0x74,0x3, 0x12,0x13,0x56,0xa9,0xd1,0xc4,0x7e,0xf, 0x39,0xc1,0x2e,0x14, +0x0, 0x84,0xb, 0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x7e,0x14,0x0, 0x1, 0x7e, +0x1f,0x39,0xc1,0x1b,0x1a,0x10,0x7e,0xf, 0x39,0xc9,0xb, 0x16,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0xc2,0xf, 0xe4,0x7a,0xb3,0x39,0xd9,0x7e,0x1f,0x39,0xc1, +0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0x74,0x2, 0x2, 0x13,0x56,0x7c,0x6b, +0x6c,0xaa,0x80,0x17,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x39,0xf4,0x2d,0xf4,0xb, +0x7a,0x20,0x7f,0x70,0x2d,0xf4,0x1b,0x7a,0x20,0xb, 0xa0,0xbc,0x7a,0x38,0xe5,0x6c, +0xaa,0x80,0x20,0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x39,0xf4,0x2d,0xf2,0x69,0x27, +0x0, 0x38,0xa, 0xf7,0xa, 0x4a,0x2d,0x4f,0x3e,0x44,0x7f,0x70,0x2d,0xf4,0x1b,0x7a, +0x20,0xb, 0xa0,0xbc,0x6a,0x38,0xdc,0x22,0xca,0x79,0x7c,0xab,0x5e,0xa0,0x3, 0x6c, +0x77,0x7e,0x50,0x2, 0xac,0x57,0x7f,0x60,0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6, +0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e, +0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e,0x7f,0x39,0xf4,0x2d,0xf2,0x79,0x47,0x2, 0x54, +0xb, 0x70,0xbe,0x70,0xe, 0x40,0xca,0xda,0x79,0x22,0x29,0x50,0x0, 0xf5,0xac,0x5b, +0x7e,0xf, 0x39,0xc9,0x69,0x30,0x0, 0xc, 0xa, 0x56,0x3e,0x54,0xbe,0x24,0x2, 0x0, +0x40,0x4, 0x7e,0x24,0x1, 0xff,0xbd,0x25,0x28,0x1f,0x2e,0x14,0x0, 0xc, 0x6c,0x66, +0x1b,0xa, 0x30,0x1e,0x24,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x39,0xc9,0x2e,0x14,0x0, +0xc, 0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50, +0x28,0xac,0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d, +0x24,0x7e,0x7f,0x39,0xf4,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x44,0xa, 0x4a,0x7f, +0x60,0x2d,0xd4,0x7e,0x6b,0xb0,0x7c,0x8b,0x6c,0x99,0x4d,0x24,0x79,0x27,0x1, 0x8c, +0xb, 0xa0,0xbe,0xa0,0xe, 0x40,0xc7,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50,0x28,0xac, +0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d,0x24,0x7e, +0x7f,0x39,0xf4,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x55,0xa, 0x4a,0x7f,0x60,0x2d, +0xd4,0x7e,0x6b,0xb0,0xa, 0x4b,0x4d,0x24,0x79,0x27,0x1, 0x8c,0xb, 0xa0,0xbe,0xa0, +0xe, 0x40,0xc9,0x22,0xa9,0xd6,0xcb,0x54,0x3f,0x5e,0x70,0x1f,0x7c,0x2b,0x6c,0x33, +0x3e,0x14,0x3e,0x14,0x2e,0x14,0x0, 0x5, 0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34, +0x3e,0x34,0x3e,0x34,0x2d,0x31,0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, 0x2, 0x7e,0xf, +0x33,0xfc,0x79,0x20,0x0, 0x14,0xa9,0xc6,0xcb,0x22,0x7d,0x23,0x6c,0x66,0x7e,0x30, +0x2, 0xac,0x36,0x2e,0x14,0x20,0x99,0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4,0x93,0xa, +0x1b,0xbd,0x12,0x28,0x7, 0xb, 0x60,0xbe,0x60,0x14,0x40,0xe2,0x7e,0x70,0x2, 0xac, +0x67,0x2e,0x34,0x20,0x9a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x7e,0xf, +0x39,0xc1,0x2e,0x14,0x0, 0x84,0xb, 0xa, 0x30,0x5e,0x70,0xdf,0x1b,0xa, 0x30,0x74, +0x3, 0x12,0x13,0x56,0x7e,0x14,0x0, 0x3, 0x7e,0x1f,0x39,0xc1,0x1b,0x1a,0x10,0x7e, +0x1f,0x39,0xc1,0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0xe4,0x2, 0x13,0x56, +0x2e,0x34,0x4, 0x0, 0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x60,0x7e,0x34,0x4, 0x0, +0x9d,0x32,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x62,0x7e,0x34,0x0, 0x1, 0x7e,0xf, +0x39,0xc9,0x79,0x30,0x0, 0x64,0xa, 0x3b,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, 0x66, +0x22,0x7c,0xa5,0xbe,0x34,0x0, 0x0, 0x28,0x10,0xa, 0x1b,0x3e,0x14,0x7d,0x23,0x7c, +0x45,0x6c,0x55,0x2d,0x21,0xa, 0x3a,0x80,0x8, 0xa, 0x2b,0x3e,0x24,0x7c,0x67,0x6c, +0x77,0x2d,0x32,0x7e,0xf, 0x39,0xf8,0x79,0x30,0x0, 0x4, 0x22,0x7c,0xa7,0x7e,0x1f, +0x39,0xc1,0x69,0x41,0x0, 0x8a,0x5e,0x44,0x10,0xf, 0xa, 0x1a,0x3e,0x14,0x3e,0x14, +0x3e,0x14,0x3e,0x14,0xa, 0x5b,0xc4,0x23,0x54,0xe0,0x7c,0xab,0xe4,0x2d,0x51,0x4d, +0x45,0x79,0x41,0x0, 0x8a,0x22,0x7e,0xf, 0x39,0xc1,0x69,0x30,0x0, 0x84,0x5e,0x70, +0xe7,0x1b,0xb1,0x68,0xc, 0x14,0x68,0xc, 0xb, 0xb1,0x78,0x5, 0x4e,0x70,0x10,0x80, +0x3, 0x4e,0x70,0x8, 0x79,0x30,0x0, 0x84,0x22,0x7e,0x34,0x0, 0x1f,0x7e,0xf, 0x39, +0xc9,0x79,0x30,0x0, 0x4, 0xa9,0xd2,0xcd,0x7e,0xf, 0x39,0xc9,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0x22,0xbe,0xb0,0x0, 0x28,0xa, 0xa9,0xd7,0xca,0xa9,0xd3, +0xcb,0xa9,0xd2,0xcb,0x22,0xa9,0xc7,0xca,0xa9,0xc3,0xcb,0xa9,0xc2,0xcb,0x22,0x30, +0x1, 0xa, 0x54,0x3, 0xa, 0x3b,0x2e,0x34,0x2, 0x0, 0x80,0x2, 0x6d,0x33,0x7e,0xf, +0x39,0xc9,0x79,0x30,0x0, 0x3a,0x22,0x7e,0xf, 0x39,0xc1,0x69,0x30,0x0, 0x8a,0x60, +0x5, 0x4e,0x60,0x10,0x80,0x3, 0x5e,0x60,0xef,0x79,0x30,0x0, 0x8a,0x22,0xbe,0xb0, +0x0, 0x28,0x9, 0xa9,0xd6,0xca,0xd2,0xcd,0xa9,0xd1,0xcb,0x22,0xa9,0xc6,0xca,0xc2, +0xcd,0xa9,0xc1,0xcb,0x22,0x7e,0x34,0x0, 0xf, 0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, +0x4, 0xc2,0xc3,0xd2,0xeb,0x22,0x6, 0xe, 0x15,0x1a,0x1f,0x26,0x2b,0x2d,0x2e,0x2f, +0x2c,0x2a,0x24,0x1f,0x1a,0x14,0xf, 0x8, 0x3, 0x3, 0x6, 0xb, 0x10,0x15,0x1c,0x22, +0x28,0x2d,0x34,0x39,0x3d,0x40,0xe, 0x3, 0x0, 0x0, 0x0, 0x3, 0x8, 0xc, 0x11,0x16, +0x1c,0x23,0x2b,0x32,0x37,0x3c,0x40,0x45,0x4a,0x4d,0x4c,0x4b,0x4a,0x48,0x46,0x46, +0x45,0x45,0x44,0x44,0x43,0x44,0x45,0x78,0x65,0x55,0x2, 0xd, 0x14,0x1b,0x21,0x25, +0x2b,0x31,0x37,0x36,0x33,0x2d,0x28,0x20,0x19,0x14,0xd, 0x8, 0x1, 0x2, 0x5, 0xb, +0x10,0x18,0x1e,0x23,0x2a,0x30,0x35,0x3a,0x3e,0x3f,0x0, 0x1, 0x1, 0x0, 0x0, 0x0, +0x0, 0x0, 0x1, 0x4, 0x9, 0xf, 0x15,0x1d,0x24,0x2a,0x30,0x35,0x3b,0x3e,0x3f,0x40, +0x3f,0x3e,0x3d,0x3d,0x3c,0x3c,0x3b,0x3b,0x39,0x37,0x1a,0x2d,0x65,0x55,0x1b,0x29, +0x27,0x1e,0x14,0x11,0x1a,0x26,0x2e,0x37,0x3d,0x3f,0x3d,0x37,0x2e,0x21,0x16,0xc, +0x5, 0x1, 0x0, 0x0, 0x1, 0x3, 0xa, 0x13,0x1d,0x26,0x2e,0x33,0x38,0x3a,0x16,0x21, +0x2b,0x32,0x30,0x2a,0x27,0x2a,0x2f,0x2d,0x24,0x1a,0x10,0x7, 0x1, 0x0, 0x2, 0x7, +0x10,0x19,0x23,0x2d,0x36,0x41,0x49,0x4c,0x4a,0x45,0x3c,0x34,0x2a,0x27,0x51,0x71, +0x50,0x55,0x28,0x12,0x11,0x18,0x23,0x29,0x2b,0x2a,0x2e,0x35,0x3c,0x3e,0x3f,0x39, +0x31,0x28,0x1e,0x15,0xe, 0x6, 0x3, 0x1, 0x0, 0x0, 0x3, 0xc, 0x16,0x20,0x2b,0x32, +0x37,0x39,0x20,0x29,0x32,0x37,0x31,0x28,0x21,0x2a,0x31,0x2d,0x23,0x1b,0x13,0x8, +0x1, 0x0, 0x1, 0x5, 0xc, 0x18,0x20,0x29,0x34,0x3e,0x47,0x4f,0x50,0x4d,0x45,0x3c, +0x34,0x31,0x26,0xcb,0x50,0x55,0x1d,0x2f,0x2c,0x25,0x1a,0x1b,0x20,0x29,0x31,0x31, +0x2e,0x2d,0x35,0x3d,0x3f,0x3d,0x38,0x2c,0x22,0x15,0xd, 0x6, 0x1, 0x0, 0x1, 0x6, +0x10,0x1b,0x24,0x2f,0x38,0x3d,0xd, 0x1b,0x27,0x31,0x32,0x28,0x1e,0x14,0x15,0x1d, +0x28,0x31,0x34,0x2a,0x1f,0x14,0x9, 0x1, 0x0, 0x4, 0xd, 0x17,0x21,0x2c,0x35,0x40, +0x47,0x47,0x44,0x3c,0x34,0x30,0x1b,0x82,0x50,0x55,0x19,0x2e,0x2a,0x1f,0x18,0x1b, +0x22,0x2d,0x30,0x2e,0x2e,0x35,0x3d,0x3f,0x3d,0x3a,0x2f,0x24,0x18,0xf, 0x7, 0x1, +0x0, 0x0, 0x3, 0xb, 0x16,0x1e,0x29,0x32,0x3a,0x3d,0x11,0x1f,0x28,0x32,0x30,0x26, +0x1b,0x14,0x1c,0x25,0x2e,0x35,0x2e,0x23,0x19,0x11,0x4, 0x0, 0x1, 0x8, 0x10,0x1c, +0x25,0x30,0x38,0x40,0x42,0x3f,0x39,0x32,0x2c,0x27,0xc0,0xd1,0x50,0x55,0x18,0x2c, +0x29,0x1e,0x14,0x13,0x16,0x1e,0x29,0x30,0x2e,0x2c,0x2b,0x37,0x3d,0x3f,0x3e,0x39, +0x30,0x25,0x1b,0x10,0x8, 0x1, 0x0, 0x2, 0x9, 0x13,0x1f,0x2d,0x38,0x3c,0x11,0x1a, +0x23,0x2f,0x33,0x29,0x20,0x16,0xe, 0x13,0x1d,0x28,0x32,0x31,0x28,0x1e,0x16,0xb, +0x2, 0x0, 0x1, 0x8, 0x12,0x1e,0x29,0x33,0x3b,0x3f,0x3c,0x32,0x29,0x26,0x30,0x6e, +0x50,0x55,0x16,0x2b,0x24,0x17,0xd, 0xa, 0xe, 0x15,0x24,0x28,0x25,0x23,0x2b,0x36, +0x3b,0x3d,0x3b,0x37,0x2b,0x20,0x15,0xb, 0x4, 0x0, 0x0, 0x3, 0xe, 0x19,0x27,0x33, +0x3d,0x3f,0x13,0x21,0x2e,0x37,0x3a,0x31,0x27,0x1c,0x13,0x1c,0x28,0x34,0x3e,0x37, +0x2d,0x22,0x18,0xc, 0x1, 0x0, 0x3, 0xd, 0x18,0x25,0x31,0x3c,0x47,0x48,0x42,0x38, +0x2e,0x2a,0x31,0x62,0x50,0x55,0x35,0x2e,0x27,0x22,0x1f,0x1b,0x16,0x10,0xc, 0x8, +0x6, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x3, 0x6, 0xb, 0xe, 0x12,0x17,0x1d,0x22,0x26, +0x2a,0x30,0x35,0x39,0x3d,0x3f,0x0, 0x0, 0x1, 0x4, 0x6, 0x8, 0xb, 0x10,0x16,0x1b, +0x1f,0x23,0x28,0x2d,0x32,0x36,0x3b,0x40,0x44,0x48,0x4a,0x4b,0x4c,0x4b,0x4a,0x48, +0x46,0x43,0x40,0x3e,0x3c,0x3a,0x3c,0x9c,0x34,0x55,0x9, 0x17,0x1d,0x26,0x2e,0x37, +0x3c,0x3f,0x3b,0x33,0x2b,0x22,0x1a,0x11,0xb, 0x5, 0x3, 0x1, 0x1, 0x0, 0x0, 0x0, +0x1, 0x6, 0xa, 0x11,0x19,0x22,0x2a,0x32,0x39,0x3d,0x30,0x30,0x2f,0x2c,0x26,0x1e, +0x17,0xd, 0x5, 0x0, 0x0, 0x1, 0x6, 0xe, 0x15,0x1e,0x26,0x2c,0x32,0x3a,0x41,0x48, +0x50,0x5b,0x61,0x64,0x64,0x60,0x5b,0x56,0x51,0x4f,0xd8,0x2c,0x33,0x55,0x26,0x1c, +0x19,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x17,0x17,0x15,0xf, 0x9, 0x4, 0x1, 0x0, +0x0, 0x0, 0x0, 0x1, 0x4, 0xb, 0x12,0x18,0x1f,0x28,0x31,0x37,0x3c,0x40,0x1, 0x7, +0xe, 0x14,0x1c,0x23,0x2c,0x34,0x3e,0x44,0x4c,0x54,0x5b,0x60,0x5d,0x55,0x4f,0x49, +0x43,0x3d,0x38,0x32,0x2b,0x26,0x22,0x1f,0x1e,0x1c,0x1c,0x1c,0x1c,0x1d,0x66,0x54, +0x74,0x55,0x3e,0x2c,0x21,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d, +0x1e,0x1e,0x1d,0x1a,0x11,0xc, 0x7, 0x2, 0x0, 0x0, 0x3, 0xa, 0x12,0x1c,0x23,0x2c, +0x38,0x40,0xc, 0x0, 0x6, 0xf, 0x17,0x22,0x29,0x32,0x3b,0x41,0x47,0x4f,0x55,0x5c, +0x66,0x71,0x79,0x3e,0x76,0x6d,0x64,0x5a,0x52,0x4b,0x42,0x39,0x35,0x33,0x32,0x32, +0x31,0x31,0xf3,0xdb,0x74,0x55,0x9, 0x7, 0x6, 0x6, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, +0x3, 0x2, 0x2, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xa, 0x10,0x14,0x1b,0x22, +0x28,0x2e,0x34,0x39,0x3d,0x40,0x0, 0xb, 0x11,0x16,0x1b,0x22,0x28,0x2c,0x33,0x39, +0x40,0x46,0x4d,0x52,0x56,0x5c,0x61,0x68,0x6d,0x73,0x73,0x71,0x71,0x71,0x70,0x70, +0x6f,0x6f,0x6f,0x6f,0x6d,0x6e,0x79,0x80,0x44,0x55,0x17,0x13,0x12,0x12,0x11,0x10, +0xf, 0xd, 0xc, 0xb, 0x9, 0x8, 0x7, 0x4, 0x3, 0x2, 0x1, 0x0, 0x0, 0x0, 0x1, 0x4, +0xb, 0x10,0x16,0x1d,0x24,0x29,0x31,0x39,0x3d,0x40,0x0, 0xe, 0x16,0x1a,0x1f,0x24, +0x29,0x2e,0x33,0x38,0x3e,0x43,0x47,0x50,0x55,0x59,0x62,0x69,0x6e,0x75,0x7c,0xff, +0x7d,0x7c,0x79,0x73,0x6d,0x68,0x60,0x5a,0x57,0x56,0x5d,0x8, 0x44,0x55,0x0, 0x7, +0xb, 0xd, 0x10,0x12,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x19,0x1c,0x1e,0x20,0x22, +0x23,0x25,0x27,0x29,0x2b,0x30,0x32,0x33,0x35,0x38,0x39,0x3b,0x3d,0x3f,0x3e,0x29, +0x1f,0x18,0xf, 0x7, 0x6, 0xc, 0x12,0x1d,0x25,0x2d,0x36,0x3e,0x3b,0x35,0x2c,0x26, +0x20,0x19,0x11,0xa, 0x3, 0x3, 0x9, 0x10,0x18,0x24,0x2c,0x33,0x3a,0x3e,0x60,0x9b, +0x32,0x55,0x0, 0x5, 0x5, 0x5, 0x4, 0x3, 0x2, 0x3, 0x5, 0x7, 0xa, 0xe, 0x11,0x19, +0x1b,0x1c,0x1d,0x1c,0x1c,0x1d,0x1f,0x22,0x25,0x2a,0x31,0x33,0x35,0x37,0x38,0x39, +0x3c,0x40,0x0, 0x12,0x1c,0x24,0x2b,0x34,0x3c,0x39,0x2f,0x29,0x21,0x16,0xf, 0xd, +0x14,0x1e,0x2a,0x33,0x31,0x27,0x20,0x18,0x10,0x7, 0xa, 0x10,0x1a,0x26,0x2f,0x37, +0x3d,0x3f,0xfb,0x8f,0x32,0x55,0x2c,0x23,0x1f,0x19,0x13,0xc, 0x7, 0x3, 0x0, 0x0, +0x0, 0x1, 0x5, 0xa, 0xf, 0x16,0x1d,0x23,0x2a,0x30,0x36,0x3b,0x3e,0x40,0x3f,0x3e, +0x3b,0x38,0x33,0x2f,0x2b,0x28,0x9, 0x1, 0x0, 0x1, 0x3, 0x9, 0xe, 0x14,0x1b,0x21, +0x27,0x2e,0x36,0x3b,0x3e,0x41,0x41,0x40,0x3d,0x3a,0x36,0x2f,0x2b,0x26,0x20,0x1c, +0x16,0x10,0xc, 0xa, 0x9, 0xb, 0x36,0xdc,0x30,0x55,0x1a,0x9, 0x5, 0x1, 0x0, 0x0, +0x0, 0x2, 0x5, 0x9, 0xf, 0x16,0x1c,0x22,0x2a,0x31,0x36,0x39,0x3c,0x3e,0x3f,0x3f, +0x3d,0x38,0x30,0x27,0x1f,0x18,0x12,0xb, 0x6, 0x5, 0x7, 0x12,0x19,0x22,0x2c,0x36, +0x3f,0x49,0x53,0x5c,0x63,0x66,0x64,0x5f,0x58,0x4c,0x43,0x3d,0x34,0x2b,0x22,0x1b, +0x15,0xb, 0x4, 0x0, 0x0, 0x1, 0x4, 0xb, 0x13,0x18,0xf1,0xc, 0x30,0x55,0x18,0x2c, +0x34,0x39,0x3c,0x3d,0x3f,0x3f,0x3f,0x3d,0x3b,0x36,0x30,0x2a,0x24,0x1c,0x16,0xd, +0x6, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x5, 0x9, 0xf, 0x17,0x1e,0x24,0x1, 0x2, +0x8, 0xe, 0x14,0x1a,0x21,0x28,0x30,0x37,0x40,0x49,0x50,0x55,0x59,0x5c,0x5c,0x58, +0x51,0x48,0x3f,0x38,0x31,0x2b,0x25,0x1d,0x17,0x11,0xa, 0x4, 0x1, 0x1, 0x9d,0xbf, +0x30,0x55,0x16,0x7, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4, 0x8, 0xe, 0x16,0x1f,0x28, +0x30,0x38,0x3c,0x3e,0x3f,0x40,0x3f,0x3f,0x3d,0x3b,0x37,0x32,0x2c,0x25,0x1d,0x16, +0xf, 0xc, 0x53,0x46,0x3e,0x35,0x2e,0x27,0x20,0x1a,0x14,0xd, 0x6, 0x1, 0x0, 0x0, +0x3, 0xa, 0x13,0x1a,0x20,0x27,0x2d,0x33,0x3a,0x40,0x48,0x4f,0x54,0x58,0x5a,0x5a, +0x58,0x57,0xc6,0x55,0x30,0x55,0x7, 0x1, 0x4, 0xa, 0x10,0x18,0x20,0x2a,0x32,0x38, +0x3c,0x3e,0x3f,0x3e,0x3d,0x3b,0x39,0x35,0x30,0x27,0x21,0x19,0x12,0xb, 0x6, 0x3, +0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x1d,0x12,0x9, 0x5, 0x1, 0x0, 0x0, 0x1, 0x5, +0xd, 0x17,0x20,0x2a,0x32,0x3b,0x45,0x4e,0x58,0x63,0x69,0x6b,0x6a,0x64,0x5d,0x57, +0x4f,0x47,0x40,0x38,0x32,0x2f,0x1a,0xb5,0x30,0x55,0x21,0x13,0xc, 0x8, 0x5, 0x2, +0x1, 0x0, 0x0, 0x1, 0x3, 0x8, 0xf, 0x17,0x1e,0x24,0x2b,0x32,0x39,0x3d,0x3e,0x3f, +0x3f,0x3d,0x3a,0x36,0x30,0x29,0x21,0x1a,0x16,0x13,0x5, 0x9, 0xe, 0x14,0x1a,0x22, +0x29,0x30,0x38,0x3f,0x47,0x4d,0x51,0x51,0x4f,0x4d,0x49,0x42,0x39,0x31,0x2b,0x25, +0x1e,0x17,0x10,0x8, 0x3, 0x0, 0x0, 0x1, 0x3, 0x5, 0xaf,0x13,0x30,0x55,0x38,0x3f, +0x3d,0x3a,0x36,0x2e,0x26,0x1f,0x14,0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, +0x9, 0xe, 0x14,0x1c,0x23,0x2a,0x34,0x38,0x3a,0x3b,0x3d,0x3d,0x3d,0x3d,0x29,0x1a, +0x10,0x9, 0x4, 0x0, 0x0, 0x1, 0x4, 0xc, 0x14,0x1c,0x22,0x28,0x2f,0x37,0x3f,0x47, +0x4f,0x56,0x5a,0x5b,0x59,0x56,0x4e,0x47,0x40,0x37,0x30,0x28,0x22,0x1f,0x2a,0xa9, +0x30,0x55,0x3e,0x3b,0x38,0x33,0x2b,0x24,0x1d,0x16,0x10,0x7, 0x3, 0x1, 0x0, 0x0, +0x0, 0x1, 0x1, 0x3, 0x6, 0xc, 0x15,0x1c,0x23,0x29,0x2f,0x35,0x38,0x3b,0x3c,0x3e, +0x3f,0x3f,0x1f,0x10,0xa, 0x6, 0x0, 0x0, 0x0, 0x2, 0x4, 0xc, 0x12,0x18,0x1e,0x25, +0x2c,0x35,0x3c,0x42,0x4a,0x51,0x56,0x56,0x53,0x4e,0x49,0x40,0x3a,0x33,0x2c,0x25, +0x1f,0x1c,0xf9,0xa2,0x30,0x55,0x1f,0x2b,0x31,0x35,0x38,0x3b,0x3e,0x3f,0x3f,0x3d, +0x3a,0x34,0x2d,0x27,0x23,0x1d,0x17,0x10,0x9, 0x4, 0x1, 0x0, 0x0, 0x1, 0x3, 0x6, +0xa, 0xf, 0x15,0x1b,0x20,0x23,0x45,0x42,0x3e,0x38,0x34,0x2d,0x24,0x1c,0x15,0x11, +0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x3, 0x7, 0xd, 0x12,0x18,0x20,0x28,0x30,0x36, +0x3c,0x42,0x47,0x48,0x49,0x4a,0x65,0x9d,0x30,0x55,0x1c,0x2a,0x33,0x39,0x3c,0x3e, +0x3f,0x3f,0x3e,0x3d,0x3a,0x35,0x2e,0x28,0x23,0x1c,0x15,0xf, 0x9, 0x4, 0x1, 0x0, +0x0, 0x1, 0x1, 0x4, 0x8, 0xd, 0x13,0x19,0x1e,0x22,0x40,0x3e,0x3a,0x33,0x2f,0x29, +0x22,0x1b,0x15,0x10,0xa, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x5, 0xa, 0x11,0x17,0x1c, +0x24,0x2a,0x30,0x35,0x3b,0x40,0x43,0x44,0x45,0x45,0xcb,0xc6,0x30,0x55,0x5, 0x3, +0x4, 0x7, 0xa, 0x10,0x17,0x21,0x28,0x2e,0x33,0x38,0x3c,0x3e,0x3f,0x3f,0x3e,0x3b, +0x38,0x31,0x29,0x21,0x18,0xf, 0x9, 0x4, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26,0x35, +0x3d,0x45,0x4b,0x51,0x53,0x52,0x4f,0x4c,0x46,0x41,0x3b,0x34,0x2e,0x25,0x1e,0x17, +0x11,0x9, 0x3, 0x0, 0x0, 0x2, 0x6, 0xc, 0x12,0x18,0x1e,0x24,0x2c,0x31,0xf4,0xb6, +0x30,0x55,0xa, 0x5, 0x5, 0x5, 0x8, 0xf, 0x16,0x20,0x29,0x31,0x36,0x3a,0x3c,0x3e, +0x3f,0x3f,0x3e,0x3c,0x3a,0x33,0x2d,0x24,0x1c,0x14,0xf, 0x8, 0x4, 0x0, 0x0, 0x0, +0x1, 0x2, 0x35,0x46,0x4e,0x56,0x5d,0x65,0x68,0x66,0x60,0x57,0x4f,0x47,0x3f,0x37, +0x2e,0x25,0x1e,0x16,0x10,0x6, 0x2, 0x0, 0x1, 0x5, 0xb, 0x15,0x1d,0x28,0x2f,0x39, +0x41,0x45,0xf0,0xbc,0x30,0x55,0x7, 0x3, 0x3, 0x3, 0x4, 0x7, 0xf, 0x17,0x20,0x28, +0x30,0x36,0x3b,0x3d,0x3f,0x3f,0x3d,0x39,0x36,0x2d,0x25,0x1d,0x16,0xd, 0x8, 0x2, +0x0, 0x0, 0x1, 0x2, 0x3, 0x5, 0x2e,0x3f,0x48,0x50,0x59,0x5f,0x67,0x68,0x63,0x5d, +0x52,0x4a,0x3e,0x35,0x2b,0x20,0x18,0x10,0xa, 0x3, 0x0, 0x0, 0x1, 0x7, 0xe, 0x19, +0x22,0x2b,0x31,0x3a,0x42,0x47,0xef,0xc9,0x30,0x55,0x3b,0x3c,0x3c,0x3b,0x39,0x36, +0x2f,0x27,0x21,0x19,0x11,0xb, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x4, 0x6, 0xa, 0x10, +0x16,0x1f,0x26,0x2d,0x33,0x39,0x3c,0x3e,0x3f,0x3f,0x22,0x31,0x3b,0x41,0x47,0x4d, +0x56,0x59,0x5a,0x58,0x55,0x51,0x4b,0x43,0x3d,0x35,0x29,0x20,0x18,0x11,0x9, 0x3, +0x0, 0x0, 0x1, 0x3, 0x7, 0xf, 0x15,0x1b,0x21,0x26,0x2b,0xa0,0x30,0x55,0x37,0x38, +0x37,0x34,0x2d,0x26,0x1c,0x16,0xe, 0x9, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, +0xa, 0x10,0x17,0x20,0x26,0x2e,0x35,0x3a,0x3c,0x3e,0x3f,0x3f,0x3e,0x3e,0x30,0x40, +0x49,0x50,0x59,0x5e,0x60,0x5d,0x56,0x50,0x47,0x41,0x39,0x33,0x2a,0x20,0x1a,0x10, +0xa, 0x5, 0x1, 0x0, 0x0, 0x3, 0x8, 0x10,0x17,0x1f,0x25,0x2f,0x38,0x3c,0x37,0xc3, +0x30,0x55,0x3b,0x3d,0x3d,0x3b,0x38,0x32,0x27,0x1c,0x13,0xe, 0x8, 0x3, 0x0, 0x0, +0x0, 0x1, 0x3, 0x7, 0xb, 0x12,0x18,0x20,0x28,0x31,0x39,0x3d,0x3f,0x40,0x3f,0x3f, +0x3e,0x3e,0x33,0x45,0x4e,0x57,0x5d,0x65,0x6c,0x6a,0x66,0x63,0x5c,0x53,0x4a,0x40, +0x38,0x2e,0x25,0x1a,0x11,0x8, 0x4, 0x0, 0x0, 0x2, 0x9, 0x10,0x19,0x21,0x2a,0x32, +0x39,0x3e,0x7, 0x90,0x30,0x55,0x39,0x2b,0x24,0x1c,0x15,0xe, 0x9, 0x6, 0x5, 0x6, +0x9, 0x10,0x19,0x22,0x27,0x2e,0x35,0x3b,0x3e,0x3f,0x3d,0x38,0x32,0x2c,0x26,0x1f, +0x19,0x13,0xb, 0x5, 0x1, 0x0, 0x6, 0x0, 0x1, 0x2, 0x6, 0xb, 0x11,0x17,0x1d,0x24, +0x2a,0x2f,0x32,0x34,0x35,0x36,0x37,0x3b,0x41,0x47,0x4e,0x56,0x5d,0x61,0x64,0x65, +0x65,0x63,0x60,0x5c,0x57,0x54,0xd1,0x4a,0x46,0x55,0x0, 0x1, 0x3, 0x5, 0x7, 0x8, +0xa, 0xb, 0xc, 0xe, 0xf, 0x11,0x12,0x14,0x16,0x1a,0x1e,0x22,0x24,0x27,0x2a,0x2c, +0x2e,0x31,0x33,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x3f,0x1, 0xe, 0x14,0x1b,0x23,0x28, +0x2e,0x35,0x3a,0x40,0x48,0x4f,0x56,0x5d,0x62,0x61,0x5a,0x53,0x4e,0x47,0x40,0x3b, +0x35,0x2d,0x29,0x22,0x1b,0x17,0x10,0x9, 0x5, 0x1, 0x6d,0x7d,0x54,0x55,0x0, 0x2, +0x3, 0x5, 0x6, 0x8, 0xb, 0x10,0x13,0x16,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x22,0x22, +0x22,0x22,0x23,0x25,0x28,0x2e,0x31,0x34,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x6, 0x17, +0x20,0x27,0x30,0x38,0x3e,0x39,0x32,0x2b,0x25,0x1e,0x18,0x10,0x9, 0x9, 0x10,0x18, +0x1f,0x26,0x2f,0x36,0x3c,0x38,0x2f,0x27,0x1f,0x18,0xf, 0x8, 0x1, 0x2, 0xc7,0x75, +0x31,0x55,0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x8, 0xd, 0x12,0x15,0x17,0x18,0x1a, +0x1b,0x1c,0x1d,0x1d,0x1e,0x1f,0x22,0x27,0x2e,0x35,0x38,0x3b,0x3d,0x3e,0x3f,0x40, +0x3f,0x3e,0x6, 0x15,0x1b,0x23,0x29,0x2f,0x37,0x3c,0x37,0x2e,0x27,0x20,0x1a,0x13, +0xe, 0x14,0x1a,0x21,0x27,0x2f,0x38,0x3f,0x3d,0x35,0x2e,0x26,0x20,0x18,0x11,0xb, +0x3, 0x0, 0x67,0x3f,0x31,0x55,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, +0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x1c,0x1d,0x1e,0x1f,0x20, +0x21,0x22,0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xe, +0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x0, 0x1, 0x2, 0x3, 0x4, 0x1c,0x1d,0x1e, +0x1f,0x20,0x0, 0x1, 0x2, 0x3, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, +0x18,0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x6, 0x5, 0x4, 0x3, 0x2, 0x1, +0x0, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16, +0x17,0x18,0x19,0x1a,0x1b,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, +0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, +0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x1, 0x1, 0x10,0x1c,0x2, 0x10, +0x1c,0x0, 0x1, 0x1, 0x4, 0xf, 0x1c,0x0, 0x1, 0x1, 0x6, 0x1b,0xf, 0x7, 0xe, 0x1c, +0x8, 0x23,0x15,0x0, 0x1, 0x1, 0xa, 0x10,0x19,0xb, 0x14,0x1c,0xc, 0xf, 0x18,0x0, +0x1, 0x1, 0xe, 0x23,0x15,0xf, 0xd, 0x19,0x0, 0x1, 0x1, 0x11,0xd, 0x14,0x12,0x10, +0x19,0x13,0x1c,0x10,0x14,0x1a,0x10,0x15,0x10,0x19,0x16,0x23,0x1c,0x72,0x23,0x15, +0x73,0x23,0x1c,0x74,0x23,0x1c,0x75,0xe, 0x1c,0xc2,0xd5,0x7c,0xb4,0x30,0xe7,0x8, +0xb2,0xd5,0x6e,0x24,0xff,0xff,0xb, 0x24,0x7c,0xb6,0x30,0xe7,0x12,0xb2,0xd5,0x6e, +0x34,0xff,0xff,0xb, 0x34,0x8d,0x32,0x6e,0x24,0xff,0xff,0xb, 0x24,0x80,0x2, 0x8d, +0x32,0x30,0xd5,0x6, 0x6e,0x34,0xff,0xff,0xb, 0x34,0x22,0x7d,0x51,0xad,0x3, 0x7d, +0x2, 0x7d,0x21,0xad,0x5, 0x2d,0x12,0xad,0x35,0x2d,0x21,0x22,0x7d,0x2, 0xad,0x31, +0xad,0x10,0x2d,0x21,0x22,0x6d,0x0, 0x74,0x10,0x4d,0x0, 0x78,0xb, 0x4d,0x22,0x78, +0x27,0x8d,0x31,0x7d,0x12,0x6d,0x22,0x22,0x7d,0x43,0x7d,0x32,0x6d,0x22,0x2f,0x11, +0x2d,0x44,0x50,0x2, 0xa5,0xf, 0xbf,0x10,0x40,0x4, 0x9f,0x10,0xb, 0x90,0x14,0x78, +0xed,0x7f,0x1, 0x6d,0x22,0x7d,0x34,0x22,0x7d,0x41,0x7d,0x13,0x8d,0x24,0x7d,0x2, +0x2f,0x0, 0x40,0x4, 0xbd,0x4, 0x40,0x4, 0x9d,0x4, 0xb, 0x14,0x14,0x78,0xf1,0x7d, +0x23,0x7d,0x31,0x7d,0x10,0x6d,0x0, 0x22,0xc2,0xd5,0x7c,0xb0,0x30,0xe7,0x8, 0xb2, +0xd5,0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x7c,0xb4,0x30,0xe7,0x13,0xb2,0xd5,0x9f,0x22, +0x9f,0x21,0x7f,0x12,0x12,0x1f,0x7, 0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x80,0x3, 0x12, +0x1f,0x7, 0x30,0xd5,0x6, 0x9f,0x22,0x9f,0x21,0x7f,0x12,0x22,0x6c,0xaa,0x4d,0x11, +0x68,0x1a,0x1e,0x54,0x68,0xe, 0xb, 0x38,0x20,0x1b,0x18,0x20,0xb, 0x35,0xb, 0x15, +0x1b,0x54,0x78,0xf2,0x50,0x6, 0x7e,0x39,0x40,0x7a,0x19,0x40,0x22,0x6c,0xaa,0x4d, +0x11,0x68,0x1e,0x1e,0x54,0x50,0xc, 0x7e,0x1b,0x0, 0x7a,0x19,0x0, 0x68,0x12,0xb, +0x1c,0xb, 0x14,0xb, 0x1a,0x0, 0x1b,0x18,0x0, 0xb, 0x1d,0xb, 0x15,0x1b,0x54,0x78, +0xf2,0x22,0x75,0x84,0x1, 0x7e,0x44,0x3f,0xff,0xe4,0x7a,0x49,0xb0,0x1b,0x44,0x78, +0xf9,0x7e,0xf8,0x3a,0x10,0x75,0xc, 0x0, 0x75,0xd, 0x0, 0x75,0xe, 0x2, 0x75,0xf, +0x0, 0xc2,0x8, 0xc2,0x9, 0x75,0x1d,0x0, 0xc2,0x10,0xc2,0x11,0xc2,0x13,0x75,0x1e, +0x0, 0x75,0x1f,0x0, 0xc2,0xa, 0xc2,0xb, 0x75,0x5a,0x0, 0xc2,0x15,0x75,0x5b,0x0, +0xc2,0x17,0x75,0x5c,0x0, 0xc2,0x18,0xc2,0x19,0xc2,0x1a,0x75,0x5d,0x0, 0xc2,0xc, +0x75,0x1b,0x0, 0x75,0x1c,0x64,0xc2,0x1b,0xc2,0x1c,0x75,0x5e,0x0, 0xd2,0x5, 0xd2, +0x6, 0xd2,0x7, 0xd2,0x1d,0xc2,0xe, 0xd2,0xf, 0x7e,0x4, 0x0, 0xff,0x7e,0x14,0x21, +0x1a,0xb, 0xa, 0x40,0x5d,0x44,0x68,0x1a,0x69,0x20,0x0, 0x2, 0xb, 0xe, 0xb, 0x44, +0x80,0xa, 0x7e,0xb, 0xb0,0x7a,0x29,0xb0,0xb, 0x24,0xb, 0xc, 0x1b,0x44,0x78,0xf2, +0x80,0xdf,0x2, 0x28,0x9, 0x0, 0x0, 0x0, 0x47,0x0, 0xcb,0x1, 0x0, 0x0, 0x10,0xfd, +0xc7,0xfb,0x7e,0xfb,0xfb,0x1, 0xbb,0xc, 0x9e,0x19,0x0, 0x21,0x45,0x0, 0xe, 0x1, +0xf, 0x2, 0x10,0x3, 0x11,0x4, 0x12,0x5, 0x13,0x6, 0x14,0x7, 0x15,0x8, 0x16,0x9, +0x17,0xa, 0x18,0xb, 0x19,0xc, 0x1a,0xd, 0x1b,0xdf,0x22,0xc3,0x21,0xa9,0x20,0x94, +0x1f,0x81,0x1e,0x70,0x1d,0x62,0x1c,0x55,0x1b,0x4a,0x1a,0x41,0x19,0x38,0x18,0x31, +0x17,0x2b,0x16,0x25,0x15,0x21,0x14,0x1c,0x13,0x19,0x12,0x16,0x11,0x13,0x10,0x11, +0xf, 0x10,0xe, 0xca,0xf8,0x7f,0x20,0x80,0xa, 0x7e,0x1b,0xf0,0x7a,0x2b,0xf0,0xb, +0x34,0xb, 0x54,0x69,0xff,0xff,0xfc,0x7d,0xef,0x1b,0xe4,0x79,0xef,0xff,0xfc,0x4d, +0xff,0x78,0xe6,0x7f,0x10,0xda,0xf8,0x22,0x7d,0x43,0x7f,0x10,0x80,0x7, 0x1b,0x44, +0x7a,0xb, 0xb0,0xb, 0x14,0x4d,0x44,0x78,0xf5,0x22,0xff,0x0, 0x1, 0x2, 0x0, 0xff, +0x1, 0x2, 0x0, 0x1, 0xff,0x2, 0x0, 0x1, 0x2, 0xff,0x7d,0x23,0xbe,0x24,0x0, 0x0, +0x48,0x3, 0x7d,0x32,0x22,0x6d,0x33,0x9d,0x32,0x22,0x0, 0x4, 0x32,0xe5,0x0, 0x0, +0x0, 0x0, 0x0, 0x1, 0x3, 0xff,0x1, 0x0, 0x1, 0x25,0xf6,0x1, 0x0, 0x1, 0x38,0x9c, +0x0, 0x0, 0x2, 0x38,0xee,0x0, 0x0, 0x0, 0x2, 0x38,0xf0,0x0, 0x0, 0x0, 0x1, 0x38, +0xf2,0x0, 0x0, 0x1, 0x37,0xe1,0xff,0x0, 0x1, 0x34,0x4f,0x0, 0x0, 0x1, 0x3a,0xe, +0x0, 0x0, 0x1, 0x34,0x8b,0x0, 0x0, 0x2, 0x34,0xb4,0x0, 0x0, 0x0, 0x1, 0x34,0xb6, +0x0, 0x0, 0x1, 0x34,0xc4,0x0, 0x0, 0x1, 0x34,0xc5,0x0, 0x0, 0x1, 0x34,0xda,0x0, +0x0, 0x1, 0x34,0xdb,0x0, 0x0, 0x1, 0x35,0x54,0x0, 0x0, 0x1, 0x35,0x55,0x1, 0x0, +0x1, 0x35,0x56,0x0, 0x0, 0x3c,0x36,0xe9,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x37,0x61,0x0, 0x0, 0x1, 0x37,0x62,0x0, 0x0, 0x1, +0x37,0x63,0x0, 0x0, 0x1, 0x36,0xe2,0x1, 0x0, 0x2, 0x36,0xe5,0x0, 0x0, 0x0, 0x1, +0x2f,0xa9,0x0, 0x0, 0x1, 0x2f,0xaa,0x0, 0x0, 0x1, 0x2f,0xab,0x0, 0x0, 0x1, 0x37, +0x66,0x1, 0x0, 0x1, 0x37,0xe0,0x0, 0x0, 0x1, 0x3a,0xf, 0x0, 0x0, 0x6, 0x39,0xfc, +0x3f,0x1f,0x50,0x11,0x20,0x10,0x0, 0x1, 0x3a,0x2, 0x24,0x0, 0x1, 0x3a,0x9, 0x0, +0x0, 0x1, 0x3a,0xa, 0x0, 0x0, 0x1, 0x3a,0xb, 0x0, 0x0, 0x1, 0x3a,0xc, 0x0, 0x0, +0x1, 0x3a,0xd, 0x0, 0x0, 0x1, 0x0, 0x5f,0x0, 0x0, 0x1, 0x3, 0xfc,0x0, 0x0, 0x1, +0x31,0xcd,0x0, 0x0, 0x2, 0x31,0xee,0x0, 0x0, 0x0, 0x1, 0x32,0x2c,0x0, 0x0, 0x4, +0x38,0x41,0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3a,0x3, 0x0, 0x0, 0x1, 0x3a,0x4, 0x0, +0x0, 0x2, 0x3a,0x5, 0x0, 0x0, 0x0, 0x1, 0x3a,0x7, 0x64,0x0, 0x1, 0x3a,0x8, 0x0, +0x0, 0x1, 0x3a,0x10,0x0, 0x0, 0x1, 0x3, 0xfd,0x0, 0x0, 0x1, 0x3, 0xfe,0x0, 0x0, +0x2, 0x2b,0xb9,0x2b,0xbf,0x0, 0x1, 0x2f,0x7f,0x2, 0x0, 0x1, 0x2f,0xa8,0x0, 0x0, +0x1, 0x39,0x3f,0xff,0x0, 0x1, 0x39,0x40,0x0, 0x0, 0x1, 0x39,0x41,0x0, 0x0, 0x1, +0x39,0x42,0x40,0x0, 0x1, 0x39,0x43,0x40,0x0, 0x1, 0x39,0xde,0x0, 0x0, 0x4, 0x39, +0xf4,0x0, 0x0, 0x50,0x0, 0x0, 0x4, 0x39,0xf8,0x0, 0x0, 0x64,0x0, 0x0, 0x4, 0x39, +0xc1,0x0, 0x0, 0x6c,0x0, 0x0, 0x4, 0x39,0xc5,0x0, 0x0, 0x68,0xc0,0x0, 0x4, 0x39, +0xc9,0x0, 0x0, 0x68,0x0, 0x0, 0x4, 0x39,0xda,0x0, 0x0, 0x40,0x0, 0x0, 0x4, 0x33, +0xfc,0x0, 0x0, 0x60,0x0, 0x0, 0x0, 0x3, 0x84,0x0, 0xd, 0x1, 0xf4,0x2, 0xbc,0x0, +0xd, 0x1, 0x4a,0x2, 0x58,0x0, 0xc, 0x0, 0xc8,0x1, 0xf4,0x0, 0xb, 0x0, 0xa0,0x1, +0x90,0x0, 0x9, 0x0, 0x50,0x0, 0xc8,0x0, 0x7, 0x0, 0x1e,0x0, 0x3c,0x0, 0x14,0x0, +0x18,0x0, 0xe, 0x1c,0x23,0x5, 0xdc,0x0, 0x32,0x3, 0xe8,0x0, 0x28,0x0, 0x0, 0x0, +0x1e,0x12,0x31,0xa9,0x12,0x23,0x91,0x12,0x23,0x5c,0x12,0x24,0x36,0x2, 0x23,0x20, +0x12,0x23,0x31,0x7e,0xb3,0x2b,0xf, 0x12,0x57,0xfc,0x74,0x1, 0x7a,0xb3,0x37,0x6a, +0x22,0x12,0xab,0x26,0x74,0x1, 0x7a,0xb3,0x37,0x66,0x22,0x12,0x23,0xc8,0x12,0x28, +0x2b,0x12,0x58,0xef,0x12,0x31,0xa9,0x12,0x23,0xc8,0x12,0x23,0x91,0x12,0xc6,0x6e, +0x12,0x23,0x5c,0x12,0x24,0x36,0x12,0x24,0x66,0x2, 0x23,0x20,0x12,0x59,0x38,0x12, +0x23,0xae,0x2, 0x23,0x65,0x7e,0x34,0x0, 0x3, 0x6d,0x22,0x2, 0x23,0x6e,0x7d,0x43, +0x7e,0xa3,0x34,0x38,0xbe,0xa0,0x5, 0x50,0x16,0x7e,0x70,0x4, 0xac,0x7a,0x59,0x43, +0x34,0x3b,0x59,0x23,0x34,0x3d,0x7c,0xba,0x4, 0x7a,0xb3,0x34,0x38,0xc3,0x22,0xd3, +0x22,0x12,0x36,0xad,0x12,0x69,0x83,0x2, 0x23,0x9a,0x30,0x13,0x10,0x12,0x57,0x8e, +0x50,0x3, 0x12,0x51,0xf9,0x12,0x69,0xa9,0x12,0x55,0xae,0xc2,0x13,0x22,0x6d,0x33, +0x7e,0x24,0x6, 0xfc,0x12,0x23,0x6e,0x7e,0x34,0x0, 0x1, 0x7e,0x24,0x7, 0x7a,0x2, +0x23,0x6e,0x74,0x1, 0x7a,0xb3,0x38,0xa1,0x7e,0x34,0xd, 0xac,0x6d,0x22,0x7a,0x27, +0x33,0xeb,0x7a,0x37,0x33,0xed,0x22,0xca,0xf8,0x7e,0xf3,0x38,0xa1,0xbe,0xf0,0x5, +0x78,0xb, 0x74,0x1, 0x7a,0xb3,0x38,0xa1,0x12,0x0, 0xa, 0x80,0x40,0xbe,0xf0,0x4, +0x78,0xd, 0x12,0x23,0xc2,0xe4,0x7a,0xb3,0x2b,0x2, 0x12,0x36,0xad,0x80,0x2e,0xbe, +0xf0,0x6, 0x78,0x13,0x12,0x23,0xc2,0x12,0x3b,0xd3,0xe4,0x7a,0xb3,0x2b,0x1e,0x12, +0x69,0x83,0x12,0xc6,0xd0,0x80,0x16,0xbe,0xf0,0x7, 0x78,0x17,0x12,0x23,0xc2,0x12, +0x69,0x78,0x50,0xfb,0x12,0x6a,0xb8,0x12,0x23,0x9a,0x12,0x24,0x36,0x74,0x2, 0x7a, +0xb3,0x38,0xa1,0xda,0xf8,0x22,0xe4,0x7a,0xb3,0x34,0x3a,0x7a,0xb3,0x34,0x39,0x12, +0x3f,0xd2,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x2, 0x74,0x3, 0x7a,0xb3,0x34,0x3a,0x22, +0x12,0xc6,0x6e,0x12,0x4a,0x2e,0x7a,0x37,0x3a,0x5, 0x12,0x23,0xc8,0x12,0x23,0x91, +0x12,0x24,0x36,0x2, 0x24,0x66,0x74,0xa, 0x7a,0xb3,0x34,0x89,0xe4,0x7a,0xb3,0x34, +0x8a,0x7e,0x8, 0x34,0x8c,0x7e,0x34,0x0, 0xa, 0x74,0xa, 0x12,0x20,0xe8,0x7e,0x8, +0x34,0x96,0x7e,0x34,0x0, 0xa, 0xe4,0x2, 0x20,0xe8,0xca,0x3b,0x12,0x69,0x78,0x50, +0xfb,0x7e,0xf3,0x2b,0xf, 0x7c,0xbf,0x12,0x8b,0x38,0x12,0xb8,0xc9,0x7e,0xb3,0x2b, +0x1f,0xf5,0x28,0x7e,0xc3,0x2b,0x20,0x7e,0xb3,0x38,0x9, 0xb4,0x1, 0xf, 0x12,0x51, +0xbf,0x7e,0xb3,0x16,0x91,0x70,0x6, 0x12,0x24,0x36,0xc3,0xa1,0x86,0x12,0x25,0x89, +0x3e,0x34,0xca,0x39,0x7e,0x18,0x6, 0xfc,0x7e,0x8, 0x4, 0x7e,0x12,0x20,0xc3,0x1b, +0xfd,0x12,0x25,0x89,0x3e,0x34,0xca,0x39,0x7e,0x18,0x7, 0x7a,0x7e,0x8, 0x4, 0x0, +0x12,0x20,0xc3,0x1b,0xfd,0x7e,0xb3,0x38,0x9, 0xb4,0x3, 0x7, 0x12,0xa5,0x25,0x7a, +0x37,0x38,0xe4,0x74,0x1, 0x7a,0xb3,0x16,0x90,0x12,0x23,0x91,0x12,0xa5,0x16,0x12, +0x50,0xd8,0xe4,0x12,0x13,0xde,0x12,0x24,0x36,0x7e,0x8, 0x4, 0x7e,0x7a,0xd, 0x29, +0x7e,0x18,0x6, 0x76,0x7e,0xb3,0x2b,0x72,0x12,0xb9,0xea,0x7e,0x8, 0x4, 0x0, 0x7a, +0xd, 0x29,0x7e,0x18,0x5, 0xf8,0x7e,0xb3,0x25,0xf0,0x12,0xb9,0xea,0x7e,0xd3,0x2b, +0x1f,0x7e,0xe3,0x2b,0x20,0xe5,0x28,0x7a,0xb3,0x2b,0x1f,0x7a,0xc3,0x2b,0x20,0x7e, +0x34,0x8, 0xa, 0x7e,0x4, 0xd, 0xc8,0x7d,0x20,0x7d,0x10,0x12,0x56,0x2d,0x7a,0xd3, +0x2b,0x1f,0x7a,0xe3,0x2b,0x20,0x7c,0xbf,0x12,0x8a,0xbb,0x12,0xa4,0x16,0x7e,0xb3, +0x3a,0x8, 0x4, 0x7a,0xb3,0x3a,0x8, 0x7e,0x73,0x3a,0x8, 0xbe,0x70,0xfa,0x28,0x6, +0x74,0x64,0x7a,0xb3,0x3a,0x8, 0x7e,0xb3,0x16,0x90,0x60,0x9, 0x7e,0xb3,0x16,0x91, +0x60,0x3, 0xd3,0x80,0x1, 0xc3,0xda,0x3b,0x22,0x7e,0x73,0x2a,0x74,0xa, 0x27,0x7e, +0x73,0x2a,0x73,0xa, 0x37,0x2d,0x32,0x22,0x12,0x3a,0xc6,0x7e,0xb3,0x38,0x9, 0xb4, +0x3, 0x69,0x12,0xb8,0x28,0x12,0x2f,0xe7,0x12,0x2d,0x59,0x7e,0xb3,0x38,0x9d,0x30, +0xe7,0xe9,0x12,0x24,0x8a,0x12,0x25,0x89,0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, 0x0, +0x7e,0x8, 0x4, 0xfc,0x12,0x20,0xc3,0x1b,0xfd,0x12,0x25,0x89,0x3e,0x34,0xca,0x39, +0x7e,0x18,0x4, 0x7e,0x7e,0x8, 0x5, 0x7a,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0xb3,0x2b, +0x1d,0xb4,0x1, 0x15,0x12,0x67,0x6c,0x12,0x85,0xfd,0x12,0x44,0xaf,0x12,0x6a,0xc3, +0x12,0x77,0x1d,0x12,0x26,0x1b,0x12,0x3f,0xfa,0x12,0x3b,0x8, 0x12,0xad,0x82,0x7e, +0xb3,0x38,0x9d,0x54,0x7f,0x7a,0xb3,0x38,0x9d,0x80,0x90,0x12,0x6a,0x6d,0x2, 0x0, +0x46,0xe4,0x7a,0xb3,0x2b,0x2, 0x7a,0xb3,0x2b,0x1e,0x22,0x12,0x73,0x74,0x12,0x75, +0x4a,0x12,0x75,0x4a,0x12,0x8c,0xdb,0x12,0xa1,0xc1,0x12,0x88,0x7e,0x12,0x75,0x4a, +0x12,0x92,0xe7,0x12,0x75,0x4a,0x12,0x96,0xc8,0x12,0x75,0x4a,0x2, 0x26,0x3f,0xca, +0x3b,0x75,0x24,0x0, 0x6c,0xcc,0x6c,0xdd,0x7e,0xc4,0x0, 0x3c,0xca,0xc9,0x7e,0x18, +0x37,0x25,0x7e,0x8, 0x36,0xe9,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0xf3,0x28,0x84,0xa, +0xcf,0x3e,0xc4,0xca,0xc9,0x7e,0x18,0x26,0xfa,0x7e,0x8, 0x1f,0x34,0x12,0x20,0xc3, +0x1b,0xfd,0x6c,0x88,0x6c,0xee,0xe1,0x13,0x7e,0xc4,0x3, 0xff,0x7e,0xc0,0xff,0x6c, +0x99,0x80,0x4c,0x74,0x2, 0xac,0xb9,0x9, 0xb5,0x1f,0x34,0xbe,0xb0,0xff,0x68,0x3d, +0x7c,0xb9,0x12,0x88,0x65,0x60,0x36,0x74,0x2, 0xac,0xb9,0x9, 0x75,0x1f,0x35,0xa, +0x27,0x74,0x2, 0xac,0xbe,0x9, 0x75,0x37,0x26,0x12,0x96,0xa4,0x7d,0x13,0x74,0x2, +0xac,0xb9,0x9, 0x75,0x1f,0x34,0xa, 0x27,0x74,0x2, 0xac,0xbe,0x9, 0x75,0x37,0x25, +0x12,0x96,0xa4,0x2d,0x13,0xbd,0xc1,0x28,0x4, 0x7d,0xc1,0x7c,0xc9,0xb, 0x90,0xbc, +0xf9,0x38,0xb0,0xbe,0xc0,0xff,0x68,0x39,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x1f, +0x34,0x9, 0x73,0x1f,0x35,0x12,0x6d,0xcb,0xbe,0x37,0x2a,0x5a,0x48,0x23,0x7e,0x70, +0x2, 0xac,0x7c,0x9, 0x53,0x1f,0x34,0x74,0x2, 0xac,0xbd,0x19,0x55,0x1f,0x70,0x9, +0x53,0x1f,0x35,0x19,0x55,0x1f,0x71,0x74,0xff,0x19,0xb3,0x1f,0x34,0xb, 0x80,0xb, +0xd0,0xb, 0xe0,0x7e,0x73,0x36,0xe8,0xbc,0x7e,0x28,0x2, 0xc1,0x78,0x7c,0xe8,0x80, +0x6d,0x6d,0xdd,0x7e,0x80,0xff,0x6c,0x99,0x80,0x3c,0x7c,0xb9,0x12,0x88,0x65,0x60, +0x33,0x12,0xc6,0x99,0xbe,0xb0,0xff,0x68,0x2b,0x9, 0x73,0x1f,0x35,0x12,0x6f,0x81, +0x7f,0x71,0xb, 0x7a,0x50,0xbe,0x54,0x0, 0x0, 0x58,0x5, 0x6d,0x55,0x1b,0x7a,0x50, +0xb, 0x7a,0xc0,0xbd,0xcd,0x8, 0xd, 0x12,0xc6,0x99,0xf5,0x24,0x9, 0xc3,0x1f,0x35, +0x7d,0xdc,0x7c,0x89,0xb, 0x90,0xbc,0xf9,0x38,0xc0,0xbe,0x80,0xff,0x68,0x1d,0x7e, +0x71,0x24,0x74,0x2, 0xac,0xbd,0x19,0x75,0x1f,0x70,0x19,0xc5,0x1f,0x71,0x7e,0xa0, +0xff,0x7e,0x70,0x2, 0xac,0x78,0x19,0xa3,0x1f,0x34,0xb, 0xd0,0xb, 0xe0,0xbe,0xe0, +0xa, 0x40,0x8e,0x7e,0x34,0x0, 0x3c,0xca,0x39,0x7e,0x18,0x1f,0x70,0x7e,0x8, 0x1f, +0x34,0x12,0x20,0xc3,0x1b,0xfd,0x7c,0xfd,0x7e,0x8, 0x37,0x25,0x7e,0x34,0x0, 0x14, +0x74,0xff,0x12,0x20,0xe8,0xbe,0xf0,0x0, 0x28,0x35,0xa, 0x3f,0x3e,0x34,0xca,0x39, +0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x26,0xfa,0x12,0x20,0xc3,0x1b,0xfd,0xa, 0x3f,0x3e, +0x34,0xca,0x39,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x37,0x25,0x12,0x20,0xc3,0x1b,0xfd, +0x6c,0xee,0x80,0x7, 0x7c,0xbe,0x12,0x76,0xfb,0xb, 0xe0,0xbc,0xfe,0x38,0xf5,0x7a, +0xf3,0x36,0xe8,0x7a,0xf3,0x28,0x84,0x7e,0x73,0x28,0x84,0xbe,0x70,0xa, 0x28,0x6, +0x74,0xa, 0x7a,0xb3,0x28,0x84,0xda,0x3b,0x22,0x12,0x28,0x2b,0x12,0x62,0xf6,0x12, +0x58,0xef,0x12,0x23,0x11,0x7e,0xb3,0x38,0x9, 0x24,0xfd,0x68,0x9, 0xb, 0xb1,0x78, +0xf4,0x12,0x40,0x98,0x80,0xef,0x12,0x25,0x98,0x80,0xea,0xe4,0x12,0xb6,0xbd,0x12, +0xb7,0xaa,0x12,0x2f,0xe7,0x12,0xb8,0x21,0x12,0x28,0x6e,0x12,0xb6,0x6b,0x12,0xb7, +0xc1,0x12,0x0, 0x9, 0x12,0xb7,0xcd,0x12,0x68,0xad,0x12,0xb7,0xdd,0xd2,0xaf,0x12, +0xb7,0x3c,0x12,0x64,0x46,0x12,0x2a,0x98,0x12,0xb7,0x2, 0x7e,0x8, 0x33,0xef,0x12, +0xb8,0x41,0x74,0xe, 0x7e,0x70,0x19,0x7e,0x24,0xff,0xff,0x2, 0x12,0x34,0xa9,0xd5, +0xcb,0x74,0x2, 0x7e,0x70,0x3f,0x12,0x28,0xba,0x74,0xf, 0x12,0x0, 0x66,0x7c,0x7b, +0x74,0xf, 0x5e,0x70,0xfe,0x12,0x28,0xba,0x74,0xc, 0x12,0x0, 0x66,0x54,0x7f,0x68, +0x8, 0x74,0xc, 0x7e,0x70,0xf8,0x12,0x28,0xba,0x7e,0x70,0x72,0x74,0xe, 0x12,0x28, +0xba,0x74,0x7, 0x12,0x0, 0x66,0x7c,0x7b,0x5e,0x70,0xfb,0x74,0x7, 0x2, 0x28,0xb0, +0x12,0x28,0xba,0x75,0xfd,0xff,0xa9,0xc5,0xcb,0x22,0xf5,0xfd,0x7a,0x71,0xfe,0x22, +0xca,0x79,0x7d,0xd3,0x7e,0x80,0xe, 0x7e,0xf0,0x28,0x12,0x2f,0xe7,0xa9,0xd0,0xc4, +0xa9,0xd5,0xcb,0x74,0x7, 0x12,0x0, 0x66,0xf5,0x24,0x74,0x7, 0x7e,0x70,0xf, 0x12, +0x28,0xb0,0x7e,0x54,0x0, 0x78,0x7e,0x1f,0x39,0xc5,0x79,0x51,0x0, 0x6, 0x7e,0x54, +0x0, 0x80,0x7e,0x1f,0x39,0xc5,0x79,0x51,0x0, 0x8, 0x7e,0x54,0x0, 0xc, 0x7e,0x1f, +0x39,0xc5,0x79,0x51,0x0, 0x10,0xbe,0xd4,0x0, 0x2, 0x78,0x7, 0x12,0x2a,0x7d,0x44, +0x1, 0x80,0x1c,0x12,0x2a,0x7d,0x44,0x8, 0x1b,0x1a,0x50,0x4d,0xdd,0x7e,0x1f,0x39, +0xc5,0x78,0x7, 0x12,0x2a,0x81,0x54,0xfb,0x80,0x5, 0x12,0x2a,0x81,0x44,0x4, 0x1b, +0x1a,0x50,0x7e,0x1f,0x39,0xc1,0x69,0xe1,0x0, 0x84,0x69,0x51,0x0, 0x90,0x7d,0xf5, +0x2e,0x34,0x0, 0x90,0x5e,0xa0,0xf6,0x1b,0x1a,0x50,0x7e,0xb3,0x38,0x13,0xbe,0xb0, +0x6, 0x40,0x3, 0xb4,0xff,0xe, 0x12,0x2a,0x8c,0x54,0xe6,0x12,0x2a,0x89,0x4e,0x54, +0x1, 0xa4,0x80,0xc, 0x12,0x2a,0x8c,0x5e,0x54,0xfe,0xe6,0x12,0x2a,0x89,0x44,0xa4, +0x1b,0x1a,0x50,0xbe,0xd4,0x0, 0x2, 0x78,0x26,0x12,0x2f,0x3, 0x5e,0x34,0x0, 0xf, +0x1b,0xa, 0x30,0x12,0x2f,0x3, 0x4e,0x70,0x50,0x1b,0xa, 0x30,0x7e,0x34,0x0, 0x2, +0x12,0x2d,0x3a,0x12,0x2d,0x13,0x12,0x2c,0xf0,0x7a,0x37,0x32,0xe9,0x41,0x3a,0x6c, +0xee,0x41,0x34,0x4c,0xee,0x78,0x4, 0x6c,0x99,0x80,0x2b,0xbc,0x8e,0x40,0x12,0xa, +0xce,0x9, 0x9c,0x2a,0xb8,0xbe,0x90,0x23,0x40,0x3, 0x7e,0x90,0x22,0xb, 0x90,0x80, +0x15,0xa, 0x38,0xa, 0xce,0x9d,0xc3,0x9, 0x9c,0x2a,0xdb,0xbe,0x90,0x1c,0x40,0x3, +0x7e,0x90,0x1b,0x2e,0x90,0x24,0x12,0x2a,0x7d,0x5e,0x54,0x0, 0xf, 0x1b,0x1a,0x50, +0xa, 0xc9,0x3e,0xc4,0x3e,0xc4,0x3e,0xc4,0x3e,0xc4,0x12,0x2a,0x7d,0x4d,0x5c,0x1b, +0x1a,0x50,0xe5,0xe, 0x60,0x7, 0xe5,0xe, 0xbe,0xb0,0x64,0x28,0x6, 0x7e,0x34,0x0, +0x2, 0x80,0x4, 0xe5,0xe, 0xa, 0x3b,0x12,0x2d,0x3a,0x12,0x2d,0x13,0xbe,0xd4,0x0, +0x1, 0x78,0x10,0x12,0x2d,0x13,0x12,0x2c,0xf0,0x74,0x2, 0xac,0xbe,0x59,0x35,0x32, +0xeb,0x80,0xf, 0x12,0x2c,0xf0,0xa, 0x5f,0xa, 0x2e,0x2d,0x25,0x3e,0x24,0x59,0x32, +0x32,0xeb,0xb, 0xe0,0xbc,0xfe,0x28,0x2, 0x21,0xa3,0xa9,0xd5,0xcb,0x74,0x7, 0x7e, +0x71,0x24,0x12,0x28,0xb0,0xa9,0xc0,0xc4,0x7e,0x1f,0x39,0xc1,0x79,0xe1,0x0, 0x84, +0x7e,0x1f,0x39,0xc1,0x79,0xf1,0x0, 0x90,0x6d,0x33,0x7e,0xf, 0x39,0xc5,0x79,0x30, +0x0, 0x6, 0x7e,0xf, 0x39,0xc5,0x79,0x30,0x0, 0x8, 0x7e,0xf, 0x39,0xc5,0x79,0x30, +0x0, 0x10,0x7e,0xf, 0x39,0xc5,0x79,0x30,0x0, 0xe, 0xda,0x79,0x22,0x7e,0x1f,0x39, +0xc5,0x2e,0x34,0x0, 0xe, 0xb, 0x1a,0x50,0x22,0x1b,0x1a,0x50,0x7e,0x1f,0x39,0xc1, +0x2e,0x34,0x0, 0x84,0xb, 0x1a,0x50,0x22,0x6d,0x33,0x7e,0x8, 0x0, 0x24,0x7e,0x24, +0x0, 0x12,0x12,0x63,0x62,0xe5,0x34,0x20,0xe7,0x1b,0xa9,0xd5,0xcb,0x74,0x3, 0x7e, +0x71,0x27,0x12,0x28,0xba,0x74,0xb, 0x7e,0x71,0x2f,0x12,0x28,0xba,0x74,0xc, 0x7e, +0x71,0x30,0x12,0x28,0xb0,0x22,0xca,0xf8,0x7c,0xab,0xbe,0xa0,0x34,0x38,0x2, 0x61, +0xd7,0xbe,0xa0,0x35,0x78,0x6, 0x7e,0xb3,0x2b,0x10,0x81,0xed,0xbe,0xa0,0x36,0x68, +0x5, 0xbe,0xa0,0x37,0x78,0x1d,0x7e,0x35,0x8, 0x7d,0x23,0xb, 0x24,0x7a,0x25,0x8, +0x2e,0x37,0x32,0xe3,0x7e,0x39,0xb0,0xbe,0xa0,0x37,0x68,0x2, 0x81,0xed,0x75,0x1a, +0x36,0x81,0xed,0xbe,0xa0,0x38,0x68,0x5, 0xbe,0xa0,0x39,0x78,0x1b,0x7e,0xf3,0x38, +0xc1,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc1,0xbe,0xa0,0x39,0x78,0x3, 0x75,0x1a,0x38, +0xa, 0x3f,0x9, 0xb3,0x2b,0x21,0x81,0xed,0xbe,0xa0,0x3a,0x68,0x5, 0xbe,0xa0,0x3b, +0x78,0x1b,0x7e,0xf3,0x38,0xc3,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc3,0xbe,0xa0,0x3b, +0x78,0x3, 0x75,0x1a,0x3a,0xa, 0x3f,0x9, 0xb3,0x2b,0x44,0x81,0xed,0xbe,0xa0,0xfb, +0x78,0x6, 0x7e,0xb3,0x2b,0x12,0x81,0xed,0xbe,0xa0,0x5e,0x78,0x26,0x7e,0xf, 0x39, +0xc1,0x69,0x30,0x0, 0x8e,0xa, 0x56,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, +0x1, 0x3, 0x3, 0x54,0xc0,0xa, 0x36,0x5e,0x34,0x0, 0x3, 0x7c,0xa7,0x4c,0xba,0x44, +0x80,0x81,0xed,0xbe,0xa0,0x3c,0x68,0x5, 0xbe,0xa0,0x3d,0x78,0x1b,0x7e,0xf3,0x38, +0xc5,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc5,0xbe,0xa0,0x3d,0x78,0x3, 0x75,0x1a,0x3c, +0xa, 0x3f,0x9, 0xb3,0x2a,0x7a,0x81,0xed,0xbe,0xa0,0x3e,0x68,0x5, 0xbe,0xa0,0x3f, +0x78,0x1b,0x7e,0xf3,0x38,0xc7,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc7,0xbe,0xa0,0x3f, +0x78,0x3, 0x75,0x1a,0x3e,0xa, 0x3f,0x9, 0xb3,0x2a,0x9d,0x81,0xed,0xbe,0xa0,0x40, +0x40,0xd, 0xbe,0xa0,0x4d,0x38,0x8, 0xa, 0x3a,0x9, 0xb3,0x38,0x9d,0x81,0xed,0xbe, +0xa0,0x4e,0x68,0x5, 0xbe,0xa0,0x4f,0x78,0x1e,0x7e,0xf3,0x38,0xe2,0x7c,0xbf,0x4, +0x7a,0xb3,0x38,0xe2,0xbe,0xa0,0x4f,0x78,0x3, 0x75,0x1a,0x4e,0xa, 0x3f,0x2e,0x37, +0x32,0xe1,0x7e,0x39,0xb0,0x81,0xed,0xbe,0xa0,0x51,0x68,0x5, 0xbe,0xa0,0x52,0x78, +0x28,0x7e,0x14,0x60,0x0, 0x6d,0x0, 0x2e,0x4, 0x0, 0xff,0x7e,0xb3,0x38,0xed,0xa, +0x3b,0x6d,0x22,0x2f,0x10,0x7e,0x1b,0x70,0x4, 0x7a,0xb3,0x38,0xed,0xbe,0xa0,0x52, +0x78,0x3, 0x75,0x1a,0x51,0x7c,0xb7,0x81,0xed,0xbe,0xa0,0x5c,0x68,0x5, 0xbe,0xa0, +0x5d,0x78,0x1a,0x7e,0xf3,0x38,0xb6,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xb6,0xbe,0xa0, +0x5d,0x78,0x3, 0x75,0x1a,0x5c,0x7c,0xbf,0x12,0xad,0x2, 0x81,0xed,0xbe,0xa0,0x60, +0x40,0xd, 0xbe,0xa0,0x6c,0x38,0x8, 0xa, 0x3a,0x9, 0xb3,0x33,0x8f,0x80,0x7e,0xbe, +0xa0,0x6d,0x78,0x4, 0xe5,0xe, 0x80,0x75,0xbe,0xa0,0xf4,0x68,0x5, 0xbe,0xa0,0xf5, +0x78,0x18,0x7e,0x35,0xa, 0x7d,0x23,0xb, 0x24,0x7a,0x25,0xa, 0x9, 0xb3,0x32,0xe9, +0xbe,0xa0,0xf5,0x78,0x58,0x75,0x1a,0xf4,0x80,0x53,0xbe,0xa0,0xf0,0x68,0x5, 0xbe, +0xa0,0xf1,0x78,0x9, 0x7c,0x1a,0x2e,0x10,0x20,0xa5,0xe7,0x80,0x40,0xbe,0xa0,0xf2, +0x68,0x5, 0xbe,0xa0,0xf3,0x78,0x1b,0x7e,0x15,0x10,0x3e,0x14,0x7e,0x1f,0x32,0xe5, +0x2d,0x31,0xb, 0x1a,0x30,0xbe,0xa0,0xf2,0x78,0x4, 0xa, 0x56,0x80,0x1f,0x7d,0x53, +0x80,0x1b,0xbe,0xa0,0xf6,0x78,0x4, 0xe5,0xf, 0x80,0x12,0xbe,0xa0,0xf7,0x78,0x4, +0x74,0x32,0x80,0x9, 0xbe,0xa0,0xfd,0x78,0x3, 0xe4,0x80,0x1, 0xe4,0xda,0xf8,0x22, +0x7e,0xf, 0x39,0xc5,0x69,0x30,0x0, 0xa, 0x7d,0x23,0x6d,0x33,0x69,0x10,0x0, 0xc, +0x6d,0x0, 0x2f,0x10,0x74,0x7, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14, +0x78,0xf4,0x22,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x39,0xc5,0x79,0x30,0x0, 0x4, 0x7e, +0xf, 0x39,0xc5,0x69,0x30,0x0, 0x12,0x5e,0x34,0x0, 0x1, 0x68,0xf2,0x7e,0x34,0x0, +0x1, 0x79,0x30,0x0, 0x12,0x22,0x7e,0x34,0x0, 0x1, 0x7d,0x23,0x80,0x12,0x7e,0x30, +0x4, 0x80,0x5, 0x74,0xfa,0x12,0x2f,0x39,0x7c,0x23,0x1b,0x30,0xa5,0xba,0x0, 0xf3, +0x7d,0x32,0x1b,0x24,0x4d,0x33,0x78,0xe6,0x22,0x30,0x8, 0x3b,0xc2,0x8, 0x12,0x23, +0xd7,0x7e,0x73,0x38,0xa2,0x7a,0x73,0x2a,0x4d,0x7e,0x73,0x38,0xa3,0x7a,0x73,0x2b, +0x1d,0x7e,0x73,0x38,0xa3,0x7a,0x73,0x2b,0x1, 0x7e,0xb3,0x38,0xa4,0x60,0x18,0x7e, +0x34,0x0, 0x2, 0x12,0x28,0xc0,0x7e,0x34,0x0, 0x1, 0x12,0x28,0xc0,0x6d,0x33,0x12, +0x28,0xc0,0xe4,0x7a,0xb3,0x38,0xa4,0x12,0x36,0x2d,0x2, 0x2d,0x9d,0xe5,0xc, 0x70, +0x2, 0xc1,0xbc,0xe5,0xc, 0x30,0xe0,0x10,0x53,0xc, 0xfe,0x12,0xaa,0xc5,0x12,0x64, +0xdf,0x7e,0x8, 0x2a,0x6d,0x12,0x9, 0xa1,0xe5,0xc, 0x30,0xe1,0x6, 0x53,0xc, 0xfd, +0x12,0xbb,0x4c,0xe5,0xc, 0x30,0xe2,0x2f,0x53,0xc, 0xfb,0x7e,0xb3,0x2b,0x12,0x60, +0x9, 0x7e,0x8, 0x2a,0x6d,0x12,0x6, 0xba,0x80,0xb, 0x7e,0xb3,0x2b,0x65,0x7e,0x73, +0x2b,0x64,0x12,0xb, 0xad,0x7e,0x73,0x2b,0x12,0x2e,0x70,0xff,0x92,0x1, 0x74,0x19, +0x9e,0xb3,0x2a,0x77,0x12,0xb, 0x1e,0xe5,0xc, 0x30,0xe3,0x4a,0x53,0xc, 0xf7,0x7e, +0x73,0x38,0xcf,0x7a,0x73,0x2b,0xf, 0x12,0x8b,0x16,0x7a,0xb3,0x0, 0x5f,0xbe,0xb0, +0xff,0x68,0xb, 0x43,0xc, 0x20,0x7e,0x73,0x0, 0x5f,0x7a,0x73,0x38,0xa7,0x12,0x51, +0x36,0x12,0x3f,0xeb,0x7e,0x73,0x38,0xd0,0xbe,0x73,0x2b,0x62,0x68,0x6, 0x7a,0x73, +0x2b,0x62,0xd2,0x10,0x30,0x10,0x9, 0xc2,0x10,0x12,0x57,0xd5,0xe4,0x12,0xa, 0x66, +0x12,0x23,0x31,0x12,0x57,0xf8,0xe5,0xc, 0x30,0xe4,0xf, 0x53,0xc, 0xef,0x7e,0x43, +0x38,0xd1,0x7e,0x50,0xa, 0xac,0x45,0x12,0x3a,0xf8,0xe5,0xc, 0x30,0xe6,0x4e,0x53, +0xc, 0xbf,0x7e,0x73,0x38,0xbd,0xbe,0x70,0x7, 0x28,0x6, 0x74,0x7, 0x7a,0xb3,0x38, +0xbd,0xa9,0xd5,0xcb,0x74,0xe, 0x12,0x0, 0x66,0x7c,0x7b,0x5e,0x70,0xf, 0x7e,0x63, +0x38,0xbd,0xa, 0x26,0x2e,0x24,0x0, 0x3, 0x12,0x7f,0x9, 0x7c,0x65,0x4c,0x76,0x74, +0xe, 0x12,0x28,0xba,0x12,0x0, 0x66,0x12,0x28,0xb3,0x7e,0x73,0x38,0xc0,0x7a,0x73, +0x2b,0x14,0x7e,0x73,0x38,0xbf,0x7a,0x73,0x2b,0x1f,0x12,0xc6,0xd0,0xe5,0xc, 0x30, +0xe5,0xa, 0x53,0xc, 0xdf,0x7e,0xb3,0x38,0xa7,0x2, 0x3b,0x46,0x22,0x24,0xab,0x68, +0x10,0x24,0xef,0x68,0x1c,0x24,0xde,0x68,0x26,0x24,0xde,0x78,0x2f,0x74,0x5, 0x80, +0x2d,0x7e,0xb3,0x3, 0xff,0xb4,0x5, 0x2a,0x12,0x2d,0x36,0x12,0xb6,0x75,0x2, 0xb8, +0xe, 0x7e,0xb3,0x3, 0xff,0xb4,0x5, 0x1a,0x12,0x2d,0x36,0x75,0xe9,0xff,0x22,0x7e, +0xb3,0x3, 0xff,0xb4,0x5, 0xc, 0x12,0x2d,0x36,0x2, 0xb8,0x8, 0x74,0x1, 0x7a,0xb3, +0x3, 0xff,0x22,0x7e,0xf, 0x39,0xc5,0x2e,0x14,0x0, 0xe, 0xb, 0xa, 0x30,0x22,0x7c, +0x6b,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x28,0xba,0x7a,0x61,0xfc,0x12,0x28,0xb3,0x12, +0xb7,0x2, 0xd2,0x0, 0x12,0xb6,0xee,0x12,0x2f,0xee,0x12,0x13,0xde,0x2, 0x13,0x96, +0x74,0x4, 0x7d,0x30,0x12,0x2f,0x58,0x74,0x14,0x7c,0xab,0x80,0xe, 0x7e,0x70,0x3, +0x80,0x1, 0x0, 0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, 0xf7,0x7c,0x6a,0x1b,0xa0,0xa5, +0xbe,0x0, 0xea,0x22,0x74,0x2, 0x7d,0x3f,0x7d,0x23,0x7c,0x6b,0xa, 0x14,0x7c,0x73, +0x7d,0x52,0x7c,0xab,0x7e,0xb3,0x3a,0x10,0xb4,0xa5,0x3c,0x12,0x64,0x8d,0x75,0xb5, +0x1, 0xa9,0x36,0xb3,0xfc,0x12,0x2f,0xa8,0xa9,0x36,0xb3,0xfc,0x12,0x2f,0xa8,0xa9, +0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3, +0x7a,0x71,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0xa1,0xb5,0xa9,0x36,0xb3, +0xfc,0xa9,0xc6,0xb3,0xa9,0xd2,0xb4,0x22,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0x22,0x12, +0xc7,0x9, 0xc2,0x0, 0x12,0xb6,0xf9,0xc2,0x2, 0x12,0x2f,0xde,0xc2,0x0, 0x12,0xb6, +0xee,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x0, 0x66,0x7a,0x1b,0xb0,0x74,0xf, 0x6c,0x77, +0x12,0x28,0xba,0xe5,0xfc,0x7a,0xb, 0xb0,0x43,0xfc,0x10,0x2, 0x28,0xb3,0xa9,0xd0, +0xce,0xa2,0x2, 0xa9,0x91,0xc9,0x22,0x7e,0x34,0x3, 0xe8,0x2, 0x23,0xcc,0xd2,0x2, +0x12,0x2f,0xde,0x74,0x1, 0x22,0x12,0xc6,0xd9,0xb4,0x1, 0x19,0xca,0x39,0x7e,0x18, +0x38,0xdd,0x7e,0x8, 0x25,0xee,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x1f,0x25,0xf2,0x7e, +0xf, 0x25,0xee,0x80,0x17,0xca,0x39,0x7e,0x18,0x38,0xdd,0x7e,0x8, 0x2b,0x70,0x12, +0x20,0xc3,0x1b,0xfd,0x7e,0x1f,0x2b,0x74,0x7e,0xf, 0x2b,0x70,0x2, 0x30,0x2f,0x7a, +0x1f,0x2a,0xfc,0x7a,0xf, 0x2a,0xf8,0x22,0x7a,0xb3,0x2b,0x0, 0x70,0x19,0x7e,0x1f, +0x2b,0x74,0x7e,0xf, 0x2b,0x70,0x12,0x30,0x2f,0x7e,0x18,0x6, 0x76,0x7a,0x1f,0x6, +0xf4,0x7e,0x18,0x4, 0x7e,0x80,0x15,0xb4,0x1, 0x16,0x7e,0x1f,0x25,0xf2,0x7e,0xf, +0x25,0xee,0x12,0x30,0x2f,0x12,0x5d,0xd5,0x7e,0x18,0x4, 0x0, 0x7a,0x1f,0x6, 0xf8, +0x22,0x74,0x1, 0x12,0x0, 0x1e,0xe4,0x12,0x30,0x38,0x12,0x30,0x89,0xe4,0x12,0x0, +0x1e,0x74,0x1, 0x12,0x30,0x38,0x2, 0x30,0x89,0xca,0x3b,0x7e,0xd3,0x2a,0x73,0x7e, +0xc3,0x2a,0x74,0x7e,0x8, 0x1f,0x44,0x12,0xb9,0xa7,0x7e,0x8, 0x1f,0x8a,0x7e,0x34, +0x0, 0x46,0x12,0x20,0xe8,0x7e,0x8, 0x1f,0xd0,0x7e,0x34,0x0, 0xa, 0xe4,0x12,0x20, +0xe8,0x7e,0x8, 0x1f,0xda,0x7e,0x34,0x0, 0xa, 0x12,0x20,0xe8,0x7e,0xf3,0x2a,0xfc, +0x7e,0x18,0x2a,0xdc,0x7a,0x1d,0x24,0x7e,0x18,0x1f,0xd0,0x7a,0x1d,0x28,0x7c,0xbd, +0x7c,0x7c,0x7e,0x8, 0x2a,0xb9,0x12,0x31,0xdf,0x6c,0xee,0x80,0x2b,0xa, 0x3e,0x9, +0xa3,0x2a,0xdc,0xa, 0x3a,0x2e,0x34,0x20,0x7d,0x12,0x88,0x5c,0x7c,0xab,0xbe,0xa0, +0x1c,0x50,0x13,0xa, 0x3e,0x12,0x31,0xa1,0xa, 0x4a,0x19,0xb4,0x1f,0x44,0x7e,0xb3, +0x2a,0xfb,0x19,0xb4,0x1f,0x8a,0xb, 0xe0,0xbc,0xce,0x38,0xd1,0x6c,0xee,0x80,0x24, +0xa, 0x3e,0x9, 0xa3,0x2a,0xb9,0xbe,0xa0,0x23,0x50,0x17,0xa, 0x2e,0xa, 0x3c,0x2d, +0x32,0x12,0x31,0xa1,0xa, 0x4a,0x19,0xb4,0x1f,0x60,0x7e,0xb3,0x2a,0xfb,0x19,0xb4, +0x1f,0xa6,0xb, 0xe0,0xbc,0xde,0x38,0xd8,0x7e,0xb3,0x2a,0xfd,0x7e,0x8, 0x1f,0xe4, +0x60,0x9, 0x7e,0x18,0x1f,0xd0,0x12,0x7e,0x45,0x80,0x3, 0x12,0xbb,0x3b,0x6c,0xee, +0x7e,0x18,0x1f,0xe4,0x7a,0x1f,0x1f,0x34,0x74,0x2, 0xac,0xbe,0x49,0x35,0x1f,0xd0, +0x7a,0x37,0x1f,0x38,0x74,0x2, 0xac,0xbe,0x49,0x35,0x1f,0xda,0x7a,0x37,0x1f,0x3a, +0x7e,0x70,0xe, 0xac,0x7e,0x2e,0x34,0x1f,0x44,0x6d,0x22,0x7a,0x1f,0x1f,0x3c,0x7e, +0x70,0xe, 0xac,0x7e,0x2e,0x34,0x1f,0x8a,0x7a,0x1f,0x1f,0x40,0x7e,0x8, 0x1f,0x34, +0x7c,0xbf,0x7c,0x7e,0x12,0x8, 0xd1,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xb2,0xda,0x3b, +0x22,0x2e,0x37,0x2a,0xfe,0x7e,0x39,0xb0,0x22,0x74,0x1, 0x7a,0xb3,0x38,0x9, 0x12, +0x57,0xd5,0x12,0x13,0xf5,0x12,0xba,0xb3,0xe4,0x12,0xa, 0x66,0x7e,0x24,0x3, 0xd4, +0x12,0x3a,0xf8,0x74,0x1, 0x12,0x30,0x38,0x12,0xc6,0xf2,0x7e,0x34,0xd0,0xc, 0x12, +0x1, 0xe, 0x12,0x30,0x71,0x7e,0x34,0x0, 0x1, 0xe4,0x6c,0x55,0x2, 0x13,0x1, 0x7c, +0x57,0x7c,0xab,0x6c,0x77,0x80,0x4b,0xa, 0x47,0x7e,0x7d,0x24,0x2d,0xf4,0x7e,0x7b, +0x60,0xa, 0x46,0x2e,0x44,0x20,0x7d,0x12,0xc6,0xb6,0x7c,0x6b,0xbe,0x60,0xd, 0x38, +0x12,0x7e,0xd4,0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0xd4,0x14,0x78,0xfb,0x7e,0x7d, +0x28,0x80,0x15,0x9e,0x60,0xe, 0x7e,0xd4,0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0xd4, +0x14,0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40, +0xb, 0x70,0xbc,0x57,0x38,0xb1,0x6c,0x77,0x80,0x58,0xa, 0x27,0x7f,0x70,0x2d,0xf2, +0x7e,0x7b,0x60,0xbe,0x60,0xd, 0x38,0x11,0x12,0x32,0x97,0x60,0x5, 0x3e,0x44,0x14, +0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf6,0x80,0x2f,0xbe,0x60,0x1b,0x38,0x16,0x9e,0x60, +0xe, 0x12,0x32,0x97,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x2e,0xf4, +0x0, 0x6, 0x80,0x14,0x9e,0x60,0x1c,0x12,0x32,0x97,0x60,0x5, 0x3e,0x44,0x14,0x78, +0xfb,0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x8, 0xb, 0x7a,0x20,0x4d,0x24,0x1b,0x7a,0x20, +0xb, 0x70,0xbc,0xa7,0x38,0xa4,0x22,0x7e,0x44,0x0, 0x1, 0x7c,0xb6,0x22,0x7c,0x96, +0x7c,0xa7,0x12,0x30,0x38,0x7c,0xba,0x12,0x13,0xc7,0x74,0xa, 0x12,0x2f,0x39,0x7c, +0xb9,0x12,0x0, 0x1e,0x2, 0x32,0xb7,0xca,0x3b,0x7e,0xe3,0x2a,0x74,0x7e,0xf3,0x2a, +0xfa,0x74,0x1, 0x7a,0xb3,0x2a,0xfa,0x12,0x35,0xfd,0x12,0xc6,0xc8,0x12,0x25,0x89, +0x7e,0x17,0x2a,0xfe,0x6d,0x0, 0x12,0x20,0xe8,0x7e,0xd0,0x7, 0x12,0x2f,0xe7,0x6c, +0xcc,0x80,0x19,0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb, +0x7c,0x67,0x12,0x36,0x98,0x4c,0x76,0x7a,0x29,0x70,0xb, 0xc0,0x12,0x34,0x64,0xa, +0x3c,0xbd,0x32,0x48,0xde,0x12,0x34,0x73,0x30,0x1d,0xfd,0x12,0xc6,0xac,0x7e,0xb3, +0x2a,0x73,0x7c,0x7e,0x12,0x37,0x66,0x6c,0xcc,0x80,0x29,0x74,0x2, 0xac,0xbc,0x49, +0x35,0x6, 0xfc,0xbe,0x34,0x15,0x40,0x50,0x19,0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60, +0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0xb7,0x64,0xff,0x12,0x36,0x98,0x5c,0x7b,0x7a, +0x29,0x70,0xb, 0xc0,0x12,0x34,0x64,0xa, 0x3c,0xbd,0x32,0x48,0xce,0x1b,0xd0,0xbe, +0xd0,0x0, 0x58,0x88,0x12,0x33,0xe6,0x74,0x2, 0x12,0xc6,0xe2,0x12,0x33,0x6e,0x74, +0x2, 0x12,0x0, 0x1e,0x7a,0xf3,0x2a,0xfa,0x12,0x35,0xfd,0xda,0x3b,0x22,0xca,0x79, +0x7c,0xfb,0x7e,0x8, 0x24,0xf2,0x12,0xb9,0xa7,0x7e,0xa3,0x2a,0x73,0x7e,0x73,0x2a, +0x74,0x6c,0xee,0x80,0x1d,0xa, 0x2e,0x9, 0x62,0x2a,0xdc,0xa, 0x26,0x12,0x67,0x43, +0x7c,0x6b,0xbe,0x60,0x1c,0x50,0x9, 0xa, 0x2e,0x12,0x36,0x8e,0x19,0xb2,0x24,0xf2, +0xb, 0xe0,0xbc,0x7e,0x38,0xdf,0x6c,0xee,0x80,0x1a,0xa, 0x2e,0x9, 0x62,0x2a,0xb9, +0xbe,0x60,0x23,0x50,0xd, 0xa, 0x1e,0xa, 0x27,0x2d,0x21,0x12,0x36,0x8e,0x19,0xb2, +0x25,0xe, 0xb, 0xe0,0xbc,0xae,0x38,0xe2,0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e, +0x14,0x24,0xf2,0x6d,0x0, 0x7c,0xbf,0x7c,0x7e,0x12,0x11,0xba,0xb, 0xe0,0xbe,0xe0, +0x5, 0x40,0xe7,0xda,0x79,0x22,0xca,0xd8,0xca,0x79,0x7e,0xf0,0xa, 0x74,0x1, 0x7a, +0xb3,0x2a,0xfa,0x12,0x25,0x89,0x7c,0xe7,0x80,0x5d,0x12,0x2f,0xe7,0x12,0x34,0x73, +0x30,0x1d,0xfd,0x12,0xc6,0xac,0x12,0x37,0x5e,0x6c,0xdd,0x80,0x3d,0x7e,0x50,0x2, +0xac,0x5d,0x49,0x32,0x6, 0xfc,0xbe,0x34,0x14,0x78,0x50,0x14,0xa, 0x1d,0x2e,0x17, +0x2a,0xfe,0x7e,0x19,0xb0,0xbe,0xb0,0x0, 0x28,0x1e,0x14,0x7a,0x19,0xb0,0x80,0x18, +0xbe,0x34,0x19,0x28,0x28,0x10,0xa, 0x3d,0x12,0x31,0xa1,0xbe,0xb0,0xff,0x68,0x8, +0x4, 0x7a,0x39,0xb0,0x80,0x2, 0x1b,0xe0,0xb, 0xd0,0x12,0x34,0x64,0xa, 0x3d,0xbd, +0x32,0x48,0xba,0x4c,0xee,0x68,0x8, 0x7c,0xaf,0x1b,0xf0,0x4c,0xaa,0x78,0x9b,0xda, +0x79,0xda,0xd8,0x22,0x7e,0x73,0x2a,0x74,0xa, 0x37,0x7e,0x53,0x2a,0x73,0xa, 0x25, +0x2d,0x23,0x22,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0xfc,0x12,0x33,0x6e,0x74, +0x2, 0x12,0x0, 0x1e,0x74,0x5, 0x7e,0x70,0x9b,0x12,0x13,0x2c,0x12,0x34,0x96,0x7e, +0xb3,0x2a,0xfc,0x2, 0xe, 0x94,0x6c,0xaa,0x80,0x22,0xa, 0x3a,0x9, 0x73,0x2a,0xdc, +0x2e,0x34,0x20,0x7d,0x12,0x88,0x5c,0x7c,0x7b,0xa, 0x47,0x7e,0x50,0x2, 0xac,0x5a, +0x7e,0xf, 0x39,0xc1,0x2d,0x12,0x79,0x40,0x0, 0x48,0xb, 0xa0,0x7e,0x63,0x2a,0x74, +0xbc,0x6a,0x38,0xd6,0x22,0xca,0x3b,0x7e,0xb3,0x38,0x7, 0xb4,0x1, 0x2, 0x80,0x2, +0xa1,0xfa,0x6c,0xcc,0x6c,0xdd,0x7e,0xb3,0x38,0x32,0xb4,0x1, 0x8, 0x7e,0xe0,0x10, +0x7e,0xf0,0x32,0x80,0x6, 0x7e,0xe0,0xa, 0x7e,0xf0,0x1e,0x12,0x87,0xf3,0x7d,0xf3, +0x12,0x69,0x78,0x50,0xfb,0x74,0x1, 0x7a,0xb3,0x39,0x87,0x12,0x30,0x38,0x12,0x13, +0xc7,0x12,0x0, 0x1e,0x74,0xa, 0x12,0x2f,0x39,0x12,0xc6,0xc8,0x7e,0xe7,0x2b,0xd, +0x7a,0xe5,0x25,0x7e,0xb3,0x2a,0xfa,0xf5,0x24,0x74,0x4, 0x7a,0xb3,0x2a,0xfa,0x7e, +0xe7,0x2b,0xd, 0x5e,0xe4,0x0, 0x3f,0x7a,0xe7,0x2b,0xd, 0x7e,0xb3,0x2a,0xfa,0x12, +0xba,0x42,0x7c,0x7b,0x74,0x6, 0xac,0x7b,0x7e,0x24,0x0, 0x4, 0x12,0x1e,0xb9,0x7d, +0x23,0x7d,0x3f,0x12,0x7e,0x3c,0xad,0x32,0x7a,0x37,0x2b,0x7, 0x12,0x35,0xfd,0x12, +0x8f,0xf5,0xa1,0xdb,0x12,0x2f,0xe7,0x30,0x11,0x2, 0xa1,0xe1,0x7c,0xbe,0x12,0x88, +0x4c,0x12,0x34,0x84,0x80,0xf, 0x80,0x7, 0x12,0x37,0x6e,0xe4,0x12,0x49,0xe7,0x20, +0x93,0xf6,0x12,0x37,0xb7,0x30,0x1d,0xf7,0x30,0x1c,0xf4,0xd2,0x1, 0x12,0x37,0xa6, +0xe4,0x12,0x13,0xde,0xb, 0xc0,0x12,0x83,0xf3,0x12,0x90,0x3d,0x7e,0xa3,0x39,0x86, +0x4c,0xaa,0x78,0x6, 0x74,0x1, 0x7a,0xb3,0x39,0x87,0x4c,0xaa,0x68,0xb, 0x7e,0xb3, +0x38,0x32,0x70,0x5, 0xe4,0x7a,0xb3,0x39,0x86,0x12,0x36,0xa2,0x78,0x18,0x7e,0xb3, +0x39,0x86,0x60,0x12,0xe4,0x7a,0xb3,0x39,0x86,0x7a,0xb3,0x2a,0x2, 0x7a,0xb3,0x2a, +0x3, 0x7e,0xd0,0x1, 0x80,0x1b,0x12,0x36,0xa2,0x68,0x10,0x7e,0xb3,0x39,0x86,0x70, +0xa, 0x7e,0xd0,0x1, 0xe4,0x7a,0xb3,0x38,0x7, 0x80,0x6, 0xbc,0xfc,0x28,0x2, 0xa1, +0x54,0xe4,0x7a,0xb3,0x2b,0x4, 0x7e,0x35,0x25,0x7a,0x37,0x2b,0xd, 0xe5,0x24,0x7a, +0xb3,0x2a,0xfa,0x4c,0xdd,0x68,0x3, 0x12,0x24,0x36,0xda,0x3b,0x22,0x7e,0x8, 0x2a, +0x6d,0x2, 0x5, 0xb4,0x7e,0xd7,0x2b,0xd, 0xbe,0xb0,0x1, 0x28,0x2, 0xe4,0x22,0x12, +0x65,0x47,0x12,0x35,0xfd,0x7a,0xd7,0x2b,0xd, 0x7e,0x73,0x2a,0xfa,0x12,0x46,0xb2, +0xe4,0x7e,0x50,0x1, 0x12,0x13,0x1, 0x12,0x34,0x84,0x74,0x1, 0x22,0xe5,0xd, 0x60, +0x5c,0xe5,0xd, 0x30,0xe0,0x6, 0x53,0xd, 0xfe,0x12,0x35,0xfd,0xe5,0xd, 0x30,0xe1, +0x14,0x53,0xd, 0xfd,0x7e,0xb3,0x38,0xe1,0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x12, +0xc6,0xe2,0x12,0xb9,0x31,0xe5,0xd, 0x30,0xe2,0x33,0x53,0xd, 0xfb,0xe4,0x7a,0xb3, +0x38,0xe2,0x7e,0xb3,0x38,0xe1,0x70,0xf, 0x74,0x1, 0x12,0x0, 0x1e,0x7e,0x1f,0x2b, +0x74,0x7e,0xf, 0x2b,0x70,0x80,0xc, 0xe4,0x12,0x0, 0x1e,0x7e,0x1f,0x25,0xf2,0x7e, +0xf, 0x25,0xee,0x12,0x30,0x2f,0x7e,0xb3,0x2a,0xfc,0x2, 0x33,0x6e,0x22,0x2e,0x27, +0x2a,0xfe,0x7e,0x29,0xb0,0xa, 0x26,0x22,0xa, 0x2c,0x2e,0x27,0x2a,0xfe,0x7e,0x29, +0x70,0x22,0x7e,0x73,0x39,0xf3,0xa, 0x37,0x5e,0x34,0x0, 0x2, 0x22,0x7e,0xb3,0x2b, +0x2, 0x70,0x41,0x12,0x69,0x78,0x50,0xfb,0xe4,0x6c,0x77,0x6c,0x66,0x12,0x32,0x9e, +0x7e,0x8, 0x6, 0xfc,0x7e,0x1f,0x6, 0xf4,0x7e,0xb3,0x2b,0x72,0x12,0x36,0xf5,0x74, +0x1, 0x7e,0x70,0x1, 0x7e,0x60,0x1, 0x12,0x32,0x9e,0x7e,0x8, 0x7, 0x7a,0x7e,0x1f, +0x6, 0xf4,0x7e,0xb3,0x25,0xf0,0x12,0x36,0xf5,0x74,0x2, 0x7a,0xb3,0x2b,0x2, 0xe4, +0x7a,0xb3,0x16,0x90,0x22,0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7f,0x51,0x7f,0x40,0x7f, +0x15,0x12,0x65,0x54,0x12,0xc6,0xf2,0x7e,0xe0,0x1, 0x12,0x34,0x84,0x30,0x1d,0xfd, +0x74,0x2, 0x12,0x0, 0x1e,0x7f,0x4, 0x12,0x37,0x5e,0x6c,0xdd,0x80,0x18,0x74,0x2, +0xac,0xbd,0x7f,0x14,0x2d,0x35,0xb, 0x1a,0x20,0x74,0x2, 0xac,0xbd,0x7f,0x5, 0x2d, +0x15,0x12,0xc6,0xbf,0xb, 0xd0,0x7e,0x73,0x2a,0x74,0xa, 0x7, 0x7e,0x63,0x2a,0x73, +0xa, 0x16,0x2d,0x10,0xa, 0x2d,0xbd,0x21,0x48,0xd4,0x1b,0xe0,0x78,0xbc,0x7f,0x5, +0x7c,0xbf,0x2e,0x73,0x2a,0x73,0x12,0xb9,0xb0,0xda,0x79,0xda,0xd8,0x22,0x7e,0xb3, +0x2a,0x73,0x7e,0x73,0x2a,0x74,0x12,0x10,0xee,0x74,0x2, 0x2, 0x0, 0x1e,0x74,0x81, +0x7a,0xb3,0x3a,0x3, 0x22,0x80,0x1d,0x12,0x37,0x6e,0x12,0x49,0x8a,0x68,0x5, 0xc2, +0x1, 0x12,0x37,0xa6,0x7e,0xb3,0x34,0x3a,0xbe,0xb0,0x2, 0x68,0x18,0x20,0x1c,0x15, +0xe4,0x12,0x49,0xe7,0x20,0x93,0xe0,0x12,0x37,0x6e,0xa9,0xd1,0xcd,0xa9,0xc5,0xea, +0x74,0x2, 0x2, 0x49,0xe7,0x22,0x30,0x1, 0x6, 0x12,0x2f,0xee,0x2, 0x13,0x96,0x12, +0xc7,0x9, 0xc2,0x2, 0x2, 0x2f,0xde,0x30,0x1d,0x5, 0xc2,0x1, 0x12,0x37,0xa6,0xa9, +0xd1,0xcd,0xa9,0xc5,0xea,0x30,0x1c,0x3, 0x20,0x1d,0x14,0x12,0x37,0x6e,0xa9,0xd0, +0xce,0xa9,0xc4,0xc9,0x74,0x2, 0x12,0x49,0xe7,0xa9,0xd0,0xce,0xa9,0xd4,0xc9,0xa9, +0xc1,0xcd,0xd2,0x1, 0x2, 0x37,0xa6,0xca,0xf8,0x7c,0x6b,0xa5,0xbe,0x0, 0xa, 0x7c, +0xb7,0x12,0x68,0x27,0xd2,0x8, 0x2, 0x3a,0x6a,0xa5,0xbe,0x1, 0x3d,0x7a,0x73,0x38, +0x9e,0xa5,0xbf,0xad,0x2, 0x80,0x2f,0xa5,0xbf,0xae,0x4, 0xd2,0x9, 0x41,0x6a,0xa5, +0xbf,0xaa,0x5, 0x12,0x3a,0xef,0x80,0x1e,0xa5,0xbf,0xab,0xa, 0x7e,0x34,0x5, 0x7a, +0x7a,0x37,0x32,0xe3,0x80,0x10,0xa5,0xbf,0xac,0x2, 0x80,0x2, 0x41,0x6a,0x7e,0x34, +0x4, 0xfc,0x7a,0x37,0x32,0xe3,0x6d,0x33,0x1, 0xe6,0xbe,0x60,0x4, 0x40,0x20,0xbe, +0x60,0x8, 0x38,0x1b,0x12,0x3a,0x6d,0xa5,0xbe,0x7, 0x7, 0x6d,0x33,0x7a,0x35,0xa, +0x41,0x6a,0xa5,0xbe,0x8, 0x2, 0x80,0x2, 0x41,0x6a,0x12,0x7, 0xfb,0x41,0x6a,0xa5, +0xbe,0xa, 0x9, 0x43,0xc, 0x20,0x7a,0x73,0x38,0xa7,0x41,0x6a,0xa5,0xbe,0xb, 0x8, +0x12,0x3a,0x6d,0x12,0x3a,0xba,0x41,0x6a,0xbe,0x60,0x1b,0x40,0x7, 0xbe,0x60,0x1c, +0x38,0x2, 0x41,0x2, 0xbe,0x60,0x1e,0x40,0xd, 0xbe,0x60,0x23,0x38,0x8, 0x12,0x3a, +0x6f,0x43,0xc, 0x40,0x41,0x6a,0xbe,0x60,0x15,0x40,0x1a,0xbe,0x60,0x18,0x38,0x15, +0x12,0x3a,0x6f,0xd2,0x8, 0xa5,0xbe,0x15,0x2, 0x80,0x2, 0x41,0x6a,0x74,0x7, 0x7a, +0xb3,0x38,0xa1,0x41,0x6a,0xa5,0xbe,0x19,0x7, 0xe4,0x7a,0xb3,0x38,0xb6,0x41,0x6a, +0xbe,0x60,0x24,0x40,0x7, 0xbe,0x60,0x2c,0x38,0x2, 0x41,0x2, 0xa5,0xbe,0x2d,0x1b, +0x12,0x3a,0x6f,0x20,0x9, 0x2, 0x41,0x6a,0x7e,0x63,0x38,0xc9,0x7c,0x46,0x6c,0x55, +0xa, 0x37,0x2d,0x32,0x3e,0x34,0x7a,0x35,0x8, 0x41,0x6a,0xbe,0x60,0x2f,0x40,0xa, +0xbe,0x60,0x33,0x38,0x5, 0x43,0xc, 0x8, 0x41,0x2, 0xa5,0xbe,0x34,0xf, 0x43,0xc, +0x10,0xbe,0x70,0x64,0x38,0x2, 0x41,0x2, 0x7e,0x70,0x64,0x41,0x2, 0xbe,0x60,0x38, +0x68,0x4, 0xa5,0xbe,0x39,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x38,0xc2,0x7c,0xbf,0x4, +0x7a,0xb3,0x38,0xc2,0xa, 0x2f,0x19,0x72,0x2b,0x21,0xa5,0xbe,0x39,0x2, 0x80,0x2, +0x41,0x6a,0x75,0x1a,0x38,0x41,0x6a,0xbe,0x60,0x3a,0x68,0x4, 0xa5,0xbe,0x3b,0x21, +0x43,0xc, 0x2, 0x7e,0xf3,0x38,0xc4,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc4,0xa, 0x2f, +0x19,0x72,0x2b,0x44,0xa5,0xbe,0x3b,0x2, 0x80,0x2, 0x41,0x6a,0x75,0x1a,0x3a,0x41, +0x6a,0xa5,0xbe,0xfb,0x9, 0x43,0xc, 0x4, 0x7a,0x73,0x2b,0x12,0x41,0x6a,0xa5,0xbe, +0x50,0x6, 0x7a,0x73,0x38,0xed,0x41,0x6a,0xbe,0x60,0x3c,0x68,0x4, 0xa5,0xbe,0x3d, +0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x38,0xc6,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc6,0xa, +0x2f,0x19,0x72,0x2a,0x7a,0xa5,0xbe,0x3d,0x2, 0x80,0x2, 0x41,0x6a,0x75,0x1a,0x3c, +0x41,0x6a,0xbe,0x60,0x3e,0x68,0x4, 0xa5,0xbe,0x3f,0x21,0x43,0xc, 0x1, 0x7e,0xf3, +0x38,0xc8,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc8,0xa, 0x2f,0x19,0x72,0x2a,0x9d,0xa5, +0xbe,0x3f,0x2, 0x80,0x2, 0x41,0x6a,0x75,0x1a,0x3e,0x41,0x6a,0xbe,0x60,0x40,0x40, +0xd, 0xbe,0x60,0x42,0x38,0x8, 0x12,0x3a,0x6f,0x75,0xd, 0x1, 0x80,0xa, 0xa5,0xbe, +0x43,0xb, 0x12,0x3a,0x6f,0x75,0xd, 0x2, 0x12,0x2f,0xf6,0x80,0x7d,0xa5,0xbe,0x44, +0x8, 0x12,0x3a,0x6f,0x12,0x3a,0x76,0x80,0x71,0xbe,0x60,0x45,0x68,0x4, 0xa5,0xbe, +0x46,0x5, 0x12,0x3a,0x6f,0x80,0x63,0xbe,0x60,0x4e,0x68,0x4, 0xa5,0xbe,0x4f,0x20, +0x43,0xd, 0x4, 0x7e,0xf3,0x38,0xe3,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xe3,0xa, 0x2f, +0x2e,0x27,0x32,0xe1,0x7a,0x29,0x70,0xa5,0xbe,0x4f,0x3f,0x75,0x1a,0x4e,0x80,0x3a, +0xa5,0xbe,0x6d,0x5, 0x7a,0x71,0xe, 0x80,0x31,0xbe,0x60,0xf0,0x40,0x25,0xbe,0x60, +0xf3,0x38,0x20,0x7c,0x16,0x2e,0x10,0x20,0x7c,0xb7,0xa5,0xf7,0xa5,0xbe,0xf3,0x1a, +0x7e,0x15,0x12,0x7e,0x5, 0x10,0x3e,0x4, 0x7e,0x1f,0x32,0xe5,0x2d,0x30,0x1b,0x1a, +0x10,0x80,0x7, 0xa5,0xbe,0xf6,0x3, 0x7a,0x71,0xf, 0xda,0xf8,0x22,0xd2,0x8, 0xa, +0x26,0x19,0x72,0x38,0x9d,0x22,0x12,0xc6,0xd9,0xb4,0x1, 0x1c,0xca,0x39,0x7e,0x18, +0x25,0xee,0x7e,0x8, 0x38,0xdd,0x12,0x20,0xc3,0x1b,0xfd,0x12,0x3a,0xbd,0x7e,0x1f, +0x25,0xf2,0x7e,0xf, 0x25,0xee,0x80,0x1f,0xca,0x39,0x7e,0x18,0x2b,0x70,0x7e,0x8, +0x38,0xdd,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x37,0x2b,0x76,0x7a,0x37,0x32,0xe1,0x7e, +0x1f,0x2b,0x74,0x7e,0xf, 0x2b,0x70,0x2, 0x30,0x2f,0xb2,0x82,0x22,0x7e,0x37,0x25, +0xf4,0x7a,0x37,0x32,0xe1,0x22,0x12,0x3a,0xef,0x12,0x3a,0xbd,0x6d,0x33,0x7a,0x35, +0xa, 0x12,0x3b,0x25,0x12,0x3a,0xff,0x74,0x50,0x7a,0xb3,0x38,0xd1,0x7e,0x24,0x3, +0x20,0x12,0x3a,0xf8,0xe4,0x12,0xc6,0x70,0x6d,0x33,0x7a,0x37,0x3a,0x5, 0x22,0x7e, +0x34,0xd, 0xc8,0x7a,0x37,0x32,0xe3,0x22,0x7d,0x32,0x74,0xfa,0x2, 0x12,0xd0,0x7e, +0x73,0x2b,0x62,0x7a,0x73,0x38,0xd0,0x22,0xa2,0xe, 0xe4,0x33,0x7a,0xb3,0x38,0xcb, +0x7e,0x73,0x38,0xcf,0xbe,0x73,0x2b,0xf, 0x68,0xa, 0xe5,0xc, 0x70,0x6, 0x12,0x3b, +0x25,0x12,0x3a,0xff,0x22,0x7e,0x73,0x2b,0xf, 0x7a,0x73,0x38,0xcf,0x7e,0x73,0x2b, +0x1f,0x7a,0x73,0x38,0xbf,0x7e,0x73,0x2b,0x20,0x7a,0x73,0x38,0xbe,0x7e,0x73,0x2b, +0x14,0x7a,0x73,0x38,0xc0,0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0x7e,0xa0,0x4, 0xbe, +0xd0,0x80,0x78,0x18,0x7e,0xe0,0xff,0x6c,0xff,0x80,0xb, 0x12,0x3b,0xae,0x38,0x4, +0x7c,0xeb,0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38,0xf1,0x80,0x1a,0xbe,0xd0,0x81,0x78, +0x15,0x6c,0xee,0x6c,0xff,0x80,0xb, 0x12,0x3b,0xae,0x40,0x4, 0x7c,0xeb,0x7c,0xdf, +0xb, 0xf0,0xbc,0xaf,0x38,0xf1,0xbc,0xad,0x38,0x2, 0x6c,0xdd,0x7c,0xbd,0x12,0x51, +0x89,0x12,0x3b,0x3d,0x12,0x3f,0x95,0x12,0x3b,0xca,0x7e,0x73,0x2b,0xf, 0x7a,0x73, +0x38,0xcf,0x12,0x3a,0xff,0x7a,0xd3,0x38,0xa7,0xda,0x79,0xda,0xd8,0x22,0x7e,0x90, +0x5, 0xac,0x9f,0x9, 0xb4,0x26,0x33,0xbc,0xbe,0x22,0x30,0x0, 0x3, 0x12,0x3b,0x3d, +0xa2,0x1, 0x92,0x2, 0x12,0x3c,0x88,0x2, 0x3b,0xca,0x7e,0x73,0x2b,0x20,0x7a,0x73, +0x38,0xbe,0x22,0x74,0x40,0x7a,0xb3,0x2b,0x20,0x12,0x57,0x8e,0x50,0x9, 0xd2,0x0, +0xd2,0x1, 0x12,0x3b,0xba,0x80,0x1c,0x74,0x1, 0x12,0x3c,0xc, 0x7e,0x43,0x38,0xbc, +0x7e,0x50,0x64,0xac,0x45,0x12,0x80,0x27,0x7a,0xb3,0x2b,0x1f,0x7e,0xf, 0x39,0xda, +0x12,0x3e,0xfb,0x12,0x3b,0xca,0x12,0x3f,0x95,0x2, 0x3b,0x3d,0xca,0x3b,0x7c,0xdb, +0xe4,0x7a,0xb3,0x2b,0x14,0x12,0x3f,0xeb,0x7e,0xc0,0xa, 0x12,0x3f,0xa5,0x30,0xf, +0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x1f,0x39,0xda,0x12,0x83,0x93,0x7d,0x73,0xbe, +0x74,0xff,0xff,0x78,0x9, 0x12,0x3c,0x7c,0x2e,0x34,0x0, 0x3, 0x80,0x18,0xbe,0x74, +0x80,0x0, 0x28,0x7, 0x12,0x3c,0x7c,0xb, 0x35,0x80,0xb, 0xbe,0x74,0x40,0x0, 0x28, +0xc, 0x12,0x3c,0x7c,0xb, 0x34,0x1b,0xa, 0x30,0x1b,0xc0,0x78,0xbe,0xbe,0xd0,0x1, +0x78,0x9, 0x7e,0x1f,0x39,0xda,0x12,0x80,0x46,0x7d,0x73,0x7e,0x1f,0x39,0xc9,0x69, +0x31,0x0, 0x1a,0x7a,0x73,0x2b,0x14,0x7d,0x37,0xda,0x3b,0x22,0x7e,0xf, 0x39,0xc9, +0x2e,0x14,0x0, 0x1a,0xb, 0xa, 0x30,0x22,0xca,0x3b,0x7e,0x34,0xff,0xff,0x7a,0x35, +0x34,0x7e,0xb3,0x38,0xb2,0xf5,0x29,0x7e,0xb3,0x2a,0x6d,0xf5,0x2a,0x7e,0xb3,0x2a, +0x6e,0xf5,0x2b,0x7e,0xb3,0x2a,0x70,0xf5,0x2c,0x7e,0xb3,0x2a,0x6f,0xf5,0x2d,0x7e, +0x34,0x27,0x10,0x7a,0x35,0x2e,0x7e,0x18,0x40,0x0, 0x7a,0x1d,0x30,0x12,0x3f,0x9e, +0x30,0xf, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x8, 0x34,0x0, 0x12,0x3f,0xf2,0x6c, +0xff,0x80,0x34,0x9f,0x77,0x6c,0xee,0x80,0x19,0x7e,0x11,0x2b,0xac,0x1e,0x3e,0x4, +0x7e,0x30,0x2, 0xac,0x3f,0x2d,0x10,0x7e,0x1d,0x30,0x2d,0x31,0xb, 0x1a,0x30,0x12, +0x3e,0xf4,0xe5,0x2d,0xbc,0xbe,0x38,0xe1,0xe5,0x2d,0x12,0x3f,0x6b,0x74,0x2, 0xac, +0xbf,0x59,0x35,0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xc6,0x7e,0x34,0x10, +0x0, 0x7e,0xa1,0x2b,0x74,0x2, 0xa4,0x59,0x35,0x33,0xfe,0x6c,0xff,0x80,0x72,0x9f, +0x77,0x6c,0xee,0x80,0x12,0x12,0xc6,0x47,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60, +0x80,0x14,0x78,0xf4,0x12,0x3e,0xf4,0xe5,0x29,0xbc,0xbe,0x38,0xe8,0xe5,0x29,0x12, +0x3f,0x6b,0x74,0x4, 0xac,0xbf,0x59,0x35,0x3, 0x70,0xe5,0x29,0xbe,0xb1,0x2c,0x50, +0x32,0x9f,0x77,0x7e,0xe1,0x29,0x80,0x12,0x12,0xc6,0x47,0x1e,0x34,0x1e,0x24,0x50, +0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x12,0x3e,0xf4,0xe5,0x2c,0xbc,0xbe,0x38,0xe8, +0xe5,0x29,0xa, 0x3b,0x6d,0x22,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x9f,0x1, 0x12,0x3f, +0x6f,0x80,0x4, 0x7e,0x34,0x10,0x0, 0x74,0x4, 0xac,0xbf,0x59,0x35,0x3, 0x72,0xb, +0xf0,0xe5,0x2d,0xbc,0xbf,0x38,0x88,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x7e,0x78,0x0, +0xcc,0x12,0x3f,0x8d,0x80,0x2e,0x74,0x2, 0xac,0xbf,0x49,0x25,0x34,0x0, 0xa, 0x5f, +0xad,0x53,0x7e,0x14,0x10,0x0, 0x9d,0x15,0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e,0x4, +0x50,0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x2, 0xac,0xbf,0x59,0x25, +0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xcc,0xe5,0x2a,0xa, 0x1b,0x6d,0x0, +0x12,0x3f,0x8d,0x80,0x5c,0x74,0x4, 0xac,0xbf,0x49,0x25,0x3, 0x70,0xa, 0x1f,0xad, +0x13,0x7e,0xf4,0x10,0x0, 0x9d,0xf1,0xad,0xf2,0x74,0xc, 0x1e,0xf4,0x1e,0xe4,0x50, +0x4, 0x4e,0xf4,0x80,0x0, 0x14,0x78,0xf3,0x7d,0x2f,0x74,0x4, 0xac,0xbf,0x59,0x25, +0x3, 0x70,0xe5,0x29,0xbe,0xb1,0x2c,0x50,0x26,0x74,0x4, 0xac,0xbf,0x49,0x25,0x3, +0x72,0x2e,0x14,0x10,0x0, 0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e,0x4, 0x50,0x3, 0x4e, +0x20,0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x4, 0xac,0xbf,0x59,0x25,0x3, 0x72,0xb, +0xf0,0xe5,0x2a,0xbc,0xbf,0x38,0x9e,0x7e,0x73,0x38,0xb4,0xa, 0x37,0x6d,0x22,0x74, +0xc, 0x2f,0x11,0x14,0x78,0xfb,0x7e,0xf4,0x0, 0x64,0x7d,0x1f,0x12,0x1f,0x5, 0x7d, +0xe3,0x7a,0xe5,0x34,0x7e,0x73,0x38,0xb5,0xa, 0x37,0x6d,0x22,0x74,0xc, 0x2f,0x11, +0x14,0x78,0xfb,0x7d,0x1f,0x12,0x1f,0x5, 0x7d,0x63,0x6c,0xff,0x80,0x20,0x74,0x2, +0xac,0xbf,0x49,0x45,0x34,0x0, 0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35, +0x34,0x0, 0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65,0x34,0x0, 0xb, 0xf0,0xe5,0x2c, +0xbc,0xbf,0x38,0xda,0x6c,0xff,0x80,0x3a,0x74,0x4, 0xac,0xbf,0x49,0x45,0x3, 0x70, +0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35,0x3, 0x70,0x80,0x8, 0xbd,0x46, +0x50,0x4, 0x59,0x65,0x3, 0x70,0x49,0x45,0x3, 0x72,0xbe,0x45,0x34,0x28,0x9, 0x7e, +0x35,0x34,0x59,0x35,0x3, 0x72,0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65,0x3, 0x72, +0xb, 0xf0,0xe5,0x2a,0xbc,0xbf,0x38,0xc0,0x30,0x2, 0x6, 0x7e,0xd, 0x30,0x12,0x3e, +0xfb,0xda,0x3b,0x22,0x6d,0x22,0x2f,0x71,0xb, 0xe0,0x22,0x12,0x3f,0x5, 0xb, 0x34, +0x7a,0x73,0x2b,0x20,0x22,0xca,0x79,0x7f,0x10,0x9f,0x0, 0x6c,0xaa,0xa, 0x4a,0x2e, +0x44,0x60,0xac,0x12,0xc6,0xb6,0x7c,0x9b,0x7e,0xf3,0x2a,0x6e,0xac,0xf9,0x7e,0xb3, +0x2a,0x70,0xa, 0xfb,0x2d,0xf7,0x7d,0xef,0x3e,0xe4,0x7f,0x61,0x2d,0xde,0xb, 0x6a, +0xd0,0x6d,0xcc,0x2f,0x6, 0xb, 0xa0,0xbe,0xa0,0x3, 0x78,0xd1,0xbe,0x8, 0x0, 0x0, +0x78,0x2, 0xb, 0xc, 0x7e,0x54,0x0, 0x3, 0x7f,0x10,0x7d,0x15,0x12,0x1f,0x5, 0x7f, +0x1, 0xb, 0xc, 0x7e,0x34,0xc4,0x0, 0x7e,0x24,0x0, 0x9, 0x12,0x1f,0x7, 0xbe,0x34, +0x0, 0xfa,0x28,0x4, 0x7e,0x34,0x0, 0xfa,0xda,0x79,0x22,0xa, 0x1b,0x6d,0x0, 0x7f, +0x17,0x12,0x1f,0x7, 0x7f,0x71,0x7e,0x25,0x2e,0x74,0xc, 0x7d,0x13,0x7d,0x32,0x6d, +0x22,0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0xb, 0x14,0x2, 0x1f,0x5, 0x7f,0x17,0x12, +0x1f,0x7, 0x6c,0xff,0x22,0x7e,0x73,0x2b,0x1f,0x7a,0x73,0x38,0xbf,0x22,0x7e,0x8, +0x2a,0x6d,0x12,0xd, 0x72,0xe4,0x12,0x0, 0xe, 0x74,0x1, 0x7e,0x70,0x99,0x12,0x13, +0x2c,0x2, 0x0, 0x4e,0xb4,0x3, 0x5, 0x12,0x3f,0xc4,0x80,0x2, 0xe4,0x22,0x12,0x3f, +0xa9,0x74,0x1, 0x22,0x12,0xc6,0xa3,0xe4,0x12,0x0, 0xe, 0x7e,0x8, 0x2a,0x6d,0x2, +0xd, 0x72,0x12,0x69,0x6f,0x38,0x2, 0xe4,0x22,0x12,0x69,0x67,0x49,0x55,0x34,0x3b, +0xbe,0xb0,0x2, 0x38,0x3, 0x2, 0x36,0x4, 0x2, 0x3f,0xb4,0x7e,0x8, 0x2a,0x6d,0x2, +0xd, 0x72,0x7e,0x34,0x0, 0x38,0xe4,0x2, 0x20,0xe8,0xca,0xd8,0xca,0x79,0x7e,0x73, +0x2a,0x6e,0x7e,0xf3,0x2a,0x6d,0xac,0xf7,0x7d,0x37,0x3e,0x34,0x7e,0x8, 0x1f,0x34, +0xe4,0x12,0x20,0xe8,0x7e,0xb3,0x38,0xb8,0xb4,0x1, 0x64,0x7e,0x73,0x38,0xb9,0xbe, +0x70,0x0, 0x28,0x5b,0x6c,0xdd,0x80,0x3c,0x12,0x2f,0xe7,0x12,0x24,0x8a,0x6d,0x33, +0x80,0x28,0x7e,0x35,0x24,0x3e,0x34,0x49,0x33,0xd, 0xc8,0x12,0x21,0xa, 0x7a,0x35, +0x26,0x7e,0x35,0x24,0x7d,0x13,0x3e,0x14,0x49,0x21,0x1f,0x34,0xbe,0x25,0x26,0x58, +0x7, 0x7e,0x25,0x26,0x59,0x21,0x1f,0x34,0xb, 0x34,0x7a,0x35,0x24,0xbe,0x75,0x24, +0x38,0xd0,0xb, 0xd0,0x7e,0x73,0x38,0xb9,0xbc,0x7d,0x38,0xbc,0x7d,0x37,0x3e,0x34, +0xca,0x39,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0xd, 0xc8,0x12,0x20,0xc3,0x1b,0xfd,0xda, +0x79,0xda,0xd8,0x22,0x7e,0xb3,0x38,0x6, 0xb4,0x1, 0x4, 0xe4,0x2, 0x40,0x90,0x22, +0x70,0x3, 0xd2,0x86,0x22,0xc2,0x86,0x22,0x12,0x24,0x50,0x12,0x67,0xf4,0x7e,0xb3, +0x38,0x9, 0xb4,0x1, 0x67,0x12,0xb8,0x28,0x12,0x4f,0xc5,0x12,0x88,0x7, 0x12,0x46, +0x4b,0x12,0x24,0x8a,0x50,0xe5,0x12,0x67,0x6c,0x12,0x85,0xfd,0x7e,0xb3,0x38,0x6, +0xb4,0x1, 0x4, 0xe4,0x12,0x40,0x90,0x12,0x44,0xaf,0x12,0x44,0x6c,0x40,0xcc,0x12, +0x6a,0xc3,0x12,0x44,0x6c,0x40,0xc4,0x12,0x77,0x1d,0x12,0x26,0x1b,0x12,0x47,0xc8, +0x12,0x44,0xdd,0x12,0x6f,0xf1,0x12,0x92,0x54,0x12,0x59,0xe3,0x12,0x7d,0x5a,0x12, +0x78,0x8e,0x12,0x7f,0xf6,0x12,0x79,0xe9,0x12,0x97,0xf6,0x12,0x4d,0x91,0x12,0x41, +0x12,0x12,0x4f,0xf7,0x12,0x49,0x92,0x12,0x48,0x28,0x80,0x8f,0x12,0x6a,0x6d,0x2, +0x40,0x84,0xca,0x3b,0x75,0x24,0x0, 0x6c,0xff,0x12,0x43,0x2a,0x75,0x28,0x3, 0x6c, +0xee,0x7e,0x48,0x29,0xbc,0x7e,0xb3,0x2a,0xb, 0x70,0xe, 0x7e,0xb3,0x2a,0x7, 0x70, +0x8, 0x7e,0xb3,0x2a,0x8, 0x70,0x2, 0x41,0xff,0x30,0x12,0x6, 0x7e,0x68,0x35,0xd1, +0x80,0x4, 0x7e,0x68,0x35,0x93,0x7f,0x6, 0x12,0x68,0xfc,0x7e,0x73,0x2a,0x4, 0x7a, +0x6b,0x70,0x6c,0xdd,0x41,0xb0,0x74,0x9, 0xac,0xbd,0x9, 0xc5,0x29,0xc, 0x7c,0xbc, +0x54,0xf, 0x12,0x44,0x62,0xf5,0x28,0x7c,0xbc,0x54,0xf0,0xbe,0xb0,0x0, 0x28,0x2, +0x41,0xae,0xe5,0x28,0xbe,0xb0,0x3, 0x78,0x2, 0x41,0xae,0x7e,0x8, 0x0, 0x28,0x7c, +0xbc,0x12,0x9f,0xac,0x50,0x2, 0x41,0xae,0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x29,0xd, +0xf5,0x25,0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x29,0xe, 0xc4,0x54,0xf0,0xf5,0x26,0x7e, +0x73,0x2a,0x4d,0xbc,0x7c,0x28,0x54,0x7e,0xb3,0x2a,0x9, 0x70,0x2a,0x75,0x29,0xf, +0x7e,0x8, 0x0, 0x25,0xa, 0x3c,0x2e,0x34,0x35,0x7f,0x6d,0x22,0x74,0x1, 0x12,0x46, +0x9, 0x75,0x29,0x20,0x7e,0x8, 0x0, 0x26,0xa, 0x3c,0x2e,0x34,0x35,0x89,0x6d,0x22, +0x74,0x10,0x12,0x46,0x9, 0x80,0xe, 0xa, 0x3c,0x9, 0xb3,0x35,0x7f,0xf5,0x25,0x9, +0xb3,0x35,0x89,0xf5,0x26,0xa, 0x3c,0x12,0x44,0x64,0xb4,0x1, 0xe, 0xe4,0xa, 0x3c, +0x19,0xb3,0x35,0x7f,0x19,0xb3,0x35,0x89,0x12,0x43,0x2a,0x7e,0xb3,0x2a,0x64,0xb4, +0xff,0x13,0x75,0x25,0x0, 0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x29,0xc, 0xbe,0xb0,0xff, +0x68,0x3, 0x75,0x25,0x1, 0x7e,0x90,0x9, 0xac,0x9d,0x49,0xb4,0x29,0x8, 0x49,0xa4, +0x29,0xa, 0xe5,0x28,0xb4,0x1, 0x27,0x75,0x27,0x0, 0x7e,0x71,0x27,0x74,0x9, 0xac, +0x7b,0x9, 0xb3,0x36,0x13,0x54,0xf, 0xbc,0xbc,0x78,0xa, 0x49,0xb3,0x36,0xf, 0x49, +0xa3,0x36,0x11,0x80,0x9, 0x5, 0x27,0xe5,0x27,0xbe,0xb0,0xa, 0x40,0xdc,0x5e,0xb4, +0xf, 0xff,0x5e,0xa4,0xf, 0xff,0x9, 0x74,0x29,0xc, 0xa, 0x57,0xc4,0x54,0xf0,0x7c, +0xab,0xe4,0x2d,0xa5,0xbe,0x70,0xff,0x68,0x16,0xe5,0x28,0xbe,0xb0,0x1, 0x68,0x2, +0x5, 0x24,0xb, 0xf0,0xe5,0x28,0xa, 0x5b,0x12,0x7f,0x90,0x2d,0xb5,0x80,0x4, 0x2e, +0xb4,0xc0,0x0, 0x7e,0x70,0x6, 0xac,0x7e,0x7f,0x6, 0x2d,0x13,0x79,0xb0,0x0, 0x2, +0x7f,0x6, 0x2d,0x13,0x79,0xa0,0x0, 0x4, 0xe5,0x25,0x7f,0x6, 0x2d,0x13,0x39,0xb0, +0x0, 0x6, 0xe5,0x26,0x2d,0x3d,0x7d,0x2c,0x39,0xb1,0x0, 0x7, 0xb, 0xe0,0xb, 0xd0, +0x7e,0x73,0x2a,0x4d,0xbc,0x7d,0x28,0x2, 0x21,0x56,0xe5,0x24,0x39,0xb6,0x0, 0x1, +0x7e,0xb3,0x38,0x32,0xb4,0x1, 0x9, 0x7e,0xb3,0x2a,0x8, 0xb4,0x1, 0x17,0x80,0xd, +0xbe,0xf0,0x0, 0x38,0x6, 0x7e,0xb3,0x2a,0x8, 0x60,0xa, 0xb2,0x12,0x12,0x68,0x52, +0x74,0x1, 0x12,0x40,0x90,0x7e,0xb3,0x2a,0x7, 0x60,0x5, 0x7f,0x4, 0x12,0x59,0xb1, +0xe4,0x7a,0xb3,0x2a,0xb, 0x7a,0xb3,0x2a,0x7, 0x7a,0xb3,0x2a,0x8, 0x80,0x4, 0xe4, +0x12,0x40,0x90,0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18,0x29,0x8, 0x7e,0x8, 0x36, +0xf, 0x12,0x20,0xc3,0x1b,0xfd,0x4c,0xff,0x78,0xd, 0x7e,0x8, 0x36,0xf, 0x7e,0x34, +0x0, 0x5a,0x74,0xff,0x12,0x20,0xe8,0xda,0x3b,0x22,0x75,0x25,0x0, 0x75,0x26,0x0, +0x22,0xca,0x3b,0x6c,0xff,0x7e,0xb3,0x2a,0x6f,0xf5,0x29,0x7e,0xe3,0x2a,0x70,0x6c, +0xdd,0x7e,0xb3,0x16,0x91,0xbe,0xb0,0x1, 0x68,0xf, 0x60,0x2, 0x81,0x52,0x7e,0xb3, +0x28,0x84,0xb4,0x1, 0x2, 0x80,0x2, 0x81,0x52,0x6c,0xcc,0x81,0x44,0x12,0x97,0xd4, +0xf5,0x27,0x9, 0xb3,0x26,0xfb,0xf5,0x28,0x75,0x25,0x2, 0x75,0x26,0x2, 0x12,0xa1, +0xbe,0x50,0x6, 0x75,0x25,0x3, 0x75,0x26,0x3, 0x7c,0xbc,0x12,0x70,0x47,0xd2,0x0, +0x12,0x67,0xa3,0xe5,0x27,0x60,0xe, 0xe5,0x29,0xa, 0x2b,0x1b,0x24,0xe5,0x27,0xa, +0x3b,0xbd,0x32,0x48,0x3, 0x75,0x25,0x1, 0xe5,0x28,0x60,0xc, 0xa, 0x2e,0x1b,0x24, +0xe5,0x28,0xa, 0x3b,0xbd,0x32,0x48,0x3, 0x75,0x26,0x1, 0x75,0x24,0x0, 0x80,0x6a, +0xe5,0x24,0xbc,0xbc,0x68,0x62,0x12,0xb5,0x9b,0x7a,0xa1,0x2a,0x9, 0xb3,0x26,0xfb, +0xf5,0x2b,0xa, 0x2a,0xe5,0x27,0x12,0x44,0x5b,0xbe,0x34,0x0, 0x3, 0x18,0x11,0x12, +0x44,0x55,0xbe,0x34,0x0, 0x3, 0x18,0x8, 0x75,0x25,0x1, 0x75,0x26,0x1, 0x80,0x3f, +0xe5,0x2a,0xa, 0x2b,0xe5,0x27,0x12,0x44,0x5b,0xbe,0x34,0x0, 0x8, 0x18,0xf, 0xe5, +0x2a,0xa, 0x2b,0xe5,0x27,0x12,0x44,0x5b,0xbe,0x34,0x0, 0x3, 0x18,0x12,0x12,0x44, +0x55,0xbe,0x34,0x0, 0x8, 0x18,0x11,0x12,0x44,0x55,0xbe,0x34,0x0, 0x3, 0x8, 0x8, +0x75,0x25,0x2, 0x75,0x26,0x2, 0x80,0x7, 0x5, 0x24,0x12,0x8f,0xd6,0x38,0x91,0xe5, +0x27,0x7e,0x71,0x28,0x12,0x88,0xe8,0x50,0x6, 0x12,0x44,0x84,0x12,0x43,0x2a,0xe5, +0x25,0x7e,0x71,0x26,0x7c,0x6c,0x7c,0x5f,0x7c,0x4d,0x12,0x80,0xa3,0x12,0x44,0x84, +0xb, 0xf0,0xb, 0xc0,0x7e,0x73,0x28,0x84,0xbc,0x7c,0x28,0x2, 0x61,0x5d,0x7a,0xf3, +0x28,0x84,0xda,0x3b,0x22,0xe5,0x2b,0xa, 0x2b,0xe5,0x28,0xa, 0x3b,0x9d,0x32,0x2, +0x21,0xa, 0xa, 0x3b,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0x22,0xc2,0x0, 0x7e,0xb3, +0x16,0x91,0x60,0x6, 0x7e,0xb3,0x16,0x90,0x70,0x7, 0x12,0x97,0xcc,0x28,0x2, 0xd2, +0x0, 0xa2,0x0, 0x22,0x6c,0x33,0x6c,0x22,0x80,0x1c,0x7c,0xb2,0x12,0x67,0x50,0x50, +0x13,0x7c,0xb2,0x12,0x67,0x98,0x7d,0x3, 0x12,0x67,0xda,0x49,0x55,0x39,0xe9,0x7d, +0x40,0x12,0xc6,0x79,0xb, 0x20,0x7e,0x73,0x2a,0x75,0xbc,0x72,0x38,0xdc,0x22,0x12, +0x45,0xb8,0x12,0x44,0xc1,0x12,0x44,0xcc,0x30,0x16,0x5, 0x12,0x44,0x84,0xc2,0x16, +0x22,0x2, 0x44,0xc4,0x7e,0x73,0x2a,0x6b,0x2e,0x70,0xff,0x22,0x12,0x44,0xc4,0x40, +0xb, 0x12,0xab,0x58,0xe4,0x7a,0xb3,0x3, 0xfd,0x2, 0x45,0xbe,0x22,0xca,0x3b,0x7e, +0x73,0x38,0x26,0xa, 0x37,0x6d,0x22,0x7a,0x1d,0x26,0x7e,0x33,0x38,0x28,0xa, 0xf3, +0x6d,0xee,0x7a,0x7d,0x2a,0x7e,0x33,0x38,0x27,0xa, 0x93,0x6d,0x88,0x7e,0x33,0x38, +0x29,0xa, 0x73,0x6d,0x66,0x7e,0x44,0x4, 0x38,0x7d,0x14,0x12,0x1e,0xfc,0x12,0x45, +0xb1,0x7a,0x1d,0x26,0x7e,0x54,0x7, 0x80,0x7f,0x17,0x7d,0x15,0x12,0x1e,0xfc,0x12, +0x45,0xb1,0x7a,0x1d,0x2a,0x7f,0x14,0x7d,0x14,0x12,0x1e,0xfc,0x12,0x45,0xb1,0x7f, +0x41,0x7f,0x13,0x7d,0x15,0x12,0x1e,0xfc,0x7c,0xf6,0x7c,0xe5,0xa, 0x64,0x12,0x44, +0xc4,0x50,0x60,0x7e,0xb3,0x16,0x91,0xb4,0x1, 0x59,0x75,0x2e,0x0, 0x80,0x4b,0x7e, +0xa1,0x2e,0x74,0x9, 0xa4,0x49,0x35,0x27,0x76,0x12,0x7a,0xa2,0x7a,0x35,0x24,0x7e, +0xa1,0x2e,0x74,0x9, 0xa4,0x49,0x35,0x27,0x78,0x12,0x78,0xeb,0x7d,0xa3,0x7e,0x35, +0x24,0x6d,0x22,0x7e,0xd, 0x26,0xbf,0x10,0x40,0x17,0x7d,0x5a,0x6d,0x44,0x7e,0xd, +0x2a,0xbf,0x20,0x40,0xc, 0xbf,0x14,0x38,0x8, 0x7d,0x3a,0x6d,0x22,0xbf,0x13,0x28, +0x7, 0xe5,0x2e,0x6c,0x77,0x12,0x73,0x2e,0x5, 0x2e,0x7e,0x73,0x28,0x84,0xbe,0x71, +0x2e,0x38,0xac,0xda,0x3b,0x22,0x9d,0x32,0x12,0x21,0xa, 0x7d,0x13,0x7d,0x30,0xad, +0x31,0x7c,0x76,0x7c,0x65,0xa, 0x24,0x22,0x12,0x47,0xcb,0x2, 0x45,0xbe,0xe4,0x7a, +0xb3,0x28,0x93,0x12,0xa3,0x3f,0x12,0xbc,0x1a,0x7e,0xb3,0x16,0x91,0xb4,0x1, 0x8, +0x7e,0x73,0x28,0x84,0x7a,0x73,0x28,0x92,0x7e,0x18,0x4, 0xfc,0x7a,0x1f,0x6, 0xf8, +0x12,0x5d,0xd5,0x12,0x89,0x37,0x12,0x86,0x47,0x7e,0xb3,0x16,0x90,0xb4,0x1, 0x18, +0x7e,0x73,0x26,0x83,0x7a,0x73,0x26,0xf3,0x7e,0x73,0x26,0x85,0x7a,0x73,0x26,0xf5, +0x7e,0x73,0x26,0x84,0x7a,0x73,0x26,0xf4,0x22,0x7c,0x9b,0x7f,0x71,0x7e,0x7b,0x80, +0x4c,0x88,0x78,0x7, 0x7e,0xb, 0x90,0x7a,0x7b,0x90,0x22,0xa, 0x28,0x7e,0xb, 0x80, +0xa, 0x38,0x9d,0x32,0x12,0x21,0xa, 0xe5,0x29,0xa, 0x2b,0xbd,0x32,0x8, 0x15,0x7e, +0x7b,0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x7c,0xba,0x28,0x4, 0x2c,0xb9,0x80,0x2, 0x9c, +0xb9,0x7a,0x7b,0xb0,0x7e,0x7b,0x70,0x7a,0xb, 0x70,0x22,0x7e,0x24,0x37,0xe2,0x30, +0x11,0x54,0xc2,0x11,0x9, 0x72,0x0, 0x2, 0x12,0x46,0xa7,0x7a,0x37,0x2a,0x4f,0x9, +0x72,0x0, 0x3, 0x12,0x46,0xa7,0x7a,0x37,0x2a,0x51,0x9, 0x72,0x0, 0x4, 0x12,0x46, +0xa7,0x7a,0x37,0x2a,0x53,0x7e,0x29,0x70,0x12,0x46,0xb2,0x7a,0x37,0x2a,0x5a,0x9, +0x72,0x0, 0x1, 0x12,0x46,0xb2,0x7a,0x37,0x2a,0x5c,0x9, 0x72,0x0, 0x5, 0x12,0x46, +0xa7,0x7a,0x37,0x2a,0x62,0x9, 0x72,0x0, 0x41,0xbe,0x73,0x2a,0x6b,0x68,0x7, 0x7a, +0x73,0x2a,0x6b,0x2, 0x47,0xda,0x22,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x3e, +0x34,0x22,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x22,0x7e,0x30,0x64,0x7e,0x20,0x64,0x6c, +0x11,0x80,0x4a,0xa, 0x31,0xb, 0x34,0x7c,0x7, 0x80,0x38,0x7e,0x70,0x2, 0xac,0x70, +0x9, 0xb3,0x26,0xfa,0x12,0x47,0x2e,0x9, 0xb3,0x26,0xfa,0x12,0x44,0x5b,0x7c,0x97, +0x7e,0x70,0x2, 0xac,0x70,0x9, 0xb3,0x26,0xfb,0x12,0x47,0x2e,0x9, 0xb3,0x26,0xfb, +0x12,0x44,0x5b,0x7c,0x87,0xbc,0x39,0x28,0x2, 0x7c,0x39,0xbc,0x28,0x28,0x2, 0x7c, +0x28,0xb, 0x0, 0x7e,0xb3,0x28,0x84,0xbc,0xb0,0x38,0xc0,0xb, 0x10,0x7e,0xb3,0x28, +0x84,0xbc,0xb1,0x38,0xae,0xa5,0xbb,0x64,0x2, 0x6c,0x33,0xa5,0xba,0x64,0x2, 0x6c, +0x22,0xbc,0x23,0x28,0x4, 0x7c,0xa2,0x80,0x2, 0x7c,0xa3,0x7c,0xba,0x22,0xa, 0x2b, +0x7e,0x70,0x2, 0xac,0x71,0x22,0xca,0x79,0x7c,0xe5,0x7c,0xfb,0x7e,0xe4,0xff,0xfc, +0x7c,0xb4,0x12,0xa0,0x0, 0x7d,0x3, 0x74,0x9, 0xac,0xbf,0x12,0x7f,0xa8,0x12,0x45, +0xa6,0x7d,0x13,0x5e,0x30,0xfc,0x7e,0x70,0x9, 0xac,0x7f,0x49,0xf3,0x29,0x62,0x74, +0x9, 0xac,0xbe,0x49,0x25,0x28,0xae,0xbd,0x2f,0x28,0xf, 0x7d,0x53,0x2e,0x54,0x29, +0x62,0x7d,0x2f,0x2d,0x21,0x1b,0x58,0x20,0x80,0x9, 0x2e,0x34,0x29,0x62,0x9d,0xf1, +0x1b,0x38,0xf0,0x74,0x9, 0xac,0xbf,0x49,0x25,0x29,0x64,0x74,0x9, 0xac,0xbe,0x49, +0x35,0x28,0xb0,0x12,0x45,0xa6,0x7d,0x13,0x5d,0x1e,0x7e,0x50,0x9, 0xac,0x5f,0x49, +0x32,0x29,0x64,0x74,0x9, 0xac,0xbe,0x49,0x5, 0x28,0xb0,0xbd,0x3, 0x28,0xd, 0x7d, +0x2, 0x2e,0x4, 0x29,0x64,0x2d,0x13,0x1b,0x8, 0x10,0x80,0x9, 0x2e,0x24,0x29,0x64, +0x9d,0x31,0x1b,0x28,0x30,0xda,0x79,0x22,0x2, 0x43,0x31,0x12,0x47,0xe2,0x2, 0x47, +0xd1,0x12,0x44,0xc4,0x50,0x3, 0x2, 0x48,0x9, 0x22,0x12,0x44,0xc4,0xd2,0x1a,0x2, +0x26,0x11,0x12,0x5d,0xde,0x7e,0x34,0x0, 0x78,0x7a,0x37,0x2a,0x5c,0x7e,0x34,0xff, +0x6a,0x7a,0x37,0x2a,0x5e,0x2, 0x47,0xf8,0x7e,0x34,0x0, 0xfa,0x7a,0x37,0x2a,0x4f, +0x7a,0x37,0x2a,0x51,0x7a,0x37,0x2a,0x53,0x22,0x7e,0x34,0x0, 0x32,0x7a,0x37,0x2a, +0x5a,0x7e,0x34,0x0, 0x28,0x7a,0x37,0x2a,0x5c,0x7e,0x34,0x0, 0x78,0x7a,0x37,0x2a, +0x4f,0x7e,0x34,0x0, 0x64,0x2, 0x48,0x0, 0x7e,0x8, 0x38,0xf4,0x12,0x48,0x5c,0x7e, +0x8, 0x38,0xfc,0x12,0x48,0x5c,0x12,0x48,0x71,0x12,0x48,0x78,0x2, 0x48,0x3f,0x7e, +0x37,0x38,0xf4,0xbe,0x34,0x0, 0x0, 0x28,0x12,0x7e,0x73,0x3a,0x8, 0xbe,0x70,0x5, +0x50,0x9, 0x7e,0xb3,0x38,0x32,0x70,0x3, 0x12,0x48,0x7f,0x22,0xb, 0xa, 0x30,0xe5, +0x5e,0xa, 0x2b,0xbd,0x32,0x28,0x4, 0x9d,0x32,0x80,0x2, 0x6d,0x33,0x1b,0xa, 0x30, +0x22,0x7e,0x8, 0x2b,0xb7,0x2, 0x48,0x5c,0x7e,0x8, 0x39,0xe7,0x2, 0x48,0x5c,0x6d, +0x33,0x7a,0x37,0x39,0x84,0x74,0x1, 0x7a,0xb3,0x38,0x7, 0x22,0x7e,0xb3,0x38,0x7, +0x14,0x68,0x51,0x14,0x78,0x2, 0x21,0x20,0x14,0x68,0x61,0x24,0x3, 0x78,0x79,0x12, +0x49,0x26,0x38,0x8, 0x30,0x14,0xf, 0x12,0x4f,0xd4,0x68,0xa, 0x12,0x4a,0x2e,0xe4, +0x7a,0xb3,0x39,0x86,0x80,0x6a,0x7e,0xb3,0x37,0xe8,0x30,0xe0,0x63,0x7e,0x73,0x37, +0xe9,0xa, 0x27,0x7e,0x34,0x4, 0x0, 0xad,0x32,0x7e,0xb3,0x38,0x32,0xb4,0x1, 0x4, +0x7e,0x34,0x5, 0xf4,0xbe,0x37,0x39,0x84,0x50,0x46,0x12,0x48,0x7f,0xe4,0x7a,0xb3, +0x39,0x88,0x80,0x3c,0x12,0x49,0x26,0x28,0x32,0xe4,0x7a,0xb3,0x38,0x7, 0x7e,0xb3, +0x39,0x86,0xb4,0x1, 0x3, 0x12,0x48,0x85,0xd2,0x1c,0x80,0x1f,0x74,0xff,0x7a,0xb3, +0x37,0xe1,0x12,0x4f,0xc5,0x12,0x49,0xb2,0x12,0x23,0x3b,0xe4,0x7a,0xb3,0x38,0x7, +0x7a,0xb3,0x3a,0x8, 0xd2,0x1c,0x80,0x8, 0x12,0x48,0x85,0xe4,0x7a,0xb3,0x3a,0x8, +0x12,0x49,0x2e,0x2, 0x34,0xc5,0x7e,0x73,0x2a,0x2, 0xbe,0x70,0x0, 0x22,0x74,0x1, +0x12,0x49,0x4d,0x20,0x1c,0x6, 0x12,0x49,0x70,0x12,0x0, 0x6e,0x7e,0xb3,0x34,0x3a, +0xb4,0x1, 0x6, 0x12,0x49,0x56,0x12,0x0, 0x6e,0xe4,0x2, 0x49,0x4d,0xbe,0xb0,0x8, +0x50,0x3, 0x12,0x4f,0xdc,0x22,0x74,0xc8,0x7a,0xb3,0x3a,0x7, 0xc2,0x1c,0x80,0xa, +0x12,0x37,0x75,0x30,0x1c,0x4, 0x75,0xe9,0xff,0x22,0x12,0x49,0x8a,0x68,0xf1,0x22, +0xd2,0x0, 0x80,0x12,0x30,0x0, 0xc, 0x12,0x49,0x8a,0x68,0x7, 0xc2,0x0, 0xc2,0x1, +0x12,0x37,0xa6,0x12,0x37,0x75,0x30,0x1c,0xeb,0x22,0x7e,0xb3,0x34,0x3a,0xbe,0xb0, +0x1, 0x22,0x12,0x48,0x8c,0x7e,0x73,0x37,0xe1,0xbe,0x70,0xff,0x68,0x13,0xbe,0x73, +0x38,0x7, 0x68,0xd, 0x7a,0x73,0x38,0x7, 0x74,0xff,0x7a,0xb3,0x37,0xe1,0x2, 0x48, +0x8c,0x22,0x12,0x37,0x6e,0x12,0x49,0xde,0x75,0xcd,0x0, 0xa9,0xd6,0xeb,0xa9,0xd7, +0xcd,0xc2,0xce,0x12,0x4f,0xee,0x12,0x2f,0xaf,0x74,0x1, 0x12,0x49,0xe7,0xa9,0xc6, +0xeb,0xa9,0xc7,0xcd,0xd2,0xce,0xe5,0x25,0x7e,0x71,0x24,0x2, 0x2f,0xf, 0x12,0x49, +0x8a,0x68,0xfb,0x20,0x93,0xfd,0x22,0x7c,0xab,0x7e,0xb3,0x3a,0x3, 0xb4,0x81,0x38, +0x4c,0xaa,0x78,0x5, 0xa9,0xd0,0x87,0x80,0x29,0xbe,0xa0,0x1, 0x78,0xf, 0xc2,0xaf, +0xa9,0xd0,0xce,0xa9,0xc7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf,0x80,0x15,0xbe,0xa0,0x2, +0x78,0x16,0xc2,0xaf,0x20,0x93,0x9, 0xa9,0xd0,0xce,0xa9,0xd7,0xc9,0xa9,0xd1,0x87, +0xd2,0xaf,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe4,0x7a,0xb3,0x3a,0x3, 0x22,0x6d,0x33, +0x7a,0x37,0x39,0x84,0x22,0xca,0xf8,0x7e,0xa3,0x2a,0x2, 0x7e,0x73,0x2a,0x3, 0xbe, +0xa0,0x1, 0x38,0x21,0xbe,0x70,0x1, 0x38,0x1c,0x7e,0x27,0x28,0x86,0xbe,0x24,0x0, +0x1e,0x28,0x2, 0x80,0x10,0x7e,0xf3,0x2f,0x80,0x4c,0xff,0x68,0x17,0x7e,0x27,0x2b, +0xb7,0x4d,0x22,0x78,0xf, 0x12,0x4a,0x2e,0x74,0x1, 0x7a,0xb3,0x39,0x86,0x7a,0xb3, +0x38,0x7, 0x80,0x36,0x4c,0xaa,0x78,0x37,0xa5,0xbf,0x1, 0x33,0x7e,0x37,0x2b,0xb7, +0x7a,0x37,0x2f,0x82,0x7e,0xb3,0x2f,0x80,0xb4,0x3, 0x1f,0x7e,0x37,0x2b,0xb7,0xbe, +0x34,0x0, 0x0, 0x28,0x15,0x74,0x4, 0x7a,0xb3,0x2f,0x80,0x7e,0x37,0x2f,0x98,0x7e, +0x27,0x2f,0x9a,0x12,0x4b,0x3e,0x61,0x37,0x80,0x0, 0x12,0xbe,0x2f,0x61,0x37,0x7e, +0x63,0x34,0x88,0x7e,0x50,0x9, 0xac,0x56,0x49,0xc2,0x29,0x8, 0x49,0xd2,0x29,0xa, +0x4c,0xff,0x78,0x1b,0xa5,0xbf,0x0, 0x43,0xbe,0xa0,0x1, 0x78,0x3e,0x7d,0x3c,0x7d, +0x2d,0x12,0xbd,0xcd,0x12,0x4b,0x3a,0x74,0x1, 0x7a,0xb3,0x2f,0x80,0x80,0x2c,0xbe, +0xf0,0x1, 0x78,0x1a,0x12,0x4c,0x76,0xbe,0x34,0x0, 0x64,0x38,0x9, 0x12,0x4c,0x1, +0xbe,0x34,0x0, 0xa0,0x28,0x15,0x74,0x3, 0x7a,0xb3,0x2f,0x80,0x80,0x5, 0xbe,0xf0, +0x3, 0x78,0x8, 0x7a,0xc7,0x2f,0x98,0x7a,0xd7,0x2f,0x9a,0x7e,0xb3,0x2f,0x80,0x60, +0x26,0x7d,0x3c,0x7d,0x2d,0x7e,0x17,0x2b,0xbb,0x7e,0x7, 0x2b,0xbd,0x12,0x4b,0xe9, +0xa, 0x2b,0x7e,0x73,0x2f,0x7f,0xa, 0x37,0xbd,0x32,0x58,0xb, 0x12,0x4b,0x3a,0x7a, +0xc7,0x2b,0xbb,0x7a,0xd7,0x2b,0xbd,0xda,0xf8,0x22,0x7d,0x3c,0x7d,0x2d,0x7d,0x42, +0x7d,0x13,0x7d,0x24,0x12,0x4f,0x6a,0x7d,0x31,0x12,0x4c,0xa, 0x2, 0x4b,0x4f,0x7e, +0x3, 0x2f,0xa8,0xbe,0x0, 0xf0,0x50,0x2, 0x61,0xe8,0x61,0xdd,0x6c,0x99,0x7e,0xb3, +0x2f,0x7f,0xbe,0xb0,0x20,0x50,0x5, 0x4, 0x7a,0xb3,0x2f,0x7f,0x7e,0x1f,0x2b,0xbf, +0x7a,0x1f,0x1f,0x34,0x7e,0x80,0x1, 0x80,0x49,0x74,0x4, 0xac,0xb8,0x49,0x35,0x2b, +0xbf,0x49,0x25,0x2b,0xc1,0x7e,0x17,0x1f,0x34,0x7e,0x7, 0x1f,0x36,0x12,0x4b,0xe9, +0x7c,0x1b,0x7e,0x3, 0x2f,0x7f,0xbc,0x1, 0x38,0x26,0xb, 0x90,0x7e,0x70,0x4, 0xac, +0x78,0x2e,0x34,0x2b,0xbf,0x7e,0x14,0x1f,0x34,0x74,0x4, 0x12,0x1f,0x8c,0x7e,0x34, +0x1f,0x34,0x7e,0x30,0x4, 0xac,0x39,0x2e,0x14,0x2b,0xbf,0x74,0x4, 0x12,0x1f,0x8c, +0xb, 0x80,0x7e,0x3, 0x2f,0xa8,0xbc,0x8, 0x38,0xaf,0xa, 0x59,0xb, 0x54,0x7c,0xb, +0x7a,0x3, 0x2f,0xa8,0x7e,0x3, 0x2f,0x7f,0xbe,0x0, 0x20,0x50,0xb, 0x7e,0x3, 0x2f, +0xa8,0xbe,0x0, 0xec,0x40,0x2, 0x61,0x5c,0x22,0x7d,0x51,0x7d,0x12,0x9d,0x35,0x12, +0x21,0xa, 0x7c,0xa7,0x12,0x4f,0xe, 0x7c,0xb7,0xbc,0xba,0x50,0x3, 0x7c,0xba,0x22, +0x22,0x7e,0x37,0x2f,0x96,0x9e,0x37,0x2f,0x8e,0x22,0x7e,0x17,0x2f,0x90,0xbd,0x13, +0x28,0xa, 0x7a,0x37,0x2f,0x90,0x7a,0x27,0x2f,0x92,0x80,0x10,0x7e,0x17,0x2f,0x88, +0xbd,0x13,0x50,0x8, 0x7a,0x37,0x2f,0x88,0x7a,0x27,0x2f,0x8a,0x7e,0x17,0x2f,0x8e, +0xbd,0x12,0x28,0xa, 0x7a,0x27,0x2f,0x8e,0x7a,0x37,0x2f,0x8c,0x80,0x10,0x7e,0x17, +0x2f,0x96,0xbd,0x12,0x50,0x8, 0x7a,0x27,0x2f,0x96,0x7a,0x37,0x2f,0x94,0x7e,0xb3, +0x2f,0xa8,0xb4,0xa, 0xf, 0x12,0x4c,0x76,0x7a,0x37,0x2f,0xa0,0x12,0x4c,0x1, 0x7a, +0x37,0x2f,0xa2,0x22,0xb4,0x14,0xe, 0x12,0x4c,0x76,0x7a,0x37,0x2f,0xa4,0x12,0x4c, +0x1, 0x7a,0x37,0x2f,0xa6,0x22,0x7e,0x37,0x2f,0x88,0x9e,0x37,0x2f,0x90,0x22,0x12, +0x4c,0x76,0x7a,0x37,0x2f,0x9c,0x12,0x4c,0x1, 0x7a,0x37,0x2f,0x9e,0x12,0x4d,0xd0, +0x60,0x1, 0x22,0x7e,0x73,0x2f,0xa8,0xa, 0x37,0x7a,0x35,0x24,0x7e,0x8, 0x2b,0xbf, +0x7e,0x18,0x2f,0x80,0x2, 0x4c,0xa7,0xca,0xf8,0x7e,0x45,0x24,0x7c,0xb9,0x7a,0xb3, +0x39,0x40,0x74,0xff,0x7a,0xb3,0x39,0x3f,0x6d,0x55,0x80,0x19,0x7d,0xf5,0x3e,0xf4, +0x12,0x4f,0x17,0x7d,0xe5,0x3e,0xe4,0x59,0xfe,0x1f,0x34,0x69,0xf6,0x0, 0x2, 0x59, +0xfe,0x21,0x14,0xb, 0x54,0xbd,0x45,0x38,0xe3,0x7e,0x33,0x39,0x40,0xbe,0x30,0x4, +0x38,0x2, 0xa1,0x69,0x69,0xf1,0x0, 0x1c,0x69,0x11,0x0, 0x1e,0xbd,0x1f,0x18,0x19, +0x4d,0x11,0x78,0x4, 0x7e,0x14,0x0, 0x1, 0x7d,0x3f,0x7d,0x21,0x12,0x1e,0xb9,0x7c, +0xf7,0x74,0x40,0x7a,0xb3,0x39,0x43,0x80,0x43,0x4d,0xff,0x78,0x4, 0x7e,0xf4,0x0, +0x1, 0x7d,0x31,0x7d,0x2f,0x12,0x1e,0xb9,0x7c,0xf7,0x74,0x80,0x7a,0xb3,0x39,0x43, +0x7d,0xf, 0x2d,0xf, 0xbd,0x1, 0x8, 0x24,0x1a,0x2, 0x1a,0x0, 0x7e,0x73,0x39,0x43, +0xa, 0x37,0x6d,0x22,0x12,0x1e,0xeb,0x7d,0x5f,0x1a,0x4a,0x1a,0x48,0x7d,0x1f,0x1a, +0x2, 0x1a,0x0, 0x2f,0x2, 0x12,0x1f,0x7, 0x7a,0x73,0x39,0x43,0xbe,0xf0,0x5, 0x58, +0x14,0x12,0x4d,0x88,0x12,0xc1,0xd5,0x12,0x4d,0x88,0x12,0xc3,0x7c,0x12,0x4d,0x88, +0x12,0xc2,0xc0,0x80,0xa, 0x74,0x7d,0x80,0x2, 0x74,0x7f,0x7a,0xb3,0x39,0x3f,0xe4, +0x7a,0xb3,0x39,0x40,0x7e,0x73,0x3a,0x2, 0xbe,0x73,0x39,0x3f,0x48,0x6, 0x7e,0xb3, +0x39,0x41,0x80,0x1, 0xe4,0xda,0xf8,0x22,0x7e,0x8, 0x1f,0x34,0x7e,0x18,0x21,0x14, +0x22,0x7e,0xb3,0x38,0x32,0x70,0x6, 0x12,0x4d,0xca,0x2, 0x4f,0xbf,0x12,0x4a,0x35, +0x12,0xbd,0xc2,0x50,0xa, 0x12,0x4c,0x7f,0x7c,0x3b,0x12,0x4d,0xca,0x80,0x5, 0x12, +0xc5,0x1f,0x7c,0x3b,0x4c,0x33,0x68,0x11,0x7c,0xb3,0x12,0xbd,0x46,0x60,0xa, 0x7a, +0x33,0x38,0x35,0x74,0x1, 0x7a,0xb3,0x2a,0x8, 0x22,0xe4,0x7a,0xb3,0x2f,0x80,0x22, +0xca,0xf8,0x6c,0xff,0x7e,0xb7,0x2f,0x9c,0x7e,0xc7,0x2f,0x9e,0x7e,0x97,0x2f,0x84, +0x7e,0xd7,0x2f,0x86,0x7e,0xa7,0x2f,0x98,0x7e,0xe7,0x2f,0x9a,0xe4,0x7e,0x73,0x2f, +0xa8,0x1b,0x70,0x7d,0x2b,0x7d,0x1c,0x12,0x4e,0xc2,0x70,0x2, 0xc1,0xbd,0x7e,0x73, +0x2f,0xa8,0xbe,0x70,0xa, 0x28,0x13,0xe4,0x7e,0x70,0x9, 0x7e,0x27,0x2f,0xa0,0x7e, +0x17,0x2f,0xa2,0x12,0x4e,0xc2,0x70,0x2, 0xc1,0xbd,0x7e,0x73,0x2f,0xa8,0xbe,0x70, +0x14,0x28,0x13,0xe4,0x7e,0x70,0x13,0x7e,0x27,0x2f,0xa4,0x7e,0x17,0x2f,0xa6,0x12, +0x4e,0xc2,0x70,0x2, 0xc1,0xbd,0xbe,0xc4,0x0, 0xf0,0x50,0x2d,0xbe,0xb4,0x1, 0xe, +0x28,0x27,0x7e,0xb3,0x2f,0x81,0x70,0x21,0x12,0x4f,0x5, 0x28,0x1c,0xbe,0xf4,0x13, +0x4c,0x50,0x16,0x7d,0xfc,0x3e,0xf4,0xbd,0xfb,0x50,0x62,0xbd,0xa9,0x50,0x5, 0x7e, +0xf0,0x20,0x80,0x59,0x7e,0xf0,0x21,0x80,0x54,0xbe,0xb4,0x0, 0x87,0x50,0x4e,0xbe, +0xc4,0x1, 0xe0,0x28,0x48,0x7e,0xb3,0x2f,0x81,0x70,0x42,0x12,0x4f,0x5, 0x28,0x3d, +0xbe,0xf4,0x13,0x4c,0x50,0x37,0x7d,0xfb,0x3e,0xf4,0xbd,0xfc,0x50,0x2f,0xbd,0xed, +0x50,0x5, 0x7e,0xf0,0x22,0x80,0x26,0x12,0x4f,0x8b,0x49,0x35,0x2b,0xbb,0x49,0x15, +0x2b,0xbd,0x49,0x25,0x2b,0xab,0x49,0x5, 0x2b,0xad,0x9d,0x10,0xbe,0x14,0x0, 0x20, +0x18,0x8, 0x9d,0x32,0xbe,0x34,0x0, 0x10,0x58,0x3, 0x7e,0xf0,0x23,0x7c,0xbf,0xda, +0xf8,0x22,0x7d,0x41,0x7d,0x2, 0x7c,0x37,0x7c,0x2b,0x74,0x4, 0xac,0xb2,0x49,0x35, +0x2b,0xbf,0x49,0xf5,0x2b,0xc1,0x74,0x4, 0xac,0xb3,0x49,0x25,0x2b,0xbf,0x49,0x55, +0x2b,0xc1,0x12,0x4f,0xcc,0x7d,0x3f,0x9d,0x35,0x12,0x21,0xa, 0x9d,0x34,0x12,0x21, +0xa, 0xbe,0x34,0x0, 0x4d,0x58,0xc, 0x12,0x4f,0xe, 0xbe,0x34,0x0, 0x4d,0x58,0x3, +0x74,0x1, 0x22,0xe4,0x22,0x7e,0xf7,0x2f,0x82,0xbe,0xf4,0xf, 0xa0,0x22,0x7d,0x31, +0x9d,0x30,0x2, 0x21,0xa, 0x7d,0xf4,0x3e,0xf4,0x7f,0x60,0x2d,0xdf,0xb, 0x6a,0xf0, +0x22,0x7c,0xab,0x6d,0x44,0x80,0x29,0x4c,0xaa,0x68,0x11,0x12,0x4f,0x58,0x60,0x5, +0x3e,0xe4,0x14,0x78,0xfb,0x12,0x4f,0x15,0x2d,0xfe,0x80,0xf, 0x12,0x4f,0x58,0x60, +0x5, 0x3e,0xe4,0x14,0x78,0xfb,0x12,0x4f,0x15,0x9d,0xfe,0x1b,0x6a,0xf0,0xb, 0x44, +0x7e,0xf5,0x29,0xbd,0xf4,0x38,0xd0,0x22,0x7f,0x71,0x2d,0xf4,0x7e,0x7b,0xb0,0x1a, +0xeb,0x7f,0x61,0x2e,0xd5,0x29,0x7e,0x6b,0xb0,0x22,0x7e,0xa3,0x2f,0xa8,0xbe,0xa0, +0xf0,0x50,0x17,0x74,0x4, 0xa4,0x59,0x35,0x2b,0xbf,0x12,0x4f,0x8b,0x59,0x25,0x2b, +0xc1,0x7e,0xb3,0x2f,0xa8,0x4, 0x7a,0xb3,0x2f,0xa8,0x22,0x7e,0xa3,0x2f,0xa8,0x74, +0x4, 0xa4,0x22,0x7c,0x7b,0x7e,0x63,0x2a,0x71,0xa, 0x6, 0x2e,0x4, 0x0, 0x3, 0x7e, +0x63,0x2a,0x6e,0xa, 0x16,0xad,0x10,0x7d,0x21,0x12,0x4f,0xe5,0xa, 0x26,0x7a,0x25, +0x29,0x74,0x1d,0xac,0x7b,0x2e,0x34,0x38,0x45,0x6d,0x22,0xe4,0x2, 0x4f,0x21,0xe4, +0x7a,0xb3,0x39,0xde,0x22,0x7e,0x34,0x0, 0xc8,0x2, 0x23,0xcc,0x9d,0x32,0x12,0x21, +0xa, 0x7d,0x13,0x22,0x7e,0xb3,0x38,0x32,0xbe,0xb0,0x1, 0x22,0xa, 0x5b,0x2e,0x54, +0x0, 0x8, 0xf5,0xcc,0x22,0x3e,0x24,0x7e,0xf, 0x39,0xda,0x2d,0x12,0x22,0x7e,0x8, +0x0, 0x25,0x7e,0x18,0x0, 0x24,0x22,0x7e,0x73,0x28,0x93,0x7a,0x73,0x28,0x94,0x7e, +0x73,0x2a,0x2, 0x7a,0x73,0x2a,0x3, 0xe4,0x7a,0xb3,0x2a,0x6, 0x22,0x7e,0x37,0x33, +0xeb,0xb, 0x34,0x7a,0x37,0x33,0xeb,0x7e,0x37,0x33,0xed,0xbe,0x37,0x33,0xeb,0x28, +0x3, 0x2, 0x50,0x28,0x22,0x2, 0x50,0xd, 0xe5,0x9a,0x60,0x5, 0xd2,0x9c,0xa9,0xd6, +0xdf,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, +0xc0,0xd0,0xc0,0x83,0xc0,0x82,0x12,0x50,0x25,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda, +0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7e,0x23, +0x2b,0xf, 0x7e,0x33,0x38,0xce,0xac,0x23,0x2e,0x14,0x1, 0xf4,0xbe,0x14,0x0, 0xa, +0x50,0x4, 0x7e,0x14,0x0, 0xa, 0x7e,0x63,0x2b,0x10,0xbe,0x14,0xf, 0x3c,0x40,0x4, +0x7e,0x14,0xf, 0x3c,0xbe,0x14,0x7, 0x8, 0x40,0x3, 0xe4,0x80,0x2, 0x74,0x1, 0x7a, +0xb3,0x2b,0x10,0x7e,0x73,0x2b,0x10,0xbc,0x76,0x68,0x2, 0xd2,0x10,0x7e,0x24,0x1, +0xf4,0x7d,0x31,0x8d,0x32,0x7c,0x17,0xbe,0x10,0x7, 0x28,0x3, 0x7e,0x10,0x7, 0x7e, +0x1f,0x39,0xc1,0x69,0x51,0x0, 0x86,0x54,0x1f,0xa, 0x1, 0x3e,0x4, 0x3e,0x4, 0x3e, +0x4, 0x3e,0x4, 0x3e,0x4, 0x2d,0x5, 0x79,0x1, 0x0, 0x86,0x6d,0x0, 0x7e,0x34,0xb8, +0x0, 0x7e,0x24,0x0, 0xb, 0x2, 0x1f,0x58,0x7e,0xa3,0x0, 0x5f,0xbe,0xa0,0xff,0x68, +0x48,0xbe,0xa3,0x3, 0xfc,0x68,0x42,0x74,0x5, 0xa4,0x12,0x57,0x7c,0x12,0x51,0x2a, +0x12,0x55,0x70,0x12,0x51,0x2a,0x12,0x55,0x67,0x12,0x57,0x8e,0x50,0x9, 0x7e,0xb3, +0x0, 0x5f,0x12,0x55,0x79,0x80,0x6, 0x12,0x51,0x2a,0x12,0x54,0x6a,0x12,0x51,0x36, +0x12,0x54,0x63,0x7e,0x73,0x2b,0x14,0xa, 0x37,0x7e,0xf, 0x39,0xc9,0x79,0x30,0x0, +0x1a,0x7e,0x73,0x0, 0x5f,0x7a,0x73,0x3, 0xfc,0x22,0x7e,0xa3,0x0, 0x5f,0x74,0x5, +0xa4,0x22,0x7a,0xb3,0x2b,0xf, 0x12,0x50,0x5e,0x7a,0x37,0x2b,0x1b,0x22,0x12,0x51, +0x32,0x30,0x10,0xc, 0xc2,0x10,0x12,0x57,0xd5,0x30,0x0, 0x4, 0xe4,0x12,0xa, 0x66, +0x30,0x0, 0x9, 0x12,0xab,0x26,0x12,0x57,0xf8,0x2, 0x57,0x9f,0x22,0x7e,0xb, 0x70, +0x7a,0x73,0x2b,0xf, 0x29,0x70,0x0, 0x4, 0x7a,0x73,0x2b,0x62,0x29,0x70,0x0, 0x1, +0x7a,0x73,0x2b,0x14,0x29,0x70,0x0, 0x3, 0x7a,0x73,0x2b,0x20,0x12,0x51,0x36,0x12, +0x54,0x63,0xd2,0x0, 0xc2,0x1, 0x2, 0x3b,0xba,0xca,0xf8,0x7c,0xfb,0x74,0x5, 0xac, +0xbf,0x12,0x57,0x7c,0x12,0x55,0x70,0x12,0x54,0x6a,0x12,0x55,0x67,0x7a,0xf3,0x0, +0x5f,0x7c,0xbf,0x12,0x55,0x79,0x12,0x51,0x36,0x74,0x5, 0xac,0xbf,0x9, 0xb5,0x26, +0x37,0x12,0x57,0xba,0x12,0x23,0x23,0xe4,0x7a,0xb3,0x16,0x91,0xda,0xf8,0x22,0x7e, +0xb3,0x37,0x66,0x60,0x6, 0x14,0x7a,0xb3,0x37,0x66,0x22,0x12,0xa7,0xf9,0x7e,0xb3, +0x37,0xed,0x70,0xe, 0x7e,0xb3,0x3a,0xf, 0xb4,0x1, 0x7, 0xe4,0x12,0x51,0x89,0x12, +0x57,0xee,0x12,0x54,0x27,0x12,0xa9,0x2d,0x7e,0xa3,0x37,0xed,0x7a,0xa3,0x3a,0xf, +0xbe,0xb0,0xff,0x68,0x3, 0x2, 0x51,0x89,0x22,0xca,0xf8,0x6c,0xff,0x7e,0x73,0x0, +0x5f,0xbc,0x7f,0x68,0x2a,0x7e,0x30,0x5, 0xac,0x3f,0x12,0x52,0x6f,0xca,0x39,0x7e, +0x30,0x38,0xac,0x3f,0x12,0x52,0x88,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c, +0xca,0x39,0x7e,0x30,0x8c,0xac,0x3f,0x12,0x52,0x7d,0x12,0x20,0xc3,0x1b,0xfd,0xb, +0xf0,0xbe,0xf0,0x4, 0x40,0xc7,0x7e,0x23,0x0, 0x5f,0x7e,0x30,0x5, 0xac,0x23,0x12, +0x52,0x6f,0xca,0x39,0x7e,0x23,0x0, 0x5f,0x7e,0x30,0x38,0xac,0x23,0x12,0x52,0x88, +0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x23,0x0, 0x5f,0x7e, +0x30,0x8c,0xac,0x23,0x12,0x52,0x7d,0x12,0x20,0xc3,0x1b,0xfd,0xda,0xf8,0x22,0x2e, +0x14,0x26,0x33,0x6d,0x0, 0x12,0x51,0x5d,0x7e,0x34,0x0, 0x38,0x22,0x2e,0x14,0x1, +0x40,0x6d,0x0, 0x7e,0x18,0x3, 0x70,0x22,0x2e,0x14,0x0, 0x60,0x6d,0x0, 0x7e,0x18, +0x34,0x0, 0x22,0xca,0xd8,0xca,0x79,0x7e,0xd0,0xe, 0x7e,0xe0,0x19,0x7e,0x73,0x2a, +0x74,0xbe,0x70,0x19,0x28,0x4, 0x7c,0xf7,0x80,0x2, 0x7c,0xfe,0x7a,0xd3,0x2a,0x6d, +0x7a,0xe3,0x2a,0x6e,0x7a,0xd3,0x2a,0x71,0x7a,0xe3,0x2a,0x72,0x7a,0xd3,0x2a,0x73, +0x7a,0xe3,0x2a,0x74,0x74,0x1, 0x7a,0xb3,0x2a,0x77,0x7a,0xd3,0x2a,0x6f,0xa, 0x3e, +0x1b,0x34,0x7a,0x73,0x2a,0x70,0x74,0x5, 0x7a,0xb3,0x2a,0x78,0x74,0xff,0x7a,0xb3, +0x2a,0x79,0xa, 0x3d,0xca,0x39,0x7e,0x34,0x60,0x52,0x7e,0x24,0x0, 0xff,0x7e,0x8, +0x2a,0x7a,0x12,0x20,0xc3,0x1b,0xfd,0xa, 0x3f,0xca,0x39,0x7e,0x34,0x60,0x75,0x7e, +0x24,0x0, 0xff,0x7e,0x8, 0x2a,0x9d,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x23, +0xca,0x39,0x7e,0x34,0x60,0xd8,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x21,0x12,0x20, +0xc3,0x1b,0xfd,0x12,0xaa,0xc5,0x12,0x64,0xdf,0x7a,0xd3,0x2a,0x75,0x7a,0xe3,0x2a, +0x76,0x12,0x5d,0x7e,0x74,0x1, 0x12,0x30,0x38,0xe4,0x7a,0xb3,0x2b,0x1, 0x7a,0xb3, +0x2b,0x2, 0x12,0x62,0xab,0x7a,0x37,0x2b,0xd, 0x74,0x3, 0x7a,0xb3,0x2b,0x3, 0xe4, +0x7a,0xb3,0x2b,0x4, 0x74,0x2, 0x7a,0xb3,0x2b,0x5, 0x7e,0x34,0x0, 0xfa,0x7a,0x37, +0x2b,0x7, 0x74,0x4, 0x7a,0xb3,0x2b,0x6, 0x7e,0x34,0x0, 0xf, 0x7a,0x37,0x2b,0x9, +0x7e,0x34,0x20,0x5f,0x7a,0x37,0x2b,0xb, 0x74,0x20,0x7a,0xb3,0x2b,0x62,0x74,0x1, +0x7a,0xb3,0x2b,0x10,0x74,0x20,0x7a,0xb3,0x2b,0x11,0x74,0x4, 0x7a,0xb3,0x2b,0x13, +0x74,0x1e,0x12,0x51,0x32,0xe4,0x7a,0xb3,0x2b,0x1d,0x7a,0xb3,0x2b,0x1e,0x7e,0x34, +0x1, 0xf4,0x7a,0x37,0x2b,0x19,0x74,0x1, 0x7a,0xb3,0x2b,0x12,0x74,0x54,0x7a,0xb3, +0x2b,0x20,0x74,0x4f,0x7a,0xb3,0x2b,0x1f,0x6d,0x33,0x7a,0x37,0x2b,0x15,0x7a,0x37, +0x2b,0x17,0x74,0x3, 0x7a,0xb3,0x2b,0x14,0x7e,0x34,0x0, 0x30,0x7a,0x37,0x2b,0x6a, +0x7a,0xb3,0x2b,0x67,0x7e,0x34,0x0, 0x5, 0x7a,0x37,0x2b,0x68,0xe4,0x7a,0xb3,0x2b, +0x66,0x7e,0x34,0x4, 0x6d,0x7a,0x37,0x2b,0x6c,0x74,0x1, 0x7a,0xb3,0x2b,0x63,0x74, +0x4, 0x7a,0xb3,0x2b,0x64,0xe4,0x7a,0xb3,0x2b,0x65,0x74,0x1, 0x7a,0xb3,0x2b,0x60, +0xe4,0x7a,0xb3,0x2b,0x61,0x7e,0x34,0x20,0x65,0x7a,0x37,0x2b,0x6e,0xa, 0x3e,0xca, +0x39,0x7e,0x34,0x60,0xfb,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x44,0x12,0x20,0xc3, +0x1b,0xfd,0xda,0x79,0xda,0xd8,0x22,0x12,0xa7,0x37,0x2, 0x54,0x2d,0x7e,0xb3,0x37, +0x69,0x60,0xf, 0x74,0x1, 0x7a,0xb3,0x37,0x71,0x7e,0xb3,0x37,0xdf,0x70,0x3, 0x12, +0xa7,0xd0,0x7e,0xb3,0x37,0x71,0xb4,0x1, 0xc, 0x74,0x3, 0x7a,0xb3,0x34,0xc3,0x7e, +0x34,0x14,0x0, 0x80,0x9, 0xe4,0x7a,0xb3,0x34,0xc3,0x7e,0x34,0xa, 0x0, 0x7a,0x37, +0x2a,0x62,0x22,0x7e,0x8, 0x2a,0x6d,0x2, 0x3, 0x8b,0x9, 0x75,0x26,0x35,0x7a,0x73, +0x2b,0x1f,0x22,0xca,0x3b,0x7a,0xd, 0x2e,0x7c,0xcb,0x7e,0xb3,0x2b,0x1d,0xf5,0x32, +0x7e,0xb3,0x2b,0xf, 0xf5,0x33,0x7e,0xd3,0x2b,0x14,0x7e,0xe3,0x2b,0x1f,0x7e,0xf3, +0x2b,0x20,0x7e,0x34,0x0, 0x38,0xca,0x39,0x7e,0x18,0x34,0x0, 0x7e,0x8, 0x24,0xf2, +0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x18,0x3, 0x70,0x7e, +0x8, 0x25,0x2a,0x12,0x20,0xc3,0x1b,0xfd,0x7c,0xbc,0x12,0x55,0x79,0x74,0x1, 0x7a, +0xb3,0x2b,0x1d,0x74,0x5, 0xac,0xbc,0x12,0x55,0x70,0x74,0x5, 0xac,0xbc,0x12,0x54, +0x6a,0x74,0x5, 0xac,0xbc,0x12,0x55,0x67,0x74,0x5, 0xac,0xbc,0x9, 0x75,0x26,0x37, +0xbe,0x73,0x2b,0x62,0x68,0x6, 0x7a,0x73,0x2b,0x62,0xd2,0x10,0xc2,0x0, 0x12,0x57, +0x85,0x12,0x51,0x3e,0x12,0x3f,0x9e,0x30,0xf, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e, +0x14,0x40,0x0, 0x7d,0x31,0x7e,0x2f,0x13,0x86,0x7d,0x25,0x7e,0x4, 0xd, 0xc8,0x12, +0x56,0x2d,0x12,0x57,0xe5,0xa4,0x7a,0x55,0x34,0x7e,0xd, 0x2e,0x7e,0x18,0xd, 0xc8, +0x12,0x5d,0xf1,0x12,0xb5,0xa7,0xe5,0x32,0x7a,0xb3,0x2b,0x1d,0xe5,0x33,0x7a,0xb3, +0x2b,0xf, 0x7a,0xd3,0x2b,0x14,0x7a,0xe3,0x2b,0x1f,0x7a,0xf3,0x2b,0x20,0x7e,0x34, +0x0, 0x38,0xca,0x39,0x7e,0x18,0x24,0xf2,0x7e,0x8, 0x34,0x0, 0x12,0x20,0xc3,0x1b, +0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x18,0x25,0x2a,0x7e,0x8, 0x3, 0x70,0x12, +0x20,0xc3,0x1b,0xfd,0xda,0x3b,0x22,0x9, 0x75,0x26,0x36,0x7a,0x73,0x2b,0x20,0x22, +0x9, 0x75,0x26,0x34,0x7a,0x73,0x2b,0x14,0x22,0xca,0xf8,0x7c,0xfb,0x7e,0x34,0x0, +0x38,0xca,0x39,0xac,0x7f,0x2e,0x34,0x0, 0x60,0x6d,0x22,0x7e,0x8, 0x34,0x0, 0x12, +0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0xac,0x7f,0x2e,0x34,0x1, 0x40, +0x6d,0x22,0x7e,0x8, 0x3, 0x70,0x12,0x20,0xc3,0x1b,0xfd,0xda,0xf8,0x22,0xca,0x3b, +0x7e,0xb3,0x2b,0xf, 0x7a,0xb3,0x1f,0x33,0x7e,0xf3,0x2b,0x62,0x12,0x8b,0x1a,0x7c, +0xdb,0xbe,0xd0,0xff,0x68,0x64,0x6c,0xcc,0x12,0x57,0x85,0xf5,0x29,0x7e,0x73,0x2b, +0xf, 0xbe,0x71,0x29,0x68,0x36,0x7e,0x70,0x4, 0xac,0x7d,0xa, 0x2c,0x12,0x88,0x56, +0x7c,0xeb,0xbe,0xe0,0x2, 0x38,0x43,0xa, 0xe, 0x7e,0x14,0x2, 0xe0,0xad,0x10,0x2e, +0x14,0x16,0x93,0x6d,0x0, 0x7a,0xd, 0x2a,0x7e,0x70,0x1d,0xac,0x7e,0x2e,0x34,0x38, +0x45,0x6d,0x22,0x7a,0x1f,0x38,0x41,0x7c,0xbc,0x12,0x54,0x73,0xb, 0xc0,0xbe,0xc0, +0x4, 0x40,0xb5,0x7e,0x73,0x2b,0x62,0xbc,0x7f,0x68,0x6, 0x7a,0xf3,0x2b,0x62,0xd2, +0x10,0xd2,0x0, 0x7e,0xb3,0x1f,0x33,0x12,0x51,0x3e,0xda,0x3b,0x22,0x7e,0xb3,0x2a, +0x6d,0xca,0x3b,0x7c,0xdb,0x7a,0x5, 0x38,0x7d,0x71,0x7a,0x25,0x36,0x7a,0x35,0x34, +0x12,0x57,0x8e,0x50,0x7b,0x6c,0xcc,0x80,0x13,0x7e,0x73,0x2a,0x6e,0x12,0x57,0x57, +0x12,0x57,0x3d,0x7e,0x34,0x34,0x0, 0x12,0x57,0x60,0xb, 0xc0,0x12,0x57,0x75,0x38, +0xe8,0x6c,0xcc,0x80,0x55,0x7e,0xa3,0x2a,0x6e,0x7c,0x7a,0x12,0x57,0x57,0x75,0x3a, +0x0, 0x80,0x27,0x7e,0xb3,0x38,0xb2,0xbe,0xb1,0x3a,0x7e,0x70,0x4, 0x28,0x8, 0xac, +0x7c,0x49,0x43,0x3, 0x70,0x80,0x6, 0xac,0x7c,0x49,0x43,0x3, 0x72,0x7e,0x71,0x3a, +0x74,0x2, 0xac,0x7b,0x59,0x43,0x34,0x50,0x5, 0x3a,0x7e,0xb3,0x2a,0x70,0xbe,0xb1, +0x3a,0x38,0xd0,0x7e,0x34,0x10,0x0, 0x74,0x2, 0xa4,0x59,0x35,0x34,0x4e,0x12,0x57, +0x3d,0x7e,0x34,0x34,0x50,0x12,0x57,0x60,0xb, 0xc0,0xbc,0xdc,0x38,0xa7,0x80,0x2c, +0x7a,0xd3,0x25,0xb6,0x7e,0x73,0x2a,0x70,0x7a,0x73,0x25,0xb7,0xe4,0x7a,0xb3,0x25, +0xb9,0x74,0x6, 0x7a,0xb3,0x25,0xb8,0x7a,0x77,0x25,0xba,0x7a,0x77,0x25,0xbe,0x7e, +0x8, 0x25,0xb6,0x7e,0x73,0x2b,0x1f,0xa, 0x37,0x12,0xe, 0x37,0x7d,0x37,0x12,0x6f, +0xfa,0x7e,0x35,0x38,0x7a,0x37,0x25,0xbe,0xe4,0x7a,0xb3,0x25,0xb8,0x12,0x57,0x4e, +0x7a,0xd3,0x25,0xb6,0x7e,0xb3,0x2b,0x1d,0x70,0xf, 0xe4,0x7a,0xb3,0x25,0xb9,0x7a, +0x77,0x25,0xba,0x7e,0x34,0x0, 0x20,0x80,0x16,0x74,0x1, 0x7a,0xb3,0x25,0xb9,0x7e, +0x35,0x34,0x7a,0x37,0x25,0xba,0x7e,0x35,0x36,0x7a,0x37,0x25,0xbc,0x6d,0x33,0x7a, +0x37,0x25,0xc0,0x7e,0x8, 0x25,0xb6,0x12,0xd, 0x7, 0xda,0x3b,0x22,0x74,0xc, 0x7a, +0xb3,0x25,0xb8,0x74,0x1, 0x7a,0xb3,0x25,0xb6,0xe4,0x7a,0xb3,0x25,0xb9,0x7e,0x73, +0x2a,0x6e,0x7a,0x73,0x25,0xb7,0x22,0xac,0x7c,0x3e,0x34,0x7d,0xf7,0x2d,0xf3,0x22, +0x7a,0x37,0x25,0xba,0x7d,0x3f,0x7a,0x37,0x25,0xbc,0x7a,0x37,0x25,0xbe,0x7e,0x8, +0x25,0xb6,0x2, 0x7, 0x9b,0x7e,0x73,0x2a,0x6f,0xbc,0x7c,0x22,0x9, 0x75,0x26,0x33, +0x7a,0x73,0x2b,0xf, 0x22,0x74,0x5, 0xac,0xbc,0x9, 0xb5,0x26,0x33,0x22,0x7e,0xb3, +0x38,0x9, 0xb4,0x3, 0x8, 0x7e,0xb3,0x38,0xb3,0x70,0x2, 0xc3,0x22,0xd3,0x22,0x12, +0xa7,0xf9,0x6d,0x33,0x7a,0x37,0x37,0xdd,0x6c,0xaa,0x12,0xaa,0x88,0xb, 0xa0,0xbe, +0xa0,0x4, 0x40,0xf6,0xe4,0x7a,0xb3,0x37,0x72,0x22,0x7e,0xa3,0x2b,0x62,0xbc,0xab, +0x68,0x6, 0x7a,0xb3,0x2b,0x62,0xd2,0x10,0x30,0x10,0x9, 0xc2,0x10,0x12,0x57,0xd5, +0xe4,0x2, 0xa, 0x66,0x22,0x7e,0x8, 0x2a,0x6d,0x12,0x3, 0x8b,0x7e,0x8, 0x2a,0x6d, +0x74,0x3, 0x2, 0x11,0x7a,0x7e,0xa3,0x2a,0x6e,0x7e,0xb3,0x2a,0x6d,0x22,0xe4,0x7a, +0xb3,0x37,0x69,0x7a,0xb3,0x37,0x71,0x22,0x7e,0xb3,0x2b,0xf, 0xca,0x3b,0x7c,0xeb, +0x6c,0xff,0x7e,0xc4,0x1, 0xf4,0x7e,0x73,0x38,0xce,0xa, 0xb7,0x7e,0xb3,0x2b,0x10, +0xf5,0x34,0x75,0x35,0x4, 0xe4,0x7a,0xb3,0x37,0x72,0xa, 0x3e,0xad,0x3b,0x7d,0xa3, +0x2d,0xac,0x6c,0xdd,0x7e,0xa3,0x37,0x72,0xbe,0xa1,0x35,0x40,0x2, 0x80,0x19,0xbe, +0xa0,0x0, 0x28,0x19,0x74,0x5, 0xa4,0x9, 0x75,0x26,0x33,0xbc,0x7e,0x78,0xe, 0xe5, +0x35,0x14,0xbe,0xb3,0x37,0x72,0x78,0x5, 0xe4,0x7a,0xb3,0x37,0x72,0x7e,0xc3,0x37, +0x72,0x80,0x3a,0x7e,0xb3,0x37,0x72,0x4, 0x7a,0xb3,0x37,0x72,0x74,0x5, 0xac,0xbc, +0x9, 0x75,0x26,0x33,0xbc,0x7e,0x68,0x23,0xa, 0xdd,0x19,0xcd,0x37,0x76,0xa, 0x97, +0xad,0x9b,0x2d,0x9c,0x7c,0xad,0xb, 0xd0,0x7c,0xba,0x7d,0x39,0x7d,0x2a,0x7e,0x31, +0x34,0x12,0x10,0x0, 0xb, 0xf0,0xbe,0xf0,0x3, 0x50,0x8, 0xb, 0xc0,0xe5,0x35,0xbc, +0xbc,0x38,0xc0,0x7a,0xf3,0x37,0x73,0xda,0x3b,0x22,0x74,0xa, 0x7a,0xb3,0x2a,0x4d, +0x74,0x10,0x7a,0xb3,0x2a,0x4e,0x12,0x47,0xf8,0x7a,0x37,0x2a,0x55,0x74,0x14,0x7a, +0xb3,0x2a,0x59,0x12,0x5d,0xde,0x7e,0x24,0x0, 0x78,0x7a,0x27,0x2a,0x5c,0x7e,0x24, +0xff,0x6a,0x7a,0x27,0x2a,0x5e,0x7a,0x37,0x2a,0x60,0xe4,0x7a,0xb3,0x2a,0x64,0x74, +0x4, 0x7a,0xb3,0x2a,0x65,0x7e,0x34,0x0, 0x64,0x7a,0x37,0x2a,0x66,0x7e,0x34,0xa, +0x0, 0x7a,0x37,0x2a,0x62,0xe4,0x7a,0xb3,0x2a,0x6b,0x7a,0xb3,0x16,0x92,0x22,0x12, +0x5c,0x95,0x12,0x52,0x93,0x12,0x0, 0x42,0x12,0x5d,0xd5,0x7e,0x18,0x4, 0x0, 0x7a, +0x1f,0x6, 0xf8,0x7e,0xf, 0x6, 0xf8,0x7e,0x1f,0x6, 0xf4,0x12,0x65,0x54,0x7e,0x18, +0x8, 0xa, 0x7a,0x1f,0x13,0x86,0x7e,0x18,0xd, 0xc8,0x7a,0x1f,0x13,0x8a,0x7e,0xf, +0x13,0x8a,0x7e,0x1f,0x13,0x86,0x12,0x5f,0xd5,0x12,0x59,0x46,0x12,0x58,0x9a,0x12, +0x64,0xb0,0x12,0x59,0x8e,0x2, 0x59,0x38,0xe4,0x7a,0xb3,0x34,0x38,0x7a,0xb3,0x34, +0x39,0x7a,0xb3,0x34,0x3a,0x22,0x2, 0x59,0x49,0x7e,0x34,0x0, 0xfa,0x7a,0x37,0x28, +0x95,0x7e,0x34,0x2, 0x26,0x7a,0x37,0x28,0x99,0x7e,0x34,0x0, 0x96,0x7a,0x37,0x28, +0x97,0x7a,0x37,0x28,0x9b,0x7e,0x34,0x0, 0x50,0x7a,0x37,0x28,0x9d,0x7e,0x34,0x0, +0x2b,0x7a,0x37,0x28,0x9f,0x12,0x5f,0xc8,0x74,0x1, 0x7a,0xb3,0x28,0xa5,0xe4,0x7a, +0xb3,0x28,0xa8,0x7e,0x8, 0x25,0xf7,0x7e,0x34,0x0, 0x3c,0x2, 0x20,0xe8,0x7e,0x8, +0x28,0xae,0x7e,0x34,0x1, 0xe, 0x74,0xff,0x12,0x20,0xe8,0x12,0x5f,0xbc,0x7e,0x8, +0x29,0xbc,0x12,0x59,0xb1,0x7e,0x8, 0x2a,0x2, 0x7e,0x34,0x0, 0xb, 0xe4,0x2, 0x20, +0xe8,0x6c,0xaa,0x74,0x3, 0x12,0x5d,0xe7,0x7f,0x10,0x2d,0x34,0x39,0xb1,0x0, 0xa, +0x12,0x59,0xd9,0x7f,0x70,0x2d,0xf3,0x79,0x47,0x0, 0x14,0x2d,0x31,0x79,0x41,0x0, +0x28,0xb, 0xa0,0xbe,0xa0,0xa, 0x40,0xdb,0x22,0x7e,0x44,0x7f,0xff,0x7e,0x70,0x2, +0xac,0x7a,0x22,0xca,0xf8,0x7e,0x68,0x29,0xbc,0x6c,0xaa,0x7e,0x70,0xff,0x12,0x5c, +0x74,0xe4,0xa, 0x4a,0x19,0xb4,0x1f,0x34,0x74,0xff,0x19,0xb4,0x1f,0x46,0x19,0xb4, +0x1f,0x50,0xb, 0xa0,0xbe,0xa0,0xa, 0x78,0xe2,0x7e,0x73,0x2a,0x2, 0xa5,0xbf,0x0, +0x21,0x7e,0xb3,0x34,0x4f,0x70,0x2, 0x61,0xe2,0x6c,0xaa,0x7e,0x44,0x7f,0xff,0x12, +0x5c,0x7e,0x79,0x40,0x0, 0x14,0x12,0x5c,0x6b,0xb, 0xa0,0xbe,0xa0,0xa, 0x78,0xeb, +0x61,0xe2,0x7e,0xb3,0x34,0x4f,0x70,0x3d,0xbe,0x70,0x0, 0x28,0x38,0x6c,0xaa,0x80, +0x2a,0x7e,0x90,0x9, 0xac,0x9a,0x49,0x34,0x28,0xae,0x12,0x5c,0x7e,0x79,0x30,0x0, +0x14,0x49,0x34,0x28,0xb0,0x7f,0x6, 0x2d,0x12,0x79,0x30,0x0, 0x28,0x74,0x1, 0xa, +0x3a,0x19,0xb3,0x1f,0x34,0x19,0xa4,0x28,0xb2,0xb, 0xa0,0x7e,0xb3,0x2a,0x2, 0xbc, +0xba,0x38,0xce,0x61,0xe2,0x6c,0xaa,0x12,0x59,0xd9,0x3e,0x34,0x59,0x43,0x15,0x4e, +0x59,0x43,0x15,0x50,0x59,0x43,0x15,0x76,0x59,0x43,0x15,0x78,0xb, 0xa0,0xbe,0xa0, +0xa, 0x78,0xe4,0x6c,0xaa,0x80,0x3b,0x6c,0xff,0x7e,0x70,0x2, 0xac,0x7f,0x7f,0x6, +0x2d,0x13,0x69,0x30,0x0, 0x14,0xbe,0x34,0x7f,0xff,0x68,0x1d,0xa, 0x4f,0x9, 0xb4, +0x1f,0x50,0xb4,0xff,0x14,0x12,0x5c,0x63,0x59,0x32,0x15,0x4e,0x69,0x30,0x0, 0x28, +0x59,0x32,0x15,0x50,0x12,0x5c,0x88,0x80,0x7, 0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0xc9, +0xb, 0xa0,0x7e,0xb3,0x34,0x4f,0xbc,0xba,0x38,0xbd,0x6c,0xaa,0xa, 0x3a,0x9, 0xb3, +0x1f,0x46,0xb4,0xff,0x17,0x6c,0xff,0xa, 0x4f,0x9, 0xb4,0x1f,0x50,0xb4,0xff,0x5, +0x12,0x5c,0x88,0x80,0x7, 0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0xeb,0xb, 0xa0,0xbe,0xa0, +0xa, 0x78,0xd9,0x6c,0xaa,0x80,0x1a,0x7e,0x70,0x9, 0xac,0x7a,0x49,0x43,0x28,0xae, +0x12,0x5c,0x63,0x59,0x42,0x15,0x76,0x49,0x33,0x28,0xb0,0x59,0x32,0x15,0x78,0xb, +0xa0,0x7e,0xb3,0x2a,0x2, 0xbc,0xba,0x38,0xde,0x7e,0x34,0x15,0x4e,0x7a,0x37,0x1f, +0x40,0x7e,0x34,0x15,0x76,0x7a,0x37,0x1f,0x42,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f, +0x44,0x7e,0x73,0x34,0x4f,0x7a,0x73,0x1f,0x3e,0x7e,0x73,0x2a,0x2, 0x7a,0x73,0x1f, +0x3f,0x7e,0x8, 0x1f,0x3e,0x12,0x4, 0xad,0x6c,0xaa,0x80,0x57,0x7e,0x70,0xff,0x6c, +0xff,0x7e,0x50,0x2, 0xac,0x5f,0x49,0x12,0x15,0x9e,0xa, 0x2a,0xbd,0x21,0x78,0x8, +0xa, 0x3f,0x9, 0x73,0x1f,0x46,0x80,0x7, 0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0xe2,0xbe, +0x70,0xff,0x68,0x2d,0x12,0x5c,0x74,0x74,0x1, 0xa, 0x47,0x19,0xb4,0x1f,0x34,0x7e, +0x90,0x9, 0xac,0x9a,0x49,0x24,0x28,0xae,0x7e,0x30,0x2, 0xac,0x37,0x2d,0x1d,0x7d, +0xc, 0x79,0x20,0x0, 0x14,0x49,0x44,0x28,0xb0,0x7e,0x50,0x2, 0xac,0x57,0x12,0x5c, +0x6b,0xb, 0xa0,0x7e,0x63,0x2a,0x2, 0xbc,0x6a,0x38,0xa1,0x6c,0xaa,0xa, 0x3a,0x9, +0xb3,0x1f,0x34,0xbe,0xb0,0x1, 0x68,0x13,0x12,0x59,0xd9,0x7f,0x6, 0x2d,0x13,0x79, +0x40,0x0, 0x14,0x2d,0x3d,0x7d,0x2c,0x79,0x41,0x0, 0x28,0xb, 0xa0,0xbe,0xa0,0xa, +0x78,0xdb,0x7e,0xf3,0x2a,0x2, 0x7a,0xf3,0x34,0x4f,0x6c,0xaa,0xa, 0x3a,0x9, 0xb3, +0x1f,0x34,0xb4,0x1, 0x2c,0x12,0x5c,0x5c,0x29,0xb1,0x0, 0xa, 0xb4,0x1, 0x6, 0x74, +0x3, 0x39,0xb1,0x0, 0xa, 0x12,0x5c,0x5c,0x29,0x31,0x0, 0xa, 0xa5,0xbb,0x3, 0x6, +0xe4,0x7a,0x1b,0xb0,0x80,0x32,0xa5,0xbb,0x0, 0x2e,0x74,0x2, 0x7a,0x1b,0xb0,0x80, +0x27,0x12,0x5c,0x5c,0x29,0xb1,0x0, 0xa, 0xbe,0xb0,0x2, 0x68,0x2, 0x70,0x14,0x74, +0x1, 0x7a,0x1b,0xb0,0x7c,0x2f,0xb, 0xf0,0x7e,0x30,0x9, 0xac,0x23,0x19,0xa1,0x28, +0xb2,0x80,0x5, 0x74,0x3, 0x7a,0x1b,0xb0,0x12,0x5c,0x5c,0x7e,0x1b,0xb0,0x39,0xb1, +0x0, 0xa, 0xb, 0xa0,0xbe,0xa0,0xa, 0x40,0x93,0xda,0xf8,0x22,0xa, 0x3a,0x2d,0x3d, +0x7d,0x2c,0x22,0x7e,0x50,0x2, 0xac,0x5a,0x3e,0x24,0x22,0x7f,0x6, 0x2d,0x12,0x79, +0x40,0x0, 0x28,0x22,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x72,0x28,0xb2,0x22,0x7e,0x50, +0x2, 0xac,0x5a,0x7f,0x6, 0x2d,0x12,0x22,0xa, 0x3a,0x19,0xf3,0x1f,0x46,0x74,0x1, +0x19,0xb4,0x1f,0x50,0x22,0xe4,0x7a,0xb3,0x38,0x9d,0x7a,0xb3,0x38,0x9e,0x74,0xe, +0x7a,0xb3,0x38,0x9f,0x74,0x19,0x7a,0xb3,0x38,0xa0,0xe4,0x7a,0xb3,0x38,0xa1,0x74, +0xa, 0x7a,0xb3,0x38,0xa2,0xe4,0x7a,0xb3,0x38,0xa3,0x7a,0xb3,0x38,0xa4,0x74,0x1, +0x7a,0xb3,0x38,0xa6,0x74,0x25,0x7a,0xb3,0x38,0xaa,0x74,0x3e,0x7a,0xb3,0x38,0xab, +0x74,0x64,0x7a,0xb3,0x38,0xbc,0x74,0x4, 0x7a,0xb3,0x38,0xbd,0xe4,0x7a,0xb3,0x38, +0xa9,0x74,0x4f,0x7a,0xb3,0x38,0xbf,0x74,0x54,0x7a,0xb3,0x38,0xbe,0x74,0x3, 0x7a, +0xb3,0x38,0xc0,0x74,0x40,0x7a,0xb3,0x38,0xbb,0xe4,0x7a,0xb3,0x38,0xb6,0x74,0xfa, +0x7a,0xb3,0x38,0xb4,0x74,0x1e,0x7a,0xb3,0x38,0xb5,0x74,0x1, 0x7a,0xb3,0x38,0xb3, +0x74,0xb, 0x7a,0xb3,0x38,0xb2,0x74,0x1, 0x7a,0xb3,0x38,0xb7,0xe4,0x7a,0xb3,0x38, +0xb8,0x7a,0xb3,0x38,0xb9,0x7e,0x8, 0x38,0xc1,0x7e,0x34,0x0, 0x2c,0x12,0x20,0xe8, +0x74,0x1, 0x7a,0xb3,0x38,0xcc,0x74,0xf4,0x7a,0xb3,0x38,0xcd,0x74,0x19,0x7a,0xb3, +0x38,0xce,0x74,0x1e,0x7a,0xb3,0x38,0xcf,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x12,0x5d, +0xcc,0x7e,0x8, 0x38,0xdd,0x12,0x20,0xc3,0x1b,0xfd,0x74,0x5, 0x7a,0xb3,0x38,0xea, +0x74,0x1, 0x7a,0xb3,0x38,0xe1,0x7e,0x34,0x0, 0x28,0xca,0x39,0x7e,0x34,0x61,0xdb, +0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x26,0x33,0x12,0x20,0xc3,0x1b,0xfd,0x22,0x7e,0x34, +0x0, 0x4, 0xca,0x39,0x7e,0x34,0x61,0x2d,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x70, +0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x2a,0xe, 0x7a,0x37,0x2b,0x76,0xe4,0x7a,0xb3, +0x2b,0x74,0x7a,0xb3,0x2b,0x75,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x12,0x5d,0xcc,0x7e, +0x8, 0x25,0xee,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x2b,0x78,0x7a,0x37,0x25,0xf4, +0xe4,0x7a,0xb3,0x25,0xf2,0x74,0x1, 0x7a,0xb3,0x25,0xf3,0x22,0x7e,0x34,0x61,0x29, +0x7e,0x24,0x0, 0xff,0x22,0x7e,0x18,0x5, 0xf8,0x7a,0x1f,0x6, 0xf4,0x22,0x7e,0x34, +0x0, 0x96,0x7a,0x37,0x2a,0x5a,0x22,0xa, 0x4a,0x7f,0x10,0x2d,0x34,0x7a,0x1b,0xb0, +0x22,0xca,0xf8,0x7f,0x71,0x6d,0xdd,0x6c,0xaa,0x7e,0xf0,0x80,0xc2,0x0, 0x6d,0x44, +0x80,0x32,0x12,0x5e,0x92,0x12,0x5e,0xa3,0xbd,0x3d,0x48,0x26,0x12,0x5e,0x92,0xb, +0x1a,0x30,0xbe,0x34,0x0, 0x0, 0x8, 0x4, 0xd2,0x0, 0x80,0x9, 0x12,0x21,0xa, 0xbd, +0x3d,0x68,0x2, 0xc2,0x0, 0x7d,0x34,0x3e,0x34,0x2d,0x3f,0x7d,0x2e,0x12,0x5e,0xa3, +0x7d,0xd3,0xb, 0x44,0x7e,0xc5,0x34,0xbd,0xc4,0x38,0xc7,0x30,0x0, 0xc, 0x7e,0xf0, +0x7f,0x80,0x7, 0xb, 0xa0,0xbe,0xa0,0x8, 0x50,0x11,0x7c,0xba,0x7d,0x3d,0x60,0x5, +0xe, 0x34,0x14,0x78,0xfb,0xa, 0xcf,0xbd,0x3c,0x18,0xe8,0x7f,0x10,0x2e,0x35,0x34, +0x7a,0x1b,0xa0,0x6d,0x44,0x80,0x21,0x7d,0x54,0x3e,0x54,0x7f,0x17,0x2d,0x35,0xb, +0x1a,0x30,0x7f,0x60,0x2e,0xd5,0x34,0x7e,0x6b,0xb0,0x60,0x5, 0xe, 0x34,0x14,0x78, +0xfb,0x7c,0xb7,0x12,0x5d,0xe9,0xb, 0x44,0x7e,0x55,0x34,0xbd,0x54,0x38,0xd8,0xda, +0xf8,0x22,0x7d,0xc4,0x3e,0xc4,0x7f,0x17,0x2d,0x3c,0x22,0x74,0x2, 0xac,0xbe,0x7f, +0x17,0x2d,0x35,0xb, 0x1a,0x30,0x2, 0x21,0xa, 0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7f, +0x70,0xc2,0x0, 0x6c,0xdd,0x6d,0xdd,0x7e,0x34,0x23,0x5, 0x7e,0x24,0x0, 0xff,0x7e, +0x14,0x1f,0x7a,0x74,0xc, 0x12,0x1f,0xad,0x6d,0x11,0x7e,0x4, 0x7f,0xff,0x6c,0xee, +0x80,0x13,0x12,0x5e,0x9b,0x7d,0xc3,0xbd,0xdc,0x50,0x2, 0x7d,0xdc,0xbd,0xc, 0x28, +0x2, 0x7d,0xc, 0xb, 0xe0,0xbc,0xfe,0x38,0xe9,0xbe,0xd4,0x0, 0x1e,0x58,0xa, 0x7e, +0xb3,0x28,0x94,0x70,0x4, 0x6d,0x33,0xe1,0xa4,0xbe,0xd4,0x4, 0xb0,0x8, 0x2, 0xd2, +0x0, 0x6c,0xee,0x74,0x4, 0xac,0xbe,0x49,0x45,0x1f,0x7a,0xbd,0x4d,0x58,0x6, 0x49, +0xd5,0x1f,0x7c,0x80,0x7, 0xb, 0xe0,0xbe,0xe0,0x3, 0x40,0xe7,0xbe,0xe0,0x3, 0x78, +0x4, 0x6d,0x33,0x80,0x7f,0xbd,0xd, 0x8, 0x5, 0x30,0x0, 0x2, 0x7d,0xd0,0x9f,0x55, +0x6c,0xee,0x80,0xb, 0x12,0x5e,0x9b,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xe0,0xbc, +0xfe,0x38,0xf1,0xa, 0x1f,0x12,0x5f,0xb2,0x9f,0x55,0x6c,0xee,0x80,0x1d,0x12,0x5f, +0xa9,0xb, 0x1a,0x90,0x7d,0x39,0x12,0x21,0xa, 0x7d,0xc3,0xbd,0x1c,0x28,0xa, 0x7d, +0x39,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xd0,0xb, 0xe0,0xbc,0xfe,0x38,0xdf,0x6d, +0x11,0xbe,0xd0,0x0, 0x28,0x5, 0xa, 0x1d,0x12,0x5f,0xb2,0xbd,0x1d,0x8, 0x4, 0x7d, +0x1d,0x80,0xa, 0x6d,0x0, 0x9d,0xd, 0xbd,0x1, 0x8, 0x2, 0x7d,0x10,0x6c,0xee,0x80, +0xd, 0x12,0x5f,0xa9,0xb, 0x1a,0x0, 0x9d,0x1, 0x1b,0x1a,0x0, 0xb, 0xe0,0xbc,0xfe, +0x38,0xef,0x7d,0x31,0xda,0x79,0xda,0xd8,0x22,0x74,0x2, 0xac,0xbe,0x7f,0x17,0x2d, +0x35,0x22,0x6d,0x0, 0x7f,0x15,0x12,0x1f,0x58,0x7d,0x13,0x22,0x7e,0x8, 0x34,0xb7, +0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x20,0xe8,0x7e,0x34,0x0, 0x4, 0x7a,0x37,0x28,0xa1, +0x7a,0x37,0x28,0xa3,0x22,0x7f,0x60,0x7e,0xa3,0x2a,0x6d,0x7e,0xb3,0x2a,0x6e,0xa4, +0x7d,0xf5,0x3e,0xf4,0x7f,0x1, 0x7d,0x3f,0xe4,0x12,0x20,0xe8,0x7f,0x6, 0x7d,0x3f, +0x12,0x20,0xe8,0x7a,0xb3,0x16,0x91,0x22,0x7e,0xb3,0x2a,0x73,0xbc,0xba,0x22,0xff, +0x70,0x8f,0x0, 0xff,0x51,0xae,0x5a,0xa5,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x34,0x35,0x31,0x1, 0xc6,0x1, 0x34,0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0xa, 0xf5,0x43,0x36,0x5f,0x4f,0x66,0x69,0x6c,0x6d,0x5f,0x57,0x0, 0x0, 0x0, 0x0, +0xe, 0x19,0x3, 0x2, 0x7, 0x6, 0x5, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0x4, 0x1, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x11,0x4, 0x10,0x3, 0xf, 0x2, 0xe, 0x1, 0xd, 0x0, 0xc, +0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x0, 0x0, +0x0, 0x5, 0x0, 0x4, 0xff,0x23,0x1c,0x2, 0xdf,0xa, 0x1e,0xa, 0x64,0x14,0x10,0x0, +0x4, 0x0, 0x64,0xd, 0xac,0x0, 0xc8,0x3, 0x1, 0x0, 0x0, 0x18,0x2, 0x6, 0xb, 0x0, +0x0, 0x0, 0x96,0x0, 0xf0,0x1, 0xcc,0x2, 0x26,0x3, 0x48,0x3, 0xa2,0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc8,0x1, 0xf4,0x3, 0x20,0x0, 0x0, 0x0, 0x0, 0x7, +0xf8,0x0, 0x14,0x1, 0x19,0x1e,0x1, 0xf4,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x0, 0x4, 0x4f,0x20,0x1, 0x20,0x3, 0x0, 0x0, +0x0, 0x0, 0x1, 0xf4,0x54,0x40,0xe, 0x19,0x27,0x1c,0xf, 0x6, 0x60,0x1c,0xf, 0x6, +0x70,0x8, 0x10,0x4, 0x20,0x1, 0x0, 0x4, 0x38,0x44,0x44,0x2, 0x36,0x2, 0x4a,0x1, +0x39,0x1, 0x3b,0x7, 0x80,0x4a,0x4d,0x2, 0x57,0x2, 0x52,0x1, 0x44,0x1, 0x43,0x0, +0x96,0x0, 0x78,0x0, 0x96,0x0, 0xfa,0x0, 0x7d,0x0, 0xfa,0x0, 0xfa,0xa, 0x0, 0x0, +0xa8,0xa, 0x10,0x1e,0x32,0x1, 0xf, 0xb, 0x1e,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22,0x15, +0x0, 0x1, 0x54,0x1, 0x0, 0xa, 0x1, 0x51,0x1, 0x14,0x0, 0x5a,0x1, 0x1, 0xe, 0x0, +0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55,0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x96, +0x2, 0x26,0x0, 0x50,0x0, 0x2b,0x0, 0x4, 0x0, 0x4, 0x1, 0x4, 0x1, 0x90,0x0, 0xc8, +0x0, 0x50,0x1, 0xf4,0x0, 0x96,0x1, 0x2c,0x1, 0x2c,0x4, 0x1e,0x3, 0x4f,0x54,0x20, +0x22,0x3, 0x51,0x56,0x20,0x2c,0x3, 0x55,0x5c,0x20,0x36,0x2, 0x52,0x69,0x20,0x1e, +0x3, 0x4f,0x54,0x20,0x1e,0x3, 0x4f,0x54,0x20,0x1e,0x3, 0x4f,0x54,0x20,0x1e,0x3, +0x4f,0x54,0x20,0x4, 0x5, 0xf, 0x10,0x11,0x12,0x13,0x4, 0x0, 0xbb,0x4, 0xe2,0x2d, +0x0, 0xc8,0x1, 0x5e,0x0, 0x64,0x0, 0x64,0x0, 0x96,0x0, 0x64,0xb, 0xb8,0x8, 0x5, +0x6, 0x80,0x1, 0x90,0x1, 0x2c,0x1, 0xc2,0x3, 0x20,0xf, 0xa0,0x1, 0x3, 0x20,0x4, +0xb0,0x3, 0x20,0x1, 0x2, 0x2, 0x4, 0x4, 0x6, 0x40,0x0, 0xf0,0x0, 0xc8,0x1, 0x40, +0x1, 0x40,0x1, 0x2c,0x1, 0x18,0x0, 0xfa,0x1, 0x40,0x1, 0x40,0x1, 0x7c,0x0, 0x32, +0x0, 0x28,0x0, 0x78,0x0, 0x64,0x0, 0x64,0x0, 0x78,0x0, 0x78,0x14,0xa, 0x0, 0x50, +0x3, 0xe8,0x0, 0x50,0x7, 0x30,0x0, 0x14,0x1, 0xf4,0x1, 0xf4,0x3, 0x20,0x0, 0x64, +0x0, 0x4d,0x0, 0x1e,0x0, 0x80,0x1, 0xe, 0x0, 0xf0,0x0, 0x3c,0x3, 0xe8,0x1, 0xe0, +0x0, 0x87,0x0, 0x3c,0x3, 0xe8,0x0, 0x20,0x4, 0x18,0x0, 0x0, 0x7, 0x80,0x0, 0x64, +0x0, 0xa0,0x0, 0xa0,0x13,0x88,0x1, 0x2c,0x0, 0xa0,0x0, 0xa0,0x10,0x0, 0xc, 0x0, +0xb, 0xc, 0x5, 0x6, 0x8, 0x9, 0x6, 0x6, 0xc, 0x64,0xc8,0x6d,0x33,0x6c,0xaa,0x80, +0x14,0xa, 0x2a,0x9, 0xb2,0x2a,0xdc,0x54,0x1, 0x78,0x5, 0x4e,0x70,0x1, 0x80,0x3, +0x4e,0x70,0x10,0xb, 0xa0,0x7e,0x53,0x2a,0x74,0xbc,0x5a,0x38,0xe4,0x6c,0xaa,0x80, +0x1f,0xa, 0x2a,0x9, 0xb2,0x2a,0xb9,0xbe,0xb0,0xd, 0x38,0x5, 0x4e,0x70,0xc0,0x80, +0xd, 0xbe,0xb0,0x1b,0x38,0x5, 0x4e,0x60,0x8, 0x80,0x3, 0x4e,0x60,0x50,0xb, 0xa0, +0x12,0x5f,0xf8,0x38,0xdc,0x22,0x7e,0x54,0x0, 0x54,0x7e,0x44,0x0, 0xff,0x69,0x32, +0x0, 0x4, 0x69,0x22,0x0, 0x2, 0xb, 0x2a,0x10,0x7a,0x1d,0x26,0x7a,0x15,0x24,0x7e, +0x34,0x0, 0x20,0x7e,0x8, 0x0, 0x24,0x7e,0x24,0x0, 0x6, 0x12,0x63,0x62,0x74,0x25, +0x7a,0xb3,0x37,0xe2,0x74,0x1e,0x7a,0xb3,0x37,0xe3,0x74,0xf, 0x7a,0xb3,0x37,0xe4, +0x7a,0xb3,0x37,0xe5,0x7a,0xb3,0x37,0xe6,0x74,0xa0,0x7a,0xb3,0x37,0xe7,0x7e,0x34, +0x0, 0x59,0xca,0x39,0x7e,0x34,0x61,0x65,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x37,0xe8, +0x12,0x20,0xc3,0x1b,0xfd,0xe5,0x25,0x7a,0xb3,0x38,0x13,0xe5,0x28,0x7a,0xb3,0x38, +0x2, 0x22,0x7d,0x42,0x7f,0x60,0x7d,0x3, 0x12,0x64,0x60,0x74,0x2, 0x12,0x63,0x9c, +0x7d,0xf3,0x4e,0xf4,0x0, 0x1, 0x4e,0xf4,0x0, 0xa, 0x12,0x2f,0x54,0x7a,0x45,0x36, +0x7d,0x30,0x6d,0x22,0x7f,0x6, 0x12,0x64,0x2, 0x5e,0xf4,0xff,0xfd,0x12,0x2f,0x54, +0x2, 0x63,0x93,0xa9,0xc5,0xca,0xe4,0x7a,0xb3,0x3a,0x10,0x22,0x7c,0x6b,0x6c,0x77, +0x6c,0xaa,0x7e,0xb3,0x3a,0x10,0xb4,0xa5,0x46,0x12,0x64,0x8d,0x75,0xb5,0x5, 0xa9, +0x36,0xb3,0xfc,0x12,0x2f,0xa8,0xa9,0x36,0xb3,0xfc,0x12,0x2f,0xa8,0xa9,0x36,0xb3, +0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36,0xb3,0xfc,0x12,0x2f,0xa8,0xa9,0x36, +0xb3,0xfc,0x12,0x2f,0xa8,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7e,0x71,0xb5,0x75, +0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7e,0xa1,0xb5,0xa9,0xd2,0xb4,0x7c, +0x47,0x6c,0x55,0xa, 0x3a,0x4d,0x32,0x22,0x74,0x6, 0x12,0x63,0x9c,0x7d,0x3, 0x6c, +0x11,0x22,0x12,0x64,0x10,0x7e,0x35,0x36,0x12,0x64,0x94,0xa9,0xd2,0xb4,0xd3,0x22, +0x7d,0x52,0xf5,0x3a,0x7c,0xb6,0x7c,0xa5,0xa, 0x44,0xf5,0x39,0x7f,0x21,0xf5,0x38, +0xa9,0xc2,0xb4,0x74,0xb, 0x12,0x64,0x3b,0xe5,0x3a,0x12,0x64,0x3b,0xe5,0x39,0x12, +0x64,0x3b,0xe5,0x38,0x12,0x64,0x3b,0xe4,0x2, 0x64,0x3b,0xf5,0xb5,0xa9,0x36,0xb3, +0xfc,0xa9,0xc6,0xb3,0xd3,0x22,0xd2,0xc8,0x43,0xed,0xf, 0xc2,0xea,0x75,0xb3,0x13, +0xa9,0xd1,0xb4,0xa9,0xc0,0xb4,0x12,0x64,0x60,0xe4,0x12,0x64,0x70,0x2, 0x63,0x93, +0xa9,0xd5,0xca,0xa9,0xd1,0xea,0xa9,0xc1,0xea,0x74,0xa5,0x7a,0xb3,0x3a,0x10,0x22, +0xca,0xf8,0x7c,0xfb,0x74,0x2, 0x12,0x63,0x9c,0x4c,0xff,0x78,0x5, 0x5e,0x70,0xdf, +0x80,0x3, 0x4e,0x70,0x20,0x74,0x2, 0x12,0x2f,0x58,0xda,0xf8,0x22,0xa9,0xc2,0xb4, +0xa9,0xc6,0xb3,0x22,0x6d,0x22,0x80,0x13,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9, +0xc6,0xb3,0xe5,0xb5,0x7a,0xb, 0xb0,0xb, 0x14,0xb, 0x24,0xbd,0x32,0x38,0xe9,0x22, +0x7e,0x8, 0x26,0x5b,0x7e,0x34,0x2, 0x3a,0xe4,0x12,0x20,0xe8,0x7e,0x8, 0x26,0x8c, +0x7e,0x34,0x0, 0xc8,0x74,0xff,0x12,0x20,0xe8,0x7e,0x8, 0x26,0xb4,0x7e,0x34,0x0, +0xc8,0x12,0x20,0xe8,0x7e,0x8, 0x27,0x76,0x7e,0x34,0x1, 0xe, 0x2, 0x20,0xe8,0xca, +0xf8,0x7e,0x73,0x2a,0x78,0xa, 0x47,0x7e,0x73,0x2a,0x71,0xa, 0x57,0x2d,0x54,0x7e, +0xa3,0x2a,0x73,0xbc,0xab,0x28,0x2, 0x7c,0xba,0x7e,0xf3,0x2a,0x72,0x7e,0xa3,0x2a, +0x74,0xbc,0xaf,0x28,0x2, 0x7c,0xfa,0x75,0x25,0x15,0x7e,0x8, 0x2a,0xb9,0x7e,0x18, +0x2a,0x7a,0x12,0xd, 0xd9,0x75,0x25,0x15,0x7e,0x8, 0x2a,0xdc,0x7e,0x18,0x2a,0x9d, +0x7c,0xbf,0x12,0xf, 0x9c,0xda,0xf8,0x22,0x7a,0xb3,0x2b,0x0, 0x70,0xa, 0x7e,0x1f, +0x2b,0x74,0x7e,0xf, 0x2b,0x70,0x80,0xb, 0xb4,0x1, 0xb, 0x7e,0x1f,0x25,0xf2,0x7e, +0xf, 0x25,0xee,0x12,0x30,0x2f,0x22,0x7c,0xab,0x12,0x65,0x28,0x7c,0xba,0x12,0x13, +0xc7,0x2, 0x0, 0x1e,0x7f,0x70,0x7e,0x33,0x2a,0x74,0xa, 0x43,0x7e,0x33,0x2a,0x73, +0xa, 0x53,0x2d,0x54,0x3e,0x54,0x7c,0xab,0xe4,0x7a,0xb3,0x16,0x90,0x7f,0x1, 0xa, +0x3a,0x12,0x20,0xe8,0x7f,0x7, 0xa, 0x3a,0x2, 0x20,0xe8,0x7e,0xa3,0x2f,0xa8,0x7e, +0x70,0x4, 0xac,0x7a,0xb, 0x34,0xbe,0x37,0x38,0xee,0x40,0x39,0x7e,0x37,0x38,0xee, +0xb, 0x34,0x7a,0x37,0x38,0xee,0xbe,0x34,0x0, 0x1, 0x78,0x5, 0x7e,0xb3,0x38,0x35, +0x22,0xbe,0x34,0x0, 0x2, 0x78,0x3, 0x7c,0xba,0x22,0xbe,0x34,0x0, 0x2, 0x50,0x9, +0x7d,0x23,0x1b,0x25,0x9, 0xb2,0x39,0xfc,0x22,0x9e,0x34,0x0, 0x3, 0x2e,0x37,0x2b, +0xb9,0x7e,0x39,0xb0,0x22,0x74,0xff,0x22,0x70,0x5, 0x7e,0xb3,0x38,0x9d,0x22,0xbe, +0xb0,0x3, 0x38,0x15,0x75,0x1d,0x0, 0x30,0x12,0x6, 0x7e,0x18,0x35,0x93,0x80,0x4, +0x7e,0x18,0x35,0xd1,0x7a,0x1d,0x14,0x80,0x8, 0xbe,0xb0,0x5e,0x38,0x10,0x75,0x1d, +0x0, 0xa, 0x1b,0x7e,0x1d,0x14,0x2d,0x31,0x1b,0x34,0x7e,0x1b,0xb0,0x22,0xbe,0xb0, +0xd3,0x68,0x3, 0xb4,0xd4,0x10,0xb4,0xd3,0x8, 0x6d,0x33,0x7a,0x37,0x38,0xee,0x80, +0x2, 0x15,0x1a,0x2, 0x65,0x7b,0xbe,0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x3, 0x2, 0x66, +0xc6,0xbe,0xb0,0x80,0x40,0xc, 0xbe,0xb0,0xdf,0x38,0x7, 0xa, 0x3b,0x9, 0xb3,0x37, +0x62,0x22,0xb4,0xfc,0x5, 0x7e,0xb3,0x38,0x9, 0x22,0xb4,0xfd,0x17,0x6c,0xaa,0x7e, +0xb3,0x28,0xa8,0x60,0x3, 0x4e,0xa0,0x1, 0x7e,0xb3,0x37,0x71,0x60,0x3, 0x4e,0xa0, +0x2, 0x7c,0xba,0x22,0xb4,0xfe,0x5, 0x7e,0xb3,0x2b,0xf, 0x22,0x74,0xff,0x22,0x7c, +0x7b,0x6c,0xaa,0x12,0x66,0xbe,0x78,0x9, 0x7c,0xb7,0x12,0x65,0xc8,0x7c,0xab,0x80, +0xa, 0xb4,0x4, 0x7, 0x7c,0xb7,0x12,0x2a,0xc6,0x7c,0xab,0x7c,0xba,0x22,0x30,0x90, +0x19,0xc2,0x90,0xe5,0x18,0x70,0x9, 0x75,0x18,0x1, 0xe5,0x91,0xf5,0x1a,0x80,0x11, +0x7e,0x71,0x91,0xe5,0x1a,0x12,0x66,0xa9,0x5, 0x1a,0x30,0x91,0xb, 0xc2,0x91,0x5, +0x1a,0xe5,0x1a,0x12,0x66,0x5f,0xf5,0x91,0x22,0x7c,0x6b,0x12,0x66,0xbe,0x78,0x5, +0x7c,0xb6,0x2, 0x66,0xf8,0xb4,0x4, 0x5, 0x7c,0xb6,0x2, 0x37,0xe7,0x22,0x7e,0xb3, +0x38,0x9d,0xc4,0x54,0x7, 0x22,0xb4,0xeb,0x5, 0xe4,0x7a,0xb3,0x38,0xf3,0x7e,0x73, +0x38,0xf3,0xa, 0x27,0x2e,0x24,0x0, 0x6, 0x12,0x67,0x47,0x7c,0xab,0x7c,0xb7,0x4, +0x7a,0xb3,0x38,0xf3,0xb4,0x3, 0xb, 0xe4,0x7a,0xb3,0x38,0xf3,0x6d,0x33,0x7a,0x37, +0x38,0xf0,0x75,0x1a,0xeb,0x7c,0xba,0x22,0x7c,0xa7,0x7c,0x3b,0xa5,0xbb,0x0, 0x7, +0x7c,0xba,0x12,0x68,0x27,0x80,0x2c,0xbe,0x30,0xeb,0x68,0x4, 0xa5,0xbb,0xec,0x9, +0x7c,0xb3,0x7c,0x7a,0x12,0x68,0x71,0x80,0x1a,0xbe,0x30,0x80,0x40,0x15,0xbe,0x30, +0xdf,0x38,0x10,0x7c,0xb3,0x24,0x80,0x7c,0x7a,0x12,0x71,0x62,0xa5,0xbb,0x8f,0x3, +0x75,0x19,0x1, 0xa5,0xbb,0xfc,0x5, 0x7c,0xba,0x2, 0x2e,0xbd,0x74,0x1, 0x7a,0xb3, +0x3, 0xff,0x22,0x2e,0x24,0x20,0x7d,0x7a,0x51,0x82,0x7a,0x41,0x83,0xe4,0x93,0x22, +0x7c,0xab,0x6c,0x77,0xa, 0x27,0x2e,0x24,0x60,0xac,0x12,0x67,0x47,0xbc,0xba,0x78, +0x2, 0xd3,0x22,0xb, 0x70,0xbe,0x70,0x3, 0x40,0xea,0xc3,0x22,0x6c,0x33,0x80,0x1f, +0x7c,0xb3,0x12,0x67,0x50,0x40,0x16,0x7c,0xb3,0x12,0x67,0x98,0x7d,0x43,0x6d,0x55, +0x7d,0x4, 0x3e,0x4, 0x7e,0x1f,0x13,0x8a,0x2d,0x30,0x1b,0x1a,0x50,0xb, 0x30,0x7e, +0x23,0x2a,0x75,0xbc,0x23,0x38,0xd9,0x22,0x7e,0x73,0x2a,0x6e,0xac,0x7b,0x2e,0x34, +0x0, 0x18,0x22,0x6c,0x33,0x6c,0x22,0x80,0x28,0x7c,0xb2,0x12,0x67,0x50,0x50,0x1f, +0x7c,0xb2,0x12,0x67,0x98,0x3e,0x34,0x7e,0x7f,0x13,0x8a,0x2d,0xf3,0xb, 0x7a,0x30, +0x12,0x67,0xda,0x59,0x35,0x39,0xe9,0x30,0x0, 0x5, 0x6d,0x33,0x1b,0x7a,0x30,0xb, +0x20,0x7e,0x73,0x2a,0x75,0xbc,0x72,0x38,0xd0,0x22,0x7c,0xa3,0xb, 0x30,0x74,0x2, +0xa4,0x22,0x7c,0xab,0x7c,0xb7,0xb4,0x18,0x9, 0x7c,0xba,0x12,0x67,0x50,0x50,0x2, +0xd3,0x22,0xc3,0x22,0x7e,0xa3,0x38,0x9c,0x7c,0xba,0x4, 0x7a,0xb3,0x38,0x9c,0x7a, +0xa3,0x37,0xf3,0x22,0xca,0x7b,0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0x83,0xc0,0x82, +0x12,0x66,0x7e,0xd0,0x82,0xd0,0x83,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x7b,0x32, +0xa9,0xc0,0x93,0x75,0x18,0x0, 0x32,0x7a,0xb3,0x38,0x9d,0xc4,0x54,0x7, 0xbe,0xb0, +0x4, 0x68,0x3, 0xb4,0x2, 0x4, 0x74,0x3, 0x80,0x7, 0x60,0x3, 0xb4,0x1, 0x7, 0x74, +0x1, 0x7a,0xb3,0x38,0x9, 0x22,0x74,0x1, 0x7a,0xb3,0x38,0x9, 0xe4,0x7a,0xb3,0x38, +0x9d,0x22,0x7e,0xb3,0x38,0xf2,0x4, 0x7a,0xb3,0x38,0xf2,0xe5,0x19,0xb4,0x1, 0x8, +0xe4,0x7a,0xb3,0x38,0xf2,0x75,0x19,0x0, 0x7e,0x73,0x38,0xf2,0x7a,0x73,0x37,0xf1, +0x22,0xbe,0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x33,0x7e,0x27,0x38,0xf0,0x4d,0x22,0x78, +0xe, 0xa5,0xbf,0xaa,0xa, 0x7e,0x24,0x0, 0x1, 0x7a,0x27,0x38,0xf0,0x15,0x1a,0x7e, +0x27,0x38,0xf0,0xbe,0x24,0x0, 0x1, 0x78,0x10,0xa5,0xbf,0x9, 0x6, 0x7e,0x34,0x0, +0x2, 0x80,0x2, 0x6d,0x33,0x7a,0x37,0x38,0xf0,0x75,0x1a,0xea,0x22,0xe4,0x7a,0xb3, +0x38,0x9d,0x7e,0x8, 0x35,0x93,0x12,0x68,0xfc,0x7e,0x8, 0x35,0xd1,0x7e,0x34,0x0, +0x3e,0x12,0x20,0xe8,0x7e,0x18,0x35,0x93,0x7a,0x1d,0x14,0x12,0x68,0xde,0x2, 0x68, +0xd1,0x75,0x18,0x0, 0x75,0x1a,0x0, 0x7e,0xb3,0x38,0x9d,0xf5,0x91,0x22,0x2, 0x68, +0xe1,0x90,0x60,0x0, 0xe4,0x93,0x54,0xfe,0x75,0x91,0x0, 0xc2,0x90,0xc2,0x91,0xc2, +0xc9,0x54,0xfe,0xf5,0x92,0xd2,0xe8,0xc2,0xc0,0xd2,0xad,0x22,0x7e,0x34,0x0, 0x3e, +0x74,0xff,0x2, 0x20,0xe8,0x30,0x1d,0x8, 0x74,0x5, 0x7e,0x70,0x99,0x12,0x13,0x2c, +0x7e,0xb3,0x34,0x3a,0xb4,0x1, 0x4f,0x12,0x69,0x67,0x49,0x35,0x34,0x3b,0x49,0x15, +0x34,0x3d,0x6d,0x0, 0xbe,0x8, 0x0, 0x0, 0x68,0x1a,0xbe,0x70,0x0, 0x40,0x15,0xbe, +0x70,0x2, 0x38,0x10,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0x73,0x7e,0x73,0x2a, +0x74,0x12,0x10,0xee,0x7e,0xb3,0x34,0x39,0x4, 0x7a,0xb3,0x34,0x39,0x12,0x69,0x6f, +0x28,0xe, 0x12,0x3f,0xd2,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x6, 0x74,0x3, 0x80,0x2, +0x74,0x2, 0x7a,0xb3,0x34,0x3a,0x22,0x7e,0xa3,0x34,0x39,0x74,0x4, 0xa4,0x22,0x7e, +0x73,0x34,0x38,0xbe,0x73,0x34,0x39,0x22,0x7e,0xb3,0x34,0x3a,0xb4,0x1, 0x2, 0xc3, +0x22,0xd3,0x22,0x7e,0xb3,0x2b,0x1e,0x70,0x1f,0x12,0x2f,0xe7,0x12,0x69,0x78,0x50, +0xfb,0x12,0x69,0xa9,0x12,0x6a,0xb8,0x20,0x13,0x3, 0x12,0x55,0xae,0x74,0x2, 0x7a, +0xb3,0x2b,0x1e,0xe4,0x7a,0xb3,0x16,0x91,0x22,0x7e,0xf, 0x13,0x8a,0x7e,0x18,0x8, +0xa, 0xca,0x3b,0x7a,0x1d,0x29,0x7f,0x30,0x12,0x57,0xe5,0xa4,0x7a,0x55,0x31,0x7e, +0xb3,0x2b,0x1d,0xf5,0x2e,0xe4,0x7a,0xb3,0x2b,0x1d,0x7f,0x3, 0x7e,0x1d,0x29,0x12, +0x5f,0xd5,0x12,0xc6,0xa3,0x12,0x3f,0xeb,0x75,0x2d,0x0, 0x12,0x3f,0xa5,0x30,0xf, +0xfd,0x74,0x1, 0x12,0x6a,0x73,0x7e,0x14,0x40,0x0, 0x7d,0x21,0x7d,0x7, 0x12,0x56, +0x2d,0x12,0x6a,0x2e,0x6d,0x33,0x80,0x19,0x7e,0x35,0x2f,0x3e,0x34,0x7f,0x3, 0x2d, +0x13,0xb, 0xa, 0x20,0x7e,0xd, 0x29,0x2d,0x13,0x12,0xc6,0xbf,0x7e,0x35,0x2f,0xb, +0x34,0x7a,0x35,0x2f,0x7e,0x35,0x31,0xbe,0x35,0x2f,0x38,0xdc,0x5, 0x2d,0xe5,0x2d, +0xbe,0xb0,0x1, 0x40,0xb6,0xe5,0x2e,0x7a,0xb3,0x2b,0x1d,0xda,0x3b,0x22,0x7e,0xa3, +0x2a,0x6e,0xa, 0x3a,0x3e,0x34,0x7e,0x8, 0x13,0x8e,0xe4,0x12,0x20,0xe8,0x7e,0xb3, +0x2a,0x71,0x12,0xb9,0x19,0x7d,0x43,0x6c,0x77,0x80,0x1d,0xa, 0x27,0x2d,0x24,0x12, +0x4f,0xe5,0xb, 0xa, 0x0, 0x7e,0x30,0x2, 0xac,0x37,0x2e,0x14,0x13,0x8e,0xb, 0x18, +0x20,0x2d,0x20,0x1b,0x18,0x20,0xb, 0x70,0xbc,0xa7,0x38,0xdf,0x22,0x12,0x69,0x78, +0x50,0xfb,0x22,0x12,0x0, 0xe, 0x7e,0x1f,0x13,0x86,0x22,0x7e,0x8, 0x24,0xf2,0x7e, +0x34,0x0, 0xc, 0xe4,0x12,0x20,0xe8,0x12,0xa4,0x5f,0x12,0xa4,0x56,0xa9,0xd1,0xcb, +0x12,0x6a,0x73,0x7a,0x37,0x24,0xf6,0x7e,0x1f,0x39,0xda,0x7a,0x37,0x24,0xf8,0x7e, +0x1f,0x13,0x86,0x7a,0x37,0x24,0xfa,0x6d,0x33,0x12,0xb9,0x10,0x2, 0xd, 0x7, 0x12, +0xa5,0xef,0x12,0x6a,0x7b,0x2, 0x6a,0xb8,0x12,0x57,0x8e,0x50,0x3, 0xd2,0x13,0x22, +0xc2,0x13,0x22,0x12,0x75,0xd2,0x12,0x6b,0x17,0x12,0xad,0xc9,0x12,0x6c,0x68,0x7e, +0xb3,0x38,0x7, 0xb4,0x1, 0x7, 0x7e,0x34,0x0, 0x14,0x12,0x5f,0xcc,0x7e,0xb3,0x3a, +0xe, 0x60,0x7, 0x14,0x7a,0xb3,0x3a,0xe, 0x80,0x6, 0x7e,0xb3,0x28,0xac,0x60,0xc, +0x12,0x6a,0xaf,0x12,0x57,0x9f,0x12,0xb5,0xf1,0x12,0x9e,0x4f,0x7e,0xb3,0x34,0xb6, +0x60,0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x7e,0xb3,0x28,0xad,0x60,0x9, 0x12,0xbb,0x95, +0x12,0xa4,0x68,0x2, 0xaa,0x3c,0x22,0x7e,0x90,0x1, 0x12,0x5f,0xc8,0x7e,0xf4,0x0, +0x96,0xe4,0x7a,0xb3,0x28,0xac,0x12,0x6c,0x48,0x7e,0x34,0xfe,0x89,0x7e,0x27,0x7, +0xfe,0xbe,0x24,0xfd,0x12,0x58,0x1c,0x7e,0xe7,0x7, 0xfc,0xbd,0xe3,0x58,0x14,0x6d, +0xee,0x9e,0xe7,0x2a,0x5a,0xbe,0xe7,0x28,0x8e,0x8, 0x8, 0x12,0xac,0x93,0x60,0x3, +0x12,0xa6,0x2e,0x12,0xa6,0x3d,0x40,0x5, 0xe4,0x7a,0xb3,0x28,0xa8,0x12,0xc7,0x1, +0x68,0x6, 0x7e,0xb3,0x3a,0xc, 0x60,0x7, 0xe4,0x7a,0xb3,0x28,0xad,0x80,0x65,0x12, +0x6c,0x4f,0x28,0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x30,0x14,0x5, 0xe4,0x7a,0xb3,0x28, +0xad,0x12,0xa6,0x7b,0x50,0xa, 0x12,0x6c,0x48,0x12,0x6c,0x85,0x7c,0x9b,0x80,0x17, +0x7e,0xb3,0x26,0x84,0x70,0x11,0x7e,0xb3,0x26,0x85,0x70,0xb, 0x12,0x6c,0x4f,0x28, +0x6, 0x7e,0x90,0x3, 0x12,0x6c,0x48,0x7e,0xe7,0x7, 0xfa,0xbe,0xe4,0x5, 0xdc,0x8, +0x17,0x12,0x6c,0x4f,0x28,0x12,0x6d,0xee,0x9d,0xef,0xbe,0xe7,0x28,0x8e,0x58,0x8, +0x12,0x6c,0x5a,0xe4,0x7a,0xb3,0x28,0xad,0x74,0x4, 0xac,0xb9,0x7a,0x57,0x28,0xa1, +0x7a,0x57,0x28,0xa3,0x12,0x6c,0x57,0x50,0xd, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0x76, +0xe0,0x28,0x3, 0x12,0x6c,0x5a,0x7e,0xe7,0x28,0x8a,0xbd,0xef,0x8, 0x1f,0x7e,0x24, +0x0, 0x2, 0x7d,0x3f,0x12,0x1e,0xb9,0x6e,0x34,0xff,0xff,0xb, 0x34,0xbe,0x37,0x28, +0x8e,0x58,0xa, 0x12,0x6c,0x57,0x50,0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0x6c,0xe8, +0xb4,0x1, 0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0xa5,0x95,0x7e,0xb3,0x2f,0xa9,0xbe, +0xb0,0x0, 0x28,0x23,0x14,0x7a,0xb3,0x2f,0xa9,0x70,0x1c,0xe4,0x7a,0xb3,0x28,0xad, +0x74,0x1, 0x7a,0xb3,0x28,0xac,0xe4,0x7a,0xb3,0x16,0x91,0x7a,0xb3,0x16,0x90,0x7a, +0xb3,0x28,0x84,0x7a,0xb3,0x26,0x83,0x22,0x74,0x1, 0x7a,0xb3,0x28,0xad,0x22,0x7e, +0x83,0x28,0x84,0xbe,0x80,0x0, 0x22,0xa2,0x17,0x22,0xe4,0x7a,0xb3,0x2f,0xa9,0x7a, +0xb3,0x28,0xac,0x74,0x2, 0x2, 0x26,0x12,0x12,0xab,0xcd,0x60,0x17,0x12,0x6c,0x48, +0x7e,0x37,0x28,0xa1,0x3e,0x34,0x7a,0x37,0x28,0xa1,0x7e,0x37,0x28,0xa3,0x3e,0x34, +0x7a,0x37,0x28,0xa3,0x22,0x7e,0xa0,0x1, 0x7e,0x47,0x7, 0xf8,0x7e,0x4, 0x0, 0xfa, +0xbe,0x44,0xfd,0x12,0x58,0x12,0x7e,0xb3,0x28,0xac,0x60,0x7, 0xe4,0x7a,0xb3,0x28, +0xad,0x80,0x38,0x7e,0xa0,0x5, 0x80,0x33,0x7e,0x34,0xff,0xfb,0xad,0x30,0x7e,0x14, +0x0, 0x2, 0x12,0x6c,0xe0,0x8, 0x5, 0x7e,0xa0,0x4, 0x80,0x1f,0x7e,0x34,0xff,0xfc, +0x12,0x6c,0xde,0x8, 0x5, 0x7e,0xa0,0x3, 0x80,0x11,0x7e,0x34,0xff,0xfd,0x12,0x6c, +0xde,0x8, 0x5, 0x7e,0xa0,0x2, 0x80,0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0xad,0x30, +0x7d,0x21,0x12,0x1e,0xb9,0xbd,0x34,0x22,0xca,0x3b,0x12,0x9a,0xbf,0x38,0x2, 0xa1, +0xab,0x7e,0xc3,0x2f,0xac,0x4c,0xcc,0x78,0x3d,0x7a,0xb3,0x2f,0xac,0xe4,0x7a,0xb3, +0x2f,0xae,0x6c,0xaa,0x80,0x26,0x12,0x6d,0xb6,0x7e,0x70,0x2, 0xac,0x7a,0x9, 0xd3, +0x26,0xfa,0x9, 0xe3,0x26,0xfb,0x7a,0x49,0xd0,0x19,0xe4,0x0, 0x1, 0x74,0x1, 0x19, +0xb4,0x0, 0x8, 0x12,0x6d,0xc0,0x59,0x34,0x0, 0x2, 0xb, 0xa0,0x7e,0xb3,0x28,0x84, +0xbc,0xba,0x38,0xd2,0x80,0x7b,0x7c,0xfc,0x6c,0xaa,0x80,0x31,0x12,0x6d,0xb6,0x7e, +0x49,0xd0,0x9, 0xe4,0x0, 0x1, 0x9, 0xb4,0x0, 0x8, 0x70,0x4, 0x1b,0xf0,0x80,0x1b, +0x12,0x6d,0xc0,0x7d,0x23,0x49,0x34,0x0, 0x2, 0x12,0xa1,0xb6,0xbe,0xf4,0x0, 0x23, +0x8, 0x9, 0x74,0x5, 0x19,0xb4,0x0, 0x8, 0x75,0x5c,0x1, 0xb, 0xa0,0xbc,0xfa,0x38, +0xcb,0x4c,0xff,0x78,0x2, 0x80,0x26,0x7e,0x73,0x2f,0xae,0xbe,0x70,0x4, 0x40,0x22, +0x6c,0xaa,0x80,0xe, 0x12,0x6d,0xb6,0x9, 0xb4,0x0, 0x8, 0xbe,0xb0,0x5, 0x68,0x6, +0xb, 0xa0,0xbc,0xfa,0x38,0xee,0xbc,0xfa,0x78,0x3, 0x75,0x5c,0x0, 0x12,0x6f,0x5d, +0x80,0xf, 0x7c,0xb7,0x4, 0x7a,0xb3,0x2f,0xae,0x80,0x6, 0x12,0x6f,0x5d,0x75,0x5c, +0x0, 0xe5,0x5c,0xda,0x3b,0x22,0x7e,0x90,0x9, 0xac,0x9a,0x2e,0x44,0x2f,0xaf,0x22, +0x7c,0xbd,0x7c,0x7e,0x2, 0x6d,0xcb,0x7c,0xba,0x7c,0x79,0x12,0x6f,0x81,0xb, 0x1a, +0x30,0x22,0x7c,0xbd,0x7c,0x7e,0x7f,0x4, 0xca,0x3b,0x7f,0x70,0x7c,0xe7,0x7c,0xdb, +0x7e,0xc0,0x4, 0x7e,0xb3,0x2a,0x6d,0xf5,0x26,0x7e,0xb3,0x2a,0x6e,0xf5,0x25,0x7e, +0xd4,0x0, 0xc8,0x6c,0xff,0x12,0x6f,0x7d,0xe5,0x26,0xa, 0x1b,0x1b,0x14,0xa, 0xcd, +0xbd,0xc1,0x58,0x14,0xe5,0x25,0xa, 0x1b,0x1b,0x14,0xa, 0xce,0xbd,0xc1,0x58,0x8, +0x4c,0xee,0x68,0x4, 0x4c,0xdd,0x78,0x3, 0x4e,0xf0,0x10,0xb, 0x1a,0xc0,0xbe,0xc4, +0x0, 0xc8,0x8, 0xc, 0x7e,0x17,0x28,0x8a,0xbe,0x14,0x3, 0x20,0x8, 0x2, 0xe1,0x1c, +0xbe,0xc4,0x0, 0x64,0x8, 0xc, 0x7e,0xc7,0x28,0x8a,0xbe,0xc4,0x3, 0x20,0x58,0x2, +0xe1,0x1c,0x6c,0xaa,0x7c,0x8d,0x80,0x1c,0x7c,0x9e,0xbe,0x80,0x0, 0x48,0x11,0x7e, +0xb3,0x2a,0x6d,0xbc,0xb8,0x8, 0x9, 0x12,0x6f,0x53,0x58,0x14,0xb, 0xa0,0x80,0x2, +0xb, 0xa0,0x1b,0x80,0x1a,0x2c,0x1a,0x3d,0x9d,0x32,0x1a,0xc8,0xbd,0xc3,0x18,0xd8, +0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x1, 0xe1,0x1c,0x6c,0xaa,0x7c,0x8d,0x80,0x1c,0x7c, +0x9e,0xbe,0x80,0x0, 0x48,0x11,0x7e,0xb3,0x2a,0x6d,0xbc,0xb8,0x8, 0x9, 0x12,0x6f, +0x53,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0xb, 0x80,0x1a,0x2c,0x1a,0x3d,0x2d, +0x32,0x1a,0xc8,0xbd,0xc3,0x48,0xd8,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x2, 0x80,0x6c, +0x6c,0xaa,0x7c,0x9e,0x80,0x1c,0x7c,0x8d,0xbe,0x90,0x0, 0x48,0x11,0x7e,0xb3,0x2a, +0x6e,0xbc,0xb9,0x8, 0x9, 0x12,0x6f,0x53,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0, +0x1b,0x90,0x1a,0x2c,0x1a,0x3e,0x9d,0x32,0x1a,0xc9,0xbd,0xc3,0x18,0xd8,0xbc,0xca, +0x18,0x5, 0x4e,0xf0,0x4, 0x80,0x35,0x6c,0xaa,0x7c,0x9e,0x80,0x1c,0x7c,0x8d,0xbe, +0x90,0x0, 0x48,0x11,0x7e,0xb3,0x2a,0x6e,0xbc,0xb9,0x8, 0x9, 0x12,0x6f,0x53,0x58, +0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0xb, 0x90,0x1a,0x2c,0x1a,0x3e,0x2d,0x32,0x1a, +0xc9,0xbd,0xc3,0x48,0xd8,0xbc,0xca,0x18,0x3, 0x4e,0xf0,0x8, 0x4c,0xff,0x68,0x2e, +0x7e,0x7b,0xb0,0xbc,0xbd,0x40,0x3, 0x7a,0x7b,0xd0,0x29,0xb7,0x0, 0x2, 0xbc,0xbd, +0x38,0x4, 0x39,0xd7,0x0, 0x2, 0x29,0xb7,0x0, 0x1, 0xbc,0xbe,0x40,0x4, 0x39,0xe7, +0x0, 0x1, 0x29,0xb7,0x0, 0x3, 0xbc,0xbe,0x38,0x4, 0x39,0xe7,0x0, 0x3, 0x7c,0xbf, +0xda,0x3b,0x22,0x7c,0xb8,0x7c,0x79,0x12,0x6d,0xcb,0xbd,0x3d,0x22,0xe4,0x7a,0xb3, +0x2f,0xad,0x7a,0xb3,0x2f,0xac,0x7a,0xb3,0x2f,0xae,0x22,0x7c,0xab,0x7e,0x70,0x2, +0xac,0x7a,0x9, 0xb3,0x26,0xfa,0x9, 0x73,0x26,0xfb,0x2, 0x6d,0xcb,0x7c,0xbd,0x7c, +0x7e,0x7e,0x13,0x2a,0x6e,0xac,0x1b,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x37,0x2d,0x10, +0x7e,0x1f,0x13,0x8a,0x2d,0x31,0x22,0xca,0x79,0x6c,0xff,0x7e,0xd7,0x2a,0x5a,0x6c, +0xee,0x80,0x3e,0x12,0x7f,0xfc,0x50,0x4, 0x7e,0xd7,0x2a,0x5c,0x7c,0xbe,0x12,0x6f, +0x6b,0xbd,0x3d,0x48,0x2a,0x7c,0xbe,0x12,0x88,0x65,0x60,0x23,0x7e,0xc4,0x0, 0x9, +0xca,0xc9,0x7e,0x70,0x9, 0xac,0x7e,0x2e,0x34,0x27,0x76,0x6d,0x22,0x7e,0x30,0x9, +0xac,0x3f,0x2e,0x14,0x28,0xae,0x6d,0x0, 0x12,0x20,0xc3,0x1b,0xfd,0xb, 0xf0,0xb, +0xe0,0x12,0x97,0xbe,0x38,0xbd,0x7a,0x73,0x28,0x93,0x7a,0xf3,0x2a,0x2, 0xda,0x79, +0x22,0x2, 0x6f,0x97,0x7e,0x70,0x18,0x2, 0x6d,0xcb,0x7d,0xf3,0x6d,0xee,0x6c,0x99, +0x80,0x3c,0x7c,0xb9,0x12,0x67,0x98,0x7d,0xd3,0x7d,0xcd,0x3e,0xc4,0x7f,0x57,0x2d, +0xbc,0xb, 0x5a,0x10,0x1a,0x2, 0x1a,0x0, 0x7e,0x83,0x2b,0x20,0xa, 0x98,0x6d,0x88, +0x7f,0x10,0x7f,0x4, 0x12,0x1e,0xeb,0x74,0x6, 0x7f,0x1, 0x1e,0x14,0x1e,0x4, 0x50, +0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0xc1,0x1b,0x5a,0xc0,0xb, 0x90,0x7e,0x83, +0x2a,0x75,0xbc,0x89,0x38,0xbc,0x22,0xca,0x79,0x7c,0x5b,0x7e,0x43,0x28,0x84,0xbe, +0x40,0x1, 0x28,0x2, 0x21,0x56,0x7e,0xa3,0x2a,0x6e,0x7e,0x70,0x2, 0xac,0x75,0x9, +0xf3,0x26,0xfa,0x9, 0xe3,0x26,0xfb,0x7c,0xbf,0x7c,0x7e,0x12,0x6f,0x81,0x7f,0x51, +0x7c,0x1e,0x7c,0x3f,0x7e,0x3, 0x2a,0x70,0x7e,0x23,0x2a,0x6f,0xa, 0x3a,0x6d,0xdd, +0x9d,0xd3,0xa, 0x9a,0xa, 0xc0,0x1b,0xc5,0xa, 0x51,0xbd,0x5c,0x58,0x2, 0x21,0x56, +0xa, 0x53,0x1b,0x54,0xbe,0x54,0x0, 0x0, 0x48,0x55,0x7c,0xb3,0x14,0x12,0x67,0x50, +0x50,0x4d,0x7c,0xb3,0x14,0x12,0x67,0x98,0x7d,0xe3,0x7d,0x5e,0x12,0x71,0x59,0xb, +0x1a,0xf0,0x7d,0x5d,0x3e,0x54,0x7f,0x15,0x2d,0x35,0xb, 0x1a,0x80,0xbe,0xf4,0x0, +0x0, 0x8, 0x11,0x9d,0x8f,0xbe,0x84,0x0, 0x0, 0x58,0x4, 0x6d,0x55,0x80,0x2, 0x7d, +0x58,0x1b,0x1a,0x50,0x7c,0xb0,0x24,0xfe,0xbc,0xb1,0x78,0x13,0x7d,0x4e,0x1b,0x44, +0x7d,0x54,0x12,0x71,0x59,0xb, 0x1a,0x50,0xbd,0x58,0x8, 0x3, 0x1b,0x1a,0x80,0xa, +0x83,0xb, 0x84,0xa, 0x52,0xbd,0x85,0x58,0x5d,0x7c,0xb3,0x4, 0x12,0x67,0x50,0x50, +0x55,0x7c,0xb3,0x4, 0x12,0x67,0x98,0x7d,0xe3,0x7d,0x1e,0x3e,0x14,0x7e,0x1f,0x13, +0x8a,0x7f,0x61,0x2d,0xd1,0xb, 0x6a,0xf0,0x7d,0x19,0x3e,0x14,0x7f,0x65,0x2d,0xd1, +0xb, 0x6a,0x10,0xbe,0xf4,0x0, 0x0, 0x8, 0x11,0x9d,0x1f,0xbe,0x14,0x0, 0x0, 0x58, +0x4, 0x6d,0x55,0x80,0x2, 0x7d,0x51,0x1b,0x6a,0x50,0x7c,0xb0,0x24,0xfe,0xbc,0xb1, +0x78,0x14,0x7d,0x4e,0x1b,0x44,0x7d,0x4, 0x3e,0x4, 0x2d,0x30,0xb, 0x1a,0x0, 0xbd, +0x1, 0x8, 0x3, 0x1b,0x1a,0x10,0xda,0x79,0x22,0x3e,0x54,0x7e,0x1f,0x13,0x8a,0x2d, +0x35,0x22,0x7c,0x6b,0x2e,0x60,0xdd,0x68,0x26,0x2e,0x60,0xfd,0x68,0x21,0x1b,0x61, +0x68,0x1d,0x1b,0x62,0x68,0x19,0x1b,0x61,0x68,0x15,0x1b,0x60,0x68,0x11,0x2e,0x60, +0xa, 0x78,0x4, 0x7a,0x73,0x37,0xe1,0xa, 0x2b,0x19,0x72,0x37,0xe2,0xd2,0x11,0x22, +0xca,0x79,0x6c,0xaa,0x6c,0xee,0x6d,0xdd,0x7e,0xe4,0x7f,0xff,0x7e,0xf0,0x1, 0x80, +0x28,0xa, 0xff,0x7e,0xb3,0x2a,0x6e,0xa, 0xcb,0x2d,0xcf,0x3e,0xc4,0x49,0xfc,0x4, +0xfc,0xbe,0xf4,0x1, 0xf4,0x8, 0x10,0xb, 0xa0,0xbd,0xfd,0x8, 0x4, 0x7d,0xdf,0x80, +0x6, 0xbd,0xfe,0x58,0x2, 0x7d,0xef,0xb, 0xf0,0x7e,0xb3,0x2a,0x6f,0xa, 0xcb,0x1b, +0xc4,0xa, 0xff,0xbd,0xfc,0x48,0xca,0x74,0x2, 0x12,0x6f,0xf4,0x7d,0xf3,0x74,0x6, +0x12,0x6f,0xf4,0x7d,0x43,0x74,0xb, 0x12,0x6f,0xf4,0xbe,0xa0,0xc, 0x78,0x1f,0x7d, +0x2d,0x9d,0x2e,0xbe,0x24,0x7, 0xd0,0x58,0x15,0xbe,0xf4,0x0, 0x50,0x8, 0xf, 0xbe, +0x44,0x0, 0x64,0x8, 0x9, 0xbe,0x34,0x0, 0x50,0x8, 0x3, 0x7e,0xe0,0x1, 0x7e,0xb3, +0x37,0xee,0xb4,0x1, 0xc, 0x74,0xc, 0x6c,0x77,0x12,0x71,0x62,0x6c,0xee,0x12,0x72, +0xfd,0xbe,0xe0,0x1, 0x78,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x7a,0xb3,0x34,0xb6,0xb4, +0x1, 0x34,0x7e,0xb3,0x34,0xc5,0xbe,0xb0,0x8, 0x50,0x1a,0x4, 0x7a,0xb3,0x34,0xc5, +0x7e,0x73,0x34,0xc5,0xbe,0x70,0x3, 0x28,0xc, 0x74,0x8, 0x7a,0xb3,0x34,0xc5,0x74, +0x1, 0x7a,0xb3,0x34,0x8b,0x7e,0x73,0x34,0xc5,0xbe,0x70,0x8, 0x40,0x8, 0x12,0x72, +0xc2,0x60,0x3, 0x12,0x73,0x12,0x7e,0x73,0x34,0xb6,0xbe,0x70,0x0, 0x38,0x5, 0x12, +0x72,0xc2,0x70,0x39,0x6c,0xff,0x80,0x30,0x7c,0xbf,0x12,0x8b,0xef,0x60,0x23,0x7e, +0xb3,0x34,0xda,0x4, 0x12,0x73,0x26,0x7e,0x73,0x34,0xda,0xbe,0x70,0x5, 0x40,0x16, +0x12,0x72,0xfd,0xe4,0x7a,0xb3,0x34,0xda,0x7a,0xb3,0x34,0xc5,0x7a,0xb3,0x34,0x8b, +0x80,0x4, 0xe4,0x12,0x73,0x26,0xb, 0xf0,0x12,0x73,0x6d,0x38,0xcb,0x12,0x72,0xc2, +0x70,0xc, 0x12,0x76,0xe0,0x28,0x4, 0x74,0x5, 0x80,0x4, 0xe4,0x80,0x1, 0xe4,0xda, +0x79,0x22,0x7e,0xb3,0x38,0x32,0xb4,0x1, 0x3, 0x74,0x1, 0x22,0x7e,0x34,0xd7,0x0, +0x12,0x72,0xf5,0x70,0x1b,0x7e,0x34,0xd7,0x1, 0x12,0x72,0xf5,0x70,0x12,0x7e,0x34, +0xd7,0x2, 0x12,0x72,0xf5,0x70,0x9, 0x7e,0x34,0xd7,0x3, 0x12,0x72,0xf5,0x60,0x2, +0xe4,0x22,0x74,0x1, 0x22,0x7e,0x24,0x0, 0xff,0x7e,0x1b,0xb0,0x22,0xe4,0x12,0x77, +0x11,0x12,0x77,0x9, 0x12,0x77,0x1, 0x2, 0x73,0xa, 0x7e,0x34,0xd7,0x3, 0x7a,0x1b, +0xb0,0x22,0x74,0x55,0x12,0x77,0x11,0x74,0xaa,0x12,0x77,0x9, 0x74,0x55,0x12,0x77, +0x1, 0x74,0xaa,0x2, 0x73,0xa, 0x7a,0xb3,0x34,0xda,0x7c,0xbf,0x6c,0x77,0x7c,0x67, +0x7c,0x7b,0xc4,0x23,0x54,0x1f,0x7c,0xab,0x7c,0xb7,0x54,0x7, 0xa, 0x2b,0x2e,0x24, +0x0, 0x5e,0x12,0x67,0x47,0x7c,0x7b,0x4c,0x66,0x68,0xf, 0xa, 0x2a,0x2e,0x24,0x27, +0x72,0x7e,0x29,0xb0,0x4c,0xb7,0x7a,0x29,0xb0,0x22,0x7c,0xb7,0x64,0xff,0xa, 0x2a, +0x2e,0x24,0x27,0x72,0x7e,0x29,0x70,0x5c,0x7b,0x7a,0x29,0x70,0x22,0x7e,0x73,0x28, +0x84,0xbc,0x7f,0x22,0xca,0xd8,0xca,0x79,0xc2,0x0, 0x6d,0x88,0x7a,0x87,0x39,0x3d, +0xe4,0x7a,0xb3,0x1f,0x58,0xe5,0x1f,0xbe,0xb0,0xff,0x50,0x2, 0x5, 0x1f,0x7e,0xb3, +0x28,0x84,0x60,0xa, 0x7e,0x87,0x7, 0xfa,0xbe,0x84,0x0, 0xfa,0x58,0xa, 0xc2,0x14, +0x6d,0x88,0x7a,0x87,0x38,0xfe,0x81,0x97,0x12,0x91,0xe1,0x60,0x10,0x7e,0x84,0x0, +0x64,0x7a,0x87,0x38,0xf4,0x7e,0x84,0x0, 0x2d,0x7a,0x87,0x38,0xfe,0x7e,0x87,0x38, +0xf4,0x4d,0x88,0x68,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xa9,0x6c,0xff,0x80,0x76,0xe4, +0xa, 0x3f,0x19,0xb3,0x1f,0x34,0x12,0x75,0x14,0x7e,0x8, 0x1f,0x52,0x7c,0xbd,0x7c, +0x7e,0x12,0x90,0x9c,0x7d,0x93,0x7e,0x87,0x38,0xfe,0xbd,0x89,0x50,0x4, 0x7a,0x97, +0x38,0xfe,0x7e,0x87,0x39,0x3d,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x39,0x3d,0xe5,0x1f, +0xbe,0xb0,0x5, 0x38,0x1f,0x7e,0x8, 0x39,0x0, 0x12,0x75,0x8c,0x50,0x7, 0x12,0x75, +0xb, 0xd2,0x0, 0x80,0x2e,0x7e,0x8, 0x39,0x0, 0x7e,0x18,0x1f,0x52,0x12,0x77,0x42, +0x50,0x21,0x80,0xf, 0xbe,0x94,0x0, 0x2d,0x40,0x19,0x7e,0x8, 0x1f,0x52,0x12,0x90, +0x4d,0x50,0x10,0x12,0x75,0xb, 0x7e,0x8, 0x1f,0x58,0x7e,0x18,0x1f,0x52,0x12,0x91, +0xbb,0xd2,0x0, 0xb, 0xf0,0x12,0x73,0x6d,0x38,0x85,0x30,0x0, 0x30,0x6c,0xff,0x80, +0x1c,0x12,0x75,0x14,0x7e,0x8, 0x1f,0x58,0x12,0x75,0x8c,0x40,0x9, 0xa, 0x3f,0x9, +0xb3,0x1f,0x34,0xb4,0x1, 0x5, 0x7c,0xbf,0x12,0x74,0xeb,0xb, 0xf0,0x12,0x73,0x6d, +0x38,0xdf,0x75,0x1f,0x0, 0x7e,0x34,0x0, 0x64,0x7a,0x37,0x38,0xf4,0x7e,0x63,0x1f, +0x58,0x7e,0x70,0x6, 0xac,0x67,0xb, 0x34,0xca,0x39,0x7e,0x18,0x1f,0x58,0x7e,0x8, +0x39,0x0, 0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x37,0x38,0xf4,0x4d,0x33,0x78,0x26,0x7e, +0x37,0x38,0xfe,0xbe,0x34,0x0, 0x2d,0x40,0x30,0x7e,0x37,0x39,0x3d,0xbe,0x34,0x0, +0x16,0x40,0x26,0x7e,0x73,0x26,0xf7,0xbe,0x70,0xc, 0x28,0x1d,0x7e,0x73,0x26,0xf6, +0xbe,0x70,0x7, 0x28,0x14,0x6c,0xff,0x80,0x7, 0x7c,0xbf,0x12,0x74,0xeb,0xb, 0xf0, +0x12,0x73,0x6d,0x38,0xf4,0xd2,0x0, 0x80,0x6, 0x6d,0x33,0x7a,0x37,0x38,0xfe,0xa2, +0x0, 0x92,0x14,0x12,0x77,0x2b,0xda,0x79,0xda,0xd8,0x22,0x7c,0xab,0x7e,0xb3,0x3a, +0xc, 0x70,0x17,0x7e,0xb3,0x28,0xa8,0x70,0x11,0x12,0x4f,0xd4,0x68,0xc, 0x12,0x90, +0x35,0x68,0x7, 0x7c,0xba,0x6c,0x77,0x2, 0x73,0x2e,0x22,0x74,0x1, 0xa, 0x8f,0x19, +0xb8,0x1f,0x34,0x22,0x74,0x2, 0xac,0xbf,0x9, 0xd5,0x26,0xfa,0x9, 0xe5,0x26,0xfb, +0x22,0xca,0xf8,0x6c,0xff,0x80,0x18,0x7c,0xbf,0x12,0x6f,0x6b,0xbe,0x37,0x2a,0x5c, +0x58,0xb, 0x12,0x73,0x2a,0x7e,0x70,0x2, 0xac,0x7f,0x12,0x8f,0xa4,0xb, 0xf0,0x12, +0x73,0x6d,0x38,0xe3,0x12,0x75,0x4a,0xda,0xf8,0x22,0xca,0x79,0x6c,0xff,0x6c,0xee, +0x80,0x2e,0x7c,0xbe,0x12,0x88,0x65,0x60,0x25,0x7e,0x34,0x0, 0x2, 0xca,0x39,0xac, +0x7e,0x2e,0x34,0x26,0xfa,0x6d,0x22,0x7e,0x30,0x2, 0xac,0x3f,0x2e,0x14,0x26,0xfa, +0x6d,0x0, 0x12,0x20,0xc3,0x1b,0xfd,0x7c,0xbf,0x12,0x76,0xfb,0xb, 0xf0,0xb, 0xe0, +0x12,0x97,0xbe,0x38,0xcd,0x7a,0xf3,0x28,0x84,0xda,0x79,0x22,0x7c,0xbd,0x7c,0x7e, +0x7c,0x6b,0xc2,0x1, 0x6c,0xaa,0x80,0x30,0x7e,0x50,0x6, 0xac,0x5a,0x7f,0x70,0x2d, +0xf2,0xb, 0xf4,0x29,0xb7,0x0, 0x2, 0xbc,0xb6,0x40,0x1b,0x7e,0x7b,0xb0,0xbc,0xb6, +0x38,0x14,0x29,0xb7,0x0, 0x3, 0xbc,0xb7,0x40,0xc, 0x29,0xb7,0x0, 0x1, 0xbc,0xb7, +0x38,0x4, 0xd2,0x1, 0x80,0x9, 0xb, 0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x38,0xc9,0xa2, +0x1, 0x22,0xca,0xd8,0xca,0x79,0x7e,0xa3,0x2a,0x6e,0x7e,0x47,0x28,0x99,0xe4,0x7a, +0xb3,0x28,0xa6,0x7e,0xb3,0x26,0xf0,0xbe,0xb0,0x0, 0x28,0x48,0x12,0x9e,0x47,0x28, +0x43,0x6c,0xff,0x80,0x3b,0x7e,0x50,0x2, 0xac,0x5f,0x9, 0xd2,0x27,0x36,0x9, 0xe2, +0x27,0x37,0x7e,0x50,0x2, 0xac,0x5e,0x49,0x12,0x4, 0xfc,0x6d,0x22,0x9e,0x27,0x2a, +0x53,0xbd,0x12,0x58,0x19,0x12,0x76,0xe8,0x49,0x12,0x4, 0xfc,0x6d,0x22,0x9e,0x27, +0x2a,0x51,0xbd,0x12,0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x28,0xa6,0x80,0x6, 0xb, 0xf0, +0xbc,0x7f,0x38,0xc1,0xe4,0x7a,0xb3,0x28,0xa7,0x7e,0xb3,0x26,0x83,0x70,0x40,0x12, +0x76,0xe0,0x28,0x3b,0x6c,0xff,0x80,0x33,0x7e,0x50,0x2, 0xac,0x5f,0x9, 0xd2,0x26, +0xfa,0x9, 0xe2,0x26,0xfb,0x12,0x76,0xe8,0x49,0x2, 0x5, 0x7a,0x6d,0x11,0x9d,0x14, +0xbd,0x1, 0x48,0xd, 0x7e,0x10,0x2, 0xac,0x1e,0x49,0x20,0x5, 0x7a,0xbd,0x21,0x58, +0x8, 0x74,0x1, 0x7a,0xb3,0x28,0xa7,0x80,0x6, 0xb, 0xf0,0xbc,0x7f,0x38,0xc9,0x12, +0x9c,0xbc,0xe4,0x7a,0xb3,0x28,0xa9,0x7e,0x37,0x28,0x88,0x2e,0x37,0x28,0x86,0xbe, +0x37,0x28,0x9f,0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xa9,0x74,0x1, 0x7a,0xb3,0x28, +0xaa,0x6c,0xff,0x80,0x1f,0x12,0x76,0xf1,0x49,0x25,0x25,0xf7,0x7d,0x43,0x9d,0x42, +0x7d,0x34,0x12,0x21,0xa, 0xbe,0x37,0x28,0x9d,0x8, 0x7, 0xe4,0x7a,0xb3,0x28,0xaa, +0x80,0x7, 0xb, 0xf0,0x12,0x73,0x6d,0x38,0xdc,0x6c,0xff,0x80,0x9, 0x12,0x76,0xf1, +0x59,0x35,0x25,0xf7,0xb, 0xf0,0x12,0x73,0x6d,0x38,0xf2,0xda,0x79,0xda,0xd8,0x22, +0x7e,0x73,0x28,0x84,0xbe,0x70,0x0, 0x22,0xa, 0x1d,0xa, 0x2a,0x2d,0x21,0x3e,0x24, +0x22,0x7c,0xbf,0x12,0x6f,0x6b,0x74,0x2, 0xac,0xbf,0x22,0x7e,0x70,0x1, 0x2, 0x73, +0x2e,0x7e,0x34,0xd7,0x2, 0x7a,0x1b,0xb0,0x22,0x7e,0x34,0xd7,0x1, 0x7a,0x1b,0xb0, +0x22,0x7e,0x34,0xd7,0x0, 0x7e,0x24,0x0, 0xff,0x7a,0x1b,0xb0,0x22,0x12,0x77,0x74, +0x12,0x8d,0x9b,0x12,0x71,0x90,0x7a,0xb3,0x2a,0xc, 0x22,0x30,0x14,0x13,0x12,0xc7, +0x1, 0x68,0x6, 0x7e,0xb3,0x3a,0xc, 0x60,0x8, 0x7e,0x34,0xb, 0xb8,0x7a,0x37,0x38, +0xfc,0x22,0x7f,0x61,0x7f,0x50,0x7e,0x6b,0x90,0x80,0x1f,0x29,0x86,0x0, 0x1, 0x80, +0xf, 0x7f,0x5, 0x7c,0xb9,0x7c,0x78,0x12,0x75,0x90,0x50,0x2, 0xd3,0x22,0xb, 0x80, +0x29,0x76,0x0, 0x3, 0xbc,0x78,0x50,0xe9,0xb, 0x90,0x29,0x76,0x0, 0x2, 0xbc,0x79, +0x50,0xd9,0xc3,0x22,0x7e,0xa3,0x28,0x84,0xe4,0x7a,0xb3,0x34,0xb7,0x6c,0x33,0x80, +0x3d,0x7e,0x70,0x2, 0xac,0x73,0x9, 0x23,0x26,0xfb,0x7e,0x10,0x1, 0x6c,0x0, 0x80, +0x27,0xbc,0x3, 0x68,0x21,0x7e,0x70,0x2, 0xac,0x70,0x9, 0x93,0x26,0xfb,0xa, 0x29, +0xa, 0x32,0x12,0x82,0xcd,0x18,0x2, 0xb, 0x10,0xbe,0x10,0x2, 0x40,0x8, 0x74,0x2, +0x7a,0xb3,0x34,0xb7,0x80,0x6, 0xb, 0x0, 0xbc,0xa0,0x38,0xd5,0xb, 0x30,0xbc,0xa3, +0x38,0xbf,0x2, 0x77,0xc5,0xca,0xf8,0x7e,0x33,0x28,0x84,0x6c,0x22,0x80,0x3f,0x74, +0x2, 0xac,0xb2,0x9, 0x15,0x26,0xfa,0x9, 0x5, 0x26,0xfb,0x7e,0xa0,0x1, 0x6c,0x99, +0x80,0x26,0xbc,0x92,0x68,0x20,0x12,0x8f,0xde,0x9, 0xf3,0x26,0xfb,0xa, 0x28,0xa, +0x31,0x12,0x82,0xcd,0x18,0xb, 0xa, 0x2f,0xa, 0x30,0x12,0x82,0xcd,0x8, 0x2, 0xb, +0xa0,0xbe,0xa0,0x3, 0x50,0x6, 0xb, 0x90,0xbc,0x39,0x38,0xd6,0xb, 0x20,0xbc,0x32, +0x38,0xbd,0x7e,0xb3,0x35,0x54,0xbe,0xb0,0x0, 0x28,0x12,0x14,0x7a,0xb3,0x35,0x54, +0xbe,0xb0,0x14,0x28,0x8, 0x7e,0x34,0x0, 0x8c,0x7a,0x37,0x2a,0x5a,0x7e,0xb3,0x37, +0xed,0x70,0x58,0x7e,0xb3,0x3a,0xc, 0x70,0x52,0x7e,0xb3,0x37,0x71,0x70,0x4c,0x7e, +0x37,0x38,0xfe,0xbe,0x34,0x0, 0x14,0x50,0x42,0x7e,0x37,0x28,0x8a,0xbe,0x34,0x3, +0x20,0x58,0x38,0x7e,0xb3,0x28,0x84,0xbe,0xb0,0x3, 0x40,0x2f,0xbe,0xa0,0x3, 0x40, +0x2a,0x7e,0xb3,0x26,0x85,0xbe,0xb0,0x3, 0x50,0x9, 0x7e,0xb3,0x26,0x84,0xbe,0xb0, +0x3, 0x40,0x18,0x7e,0xb3,0x26,0xf6,0xbe,0xb0,0x8, 0x50,0x9, 0x7e,0xb3,0x26,0xf7, +0xbe,0xb0,0x8, 0x40,0x6, 0x74,0x1e,0x7a,0xb3,0x35,0x54,0xda,0xf8,0x22,0xca,0xf8, +0x7e,0xa3,0x2a,0x2, 0x4c,0xaa,0x78,0x11,0x7e,0xb3,0x2a,0x3, 0xbe,0xb0,0x0, 0x28, +0x13,0x74,0x1, 0x7a,0xb3,0x2a,0x7, 0x80,0xb, 0xbe,0xa0,0x0, 0x28,0x6, 0x74,0x1, +0x7a,0xb3,0x2a,0xb, 0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18,0x28,0xae,0x7e,0x8, +0x29,0x8, 0x12,0x20,0xc3,0x1b,0xfd,0x6c,0xff,0x12,0x7d,0x51,0x12,0x7a,0xa2,0x74, +0x9, 0xac,0xbf,0x59,0x35,0x29,0x8, 0x49,0x35,0x28,0xb0,0x12,0x78,0xeb,0x12,0x79, +0xe0,0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0xe1,0xda,0xf8,0x22,0x7d,0xf3,0x9f,0x11,0x7e, +0x44,0x7, 0x80,0x12,0x7b,0x74,0x7d,0xd5,0x1b,0xd4,0xbe,0xf4,0x0, 0x3f,0x38,0x1f, +0x7e,0x24,0x0, 0x3f,0x9d,0x2f,0x7e,0x34,0x2, 0x57,0x12,0x79,0xc5,0xbe,0x18,0x0, +0x4a,0x40,0x4, 0x7e,0x18,0x0, 0x4a,0x7e,0x8, 0x0, 0x4a,0x9f,0x1, 0x7f,0x10,0x7d, +0x5d,0x9e,0x54,0x0, 0x3f,0xbd,0x5f,0x38,0x1f,0x12,0x79,0xd7,0x40,0x1a,0x7d,0x3d, +0x9e,0x34,0x0, 0x40,0x12,0x79,0xbd,0xbe,0x18,0x0, 0x4d,0x40,0x4, 0x7e,0x18,0x0, +0x4c,0x12,0x79,0xce,0x2f,0x10,0x80,0x14,0x12,0x79,0xd7,0x50,0xf, 0x7d,0x3d,0x9e, +0x34,0x0, 0x20,0x12,0x79,0xbd,0x7d,0x14,0x6d,0x0, 0x2f,0x10,0xbe,0xf4,0x0, 0x3f, +0x28,0x5a,0xbd,0x5f,0x28,0x56,0x7d,0xed,0xb, 0xe4,0x1e,0xe4,0x7d,0x5e,0x1b,0x54, +0xbd,0x5f,0x40,0xc, 0x7d,0x35,0x9d,0x3f,0x6d,0x22,0x7e,0x14,0x1, 0x44,0x80,0xa, +0x7d,0x3f,0x9d,0x3e,0x6d,0x22,0x7e,0x14,0x1, 0x43,0x12,0x1e,0xfc,0x12,0x79,0xc7, +0xbd,0x5f,0x7d,0x14,0x40,0xc, 0x1e,0x14,0x1b,0x14,0x6d,0x0, 0x9f,0x1, 0x7f,0x10, +0x80,0x6, 0x1e,0x14,0x6d,0x0, 0x2f,0x10,0xbe,0x18,0x0, 0x4a,0x50,0x5, 0x7e,0x18, +0x0, 0x4a,0x22,0x12,0x79,0xce,0xbf,0x10,0x28,0x2, 0x7f,0x10,0x22,0x7d,0x2f,0x9d, +0x23,0x7e,0x34,0x2, 0x52,0xad,0x23,0x7c,0x76,0x7c,0x65,0x1a,0x24,0x22,0x7d,0x14, +0x6d,0x0, 0x9e,0x8, 0x0, 0x4d,0x22,0x7d,0xed,0x9e,0xe4,0x0, 0xb, 0xbd,0xef,0x22, +0x74,0x9, 0xac,0xbf,0x59,0x35,0x29,0xa, 0x22,0xca,0xd8,0xca,0x79,0x7e,0x44,0x7, +0x80,0x6c,0xff,0x7e,0x70,0x9, 0xac,0x7f,0x9, 0xe3,0x29,0xc, 0x5e,0xe0,0xf, 0x49, +0xc3,0x29,0xa, 0x7d,0x24,0x2e,0x24,0x0, 0x14,0xbd,0xc2,0x40,0x3f,0x49,0xd3,0x29, +0x8, 0x7d,0x3d,0x12,0xa4,0xe5,0x7c,0xdb,0xbe,0xd0,0x3, 0x40,0xe, 0x7d,0x34,0x1b, +0x34,0x12,0x79,0xe0,0x7c,0xbe,0x12,0x7a,0x77,0x80,0x40,0x7e,0x70,0x2, 0xac,0x7d, +0x2e,0x34,0x60,0xc5,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xd0,0x74,0x9, 0xac,0xbf,0x59, +0xd5,0x29,0x8, 0x7e,0x34,0x7, 0xf8,0x12,0x79,0xe0,0x80,0x1f,0xbd,0xc4,0x40,0x1b, +0x7d,0x54,0x2e,0x54,0x0, 0xa, 0xbd,0xc5,0x40,0x5, 0x7c,0xbe,0x12,0x7a,0x77,0x7d, +0xc4,0x1b,0xc4,0x74,0x9, 0xac,0xbf,0x59,0xc5,0x29,0xa, 0xb, 0xf0,0xbe,0xf0,0xa, +0x40,0x81,0xda,0x79,0xda,0xd8,0x22,0x7c,0xab,0x7e,0x8, 0x29,0xbc,0xbe,0xa0,0xa, +0x50,0x1f,0xa, 0x3a,0x7f,0x70,0x2d,0xf3,0x7e,0x7b,0xb0,0xb4,0x2, 0x4, 0x74,0x1, +0x80,0x2, 0x74,0x3, 0x7a,0x7b,0xb0,0x74,0x3, 0x2d,0x31,0x7d,0x20,0x39,0xb1,0x0, +0xa, 0x22,0x7d,0xd3,0x7e,0x44,0x4, 0x38,0x7e,0xa3,0x2a,0x6f,0x74,0x40,0xa4,0x7d, +0xb5,0x1b,0xb4,0xbe,0xd4,0x0, 0x3f,0x38,0x1d,0x7e,0xe4,0x0, 0x3f,0x9d,0xed,0x7e, +0xf4,0x2, 0x36,0x12,0x7b,0x61,0x40,0x4, 0x7e,0x78,0x0, 0x44,0x7e,0x18,0x0, 0x44, +0x9f,0x17,0x7f,0x71,0x80,0x7f,0x7d,0x5b,0x9e,0x54,0x0, 0x3f,0xbd,0x5d,0x38,0x18, +0x7d,0xed,0x9d,0xe5,0x7e,0xf4,0x2, 0x4a,0x12,0x7b,0x61,0x40,0x4, 0x7e,0x78,0x0, +0x43,0x12,0x7b,0x58,0x2f,0x71,0x80,0x5d,0x7d,0xcb,0xb, 0xc4,0x1e,0xc4,0x7d,0x5c, +0x1b,0x54,0xbd,0x5d,0x40,0xc, 0x7d,0xf5,0x9d,0xfd,0x6d,0xee,0x7e,0x14,0x1, 0x39, +0x80,0xa, 0x7d,0xfd,0x9d,0xfc,0x6d,0xee,0x7e,0x14,0x1, 0x3b,0x7f,0x17,0x12,0x1e, +0xfc,0x7f,0x71,0x12,0x45,0xb1,0x7f,0x71,0xbd,0x5d,0x7d,0x34,0x40,0xc, 0x1e,0x34, +0x1b,0x34,0x6d,0x22,0x9f,0x17,0x7f,0x71,0x80,0x6, 0x1e,0x34,0x6d,0x22,0x2f,0x71, +0xbe,0x78,0x0, 0x44,0x50,0x6, 0x7e,0x78,0x0, 0x44,0x80,0x9, 0x12,0x7b,0x58,0xbf, +0x71,0x28,0x2, 0x7f,0x71,0x7d,0x3f,0x22,0x7d,0x34,0x9e,0x34,0x0, 0x44,0x6d,0x22, +0x22,0xad,0xfe,0x6d,0xee,0x7d,0x3f,0x7d,0x2e,0x7c,0x76,0x7c,0x65,0x7f,0x71,0xbe, +0x78,0x0, 0x44,0x22,0x7e,0xa3,0x2a,0x70,0x74,0x40,0xa4,0x22,0xca,0x3b,0x6d,0x0, +0x7e,0xe3,0x2a,0x2, 0x4c,0xee,0x78,0x20,0x6c,0xff,0x6d,0x11,0x74,0x2, 0xac,0xbf, +0x12,0x7d,0x46,0xac,0x3f,0x19,0xa1,0x34,0xe0,0x74,0x2, 0xa, 0x1f,0x19,0xb1,0x35, +0x4a,0xb, 0xf0,0xbe,0xf0,0xa, 0x78,0xe2,0x12,0x7d,0xb3,0x7e,0x24,0x0, 0x14,0xad, +0x32,0x7d,0x43,0x2e,0x44,0x3, 0x20,0x6c,0xff,0xa1,0x18,0x74,0x9, 0xac,0xbf,0x9, +0xd5,0x28,0xb2,0x5e,0xd0,0xf, 0xbe,0xd0,0xa, 0x40,0x2, 0xa1,0x16,0xa, 0x1d,0x9, +0xb1,0x29,0xbc,0xbe,0xb0,0x1, 0x78,0x2, 0x81,0xff,0x75,0x24,0x0, 0x7e,0x71,0x24, +0x74,0x9, 0xac,0x7b,0x9, 0xc3,0x34,0xe0,0xbc,0xcd,0x68,0x2, 0x81,0xf2,0x12,0x7b, +0x74,0x7d,0xf5,0x9e,0xf4,0x0, 0x20,0x2e,0xf4,0x0, 0x14,0x49,0x23,0x34,0xde,0xbd, +0x2f,0x28,0xe, 0x74,0x9, 0xac,0xbf,0x49,0x15,0x28,0xb0,0xbd,0x1f,0x38,0x2, 0x81, +0x9e,0x74,0x9, 0xac,0xbf,0x49,0x35,0x28,0xb0,0x9d,0x32,0x12,0x21,0xa, 0x7d,0x3, +0x7e,0xa1,0x24,0x74,0x9, 0xa4,0x49,0x25,0x34,0xdc,0x12,0x7d,0x51,0x9d,0x32,0x12, +0x21,0xa, 0x2d,0x3, 0xa, 0x1c,0x9, 0xa1,0x35,0x4a,0xbe,0xa0,0x0, 0x28,0x17,0x7e, +0x30,0x2, 0xac,0x3c,0x59,0x1, 0x35,0x36,0xa, 0x1c,0x2e,0x14,0x35,0x4a,0x7c,0xba, +0x14,0x7a,0x19,0xb0,0xa1,0x16,0x74,0x2, 0xac,0xbc,0x49,0x15,0x35,0x36,0xbe,0x14, +0x0, 0x32,0x28,0x8, 0x7d,0xe1,0x2d,0xe4,0xbd,0xe0,0x40,0x20,0xbe,0x14,0x0, 0x32, +0x28,0x8, 0xbe,0x4, 0x0, 0x32,0x28,0x2, 0x80,0x72,0x7d,0xe1,0x2e,0xe4,0x0, 0x32, +0xbd,0xe0,0x50,0x8, 0xbe,0x14,0x0, 0x32,0x28,0x2, 0x80,0x60,0xbe,0x4, 0x0, 0xa0, +0x28,0x56,0xa, 0x1d,0x9, 0xb1,0x29,0xbc,0x70,0x4, 0x74,0x3, 0x80,0x2, 0x74,0x1, +0xa, 0x1d,0x19,0xb1,0x29,0xbc,0x74,0x3, 0xa, 0x1c,0x19,0xb1,0x29,0xc6,0xbe,0xe0, +0x0, 0x28,0x63,0x1b,0xe0,0x7e,0x70,0x9, 0xac,0x7f,0x2e,0x34,0x28,0xae,0x7e,0x14, +0x1f,0x34,0x74,0x9, 0x12,0x1f,0x8c,0x7e,0x70,0x9, 0xac,0x7e,0x12,0x7f,0xa0,0xac, +0x3f,0x12,0x7d,0x3d,0x7e,0x34,0x1f,0x34,0x7e,0x30,0x9, 0xac,0x3e,0x12,0x7d,0x3d, +0x1b,0xf0,0x74,0x2, 0xac,0xbc,0x80,0x4, 0x74,0x2, 0xac,0xbc,0x59,0x5, 0x35,0x36, +0x80,0x24,0x5, 0x24,0xe5,0x24,0xbe,0xb0,0xa, 0x50,0x2, 0x61,0xdd,0x80,0x17,0x6d, +0x11,0x74,0x2, 0xac,0xbd,0x12,0x7d,0x46,0xac,0x3d,0x19,0xa1,0x34,0xe0,0x74,0x2, +0xa, 0x1d,0x19,0xb1,0x35,0x4a,0xb, 0xf0,0xbc,0xef,0x28,0x2, 0x61,0xbb,0xe4,0x7a, +0xb3,0x16,0x92,0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18,0x28,0xae,0x7e,0x8, 0x34, +0xdc,0x12,0x20,0xc3,0x1b,0xfd,0x7a,0xe3,0x2a,0x2, 0xda,0x3b,0x22,0x2e,0x14,0x28, +0xae,0x74,0x9, 0x2, 0x1f,0x8c,0x59,0x15,0x35,0x36,0x7e,0xa0,0xff,0x7e,0x30,0x9, +0x22,0x74,0x9, 0xac,0xbf,0x49,0x35,0x28,0xae,0x22,0x7e,0xb3,0x38,0x32,0x70,0x3, +0x12,0x7b,0x7c,0x2, 0x7d,0x66,0xca,0x79,0x7e,0xf3,0x2a,0x2, 0x7e,0xe3,0x2a,0x3, +0x7c,0xbf,0x7c,0x7e,0x12,0x7e,0x9f,0x7c,0xbf,0x12,0x9e,0x59,0x4c,0xee,0x78,0x15, +0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18,0x28,0xae,0x7e,0x8, 0x29,0x62,0x12,0x20, +0xc3,0x1b,0xfd,0x80,0xb, 0x7e,0xb3,0x2a,0x9, 0x70,0x5, 0x7c,0xbf,0x12,0x7f,0x12, +0x7c,0xbf,0x12,0x7d,0xeb,0xbe,0xf0,0x0, 0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x2a,0xb, +0xda,0x79,0x22,0x7e,0x73,0x2a,0x3, 0xbe,0x73,0x2a,0x2, 0x78,0x13,0x12,0x7f,0x98, +0x40,0xe, 0x7e,0x37,0x34,0xb4,0xbe,0x34,0x0, 0x14,0x38,0xe, 0xb, 0x34,0x80,0x6, +0x7e,0x37,0x34,0xb4,0x1e,0x34,0x7a,0x37,0x34,0xb4,0x7e,0xb3,0x2a,0x2, 0x70,0x6, +0x6d,0x33,0x7a,0x37,0x34,0xb4,0x7e,0x37,0x34,0xb4,0x22,0x6c,0xaa,0x7e,0x50,0x9, +0xac,0x5a,0x49,0x32,0x29,0x62,0x12,0x7e,0x3c,0x59,0x32,0x28,0xae,0x7e,0x50,0x9, +0xac,0x5a,0x49,0x32,0x29,0x64,0x12,0x7e,0x3c,0x59,0x32,0x28,0xb0,0x7e,0x90,0x9, +0xac,0x9a,0x9, 0xb4,0x29,0x66,0x19,0xb4,0x28,0xb2,0x7e,0x90,0x9, 0xac,0x9a,0x9, +0xb4,0x29,0x67,0x19,0xb4,0x28,0xb3,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x68, +0x19,0xb4,0x28,0xb4,0xb, 0xa0,0xbe,0xa0,0xa, 0x40,0xb2,0x22,0x1e,0x34,0x1e,0x34, +0x1e,0x34,0x1e,0x34,0x22,0x7f,0x71,0x69,0x37,0x0, 0x2, 0x7d,0x53,0x12,0x7f,0x90, +0xb, 0x7a,0x20,0x2d,0x25,0x1b,0xa, 0x20,0x69,0x27,0x0, 0x4, 0x7d,0x52,0xc4,0x54, +0xf0,0x7c,0xab,0xe4,0x1e,0x34,0x1e,0x34,0x2d,0x35,0x79,0x30,0x0, 0x2, 0x69,0x37, +0x0, 0x6, 0x7d,0x53,0x7c,0xab,0xe4,0x3e,0x54,0x3e,0x54,0x1e,0x24,0x1e,0x24,0x1e, +0x24,0x1e,0x24,0x2d,0x25,0x79,0x20,0x0, 0x4, 0x69,0x27,0x0, 0x8, 0x7c,0x45,0x6c, +0x55,0x12,0x7e,0x3c,0x1e,0x34,0x1e,0x34,0x2d,0x32,0x79,0x30,0x0, 0x6, 0x22,0x7c, +0x67,0x7c,0x7b,0xa5,0xbf,0x0, 0x17,0xbe,0x60,0x0, 0x28,0xf, 0x74,0x1, 0x7a,0xb3, +0x2a,0x7, 0xe4,0x7a,0xb3,0x2a,0x9, 0x7a,0xb3,0x2a,0xa, 0x2, 0x7f,0xb5,0xa5,0xbe, +0x0, 0x1b,0x6c,0xaa,0x7e,0x60,0xff,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x62,0x29,0x66, +0xb, 0xa0,0xbe,0xa0,0xa, 0x78,0xf0,0x74,0x1, 0x7a,0xb3,0x2a,0x6, 0x6c,0xaa,0x80, +0x20,0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x28,0xae,0x12,0x7f,0x6, 0x1b,0x18,0x20, +0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x28,0xb0,0x12,0x7f,0x6, 0x1b,0x18,0x20,0xb, +0xa0,0xbc,0x7a,0x38,0xdc,0x22,0xb, 0x18,0x20,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e, +0x24,0x22,0xca,0x3b,0x7c,0xfb,0x6c,0xee,0x80,0x6c,0x6c,0xdd,0x74,0x9, 0xac,0xbd, +0x9, 0x45,0x29,0x66,0x7e,0x70,0x9, 0xac,0x7e,0x9, 0x53,0x28,0xb2,0xbc,0x45,0x68, +0x7, 0xb, 0xd0,0xbe,0xd0,0xa, 0x40,0xe4,0xbe,0xd0,0xa, 0x50,0x4d,0x74,0x9, 0xac, +0xbd,0x9, 0xc5,0x29,0x66,0x49,0x25,0x29,0x64,0x49,0x33,0x28,0xb0,0x12,0x4f,0xcc, +0x74,0x9, 0xac,0xbd,0x12,0x7f,0xa8,0x9d,0x32,0x12,0x21,0xa, 0x2d,0x31,0x7a,0x35, +0x24,0xa, 0x3c,0x9, 0xb3,0x29,0xbc,0xb4,0x1, 0xe, 0x6d,0x33,0x74,0x2, 0xac,0xbc, +0x59,0x35,0x34,0xa0,0x59,0x35,0x34,0xc6,0x7e,0x35,0x24,0x7c,0xbd,0x7c,0x5e,0x7c, +0x4c,0x12,0x7f,0x8d,0xb, 0xe0,0xbc,0xfe,0x38,0x90,0xda,0x3b,0x22,0x2, 0x47,0x36, +0x3, 0x3, 0x54,0xc0,0x7c,0xab,0xe4,0x22,0x7e,0x73,0x2a,0x2, 0xbe,0x70,0x1, 0x22, +0x2e,0x34,0x28,0xae,0x7e,0x30,0x9, 0x22,0x49,0x25,0x29,0x62,0x74,0x9, 0xac,0xbe, +0x49,0x35,0x28,0xae,0x22,0x7e,0x8, 0x34,0xc6,0x7e,0x34,0x0, 0x14,0xe4,0x12,0x20, +0xe8,0x7e,0x8, 0x34,0xa0,0x7e,0x34,0x0, 0x14,0x2, 0x20,0xe8,0x7e,0xb3,0x2a,0x9, +0x70,0x23,0x7e,0xb3,0x34,0xb7,0xb4,0x2, 0x9, 0x12,0x7f,0x98,0x28,0x4, 0x74,0x3, +0x80,0x1, 0xe4,0x7a,0xb3,0x34,0xc2,0x7e,0x73,0x34,0xc3,0xbe,0x73,0x34,0xc2,0x28, +0x4, 0x7a,0x73,0x34,0xc2,0x22,0x12,0xa0,0x50,0x2, 0x7f,0xcc,0x7e,0xb3,0x2a,0x3, +0xb4,0x1, 0x22,0x7e,0xb3,0x28,0x84,0xb4,0x1, 0x1b,0x7e,0xb3,0x28,0xa8,0x70,0x15, +0x7e,0xb3,0x26,0x83,0xb4,0x1, 0xe, 0x7e,0xb3,0x28,0x85,0x70,0x8, 0x7e,0xb3,0x2a, +0x68,0x70,0x2, 0xd3,0x22,0xc3,0x22,0x7d,0x13,0x7d,0x32,0x6d,0x22,0x74,0x6, 0x2f, +0x11,0x14,0x78,0xfb,0xb, 0x14,0x12,0x1f,0x5, 0x7d,0x53,0xbe,0x54,0x0, 0xff,0x28, +0x4, 0x7e,0x54,0x0, 0x40,0x22,0xca,0xf8,0x7e,0xf3,0x2a,0x70,0x7a,0x37,0x1f,0x3a, +0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x3c,0xe4,0x7a,0xb3,0x1f,0x34,0x7a,0xb3,0x1f, +0x35,0x7e,0x73,0x2a,0x6f,0x7a,0x73,0x1f,0x36,0x7a,0xf3,0x1f,0x37,0x7a,0xb3,0x1f, +0x38,0x7a,0xb3,0x1f,0x39,0x7e,0x8, 0x1f,0x34,0x12,0x80,0x9b,0x6d,0x22,0x7d,0x3, +0x6d,0x11,0x7e,0x37,0x15,0xa0,0x2f,0x10,0x7e,0x33,0x1f,0x36,0x6d,0x0, 0x12,0x1f, +0x7, 0xa, 0x1f,0x6d,0x0, 0x12,0x1f,0x7, 0xda,0xf8,0x22,0x12,0xc, 0x29,0x7e,0x37, +0x15,0x9e,0x22,0xca,0x3b,0x7c,0xc4,0x7c,0xf6,0x7c,0xe7,0x7c,0xdb,0x74,0x9, 0xac, +0xb5,0x7d,0x95,0x2e,0x94,0x27,0x76,0x6d,0x88,0x7e,0xe7,0x2a,0x66,0xe4,0x39,0xb4, +0x0, 0x6, 0x7e,0x70,0x2, 0xac,0x7f,0x9, 0xb3,0x26,0xfa,0xf5,0x35,0x9, 0xb3,0x26, +0xfb,0xf5,0x36,0x7e,0x73,0x2a,0x6e,0x7c,0x6e,0x7e,0x8, 0x0, 0x39,0x12,0x82,0xe6, +0xf5,0x37,0xe5,0x35,0x7e,0x73,0x2a,0x6d,0x7c,0x6d,0x7e,0x8, 0x0, 0x38,0x12,0x82, +0xe6,0x7c,0xab,0xe5,0x38,0x7e,0x71,0x39,0x12,0x6f,0x81,0x7d,0xf3,0x7a,0xf5,0x41, +0x7e,0xf4,0x15,0x9e,0x7a,0xf5,0x43,0x85,0x38,0x3b,0x85,0x39,0x3c,0x7a,0xa1,0x3d, +0x85,0x37,0x3e,0x7e,0xb3,0x2a,0x59,0xf5,0x3f,0x75,0x40,0x0, 0xbe,0xc0,0x1, 0x78, +0x8, 0xe5,0x3f,0x1e,0xb0,0x1e,0xb0,0xf5,0x3f,0x7e,0x8, 0x0, 0x3b,0x12,0x80,0x9b, +0x7d,0x23,0x6d,0x33,0x7e,0xb7,0x15,0xa0,0x6d,0xaa,0x2f,0x51,0x7e,0x37,0x15,0xa2, +0x6d,0x22,0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x15,0xa4,0x2f,0x10,0x7a,0x1d,0x2c,0x7e, +0x37,0x15,0xa6,0x6d,0x22,0x7d,0x3, 0x7e,0x37,0x15,0xa8,0x2f,0x10,0x7a,0x1d,0x30, +0x7f,0x65,0xa, 0x3d,0xe5,0x35,0xa, 0xfb,0x9d,0xf3,0x7d,0x3f,0x7c,0xc7,0x41,0x48, +0xa, 0x4e,0xe5,0x36,0xa, 0x5b,0x9d,0x54,0xf5,0x34,0x41,0x32,0xbe,0xc0,0x0, 0x58, +0x2, 0x41,0x30,0x7e,0x73,0x2a,0x6d,0xbc,0x7c,0x18,0x2, 0x41,0x30,0xe5,0x34,0xbe, +0xb0,0x0, 0x58,0x2, 0x41,0x30,0x7e,0x73,0x2a,0x6e,0xbe,0x71,0x34,0x18,0x2, 0x41, +0x30,0x7c,0xbc,0x7e,0x71,0x34,0x12,0x6d,0xcb,0x7e,0x53,0x2a,0x59,0xa, 0x25,0x7d, +0xf3,0x9d,0xf2,0xbe,0xf4,0x0, 0x0, 0x8, 0x77,0xbd,0xef,0x18,0xd, 0x7f,0x14,0x2e, +0x34,0x0, 0x6, 0x7e,0x1b,0xb0,0x4, 0x7a,0x1b,0xb0,0xe5,0x35,0xa, 0x2b,0x1a,0x3c, +0x12,0x82,0xcd,0x18,0xd, 0xe5,0x36,0xa, 0x2b,0xe5,0x34,0x1a,0x3b,0x12,0x82,0xcd, +0x8, 0x4e,0x7c,0xbc,0x7e,0x71,0x34,0x7c,0x6f,0x12,0x83,0x39,0xf5,0x3a,0xb4,0x2, +0x6, 0x7d,0x3f,0xe, 0x34,0x9d,0xf3,0xe5,0x3a,0xbe,0xb0,0x2, 0x68,0x5, 0xe5,0x3a, +0xb4,0x1, 0x2d,0x12,0x82,0xbe,0x1a,0x1c,0x12,0x82,0xc5,0x7e,0x1d,0x2c,0x9f,0x10, +0x7a,0x1d,0x2c,0x12,0x82,0xbe,0xe5,0x34,0x1a,0x1b,0x12,0x82,0xc5,0x7e,0x1d,0x30, +0x9f,0x10,0x7a,0x1d,0x30,0x12,0x82,0xbe,0x9f,0x51,0x1a,0x26,0x1a,0x24,0x9f,0x61, +0x5, 0x34,0xa, 0x2e,0xe5,0x36,0xa, 0x3b,0x2d,0x32,0x1a,0x27,0xe5,0x34,0x1a,0x3b, +0xbd,0x32,0x18,0x2, 0x21,0x7c,0xb, 0xc0,0xa, 0x2d,0xe5,0x35,0xa, 0x3b,0x2d,0x32, +0x1a,0x37,0x1a,0xfc,0xbd,0xf3,0x18,0x2, 0x21,0x70,0xbe,0x58,0x0, 0x0, 0x78,0x2, +0xb, 0x5c,0xbe,0x68,0x0, 0x0, 0x78,0x2, 0xb, 0x6c,0x7e,0x1d,0x2c,0x7f,0x5, 0x12, +0x82,0xd7,0x1b,0x4a,0x30,0x7e,0x1d,0x30,0x7f,0x6, 0x12,0x82,0xd7,0x79,0x34,0x0, +0x2, 0x7e,0xb3,0x2a,0x65,0x60,0xd, 0x1e,0xd4,0x1e,0xc4,0x50,0x4, 0x4e,0xd4,0x80, +0x0, 0x14,0x78,0xf3,0xbe,0x68,0x0, 0x7f,0x28,0x4, 0x7e,0x68,0x0, 0x7f,0x7d,0x3d, +0x39,0x74,0x0, 0x5, 0x74,0x9, 0xac,0xbf,0x9, 0x75,0x27,0x7c,0x39,0x74,0x0, 0x6, +0xbe,0x70,0xf, 0x28,0x6, 0x74,0xf, 0x39,0xb4,0x0, 0x6, 0xda,0x3b,0x22,0x7d,0x3f, +0x1a,0x26,0x1a,0x24,0x22,0x1a,0x2, 0x12,0x1e,0xeb,0x7f,0x1, 0x22,0x9d,0x32,0x12, +0x21,0xa, 0xbe,0x34,0x0, 0x1, 0x22,0x74,0x6, 0x2f,0x11,0x14,0x78,0xfb,0x12,0x1f, +0x7, 0x2e,0x18,0x0, 0x20,0x22,0xca,0xf8,0x7c,0xf6,0x7c,0x87,0x7c,0x9b,0xa, 0x2f, +0x7d,0x32,0x3e,0x34,0xb, 0x34,0x7c,0xb7,0xbc,0xf9,0x38,0x14,0xa, 0xf8,0x1b,0xf4, +0xa, 0x3f,0x9d,0xf3,0xa, 0x39,0xbd,0x3f,0x18,0x6, 0x7c,0xab,0xa, 0x39,0x80,0x1d, +0xbc,0xf9,0x28,0xd, 0xa, 0x39,0xa, 0x5f,0x2d,0x53,0xb, 0x54,0x7c,0xab,0xe4,0x80, +0x10,0xa, 0x3f,0xa, 0x58,0x2d,0x53,0xa, 0x39,0x9d,0x53,0x7c,0xab,0x9d,0x32,0x7c, +0xb7,0x7a,0xb, 0xb0,0x7c,0xba,0xda,0xf8,0x22,0x7c,0xa6,0x7c,0x37,0x7c,0x2b,0xe4, +0x6c,0x11,0x80,0x46,0xbc,0xa1,0x68,0x40,0x1a,0x41,0x3e,0x44,0x9, 0x4, 0x26,0xfb, +0xa, 0x20,0xa, 0x33,0x9d,0x32,0x12,0x21,0xa, 0x7c,0x7, 0x1a,0x41,0x3e,0x44,0x9, +0x74,0x26,0xfa,0xa, 0x27,0xa, 0x32,0x9d,0x32,0x12,0x21,0xa, 0x7c,0x97,0xbe,0x90, +0x1, 0x18,0x8, 0xbe,0x0, 0x1, 0x18,0x3, 0x74,0x1, 0x22,0xbe,0x90,0x2, 0x18,0x8, +0xbe,0x0, 0x2, 0x18,0x3, 0x74,0x2, 0x22,0xb, 0x10,0x7e,0x83,0x28,0x84,0xbc,0x81, +0x18,0xb2,0x22,0x7a,0x37,0x1f,0x38,0x7e,0x34,0x15,0xa8,0x7a,0x37,0x1f,0x3c,0x7e, +0x34,0x15,0x9e,0x7a,0x37,0x1f,0x3a,0x7e,0x73,0x2a,0x6f,0x7a,0x73,0x1f,0x35,0x7e, +0x73,0x2a,0x70,0x7a,0x73,0x1f,0x34,0x7e,0x37,0x2a,0x5c,0x7a,0x37,0x1f,0x3e,0x7e, +0x37,0x2a,0x5e,0x7a,0x37,0x1f,0x40,0x7e,0x37,0x2a,0x60,0x7a,0x37,0x1f,0x42,0x74, +0x1, 0x7a,0xb3,0x1f,0x36,0x7a,0xb3,0x1f,0x37,0x7e,0x8, 0x1f,0x34,0x7e,0x18,0x1f, +0x44,0x12,0x8, 0x0, 0x7e,0x37,0x1f,0x4e,0x7e,0x27,0x1f,0x4a,0xbd,0x23,0x28,0x2, +0x7d,0x32,0x22,0xca,0x3b,0x7e,0x8, 0x1f,0x34,0x12,0x3f,0xf2,0x7e,0x1f,0x39,0xf4, +0x7a,0x1d,0x27,0x7e,0xb3,0x2a,0x74,0xf5,0x2e,0x7e,0xb3,0x39,0x87,0xb4,0x1, 0x6, +0x7e,0x38,0x39,0x89,0x80,0x4, 0x7e,0x38,0x5, 0xf8,0x6d,0x33,0x7a,0x35,0x2b,0x74, +0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x39,0x88,0x70,0xe, 0x7e,0xb3,0x39,0x86,0x70,0x8, +0x74,0x1, 0x7a,0xb3,0x39,0x88,0x81,0xb8,0x7e,0xb3,0x39,0x88,0x70,0x6, 0x74,0x1, +0x7a,0xb3,0x39,0x88,0x7e,0xb3,0x39,0x87,0xb4,0x1, 0x14,0x75,0x2d,0x0, 0x80,0x6, +0x12,0x84,0xfa,0x12,0x85,0x8, 0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xf3,0x80,0x18,0x75, +0x2d,0x0, 0x80,0xc, 0x12,0x84,0xfa,0x3e,0x24,0x3e,0x24,0x1e,0x24,0x12,0x85,0x8, +0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xed,0x7e,0x34,0x0, 0xfa,0x7a,0x35,0x2f,0x7e,0x18, +0x1f,0x34,0x7f,0x1, 0x12,0x85,0x19,0x75,0x2d,0x0, 0x80,0x10,0x12,0x84,0xed,0xbe, +0x35,0x2b,0x8, 0x6, 0x12,0x84,0xed,0x7a,0x35,0x2b,0x5, 0x2d,0xe5,0x2e,0xbe,0xb1, +0x2d,0x38,0xe9,0x12,0x84,0xe5,0x40,0x25,0x7e,0xb3,0x39,0x87,0xb4,0x1, 0x1e,0x5, +0x1e,0xe5,0x1e,0xbe,0xb0,0xa, 0x40,0x15,0x75,0x1e,0x0, 0xe5,0x2e,0xa, 0x3b,0x3e, +0x34,0xca,0x39,0x7e,0x1d,0x27,0x7f,0x3, 0x12,0x20,0xc3,0x1b,0xfd,0x74,0x2, 0x12, +0x0, 0x1e,0x12,0x84,0xe5,0x50,0xb, 0x74,0x2, 0x7a,0xb3,0x39,0xf3,0xe4,0x7a,0xb3, +0x39,0x88,0xda,0x3b,0x22,0x7e,0x37,0x2b,0x7, 0xbe,0x35,0x2b,0x22,0x7e,0xa1,0x2d, +0x74,0x2, 0xa4,0x49,0x35,0x1f,0x34,0x2, 0x21,0xa, 0x7e,0xa1,0x2d,0x74,0x2, 0xa4, +0x7f,0x13,0x2d,0x35,0xb, 0x1a,0x20,0x22,0x7e,0xd, 0x27,0x2d,0x15,0xb, 0xa, 0x30, +0x9d,0x32,0x59,0x35,0x1f,0x34,0x5, 0x2d,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e, +0x73,0x2a,0x6e,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7f,0x16,0x7f,0x5, 0x12,0x20,0xc3, +0x1b,0xfd,0x6c,0xdd,0x12,0x87,0xb8,0x7a,0xb3,0x1f,0x6c,0x6c,0xcc,0x80,0x45,0x12, +0x85,0xbf,0x78,0x3e,0x12,0x87,0xc0,0xb, 0x1a,0xe0,0x7d,0x3f,0x12,0x21,0xa, 0x7d, +0x13,0x7d,0x3e,0x12,0x21,0xa, 0xbd,0x31,0x58,0x2, 0x7d,0xfe,0xbe,0xe5,0x2f,0x8, +0x5, 0x7e,0xe5,0x2f,0x80,0xb, 0x6d,0x33,0x9e,0x35,0x2f,0xbd,0x3e,0x8, 0x2, 0x7d, +0xe3,0x7d,0x3e,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1f,0x6c,0x4, 0x7a,0xb3, +0x1f,0x6c,0xb, 0xc0,0x7e,0x73,0x2a,0x70,0xbc,0x7c,0x38,0xb3,0x7e,0x73,0x1f,0x6c, +0x4c,0x77,0x68,0x1f,0x12,0x87,0xc9,0xbd,0x3e,0x8, 0x2, 0x7d,0x7f,0x6c,0xcc,0x80, +0xa, 0x12,0x85,0xbf,0x78,0x3, 0x12,0x87,0xde,0xb, 0xc0,0x7e,0x73,0x2a,0x70,0xbc, +0x7c,0x38,0xee,0xb, 0xd0,0xbe,0xd0,0x2, 0x50,0x2, 0xa1,0x34,0xda,0x3b,0x22,0xa, +0xec,0x9, 0x7e,0x2a,0xdc,0xa, 0x37,0x5e,0x34,0x0, 0x1, 0xa, 0xed,0xbd,0x3e,0x22, +0xca,0x3b,0x7f,0x31,0x7a,0xd, 0x24,0x7e,0x35,0x28,0x7a,0x35,0x2f,0x7e,0xd, 0x24, +0x7f,0x13,0x12,0x85,0x19,0x7e,0x35,0x28,0x7a,0x35,0x2a,0x12,0x86,0x3f,0x7e,0xd, +0x24,0x2d,0x15,0x7f,0x13,0x2d,0x35,0x12,0xa2,0x54,0xda,0x3b,0x22,0x7e,0x37,0x2a, +0x4f,0x1e,0x34,0x7a,0x35,0x28,0x7e,0x8, 0x4, 0xfc,0x7e,0x18,0x4, 0x0, 0x12,0x85, +0xd0,0x7e,0x37,0x28,0x99,0xe, 0x34,0x7a,0x35,0x28,0x7e,0x8, 0x5, 0x7a,0x7e,0x18, +0x4, 0x7e,0x12,0x85,0xd0,0x12,0xa4,0xb9,0x12,0xa3,0xb3,0x2, 0x86,0x2e,0xe4,0x7a, +0xb3,0x3, 0xfe,0x7e,0xb3,0x28,0xa8,0x60,0x5, 0xe4,0x7a,0xb3,0x3, 0xfe,0x22,0x7e, +0xa3,0x2a,0x74,0x74,0x2, 0xa4,0x22,0xca,0x3b,0x7e,0x44,0x7f,0xff,0x7d,0x14,0x7d, +0x4, 0x6d,0x22,0x7d,0x32,0x7d,0xb4,0x6c,0xee,0x6c,0xff,0x7e,0x68,0x4, 0xfc,0x7e, +0x78,0x5, 0x7a,0xe4,0x7a,0xb3,0x8, 0x8, 0x7a,0xb3,0x8, 0x9, 0x7a,0xb3,0x26,0xf6, +0x7a,0xb3,0x26,0xf8,0x7a,0xb3,0x26,0xf7,0x7a,0xb3,0x26,0xf9,0x6c,0xaa,0x80,0x5c, +0x12,0x87,0x9e,0xbd,0xa1,0x58,0x2, 0x7d,0x1a,0xbd,0xa3,0x8, 0x2, 0x7d,0x3a,0x7e, +0xd0,0x2, 0xac,0xda,0x7f,0x47,0x2d,0x96,0xb, 0x4a,0xa0,0xbd,0xab,0x58,0x2, 0x7d, +0xba,0x12,0x87,0x9e,0x7e,0x87,0x2a,0x53,0x7e,0x94,0x0, 0x3, 0xad,0x98,0xbd,0xa9, +0x8, 0x2, 0xb, 0xe0,0x12,0x87,0x9e,0xbe,0xa4,0x0, 0x64,0x8, 0xb, 0x7e,0xb3,0x26, +0xf7,0x4, 0x7a,0xb3,0x26,0xf7,0x80,0x12,0x12,0x87,0x9e,0xbe,0xa4,0xff,0x9c,0x58, +0x9, 0x7e,0xb3,0x26,0xf9,0x4, 0x7a,0xb3,0x26,0xf9,0xb, 0xa0,0x7e,0xb3,0x2a,0x74, +0xbc,0xba,0x38,0x9c,0x7a,0x17,0x7, 0xfe,0x7a,0x37,0x8, 0x2, 0x7a,0xe3,0x8, 0x9, +0x7a,0xb7,0x8, 0x6, 0x12,0x86,0x3f,0x2d,0xd5,0x6c,0xaa,0x80,0x53,0x12,0x87,0xab, +0xbd,0xb0,0x58,0x2, 0x7d,0xb, 0xbd,0xb2,0x8, 0x2, 0x7d,0x2b,0x7e,0xd0,0x2, 0xac, +0xda,0x7f,0x56,0x2d,0xb6,0xb, 0x5a,0x90,0x7e,0xa7,0x2a,0x51,0x7e,0xb4,0x0, 0x3, +0xad,0xba,0xbd,0x9b,0x8, 0x2, 0xb, 0xf0,0x12,0x87,0xab,0xbe,0xb4,0x0, 0x64,0x8, +0xb, 0x7e,0xb3,0x26,0xf6,0x4, 0x7a,0xb3,0x26,0xf6,0x80,0x12,0x12,0x87,0xab,0xbe, +0xb4,0xff,0x9c,0x58,0x9, 0x7e,0xb3,0x26,0xf8,0x4, 0x7a,0xb3,0x26,0xf8,0xb, 0xa0, +0x12,0x5f,0xf8,0x38,0xa8,0x7a,0x7, 0x7, 0xfc,0x7a,0x27,0x8, 0x0, 0x7a,0xf3,0x8, +0x8, 0x12,0x86,0x3f,0x2d,0xf5,0x6c,0xaa,0x80,0x14,0x7e,0xf0,0x2, 0xac,0xfa,0x7f, +0x67,0x2d,0xd7,0xb, 0x6a,0xd0,0xbd,0xd4,0x58,0x2, 0x7d,0x4d,0xb, 0xa0,0x12,0x5f, +0xf8,0x38,0xe7,0x7a,0x47,0x8, 0x4, 0xbd,0x1, 0x58,0x2, 0x7d,0x10,0x7a,0x17,0x7, +0xf8,0xbd,0x32,0x58,0x2, 0x7d,0x32,0x7a,0x37,0x7, 0xfa,0xda,0x3b,0x22,0x7e,0xd0, +0x2, 0xac,0xda,0x7f,0x46,0x2d,0x96,0xb, 0x4a,0xa0,0x22,0x7e,0xd0,0x2, 0xac,0xda, +0x7f,0x56,0x2d,0xb6,0xb, 0x5a,0xb0,0x22,0x7e,0xf4,0x7f,0xff,0x9f,0x44,0xe4,0x22, +0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d,0x35,0x22,0xa, 0x17,0x6d,0x0, 0x7f,0x14,0x12, +0x1f,0x58,0x7d,0x73,0x12,0x21,0xa, 0x7d,0xe3,0x7d,0x3f,0x2, 0x21,0xa, 0x74,0x2, +0xac,0xbc,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0xe0,0x9d,0xe7,0x7f,0x15,0x2d,0x35,0x1b, +0x1a,0xe0,0x22,0x7e,0x24,0x0, 0x7d,0x12,0x90,0xd, 0x50,0x8, 0x7e,0x27,0x2a,0x4f, +0x1e,0x24,0x1e,0x24,0x7d,0x32,0x22,0x7e,0xb3,0x38,0x7, 0x70,0x2e,0x7e,0x73,0x37, +0xea,0xbe,0x70,0x10,0x40,0x2, 0x6c,0x77,0x7e,0xb3,0x38,0x32,0xb4,0x1, 0x3, 0x7e, +0x70,0x6, 0xa, 0x37,0x2e,0x34,0xf, 0xf0,0x12,0x88,0x5c,0x7c,0xab,0xe5,0x5e,0xa, +0x3b,0x2e,0x37,0x39,0x84,0x7a,0x37,0x39,0x84,0x80,0xc, 0x7e,0xa3,0x37,0xeb,0xbe, +0xa0,0x7f,0x28,0x3, 0x7e,0xa0,0x7f,0x7c,0xba,0x2, 0x88,0x4c,0x75,0x5e,0x0, 0x7a, +0xb3,0x3a,0x7, 0xc2,0x1c,0x22,0x2d,0x32,0x2e,0x34,0x20,0xfa,0x7a,0x71,0x82,0x7a, +0x61,0x83,0xe4,0x93,0x22,0x7c,0x7b,0x12,0x89,0x30,0x9, 0xa2,0x27,0x72,0x7c,0xb7, +0x54,0x7, 0xa, 0x3b,0x2e,0x34,0x0, 0x5e,0x12,0x88,0x5c,0x5c,0xba,0x22,0x6c,0x0, +0x6c,0x11,0x80,0x13,0x7c,0xb1,0x12,0x88,0x65,0x60,0xa, 0x12,0x88,0xd8,0x40,0x5, +0x7e,0x0, 0x1, 0x80,0xa, 0xb, 0x10,0x7e,0x73,0x28,0x84,0xbc,0x71,0x38,0xe5,0x7c, +0xb0,0x6c,0x77,0x12,0x88,0xf1,0xbe,0x0, 0x1, 0x68,0xb, 0x7c,0xb0,0x7e,0x70,0x1, +0x12,0x88,0xf1,0xb4,0x1, 0x21,0x6c,0x11,0x80,0x15,0x7c,0xb1,0x12,0x88,0x65,0x60, +0xc, 0x12,0x88,0xd8,0x50,0x7, 0x7c,0xb1,0x6c,0x77,0x12,0x73,0x2e,0xb, 0x10,0x7e, +0x3, 0x28,0x84,0xbc,0x1, 0x38,0xe3,0x22,0x74,0x2, 0xac,0xb1,0x9, 0x25,0x26,0xfa, +0x9, 0x35,0x26,0xfb,0x7c,0xb2,0x7c,0x73,0x7c,0xb7,0xb4,0x18,0x2, 0xd3,0x22,0xc3, +0x22,0x7c,0xab,0xa5,0xbf,0x0, 0xc, 0x7e,0xb3,0x37,0x61,0x7a,0xb3,0x37,0x62,0x7a, +0xa3,0x37,0x61,0x7e,0xb3,0x37,0x62,0x60,0x4, 0x74,0x8, 0x80,0xd, 0x7e,0xb3,0x28, +0x84,0x70,0xb, 0x7e,0xb3,0x37,0x63,0x60,0x5, 0x14,0x7a,0xb3,0x37,0x63,0x7e,0x73, +0x37,0x63,0xbe,0x70,0x0, 0x28,0x3, 0x74,0x1, 0x22,0xe4,0x22,0x7c,0xa5,0x7c,0xb7, +0xc4,0x23,0x54,0x1f,0xa, 0x2b,0x22,0x7e,0x8, 0x26,0x86,0x7e,0x34,0x0, 0x3, 0xe4, +0x12,0x20,0xe8,0x7e,0x8, 0x26,0x89,0x12,0x8f,0xc7,0x7a,0xb3,0x26,0x83,0x7a,0xb3, +0x26,0x84,0x7a,0xb3,0x26,0x85,0x7a,0xb3,0x26,0xf0,0x7a,0xb3,0x26,0xf1,0x7a,0xb3, +0x26,0xf2,0x7e,0x18,0x26,0x6f,0x12,0x8a,0x92,0x6c,0x55,0x12,0x89,0xf9,0x7a,0xb3, +0x26,0x85,0x7e,0x18,0x26,0x5b,0x12,0x8a,0xa2,0x6c,0x55,0x12,0x89,0xf9,0x7a,0xb3, +0x26,0x84,0x6c,0x77,0x80,0x14,0x12,0x8a,0x7e,0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb, +0x12,0x89,0x2c,0x2e,0x24,0x26,0x86,0x12,0x8a,0x87,0x7e,0x63,0x26,0x84,0xbc,0x67, +0x38,0xe4,0x6c,0x77,0x80,0x14,0x12,0x8a,0x7e,0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb, +0x12,0x89,0x2c,0x2e,0x24,0x26,0x89,0x12,0x8a,0x87,0x7e,0xa3,0x26,0x85,0xbc,0xa7, +0x38,0xe4,0x7e,0xb3,0x26,0x84,0xa4,0x7a,0xb3,0x26,0x83,0x7e,0x18,0x26,0xe6,0x12, +0x8a,0x92,0x7e,0x50,0x1, 0x12,0x89,0xf9,0x7a,0xb3,0x26,0xf2,0x7e,0x18,0x26,0xdc, +0x12,0x8a,0xa2,0x7e,0x50,0x1, 0x12,0x89,0xf9,0x7c,0xab,0x7a,0xa3,0x26,0xf1,0x7e, +0xb3,0x26,0xf2,0xa4,0x7a,0xb3,0x26,0xf0,0x22,0xca,0x69,0xca,0xf8,0x7c,0x4b,0x6c, +0xaa,0x6d,0xff,0x6c,0xff,0x80,0x6c,0x7e,0xd0,0x2, 0xac,0xdf,0x7f,0x60,0x2d,0xd6, +0xb, 0x6a,0xe0,0x4c,0x55,0x68,0x6, 0x6e,0xe4,0xff,0xff,0xb, 0xe4,0xbd,0x3e,0x58, +0x50,0x4c,0xff,0x78,0x8, 0x6d,0x44,0x69,0xf0,0x0, 0x2, 0x80,0x1b,0x7c,0xb4,0x14, +0xbc,0xbf,0x7f,0x56,0x78,0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x6d,0xff,0x80,0x9, 0x1b, +0xb5,0xb, 0x5a,0x40,0x69,0xf6,0x0, 0x2, 0x4c,0x55,0x68,0xc, 0x6e,0x44,0xff,0xff, +0xb, 0x44,0x6e,0xf4,0xff,0xff,0xb, 0xf4,0xbd,0x4e,0x58,0x15,0xbd,0xfe,0x18,0x11, +0xa, 0xba,0x7e,0x6d,0x24,0x2d,0xdb,0x7a,0x6b,0xf0,0xb, 0xa0,0xbe,0xa0,0xa, 0x50, +0x6, 0xb, 0xf0,0xbc,0x4f,0x38,0x90,0x7c,0xba,0xda,0xf8,0xda,0x69,0x22,0x7c,0xb7, +0x54,0x7, 0x7e,0x24,0x0, 0x1, 0x22,0x7e,0x29,0x60,0x4c,0x6a,0x7a,0x29,0x60,0xb, +0x70,0x22,0x7a,0x1d,0x24,0x7e,0xf, 0x6, 0xf8,0x7e,0xb3,0x2a,0x6e,0x7e,0x37,0x2a, +0x53,0x22,0x7a,0x1d,0x24,0x7e,0xa3,0x2a,0x6e,0x74,0x2, 0xa4,0x7e,0xf, 0x6, 0xf8, +0x2d,0x15,0x7e,0xb3,0x2a,0x6d,0x7e,0x37,0x2a,0x51,0x22,0x7c,0x2b,0x7e,0xb3,0x1f, +0x33,0xbc,0x2b,0x68,0x50,0x12,0x8b,0x1a,0x7c,0x3b,0x7c,0xb2,0x12,0x8b,0x1a,0x7c, +0xab,0xbe,0x30,0xff,0x68,0x3f,0xbe,0xa0,0xff,0x68,0x3a,0x7e,0x70,0x4, 0xac,0x73, +0xa, 0x2a,0x12,0x88,0x56,0xbe,0xb0,0x2, 0x38,0x2b,0xa, 0x2b,0x7e,0x34,0x2, 0xe0, +0xad,0x32,0x2e,0x34,0x16,0x93,0x6d,0x22,0x30,0x1b,0x3, 0x2, 0x4f,0x93,0x7e,0xb3, +0x2b,0x1d,0xb4,0x1, 0x10,0x12,0x57,0xe5,0xa4,0x7a,0x55,0x29,0x7e,0x8, 0xd, 0xc8, +0x74,0x1, 0x2, 0x4f,0x21,0x22,0x7e,0xb3,0x2b,0xf, 0x7c,0xab,0x6c,0x77,0x7e,0x50, +0x5, 0xac,0x57,0x9, 0x62,0x26,0x33,0xbc,0x6a,0x78,0x3, 0x7c,0xb7,0x22,0xb, 0x70, +0xbe,0x70,0x4, 0x40,0xe9,0x74,0xff,0x22,0x7c,0xab,0x12,0x8f,0xce,0xd2,0x1b,0x7c, +0xba,0x12,0x8a,0xbb,0xc2,0x1b,0x22,0xca,0x3b,0x7e,0xb3,0x2a,0x74,0xf5,0x27,0x12, +0x6c,0x57,0x50,0x2, 0x61,0xd9,0x6d,0x33,0x9e,0x37,0x2a,0x4f,0x3e,0x34,0xbe,0x37, +0x7, 0xf8,0x18,0x75,0x7e,0xb3,0x16,0x92,0x70,0x6f,0x7e,0xb3,0x28,0xa8,0xb4,0x1, +0x59,0x7e,0x77,0x2a,0x51,0x7e,0x67,0x2a,0x53,0x75,0x24,0x0, 0x80,0x47,0xe5,0x24, +0x12,0x88,0x65,0x60,0x3e,0x12,0x8b,0xdc,0x12,0x8f,0xe8,0x7e,0xb3,0x2a,0x3, 0xb4, +0x1, 0x9, 0xe5,0x26,0xb4,0x18,0x4, 0xe, 0x64,0xe, 0x74,0x7e,0xa1,0x26,0x74,0x2, +0xa4,0x49,0x35,0x4, 0xfc,0xbd,0x36,0x48,0xd, 0xe5,0x25,0xa, 0x2b,0xe5,0x27,0x12, +0x8b,0xe4,0xbd,0x37,0x58,0xd, 0xe5,0x24,0x6c,0x77,0x12,0x73,0x2e,0x12,0x8b,0xdc, +0x12,0x8f,0xa4,0x5, 0x24,0x12,0x8f,0xd6,0x38,0xb4,0x7e,0xb3,0x2a,0x68,0x70,0x9, +0x7e,0xb3,0x2a,0x6b,0x70,0x3, 0x12,0x9a,0x76,0xda,0x3b,0x22,0x7e,0x71,0x24,0x74, +0x2, 0xac,0x7b,0x22,0xa, 0x3b,0x2d,0x32,0x3e,0x34,0x49,0x33,0x4, 0xfc,0x22,0xca, +0xf8,0x7c,0xfb,0x6d,0xdd,0x7c,0xbf,0x12,0x98,0x93,0x7d,0xe3,0x7c,0xbf,0x12,0x6f, +0x6b,0x7d,0xf3,0x74,0x2, 0xac,0xbf,0x9, 0x95,0x26,0xfb,0x7c,0xbf,0x12,0x8f,0x82, +0x40,0x2, 0x81,0xc0,0x74,0x2, 0xac,0xbf,0x9, 0xa5,0x26,0xfa,0xbe,0xa0,0x0, 0x28, +0xa, 0x7c,0xba,0x14,0x7c,0x79,0x12,0x6d,0xcb,0x7d,0xd3,0x12,0x8c,0xce,0x58,0x6, +0x7c,0xba,0x4, 0x12,0x8f,0x67,0x7e,0x24,0x0, 0x2, 0x12,0x8f,0x5f,0xbe,0xa0,0x0, +0x28,0x4e,0x12,0x8c,0xce,0x58,0x49,0xbe,0x90,0x0, 0x28,0x44,0xbe,0x90,0x0, 0x28, +0x3f,0xbe,0xf4,0x0, 0xc8,0x8, 0x39,0x7d,0x3d,0x3e,0x34,0x3e,0x34,0xbd,0x3f,0x8, +0x2f,0x12,0x8c,0xc4,0xbe,0x34,0x1, 0x2c,0x8, 0x26,0xa, 0x2a,0x7e,0xb3,0x2a,0x74, +0x12,0x8b,0xe4,0xbe,0x34,0x1, 0x90,0x8, 0x17,0xbe,0xf4,0x1, 0x5e,0x58,0xd, 0x7e, +0x34,0x0, 0x3, 0xad,0x3e,0xbd,0x3f,0x8, 0x3, 0xe4,0x80,0x35,0x74,0x1, 0x80,0x31, +0xbe,0x90,0x18,0x78,0x2b,0xbe,0xf4,0x0, 0xc8,0x8, 0x25,0x12,0x8c,0xc4,0xbe,0x34, +0x0, 0xc8,0x8, 0x1c,0xa, 0x2a,0x7e,0x73,0x2a,0x74,0xa, 0x37,0x12,0x8b,0xe6,0xbe, +0x34,0x0, 0xc8,0x8, 0xb, 0x7e,0xb3,0x28,0x84,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x1, +0xe4,0xda,0xf8,0x22,0x7e,0x70,0x2, 0xac,0x79,0x49,0x33,0x4, 0xfc,0x22,0x7e,0xb3, +0x2a,0x6f,0xa, 0x3b,0x1b,0x34,0xa, 0xca,0xbd,0xc3,0x22,0x12,0xa2,0x3d,0x12,0x9a, +0xed,0x12,0x8b,0x47,0x12,0x99,0xd6,0x2, 0x8c,0xea,0xca,0x3b,0x12,0x75,0x4a,0x7e, +0xb3,0x28,0x84,0x60,0x6, 0x7e,0xb3,0x36,0xe2,0x60,0x9, 0xe4,0x7a,0xb3,0x36,0xe4, +0x7a,0xb3,0x36,0x69,0x7e,0xb3,0x36,0xe2,0x70,0x5d,0x6c,0x99,0x80,0x51,0x12,0x8d, +0x92,0x9, 0xf5,0x26,0xfb,0x7c,0xb9,0x12,0x8f,0x82,0x40,0x41,0x6c,0xee,0x80,0x35, +0x74,0x2, 0xac,0xbe,0x9, 0xd5,0x36,0x6a,0x9, 0xc5,0x36,0x6b,0xa, 0x28,0xa, 0x3d, +0x12,0x8d,0x8a,0x78,0x1e,0xa, 0x2f,0xa, 0x3c,0x12,0x8d,0x8a,0x78,0x15,0x7c,0xb9, +0x12,0x6f,0x6b,0xbe,0x34,0x3, 0x20,0x58,0xa, 0x12,0x8f,0x58,0x7c,0xb8,0x7c,0x7f, +0x12,0x8f,0xac,0xb, 0xe0,0x7e,0x73,0x36,0xe4,0xbc,0x7e,0x38,0xc3,0xb, 0x90,0x7e, +0x73,0x28,0x84,0xbc,0x79,0x38,0xa7,0x7e,0x73,0x36,0x69,0x7a,0x73,0x36,0xe4,0xa, +0x37,0x3e,0x34,0xca,0x39,0x7e,0x18,0x36,0xa6,0x7e,0x8, 0x36,0x6a,0x12,0x20,0xc3, +0x1b,0xfd,0xe4,0x7a,0xb3,0x36,0xe2,0xda,0x3b,0x22,0x9d,0x32,0x12,0x21,0xa, 0x4d, +0x33,0x22,0x74,0x2, 0xac,0xb9,0x9, 0x85,0x26,0xfa,0x22,0xca,0x3b,0x7e,0xb3,0x2a, +0x6f,0xf5,0x26,0x7e,0xa3,0x2a,0x70,0x7e,0xb3,0x28,0x84,0xf5,0x24,0x70,0x2, 0xe1, +0x4c,0x7e,0x8, 0x1f,0x34,0x7e,0x34,0x3, 0xd4,0xe4,0x12,0x20,0xe8,0x7e,0x8, 0x23, +0x8, 0x7e,0x34,0x0, 0x23,0x12,0x20,0xe8,0x6c,0x99,0x80,0x5a,0x12,0x8f,0xde,0x9, +0xe3,0x26,0xfb,0x1a,0x68,0x1b,0x65,0x80,0x41,0xbe,0xd0,0x0, 0x48,0x3a,0xe5,0x26, +0xbc,0xbd,0x8, 0x34,0x74,0x1, 0x1a,0xcd,0x19,0xbc,0x23,0x8, 0x1a,0xce,0x1b,0xc5, +0x7d,0x3c,0x7c,0xf7,0x80,0x18,0xbe,0xf0,0x0, 0x48,0x11,0xbc,0xaf,0x8, 0xd, 0x74, +0x1, 0x12,0x8f,0x4f,0x1a,0xcf,0x2d,0xc3,0x19,0xbc,0x1f,0x34,0xb, 0xf0,0x1a,0x3e, +0xb, 0x35,0x1a,0xcf,0xbd,0xc3,0x8, 0xde,0xb, 0xd0,0x1a,0x38,0xb, 0x35,0x1a,0xcd, +0xbd,0xc3,0x8, 0xb5,0xb, 0x90,0xe5,0x24,0xbc,0xb9,0x38,0xa0,0x6c,0xdd,0x80,0x71, +0x1a,0xcd,0x9, 0xbc,0x23,0x8, 0x60,0x67,0x6d,0xdd,0x75,0x25,0x0, 0x7e,0xb3,0x2a, +0x6e,0xa, 0x2b,0x1a,0x3d,0xad,0x32,0x7d,0xc3,0x3e,0xc4,0x7e,0x7f,0x13,0x8a,0x6c, +0x99,0x80,0x16,0x12,0x8f,0x4f,0xa, 0xc9,0x2d,0xc3,0x9, 0xbc,0x1f,0x34,0x70,0x7, +0x7c,0xbd,0x12,0x8f,0x67,0x5, 0x25,0xb, 0x90,0xbc,0xa9,0x38,0xe6,0xe5,0x25,0x60, +0x2e,0xe5,0x25,0x1a,0x2b,0x12,0x8f,0x5f,0x6c,0xff,0x80,0x1f,0x12,0x8f,0x4f,0x1a, +0xcf,0x2d,0xc3,0x9, 0xbc,0x1f,0x34,0xb4,0x1, 0xf, 0x7c,0xbd,0x7c,0x7f,0x12,0x6f, +0x81,0xb, 0x1a,0xc0,0x9d,0xcd,0x1b,0x1a,0xc0,0xb, 0xf0,0xbc,0xaf,0x18,0xdd,0xb, +0xd0,0xe5,0x26,0xbc,0xbd,0x18,0x89,0x6c,0x99,0xe1,0x44,0x12,0x8d,0x92,0x9, 0xe5, +0x26,0xfb,0x7c,0xb8,0x7c,0x7e,0x12,0x6f,0x81,0x7f,0x71,0x4c,0x88,0x78,0xc, 0x12, +0x8f,0x78,0x2d,0x35,0x12,0x8f,0x6f,0x8, 0x62,0x80,0x51,0xe5,0x26,0x14,0xbc,0xb8, +0x78,0xc, 0x12,0x8f,0x78,0x9d,0x35,0x12,0x8f,0x6f,0x8, 0x4f,0x80,0x31,0xe5,0x26, +0xa, 0xcb,0x1b,0xc4,0x1a,0x58,0xbd,0x5c,0x58,0x41,0x7e,0xa3,0x2a,0x6e,0x7e,0x30, +0x2, 0xac,0x3a,0x7f,0x17,0x9d,0x31,0xb, 0x1a,0x30,0x74,0x2, 0xa4,0x7f,0x7, 0x2d, +0x15,0xb, 0xa, 0xc0,0xbd,0x3c,0x8, 0xd, 0xb, 0x7a,0x50,0xbd,0x35,0x8, 0x1c,0x1a, +0x58,0x1b,0x54,0x80,0xb, 0xb, 0x7a,0x50,0xbd,0xc5,0x8, 0xf, 0x1a,0x58,0xb, 0x54, +0x7c,0xab,0x7e,0x70,0x2, 0xac,0x79,0x19,0xa3,0x26,0xfa,0x12,0x8d,0x92,0x7c,0xb8, +0x7c,0x7e,0x12,0x6d,0xcb,0x7d,0xc3,0x7e,0x57,0x2a,0x5a,0xbd,0x5c,0x8, 0x3, 0x12, +0x8f,0x58,0xb, 0x90,0xe5,0x24,0xbc,0xb9,0x28,0x2, 0xc1,0xab,0xda,0x3b,0x22,0x1a, +0x2d,0x7e,0x34,0x0, 0x1c,0xad,0x32,0x22,0x7c,0xb9,0x6c,0x77,0x2, 0x73,0x2e,0x7d, +0x3d,0x12,0x1e,0xb9,0x7d,0xd3,0x22,0x7c,0x79,0x12,0x6d,0xcb,0x2d,0xd3,0x22,0xb, +0x1a,0xc0,0xb, 0x7a,0x50,0xbd,0xc5,0x22,0x7e,0xa3,0x2a,0x6e,0x74,0x2, 0xa4,0x7f, +0x17,0x22,0x7c,0x4b,0x74,0x2, 0xac,0xb4,0x9, 0x55,0x26,0xfa,0x9, 0x65,0x26,0xfb, +0x7e,0x73,0x28,0x8c,0xbc,0x75,0x78,0xa, 0x7e,0x73,0x28,0x8d,0xbc,0x76,0x78,0x2, +0xd3,0x22,0xc3,0x22,0x9, 0xb3,0x26,0xfa,0x9, 0x73,0x26,0xfb,0x7c,0x6b,0x7e,0xa3, +0x36,0x69,0x7e,0x50,0x2, 0xac,0x5a,0x19,0x62,0x36,0xa6,0x19,0x72,0x36,0xa7,0x7c, +0xba,0x4, 0x7a,0xb3,0x36,0x69,0x22,0x7e,0x34,0x0, 0x3, 0x2, 0x20,0xe8,0xa9,0xd1, +0xcb,0x74,0x1, 0x2, 0x0, 0xe, 0x7e,0x73,0x28,0x84,0xbe,0x71,0x24,0x22,0x7e,0x70, +0x2, 0xac,0x79,0x9, 0x83,0x26,0xfa,0x22,0x9, 0xb3,0x26,0xfa,0xf5,0x25,0x9, 0xb3, +0x26,0xfb,0xf5,0x26,0x22,0x12,0x90,0xd, 0x50,0x12,0x7e,0x37,0x2b,0x7, 0xbe,0x34, +0x1, 0x2c,0x28,0x8, 0x7e,0x34,0x1, 0x2c,0x7a,0x37,0x2b,0x7, 0x22,0xc2,0x0, 0x12, +0x90,0x35,0x68,0x7, 0x7e,0xb3,0x2a,0x68,0xb4,0x1, 0x17,0x7e,0xb3,0x37,0x71,0x70, +0x11,0x12,0x44,0xc4,0x40,0xa, 0x7e,0x37,0x28,0x8a,0xbe,0x34,0x1, 0x90,0x58,0x2, +0xd2,0x0, 0xa2,0x0, 0x22,0x7e,0xb3,0x2a,0x6b,0xbe,0xb0,0x1, 0x22,0x7e,0xb3,0x39, +0x87,0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x7a,0xb3,0x39,0x87,0x22,0x7f,0x20,0xc2, +0x1, 0x7e,0x2b,0x60,0x29,0x72,0x0, 0x2, 0x9c,0x76,0x1a,0x37,0x12,0x21,0xa, 0x7c, +0x27,0x29,0x72,0x0, 0x1, 0x29,0x32,0x0, 0x3, 0x9c,0x37,0x1a,0x33,0x12,0x21,0xa, +0x7c,0x37,0x1a,0x23,0x1a,0x32,0x9d,0x32,0x12,0x21,0xa, 0x7c,0x67,0x7c,0x72,0xbc, +0x32,0x58,0x2, 0x7c,0x73,0xbe,0x60,0x5, 0x18,0x5, 0xbe,0x70,0x6, 0x58,0x8, 0x7e, +0x37,0x38,0xf4,0x4d,0x33,0x68,0x2, 0xd2,0x1, 0xa2,0x1, 0x22,0xca,0x3b,0x7c,0xc7, +0x7c,0xfb,0x7f,0x40,0x6d,0xbb,0x7e,0xa3,0x2a,0x6d,0x7e,0x73,0x2a,0x6e,0x4c,0xcc, +0x78,0x5, 0x7e,0xc0,0x1, 0x80,0xd, 0x7c,0xb7,0x14,0xbc,0xbc,0x78,0x6, 0xa, 0x6c, +0x1b,0x65,0x7c,0xcd,0x4c,0xff,0x78,0x5, 0x7e,0xf0,0x1, 0x80,0xb, 0x7c,0xba,0x14, +0xbc,0xbf,0x78,0x4, 0xa, 0x7f,0x1b,0x75,0x7f,0x4, 0x7e,0x34,0x0, 0x6, 0xe4,0x12, +0x20,0xe8,0x7e,0x73,0x2a,0x6d,0xa, 0x37,0x1b,0x34,0x7a,0x4b,0x70,0x7e,0x73,0x2a, +0x6e,0xa, 0x37,0x1b,0x34,0x39,0x74,0x0, 0x1, 0x7c,0xec,0x80,0x1d,0x75,0x24,0x0, +0x7c,0xdf,0x80,0xb, 0x12,0x6d,0xd2,0x70,0xb, 0x5, 0x24,0xb, 0xb4,0x1b,0xd0,0xbe, +0xd0,0x0, 0x58,0xf0,0xe5,0x24,0x60,0x7, 0x1b,0xe0,0xbe,0xe0,0x0, 0x58,0xde,0x7c, +0xec,0x80,0x26,0x75,0x24,0x0, 0x1a,0xaf,0xb, 0xa4,0x7d,0x3a,0x7c,0xd7,0x80,0xb, +0x12,0x6d,0xd2,0x70,0xe, 0x5, 0x24,0xb, 0xb4,0xb, 0xd0,0x7e,0x73,0x2a,0x6d,0xbc, +0x7d,0x18,0xed,0xe5,0x24,0x60,0x7, 0x1b,0xe0,0xbe,0xe0,0x0, 0x58,0xd5,0x12,0x91, +0xb2,0x80,0x1d,0x75,0x24,0x0, 0x7c,0xdf,0x80,0xb, 0x12,0x6d,0xd2,0x70,0xb, 0x5, +0x24,0xb, 0xb4,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0xf0,0xe5,0x24,0x60,0xa, 0xb, 0xe0, +0x7e,0x73,0x2a,0x6e,0xbc,0x7e,0x18,0xdb,0x12,0x91,0xb2,0x80,0x22,0x75,0x24,0x0, +0x1a,0x6f,0xb, 0x64,0x80,0xb, 0x12,0x6d,0xd2,0x70,0xe, 0x5, 0x24,0xb, 0xb4,0xb, +0xd0,0x7e,0x73,0x2a,0x6d,0xbc,0x7d,0x18,0xed,0xe5,0x24,0x60,0xa, 0xb, 0xe0,0x7e, +0x73,0x2a,0x6e,0xbc,0x7e,0x18,0xd6,0x7d,0x3b,0x39,0x74,0x0, 0x5, 0x7d,0x3b,0xda, +0x3b,0x22,0x1a,0xac,0xb, 0xa4,0x7d,0x3a,0x7c,0xe7,0x22,0x7f,0x60,0x7e,0x6b,0xa0, +0xbe,0xa0,0xa, 0x50,0x1b,0x7e,0x14,0x0, 0x6, 0xca,0x19,0x74,0x6, 0xa4,0x7f,0x6, +0x2d,0x15,0xb, 0x14,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x6b,0xb0,0x4, 0x7a,0x6b,0xb0, +0x22,0xe4,0x7e,0x63,0x2a,0x6e,0x7e,0x73,0x2a,0x6d,0xac,0x76,0x7d,0x13,0x1e,0x14, +0x7e,0x27,0x28,0x88,0x2e,0x27,0x28,0x86,0xbd,0x21,0x38,0xa, 0x1e,0x34,0x1e,0x34, +0xbe,0x37,0x28,0x86,0x50,0x14,0x7e,0xa3,0x26,0xf7,0xbe,0xa0,0xc, 0x28,0xb, 0x7e, +0xa3,0x26,0xf6,0xbe,0xa0,0x7, 0x28,0x2, 0x74,0x1, 0x22,0x7e,0xa3,0x2a,0x3, 0xbe, +0xa0,0x0, 0x38,0x2f,0xbe,0xa3,0x2a,0x2, 0x50,0x19,0x7e,0xb3,0x2a,0xc, 0xbe,0xb3, +0x35,0x56,0x28,0x14,0x7e,0xb3,0x35,0x56,0x4, 0x7a,0xb3,0x35,0x56,0x7a,0xa3,0x2a, +0x2, 0x80,0x5, 0xe4,0x7a,0xb3,0x35,0x56,0x7e,0xb3,0x2a,0x2, 0x70,0x5, 0xe4,0x7a, +0xb3,0x2a,0xb, 0x22,0x12,0x92,0x5a,0x2, 0x92,0x1b,0x7e,0xb3,0x2a,0x2, 0x70,0x29, +0x12,0x92,0x93,0x28,0x24,0x7e,0xb3,0x34,0xdb,0x70,0x18,0x12,0x92,0x9b,0x7e,0x73, +0x2a,0x3, 0x7a,0x73,0x2a,0x2, 0x74,0x1, 0x7a,0xb3,0x2a,0x9, 0x7e,0xb3,0x34,0xdb, +0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x34,0xdb,0x22,0xe4,0x7a,0xb3,0x34,0xdb,0x7a,0xb3, +0x2a,0x9, 0x22,0x7e,0x73,0x2a,0x3, 0xbe,0x70,0x0, 0x22,0x7e,0x34,0x0, 0x3c,0xca, +0x39,0x7e,0x18,0x36,0xe9,0x7e,0x8, 0x37,0x25,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x73, +0x28,0x94,0x7a,0x73,0x36,0xe8,0x7a,0x73,0x28,0x93,0x22,0x12,0x92,0x93,0x28,0x8, +0x7e,0xb3,0x28,0x84,0x70,0x2, 0xf5,0x1b,0x7e,0xb3,0x28,0x84,0x70,0x18,0xe5,0x1b, +0xbe,0xb0,0xfa,0x50,0x2, 0x5, 0x1b,0xe5,0x1b,0xbe,0xb0,0x5, 0x40,0x8, 0xe4,0x7a, +0xb3,0x32,0x2c,0x75,0x1b,0xfa,0x22,0xca,0x79,0xc2,0x0, 0x7e,0xf0,0x3, 0x12,0x92, +0xbb,0x7e,0xe3,0x2a,0x3, 0x7e,0x34,0x1f,0x34,0x7a,0x37,0x31,0xee,0x12,0x97,0xcc, +0x38,0x2, 0x61,0xc0,0x12,0x93,0xf5,0x92,0xd, 0x12,0x93,0xc9,0x7c,0xbf,0x12,0xae, +0x2d,0x4c,0xee,0x68,0xe, 0x7e,0xa3,0x31,0xcb,0x4c,0xaa,0x78,0xa, 0x7e,0xb3,0x31, +0xcc,0x70,0x4, 0xd2,0x0, 0x80,0x25,0xbe,0xe0,0x1, 0x28,0xb, 0xe5,0x1c,0xbe,0xb0, +0x8, 0x28,0x4, 0xd2,0x0, 0x80,0x15,0xd2,0x0, 0x7e,0xb3,0x28,0x84,0xbc,0xbe,0x78, +0xb, 0x20,0xd, 0x8, 0x4c,0xaa,0x78,0x4, 0x6c,0xff,0xc2,0x0, 0x20,0x0, 0x5, 0x7c, +0xbf,0x12,0xae,0x2d,0x7e,0x8, 0x31,0xd0,0x12,0xb4,0x20,0x7a,0xb3,0x31,0xcf,0xbe, +0xb3,0x28,0x84,0x50,0x3a,0x7e,0x33,0x31,0xcf,0x80,0x26,0x7e,0x70,0x2, 0xac,0x73, +0x9, 0x23,0x31,0xf0,0x9, 0x13,0x31,0xf1,0x2e,0x37,0x31,0xee,0xb, 0x38,0x50,0x7e, +0x93,0x2a,0x6e,0xac,0x92,0xa, 0x31,0x2d,0x43,0x12,0xc6,0x79,0x7c,0xb3,0x12,0x76, +0xfb,0x7c,0x3, 0x1b,0x30,0xa5,0xb8,0x0, 0xd2,0x74,0x1, 0x7a,0xb3,0x31,0xcd,0x7e, +0xa3,0x31,0xcf,0x7a,0xa3,0x28,0x84,0x74,0x2, 0xa4,0xca,0x59,0x7e,0x18,0x31,0xf0, +0x7e,0x8, 0x26,0xfa,0x12,0x20,0xc3,0x1b,0xfd,0x12,0x46,0xb9,0xf5,0x1c,0x80,0x6, +0x75,0x1c,0x64,0x12,0x97,0xde,0xda,0x79,0x22,0x6c,0xaa,0x12,0x97,0xea,0x12,0x93, +0xeb,0x54,0xfe,0x12,0x93,0xe8,0x54,0x7, 0x12,0x93,0xe8,0x54,0xfb,0x7a,0xb, 0xb0, +0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xe4,0x22,0x7a,0xb, 0xb0,0x7f,0x1, 0x2e,0x14,0x0, +0x5, 0x7e,0xb, 0xb0,0x22,0xca,0x3b,0x7e,0xe3,0x28,0x84,0x6c,0xdd,0x6c,0xff,0x74, +0x6, 0xac,0xbd,0x12,0x97,0x6e,0x30,0xe0,0x37,0x6c,0xcc,0x80,0x27,0x12,0x97,0xd4, +0x7a,0xb3,0x1f,0x70,0x9, 0xa3,0x26,0xfb,0x7a,0xa3,0x1f,0x71,0x7f,0x7, 0x12,0x94, +0x4b,0x50,0xf, 0x7f,0x7, 0x7e,0xb3,0x1f,0x71,0x6c,0x77,0x12,0x94,0x4e,0x50,0x2, +0xb, 0xf0,0xb, 0xc0,0xbc,0xec,0x38,0xd5,0xbe,0xf0,0x2, 0x40,0x3, 0xd3,0x80,0x8, +0xb, 0xd0,0xbe,0xd0,0x1e,0x40,0xb6,0xc3,0xda,0x3b,0x22,0x7e,0x70,0x1, 0x7c,0x87, +0x7c,0x9b,0x29,0xa0,0x0, 0x3, 0x29,0x60,0x0, 0x1, 0x7e,0x70,0x1, 0xbe,0x80,0x1, +0x78,0x7, 0x29,0xa0,0x0, 0x2, 0x7e,0xb, 0x60,0xa, 0x7, 0xa, 0x29,0x2d,0x2, 0xa, +0x16,0xbd,0x1, 0x48,0xc, 0xa, 0x17,0xa, 0x3a,0x2d,0x31,0xbd,0x23,0x18,0x2, 0xd3, +0x22,0xc3,0x22,0xca,0x3b,0x7c,0xf5,0x7c,0xe6,0x7c,0xd7,0x7c,0xcb,0x75,0x54,0x0, +0x7e,0xa1,0x54,0x74,0x6, 0xa4,0x12,0x97,0x6e,0x30,0xe1,0x2e,0x7f,0x7, 0x7c,0xbc, +0x12,0x96,0xab,0x50,0x25,0x7f,0x7, 0x7c,0xbe,0x12,0x94,0x4b,0x50,0x1c,0x7f,0x7, +0x7c,0xbd,0x6c,0x77,0x12,0x94,0x4e,0x50,0x11,0x7f,0x7, 0x7c,0xbf,0x6c,0x77,0x12, +0x94,0x4e,0x50,0x6, 0x29,0xb7,0x0, 0x4, 0x80,0xa, 0x5, 0x54,0xe5,0x54,0xbe,0xb0, +0x1e,0x40,0xbd,0xe4,0xda,0x3b,0x22,0xca,0x79,0x7f,0x70,0x7e,0xb4,0xff,0xff,0x6c, +0xee,0xc2,0x1, 0xc2,0x2, 0x29,0x67,0x0, 0x2, 0x7e,0x7b,0x70,0xbc,0x76,0x78,0xe, +0x29,0x67,0x0, 0x3, 0x29,0x77,0x0, 0x1, 0xbc,0x76,0x78,0x2, 0xd2,0x2, 0x6c,0xff, +0x12,0x96,0xbb,0x6d,0xaa,0x29,0xb6,0x0, 0x5, 0x20,0xe1,0x2, 0xa1,0x91,0x7f,0x6, +0x7e,0x7b,0xb0,0x12,0x96,0xab,0x50,0x2d,0x7f,0x6, 0x29,0xb7,0x0, 0x2, 0x12,0x96, +0xab,0x50,0x22,0x7f,0x6, 0x29,0xb7,0x0, 0x1, 0x6c,0x77,0x12,0x94,0x4e,0x50,0x15, +0x7f,0x6, 0x29,0xb7,0x0, 0x3, 0x6c,0x77,0x12,0x94,0x4e,0x50,0x8, 0x7c,0xef,0xd2, +0x1, 0x6d,0xbb,0x80,0x55,0x7e,0x6b,0x70,0xa, 0x27,0x7e,0x7b,0x70,0x12,0x96,0xa4, +0x2d,0xa3,0x29,0x76,0x0, 0x2, 0xa, 0x27,0x29,0x77,0x0, 0x2, 0x12,0x96,0xa4,0x2d, +0xa3,0x29,0x76,0x0, 0x1, 0xa, 0x27,0x29,0x77,0x0, 0x1, 0x12,0x96,0xa4,0x2d,0xa3, +0x29,0x76,0x0, 0x3, 0xa, 0x27,0x29,0x77,0x0, 0x3, 0x12,0x96,0xa4,0x2d,0xa3,0xbd, +0xab,0x50,0x4, 0x7d,0xba,0x7c,0xef,0xbe,0xa4,0x0, 0x4, 0x38,0x4, 0xd2,0x1, 0x80, +0x9, 0xb, 0xf0,0xbe,0xf0,0x1e,0x50,0x2, 0xa1,0x0, 0x20,0x1, 0xb, 0x20,0x2, 0x8, +0xbe,0xb4,0x0, 0x8, 0x50,0x2, 0xd2,0x1, 0x20,0x1, 0x2, 0xc1,0x52,0x74,0x6, 0xac, +0xbe,0x12,0x96,0xbf,0x29,0x76,0x0, 0x5, 0x7c,0xb7,0xc4,0x23,0x54,0x1f,0xbe,0xb0, +0x1f,0x50,0x16,0x7f,0x6, 0x2e,0x14,0x0, 0x5, 0x7c,0x67,0x2e,0x60,0x8, 0x5e,0x60, +0xf8,0x5e,0x70,0x7, 0x4c,0x76,0x7a,0xb, 0x70,0x20,0x2, 0x11,0x29,0xb6,0x0, 0x4, +0xbe,0xb0,0xfa,0x50,0x8, 0x7f,0x16,0xb, 0x36,0x4, 0x7a,0x1b,0xb0,0x29,0x67,0x0, +0x3, 0x29,0x76,0x0, 0x3, 0xbc,0x76,0x28,0x6, 0x29,0x76,0x0, 0x3, 0x80,0x4, 0x29, +0x77,0x0, 0x3, 0x39,0x76,0x0, 0x3, 0x29,0x67,0x0, 0x2, 0x29,0x76,0x0, 0x2, 0xbc, +0x76,0x28,0x6, 0x29,0x76,0x0, 0x2, 0x80,0x4, 0x29,0x77,0x0, 0x2, 0x39,0x76,0x0, +0x2, 0x29,0x67,0x0, 0x1, 0x29,0x76,0x0, 0x1, 0xbc,0x76,0x50,0x6, 0x29,0x76,0x0, +0x1, 0x80,0x4, 0x29,0x77,0x0, 0x1, 0x39,0x76,0x0, 0x1, 0x7e,0x7b,0x60,0x7e,0x6b, +0x70,0xbc,0x76,0x50,0x5, 0x7e,0x6b,0x70,0x80,0x3, 0x7e,0x7b,0x70,0x7a,0x6b,0x70, +0x80,0x31,0x6c,0xff,0x74,0x6, 0xac,0xbf,0x9, 0xb5,0x32,0x32,0x30,0xe1,0x7, 0xb, +0xf0,0xbe,0xf0,0x1e,0x40,0xee,0xbe,0xf0,0x1e,0x50,0x33,0x74,0x1, 0x39,0xb7,0x0, +0x4, 0x12,0x96,0xbb,0x7e,0x34,0x0, 0x6, 0xca,0x39,0x7f,0x17,0x7f,0x6, 0x12,0x20, +0xc3,0x1b,0xfd,0x12,0x96,0xb1,0x44,0x1, 0x7a,0x1b,0xb0,0x12,0x96,0xb1,0x44,0x2, +0x7a,0x1b,0xb0,0x30,0x2, 0x8, 0x12,0x96,0xb1,0x44,0x4, 0x7a,0x1b,0xb0,0xda,0x79, +0x22,0x7e,0x39,0x70,0xa, 0x37,0x9d,0x32,0x2, 0x21,0xa, 0x7e,0x70,0x1, 0x2, 0x94, +0x4e,0x7f,0x16,0x2e,0x34,0x0, 0x5, 0x7e,0x1b,0xb0,0x22,0x74,0x6, 0xac,0xbf,0x7d, +0xd5,0x2e,0xd4,0x32,0x2d,0x6d,0xcc,0x22,0xca,0xf8,0x7e,0xd4,0x0, 0x7, 0x7e,0xb3, +0x28,0x84,0x70,0x8, 0xf5,0x5a,0xc2,0xa, 0xc2,0xb, 0x80,0x7d,0xbe,0xb0,0x2, 0x38, +0x72,0xb4,0x2, 0x28,0x7e,0x73,0x26,0xfc,0xa, 0x27,0x7e,0x73,0x26,0xfa,0x12,0x96, +0xa4,0xbe,0x34,0x0, 0x5, 0x58,0x15,0x7e,0x73,0x26,0xfd,0xa, 0x27,0x7e,0x73,0x26, +0xfb,0x12,0x96,0xa4,0xbe,0x34,0x0, 0x5, 0x58,0x2, 0x80,0x5a,0x6c,0xff,0x80,0x3c, +0x7c,0xbf,0x12,0x97,0x7b,0x1a,0x4b,0x7c,0xbf,0x12,0x6f,0x6b,0x7d,0xc3,0xbe,0xc4, +0x2, 0x58,0x58,0x4, 0x7e,0xd4,0x0, 0x6, 0x7d,0x5d,0x3e,0x54,0xbd,0x54,0x58,0x4, +0xd2,0xb, 0x80,0xa, 0x7d,0x5d,0xe, 0x54,0xbd,0x54,0x48,0x2, 0xc2,0xb, 0x20,0xb, +0x4, 0xbd,0xd4,0x58,0x5, 0x75,0x5a,0x28,0x80,0xf, 0xb, 0xf0,0x12,0x73,0x6d,0x38, +0xbf,0x80,0x6, 0xe5,0x5a,0x24,0xfb,0xf5,0x5a,0xe5,0x5a,0xbe,0xb0,0x0, 0x8, 0x6, +0xd2,0xa, 0x15,0x5a,0x80,0x5, 0x75,0x5a,0x0, 0xc2,0xa, 0xda,0xf8,0x22,0x7d,0xf5, +0x2e,0xf4,0x32,0x2d,0x6d,0xee,0x29,0xb7,0x0, 0x5, 0x22,0xca,0xf8,0x7c,0xfb,0x7e, +0x70,0x2, 0x12,0x99,0xd, 0x7f,0x71,0x7c,0xbf,0x12,0x6f,0x6b,0x12,0x97,0xc5,0x7f, +0x17,0x12,0x1f,0x58,0x7c,0xb7,0xda,0xf8,0x22,0xca,0xd8,0xca,0x79,0x6c,0xff,0x6c, +0xee,0x80,0xf, 0x7c,0xbe,0x12,0x97,0x7b,0x7c,0xdb,0xbc,0xfd,0x58,0x2, 0x7c,0xfd, +0xb, 0xe0,0x12,0x97,0xbe,0x38,0xec,0x7c,0xbf,0xda,0x79,0xda,0xd8,0x22,0x7e,0x73, +0x28,0x84,0xbc,0x7e,0x22,0x7d,0x13,0x1a,0x2, 0x1a,0x0, 0x22,0x7e,0x73,0x28,0x84, +0xbe,0x70,0x1, 0x22,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x26,0xfa,0x22,0x7e,0x8, +0x32,0x2d,0x7e,0x34,0x0, 0xb4,0xe4,0x2, 0x20,0xe8,0x7e,0x70,0x6, 0xac,0x7a,0x2e, +0x34,0x32,0x2d,0x6d,0x22,0x22,0x7e,0xa3,0x2a,0x2, 0x7e,0xb3,0x38,0x32,0x70,0x5, +0x7a,0xb3,0x34,0xc4,0x22,0xe4,0x7a,0xb3,0x34,0x88,0x6c,0x77,0x80,0x78,0x7e,0x90, +0x9, 0xac,0x97,0x9, 0x64,0x29,0xc, 0x7c,0xb6,0x54,0xf, 0xa, 0x2b,0x9, 0x52,0x29, +0xbc,0x4c,0x55,0x68,0xa, 0xa5,0xbd,0x2, 0x5b,0x7e,0xb3,0x34,0xc4,0x70,0x55,0x49, +0x14,0x29,0x8, 0xbe,0x14,0x0, 0x64,0x28,0x10,0xbe,0x14,0x3, 0xd4,0x50,0xa, 0x49, +0x14,0x29,0xa, 0xbe,0x14,0x0, 0x64,0x38,0x3b,0x7e,0xb3,0x34,0x88,0xbc,0xb7,0x40, +0x5, 0x4, 0x7a,0xb3,0x34,0x88,0x7e,0xb3,0x2a,0x2, 0x14,0x7a,0xb3,0x2a,0x2, 0x7e, +0x40,0xff,0x7e,0x30,0x9, 0xac,0x37,0x19,0x41,0x29,0xc, 0x74,0x3, 0xa, 0x46,0x19, +0xb4,0x29,0xbc,0x19,0xb4,0x29,0xc6,0xa5,0xbd,0x2, 0x9, 0x7e,0xb3,0x2a,0x3, 0x14, +0x7a,0xb3,0x2a,0x3, 0xb, 0x70,0xbc,0xa7,0x38,0x84,0x7e,0x73,0x38,0x32,0x7a,0x73, +0x34,0xc4,0x22,0xca,0x79,0x7c,0x8b,0x6c,0xaa,0x9f,0x77,0x12,0x99,0xc8,0x1a,0x79, +0x1b,0x74,0x80,0x41,0x1a,0x38,0x1b,0x34,0x7c,0xe7,0x80,0x2d,0xbc,0x9f,0x78,0x4, +0xbc,0x8e,0x68,0x23,0xbe,0xf0,0x0, 0x48,0x1e,0x7e,0xb3,0x2a,0x6f,0xbc,0xbf,0x8, +0x16,0xbe,0xe0,0x0, 0x48,0x11,0x7e,0xb3,0x2a,0x70,0xbc,0xbe,0x8, 0x9, 0x7c,0xbf, +0x7c,0x7e,0x12,0x99,0x3, 0xb, 0xa0,0xb, 0xe0,0x1a,0x28,0xb, 0x24,0x1a,0x3e,0xbd, +0x32,0x8, 0xc9,0xb, 0xf0,0x1a,0x29,0xb, 0x24,0x1a,0x3f,0xbd,0x32,0x8, 0xb5,0x4c, +0xaa,0x78,0x4, 0x6d,0x33,0x80,0x9, 0xa, 0x1a,0x6d,0x0, 0x7f,0x17,0x12,0x1f,0x58, +0xda,0x79,0x22,0x12,0x6d,0xcb,0x1a,0x26,0x1a,0x24,0x2f,0x71,0x22,0xca,0x79,0x7c, +0xa7,0x7c,0x8b,0x7e,0xb3,0x2a,0x6f,0x7a,0xb3,0x1f,0x9a,0x7e,0xb3,0x2a,0x70,0x7a, +0xb3,0x1f,0x9b,0x12,0x99,0xc8,0x9f,0x77,0x1a,0x3a,0x1a,0x79,0x9d,0x73,0x21,0xb5, +0x7a,0xf1,0x58,0xbe,0xf0,0x0, 0x58,0xe, 0x1a,0x3f,0x1a,0x29,0x9d,0x23,0x1a,0x39, +0x2d,0x32,0x7c,0xb7,0xf5,0x58,0x7e,0xb3,0x1f,0x9a,0xbc,0xbf,0x18,0xe, 0x1a,0x39, +0x1a,0x2f,0x9d,0x23,0x1a,0x39,0x9d,0x32,0x7c,0xb7,0xf5,0x58,0x1a,0x2a,0x1a,0x38, +0x9d,0x32,0x7c,0xb7,0xf5,0x57,0x80,0x3d,0x85,0x57,0x59,0xe5,0x57,0xbe,0xb0,0x0, +0x58,0x10,0xe5,0x57,0x1a,0x3b,0x1a,0x28,0x9d,0x23,0x1a,0x38,0x2d,0x32,0x7c,0xb7, +0xf5,0x59,0x7e,0xb3,0x1f,0x9b,0xbe,0xb1,0x57,0x18,0x10,0x1a,0x38,0xe5,0x57,0x1a, +0x2b,0x9d,0x23,0x1a,0x38,0x9d,0x32,0x7c,0xb7,0xf5,0x59,0xe5,0x58,0x7e,0x71,0x59, +0x12,0x99,0x3, 0x5, 0x57,0x1a,0x3a,0x1a,0x28,0x2d,0x23,0xe5,0x57,0x1a,0x3b,0xbd, +0x32,0x8, 0xb5,0xb, 0xf0,0x1a,0x3a,0x1a,0x29,0x2d,0x23,0x1a,0x3f,0xbd,0x32,0x18, +0x2, 0x21,0x30,0x7f,0x17,0xda,0x79,0x22,0x7e,0x70,0x2, 0xac,0x78,0x9, 0x93,0x26, +0xfa,0x9, 0x83,0x26,0xfb,0x22,0xca,0xd8,0xca,0x79,0x7e,0xf4,0x3, 0x20,0x7d,0x7f, +0x12,0x9a,0xc7,0x50,0x2, 0x41,0x6a,0x7a,0xf5,0x2a,0x7e,0xb3,0x28,0xa8,0xb4,0x1, +0x4, 0x7e,0x74,0x4, 0xb0,0x7e,0x37,0x28,0x8a,0xbe,0x34,0x4, 0x4c,0x8, 0x6b,0x6c, +0xdd,0x80,0x5f,0xc2,0x0, 0x7c,0xbd,0x12,0x6f,0x6b,0x7a,0x35,0x26,0x7c,0xbd,0x7e, +0x70,0x1, 0x12,0x99,0xd, 0x7a,0x35,0x24,0x9e,0x35,0x26,0x7a,0x35,0x24,0x7e,0x35, +0x26,0x3e,0x34,0x3e,0x34,0x12,0x9a,0x6f,0x7a,0x35,0x28,0xbe,0x75,0x28,0x58,0x3, +0x7a,0x75,0x28,0x7e,0x35,0x28,0xbe,0x35,0x24,0x8, 0xa, 0x7e,0x35,0x2a,0xbe,0x35, +0x26,0x8, 0x2, 0xd2,0x0, 0x7c,0xbd,0x12,0x8f,0x82,0x50,0x2, 0xc2,0x0, 0x30,0x0, +0xf, 0x7c,0xbd,0x6c,0x77,0x12,0x73,0x2e,0x7e,0x70,0x2, 0xac,0x7d,0x12,0x8f,0xa4, +0xb, 0xd0,0x7e,0x73,0x28,0x84,0xbc,0x7d,0x38,0x99,0xda,0x79,0xda,0xd8,0x22,0x7e, +0x24,0x0, 0x2, 0x2, 0x1e,0xb9,0x7e,0xa0,0x1, 0x7e,0x37,0x2a,0x4f,0x12,0x9a,0xbf, +0x28,0x35,0x6d,0x22,0x9d,0x23,0xbe,0x27,0x7, 0xf8,0x58,0x2b,0x12,0x9a,0x6f,0xbe, +0x37,0x7, 0xfa,0x8, 0x22,0xe4,0x7a,0xb3,0x28,0x84,0x7e,0xb3,0x2a,0x3, 0x70,0x17, +0x7e,0xb3,0x38,0x9, 0xb4,0x1, 0x10,0x6c,0xaa,0x5, 0x5b,0xe5,0x5b,0xbe,0xb0,0x10, +0x28,0x5, 0xd2,0x15,0x75,0x5b,0x0, 0x4c,0xaa,0x68,0x3, 0x75,0x5b,0x0, 0x22,0x7e, +0xb3,0x28,0x84,0xbe,0xb0,0x0, 0x22,0x6c,0x99,0x6c,0x88,0x80,0xf, 0x7c,0xb8,0x12, +0x6f,0x6b,0xbe,0x34,0x1, 0xf4,0x8, 0x2, 0xb, 0x90,0xb, 0x80,0x7e,0x73,0x28,0x84, +0xbc,0x78,0x38,0xe9,0xbe,0x90,0x1, 0x38,0x2, 0xc3,0x22,0xd3,0x22,0xca,0x3b,0x7e, +0x77,0x2a,0x5c,0x12,0x9b,0x83,0x7d,0x63,0x3e,0x34,0x3e,0x34,0x7e,0xe4,0x0, 0xa, +0x12,0x9b,0x7b,0x7e,0xb3,0x28,0xa8,0x60,0xf, 0x7e,0x37,0x36,0xe5,0xbd,0x36,0x48, +0x7, 0x3e,0x34,0x3e,0x34,0x12,0x9b,0x7b,0xbe,0x64,0x4, 0x4c,0x8, 0xf, 0x12,0x9a, +0xc7,0x50,0x6, 0x7e,0xb3,0x28,0xa8,0x60,0x4, 0x74,0xa, 0x80,0x13,0x7e,0xb3,0x28, +0xa8,0x60,0xc, 0x7e,0xb3,0x36,0xe3,0xbe,0xb0,0x0, 0x28,0x8, 0x14,0x80,0x1, 0xe4, +0x7a,0xb3,0x36,0xe3,0x7e,0xe7,0x2a,0x5c,0x7d,0x3e,0x12,0x46,0xab,0x7e,0x53,0x36, +0xe3,0xbe,0x50,0x0, 0x28,0x12,0xbd,0x3f,0x58,0x4, 0x7d,0xf3,0x80,0x6, 0xbd,0xef, +0x8, 0x2, 0x7d,0xfe,0x7a,0xf7,0x2a,0x5c,0x12,0x97,0xcc,0x28,0x3, 0x12,0x75,0x21, +0x7a,0x67,0x36,0xe5,0x7a,0x77,0x2a,0x5c,0xda,0x3b,0x22,0x7d,0x2e,0x12,0x1e,0xb9, +0x7d,0xf3,0x22,0xca,0x3b,0x6d,0x44,0x7e,0xf3,0x28,0x84,0x6c,0xee,0x80,0x24,0x7c, +0xbe,0x12,0x88,0x65,0x60,0x1b,0x74,0x2, 0xac,0xbe,0x9, 0xd5,0x26,0xfa,0x9, 0xc5, +0x26,0xfb,0x7c,0xbd,0x7c,0x7c,0x12,0x6d,0xcb,0x7d,0xf3,0xbd,0x4f,0x58,0x2, 0x7d, +0x4f,0xb, 0xe0,0xbc,0xfe,0x38,0xd8,0x7d,0x34,0xda,0x3b,0x22,0xca,0x79,0x6c,0xff, +0x9f,0x77,0x7f,0x67,0x6d,0xbb,0x7e,0xa3,0x2a,0x70,0x7e,0xe3,0x2a,0x6f,0x7e,0xa7, +0x28,0x97,0x7e,0x8, 0x1f,0x34,0x7e,0x34,0x0, 0x1c,0xe4,0x12,0x20,0xe8,0x7e,0x8, +0x1f,0x50,0x7e,0x34,0x0, 0x1c,0x12,0x20,0xe8,0x6c,0x99,0x80,0x41,0x7e,0x50,0x2, +0xac,0x59,0x49,0x32,0x5, 0x7a,0xbe,0x34,0x0, 0xfa,0x8, 0x12,0x49,0x12,0x4, 0xfc, +0xbd,0x1a,0x58,0xa, 0x74,0x1, 0xa, 0x19,0x19,0xb1,0x1f,0x34,0x80,0x1e,0xbe,0x34, +0x0, 0xfa,0x8, 0x18,0x49,0x32,0x4, 0xfc,0xbe,0x34,0x0, 0xfa,0x8, 0xe, 0xbd,0x3b, +0x8, 0x2, 0x7d,0xb3,0x74,0x1, 0xa, 0x39,0x19,0xb3,0x1f,0x50,0xb, 0x90,0xbc,0xa9, +0x38,0xbb,0x6c,0x99,0x80,0x27,0xa, 0xa9,0x9, 0xba,0x1f,0x34,0xb4,0x1, 0x1c,0x6c, +0x88,0x80,0x14,0x7c,0xb8,0x7c,0x79,0x12,0x6d,0xcb,0x12,0x21,0xa, 0xbe,0x34,0x0, +0xfa,0x8, 0x2, 0xb, 0xf0,0xb, 0x80,0xbc,0xe8,0x38,0xe8,0xb, 0x90,0xbc,0xa9,0x38, +0xd5,0xbe,0xf0,0x1, 0x28,0x52,0xbe,0xb4,0x3, 0xe8,0x8, 0x4, 0x74,0x1, 0x80,0x49, +0x6c,0x99,0x80,0x21,0xa, 0x39,0x9, 0xb3,0x1f,0x50,0xb4,0x1, 0x16,0x7e,0x70,0x2, +0xac,0x79,0x49,0x13,0x5, 0x7a,0x1a,0x2, 0x1a,0x0, 0x2f,0x60,0x49,0x33,0x4, 0xfc, +0x12,0x99,0x6, 0xb, 0x90,0xbc,0xa9,0x38,0xdb,0x74,0x2, 0x7f,0x16,0x1e,0x34,0xe, +0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7e,0x14,0x0, 0x5, 0x12,0x1e,0xfc, +0xbf,0x71,0x8, 0x4, 0x74,0x1, 0x80,0x1, 0xe4,0xda,0x79,0x22,0xca,0x3b,0x6c,0xaa, +0xc2,0x0, 0x7e,0x97,0x28,0x99,0x7e,0x87,0x28,0x97,0x7e,0xb3,0x28,0xa5,0x14,0x68, +0x19,0x14,0x68,0x1e,0x24,0xc2,0x68,0x8, 0x24,0xfb,0x68,0xe, 0x24,0x45,0x78,0x26, +0x7e,0xe3,0x2a,0x6e,0x7e,0xd3,0x2a,0x6d,0x80,0x20,0x6c,0xee,0x7e,0xd3,0x2a,0x6e, +0x80,0x18,0x6c,0xee,0x7e,0xb3,0x2a,0x6d,0xa, 0x2b,0x7e,0xb3,0x2a,0x6e,0xa, 0x3b, +0x2d,0x32,0x7c,0xd7,0x80,0x4, 0x6c,0xee,0x6c,0xdd,0x6c,0xff,0x80,0xf, 0x12,0x9e, +0x3a,0x6d,0x33,0x9d,0x39,0xbd,0x23,0x58,0x2, 0xb, 0xa0,0xb, 0xf0,0xbc,0xdf,0x38, +0xed,0x4c,0xaa,0x78,0x3c,0x7e,0xb3,0x26,0x85,0x70,0x25,0x7e,0xb3,0x26,0x84,0x70, +0x1f,0x6c,0xff,0x80,0x15,0x12,0x9e,0x3a,0xbd,0x29,0x8, 0xc, 0x49,0x33,0x4, 0xfc, +0xbd,0x38,0x58,0x4, 0xd2,0x0, 0x80,0x19,0xb, 0xf0,0xbc,0xdf,0x38,0xe7,0x80,0x11, +0x12,0x9b,0xbc,0xa, 0x8b,0x4d,0x88,0x68,0x8, 0x12,0x76,0xe0,0x28,0x3, 0x12,0x9e, +0x2d,0x6c,0xcc,0x12,0x76,0xe0,0x38,0x5, 0x12,0x9e,0x47,0x28,0x69,0x7e,0xb3,0x28, +0xa7,0xb4,0x1, 0x9, 0x7e,0xb3,0x28,0xaa,0xbe,0xb0,0x1, 0x68,0x59,0x7e,0xb3,0x28, +0xa8,0xb4,0x1, 0x52,0x6c,0xff,0x80,0x1d,0x7e,0x70,0x2, 0xac,0x7f,0x9, 0xa3,0x26, +0xfa,0x9, 0x93,0x26,0xfb,0x12,0x6d,0xc7,0xbe,0x34,0x0, 0xc8,0x8, 0x5, 0x7e,0xc0, +0x1, 0x80,0xa, 0xb, 0xf0,0x7e,0xb3,0x28,0x84,0xbc,0xbf,0x38,0xdb,0x6c,0xff,0x80, +0x1d,0x7e,0x70,0x2, 0xac,0x7f,0x9, 0xa3,0x27,0x36,0x9, 0x93,0x27,0x37,0x12,0x6d, +0xc7,0xbe,0x34,0xff,0x38,0x58,0x5, 0x7e,0xc0,0x1, 0x80,0xa, 0xb, 0xf0,0x7e,0xb3, +0x28,0x85,0xbc,0xbf,0x38,0xdb,0x4c,0xcc,0x78,0x29,0x6c,0xff,0x80,0x21,0xa, 0x3f, +0xa, 0x2e,0x2d,0x23,0x3e,0x24,0x49,0x32,0x5, 0x7a,0xbd,0x39,0x8, 0xf, 0x49,0x82, +0x4, 0xfc,0x3e,0x84,0xbd,0x38,0x8, 0x5, 0x7e,0xc0,0x1, 0x80,0x6, 0xb, 0xf0,0xbc, +0xdf,0x38,0xdb,0x30,0x0, 0x15,0x7e,0xb3,0x3a,0xc, 0x4, 0x7a,0xb3,0x3a,0xc, 0x7e, +0x73,0x3a,0xc, 0xbe,0x70,0xa, 0x28,0x3, 0x12,0x9e,0x2d,0x4c,0xcc,0x78,0xb, 0x7e, +0xb3,0x28,0xa8,0x60,0x2, 0xd2,0x19,0x12,0x9e,0x4f,0xda,0x3b,0x22,0x74,0xa, 0x7a, +0xb3,0x3a,0xc, 0x74,0x1, 0x7a,0xb3,0x28,0xa8,0x22,0xa, 0x2f,0xa, 0x3e,0x2d,0x32, +0x3e,0x34,0x49,0x23,0x5, 0x7a,0x22,0x7e,0x73,0x28,0x85,0xbe,0x70,0x0, 0x22,0xe4, +0x7a,0xb3,0x28,0xa8,0x7a,0xb3,0x3a,0xc, 0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0x7e, +0xf0,0xa, 0x6c,0x11,0x80,0x21,0x7e,0x0, 0xff,0x74,0x9, 0xac,0xb1,0x19,0x5, 0x1f, +0x38,0x7e,0x34,0x7f,0xff,0x74,0x9, 0xac,0xb1,0x59,0x35,0x1f,0x34,0x74,0x9, 0xac, +0xb1,0x59,0x35,0x1f,0x36,0xb, 0x10,0xbc,0xf1,0x38,0xdb,0xe4,0x6c,0x77,0x7c,0x6d, +0x12,0x9f,0xa2,0x7c,0x7d,0x7c,0x6f,0x12,0x9f,0xa2,0x6c,0x0, 0x80,0x39,0x6c,0xee, +0x80,0x16,0x74,0x9, 0xac,0xbe,0x9, 0x65,0x1f,0x38,0x74,0x9, 0xac,0xb0,0x9, 0x75, +0x28,0xb2,0xbc,0x76,0x68,0x6, 0xb, 0xe0,0xbc,0x1e,0x38,0xe6,0xbc,0x1e,0x78,0x15, +0x7e,0x70,0x9, 0xac,0x70,0x12,0x7f,0xa0,0xac,0x31,0x2e,0x14,0x1f,0x34,0x74,0x9, +0x12,0x1f,0x8c,0xb, 0x10,0xb, 0x0, 0xbc,0xf0,0x38,0xc3,0x74,0x9, 0xac,0xbf,0xca, +0x59,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x29,0x62,0x12,0x20,0xc3,0x1b,0xfd,0xda,0x79, +0xda,0xd8,0x22,0xca,0x3b,0x7c,0x46,0x7c,0xab,0x6c,0x66,0x7c,0x57,0xe1,0x84,0x7e, +0xf0,0x9, 0xac,0xf6,0x9, 0x87,0x29,0x66,0x7c,0x98,0x7e,0xd0,0x9, 0xac,0xd5,0x9, +0xb6,0x28,0xb2,0xbc,0xb9,0x78,0x6b,0xbe,0x90,0xff,0x68,0x66,0x12,0x9f,0x98,0x39, +0x87,0x0, 0x4, 0xa, 0xf9,0x9, 0xbf,0x29,0xbc,0x7e,0xf0,0x9, 0x70,0xc, 0xac,0xf5, +0x7d,0x97,0x2e,0x94,0x28,0xae,0x6d,0x88,0x80,0xa, 0xac,0xf6,0x7d,0x97,0x2e,0x94, +0x29,0x62,0x6d,0x88,0xb, 0x4a,0xd0,0x12,0x9f,0x98,0x1b,0x7a,0xd0,0x69,0xf4,0x0, +0x2, 0x7e,0xf0,0x9, 0xac,0xfa,0x7f,0x60,0x2d,0xd7,0x79,0xf6,0x0, 0x2, 0x7e,0xf0, +0x9, 0xac,0xf5,0x9, 0x87,0x28,0xb3,0x12,0x9f,0x98,0x39,0x87,0x0, 0x5, 0x7e,0xf0, +0x9, 0xac,0xf5,0x9, 0x87,0x28,0xb4,0x12,0x9f,0x98,0x39,0x87,0x0, 0x6, 0xb, 0xa0, +0x80,0x8, 0xb, 0x50,0xbc,0x45,0x28,0x2, 0xc1,0xff,0xb, 0x60,0xbe,0x60,0xa, 0x50, +0x2, 0xc1,0xfb,0x7c,0xba,0xda,0x3b,0x22,0x7e,0xf0,0x9, 0xac,0xfa,0x7f,0x70,0x2d, +0xf7,0x22,0x7e,0x8, 0x1f,0x34,0x12,0x9e,0xf3,0x7c,0x1b,0x22,0x7c,0xab,0x7e,0xb, +0xb0,0x60,0x3, 0xb4,0x2, 0x31,0xa, 0x4a,0x9, 0x74,0x34,0xb8,0xbe,0x73,0x34,0xc2, +0x50,0xe, 0x7d,0x24,0x2e,0x24,0x34,0xb8,0x7c,0xb7,0x4, 0x7a,0x29,0xb0,0xd3,0x22, +0xbe,0x73,0x34,0xc2,0x40,0x9, 0xbe,0x70,0xff,0x68,0x4, 0xe4,0x7a,0xb, 0xb0,0x74, +0xff,0x19,0xb4,0x34,0xb8,0x80,0x17,0xa, 0x3a,0x9, 0xb3,0x34,0xb8,0xbe,0xb0,0xff, +0x68,0x7, 0xe4,0x19,0xb3,0x34,0xb8,0xd3,0x22,0xe4,0x19,0xb3,0x34,0xb8,0xc3,0x22, +0xca,0xf8,0x7c,0xfb,0x7d,0xf3,0x7e,0x17,0x2a,0x62,0xbd,0x13,0x38,0x6, 0x7e,0x34, +0x1, 0x0, 0x80,0x15,0x6d,0x22,0x7c,0x56,0x7c,0x67,0x6c,0x77,0x12,0x1f,0x5, 0xbe, +0x34,0x0, 0x10,0x50,0x4, 0x7e,0x34,0x0, 0x10,0x74,0x2, 0xac,0xbf,0x49,0x25,0x34, +0xc6,0xbd,0x2f,0x28,0x6, 0x49,0x35,0x34,0xa0,0x80,0x4, 0x59,0x35,0x34,0xa0,0x59, +0xf5,0x34,0xc6,0xbe,0x34,0x1, 0x0, 0x28,0x4, 0x7e,0x34,0x1, 0x0, 0xda,0xf8,0x22, +0xca,0x69,0xca,0xf8,0x7e,0xa3,0x2a,0x2, 0x7e,0x8, 0x29,0xbc,0x4c,0xaa,0x78,0x5, +0x12,0x24,0x66,0x21,0x9d,0x6c,0x99,0x7e,0x70,0x9, 0xac,0x79,0x9, 0x83,0x29,0xc, +0xbe,0x80,0xff,0x78,0x2, 0x21,0x94,0xa, 0x28,0x9, 0xb2,0x34,0x8c,0x7a,0xb3,0x34, +0x89,0x9, 0xb2,0x34,0x96,0x7a,0xb3,0x34,0x8a,0x7f,0x60,0x2d,0xd2,0x7e,0x6b,0xf0, +0xbe,0xf0,0x2, 0x68,0x2, 0x21,0x57,0x12,0xa1,0xac,0x49,0x33,0x29,0x8, 0x12,0xa1, +0xb6,0x7e,0x70,0x4, 0xac,0x78,0x49,0x23,0x35,0x59,0x12,0xa1,0xa2,0x9d,0x32,0x12, +0x21,0xa, 0x7d,0xe3,0x7e,0x73,0x34,0x89,0xa, 0x27,0xbd,0x2f,0x28,0x55,0xbd,0x2e, +0x28,0x51,0x12,0xa1,0xac,0x7e,0xd0,0x9, 0xac,0xd9,0x59,0x26,0x29,0x8, 0x7e,0x50, +0x4, 0xac,0x58,0x49,0x22,0x35,0x59,0x7e,0xd0,0x9, 0xac,0xd9,0x59,0x26,0x29,0xa, +0xbe,0xa0,0x0, 0x28,0x2, 0x1b,0xa0,0x4c,0xaa,0x78,0x5c,0x7e,0xb3,0x34,0x8a,0x4, +0x7a,0xb3,0x34,0x8a,0x7e,0x63,0x34,0x8a,0xbe,0x60,0x32,0x40,0x4a,0x74,0x1e,0x7a, +0xb3,0x34,0x8a,0x7e,0xb3,0x34,0x89,0xbe,0xb0,0x6, 0x50,0x3b,0x4, 0x7a,0xb3,0x34, +0x89,0x80,0x34,0x7e,0x50,0x9, 0xac,0x59,0x49,0xb2,0x29,0x8, 0x7e,0xd0,0x4, 0xac, +0xd8,0x59,0xb6,0x35,0x57,0x49,0x22,0x29,0xa, 0x59,0x26,0x35,0x59,0xbe,0x70,0xa, +0x40,0x4, 0x74,0x6, 0x80,0x8, 0xbe,0x70,0x1, 0x28,0x7, 0x7c,0xb7,0x14,0x7a,0xb3, +0x34,0x89,0xe4,0x7a,0xb3,0x34,0x8a,0x7e,0xb3,0x34,0x89,0xa, 0x38,0x19,0xb3,0x34, +0x8c,0x7e,0xb3,0x34,0x8a,0x80,0x37,0x4c,0xff,0x78,0x1b,0x7e,0x70,0x9, 0xac,0x79, +0x49,0x33,0x29,0x8, 0x7e,0x50,0x4, 0xac,0x58,0x59,0x32,0x35,0x57,0x12,0xa1,0xa2, +0x59,0x32,0x35,0x59,0x80,0x1e,0x7e,0x6b,0xb0,0xb4,0x1, 0x18,0x7e,0xb3,0x2a,0x2, +0xbe,0xb0,0x0, 0x28,0xf, 0x74,0xa, 0xa, 0x38,0x19,0xb3,0x34,0x8c,0xe4,0xa, 0x38, +0x19,0xb3,0x34,0x96,0xb, 0x90,0xbe,0x90,0xa, 0x68,0x2, 0x1, 0x67,0xda,0xf8,0xda, +0x69,0x22,0x7e,0x70,0x9, 0xac,0x79,0x49,0x33,0x29,0xa, 0x22,0x7e,0x50,0x4, 0xac, +0x58,0x49,0x22,0x35,0x57,0x22,0x9d,0x32,0x12,0x21,0xa, 0x7d,0xf3,0x22,0xa2,0xa, +0x22,0xca,0x79,0x6c,0x88,0x80,0x6b,0x74,0x2, 0xac,0xb8,0x9, 0xf5,0x26,0xfa,0x9, +0x75,0x26,0xfb,0x7a,0x71,0x24,0x7c,0xbf,0x12,0x67,0xe2,0x50,0x53,0x6c,0xee,0x80, +0x4a,0xbc,0xe8,0x68,0x44,0x7e,0x70,0x2, 0xac,0x7e,0x12,0x8f,0xe8,0x6c,0x99,0x7e, +0xb3,0x2a,0x70,0x14,0xbe,0xb1,0x26,0x78,0x10,0xa, 0x2f,0xe5,0x25,0x12,0x44,0x5b, +0xbe,0x34,0x0, 0x1, 0x18,0x3, 0x7e,0x90,0x1, 0xbe,0x90,0x1, 0x78,0x1b,0x7c,0xbe, +0x12,0x6f,0x6b,0x7d,0xf3,0x7c,0xb8,0x12,0x6f,0x6b,0xbd,0x3f,0x8, 0x4, 0x7c,0xbe, +0x80,0x2, 0x7c,0xb8,0x6c,0x77,0x12,0x73,0x2e,0xb, 0xe0,0x12,0x97,0xbe,0x38,0xb1, +0xb, 0x80,0x7e,0x73,0x28,0x84,0xbc,0x78,0x38,0x8d,0xda,0x79,0x22,0xe4,0x7a,0xb3, +0x36,0x69,0x7e,0xb3,0x28,0x84,0x60,0x6, 0x7e,0xb3,0x36,0xe2,0x60,0x5, 0xe4,0x7a, +0xb3,0x36,0xe4,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x14,0x23,0x1, 0x7e,0x4, +0x0, 0xff,0x69,0x30,0x0, 0x2, 0xb, 0xa, 0x20,0x7a,0x1d,0x2c,0x7e,0x73,0x2a,0x6d, +0xa, 0x37,0x3e,0x34,0xca,0x39,0x7f,0x16,0x7f,0x5, 0x12,0x20,0xc3,0x1b,0xfd,0x6c, +0xdd,0x12,0x87,0xb8,0x7a,0xb3,0x1f,0x34,0x6c,0xcc,0x80,0x4a,0x12,0xa3,0x2f,0x40, +0x43,0x12,0xa3,0x25,0x50,0x3e,0x12,0x87,0xc0,0xb, 0x1a,0x10,0x7d,0x3f,0x12,0x21, +0xa, 0x7d,0x3, 0x7d,0x31,0x12,0x21,0xa, 0xbd,0x30,0x58,0x2, 0x7d,0xf1,0xbe,0x15, +0x2a,0x8, 0x5, 0x7e,0x15,0x2a,0x80,0xb, 0x6d,0x0, 0x9e,0x5, 0x2a,0xbd,0x1, 0x8, +0x2, 0x7d,0x10,0x7d,0x31,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1f,0x34,0x4, +0x7a,0xb3,0x1f,0x34,0xb, 0xc0,0x12,0x57,0x75,0x38,0xb1,0x7e,0x73,0x1f,0x34,0x4c, +0x77,0x68,0x36,0x12,0x87,0xc9,0xbd,0x3e,0x8, 0x2, 0x7d,0x7f,0xbe,0x75,0x2a,0x8, +0x5, 0x7e,0x75,0x2a,0x80,0xb, 0x6d,0xee,0x9e,0xe5,0x2a,0xbd,0xe7,0x8, 0x2, 0x7d, +0x7e,0x6c,0xcc,0x80,0xf, 0x12,0xa3,0x2f,0x40,0x8, 0x12,0xa3,0x25,0x50,0x3, 0x12, +0x87,0xde,0xb, 0xc0,0x12,0x57,0x75,0x38,0xec,0xb, 0xd0,0xbe,0xd0,0x3, 0x50,0x2, +0x41,0x81,0xda,0x3b,0x22,0x7c,0x1d,0x2e,0x10,0x2d,0xa5,0xe7,0xbc,0xab,0x22,0xa, +0xec,0x9, 0xae,0x2a,0xb9,0x7c,0x1d,0x2e,0x10,0x2c,0xa5,0xe7,0xbc,0xab,0x22,0xca, +0x79,0x7e,0xb3,0x3, 0xfd,0x60,0x5f,0x7e,0xb3,0x2a,0x68,0x60,0x59,0x7e,0xf3,0x2a, +0x6f,0x7e,0xe3,0x2a,0x70,0x7e,0x1f,0x13,0x8a,0x7a,0x1d,0x24,0x74,0x2, 0xac,0xbe, +0x2d,0x35,0x1b,0x35,0x6c,0xaa,0x80,0xf, 0xb, 0x1a,0x40,0x7e,0x30,0x2, 0xac,0x3a, +0x59,0x41,0x1f,0x34,0x12,0xa3,0xa9,0xbc,0xfa,0x38,0xed,0x7e,0x8, 0x1f,0x34,0x7c, +0xbf,0x12,0x5e,0xa9,0x74,0x2, 0xac,0xbe,0x7e,0x1d,0x24,0x2d,0x35,0x1b,0x35,0x6c, +0xaa,0x80,0xf, 0x7e,0x30,0x2, 0xac,0x3a,0x49,0x11,0x1f,0x34,0x1b,0x1a,0x10,0x12, +0xa3,0xa9,0xbc,0xfa,0x38,0xed,0xda,0x79,0x22,0x7e,0x30,0x2, 0xac,0x3e,0x2d,0x31, +0xb, 0xa0,0x22,0x7e,0x63,0x2a,0x6e,0xc2,0x16,0x6c,0x33,0x80,0x48,0x7c,0x96,0xac, +0x93,0x2e,0x44,0x0, 0x17,0x7d,0x4, 0xb, 0x4, 0x7d,0x54,0x3e,0x54,0x7e,0x7f,0x13, +0x8a,0x2d,0xf5,0xb, 0x7a,0x50,0xbe,0x57,0x2a,0x5a,0x8, 0x27,0x7c,0xb3,0x12,0x67, +0x50,0x50,0x20,0x7d,0x50,0x3e,0x54,0x7e,0x7f,0x13,0x8a,0x7f,0x67,0x2d,0xd5,0xb, +0x6a,0x20,0x7d,0x54,0x3e,0x54,0x2d,0xf5,0xb, 0x7a,0x50,0xbd,0x52,0x8, 0x4, 0xd2, +0x16,0x80,0xa, 0xb, 0x30,0x7e,0x73,0x2a,0x75,0xbc,0x73,0x38,0xb0,0x30,0x16,0x5, +0xd2,0x0, 0x2, 0x67,0xa3,0x22,0x7e,0xb3,0x2b,0x1d,0xb4,0x1, 0x31,0x12,0xa4,0x4f, +0x7e,0x1f,0x39,0xda,0x7a,0x37,0x24,0xfa,0x7e,0x34,0xd, 0xc8,0x7a,0x37,0x24,0xf6, +0x12,0xa4,0x56,0x12,0xa4,0x5f,0xe4,0x7a,0xb3,0x24,0xf5,0x7e,0x34,0x0, 0x20,0x7a, +0x37,0x24,0xfc,0x7a,0xb3,0x24,0xf4,0x7e,0x8, 0x24,0xf2,0x2, 0xd, 0x7, 0x22,0xa9, +0xd1,0xcb,0xe4,0x2, 0x0, 0xe, 0x7e,0x73,0x2a,0x6d,0x7a,0x73,0x24,0xf2,0x22,0x7e, +0x73,0x2a,0x6e,0x7a,0x73,0x24,0xf3,0x22,0x7e,0x43,0x2a,0x6e,0x7e,0x53,0x2a,0x6d, +0xac,0x54,0x7e,0x17,0x28,0xa1,0x12,0xa4,0x4f,0x6d,0x0, 0x80,0x37,0x7d,0x40,0x3e, +0x44,0x7e,0x7f,0x39,0xda,0x2d,0xf4,0xb, 0x7a,0x30,0xbd,0x13,0x58,0x10,0x7d,0xf4, +0x2e,0xf4,0x8, 0xa, 0xb, 0xf8,0x50,0x9d,0x51,0x1b,0xf8,0x50,0x80,0x14,0x6d,0x55, +0x9d,0x51,0xbd,0x53,0x8, 0xc, 0x2e,0x44,0x8, 0xa, 0xb, 0x48,0x50,0x2d,0x51,0x1b, +0x48,0x50,0xb, 0x4, 0xbd,0x20,0x38,0xc5,0x22,0xca,0x3b,0x7e,0xf3,0x2a,0x6e,0x7e, +0xe3,0x2a,0x6f,0x7e,0xd3,0x2a,0x70,0x6c,0xcc,0x80,0x13,0x7c,0x7c,0xac,0x7f,0x3e, +0x34,0x7e,0xf, 0x13,0x8a,0x2d,0x13,0x7c,0xbd,0x12,0x5e,0xa9,0xb, 0xc0,0xbc,0xec, +0x38,0xe9,0xda,0x3b,0x22,0x6c,0xaa,0x7e,0x30,0x4, 0xac,0x3a,0x7d,0xf1,0x2e,0xf4, +0x60,0xb1,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x20,0xbd,0x23,0x38,0xf, 0x2e,0x14,0x60, +0xb3,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20,0xbd,0x23,0x50,0x7, 0xb, 0xa0,0xbe,0xa0, +0x3, 0x40,0xd4,0x7c,0xba,0x22,0x12,0xa5,0x25,0xbe,0x34,0x4, 0xe2,0x28,0x3, 0xd2, +0x17,0x22,0xc2,0x17,0x22,0x6d,0x11,0xe4,0x12,0x0, 0x1e,0x6c,0xaa,0x80,0x5b,0x7e, +0x10,0x2, 0xac,0x1a,0x7e,0x7f,0x39,0xf4,0x2d,0xf0,0x69,0x27,0x1, 0x0, 0x69,0x37, +0x0, 0x80,0x9d,0x32,0x12,0x21,0xa, 0xbd,0x31,0x28,0x16,0x7e,0x70,0x2, 0xac,0x7a, +0x7e,0xf, 0x39,0xf4,0x2d,0x13,0x69,0x20,0x1, 0x0, 0x69,0x30,0x0, 0x80,0x12,0x4f, +0xcc,0x7e,0x10,0x2, 0xac,0x1a,0x7e,0x1f,0x39,0xf4,0x2d,0x30,0x69,0x1, 0x0, 0x80, +0xbe,0x4, 0x7f,0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff,0x69,0x1, 0x1, 0x0, 0xbe,0x4, +0x7f,0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xbc,0xba, +0x38,0x9d,0x7d,0x31,0x22,0x7e,0x60,0x4, 0x7e,0x27,0x3a,0x5, 0xbe,0x24,0x3, 0xe8, +0x28,0x3, 0x7e,0x60,0x8, 0x7e,0xb3,0x28,0xac,0xb4,0x1, 0x1a,0x7e,0x73,0x2f,0xaa, +0xbc,0x76,0x50,0xf, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0x6c,0x5a,0x7e,0xb3,0x2f,0xaa, +0x4, 0x80,0x4, 0xe4,0x80,0x1, 0xe4,0x7a,0xb3,0x2f,0xaa,0x7e,0xb3,0x28,0xad,0xb4, +0x1, 0x17,0x7e,0xa3,0x2f,0xab,0xbe,0xa0,0x5, 0x50,0xa, 0xe4,0x7a,0xb3,0x28,0xad, +0x7c,0xba,0x4, 0x80,0x5, 0x74,0x5, 0x80,0x1, 0xe4,0x7a,0xb3,0x2f,0xab,0x22,0x6c, +0xaa,0x80,0x26,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12,0x5, 0xf8,0x49,0x32,0x4, 0x0, +0x2d,0x31,0x59,0x32,0x5, 0xf8,0x30,0x6, 0xe, 0x49,0x12,0x4, 0x7e,0x49,0x32,0x6, +0x76,0x2d,0x31,0x59,0x32,0x6, 0x76,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xa, 0x3b,0x7e, +0xb3,0x2a,0x73,0xa, 0x2b,0x2d,0x23,0xa, 0x3a,0xbd,0x32,0x48,0xc6,0x22,0x74,0x2, +0x7a,0xb3,0x2f,0xa9,0x74,0x1, 0x7a,0xb3,0x28,0xac,0x2, 0x26,0x11,0xd2,0x0, 0x6c, +0xaa,0x6c,0x77,0x80,0x1f,0x7e,0x63,0x2a,0x6e,0xa, 0x16,0xa, 0x27,0x2d,0x21,0x7c, +0x65,0x7e,0x50,0x2, 0xac,0x56,0x49,0x22,0x5, 0x7a,0xbe,0x24,0xfe,0xc, 0x58,0x2, +0xb, 0xa0,0xb, 0x70,0x7e,0xb3,0x2a,0x6d,0xbc,0xb7,0x38,0xd9,0xa, 0x2b,0x1e,0x24, +0xa, 0x3a,0xbd,0x32,0x8, 0x2, 0xc2,0x0, 0xa2,0x0, 0x22,0x7e,0x63,0x2a,0x6f,0x7e, +0xa3,0x2a,0x70,0x7e,0x70,0x1, 0x80,0x15,0xa, 0x17,0x7e,0xb3,0x2a,0x6e,0xa, 0x2b, +0x2d,0x21,0x3e,0x24,0x12,0xa6,0xc6,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x16,0x1b, +0x14,0xa, 0x27,0xbd,0x21,0x48,0xe1,0x7e,0x70,0x2, 0x80,0xe, 0x7e,0x50,0x2, 0xac, +0x57,0x12,0xa6,0xc6,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x1a,0x1b,0x15,0xa, 0x27, +0xbd,0x21,0x48,0xe8,0xc3,0x22,0x49,0x22,0x4, 0xfc,0xbe,0x24,0xff,0x6, 0x22,0x7e, +0xb3,0x37,0x75,0xb4,0x1, 0x3, 0x2, 0xa7,0x26,0x7e,0xb3,0x37,0xdb,0x4, 0x7a,0xb3, +0x37,0xdb,0x7e,0xb3,0x37,0x69,0xb4,0x2, 0x18,0x7e,0xb3,0x37,0xda,0x4, 0x7a,0xb3, +0x37,0xda,0xb4,0x1, 0x6, 0x74,0x1, 0x7a,0xb3,0x37,0xdb,0x74,0x1, 0x7a,0xb3,0x37, +0x69,0x7e,0x73,0x37,0xda,0xbe,0x70,0x3, 0x40,0xf, 0x74,0x1, 0x7a,0xb3,0x37,0x75, +0x12,0xa7,0x26,0x12,0xa7,0xd0,0x12,0xa7,0x2d,0x7e,0x73,0x37,0xdb,0xbe,0x70,0xa, +0x28,0x3, 0x2, 0xa7,0x2d,0x22,0x74,0x2, 0x7a,0xb3,0x37,0x69,0x22,0xe4,0x7a,0xb3, +0x37,0xdb,0x7a,0xb3,0x37,0xda,0x22,0x7e,0x73,0x37,0x69,0x7a,0x73,0x37,0xdf,0x7e, +0x47,0x39,0xd7,0xbe,0x44,0x0, 0x64,0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x37,0x69,0xbe, +0x44,0x0, 0xc8,0x28,0x8, 0xe4,0x7a,0xb3,0x37,0x67,0x12,0xa7,0x26,0x7e,0x57,0x37, +0x6f,0xbd,0x54,0x50,0x4, 0x7a,0x47,0x37,0x6f,0x12,0xa7,0xc8,0x38,0xa, 0x12,0xa7, +0xc0,0x38,0x5, 0x12,0xa7,0xb8,0x28,0x34,0x12,0xa6,0xcf,0xbe,0x44,0x0, 0x32,0x50, +0x21,0x7e,0xb3,0x37,0x67,0x4, 0x7a,0xb3,0x37,0x67,0x7e,0x73,0x37,0x67,0xbe,0x70, +0x32,0x28,0x14,0x74,0x32,0x7a,0xb3,0x37,0x67,0x12,0x57,0xee,0x7a,0xb3,0x37,0xdc, +0x80,0x5, 0xe4,0x7a,0xb3,0x37,0x67,0x7d,0x34,0x2, 0xa8,0x35,0x2, 0xa7,0xaf,0x12, +0xa7,0x2d,0xe4,0x7a,0xb3,0x37,0x75,0x22,0x7e,0x73,0x26,0xf5,0xbe,0x70,0x0, 0x22, +0x7e,0x73,0x26,0xf4,0xbe,0x70,0x0, 0x22,0x7e,0x73,0x28,0x92,0xbe,0x70,0x0, 0x22, +0xe4,0x7a,0xb3,0x37,0x67,0x6d,0x33,0x6c,0xaa,0x7e,0x50,0xc, 0xac,0x5a,0x59,0x32, +0x37,0x7e,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xf0,0xe4,0x7a,0xb3,0x37,0x68,0x6d,0x33, +0x7a,0x37,0x37,0x6f,0x7a,0x37,0x37,0x64,0x22,0x7e,0x37,0x39,0xd3,0x12,0x7e,0x3c, +0x7a,0x37,0x37,0xdd,0x6c,0xaa,0x80,0x24,0xbe,0xa0,0x4, 0x50,0x27,0xa, 0x3a,0x9, +0x63,0x37,0x76,0xbe,0x60,0x4, 0x50,0x12,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x42,0x39, +0xcd,0x7e,0x70,0xc, 0xac,0x67,0x59,0x43,0x37,0x80,0xb, 0xa0,0x7e,0xb3,0x37,0x73, +0xbc,0xba,0x38,0xd4,0x22,0xbe,0x34,0x1, 0xf4,0x28,0xd, 0x7e,0x53,0x37,0xdc,0xbe, +0x50,0x8, 0x50,0x3f,0x74,0x8, 0x80,0x37,0xbe,0x34,0x1, 0x90,0x28,0xd, 0x7e,0x53, +0x37,0xdc,0xbe,0x50,0x6, 0x50,0x2c,0x74,0x6, 0x80,0x24,0xbe,0x34,0x1, 0x2c,0x28, +0xd, 0x7e,0x53,0x37,0xdc,0xbe,0x50,0x4, 0x50,0x19,0x74,0x4, 0x80,0x11,0xbe,0x34, +0x0, 0xc8,0x28,0xf, 0x7e,0x73,0x37,0xdc,0xbe,0x70,0x2, 0x50,0x6, 0x74,0x2, 0x7a, +0xb3,0x37,0xdc,0x7e,0xb3,0x37,0xdc,0xbe,0xb0,0x0, 0x28,0x19,0x14,0x7a,0xb3,0x37, +0xdc,0x74,0x1, 0x7a,0xb3,0x16,0x92,0x7e,0x73,0x37,0xdc,0xbe,0x70,0x4, 0x28,0x5, +0xe4,0x7a,0xb3,0x16,0x91,0x22,0x7c,0x3b,0x7e,0x44,0xff,0xff,0x6c,0x22,0x80,0x2a, +0x12,0xa9,0x1f,0x68,0x23,0x7e,0x70,0xc, 0xac,0x72,0x12,0xaa,0x2f,0x7d,0x23,0x7e, +0x70,0xc, 0xac,0x72,0x59,0x23,0x37,0x82,0x49,0x3, 0x37,0x82,0x49,0x23,0x37,0x7e, +0xbd,0x20,0x50,0x4, 0x59,0x3, 0x37,0x7e,0xb, 0x20,0xbc,0x32,0x50,0xd2,0x6c,0xaa, +0x6c,0x22,0x80,0x18,0x12,0xa9,0x1f,0x68,0x11,0x7e,0x70,0xc, 0xac,0x72,0x49,0x3, +0x37,0x7e,0xbd,0x4, 0x50,0x4, 0x7d,0x40,0x7c,0xa2,0xb, 0x20,0xbc,0x32,0x50,0xe4, +0x7e,0x37,0x37,0x64,0xbe,0x37,0x37,0xdd,0x50,0x8, 0x7e,0x37,0x37,0xdd,0x7a,0x37, +0x37,0x64,0x12,0xaa,0x25,0x4d,0x33,0x78,0x3, 0x7e,0xa0,0xff,0x7c,0xba,0x22,0x7e, +0x10,0x5, 0xac,0x12,0x9, 0xb0,0x26,0x33,0xbe,0xb3,0x2b,0xf, 0x22,0xca,0x79,0x7e, +0xf0,0xff,0x12,0xaa,0x96,0x7e,0xb3,0x37,0x6b,0xb4,0x1, 0x8, 0x12,0x6a,0xaf,0xe4, +0x7a,0xb3,0x37,0x6b,0x7e,0xb3,0x37,0x6a,0x60,0x4, 0x74,0xff,0x41,0x22,0x7e,0xb3, +0x37,0x69,0xb4,0x2, 0x2, 0x80,0x2, 0x41,0x16,0x12,0xa7,0xc8,0x38,0xc, 0x12,0xa7, +0xc0,0x38,0x7, 0x12,0xa7,0xb8,0x38,0x2, 0x41,0x16,0x74,0x3, 0x12,0xa8,0xa6,0x7c, +0xeb,0x7e,0xb3,0x37,0x68,0x4, 0x7a,0xb3,0x37,0x68,0x74,0x3, 0x12,0xa8,0xa6,0x7c, +0xab,0xbe,0xa0,0xff,0x68,0x23,0xbe,0xe0,0xff,0x68,0x1c,0x7e,0x30,0xc, 0xac,0x3e, +0x49,0x21,0x37,0x7e,0xbe,0x24,0x1, 0xf4,0x28,0xf, 0x12,0xaa,0x25,0x3e,0x34,0xbd, +0x23,0x28,0x6, 0x7c,0xea,0x80,0x2, 0x7c,0xea,0xbe,0xe0,0xff,0x78,0x11,0xe4,0x7a, +0xb3,0x37,0x68,0x7a,0xb3,0x37,0x69,0x7a,0xb3,0x37,0x75,0x74,0xff,0x80,0x63,0x7e, +0x73,0x37,0x68,0xbe,0x70,0x4, 0x28,0x4e,0x74,0xc, 0xac,0xbe,0x49,0x35,0x37,0x7e, +0xbe,0x34,0x1, 0xf4,0x50,0x37,0x7e,0x37,0x37,0x64,0xbe,0x34,0x1, 0x2c,0x38,0xa, +0x7e,0x37,0x37,0x6f,0xbe,0x34,0x1, 0x2c,0x28,0x23,0x74,0x5, 0xac,0xbe,0x9, 0x75, +0x26,0x33,0xbe,0x73,0x2b,0xf, 0x68,0x15,0x7c,0xfe,0xbe,0xf0,0x4, 0x50,0x8, 0x12, +0x8b,0x16,0xbe,0xb0,0x4, 0x40,0x6, 0x74,0x1, 0x7a,0xb3,0x37,0x6b,0xe4,0x7a,0xb3, +0x37,0x75,0x7a,0xb3,0x37,0x69,0xbe,0xf0,0xff,0x68,0x5, 0xe4,0x7a,0xb3,0x37,0x68, +0x7c,0xbf,0xda,0x79,0x22,0x7e,0x70,0xc, 0xac,0x7a,0x49,0x33,0x37,0x7e,0x22,0x49, +0x23,0x37,0x84,0x49,0x33,0x37,0x80,0x9d,0x32,0x2, 0x21,0xa, 0x6c,0xaa,0x7e,0x70, +0xc, 0xac,0x7a,0x12,0xaa,0x2f,0xbe,0x34,0x3, 0xe8,0x8, 0x5, 0x12,0xaa,0x88,0x80, +0x2f,0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x37,0x84,0x49,0x12,0x37,0x80,0xbd,0x13, +0x28,0xf, 0x7d,0x2, 0x2e,0x4, 0x37,0x84,0x7d,0x13,0xb, 0x15,0x1b,0x8, 0x10,0x80, +0xf, 0xbe,0x34,0x0, 0x2, 0x28,0x9, 0x2e,0x24,0x37,0x84,0x1b,0x35,0x1b,0x28,0x30, +0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xb7,0x22,0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x37, +0x80,0x59,0x32,0x37,0x84,0x22,0x7e,0xb3,0x37,0x6a,0xb4,0x1, 0x27,0x7e,0xb3,0x37, +0xe0,0x4, 0x7a,0xb3,0x37,0xe0,0x7e,0x73,0x37,0xe0,0xbe,0x70,0x3, 0x40,0x15,0x12, +0x57,0x9f,0x7e,0x73,0x37,0xe0,0xbe,0x70,0x6, 0x40,0x9, 0xe4,0x7a,0xb3,0x37,0xe0, +0x7a,0xb3,0x37,0x6a,0x22,0x12,0x4f,0xee,0x12,0xaa,0xfe,0x7e,0x8, 0x2a,0x88,0x7e, +0xb3,0x2a,0x87,0x12,0xaa,0xf7,0x7e,0x8, 0x2b,0x2f,0x7e,0xb3,0x2b,0x2e,0x12,0xaa, +0xf7,0x7e,0x8, 0x2a,0x8a,0xe5,0x25,0x12,0x8f,0xc7,0x7e,0x8, 0x2b,0x31,0xe5,0x24, +0x7e,0x34,0x0, 0x3, 0x2, 0x20,0xe8,0x7e,0x34,0x0, 0x2, 0x2, 0x20,0xe8,0x6c,0xaa, +0xe4,0xa, 0x4b,0x9, 0x94,0x2a,0x7a,0xbc,0x9a,0x68,0x6, 0x4, 0xbe,0xb0,0xe, 0x40, +0xf0,0xbe,0xb0,0xe, 0x68,0x7, 0xb, 0xa0,0xbe,0xa0,0x23,0x40,0xe3,0x7a,0xb, 0xa0, +0x74,0x6e,0x7a,0x1b,0xb0,0x22,0x7e,0x8, 0x37,0x7a,0x7e,0x34,0x0, 0x60,0xe4,0x12, +0x20,0xe8,0x6c,0xaa,0x7e,0x44,0xff,0xff,0x7e,0x70,0xc, 0xac,0x7a,0x59,0x43,0x37, +0x7c,0x59,0x43,0x37,0x84,0xb, 0xa0,0xbe,0xa0,0x8, 0x40,0xe8,0x7e,0x8, 0x37,0x68, +0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x20,0xe8,0x12,0x47,0xe2,0x7e,0xb3,0x37,0x71,0xbe, +0xb0,0x1, 0x68,0x6, 0x7e,0xb3,0x37,0xed,0x60,0x10,0x7e,0x34,0x0, 0xf0,0x7a,0x37, +0x2a,0x5a,0x7e,0x34,0x0, 0xc8,0x7a,0x37,0x2a,0x5c,0x7e,0xb3,0x28,0xa8,0xb4,0x1, +0x24,0x7e,0x34,0x1, 0x18,0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x0, 0xfa,0x7a,0x37,0x2a, +0x5c,0x7e,0x34,0x1, 0x40,0x7a,0x37,0x2a,0x4f,0x7a,0x37,0x2a,0x51,0x7e,0x34,0x1, +0x7c,0x7a,0x37,0x2a,0x53,0x7e,0xb3,0x2a,0x2, 0x70,0x21,0x7e,0x27,0x2a,0x5a,0x7d, +0x32,0x7e,0x14,0x0, 0x4, 0xad,0x13,0x7d,0x31,0x12,0x7e,0x3c,0xbe,0x34,0x0, 0x50, +0x28,0x4, 0x7e,0x34,0x0, 0x50,0x2d,0x32,0x7a,0x37,0x2a,0x5a,0x22,0x6d,0x33,0x7d, +0x23,0x7d,0x3, 0x6c,0x33,0x80,0x45,0x6c,0x22,0x80,0x37,0x7e,0xb3,0x2a,0x6e,0xac, +0xb3,0xa, 0x42,0x2d,0x54,0x7d,0x45,0x3e,0x44,0x7e,0x7f,0x13,0x8a,0x2d,0xf4,0xb, +0x7a,0x40,0xbe,0x44,0x0, 0x32,0x8, 0x8, 0xbe,0x44,0x2, 0x58,0x58,0x2, 0xb, 0x24, +0xbe,0x44,0xff,0xce,0x58,0x8, 0xbe,0x44,0xfd,0xa8,0x8, 0x2, 0xb, 0x4, 0xb, 0x34, +0xb, 0x21,0x7e,0x93,0x2a,0x6e,0xbc,0x92,0x38,0xc1,0xb, 0x31,0x7e,0xb3,0x2a,0x6d, +0xbc,0xb3,0x38,0xb3,0x7e,0x54,0x0, 0x6, 0xad,0x53,0x7d,0x15,0x1e,0x14,0x1e,0x14, +0x1e,0x14,0x12,0x7e,0x3e,0xbd,0x12,0x50,0x22,0xbd,0x30,0x28,0x1e,0xe4,0x7a,0xb3, +0x3a,0x9, 0x7e,0xb3,0x3a,0xa, 0xbe,0xb0,0x5, 0x50,0x7, 0x4, 0x7a,0xb3,0x3a,0xa, +0x80,0x3c,0xe4,0x7a,0xb3,0x3a,0xa, 0x74,0x1, 0x80,0x2f,0xbd,0x10,0x50,0x22,0xbd, +0x32,0x28,0x1e,0xe4,0x7a,0xb3,0x3a,0xa, 0x7e,0xb3,0x3a,0x9, 0xbe,0xb0,0x5, 0x50, +0x7, 0x4, 0x7a,0xb3,0x3a,0x9, 0x80,0x16,0xe4,0x7a,0xb3,0x3a,0x9, 0x74,0x2, 0x80, +0x9, 0xe4,0x7a,0xb3,0x3a,0x9, 0x7a,0xb3,0x3a,0xa, 0x7a,0xb3,0x3a,0xb, 0x7e,0xb3, +0x3a,0xb, 0x22,0x6c,0x66,0x7e,0xb3,0x28,0xa8,0xb4,0x1, 0x63,0x7e,0x73,0x26,0xf2, +0xbe,0x70,0x0, 0x28,0x5a,0x6c,0x33,0x80,0x4e,0xa, 0x23,0x9, 0x72,0x26,0xe6,0x7e, +0xb3,0x2a,0x6e,0x14,0xbc,0x7b,0x78,0x3d,0x6c,0x22,0x80,0x27,0x7c,0xb2,0x7c,0x73, +0x12,0x67,0xe2,0x50,0x1c,0xa, 0x22,0x7e,0x73,0x2a,0x6e,0xa, 0x7, 0x2d,0x2, 0x3e, +0x4, 0x49,0x20,0x4, 0xfc,0x6d,0x0, 0x9e,0x7, 0x2a,0x4f,0xbd,0x20,0x58,0x2, 0xb, +0x60,0xb, 0x20,0x7e,0x73,0x2a,0x6d,0xbc,0x72,0x38,0xd1,0xbe,0x60,0x0, 0x28,0x3, +0x74,0x1, 0x22,0xe4,0x22,0xb, 0x30,0x7e,0x73,0x26,0xf2,0xbc,0x73,0x38,0xaa,0x74, +0x1, 0x22,0x7c,0xab,0xbe,0xa0,0x0, 0x40,0x11,0x7e,0xb3,0x2a,0x6e,0xbc,0xba,0x28, +0x9, 0x74,0x2, 0xa4,0x49,0x25,0x34,0x0, 0x80,0x51,0x7e,0x13,0x2a,0x6e,0xbc,0x1a, +0x38,0x1c,0x7e,0x3, 0x2a,0x6d,0xa, 0x10,0xa, 0x21,0x2d,0x12,0xa, 0x3a,0xbd,0x31, +0x58,0xc, 0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23,0x3, 0x70,0x80,0x2d,0x7e,0x3, +0x2a,0x6d,0xa, 0x20,0xa, 0x11,0x7d,0x41,0x2d,0x42,0xa, 0x3a,0xbd,0x34,0x48,0x19, +0x7e,0x10,0x2, 0xac,0x1, 0x2d,0x1, 0xbd,0x30,0x58,0xe, 0x9d,0x31,0x9d,0x32,0x3e, +0x34,0x3e,0x34,0x49,0x23,0x3, 0x72,0x80,0x2, 0xe4,0x22,0x7e,0x34,0x0, 0x64,0xad, +0x23,0x74,0xc, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7c, +0xb7,0x22,0xca,0xf8,0x80,0x38,0x7c,0xbf,0x12,0xad,0x2, 0xa, 0x1b,0x7e,0x63,0x2a, +0x6e,0x7e,0x70,0x2, 0xac,0x67,0x7e,0x10,0x2, 0xac,0x1f,0x2d,0x3, 0x7e,0x1f,0x13, +0x8a,0x2d,0x30,0x12,0xad,0xc1,0x9d,0x35,0x1b,0x1a,0x10,0xb, 0xf0,0x12,0xad,0xc1, +0x7e,0x73,0x2a,0x6e,0xa, 0x27,0x2d,0x25,0xa, 0x3f,0xbd,0x32,0x48,0xc8,0xda,0xf8, +0x22,0x7e,0xa3,0x2a,0x6d,0x74,0x2, 0xa4,0x22,0xc2,0x0, 0x12,0x44,0xc4,0x50,0x42, +0x6c,0xaa,0x80,0x30,0x7e,0x50,0x2, 0xac,0x5a,0x9, 0x72,0x26,0xfa,0x9, 0x62,0x26, +0xfb,0xbe,0x70,0x0, 0x40,0x1c,0x7e,0xb3,0x2a,0x6f,0xa, 0x1b,0x1b,0x14,0xa, 0x27, +0xbd,0x21,0x18,0xe, 0xbe,0x60,0x0, 0x40,0x9, 0xbe,0x60,0xf, 0x38,0x4, 0xd2,0x0, +0x80,0xa, 0xb, 0xa0,0x7e,0xb3,0x28,0x84,0xbc,0xba,0x38,0xc8,0x20,0x0, 0x3, 0x12, +0x6c,0x48,0x30,0x1a,0x14,0x5, 0x5d,0xe5,0x5d,0xbe,0xb0,0x50,0x50,0x7, 0x7e,0x34, +0x0, 0x8, 0x2, 0x5f,0xcc,0xc2,0x1a,0x80,0x0, 0x75,0x5d,0x0, 0x22,0xca,0x3b,0x7c, +0xfb,0x75,0x3d,0x0, 0x7e,0xb3,0x2a,0x6f,0xf5,0x42,0x7e,0xb3,0x2a,0x70,0xf5,0x43, +0x75,0x44,0x28,0x7e,0xd3,0x28,0x84,0xe4,0x7a,0xb3,0x31,0xcf,0x7a,0xb3,0x31,0xcb, +0x7a,0xb3,0x31,0xcc,0x7e,0x8, 0x31,0xd0,0x7e,0x34,0x0, 0x1e,0x12,0x20,0xe8,0x7e, +0x8, 0x31,0xf0,0x7e,0x34,0x0, 0x3c,0x12,0x20,0xe8,0xbe,0xd0,0x2, 0x50,0x3, 0x2, +0xb2,0x15,0x6c,0xcc,0x2, 0xb2,0xe, 0x12,0x97,0xd4,0xf5,0x24,0x9, 0xb3,0x26,0xfb, +0xf5,0x25,0x4c,0xcc,0x68,0x8, 0xa, 0x3c,0x9, 0xb3,0x31,0xd0,0x70,0xa, 0xa, 0x3c, +0xb, 0x34,0xa, 0x2c,0x19,0x72,0x31,0xd0,0x7c,0xbd,0x14,0xbc,0xbc,0x78,0x3, 0x2, +0xb2,0x15,0xa, 0x5c,0xb, 0x54,0xf5,0x2e,0x2, 0xb2,0x4, 0x7e,0x71,0x2e,0x12,0xb5, +0x9e,0x7a,0xa1,0x26,0x9, 0xb3,0x26,0xfb,0xf5,0x27,0xa, 0x2a,0xe5,0x24,0x12,0x44, +0x5b,0x7c,0xb7,0xf5,0x28,0xe5,0x27,0xa, 0x2b,0xe5,0x25,0x12,0x44,0x5b,0x7c,0xb7, +0xf5,0x29,0xe5,0x28,0xbe,0xb0,0x5, 0x40,0x3, 0x2, 0xb2,0x2, 0xe5,0x29,0xbe,0xb0, +0x5, 0x40,0x3, 0x2, 0xb2,0x2, 0x12,0xb2,0x18,0x12,0x94,0x83,0x7a,0xb3,0x31,0xce, +0x85,0x25,0x54,0x85,0x26,0x55,0x85,0x27,0x56,0x7e,0x8, 0x0, 0x31,0x7e,0x18,0x0, +0x33,0xe5,0x24,0x12,0xb3,0x37,0x75,0x3d,0x0, 0x6c,0xee,0x75,0x30,0x0, 0xe5,0x24, +0x7e,0x71,0x25,0x12,0x6d,0xcb,0x7a,0x35,0x35,0xe5,0x26,0x7e,0x71,0x27,0x12,0x6d, +0xcb,0x7a,0x35,0x37,0x7e,0x35,0x35,0xbe,0x35,0x37,0x8, 0x5, 0x7e,0x35,0x37,0x80, +0x3, 0x7e,0x35,0x35,0x7a,0x35,0x3b,0xe, 0x34,0x7a,0x35,0x39,0xe5,0x28,0xbe,0xb0, +0x1, 0x38,0x2e,0xe5,0x29,0xbe,0xb0,0x1, 0x38,0x27,0x7c,0xbf,0x30,0xe1,0x22,0xe5, +0x26,0x7e,0x71,0x25,0x12,0x6d,0xcb,0x7d,0x43,0xe5,0x24,0x7e,0x71,0x27,0x12,0x6d, +0xcb,0x2d,0x34,0xbe,0x35,0x39,0x18,0x3, 0x2, 0xb1,0x99,0x75,0x30,0x1, 0x2, 0xb1, +0x99,0xe5,0x28,0xbe,0xb0,0x1, 0x38,0xa, 0xe5,0x29,0xbe,0xb0,0x1, 0x38,0x3, 0x2, +0xb1,0x99,0xe5,0x28,0xbe,0xb0,0x5, 0x40,0x3, 0x2, 0xb1,0x99,0xe5,0x29,0xbe,0xb0, +0x5, 0x40,0x3, 0x2, 0xb1,0x99,0x7c,0xbf,0x20,0xe0,0x3, 0x2, 0xb1,0x99,0x6d,0x33, +0x7a,0x35,0x4d,0x75,0x4f,0x0, 0x7a,0x35,0x50,0x75,0x52,0x0, 0xc2,0x2, 0xc2,0x3, +0xe5,0x26,0xbe,0xb1,0x24,0x28,0x4, 0xe5,0x24,0x80,0x2, 0xe5,0x26,0xf5,0x2a,0xe5, +0x26,0xbe,0xb1,0x24,0x50,0x4, 0xe5,0x24,0x80,0x2, 0xe5,0x26,0xf5,0x2c,0xe5,0x27, +0xbe,0xb1,0x25,0x28,0x4, 0xe5,0x25,0x80,0x2, 0xe5,0x27,0xf5,0x2b,0xe5,0x27,0xbe, +0xb1,0x25,0x50,0x4, 0xe5,0x25,0x80,0x2, 0xe5,0x27,0xf5,0x2d,0xe5,0x2c,0xbe,0xb1, +0x2a,0x78,0x29,0xd2,0x2, 0xe5,0x2a,0x60,0x8, 0xe5,0x42,0x14,0xbe,0xb1,0x2a,0x78, +0x2, 0xd2,0x3, 0xe5,0x2a,0xbe,0xb0,0x0, 0x28,0x2, 0x15,0x2a,0xe5,0x42,0xa, 0x2b, +0x1b,0x24,0xe5,0x2c,0xa, 0x3b,0xbd,0x32,0x58,0x2, 0x5, 0x2c,0xe5,0x2d,0xbe,0xb1, +0x2b,0x78,0x29,0xd2,0x2, 0xe5,0x2b,0x60,0x8, 0xe5,0x43,0x14,0xbe,0xb1,0x2b,0x78, +0x2, 0xd2,0x3, 0xe5,0x2b,0xbe,0xb0,0x0, 0x28,0x2, 0x15,0x2b,0xe5,0x43,0xa, 0x2b, +0x1b,0x24,0xe5,0x2d,0xa, 0x3b,0xbd,0x32,0x58,0x2, 0x5, 0x2d,0x85,0x2a,0x3e,0x80, +0x5b,0x85,0x2b,0x3f,0x80,0x4d,0xe5,0x3e,0x7e,0x71,0x3f,0x12,0x6d,0xcb,0x7a,0x35, +0x40,0xe5,0x2a,0xbe,0xb1,0x3e,0x68,0x15,0xe5,0x2c,0xbe,0xb1,0x3e,0x68,0xe, 0xe5, +0x2b,0xbe,0xb1,0x3f,0x68,0x7, 0xe5,0x2d,0xbe,0xb1,0x3f,0x78,0xd, 0x7e,0x35,0x40, +0x2e,0x35,0x4d,0x7a,0x35,0x4d,0x5, 0x4f,0x80,0x17,0x5, 0x52,0x7e,0x35,0x40,0x2e, +0x35,0x50,0x7a,0x35,0x50,0x7e,0x35,0x33,0xbe,0x35,0x40,0x58,0x2, 0x5, 0x3d,0xb, +0xe0,0x5, 0x3f,0xe5,0x2d,0xbe,0xb1,0x3f,0x50,0xac,0x5, 0x3e,0xe5,0x2c,0xbe,0xb1, +0x3e,0x50,0x9e,0xe5,0x2c,0x7e,0x71,0x2b,0x12,0x6d,0xcb,0x7e,0x45,0x4d,0x9d,0x43, +0xe5,0x2a,0x7e,0x71,0x2d,0x12,0x6d,0xcb,0x9d,0x43,0xe5,0x2a,0x7e,0x71,0x2b,0x12, +0x6d,0xcb,0x9d,0x43,0xe5,0x2c,0x7e,0x71,0x2d,0x12,0x6d,0xcb,0x7d,0x23,0x7d,0x34, +0x9d,0x32,0x7a,0x35,0x4d,0x7e,0x35,0x37,0x2e,0x35,0x35,0x7a,0x35,0x39,0x30,0x2, +0x10,0x20,0x3, 0xd, 0x7e,0x35,0x4d,0x9e,0x35,0x39,0x7a,0x35,0x4d,0x15,0x4f,0x15, +0x4f,0xe5,0x4f,0xbe,0xb0,0x4, 0x28,0x6, 0xe5,0x4f,0x24,0xfc,0xf5,0x4f,0x7e,0x35, +0x4d,0xbe,0x34,0x0, 0x0, 0x58,0x5, 0x6d,0x33,0x7a,0x35,0x4d,0x75,0x44,0x28,0xe5, +0x42,0x14,0xbe,0xb1,0x24,0x68,0xd, 0xbe,0xb1,0x26,0x68,0x8, 0xe5,0x24,0x60,0x4, +0xe5,0x26,0x70,0x8, 0x12,0xb3,0x2f,0x28,0x3, 0x75,0x44,0x2c,0x7e,0x15,0x50,0x1a, +0x2, 0x1a,0x0, 0x7e,0x35,0x4d,0x1a,0x26,0x1a,0x24,0x2f,0x10,0xe5,0x44,0xa, 0x1b, +0x6d,0x0, 0x12,0x1e,0xeb,0x7f,0x71,0x7a,0x7d,0x45,0x7e,0x15,0x39,0x1a,0x2, 0x1a, +0x0, 0x7e,0x35,0x31,0x1a,0x26,0x1a,0x24,0x12,0x1e,0xeb,0xe5,0x52,0xa, 0xdb,0x6d, +0xcc,0xe5,0x4f,0xa, 0x1b,0x6d,0x0, 0x2f,0x6, 0x12,0x1e,0xeb,0x7a,0x1d,0x49,0xbf, +0x71,0x8, 0x3, 0x75,0x30,0x2, 0xc2,0x1, 0x20,0xc, 0xe, 0x12,0xb2,0x18,0x12,0xb2, +0x24,0x92,0x1, 0x20,0x1, 0x3, 0x75,0x30,0x0, 0xe5,0x30,0xbe,0xb0,0x0, 0x28,0x62, +0xe5,0x30,0xa, 0x3b,0x2e,0x34,0x31,0xca,0x7e,0x39,0xb0,0x4, 0x7a,0x39,0xb0,0xe5, +0x2e,0xa, 0x3b,0x9, 0xa3,0x31,0xd0,0x4c,0xaa,0x78,0xc, 0xa, 0x2c,0x9, 0xb2,0x31, +0xd0,0x19,0xb3,0x31,0xd0,0x80,0x3b,0xa, 0x2c,0x9, 0xb2,0x31,0xd0,0xf5,0x53,0xbc, +0xba,0x28,0x3, 0x7a,0xa1,0x53,0x75,0x2f,0x0, 0x80,0x22,0x9, 0x33,0x31,0xd0,0xe5, +0x2f,0xa, 0x2b,0x9, 0x22,0x31,0xd0,0xbc,0x23,0x68,0xa, 0xa, 0xc, 0x9, 0x30,0x31, +0xd0,0xbc,0x23,0x78,0x6, 0xe5,0x53,0x19,0xb2,0x31,0xd0,0x5, 0x2f,0xbe,0xd1,0x2f, +0x38,0xd9,0x5, 0x2e,0xbe,0xd1,0x2e,0x28,0x3, 0x2, 0xae,0xab,0xb, 0xc0,0xbc,0xdc, +0x28,0x3, 0x2, 0xae,0x77,0xda,0x3b,0x22,0xe5,0x24,0x7e,0x71,0x25,0x7e,0x61,0x26, +0x7e,0x51,0x27,0x22,0x12,0xb2,0x50,0x92,0x4, 0x30,0x4, 0xc, 0x7e,0xb3,0x32,0x2c, +0xbe,0xb0,0xfa,0x50,0x11,0x4, 0x80,0xa, 0x7e,0xb3,0x32,0x2c,0xbe,0xb0,0x0, 0x28, +0x5, 0x14,0x7a,0xb3,0x32,0x2c,0x7e,0xb3,0x32,0x2c,0x70,0x2, 0xc3,0x22,0xd3,0x22, +0xca,0x3b,0x7c,0x45,0x7c,0x6, 0x7c,0x57,0x7c,0x1b,0x7e,0x34,0x4, 0xfc,0x7e,0xb3, +0x26,0x83,0x7e,0xf3,0x2a,0x6e,0x7c,0x31,0x7c,0xe0,0x7c,0x25,0x7c,0xa4,0xbc,0x1, +0x50,0x4, 0x7c,0x30,0x7c,0xe1,0xbc,0x45,0x50,0x4, 0x7c,0x24,0x7c,0xa5,0xbe,0xb0, +0x1, 0x50,0x2, 0x61,0x15,0x7e,0x90,0x2, 0xac,0x9f,0x7e,0x50,0x2, 0xac,0x53,0x2d, +0x24,0x2d,0x23,0xb, 0x28,0x20,0x7e,0x10,0x2, 0xac,0x1e,0x2d,0x4, 0x2d,0x3, 0xb, +0x8, 0x40,0xa, 0x3, 0xb, 0x4, 0x7c,0x31,0x80,0x28,0x7e,0xd0,0x2, 0xac,0xdf,0x7e, +0x10,0x2, 0xac,0x13,0x2d,0x6, 0x12,0xb3,0x19,0x58,0x15,0xad,0xf4,0xbd,0xdf,0x58, +0xf, 0xbe,0x24,0x0, 0x0, 0x8, 0x9, 0xbe,0x44,0x0, 0x0, 0x8, 0x3, 0xc3,0x80,0x46, +0xb, 0x30,0xbc,0xe3,0x38,0xd4,0x7e,0x50,0x2, 0xac,0x52,0x2d,0x23,0xb, 0x28,0x20, +0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x43,0xb, 0x48,0x40,0xa, 0x12,0xb, 0x14,0x80,0x21, +0x7e,0x10,0x2, 0xac,0x13,0x12,0xb3,0x19,0x58,0x15,0xad,0xf4,0xbd,0xdf,0x58,0xf, +0xbe,0x24,0x0, 0x0, 0x8, 0x9, 0xbe,0x44,0x0, 0x0, 0x8, 0x3, 0xc3,0x80,0x7, 0xb, +0x30,0xbc,0xa3,0x38,0xdb,0xd3,0xda,0x3b,0x22,0x2d,0x3, 0xb, 0x8, 0x0, 0x7e,0xf4, +0x0, 0x9, 0x7d,0xb2,0xad,0xbf,0x7e,0xd4,0x0, 0xa, 0xad,0xd0,0xbd,0xdb,0x22,0x7e, +0x73,0x31,0xce,0xbe,0x70,0x5, 0x22,0xca,0xf8,0x7c,0xfb,0x7f,0x61,0x7f,0x50,0x7e, +0x34,0x22,0xd7,0x7e,0x24,0x0, 0xff,0x7e,0x14,0x1f,0x70,0x74,0x2a,0x12,0x1f,0xad, +0x7e,0x48,0x1f,0x70,0x12,0xb3,0xc6,0x92,0xc, 0x7c,0xbf,0x7e,0x71,0x54,0x12,0x6d, +0xcb,0x7d,0x43,0xe5,0x55,0x7e,0x71,0x56,0x12,0x6d,0xcb,0x2d,0x34,0xe, 0x34,0x7f, +0x4, 0x7e,0x50,0x7, 0xb, 0xa, 0x50,0xbd,0x53,0x58,0x10,0x69,0x30,0x0, 0x2, 0x1b, +0x5a,0x30,0x69,0x30,0x0, 0x4, 0x1b,0x6a,0x30,0x80,0x8, 0x2e,0x14,0x0, 0x6, 0x1b, +0x50,0x78,0xe1,0x12,0xb3,0x2f,0x28,0x2b,0xb, 0x5a,0x20,0x7e,0x34,0x0, 0xd, 0xad, +0x32,0x7e,0x24,0x0, 0x10,0x12,0x1e,0xb9,0x1b,0x5a,0x30,0xb, 0x6a,0x30,0x1a,0x26, +0x1a,0x24,0x7e,0x14,0x0, 0xd, 0x12,0x1e,0xfc,0x7e,0x8, 0x0, 0x10,0x12,0x1f,0x58, +0x1b,0x6a,0x30,0xda,0xf8,0x22,0x7e,0x37,0x28,0x8a,0xbe,0x34,0x2, 0x58,0x8, 0xa, +0x12,0x97,0x99,0xbe,0xb0,0x8, 0x48,0x2, 0xd3,0x22,0xc3,0x22,0x6c,0xaa,0x12,0x97, +0xea,0x29,0x81,0x0, 0x5, 0x7c,0x98,0x5e,0x90,0x1, 0x3e,0x90,0x7f,0x1, 0x2e,0x14, +0x0, 0x5, 0x7c,0xb8,0x54,0xfd,0x4c,0xb9,0x7a,0xb, 0xb0,0x29,0xb1,0x0, 0x5, 0x30, +0xe0,0x16,0x30,0xe2,0x13,0xc4,0x23,0x54,0x1f,0xb4,0x1, 0xc, 0x7f,0x1, 0xb, 0x16, +0x7e,0xb, 0xb0,0x1e,0xb0,0x7a,0xb, 0xb0,0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xbf,0x22, +0xca,0x3b,0x7f,0x40,0x7e,0xe3,0x28,0x84,0x6c,0xdd,0x7e,0xc0,0x1, 0x80,0x1a,0xa, +0x3d,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0x60,0xa, 0x2c,0x7f,0x4, 0x2d,0x12,0x7e,0xb, +0x70,0xbc,0x76,0x40,0x2, 0x7c,0xdc,0xb, 0xc0,0xbc,0xec,0x38,0xe2,0xa, 0x3d,0x2d, +0x39,0x7d,0x28,0x7e,0x1b,0xd0,0x6c,0xff,0x7e,0xc0,0x1, 0xa1,0x85,0x75,0x2d,0x0, +0x6d,0x33,0x7a,0x35,0x2e,0x7a,0x35,0x25,0x7a,0x35,0x27,0x7e,0x18,0x1f,0x70,0x7a, +0x1d,0x29,0x74,0xff,0x7e,0x34,0x1f,0x71,0x7e,0x24,0x0, 0x0, 0x7a,0x1b,0xb0,0x7e, +0x1d,0x29,0x7a,0x1b,0xb0,0xe4,0x7e,0x1d,0x29,0x39,0xb1,0x0, 0x3, 0x7e,0x1d,0x29, +0x39,0xb1,0x0, 0x2, 0x7e,0x1d,0x29,0x12,0x96,0xb3,0x44,0x1, 0x7a,0x1b,0xb0,0x75, +0x24,0x0, 0x80,0x6c,0x12,0xb5,0x9b,0x9, 0x93,0x26,0xfb,0xe5,0x24,0x12,0x44,0x62, +0xbc,0xbc,0x78,0x5a,0x5, 0x2d,0xa, 0x3a,0x2e,0x35,0x25,0x7a,0x35,0x25,0xa, 0x39, +0x2e,0x35,0x27,0x7a,0x35,0x27,0x12,0x6d,0xc7,0xbe,0x35,0x2e,0x8, 0x6, 0x12,0x6d, +0xc7,0x7a,0x35,0x2e,0x7e,0x1d,0x29,0x7e,0x1b,0xb0,0xbc,0xba,0x28,0x3, 0x7a,0x1b, +0xa0,0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x2, 0xbc,0xba,0x50,0x4, 0x39,0xa1,0x0, 0x2, +0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x1, 0xbc,0xb9,0x28,0x4, 0x39,0x91,0x0, 0x1, 0x7e, +0x1d,0x29,0x29,0xb1,0x0, 0x3, 0xbc,0xb9,0x50,0x4, 0x39,0x91,0x0, 0x3, 0x5, 0x24, +0xbe,0xe1,0x24,0x38,0x8f,0xe5,0x2d,0xbe,0xb0,0x0, 0x28,0x67,0x7e,0xd, 0x29,0x12, +0x94,0xd7,0xe5,0x2d,0xa, 0x2b,0x7e,0x15,0x25,0x8d,0x12,0x7a,0x15,0x25,0x7e,0x35, +0x27,0x8d,0x32,0x7a,0x35,0x27,0x7e,0x55,0x25,0x12,0xb5,0x93,0x19,0xa3,0x31,0xf0, +0x7e,0x55,0x27,0x12,0xb5,0x93,0x19,0xa3,0x31,0xf1,0x7e,0x37,0x28,0x8a,0xbe,0x35, +0x2e,0x78,0xe, 0x7e,0x35,0x25,0x7a,0x73,0x28,0x8c,0x7e,0x35,0x27,0x7a,0x73,0x28, +0x8d,0x7e,0x37,0x31,0xee,0x4d,0x33,0x68,0x18,0x7e,0x55,0x25,0x7e,0x35,0x27,0x12, +0x6d,0xcb,0x7e,0x25,0x2e,0x7e,0x70,0x2, 0xac,0x7f,0x2e,0x37,0x31,0xee,0x1b,0x38, +0x20,0xb, 0xf0,0xb, 0xc0,0xbc,0xdc,0x40,0x2, 0x81,0x5d,0x12,0xb3,0xdc,0x7c,0xbf, +0xda,0x3b,0x22,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7f,0x22,0x7e,0x71,0x24,0x74,0x2, +0xac,0x7b,0x9, 0xa3,0x26,0xfa,0x22,0x7e,0x73,0x2a,0x71,0xa, 0x17,0x2e,0x14,0x0, +0x3, 0x7e,0xa3,0x2a,0x6e,0xa, 0x3a,0xad,0x13,0x7d,0x21,0x6c,0x33,0x80,0x20,0xa, +0x3, 0x2d,0x2, 0x3e,0x4, 0x7e,0x7f,0x39,0xda,0x2d,0xf0,0xb, 0x7a,0x0, 0x7e,0x90, +0x2, 0xac,0x93,0x49,0xf4,0x13,0x8e,0x9d,0xf, 0x59,0x4, 0x25,0xb6,0xb, 0x30,0xbc, +0xa3,0x38,0xdc,0x7a,0x35,0x34,0x7e,0xf, 0x38,0x41,0x7e,0x18,0x25,0xb6,0x2, 0x5d, +0xf1,0x6c,0xaa,0x80,0x1c,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12,0x13,0xc6,0x49,0x32, +0x13,0x8e,0xbd,0x31,0x28,0x9, 0x2e,0x24,0x13,0x8e,0x9d,0x31,0x1b,0x28,0x30,0xb, +0xa0,0x7e,0xb3,0x2a,0x6e,0xbc,0xba,0x38,0xdc,0x22,0xca,0x78,0xa9,0x31,0xe5,0x6, +0xa9,0xd5,0xea,0xa9,0xc5,0xea,0xa9,0x30,0xe5,0x19,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e, +0x5, 0x5e,0x7e,0x73,0x3a,0x7, 0xbe,0x71,0x5e,0x38,0x2, 0xd2,0x1c,0xa9,0xd0,0x9e, +0xa9,0xd7,0x9e,0xa9,0x34,0xe5,0x5, 0xa9,0xc4,0xcd,0xc2,0x95,0xa9,0x32,0xe5,0x3, +0xa9,0xc2,0xcd,0xa9,0x33,0xe5,0x3, 0xa9,0xc3,0xcd,0xa9,0x37,0xe5,0x3, 0xa9,0xc7, +0xcd,0xa9,0x36,0xe5,0x3, 0xa9,0xc6,0xcd,0xda,0x78,0x32,0xc2,0x9a,0xa9,0xd4,0xa6, +0xc2,0x88,0xd2,0xa8,0x22,0x7e,0x14,0xd7,0xe8,0x7e,0x4, 0x0, 0xff,0x7e,0x34,0x47, +0x52,0x7e,0x24,0x55,0x50,0x79,0x30,0x0, 0x2, 0x1b,0xa, 0x20,0x7e,0x34,0x45,0x20, +0x7e,0x24,0x41,0x44,0x79,0x30,0x0, 0x6, 0x79,0x20,0x0, 0x4, 0x7e,0x34,0x99,0x33, +0x7e,0x24,0x66,0xcc,0x79,0x30,0x0, 0xa, 0x79,0x20,0x0, 0x8, 0x7e,0x34,0x41,0x47, +0x7e,0x24,0x46,0x4c,0x79,0x30,0x0, 0xe, 0x79,0x20,0x0, 0xc, 0x22,0xa9,0xc4,0xca, +0xa9,0xc5,0xca,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0x4f,0xdc,0xa9,0xd0,0xce,0xa9,0xc0, +0xc9,0xd2,0x2, 0x12,0x2f,0xde,0xa9,0xc2,0xea,0x75,0xc1,0x6, 0x75,0xc2,0xc, 0xd2, +0x0, 0x12,0xb6,0xee,0xa9,0xc1,0xc4,0xa9,0xd2,0xc4,0xa9,0xc2,0xe1,0x22,0xa2,0x0, +0xa9,0x97,0xc1,0xa2,0x0, 0xa9,0x97,0xc2,0x22,0xa9,0xd0,0xce,0xa2,0x0, 0xa9,0x95, +0xc9,0x22,0xca,0xf8,0xa2,0xaf,0xe4,0x33,0x7c,0xfb,0xd2,0x0, 0x12,0xb6,0xf9,0xa9, +0xd0,0xcb,0xc2,0xaf,0xa9,0xd0,0x9e,0x75,0x9d,0x0, 0xa9,0xd0,0x9e,0x75,0x9c,0x20, +0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0xa9,0xd0,0xcd,0x74,0x41,0x12,0x2f,0x39,0xa9,0xd0, +0x9e,0xa9,0xd7,0x9e,0x2e,0xf0,0xff,0x92,0xaf,0xda,0xf8,0x22,0xa9,0xd5,0xcb,0x74, +0x10,0x12,0x0, 0x66,0x7c,0x7b,0x12,0x28,0xb3,0x30,0xe7,0x3, 0x7e,0x70,0x2, 0xd2, +0xcd,0x7e,0x24,0x0, 0xef,0x7e,0xf, 0x39,0xc1,0x79,0x20,0x0, 0x84,0x7e,0x24,0x20, +0x5f,0x7e,0xf, 0x39,0xc1,0x79,0x20,0x0, 0x82,0x7e,0x24,0x41,0x0, 0x7e,0xf, 0x39, +0xc1,0x79,0x20,0x0, 0x90,0x7c,0x67,0x6c,0x77,0x2e,0x34,0x0, 0xc1,0x7e,0xf, 0x39, +0xc1,0x79,0x30,0x0, 0x86,0x7e,0x34,0x29,0x90,0x7e,0xf, 0x39,0xc1,0x79,0x30,0x0, +0x8a,0x7e,0x34,0x6a,0xd1,0x7e,0xf, 0x39,0xc1,0x79,0x30,0x0, 0x8c,0x7e,0x34,0x3, +0x61,0x7e,0xf, 0x39,0xc1,0x79,0x30,0x0, 0x8e,0x22,0xa9,0xc6,0xeb,0xa9,0xd6,0xac, +0xa9,0xd6,0xec,0xd2,0x86,0xa9,0xc2,0xeb,0xa9,0xd2,0xac,0xa9,0xd2,0xec,0xd2,0x82, +0x22,0x75,0x9a,0x2f,0xa9,0xd1,0x99,0xd2,0x9c,0xa9,0xd6,0xdf,0x22,0xc2,0x8e,0x43, +0x89,0x20,0x75,0x8d,0x1, 0x75,0x8b,0x0, 0xd2,0x8e,0xd2,0xab,0x22,0x75,0xb7,0x0, +0x75,0xb8,0x0, 0x75,0xf7,0x0, 0x75,0xf8,0x0, 0xa9,0xd0,0xb7,0xd2,0xb8,0xa9,0xd5, +0xb7,0xd2,0xbd,0xa9,0xd0,0xf7,0xd2,0xf8,0xa9,0xc1,0xb7,0xc2,0xb9,0xa9,0xc3,0xb7, +0xc2,0xbb,0xa9,0xc6,0xb7,0xc2,0xbe,0x22,0x75,0xe7,0x6b,0x2, 0xb8,0xe, 0xe4,0x7e, +0x34,0xd7,0xfc,0x12,0x77,0x15,0x7e,0x34,0xd7,0xfd,0x7a,0x1b,0xb0,0x75,0xe9,0xff, +0x22,0xa9,0xd0,0x99,0xa9,0xc6,0xdf,0x22,0x7e,0x37,0x3a,0x5, 0xb, 0x34,0x7a,0x37, +0x3a,0x5, 0xbe,0x34,0xff,0x0, 0x40,0x8, 0x7e,0x34,0xff,0x0, 0x7a,0x37,0x3a,0x5, +0x22,0xd2,0xc9,0x75,0xf2,0x30,0x75,0xf3,0x80,0x75,0xf4,0xc, 0x75,0xf5,0x1, 0x6c, +0xaa,0xe5,0xf5,0x54,0x80,0xb4,0x80,0xf9,0xe5,0xf6,0x12,0x5d,0xe7,0xb, 0xa0,0xbe, +0xa0,0xd, 0x40,0xed,0xc2,0xc9,0x22,0x2, 0xb8,0x6a,0x6d,0x11,0x12,0x57,0xe5,0x12, +0xb9,0x19,0x7d,0x3, 0x7e,0x78,0x13,0x8e,0x6c,0x99,0x80,0x17,0x12,0xb8,0xb9,0x7e, +0x50,0x2, 0xac,0x59,0x7f,0x57,0x2d,0xb2,0xb, 0x5a,0x30,0x9d,0x3d,0x59,0x32,0x13, +0xc6,0xb, 0x90,0xbc,0xa9,0x38,0xe5,0x6c,0x99,0x80,0x17,0x12,0xb8,0xb9,0x7e,0x70, +0x2, 0xac,0x79,0x2d,0x3f,0x7d,0x2e,0x12,0xb9,0x24,0xbd,0x1b,0x58,0x2, 0x7d,0x1b, +0xb, 0x90,0xbc,0xa9,0x38,0xe5,0x7d,0x31,0x22,0xa, 0xd9,0x2d,0xd0,0x3e,0xd4,0x7e, +0x1f,0x39,0xda,0x2d,0x3d,0xb, 0x1a,0xd0,0x22,0x12,0x8f,0xce,0x7e,0x34,0xd, 0xc8, +0x7e,0xb3,0x2a,0x6d,0x12,0xb8,0xe5,0x12,0xb8,0x67,0x7a,0x37,0x39,0xd7,0x74,0x1, +0x7a,0xb3,0x16,0x91,0x22,0x7a,0xb3,0x24,0xf2,0x7e,0x53,0x2a,0x6e,0x7a,0x53,0x24, +0xf3,0x7a,0x37,0x24,0xfa,0xe4,0x7a,0xb3,0x24,0xf4,0x7a,0xb3,0x24,0xf5,0x7e,0x34, +0x40,0x0, 0x7a,0x37,0x24,0xf6,0x7e,0x34,0x0, 0x20,0x12,0xb9,0x10,0x2, 0xd, 0x7, +0x7a,0x37,0x24,0xfc,0x7e,0x8, 0x24,0xf2,0x22,0xa, 0x2b,0x2e,0x24,0x0, 0x3, 0xa, +0x3a,0xad,0x32,0x22,0xb, 0x1a,0xc0,0x7d,0x3d,0x9d,0x3c,0x12,0x21,0xa, 0x7d,0xb3, +0x22,0xca,0x79,0x7c,0xfb,0x7e,0x8, 0x1f,0x34,0x12,0xb9,0xa7,0x7e,0xa3,0x2a,0x73, +0x7e,0x63,0x2a,0x74,0x6c,0xee,0x80,0x1e,0xa, 0x2e,0x9, 0x72,0x2a,0xdc,0xbe,0x70, +0x1c,0x50,0x11,0xa, 0x27,0x12,0x67,0x43,0x7c,0x7b,0x7e,0xb3,0x2a,0xfb,0xa, 0x27, +0x19,0xb2,0x1f,0x34,0xb, 0xe0,0xbc,0x6e,0x38,0xde,0x6c,0xee,0x80,0x17,0xa, 0x3e, +0x9, 0x73,0x2a,0xb9,0xbe,0x70,0x23,0x50,0xa, 0x7e,0x63,0x2a,0xfb,0xa, 0x27,0x19, +0x62,0x1f,0x50,0xb, 0xe0,0xbc,0xae,0x38,0xe5,0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e, +0x2e,0x14,0x1f,0x34,0x6d,0x0, 0x7c,0xbf,0x7c,0x7e,0x12,0x11,0xf8,0xb, 0xe0,0xbe, +0xe0,0x5, 0x40,0xe7,0xda,0x79,0x22,0x7e,0x34,0x0, 0x46,0x74,0x3f,0x2, 0x20,0xe8, +0xca,0xd8,0xca,0x79,0x7c,0xf7,0x7f,0x70,0x12,0xba,0x42,0x7c,0xeb,0x6c,0xdd,0x80, +0x20,0x74,0x2, 0xac,0xbd,0x7f,0x67,0x2d,0xd5,0xb, 0x6a,0x30,0x6d,0x22,0x74,0x4, +0x2f,0x11,0x14,0x78,0xfb,0xa, 0x1e,0x6d,0x0, 0x12,0x1f,0x7, 0x1b,0x6a,0x30,0xb, +0xd0,0xbc,0xfd,0x38,0xdc,0xda,0x79,0xda,0xd8,0x22,0xca,0x79,0x7f,0x51,0x7f,0x40, +0x7e,0xa3,0x2a,0x74,0xa, 0x3a,0x7e,0xa3,0x2a,0x73,0xa, 0x7a,0x2d,0x73,0x7e,0xd, +0x29,0x7c,0x7f,0x12,0xb9,0xb0,0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x1d,0x29,0x7f, +0x4, 0x12,0x20,0xc3,0x1b,0xfd,0x7e,0xb3,0x2b,0x1, 0xb4,0x1, 0x22,0x6c,0xaa,0x80, +0x1a,0x7e,0x70,0x2, 0xac,0x7a,0x7f,0x5, 0x2d,0x13,0xb, 0xa, 0x20,0x7f,0x4, 0x2d, +0x13,0xb, 0xa, 0x30,0x9d,0x32,0x1b,0xa, 0x30,0xb, 0xa0,0xbc,0xfa,0x38,0xe2,0xda, +0x79,0x22,0x7c,0x7b,0xa5,0xbf,0x0, 0x3, 0x74,0x10,0x22,0xbe,0x70,0x4, 0x38,0x4, +0x6c,0xaa,0x80,0x21,0xbe,0x70,0x8, 0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x70, +0x10,0x38,0x5, 0x7e,0xa0,0x2, 0x80,0xd, 0xbe,0x70,0x20,0x38,0x5, 0x7e,0xa0,0x3, +0x80,0x3, 0x7e,0xa0,0x4, 0xa, 0x47,0x3e,0x44,0x3e,0x44,0x3e,0x44,0x7c,0xba,0x60, +0x5, 0x1e,0x44,0x14,0x78,0xfb,0x7c,0xb9,0x22,0x7c,0xab,0x9f,0x11,0x30,0x0, 0x22, +0x6c,0x99,0x80,0x1a,0xa, 0xf9,0x2d,0xf1,0x7d,0xe0,0x7e,0x7b,0xb0,0x7e,0x78,0x0, +0x1, 0x60,0x5, 0x2f,0x77,0x14,0x78,0xfb,0x4d,0x3f,0x4d,0x2e,0xb, 0x90,0xbc,0xa9, +0x38,0xe2,0x22,0xca,0xf8,0x7e,0xf0,0x19,0x7e,0x8, 0x1f,0x34,0x12,0xbb,0x3b,0x7e, +0x8, 0x1f,0x3c,0x12,0xbb,0x43,0xd2,0x0, 0x7e,0x8, 0x2a,0xdc,0x74,0x19,0x12,0xba, +0x89,0x7e,0x8, 0x1f,0x34,0x7a,0xf, 0x1f,0x58,0x7f,0x1, 0x7a,0x17,0x1f,0x5c,0x7d, +0x32,0x7a,0x37,0x1f,0x5e,0x7e,0x18,0x1f,0x3c,0x7a,0x1f,0x1f,0x64,0x6c,0x77,0x80, +0xe, 0x12,0xbb,0x8b,0x50,0x7, 0x12,0xbb,0x82,0x19,0x51,0x1f,0x3c,0xb, 0x70,0xbc, +0xf7,0x38,0xee,0x12,0xbb,0x28,0xe4,0x12,0xbb,0x30,0xe4,0x12,0xc, 0x9b,0x6d,0x33, +0x7a,0x37,0x1f,0x5c,0x7a,0x37,0x1f,0x5e,0x12,0xbb,0x28,0x74,0x1, 0x12,0xbb,0x30, +0x74,0x1, 0x12,0xc, 0x9b,0xda,0xf8,0x22,0xa9,0xc6,0xea,0x7e,0x8, 0x1f,0x58,0x22, +0x12,0xc, 0x9b,0xa9,0xd6,0xea,0x7e,0x8, 0x1f,0x58,0x22,0x7e,0x34,0x0, 0x8, 0xe4, +0x2, 0x20,0xe8,0x7e,0x34,0x0, 0x1c,0x74,0x3f,0x2, 0x20,0xe8,0x7e,0x8, 0x1f,0x34, +0x12,0xbb,0x43,0x6c,0x77,0x80,0xe, 0x12,0xbb,0x8b,0x50,0x7, 0x12,0xbb,0x82,0x19, +0x51,0x1f,0x34,0xb, 0x70,0x7e,0x53,0x2a,0x6e,0xbc,0x57,0x38,0xea,0xa9,0xc6,0xea, +0x7e,0x8, 0x1f,0x34,0xe4,0x12,0x11,0x38,0xa9,0xd6,0xea,0x7e,0x8, 0x1f,0x34,0x2, +0x11,0x38,0xa, 0x27,0x9, 0x52,0x2b,0x44,0xa, 0x16,0x22,0xa, 0x27,0x9, 0x62,0x2a, +0xdc,0xbe,0x60,0x1c,0x22,0x7e,0x27,0x28,0xa3,0x6d,0x11,0x9d,0x12,0x6c,0xaa,0x80, +0x64,0x30,0x5, 0x2e,0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x5, 0xf8,0x49,0x4, 0x4, +0x0, 0xbd,0x2, 0x8, 0x11,0x7e,0xb3,0x25,0xf6,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3, +0x59,0xf4,0x5, 0xf8,0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, +0x5, 0xf8,0x30,0x7, 0x2e,0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x6, 0x76,0x49,0x4, +0x4, 0x7e,0xbd,0x2, 0x8, 0x11,0x7e,0xb3,0x25,0xf6,0xb4,0x1, 0x16,0x7d,0xf2,0x2d, +0xf3,0x59,0xf4,0x6, 0x76,0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59, +0x4, 0x6, 0x76,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xa, 0xb, 0x7e,0xb3,0x2a,0x73,0xa, +0x4b,0x2d,0x40,0xa, 0xa, 0xbd,0x4, 0x48,0x88,0x22,0xe4,0x6c,0x33,0xa, 0x33,0x19, +0xb3,0x27,0x72,0xb, 0x30,0xa5,0xbb,0x4, 0xf4,0xe4,0x7a,0xb3,0x28,0x84,0x7a,0xb3, +0x28,0x85,0x6d,0x33,0x7a,0x37,0x28,0x86,0x7a,0x37,0x28,0x88,0x7a,0x37,0x28,0x8a, +0x7a,0x37,0x28,0x8e,0x7e,0xd4,0x1f,0x36,0x5e,0xd4,0xff,0xfe,0x6d,0xcc,0x7e,0x1f, +0x13,0x8a,0x7a,0x37,0x1f,0x76,0x7d,0x3d,0x7a,0x37,0x1f,0x7a,0x7e,0x34,0x15,0x9e, +0x7a,0x37,0x1f,0x78,0x7e,0x73,0x2a,0x6d,0x7a,0x73,0x1f,0x73,0x7e,0x73,0x2a,0x6e, +0x7a,0x73,0x1f,0x72,0x7e,0x37,0x2a,0x5c,0x7a,0x37,0x1f,0x7c,0x7e,0x37,0x2a,0x5e, +0x7a,0x37,0x1f,0x7e,0x7e,0x37,0x2a,0x60,0x7a,0x37,0x1f,0x80,0x74,0x1e,0x7a,0xb3, +0x1f,0x74,0x7e,0x73,0x3, 0xfe,0x7a,0x73,0x1f,0x75,0x7e,0x8, 0x1f,0x72,0x7e,0x18, +0x1f,0x82,0x12,0x8, 0x0, 0x7e,0x73,0x1f,0x82,0x7a,0x73,0x28,0x84,0x7e,0x73,0x1f, +0x83,0x7a,0x73,0x28,0x85,0x7e,0x37,0x1f,0x84,0x7a,0x37,0x28,0x86,0x7e,0x37,0x1f, +0x86,0x7a,0x37,0x28,0x88,0x7e,0x37,0x1f,0x8c,0x7a,0x37,0x28,0x8a,0x7e,0x37,0x1f, +0x8e,0x7d,0x23,0x7a,0x53,0x28,0x8c,0xa, 0x36,0x7a,0x73,0x28,0x8d,0x7e,0x37,0x1f, +0x88,0x7a,0x37,0x28,0x8e,0x7e,0x37,0x1f,0x8a,0x7d,0x23,0x7a,0x53,0x28,0x90,0xa, +0x36,0x7a,0x73,0x28,0x91,0x6c,0x33,0x80,0x1d,0x7c,0xb3,0x12,0x76,0xfb,0x74,0x2, +0xac,0xb3,0x49,0x45,0x15,0x9e,0xa, 0x38,0x7c,0x27,0x19,0x25,0x26,0xfa,0x7c,0x29, +0x19,0x25,0x26,0xfb,0xb, 0x30,0x7e,0x23,0x28,0x84,0xbc,0x23,0x38,0xdb,0x6c,0x33, +0x80,0x1b,0x74,0x2, 0xac,0xb3,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0x40,0xa, 0x38,0x7c, +0x27,0x19,0x25,0x27,0x36,0x7c,0x29,0x19,0x25,0x27,0x37,0xb, 0x30,0x7e,0x23,0x28, +0x85,0xbc,0x23,0x38,0xdd,0x22,0x7c,0x7b,0xa, 0x57,0x9e,0x54,0x0, 0x20,0xe, 0x54, +0xe, 0x54,0xe, 0x54,0xe, 0x54,0x7c,0xab,0x7c,0x67,0x5e,0x60,0xf0,0xa5,0xbe,0x20, +0x1d,0x7c,0xb7,0x54,0xf, 0x7e,0x24,0x0, 0x1, 0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb, +0x7e,0x73,0x39,0xfc,0xa, 0x47,0x5d,0x42,0x7e,0x73,0x38,0x33,0x80,0x36,0xa5,0xbe, +0x30,0x18,0x12,0xbd,0xb9,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7e,0x53,0x39,0xfd, +0xa, 0x45,0x5d,0x43,0x7e,0x73,0x38,0x34,0x80,0x1a,0x12,0xbd,0xb9,0x60,0x5, 0x3e, +0x34,0x14,0x78,0xfb,0xa, 0x2a,0x9, 0xb2,0x39,0xfc,0xa, 0x4b,0x5d,0x43,0xa, 0x5a, +0x9, 0x75,0x38,0x35,0xa, 0x57,0x5d,0x54,0x22,0x7c,0xb7,0x54,0xf, 0x7e,0x34,0x0, +0x1, 0x22,0x7e,0xb3,0x2f,0x80,0xb4,0x4, 0x2, 0xd3,0x22,0xc3,0x22,0x7d,0xf2,0x7d, +0xe3,0x7e,0x8, 0x2f,0x80,0x7e,0x34,0x0, 0x28,0xe4,0x12,0x20,0xe8,0x7e,0x8, 0x2b, +0xbf,0x7e,0x34,0x3, 0xc0,0x12,0x20,0xe8,0x7a,0xb3,0x38,0x35,0x7e,0x34,0x13,0x88, +0x7a,0x37,0x2b,0xb7,0x7a,0xe7,0x2f,0x84,0x7a,0xf7,0x2f,0x86,0x7a,0xe7,0x2f,0x88, +0x7a,0xe7,0x2f,0x8c,0x7a,0xe7,0x2f,0x90,0x7a,0xe7,0x2f,0x94,0x7a,0xf7,0x2f,0x8a, +0x7a,0xf7,0x2f,0x8e,0x7a,0xf7,0x2f,0x92,0x7a,0xf7,0x2f,0x96,0x7a,0xe7,0x2b,0xbb, +0x7a,0xf7,0x2b,0xbd,0x7a,0xb3,0x2f,0xa8,0x74,0x2, 0x7a,0xb3,0x2f,0x7f,0x22,0x74, +0xfe,0x7a,0xb3,0x38,0x35,0xe4,0x7a,0xb3,0x2f,0x80,0x22,0xca,0x3b,0xf5,0x2a,0x7f, +0x31,0x7a,0xd, 0x26,0xe4,0x7a,0xb3,0x22,0xf6,0x7a,0xb3,0x22,0xf7,0x7a,0xb3,0x22, +0xf8,0x7e,0x34,0x3, 0xe8,0x7a,0x37,0x22,0xfd,0x74,0x3c,0x7a,0xb3,0x22,0xf5,0x75, +0x2f,0x46,0x75,0x2b,0x0, 0x2, 0xc0,0x38,0x12,0xc0,0x74,0x28,0x1e,0x7e,0x34,0x0, +0x44,0xca,0x39,0x7e,0x71,0x2b,0x74,0x44,0xac,0x7b,0x2e,0x34,0x14,0x6, 0x7e,0x24, +0x0, 0xff,0x7e,0x8, 0x22,0xff,0x12,0x20,0xc3,0x1b,0xfd,0x6d,0x33,0x7a,0x37,0x22, +0xf9,0x7a,0x35,0x30,0x7a,0x37,0x22,0xfb,0x7a,0x35,0x32,0x7a,0x35,0x34,0x7e,0x34, +0x22,0xff,0x7a,0x35,0x36,0x7e,0x34,0x23,0x1f,0x7a,0x35,0x38,0x75,0x2c,0x0, 0x80, +0x59,0xe5,0x2c,0xa, 0x3b,0x7e,0xd, 0x26,0x12,0xc6,0xea,0x2e,0x35,0x36,0x12,0x96, +0xa1,0x7d,0xd3,0x7e,0xc7,0x22,0xfb,0xbd,0xcd,0x58,0x4, 0x7a,0xd7,0x22,0xfb,0xe5, +0x2c,0xa, 0x3b,0x7f,0x3, 0x12,0xc6,0xea,0x2e,0x35,0x38,0x12,0x96,0xa1,0x7d,0xc3, +0x7e,0x35,0x32,0xbd,0x3c,0x58,0x3, 0x7a,0xc5,0x32,0x7e,0x37,0x22,0xf9,0x2d,0x3d, +0x7a,0x37,0x22,0xf9,0x7d,0x3c,0x2e,0x35,0x30,0x7a,0x35,0x30,0x2d,0xcd,0x7e,0x35, +0x34,0xbd,0x3c,0x58,0x3, 0x7a,0xc5,0x34,0x5, 0x2c,0xe5,0x2a,0xbe,0xb1,0x2c,0x38, +0xa0,0xe5,0x2a,0xb4,0xa, 0x2d,0x7e,0x37,0x22,0xfb,0xbe,0x34,0x0, 0x40,0x48,0xc, +0x7e,0x25,0x32,0xbe,0x24,0x0, 0x40,0x48,0x3, 0x2, 0xc0,0x36,0xbe,0x34,0x0, 0x60, +0x8, 0x3, 0x2, 0xc0,0x36,0x7e,0x35,0x32,0xbe,0x34,0x0, 0x60,0x8, 0x3, 0x2, 0xc0, +0x36,0x80,0x2b,0x7e,0x37,0x22,0xfb,0xbe,0x34,0x0, 0x20,0x8, 0xc, 0x7e,0x25,0x32, +0xbe,0x24,0x0, 0x20,0x8, 0x3, 0x2, 0xc0,0x36,0xbe,0x34,0x0, 0x30,0x8, 0x3, 0x2, +0xc0,0x36,0x7e,0x35,0x32,0xbe,0x34,0x0, 0x30,0x8, 0x3, 0x2, 0xc0,0x36,0x7e,0xa3, +0x39,0x42,0x74,0xc, 0xa4,0xbe,0x57,0x22,0xf9,0x58,0x3, 0x2, 0xc0,0x36,0x7e,0xa3, +0x39,0x43,0x74,0xc, 0xa4,0xbe,0x55,0x30,0x58,0x3, 0x2, 0xc0,0x36,0x7e,0x15,0x36, +0x6d,0x0, 0x7e,0x1d,0x26,0xe5,0x2a,0x12,0xc0,0x7c,0x7a,0xb3,0x22,0xf4,0x7e,0x15, +0x38,0x6d,0x0, 0x7f,0x13,0xe5,0x2a,0x12,0xc0,0x7c,0xf5,0x2d,0x7e,0x73,0x22,0xf5, +0xbe,0x73,0x22,0xf4,0x28,0x3, 0x2, 0xc0,0x36,0xbe,0x71,0x2d,0x38,0x78,0xe5,0x2d, +0x7e,0x31,0x2d,0xac,0x3b,0x1a,0x2, 0x1a,0x0, 0x7e,0x73,0x22,0xf4,0xac,0x77,0x1a, +0x26,0x1a,0x24,0x2f,0x10,0xe5,0x2d,0xa, 0x5b,0x6d,0x44,0x7e,0x33,0x22,0xf4,0xa, +0x13,0x6d,0x0, 0x2f,0x2, 0x12,0x1f,0x7, 0x7c,0xb7,0xf5,0x2e,0xe5,0x2f,0xbe,0xb1, +0x2e,0x38,0x43,0x7e,0x37,0x22,0xfb,0x2e,0x35,0x32,0x2e,0x35,0x34,0x7a,0x35,0x3a, +0xe5,0x2e,0xa, 0x2b,0x7e,0x34,0x0, 0x64,0x9d,0x32,0x3e,0x34,0x2e,0x35,0x3a,0x7a, +0x35,0x3a,0x7e,0x37,0x22,0xfd,0xbe,0x35,0x3a,0x8, 0x1b,0x7e,0x35,0x3a,0x7a,0x37, +0x22,0xfd,0xe5,0x2e,0x7a,0xb3,0x22,0xf7,0x7e,0x73,0x23,0x41,0x7a,0x73,0x22,0xf8, +0xe5,0x2b,0x7a,0xb3,0x22,0xf6,0x5, 0x2b,0x12,0xc0,0x74,0x28,0x3, 0x2, 0xbe,0x68, +0x7e,0xa3,0x22,0xf7,0xbe,0xa1,0x2f,0x40,0x20,0x7e,0xb3,0x22,0xf8,0xbe,0xb0,0x0, +0x28,0x17,0xbe,0xb0,0xff,0x50,0x12,0x7e,0x73,0x22,0xf6,0xa, 0x37,0xb, 0x34,0x7a, +0x73,0x39,0x3f,0x7a,0xb3,0x39,0x41,0x80,0x6, 0x74,0x7c,0x7a,0xb3,0x39,0x3f,0x7c, +0xba,0xda,0x3b,0x22,0x7e,0x73,0x3a,0x2, 0xbe,0x71,0x2b,0x22,0xca,0x3b,0x7c,0xfb, +0x7f,0x61,0x7f,0x40,0x9f,0x11,0x7f,0x51,0x7f,0x71,0x7a,0x1d,0x3c,0x7a,0x1d,0x40, +0x7a,0x1d,0x44,0xbe,0xf0,0xa, 0x78,0x6, 0x7e,0x54,0x1, 0x3c,0x80,0x4, 0x7e,0x54, +0x2, 0x35,0x7a,0x57,0x23,0x43,0x6c,0xee,0x80,0x60,0xa, 0x5e,0x7f,0x14,0x12,0xc1, +0xcd,0x7a,0x55,0x4a,0xa, 0x5e,0x7f,0x16,0x12,0xc1,0xcd,0x7a,0x55,0x48,0x7e,0x35, +0x48,0x12,0x97,0xc5,0x2f,0x50,0x7e,0x65,0x4a,0x7d,0x16,0x1a,0x2, 0x1a,0x0, 0x2f, +0x70,0x12,0x97,0xc5,0x12,0xc1,0xc3,0x7e,0x1d,0x3c,0x2f,0x10,0x7a,0x1d,0x3c,0x7d, +0x16,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x4a,0x12,0xc1,0xc3,0x7e,0x1d,0x40,0x2f,0x10, +0x7a,0x1d,0x40,0x7e,0x15,0x4a,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x48,0x12,0xc1,0xc3, +0x7e,0x1d,0x44,0x2f,0x10,0x7a,0x1d,0x44,0xb, 0xe0,0xbc,0xfe,0x38,0x9c,0xa, 0xdf, +0x6d,0xcc,0x7f,0x15,0x7f,0x6, 0x12,0x1f,0x58,0x7f,0x51,0x7f,0x17,0x7f,0x6, 0x12, +0x1f,0x58,0x7f,0x71,0x7e,0x94,0x0, 0x64,0x7e,0x1d,0x3c,0x7d,0x19,0x12,0x1e,0xfc, +0x7e,0x87,0x23,0x43,0x7d,0x18,0x7d,0xd8,0x1a,0x12,0x1a,0xc2,0x7f,0x6, 0x12,0x1f, +0x58,0x7a,0x1d,0x3c,0x7e,0x1d,0x40,0x7d,0x19,0x12,0x1e,0xfc,0x7f,0x6, 0x12,0x1f, +0x58,0x7a,0x1d,0x40,0x7e,0x1d,0x44,0x7d,0x19,0x12,0x1e,0xfc,0x7d,0x18,0x1a,0x2, +0x1a,0x0, 0x12,0x1f,0x58,0x7a,0x1d,0x44,0x7f,0x15,0x7f,0x7, 0x12,0x1e,0xeb,0x7e, +0x6d,0x44,0x9f,0x61,0x7f,0x15,0x7f,0x5, 0x12,0x1e,0xeb,0x7e,0x5d,0x3c,0x9f,0x51, +0x7f,0x17,0x7f,0x7, 0x12,0x1e,0xeb,0x7e,0x7d,0x40,0x9f,0x71,0xbe,0x58,0x0, 0x0, +0x68,0x6, 0xbe,0x78,0x0, 0x0, 0x78,0x6, 0x7e,0x44,0x0, 0x64,0x80,0x18,0x7f,0x16, +0x7d,0x19,0x12,0x1e,0xfc,0x7f,0x5, 0x12,0x1f,0x58,0x7f,0x6, 0x12,0x1e,0xeb,0x7f, +0x7, 0x12,0x1f,0x58,0x7d,0x43,0xbe,0x44,0x0, 0x0, 0x18,0x2, 0x6d,0x44,0x7c,0xb9, +0xda,0x3b,0x22,0x1a,0x26,0x1a,0x24,0x12,0x1e,0xeb,0x7f,0x1, 0x22,0x2d,0x35,0x7e, +0x1b,0x70,0xa, 0x57,0x22,0xca,0xf8,0x7f,0x51,0x7f,0x40,0x7e,0x37,0x2f,0x90,0x7a, +0x35,0x2a,0x7e,0x37,0x2f,0x8e,0x7a,0x35,0x2c,0x7e,0x37,0x2f,0x9c,0x7a,0x35,0x26, +0x7e,0x37,0x2f,0x9e,0x7a,0x35,0x28,0x6c,0xff,0x80,0x1e,0x7e,0x34,0x0, 0x26,0x7e, +0x14,0x0, 0x2f,0x74,0x9, 0x12,0x1f,0x8c,0x74,0x2, 0xac,0xbf,0x7f,0x4, 0x2d,0x15, +0x7f,0x15,0x2d,0x35,0x12,0xc2,0x24,0xb, 0xf0,0x7e,0x73,0x39,0x40,0xbc,0x7f,0x38, +0xda,0xda,0xf8,0x22,0x7f,0x71,0x7f,0x60,0x7e,0x35,0x2f,0xbe,0x34,0x0, 0x0, 0x38, +0x7, 0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x2f,0x7e,0x35,0x31,0xbe,0x34,0x0, 0x0, 0x38, +0x7, 0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x31,0xb, 0x6a,0x30,0x9e,0x35,0x33,0x6d,0x22, +0x7e,0x33,0x39,0x42,0x12,0xc2,0x79,0x7e,0x15,0x2f,0x12,0x1f,0x5, 0x1b,0x6a,0x30, +0xb, 0x7a,0x30,0x9e,0x35,0x35,0x6d,0x22,0x7e,0x33,0x39,0x43,0x12,0xc2,0x79,0x7e, +0x15,0x31,0x12,0x1f,0x5, 0x1b,0x7a,0x30,0x22,0xa, 0x13,0x6d,0x0, 0x2, 0x1e,0xeb, +0xca,0x79,0x6c,0xaa,0x7e,0x90,0x2, 0xac,0x9a,0x7f,0x70,0x2d,0xf4,0xb, 0x7a,0xf0, +0x7d,0x7f,0x7c,0xbf,0xa, 0xfa,0x19,0xbf,0x39,0x44,0x7f,0x71,0x2d,0xf4,0xb, 0x7a, +0x40,0x7c,0xb9,0xa, 0x4a,0x19,0xb4,0x39,0x64,0xb, 0xa0,0xbe,0xa0,0x20,0x40,0xd4, +0x7e,0x8, 0x39,0x44,0x7e,0x18,0x39,0x64,0x74,0x20,0x12,0xbe,0x3b,0xda,0x79,0x22, +0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x73,0x39,0x40,0xbe,0x70,0x20,0x40,0x52,0x7e, +0xf0,0x2, 0x80,0x3c,0xa, 0x3f,0x6d,0x22,0x74,0x5, 0x2f,0x11,0x14,0x78,0xfb,0x7e, +0x33,0x39,0x40,0xa, 0x13,0x6d,0x0, 0x12,0x1f,0x7, 0x7c,0xe7,0xbe,0xe0,0x2, 0x50, +0x3, 0x7e,0xe0,0x2, 0xa, 0x6f,0x1b,0x64,0xa, 0x3e,0x1b,0x34,0x7c,0xc7,0x7f,0x5, +0x7c,0xbd,0x12,0xc3,0x2a,0x7f,0x6, 0x7c,0xbd,0x7c,0x7c,0x12,0xc3,0x2a,0xb, 0xf0, +0x7e,0x73,0x39,0x40,0xbc,0x7f,0x50,0xbc,0x7f,0x5, 0x7f,0x16,0x12,0xc2,0x80,0x80, +0x6, 0x74,0x7e,0x7a,0xb3,0x39,0x3f,0xda,0x3b,0x22,0x7c,0x97,0x7c,0xab,0x7f,0x10, +0x7e,0x30,0x2, 0xac,0x3a,0x2d,0x13,0x7d,0x2, 0xb, 0xa, 0x10,0x7e,0x10,0x2, 0xac, +0x19,0x7f,0x71,0x2d,0xf0,0xb, 0x7a,0x0, 0x7c,0x21,0xa5,0xba,0x0, 0x14,0xa, 0x3, +0x1b,0x7a,0x0, 0xbc,0x9a,0x68,0x24,0x6d,0x44,0x74,0x2, 0xa4,0x2d,0x35,0x1b,0x1a, +0x40,0x22,0xbc,0x9a,0x68,0x15,0xa, 0x2, 0xa, 0x13,0x2d,0x10,0xe, 0x14,0x1b,0x7a, +0x10,0x6d,0x11,0x74,0x2, 0xa4,0x2d,0x35,0x1b,0x1a,0x10,0x22,0xca,0x3b,0x7f,0x71, +0x7e,0x60,0x1, 0xb, 0xa, 0x20,0xb, 0x7a,0x50,0x7c,0x4b,0x7a,0x53,0x22,0xf4,0x7a, +0x43,0x23,0xe4,0x7e,0x70,0x1, 0x7e,0xa0,0x1, 0x81,0x9d,0x7e,0x90,0x2, 0xac,0x9a, +0x7f,0x60,0x2d,0xd4,0xb, 0x6a,0xd0,0x7d,0x7d,0x7c,0xbf,0xf5,0x26,0x7f,0x67,0x2d, +0xd4,0xb, 0x6a,0x40,0xa, 0xd5,0xa, 0xbb,0x7d,0xab,0x9d,0xad,0x7d,0x7a,0x7c,0x8f, +0xbe,0x80,0x0, 0x58,0x5, 0x6e,0x80,0xff,0xb, 0x80,0xa, 0xa4,0xa, 0x79,0x9d,0x7a, +0xbe,0xf0,0x0, 0x58,0x5, 0x6e,0xf0,0xff,0xb, 0xf0,0xbe,0x80,0x2, 0x58,0x7, 0xbe, +0xf0,0x2, 0x58,0x2, 0x81,0x9b,0xbe,0x60,0x0, 0x18,0x2, 0x81,0x83,0xbe,0x70,0xec, +0x28,0x2, 0x81,0xa7,0xbe,0x80,0x8, 0x58,0x5, 0xbe,0xf0,0x8, 0x48,0x61,0xa, 0xa7, +0xb, 0xa4,0x7d,0x6a,0x7c,0x7d,0xa, 0xa5,0x2d,0xab,0x12,0xc4,0xeb,0x19,0xba,0x22, +0xf4,0xa, 0xd9,0xa, 0xa4,0x2d,0xad,0x12,0xc4,0xeb,0x19,0xba,0x23,0xe4,0x9, 0xba, +0x22,0xf4,0xa, 0xdb,0xa, 0xc5,0x2d,0xcd,0xe, 0xc4,0x7d,0x6c,0x7c,0xbd,0xa, 0xc7, +0x19,0xbc,0x22,0xf3,0x9, 0xbc,0x23,0xe4,0xa, 0xcb,0xa, 0xa4,0x2d,0xac,0x12,0xc4, +0xeb,0x19,0xba,0x23,0xe3,0x2d,0xdb,0x12,0xc4,0xe2,0x19,0xbd,0x22,0xf5,0xa, 0xd9, +0x12,0xc4,0xe0,0x19,0xbd,0x23,0xe5,0xb, 0xd5,0x7d,0x6d,0x7c,0x7d,0x80,0x24,0xbe, +0x80,0x4, 0x58,0x5, 0xbe,0xf0,0x4, 0x48,0x1a,0xe5,0x26,0xa, 0xcb,0xa, 0xd5,0x12, +0xc4,0xe0,0x19,0xbd,0x22,0xf4,0xa, 0xc9,0xa, 0xd4,0x12,0xc4,0xe0,0x19,0xbd,0x23, +0xe4,0xb, 0x70,0xbe,0x70,0xf0,0x50,0x1f,0x7e,0x51,0x26,0x7c,0x49,0xe5,0x26,0xa, +0xd7,0x19,0xbd,0x22,0xf4,0x19,0x9d,0x23,0xe4,0xb, 0x70,0xb, 0xa0,0x7e,0xb3,0x39, +0x40,0xbc,0xba,0x28,0x2, 0x61,0x9b,0x7a,0x73,0x39,0x40,0x7e,0xa0,0x1, 0x80,0x25, +0xa, 0x3a,0x9, 0xb3,0x22,0xf4,0xa, 0x2b,0x7e,0x70,0x2, 0xac,0x7a,0x7f,0x60,0x2d, +0xd3,0x1b,0x6a,0x20,0xa, 0x2a,0x9, 0xb2,0x23,0xe4,0xa, 0x4b,0x2d,0x3f,0x7d,0x2e, +0x1b,0x1a,0x40,0xb, 0xa0,0x7e,0xb3,0x39,0x40,0xbc,0xba,0x38,0xd3,0xda,0x3b,0x22, +0x2d,0xdc,0xe, 0xd4,0x7d,0x6d,0x7c,0xbd,0xa, 0xd7,0x22,0xe, 0xa4,0x7d,0x6a,0x7c, +0xbd,0xa, 0xa7,0x22,0x7d,0x13,0x3e,0x14,0x3e,0x14,0x3e,0x14,0x7e,0x37,0x39,0xe3, +0x9e,0x37,0x39,0xdf,0x12,0x21,0xa, 0xbd,0x31,0x38,0x12,0x7e,0x37,0x39,0xe5,0x9e, +0x37,0x39,0xe1,0x12,0x21,0xa, 0xbd,0x31,0x38,0x3, 0x74,0x1, 0x22,0xe4,0x22,0xca, +0x79,0x6c,0xaa,0x6d,0x11,0x7d,0x41,0x7d,0x1, 0x7e,0xe3,0x2a,0x2, 0x7e,0xf3,0x2a, +0x3, 0x7e,0x73,0x39,0xde,0x4c,0x77,0x68,0x11,0x7e,0x27,0x39,0xe7,0x4d,0x22,0x78, +0x2, 0xc1,0x10,0xbe,0xe0,0x1, 0x28,0x2, 0xc1,0x10,0xbe,0xe0,0x1, 0x78,0x38,0xbe, +0x70,0x4, 0x78,0x2, 0xc1,0x10,0x7e,0x63,0x34,0x88,0x7e,0x10,0x9, 0xac,0x16,0x49, +0x40,0x29,0x8, 0x49,0x0, 0x29,0xa, 0xbe,0x44,0x0, 0x6e,0x50,0x2, 0xc1,0x10,0xbe, +0x44,0x3, 0x7a,0x28,0x2, 0xc1,0x10,0xbe,0x4, 0x0, 0x6e,0x50,0x2, 0xc1,0x10,0xbe, +0x4, 0x6, 0xc2,0x28,0x2, 0xc1,0x10,0x7c,0xb7,0x14,0x68,0x2b,0x14,0x68,0x51,0x14, +0x68,0x25,0x14,0x68,0x78,0xb, 0xb2,0x78,0x77,0xbe,0xe0,0x1, 0x68,0x2, 0xc1,0x1f, +0x4c,0xff,0x78,0x7b,0x74,0x1, 0x7a,0xb3,0x39,0xde,0x12,0xc6,0x35,0x7e,0x24,0x1, +0xf4,0x7a,0x27,0x39,0xe7,0x80,0x68,0x4c,0xee,0x78,0x17,0xa5,0xbf,0x1, 0x7, 0x74, +0x2, 0x12,0xc6,0x2c,0x80,0x41,0x74,0x4, 0x7a,0xb3,0x39,0xde,0x7e,0x34,0x0, 0x64, +0x80,0x35,0x12,0xc6,0x3e,0x7e,0x34,0x0, 0xa, 0x12,0xc6,0x24,0x68,0x32,0x80,0x3f, +0xbe,0xe0,0x1, 0x78,0x3a,0x4c,0xff,0x78,0x36,0x12,0xc6,0x3e,0x7e,0x37,0x39,0xe7, +0xbe,0x34,0x1, 0xe0,0x38,0x1a,0x7e,0x34,0x0, 0x14,0x12,0xc6,0x24,0x68,0x11,0x12, +0xc6,0x35,0x74,0x3, 0x12,0xc6,0x2c,0x7a,0x37,0x39,0xe7,0x80,0x12,0x7e,0xa0,0x24, +0xe4,0x7a,0xb3,0x39,0xde,0x6d,0x33,0x7a,0x37,0x39,0xe7,0x7c,0xba,0x80,0x2, 0x7c, +0xba,0xda,0x79,0x22,0x12,0xc4,0xf4,0xa, 0x1b,0x4d,0x11,0x22,0x7a,0xb3,0x39,0xde, +0x7e,0x34,0x1, 0xf4,0x22,0x7a,0x47,0x39,0xdf,0x7a,0x7, 0x39,0xe1,0x22,0x7a,0x47, +0x39,0xe3,0x7a,0x7, 0x39,0xe5,0x22,0x7e,0x11,0x2b,0xac,0x1f,0x3e,0x4, 0x7e,0x30, +0x2, 0xac,0x3e,0x2d,0x10,0x7e,0x1d,0x30,0x2d,0x31,0xb, 0x1a,0x20,0x7a,0x27,0x24, +0xf2,0x74,0x2, 0xac,0xbe,0x49,0x35,0x34,0x0, 0xad,0x23,0x74,0xc, 0x22,0x74,0x1, +0x7a,0xb3,0x2b,0x1, 0x7a,0xb3,0x2b,0x1d,0x22,0x3e,0x44,0x7e,0x1f,0x13,0x8a,0x2d, +0x34,0x1b,0x1a,0x50,0x22,0xa, 0x47,0x7f,0x70,0x2d,0xf4,0x7e,0x7b,0x60,0x22,0x74, +0x6, 0x7d,0x30,0x12,0x2f,0x58,0x6c,0x11,0x22,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xb3, +0x1f,0x34,0x22,0x74,0x1, 0x12,0x13,0xde,0xe4,0x2, 0x0, 0x1e,0x74,0x2, 0x12,0x0, +0x1e,0x7e,0x8, 0x6, 0xfc,0x22,0x7a,0x91,0x82,0x7a,0x81,0x83,0xe4,0x93,0x22,0xb, +0xa, 0x30,0x2d,0x32,0x1b,0xa, 0x30,0x22,0x6d,0x33,0xe4,0x6c,0x55,0x2, 0x13,0x1, +0x7e,0x73,0x38,0xbe,0x7a,0x73,0x2b,0x20,0x22,0x7e,0xb3,0x38,0xe1,0x7e,0x34,0x0, +0x4, 0x22,0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0xfc,0x22,0x2d,0x13,0x7e,0xb, 0x50,0xa, +0x25,0x22,0x7e,0x8, 0x2a,0x6d,0x2, 0x0, 0x2e,0x12,0x2f,0x58,0x74,0x6, 0x7d,0x30, +0x22,0x7e,0xb3,0x28,0xa8,0xbe,0xb0,0x1, 0x22,0xe4,0x12,0x13,0xde,0x2, 0x13,0x96, +0xc7,0x10,0x38,0xef,0x79,0x86,0xa, 0x51, diff --git a/drivers/input/touchscreen/ft5435/Makefile b/drivers/input/touchscreen/ft5435/Makefile new file mode 100644 index 0000000000000..c161cc3a8a8f6 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/Makefile @@ -0,0 +1,7 @@ +obj-$(CONFIG_TOUCHSCREEN_FT5435) += ft5435_ts.o +# for focaltech tp firmware power on upgrade + #EXTRA_CFLAGS += -DFOCALTECH_PWRON_UPGRADE + #EXTRA_CFLAGS += -DFOCALTECH_TP_GESTURE + #EXTRA_CFLAGS += -DFOCALTECH_FAE_MOD + #EXTRA_CFLAGS += -DFOCALTECH_FW_COMPAT + diff --git a/drivers/input/touchscreen/ft5435/ft5435_ts.c b/drivers/input/touchscreen/ft5435/ft5435_ts.c new file mode 100644 index 0000000000000..7ebb3a2876e03 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/ft5435_ts.c @@ -0,0 +1,4294 @@ +/* + * + * FocalTech ft5435 TouchScreen driver. + * + * Copyright (c) 2010 Focal tech Ltd. + * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ft5435_ts.h" + + +#include +#include + +#if defined(CONFIG_FB) +#include +#include + +#elif defined(CONFIG_HAS_EARLYSUSPEND) +#include +#include +/* Early-suspend level */ +#define FT_SUSPEND_LEVEL 1 +#endif + +#if defined(FOCALTECH_AUTO_UPGRADE) +#define FTS_VENDOR_1 0x3b +#define FTS_VENDOR_2 0x51 +static unsigned char firmware_data_vendor1[] = { + #include "HQ_AL1512_C6_FT5435_Biel0x3b_Ver0a_20170119_app.i" +}; + +static unsigned char firmware_data_vendor2[] = { + + #include "HQ_AL1512_C6_FT5435_Ofilm0x51_Ver0a_20170119_app.i" +}; +#endif +#define TCT_KEY_BACK 158 +#define TCT_KEY_HOME 172 +#define TCT_KEY_MENU 139 + + + +#define TCT_KEY_BACK_POS_X 100 +#define TCT_KEY_BACK_POS_Y 1321 + +#define TCT_KEY_HOME_POS_X 360 +#define TCT_KEY_HOME_POS_Y 1321 + +#define TCT_KEY_MENU_POS_X 620 +#define TCT_KEY_MENU_POS_Y 1321 + +#define TX_NUM_MAX 50 +#define RX_NUM_MAX 50 + + + +/* [PLATFORM]-Mod-BEGIN by TCTNB.ZXZ, PR-814306, 2014/10/24, add for rawdata test */ +#define CONFIG_TCT_TP_FTDEBUG + +/* [PLATFORM]-Mod-END by TCTNB.ZXZ */ + +#define FT_DRIVER_VERSION 0x02 + +#define TRULY 0x79 +#define CHAOSHENG 0x57 + +#define FT_META_REGS 3 +#define FT_ONE_TCH_LEN 6 +#define FT_TCH_LEN(x) (FT_META_REGS + FT_ONE_TCH_LEN * x) + +#define FT_PRESS 0x7F +#define FT_MAX_ID 0x0F +#define FT_TOUCH_X_H_POS 3 +#define FT_TOUCH_X_L_POS 4 +#define FT_TOUCH_Y_H_POS 5 +#define FT_TOUCH_Y_L_POS 6 +#define FT_TD_STATUS 2 +#define FT_TOUCH_EVENT_POS 3 +#define FT_TOUCH_ID_POS 5 +#define FT_TOUCH_DOWN 0 +#define FT_TOUCH_CONTACT 2 + +/*register address*/ +#define FT_REG_DEV_MODE 0x00 +#define FT_DEV_MODE_REG_CAL 0x02 +#define FT_REG_ID 0xA3 +#define FT_REG_PMODE 0xA5 +#define FT_REG_FW_VER 0xA6 +#define FT_REG_FW_VENDOR_ID 0xA8 +#define FT_REG_POINT_RATE 0x88 +#define FT_REG_THGROUP 0x80 +#define FT_REG_ECC 0xCC +#define FT_REG_RESET_FW 0x07 +#define FT_REG_FW_MIN_VER 0xB2 +#define FT_REG_FW_SUB_MIN_VER 0xB3 + +/* power register bits*/ +#define FT_PMODE_ACTIVE 0x00 +#define FT_PMODE_MONITOR 0x01 +#define FT_PMODE_STANDBY 0x02 +#define FT_PMODE_HIBERNATE 0x03 +#define FT_FACTORYMODE_VALUE 0x40 +#define FT_WORKMODE_VALUE 0x00 +#define FT_RST_CMD_REG1 0xFC +#define FT_RST_CMD_REG2 0xBC +#define FT_READ_ID_REG 0x90 +#define FT_ERASE_APP_REG 0x61 +#define FT_ERASE_PANEL_REG 0x63 +#define FT_FW_START_REG 0xBF + +#define FT_STATUS_NUM_TP_MASK 0x0F + +#define FT_VTG_MIN_UV 2600000 +#define FT_VTG_MAX_UV 3300000 +#define FT_I2C_VTG_MIN_UV 1800000 +#define FT_I2C_VTG_MAX_UV 1800000 + +#define FT_COORDS_ARR_SIZE 4 +#define MAX_BUTTONS 4 + +#define FT_8BIT_SHIFT 8 +#define FT_4BIT_SHIFT 4 +#define FT_FW_NAME_MAX_LEN 50 + +#define FT5316_ID 0x0A +#define FT5306I_ID 0x55 +#define FT6X06_ID 0x06 +#define FT6X36_ID 0x36 +#define FT5X46_ID 0x54 + +#define FT_UPGRADE_AA 0xAA +#define FT_UPGRADE_55 0x55 + +#define FT_FW_MIN_SIZE 8 +#define FT_FW_MAX_SIZE 65536 + +/* Firmware file is not supporting minor and sub minor so use 0 */ +#define FT_FW_FILE_MAJ_VER(x) ((x)->data[(x)->size - 2]) +#define FT_FW_FILE_MIN_VER(x) 0 +#define FT_FW_FILE_SUB_MIN_VER(x) 0 +#define FT_FW_FILE_VENDOR_ID(x) ((x)->data[(x)->size - 1]) + +#define FT_FW_FILE_MAJ_VER_FT6X36(x) ((x)->data[0x10a]) +#define FT_FW_FILE_VENDOR_ID_FT6X36(x) ((x)->data[0x108]) + +/** +* Application data verification will be run before upgrade flow. +* Firmware image stores some flags with negative and positive value +* in corresponding addresses, we need pick them out do some check to +* make sure the application data is valid. +*/ +#define FT_FW_CHECK(x, ts_data) \ + (ts_data->family_id == FT6X36_ID ? \ + (((x)->data[0x104] ^ (x)->data[0x105]) == 0xFF \ + && ((x)->data[0x106] ^ (x)->data[0x107]) == 0xFF) : \ + (((x)->data[(x)->size - 8] ^ (x)->data[(x)->size - 6]) == 0xFF \ + && ((x)->data[(x)->size - 7] ^ (x)->data[(x)->size - 5]) == 0xFF \ + && ((x)->data[(x)->size - 3] ^ (x)->data[(x)->size - 4]) == 0xFF)) + +#define FT_MAX_TRIES 5 +#define FT_RETRY_DLY 20 + +#define FT_MAX_WR_BUF 10 +#define FT_MAX_RD_BUF 2 +#define FT_FW_PKT_LEN 128 +#define FT_FW_PKT_META_LEN 6 +#define FT_FW_PKT_DLY_MS 20 +#define FT_FW_LAST_PKT 0x6ffa +#define FT_EARSE_DLY_MS 100 +#define FT_55_AA_DLY_NS 5000 + +#define FT_UPGRADE_LOOP 30 +#define FT_CAL_START 0x04 +#define FT_CAL_FIN 0x00 +#define FT_CAL_STORE 0x05 +#define FT_CAL_RETRY 100 +#define FT_REG_CAL 0x00 +#define FT_CAL_MASK 0x70 + +#define FT_INFO_MAX_LEN 512 + +#define FT_BLOADER_SIZE_OFF 12 +#define FT_BLOADER_NEW_SIZE 30 +#define FT_DATA_LEN_OFF_OLD_FW 8 +#define FT_DATA_LEN_OFF_NEW_FW 14 +#define FT_FINISHING_PKT_LEN_OLD_FW 6 +#define FT_FINISHING_PKT_LEN_NEW_FW 12 +#define FT_MAGIC_BLOADER_Z7 0x7bfa +#define FT_MAGIC_BLOADER_LZ4 0x6ffa +#define FT_MAGIC_BLOADER_GZF_30 0x7ff4 +#define FT_MAGIC_BLOADER_GZF 0x7bf4 + +enum { + FT_BLOADER_VERSION_LZ4 = 0, + FT_BLOADER_VERSION_Z7 = 1, + FT_BLOADER_VERSION_GZF = 2, +}; + +enum { + FT_FT5336_FAMILY_ID_0x11 = 0x11, + FT_FT5336_FAMILY_ID_0x12 = 0x12, + FT_FT5336_FAMILY_ID_0x13 = 0x13, + FT_FT5336_FAMILY_ID_0x14 = 0x14, +}; + +enum proximity_sensor_vendor { + TAOS = 1, + STK, + TOTAL, +}; + +extern int set_usb_charge_mode_par; +extern int TX_NUM; +extern int RX_NUM; +extern int SCab_1; +extern int SCab_2; +extern int SCab_3; +extern int SCab_4; +extern int SCab_5; +extern int SCab_6; +extern int SCab_7; +extern int SCab_8; +extern int Save_rawData1[TX_NUM_MAX][RX_NUM_MAX]; + + +#define FTS_FACTORYMODE_VALUE 0x40 +#define FTS_WORKMODE_VALUE 0x00 +static struct i2c_client *ft_g_client; + +#define FT_STORE_TS_INFO(buf, id, name, max_tch, group_id, fw_vkey_support, \ + fw_name, fw_maj, fw_min, fw_sub_min) \ + snprintf(buf, FT_INFO_MAX_LEN, \ + "controller\t= focaltech\n" \ + "model\t\t= 0x%x\n" \ + "name\t\t= %s\n" \ + "max_touches\t= %d\n" \ + "drv_ver\t\t= 0x%x\n" \ + "group_id\t= 0x%x\n" \ + "fw_vkey_support\t= %s\n" \ + "fw_name\t\t= %s\n" \ + "fw_ver\t\t= %d.%d.%d\n", id, name, \ + max_tch, FT_DRIVER_VERSION, group_id, \ + fw_vkey_support, fw_name, fw_maj, fw_min, \ + fw_sub_min) + +#define FT_DEBUG_DIR_NAME "ts_debug" + + u8 fts_fw_vendor_id; + +struct ft5435_ts_data { + struct i2c_client *client; + struct input_dev *input_dev; + const struct ft5435_ts_platform_data *pdata; + struct regulator *vdd; + struct regulator *vcc_i2c; + char fw_name[FT_FW_NAME_MAX_LEN]; + bool loading_fw; + u8 family_id; + struct dentry *dir; + u16 addr; + bool suspended; + char *ts_info; + u8 *tch_data; + u32 tch_data_len; + u8 fw_ver[3]; + int touch_log_switch; +#if defined(FOCALTECH_FW_COMPAT) + u8 fw_compat; +#endif +#if defined(FOCALTECH_PWRON_UPGRADE) + struct delayed_work focaltech_update_work; +#endif + u8 fw_vendor_id; +#if defined(CONFIG_FB) + struct notifier_block fb_notif; +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif + + struct pinctrl *ts_pinctrl; + struct pinctrl_state *gpio_state_active; + struct pinctrl_state *gpio_state_suspend; + +#if defined(FOCALTECH_TP_GLOVE) + u8 glove_id; +#endif + +#if defined(USB_CHARGE_DETECT) +struct work_struct work; +u8 charger_in; +#endif +#if defined(LEATHER_COVER) +struct work_struct work_cover; +u8 cover_on; +#endif +#if defined(VR_GLASS) +struct work_struct work_vr; +u8 vr_on; +#endif +}; +bool is_ft5435 = false; +struct wake_lock ft5436_wakelock; + +static int ft5435_i2c_read(struct i2c_client *client, char *writebuf, + int writelen, char *readbuf, int readlen); +static int ft5x0x_read_reg(struct i2c_client *client, u8 addr, u8 *val); + +#ifdef CONFIG_TOUCHPANEL_PROXIMITY_SENSOR +struct virtualpsensor { + char const *name; + struct input_dev *proximity_dev; + int proximity_function; + int vps_enabled; + struct sensors_classdev vps_cdev; + int value; +}; + +struct virtualpsensor *vps_ft5436; + +#define VPS_NAME "virtual-proximity" + +struct sensors_classdev virtual_sensors_proximity_cdev2 = { + .name = VPS_NAME, + .vendor = "NULL", + .version = 1, + .handle = SENSORS_PROXIMITY_HANDLE, + .type = SENSOR_TYPE_PROXIMITY, + .max_range = "5", + .resolution = "5.0", + .sensor_power = "3", + .min_delay = 0, /* in microseconds */ + .fifo_reserved_event_count = 0, + .fifo_max_event_count = 0, + .enabled = 0, + .delay_msec = 100, + .sensors_enable = NULL, + .sensors_poll_delay = NULL, +}; + +static int vps_set_enable(struct sensors_classdev *sensors_cdev, unsigned int enable); + +static void tp_prox_sensor_enable(struct i2c_client *client, int enable); +#endif +static int ft5435_i2c_write(struct i2c_client *client, char *writebuf, int writelen); +static struct workqueue_struct *ft5435_wq_cover; +#if defined(VR_GLASS) +static struct workqueue_struct *ft5435_wq_vr; +#endif +static struct workqueue_struct *ft5435_wq; +static struct ft5435_ts_data *g_ft5435_ts_data; + +static int init_ok; +module_param_named(init_ok, init_ok, int, 0644); + + + +static void ft5435_update_fw_ver(struct ft5435_ts_data *data) +{ + struct i2c_client *client = data->client; + u8 reg_addr; + int err; + + reg_addr = FT_REG_FW_VER; + err = ft5435_i2c_read(client, ®_addr, 1, &data->fw_ver[0], 1); + if (err < 0) + dev_err(&client->dev, "fw major version read failed"); + + reg_addr = FT_REG_FW_MIN_VER; + err = ft5435_i2c_read(client, ®_addr, 1, &data->fw_ver[1], 1); + if (err < 0) + dev_err(&client->dev, "fw minor version read failed"); + + reg_addr = FT_REG_FW_SUB_MIN_VER; + err = ft5435_i2c_read(client, ®_addr, 1, &data->fw_ver[2], 1); + if (err < 0) + dev_err(&client->dev, "fw sub minor version read failed"); + + dev_info(&client->dev, "Firmware version = %d.%d.%d\n", + data->fw_ver[0], data->fw_ver[1], data->fw_ver[2]); +} + +static struct mutex g_device_mutex; + +#if defined(FOCALTECH_TP_GESTURE) + +/* [PLATFORM]-Mod-BEGIN by TCTNB.YQJ, FR797197, 2014/11/28 modify for 5x36 tp register of gesture */ +#define FT5435_REG_GESTURE_SET 0xd0 +#define FT5435_REG_GESTURE_STATE 0xd3 + +#define GESTURE_DB 0x24 + +/* [PLATFORM]-Mod-END by TCTNB.YQJ */ +static int ft_tp_suspend(struct ft5435_ts_data *data); +#endif +static int ft5435_i2c_read(struct i2c_client *client, char *writebuf, + int writelen, char *readbuf, int readlen) +{ + int ret; + if (writelen > 0) { + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = writelen, + .buf = writebuf, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = readlen, + .buf = readbuf, + }, + }; + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret < 0) + dev_err(&client->dev, "%s: i2c read error.\n", + __func__); + } else { + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = readlen, + .buf = readbuf, + }, + }; + ret = i2c_transfer(client->adapter, msgs, 1); + if (ret < 0) + dev_err(&client->dev, "%s:i2c read error.\n", __func__); + } + return ret; +} + +static int ft5435_i2c_write(struct i2c_client *client, char *writebuf, + int writelen) +{ + int ret; + + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = writelen, + .buf = writebuf, + }, + }; + ret = i2c_transfer(client->adapter, msgs, 1); + if (ret < 0) + dev_err(&client->dev, "%s: i2c write error.\n", __func__); + return ret; +} + +#if defined(FOCALTECH_TP_GLOVE) + +#define FOCALTECH_TP_GLOVE_SET 0xc0 +#define FOCALTECH_TP_GLOVE_ENABLE 0x01 + +static struct device *tp_glove_dev; + +/* + u8 glove_id; 0: close glove function, 1: open glove function +*/ +static ssize_t tp_glove_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5435_ts_data *data = NULL; + int ret; + + data = dev_get_drvdata(dev); + + ret = snprintf(buf, 50, "glove_id show:%d\n", data->glove_id); + + return ret; +} + +static ssize_t tp_glove_id_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct ft5435_ts_data *data = NULL; + unsigned long val = 0; + char val_read = 0; + ssize_t ret = -EINVAL; + char txbuf[2]; + txbuf[0] = FOCALTECH_TP_GLOVE_SET; + + + data = dev_get_drvdata(dev); + + if (data->suspended) + return ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + + if (0 == val) { + data->glove_id = 0x00; + txbuf[1] = 0x00; + ft5435_i2c_write(data->client, txbuf, sizeof(txbuf)); + } else + if (1 == val) { + data->glove_id = 0x01; + txbuf[1] = FOCALTECH_TP_GLOVE_ENABLE; + ft5435_i2c_write(data->client, txbuf, sizeof(txbuf)); + } else { + pr_err("invalid command! \n"); + return -EPERM; + } + printk("set glove_id = %d \n", data->glove_id); + ft5435_i2c_read(data->client, &txbuf[0], 1, &val_read, 1); + printk("read glove_id = %d\n", val_read); + + return size; +} +static DEVICE_ATTR(glove_enable, 0644, tp_glove_id_show, tp_glove_id_store); + +void tp_glove_register (struct ft5435_ts_data *data) +{ + int rc = 0; + + tp_glove_dev = device_create(tp_device_class, NULL, 0, NULL, "tp_glove"); + if (IS_ERR(tp_glove_dev)) + pr_err("Failed to create device(glove_ctrl)!\n"); + + + rc = device_create_file(tp_glove_dev, &dev_attr_glove_enable); + if (rc < 0) + pr_err("Failed to create device file(%s)!\n", dev_attr_glove_enable.attr.name); + dev_set_drvdata(tp_glove_dev, data); + + printk("~~~~~ %s enable!!!!!\n", __func__); + +} +#endif + + + +static int ft5x0x_write_reg(struct i2c_client *client, u8 addr, const u8 val) +{ + u8 buf[2] = {0}; + + buf[0] = addr; + buf[1] = val; + + return ft5435_i2c_write(client, buf, sizeof(buf)); +} + +static int ft5x0x_read_reg(struct i2c_client *client, u8 addr, u8 *val) +{ + return ft5435_i2c_read(client, &addr, 1, val, 1); +} +#ifdef CONFIG_TOUCHPANEL_PROXIMITY_SENSOR +int virtual_psensor_input_register2(struct i2c_client *pClient) +{ + s32 nRetVal = 0; + + pr_err("*** %s() ***\n", __func__); + + vps_ft5436->proximity_dev = input_allocate_device(); + if (vps_ft5436->proximity_dev == NULL) { + pr_err("*** input device allocation failed ***\n"); + return -ENOMEM; + } + + vps_ft5436->proximity_dev->name = "proximity"; + vps_ft5436->proximity_dev->id.bustype = BUS_I2C; + + /* set the supported event type for input device */ + set_bit(EV_ABS, vps_ft5436->proximity_dev->evbit); + set_bit(ABS_DISTANCE, vps_ft5436->proximity_dev->absbit); + input_set_abs_params(vps_ft5436->proximity_dev, ABS_DISTANCE, 0, 1, 0, 0); + + nRetVal = input_register_device(vps_ft5436->proximity_dev); + if (nRetVal < 0) { + pr_err("*** Unable to register virtual P-sensor input device ***\n"); + return nRetVal; + } + + vps_ft5436->vps_cdev = virtual_sensors_proximity_cdev2; + vps_ft5436->vps_cdev.sensors_enable = vps_set_enable; + vps_ft5436->vps_cdev.sensors_poll_delay = NULL; + + nRetVal = sensors_classdev_register(&pClient->dev, &vps_ft5436->vps_cdev); + if (nRetVal) { + pr_err("%s: Unable to register to sensors class: %d\n", __func__, nRetVal); + return nRetVal; + } + + return 0; +} +static void tp_prox_sensor_enable(struct i2c_client *client, int enable) +{ + u8 state; + int ret = -1; + + if (client == NULL) + return; + + if (gpio_is_valid(g_ft5435_ts_data->pdata->reset_gpio)) { + gpio_set_value_cansleep(g_ft5435_ts_data->pdata->reset_gpio, 0); + printk("reset tp ~~~ \n"); + msleep(g_ft5435_ts_data->pdata->hard_rst_dly); + gpio_set_value_cansleep(g_ft5435_ts_data->pdata->reset_gpio, 1); + } + msleep(g_ft5435_ts_data->pdata->soft_rst_dly); + + if (enable) { + state = 0x01; + } else{ + state = 0x00; + } + ret = ft5x0x_write_reg(client, 0xB0, state); + if (ret < 0) + printk("[proxi_5206]write psensor switch command failed\n"); + ft5x0x_read_reg(client, 0xB0, &state); + printk(" proximity function status[0x%x]\n", state); + if ((!enable) && (g_ft5435_ts_data->suspended) && (g_ft5435_ts_data->gesture_id > 0)) { + printk("double click function enable again \n"); + ft_tp_suspend(g_ft5435_ts_data); + } + + return; +} +static int vps_set_enable(struct sensors_classdev *sensors_cdev, unsigned int enable) +{ + u8 status, reg_value; + + printk("FT vps_set_enable in. enable[%d]\n", enable); + vps_ft5436->vps_enabled = enable ? 1 : 0; + if (enable == 1) { + ft5x0x_read_reg(g_ft5435_ts_data->client, 0xB0, ®_value); + printk("FT proxi_fts 0xB0 state value is0x%02X\n", reg_value); + if (!(reg_value&0x01)) + tp_prox_sensor_enable(g_ft5435_ts_data->client, 1); + ft5x0x_read_reg(g_ft5435_ts_data->client, 0x01, &status); + printk("FT 0x01 reg status[0x%x]\n", status); + if (status == 0xC0) { + input_report_abs(vps_ft5436->proximity_dev, ABS_DISTANCE, 0); + input_sync(vps_ft5436->proximity_dev); + } else if (status == 0xE0) { + input_report_abs(vps_ft5436->proximity_dev, ABS_DISTANCE, 1); + input_sync(vps_ft5436->proximity_dev); + } + } + + return 0; +} + +ssize_t ft_virtual_proximity_enable_show(struct device *pDevice, struct device_attribute *pAttr, char *pBuf) +{ + return sprintf(pBuf, "%d", vps_ft5436->vps_enabled); +} +ssize_t ft_virtual_proximity_enable_store(struct device *pDevice, struct device_attribute *pAttr, const char *pBuf, size_t nSize) +{ + int enable; + if (pBuf != NULL) { + sscanf(pBuf, "%d\n", &enable); + vps_set_enable(&vps_ft5436->vps_cdev, enable); + if (g_ft5435_ts_data->gesture_id == 0) { + if (enable) + device_init_wakeup(&g_ft5435_ts_data->client->dev, 1); + else + device_init_wakeup(&g_ft5435_ts_data->client->dev, 0); + } + } + return nSize; +} + +static DEVICE_ATTR(enable, 0664, ft_virtual_proximity_enable_show, ft_virtual_proximity_enable_store); + +ssize_t ft_proximity_function_enable_show(struct device *pDevice, struct device_attribute *pAttr, char *pBuf) +{ + return sprintf(pBuf, "%x", vps_ft5436->proximity_function); +} + +ssize_t ft_proximity_function_enable_store(struct device *pDevice, struct device_attribute *pAttr, const char *pBuf, size_t nSize) +{ + u32 nProximityMode; + if (pBuf != NULL) { + sscanf(pBuf, "%x", &nProximityMode); + printk("nProximityMode = 0x%x\n", nProximityMode); + vps_ft5436->proximity_function = nProximityMode; + tp_prox_sensor_enable(g_ft5435_ts_data->client, nProximityMode); + } + return nSize; +} + +static DEVICE_ATTR(proximity, 0664, ft_proximity_function_enable_show, ft_proximity_function_enable_store); + +static int sys_device_create(void) +{ + struct class *virtual_proximity = NULL; + struct device *virtual_proximity_device = NULL; + + virtual_proximity = class_create(THIS_MODULE, "virtual-proximity"); + if (IS_ERR(virtual_proximity)) + printk("Failed to create class(virtual_proximity)!\n"); + + virtual_proximity_device = device_create(virtual_proximity, NULL, 0, NULL, "device"); + if (IS_ERR(virtual_proximity_device)) + printk("Failed to create device(virtual_proximity_device)!\n"); + + if (device_create_file(virtual_proximity_device, &dev_attr_enable) < 0) + printk("Failed to create device file(%s)!\n", dev_attr_enable.attr.name); + + if (device_create_file(virtual_proximity_device, &dev_attr_proximity) < 0) + printk("Failed to create device file(%s)!\n", dev_attr_enable.attr.name); + + return 0; +} + +#endif +#if defined(LEATHER_COVER) +void ft5435_enable_leather_cover(void) +{ + struct ft5435_ts_data *data; + + if (!ft_g_client) + return ; + if (init_ok == 0) + return; + printk("[wxc]%s\n", __func__); + data = g_ft5435_ts_data; + + data->cover_on = 1; + + queue_work(ft5435_wq_cover, &data->work_cover); +} +EXPORT_SYMBOL(ft5435_enable_leather_cover); +void ft5435_disable_leather_cover(void) +{ + struct ft5435_ts_data *data; + + + if (!ft_g_client) + return ; + if (init_ok == 0) + return; + printk("[wxc]%s\n", __func__); + data = g_ft5435_ts_data; + + data->cover_on = 0; + + queue_work(ft5435_wq_cover, &data->work_cover); +} +EXPORT_SYMBOL(ft5435_disable_leather_cover); +void ft5435_change_leather_cover_switch(struct work_struct *work) +{ + u8 cover_flag = 0; + struct ft5435_ts_data *data; + + + data = g_ft5435_ts_data; + + if (data->suspended) { + printk(KERN_ERR"data->suspended, data->cover_on = %d \n", data->cover_on); + return ; + } + if (ft_g_client == NULL) + return ; + ft5x0x_read_reg(ft_g_client, 0xc1, &cover_flag); + printk("[Fu]%s cover_flag=%d, data->cover_on=%d\n", __func__, cover_flag, data->cover_on); + if (cover_flag != data->cover_on) { + printk(KERN_ERR"[Fu]%s: Write %d to 0xc1\n", __FUNCTION__, data->cover_on); + ft5x0x_write_reg(ft_g_client, 0xc1, data->cover_on); + } +} + +#endif +#if defined(VR_GLASS) +void ft5435_enable_vr(void) +{ + struct ft5435_ts_data *data; + + if (!ft_g_client) + return ; + if (init_ok == 0) + return; + printk("[wxc]%s\n", __func__); + data = g_ft5435_ts_data; + + data->vr_on = 1; + + queue_work(ft5435_wq_vr, &data->work_vr); +} +EXPORT_SYMBOL(ft5435_enable_vr); +void ft5435_disable_vr(void) +{ + struct ft5435_ts_data *data; + + if (!ft_g_client) + return ; + if (init_ok == 0) + return; + printk("[wxc]%s\n", __func__); + data = g_ft5435_ts_data; + + data->vr_on = 0; + + queue_work(ft5435_wq_vr, &data->work_vr); +} +EXPORT_SYMBOL(ft5435_disable_vr); +void ft5435_change_vr_switch(struct work_struct *work) +{ + u8 vr_flag = 0; + struct ft5435_ts_data *data; + + + data = g_ft5435_ts_data; + + if (data->suspended) { + printk(KERN_ERR"data->suspended, data->vr_on = %d \n", data->vr_on); + return ; + } + if (ft_g_client == NULL) + return ; + ft5x0x_read_reg(ft_g_client, 0xc1, &vr_flag); + printk("[wxc]%s cover_flag=%d, data->vr_on=%d\n", __func__, vr_flag, data->vr_on); + if (vr_flag != data->vr_on) { + printk(KERN_ERR"[wxc]%s: Write %d to 0xc1\n", __FUNCTION__, data->vr_on); + ft5x0x_write_reg(ft_g_client, 0xc1, data->vr_on); + } +} + +#endif +#if defined(USB_CHARGE_DETECT) +void ft5435_enable_change_scanning_frq(void) +{ + struct ft5435_ts_data *data; + + if (!ft_g_client) + return ; + if (init_ok == 0) + return; + + data = g_ft5435_ts_data; + + data->charger_in = 1; + pr_debug("%s \n", __func__); + + queue_work(ft5435_wq, &data->work); +} +EXPORT_SYMBOL(ft5435_enable_change_scanning_frq); +void ft5435_disable_change_scanning_frq(void) +{ + struct ft5435_ts_data *data; + + + if (!ft_g_client) + return ; + if (init_ok == 0) + return; + + data = g_ft5435_ts_data; + + data->charger_in = 0; + pr_debug("%s \n", __func__); + + queue_work(ft5435_wq, &data->work); +} +EXPORT_SYMBOL(ft5435_disable_change_scanning_frq); +void ft5435_change_scanning_frq_switch(struct work_struct *work) +{ + u8 charger_in_flag = 0; + struct ft5435_ts_data *data; + + + data = container_of(work, struct ft5435_ts_data, work); + + if (data->suspended) { + printk(KERN_ERR"changer_in = %d \n", data->charger_in); + return ; + } + if (ft_g_client == NULL) + return ; + ft5x0x_read_reg(ft_g_client, 0x8b, &charger_in_flag); + + if (charger_in_flag != data->charger_in) { + printk(KERN_ERR"[ft5435]%s: Write %d to 0x8b\n", __FUNCTION__, data->charger_in); + ft5x0x_write_reg(ft_g_client, 0x8b, data->charger_in); + } +} + +void tpd_usb_plugin(bool mode) +{ + struct ft5435_ts_data *data = g_ft5435_ts_data; + int ret = -1; + if (data->suspended) + return ; + if (ft_g_client == NULL) + return ; + ret = ft5x0x_write_reg(ft_g_client, 0x8b, mode); + if (ret < 0) + pr_err("usb detect write err: %s %d.\n", __FUNCTION__, mode); +} + +#else +void ft5435_enable_change_scanning_frq(void) +{ +} +EXPORT_SYMBOL(ft5435_enable_change_scanning_frq); +void ft5435_disable_change_scanning_frq(void) +{ +} +EXPORT_SYMBOL(ft5435_disable_change_scanning_frq); +#endif +static void ft5435_update_fw_vendor_id(struct ft5435_ts_data *data) +{ + struct i2c_client *client = data->client; + u8 reg_addr; + int err; + + reg_addr = FT_REG_FW_VENDOR_ID; + err = ft5435_i2c_read(client, ®_addr, 1, &data->fw_vendor_id, 1); + if (err < 0) + dev_err(&client->dev, "fw vendor id read failed"); + printk("[Fu]fw_vendor_id=0x%x\n", data->fw_vendor_id); +} + + +int fts_ctpm_auto_clb(struct i2c_client *client) +{ + unsigned char uc_temp = 0x00; + unsigned char i = 0; + + /*start auto CLB */ + msleep(200); + + ft5x0x_write_reg(client, 0, FTS_FACTORYMODE_VALUE); + /*make sure already enter factory mode */ + msleep(100); + /*write command to start calibration */ + ft5x0x_write_reg(client, 2, 0x4); + msleep(300); + for (i = 0; i < 100; i++) { + ft5x0x_read_reg(client, 0, &uc_temp); + /*return to normal mode, calibration finish */ + if (0x0 == ((uc_temp & 0x70) >> 4)) + break; + } + + msleep(200); + /*calibration OK */ + msleep(300); + ft5x0x_write_reg(client, 0, FTS_FACTORYMODE_VALUE); /*goto factory mode for store */ + msleep(100); /*make sure already enter factory mode */ + ft5x0x_write_reg(client, 2, 0x5); /*store CLB result */ + msleep(300); + ft5x0x_write_reg(client, 0, FTS_WORKMODE_VALUE); /*return to normal mode */ + msleep(300); + + /*store CLB result OK */ + return 0; +} + + +/* [PLATFORM]-Mod-BEGIN by TCTNB.ZXZ, PR-814306, 2014/10/24, add for alto5 premium firmware version*/ +#ifdef CONFIG_TCT_8X16_ALTO5_PREMIUM +static struct class *firm_ver_class; +static struct device *firm_ver_dev; + +static ssize_t firm_ver_show (struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 reg_ver; + u8 reg_vendor; + u8 ver_value, vendor_value; + int err; + reg_ver = FT_REG_FW_VER; + err = ft5435_i2c_read(ft_g_client, ®_ver, 1, &ver_value, 1); + if (err < 0) { + pr_err("TP FW version read failure\n"); + return sprintf (buf, "can't read firmware version \n"); + } + pr_err("0xA6=0x%x\n", ver_value); + reg_vendor = 0xA8; + err = ft5435_i2c_read(ft_g_client, ®_vendor, 1, &vendor_value, 1); + if (err < 0) { + pr_err("TP FW version read failure\n"); + return sprintf (buf, "ft irmware version(0xA6) is 0x%x\n can't read tp moudule version \n" , ver_value); + } + pr_err("0xA8=0x%x\n", vendor_value); + + return sprintf (buf, "ft TP module (0xA8)is 0x%x , fimware version(0xA6) is 0x%x\n", vendor_value, ver_value); +} + +static DEVICE_ATTR(firm_ver, 0664, firm_ver_show, NULL); + + +static void firm_ver_attr_create(void) +{ + firm_ver_class = class_create(THIS_MODULE, "firmware_ver"); + if (IS_ERR(firm_ver_class)) + pr_err("Failed to create class(firm_ver_class)!\n"); + firm_ver_dev = device_create(firm_ver_class, + NULL, 0, NULL, "device"); + if (IS_ERR(firm_ver_dev)) + pr_err("Failed to create device(gt_dclick_dev)!\n"); + + + if (device_create_file(firm_ver_dev, &dev_attr_firm_ver) < 0) + pr_err("Failed to create device file(%s)!\n", dev_attr_firm_ver.attr.name); +} +#endif +/* [PLATFORM]-Mod-END by TCTNB.ZXZ*/ + +#if defined(FOCALTECH_TP_GESTURE) +#define WAKEUP_OFF 4 +#define WAKEUP_ON 5 +static bool gesture_func_on = true; +static int ft5435_gesture_switch(struct input_dev *dev, unsigned int type, unsigned int code, int value) +{ + if (type == EV_SYN && code == SYN_CONFIG) { + if (value == WAKEUP_OFF) { + gesture_func_on = false; + } else if (value == WAKEUP_ON) { + gesture_func_on = true; + } + } + return 0; +} + +static int ft_tp_interrupt(struct ft5435_ts_data *data) +{ + int rc = 0; + u8 reg_value, reg = 0x00; + printk("[FTS]%s start\n", __func__); + reg = FT5435_REG_GESTURE_STATE; + rc = ft5435_i2c_read(data->client, ®, 1, ®_value, 1); + if (rc < 0) { + dev_err(&data->client->dev, "%s: read data fail\n", __func__); + return rc; + } + + if (GESTURE_DB == reg_value) { + input_report_key(data->input_dev, KEY_WAKEUP, 1); + input_sync(data->input_dev); + input_report_key(data->input_dev, KEY_WAKEUP, 0); + input_sync(data->input_dev); + printk("[FTS]gesture KEY_POWER\n"); + } else { + printk("[FTS]gesture_id, reg_value=0x%x \n", reg_value); + } + + return rc; +} +#endif +static irqreturn_t ft5435_ts_interrupt(int irq, void *dev_id) +{ +#if 1 + struct ft5435_ts_data *data = dev_id; + struct input_dev *ip_dev; + int rc, i, j; + u32 id, x, y, status, num_touches; + u8 reg = 0x00, *buf; + bool update_input = false; + + #ifdef CONFIG_TOUCHPANEL_PROXIMITY_SENSOR + u8 reg_value; + u8 proximity_status; + #endif + #ifdef FOCALTECH_TP_GESTURE + int ret = 0; + u8 state = 0; + #endif + + if (!data) { + pr_err("%s: Invalid data\n", __func__); + return IRQ_HANDLED; + } +#if defined(FOCALTECH_TP_GESTURE) + if (gesture_func_on) { + ret = ft5x0x_read_reg(data->client, 0xd0, &state); + if (ret < 0) + printk("[FTS]read value fail\n"); + + if (state == 1) { + ft_tp_interrupt(data); + return IRQ_HANDLED; + } + } +#endif + + ip_dev = data->input_dev; + buf = data->tch_data; +#ifdef CONFIG_TOUCHPANEL_PROXIMITY_SENSOR + if (vps_ft5436->vps_enabled) { + ft5x0x_read_reg(data->client, 0xB0, ®_value); + printk("proxi_fts 0xB0 state value is0x%02X\n", reg_value); + if (!(reg_value&0x01)) + tp_prox_sensor_enable(data->client, 1); + ft5x0x_read_reg(data->client, 0x01, &proximity_status); + printk("FT 0x01 reg proximity_status[0x%x]--%s\n", proximity_status, __FUNCTION__); + if (proximity_status == 0xC0) { + input_report_abs(vps_ft5436->proximity_dev, ABS_DISTANCE, 0); + input_sync(vps_ft5436->proximity_dev); + printk("[Fu]close\n"); + } else if (proximity_status == 0xE0) { + wake_lock_timeout(&ft5436_wakelock, 1*HZ); + input_report_abs(vps_ft5436->proximity_dev, ABS_DISTANCE, 1); + input_sync(vps_ft5436->proximity_dev); + printk("[Fu]leave\n"); + } + } +#endif + + + + rc = ft5435_i2c_read(data->client, ®, 1, + buf, data->tch_data_len); + if (rc < 0) { + dev_err(&data->client->dev, "%s: read data fail\n", __func__); + return IRQ_HANDLED; + } + + for (i = 0; i < data->pdata->num_max_touches; i++) { + id = (buf[FT_TOUCH_ID_POS + FT_ONE_TCH_LEN * i]) >> 4; + if (id >= FT_MAX_ID) + break; + + update_input = true; + + x = (buf[FT_TOUCH_X_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 | + (buf[FT_TOUCH_X_L_POS + FT_ONE_TCH_LEN * i]); + y = (buf[FT_TOUCH_Y_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 | + (buf[FT_TOUCH_Y_L_POS + FT_ONE_TCH_LEN * i]); + + status = buf[FT_TOUCH_EVENT_POS + FT_ONE_TCH_LEN * i] >> 6; + + num_touches = buf[FT_TD_STATUS] & FT_STATUS_NUM_TP_MASK; + + /* invalid combination */ + if (!num_touches && !status && !id) + break; + input_mt_slot(ip_dev, id); + + if (status == FT_TOUCH_DOWN) + printk("[FTS]Down pid[%d]:[%d, %d]\n", id, x, y); + else if (status == 1) + printk("[FTS]Up pid[%d]:[%d, %d]\n", id, x, y); + + if (x < data->pdata->panel_maxx && y < data->pdata->panel_maxy) { + if (status == FT_TOUCH_DOWN || status == FT_TOUCH_CONTACT) { + input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1); + input_report_abs(ip_dev, ABS_MT_POSITION_X, x); + input_report_abs(ip_dev, ABS_MT_POSITION_Y, y); + } else { + input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0); + } + } else{ + if (data->pdata->fw_vkey_support) { + for (j = 0; j < data->pdata->num_virkey; j++) { + if (x == data->pdata->vkeys[j].x) { + if (status == FT_TOUCH_DOWN || status == FT_TOUCH_CONTACT) + input_report_key(data->input_dev, data->pdata->vkeys[j].keycode, true); + else { + input_report_key(data->input_dev, data->pdata->vkeys[j].keycode, false); + } + } + } + } + } + } + + if (update_input) { +#if defined(FOCALTECH_FAE_MOD) + if (num_touches == 0) { /* release all touches */ + for (i = 0; i < data->pdata->num_max_touches; i++) { + input_mt_slot(data->input_dev, i); + input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0); + } + } +#endif + input_mt_report_pointer_emulation(ip_dev, false); + input_sync(ip_dev); + } + #endif + return IRQ_HANDLED; +} + +static int ft5435_power_on(struct ft5435_ts_data *data, bool on) +{ + int rc; + + if (!on) + goto power_off; + + rc = regulator_enable(data->vdd); + if (rc) { + dev_err(&data->client->dev, + "Regulator vdd enable failed rc=%d\n", rc); + return rc; + } + +#if 1 + rc = regulator_enable(data->vcc_i2c); + if (rc) { + dev_err(&data->client->dev, + "Regulator vcc_i2c enable failed rc=%d\n", rc); + regulator_disable(data->vdd); + } +#endif + + + return rc; + +power_off: +#if 1 + rc = regulator_disable(data->vdd); + if (rc) { + dev_err(&data->client->dev, + "Regulator vdd disable failed rc=%d\n", rc); + return rc; + } +#endif + +#if 1 + rc = regulator_disable(data->vcc_i2c); + if (rc) { + dev_err(&data->client->dev, + "Regulator vcc_i2c disable failed rc=%d\n", rc); + rc = regulator_enable(data->vdd); + if (rc) { + dev_err(&data->client->dev, + "Regulator vdd enable failed rc=%d\n", rc); + } + } +#endif + + + return rc; +} + +static int ft5435_power_init(struct ft5435_ts_data *data, bool on) +{ + int rc; + + if (!on) + goto pwr_deinit; + + data->vdd = regulator_get(&data->client->dev, "vdd"); + if (IS_ERR(data->vdd)) { + rc = PTR_ERR(data->vdd); + dev_err(&data->client->dev, + "Regulator get failed vdd rc=%d\n", rc); + return rc; + } + + if (regulator_count_voltages(data->vdd) > 0) { + rc = regulator_set_voltage(data->vdd, FT_VTG_MIN_UV, + FT_VTG_MAX_UV); + if (rc) { + dev_err(&data->client->dev, + "Regulator set_vtg failed vdd rc=%d\n", rc); + goto reg_vdd_put; + } + } + +#if 1 + data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c"); + if (IS_ERR(data->vcc_i2c)) { + rc = PTR_ERR(data->vcc_i2c); + dev_err(&data->client->dev, + "Regulator get failed vcc_i2c rc=%d\n", rc); + goto reg_vdd_set_vtg; + } + + if (regulator_count_voltages(data->vcc_i2c) > 0) { + rc = regulator_set_voltage(data->vcc_i2c, FT_I2C_VTG_MIN_UV, + FT_I2C_VTG_MAX_UV); + if (rc) { + dev_err(&data->client->dev, + "Regulator set_vtg failed vcc_i2c rc=%d\n", rc); + goto reg_vcc_i2c_put; + } + } +#endif + + + return 0; + +#if 1 +reg_vcc_i2c_put: + regulator_put(data->vcc_i2c); + +reg_vdd_set_vtg: + if (regulator_count_voltages(data->vdd) > 0) + regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV); +#endif + +reg_vdd_put: + regulator_put(data->vdd); + return rc; + +pwr_deinit: + if (regulator_count_voltages(data->vdd) > 0) + regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV); + + regulator_put(data->vdd); + + return 0; +} + +static int ft5435_ts_pinctrl_init(struct ft5435_ts_data *ft5435_data) +{ + int retval; + + /* Get pinctrl if target uses pinctrl */ + ft5435_data->ts_pinctrl = devm_pinctrl_get(&(ft5435_data->client->dev)); + if (IS_ERR_OR_NULL(ft5435_data->ts_pinctrl)) { + dev_dbg(&ft5435_data->client->dev, + "Target does not use pinctrl\n"); + retval = PTR_ERR(ft5435_data->ts_pinctrl); + ft5435_data->ts_pinctrl = NULL; + goto err_pinctrl_get; + } + + ft5435_data->gpio_state_active + = pinctrl_lookup_state(ft5435_data->ts_pinctrl, + "pmx_ts_active"); + if (IS_ERR_OR_NULL(ft5435_data->gpio_state_active)) { + dev_dbg(&ft5435_data->client->dev, + "Can not get ts default pinstate\n"); + retval = PTR_ERR(ft5435_data->gpio_state_active); + ft5435_data->ts_pinctrl = NULL; + goto err_pinctrl_lookup; + } + + ft5435_data->gpio_state_suspend + = pinctrl_lookup_state(ft5435_data->ts_pinctrl, + "pmx_ts_suspend"); + if (IS_ERR_OR_NULL(ft5435_data->gpio_state_suspend)) { + dev_err(&ft5435_data->client->dev, + "Can not get ts sleep pinstate\n"); + retval = PTR_ERR(ft5435_data->gpio_state_suspend); + ft5435_data->ts_pinctrl = NULL; + goto err_pinctrl_lookup; + } + + return 0; +err_pinctrl_lookup: + devm_pinctrl_put(ft5435_data->ts_pinctrl); +err_pinctrl_get: + ft5435_data->ts_pinctrl = NULL; + return retval; +} + +static int ft5435_ts_pinctrl_select(struct ft5435_ts_data *ft5435_data, + bool on) +{ + struct pinctrl_state *pins_state; + int ret; + pins_state = on ? ft5435_data->gpio_state_active + : ft5435_data->gpio_state_suspend; + if (!IS_ERR_OR_NULL(pins_state)) { + ret = pinctrl_select_state(ft5435_data->ts_pinctrl, pins_state); + if (ret) { + dev_err(&ft5435_data->client->dev, + "can not set %s pins\n", + on ? "pmx_ts_active" : "pmx_ts_suspend"); + return ret; + } + } else { + dev_err(&ft5435_data->client->dev, + "not a valid '%s' pinstate\n", + on ? "pmx_ts_active" : "pmx_ts_suspend"); + } + return 0; +} + +#if defined(FOCALTECH_TP_GESTURE) +static int ft_tp_suspend(struct ft5435_ts_data *data) +{ + int i = 0; + u8 state = 0; + + printk("[FTS] FTS_GESTRUE suspend\n"); + ft5x0x_write_reg(data->client, 0xd0, 0x01); + ft5x0x_write_reg(data->client, 0xd1, 0xff); + ft5x0x_write_reg(data->client, 0xd2, 0xff); + ft5x0x_write_reg(data->client, 0xd5, 0xff); + ft5x0x_write_reg(data->client, 0xd6, 0xff); + ft5x0x_write_reg(data->client, 0xd7, 0xff); + ft5x0x_write_reg(data->client, 0xd8, 0xff); + msleep(10); + + for (i = 0; i < 10; i++) { + printk("[FTS]tpd_suspend4 %d\t", i); + ft5x0x_read_reg(data->client, 0xd0, &state); + + if (state == 1) { + printk("[FTS]TPD gesture write 0x01 OK\n"); + break; + } else { + ft5x0x_write_reg(data->client, 0xd0, 0x01); + ft5x0x_write_reg(data->client, 0xd1, 0xff); + ft5x0x_write_reg(data->client, 0xd2, 0xff); + ft5x0x_write_reg(data->client, 0xd5, 0xff); + ft5x0x_write_reg(data->client, 0xd6, 0xff); + ft5x0x_write_reg(data->client, 0xd7, 0xff); + ft5x0x_write_reg(data->client, 0xd8, 0xff); + msleep(10); + } + } + + if (i >= 9) + { + printk("[FTS]TPD gesture write 0x01 to d0 fail \n"); + } + + data->suspended = true; + printk("[FTS] FTS_GESTRUE suspend end\n"); + return 0; +} +#endif + +#ifdef CONFIG_PM +static int ft5435_ts_suspend(struct device *dev) +{ + struct ft5435_ts_data *data = g_ft5435_ts_data; + char i; + + u8 state = -1; + if (data->loading_fw) { + dev_info(dev, "Firmware loading in process...\n"); + return 0; + } + + if (data->suspended) { + dev_info(dev, "Already in suspend state\n"); + return 0; + } + + disable_irq(data->client->irq); + + /* release all touches */ + for (i = 0; i < data->pdata->num_max_touches; i++) { + input_mt_slot(data->input_dev, i); + input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0); + } + input_mt_report_pointer_emulation(data->input_dev, false); + input_sync(data->input_dev); + +#if defined(FOCALTECH_TP_GESTURE) + { + if (gesture_func_on) { + enable_irq(data->client->irq); + ft_tp_suspend(data); + return 0; + } + } +#endif + if (gpio_is_valid(data->pdata->reset_gpio)) { + gpio_set_value_cansleep(data->pdata->reset_gpio, 1); + msleep(300); + } + if (gpio_is_valid(data->pdata->reset_gpio)) { + for (i = 0; i < 10; i++) { + ft5x0x_write_reg(data->client, 0xa5, 0x03); + ft5x0x_read_reg(data->client, 0xa5, &state); + + if ((state != 0) && (state != 1)) { + printk("[FTS]Ft5435 TPDwrite OK [%d]\n", i); + break; + } else { + printk("[FTS]Ft5435 TPDwrite Error[%d]\n", i); + } + } + } + + data->suspended = true; + return 0; +} + +static int ft5435_ts_resume(struct device *dev) +{ + struct ft5435_ts_data *data = g_ft5435_ts_data; + + + + if (!data->suspended) { + dev_dbg(dev, "Already in awake state\n"); + return 0; + } + + /* release all touches */ + input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0); + input_sync(data->input_dev); + +/*hw rst*/ + if (gpio_is_valid(data->pdata->reset_gpio)) { + gpio_set_value_cansleep(data->pdata->reset_gpio, 0); + msleep(2); + gpio_set_value_cansleep(data->pdata->reset_gpio, 1); + } + + msleep(data->pdata->soft_rst_dly); + + + ft5x0x_write_reg(data->client, 0x8c, 0x01); + enable_irq(data->client->irq); + data->suspended = false; + +#if defined(USB_CHARGE_DETECT) + queue_work(ft5435_wq, &data->work); +#endif + +#if defined(LEATHER_COVER) + queue_work(ft5435_wq_cover, &data->work_cover); +#endif +#if defined(VR_GLASS) + queue_work(ft5435_wq_vr, &data->work_vr); +#endif + return 0; +} + +static const struct dev_pm_ops ft5435_ts_pm_ops = { +#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND)) + .suspend = ft5435_ts_suspend, + .resume = ft5435_ts_resume, +#endif +}; + +#else +static int ft5435_ts_suspend(struct device *dev) +{ + return 0; +} + +static int ft5435_ts_resume(struct device *dev) +{ + return 0; +} + +#endif + +#if 1 +#if defined(CONFIG_FB) +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct ft5435_ts_data *ft5435_data = + container_of(self, struct ft5435_ts_data, fb_notif); + + if (evdata && evdata->data && event == FB_EVENT_BLANK && + ft5435_data && ft5435_data->client) { + blank = evdata->data; + if (*blank == FB_BLANK_UNBLANK) + ft5435_ts_resume(&ft5435_data->client->dev); + else if (*blank == FB_BLANK_POWERDOWN) + ft5435_ts_suspend(&ft5435_data->client->dev); + } + return 0; +} +#elif defined(CONFIG_HAS_EARLYSUSPEND) +static void ft5435_ts_early_suspend(struct early_suspend *handler) +{ + struct ft5435_ts_data *data = container_of(handler, + struct ft5435_ts_data, + early_suspend); + + ft5435_ts_suspend(&data->client->dev); +} + +static void ft5435_ts_late_resume(struct early_suspend *handler) +{ + struct ft5435_ts_data *data = container_of(handler, + struct ft5435_ts_data, + early_suspend); + + ft5435_ts_resume(&data->client->dev); +} +#endif +#else +#if defined(CONFIG_FB) +static void fb_notify_resume_work(struct work_struct *work) +{ + struct ft5435_ts_data *ft5435_data = + container_of(work, struct ft5435_ts_data, fb_notify_work); + ft5435_ts_resume(&ft5435_data->client->dev); +} + +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct ft5435_ts_data *ft5435_data = + container_of(self, struct ft5435_ts_data, fb_notif); + + if (evdata && evdata->data && ft5435_data && ft5435_data->client) { + blank = evdata->data; + if (ft5435_data->pdata->resume_in_workqueue) { + if (event == FB_EARLY_EVENT_BLANK && + *blank == FB_BLANK_UNBLANK) + schedule_work(&ft5435_data->fb_notify_work); + else if (event == FB_EVENT_BLANK && + *blank == FB_BLANK_POWERDOWN) { + flush_work(&ft5435_data->fb_notify_work); + ft5435_ts_suspend(&ft5435_data->client->dev); + } + } else { + if (event == FB_EVENT_BLANK) { + if (*blank == FB_BLANK_UNBLANK) + ft5435_ts_resume( + &ft5435_data->client->dev); + else if (*blank == FB_BLANK_POWERDOWN) + ft5435_ts_suspend( + &ft5435_data->client->dev); + } + } + } + + return 0; +} +#elif defined(CONFIG_HAS_EARLYSUSPEND) +static void ftft5346_ts_early_suspend(struct early_suspend *handler) +{ + struct ftft5346_ts_data *data = container_of(handler, + struct ft5435_ts_data, + early_suspend); + + /* + * During early suspend/late resume, the driver doesn't access xPU/SMMU + * protected HW resources. So, there is no compelling need to block, + * but notifying the userspace that a power event has occurred is + * enough. Hence 'blocking' variable can be set to false. + */ + ft5435_secure_touch_stop(data, false); + ft5435_ts_suspend(&data->client->dev); +} + +static void ft5435_ts_late_resume(struct early_suspend *handler) +{ + struct ft5435_ts_data *data = container_of(handler, + struct ft5435_ts_data, + early_suspend); + + ft5435_secure_touch_stop(data, false); + ft5435_ts_resume(&data->client->dev); +} +#endif + +#endif + +static int ft5435_auto_cal(struct i2c_client *client) +{ + struct ft5435_ts_data *data = i2c_get_clientdata(client); + u8 temp = 0, i; + + /* set to factory mode */ + msleep(2 * data->pdata->soft_rst_dly); + ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE); + msleep(data->pdata->soft_rst_dly); + + /* start calibration */ + ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START); + msleep(2 * data->pdata->soft_rst_dly); + for (i = 0; i < FT_CAL_RETRY; i++) { + ft5x0x_read_reg(client, FT_REG_CAL, &temp); + /*return to normal mode, calibration finish */ + if (((temp & FT_CAL_MASK) >> FT_4BIT_SHIFT) == FT_CAL_FIN) + break; + } + + /*calibration OK */ + msleep(2 * data->pdata->soft_rst_dly); + ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE); + msleep(data->pdata->soft_rst_dly); + + /* store calibration data */ + ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE); + msleep(2 * data->pdata->soft_rst_dly); + + /* set to normal mode */ + ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE); + msleep(2 * data->pdata->soft_rst_dly); + + return 0; +} + +int hid_to_i2c(struct i2c_client *client) +{ + u8 auc_i2c_write_buf[5] = {0}; + int bRet = 0; + + auc_i2c_write_buf[0] = 0xeb; + auc_i2c_write_buf[1] = 0xaa; + auc_i2c_write_buf[2] = 0x09; + + ft5435_i2c_write(client, auc_i2c_write_buf, 3); + + msleep(10); + + auc_i2c_write_buf[0] = auc_i2c_write_buf[1] = auc_i2c_write_buf[2] = 0; + + ft5435_i2c_read(client, auc_i2c_write_buf, 0, auc_i2c_write_buf, 3); + + + if (1) + bRet = 1; + else bRet = 0; + return bRet; +} + + +static int ft5435_fw_upgrade_start(struct i2c_client *client, + const u8 *data, u32 data_len) +{ + struct ft5435_ts_data *ts_data = i2c_get_clientdata(client); + struct fw_upgrade_info info = ts_data->pdata->info; + u8 reset_reg; + u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0}; + u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN]; + int i, j; + u32 pkt_num, pkt_len, temp; + + u8 is_5336_fwsize_30 = false; + u8 fw_ecc; + hid_to_i2c(client); + /* determine firmware size */ + if (*(data + data_len - FT_BLOADER_SIZE_OFF) == FT_BLOADER_NEW_SIZE) + is_5336_fwsize_30 = true; + else + is_5336_fwsize_30 = false; + + for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) { + msleep(FT_EARSE_DLY_MS); + /* reset - write 0xaa and 0x55 to reset register */ + if (ts_data->family_id == FT6X06_ID + || ts_data->family_id == FT6X36_ID) + reset_reg = FT_RST_CMD_REG1; + else + reset_reg = FT_RST_CMD_REG1; + + ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_AA); + msleep(info.delay_aa); + + ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_55); + if (i <= (FT_UPGRADE_LOOP / 2)) + msleep(info.delay_55 + i * 3); + else + msleep(info.delay_55 - (i - (FT_UPGRADE_LOOP / 2)) * 2); + hid_to_i2c(client); + msleep(10); + w_buf[0] = 0x55; + w_buf[1] = 0xaa; + temp = 0; + do { + temp++; + ft5435_i2c_write(client, w_buf, 2); + msleep(5); + } while (temp < 1); + + /* check READ_ID */ + msleep(info.delay_readid); + w_buf[0] = FT_READ_ID_REG; + w_buf[1] = 0x00; + w_buf[2] = 0x00; + w_buf[3] = 0x00; + + ft5435_i2c_read(client, w_buf, 4, r_buf, 2); + + if (r_buf[0] != info.upgrade_id_1 + || r_buf[1] != info.upgrade_id_2) { + dev_err(&client->dev, "Upgrade ID mismatch(%d), IC=0x%x 0x%x, info=0x%x 0x%x\n", + i, r_buf[0], r_buf[1], + info.upgrade_id_1, info.upgrade_id_2); + } else + break; + } + + if (i >= FT_UPGRADE_LOOP) { + dev_err(&client->dev, "Abort upgrade\n"); + return -EIO; + } + /* erase app and panel paramenter area */ + w_buf[0] = FT_ERASE_APP_REG; + ft5435_i2c_write(client, w_buf, 1); + msleep(info.delay_erase_flash); + + for (i = 0; i < 15; i++) { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + printk("1~~~~1 r_buf[0] =%x r_buf[1] = %x \n ", r_buf[0], r_buf[1]); + if (0xF0 == r_buf[0] && 0xAA == r_buf[1]) + break; + msleep(50); + } + + w_buf[0] = 0xB0; + w_buf[1] = (u8) ((data_len >> 16) & 0xFF); + w_buf[2] = (u8) ((data_len >> 8) & 0xFF); + w_buf[3] = (u8) (data_len & 0xFF); + printk("data_len = %d \n", data_len); + ft5435_i2c_write(client, w_buf, 4); + + +/*********Step 5:write firmware(FW) to ctpm flash*********/ + fw_ecc = 0; + printk("Step 5:write firmware(FW) to ctpm flash\n"); + temp = 0; + pkt_num = (data_len) / FT_FW_PKT_LEN; + pkt_buf[0] = 0xbf; + pkt_buf[1] = 0x00; + printk("@@@@@pkt_num = %x \n", pkt_num); + for (j = 0; j < pkt_num; j++) { + temp = j * FT_FW_PKT_LEN; + pkt_buf[2] = (u8) (temp >> 8); + pkt_buf[3] = (u8) temp; + pkt_len = FT_FW_PKT_LEN; + pkt_buf[4] = (u8) (pkt_len >> 8); + pkt_buf[5] = (u8) pkt_len; + for (i = 0; i < FT_FW_PKT_LEN; i++) { + pkt_buf[6 + i] = data[j * FT_FW_PKT_LEN + i]; + fw_ecc ^= pkt_buf[6 + i]; + } + ft5435_i2c_write(client, pkt_buf, FT_FW_PKT_LEN + 6); + + for (i = 0; i < 30; i++) { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + + if ((j + 0x1000) == (((r_buf[0]) << 8) | r_buf[1])) + break; + msleep(1); + } + } + + if ((data_len) % FT_FW_PKT_LEN > 0) { + temp = pkt_num * FT_FW_PKT_LEN; + pkt_buf[2] = (u8) (temp >> 8); + pkt_buf[3] = (u8) temp; + temp = (data_len) % FT_FW_PKT_LEN; + pkt_buf[4] = (u8) (temp >> 8); + pkt_buf[5] = (u8) temp; + + for (i = 0; i < temp; i++) { + pkt_buf[6 + i] = data[pkt_num * FT_FW_PKT_LEN + i]; + fw_ecc ^= pkt_buf[6 + i]; + } + ft5435_i2c_write(client, pkt_buf, temp + 6); + + for (i = 0; i < 30; i++) { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + printk("@~~~~@ r_buf[0] =%x r_buf[1] = %x j =%x \n ", r_buf[0], r_buf[1], j); + if ((j + 0x1000) == (((r_buf[0]) << 8) | r_buf[1])) + break; + msleep(1); + } + } + + msleep(50); + + /*********Step 6: read out checksum***********************/ + /*send the opration head */ + printk("Step 6: read out checksum\n"); + w_buf[0] = 0x64; + ft5435_i2c_write(client, w_buf, 1); + msleep(300); + + temp = 0; + w_buf[0] = 0x65; + w_buf[1] = (u8)(temp >> 16); + w_buf[2] = (u8)(temp >> 8); + w_buf[3] = (u8)(temp); + temp = data_len; + w_buf[4] = (u8)(temp >> 8); + w_buf[5] = (u8)(temp); + ft5435_i2c_write(client, w_buf, 6); + msleep(data_len/256); + + for (i = 0; i < 100; i++) { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + printk("~~~~ r_buf[0] =%x r_buf[1] = %x \n ", r_buf[0], r_buf[1]); + if (0xF0 == r_buf[0] && 0x55 == r_buf[1]) + break; + msleep(1); + } + w_buf[0] = 0x66; + ft5435_i2c_read(client, w_buf, 1, r_buf, 1); + if (r_buf[0] != fw_ecc) + { + dev_err(&client->dev, "[FTS]--ecc error! FW=%02x bt_ecc=%02x\n", + r_buf[0], + fw_ecc); + + return -EIO; + } + printk(KERN_WARNING "checksum %x %x \n", r_buf[0], fw_ecc); + /* reset */ + w_buf[0] = FT_REG_RESET_FW; + ft5435_i2c_write(client, w_buf, 1); + msleep(ts_data->pdata->soft_rst_dly); + + dev_info(&client->dev, "Firmware upgrade successful\n"); + + return 0; +} +#if defined(FOCALTECH_AUTO_UPGRADE) + +static int ft5x46_fw_upgrade_start(struct i2c_client *client, + const u8 *data, u32 data_len) +{ + struct ft5435_ts_data *ts_data = i2c_get_clientdata(client); + struct fw_upgrade_info info = ts_data->pdata->info; + u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0}; + u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN]; + int i, j, temp; + u32 pkt_num, pkt_len; + u8 fw_ecc; + int i_ret; + + printk("%s\n", __func__); + i_ret = hid_to_i2c(client); + + if (i_ret == 0) + printk("[FTS] hid1 change to i2c fail ! \n"); + + for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) { + msleep(FT_EARSE_DLY_MS); + + /*********Step 1:Reset CTPM *****/ + /*write 0xaa to register 0xfc */ + ft5x0x_write_reg(client, 0xfc, FT_UPGRADE_AA); + msleep(2); + + ft5x0x_write_reg(client, 0xfc, FT_UPGRADE_55); + + msleep(200); + + i_ret = hid_to_i2c(client); + + if (i_ret == 0) + printk("[FTS] hid%d change to i2c fail ! \n", i); + + msleep(10); + + /*********Step 2:Enter upgrade mode *****/ + w_buf[0] = FT_UPGRADE_55; + w_buf[1] = FT_UPGRADE_AA; + i_ret = ft5435_i2c_write(client, w_buf, 2); + + if (i_ret < 0) { + printk("[FTS] failed writing 0x55 and 0xaa ! \n"); + continue; + } + + /*********Step 3:check READ-ID***********************/ + msleep(1); + w_buf[0] = FT_READ_ID_REG; + w_buf[1] = 0x00; + w_buf[2] = 0x00; + w_buf[3] = 0x00; + + r_buf[0] = r_buf[1] = 0x00; + + ft5435_i2c_read(client, w_buf, 4, r_buf, 2); + + if (r_buf[0] == 0x54 && r_buf[1] == 0x2c) { + printk("Upgrade ID mismatch(%d), IC=0x%x 0x%x, info=0x%x 0x%x\n", + i, r_buf[0], r_buf[1], info.upgrade_id_1, info.upgrade_id_2); + break; + } else{ + printk("[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n", + r_buf[0], r_buf[1]); + continue; + } + } + + if (i >= FT_UPGRADE_LOOP) { + dev_err(&client->dev, "Abort upgrade\n"); + return -EIO; + } + + /******Step 4:erase app and panel paramenter area******/ + printk("Step 4:erase app and panel paramenter area\n"); + w_buf[0] = 0x61; + ft5435_i2c_write(client, w_buf, 1); + msleep(1350); + + for (i = 0; i < 15; i++) { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + + if (0xF0 == r_buf[0] && 0xAA == r_buf[1]) + break; + msleep(50); + + } + + w_buf[0] = 0xB0; + w_buf[1] = (u8) ((data_len >> 16) & 0xFF); + w_buf[2] = (u8) ((data_len >> 8) & 0xFF); + w_buf[3] = (u8) (data_len & 0xFF); + + ft5435_i2c_write(client, w_buf, 4); + + /*********Step 5:write firmware(FW) to ctpm flash*********/ + fw_ecc = 0; + printk("Step 5:write firmware(FW) to ctpm flash\n"); + temp = 0; + pkt_num = (data_len) / FT_FW_PKT_LEN; + pkt_buf[0] = 0xbf; + pkt_buf[1] = 0x00; + + for (j = 0; j < pkt_num; j++) { + temp = j * FT_FW_PKT_LEN; + pkt_buf[2] = (u8) (temp >> 8); + pkt_buf[3] = (u8) temp; + pkt_len = FT_FW_PKT_LEN; + pkt_buf[4] = (u8) (pkt_len >> 8); + pkt_buf[5] = (u8) pkt_len; + + for (i = 0; i < FT_FW_PKT_LEN; i++) { + pkt_buf[6 + i] = data[j * FT_FW_PKT_LEN + i]; + fw_ecc ^= pkt_buf[6 + i]; + } + ft5435_i2c_write(client, pkt_buf, FT_FW_PKT_LEN + 6); + + for (i = 0; i < 30; i++) { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + + if ((j + 0x1000) == (((r_buf[0]) << 8) | r_buf[1])) + break; + msleep(1); + + } + } + + if ((data_len) % FT_FW_PKT_LEN > 0) { + temp = pkt_num * FT_FW_PKT_LEN; + pkt_buf[2] = (u8) (temp >> 8); + pkt_buf[3] = (u8) temp; + temp = (data_len) % FT_FW_PKT_LEN; + pkt_buf[4] = (u8) (temp >> 8); + pkt_buf[5] = (u8) temp; + + for (i = 0; i < temp; i++) { + pkt_buf[6 + i] = data[pkt_num* FT_FW_PKT_LEN + i]; + fw_ecc ^= pkt_buf[6 + i]; + } + ft5435_i2c_write(client, pkt_buf, temp + 6); + + for (i = 0; i < 30; i++) { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + + if ((j + 0x1000) == (((r_buf[0]) << 8) | r_buf[1])) + break; + msleep(1); + + } + } + + msleep(50); + +/*********Step 6: read out checksum***********************/ + /*send the opration head */ + printk("Step 6: read out checksum\n"); + w_buf[0] = 0x64; + ft5435_i2c_write(client, w_buf, 1); + msleep(300); + + temp = 0; + w_buf[0] = 0x65; + w_buf[1] = (u8)(temp >> 16); + w_buf[2] = (u8)(temp >> 8); + w_buf[3] = (u8)(temp); + temp = data_len; + w_buf[4] = (u8)(temp >> 8); + w_buf[5] = (u8)(temp); + i_ret = ft5435_i2c_write(client, w_buf, 6); + msleep(data_len/256); + + for (i = 0; i < 100; i++) { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + + if (0xF0 == r_buf[0] && 0x55 == r_buf[1]) + break; + msleep(1); + + } + w_buf[0] = 0x66; + ft5435_i2c_read(client, w_buf, 1, r_buf, 1); + if (r_buf[0] != fw_ecc) { + dev_err(&client->dev, "[FTS]--ecc error! FW=%02x bt_ecc=%02x\n", + r_buf[0], fw_ecc); + + return -EIO; + } + printk(KERN_WARNING "checksum %X %X \n", r_buf[0], fw_ecc); + + /*********Step 7: reset the new FW***********************/ + printk("Step 7: reset the new FW\n"); + w_buf[0] = 0x07; + ft5435_i2c_write(client, w_buf, 1); + msleep(130); + + return 0; +} +#endif +#if defined(FOCALTECH_FW_COMPAT) +static int ft5435_fw_upgrade_arbitrate(struct i2c_client *client) +{ + struct ft5435_ts_data *ts_data = i2c_get_clientdata(client); + struct fw_upgrade_info info = ts_data->pdata->info; + u8 reset_reg; + u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0}; + int i; + + for (i = 0; i < FT_UPGRADE_LOOP; i++) { + msleep(FT_EARSE_DLY_MS); + /* reset - write 0xaa and 0x55 to reset register */ + if (ts_data->family_id == FT6X06_ID + || ts_data->family_id == FT6X36_ID) + reset_reg = FT_RST_CMD_REG2; + else + reset_reg = FT_RST_CMD_REG1; + + ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_AA); + msleep(info.delay_aa); + + ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_55); + if (i <= (FT_UPGRADE_LOOP / 2)) + msleep(info.delay_55 + i * 3); + else + msleep(info.delay_55 - (i - (FT_UPGRADE_LOOP / 2)) * 2); + + /* Enter upgrade mode */ + w_buf[0] = FT_UPGRADE_55; + ft5435_i2c_write(client, w_buf, 1); + usleep(FT_55_AA_DLY_NS); + w_buf[0] = FT_UPGRADE_AA; + ft5435_i2c_write(client, w_buf, 1); + + /* check READ_ID */ + msleep(info.delay_readid); + w_buf[0] = FT_READ_ID_REG; + w_buf[1] = 0x00; + w_buf[2] = 0x00; + w_buf[3] = 0x00; + + ft5435_i2c_read(client, w_buf, 4, r_buf, 2); + + if (r_buf[0] != info.upgrade_id_1 + || r_buf[1] != info.upgrade_id_2) { + dev_err(&client->dev, "Upgrade ID mismatch(%d), IC=0x%x 0x%x, info=0x%x 0x%x\n", + i, r_buf[0], r_buf[1], + info.upgrade_id_1, info.upgrade_id_2); + } else + break; + } + + if (i >= FT_UPGRADE_LOOP) { + dev_err(&client->dev, "Abort upgrade\n"); + return -EIO; + } + +/* get tp vid */ + + w_buf[0] = 0x03; + w_buf[1] = 0x00; + w_buf[2] = 0x78; + w_buf[3] = 0x40; + ft5435_i2c_read(client, w_buf, 4, r_buf, 1); + ts_data->fw_compat = r_buf[0]; + printk("%s line=%d, fw_compat=%x \n", __func__, __LINE__, ts_data->fw_compat); + + /* reset */ + w_buf[0] = FT_REG_RESET_FW; + ft5435_i2c_write(client, w_buf, 1); + msleep(ts_data->pdata->soft_rst_dly); + +/* New TP with fw_version >= 0x30 */ + if (ts_data->fw_compat >= 0x30) { + strlcpy(ts_data->fw_name, "ft_fw3.bin", strlen("ft_fw3.bin") + 1); + } + + return 0; +} +#endif + +static unsigned int booting_into_recovery; +static int __init get_boot_mode(char *str) +{ + if (strcmp("boot_with_recovery", str) == 0) + booting_into_recovery = 1; + + printk("zakk: booting_into_recovery=%d\n", booting_into_recovery); + return 0; +} +__setup("androidboot.boot_reason=", get_boot_mode); + +static int ft5435_fw_upgrade(struct device *dev, bool force) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + const struct firmware *fw = NULL; + int rc; + u8 fw_file_maj, fw_file_min, fw_file_sub_min, fw_file_vendor_id; + bool fw_upgrade = false; + + if (data->suspended) { + dev_err(dev, "Device is in suspend state: Exit FW upgrade\n"); + return -EBUSY; + } + +#if defined(FOCALTECH_FW_COMPAT) + rc = ft5435_fw_upgrade_arbitrate(data->client); + if (rc < 0) { + printk(">>-- distinguish tp failed ! \n"); + return rc; + } +#endif + + ft5435_update_fw_vendor_id(data); + + printk("[Fu]%s, booting_into_recovery=%d\n", __func__, booting_into_recovery); + + rc = request_firmware(&fw, data->fw_name, dev); + + + if (rc < 0) { + dev_err(dev, "[Fu]Request firmware failed - %s (%d)\n", + data->fw_name, rc); + return rc; + } + + if (fw->size < FT_FW_MIN_SIZE || fw->size > FT_FW_MAX_SIZE) { + dev_err(dev, "Invalid firmware size (%zu)\n", fw->size); + rc = -EIO; + goto rel_fw; + } + + if (data->family_id == FT6X36_ID) { + fw_file_maj = FT_FW_FILE_MAJ_VER_FT6X36(fw); + fw_file_vendor_id = FT_FW_FILE_VENDOR_ID_FT6X36(fw); + } else { + fw_file_maj = FT_FW_FILE_MAJ_VER(fw); + fw_file_vendor_id = FT_FW_FILE_VENDOR_ID(fw); + } + fw_file_min = FT_FW_FILE_MIN_VER(fw); + fw_file_sub_min = FT_FW_FILE_SUB_MIN_VER(fw); + + printk("[Fu]Current firmware: %d.%d.%d", data->fw_ver[0], + data->fw_ver[1], data->fw_ver[2]); + printk("[Fu]New firmware: %d.%d.%d", fw_file_maj, + fw_file_min, fw_file_sub_min); + + if (force) + fw_upgrade = true; + + else if (fw_file_maj == 18 && data->fw_ver[0] != 18) { + fw_upgrade = true; + printk("\n[wxc]roll back firmware to v12 for temp\n"); + } + + else if ((data->fw_ver[0] < fw_file_maj) && + (data->pdata->ignore_id_check || (data->fw_vendor_id == fw_file_vendor_id))) + fw_upgrade = true; + + if (!fw_upgrade) { + dev_info(dev, "Exiting fw upgrade...\n"); + rc = -EFAULT; + goto rel_fw; + } + + /* start firmware upgrade */ + if (FT_FW_CHECK(fw, data)) { + rc = ft5435_fw_upgrade_start(data->client, fw->data, fw->size); + if (rc < 0) + dev_err(dev, "update failed (%d). try later...\n", rc); + else if (data->pdata->info.auto_cal) + ft5435_auto_cal(data->client); + } else { + dev_err(dev, "FW format error\n"); + rc = -EIO; + } + + ft5435_update_fw_ver(data); + + FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name, + data->pdata->num_max_touches, data->pdata->group_id, + data->pdata->fw_vkey_support ? "yes" : "no", + data->pdata->fw_name, data->fw_ver[0], + data->fw_ver[1], data->fw_ver[2]); +rel_fw: + release_firmware(fw); + return rc; +} +#if defined(FOCALTECH_AUTO_UPGRADE) +static unsigned char ft5435_fw_Vid_get_from_boot(struct i2c_client *client) +{ + unsigned char auc_i2c_write_buf[10]; + u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0}; + unsigned char i = 0; + unsigned char vid = 0xFF; + int i_ret; + + i_ret = hid_to_i2c(client); + + for (i = 0; i < FT_UPGRADE_LOOP; i++) { + msleep(FT_EARSE_DLY_MS); + + /*********Step 1:Reset CTPM *****/ + /*write 0xaa to register 0xfc */ + ft5x0x_write_reg(client, 0xfc, FT_UPGRADE_AA); + msleep(2); + + ft5x0x_write_reg(client, 0xfc, FT_UPGRADE_55); + + msleep(200); + + i_ret = hid_to_i2c(client); + + if (i_ret == 0) + printk("[FTS] hid%d change to i2c fail ! \n", i); + + msleep(10); + + /*********Step 2:Enter upgrade mode *****/ + w_buf[0] = FT_UPGRADE_55; + w_buf[1] = FT_UPGRADE_AA; + + i_ret = ft5435_i2c_write(client, w_buf, 2); + + if (i_ret < 0) { + printk("[FTS] failed writing 0x55 and 0xaa ! \n"); + continue; + } + + /*********Step 3:check READ-ID***********************/ + msleep(1); + w_buf[0] = FT_READ_ID_REG; + w_buf[1] = 0x00; + w_buf[2] = 0x00; + w_buf[3] = 0x00; + + r_buf[0] = r_buf[1] = 0x00; + + ft5435_i2c_read(client, w_buf, 4, r_buf, 2); + + if (r_buf[0] == 0x54 && r_buf[1] == 0x2c) { + /* + printk("Upgrade ID mismatch(%d), IC=0x%x 0x%x, info=0x%x 0x%x\n", + i, r_buf[0], r_buf[1],info.upgrade_id_1, info.upgrade_id_2); + */ + break; + } else{ + printk("[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n", + r_buf[0], r_buf[1]); + continue; + } + } + + if (i >= FT_UPGRADE_LOOP) { + dev_err(&client->dev, "Abort upgrade\n"); + return -EIO; + } + + printk("FTS_UPGRADE_LOOP ok is i = %d \n", i); + + msleep(10); + auc_i2c_write_buf[0] = 0x03; + auc_i2c_write_buf[1] = 0x00; + for (i = 0; i < FT_UPGRADE_LOOP; i++) { + auc_i2c_write_buf[2] = 0xd7; + auc_i2c_write_buf[3] = 0x83; + i_ret = ft5435_i2c_write(client, auc_i2c_write_buf, 4); + if (i_ret < 0) { + printk("[FTS] Step 4: read lcm id from flash error when i2c write, i_ret = %d\n", i_ret); + continue; + } + i_ret = ft5435_i2c_read(client, auc_i2c_write_buf, 0, r_buf, 2); + if (i_ret < 0) { + printk("[FTS] Step 4: read lcm id from flash error when i2c write, i_ret = %d\n", i_ret); + continue; + } + + vid = r_buf[1]; + + printk("%s: REG VAL ID1 = 0x%x, ID2 = 0x%x\n", __func__, r_buf[0], r_buf[1]); + break; + } + + printk("%s: reset the tp\n", __func__); + auc_i2c_write_buf[0] = 0x07; + ft5435_i2c_write(client, auc_i2c_write_buf, 1); + msleep(300); + return vid; +} + +static int ft5435_fw_upgrade_by_array_data(struct device *dev, char *fw_data, int size, bool force) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + struct firmware *fw = NULL; + int rc; + u8 fw_file_maj, fw_file_min, fw_file_sub_min, fw_file_vendor_id; + bool fw_upgrade = false; + char *pfw_data = fw_data; + int fw_size = size; + + printk("%s, suspended=%d\n", __func__, data->suspended); + if (data->suspended) { + dev_err(dev, "Device is in suspend state: Exit FW upgrade\n"); + return -EBUSY; + } + + fw = kzalloc(sizeof(struct firmware), GFP_KERNEL); + fw->size = fw_size; + fw->data = pfw_data; + + if (fw->size < FT_FW_MIN_SIZE || fw->size > FT_FW_MAX_SIZE) { + dev_err(dev, "Invalid firmware size (%zu)\n", fw->size); + rc = -EIO; + goto rel_fw; + } + + if (data->family_id == FT6X36_ID) { + fw_file_maj = FT_FW_FILE_MAJ_VER_FT6X36(fw); + fw_file_vendor_id = FT_FW_FILE_VENDOR_ID_FT6X36(fw); + } else { + fw_file_maj = FT_FW_FILE_MAJ_VER(fw); + fw_file_vendor_id = FT_FW_FILE_VENDOR_ID(fw); + } + fw_file_min = FT_FW_FILE_MIN_VER(fw); + fw_file_sub_min = FT_FW_FILE_SUB_MIN_VER(fw); + + dev_info(dev, "Current firmware: 0x%02x.%d.%d", data->fw_ver[0], + data->fw_ver[1], data->fw_ver[2]); + dev_info(dev, "New firmware: 0x%02x.%d.%d", fw_file_maj, + fw_file_min, fw_file_sub_min); + + if (force) + fw_upgrade = true; + + + else if (data->fw_ver[0] != fw_file_maj) + fw_upgrade = true; + + if (!fw_upgrade) { + dev_info(dev, "Exiting fw upgrade...\n"); + rc = -EFAULT; + goto rel_fw; + } + + /* start firmware upgrade */ + if (data->family_id == FT5X46_ID) { + rc = ft5x46_fw_upgrade_start(data->client, fw->data, fw->size); + if (rc < 0) + dev_err(dev, "update failed (%d). try later...\n", rc); + } else if (FT_FW_CHECK(fw, data)) { + rc = ft5435_fw_upgrade_start(data->client, fw->data, fw->size); + if (rc < 0) + dev_err(dev, "update failed (%d). try later...\n", rc); + else if (data->pdata->info.auto_cal) + ft5435_auto_cal(data->client); + } else { + dev_err(dev, "FW format error\n"); + rc = -EIO; + } + + ft5435_update_fw_ver(data); + +rel_fw: + kfree(fw); + printk("%s done\n", __func__); + return rc; +} + +#endif +#if defined(FOCALTECH_LOCK_DOWN_INFO) +#define CTP_PROC_LOCKDOWN_FILE "tp_lockdown_info" +static struct proc_dir_entry *ctp_lockdown_status_proc; +static char tp_lockdown_info[128]; + +static int ctp_lockdown_proc_show(struct seq_file *file, void *data) +{ + char temp[40] = {0}; + + sprintf(temp, "%s\n", tp_lockdown_info); + seq_printf(file, "%s\n", temp); + + return 0; +} + +static int ctp_lockdown_proc_open (struct inode *inode, struct file *file) +{ + return single_open(file, ctp_lockdown_proc_show, inode->i_private); +} + +static const struct file_operations ctp_lockdown_proc_fops = { + .open = ctp_lockdown_proc_open, + .read = seq_read, +}; + +static unsigned char ft5435_fw_LockDownInfo_get_from_boot(struct i2c_client *client, char *pProjectCode) +{ + unsigned char auc_i2c_write_buf[10]; + u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[10] = {0}; + unsigned char i = 0, j = 0; + + + int i_ret; + + printk("[fts]%s, fw_vendor_id=0x%02x\n", __func__, fts_fw_vendor_id); + i_ret = hid_to_i2c(client); + + for (i = 0; i < FT_UPGRADE_LOOP; i++) { + msleep(FT_EARSE_DLY_MS); + + /*********Step 1:Reset CTPM *****/ + /*write 0xaa to register 0xfc */ + ft5x0x_write_reg(client, 0xfc, FT_UPGRADE_AA); + msleep(2); + + ft5x0x_write_reg(client, 0xfc, FT_UPGRADE_55); + + msleep(200); + + i_ret = hid_to_i2c(client); + + if (i_ret == 0) + printk("[FTS] hid%d change to i2c fail ! \n", i); + + msleep(10); + + /*********Step 2:Enter upgrade mode *****/ + w_buf[0] = FT_UPGRADE_55; + w_buf[1] = FT_UPGRADE_AA; + i_ret = ft5435_i2c_write(client, w_buf, 2); + + if (i_ret < 0) { + printk("[FTS] failed writing 0x55 and 0xaa ! \n"); + continue; + } + + /*********Step 3:check READ-ID***********************/ + msleep(10); + w_buf[0] = FT_READ_ID_REG; + w_buf[1] = 0x00; + w_buf[2] = 0x00; + w_buf[3] = 0x00; + + r_buf[0] = r_buf[1] = 0x00; + + ft5435_i2c_read(client, w_buf, 4, r_buf, 2); + + if (r_buf[0] == 0x54 && r_buf[1] == 0x2c) { + /* + printk("Upgrade ID mismatch(%d), IC=0x%x 0x%x, info=0x%x 0x%x\n", + i, r_buf[0], r_buf[1],info.upgrade_id_1, info.upgrade_id_2); + */ + break; + } else{ + printk("[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n", + r_buf[0], r_buf[1]); + continue; + } + } + + if (i >= FT_UPGRADE_LOOP) { + dev_err(&client->dev, "Abort upgrade\n"); + return -EIO; + } + + printk("%s, FTS_UPGRADE_LOOP ok is i = %d \n", __func__, i); + + /********* Step 4: read project code from app param area ***********************/ + msleep(10); + auc_i2c_write_buf[0] = 0x03; + auc_i2c_write_buf[1] = 0x00; + for (i = 0; i < FT_UPGRADE_LOOP; i++) { + auc_i2c_write_buf[2] = 0xd7; + auc_i2c_write_buf[3] = 0xa0; + i_ret = ft5435_i2c_write(client, auc_i2c_write_buf, 4); + if (i_ret < 0) { + printk("[FTS] Step 4: read lcm id from flash error when i2c write, i_ret = %d\n", i_ret); + continue; + } + msleep(10); + i_ret = ft5435_i2c_read(client, auc_i2c_write_buf, 0, r_buf, 8); + if (i_ret < 0) { + printk("[FTS] Step 4: read lcm id from flash error when i2c write, i_ret = %d\n", i_ret); + continue; + } + + for (j = 0; j < 8; j++) { + printk("%s: REG VAL = 0x%02x, j=%d\n", __func__, r_buf[j], j); + } + sprintf(pProjectCode, "%02x%02x%02x%02x%02x%02x%02x%02x", \ + r_buf[0], r_buf[1], r_buf[2], r_buf[3], r_buf[4], r_buf[5], r_buf[6], r_buf[7]); + break; + } + + printk("%s: reset the tp\n", __func__); + auc_i2c_write_buf[0] = 0x07; + ft5435_i2c_write(client, auc_i2c_write_buf, 1); + msleep(300); + return 0; +} +#endif + + +static ssize_t ft5435_update_fw_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + return snprintf(buf, 2, "%d\n", data->loading_fw); +} + +static ssize_t ft5435_update_fw_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + unsigned long val; + int rc; + + if (size > 2) + return -EINVAL; + + rc = kstrtoul(buf, 10, &val); + if (rc != 0) + return rc; + + if (data->suspended) { + dev_info(dev, "In suspend state, try again later...\n"); + return size; + } + + mutex_lock(&data->input_dev->mutex); + if (!data->loading_fw && val) { + data->loading_fw = true; + ft5435_fw_upgrade(dev, false); + data->loading_fw = false; + } + mutex_unlock(&data->input_dev->mutex); + + return size; +} + +static DEVICE_ATTR(update_fw, 0664, ft5435_update_fw_show, + ft5435_update_fw_store); + +static ssize_t ft5435_force_update_fw_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + unsigned long val; + int rc; + + if (size > 2) + return -EINVAL; + + rc = kstrtoul(buf, 10, &val); + if (rc != 0) + return rc; + + mutex_lock(&data->input_dev->mutex); + if (!data->loading_fw && val) { + data->loading_fw = true; + ft5435_fw_upgrade(dev, true); + data->loading_fw = false; + } + mutex_unlock(&data->input_dev->mutex); + + return size; +} + +static DEVICE_ATTR(force_update_fw, 0664, ft5435_update_fw_show, + ft5435_force_update_fw_store); + +#ifdef SET_COVER_MODE +static int set_cover_mode_buf; +static ssize_t fts_set_cover_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + struct ft5435_ts_data *data = dev_get_drvdata(dev); + sscanf(buf, "%d\n", &set_cover_mode_buf) ; + switch (set_cover_mode_buf) { + case 1: + ret = ft5x0x_write_reg(data->client, 0xC1, 0x01); + ft5x0x_write_reg(data->client, 0xC4, 0x00); + ft5x0x_write_reg(data->client, 0xC5, 0xff); + ft5x0x_write_reg(data->client, 0xC6, 0x00); + ft5x0x_write_reg(data->client, 0xC7, 0xa0); + break; + case 2: + ret = ft5x0x_write_reg(data->client, 0xC1, 0x01); + ft5x0x_write_reg(data->client, 0xC4, 0x00); + ft5x0x_write_reg(data->client, 0xC5, 0xff); + ft5x0x_write_reg(data->client, 0xc6, 0x00); + ft5x0x_write_reg(data->client, 0xC7, 0xff); + break; + case 0: + ret = ft5x0x_write_reg(data->client, 0xC1, 0x00); + break; + } + return ret; +} +static DEVICE_ATTR(set_cover_mode, 0664, NULL, + fts_set_cover_mode); + +#endif +static ssize_t ft5435_fw_name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + return snprintf(buf, FT_FW_NAME_MAX_LEN - 1, "%s\n", data->fw_name); +} + +static ssize_t ft5435_fw_name_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + + if (size > FT_FW_NAME_MAX_LEN - 1) + return -EINVAL; + + strlcpy(data->fw_name, buf, size); + if (data->fw_name[size-1] == '\n') + data->fw_name[size-1] = 0; + + return size; +} + +static DEVICE_ATTR(fw_name, 0664, ft5435_fw_name_show, ft5435_fw_name_store); + +static ssize_t ft5435_fw_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + return sprintf(buf, "v%d.%d.%d\n", data->fw_ver[0], data->fw_ver[1], data->fw_ver[2]); +} + +static ssize_t ft5435_fw_version_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + return 0; +} + +static DEVICE_ATTR(fw_version, 0664, ft5435_fw_version_show, ft5435_fw_version_store); + + +static bool ft5435_debug_addr_is_valid(int addr) +{ + if (addr < 0 || addr > 0xFF) { + pr_err("FT reg address is invalid: 0x%x\n", addr); + return false; + } + + return true; +} + +static int ft5435_debug_data_set(void *_data, u64 val) +{ + struct ft5435_ts_data *data = _data; + + mutex_lock(&data->input_dev->mutex); + + if (ft5435_debug_addr_is_valid(data->addr)) + dev_info(&data->client->dev, + "Writing into FT registers not supported\n"); + + mutex_unlock(&data->input_dev->mutex); + + return 0; +} + +static int ft5435_debug_data_get(void *_data, u64 *val) +{ + struct ft5435_ts_data *data = _data; + int rc; + u8 reg; + + mutex_lock(&data->input_dev->mutex); + + if (ft5435_debug_addr_is_valid(data->addr)) { + rc = ft5x0x_read_reg(data->client, data->addr, ®); + if (rc < 0) + dev_err(&data->client->dev, + "FT read register 0x%x failed (%d)\n", + data->addr, rc); + else + *val = reg; + } + + mutex_unlock(&data->input_dev->mutex); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, ft5435_debug_data_get, + ft5435_debug_data_set, "0x%02llX\n"); + +static int ft5435_debug_addr_set(void *_data, u64 val) +{ + struct ft5435_ts_data *data = _data; + + if (ft5435_debug_addr_is_valid(val)) { + mutex_lock(&data->input_dev->mutex); + data->addr = val; + mutex_unlock(&data->input_dev->mutex); + } + + return 0; +} + +static int ft5435_debug_addr_get(void *_data, u64 *val) +{ + struct ft5435_ts_data *data = _data; + + mutex_lock(&data->input_dev->mutex); + + if (ft5435_debug_addr_is_valid(data->addr)) + *val = data->addr; + + mutex_unlock(&data->input_dev->mutex); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, ft5435_debug_addr_get, + ft5435_debug_addr_set, "0x%02llX\n"); + +static int ft5435_debug_suspend_set(void *_data, u64 val) +{ + struct ft5435_ts_data *data = _data; + + mutex_lock(&data->input_dev->mutex); + + if (val) + ft5435_ts_suspend(&data->client->dev); + else + ft5435_ts_resume(&data->client->dev); + + mutex_unlock(&data->input_dev->mutex); + + return 0; +} + +static int ft5435_debug_suspend_get(void *_data, u64 *val) +{ + struct ft5435_ts_data *data = _data; + + mutex_lock(&data->input_dev->mutex); + *val = data->suspended; + mutex_unlock(&data->input_dev->mutex); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, ft5435_debug_suspend_get, + ft5435_debug_suspend_set, "%lld\n"); + +static int ft5435_debug_dump_info(struct seq_file *m, void *v) +{ + struct ft5435_ts_data *data = m->private; + + seq_printf(m, "%s\n", data->ts_info); + + return 0; +} + +static int debugfs_dump_info_open(struct inode *inode, struct file *file) +{ + return single_open(file, ft5435_debug_dump_info, inode->i_private); +} + +static const struct file_operations debug_dump_info_fops = { + .owner = THIS_MODULE, + .open = debugfs_dump_info_open, + .read = seq_read, + .release = single_release, +}; + +#ifdef CONFIG_OF +static int ft5435_get_dt_coords(struct device *dev, char *name, + struct ft5435_ts_platform_data *pdata) +{ + u32 coords[FT_COORDS_ARR_SIZE]; + struct property *prop; + struct device_node *np = dev->of_node; + int coords_size, rc; + + prop = of_find_property(np, name, NULL); + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + + coords_size = prop->length / sizeof(u32); + if (coords_size != FT_COORDS_ARR_SIZE) { + dev_err(dev, "invalid %s\n", name); + return -EINVAL; + } + + rc = of_property_read_u32_array(np, name, coords, coords_size); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read %s\n", name); + return rc; + } + + if (!strcmp(name, "focaltech,panel-coords")) { + pdata->panel_minx = coords[0]; + pdata->panel_miny = coords[1]; + pdata->panel_maxx = coords[2]; + pdata->panel_maxy = coords[3]; + } else if (!strcmp(name, "focaltech,display-coords")) { + pdata->x_min = coords[0]; + pdata->y_min = coords[1]; + pdata->x_max = coords[2]; + pdata->y_max = coords[3]; + } else { + dev_err(dev, "unsupported property %s\n", name); + return -EINVAL; + } + + return 0; +} +static int ft5435_get_dt_vkey(struct device *dev, struct ft5435_ts_platform_data *pdata) +{ + u32 coords[FOCALTECH_MAX_VKEY_NUM]; + struct property *prop; + struct device_node *np = dev->of_node; + int coords_size, rc, i; + char name[128]; + memset(name, 0, sizeof(name)); + + sprintf(name, "focal,virtual_key_1"); + prop = of_find_property(np, name, NULL); + printk("[%s]000\n", __FUNCTION__); + if (!prop) + return -EINVAL; + printk("[%s]111\n", __FUNCTION__); + if (!prop->value) + return -ENODATA; + printk("[%s]222\n", __FUNCTION__); + coords_size = prop->length / sizeof(u32); + if (coords_size != pdata->num_virkey) { + printk("[%s]invalid %s\n", __FUNCTION__, name); + return -EINVAL; + } + printk("[%s]333\n", __FUNCTION__); + for (i = 0; i < pdata->num_virkey; i++) { + sprintf(name, "focal,virtual_key_%d", i+1); + rc = of_property_read_u32_array(np, name, coords, coords_size); + if (rc && (rc != -EINVAL)) { + printk("[%s]Unable to read %s\n", __FUNCTION__, name); + return rc; + } + + pdata->vkeys[i].keycode = coords[0]; + pdata->vkeys[i].x = coords[1]; + pdata->vkeys[i].y = coords[2]; + printk("[FTS]keycode = %d, x= %d, y=%d \n", pdata->vkeys[i].keycode, + pdata->vkeys[i].x, pdata->vkeys[i].y); + } + printk("[%s]5555\n", __FUNCTION__); + return 0; + + +} + +static int ft5435_parse_dt(struct device *dev, + struct ft5435_ts_platform_data *pdata) +{ + int rc; + struct device_node *np = dev->of_node; + u32 temp_val; + + pdata->name = "focaltech"; + rc = of_property_read_string(np, "focaltech,name", &pdata->name); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read name\n"); + return rc; + } + + rc = ft5435_get_dt_coords(dev, "focaltech,panel-coords", pdata); + if (rc && (rc != -EINVAL)) + return rc; + + rc = ft5435_get_dt_coords(dev, "focaltech,display-coords", pdata); + if (rc) + return rc; + + pdata->i2c_pull_up = of_property_read_bool(np, + "focaltech,i2c-pull-up"); + + pdata->no_force_update = of_property_read_bool(np, + "focaltech,no-force-update"); + /* reset, irq gpio info */ + pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio", + 0, &pdata->reset_gpio_flags); + if (pdata->reset_gpio < 0) + return pdata->reset_gpio; + + pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio", + 0, &pdata->irq_gpio_flags); + if (pdata->irq_gpio < 0) + return pdata->irq_gpio; + + pdata->fw_name = "ft_fw.bin"; + rc = of_property_read_string(np, "focaltech,fw-name", &pdata->fw_name); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw name\n"); + return rc; + } + + rc = of_property_read_u32(np, "focaltech,group-id", &temp_val); + if (!rc) + pdata->group_id = temp_val; + else + return rc; + + rc = of_property_read_u32(np, "focaltech,hard-reset-delay-ms", + &temp_val); + if (!rc) + pdata->hard_rst_dly = temp_val; + else + return rc; + + rc = of_property_read_u32(np, "focaltech,soft-reset-delay-ms", + &temp_val); + if (!rc) + pdata->soft_rst_dly = temp_val; + else + return rc; + + rc = of_property_read_u32(np, "focaltech,num-max-touches", &temp_val); + if (!rc) + pdata->num_max_touches = temp_val; + else + return rc; + + rc = of_property_read_u32(np, "focaltech,fw-delay-aa-ms", &temp_val); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw delay aa\n"); + return rc; + } else if (rc != -EINVAL) + pdata->info.delay_aa = temp_val; + + rc = of_property_read_u32(np, "focaltech,fw-delay-55-ms", &temp_val); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw delay 55\n"); + return rc; + } else if (rc != -EINVAL) + pdata->info.delay_55 = temp_val; + + rc = of_property_read_u32(np, "focaltech,fw-upgrade-id1", &temp_val); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw upgrade id1\n"); + return rc; + } else if (rc != -EINVAL) + pdata->info.upgrade_id_1 = temp_val; + + rc = of_property_read_u32(np, "focaltech,fw-upgrade-id2", &temp_val); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw upgrade id2\n"); + return rc; + } else if (rc != -EINVAL) + pdata->info.upgrade_id_2 = temp_val; + + rc = of_property_read_u32(np, "focaltech,fw-delay-readid-ms", + &temp_val); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw delay read id\n"); + return rc; + } else if (rc != -EINVAL) + pdata->info.delay_readid = temp_val; + + rc = of_property_read_u32(np, "focaltech,fw-delay-era-flsh-ms", + &temp_val); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw delay erase flash\n"); + return rc; + } else if (rc != -EINVAL) + pdata->info.delay_erase_flash = temp_val; + + pdata->info.auto_cal = of_property_read_bool(np, + "focaltech,fw-auto-cal"); + + pdata->resume_in_workqueue = of_property_read_bool(np, + "focaltech,resume-in-workqueue"); + + + pdata->fw_vkey_support = of_property_read_bool(np, + "focaltech,fw-vkey-support"); + + pdata->ignore_id_check = of_property_read_bool(np, + "focaltech,ignore-id-check"); + + rc = of_property_read_u32(np, "focaltech,num-virtual-key", &temp_val); + if (rc && (rc != -EINVAL)) { + printk("[%s]focaltech,num-virtual-key,dts parase failed\n", __FUNCTION__); + return rc; + } else if (rc != -EINVAL) { + pdata->num_virkey = temp_val; + } + rc = ft5435_get_dt_vkey(dev, pdata); + if (rc) { + printk("[%s]focaltech,ft5435_get_dt_vkey failed\n", __FUNCTION__); + return rc; + } + + rc = of_property_read_u32(np, "focaltech,family-id", &temp_val); + if (!rc) + pdata->family_id = temp_val; + else + return rc; + + return 0; +} +#else +static int ft5435_parse_dt(struct device *dev, + struct ft5435_ts_platform_data *pdata) +{ + return -ENODEV; +} +#endif + +#if defined(FOCALTECH_PWRON_UPGRADE) +static void ft_init_update_work(struct work_struct *work) +{ + struct delayed_work *delay_work; + struct ft5435_ts_data *ts; + struct device *dev; + + delay_work = to_delayed_work(work); + ts = container_of(delay_work, struct ft5435_ts_data, focaltech_update_work); + dev = &ts->input_dev->dev; + + mutex_lock(&ts->input_dev->mutex); + ft5435_fw_upgrade(dev, false); + + mutex_unlock(&ts->input_dev->mutex); +} + +u8 ft_init_update_proc(struct ft5435_ts_data *ts) +{ + dev_dbg(&ts->client->dev, "Ready to run update work."); + + INIT_DELAYED_WORK(&ts->focaltech_update_work, ft_init_update_work); + schedule_delayed_work(&ts->focaltech_update_work, + msecs_to_jiffies(3000)); + + return 0; +} +#endif + +#if defined(FOCALTECH_TP_GESTURE) +void keyset_for_tp_gesture(struct input_dev *input_dev) +{ + input_set_capability(input_dev, EV_KEY, KEY_WAKEUP); + +} +#endif + + +#if defined(RAWDATA_INTERFACE) +extern struct ft5435_rawdata_test_result ft5436_rawdata_test_result; +extern int rawdata_fail_num; +#define FTS_TX_MAX 40 +#define FTS_RX_MAX 40 +#define FTS_DEVICE_MODE_REG 0x00 +#define FTS_RAW_READ_REG 0x01 +#define FTS_RAW_BEGIN_REG 0x10 + +static int ft5x0x_enter_factory(void) +{ + u8 regval; + + ft5x0x_write_reg(ft_g_client, 0, 0x40); + mdelay(100); + if (ft5x0x_read_reg(ft_g_client, 0x00, ®val) < 0) { + pr_err("%s ERROR: could not read register\n", __FUNCTION__); + return -EPERM; + } + + if ((regval & 0x70) != 0x40) { + pr_err("%s ERROR:Touch Panel put in Factory Mode err. Mode reg: 0x%02X\n", __func__, regval); + return -EPERM; + } + + return 0; +} + +static int ft5x0x_enter_work(void) +{ + u8 regval; + ft5x0x_write_reg(ft_g_client, 0x00, 0x00); + msleep(100); + + if (ft5x0x_read_reg(ft_g_client, 0x00, ®val) < 0) { + pr_err("%s ERROR: could not read register\n", __FUNCTION__); + return -EPERM; + } + + if ((regval & 0x70) != 0x00) { + pr_err("%s ERROR:Touch Panel put in Work Mode err. Mode reg: 0x%02X\n", __func__, regval); + return -EPERM; + } + + return 0; +} + + +static int ft5x0x_read_rawdata(u16 rawdata[][FTS_RX_MAX], + u8 tx, u8 rx) +{ + u8 i = 0, j = 0, k = 0; + int err = 0; + u8 regvalue = 0x00; + u8 regaddr = 0x00; + u16 dataval = 0x0000; + u8 writebuf[2] = {0}; + u8 read_buffer[FTS_RX_MAX * 2]; + /*scan*/ + err = ft5x0x_read_reg(ft_g_client, FTS_DEVICE_MODE_REG, ®value); + if (err < 0) + return err; + + regvalue |= 0x80; + err = ft5x0x_write_reg(ft_g_client, FTS_DEVICE_MODE_REG, regvalue); + if (err < 0) + return err; + + for (i = 0; i < 20; i++) { + msleep(8); + err = ft5x0x_read_reg(ft_g_client, FTS_DEVICE_MODE_REG, + ®value); + if (err < 0) + return err; + + if (0 == (regvalue >> 7)) + break; + } + + /*get rawdata*/ + + for (i = 0; i < tx; i++) { + memset(read_buffer, 0x00, (FTS_RX_MAX * 2)); + writebuf[0] = FTS_RAW_READ_REG; + writebuf[1] = i; + err = ft5435_i2c_write(ft_g_client, writebuf, 2); + if (err < 0) { + return err; + } + /* Read the data for this row */ + regaddr = FTS_RAW_BEGIN_REG; + err = ft5435_i2c_read(ft_g_client, ®addr, 1, read_buffer, rx*2); + if (err < 0) { + return err; + } + + k = 0; + for (j = 0; j < rx*2; j += 2) { + dataval = read_buffer[j]; + dataval = (dataval << 8); + dataval |= read_buffer[j+1]; + rawdata[i][k] = dataval; + k++; + } + } + + return 0; +} + +static int fts_get_channel_info(u8 *rx, u8 *tx) +{ + /*get rx and tx num*/ + if (ft5x0x_read_reg(ft_g_client, 0x02, tx) < 0) { + printk("%s: get tx info err!\n", __func__); + return -EPERM; + } + + if (ft5x0x_read_reg(ft_g_client, 0x03, rx) < 0) { + printk("%s: get rx info err!\n", __func__); + return -EPERM; + } + + return 0; +} + +static u16 g_rawdata[FTS_TX_MAX][FTS_RX_MAX]; +static ssize_t ft5435_rawdata_register(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + struct ft5435_ts_data *data = i2c_get_clientdata(ft_g_client); + int i, j, p = 0; + u8 rx, tx; + int ret; + +printk("ft5435_rawdata_register: start\n"); + mutex_lock(&data->input_dev->mutex); + if (data->loading_fw) { + p = sprintf(buf+p, "loading fw!!!"); + goto RAW_ERROR; + } + + data->loading_fw = true; + if (ft5x0x_enter_factory()) { + p = sprintf(buf+p, "enter factory mode err!!!"); + goto RAW_ERROR; + } + + if (fts_get_channel_info(&rx, &tx)) { + p = sprintf(buf+p, "read channel info error!!\n"); + goto RAW_ERROR; + } + +/*[BUGFIX] ADD BEGIN - hui.wang,2014/03/17 PR-618021 To get the params*/ + p += sprintf(buf+p, "tp channel: tx = %u, rx = %u\n", tx, rx); +/*[BUGFIX] ADD END - hui.wang,2014/03/17 PR-618021 To get the params*/ + + ret = ft5x0x_read_rawdata(g_rawdata, tx, rx); + + if (ret < 0) { + p = sprintf(buf+p, "rawdata read error!\n"); + goto RAW_ERROR; + } + + for (i = 0; i < tx; i++) { + for (j = 0; j < rx; j++) { + p += sprintf(buf+p, "%u ", g_rawdata[i][j]); + } + p += sprintf(buf+p, "\n"); + } + +RAW_ERROR: + /*enter work mode*/ + data->loading_fw = false; + if (ft5x0x_enter_work()) + p = sprintf(buf+p, "enter work mode error!!\n"); + msleep(100); + mutex_unlock(&data->input_dev->mutex); + return p; +} +static ssize_t rd_result_show (struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + char *s = buf; + int i; + + + s += sprintf(s, "**************************\nAA Zone:"); + + if (rawdata_fail_num == 0) { + s += sprintf(s, "PASS\n"); + } else { + s += sprintf(s, "NG\n"); + for (i = 0; i < rawdata_fail_num; i++) { + if (ft5436_rawdata_test_result.index[i][1] < 25) { + s += sprintf(s, "X%dY%d(%u)\n", ft5436_rawdata_test_result.index[i][0], + ft5436_rawdata_test_result.index[i][1], + ft5436_rawdata_test_result.index[i][2]); + } + } + } + s += sprintf(s, "Min: %u Max: %u\n", ft5436_rawdata_test_result.min_value, ft5436_rawdata_test_result.max_value); + s += sprintf(s, "Spec Min: %u Max: %u\n", ft5436_rawdata_test_result.min_limited_value, ft5436_rawdata_test_result.max_limited_value); + + + s += sprintf(s, "**************************\nKey Zone:"); + if (rawdata_fail_num == 0) { + s += sprintf(s, "PASS\n"); + } else { + s += sprintf(s, "NG\n"); + } + s += sprintf(s, "Spec Min: %u Max: %u\n", ft5436_rawdata_test_result.min_limited_value, ft5436_rawdata_test_result.max_limited_value); + s += sprintf(s, "**************************\n"); + + return (s-buf); +} + + +static ssize_t jrd_ic_info_show (struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + u8 reg_ver; + u8 reg_vendor; + u8 ver_value, vendor_value; + int err; + char *ret = buf; + + reg_ver = FT_REG_FW_VER; + err = ft5435_i2c_read(ft_g_client, ®_ver, 1, &ver_value, 1); + if (err < 0) { + pr_err("TP FW version read failure\n"); + return sprintf (buf, "can't read firmware version \n"); + } + pr_err("0xA6=0x%x\n", ver_value); + reg_vendor = 0xA8; + err = ft5435_i2c_read(ft_g_client, ®_vendor, 1, &vendor_value, 1); + if (err < 0) { + pr_err("TP FW version read failure\n"); + return sprintf (buf, "ft irmware version(0xA6) is 0x%x\n can't read tp moudule version \n" , ver_value); + } + pr_err("0xA8=0x%x\n", vendor_value); + + ret += sprintf(ret, "%s", "TP IC: FT5436\n"); + ret += sprintf(ret, "TP module (0xA8) is 0x%x\n", vendor_value); + ret += sprintf(ret, "fimware version (0xA6) is 0x%x\n", ver_value); + return (ret - buf); +} + +static struct kobj_attribute ft5435_rawdata_attr = { + .attr = { + .name = "ft5435_rawdata", + .mode = S_IRUGO, + }, + .show = &ft5435_rawdata_register, +}; + +static struct kobj_attribute rd_result = { + .attr = { + .name = "rd_result", + .mode = S_IRUGO, + }, + .show = &rd_result_show, +}; + +static struct kobj_attribute ft5435_ic_info_attr = { + .attr = { + .name = "jrd_tp_ic_info", + .mode = S_IRUGO, + }, + .show = &jrd_ic_info_show, +}; + +static struct attribute *ft5435_rawdata_properties_attrs[] = { + &ft5435_rawdata_attr.attr, + &rd_result.attr, + &ft5435_ftsscaptest_attr.attr, + &ft5435_ic_info_attr.attr, + NULL, +}; +static struct attribute_group ft5435_rawdata_properties_attr_group = { + .attrs = ft5435_rawdata_properties_attrs, +}; +#endif + +#if defined(CONFIG_TCT_TP_FTDEBUG) +#define FTS_PACKET_LENGTH 128 +#define PROC_UPGRADE 0 +#define PROC_READ_REGISTER 1 +#define PROC_WRITE_REGISTER 2 +#define PROC_AUTOCLB 4 +#define PROC_UPGRADE_INFO 5 +#define PROC_WRITE_DATA 6 +#define PROC_READ_DATA 7 + +#define PROC_NAME "ft5x0x-debug" +static unsigned char proc_operate_mode = PROC_UPGRADE; +static struct proc_dir_entry *ft5x0x_proc_entry; + + +/*interface of write proc*/ +static ssize_t ft5x0x_debug_write(struct file *filp, const char __user *buffer, size_t count, loff_t *off) +{ + struct i2c_client *client = ft_g_client; + unsigned char writebuf[FTS_PACKET_LENGTH]; + int buflen = count; + int writelen = 0; + int ret = 0; + + if (copy_from_user(writebuf, (void __user *)buffer, buflen)) { + dev_err(&client->dev, "%s:copy from user error\n", __func__); + return -EFAULT; + } + + proc_operate_mode = writebuf[0]; + printk("proc_operate_mode = %d\n", proc_operate_mode); + switch (proc_operate_mode) { + case PROC_READ_REGISTER: + printk("%s, %d:PROC_READ_REGISTER\n", __func__, __LINE__); + writelen = 1; + ret = ft5435_i2c_write(client, writebuf + 1, writelen); + if (ret < 0) { + dev_err(&client->dev, "%s:write iic error\n", __func__); + return ret; + } + break; + case PROC_WRITE_REGISTER: + printk("%s, %d:PROC_WRITE_REGISTER\n", __func__, __LINE__); + writelen = 2; + ret = ft5435_i2c_write(client, writebuf + 1, writelen); + if (ret < 0) { + dev_err(&client->dev, "%s:write iic error\n", __func__); + return ret; + } + break; + case PROC_AUTOCLB: + printk("%s, %d:PROC_AUTOCLB\n", __func__, __LINE__); + printk("%s: autoclb\n", __func__); + fts_ctpm_auto_clb(client); + break; + case PROC_READ_DATA: + case PROC_WRITE_DATA: + printk("%s, %d:PROC_READ_DATA, PROC_WRITE_DATA\n", __func__, __LINE__); + writelen = count - 1; + ret = ft5435_i2c_write(client, writebuf + 1, writelen); + if (ret < 0) { + dev_err(&client->dev, "%s:write iic error\n", __func__); + return ret; + } + break; + default: + printk("%s, %d:default\n", __func__, __LINE__); + break; + } + + return count; +} + +/*interface of read proc*/ +static ssize_t ft5x0x_debug_read(struct file *file, char __user *page, size_t size, loff_t *ppos) +{ + struct i2c_client *client = ft_g_client; + int ret = 0; + unsigned char buf[1000]; + int num_read_chars = 0; + int readlen = 0; + u8 regvalue = 0x00, regaddr = 0x00; + + switch (proc_operate_mode) { + case PROC_UPGRADE: + /*after calling ft5x0x_debug_write to upgrade*/ + printk("%s, %d:PROC_UPGRADE\n", __func__, __LINE__); + regaddr = 0xA6; + ret = ft5x0x_read_reg(client, regaddr, ®value); + if (ret < 0) + num_read_chars = sprintf(buf, "%s", "get fw version failed.\n"); + else + num_read_chars = sprintf(buf, "current fw version:0x%02x\n", regvalue); + break; + case PROC_READ_REGISTER: + readlen = 1; + ret = ft5435_i2c_read(client, NULL, 0, buf, readlen); + if (ret < 0) { + dev_err(&client->dev, "%s:read iic error\n", __func__); + return ret; + } + printk("%s, %d:PROC_READ_REGISTER, buf = %c\n", __func__, __LINE__, *buf); + num_read_chars = 1; + break; + case PROC_READ_DATA: + printk("%s, %d:PROC_READ_DATA\n", __func__, __LINE__); + readlen = size; + ret = ft5435_i2c_read(client, NULL, 0, buf, readlen); + if (ret < 0) { + dev_err(&client->dev, "%s:read iic error\n", __func__); + return ret; + } + + num_read_chars = readlen; + break; + case PROC_WRITE_DATA: + printk("%s, %d:PROC_WRITE_DATA\n", __func__, __LINE__); + break; + default: + printk("%s, %d:default\n", __func__, __LINE__); + break; + } + + memcpy(page, buf, num_read_chars); + + return num_read_chars; +} + +static const struct file_operations ft5x0x_debug_ops = { + .owner = THIS_MODULE, + .read = ft5x0x_debug_read, + .write = ft5x0x_debug_write, +}; + +static int ft5x0x_create_apk_debug_channel(struct i2c_client *client) +{ + ft5x0x_proc_entry = proc_create(PROC_NAME, 0777, NULL, &ft5x0x_debug_ops); + + if (NULL == ft5x0x_proc_entry) { + dev_err(&client->dev, "Couldn't create proc entry!\n"); + return -ENOMEM; + } else { + dev_info(&client->dev, "Create proc entry success!\n"); + } + return 0; +} + +static void ft5x0x_release_apk_debug_channel(void) +{ + if (ft5x0x_proc_entry) + remove_proc_entry(PROC_NAME, NULL); +} +#endif + +static char tp_info_summary[80] = ""; + +static int ft5435_ts_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct ft5435_ts_platform_data *pdata; + struct ft5435_ts_data *data; + struct input_dev *input_dev; + struct dentry *temp; + u8 reg_value; + u8 reg_addr; + int err, len; + u8 w_buf[FT_MAX_WR_BUF] = {0}; + int i; + int retry = 3; + char tp_temp_info[80]; + printk("~~~~~ ft5435_ts_probe start\n"); + +#if defined(CONFIG_FB) + printk("[%s]CONFIG_FB is defined\n", __FUNCTION__); +#endif +#if defined(CONFIG_PM) + printk("[%s]CONFIG_PM is defined\n", __FUNCTION__); +#endif + + if (client->dev.of_node) { + pdata = devm_kzalloc(&client->dev, + sizeof(struct ft5435_ts_platform_data), GFP_KERNEL); + if (!pdata) { + dev_err(&client->dev, "Failed to allocate memory\n"); + return -ENOMEM; + } + + err = ft5435_parse_dt(&client->dev, pdata); + if (err) { + dev_err(&client->dev, "DT parsing failed\n"); + return err; + } + } else + pdata = client->dev.platform_data; + + if (!pdata) { + dev_err(&client->dev, "Invalid pdata\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "I2C not supported\n"); + return -ENODEV; + } + + data = devm_kzalloc(&client->dev, + sizeof(struct ft5435_ts_data), GFP_KERNEL); + if (!data) { + dev_err(&client->dev, "Not enough memory\n"); + return -ENOMEM; + } + + if (pdata->fw_name) { + len = strlen(pdata->fw_name); + if (len > FT_FW_NAME_MAX_LEN - 1) { + dev_err(&client->dev, "Invalid firmware name\n"); + return -EINVAL; + } + + strlcpy(data->fw_name, pdata->fw_name, len + 1); + } + + data->tch_data_len = FT_TCH_LEN(pdata->num_max_touches); + data->tch_data = devm_kzalloc(&client->dev, + data->tch_data_len, GFP_KERNEL); + if (!data) { + dev_err(&client->dev, "Not enough memory\n"); + return -ENOMEM; + } + + input_dev = input_allocate_device(); + if (!input_dev) { + dev_err(&client->dev, "failed to allocate input device\n"); + return -ENOMEM; + } + + ft_g_client = client; + data->input_dev = input_dev; + data->client = client; + data->pdata = pdata; + + input_dev->name = "ft5435_ts"; + input_dev->id.bustype = BUS_I2C; + input_dev->dev.parent = &client->dev; + + input_set_drvdata(input_dev, data); + i2c_set_clientdata(client, data); + + __set_bit(EV_KEY, input_dev->evbit); + __set_bit(EV_ABS, input_dev->evbit); + __set_bit(BTN_TOUCH, input_dev->keybit); + __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); + + for (i = 0; i < pdata->num_virkey; i++) { + input_set_capability(input_dev, EV_KEY, + pdata->vkeys[i].keycode); + } + input_mt_init_slots(input_dev, pdata->num_max_touches, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min, + pdata->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min, + pdata->y_max, 0, 0); +#if defined(USB_CHARGE_DETECT) +INIT_WORK(&data->work, ft5435_change_scanning_frq_switch); +#endif + +#if defined(LEATHER_COVER) +INIT_WORK(&data->work_cover, ft5435_change_leather_cover_switch); +#endif +#if defined(VR_GLASS) +INIT_WORK(&data->work_vr, ft5435_change_vr_switch); +#endif + +#if defined(FOCALTECH_TP_GESTURE) + keyset_for_tp_gesture(input_dev); + input_dev->event = ft5435_gesture_switch; +#endif + err = input_register_device(input_dev); + if (err) { + dev_err(&client->dev, "Input device registration failed\n"); + goto free_inputdev; + } + + if (gpio_is_valid(pdata->reset_gpio)) { + err = gpio_request(pdata->reset_gpio, "ft5435_reset_gpio"); + if (err) { + dev_err(&client->dev, "reset gpio request failed"); + goto unreg_inputdev; + } + + err = gpio_direction_output(pdata->reset_gpio, 0); + if (err) { + dev_err(&client->dev, + "set_direction for reset gpio failed\n"); + goto free_reset_gpio; + } + msleep(2); + } + + if (pdata->power_init) { + err = pdata->power_init(true); + if (err) { + dev_err(&client->dev, "power init failed"); + goto free_reset_gpio; + } + } else { + err = ft5435_power_init(data, true); + if (err) { + dev_err(&client->dev, "power init failed"); + goto free_reset_gpio; + } + } + + if (pdata->power_on) { + err = pdata->power_on(true); + if (err) { + dev_err(&client->dev, "power on failed"); + goto pwr_deinit; + } + } else { + err = ft5435_power_on(data, true); + if (err) { + dev_err(&client->dev, "power on failed"); + goto pwr_deinit; + } + } + + msleep(2); + + err = ft5435_ts_pinctrl_init(data); + if (!err && data->ts_pinctrl) { + err = ft5435_ts_pinctrl_select(data, true); + if (err < 0) + goto pwr_off; + } + + if (gpio_is_valid(pdata->irq_gpio)) { + err = gpio_request(pdata->irq_gpio, "ft5435_irq_gpio"); + if (err) { + dev_err(&client->dev, "irq gpio request failed"); + goto pwr_off; + } + err = gpio_direction_input(pdata->irq_gpio); + if (err) { + dev_err(&client->dev, + "set_direction for irq gpio failed\n"); + goto free_irq_gpio; + } + } + + if (gpio_is_valid(pdata->reset_gpio)) { + gpio_set_value_cansleep(data->pdata->reset_gpio, 1); + } + + /* make sure CTP already finish startup process */ + msleep(data->pdata->soft_rst_dly); + + /* check the controller id */ + reg_addr = FT_REG_ID; + while (retry--) { + err = ft5435_i2c_read(client, ®_addr, 1, ®_value, 1); + if (!(err < 0)) { +#ifdef CONFIG_MACH_XIAOMI_MIDO + set_usb_charge_mode_par = 2; +#endif + dev_info(&client->dev, "Device ID = 0x%x\n", reg_value); + break; + } + if (gpio_is_valid(pdata->reset_gpio)) { + gpio_set_value_cansleep(data->pdata->reset_gpio, 0); + msleep(10); + gpio_set_value_cansleep(data->pdata->reset_gpio, 1); + msleep(200); + } + if (retry == 0) { + dev_err(&client->dev, "version read failed"); + goto free_irq_gpio; + } + } + data->family_id = pdata->family_id; + + +#ifdef CONFIG_TOUCHPANEL_PROXIMITY_SENSOR + vps_ft5436 = kzalloc(sizeof(struct virtualpsensor), GFP_KERNEL); + if (!vps_ft5436) { + dev_err(&client->dev, "Not enough memory\n"); + return -ENOMEM; + } + virtual_psensor_input_register2(client) ; + sys_device_create(); +#endif + + + mutex_init(&g_device_mutex); + +#if defined(FOCALTECH_PWRON_UPGRADE) + err = ft_init_update_proc(data); + if (err < 0) { + dev_err(&client->dev, + "GTP Create firmware update thread error.\n"); + + } +#endif + err = request_threaded_irq(client->irq, NULL, + ft5435_ts_interrupt, + pdata->irqflags | IRQF_ONESHOT|IRQF_TRIGGER_FALLING, + client->dev.driver->name, data); + if (err) { + dev_err(&client->dev, "request irq failed\n"); + goto free_reset_gpio; + } + + err = device_create_file(&client->dev, &dev_attr_fw_name); + if (err) { + dev_err(&client->dev, "sys file creation failed\n"); + goto irq_free; + } + + err = device_create_file(&client->dev, &dev_attr_fw_version); + if (err) { + dev_err(&client->dev, "sys file creation failed\n"); + goto free_fw_name_sys; + } + + err = device_create_file(&client->dev, &dev_attr_update_fw); + if (err) { + dev_err(&client->dev, "sys file creation failed\n"); + goto free_fw_version_sys; + } + + err = device_create_file(&client->dev, &dev_attr_force_update_fw); + if (err) { + dev_err(&client->dev, "sys file creation failed\n"); + goto free_update_fw_sys; + } +#ifdef SET_COVER_MODE + err = device_create_file(&client->dev, &dev_attr_set_cover_mode); + if (err) { + dev_err(&client->dev, "sys file creation failed\n"); + goto free_set_cover_mode; + } +#endif + data->dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL); + if (data->dir == NULL || IS_ERR(data->dir)) { + pr_err("debugfs_create_dir failed(%ld)\n", PTR_ERR(data->dir)); + err = PTR_ERR(data->dir); + goto free_force_update_fw_sys; + } + + temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, data->dir, data, + &debug_addr_fops); + if (temp == NULL || IS_ERR(temp)) { + pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp)); + err = PTR_ERR(temp); + goto free_debug_dir; + } + + temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, data->dir, data, + &debug_data_fops); + if (temp == NULL || IS_ERR(temp)) { + pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp)); + err = PTR_ERR(temp); + goto free_debug_dir; + } + + temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, data->dir, + data, &debug_suspend_fops); + if (temp == NULL || IS_ERR(temp)) { + pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp)); + err = PTR_ERR(temp); + goto free_debug_dir; + } + + temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR, data->dir, + data, &debug_dump_info_fops); + if (temp == NULL || IS_ERR(temp)) { + pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp)); + err = PTR_ERR(temp); + goto free_debug_dir; + } + + data->ts_info = devm_kzalloc(&client->dev, + FT_INFO_MAX_LEN, GFP_KERNEL); + if (!data->ts_info) { + dev_err(&client->dev, "Not enough memory\n"); + goto free_debug_dir; + } + + /*get some register information */ + reg_addr = FT_REG_POINT_RATE; + ft5435_i2c_read(client, ®_addr, 1, ®_value, 1); + if (err < 0) + dev_err(&client->dev, "report rate read failed"); + + dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10); + + reg_addr = FT_REG_THGROUP; + err = ft5435_i2c_read(client, ®_addr, 1, ®_value, 1); + if (err < 0) + dev_err(&client->dev, "threshold read failed"); + + dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4); + + ft5435_update_fw_ver(data); + ft5435_update_fw_vendor_id(data); + fts_fw_vendor_id = data->fw_vendor_id; + printk("upgrade,fts_fw_vendor_id=0x%02x\n", data->fw_vendor_id); +#if defined(FOCALTECH_AUTO_UPGRADE) + if ((fts_fw_vendor_id != FTS_VENDOR_1) && (fts_fw_vendor_id != FTS_VENDOR_2)) { + fts_fw_vendor_id = ft5435_fw_Vid_get_from_boot(client); + printk("get_Vid_from_boot, fw_vendor_id=0x%02x\n", fts_fw_vendor_id); + } + + mutex_lock(&data->input_dev->mutex); + if (!data->loading_fw) { + data->loading_fw = true; + if (fts_fw_vendor_id == FTS_VENDOR_1) + ft5435_fw_upgrade_by_array_data(&client->dev, firmware_data_vendor1, sizeof(firmware_data_vendor1), !data->pdata->no_force_update); + else if (fts_fw_vendor_id == FTS_VENDOR_2) + ft5435_fw_upgrade_by_array_data(&client->dev, firmware_data_vendor2, sizeof(firmware_data_vendor2), !data->pdata->no_force_update); + else + printk("[FTS] FW unmatched,stop upgrade\n"); + data->loading_fw = false; + } + mutex_unlock(&data->input_dev->mutex); + +#endif + + FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name, + data->pdata->num_max_touches, data->pdata->group_id, + data->pdata->fw_vkey_support ? "yes" : "no", + data->pdata->fw_name, data->fw_ver[0], + data->fw_ver[1], data->fw_ver[2]); + +#if defined(CONFIG_FB) + + data->fb_notif.notifier_call = fb_notifier_callback; + + err = fb_register_client(&data->fb_notif); + + if (err) + dev_err(&client->dev, "Unable to register fb_notifier: %d\n", + err); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + + FT_SUSPEND_LEVEL; + data->early_suspend.suspend = ft5435_ts_early_suspend; + data->early_suspend.resume = ft5435_ts_late_resume; + register_early_suspend(&data->early_suspend); +#endif + + +/* [PLATFORM]-Mod-BEGIN by TCTNB.ZXZ, PR-814306, 2014/10/24, add for alto5 premium firmware version*/ +#ifdef CONFIG_TCT_8X16_ALTO5_PREMIUM +firm_ver_attr_create(); +#endif +/* [PLATFORM]-Mod-END by TCTNB.ZXZ*/ + +#ifdef FOCALTECH_TP_GLOVE + tp_glove_register(data); +#endif + + +g_ft5435_ts_data = data; + + +#if defined(RAWDATA_INTERFACE) +{ + static struct kobject *ft5435_rawdata_properties_kobj; + static struct kobject *ft5435_CTP_properties_kobj; + int rc = 0; + + ft5435_rawdata_properties_kobj = + kobject_create_and_add("rawdata", NULL); + + if (ft5435_rawdata_properties_kobj) + rc = sysfs_create_group(ft5435_rawdata_properties_kobj, + &ft5435_rawdata_properties_attr_group); + + if (!ft5435_rawdata_properties_kobj || rc) + pr_err("%s: failed to create rawdata\n", __func__); + + ft5435_CTP_properties_kobj = + kobject_create_and_add("CTP", NULL); + + if (ft5435_CTP_properties_kobj) + rc = sysfs_create_group(ft5435_CTP_properties_kobj, + &ft5435_rawdata_properties_attr_group); + + if (!ft5435_CTP_properties_kobj || rc) + pr_err("%s: failed to create rawdata\n", __func__); +} +#endif +#ifdef FOCALTECH_LOCK_DOWN_INFO + ft5435_fw_LockDownInfo_get_from_boot(client, tp_lockdown_info); + printk("tpd_probe, ft5x46_ctpm_LockDownInfo_get_from_boot, tp_lockdown_info=%s\n", tp_lockdown_info); + ctp_lockdown_status_proc = proc_create(CTP_PROC_LOCKDOWN_FILE, 0644, NULL, &ctp_lockdown_proc_fops); + if (ctp_lockdown_status_proc == NULL) + printk("tpd, create_proc_entry ctp_lockdown_status_proc failed\n"); +#endif + +#if defined(CONFIG_TCT_TP_FTDEBUG) + if (ft5x0x_create_apk_debug_channel(client) < 0) + ft5x0x_release_apk_debug_channel(); +#endif + + w_buf[0] = FT_REG_RESET_FW; + ft5435_i2c_write(client, w_buf, 1); + init_ok = 1; + wake_lock_init(&ft5436_wakelock, WAKE_LOCK_SUSPEND, "ft5436"); + if (fts_fw_vendor_id == FTS_VENDOR_1) { + strcpy(tp_info_summary, "[Vendor]Biel, [IC]FT5435, [FW]Ver"); + } else if (fts_fw_vendor_id == FTS_VENDOR_2) { + strcpy(tp_info_summary, "[Vendor]Ofilm, [IC]FT5435, [FW]Ver"); + } else{ + strcpy(tp_info_summary, "[Vendor]Unknown, [IC]FT5435, [FW]Ver"); + } + sprintf(tp_temp_info, "%d", data->fw_ver[0]); + strcat(tp_info_summary, tp_temp_info); + strcat(tp_info_summary, "\0"); + printk("~~~~~ ft5435_ts_probe end\n"); + return 0; + +free_debug_dir: + debugfs_remove_recursive(data->dir); +free_force_update_fw_sys: + device_remove_file(&client->dev, &dev_attr_force_update_fw); +free_update_fw_sys: + device_remove_file(&client->dev, &dev_attr_update_fw); + +#ifdef SET_COVER_MODE +free_set_cover_mode: + device_remove_file(&client->dev, &dev_attr_set_cover_mode); +#endif + +free_fw_version_sys: + device_remove_file(&client->dev, &dev_attr_fw_version); + +free_fw_name_sys: + device_remove_file(&client->dev, &dev_attr_fw_name); +irq_free: + free_irq(client->irq, data); + +free_irq_gpio: + if (gpio_is_valid(pdata->irq_gpio)) + gpio_free(pdata->irq_gpio); + if (data->ts_pinctrl) { + err = ft5435_ts_pinctrl_select(data, false); + if (err < 0) + pr_err("Cannot get idle pinctrl state\n"); + } + if (data->ts_pinctrl) { + devm_pinctrl_put(data->ts_pinctrl); + data->ts_pinctrl = NULL; + } + if (gpio_is_valid(pdata->reset_gpio)) { + gpio_direction_output(pdata->reset_gpio, 0); + mdelay(2); + } +pwr_off: + if (pdata->power_on) + pdata->power_on(false); + else + ft5435_power_on(data, false); +pwr_deinit: + if (pdata->power_init) + pdata->power_init(false); + else + ft5435_power_init(data, false); +free_reset_gpio: + if (gpio_is_valid(pdata->reset_gpio)) { + gpio_direction_output(pdata->reset_gpio, 0); + mdelay(5); + gpio_free(pdata->reset_gpio); + } +unreg_inputdev: + input_unregister_device(input_dev); + input_dev = NULL; +free_inputdev: + input_free_device(input_dev); + return err; +} + +static int ft5435_ts_remove(struct i2c_client *client) +{ + struct ft5435_ts_data *data = i2c_get_clientdata(client); + int retval; + + debugfs_remove_recursive(data->dir); + device_remove_file(&client->dev, &dev_attr_force_update_fw); + device_remove_file(&client->dev, &dev_attr_update_fw); + device_remove_file(&client->dev, &dev_attr_fw_name); + +#if defined(CONFIG_FB) + if (fb_unregister_client(&data->fb_notif)) + dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n"); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + unregister_early_suspend(&data->early_suspend); +#endif + free_irq(client->irq, data); + + if (gpio_is_valid(data->pdata->reset_gpio)) + gpio_free(data->pdata->reset_gpio); + + if (gpio_is_valid(data->pdata->irq_gpio)) + gpio_free(data->pdata->irq_gpio); + + if (data->ts_pinctrl) { + retval = ft5435_ts_pinctrl_select(data, false); + if (retval < 0) + pr_err("Cannot get idle pinctrl state\n"); + devm_pinctrl_put(data->ts_pinctrl); + data->ts_pinctrl = NULL; + } + + if (data->pdata->power_on) + data->pdata->power_on(false); + else + ft5435_power_on(data, false); + + if (data->pdata->power_init) + data->pdata->power_init(false); + else + ft5435_power_init(data, false); + + +#if defined(CONFIG_TCT_TP_FTDEBUG) + ft5x0x_release_apk_debug_channel(); +#endif + + input_unregister_device(data->input_dev); + wake_lock_destroy(&ft5436_wakelock); + + return 0; +} + +static const struct i2c_device_id ft5435_ts_id[] = { + {"ft5435_ts", 0}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, ft5435_ts_id); + +#ifdef CONFIG_OF +static struct of_device_id ft5435_match_table[] = { + { .compatible = "focaltech,5435",}, + { }, +}; +#else +#define ft5435_match_table NULL +#endif + +static struct i2c_driver ft5435_ts_driver = { + .probe = ft5435_ts_probe, + .remove = ft5435_ts_remove, + .driver = { + .name = "ft5435_ts", + .owner = THIS_MODULE, + .of_match_table = ft5435_match_table, +#ifdef CONFIG_PM + .pm = &ft5435_ts_pm_ops, +#endif + }, + .id_table = ft5435_ts_id, +}; + +static int __init ft5435_ts_init(void) +{ + printk("tony_test:[%s]\n", __FUNCTION__); + ft5435_wq = create_singlethread_workqueue("ft5435_wq"); + if (!ft5435_wq) { + printk("Creat ft5435 workqueue failed. \n"); + return -ENOMEM; + } + ft5435_wq_cover = create_singlethread_workqueue("ft5435_wq_cover"); + if (!ft5435_wq_cover) { + printk("Creat ft5435_wq_cover workqueue failed. \n"); + return -ENOMEM; + } +#if defined(VR_GLASS) + ft5435_wq_vr = create_singlethread_workqueue("ft5435_wq_vr"); + if (!ft5435_wq_vr) { + printk("Creat ft5435_wq_vr workqueue failed. \n"); + return -ENOMEM; + } +#endif + return i2c_add_driver(&ft5435_ts_driver); +} +module_init(ft5435_ts_init); + +static void __exit ft5435_ts_exit(void) +{ + if (ft5435_wq) { + destroy_workqueue(ft5435_wq); + } + i2c_del_driver(&ft5435_ts_driver); +} +module_exit(ft5435_ts_exit); + +MODULE_DESCRIPTION("FocalTech ft5435 TouchScreen driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/ft5435/ft5435_ts.h b/drivers/input/touchscreen/ft5435/ft5435_ts.h new file mode 100644 index 0000000000000..986359e0a254b --- /dev/null +++ b/drivers/input/touchscreen/ft5435/ft5435_ts.h @@ -0,0 +1,93 @@ +/* + * + * FocalTech ft5435 TouchScreen driver header file. + * + * Copyright (c) 2010 Focal tech Ltd. + * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef __LINUX_FT5435_TS_H__ +#define __LINUX_FT5435_TS_H__ + +#define FT5435_ID 0x55 +#define FT5X16_ID 0x0A +#define FT5X36_ID 0x14 +#define FT6X06_ID 0x06 +#define FT6X36_ID 0x36 +/* [PLATFORM]-Mod-BEGIN by TCTNB.YQJ, FR797197, 2014/11/28 add for tp gesture */ + +#define SET_COVER_MODE +#define FOCALTECH_AUTO_UPGRADE 1 +#define FOCALTECH_LOCK_DOWN_INFO 1 +#define FOCALTECH_TP_GESTURE +#define FOCALTECH_FAE_MOD + +#define USB_CHARGE_DETECT +#define FOCALTECH_ITO_TEST 1 +#define FOCALTECH_MAX_VKEY_NUM 3 + +struct fw_upgrade_info { + bool auto_cal; + u16 delay_aa; + u16 delay_55; + u8 upgrade_id_1; + u8 upgrade_id_2; + u16 delay_readid; + u16 delay_erase_flash; +}; +struct virkey{ + int keycode; + int x; + int y; +}; +struct ft5435_ts_platform_data { + struct fw_upgrade_info info; + const char *name; + const char *fw_name; + u32 irqflags; + u32 irq_gpio; + u32 irq_gpio_flags; + u32 reset_gpio; + u32 reset_gpio_flags; + u32 family_id; + u32 x_max; + u32 y_max; + u32 x_min; + u32 y_min; + u32 panel_minx; + u32 panel_miny; + u32 panel_maxx; + u32 panel_maxy; + u32 group_id; + u32 hard_rst_dly; + u32 soft_rst_dly; + u32 num_max_touches; + bool fw_vkey_support; + bool no_force_update; + bool i2c_pull_up; + bool ignore_id_check; + bool resume_in_workqueue; + int (*power_init) (bool); + int (*power_on) (bool); + int num_virkey; + struct virkey vkeys[FOCALTECH_MAX_VKEY_NUM]; +}; +struct ft5435_rawdata_test_result { + int result; + int min_limited_value; + int max_limited_value; + int min_value; + int max_value; + int index[350][3]; +}; +#endif diff --git a/drivers/input/touchscreen/ft5435/mcap_test_lib.h b/drivers/input/touchscreen/ft5435/mcap_test_lib.h new file mode 100644 index 0000000000000..c7ab8258a659a --- /dev/null +++ b/drivers/input/touchscreen/ft5435/mcap_test_lib.h @@ -0,0 +1,26 @@ +#ifndef _FOCAL_MCAPTESTLIB_H +#define _FOCAL_MCAPTESTLIB_H + +#define boolean unsigned char +#define bool unsigned char +#define BYTE unsigned char +#define false 0 +#define true 1 + +typedef int (*FTS_I2C_READ_FUNCTION)(unsigned char *, int , unsigned char *, int); +typedef int (*FTS_I2C_WRITE_FUNCTION)(unsigned char *, int); + +extern FTS_I2C_READ_FUNCTION fts_i2c_read_test; +extern FTS_I2C_WRITE_FUNCTION fts_i2c_write_test; + +extern int init_i2c_read_func(FTS_I2C_READ_FUNCTION fpI2C_Read); +extern int init_i2c_write_func(FTS_I2C_WRITE_FUNCTION fpI2C_Write); + +int set_param_data(char *TestParamData); +boolean start_test_tp(void); +int get_test_data(char *pTestData); + +void free_test_param_data(void); +int show_lib_ver(char *pLibVer); + +#endif diff --git a/drivers/input/touchscreen/gt9xx_mido/Makefile b/drivers/input/touchscreen/gt9xx_mido/Makefile new file mode 100644 index 0000000000000..100fefff55922 --- /dev/null +++ b/drivers/input/touchscreen/gt9xx_mido/Makefile @@ -0,0 +1,8 @@ +#gt915 touchpanel driver + +EXTRA_CFLAGS +=-Wno-error=date-time +EXTRA_CFLAGS +=-Wno-date-time + +obj-$(CONFIG_TOUCHSCREEN_GT9XX_MIDO) += gt9xx.o +obj-$(CONFIG_TOUCHSCREEN_GT9XX_MIDO) += gt9xx_update.o +obj-$(CONFIG_TOUCHSCREEN_GT9XX_MIDO) += goodix_tool.o diff --git a/drivers/input/touchscreen/gt9xx_mido/goodix_tool.c b/drivers/input/touchscreen/gt9xx_mido/goodix_tool.c new file mode 100644 index 0000000000000..597fd95e8a896 --- /dev/null +++ b/drivers/input/touchscreen/gt9xx_mido/goodix_tool.c @@ -0,0 +1,531 @@ +/* + * Goodix GT9xx touchscreen driver + * + * Copyright (C) 2010 - 2014 Goodix. Ltd. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be a reference + * to you, when you are integrating the GOODiX's CTP IC into your system, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Version: 2.4 + * Release Date: 2014/11/28 + */ + +#include "gt9xx.h" + +#define DATA_LENGTH_UINT 512 +#define CMD_HEAD_LENGTH (sizeof(st_cmd_head) - sizeof(u8 *)) +static char procname[20] = {0}; + +#define UPDATE_FUNCTIONS + +#ifdef UPDATE_FUNCTIONS +extern s32 gup_enter_update_mode(struct i2c_client *client); +extern void gup_leave_update_mode(void); +extern s32 gup_update_proc(void *dir); +#endif + +extern void gtp_irq_disable(struct goodix_ts_data *); +extern void gtp_irq_enable(struct goodix_ts_data *); + +#pragma pack(1) +typedef struct{ + u8 wr; + u8 flag; + u8 flag_addr[2]; + u8 flag_val; + u8 flag_relation; + u16 circle; + u8 times; + u8 retry; + u16 delay; + u16 data_len; + u8 addr_len; + u8 addr[2]; + u8 res[3]; + u8 *data; +} st_cmd_head; +#pragma pack() +st_cmd_head cmd_head; + +static struct i2c_client *gt_client; + +static struct proc_dir_entry *goodix_proc_entry; + +static ssize_t goodix_tool_read(struct file *, char __user *, size_t, loff_t *); +static ssize_t goodix_tool_write(struct file *, const char __user *, size_t, loff_t *); +static const struct file_operations tool_ops = { + .owner = THIS_MODULE, + .read = goodix_tool_read, + .write = goodix_tool_write, +}; + + + +static s32 (*tool_i2c_read)(u8 *, u16); +static s32 (*tool_i2c_write)(u8 *, u16); + +#if GTP_ESD_PROTECT +extern void gtp_esd_switch(struct i2c_client *, s32); +#endif +s32 DATA_LENGTH = 0; +s8 IC_TYPE[16] = "GT9XX"; + +static void tool_set_proc_name(char *procname) +{ + char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", + "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + char date[20] = {0}; + char month[4] = {0}; + int i = 0, n_month = 1, n_day = 0, n_year = 0; + + sprintf(date, "%s", __DATE__); + sscanf(date, "%s %d %d", month, &n_day, &n_year); + + for (i = 0; i < 12; ++i) { + if (!memcmp(months[i], month, 3)) { + n_month = i+1; + break; + } + } + sprintf(procname, "gmnode"); +} + +static s32 tool_i2c_read_no_extra(u8 *buf, u16 len) +{ + s32 ret = -1; + s32 i = 0; + struct i2c_msg msgs[2]; + + msgs[0].flags = !I2C_M_RD; + msgs[0].addr = gt_client->addr; + msgs[0].len = cmd_head.addr_len; + msgs[0].buf = &buf[0]; + + msgs[1].flags = I2C_M_RD; + msgs[1].addr = gt_client->addr; + msgs[1].len = len; + msgs[1].buf = &buf[GTP_ADDR_LENGTH]; + + for (i = 0; i < cmd_head.retry; i++) { + ret = i2c_transfer(gt_client->adapter, msgs, 2); + if (ret > 0) + break; + } + return ret; +} + +static s32 tool_i2c_write_no_extra(u8 *buf, u16 len) +{ + s32 ret = -1; + s32 i = 0; + struct i2c_msg msg; + + msg.flags = !I2C_M_RD; + msg.addr = gt_client->addr; + msg.len = len; + msg.buf = buf; + + for (i = 0; i < cmd_head.retry; i++) { + ret = i2c_transfer(gt_client->adapter, &msg, 1); + if (ret > 0) + break; + } + return ret; +} + +static s32 tool_i2c_read_with_extra(u8 *buf, u16 len) +{ + s32 ret = -1; + u8 pre[2] = {0x0f, 0xff}; + u8 end[2] = {0x80, 0x00}; + + tool_i2c_write_no_extra(pre, 2); + ret = tool_i2c_read_no_extra(buf, len); + tool_i2c_write_no_extra(end, 2); + + return ret; +} + +static s32 tool_i2c_write_with_extra(u8 *buf, u16 len) +{ + s32 ret = -1; + u8 pre[2] = {0x0f, 0xff}; + u8 end[2] = {0x80, 0x00}; + + tool_i2c_write_no_extra(pre, 2); + ret = tool_i2c_write_no_extra(buf, len); + tool_i2c_write_no_extra(end, 2); + + return ret; +} + +static void register_i2c_func(void) +{ + if (strncmp(IC_TYPE, "GT8110", 6) && strncmp(IC_TYPE, "GT8105", 6) + && strncmp(IC_TYPE, "GT801", 5) && strncmp(IC_TYPE, "GT800", 5) + && strncmp(IC_TYPE, "GT801PLUS", 9) && strncmp(IC_TYPE, "GT811", 5) + && strncmp(IC_TYPE, "GTxxx", 5) && strncmp(IC_TYPE, "GT9XX", 5)) { + tool_i2c_read = tool_i2c_read_with_extra; + tool_i2c_write = tool_i2c_write_with_extra; + GTP_DEBUG("I2C function: with pre and end cmd!"); + } else { + tool_i2c_read = tool_i2c_read_no_extra; + tool_i2c_write = tool_i2c_write_no_extra; + GTP_INFO("I2C function: without pre and end cmd!"); + } +} + +static void unregister_i2c_func(void) +{ + tool_i2c_read = NULL; + tool_i2c_write = NULL; + GTP_INFO("I2C function: unregister i2c transfer function!"); +} + +s32 init_wr_node(struct i2c_client *client) +{ + s32 i; + + gt_client = client; + memset(&cmd_head, 0, sizeof(cmd_head)); + cmd_head.data = NULL; + + i = 5; + while ((!cmd_head.data) && i) { + cmd_head.data = kzalloc(i * DATA_LENGTH_UINT, GFP_KERNEL); + if (NULL != cmd_head.data) { + break; + } + i--; + } + if (i) { + DATA_LENGTH = i * DATA_LENGTH_UINT + GTP_ADDR_LENGTH; + GTP_INFO("Applied memory size:%d.", DATA_LENGTH); + } else { + GTP_ERROR("Apply for memory failed."); + return FAIL; + } + + cmd_head.addr_len = 2; + cmd_head.retry = 5; + + register_i2c_func(); + + tool_set_proc_name(procname); + goodix_proc_entry = proc_create(procname, 0666, NULL, &tool_ops); + if (goodix_proc_entry == NULL) { + GTP_ERROR("Couldn't create proc entry!"); + return FAIL; + } else { + GTP_INFO("Create proc entry success!"); + } + + return SUCCESS; +} + +void uninit_wr_node(void) +{ + kfree(cmd_head.data); + cmd_head.data = NULL; + unregister_i2c_func(); + remove_proc_entry(procname, NULL); +} + +static u8 relation(u8 src, u8 dst, u8 rlt) +{ + u8 ret = 0; + + switch (rlt) { + + case 0: + ret = (src != dst) ? true : false; + break; + + case 1: + ret = (src == dst) ? true : false; + GTP_DEBUG("equal:src:0x%02x dst:0x%02x ret:%d.",src, dst, (s32)ret); + break; + + case 2: + ret = (src > dst) ? true : false; + break; + + case 3: + ret = (src < dst) ? true : false; + break; + + case 4: + ret = (src & dst) ? true : false; + break; + + case 5: + ret = (!(src | dst)) ? true : false; + break; + + default: + ret = false; + break; + } + + return ret; +} + +/******************************************************* +Function: + Comfirm function. +Input: + None. +Output: + Return write length. +********************************************************/ +static u8 comfirm(void) +{ + s32 i = 0; + u8 buf[32]; + + memcpy(buf, cmd_head.flag_addr, cmd_head.addr_len); + + for (i = 0; i < cmd_head.times; i++) { + if (tool_i2c_read(buf, 1) <= 0) { + GTP_ERROR("Read flag data failed!"); + return FAIL; + } + if (true == relation(buf[GTP_ADDR_LENGTH], cmd_head.flag_val, cmd_head.flag_relation)) { + GTP_DEBUG("value at flag addr:0x%02x.", buf[GTP_ADDR_LENGTH]); + GTP_DEBUG("flag value:0x%02x.", cmd_head.flag_val); + break; + } + + msleep(cmd_head.circle); + } + + if (i >= cmd_head.times) { + GTP_ERROR("Didn't get the flag to continue!"); + return FAIL; + } + + return SUCCESS; +} + +/******************************************************* +Function: + Goodix tool write function. +Input: + standard proc write function param. +Output: + Return write length. +********************************************************/ + +ssize_t goodix_tool_write(struct file *filp, const char __user *buff, size_t len, loff_t *off) +{ + s32 ret = 0; + + GTP_DEBUG_FUNC(); + GTP_DEBUG_ARRAY((u8 *)buff, len); + + ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH); + if (ret) { + GTP_ERROR("copy_from_user failed."); + return -EPERM; + } + + + GTP_DEBUG("[Operation]wr: %02X", cmd_head.wr); + GTP_DEBUG("[Flag]flag: %02X, addr: %02X%02X, value: %02X, relation: %02X", cmd_head.flag, cmd_head.flag_addr[0], + cmd_head.flag_addr[1], cmd_head.flag_val, cmd_head.flag_relation); + GTP_DEBUG("[Retry]circle: %d, times: %d, retry: %d, delay: %d", (s32)cmd_head.circle, (s32)cmd_head.times, + (s32)cmd_head.retry, (s32)cmd_head.delay); + GTP_DEBUG("[Data]data len: %d, addr len: %d, addr: %02X%02X, buffer len: %d, data[0]: %02X", (s32)cmd_head.data_len, + (s32)cmd_head.addr_len, cmd_head.addr[0], cmd_head.addr[1], (s32)len, buff[CMD_HEAD_LENGTH]); + + if (1 == cmd_head.wr) { + ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); + if (ret) { + GTP_ERROR("copy_from_user failed."); + return -EPERM; + } + memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], cmd_head.addr, cmd_head.addr_len); + + GTP_DEBUG_ARRAY(cmd_head.data, cmd_head.data_len + cmd_head.addr_len); + GTP_DEBUG_ARRAY((u8 *)&buff[CMD_HEAD_LENGTH], cmd_head.data_len); + + if (1 == cmd_head.flag) { + if (FAIL == comfirm()) { + GTP_ERROR("[WRITE]Comfirm fail!"); + return -EPERM; + } + } else if (2 == cmd_head.flag) { + + } + if (tool_i2c_write(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], + cmd_head.data_len + cmd_head.addr_len) <= 0) { + GTP_ERROR("[WRITE]Write data failed!"); + return -EPERM; + } + + GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], cmd_head.data_len + cmd_head.addr_len); + if (cmd_head.delay) { + msleep(cmd_head.delay); + } + } else if (3 == cmd_head.wr) { + ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); + if (ret) { + GTP_ERROR("copy_from_user failed."); + return -EPERM; + } + memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len); + + register_i2c_func(); + } else if (5 == cmd_head.wr) { + + } else if (7 == cmd_head.wr) { + gtp_irq_disable(i2c_get_clientdata(gt_client)); + + #if GTP_ESD_PROTECT + gtp_esd_switch(gt_client, SWITCH_OFF); + #endif + } else if (9 == cmd_head.wr) { + gtp_irq_enable(i2c_get_clientdata(gt_client)); + + #if GTP_ESD_PROTECT + gtp_esd_switch(gt_client, SWITCH_ON); + #endif + } else if (17 == cmd_head.wr) { + struct goodix_ts_data *ts = i2c_get_clientdata(gt_client); + ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); + if (ret) { + GTP_DEBUG("copy_from_user failed."); + return -EPERM; + } + if (cmd_head.data[GTP_ADDR_LENGTH]) { + GTP_INFO("gtp enter rawdiff."); + ts->gtp_rawdiff_mode = true; + } else { + ts->gtp_rawdiff_mode = false; + GTP_INFO("gtp leave rawdiff."); + } + } +#ifdef UPDATE_FUNCTIONS + else if (11 == cmd_head.wr) { + if (FAIL == gup_enter_update_mode(gt_client)) { + return -EPERM; + } + } else if (13 == cmd_head.wr) { + gup_leave_update_mode(); + } else if (15 == cmd_head.wr) { + show_len = 0; + total_len = 0; + memset(cmd_head.data, 0, cmd_head.data_len + 1); + memcpy(cmd_head.data, &buff[CMD_HEAD_LENGTH], cmd_head.data_len); + + if (FAIL == gup_update_proc((void *)cmd_head.data)) { + return -EPERM; + } + } + +#endif + + return len; +} + +/******************************************************* +Function: + Goodix tool read function. +Input: + standard proc read function param. +Output: + Return read length. +********************************************************/ +ssize_t goodix_tool_read(struct file *file, char __user *page, size_t size, loff_t *ppos) +{ + s32 ret = 0; + + GTP_DEBUG_FUNC(); + + if (*ppos) { + + + + *ppos = 0; + return 0; + } + + if (cmd_head.wr % 2) { + return -EPERM; + } else if (!cmd_head.wr) { + u16 len = 0; + s16 data_len = 0; + u16 loc = 0; + + if (1 == cmd_head.flag) { + if (FAIL == comfirm()) { + GTP_ERROR("[READ]Comfirm fail!"); + return -EPERM; + } + } else if (2 == cmd_head.flag) { + + } + + memcpy(cmd_head.data, cmd_head.addr, cmd_head.addr_len); + + GTP_DEBUG("[CMD HEAD DATA] ADDR:0x%02x%02x.", cmd_head.data[0], cmd_head.data[1]); + GTP_DEBUG("[CMD HEAD ADDR] ADDR:0x%02x%02x.", cmd_head.addr[0], cmd_head.addr[1]); + + if (cmd_head.delay) + msleep(cmd_head.delay); + + data_len = cmd_head.data_len; + + while (data_len > 0) { + if (data_len > DATA_LENGTH) { + len = DATA_LENGTH; + } else { + len = data_len; + } + data_len -= len; + + if (tool_i2c_read(cmd_head.data, len) <= 0) { + GTP_ERROR("[READ]Read data failed!"); + return -EPERM; + } + + + ret = simple_read_from_buffer(&page[loc], size, ppos, &cmd_head.data[GTP_ADDR_LENGTH], len); + if (ret < 0) { + return ret; + } + loc += len; + + GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH], len); + GTP_DEBUG_ARRAY(page, len); + } + return cmd_head.data_len; + } else if (2 == cmd_head.wr) { + ret = simple_read_from_buffer(page, size, ppos, IC_TYPE, sizeof(IC_TYPE)); + return ret; + } else if (4 == cmd_head.wr) { + u8 progress_buf[4]; + progress_buf[0] = show_len >> 8; + progress_buf[1] = show_len & 0xff; + progress_buf[2] = total_len >> 8; + progress_buf[3] = total_len & 0xff; + + ret = simple_read_from_buffer(page, size, ppos, progress_buf, 4); + return ret; + } else if (6 == cmd_head.wr) { + + } else if (8 == cmd_head.wr) { + ret = simple_read_from_buffer(page, size, ppos, GTP_DRIVER_VERSION, strlen(GTP_DRIVER_VERSION)); + return ret; + } + return -EPERM; +} diff --git a/drivers/input/touchscreen/gt9xx_mido/gt9xx.c b/drivers/input/touchscreen/gt9xx_mido/gt9xx.c new file mode 100644 index 0000000000000..d54ce7b8d8ce2 --- /dev/null +++ b/drivers/input/touchscreen/gt9xx_mido/gt9xx.c @@ -0,0 +1,3317 @@ +/* + * Goodix GT9xx touchscreen driver + * + * Copyright (C) 2010 - 2014 Goodix. Ltd. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be a reference + * to you, when you are integrating the GOODiX's CTP IC into your system, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Version: 2.4 + * Release Date: 2014/11/28 + */ + +#include +#include "gt9xx.h" + +#if GTP_ICS_SLOT_REPORT + #include +#endif + + +#define PINCTRL_STATE_ACTIVE "pmx_ts_active" +#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend" +#define PINCTRL_STATE_RELEASE "pmx_ts_release" + +static const char *goodix_ts_name = "goodix-ts"; +static const char *goodix_input_phys = "input/ts"; +static struct workqueue_struct *goodix_wq; +struct i2c_client *i2c_connect_client = NULL; +int gtp_rst_gpio; +int gtp_int_gpio; +u8 config[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH] + = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; +u8 glove0_config1[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH] + = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; +u8 glove0_config2[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH] + = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; +u8 glove1_config1[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH] + = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; +u8 glove1_config2[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH] + = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; + +static char tp_lockdown_info[128]; +static char tp_fw_version[10]; + +static char tp_info_summary[80] = ""; +extern int set_usb_charge_mode_par; + +int gt9xx_id; +int gt9xx_flag; + + + +#if GTP_HAVE_TOUCH_KEY + static const u16 touch_key_array[] = GTP_KEY_TAB; + #define GTP_MAX_KEY_NUM (sizeof(touch_key_array)/sizeof(touch_key_array[0])) + +#if GTP_DEBUG_ON + static const int key_codes[] = {KEY_HOME, KEY_BACK, KEY_MENU, KEY_SEARCH}; + static const char *key_names[] = {"Key_Home", "Key_Back", "Key_Menu", "Key_Search"}; +#endif + +#endif + +static s8 gtp_i2c_test(struct i2c_client *client); +void gtp_reset_guitar(struct i2c_client *client, s32 ms); +s32 gtp_send_cfg(struct i2c_client *client); +void gtp_int_sync(s32 ms); + + + +static ssize_t gt91xx_config_read_proc(struct file *, char __user *, size_t, loff_t *); +static ssize_t gt91xx_config_write_proc(struct file *, const char __user *, size_t, loff_t *); + +static int gtp_lockdown_proc_open (struct inode *inode, struct file *file); +static int gtp_lockdown_proc_show(struct seq_file *file, void *data); +static ssize_t gtp_glove_write_proc(struct file *filp, const char __user *buffer, size_t count, loff_t *off); + +static int gtp_power_switch(struct i2c_client *client, int on); +s32 gtp_i2c_write_no_rst(struct i2c_client *client, u8 *buf, s32 len); + + + +static struct proc_dir_entry *gt91xx_config_proc; +static struct proc_dir_entry *gt91xx_lockdown_proc; +static struct proc_dir_entry *gt91xx_glove_proc; + +static const struct file_operations config_proc_ops = { + .owner = THIS_MODULE, + .read = gt91xx_config_read_proc, + .write = gt91xx_config_write_proc, +}; + +static const struct file_operations lockdown_proc_ops = { + .owner = THIS_MODULE, + .open = gtp_lockdown_proc_open, + + .read = seq_read, +}; + +static const struct file_operations glove_proc_ops = { + .owner = THIS_MODULE, + .write = gtp_glove_write_proc, + + .read = NULL , +}; + + +const u8 cfg_grp0_glove[] = GTP_CFG_GROUP0_GLOVE1; +const u8 cfg_grp0_glove2[] = GTP_CFG_GROUP0_GLOVE2; + + +static int gtp_register_powermanger(struct goodix_ts_data *ts); +static int gtp_unregister_powermanger(struct goodix_ts_data *ts); + + + +#if GTP_CREATE_WR_NODE +extern s32 init_wr_node(struct i2c_client *); +extern void uninit_wr_node(void); +#endif + +#if GTP_AUTO_UPDATE +extern u8 gup_init_update_proc(struct goodix_ts_data *); +#endif + +#if GTP_ESD_PROTECT +static struct delayed_work gtp_esd_check_work; +static struct workqueue_struct *gtp_esd_check_workqueue; +static void gtp_esd_check_func(struct work_struct *); +static s32 gtp_init_ext_watchdog(struct i2c_client *client); +void gtp_esd_switch(struct i2c_client *, s32); +#endif + + +#if defined(CONFIG_GTP_GLOVE_MODE) +int glove_tpd_halt = 0; +static int gtp_glove_mode_status; +struct kobject *goodix_glove_kobj = NULL; +static u8 gtp_glove_config[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH] + = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; +#endif + + + +#if GTP_COMPATIBLE_MODE +extern s32 i2c_read_bytes(struct i2c_client *client, u16 addr, u8 *buf, s32 len); +extern s32 i2c_write_bytes(struct i2c_client *client, u16 addr, u8 *buf, s32 len); +extern s32 gup_clk_calibration(void); +extern s32 gup_fw_download_proc(void *dir, u8 dwn_mode); +extern u8 gup_check_fs_mounted(char *path_name); + +void gtp_recovery_reset(struct i2c_client *client); +static s32 gtp_esd_recovery(struct i2c_client *client); +s32 gtp_fw_startup(struct i2c_client *client); +static s32 gtp_main_clk_proc(struct goodix_ts_data *ts); +static s32 gtp_bak_ref_proc(struct goodix_ts_data *ts, u8 mode); + +#endif + + +#if GTP_GESTURE_WAKEUP +typedef enum +{ + DOZE_DISABLED = 0, + DOZE_ENABLED = 1, + DOZE_WAKEUP = 2, +}DOZE_T; +static DOZE_T doze_status = DOZE_DISABLED; +static s8 gtp_enter_doze(struct goodix_ts_data *ts); +#endif + +#if 1 +int gtp_parse_dt_cfg(struct device *dev, u8 *cfg, int *cfg_len, u8 sid); +#endif + +static int gtp_lockdown_proc_show(struct seq_file *file, void *data) +{ + char temp[40] = {0}; + + sprintf(temp, "%s\n", tp_lockdown_info); + seq_printf(file, "%s\n", temp); + + return 0; +} + +static int gtp_lockdown_proc_open (struct inode *inode, struct file *file) +{ + return single_open(file, gtp_lockdown_proc_show, inode->i_private); +} + + +/******************************************************* +Function: + Read data from the i2c slave device. +Input: + client: i2c device. + buf[0~1]: read start address. + buf[2~len-1]: read data buffer. + len: GTP_ADDR_LENGTH + read bytes count +Output: + numbers of i2c_msgs to transfer: + 2: succeed, otherwise: failed +*********************************************************/ +s32 gtp_i2c_read(struct i2c_client *client, u8 *buf, s32 len) +{ + struct i2c_msg msgs[2]; + s32 ret = -1; + s32 retries = 0; + + GTP_DEBUG_FUNC(); + + msgs[0].flags = !I2C_M_RD; + msgs[0].addr = client->addr; + msgs[0].len = GTP_ADDR_LENGTH; + msgs[0].buf = &buf[0]; + + + msgs[1].flags = I2C_M_RD; + msgs[1].addr = client->addr; + msgs[1].len = len - GTP_ADDR_LENGTH; + msgs[1].buf = &buf[GTP_ADDR_LENGTH]; + + + while (retries < 5) { + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret == 2) + break; + retries++; + } + if ((retries >= 5)) { + #if GTP_COMPATIBLE_MODE + struct goodix_ts_data *ts = i2c_get_clientdata(client); + #endif + + #if GTP_GESTURE_WAKEUP + + if (DOZE_ENABLED == doze_status) { + return ret; + } + #endif + GTP_ERROR("I2C Read: 0x%04X, %d bytes failed, errcode: %d! Process reset.", (((u16)(buf[0] << 8)) | buf[1]), len-2, ret); + #if GTP_COMPATIBLE_MODE + if (CHIP_TYPE_GT9F == ts->chip_type) { + gtp_recovery_reset(client); + } else + #endif + { + gtp_reset_guitar(client, 10); + } + } + return ret; +} + +/******************************************************* +Function: + Write data to the i2c slave device. +Input: + client: i2c device. + buf[0~1]: write start address. + buf[2~len-1]: data buffer + len: GTP_ADDR_LENGTH + write bytes count +Output: + numbers of i2c_msgs to transfer: + 1: succeed, otherwise: failed +*********************************************************/ +s32 gtp_i2c_write(struct i2c_client *client, u8 *buf, s32 len) +{ + struct i2c_msg msg; + s32 ret = -1; + s32 retries = 0; + + GTP_DEBUG_FUNC(); + + msg.flags = !I2C_M_RD; + msg.addr = client->addr; + msg.len = len; + msg.buf = buf; + + + while (retries < 5) { + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret == 1) + break; + retries++; + } + if ((retries >= 5)) { + #if GTP_COMPATIBLE_MODE + struct goodix_ts_data *ts = i2c_get_clientdata(client); + #endif + + #if GTP_GESTURE_WAKEUP + if (DOZE_ENABLED == doze_status) { + return ret; + } + #endif + GTP_ERROR("I2C Write: 0x%04X, %d bytes failed, errcode: %d! Process reset.", (((u16)(buf[0] << 8)) | buf[1]), len-2, ret); + #if GTP_COMPATIBLE_MODE + if (CHIP_TYPE_GT9F == ts->chip_type) { + gtp_recovery_reset(client); + } else + #endif + { + gtp_reset_guitar(client, 10); + } + } + return ret; +} + +/******************************************************* +Function: + i2c read twice, compare the results +Input: + client: i2c device + addr: operate address + rxbuf: read data to store, if compare successful + len: bytes to read +Output: + FAIL: read failed + SUCCESS: read successful +*********************************************************/ +s32 gtp_i2c_read_dbl_check(struct i2c_client *client, u16 addr, u8 *rxbuf, int len) +{ + u8 buf[16] = {0}; + u8 confirm_buf[16] = {0}; + u8 retry = 0; + + while (retry++ < 3) { + memset(buf, 0xAA, 16); + buf[0] = (u8)(addr >> 8); + buf[1] = (u8)(addr & 0xFF); + gtp_i2c_read(client, buf, len + 2); + + memset(confirm_buf, 0xAB, 16); + confirm_buf[0] = (u8)(addr >> 8); + confirm_buf[1] = (u8)(addr & 0xFF); + gtp_i2c_read(client, confirm_buf, len + 2); + + if (!memcmp(buf, confirm_buf, len+2)) { + memcpy(rxbuf, confirm_buf+2, len); + return SUCCESS; + } + } + GTP_ERROR("I2C read 0x%04X, %d bytes, double check failed!", addr, len); + return FAIL; +} + +/******************************************************* +Function: + Send config. +Input: + client: i2c device. +Output: + result of i2c write operation. + 1: succeed, otherwise: failed +*********************************************************/ + +s32 gtp_send_cfg(struct i2c_client *client) +{ + s32 ret = 2; + +#if GTP_DRIVER_SEND_CFG + s32 retry = 0; + struct goodix_ts_data *ts = i2c_get_clientdata(client); + + if (ts->pnl_init_error) { + GTP_INFO("Error occured in init_panel, no config sent"); + return 0; + } + + for (retry = 0; retry < 5; retry++) { + GTP_INFO("before send ,gtp_glove_mode : %d",gtp_glove_mode_status); + #if CONFIG_GTP_GLOVE_MODE + switch(gtp_glove_mode_status) { + case 1: + if (gt9xx_id == 0) { + msleep(100); + ret = gtp_i2c_write(client, glove0_config1 , GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH); + if (ret < 0) + GTP_INFO("gtp write glove1 error"); + else + GTP_INFO("glove1 send success"); + break; + } else { + msleep(100); + ret = gtp_i2c_write(client, glove1_config1 , GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH); + if (ret < 0) + GTP_INFO("gt917 write glove1 error"); + else + GTP_INFO("gt917 glove1 send success"); + break; + } + case 2: + if (gt9xx_id == 0) { + ret = gtp_i2c_write(client, glove0_config2, GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH); + if (ret < 0) + GTP_INFO("gtp write glove2 error"); + else + GTP_INFO("glove2 send success"); + break; + } else { + ret = gtp_i2c_write(client, glove1_config2, GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH); + if (ret < 0) + GTP_INFO("gtp write gt917 glove2 error"); + else + GTP_INFO("gt917 glove2 send success"); + break; + } + case 0: + default: + + ret = gtp_i2c_write(client, config , GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH); + if (ret < 0) + GTP_DEBUG("gtp_glove_mode_status = %d", gtp_glove_mode_status); + else + GTP_INFO("send normal config success"); + break; + } + #endif + #if (!CONFIG_GTP_GLOVE_MODE) + ret = gtp_i2c_write(client, config , GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH); + if (ret < 0) + GTP_DEBUG("gtp write config error."); + GTP_DEBUG("gtp write config success"); + #endif + GTP_DEBUG("after send "); + if(ret > 0) + break; + } +#endif + return ret; +} + +/******************************************************* +Function: + Disable irq function +Input: + ts: goodix i2c_client private data +Output: + None. +*********************************************************/ +void gtp_irq_disable(struct goodix_ts_data *ts) +{ + unsigned long irqflags; + + GTP_DEBUG_FUNC(); + + spin_lock_irqsave(&ts->irq_lock, irqflags); + if (!ts->irq_is_disable) { + ts->irq_is_disable = 1; + disable_irq_nosync(ts->client->irq); + } + spin_unlock_irqrestore(&ts->irq_lock, irqflags); +} + +/******************************************************* +Function: + Enable irq function +Input: + ts: goodix i2c_client private data +Output: + None. +*********************************************************/ +void gtp_irq_enable(struct goodix_ts_data *ts) +{ + unsigned long irqflags = 0; + + GTP_DEBUG_FUNC(); + + spin_lock_irqsave(&ts->irq_lock, irqflags); + if (ts->irq_is_disable) { + enable_irq(ts->client->irq); + ts->irq_is_disable = 0; + } + spin_unlock_irqrestore(&ts->irq_lock, irqflags); +} + +/******************************************************* +Function: + Report touch point event +Input: + ts: goodix i2c_client private data + id: trackId + x: input x coordinate + y: input y coordinate + w: input pressure +Output: + None. +*********************************************************/ +static void gtp_touch_down(struct goodix_ts_data *ts, s32 id, s32 x, s32 y, s32 w) +{ +#if GTP_CHANGE_X2Y + GTP_SWAP(x, y); +#endif + +#if GTP_ICS_SLOT_REPORT + input_mt_slot(ts->input_dev, id); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w); +#else + input_report_key(ts->input_dev, BTN_TOUCH, 1); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id); + input_mt_sync(ts->input_dev); +#endif + + GTP_DEBUG("ID:%d, X:%d, Y:%d, W:%d", id, x, y, w); +} + +/******************************************************* +Function: + Report touch release event +Input: + ts: goodix i2c_client private data +Output: + None. +*********************************************************/ +static void gtp_touch_up(struct goodix_ts_data *ts, s32 id) +{ +#if GTP_ICS_SLOT_REPORT + input_mt_slot(ts->input_dev, id); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1); + GTP_DEBUG("Touch id[%2d] release!", id); +#else + input_report_key(ts->input_dev, BTN_TOUCH, 0); +#endif +} + +#if GTP_WITH_PEN + +static void gtp_pen_init(struct goodix_ts_data *ts) +{ + s32 ret = 0; + + GTP_INFO("Request input device for pen/stylus."); + + ts->pen_dev = input_allocate_device(); + if (ts->pen_dev == NULL) { + GTP_ERROR("Failed to allocate input device for pen/stylus."); + return; + } + + ts->pen_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ; + +#if GTP_ICS_SLOT_REPORT + input_mt_init_slots(ts->pen_dev, 16); +#else + ts->pen_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); +#endif + + set_bit(BTN_TOOL_PEN, ts->pen_dev->keybit); + set_bit(INPUT_PROP_DIRECT, ts->pen_dev->propbit); + + +#if GTP_PEN_HAVE_BUTTON + input_set_capability(ts->pen_dev, EV_KEY, BTN_STYLUS); + input_set_capability(ts->pen_dev, EV_KEY, BTN_STYLUS2); +#endif + + input_set_abs_params(ts->pen_dev, ABS_MT_POSITION_X, 0, ts->abs_x_max, 0, 0); + input_set_abs_params(ts->pen_dev, ABS_MT_POSITION_Y, 0, ts->abs_y_max, 0, 0); + input_set_abs_params(ts->pen_dev, ABS_MT_PRESSURE, 0, 255, 0, 0); + input_set_abs_params(ts->pen_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(ts->pen_dev, ABS_MT_TRACKING_ID, 0, 255, 0, 0); + ts->pen_dev->name = "goodix-pen"; + ts->pen_dev->id.bustype = BUS_I2C; + + ret = input_register_device(ts->pen_dev); + if (ret) { + GTP_ERROR("Register %s input device failed", ts->pen_dev->name); + return; + } +} + +static void gtp_pen_down(s32 x, s32 y, s32 w, s32 id) +{ + struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client); + +#if GTP_CHANGE_X2Y + GTP_SWAP(x, y); +#endif + + input_report_key(ts->pen_dev, BTN_TOOL_PEN, 1); +#if GTP_ICS_SLOT_REPORT + input_mt_slot(ts->pen_dev, id); + input_report_abs(ts->pen_dev, ABS_MT_TRACKING_ID, id); + input_report_abs(ts->pen_dev, ABS_MT_POSITION_X, x); + input_report_abs(ts->pen_dev, ABS_MT_POSITION_Y, y); + input_report_abs(ts->pen_dev, ABS_MT_PRESSURE, w); + input_report_abs(ts->pen_dev, ABS_MT_TOUCH_MAJOR, w); +#else + input_report_key(ts->pen_dev, BTN_TOUCH, 1); + input_report_abs(ts->pen_dev, ABS_MT_POSITION_X, x); + input_report_abs(ts->pen_dev, ABS_MT_POSITION_Y, y); + input_report_abs(ts->pen_dev, ABS_MT_PRESSURE, w); + input_report_abs(ts->pen_dev, ABS_MT_TOUCH_MAJOR, w); + input_report_abs(ts->pen_dev, ABS_MT_TRACKING_ID, id); + input_mt_sync(ts->pen_dev); +#endif + GTP_DEBUG("(%d)(%d, %d)[%d]", id, x, y, w); +} + +static void gtp_pen_up(s32 id) +{ + struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client); + + input_report_key(ts->pen_dev, BTN_TOOL_PEN, 0); + +#if GTP_ICS_SLOT_REPORT + input_mt_slot(ts->pen_dev, id); + input_report_abs(ts->pen_dev, ABS_MT_TRACKING_ID, -1); +#else + + input_report_key(ts->pen_dev, BTN_TOUCH, 0); +#endif + +} +#endif + +/******************************************************* +Function: + Goodix touchscreen work function +Input: + work: work struct of goodix_workqueue +Output: + None. +*********************************************************/ +static void goodix_ts_work_func(struct work_struct *work) +{ + u8 end_cmd[3] = { GTP_READ_COOR_ADDR >> 8, + GTP_READ_COOR_ADDR & 0xFF, 0}; + u8 point_data[2 + 1 + 8 * GTP_MAX_TOUCH + 1] = { + GTP_READ_COOR_ADDR >> 8, + GTP_READ_COOR_ADDR & 0xFF}; + u8 touch_num = 0; + u8 finger = 0; + static u16 pre_touch; + static u8 pre_key; +#if GTP_WITH_PEN + u8 pen_active = 0; + static u8 pre_pen; +#endif + u8 key_value = 0; + u8 *coor_data = NULL; + s32 input_x = 0; + s32 input_y = 0; + s32 input_w = 0; + s32 id = 0; + s32 i = 0; + s32 ret = -1; + struct goodix_ts_data *ts = NULL; + +#if GTP_COMPATIBLE_MODE + u8 rqst_buf[3] = {0x80, 0x43}; +#endif + +#if GTP_GESTURE_WAKEUP + u8 doze_buf[3] = {0x81, 0x4B}; +#endif + + GTP_DEBUG_FUNC(); + ts = container_of(work, struct goodix_ts_data, work); + if (ts->enter_update) { + return; + } +#if GTP_GESTURE_WAKEUP + GTP_DEBUG("doze_status : %d", doze_status); + + if (DOZE_ENABLED == doze_status) { + ret = gtp_i2c_read(i2c_connect_client, doze_buf, 3); + if (ret > 0) { + if ((doze_buf[2] == 'a') || (doze_buf[2] == 'b') || (doze_buf[2] == 'c') || + (doze_buf[2] == 'd') || (doze_buf[2] == 'e') || (doze_buf[2] == 'g') || + (doze_buf[2] == 'h') || (doze_buf[2] == 'm') || (doze_buf[2] == 'o') || + (doze_buf[2] == 'q') || (doze_buf[2] == 's') || (doze_buf[2] == 'v') || + (doze_buf[2] == 'w') || (doze_buf[2] == 'y') || (doze_buf[2] == 'z') || + (doze_buf[2] == 0x5E) /* ^ */ + ) { + if (doze_buf[2] != 0x5E) { + GTP_INFO("Wakeup by gesture(%c), light up the screen!", doze_buf[2]); + } else { + GTP_INFO("Wakeup by gesture(^), light up the screen!"); + } + doze_status = DOZE_WAKEUP; + input_report_key(ts->input_dev, KEY_WAKEUP, 1); + input_sync(ts->input_dev); + input_report_key(ts->input_dev, KEY_WAKEUP, 0); + input_sync(ts->input_dev); + + doze_buf[2] = 0x00; + gtp_i2c_write(i2c_connect_client, doze_buf, 3); + } else if ((doze_buf[2] == 0xAA) || (doze_buf[2] == 0xBB) || + (doze_buf[2] == 0xAB) || (doze_buf[2] == 0xBA)) { + char *direction[4] = {"Right", "Down", "Up", "Left"}; + u8 type = ((doze_buf[2] & 0x0F) - 0x0A) + (((doze_buf[2] >> 4) & 0x0F) - 0x0A) * 2; + + GTP_INFO("%s slide to light up the screen!", direction[type]); + doze_status = DOZE_WAKEUP; + input_report_key(ts->input_dev, KEY_WAKEUP, 1); + input_sync(ts->input_dev); + input_report_key(ts->input_dev, KEY_WAKEUP, 0); + input_sync(ts->input_dev); + + doze_buf[2] = 0x00; + gtp_i2c_write(i2c_connect_client, doze_buf, 3); + } else if (0xCC == doze_buf[2]) { + GTP_INFO("Double click to light up the screen!"); + doze_status = DOZE_WAKEUP; + input_report_key(ts->input_dev, KEY_WAKEUP, 1); + input_sync(ts->input_dev); + input_report_key(ts->input_dev, KEY_WAKEUP, 0); + input_sync(ts->input_dev); + + doze_buf[2] = 0x00; + gtp_i2c_write(i2c_connect_client, doze_buf, 3); + } else { + + doze_buf[2] = 0x00; + gtp_i2c_write(i2c_connect_client, doze_buf, 3); + gtp_enter_doze(ts); + } + } + if (ts->use_irq) { + gtp_irq_enable(ts); + } + return; + } +#endif + + ret = gtp_i2c_read(ts->client, point_data, 12); + if (ret < 0) { + GTP_ERROR("I2C transfer error. errno:%d\n ", ret); + if (ts->use_irq) { + gtp_irq_enable(ts); + } + return; + } + + finger = point_data[GTP_ADDR_LENGTH]; + +#if GTP_COMPATIBLE_MODE + + if ((finger == 0x00) && (CHIP_TYPE_GT9F == ts->chip_type)) { + ret = gtp_i2c_read(ts->client, rqst_buf, 3); + if (ret < 0) { + GTP_ERROR("Read request status error!"); + goto exit_work_func; + } + + switch (rqst_buf[2]) { + case GTP_RQST_CONFIG: + GTP_INFO("Request for config."); + ret = gtp_send_cfg(ts->client); + if (ret < 0) { + GTP_ERROR("Request for config unresponded!"); + } else { + rqst_buf[2] = GTP_RQST_RESPONDED; + gtp_i2c_write(ts->client, rqst_buf, 3); + GTP_INFO("Request for config responded!"); + } + break; + + case GTP_RQST_BAK_REF: + GTP_INFO("Request for backup reference."); + ts->rqst_processing = 1; + ret = gtp_bak_ref_proc(ts, GTP_BAK_REF_SEND); + if (SUCCESS == ret) { + rqst_buf[2] = GTP_RQST_RESPONDED; + gtp_i2c_write(ts->client, rqst_buf, 3); + ts->rqst_processing = 0; + GTP_INFO("Request for backup reference responded!"); + } else { + GTP_ERROR("Requeset for backup reference unresponed!"); + } + break; + + case GTP_RQST_RESET: + GTP_INFO("Request for reset."); + gtp_recovery_reset(ts->client); + break; + + case GTP_RQST_MAIN_CLOCK: + GTP_INFO("Request for main clock."); + ts->rqst_processing = 1; + ret = gtp_main_clk_proc(ts); + if (FAIL == ret) { + GTP_ERROR("Request for main clock unresponded!"); + } else { + GTP_INFO("Request for main clock responded!"); + rqst_buf[2] = GTP_RQST_RESPONDED; + gtp_i2c_write(ts->client, rqst_buf, 3); + ts->rqst_processing = 0; + ts->clk_chk_fs_times = 0; + } + break; + + default: + GTP_INFO("Undefined request: 0x%02X", rqst_buf[2]); + rqst_buf[2] = GTP_RQST_RESPONDED; + gtp_i2c_write(ts->client, rqst_buf, 3); + break; + } + } +#endif + if (finger == 0x00) { + if (ts->use_irq) { + gtp_irq_enable(ts); + } + return; + } + + if ((finger & 0x80) == 0) + goto exit_work_func; + + touch_num = finger & 0x0f; + if (touch_num > GTP_MAX_TOUCH) + goto exit_work_func; + + if (touch_num > 1) { + u8 buf[8 * GTP_MAX_TOUCH] = { (GTP_READ_COOR_ADDR + 10) >> 8, + (GTP_READ_COOR_ADDR + 10) & 0xff }; + + ret = gtp_i2c_read(ts->client, buf, + 2 + 8 * (touch_num - 1)); + memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1)); + } + +#if (GTP_HAVE_TOUCH_KEY || GTP_PEN_HAVE_BUTTON) + key_value = point_data[3 + 8 * touch_num]; + + if (key_value || pre_key) { + #if GTP_PEN_HAVE_BUTTON + if (key_value == 0x40) { + GTP_DEBUG("BTN_STYLUS & BTN_STYLUS2 Down."); + input_report_key(ts->pen_dev, BTN_STYLUS, 1); + input_report_key(ts->pen_dev, BTN_STYLUS2, 1); + pen_active = 1; + } else if (key_value == 0x10) { + GTP_DEBUG("BTN_STYLUS Down, BTN_STYLUS2 Up."); + input_report_key(ts->pen_dev, BTN_STYLUS, 1); + input_report_key(ts->pen_dev, BTN_STYLUS2, 0); + pen_active = 1; + } else if (key_value == 0x20) { + GTP_DEBUG("BTN_STYLUS Up, BTN_STYLUS2 Down."); + input_report_key(ts->pen_dev, BTN_STYLUS, 0); + input_report_key(ts->pen_dev, BTN_STYLUS2, 1); + pen_active = 1; + } else { + GTP_DEBUG("BTN_STYLUS & BTN_STYLUS2 Up."); + input_report_key(ts->pen_dev, BTN_STYLUS, 0); + input_report_key(ts->pen_dev, BTN_STYLUS2, 0); + if ((pre_key == 0x40) || (pre_key == 0x20) || + (pre_key == 0x10) + ) { + pen_active = 1; + } + } + if (pen_active) { + touch_num = 0; + + } + #endif + + #if GTP_HAVE_TOUCH_KEY + if (!pre_touch) { + for (i = 0; i < GTP_MAX_KEY_NUM; i++) { + #if GTP_DEBUG_ON + for (ret = 0; ret < 4; ++ret) { + if (key_codes[ret] == touch_key_array[i]) { + GTP_DEBUG("Key: %s %s", key_names[ret], (key_value & (0x01 << i)) ? "Down" : "Up"); + break; + } + } + #endif + input_report_key(ts->input_dev, touch_key_array[i], key_value & (0x01<pen_dev); + } else +#endif + { + input_sync(ts->input_dev); + } + +exit_work_func: + if (!ts->gtp_rawdiff_mode) { + ret = gtp_i2c_write(ts->client, end_cmd, 3); + if (ret < 0) { + GTP_INFO("I2C write end_cmd error!"); + } + } + if (ts->use_irq) { + gtp_irq_enable(ts); + } +} + +/******************************************************* +Function: + Timer interrupt service routine for polling mode. +Input: + timer: timer struct pointer +Output: + Timer work mode. + HRTIMER_NORESTART: no restart mode +*********************************************************/ +static enum hrtimer_restart goodix_ts_timer_handler(struct hrtimer *timer) +{ + struct goodix_ts_data *ts = container_of(timer, struct goodix_ts_data, timer); + + GTP_DEBUG_FUNC(); + + queue_work(goodix_wq, &ts->work); + hrtimer_start(&ts->timer, ktime_set(0, (GTP_POLL_TIME+6)*1000000), HRTIMER_MODE_REL); + return HRTIMER_NORESTART; +} + +/******************************************************* +Function: + External interrupt service routine for interrupt mode. +Input: + irq: interrupt number. + dev_id: private data pointer +Output: + Handle Result. + IRQ_HANDLED: interrupt handled successfully +*********************************************************/ +static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id) +{ + struct goodix_ts_data *ts = dev_id; + GTP_DEBUG_FUNC(); + + gtp_irq_disable(ts); + + queue_work(goodix_wq, &ts->work); + + return IRQ_HANDLED; +} +/******************************************************* +Function: + Synchronization. +Input: + ms: synchronization time in millisecond. +Output: + None. +*******************************************************/ +void gtp_int_sync(s32 ms) +{ + GTP_GPIO_OUTPUT(gtp_int_gpio, 0); + msleep(ms); + GTP_GPIO_AS_INT(gtp_int_gpio); +} + +/******************************************************* +Function: + Reset chip. +Input: + ms: reset time in millisecond +Output: + None. +*******************************************************/ +void gtp_reset_guitar(struct i2c_client *client, s32 ms) +{ + +#if GTP_COMPATIBLE_MODE + struct goodix_ts_data *ts = i2c_get_clientdata(client); +#endif + + GTP_DEBUG_FUNC(); + GTP_INFO("Guitar reset"); + + GTP_GPIO_OUTPUT(gtp_rst_gpio, 0); + + msleep(ms); + + GTP_GPIO_OUTPUT(gtp_int_gpio, client->addr == 0x14); + + msleep(2); + GTP_GPIO_OUTPUT(gtp_rst_gpio, 1); + + msleep(6); + + + +#if GTP_COMPATIBLE_MODE + if (CHIP_TYPE_GT9F == ts->chip_type) { + return; + } +#endif + + gtp_int_sync(50); + +#if GTP_ESD_PROTECT + gtp_init_ext_watchdog(client); +#endif +} + +#if GTP_GESTURE_WAKEUP +/******************************************************* +Function: + Enter doze mode for sliding wakeup. +Input: + ts: goodix tp private data +Output: + 1: succeed, otherwise failed +*******************************************************/ +static s8 gtp_enter_doze(struct goodix_ts_data *ts) +{ + s8 ret = -1; + s8 retry = 0; + u8 i2c_control_buf[3] = {(u8)(GTP_REG_SLEEP >> 8), (u8)GTP_REG_SLEEP, 8}; + + GTP_DEBUG_FUNC(); + + GTP_DEBUG("Entering gesture mode."); + while (retry++ < 5) { + i2c_control_buf[0] = 0x80; + i2c_control_buf[1] = 0x46; + ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); + if (ret < 0) { + GTP_DEBUG("failed to set doze flag into 0x8046, %d", retry); + continue; + } + i2c_control_buf[0] = 0x80; + i2c_control_buf[1] = 0x40; + ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); + if (ret > 0) { + doze_status = DOZE_ENABLED; + GTP_INFO("Gesture mode enabled."); + return ret; + } + msleep(10); + } + GTP_ERROR("GTP send gesture cmd failed."); + return ret; +} +#endif +/******************************************************* +Function: + Enter sleep mode. +Input: + ts: private data. +Output: + Executive outcomes. + 1: succeed, otherwise failed. +*******************************************************/ +static s8 gtp_enter_sleep(struct goodix_ts_data *ts) +{ + s8 ret = -1; + s8 retry = 0; + u8 i2c_control_buf[3] = {(u8)(GTP_REG_SLEEP >> 8), (u8)GTP_REG_SLEEP, 5}; + +#if GTP_COMPATIBLE_MODE + u8 status_buf[3] = {0x80, 0x44}; +#endif + + GTP_DEBUG_FUNC(); + +#if GTP_COMPATIBLE_MODE + if (CHIP_TYPE_GT9F == ts->chip_type) { + + ret = gtp_i2c_read(ts->client, status_buf, 3); + if (ret < 0) { + GTP_ERROR("failed to get backup-reference status"); + } + + if (status_buf[2] & 0x80) { + ret = gtp_bak_ref_proc(ts, GTP_BAK_REF_STORE); + if (FAIL == ret) { + GTP_ERROR("failed to store bak_ref"); + } + } + } +#endif + + GTP_GPIO_OUTPUT(gtp_int_gpio, 0); + msleep(5); + + while(retry++ < 5) { + ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); + if (ret > 0) { + GTP_INFO("GTP enter sleep!"); + + return ret; + } + msleep(10); + } + GTP_ERROR("GTP send sleep cmd failed."); + return ret; +} + +/******************************************************* +Function: + Wakeup from sleep. +Input: + ts: private data. +Output: + Executive outcomes. + >0: succeed, otherwise: failed. +*******************************************************/ +static s8 gtp_wakeup_sleep(struct goodix_ts_data *ts) +{ + u8 retry = 0; + s8 ret = -1; + + GTP_DEBUG_FUNC(); + +#if GTP_COMPATIBLE_MODE + if (CHIP_TYPE_GT9F == ts->chip_type) { + u8 opr_buf[3] = {0x41, 0x80}; + + GTP_GPIO_OUTPUT(gtp_int_gpio, 1); + msleep(5); + + for (retry = 0; retry < 10; ++retry) { + + opr_buf[2] = 0x0C; + ret = gtp_i2c_write(ts->client, opr_buf, 3); + if (FAIL == ret) { + GTP_ERROR("failed to hold ss51 & dsp!"); + continue; + } + opr_buf[2] = 0x00; + ret = gtp_i2c_read(ts->client, opr_buf, 3); + if (FAIL == ret) { + GTP_ERROR("failed to get ss51 & dsp status!"); + continue; + } + if (0x0C != opr_buf[2]) { + GTP_DEBUG("ss51 & dsp not been hold, %d", retry+1); + continue; + } + GTP_DEBUG("ss51 & dsp confirmed hold"); + + ret = gtp_fw_startup(ts->client); + if (FAIL == ret) { + GTP_ERROR("failed to startup GT9XXF, process recovery"); + gtp_esd_recovery(ts->client); + } + break; + } + if (retry >= 10) { + GTP_ERROR("failed to wakeup, processing esd recovery"); + gtp_esd_recovery(ts->client); + } else { + GTP_INFO("GT9XXF gtp wakeup success"); + } + return ret; + } +#endif + +#if GTP_POWER_CTRL_SLEEP + while (retry++ < 5) { + gtp_reset_guitar(ts->client, 20); + + GTP_INFO("GTP wakeup sleep."); + return 1; + } +#else + while (retry++ < 10) { + #if GTP_GESTURE_WAKEUP + if (DOZE_WAKEUP != doze_status) { + GTP_INFO("Powerkey wakeup."); + } else { + GTP_INFO("Gesture wakeup."); + } + doze_status = DOZE_DISABLED; + gtp_irq_disable(ts); + gtp_reset_guitar(ts->client, 10); + gtp_irq_enable(ts); + + #else + GTP_GPIO_OUTPUT(gtp_int_gpio, 1); + msleep(5); + #endif + + ret = gtp_i2c_test(ts->client); + if (ret > 0) { + GTP_INFO("GTP wakeup sleep."); + + #if (!GTP_GESTURE_WAKEUP) + { + gtp_int_sync(25); + #if GTP_ESD_PROTECT + gtp_init_ext_watchdog(ts->client); + #endif + } + #endif + + return ret; + } + gtp_reset_guitar(ts->client, 20); + } +#endif + + GTP_ERROR("GTP wakeup sleep failed."); + return ret; +} + +/******************************************************* +Function: + Initialize gtp. +Input: + ts: goodix private data +Output: + Executive outcomes. + 0: succeed, otherwise: failed +*******************************************************/ + +static s32 gtp_init_panel(struct goodix_ts_data *ts) +{ + s32 ret = -1; + +#if GTP_DRIVER_SEND_CFG + s32 i = 0; + u8 check_sum = 0; + u8 opr_buf[16] = {0}; + u8 sensor_id = 0; + u8 drv_cfg_version; + u8 flash_cfg_version; + +/* if defined CONFIG_OF, parse config data from dtsi + * else parse config data form header file. + */ +#if CONFIG_GTP_GLOVE_MODE + u8 cfg_info_group1[] = GTP_CFG_GROUP0_GLOVE1; + u8 cfg_info_group2[] = GTP_CFG_GROUP0_GLOVE2; + u8 cfg_info_group3[] = GTP_CFG_GROUP1_GLOVE2; + u8 cfg_info_group4[] = GTP_CFG_GROUP1_GLOVE2; + + u8 *send_glove_cfg_buf[] = {cfg_info_group1, cfg_info_group2, cfg_info_group3, cfg_info_group4}; + u8 glove_cfg_info_len[] = { CFG_GROUP_LEN(cfg_info_group1), CFG_GROUP_LEN(cfg_info_group3)}; + GTP_DEBUG("Glove Config Groups\' Lengths: %d",glove_cfg_info_len[0]); +#endif + +#if GTP_COMPATIBLE_MODE + if (CHIP_TYPE_GT9F == ts->chip_type) { + ts->fw_error = 0; + } else +#endif + { /* check firmware */ + ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1); + if (SUCCESS == ret) { + if (opr_buf[0] != 0xBE) { + ts->fw_error = 1; + GTP_ERROR("Firmware error, no config sent!"); + return -EPERM; + } + } + } + + /* read sensor id */ +#if GTP_COMPATIBLE_MODE + msleep(50); +#endif + ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID, &sensor_id, 1); + if (SUCCESS == ret) { + gt9xx_id = sensor_id; + printk("[GTP]gt9xx_id = %d\n", gt9xx_id); + if (sensor_id >= 0x06) { + GTP_ERROR("Invalid sensor_id(0x%02X), No Config Sent!", sensor_id); + ts->pnl_init_error = 1; + return -EPERM; + } + } else { + GTP_ERROR("Failed to get sensor_id, No config sent!"); + ts->pnl_init_error = 1; + return -EPERM; + } + GTP_INFO("Sensor_ID: %d", sensor_id); + if (sensor_id == 0) { + } + + /* parse config data*/ +#if 1 + GTP_DEBUG("Get config data from device tree."); + ret = gtp_parse_dt_cfg(&ts->client->dev, &config[GTP_ADDR_LENGTH], &ts->gtp_cfg_len, sensor_id); + if (ret < 0) { + GTP_ERROR("Failed to parse config data form device tree."); + ts->pnl_init_error = 1; + return -EPERM; + } +#endif + +#if CONFIG_GTP_GLOVE_MODE + GTP_DEBUG("Get glove config from head file ."); + sensor_id = gt9xx_id; + printk("[GTP] sensor id = gt9xx_id = %d\n", sensor_id); + ts->gtp_cfg_len = glove_cfg_info_len[sensor_id]; + memset(&glove0_config1[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); + memcpy(&glove0_config1[GTP_ADDR_LENGTH], send_glove_cfg_buf[0], ts->gtp_cfg_len); + memset(&glove0_config2[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); + memcpy(&glove0_config2[GTP_ADDR_LENGTH], send_glove_cfg_buf[1], ts->gtp_cfg_len); + memset(&glove1_config1[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); + memcpy(&glove1_config1[GTP_ADDR_LENGTH], send_glove_cfg_buf[2], ts->gtp_cfg_len); + memset(&glove1_config2[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); + memcpy(&glove1_config2[GTP_ADDR_LENGTH], send_glove_cfg_buf[3], ts->gtp_cfg_len); +#endif + + GTP_INFO("Config group%d used,length: %d", sensor_id, ts->gtp_cfg_len); + + if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH) { + GTP_ERROR("Config Group%d is INVALID CONFIG GROUP(Len: %d)! NO Config Sent! You need to check you header file CFG_GROUP section!", sensor_id, ts->gtp_cfg_len); + ts->pnl_init_error = 1; + return -EPERM; + } + +#if GTP_COMPATIBLE_MODE + if (ts->chip_type != CHIP_TYPE_GT9F) +#endif + +#if defined(CONFIG_GTP_GLOVE_MODE) + + + + memset(>p_glove_config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); + + + +#ifdef GTP_CUSTOM_CFG + gtp_glove_config[RESOLUTION_LOC] = (u8) GTP_MAX_WIDTH; + gtp_glove_config[RESOLUTION_LOC + 1] = (u8) (GTP_MAX_WIDTH >> 8); + gtp_glove_config[RESOLUTION_LOC + 2] = (u8) GTP_MAX_HEIGHT; + gtp_glove_config[RESOLUTION_LOC + 3] = (u8) (GTP_MAX_HEIGHT >> 8); + + if (GTP_INT_TRIGGER == 0) /* RISING */ + gtp_glove_config[TRIGGER_LOC] &= 0xfe; + else if (GTP_INT_TRIGGER == 1) /* FALLING */ + gtp_glove_config[TRIGGER_LOC] |= 0x01; +#endif /* END CONFIG_GTP_CUSTOM_CFG */ + if (gtp_glove_config[sensor_id] != ts->gtp_cfg_len) + memset(>p_glove_config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); + + check_sum = 0; + for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++) + check_sum += gtp_glove_config[i]; + + gtp_glove_config[ts->gtp_cfg_len] = (~check_sum) + 1; + +#endif /* END CONFIG_GTP_CHARGER_DETECT */ + + { + ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA, &opr_buf[0], 1); + if (ret == SUCCESS) { + GTP_DEBUG("Config Version: %d, 0x%02X; IC Config Version: %d, 0x%02X", + config[GTP_ADDR_LENGTH], config[GTP_ADDR_LENGTH], opr_buf[0], opr_buf[0]); + + flash_cfg_version = opr_buf[0]; + drv_cfg_version = config[GTP_ADDR_LENGTH]; + + if (flash_cfg_version < 90 && flash_cfg_version > drv_cfg_version) { + config[GTP_ADDR_LENGTH] = 0x00; + } + } else { + GTP_ERROR("Failed to get ic config version!No config sent!"); + return -EPERM; + } + } + +#if GTP_CUSTOM_CFG + config[RESOLUTION_LOC] = (u8)GTP_MAX_WIDTH; + config[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8); + config[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT; + config[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8); + + if (GTP_INT_TRIGGER == 0) { + config[TRIGGER_LOC] &= 0xfe; + } else if (GTP_INT_TRIGGER == 1) { + config[TRIGGER_LOC] |= 0x01; + } +#endif + + check_sum = 0; + for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++) { + check_sum += config[i]; + } + config[ts->gtp_cfg_len] = (~check_sum) + 1; + +#else + + ts->gtp_cfg_len = GTP_CONFIG_MAX_LENGTH; + ret = gtp_i2c_read(ts->client, config, ts->gtp_cfg_len + GTP_ADDR_LENGTH); + if (ret < 0) { + GTP_ERROR("Read Config Failed, Using Default Resolution & INT Trigger!"); + ts->abs_x_max = GTP_MAX_WIDTH; + ts->abs_y_max = GTP_MAX_HEIGHT; + ts->int_trigger_type = GTP_INT_TRIGGER; + } + +#endif + + if ((ts->abs_x_max == 0) && (ts->abs_y_max == 0)) { + ts->abs_x_max = (config[RESOLUTION_LOC + 1] << 8) + config[RESOLUTION_LOC]; + ts->abs_y_max = (config[RESOLUTION_LOC + 3] << 8) + config[RESOLUTION_LOC + 2]; + ts->int_trigger_type = (config[TRIGGER_LOC]) & 0x03; + } + +#if GTP_COMPATIBLE_MODE + if (CHIP_TYPE_GT9F == ts->chip_type) { + u8 sensor_num = 0; + u8 driver_num = 0; + u8 have_key = 0; + + have_key = (config[GTP_REG_HAVE_KEY - GTP_REG_CONFIG_DATA + 2] & 0x01); + + if (1 == ts->is_950) { + driver_num = config[GTP_REG_MATRIX_DRVNUM - GTP_REG_CONFIG_DATA + 2]; + sensor_num = config[GTP_REG_MATRIX_SENNUM - GTP_REG_CONFIG_DATA + 2]; + if (have_key) { + driver_num--; + } + ts->bak_ref_len = (driver_num * (sensor_num - 1) + 2) * 2 * 6; + } else { + driver_num = (config[CFG_LOC_DRVA_NUM] & 0x1F) + (config[CFG_LOC_DRVB_NUM]&0x1F); + if (have_key) { + driver_num--; + } + sensor_num = (config[CFG_LOC_SENS_NUM] & 0x0F) + ((config[CFG_LOC_SENS_NUM] >> 4) & 0x0F); + ts->bak_ref_len = (driver_num * (sensor_num - 2) + 2) * 2; + } + + GTP_INFO("Drv * Sen: %d * %d(key: %d), X_MAX: %d, Y_MAX: %d, TRIGGER: 0x%02x", + driver_num, sensor_num, have_key, ts->abs_x_max, ts->abs_y_max, ts->int_trigger_type); + return 0; + } else +#endif + { +#if GTP_DRIVER_SEND_CFG + ret = gtp_send_cfg(ts->client); + if (ret < 0) { + GTP_ERROR("Send config error."); + } +#if GTP_COMPATIBLE_MODE + if (ts->chip_type != CHIP_TYPE_GT9F) +#endif + { + if (flash_cfg_version < 90 && flash_cfg_version > drv_cfg_version) { + check_sum = 0; + config[GTP_ADDR_LENGTH] = drv_cfg_version; + for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++) { + check_sum += config[i]; + } + config[ts->gtp_cfg_len] = (~check_sum) + 1; + } + } + +#endif + GTP_INFO("X_MAX: %d, Y_MAX: %d, TRIGGER: 0x%02x", ts->abs_x_max, ts->abs_y_max, ts->int_trigger_type); + } + + msleep(10); + return 0; + +} + +static ssize_t gt91xx_config_read_proc(struct file *file, char __user *page, size_t size, loff_t *ppos) +{ + char *ptr = page; + char temp_data[GTP_CONFIG_MAX_LENGTH + 2] = {0x80, 0x47}; + int i; + + if (*ppos) { + return 0; + } + ptr += sprintf(ptr, "==== GT9XX config init value====\n"); + + for (i = 0 ; i < GTP_CONFIG_MAX_LENGTH ; i++) { + ptr += sprintf(ptr, "0x%02X ", config[i + 2]); + + if (i % 8 == 7) + ptr += sprintf(ptr, "\n"); + } + + ptr += sprintf(ptr, "\n"); + + ptr += sprintf(ptr, "==== GT9XX config real value====\n"); + gtp_i2c_read(i2c_connect_client, temp_data, GTP_CONFIG_MAX_LENGTH + 2); + for (i = 0 ; i < GTP_CONFIG_MAX_LENGTH ; i++) { + ptr += sprintf(ptr, "0x%02X ", temp_data[i+2]); + + if (i % 8 == 7) + ptr += sprintf(ptr, "\n"); + } + *ppos += ptr - page; + return (ptr - page); +} + + + +static ssize_t gtp_glove_write_proc(struct file *filp, const char __user *buffer, size_t count, loff_t *off) +{ + char ret = 0; + + if (count > 2) { + GTP_ERROR("size not match:%scount : %zd",buffer,count); + } + if (get_user(ret , buffer)) { + GTP_ERROR("get from user fail\n"); + return -EFAULT; + } + printk("GTP ret : %c\n", ret); + if (ret == '1') { + gtp_glove_mode_status = 1; + GTP_INFO("send glove1"); + gtp_send_cfg(i2c_connect_client); + } else if (ret == '2') { + gtp_glove_mode_status = 2; + GTP_INFO("send glove2"); + gtp_send_cfg(i2c_connect_client); + } else if (ret == '0') { + gtp_glove_mode_status = 0; + GTP_INFO("send glove0"); + gtp_send_cfg(i2c_connect_client); + } + + return count; + +} + +static ssize_t gt91xx_config_write_proc(struct file *filp, const char __user *buffer, size_t count, loff_t *off) +{ + s32 ret = 0; + + GTP_DEBUG("write count %zd\n", count); + + if (count > GTP_CONFIG_MAX_LENGTH) { + GTP_ERROR("size not match [%d:%zd]\n", GTP_CONFIG_MAX_LENGTH, count); + return -EFAULT; + } + + if (copy_from_user(&config[2], buffer, count)) { + GTP_ERROR("copy from user fail\n"); + return -EFAULT; + } + ret = gtp_send_cfg(i2c_connect_client); + + + if (ret < 0) { + GTP_ERROR("send config failed."); + } + + return count; +} +/******************************************************* +Function: + Read chip version. +Input: + client: i2c device + version: buffer to keep ic firmware version +Output: + read operation return. + 2: succeed, otherwise: failed +*******************************************************/ +s32 gtp_read_version(struct i2c_client *client, u16 *version) +{ + s32 ret = -1; + u8 buf[8] = {GTP_REG_VERSION >> 8, GTP_REG_VERSION & 0xff}; + + GTP_DEBUG_FUNC(); + + ret = gtp_i2c_read(client, buf, sizeof(buf)); + if (ret < 0) { + GTP_ERROR("GTP read version failed"); + return ret; + } + + if (version) { + *version = (buf[7] << 8) | buf[6]; + } + if (buf[5] == 0x00) { + GTP_INFO("IC Version: %c%c%c_%02x%02x", buf[2], buf[3], buf[4], buf[7], buf[6]); + } else { + GTP_INFO("IC Version: %c%c%c%c_%02x%02x", buf[2], buf[3], buf[4], buf[5], buf[7], buf[6]); + } + return ret; +} + +s32 gtp_read_Color(struct i2c_client *client) +{ + s32 ret = -1; + u8 buf[10] = {0} ; + u8 esd_buf[5] = {0x42, 0x26}; + char *page = NULL; + char * temp= NULL; + + if (gt9xx_id == 0) { + buf[0] = GTP_REG_COLOR_GT915 >> 8 ; + buf[1] = GTP_REG_COLOR_GT915 & 0xff; + } else { + buf[0] = GTP_REG_COLOR_GT917 >> 8 ; + buf[1] = GTP_REG_COLOR_GT917& 0xff; + } + + + + page = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!page) { + kfree(page); + return -ENOMEM; + } + + temp = page; + GTP_DEBUG_FUNC(); + + ret = gtp_i2c_read(client, buf, sizeof(buf)); + if (ret < 0) { + GTP_ERROR("GTP read color failed"); + return ret; + } + + sprintf(temp, "%02x%02x%02x%02x%02x%02x%02x%02x", buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]); + GTP_INFO("Color : %s\n", temp); + strcpy(tp_lockdown_info, temp); + + ret = gtp_i2c_read(client, buf, sizeof(buf)); + if (ret < 0) { + GTP_ERROR("GTP read color failed"); + return ret; + } + if (((buf[2] != 0x45) || ((buf[3] != 0x37)&&(buf[3] != 0x35))) || ((buf[2] != 0x32) || (buf[3] != 0x37))) { + GTP_ERROR("IC lockdown info error!buf[2] = %02x, buf[3] = %02x, Process reset guitar.", buf[2], buf[3]); + esd_buf[0] = 0x42; + esd_buf[1] = 0x26; + esd_buf[2] = 0x01; + esd_buf[3] = 0x01; + esd_buf[4] = 0x01; + gtp_i2c_write_no_rst(client, esd_buf, 5); + msleep(50); + gtp_power_switch(client, 0); + msleep(20); + gtp_power_switch(client, 1); + msleep(20); + gtp_reset_guitar(client, 50); + msleep(50); + gtp_send_cfg(client); + msleep(20); + + ret = gtp_i2c_read(client, buf, sizeof(buf)); + if (ret < 0) { + GTP_ERROR("GTP read color failed"); + return ret; + } + } + sprintf(temp,"%02x%02x%02x%02x%02x%02x%02x%02x", buf[2], buf[3], buf[4], buf[5], buf[6],buf[7],buf[8],buf[9]); + GTP_INFO("Color : %s\n",temp ); + strcpy(tp_lockdown_info,temp); + return ret; +} + + +s32 gtp_read_FW(struct i2c_client *client) +{ + s32 ret = -1; + u8 buf[4] = {GTP_REG_FW >> 8, GTP_REG_FW & 0xff}; + + char *page = NULL; + char *temp = NULL; + + page = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!page) { + kfree(page); + return -ENOMEM; + } + + temp = page; + GTP_DEBUG_FUNC(); + + ret = gtp_i2c_read(client, buf, sizeof(buf)); + if (ret < 0) { + GTP_ERROR("GTP read color failed"); + return ret; + } + + sprintf(temp, "%02x%02x", buf[3], buf[2]); + GTP_INFO("FW : %s\n", temp); + strcpy(tp_fw_version, temp); + + return ret; +} + +/******************************************************* +Function: + I2c test Function. +Input: + client:i2c client. +Output: + Executive outcomes. + 2: succeed, otherwise failed. +*******************************************************/ +static s8 gtp_i2c_test(struct i2c_client *client) +{ + u8 test[3] = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; + u8 retry = 0; + s8 ret = -1; + + GTP_DEBUG_FUNC(); + + while (retry++ < 5) { + ret = gtp_i2c_read(client, test, 3); + if (ret > 0) { + return ret; + } + GTP_ERROR("GTP i2c test failed time %d.", retry); + msleep(10); + } + return ret; +} + +/******************************************************* +Function: + Request gpio(INT & RST) ports. +Input: + ts: private data. +Output: + Executive outcomes. + >= 0: succeed, < 0: failed +*******************************************************/ +static s8 gtp_request_io_port(struct goodix_ts_data *ts) +{ + s32 ret = 0; + + GTP_DEBUG_FUNC(); + ret = GTP_GPIO_REQUEST(gtp_int_gpio, "GTP INT IRQ"); + if (ret < 0) { + GTP_ERROR("Failed to request GPIO:%d, ERRNO:%d", (s32)gtp_int_gpio, ret); + gpio_free(gtp_int_gpio); + ret = -ENODEV; + return ret; + } else { + GTP_GPIO_AS_INT(gtp_int_gpio); + ts->client->irq = gpio_to_irq(gtp_int_gpio); + } + + ret = GTP_GPIO_REQUEST(gtp_rst_gpio, "GTP RST PORT"); + if (ret < 0) { + GTP_ERROR("Failed to request GPIO:%d, ERRNO:%d", (s32)gtp_rst_gpio, ret); + gpio_free(gtp_rst_gpio); + + ret = -ENODEV; + return ret; + } + + + GTP_GPIO_OUTPUT(gtp_rst_gpio, 0); + + gtp_reset_guitar(ts->client, 20); + + if (ret < 0) { + GTP_GPIO_FREE(gtp_rst_gpio); + GTP_GPIO_FREE(gtp_int_gpio); + } + + return ret; +} + +/******************************************************* +Function: + Request interrupt. +Input: + ts: private data. +Output: + Executive outcomes. + 0: succeed, -1: failed. +*******************************************************/ +static s8 gtp_request_irq(struct goodix_ts_data *ts) +{ + s32 ret = -1; + const u8 irq_table[] = GTP_IRQ_TAB; + + GTP_DEBUG_FUNC(); + GTP_DEBUG("INT trigger type:%x", ts->int_trigger_type); + + ret = request_irq(ts->client->irq, + goodix_ts_irq_handler, + irq_table[ts->int_trigger_type], + ts->client->name, + ts); + if (ret) { + GTP_ERROR("Request IRQ failed!ERRNO:%d.", ret); + GTP_GPIO_AS_INPUT(gtp_int_gpio); + GTP_GPIO_FREE(gtp_int_gpio); + + hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + ts->timer.function = goodix_ts_timer_handler; + hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); + return -EPERM; + } else { + gtp_irq_disable(ts); + ts->use_irq = 1; + return 0; + } +} +#if GTP_GESTURE_WAKEUP +#define WAKEUP_OFF 4 +#define WAKEUP_ON 5 + +static bool gtp_gesture_func_on = true; + +int gtp_gesture_switch(struct input_dev *dev, unsigned int type, unsigned int code, int value) +{ + if (type == EV_SYN && code == SYN_CONFIG) { + if (value == WAKEUP_OFF) { + gtp_gesture_func_on = false; + } else if (value == WAKEUP_ON) { + gtp_gesture_func_on = true; + } + } + return 0; +} + +#endif + +/******************************************************* +Function: + Request input device Function. +Input: + ts:private data. +Output: + Executive outcomes. + 0: succeed, otherwise: failed. +*******************************************************/ +static s8 gtp_request_input_dev(struct goodix_ts_data *ts) +{ + s8 ret = -1; +#if GTP_HAVE_TOUCH_KEY + u8 index = 0; +#endif + + GTP_DEBUG_FUNC(); + + ts->input_dev = input_allocate_device(); + if (ts->input_dev == NULL) { + GTP_ERROR("Failed to allocate input device."); + return -ENOMEM; + } + + ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ; +#if GTP_ICS_SLOT_REPORT + input_mt_init_slots(ts->input_dev, 16); +#else + ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); +#endif + __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); + +#if GTP_HAVE_TOUCH_KEY + for (index = 0; index < GTP_MAX_KEY_NUM; index++) { + input_set_capability(ts->input_dev, EV_KEY, touch_key_array[index]); + } +#endif + +#if GTP_GESTURE_WAKEUP + input_set_capability(ts->input_dev, EV_KEY, KEY_WAKEUP); + + ts->input_dev->event = gtp_gesture_switch; +#endif + +#if GTP_CHANGE_X2Y + GTP_SWAP(ts->abs_x_max, ts->abs_y_max); +#endif + + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, ts->abs_x_max, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, ts->abs_y_max, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, 255, 0, 0); + + ts->input_dev->name = goodix_ts_name; + ts->input_dev->phys = goodix_input_phys; + ts->input_dev->id.bustype = BUS_I2C; + ts->input_dev->id.vendor = 0xDEAD; + ts->input_dev->id.product = 0xBEEF; + ts->input_dev->id.version = 10427; + + ret = input_register_device(ts->input_dev); + if (ret) { + GTP_ERROR("Register %s input device failed", ts->input_dev->name); + return -ENODEV; + } + +#if GTP_WITH_PEN + gtp_pen_init(ts); +#endif + + return 0; +} + + +#if GTP_COMPATIBLE_MODE + +s32 gtp_fw_startup(struct i2c_client *client) +{ + u8 opr_buf[4]; + s32 ret = 0; + + + opr_buf[0] = 0xAA; + ret = i2c_write_bytes(client, 0x8041, opr_buf, 1); + if (ret < 0) { + return FAIL; + } + + + opr_buf[0] = 0x00; + ret = i2c_write_bytes(client, 0x4180, opr_buf, 1); + if (ret < 0) { + return FAIL; + } + + gtp_int_sync(25); + + + ret = i2c_read_bytes(client, 0x8041, opr_buf, 1); + if (ret < 0) { + return FAIL; + } + if (0xAA == opr_buf[0]) { + GTP_ERROR("IC works abnormally,startup failed."); + return FAIL; + } else { + GTP_INFO("IC works normally, Startup success."); + opr_buf[0] = 0xAA; + i2c_write_bytes(client, 0x8041, opr_buf, 1); + return SUCCESS; + } +} + +static s32 gtp_esd_recovery(struct i2c_client *client) +{ + s32 retry = 0; + s32 ret = 0; + struct goodix_ts_data *ts; + + ts = i2c_get_clientdata(client); + + gtp_irq_disable(ts); + + GTP_INFO("GT9XXF esd recovery mode"); + for (retry = 0; retry < 5; retry++) { + ret = gup_fw_download_proc(NULL, GTP_FL_ESD_RECOVERY); + if (FAIL == ret) { + GTP_ERROR("esd recovery failed %d", retry+1); + continue; + } + ret = gtp_fw_startup(ts->client); + if (FAIL == ret) { + GTP_ERROR("GT9XXF start up failed %d", retry+1); + continue; + } + break; + } + gtp_irq_enable(ts); + + if (retry >= 5) { + GTP_ERROR("failed to esd recovery"); + return FAIL; + } + + GTP_INFO("Esd recovery successful"); + return SUCCESS; +} + +void gtp_recovery_reset(struct i2c_client *client) +{ +#if GTP_ESD_PROTECT + gtp_esd_switch(client, SWITCH_OFF); +#endif + GTP_DEBUG_FUNC(); + + gtp_esd_recovery(client); + +#if GTP_ESD_PROTECT + gtp_esd_switch(client, SWITCH_ON); +#endif +} + +static s32 gtp_bak_ref_proc(struct goodix_ts_data *ts, u8 mode) +{ + s32 ret = 0; + s32 i = 0; + s32 j = 0; + u16 ref_sum = 0; + u16 learn_cnt = 0; + u16 chksum = 0; + s32 ref_seg_len = 0; + s32 ref_grps = 0; + struct file *ref_filp = NULL; + u8 *p_bak_ref; + + ret = gup_check_fs_mounted("/data"); + if (FAIL == ret) { + ts->ref_chk_fs_times++; + GTP_DEBUG("Ref check /data times/MAX_TIMES: %d / %d", ts->ref_chk_fs_times, GTP_CHK_FS_MNT_MAX); + if (ts->ref_chk_fs_times < GTP_CHK_FS_MNT_MAX) { + msleep(50); + GTP_INFO("/data not mounted."); + return FAIL; + } + GTP_INFO("check /data mount timeout..."); + } else { + GTP_INFO("/data mounted!!!(%d/%d)", ts->ref_chk_fs_times, GTP_CHK_FS_MNT_MAX); + } + + p_bak_ref = (u8 *)kzalloc(ts->bak_ref_len, GFP_KERNEL); + + if (NULL == p_bak_ref) { + GTP_ERROR("Allocate memory for p_bak_ref failed!"); + return FAIL; + } + + if (ts->is_950) { + ref_seg_len = ts->bak_ref_len / 6; + ref_grps = 6; + } else { + ref_seg_len = ts->bak_ref_len; + ref_grps = 1; + } + ref_filp = filp_open(GTP_BAK_REF_PATH, O_RDWR | O_CREAT, 0666); + if (IS_ERR(ref_filp)) { + GTP_ERROR("Failed to open/create %s.", GTP_BAK_REF_PATH); + if (GTP_BAK_REF_SEND == mode) { + goto bak_ref_default; + } else { + goto bak_ref_exit; + } + } + + switch (mode) { + case GTP_BAK_REF_SEND: + GTP_INFO("Send backup-reference"); + ref_filp->f_op->llseek(ref_filp, 0, SEEK_SET); + ret = ref_filp->f_op->read(ref_filp, (char *)p_bak_ref, ts->bak_ref_len, &ref_filp->f_pos); + if (ret < 0) { + GTP_ERROR("failed to read bak_ref info from file, sending defualt bak_ref"); + goto bak_ref_default; + } + for (j = 0; j < ref_grps; ++j) { + ref_sum = 0; + for (i = 0; i < (ref_seg_len); i += 2) { + ref_sum += (p_bak_ref[i + j * ref_seg_len] << 8) + p_bak_ref[i+1 + j * ref_seg_len]; + } + learn_cnt = (p_bak_ref[j * ref_seg_len + ref_seg_len - 4] << 8) + (p_bak_ref[j * ref_seg_len + ref_seg_len - 3]); + chksum = (p_bak_ref[j * ref_seg_len + ref_seg_len - 2] << 8) + (p_bak_ref[j * ref_seg_len + ref_seg_len - 1]); + GTP_DEBUG("learn count = %d", learn_cnt); + GTP_DEBUG("chksum = %d", chksum); + GTP_DEBUG("ref_sum = 0x%04X", ref_sum & 0xFFFF); + + if (1 != ref_sum) { + GTP_INFO("wrong chksum for bak_ref, reset to 0x00 bak_ref"); + memset(&p_bak_ref[j * ref_seg_len], 0, ref_seg_len); + p_bak_ref[ref_seg_len + j * ref_seg_len - 1] = 0x01; + } else { + if (j == (ref_grps - 1)) { + GTP_INFO("backup-reference data in %s used", GTP_BAK_REF_PATH); + } + } + } + ret = i2c_write_bytes(ts->client, GTP_REG_BAK_REF, p_bak_ref, ts->bak_ref_len); + if (FAIL == ret) { + GTP_ERROR("failed to send bak_ref because of iic comm error"); + goto bak_ref_exit; + } + break; + + case GTP_BAK_REF_STORE: + GTP_INFO("Store backup-reference"); + ret = i2c_read_bytes(ts->client, GTP_REG_BAK_REF, p_bak_ref, ts->bak_ref_len); + if (ret < 0) { + GTP_ERROR("failed to read bak_ref info, sending default back-reference"); + goto bak_ref_default; + } + ref_filp->f_op->llseek(ref_filp, 0, SEEK_SET); + ref_filp->f_op->write(ref_filp, (char *)p_bak_ref, ts->bak_ref_len, &ref_filp->f_pos); + break; + + default: + GTP_ERROR("invalid backup-reference request"); + break; + } + ret = SUCCESS; + goto bak_ref_exit; + +bak_ref_default: + + for (j = 0; j < ref_grps; ++j) { + memset(&p_bak_ref[j * ref_seg_len], 0, ref_seg_len); + p_bak_ref[j * ref_seg_len + ref_seg_len - 1] = 0x01; + } + ret = i2c_write_bytes(ts->client, GTP_REG_BAK_REF, p_bak_ref, ts->bak_ref_len); + if (!IS_ERR(ref_filp)) { + GTP_INFO("write backup-reference data into %s", GTP_BAK_REF_PATH); + ref_filp->f_op->llseek(ref_filp, 0, SEEK_SET); + ref_filp->f_op->write(ref_filp, (char *)p_bak_ref, ts->bak_ref_len, &ref_filp->f_pos); + } + if (ret == FAIL) { + GTP_ERROR("failed to load the default backup reference"); + } + +bak_ref_exit: + + if (p_bak_ref) { + kfree(p_bak_ref); + } + if (ref_filp && !IS_ERR(ref_filp)) { + filp_close(ref_filp, NULL); + } + return ret; +} + + +static s32 gtp_verify_main_clk(u8 *p_main_clk) +{ + u8 chksum = 0; + u8 main_clock = p_main_clk[0]; + s32 i = 0; + + if (main_clock < 50 || main_clock > 120) { + return FAIL; + } + + for (i = 0; i < 5; ++i) { + if (main_clock != p_main_clk[i]) { + return FAIL; + } + chksum += p_main_clk[i]; + } + chksum += p_main_clk[5]; + if ((chksum) == 0) { + return SUCCESS; + } else { + return FAIL; + } +} + +static s32 gtp_main_clk_proc(struct goodix_ts_data *ts) +{ + s32 ret = 0; + s32 i = 0; + s32 clk_chksum = 0; + struct file *clk_filp = NULL; + u8 p_main_clk[6] = {0}; + + ret = gup_check_fs_mounted("/data"); + if (FAIL == ret) { + ts->clk_chk_fs_times++; + GTP_DEBUG("Clock check /data times/MAX_TIMES: %d / %d", ts->clk_chk_fs_times, GTP_CHK_FS_MNT_MAX); + if (ts->clk_chk_fs_times < GTP_CHK_FS_MNT_MAX) { + msleep(50); + GTP_INFO("/data not mounted."); + return FAIL; + } + GTP_INFO("Check /data mount timeout!"); + } else { + GTP_INFO("/data mounted!!!(%d/%d)", ts->clk_chk_fs_times, GTP_CHK_FS_MNT_MAX); + } + + clk_filp = filp_open(GTP_MAIN_CLK_PATH, O_RDWR | O_CREAT, 0666); + if (IS_ERR(clk_filp)) { + GTP_ERROR("%s is unavailable, calculate main clock", GTP_MAIN_CLK_PATH); + } else { + clk_filp->f_op->llseek(clk_filp, 0, SEEK_SET); + clk_filp->f_op->read(clk_filp, (char *)p_main_clk, 6, &clk_filp->f_pos); + + ret = gtp_verify_main_clk(p_main_clk); + if (FAIL == ret) { + + GTP_ERROR("main clock data in %s is wrong, recalculate main clock", GTP_MAIN_CLK_PATH); + } else { + GTP_INFO("main clock data in %s used, main clock freq: %d", GTP_MAIN_CLK_PATH, p_main_clk[0]); + filp_close(clk_filp, NULL); + goto update_main_clk; + } + } + +#if GTP_ESD_PROTECT + gtp_esd_switch(ts->client, SWITCH_OFF); +#endif + ret = gup_clk_calibration(); + gtp_esd_recovery(ts->client); + +#if GTP_ESD_PROTECT + gtp_esd_switch(ts->client, SWITCH_ON); +#endif + + GTP_INFO("calibrate main clock: %d", ret); + if (ret < 50 || ret > 120) { + GTP_ERROR("wrong main clock: %d", ret); + goto exit_main_clk; + } + + + for (i = 0; i < 5; ++i) { + p_main_clk[i] = ret; + clk_chksum += p_main_clk[i]; + } + p_main_clk[5] = 0 - clk_chksum; + + if (!IS_ERR(clk_filp)) { + GTP_DEBUG("write main clock data into %s", GTP_MAIN_CLK_PATH); + clk_filp->f_op->llseek(clk_filp, 0, SEEK_SET); + clk_filp->f_op->write(clk_filp, (char *)p_main_clk, 6, &clk_filp->f_pos); + filp_close(clk_filp, NULL); + } + +update_main_clk: + ret = i2c_write_bytes(ts->client, GTP_REG_MAIN_CLK, p_main_clk, 6); + if (FAIL == ret) { + GTP_ERROR("update main clock failed!"); + return FAIL; + } + return SUCCESS; + +exit_main_clk: + if (!IS_ERR(clk_filp)) { + filp_close(clk_filp, NULL); + } + return FAIL; +} + + +s32 gtp_gt9xxf_init(struct i2c_client *client) +{ + s32 ret = 0; + + ret = gup_fw_download_proc(NULL, GTP_FL_FW_BURN); + if (FAIL == ret) { + return FAIL; + } + + ret = gtp_fw_startup(client); + if (FAIL == ret) { + return FAIL; + } + return SUCCESS; +} + +void gtp_get_chip_type(struct goodix_ts_data *ts) +{ + u8 opr_buf[10] = {0x00}; + s32 ret = 0; + + msleep(10); + + ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CHIP_TYPE, opr_buf, 10); + + if (FAIL == ret) { + GTP_ERROR("Failed to get chip-type, set chip type default: GOODIX_GT9"); + ts->chip_type = CHIP_TYPE_GT9; + return; + } + + if (!memcmp(opr_buf, "GOODIX_GT9", 10)) { + ts->chip_type = CHIP_TYPE_GT9; + } else { + ts->chip_type = CHIP_TYPE_GT9F; + } + GTP_INFO("Chip Type: %s", (ts->chip_type == CHIP_TYPE_GT9) ? "GOODIX_GT9" : "GOODIX_GT9F"); +} +#endif + +/* + * Devices Tree support, +*/ +#if 1 +/** + * gtp_parse_dt - parse platform infomation form devices tree. + */ +static void gtp_parse_dt(struct device *dev) +{ + struct device_node *np = dev->of_node; + + gtp_int_gpio = of_get_named_gpio(np, "goodix,irq-gpio", 0); + gtp_rst_gpio = of_get_named_gpio(np, "goodix,rst-gpio", 0); + +} + +/** + * gtp_parse_dt_cfg - parse config data from devices tree. + * @dev: device that this driver attached. + * @cfg: pointer of the config array. + * @cfg_len: pointer of the config length. + * @sid: sensor id. + * Return: 0-succeed, -1-faileds + */ +int gtp_parse_dt_cfg(struct device *dev, u8 *cfg, int *cfg_len, u8 sid) +{ + struct device_node *np = dev->of_node; + struct property *prop; + char cfg_name[18]; + + snprintf(cfg_name, sizeof(cfg_name), "goodix,cfg-group%d", sid); + prop = of_find_property(np, cfg_name, cfg_len); + if (!prop || !prop->value || *cfg_len == 0 || *cfg_len > GTP_CONFIG_MAX_LENGTH) { + return -EPERM;/* failed */ + } else { + memcpy(cfg, prop->value, *cfg_len); + return 0; + } +} + +static int gt9xx_ts_pinctrl_init(struct goodix_ts_data *gt9xx_data) +{ + int retval; + + /* Get pinctrl if target uses pinctrl */ + gt9xx_data->ts_pinctrl = devm_pinctrl_get(&(gt9xx_data->client->dev)); + if (IS_ERR_OR_NULL(gt9xx_data->ts_pinctrl)) { + retval = PTR_ERR(gt9xx_data->ts_pinctrl); + dev_dbg(>9xx_data->client->dev, + "Target does not use pinctrl %d\n", retval); + goto err_pinctrl_get; + } + + gt9xx_data->pinctrl_state_active + = pinctrl_lookup_state(gt9xx_data->ts_pinctrl, + PINCTRL_STATE_ACTIVE); + if (IS_ERR_OR_NULL(gt9xx_data->pinctrl_state_active)) { + retval = PTR_ERR(gt9xx_data->pinctrl_state_active); + dev_err(>9xx_data->client->dev, + "Can not lookup %s pinstate %d\n", + PINCTRL_STATE_ACTIVE, retval); + goto err_pinctrl_lookup; + } + + gt9xx_data->pinctrl_state_suspend + = pinctrl_lookup_state(gt9xx_data->ts_pinctrl, + PINCTRL_STATE_SUSPEND); + if (IS_ERR_OR_NULL(gt9xx_data->pinctrl_state_suspend)) { + retval = PTR_ERR(gt9xx_data->pinctrl_state_suspend); + dev_err(>9xx_data->client->dev, + "Can not lookup %s pinstate %d\n", + PINCTRL_STATE_SUSPEND, retval); + goto err_pinctrl_lookup; + } + + gt9xx_data->pinctrl_state_release + = pinctrl_lookup_state(gt9xx_data->ts_pinctrl, + PINCTRL_STATE_RELEASE); + if (IS_ERR_OR_NULL(gt9xx_data->pinctrl_state_release)) { + retval = PTR_ERR(gt9xx_data->pinctrl_state_release); + dev_dbg(>9xx_data->client->dev, + "Can not lookup %s pinstate %d\n", + PINCTRL_STATE_RELEASE, retval); + } + + return 0; + +err_pinctrl_lookup: + devm_pinctrl_put(gt9xx_data->ts_pinctrl); +err_pinctrl_get: + gt9xx_data->ts_pinctrl = NULL; + return retval; +} + +/** + * gtp_power_switch - power switch . + * @on: 1-switch on, 0-switch off. + * return: 0-succeed, -1-faileds + */ +static int gtp_power_switch(struct i2c_client *client, int on) +{ + static struct regulator *vdd_ana; + static struct regulator *vcc_i2c; + int ret; + + if (!vdd_ana) { + vdd_ana = regulator_get(&client->dev, "vdd_ana"); + if (IS_ERR(vdd_ana)) { + GTP_ERROR("regulator get of vdd_ana failed"); + ret = PTR_ERR(vdd_ana); + vdd_ana = NULL; + return ret; + } + } + + if (!vcc_i2c) { + vcc_i2c = regulator_get(&client->dev, "vcc_i2c"); + if (IS_ERR(vcc_i2c)) { + GTP_ERROR("regulator get of vcc_i2c failed"); + ret = PTR_ERR(vcc_i2c); + vcc_i2c = NULL; + goto ERR_GET_VCC; + } + } + + if (on) { + GTP_DEBUG("GTP power on."); + ret = regulator_enable(vdd_ana); + udelay(2); + ret = regulator_enable(vcc_i2c); + } else { + GTP_DEBUG("GTP power off."); + ret = regulator_disable(vcc_i2c); + udelay(2); + ret = regulator_disable(vdd_ana); + } + return ret; + +ERR_GET_VCC: + regulator_put(vdd_ana); + return ret; +} +#endif + +void gtp_usb_plugin(bool mode) +{ + s8 ret = -1; + s8 retry = 0; + u8 i2c_control_buf[3] = {(u8)(GTP_REG_SLEEP >> 8), (u8)GTP_REG_SLEEP, 7}; + + struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client); + + if (mode) { + i2c_control_buf[2] = 6; + GTP_INFO("Enter %s, usb in", __func__); + } else { + i2c_control_buf[2] = 7; + GTP_INFO("Enter %s, usb off", __func__); + } + while (retry++ < 5) { + ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); + if (ret > 0) { + GTP_INFO("GTP enter Charge mode!"); + } + msleep(10); + } + GTP_ERROR("GTP send Charge cmd failed."); +} + + +/******************************************************* +Function: + I2c probe. +Input: + client: i2c device struct. + id: device id. +Output: + Executive outcomes. + 0: succeed. +*******************************************************/ +static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + s32 ret = -1; + struct goodix_ts_data *ts; + u16 version_info; + u8 sensor_id = 0; + GTP_DEBUG_FUNC(); + + GTP_INFO("GTP Driver Version: %s", GTP_DRIVER_VERSION); + GTP_INFO("GTP I2C Address: 0x%02x", client->addr); + + i2c_connect_client = client; + gt9xx_flag = 1; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + GTP_ERROR("I2C check functionality failed."); + return -ENODEV; + } + ts = kzalloc(sizeof(*ts), GFP_KERNEL); + if (ts == NULL) { + GTP_ERROR("Alloc GFP_KERNEL memory failed."); + return -ENOMEM; + } + + if (client->dev.of_node) { + gtp_parse_dt(&client->dev); + } + ret = gtp_power_switch(client, 1); + if (ret) { + GTP_ERROR("GTP power on failed."); + return -EINVAL; + } + + INIT_WORK(&ts->work, goodix_ts_work_func); + ts->client = client; + spin_lock_init(&ts->irq_lock); + +#if GTP_ESD_PROTECT + ts->clk_tick_cnt = 2 * HZ; + GTP_DEBUG("Clock ticks for an esd cycle: %d", ts->clk_tick_cnt); + spin_lock_init(&ts->esd_lock); +#endif + i2c_set_clientdata(client, ts); + ts->gtp_rawdiff_mode = 0; + ret = gtp_request_io_port(ts); + GTP_INFO("gtp_request_io_port : ret = %d\n",ret); + if (ret < 0) { + GTP_ERROR("GTP request IO port failed."); + gt9xx_flag = 0; + if (goodix_wq) { + GTP_INFO("destroy_workqueue : goodix_wq"); + destroy_workqueue(goodix_wq); + } + #if GTP_ESD_PROTECT + if (gtp_esd_check_workqueue) { + GTP_INFO("destroy_workqueue : gtp_esd_check_workqueue"); + destroy_workqueue(gtp_esd_check_workqueue); + } + #endif + kfree(ts); + return ret; + } + +#if GTP_COMPATIBLE_MODE + gtp_get_chip_type(ts); + if (CHIP_TYPE_GT9F == ts->chip_type) { + ret = gtp_gt9xxf_init(ts->client); + if (FAIL == ret) { + GTP_INFO("Failed to init GT9XXF."); + } + } +#endif + + ret = gtp_i2c_test(client); + if (ret < 0) { + GTP_ERROR("I2C communication ERROR!"); + gt9xx_flag = 0; + if (goodix_wq) { + GTP_INFO("destroy_workqueue : goodix_wq"); + destroy_workqueue(goodix_wq); + } + #if GTP_ESD_PROTECT + if (gtp_esd_check_workqueue) { + GTP_INFO("destroy_workqueue : gtp_esd_check_workqueue"); + destroy_workqueue(gtp_esd_check_workqueue); + } + #endif + kfree(ts); + return -EINVAL; + } + + ret = gtp_read_version(client, &version_info); + if (ret < 0) { + GTP_ERROR("Read version failed."); + } + + ret = gt9xx_ts_pinctrl_init(ts); + if (!ret && ts->ts_pinctrl) { + /* + * Pinctrl handle is optional. If pinctrl handle is found + * let pins to be configured in active state. If not + * found continue further without error. + */ + ret = pinctrl_select_state(ts->ts_pinctrl, + ts->pinctrl_state_active); + if (ret < 0) { + dev_err(&client->dev, + "failed to select pin to active state"); + } + } + ret = gtp_init_panel(ts); + if (ret < 0) { + GTP_ERROR("GTP init panel failed."); + ts->abs_x_max = GTP_MAX_WIDTH; + ts->abs_y_max = GTP_MAX_HEIGHT; + ts->int_trigger_type = GTP_INT_TRIGGER; + } + + ret = gtp_read_Color(client); + if (ret < 0) { + GTP_ERROR("Read color failed."); + } + set_usb_charge_mode_par = 3; + printk("set_usb_charge_mode_par = %d\n",set_usb_charge_mode_par); + gt91xx_config_proc = proc_create(GT91XX_CONFIG_PROC_FILE, 0666, NULL, &config_proc_ops); + if (gt91xx_config_proc == NULL) { + GTP_ERROR("create_proc_entry %s failed\n", GT91XX_CONFIG_PROC_FILE); + } else { + GTP_INFO("create proc entry %s success", GT91XX_CONFIG_PROC_FILE); + } + + gt91xx_lockdown_proc = proc_create(GT91XX_Color_PROC_FILE, 0666, NULL, &lockdown_proc_ops); + if (gt91xx_lockdown_proc == NULL) { + GTP_ERROR("create_proc_entry %s failed\n", GT91XX_Color_PROC_FILE); + } else { + GTP_INFO("create proc entry %s success", GT91XX_Color_PROC_FILE); + } + + gt91xx_glove_proc = proc_create(GT91XX_Glove_PROC_FILE, 0666, NULL, &glove_proc_ops); + if (gt91xx_glove_proc == NULL) { + GTP_ERROR("create_glove_proc %s failed\n", GT91XX_Glove_PROC_FILE); + } else { + GTP_INFO("create_glove_proc %s success", GT91XX_Glove_PROC_FILE); + } + + +#if GTP_ESD_PROTECT + gtp_esd_switch(client, SWITCH_ON); +#endif + +#if GTP_AUTO_UPDATE + ret = gup_init_update_proc(ts); + if (ret < 0) { + GTP_ERROR("Create update thread error."); + } +#endif + + ret = gtp_request_input_dev(ts); + if (ret < 0) { + GTP_ERROR("GTP request input dev failed"); + } + + ret = gtp_request_irq(ts); + if (ret < 0) { + GTP_INFO("GTP works in polling mode."); + } else { + GTP_INFO("GTP works in interrupt mode."); + } + + if (ts->use_irq) { + gtp_irq_enable(ts); +#if GTP_GESTURE_WAKEUP + enable_irq_wake(client->irq); +#endif + } + + /* register suspend and resume fucntion*/ + gtp_register_powermanger(ts); + +if (gtp_read_FW(client) < 0) + printk("read FW fail\n"); +sensor_id = gt9xx_id; +if (sensor_id == 0) { + strcpy(tp_info_summary, "[Vendor]Lansi, [IC]GT915, [FW]Ver"); + } +if (sensor_id == 1) { + strcpy(tp_info_summary, "[Vendor]Lansi, [IC]GT917, [FW]Ver"); +} + strcat(tp_info_summary,tp_fw_version); + strcat(tp_info_summary,"\0"); +#if GTP_CREATE_WR_NODE + init_wr_node(client); +#endif + GTP_INFO("wmy goodix_ts_probe return okay\n"); + return 0; +} + +/******************************************************* +Function: + Goodix touchscreen driver release function. +Input: + client: i2c device struct. +Output: + Executive outcomes. 0---succeed. +*******************************************************/ +static int goodix_ts_remove(struct i2c_client *client) +{ + struct goodix_ts_data *ts = i2c_get_clientdata(client); + + GTP_DEBUG_FUNC(); + + gtp_unregister_powermanger(ts); + +#if GTP_CREATE_WR_NODE + uninit_wr_node(); +#endif + +#if GTP_ESD_PROTECT + destroy_workqueue(gtp_esd_check_workqueue); +#endif + + if (ts) { + if (ts->use_irq) { + GTP_GPIO_AS_INPUT(gtp_int_gpio); + GTP_GPIO_FREE(gtp_int_gpio); + free_irq(client->irq, ts); + } else { + hrtimer_cancel(&ts->timer); + } + } + + GTP_INFO("GTP driver removing..."); + i2c_set_clientdata(client, NULL); + input_unregister_device(ts->input_dev); + kfree(ts); + + return 0; +} + + +/******************************************************* +Function: + Early suspend function. +Input: + h: early_suspend struct. +Output: + None. +*******************************************************/ +static void goodix_ts_suspend(struct goodix_ts_data *ts) +{ + s8 ret = -1; + + GTP_DEBUG_FUNC(); + if (ts->enter_update) { + return; + } + GTP_INFO("System suspend."); + + ts->gtp_is_suspend = 1; +#if GTP_ESD_PROTECT + gtp_esd_switch(ts->client, SWITCH_OFF); +#endif + printk("gtp_gesture_func_on: %d\n", gtp_gesture_func_on); +#if GTP_GESTURE_WAKEUP + #if defined(CONFIG_GTP_GLOVE_MODE) + if (gtp_glove_mode_status) { + gtp_irq_disable(ts); + ret = gtp_enter_sleep(ts); + if (ret < 0) + GTP_ERROR(" GTP enter suspend failed."); + } else if (gtp_gesture_func_on) { + ret = gtp_enter_doze(ts); + } + #else + if (gtp_gesture_func_on) + ret = gtp_enter_doze(ts); +#endif +#else + if (ts->use_irq) { + gtp_irq_disable(ts); + } else { + hrtimer_cancel(&ts->timer); + } + ret = gtp_enter_sleep(ts); +#endif + if (ret < 0) { + GTP_ERROR("GTP early suspend failed."); + } + + +#if defined(CONFIG_GTP_GLOVE_MODE) + glove_tpd_halt = 1; +#endif + msleep(58); +} + +/******************************************************* +Function: + Late resume function. +Input: + h: early_suspend struct. +Output: + None. +*******************************************************/ +static void goodix_ts_resume(struct goodix_ts_data *ts) +{ + s8 ret = -1; + GTP_DEBUG_FUNC(); + if (ts->enter_update) { + return; + } + GTP_INFO("System resume."); + + ret = gtp_wakeup_sleep(ts); +#if GTP_GESTURE_WAKEUP + doze_status = DOZE_DISABLED; +#endif + + if (ret < 0) { + GTP_ERROR("GTP later resume failed."); + } +#if (GTP_COMPATIBLE_MODE) + if (CHIP_TYPE_GT9F == ts->chip_type) { + + } else +#endif + { + gtp_send_cfg(ts->client); + } + + if (ts->use_irq) { + gtp_irq_enable(ts); + } else { + hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); + } + + ts->gtp_is_suspend = 0; +#if GTP_ESD_PROTECT + gtp_esd_switch(ts->client, SWITCH_ON); +#endif + +} + + +#if defined(CONFIG_FB) +/* frame buffer notifier block control the suspend/resume procedure */ +static int gtp_fb_notifier_callback(struct notifier_block *noti, unsigned long event, void *data) +{ + struct fb_event *ev_data = data; + struct goodix_ts_data *ts = container_of(noti, struct goodix_ts_data, notifier); + int *blank; + + if (ev_data && ev_data->data && event == FB_EVENT_BLANK && ts) { + blank = ev_data->data; + if (*blank == FB_BLANK_UNBLANK) { + GTP_DEBUG("Resume by fb notifier."); + goodix_ts_resume(ts); + + } else if (*blank == FB_BLANK_POWERDOWN) { + GTP_DEBUG("Suspend by fb notifier."); + goodix_ts_suspend(ts); + } + } + + return 0; +} +#elif defined(CONFIG_PM) +/* bus control the suspend/resume procedure */ +static int gtp_pm_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct goodix_ts_data *ts = i2c_get_clientdata(client); + + if (ts) { + GTP_DEBUG("Suspend by i2c pm."); + goodix_ts_suspend(ts); + } + + return 0; +} +static int gtp_pm_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct goodix_ts_data *ts = i2c_get_clientdata(client); + + if (ts) { + GTP_DEBUG("Resume by i2c pm."); + goodix_ts_resume(ts); + } + + return 0; +} + +static struct dev_pm_ops gtp_pm_ops = { + .suspend = gtp_pm_suspend, + .resume = gtp_pm_resume, +}; + +#elif defined(CONFIG_HAS_EARLYSUSPEND) +/* earlysuspend module the suspend/resume procedure */ +static void gtp_early_suspend(struct early_suspend *h) +{ + struct goodix_ts_data *ts = container_of(h, struct goodix_ts_data, early_suspend); + + if (ts) { + GTP_DEBUG("Suspend by earlysuspend module."); + goodix_ts_suspend(ts); + } +} +static void gtp_early_resume(struct early_suspend *h) +{ + struct goodix_ts_data *ts = container_of(h, struct goodix_ts_data, early_suspend); + + if (ts) { + GTP_DEBUG("Resume by earlysuspend module."); + goodix_ts_resume(ts); + } +} +#endif + +static int gtp_register_powermanger(struct goodix_ts_data *ts) +{ +#if defined(CONFIG_FB) + ts->notifier.notifier_call = gtp_fb_notifier_callback; + fb_register_client(&ts->notifier); + +#elif defined(CONFIG_HAS_EARLYSUSPEND) + ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + ts->early_suspend.suspend = goodix_ts_early_suspend; + ts->early_suspend.resume = goodix_ts_late_resume; + register_early_suspend(&ts->early_suspend); +#endif + + return 0; +} + +static int gtp_unregister_powermanger(struct goodix_ts_data *ts) +{ +#if defined(CONFIG_FB) + fb_unregister_client(&ts->notifier); + +#elif defined(CONFIG_HAS_EARLYSUSPEND) + unregister_early_suspend(&ts->early_suspend); +#endif + return 0; +} + +/* end */ + +#if GTP_ESD_PROTECT +s32 gtp_i2c_read_no_rst(struct i2c_client *client, u8 *buf, s32 len) +{ + struct i2c_msg msgs[2]; + s32 ret = -1; + s32 retries = 0; + + GTP_DEBUG_FUNC(); + + msgs[0].flags = !I2C_M_RD; + msgs[0].addr = client->addr; + msgs[0].len = GTP_ADDR_LENGTH; + msgs[0].buf = &buf[0]; + + + msgs[1].flags = I2C_M_RD; + msgs[1].addr = client->addr; + msgs[1].len = len - GTP_ADDR_LENGTH; + msgs[1].buf = &buf[GTP_ADDR_LENGTH]; + + + while (retries < 5) { + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret == 2) + break; + retries++; + } + if ((retries >= 5)) { + GTP_ERROR("I2C Read: 0x%04X, %d bytes failed, errcode: %d!", (((u16)(buf[0] << 8)) | buf[1]), len-2, ret); + } + return ret; +} + +s32 gtp_i2c_write_no_rst(struct i2c_client *client, u8 *buf, s32 len) +{ + struct i2c_msg msg; + s32 ret = -1; + s32 retries = 0; + + GTP_DEBUG_FUNC(); + + msg.flags = !I2C_M_RD; + msg.addr = client->addr; + msg.len = len; + msg.buf = buf; + + + while (retries < 5) { + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret == 1) + break; + retries++; + } + if ((retries >= 5)) { + GTP_ERROR("I2C Write: 0x%04X, %d bytes failed, errcode: %d!", (((u16)(buf[0] << 8)) | buf[1]), len-2, ret); + } + return ret; +} +/******************************************************* +Function: + switch on & off esd delayed work +Input: + client: i2c device + on: SWITCH_ON / SWITCH_OFF +Output: + void +*********************************************************/ +void gtp_esd_switch(struct i2c_client *client, s32 on) +{ + struct goodix_ts_data *ts; + + ts = i2c_get_clientdata(client); + spin_lock(&ts->esd_lock); + + if (SWITCH_ON == on) { + if (!ts->esd_running) { + ts->esd_running = 1; + spin_unlock(&ts->esd_lock); + GTP_INFO("Esd started"); + queue_delayed_work(gtp_esd_check_workqueue, >p_esd_check_work, ts->clk_tick_cnt); + } else { + spin_unlock(&ts->esd_lock); + } + } else { + if (ts->esd_running) { + ts->esd_running = 0; + spin_unlock(&ts->esd_lock); + GTP_INFO("Esd cancelled"); + cancel_delayed_work_sync(>p_esd_check_work); + } else { + spin_unlock(&ts->esd_lock); + } + } +} + +/******************************************************* +Function: + Initialize external watchdog for esd protect +Input: + client: i2c device. +Output: + result of i2c write operation. + 1: succeed, otherwise: failed +*********************************************************/ +static s32 gtp_init_ext_watchdog(struct i2c_client *client) +{ + u8 opr_buffer[3] = {0x80, 0x41, 0xAA}; + GTP_DEBUG("[Esd]Init external watchdog"); + return gtp_i2c_write_no_rst(client, opr_buffer, 3); +} + +/******************************************************* +Function: + Esd protect function. + External watchdog added by meta, 2013/03/07 +Input: + work: delayed work +Output: + None. +*******************************************************/ +static void gtp_esd_check_func(struct work_struct *work) +{ + s32 i; + s32 ret = -1; + struct goodix_ts_data *ts = NULL; + u8 esd_buf[5] = {0x80, 0x40}; + + GTP_DEBUG_FUNC(); + + ts = i2c_get_clientdata(i2c_connect_client); + + if (ts->gtp_is_suspend || ts->enter_update) { + GTP_INFO("Esd suspended!"); + return; + } + + for (i = 0; i < 3; i++) { + ret = gtp_i2c_read_no_rst(ts->client, esd_buf, 4); + + GTP_DEBUG("[Esd]0x8040 = 0x%02X, 0x8041 = 0x%02X", esd_buf[2], esd_buf[3]); + if ((ret < 0)) { + + continue; + } else { + if ((esd_buf[2] == 0xAA) || (esd_buf[3] != 0xAA)) { + + u8 chk_buf[4] = {0x80, 0x40}; + + gtp_i2c_read_no_rst(ts->client, chk_buf, 4); + GTP_DEBUG("[Check]0x8040 = 0x%02X, 0x8041 = 0x%02X", chk_buf[2], chk_buf[3]); + if ((chk_buf[2] == 0xAA) || (chk_buf[3] != 0xAA)) { + i = 3; + break; + } else { + continue; + } + } else { + + esd_buf[2] = 0xAA; + gtp_i2c_write_no_rst(ts->client, esd_buf, 3); + break; + } + } + } + if (i >= 3) { + #if GTP_COMPATIBLE_MODE + if (CHIP_TYPE_GT9F == ts->chip_type) { + if (ts->rqst_processing) { + GTP_INFO("Request processing, no esd recovery"); + } else { + GTP_ERROR("IC working abnormally! Process esd recovery."); + esd_buf[0] = 0x42; + esd_buf[1] = 0x26; + esd_buf[2] = 0x01; + esd_buf[3] = 0x01; + esd_buf[4] = 0x01; + gtp_i2c_write_no_rst(ts->client, esd_buf, 5); + msleep(50); + #if 1 + gtp_power_switch(ts->client, 0); + msleep(20); + gtp_power_switch(ts->client, 1); + msleep(20); + #endif + gtp_esd_recovery(ts->client); + } + } else + #endif + { + GTP_ERROR("IC working abnormally! Process reset guitar."); + esd_buf[0] = 0x42; + esd_buf[1] = 0x26; + esd_buf[2] = 0x01; + esd_buf[3] = 0x01; + esd_buf[4] = 0x01; + gtp_i2c_write_no_rst(ts->client, esd_buf, 5); + msleep(50); + #if 1 + gtp_power_switch(ts->client, 0); + msleep(20); + gtp_power_switch(ts->client, 1); + msleep(20); + #endif + gtp_reset_guitar(ts->client, 50); + msleep(50); + gtp_send_cfg(ts->client); + } + } + + if (!ts->gtp_is_suspend) { + queue_delayed_work(gtp_esd_check_workqueue, >p_esd_check_work, ts->clk_tick_cnt); + } else { + GTP_INFO("Esd suspended!"); + } + return; +} +#endif + +#if 1 +static const struct of_device_id goodix_match_table[] = { + {.compatible = "goodix,gt9xx",}, + { }, +}; +#endif + +static const struct i2c_device_id goodix_ts_id[] = { + { GTP_I2C_NAME, 0 }, + { } +}; + +static struct i2c_driver goodix_ts_driver = { + .probe = goodix_ts_probe, + .remove = goodix_ts_remove, + .id_table = goodix_ts_id, + .driver = { + .name = GTP_I2C_NAME, + .owner = THIS_MODULE, +#if 1 + .of_match_table = goodix_match_table, +#endif +#if !defined(CONFIG_FB) && defined(CONFIG_PM) + .pm = >p_pm_ops, +#endif + }, +}; + +/******************************************************* +Function: + Driver Install function. +Input: + None. +Output: + Executive Outcomes. 0---succeed. +********************************************************/ +static int __init goodix_ts_init(void) +{ + s32 ret; + + GTP_DEBUG_FUNC(); + GTP_INFO("GTP driver installing..."); + goodix_wq = create_singlethread_workqueue("goodix_wq"); + if (!goodix_wq) { + GTP_ERROR("Creat workqueue failed."); + return -ENOMEM; + } +#if GTP_ESD_PROTECT + INIT_DELAYED_WORK(>p_esd_check_work, gtp_esd_check_func); + gtp_esd_check_workqueue = create_workqueue("gtp_esd_check"); +#endif + ret = i2c_add_driver(&goodix_ts_driver); + GTP_INFO("wmy i2c_add_driver, ret = %d", ret); + return ret; +} + +/******************************************************* +Function: + Driver uninstall function. +Input: + None. +Output: + Executive Outcomes. 0---succeed. +********************************************************/ +static void __exit goodix_ts_exit(void) +{ + GTP_DEBUG_FUNC(); + GTP_INFO("GTP driver exited."); + i2c_del_driver(&goodix_ts_driver); + if (goodix_wq) { + destroy_workqueue(goodix_wq); + } +} + +module_init(goodix_ts_init); +module_exit(goodix_ts_exit); + +MODULE_DESCRIPTION("GTP Series Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/gt9xx_mido/gt9xx.h b/drivers/input/touchscreen/gt9xx_mido/gt9xx.h new file mode 100644 index 0000000000000..64bb7dff4ea61 --- /dev/null +++ b/drivers/input/touchscreen/gt9xx_mido/gt9xx.h @@ -0,0 +1,403 @@ +/* + * Goodix GT9xx touchscreen driver + * + * Copyright (C) 2010 - 2014 Goodix. Ltd. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be a reference + * to you, when you are integrating the GOODiX's CTP IC into your system, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Version: 2.4 + * Release Date: 2014/11/28 + */ + +#ifndef _GOODIX_GT9XX_H_ +#define _GOODIX_GT9XX_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_OF +#include +#include +#endif +#ifdef CONFIG_FB +#include +#include +#endif +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif + + +#define GTP_CUSTOM_CFG 1 +#define GTP_CHANGE_X2Y 0 +#define GTP_DRIVER_SEND_CFG 1 +#define GTP_HAVE_TOUCH_KEY 1 +#define GTP_POWER_CTRL_SLEEP 0 +#define GTP_ICS_SLOT_REPORT 0 + +#define CONFIG_GTP_GLOVE_MODE 1 +#define GTP_AUTO_UPDATE 1 +#define GTP_HEADER_FW_UPDATE 1 +#define GTP_AUTO_UPDATE_CFG 0 + +#define GTP_COMPATIBLE_MODE 0 + +#define GTP_CREATE_WR_NODE 1 +#define GTP_ESD_PROTECT 1 + +#define GTP_WITH_PEN 0 +#define GTP_PEN_HAVE_BUTTON 0 + +#define GTP_GESTURE_WAKEUP 1 + +#define GTP_DEBUG_ON 0 +#define GTP_DEBUG_ARRAY_ON 0 +#define GTP_DEBUG_FUNC_ON 0 +#define GTP_CONFIG_OF 1 + +#if GTP_COMPATIBLE_MODE +typedef enum { + CHIP_TYPE_GT9 = 0, + CHIP_TYPE_GT9F = 1, +} CHIP_TYPE_T; +#endif + +struct goodix_ts_data { + spinlock_t irq_lock; + struct i2c_client *client; + struct input_dev *input_dev; + struct hrtimer timer; + struct work_struct work; + s32 irq_is_disable; + s32 use_irq; + u16 abs_x_max; + u16 abs_y_max; + u8 max_touch_num; + u8 int_trigger_type; + u8 green_wake_mode; + u8 enter_update; + u8 gtp_is_suspend; + u8 gtp_rawdiff_mode; + int gtp_cfg_len; + u8 fw_error; + u8 pnl_init_error; + +#if defined(CONFIG_FB) + struct notifier_block notifier; +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif + +#if GTP_WITH_PEN + struct input_dev *pen_dev; +#endif + struct pinctrl *ts_pinctrl; + struct pinctrl_state *pinctrl_state_active; + struct pinctrl_state *pinctrl_state_suspend; + struct pinctrl_state *pinctrl_state_release; +#if GTP_ESD_PROTECT + spinlock_t esd_lock; + u8 esd_running; + s32 clk_tick_cnt; +#endif +#if GTP_COMPATIBLE_MODE + u16 bak_ref_len; + s32 ref_chk_fs_times; + s32 clk_chk_fs_times; + CHIP_TYPE_T chip_type; + u8 rqst_processing; + u8 is_950; +#endif + +}; + +extern u16 show_len; +extern u16 total_len; +extern int gtp_rst_gpio; +extern int gtp_int_gpio; + +#define CTP_CFG_GROUP0 {\ + 0x45, 0x38, 0x04, 0x80, 0x07, 0x0A, 0x35, 0x41, 0x01, 0x0A, \ + 0x26, 0x0B, 0x5A, 0x32, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x05, 0x14, 0x14, 0x26, 0x14, 0x8C, 0x2E, 0x0E, \ + 0x4A, 0x4C, 0xF4, 0x0A, 0xF4, 0x0A, 0x00, 0xBA, 0x33, 0x11, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x28, 0x78, 0x96, \ + 0x3A, 0x1E, 0x5A, 0x8F, 0x90, 0x03, 0x00, 0x00, 0x00, 0x04, \ + 0xCE, 0x21, 0x00, 0xB0, 0x29, 0x28, 0x98, 0x34, 0x00, 0x87, \ + 0x41, 0x60, 0x7B, 0x51, 0x00, 0x7B, 0x18, 0x38, 0x60, 0x00, \ + 0xF0, 0x55, 0x40, 0xAA, 0xA0, 0x27, 0x00, 0x04, 0x53, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, \ + 0x00, 0x28, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, \ + 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0F, \ + 0x10, 0x12, 0x13, 0x14, 0x16, 0x18, 0x1C, 0x1D, 0x1E, 0x1F, \ + 0x20, 0x21, 0x22, 0x24, 0x26, 0x28, 0x29, 0x2A, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x23, 0x01\ +} +#define GTP_CFG_GROUP0_GLOVE1 {\ + 0x00, 0x38, 0x04, 0xC4, 0x04, 0x0A, 0x35, 0x04, 0x02, 0x0F, \ + 0x64, 0x0F, 0x4B, 0x37, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x08, 0x14, 0x14, 0x14, 0x14, 0x8C, 0x24, 0x0E, \ + 0x6E, 0x70, 0x43, 0x06, 0x00, 0x00, 0x00, 0x5B, 0x03, 0x91, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x46, 0x7D, 0x94, 0x80, 0x03, 0x00, 0x00, 0x00, 0x04, \ + 0x98, 0x4A, 0x00, 0x8F, 0x53, 0x00, 0x88, 0x5D, 0x00, 0x82, \ + 0x69, 0x00, 0x7D, 0x76, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0xAA, 0xA0, 0x27, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, \ + 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0F, \ + 0x10, 0x12, 0x13, 0x14, 0x16, 0x18, 0x1C, 0x1D, 0xFF, 0xFF, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x79, 0x01\ +} +#define GTP_CFG_GROUP0_GLOVE2 {\ + 0x00, 0x38, 0x04, 0x80, 0x07, 0x0A, 0x35, 0x04, 0x02, 0x0F, \ + 0x64, 0x0F, 0x4B, 0x37, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x08, 0x14, 0x14, 0x26, 0x14, 0x8C, 0x2D, 0x0E, \ + 0x6E, 0x70, 0x43, 0x06, 0x00, 0x00, 0x00, 0x5B, 0x03, 0x91, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x46, 0x7D, 0x94, 0x80, 0x03, 0x00, 0x00, 0x00, 0x04, \ + 0x98, 0x4A, 0x00, 0x8F, 0x53, 0x00, 0x88, 0x5D, 0x00, 0x82, \ + 0x69, 0x00, 0x7D, 0x76, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0xAA, 0xA0, 0x27, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, \ + 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0F, \ + 0x10, 0x12, 0x13, 0x14, 0x16, 0x18, 0x1C, 0x1D, 0x1E, 0x1F, \ + 0x20, 0x21, 0x22, 0x24, 0x26, 0x28, 0x29, 0xFF, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x5B, 0x01\ +} + + +#define GTP_CFG_GROUP1_GLOVE1 {\ + 0x49, 0x38, 0x04, 0xC4, 0x04, 0x0A, 0x3D, 0x28, 0x01, 0xC8, \ + 0x28, 0x0D, 0x50, 0x41, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x02, 0x00, 0x16, 0x1A, 0x1E, 0x14, 0x87, 0x27, 0x78, \ + 0x50, 0x52, 0xE7, 0x07, 0xE7, 0x07, 0x01, 0x43, 0x34, 0x91, \ + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x83, 0x64, 0x14, 0x14, 0xC8, \ + 0x02, 0x3C, 0x64, 0x94, 0xD0, 0x03, 0x05, 0x1E, 0x00, 0x04, \ + 0x94, 0x3F, 0x00, 0x8A, 0x46, 0x00, 0x82, 0x4D, 0x00, 0x7B, \ + 0x55, 0x00, 0x74, 0x5F, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, \ + 0xF7, 0x55, 0x40, 0xFF, 0xFF, 0x17, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x28, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x46, 0x00, 0x00, 0x00, \ + 0x00, 0x32, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, \ + 0x04, 0x03, 0x02, 0x01, 0x00, 0x0D, 0x0E, 0xFF, 0xFF, 0xFF, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xFF, 0xFF, 0x29, 0x28, 0x24, 0x22, 0x20, 0x1F, 0x1E, 0x0A, \ + 0x08, 0x06, 0x05, 0x04, 0x02, 0x00, 0xFF, 0xFF, 0xFF, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x32, \ + 0x3C, 0x00, 0x23, 0x28, 0x06, 0x00, 0x00, 0x00, 0x00, 0x20, \ + 0x22, 0x32, 0x0F, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x1E, 0x46, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, \ + 0x01, 0x14, 0x78, 0x41, 0x19, 0x46, 0x1E, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0x01\ +} +#define GTP_CFG_GROUP1_GLOVE2 {\ + 0x49, 0x38, 0x04, 0x80, 0x07, 0x0A, 0x3D, 0x28, 0x01, 0xC8, \ + 0x28, 0x0D, 0x50, 0x41, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x02, 0x00, 0x16, 0x1A, 0x1E, 0x14, 0x87, 0x27, 0xCD, \ + 0x50, 0x52, 0xE7, 0x07, 0xE7, 0x07, 0x00, 0x43, 0x34, 0x91, \ + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x03, 0x60, 0x14, 0x14, 0xC8, \ + 0x02, 0x3C, 0x64, 0x94, 0xD0, 0x03, 0x05, 0x1E, 0x00, 0x04, \ + 0x94, 0x3F, 0x00, 0x8A, 0x46, 0x00, 0x82, 0x4D, 0x00, 0x7B, \ + 0x55, 0x00, 0x74, 0x5F, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, \ + 0xF7, 0x55, 0x40, 0xFF, 0xFF, 0x17, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x28, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x46, 0x00, 0x00, 0x00, \ + 0x00, 0x32, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, \ + 0x04, 0x03, 0x02, 0x01, 0x00, 0x0D, 0x0E, 0x0F, 0x10, 0x11, \ + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, \ + 0xFF, 0xFF, 0x29, 0x28, 0x24, 0x22, 0x20, 0x1F, 0x1E, 0x0A, \ + 0x08, 0x06, 0x05, 0x04, 0x02, 0x00, 0xFF, 0xFF, 0xFF, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x32, \ + 0x3C, 0x00, 0x23, 0x28, 0x06, 0x00, 0x00, 0x00, 0x00, 0x20, \ + 0x22, 0x32, 0x0F, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x1E, 0x46, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, \ + 0x01, 0x14, 0x78, 0x41, 0x19, 0x46, 0x1E, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x01\ +} + + +#define CTP_CFG_GROUP1 {\ +} + + +#define CTP_CFG_GROUP2 {\ +} + + +#define CTP_CFG_GROUP3 {\ +} + +#define CTP_CFG_GROUP4 {\ +} + + +#define CTP_CFG_GROUP5 {\ +} + + +#define GTP_RST_PORT 64 +#define GTP_INT_PORT 65 + +#define GTP_GPIO_AS_INPUT(pin) do {\ + gpio_direction_input(pin);\ + } while (0) +#define GTP_GPIO_AS_INT(pin) do {\ + GTP_GPIO_AS_INPUT(pin);\ + } while (0) +#define GTP_GPIO_GET_VALUE(pin) gpio_get_value(pin) +#define GTP_GPIO_OUTPUT(pin, level) gpio_direction_output(pin, level) +#define GTP_GPIO_REQUEST(pin, label) gpio_request(pin, label) +#define GTP_GPIO_FREE(pin) gpio_free(pin) +#define GTP_IRQ_TAB {IRQ_TYPE_EDGE_RISING, IRQ_TYPE_EDGE_FALLING, IRQ_TYPE_LEVEL_LOW, IRQ_TYPE_LEVEL_HIGH} + + +#if GTP_CUSTOM_CFG + #define GTP_MAX_HEIGHT 1920 + #define GTP_MAX_WIDTH 1080 + #define GTP_INT_TRIGGER 1 +#else + #define GTP_MAX_HEIGHT 4096 + #define GTP_MAX_WIDTH 4096 + #define GTP_INT_TRIGGER 1 +#endif +#define GTP_MAX_TOUCH 10 + + +#if GTP_HAVE_TOUCH_KEY + #define GTP_KEY_TAB {KEY_MENU, KEY_HOMEPAGE, KEY_BACK} +#endif + + +#define GTP_DRIVER_VERSION "V2.4<2014/11/28>" +#define GTP_I2C_NAME "Goodix-TS" +#define GT91XX_CONFIG_PROC_FILE "gt9xx_config" +#define GT91XX_Color_PROC_FILE "tp_lockdown_info" +#define GT91XX_Glove_PROC_FILE "gtp_glove_fun" + +#define GTP_POLL_TIME 10 +#define GTP_ADDR_LENGTH 2 +#define GTP_CONFIG_MIN_LENGTH 186 +#define GTP_CONFIG_MAX_LENGTH 240 +#define FAIL 0 +#define SUCCESS 1 +#define SWITCH_OFF 0 +#define SWITCH_ON 1 + + +#define GTP_REG_BAK_REF 0x99D0 +#define GTP_REG_MAIN_CLK 0x8020 +#define GTP_REG_CHIP_TYPE 0x8000 +#define GTP_REG_HAVE_KEY 0x804E +#define GTP_REG_MATRIX_DRVNUM 0x8069 +#define GTP_REG_MATRIX_SENNUM 0x806A + +#define GTP_FL_FW_BURN 0x00 +#define GTP_FL_ESD_RECOVERY 0x01 +#define GTP_FL_READ_REPAIR 0x02 + +#define GTP_BAK_REF_SEND 0 +#define GTP_BAK_REF_STORE 1 +#define CFG_LOC_DRVB_NUM 30 +#define CFG_LOC_SENS_NUM 31 + +#define GTP_CHK_FW_MAX 40 +#define GTP_CHK_FS_MNT_MAX 300 +#define GTP_BAK_REF_PATH "/data/gtp_ref.bin" +#define GTP_MAIN_CLK_PATH "/data/gtp_clk.bin" +#define GTP_RQST_CONFIG 0x01 +#define GTP_RQST_BAK_REF 0x02 +#define GTP_RQST_RESET 0x03 +#define GTP_RQST_MAIN_CLOCK 0x04 +#define GTP_RQST_RESPONDED 0x00 +#define GTP_RQST_IDLE 0xFF + + + +#define GTP_READ_COOR_ADDR 0x814E +#define GTP_REG_SLEEP 0x8040 +#define GTP_REG_SENSOR_ID 0x814A +#define GTP_REG_CONFIG_DATA 0x8047 +#define GTP_REG_VERSION 0x8140 +#define GTP_REG_COLOR_GT915 0xc8a4 +#define GTP_REG_COLOR_GT917 0x81a0 +#define GTP_REG_FW 0x8144 + + +#define RESOLUTION_LOC 3 +#define TRIGGER_LOC 8 + +#define CFG_GROUP_LEN(p_cfg_grp) (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0])) + +#define GTP_INFO(fmt, arg...) printk("<<-GTP-INFO->> "fmt"\n", ##arg) +#define GTP_ERROR(fmt, arg...) printk("<<-GTP-ERROR->> "fmt"\n", ##arg) +#define GTP_DEBUG(fmt, arg...) do {\ + if (GTP_DEBUG_ON)\ + printk("<<-GTP-DEBUG->> [%d]"fmt"\n", __LINE__, ##arg);\ + } while (0) +#define GTP_DEBUG_ARRAY(array, num) do {\ + s32 i;\ + u8 *a = array;\ + if (GTP_DEBUG_ARRAY_ON) {\ + printk("<<-GTP-DEBUG-ARRAY->>\n");\ + for (i = 0; i < (num); i++) {\ + printk("%02x ", (a)[i]);\ + if ((i + 1) % 10 == 0)\ + printk("\n");\ + } \ + printk("\n");\ + } \ + } while (0) +#define GTP_DEBUG_FUNC() do {\ + if (GTP_DEBUG_FUNC_ON)\ + printk("<<-GTP-FUNC->> Func:%s@Line:%d\n", __func__, __LINE__);\ + } while (0) +#define GTP_SWAP(x, y) do {\ + typeof(x) z = x;\ + x = y;\ + y = z;\ + } while (0) + + +#ifdef CONFIG_OF +int gtp_parse_dt_cfg(struct device *dev, u8 *cfg, int *cfg_len, u8 sid); +#endif +#define CFG_LOC_DRVA_NUM 29 +#endif /* _GOODIX_GT9XX_H_ */ diff --git a/drivers/input/touchscreen/gt9xx_mido/gt9xx_firmware.h b/drivers/input/touchscreen/gt9xx_mido/gt9xx_firmware.h new file mode 100644 index 0000000000000..0f38db6d092ad --- /dev/null +++ b/drivers/input/touchscreen/gt9xx_mido/gt9xx_firmware.h @@ -0,0 +1,13557 @@ +/* Copyright Statement: +*This firmware are protected under relevant copyright laws, this information contained +*herein is confidential and proprietary to Goodix. +* +* Copyright (C) 2010 - 2014 Goodix. Ltd. +* Copyright (C) 2017 XiaoMi, Inc. +* +*WARNING:The GTP_COMPATIBLE_MODE part of this file was generated by the specialized tools, +*please do not modify it manually! +* +*/ + +#ifndef _GT9XX_FIRMWARE_H_ +#define _GT9XX_FIRMWARE_H_ + +#if GTP_HEADER_FW_UPDATE + +unsigned char gt917_FW[] = { + 0x00, 0x01, 0x60, 0x00, 0x39, 0x31, 0x37, 0x44, 0x00, 0x00, 0x00, 0x00, 0x50, 0x03, 0x80, 0x00, 0x55, 0x40, 0xBD, 0xDA, + 0xFD, 0x24, 0x34, 0xDF, 0x44, 0x40, 0x44, 0x02, 0xBE, 0x03, 0x08, 0xB4, 0x27, 0x41, 0x8C, 0x90, 0x4C, 0xA4, 0x22, 0xB7, + 0xED, 0x5E, 0x58, 0x34, 0x17, 0xBF, 0x01, 0x08, 0x84, 0x00, 0x72, 0xFC, 0x81, 0xD9, 0x39, 0x25, 0xC8, 0xE2, 0x39, 0x87, + 0x0F, 0xED, 0x09, 0x1D, 0xC9, 0x1A, 0xE9, 0xD5, 0x5F, 0x2E, 0x23, 0xB6, 0x6D, 0x4B, 0xA6, 0xE6, 0xA3, 0x7E, 0x3F, 0x64, + 0xFB, 0x1B, 0x67, 0xA6, 0xF2, 0xB5, 0xF4, 0x02, 0xA9, 0x4B, 0x2B, 0x1F, 0x7C, 0xDB, 0x58, 0x96, 0x51, 0xDA, 0x75, 0x4A, + 0xB0, 0xA0, 0x5D, 0x1B, 0x2B, 0x01, 0x0C, 0x9B, 0x51, 0x8B, 0x3F, 0xA3, 0x77, 0x82, 0xEE, 0xF4, 0x31, 0xB9, 0xE5, 0x03, + 0xE6, 0x4C, 0xEA, 0xC0, 0x21, 0x1B, 0x7E, 0xB3, 0xE8, 0x08, 0x32, 0x7E, 0x30, 0x5A, 0x20, 0x67, 0x60, 0x57, 0x5D, 0xFE, + 0xD2, 0xE7, 0xD2, 0xAC, 0x2E, 0x48, 0x98, 0x22, 0x39, 0xB8, 0x96, 0xDE, 0xC8, 0x68, 0x3A, 0x8E, 0xDF, 0x4F, 0x9A, 0x18, + 0x09, 0x49, 0xC2, 0x8F, 0xF8, 0x26, 0x3A, 0x11, 0xA8, 0x2F, 0x35, 0x42, 0x84, 0x94, 0x8C, 0x7B, 0x2B, 0x6F, 0x43, 0x51, + 0x03, 0x2C, 0xEB, 0x21, 0x17, 0xC5, 0x03, 0xA9, 0xD0, 0x1C, 0xCE, 0x8B, 0x89, 0x0B, 0xEB, 0xDD, 0x5B, 0x24, 0xAF, 0xD3, + 0x8A, 0xAB, 0x44, 0x35, 0xF7, 0x2D, 0x43, 0x37, 0x76, 0xF3, 0x65, 0xAE, 0xFA, 0xD0, 0xE8, 0x4C, 0xF4, 0x93, 0x6F, 0xE7, + 0xE5, 0x9C, 0xCC, 0xD2, 0x08, 0xCD, 0x9F, 0xA2, 0xFA, 0xBE, 0x23, 0x1E, 0xA0, 0x42, 0x23, 0x58, 0x68, 0x7F, 0x7C, 0xEC, + 0x71, 0x06, 0xED, 0xAF, 0xEE, 0x92, 0xD2, 0x02, 0xA2, 0x0A, 0xBA, 0x1E, 0x3B, 0x51, 0x25, 0xBB, 0x2C, 0x4E, 0xB0, 0x33, + 0x7B, 0x9E, 0x5A, 0x1F, 0xEF, 0xE2, 0x64, 0x40, 0x24, 0xB2, 0x04, 0x80, 0x78, 0xF8, 0xBE, 0x7B, 0x36, 0xC1, 0x74, 0x7C, + 0xAD, 0xDD, 0x04, 0xDB, 0xA8, 0x7F, 0xDE, 0xB0, 0x26, 0xE9, 0xAF, 0x3C, 0xE9, 0x02, 0x6F, 0x97, 0x9E, 0xDB, 0xBF, 0x56, + 0x91, 0x60, 0x4F, 0x28, 0x82, 0x11, 0x94, 0x81, 0xC5, 0xA9, 0xCE, 0xA0, 0x6E, 0x5B, 0xA7, 0x8F, 0x53, 0x8E, 0x02, 0x1D, + 0x24, 0xE6, 0x2C, 0x39, 0x2D, 0x40, 0xCA, 0x11, 0x08, 0x63, 0x36, 0xAE, 0x52, 0xF6, 0xBB, 0xB2, 0xF4, 0xCB, 0xFB, 0x4A, + 0xC3, 0x02, 0xC4, 0x20, 0x7A, 0x69, 0xFF, 0x0B, 0x56, 0xDF, 0x76, 0x4B, 0xD8, 0x98, 0xCF, 0x27, 0xB7, 0xE8, 0x5D, 0xC6, + 0xC0, 0x14, 0x23, 0x8A, 0x5D, 0xAA, 0x85, 0xC0, 0x2D, 0x7A, 0xFB, 0xC3, 0x20, 0x3E, 0x43, 0xE7, 0x73, 0x99, 0xAD, 0x65, + 0x0F, 0x87, 0x2E, 0x2B, 0x23, 0x77, 0x28, 0x2B, 0x4A, 0x61, 0xA8, 0x0F, 0xFB, 0x6A, 0xE2, 0x50, 0x08, 0xEB, 0xC6, 0x55, + 0x4C, 0x03, 0x2D, 0xF3, 0xED, 0x76, 0x5C, 0x35, 0x9F, 0xD5, 0x05, 0x52, 0x5C, 0xEF, 0x71, 0x1A, 0xA1, 0x11, 0xFA, 0x61, + 0x07, 0x7B, 0x9D, 0xE7, 0x2A, 0x55, 0x8B, 0xC3, 0xA1, 0x76, 0xF8, 0xFB, 0x4F, 0x04, 0xF1, 0xCB, 0x1E, 0x76, 0xF3, 0x8E, + 0xC9, 0x7A, 0x97, 0xA0, 0x0E, 0x7A, 0xD0, 0xDB, 0xDE, 0xE3, 0x8B, 0x0E, 0x45, 0x28, 0x09, 0xDB, 0xC8, 0x4E, 0xBD, 0x42, + 0x01, 0x74, 0x86, 0xC9, 0xA5, 0x1F, 0xB9, 0xB6, 0xA0, 0xA3, 0x40, 0xEE, 0xFB, 0x13, 0x02, 0xB6, 0xEB, 0x1F, 0xA9, 0x27, + 0xCA, 0xCB, 0xF4, 0x82, 0x84, 0xB0, 0xCE, 0x92, 0xB7, 0x52, 0x3B, 0x86, 0xED, 0x60, 0x29, 0xDC, 0x27, 0x93, 0x40, 0x1E, + 0x19, 0xF0, 0x69, 0x0B, 0xFA, 0x11, 0xFE, 0x6D, 0x35, 0x9E, 0xB4, 0xFD, 0x62, 0x10, 0xE0, 0x33, 0x5A, 0xA3, 0x6D, 0xA3, + 0x77, 0x50, 0xBA, 0xBD, 0xEF, 0xC2, 0x20, 0x02, 0x04, 0xC0, 0x7F, 0xAB, 0x12, 0x52, 0x22, 0x3A, 0xD5, 0xAC, 0x42, 0xE0, + 0xF6, 0xAC, 0x28, 0x12, 0x05, 0xC1, 0xAA, 0xEB, 0x74, 0x7A, 0x32, 0x12, 0xD4, 0xA5, 0x4D, 0x37, 0x11, 0xD5, 0x21, 0x1F, + 0x84, 0x82, 0x58, 0x41, 0x60, 0xEE, 0xE5, 0x71, 0x87, 0x32, 0xC1, 0xF8, 0x3B, 0xA3, 0x29, 0x92, 0x85, 0x83, 0xA9, 0x93, + 0xDA, 0x4E, 0x31, 0x23, 0x26, 0x09, 0x19, 0x39, 0x59, 0xEE, 0xCC, 0xC8, 0xFD, 0x74, 0x4B, 0xF7, 0xB5, 0x1B, 0xD4, 0x4E, + 0xAD, 0xA0, 0x24, 0x98, 0xAF, 0x87, 0xC0, 0x81, 0xF6, 0x86, 0xB6, 0xB4, 0x07, 0x0E, 0xCC, 0x19, 0xC9, 0x84, 0xD5, 0xD3, + 0xCE, 0xE7, 0x0F, 0xA1, 0x33, 0xC7, 0xDB, 0xFF, 0x65, 0xE7, 0x4C, 0xE4, 0x2D, 0xC9, 0x8E, 0x1D, 0xF8, 0x79, 0xD7, 0x5A, + 0x21, 0x29, 0x49, 0x57, 0x6A, 0x56, 0x00, 0xDC, 0xCF, 0xE5, 0x17, 0x66, 0x49, 0xDA, 0x22, 0x0A, 0x0C, 0xC8, 0xC2, 0x4E, + 0xA2, 0x23, 0x12, 0x2B, 0x09, 0x07, 0x22, 0xEE, 0x58, 0x05, 0x2A, 0x1A, 0x0D, 0xC9, 0x42, 0x21, 0x9F, 0x7D, 0x3E, 0x3E, + 0x0D, 0xD9, 0x06, 0x1A, 0xC5, 0xAD, 0x23, 0x8F, 0x8C, 0x8A, 0xA7, 0xED, 0x1B, 0xFF, 0xDC, 0x59, 0x4C, 0xBA, 0x23, 0x80, + 0x2B, 0xAA, 0x66, 0xDD, 0x8D, 0x8B, 0x58, 0xEF, 0x8C, 0xA4, 0x7B, 0x1B, 0xCC, 0xCF, 0x1A, 0x38, 0x3C, 0x8D, 0x58, 0x0D, + 0xD4, 0x33, 0x1D, 0x30, 0x30, 0x73, 0x4C, 0x6C, 0x76, 0x63, 0x13, 0x2E, 0x12, 0x71, 0x3A, 0x2D, 0x45, 0xCA, 0x3E, 0x04, + 0xD6, 0xE9, 0x04, 0x7D, 0xFE, 0xC2, 0x87, 0x63, 0xCC, 0xE0, 0x59, 0xD1, 0x7D, 0x53, 0xCC, 0xEA, 0x47, 0x32, 0xD3, 0x18, + 0x42, 0x9D, 0x16, 0x95, 0x67, 0xB8, 0x05, 0x29, 0x02, 0x79, 0x3F, 0x0C, 0x1B, 0xD9, 0x45, 0x99, 0x63, 0xC0, 0xC1, 0x34, + 0x68, 0x62, 0x1E, 0x60, 0x88, 0x6E, 0x64, 0x87, 0xAA, 0x45, 0x3C, 0x08, 0x85, 0xB6, 0x24, 0xD4, 0xA5, 0xEF, 0x2C, 0x6F, + 0x25, 0x1C, 0x73, 0x9E, 0xB2, 0xB6, 0x88, 0x58, 0x84, 0xB7, 0x2B, 0x49, 0x80, 0x92, 0x5E, 0x5D, 0x13, 0x89, 0xF0, 0x03, + 0xBC, 0xC4, 0x81, 0x4D, 0x05, 0xB4, 0xEB, 0x45, 0xE4, 0x0F, 0xD5, 0x9B, 0x7A, 0x0C, 0x05, 0x35, 0x6A, 0xEC, 0x89, 0xF9, + 0x2C, 0x97, 0x46, 0xCD, 0xDB, 0x6C, 0x1D, 0xE5, 0x87, 0x85, 0x99, 0xEC, 0xB2, 0xF5, 0x46, 0xDA, 0x95, 0xE9, 0x11, 0x1D, + 0x87, 0xA2, 0x52, 0xD4, 0x6D, 0xD1, 0xEC, 0x1F, 0x81, 0xB5, 0x07, 0xFC, 0xC4, 0x68, 0x7B, 0x25, 0xD4, 0xAB, 0x1D, 0x90, + 0x05, 0x89, 0x94, 0xC7, 0x3F, 0x81, 0xD6, 0x01, 0x06, 0x47, 0x8E, 0x8D, 0x6C, 0xE9, 0x35, 0xD7, 0xED, 0xF3, 0xFA, 0xAD, + 0x2B, 0xB8, 0x4F, 0xCB, 0x14, 0x8A, 0xC7, 0xAC, 0x48, 0x7A, 0x78, 0xA8, 0xF9, 0x33, 0x0E, 0x3D, 0xF4, 0xCB, 0x1F, 0xE4, + 0xA5, 0xBC, 0x0D, 0x35, 0x8D, 0xEE, 0x1E, 0x6B, 0x00, 0xE9, 0x75, 0x9C, 0x42, 0x39, 0x10, 0xBC, 0xFC, 0x85, 0xD9, 0x40, + 0x21, 0x57, 0xA2, 0xD0, 0xC7, 0x0A, 0x07, 0x9C, 0x8A, 0xDE, 0x9E, 0x49, 0x40, 0xC6, 0xBF, 0xBE, 0x0F, 0x27, 0x71, 0x90, + 0xAD, 0x30, 0x47, 0x3D, 0x19, 0x3C, 0x11, 0xBC, 0x78, 0x25, 0xC7, 0xD4, 0x1C, 0x27, 0x5E, 0x62, 0x8D, 0xDD, 0xC4, 0x91, + 0xEB, 0x00, 0xD5, 0x08, 0x8E, 0x60, 0xDD, 0x00, 0x9F, 0xE0, 0xCE, 0xF3, 0xC4, 0xD9, 0x93, 0x36, 0x2D, 0x40, 0x4C, 0xC3, + 0xBE, 0xCE, 0x80, 0x1C, 0xCA, 0x2B, 0x92, 0xCA, 0xAC, 0x33, 0x9C, 0xBC, 0x1D, 0xC2, 0x46, 0x09, 0x72, 0xD1, 0x8A, 0xCB, + 0x43, 0x08, 0x51, 0xDC, 0x99, 0x30, 0x78, 0x20, 0x4A, 0xDC, 0x69, 0x19, 0x14, 0xE2, 0x77, 0x1D, 0x46, 0x49, 0x88, 0xE2, + 0xF1, 0x89, 0x33, 0xBC, 0xEC, 0x93, 0xAF, 0xC6, 0x64, 0x55, 0x15, 0x67, 0x43, 0x4C, 0x69, 0x41, 0xA2, 0x40, 0x88, 0x90, + 0x15, 0x30, 0x70, 0x37, 0xC2, 0x05, 0x0E, 0xD9, 0xB8, 0x5B, 0x21, 0x4B, 0xE1, 0x06, 0xAE, 0x6A, 0x49, 0xB9, 0xB1, 0x32, + 0x4C, 0x4D, 0x33, 0x66, 0x60, 0x20, 0xB4, 0x8E, 0x6A, 0x0C, 0xAE, 0xBD, 0xB3, 0x22, 0xD9, 0x21, 0x57, 0x01, 0xDB, 0xCE, + 0x38, 0x50, 0x08, 0x44, 0x8B, 0xCA, 0x88, 0x40, 0xBB, 0x4A, 0x2E, 0x20, 0xEB, 0xF5, 0x6E, 0xE1, 0xA5, 0xC9, 0xA2, 0x41, + 0x69, 0xA8, 0x4C, 0x27, 0x65, 0xAA, 0x27, 0x88, 0x43, 0xE4, 0x0E, 0x0A, 0x21, 0xCA, 0x81, 0x74, 0x16, 0x2A, 0xFF, 0xF8, + 0x71, 0x2D, 0x57, 0xD0, 0x2B, 0x1C, 0x42, 0xE0, 0xAA, 0xC9, 0xDE, 0x77, 0x6E, 0x65, 0xD1, 0xCC, 0x7A, 0xD4, 0x61, 0x8E, + 0x32, 0x05, 0x0B, 0xB2, 0x3A, 0x84, 0xBB, 0x96, 0x0D, 0x07, 0xC7, 0xE4, 0x67, 0xE5, 0x10, 0xA6, 0x4E, 0xC8, 0x3E, 0xB7, + 0x5B, 0xCA, 0x33, 0x82, 0x40, 0x06, 0xCE, 0x98, 0x75, 0xFF, 0x20, 0xDD, 0xA8, 0x2F, 0xE5, 0x4F, 0x63, 0x05, 0x3E, 0x92, + 0x8D, 0x05, 0x2F, 0x9F, 0x9C, 0x20, 0xF2, 0xAD, 0x88, 0x1C, 0xAD, 0xE4, 0xB8, 0xB5, 0x9B, 0x73, 0xA8, 0xFB, 0xD4, 0x09, + 0x9F, 0x0B, 0xAF, 0x6A, 0x45, 0xE7, 0xFC, 0x7D, 0xDD, 0x47, 0x3C, 0xED, 0xE3, 0x0F, 0xD4, 0x2E, 0xE5, 0x81, 0xC4, 0x11, + 0xA3, 0x7F, 0xB4, 0xC8, 0xB3, 0x4F, 0x1A, 0x66, 0x77, 0x16, 0x31, 0x7B, 0xBA, 0x41, 0x71, 0xB8, 0x57, 0x0F, 0x0B, 0xF8, + 0x37, 0x8C, 0x87, 0xBA, 0xE8, 0xA3, 0x10, 0xC9, 0xF6, 0xFF, 0x4B, 0xE9, 0xCC, 0xAF, 0x13, 0x58, 0x97, 0x66, 0xCF, 0x07, + 0x2F, 0xE2, 0xAD, 0xE8, 0x72, 0xEC, 0xCD, 0x77, 0x22, 0xFC, 0x1B, 0x48, 0xA9, 0x67, 0x6D, 0x63, 0x04, 0xDD, 0x27, 0x25, + 0xEC, 0x73, 0x15, 0x50, 0x64, 0x36, 0x14, 0xE7, 0xB7, 0x32, 0x0D, 0xE6, 0xD6, 0x01, 0xD5, 0x90, 0xE4, 0x74, 0xF8, 0x56, + 0x02, 0xD1, 0xE2, 0x08, 0xF8, 0xBF, 0x7E, 0x89, 0x45, 0xAD, 0xBB, 0x25, 0x44, 0xC3, 0xED, 0xA9, 0x83, 0x32, 0x03, 0x57, + 0x9A, 0xE1, 0xB7, 0x6E, 0x85, 0x9E, 0x33, 0x10, 0x64, 0x51, 0xC1, 0x83, 0x89, 0x17, 0x9B, 0x04, 0x18, 0x29, 0x0C, 0x50, + 0x24, 0xF5, 0x57, 0x37, 0x4A, 0x51, 0x94, 0xD5, 0x81, 0xF7, 0x14, 0x23, 0x9B, 0x97, 0x9F, 0x97, 0xCA, 0xA6, 0xC0, 0xE5, + 0x92, 0xCA, 0x5C, 0x83, 0x19, 0xF4, 0x1C, 0xC1, 0x3E, 0x7D, 0x3F, 0x70, 0xD0, 0xB9, 0xFD, 0x36, 0xC6, 0x9B, 0x06, 0x12, + 0x94, 0x8D, 0xB3, 0x55, 0x1B, 0x15, 0xAA, 0x22, 0xAA, 0xBA, 0xF3, 0x95, 0xB5, 0xD6, 0x94, 0x02, 0xEA, 0x8A, 0x5F, 0x71, + 0x9F, 0x7D, 0xE2, 0x72, 0x4B, 0x38, 0xEF, 0x66, 0xD3, 0xBB, 0x68, 0xAE, 0x81, 0x57, 0x84, 0xAD, 0x87, 0xF5, 0xEA, 0x66, + 0x4A, 0x79, 0xD8, 0xEF, 0x53, 0x55, 0x8E, 0xCB, 0x3E, 0x52, 0xCB, 0xDC, 0x33, 0x17, 0xE3, 0x72, 0xCB, 0x5A, 0x24, 0x28, + 0x59, 0x95, 0x41, 0xAE, 0x03, 0x3E, 0x57, 0x98, 0x81, 0xD7, 0xEB, 0x66, 0x8D, 0x86, 0xED, 0x95, 0xB8, 0x7B, 0x9F, 0xDA, + 0x26, 0x19, 0xFD, 0xBC, 0xFA, 0x3B, 0x15, 0x56, 0xC1, 0x14, 0x55, 0x32, 0x96, 0x31, 0x00, 0x50, 0x81, 0x54, 0x16, 0xF9, + 0xE9, 0xDC, 0x14, 0xDC, 0x43, 0xAE, 0xA8, 0xE0, 0xD2, 0x8C, 0x16, 0x9A, 0x0A, 0x7D, 0x84, 0xFD, 0xD8, 0x88, 0x7B, 0xF0, + 0xE2, 0xBD, 0x38, 0x0A, 0x53, 0x4D, 0x6B, 0xD0, 0xEC, 0xBF, 0x81, 0xCE, 0xE1, 0x3F, 0x31, 0x60, 0x4A, 0xBC, 0xD5, 0xDF, + 0x08, 0x92, 0x07, 0xFD, 0x42, 0x31, 0x88, 0xC3, 0x89, 0x3D, 0x1B, 0x45, 0x0A, 0x1F, 0x8C, 0xFF, 0x04, 0xE2, 0x48, 0x71, + 0xC8, 0xDC, 0x5A, 0x55, 0x2E, 0x11, 0xEC, 0xEC, 0xF8, 0xE3, 0x88, 0x0A, 0x13, 0x40, 0x8C, 0x61, 0xC9, 0x6D, 0xFF, 0x27, + 0x3F, 0xA3, 0x1E, 0x86, 0x7F, 0x5F, 0x37, 0x90, 0xEF, 0xC2, 0x1F, 0x25, 0x55, 0xCD, 0xCF, 0x9A, 0x21, 0xE6, 0xD6, 0xD9, + 0x2E, 0xC2, 0x4A, 0xEE, 0xD9, 0xE1, 0x41, 0x60, 0x49, 0xDF, 0x2F, 0x04, 0xD3, 0x02, 0xA4, 0x1C, 0x08, 0x9A, 0xFA, 0x44, + 0xA5, 0x79, 0x67, 0x91, 0x4F, 0x59, 0xE0, 0xE2, 0x3A, 0x31, 0x38, 0xCD, 0xEC, 0x86, 0x68, 0x35, 0x98, 0x88, 0x22, 0x8C, + 0x2F, 0x76, 0x00, 0x7E, 0xBE, 0x06, 0x18, 0xBC, 0x0B, 0x2B, 0xFB, 0x45, 0x04, 0xAE, 0x51, 0x4F, 0x8E, 0x65, 0xB9, 0x72, + 0x3F, 0x25, 0x57, 0x6E, 0x51, 0x28, 0xC6, 0xD3, 0xFB, 0xAD, 0x07, 0xCA, 0xA4, 0x38, 0x01, 0x9F, 0xEC, 0xAA, 0x1B, 0x6A, + 0x50, 0x75, 0xA6, 0x4D, 0x44, 0xEA, 0x1C, 0x2C, 0xDD, 0x89, 0x29, 0xAA, 0x30, 0x74, 0xFE, 0xE4, 0xF4, 0xEA, 0x6A, 0x1F, + 0x94, 0x12, 0x00, 0xBD, 0xEA, 0xD9, 0xA8, 0xC0, 0xA2, 0x44, 0x8F, 0xAE, 0x73, 0x57, 0x35, 0x98, 0xE7, 0x0A, 0x5B, 0x2C, + 0x4F, 0x8E, 0xFB, 0xBB, 0x35, 0xB0, 0x54, 0x61, 0xA3, 0x14, 0xAA, 0x9B, 0x99, 0xBA, 0x61, 0x3A, 0x43, 0x84, 0xEA, 0x78, + 0x03, 0xE3, 0xF5, 0xCE, 0x62, 0xF7, 0xDA, 0x3E, 0x16, 0xA7, 0x24, 0xD2, 0xA5, 0x5F, 0xF0, 0x88, 0x58, 0x0D, 0x54, 0x93, + 0x4D, 0x32, 0x3D, 0x6F, 0xBE, 0x52, 0x46, 0xBD, 0xA6, 0xFE, 0x4D, 0xC7, 0xAB, 0x7E, 0x5D, 0xE3, 0xAF, 0x5C, 0x63, 0x2C, + 0x11, 0x03, 0x4D, 0xC3, 0xED, 0x8E, 0xBB, 0xEB, 0x92, 0xF0, 0x55, 0xF2, 0x02, 0x39, 0xD5, 0xE3, 0x99, 0x4E, 0x23, 0x7F, + 0x66, 0xA1, 0x3B, 0xA6, 0x0D, 0xEB, 0xDE, 0x8A, 0xDD, 0x5F, 0x80, 0x4D, 0x57, 0x4F, 0xFB, 0x2B, 0xB0, 0x43, 0x98, 0x70, + 0x9D, 0x43, 0x93, 0x64, 0x01, 0x0C, 0x92, 0x27, 0xD7, 0xA1, 0xAA, 0x41, 0x53, 0xB4, 0x82, 0x0E, 0xB7, 0xF1, 0x24, 0xFD, + 0x43, 0x82, 0xDB, 0x3B, 0x5F, 0x41, 0x92, 0x1A, 0xE2, 0x33, 0xD3, 0x6B, 0x1F, 0x01, 0x55, 0xB4, 0x5C, 0x9C, 0xAD, 0xD7, + 0xB1, 0x9F, 0x05, 0x40, 0xDB, 0x7E, 0xC3, 0x0B, 0x7C, 0x3D, 0x37, 0x31, 0x54, 0xD6, 0x35, 0xB6, 0xB6, 0xA2, 0xB4, 0xD7, + 0x0A, 0x96, 0x7B, 0x87, 0x52, 0x01, 0x52, 0x1B, 0x65, 0x6A, 0x39, 0x49, 0xC2, 0x3C, 0xBC, 0xC7, 0x93, 0xDF, 0x2C, 0xCA, + 0x71, 0xDD, 0xF3, 0x99, 0xA5, 0x04, 0xED, 0xBE, 0x39, 0x1B, 0xE3, 0x5B, 0xE7, 0x06, 0x6B, 0x95, 0x01, 0x7D, 0x53, 0x7A, + 0x2A, 0x61, 0xCD, 0x3D, 0x5E, 0xE4, 0xFB, 0x80, 0x81, 0x98, 0x45, 0x88, 0x54, 0x7C, 0x92, 0xF4, 0x8F, 0xFD, 0x4C, 0x0C, + 0x74, 0x53, 0xFF, 0x45, 0x5B, 0xD8, 0xB0, 0x1F, 0x7A, 0x19, 0xD6, 0x92, 0xD4, 0xD6, 0x08, 0xBD, 0x81, 0x9C, 0x41, 0x42, + 0x6D, 0x9B, 0x61, 0xCD, 0x4F, 0xF0, 0x98, 0x69, 0x88, 0x07, 0xB1, 0xED, 0x93, 0x9F, 0x84, 0x13, 0x10, 0x69, 0x81, 0x51, + 0xFA, 0x1B, 0x2E, 0xE5, 0x0A, 0x8B, 0x04, 0xBC, 0x1A, 0x97, 0xBF, 0x93, 0x31, 0xE8, 0xBC, 0x78, 0x3F, 0xDB, 0x2E, 0x4E, + 0x28, 0x7D, 0xFC, 0xCC, 0xAC, 0xB4, 0x77, 0x99, 0x00, 0x93, 0xD6, 0xD2, 0x78, 0xD4, 0x08, 0x16, 0xC4, 0xB5, 0x2A, 0x24, + 0xC2, 0xDF, 0xA8, 0x69, 0x0D, 0x70, 0x79, 0xC3, 0x80, 0x2D, 0xC6, 0x8C, 0x47, 0x2D, 0x2C, 0xB1, 0x1A, 0x53, 0x4B, 0xD0, + 0x61, 0x73, 0x4C, 0x9D, 0x5D, 0x75, 0x51, 0x63, 0x6D, 0x9F, 0x90, 0xAC, 0xC7, 0xFA, 0xAB, 0x7F, 0x83, 0x37, 0x0C, 0xF3, + 0x4E, 0xBE, 0x3A, 0xF3, 0x30, 0xBF, 0x91, 0x08, 0x16, 0x11, 0x2A, 0xC8, 0xC7, 0x0F, 0x6F, 0x5A, 0x82, 0xBF, 0xCC, 0x63, + 0x20, 0x63, 0x4E, 0xC3, 0x91, 0x20, 0x41, 0xF3, 0xE4, 0xBE, 0x74, 0x4B, 0x8B, 0xEA, 0x3F, 0xDC, 0x24, 0xEF, 0x41, 0xC5, + 0xD8, 0x60, 0x50, 0xC7, 0x40, 0x60, 0xA6, 0x0C, 0xA3, 0x62, 0x77, 0x38, 0x68, 0x2A, 0xD0, 0x67, 0xF2, 0x63, 0xF5, 0xAA, + 0xC0, 0xE3, 0xB9, 0xDF, 0xA4, 0x75, 0xC0, 0x86, 0x28, 0x07, 0x99, 0x47, 0xB3, 0xDB, 0x09, 0xB6, 0xE5, 0x05, 0x32, 0x17, + 0x0D, 0x2B, 0x10, 0xF4, 0x30, 0x6F, 0xC9, 0x2B, 0xB4, 0x64, 0xA7, 0x0E, 0x6D, 0x9A, 0x48, 0x0F, 0x9B, 0x3F, 0x15, 0x89, + 0x6B, 0x6C, 0x75, 0x27, 0x4F, 0x69, 0xAA, 0x1E, 0xAA, 0x4B, 0xD0, 0x16, 0xF3, 0x29, 0xF1, 0xB1, 0xFB, 0x45, 0x74, 0xAA, + 0xE4, 0x27, 0x03, 0x11, 0xBF, 0xE8, 0xA1, 0x47, 0x2C, 0x0B, 0x1A, 0x19, 0x63, 0x19, 0x7A, 0x0E, 0x46, 0x6A, 0xAD, 0xB3, + 0xEF, 0x4C, 0x9A, 0x20, 0x6B, 0xC6, 0x1D, 0x1D, 0x2B, 0x58, 0x32, 0x2D, 0x29, 0x66, 0xE2, 0xD0, 0xC2, 0x04, 0x22, 0x84, + 0xD9, 0x7B, 0x07, 0xF0, 0x8C, 0x09, 0x45, 0xDA, 0xAB, 0xA7, 0x11, 0x5B, 0xFB, 0x64, 0x2B, 0x14, 0x7F, 0x78, 0x08, 0x5E, + 0xBA, 0x17, 0x33, 0xDA, 0x5B, 0x0B, 0xF7, 0xAB, 0xDD, 0x43, 0x37, 0x4F, 0x13, 0x5A, 0x84, 0x1C, 0x0B, 0x4C, 0x7A, 0xB6, + 0x0A, 0x61, 0xF2, 0x98, 0xE2, 0x9F, 0xEC, 0xC1, 0x84, 0x93, 0x8A, 0xCD, 0x65, 0x63, 0x31, 0x7B, 0xBA, 0x43, 0xEE, 0x1A, + 0xF4, 0xE0, 0x6C, 0x1C, 0xF8, 0x90, 0x63, 0xF0, 0xB9, 0x80, 0xBC, 0x49, 0x92, 0x02, 0x2D, 0x6E, 0x6B, 0x11, 0xED, 0xC1, + 0xFE, 0x68, 0xF4, 0xCA, 0xAA, 0xA2, 0xAD, 0x1C, 0x72, 0x27, 0x8E, 0x48, 0x6A, 0xB0, 0x6F, 0x9F, 0xA8, 0x8A, 0x14, 0xBD, + 0x67, 0x0B, 0xDB, 0x6C, 0xEC, 0xFD, 0x10, 0x84, 0x40, 0x21, 0xC2, 0x4C, 0xAC, 0xBD, 0x74, 0x81, 0xC1, 0x90, 0x73, 0x6F, + 0xBE, 0x9C, 0x0C, 0x98, 0x0C, 0x13, 0x23, 0x2F, 0x12, 0x75, 0x8B, 0xE7, 0x5F, 0xB9, 0x41, 0x00, 0xF3, 0xC1, 0x97, 0x81, + 0xC2, 0x32, 0x39, 0x20, 0x0B, 0x1E, 0x0B, 0x6F, 0x92, 0x99, 0x45, 0x0E, 0xD2, 0x37, 0x17, 0x5A, 0x08, 0x39, 0xE4, 0xC9, + 0x63, 0x79, 0x84, 0x55, 0x4C, 0x78, 0x9D, 0xDE, 0x97, 0xC2, 0x32, 0x02, 0x46, 0x59, 0xC4, 0xD6, 0xBA, 0x7B, 0x76, 0x43, + 0x7C, 0x57, 0x5B, 0x32, 0x21, 0x78, 0x6F, 0xDC, 0x2B, 0x04, 0x96, 0xE9, 0x57, 0x88, 0x7F, 0x52, 0x83, 0xA9, 0x55, 0xBB, + 0x4D, 0x7B, 0xAE, 0xC6, 0x43, 0xE9, 0x42, 0x16, 0xD0, 0x4B, 0x8B, 0x3D, 0xA0, 0xD7, 0x9F, 0xD5, 0x14, 0x76, 0x07, 0xB1, + 0x93, 0xF8, 0xCA, 0x06, 0x77, 0xFA, 0xBE, 0x72, 0xA7, 0xCE, 0xFF, 0xFD, 0x33, 0x2E, 0x4E, 0xE9, 0x5B, 0xF3, 0x12, 0x5D, + 0x0D, 0x3B, 0xB6, 0x5F, 0xEB, 0x39, 0x69, 0x63, 0xD8, 0xBF, 0xE1, 0xC6, 0x4B, 0xB4, 0x0B, 0xB8, 0x70, 0x1D, 0x0F, 0x91, + 0x9B, 0x54, 0xCF, 0x90, 0x35, 0xB7, 0xAF, 0x57, 0xF8, 0x17, 0xC7, 0x85, 0xB0, 0x7B, 0x47, 0xBD, 0xCA, 0x3B, 0x8F, 0x19, + 0xFF, 0x64, 0x99, 0xFE, 0x08, 0xAD, 0x33, 0xCE, 0x8C, 0xDD, 0x86, 0x5D, 0xE6, 0xB7, 0x39, 0x30, 0x3A, 0x7E, 0xF6, 0x9A, + 0x08, 0x78, 0x05, 0x1F, 0xF6, 0x3D, 0x16, 0xC8, 0x40, 0xE4, 0xD9, 0x2F, 0x43, 0xB0, 0xE5, 0x07, 0x9F, 0x0C, 0x21, 0x14, + 0xE1, 0x30, 0xDC, 0xC5, 0x43, 0xC7, 0xC3, 0x8E, 0x4F, 0x9F, 0x29, 0xEE, 0x13, 0x51, 0xB7, 0xEF, 0xDD, 0x73, 0xCF, 0xFD, + 0x26, 0xB2, 0x99, 0xE5, 0x50, 0xAE, 0x59, 0xD5, 0x88, 0x57, 0x24, 0xBA, 0x25, 0x3E, 0x98, 0x91, 0x34, 0xCF, 0xA8, 0x86, + 0xF5, 0xEF, 0x32, 0xE4, 0x38, 0x4D, 0xCF, 0x54, 0x96, 0xE0, 0xD0, 0xFA, 0xC8, 0xCC, 0xBD, 0x92, 0x16, 0x61, 0x61, 0xF1, + 0xE0, 0x60, 0x3F, 0x71, 0x66, 0x4F, 0x60, 0x65, 0x46, 0x82, 0xF1, 0x2F, 0x88, 0xE0, 0xC9, 0x83, 0xB8, 0x90, 0x71, 0xB2, + 0xE3, 0xE8, 0x28, 0xB3, 0x68, 0x81, 0xF7, 0x6A, 0xD5, 0xEF, 0x28, 0xD5, 0x2C, 0xA9, 0x01, 0xA4, 0xED, 0xAC, 0xAF, 0xC6, + 0x48, 0x7F, 0xFA, 0x44, 0xA5, 0x79, 0x4E, 0xCE, 0x68, 0x1B, 0xAF, 0x06, 0x3D, 0x27, 0xCE, 0xA3, 0x72, 0xC6, 0x44, 0x25, + 0x10, 0x03, 0xD8, 0x82, 0xEF, 0x16, 0xE3, 0x9E, 0x45, 0xA8, 0x69, 0x4B, 0x80, 0x64, 0xFB, 0x45, 0x04, 0xE7, 0x2B, 0x03, + 0xBA, 0x69, 0x71, 0x43, 0x37, 0x49, 0x49, 0x7B, 0x08, 0x7A, 0xF1, 0x24, 0xC8, 0x2E, 0x07, 0x74, 0x66, 0x86, 0x99, 0x69, + 0xAC, 0xE8, 0x72, 0x33, 0x08, 0xC6, 0x76, 0x2A, 0x3C, 0xB9, 0x2A, 0x2E, 0xAD, 0x87, 0xF3, 0x48, 0x9E, 0xE8, 0x84, 0xEA, + 0x05, 0xC6, 0x3F, 0x1A, 0x35, 0x27, 0x58, 0x32, 0x4C, 0x09, 0x84, 0x42, 0x7E, 0xFB, 0x30, 0xCD, 0xF4, 0x91, 0x23, 0x2E, + 0x5F, 0xA9, 0x6A, 0xE8, 0x69, 0xA4, 0x4B, 0xDE, 0xA9, 0xBA, 0x2A, 0xEB, 0xFD, 0xC4, 0x6B, 0x8A, 0xD8, 0xA1, 0x01, 0xDD, + 0xA6, 0x32, 0xB7, 0xF3, 0xDB, 0x09, 0x04, 0x63, 0x6D, 0x88, 0xC2, 0xA4, 0xF7, 0x86, 0xDE, 0x82, 0x9A, 0x81, 0x92, 0x70, + 0x74, 0xE1, 0x6C, 0xDE, 0x41, 0x69, 0xB3, 0xDD, 0xBA, 0x72, 0x60, 0x78, 0xA4, 0xC2, 0x6A, 0x1C, 0xE4, 0x61, 0x1A, 0x37, + 0x1C, 0x86, 0xF9, 0x4D, 0x0C, 0xEF, 0x15, 0xAF, 0x27, 0xE4, 0x93, 0x71, 0x4A, 0xE1, 0x4B, 0xCA, 0xBC, 0x01, 0xEA, 0x98, + 0x3A, 0x50, 0x3A, 0x1D, 0xAE, 0xCB, 0xB1, 0x62, 0xB4, 0xE0, 0x04, 0x16, 0xD5, 0x3B, 0xAC, 0x83, 0x14, 0x61, 0xCB, 0xD0, + 0xB2, 0x0F, 0xA5, 0x55, 0x01, 0x9E, 0x2A, 0x6C, 0xD8, 0xFF, 0xCA, 0xBE, 0xDE, 0x68, 0x02, 0x73, 0x63, 0x33, 0x82, 0x6B, + 0x73, 0x13, 0x5D, 0x92, 0x44, 0x13, 0xE8, 0xC0, 0x5D, 0x6B, 0x99, 0xDC, 0x2E, 0x98, 0x8B, 0x63, 0x3E, 0xFB, 0xCE, 0xD3, + 0xBF, 0x88, 0xF5, 0x93, 0x32, 0x90, 0xE2, 0x73, 0xA5, 0x06, 0xB2, 0x77, 0xBD, 0xB1, 0xAC, 0x51, 0x07, 0x39, 0x08, 0xB5, + 0x4E, 0x32, 0xE7, 0x11, 0xE2, 0x59, 0xCC, 0x1A, 0x76, 0xE8, 0x24, 0x43, 0x21, 0x57, 0xEC, 0xF2, 0xB5, 0x99, 0xEC, 0x0C, + 0xCB, 0xD8, 0xC4, 0x09, 0xD2, 0x03, 0xAA, 0x47, 0xE8, 0x2E, 0x1A, 0xB4, 0xC6, 0x30, 0x27, 0xE0, 0x0D, 0xB2, 0xCA, 0xAD, + 0xE6, 0xB7, 0x95, 0x13, 0xA5, 0x8C, 0xE2, 0xB5, 0x40, 0xD2, 0xD1, 0x60, 0x99, 0x28, 0x02, 0x7F, 0x52, 0x71, 0xCE, 0xEC, + 0x4D, 0xB8, 0xF6, 0x2F, 0x15, 0xFA, 0x7A, 0x95, 0x6B, 0xC3, 0x74, 0x48, 0x7F, 0xC8, 0xD6, 0x12, 0x88, 0x38, 0x16, 0x64, + 0x2D, 0xF4, 0x76, 0x3E, 0x98, 0x96, 0x12, 0x2D, 0x4D, 0x56, 0x3F, 0x87, 0xCF, 0xDA, 0x61, 0x3E, 0x8F, 0x34, 0x5E, 0x2F, + 0xAA, 0x65, 0x89, 0xD3, 0xDD, 0x5A, 0x3E, 0x7D, 0x2D, 0xA9, 0xD0, 0xD8, 0x40, 0x0D, 0x3E, 0xC4, 0x4A, 0xD8, 0x24, 0xCC, + 0x88, 0xF0, 0x8C, 0xAC, 0x46, 0x8D, 0xDE, 0x31, 0x1A, 0xA7, 0xCD, 0x79, 0x18, 0x03, 0xF6, 0x10, 0xF1, 0x41, 0x68, 0x9A, + 0x3F, 0x36, 0xD6, 0x81, 0x98, 0xAD, 0x64, 0xF8, 0xDC, 0x80, 0x9E, 0xFC, 0x02, 0xF0, 0x9F, 0xAD, 0x23, 0x18, 0xEC, 0xAD, + 0x41, 0xDB, 0x9B, 0x84, 0x30, 0x03, 0x10, 0x95, 0x28, 0xBF, 0xF0, 0xDE, 0x8B, 0x12, 0x50, 0x39, 0x9B, 0xA4, 0x65, 0xF9, + 0x7D, 0x9E, 0x00, 0x03, 0xFF, 0x64, 0x00, 0xF9, 0x14, 0x42, 0xC3, 0x86, 0x9D, 0x6A, 0x2A, 0xC8, 0xDA, 0x0F, 0xC9, 0x75, + 0x56, 0x10, 0x36, 0x38, 0x69, 0x0C, 0x44, 0x72, 0x32, 0x03, 0xAC, 0xD2, 0x65, 0x47, 0x23, 0xD6, 0xFD, 0x9C, 0x05, 0x42, + 0x0F, 0x43, 0xB9, 0xE5, 0xD6, 0x39, 0x71, 0x62, 0xB8, 0x4D, 0xD1, 0xA1, 0x80, 0xA9, 0x1B, 0xBA, 0x6A, 0x47, 0xD0, 0x30, + 0x34, 0x28, 0x35, 0x7A, 0x60, 0xC3, 0xE1, 0xDD, 0x98, 0x2E, 0x43, 0x48, 0xA3, 0x9B, 0xA0, 0x03, 0x15, 0x2B, 0x68, 0x9F, + 0xCF, 0xE9, 0xD6, 0x22, 0x38, 0x9F, 0x4B, 0x99, 0x05, 0xBF, 0x64, 0x90, 0xB2, 0x2C, 0x3A, 0x70, 0x42, 0x57, 0x60, 0xA4, + 0x0F, 0x9A, 0xF5, 0x23, 0x79, 0x44, 0x7E, 0xA5, 0x88, 0x20, 0xC2, 0xFE, 0x2B, 0xF7, 0x2E, 0x41, 0xE1, 0xA1, 0x02, 0x4F, + 0xBF, 0xF3, 0x0D, 0xD7, 0x16, 0x77, 0xB1, 0xEC, 0xC5, 0xD7, 0x02, 0x75, 0xE0, 0x13, 0x38, 0xB8, 0x8D, 0xA7, 0x06, 0x08, + 0x4B, 0x5C, 0x6A, 0x4A, 0xC5, 0xCE, 0x6B, 0x24, 0xFD, 0x17, 0x1C, 0x7A, 0x69, 0xE7, 0x32, 0x8C, 0xBE, 0x2D, 0x24, 0x61, + 0xEE, 0x59, 0xC8, 0xC3, 0xAE, 0x07, 0xA7, 0x2D, 0x61, 0x1B, 0x6B, 0x90, 0xAB, 0x4B, 0x93, 0x0D, 0xFB, 0x12, 0x81, 0x4B, + 0x27, 0x37, 0x75, 0x1F, 0x68, 0x88, 0x8D, 0xF5, 0xB5, 0xA0, 0x25, 0x65, 0x6E, 0x0A, 0xFB, 0x7E, 0x88, 0x66, 0x51, 0xCC, + 0x5A, 0xCE, 0xFA, 0x5C, 0xB9, 0x21, 0x1F, 0xEC, 0x1A, 0x5C, 0x6A, 0x96, 0x4A, 0x21, 0x35, 0xDC, 0x17, 0x54, 0xC9, 0x2E, + 0x99, 0x41, 0x22, 0xFC, 0x57, 0x14, 0x61, 0xD9, 0x91, 0x60, 0x7B, 0xB3, 0x26, 0x03, 0x2F, 0xDF, 0xD2, 0x26, 0xE8, 0x8B, + 0x66, 0xB3, 0xAC, 0xE9, 0xD2, 0x42, 0x8B, 0x80, 0xD8, 0xDB, 0x03, 0xBF, 0x1B, 0x0F, 0x9B, 0x61, 0x8D, 0x92, 0xA4, 0x87, + 0xE8, 0xEF, 0xD5, 0x31, 0x83, 0x51, 0x63, 0xC4, 0x34, 0x1C, 0xEB, 0xD2, 0x4E, 0x8F, 0xEC, 0x83, 0x8D, 0x7F, 0x6E, 0x0C, + 0xA3, 0x3D, 0xD4, 0x90, 0xB8, 0xB4, 0xA8, 0xCF, 0xC2, 0x10, 0x9D, 0xD2, 0xCE, 0xF0, 0x65, 0xC2, 0xF1, 0x1F, 0xB4, 0x01, + 0xE0, 0xFC, 0x85, 0x5E, 0x15, 0x5D, 0xCC, 0xED, 0x55, 0x2D, 0x80, 0xF3, 0x63, 0x13, 0xB7, 0x6E, 0x4D, 0x22, 0x22, 0x4D, + 0xE1, 0xF2, 0x23, 0x4A, 0x44, 0xF0, 0x55, 0x22, 0xCB, 0xEC, 0xD4, 0x59, 0x66, 0x99, 0xAB, 0x08, 0xE6, 0x99, 0x2B, 0x23, + 0xEC, 0xA9, 0x44, 0xE1, 0x17, 0x57, 0x6C, 0xA2, 0x10, 0x25, 0xE7, 0x12, 0xE4, 0xA7, 0x83, 0x92, 0x80, 0x65, 0x37, 0xC5, + 0xBE, 0x9D, 0x09, 0x25, 0xEA, 0x2D, 0xAE, 0x9C, 0xC3, 0xD6, 0x34, 0x25, 0xB4, 0x6D, 0xCC, 0xB2, 0x02, 0x9F, 0x94, 0xF0, + 0x16, 0x3E, 0x04, 0x34, 0x46, 0xA8, 0x65, 0x0E, 0x0E, 0xC1, 0x96, 0x0A, 0xA8, 0xA0, 0x46, 0xB5, 0x08, 0x3E, 0xC3, 0x57, + 0x9D, 0xFB, 0x69, 0x52, 0xFA, 0x54, 0x9E, 0x1A, 0xA0, 0x61, 0x3A, 0xE3, 0x9A, 0x82, 0x08, 0x90, 0xDA, 0x14, 0xA6, 0x47, + 0xF6, 0x8F, 0x3F, 0x59, 0xA4, 0xE5, 0xAB, 0xC0, 0x4D, 0x35, 0xC6, 0x8D, 0x8B, 0xF0, 0x98, 0xCF, 0x0B, 0x1F, 0x37, 0x67, + 0x05, 0x16, 0x8B, 0xA2, 0x89, 0x79, 0x8F, 0x46, 0x1C, 0x14, 0xA4, 0x23, 0xF8, 0x89, 0x66, 0x2A, 0x62, 0x4D, 0x42, 0x48, + 0x6D, 0xDF, 0x4C, 0xE9, 0x4B, 0x8C, 0xED, 0x9C, 0xFA, 0x63, 0xCF, 0x9F, 0xD6, 0x12, 0x33, 0x30, 0x3B, 0x90, 0x46, 0xC9, + 0x82, 0xD7, 0xD6, 0x7D, 0x59, 0xDE, 0x27, 0x8A, 0xB7, 0x5C, 0x57, 0x25, 0x58, 0x73, 0x37, 0xAE, 0xED, 0x53, 0x6C, 0x9D, + 0x7A, 0x68, 0x2F, 0x9A, 0xF2, 0x5D, 0x40, 0x3D, 0xF7, 0x24, 0x07, 0xE9, 0x02, 0x6E, 0x5C, 0x15, 0x49, 0x32, 0x88, 0xF1, + 0x88, 0xC1, 0x24, 0xE0, 0x7F, 0xF1, 0x4E, 0x25, 0xE5, 0x6F, 0x57, 0xA4, 0xDD, 0x98, 0x28, 0x2C, 0x33, 0x74, 0x96, 0x4B, + 0x74, 0x81, 0x6A, 0x16, 0xD8, 0x3C, 0x78, 0x3B, 0x60, 0x5D, 0x1F, 0xCF, 0x7F, 0x19, 0x26, 0x75, 0x7F, 0x93, 0xE5, 0x04, + 0x65, 0x6D, 0x89, 0xB9, 0xD5, 0x70, 0xFC, 0x17, 0x8D, 0xED, 0xF1, 0x13, 0x1C, 0xB6, 0x94, 0x7D, 0x30, 0x9F, 0x04, 0x6C, + 0x04, 0xBE, 0x77, 0x5D, 0x72, 0x31, 0xDA, 0xC4, 0x93, 0xF4, 0x08, 0x45, 0xBB, 0xCB, 0x30, 0x76, 0x0C, 0xFF, 0x7B, 0x6C, + 0x3B, 0xC7, 0xD0, 0x27, 0x27, 0xAC, 0x21, 0x74, 0xA2, 0x87, 0x40, 0x8D, 0xD8, 0x13, 0xF2, 0x79, 0xFE, 0x73, 0x99, 0xC5, + 0x1B, 0xCC, 0x77, 0x4B, 0x6E, 0xF5, 0xD9, 0x01, 0x25, 0xF6, 0xF6, 0x76, 0x7A, 0x8E, 0xEF, 0x24, 0xA7, 0xA8, 0xF8, 0xB8, + 0x3A, 0xC8, 0xC2, 0xE9, 0xD4, 0x07, 0xD9, 0x75, 0x64, 0x85, 0x9C, 0xCB, 0x3F, 0xE8, 0x08, 0xC1, 0xFF, 0x89, 0x99, 0xAA, + 0x54, 0xC4, 0x0C, 0xD6, 0xAE, 0x0C, 0xBB, 0xF6, 0x8F, 0xE4, 0x95, 0xD8, 0xE1, 0x34, 0x07, 0xA1, 0xA2, 0xB4, 0xDC, 0x75, + 0xA8, 0x37, 0x8F, 0x25, 0x7D, 0x05, 0x8B, 0xD4, 0xDC, 0x87, 0x73, 0x37, 0xBB, 0x86, 0x3D, 0xB6, 0x72, 0x26, 0x54, 0x6C, + 0xAD, 0xC7, 0x43, 0x1F, 0xAD, 0x4B, 0x58, 0xBD, 0x54, 0x93, 0xBC, 0xCE, 0x5E, 0x42, 0x0A, 0xD3, 0xFF, 0xAA, 0x4C, 0x43, + 0x0F, 0xC8, 0x5E, 0x15, 0xC0, 0x71, 0x30, 0x1A, 0x67, 0xDC, 0x2D, 0x5B, 0xF6, 0xBC, 0xFE, 0x3F, 0x7F, 0xCF, 0x01, 0x5A, + 0x6C, 0x86, 0x7B, 0x37, 0xC6, 0xBF, 0xC7, 0x13, 0x3D, 0xAD, 0x0D, 0x43, 0x33, 0xC7, 0x12, 0x2F, 0xD2, 0x15, 0xAB, 0x57, + 0x26, 0x22, 0x93, 0xFF, 0x99, 0x2D, 0x1B, 0x38, 0xDA, 0xC2, 0x43, 0x81, 0xCF, 0xA2, 0xDB, 0xA6, 0xDB, 0x9D, 0xB3, 0xAE, + 0xB6, 0x9C, 0x35, 0xDD, 0xC3, 0x91, 0x74, 0xBE, 0x35, 0xFA, 0x80, 0x0D, 0xD4, 0x17, 0x13, 0x74, 0xC9, 0xA0, 0x9C, 0x41, + 0xE9, 0x4C, 0x43, 0xD8, 0xA7, 0x2E, 0x5E, 0xA4, 0x05, 0x2D, 0xAA, 0xF9, 0x17, 0xD7, 0x4B, 0xA5, 0x05, 0x51, 0x74, 0xE0, + 0x49, 0x44, 0x2D, 0xB7, 0x6F, 0xF0, 0x6D, 0x07, 0x41, 0xF1, 0x45, 0x97, 0x67, 0xF7, 0xE4, 0xE6, 0xF3, 0x83, 0xE5, 0x85, + 0xDB, 0x9B, 0x6B, 0xA0, 0x81, 0xA4, 0x6C, 0x7B, 0x6B, 0xC5, 0xF6, 0x17, 0xD5, 0xE4, 0xED, 0x19, 0xDA, 0x9A, 0xB5, 0x3E, + 0xAB, 0xF8, 0x44, 0x0C, 0xA6, 0xB7, 0x84, 0xF4, 0x73, 0xB9, 0xA5, 0xDB, 0x61, 0xD4, 0x5D, 0x28, 0xB0, 0xCE, 0x7D, 0x61, + 0x66, 0x7D, 0xC7, 0x65, 0x77, 0xA6, 0x6B, 0xFF, 0xEF, 0xC6, 0x96, 0xDF, 0x12, 0x08, 0xB9, 0x23, 0xEB, 0xD4, 0xAB, 0x1F, + 0x19, 0xBA, 0x18, 0x2E, 0x4D, 0x9C, 0x23, 0xE2, 0xB1, 0x3E, 0xBD, 0xC8, 0x4D, 0x98, 0xF6, 0xF5, 0xC1, 0x44, 0x96, 0x60, + 0x3D, 0xD4, 0xE6, 0xD2, 0xB0, 0xFB, 0x00, 0x7F, 0x4E, 0xF8, 0xBA, 0x79, 0x88, 0xF6, 0x5E, 0xAF, 0x9F, 0x82, 0xE2, 0xF1, + 0x7E, 0xBA, 0x0B, 0x12, 0x69, 0x28, 0x9C, 0xC1, 0x2D, 0xB8, 0x50, 0x9F, 0xA5, 0xF5, 0xAC, 0xCF, 0xBE, 0x0B, 0x66, 0xBD, + 0x08, 0xD0, 0x0B, 0xC0, 0x5E, 0xB9, 0x06, 0xC8, 0x61, 0x91, 0x4A, 0x4A, 0x23, 0xB8, 0x4E, 0x6E, 0x61, 0xCD, 0xF4, 0x1F, + 0xDD, 0xEC, 0x89, 0xA9, 0x13, 0x1B, 0xD5, 0x50, 0x3C, 0xED, 0x24, 0xFB, 0xCC, 0x91, 0xBE, 0xEF, 0x79, 0xCF, 0x98, 0x8C, + 0x47, 0x0F, 0xEF, 0xC2, 0x47, 0xC8, 0x0F, 0x69, 0x63, 0x94, 0xC5, 0x10, 0xDA, 0xFD, 0x6F, 0x1B, 0xF7, 0xFA, 0xB6, 0x64, + 0x1A, 0xB4, 0xB8, 0xF9, 0xA7, 0x52, 0xD4, 0xB9, 0xFD, 0xBE, 0x50, 0x29, 0x58, 0x42, 0xE0, 0x47, 0x89, 0x2F, 0xDB, 0x11, + 0xFC, 0xDA, 0xE9, 0xA6, 0xD5, 0xBA, 0x49, 0x63, 0x70, 0x86, 0x70, 0xFC, 0x26, 0x63, 0xC7, 0x12, 0x36, 0x14, 0xD7, 0x56, + 0x87, 0x69, 0x48, 0xC9, 0xA0, 0x72, 0xD8, 0xF0, 0x37, 0x32, 0xA0, 0xEC, 0x21, 0xFD, 0xA9, 0xBA, 0x52, 0x2E, 0x89, 0x15, + 0x01, 0x21, 0x0C, 0x16, 0x1E, 0x38, 0xD9, 0xE5, 0x83, 0x2D, 0x9F, 0x47, 0x53, 0x4F, 0x1F, 0x20, 0x71, 0x21, 0x44, 0x58, + 0x14, 0x74, 0x48, 0x4C, 0xAB, 0x2E, 0x28, 0x40, 0x54, 0x14, 0x36, 0x90, 0x81, 0x69, 0x14, 0xA0, 0x53, 0xA8, 0x66, 0xB5, + 0x60, 0x25, 0xB9, 0x53, 0xF2, 0x9A, 0x81, 0x81, 0x75, 0x8B, 0xB1, 0x05, 0x8A, 0x3D, 0x33, 0x60, 0xC1, 0xC7, 0xBB, 0xA5, + 0xD6, 0x42, 0x50, 0xB3, 0x85, 0xC6, 0xA9, 0x17, 0x6E, 0x28, 0xE6, 0x11, 0x8B, 0x44, 0x62, 0xB2, 0x0D, 0x6F, 0x12, 0x0D, + 0x04, 0x4A, 0x64, 0x88, 0x0C, 0x4F, 0x4B, 0xAA, 0x4E, 0x18, 0xBF, 0xCE, 0x5E, 0x22, 0xCA, 0xDD, 0x29, 0x08, 0xD2, 0x18, + 0x9C, 0xFB, 0xFE, 0x5E, 0xBE, 0x59, 0x5A, 0xC0, 0x57, 0x2B, 0xCF, 0x9B, 0x0D, 0x6A, 0x8B, 0x19, 0x71, 0x40, 0xE7, 0x69, + 0xE0, 0x51, 0x29, 0xA9, 0x93, 0x27, 0x1E, 0x0D, 0x8F, 0x91, 0xEB, 0x1F, 0xE4, 0x26, 0xA3, 0xC6, 0xFA, 0x3F, 0xDC, 0x61, + 0x38, 0x6D, 0x04, 0xCC, 0x0C, 0xE5, 0x9B, 0xA9, 0xFF, 0xA6, 0x44, 0x6C, 0xC2, 0x56, 0x52, 0x6F, 0xC8, 0x77, 0x12, 0x49, + 0x2B, 0xDF, 0xD2, 0x59, 0xE5, 0xAD, 0x42, 0x7D, 0x78, 0xD6, 0xFE, 0xF6, 0x7B, 0xAC, 0xEB, 0x7D, 0x63, 0xF6, 0x44, 0xB2, + 0xFB, 0x6E, 0x0A, 0x6F, 0x2F, 0xB1, 0xE7, 0x0B, 0xFB, 0x2E, 0xCB, 0xAA, 0x84, 0x14, 0x49, 0xDF, 0x1A, 0xD2, 0xA3, 0x0A, + 0xC4, 0xC6, 0x5B, 0x7E, 0x49, 0x2D, 0x15, 0x04, 0x40, 0x6F, 0x98, 0x00, 0x2C, 0x08, 0x6C, 0xD2, 0x8B, 0xA8, 0xF4, 0xA6, + 0x25, 0x7D, 0x17, 0x22, 0x61, 0x63, 0xD5, 0xF2, 0xEF, 0x23, 0x1D, 0xD6, 0x52, 0xEA, 0xD6, 0x29, 0x51, 0x7C, 0xC5, 0x89, + 0xA0, 0xBF, 0x45, 0x88, 0x03, 0x29, 0x4C, 0x3F, 0x45, 0xAD, 0x6A, 0x20, 0xFE, 0x10, 0x53, 0x50, 0x21, 0xB8, 0x35, 0x0B, + 0xB0, 0x53, 0xB2, 0x57, 0xF1, 0xAE, 0xD9, 0x31, 0xD2, 0x73, 0x9A, 0x26, 0x32, 0x5B, 0xC2, 0xBB, 0x53, 0x54, 0x34, 0xA6, + 0x39, 0x5B, 0xCC, 0xE0, 0xFA, 0x6E, 0x5C, 0xD0, 0x25, 0x74, 0x74, 0xC4, 0x94, 0x33, 0x04, 0x74, 0x7F, 0xBB, 0x9C, 0x70, + 0x6F, 0x66, 0x85, 0x78, 0xB2, 0x54, 0x9D, 0x7D, 0x81, 0x00, 0xE1, 0x03, 0x60, 0x52, 0x8C, 0x00, 0x17, 0x7D, 0xA6, 0x55, + 0x91, 0x17, 0xED, 0x35, 0x12, 0xC8, 0x55, 0xFC, 0x61, 0x53, 0x66, 0x71, 0xE7, 0x60, 0xCE, 0x88, 0x57, 0x11, 0xBC, 0x7F, + 0x65, 0x7A, 0xEE, 0xAA, 0x0E, 0x43, 0xCF, 0x4C, 0x9D, 0x71, 0x61, 0xEB, 0x26, 0x12, 0xD7, 0x3A, 0x9C, 0xC6, 0x47, 0x41, + 0x6F, 0xC9, 0x92, 0xC8, 0x4A, 0xD2, 0xDC, 0xAA, 0xAE, 0x99, 0x02, 0xA5, 0xBB, 0x69, 0xE7, 0xCF, 0x9F, 0x5A, 0x91, 0x0D, + 0xFE, 0x3A, 0x8E, 0x1D, 0xB5, 0x0A, 0x23, 0x75, 0x69, 0x76, 0x70, 0x3D, 0xF5, 0x4A, 0x2D, 0x6D, 0xCE, 0x5E, 0x86, 0x15, + 0xC2, 0x1F, 0x7E, 0x0B, 0xE4, 0x36, 0x8A, 0x8A, 0x95, 0x81, 0xDE, 0xF9, 0x49, 0x17, 0xF6, 0x48, 0x8C, 0x50, 0x55, 0xA6, + 0xB9, 0x11, 0x3F, 0x10, 0x44, 0x90, 0xFE, 0x8E, 0xF9, 0x31, 0x53, 0xD0, 0x99, 0xE5, 0xD0, 0xBF, 0x45, 0x7C, 0xB0, 0xA9, + 0xEE, 0x7A, 0x0D, 0x6D, 0xFC, 0xEE, 0x17, 0xC8, 0x2E, 0x3E, 0x5C, 0xBF, 0xC7, 0x30, 0x2D, 0xF8, 0xBF, 0x1D, 0x90, 0x1F, + 0x57, 0x70, 0x12, 0x06, 0x57, 0x13, 0xB8, 0xE6, 0x12, 0xD0, 0x88, 0xD8, 0x54, 0x8D, 0x98, 0x5C, 0xF7, 0xA2, 0xF1, 0x31, + 0x3A, 0x88, 0x58, 0x51, 0x13, 0xD1, 0x18, 0xD8, 0xB4, 0x48, 0xE2, 0x54, 0x77, 0x0C, 0xFA, 0x90, 0xFB, 0x8B, 0xB0, 0xC7, + 0xE4, 0xB9, 0x4E, 0xBC, 0x31, 0x4B, 0x6B, 0x07, 0x56, 0xE6, 0x77, 0x52, 0x8D, 0x28, 0x7A, 0xE7, 0x15, 0xE1, 0x19, 0xB9, + 0xC4, 0xA3, 0x7D, 0xB5, 0x14, 0x62, 0x3B, 0x24, 0x45, 0x8B, 0xD8, 0x56, 0xB5, 0xBF, 0x74, 0x02, 0x42, 0xED, 0xF3, 0x69, + 0x55, 0xA4, 0x10, 0xB4, 0xA2, 0x0F, 0xEE, 0xD2, 0x03, 0xA2, 0x32, 0x90, 0x66, 0x85, 0x78, 0x9E, 0x36, 0x6E, 0x79, 0x4F, + 0x23, 0x07, 0x3D, 0x31, 0x74, 0x26, 0x03, 0x8B, 0xE9, 0x0B, 0xD5, 0xED, 0xBD, 0x1E, 0xEE, 0xBB, 0x03, 0x48, 0xE1, 0x5E, + 0x15, 0xAB, 0x5D, 0xBB, 0xF4, 0xAC, 0xFF, 0x91, 0xE4, 0xD1, 0xAA, 0x28, 0x77, 0x81, 0x23, 0xA0, 0x1D, 0xC8, 0x22, 0x9A, + 0x04, 0x65, 0x8A, 0xDD, 0x07, 0x65, 0xDB, 0x9E, 0x14, 0xBF, 0x25, 0xAC, 0x19, 0x4B, 0x5A, 0x79, 0x31, 0xC4, 0x7A, 0xD3, + 0x1A, 0x64, 0x78, 0x84, 0x8A, 0x79, 0xB3, 0xBF, 0xCE, 0x07, 0x2C, 0x99, 0x5C, 0xB8, 0xD3, 0x6C, 0xAC, 0xE5, 0xF4, 0x1A, + 0x8B, 0x7A, 0xF2, 0xF7, 0x38, 0x0A, 0x63, 0x3E, 0xAE, 0x8B, 0x44, 0xBB, 0xF5, 0x13, 0x5C, 0x8F, 0x2D, 0x2C, 0x5D, 0x2C, + 0x91, 0x2A, 0xC8, 0x8A, 0x1E, 0x8E, 0xA8, 0x91, 0xD6, 0x6A, 0xEF, 0x29, 0x52, 0x0A, 0xA3, 0xB6, 0x30, 0x60, 0x23, 0x9F, + 0x28, 0xED, 0x7A, 0x7D, 0xCD, 0xF6, 0x3A, 0x4D, 0x6B, 0x87, 0xE5, 0x0F, 0x9A, 0x8A, 0xF2, 0xC9, 0xCD, 0x2E, 0xAA, 0x97, + 0x7B, 0xE5, 0xEB, 0x4F, 0x6E, 0x94, 0x14, 0x2F, 0x97, 0xA6, 0xBB, 0x63, 0x4F, 0x42, 0x27, 0x09, 0x9C, 0x1F, 0x6C, 0x93, + 0xC5, 0x6F, 0x43, 0x76, 0xB4, 0xF2, 0x7C, 0x97, 0xE9, 0x6D, 0x69, 0xC6, 0xA9, 0x8D, 0xA1, 0x71, 0x07, 0xD3, 0xBC, 0x26, + 0x59, 0x1C, 0x27, 0x38, 0x64, 0xB1, 0xDC, 0xB4, 0x72, 0xFC, 0xE5, 0x5E, 0xF4, 0xD0, 0x24, 0x29, 0xB5, 0xD2, 0xD2, 0x53, + 0x64, 0xCD, 0x1A, 0xF9, 0x41, 0x2E, 0xA9, 0x17, 0xF6, 0x00, 0x22, 0x25, 0xBD, 0xF2, 0x2D, 0x03, 0xF3, 0x7E, 0xC2, 0x4F, + 0xF5, 0x57, 0xA4, 0x8F, 0xF0, 0xD6, 0x84, 0x85, 0x4E, 0xB9, 0xF5, 0x40, 0x67, 0xE4, 0x94, 0xE4, 0x59, 0xF9, 0xE3, 0xA2, + 0x2F, 0x9C, 0xB0, 0xB4, 0xC8, 0xD9, 0x46, 0x70, 0xE6, 0x28, 0x50, 0x69, 0x76, 0xB5, 0xFA, 0x8B, 0x82, 0x3B, 0x36, 0x25, + 0x34, 0xB2, 0x2C, 0x06, 0x81, 0x96, 0x0A, 0x0F, 0x6C, 0xBB, 0x6B, 0xA1, 0x94, 0xFC, 0x8D, 0x94, 0xC3, 0xBA, 0x05, 0x1B, + 0xC8, 0x1A, 0xD9, 0x7D, 0xC4, 0x9C, 0xE6, 0x87, 0x53, 0xDA, 0xC6, 0xC8, 0x6B, 0xB5, 0xB9, 0x4A, 0x2A, 0xDE, 0x7B, 0x92, + 0xB4, 0x62, 0xCB, 0x3A, 0x4F, 0xF9, 0x06, 0x47, 0x9C, 0x3A, 0x46, 0xD8, 0x4E, 0xB9, 0x65, 0x9D, 0x02, 0xF0, 0x24, 0x1D, + 0xAA, 0x61, 0xB1, 0xEE, 0x1F, 0xBC, 0x1B, 0x96, 0x4D, 0x58, 0x20, 0x2B, 0xFF, 0xF2, 0xEF, 0x36, 0x7D, 0xD9, 0xAF, 0x7D, + 0xBB, 0xCB, 0x61, 0xE6, 0xE5, 0x56, 0x0A, 0x67, 0x49, 0x81, 0x9C, 0xEE, 0x1D, 0xB9, 0x01, 0x4C, 0xB7, 0x0D, 0x04, 0xEE, + 0x76, 0x9E, 0x4C, 0x5C, 0x7C, 0xBE, 0x6A, 0x1A, 0x05, 0x86, 0xEB, 0x2F, 0x62, 0xFD, 0x27, 0x1F, 0x08, 0xBD, 0x3E, 0xF2, + 0xCD, 0xF7, 0xDF, 0x34, 0x21, 0x18, 0xDF, 0x5D, 0xBE, 0xB6, 0xF6, 0x49, 0xED, 0x5E, 0x37, 0xE2, 0xCC, 0x23, 0x18, 0xBD, + 0xCE, 0x3F, 0xB6, 0x54, 0xDC, 0x40, 0x26, 0x1E, 0x0A, 0x58, 0xFA, 0x17, 0xD0, 0x34, 0x10, 0x72, 0x82, 0x0C, 0x44, 0x5A, + 0x1E, 0x3E, 0xA8, 0xDF, 0x61, 0xC2, 0x5E, 0x91, 0x98, 0x7A, 0xB2, 0xA2, 0x21, 0xB1, 0xA4, 0xDB, 0x72, 0x8B, 0x9F, 0xC1, + 0x1C, 0x01, 0xBE, 0xE0, 0x6B, 0xC5, 0xBE, 0xE3, 0xB3, 0x69, 0xFC, 0xA5, 0x31, 0x62, 0xD1, 0x39, 0x5C, 0x4A, 0x43, 0x36, + 0x9B, 0x71, 0xC9, 0x1C, 0xB3, 0xDE, 0x9F, 0x28, 0x22, 0x6E, 0xA6, 0x61, 0xC2, 0x0C, 0xD4, 0x99, 0x19, 0x39, 0x18, 0x95, + 0xEB, 0xC7, 0x7B, 0x34, 0x92, 0x8B, 0xC7, 0x68, 0xC2, 0xE4, 0xF0, 0x8E, 0xA7, 0xED, 0xDC, 0x23, 0x79, 0x47, 0xE8, 0xC7, + 0xB0, 0x64, 0x9C, 0xBA, 0xF8, 0x46, 0xB2, 0x07, 0x58, 0x2A, 0xAD, 0xD3, 0x8A, 0x0C, 0xB9, 0xCD, 0x37, 0xAF, 0xFA, 0x26, + 0xCC, 0x9A, 0xF1, 0xEF, 0xF6, 0x7D, 0x4A, 0x2D, 0x6A, 0x94, 0x09, 0x45, 0xFC, 0x3C, 0x61, 0xE9, 0xA0, 0xED, 0xD8, 0x06, + 0xD4, 0x28, 0xC2, 0x04, 0xBA, 0x00, 0xDA, 0x08, 0x91, 0x56, 0x4B, 0xA3, 0x2B, 0x97, 0x47, 0x5F, 0x6A, 0xEA, 0x5A, 0xF0, + 0x26, 0xC4, 0xEA, 0x5F, 0x04, 0x6B, 0x24, 0xFD, 0x6A, 0x39, 0x1B, 0x1A, 0xB2, 0xFA, 0x01, 0xE1, 0xA7, 0xC1, 0xE3, 0x5F, + 0xF0, 0x27, 0xEB, 0x5B, 0x6B, 0x0B, 0x53, 0xB9, 0x0B, 0x28, 0x79, 0xB9, 0x8F, 0x49, 0x88, 0x79, 0x98, 0x2A, 0x42, 0x3F, + 0x2C, 0x40, 0x2F, 0x5F, 0x32, 0xD8, 0x58, 0x4A, 0x98, 0x06, 0xED, 0x2A, 0xE9, 0x3C, 0x44, 0x55, 0xF9, 0xC1, 0x42, 0x9C, + 0x78, 0xCD, 0x49, 0x24, 0xE2, 0xDE, 0x31, 0x54, 0xBE, 0xD2, 0x6B, 0x45, 0x5B, 0x49, 0x88, 0x3F, 0xB0, 0x09, 0x05, 0x3A, + 0xF4, 0x4C, 0x7B, 0xB6, 0x8A, 0x63, 0xAB, 0x79, 0xBD, 0x4E, 0xC2, 0x9E, 0x5E, 0xE3, 0x51, 0x5B, 0x19, 0x07, 0x5B, 0x3F, + 0x68, 0x4A, 0x5D, 0x3E, 0xE5, 0x93, 0x4B, 0x0E, 0xCC, 0xC4, 0xBB, 0xE2, 0x60, 0x1F, 0xDE, 0x55, 0x58, 0xC1, 0xC0, 0x51, + 0x02, 0xD0, 0xEA, 0xE5, 0x99, 0x23, 0x04, 0x81, 0x27, 0x41, 0xB6, 0x6B, 0xCC, 0x5D, 0x3C, 0x46, 0xC0, 0x58, 0x9E, 0x30, + 0x37, 0x6C, 0x5C, 0x64, 0x45, 0x95, 0xFC, 0xF7, 0x17, 0x73, 0x4B, 0x10, 0xA8, 0x54, 0xD7, 0x5A, 0x19, 0x41, 0x7D, 0xD1, + 0xB9, 0x15, 0xEB, 0x55, 0xB2, 0x71, 0x1E, 0xD3, 0x1E, 0xDF, 0x5D, 0xB9, 0x55, 0xAC, 0x64, 0x4A, 0x21, 0x76, 0x3B, 0xB7, + 0x39, 0xE2, 0x0E, 0xE1, 0x15, 0x54, 0x44, 0x41, 0x85, 0x89, 0x9C, 0x54, 0x3F, 0x14, 0x04, 0x47, 0x66, 0x98, 0x5A, 0xB7, + 0x4D, 0x89, 0x8E, 0xC3, 0x84, 0x34, 0xFA, 0x52, 0x8C, 0xBB, 0x3E, 0xE1, 0x3F, 0x9B, 0x64, 0xDC, 0xF2, 0x52, 0xC7, 0x85, + 0x0D, 0xAB, 0x45, 0xDC, 0x4A, 0x64, 0xC2, 0xA5, 0x33, 0x28, 0x89, 0xAF, 0x70, 0x68, 0x22, 0x86, 0x8B, 0x81, 0x2E, 0xF7, + 0x89, 0x76, 0xDC, 0xA3, 0x44, 0x97, 0x5C, 0xB5, 0x83, 0xDB, 0x22, 0xCE, 0x87, 0x7E, 0x8E, 0x51, 0xAD, 0x02, 0xF0, 0x9B, + 0x98, 0x90, 0x48, 0x3A, 0xE8, 0xE4, 0xA0, 0x08, 0xF6, 0xCF, 0x65, 0x98, 0xA9, 0x7A, 0x27, 0xFF, 0xDA, 0xDF, 0x2F, 0x79, + 0xB4, 0xF5, 0x3B, 0xD5, 0x59, 0xC5, 0xD3, 0xEF, 0x56, 0x92, 0x18, 0xFD, 0xB5, 0xCB, 0x27, 0x57, 0x45, 0x56, 0x97, 0xA4, + 0x10, 0x28, 0x04, 0x37, 0xC3, 0x2F, 0xF8, 0x0D, 0x5B, 0x38, 0xA9, 0x6A, 0xEB, 0xE1, 0x8C, 0xEE, 0xC9, 0xD5, 0x98, 0xAB, + 0x09, 0x71, 0x75, 0x52, 0xCC, 0x80, 0x66, 0xA5, 0xC8, 0x1C, 0x87, 0x2B, 0xDC, 0x6D, 0xA0, 0x09, 0xAE, 0x50, 0xA6, 0xE9, + 0x24, 0xC1, 0x6F, 0xB5, 0x49, 0x3B, 0xC4, 0x67, 0xDE, 0xF3, 0x2D, 0xDD, 0xAA, 0xDF, 0xAA, 0x26, 0x4A, 0x29, 0x20, 0x8B, + 0x14, 0x1D, 0x27, 0xD9, 0x79, 0x73, 0xA5, 0xAA, 0xF1, 0xC2, 0xC0, 0x41, 0x2D, 0xBB, 0xB2, 0xCA, 0x6B, 0x0F, 0x8E, 0x8F, + 0x14, 0xA2, 0x71, 0xF7, 0x62, 0x89, 0xE0, 0x82, 0x97, 0xED, 0x46, 0xF7, 0x76, 0x85, 0x08, 0xC5, 0x23, 0x84, 0xA0, 0xA9, + 0x87, 0xB2, 0x2B, 0x83, 0x88, 0xBF, 0x68, 0xDB, 0x63, 0x4F, 0x73, 0xFD, 0xD2, 0xB2, 0x13, 0x91, 0x04, 0x7E, 0x2F, 0x75, + 0x17, 0x8F, 0xC3, 0x17, 0x19, 0x32, 0x81, 0xC4, 0xAB, 0x4E, 0xE5, 0x31, 0x38, 0x06, 0xD8, 0xBD, 0xBA, 0xA9, 0xA4, 0x3C, + 0xD5, 0xFB, 0x88, 0x62, 0xB6, 0x31, 0x20, 0x56, 0x80, 0x66, 0x50, 0xB9, 0x07, 0xE8, 0x58, 0x5E, 0x24, 0xE5, 0xBE, 0x14, + 0xE4, 0x80, 0x1E, 0x30, 0xBC, 0x30, 0x1A, 0x60, 0x37, 0x59, 0x8E, 0xE1, 0x4B, 0x9F, 0x89, 0x43, 0x54, 0xEA, 0x57, 0xFF, + 0xE7, 0x58, 0x94, 0x5F, 0x32, 0xF8, 0xA2, 0x73, 0x77, 0x36, 0xC1, 0x9C, 0x7B, 0xEA, 0x5A, 0xE2, 0x23, 0x45, 0xAD, 0x8A, + 0x4C, 0xE1, 0x52, 0x78, 0x28, 0xC5, 0x63, 0xBE, 0xA3, 0x45, 0x3A, 0x7A, 0x01, 0x7E, 0xE0, 0xF6, 0x04, 0xEB, 0x5A, 0x38, + 0xBE, 0xC4, 0x83, 0xBA, 0x49, 0xAC, 0x69, 0x16, 0x73, 0x03, 0xAB, 0x03, 0x1E, 0xC6, 0x6B, 0x2F, 0x45, 0xB4, 0xE2, 0xBF, + 0xDA, 0x28, 0x23, 0x0F, 0x0F, 0x87, 0x2E, 0x75, 0x9C, 0xBB, 0x65, 0x9F, 0xCD, 0x64, 0xC5, 0x7F, 0x71, 0xE6, 0x1D, 0x39, + 0x60, 0xE0, 0xE3, 0x28, 0x83, 0xB3, 0x73, 0x68, 0x06, 0xA0, 0x0B, 0x49, 0xFF, 0x93, 0x54, 0x1B, 0x09, 0x1D, 0x11, 0x56, + 0xBA, 0x52, 0x13, 0x91, 0xB0, 0xCB, 0xB9, 0x8D, 0xDB, 0x60, 0x04, 0x0B, 0xAA, 0xE0, 0x73, 0xA7, 0xF5, 0xE3, 0xA7, 0x35, + 0xE0, 0x12, 0x63, 0x5E, 0x7F, 0x6F, 0xF0, 0x28, 0x8E, 0x06, 0x47, 0x2C, 0x98, 0x59, 0x53, 0x00, 0x4F, 0x4D, 0xA9, 0x60, + 0x34, 0x8B, 0x64, 0xE2, 0x64, 0x6D, 0x84, 0xEC, 0xD5, 0x1F, 0xC9, 0xEE, 0x45, 0x20, 0xF6, 0x3D, 0x8F, 0x5D, 0x49, 0xF4, + 0x65, 0xDE, 0xB2, 0x56, 0x14, 0xD3, 0x67, 0xB2, 0x1E, 0x91, 0x3C, 0xF5, 0xF4, 0x5C, 0x57, 0x23, 0xEC, 0x89, 0xF5, 0x74, + 0x9E, 0x4F, 0x86, 0x07, 0x18, 0xB1, 0x63, 0xE0, 0x2E, 0xF8, 0xED, 0x9E, 0x66, 0x9B, 0x6D, 0x5A, 0x04, 0xDF, 0xFD, 0xB7, + 0xD5, 0x07, 0xED, 0x05, 0xFD, 0x33, 0x5A, 0x63, 0xEC, 0x17, 0x9F, 0xB4, 0x09, 0x25, 0xBB, 0x9E, 0x9B, 0x75, 0xB2, 0x62, + 0x36, 0x8D, 0xC0, 0x40, 0x2F, 0x9D, 0x00, 0xD2, 0x77, 0x25, 0x03, 0x76, 0x38, 0x0C, 0x51, 0x89, 0xEA, 0xA9, 0x2D, 0xDA, + 0x4F, 0x95, 0x3C, 0xC6, 0x0D, 0xA9, 0x4D, 0x1C, 0x13, 0x97, 0x95, 0xA5, 0xEC, 0xB7, 0x6C, 0xA0, 0x8D, 0x31, 0x8D, 0x95, + 0xFD, 0xBA, 0xC2, 0xC2, 0x46, 0x28, 0x46, 0xB9, 0xD3, 0x01, 0xB0, 0xAD, 0x8D, 0x67, 0x98, 0x46, 0xF6, 0x52, 0xE6, 0xB5, + 0x42, 0x94, 0x88, 0x0F, 0x1D, 0x98, 0xE9, 0x72, 0xA9, 0x54, 0x90, 0x4A, 0xF7, 0x13, 0x95, 0x90, 0x11, 0xC9, 0xA4, 0xBF, + 0x5E, 0x43, 0x9C, 0x4C, 0x72, 0x90, 0xA5, 0x7C, 0x9E, 0xD6, 0xE1, 0xC4, 0x39, 0x87, 0xAF, 0xB7, 0x15, 0xF9, 0x77, 0x17, + 0x9E, 0x00, 0xAD, 0x6C, 0x97, 0x1F, 0x1F, 0xAA, 0x38, 0xB7, 0x81, 0x1E, 0x9C, 0x7B, 0x30, 0x8A, 0x2A, 0xD2, 0x9D, 0xE9, + 0x9F, 0x03, 0xCD, 0xCE, 0xE3, 0x51, 0x4D, 0x9E, 0xFE, 0xE3, 0x0E, 0x9D, 0x1A, 0x90, 0xD6, 0xFA, 0xCC, 0xD1, 0x18, 0x27, + 0x98, 0xC6, 0x6E, 0xB9, 0x4C, 0xC3, 0xB1, 0xEB, 0xC0, 0x5C, 0x53, 0xAD, 0x49, 0xDB, 0x11, 0x8B, 0x11, 0x53, 0x4E, 0x9F, + 0x7E, 0xE8, 0x94, 0xFC, 0x0E, 0x8A, 0x50, 0x44, 0x4E, 0x36, 0xA5, 0xBC, 0x4A, 0x29, 0x47, 0x6D, 0xF7, 0xBE, 0x3A, 0xE8, + 0x24, 0x4F, 0x7F, 0x77, 0x64, 0x4C, 0xEB, 0x53, 0x21, 0x2C, 0x21, 0xDB, 0xB9, 0x23, 0x6E, 0x65, 0xEA, 0xD0, 0x3E, 0x53, + 0xF8, 0x7B, 0x0A, 0xCE, 0xAA, 0xC8, 0xCC, 0xE4, 0xE5, 0xDE, 0xAD, 0xE9, 0x14, 0xCF, 0x66, 0x45, 0x94, 0x03, 0xF2, 0x61, + 0x88, 0xBF, 0xDB, 0x0B, 0x27, 0xCF, 0x50, 0x0A, 0x87, 0x4B, 0xEF, 0x28, 0x6E, 0x5E, 0x40, 0xB9, 0x28, 0xCA, 0xA7, 0x95, + 0x92, 0x32, 0x41, 0x26, 0xFD, 0x46, 0xFA, 0xAC, 0x1E, 0x6B, 0xC1, 0x20, 0x66, 0x06, 0xCC, 0x82, 0xD0, 0xB0, 0xF0, 0xAE, + 0x13, 0x48, 0x59, 0xAB, 0x9E, 0x83, 0x66, 0x59, 0xCE, 0xE3, 0x5C, 0x12, 0xDE, 0x93, 0x4E, 0xBD, 0xB1, 0xA4, 0x98, 0x74, + 0x37, 0x87, 0xD9, 0x65, 0x29, 0x57, 0x0A, 0x07, 0x2D, 0x7D, 0xB6, 0xD5, 0xDA, 0xDC, 0x58, 0x95, 0x97, 0xDC, 0x48, 0xB1, + 0xD5, 0x5C, 0xD1, 0x64, 0x32, 0x28, 0x43, 0x1B, 0xAB, 0xF9, 0x6E, 0x93, 0x19, 0x48, 0xEA, 0xC0, 0x60, 0x05, 0xE9, 0x5F, + 0x2C, 0xC3, 0x34, 0x25, 0x28, 0x89, 0xF4, 0xB9, 0xF2, 0x6A, 0xE2, 0x98, 0x05, 0x79, 0xEE, 0xCF, 0xDD, 0xE4, 0x5A, 0x1B, + 0xEF, 0xFA, 0x2E, 0x72, 0x05, 0xA7, 0x05, 0x59, 0xFB, 0x78, 0xEB, 0x25, 0x38, 0xEB, 0xF1, 0xF1, 0x51, 0xCB, 0xF5, 0xBC, + 0x72, 0x28, 0xA3, 0xD1, 0xDB, 0x04, 0xC9, 0x26, 0x32, 0x0F, 0x22, 0x56, 0x0F, 0x01, 0x3D, 0x3F, 0x26, 0x42, 0x56, 0x0E, + 0x0A, 0x03, 0x12, 0xB5, 0x9F, 0x2D, 0x42, 0x5D, 0xE2, 0xE4, 0x8A, 0x3A, 0x38, 0xED, 0x64, 0x51, 0x23, 0xA4, 0xF2, 0x7B, + 0xDA, 0x29, 0xEF, 0xA1, 0x1E, 0xC8, 0x24, 0x0D, 0xF4, 0x35, 0x31, 0x68, 0xCB, 0x6C, 0xFB, 0x0F, 0x5B, 0x61, 0x33, 0x2B, + 0x09, 0xDB, 0xC9, 0xBB, 0x7A, 0x34, 0xA4, 0xFD, 0x8E, 0x42, 0xF3, 0xBF, 0xB0, 0x61, 0x5D, 0x81, 0x87, 0x0B, 0x50, 0xD9, + 0xDB, 0x53, 0xB2, 0xD3, 0xC3, 0x9F, 0x54, 0xE5, 0xAB, 0x7D, 0x4B, 0x12, 0x03, 0xE1, 0x5C, 0xE7, 0x1B, 0x89, 0xBE, 0xCF, + 0x86, 0xDC, 0x68, 0xC5, 0xD2, 0x30, 0xC0, 0x67, 0x82, 0x30, 0xBB, 0x21, 0xE5, 0x9D, 0xD5, 0x74, 0x56, 0x49, 0xCC, 0xB2, + 0x94, 0x74, 0x35, 0xD6, 0x6B, 0x9A, 0xF3, 0x34, 0x58, 0x30, 0x7D, 0xAF, 0x9E, 0x5C, 0x35, 0x00, 0xF7, 0xB9, 0xE3, 0xE9, + 0x11, 0xD0, 0x84, 0xA2, 0x70, 0x7B, 0x41, 0x92, 0x9D, 0x4F, 0x60, 0x86, 0x8D, 0x72, 0x13, 0x51, 0x25, 0x46, 0xDA, 0xA1, + 0xCC, 0x77, 0x3C, 0xEE, 0x22, 0x58, 0xA4, 0x76, 0xF2, 0x28, 0xFF, 0x3E, 0x9D, 0x47, 0xE5, 0xCD, 0x5B, 0x07, 0x15, 0x87, + 0xC3, 0x46, 0xFD, 0x8A, 0x53, 0x87, 0x39, 0xCE, 0x93, 0xBA, 0x47, 0xB7, 0x31, 0xE3, 0xF1, 0x62, 0xDB, 0xA8, 0xE5, 0x49, + 0x50, 0x6C, 0x5F, 0xA9, 0x8F, 0x55, 0x8D, 0x7F, 0x1A, 0x48, 0x76, 0xAA, 0xEC, 0x55, 0xFC, 0x44, 0x3A, 0x35, 0x74, 0x88, + 0x8E, 0x14, 0x5A, 0x4C, 0x72, 0xC6, 0x9E, 0x55, 0x61, 0xF4, 0x4D, 0x5A, 0xFE, 0x9A, 0xF8, 0x29, 0x45, 0x0A, 0x06, 0x8F, + 0x2D, 0x97, 0xBB, 0x2C, 0x57, 0x51, 0x00, 0x4B, 0xEA, 0x37, 0x71, 0xE9, 0x2E, 0xFB, 0xB1, 0x39, 0xFA, 0x91, 0xD6, 0xB6, + 0x4A, 0xDF, 0x5F, 0x69, 0x3A, 0x60, 0x57, 0x3A, 0x0B, 0x7C, 0x95, 0xAE, 0xC5, 0x91, 0xE9, 0x2F, 0xA8, 0x1C, 0x46, 0x8A, + 0x5B, 0x3C, 0x6F, 0xAE, 0x40, 0x12, 0x4A, 0x58, 0x2C, 0xF5, 0xA5, 0x38, 0x2B, 0xD0, 0xC4, 0xFD, 0x5A, 0x3D, 0x61, 0xE1, + 0x92, 0x05, 0x56, 0x0A, 0x64, 0x36, 0x5F, 0xE0, 0x17, 0xD8, 0xE3, 0x69, 0x13, 0xD7, 0xC8, 0xEB, 0x98, 0xFB, 0x96, 0xDC, + 0x1E, 0x34, 0x06, 0x79, 0x4C, 0x59, 0xFB, 0x66, 0x79, 0xAB, 0x79, 0x19, 0xE1, 0xEE, 0x59, 0x68, 0x99, 0x06, 0x69, 0xAB, + 0xAD, 0x49, 0x70, 0x36, 0x69, 0x40, 0xF2, 0x1E, 0x36, 0x05, 0x5E, 0x3B, 0xFE, 0xE5, 0x58, 0x92, 0x5D, 0xCE, 0x4C, 0x56, + 0xBC, 0x08, 0x43, 0x0F, 0x85, 0x42, 0x36, 0xC7, 0xB6, 0x29, 0xC9, 0xCB, 0xD6, 0x8F, 0x22, 0x26, 0x2F, 0xE4, 0xF3, 0x0E, + 0x83, 0xCB, 0x93, 0xA7, 0x15, 0x0C, 0x60, 0xBA, 0x60, 0xC5, 0xC1, 0xDF, 0x41, 0x2E, 0x47, 0xA0, 0x35, 0xE6, 0x64, 0xA0, + 0x25, 0xA6, 0xB0, 0xBB, 0x83, 0xC0, 0xB0, 0xC6, 0x4E, 0x06, 0x2E, 0xB4, 0x17, 0xCA, 0x8A, 0x46, 0x16, 0xE4, 0x80, 0x9A, + 0x23, 0x88, 0x0C, 0xF0, 0x6D, 0xA9, 0x99, 0x4B, 0x21, 0x9D, 0x59, 0x57, 0x31, 0xCA, 0x73, 0x11, 0xF5, 0xE6, 0x19, 0x76, + 0x72, 0x56, 0x09, 0x0C, 0x66, 0xC5, 0x89, 0x55, 0xEC, 0xAA, 0x86, 0x9B, 0xD9, 0x8A, 0x28, 0xF3, 0x8C, 0xB9, 0x6A, 0x88, + 0x2E, 0xB8, 0x06, 0x6C, 0xA7, 0x25, 0x62, 0x37, 0xEF, 0xA4, 0x06, 0xCC, 0x67, 0x58, 0xAC, 0x68, 0x3E, 0x88, 0xD1, 0x54, + 0xA4, 0xB5, 0x44, 0x06, 0x7E, 0xDD, 0x39, 0x58, 0xF1, 0xE6, 0x1B, 0xF8, 0xED, 0xC6, 0x7C, 0x0E, 0x6B, 0x15, 0x0D, 0x5B, + 0x06, 0x23, 0x0F, 0x08, 0x7F, 0xF1, 0xD3, 0xF3, 0x8F, 0xC4, 0x6B, 0x0F, 0xBF, 0x06, 0xFB, 0x7F, 0xDF, 0xD0, 0x0F, 0xCF, + 0xD5, 0xE4, 0xEA, 0x1A, 0x65, 0xDD, 0xA8, 0xEE, 0xE1, 0x5B, 0x70, 0x8C, 0xC1, 0x3A, 0xAD, 0x6C, 0xBF, 0x13, 0x95, 0xB7, + 0x3B, 0x00, 0xB2, 0x4F, 0x2C, 0xE9, 0x40, 0x9C, 0x49, 0x55, 0xF8, 0x5D, 0x52, 0xEB, 0x9C, 0xA3, 0x1E, 0x43, 0xA3, 0xCF, + 0x77, 0xC4, 0x3B, 0x6F, 0xE7, 0x54, 0x33, 0xBE, 0xAD, 0xA0, 0x14, 0xDF, 0xB9, 0xA8, 0x51, 0x3F, 0xD3, 0xB4, 0x9F, 0x64, + 0xFB, 0x1B, 0xAB, 0x79, 0x7E, 0x30, 0x7D, 0xA3, 0x81, 0x8B, 0x5F, 0xF5, 0x1E, 0x3A, 0x4A, 0x9F, 0x8D, 0x8A, 0x76, 0xC0, + 0x08, 0xBF, 0x42, 0xE1, 0x44, 0xFF, 0xE6, 0x07, 0xC6, 0x1C, 0x44, 0xD2, 0x61, 0x71, 0xDC, 0xA8, 0xAD, 0xFC, 0x35, 0x65, + 0xA2, 0x48, 0xEB, 0x7C, 0x5D, 0xB1, 0x90, 0x41, 0x24, 0x7F, 0xF4, 0xC1, 0x82, 0xBD, 0x4B, 0xE6, 0xA6, 0x33, 0x3E, 0x66, + 0x16, 0xA3, 0xAA, 0xC0, 0xF2, 0x72, 0xBF, 0x55, 0x77, 0x27, 0xF6, 0x3D, 0x20, 0xAE, 0x22, 0x2E, 0x34, 0xF9, 0xD7, 0xB2, + 0x8F, 0xE5, 0x83, 0x84, 0x55, 0x76, 0x0C, 0x94, 0x7E, 0x9A, 0x1D, 0xC9, 0x07, 0xAE, 0x5E, 0x01, 0x57, 0xCE, 0x25, 0x1E, + 0x3F, 0x08, 0xE7, 0xBD, 0x4D, 0xE7, 0xBD, 0x43, 0xB0, 0x5C, 0x0D, 0x12, 0x45, 0x26, 0x42, 0x8B, 0xF0, 0x0C, 0x34, 0x57, + 0x02, 0x68, 0x4F, 0xA1, 0xDE, 0xA6, 0x5C, 0x87, 0xC6, 0x55, 0x05, 0xC8, 0xCA, 0xB5, 0x18, 0xFF, 0x6C, 0x37, 0x94, 0xBE, + 0xC4, 0x17, 0xA1, 0x3A, 0xA4, 0x29, 0x65, 0xCC, 0x5D, 0xEB, 0xD1, 0xDD, 0x1E, 0xCD, 0xD0, 0x99, 0x3B, 0x39, 0xC6, 0xC8, + 0xD2, 0x76, 0xA4, 0xAE, 0x5E, 0xFA, 0x3D, 0x63, 0x8C, 0xD7, 0x07, 0xFD, 0xDE, 0x0E, 0x4F, 0xB9, 0xDF, 0x68, 0xD7, 0xB1, + 0x24, 0xF7, 0x95, 0x04, 0x52, 0x19, 0x32, 0xEC, 0x93, 0x31, 0xAC, 0x53, 0xB7, 0x96, 0xE6, 0x3A, 0x58, 0x24, 0x58, 0xE6, + 0xA3, 0x6A, 0xFE, 0xDA, 0xDA, 0xAD, 0x48, 0xC2, 0x5D, 0x18, 0x3D, 0x82, 0x4D, 0x1C, 0x50, 0xF7, 0x21, 0xFF, 0xD0, 0x1B, + 0x1E, 0x7D, 0x3E, 0x0A, 0x67, 0x92, 0x49, 0x93, 0x79, 0x07, 0x2F, 0xCF, 0x72, 0xCF, 0xDD, 0x27, 0xB2, 0xF1, 0xED, 0x8B, + 0xB6, 0xC5, 0x48, 0x09, 0x7E, 0xBC, 0x25, 0x66, 0x22, 0x39, 0xB6, 0xDA, 0x1A, 0x1E, 0x26, 0xED, 0x0B, 0xCE, 0x26, 0x17, + 0xB3, 0x02, 0xF8, 0x3F, 0x35, 0x42, 0xD9, 0x1E, 0x54, 0x23, 0x8A, 0xC2, 0xA0, 0xBF, 0x81, 0x37, 0x47, 0x6F, 0xB7, 0xF6, + 0x07, 0xF2, 0xD2, 0x15, 0xB6, 0x6D, 0x23, 0xA3, 0xE2, 0x9E, 0xE6, 0x0C, 0xB0, 0xCE, 0xCA, 0x6D, 0xB3, 0xA2, 0x02, 0xBC, + 0xA3, 0x63, 0xBD, 0x5A, 0x1E, 0xBD, 0xA3, 0x36, 0x73, 0x13, 0xC8, 0xF9, 0xDD, 0x4E, 0x8B, 0x91, 0xCA, 0x20, 0xA4, 0x00, + 0xF8, 0xFC, 0x8C, 0x46, 0xE9, 0x0F, 0x7E, 0x68, 0x23, 0x86, 0xD1, 0x67, 0x77, 0x65, 0xE8, 0x9B, 0xCF, 0xB9, 0xC2, 0x4F, + 0xB9, 0x20, 0x81, 0xAF, 0xEA, 0x74, 0xDA, 0x09, 0xF8, 0x61, 0x50, 0x78, 0x63, 0x24, 0x6C, 0x53, 0xF2, 0xFA, 0xED, 0x32, + 0xF2, 0xA0, 0xFF, 0x6D, 0xFA, 0x2B, 0x36, 0x13, 0x00, 0x46, 0xEB, 0xD5, 0x5B, 0x27, 0x2B, 0x51, 0x85, 0xD4, 0xF3, 0xE5, + 0x1A, 0x88, 0x5F, 0x99, 0xCC, 0xCC, 0x6D, 0x17, 0x28, 0x25, 0x7D, 0x2E, 0x12, 0x85, 0xA2, 0xAD, 0x1E, 0x92, 0x28, 0x8D, + 0xBB, 0x0A, 0xF4, 0xE0, 0x59, 0x28, 0x6A, 0x06, 0xF3, 0x04, 0x75, 0xF4, 0x3D, 0x64, 0xA1, 0xDE, 0x59, 0xB4, 0x9A, 0x5E, + 0x78, 0x29, 0xD7, 0x59, 0x08, 0xF5, 0xD3, 0xE5, 0x8E, 0x67, 0x17, 0x6A, 0xFB, 0x1A, 0xBF, 0xD2, 0xDE, 0x99, 0xF0, 0x4B, + 0xA7, 0x68, 0x27, 0x82, 0x9A, 0x7B, 0xE3, 0xC0, 0xC1, 0xE6, 0xB7, 0xDE, 0x30, 0xFA, 0x1F, 0xCC, 0x7C, 0xB8, 0x66, 0x2E, + 0xED, 0x49, 0x56, 0x8E, 0x79, 0x77, 0x19, 0x6C, 0xD7, 0x91, 0x8A, 0xE5, 0x0B, 0x86, 0xDC, 0x3E, 0x7B, 0x94, 0x01, 0xEE, + 0x4A, 0x0D, 0xDA, 0x58, 0xEE, 0xCC, 0x4B, 0x4D, 0x03, 0x21, 0xFB, 0x69, 0x73, 0x3F, 0xEB, 0x96, 0x45, 0x55, 0xB1, 0x6F, + 0x2F, 0xE8, 0x4F, 0xBB, 0x43, 0x3E, 0xB5, 0x5B, 0x7A, 0xAC, 0xE4, 0x8F, 0xF8, 0x2B, 0xE3, 0x4D, 0x9E, 0xC0, 0xF9, 0xB1, + 0x19, 0xAF, 0x44, 0x41, 0xE1, 0x3E, 0x5A, 0x58, 0x66, 0xBA, 0xCE, 0xC0, 0x76, 0xA3, 0x96, 0x83, 0x04, 0x1E, 0x28, 0x56, + 0x92, 0x3F, 0x46, 0xB8, 0xC2, 0xFC, 0x94, 0xB0, 0xF8, 0x5E, 0x3F, 0x24, 0x53, 0xBF, 0xED, 0x47, 0x34, 0x3C, 0x91, 0x23, + 0xE1, 0xBC, 0x31, 0x21, 0x86, 0xC6, 0x3F, 0x6E, 0x55, 0x1C, 0xB5, 0x31, 0x50, 0x9C, 0x03, 0x76, 0x2B, 0x9A, 0xA3, 0x7C, + 0xB3, 0xDA, 0x29, 0x28, 0xE2, 0x59, 0x68, 0xE0, 0x87, 0x9F, 0xAB, 0x9E, 0x03, 0x50, 0xAA, 0xE3, 0x56, 0xC0, 0x14, 0xD4, + 0xAA, 0x3A, 0xE1, 0x27, 0xB7, 0xB8, 0xE4, 0x0F, 0x65, 0x86, 0x27, 0xD3, 0xD2, 0x34, 0x1D, 0xC5, 0xB0, 0x5B, 0xBD, 0xD1, + 0x52, 0xB7, 0x37, 0xE3, 0xE1, 0xB6, 0x75, 0xFF, 0x7E, 0x7B, 0x73, 0x05, 0xCA, 0xBD, 0x9F, 0x92, 0x97, 0x9A, 0x32, 0x8E, + 0x40, 0x4C, 0x87, 0x24, 0xC7, 0x68, 0xC6, 0x89, 0xA1, 0x03, 0x17, 0x7F, 0x7B, 0x23, 0x1E, 0x49, 0x89, 0xA7, 0x87, 0xCC, + 0x3A, 0xA3, 0xB1, 0x7E, 0x9D, 0x60, 0xD6, 0x95, 0x0A, 0xDF, 0x00, 0xB8, 0xCF, 0xA9, 0x57, 0x43, 0x8C, 0xDA, 0x06, 0xF7, + 0x0F, 0x0A, 0x4B, 0x6B, 0x51, 0xC2, 0xD7, 0x74, 0xCE, 0xF1, 0x97, 0xDE, 0x88, 0xDB, 0x6F, 0x87, 0x53, 0x16, 0x4F, 0x21, + 0x0D, 0x33, 0x46, 0xB2, 0xAD, 0x15, 0x0A, 0x39, 0x8F, 0x40, 0x1E, 0xD0, 0xA7, 0xB1, 0xD7, 0xFD, 0x9B, 0xBD, 0x18, 0x6C, + 0x2A, 0x34, 0x69, 0x0A, 0x19, 0xD6, 0x2C, 0xC8, 0x2A, 0x5D, 0x9C, 0x9F, 0xD0, 0x59, 0x20, 0xFE, 0x8A, 0xDE, 0x4E, 0x0F, + 0xF7, 0xD0, 0x0E, 0x5A, 0xE5, 0x70, 0x62, 0x3E, 0x3E, 0xB3, 0x0D, 0x7D, 0x82, 0x0F, 0x46, 0x07, 0x5F, 0x81, 0x63, 0x3A, + 0x26, 0xB2, 0xF7, 0x27, 0x17, 0x32, 0xF3, 0x0A, 0x67, 0x1D, 0xCE, 0x1F, 0x57, 0xD2, 0x6A, 0x40, 0x59, 0x08, 0x60, 0x43, + 0x37, 0xBB, 0x2E, 0x90, 0x4C, 0xA0, 0xA6, 0x44, 0xAB, 0x4D, 0xE8, 0xCF, 0x10, 0x9A, 0x88, 0x1F, 0x26, 0xE0, 0x26, 0x43, + 0x20, 0xCA, 0xC3, 0x11, 0xF4, 0x5E, 0x71, 0xEC, 0x78, 0x4B, 0x31, 0x61, 0xD4, 0xED, 0x76, 0x21, 0xD4, 0x6F, 0x24, 0xA3, + 0xA2, 0x19, 0x2F, 0x75, 0x7A, 0x98, 0x93, 0xF1, 0x12, 0x23, 0xB9, 0xCA, 0xC9, 0x6E, 0x55, 0xDF, 0xEA, 0xAE, 0x2E, 0x51, + 0x3E, 0x4E, 0xCC, 0x62, 0xFF, 0xB5, 0xC8, 0x9C, 0x56, 0x89, 0x50, 0x14, 0x34, 0x68, 0x79, 0x9A, 0x34, 0xBE, 0x96, 0x50, + 0xF6, 0x26, 0x40, 0x42, 0x1B, 0x6A, 0x5C, 0x51, 0xFB, 0xE8, 0x47, 0x6B, 0xC9, 0x22, 0xF7, 0x25, 0xF6, 0x5E, 0x8E, 0x10, + 0x85, 0x67, 0x61, 0x7C, 0x52, 0x72, 0x91, 0xBB, 0x0B, 0x1A, 0xC5, 0xA4, 0x1B, 0x7A, 0xD9, 0x01, 0xA5, 0x8B, 0x00, 0x50, + 0x76, 0x98, 0xA4, 0x6C, 0xF7, 0x93, 0x62, 0xDB, 0xC4, 0xEA, 0x2C, 0xBA, 0xB3, 0x8D, 0xD5, 0x54, 0x5A, 0x3B, 0x9F, 0x73, + 0x0B, 0x73, 0x12, 0xFE, 0x0D, 0xAF, 0x8A, 0x27, 0xCB, 0x9A, 0xC6, 0x4D, 0x4A, 0x6B, 0xE0, 0x6D, 0x67, 0x62, 0x2B, 0x65, + 0xAF, 0xEB, 0x34, 0x8C, 0x4A, 0xF9, 0xC3, 0x6F, 0xD8, 0xC6, 0xE1, 0xF3, 0xDB, 0xC6, 0x08, 0x5B, 0x3C, 0x54, 0xFB, 0xE2, + 0x5A, 0x89, 0xA5, 0x16, 0xFC, 0x7B, 0x9A, 0x42, 0xF7, 0xC3, 0x9A, 0x69, 0xE3, 0xA3, 0x0C, 0x6D, 0xBB, 0xC3, 0x62, 0x7D, + 0x78, 0xA8, 0x79, 0x64, 0x33, 0xCF, 0x68, 0x6C, 0x7F, 0x54, 0xA9, 0xA1, 0x2C, 0x32, 0xA0, 0x56, 0x6B, 0x42, 0x59, 0xB8, + 0xD9, 0x7B, 0x73, 0x21, 0xF5, 0xA1, 0xC7, 0x14, 0x6D, 0x8C, 0xD5, 0xCE, 0x52, 0xAF, 0x24, 0xC1, 0x89, 0x0F, 0x95, 0x59, + 0x7E, 0x2C, 0x03, 0x3C, 0x32, 0x49, 0x5B, 0x0D, 0xBD, 0x63, 0x7C, 0x86, 0x90, 0xC9, 0x24, 0xE5, 0x38, 0x3D, 0xF2, 0x64, + 0x24, 0xEB, 0x74, 0x1A, 0xAC, 0xF8, 0xD3, 0x6D, 0xC4, 0x12, 0x00, 0x05, 0x2E, 0xB9, 0x99, 0x24, 0x64, 0x3B, 0xA9, 0xD6, + 0x3F, 0x5C, 0x7C, 0x93, 0x01, 0x13, 0xDB, 0xAF, 0x5D, 0xA3, 0x10, 0xD4, 0x69, 0xC9, 0x35, 0xE4, 0x5F, 0x5F, 0xD2, 0x6D, + 0x5D, 0x5A, 0x2D, 0xF4, 0xB9, 0x38, 0x95, 0xAE, 0xD6, 0xE7, 0xAE, 0x86, 0x54, 0x0C, 0xAE, 0x51, 0x6D, 0x6B, 0x74, 0x57, + 0x06, 0x00, 0x76, 0x8F, 0x05, 0x54, 0xE1, 0x04, 0x52, 0x27, 0x6D, 0xA1, 0x34, 0x3C, 0xFD, 0x27, 0x94, 0xF5, 0x7A, 0x22, + 0x8E, 0x5F, 0x78, 0xF2, 0x7F, 0x9B, 0x89, 0x51, 0xE6, 0x9E, 0x45, 0xDD, 0x3A, 0x1B, 0x63, 0xCF, 0x0D, 0x87, 0x0E, 0x1F, + 0xF6, 0x4D, 0xA3, 0x33, 0xA3, 0xBB, 0x6D, 0xC7, 0x6E, 0xEA, 0xD1, 0x61, 0xBB, 0xDD, 0xDB, 0xCF, 0x73, 0x53, 0x7D, 0x8A, + 0x2A, 0xB8, 0xDD, 0xBF, 0x0C, 0x17, 0xEC, 0xAA, 0x24, 0x91, 0x88, 0x83, 0x52, 0x27, 0x15, 0x26, 0xDE, 0x34, 0xD0, 0x99, + 0x9C, 0xB2, 0x00, 0xDE, 0xB3, 0xD1, 0x1A, 0x3A, 0x0B, 0x4D, 0x0B, 0xF4, 0x98, 0x25, 0x07, 0xFD, 0xDE, 0x6E, 0x6E, 0xBB, + 0x49, 0x25, 0xED, 0x73, 0xFA, 0x29, 0xB7, 0xAA, 0x0C, 0x3F, 0x2F, 0xDC, 0x42, 0x16, 0xB5, 0x4A, 0xC8, 0xDB, 0xB7, 0xBB, + 0x74, 0xD4, 0x1A, 0x8D, 0xC7, 0x86, 0xF0, 0xAC, 0x5E, 0x35, 0xB6, 0xFB, 0x56, 0x7C, 0x63, 0xE9, 0x5A, 0x58, 0xD1, 0xCA, + 0xFB, 0x92, 0xC4, 0x2D, 0xB3, 0xFC, 0xFE, 0xD9, 0xB7, 0x7D, 0x5A, 0xDA, 0xFD, 0xF5, 0x01, 0x1E, 0xEE, 0x41, 0x99, 0xC9, + 0x5F, 0x3D, 0x64, 0x98, 0x9E, 0xD7, 0x64, 0xE9, 0x36, 0x4F, 0x5D, 0x24, 0x9C, 0x9B, 0xD1, 0xF7, 0xD7, 0xB2, 0xEA, 0xD8, + 0x37, 0x7F, 0x43, 0x80, 0x5C, 0xBE, 0x3E, 0xC5, 0x21, 0x30, 0x08, 0xF7, 0x9C, 0x8D, 0xB4, 0xDA, 0xCF, 0xBD, 0x5F, 0xA6, + 0xD0, 0x65, 0x1A, 0x1C, 0xA2, 0x05, 0x1D, 0xF6, 0x17, 0xD3, 0x99, 0x5F, 0xBA, 0xBC, 0x30, 0x20, 0xF2, 0x6C, 0x61, 0x53, + 0x0A, 0x0F, 0x10, 0xE7, 0x3C, 0x8F, 0x76, 0x5F, 0x12, 0x4A, 0xA9, 0xF5, 0x8C, 0x64, 0x0F, 0x63, 0x03, 0x8F, 0x68, 0x91, + 0xCF, 0x1D, 0x7E, 0xCE, 0x34, 0xC5, 0x75, 0xA7, 0x95, 0x6B, 0xC5, 0x22, 0x82, 0xA4, 0x3F, 0xC0, 0x7C, 0x81, 0xAF, 0x88, + 0x96, 0x06, 0xEA, 0x59, 0x61, 0xA8, 0xE3, 0x9A, 0xB8, 0x3E, 0xF6, 0x9C, 0x9E, 0xD3, 0xF7, 0x8C, 0x43, 0x5E, 0x99, 0x92, + 0x55, 0x8F, 0xED, 0xE4, 0x57, 0x65, 0xFF, 0x8C, 0xD0, 0xD9, 0xD4, 0x34, 0x1F, 0x3B, 0x29, 0x1B, 0xB0, 0x46, 0xEA, 0xB6, + 0x76, 0x35, 0x81, 0x4D, 0x5B, 0x3D, 0xFE, 0xF5, 0xDF, 0x45, 0x16, 0xF7, 0x2D, 0x98, 0x66, 0xEA, 0x3F, 0xF8, 0x42, 0x91, + 0x65, 0x85, 0x12, 0x2A, 0x0A, 0x35, 0x16, 0xDC, 0x1C, 0x67, 0x73, 0x7E, 0x2A, 0x49, 0x1F, 0xFE, 0x7A, 0x6C, 0x61, 0x7F, + 0xB0, 0xEF, 0x99, 0xAA, 0xDB, 0x25, 0xC2, 0xF9, 0xC3, 0x5B, 0x12, 0xEF, 0x34, 0x87, 0x84, 0xD2, 0x29, 0x99, 0x53, 0x20, + 0xA7, 0x28, 0x1F, 0x50, 0x35, 0xB1, 0x1A, 0xF7, 0x3C, 0x47, 0xBB, 0x43, 0x03, 0x2F, 0x19, 0x5F, 0x22, 0x6D, 0xBE, 0xA0, + 0x1F, 0x41, 0xC3, 0x3E, 0xA5, 0x97, 0xE9, 0x97, 0x79, 0x4A, 0xEA, 0x3E, 0xE9, 0xE6, 0xA6, 0xB0, 0x89, 0x40, 0x1C, 0x6F, + 0xD3, 0x37, 0x83, 0xFC, 0x57, 0x69, 0x6E, 0x1E, 0x9A, 0xE7, 0xB8, 0x41, 0x2F, 0xF1, 0xC7, 0x72, 0x8D, 0x6C, 0x93, 0x64, + 0x87, 0x55, 0xAB, 0x27, 0xEB, 0x61, 0xAC, 0x27, 0x8D, 0x5F, 0xCA, 0x4C, 0x83, 0x2B, 0xCB, 0xFD, 0xD4, 0x52, 0x5C, 0x35, + 0x78, 0xC2, 0x7A, 0xB8, 0x8C, 0x1D, 0x44, 0x19, 0xE1, 0xBB, 0x83, 0x8D, 0xE0, 0xD3, 0xB4, 0xB5, 0xFD, 0x13, 0x93, 0xF2, + 0xCA, 0xC0, 0x74, 0xFA, 0x10, 0x71, 0x45, 0x92, 0xC4, 0x2E, 0xE1, 0x5D, 0xBF, 0x1E, 0x7B, 0xB8, 0xA6, 0xE0, 0x35, 0xA9, + 0x03, 0xCF, 0x28, 0x81, 0x41, 0x30, 0x3E, 0x00, 0x25, 0x6C, 0xB9, 0xF3, 0x4A, 0xE2, 0x89, 0x05, 0x95, 0x4F, 0x2A, 0x8C, + 0x11, 0x82, 0x26, 0x3C, 0x5E, 0x68, 0x62, 0xF8, 0x7D, 0xB0, 0xBB, 0x39, 0x3A, 0x76, 0xB8, 0x73, 0x71, 0x5C, 0x2B, 0x06, + 0xFF, 0x72, 0x5F, 0xC3, 0x76, 0xA4, 0xC0, 0x6A, 0xB1, 0x39, 0x12, 0xF9, 0x8A, 0x65, 0x27, 0x76, 0x8D, 0x8A, 0x52, 0xA1, + 0x6A, 0xAE, 0x13, 0xF6, 0xFA, 0x26, 0xD5, 0x80, 0xF7, 0xF2, 0xFD, 0xE5, 0x53, 0xF0, 0xF0, 0xEB, 0xFA, 0xA2, 0xC9, 0x51, + 0xC5, 0xE1, 0xB1, 0x62, 0xA4, 0x5D, 0xE5, 0x67, 0xF3, 0x7F, 0x3C, 0x63, 0x2E, 0xEA, 0x39, 0xC3, 0xBA, 0x14, 0xA1, 0x85, + 0x9C, 0x09, 0x74, 0xCA, 0x87, 0x68, 0xF1, 0x8B, 0x51, 0x5D, 0xEE, 0x9E, 0x7A, 0x34, 0x8F, 0xA7, 0x55, 0x64, 0x66, 0xB4, + 0x84, 0x36, 0x51, 0x0D, 0xF6, 0xEA, 0x94, 0xEF, 0x9B, 0x78, 0xD7, 0x79, 0x0C, 0x8E, 0x2F, 0x45, 0x24, 0x86, 0x29, 0xA1, + 0x25, 0x55, 0xD1, 0x40, 0xB9, 0x94, 0x0F, 0xDA, 0xE7, 0x40, 0xC6, 0xA6, 0xFF, 0x0B, 0xCD, 0x4C, 0x36, 0x16, 0x9F, 0xC5, + 0x3C, 0xBC, 0x1E, 0xD7, 0x7A, 0x87, 0xD4, 0x1D, 0x6E, 0x83, 0x4E, 0x29, 0x53, 0xE2, 0x0E, 0x60, 0x85, 0x58, 0x5E, 0x7C, + 0x63, 0x71, 0xE6, 0x0F, 0x6F, 0xDD, 0x4F, 0xDD, 0xC1, 0x8F, 0x97, 0x4F, 0x3B, 0x1E, 0x57, 0xD2, 0xFD, 0xC5, 0x47, 0x6F, + 0x7B, 0x7E, 0x69, 0xE1, 0xF2, 0xBB, 0x0F, 0x61, 0x6D, 0x7D, 0xE0, 0xC8, 0xF3, 0xA0, 0x5E, 0xD9, 0x1A, 0xD0, 0xE0, 0x9F, + 0xB6, 0x8D, 0x64, 0xF9, 0x77, 0x0A, 0x78, 0x2E, 0xF9, 0x31, 0x90, 0x81, 0xF5, 0xE9, 0x90, 0xFD, 0x27, 0xD3, 0x6C, 0x2B, + 0xEA, 0xE3, 0x15, 0x62, 0x4D, 0xFD, 0x98, 0x27, 0xD8, 0x82, 0x79, 0x93, 0xB7, 0x14, 0x30, 0xED, 0x31, 0xCE, 0xCE, 0x51, + 0xB2, 0x1D, 0x71, 0xA3, 0xC8, 0xEF, 0x2E, 0x91, 0x44, 0xA5, 0x6E, 0x4D, 0xE2, 0xA3, 0x29, 0x86, 0x27, 0x17, 0x12, 0x92, + 0x00, 0xFD, 0x11, 0x02, 0x4E, 0x59, 0xD5, 0x35, 0x5D, 0xAD, 0x10, 0x20, 0x4E, 0x86, 0x7F, 0x86, 0x08, 0xE2, 0xD5, 0x32, + 0x76, 0x21, 0x17, 0x24, 0xEC, 0x5E, 0x78, 0x72, 0xC5, 0xC9, 0x98, 0xC9, 0xA8, 0xE8, 0x99, 0x4B, 0x7B, 0xC9, 0x64, 0xB4, + 0x8E, 0xDD, 0x73, 0x64, 0xC6, 0xC6, 0x59, 0x73, 0x77, 0x19, 0xA6, 0x6B, 0x4F, 0x8E, 0x16, 0xD3, 0xF9, 0x02, 0x7F, 0xF7, + 0x87, 0xA3, 0x02, 0x50, 0x76, 0xFB, 0x1A, 0x4D, 0xCE, 0x93, 0xF8, 0x28, 0x28, 0xB7, 0xA3, 0x35, 0x70, 0xF5, 0xCF, 0xC7, + 0x41, 0x87, 0xBF, 0xF5, 0x0B, 0x7B, 0x94, 0xC7, 0x90, 0xCB, 0x2B, 0x29, 0x35, 0xF8, 0x9A, 0x98, 0xFC, 0xE0, 0x6B, 0x1B, + 0xEF, 0x13, 0x1B, 0xF4, 0xEF, 0xAA, 0x6B, 0x37, 0x04, 0x5B, 0x08, 0xA6, 0x73, 0xEC, 0xCA, 0xE8, 0x01, 0x86, 0x56, 0x9B, + 0xDE, 0x6E, 0x1D, 0x07, 0xF9, 0x6F, 0x7B, 0xBB, 0xC1, 0xE6, 0x75, 0x70, 0x51, 0x39, 0xDC, 0x82, 0x5C, 0x53, 0x72, 0x6A, + 0x4E, 0xCC, 0x4D, 0x24, 0x4E, 0xE8, 0x62, 0x4E, 0x64, 0x1C, 0xA2, 0x46, 0xD7, 0x67, 0x02, 0x5D, 0xEC, 0x69, 0x51, 0xFB, + 0xCC, 0xD2, 0x7B, 0xCF, 0x92, 0x84, 0xDD, 0x9B, 0x13, 0x58, 0x49, 0xE9, 0x30, 0x31, 0xF5, 0x31, 0x53, 0x8C, 0x6B, 0xAA, + 0xF7, 0x70, 0xEE, 0xB2, 0x97, 0x22, 0xB5, 0x73, 0x26, 0xDF, 0x83, 0x01, 0x5D, 0x18, 0xF2, 0x80, 0x6A, 0xAD, 0xBC, 0x04, + 0xB4, 0xDA, 0x04, 0xC4, 0xDB, 0x65, 0x90, 0x24, 0xF4, 0x57, 0x3D, 0x8D, 0x1D, 0xD3, 0xD2, 0xCA, 0xB7, 0x65, 0x29, 0x8C, + 0x55, 0x93, 0x39, 0xD4, 0xF5, 0x51, 0x33, 0xE1, 0x1F, 0x46, 0x9D, 0x76, 0xED, 0xB2, 0x22, 0x99, 0x94, 0x27, 0x8D, 0xC7, + 0xF2, 0xB0, 0xEA, 0xD7, 0xA3, 0x61, 0x7A, 0xF5, 0x94, 0x91, 0x77, 0x85, 0x31, 0xC2, 0x11, 0x12, 0x20, 0x90, 0x73, 0x9E, + 0x15, 0x52, 0x60, 0xB6, 0xD7, 0x45, 0x4F, 0x5E, 0x60, 0x07, 0xE5, 0x16, 0x3D, 0x55, 0x8A, 0x56, 0x3B, 0x3D, 0xBE, 0xD7, + 0x25, 0xFA, 0x83, 0x76, 0x66, 0xD5, 0x7C, 0xF5, 0xDA, 0x58, 0xA5, 0xCE, 0xF6, 0x8D, 0xBC, 0x95, 0x11, 0x6B, 0x28, 0x1D, + 0x4A, 0xDB, 0xE4, 0x0D, 0x53, 0xFD, 0x34, 0x9F, 0xA1, 0xE7, 0x2D, 0x6B, 0x29, 0xAC, 0x43, 0xFB, 0x8E, 0xCD, 0xEC, 0x73, + 0xA9, 0x34, 0xA1, 0x75, 0xE4, 0x49, 0xC6, 0x8D, 0x3E, 0xB5, 0x91, 0x83, 0x6A, 0x2A, 0x1D, 0x64, 0xC7, 0xC3, 0x86, 0x2F, + 0x90, 0x38, 0x49, 0x6D, 0x1C, 0x14, 0xFE, 0x27, 0x07, 0x9B, 0x42, 0x3C, 0xFD, 0x7E, 0x83, 0x98, 0xD0, 0xDE, 0x58, 0xC8, + 0x55, 0xB3, 0x46, 0x5B, 0xE4, 0xD5, 0xD7, 0x48, 0x09, 0xC8, 0x8F, 0x60, 0x4C, 0x38, 0x60, 0x0D, 0xBD, 0x14, 0xF8, 0x70, + 0xEB, 0x29, 0x87, 0xDF, 0xFB, 0xB9, 0x65, 0x22, 0x33, 0xDE, 0xE3, 0x4A, 0x7E, 0xBF, 0x2E, 0xC7, 0x87, 0x36, 0x41, 0xE8, + 0x95, 0x8D, 0xB5, 0xDA, 0x1C, 0x29, 0x3D, 0x71, 0x39, 0x6E, 0x40, 0x36, 0x8C, 0x5D, 0x3E, 0x63, 0x72, 0x08, 0xE2, 0x9A, + 0x13, 0x61, 0x87, 0x8D, 0xF6, 0xFC, 0x6F, 0xF7, 0x05, 0xCE, 0x50, 0xD7, 0x17, 0xEF, 0xAF, 0xD6, 0xAD, 0x42, 0x0A, 0x5B, + 0xB3, 0x36, 0x80, 0x89, 0x50, 0x64, 0x5F, 0x0C, 0x87, 0x0B, 0x93, 0x84, 0x5E, 0x80, 0xD9, 0x02, 0xF5, 0x29, 0x9F, 0xA4, + 0x20, 0xBD, 0x24, 0x46, 0x63, 0x80, 0xC8, 0x8D, 0x47, 0xAE, 0x44, 0xF4, 0x0D, 0x3A, 0xDA, 0xB4, 0x1F, 0xB1, 0x5C, 0xFE, + 0xEA, 0x9E, 0xFC, 0x4F, 0x75, 0x5E, 0x01, 0x46, 0xD2, 0x8F, 0x59, 0xA5, 0xC6, 0xB0, 0x3A, 0x62, 0xDE, 0xBE, 0xAD, 0x73, + 0x6A, 0x32, 0x45, 0x73, 0xB2, 0xE3, 0xE6, 0xB5, 0x9F, 0xD8, 0xC3, 0x5F, 0xB9, 0x72, 0x58, 0xC4, 0xE3, 0x0B, 0xBE, 0x42, + 0xF3, 0xA7, 0x83, 0xEC, 0xE3, 0x47, 0xC6, 0xDD, 0xB9, 0xD7, 0x02, 0x4D, 0x30, 0x32, 0xB0, 0x45, 0x23, 0x88, 0xDE, 0x0F, + 0xA1, 0x65, 0x8B, 0x50, 0xBA, 0xD6, 0x18, 0xF7, 0x27, 0x8A, 0x62, 0xB6, 0x1E, 0xAB, 0xED, 0x64, 0xE2, 0x07, 0x6A, 0xD4, + 0xA0, 0xC9, 0xB1, 0xD5, 0x9E, 0x53, 0xD8, 0xE7, 0xCF, 0xF9, 0x5C, 0xD1, 0xE7, 0x87, 0xCB, 0x8A, 0x38, 0x94, 0xB6, 0x6A, + 0xE3, 0x59, 0xE2, 0x4E, 0x16, 0x25, 0xD2, 0xB5, 0x5F, 0x0A, 0xEC, 0x2A, 0xB9, 0xEB, 0x31, 0x7A, 0xFA, 0x6C, 0xFF, 0xFA, + 0x2A, 0xEE, 0x24, 0x10, 0x21, 0x44, 0xE5, 0xB8, 0x0E, 0x04, 0x5E, 0x08, 0x8E, 0xF8, 0x9B, 0x1D, 0x79, 0x31, 0x01, 0x56, + 0xC9, 0x32, 0xBF, 0xDE, 0x54, 0x67, 0x33, 0xE6, 0x5C, 0x96, 0x33, 0x4F, 0xDA, 0xDB, 0x09, 0x36, 0x22, 0x0F, 0xA5, 0xF8, + 0xF8, 0x1A, 0x22, 0x0A, 0x48, 0x03, 0x02, 0x2C, 0x1A, 0x6E, 0x32, 0x76, 0xDF, 0xC7, 0xEC, 0xD4, 0x38, 0x93, 0x2C, 0x98, + 0x89, 0xD9, 0xB7, 0xD8, 0x04, 0xAC, 0xDB, 0xFC, 0x3D, 0x1F, 0x5A, 0x54, 0x8F, 0x9C, 0xD3, 0x0E, 0x63, 0x84, 0xDC, 0x06, + 0x9C, 0x6D, 0x57, 0x8B, 0xEA, 0xCF, 0xAD, 0xD1, 0xFE, 0x2C, 0xF6, 0xBB, 0x43, 0x85, 0x0B, 0x11, 0x45, 0x29, 0x63, 0xD9, + 0x66, 0x2F, 0x7C, 0xDD, 0x2F, 0x3C, 0xFB, 0xD2, 0x63, 0xE0, 0x95, 0xC3, 0xEE, 0x38, 0xAB, 0x24, 0x3E, 0x69, 0xF6, 0xA0, + 0x71, 0x90, 0x88, 0xCF, 0x9C, 0xED, 0xC2, 0xA5, 0x01, 0x2E, 0x64, 0x34, 0x3F, 0xCA, 0xE4, 0xB6, 0x31, 0xD1, 0x15, 0xE3, + 0xA4, 0x29, 0x05, 0xA6, 0x6D, 0xB9, 0x2E, 0x43, 0x4C, 0xEF, 0xAF, 0x27, 0x71, 0xF0, 0xA6, 0xFF, 0x74, 0x6F, 0x35, 0xF5, + 0xC2, 0x9E, 0xDD, 0x2C, 0xF6, 0xEC, 0x8C, 0x96, 0xCF, 0xDE, 0xED, 0x22, 0xA0, 0xC0, 0xBA, 0x71, 0xBD, 0x92, 0xF7, 0x5F, + 0xC1, 0x50, 0xEA, 0x28, 0x1A, 0x57, 0xE0, 0x43, 0x0A, 0x1A, 0xEC, 0x3E, 0xDA, 0xF6, 0x4D, 0x80, 0x3F, 0x5E, 0x8C, 0x07, + 0x51, 0x34, 0xD6, 0xA3, 0x83, 0xD6, 0x95, 0xB6, 0xCE, 0xBF, 0x54, 0xF0, 0xD2, 0xFB, 0xAB, 0x44, 0x13, 0xD5, 0x6D, 0xD5, + 0x26, 0x96, 0xD7, 0xD7, 0x21, 0x76, 0xE8, 0x19, 0x4B, 0x1A, 0xE3, 0x39, 0xB1, 0x88, 0x3B, 0xC7, 0xD0, 0x89, 0x97, 0xBD, + 0x99, 0xB9, 0xD6, 0x35, 0xC7, 0xF3, 0x5A, 0x4C, 0x18, 0x3A, 0xC3, 0x1C, 0x77, 0x58, 0xDC, 0xDF, 0xD2, 0x5D, 0x1C, 0xE3, + 0x98, 0x56, 0xB6, 0x2C, 0xD8, 0x15, 0x34, 0xA4, 0xAE, 0x52, 0x08, 0x7E, 0x3C, 0xB7, 0x6F, 0xAD, 0x15, 0x18, 0x1A, 0xA3, + 0x07, 0x7C, 0xA2, 0xF2, 0x34, 0xAE, 0xB7, 0x63, 0x15, 0x36, 0xAB, 0xC2, 0x4A, 0xAB, 0x78, 0x7D, 0xEB, 0x76, 0x7C, 0x3B, + 0x25, 0x67, 0x9C, 0xEE, 0x52, 0x8F, 0x24, 0xE9, 0x6C, 0x5F, 0xE8, 0x44, 0xF7, 0x8A, 0x95, 0xEF, 0x2D, 0xC7, 0x98, 0x64, + 0xD0, 0x59, 0x9E, 0x44, 0x0D, 0x46, 0x21, 0x8F, 0x07, 0x11, 0xC0, 0x32, 0xD5, 0xC5, 0xB9, 0xCB, 0xD9, 0x6B, 0x45, 0xF4, + 0xD9, 0x1A, 0x47, 0x9E, 0xE1, 0xFC, 0x33, 0xAA, 0xA8, 0x14, 0x5F, 0x22, 0x5A, 0x5C, 0x97, 0x7D, 0x9D, 0x9C, 0x38, 0xD9, + 0x12, 0x25, 0x8B, 0x86, 0x5A, 0x1D, 0x5F, 0xEE, 0xAE, 0xED, 0x0A, 0x92, 0xCD, 0x82, 0x70, 0x6B, 0x6D, 0x7F, 0xEB, 0x96, + 0x5B, 0xEE, 0x10, 0x27, 0x3C, 0xEE, 0xFF, 0x16, 0x43, 0x33, 0xC7, 0x4C, 0x37, 0x81, 0xE1, 0x9E, 0x14, 0x88, 0x0D, 0x98, + 0x97, 0xB2, 0xF6, 0x3E, 0x3B, 0x80, 0x05, 0x45, 0xB4, 0xE2, 0x11, 0xE9, 0x29, 0x8E, 0x93, 0xFF, 0x67, 0xEC, 0x62, 0xB7, + 0x9B, 0x33, 0xC2, 0xF0, 0xE6, 0xF7, 0x28, 0xBE, 0xD3, 0x7F, 0x43, 0x29, 0xB7, 0xBF, 0x60, 0x46, 0x4C, 0xC7, 0x47, 0xCB, + 0x25, 0xE4, 0x17, 0xD6, 0x50, 0xAA, 0xBF, 0x67, 0xB6, 0x5A, 0xB9, 0x10, 0x65, 0xA8, 0x07, 0x89, 0xB6, 0x66, 0x2F, 0xAE, + 0xDA, 0x0B, 0xD5, 0xA1, 0xB2, 0x0B, 0x63, 0xFE, 0xC0, 0x15, 0x61, 0x14, 0xC1, 0x67, 0x57, 0x93, 0xA4, 0xC5, 0xD7, 0xEF, + 0xB9, 0x78, 0x38, 0xF1, 0x13, 0x30, 0x06, 0x53, 0xE4, 0x63, 0xDD, 0x54, 0xFD, 0x54, 0x9C, 0x53, 0x7D, 0x88, 0xCD, 0xAE, + 0x12, 0x0A, 0x0A, 0xB5, 0x4E, 0xA5, 0xED, 0x10, 0x0E, 0xF9, 0x90, 0xED, 0x2D, 0xB2, 0xC5, 0xBE, 0x13, 0x31, 0xAF, 0x79, + 0x9F, 0xA9, 0xE3, 0x96, 0x23, 0xC8, 0xFB, 0x0B, 0x34, 0x56, 0xF3, 0xB6, 0xB4, 0x47, 0xD0, 0xEF, 0x9E, 0x47, 0x4B, 0x19, + 0xE6, 0x86, 0xCA, 0x79, 0x62, 0x06, 0x44, 0xBF, 0x93, 0x56, 0xF3, 0x2B, 0x20, 0x87, 0x5C, 0x8F, 0x2D, 0x5C, 0xB8, 0x2E, + 0x62, 0x03, 0x4A, 0xD8, 0x46, 0xEE, 0x4A, 0xFD, 0x30, 0x41, 0x6F, 0xB2, 0x8F, 0x42, 0x94, 0x59, 0xBE, 0xEC, 0xE9, 0x8A, + 0x13, 0xC2, 0x82, 0xF6, 0xFA, 0x64, 0x3A, 0x68, 0x2B, 0x85, 0x43, 0xBF, 0x36, 0x7D, 0x9B, 0x5B, 0x4C, 0x1A, 0x21, 0x1F, + 0x5E, 0x41, 0x6A, 0xAD, 0x0D, 0x5B, 0x95, 0xEB, 0x33, 0xA2, 0xD3, 0x5F, 0x2E, 0xC9, 0xDB, 0xEC, 0x7C, 0xAE, 0xB7, 0xB8, + 0x5C, 0x65, 0xFD, 0x93, 0xE1, 0xDC, 0xC3, 0xA7, 0xA3, 0x70, 0xA2, 0xC7, 0xD7, 0x7D, 0xA4, 0x5F, 0x23, 0x63, 0xD1, 0x69, + 0x56, 0xED, 0x5E, 0xAF, 0x66, 0x91, 0x04, 0xD6, 0x25, 0x5C, 0xB4, 0xBD, 0x9C, 0xD0, 0x61, 0xD9, 0xBA, 0xAC, 0x24, 0xD0, + 0xD4, 0xBE, 0xEC, 0x1D, 0x53, 0xE2, 0xEF, 0x17, 0xFB, 0x22, 0xBB, 0xBF, 0x5E, 0xF7, 0x21, 0xD0, 0xC1, 0x6C, 0x32, 0xC7, + 0xFD, 0xFA, 0xE4, 0x81, 0x9B, 0xD6, 0x1F, 0x81, 0xDF, 0x97, 0x2D, 0xBB, 0x60, 0x07, 0xB6, 0x19, 0x9F, 0x25, 0x01, 0x56, + 0x1A, 0x5D, 0xBC, 0x48, 0xDC, 0xB6, 0xBC, 0xB7, 0x8C, 0x58, 0xCC, 0xC7, 0x5D, 0x5A, 0x2F, 0xC6, 0xA0, 0xBF, 0x02, 0x34, + 0x9C, 0x1B, 0xA7, 0x67, 0x9B, 0x6F, 0x59, 0x78, 0xD2, 0x7D, 0xAD, 0xBF, 0xD3, 0xD5, 0x7D, 0x72, 0x40, 0xDB, 0x03, 0xDB, + 0x84, 0xED, 0x5D, 0x07, 0x43, 0x54, 0x7C, 0xFA, 0x44, 0x89, 0x9C, 0x3E, 0xB5, 0x17, 0xF6, 0x73, 0x3F, 0xB6, 0x34, 0x2C, + 0xFD, 0x9A, 0x76, 0xF3, 0x2B, 0x6B, 0x65, 0xF9, 0xE1, 0x88, 0x5C, 0xBB, 0x49, 0xD8, 0xC9, 0xD8, 0x5E, 0xEB, 0x5E, 0xED, + 0xCD, 0xBA, 0x03, 0xED, 0x47, 0xF8, 0x88, 0x39, 0xEC, 0x07, 0xED, 0xAE, 0x5F, 0xE1, 0x2D, 0x64, 0xAB, 0x69, 0x6F, 0xD2, + 0x84, 0x64, 0x6D, 0xBF, 0x64, 0x59, 0xDF, 0xFD, 0xF3, 0xF6, 0x2F, 0xD8, 0x28, 0x35, 0xD8, 0x77, 0xE0, 0x13, 0x60, 0xC2, + 0x85, 0x98, 0xA6, 0x1D, 0xF2, 0xBD, 0x0E, 0xC4, 0xBA, 0x90, 0x90, 0x66, 0x1B, 0x48, 0xDA, 0x98, 0x4C, 0x6D, 0x80, 0x43, + 0x9E, 0xBC, 0x24, 0xB9, 0x45, 0x8F, 0xB0, 0xBC, 0xCC, 0x68, 0x4D, 0x5B, 0x63, 0x71, 0xC9, 0x56, 0x9E, 0xDE, 0x90, 0x3B, + 0xBB, 0xDD, 0x26, 0x23, 0xBF, 0x42, 0x25, 0x81, 0x87, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, 0xF3, 0x34, 0xAF, 0xBA, 0xEF, + 0xA3, 0xD5, 0x11, 0x53, 0x38, 0x0F, 0xE8, 0x20, 0xE9, 0xE5, 0x09, 0xF6, 0x76, 0xF5, 0x0C, 0x64, 0x22, 0x5F, 0x66, 0x1D, + 0xA0, 0xE2, 0xA6, 0xD6, 0x33, 0x84, 0x94, 0xE9, 0x29, 0x4D, 0xD5, 0x3B, 0xB2, 0x60, 0x2F, 0x08, 0xA8, 0x33, 0x83, 0x55, + 0x3B, 0x26, 0xD6, 0x89, 0xBE, 0x0B, 0x32, 0xF3, 0x81, 0xDE, 0x88, 0xC2, 0xF5, 0x58, 0xE7, 0x32, 0x70, 0x3C, 0x21, 0x00, + 0x06, 0x4A, 0x63, 0xB2, 0x92, 0xA4, 0x41, 0xA7, 0xFF, 0x06, 0x8E, 0x4C, 0x46, 0x26, 0x58, 0x6C, 0x01, 0x1E, 0x08, 0xC1, + 0xA8, 0x2D, 0xB0, 0xD0, 0xC4, 0x54, 0x58, 0x65, 0x2B, 0x98, 0x97, 0xE1, 0xEC, 0xA4, 0x98, 0x5B, 0xF5, 0x06, 0x97, 0x1E, + 0xC3, 0x06, 0xC2, 0xEC, 0xF0, 0x6B, 0x64, 0xD5, 0xCD, 0x25, 0xCF, 0xBD, 0x47, 0xEA, 0xF5, 0x99, 0x54, 0x0A, 0xF3, 0xF0, + 0x90, 0x87, 0xFB, 0xF3, 0x0E, 0xC2, 0x7A, 0x28, 0x9D, 0xCB, 0xB5, 0x5E, 0xC5, 0x2A, 0x26, 0x4E, 0xD5, 0xDE, 0x41, 0xF0, + 0xE0, 0x44, 0x1B, 0xEC, 0xE6, 0x66, 0x52, 0x90, 0x4F, 0xAB, 0x36, 0xA3, 0xB2, 0xB8, 0x41, 0xF1, 0x54, 0xB1, 0xDA, 0x9E, + 0x3D, 0x85, 0xBF, 0xAD, 0x86, 0xD6, 0xEC, 0x43, 0x0A, 0xD6, 0x75, 0x58, 0x99, 0x46, 0xB5, 0x31, 0x14, 0x8D, 0x7F, 0xC9, + 0xC1, 0x44, 0xA4, 0xA3, 0x32, 0xDA, 0x43, 0xCC, 0x44, 0x1D, 0xDA, 0x48, 0x9D, 0x7D, 0x30, 0x79, 0x58, 0x01, 0x82, 0x0E, + 0x5E, 0xCC, 0x42, 0x59, 0x2F, 0x63, 0xF4, 0x84, 0x73, 0x20, 0x4A, 0x44, 0x32, 0x4E, 0xBA, 0x3D, 0xE0, 0x60, 0xAF, 0xCD, + 0xCA, 0x9E, 0x18, 0x6E, 0xE5, 0x27, 0x31, 0x69, 0xCB, 0xD7, 0x40, 0xBE, 0xEA, 0x13, 0xDB, 0x1E, 0xAF, 0x43, 0x36, 0x2E, + 0x84, 0x4C, 0x4C, 0x51, 0xF8, 0x89, 0x91, 0x83, 0x78, 0x69, 0x91, 0xB1, 0x81, 0xEF, 0xFA, 0xB9, 0xEC, 0x33, 0x6A, 0xA6, + 0x03, 0xF6, 0x52, 0x17, 0xD1, 0xEF, 0x20, 0xE3, 0x19, 0x6E, 0xBB, 0xB8, 0x37, 0xBB, 0x22, 0x7C, 0x09, 0x0B, 0x30, 0x31, + 0x86, 0xCC, 0x3B, 0xAD, 0xA6, 0xF0, 0x5E, 0xB2, 0xCF, 0x3B, 0x46, 0x9A, 0x64, 0xCD, 0x21, 0xC7, 0x0B, 0xEF, 0xD4, 0x91, + 0xDA, 0x16, 0xE6, 0xE7, 0x0A, 0x9E, 0xE0, 0x35, 0xFA, 0x6C, 0x59, 0x4A, 0x7C, 0xDE, 0x9B, 0xC5, 0x24, 0xE5, 0xFC, 0x94, + 0x36, 0x3B, 0x1C, 0xB4, 0x05, 0x14, 0xAA, 0xCD, 0xF2, 0x84, 0x93, 0xD4, 0x25, 0xE4, 0x86, 0x2F, 0x90, 0x33, 0xE4, 0x1E, + 0x73, 0x18, 0xDD, 0xB4, 0x3B, 0xDE, 0x54, 0x45, 0x81, 0x16, 0xA5, 0x84, 0x45, 0x3B, 0x75, 0xA5, 0xD1, 0x90, 0xEB, 0xDC, + 0x7F, 0xF0, 0x5C, 0x16, 0x90, 0x49, 0xC1, 0x2E, 0x12, 0xBF, 0xA0, 0x09, 0xE3, 0xEC, 0xC8, 0xF4, 0x73, 0x17, 0x5D, 0xA6, + 0x2E, 0xC9, 0x4F, 0xBC, 0xCF, 0xC7, 0x36, 0x28, 0x5B, 0xAC, 0x85, 0x33, 0x91, 0x09, 0xC8, 0x2B, 0xDC, 0x16, 0x94, 0x8F, + 0x1B, 0x7D, 0x35, 0xF8, 0x25, 0x1B, 0x48, 0x4C, 0x5B, 0xD8, 0x16, 0xFA, 0x98, 0x58, 0xBA, 0xCA, 0x66, 0x30, 0xAD, 0x6E, + 0xEE, 0xB8, 0x74, 0x6D, 0xFC, 0x34, 0xBB, 0xE6, 0x0A, 0xB6, 0xA9, 0xA0, 0x35, 0x90, 0xD9, 0x3A, 0x48, 0xD3, 0x0E, 0x39, + 0xB7, 0xDD, 0xFE, 0x5A, 0x22, 0x0E, 0x46, 0x2E, 0x51, 0x2D, 0xD6, 0x17, 0xBF, 0x01, 0x88, 0xC5, 0x85, 0xD1, 0xCE, 0xB9, + 0x3B, 0x06, 0xDE, 0xBE, 0x3F, 0x9D, 0xF2, 0x10, 0xCE, 0x1F, 0xD6, 0xE0, 0x9A, 0xD2, 0xFF, 0x5B, 0xAA, 0x14, 0x46, 0x49, + 0xCA, 0x0C, 0xFC, 0x6D, 0xEE, 0x4F, 0xC4, 0xAA, 0x38, 0x6E, 0xAD, 0xBF, 0x5C, 0x0F, 0x5A, 0xA2, 0x7A, 0x5D, 0x9D, 0x07, + 0xE8, 0x4E, 0x4E, 0x8E, 0x8F, 0xF9, 0x5E, 0x46, 0x3B, 0x89, 0xED, 0x46, 0x1C, 0xE1, 0x0E, 0x0A, 0x8C, 0x9A, 0xE0, 0x51, + 0x48, 0x8C, 0xF3, 0x25, 0x03, 0x72, 0xBB, 0x65, 0x02, 0x20, 0xE8, 0xC1, 0x6B, 0x60, 0x2B, 0x44, 0x9F, 0x50, 0xF8, 0x34, + 0xFB, 0x8B, 0x9B, 0xF4, 0xA8, 0x0D, 0x49, 0x11, 0x0C, 0xCD, 0x8B, 0xB4, 0xA0, 0x4D, 0xD8, 0x60, 0x92, 0x02, 0x52, 0xFC, + 0x5D, 0xF2, 0x01, 0xC8, 0x2C, 0x80, 0xC7, 0x0E, 0x3C, 0x32, 0x71, 0x04, 0x3A, 0xC8, 0x19, 0x34, 0xED, 0xE4, 0xC8, 0x9C, + 0x56, 0x89, 0xFC, 0x9D, 0xF7, 0x6E, 0xE6, 0x97, 0x01, 0xDD, 0x7D, 0xA5, 0x67, 0x0A, 0xFC, 0xF6, 0x4F, 0xE9, 0x54, 0xE4, + 0x47, 0xED, 0xF0, 0x05, 0xA4, 0xC4, 0x2B, 0xD7, 0x77, 0x09, 0x8E, 0x9B, 0xC6, 0x7D, 0x0A, 0x85, 0x3F, 0x97, 0x17, 0xD7, + 0xB7, 0x87, 0xFE, 0xA4, 0xE3, 0xA1, 0x3E, 0xF7, 0xC3, 0xD6, 0x7C, 0x04, 0xAF, 0x61, 0xD9, 0xF9, 0x34, 0x05, 0xDA, 0x3C, + 0x77, 0xA7, 0xE6, 0xD0, 0x2F, 0x57, 0xA4, 0x16, 0xB7, 0x79, 0x86, 0x89, 0x16, 0x81, 0xD4, 0x18, 0xF4, 0xA6, 0x4F, 0x82, + 0xB1, 0x8D, 0xC4, 0x13, 0x45, 0xED, 0x5D, 0x23, 0x65, 0x9B, 0x23, 0x3D, 0xFC, 0x30, 0x24, 0xD8, 0x48, 0x41, 0x8D, 0x16, + 0xB6, 0x9B, 0xAB, 0x1A, 0x68, 0x26, 0xF9, 0x00, 0x61, 0xEF, 0xC0, 0xCB, 0xEC, 0x7A, 0x5B, 0x4C, 0xE9, 0xA9, 0x5C, 0x37, + 0x83, 0x0A, 0x6A, 0x0B, 0xBF, 0x26, 0x9E, 0x82, 0xEB, 0x8E, 0xF3, 0x2E, 0x16, 0x47, 0x79, 0xDF, 0x2F, 0x5C, 0x13, 0x3C, + 0x5C, 0x12, 0x5A, 0x36, 0x7C, 0x19, 0xC4, 0x53, 0xD2, 0x6B, 0xE7, 0x8B, 0xC8, 0x8D, 0x18, 0xAD, 0x1C, 0x86, 0xB1, 0x95, + 0xCF, 0x8E, 0xE6, 0x6B, 0x5E, 0x9C, 0x2B, 0x7B, 0x9F, 0x3F, 0x93, 0xDD, 0x96, 0x90, 0xC1, 0x3C, 0x0D, 0x8F, 0xFA, 0x3F, + 0x97, 0x62, 0x31, 0x79, 0x57, 0x90, 0xDC, 0x82, 0x8D, 0xF2, 0xB4, 0x40, 0x2C, 0xC1, 0x8C, 0x14, 0x78, 0x90, 0xFC, 0x6F, + 0x85, 0x4A, 0x18, 0xF4, 0xCA, 0x1A, 0xE3, 0x2A, 0x9D, 0xEB, 0x83, 0x25, 0x05, 0x5E, 0xF8, 0xBB, 0xCF, 0x9A, 0xA7, 0xDC, + 0x15, 0x6D, 0x31, 0x17, 0x93, 0x26, 0x05, 0x12, 0xD0, 0x9E, 0x9C, 0x17, 0xAE, 0xE8, 0xD5, 0x93, 0x0C, 0x36, 0x66, 0xB3, + 0xE3, 0x79, 0x2E, 0xCD, 0x3F, 0x82, 0xDC, 0x3D, 0x15, 0xB9, 0xAE, 0xD3, 0x16, 0xB9, 0x2F, 0xE2, 0x1D, 0x54, 0xF5, 0xA6, + 0x6A, 0x5F, 0x91, 0x15, 0x21, 0x77, 0xFD, 0xB9, 0xB5, 0x9D, 0xC5, 0xAC, 0x61, 0x95, 0xA2, 0xDF, 0x88, 0x5E, 0xDD, 0x2D, + 0xB6, 0xDB, 0x65, 0xD6, 0xC6, 0x18, 0xDA, 0x8C, 0x3B, 0x0A, 0x64, 0xE2, 0x76, 0x36, 0xD2, 0x93, 0xEB, 0x94, 0x90, 0xB5, + 0xF4, 0x08, 0x6C, 0xB4, 0xD4, 0x49, 0x6C, 0x08, 0x1E, 0xC6, 0x8A, 0x62, 0x89, 0xD5, 0xB4, 0xEE, 0xD7, 0xFC, 0xF6, 0xB5, + 0x46, 0x0C, 0xC8, 0x97, 0xF3, 0x55, 0xEE, 0x0F, 0x25, 0x93, 0xD0, 0x99, 0x9C, 0x26, 0xAD, 0x84, 0x72, 0x2C, 0x71, 0xCE, + 0xFD, 0xE6, 0x41, 0xB2, 0x45, 0x0B, 0x99, 0x6D, 0xDE, 0x5F, 0x67, 0xB0, 0x90, 0x4E, 0x24, 0x3C, 0xDD, 0x57, 0xA9, 0xE8, + 0xDD, 0xD4, 0x1B, 0xFD, 0x46, 0x10, 0x74, 0x3F, 0xA3, 0xC6, 0x81, 0x86, 0x9C, 0xFF, 0x77, 0x46, 0xA9, 0xED, 0x9E, 0xAC, + 0x7F, 0x9C, 0xB6, 0x7E, 0x99, 0xD6, 0xEC, 0xEA, 0x5F, 0x7C, 0xD9, 0xBA, 0x5C, 0x9D, 0xD6, 0x0E, 0xC4, 0xB2, 0x76, 0xE6, + 0xE8, 0xCC, 0x9E, 0xBF, 0xC4, 0xF0, 0x47, 0x5F, 0x5A, 0x64, 0x9F, 0x4D, 0xB7, 0x01, 0xB3, 0x6F, 0xA0, 0xE1, 0xC9, 0xC6, + 0xDD, 0x1E, 0x30, 0xDF, 0xA9, 0xDF, 0xD7, 0x8F, 0xB7, 0xB0, 0x97, 0xC7, 0x0E, 0xC4, 0xF5, 0xFB, 0x5C, 0x52, 0x91, 0xF2, + 0x21, 0xE0, 0xBD, 0x44, 0x52, 0x62, 0xD0, 0x2C, 0xF9, 0x48, 0xB6, 0x42, 0xBB, 0xC3, 0x02, 0x14, 0xA2, 0xAC, 0x48, 0x0C, + 0x33, 0x63, 0xD8, 0x28, 0x63, 0x03, 0x34, 0x47, 0x37, 0xC7, 0x61, 0x40, 0x7B, 0x0F, 0x04, 0x0E, 0x5A, 0x2D, 0xD1, 0xA5, + 0x90, 0xDE, 0x90, 0x43, 0x3B, 0xA1, 0x1C, 0xA3, 0x7E, 0x63, 0x08, 0x33, 0x97, 0x53, 0x98, 0x17, 0xC7, 0x33, 0x49, 0xC6, + 0xB7, 0xCE, 0x16, 0x7E, 0x2C, 0xF1, 0xA1, 0xE4, 0xC4, 0x9B, 0xF3, 0x56, 0x9E, 0xA1, 0x67, 0x16, 0xB9, 0xF5, 0xFB, 0xE5, + 0xFF, 0x16, 0xB6, 0xFD, 0xFA, 0x36, 0x6A, 0x74, 0xC6, 0x53, 0xA0, 0xF0, 0x40, 0x1B, 0x13, 0xC5, 0xD2, 0x53, 0xFF, 0xEC, + 0xFA, 0xD1, 0x0F, 0x52, 0xC6, 0xED, 0xB1, 0x25, 0xC3, 0xEB, 0x32, 0xAA, 0x85, 0x47, 0x9F, 0xEB, 0x78, 0x34, 0xF8, 0x6B, + 0x5F, 0xF3, 0x87, 0xCD, 0xC3, 0x18, 0xDD, 0xF7, 0x2C, 0xA5, 0xC3, 0x4C, 0x58, 0xB4, 0x53, 0x68, 0x08, 0xD4, 0xC4, 0xBF, + 0x72, 0xC7, 0x9A, 0xE5, 0x68, 0x4B, 0x0D, 0x19, 0x66, 0x09, 0x4D, 0x7F, 0x93, 0x41, 0xB3, 0xC3, 0xB8, 0xCA, 0x92, 0x38, + 0xB0, 0xF5, 0x89, 0x05, 0x49, 0xBD, 0x19, 0x28, 0x19, 0xE7, 0xC5, 0x5E, 0xBA, 0xEB, 0x44, 0x4D, 0x0B, 0x43, 0x1B, 0x04, + 0x60, 0xA2, 0x9C, 0x42, 0x36, 0x09, 0x4F, 0xC3, 0x54, 0x96, 0x2F, 0x36, 0x8B, 0x01, 0xFC, 0xF9, 0x70, 0x9B, 0x0C, 0x67, + 0x04, 0x02, 0x0B, 0x2E, 0xA1, 0xF7, 0x1C, 0x67, 0x6D, 0x4F, 0x9C, 0xE6, 0xF0, 0xEE, 0x60, 0x8B, 0x8D, 0xE2, 0xD3, 0x85, + 0x4B, 0xF6, 0xFC, 0x0B, 0x2B, 0xDB, 0xBD, 0xF8, 0x73, 0xED, 0x32, 0xC9, 0x1C, 0xF1, 0xB0, 0x92, 0xDC, 0x4E, 0x48, 0x77, + 0x08, 0x02, 0x7C, 0xF4, 0x6F, 0x3C, 0xBD, 0x88, 0x01, 0x5F, 0xDB, 0x80, 0xDB, 0xB4, 0x0C, 0x9F, 0x29, 0x52, 0xA4, 0x00, + 0x03, 0x98, 0x3F, 0xDB, 0x08, 0xC3, 0xAA, 0x14, 0xBA, 0xB3, 0xCC, 0x88, 0x41, 0xA5, 0x34, 0x67, 0x03, 0x37, 0xB0, 0xCF, + 0xAB, 0x6B, 0x94, 0xAC, 0x98, 0xB2, 0x06, 0xB1, 0x7C, 0x81, 0x3D, 0x76, 0xDE, 0x22, 0xEA, 0xD3, 0xCE, 0x8D, 0xAB, 0x00, + 0x3A, 0xD1, 0x5A, 0xFE, 0x80, 0x91, 0xAD, 0x4D, 0xB7, 0x43, 0x47, 0xB3, 0x52, 0x8A, 0x8F, 0x4A, 0x1A, 0xF0, 0x26, 0xDE, + 0xF4, 0xE0, 0xBB, 0x26, 0xB0, 0x1C, 0xD0, 0x26, 0xF0, 0x57, 0xDC, 0x53, 0x93, 0x7B, 0x2F, 0xD4, 0xDF, 0x51, 0xB4, 0x56, + 0x30, 0x93, 0x09, 0xE3, 0x95, 0x46, 0xBC, 0xB4, 0x7D, 0x78, 0xA2, 0x32, 0x78, 0xBD, 0x61, 0xA7, 0xF3, 0x16, 0xB6, 0x1A, + 0x2A, 0xA1, 0xB5, 0xA5, 0x4C, 0x79, 0xFE, 0xD6, 0x77, 0xD2, 0xF5, 0x26, 0x8F, 0x9A, 0x7B, 0x4A, 0x8D, 0xF3, 0x97, 0x2A, + 0x50, 0x7A, 0xB5, 0x34, 0xD4, 0xEB, 0xF3, 0x7D, 0x9B, 0x39, 0x77, 0x68, 0x74, 0x1A, 0xA8, 0x1D, 0x1A, 0x87, 0xCE, 0x9C, + 0x19, 0x75, 0xF0, 0x38, 0x9D, 0xF9, 0x3C, 0x3C, 0x7D, 0x64, 0xCC, 0x2F, 0x5B, 0xD4, 0x5C, 0x89, 0xD3, 0x7A, 0xB5, 0x9E, + 0x1B, 0x19, 0x14, 0x1C, 0xEE, 0x0A, 0xE9, 0x08, 0x75, 0xD7, 0x35, 0x06, 0x42, 0xE8, 0xB5, 0x38, 0xC0, 0x32, 0x17, 0x3D, + 0xEF, 0xCB, 0x4B, 0x2E, 0x85, 0x71, 0xE1, 0xFF, 0x41, 0xB9, 0x57, 0x8B, 0x34, 0x35, 0x25, 0x5C, 0xA2, 0xDF, 0x9C, 0x53, + 0xD9, 0x7A, 0xE6, 0x52, 0xBF, 0x89, 0x5F, 0x0C, 0x33, 0x92, 0x64, 0x0B, 0xA1, 0xF6, 0x20, 0x1E, 0x10, 0x99, 0xC7, 0x38, + 0x4A, 0x5E, 0x03, 0xBE, 0x86, 0x97, 0xB5, 0xFA, 0x80, 0xB8, 0xDB, 0xEA, 0x5B, 0xF4, 0xEA, 0xC2, 0xC0, 0x6B, 0xDC, 0xAE, + 0x8F, 0xB5, 0x3D, 0xFD, 0x17, 0x1B, 0xDB, 0x7F, 0xF8, 0xF9, 0xE6, 0x60, 0xFB, 0x0C, 0xA2, 0x66, 0x10, 0x84, 0xB5, 0xA0, + 0x86, 0xC0, 0xD6, 0x86, 0xA1, 0x46, 0xF9, 0x0D, 0x3B, 0xFD, 0x83, 0x69, 0xC4, 0x1C, 0xB9, 0x59, 0x44, 0x63, 0x6A, 0x06, + 0xC4, 0x1E, 0x6B, 0x1E, 0xA0, 0x56, 0xB8, 0xFA, 0x94, 0xE3, 0xF1, 0x2F, 0x04, 0x80, 0x26, 0x67, 0xD2, 0x4F, 0x16, 0x5C, + 0x4D, 0x79, 0xB1, 0x87, 0xA6, 0xBB, 0x06, 0xB7, 0xD9, 0x17, 0x83, 0x86, 0xBF, 0x3C, 0x9F, 0x80, 0xA7, 0x5B, 0xD7, 0xF3, + 0xE5, 0xAA, 0x0E, 0xF0, 0xBA, 0x80, 0xD8, 0xE2, 0x4F, 0x17, 0x84, 0xD2, 0xFB, 0xA5, 0x4F, 0x7A, 0x95, 0xAF, 0xDF, 0xED, + 0xAC, 0x73, 0xFE, 0x4E, 0xBE, 0x74, 0xA1, 0x46, 0xE7, 0xC7, 0x89, 0xC1, 0x6A, 0xE7, 0xC2, 0x64, 0x12, 0x10, 0x4E, 0x3B, + 0xF7, 0xC4, 0xC5, 0x11, 0x04, 0x53, 0x0F, 0x35, 0x75, 0xF2, 0x27, 0xE9, 0xC3, 0x13, 0x55, 0xE5, 0xDB, 0xEF, 0xF1, 0x19, + 0x2D, 0x7B, 0x1A, 0xFD, 0x72, 0xB8, 0x50, 0x2A, 0x4A, 0x58, 0x5E, 0x5D, 0x3E, 0x1E, 0x71, 0x1A, 0x76, 0xC9, 0x8A, 0xD3, + 0x1B, 0xD9, 0xFA, 0x37, 0x5F, 0xC1, 0x38, 0xCE, 0x16, 0x78, 0x90, 0xD6, 0x70, 0x83, 0x1B, 0xFC, 0xAE, 0xAC, 0x63, 0xAF, + 0xD8, 0x8F, 0x8D, 0x8A, 0x0A, 0xE2, 0xEB, 0x1F, 0xBD, 0x5F, 0xDE, 0xEE, 0x3E, 0xA9, 0x39, 0x61, 0x8C, 0x8B, 0xC2, 0x4D, + 0x7A, 0x87, 0x30, 0x55, 0x64, 0x38, 0x63, 0xCC, 0x1D, 0x2A, 0xC0, 0x75, 0xA2, 0x63, 0x1E, 0xEC, 0x57, 0x01, 0x14, 0xCC, + 0xE4, 0x6B, 0x75, 0x3E, 0x4B, 0xAB, 0xD2, 0xF0, 0xDB, 0x59, 0x01, 0xFC, 0x5C, 0x6B, 0xC3, 0x51, 0x02, 0x03, 0xDB, 0xB0, + 0x32, 0xA3, 0x45, 0x9A, 0x2E, 0x8E, 0xA9, 0x95, 0x7D, 0xEA, 0x35, 0xC8, 0x9F, 0x20, 0xE7, 0xD8, 0x3E, 0x25, 0xDE, 0x60, + 0xA4, 0xBB, 0xC5, 0x53, 0x7C, 0xE9, 0x1E, 0x1C, 0xCF, 0x43, 0xE0, 0xFC, 0x5C, 0xBD, 0xE2, 0x26, 0x34, 0xD3, 0x36, 0xB5, + 0x08, 0x93, 0x13, 0xA3, 0x5F, 0x6E, 0x96, 0x26, 0xBC, 0xF3, 0xB9, 0x3A, 0x64, 0x51, 0x82, 0x06, 0xBF, 0xF2, 0x7A, 0x82, + 0x45, 0x0D, 0xB7, 0xFE, 0x5F, 0xF6, 0xF5, 0xAF, 0x40, 0x90, 0x93, 0x07, 0x96, 0x9E, 0x17, 0x36, 0x52, 0xFF, 0xAE, 0xB5, + 0x86, 0x57, 0x16, 0xE3, 0xA5, 0x4F, 0xC3, 0x07, 0x1C, 0x90, 0x20, 0x04, 0xB4, 0x97, 0xE0, 0x39, 0xDF, 0xC5, 0xC7, 0xE5, + 0xB2, 0x02, 0xCC, 0x54, 0x89, 0x3B, 0x8E, 0xC1, 0x4D, 0x73, 0xD2, 0xFA, 0x5F, 0xB8, 0xFC, 0x03, 0xB5, 0x95, 0xB4, 0x65, + 0x9E, 0x84, 0x86, 0x38, 0x6E, 0x15, 0xAF, 0x39, 0x36, 0x46, 0xD2, 0x7C, 0x8D, 0x60, 0x35, 0xBB, 0x6D, 0xF0, 0x57, 0x20, + 0x6D, 0x3C, 0x12, 0xA6, 0x8B, 0x3D, 0xDE, 0xC5, 0x3B, 0x32, 0x85, 0x75, 0xF4, 0x71, 0x99, 0x19, 0x3B, 0x13, 0x86, 0x93, + 0xCD, 0x19, 0x08, 0x12, 0xE1, 0x6E, 0xD0, 0x93, 0x97, 0x9B, 0x66, 0x97, 0x2B, 0x09, 0x0E, 0xEC, 0x5F, 0x95, 0x1B, 0x29, + 0xCE, 0x9B, 0xEE, 0x4D, 0x1B, 0x54, 0x07, 0x61, 0xD9, 0x8C, 0x9F, 0xBF, 0xE1, 0x15, 0x3F, 0xB2, 0xEA, 0xAA, 0x1B, 0xDC, + 0x9A, 0x5C, 0x04, 0x1F, 0xB9, 0x1F, 0x6F, 0x87, 0x1D, 0xA0, 0xBE, 0xA9, 0xEB, 0x8B, 0xE9, 0x2C, 0x81, 0x54, 0x04, 0xCE, + 0xD2, 0xD8, 0x66, 0x3D, 0x4E, 0x11, 0x28, 0xD9, 0x6A, 0x77, 0x8E, 0x6C, 0x7F, 0xE4, 0xC9, 0x45, 0x44, 0x2B, 0x90, 0xF3, + 0xD6, 0x2C, 0xDF, 0xE0, 0xF3, 0x69, 0x56, 0x5D, 0x00, 0x3D, 0xD4, 0xCC, 0x7A, 0x48, 0x72, 0x1F, 0xB6, 0x46, 0x45, 0xEF, + 0x6B, 0xC8, 0xAD, 0xEE, 0x5D, 0xBF, 0xEF, 0x2A, 0x7D, 0xDF, 0xF7, 0x36, 0xB9, 0x45, 0x21, 0xF4, 0xA9, 0x91, 0x3F, 0x26, + 0x3D, 0xBE, 0x50, 0x0D, 0x7B, 0x4C, 0xD9, 0xAB, 0xB5, 0x81, 0x70, 0x3E, 0x62, 0x4D, 0x91, 0x26, 0x54, 0x0C, 0x58, 0x80, + 0x7D, 0xBA, 0x30, 0xEF, 0x22, 0x56, 0x40, 0xB1, 0x72, 0x2B, 0x9F, 0x8F, 0x11, 0x24, 0x43, 0x85, 0xAB, 0xDC, 0x9D, 0xE3, + 0xA3, 0x85, 0x09, 0x5C, 0x29, 0x28, 0x45, 0xEF, 0x23, 0x5D, 0x0A, 0xE9, 0x81, 0xF8, 0x31, 0x52, 0x4B, 0x2B, 0xA1, 0xD1, + 0x91, 0x42, 0xF9, 0x37, 0x84, 0x6E, 0xE1, 0xE0, 0x9E, 0x27, 0xB9, 0x22, 0xF9, 0x55, 0xE9, 0xFA, 0x43, 0xF5, 0xE8, 0x9F, + 0xDF, 0x99, 0x19, 0xD2, 0x83, 0x4A, 0x8E, 0x79, 0xFA, 0x54, 0xBB, 0x8A, 0xCE, 0xE8, 0x75, 0x0B, 0xCE, 0x3A, 0x6C, 0x3E, + 0x1B, 0x4A, 0x8B, 0x58, 0xB3, 0xE5, 0x6B, 0xFE, 0x39, 0xCB, 0xB6, 0x9A, 0x27, 0xF0, 0x71, 0xA0, 0x20, 0x57, 0x83, 0x48, + 0xB2, 0xE5, 0xCE, 0xEA, 0x32, 0xCE, 0xEE, 0x4C, 0x23, 0xF6, 0xDB, 0xF4, 0x88, 0x4A, 0x83, 0x7E, 0xBF, 0x38, 0x86, 0x21, + 0x6A, 0x59, 0x56, 0xA9, 0x1B, 0x9B, 0x8F, 0x8F, 0x36, 0xD6, 0x5E, 0xA3, 0xE6, 0xC9, 0x4A, 0x98, 0x51, 0x4F, 0xE7, 0x57, + 0x2D, 0xB6, 0x4D, 0x8D, 0x7D, 0x48, 0x7B, 0x05, 0x3F, 0x66, 0x91, 0x09, 0xF4, 0x2A, 0x83, 0x4F, 0xDC, 0xE7, 0xCB, 0xB9, + 0x6E, 0x65, 0xB1, 0xE3, 0xAA, 0x5C, 0xB8, 0x78, 0x68, 0x4D, 0x83, 0x2C, 0x56, 0xED, 0x70, 0xB7, 0xFE, 0x03, 0x92, 0x69, + 0x1E, 0x05, 0x72, 0x82, 0xA3, 0x9D, 0x65, 0x45, 0x5C, 0x4F, 0x72, 0xA2, 0x86, 0x90, 0xDF, 0xD8, 0x6E, 0x58, 0x1B, 0x90, + 0x83, 0x00, 0x0C, 0x78, 0x72, 0x71, 0x7E, 0xCD, 0xF0, 0x70, 0xAE, 0x3F, 0x61, 0xDB, 0x49, 0x6B, 0x58, 0x44, 0xA8, 0xEB, + 0xB4, 0x6D, 0x51, 0x5B, 0x49, 0x6B, 0xAB, 0x1A, 0xAA, 0x22, 0x20, 0x71, 0x6E, 0xF0, 0xC7, 0xBA, 0xDD, 0xDC, 0x00, 0x73, + 0xA2, 0xC4, 0xBF, 0x43, 0xEE, 0x38, 0xD4, 0x69, 0x77, 0xAB, 0x6C, 0x4C, 0x8A, 0x3D, 0x54, 0x80, 0x8D, 0x1C, 0xD5, 0x33, + 0x94, 0x6E, 0x7C, 0x87, 0x40, 0xDA, 0xDD, 0x52, 0x61, 0x3C, 0xAB, 0xE3, 0xC1, 0xCA, 0x01, 0xFF, 0x6E, 0x4D, 0x91, 0x25, + 0x9C, 0x43, 0x0E, 0xC5, 0xBE, 0xFF, 0x17, 0x83, 0x80, 0xC3, 0x30, 0x52, 0x27, 0x39, 0x36, 0x53, 0x82, 0xB8, 0x62, 0x72, + 0x33, 0x73, 0x79, 0x44, 0x54, 0x14, 0x8E, 0x26, 0x11, 0x74, 0x37, 0xA0, 0x4C, 0xD9, 0x2B, 0x9A, 0xFF, 0x82, 0x56, 0xD2, + 0xE1, 0x71, 0x0C, 0xA8, 0x65, 0xC1, 0xA7, 0xB7, 0x8A, 0x76, 0x83, 0xF5, 0x8F, 0x44, 0x7D, 0x3B, 0x2F, 0x8B, 0xD9, 0x0E, + 0x4E, 0x07, 0xB2, 0x1E, 0x03, 0x80, 0xDD, 0xE1, 0x72, 0x06, 0x05, 0xE1, 0x4A, 0x34, 0x5C, 0x51, 0xAC, 0x2A, 0xBA, 0x8F, + 0x82, 0x53, 0x1D, 0x89, 0x4F, 0xD7, 0x66, 0x96, 0xB9, 0x15, 0x01, 0x7C, 0x30, 0x24, 0xD6, 0xA5, 0xBA, 0x23, 0x9E, 0xB9, + 0x85, 0xFE, 0x6E, 0x86, 0xE4, 0x14, 0x0E, 0xDB, 0x17, 0x27, 0x1A, 0x3C, 0x22, 0xAC, 0x4E, 0x54, 0x83, 0xA4, 0x05, 0x6B, + 0x8B, 0xDA, 0xB8, 0xC7, 0xA8, 0x3E, 0x6C, 0x45, 0x14, 0xA1, 0x90, 0x6D, 0xFC, 0x34, 0x0D, 0x7B, 0x2B, 0xCF, 0xF4, 0x63, + 0x39, 0x2A, 0x25, 0x3B, 0x3D, 0x58, 0x67, 0x99, 0xCA, 0xEC, 0xA1, 0xB6, 0x4B, 0x18, 0x06, 0x70, 0x6E, 0xB7, 0x2F, 0x9B, + 0x48, 0xD5, 0x1A, 0xEE, 0x3E, 0x3E, 0x6E, 0x52, 0x2A, 0xDF, 0xD8, 0xF1, 0xD0, 0x4C, 0x07, 0xEF, 0xCE, 0x82, 0xA6, 0x0C, + 0x1A, 0xDC, 0x3E, 0xBA, 0x88, 0x97, 0x38, 0x2F, 0xD9, 0x31, 0x77, 0x63, 0xE9, 0x8C, 0x04, 0xF1, 0x13, 0x4F, 0x72, 0x5D, + 0xDD, 0x1F, 0x85, 0x3F, 0x98, 0x04, 0x5E, 0x9F, 0x14, 0x62, 0xCA, 0x17, 0x12, 0x0E, 0x40, 0x1C, 0x95, 0x8D, 0x58, 0x04, + 0x2D, 0x57, 0x93, 0x1F, 0xE7, 0x81, 0xB3, 0x66, 0x44, 0x6D, 0x86, 0x70, 0xC7, 0x59, 0x88, 0x72, 0x62, 0x71, 0x60, 0x7F, + 0xC7, 0x15, 0x03, 0x34, 0x49, 0xFA, 0x43, 0x23, 0x06, 0x56, 0x5A, 0x17, 0xE3, 0x12, 0x0F, 0x42, 0xA5, 0xE2, 0xE8, 0x9D, + 0x73, 0xF2, 0x21, 0x06, 0xE6, 0x5B, 0x93, 0xEC, 0xF6, 0x53, 0xAE, 0x51, 0x87, 0xCC, 0xCE, 0x51, 0x2A, 0x8D, 0x28, 0xDE, + 0xEF, 0x75, 0xE2, 0xA4, 0x5E, 0xCE, 0x4D, 0xE6, 0x3C, 0xBA, 0xDA, 0xE2, 0x20, 0x25, 0x11, 0x21, 0x73, 0x0C, 0xFE, 0x7F, + 0xFC, 0xE1, 0x00, 0xF0, 0xCA, 0xFC, 0xC5, 0xF2, 0x21, 0x24, 0x86, 0x3D, 0xE7, 0x82, 0xFD, 0x8C, 0xF5, 0x9C, 0x4A, 0x81, + 0x6A, 0x7B, 0xB9, 0x6F, 0xD0, 0x55, 0x49, 0xD9, 0x86, 0x85, 0xD3, 0xE7, 0x1A, 0x08, 0x41, 0x93, 0xC3, 0x89, 0xF1, 0x46, + 0x23, 0xFD, 0x5A, 0x2D, 0x6F, 0x0C, 0xB5, 0xFD, 0x98, 0x25, 0x6A, 0x6F, 0xB7, 0x53, 0xD0, 0x36, 0x5D, 0x28, 0xAE, 0xFC, + 0x0B, 0xF9, 0x92, 0xE4, 0x3C, 0x31, 0x77, 0xF6, 0x36, 0xC9, 0x6A, 0x1A, 0xA0, 0xE2, 0x5B, 0xE3, 0xDC, 0x01, 0xF1, 0x4D, + 0x77, 0xCE, 0x53, 0xD6, 0xC4, 0x88, 0x89, 0xA7, 0x7B, 0xA6, 0x99, 0xBB, 0x91, 0xCB, 0x07, 0x60, 0x4F, 0xD4, 0x60, 0x19, + 0xB2, 0xEB, 0xB9, 0xD7, 0x27, 0x36, 0x5F, 0xCE, 0x74, 0xF2, 0x46, 0x3C, 0xBD, 0x27, 0x23, 0x82, 0xDE, 0x8E, 0xC5, 0xA7, + 0xDC, 0x80, 0x0A, 0x08, 0x67, 0x80, 0x39, 0xC2, 0xFE, 0xA2, 0x7A, 0x18, 0xF8, 0xA8, 0x34, 0xB9, 0x8D, 0xE5, 0x59, 0xA9, + 0x22, 0x81, 0x68, 0x7E, 0xA6, 0xEC, 0xA0, 0x0E, 0xC8, 0x1D, 0xE8, 0x0D, 0x2D, 0x43, 0x33, 0x5F, 0x08, 0x9C, 0xF7, 0x94, + 0x76, 0xDE, 0x43, 0xBC, 0x15, 0x92, 0xFE, 0x04, 0x9D, 0x79, 0x8A, 0xE0, 0xDB, 0xF5, 0xC4, 0xC4, 0x20, 0xBD, 0x4C, 0x64, + 0x78, 0xCB, 0x0C, 0x86, 0x99, 0x90, 0xCA, 0x7F, 0x92, 0xD3, 0x97, 0x51, 0xA3, 0xB9, 0x67, 0x50, 0xE7, 0x05, 0xCF, 0xD0, + 0x8A, 0x9F, 0x1D, 0xDC, 0xA2, 0xE2, 0x5C, 0xC0, 0x66, 0xCD, 0x36, 0x45, 0x66, 0x06, 0x0D, 0xB7, 0x53, 0xE9, 0x7D, 0x65, + 0x27, 0x47, 0xAB, 0xF5, 0x0A, 0x2E, 0x10, 0x51, 0xD6, 0xC1, 0xDF, 0xB3, 0xF4, 0x83, 0x5E, 0x20, 0x8A, 0x9B, 0xF4, 0xE3, + 0x08, 0xB2, 0xB4, 0x5E, 0x66, 0x09, 0x0C, 0xF7, 0x4E, 0x59, 0x34, 0xDA, 0xA5, 0x19, 0xBA, 0x52, 0x4D, 0x39, 0x1C, 0xB5, + 0x24, 0xD8, 0xB4, 0xF2, 0x7E, 0x6A, 0x05, 0x85, 0xEA, 0x9B, 0xC5, 0x21, 0x17, 0xBF, 0x0D, 0xC4, 0x1B, 0xD9, 0xE0, 0xA0, + 0x34, 0x06, 0xFF, 0xB1, 0x84, 0xD7, 0xD5, 0x2D, 0x1B, 0xBA, 0x25, 0xFB, 0x65, 0x5B, 0x6D, 0xD7, 0xB7, 0xB7, 0x55, 0xE8, + 0xD3, 0xDA, 0x43, 0x61, 0x0F, 0xDF, 0x8E, 0x28, 0xB8, 0x4F, 0x09, 0xFE, 0xFC, 0xB7, 0xEE, 0x47, 0x7D, 0x62, 0xCD, 0x5E, + 0x65, 0x32, 0xE1, 0xBB, 0x6B, 0x73, 0xE8, 0xF8, 0x5B, 0xB8, 0xAD, 0xE9, 0xD3, 0xBA, 0x1F, 0x75, 0x01, 0xD4, 0x4F, 0x8F, + 0xDB, 0x2F, 0x8A, 0xCF, 0xF8, 0xB4, 0xAF, 0x9F, 0xD1, 0x8A, 0xAB, 0xD5, 0x44, 0xA7, 0x88, 0x9F, 0x0C, 0xE4, 0x9C, 0x83, + 0x25, 0x0A, 0x8E, 0x62, 0x1D, 0x58, 0x99, 0x89, 0xC3, 0x0A, 0xE4, 0x88, 0x4D, 0x9C, 0xD2, 0x34, 0x5C, 0xCC, 0x39, 0x15, + 0x8E, 0xC2, 0x90, 0xE6, 0x39, 0x0E, 0xEE, 0x88, 0x84, 0xEC, 0x9E, 0xA1, 0xDC, 0xF0, 0xA7, 0x77, 0x83, 0xDC, 0x99, 0xF6, + 0x4B, 0x28, 0x9F, 0x43, 0x4A, 0xCD, 0x35, 0x4F, 0xB6, 0x9C, 0xDB, 0xB9, 0x20, 0x29, 0xD2, 0xBD, 0x4C, 0xDA, 0x25, 0x8B, + 0x87, 0xEE, 0x8D, 0xFA, 0xF3, 0x91, 0x20, 0x01, 0x8D, 0x08, 0xE9, 0x77, 0x64, 0x23, 0x70, 0x64, 0xC0, 0x4D, 0x28, 0x34, + 0xF7, 0x0E, 0x0D, 0x56, 0x49, 0x1A, 0xEE, 0x29, 0xFA, 0xD0, 0x5C, 0x56, 0x20, 0x61, 0xA6, 0xF5, 0x30, 0x65, 0x81, 0x02, + 0x53, 0x4E, 0x3F, 0x9C, 0x1D, 0xAF, 0x1B, 0x23, 0x63, 0x59, 0xAF, 0x84, 0x1A, 0x28, 0x99, 0x77, 0xA0, 0x43, 0xB3, 0x86, + 0xE5, 0x8C, 0x41, 0x98, 0x43, 0x4B, 0xE0, 0x46, 0xF3, 0xEA, 0x32, 0x48, 0x02, 0x0C, 0x1E, 0x9F, 0x6D, 0x64, 0xC6, 0xBE, + 0x43, 0x86, 0x01, 0xE6, 0xD2, 0xAC, 0x9A, 0x49, 0x6B, 0x08, 0xAE, 0xD6, 0x93, 0xDC, 0x4E, 0xD1, 0xA8, 0x66, 0xF8, 0x34, + 0xF0, 0x61, 0xC1, 0x02, 0x14, 0x00, 0x01, 0x78, 0xA2, 0x0B, 0x57, 0x58, 0xA1, 0x99, 0x8B, 0x9A, 0x71, 0x60, 0x95, 0x12, + 0xD9, 0x2B, 0xF1, 0xB5, 0xC7, 0x8A, 0x03, 0x8E, 0xA9, 0x44, 0xD8, 0x84, 0xAA, 0x73, 0x26, 0xD2, 0x2A, 0xEA, 0x11, 0xCB, + 0xF1, 0xD9, 0x3A, 0x4A, 0xBF, 0x2D, 0xB2, 0xA6, 0x59, 0x18, 0x32, 0xAA, 0x05, 0x69, 0x4A, 0xC5, 0xE0, 0x21, 0xEC, 0x4A, + 0xEA, 0x4F, 0xCE, 0xF8, 0x6A, 0xCF, 0x47, 0x8B, 0x55, 0x05, 0xE5, 0xAC, 0x71, 0x29, 0x2B, 0xD6, 0x4A, 0x42, 0xB5, 0x8D, + 0xD3, 0xCE, 0xE7, 0x1B, 0x81, 0x67, 0x09, 0x0E, 0xED, 0x28, 0x13, 0x8B, 0x68, 0xD4, 0xA5, 0x99, 0x7E, 0xC0, 0xD4, 0x0B, + 0x68, 0x20, 0x4D, 0xFE, 0x1E, 0x1C, 0x2C, 0xC8, 0xA3, 0x9D, 0xF2, 0x69, 0x31, 0xD5, 0xD6, 0x1B, 0x68, 0x21, 0x6C, 0xBE, + 0xF8, 0x48, 0x42, 0xF5, 0x4D, 0xAC, 0xCF, 0x1C, 0x43, 0x6B, 0x4F, 0x0A, 0xC1, 0x22, 0xA3, 0x4F, 0xEA, 0xA5, 0x4B, 0xF4, + 0x23, 0xBF, 0xF6, 0x1E, 0xA3, 0xC7, 0xE9, 0xDD, 0xE7, 0x03, 0xB3, 0xD9, 0x82, 0x00, 0xE5, 0x1B, 0x29, 0x6F, 0xFB, 0x45, + 0x32, 0xD6, 0xEC, 0x84, 0xA5, 0x90, 0xFC, 0x80, 0x36, 0xB0, 0x6C, 0xD2, 0x9B, 0xAF, 0xEA, 0x9D, 0x85, 0xD3, 0x88, 0x72, + 0xA3, 0x59, 0xB4, 0x6B, 0xF9, 0x80, 0xD9, 0x94, 0x88, 0xF8, 0x4C, 0xB7, 0x90, 0x30, 0x65, 0xC5, 0xE7, 0x99, 0xAA, 0xE7, + 0x47, 0x57, 0xD5, 0xFC, 0x00, 0x1E, 0x86, 0x56, 0x80, 0xD2, 0xC4, 0x73, 0x23, 0x5B, 0x2D, 0x86, 0xC1, 0x57, 0x45, 0xB4, + 0xE7, 0x89, 0xA3, 0x69, 0xD2, 0x33, 0x53, 0x44, 0x4E, 0xB1, 0xFC, 0x94, 0x36, 0x3B, 0x6C, 0x52, 0x32, 0x54, 0x64, 0x93, + 0x7C, 0xAB, 0x32, 0x71, 0xD6, 0xB6, 0x5B, 0x36, 0xB1, 0x31, 0x3C, 0x44, 0xB6, 0xF4, 0x75, 0x8A, 0xE6, 0x80, 0xBE, 0xBE, + 0xCA, 0x35, 0xFD, 0x37, 0x30, 0x32, 0x5D, 0xE5, 0x4B, 0xF0, 0x61, 0x87, 0xFC, 0x09, 0x1D, 0x22, 0x81, 0xBA, 0x94, 0xB7, + 0x4C, 0x33, 0x65, 0x14, 0x6A, 0x9A, 0x8B, 0x8A, 0xDD, 0xD1, 0x1E, 0x78, 0x57, 0x17, 0xBE, 0x76, 0x94, 0x35, 0xCF, 0x2C, + 0x27, 0x38, 0xBA, 0x07, 0x7E, 0x82, 0x6E, 0xDC, 0x26, 0x14, 0x5D, 0x6F, 0x4D, 0x57, 0x1F, 0x5A, 0xEC, 0xD9, 0xCA, 0xCF, + 0x6E, 0x06, 0xB3, 0x79, 0x57, 0x15, 0x10, 0x7E, 0xC4, 0xA7, 0x77, 0xE9, 0x27, 0xD1, 0xD2, 0xB3, 0xDA, 0x8E, 0x05, 0x98, + 0x0A, 0x1D, 0xB1, 0xA0, 0x73, 0x32, 0x8F, 0xA7, 0x99, 0xAF, 0x46, 0xBD, 0x02, 0xE0, 0xD5, 0x28, 0x67, 0xBC, 0x80, 0x8A, + 0x28, 0x3A, 0x7A, 0x86, 0xE3, 0x01, 0xEE, 0x12, 0x87, 0xCD, 0x70, 0xE4, 0x0A, 0xBD, 0x35, 0x3E, 0x9A, 0xB7, 0x62, 0xF1, + 0xC2, 0xFE, 0xE1, 0xCD, 0xDA, 0x82, 0x50, 0x4D, 0xC6, 0x12, 0xE7, 0xF1, 0x1B, 0xB4, 0x7B, 0x97, 0x63, 0x01, 0xA8, 0x93, + 0x88, 0xE1, 0x8F, 0xEC, 0x60, 0x17, 0xB0, 0x3F, 0x1A, 0xB0, 0x63, 0x38, 0x42, 0x26, 0xE4, 0x79, 0x8D, 0x84, 0x28, 0x06, + 0x8C, 0x1E, 0x86, 0x3B, 0x3E, 0xCC, 0x84, 0x40, 0xC9, 0x36, 0xC8, 0x22, 0xBD, 0xA3, 0x92, 0xF2, 0x01, 0xA5, 0x96, 0x4F, + 0x74, 0xA5, 0x87, 0xDA, 0x41, 0x1D, 0x18, 0x45, 0xF6, 0x62, 0x89, 0x96, 0xB7, 0x16, 0x9F, 0xA6, 0x5E, 0x7A, 0xCE, 0x59, + 0x12, 0x1D, 0x83, 0x17, 0xF5, 0x4D, 0x80, 0xB3, 0xD1, 0x81, 0xD0, 0x64, 0xB7, 0x2A, 0x95, 0xB6, 0x10, 0xA1, 0x0F, 0xC4, + 0x59, 0x4E, 0xA0, 0x77, 0xCD, 0x8C, 0xDA, 0xB9, 0x10, 0x55, 0x32, 0xE6, 0x2A, 0x29, 0x88, 0x94, 0xFA, 0xEB, 0xFE, 0x61, + 0x01, 0x64, 0x7F, 0x7E, 0x6C, 0xA5, 0x2C, 0x4C, 0x65, 0x87, 0x2A, 0x79, 0x39, 0x50, 0x3F, 0x52, 0xFE, 0xC4, 0xF0, 0xBA, + 0x9A, 0xE4, 0x2B, 0x13, 0x65, 0x33, 0x61, 0x78, 0xBC, 0x52, 0x71, 0xD7, 0xEB, 0x59, 0xB2, 0x37, 0xE8, 0x87, 0xF6, 0x12, + 0x3B, 0xE4, 0xFC, 0x48, 0xC7, 0xA5, 0xCA, 0x8A, 0x3F, 0x9A, 0x82, 0x84, 0x1F, 0x50, 0x5B, 0xC1, 0xB3, 0xCE, 0xE2, 0xCC, + 0xF0, 0x45, 0x52, 0xF2, 0x17, 0xC4, 0xB9, 0x19, 0xF4, 0xF3, 0x8E, 0x45, 0xEE, 0xCF, 0xE4, 0xDC, 0x59, 0x6C, 0x9B, 0x89, + 0xAE, 0xBA, 0x85, 0x36, 0x18, 0x0E, 0x3B, 0x99, 0x39, 0xC5, 0xE7, 0xCD, 0x35, 0xB0, 0x4B, 0xBB, 0xD1, 0x84, 0xE9, 0xCF, + 0x6A, 0x00, 0x33, 0x8C, 0xAE, 0xEB, 0x08, 0xDD, 0xB5, 0x5A, 0x6A, 0x22, 0x46, 0x3D, 0x22, 0xAA, 0xAD, 0xA8, 0xC1, 0xCA, + 0x48, 0x76, 0x3D, 0x12, 0x87, 0x11, 0xAA, 0x6F, 0x54, 0x20, 0xEB, 0xDC, 0x9F, 0x7C, 0x84, 0x5E, 0x87, 0x74, 0xC5, 0x4F, + 0xFE, 0x12, 0x5D, 0x87, 0xEE, 0xAE, 0xFB, 0x89, 0x8C, 0xE0, 0x10, 0x7A, 0xB6, 0xEB, 0xDC, 0x35, 0x2B, 0x72, 0xFC, 0xBB, + 0x90, 0x2F, 0xD3, 0x0F, 0x97, 0xA0, 0x6E, 0xF9, 0x4F, 0xC7, 0xC0, 0xFB, 0xA9, 0x14, 0x28, 0x85, 0x85, 0x18, 0x9A, 0x5B, + 0x32, 0x0A, 0x23, 0xD0, 0x8F, 0x93, 0xB4, 0x22, 0x7C, 0x9E, 0xE8, 0xF0, 0x64, 0xD1, 0xE6, 0x94, 0x7F, 0xDD, 0x71, 0xF2, + 0x61, 0xF4, 0x0B, 0x17, 0xAC, 0x8C, 0x65, 0x61, 0x26, 0x9A, 0x9A, 0xC7, 0xF4, 0xA9, 0x0B, 0x07, 0x69, 0x74, 0x12, 0x9A, + 0x00, 0xF1, 0x55, 0xF1, 0xE4, 0x13, 0x97, 0x04, 0x94, 0x4C, 0x90, 0xC0, 0xF2, 0x6C, 0x92, 0x4F, 0xF5, 0xB1, 0x31, 0xD3, + 0x5E, 0x1F, 0x84, 0xC4, 0x4A, 0xBB, 0x48, 0x1E, 0xCF, 0x60, 0x0F, 0xC1, 0xD7, 0x0B, 0xAC, 0xE7, 0xF0, 0x9F, 0x63, 0xD4, + 0x03, 0x4E, 0x40, 0x61, 0xE2, 0x97, 0xF4, 0xE2, 0xA2, 0xA8, 0xE5, 0x47, 0xCA, 0xDA, 0xDF, 0x38, 0xB0, 0x97, 0x49, 0x65, + 0x61, 0x94, 0x19, 0x68, 0x03, 0xA0, 0x6B, 0x57, 0xCB, 0x39, 0x69, 0x53, 0xCB, 0xA6, 0x41, 0x60, 0x06, 0x28, 0x56, 0xA8, + 0x4A, 0x0B, 0x5E, 0xE8, 0x6D, 0x99, 0x9C, 0x1D, 0x63, 0x67, 0x6D, 0xAA, 0x53, 0xDB, 0xB2, 0x69, 0xA4, 0x29, 0x56, 0x18, + 0x28, 0xBD, 0x15, 0x1A, 0x66, 0x04, 0x6B, 0xBE, 0x91, 0x68, 0xA9, 0xF9, 0xBF, 0xE9, 0x5F, 0xE9, 0xED, 0x92, 0x0B, 0xFC, + 0xC0, 0x4C, 0x69, 0x03, 0x98, 0x71, 0x8D, 0x5C, 0x84, 0x57, 0x17, 0xCB, 0xA5, 0x94, 0xE7, 0x8E, 0x8E, 0x53, 0x8C, 0x83, + 0xEB, 0xC3, 0xF7, 0xE1, 0x14, 0x4A, 0x6E, 0xE2, 0x66, 0x2D, 0x26, 0x26, 0x3E, 0xBA, 0xB6, 0x37, 0xF3, 0x51, 0xC8, 0x5A, + 0x16, 0xEC, 0xAE, 0xEF, 0x74, 0x30, 0x96, 0x5A, 0x58, 0xC3, 0x42, 0x69, 0x10, 0xBD, 0xE8, 0xF7, 0x94, 0xCD, 0x59, 0x07, + 0xC6, 0x93, 0xAF, 0x58, 0xDD, 0xAE, 0x88, 0x6F, 0xB1, 0xE9, 0x89, 0xE7, 0x17, 0x1D, 0xF8, 0xBB, 0xE7, 0xDD, 0xCF, 0x4A, + 0xB9, 0x35, 0xBF, 0xC6, 0xDF, 0x9D, 0x7F, 0xBF, 0xFF, 0xFF, 0x60, 0x52, 0x64, 0x0D, 0xFF, 0x77, 0xB3, 0x73, 0xEF, 0x67, + 0xC2, 0x4C, 0xC9, 0x7F, 0x56, 0x82, 0x36, 0xD5, 0x22, 0x41, 0x41, 0xF6, 0xF1, 0x85, 0x78, 0x72, 0xB8, 0x4C, 0xA5, 0x76, + 0xF0, 0x3C, 0x59, 0x05, 0x88, 0x5F, 0xFA, 0x76, 0xE8, 0x86, 0xAA, 0x43, 0x1E, 0x4D, 0x80, 0x4F, 0x51, 0x6F, 0x0D, 0x92, + 0x60, 0xBC, 0xF1, 0x54, 0x7A, 0x6B, 0xFA, 0xD3, 0x99, 0x63, 0xB1, 0x57, 0x6C, 0x6F, 0x1E, 0x04, 0xA2, 0xBF, 0xD0, 0xCC, + 0x02, 0x3F, 0xE7, 0x12, 0xBD, 0x40, 0xB6, 0xD5, 0x51, 0x04, 0x9F, 0xFE, 0x74, 0x20, 0xF2, 0xF8, 0xA4, 0xD0, 0x00, 0xED, + 0xC1, 0x41, 0x8E, 0x4B, 0x75, 0x24, 0x59, 0xB9, 0x1C, 0x44, 0xD7, 0x23, 0xAE, 0x59, 0x45, 0x89, 0xC8, 0x0B, 0x0E, 0x9A, + 0xF6, 0xA3, 0x96, 0x31, 0x85, 0x84, 0x9B, 0x44, 0xF1, 0x65, 0x17, 0x13, 0x80, 0xB7, 0xE3, 0x86, 0xE7, 0xC8, 0x5B, 0x82, + 0xAD, 0xF7, 0x2D, 0x63, 0xC5, 0xF4, 0x52, 0x5A, 0xCA, 0x44, 0xAA, 0x5F, 0x76, 0xC9, 0x8A, 0x19, 0xBC, 0x82, 0x53, 0x2B, + 0x1F, 0xDA, 0x7A, 0x7F, 0x7C, 0x46, 0x5A, 0xA9, 0xD0, 0xC4, 0x3C, 0x4E, 0x56, 0x02, 0x3A, 0x53, 0xA7, 0x23, 0x2C, 0xCB, + 0x64, 0x45, 0xAB, 0xD2, 0x31, 0x29, 0x45, 0x20, 0x3A, 0x46, 0x7A, 0xEC, 0xED, 0xCE, 0xAF, 0xDB, 0x4B, 0x6F, 0x88, 0xD2, + 0xEE, 0x6B, 0x2D, 0xCC, 0x5D, 0x56, 0x0F, 0x4C, 0xC6, 0x4F, 0x0C, 0x8A, 0x5E, 0xC9, 0x47, 0x9F, 0x2A, 0xC3, 0x09, 0xDC, + 0x35, 0x99, 0xB5, 0xA2, 0x1D, 0x6D, 0xB6, 0xE7, 0xA2, 0x42, 0x62, 0x83, 0xE6, 0x01, 0x0B, 0x79, 0xA8, 0x8D, 0xF9, 0xA6, + 0x29, 0xB1, 0xAC, 0x81, 0xCA, 0x03, 0xC4, 0x82, 0xE9, 0x49, 0x12, 0xFF, 0x2E, 0xF0, 0xA6, 0xB5, 0xD7, 0x6D, 0x41, 0x7B, + 0x78, 0xC4, 0x3C, 0x3D, 0xDF, 0x4B, 0x05, 0x82, 0x68, 0x7C, 0x13, 0xAA, 0x44, 0xC5, 0x74, 0xE7, 0x59, 0x5F, 0xBB, 0x20, + 0x30, 0x9B, 0x65, 0x7B, 0xDE, 0x7D, 0x5B, 0x3A, 0xD8, 0xA0, 0x56, 0xAD, 0x40, 0x91, 0xE2, 0x11, 0x90, 0xD2, 0xD1, 0xDF, + 0x8E, 0xCE, 0xD1, 0xBB, 0x92, 0x70, 0x75, 0xA2, 0x02, 0x5F, 0xAB, 0x9D, 0x98, 0x11, 0x6D, 0xD6, 0x9C, 0x1E, 0x4D, 0x00, + 0x6F, 0x92, 0x43, 0x53, 0xA9, 0xD6, 0x4D, 0x46, 0xD7, 0xD3, 0x46, 0x28, 0x70, 0x59, 0x23, 0x84, 0x76, 0x76, 0xF8, 0x73, + 0x0F, 0xFB, 0xC3, 0x97, 0x02, 0xFD, 0x34, 0xE2, 0xDC, 0x0E, 0xB4, 0xA7, 0x11, 0x3C, 0x05, 0xEB, 0x86, 0xD7, 0xC6, 0xF6, + 0xE1, 0x7F, 0xBA, 0xB2, 0x93, 0xE2, 0xC9, 0x33, 0x5B, 0x55, 0x05, 0x10, 0xC8, 0xA6, 0xF5, 0x0F, 0x1B, 0x67, 0xCD, 0x37, + 0x90, 0xD7, 0x8C, 0x92, 0x79, 0xF4, 0x43, 0xC9, 0xC0, 0xF7, 0x5F, 0xE6, 0xC3, 0xE6, 0xE1, 0x6A, 0xAA, 0x74, 0x11, 0x7F, + 0x44, 0xE5, 0x36, 0xA9, 0x89, 0x5E, 0x03, 0xAE, 0x9C, 0x39, 0x6E, 0xDA, 0xD0, 0x14, 0x4E, 0x09, 0xE3, 0x98, 0x3A, 0x0B, + 0xC8, 0xD3, 0xC6, 0xDC, 0x4A, 0x5B, 0x9E, 0xEB, 0x7E, 0x15, 0xD1, 0xB1, 0x53, 0xEB, 0xBF, 0xBC, 0x4B, 0x5C, 0x3F, 0x18, + 0x11, 0x63, 0xF4, 0xBE, 0x08, 0x07, 0xDB, 0x6E, 0x93, 0xE6, 0x98, 0xD9, 0xAD, 0xF0, 0x27, 0x5D, 0xB9, 0xD6, 0xFE, 0xF5, + 0x8D, 0x91, 0x8E, 0x49, 0xC6, 0x3F, 0x0F, 0xFA, 0x8F, 0xF3, 0xF0, 0xC5, 0x02, 0xD1, 0xF6, 0x1F, 0xE9, 0x94, 0xB0, 0x79, + 0xB6, 0x9B, 0xDE, 0x68, 0x80, 0x9E, 0xE4, 0x0F, 0x4B, 0xD2, 0x39, 0xA1, 0x41, 0x37, 0x07, 0x04, 0xFE, 0xE3, 0x03, 0xAE, + 0xEC, 0x16, 0xC6, 0x4D, 0x17, 0xDE, 0x47, 0xC1, 0x0E, 0x9E, 0x99, 0x1D, 0xFF, 0x9B, 0x01, 0x48, 0x14, 0xD2, 0xCA, 0x3A, + 0x12, 0x4E, 0x78, 0x7A, 0x86, 0xEC, 0xFE, 0x3B, 0x35, 0x0B, 0xC0, 0x40, 0x07, 0x30, 0xEF, 0x04, 0x27, 0xB5, 0x10, 0x58, + 0xFC, 0x9D, 0xB0, 0x05, 0x6D, 0xD0, 0x3E, 0x00, 0xC5, 0xE1, 0x80, 0xD9, 0xD6, 0xEC, 0xB8, 0x61, 0x73, 0xE7, 0xF1, 0x30, + 0xFF, 0x81, 0x29, 0x37, 0xAF, 0xCD, 0x71, 0x1B, 0xE4, 0xEC, 0x28, 0x11, 0xCD, 0x5F, 0x97, 0x3A, 0xB4, 0xB0, 0x03, 0xB1, + 0x04, 0x62, 0x40, 0xF5, 0x74, 0xDC, 0x8C, 0xAA, 0xD6, 0xC9, 0xE2, 0xDF, 0x83, 0x79, 0x50, 0xE8, 0x47, 0x64, 0x26, 0x39, + 0xEB, 0x18, 0x10, 0xDA, 0xA2, 0x0C, 0x28, 0x17, 0xCE, 0xF8, 0x78, 0x52, 0x41, 0x45, 0x14, 0xE4, 0x5B, 0xED, 0x86, 0xB3, + 0x06, 0x29, 0x48, 0x08, 0x6B, 0xDA, 0xAE, 0x62, 0xC0, 0xDC, 0x31, 0xB2, 0xFC, 0x1B, 0x49, 0xC0, 0x24, 0x8F, 0x91, 0x70, + 0x2A, 0xA8, 0x43, 0x9B, 0xC7, 0x88, 0x7F, 0x05, 0x3C, 0xF6, 0x8E, 0x8F, 0xD9, 0xEA, 0x9C, 0xAF, 0x7C, 0x28, 0x4A, 0xA8, + 0xC4, 0xAF, 0xDA, 0x4C, 0xEF, 0x95, 0xED, 0xEA, 0x05, 0x52, 0xD1, 0xEF, 0x14, 0xA9, 0xB8, 0xCB, 0xEE, 0x69, 0x41, 0x55, + 0x27, 0x56, 0x4A, 0xE0, 0xAE, 0x87, 0xDC, 0x7D, 0xF6, 0xA9, 0x0B, 0xFB, 0x90, 0xC3, 0x24, 0xD0, 0x69, 0x39, 0x2B, 0x51, + 0x74, 0x97, 0x8D, 0x27, 0x98, 0xDE, 0x09, 0x39, 0xC5, 0x46, 0x82, 0x87, 0x2E, 0xF0, 0x60, 0x8C, 0x66, 0x88, 0x9C, 0xEB, + 0xEB, 0xA5, 0xE2, 0x75, 0x3E, 0x78, 0x8C, 0x47, 0xD6, 0xBD, 0x4A, 0xC0, 0x70, 0x9C, 0x2A, 0x1F, 0xF8, 0xA0, 0xAA, 0x47, + 0x49, 0xE5, 0x84, 0x56, 0xF3, 0xE0, 0x65, 0xCF, 0xD9, 0xB6, 0x67, 0xBE, 0xB0, 0x51, 0x64, 0x64, 0xBA, 0x45, 0x33, 0x22, + 0x8D, 0xE3, 0x32, 0xDA, 0x2A, 0x84, 0x14, 0x2C, 0xB1, 0xC1, 0xC3, 0x19, 0x24, 0x4C, 0x85, 0x56, 0x52, 0x49, 0x1B, 0xC8, + 0x34, 0x94, 0xF2, 0x26, 0xDF, 0xB3, 0x4C, 0xB3, 0x84, 0xD4, 0x78, 0x46, 0x73, 0xF3, 0x87, 0x17, 0xB6, 0xAE, 0x96, 0x65, + 0x13, 0x1E, 0x76, 0x50, 0x41, 0x93, 0xB7, 0x70, 0x1B, 0xB3, 0x23, 0xDD, 0x29, 0xF0, 0xE3, 0xAA, 0x34, 0x3E, 0x31, 0xD1, + 0x66, 0xBE, 0x35, 0xFA, 0xD4, 0x11, 0x7D, 0xF1, 0xFB, 0x18, 0x79, 0x7F, 0x6C, 0xF1, 0xFB, 0xD9, 0x0C, 0x89, 0xEE, 0xFB, + 0x72, 0x63, 0x07, 0x24, 0x4D, 0xBD, 0x30, 0x77, 0xFE, 0xB7, 0x0A, 0xDF, 0x8F, 0x25, 0x96, 0x19, 0x9F, 0xE5, 0x6E, 0x34, + 0x21, 0x4F, 0xBC, 0x97, 0x92, 0xF7, 0xFC, 0x93, 0x5A, 0x97, 0xF4, 0xE2, 0x1C, 0xE4, 0x61, 0x2B, 0xA6, 0xDB, 0x35, 0xD6, + 0xCA, 0x16, 0xD9, 0x70, 0xCC, 0xDE, 0xEF, 0xE5, 0x34, 0x02, 0xA4, 0x13, 0xBB, 0x96, 0xE1, 0xB9, 0x16, 0x48, 0x71, 0xA8, + 0x46, 0x08, 0x7A, 0x06, 0xCF, 0x08, 0x22, 0x76, 0x2C, 0x84, 0xA4, 0x3C, 0x3C, 0xB8, 0x24, 0x54, 0x87, 0x49, 0x76, 0x6B, + 0xBE, 0xB6, 0x28, 0xDD, 0x03, 0x45, 0x3B, 0xED, 0x01, 0xD5, 0x29, 0xC9, 0x7A, 0x72, 0xA6, 0x52, 0xD5, 0x82, 0x18, 0xC1, + 0xBC, 0x9E, 0xA7, 0x8F, 0x5D, 0x15, 0x09, 0x62, 0xAE, 0x75, 0x33, 0x53, 0x36, 0x01, 0xFB, 0xC5, 0x3E, 0xA4, 0xC9, 0xA6, + 0xBE, 0xD1, 0x47, 0xBF, 0x0D, 0xAA, 0xA7, 0x4E, 0xF4, 0xDB, 0x70, 0xC2, 0x0E, 0xEC, 0xD8, 0x7F, 0xB1, 0x4A, 0xC2, 0x88, + 0xD1, 0x80, 0xAC, 0xE3, 0x02, 0x53, 0xEE, 0xD7, 0xCE, 0x86, 0x57, 0xAD, 0x55, 0xB2, 0xC6, 0x05, 0x86, 0xDE, 0x80, 0xF9, + 0xDE, 0x42, 0x61, 0xB8, 0xDF, 0x19, 0xEF, 0xDB, 0xB8, 0x96, 0xCC, 0xA5, 0xDD, 0x2C, 0x57, 0x9D, 0x9C, 0xF2, 0x6F, 0x3D, + 0xA9, 0x65, 0xDE, 0xE3, 0x5A, 0xD1, 0xD3, 0x64, 0xEE, 0xAF, 0x4C, 0xD7, 0x03, 0xCE, 0x5B, 0x00, 0x06, 0x20, 0x5F, 0x64, + 0x67, 0xC5, 0x2E, 0xC2, 0x22, 0xA5, 0xE8, 0x57, 0x60, 0x6B, 0x42, 0xF2, 0x90, 0x18, 0xB2, 0xFF, 0xA8, 0x63, 0xAC, 0x4F, + 0xE2, 0xEC, 0xE1, 0x52, 0xAA, 0xEA, 0x2D, 0x7F, 0x41, 0x1D, 0x41, 0xC4, 0x2A, 0x63, 0x6F, 0x26, 0x35, 0x4D, 0xAB, 0xD5, + 0x9B, 0x53, 0x77, 0x39, 0x7C, 0x8F, 0x4E, 0xA1, 0x69, 0x67, 0xD0, 0x01, 0xC9, 0xBC, 0x29, 0x1C, 0x62, 0xDE, 0x1E, 0xA2, + 0x46, 0x81, 0x9A, 0x66, 0x7A, 0xB5, 0xAB, 0x90, 0x63, 0xB5, 0x8A, 0x51, 0x26, 0x7B, 0x72, 0xE0, 0x8E, 0xAA, 0x9E, 0x79, + 0xF8, 0x41, 0x8B, 0x83, 0xCF, 0x48, 0x66, 0xF1, 0xA8, 0xF8, 0x53, 0x0E, 0x69, 0x42, 0xBF, 0x43, 0xF1, 0x73, 0x2F, 0x67, + 0xA1, 0x63, 0x69, 0x22, 0x08, 0x23, 0xED, 0x75, 0xE0, 0x72, 0x59, 0x37, 0x20, 0x42, 0xC9, 0x8F, 0x6F, 0x4A, 0x81, 0x64, + 0xB0, 0x6D, 0x48, 0x15, 0x19, 0xA7, 0xF9, 0x67, 0x1E, 0xDA, 0x28, 0x8D, 0xBF, 0xB5, 0x6A, 0xDC, 0x68, 0x59, 0x34, 0x34, + 0x68, 0x0D, 0x1F, 0x03, 0x69, 0xA2, 0xA1, 0x89, 0x79, 0xE6, 0xE2, 0x57, 0x5F, 0x9B, 0x16, 0xCE, 0x42, 0x7B, 0x0F, 0x32, + 0x1C, 0x85, 0x05, 0x00, 0x23, 0x7B, 0x53, 0xB0, 0x66, 0xE7, 0x72, 0x6A, 0xB9, 0x82, 0xC5, 0x34, 0x2A, 0x66, 0x0A, 0x28, + 0xB9, 0x4F, 0x7E, 0xB9, 0x87, 0xDA, 0x54, 0x64, 0xE1, 0x48, 0xFA, 0xA7, 0xB6, 0x21, 0xBE, 0xF3, 0xBB, 0xC5, 0xC7, 0x6E, + 0x12, 0xC1, 0xEE, 0x7C, 0x68, 0xD5, 0xF3, 0x78, 0x28, 0xCC, 0x7A, 0xF2, 0x6F, 0x4B, 0xA4, 0x7A, 0xBA, 0xEE, 0x79, 0xF9, + 0x66, 0xA1, 0x3A, 0x6A, 0x3B, 0x51, 0x73, 0x83, 0x3F, 0xC7, 0xCE, 0x44, 0xBA, 0x64, 0x5D, 0x71, 0x60, 0x4B, 0x73, 0xD8, + 0x1D, 0xED, 0x73, 0x68, 0x6A, 0xD0, 0xFC, 0x8E, 0x57, 0xD2, 0x5D, 0x8B, 0xC9, 0x81, 0xFD, 0xF6, 0x97, 0x15, 0x2C, 0xDF, + 0xE1, 0x5D, 0x14, 0x87, 0x64, 0x31, 0xF4, 0xB4, 0x01, 0x92, 0x0E, 0x6B, 0x88, 0x73, 0xD5, 0x5F, 0x56, 0x51, 0x0D, 0x86, + 0x11, 0x4D, 0xFD, 0x89, 0x49, 0xA3, 0x70, 0xEE, 0xB6, 0xC0, 0xD5, 0xEC, 0xF5, 0xFF, 0xCB, 0x47, 0xF4, 0xDF, 0x8D, 0xB2, + 0xED, 0x12, 0x4A, 0x1D, 0x5A, 0x57, 0x75, 0xD3, 0x1E, 0x5D, 0xE3, 0xB3, 0x18, 0x7C, 0x3A, 0xC6, 0xCB, 0x1B, 0xCE, 0xC6, + 0x91, 0x58, 0xAB, 0x82, 0x95, 0x31, 0xBC, 0xFA, 0xB4, 0x80, 0xF7, 0x32, 0x8F, 0xE8, 0x5A, 0x3E, 0x96, 0x59, 0xF5, 0x82, + 0xD8, 0x4A, 0x82, 0x66, 0x77, 0xA9, 0x17, 0xF6, 0x49, 0x72, 0x9F, 0xC4, 0x60, 0xB7, 0x6D, 0x0E, 0x77, 0x8B, 0x33, 0x97, + 0x19, 0xD0, 0x35, 0xF5, 0x48, 0x53, 0x09, 0x2A, 0xD0, 0x3D, 0xCD, 0x1B, 0x5E, 0xA6, 0xE6, 0xAB, 0x2E, 0xCA, 0xD4, 0x8C, + 0x80, 0xF8, 0xBE, 0x7F, 0x00, 0x5D, 0x2E, 0x56, 0x6E, 0x72, 0xC4, 0x9B, 0x93, 0x1C, 0xC7, 0xB1, 0xC8, 0xB6, 0x2E, 0x86, + 0xB5, 0x34, 0x1E, 0xC7, 0x09, 0x79, 0x61, 0xCF, 0x41, 0xD2, 0x59, 0xA1, 0xA8, 0xBE, 0xBF, 0x7E, 0x8C, 0x8E, 0x62, 0x96, + 0xFF, 0x81, 0xAF, 0x53, 0x54, 0x77, 0x1C, 0xEA, 0xD9, 0x77, 0x76, 0xBA, 0x18, 0xB4, 0x60, 0xC7, 0xC7, 0xC4, 0xE7, 0xA9, + 0x19, 0xFA, 0x7C, 0x78, 0xAF, 0xB3, 0xD0, 0xA5, 0xD1, 0x78, 0xA9, 0x86, 0x1C, 0x83, 0x79, 0xF2, 0xAC, 0x88, 0xB5, 0xD0, + 0x8E, 0xE2, 0x6A, 0xA3, 0x98, 0x06, 0x0D, 0x02, 0x6F, 0xDD, 0xBD, 0xF8, 0xAE, 0x20, 0xE3, 0xAB, 0x8E, 0x53, 0xFD, 0x7D, + 0x62, 0x91, 0x6A, 0x50, 0x11, 0x43, 0x30, 0x1E, 0x20, 0xD5, 0x11, 0x3B, 0xAF, 0xB2, 0xCB, 0x35, 0xED, 0x72, 0xC2, 0x09, + 0x75, 0xFE, 0x74, 0xA2, 0x46, 0x83, 0x00, 0x88, 0x05, 0x40, 0xF8, 0x23, 0x12, 0x52, 0x43, 0x50, 0xAF, 0xD1, 0x8D, 0xA2, + 0x0A, 0xEB, 0x3D, 0x3F, 0x03, 0xF9, 0x13, 0xE4, 0x36, 0xE1, 0x46, 0x1F, 0xAE, 0x50, 0x86, 0x1A, 0xF6, 0xE5, 0x07, 0x2B, + 0xB0, 0x26, 0x0D, 0xF5, 0xB7, 0xE2, 0x4F, 0x0A, 0x2F, 0x93, 0x8F, 0x0E, 0x77, 0x87, 0x62, 0x60, 0xB5, 0x8C, 0x9D, 0xB8, + 0xFE, 0xB2, 0x07, 0x0B, 0x48, 0x65, 0x3A, 0xB3, 0x84, 0x8E, 0x5A, 0xF2, 0x83, 0x2B, 0x50, 0xD2, 0xF7, 0xC7, 0xC4, 0x00, + 0xBD, 0xA1, 0x88, 0x19, 0xD9, 0x62, 0xDC, 0x30, 0xFC, 0xC7, 0x50, 0x11, 0x19, 0xA3, 0x87, 0x56, 0xC8, 0x88, 0xFC, 0xEC, + 0xA4, 0xA0, 0xC5, 0x67, 0x27, 0x19, 0x9A, 0x77, 0xFA, 0xB9, 0x49, 0x9D, 0x6A, 0xCB, 0xF5, 0x27, 0x82, 0x6D, 0x26, 0x8B, + 0x08, 0x7A, 0xCE, 0x97, 0x34, 0xBC, 0x1F, 0xB7, 0x2E, 0xED, 0x3B, 0x05, 0xF9, 0x7E, 0x96, 0x79, 0x34, 0x87, 0x26, 0x8A, + 0x42, 0x81, 0x7F, 0xEA, 0x05, 0x8A, 0x85, 0x16, 0xAC, 0x99, 0x8F, 0x69, 0x39, 0xC6, 0xD2, 0x6D, 0x2D, 0xA2, 0x22, 0xC5, + 0xB8, 0x4A, 0x7A, 0x66, 0xF0, 0xD9, 0xA6, 0x6A, 0x4A, 0x91, 0xF9, 0xF0, 0x3F, 0xCF, 0xBE, 0xB9, 0x31, 0x4B, 0x04, 0x03, + 0x28, 0xDB, 0x2A, 0x68, 0xB1, 0xC4, 0xD1, 0xEF, 0x39, 0x9A, 0xDE, 0xC5, 0x38, 0xC7, 0x86, 0x4F, 0x81, 0xE2, 0x00, 0x4A, + 0xFB, 0x0A, 0x47, 0x38, 0xE9, 0xC2, 0x68, 0x68, 0xA5, 0xC3, 0xAA, 0x7E, 0x46, 0xE8, 0x5A, 0xBC, 0x1D, 0xC0, 0xD2, 0x0E, + 0x1E, 0xA2, 0x1C, 0x98, 0x6B, 0x8F, 0xC8, 0x5A, 0xD0, 0xEF, 0xE3, 0x6F, 0x2B, 0x0F, 0x81, 0x4E, 0x9F, 0xCF, 0x32, 0x0D, + 0xAF, 0xCA, 0xF7, 0x66, 0x8A, 0xEA, 0x39, 0x5B, 0x28, 0xCE, 0xD0, 0x3F, 0xDF, 0xA2, 0x79, 0x16, 0x4D, 0x38, 0x4C, 0x7E, + 0x52, 0xE3, 0x42, 0x4B, 0x27, 0x23, 0xFC, 0x82, 0x81, 0x3F, 0x0B, 0x93, 0x5C, 0x7F, 0xE8, 0x55, 0xF0, 0x7D, 0x34, 0xAF, + 0xCE, 0xD5, 0x28, 0x12, 0x6B, 0x98, 0x42, 0x9A, 0x98, 0x70, 0x2C, 0x47, 0xD6, 0xB1, 0xE5, 0xCE, 0x66, 0x19, 0xFD, 0xD2, + 0xDF, 0xA3, 0x20, 0xD9, 0x8E, 0xC3, 0xE7, 0xE0, 0x1F, 0x96, 0x77, 0x1C, 0xD3, 0x3C, 0x16, 0x75, 0x19, 0x4E, 0xA8, 0x40, + 0xD9, 0x0E, 0x83, 0x9B, 0x15, 0x72, 0x36, 0xF0, 0x02, 0xD9, 0x19, 0xB5, 0x0F, 0xC5, 0x3E, 0x11, 0xE2, 0x59, 0x57, 0xD0, + 0xAA, 0x11, 0xD4, 0x62, 0xDC, 0x0A, 0x57, 0x91, 0xA9, 0xE8, 0xEC, 0x76, 0x6F, 0xF9, 0x7C, 0xB0, 0xE5, 0x51, 0x77, 0xC3, + 0x5D, 0x84, 0x18, 0xB5, 0x98, 0xE9, 0x27, 0xA5, 0x0D, 0xB2, 0x8B, 0xD4, 0x9D, 0x73, 0x50, 0xF7, 0x4C, 0xF3, 0xF7, 0xD5, + 0x04, 0x3C, 0x1D, 0xB1, 0xFF, 0xDA, 0xF1, 0xED, 0x3F, 0xBF, 0x82, 0xE8, 0xDB, 0xFD, 0xDE, 0x9D, 0x4C, 0xFC, 0x60, 0x86, + 0x87, 0x89, 0x08, 0x5D, 0xF8, 0x55, 0xAE, 0xE9, 0x5D, 0x1C, 0x69, 0xEB, 0xD4, 0x88, 0xFE, 0xF7, 0x78, 0x74, 0x1A, 0xDC, + 0x8A, 0x9C, 0x1F, 0x74, 0xC7, 0x95, 0x81, 0xA2, 0x30, 0xF8, 0x31, 0x93, 0x6C, 0x5D, 0xCF, 0x1F, 0x10, 0x55, 0x3D, 0xFB, + 0x46, 0xDF, 0xD7, 0xB8, 0x54, 0xEA, 0x72, 0x54, 0xDA, 0xDB, 0x87, 0x40, 0x14, 0xCA, 0x5E, 0x30, 0x82, 0x91, 0xC6, 0x44, + 0x3D, 0x14, 0x09, 0xCE, 0x68, 0xFC, 0xD1, 0x1F, 0xE2, 0x9C, 0xFE, 0x24, 0xD2, 0x3C, 0x42, 0xA0, 0xE1, 0x3C, 0x00, 0x42, + 0x9A, 0x7E, 0x81, 0x03, 0x7F, 0xF3, 0x18, 0xB5, 0xC6, 0x93, 0xBE, 0xC0, 0x5B, 0x41, 0x9B, 0x94, 0x86, 0x4D, 0x1F, 0x65, + 0xDC, 0x28, 0x57, 0x24, 0x5A, 0xFC, 0x79, 0x35, 0x1A, 0x00, 0xAA, 0x08, 0xD1, 0x9E, 0x97, 0x79, 0x03, 0xBE, 0xA3, 0xA8, + 0xDC, 0x33, 0x78, 0x0C, 0xE9, 0x6F, 0x28, 0xCE, 0xC3, 0x4D, 0x69, 0x5F, 0xCA, 0x5F, 0xB9, 0xD0, 0x17, 0x07, 0xA8, 0x09, + 0x9C, 0x3A, 0x30, 0x21, 0x47, 0x92, 0x0D, 0x0B, 0x21, 0xEC, 0x58, 0x83, 0x86, 0xD1, 0xD8, 0xAF, 0x6D, 0x6D, 0x6C, 0xE3, + 0x61, 0x44, 0xAA, 0xAF, 0x63, 0xB7, 0xA1, 0x05, 0x20, 0xFC, 0xA5, 0x73, 0x4B, 0x31, 0x36, 0xB3, 0x40, 0x43, 0xE2, 0xCE, + 0x5E, 0x21, 0xE4, 0x64, 0x31, 0x50, 0x92, 0x47, 0x14, 0x6C, 0xF0, 0x12, 0x28, 0x20, 0xE8, 0xE6, 0x70, 0x94, 0x11, 0x70, + 0xA6, 0xDA, 0x68, 0x26, 0x71, 0x01, 0xA7, 0x0A, 0x45, 0xB7, 0xE0, 0xA4, 0x0F, 0x9A, 0xFB, 0xD2, 0xEF, 0xF9, 0xD3, 0x75, + 0x33, 0x89, 0x91, 0xFC, 0xD5, 0xB7, 0xA9, 0xE7, 0x52, 0xDF, 0xE5, 0x2E, 0x55, 0x46, 0x09, 0x11, 0x91, 0x65, 0xE5, 0x6F, + 0xA1, 0xB3, 0x75, 0xE7, 0xDF, 0x6F, 0x1A, 0x8D, 0xE1, 0x3B, 0x3A, 0x96, 0x1B, 0x88, 0x2A, 0x19, 0x72, 0x47, 0x90, 0x34, + 0x59, 0xC8, 0x2A, 0x09, 0xDC, 0x65, 0x72, 0x01, 0x99, 0xEF, 0x4C, 0x90, 0xEA, 0x08, 0x0A, 0xB8, 0x17, 0xAC, 0x2A, 0x76, + 0x19, 0x1A, 0xB8, 0xEB, 0x88, 0x97, 0x73, 0x96, 0x37, 0x47, 0x83, 0x08, 0xDC, 0x04, 0xCF, 0x47, 0x87, 0x15, 0xEB, 0x1F, + 0xCC, 0x26, 0x21, 0xD1, 0x27, 0x04, 0xA2, 0x7F, 0x78, 0x70, 0x3C, 0x4F, 0xAB, 0x93, 0xC9, 0x08, 0xF3, 0x44, 0x04, 0x1B, + 0x6C, 0xCD, 0x52, 0x91, 0x56, 0x91, 0x14, 0xBA, 0x57, 0x89, 0xB1, 0x7B, 0xBA, 0x41, 0x0C, 0xD9, 0xA0, 0x29, 0x1F, 0x9E, + 0xD9, 0xB9, 0xF7, 0x2B, 0x71, 0x4F, 0x03, 0x0C, 0x11, 0x23, 0x51, 0x9A, 0x4E, 0xC3, 0xC1, 0x69, 0x58, 0x6D, 0xB1, 0x2A, + 0xFF, 0xA4, 0x2C, 0x27, 0x4D, 0x25, 0xE2, 0x9B, 0x67, 0x32, 0x04, 0x1F, 0x9B, 0x60, 0xB3, 0x89, 0xD3, 0xAF, 0x2C, 0x90, + 0x91, 0xCF, 0xB0, 0xDF, 0x66, 0x28, 0x90, 0x64, 0x34, 0x6B, 0x64, 0xF2, 0x9E, 0x1F, 0xA5, 0xEB, 0xA0, 0x21, 0x24, 0x4B, + 0xEE, 0xF7, 0x1C, 0x73, 0x55, 0x1D, 0xFE, 0x05, 0xA4, 0x2C, 0xDF, 0x4D, 0xC7, 0x72, 0x89, 0xC3, 0x13, 0x37, 0x59, 0xC3, + 0x12, 0x52, 0x35, 0x7F, 0x22, 0x1E, 0xAD, 0x84, 0x3C, 0x50, 0x08, 0xCB, 0x2B, 0x42, 0x0D, 0xC6, 0x89, 0xD2, 0x6C, 0x33, + 0xAE, 0x55, 0x04, 0x80, 0x30, 0x76, 0x94, 0xE1, 0xEB, 0x08, 0xAC, 0xF6, 0x8D, 0xA9, 0x4D, 0xB6, 0xFE, 0x1A, 0x15, 0xCA, + 0x08, 0x45, 0xF1, 0xCF, 0x4D, 0x8E, 0xCA, 0x96, 0x07, 0x8A, 0x1C, 0xD8, 0x07, 0xE9, 0xCE, 0x81, 0x8D, 0x16, 0xEE, 0xAF, + 0x7F, 0xAB, 0x9F, 0xE4, 0x05, 0x8B, 0xF9, 0xAE, 0x00, 0x56, 0x0D, 0x91, 0x91, 0x75, 0x5D, 0xCB, 0x9F, 0xE2, 0x84, 0x6C, + 0x56, 0xD6, 0x7B, 0x4A, 0x89, 0x1E, 0x2D, 0x29, 0xED, 0x26, 0x1E, 0x3D, 0x5B, 0x33, 0x01, 0x9D, 0xD9, 0xF9, 0x21, 0x1A, + 0xA8, 0xB9, 0x1B, 0x74, 0xA0, 0x7B, 0x20, 0x91, 0xCE, 0x42, 0xCC, 0xA7, 0x92, 0x1D, 0x2F, 0x88, 0xAE, 0xC9, 0xFA, 0x7E, + 0xC8, 0xEE, 0x29, 0x81, 0x4F, 0x4A, 0xAA, 0x5E, 0x7C, 0xF7, 0xCF, 0x24, 0xF1, 0x17, 0x49, 0x1C, 0xBF, 0xD9, 0xE9, 0xDF, + 0xF9, 0x14, 0x0F, 0x55, 0x69, 0xB6, 0x26, 0x68, 0x3A, 0x97, 0x46, 0x3C, 0xC1, 0x52, 0x06, 0x6C, 0x62, 0x70, 0xEE, 0x12, + 0x87, 0xA8, 0xCD, 0x3A, 0x0F, 0xC9, 0xB6, 0x9C, 0x23, 0x7F, 0x9E, 0x65, 0xC6, 0x1F, 0xC8, 0x9E, 0x13, 0x70, 0x43, 0x2B, + 0x28, 0x1D, 0x78, 0x56, 0x4F, 0x98, 0xEA, 0xD4, 0x15, 0x03, 0xAF, 0xFF, 0x13, 0x71, 0xD8, 0xC6, 0x89, 0x8B, 0x47, 0x7D, + 0x4E, 0xCB, 0x98, 0x5A, 0x1E, 0x50, 0xCD, 0xC6, 0x10, 0x3B, 0x5D, 0xF1, 0x3E, 0x54, 0x64, 0x83, 0x57, 0x53, 0x4E, 0x0A, + 0xAF, 0xF1, 0xDF, 0xA2, 0x1A, 0xC2, 0xE8, 0xAF, 0x5D, 0x8D, 0x74, 0x70, 0xEA, 0xB1, 0xC0, 0xDA, 0xF7, 0x8E, 0x07, 0xB2, + 0x1B, 0x2B, 0x70, 0x81, 0x05, 0xA2, 0xB1, 0x65, 0xCC, 0xB9, 0x68, 0xC6, 0x63, 0xD2, 0xD9, 0x45, 0x67, 0x8E, 0x11, 0x78, + 0x04, 0x8E, 0x11, 0xFF, 0x14, 0x5F, 0x60, 0x71, 0x62, 0xD3, 0xF1, 0x2B, 0xE6, 0x5D, 0x18, 0x5F, 0xC6, 0xC5, 0x61, 0x35, + 0x1B, 0xE6, 0x08, 0xE6, 0x18, 0xE3, 0xC8, 0x98, 0xA9, 0xFF, 0xDC, 0x30, 0xF8, 0x28, 0x5C, 0x29, 0xB4, 0x08, 0xB8, 0xEF, + 0xED, 0xA0, 0xE0, 0x52, 0x64, 0x57, 0x1F, 0x44, 0x27, 0x59, 0xED, 0x84, 0x63, 0xA9, 0x49, 0x9C, 0x6A, 0xCB, 0xD7, 0x11, + 0x2D, 0x69, 0x63, 0x62, 0x26, 0xC6, 0xE3, 0x66, 0x36, 0x26, 0xCD, 0x2C, 0x64, 0xA2, 0x41, 0x8D, 0x3E, 0xBD, 0x9B, 0x48, + 0xAD, 0xF5, 0x5A, 0x06, 0xE1, 0xE7, 0xCA, 0xD5, 0x7F, 0xEF, 0x72, 0xBB, 0x6C, 0xAA, 0x9D, 0xB3, 0x90, 0x74, 0xF4, 0x26, + 0x0E, 0x04, 0xD9, 0xFA, 0x64, 0x6D, 0x7C, 0xEA, 0x5C, 0x19, 0x0B, 0x69, 0x78, 0x99, 0x33, 0xFE, 0xA0, 0xEA, 0x8B, 0xD5, + 0x31, 0xA6, 0x75, 0x57, 0x51, 0xA8, 0x86, 0x9F, 0xFB, 0x47, 0x24, 0xFF, 0x8B, 0xAD, 0xBC, 0x3D, 0x05, 0x1B, 0x85, 0xFA, + 0x52, 0x6D, 0x3C, 0xA8, 0x0A, 0x21, 0xE2, 0xBD, 0x9A, 0x21, 0xCD, 0x88, 0xC3, 0x47, 0xD1, 0x8C, 0x9E, 0x13, 0x4C, 0xB8, + 0x83, 0xCC, 0xF8, 0x6E, 0x3F, 0x02, 0x40, 0xE8, 0x4F, 0x12, 0xD8, 0x0D, 0xFC, 0xE4, 0xEF, 0x79, 0x65, 0xCA, 0xB1, 0x49, + 0x98, 0xE6, 0xF7, 0xF8, 0xE0, 0x31, 0xCD, 0xA3, 0x0E, 0xE1, 0x15, 0x5D, 0x6E, 0x0C, 0x4B, 0x2D, 0xFD, 0xEB, 0x48, 0xCB, + 0x37, 0x6C, 0xFF, 0x62, 0x26, 0x1B, 0x1C, 0xE9, 0xA5, 0x9D, 0x16, 0xC1, 0x32, 0x30, 0x17, 0x8A, 0xBC, 0xE1, 0xA6, 0x02, + 0x9F, 0xB4, 0x04, 0xF0, 0xD1, 0x82, 0x84, 0x07, 0x94, 0xAE, 0x6C, 0x5A, 0x4A, 0x9C, 0x18, 0x92, 0x16, 0xF5, 0x9C, 0xC1, + 0x05, 0xEF, 0xA6, 0x47, 0x92, 0xB4, 0x74, 0xDC, 0x43, 0xD6, 0x8F, 0x17, 0x20, 0x5D, 0x9A, 0x3A, 0x38, 0x6E, 0x19, 0xB0, + 0x19, 0xAE, 0xC4, 0xBB, 0x40, 0xAC, 0xAB, 0x8F, 0x1E, 0xB7, 0x30, 0xD9, 0x00, 0xE0, 0x9C, 0x42, 0x32, 0x21, 0xC0, 0x9D, + 0xC5, 0x01, 0xCE, 0x56, 0xAE, 0xB6, 0xAC, 0x4F, 0x9F, 0xD7, 0x40, 0x44, 0x6B, 0xBF, 0x46, 0x01, 0x6A, 0x71, 0x07, 0xD1, + 0xD6, 0x0A, 0xB1, 0x47, 0xF8, 0xB1, 0xE3, 0x82, 0x5F, 0xDE, 0x27, 0xDC, 0x8C, 0x97, 0x7D, 0x67, 0x5A, 0xFB, 0xAA, 0x70, + 0x06, 0x48, 0x6D, 0x96, 0x0A, 0xF6, 0xF1, 0xA3, 0xC5, 0x67, 0x9D, 0x53, 0xB6, 0xB5, 0x8B, 0x0E, 0x5A, 0x54, 0x8E, 0xEC, + 0x0F, 0x84, 0x9A, 0x31, 0xD9, 0x4E, 0x8C, 0x1E, 0xA8, 0x57, 0xD5, 0x1E, 0x29, 0xA7, 0x96, 0x74, 0xB0, 0x44, 0x87, 0x5C, + 0x7D, 0xA4, 0xA8, 0x1E, 0x96, 0xBD, 0x90, 0x83, 0x5F, 0x25, 0x67, 0x1A, 0xB6, 0xB4, 0x7F, 0x3B, 0xDF, 0xD6, 0x13, 0x8B, + 0x9F, 0x33, 0x47, 0xF9, 0x12, 0x95, 0x4A, 0x70, 0x48, 0xED, 0xC7, 0x53, 0xC2, 0x46, 0x85, 0x0F, 0x53, 0x54, 0xD2, 0xA8, + 0x12, 0x63, 0x26, 0x8A, 0x3D, 0xFE, 0xF4, 0x1A, 0x6F, 0x7D, 0xF4, 0x83, 0x7A, 0x26, 0xCE, 0xC0, 0xA3, 0x30, 0xBE, 0xD7, + 0x9C, 0xA6, 0x74, 0xCB, 0xCE, 0x5C, 0xC0, 0xD7, 0xF2, 0x5B, 0xDC, 0x67, 0x59, 0x2A, 0xEB, 0x14, 0x1F, 0xB8, 0x7D, 0x18, + 0xAF, 0x73, 0x16, 0x9D, 0x15, 0xCF, 0xCF, 0xEB, 0xEF, 0x30, 0x4D, 0x5B, 0xB6, 0x41, 0x57, 0x08, 0x6B, 0x52, 0xB7, 0x3F, + 0xCC, 0x74, 0xE5, 0x31, 0x38, 0x42, 0x40, 0xDC, 0x3B, 0xFB, 0xCE, 0xC8, 0x4F, 0x0D, 0x81, 0x57, 0x60, 0x0C, 0x52, 0x3F, + 0x69, 0x30, 0xD9, 0x7B, 0x22, 0x4F, 0x41, 0xD8, 0xD5, 0x0C, 0xC2, 0xCE, 0x39, 0x70, 0xD2, 0x5D, 0xA1, 0x7B, 0x37, 0xF8, + 0xB1, 0x60, 0x49, 0xC5, 0xC6, 0x3A, 0xF7, 0xEC, 0xD3, 0x1B, 0xC9, 0xAD, 0x87, 0x0E, 0x31, 0x52, 0x53, 0x21, 0x8E, 0xB9, + 0x64, 0x90, 0xE7, 0x33, 0x30, 0xE0, 0xF4, 0x3B, 0xA1, 0x1F, 0x99, 0xCC, 0xFB, 0xB5, 0xAF, 0x0E, 0x20, 0x9B, 0x10, 0x65, + 0x43, 0xC9, 0x88, 0x48, 0xE1, 0x1E, 0xB0, 0xBC, 0x09, 0x88, 0xB4, 0x0B, 0x81, 0x99, 0xE6, 0x5C, 0x7D, 0xBA, 0x0D, 0xC3, + 0x0F, 0xBF, 0x39, 0xC7, 0xB0, 0x16, 0x7E, 0x1E, 0x1B, 0xD9, 0xC4, 0x54, 0x73, 0x99, 0x42, 0xD3, 0x0E, 0xED, 0xDE, 0xB3, + 0x11, 0x24, 0x62, 0xE3, 0xC3, 0x4F, 0x83, 0xAD, 0xAF, 0xC8, 0x78, 0xE8, 0x29, 0xA7, 0xCA, 0x95, 0xBD, 0xA8, 0x42, 0x5F, + 0x14, 0x53, 0x31, 0xDF, 0xD4, 0x65, 0x6C, 0xD8, 0x0A, 0xE3, 0xD3, 0x47, 0x1F, 0xCB, 0xE2, 0x5E, 0xC6, 0xCF, 0xC4, 0xDE, + 0x5D, 0xEC, 0x92, 0x7A, 0xBC, 0x66, 0x7B, 0x8F, 0x19, 0x18, 0xE0, 0x4F, 0xA0, 0x63, 0xCB, 0x19, 0x31, 0x30, 0x35, 0x30, + 0xE0, 0x5A, 0xCC, 0x62, 0xA5, 0xD4, 0x1D, 0x79, 0xD2, 0x07, 0x66, 0x13, 0x7A, 0x29, 0x82, 0x50, 0xE8, 0x0A, 0x45, 0xAE, + 0x29, 0x9C, 0x17, 0x13, 0x2A, 0x0F, 0x72, 0x9C, 0x86, 0xBF, 0x00, 0x45, 0xB4, 0x4F, 0x35, 0xD8, 0x04, 0x39, 0xA1, 0xFA, + 0xC3, 0xCF, 0x6E, 0x1E, 0x68, 0x53, 0x63, 0x6B, 0x2B, 0x82, 0x7B, 0xB3, 0x8A, 0x63, 0xAC, 0x13, 0xA8, 0xB1, 0xAD, 0x6A, + 0x7B, 0x91, 0x48, 0xE7, 0x8D, 0x2F, 0xAB, 0x5F, 0xE0, 0x22, 0x63, 0x82, 0xB8, 0x4F, 0x74, 0x9B, 0xCB, 0x92, 0xC4, 0xF4, + 0xB2, 0xE5, 0x20, 0x84, 0x30, 0x30, 0xAC, 0x4F, 0x1C, 0x0D, 0xF2, 0x68, 0x73, 0x01, 0x56, 0xBF, 0x49, 0x40, 0x74, 0x16, + 0xB0, 0x93, 0x45, 0x0F, 0xC4, 0xF0, 0xE2, 0xB2, 0x12, 0x24, 0x94, 0x05, 0xBB, 0x47, 0x85, 0xF7, 0x83, 0x5C, 0xC6, 0x01, + 0x0D, 0xA2, 0xCF, 0x87, 0x98, 0x23, 0xCD, 0x2D, 0xA7, 0x1E, 0xD4, 0x4E, 0xB7, 0xD1, 0x01, 0x57, 0x44, 0x3D, 0xCB, 0x9C, + 0x1A, 0x17, 0xEF, 0x45, 0xB1, 0x2B, 0xB4, 0x40, 0x69, 0x13, 0x6C, 0x1F, 0x15, 0x54, 0x2C, 0xEC, 0xD5, 0x38, 0x4F, 0x83, + 0xFE, 0x68, 0x17, 0x97, 0x4C, 0x36, 0xE1, 0xAB, 0x65, 0x86, 0xD8, 0xF5, 0x7B, 0x55, 0x25, 0x87, 0xDA, 0x54, 0x8D, 0xC1, + 0x37, 0xE7, 0x7E, 0x8F, 0x33, 0xEA, 0xC4, 0xC1, 0xFA, 0x76, 0xE2, 0xBE, 0xA5, 0x87, 0x78, 0x1C, 0x52, 0x88, 0x60, 0x09, + 0xE3, 0x15, 0x22, 0xF4, 0xF3, 0x77, 0xF9, 0x7A, 0x09, 0x6A, 0xC1, 0x4B, 0x3E, 0xB8, 0x74, 0x34, 0x69, 0xD9, 0xAE, 0x4C, + 0x72, 0x3A, 0x27, 0xE7, 0xB8, 0x09, 0x48, 0xE4, 0xC6, 0x22, 0x93, 0x50, 0x1A, 0x59, 0x09, 0x4F, 0xFD, 0xF2, 0x5D, 0x88, + 0xDF, 0x1A, 0x84, 0xCD, 0xA0, 0x78, 0xBF, 0x0C, 0xCC, 0x18, 0xD8, 0x5B, 0x9B, 0x73, 0x2F, 0x88, 0x24, 0x78, 0xE0, 0x19, + 0xF9, 0xD0, 0x40, 0xBD, 0xEF, 0x1B, 0xAB, 0x01, 0x12, 0x1F, 0xB5, 0x20, 0x7B, 0x5E, 0x46, 0x10, 0x91, 0x27, 0x52, 0x2F, + 0x97, 0xFD, 0xD6, 0xED, 0x72, 0x83, 0xCE, 0x86, 0xA6, 0x7F, 0xCF, 0xBA, 0xD0, 0x0C, 0x08, 0x55, 0x80, 0x2E, 0x21, 0x03, + 0x7B, 0x7D, 0xC2, 0x49, 0x57, 0x05, 0xF9, 0xAB, 0x51, 0x2F, 0x04, 0x1A, 0x98, 0x83, 0xD3, 0x12, 0xF2, 0x1E, 0xE4, 0x5C, + 0x38, 0x20, 0xD9, 0xBF, 0x44, 0x92, 0xA4, 0xC6, 0x99, 0x1E, 0x20, 0xFD, 0x04, 0x80, 0x38, 0x5B, 0x67, 0xF6, 0x1B, 0xAA, + 0xE3, 0x1D, 0xE4, 0x06, 0x37, 0xC0, 0xFF, 0xD0, 0xA9, 0x61, 0xA3, 0x72, 0x44, 0x34, 0xD3, 0x94, 0x94, 0x93, 0x29, 0xF5, + 0x76, 0x55, 0x8C, 0xC8, 0xB4, 0x5E, 0x37, 0x2F, 0x82, 0x51, 0xF4, 0xFC, 0x65, 0xB1, 0x6E, 0x33, 0xC2, 0x82, 0xA9, 0xD8, + 0x21, 0x61, 0xB8, 0x2C, 0xBD, 0xC1, 0x29, 0x07, 0xA8, 0xA5, 0x81, 0xAC, 0x30, 0x4A, 0x79, 0xE3, 0x97, 0x4E, 0x4C, 0x3D, + 0x35, 0xC4, 0xF0, 0x35, 0x02, 0x5F, 0xB0, 0xDE, 0xFF, 0x86, 0x08, 0x9A, 0x8A, 0x1F, 0xAC, 0x98, 0xBC, 0x83, 0x37, 0x52, + 0x11, 0x5F, 0x27, 0x2C, 0xC5, 0xE1, 0x78, 0x8D, 0xB6, 0x46, 0xCA, 0x04, 0x88, 0x5A, 0x61, 0xC3, 0xC9, 0xDA, 0xA2, 0x85, + 0xB5, 0xC6, 0xBA, 0x14, 0xEE, 0x67, 0xC5, 0x82, 0x81, 0x17, 0x9C, 0xD3, 0x85, 0xA7, 0x3F, 0x11, 0x38, 0x1C, 0xE8, 0x8D, + 0xD1, 0x4D, 0x39, 0x81, 0x83, 0x93, 0x8A, 0x87, 0x1A, 0x4A, 0x12, 0xD9, 0xEF, 0xDA, 0x7B, 0x1F, 0x68, 0x47, 0x92, 0x84, + 0x0C, 0xEA, 0x6A, 0x0E, 0x47, 0xEB, 0x42, 0xFA, 0x15, 0xD2, 0xC4, 0x17, 0xDD, 0x8A, 0x83, 0x6D, 0x52, 0x98, 0x3C, 0xF0, + 0xAF, 0x2A, 0x8B, 0x5B, 0x4C, 0x6C, 0x22, 0x5D, 0xB6, 0xDB, 0x1C, 0x32, 0x71, 0xDA, 0x6D, 0xC1, 0x9B, 0x2B, 0x1E, 0x5D, + 0x7A, 0xDB, 0x81, 0xC4, 0x24, 0x87, 0x4C, 0x25, 0x08, 0x1C, 0x82, 0x4C, 0x3C, 0xEE, 0x72, 0xEE, 0x38, 0xF1, 0x32, 0x11, + 0x0B, 0xE7, 0xEF, 0xDA, 0xF2, 0x96, 0xF9, 0xBC, 0xB3, 0x00, 0x82, 0x96, 0x4B, 0xB6, 0xF2, 0x73, 0xD8, 0xFC, 0x90, 0xA3, + 0x85, 0xCC, 0x6B, 0x1F, 0x32, 0x03, 0x28, 0x6B, 0xC8, 0x1D, 0xF2, 0xEB, 0x90, 0xD1, 0xEB, 0x05, 0x02, 0xED, 0xFC, 0xBD, + 0x99, 0xB5, 0x7B, 0xF9, 0x31, 0x50, 0x6B, 0x0D, 0xEC, 0xD1, 0x8F, 0x27, 0xF1, 0x8E, 0x64, 0xC7, 0x5E, 0xBA, 0x25, 0xE5, + 0x57, 0x44, 0x8E, 0x44, 0xD8, 0xFF, 0x96, 0xCE, 0xC2, 0x81, 0xAE, 0x70, 0x90, 0x17, 0x84, 0x3C, 0x96, 0xBD, 0xE4, 0xB2, + 0x3D, 0xC0, 0x58, 0x7C, 0x97, 0x96, 0xE5, 0x6F, 0x19, 0xFF, 0x8D, 0x2C, 0x1F, 0xC0, 0xB3, 0x8B, 0x1D, 0xA3, 0x97, 0xCE, + 0x42, 0x33, 0x3C, 0xD7, 0xA1, 0x18, 0x02, 0x37, 0xF8, 0xD7, 0xBA, 0xB5, 0x28, 0x53, 0x9B, 0x40, 0xA3, 0x24, 0xF5, 0x63, + 0xC1, 0x49, 0xD3, 0xDA, 0x60, 0xAE, 0x0F, 0x19, 0x7E, 0xF4, 0x14, 0xF6, 0xBA, 0x68, 0x3F, 0x28, 0xCA, 0xAE, 0xC3, 0x10, + 0xAF, 0x44, 0xFC, 0xF6, 0x77, 0x55, 0xDE, 0x21, 0x0A, 0x6B, 0xF7, 0xC0, 0x49, 0x3B, 0x75, 0x61, 0x32, 0xF5, 0x0A, 0x18, + 0xF6, 0xD6, 0xC0, 0x9D, 0x52, 0xCB, 0x6B, 0x89, 0x3A, 0xD5, 0x6A, 0x53, 0xED, 0xD5, 0xFD, 0xF7, 0xF7, 0x17, 0xB7, 0x88, + 0x88, 0x38, 0x39, 0x9A, 0xB9, 0xDB, 0x7E, 0xBE, 0x8D, 0xC3, 0xA7, 0xAC, 0xA8, 0xB9, 0x77, 0x21, 0x88, 0x92, 0x56, 0xBA, + 0xDC, 0x16, 0xAE, 0x4B, 0x59, 0xF9, 0xBF, 0xD8, 0x86, 0xFF, 0x32, 0xEA, 0x1F, 0xDB, 0x37, 0xFD, 0x8F, 0xD7, 0xC4, 0x4D, + 0xFC, 0x95, 0xEE, 0xAC, 0x59, 0x65, 0xF2, 0xE8, 0xA2, 0x90, 0xBA, 0x6C, 0x89, 0x14, 0xE4, 0x8C, 0x92, 0xD2, 0x17, 0xB2, + 0x0C, 0xF4, 0x5C, 0x39, 0x10, 0x33, 0x4D, 0x4B, 0xAD, 0x83, 0x2F, 0xCB, 0xCB, 0x7D, 0xF6, 0xEE, 0x7E, 0x5E, 0x6E, 0xB4, + 0xED, 0xDD, 0x90, 0x66, 0x44, 0xBD, 0xF8, 0xEE, 0x93, 0x4C, 0xFE, 0xFE, 0x7F, 0x6C, 0x34, 0x0C, 0x13, 0x18, 0x3E, 0xD0, + 0x81, 0x24, 0x64, 0x18, 0x96, 0xDD, 0xF7, 0xEF, 0xFE, 0x5D, 0x67, 0x66, 0x4E, 0xEE, 0xB4, 0x3D, 0x5E, 0x40, 0x01, 0xC3, + 0x33, 0x6E, 0xFF, 0xFF, 0xF7, 0xE6, 0xDB, 0x02, 0x7F, 0x44, 0x63, 0x17, 0x72, 0xD6, 0xBC, 0x53, 0x2A, 0xC6, 0x9E, 0x96, + 0x73, 0xA0, 0x28, 0xF2, 0x83, 0xD5, 0x08, 0xE7, 0xF5, 0x8E, 0x22, 0xA3, 0x27, 0xBE, 0xB8, 0x24, 0xE5, 0xB6, 0x61, 0x1F, + 0x01, 0x89, 0xFF, 0x9E, 0xFB, 0xB4, 0x13, 0xE1, 0x9A, 0x2E, 0xCB, 0x7F, 0x67, 0x1D, 0x57, 0x62, 0xEC, 0x0C, 0x3F, 0xE4, + 0x79, 0x33, 0x43, 0x21, 0x0B, 0xE0, 0x2C, 0x8A, 0x0C, 0x1E, 0x29, 0xBC, 0x1A, 0x46, 0xD8, 0x37, 0x05, 0xA5, 0x68, 0x8F, + 0xB7, 0x27, 0x37, 0x1A, 0x33, 0x60, 0xBE, 0xA0, 0x0B, 0x0A, 0xB6, 0x68, 0xFA, 0xF4, 0xF3, 0x98, 0x47, 0x99, 0xB9, 0x50, + 0xD1, 0x61, 0x0A, 0x55, 0x00, 0x0E, 0x3A, 0xB6, 0xEE, 0xAB, 0xA8, 0x1A, 0x17, 0xDB, 0xA8, 0x1F, 0xB3, 0x62, 0x29, 0x15, + 0x8C, 0x0A, 0x65, 0xC6, 0x88, 0x2D, 0xF5, 0xF4, 0x16, 0x25, 0x96, 0x17, 0x90, 0x68, 0x5D, 0x09, 0xF1, 0x64, 0xFC, 0x3E, + 0x9D, 0x3E, 0xE9, 0xAC, 0x0D, 0x11, 0x3D, 0x72, 0xED, 0xB4, 0xAD, 0x1E, 0xDD, 0x6D, 0xDF, 0xEF, 0xC1, 0x84, 0x40, 0x28, + 0x9F, 0x96, 0x0A, 0x4F, 0x28, 0xE0, 0x61, 0x1C, 0x8B, 0x62, 0x2F, 0x7E, 0xFE, 0x8C, 0xBF, 0x5B, 0x16, 0xB5, 0xFB, 0xEF, + 0x5E, 0x9F, 0xBF, 0x7B, 0x7A, 0x80, 0xDD, 0x8F, 0x99, 0x84, 0x4B, 0x4E, 0xFB, 0xC6, 0x1F, 0xDD, 0xD8, 0xB0, 0x08, 0xB6, + 0xA9, 0x0A, 0x93, 0x3F, 0x26, 0xAD, 0x3B, 0x83, 0x76, 0xF3, 0xF8, 0xBC, 0x06, 0x2D, 0xFE, 0xBA, 0x89, 0x45, 0x5B, 0xA2, + 0x70, 0x05, 0x85, 0x87, 0x6F, 0xB1, 0x25, 0x0F, 0x6B, 0x0E, 0xCB, 0x29, 0x6B, 0x01, 0xC1, 0xB2, 0x7B, 0x8D, 0xE8, 0xC5, + 0xEB, 0x2E, 0xED, 0x44, 0xB2, 0x63, 0x82, 0xBB, 0x09, 0x47, 0xCB, 0x4E, 0xE7, 0x67, 0x64, 0x26, 0xEF, 0xC2, 0x20, 0x59, + 0xAC, 0x6B, 0xF9, 0xC7, 0xD1, 0x66, 0xC4, 0xBB, 0x38, 0x5C, 0x2A, 0x09, 0x16, 0x8F, 0x71, 0x20, 0x69, 0x7D, 0x72, 0x96, + 0xC0, 0x92, 0x2B, 0x03, 0x5A, 0x97, 0xA7, 0x23, 0x0F, 0x59, 0x9E, 0xD9, 0xF3, 0x7D, 0x7E, 0x71, 0xCB, 0xA3, 0xAD, 0x47, + 0x64, 0xF4, 0xB9, 0xDE, 0x2A, 0x41, 0xF5, 0xE7, 0xBA, 0x30, 0xAE, 0x62, 0x2D, 0x8E, 0x0D, 0x64, 0x73, 0x73, 0x9C, 0xC2, + 0xD3, 0xD2, 0xD8, 0x31, 0xB1, 0x17, 0x3C, 0x42, 0x2B, 0x70, 0x7F, 0x75, 0x06, 0x9B, 0x2A, 0xE6, 0x83, 0xD7, 0xF4, 0x60, + 0x39, 0x36, 0xDC, 0x9B, 0xDE, 0x29, 0xE0, 0xF0, 0xDA, 0x44, 0x4E, 0xFF, 0x88, 0x11, 0xDE, 0x99, 0x04, 0x90, 0x7D, 0x11, + 0x5F, 0x19, 0x54, 0xD4, 0xC6, 0x32, 0x79, 0x65, 0x94, 0x8F, 0xB5, 0xE6, 0x82, 0x36, 0x70, 0x29, 0xA3, 0x96, 0xDB, 0xB7, + 0x4C, 0x9A, 0x67, 0x41, 0x6A, 0xF8, 0x02, 0x95, 0x80, 0x73, 0x7E, 0x91, 0x4B, 0x78, 0xBC, 0x7F, 0xEE, 0x97, 0xE9, 0x57, + 0x81, 0xBB, 0x96, 0xAC, 0x78, 0x78, 0xF5, 0x9A, 0xC7, 0x02, 0xF0, 0x06, 0xD2, 0xFC, 0xF2, 0x38, 0x95, 0x79, 0xE6, 0x38, + 0x22, 0x19, 0x90, 0x76, 0x49, 0xC9, 0x60, 0x7C, 0x62, 0x2A, 0x45, 0x56, 0x1F, 0x1B, 0xAD, 0x2F, 0x2D, 0x14, 0xAE, 0xEF, + 0x2B, 0xCF, 0xF1, 0xAA, 0xD2, 0x9E, 0xB3, 0xFB, 0x6A, 0x8F, 0xC1, 0xC5, 0xB9, 0x3A, 0x58, 0x37, 0xDB, 0x9F, 0x57, 0x69, + 0xCD, 0xC1, 0xF2, 0x92, 0xC9, 0x39, 0x89, 0xB9, 0x45, 0x11, 0x30, 0xDF, 0x8A, 0x71, 0x9C, 0x53, 0xC8, 0x7C, 0x66, 0xC8, + 0x12, 0xF2, 0xDE, 0x04, 0xDA, 0xF0, 0xB3, 0x37, 0x76, 0x5A, 0xD5, 0xAD, 0x41, 0xE3, 0x68, 0x0B, 0x1F, 0xFF, 0x17, 0x24, + 0x41, 0xC5, 0x8B, 0x22, 0x07, 0x12, 0xE9, 0xC0, 0x3F, 0x9B, 0xFF, 0x8B, 0x89, 0x73, 0x20, 0x79, 0xE0, 0x25, 0x08, 0x3B, + 0xEF, 0xC4, 0x83, 0xF7, 0x88, 0xC0, 0xCB, 0xDD, 0xC4, 0xA3, 0xD6, 0xDB, 0x75, 0xA2, 0x8C, 0x68, 0xA6, 0x75, 0xD7, 0x5C, + 0xA8, 0xBD, 0xE9, 0x41, 0x2F, 0x67, 0x78, 0x26, 0x3A, 0xFA, 0x1B, 0xB3, 0x50, 0x2D, 0x49, 0x8D, 0xB6, 0x74, 0xDD, 0x50, + 0xA2, 0x64, 0xBC, 0x45, 0xE7, 0xDE, 0x89, 0x0D, 0x09, 0xE6, 0x1B, 0xA5, 0x85, 0x66, 0x6C, 0x73, 0xF5, 0x6E, 0x94, 0x51, + 0x26, 0xF3, 0xAA, 0xA0, 0x84, 0xCC, 0x55, 0x7F, 0xA2, 0x35, 0x8F, 0x1D, 0xCB, 0x62, 0x2F, 0x33, 0x2D, 0xA9, 0x10, 0x75, + 0xA6, 0x0F, 0x28, 0xEB, 0xA1, 0x08, 0xCD, 0x4F, 0x41, 0x16, 0x82, 0x66, 0xD5, 0xC1, 0x41, 0x21, 0xC5, 0x7D, 0xD6, 0x6A, + 0x66, 0xF7, 0x39, 0xA3, 0x9F, 0x4D, 0x31, 0xAA, 0x66, 0x1B, 0x92, 0xB1, 0x05, 0x8F, 0x7E, 0xD3, 0xD9, 0x51, 0xB9, 0x11, + 0x30, 0x48, 0xEC, 0x95, 0x55, 0xE3, 0x96, 0x68, 0x64, 0x85, 0xD4, 0x24, 0x2E, 0x6D, 0xE0, 0xB9, 0x7A, 0x37, 0x0A, 0xD5, + 0x4C, 0xA5, 0x54, 0x1C, 0xEC, 0x0A, 0x75, 0x1E, 0x9E, 0xA7, 0xC1, 0xBE, 0x08, 0x90, 0xE3, 0xE5, 0x5B, 0x69, 0x58, 0xFB, + 0xEF, 0x3B, 0x90, 0x07, 0x78, 0x1F, 0x0D, 0x9A, 0x06, 0xF9, 0x48, 0x27, 0x79, 0x15, 0x88, 0xE8, 0x01, 0x86, 0x4B, 0x20, + 0xB9, 0xC5, 0x05, 0x97, 0xB1, 0x34, 0x65, 0xC2, 0xFC, 0x30, 0xA6, 0x28, 0x4D, 0x7B, 0xF4, 0x77, 0xF5, 0x1D, 0x6A, 0xD7, + 0x2D, 0x45, 0xAC, 0x0C, 0x9F, 0x8E, 0x12, 0x38, 0x4C, 0xF2, 0xF9, 0xDA, 0x51, 0x1B, 0xFD, 0x9A, 0x29, 0x10, 0xBE, 0x87, + 0x74, 0x76, 0x1B, 0x29, 0xCD, 0x70, 0x58, 0xFE, 0xEE, 0x01, 0xE0, 0x81, 0x6B, 0x44, 0xB9, 0x7A, 0xFC, 0xE3, 0x13, 0x39, + 0xCC, 0x30, 0xFD, 0x72, 0x74, 0xDE, 0x6D, 0x19, 0xAF, 0x37, 0xFB, 0x82, 0xCE, 0x34, 0xF9, 0x60, 0xD8, 0x19, 0x25, 0x75, + 0xD4, 0xFC, 0xE0, 0xBD, 0x06, 0x44, 0x74, 0x0E, 0xC9, 0xEB, 0x8F, 0x33, 0xD8, 0x9E, 0x07, 0x7E, 0x71, 0xDD, 0x69, 0x43, + 0xC6, 0x91, 0x04, 0x4D, 0x65, 0xBC, 0xE5, 0x4E, 0xA4, 0x94, 0xC4, 0xFC, 0x61, 0x2F, 0x63, 0xB8, 0x82, 0x7F, 0x9A, 0xC1, + 0x07, 0xE2, 0xBD, 0x8D, 0xCF, 0x67, 0x79, 0xC9, 0x9B, 0x6F, 0x0F, 0x82, 0x87, 0x2C, 0x46, 0xBF, 0x50, 0x0C, 0x73, 0x39, + 0xD7, 0xF7, 0x67, 0xC1, 0x8B, 0x1F, 0xB4, 0x5E, 0x13, 0x55, 0xAF, 0xD1, 0x0D, 0xFD, 0xC8, 0xF5, 0x8B, 0x98, 0xC3, 0xA5, + 0x07, 0x14, 0x2E, 0xB1, 0x8C, 0xB1, 0xFC, 0x1A, 0xD6, 0x78, 0x1E, 0xDC, 0x22, 0x42, 0x9D, 0xC3, 0xB2, 0x36, 0x40, 0x10, + 0x62, 0x5B, 0xAB, 0x53, 0x17, 0x8D, 0xC1, 0x56, 0xD0, 0x97, 0xD5, 0xE7, 0xCE, 0x18, 0x46, 0x11, 0x4B, 0x6A, 0x02, 0x73, + 0xBC, 0x02, 0xF4, 0x90, 0x42, 0x2C, 0xCF, 0x65, 0xD7, 0x0C, 0x08, 0x48, 0x06, 0xBB, 0x26, 0x8E, 0x62, 0x72, 0x50, 0x36, + 0xC4, 0x7A, 0x2E, 0x58, 0xAF, 0xBA, 0x04, 0x49, 0xA7, 0x72, 0x06, 0x0C, 0x75, 0xFB, 0x76, 0xF9, 0xC4, 0x89, 0x04, 0x95, + 0xD7, 0xCE, 0x49, 0x3D, 0x30, 0x3C, 0x5F, 0x22, 0xCF, 0xD8, 0x7D, 0x61, 0x46, 0xA8, 0x4C, 0x64, 0x54, 0x1C, 0x5D, 0xBF, + 0x25, 0xB8, 0x7F, 0x62, 0x01, 0x00, 0x71, 0x35, 0xDB, 0x0F, 0x46, 0xBC, 0x5C, 0x90, 0x0E, 0xF7, 0xEE, 0x69, 0x66, 0x9D, + 0x03, 0xF5, 0x34, 0x0A, 0x17, 0xDF, 0xB7, 0x27, 0x9A, 0x62, 0x20, 0xD7, 0x4E, 0x76, 0xF6, 0x7E, 0x08, 0xD8, 0x48, 0xB4, + 0x77, 0x01, 0x99, 0xC8, 0x1F, 0xFF, 0xE7, 0x1A, 0xDA, 0x78, 0xFC, 0x28, 0x3C, 0x1E, 0xE7, 0x63, 0x0E, 0x3E, 0xEE, 0xB9, + 0x40, 0xFE, 0x6C, 0xCC, 0x84, 0x6E, 0x20, 0x9F, 0xC0, 0xFF, 0xD9, 0x14, 0xE1, 0xBF, 0x7F, 0x43, 0xDA, 0xF1, 0x53, 0xD1, + 0xFF, 0x20, 0x37, 0x1D, 0xD2, 0xB4, 0x97, 0x34, 0x83, 0xB5, 0x9D, 0x90, 0x4F, 0x84, 0x61, 0xCB, 0xB5, 0x9E, 0x06, 0xDB, + 0x31, 0xEB, 0xC1, 0xD5, 0xC2, 0xA0, 0x3A, 0x96, 0xE8, 0x28, 0x4F, 0xCE, 0xE2, 0x41, 0x19, 0x47, 0x5D, 0xC4, 0x3A, 0xE1, + 0x89, 0x0C, 0x25, 0x6A, 0x0F, 0xFE, 0xAE, 0xCE, 0x42, 0x4D, 0x59, 0x71, 0xA3, 0x6E, 0x21, 0xE0, 0xD4, 0xBB, 0xA2, 0x41, + 0x13, 0x3A, 0xF8, 0xEA, 0xD6, 0xD0, 0x1E, 0x17, 0x45, 0xDB, 0xA8, 0x6F, 0x27, 0x06, 0xB3, 0xB6, 0x93, 0xFA, 0xD8, 0xB6, + 0xD1, 0x46, 0x73, 0x2B, 0xEE, 0x99, 0x9E, 0x41, 0x01, 0x08, 0xA1, 0x04, 0x7F, 0xAD, 0xF4, 0x7A, 0xA9, 0x32, 0x8A, 0x65, + 0x07, 0x3B, 0x0C, 0xC9, 0xA3, 0x37, 0x09, 0x88, 0xF7, 0x21, 0xBA, 0x8A, 0xBC, 0x47, 0x19, 0x74, 0x5C, 0x9B, 0xD9, 0x9B, + 0x77, 0x01, 0x63, 0xCC, 0x46, 0x9C, 0xF2, 0x17, 0x6C, 0xE3, 0x6B, 0xAE, 0x8C, 0xBB, 0x6C, 0xE5, 0x28, 0x4B, 0x3E, 0x7E, + 0xEE, 0x4C, 0x64, 0x05, 0xA2, 0x4A, 0xA8, 0xC7, 0xA9, 0x66, 0xC3, 0xD1, 0xA3, 0xD1, 0x23, 0x17, 0x14, 0x4F, 0x80, 0x28, + 0xAB, 0xB5, 0xAB, 0xDC, 0x7B, 0xEA, 0x5A, 0x76, 0x8F, 0xE9, 0xB3, 0x2C, 0xED, 0xD4, 0x42, 0x22, 0x2C, 0xE0, 0x2C, 0x04, + 0xDF, 0x4B, 0x07, 0xCA, 0xDE, 0xBB, 0xCE, 0x4B, 0xBB, 0xA6, 0x3A, 0xAA, 0xCC, 0xB9, 0xED, 0x33, 0xA7, 0x02, 0x8A, 0x99, + 0xE4, 0x0E, 0x2C, 0xAC, 0xAF, 0x22, 0x65, 0xA8, 0x47, 0xE6, 0x7D, 0xA8, 0x7F, 0x90, 0x7B, 0xB2, 0x6B, 0xF1, 0x3D, 0xAF, + 0x18, 0x24, 0xC3, 0x32, 0x37, 0xF2, 0xB5, 0xB9, 0xDB, 0x0E, 0x0F, 0xF8, 0x09, 0xDB, 0x5B, 0x1B, 0x50, 0x32, 0x23, 0xF9, + 0x2B, 0xB0, 0x77, 0xEE, 0x90, 0x65, 0x92, 0xA4, 0xAF, 0x12, 0x81, 0xF7, 0x41, 0xB9, 0x51, 0x9F, 0x10, 0x12, 0x1C, 0xC6, + 0x30, 0x7F, 0x64, 0x8E, 0xD6, 0xE5, 0x97, 0x95, 0xD8, 0xA8, 0x7A, 0x10, 0x94, 0xF7, 0x98, 0xF3, 0xF0, 0x7F, 0xB2, 0x80, + 0x2D, 0x1E, 0x05, 0xE5, 0xBC, 0x99, 0x58, 0xB5, 0x6D, 0xAF, 0x05, 0x62, 0xF2, 0x87, 0xF2, 0x60, 0x1E, 0x20, 0xFF, 0x91, + 0xE9, 0xC8, 0x8A, 0x71, 0xAD, 0x87, 0x3E, 0x23, 0x2D, 0x95, 0x14, 0x41, 0x72, 0xB9, 0x21, 0x2B, 0xD3, 0x62, 0xC9, 0x02, + 0xE0, 0x50, 0xAC, 0x66, 0x77, 0xED, 0x04, 0xC1, 0x5C, 0xD7, 0xF6, 0x5E, 0x80, 0x31, 0x3E, 0xF9, 0x62, 0x95, 0xC1, 0x16, + 0xDF, 0x7A, 0x5B, 0x86, 0x68, 0x6F, 0x3C, 0xB7, 0x28, 0x09, 0x73, 0x83, 0x1D, 0x3A, 0xEF, 0x07, 0x70, 0x3E, 0x8D, 0x1D, + 0x25, 0x56, 0x49, 0x51, 0xBF, 0xBE, 0xE2, 0x36, 0x21, 0x48, 0xBD, 0xB1, 0xFC, 0x7A, 0x56, 0x76, 0x24, 0xB3, 0x02, 0x08, + 0x44, 0x29, 0x81, 0xB7, 0x4A, 0xFC, 0xC8, 0x3F, 0x7C, 0xD3, 0xCE, 0x69, 0x96, 0xBB, 0x0E, 0x18, 0x45, 0x28, 0x3E, 0xDA, + 0x80, 0x88, 0x31, 0x4D, 0xAF, 0x79, 0xFA, 0x99, 0xC3, 0x65, 0x47, 0x65, 0x56, 0xC1, 0x04, 0x95, 0xA0, 0xCB, 0xF5, 0xA9, + 0x25, 0xC7, 0x51, 0x76, 0xF9, 0x18, 0xB1, 0xE5, 0x5B, 0x1B, 0x64, 0xCA, 0x95, 0xA4, 0x38, 0x22, 0x92, 0xCD, 0xAA, 0x48, + 0xD6, 0x3C, 0x96, 0x1F, 0x62, 0xB1, 0x5E, 0xFC, 0xE8, 0x14, 0x9C, 0x12, 0xD9, 0x71, 0x5C, 0xDC, 0xC0, 0xFB, 0x2D, 0x22, + 0xDA, 0x8B, 0xCE, 0x8A, 0x80, 0xEC, 0x65, 0xA3, 0x7D, 0xA5, 0xEB, 0x8B, 0x29, 0xE3, 0x6B, 0x52, 0x45, 0xB3, 0xCA, 0x8B, + 0x96, 0x51, 0x9D, 0x16, 0x59, 0x82, 0x75, 0x65, 0x40, 0xD9, 0xB0, 0xAF, 0x69, 0xA0, 0x9F, 0x31, 0x74, 0xF4, 0xB9, 0x7F, + 0xFA, 0x1C, 0xA7, 0xEA, 0x9D, 0xC2, 0x9E, 0x3F, 0x62, 0xCC, 0x48, 0x3F, 0xA4, 0xDB, 0x5C, 0x48, 0x28, 0x1F, 0xEF, 0x96, + 0x5E, 0xE1, 0x57, 0x0D, 0x91, 0x35, 0x46, 0x0B, 0x67, 0xE3, 0x43, 0x49, 0x5B, 0x1E, 0x23, 0xF6, 0x82, 0xD3, 0x65, 0xF9, + 0x69, 0xC0, 0x13, 0x17, 0xA4, 0xCD, 0x8B, 0x9B, 0x59, 0x80, 0x79, 0x3B, 0x87, 0x82, 0x0D, 0x69, 0x36, 0xC6, 0xB8, 0xDB, + 0xE5, 0x8E, 0x02, 0x57, 0x95, 0xB8, 0x17, 0x20, 0x67, 0xA4, 0xB0, 0x31, 0x4A, 0xE3, 0x10, 0x26, 0xC6, 0xC9, 0x70, 0x79, + 0x1D, 0xA5, 0x24, 0xA5, 0xEE, 0x2C, 0x15, 0x24, 0x81, 0xFA, 0xD7, 0x9D, 0xF2, 0x6D, 0xBA, 0x16, 0x4F, 0x65, 0x1E, 0xBE, + 0xC0, 0xC6, 0x8F, 0x35, 0x1B, 0xD0, 0x88, 0x44, 0x67, 0x4C, 0x5A, 0x1C, 0x03, 0x1B, 0xC5, 0xC0, 0xB2, 0x8D, 0xD3, 0xDC, + 0x2C, 0x2A, 0x01, 0x8D, 0x7A, 0x3F, 0xA1, 0xC6, 0x55, 0xEF, 0xB7, 0x13, 0x2E, 0xE9, 0x1D, 0xEC, 0x38, 0xA9, 0xCD, 0x6D, + 0xA5, 0x79, 0x4D, 0x2C, 0x50, 0xB4, 0x2A, 0x12, 0x6A, 0xA9, 0x12, 0xE1, 0x9F, 0x7D, 0x29, 0x3B, 0xA4, 0x58, 0x2F, 0xBA, + 0x58, 0x7A, 0xA5, 0xE3, 0xE3, 0x41, 0x26, 0x5A, 0xAF, 0xB8, 0xD4, 0xD8, 0xB4, 0x61, 0x0C, 0x61, 0xBF, 0x60, 0x83, 0x2E, + 0xA9, 0xC5, 0xF4, 0x7D, 0xE0, 0xA2, 0x97, 0xA8, 0xB5, 0xC1, 0x02, 0xDD, 0x5F, 0x3F, 0xE4, 0x38, 0xF1, 0xCE, 0x83, 0xA4, + 0xEF, 0xAF, 0x8D, 0xE8, 0x4B, 0xC8, 0x26, 0x1C, 0xFD, 0xAD, 0x3A, 0x53, 0x47, 0x00, 0x2A, 0x03, 0x10, 0xEF, 0x02, 0x01, + 0x41, 0xAF, 0xB0, 0xA1, 0xFC, 0xEB, 0xAA, 0xCD, 0x0E, 0x9E, 0x5D, 0xDA, 0x38, 0x00, 0xC8, 0x89, 0x62, 0x33, 0x93, 0x2B, + 0xD1, 0xE3, 0x94, 0xDF, 0xD0, 0xCC, 0x6F, 0x2F, 0x7E, 0xC3, 0x31, 0xC6, 0x4D, 0x87, 0x73, 0x9A, 0xBC, 0xCF, 0x5D, 0x79, + 0x4F, 0xEF, 0xE7, 0x7B, 0x30, 0xF2, 0x0F, 0x5C, 0x40, 0x04, 0x31, 0xD4, 0x9F, 0x66, 0xD3, 0x63, 0x9A, 0xA2, 0x14, 0x51, + 0xF7, 0x91, 0xFB, 0xF5, 0x9A, 0xBF, 0x01, 0xE9, 0xA1, 0x34, 0xE4, 0x99, 0x53, 0x26, 0x6A, 0x2C, 0x87, 0x22, 0x22, 0xBC, + 0x90, 0x90, 0x1E, 0xC9, 0x21, 0x0E, 0x7D, 0x6D, 0xA9, 0x38, 0xA5, 0x9B, 0xDE, 0x2A, 0x5B, 0x8F, 0x10, 0x75, 0x1A, 0x80, + 0x9E, 0x56, 0x3A, 0x51, 0x22, 0x3F, 0x74, 0x89, 0xCB, 0xC8, 0x27, 0xC2, 0xD9, 0x8F, 0xAE, 0xE7, 0xD5, 0xB5, 0x8F, 0x21, + 0xF9, 0x3E, 0x25, 0x2D, 0x44, 0xB5, 0x83, 0x76, 0x6F, 0xCD, 0xD4, 0xF1, 0xF6, 0xB1, 0x07, 0xD3, 0x47, 0x39, 0x4C, 0xB9, + 0x23, 0x1B, 0x5D, 0x18, 0x95, 0xD2, 0xDD, 0x85, 0x77, 0xF9, 0x0A, 0xDB, 0x4C, 0x01, 0x2D, 0xD6, 0x38, 0x4A, 0x22, 0xD3, + 0x94, 0xD7, 0xD5, 0x35, 0x9C, 0xF9, 0xDB, 0x9A, 0x47, 0xE7, 0x26, 0xFC, 0x0F, 0xD2, 0x21, 0xEA, 0x78, 0x9A, 0x96, 0x5F, + 0x9C, 0x78, 0x70, 0x75, 0x79, 0x9A, 0x71, 0x9F, 0x3B, 0x43, 0xDB, 0xC4, 0xFB, 0xD3, 0x9D, 0xAD, 0x09, 0x4D, 0xE7, 0x7A, + 0x13, 0x38, 0x5F, 0xC9, 0x8C, 0xFB, 0xF0, 0x98, 0x63, 0x27, 0x1F, 0x25, 0x34, 0x4B, 0x56, 0x60, 0xC6, 0xE4, 0xAC, 0xBB, + 0x69, 0x2A, 0xFD, 0x3F, 0xB3, 0xB7, 0xE1, 0xB0, 0xB9, 0xB5, 0xCD, 0xB0, 0xFB, 0x60, 0x0A, 0x5D, 0x2D, 0xB4, 0xA9, 0xEA, + 0x19, 0xD0, 0xB6, 0x6A, 0x50, 0x41, 0xC9, 0xED, 0x44, 0x38, 0xEF, 0xA1, 0xB2, 0x1B, 0xF5, 0x9A, 0x65, 0x7D, 0x96, 0xF9, + 0xFC, 0xF2, 0x58, 0x94, 0x7A, 0x5B, 0xE5, 0xD0, 0xAD, 0xBA, 0xB7, 0xA2, 0x90, 0x23, 0x9F, 0x2D, 0x7D, 0xBA, 0xEF, 0x2A, + 0x4F, 0xDF, 0x21, 0x1F, 0xBB, 0x4B, 0x68, 0x88, 0x97, 0xB3, 0x97, 0x9D, 0xD9, 0xFF, 0x60, 0x02, 0x79, 0x0D, 0x37, 0x05, + 0x9D, 0x2C, 0xB7, 0x26, 0x94, 0x24, 0xB8, 0xE6, 0x84, 0xA6, 0xCD, 0xF2, 0x32, 0xB1, 0x6E, 0x66, 0xFA, 0x87, 0xDC, 0xE0, + 0x4D, 0x47, 0xFE, 0xC5, 0x93, 0x21, 0x4B, 0x1C, 0x02, 0x01, 0xE9, 0x1B, 0x56, 0xD6, 0x29, 0xCE, 0xCE, 0x20, 0x36, 0xB2, + 0x31, 0xCD, 0xB1, 0xEF, 0x91, 0x4E, 0xD7, 0x87, 0x95, 0x8C, 0x91, 0xFC, 0x62, 0x3E, 0xE7, 0x03, 0x3A, 0x86, 0xF8, 0x07, + 0xC8, 0x4D, 0xA0, 0x03, 0x5D, 0x20, 0xAB, 0x90, 0x4A, 0x22, 0xEE, 0xA8, 0x32, 0xBB, 0x7A, 0xAE, 0xFE, 0xD4, 0x08, 0x59, + 0x13, 0x23, 0xF4, 0xE3, 0x26, 0x4F, 0xA0, 0x46, 0xAC, 0x7E, 0x03, 0x52, 0xE7, 0x09, 0x07, 0xC7, 0x1F, 0x8C, 0xAE, 0x13, + 0x39, 0xFB, 0x2E, 0x16, 0xC9, 0x92, 0xB2, 0x7E, 0xEA, 0x52, 0x61, 0x6C, 0x32, 0xD8, 0x1E, 0xF5, 0xDF, 0x3B, 0xE7, 0x06, + 0x70, 0x28, 0xFD, 0x8C, 0x17, 0x1C, 0x61, 0xFF, 0xC6, 0x83, 0x58, 0x3D, 0xCA, 0x4B, 0xCC, 0x1F, 0x48, 0xC7, 0x6A, 0xB8, + 0x11, 0x06, 0x21, 0x66, 0xCC, 0xD5, 0x56, 0xC8, 0x45, 0x46, 0xB9, 0x27, 0x81, 0xC2, 0x5A, 0x81, 0x2D, 0xF5, 0xE4, 0x05, + 0x73, 0xBC, 0x50, 0xCB, 0x4A, 0x02, 0xA1, 0x6B, 0x4A, 0xFE, 0x52, 0x90, 0xAB, 0x29, 0xB4, 0x42, 0x4D, 0xEE, 0x3C, 0x3F, + 0x19, 0x2F, 0x3E, 0xB5, 0x5E, 0x7D, 0xD8, 0x26, 0x2B, 0xDE, 0x76, 0x2E, 0x29, 0x06, 0x68, 0xEF, 0xB9, 0xC7, 0xD3, 0x13, + 0xFD, 0x2D, 0x30, 0x38, 0x45, 0xF1, 0x32, 0xDE, 0x9E, 0x9D, 0x60, 0xFC, 0x57, 0x31, 0x79, 0xDD, 0xFA, 0xD2, 0x83, 0x84, + 0x95, 0x91, 0x6C, 0xAB, 0x8A, 0xD3, 0x7B, 0x50, 0xCC, 0xDE, 0x83, 0x71, 0xB8, 0x68, 0x70, 0x06, 0xE8, 0x09, 0x0B, 0x50, + 0xB4, 0x6E, 0x61, 0xFE, 0x38, 0xE2, 0xC3, 0x44, 0xEC, 0x8A, 0xE8, 0x00, 0xDC, 0x30, 0xBC, 0xF4, 0x84, 0x39, 0xDA, 0xC0, + 0x34, 0xD1, 0x37, 0x32, 0xAC, 0x96, 0xEE, 0x8F, 0xEF, 0x9C, 0x8D, 0x09, 0x52, 0x22, 0x4E, 0xAE, 0x8A, 0x35, 0xFE, 0xB0, + 0x9A, 0xA7, 0xA9, 0xC3, 0x23, 0xC6, 0x05, 0xC2, 0x94, 0xC9, 0xE8, 0x52, 0x64, 0xDF, 0xAF, 0x56, 0x3A, 0xD9, 0x73, 0x02, + 0xCA, 0x95, 0x1A, 0x66, 0x35, 0xBE, 0x25, 0xD1, 0xE5, 0xF1, 0xE3, 0x2A, 0x9A, 0xC5, 0x7A, 0x04, 0xFC, 0xB9, 0x21, 0x3E, + 0x01, 0x13, 0x5E, 0xE4, 0x89, 0xF2, 0x09, 0xC6, 0x45, 0x54, 0x5A, 0x52, 0xA6, 0xAD, 0x0C, 0x1D, 0x88, 0x2E, 0xEE, 0xEF, + 0x8F, 0xFE, 0x1C, 0xA8, 0x70, 0x34, 0x09, 0x52, 0x01, 0x1C, 0x7D, 0xF4, 0x13, 0x49, 0x0B, 0x73, 0xE6, 0x82, 0x8A, 0x85, + 0x81, 0x00, 0x75, 0x96, 0x61, 0x95, 0x3C, 0xB3, 0x51, 0x27, 0x6B, 0xF5, 0x88, 0xD2, 0x7A, 0xB0, 0x74, 0x47, 0x86, 0x92, + 0xFE, 0xAC, 0xD4, 0x8E, 0xD3, 0x5C, 0xD8, 0xDB, 0x73, 0xDA, 0x97, 0x5F, 0xAA, 0xA4, 0x70, 0x02, 0xFC, 0x44, 0x19, 0x6F, + 0xBD, 0xB4, 0xF9, 0x78, 0x6B, 0xD2, 0x31, 0xA2, 0x9D, 0x8D, 0xE0, 0x78, 0x72, 0x0A, 0xBF, 0x73, 0xDB, 0x39, 0xE8, 0xDA, + 0xFB, 0x36, 0xAC, 0xF3, 0x25, 0xC7, 0xA4, 0xC6, 0x14, 0xE7, 0xDD, 0x9F, 0x52, 0x5F, 0x60, 0x88, 0xFA, 0xF4, 0x29, 0x4E, + 0x11, 0xD0, 0x0E, 0x50, 0xF7, 0xA1, 0x42, 0x0A, 0x14, 0x7D, 0xD6, 0xAE, 0xF8, 0x08, 0x7E, 0xFC, 0x49, 0x8C, 0x76, 0x9F, + 0xF5, 0xB2, 0x36, 0xF8, 0xBE, 0x0C, 0xFB, 0x70, 0xEC, 0x4B, 0xA9, 0x9E, 0xBA, 0x1E, 0xE8, 0x4B, 0x2A, 0x74, 0x9E, 0x63, + 0x1F, 0xBE, 0x74, 0xE6, 0x32, 0xF5, 0x6F, 0x16, 0x78, 0xAA, 0xC4, 0xAB, 0x69, 0x1F, 0x67, 0xE1, 0x3E, 0x8E, 0x0F, 0x67, + 0x10, 0xA4, 0x0B, 0x2D, 0x7A, 0xF7, 0x23, 0x64, 0x86, 0x83, 0x07, 0x31, 0x7F, 0x05, 0x08, 0xDD, 0x85, 0xA2, 0xE0, 0xB8, + 0xAF, 0xFC, 0x2F, 0x60, 0xA6, 0x85, 0x00, 0x9C, 0x81, 0x35, 0x58, 0x76, 0x16, 0xCE, 0xB9, 0x00, 0xBF, 0xF4, 0xA6, 0xE1, + 0x06, 0x81, 0x21, 0xF6, 0x74, 0xE2, 0xF5, 0xA6, 0x87, 0xE2, 0x0C, 0x6D, 0x30, 0x65, 0x28, 0x6C, 0x22, 0x85, 0x0C, 0x0C, + 0xFE, 0xD7, 0x86, 0x61, 0xCB, 0x49, 0xB1, 0x01, 0x25, 0xF3, 0xF5, 0xB1, 0x82, 0x09, 0xB0, 0xF6, 0x70, 0xA5, 0xEA, 0x5B, + 0x26, 0xC8, 0x2D, 0x06, 0x3D, 0x55, 0x50, 0xA9, 0x01, 0x5F, 0xFE, 0x34, 0xEC, 0x08, 0x58, 0xA9, 0x63, 0xAB, 0x27, 0x16, + 0x20, 0x93, 0x33, 0x5D, 0x6D, 0xE2, 0x35, 0xE2, 0x7F, 0x3C, 0xB1, 0x7B, 0x27, 0x76, 0xF5, 0x96, 0xA2, 0xE3, 0x96, 0xDF, + 0xD3, 0xF7, 0x24, 0xF2, 0x64, 0x2C, 0x39, 0x4C, 0xCF, 0xAB, 0x39, 0x2E, 0x1E, 0x3C, 0x72, 0x13, 0x6F, 0xA8, 0x22, 0xC8, + 0x8E, 0xAB, 0xB6, 0x0D, 0xEF, 0x7C, 0x00, 0x15, 0x23, 0xE8, 0xB7, 0xE2, 0x8D, 0x32, 0xC2, 0xDC, 0x9B, 0x5C, 0x70, 0x2F, + 0xCF, 0x81, 0x2A, 0xF9, 0x5F, 0x1C, 0x5B, 0xF7, 0x0C, 0x71, 0x40, 0xF4, 0xE3, 0xAA, 0x93, 0x31, 0x40, 0xC7, 0xDB, 0xED, + 0x5A, 0x1F, 0x30, 0x1F, 0x8E, 0x8F, 0x3B, 0x9D, 0x1D, 0x28, 0xA3, 0xD9, 0xE9, 0x66, 0xBF, 0x78, 0x5C, 0xE5, 0x42, 0x95, + 0x2A, 0x30, 0xFA, 0x77, 0xF5, 0xE8, 0x5A, 0xA8, 0x92, 0x88, 0x44, 0x93, 0x7F, 0x97, 0x20, 0x38, 0x64, 0x82, 0x4A, 0xA0, + 0xE6, 0x2C, 0x98, 0x69, 0xCB, 0x2B, 0x7C, 0xFA, 0x18, 0x45, 0xDC, 0x10, 0x0C, 0x8A, 0xB9, 0xDC, 0xEC, 0x5B, 0xD0, 0x6C, + 0x06, 0xAA, 0xC3, 0x83, 0xD6, 0x55, 0xEF, 0x69, 0x70, 0xE3, 0xF3, 0xA4, 0x6E, 0x2C, 0x44, 0x29, 0x8C, 0xC0, 0x20, 0x48, + 0xA0, 0xE6, 0x87, 0xB4, 0xF8, 0x75, 0x9C, 0xFA, 0x15, 0xF0, 0x94, 0xD0, 0x06, 0x04, 0x86, 0xA2, 0xF1, 0xE6, 0xAC, 0xD4, + 0xB7, 0x35, 0x94, 0x6A, 0xB5, 0x4A, 0xBC, 0xA3, 0x76, 0x7C, 0xE2, 0xB9, 0x71, 0xBF, 0x5B, 0xB0, 0xCF, 0x17, 0x09, 0xA3, + 0x49, 0xB9, 0x4B, 0xA4, 0x45, 0xDB, 0x14, 0xBD, 0x68, 0x46, 0xBE, 0x89, 0x6D, 0x62, 0xFD, 0x6E, 0xF5, 0x2C, 0x73, 0xD3, + 0xE1, 0x71, 0xDC, 0x17, 0x23, 0x4C, 0x1A, 0x9B, 0xCF, 0x4C, 0x4C, 0xFE, 0x30, 0x56, 0x74, 0x20, 0xE5, 0x92, 0x84, 0x09, + 0x8A, 0x3D, 0x52, 0x8B, 0x45, 0x6A, 0xB5, 0x81, 0x54, 0xF5, 0x24, 0x7F, 0xE8, 0xCE, 0x7B, 0x90, 0xC8, 0x78, 0x77, 0xB9, + 0x4D, 0x9F, 0x0B, 0x2F, 0x5B, 0xF9, 0xC2, 0xC7, 0x0F, 0x2E, 0x35, 0x3A, 0xE3, 0xED, 0x13, 0x0E, 0x83, 0xD5, 0x15, 0xDF, + 0xD4, 0xAD, 0x9B, 0x77, 0xF3, 0xB0, 0x83, 0xA2, 0x0F, 0x3E, 0x01, 0x7B, 0xB0, 0xF8, 0x66, 0x5F, 0x3A, 0x45, 0x78, 0xD9, + 0x7B, 0x5A, 0x69, 0xAE, 0xFF, 0xF6, 0x51, 0x67, 0x2D, 0x97, 0x3E, 0x59, 0x19, 0xD7, 0xD9, 0x7A, 0x69, 0x79, 0xE6, 0xAE, + 0x94, 0xB0, 0xCF, 0x01, 0x8E, 0x4C, 0x2C, 0xEF, 0xB8, 0xD6, 0xC8, 0xD8, 0xAB, 0xB6, 0x57, 0x90, 0xD8, 0x47, 0x47, 0x1D, + 0x51, 0xDA, 0xEF, 0xA0, 0xB5, 0xD7, 0xF5, 0x9F, 0x62, 0xD9, 0x9F, 0xAA, 0xCE, 0x7B, 0xF9, 0xE4, 0xD3, 0x3D, 0x1E, 0xBC, + 0x0D, 0x68, 0x3E, 0x6F, 0xEC, 0x90, 0x41, 0x9A, 0x78, 0x06, 0xCE, 0xA8, 0x4D, 0x67, 0x14, 0xAC, 0x0C, 0x3C, 0x1E, 0xBD, + 0x16, 0xC6, 0xC0, 0xBB, 0xDC, 0x7D, 0x5F, 0xFB, 0x8B, 0x31, 0x1D, 0xC7, 0x57, 0xB7, 0xF2, 0x6F, 0xF2, 0xDE, 0x3D, 0x6D, + 0xDC, 0xCE, 0x11, 0xDC, 0x4E, 0xF9, 0x17, 0x5B, 0xE4, 0xDF, 0x33, 0x7F, 0xF3, 0x74, 0x9F, 0x5F, 0xA3, 0xF0, 0x80, 0xD5, + 0x0C, 0x7B, 0x7B, 0xF5, 0x19, 0x20, 0x08, 0x35, 0x23, 0xBF, 0x94, 0xC6, 0xD2, 0x9C, 0x0E, 0xEC, 0xB1, 0x43, 0x58, 0x3A, + 0x3B, 0x94, 0x60, 0xB2, 0xC9, 0x10, 0xF8, 0x6B, 0xB6, 0xCC, 0x86, 0x73, 0x7B, 0xF9, 0xA7, 0xC9, 0x95, 0x57, 0x69, 0xA3, + 0x40, 0x8A, 0xEB, 0xD5, 0x03, 0x6D, 0xC2, 0xF2, 0x60, 0xAC, 0xDB, 0x2F, 0xBF, 0x63, 0x21, 0x83, 0xC9, 0xE1, 0x17, 0xD7, + 0x7D, 0xCE, 0xE0, 0xB6, 0x31, 0x93, 0xE0, 0x37, 0x36, 0x89, 0x9B, 0x29, 0xAB, 0x5D, 0x6F, 0x82, 0x76, 0x9B, 0xA8, 0x61, + 0xFE, 0x06, 0xC0, 0x51, 0x31, 0x15, 0xA4, 0xF4, 0x1C, 0x33, 0xA7, 0xF0, 0x42, 0xDC, 0xF9, 0xBE, 0xE2, 0xF9, 0xDF, 0x02, + 0x58, 0xEF, 0xFD, 0xF3, 0xD6, 0x4E, 0x69, 0x9F, 0xC2, 0x2B, 0xF7, 0x40, 0x93, 0x4A, 0x0A, 0xD1, 0xC8, 0x75, 0x99, 0xAD, + 0xCD, 0x46, 0x49, 0xF7, 0xF1, 0x95, 0x17, 0x7B, 0x30, 0x64, 0x55, 0xA2, 0x97, 0x2A, 0x28, 0xCA, 0x3F, 0x4C, 0x9B, 0xCE, + 0xFC, 0x5B, 0x50, 0x97, 0x61, 0x38, 0xE2, 0x02, 0xDF, 0xDD, 0xDA, 0xF5, 0xF9, 0xB4, 0x4E, 0xEC, 0xD8, 0xD1, 0x65, 0xD9, + 0x8B, 0x68, 0x34, 0x0C, 0x15, 0x26, 0xCC, 0x7C, 0xB3, 0x27, 0xA9, 0x88, 0x19, 0x09, 0xCB, 0xA5, 0x20, 0x06, 0x6D, 0xEC, + 0x53, 0x6B, 0x43, 0x2C, 0x36, 0x09, 0x60, 0x1B, 0xEF, 0xE6, 0x1B, 0x4E, 0xED, 0x4D, 0x92, 0x51, 0x52, 0x2F, 0x51, 0x6D, + 0x4C, 0xDF, 0xEA, 0xBC, 0xAD, 0x63, 0xE6, 0x1A, 0x88, 0xA6, 0x9A, 0xC8, 0x53, 0x6F, 0xDF, 0x7D, 0x4D, 0xBD, 0xA2, 0xFE, + 0x79, 0x9F, 0xAF, 0xC9, 0x76, 0x2E, 0x01, 0x5C, 0x1A, 0x3E, 0xDA, 0x2F, 0x9A, 0x4F, 0xB3, 0x29, 0x9D, 0xE3, 0xA9, 0x59, + 0x53, 0xE9, 0x04, 0xDF, 0x1B, 0x4F, 0xA5, 0xFD, 0xCB, 0x8F, 0xE3, 0xAD, 0x20, 0x60, 0xC4, 0x49, 0x37, 0x8B, 0xF3, 0xBE, + 0xC2, 0x3E, 0xB0, 0x32, 0x60, 0x8F, 0xC6, 0x20, 0x78, 0x06, 0xDE, 0x14, 0x1E, 0x11, 0x60, 0x14, 0xCD, 0x11, 0xE3, 0xC2, + 0x0B, 0x35, 0x79, 0xA7, 0x5F, 0x35, 0x21, 0x78, 0x00, 0xB9, 0xED, 0x03, 0x4C, 0x73, 0x85, 0xCE, 0x88, 0x16, 0x22, 0x14, + 0xF6, 0x52, 0xD4, 0x93, 0xDE, 0x33, 0x21, 0xD7, 0x32, 0xE7, 0xE6, 0xF6, 0x1C, 0xE5, 0xBB, 0x11, 0x7D, 0x7E, 0x2C, 0x02, + 0xA4, 0xE1, 0x06, 0x83, 0xF0, 0xB4, 0x9E, 0x10, 0x6E, 0x5B, 0xF3, 0x92, 0x81, 0xC9, 0x48, 0x97, 0xA2, 0x1B, 0xEC, 0xC4, + 0xCA, 0xB4, 0x8C, 0x0D, 0x22, 0x53, 0x85, 0xFE, 0x96, 0xCC, 0xD5, 0x06, 0xA0, 0xE3, 0x8D, 0xD5, 0xC1, 0x36, 0x6F, 0x1E, + 0xE4, 0xAC, 0x79, 0x7F, 0xF1, 0x04, 0x72, 0x83, 0xE0, 0x18, 0xB6, 0x2F, 0x42, 0x55, 0x7A, 0x9A, 0x02, 0x58, 0xC5, 0x71, + 0x90, 0x73, 0xC6, 0x59, 0xD4, 0x43, 0x64, 0x93, 0xF6, 0xB5, 0xAD, 0x32, 0x6B, 0x78, 0x22, 0x53, 0x7E, 0x58, 0x5D, 0x99, + 0x52, 0x19, 0x8C, 0x6F, 0xDD, 0x96, 0xB1, 0xC3, 0xB4, 0x18, 0x36, 0x1E, 0xFE, 0x5E, 0xB1, 0x64, 0x89, 0xB1, 0xF9, 0x1E, + 0xD3, 0xBC, 0x87, 0xF7, 0x19, 0x86, 0x72, 0x7E, 0x9E, 0x95, 0x54, 0x9B, 0xD6, 0x3B, 0x39, 0x6C, 0x51, 0x2B, 0xBC, 0x18, + 0x35, 0x18, 0x5F, 0x65, 0xD1, 0x3B, 0x4C, 0xC0, 0xC1, 0xBA, 0x02, 0x49, 0x79, 0xCE, 0xE2, 0x37, 0x99, 0x1D, 0xC1, 0x68, + 0x73, 0xA1, 0xFC, 0xC7, 0xC7, 0xB6, 0x3D, 0xCC, 0xA8, 0xC1, 0x0E, 0x4D, 0x2F, 0x5B, 0x96, 0xE8, 0xA6, 0xE0, 0x19, 0x52, + 0xBA, 0xCA, 0x58, 0xAD, 0xFA, 0xEE, 0x6D, 0x16, 0x1D, 0xE1, 0xEF, 0x17, 0x77, 0x88, 0x79, 0xDF, 0xC0, 0x9A, 0x74, 0x82, + 0x9F, 0x24, 0xFC, 0x45, 0x4A, 0xEE, 0x70, 0xA3, 0x02, 0xA3, 0x38, 0x13, 0xF8, 0xB1, 0xFE, 0x94, 0x10, 0x2D, 0xA7, 0x0A, + 0x42, 0x79, 0x64, 0x74, 0x7A, 0x6A, 0x3D, 0x10, 0xE0, 0x9A, 0xF6, 0x25, 0x01, 0x0E, 0x9B, 0x35, 0xF8, 0x70, 0x32, 0x6E, + 0xE9, 0x49, 0xE1, 0xCA, 0x30, 0x22, 0xDF, 0x31, 0x7F, 0x47, 0xF3, 0x07, 0x18, 0x86, 0x89, 0x7B, 0x2F, 0x46, 0x0F, 0xE7, + 0x7A, 0x2E, 0x9B, 0x51, 0x07, 0x37, 0xC6, 0x41, 0xB7, 0x1C, 0x39, 0xFB, 0xF5, 0x77, 0x3E, 0xD1, 0x1A, 0x09, 0x20, 0x9B, + 0xDE, 0xE6, 0xB0, 0xCB, 0x85, 0xC0, 0x90, 0xC6, 0x0C, 0x69, 0xCF, 0x65, 0x6C, 0x20, 0x09, 0xF0, 0x4F, 0xA4, 0x40, 0x22, + 0x43, 0xCA, 0xC0, 0xA6, 0x0B, 0xE3, 0x1F, 0xD1, 0x52, 0x43, 0x6A, 0x4A, 0x90, 0x7C, 0x9F, 0xE1, 0xE4, 0x34, 0x89, 0xE5, + 0x56, 0x5F, 0xED, 0xA2, 0x67, 0xA7, 0xEC, 0x53, 0xDF, 0x0E, 0x19, 0xD3, 0x9D, 0x4C, 0xA9, 0xFA, 0x74, 0xA5, 0x68, 0x6A, + 0x48, 0xB3, 0x81, 0x15, 0xC4, 0x03, 0xDE, 0x59, 0xC8, 0x3E, 0x62, 0x35, 0x72, 0xBC, 0xD0, 0x3E, 0x76, 0x89, 0xFA, 0x80, + 0xE6, 0x5C, 0x39, 0x55, 0xB2, 0x64, 0xF5, 0x29, 0x22, 0xA9, 0x8F, 0x6C, 0x01, 0xE8, 0x06, 0x87, 0x1B, 0xBC, 0x0D, 0x2C, + 0x1A, 0xC2, 0xE1, 0x20, 0xB6, 0xA8, 0x70, 0x19, 0xF2, 0xAB, 0x5C, 0x21, 0x6B, 0x1E, 0x9B, 0xA4, 0x32, 0x66, 0x7B, 0x3E, + 0x17, 0x1E, 0xCA, 0xC0, 0x9A, 0x18, 0x72, 0x3C, 0xE9, 0x27, 0x76, 0x88, 0xCC, 0xCF, 0x3F, 0xAF, 0x58, 0x6C, 0x2B, 0x9C, + 0x9D, 0x8E, 0xD0, 0xEE, 0x9E, 0x02, 0x02, 0xF8, 0x6D, 0x1F, 0xB4, 0x5A, 0x20, 0x12, 0xC6, 0x50, 0xE5, 0xFA, 0x64, 0x73, + 0x75, 0xEA, 0xB4, 0x09, 0x8F, 0xEE, 0x57, 0xFE, 0x95, 0x44, 0x88, 0xA0, 0xF0, 0x8F, 0x4F, 0x3D, 0x64, 0xA6, 0x41, 0x99, + 0x4D, 0x87, 0xC1, 0x81, 0x24, 0xF4, 0xE4, 0x83, 0x35, 0x4B, 0xDA, 0xB4, 0xB1, 0xA6, 0x0A, 0x6E, 0xBC, 0xDF, 0x7B, 0xE1, + 0x56, 0x73, 0xEC, 0x6B, 0x04, 0x0A, 0x8F, 0x89, 0xED, 0x1A, 0x02, 0x50, 0x4B, 0x0E, 0x7C, 0xF6, 0xA7, 0x7C, 0x01, 0x7E, + 0x04, 0xE9, 0x0A, 0xFC, 0x69, 0x1D, 0x07, 0x92, 0x45, 0x2D, 0x26, 0x23, 0xB5, 0xE9, 0x9B, 0x97, 0xBE, 0xAC, 0x08, 0x1F, + 0x32, 0xA5, 0x82, 0x83, 0xC4, 0x7C, 0xDD, 0xF5, 0xE1, 0xFC, 0x66, 0x84, 0xB4, 0xC0, 0x48, 0xA0, 0xC1, 0xA4, 0x0B, 0x60, + 0xB2, 0x07, 0xF3, 0xE4, 0xA5, 0x08, 0xC9, 0x4A, 0xA0, 0x83, 0x22, 0xD1, 0x04, 0xD9, 0xD0, 0x68, 0x64, 0x17, 0xF4, 0x59, + 0x96, 0xFA, 0x46, 0xCC, 0x7E, 0x3D, 0x5D, 0x2F, 0x7E, 0xF4, 0x4D, 0xDA, 0x15, 0x6B, 0x4E, 0xB8, 0xD2, 0xF0, 0x3D, 0x4D, + 0x5C, 0x6C, 0x56, 0x31, 0xA7, 0x4A, 0xD0, 0x88, 0x7A, 0x67, 0x9D, 0xB7, 0x41, 0xFA, 0x46, 0x88, 0x2D, 0x95, 0xF6, 0x10, + 0xC7, 0x6D, 0x64, 0xD4, 0x0E, 0xFD, 0x76, 0xB3, 0x37, 0xBA, 0xFC, 0x34, 0xAF, 0x9D, 0xC6, 0x18, 0xC1, 0xF8, 0xA9, 0x49, + 0xE9, 0x52, 0xB8, 0x56, 0x72, 0xB4, 0x5D, 0xEB, 0xAA, 0xD8, 0x54, 0xB0, 0x42, 0xB4, 0x49, 0x0E, 0x8F, 0xD3, 0xE7, 0x51, + 0xDE, 0xB9, 0x27, 0xF9, 0xCC, 0xCE, 0xCF, 0xC0, 0x1E, 0x30, 0x59, 0x07, 0x11, 0x9F, 0xA7, 0xAF, 0x1C, 0xE0, 0x66, 0x08, + 0xAD, 0xDA, 0x1E, 0xC6, 0x9B, 0x63, 0x2C, 0xBE, 0x52, 0x73, 0xBC, 0x10, 0xDD, 0xF1, 0xA0, 0x5E, 0x7C, 0x0E, 0x2E, 0x0B, + 0xB3, 0xA6, 0x00, 0xFD, 0xCE, 0x2C, 0xF6, 0x54, 0x8A, 0xF2, 0xD0, 0xEF, 0xA8, 0x07, 0xE6, 0xA9, 0x8D, 0x5A, 0xD7, 0x99, + 0x8C, 0xD2, 0xBD, 0xF2, 0x5D, 0xF8, 0x7F, 0xDF, 0xBB, 0xDD, 0xC1, 0xA1, 0x18, 0xAF, 0x80, 0x89, 0x99, 0x00, 0x4B, 0x80, + 0x5C, 0xBE, 0xA7, 0x28, 0x33, 0x22, 0xF8, 0xB4, 0xE0, 0x8F, 0xD0, 0x79, 0x6E, 0x01, 0x5F, 0x63, 0xB1, 0xCF, 0x98, 0x63, + 0x31, 0x0A, 0x48, 0x58, 0x08, 0xD5, 0x02, 0x31, 0x62, 0x20, 0x38, 0xC2, 0x26, 0xBD, 0xB9, 0x70, 0xB0, 0x0B, 0x25, 0x21, + 0x4C, 0xC1, 0x71, 0x3F, 0x7D, 0x4F, 0x1E, 0xD6, 0xDF, 0x79, 0x0A, 0xF9, 0xD3, 0x4E, 0xD8, 0x6A, 0xEE, 0x23, 0x67, 0x18, + 0x28, 0x72, 0x46, 0xE4, 0xEE, 0x93, 0x93, 0x2F, 0x23, 0x76, 0x1B, 0x45, 0x71, 0x8F, 0x90, 0xF5, 0x95, 0x06, 0x6A, 0xEC, + 0xA7, 0xAB, 0x36, 0x56, 0xE2, 0xA6, 0x9A, 0x4A, 0xF8, 0x41, 0x58, 0x70, 0xA2, 0x5E, 0xE2, 0x8E, 0xA8, 0x1E, 0x84, 0x32, + 0xF4, 0x77, 0x52, 0xB6, 0x16, 0xAB, 0x53, 0x66, 0xC2, 0x46, 0xD0, 0x1A, 0x35, 0x27, 0x1E, 0xA2, 0x0F, 0x0A, 0xF1, 0xAE, + 0x6E, 0x4B, 0xB5, 0x97, 0xF0, 0x2A, 0x99, 0x99, 0xBF, 0x58, 0x5C, 0xEA, 0x76, 0x8D, 0x79, 0xAC, 0x12, 0x5A, 0xBE, 0xBB, + 0x4B, 0x42, 0xED, 0xA8, 0x0F, 0x47, 0x08, 0xE5, 0x89, 0xD2, 0x5C, 0xE3, 0x1F, 0x71, 0x0F, 0xBC, 0x3F, 0x91, 0x47, 0x21, + 0xB8, 0xD6, 0xFC, 0x37, 0x2B, 0x0E, 0xDA, 0x2D, 0x3D, 0x8B, 0xD2, 0xD9, 0x56, 0xEB, 0x48, 0x6A, 0xA7, 0x50, 0x8B, 0x9D, + 0xDA, 0xCB, 0x86, 0x46, 0x64, 0x97, 0x03, 0x20, 0x35, 0x7A, 0x5B, 0xE1, 0x72, 0xB0, 0xBD, 0x3B, 0x78, 0x7D, 0xA5, 0x0C, + 0x5A, 0xFC, 0xAA, 0x4C, 0x9F, 0xB1, 0xAB, 0xE8, 0x5E, 0x52, 0x9F, 0xAB, 0x87, 0xF0, 0xE2, 0x60, 0xF0, 0x69, 0xA1, 0x0B, + 0x22, 0x44, 0x87, 0x74, 0x68, 0x6D, 0x3D, 0x4F, 0x6B, 0xAD, 0x30, 0x59, 0x27, 0xA5, 0xF8, 0x1A, 0xA3, 0x9F, 0x0E, 0x54, + 0xED, 0x19, 0x33, 0x5B, 0x2E, 0x4E, 0xF1, 0xED, 0x4F, 0x80, 0x1F, 0x89, 0x8E, 0x9E, 0x1B, 0x20, 0x81, 0x69, 0x00, 0x0F, + 0xDC, 0x93, 0x7B, 0xF6, 0x46, 0xEF, 0xD4, 0xE7, 0x81, 0xA6, 0x54, 0x18, 0x71, 0xFB, 0xF3, 0x14, 0x29, 0x67, 0x33, 0x72, + 0x51, 0x33, 0x3C, 0x04, 0xC2, 0x34, 0x3C, 0xC6, 0x13, 0x64, 0xC5, 0x80, 0x3E, 0x9F, 0xDC, 0x44, 0x17, 0x22, 0xEA, 0xD3, + 0x36, 0x54, 0x93, 0x94, 0x92, 0xDD, 0x62, 0x7A, 0x24, 0x14, 0xD4, 0xCC, 0x16, 0xBE, 0xA2, 0x53, 0x96, 0x57, 0xE3, 0xB2, + 0x18, 0x23, 0xBB, 0xA2, 0x02, 0x19, 0x08, 0xD5, 0x0A, 0x30, 0xAB, 0x93, 0x25, 0x38, 0x50, 0x19, 0xC6, 0x35, 0x16, 0xA4, + 0x5B, 0x57, 0x6C, 0xA6, 0x90, 0x33, 0x96, 0x83, 0x2C, 0x5C, 0x07, 0xD7, 0x0C, 0x7C, 0x38, 0xE5, 0x43, 0xA9, 0x7D, 0xE1, + 0x30, 0x7E, 0xB2, 0x21, 0xE6, 0xF6, 0x7A, 0x9E, 0x2F, 0x37, 0x41, 0x3F, 0x02, 0xBC, 0x1D, 0x91, 0x10, 0x52, 0xDD, 0x60, + 0xAC, 0xFA, 0x00, 0xDD, 0x98, 0x7F, 0xEE, 0x2B, 0x2E, 0x82, 0x55, 0x04, 0x9F, 0x78, 0xC9, 0x00, 0x1B, 0x5C, 0xEE, 0x88, + 0xF9, 0x75, 0x5E, 0x1D, 0x19, 0x1F, 0xE0, 0xB8, 0xE9, 0x1A, 0x9E, 0x71, 0xD2, 0x5F, 0xB6, 0xBA, 0xF8, 0x77, 0x13, 0x8D, + 0xF7, 0x76, 0x89, 0x7F, 0xBE, 0xA0, 0x48, 0x09, 0xD7, 0x4A, 0xBF, 0x4F, 0x79, 0x1E, 0x2F, 0x68, 0x08, 0xE4, 0xA8, 0x39, + 0xBF, 0x81, 0x13, 0xBE, 0x48, 0xD3, 0xC1, 0x7F, 0xEB, 0x39, 0x3E, 0xDD, 0xCA, 0xC9, 0xBE, 0x4E, 0x3F, 0x87, 0x1B, 0x78, + 0x95, 0xF1, 0x47, 0xD7, 0x29, 0xE9, 0xE2, 0x5D, 0xFE, 0x7F, 0x1E, 0x8C, 0x1F, 0xB6, 0xDE, 0xE9, 0x78, 0x1C, 0xF8, 0xD4, + 0x70, 0xD9, 0x3F, 0x21, 0xA6, 0xC2, 0x9D, 0xC9, 0x19, 0x38, 0x1E, 0xAE, 0x34, 0x54, 0x1A, 0x69, 0xF1, 0x05, 0x26, 0x32, + 0x54, 0x94, 0x41, 0xE1, 0x50, 0x7B, 0x61, 0x8D, 0x54, 0xE2, 0xCA, 0x39, 0xC8, 0xD4, 0x40, 0x42, 0xEA, 0x0B, 0x9F, 0xF8, + 0xFD, 0xB3, 0xF0, 0xEF, 0xF5, 0x82, 0x1B, 0xDB, 0x35, 0x9B, 0x16, 0x3A, 0xA2, 0xC0, 0xCF, 0x56, 0x55, 0xDC, 0xB8, 0xFB, + 0xF1, 0x61, 0x73, 0xD5, 0x89, 0x62, 0x25, 0xE1, 0xB7, 0xA0, 0x5C, 0x68, 0x6B, 0xCC, 0xF8, 0x94, 0x38, 0xF3, 0x36, 0x55, + 0x2F, 0xA2, 0x8A, 0xB6, 0x59, 0x00, 0x52, 0x6C, 0x6A, 0xE2, 0x2C, 0x31, 0x1A, 0x82, 0x79, 0x13, 0x0F, 0xF8, 0x00, 0x1D, + 0xB9, 0x79, 0x44, 0x24, 0xE9, 0xE5, 0x0E, 0x64, 0xA7, 0x47, 0xA0, 0xF2, 0xB7, 0xEB, 0x57, 0xB0, 0x85, 0x79, 0xFD, 0x11, + 0xDD, 0xAF, 0x87, 0x00, 0xBC, 0x87, 0xD5, 0x0D, 0xCE, 0x68, 0x19, 0xC1, 0x5B, 0xD9, 0xDB, 0xB4, 0xAE, 0x0B, 0xD2, 0x90, + 0x4A, 0xCB, 0x45, 0x18, 0x75, 0xA7, 0x14, 0x3C, 0x24, 0x81, 0xA1, 0xC2, 0xF4, 0xD2, 0xB2, 0x8C, 0xC1, 0xBD, 0x86, 0x8D, + 0xCD, 0x1A, 0xE2, 0xD3, 0x98, 0x73, 0x1D, 0x6E, 0x30, 0x03, 0x52, 0x28, 0x2E, 0x43, 0x1E, 0xAA, 0x2A, 0x02, 0x10, 0xE5, + 0x0B, 0xA9, 0xD2, 0xF6, 0x95, 0xEB, 0xE5, 0x9A, 0x36, 0xA9, 0xB2, 0xD6, 0x94, 0xAB, 0xA3, 0x8F, 0x84, 0xFC, 0xDB, 0x2F, + 0x7C, 0x7F, 0x82, 0xC9, 0xBB, 0xCE, 0xA1, 0x64, 0xDA, 0x39, 0xCE, 0x24, 0xA3, 0xC9, 0xA8, 0xC4, 0xFD, 0xA3, 0x60, 0x3B, + 0xCB, 0x61, 0x68, 0xEA, 0xBD, 0x06, 0xCD, 0xA0, 0xE7, 0x14, 0xF4, 0x67, 0x18, 0x7F, 0xBF, 0x95, 0x35, 0x8C, 0xE7, 0xEA, + 0x42, 0x50, 0x30, 0x5B, 0xAC, 0x8E, 0xF2, 0x4B, 0xE7, 0x9C, 0x34, 0x1A, 0x4B, 0x6F, 0xA9, 0x84, 0xE6, 0xE6, 0x1B, 0xC9, + 0x8F, 0xF3, 0x23, 0x2D, 0x61, 0x21, 0xF3, 0xB7, 0x31, 0x63, 0xCB, 0x56, 0x25, 0x63, 0x94, 0xA0, 0x0D, 0x87, 0x2B, 0x23, + 0xF2, 0x0F, 0x35, 0x08, 0xD8, 0x4D, 0x87, 0x04, 0x8E, 0xE4, 0x0E, 0x07, 0x67, 0x70, 0x02, 0x7B, 0x14, 0xF2, 0x35, 0x40, + 0xE6, 0xD8, 0x7B, 0x29, 0xF6, 0xF8, 0xA9, 0x17, 0xA7, 0x25, 0x6C, 0x97, 0xAB, 0x44, 0x5C, 0xF2, 0x70, 0x53, 0xB0, 0xB1, + 0xD4, 0x79, 0x35, 0xE1, 0xF6, 0x93, 0xA1, 0x14, 0x48, 0x91, 0xB8, 0x53, 0xE0, 0xDD, 0x41, 0xD5, 0x57, 0xF4, 0x1E, 0xF1, + 0x84, 0x23, 0x7D, 0x13, 0xEE, 0x35, 0x45, 0x31, 0xE0, 0x22, 0xB9, 0x55, 0x76, 0xFD, 0xFE, 0xFB, 0x20, 0xBC, 0xDE, 0x76, + 0xE2, 0x1B, 0xE1, 0x0D, 0x87, 0xB7, 0xCA, 0xCA, 0xD1, 0xE4, 0x1B, 0x44, 0xFC, 0xD4, 0xA3, 0x32, 0x04, 0x8E, 0xC5, 0x82, + 0xE7, 0xCA, 0x43, 0xC7, 0xD6, 0x54, 0x9C, 0xBC, 0x05, 0x26, 0x41, 0xA5, 0x92, 0xF4, 0x8C, 0x9C, 0x6B, 0xA0, 0xCB, 0xCA, + 0x51, 0xB7, 0xB6, 0x40, 0xD8, 0x9E, 0x57, 0x2D, 0xA7, 0x7A, 0x27, 0xF1, 0x75, 0xDF, 0xC5, 0xC7, 0xB1, 0x58, 0xF9, 0x8F, + 0x2A, 0x69, 0x66, 0x56, 0x14, 0x23, 0x4E, 0x28, 0x69, 0x09, 0xDE, 0xA8, 0xFF, 0x9C, 0xF1, 0x9E, 0x2B, 0x68, 0x75, 0x41, + 0x3B, 0xA3, 0x46, 0xBE, 0x8D, 0x58, 0x6E, 0xA0, 0x43, 0x0D, 0x36, 0x0F, 0x8F, 0xF6, 0xE5, 0xFD, 0x47, 0x45, 0x0D, 0x49, + 0xC8, 0x71, 0xDF, 0x4D, 0x7F, 0xF7, 0x3E, 0x1F, 0x8F, 0x9B, 0xBC, 0x45, 0x5A, 0xFB, 0x37, 0x48, 0x69, 0x76, 0xEC, 0xA5, + 0x87, 0x4F, 0xA6, 0x62, 0x93, 0xDE, 0x99, 0x89, 0xC3, 0x0A, 0xF2, 0xD5, 0x0B, 0x9D, 0x56, 0x9C, 0x1C, 0x90, 0xAE, 0x4F, + 0x7F, 0x86, 0x42, 0xA5, 0xFD, 0xF3, 0x7C, 0x85, 0xB5, 0x22, 0x4A, 0x9C, 0x84, 0x98, 0xA1, 0xD6, 0x9D, 0x20, 0x98, 0xB1, + 0x6C, 0x21, 0xC8, 0xAC, 0x34, 0xD6, 0x89, 0xE8, 0x5F, 0x61, 0x42, 0x5F, 0xE1, 0x0F, 0xD4, 0x4D, 0xBF, 0xB7, 0xEF, 0x06, + 0xEF, 0x9E, 0xC7, 0x01, 0x53, 0xF2, 0xFF, 0xE8, 0x4B, 0x40, 0x0E, 0xE2, 0x34, 0xAD, 0x1C, 0x33, 0x13, 0x08, 0x70, 0x1B, + 0xA4, 0x91, 0xFE, 0x62, 0xA2, 0x07, 0x70, 0x52, 0x6D, 0x31, 0x98, 0x8D, 0xF7, 0x03, 0x27, 0x6A, 0xD6, 0xC6, 0x03, 0xDC, + 0x02, 0x0A, 0xFF, 0x78, 0xA3, 0x0C, 0xA6, 0x19, 0x34, 0x33, 0x26, 0x85, 0xF4, 0xBE, 0x01, 0xA7, 0x20, 0x89, 0x71, 0xFD, + 0x52, 0x6C, 0x56, 0xD5, 0xF2, 0x78, 0x31, 0x93, 0xD7, 0x92, 0xEC, 0x3F, 0xD8, 0xFB, 0x57, 0xBB, 0xF3, 0xA7, 0x90, 0xA0, + 0x42, 0x42, 0xAF, 0xE0, 0x45, 0xFA, 0xF6, 0x58, 0x8E, 0x88, 0x6C, 0x2F, 0xB0, 0x64, 0x20, 0x54, 0xA2, 0xDA, 0x18, 0x64, + 0xDF, 0xC7, 0xFA, 0xDB, 0x75, 0x05, 0x11, 0x5A, 0x16, 0x89, 0xD9, 0x66, 0xA1, 0xC6, 0x41, 0xE1, 0xCD, 0xAE, 0xAE, 0xAE, + 0x62, 0xD1, 0x6E, 0x7D, 0x95, 0x57, 0x1E, 0xF5, 0xDF, 0x3B, 0x97, 0xA4, 0x98, 0x26, 0xF9, 0xEA, 0xA9, 0x82, 0x83, 0xEA, + 0x08, 0x67, 0xA9, 0xDE, 0x58, 0xB5, 0xEB, 0x6A, 0xF2, 0x29, 0x6A, 0x58, 0xEB, 0xD4, 0x5A, 0x38, 0x9B, 0x2A, 0x02, 0x3D, + 0xB7, 0x29, 0xEA, 0xFA, 0xF3, 0x28, 0x84, 0x59, 0x89, 0x05, 0x2B, 0xAC, 0xF3, 0xF3, 0xE9, 0xAD, 0x98, 0x60, 0x53, 0x2C, + 0x46, 0x26, 0x73, 0x3E, 0x74, 0x04, 0xCA, 0xBD, 0xC1, 0x3B, 0x9F, 0x3D, 0x9A, 0xFC, 0xA5, 0xE1, 0x54, 0xED, 0xB9, 0x6C, + 0x2E, 0x4E, 0x70, 0xC8, 0x45, 0x50, 0x6A, 0x50, 0xB9, 0xF1, 0x12, 0xA1, 0x1F, 0x2E, 0x42, 0x3A, 0xE9, 0x58, 0xBF, 0xCD, + 0x4C, 0x80, 0xF5, 0x5C, 0xC9, 0x4E, 0x6B, 0x52, 0x7F, 0x6B, 0x09, 0xA9, 0x08, 0x0A, 0x74, 0x65, 0x9E, 0xD4, 0x0B, 0x9F, + 0x17, 0xD3, 0xD1, 0x6A, 0xEE, 0x3B, 0xCD, 0xA9, 0x74, 0x00, 0x00, 0xD9, 0x88, 0xC0, 0xDF, 0x0B, 0x68, 0x4C, 0xD3, 0xDA, + 0x7A, 0x90, 0x83, 0xC6, 0x78, 0x9D, 0x4B, 0x97, 0x36, 0x58, 0x2C, 0x70, 0x97, 0x5F, 0x9C, 0xA0, 0xFF, 0x31, 0x29, 0x66, + 0xA4, 0xF3, 0x3A, 0xF6, 0xC6, 0x37, 0x64, 0x97, 0x02, 0xA1, 0xC6, 0xB6, 0x0D, 0x33, 0x5C, 0x9B, 0x47, 0x09, 0xDD, 0xA1, + 0x32, 0x3A, 0xA1, 0xC3, 0xA3, 0x8D, 0x39, 0x81, 0x11, 0x8D, 0x73, 0xE0, 0x4A, 0x5A, 0x85, 0xA2, 0x10, 0x5F, 0x65, 0x33, + 0xE8, 0x8E, 0x91, 0xCB, 0x50, 0xAC, 0xC0, 0xC5, 0x26, 0xCE, 0xEB, 0x29, 0x30, 0xCF, 0x8B, 0x80, 0x15, 0x22, 0x25, 0x02, + 0x56, 0x38, 0xDC, 0x17, 0x21, 0xE0, 0x07, 0x37, 0xB1, 0xC9, 0x5B, 0xB3, 0x3F, 0x79, 0x93, 0x66, 0x57, 0x88, 0x70, 0x45, + 0xF1, 0xA1, 0xD6, 0x39, 0x94, 0x76, 0xD5, 0x20, 0x58, 0x7A, 0xA1, 0x18, 0xB2, 0x34, 0x49, 0x96, 0x22, 0x19, 0xB7, 0xA7, + 0x10, 0x43, 0xDC, 0xB2, 0xA3, 0x73, 0xCF, 0xE0, 0x18, 0x8E, 0xAE, 0x81, 0xAD, 0x58, 0x65, 0xCB, 0xE6, 0x30, 0x2E, 0xF8, + 0x6C, 0x57, 0x3A, 0x29, 0xDB, 0x88, 0x3A, 0x65, 0x08, 0x62, 0x22, 0x5C, 0x9A, 0x78, 0xDE, 0xB5, 0x69, 0x5F, 0x57, 0xE8, + 0x4A, 0x69, 0xEF, 0x99, 0x8C, 0xC1, 0x03, 0x4A, 0x38, 0x1A, 0x87, 0x2B, 0x65, 0xD8, 0x60, 0xA1, 0x53, 0x3A, 0x9E, 0x68, + 0xA8, 0x0A, 0x63, 0xE2, 0x63, 0xE6, 0xB7, 0xB1, 0xDA, 0x71, 0x27, 0x4E, 0xB0, 0x6B, 0x46, 0x39, 0xE6, 0x3C, 0xCD, 0x21, + 0x32, 0x7C, 0x9A, 0xE8, 0xE3, 0x7D, 0x46, 0xEC, 0x7A, 0x7C, 0xF9, 0xFC, 0xA4, 0xB0, 0xB4, 0x2C, 0x33, 0x32, 0x20, 0x9C, + 0xE9, 0x55, 0xDE, 0xFC, 0x7B, 0x7D, 0x47, 0x0B, 0x29, 0x58, 0x0E, 0xED, 0x38, 0xC2, 0x57, 0x9B, 0x01, 0xF7, 0xD7, 0xED, + 0xFA, 0x7E, 0x87, 0x4A, 0x8A, 0xB2, 0xE9, 0x88, 0xEA, 0x7F, 0xAA, 0x1B, 0xAB, 0x50, 0xDF, 0xFD, 0xFB, 0x7F, 0xB0, 0x44, + 0xAE, 0x7B, 0xFA, 0x00, 0xB7, 0xC5, 0xF0, 0xFE, 0xFC, 0x81, 0x73, 0xE6, 0x0C, 0x55, 0xF7, 0x07, 0x82, 0x86, 0xF2, 0x15, + 0xB6, 0xC4, 0xC0, 0xB6, 0x12, 0xD6, 0x78, 0xFE, 0xBA, 0x3C, 0x27, 0x87, 0x8C, 0xF4, 0xFB, 0x47, 0x37, 0xE3, 0x68, 0x54, + 0x61, 0x42, 0x7A, 0x36, 0x83, 0x5F, 0x81, 0xB1, 0x5A, 0xDC, 0xF3, 0x55, 0x36, 0xE2, 0x60, 0x44, 0x60, 0xAD, 0xC1, 0x10, + 0x28, 0xEC, 0x00, 0x40, 0x43, 0x8B, 0xD8, 0xB8, 0xBA, 0xA9, 0x8F, 0x99, 0xC4, 0xC7, 0xCA, 0x84, 0xAB, 0xEB, 0xA8, 0x4A, + 0x0C, 0x8E, 0x65, 0xA6, 0x1B, 0xAA, 0xE8, 0xF0, 0x4E, 0x18, 0xE8, 0xF2, 0x5B, 0xA7, 0xF1, 0xC7, 0x99, 0x6F, 0x1E, 0x63, + 0x14, 0xAE, 0xF5, 0x93, 0xCE, 0xC9, 0x61, 0xE3, 0x86, 0x3B, 0xED, 0x57, 0xD4, 0x30, 0x89, 0x17, 0x82, 0x2A, 0x41, 0xA3, + 0x3C, 0xC8, 0x66, 0x6D, 0xF3, 0xE1, 0xCA, 0xA8, 0xA8, 0x0F, 0x62, 0xD7, 0x0A, 0xEF, 0x50, 0x22, 0x4D, 0xD8, 0x22, 0x0E, + 0x24, 0xEA, 0x3A, 0xAF, 0xE8, 0xC8, 0xA9, 0xEF, 0x74, 0x56, 0xF3, 0x42, 0xCA, 0xF8, 0xD8, 0x06, 0x4F, 0xA4, 0xC3, 0xBE, + 0x09, 0x8D, 0xA4, 0x7C, 0xF5, 0xA1, 0xF3, 0x07, 0x92, 0x88, 0x5F, 0xC7, 0x4D, 0xA7, 0xEB, 0x52, 0x26, 0xC7, 0x6B, 0xCB, + 0x75, 0xE9, 0xAB, 0xB9, 0xC4, 0x76, 0xA1, 0x3D, 0x1F, 0xCF, 0x95, 0x4B, 0x02, 0xCE, 0x9A, 0x6A, 0xC7, 0x51, 0x12, 0x2B, + 0xB7, 0xC1, 0x51, 0xD0, 0xFF, 0x53, 0xA7, 0x2F, 0x09, 0x1D, 0xEA, 0xA2, 0x39, 0xED, 0x21, 0xE9, 0x34, 0xC4, 0xC8, 0x38, + 0x71, 0x81, 0xA8, 0x60, 0xAA, 0xCC, 0xCC, 0xA2, 0xEE, 0x55, 0x79, 0x6A, 0x6D, 0x8F, 0x2C, 0x6E, 0xDA, 0x16, 0x27, 0x3B, + 0x83, 0x78, 0x20, 0xBC, 0x46, 0x52, 0xCE, 0xA3, 0x7B, 0xB5, 0xA1, 0x77, 0x01, 0xF4, 0x13, 0x5A, 0xD4, 0xEA, 0xC7, 0xC6, + 0x78, 0x4D, 0xF4, 0xAF, 0x60, 0xD6, 0x0C, 0x55, 0x31, 0xEB, 0x72, 0xE1, 0x15, 0xDE, 0x57, 0xB2, 0xB8, 0x0C, 0xE0, 0xB6, + 0x2C, 0x5E, 0xBD, 0xD0, 0x9E, 0xE9, 0xE5, 0x42, 0x9B, 0x89, 0xC2, 0x78, 0x41, 0x24, 0x19, 0xF4, 0xE2, 0xA2, 0x34, 0xC1, + 0x1F, 0x1A, 0x2C, 0xE0, 0x9D, 0xDC, 0x4A, 0x68, 0x44, 0x65, 0x63, 0x72, 0x65, 0x78, 0x2D, 0xC7, 0x75, 0xEC, 0xAB, 0xB2, + 0xA6, 0x8B, 0x2D, 0xE6, 0x7B, 0x78, 0x9C, 0xCC, 0x42, 0x29, 0xF4, 0xE6, 0x76, 0xF4, 0x0D, 0xF6, 0x14, 0x15, 0x62, 0x10, + 0x7A, 0xAB, 0xC3, 0x69, 0x98, 0x94, 0xFC, 0xF6, 0x77, 0xF5, 0x5B, 0x02, 0xC7, 0x92, 0x6B, 0x8C, 0xFB, 0x0A, 0x99, 0x78, + 0xE7, 0x56, 0xF5, 0xE7, 0xF6, 0xF6, 0xD5, 0x94, 0x6D, 0xDE, 0x63, 0x08, 0x4A, 0x13, 0xD1, 0x88, 0x39, 0x28, 0xFD, 0xF7, + 0xF7, 0xF7, 0xB6, 0x0E, 0x62, 0x85, 0x5D, 0xAA, 0xB3, 0xBA, 0xFE, 0xAA, 0x5F, 0x73, 0x88, 0x92, 0x1D, 0xFC, 0x3D, 0xFA, + 0x56, 0x90, 0xA6, 0xA8, 0x9C, 0x16, 0x64, 0x45, 0xCA, 0x54, 0xA8, 0xDC, 0x82, 0x54, 0x79, 0xA6, 0x66, 0x31, 0x10, 0x8E, + 0x31, 0xBC, 0x6D, 0x56, 0x4B, 0xCA, 0xD6, 0x8B, 0x15, 0xAB, 0x74, 0xB8, 0x65, 0xE1, 0x38, 0x8C, 0x62, 0xB8, 0x66, 0x6B, + 0x4A, 0xC0, 0xAA, 0x1A, 0x0A, 0xBA, 0x24, 0xD9, 0x4B, 0x93, 0x2F, 0x2C, 0xDE, 0x0D, 0xE6, 0xF5, 0xEA, 0x08, 0xF6, 0xEE, + 0x7E, 0xFC, 0x05, 0xFE, 0xAD, 0xD5, 0x15, 0xFA, 0xD6, 0x74, 0xBB, 0x81, 0xCC, 0xB8, 0xFE, 0xFE, 0x7F, 0xFD, 0x55, 0x30, + 0xA8, 0xC4, 0x18, 0xBD, 0xD4, 0xB1, 0xD3, 0x84, 0xCF, 0x1E, 0xF7, 0xEF, 0xFE, 0xFE, 0xA0, 0x2B, 0xA3, 0x90, 0xC9, 0xBB, + 0x1C, 0x3A, 0x5F, 0x0C, 0xCB, 0x52, 0xFF, 0xFF, 0x58, 0x62, 0xA8, 0xB5, 0xE1, 0x1B, 0x0B, 0x66, 0xD1, 0x42, 0x5A, 0xC2, + 0x73, 0x98, 0xC9, 0x27, 0xF5, 0xBF, 0xE0, 0x94, 0x86, 0x51, 0x4C, 0xB3, 0x97, 0x73, 0x9F, 0x20, 0x72, 0x17, 0xC1, 0xF0, + 0xF4, 0x97, 0xA1, 0xF7, 0x05, 0xA3, 0x45, 0x80, 0xD3, 0x02, 0xE9, 0x43, 0x01, 0xC8, 0x90, 0x43, 0x2F, 0x0C, 0x50, 0x8A, + 0x26, 0x05, 0xE9, 0x17, 0xCA, 0x2E, 0xE1, 0x57, 0x36, 0xCA, 0xD8, 0x53, 0x07, 0x69, 0x94, 0xAE, 0x31, 0x20, 0x09, 0x37, + 0x09, 0x80, 0x30, 0x62, 0x67, 0x49, 0x9D, 0x8E, 0xB3, 0x5F, 0xE4, 0xD5, 0xD6, 0x67, 0xB0, 0x99, 0xF8, 0xBF, 0x60, 0x56, + 0xAA, 0x03, 0xE0, 0xFD, 0xFC, 0x63, 0x81, 0x2C, 0x48, 0xDA, 0x08, 0xA7, 0x72, 0x82, 0x85, 0xE7, 0xD8, 0x23, 0xF0, 0x82, + 0x63, 0xC7, 0x20, 0xBA, 0x01, 0x6B, 0xA9, 0x57, 0xF8, 0x2A, 0x1D, 0x99, 0x5F, 0x8C, 0xFD, 0x69, 0x72, 0x61, 0x2A, 0x66, + 0xAB, 0x6D, 0xC8, 0x11, 0x2B, 0x2D, 0x16, 0x48, 0x0C, 0x95, 0x97, 0x53, 0x38, 0x6A, 0x95, 0xF5, 0x1E, 0xB2, 0xD0, 0x0C, + 0xBE, 0x2F, 0x18, 0xD0, 0xDF, 0xB4, 0xDB, 0xDA, 0x6A, 0x43, 0x7B, 0xF5, 0x05, 0xF1, 0x7B, 0x6B, 0xBB, 0x4A, 0xFF, 0xBA, + 0xF4, 0x42, 0x92, 0xCB, 0x39, 0xB9, 0xF4, 0x9D, 0xDE, 0x24, 0xAB, 0xDC, 0x38, 0x30, 0xE3, 0xC5, 0x44, 0xB0, 0x23, 0xC3, + 0xC9, 0x26, 0x0C, 0xCC, 0x37, 0xA3, 0xE8, 0xC9, 0x59, 0xCC, 0x56, 0x80, 0x1C, 0x01, 0x71, 0x72, 0x5C, 0x15, 0x2C, 0x06, + 0x86, 0x6F, 0x03, 0x9B, 0xD9, 0xFD, 0xFF, 0x6C, 0x6B, 0x6F, 0xE2, 0x8D, 0xF8, 0xED, 0x1A, 0x88, 0x8C, 0x77, 0xD3, 0x2F, + 0xFC, 0x83, 0xAC, 0x09, 0xC6, 0x55, 0x65, 0xEF, 0x52, 0x9E, 0xE0, 0xDC, 0x18, 0x30, 0x83, 0x60, 0xA8, 0xCD, 0x5E, 0x0A, + 0xF6, 0xEE, 0xE9, 0x82, 0x59, 0xBB, 0x5D, 0xA5, 0x43, 0x70, 0x7C, 0x06, 0xB0, 0xE6, 0xCB, 0xD0, 0x5F, 0xA0, 0x95, 0xC2, + 0x8B, 0x76, 0x86, 0x68, 0xA1, 0xAA, 0x8A, 0x7D, 0xB5, 0x73, 0x60, 0x32, 0xE1, 0x5B, 0x28, 0xCF, 0xD2, 0x6A, 0xFD, 0x7D, + 0x28, 0xE9, 0xBD, 0x55, 0xEC, 0x3B, 0x2F, 0x5A, 0xE6, 0x88, 0x3D, 0xAD, 0x01, 0x7D, 0x04, 0x7C, 0xE1, 0x51, 0x10, 0xFF, + 0x82, 0x19, 0x25, 0x80, 0x40, 0xF2, 0x96, 0xD3, 0x46, 0x63, 0x2D, 0x2B, 0xDD, 0x12, 0x1B, 0x8C, 0x45, 0x30, 0x44, 0x69, + 0x3A, 0xF0, 0x77, 0x4A, 0xD3, 0x7F, 0xF8, 0xAF, 0x80, 0xCE, 0xE8, 0xEC, 0x35, 0xB5, 0xF0, 0x63, 0x5E, 0x5F, 0xD9, 0x76, + 0xA7, 0x22, 0xED, 0xD8, 0x57, 0x19, 0x05, 0x14, 0xB4, 0x30, 0xCC, 0x95, 0x0B, 0x0F, 0x55, 0xC2, 0x53, 0x7D, 0xEE, 0x2C, + 0x3E, 0x8C, 0x50, 0x57, 0x33, 0x9C, 0xD9, 0xE2, 0xDE, 0x9E, 0xDF, 0x17, 0x5F, 0xFC, 0x4B, 0x63, 0x5F, 0x3C, 0xBC, 0x6A, + 0x28, 0xB3, 0x2E, 0x5B, 0x33, 0x36, 0x2E, 0x43, 0xFA, 0x54, 0x34, 0x63, 0x2F, 0xC3, 0x69, 0xFE, 0x7A, 0xC9, 0x7E, 0xBA, + 0x02, 0x54, 0x23, 0x5E, 0xFB, 0x35, 0xD8, 0xD1, 0x97, 0x90, 0xDF, 0x6B, 0x3A, 0x3E, 0x75, 0x39, 0xE9, 0xEA, 0x39, 0xC3, + 0x5B, 0x1F, 0x73, 0x1D, 0xDC, 0x79, 0x97, 0x8C, 0x82, 0x71, 0x35, 0x69, 0xB5, 0x58, 0x1A, 0xC3, 0x5A, 0x1E, 0x66, 0x31, + 0xE1, 0x67, 0xFE, 0x9E, 0x34, 0xB6, 0x70, 0x85, 0x56, 0xF1, 0xDE, 0x0E, 0xF8, 0x78, 0x95, 0x86, 0x54, 0xFC, 0xF0, 0x04, + 0x72, 0x47, 0x56, 0xFD, 0xA3, 0x04, 0x1A, 0x79, 0x38, 0x8F, 0x57, 0x4D, 0xB1, 0x21, 0x41, 0x48, 0x3C, 0x3E, 0xCE, 0xAE, + 0x20, 0x27, 0xD8, 0x8F, 0x05, 0x1C, 0x14, 0xDB, 0xD0, 0xF8, 0xD7, 0xD0, 0x34, 0x92, 0xCA, 0x8A, 0xD7, 0xFE, 0x1B, 0x7B, + 0xBF, 0x79, 0x1A, 0xEA, 0x84, 0x4F, 0x80, 0xE0, 0xF5, 0xBB, 0xF2, 0xCF, 0x36, 0x7B, 0x4F, 0x61, 0x67, 0x58, 0x71, 0x31, + 0xA2, 0x2E, 0xBB, 0xF4, 0x97, 0xED, 0xE3, 0x74, 0x3A, 0x3B, 0x5B, 0xF6, 0x1D, 0x3C, 0x20, 0xF5, 0x6F, 0x88, 0x44, 0xE1, + 0x16, 0x8E, 0xCE, 0xA7, 0x93, 0xED, 0x09, 0xB8, 0xC6, 0xAF, 0xE5, 0x55, 0xD3, 0x85, 0xA6, 0xF5, 0x17, 0x2F, 0xE4, 0x8B, + 0xBE, 0x3C, 0x41, 0x3F, 0x28, 0xAC, 0x9F, 0xC0, 0x83, 0x35, 0x58, 0xB9, 0xFF, 0xFE, 0xE9, 0x91, 0x73, 0x49, 0x01, 0xE2, + 0x6B, 0x71, 0x10, 0x21, 0x3B, 0x04, 0xD0, 0x06, 0x37, 0xAA, 0xE3, 0x10, 0xB0, 0xA7, 0x80, 0x51, 0x34, 0xED, 0xDA, 0xA1, + 0x2A, 0x7B, 0x4D, 0xD8, 0x95, 0x07, 0x0F, 0x0E, 0x44, 0xC2, 0x91, 0x79, 0x4A, 0x6B, 0x6B, 0xAC, 0x66, 0xE4, 0x32, 0x55, + 0xE8, 0x4F, 0xBD, 0xA3, 0x99, 0x68, 0x81, 0xF5, 0x03, 0x33, 0x8E, 0xCE, 0xAF, 0x8E, 0xB0, 0x7D, 0x47, 0xA7, 0xF2, 0xF6, + 0xE7, 0x13, 0xEB, 0x2D, 0xF9, 0x37, 0x6B, 0x5C, 0x1D, 0xC5, 0x25, 0xF6, 0x95, 0x24, 0xBD, 0x48, 0xB6, 0x8B, 0xF8, 0xBA, + 0x60, 0x46, 0x8B, 0x07, 0x2F, 0xC6, 0x99, 0xF0, 0x9A, 0x8B, 0x9F, 0xD6, 0xD7, 0xB1, 0xB2, 0x49, 0x5E, 0x86, 0xAF, 0xF3, + 0x8D, 0xC4, 0x53, 0x17, 0xFE, 0xA3, 0xF0, 0xD8, 0xBA, 0x17, 0xE2, 0xFE, 0x78, 0x74, 0x99, 0xA2, 0x5F, 0xC1, 0xBD, 0x28, + 0x18, 0xD6, 0xE8, 0x82, 0x12, 0x61, 0xCA, 0x8E, 0x5A, 0x89, 0xAA, 0x37, 0xAF, 0x51, 0x8A, 0x5D, 0x27, 0xA2, 0x32, 0x6E, + 0x7C, 0x1F, 0x59, 0x60, 0xFC, 0x88, 0x18, 0x43, 0x2B, 0x31, 0xD2, 0x30, 0x7D, 0x2E, 0x6E, 0x8D, 0x43, 0x38, 0xCB, 0x8F, + 0xCE, 0xE8, 0xC7, 0xDE, 0x5A, 0xED, 0xB4, 0xBE, 0xEC, 0xAF, 0xC3, 0x93, 0x93, 0x80, 0xA1, 0x97, 0x7C, 0xE9, 0xE4, 0x5A, + 0xB8, 0x96, 0x64, 0xEB, 0x85, 0xAB, 0x0C, 0xA7, 0x0F, 0x6A, 0x0B, 0x44, 0xF6, 0x9C, 0xE8, 0x42, 0x5B, 0xF3, 0xF6, 0xD4, + 0x92, 0xB7, 0x04, 0xE0, 0x6B, 0xB3, 0x83, 0x54, 0xF7, 0x9D, 0x05, 0xDA, 0x05, 0xF0, 0xAE, 0xF5, 0x13, 0xA2, 0x77, 0x21, + 0x64, 0xD8, 0xAA, 0xDD, 0x57, 0x97, 0xCD, 0x0A, 0x27, 0x97, 0x8D, 0x08, 0x14, 0x3F, 0x77, 0xB6, 0x1A, 0xD5, 0x73, 0xD9, + 0x56, 0x96, 0xB9, 0x5E, 0x20, 0xAE, 0xAF, 0x54, 0xC7, 0x19, 0xEE, 0x72, 0x8D, 0xA5, 0xD4, 0xAF, 0xD7, 0x2B, 0x54, 0x02, + 0x79, 0x3A, 0x6D, 0x54, 0xBF, 0xE4, 0x25, 0xE2, 0xC0, 0x78, 0xF2, 0x72, 0x06, 0xC5, 0x18, 0x41, 0x26, 0xDF, 0x28, 0x55, + 0xF6, 0xBE, 0x53, 0x97, 0x45, 0x52, 0x95, 0xE5, 0xE7, 0xED, 0xF4, 0xF4, 0x06, 0x1D, 0xD5, 0xB7, 0xB3, 0x97, 0xE4, 0xC2, + 0xDA, 0x78, 0x9D, 0xF5, 0xEA, 0xFA, 0x2D, 0xE8, 0x1F, 0x8E, 0xEC, 0x93, 0x1D, 0x28, 0xA9, 0x6C, 0xE2, 0xC3, 0x0B, 0x4C, + 0xFE, 0xFC, 0x16, 0x4A, 0x71, 0x36, 0x96, 0x77, 0x64, 0xD6, 0x38, 0xC9, 0x36, 0xB5, 0xF4, 0xA3, 0x96, 0x88, 0xDF, 0x09, + 0x2C, 0x62, 0x9F, 0x5F, 0x1F, 0x1B, 0x54, 0x4D, 0x12, 0xBA, 0x87, 0xCD, 0x03, 0x76, 0xBA, 0x8B, 0x52, 0x17, 0x95, 0x3A, + 0xA7, 0xD4, 0xFB, 0x5D, 0x6F, 0xDF, 0xAD, 0xAF, 0x42, 0x76, 0xA1, 0x39, 0x13, 0xF9, 0xE8, 0xCC, 0xD9, 0x11, 0x3B, 0x02, + 0x20, 0x93, 0x0D, 0x6C, 0xFE, 0xA4, 0x73, 0xB8, 0xEE, 0x17, 0x4C, 0x39, 0x8E, 0x1C, 0x63, 0x09, 0x78, 0x9F, 0xFB, 0x7C, + 0xFF, 0x27, 0x5F, 0x1B, 0xF2, 0x31, 0x2E, 0x25, 0x5F, 0x85, 0x2E, 0x77, 0x4B, 0x7F, 0xAE, 0xA7, 0xF8, 0x67, 0xE8, 0x33, + 0xF9, 0xD0, 0xD7, 0x56, 0x10, 0x12, 0x66, 0xFB, 0xE9, 0xB5, 0xC7, 0x7D, 0x01, 0x60, 0x78, 0x82, 0x80, 0x29, 0x38, 0x24, + 0x1A, 0x30, 0xEA, 0x53, 0x78, 0x2C, 0x50, 0x31, 0xFD, 0x22, 0x70, 0x56, 0xFD, 0x4D, 0xB2, 0xEF, 0x91, 0xE1, 0x26, 0x1C, + 0x8B, 0xA8, 0x98, 0xB6, 0x85, 0x3A, 0x39, 0x83, 0x01, 0x32, 0xFF, 0x50, 0x2C, 0x1B, 0x77, 0x54, 0xC1, 0x20, 0xD0, 0x25, + 0xD6, 0x7A, 0xCC, 0x95, 0x98, 0x2C, 0xF7, 0x40, 0x2D, 0x1A, 0x11, 0x28, 0x24, 0xBC, 0xA1, 0x72, 0x1B, 0x8A, 0x60, 0x5D, + 0x31, 0x50, 0x5B, 0xA4, 0x54, 0xD9, 0x28, 0xE2, 0xCF, 0x1D, 0x0E, 0x94, 0x6E, 0x6B, 0xC0, 0x32, 0x8E, 0xF3, 0xD7, 0xD6, + 0x93, 0xB4, 0x78, 0x9E, 0xE2, 0xC9, 0x92, 0x23, 0x12, 0x75, 0xFB, 0xBE, 0x00, 0xD2, 0xB3, 0x4F, 0x96, 0x89, 0x29, 0x46, + 0x61, 0x40, 0xB1, 0x05, 0xAE, 0x6B, 0x41, 0x54, 0x7E, 0x85, 0xF1, 0xE7, 0x5F, 0x17, 0x13, 0x6C, 0x41, 0x2B, 0xA1, 0x17, + 0x90, 0x78, 0x38, 0xFB, 0x39, 0x13, 0xB5, 0x78, 0xE4, 0xE1, 0x2C, 0x01, 0xC7, 0xBE, 0xCB, 0xB1, 0xFF, 0x6E, 0x6A, 0x1A, + 0x4E, 0x04, 0x41, 0xCF, 0x9B, 0x2A, 0xFD, 0x78, 0x4D, 0x05, 0xDE, 0x1B, 0xB0, 0x58, 0x81, 0xEF, 0x63, 0x23, 0x43, 0xD0, + 0xDF, 0x68, 0x5B, 0x38, 0x21, 0x1B, 0xB3, 0x8D, 0xDE, 0xF3, 0x41, 0x04, 0xE9, 0xAB, 0x0F, 0xED, 0x91, 0x24, 0x1F, 0x99, + 0x9D, 0x8B, 0xE3, 0x1A, 0x30, 0x3A, 0x3A, 0x3A, 0x88, 0xD8, 0x9C, 0x11, 0x1E, 0xA7, 0x49, 0x8A, 0xC8, 0x48, 0xAA, 0xEE, + 0x34, 0x0F, 0xB2, 0x50, 0xAC, 0x16, 0xB2, 0x9A, 0xE7, 0x6C, 0xC8, 0x9A, 0xAA, 0x4B, 0xBA, 0x38, 0x7A, 0xE0, 0x64, 0xAB, + 0xB9, 0x6C, 0xE6, 0xAF, 0x79, 0x4B, 0xAE, 0x0B, 0x48, 0xC2, 0xEB, 0xBD, 0x05, 0x61, 0x0D, 0xBF, 0x9B, 0x40, 0xAB, 0x1D, + 0x95, 0x22, 0xF3, 0x6C, 0x68, 0x49, 0xA3, 0x5A, 0x78, 0x69, 0x3E, 0x62, 0xA5, 0x45, 0x5F, 0x66, 0xB2, 0x34, 0x8A, 0xC2, + 0x9B, 0x8D, 0x6E, 0xE2, 0x50, 0x3C, 0x6C, 0x92, 0x5A, 0x1C, 0x0B, 0x7C, 0x37, 0x7E, 0x1D, 0x56, 0x52, 0x43, 0xA4, 0x5C, + 0x4E, 0xBE, 0x65, 0x21, 0xAC, 0x1D, 0x5E, 0xE7, 0x71, 0xB8, 0x4C, 0xB8, 0x47, 0xEF, 0x01, 0x27, 0x70, 0xB9, 0xD9, 0x17, + 0xF5, 0x10, 0x35, 0xD2, 0x73, 0x93, 0x23, 0x98, 0x46, 0x48, 0x27, 0xF2, 0x33, 0x63, 0xC3, 0xA6, 0xDD, 0xB9, 0xBC, 0x46, + 0x10, 0x56, 0x7E, 0xD4, 0xC3, 0xDE, 0xEC, 0x34, 0xAD, 0x7B, 0xD9, 0xA3, 0x1F, 0xB4, 0x9C, 0xCC, 0x50, 0x55, 0x24, 0xE1, + 0x83, 0x53, 0x96, 0x1B, 0xD0, 0x78, 0xD0, 0x86, 0x7C, 0x1C, 0x9F, 0xD0, 0x11, 0x30, 0xD2, 0x81, 0xF2, 0xFD, 0xB5, 0x50, + 0xDC, 0x7B, 0x75, 0xE1, 0xCF, 0x08, 0xB5, 0x57, 0xB6, 0xCD, 0x77, 0xC0, 0x40, 0x51, 0xD7, 0xF4, 0x50, 0x7A, 0x85, 0xC5, + 0xAA, 0x1C, 0xCE, 0x89, 0x5B, 0x98, 0x53, 0xDB, 0x5C, 0x17, 0xDE, 0xA8, 0x1F, 0x79, 0x6E, 0x9A, 0x5D, 0x14, 0xB6, 0x4C, + 0x65, 0x98, 0x87, 0xF3, 0x6F, 0xAA, 0xC7, 0x45, 0x9E, 0xB4, 0x90, 0xEB, 0x4B, 0xE5, 0x7F, 0x0F, 0x38, 0xE1, 0xD7, 0x69, + 0xE8, 0x18, 0xF7, 0xAF, 0x97, 0x77, 0x90, 0x79, 0xF1, 0x16, 0xB7, 0xAC, 0x18, 0x20, 0xDE, 0x3D, 0xEE, 0xA2, 0x33, 0x2F, + 0xED, 0x71, 0xFE, 0x8F, 0x24, 0xB3, 0xFE, 0x9C, 0x32, 0x33, 0x7C, 0xD9, 0xCB, 0x5A, 0xDC, 0xE8, 0xD9, 0x87, 0x46, 0xCC, + 0x48, 0x22, 0xC4, 0x9C, 0x98, 0x3B, 0x74, 0xCC, 0xCA, 0xA2, 0xBE, 0x49, 0x1B, 0xF0, 0x52, 0x8E, 0x68, 0xFE, 0xA7, 0x6D, + 0x06, 0x33, 0xFB, 0x80, 0x49, 0x58, 0x2E, 0x69, 0xA1, 0xB6, 0x59, 0xF0, 0x40, 0x2E, 0x9F, 0xCC, 0x1A, 0xB7, 0x15, 0xE4, + 0x69, 0x7B, 0xA7, 0xDA, 0x98, 0x80, 0x79, 0x9A, 0xA3, 0xCD, 0xF0, 0x1A, 0x37, 0xA6, 0x60, 0x23, 0x48, 0xC3, 0xC8, 0x06, + 0x5E, 0x80, 0x12, 0xFA, 0x0F, 0xCE, 0x6C, 0x93, 0x56, 0xC1, 0x26, 0x50, 0xAE, 0xF0, 0xF1, 0x94, 0xB4, 0x1E, 0xDE, 0xEB, + 0x80, 0xCD, 0x81, 0xFF, 0x35, 0x2E, 0x77, 0x3B, 0x46, 0xC6, 0x8F, 0x0E, 0x77, 0xA0, 0x96, 0xE2, 0x26, 0x70, 0xF0, 0x9B, + 0x32, 0xAE, 0x8D, 0x51, 0x2E, 0x92, 0x79, 0xEA, 0xF3, 0x6E, 0x00, 0x5C, 0x70, 0x8B, 0xAA, 0xBD, 0xB5, 0xA9, 0x5A, 0x56, + 0xE7, 0x4E, 0x78, 0xBA, 0x16, 0xEB, 0x31, 0x63, 0xA2, 0x3A, 0xE7, 0x86, 0xA8, 0xAA, 0x32, 0x6F, 0x2C, 0xCA, 0x80, 0xF4, + 0x52, 0xBE, 0xBA, 0x01, 0xF9, 0x0C, 0xAB, 0xA8, 0x90, 0x3F, 0x09, 0x03, 0xDA, 0x4A, 0x45, 0x05, 0x97, 0xA6, 0xB4, 0xC5, + 0x81, 0x5D, 0x89, 0xF7, 0x95, 0x2C, 0x7F, 0x41, 0x45, 0x8B, 0xA3, 0x76, 0x74, 0xE1, 0x10, 0xF5, 0xF8, 0x87, 0xE8, 0xB3, + 0x2F, 0x69, 0x9A, 0xBB, 0x33, 0x41, 0xEB, 0xD3, 0xBB, 0xF3, 0x22, 0xAD, 0x6E, 0xA9, 0x2E, 0x2C, 0x76, 0xA6, 0x84, 0xB8, + 0xCD, 0xD0, 0xE3, 0xCE, 0xBA, 0xF2, 0xE3, 0xD3, 0xC8, 0x8C, 0x5B, 0x69, 0xF7, 0xA5, 0xE8, 0x2B, 0xCA, 0x20, 0x6D, 0xD9, + 0xCC, 0x25, 0x53, 0x99, 0x8C, 0xFC, 0xAD, 0x0D, 0x1F, 0x7F, 0x03, 0xC5, 0x4F, 0xCF, 0xE5, 0xC9, 0xEE, 0x30, 0x1E, 0xB6, + 0x8F, 0x77, 0x65, 0xAC, 0x9C, 0xAF, 0xF4, 0x88, 0xCC, 0x80, 0x7A, 0x87, 0xFD, 0xEA, 0xEA, 0xDE, 0x58, 0xA2, 0xE0, 0x4B, + 0xBC, 0xAB, 0x30, 0x98, 0xAE, 0xCB, 0x9A, 0x3A, 0x28, 0x6D, 0xB0, 0xA6, 0x9E, 0x35, 0x52, 0x2D, 0xDD, 0xA1, 0xF5, 0x09, + 0x4C, 0xA2, 0x7B, 0x92, 0x3F, 0xE1, 0x51, 0xA8, 0xB3, 0x94, 0xBB, 0xCE, 0xFC, 0x8F, 0x51, 0x4A, 0x6C, 0xC9, 0x83, 0xFD, + 0xDA, 0xEB, 0xE0, 0x04, 0x36, 0x93, 0xB2, 0x60, 0xB6, 0xB4, 0x6D, 0xBF, 0xC1, 0x6F, 0x34, 0x52, 0x15, 0x2B, 0xE8, 0x17, + 0xA3, 0x81, 0xFF, 0x74, 0x94, 0xDD, 0x36, 0xB0, 0x9A, 0xD7, 0xF1, 0xC4, 0x8E, 0xB3, 0x64, 0x97, 0x05, 0xFE, 0x85, 0xE5, + 0x36, 0x66, 0x85, 0x2A, 0x05, 0xB1, 0x99, 0x5A, 0xD6, 0x87, 0x4D, 0x91, 0x83, 0x9E, 0xCF, 0x9B, 0xB6, 0xD3, 0x9E, 0x08, + 0x44, 0x0C, 0x76, 0x54, 0xF3, 0x4A, 0xA4, 0xAF, 0xD5, 0x16, 0xE5, 0x24, 0x9A, 0x3F, 0x84, 0x00, 0xCA, 0xDB, 0x8C, 0xC1, + 0x15, 0x14, 0x34, 0xC6, 0xA5, 0x41, 0x69, 0xB4, 0x74, 0xBA, 0xC8, 0x10, 0xCB, 0xDA, 0x84, 0x74, 0x55, 0xB4, 0x1D, 0x47, + 0x9B, 0x09, 0x62, 0x25, 0x34, 0xB5, 0xCA, 0xB1, 0xA5, 0x26, 0x8D, 0xC0, 0x95, 0x09, 0xBE, 0xB1, 0xE7, 0x98, 0x95, 0x55, + 0x95, 0x95, 0xD5, 0xE3, 0x8C, 0x6E, 0xC7, 0x15, 0x75, 0xFF, 0x58, 0xA3, 0x80, 0x95, 0xFC, 0x71, 0x9F, 0x63, 0x1C, 0x0F, + 0x42, 0x52, 0x54, 0x46, 0x6E, 0xB5, 0xF7, 0xF8, 0xC6, 0x70, 0x4C, 0x72, 0x3D, 0x34, 0xC3, 0x85, 0x08, 0x9B, 0x12, 0x2D, + 0x10, 0xF3, 0x59, 0xA7, 0x2E, 0x9E, 0x53, 0x72, 0xD9, 0xC1, 0x1F, 0xF6, 0xAD, 0xD9, 0xD7, 0xB1, 0xF9, 0xF5, 0x9B, 0xF9, + 0x9E, 0xCF, 0xD0, 0x1B, 0xFA, 0x39, 0xF0, 0xF7, 0xDE, 0x09, 0xB9, 0xCC, 0x90, 0xF4, 0x60, 0xE7, 0xAE, 0xE0, 0xBC, 0x57, + 0x38, 0xC5, 0x53, 0x98, 0x85, 0x24, 0xFF, 0xFE, 0xDD, 0x71, 0x75, 0x5B, 0xCE, 0x9B, 0xD4, 0x3C, 0xBD, 0xF5, 0x5E, 0xC2, + 0xCE, 0x22, 0xC4, 0x01, 0x7B, 0x07, 0x07, 0x94, 0x4F, 0xDC, 0xC9, 0x4D, 0xBB, 0x74, 0x2E, 0x0E, 0x09, 0xD8, 0x08, 0x6B, + 0xA1, 0xBD, 0x47, 0xA0, 0x0C, 0xFA, 0x26, 0x3D, 0x3D, 0xF7, 0x05, 0x05, 0x43, 0xD2, 0x2C, 0xFF, 0xFF, 0xFF, 0xDB, 0x5E, + 0x7F, 0xE7, 0x3F, 0x54, 0x31, 0x6F, 0xF4, 0x7F, 0xE7, 0x50, 0xAE, 0xE8, 0xF7, 0x95, 0xC8, 0xCC, 0xAA, 0x8C, 0xA2, 0xC4, + 0x4D, 0xA1, 0x41, 0xB3, 0xA0, 0x0E, 0x51, 0xCC, 0x51, 0x23, 0xDC, 0x0C, 0x61, 0xBD, 0xE1, 0x07, 0x06, 0x2F, 0xAE, 0xC7, + 0x39, 0xBD, 0xDC, 0xD9, 0xD0, 0xD7, 0x69, 0x52, 0x94, 0x0C, 0xE9, 0x57, 0x8D, 0x2C, 0x18, 0x4E, 0x66, 0x45, 0x9D, 0x76, + 0x2C, 0xC2, 0x38, 0x67, 0xA1, 0x02, 0x3D, 0x2B, 0x9F, 0x82, 0x30, 0x24, 0x1A, 0x06, 0xAF, 0x3E, 0xAF, 0xF8, 0x28, 0x14, + 0x36, 0x88, 0x5F, 0x84, 0x1B, 0xDA, 0x98, 0xA9, 0x06, 0x43, 0xA6, 0x72, 0xB2, 0xE6, 0x49, 0x66, 0xC2, 0x09, 0x5B, 0x85, + 0xE6, 0x8B, 0xCC, 0xC6, 0xBD, 0xCF, 0x56, 0x95, 0x89, 0xF7, 0x31, 0xD3, 0x8A, 0x43, 0x76, 0x45, 0x24, 0xAC, 0xD1, 0xE4, + 0x62, 0xB8, 0x7A, 0x86, 0x5F, 0xDA, 0xAA, 0xAD, 0x3B, 0x2F, 0xE2, 0x0E, 0x8E, 0x25, 0x32, 0x1A, 0xE9, 0x41, 0xAA, 0xD3, + 0xAD, 0x0B, 0x72, 0x9A, 0x88, 0x8B, 0xA2, 0x04, 0xBA, 0x2F, 0x3A, 0x29, 0xC4, 0x2A, 0xE4, 0x21, 0xAC, 0xEA, 0xFB, 0x8B, + 0x09, 0x68, 0xC9, 0x10, 0xD8, 0x2C, 0xD3, 0xAD, 0xF5, 0x04, 0x68, 0x52, 0xB8, 0x63, 0x73, 0x9B, 0x09, 0xD3, 0xAB, 0x92, + 0x38, 0xA7, 0xB0, 0x9C, 0x1C, 0x55, 0xAF, 0xCE, 0x8D, 0x2A, 0x7A, 0x18, 0x0E, 0x03, 0xA2, 0x61, 0x1C, 0xB5, 0x78, 0xED, + 0x44, 0xC6, 0xAA, 0x61, 0xDA, 0x7B, 0x4E, 0xBA, 0x89, 0x25, 0xD8, 0xDE, 0x1D, 0xB4, 0x3A, 0x3C, 0x43, 0x0F, 0x62, 0x87, + 0x86, 0x10, 0x23, 0x09, 0xA4, 0x85, 0x13, 0x3E, 0xFF, 0x5F, 0xD7, 0xC9, 0x6B, 0x8E, 0x43, 0x0B, 0x29, 0x7E, 0xEB, 0x3B, + 0xC8, 0xB0, 0x1B, 0x62, 0xE7, 0xFA, 0xC6, 0xC3, 0x36, 0xC3, 0x74, 0x23, 0x6E, 0xB3, 0x8B, 0x04, 0x51, 0x83, 0x44, 0x85, + 0x80, 0xAF, 0x9B, 0xC6, 0x97, 0x40, 0xCE, 0xA1, 0xD3, 0x76, 0x77, 0x12, 0xA1, 0x54, 0xB7, 0x66, 0x10, 0x71, 0x7E, 0xD6, + 0xBF, 0x8C, 0xFC, 0xF0, 0x36, 0x7E, 0x65, 0xC7, 0xE4, 0x1F, 0xCF, 0x90, 0x91, 0xF2, 0xAD, 0x5E, 0x6F, 0x49, 0x1D, 0x69, + 0x11, 0x7D, 0x35, 0xF1, 0xA7, 0x51, 0x25, 0x25, 0xD2, 0xC3, 0x07, 0xB3, 0x0A, 0x5C, 0xFD, 0xF1, 0x71, 0x7E, 0x3C, 0x42, + 0x00, 0xF5, 0x70, 0x0B, 0xC1, 0xEF, 0x6C, 0xF4, 0xE0, 0x1C, 0xEC, 0xB4, 0x7A, 0x7B, 0x74, 0x00, 0xD8, 0x1A, 0x17, 0x45, + 0xD2, 0x4A, 0xCC, 0x82, 0xE1, 0x81, 0x10, 0x96, 0x30, 0xAA, 0x3D, 0x43, 0xAB, 0x4B, 0x50, 0x65, 0xB8, 0x76, 0x52, 0x65, + 0xDF, 0xC1, 0x45, 0x07, 0x70, 0x3E, 0x2D, 0x90, 0x1A, 0x55, 0x94, 0x40, 0x16, 0x88, 0x2A, 0x13, 0xC1, 0x75, 0xA5, 0x97, + 0xB0, 0xC8, 0x9B, 0x4E, 0xA8, 0xB8, 0x11, 0x7F, 0xBC, 0xB5, 0x57, 0xCE, 0x09, 0x5C, 0xDC, 0x51, 0xDB, 0x1D, 0xA5, 0x52, + 0x92, 0x22, 0xB5, 0x7E, 0x65, 0xCE, 0xA5, 0x5E, 0x79, 0xA4, 0xFE, 0xFC, 0x7F, 0x74, 0xAB, 0x2C, 0x7D, 0x79, 0xD5, 0xCF, + 0x53, 0x5E, 0x71, 0x4B, 0xE9, 0xFA, 0xAF, 0x7D, 0x0F, 0x75, 0x47, 0x7E, 0x5C, 0x29, 0x8D, 0x4B, 0x58, 0x20, 0xE7, 0x3B, + 0x69, 0xBD, 0xD5, 0x52, 0x5A, 0x76, 0xDB, 0x83, 0xA8, 0x54, 0x7B, 0x8B, 0xE0, 0x36, 0xD1, 0x6A, 0xBE, 0x20, 0xAE, 0xC8, + 0xDB, 0xA7, 0x36, 0x5A, 0x2E, 0xDD, 0xB0, 0xDA, 0xDA, 0xBE, 0x56, 0xEC, 0xE9, 0x89, 0xDF, 0xD8, 0x4C, 0x98, 0xC7, 0xAB, + 0xE9, 0xA1, 0x10, 0x3D, 0x27, 0x4F, 0x6F, 0xAE, 0x28, 0xFC, 0xD7, 0xA7, 0x0B, 0x62, 0x77, 0x09, 0x50, 0x10, 0x6C, 0x2E, + 0x37, 0x32, 0x28, 0x09, 0xE3, 0x50, 0x02, 0x9D, 0x90, 0xEC, 0x18, 0x87, 0x82, 0x03, 0xEA, 0x1B, 0x54, 0xA6, 0x4D, 0xCB, + 0x86, 0xAF, 0xD0, 0x62, 0x25, 0x6D, 0xCF, 0x90, 0x85, 0x97, 0x88, 0x99, 0xB4, 0x2B, 0x18, 0x15, 0xE4, 0xC8, 0x78, 0x5B, + 0x9C, 0xE7, 0x31, 0xB3, 0x80, 0xA3, 0x89, 0x1E, 0x37, 0xA4, 0x8A, 0xAA, 0x6B, 0xC4, 0xC9, 0xA5, 0xD1, 0xDB, 0x11, 0xFB, + 0x67, 0xCC, 0x2E, 0x07, 0x17, 0xAF, 0xF9, 0xB7, 0xF8, 0x8D, 0x31, 0x34, 0x74, 0x69, 0xA0, 0x3A, 0x5F, 0x0C, 0x73, 0x7D, + 0x6E, 0x31, 0xB4, 0xE7, 0x48, 0x4E, 0x30, 0x67, 0xDF, 0x19, 0x95, 0xB0, 0x85, 0xCD, 0xEA, 0xCF, 0xCB, 0x54, 0x18, 0x36, + 0x0F, 0x87, 0x80, 0x66, 0xB7, 0x1A, 0x69, 0xA1, 0x27, 0x0C, 0xF2, 0xAF, 0x9E, 0xE4, 0x75, 0xC3, 0x67, 0x06, 0xA8, 0x63, + 0xF2, 0x4D, 0xCF, 0xA3, 0x8F, 0x88, 0x4A, 0x6B, 0x4F, 0x16, 0xE4, 0xC9, 0x45, 0x8F, 0xC7, 0x95, 0x74, 0x82, 0x96, 0x68, + 0x3F, 0xCF, 0x21, 0xEC, 0xFD, 0x57, 0x12, 0x3B, 0xC1, 0xAB, 0xCD, 0xCC, 0xDE, 0xEB, 0xC9, 0x9E, 0x7C, 0x1A, 0xAE, 0x2E, + 0x93, 0x96, 0x47, 0xD3, 0xCB, 0xA6, 0xC2, 0xBC, 0x58, 0xE0, 0xDB, 0x6D, 0x77, 0x91, 0x1C, 0xF7, 0x9C, 0xD1, 0x98, 0x8E, + 0x19, 0xD4, 0x06, 0x4D, 0x9F, 0x1D, 0x72, 0xA9, 0x28, 0x90, 0x90, 0xAF, 0x1D, 0xF4, 0x80, 0xB2, 0x62, 0xD0, 0xE1, 0x7F, + 0x7E, 0x8E, 0x02, 0xEA, 0x46, 0x01, 0xC1, 0x76, 0x02, 0xA8, 0xB0, 0x08, 0xB1, 0xCF, 0x4D, 0x8C, 0x7A, 0xE1, 0x12, 0xD8, + 0x2D, 0x3F, 0x37, 0x66, 0x9D, 0x79, 0x7F, 0xFE, 0x72, 0x5A, 0xF0, 0x7A, 0xFC, 0xAC, 0x1B, 0xC9, 0xAC, 0xBD, 0xC8, 0x3D, + 0x25, 0x51, 0x4B, 0x7F, 0x4C, 0x86, 0xB9, 0x91, 0x7D, 0xE3, 0x13, 0xD9, 0xAD, 0xFF, 0x65, 0xAF, 0x60, 0xA0, 0xC4, 0x3C, + 0xC1, 0xCC, 0xC3, 0xAF, 0x24, 0xE0, 0xD8, 0x00, 0xA4, 0xB5, 0x50, 0x60, 0xB1, 0x20, 0x0C, 0x72, 0x38, 0xCB, 0xFE, 0x5D, + 0xD7, 0x95, 0xB1, 0x54, 0xA5, 0x31, 0x86, 0x13, 0x3B, 0x3B, 0x76, 0xAF, 0x0E, 0xDE, 0x84, 0x66, 0xAA, 0xFE, 0x1D, 0xE3, + 0xA2, 0xD0, 0xC5, 0x85, 0xE1, 0xBF, 0xC1, 0x45, 0x45, 0x5E, 0x8D, 0x77, 0x0A, 0xFD, 0x81, 0x36, 0x70, 0xF0, 0x29, 0x12, + 0x33, 0x70, 0xBC, 0x81, 0x85, 0x83, 0xDD, 0xF7, 0xF3, 0xFE, 0x04, 0x86, 0x32, 0x99, 0x1D, 0x81, 0xE0, 0xBE, 0x24, 0x6B, + 0x61, 0x96, 0x74, 0x1F, 0x76, 0x6F, 0xE4, 0xCE, 0x86, 0x1F, 0x93, 0x8C, 0x8E, 0x29, 0x44, 0xC3, 0xC6, 0x54, 0xC4, 0x26, + 0x2B, 0x5E, 0x2F, 0x38, 0x05, 0x90, 0x25, 0xA9, 0xD7, 0xD6, 0xEA, 0xCD, 0x1B, 0x77, 0xCD, 0x95, 0x09, 0xB7, 0x12, 0x31, + 0x25, 0xDF, 0xE8, 0x27, 0xFA, 0x26, 0x44, 0x00, 0x63, 0x5A, 0x85, 0xD7, 0x17, 0x98, 0x8D, 0x40, 0x97, 0xA3, 0xF6, 0x3A, + 0x24, 0x1A, 0x6F, 0x19, 0xCB, 0xDE, 0xFC, 0x50, 0xDF, 0x9D, 0xD2, 0x72, 0xFB, 0xD4, 0xE3, 0x78, 0xBD, 0x59, 0xCC, 0x5C, + 0xC8, 0x26, 0x86, 0x6E, 0x86, 0xF6, 0xC0, 0x6C, 0x59, 0xA8, 0x6E, 0x67, 0x16, 0x17, 0x17, 0x31, 0x4D, 0xC1, 0x8F, 0x7F, + 0x43, 0xF5, 0xD0, 0x93, 0x08, 0x80, 0xE9, 0x56, 0x8E, 0x9C, 0x75, 0x59, 0xCE, 0x5B, 0xDF, 0xFB, 0x9D, 0x76, 0x62, 0x4E, + 0x13, 0xFB, 0x98, 0xC8, 0xDF, 0x3F, 0x24, 0xBF, 0x85, 0xB8, 0xC8, 0x0C, 0x64, 0x93, 0xF3, 0x7D, 0xAD, 0xD5, 0x42, 0x4C, + 0x03, 0xB7, 0xE9, 0xE4, 0x1B, 0x69, 0x4A, 0x81, 0xDC, 0xBC, 0x07, 0x8F, 0xE6, 0xDC, 0x44, 0xCD, 0xF8, 0xE3, 0xB7, 0xFB, + 0xB3, 0x2A, 0x67, 0x10, 0x0B, 0xF1, 0x6A, 0x5F, 0x92, 0xF8, 0xAD, 0xB1, 0xDE, 0xDF, 0x68, 0xE1, 0x9F, 0x52, 0xA5, 0x43, + 0x97, 0xCE, 0x7E, 0x06, 0xE1, 0x83, 0xD0, 0x18, 0x1C, 0x23, 0xD6, 0x42, 0xCD, 0x22, 0x14, 0xD4, 0x59, 0x6F, 0x98, 0x72, + 0xFA, 0xDC, 0x8D, 0x96, 0x91, 0x29, 0x14, 0x4B, 0xE0, 0xCB, 0xC1, 0xC9, 0x32, 0xE3, 0x29, 0xF2, 0x0C, 0x0F, 0x85, 0x1D, + 0xB0, 0x80, 0x01, 0x43, 0x69, 0x44, 0x79, 0x04, 0x55, 0x42, 0xF1, 0x6A, 0x91, 0x4C, 0xD3, 0xEA, 0x32, 0x63, 0x66, 0xD3, + 0xBE, 0x03, 0x61, 0x47, 0x53, 0x67, 0x43, 0xA6, 0x80, 0xD0, 0xA2, 0x40, 0x11, 0xA4, 0x28, 0xE2, 0xCA, 0x1C, 0xD0, 0x59, + 0xB9, 0x20, 0x28, 0x4B, 0xF3, 0x8E, 0x08, 0x84, 0x30, 0x21, 0xC7, 0xA8, 0x45, 0x7C, 0x7C, 0x0A, 0xF0, 0x98, 0xD6, 0xB1, + 0xE3, 0x09, 0xC7, 0x6D, 0x12, 0x58, 0x0B, 0x9E, 0x61, 0x04, 0xEB, 0xD5, 0x52, 0xC9, 0x4D, 0xB3, 0x01, 0xD3, 0x70, 0xA9, + 0x13, 0xDC, 0x69, 0x37, 0x3F, 0x05, 0x81, 0x1B, 0xF7, 0x61, 0x92, 0xE0, 0x50, 0x45, 0x9A, 0x0C, 0x1E, 0xF1, 0xD2, 0x15, + 0x78, 0x0A, 0x01, 0xCE, 0x5E, 0x61, 0x72, 0x3F, 0xF4, 0x06, 0x06, 0x3C, 0xB8, 0xD3, 0x02, 0xD3, 0xCB, 0x6D, 0xC5, 0x5E, + 0xFD, 0xA4, 0xFC, 0x01, 0x2D, 0xF6, 0x69, 0x29, 0x9E, 0xB3, 0x86, 0x1D, 0x35, 0xC5, 0x93, 0x09, 0x5A, 0x6E, 0x9B, 0xE9, + 0x29, 0xDA, 0x4B, 0x70, 0x0E, 0x69, 0x92, 0x46, 0x6A, 0x09, 0x7B, 0xB8, 0x5B, 0x6F, 0x12, 0xAA, 0x2E, 0x4E, 0x4C, 0xB4, + 0xF6, 0x97, 0x9D, 0x5C, 0xC8, 0x64, 0xDA, 0xCB, 0xBB, 0x63, 0x70, 0xA7, 0x0D, 0x2D, 0x87, 0xB7, 0x1D, 0x24, 0x22, 0xFA, + 0x48, 0xA9, 0xD0, 0x7D, 0xF8, 0x60, 0x58, 0x61, 0xF9, 0x00, 0xDB, 0xA0, 0x37, 0x6C, 0xEF, 0x0B, 0x8B, 0x0E, 0xB3, 0x2D, + 0x7C, 0x63, 0x42, 0xDB, 0x5F, 0xD8, 0xCB, 0x79, 0x9D, 0xB6, 0x01, 0x69, 0x68, 0x49, 0x91, 0x60, 0x9A, 0x6A, 0xBB, 0x66, + 0x04, 0x16, 0x0A, 0xE6, 0xBD, 0xC6, 0x9A, 0x59, 0xCD, 0x12, 0xF4, 0xBA, 0x5F, 0x32, 0x26, 0x15, 0x62, 0xF1, 0xD6, 0xF4, + 0x4D, 0x9E, 0x1E, 0x76, 0x2B, 0x55, 0x92, 0xD6, 0x52, 0x31, 0x25, 0x70, 0x01, 0xED, 0x8D, 0xA0, 0x51, 0xCD, 0xD8, 0x8B, + 0x1D, 0x5B, 0x08, 0x92, 0x72, 0xA6, 0x9D, 0x73, 0x23, 0x10, 0x2D, 0xE7, 0xD3, 0xD6, 0xC9, 0x48, 0xCA, 0xC8, 0x29, 0xD7, + 0xD2, 0x63, 0x5E, 0x85, 0x01, 0xF7, 0x53, 0x3B, 0x66, 0xE3, 0x58, 0xF5, 0x01, 0x94, 0x5A, 0xB9, 0x2F, 0xFC, 0xB7, 0xAF, + 0x56, 0xEA, 0xBC, 0xB6, 0xD1, 0x60, 0x24, 0x72, 0x6A, 0xF5, 0x96, 0x5D, 0x51, 0x76, 0x25, 0xF6, 0x8F, 0x1B, 0x05, 0xB6, + 0x30, 0x12, 0x2D, 0x63, 0xEB, 0x96, 0xD8, 0x2D, 0xAD, 0x9E, 0x2D, 0xE6, 0xCA, 0x1A, 0x49, 0xAA, 0x92, 0x47, 0x07, 0xEC, + 0x40, 0x51, 0x12, 0x44, 0xD1, 0x74, 0xB3, 0xEA, 0x69, 0x98, 0xF8, 0x8B, 0x99, 0xE7, 0x16, 0x55, 0x79, 0x83, 0xF6, 0xB2, + 0x31, 0x77, 0x0E, 0x64, 0x69, 0x5B, 0x2E, 0xEE, 0x5B, 0x3D, 0x7E, 0xBB, 0x4B, 0x1B, 0xFE, 0xA2, 0x56, 0x74, 0x7F, 0xEB, + 0x8C, 0xE1, 0xDD, 0xD8, 0xC4, 0x95, 0x37, 0x2D, 0xA3, 0x18, 0x23, 0x5D, 0x3E, 0x75, 0x90, 0x86, 0x2B, 0x13, 0xF1, 0x9A, + 0x18, 0xE2, 0x1D, 0xD4, 0x6B, 0x7F, 0xC7, 0xB9, 0x55, 0x76, 0xD9, 0x28, 0x1A, 0x1A, 0x1D, 0xCF, 0x45, 0x39, 0x5A, 0xF8, + 0xC9, 0x1C, 0x02, 0xEC, 0x0D, 0x26, 0x8E, 0x05, 0xD7, 0x1B, 0x0E, 0x00, 0x90, 0x7C, 0x4F, 0x7A, 0xEB, 0x55, 0x01, 0x08, + 0x0C, 0x3D, 0xE4, 0x77, 0x5F, 0x11, 0x1A, 0x49, 0xC1, 0xC1, 0x9D, 0x1D, 0x0B, 0xF1, 0x05, 0x69, 0x97, 0xEC, 0xF9, 0xB5, + 0x0A, 0x96, 0xAF, 0xDE, 0xBA, 0xB4, 0x05, 0x06, 0x48, 0x59, 0x5F, 0x28, 0x16, 0x7F, 0x5E, 0x04, 0xE5, 0x03, 0xA4, 0x4E, + 0x6F, 0xCD, 0xAF, 0xBE, 0xC6, 0xC4, 0x0F, 0x44, 0xD6, 0x34, 0xF1, 0x25, 0x3A, 0x88, 0x68, 0xDB, 0xA5, 0x5C, 0xBB, 0x92, + 0x11, 0x21, 0x3C, 0xC6, 0x73, 0xEE, 0x05, 0xF0, 0x08, 0xC3, 0x7E, 0x67, 0xE3, 0x47, 0x6E, 0x41, 0xEA, 0x84, 0xB9, 0xC5, + 0x75, 0xE9, 0x77, 0xAB, 0x8D, 0x38, 0xF1, 0xC3, 0x17, 0xA7, 0xF9, 0xF2, 0xBF, 0x85, 0xD9, 0x35, 0x76, 0xEE, 0x3A, 0x0A, + 0xA5, 0x82, 0xF1, 0xBE, 0x96, 0x5F, 0x38, 0x74, 0xE5, 0xC2, 0x88, 0xE4, 0x57, 0xE3, 0x72, 0x06, 0x24, 0x7D, 0xD2, 0xA9, + 0xE0, 0x2E, 0xCC, 0x62, 0xE4, 0x87, 0x80, 0x52, 0xBE, 0x2C, 0xD7, 0x23, 0x27, 0x79, 0xE5, 0xC3, 0x9E, 0xBE, 0xF9, 0xCF, + 0x27, 0xC9, 0x4A, 0x85, 0x7A, 0x1B, 0x09, 0x64, 0xA2, 0x8A, 0xF1, 0x6B, 0x7C, 0xE3, 0xE6, 0xA0, 0xAC, 0xD0, 0x15, 0xE5, + 0xD3, 0xEF, 0x22, 0x2E, 0xE7, 0xCC, 0x2C, 0x6C, 0x3F, 0x08, 0x36, 0x28, 0x48, 0x84, 0xA4, 0x4C, 0xAB, 0x65, 0x8E, 0x74, + 0xAE, 0xC8, 0xAD, 0x9C, 0xF1, 0xA0, 0x21, 0x7F, 0x6F, 0xC4, 0xC2, 0x19, 0x88, 0xE6, 0x19, 0xBB, 0x58, 0x25, 0xF9, 0x4E, + 0x3F, 0xAE, 0x37, 0x6D, 0x86, 0x88, 0x67, 0xAD, 0x08, 0x42, 0xD4, 0x69, 0x2A, 0x9B, 0x93, 0xE0, 0x1F, 0xAF, 0x75, 0xC7, + 0x4D, 0x30, 0xDB, 0x3D, 0x76, 0xE6, 0x99, 0x35, 0x7B, 0x73, 0xD8, 0xFE, 0xF2, 0x03, 0x71, 0xAC, 0xFE, 0xCA, 0xF1, 0x1D, + 0x3B, 0x6A, 0xF5, 0xBA, 0x0E, 0x8B, 0xF1, 0xC7, 0xE6, 0xA2, 0x02, 0x3C, 0xBB, 0x83, 0x60, 0x4E, 0xA4, 0x12, 0x03, 0x7C, + 0xEF, 0x83, 0x47, 0x2D, 0x65, 0xEC, 0x7B, 0x8D, 0xAD, 0xEE, 0xF2, 0xAF, 0x9A, 0x43, 0xDD, 0x3A, 0x2E, 0x70, 0x2B, 0x27, + 0xC5, 0xA2, 0xCE, 0xBD, 0x3F, 0xC9, 0x6B, 0x82, 0x97, 0xAE, 0xD0, 0x72, 0x2C, 0x9F, 0xFC, 0x96, 0x68, 0x47, 0x27, 0xC0, + 0x97, 0xB5, 0xEC, 0xAF, 0xF6, 0x24, 0x4C, 0xD3, 0xD0, 0x9C, 0x69, 0x6A, 0xB5, 0x4A, 0xC7, 0x95, 0xC4, 0x2E, 0xE6, 0x8E, + 0xD6, 0xEA, 0x8D, 0x03, 0x21, 0xD2, 0x1D, 0xE1, 0x4A, 0xFF, 0x0D, 0x58, 0x48, 0xDF, 0x69, 0xB7, 0x57, 0x97, 0x67, 0x68, + 0x06, 0x95, 0x23, 0x7A, 0x18, 0x08, 0x89, 0xD1, 0x56, 0xB6, 0xFC, 0xD1, 0x77, 0x27, 0x31, 0x22, 0x60, 0xF1, 0xB1, 0x24, + 0x9A, 0x3F, 0x54, 0xB6, 0xC5, 0x96, 0xF4, 0xE6, 0x76, 0xF4, 0xD8, 0xB0, 0xC5, 0x76, 0x3A, 0x34, 0x9B, 0x3E, 0x75, 0xB4, + 0x73, 0x0E, 0xFC, 0xF6, 0x77, 0xF5, 0x5D, 0x71, 0x8C, 0xB4, 0xB1, 0x25, 0x1A, 0x3D, 0xE8, 0x2D, 0xE0, 0xF6, 0xF5, 0xE7, + 0xF6, 0xF6, 0x6E, 0xF4, 0x06, 0x68, 0xE7, 0x35, 0x1B, 0x3C, 0xCB, 0x0E, 0xC6, 0x6C, 0xFD, 0xF7, 0xF7, 0xF7, 0x2A, 0xF1, + 0x8D, 0x10, 0xBE, 0x76, 0xD0, 0xFA, 0x0E, 0x41, 0xC0, 0xD5, 0xE9, 0x4C, 0xFE, 0x2C, 0xEE, 0x43, 0x68, 0xDB, 0xED, 0x9C, + 0x21, 0xBF, 0x92, 0x3E, 0x2D, 0x49, 0x1F, 0x5C, 0xF8, 0x89, 0xA7, 0x69, 0xD3, 0xD9, 0xEA, 0x64, 0x9E, 0xBA, 0xCE, 0x8C, + 0x4D, 0xA5, 0xE3, 0xCD, 0x7E, 0x2E, 0xE0, 0x14, 0x2F, 0xD3, 0x8F, 0xCA, 0x1C, 0xB0, 0x27, 0xBF, 0x6A, 0x79, 0x85, 0x4C, + 0x8C, 0xE0, 0x7C, 0x9A, 0x0F, 0x7C, 0x62, 0x2C, 0x92, 0x37, 0xCA, 0x6E, 0x71, 0xC9, 0xF6, 0xEE, 0x7E, 0xFC, 0xEE, 0xD8, + 0xD8, 0xDC, 0x29, 0xA1, 0xBD, 0x44, 0xFF, 0xDF, 0x69, 0x27, 0xFE, 0xFE, 0x7F, 0xFD, 0xD8, 0xBB, 0xA1, 0x97, 0xAF, 0x2D, + 0xC1, 0xFC, 0xC8, 0x8B, 0xA8, 0xDF, 0xF7, 0xEF, 0xFE, 0xFE, 0x55, 0x59, 0x27, 0xCE, 0xC7, 0x58, 0x48, 0x34, 0x9A, 0x88, + 0xDF, 0xB3, 0xFF, 0xFF, 0x94, 0x54, 0x26, 0x59, 0x6E, 0xA4, 0x82, 0xF1, 0x58, 0xB1, 0x16, 0x11, 0x78, 0x02, 0x82, 0xDC, + 0xBB, 0x24, 0xB0, 0xE3, 0x3B, 0x11, 0xB6, 0x28, 0x32, 0x61, 0x26, 0x19, 0x29, 0x4C, 0x58, 0xDC, 0xEF, 0xEC, 0x8A, 0xA9, + 0xB3, 0x59, 0x87, 0x28, 0xD8, 0xF3, 0x4C, 0x6D, 0x21, 0x4D, 0xAF, 0xC7, 0xB2, 0xF7, 0xB1, 0xE2, 0xB7, 0x98, 0x8F, 0x2C, + 0x99, 0xD4, 0x0F, 0x53, 0xA1, 0x4C, 0xE7, 0x94, 0x3A, 0x20, 0x1A, 0x41, 0xA1, 0xB4, 0xC8, 0x54, 0xC6, 0x07, 0x09, 0x30, + 0x44, 0x7F, 0x8C, 0x92, 0x42, 0xAB, 0x11, 0xD6, 0x02, 0xC5, 0xCA, 0x36, 0xEC, 0x67, 0x0C, 0x6F, 0x65, 0xE8, 0xF2, 0xA4, + 0x0F, 0x64, 0x81, 0xA9, 0xFE, 0x44, 0x66, 0xE1, 0x10, 0x4A, 0x89, 0x21, 0x82, 0x92, 0xB1, 0x67, 0x87, 0x6B, 0x6F, 0xF4, + 0xA9, 0xA3, 0x90, 0x01, 0x7A, 0x04, 0xC8, 0xF5, 0xF0, 0x8F, 0xE1, 0x71, 0x56, 0xD5, 0xF6, 0xF1, 0xFB, 0xAC, 0x84, 0x20, + 0x10, 0x7D, 0x6C, 0x2E, 0xA9, 0xCB, 0xED, 0x3F, 0x17, 0x39, 0x82, 0xF5, 0x28, 0x52, 0x81, 0x6E, 0xE6, 0xF6, 0x24, 0xE9, + 0x20, 0x83, 0xD3, 0x7C, 0x5D, 0x41, 0xCE, 0x48, 0x40, 0x90, 0x43, 0xE5, 0xCF, 0x22, 0x3B, 0xAD, 0xFB, 0x3D, 0xAD, 0x01, + 0x57, 0xCC, 0xBD, 0xE4, 0xA8, 0xD0, 0xF4, 0xE7, 0x9F, 0x30, 0x43, 0x30, 0x20, 0xA1, 0x0B, 0x4E, 0xED, 0x29, 0x10, 0xEC, + 0x42, 0x7D, 0xBA, 0x6B, 0xF3, 0x6F, 0x6C, 0xC9, 0xE9, 0x29, 0x8B, 0x84, 0xBF, 0xAE, 0x12, 0x5C, 0x43, 0xBC, 0xCC, 0x75, + 0x33, 0x06, 0xCB, 0xFC, 0x34, 0xC1, 0x83, 0x94, 0xBE, 0x7F, 0x45, 0x75, 0x63, 0xDF, 0xBB, 0xC9, 0xE5, 0xA2, 0x6D, 0xCD, + 0x69, 0xBB, 0x92, 0x8D, 0xD2, 0xAC, 0x5F, 0x76, 0xC3, 0x5E, 0xAB, 0x1A, 0xDB, 0x22, 0x01, 0x68, 0xA3, 0x5E, 0x51, 0x9D, + 0xE7, 0x69, 0xD9, 0x04, 0x13, 0x0E, 0x3E, 0x00, 0x03, 0x99, 0x81, 0x67, 0xAA, 0x9A, 0x85, 0xD4, 0x2C, 0x79, 0xB6, 0x78, + 0x56, 0xDE, 0x3E, 0x35, 0x21, 0xF4, 0x0A, 0xD2, 0x9E, 0xFC, 0x84, 0x18, 0x90, 0xDE, 0x0D, 0x95, 0x93, 0x69, 0x8D, 0x90, + 0x83, 0x19, 0x5D, 0xED, 0x09, 0x83, 0x9A, 0xD6, 0xC0, 0xFD, 0x37, 0x13, 0x2C, 0x93, 0x5D, 0xE6, 0xC1, 0x5D, 0x0A, 0x35, + 0xD2, 0xB3, 0x8E, 0xC6, 0x81, 0x1F, 0x14, 0x44, 0x11, 0xCE, 0xA4, 0xB2, 0xBD, 0x82, 0x95, 0xC0, 0x4E, 0xDE, 0xCE, 0xE6, + 0xE0, 0x7C, 0xDB, 0xC3, 0x05, 0x16, 0xD6, 0xD5, 0x12, 0xB7, 0xA3, 0x83, 0x0D, 0xF6, 0x13, 0xBB, 0xF1, 0x19, 0x4D, 0xD5, + 0x6A, 0x35, 0xCD, 0x49, 0x5B, 0xBC, 0x6B, 0x49, 0x8A, 0x05, 0xD3, 0x97, 0x0D, 0x34, 0x17, 0xFF, 0xCB, 0x06, 0x94, 0xD2, + 0xF7, 0xFA, 0x08, 0x0F, 0xE5, 0x4C, 0xDF, 0x97, 0x0C, 0x7C, 0x7E, 0xFB, 0x6B, 0x13, 0xE4, 0x85, 0x39, 0x88, 0x2E, 0x2C, + 0x5B, 0x1E, 0xF1, 0x6C, 0x2A, 0xF3, 0x53, 0x13, 0x56, 0x82, 0x0E, 0x5C, 0x7D, 0x3A, 0x4A, 0xAB, 0x0B, 0x1A, 0xC3, 0x60, + 0xD8, 0xD0, 0x87, 0xE8, 0xFA, 0x58, 0xDE, 0x70, 0x5D, 0xBC, 0x1F, 0xBD, 0x20, 0x39, 0x26, 0x9C, 0x88, 0x38, 0xD4, 0xA3, + 0xAF, 0x21, 0x1B, 0x98, 0xBF, 0x61, 0xDF, 0x51, 0x46, 0x19, 0x8E, 0x5D, 0xA9, 0xF0, 0x86, 0x21, 0x7D, 0x11, 0x2A, 0x5E, + 0x36, 0x34, 0x5C, 0x8A, 0x99, 0x39, 0xD0, 0x04, 0x19, 0xBC, 0x8E, 0x31, 0x3E, 0x10, 0x4B, 0xD4, 0x5C, 0x2A, 0xBD, 0xB8, + 0x11, 0xD0, 0x84, 0x0A, 0x7D, 0x66, 0x39, 0xE1, 0xCA, 0xBE, 0x40, 0x25, 0xD5, 0xF5, 0x6F, 0x2E, 0x34, 0xC3, 0xF7, 0xFD, + 0x1B, 0x65, 0xB0, 0x22, 0x24, 0xB2, 0x27, 0xF8, 0x3B, 0xBF, 0x06, 0x09, 0x0C, 0x1D, 0xB6, 0xBD, 0xB1, 0x82, 0x14, 0x86, + 0x7A, 0xD7, 0x5C, 0xC1, 0x12, 0xC0, 0x2E, 0xEA, 0x67, 0xA0, 0xED, 0xB2, 0xBF, 0x31, 0x77, 0xED, 0x7A, 0x84, 0x72, 0x60, + 0x34, 0x11, 0xF6, 0x1E, 0xAC, 0x90, 0x9E, 0xE7, 0x69, 0x4C, 0x94, 0xDB, 0x30, 0xF8, 0x5B, 0x47, 0xE2, 0xB9, 0xF1, 0xEF, + 0x2A, 0x66, 0x08, 0x9B, 0x3F, 0x53, 0xF2, 0x3D, 0x83, 0x49, 0x69, 0xFE, 0x92, 0xB8, 0xD5, 0xA0, 0xD6, 0xC9, 0x2C, 0xF0, + 0x1F, 0x29, 0x74, 0xD0, 0xFF, 0x8F, 0x9F, 0x01, 0xFF, 0x2E, 0xB0, 0x8B, 0x53, 0x69, 0xD0, 0x3F, 0xF7, 0x86, 0x16, 0x6A, + 0x5D, 0xC7, 0x28, 0xBF, 0xC3, 0xBE, 0xE2, 0x01, 0x73, 0xCA, 0x18, 0xEF, 0xD2, 0x84, 0xE1, 0x02, 0x72, 0x0B, 0x86, 0xAF, + 0x14, 0x69, 0x21, 0x81, 0xC0, 0xFD, 0x35, 0xB7, 0xA8, 0x84, 0x34, 0x57, 0x26, 0x78, 0xB7, 0x31, 0x20, 0xB7, 0x65, 0xFB, + 0x2E, 0x94, 0x51, 0x57, 0x55, 0x8B, 0x60, 0xE7, 0x66, 0x23, 0x7A, 0x98, 0x0E, 0x65, 0xAE, 0x59, 0x78, 0x8A, 0xFA, 0x56, + 0x3F, 0xED, 0x19, 0xD7, 0x72, 0x80, 0xFE, 0xD9, 0xF4, 0xEA, 0x01, 0x86, 0xA6, 0x78, 0xE0, 0x10, 0x37, 0x58, 0x2B, 0xAA, + 0x74, 0x10, 0x63, 0xE7, 0xF0, 0xA2, 0x6A, 0x41, 0x27, 0x1B, 0xA5, 0x13, 0x37, 0xAE, 0xF0, 0x2C, 0x8B, 0xA1, 0xF2, 0xFB, + 0x5B, 0xB9, 0x1D, 0xEA, 0xF1, 0x66, 0xC5, 0x38, 0x7C, 0x44, 0x8E, 0xD9, 0x7E, 0x84, 0x5A, 0xA1, 0x93, 0x21, 0x64, 0x08, + 0xB1, 0x61, 0xF0, 0x0C, 0x7D, 0x2E, 0x7B, 0x21, 0x2C, 0x50, 0x13, 0x99, 0x19, 0xB6, 0x44, 0xDE, 0x91, 0x10, 0x2B, 0x0D, + 0x65, 0x64, 0x61, 0x54, 0xFE, 0x3A, 0x06, 0xA0, 0x7F, 0xF8, 0x26, 0xCE, 0x39, 0xA0, 0x1F, 0x1C, 0xD9, 0x48, 0x15, 0x66, + 0x47, 0x1E, 0xC4, 0x1F, 0xB7, 0xB4, 0xBB, 0x93, 0xA6, 0xC5, 0xDB, 0x95, 0x36, 0xC5, 0x59, 0xF0, 0xCF, 0xA1, 0x52, 0xB9, + 0x0C, 0xB4, 0x6D, 0x9F, 0x93, 0xB5, 0xCA, 0x97, 0x04, 0xB2, 0xF3, 0x04, 0x24, 0xD1, 0x77, 0x78, 0x7D, 0x80, 0x02, 0x17, + 0x13, 0x0E, 0xC4, 0xB4, 0x35, 0x51, 0x1B, 0xAA, 0x29, 0x89, 0x25, 0x7A, 0xE8, 0xF0, 0x0D, 0x92, 0x86, 0x2D, 0xE8, 0xB6, + 0x55, 0x72, 0x39, 0xEF, 0x44, 0x3C, 0xA9, 0xE7, 0x54, 0x1C, 0xE9, 0x20, 0x44, 0x6C, 0xAE, 0xB5, 0x22, 0x5E, 0x34, 0x59, + 0xCF, 0x65, 0xDE, 0x2E, 0xBA, 0x7B, 0x29, 0x26, 0xAC, 0x17, 0xE6, 0xE2, 0x89, 0x79, 0x70, 0x5A, 0xA5, 0xF9, 0x40, 0x2B, + 0x71, 0xCE, 0xEA, 0x32, 0x3B, 0xB9, 0x46, 0x72, 0x4C, 0x90, 0x07, 0xC3, 0xA5, 0xD6, 0xF5, 0xE2, 0xEA, 0x6D, 0x4B, 0x52, + 0xE0, 0xCD, 0x21, 0x19, 0xC5, 0xF0, 0x6F, 0xB1, 0x4C, 0xC6, 0xBE, 0x2E, 0xC4, 0x2C, 0x43, 0x57, 0x2D, 0xC4, 0xF5, 0xE3, + 0x70, 0xF6, 0x72, 0x79, 0x0A, 0x83, 0xB3, 0xFD, 0x04, 0xD4, 0x4D, 0xC5, 0x10, 0x27, 0xA5, 0xD7, 0x5F, 0xFA, 0x2E, 0x9A, + 0x2D, 0x99, 0xB2, 0x06, 0x56, 0xB6, 0x69, 0x41, 0xDC, 0x4A, 0xE3, 0x62, 0x94, 0xE8, 0x1E, 0x0F, 0xEC, 0x1D, 0xC1, 0x5F, + 0xBD, 0xFA, 0x8E, 0x17, 0x1B, 0xE7, 0xED, 0x81, 0x84, 0xB8, 0x15, 0x68, 0xDD, 0x10, 0xAD, 0xEC, 0x85, 0x3E, 0x44, 0x53, + 0x5C, 0x99, 0xC7, 0x3B, 0xC6, 0xBB, 0xD9, 0xAA, 0x7E, 0xDE, 0xD5, 0x4A, 0x25, 0x83, 0x48, 0x5F, 0x68, 0xC7, 0xAF, 0x1A, + 0x19, 0x7E, 0xFF, 0x58, 0xA2, 0x1D, 0x54, 0xBE, 0x33, 0x7F, 0xEA, 0x66, 0x69, 0xC6, 0x80, 0x2E, 0x4C, 0x56, 0x3A, 0xBF, + 0x0F, 0x31, 0xC3, 0xD6, 0x8D, 0x75, 0x69, 0x2B, 0xE2, 0xDF, 0x97, 0xA8, 0xBE, 0xF3, 0x57, 0x4B, 0x0C, 0xDD, 0xCF, 0xCB, + 0x5E, 0xA4, 0x75, 0x7F, 0xD4, 0x94, 0x45, 0x9F, 0xAB, 0x56, 0x4A, 0x60, 0x14, 0x1B, 0x80, 0x66, 0xE7, 0x45, 0xEB, 0xD3, + 0x74, 0x2C, 0x2B, 0xAA, 0xBB, 0xF1, 0x8C, 0xD0, 0x05, 0xC1, 0x59, 0xFA, 0x09, 0x25, 0x7A, 0x32, 0x40, 0x80, 0x50, 0x47, + 0x5A, 0xE8, 0x59, 0x77, 0x0D, 0x84, 0xB9, 0x28, 0x2F, 0xFF, 0x2F, 0x0D, 0xA1, 0x46, 0x7D, 0x56, 0xA8, 0xC4, 0x99, 0x63, + 0xB2, 0x08, 0x8B, 0x04, 0xA5, 0x27, 0xD9, 0xD9, 0xB4, 0x4E, 0xB9, 0xDF, 0x38, 0xF2, 0x40, 0x33, 0x72, 0x0B, 0x85, 0x57, + 0x59, 0x95, 0x45, 0x13, 0x7A, 0x4F, 0x8A, 0x9E, 0x3A, 0x55, 0x88, 0xB8, 0x76, 0x8E, 0x02, 0x94, 0x0F, 0x90, 0x78, 0x12, + 0x13, 0x41, 0xC0, 0x1D, 0xBA, 0x3F, 0xF5, 0x32, 0xFA, 0x09, 0xFF, 0x7C, 0x1D, 0x80, 0xD1, 0x70, 0xF2, 0xB6, 0x11, 0x8C, + 0xA5, 0x6B, 0x41, 0xB3, 0xE0, 0x47, 0xDE, 0x6A, 0xE3, 0x65, 0x74, 0x02, 0xE2, 0xC6, 0xFF, 0x5C, 0x70, 0xE2, 0xF8, 0xE0, + 0x7F, 0xC5, 0x2E, 0x67, 0x39, 0xF8, 0x0A, 0x34, 0x2B, 0x97, 0x88, 0x2E, 0xCA, 0x60, 0xE8, 0xD8, 0x11, 0xF4, 0x37, 0x43, + 0xCC, 0x74, 0x40, 0xC7, 0x23, 0x98, 0xBC, 0x05, 0x5E, 0x6D, 0xFC, 0x4E, 0xBB, 0x71, 0xFC, 0xF5, 0x98, 0xD6, 0x05, 0x14, + 0x23, 0xBB, 0x92, 0x3E, 0xA8, 0x40, 0xA7, 0x8B, 0x99, 0x03, 0x20, 0x99, 0x9D, 0x3A, 0x65, 0x05, 0x49, 0xDB, 0x5E, 0xFA, + 0xEA, 0xA0, 0x54, 0x75, 0xE1, 0xFD, 0x1C, 0x88, 0x52, 0x9D, 0x91, 0x97, 0xAB, 0xEF, 0xF4, 0x8E, 0x66, 0xC3, 0xD9, 0x49, + 0x3F, 0xAD, 0xEA, 0x3E, 0xE3, 0x5C, 0x0D, 0xFC, 0x70, 0x28, 0xE4, 0x54, 0xD6, 0xCB, 0x79, 0xF8, 0xFE, 0xA1, 0xE3, 0x33, + 0xD2, 0xBF, 0x9C, 0x97, 0xCC, 0x75, 0xC0, 0x1F, 0x31, 0x7F, 0xDA, 0x7A, 0x8A, 0x4E, 0x7C, 0x71, 0x9D, 0xC4, 0x53, 0x64, + 0x49, 0x6B, 0x12, 0xBD, 0x98, 0x2D, 0x30, 0x04, 0x2B, 0x27, 0xB3, 0xA8, 0xC9, 0x53, 0xBB, 0x90, 0x68, 0xFF, 0xCE, 0xA6, + 0xC3, 0xA9, 0x51, 0x60, 0xCC, 0x7F, 0xB3, 0x07, 0x76, 0xBA, 0x8F, 0xC3, 0x2A, 0xDB, 0xA2, 0x8D, 0xBB, 0x78, 0x3F, 0x69, + 0xD7, 0xDD, 0xE3, 0xE7, 0x43, 0x5C, 0x82, 0xD3, 0x9E, 0xFD, 0xF4, 0x65, 0x9E, 0x1E, 0x54, 0x68, 0x67, 0x1B, 0xAD, 0x7F, + 0xC0, 0x25, 0x19, 0x42, 0xDD, 0xFE, 0xA3, 0x68, 0x90, 0x77, 0xD5, 0xB3, 0x16, 0x78, 0x0B, 0xB8, 0xCF, 0x95, 0xB8, 0x93, + 0x12, 0xA2, 0xCE, 0x06, 0x74, 0xD7, 0x8C, 0x39, 0x59, 0x1C, 0x95, 0xC1, 0xDA, 0x16, 0x54, 0xE1, 0x50, 0x3F, 0x85, 0x25, + 0x75, 0xF5, 0x23, 0x11, 0xA1, 0x7D, 0xFD, 0x3A, 0x47, 0x74, 0x6B, 0xCC, 0x20, 0x56, 0xFE, 0x61, 0xF1, 0x81, 0xD4, 0xEE, + 0x97, 0x55, 0xB5, 0xF2, 0x5A, 0x74, 0x07, 0xF0, 0x44, 0x51, 0x51, 0x05, 0x80, 0xD6, 0x01, 0xFA, 0x1B, 0x93, 0x8E, 0x88, + 0xB1, 0xCA, 0xDC, 0xB8, 0x83, 0x09, 0xEF, 0xDF, 0x08, 0xF1, 0xA3, 0x9A, 0x25, 0x02, 0xB4, 0x03, 0xC6, 0xB4, 0x78, 0xDA, + 0x9A, 0x35, 0x27, 0xCC, 0xF9, 0xFF, 0xFD, 0x76, 0xAE, 0xE0, 0x47, 0x64, 0x6C, 0x56, 0x20, 0x85, 0x11, 0x39, 0xB7, 0x27, + 0xF9, 0xBB, 0xD4, 0x8D, 0x9A, 0x80, 0x6C, 0x63, 0x34, 0x79, 0x20, 0x2A, 0xFE, 0xD0, 0xBF, 0x7D, 0xA7, 0x39, 0x8B, 0xA2, + 0xCB, 0xA3, 0xBE, 0xE8, 0x3C, 0xC6, 0x7E, 0x92, 0x83, 0xCD, 0x47, 0x68, 0x49, 0xC7, 0x28, 0x10, 0x28, 0x3E, 0x31, 0xA2, + 0x15, 0x48, 0x79, 0xD5, 0x00, 0x8C, 0x01, 0x88, 0x18, 0xFD, 0x74, 0x1C, 0x5B, 0x70, 0x5C, 0xB2, 0xD2, 0x33, 0x2F, 0xCD, + 0x36, 0x0F, 0x17, 0xFD, 0xC7, 0x3C, 0x74, 0x35, 0xAB, 0x5D, 0x5C, 0xF3, 0xC7, 0x0A, 0x5B, 0x08, 0x97, 0xBA, 0xC9, 0xD1, + 0x10, 0x2E, 0xF1, 0xA2, 0x24, 0x63, 0x80, 0x0A, 0xFD, 0x0A, 0xF0, 0xCA, 0x44, 0xCD, 0x08, 0xB5, 0x2C, 0x4D, 0x71, 0xEF, + 0xE2, 0x5A, 0x66, 0x92, 0x6A, 0x50, 0x65, 0x33, 0xC5, 0x01, 0xC0, 0xBE, 0xF0, 0x68, 0x41, 0x44, 0xC4, 0x8F, 0xEB, 0x06, + 0x6F, 0x57, 0xC8, 0x04, 0x65, 0xBD, 0xA2, 0x57, 0x54, 0x4D, 0x01, 0xEE, 0x26, 0xC1, 0x00, 0x69, 0x00, 0xDF, 0x7F, 0x1F, + 0x8F, 0x92, 0x99, 0xA4, 0x76, 0xEB, 0x30, 0x67, 0x02, 0xA8, 0x28, 0xC4, 0x9E, 0x14, 0x76, 0x00, 0xB9, 0x79, 0xAD, 0xC6, + 0xF7, 0x6D, 0x50, 0xB2, 0x03, 0xA9, 0x6C, 0xA7, 0x67, 0xF5, 0x21, 0xB7, 0x24, 0xE5, 0x33, 0x49, 0x27, 0x30, 0x0F, 0xC1, + 0x0E, 0x26, 0xD9, 0xB4, 0xE6, 0xAD, 0x9D, 0xFC, 0xC7, 0x66, 0xF5, 0x87, 0xD7, 0x49, 0x07, 0x74, 0x26, 0x8C, 0x5A, 0xF6, + 0x6B, 0xE4, 0x81, 0x08, 0xAF, 0x56, 0x6C, 0xF3, 0x8C, 0x71, 0x7F, 0x81, 0x0A, 0xB2, 0x1D, 0x41, 0xF5, 0x42, 0x12, 0xE9, + 0xA5, 0x22, 0x34, 0x5D, 0x2C, 0xA7, 0x51, 0x35, 0x5E, 0xDC, 0x3D, 0x64, 0x6B, 0x06, 0x61, 0x3A, 0x25, 0x03, 0xDA, 0x3C, + 0x87, 0xE4, 0x5E, 0xF3, 0x22, 0x31, 0x63, 0xE7, 0x2D, 0x05, 0x15, 0xE7, 0x6F, 0x4F, 0xB2, 0x5C, 0xA4, 0xA5, 0xE6, 0xE6, + 0xAC, 0x50, 0x38, 0x0C, 0xD6, 0xFA, 0xC4, 0x41, 0xA7, 0xC4, 0xC4, 0x78, 0x20, 0x5D, 0xE2, 0x09, 0xC5, 0x21, 0xD5, 0x76, + 0x6D, 0xAC, 0x0C, 0x52, 0xAF, 0x6F, 0xD4, 0x46, 0x15, 0x48, 0x58, 0x49, 0xAC, 0xFC, 0xBE, 0x41, 0x39, 0x18, 0xEB, 0x39, + 0x46, 0xCB, 0x34, 0x6D, 0x67, 0xF7, 0x29, 0xBA, 0x2D, 0xCE, 0x23, 0x4B, 0xAE, 0x7A, 0xE6, 0x98, 0xF2, 0x6E, 0xE2, 0xBB, + 0x16, 0xDF, 0x15, 0x63, 0x6E, 0x20, 0x7E, 0x60, 0xAB, 0xED, 0x5F, 0x6F, 0x6E, 0x30, 0x3B, 0x96, 0xFD, 0x64, 0x9E, 0xE2, + 0x2C, 0x52, 0xFD, 0xDD, 0x37, 0x70, 0x14, 0x48, 0x15, 0xC6, 0xED, 0xA6, 0xD5, 0x2F, 0x51, 0xE1, 0x6A, 0x35, 0x13, 0xD9, + 0x33, 0xAA, 0x76, 0xB3, 0x0C, 0xA0, 0xBC, 0x4F, 0x71, 0xB3, 0xB5, 0xF1, 0x1B, 0xCD, 0x0C, 0xF9, 0x21, 0xCE, 0x7D, 0x8E, + 0x0D, 0x83, 0x01, 0xC5, 0x0B, 0x69, 0xE4, 0x71, 0x45, 0x32, 0x36, 0xF5, 0xD4, 0xBB, 0x65, 0xA7, 0xE3, 0xC8, 0x3D, 0x9F, + 0x24, 0x2E, 0x3D, 0xAC, 0xCD, 0xA5, 0xB4, 0xD9, 0xB2, 0x1B, 0x2A, 0x42, 0x47, 0x70, 0x58, 0x74, 0xD6, 0xFC, 0xDB, 0x03, + 0xDA, 0xFB, 0x5F, 0x34, 0x5F, 0xF6, 0xB6, 0xE1, 0x53, 0x3F, 0xEF, 0x85, 0x07, 0xFE, 0xDC, 0x7F, 0x4D, 0x87, 0x41, 0x43, + 0xB2, 0x3D, 0xE0, 0x32, 0x2E, 0xA7, 0x75, 0xE5, 0xF4, 0x56, 0x0B, 0x07, 0xA4, 0xC5, 0x93, 0x73, 0x42, 0x14, 0x5B, 0xDF, + 0xF4, 0x95, 0x7D, 0xE6, 0xCB, 0x57, 0x68, 0x0E, 0x17, 0x5C, 0xFE, 0x8A, 0xB5, 0x68, 0xAD, 0xC8, 0x4D, 0x88, 0x9D, 0xF5, + 0x81, 0x44, 0x91, 0x2A, 0xD2, 0x36, 0x55, 0xB9, 0x9C, 0x46, 0x66, 0x3F, 0x25, 0x08, 0xC6, 0x99, 0x84, 0xF6, 0x35, 0x75, + 0x47, 0x6B, 0x67, 0x67, 0xBC, 0xB7, 0x31, 0x96, 0x05, 0x2B, 0x77, 0x47, 0xFC, 0x67, 0xBC, 0xE8, 0xE6, 0x1A, 0x03, 0x10, + 0x56, 0x0A, 0x1F, 0xA6, 0xEB, 0xC0, 0x9F, 0xB3, 0xFB, 0xE0, 0x3C, 0xE8, 0x46, 0xAD, 0xB2, 0x3D, 0x14, 0xFD, 0xBF, 0x5D, + 0x8F, 0x73, 0xE7, 0xEC, 0x96, 0x5C, 0x38, 0xF2, 0xC4, 0xF9, 0xFB, 0xAD, 0x07, 0xD1, 0xB0, 0xC2, 0x86, 0x4C, 0x56, 0x8D, + 0x4B, 0xB2, 0x19, 0xCD, 0xCD, 0xCB, 0xDD, 0x3C, 0x8A, 0x11, 0x23, 0x18, 0xC8, 0x7A, 0xE2, 0x8C, 0xC5, 0xE5, 0x57, 0xE2, + 0x54, 0x3F, 0x89, 0x16, 0xBC, 0x54, 0x93, 0x68, 0xFC, 0xD5, 0x6F, 0xFF, 0xFF, 0xFF, 0x3E, 0x3D, 0x68, 0x0D, 0xF9, 0x20, + 0x73, 0x8F, 0x42, 0x1A, 0xAB, 0x24, 0xAA, 0x94, 0x84, 0xCF, 0xF3, 0xE0, 0x20, 0xF0, 0xDA, 0x52, 0xFA, 0x45, 0x60, 0x80, + 0xAD, 0xEE, 0x67, 0x4E, 0x3B, 0x6E, 0xFE, 0x72, 0xF4, 0x61, 0x96, 0xF6, 0x14, 0xAF, 0x81, 0xD2, 0x44, 0xEF, 0x35, 0x01, + 0xA3, 0x62, 0x77, 0x17, 0xE2, 0x26, 0x19, 0x66, 0x86, 0x87, 0xBD, 0x53, 0x36, 0x26, 0x36, 0x11, 0x38, 0x99, 0x0B, 0xBB, + 0xF3, 0x87, 0x00, 0xAC, 0x55, 0xAF, 0x68, 0x9E, 0xEE, 0x49, 0x8E, 0xD4, 0xE5, 0xE9, 0xFA, 0xF5, 0xF4, 0xF8, 0x93, 0x54, + 0x9E, 0x98, 0x40, 0x9F, 0xAA, 0x94, 0x21, 0x87, 0x3D, 0xC1, 0x75, 0xBB, 0x84, 0x1D, 0xC5, 0xA7, 0x6A, 0x7C, 0xAE, 0x12, + 0xBE, 0xE7, 0xAF, 0xD4, 0xB9, 0xA5, 0x5B, 0x31, 0x3C, 0xDA, 0xAF, 0x7C, 0x6C, 0xBA, 0x0F, 0xAC, 0x4E, 0x05, 0xC1, 0x58, + 0x38, 0x76, 0xD1, 0xFB, 0x84, 0x49, 0x93, 0xEE, 0xF8, 0xFD, 0x2A, 0x0C, 0xA3, 0x2B, 0x22, 0x5B, 0x56, 0xB7, 0xF5, 0x6B, + 0x75, 0xA8, 0xF2, 0x2E, 0xE6, 0xFC, 0xF6, 0xAB, 0x6F, 0xE4, 0x0A, 0xC4, 0xD4, 0xD2, 0x3B, 0xF7, 0x24, 0x07, 0xFB, 0x29, + 0x50, 0x70, 0xA7, 0x4B, 0x23, 0xC9, 0xAD, 0x4D, 0xD6, 0x95, 0x13, 0xF6, 0x60, 0xDA, 0xF3, 0x6E, 0xD2, 0x70, 0x4F, 0x49, + 0x49, 0x54, 0x59, 0x0C, 0x78, 0xCA, 0x10, 0x7F, 0xBD, 0xA1, 0xA0, 0x4C, 0xC7, 0xAD, 0x0B, 0x4D, 0x49, 0xDD, 0xEC, 0x44, + 0xD7, 0xCA, 0xC2, 0x2A, 0x69, 0xF2, 0x31, 0xD8, 0x20, 0x98, 0x22, 0x7A, 0x23, 0x0F, 0xCB, 0xF8, 0x44, 0x70, 0x8A, 0x79, + 0x7D, 0xA1, 0x3C, 0x12, 0x67, 0xA4, 0x93, 0x81, 0x3E, 0xC3, 0x99, 0xAD, 0xF0, 0x9B, 0x35, 0x18, 0x08, 0x02, 0x30, 0xD9, + 0xA8, 0x65, 0x02, 0x4F, 0xCD, 0x54, 0xE5, 0xAC, 0x56, 0xC9, 0x7A, 0x87, 0x81, 0x51, 0x15, 0x77, 0xB4, 0xBD, 0x2C, 0x5B, + 0xCC, 0x5D, 0x25, 0x20, 0x37, 0xF2, 0x1E, 0x8D, 0xCA, 0x55, 0xB4, 0xB0, 0xDA, 0x75, 0x45, 0x61, 0x65, 0xD1, 0x8D, 0xF3, + 0xBB, 0x4B, 0x3B, 0xA8, 0xC8, 0x1F, 0xD7, 0xC3, 0x5B, 0x56, 0xEE, 0x86, 0x41, 0xAD, 0xAF, 0x56, 0xC0, 0xDF, 0x37, 0x21, + 0x24, 0xBC, 0xB7, 0x25, 0x3C, 0x9C, 0xD2, 0xDE, 0x3F, 0x8E, 0x95, 0xB1, 0xD8, 0xD9, 0x9B, 0xFD, 0xF6, 0xC5, 0x9E, 0xC5, + 0x91, 0x76, 0x0E, 0xE4, 0x64, 0x6F, 0x50, 0xF7, 0x61, 0x97, 0x6A, 0xF8, 0x80, 0x90, 0xB4, 0xA7, 0x0B, 0x3E, 0x97, 0x74, + 0x58, 0xE5, 0x70, 0x87, 0x19, 0xD3, 0xE2, 0xFC, 0x4B, 0x4C, 0x9C, 0x01, 0xD1, 0x16, 0x62, 0xF8, 0xBA, 0x7E, 0xD3, 0xCD, + 0x72, 0x6A, 0x5B, 0xF8, 0xA5, 0x2C, 0xCF, 0xC4, 0x8B, 0x1F, 0x6A, 0xD8, 0x90, 0x57, 0x8F, 0x06, 0xC9, 0x1B, 0xA2, 0xAC, + 0x4B, 0xCE, 0x22, 0xA8, 0xD1, 0x7B, 0x0C, 0xAA, 0xDB, 0x05, 0xCC, 0x56, 0x10, 0x69, 0x54, 0xB6, 0x5F, 0xB6, 0xDA, 0x39, + 0xCE, 0x55, 0xF2, 0xCB, 0x0F, 0xFF, 0xC6, 0xB8, 0x50, 0x53, 0x11, 0x28, 0x43, 0x5E, 0x91, 0xEF, 0x47, 0x97, 0x0D, 0xAB, + 0x7A, 0x1B, 0x57, 0x44, 0x8F, 0x77, 0xAB, 0xBD, 0x26, 0xB6, 0x30, 0xB9, 0x52, 0x7F, 0x4E, 0xCA, 0x87, 0xD2, 0x5F, 0x54, + 0xA1, 0xFA, 0xE4, 0xF8, 0x2E, 0xB3, 0x13, 0xDD, 0x0A, 0x1D, 0x41, 0x1B, 0x40, 0xC1, 0xE8, 0x59, 0xB0, 0xBF, 0x1E, 0xAB, + 0x13, 0x9C, 0x5D, 0x2F, 0x47, 0x92, 0x04, 0xDE, 0x6D, 0x46, 0x16, 0x6F, 0x51, 0xD0, 0x13, 0xBB, 0xD4, 0xB1, 0x69, 0xE9, + 0x5B, 0x91, 0x84, 0x1A, 0xC8, 0x81, 0xA9, 0x45, 0x75, 0xD3, 0xCF, 0x22, 0x52, 0x73, 0x1B, 0x5F, 0x33, 0x7D, 0x15, 0x9B, + 0x09, 0x7F, 0x93, 0x6E, 0xD9, 0x75, 0x76, 0xDF, 0x8B, 0xDF, 0xA0, 0x3B, 0x30, 0x2B, 0x0E, 0x87, 0x25, 0xC4, 0x88, 0xC9, + 0x70, 0x8E, 0x08, 0xF8, 0xF0, 0x08, 0x08, 0xE6, 0xA1, 0x02, 0x2E, 0x50, 0xBA, 0x6C, 0xC1, 0xC6, 0xD5, 0xF7, 0x9E, 0x8C, + 0x31, 0x0B, 0x91, 0x36, 0xE0, 0x0D, 0x50, 0x07, 0x2D, 0xE1, 0x56, 0x59, 0xB5, 0xE6, 0x09, 0x99, 0xA1, 0x2E, 0xBE, 0xE4, + 0x19, 0xE2, 0x69, 0x17, 0xA6, 0xC6, 0x29, 0x06, 0xFF, 0x4C, 0x9F, 0x80, 0xA7, 0x5B, 0xD8, 0x36, 0x1E, 0xAF, 0xA2, 0x8C, + 0xEA, 0xC9, 0xA2, 0xA6, 0x5A, 0x40, 0xA7, 0x7E, 0xCF, 0x8C, 0x28, 0xBE, 0x5B, 0xE7, 0x6B, 0xF6, 0x74, 0xCB, 0x14, 0xE5, + 0x3D, 0xED, 0xA1, 0xFE, 0x30, 0x22, 0xF3, 0xC3, 0xA5, 0x63, 0xDD, 0xF0, 0xBE, 0x6B, 0xBF, 0xD7, 0x3F, 0x2C, 0xFC, 0x14, + 0x66, 0x21, 0xB0, 0xC7, 0x96, 0x95, 0x31, 0xF7, 0xA4, 0x5D, 0x7D, 0x64, 0x90, 0x44, 0xB1, 0x3B, 0xAD, 0x77, 0xF8, 0x2C, + 0x74, 0x39, 0x24, 0x8B, 0xA7, 0x8C, 0xE6, 0x5C, 0x36, 0xEB, 0x70, 0x7A, 0x71, 0x26, 0xFC, 0x33, 0xF6, 0xCD, 0x44, 0x3D, + 0x69, 0x66, 0xF1, 0x10, 0x42, 0x64, 0x1D, 0x32, 0xA2, 0x55, 0xDD, 0x09, 0xFF, 0xFF, 0x69, 0x05, 0xA6, 0xC9, 0xCD, 0x8F, + 0xF8, 0x9F, 0x8B, 0xEB, 0x61, 0x58, 0x3B, 0xEF, 0x03, 0x0A, 0x9F, 0x59, 0x3E, 0xAE, 0xC4, 0xC2, 0x7D, 0x30, 0x7A, 0xB9, + 0x76, 0x01, 0x22, 0xA7, 0x46, 0x1D, 0xB2, 0x82, 0x52, 0x8E, 0xCC, 0xBB, 0xD3, 0x4A, 0x50, 0xA9, 0x37, 0x38, 0x94, 0xFE, + 0xE8, 0x26, 0x20, 0xE4, 0x49, 0xD6, 0x34, 0xCA, 0xB6, 0xF7, 0x05, 0x96, 0x65, 0x1F, 0x9D, 0xEE, 0x6F, 0x7D, 0x2A, 0xFB, + 0xCF, 0xDE, 0x21, 0xAF, 0xD2, 0x4A, 0x7E, 0x64, 0xBF, 0xCD, 0x0C, 0xDB, 0xAC, 0x25, 0x0B, 0x8B, 0xC7, 0xC0, 0x17, 0xEC, + 0xB1, 0xE7, 0xF4, 0x11, 0x12, 0x3D, 0x9E, 0x36, 0xB1, 0x1F, 0x14, 0x48, 0x8D, 0x73, 0x34, 0x55, 0x5E, 0x7D, 0x12, 0x33, + 0x44, 0x95, 0xBA, 0xBE, 0xDE, 0xF5, 0x67, 0xB2, 0xAD, 0x8B, 0xE8, 0x87, 0xD4, 0x4E, 0x70, 0xF3, 0x24, 0x8D, 0x01, 0xA3, + 0xD7, 0x5D, 0x2F, 0xA1, 0x76, 0x93, 0x66, 0x54, 0xD6, 0x5F, 0x4C, 0xB7, 0xC6, 0x96, 0x97, 0x27, 0x3C, 0x1C, 0x45, 0x81, + 0x11, 0xDC, 0x83, 0x17, 0xDB, 0x6C, 0x02, 0x0E, 0x25, 0x3D, 0xDC, 0x37, 0x95, 0xE4, 0x62, 0x66, 0x55, 0x11, 0x72, 0x95, + 0x35, 0xFD, 0x35, 0x66, 0x90, 0xF0, 0x92, 0x77, 0x9B, 0xB8, 0x25, 0x62, 0x66, 0x87, 0x3C, 0x2E, 0xBC, 0x78, 0xA5, 0x2B, + 0x42, 0xD4, 0xD7, 0xD4, 0x15, 0xB5, 0xB5, 0x0B, 0xAA, 0x94, 0x71, 0x47, 0xE4, 0xE6, 0x55, 0x14, 0x6D, 0xE6, 0x93, 0x73, + 0x35, 0xB3, 0x43, 0x52, 0x3D, 0x28, 0xA4, 0x78, 0x50, 0xB6, 0x30, 0xB7, 0xC7, 0xDC, 0x02, 0xAA, 0x9D, 0x67, 0x20, 0x7B, + 0x48, 0xC3, 0x89, 0x9E, 0x5D, 0x07, 0x50, 0x9D, 0x09, 0x38, 0xC8, 0x3A, 0xC8, 0x1F, 0x86, 0x51, 0x7D, 0x94, 0x05, 0xFC, + 0xDC, 0x04, 0x7D, 0xA5, 0xC6, 0x4B, 0x13, 0xED, 0x43, 0xD4, 0x0E, 0xCD, 0x53, 0xCA, 0x8C, 0x1F, 0x54, 0x25, 0x3E, 0x68, + 0x29, 0x16, 0xFB, 0xBB, 0x56, 0xFF, 0xC6, 0xB3, 0x48, 0xA7, 0x97, 0xDD, 0x04, 0x7A, 0x58, 0xE6, 0x28, 0x87, 0x2A, 0xAC, + 0xB3, 0xDE, 0x48, 0x4A, 0xBC, 0x03, 0x96, 0xAC, 0x8F, 0xF1, 0x37, 0xE4, 0x4C, 0xBD, 0x09, 0x9E, 0x77, 0xB0, 0x27, 0x2E, + 0x0C, 0xFD, 0x77, 0x8D, 0x4D, 0x7B, 0x0F, 0x8B, 0xCE, 0xDC, 0x18, 0xBC, 0x98, 0xD2, 0x2D, 0xC9, 0x92, 0x9C, 0x5B, 0x7D, + 0xCE, 0xF4, 0x17, 0x5F, 0x9C, 0xAF, 0x10, 0x5A, 0x54, 0xFC, 0x07, 0x0B, 0x47, 0x2E, 0x7D, 0x3F, 0xB3, 0x52, 0x55, 0x47, + 0xC2, 0xC0, 0xFE, 0x2C, 0xF9, 0x31, 0x06, 0x42, 0xBF, 0xED, 0x86, 0x0C, 0xBB, 0x24, 0xE4, 0x82, 0x45, 0x0B, 0x08, 0x57, + 0x17, 0x8A, 0x20, 0xCE, 0xED, 0x4C, 0x3C, 0x56, 0x30, 0x01, 0x49, 0x1D, 0x69, 0x31, 0x2D, 0x96, 0x8B, 0x2A, 0x02, 0xA5, + 0xF3, 0xA2, 0xAB, 0x95, 0x59, 0xCD, 0xDB, 0x62, 0xB3, 0x6F, 0xF1, 0x11, 0x78, 0x32, 0xB5, 0xA2, 0xFD, 0xC8, 0x81, 0x31, + 0x58, 0xB3, 0xFF, 0xA2, 0x4A, 0x35, 0x2C, 0xD7, 0x01, 0x2E, 0x18, 0x6D, 0xBA, 0x75, 0x10, 0x8D, 0x7E, 0x69, 0x10, 0x54, + 0x4B, 0x54, 0xB0, 0x66, 0x24, 0x25, 0xB2, 0x61, 0x7B, 0x41, 0x4C, 0x84, 0x32, 0x6A, 0x47, 0x6C, 0x6B, 0x77, 0xD4, 0x3F, + 0x5A, 0x7C, 0xE6, 0x49, 0xC4, 0x8D, 0x89, 0x71, 0xD4, 0x5D, 0x69, 0xD3, 0xCB, 0x16, 0xDF, 0x84, 0x6C, 0x7A, 0xE4, 0x60, + 0xF3, 0x43, 0xDF, 0x49, 0x3A, 0xB6, 0x60, 0x1C, 0x09, 0xF9, 0xB0, 0x3C, 0x39, 0x6A, 0x32, 0xC2, 0xBD, 0xC1, 0xAC, 0xE0, + 0x90, 0x79, 0x0E, 0xFA, 0x6A, 0x19, 0x92, 0x6F, 0x46, 0x6B, 0x45, 0x39, 0xB5, 0xF8, 0x0B, 0xCF, 0x65, 0xE4, 0x63, 0x4A, + 0xF8, 0x81, 0xDA, 0x1E, 0x17, 0x8C, 0x33, 0xA3, 0xCB, 0x9A, 0xEB, 0x1F, 0x10, 0x65, 0x1D, 0xC0, 0x62, 0xB1, 0xD2, 0x28, + 0x9A, 0x6B, 0xA8, 0x01, 0xCF, 0xDA, 0xE5, 0x14, 0x30, 0x5A, 0x76, 0x4C, 0x2E, 0x81, 0x94, 0xAE, 0xED, 0x59, 0xBB, 0x4C, + 0x79, 0x00, 0x8A, 0x68, 0x12, 0xDD, 0x2A, 0x5A, 0x00, 0x00, 0x00, 0x9C, 0x19, 0xA6, 0xF6, 0xEB, 0x4C, 0xD2, 0xFA, 0x22, + 0x7F, 0x2F, 0x23, 0x57, 0xF4, 0x01, 0x8D, 0x22, 0x15, 0x88, 0xEB, 0x96, 0xE9, 0x2C, 0x54, 0x6F, 0x77, 0xDE, 0x12, 0x5B, + 0x2C, 0x09, 0xFB, 0x60, 0x9D, 0x34, 0x61, 0xEA, 0xC0, 0x54, 0x90, 0x07, 0xA4, 0x66, 0x5A, 0x25, 0x64, 0xBD, 0xA4, 0xC4, + 0x64, 0xBB, 0x34, 0x37, 0x89, 0xA1, 0xEA, 0xA2, 0x13, 0xD6, 0x04, 0x94, 0xA9, 0xEF, 0x2C, 0xE6, 0x53, 0xE5, 0x45, 0x3F, + 0x02, 0x71, 0x30, 0x2F, 0x8E, 0xAC, 0x54, 0x46, 0x62, 0xD2, 0x78, 0xB4, 0x80, 0x9D, 0x1B, 0x9D, 0xC1, 0xF2, 0x46, 0x21, + 0xC3, 0x06, 0x33, 0x38, 0x63, 0xD3, 0xF3, 0x92, 0xD2, 0x13, 0xE5, 0xC2, 0xD3, 0x3D, 0xFE, 0xEE, 0x0C, 0xCF, 0x3C, 0x42, + 0xAA, 0x36, 0x3F, 0xB7, 0x25, 0xB4, 0x8B, 0x64, 0x51, 0x2F, 0x14, 0x29, 0xE3, 0x35, 0x15, 0xD2, 0x84, 0x13, 0xB2, 0x70, + 0xCE, 0x94, 0x92, 0x37, 0xA9, 0x4F, 0x92, 0x70, 0x33, 0x1D, 0x7D, 0xA1, 0xE2, 0x1B, 0x69, 0x5E, 0x3F, 0x54, 0x6D, 0x12, + 0xF1, 0xFB, 0x78, 0x9A, 0x6F, 0x6D, 0x6D, 0x22, 0x02, 0x9D, 0xF5, 0x2A, 0x46, 0x54, 0x15, 0xD4, 0x80, 0xCC, 0x60, 0xC4, + 0x52, 0xD6, 0x0E, 0x8C, 0xA0, 0xE6, 0xFE, 0xFF, 0x23, 0xBA, 0x74, 0xAC, 0x6B, 0x98, 0xED, 0x6B, 0x81, 0xFE, 0x1B, 0xEB, + 0x11, 0x75, 0x69, 0x5C, 0x15, 0x92, 0x16, 0xA9, 0x4B, 0xD8, 0xFC, 0xBE, 0x78, 0xB8, 0x39, 0x3D, 0xE8, 0xB5, 0x78, 0xFE, + 0x88, 0x56, 0x29, 0x00, 0x2A, 0x1A, 0x97, 0xD7, 0x99, 0x7E, 0x69, 0x2C, 0xAA, 0x52, 0xF7, 0x99, 0x50, 0x2A, 0x9D, 0xBB, + 0xE9, 0xD6, 0xA1, 0x90, 0x91, 0x76, 0xC1, 0x3B, 0x1A, 0x15, 0x3D, 0xB3, 0x5A, 0x35, 0x96, 0x00, 0x55, 0x51, 0xEE, 0xDC, + 0x3C, 0xD3, 0x36, 0x20, 0xC7, 0xA6, 0x35, 0xE7, 0x1D, 0x7F, 0x9E, 0x10, 0x54, 0x50, 0xA0, 0xFB, 0x7D, 0xFD, 0x45, 0x4B, + 0x7E, 0xAD, 0x38, 0xB3, 0xD8, 0x1B, 0x29, 0x38, 0x89, 0xE5, 0x77, 0x9F, 0x98, 0x12, 0x57, 0xF6, 0xF8, 0x4A, 0x81, 0x95, + 0x43, 0x7C, 0x21, 0x2D, 0xED, 0xD4, 0x42, 0x7F, 0x76, 0xFF, 0x97, 0xA6, 0x02, 0xCA, 0x8C, 0x1A, 0x77, 0x3F, 0xA6, 0x5D, + 0x67, 0x10, 0x1C, 0xB5, 0x43, 0xEA, 0x16, 0xDB, 0x88, 0xE3, 0x73, 0xE6, 0x1D, 0xAE, 0x8F, 0x0B, 0xB1, 0x50, 0x80, 0xC9, + 0xBC, 0xB0, 0xF5, 0xF2, 0xAA, 0xC2, 0xB7, 0x2F, 0x92, 0x99, 0x11, 0xB3, 0x25, 0x7D, 0xAC, 0x54, 0xE8, 0x43, 0xD6, 0x60, + 0xB7, 0xED, 0x97, 0x3F, 0xB4, 0x82, 0xF9, 0x0B, 0xA9, 0x3E, 0x6D, 0xC9, 0xB6, 0x7C, 0xC3, 0xFB, 0x65, 0x94, 0x2A, 0x3D, + 0xB5, 0xD4, 0x2E, 0x84, 0x56, 0x58, 0x2B, 0x45, 0x50, 0x67, 0xC4, 0xC0, 0x03, 0x8D, 0x6B, 0x54, 0xA2, 0x35, 0x06, 0xB6, + 0x63, 0x31, 0xA8, 0xEF, 0x1D, 0xE3, 0x19, 0xAB, 0x2E, 0xCB, 0x66, 0xF8, 0x96, 0x86, 0x89, 0x11, 0x2D, 0xEC, 0x9E, 0xE3, + 0xA5, 0xC9, 0x73, 0xF3, 0xE7, 0xAE, 0xC9, 0x94, 0xB3, 0x53, 0x6C, 0x01, 0x2C, 0xD6, 0xD5, 0x4F, 0x76, 0xEC, 0xC5, 0xCA, + 0x54, 0x25, 0xFC, 0xEC, 0x18, 0x2D, 0x2A, 0x22, 0x04, 0x39, 0x25, 0xDD, 0xD8, 0x63, 0x08, 0xE5, 0xE4, 0xBA, 0x8C, 0xD9, + 0xDF, 0xB9, 0x3C, 0x06, 0x05, 0x98, 0x82, 0xC4, 0xF1, 0xE4, 0xEA, 0xFA, 0x2F, 0xEA, 0xB1, 0xD3, 0x9A, 0xB1, 0x0D, 0x16, + 0xEF, 0x8A, 0xC6, 0x93, 0x37, 0x8E, 0xC7, 0x84, 0x8C, 0xEB, 0x10, 0x6F, 0x1D, 0x2D, 0x1B, 0x0C, 0x85, 0xFA, 0xC4, 0xCF, + 0xFC, 0x1A, 0x02, 0x48, 0x5B, 0x81, 0x32, 0x3D, 0x38, 0x08, 0x4C, 0x42, 0xC3, 0x6A, 0x75, 0xEA, 0x65, 0x0B, 0x3A, 0x38, + 0x48, 0x8B, 0xD5, 0xB2, 0x1F, 0x5C, 0xA1, 0xFE, 0x7C, 0xB6, 0x21, 0xF8, 0x59, 0x77, 0x49, 0xCE, 0xCD, 0x6E, 0x2A, 0xAD, + 0x7E, 0x51, 0x66, 0xAB, 0xCB, 0x45, 0x33, 0x9A, 0xBD, 0xAC, 0xC8, 0xE6, 0xEC, 0xAF, 0x14, 0x31, 0xF5, 0xA0, 0x43, 0x88, + 0x80, 0x44, 0x35, 0x7B, 0x96, 0xB4, 0x1A, 0x32, 0x64, 0x3F, 0x96, 0xB6, 0x11, 0xF2, 0x6D, 0x2D, 0xC3, 0xCB, 0x4B, 0xD5, + 0x40, 0xB2, 0x4A, 0x23, 0x26, 0xDB, 0xAD, 0xE8, 0x54, 0xB5, 0x62, 0x17, 0x21, 0x24, 0x94, 0xB0, 0xF8, 0x94, 0xB4, 0xF0, + 0x90, 0xFE, 0xFC, 0x94, 0x3B, 0x34, 0xD0, 0xC5, 0xC5, 0xB2, 0xEC, 0xB2, 0x75, 0x96, 0x13, 0xBA, 0x6D, 0xC9, 0xCF, 0x95, + 0xB4, 0x63, 0xE9, 0x37, 0xFE, 0xD0, 0x85, 0x2C, 0x0A, 0x53, 0xA9, 0x3F, 0x07, 0x4F, 0xBF, 0xC6, 0x30, 0xF4, 0x6A, 0xA5, + 0x8F, 0x1E, 0xCC, 0xF6, 0xD5, 0xB5, 0x32, 0xFA, 0x2F, 0x38, 0xD3, 0x11, 0xFD, 0xAF, 0x7A, 0x23, 0x61, 0x5E, 0xFC, 0xF6, + 0x77, 0xF5, 0x51, 0x47, 0xAD, 0xA1, 0xF4, 0xE3, 0x4E, 0x5C, 0x13, 0x32, 0xC7, 0x76, 0xF5, 0xE7, 0xF6, 0xF6, 0x20, 0x43, + 0x58, 0x3A, 0xA5, 0xEF, 0x4E, 0xF5, 0x63, 0xE2, 0xA8, 0xD3, 0xFD, 0xF7, 0xF7, 0xF7, 0x5E, 0xB8, 0xD8, 0x97, 0xFC, 0x75, + 0x54, 0xA9, 0xA6, 0x56, 0xB8, 0x23, 0x16, 0x7D, 0xF8, 0xB8, 0x50, 0xA3, 0xDC, 0x4A, 0x0D, 0x6D, 0xB1, 0x32, 0xE7, 0xBA, + 0x8C, 0x66, 0x86, 0x24, 0xFE, 0xBD, 0x7C, 0x8B, 0xC4, 0xCB, 0xD9, 0x89, 0x5D, 0x39, 0x4C, 0xD8, 0xF7, 0xA5, 0xF1, 0xA8, + 0xB6, 0xBE, 0x51, 0xA3, 0x44, 0x2A, 0xAB, 0x7D, 0xDE, 0xB8, 0xFF, 0x6F, 0xAF, 0x56, 0xD7, 0xB8, 0x5E, 0x9E, 0x77, 0x8D, + 0xF0, 0x96, 0xBB, 0x5A, 0xD5, 0x6D, 0x9C, 0x1A, 0x2E, 0x7D, 0xF6, 0xEE, 0x7E, 0xFC, 0x50, 0x16, 0x6D, 0x62, 0x59, 0x0F, + 0xC2, 0xD3, 0x88, 0xDE, 0xB6, 0x20, 0xFE, 0xFE, 0x7F, 0xFD, 0x24, 0x3A, 0x96, 0xBE, 0x5E, 0x73, 0x55, 0x0F, 0x66, 0x18, + 0xDE, 0xDA, 0xF7, 0xEF, 0xFE, 0xFE, 0x51, 0xF2, 0x22, 0x69, 0x89, 0x0B, 0xBC, 0x5D, 0x50, 0xC1, 0xA0, 0x42, 0xFF, 0xFF, + 0xD7, 0xEF, 0x80, 0x0C, 0x8D, 0x40, 0x08, 0xC4, 0x1C, 0x60, 0xBB, 0x67, 0x4E, 0x9C, 0x15, 0x6E, 0xAC, 0x68, 0xA7, 0xE1, + 0xED, 0x0C, 0xC2, 0x15, 0xEE, 0x85, 0xD4, 0xC3, 0x4E, 0x9C, 0xC3, 0x34, 0x57, 0x31, 0x83, 0xDE, 0xEB, 0xC7, 0x01, 0xE2, + 0x79, 0x81, 0xD5, 0xEB, 0x7B, 0xE3, 0x4A, 0x25, 0x28, 0x83, 0x57, 0x22, 0x01, 0xA8, 0x5B, 0x55, 0x78, 0x0B, 0x4F, 0xF5, + 0x2A, 0x09, 0x5C, 0x4A, 0xB9, 0x6E, 0xAD, 0x3E, 0x83, 0x09, 0xC8, 0x60, 0x79, 0x0C, 0x18, 0x5A, 0x1F, 0x4F, 0xD1, 0x74, + 0x2D, 0x64, 0x04, 0x61, 0xA2, 0x84, 0x96, 0x11, 0x8D, 0x8E, 0x26, 0x76, 0x93, 0x21, 0x7F, 0x39, 0x71, 0x35, 0xFE, 0x03, + 0x23, 0xAB, 0x24, 0xB4, 0x97, 0x2F, 0xD1, 0x70, 0x9F, 0xC4, 0xF1, 0x61, 0xAD, 0x46, 0x1A, 0xD5, 0x9F, 0x61, 0xC3, 0x35, + 0x16, 0xD7, 0x67, 0xB4, 0x60, 0xE7, 0xDB, 0x88, 0xD7, 0x63, 0x30, 0x18, 0x8D, 0x1E, 0x98, 0x08, 0x3B, 0x99, 0x38, 0xC2, + 0x0B, 0x47, 0x6D, 0x52, 0x76, 0xB7, 0x2D, 0x19, 0x62, 0x7D, 0x82, 0x19, 0x1D, 0x69, 0x50, 0x25, 0x58, 0xE6, 0x13, 0x42, + 0x3B, 0x1F, 0x5D, 0x13, 0x88, 0xA1, 0xBD, 0xB9, 0x52, 0x69, 0x3A, 0x5A, 0xC7, 0xC6, 0x2C, 0x1D, 0xF9, 0xC5, 0x89, 0xDF, + 0x1B, 0x08, 0x30, 0x6E, 0xFB, 0x28, 0x57, 0x4A, 0xC6, 0xC1, 0xE5, 0x74, 0xF9, 0xDB, 0x69, 0x36, 0xDB, 0xB0, 0x75, 0x60, + 0x6D, 0x2C, 0x5A, 0x98, 0x4E, 0xED, 0x52, 0x91, 0x52, 0x98, 0xB5, 0x9A, 0xAA, 0xD2, 0x0A, 0x50, 0x05, 0xD0, 0x0C, 0x28, + 0xA0, 0xC5, 0x36, 0xEF, 0x46, 0x67, 0xFC, 0x12, 0x09, 0x03, 0xF4, 0x65, 0xE9, 0x2E, 0x5D, 0x9A, 0x83, 0xC3, 0xDB, 0x80, + 0xDE, 0x13, 0xE7, 0x22, 0x55, 0xA0, 0xDD, 0x3F, 0x64, 0xF2, 0x01, 0x7D, 0xA3, 0x57, 0x5F, 0x79, 0x93, 0x0D, 0x7A, 0x86, + 0xC1, 0x93, 0x15, 0xF7, 0x56, 0x5C, 0x6D, 0xF6, 0x95, 0x9C, 0x91, 0x55, 0x33, 0x50, 0x74, 0x81, 0x20, 0xBC, 0x0C, 0x90, + 0x9E, 0x9C, 0xC7, 0xB8, 0x1E, 0x80, 0x56, 0x74, 0xC5, 0xDB, 0x2D, 0x72, 0x2C, 0x9F, 0xE3, 0x20, 0xB1, 0x52, 0x14, 0xF7, + 0x1D, 0x9E, 0xCB, 0x74, 0x28, 0xD9, 0x05, 0x23, 0xF5, 0x8E, 0xDF, 0x6D, 0x35, 0x30, 0xDD, 0xB5, 0x52, 0xF2, 0x5D, 0xB8, + 0xBE, 0x72, 0x3A, 0x9C, 0xA1, 0x19, 0xE4, 0x35, 0xD2, 0xB4, 0xD1, 0x26, 0x99, 0xC1, 0xAC, 0xD6, 0xBA, 0x7B, 0x42, 0xD6, + 0xEB, 0x9D, 0x6B, 0xCF, 0x58, 0x41, 0x7A, 0xBC, 0xE7, 0xF1, 0x5E, 0xE7, 0x1D, 0xDD, 0x96, 0x32, 0xFB, 0xB2, 0x6D, 0x4F, + 0x66, 0xA2, 0x2D, 0x65, 0xB2, 0xBE, 0xDB, 0x16, 0xB7, 0x72, 0xE9, 0xB3, 0x54, 0x72, 0x8E, 0x13, 0x21, 0x34, 0x50, 0xF6, + 0x16, 0x58, 0xFB, 0x5D, 0xB6, 0x35, 0x3C, 0x7B, 0x29, 0xB5, 0xBE, 0x9C, 0x43, 0x3C, 0x2E, 0x98, 0x4C, 0x47, 0x91, 0xA9, + 0x7C, 0x38, 0x3C, 0xA8, 0x3D, 0xE6, 0x4E, 0x91, 0xC9, 0x02, 0xB4, 0xC7, 0xAC, 0xF9, 0xA0, 0xFC, 0xF4, 0xFF, 0x0F, 0x78, + 0x0B, 0x5A, 0xA7, 0x89, 0xC3, 0x3A, 0xBD, 0xD7, 0x2D, 0x4A, 0x26, 0xDF, 0x13, 0x72, 0x31, 0x7B, 0xCB, 0x18, 0xBF, 0x92, + 0xFC, 0x6F, 0x17, 0xCA, 0xE8, 0x37, 0x19, 0xFD, 0xF5, 0x3B, 0x7E, 0x8F, 0xE0, 0x84, 0x25, 0x37, 0x51, 0xFA, 0xE2, 0x97, + 0xC9, 0xD7, 0x53, 0x11, 0xFA, 0x64, 0xB5, 0x5C, 0x37, 0x53, 0xF4, 0x2F, 0xF1, 0x96, 0x94, 0x8A, 0x01, 0xF7, 0xE9, 0xD4, + 0x08, 0x7D, 0xB8, 0xB7, 0x60, 0x66, 0x63, 0x3C, 0x74, 0x7E, 0x53, 0xD8, 0xAD, 0xF1, 0x60, 0xC1, 0x8D, 0x7E, 0xE3, 0x4A, + 0xFE, 0xA0, 0xAD, 0xCD, 0x50, 0xE9, 0x21, 0x28, 0x5C, 0x1D, 0x1F, 0xF1, 0xE5, 0x82, 0xC3, 0xF9, 0x20, 0xC0, 0x98, 0x12, + 0x67, 0xE4, 0xB7, 0xD1, 0x49, 0x6D, 0x23, 0x00, 0x04, 0x6D, 0x9F, 0x13, 0x88, 0x8D, 0xF3, 0x15, 0x6E, 0xAD, 0x30, 0x3F, + 0x76, 0xFC, 0xF2, 0x37, 0x28, 0xE8, 0x26, 0x5B, 0x0B, 0x80, 0xFE, 0x47, 0x14, 0x22, 0x7D, 0xE4, 0x06, 0x31, 0x65, 0xD8, + 0x3D, 0x41, 0x41, 0x33, 0xDD, 0xE3, 0x69, 0x1A, 0x65, 0x98, 0x63, 0xCC, 0x62, 0xD8, 0xFB, 0x44, 0xA1, 0x62, 0x6B, 0x38, + 0xD0, 0x2B, 0x34, 0xB8, 0x34, 0xB4, 0x0E, 0x2A, 0xA7, 0x67, 0xCE, 0xD7, 0x15, 0xC4, 0x50, 0x62, 0x75, 0xC7, 0x17, 0x28, + 0x39, 0x7A, 0x7C, 0xB8, 0x8F, 0x74, 0x78, 0x96, 0x6F, 0x4E, 0xEC, 0x30, 0x8D, 0x27, 0x67, 0x38, 0xFE, 0xAB, 0xFF, 0x90, + 0x8B, 0x86, 0x8F, 0x3F, 0x6B, 0x6F, 0xEC, 0x9C, 0x72, 0x8B, 0xD7, 0xF7, 0x56, 0x2D, 0x71, 0x00, 0xC6, 0xA9, 0x77, 0x70, + 0x3C, 0xFF, 0xA2, 0x0A, 0xE1, 0x23, 0xBA, 0x01, 0x59, 0xFC, 0x88, 0xCC, 0x48, 0x88, 0xFA, 0xD1, 0xBD, 0x6B, 0xA0, 0x68, + 0xE6, 0x81, 0xAD, 0xAF, 0x3F, 0xD9, 0x89, 0xBE, 0x49, 0xD6, 0xE4, 0xEE, 0x55, 0x46, 0xAC, 0x49, 0xE7, 0x80, 0x2D, 0x04, + 0x8D, 0xAB, 0xCF, 0xD7, 0xDC, 0x31, 0x94, 0x64, 0x21, 0xD6, 0x71, 0x4F, 0xE5, 0x83, 0x7B, 0x6C, 0xB3, 0xAF, 0x2D, 0x59, + 0xAD, 0x58, 0xF5, 0x34, 0x9A, 0xEF, 0x5A, 0x35, 0x8F, 0x81, 0x9A, 0x1E, 0x0E, 0x03, 0x10, 0x6A, 0x4F, 0x9F, 0xD4, 0xCA, + 0x4B, 0xEF, 0x78, 0x7E, 0x09, 0xFD, 0xB4, 0x68, 0x93, 0x06, 0x70, 0x7D, 0xEE, 0x12, 0xF4, 0xCB, 0x7C, 0x5D, 0x5D, 0x8A, + 0xE6, 0x83, 0x85, 0xBE, 0x44, 0xBE, 0x55, 0x3A, 0x4A, 0x6A, 0x76, 0x1B, 0x37, 0xFD, 0x8F, 0x99, 0x2E, 0x7E, 0x5D, 0x5F, + 0xF4, 0x0A, 0xCF, 0x19, 0x30, 0x8D, 0xC5, 0x4A, 0x17, 0x8C, 0xDF, 0xFD, 0x45, 0xF0, 0x2A, 0x8D, 0x25, 0xB1, 0x56, 0xA6, + 0x67, 0xB0, 0x34, 0xD8, 0x17, 0x23, 0x14, 0x69, 0x56, 0x91, 0x2E, 0xE5, 0x13, 0x10, 0x3D, 0xA2, 0x1A, 0xF1, 0x86, 0x06, + 0xF4, 0x5E, 0x5B, 0x85, 0x70, 0xF6, 0xA2, 0x8E, 0x96, 0xC2, 0xB5, 0xA3, 0xEB, 0xD3, 0xA3, 0xE7, 0x1F, 0xB6, 0x74, 0xE1, + 0x00, 0x4C, 0xA5, 0x64, 0xB4, 0xB2, 0x1D, 0xB7, 0x9A, 0xD3, 0x19, 0xD5, 0xD4, 0x93, 0x5A, 0x20, 0xEC, 0x2C, 0x9A, 0x59, + 0x5D, 0x02, 0xF1, 0x37, 0x8F, 0xBC, 0xAD, 0xE2, 0xFB, 0x97, 0xCF, 0x16, 0xFB, 0xFF, 0x5E, 0xD1, 0xDC, 0x50, 0xF9, 0xB8, + 0x2D, 0xDD, 0x81, 0xC7, 0x66, 0x5A, 0x1E, 0x47, 0xF6, 0x7E, 0xE4, 0x34, 0x64, 0x1D, 0xB5, 0xEE, 0x6F, 0x94, 0x5E, 0x42, + 0x23, 0xE8, 0x81, 0xA0, 0xA8, 0x11, 0x93, 0xE4, 0xDC, 0x32, 0x5D, 0x4C, 0xAD, 0xFF, 0xF4, 0x89, 0x9D, 0x1F, 0x27, 0xEC, + 0xD3, 0xE3, 0xA1, 0x0E, 0xC1, 0xDB, 0x91, 0xEE, 0xC8, 0x88, 0x36, 0xAA, 0xA0, 0x94, 0x8D, 0x5E, 0xF1, 0xF3, 0xB8, 0xFC, + 0xC2, 0x64, 0xB2, 0x4B, 0x64, 0x99, 0xC0, 0x7F, 0x15, 0xF4, 0xA6, 0x0F, 0xB0, 0xD5, 0xC1, 0xED, 0x4B, 0x47, 0x0D, 0x0E, + 0xAC, 0x75, 0xED, 0xAB, 0x36, 0xD2, 0x11, 0x5E, 0x9E, 0x3B, 0x7B, 0x61, 0x40, 0xF9, 0x01, 0xFA, 0x62, 0x7D, 0xAD, 0x9B, + 0xFB, 0x8B, 0x99, 0xB9, 0x29, 0x1A, 0x66, 0x88, 0xAC, 0x68, 0xF6, 0xEA, 0x9D, 0xD2, 0x88, 0xBB, 0xB6, 0x9F, 0xA6, 0xDA, + 0x44, 0xF7, 0x4B, 0xDA, 0xB8, 0xAB, 0xCB, 0xBF, 0x97, 0xF7, 0xA0, 0xAE, 0x5E, 0xFC, 0x67, 0x8B, 0xEA, 0x35, 0xC4, 0xD0, + 0x66, 0x15, 0x1F, 0x6D, 0x12, 0x9F, 0x7E, 0x1E, 0xF3, 0x88, 0x90, 0xCA, 0xAC, 0x32, 0xBF, 0x41, 0x44, 0xBC, 0xBF, 0xF2, + 0x9B, 0x72, 0x7A, 0x67, 0x16, 0xEC, 0x0E, 0xB5, 0x23, 0xB0, 0xA2, 0x77, 0x09, 0x4E, 0x63, 0xDA, 0xF8, 0x18, 0x37, 0x61, + 0x3B, 0xE8, 0x70, 0x22, 0xC9, 0x0E, 0x3F, 0x50, 0xE5, 0x09, 0x09, 0x5E, 0x60, 0x6A, 0xB8, 0xE1, 0xAB, 0x21, 0x3F, 0x34, + 0x48, 0x41, 0xE3, 0x05, 0x91, 0xC2, 0x2C, 0x41, 0xF7, 0x17, 0x35, 0xD4, 0x99, 0xE2, 0x07, 0xE2, 0xC4, 0x07, 0x49, 0x0D, + 0x02, 0x51, 0x47, 0xDE, 0xCD, 0xE8, 0x0C, 0x46, 0xB3, 0x60, 0x45, 0xB1, 0x1F, 0x24, 0xD6, 0xA4, 0x1E, 0x64, 0x57, 0x26, + 0xD0, 0xEF, 0x89, 0x8B, 0xF7, 0xCB, 0x47, 0x90, 0xBF, 0x7D, 0xD0, 0x51, 0x17, 0x35, 0x7F, 0x81, 0xDF, 0xA5, 0x0C, 0xFC, + 0xF6, 0xCA, 0x1F, 0x19, 0x5A, 0xAD, 0x47, 0xE3, 0xF2, 0xB8, 0x72, 0x61, 0x0A, 0x17, 0x01, 0xED, 0x77, 0xC9, 0xF8, 0x09, + 0x3B, 0xBF, 0x08, 0xBD, 0x2C, 0x6A, 0xB1, 0xFB, 0xA0, 0x67, 0x4A, 0xFD, 0x76, 0xC8, 0x80, 0x1B, 0x66, 0xA0, 0x02, 0x09, + 0xD6, 0x69, 0xEF, 0x88, 0xCD, 0x5E, 0xAA, 0x38, 0x2F, 0x2C, 0x8F, 0xE5, 0x8C, 0xF9, 0x26, 0x5E, 0x9A, 0x84, 0x3D, 0x3C, + 0x22, 0x3D, 0x41, 0x3A, 0x26, 0x69, 0x25, 0xA1, 0xCD, 0x48, 0x6F, 0x8D, 0x64, 0x0A, 0x4D, 0x33, 0xC8, 0xE1, 0x4C, 0x2F, + 0x58, 0xEA, 0x35, 0xB5, 0xE1, 0x06, 0x59, 0x2D, 0x18, 0x84, 0x99, 0xFF, 0x5B, 0x48, 0x38, 0x79, 0x05, 0x03, 0x82, 0x44, + 0x0E, 0xF3, 0xBC, 0x61, 0x08, 0x61, 0x44, 0x31, 0xA1, 0xF4, 0x45, 0x1F, 0x7C, 0xCD, 0xF5, 0x69, 0xAA, 0xF2, 0xB4, 0xFC, + 0x09, 0x60, 0x51, 0x57, 0x56, 0x12, 0x49, 0x4D, 0x27, 0xC2, 0x97, 0xDA, 0x2B, 0xD1, 0xBD, 0x65, 0x88, 0x63, 0x69, 0xD8, + 0x9B, 0xE1, 0x07, 0x9E, 0xE2, 0xC3, 0xF0, 0xFC, 0x7C, 0xF2, 0x34, 0xD8, 0x1D, 0xFF, 0x6E, 0x20, 0xCD, 0x1F, 0x4D, 0x0E, + 0xFD, 0x01, 0xBB, 0x04, 0x3C, 0xF7, 0x50, 0x77, 0x29, 0x8B, 0x03, 0xE9, 0x89, 0xB1, 0xA4, 0xA6, 0x30, 0xAB, 0x82, 0xAF, + 0x30, 0xC5, 0x85, 0x54, 0x3D, 0x71, 0x99, 0xBB, 0x9D, 0xC9, 0x14, 0xAB, 0x7C, 0xDC, 0x23, 0xB8, 0xB9, 0xC7, 0x87, 0xFE, + 0x3F, 0x94, 0xD5, 0xAC, 0x69, 0x10, 0x35, 0x58, 0xD0, 0xA6, 0xEF, 0x8E, 0x6F, 0x9E, 0x0F, 0x5B, 0x4B, 0xB3, 0xA2, 0x14, + 0x2B, 0x5E, 0x14, 0x8B, 0xE8, 0x68, 0x62, 0x94, 0xE4, 0xB0, 0xC1, 0xBB, 0x71, 0xE6, 0x2A, 0xB0, 0xAA, 0x3C, 0x78, 0x62, + 0x2A, 0x89, 0x48, 0x21, 0xE1, 0x35, 0xAC, 0xCF, 0x30, 0x38, 0x64, 0x03, 0x62, 0x30, 0xD8, 0xF6, 0x77, 0x8E, 0xCB, 0x56, + 0xC9, 0xB0, 0x69, 0x40, 0x59, 0xF7, 0xF5, 0xF2, 0xE7, 0x32, 0x85, 0x93, 0xB2, 0x8D, 0x6B, 0x91, 0x75, 0xB3, 0x9D, 0xA2, + 0xF3, 0x79, 0x65, 0x02, 0xEA, 0x54, 0xDD, 0xEA, 0x91, 0x6C, 0x78, 0x1B, 0x43, 0x9E, 0x43, 0xFF, 0x5A, 0x3B, 0xED, 0xD7, + 0x00, 0x55, 0x16, 0xEB, 0x56, 0xA4, 0xE9, 0x6B, 0xF3, 0xB2, 0x51, 0xDC, 0xB9, 0xB9, 0xA1, 0x89, 0x28, 0xF6, 0x8C, 0xAC, + 0x92, 0xD1, 0x87, 0x97, 0x7E, 0xEE, 0xBF, 0x99, 0xCF, 0x7E, 0xE8, 0xD7, 0xC6, 0x85, 0x43, 0xF3, 0x6B, 0x45, 0x6C, 0x9D, + 0x42, 0xDE, 0x54, 0x9E, 0xC6, 0x37, 0x97, 0xC7, 0x83, 0x33, 0x24, 0x0D, 0x75, 0xD4, 0x4A, 0x57, 0x41, 0xAA, 0xC5, 0xCE, + 0x3E, 0x70, 0xB5, 0x13, 0x38, 0x1C, 0x2F, 0x8A, 0x85, 0x7F, 0x68, 0x88, 0xCF, 0xB9, 0xF6, 0x7C, 0xDE, 0xBD, 0x58, 0xA9, + 0xE8, 0x53, 0xFE, 0xF8, 0x0C, 0x7D, 0x46, 0xBB, 0x41, 0x88, 0xC4, 0x4F, 0x62, 0x34, 0xD5, 0x5C, 0xB0, 0x1E, 0xE9, 0xFD, + 0x8D, 0x5E, 0x41, 0xEE, 0xC0, 0xBA, 0x27, 0xD1, 0x3B, 0x7F, 0xBF, 0xC6, 0xCF, 0x53, 0x7C, 0x4C, 0x06, 0xF5, 0xDF, 0x71, + 0x3E, 0xC2, 0x2E, 0x74, 0x76, 0xE4, 0xB7, 0x62, 0xAD, 0xF8, 0x8E, 0x6A, 0xA0, 0xD8, 0x0E, 0x42, 0x00, 0x2C, 0x28, 0xB6, + 0x05, 0xC1, 0x7C, 0x0D, 0x40, 0x14, 0x13, 0x93, 0x80, 0xFF, 0xA4, 0x15, 0x6F, 0xAA, 0xDF, 0x53, 0xFF, 0xBA, 0xDD, 0xB1, + 0xC4, 0xCA, 0xE8, 0x23, 0x59, 0x81, 0xA0, 0xF3, 0x89, 0xC3, 0x93, 0xE4, 0x84, 0x56, 0x35, 0xB7, 0x95, 0xDD, 0xC4, 0x07, + 0xD5, 0x4C, 0x76, 0x07, 0xED, 0xEC, 0x5F, 0xE6, 0xFB, 0xC4, 0xF0, 0x9D, 0x68, 0x62, 0x96, 0xC3, 0x57, 0x64, 0xE0, 0x41, + 0x0A, 0xC1, 0x08, 0x5E, 0xEA, 0xA6, 0x40, 0x8D, 0xB2, 0xA6, 0x4F, 0xD3, 0x8B, 0xB4, 0xDA, 0xF2, 0x83, 0x29, 0x0D, 0x45, + 0x9E, 0xCA, 0x49, 0x9D, 0x3B, 0x67, 0x46, 0xC3, 0x56, 0xA6, 0x17, 0x54, 0x26, 0x28, 0x53, 0x52, 0x18, 0xA3, 0x82, 0x0C, + 0xAF, 0xAF, 0xA0, 0x95, 0x36, 0xA8, 0x24, 0x17, 0xF0, 0x10, 0x33, 0xF2, 0x1C, 0x1D, 0x74, 0x63, 0xA5, 0xC0, 0xBC, 0x50, + 0x3E, 0x8C, 0xD1, 0x65, 0x65, 0x84, 0x2B, 0x93, 0xE0, 0x08, 0xBF, 0x8D, 0xF8, 0x60, 0x84, 0x8E, 0x7F, 0xE4, 0x9C, 0xAE, + 0x46, 0x87, 0xB2, 0xF7, 0x9C, 0xE8, 0xF3, 0x26, 0x45, 0x88, 0xCD, 0x7F, 0x5C, 0xDB, 0xD4, 0x65, 0xA3, 0x54, 0x93, 0xEC, + 0x88, 0x76, 0x2A, 0xDB, 0xE1, 0x6F, 0x39, 0xC3, 0x59, 0x10, 0x6A, 0x6D, 0xAF, 0x23, 0xE6, 0x09, 0x98, 0xDC, 0x0C, 0x2F, + 0xBB, 0x6F, 0xD2, 0x06, 0x6D, 0x93, 0x86, 0xC8, 0x0F, 0x87, 0xBA, 0x2D, 0x13, 0xC3, 0x7B, 0x4B, 0x06, 0x62, 0x42, 0x81, + 0x7D, 0x00, 0x6F, 0x71, 0xBE, 0x13, 0xBA, 0xA5, 0x3B, 0x51, 0xFB, 0x98, 0xCB, 0x45, 0x4B, 0x9C, 0xB8, 0xFC, 0xEF, 0x5F, + 0xCB, 0x41, 0xCB, 0x5E, 0x12, 0xE9, 0x75, 0x09, 0xA5, 0x47, 0x7F, 0xB8, 0x5F, 0xCF, 0x5A, 0xB5, 0x4F, 0x35, 0x07, 0xC2, + 0xE8, 0xD8, 0x4A, 0xE3, 0xE3, 0x20, 0xBE, 0x80, 0x24, 0x7D, 0x4D, 0x61, 0xF5, 0x3A, 0xA2, 0x96, 0xB5, 0x1A, 0x45, 0x49, + 0xAD, 0x26, 0xF6, 0xB7, 0x08, 0xF8, 0x24, 0x70, 0x44, 0xDE, 0xFB, 0xD7, 0x38, 0x19, 0x65, 0x3D, 0x1F, 0xD1, 0x61, 0x58, + 0x1D, 0x51, 0x0A, 0x97, 0xCE, 0xE7, 0xDA, 0x92, 0xAB, 0x1E, 0x82, 0xA0, 0x13, 0x0E, 0xFF, 0xC4, 0x81, 0x72, 0x44, 0xB1, + 0x16, 0x3F, 0x4C, 0xCA, 0xB4, 0x00, 0x4C, 0xA0, 0xC5, 0xD8, 0x33, 0x15, 0x48, 0xEF, 0x5E, 0xA1, 0x41, 0x9E, 0x94, 0x2B, + 0x37, 0xF7, 0x14, 0x03, 0xE4, 0xC5, 0xBD, 0x90, 0x9C, 0xA6, 0x1D, 0xCB, 0x46, 0x39, 0xAD, 0xA5, 0xF5, 0x45, 0xD1, 0xA1, + 0x62, 0xDA, 0x88, 0x81, 0x1D, 0xC5, 0x2F, 0xA0, 0x99, 0x96, 0xEE, 0x39, 0x94, 0x37, 0x1D, 0xB3, 0x18, 0xDA, 0xA4, 0x01, + 0x52, 0x58, 0xA4, 0x4C, 0xBE, 0x9B, 0xF4, 0x2E, 0x9D, 0x78, 0x10, 0x11, 0x95, 0x7C, 0xFE, 0x51, 0x9D, 0x7B, 0xD1, 0x89, + 0xDB, 0x46, 0x8E, 0x8E, 0x4A, 0x9D, 0x7F, 0x36, 0x69, 0x59, 0xE0, 0xF3, 0x75, 0x56, 0xC4, 0x70, 0x64, 0x6D, 0x7C, 0x89, + 0xC3, 0xB3, 0x44, 0xD1, 0x87, 0xA5, 0x90, 0xE4, 0x01, 0xC6, 0x09, 0x20, 0x56, 0x3F, 0x70, 0xFD, 0x69, 0xF3, 0x1A, 0x32, + 0xE9, 0x5B, 0xB4, 0xB4, 0xA4, 0xFF, 0x5E, 0xD7, 0xAB, 0x8A, 0x98, 0xF6, 0xBE, 0xAF, 0x66, 0x88, 0x62, 0x9C, 0x20, 0xE6, + 0xDB, 0x53, 0xFF, 0xC1, 0x44, 0xE9, 0x17, 0x3E, 0x15, 0x16, 0xC6, 0x6A, 0x4C, 0xBD, 0xC0, 0x4F, 0x5D, 0xF0, 0x39, 0xD1, + 0xAE, 0x3A, 0x38, 0xCE, 0xB8, 0x2E, 0x76, 0xCE, 0xDD, 0x51, 0xA6, 0x4F, 0xEE, 0xAC, 0xED, 0x1D, 0x3D, 0x9B, 0xFC, 0xDE, + 0x3F, 0x2E, 0xFF, 0xEE, 0x6F, 0x5E, 0xFE, 0xEC, 0xD1, 0xDC, 0x50, 0x18, 0x10, 0x04, 0x85, 0x31, 0x00, 0x3E, 0xE8, 0x42, + 0xE7, 0x15, 0x50, 0x24, 0x14, 0xDD, 0x58, 0x08, 0x49, 0xA5, 0x0E, 0x72, 0x5D, 0xF5, 0xE0, 0xA0, 0xEA, 0xEC, 0x4C, 0xCA, + 0xAC, 0xC0, 0x41, 0x12, 0xA6, 0x21, 0x80, 0x12, 0x80, 0x81, 0xE9, 0xD5, 0x67, 0xCA, 0x83, 0x24, 0x2F, 0xEF, 0x9E, 0x28, + 0x01, 0x13, 0x0F, 0xBC, 0xD5, 0x4E, 0x65, 0x9A, 0x6A, 0xB7, 0xA1, 0xCA, 0x24, 0x00, 0xF7, 0x64, 0xBC, 0x24, 0xBA, 0x90, + 0x92, 0x04, 0xC0, 0xA0, 0x5A, 0x79, 0x5A, 0x55, 0xF3, 0x9B, 0xEC, 0x32, 0x27, 0x0F, 0xE8, 0x59, 0x1B, 0x65, 0x20, 0x78, + 0xA6, 0x04, 0x67, 0x45, 0x12, 0xCA, 0xC3, 0x4A, 0x06, 0x52, 0x4B, 0xB3, 0x4D, 0xAB, 0x47, 0x67, 0x71, 0x82, 0xEF, 0x34, + 0xFC, 0xB9, 0xC9, 0x26, 0xA7, 0x70, 0xCB, 0x5D, 0x91, 0x26, 0xAC, 0x8F, 0xD7, 0x7A, 0xD3, 0x0B, 0xB9, 0x0F, 0x22, 0x0D, + 0xC0, 0x4B, 0x00, 0x03, 0x5C, 0x4B, 0x6E, 0x5C, 0xE3, 0x40, 0x69, 0x5F, 0x4B, 0x99, 0xE2, 0x18, 0x8B, 0x01, 0x8C, 0x28, + 0x59, 0x55, 0x62, 0xF6, 0xEA, 0xDE, 0x49, 0xCF, 0xD5, 0xE4, 0x57, 0x1A, 0xFC, 0xBB, 0x85, 0xC3, 0xD0, 0x2E, 0x6F, 0xB1, + 0x6B, 0x15, 0xED, 0x2B, 0x31, 0x80, 0xB2, 0xE9, 0x81, 0x04, 0x89, 0x60, 0xD9, 0x69, 0x63, 0x1B, 0x6A, 0xAF, 0x7F, 0xCE, + 0x1F, 0xE0, 0xB9, 0x4C, 0xA7, 0x4D, 0xCA, 0x4E, 0x98, 0x9C, 0x44, 0x6E, 0xF9, 0x01, 0xAC, 0x29, 0x7E, 0x73, 0x70, 0xDF, + 0x2F, 0xF0, 0x2E, 0x3C, 0xE9, 0x48, 0xCA, 0x0B, 0xC7, 0x1C, 0xA5, 0x0F, 0x12, 0xEC, 0x66, 0x4F, 0x1E, 0x6A, 0xCA, 0x3F, + 0xED, 0x0E, 0x2D, 0x8B, 0xDA, 0x03, 0x69, 0x97, 0xCA, 0xA3, 0x6C, 0xBB, 0x6B, 0x1A, 0x34, 0x8D, 0xE5, 0x2C, 0x25, 0x7E, + 0x72, 0x29, 0x58, 0x8E, 0x5F, 0xE2, 0x7F, 0xB6, 0xD3, 0x08, 0xDA, 0x66, 0x34, 0x8D, 0x93, 0x93, 0x3C, 0x56, 0xA6, 0xB4, + 0xF5, 0x66, 0xF1, 0x34, 0x96, 0xFF, 0x68, 0x6A, 0x52, 0x11, 0x9B, 0xF5, 0x3D, 0xF0, 0x98, 0x45, 0xED, 0x91, 0xF8, 0xEE, + 0x1F, 0xC6, 0x45, 0x89, 0x5E, 0xBF, 0x92, 0x49, 0xBC, 0xA8, 0xEB, 0xBF, 0x9B, 0xC6, 0xF4, 0x69, 0x16, 0x72, 0x69, 0x6A, + 0xB5, 0x03, 0x9A, 0xA0, 0xB5, 0x3E, 0x75, 0x3F, 0xD3, 0xA5, 0x15, 0x22, 0x06, 0x63, 0xEA, 0xC2, 0xA3, 0x68, 0x2A, 0xE7, + 0x46, 0x18, 0x44, 0x15, 0xD1, 0x34, 0xED, 0xD7, 0x82, 0xBA, 0x78, 0x9E, 0xFA, 0x71, 0xA6, 0x3A, 0x98, 0xFE, 0xCA, 0xB8, + 0x98, 0x2D, 0x41, 0xCD, 0x3A, 0x52, 0xEB, 0xC2, 0x27, 0x39, 0xE2, 0x09, 0x1D, 0xDB, 0xE7, 0xDB, 0x51, 0x37, 0x35, 0xF6, + 0x02, 0x56, 0xE4, 0x9B, 0x7A, 0x53, 0x6D, 0xAE, 0x88, 0x63, 0x66, 0x44, 0xEA, 0xD8, 0x7B, 0xC6, 0x93, 0x33, 0xF9, 0x9F, + 0x2B, 0x7C, 0x95, 0x17, 0x3C, 0x4E, 0xE9, 0x5D, 0xB2, 0x60, 0x77, 0xE5, 0x9A, 0x6B, 0xF6, 0x98, 0xC0, 0x7B, 0x9D, 0x31, + 0x31, 0x24, 0x2C, 0xE3, 0x12, 0x9C, 0x7A, 0x05, 0x1B, 0x96, 0xA1, 0x58, 0x34, 0x91, 0x94, 0x49, 0xBC, 0xF2, 0xC9, 0x36, + 0xE8, 0xD1, 0xF1, 0xD3, 0x46, 0xD0, 0x0E, 0x2A, 0x58, 0x5D, 0x18, 0x17, 0xB1, 0x4F, 0xA7, 0x4C, 0x11, 0x7F, 0x0E, 0xDC, + 0xE6, 0x13, 0x6F, 0x13, 0x83, 0xE2, 0x56, 0x19, 0xE2, 0xA3, 0xDB, 0xC8, 0xC6, 0xB4, 0xBB, 0x26, 0x67, 0x70, 0x84, 0xF7, + 0x7C, 0x7F, 0x5D, 0x04, 0x8A, 0x3B, 0x5E, 0xF0, 0x76, 0x62, 0x42, 0xBE, 0xB0, 0x5F, 0x79, 0xCF, 0x4C, 0x4B, 0xD7, 0xE4, + 0xEC, 0x1E, 0x66, 0xB8, 0x42, 0x66, 0x31, 0x3B, 0xB3, 0x72, 0x4E, 0xD9, 0x44, 0x5C, 0xEB, 0x13, 0x0A, 0x39, 0x65, 0x07, + 0xEB, 0xB2, 0x70, 0xFD, 0xFF, 0x8E, 0x24, 0xB5, 0x18, 0x4A, 0x48, 0x5F, 0xE7, 0x9A, 0xB4, 0xA1, 0xBF, 0x06, 0x8C, 0xD0, + 0xA6, 0x8F, 0x28, 0xBB, 0x1D, 0x3F, 0x40, 0x1A, 0xE6, 0x53, 0xC6, 0xA4, 0x88, 0x9C, 0x49, 0xC1, 0x00, 0x8C, 0x21, 0xEC, + 0x90, 0xF4, 0x49, 0x76, 0x67, 0x21, 0xEF, 0xB4, 0xC4, 0x6F, 0x11, 0xB7, 0x85, 0x83, 0xAD, 0xEF, 0x1A, 0xA1, 0x41, 0xB7, + 0xC7, 0xC3, 0x16, 0xC4, 0x03, 0x17, 0x18, 0x1D, 0xD6, 0x8B, 0xDE, 0x4F, 0x55, 0x56, 0x0E, 0x80, 0xEA, 0xF9, 0xA6, 0x36, + 0xBD, 0x80, 0x10, 0x60, 0x73, 0x5A, 0xF0, 0x57, 0x43, 0x59, 0x06, 0x90, 0xF2, 0x13, 0x07, 0x72, 0x4B, 0xAA, 0x53, 0x6B, + 0x53, 0x32, 0x1A, 0x35, 0x18, 0xC3, 0x95, 0x47, 0x7B, 0x30, 0xC9, 0x99, 0x7A, 0xEB, 0xF9, 0x00, 0x24, 0x98, 0xA3, 0x15, + 0xFF, 0xAA, 0xF1, 0x91, 0x7E, 0x71, 0xDA, 0x27, 0x0F, 0x4F, 0xDD, 0x28, 0xF3, 0x80, 0x15, 0x0F, 0x91, 0xA4, 0xB5, 0xD5, + 0x10, 0xB7, 0x55, 0xDF, 0x86, 0xF8, 0xD1, 0x3B, 0xF6, 0xA5, 0xE3, 0x71, 0x3E, 0x0B, 0xBD, 0x48, 0x11, 0x27, 0x15, 0xCF, + 0xB1, 0xE4, 0xD8, 0x69, 0x7B, 0x8E, 0xCB, 0x11, 0xD3, 0x5E, 0xB4, 0xDD, 0x90, 0x17, 0xCD, 0xB5, 0xB7, 0x2F, 0x54, 0x7F, + 0x76, 0x0B, 0x0C, 0x19, 0x49, 0xCF, 0xBC, 0x70, 0x91, 0xDC, 0xE5, 0x0C, 0x5D, 0x40, 0xD6, 0x28, 0x3E, 0x83, 0xFA, 0x64, + 0x1F, 0xBB, 0xFA, 0x88, 0xFF, 0x5A, 0xCC, 0xDE, 0x61, 0xCC, 0xCA, 0xCB, 0x8B, 0x86, 0xD0, 0xD9, 0xB3, 0xB2, 0x6C, 0x7C, + 0xA4, 0x89, 0x72, 0x8D, 0x5A, 0x30, 0x4D, 0xA9, 0x3D, 0x23, 0xD9, 0xC8, 0x32, 0xF1, 0x7D, 0x89, 0xEA, 0x4B, 0x2A, 0x69, + 0xFA, 0x4F, 0xEB, 0xCA, 0x03, 0x82, 0xD1, 0xD8, 0x33, 0xB3, 0x45, 0x99, 0xA5, 0xAB, 0xAD, 0x3E, 0x34, 0xC7, 0xDA, 0xB3, + 0xC3, 0x5E, 0xDA, 0x10, 0x57, 0x90, 0x33, 0x72, 0x3C, 0x02, 0xEA, 0x94, 0x34, 0xBC, 0x52, 0x70, 0xCE, 0x54, 0xCA, 0x9E, + 0xD4, 0x1E, 0x3F, 0x52, 0x35, 0xB2, 0xE2, 0xAD, 0x7D, 0x5A, 0xDF, 0x89, 0x43, 0xE1, 0x41, 0x74, 0x7A, 0x19, 0x36, 0xD5, + 0xB4, 0x47, 0xD4, 0x56, 0x24, 0xF2, 0x53, 0x4A, 0x4E, 0x51, 0xCF, 0xF8, 0x4A, 0xDF, 0xB8, 0x41, 0xF9, 0xB4, 0x18, 0x2F, + 0x72, 0xE5, 0x21, 0xE6, 0xBE, 0xD0, 0x82, 0xA4, 0xC1, 0x49, 0xC0, 0xA2, 0x6A, 0x1B, 0x8B, 0xC9, 0x33, 0xA1, 0x12, 0x30, + 0x44, 0xB5, 0x38, 0x28, 0xCA, 0x14, 0x93, 0x00, 0xE7, 0xE4, 0xFC, 0xEA, 0x71, 0xA5, 0xC4, 0xC4, 0x47, 0xF0, 0xF3, 0xA5, + 0x49, 0x6B, 0x55, 0xE2, 0x41, 0xC6, 0x7B, 0xCC, 0xE7, 0xF0, 0x89, 0xF7, 0x19, 0xB7, 0xE3, 0x24, 0xFE, 0x6A, 0x47, 0x74, + 0x4B, 0xC8, 0x66, 0x08, 0x03, 0xF8, 0x5C, 0x49, 0xCF, 0x2C, 0xFC, 0x0E, 0xE2, 0x17, 0xB3, 0x4B, 0x70, 0x69, 0xE6, 0x30, + 0x87, 0xFE, 0xD2, 0xD5, 0x82, 0x4D, 0xD0, 0x00, 0x56, 0x0F, 0xBF, 0x72, 0x79, 0x09, 0x86, 0x40, 0xD1, 0xF4, 0x5D, 0xC7, + 0x4F, 0xCA, 0x40, 0xFD, 0x7E, 0xBA, 0xB6, 0xDC, 0xF8, 0xDF, 0x18, 0xCD, 0x50, 0x9F, 0xD3, 0x5F, 0x02, 0x89, 0xAE, 0xED, + 0x56, 0x2D, 0x3A, 0xFD, 0xF5, 0x70, 0x40, 0x7D, 0x7E, 0xBD, 0x26, 0xB9, 0xAA, 0xAD, 0xB0, 0x9E, 0xD5, 0x34, 0x3C, 0xFF, + 0x0E, 0x4C, 0x2B, 0xF6, 0xF1, 0xFE, 0xBF, 0x29, 0xA3, 0x90, 0xE7, 0xA0, 0x55, 0x55, 0x34, 0xE7, 0x2E, 0xDC, 0x96, 0xE0, + 0xB9, 0x09, 0x19, 0xCD, 0x47, 0xFA, 0x58, 0xFE, 0xAF, 0x11, 0x5E, 0xAC, 0xC0, 0x52, 0x40, 0xEE, 0x73, 0xF2, 0x11, 0x39, + 0x03, 0x92, 0x91, 0x8A, 0x9B, 0x12, 0x56, 0xFC, 0xEE, 0x5F, 0x19, 0x0E, 0x35, 0xEF, 0x3A, 0xF3, 0xC2, 0x94, 0xE0, 0x40, + 0x30, 0x2D, 0x4E, 0x8A, 0x48, 0x46, 0x6F, 0xDB, 0xAF, 0x9F, 0x6F, 0x18, 0xEA, 0x97, 0x3C, 0x76, 0xA6, 0x44, 0x60, 0xF6, + 0xF1, 0x0F, 0x67, 0xCB, 0xAE, 0x9E, 0xE2, 0x1A, 0x5E, 0xA9, 0xF8, 0x22, 0x31, 0x1D, 0x19, 0xC6, 0xA3, 0x62, 0x6E, 0xDA, + 0x2F, 0x9D, 0xC9, 0x11, 0xC5, 0x7E, 0xB1, 0xFA, 0x1C, 0x63, 0xAE, 0xB3, 0xC4, 0x23, 0x66, 0xCA, 0x2E, 0x9C, 0xBF, 0xBF, + 0xFD, 0xFB, 0x3F, 0xBB, 0xED, 0xDB, 0xAF, 0x9F, 0xBD, 0xBB, 0x2F, 0x9B, 0xAD, 0x9B, 0xB7, 0xAF, 0xFC, 0xFA, 0x37, 0xAB, + 0xEC, 0xDA, 0xA7, 0x8F, 0xBC, 0xBA, 0x27, 0x8B, 0xAC, 0x9A, 0xBE, 0xBE, 0x7D, 0xF9, 0x3E, 0xBA, 0x6D, 0xD9, 0xAE, 0x9E, + 0x3D, 0xB9, 0x2E, 0x9A, 0x2D, 0x99, 0xB6, 0xAE, 0x7C, 0xF8, 0x36, 0xAA, 0x6C, 0xD8, 0xA6, 0x8E, 0x3C, 0xB8, 0x26, 0x8A, + 0x2C, 0x98, 0x1A, 0x3C, 0xC9, 0x82, 0x03, 0x3A, 0x97, 0x2A, 0x48, 0x35, 0xEB, 0x4E, 0x6D, 0xD3, 0xA7, 0x97, 0x6C, 0xE9, + 0xD3, 0x19, 0xE2, 0x6F, 0x39, 0x22, 0x9A, 0xDA, 0xE8, 0xC3, 0x65, 0xC3, 0xA6, 0x96, 0x7B, 0x59, 0x98, 0xA5, 0x34, 0x0C, + 0x15, 0x26, 0x9B, 0x2D, 0x69, 0xC2, 0x6C, 0xD2, 0x27, 0x95, 0x55, 0x2F, 0x54, 0xA0, 0x8D, 0x1D, 0xF2, 0xCF, 0xE0, 0xDB, + 0x4B, 0x03, 0x64, 0xC2, 0x26, 0x94, 0xBD, 0xB7, 0xF5, 0xF3, 0x3D, 0xB3, 0xE5, 0xD3, 0xAD, 0x97, 0xB5, 0xB3, 0x2D, 0x93, + 0xA5, 0x93, 0xB5, 0xA7, 0xF4, 0xF2, 0x35, 0xA3, 0xE4, 0xD2, 0xA5, 0x87, 0xB4, 0xB2, 0x25, 0x83, 0xA4, 0x92, 0xBC, 0xB6, + 0x75, 0xF1, 0x3C, 0xB2, 0x65, 0xD1, 0xAC, 0x96, 0x35, 0xB1, 0x2C, 0x92, 0x25, 0x91, 0xB4, 0xA6, 0x74, 0xF0, 0x34, 0xA2, + 0x64, 0xD0, 0xA4, 0x86, 0x34, 0xB0, 0x24, 0x82, 0x24, 0x90, 0x3C, 0x7F, 0xA3, 0x1E, 0x04, 0x86, 0x83, 0x72, 0xC6, 0x40, + 0x3C, 0xFD, 0x6B, 0x5B, 0x8F, 0x8F, 0x4C, 0xAF, 0x29, 0x7D, 0x88, 0xB4, 0x31, 0x31, 0x14, 0xB8, 0x67, 0x31, 0x63, 0x4B, + 0x8E, 0x8E, 0xE5, 0xBE, 0x84, 0x7C, 0x86, 0x22, 0x30, 0x5D, 0xC0, 0xE6, 0x22, 0x12, 0x6A, 0x5A, 0x0F, 0x8D, 0x25, 0x53, + 0xA7, 0xA3, 0x5D, 0x6A, 0x4E, 0xCC, 0x9D, 0xB3, 0xED, 0x11, 0x62, 0x4A, 0x0E, 0x8C, 0xBB, 0x3F, 0xDD, 0xEB, 0x3B, 0x3B, + 0xCD, 0xCB, 0xAB, 0x1F, 0x9D, 0xAB, 0x2B, 0x1B, 0x8D, 0x8B, 0xB3, 0x2F, 0xDC, 0xEA, 0x33, 0x2B, 0xCC, 0xCA, 0xA3, 0x0F, + 0x9C, 0xAA, 0x23, 0x0B, 0x8C, 0x8A, 0xBA, 0x3E, 0x5D, 0xE9, 0x3A, 0x3A, 0x4D, 0xC9, 0xAA, 0x1E, 0x1D, 0xA9, 0x2A, 0x1A, + 0x0D, 0x89, 0xB2, 0x2E, 0x5C, 0xE8, 0x32, 0x2A, 0x4C, 0xC8, 0xA2, 0x0E, 0x1C, 0xA8, 0x22, 0x0A, 0x0C, 0x88, 0x90, 0x79, + 0x97, 0x88, 0x79, 0x73, 0xC7, 0xC7, 0x16, 0x9C, 0x5B, 0x57, 0x69, 0x53, 0x87, 0x87, 0xF3, 0x14, 0xF4, 0xA4, 0x71, 0x63, + 0xC6, 0xC6, 0xF2, 0x38, 0x95, 0x79, 0x61, 0x43, 0x86, 0x86, 0x57, 0x63, 0x53, 0xB1, 0x78, 0x72, 0x47, 0xC5, 0x4D, 0xAC, + 0x4F, 0x1B, 0x68, 0x52, 0x07, 0x85, 0xA0, 0xC7, 0x58, 0xC7, 0x70, 0x62, 0x46, 0xC4, 0xB3, 0xFB, 0x6A, 0xAF, 0x60, 0x42, + 0x06, 0x84, 0xB9, 0x37, 0xD5, 0xE3, 0x39, 0x33, 0xC5, 0xC3, 0xA9, 0x17, 0x95, 0xA3, 0x29, 0x13, 0x85, 0x83, 0xB1, 0x27, + 0xD4, 0xE2, 0x31, 0x23, 0xC4, 0xC2, 0xA1, 0x07, 0x94, 0xA2, 0x21, 0x03, 0x84, 0x82, 0xB8, 0x36, 0x55, 0xE1, 0x38, 0x32, + 0x45, 0xC1, 0xA8, 0x16, 0x15, 0xA1, 0x28, 0x12, 0x05, 0x81, 0xB0, 0x26, 0x54, 0xE0, 0x30, 0x22, 0x44, 0xC0, 0xA0, 0x06, + 0x14, 0xA0, 0x20, 0x02, 0x04, 0x80, 0x96, 0x60, 0x6F, 0x25, 0xA4, 0x06, 0x97, 0xAE, 0xB6, 0xD2, 0x18, 0xCF, 0x4F, 0xD9, + 0xAB, 0x1F, 0x80, 0x98, 0x6E, 0x15, 0x53, 0x09, 0xEA, 0x0A, 0x32, 0x36, 0xE6, 0xCC, 0x47, 0xC9, 0xAA, 0x1E, 0x01, 0xF2, + 0x64, 0x02, 0x41, 0x38, 0xB0, 0x76, 0x51, 0x67, 0x80, 0xCF, 0x4E, 0xD8, 0x2B, 0x1D, 0x29, 0xE2, 0x5D, 0xA3, 0x54, 0xBE, + 0xB7, 0x7C, 0x73, 0xCD, 0x66, 0x81, 0x46, 0xC8, 0x2A, 0x1C, 0x9F, 0xBD, 0xF9, 0x7B, 0x1F, 0xB9, 0xE9, 0x5B, 0x8F, 0x9D, + 0xB9, 0x3B, 0x0F, 0x99, 0xA9, 0x1B, 0x97, 0xAD, 0xF8, 0x7A, 0x17, 0xA9, 0xE8, 0x5A, 0x87, 0x8D, 0xB8, 0x3A, 0x07, 0x89, + 0xA8, 0x1A, 0x9E, 0xBC, 0x79, 0x79, 0x1E, 0xB8, 0x69, 0x59, 0x8E, 0x9C, 0x39, 0x39, 0x0E, 0x98, 0x29, 0x19, 0x96, 0xAC, + 0x78, 0x78, 0x16, 0xA8, 0x68, 0x58, 0x86, 0x8C, 0x38, 0x38, 0x06, 0x88, 0x28, 0x18, 0x7C, 0x05, 0x5E, 0xC6, 0x26, 0xFF, + 0xA3, 0x28, 0x35, 0x87, 0x68, 0xCB, 0x4D, 0xD1, 0xA3, 0x17, 0x4A, 0x45, 0xAC, 0xEC, 0x57, 0x8F, 0x39, 0xEB, 0xF8, 0xBE, + 0x05, 0x4B, 0x45, 0xC1, 0xA2, 0x16, 0x42, 0xAB, 0x5A, 0x35, 0xFD, 0xE0, 0x9A, 0x01, 0x36, 0xB3, 0xEE, 0x1A, 0x4C, 0xD0, + 0x23, 0x15, 0x9F, 0x79, 0x7A, 0xEE, 0xAC, 0x9B, 0x9F, 0xAB, 0x05, 0x16, 0x8F, 0x62, 0x44, 0xC0, 0x22, 0x14, 0x9D, 0xB5, + 0xF1, 0x73, 0x1D, 0xB1, 0xE1, 0x53, 0x8D, 0x95, 0xB1, 0x33, 0x0D, 0x91, 0xA1, 0x13, 0x95, 0xA5, 0xF0, 0x72, 0x15, 0xA1, + 0xE0, 0x52, 0x85, 0x85, 0xB0, 0x32, 0x05, 0x81, 0xA0, 0x12, 0x9C, 0xB4, 0x71, 0x71, 0x1C, 0xB0, 0x61, 0x51, 0x8C, 0x94, + 0x31, 0x31, 0x0C, 0x90, 0x21, 0x11, 0x94, 0xA4, 0x70, 0x70, 0x14, 0xA0, 0x60, 0x50, 0x84, 0x84, 0x30, 0x30, 0x04, 0x80, + 0x20, 0x10, 0xE4, 0x9B, 0x48, 0x3B, 0x5B, 0x79, 0xCB, 0x4F, 0x94, 0xBC, 0xE8, 0x7D, 0x4B, 0x59, 0x8B, 0x0F, 0x53, 0x63, + 0x9A, 0x03, 0x53, 0x69, 0xCA, 0x4E, 0x1A, 0xCD, 0xC6, 0x93, 0x43, 0x49, 0x8A, 0x0E, 0xD8, 0x9F, 0x86, 0x8D, 0x5A, 0x78, + 0x4B, 0x4D, 0x8E, 0x03, 0xBC, 0xC2, 0x4A, 0x58, 0x0B, 0x0D, 0x73, 0x7C, 0xA9, 0x38, 0x52, 0x68, 0x4A, 0x4C, 0xBC, 0x8A, + 0x65, 0x73, 0x42, 0x48, 0x0A, 0x0C, 0x9B, 0x3D, 0xD9, 0x6B, 0x1B, 0x39, 0xC9, 0x4B, 0x8B, 0x1D, 0x99, 0x2B, 0x0B, 0x19, + 0x89, 0x0B, 0x93, 0x2D, 0xD8, 0x6A, 0x13, 0x29, 0xC8, 0x4A, 0x83, 0x0D, 0x98, 0x2A, 0x03, 0x09, 0x88, 0x0A, 0x9A, 0x3C, + 0x59, 0x69, 0x1A, 0x38, 0x49, 0x49, 0x8A, 0x1C, 0x19, 0x29, 0x0A, 0x18, 0x09, 0x09, 0x92, 0x2C, 0x58, 0x68, 0x12, 0x28, + 0x48, 0x48, 0x82, 0x0C, 0x18, 0x28, 0x02, 0x08, 0x08, 0x08, 0xDB, 0x2A, 0x0E, 0x87, 0x59, 0x71, 0xC3, 0x47, 0x4E, 0x8D, + 0x85, 0x25, 0x49, 0x51, 0x83, 0x07, 0xD1, 0x58, 0xAE, 0xDF, 0x51, 0x61, 0xC2, 0x46, 0x89, 0x9E, 0x1A, 0x19, 0x41, 0x41, + 0x82, 0x06, 0x58, 0xB5, 0x5B, 0x6F, 0x58, 0x70, 0x43, 0x45, 0x4F, 0x69, 0x6F, 0x9C, 0x48, 0x50, 0x03, 0x05, 0x98, 0xBF, + 0x28, 0x6E, 0x50, 0x60, 0x42, 0x44, 0x60, 0x39, 0x9E, 0xDB, 0x40, 0x40, 0x02, 0x04, 0x99, 0x35, 0xD1, 0x63, 0x19, 0x31, + 0xC1, 0x43, 0x89, 0x15, 0x91, 0x23, 0x09, 0x11, 0x81, 0x03, 0x91, 0x25, 0xD0, 0x62, 0x11, 0x21, 0xC0, 0x42, 0x81, 0x05, + 0x90, 0x22, 0x01, 0x01, 0x80, 0x02, 0x98, 0x34, 0x51, 0x61, 0x18, 0x30, 0x41, 0x41, 0x88, 0x14, 0x11, 0x21, 0x08, 0x10, + 0x01, 0x01, 0x90, 0x24, 0x50, 0x60, 0x10, 0x20, 0x40, 0x40, 0x80, 0x04, 0x10, 0x20, 0x00, 0x00, 0xF3, 0x6E, 0x80, 0x00, + 0x0C, 0x4C, 0x40, 0x05, 0x97, 0x9B, 0x10, 0x20, 0x40, 0x40, 0xF0, 0x65, 0x9C, 0xEB, 0x51, 0xEF, 0xE0, 0xCE, 0x88, 0xE8, + 0x90, 0x63, 0x9F, 0xD2, 0xC3, 0x69, 0x7E, 0xC4, 0x41, 0x6E, 0xB6, 0x85, 0x8C, 0xCC, 0xA1, 0xFD, 0x90, 0xD9, 0x11, 0x21, + 0x6C, 0xC9, 0x95, 0xC7, 0x52, 0x68, 0x60, 0xEA, 0xEA, 0x06, 0x09, 0x35, 0xA2, 0x01, 0xA0, 0x53, 0x80, 0x03, 0xF9, 0x74, + 0x5D, 0x6E, 0xE0, 0x53, 0x16, 0x60, 0xDB, 0x36, 0xB1, 0x22, 0xE7, 0x68, 0x44, 0x44, 0x29, 0xA2, 0xF0, 0x21, 0xA0, 0xF2, + 0xA7, 0x82, 0xB0, 0xD6, 0x16, 0x4F, 0x58, 0x48, 0x8B, 0x35, 0xA8, 0x54, 0x53, 0xA8, 0x9A, 0x43, 0xFD, 0x86, 0x49, 0x2C, + 0x31, 0x43, 0x42, 0x5E, 0xDA, 0x04, 0xA3, 0xE3, 0xD2, 0x2A, 0x9D, 0x77, 0x6D, 0x64, 0xF1, 0x85, 0x64, 0x28, 0xF9, 0x62, + 0xD7, 0x23, 0x49, 0xB3, 0x39, 0x2B, 0xA9, 0xE0, 0x08, 0xF3, 0x39, 0xFA, 0x08, 0xD5, 0x6A, 0x4A, 0x0B, 0x97, 0xD8, 0xC3, + 0xFB, 0x65, 0xE5, 0xE2, 0x62, 0x99, 0xD0, 0x08, 0xBA, 0x2F, 0x1A, 0x38, 0x49, 0x49, 0xD2, 0xAB, 0x3A, 0x59, 0x03, 0x7B, + 0x2F, 0x1A, 0x79, 0x8F, 0x9B, 0xCC, 0x6B, 0x29, 0xC8, 0x4A, 0x99, 0x25, 0x7B, 0x6C, 0x24, 0xE8, 0xD1, 0x0E, 0x83, 0x50, + 0xFA, 0x0B, 0x1B, 0x39, 0xC9, 0x4B, 0xE3, 0xD5, 0xDB, 0xA0, 0xEA, 0xEA, 0xD5, 0x83, 0xFA, 0x9C, 0xE1, 0x23, 0x8D, 0x6A, + 0x3D, 0x5C, 0x22, 0xE8, 0x56, 0xBB, 0x75, 0x97, 0xB2, 0x41, 0x4E, 0x05, 0x99, 0x25, 0x8E, 0x3E, 0xE9, 0x93, 0x1A, 0x7C, + 0x2B, 0x21, 0x83, 0x49, 0xF0, 0xD0, 0x6C, 0x33, 0x47, 0x6C, 0xBB, 0xCB, 0x6E, 0xC9, 0x7B, 0xCE, 0xA5, 0x67, 0x3B, 0x9F, + 0x21, 0x4E, 0x1F, 0xAD, 0x93, 0x20, 0xA5, 0xFD, 0xCB, 0xFC, 0xAB, 0xBB, 0x71, 0x2D, 0x04, 0x80, 0x78, 0xF8, 0x56, 0x72, + 0x20, 0xFD, 0x2C, 0xF0, 0x20, 0x5F, 0x14, 0x8F, 0x91, 0x8F, 0xDE, 0xB0, 0x26, 0xE9, 0xEC, 0xD5, 0xDC, 0xBA, 0x18, 0x52, + 0xE3, 0x19, 0x5C, 0xB1, 0xA9, 0x33, 0x4F, 0x28, 0x82, 0x11, 0xC4, 0xD1, 0x91, 0x22, 0x75, 0xE5, 0x9C, 0xD9, 0x6E, 0x21, + 0xFC, 0x53, 0x02, 0x1D, 0x23, 0x3B, 0x70, 0x77, 0x31, 0xEC, 0x8E, 0x53, 0x63, 0x59, 0x19, 0x83, 0xF7, 0x73, 0x72, 0xCC, + 0xC9, 0x91, 0xC4, 0xFC, 0xB7, 0x33, 0xAB, 0x64, 0x62, 0xC5, 0x0B, 0xF0, 0x74, 0x74, 0x77, 0x8E, 0x10, 0xD5, 0x14, 0x50, + 0x3F, 0x69, 0x4F, 0xCF, 0x7F, 0x17, 0xA8, 0xD0, 0xF6, 0x52, 0xED, 0x4B, 0x5B, 0xCA, 0x2D, 0x66, 0xB4, 0x56, 0xE2, 0xED, + 0xE4, 0x56, 0xC6, 0xA3, 0x50, 0x38, 0xE1, 0x74, 0x76, 0x74, 0x5D, 0xAA, 0xF0, 0x57, 0x5D, 0xC9, 0x2B, 0x67, 0x02, 0xE5, + 0xF5, 0x77, 0xBB, 0x78, 0x74, 0x17, 0xE6, 0xCD, 0x85, 0xB3, 0xF0, 0x58, 0x20, 0x57, 0xC1, 0x88, 0xAC, 0x68, 0x04, 0x9C, + 0x8A, 0x14, 0x37, 0xFE, 0x78, 0x79, 0x1A, 0x5A, 0xC5, 0xD4, 0xB9, 0xB1, 0xFE, 0xDE, 0x67, 0xC8, 0x1D, 0x17, 0x00, 0x6F, + 0x3A, 0x12, 0x77, 0xE9, 0xFD, 0xD1, 0x30, 0xA4, 0x28, 0x2A, 0x45, 0x67, 0x0A, 0x1B, 0xF7, 0xFF, 0x46, 0xB1, 0x67, 0x3B, + 0xE0, 0x26, 0x37, 0x1B, 0x7C, 0x5C, 0xED, 0x02, 0x91, 0xB3, 0xB9, 0x4E, 0x3F, 0x38, 0xF6, 0xFB, 0x7A, 0x38, 0xC5, 0xAA, + 0xD8, 0x32, 0xEB, 0xDC, 0xAC, 0x0B, 0x84, 0x26, 0x84, 0x60, 0x5E, 0xC0, 0xF4, 0x42, 0xDE, 0xFC, 0x7B, 0x7D, 0x60, 0xD7, + 0x7A, 0xB5, 0xFF, 0x23, 0x16, 0x33, 0x6F, 0xCE, 0x15, 0x1C, 0xA3, 0xC9, 0xDE, 0x7E, 0x1F, 0x47, 0x50, 0xCA, 0xB4, 0xB2, + 0xE2, 0x80, 0xF7, 0x5B, 0x6C, 0x78, 0xDF, 0xFD, 0xFB, 0x7F, 0x7E, 0x1F, 0x54, 0x2B, 0xD8, 0xEB, 0x94, 0x1B, 0x30, 0x05, + 0x27, 0x30, 0xB4, 0xCE, 0x56, 0x2D, 0xD7, 0x16, 0x05, 0x59, 0xA8, 0xEA, 0x14, 0xE3, 0x00, 0x62, 0x41, 0xCE, 0xED, 0x56, + 0x31, 0xEA, 0x04, 0x03, 0xEF, 0xA6, 0xA1, 0xFF, 0x15, 0x59, 0x49, 0xA1, 0xCD, 0x9F, 0xE9, 0xC8, 0xD2, 0xE2, 0x96, 0xEE, + 0x95, 0xE0, 0xAD, 0xD1, 0xEE, 0xA7, 0x01, 0x63, 0xCD, 0xCC, 0xAB, 0xB3, 0xD9, 0x34, 0x8C, 0xC2, 0xFA, 0xA4, 0x70, 0x58, + 0x06, 0x50, 0x9F, 0x80, 0xD9, 0x59, 0x74, 0x82, 0x50, 0x84, 0x8A, 0x4D, 0xC9, 0x2E, 0x18, 0xD2, 0x1B, 0x72, 0xE8, 0x6C, + 0x57, 0x31, 0x27, 0x67, 0x51, 0xE5, 0xCD, 0x01, 0x05, 0x52, 0xE4, 0x81, 0x7C, 0xEA, 0xD9, 0xC1, 0x41, 0xE1, 0x58, 0x43, + 0x53, 0xC1, 0x0F, 0x57, 0xEC, 0x01, 0x41, 0xF4, 0xE8, 0xA6, 0x7C, 0x69, 0xD3, 0x73, 0xEA, 0x8A, 0xC7, 0xA9, 0xC2, 0xBC, + 0x8B, 0x8F, 0xF9, 0x0E, 0x63, 0xA8, 0x6D, 0x02, 0x33, 0xE8, 0x88, 0xC1, 0xA7, 0x77, 0xBA, 0x1E, 0x10, 0x0B, 0xBA, 0xF6, + 0x1B, 0x54, 0x72, 0xAD, 0x2E, 0x49, 0xA3, 0x4C, 0xE2, 0x56, 0x8B, 0xA9, 0x53, 0x65, 0x78, 0x4D, 0x9A, 0xEA, 0xF3, 0x2F, + 0x21, 0xCC, 0x4C, 0xD1, 0xDA, 0xAA, 0xBB, 0xF9, 0x21, 0xCA, 0x39, 0xE9, 0x8F, 0x76, 0x43, 0xB9, 0xC4, 0xAF, 0xC0, 0xC0, + 0x2A, 0xA9, 0xE2, 0x38, 0xE5, 0x5A, 0x22, 0x4E, 0x6E, 0x21, 0xF7, 0xAC, 0xA4, 0x80, 0x82, 0x48, 0xBC, 0x8F, 0x6B, 0xA9, + 0xDD, 0x22, 0x5D, 0x56, 0x19, 0xAD, 0xD2, 0xD9, 0x30, 0x8D, 0x52, 0xDC, 0xD8, 0xCA, 0x1D, 0xD4, 0xE5, 0x38, 0x1C, 0xCB, + 0x9E, 0x3F, 0x83, 0xEF, 0xC2, 0x19, 0x5B, 0xCD, 0x01, 0x01, 0xD9, 0xA8, 0x63, 0x24, 0xF8, 0x60, 0x87, 0xED, 0xBB, 0x7B, + 0xBF, 0x42, 0x04, 0x5B, 0x5A, 0xC8, 0x24, 0x82, 0x24, 0x90, 0xA0, 0x74, 0x77, 0x90, 0x6E, 0xBF, 0xC7, 0xD6, 0x6B, 0x0B, + 0x72, 0xF0, 0x2C, 0x92, 0x25, 0xF4, 0x27, 0x74, 0xB7, 0xBB, 0xBC, 0x50, 0xC4, 0x2E, 0xBC, 0x8E, 0x89, 0xE1, 0x25, 0x83, + 0xA4, 0x92, 0x5E, 0xF8, 0xF7, 0x6D, 0x39, 0xCD, 0x45, 0x5A, 0xA6, 0xD5, 0x0B, 0xB0, 0x77, 0x8E, 0x06, 0x95, 0x4B, 0x67, + 0xF9, 0xBC, 0x77, 0xB2, 0x06, 0x59, 0x7D, 0xB7, 0x85, 0x06, 0x97, 0xFD, 0xD8, 0x9A, 0x84, 0x82, 0xB6, 0x29, 0xB4, 0xE7, + 0x41, 0x96, 0xF4, 0xE6, 0x76, 0xF4, 0xCF, 0xDA, 0xFB, 0xA5, 0x53, 0x53, 0x39, 0x3F, 0x43, 0xAC, 0x9A, 0x57, 0xFC, 0xF6, + 0x77, 0xF5, 0x0D, 0x45, 0x5A, 0xD7, 0x9D, 0xE0, 0x4F, 0xB9, 0xF1, 0xAD, 0xC2, 0x0A, 0xF5, 0xE7, 0xF6, 0xF6, 0x4E, 0xDF, + 0x7F, 0xE7, 0x3A, 0x55, 0xB2, 0xCE, 0x65, 0xFA, 0xA7, 0xDC, 0xFD, 0xF7, 0xF7, 0xF7, 0x2A, 0xE4, 0x8D, 0x10, 0xC6, 0xCA, + 0x48, 0x35, 0x32, 0x54, 0x91, 0x52, 0xB3, 0x2A, 0x7C, 0x69, 0x2A, 0x78, 0x2D, 0x99, 0xD6, 0x1C, 0x34, 0xDF, 0x1E, 0x43, + 0x6D, 0x42, 0x16, 0x1C, 0xA2, 0xA6, 0xA7, 0x69, 0x0D, 0x12, 0xDF, 0x0D, 0xBD, 0xE2, 0xCC, 0xF7, 0x4F, 0xA1, 0x68, 0xA7, + 0x7B, 0xFD, 0x2F, 0x9B, 0xAD, 0x9B, 0x97, 0xCF, 0xB9, 0xB4, 0x17, 0xC9, 0x12, 0x04, 0x17, 0x0C, 0x35, 0x8B, 0x8E, 0x79, + 0xAB, 0xDB, 0x9E, 0xEA, 0xBB, 0x9B, 0xE1, 0x68, 0x6F, 0xBF, 0xF6, 0xEE, 0x7E, 0xFC, 0xAE, 0xDA, 0x5F, 0x10, 0xFD, 0x23, + 0x73, 0xF3, 0xF6, 0x3F, 0xCE, 0x57, 0xFE, 0xFE, 0x7F, 0xFD, 0xCF, 0x68, 0xD1, 0xFE, 0x38, 0xDE, 0xB8, 0xBE, 0x4D, 0x09, + 0xCA, 0xD8, 0xF7, 0xEF, 0xFE, 0xFE, 0x90, 0x5F, 0xAF, 0x0E, 0x9F, 0x99, 0x1D, 0x41, 0x90, 0x19, 0x6D, 0x97, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x10, 0x20, 0x10, 0x20, 0x40, 0x40, 0x90, 0x24, 0x50, 0x60, 0x08, 0x10, + 0x01, 0x01, 0x88, 0x14, 0x11, 0x21, 0x18, 0x30, 0x41, 0x41, 0x98, 0x34, 0x51, 0x61, 0x01, 0x01, 0x80, 0x02, 0x81, 0x05, + 0x90, 0x22, 0x11, 0x21, 0xC0, 0x42, 0x91, 0x25, 0xD0, 0x62, 0x09, 0x11, 0x81, 0x03, 0x89, 0x15, 0x91, 0x23, 0x19, 0x31, + 0xC1, 0x43, 0x99, 0x35, 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, + 0x52, 0x64, 0x48, 0x50, 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, + 0x82, 0x06, 0xC1, 0x45, 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, + 0x93, 0x27, 0x59, 0x71, 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0x02, 0x08, 0x08, 0x08, 0x82, 0x0C, 0x18, 0x28, 0x12, 0x28, + 0x48, 0x48, 0x92, 0x2C, 0x58, 0x68, 0x0A, 0x18, 0x09, 0x09, 0x8A, 0x1C, 0x19, 0x29, 0x1A, 0x38, 0x49, 0x49, 0x9A, 0x3C, + 0x59, 0x69, 0x03, 0x09, 0x88, 0x0A, 0x83, 0x0D, 0x98, 0x2A, 0x13, 0x29, 0xC8, 0x4A, 0x93, 0x2D, 0xD8, 0x6A, 0x0B, 0x19, + 0x89, 0x0B, 0x8B, 0x1D, 0x99, 0x2B, 0x1B, 0x39, 0xC9, 0x4B, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, + 0x1A, 0x2C, 0x52, 0x68, 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, + 0x4B, 0x4D, 0xDA, 0x7C, 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, + 0xDA, 0x6E, 0x4B, 0x59, 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, + 0x20, 0x10, 0x84, 0x84, 0x30, 0x30, 0x14, 0xA0, 0x60, 0x50, 0x94, 0xA4, 0x70, 0x70, 0x0C, 0x90, 0x21, 0x11, 0x8C, 0x94, + 0x31, 0x31, 0x1C, 0xB0, 0x61, 0x51, 0x9C, 0xB4, 0x71, 0x71, 0x05, 0x81, 0xA0, 0x12, 0x85, 0x85, 0xB0, 0x32, 0x15, 0xA1, + 0xE0, 0x52, 0x95, 0xA5, 0xF0, 0x72, 0x0D, 0x91, 0xA1, 0x13, 0x8D, 0x95, 0xB1, 0x33, 0x1D, 0xB1, 0xE1, 0x53, 0x9D, 0xB5, + 0xF1, 0x73, 0x44, 0xC0, 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, + 0x23, 0x15, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, + 0xB2, 0x36, 0x55, 0xE1, 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, + 0xE3, 0x57, 0xDD, 0xF5, 0xF3, 0x77, 0x06, 0x88, 0x28, 0x18, 0x86, 0x8C, 0x38, 0x38, 0x16, 0xA8, 0x68, 0x58, 0x96, 0xAC, + 0x78, 0x78, 0x0E, 0x98, 0x29, 0x19, 0x8E, 0x9C, 0x39, 0x39, 0x1E, 0xB8, 0x69, 0x59, 0x9E, 0xBC, 0x79, 0x79, 0x07, 0x89, + 0xA8, 0x1A, 0x87, 0x8D, 0xB8, 0x3A, 0x17, 0xA9, 0xE8, 0x5A, 0x97, 0xAD, 0xF8, 0x7A, 0x0F, 0x99, 0xA9, 0x1B, 0x8F, 0x9D, + 0xB9, 0x3B, 0x1F, 0xB9, 0xE9, 0x5B, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, + 0x6A, 0x5C, 0xD6, 0xEC, 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, + 0x7B, 0x7D, 0x47, 0xC9, 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, + 0xAB, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x20, 0x02, 0x04, 0x80, 0xA0, 0x06, + 0x14, 0xA0, 0x30, 0x22, 0x44, 0xC0, 0xB0, 0x26, 0x54, 0xE0, 0x28, 0x12, 0x05, 0x81, 0xA8, 0x16, 0x15, 0xA1, 0x38, 0x32, + 0x45, 0xC1, 0xB8, 0x36, 0x55, 0xE1, 0x21, 0x03, 0x84, 0x82, 0xA1, 0x07, 0x94, 0xA2, 0x31, 0x23, 0xC4, 0xC2, 0xB1, 0x27, + 0xD4, 0xE2, 0x29, 0x13, 0x85, 0x83, 0xA9, 0x17, 0x95, 0xA3, 0x39, 0x33, 0xC5, 0xC3, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, + 0x06, 0x84, 0xE0, 0x46, 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, + 0x17, 0xA5, 0x78, 0x72, 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, + 0xC6, 0xC6, 0xF1, 0x67, 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, + 0xD7, 0xE7, 0x22, 0x0A, 0x0C, 0x88, 0xA2, 0x0E, 0x1C, 0xA8, 0x32, 0x2A, 0x4C, 0xC8, 0xB2, 0x2E, 0x5C, 0xE8, 0x2A, 0x1A, + 0x0D, 0x89, 0xAA, 0x1E, 0x1D, 0xA9, 0x3A, 0x3A, 0x4D, 0xC9, 0xBA, 0x3E, 0x5D, 0xE9, 0x23, 0x0B, 0x8C, 0x8A, 0xA3, 0x0F, + 0x9C, 0xAA, 0x33, 0x2B, 0xCC, 0xCA, 0xB3, 0x2F, 0xDC, 0xEA, 0x2B, 0x1B, 0x8D, 0x8B, 0xAB, 0x1F, 0x9D, 0xAB, 0x3B, 0x3B, + 0xCD, 0xCB, 0xBB, 0x3F, 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, + 0x5E, 0xEC, 0x6A, 0x5A, 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, + 0x8E, 0x8E, 0xE3, 0x4F, 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, + 0x9F, 0xAF, 0x7B, 0x7B, 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x24, 0x82, 0x24, 0x90, 0xA4, 0x86, 0x34, 0xB0, 0x34, 0xA2, + 0x64, 0xD0, 0xB4, 0xA6, 0x74, 0xF0, 0x2C, 0x92, 0x25, 0x91, 0xAC, 0x96, 0x35, 0xB1, 0x3C, 0xB2, 0x65, 0xD1, 0xBC, 0xB6, + 0x75, 0xF1, 0x25, 0x83, 0xA4, 0x92, 0xA5, 0x87, 0xB4, 0xB2, 0x35, 0xA3, 0xE4, 0xD2, 0xB5, 0xA7, 0xF4, 0xF2, 0x2D, 0x93, + 0xA5, 0x93, 0xAD, 0x97, 0xB5, 0xB3, 0x3D, 0xB3, 0xE5, 0xD3, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, + 0x36, 0xB4, 0x74, 0xE2, 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, + 0x67, 0xD5, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, + 0xF6, 0xF6, 0x6D, 0xD3, 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x8A, + 0x2C, 0x98, 0xA6, 0x8E, 0x3C, 0xB8, 0x36, 0xAA, 0x6C, 0xD8, 0xB6, 0xAE, 0x7C, 0xF8, 0x2E, 0x9A, 0x2D, 0x99, 0xAE, 0x9E, + 0x3D, 0xB9, 0x3E, 0xBA, 0x6D, 0xD9, 0xBE, 0xBE, 0x7D, 0xF9, 0x27, 0x8B, 0xAC, 0x9A, 0xA7, 0x8F, 0xBC, 0xBA, 0x37, 0xAB, + 0xEC, 0xDA, 0xB7, 0xAF, 0xFC, 0xFA, 0x2F, 0x9B, 0xAD, 0x9B, 0xAF, 0x9F, 0xBD, 0xBB, 0x3F, 0xBB, 0xED, 0xDB, 0xBF, 0xBF, + 0xFD, 0xFB, 0x66, 0xCA, 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, + 0x2F, 0x9D, 0xEE, 0xDE, 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, + 0xBE, 0xBE, 0x77, 0xEB, 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, + 0xEF, 0xDF, 0xFF, 0xFF, 0x80, 0xD7, 0x80, 0x00, 0x0C, 0x4C, 0xF8, 0x86, 0x19, 0x44, 0x0A, 0x28, 0x63, 0xD8, 0x78, 0x97, + 0xD5, 0x27, 0x51, 0xEF, 0xE0, 0xCE, 0xB0, 0x44, 0x01, 0x2E, 0x38, 0xCB, 0x32, 0x4D, 0x58, 0x34, 0x21, 0x94, 0xB6, 0x85, + 0x84, 0xD3, 0xB9, 0xD5, 0x2F, 0x2D, 0x4F, 0xA1, 0xC8, 0x39, 0x39, 0x86, 0xAF, 0x11, 0x60, 0xEA, 0xEA, 0x06, 0xE9, 0xD5, + 0x5F, 0xA8, 0xE6, 0xCF, 0xC7, 0x63, 0xD9, 0xB1, 0xD1, 0xF2, 0x6F, 0x3F, 0xDB, 0xB9, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, + 0x42, 0x44, 0xD0, 0x64, 0x52, 0x64, 0x08, 0x62, 0xFC, 0x03, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, + 0x53, 0x65, 0x0B, 0x44, 0xE9, 0x09, 0xC1, 0x45, 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0xC1, 0x53, + 0x22, 0x58, 0xC9, 0x55, 0x93, 0x27, 0x59, 0x71, 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0xA9, 0xE0, 0x08, 0xF3, 0xFF, 0xEE, + 0x2B, 0x0A, 0x4B, 0xD1, 0xC8, 0xD3, 0x25, 0x24, 0x5E, 0x68, 0xE5, 0xE2, 0x62, 0x99, 0x30, 0xFC, 0xA6, 0x69, 0x32, 0xBC, + 0x41, 0x9B, 0x9A, 0x04, 0x26, 0x79, 0x03, 0x7B, 0x2F, 0x1A, 0x59, 0x0C, 0xAB, 0x08, 0x13, 0xD4, 0xC8, 0x91, 0x80, 0x12, + 0xC0, 0x28, 0x24, 0xE8, 0xD1, 0x0E, 0x8B, 0xB4, 0x16, 0x29, 0x42, 0xBD, 0x3C, 0x84, 0x73, 0x9F, 0x5C, 0x6C, 0xF6, 0x2A, + 0x49, 0xF0, 0xC2, 0x4C, 0x1A, 0x2C, 0x52, 0x68, 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0xB1, 0x37, 0x56, 0xF2, 0xCA, 0x5C, + 0x1B, 0x2D, 0x5A, 0x78, 0x4B, 0x4D, 0xDA, 0x7C, 0x5B, 0x6D, 0xBE, 0x27, 0xC3, 0x01, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, + 0xCA, 0x4E, 0xD3, 0x6D, 0xDA, 0x6E, 0x2B, 0x1D, 0x0B, 0xD2, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, + 0xDB, 0x6F, 0x04, 0x80, 0x78, 0xF8, 0xFA, 0xB6, 0xB5, 0x26, 0xCB, 0xA0, 0x17, 0x5C, 0xA9, 0xE2, 0xD2, 0x3E, 0xDE, 0xB0, + 0x26, 0xE9, 0xD5, 0x80, 0xBC, 0x52, 0xD8, 0xCF, 0x05, 0x9E, 0x37, 0xCB, 0x33, 0x78, 0x4F, 0x28, 0x82, 0x11, 0xBA, 0xDB, + 0x41, 0xEE, 0xD5, 0xA0, 0xB6, 0x49, 0xE1, 0x81, 0x25, 0xCF, 0x02, 0x1D, 0xDA, 0x02, 0x26, 0x30, 0x64, 0x2D, 0x5C, 0xCF, + 0x87, 0x9C, 0x98, 0xA5, 0xD2, 0x82, 0x44, 0xC0, 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, + 0x72, 0x74, 0x4C, 0xD0, 0x23, 0x15, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, + 0xA2, 0x16, 0xC5, 0xC5, 0xB2, 0x36, 0x55, 0xE1, 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, + 0xB3, 0x37, 0x5D, 0xF1, 0xE3, 0x57, 0xDD, 0xF5, 0xF3, 0x77, 0xD9, 0x89, 0x2E, 0x38, 0xFB, 0x7F, 0xE0, 0xEC, 0x4F, 0x2D, + 0x8D, 0x4A, 0xF6, 0xEC, 0x56, 0xF5, 0x36, 0x70, 0x6B, 0xD6, 0x66, 0x16, 0x1B, 0xEF, 0x12, 0xCF, 0x0A, 0x26, 0x52, 0xDE, + 0x3A, 0x87, 0xAD, 0x0B, 0xAB, 0xFC, 0xA4, 0x7C, 0x24, 0x7A, 0x9D, 0xC9, 0xF8, 0x5C, 0xEF, 0x89, 0x7A, 0x32, 0x55, 0x6B, + 0x0A, 0x1D, 0xF0, 0xEE, 0x53, 0x93, 0x67, 0xBB, 0x1E, 0x5D, 0xE7, 0x3F, 0xFC, 0xE2, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, + 0x3A, 0x3C, 0x56, 0xE8, 0x6A, 0x5C, 0xD6, 0xEC, 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, + 0x6B, 0x5D, 0xDE, 0xFC, 0x7B, 0x7D, 0x47, 0xC9, 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, + 0xFA, 0x7E, 0x4F, 0xD9, 0xAB, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x7E, 0x1F, + 0x54, 0x2B, 0x17, 0x07, 0x99, 0xAC, 0x31, 0x5D, 0xA3, 0xC6, 0x5F, 0xC8, 0xD1, 0x47, 0xD7, 0x16, 0x05, 0x59, 0x4E, 0xE7, + 0xDF, 0xE1, 0x40, 0xB0, 0x44, 0xB9, 0x39, 0x31, 0x22, 0xE5, 0x04, 0x03, 0xEF, 0xA6, 0xC9, 0x19, 0x52, 0x56, 0x79, 0xB4, + 0xA7, 0x0D, 0x97, 0x2A, 0x50, 0x46, 0x96, 0xEE, 0x95, 0xE0, 0xF7, 0x85, 0x91, 0x2E, 0x63, 0x32, 0x66, 0xB8, 0x66, 0x27, + 0x52, 0xE4, 0x18, 0x65, 0xFB, 0x8B, 0xE0, 0x46, 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0xBF, 0xD0, + 0x02, 0xFC, 0xE8, 0x56, 0x17, 0xA5, 0x78, 0x72, 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x5E, 0xC6, 0x88, 0x0C, 0xE1, 0x47, + 0x96, 0xA6, 0x71, 0x63, 0xC6, 0xC6, 0xF1, 0x67, 0xD6, 0xE6, 0x11, 0x77, 0xA3, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, + 0xC7, 0xC7, 0xF9, 0x77, 0xD7, 0xE7, 0xC2, 0xBC, 0x8B, 0x8F, 0xDC, 0x90, 0xF7, 0x5E, 0x12, 0xD3, 0x4C, 0x53, 0x02, 0x9C, + 0x72, 0xAD, 0xBA, 0x1E, 0x10, 0x0B, 0xC9, 0xED, 0xF9, 0x06, 0x32, 0xBE, 0x45, 0xD2, 0x55, 0xCC, 0x5B, 0xE9, 0x8B, 0xA9, + 0x53, 0x65, 0xFD, 0x94, 0x8C, 0x05, 0x1B, 0xD6, 0xCC, 0x11, 0x45, 0x8A, 0x59, 0xED, 0xBB, 0xF9, 0x21, 0xCA, 0x1D, 0xEE, + 0x75, 0xFB, 0x64, 0x39, 0xBE, 0xCB, 0xEC, 0xE1, 0x24, 0x95, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, + 0x4E, 0xCC, 0xF2, 0x6E, 0x5E, 0xEC, 0x6A, 0x5A, 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, + 0x5F, 0xED, 0x63, 0x4B, 0x8E, 0x8E, 0xE3, 0x4F, 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, + 0x8F, 0x8F, 0xEB, 0x5F, 0x9F, 0xAF, 0x7B, 0x7B, 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x28, 0x85, 0x85, 0x18, 0xD6, 0x66, + 0x70, 0x3B, 0x7C, 0x35, 0x07, 0x3F, 0x8E, 0x44, 0xF6, 0xB8, 0xBB, 0x62, 0x2D, 0x9E, 0xAE, 0xB8, 0xC3, 0xC4, 0x06, 0x50, + 0xE7, 0xD9, 0xDC, 0xF2, 0x7A, 0xFC, 0x27, 0x61, 0x26, 0xDA, 0x8E, 0x69, 0x0B, 0xB6, 0x4D, 0x21, 0xE1, 0x03, 0xA8, 0x45, + 0x58, 0xFD, 0x4D, 0xD7, 0xD1, 0x9C, 0x5A, 0xC8, 0x08, 0x4F, 0xB4, 0x51, 0x67, 0xFB, 0xF7, 0x49, 0x56, 0xFE, 0x64, 0xC2, + 0x26, 0x94, 0xE4, 0xC6, 0x36, 0xB4, 0x74, 0xE2, 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, + 0x37, 0xB5, 0x7C, 0xF2, 0x67, 0xD5, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, + 0xE6, 0xD6, 0xF5, 0xE7, 0xF6, 0xF6, 0x6D, 0xD3, 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, + 0xF7, 0xF7, 0x46, 0x4A, 0xE2, 0x13, 0x0D, 0xE0, 0xE9, 0xB6, 0xD2, 0xC8, 0x2D, 0x98, 0xFC, 0x55, 0xDF, 0x04, 0xA7, 0x6A, + 0x25, 0x96, 0x0D, 0x96, 0xE1, 0x89, 0x64, 0xBB, 0xCE, 0xDF, 0xBE, 0x3C, 0x7C, 0x9A, 0x59, 0x69, 0x2E, 0x92, 0xCF, 0x09, + 0x40, 0xFB, 0x4F, 0x29, 0xE5, 0x3E, 0x0C, 0xF0, 0xFA, 0xBA, 0x9B, 0xE9, 0x0E, 0x56, 0x8C, 0x93, 0x65, 0xCB, 0x77, 0x2C, + 0x8E, 0xC4, 0xE5, 0xBE, 0x5E, 0xBA, 0x66, 0xCA, 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, + 0x7E, 0xFC, 0x6E, 0xDA, 0x2F, 0x9D, 0xEE, 0xDE, 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, + 0xAE, 0x9E, 0xE7, 0xCF, 0xBE, 0xBE, 0x77, 0xEB, 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, + 0xBF, 0xBF, 0x7F, 0xFB, 0xEF, 0xDF, 0xFF, 0xFF, 0x8B, 0xCC, 0x80, 0x00, 0x0C, 0x4C, 0x04, 0x44, 0xCA, 0x26, 0x11, 0xD4, + 0x40, 0xBD, 0xA2, 0x62, 0xC2, 0xDD, 0x51, 0xEF, 0xE0, 0xCE, 0xE8, 0x54, 0x0C, 0xAA, 0x41, 0xB1, 0xA0, 0x80, 0x1A, 0x73, + 0x7F, 0xBD, 0xB6, 0x85, 0x8C, 0x80, 0x09, 0x39, 0x71, 0x2D, 0xBD, 0xA4, 0xE1, 0xC0, 0x3A, 0x5F, 0x05, 0x79, 0x60, 0xEA, + 0xEA, 0x06, 0x0D, 0xF7, 0x13, 0x2B, 0xE3, 0xB9, 0xA2, 0x41, 0x4D, 0x6B, 0x42, 0x5C, 0xE8, 0xE2, 0x85, 0x23, 0x00, 0x44, + 0x62, 0x68, 0x90, 0x65, 0x52, 0x05, 0xD0, 0x64, 0x52, 0x64, 0x4D, 0x4A, 0x17, 0xB1, 0x60, 0xF7, 0x6C, 0xA5, 0xB0, 0xC3, + 0xC6, 0x02, 0xD8, 0x74, 0x53, 0x65, 0xD1, 0x5F, 0x92, 0xF2, 0xB1, 0x83, 0x38, 0x67, 0xF2, 0x69, 0x1E, 0x76, 0xD1, 0x65, + 0xD2, 0x66, 0xCC, 0x97, 0x69, 0x4B, 0x09, 0x55, 0xE3, 0x6B, 0x99, 0x75, 0x30, 0x0B, 0xD9, 0x75, 0xD3, 0x67, 0xA9, 0xE0, + 0x08, 0xF3, 0x0B, 0x7E, 0xBB, 0x2E, 0xC0, 0xDE, 0x7B, 0x2A, 0xEC, 0x37, 0x8C, 0xFC, 0xE5, 0xE2, 0x62, 0x99, 0xF2, 0x9E, + 0x18, 0x4B, 0x40, 0xB8, 0x2F, 0x86, 0xFB, 0x9C, 0x8F, 0xD6, 0x03, 0x7B, 0x2F, 0x1A, 0xCB, 0x9F, 0xFB, 0xD5, 0x29, 0x1D, + 0x2F, 0x58, 0xCD, 0x22, 0xDC, 0x24, 0x24, 0xE8, 0xD1, 0x0E, 0xB3, 0xCD, 0x76, 0x24, 0x21, 0xD1, 0x8F, 0x84, 0xA5, 0x8E, + 0x90, 0xEC, 0xB2, 0x0E, 0xA0, 0xF7, 0xB2, 0x8A, 0xB0, 0x6D, 0x26, 0x95, 0x6A, 0x0E, 0xD2, 0x6C, 0x5A, 0x6C, 0x70, 0xA7, + 0x0D, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x9A, 0x78, 0x3B, 0xB8, 0xDA, 0x7C, 0x5B, 0x6D, 0xC7, 0xCD, 0x8A, 0x9F, 0x53, 0x4D, + 0x9A, 0x2E, 0x53, 0x51, 0x2B, 0xB1, 0xD3, 0x6D, 0xDA, 0x6E, 0x58, 0x66, 0x9B, 0x4D, 0xCB, 0x5D, 0x9B, 0x2F, 0x5A, 0xFD, + 0xCB, 0xDE, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, 0x78, 0xF8, 0x44, 0x80, 0x78, 0xBD, 0xC9, 0x80, 0x66, 0x70, 0xE2, 0xE2, + 0xD6, 0x3C, 0xDE, 0xB0, 0x26, 0xE9, 0x77, 0x10, 0x35, 0xF9, 0x26, 0x52, 0x1A, 0x55, 0x9C, 0x8C, 0x90, 0x8E, 0x4F, 0x28, + 0x82, 0x11, 0x78, 0x7E, 0x43, 0xCD, 0xE3, 0x23, 0xE1, 0x2A, 0xE1, 0x58, 0xCE, 0x30, 0x02, 0x1D, 0x92, 0xD1, 0xB7, 0x6A, + 0x46, 0x71, 0x66, 0x4E, 0x96, 0x5F, 0x5D, 0xB5, 0x81, 0x86, 0x7F, 0x86, 0x80, 0x5A, 0xC4, 0xC4, 0x32, 0x34, 0x24, 0xC6, + 0x80, 0x12, 0xD4, 0xE4, 0x72, 0x74, 0xEB, 0xD9, 0xF3, 0x45, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0x86, 0x47, 0x1B, 0xDC, 0xF4, + 0x73, 0x75, 0x31, 0xE5, 0x76, 0x06, 0xC5, 0xC5, 0xB2, 0x36, 0x55, 0xA7, 0x40, 0x57, 0xD5, 0xE5, 0xF2, 0x76, 0x6A, 0xDC, + 0x24, 0xB0, 0xCD, 0xD5, 0xB3, 0x37, 0x2B, 0xB7, 0x45, 0x15, 0xDD, 0xF5, 0xF3, 0x77, 0xDC, 0x84, 0x1B, 0xDA, 0x06, 0x9E, + 0x3E, 0x78, 0xD6, 0xA9, 0x33, 0x43, 0x97, 0x28, 0x78, 0xE9, 0x6E, 0xD8, 0x27, 0x14, 0x4E, 0x9C, 0x43, 0x3D, 0xA1, 0x4E, + 0xEB, 0x51, 0x8D, 0x41, 0x69, 0x37, 0xC5, 0xFF, 0x8B, 0x45, 0x2A, 0x09, 0xBC, 0xB7, 0x55, 0xD7, 0x0F, 0x4A, 0x20, 0xA4, + 0xFE, 0x7A, 0x05, 0x91, 0x0A, 0x16, 0xE3, 0x5A, 0xBB, 0xCE, 0x92, 0x49, 0xE1, 0x54, 0xEF, 0xFB, 0x5B, 0x85, 0xEE, 0x6E, + 0x2C, 0x5C, 0xC6, 0xCC, 0x3A, 0x3C, 0xD6, 0x12, 0xEF, 0x7B, 0xD6, 0xEC, 0x7A, 0x7C, 0xCE, 0x5C, 0x2B, 0x8C, 0xCE, 0xDC, + 0x3B, 0x3D, 0x4D, 0xBE, 0xC9, 0x13, 0xDE, 0xFC, 0x7B, 0x7D, 0x3C, 0x8F, 0x00, 0xE5, 0xC7, 0xCD, 0xBA, 0x3E, 0x88, 0x89, + 0xEC, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x75, 0x26, 0xAD, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x2B, 0x7D, 0xEF, 0x58, 0xDF, 0xFD, + 0xFB, 0x7F, 0x7E, 0x1F, 0x54, 0x2B, 0x98, 0xD6, 0xE9, 0xAF, 0x50, 0x66, 0x38, 0x4B, 0xE8, 0x32, 0x37, 0x7C, 0xD7, 0x16, + 0x05, 0x59, 0xAC, 0xF4, 0x97, 0xA9, 0xAB, 0xD0, 0xC7, 0xC9, 0x09, 0x88, 0xE9, 0x16, 0x04, 0x03, 0xEF, 0xA6, 0xC1, 0x47, + 0x7A, 0x29, 0x35, 0xC1, 0x46, 0x8A, 0x48, 0xC8, 0x54, 0x62, 0x96, 0xEE, 0x95, 0xE0, 0x5C, 0xF5, 0x95, 0x08, 0xB4, 0xD1, + 0x47, 0xCB, 0x16, 0x58, 0x08, 0x3F, 0x60, 0x7A, 0xFA, 0xB4, 0xE0, 0x46, 0x16, 0xA4, 0xC7, 0x6B, 0x40, 0xC4, 0xF0, 0x66, + 0x56, 0xE4, 0xED, 0x54, 0xCF, 0xD5, 0xE8, 0x56, 0x17, 0xA5, 0x0C, 0xF6, 0x43, 0xC2, 0xF8, 0x76, 0x57, 0xE5, 0xA1, 0x43, + 0xF6, 0x22, 0xE1, 0x47, 0x96, 0xA6, 0x62, 0x25, 0x64, 0x88, 0xF1, 0x67, 0xD6, 0xE6, 0xCD, 0xAE, 0x07, 0x5C, 0xE9, 0x57, + 0x97, 0xA7, 0xB9, 0x76, 0xD7, 0x86, 0xF9, 0x77, 0xD7, 0xE7, 0xC2, 0xBC, 0x8B, 0x8F, 0x04, 0x0F, 0x1C, 0xA1, 0xBB, 0xC8, + 0x7F, 0x8A, 0x0B, 0x70, 0xDF, 0xE6, 0xBA, 0x1E, 0x10, 0x0B, 0x2A, 0xE4, 0xFC, 0xD6, 0xC5, 0xD2, 0x4F, 0x04, 0xBB, 0x21, + 0x45, 0x7D, 0x8B, 0xA9, 0x53, 0x65, 0xDE, 0xEF, 0x73, 0xE8, 0x89, 0xD5, 0xDC, 0x07, 0x53, 0x10, 0xF8, 0x3E, 0xBB, 0xF9, + 0x21, 0xCA, 0xD4, 0xE5, 0x62, 0x74, 0x40, 0x33, 0x28, 0x74, 0x3A, 0x24, 0xC1, 0xA5, 0x63, 0x8C, 0xAC, 0xC9, 0xE2, 0x4E, + 0x1E, 0xAC, 0xDA, 0xC9, 0x31, 0x6C, 0xF2, 0x6E, 0x5E, 0xEC, 0x81, 0xAD, 0x09, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0xFC, 0xBC, + 0xED, 0x81, 0xFA, 0x7E, 0x5F, 0xED, 0x11, 0xEE, 0x0B, 0x89, 0xE3, 0x4F, 0x9E, 0xAE, 0xB3, 0x6B, 0xBE, 0x35, 0xF3, 0x6F, + 0xDE, 0xEE, 0x3C, 0x84, 0x2C, 0xF1, 0xEB, 0x5F, 0x9F, 0xAF, 0x0B, 0xA4, 0x78, 0x81, 0xFB, 0x7F, 0xDF, 0xEF, 0x2E, 0x02, + 0x87, 0x96, 0xA0, 0xC1, 0xB5, 0xBE, 0x6B, 0xA0, 0x17, 0xD0, 0x4D, 0xE0, 0x9E, 0x54, 0xEA, 0x64, 0x16, 0x93, 0xF2, 0x05, + 0x31, 0x1A, 0xFC, 0xB3, 0x3E, 0xCA, 0x18, 0x4A, 0xF5, 0x0A, 0x6D, 0x11, 0x05, 0x89, 0x06, 0x11, 0x68, 0x54, 0xEA, 0xA3, + 0x93, 0xDE, 0x30, 0xA1, 0x3C, 0xA2, 0xF7, 0xF1, 0xB5, 0x58, 0xCF, 0x93, 0x54, 0x1C, 0x7B, 0xCC, 0x81, 0x1C, 0xBF, 0x71, + 0x57, 0xB6, 0x77, 0xFD, 0x32, 0xD6, 0xE4, 0xC6, 0x36, 0xB4, 0xB4, 0xE7, 0x76, 0x95, 0xF4, 0xE6, 0x76, 0xF4, 0xAC, 0xD2, + 0x57, 0x31, 0xEC, 0xD6, 0x37, 0xB5, 0xBC, 0xF2, 0x17, 0x2E, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xFB, 0x5A, 0xE6, 0xE5, 0xC7, + 0xB6, 0xB6, 0xDD, 0x40, 0x99, 0x76, 0xF5, 0xE7, 0xF6, 0xF6, 0x68, 0xD5, 0x6F, 0x87, 0xED, 0xD7, 0xB7, 0xB7, 0x7C, 0x35, + 0x45, 0x92, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x62, 0x62, 0x55, 0x45, 0x7D, 0xE2, 0x13, 0x77, 0xD4, 0x0A, 0x17, 0xC4, 0x0B, + 0xD8, 0x1F, 0x16, 0x8A, 0x4A, 0x9C, 0xD0, 0xA8, 0xD6, 0x5C, 0x26, 0xB3, 0x5E, 0x1B, 0xC4, 0x3A, 0x7D, 0x4A, 0xD8, 0x63, + 0xAA, 0x99, 0xC0, 0x87, 0x57, 0x2C, 0x36, 0xDD, 0xFE, 0x12, 0x63, 0xE9, 0x5E, 0x04, 0x0F, 0x9F, 0xCA, 0x92, 0xF1, 0xAC, + 0xA9, 0x14, 0x85, 0xAF, 0x60, 0x5D, 0x54, 0xC4, 0x62, 0xC6, 0xC2, 0xA8, 0x82, 0x63, 0xE6, 0xCE, 0x3E, 0xBC, 0x04, 0x4F, + 0xEB, 0xDB, 0xF6, 0xEE, 0x7E, 0xFC, 0x17, 0x9C, 0x8D, 0xD3, 0xEE, 0xDE, 0x3F, 0xBD, 0x96, 0x59, 0x90, 0x9C, 0xFE, 0xFE, + 0x7F, 0xFD, 0xA7, 0xCB, 0xDE, 0xE0, 0xE7, 0xCF, 0xBE, 0xBE, 0x98, 0x1C, 0x6B, 0xD9, 0xF7, 0xEF, 0xFE, 0xFE, 0x1B, 0x5F, + 0xAB, 0x98, 0xEF, 0xDF, 0xBF, 0xBF, 0xD7, 0x58, 0x90, 0x1F, 0xFF, 0xFF, 0x57, 0x3D, 0x26, 0x59, 0x70, 0xA4, 0xE1, 0x62, + 0xEF, 0x8D, 0x18, 0x24, 0x68, 0x5E, 0x8D, 0xAD, 0xBB, 0x04, 0x1D, 0xE0, 0x1A, 0xA0, 0x08, 0x35, 0xD2, 0x8C, 0xD8, 0x58, + 0x46, 0x4C, 0xE0, 0xC5, 0xF2, 0x21, 0x8A, 0x38, 0x61, 0xAD, 0x10, 0x42, 0x4E, 0x28, 0x4B, 0xAE, 0xA8, 0x73, 0x2A, 0xC7, + 0x7C, 0x9F, 0x1C, 0x95, 0xB0, 0x50, 0x1C, 0xC5, 0xCD, 0x2A, 0x41, 0x35, 0xE9, 0xCD, 0xA7, 0x1C, 0x31, 0xE2, 0x78, 0xB3, + 0x3E, 0xA9, 0xF8, 0xBB, 0xF0, 0xDB, 0x2A, 0x80, 0x50, 0xF1, 0x43, 0x40, 0x8E, 0xD5, 0x51, 0x05, 0xA2, 0x8A, 0xDD, 0xD0, + 0x22, 0xCD, 0xC2, 0xFA, 0xAA, 0x46, 0x4F, 0x9E, 0xF6, 0xEF, 0x11, 0x70, 0xBA, 0x44, 0x85, 0x36, 0xB0, 0x87, 0xC0, 0x5E, + 0xFA, 0x04, 0x39, 0xD0, 0xB1, 0xEF, 0x51, 0x55, 0x8A, 0xF1, 0xF7, 0x7C, 0x95, 0x3E, 0x4F, 0x58, 0xC5, 0x5E, 0xA1, 0xB2, + 0x11, 0x65, 0x3A, 0x68, 0x53, 0x83, 0x06, 0xC9, 0x24, 0x27, 0x48, 0x07, 0x20, 0x79, 0x2C, 0xA8, 0x69, 0x88, 0x13, 0x89, + 0xA8, 0x02, 0x15, 0x33, 0xC0, 0x14, 0x67, 0xCA, 0x6A, 0x09, 0xA4, 0x10, 0x5F, 0x50, 0xD8, 0x38, 0xB0, 0x48, 0x2C, 0x66, + 0x45, 0x68, 0xD3, 0x41, 0x82, 0x47, 0x68, 0x0A, 0x79, 0x95, 0xC7, 0xE9, 0xE8, 0xAA, 0xA4, 0x22, 0xA1, 0x69, 0x0F, 0x81, + 0xAA, 0xC2, 0x8D, 0xCE, 0x55, 0xB6, 0x7C, 0x61, 0x4A, 0xA3, 0x4A, 0x3F, 0x22, 0x23, 0xDC, 0x98, 0x42, 0x0E, 0xDA, 0x68, + 0xF2, 0x1E, 0x2C, 0x98, 0x0A, 0x4D, 0x46, 0x23, 0xB8, 0x8D, 0x22, 0x7A, 0x0B, 0xED, 0x19, 0x8C, 0x53, 0xB6, 0xD2, 0x3A, + 0xBE, 0x62, 0xE3, 0x5C, 0x9C, 0x37, 0x4A, 0x2D, 0xA9, 0x6E, 0x64, 0x54, 0xDC, 0xB7, 0x47, 0xC6, 0x62, 0x5E, 0x5A, 0x1C, + 0x3D, 0x8F, 0xCA, 0x38, 0x81, 0xEF, 0xDB, 0x57, 0xA3, 0x7F, 0xBC, 0xC4, 0x1C, 0x14, 0x44, 0xEC, 0x7A, 0x3D, 0xD4, 0xC8, + 0x06, 0x5D, 0x6F, 0xDB, 0x25, 0x8F, 0x36, 0x6F, 0xA1, 0x73, 0xE6, 0xE7, 0x09, 0x73, 0x09, 0x34, 0x50, 0xF3, 0x64, 0xB6, + 0x69, 0xD1, 0xC4, 0x70, 0x9C, 0x32, 0xFF, 0xE5, 0xB4, 0x13, 0x4D, 0x10, 0x83, 0x89, 0xFD, 0xC7, 0x43, 0x8F, 0x33, 0xBC, + 0xE2, 0x1C, 0x94, 0x6F, 0x46, 0x56, 0x25, 0x21, 0x42, 0xD8, 0x0C, 0xC6, 0xC5, 0x1F, 0xE8, 0x33, 0xAE, 0x19, 0xDC, 0xF9, + 0xDB, 0x05, 0x94, 0x85, 0x05, 0x4F, 0xAA, 0xD8, 0x9B, 0x17, 0x55, 0x1C, 0xDC, 0x9E, 0x5D, 0x93, 0xF9, 0xBF, 0x18, 0xB7, + 0xE1, 0x81, 0x70, 0x6B, 0x72, 0x35, 0x5A, 0xA1, 0xAC, 0x54, 0xC7, 0x36, 0x86, 0x9B, 0x61, 0x87, 0x00, 0x76, 0x97, 0x1A, + 0x1B, 0xA7, 0x8B, 0xE0, 0xD3, 0xB8, 0x85, 0xF0, 0xB5, 0x2E, 0xA8, 0x93, 0x29, 0x86, 0xF9, 0x5F, 0x1A, 0xA6, 0x1E, 0x91, + 0xC9, 0xB7, 0xBE, 0x4B, 0xF2, 0x89, 0xCD, 0x99, 0x5C, 0x1A, 0xF4, 0xB1, 0x79, 0x6C, 0x18, 0xB1, 0x2F, 0x00, 0x53, 0xEE, + 0xD2, 0x68, 0x66, 0x83, 0x51, 0xAC, 0x0E, 0x4D, 0x05, 0x2C, 0x92, 0x76, 0xCB, 0x20, 0x3C, 0x1E, 0xC8, 0x32, 0x0E, 0x38, + 0x49, 0xDA, 0x91, 0x84, 0xF0, 0x01, 0xDE, 0xEB, 0x0A, 0x90, 0x4F, 0xF5, 0xDF, 0x36, 0x8E, 0x3D, 0x9C, 0xB2, 0xC1, 0x1D, + 0x59, 0x00, 0xE6, 0xBA, 0x48, 0x70, 0x4A, 0xAE, 0xC5, 0x91, 0x36, 0xF6, 0xDC, 0x51, 0xD4, 0x1F, 0x06, 0xD1, 0x16, 0x45, + 0x2D, 0x04, 0xD7, 0x89, 0x9A, 0xC4, 0x7E, 0xE5, 0xE6, 0x5B, 0xD6, 0xF8, 0xF3, 0xFA, 0x39, 0xCE, 0x0B, 0xE7, 0x97, 0xFC, + 0x82, 0x7C, 0x31, 0xD0, 0xEB, 0xBC, 0x40, 0xAA, 0x30, 0x1D, 0x86, 0x26, 0xAD, 0xC5, 0x97, 0xC0, 0x52, 0x6E, 0xFC, 0xE6, + 0x4A, 0xF9, 0x85, 0x9D, 0x93, 0xAE, 0x35, 0xE8, 0xA1, 0x2F, 0xBF, 0x6E, 0x77, 0xD6, 0x25, 0xC8, 0xE1, 0x6F, 0xC8, 0x01, + 0xA9, 0xEF, 0x3D, 0x96, 0x34, 0x37, 0x60, 0x74, 0xEA, 0x2A, 0xC7, 0x59, 0xC8, 0x37, 0x78, 0x5E, 0xDC, 0x1E, 0xB4, 0xF3, + 0xD1, 0x23, 0xB7, 0x2E, 0x92, 0xBB, 0xA4, 0xCB, 0x56, 0x8F, 0xEB, 0x36, 0xBC, 0xD3, 0x11, 0xEC, 0x6C, 0xF2, 0xE4, 0x3E, + 0x93, 0xBA, 0x31, 0xEA, 0x2C, 0xB2, 0xE3, 0x11, 0xBD, 0xB2, 0x76, 0x20, 0x6E, 0x89, 0xF5, 0x07, 0xF2, 0x29, 0x65, 0x43, + 0xE1, 0x49, 0xD0, 0x77, 0xDB, 0x87, 0xE4, 0x30, 0xE4, 0x8E, 0x44, 0xC5, 0x54, 0xAF, 0xD4, 0xE1, 0x04, 0xCF, 0x85, 0x89, + 0xA2, 0xFE, 0x1F, 0x7B, 0x80, 0x9F, 0x9F, 0x6E, 0x7F, 0x97, 0x0F, 0x4A, 0x2F, 0xF7, 0x5A, 0xC2, 0x03, 0xF8, 0xF2, 0xD7, + 0xAA, 0x4C, 0xE0, 0xA7, 0x09, 0x06, 0xA3, 0x00, 0xFF, 0x47, 0xD9, 0xA3, 0x3C, 0xC4, 0x7A, 0x86, 0x8B, 0x49, 0x73, 0x71, + 0xBF, 0x23, 0x78, 0xC8, 0x6F, 0x22, 0xCB, 0x51, 0xFB, 0x63, 0xA0, 0x7A, 0x01, 0x74, 0x3F, 0xF8, 0x35, 0x27, 0x82, 0xC5, + 0xA4, 0x98, 0x83, 0x7C, 0xFC, 0xA4, 0x7A, 0x08, 0x69, 0x98, 0xB9, 0x26, 0x2F, 0x07, 0x4D, 0x07, 0xFF, 0xDC, 0xA9, 0x1E, + 0xE8, 0xF5, 0x33, 0x0E, 0xBE, 0xDD, 0xF1, 0x30, 0xF5, 0x9A, 0x97, 0xA4, 0xCE, 0x38, 0x44, 0xD7, 0x88, 0xA6, 0x38, 0xDE, + 0x66, 0xFD, 0xF7, 0xCA, 0x2F, 0xE6, 0x0C, 0x46, 0xA7, 0x9D, 0x4D, 0x66, 0x19, 0x43, 0x30, 0xCF, 0x67, 0xFC, 0xBA, 0x6F, + 0x27, 0xEF, 0xE0, 0xFE, 0x7E, 0xA5, 0xED, 0xFA, 0x6E, 0x4F, 0xA3, 0x23, 0xD9, 0x31, 0xDB, 0x2F, 0xA8, 0x03, 0xDF, 0xF8, + 0x8D, 0xC4, 0x23, 0x9F, 0xA9, 0x4F, 0x15, 0x5D, 0x6E, 0x0C, 0xF2, 0x0A, 0x3E, 0x20, 0x43, 0x89, 0xEC, 0xB5, 0xC3, 0x8C, + 0xF1, 0x62, 0x3E, 0xB3, 0x1C, 0x8F, 0xFC, 0xEF, 0x32, 0xA9, 0xF4, 0xCA, 0x3E, 0x2D, 0x33, 0x5F, 0x8B, 0x05, 0xA7, 0xA3, + 0x1D, 0xD3, 0x77, 0xA7, 0x01, 0xF3, 0xFC, 0xDA, 0x53, 0x5C, 0x77, 0x55, 0x57, 0x70, 0x1B, 0xAE, 0x03, 0x19, 0xE2, 0xF8, + 0x17, 0x39, 0x4D, 0x53, 0xFF, 0xE3, 0xE5, 0x99, 0x88, 0xB0, 0x34, 0x08, 0x58, 0x9C, 0xB4, 0x06, 0xD6, 0x93, 0x45, 0xA2, + 0xEA, 0x58, 0x3D, 0xF6, 0x59, 0x7E, 0xD8, 0x7D, 0x22, 0x36, 0xF2, 0xA4, 0x5E, 0xB9, 0xE7, 0x60, 0xB2, 0x00, 0x34, 0x8E, + 0x3C, 0xF9, 0x54, 0x41, 0x53, 0x93, 0x5B, 0xFF, 0x31, 0x7C, 0xFE, 0x02, 0x98, 0x7A, 0x6B, 0x72, 0x46, 0x57, 0xC9, 0x41, + 0x72, 0x02, 0x9B, 0xFF, 0x4E, 0xE7, 0x4D, 0x70, 0x9E, 0xDE, 0x0A, 0x17, 0xD7, 0x57, 0xCE, 0xDC, 0x06, 0x31, 0x8C, 0xC6, + 0x83, 0xB3, 0x6A, 0x00, 0x93, 0x7A, 0xC5, 0x0C, 0xF1, 0x6E, 0x20, 0xA3, 0xC5, 0xA9, 0xDE, 0x7F, 0x9F, 0xF8, 0x83, 0x9B, + 0x54, 0x9A, 0xC8, 0x87, 0x95, 0xC9, 0x14, 0x69, 0x15, 0x34, 0xAC, 0x60, 0x91, 0xB4, 0x46, 0xB8, 0x2D, 0x79, 0x3E, 0xDF, + 0x16, 0x54, 0x3D, 0x96, 0x8F, 0xBC, 0x99, 0xA6, 0xBA, 0xA3, 0x2E, 0x3A, 0x8F, 0x25, 0x1B, 0x3C, 0xFF, 0xF2, 0x3A, 0xDC, + 0x67, 0x91, 0x50, 0xEC, 0x89, 0xF9, 0xAE, 0xBA, 0x0B, 0xC0, 0xAA, 0x8E, 0x5C, 0x5A, 0x71, 0x8A, 0x6A, 0x17, 0x0C, 0xDF, + 0x06, 0xB8, 0xE5, 0x18, 0x4D, 0xBC, 0x93, 0xA1, 0x83, 0x80, 0xFD, 0xA9, 0x5B, 0x12, 0x59, 0xF7, 0x39, 0x24, 0xEE, 0x89, + 0x4D, 0x7C, 0xE9, 0xCF, 0xDE, 0x5C, 0x98, 0x38, 0xD6, 0x31, 0x93, 0xEB, 0x46, 0xEF, 0x49, 0xD2, 0x0D, 0xD5, 0x5E, 0x91, + 0x6B, 0x53, 0x37, 0xDE, 0x46, 0x2E, 0x8A, 0xC1, 0xC7, 0x4B, 0x6A, 0x7F, 0xDE, 0x37, 0xC7, 0x0C, 0xDD, 0xBD, 0x19, 0xF3, + 0xC2, 0xA0, 0x13, 0x06, 0x9B, 0xD5, 0xC4, 0xDE, 0xCF, 0x3D, 0x98, 0x20, 0xD7, 0x21, 0x74, 0x82, 0x49, 0x09, 0xD2, 0x15, + 0x66, 0x21, 0x19, 0x43, 0x67, 0xE9, 0xE0, 0x47, 0x21, 0xE7, 0x49, 0x14, 0x86, 0x1B, 0xD1, 0x81, 0x8B, 0x77, 0xF6, 0x4F, + 0x16, 0x4A, 0x7D, 0x56, 0xA8, 0xE4, 0x8A, 0xD6, 0xB2, 0xBB, 0xB8, 0x2C, 0x81, 0x27, 0x4D, 0xD1, 0xC5, 0x66, 0x99, 0xF5, + 0xC1, 0x9E, 0x7E, 0x5F, 0x76, 0xA9, 0x82, 0xBB, 0xFB, 0xD5, 0x2E, 0x4C, 0x01, 0x4B, 0xD6, 0x59, 0xDB, 0xBB, 0x76, 0x6C, + 0x8C, 0x83, 0x92, 0x7B, 0x7B, 0xD4, 0x4E, 0x59, 0x45, 0x7C, 0x03, 0x49, 0x55, 0x7C, 0xD6, 0x61, 0x2F, 0x36, 0x6D, 0xDA, + 0x91, 0xBD, 0x09, 0x6D, 0xA1, 0xDB, 0x41, 0x7A, 0xE6, 0xED, 0x5B, 0x11, 0xDD, 0x03, 0x09, 0x3D, 0xD9, 0x2A, 0x1D, 0x81, + 0xCB, 0x48, 0x9F, 0x17, 0x38, 0x16, 0xBA, 0x87, 0x1A, 0x45, 0x84, 0x4B, 0x36, 0xF4, 0xD7, 0x53, 0x9D, 0xD5, 0xF0, 0xCE, + 0xAD, 0xEE, 0xDC, 0x1A, 0x59, 0x67, 0x4A, 0x75, 0x33, 0x68, 0xCE, 0x66, 0x67, 0x95, 0x39, 0x83, 0x3A, 0x49, 0xE2, 0x49, + 0x8A, 0x46, 0x57, 0x53, 0x0B, 0x15, 0xB8, 0xC1, 0xCC, 0x26, 0x93, 0x6D, 0x9C, 0x6C, 0x52, 0xDD, 0x2C, 0x7D, 0x56, 0x00, + 0xE2, 0xF0, 0x72, 0xD2, 0x36, 0x25, 0xE3, 0x4E, 0xED, 0xE1, 0xC4, 0x3B, 0x7E, 0x62, 0xDC, 0x75, 0x39, 0xB5, 0x54, 0x41, + 0xA3, 0x7D, 0x12, 0x10, 0x0C, 0xE1, 0x10, 0xA4, 0x63, 0x7C, 0x9A, 0x2F, 0x39, 0x41, 0x3A, 0x66, 0xF6, 0x40, 0x4F, 0xBC, + 0x73, 0xE6, 0x21, 0xCB, 0x8B, 0xCC, 0xFD, 0x70, 0xDA, 0x81, 0x21, 0x74, 0x49, 0x0F, 0x28, 0x13, 0x57, 0xC8, 0x8B, 0x31, + 0xC1, 0x02, 0xAD, 0x9D, 0x98, 0x26, 0x19, 0x9B, 0xA8, 0x39, 0xC3, 0x41, 0xDD, 0x76, 0x20, 0xE7, 0xD7, 0x20, 0xDC, 0x80, + 0xB9, 0x39, 0x40, 0x52, 0x53, 0x54, 0x90, 0xC4, 0x4D, 0x1E, 0xD8, 0xCE, 0x0F, 0xCD, 0xF5, 0xF2, 0xDA, 0x60, 0xD3, 0x46, + 0x45, 0x57, 0xA2, 0x8C, 0xB3, 0x41, 0xB9, 0x69, 0xA4, 0x7E, 0xDF, 0xF5, 0xD8, 0x43, 0xDF, 0x57, 0xF0, 0x9F, 0xAB, 0x9C, + 0x32, 0x7B, 0x64, 0x7A, 0x5E, 0x88, 0x4D, 0xFD, 0x2B, 0x3E, 0xAB, 0xD1, 0x40, 0xFC, 0x95, 0xB1, 0x71, 0x6B, 0xD1, 0xFF, + 0x1A, 0x56, 0x53, 0x40, 0x57, 0x22, 0xAB, 0x9B, 0x0A, 0x59, 0xAD, 0x82, 0x31, 0x7B, 0x72, 0xED, 0x03, 0xF8, 0x0C, 0xBC, + 0x79, 0xBE, 0x5E, 0x00, 0x25, 0xE4, 0xCE, 0x16, 0x06, 0x7E, 0xD8, 0x02, 0xA1, 0xE6, 0x9F, 0xEA, 0xDA, 0x35, 0x43, 0x83, + 0x19, 0x8D, 0x2E, 0x0D, 0xA7, 0x3B, 0x4B, 0x94, 0xDF, 0x13, 0x32, 0x37, 0x4F, 0xC6, 0x9D, 0x99, 0xB4, 0xC8, 0x4A, 0x71, + 0xC2, 0x77, 0x06, 0x71, 0x24, 0x5A, 0xF8, 0xB1, 0xC0, 0x49, 0x46, 0x59, 0x1C, 0x78, 0x3A, 0xD3, 0xBA, 0x7D, 0xE9, 0xF6, + 0xFF, 0x11, 0x03, 0x82, 0x49, 0xCD, 0xCA, 0x78, 0x59, 0xD2, 0x9D, 0xCF, 0x01, 0xFF, 0x03, 0x4E, 0x27, 0x67, 0x30, 0xA4, + 0xBE, 0xA3, 0x29, 0x95, 0x65, 0xFC, 0x2C, 0x3F, 0xF8, 0x70, 0xC3, 0xEA, 0x8F, 0xB3, 0x98, 0xDA, 0x50, 0x8A, 0x07, 0x88, + 0x9D, 0x19, 0xB7, 0xCE, 0x89, 0xFD, 0x66, 0xC0, 0x27, 0xED, 0x06, 0x05, 0x8E, 0x91, 0x0C, 0x7C, 0x16, 0x1E, 0xAD, 0xCB, + 0xDB, 0xC3, 0xD9, 0x25, 0x2D, 0x04, 0x4C, 0xAF, 0x19, 0x94, 0x56, 0xE8, 0x54, 0x7D, 0x9B, 0x78, 0x4A, 0x5A, 0x46, 0xCB, + 0xA6, 0x74, 0x50, 0xBC, 0xCE, 0x37, 0x4E, 0x35, 0x65, 0xC8, 0xE9, 0xC1, 0xFC, 0x47, 0x2A, 0xAA, 0xD7, 0x10, 0x5C, 0x3D, + 0xB5, 0xB4, 0x7F, 0xFD, 0xD4, 0x5F, 0x1F, 0x95, 0x41, 0x3D, 0x61, 0x64, 0x92, 0x88, 0xFB, 0x31, 0x6B, 0x22, 0x8D, 0xBD, + 0xF1, 0x16, 0xC8, 0xDD, 0x75, 0x02, 0xFC, 0x62, 0x01, 0x8A, 0xD5, 0x64, 0xFE, 0x90, 0x80, 0xCD, 0xAC, 0xCB, 0x80, 0xCC, + 0xAC, 0x8D, 0xA1, 0x45, 0xEA, 0x2F, 0x7A, 0x2D, 0x92, 0x98, 0x39, 0x2F, 0xF7, 0xE7, 0xE8, 0x7B, 0x71, 0x63, 0x20, 0x2C, + 0xA7, 0xC1, 0x97, 0x3E, 0x18, 0x05, 0xD5, 0xAC, 0xC6, 0xBA, 0xDA, 0x77, 0x85, 0x1E, 0x22, 0xA0, 0x65, 0xF1, 0xBA, 0x69, + 0x7E, 0xA7, 0x67, 0xE6, 0x77, 0x8E, 0xB6, 0x04, 0xAD, 0x1D, 0x2E, 0xA2, 0xF8, 0x8A, 0xF6, 0x6F, 0x34, 0xAF, 0xF7, 0x10, + 0xCA, 0x13, 0xEF, 0xF2, 0x66, 0x47, 0x77, 0x6A, 0x80, 0x9F, 0x21, 0x2F, 0xDC, 0xAB, 0x49, 0x9D, 0xC0, 0xDF, 0xE9, 0xE2, + 0xB5, 0x93, 0x49, 0xF7, 0x6E, 0x76, 0xDE, 0xF7, 0x6B, 0x56, 0x31, 0x62, 0xC1, 0xDE, 0xA3, 0x88, 0x74, 0x6C, 0xBD, 0x41, + 0xF1, 0xE4, 0xEA, 0x4E, 0x18, 0x84, 0x34, 0x17, 0x65, 0xA6, 0xD0, 0xB6, 0xA9, 0x6E, 0xEA, 0x72, 0xA6, 0x0F, 0xBF, 0x9A, + 0x2C, 0x0B, 0x6A, 0x8F, 0x4F, 0x64, 0xBA, 0xC3, 0x0F, 0xEF, 0x41, 0x1B, 0x8D, 0x1B, 0xB9, 0xFF, 0x20, 0x0B, 0x35, 0x17, + 0xE5, 0x86, 0xB3, 0xEF, 0x9C, 0x31, 0x29, 0x5B, 0xE5, 0xB0, 0x93, 0xEC, 0xA1, 0x24, 0xEB, 0xC9, 0x32, 0x66, 0x18, 0x71, + 0x7C, 0x62, 0x72, 0x2D, 0x76, 0x01, 0x22, 0x36, 0x84, 0xC2, 0xFD, 0x14, 0xED, 0x47, 0x29, 0x5F, 0x6A, 0xAE, 0x7F, 0xDE, + 0x32, 0xA3, 0xAB, 0x38, 0xC9, 0xA5, 0xB2, 0x08, 0xEC, 0x30, 0x82, 0x62, 0xDF, 0xD3, 0x9E, 0x70, 0xB2, 0x7B, 0xBA, 0x49, + 0x3B, 0x58, 0x96, 0x52, 0xC8, 0xD7, 0xEA, 0xFE, 0x7F, 0x6C, 0x63, 0x57, 0x93, 0x3A, 0x3C, 0x64, 0xBD, 0x5A, 0x6D, 0x19, + 0xA7, 0xC2, 0xA1, 0x0F, 0xB7, 0xBE, 0x70, 0x62, 0x7D, 0xD1, 0xC6, 0xC6, 0xDD, 0x21, 0x2D, 0x33, 0xC5, 0x7F, 0x30, 0xE6, + 0x70, 0xF4, 0xC9, 0x1A, 0x80, 0xC7, 0x80, 0xAA, 0xC9, 0xC0, 0xFC, 0xC6, 0xF7, 0x5A, 0x5B, 0xC5, 0x05, 0x27, 0x89, 0x6B, + 0x20, 0xDF, 0xC7, 0x87, 0xB7, 0xF2, 0xA2, 0x58, 0x18, 0xD1, 0x61, 0x60, 0x1D, 0x43, 0x65, 0xD7, 0x4C, 0xD0, 0x6D, 0xEB, + 0x44, 0xDD, 0x88, 0x82, 0x99, 0x91, 0xB5, 0xAF, 0x2C, 0x0E, 0x62, 0xEB, 0x8E, 0x05, 0xE0, 0x3A, 0x36, 0xA1, 0xCF, 0x32, + 0x6E, 0xAD, 0xED, 0xF3, 0x85, 0x91, 0x2E, 0xE3, 0x1F, 0xD7, 0x40, 0x73, 0xE2, 0xD6, 0xEB, 0x01, 0xE3, 0x58, 0x3C, 0x9F, + 0x1F, 0xB7, 0x5F, 0x30, 0x9E, 0x1D, 0xF2, 0xCF, 0x36, 0x16, 0x6D, 0xFB, 0x85, 0x14, 0xCD, 0x1C, 0x1F, 0xA7, 0x74, 0x90, + 0x86, 0x96, 0x46, 0x1D, 0x0C, 0xF5, 0x2F, 0xB4, 0x0C, 0xB3, 0xE4, 0x54, 0x94, 0x57, 0x28, 0x2B, 0x0F, 0x0B, 0x98, 0xB7, + 0xFE, 0xB2, 0x2F, 0x3B, 0x0F, 0x27, 0x99, 0xF4, 0x89, 0x64, 0x55, 0x92, 0x88, 0x26, 0xE6, 0x96, 0xC0, 0x3F, 0x29, 0x3E, + 0x5C, 0x7B, 0x9E, 0xAE, 0x85, 0x48, 0xB7, 0x63, 0x24, 0xD7, 0x99, 0xB7, 0x7E, 0xBA, 0x4F, 0x5B, 0x9B, 0x7B, 0x00, 0x96, + 0x08, 0x6B, 0x39, 0xF9, 0x52, 0x06, 0xE7, 0xE1, 0x7F, 0xBB, 0x07, 0x2B, 0x4E, 0x7B, 0x8C, 0x87, 0xFB, 0x02, 0x3C, 0x36, + 0x46, 0xAD, 0xFB, 0x6F, 0x5D, 0x67, 0x4D, 0x08, 0x32, 0x6C, 0x61, 0x6A, 0x4F, 0xD0, 0x36, 0x4E, 0x4C, 0x14, 0xA8, 0xBC, + 0x7D, 0xB2, 0x69, 0xE1, 0x1B, 0x50, 0x6F, 0x14, 0x82, 0xB2, 0xA7, 0xA3, 0xE4, 0x93, 0xF1, 0xF6, 0xB8, 0xA7, 0x9C, 0x2C, + 0xCA, 0x2A, 0x08, 0x1F, 0x5A, 0x5F, 0x79, 0xF2, 0x1C, 0xD2, 0xE9, 0x7F, 0x3F, 0x89, 0x01, 0xC6, 0x06, 0xD5, 0x6F, 0xFF, + 0xFF, 0xFF, 0xBF, 0xF1, 0xA3, 0x40, 0xFE, 0x02, 0xF1, 0xA3, 0xF7, 0x5E, 0x21, 0x44, 0xD6, 0x46, 0x73, 0xB1, 0xA8, 0x63, + 0xA2, 0x82, 0x18, 0xE7, 0x95, 0xAC, 0x88, 0xC3, 0xC5, 0xCC, 0x58, 0x58, 0xEF, 0x0D, 0x33, 0x31, 0x19, 0xAD, 0x29, 0xF6, + 0x1C, 0x2F, 0x68, 0xD1, 0x40, 0x54, 0xA6, 0x19, 0x2C, 0x93, 0xBF, 0xE2, 0x0D, 0x0E, 0xDB, 0x53, 0x7A, 0x47, 0x4B, 0x72, + 0x2A, 0x27, 0x26, 0xA6, 0xB3, 0xBE, 0x3B, 0x87, 0xFB, 0xF2, 0x3F, 0xB4, 0x64, 0x85, 0xB1, 0x20, 0x1E, 0xCF, 0x94, 0x06, + 0x71, 0x86, 0x6E, 0xF0, 0x3D, 0x70, 0xF0, 0xAC, 0x13, 0xD4, 0x1E, 0x80, 0xBC, 0x4A, 0x18, 0x18, 0xED, 0x09, 0x7A, 0xDF, + 0x83, 0xB6, 0x90, 0xC1, 0xAB, 0x16, 0xE4, 0x5C, 0xC4, 0x5F, 0xE6, 0x49, 0x2E, 0x57, 0x1D, 0x6A, 0xE1, 0x92, 0x36, 0x2F, + 0xE5, 0xF8, 0x99, 0x19, 0xC9, 0x4A, 0x66, 0xE6, 0xAB, 0xBA, 0x92, 0xF8, 0x7F, 0xA9, 0x12, 0xFF, 0x9C, 0xA5, 0x82, 0xDB, + 0xCC, 0xC5, 0xF4, 0x89, 0x5B, 0x88, 0x58, 0x2F, 0xE2, 0x6D, 0x1A, 0xED, 0xBA, 0xE9, 0x8A, 0xC8, 0x1C, 0xE8, 0xBC, 0x00, + 0x73, 0xDC, 0x16, 0xFA, 0x0C, 0x87, 0xD1, 0x13, 0x73, 0x4E, 0x41, 0x6A, 0x23, 0x2E, 0x30, 0x88, 0x04, 0xE9, 0x9B, 0x22, + 0xBD, 0xFE, 0xB9, 0x2D, 0xB2, 0x84, 0x8E, 0xCA, 0x4D, 0xC6, 0x08, 0x02, 0xFB, 0x29, 0x96, 0x77, 0x76, 0x08, 0x98, 0x26, + 0x72, 0x3F, 0x10, 0x8A, 0x16, 0x48, 0xB4, 0x54, 0x59, 0x8C, 0xFF, 0xFC, 0xF3, 0xCE, 0x57, 0xF1, 0xC2, 0xD0, 0x62, 0xBF, + 0x89, 0x6D, 0xFC, 0x50, 0x67, 0xCD, 0xC6, 0x5A, 0xF6, 0x7D, 0x03, 0x25, 0x10, 0x6C, 0x7F, 0xED, 0xFB, 0x6C, 0x70, 0x55, + 0x06, 0xDF, 0x78, 0xE8, 0x77, 0x0C, 0xE4, 0x07, 0x6E, 0xB3, 0x53, 0x68, 0x37, 0x7E, 0x4A, 0x0E, 0xEF, 0x03, 0xA0, 0xA4, + 0x83, 0xBD, 0x96, 0xF3, 0x14, 0x9F, 0x84, 0x53, 0xE4, 0xDD, 0xAA, 0x01, 0x93, 0x79, 0xAC, 0xE2, 0x4B, 0xE0, 0x3A, 0xB0, + 0xED, 0x80, 0x24, 0x94, 0x8A, 0x35, 0xFE, 0x94, 0x98, 0x12, 0x55, 0xB0, 0x94, 0xBD, 0x25, 0xF6, 0x13, 0xB1, 0x47, 0x8B, + 0x0B, 0x36, 0x8C, 0x62, 0x19, 0xF1, 0x73, 0x96, 0x85, 0x98, 0x4D, 0xE9, 0xE7, 0x35, 0x43, 0x53, 0xE5, 0xFE, 0xFF, 0xB4, + 0xF2, 0xC9, 0xD5, 0x44, 0x13, 0xFD, 0x10, 0x3E, 0x34, 0x8E, 0x4D, 0xE0, 0x95, 0x31, 0x14, 0x8D, 0x7F, 0xDB, 0xD9, 0xF7, + 0x82, 0xBA, 0x93, 0x2B, 0x4C, 0x40, 0xF0, 0x75, 0xB6, 0x37, 0x68, 0x87, 0x0B, 0x7A, 0x85, 0xA9, 0xEE, 0xB9, 0x8E, 0xE1, + 0x8D, 0xC6, 0x6D, 0x09, 0xAE, 0x8A, 0x71, 0x96, 0x82, 0x79, 0x5E, 0xEA, 0x97, 0xE2, 0x16, 0xE2, 0xB5, 0xED, 0x34, 0x1A, + 0x1C, 0xDC, 0xDB, 0xDC, 0xDA, 0xFD, 0xE3, 0xB5, 0xC3, 0x5C, 0x30, 0xEC, 0x99, 0x97, 0x85, 0x2C, 0x28, 0xE4, 0xA8, 0x18, + 0xBA, 0x79, 0xAA, 0xBC, 0x4A, 0xDB, 0xDE, 0x6C, 0xC6, 0x96, 0x61, 0xC7, 0x01, 0x54, 0xD6, 0x79, 0x90, 0x7A, 0x3D, 0x39, + 0x2D, 0xB5, 0x10, 0xAA, 0x19, 0x95, 0x2F, 0x53, 0x44, 0x57, 0xA9, 0x1C, 0x3A, 0x5A, 0x19, 0xA1, 0x42, 0x5F, 0x5B, 0x6E, + 0xDB, 0x94, 0x8F, 0x49, 0x95, 0xAA, 0x5F, 0xD5, 0x4C, 0x39, 0x53, 0x4C, 0x4F, 0xF3, 0xBA, 0xBE, 0xD1, 0x0D, 0xC1, 0xD9, + 0x58, 0x1E, 0x46, 0x83, 0x59, 0x1D, 0x28, 0x18, 0x28, 0x2E, 0x86, 0x1C, 0x50, 0xB6, 0x5E, 0xC5, 0x94, 0xC0, 0x6A, 0x9E, + 0x48, 0x9D, 0x7D, 0x36, 0x57, 0x72, 0xF9, 0xE4, 0x37, 0x98, 0x4E, 0x8B, 0x4B, 0xC5, 0x17, 0x85, 0xFA, 0xA1, 0x15, 0xF6, + 0xD7, 0x5D, 0x2A, 0xEC, 0x83, 0x7D, 0x8C, 0x07, 0x88, 0x03, 0x74, 0xBA, 0xF5, 0xA3, 0x35, 0x86, 0x7D, 0x99, 0x00, 0x74, + 0x76, 0xCC, 0x62, 0x64, 0xAF, 0xA4, 0x29, 0x89, 0xD9, 0x1D, 0x9D, 0xE2, 0x9B, 0x20, 0x9A, 0x26, 0x88, 0x0E, 0x40, 0x00, + 0x3D, 0x3E, 0xEE, 0xF6, 0x19, 0x35, 0x96, 0x2F, 0x82, 0x7B, 0x31, 0xF6, 0x37, 0x62, 0xA1, 0x19, 0x67, 0x6D, 0xD7, 0x93, + 0x21, 0x44, 0x3C, 0xE0, 0x01, 0x0E, 0x09, 0x65, 0xF7, 0xCF, 0x07, 0xD1, 0xB7, 0x1C, 0xEF, 0x28, 0xB3, 0x47, 0xA0, 0x3B, + 0x02, 0x0F, 0x20, 0x47, 0x9F, 0xF8, 0xB0, 0x07, 0xC2, 0x86, 0x92, 0x7B, 0x57, 0x78, 0x71, 0xC3, 0x64, 0xA5, 0x45, 0x6C, + 0x2D, 0x10, 0xF8, 0x63, 0xBB, 0xF4, 0x6E, 0x86, 0xEB, 0x44, 0xBA, 0x72, 0xFE, 0xC4, 0x5A, 0x09, 0x0B, 0x5B, 0x68, 0xE2, + 0x67, 0x41, 0xCF, 0x4A, 0x35, 0xEF, 0x11, 0x77, 0x66, 0x28, 0x38, 0x69, 0xAD, 0x52, 0xB9, 0x1A, 0xD2, 0x67, 0xEC, 0xF3, + 0xE6, 0x45, 0x70, 0x4C, 0xE7, 0xEC, 0x32, 0xF1, 0x2F, 0xAC, 0xA2, 0xD9, 0xC0, 0x55, 0x21, 0x8A, 0x14, 0x39, 0x3C, 0x36, + 0xE6, 0xCD, 0x10, 0x43, 0xFA, 0xE8, 0xAA, 0x45, 0x26, 0xC6, 0x3D, 0x7E, 0xE1, 0x44, 0x1B, 0xF4, 0xEF, 0xB0, 0x19, 0x53, + 0x7B, 0xBA, 0x4B, 0x0C, 0x35, 0xC5, 0x8D, 0x13, 0x51, 0x6C, 0x11, 0xAB, 0x00, 0x24, 0xF5, 0xFD, 0x99, 0x2E, 0xBB, 0x09, + 0xAD, 0x26, 0xE9, 0xCD, 0xFE, 0x8B, 0x77, 0xCE, 0x3F, 0xAE, 0x33, 0xCA, 0x16, 0x80, 0x67, 0x19, 0x76, 0xA0, 0xCC, 0x43, + 0xFD, 0x6D, 0x62, 0xAB, 0xF3, 0xBC, 0x3B, 0xA0, 0x3B, 0xA0, 0x76, 0xDB, 0x6B, 0x39, 0xC2, 0x6E, 0xFC, 0x40, 0x5B, 0x8C, + 0x4C, 0xAE, 0x5C, 0x62, 0x61, 0x73, 0x11, 0x76, 0xCD, 0x8E, 0x28, 0xEB, 0xEF, 0x4C, 0xAB, 0x27, 0xD9, 0x7B, 0xFD, 0x3D, + 0x64, 0x22, 0xAD, 0x60, 0xFD, 0x8D, 0xEE, 0xFB, 0xEE, 0xF6, 0x1E, 0x32, 0xA9, 0x3F, 0xF2, 0x75, 0x52, 0x3D, 0x4A, 0xA4, + 0x85, 0x53, 0xAD, 0xB3, 0x83, 0x95, 0x72, 0x70, 0x21, 0x14, 0xBA, 0xAA, 0x33, 0xA8, 0x02, 0x1F, 0x0E, 0xDE, 0x82, 0x13, + 0x03, 0x2E, 0x81, 0xE1, 0x80, 0x6F, 0xDB, 0xBB, 0xD7, 0x88, 0x9D, 0x50, 0x68, 0x93, 0x8D, 0x96, 0x96, 0x0D, 0x3F, 0x88, + 0x81, 0x9C, 0x7C, 0xF5, 0x94, 0xFB, 0xBD, 0x81, 0x85, 0x67, 0xE3, 0x55, 0xF1, 0x5E, 0x7D, 0x53, 0x87, 0x3D, 0xFD, 0x02, + 0x97, 0xBD, 0x62, 0x4A, 0x60, 0xCD, 0x30, 0x2C, 0xCD, 0x5B, 0x75, 0xA7, 0x21, 0x8C, 0xFF, 0x25, 0x4F, 0x1A, 0xDF, 0x5B, + 0xBB, 0x86, 0x3C, 0x9E, 0xEF, 0xF8, 0x70, 0x23, 0x9A, 0xD4, 0x7B, 0x37, 0x49, 0x19, 0x50, 0x67, 0xDB, 0xA5, 0xA5, 0x17, + 0x63, 0x47, 0xEB, 0x29, 0x0B, 0x9A, 0x78, 0xA5, 0x5C, 0xE6, 0x43, 0x46, 0xE1, 0xCE, 0x86, 0x07, 0x8B, 0x46, 0x19, 0x7B, + 0x8F, 0xD8, 0xFC, 0xF4, 0x54, 0x69, 0xA6, 0xD9, 0x4E, 0x59, 0x21, 0x9C, 0x1C, 0x4C, 0x3C, 0x9E, 0xD2, 0x14, 0xF6, 0x36, + 0x5E, 0x62, 0x13, 0xC5, 0xE0, 0x98, 0x0A, 0xDC, 0x15, 0x3A, 0x15, 0xBB, 0x41, 0xDB, 0x67, 0xE6, 0xB6, 0xB7, 0xB7, 0x54, + 0xEA, 0x23, 0x77, 0xC7, 0xB0, 0x65, 0xFB, 0x65, 0x5C, 0xF5, 0xB9, 0xA3, 0xBB, 0xA2, 0x29, 0xD9, 0x8D, 0x2B, 0xC0, 0xCC, + 0x97, 0x68, 0x19, 0x22, 0x77, 0xD1, 0xBC, 0x07, 0x56, 0xED, 0x2A, 0x6E, 0x5F, 0x3C, 0x88, 0xE8, 0x9F, 0x7F, 0xD6, 0x6B, + 0x13, 0xC2, 0xF6, 0xFF, 0x5C, 0x20, 0xF8, 0xA4, 0xE2, 0xBF, 0xE7, 0x55, 0x79, 0xE4, 0x71, 0xF3, 0x11, 0x8C, 0x27, 0xA7, + 0x88, 0xB3, 0x8C, 0xCC, 0x4F, 0xC5, 0x5F, 0xED, 0x9E, 0xBC, 0x83, 0xA0, 0x31, 0x02, 0xF9, 0xF3, 0xB9, 0x86, 0xD4, 0x7E, + 0x7C, 0xE0, 0x79, 0x01, 0x53, 0xF2, 0x59, 0x15, 0xD5, 0x6C, 0xB6, 0x20, 0x16, 0x39, 0x6D, 0xDF, 0x23, 0x5D, 0xED, 0xDB, + 0x33, 0x3C, 0x75, 0xE3, 0x23, 0x8A, 0xF1, 0x33, 0xB0, 0x8E, 0x7C, 0x52, 0xBA, 0x03, 0x27, 0xB0, 0x60, 0x98, 0xC5, 0x5F, + 0x8E, 0x1C, 0xB8, 0x81, 0xA1, 0xC2, 0x07, 0x80, 0xC6, 0x5B, 0x04, 0xA1, 0xE1, 0x56, 0x30, 0x28, 0x87, 0x1A, 0x29, 0x1F, + 0x1D, 0x4F, 0xD2, 0x56, 0x3C, 0xEC, 0x59, 0x5D, 0x9D, 0xBC, 0xFB, 0xB2, 0x23, 0xC6, 0x94, 0xB4, 0x64, 0x85, 0xE4, 0x0F, + 0x44, 0x5D, 0x4E, 0x77, 0x1A, 0x55, 0x51, 0xFC, 0xE2, 0x0A, 0xF0, 0xAB, 0x70, 0x38, 0xA1, 0x57, 0xE2, 0x3A, 0x5F, 0x34, + 0xBA, 0x24, 0x1B, 0x88, 0xF6, 0x44, 0x91, 0xC1, 0xAB, 0x16, 0xCE, 0xE5, 0xF3, 0xA6, 0xEF, 0x4C, 0x5F, 0xE0, 0x13, 0x0D, + 0xF7, 0x45, 0xDF, 0xF5, 0x95, 0x3E, 0xE6, 0x40, 0x62, 0xC6, 0xB9, 0x76, 0x86, 0x6A, 0x66, 0x6A, 0xFB, 0x83, 0xE0, 0x8E, + 0xF1, 0x4C, 0x6A, 0x1A, 0xB3, 0xE5, 0x26, 0x4E, 0x6B, 0x88, 0x30, 0xA8, 0x8C, 0xA6, 0xB5, 0x8E, 0x9B, 0xB4, 0x8A, 0x27, + 0x2B, 0xFD, 0x5E, 0xF6, 0xE2, 0x96, 0xD0, 0x30, 0x63, 0x4E, 0xE1, 0x0D, 0x99, 0xE9, 0xC3, 0xAD, 0xF9, 0xEF, 0x38, 0x6A, + 0xD6, 0xB6, 0xAF, 0x7B, 0x32, 0x96, 0xE9, 0x1D, 0x98, 0xFA, 0x4D, 0xBD, 0xF8, 0x4B, 0xC1, 0x57, 0xE5, 0x29, 0x5B, 0xD3, + 0xEB, 0x03, 0xA6, 0x2E, 0xE1, 0x6E, 0x4D, 0x9B, 0xCE, 0xC1, 0xD8, 0x6E, 0xF9, 0x2E, 0x70, 0xBE, 0x57, 0x09, 0xB2, 0x6E, + 0xE0, 0xB8, 0xE3, 0x9A, 0xE7, 0x30, 0x51, 0x1E, 0x7A, 0xFD, 0x19, 0x39, 0xFE, 0x11, 0x08, 0x2A, 0x67, 0x81, 0x01, 0x2A, + 0x21, 0x2A, 0x18, 0xD8, 0x58, 0x4A, 0x3D, 0x7D, 0x12, 0xF2, 0xB3, 0x2E, 0xB1, 0x6D, 0x23, 0x89, 0x83, 0xFE, 0xE5, 0x15, + 0x54, 0xE9, 0xFF, 0xEB, 0x26, 0x09, 0x44, 0xEC, 0x81, 0x72, 0x2F, 0xFF, 0x66, 0x8A, 0x34, 0xD6, 0x12, 0x3C, 0x9C, 0xD7, + 0x05, 0xE5, 0xD6, 0x6B, 0x92, 0x54, 0x4E, 0x34, 0x50, 0x06, 0x01, 0xC7, 0x2C, 0x7A, 0xDA, 0xC1, 0xA4, 0x7C, 0x98, 0xC0, + 0x5B, 0x56, 0xA9, 0xBE, 0x86, 0xFF, 0xEB, 0xA2, 0xF4, 0xF2, 0x5D, 0x8A, 0x8B, 0x51, 0xF5, 0xB1, 0xD2, 0x46, 0xDD, 0xD9, + 0xAD, 0x8C, 0xD5, 0x95, 0xA7, 0xCB, 0x5C, 0xED, 0x24, 0x0D, 0xCC, 0xC1, 0x4D, 0x34, 0x6E, 0x50, 0xEB, 0x16, 0x8E, 0x58, + 0x0E, 0x36, 0x55, 0xB8, 0x25, 0x0C, 0x17, 0xD6, 0x4C, 0xDD, 0x24, 0xE4, 0x83, 0xD4, 0x4C, 0x04, 0x2C, 0x84, 0x03, 0xBB, + 0x01, 0x54, 0x55, 0x38, 0xBA, 0x77, 0x4C, 0x42, 0x1F, 0xFD, 0xC8, 0xEC, 0x07, 0x79, 0xCB, 0x3F, 0x0F, 0x1A, 0x92, 0xB2, + 0xB5, 0x4D, 0x70, 0x02, 0x67, 0xDA, 0xA3, 0xF3, 0x12, 0xF4, 0x1F, 0x88, 0xDF, 0x7D, 0x11, 0x08, 0x09, 0x9A, 0xA2, 0xCA, + 0x5B, 0xB8, 0xAC, 0x53, 0x85, 0x14, 0xA2, 0x1D, 0xFC, 0x7B, 0x4E, 0xF4, 0x73, 0xB2, 0xDA, 0x72, 0xD2, 0xC6, 0x5E, 0xD4, + 0x24, 0x74, 0x3F, 0x61, 0xE4, 0xC6, 0x3A, 0x6F, 0xD8, 0xE1, 0xBC, 0xEE, 0xE6, 0x86, 0xF1, 0x6D, 0xFB, 0xD2, 0x66, 0x72, + 0x56, 0x90, 0x8B, 0x7F, 0xBF, 0x22, 0x21, 0x08, 0xEF, 0x62, 0x87, 0x05, 0x9A, 0x0E, 0xBB, 0x8F, 0xF4, 0x41, 0xF7, 0xB3, + 0x1B, 0xBE, 0x04, 0xAF, 0x6C, 0x45, 0x7E, 0x1F, 0xF6, 0x71, 0xF7, 0x86, 0xF6, 0x60, 0xD2, 0x3A, 0x9E, 0x53, 0xFE, 0x8A, + 0x09, 0x71, 0xA0, 0xFA, 0x9A, 0xFE, 0xA4, 0x09, 0xB2, 0xC2, 0x9E, 0x56, 0x1F, 0x9F, 0xFE, 0xD9, 0x93, 0xF1, 0x2C, 0x1D, + 0xDB, 0x8F, 0xE0, 0x82, 0x5A, 0xA3, 0xAD, 0x4D, 0xBA, 0xAF, 0x9F, 0x91, 0x41, 0xD4, 0x77, 0x0E, 0x77, 0x72, 0x32, 0x06, + 0xFB, 0x0D, 0x60, 0x6E, 0x79, 0xE2, 0xCB, 0x05, 0xE5, 0xDB, 0xA9, 0xA5, 0xA9, 0xEF, 0xE8, 0x7A, 0x7A, 0x89, 0x90, 0xE5, + 0x91, 0xB5, 0x93, 0xB7, 0xD6, 0xFE, 0x80, 0x06, 0x13, 0xA3, 0xF5, 0xFD, 0x6D, 0x81, 0xB8, 0x12, 0x27, 0xC7, 0xB7, 0x7D, + 0x49, 0xA0, 0x8E, 0x16, 0x75, 0x43, 0xAB, 0x78, 0x83, 0x9A, 0x0D, 0xD0, 0x57, 0xAF, 0x42, 0x40, 0xAF, 0x81, 0xA0, 0xEB, + 0x26, 0x86, 0x4D, 0xB2, 0xF9, 0x7B, 0xF9, 0x71, 0x32, 0x09, 0xB0, 0x0A, 0xCF, 0x1B, 0xEA, 0xA6, 0x1E, 0xA6, 0x13, 0xA1, + 0x69, 0x18, 0x88, 0x11, 0x26, 0xA8, 0xC3, 0x94, 0x63, 0x71, 0x78, 0xAE, 0x25, 0x6E, 0x9A, 0x78, 0x85, 0x0B, 0x2D, 0xF5, + 0x9E, 0x14, 0x2B, 0xB2, 0xBA, 0xD9, 0x3E, 0xE8, 0x56, 0x3B, 0xC5, 0xC0, 0x84, 0x8D, 0xF1, 0xC2, 0xB7, 0x26, 0xEA, 0x0C, + 0xAC, 0xC8, 0x50, 0x4A, 0xD1, 0xFE, 0x7B, 0xCA, 0x4E, 0x25, 0x9C, 0x09, 0xDE, 0xA8, 0x2B, 0x2B, 0xBB, 0xAD, 0x8A, 0xD5, + 0xF0, 0xE5, 0x22, 0x07, 0xFC, 0x08, 0xBC, 0xB3, 0x1B, 0xB0, 0x96, 0xBF, 0x98, 0xAB, 0x07, 0x0F, 0xFC, 0x48, 0x73, 0x8F, + 0xBD, 0x91, 0xEB, 0x87, 0xFF, 0xDF, 0x0B, 0xC3, 0x80, 0x16, 0x48, 0x08, 0x7D, 0x15, 0xAB, 0xE4, 0x6C, 0xE8, 0xED, 0xEF, + 0x62, 0xA4, 0x52, 0xD0, 0x36, 0x37, 0x83, 0x0F, 0x82, 0x44, 0xB2, 0xBA, 0xB2, 0x1D, 0xA0, 0x89, 0xE3, 0x2A, 0xF0, 0x58, + 0x2E, 0x35, 0xD7, 0x0C, 0xA9, 0xAE, 0x77, 0xBA, 0x67, 0xF8, 0xA2, 0x56, 0xE6, 0x2B, 0xD6, 0xFE, 0x7E, 0x91, 0xA0, 0x14, + 0x23, 0xAF, 0xA3, 0x23, 0xC4, 0x83, 0xF2, 0x31, 0x5C, 0xAE, 0x0D, 0x6D, 0x2F, 0x4D, 0xEA, 0xB4, 0x2B, 0xE1, 0xBD, 0x4A, + 0xE1, 0x04, 0xFA, 0x25, 0x5D, 0xAF, 0x69, 0x26, 0x24, 0x8B, 0xE2, 0xFC, 0x7E, 0x30, 0x8D, 0xB3, 0x0E, 0xD2, 0x3A, 0x02, + 0x0D, 0xD8, 0x67, 0x26, 0x55, 0x30, 0x23, 0x22, 0x45, 0x52, 0xEC, 0x4E, 0x88, 0x65, 0x01, 0xED, 0xA8, 0x0D, 0xBA, 0xEC, + 0xE8, 0xB3, 0xA5, 0x4C, 0x86, 0x94, 0x3C, 0x88, 0x05, 0x2D, 0x65, 0xEF, 0x1E, 0xF3, 0xCE, 0x84, 0x45, 0xC9, 0x8D, 0x59, + 0x09, 0xB0, 0xFD, 0xE0, 0x87, 0xD1, 0x12, 0xCC, 0xDE, 0xBC, 0x96, 0x36, 0x76, 0xEC, 0x85, 0x4C, 0xC6, 0xAB, 0x67, 0xC0, + 0xB7, 0x68, 0x84, 0x87, 0xBA, 0xB9, 0xC4, 0xDF, 0xD5, 0x99, 0x58, 0x78, 0x36, 0x0B, 0x14, 0xD6, 0xDE, 0xD7, 0xD6, 0x3E, + 0xED, 0xFA, 0x05, 0x8C, 0xC0, 0x94, 0x78, 0x08, 0x08, 0xD5, 0x5A, 0x9C, 0x82, 0x3D, 0xEF, 0xC6, 0x15, 0xF7, 0x8E, 0x13, + 0xAD, 0x27, 0x65, 0x98, 0xA3, 0xFD, 0x74, 0xC3, 0x10, 0xF2, 0x7D, 0xA5, 0x5C, 0x86, 0xDA, 0x53, 0xE1, 0xCE, 0xC2, 0xAF, + 0xD4, 0x97, 0x3B, 0x32, 0x2A, 0x81, 0x26, 0xF5, 0x3A, 0xA1, 0x49, 0xF5, 0x9D, 0x24, 0x0E, 0x40, 0x6C, 0xB5, 0x77, 0x8F, + 0xF8, 0xF5, 0xF7, 0x8B, 0xE8, 0xD5, 0x40, 0x58, 0x8D, 0x66, 0x85, 0x30, 0x7C, 0x79, 0xA1, 0x75, 0x00, 0x97, 0xA5, 0x71, + 0x10, 0xB7, 0xF7, 0x77, 0x41, 0x27, 0x4A, 0x68, 0x05, 0x8C, 0xEB, 0xC5, 0xA3, 0x85, 0x6B, 0xC1, 0xB3, 0xA5, 0x01, 0x0F, + 0xEB, 0xC2, 0x57, 0x23, 0x7D, 0xA9, 0x5E, 0x25, 0xD3, 0x3D, 0xBC, 0x32, 0x56, 0x8D, 0x19, 0x88, 0x91, 0x57, 0x8D, 0x17, + 0x76, 0xBE, 0xCE, 0xA8, 0x4D, 0xB1, 0x02, 0x4C, 0x37, 0xB5, 0x67, 0xF1, 0xCE, 0x62, 0x7A, 0x03, 0x80, 0xBC, 0x5F, 0xFB, + 0xF3, 0x31, 0x27, 0xA7, 0xF4, 0xB3, 0xDE, 0xDA, 0xCC, 0x9C, 0xF3, 0x28, 0x0B, 0xF7, 0x11, 0xDC, 0x1A, 0x90, 0xE9, 0xE0, + 0x87, 0xFD, 0xBF, 0x27, 0x42, 0x2B, 0x6F, 0xFF, 0xDA, 0x49, 0x5E, 0x28, 0xEC, 0xAB, 0xE0, 0x1A, 0xDD, 0xFD, 0xA8, 0xBB, + 0x23, 0x44, 0xCB, 0x24, 0x2F, 0x69, 0x68, 0x12, 0x6A, 0x0C, 0x24, 0x86, 0xD1, 0xFC, 0x02, 0x32, 0x8B, 0x4E, 0x73, 0x2A, + 0x61, 0x95, 0x14, 0x61, 0x05, 0x93, 0xF9, 0x22, 0x6D, 0x2D, 0x6F, 0xC3, 0xD2, 0x0F, 0x4A, 0x12, 0xD6, 0x79, 0xF6, 0x43, + 0x8F, 0x89, 0xEB, 0x49, 0x90, 0x83, 0x51, 0x90, 0x3C, 0x21, 0x8C, 0x0B, 0x88, 0x96, 0x58, 0x44, 0x0B, 0x4A, 0xF8, 0x94, + 0xE9, 0x2B, 0x45, 0x93, 0x7A, 0xC9, 0xD8, 0x43, 0xB3, 0x6B, 0x6E, 0x7C, 0x0A, 0xA1, 0x82, 0xAF, 0xB0, 0x23, 0x66, 0x5D, + 0x2B, 0x48, 0xB8, 0x34, 0xF5, 0x68, 0x9A, 0xD2, 0xFD, 0x0F, 0xA1, 0x04, 0x35, 0x2B, 0x37, 0x49, 0x29, 0x57, 0xB1, 0x25, + 0x7C, 0x69, 0xDC, 0x15, 0xBC, 0x0E, 0xC5, 0xA3, 0x32, 0xAD, 0xA6, 0x02, 0xF7, 0x24, 0x93, 0x68, 0x92, 0x66, 0x84, 0xA8, + 0xA9, 0x48, 0xB8, 0x8E, 0xCC, 0x2B, 0xD6, 0xF8, 0x36, 0xB7, 0x19, 0xA8, 0x33, 0x61, 0xB2, 0xF8, 0x0D, 0x1B, 0x8A, 0xE1, + 0x2E, 0xF2, 0xFD, 0xB0, 0xEC, 0xC0, 0xC0, 0x39, 0xFE, 0x6D, 0x07, 0x4F, 0xBB, 0x54, 0xFB, 0xF4, 0xC8, 0xB1, 0xBF, 0xC1, + 0x1B, 0x07, 0xDB, 0x38, 0xEB, 0xFA, 0xB3, 0xF9, 0x99, 0x49, 0xAB, 0x99, 0xD2, 0x69, 0x3B, 0xAA, 0x6A, 0x41, 0xCD, 0xFA, + 0x5B, 0xBF, 0x9B, 0x6B, 0x71, 0x05, 0xBD, 0xAE, 0x98, 0x04, 0xA9, 0x98, 0x6B, 0xBD, 0xAA, 0xEE, 0x5B, 0x6B, 0xBB, 0xDC, + 0x60, 0x60, 0xB2, 0xDE, 0x12, 0x90, 0x89, 0x8B, 0xC7, 0xE0, 0xA2, 0xFE, 0x5A, 0x8F, 0x18, 0xC6, 0x8C, 0xFD, 0x38, 0x2F, + 0xD9, 0x91, 0x2D, 0x6F, 0xA9, 0xAB, 0xE8, 0x8F, 0x76, 0xD3, 0x15, 0x71, 0x8B, 0xA0, 0xF3, 0x8D, 0x6C, 0x20, 0x4A, 0x9B, + 0x67, 0xE2, 0x64, 0x9F, 0x59, 0x27, 0x7A, 0x86, 0xC9, 0x01, 0xE4, 0x9A, 0x3D, 0x3D, 0x4E, 0x92, 0x44, 0xDD, 0xF4, 0xBA, + 0x79, 0xFB, 0xBC, 0xE7, 0x2F, 0x4E, 0x98, 0x4F, 0x46, 0xD4, 0x7C, 0xAE, 0x68, 0xDA, 0x24, 0x4A, 0x61, 0x3C, 0xD6, 0x72, + 0x2C, 0x1F, 0x9F, 0x84, 0x93, 0x72, 0x75, 0xBA, 0x10, 0x5D, 0x8F, 0x47, 0xC3, 0x2A, 0xB9, 0xF3, 0xAF, 0x6C, 0x52, 0xF5, + 0xB7, 0x98, 0xCD, 0x53, 0x00, 0x48, 0x62, 0x31, 0x9A, 0x7A, 0xA3, 0x30, 0xA2, 0x0B, 0xFE, 0x26, 0xB0, 0x1C, 0x2C, 0x62, + 0xB6, 0xCF, 0xB4, 0x44, 0xCE, 0x79, 0xC8, 0x96, 0x3F, 0x54, 0xB4, 0x56, 0x36, 0x6C, 0x3E, 0xE0, 0x62, 0x95, 0x54, 0x31, + 0xD2, 0xFD, 0x5B, 0x00, 0x30, 0x1E, 0x65, 0xA7, 0xF1, 0x89, 0x6D, 0xF1, 0x41, 0x3A, 0x9F, 0x5A, 0x51, 0x70, 0x96, 0x42, + 0xDC, 0x1E, 0x97, 0xD4, 0x10, 0x31, 0xF5, 0xFC, 0x64, 0xD5, 0x5D, 0x17, 0x52, 0xFF, 0x39, 0xB9, 0x89, 0xE7, 0x34, 0x08, + 0x5F, 0xA1, 0x15, 0x4E, 0x5F, 0xBD, 0xDE, 0xA1, 0x99, 0x7E, 0x45, 0xA5, 0xC2, 0x5D, 0xD5, 0xAB, 0x42, 0x30, 0x1A, 0x41, + 0xDE, 0xC2, 0xC7, 0xA4, 0x1A, 0x59, 0x3C, 0x2C, 0x5F, 0x91, 0x5C, 0x1E, 0xC7, 0x33, 0xCA, 0xC9, 0x83, 0xC9, 0x34, 0x0D, + 0x5B, 0x3B, 0x55, 0x86, 0xDF, 0xB4, 0xA9, 0x50, 0xB0, 0x9F, 0xA8, 0x44, 0xE1, 0x19, 0x67, 0x99, 0x31, 0x01, 0x9F, 0xFF, + 0x15, 0x15, 0xCE, 0x49, 0x9B, 0xB4, 0xBA, 0xCC, 0xE8, 0x88, 0xD2, 0x0E, 0xF8, 0x34, 0xDB, 0x75, 0x50, 0x14, 0xCC, 0x3E, + 0xB9, 0x35, 0x3E, 0xE6, 0x18, 0x50, 0xBE, 0xB8, 0x0A, 0x72, 0x61, 0xE5, 0x9C, 0xBA, 0x47, 0x2F, 0x1B, 0xB6, 0x7A, 0x8B, + 0xC9, 0x4C, 0xCA, 0x1D, 0xF2, 0x71, 0x14, 0x56, 0xAD, 0xF4, 0x0F, 0xBF, 0xFA, 0x1F, 0x4D, 0x0D, 0x00, 0x1B, 0xBF, 0xBC, + 0x35, 0xFF, 0xA9, 0xF1, 0x02, 0x9B, 0x03, 0x2E, 0xC8, 0x91, 0xF3, 0xCA, 0x90, 0x0D, 0x3A, 0x44, 0x9E, 0xD1, 0x16, 0x74, + 0xF2, 0x91, 0xB6, 0x3E, 0x36, 0x21, 0xBC, 0x26, 0xC5, 0xA3, 0xDE, 0x1E, 0x54, 0x70, 0xDE, 0x02, 0x7A, 0x99, 0xC1, 0x30, + 0xF5, 0xAF, 0x9D, 0xB1, 0xC8, 0xC8, 0xD1, 0x39, 0x9D, 0xEF, 0x91, 0xE8, 0x54, 0x5E, 0x1D, 0x75, 0xFC, 0x92, 0xD1, 0x1B, + 0x42, 0x12, 0x55, 0xB5, 0x01, 0x68, 0x75, 0xBF, 0x27, 0x5F, 0xD8, 0x16, 0x12, 0xAB, 0x65, 0x80, 0xC4, 0x10, 0xD4, 0x04, + 0x17, 0xC4, 0x31, 0xC1, 0xEE, 0xB4, 0xB6, 0x5D, 0x95, 0x8D, 0x78, 0xD7, 0x69, 0xA6, 0xC0, 0x26, 0xD7, 0xEA, 0x55, 0xC7, + 0xE4, 0x38, 0x81, 0x06, 0x3D, 0xE4, 0x2A, 0x01, 0xAD, 0xB7, 0x89, 0xE5, 0xD3, 0xE2, 0x91, 0x6C, 0x80, 0x52, 0x97, 0xD3, + 0xFC, 0x93, 0x33, 0x99, 0x2C, 0x96, 0x99, 0x33, 0x90, 0x6C, 0x09, 0x71, 0x56, 0x83, 0xBA, 0x0A, 0x34, 0x16, 0x08, 0xC2, + 0x98, 0x07, 0x8A, 0xBD, 0x5B, 0xEE, 0x12, 0xE5, 0xFC, 0xEA, 0xD2, 0xF6, 0x0F, 0xE4, 0x58, 0x3B, 0x4E, 0xA9, 0xF6, 0x7E, + 0x07, 0xF2, 0x27, 0x93, 0x75, 0x2B, 0x99, 0x8D, 0x48, 0xC2, 0x9F, 0xC3, 0x57, 0x87, 0x10, 0xCA, 0x7D, 0x4C, 0xD0, 0x68, + 0xB5, 0x7A, 0x54, 0x9B, 0xB2, 0x46, 0xFB, 0xCA, 0x6B, 0x89, 0xB8, 0xCF, 0xD9, 0xA4, 0x2E, 0xCE, 0x35, 0xAE, 0x82, 0x0F, + 0xE5, 0xEE, 0x48, 0x5B, 0x72, 0x33, 0x76, 0x8C, 0xDC, 0xA4, 0x0A, 0x44, 0x0E, 0x80, 0x4A, 0x3C, 0x5E, 0xED, 0x81, 0xFE, + 0x20, 0x9B, 0xE2, 0x8E, 0x20, 0xE2, 0xC0, 0x8A, 0x52, 0xC4, 0xBD, 0x44, 0x1C, 0x86, 0x4D, 0x47, 0xAC, 0xC8, 0x3A, 0x8D, + 0x5C, 0xA6, 0x94, 0x9C, 0x66, 0xC5, 0x93, 0xDD, 0x9E, 0xCC, 0x41, 0xF9, 0x1B, 0xF3, 0x4F, 0x8F, 0x20, 0xE0, 0x80, 0xEC, + 0xB8, 0x9F, 0xEF, 0xC2, 0x0B, 0xB9, 0x30, 0xEA, 0xE6, 0x35, 0x25, 0xB5, 0x27, 0x81, 0x27, 0x72, 0xE0, 0xFD, 0x5D, 0x12, + 0x5E, 0xDC, 0x64, 0xA2, 0xC9, 0xDC, 0xCE, 0xB3, 0x29, 0x6A, 0xE5, 0x87, 0xF3, 0x2F, 0x7C, 0xA4, 0xB2, 0x41, 0xAD, 0xC1, + 0x85, 0x4E, 0xD5, 0xB9, 0x6D, 0xFF, 0x74, 0x5D, 0x00, 0x15, 0xF3, 0xBF, 0xB5, 0x1C, 0x27, 0x46, 0xC4, 0xC3, 0xDB, 0x4E, + 0xD4, 0x86, 0x68, 0x3E, 0xCA, 0x6F, 0x9C, 0xE1, 0x97, 0x3C, 0x4E, 0x52, 0xB2, 0x7B, 0x8C, 0x64, 0x73, 0x85, 0xFD, 0x2B, + 0x2F, 0xD7, 0xE4, 0x34, 0xB5, 0xBD, 0xF6, 0x90, 0xE5, 0x01, 0x78, 0x74, 0xA3, 0x1E, 0x7D, 0xEC, 0x9A, 0xC3, 0xF5, 0x25, + 0x17, 0x3E, 0xD1, 0x81, 0x19, 0x94, 0xB7, 0x05, 0xD2, 0x2D, 0xA5, 0xFC, 0xD0, 0x72, 0x2D, 0xB5, 0xF6, 0xF7, 0x50, 0x03, + 0xEF, 0xD8, 0xC5, 0x0C, 0x0A, 0x99, 0x20, 0x02, 0x89, 0x1E, 0xB3, 0x73, 0x1D, 0x63, 0x0C, 0x28, 0xB8, 0x34, 0x23, 0x80, + 0x48, 0x03, 0x89, 0xEC, 0xD2, 0xFB, 0xF7, 0x0D, 0xD4, 0x88, 0x5E, 0x8D, 0x4C, 0xD4, 0xF2, 0x15, 0xFF, 0x2D, 0x27, 0xCB, + 0xBD, 0x81, 0x93, 0x0B, 0xDE, 0x04, 0x4F, 0x8C, 0x4F, 0x9B, 0xAF, 0x53, 0x62, 0xB8, 0x50, 0xDC, 0x9E, 0xD6, 0x57, 0xEC, + 0xA6, 0x04, 0xC4, 0x9C, 0x4C, 0x24, 0x92, 0xDD, 0x9C, 0x7B, 0xB9, 0xAA, 0xD6, 0xED, 0x9E, 0xAC, 0x7F, 0x3C, 0x16, 0xF4, + 0xF7, 0xD1, 0x91, 0x2E, 0x3E, 0x27, 0xAE, 0xC4, 0x1F, 0x69, 0xB4, 0xDF, 0x9C, 0xBB, 0x1E, 0xBE, 0xA3, 0x50, 0x5D, 0x16, + 0xDE, 0x42, 0x54, 0xE7, 0xA8, 0x34, 0x9F, 0x4D, 0xBB, 0x3F, 0x75, 0x09, 0x63, 0x9F, 0xF3, 0xED, 0xAE, 0xF8, 0x7A, 0x9C, + 0x4E, 0x39, 0xE7, 0xB8, 0x1C, 0xB9, 0x07, 0x79, 0xE6, 0x02, 0x40, 0x38, 0x25, 0xF5, 0x80, 0xFC, 0x04, 0x8B, 0x40, 0x43, + 0xF1, 0xD6, 0x4B, 0x03, 0x46, 0xB3, 0x07, 0xD7, 0xD4, 0xCD, 0x32, 0xA0, 0xD5, 0xAE, 0x48, 0xE5, 0xCC, 0xAA, 0x00, 0x1F, + 0x3D, 0x14, 0x08, 0x56, 0x12, 0xBE, 0x5F, 0x3D, 0x6B, 0x46, 0xFE, 0x77, 0x46, 0xBD, 0xE0, 0xDD, 0x2C, 0xB9, 0xC3, 0x99, + 0x3B, 0x06, 0xAD, 0x73, 0xEA, 0x92, 0x42, 0x28, 0x7A, 0x67, 0x8A, 0x0A, 0xB9, 0xD6, 0xE1, 0x57, 0x92, 0xDC, 0x9F, 0x20, + 0x80, 0xD0, 0x53, 0x36, 0xB1, 0x8F, 0x36, 0xB8, 0xAB, 0x17, 0x83, 0x9E, 0x54, 0xCF, 0x48, 0xA9, 0x83, 0x9E, 0xE0, 0xAF, + 0x60, 0x33, 0x98, 0x81, 0x28, 0x48, 0xA6, 0x72, 0xBA, 0x76, 0xE0, 0x23, 0x3D, 0x5D, 0x92, 0x4D, 0x2D, 0x7D, 0x37, 0xAC, + 0xC1, 0x0C, 0xBC, 0x16, 0xE8, 0x97, 0x49, 0xD5, 0xE4, 0x9E, 0x36, 0xD1, 0x9B, 0x3F, 0xA2, 0x56, 0x62, 0x38, 0x19, 0x84, + 0x55, 0xC7, 0x02, 0xFB, 0x70, 0x83, 0xD8, 0x13, 0x1E, 0x83, 0x01, 0xAC, 0x2F, 0xD1, 0xEA, 0x08, 0x2E, 0xC7, 0x30, 0xA8, + 0xDD, 0xA6, 0x31, 0xAC, 0x11, 0x86, 0xCA, 0x94, 0x81, 0x2A, 0xA5, 0xDE, 0x7D, 0x32, 0xD9, 0x35, 0x63, 0x4E, 0x63, 0x72, + 0xF8, 0x4A, 0xD3, 0xD8, 0x56, 0xEE, 0x37, 0x57, 0x7B, 0x0F, 0xAF, 0x7B, 0x04, 0xAD, 0x1A, 0xE4, 0x99, 0xB0, 0xCE, 0xC0, + 0xE8, 0xD0, 0x2D, 0xD0, 0xF8, 0x97, 0x9B, 0xDB, 0x35, 0x05, 0x9D, 0x44, 0x69, 0x2C, 0xFB, 0x16, 0xDF, 0x11, 0x85, 0x1F, + 0x20, 0x67, 0xFC, 0xA1, 0x2A, 0xA9, 0x0A, 0x15, 0x65, 0xD0, 0x23, 0x46, 0x2D, 0xB8, 0xAF, 0x58, 0x8F, 0xFC, 0x83, 0xB8, + 0x54, 0x95, 0x1C, 0x4D, 0xED, 0x22, 0x87, 0xFA, 0x6B, 0x71, 0xA4, 0x7C, 0xA8, 0x6A, 0xDA, 0x18, 0x43, 0x7E, 0x40, 0x3D, + 0x8B, 0x29, 0x8D, 0x07, 0xE5, 0xE9, 0x7C, 0x44, 0xB0, 0x9E, 0x3E, 0x30, 0xDF, 0xED, 0x11, 0x7B, 0x36, 0x9A, 0xEE, 0x60, + 0x64, 0x75, 0xAC, 0x5B, 0x99, 0x0A, 0xD8, 0x35, 0x62, 0x0E, 0xF2, 0xAC, 0x52, 0x11, 0xF0, 0x22, 0x2D, 0x59, 0x31, 0xCB, + 0xEC, 0x2D, 0x5B, 0x20, 0xA0, 0x71, 0x32, 0xF7, 0xD8, 0xA3, 0xDA, 0x49, 0x80, 0x1F, 0x41, 0x5B, 0x0D, 0x33, 0x73, 0x31, + 0x40, 0xB2, 0xDB, 0xB8, 0x5A, 0x42, 0x9D, 0x92, 0xBE, 0x48, 0x26, 0xFB, 0xD5, 0xDE, 0x22, 0x2D, 0x03, 0xA8, 0x54, 0xDA, + 0x50, 0xC0, 0xDB, 0x79, 0xBB, 0xA9, 0x9A, 0xDB, 0x93, 0xD5, 0x67, 0xC3, 0x17, 0x46, 0x1A, 0xDA, 0x01, 0x41, 0x9C, 0x01, + 0x08, 0xC8, 0xD8, 0x45, 0x0F, 0xDA, 0xF8, 0x9A, 0x73, 0x4B, 0x93, 0xDF, 0xD4, 0x82, 0x7A, 0xBB, 0x17, 0xCA, 0x85, 0x16, + 0xD0, 0xFD, 0x6B, 0xFC, 0x9D, 0x55, 0x98, 0xA7, 0x58, 0xA4, 0x25, 0xD6, 0x1A, 0x58, 0x4A, 0x87, 0x9B, 0xC6, 0x52, 0x77, + 0xC1, 0x1B, 0xBC, 0xBD, 0x4C, 0x97, 0x04, 0xCE, 0x28, 0x17, 0xC6, 0x9D, 0xD9, 0x87, 0x57, 0xE8, 0x5E, 0xFC, 0x99, 0x6F, + 0x41, 0x9B, 0x1A, 0x5E, 0x7B, 0x14, 0x0E, 0xCF, 0x03, 0xD8, 0x55, 0x0B, 0x5F, 0x58, 0x14, 0x7D, 0xB0, 0x99, 0x4E, 0x67, + 0x4D, 0xDB, 0xA9, 0x90, 0xD6, 0xA5, 0xD0, 0xF9, 0x15, 0x78, 0x1E, 0x9F, 0x36, 0x7A, 0x4D, 0xB9, 0x4E, 0x16, 0xA7, 0x42, + 0x10, 0xE8, 0x98, 0x89, 0x5D, 0xBA, 0xB8, 0x75, 0xB7, 0x91, 0x50, 0x45, 0x83, 0x2F, 0xA8, 0xD5, 0x19, 0x5C, 0xFC, 0xDC, + 0x4C, 0x84, 0x9D, 0x4F, 0x0D, 0x37, 0x7E, 0xDF, 0x4F, 0x11, 0x98, 0xC0, 0xFB, 0x33, 0x98, 0xA9, 0xAC, 0xB5, 0x90, 0x5E, + 0x84, 0x93, 0x0F, 0xDE, 0xA2, 0x0D, 0x81, 0xD5, 0x11, 0xEF, 0xB0, 0x5D, 0x84, 0xF2, 0x9C, 0x59, 0xD0, 0x01, 0xE8, 0x8B, + 0x1C, 0x59, 0x4F, 0xBA, 0xC8, 0x41, 0x37, 0xF1, 0x78, 0x0D, 0xD8, 0x74, 0xEB, 0xE2, 0x04, 0x26, 0x2B, 0xE8, 0x0D, 0x79, + 0x81, 0xBD, 0x97, 0x55, 0xCF, 0x30, 0x0F, 0xE7, 0x65, 0x3B, 0xAF, 0x3A, 0xE0, 0x6E, 0xEC, 0x54, 0xAE, 0x7A, 0x47, 0x3B, + 0x6F, 0x53, 0xEC, 0xCB, 0xFF, 0xD3, 0x68, 0x50, 0x61, 0x6D, 0x1A, 0x03, 0x56, 0x36, 0x57, 0x2A, 0x64, 0x25, 0xF7, 0x2E, + 0x36, 0x08, 0x69, 0xDB, 0x5E, 0x8E, 0xB9, 0xDA, 0x55, 0xB8, 0xE8, 0xC6, 0x78, 0xD3, 0xEC, 0x31, 0x75, 0x3B, 0x48, 0x99, + 0xB5, 0x86, 0x46, 0x97, 0x74, 0xED, 0xB2, 0x8A, 0xDE, 0x78, 0x27, 0x62, 0x95, 0xAD, 0x40, 0x0D, 0xC6, 0xC8, 0xFC, 0x08, + 0x35, 0xC5, 0x38, 0xCB, 0x23, 0xC4, 0x99, 0x45, 0x61, 0xE4, 0xF1, 0xA8, 0x33, 0xCA, 0x31, 0x96, 0x2C, 0x67, 0x46, 0x09, + 0x72, 0x1B, 0x2D, 0x35, 0xD4, 0x50, 0xCA, 0xDB, 0x3B, 0xF4, 0x87, 0x4B, 0x3E, 0x36, 0x31, 0xF9, 0x7C, 0x2C, 0x31, 0x0E, + 0xF5, 0xF9, 0xC9, 0x22, 0xE9, 0x37, 0xB2, 0x0A, 0x4C, 0xA5, 0xFE, 0x45, 0xF8, 0x75, 0x78, 0x31, 0x69, 0xFC, 0x32, 0xD6, + 0x9F, 0xF6, 0x02, 0x8E, 0x55, 0xA6, 0xEE, 0xAF, 0x44, 0x10, 0xBB, 0x26, 0x7D, 0x05, 0x09, 0xD1, 0x37, 0xB1, 0xA1, 0x2F, + 0x7B, 0xF8, 0x94, 0x2B, 0x72, 0x74, 0xBC, 0x24, 0xED, 0x3E, 0x42, 0x7C, 0xCB, 0xAB, 0x2B, 0x4C, 0x8E, 0x4A, 0xB9, 0xD9, + 0x71, 0x85, 0x9A, 0x2C, 0x5D, 0x52, 0xB2, 0x9B, 0xDF, 0x91, 0xEA, 0x42, 0xBF, 0x43, 0xAA, 0xAE, 0x7E, 0x56, 0xD2, 0x8E, + 0xF0, 0xA2, 0x03, 0xB8, 0xEE, 0x32, 0xE9, 0x45, 0x7D, 0x78, 0xD6, 0x62, 0x3A, 0x9F, 0x9B, 0xCD, 0x97, 0xCA, 0xA7, 0xF8, + 0x6F, 0xF1, 0x21, 0x40, 0xA6, 0xBB, 0xDD, 0xA6, 0xAE, 0xD4, 0xD3, 0x0F, 0xDF, 0xA0, 0x13, 0x19, 0x38, 0x8D, 0x6C, 0x82, + 0xD7, 0xAD, 0x95, 0x26, 0x5F, 0x99, 0xFF, 0x86, 0x4F, 0xF0, 0x4F, 0xAA, 0xC1, 0x6F, 0x60, 0x58, 0x50, 0x5B, 0x59, 0xE0, + 0x4D, 0xB2, 0x92, 0x52, 0xEB, 0x6C, 0x77, 0x8F, 0x8E, 0x95, 0xBC, 0x5E, 0xBF, 0xBC, 0x7E, 0xA0, 0xA2, 0xB8, 0x65, 0x83, + 0x84, 0xDE, 0xF5, 0x52, 0x39, 0x59, 0xF9, 0xA5, 0x9F, 0xB8, 0xD2, 0xE0, 0x87, 0x10, 0xB7, 0x95, 0x06, 0x1E, 0x67, 0xAC, + 0xE3, 0x78, 0x2D, 0xA4, 0xEA, 0xA2, 0xBF, 0xF5, 0x59, 0x9D, 0xDA, 0x73, 0x4A, 0x1B, 0x78, 0xE5, 0xC7, 0x5C, 0x4C, 0x74, + 0x7E, 0xFE, 0xAC, 0x3A, 0xF0, 0xD4, 0x92, 0xD1, 0x96, 0x2A, 0x75, 0x80, 0xC4, 0xD3, 0x54, 0xDB, 0xF2, 0xA4, 0x52, 0xEE, + 0x56, 0xC7, 0x45, 0xB4, 0xD0, 0x65, 0x74, 0x01, 0x64, 0xDE, 0x71, 0x63, 0x9D, 0xB1, 0xCE, 0x63, 0x7B, 0x34, 0x59, 0xB5, + 0x4C, 0x1A, 0x75, 0x54, 0x44, 0xD1, 0x15, 0xDF, 0x70, 0x26, 0x47, 0x74, 0x2A, 0x83, 0xEA, 0xFE, 0xBC, 0xAE, 0xD6, 0x56, + 0xB0, 0x23, 0x90, 0x76, 0x40, 0xFE, 0x08, 0x3E, 0x24, 0x3D, 0x96, 0x61, 0xD4, 0xEA, 0x3A, 0x41, 0x8C, 0x7A, 0x64, 0x66, + 0xA9, 0xE8, 0x3D, 0x0F, 0xC7, 0xEC, 0x37, 0xFC, 0x82, 0x1B, 0x7C, 0xD8, 0xCE, 0x5B, 0x14, 0x56, 0x5D, 0xB8, 0xFB, 0xDF, + 0xD6, 0x92, 0x7B, 0x61, 0x54, 0x18, 0xA8, 0x41, 0xEB, 0x71, 0x18, 0x96, 0x8A, 0x5D, 0x45, 0x7E, 0xF6, 0x7F, 0xB0, 0xF3, + 0xD5, 0xF8, 0x7E, 0xA7, 0x0D, 0x9C, 0xCC, 0x06, 0xAA, 0x33, 0x54, 0x29, 0x19, 0x32, 0x4A, 0xBC, 0xC8, 0xD8, 0x3C, 0x18, + 0xED, 0x95, 0xA7, 0x01, 0x7B, 0x76, 0xC6, 0x63, 0x32, 0xAD, 0xD9, 0x7F, 0xC8, 0x11, 0x0F, 0x69, 0xEF, 0x86, 0x37, 0xA3, + 0x15, 0xBC, 0xBA, 0x9C, 0x46, 0xEC, 0xD7, 0xE6, 0x44, 0x62, 0xE8, 0x19, 0x6D, 0x97, 0xCD, 0xFF, 0xFF, 0xFF, 0x3A, 0xF3, + 0x78, 0xAF, 0x27, 0xFD, 0x43, 0x3B, 0x08, 0xD3, 0x32, 0x02, 0x90, 0x24, 0x50, 0x60, 0x99, 0xEC, 0xCB, 0xFA, 0x30, 0xFB, + 0x6E, 0x28, 0xC1, 0x07, 0x7E, 0x48, 0x98, 0x34, 0x51, 0x61, 0x12, 0xF2, 0xBC, 0xAD, 0xBF, 0x63, 0x27, 0x32, 0x48, 0xAE, + 0xE1, 0x00, 0x91, 0x25, 0xD0, 0x62, 0x11, 0x2A, 0xD2, 0x96, 0x52, 0x22, 0x95, 0x09, 0x3F, 0x85, 0xB3, 0x01, 0x99, 0x35, + 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, 0x52, 0x64, 0x48, 0x50, + 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, 0x82, 0x06, 0xC1, 0x45, + 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, 0x93, 0x27, 0x59, 0x71, + 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0xCF, 0x8C, 0x43, 0x4A, 0xF7, 0x4B, 0xED, 0xA1, 0x4B, 0xA7, 0x69, 0x88, 0x92, 0x2C, + 0x58, 0x68, 0x2D, 0x35, 0xD9, 0x58, 0x8B, 0x5B, 0xF8, 0xDF, 0x1E, 0xDA, 0x6D, 0xFC, 0x9A, 0x3C, 0x59, 0x69, 0xA4, 0x30, + 0x5C, 0x9B, 0xA3, 0x9F, 0x18, 0x20, 0x73, 0x37, 0xC5, 0xC1, 0x93, 0x2D, 0xD8, 0x6A, 0xB0, 0x5B, 0x28, 0xF6, 0x74, 0x6F, + 0x4F, 0xF4, 0x4D, 0x03, 0xAB, 0xB0, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, 0x1A, 0x2C, 0x52, 0x68, + 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, 0x4B, 0x4D, 0xDA, 0x7C, + 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, 0xDA, 0x6E, 0x4B, 0x59, + 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x5E, 0xAE, 0x83, 0x75, 0x84, 0x84, + 0x30, 0x30, 0x4A, 0xDB, 0x53, 0x42, 0x94, 0xA4, 0x70, 0x70, 0xB7, 0x72, 0x8D, 0xEC, 0x8C, 0x94, 0x31, 0x31, 0x64, 0x32, + 0xB5, 0x72, 0x9C, 0xB4, 0x71, 0x71, 0x5F, 0x50, 0x03, 0x77, 0x85, 0x85, 0xB0, 0x32, 0xAD, 0x23, 0x34, 0xE9, 0x95, 0xA5, + 0xF0, 0x72, 0x75, 0xB6, 0x54, 0x1C, 0x8D, 0x95, 0xB1, 0x33, 0x25, 0x33, 0x35, 0x07, 0x9D, 0xB5, 0xF1, 0x73, 0x44, 0xC0, + 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, 0x23, 0x15, 0xCC, 0xD4, + 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, 0xB2, 0x36, 0x55, 0xE1, + 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, 0xE3, 0x57, 0xDD, 0xF5, + 0xF3, 0x77, 0xB2, 0xF7, 0x8B, 0xC3, 0x86, 0x8C, 0x38, 0x38, 0x6E, 0x2A, 0xBC, 0x30, 0x96, 0xAC, 0x78, 0x78, 0x8C, 0x1C, + 0x7E, 0x4D, 0x8E, 0x9C, 0x39, 0x39, 0x24, 0x47, 0x6F, 0xA3, 0x9E, 0xBC, 0x79, 0x79, 0x27, 0x74, 0xC0, 0xA1, 0x87, 0x8D, + 0xB8, 0x3A, 0x2F, 0x1B, 0xE0, 0xFA, 0x97, 0xAD, 0xF8, 0x7A, 0xB0, 0x6B, 0xE9, 0x1D, 0x8F, 0x9D, 0xB9, 0x3B, 0x1C, 0x9D, + 0x39, 0xCA, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, 0x6A, 0x5C, 0xD6, 0xEC, + 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, 0x7B, 0x7D, 0x47, 0xC9, + 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, 0xAB, 0x1F, 0xCF, 0xDD, + 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x08, 0x60, 0xF0, 0xFA, 0x30, 0x22, 0x14, 0xA0, 0x34, 0xA6, + 0x4C, 0xD8, 0xB0, 0x26, 0x54, 0xE0, 0x01, 0x60, 0xBE, 0x9E, 0xA8, 0x16, 0x15, 0xA1, 0x06, 0xEA, 0x25, 0xE1, 0xB8, 0x36, + 0x55, 0xE1, 0x96, 0xDB, 0x82, 0x29, 0xA1, 0x07, 0x94, 0xA2, 0xEA, 0x14, 0xBB, 0xCB, 0xB1, 0x27, 0xD4, 0xE2, 0x41, 0x71, + 0x7A, 0x8D, 0xA9, 0x17, 0x95, 0xA3, 0x46, 0x41, 0xAF, 0xB9, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, 0x06, 0x84, 0xE0, 0x46, + 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, 0x17, 0xA5, 0x78, 0x72, + 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, 0xC6, 0xC6, 0xF1, 0x67, + 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, 0xD7, 0xE7, 0x1A, 0xF4, + 0x0A, 0xE8, 0xA2, 0x0E, 0x1C, 0xA8, 0x49, 0xAE, 0x07, 0x8A, 0xB2, 0x2E, 0x5C, 0xE8, 0x39, 0x01, 0x31, 0x1D, 0xAA, 0x1E, + 0x1D, 0xA9, 0x21, 0x3F, 0xAC, 0xCF, 0xBA, 0x3E, 0x5D, 0xE9, 0x39, 0x14, 0xF4, 0x5E, 0xA3, 0x0F, 0x9C, 0xAA, 0x8C, 0x77, + 0xE8, 0x61, 0xB3, 0x2F, 0xDC, 0xEA, 0xBA, 0x99, 0x0D, 0x2A, 0xAB, 0x1F, 0x9D, 0xAB, 0x98, 0x7E, 0x6E, 0x89, 0xBB, 0x3F, + 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, 0x5E, 0xEC, 0x6A, 0x5A, + 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, 0x8E, 0x8E, 0xE3, 0x4F, + 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, 0x9F, 0xAF, 0x7B, 0x7B, + 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x04, 0xAF, 0x87, 0xD1, 0xA4, 0x86, 0x34, 0xB0, 0x13, 0x9B, 0x62, 0x7A, 0xB4, 0xA6, + 0x74, 0xF0, 0xEC, 0x63, 0xDF, 0x10, 0xAC, 0x96, 0x35, 0xB1, 0x6C, 0xA9, 0x19, 0x45, 0xBC, 0xB6, 0x75, 0xF1, 0x86, 0x33, + 0x78, 0x31, 0xA5, 0x87, 0xB4, 0xB2, 0xF5, 0xBC, 0xCE, 0x06, 0xB5, 0xA7, 0xF4, 0xF2, 0x09, 0x6C, 0x44, 0x40, 0xAD, 0x97, + 0xB5, 0xB3, 0xAE, 0x8D, 0x95, 0x26, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, 0x36, 0xB4, 0x74, 0xE2, + 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, 0x67, 0xD5, 0xFC, 0xF6, + 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, 0xF6, 0xF6, 0x6D, 0xD3, + 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0xDD, 0xF5, 0x1F, 0x78, 0xA6, 0x8E, + 0x3C, 0xB8, 0x21, 0x2E, 0x07, 0xC4, 0xB6, 0xAE, 0x7C, 0xF8, 0xEA, 0x50, 0x96, 0x36, 0xAE, 0x9E, 0x3D, 0xB9, 0x6A, 0x84, + 0x4F, 0x9B, 0xBE, 0xBE, 0x7D, 0xF9, 0x8C, 0xCC, 0xA2, 0x46, 0xA7, 0x8F, 0xBC, 0xBA, 0x0D, 0x40, 0x5F, 0x2F, 0xB7, 0xAF, + 0xFC, 0xFA, 0xFD, 0x77, 0x41, 0xE0, 0xAF, 0x9F, 0xBD, 0xBB, 0xBB, 0xCB, 0xC9, 0x40, 0xBF, 0xBF, 0xFD, 0xFB, 0x66, 0xCA, + 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, 0x2F, 0x9D, 0xEE, 0xDE, + 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, 0xBE, 0xBE, 0x77, 0xEB, + 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, 0xEF, 0xDF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x10, 0x20, 0x10, 0x20, 0x40, 0x40, 0x90, 0x24, 0x50, 0x60, 0x08, 0x10, + 0x01, 0x01, 0x88, 0x14, 0x11, 0x21, 0x18, 0x30, 0x41, 0x41, 0x98, 0x34, 0x51, 0x61, 0x01, 0x01, 0x80, 0x02, 0x81, 0x05, + 0x90, 0x22, 0x11, 0x21, 0xC0, 0x42, 0x91, 0x25, 0xD0, 0x62, 0x09, 0x11, 0x81, 0x03, 0x89, 0x15, 0x91, 0x23, 0x19, 0x31, + 0xC1, 0x43, 0x99, 0x35, 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, + 0x52, 0x64, 0x48, 0x50, 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, + 0x82, 0x06, 0xC1, 0x45, 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, + 0x93, 0x27, 0x59, 0x71, 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0x02, 0x08, 0x08, 0x08, 0x82, 0x0C, 0x18, 0x28, 0x12, 0x28, + 0x48, 0x48, 0x92, 0x2C, 0x58, 0x68, 0x0A, 0x18, 0x09, 0x09, 0x8A, 0x1C, 0x19, 0x29, 0x1A, 0x38, 0x49, 0x49, 0x9A, 0x3C, + 0x59, 0x69, 0x03, 0x09, 0x88, 0x0A, 0x83, 0x0D, 0x98, 0x2A, 0x13, 0x29, 0xC8, 0x4A, 0x93, 0x2D, 0xD8, 0x6A, 0x0B, 0x19, + 0x89, 0x0B, 0x8B, 0x1D, 0x99, 0x2B, 0x1B, 0x39, 0xC9, 0x4B, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, + 0x1A, 0x2C, 0x52, 0x68, 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, + 0x4B, 0x4D, 0xDA, 0x7C, 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, + 0xDA, 0x6E, 0x4B, 0x59, 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, + 0x20, 0x10, 0x84, 0x84, 0x30, 0x30, 0x14, 0xA0, 0x60, 0x50, 0x94, 0xA4, 0x70, 0x70, 0x0C, 0x90, 0x21, 0x11, 0x8C, 0x94, + 0x31, 0x31, 0x1C, 0xB0, 0x61, 0x51, 0x9C, 0xB4, 0x71, 0x71, 0x05, 0x81, 0xA0, 0x12, 0x85, 0x85, 0xB0, 0x32, 0x15, 0xA1, + 0xE0, 0x52, 0x95, 0xA5, 0xF0, 0x72, 0x0D, 0x91, 0xA1, 0x13, 0x8D, 0x95, 0xB1, 0x33, 0x1D, 0xB1, 0xE1, 0x53, 0x9D, 0xB5, + 0xF1, 0x73, 0x44, 0xC0, 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, + 0x23, 0x15, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, + 0xB2, 0x36, 0x55, 0xE1, 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, + 0xE3, 0x57, 0xDD, 0xF5, 0xF3, 0x77, 0x06, 0x88, 0x28, 0x18, 0x86, 0x8C, 0x38, 0x38, 0x16, 0xA8, 0x68, 0x58, 0x96, 0xAC, + 0x78, 0x78, 0x0E, 0x98, 0x29, 0x19, 0x8E, 0x9C, 0x39, 0x39, 0x1E, 0xB8, 0x69, 0x59, 0x9E, 0xBC, 0x79, 0x79, 0x07, 0x89, + 0xA8, 0x1A, 0x87, 0x8D, 0xB8, 0x3A, 0x17, 0xA9, 0xE8, 0x5A, 0x97, 0xAD, 0xF8, 0x7A, 0x0F, 0x99, 0xA9, 0x1B, 0x8F, 0x9D, + 0xB9, 0x3B, 0x1F, 0xB9, 0xE9, 0x5B, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, + 0x6A, 0x5C, 0xD6, 0xEC, 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, + 0x7B, 0x7D, 0x47, 0xC9, 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, + 0xAB, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x20, 0x02, 0x04, 0x80, 0xA0, 0x06, + 0x14, 0xA0, 0x30, 0x22, 0x44, 0xC0, 0xB0, 0x26, 0x54, 0xE0, 0x28, 0x12, 0x05, 0x81, 0xA8, 0x16, 0x15, 0xA1, 0x38, 0x32, + 0x45, 0xC1, 0xB8, 0x36, 0x55, 0xE1, 0x21, 0x03, 0x84, 0x82, 0xA1, 0x07, 0x94, 0xA2, 0x31, 0x23, 0xC4, 0xC2, 0xB1, 0x27, + 0xD4, 0xE2, 0x29, 0x13, 0x85, 0x83, 0xA9, 0x17, 0x95, 0xA3, 0x39, 0x33, 0xC5, 0xC3, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, + 0x06, 0x84, 0xE0, 0x46, 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, + 0x17, 0xA5, 0x78, 0x72, 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, + 0xC6, 0xC6, 0xF1, 0x67, 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, + 0xD7, 0xE7, 0x22, 0x0A, 0x0C, 0x88, 0xA2, 0x0E, 0x1C, 0xA8, 0x32, 0x2A, 0x4C, 0xC8, 0xB2, 0x2E, 0x5C, 0xE8, 0x2A, 0x1A, + 0x0D, 0x89, 0xAA, 0x1E, 0x1D, 0xA9, 0x3A, 0x3A, 0x4D, 0xC9, 0xBA, 0x3E, 0x5D, 0xE9, 0x23, 0x0B, 0x8C, 0x8A, 0xA3, 0x0F, + 0x9C, 0xAA, 0x33, 0x2B, 0xCC, 0xCA, 0xB3, 0x2F, 0xDC, 0xEA, 0x2B, 0x1B, 0x8D, 0x8B, 0xAB, 0x1F, 0x9D, 0xAB, 0x3B, 0x3B, + 0xCD, 0xCB, 0xBB, 0x3F, 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, + 0x5E, 0xEC, 0x6A, 0x5A, 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, + 0x8E, 0x8E, 0xE3, 0x4F, 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, + 0x9F, 0xAF, 0x7B, 0x7B, 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x24, 0x82, 0x24, 0x90, 0xA4, 0x86, 0x34, 0xB0, 0x34, 0xA2, + 0x64, 0xD0, 0xB4, 0xA6, 0x74, 0xF0, 0x2C, 0x92, 0x25, 0x91, 0xAC, 0x96, 0x35, 0xB1, 0x3C, 0xB2, 0x65, 0xD1, 0xBC, 0xB6, + 0x75, 0xF1, 0x25, 0x83, 0xA4, 0x92, 0xA5, 0x87, 0xB4, 0xB2, 0x35, 0xA3, 0xE4, 0xD2, 0xB5, 0xA7, 0xF4, 0xF2, 0x2D, 0x93, + 0xA5, 0x93, 0xAD, 0x97, 0xB5, 0xB3, 0x3D, 0xB3, 0xE5, 0xD3, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, + 0x36, 0xB4, 0x74, 0xE2, 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, + 0x67, 0xD5, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, + 0xF6, 0xF6, 0x6D, 0xD3, 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x8A, + 0x2C, 0x98, 0xA6, 0x8E, 0x3C, 0xB8, 0x36, 0xAA, 0x6C, 0xD8, 0xB6, 0xAE, 0x7C, 0xF8, 0x2E, 0x9A, 0x2D, 0x99, 0xAE, 0x9E, + 0x3D, 0xB9, 0x3E, 0xBA, 0x6D, 0xD9, 0xBE, 0xBE, 0x7D, 0xF9, 0x27, 0x8B, 0xAC, 0x9A, 0xA7, 0x8F, 0xBC, 0xBA, 0x37, 0xAB, + 0xEC, 0xDA, 0xB7, 0xAF, 0xFC, 0xFA, 0x2F, 0x9B, 0xAD, 0x9B, 0xAF, 0x9F, 0xBD, 0xBB, 0x3F, 0xBB, 0xED, 0xDB, 0xBF, 0xBF, + 0xFD, 0xFB, 0x66, 0xCA, 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, + 0x2F, 0x9D, 0xEE, 0xDE, 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, + 0xBE, 0xBE, 0x77, 0xEB, 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, + 0xEF, 0xDF, 0xFF, 0xFF, 0x68, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x07, 0xFF, 0x80, 0x00, 0x55, 0x40, 0xA9, 0x57, 0x94, 0x3C, 0x0F, 0x02, 0x2B, 0xFA, 0xCA, 0x0A, 0xF3, 0x2E, 0x88, 0x98, + 0x01, 0x41, 0x67, 0x7F, 0xC6, 0xCC, 0x46, 0x33, 0xBE, 0x01, 0x60, 0xB0, 0x58, 0x10, 0x01, 0x80, 0x05, 0x42, 0x28, 0x56, + 0x1C, 0x7E, 0x0A, 0xD0, 0x58, 0x42, 0x83, 0x57, 0xE3, 0x92, 0x09, 0x95, 0x22, 0x66, 0xA9, 0xAB, 0x14, 0xA2, 0x19, 0x7A, + 0xC5, 0x63, 0x31, 0x0A, 0xD7, 0xD8, 0xE8, 0xE2, 0xDD, 0x5B, 0xFE, 0xE0, 0x73, 0x04, 0x80, 0x23, 0xB9, 0xE9, 0x10, 0xE1, + 0x5D, 0x65, 0xE8, 0x43, 0x2D, 0x61, 0x96, 0xF0, 0x1B, 0x88, 0x74, 0x97, 0x45, 0xD6, 0xAA, 0x70, 0x4B, 0x0B, 0xE9, 0xF2, + 0x4A, 0x85, 0x99, 0x41, 0x1B, 0x99, 0x18, 0x41, 0x67, 0x06, 0xE9, 0x4D, 0x3B, 0xF6, 0x92, 0x53, 0xFC, 0x87, 0x05, 0xD0, + 0x95, 0xA5, 0x1F, 0x6E, 0xE5, 0x6B, 0x19, 0xE5, 0x62, 0x6F, 0x92, 0xAC, 0x2E, 0x48, 0xDD, 0x44, 0x67, 0x08, 0x91, 0x5A, + 0xC6, 0x2D, 0xF7, 0xAE, 0x51, 0x05, 0x0A, 0x18, 0x09, 0x49, 0x86, 0x62, 0xB8, 0xA3, 0x12, 0x3D, 0xAE, 0x4D, 0xFA, 0xFC, + 0x95, 0xE2, 0xDA, 0x97, 0xAE, 0x49, 0x43, 0x75, 0x2D, 0x2C, 0x6A, 0x5B, 0x46, 0x2F, 0xAB, 0x7D, 0xDC, 0x65, 0xC9, 0x49, + 0x89, 0x0B, 0x70, 0xFF, 0x35, 0xA0, 0x1F, 0xDF, 0xD9, 0xB5, 0x99, 0xDF, 0x5B, 0x61, 0xAA, 0xEA, 0xAE, 0x8B, 0x4A, 0x3F, + 0x4E, 0x4E, 0x2D, 0x1B, 0x59, 0x4D, 0x56, 0x9D, 0x7C, 0x4C, 0xE2, 0xFA, 0xD4, 0x82, 0x88, 0x17, 0x78, 0x29, 0x64, 0x75, + 0x23, 0xDD, 0x5B, 0x6E, 0x33, 0x5D, 0x97, 0x6F, 0x64, 0x6D, 0x07, 0x9D, 0xE4, 0x6C, 0xEF, 0x6D, 0x43, 0x21, 0xED, 0x71, + 0xB1, 0x61, 0x8B, 0x59, 0xDF, 0xD1, 0xAA, 0x9D, 0x9F, 0x03, 0xA4, 0x0B, 0xE5, 0x90, 0x24, 0x0F, 0xF5, 0xB0, 0x04, 0x80, + 0x78, 0xF8, 0xDE, 0x80, 0x93, 0x36, 0x91, 0xA1, 0x64, 0xD0, 0x21, 0x62, 0x80, 0x76, 0xDE, 0xB0, 0x26, 0xE9, 0xEC, 0xD0, + 0x4D, 0x3E, 0x3C, 0x32, 0x5E, 0xB5, 0xE4, 0x36, 0x78, 0xB1, 0x4F, 0x28, 0x82, 0x11, 0x8D, 0xC9, 0xF2, 0x3D, 0x14, 0x21, + 0xC0, 0x5A, 0x99, 0xB0, 0x93, 0xB2, 0x02, 0x1D, 0x24, 0xE6, 0xED, 0xD1, 0xC5, 0xBE, 0x27, 0x4D, 0xE9, 0x35, 0xE5, 0x37, + 0xF8, 0xD3, 0x97, 0xD0, 0x3A, 0xCE, 0xE8, 0x23, 0x4D, 0x14, 0xD3, 0x10, 0x52, 0xF5, 0xAB, 0x60, 0x3E, 0x47, 0x12, 0xA1, + 0x27, 0x71, 0x1C, 0x3C, 0x1F, 0x78, 0x9C, 0x94, 0x07, 0xA2, 0xF0, 0x13, 0x9A, 0x9F, 0xC1, 0x6C, 0x8F, 0x56, 0x05, 0x09, + 0xAE, 0xC2, 0x01, 0x0B, 0x47, 0xA9, 0xDD, 0xE1, 0x7B, 0xC9, 0x52, 0xD5, 0x29, 0xEE, 0x32, 0xEE, 0xA3, 0x75, 0x59, 0xF5, + 0x63, 0xD5, 0xCD, 0x92, 0xF7, 0x5B, 0xC6, 0x71, 0xB2, 0x1E, 0xFE, 0x61, 0x18, 0x87, 0x0E, 0x12, 0xC4, 0xA7, 0xCC, 0xB1, + 0xDB, 0x7E, 0x8E, 0x12, 0x08, 0xAB, 0xAE, 0x18, 0x31, 0x67, 0x1B, 0x68, 0x37, 0x86, 0x54, 0x34, 0xAD, 0x5A, 0xAC, 0x94, + 0x09, 0x01, 0xDC, 0xCF, 0x47, 0xE1, 0x5D, 0x14, 0xCA, 0xF7, 0x9B, 0xBD, 0x5B, 0x3A, 0x56, 0x66, 0x48, 0xD4, 0xD0, 0xBD, + 0xCA, 0x3B, 0x25, 0x3E, 0x45, 0x52, 0x38, 0x19, 0x29, 0x18, 0x40, 0xE4, 0x05, 0x9C, 0x99, 0xA9, 0xC7, 0x5E, 0x68, 0x49, + 0xE7, 0xFA, 0x2A, 0x68, 0x36, 0x7C, 0x90, 0xCC, 0xDE, 0x46, 0x71, 0x9E, 0x9A, 0x26, 0x49, 0xC9, 0x41, 0x42, 0x1E, 0x78, + 0xF1, 0x13, 0x95, 0x3D, 0xA6, 0xAF, 0x03, 0x1D, 0xC4, 0xC1, 0x54, 0x29, 0xEC, 0xD5, 0x3B, 0x72, 0xF9, 0x9E, 0x4D, 0xC7, + 0x2F, 0x9F, 0xDD, 0xBB, 0x40, 0xCA, 0xE7, 0x06, 0xED, 0x16, 0x38, 0xBD, 0xF7, 0xD4, 0x20, 0x02, 0x04, 0xC0, 0x27, 0xE4, + 0x96, 0x88, 0x4A, 0x20, 0x7C, 0x4D, 0x12, 0xC4, 0xD6, 0xA8, 0x28, 0x12, 0x05, 0xC1, 0xD0, 0x64, 0x97, 0x85, 0xBE, 0x02, + 0x15, 0xDD, 0xBA, 0xD4, 0x53, 0x5A, 0xE7, 0x6C, 0x84, 0x82, 0x1A, 0x65, 0xD5, 0xE2, 0xD5, 0x04, 0x77, 0x48, 0x60, 0x55, + 0x77, 0x87, 0x29, 0x87, 0x85, 0x83, 0x38, 0xF5, 0x17, 0xA9, 0x95, 0x96, 0x04, 0x49, 0x52, 0xCA, 0xEB, 0xA1, 0x5F, 0x8D, + 0xBF, 0xC8, 0x9F, 0x35, 0x3C, 0x2D, 0xDC, 0x1D, 0x84, 0xA4, 0x30, 0xE2, 0xA0, 0xA6, 0xD7, 0xAF, 0x17, 0xE6, 0x97, 0xA5, + 0x31, 0x89, 0x58, 0xB2, 0x4B, 0x6E, 0x99, 0xB6, 0x5B, 0x4E, 0x11, 0x85, 0x2C, 0xC7, 0x65, 0x27, 0x92, 0x8A, 0xCA, 0x13, + 0x46, 0x40, 0xB3, 0x2D, 0xB5, 0xE2, 0x89, 0xE5, 0x00, 0x80, 0x96, 0x24, 0x84, 0xA6, 0xA9, 0x72, 0xC1, 0xCC, 0x29, 0x76, + 0xE4, 0xF6, 0x22, 0x0A, 0x0C, 0xC8, 0x44, 0x6C, 0x7D, 0xFD, 0xB5, 0x7A, 0x6C, 0xD4, 0x25, 0xC0, 0x37, 0xFF, 0x2A, 0x1A, + 0x0D, 0xC9, 0x0E, 0x7C, 0x5C, 0xB9, 0xF0, 0x38, 0x45, 0x01, 0xB2, 0xD8, 0x3E, 0xC9, 0x23, 0x9E, 0x8C, 0x8A, 0xBB, 0xCA, + 0x1E, 0x82, 0x97, 0x6B, 0x8C, 0x45, 0xB0, 0xE9, 0x6C, 0xEC, 0x72, 0xC8, 0x8D, 0x8B, 0xD3, 0x9D, 0x9C, 0xD3, 0xC1, 0xE4, + 0x2C, 0xCF, 0xC3, 0x79, 0x29, 0xA5, 0xCA, 0xE8, 0xD1, 0x63, 0xD8, 0x4A, 0x97, 0xC3, 0xF4, 0xD5, 0x46, 0xAC, 0x4A, 0x95, + 0xBF, 0x13, 0x14, 0xFF, 0xF2, 0xCF, 0x3A, 0x1D, 0xE4, 0x00, 0x04, 0xDB, 0xA6, 0xEE, 0x7D, 0x96, 0x6F, 0xA0, 0xF3, 0x39, + 0x65, 0xCD, 0x23, 0x1A, 0xA7, 0x5A, 0x2D, 0xCF, 0xC6, 0x43, 0x33, 0x7A, 0xE4, 0xE6, 0xAB, 0xF3, 0x83, 0xD3, 0xA2, 0x7F, + 0x3E, 0xEF, 0xD7, 0xE8, 0xD3, 0xC5, 0x04, 0x0C, 0xCB, 0x6D, 0x4D, 0x79, 0xA6, 0xB4, 0x7B, 0x86, 0x43, 0xBC, 0x30, 0xBE, + 0xB9, 0x5A, 0x93, 0x16, 0xF3, 0x57, 0xA3, 0xE0, 0x86, 0xF4, 0x27, 0xF6, 0x25, 0xB7, 0x0D, 0xF2, 0xD7, 0x5C, 0x63, 0x1B, + 0x73, 0xB1, 0x2D, 0x7E, 0x25, 0x49, 0x65, 0xEE, 0x76, 0x4F, 0x1D, 0x92, 0x45, 0xDB, 0x1D, 0x01, 0x71, 0xD5, 0xC2, 0x69, + 0x72, 0xCC, 0xA1, 0xE0, 0xD6, 0x2C, 0xD9, 0x94, 0x52, 0x5E, 0xAC, 0xC5, 0x0A, 0xB1, 0xCA, 0xC5, 0x6E, 0x54, 0xE5, 0x42, + 0x4D, 0xDD, 0xE6, 0x5D, 0x6E, 0x74, 0x24, 0xE7, 0x45, 0xE5, 0x6A, 0x95, 0x9B, 0x55, 0xD4, 0x29, 0xC2, 0xD9, 0x79, 0xE3, + 0x4D, 0x78, 0x66, 0x72, 0x79, 0x0D, 0x47, 0xD7, 0xF5, 0xC3, 0x4E, 0xB8, 0x63, 0xB8, 0x2B, 0x47, 0xEE, 0xD2, 0x4D, 0x18, + 0xF0, 0xCC, 0xFF, 0x7D, 0xE3, 0x52, 0x0A, 0x17, 0xBB, 0x1C, 0x29, 0xB4, 0x25, 0x77, 0xAD, 0x95, 0xF3, 0xDB, 0x7F, 0x8A, + 0x53, 0x98, 0xDE, 0x8C, 0xCB, 0xFA, 0xD2, 0x8D, 0xDF, 0x55, 0x36, 0x86, 0x80, 0xDB, 0x55, 0x6B, 0x8D, 0x45, 0x0A, 0xFC, + 0x7E, 0x56, 0x9E, 0xF0, 0xF8, 0x75, 0x6E, 0x3A, 0x79, 0xE8, 0x1D, 0x6D, 0xBC, 0x64, 0xF8, 0x04, 0x3E, 0x92, 0xD3, 0x8C, + 0x7D, 0x76, 0x77, 0xAB, 0xCC, 0x0F, 0x71, 0xE3, 0x74, 0x30, 0xD7, 0x1D, 0xBE, 0x5D, 0x9B, 0xF5, 0x4E, 0xBE, 0x60, 0xB7, + 0x7A, 0xFC, 0x93, 0xCA, 0x2E, 0x5C, 0x36, 0xCF, 0x38, 0xFE, 0x7E, 0xA0, 0x68, 0x7F, 0x89, 0x9D, 0x2E, 0x75, 0x52, 0xDE, + 0xA6, 0xF2, 0xA6, 0xDB, 0x54, 0xFE, 0x2A, 0xBD, 0xAD, 0xBD, 0x81, 0x16, 0x07, 0xB0, 0x18, 0xB8, 0xBD, 0x9F, 0x83, 0x4B, + 0xF8, 0xBF, 0xF8, 0xF4, 0xC4, 0x73, 0x77, 0x8F, 0xFA, 0xD2, 0xAF, 0x47, 0xCC, 0x6B, 0xEB, 0x5B, 0xF3, 0x4F, 0x37, 0xFF, + 0x66, 0x60, 0x00, 0x7B, 0x90, 0xDE, 0xBF, 0x70, 0x08, 0x09, 0x88, 0x00, 0x99, 0x9F, 0xF7, 0xE0, 0x58, 0x02, 0x28, 0xDA, + 0x56, 0x22, 0xF4, 0x63, 0x4E, 0x00, 0x98, 0x66, 0x15, 0x0D, 0x10, 0x34, 0xC8, 0xFE, 0x34, 0xAB, 0xDE, 0xE7, 0x81, 0x42, + 0x7B, 0x2E, 0xAD, 0xE2, 0x79, 0xC8, 0xD1, 0xA2, 0x4D, 0xB4, 0xB7, 0xA1, 0xD6, 0x64, 0x33, 0x15, 0x08, 0x6C, 0x75, 0x91, + 0xDD, 0x31, 0x35, 0xD6, 0x28, 0x59, 0x98, 0xF5, 0x9B, 0x21, 0x81, 0xC4, 0x04, 0xAF, 0x1F, 0x45, 0x14, 0x7E, 0x0E, 0xC4, + 0x4A, 0xE4, 0xF0, 0xF0, 0x61, 0xE1, 0xF7, 0xA1, 0xA0, 0xB5, 0x3E, 0xC8, 0xB2, 0xDA, 0x88, 0x16, 0xBC, 0x3E, 0xE7, 0xB4, + 0x4B, 0x7E, 0x3E, 0xC5, 0xF9, 0x6F, 0x44, 0x5A, 0xB4, 0x20, 0x05, 0x63, 0x1D, 0x5D, 0x66, 0x6D, 0xD4, 0x86, 0x7B, 0x96, + 0x49, 0xD7, 0xF7, 0x5D, 0xB7, 0x3C, 0xD9, 0xF5, 0xCD, 0x5B, 0xEF, 0x4A, 0xCB, 0x25, 0x38, 0xF7, 0x0E, 0x52, 0x2E, 0x93, + 0x19, 0xC8, 0x02, 0x4A, 0x4C, 0x64, 0x52, 0x92, 0xF9, 0x97, 0xCA, 0x9B, 0x0F, 0xCB, 0x6D, 0x5C, 0x15, 0x82, 0xB6, 0xA7, + 0x48, 0xA9, 0x5A, 0x44, 0xA2, 0x2B, 0x86, 0x16, 0xAE, 0x48, 0x43, 0x89, 0x12, 0x44, 0xEF, 0xAD, 0x84, 0x4A, 0xC9, 0xA2, + 0xAC, 0x28, 0x1B, 0x59, 0xC1, 0xF6, 0x5B, 0x1C, 0xAA, 0xEA, 0xDB, 0xBD, 0x43, 0x27, 0xC4, 0x58, 0x24, 0x05, 0x18, 0x4A, + 0xB9, 0xA5, 0xD3, 0x2A, 0xE5, 0x6E, 0x8F, 0x79, 0x4C, 0x0E, 0x54, 0x17, 0x5B, 0xDC, 0x14, 0xFC, 0x03, 0xA0, 0xF0, 0xA3, + 0x1D, 0x77, 0x12, 0x7D, 0x20, 0x0E, 0x83, 0x4E, 0xB2, 0x7D, 0x3B, 0xC3, 0x8B, 0x6E, 0x8E, 0x39, 0x67, 0x6F, 0x6B, 0xED, + 0x80, 0x7E, 0xE9, 0x85, 0x36, 0x21, 0x48, 0x9E, 0x49, 0x0F, 0x4E, 0x42, 0xBD, 0x29, 0x5F, 0x0A, 0xD7, 0x21, 0x23, 0x75, + 0x32, 0x5F, 0xE8, 0x1F, 0x21, 0x70, 0xE4, 0x37, 0x16, 0x3D, 0x2D, 0xE0, 0x64, 0x7C, 0xEB, 0xE7, 0xDF, 0xDD, 0x9C, 0xF6, + 0xDE, 0x53, 0x2C, 0x54, 0x2D, 0x54, 0xD2, 0x90, 0xCC, 0x11, 0xB0, 0x53, 0x1A, 0x52, 0x5B, 0x25, 0xA8, 0x09, 0x69, 0xF5, + 0x30, 0xB4, 0x6A, 0xE2, 0x4F, 0xFF, 0x5B, 0x85, 0x51, 0x32, 0x40, 0xE5, 0x5C, 0x5B, 0xB5, 0xE5, 0x31, 0xB5, 0x31, 0x56, + 0x9E, 0x73, 0x99, 0x31, 0xBB, 0x7A, 0xFB, 0x53, 0x3A, 0xC9, 0x7F, 0x56, 0x32, 0x75, 0x72, 0x20, 0x72, 0x38, 0x46, 0x17, + 0xF6, 0xF9, 0x12, 0x74, 0x2B, 0xB8, 0x73, 0x46, 0x77, 0xE8, 0xFC, 0x30, 0x6F, 0xFE, 0x85, 0xC7, 0x75, 0x95, 0x27, 0xC1, + 0xA3, 0x76, 0x05, 0x7C, 0xF9, 0x58, 0xEA, 0x91, 0x62, 0xD0, 0x87, 0x53, 0x19, 0x12, 0xC8, 0x16, 0x61, 0x57, 0xAF, 0xD5, + 0x97, 0x9A, 0x8D, 0xF0, 0xAB, 0x74, 0xE1, 0xB5, 0xB7, 0xFA, 0xD6, 0x60, 0x0C, 0x55, 0x26, 0x4C, 0x34, 0xC3, 0xD6, 0x64, + 0x74, 0xAC, 0xDE, 0x35, 0x1B, 0x3B, 0xCE, 0x8D, 0x68, 0x13, 0x7D, 0xFE, 0xC6, 0x94, 0x56, 0xAD, 0x6F, 0x1B, 0x6A, 0xFB, + 0x18, 0x7D, 0x45, 0x72, 0x49, 0xE5, 0x83, 0xA9, 0xBE, 0x78, 0xC7, 0x2D, 0xAE, 0x6A, 0x81, 0x0C, 0xFE, 0x38, 0x8C, 0x71, + 0x8D, 0x56, 0x8A, 0xDA, 0x67, 0x31, 0x7B, 0x7E, 0x37, 0x53, 0xFD, 0xBE, 0xF8, 0x6B, 0x0E, 0xC0, 0xC3, 0x8C, 0x08, 0x1C, + 0xBE, 0x37, 0x76, 0x36, 0x59, 0x1F, 0x8F, 0xDB, 0xDD, 0x83, 0x62, 0x23, 0xA2, 0x72, 0x38, 0x3D, 0x9A, 0xB4, 0x18, 0x4E, + 0xE6, 0xF0, 0x73, 0x14, 0x97, 0x30, 0x25, 0xCD, 0xA9, 0x5E, 0x47, 0x32, 0x9E, 0x38, 0xEF, 0x10, 0xA2, 0x1C, 0x47, 0xFC, + 0x9E, 0x7A, 0x71, 0x11, 0x8B, 0xB2, 0xCB, 0xBD, 0xB7, 0xC4, 0xDC, 0x66, 0x0A, 0x89, 0xDD, 0x1B, 0x84, 0x5F, 0x46, 0x0A, + 0x07, 0xE0, 0x18, 0xF9, 0x12, 0x9A, 0xD7, 0xE2, 0x48, 0x6B, 0xD2, 0x2E, 0x55, 0x80, 0xBA, 0x74, 0xFA, 0xC3, 0x84, 0xED, + 0xFC, 0x4B, 0x80, 0xCD, 0x43, 0xFB, 0x78, 0xC7, 0xAE, 0xA3, 0x7F, 0xA7, 0x8C, 0x99, 0x3B, 0x78, 0x91, 0xE1, 0xE1, 0x22, + 0xF7, 0xD3, 0xEF, 0x83, 0xDC, 0xA0, 0x64, 0x67, 0x08, 0x08, 0xB9, 0x64, 0x91, 0x8F, 0xA3, 0xB7, 0xCB, 0x3B, 0xE6, 0x52, + 0x28, 0x48, 0x28, 0x46, 0x8F, 0x3B, 0x16, 0xDA, 0xB7, 0x5B, 0x12, 0x62, 0x47, 0xFE, 0x08, 0x14, 0xBD, 0x25, 0x78, 0x24, + 0x03, 0xA9, 0xF9, 0x30, 0xE8, 0xE7, 0x68, 0x05, 0x43, 0xC1, 0x79, 0xB6, 0x23, 0x6E, 0x4D, 0xA4, 0x6F, 0x9C, 0xDF, 0x4F, + 0xB2, 0xBD, 0x51, 0x3A, 0x2F, 0xDC, 0xCF, 0x53, 0x5B, 0x40, 0x95, 0xD7, 0x81, 0x50, 0xA4, 0x23, 0x6A, 0xE6, 0xF3, 0x82, + 0xED, 0xE7, 0x3C, 0x46, 0xB3, 0x48, 0x26, 0x95, 0x09, 0xCB, 0x5E, 0x7D, 0x00, 0x21, 0x62, 0x48, 0x48, 0xE4, 0xCA, 0x22, + 0x5A, 0x4A, 0x3A, 0x7C, 0x09, 0xA5, 0x2F, 0x6E, 0x11, 0xA0, 0xBA, 0x5A, 0x49, 0xE5, 0x9A, 0xD4, 0x3E, 0xED, 0x0F, 0xF0, + 0x65, 0x60, 0x23, 0x6F, 0x84, 0x07, 0x4C, 0x58, 0x9C, 0x43, 0xA6, 0x5C, 0x7F, 0x63, 0xD7, 0x9F, 0xC1, 0x99, 0x2F, 0xEE, + 0xBB, 0x8B, 0x44, 0x7C, 0xCB, 0x49, 0xDA, 0xFF, 0xD9, 0xC7, 0x5A, 0xB5, 0xE7, 0x5C, 0xBB, 0x67, 0xBB, 0x53, 0xB2, 0xFB, + 0x6F, 0xC6, 0x52, 0x1C, 0x3C, 0x2B, 0x15, 0x25, 0x77, 0x72, 0x7A, 0xDA, 0x65, 0x07, 0x2E, 0xFE, 0x49, 0xAA, 0x3A, 0x6B, + 0xF6, 0xE7, 0x3D, 0xA9, 0x82, 0x0A, 0x23, 0x86, 0xFB, 0x53, 0x34, 0x9B, 0xE8, 0x6F, 0x8D, 0x68, 0xED, 0x6B, 0x51, 0xFE, + 0x78, 0xE1, 0x47, 0x20, 0x5D, 0x8F, 0x97, 0x0B, 0x4F, 0x49, 0x3B, 0x8F, 0x41, 0x4E, 0x26, 0x7D, 0xCD, 0xC0, 0x24, 0x84, + 0x3C, 0xDC, 0xB0, 0x53, 0x42, 0xF0, 0x58, 0xD9, 0x15, 0xF4, 0x26, 0xD2, 0x29, 0x3A, 0xA8, 0x12, 0x79, 0x50, 0xF8, 0x77, + 0x47, 0xDC, 0xE2, 0x12, 0x7D, 0x51, 0x67, 0x78, 0xA2, 0x72, 0xAD, 0x82, 0xDF, 0xF1, 0xF5, 0xB6, 0xB8, 0x90, 0xD7, 0xA0, + 0xF5, 0x92, 0xFD, 0x92, 0x4C, 0x03, 0xB7, 0x96, 0x94, 0x13, 0xBD, 0xF0, 0x1E, 0x7E, 0xE9, 0xB5, 0x22, 0x5E, 0xE4, 0x81, + 0x89, 0x3F, 0xE4, 0xE2, 0xD7, 0xB2, 0x7C, 0xE7, 0x0D, 0x97, 0x64, 0x84, 0x89, 0xB9, 0x74, 0x12, 0x75, 0x1E, 0x9A, 0x35, + 0x96, 0xBC, 0x1E, 0xF2, 0x66, 0xF7, 0x43, 0xB1, 0xB5, 0x35, 0x31, 0xC2, 0xA0, 0x34, 0x13, 0x26, 0x15, 0xB0, 0x71, 0x90, + 0xFA, 0xB8, 0x8A, 0x63, 0x8D, 0x9F, 0xBD, 0xE2, 0x8D, 0xD5, 0x6B, 0xA5, 0x84, 0x52, 0x5D, 0xE2, 0x0E, 0x3D, 0x6D, 0x91, + 0x0C, 0xB5, 0x3C, 0x8B, 0x0D, 0xF8, 0x66, 0x9B, 0x1E, 0xB3, 0x35, 0xDA, 0x68, 0xD1, 0x33, 0xDE, 0x78, 0xF3, 0x39, 0x1E, + 0x2B, 0x1D, 0x90, 0x93, 0x5C, 0xD9, 0xAE, 0xDC, 0x92, 0xC2, 0xE6, 0x9F, 0x7B, 0x19, 0x79, 0x2F, 0xA4, 0x81, 0x23, 0x7E, + 0x9A, 0x9A, 0xB7, 0xE8, 0x17, 0xC1, 0x25, 0x2B, 0xB0, 0x1B, 0xD0, 0xE8, 0xBD, 0xF5, 0xF7, 0xB6, 0x8E, 0xEA, 0xAD, 0xDD, + 0x60, 0x2D, 0xEF, 0xCF, 0xF5, 0xF0, 0xA6, 0x6D, 0xA1, 0x15, 0x1E, 0x2C, 0xC1, 0xFD, 0x66, 0x9C, 0x26, 0x77, 0xA9, 0x8B, + 0x83, 0x90, 0xEF, 0xA5, 0x4E, 0x99, 0x6E, 0xDC, 0x7C, 0xA6, 0xBE, 0x22, 0xB3, 0x29, 0xFD, 0xEF, 0xFA, 0x6D, 0x47, 0x59, + 0x26, 0x96, 0x27, 0x9F, 0xC2, 0xB6, 0xA7, 0xEA, 0x6E, 0x7E, 0x95, 0xE7, 0xDA, 0xFD, 0x0D, 0xCC, 0xAC, 0xFF, 0x59, 0xB9, + 0x9C, 0xFF, 0xAF, 0xC4, 0xC9, 0x9E, 0x3F, 0x56, 0xA8, 0xBE, 0xA8, 0x31, 0xE1, 0x1B, 0x07, 0x66, 0xD1, 0xAA, 0x28, 0xD3, + 0x5F, 0x46, 0x77, 0xE4, 0x14, 0x7B, 0x76, 0x49, 0x84, 0x60, 0xBA, 0xFD, 0xDF, 0x4E, 0x9F, 0xC1, 0xE2, 0x11, 0x60, 0x14, + 0x5F, 0xD1, 0x34, 0xE7, 0x05, 0x43, 0x06, 0xF4, 0x33, 0x23, 0x31, 0x0A, 0x61, 0xC8, 0x54, 0x43, 0xE3, 0xB2, 0x77, 0x49, + 0xB2, 0xE6, 0xB7, 0xF7, 0x8B, 0x4C, 0x2B, 0xB3, 0x23, 0xD1, 0xBF, 0x44, 0xF0, 0xCE, 0xD7, 0xA8, 0x90, 0x49, 0x81, 0x22, + 0x21, 0x44, 0xD2, 0x86, 0xA9, 0xDE, 0xEE, 0x59, 0x98, 0x4D, 0xDB, 0xA8, 0x03, 0x47, 0xFA, 0xAB, 0xE7, 0x2A, 0x4A, 0x61, + 0x70, 0x57, 0x3F, 0xB4, 0x57, 0x2B, 0xBE, 0xBD, 0x82, 0xB3, 0x39, 0xB4, 0x31, 0xD5, 0x31, 0x63, 0x60, 0x4B, 0xD9, 0x70, + 0x3B, 0x97, 0xC5, 0x23, 0xB0, 0x11, 0x09, 0xB9, 0x50, 0x65, 0xA1, 0xF3, 0x43, 0x7C, 0xCF, 0xF7, 0x53, 0xBF, 0xFA, 0x4E, + 0x56, 0x44, 0xB8, 0xE4, 0xAC, 0x67, 0x6A, 0x6E, 0x1E, 0x4E, 0x8C, 0x6B, 0x92, 0xA1, 0x72, 0xE9, 0x55, 0xF6, 0xD1, 0x1E, + 0x62, 0x87, 0x7A, 0x3A, 0xA1, 0x44, 0x82, 0x2F, 0x3C, 0x6A, 0x13, 0x8B, 0x62, 0x25, 0x58, 0x13, 0xE7, 0x64, 0x33, 0x1F, + 0x69, 0x95, 0xDB, 0x28, 0x10, 0xA3, 0x6B, 0x1B, 0xCE, 0x06, 0x56, 0x3D, 0x9F, 0x10, 0x64, 0x47, 0x22, 0xA1, 0xA5, 0x4C, + 0x54, 0xCD, 0xBA, 0xA0, 0xD6, 0x41, 0xC8, 0x10, 0x98, 0x24, 0x6A, 0xED, 0x44, 0x2E, 0xEA, 0x2B, 0x54, 0x6D, 0xDD, 0xDC, + 0x06, 0x80, 0x7B, 0xDE, 0x39, 0x4D, 0x59, 0x9A, 0xEA, 0x46, 0x3A, 0x7C, 0xDB, 0xED, 0xBC, 0xB5, 0x8A, 0xBB, 0x36, 0x3F, + 0x39, 0x62, 0x19, 0xF4, 0x48, 0xC9, 0xEB, 0x79, 0x7E, 0x3E, 0x12, 0x46, 0x2C, 0x4D, 0xB3, 0xB5, 0xC7, 0x62, 0xDF, 0x89, + 0x97, 0x40, 0x6B, 0xF9, 0x5D, 0x6F, 0xD9, 0x10, 0x5B, 0xEF, 0xFA, 0xF4, 0x91, 0xBC, 0x5E, 0xBD, 0x8B, 0x53, 0x82, 0xD4, + 0x9B, 0xFA, 0x7A, 0x6D, 0xC2, 0x6A, 0x74, 0x16, 0xB1, 0x78, 0x18, 0x32, 0xE1, 0xA9, 0xBC, 0x9E, 0xD0, 0xFD, 0xC5, 0x78, + 0x8B, 0xC9, 0xCF, 0x98, 0x83, 0x40, 0x4D, 0xA4, 0x8B, 0x51, 0x55, 0xE8, 0x61, 0x74, 0x0B, 0xE3, 0x5A, 0x51, 0xB5, 0x30, + 0x37, 0x51, 0x25, 0xE3, 0xA2, 0xA3, 0xD7, 0xA8, 0xC2, 0x65, 0x7A, 0x10, 0x49, 0x1B, 0x9A, 0xA6, 0x3C, 0x56, 0x34, 0xE2, + 0xD1, 0x59, 0xB4, 0xE6, 0x47, 0x79, 0xA9, 0xA3, 0x80, 0x5A, 0xCE, 0xF2, 0x35, 0x73, 0xA7, 0x12, 0xE1, 0x51, 0xE4, 0x0F, + 0x86, 0x6E, 0x47, 0xF3, 0x5D, 0x0D, 0x8F, 0x78, 0x90, 0x3B, 0x1F, 0xFC, 0x60, 0x31, 0x2E, 0x67, 0x72, 0x4F, 0x4C, 0xAE, + 0x04, 0xBA, 0x4B, 0x57, 0x33, 0x8C, 0x20, 0x93, 0x22, 0xDD, 0xDE, 0x13, 0x0A, 0x67, 0x59, 0x69, 0x5F, 0xC4, 0x32, 0xEE, + 0x9C, 0x95, 0x14, 0x40, 0xD8, 0x17, 0x6E, 0xCE, 0x3B, 0x88, 0x34, 0x63, 0x2F, 0xA2, 0x54, 0x9D, 0x0A, 0x4B, 0x06, 0xAC, + 0x94, 0x37, 0xFF, 0xDA, 0x5A, 0x19, 0xD8, 0x9F, 0x97, 0xBA, 0x67, 0x91, 0x8B, 0xCE, 0xAF, 0x56, 0x89, 0x7A, 0xCE, 0xB2, + 0x5F, 0x61, 0x53, 0xEB, 0x9A, 0x29, 0x37, 0x62, 0x98, 0x5B, 0x79, 0x19, 0xE8, 0x9B, 0xC5, 0xAC, 0x5E, 0x60, 0x8A, 0x39, + 0x89, 0x9C, 0xFE, 0x69, 0xBC, 0x6C, 0xD1, 0x6A, 0xC4, 0xC3, 0x2E, 0x6E, 0xFA, 0xF6, 0x36, 0x3E, 0x3B, 0xE0, 0xEE, 0x30, + 0x9A, 0x92, 0x66, 0x28, 0x37, 0x5B, 0xFE, 0x39, 0xDA, 0xD6, 0x75, 0x36, 0xBA, 0xB3, 0x97, 0xC1, 0xDC, 0x38, 0x2F, 0x6B, + 0x6A, 0x61, 0xEF, 0x1E, 0xED, 0x78, 0xB7, 0x5B, 0x2B, 0x27, 0xD3, 0xFA, 0x1A, 0x24, 0xAB, 0x06, 0x48, 0xD2, 0xD6, 0xFD, + 0x10, 0x47, 0x0A, 0xD2, 0x58, 0x00, 0x34, 0xFA, 0xC1, 0x5B, 0x0F, 0xD1, 0x57, 0xC6, 0x2A, 0x66, 0x58, 0x44, 0x12, 0x90, + 0xEF, 0x16, 0x5E, 0xFB, 0x43, 0xE3, 0xE7, 0xD4, 0xAC, 0xDB, 0xAE, 0x56, 0x17, 0x4E, 0x41, 0xB0, 0x22, 0x8D, 0xEA, 0xFF, + 0x14, 0x19, 0x11, 0x14, 0x65, 0xD9, 0xAF, 0x87, 0x3D, 0xE1, 0x51, 0x55, 0xDD, 0x98, 0xF4, 0x32, 0x17, 0xA7, 0x37, 0xE6, + 0xE6, 0x53, 0xE9, 0x24, 0xF4, 0xEC, 0xFB, 0xA0, 0xEF, 0xEE, 0xFA, 0x42, 0x37, 0x3F, 0x10, 0x60, 0xFA, 0xC9, 0x2F, 0x16, + 0x21, 0xE4, 0x4E, 0xB0, 0x4C, 0x2A, 0x92, 0xA9, 0x95, 0xA1, 0x8C, 0x89, 0xE4, 0xC3, 0x7F, 0x10, 0x36, 0xA5, 0x47, 0x93, + 0x25, 0x03, 0x81, 0x45, 0xEA, 0xAB, 0x5B, 0xB3, 0x9A, 0xC0, 0x31, 0x8A, 0xA4, 0xFD, 0xA3, 0x02, 0xCC, 0x8C, 0x7A, 0x35, + 0xEA, 0xAC, 0x59, 0x5C, 0x66, 0x4D, 0xA1, 0x73, 0x7F, 0x87, 0xC3, 0xFC, 0x1C, 0x47, 0x3A, 0x6C, 0x5F, 0x5A, 0x8A, 0xCA, + 0x54, 0x63, 0x90, 0xC6, 0xCC, 0x27, 0x4A, 0xA9, 0xCA, 0x86, 0xE0, 0x83, 0xF6, 0x60, 0x45, 0xCA, 0x41, 0x86, 0xC4, 0xFB, + 0x6E, 0x8B, 0x5D, 0x47, 0x67, 0xF2, 0xDD, 0x7E, 0x30, 0xA7, 0xFD, 0xB6, 0xA7, 0xD0, 0x8D, 0x5E, 0xB4, 0x23, 0xF0, 0xA8, + 0xF2, 0xF5, 0x1F, 0x7D, 0xDE, 0x5B, 0x5B, 0x39, 0x90, 0xC6, 0x43, 0xD7, 0xC3, 0xA6, 0xE2, 0x4B, 0x29, 0xE2, 0xE5, 0x2C, + 0x10, 0xEA, 0xF5, 0xE8, 0xAC, 0xCC, 0x92, 0x6C, 0x6F, 0xE1, 0x54, 0x8B, 0xCD, 0x0D, 0xD2, 0x19, 0x11, 0xCF, 0x42, 0x28, + 0x0C, 0x3D, 0xC2, 0x85, 0xAA, 0x42, 0x5D, 0x9F, 0x4C, 0x13, 0x23, 0xEF, 0x98, 0x6E, 0x0B, 0xE9, 0x4E, 0xD1, 0x08, 0xED, + 0x5E, 0x07, 0x63, 0x5F, 0x87, 0xC4, 0x0B, 0x4E, 0x1D, 0xAB, 0x1B, 0xCC, 0xD1, 0xC0, 0xE8, 0x04, 0x34, 0x5E, 0xDC, 0x6A, + 0x78, 0xDD, 0xFD, 0x99, 0x70, 0xB1, 0x0A, 0x02, 0x24, 0xCB, 0x13, 0xC0, 0x57, 0x90, 0x20, 0x67, 0xA0, 0xD3, 0xBA, 0xE7, + 0xDE, 0x18, 0x8D, 0xD0, 0x44, 0x51, 0x9C, 0xEF, 0xD4, 0x93, 0x3F, 0x87, 0x87, 0xD2, 0x26, 0x8E, 0x5D, 0x7B, 0x04, 0x45, + 0x66, 0xD6, 0xEF, 0xAF, 0x53, 0xF4, 0x85, 0x82, 0x44, 0x88, 0x97, 0x64, 0xD0, 0xB5, 0x05, 0x5B, 0x2F, 0x9C, 0x79, 0x32, + 0xB6, 0x01, 0x5C, 0x3C, 0xA4, 0x90, 0x47, 0x30, 0xB4, 0xB0, 0x14, 0x51, 0xC1, 0xDB, 0xAD, 0x61, 0x97, 0xBB, 0x66, 0x7F, + 0xA5, 0x91, 0x58, 0xB4, 0xDC, 0x44, 0x36, 0xEF, 0xE5, 0x52, 0x9C, 0xF4, 0xE5, 0xF8, 0x6C, 0x2B, 0x91, 0xD4, 0x35, 0xA5, + 0x5D, 0x67, 0x15, 0xE0, 0xF2, 0xDB, 0xF4, 0x94, 0xE1, 0xB9, 0xE0, 0xB1, 0x50, 0x91, 0xBD, 0xD6, 0xE1, 0xB6, 0x79, 0x11, + 0x46, 0x7C, 0x02, 0x1F, 0xF2, 0x7A, 0x26, 0x6C, 0xCD, 0x9E, 0x86, 0xF2, 0x9D, 0x67, 0x6F, 0x3C, 0x8D, 0x97, 0xE6, 0xCC, + 0x6C, 0x5C, 0xB5, 0x17, 0x2B, 0x22, 0xD0, 0xFE, 0x0E, 0x69, 0x5E, 0xB8, 0xBB, 0xD4, 0x29, 0xBC, 0x39, 0x5D, 0x03, 0xD7, + 0x0F, 0xD8, 0x63, 0x0A, 0xFF, 0x48, 0x36, 0x5B, 0xED, 0x95, 0x7B, 0x93, 0x34, 0x70, 0x3E, 0x19, 0x2D, 0x03, 0x91, 0xEF, + 0x1A, 0xD7, 0x15, 0x6B, 0xB1, 0xD2, 0xF5, 0x83, 0x35, 0x91, 0x46, 0x86, 0x1D, 0x27, 0x61, 0x43, 0xD7, 0x6D, 0x0E, 0xE6, + 0x8E, 0xD3, 0x0E, 0xE6, 0x83, 0xB3, 0xD9, 0x5E, 0x00, 0x83, 0xAC, 0xA8, 0xC0, 0x10, 0x54, 0x2A, 0x33, 0xDB, 0xFD, 0x8D, + 0x0F, 0xB2, 0xA7, 0x9B, 0x90, 0xD2, 0x0B, 0x5C, 0x97, 0xB6, 0x17, 0xE8, 0xFA, 0xD3, 0xA7, 0xFA, 0xC3, 0xE5, 0x55, 0x28, + 0x8A, 0x84, 0x7C, 0x40, 0xBC, 0x0F, 0x09, 0x55, 0x4C, 0xC4, 0xFE, 0x8C, 0x87, 0xB0, 0x60, 0x02, 0x79, 0x0D, 0xD9, 0x95, + 0xB7, 0x62, 0xD0, 0x3D, 0x74, 0xBD, 0x4B, 0x46, 0x91, 0xEA, 0x92, 0xF2, 0x83, 0x05, 0xED, 0x90, 0x0E, 0xDC, 0xDC, 0x6E, + 0x4F, 0x5F, 0x20, 0x73, 0x93, 0xC1, 0x4B, 0x1C, 0x02, 0xD6, 0x1B, 0x9D, 0x96, 0x08, 0x48, 0x25, 0x15, 0x2E, 0x16, 0xCD, + 0xD6, 0x2D, 0x39, 0x73, 0xC2, 0xF3, 0x49, 0xE5, 0x3E, 0x38, 0x64, 0xC2, 0xD6, 0xBC, 0xD1, 0x30, 0xB2, 0xC3, 0x5E, 0xC4, + 0x28, 0xDA, 0x7D, 0x74, 0x16, 0xA3, 0xB1, 0x62, 0xF2, 0x40, 0xD8, 0x71, 0xC0, 0x6E, 0xEB, 0x2C, 0xA2, 0x69, 0x5C, 0x71, + 0x5A, 0x61, 0xF1, 0x72, 0x6D, 0x71, 0x48, 0x33, 0xC1, 0xDA, 0x81, 0x85, 0xAB, 0x00, 0xC3, 0x45, 0x91, 0xD3, 0xB8, 0x63, + 0x67, 0x42, 0x53, 0xB6, 0x71, 0x29, 0x2F, 0x30, 0xB0, 0x95, 0x5D, 0xD7, 0xC7, 0x5E, 0xF9, 0x7F, 0x4F, 0xDA, 0x5E, 0xA6, + 0x70, 0x3A, 0x7C, 0xA8, 0x87, 0x8E, 0x01, 0x6A, 0xE3, 0x6D, 0x4B, 0xAF, 0xA9, 0x07, 0x6A, 0xAE, 0xD8, 0xB3, 0x5A, 0x0C, + 0x8B, 0x0D, 0xAA, 0xE3, 0xF0, 0x40, 0x13, 0x03, 0x50, 0x52, 0xA2, 0x0D, 0xF8, 0x72, 0x81, 0x49, 0x84, 0xA1, 0x47, 0x7F, + 0xB6, 0xA2, 0x12, 0x56, 0x6F, 0xDF, 0xAB, 0xFD, 0x84, 0xCB, 0xFF, 0x7B, 0xA8, 0x09, 0xA1, 0xB8, 0xB7, 0xA1, 0x93, 0x5F, + 0x3E, 0x5B, 0x8B, 0xDB, 0x5B, 0x6F, 0xBA, 0x3A, 0xF5, 0x4E, 0x1E, 0xE3, 0x12, 0xEC, 0xAB, 0x1A, 0xC4, 0x29, 0x42, 0x2A, + 0x91, 0xF1, 0xA2, 0x67, 0x2F, 0xE0, 0xF2, 0x78, 0x18, 0x6D, 0x71, 0x2B, 0xC7, 0xD1, 0xB4, 0x0E, 0xD6, 0xDB, 0x1C, 0x7A, + 0x0F, 0x6E, 0xE6, 0x4B, 0x0E, 0x4A, 0x7A, 0x3A, 0x4E, 0x52, 0x83, 0x1A, 0xC2, 0x29, 0x4E, 0xAF, 0x9B, 0xF1, 0x75, 0x79, + 0x25, 0xF0, 0x23, 0x5E, 0x5A, 0xE3, 0xA4, 0x0F, 0x09, 0xF0, 0x6D, 0x6B, 0x1B, 0x96, 0x44, 0x7C, 0xAD, 0x72, 0xAC, 0x40, + 0x78, 0x4B, 0x69, 0x20, 0x7D, 0xA9, 0x6C, 0x92, 0x85, 0x1C, 0x08, 0x64, 0x39, 0x3E, 0x1D, 0x40, 0x4E, 0x1E, 0xA4, 0x4A, + 0x77, 0x73, 0xF9, 0xFF, 0xBA, 0x7D, 0xDE, 0x6A, 0x32, 0x31, 0x16, 0x51, 0xEE, 0x1D, 0xFD, 0xC7, 0x0F, 0x7C, 0x15, 0xF9, + 0xA7, 0x9B, 0x9D, 0x99, 0xB5, 0x1F, 0x0D, 0x80, 0xF5, 0x55, 0xB2, 0xAA, 0xD8, 0x75, 0x41, 0x26, 0x32, 0xEA, 0xC4, 0xED, + 0xCF, 0x80, 0xF5, 0xE7, 0x93, 0x0B, 0xEE, 0x7B, 0x8D, 0xF9, 0xEC, 0xCA, 0xAF, 0x78, 0xB4, 0xF0, 0xD2, 0xA9, 0xFC, 0xBA, + 0xB2, 0xF9, 0xA4, 0x1E, 0xDF, 0x78, 0xBC, 0xC3, 0x81, 0x02, 0xBD, 0xD7, 0x4D, 0x83, 0x6D, 0xC6, 0x73, 0xFA, 0x36, 0x1B, + 0xD6, 0xDA, 0x48, 0x33, 0x0F, 0xE9, 0xB4, 0x24, 0x10, 0x27, 0xF9, 0xAB, 0x40, 0x32, 0xCC, 0x17, 0x3A, 0x78, 0x48, 0x8A, + 0x60, 0x74, 0xC2, 0xAC, 0x38, 0x78, 0x36, 0xD9, 0xC9, 0xF7, 0xB6, 0x41, 0x7E, 0x10, 0x67, 0x73, 0x12, 0x71, 0x36, 0xEC, + 0x3D, 0x32, 0x89, 0x3C, 0x64, 0xB0, 0xB6, 0xDE, 0x84, 0x75, 0xD3, 0xD7, 0x86, 0xC6, 0xAB, 0x0C, 0x8B, 0xCA, 0x84, 0x8E, + 0x49, 0xF5, 0x8D, 0x29, 0xB9, 0x68, 0xF3, 0xE7, 0xB3, 0x74, 0x0F, 0xDE, 0xB3, 0x3D, 0xA8, 0x85, 0xEF, 0xD3, 0xA7, 0x39, + 0xF4, 0xE7, 0xBF, 0xCA, 0x4B, 0x28, 0x79, 0xF1, 0xC5, 0xE1, 0x7F, 0xBB, 0xEE, 0x40, 0xAF, 0x9F, 0xFE, 0xDE, 0xFA, 0x2E, + 0x3B, 0xE3, 0xB5, 0xA2, 0xE1, 0xA0, 0xB1, 0x96, 0xBC, 0x40, 0x7A, 0x9E, 0x49, 0x72, 0xE7, 0xC7, 0x26, 0x13, 0x13, 0x33, + 0x4B, 0x5D, 0x7C, 0xBA, 0x66, 0xC2, 0x77, 0x0D, 0xFE, 0xDC, 0xB6, 0xDB, 0xB8, 0x2B, 0xAE, 0x9D, 0xF3, 0xA0, 0x7F, 0x36, + 0x73, 0x1B, 0x4F, 0x52, 0xF3, 0x7D, 0xE0, 0x52, 0x4F, 0x84, 0x88, 0x5B, 0x55, 0xA3, 0x88, 0xDD, 0x42, 0x30, 0x90, 0x44, + 0xD6, 0x34, 0xFC, 0x4C, 0x96, 0xBE, 0xF7, 0x9F, 0x26, 0xD3, 0x00, 0xC9, 0x36, 0xC1, 0xDA, 0x3A, 0x56, 0x81, 0x27, 0x44, + 0xAA, 0x5E, 0x5C, 0x38, 0xB5, 0xE0, 0xA0, 0xA1, 0x44, 0xA8, 0x67, 0xC5, 0x75, 0x8E, 0x57, 0x5A, 0x51, 0x9B, 0x11, 0x37, + 0xC1, 0xB3, 0xF9, 0x2E, 0xB7, 0xD8, 0xE3, 0xC8, 0x76, 0xE5, 0x99, 0x40, 0x43, 0x69, 0x60, 0x21, 0x32, 0x90, 0xD0, 0x28, + 0x97, 0x68, 0x4B, 0xC6, 0xBB, 0x46, 0x91, 0x50, 0x71, 0x91, 0x0C, 0x72, 0xEA, 0x11, 0x93, 0x05, 0xC7, 0x75, 0x1F, 0x89, + 0xB6, 0x33, 0x64, 0xA5, 0x96, 0x78, 0x41, 0x49, 0x1A, 0x2B, 0xD5, 0x39, 0x19, 0xFB, 0x01, 0xB4, 0x37, 0x8A, 0xC9, 0x49, + 0x0B, 0x6A, 0x91, 0x65, 0x27, 0xA8, 0x5C, 0x75, 0x53, 0xA3, 0x02, 0xF3, 0x8B, 0x74, 0x42, 0x08, 0xAA, 0x85, 0xDC, 0x5F, + 0xA0, 0x21, 0xBA, 0x54, 0xEB, 0xD8, 0x92, 0xC2, 0x5A, 0x80, 0x64, 0x18, 0x45, 0xE5, 0xD4, 0x4F, 0xA1, 0x20, 0x88, 0xF6, + 0x7E, 0x79, 0x92, 0x5C, 0xA0, 0xE5, 0x3B, 0x8F, 0x8A, 0x02, 0x99, 0xF4, 0x1C, 0x6A, 0x8C, 0xCD, 0xFF, 0x2C, 0xA9, 0xAB, + 0x9D, 0xF8, 0xFF, 0x45, 0xA3, 0x57, 0x9C, 0x7F, 0x61, 0xA2, 0x83, 0xDB, 0xC9, 0xD9, 0x83, 0xBB, 0xD0, 0x77, 0x67, 0xA8, + 0xA2, 0x72, 0x4D, 0x54, 0xBD, 0x29, 0x48, 0xED, 0xE2, 0x03, 0x5E, 0x1C, 0x84, 0x53, 0x6F, 0xAC, 0x1F, 0x73, 0xD8, 0x62, + 0xE8, 0xEC, 0x83, 0x51, 0xEC, 0x70, 0x7E, 0xFA, 0x03, 0x7E, 0x9A, 0x49, 0xA8, 0xE3, 0xF2, 0x11, 0x46, 0xA1, 0x72, 0xB4, + 0x75, 0x53, 0xC9, 0xF5, 0x2D, 0xEA, 0x92, 0x59, 0xBC, 0xE2, 0x98, 0x5F, 0x83, 0x78, 0x86, 0x5F, 0x57, 0x8B, 0xAB, 0xAC, + 0x93, 0x83, 0x04, 0x52, 0xA6, 0x94, 0x84, 0x7E, 0x95, 0x3C, 0xF5, 0xE0, 0xC5, 0x2D, 0x49, 0x22, 0x79, 0x29, 0xAB, 0x10, + 0xF1, 0x58, 0xF5, 0x02, 0x92, 0xBC, 0x17, 0x5D, 0x63, 0xB9, 0x84, 0x48, 0x73, 0xF3, 0x3A, 0xE1, 0x65, 0x18, 0x61, 0x02, + 0xF7, 0xD2, 0x1D, 0xC1, 0xE2, 0xBA, 0xDD, 0xC5, 0x0B, 0xFC, 0x55, 0x11, 0x25, 0xB4, 0xE7, 0x2A, 0x86, 0x92, 0xA6, 0x71, + 0x44, 0x2C, 0x92, 0x5F, 0x21, 0x0E, 0xC4, 0xCC, 0xAA, 0x99, 0x5F, 0x5D, 0xC1, 0x44, 0xD5, 0xE5, 0x87, 0xB2, 0xCA, 0xE0, + 0x4E, 0x5B, 0x95, 0xD0, 0x76, 0x91, 0x47, 0x2D, 0x13, 0x08, 0x01, 0xF0, 0xB6, 0xC1, 0x82, 0xF1, 0xD6, 0x5A, 0xD1, 0x25, + 0xB6, 0x68, 0x8B, 0x25, 0x0F, 0x3B, 0xC1, 0x05, 0xF6, 0x28, 0x55, 0x94, 0x7A, 0xA5, 0x85, 0xD1, 0x10, 0x93, 0x94, 0x24, + 0x14, 0x6A, 0x05, 0x8C, 0xC6, 0xF7, 0x85, 0xD0, 0x56, 0xB6, 0x1E, 0xEA, 0x21, 0x95, 0x5E, 0xE8, 0x57, 0xB7, 0x5E, 0xC8, + 0x9B, 0x9A, 0x4C, 0x52, 0xD2, 0x03, 0x23, 0xA4, 0x3C, 0x66, 0xA8, 0x8C, 0xBF, 0x6D, 0x81, 0x5C, 0xE0, 0x74, 0xBE, 0xCC, + 0x86, 0xBB, 0x79, 0xC3, 0xAC, 0x35, 0x23, 0xBD, 0xD7, 0xB5, 0x77, 0xF0, 0xDF, 0x58, 0x2D, 0x42, 0x3A, 0xA1, 0x74, 0x9B, + 0xD6, 0xFB, 0xF7, 0x7D, 0x3F, 0xBF, 0xA8, 0x28, 0x99, 0x2A, 0x65, 0xA0, 0xFB, 0xA0, 0xCC, 0xC8, 0xED, 0x98, 0xC4, 0xEE, + 0xB9, 0x2E, 0xF5, 0xB6, 0x4F, 0xB0, 0xBE, 0xE7, 0xC7, 0x5D, 0xBA, 0xD8, 0x2D, 0x99, 0x96, 0xD6, 0xC2, 0x4C, 0xFE, 0x48, + 0x2F, 0xDD, 0xFF, 0x88, 0x5B, 0x8A, 0x7A, 0xC9, 0x09, 0x9A, 0x1C, 0xF4, 0x1D, 0x15, 0x56, 0x09, 0x17, 0x5F, 0x57, 0x05, + 0x3A, 0xF1, 0xDD, 0xD9, 0x1A, 0x9B, 0x10, 0xA4, 0x91, 0x00, 0x37, 0x50, 0x04, 0x9B, 0x04, 0xF3, 0x46, 0x5E, 0xA0, 0xEA, + 0xA5, 0xAF, 0xFD, 0xEA, 0x34, 0x3B, 0x3F, 0x89, 0xB7, 0xCD, 0xF9, 0xC7, 0x74, 0x7D, 0x36, 0x17, 0x35, 0xAE, 0x33, 0xB1, + 0xE6, 0x9C, 0x0F, 0x6E, 0x2B, 0x4E, 0x4C, 0xCB, 0xA4, 0x02, 0x79, 0x09, 0x25, 0x43, 0xC0, 0x7A, 0xEC, 0xDD, 0x42, 0xDB, + 0x75, 0xC7, 0x89, 0x38, 0x2D, 0x0E, 0xAD, 0x7A, 0x0F, 0xAC, 0x5D, 0xEE, 0x60, 0x40, 0x66, 0x43, 0xB3, 0xDC, 0x62, 0x4E, + 0xFF, 0xDC, 0x6E, 0x47, 0x93, 0xA8, 0xBE, 0x42, 0x71, 0xC3, 0xF4, 0x02, 0x52, 0xBB, 0xA8, 0x9A, 0xAF, 0xC5, 0x66, 0x57, + 0xCA, 0x0A, 0xF6, 0x68, 0x7B, 0x28, 0xF8, 0x02, 0x21, 0x82, 0x23, 0x50, 0x28, 0xA5, 0xE1, 0x0B, 0x21, 0x63, 0x12, 0xB6, + 0x1E, 0x67, 0xE9, 0x51, 0xDC, 0xE9, 0xE9, 0x9A, 0x27, 0x05, 0x67, 0x56, 0x12, 0xAB, 0xDB, 0x75, 0x78, 0x63, 0x27, 0x76, + 0x62, 0x06, 0x6E, 0x69, 0xA4, 0x67, 0x7A, 0x2F, 0xB1, 0x6E, 0xF9, 0x47, 0x36, 0x14, 0x82, 0xD9, 0xEB, 0x58, 0xA9, 0x89, + 0xAB, 0x76, 0x4E, 0x6B, 0x8D, 0x38, 0xB7, 0x92, 0x18, 0xC9, 0x8D, 0xC7, 0xBC, 0x2A, 0x9B, 0x4A, 0xA2, 0x79, 0x93, 0xE3, + 0x36, 0x2A, 0xC3, 0xDA, 0xD0, 0x5C, 0x4D, 0x2F, 0xC8, 0xB7, 0xEF, 0x09, 0x3D, 0xF5, 0x75, 0x1F, 0x60, 0x6F, 0xB0, 0x92, + 0x6A, 0x16, 0xE0, 0x62, 0xE7, 0xF7, 0x21, 0xC3, 0xC9, 0xA6, 0xE2, 0x02, 0x2E, 0x02, 0xF8, 0xFC, 0xF4, 0x83, 0xAD, 0x98, + 0x5C, 0xED, 0x89, 0x6C, 0x5C, 0x9C, 0xAE, 0xBE, 0x1B, 0x86, 0xF2, 0xA3, 0x68, 0x2D, 0x08, 0xCE, 0xA0, 0x29, 0x36, 0xE3, + 0xAA, 0xBB, 0xE7, 0x8B, 0x0E, 0x83, 0x67, 0x2F, 0x6D, 0x4B, 0xD2, 0x9A, 0x4E, 0xC3, 0x42, 0x85, 0xFC, 0x23, 0x4F, 0xDE, + 0x2C, 0x1F, 0x94, 0x58, 0x9D, 0xDF, 0x63, 0x5D, 0x6A, 0xB0, 0x4B, 0x95, 0xB5, 0xE4, 0xFC, 0xA4, 0x91, 0xE4, 0x02, 0x0B, + 0xC1, 0x66, 0xFE, 0xD2, 0xB5, 0x2F, 0x95, 0xDF, 0x97, 0x60, 0x74, 0xA2, 0x51, 0x8E, 0xB3, 0x1B, 0xCA, 0xAC, 0x37, 0x5B, + 0xD1, 0x15, 0x66, 0x90, 0x80, 0x7E, 0x7D, 0xB3, 0x71, 0x66, 0xBC, 0x0E, 0xB1, 0x62, 0x2F, 0xFA, 0x57, 0xDF, 0x2E, 0x53, + 0xE0, 0x8F, 0x30, 0x8F, 0x02, 0x96, 0x6C, 0x6F, 0x00, 0x05, 0x8D, 0x1B, 0xE1, 0x7F, 0x29, 0xCE, 0x52, 0x16, 0x84, 0x30, + 0x2A, 0x72, 0xBB, 0xAA, 0x40, 0xAB, 0x42, 0xEC, 0x89, 0x10, 0xEE, 0x54, 0x98, 0xDB, 0xA8, 0x3A, 0x40, 0x35, 0x6C, 0x24, + 0xDF, 0xE6, 0xF8, 0xD4, 0xBD, 0xAA, 0xE6, 0x0E, 0x88, 0xAA, 0x1D, 0xD8, 0x0E, 0x73, 0x9F, 0xA5, 0xCE, 0x99, 0x6F, 0x51, + 0x04, 0xF9, 0x71, 0xC1, 0xCD, 0x44, 0xA9, 0x22, 0x27, 0x03, 0xB3, 0xD2, 0x97, 0x5B, 0x67, 0x63, 0xE3, 0x2B, 0x24, 0x1E, + 0x40, 0x37, 0x15, 0x72, 0xBC, 0x17, 0xFF, 0x91, 0xF3, 0x37, 0x63, 0xA8, 0x73, 0x0F, 0x2D, 0x4E, 0xD4, 0x85, 0xB7, 0x86, + 0x8A, 0x9C, 0xB4, 0xC6, 0x8E, 0xB4, 0x66, 0xAA, 0xB4, 0x85, 0x9F, 0xC7, 0xDE, 0x69, 0x38, 0xBB, 0xD8, 0x85, 0x6E, 0xFF, + 0x61, 0x45, 0x17, 0x90, 0x19, 0x2E, 0xEF, 0x89, 0x09, 0x35, 0x20, 0xB3, 0x0A, 0x6F, 0xA6, 0x76, 0x9D, 0x46, 0x30, 0x43, + 0x00, 0x54, 0x24, 0x5B, 0xE9, 0x86, 0xE2, 0xBA, 0x05, 0x97, 0x9C, 0xCD, 0xE4, 0x74, 0xE9, 0xA7, 0xDD, 0xD1, 0x96, 0xA8, + 0xF8, 0x9B, 0xF1, 0xFF, 0x87, 0x78, 0xF6, 0x59, 0x35, 0x5F, 0x25, 0x03, 0x9C, 0x1F, 0xE6, 0x17, 0xD7, 0x70, 0xC7, 0x4E, + 0x9B, 0x17, 0x17, 0x4F, 0x3A, 0x95, 0x2A, 0x03, 0x16, 0xEF, 0x37, 0x8F, 0x49, 0x1B, 0x6F, 0x06, 0x40, 0x5B, 0x85, 0x40, + 0x9F, 0x80, 0x1F, 0xBD, 0xD4, 0x5D, 0x26, 0xDA, 0x5A, 0x00, 0xF1, 0xF1, 0x88, 0x9D, 0x41, 0xED, 0x48, 0xBE, 0x1B, 0x87, + 0x95, 0x6C, 0x4F, 0x02, 0xF5, 0x7F, 0x50, 0x36, 0x06, 0xB1, 0x92, 0x4C, 0xAA, 0xE0, 0xDD, 0x49, 0xD3, 0x5C, 0x80, 0xC8, + 0xF9, 0xEC, 0x59, 0x70, 0x27, 0xE7, 0x99, 0x75, 0x0D, 0xFD, 0x91, 0x86, 0x0D, 0x86, 0x05, 0x45, 0x2F, 0x87, 0x14, 0x22, + 0x01, 0x9F, 0xF7, 0xF5, 0x97, 0x5E, 0x5C, 0x40, 0x41, 0xD5, 0x46, 0x13, 0x34, 0x85, 0x3A, 0x46, 0x88, 0xCB, 0x71, 0xDF, + 0x10, 0x54, 0x4E, 0x57, 0xA6, 0x45, 0x74, 0x80, 0x65, 0x67, 0x90, 0xA2, 0x47, 0xEE, 0xD0, 0x66, 0x37, 0x0A, 0x00, 0xC2, + 0xBB, 0x6A, 0x80, 0xF4, 0xB9, 0x57, 0x60, 0xB3, 0x8A, 0xE0, 0x85, 0x34, 0xEE, 0x07, 0x69, 0x90, 0x42, 0x6B, 0x09, 0xE5, + 0x38, 0xED, 0x5B, 0x62, 0x03, 0x28, 0x49, 0x25, 0xF5, 0x40, 0xDD, 0x0C, 0x64, 0x4C, 0x81, 0x05, 0x55, 0x00, 0xD8, 0x02, + 0xE8, 0x87, 0x35, 0xF1, 0xE9, 0xCB, 0x3A, 0x32, 0xA7, 0x8C, 0xC9, 0xDE, 0x54, 0x8E, 0x17, 0x2B, 0x89, 0x95, 0x81, 0xBB, + 0xCC, 0xB5, 0xDB, 0xC1, 0xBC, 0xFF, 0x41, 0xCE, 0x51, 0x8F, 0xB3, 0xA4, 0x7B, 0xBA, 0x58, 0x74, 0xB2, 0x15, 0x88, 0xA4, + 0x3B, 0x77, 0xCC, 0xDF, 0xD8, 0x8C, 0xD3, 0x68, 0x2E, 0x9B, 0x7F, 0x55, 0x9F, 0x45, 0x40, 0x26, 0x06, 0xC4, 0x44, 0x1B, + 0x2C, 0x24, 0xC2, 0x39, 0xAD, 0x2F, 0x9C, 0x49, 0x3A, 0x5D, 0xA2, 0x5B, 0x22, 0x63, 0xAE, 0x8C, 0x3D, 0x8C, 0x02, 0x5D, + 0x8C, 0xC9, 0x39, 0xAD, 0x93, 0xA0, 0x04, 0x7D, 0xEE, 0x32, 0x02, 0x5A, 0x3C, 0xAE, 0xC7, 0xB8, 0x02, 0xCF, 0x9D, 0x49, + 0xFD, 0x4B, 0xD3, 0x19, 0xAC, 0x69, 0x0B, 0x1D, 0xED, 0xE6, 0x12, 0x29, 0x01, 0x84, 0x12, 0x78, 0x3E, 0x1E, 0xEB, 0x99, + 0xAC, 0x99, 0xED, 0x4A, 0x34, 0xAB, 0x5C, 0xB0, 0x5C, 0x0C, 0x43, 0x75, 0x97, 0xED, 0x99, 0x49, 0x57, 0xC2, 0x4C, 0x82, + 0xC4, 0xB4, 0x11, 0x8D, 0x86, 0x14, 0xCB, 0xD2, 0x96, 0xAC, 0xE8, 0x4C, 0x9C, 0xB2, 0x18, 0x74, 0xF1, 0xB3, 0x74, 0xB2, + 0x07, 0x2D, 0x46, 0xC3, 0x17, 0x8F, 0x8A, 0x9E, 0x1B, 0x0F, 0x93, 0xA0, 0x57, 0xFC, 0x3E, 0xC8, 0xCF, 0x9C, 0xCE, 0xC6, + 0x16, 0xF2, 0x42, 0xC9, 0xCB, 0x4C, 0xF9, 0x5C, 0xF3, 0xD1, 0x5E, 0x72, 0xC0, 0x3B, 0xBA, 0x24, 0x76, 0x19, 0x4E, 0x0C, + 0xDD, 0xCB, 0x64, 0x0E, 0x50, 0xB9, 0x93, 0xB4, 0x47, 0xE3, 0x92, 0xD0, 0xDE, 0xBA, 0x47, 0xB8, 0xFE, 0x68, 0x07, 0x89, + 0xF8, 0x23, 0xC1, 0x2B, 0xC2, 0x9B, 0x74, 0xF5, 0xD6, 0xEB, 0xB5, 0x63, 0x3F, 0xCA, 0xAB, 0x05, 0xFA, 0x72, 0x13, 0xD5, + 0x46, 0x14, 0xBF, 0x95, 0x5C, 0xD3, 0x50, 0xBD, 0x12, 0x8B, 0x6D, 0xB0, 0x1E, 0xE6, 0x5D, 0xE5, 0xF8, 0x97, 0x9F, 0xEE, + 0x60, 0x25, 0x8B, 0x0F, 0xD3, 0xDA, 0xCB, 0x2A, 0x76, 0xC7, 0x93, 0x85, 0x8E, 0x1C, 0x6A, 0x65, 0xC8, 0xDB, 0x3C, 0xD5, + 0xF7, 0xA6, 0x62, 0xCC, 0xF3, 0x9C, 0x15, 0x75, 0x14, 0x95, 0x0B, 0x0A, 0x4F, 0x07, 0xD9, 0xAE, 0x76, 0xD2, 0x77, 0x2E, + 0x47, 0x77, 0x80, 0xC8, 0x0E, 0x4A, 0x54, 0xE0, 0xB3, 0x44, 0xB8, 0x71, 0x04, 0x56, 0x91, 0xB8, 0x34, 0xF4, 0x94, 0x39, + 0xA2, 0x91, 0xDC, 0x2C, 0x92, 0xFD, 0xDB, 0x95, 0xF3, 0x9D, 0xEC, 0xEC, 0xBC, 0xF8, 0x7C, 0x57, 0xC4, 0xD9, 0xDC, 0xEF, + 0x51, 0x26, 0x81, 0x89, 0x53, 0xBE, 0x3A, 0x2E, 0x01, 0x22, 0xF7, 0x23, 0x9E, 0xD3, 0xDA, 0x3E, 0x1D, 0x4E, 0x49, 0xD3, + 0x86, 0xD3, 0x67, 0x9C, 0xAA, 0x9C, 0x55, 0x6B, 0x49, 0x30, 0xEF, 0x20, 0x4E, 0x1C, 0x84, 0x0B, 0xCF, 0x2E, 0x40, 0xDB, + 0x00, 0x93, 0x3E, 0x08, 0xDE, 0xAF, 0xD2, 0x3B, 0xFB, 0x44, 0xEF, 0x52, 0x82, 0x40, 0xF2, 0x24, 0xBB, 0xE3, 0x76, 0xBD, + 0x25, 0xAC, 0x18, 0x2B, 0x45, 0xAC, 0x20, 0x01, 0xE0, 0xC0, 0xA6, 0x19, 0x39, 0x62, 0x52, 0x73, 0x42, 0x02, 0x3E, 0xE7, + 0xD8, 0xC3, 0x81, 0x52, 0xF4, 0xE3, 0xCB, 0xAA, 0xAC, 0x23, 0xD8, 0x9E, 0x34, 0x8A, 0x65, 0xEF, 0x6A, 0xFC, 0x9C, 0xC2, + 0x45, 0xCE, 0xE7, 0x33, 0x30, 0xC0, 0x72, 0x64, 0xEB, 0xB5, 0xE1, 0x32, 0x72, 0xDB, 0x12, 0x5F, 0x2B, 0x06, 0x8E, 0xB9, + 0x52, 0x23, 0xD8, 0xD2, 0xED, 0xD7, 0x33, 0x6F, 0x32, 0xBE, 0xE7, 0x96, 0xBF, 0x8C, 0x30, 0xF5, 0xD4, 0x05, 0x21, 0x7D, + 0x7A, 0x60, 0x3E, 0x37, 0xF0, 0xD9, 0x0E, 0xB0, 0xF1, 0xE6, 0x54, 0x8D, 0x0A, 0xA6, 0x71, 0xAE, 0x6A, 0x17, 0xC9, 0xD1, + 0xCF, 0x76, 0x99, 0x89, 0xE4, 0x5C, 0x63, 0x32, 0xE0, 0x93, 0x22, 0xE2, 0xE1, 0x3B, 0x02, 0x8D, 0x47, 0x2E, 0x40, 0x9E, + 0xA3, 0x2C, 0x03, 0xDF, 0xD4, 0x65, 0xB9, 0xB0, 0xF5, 0x3A, 0xF2, 0x0D, 0xF9, 0xA8, 0x24, 0x14, 0x21, 0x44, 0xCA, 0xCF, + 0xDD, 0xE4, 0x19, 0x0B, 0x1A, 0x4B, 0xF1, 0x0D, 0x39, 0x81, 0x29, 0xCB, 0x64, 0x0B, 0x03, 0x5E, 0xA0, 0xCB, 0xCB, 0x04, + 0xBD, 0x97, 0x0F, 0xE2, 0x78, 0x88, 0x0D, 0x5B, 0xA9, 0xFB, 0xCD, 0x05, 0x32, 0x0F, 0xAE, 0xD7, 0x2E, 0xF0, 0x7D, 0x60, + 0xE1, 0xB1, 0xD4, 0x17, 0xED, 0x48, 0x30, 0x2C, 0x03, 0x20, 0xE1, 0x7C, 0x89, 0xEA, 0xF2, 0x4F, 0x3A, 0x22, 0x05, 0xA9, + 0x78, 0xAD, 0xDA, 0x94, 0x53, 0x20, 0xFE, 0x16, 0x5F, 0x53, 0x10, 0xB7, 0x27, 0x8F, 0x93, 0x56, 0xAF, 0x0C, 0x56, 0x85, + 0x02, 0xA5, 0xAB, 0x5D, 0x81, 0x53, 0xF9, 0xA2, 0x16, 0x92, 0xE4, 0x9F, 0x37, 0xE6, 0xD9, 0x9B, 0x7E, 0x74, 0x3A, 0x20, + 0x40, 0x30, 0x82, 0xB6, 0xC4, 0x3F, 0x6C, 0x87, 0x9D, 0x5F, 0xC7, 0x9A, 0x16, 0x85, 0x9C, 0xF2, 0xDE, 0xBC, 0xB6, 0x7F, + 0x82, 0x70, 0x24, 0xF7, 0xBF, 0x8C, 0x4C, 0xB0, 0x2D, 0x20, 0xFA, 0xF3, 0x8E, 0xCD, 0x78, 0xCB, 0x45, 0x6E, 0x85, 0xC3, + 0x13, 0x37, 0x43, 0x5D, 0xF0, 0xC9, 0xDC, 0xA0, 0xCF, 0x0C, 0x49, 0x10, 0xF2, 0xC0, 0x07, 0xB3, 0x52, 0x12, 0xA3, 0x98, + 0x8D, 0xDC, 0x7A, 0xF8, 0x85, 0x55, 0xC5, 0xB7, 0x6D, 0x9D, 0xE3, 0x80, 0x64, 0xEF, 0x16, 0x82, 0x8D, 0x6F, 0x64, 0xD7, + 0xA2, 0x51, 0x48, 0xA7, 0x6C, 0xB7, 0xA3, 0x18, 0x2F, 0x18, 0x94, 0xF8, 0x75, 0x3C, 0x6D, 0xA3, 0x23, 0x19, 0xDD, 0x25, + 0xB6, 0x8D, 0x10, 0x09, 0xAA, 0x1B, 0x12, 0x83, 0x7F, 0x80, 0x65, 0x13, 0xC8, 0x19, 0x32, 0xF3, 0xA3, 0x50, 0x22, 0x19, + 0xFD, 0x1A, 0x68, 0x1D, 0xAD, 0x3A, 0xBC, 0x73, 0x2E, 0xB3, 0x79, 0xEA, 0xCF, 0xC5, 0x49, 0xA1, 0x9C, 0xBB, 0x36, 0xDF, + 0x4C, 0xAB, 0x2E, 0x72, 0xDC, 0x90, 0xF0, 0x20, 0xD8, 0xBF, 0x9E, 0xA5, 0x5D, 0xE6, 0xA0, 0x85, 0x05, 0xD6, 0x61, 0xF6, + 0x8C, 0x93, 0x6B, 0x13, 0x9C, 0xCC, 0xA0, 0x01, 0x9B, 0x5A, 0xE9, 0xAA, 0x59, 0x3B, 0x2F, 0x13, 0x8D, 0xCE, 0x8F, 0x6E, + 0xC3, 0x7A, 0x45, 0x21, 0x95, 0xF4, 0x3F, 0xCE, 0x89, 0xA8, 0x06, 0x68, 0x72, 0x4E, 0x26, 0xF9, 0x9E, 0x4C, 0x28, 0xB9, + 0xD6, 0xD5, 0xD4, 0x0A, 0xFA, 0x4C, 0xAE, 0xF0, 0x40, 0x95, 0x76, 0x2F, 0x7A, 0x2D, 0x9B, 0x9E, 0xD0, 0xFC, 0x36, 0xF9, + 0x7D, 0x66, 0xEF, 0xFC, 0x0E, 0x6E, 0x27, 0xE5, 0x89, 0x2E, 0x97, 0x11, 0x77, 0x45, 0x8E, 0x70, 0x1B, 0x31, 0x4F, 0x28, + 0xE2, 0x1F, 0x77, 0x2E, 0xF2, 0x24, 0x45, 0x02, 0x0A, 0x3C, 0x96, 0x79, 0xD2, 0x6D, 0x9B, 0x58, 0xDD, 0x7D, 0xD8, 0xF8, + 0x30, 0xBB, 0x4E, 0x24, 0xA5, 0x43, 0x88, 0x02, 0xDB, 0x1D, 0x3E, 0x1E, 0xEE, 0xC5, 0xAA, 0x24, 0xEA, 0xCF, 0x40, 0x15, + 0x61, 0x3E, 0xB8, 0x12, 0xDA, 0x4C, 0x0E, 0x27, 0xE7, 0xA1, 0x71, 0x61, 0xFF, 0xAD, 0xC3, 0xD0, 0x48, 0x4F, 0xD3, 0xB7, + 0x21, 0x64, 0x13, 0xA3, 0x6F, 0x2C, 0x97, 0x0B, 0x4B, 0xE2, 0x81, 0x74, 0x1B, 0x3C, 0x6A, 0xA5, 0xD5, 0x4E, 0x9F, 0xC0, + 0xE8, 0x56, 0x07, 0xB9, 0xE7, 0x02, 0xB0, 0x9A, 0x61, 0xDF, 0xD1, 0xF0, 0x57, 0x77, 0x8B, 0x76, 0x7C, 0x85, 0xF2, 0xAD, + 0xF6, 0xC6, 0xB5, 0x0D, 0x74, 0x15, 0xA1, 0xF4, 0x13, 0xE6, 0x59, 0xBD, 0x7B, 0xEA, 0x99, 0xB9, 0x2F, 0x07, 0x77, 0x1C, + 0x61, 0x84, 0xA8, 0x66, 0x37, 0xA9, 0xB4, 0xAC, 0xF0, 0x87, 0x92, 0xD3, 0xCB, 0xF6, 0xC1, 0x88, 0x63, 0xA5, 0x78, 0xD3, + 0xF5, 0xE7, 0x86, 0x68, 0x28, 0x27, 0x9C, 0x13, 0x9E, 0x79, 0x08, 0xB8, 0x4C, 0x17, 0xE5, 0x5E, 0xDC, 0x6E, 0x7F, 0x2A, + 0x05, 0x36, 0xD2, 0x0A, 0xF4, 0x48, 0xC5, 0x5C, 0x31, 0xA5, 0x45, 0x4C, 0x73, 0x36, 0x87, 0x69, 0x73, 0x27, 0x94, 0x88, + 0xB8, 0x01, 0x09, 0xD1, 0x37, 0x8B, 0x93, 0x0B, 0xB4, 0xE7, 0x11, 0xBE, 0x7E, 0xCA, 0x99, 0x3B, 0xF6, 0xA4, 0xFF, 0x1C, + 0x32, 0x46, 0xE0, 0x3F, 0xD9, 0x1B, 0xE2, 0x56, 0xB3, 0x97, 0xBB, 0x42, 0xEB, 0xE3, 0x48, 0xCF, 0x0F, 0xC8, 0x65, 0x86, + 0x00, 0x6C, 0xD2, 0x7E, 0x3C, 0x1E, 0xEE, 0x2D, 0x40, 0x2A, 0xAE, 0xDF, 0x0C, 0xC1, 0xA1, 0xCA, 0xDF, 0x6C, 0x71, 0x2D, + 0x71, 0x9C, 0xE2, 0x30, 0x39, 0x15, 0x8C, 0x18, 0xE3, 0x42, 0x0B, 0x29, 0xD2, 0xAC, 0x55, 0x76, 0x28, 0x9F, 0xEF, 0x5A, + 0xC5, 0xAB, 0xF4, 0x2B, 0xED, 0xB0, 0x3B, 0x87, 0xB9, 0xF4, 0x73, 0xBD, 0x52, 0x0B, 0x9A, 0x8A, 0x76, 0x4F, 0x94, 0xD0, + 0x06, 0x17, 0xCA, 0xA1, 0xD5, 0xB1, 0xAB, 0xBE, 0xAA, 0x3C, 0x3C, 0xE4, 0x96, 0x1C, 0x65, 0x96, 0xC0, 0x2E, 0x8B, 0x31, + 0x8A, 0x5C, 0x25, 0x7A, 0xB0, 0xD2, 0x9B, 0x26, 0x39, 0x44, 0x4B, 0xA4, 0x45, 0x93, 0x8B, 0x9B, 0x76, 0x23, 0x38, 0xE3, + 0x25, 0x15, 0xAC, 0xB0, 0x16, 0xD6, 0x64, 0x87, 0x40, 0x25, 0xAA, 0x30, 0xD1, 0x5E, 0x3A, 0x96, 0x26, 0x3F, 0x65, 0xA0, + 0xDD, 0x7C, 0x0F, 0x0A, 0x6E, 0x99, 0x9C, 0x24, 0xF5, 0xB0, 0x93, 0x56, 0x04, 0xFB, 0x2C, 0x36, 0xB8, 0xF7, 0x04, 0xC0, + 0x98, 0x00, 0x94, 0x94, 0x51, 0xF9, 0xEB, 0xC3, 0x47, 0x29, 0xE4, 0xA1, 0x5D, 0x5E, 0x88, 0x90, 0xC7, 0xA2, 0x9D, 0xE0, + 0x75, 0xF9, 0x51, 0xB1, 0x94, 0x65, 0x33, 0x19, 0x35, 0xBF, 0x05, 0x77, 0xBB, 0x86, 0xC5, 0xB5, 0x7B, 0xFB, 0x06, 0xAE, + 0xD7, 0x13, 0x9C, 0x6C, 0x90, 0xF9, 0xA6, 0x95, 0x58, 0x78, 0x35, 0x5F, 0xDF, 0x38, 0x14, 0x2A, 0xCB, 0x36, 0x99, 0x19, + 0x19, 0xD5, 0x47, 0xDC, 0x2D, 0x98, 0x5D, 0x9A, 0x82, 0x52, 0x44, 0xB6, 0x47, 0xDE, 0x99, 0xB7, 0x3E, 0x6B, 0xA6, 0x5B, + 0x94, 0x2B, 0x95, 0x51, 0x01, 0x96, 0x8B, 0xF9, 0x20, 0x2D, 0xC8, 0x6C, 0xD7, 0x36, 0x41, 0xBD, 0x04, 0xD4, 0xC7, 0xAF, + 0x14, 0xAA, 0xDE, 0xAA, 0x2A, 0xB1, 0x08, 0x3E, 0x2E, 0xB3, 0x2F, 0xE2, 0x9B, 0x93, 0x56, 0xFF, 0x5B, 0xFA, 0x6A, 0xBA, + 0x2B, 0xB0, 0xF6, 0x9E, 0x56, 0x30, 0xE4, 0x89, 0x42, 0xD6, 0x86, 0x3C, 0xFB, 0xF3, 0x14, 0xB8, 0xF1, 0x17, 0xD9, 0x12, + 0x31, 0x18, 0x76, 0x94, 0x49, 0x8B, 0x54, 0x47, 0x5F, 0x7E, 0xB9, 0xA8, 0x82, 0x94, 0x10, 0x5B, 0xC4, 0x1A, 0xFF, 0xD5, + 0x86, 0xC4, 0x5B, 0x3D, 0x5E, 0xBC, 0xA8, 0x21, 0x33, 0x25, 0x8F, 0x14, 0x92, 0xA7, 0x4B, 0x20, 0x88, 0xEA, 0x10, 0x45, + 0x32, 0x63, 0x68, 0xA2, 0x51, 0x0C, 0xFE, 0xF2, 0xB0, 0x4F, 0xD8, 0xD4, 0x60, 0x9A, 0xA2, 0xB6, 0xBB, 0xF6, 0xB9, 0x30, + 0xD3, 0x4D, 0x85, 0x67, 0x6F, 0x24, 0x43, 0x32, 0x87, 0xE1, 0x85, 0x21, 0xF9, 0xE1, 0xF6, 0x77, 0x0E, 0xF5, 0x6E, 0x55, + 0x9D, 0xDE, 0x2D, 0xCC, 0xE0, 0x36, 0xE1, 0xF3, 0x87, 0x65, 0x60, 0xA0, 0x00, 0xA9, 0x39, 0x36, 0xB1, 0x22, 0x68, 0x50, + 0x0E, 0xEB, 0x00, 0xE0, 0x5C, 0xB3, 0xCF, 0xD2, 0xE9, 0x3A, 0xA8, 0xE7, 0xA8, 0x28, 0x26, 0x77, 0xA2, 0x4A, 0x29, 0x0F, + 0xF0, 0xC8, 0x4A, 0x71, 0x03, 0xA9, 0xB7, 0xDC, 0x33, 0xD9, 0xF1, 0x13, 0xA0, 0x81, 0xE9, 0x9E, 0xD4, 0x04, 0x31, 0x76, + 0x62, 0x08, 0xB1, 0x72, 0x32, 0xDF, 0xED, 0x0A, 0x60, 0x57, 0x4F, 0x44, 0x72, 0x25, 0x0A, 0x18, 0xE9, 0x13, 0xDA, 0x05, + 0x9A, 0x8F, 0xD8, 0x06, 0x03, 0xF3, 0x64, 0xCD, 0xFB, 0xC7, 0xCA, 0x61, 0x82, 0x08, 0xF2, 0x1E, 0x15, 0x41, 0xC2, 0xE7, + 0xA8, 0xE6, 0x1A, 0xB8, 0x60, 0xB4, 0xB5, 0xEF, 0x0D, 0xCB, 0x7B, 0x6F, 0xF0, 0xB0, 0x0B, 0xD1, 0x60, 0x08, 0x12, 0xDE, + 0x80, 0x91, 0x4D, 0x1C, 0x8F, 0x70, 0x84, 0x15, 0x70, 0x53, 0x92, 0xBD, 0xF8, 0x25, 0x87, 0x8D, 0x38, 0x6D, 0xBA, 0x4A, + 0x04, 0xB1, 0xBA, 0xCE, 0xF0, 0x7B, 0xEA, 0x93, 0xB7, 0xED, 0x12, 0x7F, 0xA1, 0xE7, 0x84, 0x88, 0x8F, 0x04, 0x32, 0x3E, + 0x96, 0xDB, 0x5F, 0x8B, 0xCF, 0xC0, 0x7A, 0x0E, 0x39, 0xAA, 0x31, 0x4D, 0xD6, 0xA3, 0xFB, 0xB2, 0x18, 0x89, 0x6B, 0x58, + 0x6B, 0xCF, 0x16, 0x5C, 0xB6, 0xC1, 0x4E, 0xA8, 0xD7, 0x93, 0x83, 0x58, 0xF0, 0xDF, 0x09, 0xCF, 0x20, 0x2B, 0xA5, 0x7A, + 0x22, 0x60, 0x90, 0x10, 0x26, 0x89, 0xCC, 0x81, 0x12, 0xE2, 0x74, 0x17, 0x4B, 0x5F, 0x81, 0xD7, 0x64, 0x1E, 0x5C, 0xBD, + 0x2D, 0x53, 0xF2, 0x8D, 0xB3, 0xD6, 0x45, 0x87, 0xC6, 0xFC, 0x80, 0x9D, 0xF3, 0x96, 0xE0, 0x05, 0xD3, 0x6F, 0x00, 0xF7, + 0x5B, 0x62, 0x6B, 0xF9, 0x0B, 0x02, 0xF7, 0xA7, 0xF1, 0x32, 0x45, 0xCF, 0x1D, 0xD9, 0xD1, 0x77, 0x31, 0x83, 0x96, 0x51, + 0xF3, 0x48, 0xC1, 0xD7, 0xD2, 0x33, 0xFC, 0x3F, 0x55, 0x14, 0xDC, 0xC1, 0x93, 0xB4, 0x74, 0x3D, 0xE5, 0xA6, 0x8E, 0x68, + 0x1A, 0x24, 0xF3, 0x32, 0x33, 0x58, 0xF2, 0xD8, 0xBE, 0xB3, 0x24, 0x74, 0x7D, 0x4D, 0x2E, 0x07, 0xFF, 0xC8, 0xF1, 0xBF, + 0x01, 0x73, 0xBD, 0xC1, 0xC1, 0xEC, 0x35, 0xA1, 0x0C, 0xDB, 0xAB, 0xE3, 0x13, 0xF5, 0x32, 0x29, 0xA3, 0x72, 0x4D, 0x15, + 0xFB, 0x75, 0x9D, 0xA1, 0xB6, 0x54, 0xA5, 0x05, 0x6D, 0x86, 0xB7, 0x59, 0xC9, 0xA7, 0xE6, 0x3F, 0xF7, 0x35, 0x23, 0xCE, + 0x97, 0x51, 0x8A, 0x85, 0x7E, 0x98, 0xCE, 0x6C, 0xF5, 0x5B, 0xB6, 0x67, 0x3F, 0x28, 0x15, 0x49, 0xCA, 0x49, 0x86, 0xB8, + 0x70, 0x6E, 0xD8, 0xE9, 0xDF, 0xAF, 0x78, 0x0F, 0x52, 0x04, 0xD7, 0x6F, 0xC4, 0xF5, 0x18, 0xD2, 0x99, 0x5A, 0xDB, 0xB7, + 0x2B, 0xBC, 0x8F, 0x1F, 0x5B, 0xA9, 0x2D, 0x3B, 0x03, 0xB5, 0xA1, 0xE4, 0xD8, 0x3B, 0x7D, 0x2A, 0x86, 0xA1, 0x02, 0x57, + 0xC5, 0x7D, 0x46, 0xFC, 0x8B, 0xE3, 0x16, 0x68, 0x0B, 0x83, 0xFA, 0xA7, 0x88, 0x78, 0x31, 0xAE, 0x59, 0xC2, 0xF6, 0x65, + 0xE9, 0x59, 0xA6, 0x78, 0x3D, 0x1E, 0x3F, 0xEE, 0x5F, 0x11, 0xF9, 0xC1, 0xDA, 0xC1, 0xA8, 0x6D, 0x9B, 0x03, 0x17, 0x69, + 0x0C, 0x83, 0x74, 0x3B, 0x07, 0xA2, 0x34, 0xAE, 0xAF, 0x51, 0x01, 0x9B, 0xE5, 0x3D, 0x73, 0x62, 0xC8, 0x3C, 0xBB, 0x86, + 0x7A, 0x0C, 0xF8, 0x17, 0x27, 0x95, 0x50, 0x20, 0x2F, 0xCD, 0xC6, 0x9C, 0xF7, 0xAC, 0xF1, 0x31, 0x3A, 0x88, 0xF1, 0x35, + 0xB2, 0xA7, 0x72, 0xAF, 0x65, 0xCC, 0xDA, 0x37, 0x54, 0x71, 0xFA, 0x90, 0xFB, 0x8B, 0x19, 0x67, 0xFB, 0x2F, 0xCE, 0xA6, + 0xCA, 0xA0, 0x72, 0x54, 0x8D, 0x8C, 0x77, 0x53, 0x89, 0x28, 0xDF, 0xC1, 0x34, 0xA8, 0xBD, 0xB7, 0xA6, 0x7B, 0x83, 0xC4, + 0x8C, 0x4C, 0xA0, 0x12, 0x55, 0x9F, 0x1F, 0xC4, 0xFC, 0x16, 0x4A, 0x80, 0xEA, 0x79, 0xCE, 0x53, 0x3E, 0xE9, 0x74, 0x73, + 0x34, 0x60, 0x90, 0x24, 0xFC, 0xF5, 0x40, 0x62, 0xE4, 0xC1, 0xA2, 0xF9, 0x3F, 0x04, 0xD7, 0xA5, 0x03, 0xE7, 0xD9, 0xA7, + 0x92, 0x26, 0x09, 0xE1, 0x2C, 0x74, 0x31, 0xE3, 0xE3, 0x59, 0xD1, 0x23, 0x83, 0x8E, 0x89, 0xE4, 0x34, 0xA8, 0x55, 0x82, + 0x9B, 0x5B, 0x87, 0x71, 0x36, 0x64, 0x2E, 0x0A, 0x77, 0x81, 0x23, 0x8C, 0xF6, 0xE7, 0x62, 0x0F, 0x5E, 0xA4, 0xB5, 0xC6, + 0xB0, 0xA7, 0xF8, 0x9E, 0x6E, 0x2B, 0x5C, 0xFF, 0xBE, 0x04, 0x22, 0xBB, 0xAC, 0xD2, 0x84, 0x32, 0xD0, 0x6F, 0x78, 0x84, + 0x8A, 0x73, 0xDB, 0xFC, 0x88, 0xAC, 0x0D, 0x77, 0x06, 0x92, 0xD3, 0x9C, 0x77, 0xE5, 0x7B, 0x8A, 0xC9, 0xC9, 0xA4, 0xD8, + 0x5F, 0x8B, 0x0E, 0xDD, 0x48, 0xAA, 0xBB, 0xFF, 0xD9, 0xC2, 0xE2, 0x2B, 0x26, 0x21, 0x82, 0xFD, 0xB9, 0xA3, 0x48, 0x82, + 0xA2, 0x83, 0x00, 0x9D, 0xD2, 0x51, 0xEA, 0x3B, 0x27, 0xCF, 0x9C, 0x88, 0xF6, 0xD5, 0x44, 0x23, 0xAD, 0xED, 0x0F, 0x8E, + 0x41, 0x1C, 0xAD, 0x9B, 0x0A, 0x85, 0x23, 0xA2, 0x71, 0xA8, 0x0D, 0x33, 0x4E, 0xF7, 0x8B, 0x7E, 0xB2, 0xEA, 0x61, 0x83, + 0xBC, 0x0A, 0x93, 0xB7, 0x27, 0xE2, 0x7D, 0x09, 0x24, 0x77, 0x3B, 0xFB, 0x13, 0x50, 0x51, 0xE0, 0x4C, 0x48, 0x9C, 0x79, + 0xBB, 0x36, 0x4C, 0x20, 0x8E, 0xEE, 0xB8, 0x0C, 0x56, 0x91, 0xD9, 0x70, 0x06, 0x31, 0xFE, 0x14, 0xDF, 0x26, 0xA5, 0xE7, + 0x63, 0x59, 0xC1, 0x5B, 0x51, 0x4E, 0x5D, 0xE1, 0x26, 0x35, 0xA5, 0x47, 0xB0, 0x9B, 0x6F, 0x4D, 0x47, 0x90, 0xBB, 0x5B, + 0x1E, 0x09, 0x4D, 0x20, 0x0A, 0x13, 0x95, 0xA6, 0xE6, 0xBC, 0xAA, 0x73, 0xA5, 0xDE, 0x7D, 0x4E, 0xDE, 0xE8, 0x1C, 0xB0, + 0x8A, 0x9B, 0x86, 0x86, 0x37, 0x1E, 0xB0, 0x32, 0x38, 0xD7, 0x0C, 0x0E, 0x4C, 0xB9, 0xD8, 0x30, 0xA5, 0x32, 0xCC, 0x16, + 0x62, 0x18, 0xC4, 0x70, 0x8D, 0x67, 0x50, 0x69, 0x9C, 0x25, 0xD1, 0x21, 0x0A, 0x99, 0xDB, 0xCB, 0x39, 0x30, 0x4D, 0xEA, + 0xD5, 0x77, 0x0A, 0x0F, 0xFF, 0xBB, 0x2A, 0x31, 0x25, 0x30, 0x6C, 0x90, 0xB9, 0x18, 0x05, 0xF1, 0xBB, 0x7A, 0x9D, 0x44, + 0xD1, 0xFA, 0x5E, 0x66, 0x84, 0xE3, 0xF6, 0x12, 0x78, 0xB5, 0x20, 0x72, 0xCF, 0xDE, 0x00, 0xC8, 0x87, 0x7F, 0x85, 0xF4, + 0xF8, 0x9F, 0x2F, 0x1C, 0xD7, 0x2E, 0x3B, 0x38, 0xED, 0x8C, 0xF4, 0xB8, 0x8A, 0x74, 0x3F, 0xD4, 0x11, 0x66, 0x0B, 0x1D, + 0xF8, 0xB0, 0x9C, 0x66, 0x4D, 0xD3, 0xB3, 0x36, 0x15, 0x10, 0x0F, 0x5F, 0x0C, 0x24, 0x97, 0xD8, 0x63, 0xB1, 0x07, 0xDB, + 0xE1, 0xB3, 0xE7, 0xBA, 0x08, 0x72, 0x21, 0xA8, 0xD1, 0xF0, 0x67, 0xBC, 0xD5, 0x5D, 0xF7, 0xFA, 0xEC, 0x7B, 0x09, 0x9E, + 0x32, 0xF5, 0x37, 0xE8, 0x8A, 0x22, 0x6F, 0x1E, 0x49, 0x10, 0x76, 0xBA, 0x63, 0x56, 0xE6, 0xFB, 0x82, 0xF6, 0x05, 0xDA, + 0xAD, 0x3D, 0xD9, 0xFA, 0x33, 0x18, 0x30, 0x09, 0x61, 0x58, 0xF6, 0x90, 0x9F, 0xDE, 0xD0, 0xEA, 0x0E, 0x3E, 0x79, 0xEE, + 0x1E, 0x3E, 0x77, 0x19, 0x6D, 0x78, 0x79, 0x17, 0x91, 0x74, 0x04, 0xE6, 0x80, 0x80, 0x40, 0x9A, 0x7B, 0x2F, 0xA3, 0x08, + 0xBC, 0x71, 0x27, 0xD4, 0x71, 0xC1, 0xC8, 0x80, 0x65, 0xFE, 0x9A, 0x75, 0x17, 0x63, 0x4D, 0xB4, 0x1D, 0xD2, 0x58, 0xA5, + 0x51, 0x65, 0x3B, 0xE9, 0xEE, 0x4D, 0x05, 0x76, 0xFC, 0xA7, 0x2F, 0x2D, 0xC6, 0xC0, 0x07, 0xD6, 0x54, 0xEF, 0xE5, 0x61, + 0x01, 0x85, 0xBF, 0xE4, 0x32, 0x43, 0xBA, 0x19, 0x1D, 0x72, 0x20, 0x0A, 0xC5, 0x21, 0x80, 0xC4, 0xF8, 0x09, 0x5C, 0xC0, + 0x1C, 0x8B, 0x54, 0x00, 0x56, 0x5F, 0xCD, 0x9A, 0x42, 0x26, 0x0A, 0xEE, 0x05, 0xA7, 0x17, 0x55, 0x37, 0x67, 0x15, 0x04, + 0xBD, 0x65, 0x3B, 0xB4, 0x47, 0x75, 0x21, 0xF7, 0x8A, 0x44, 0x2D, 0xDB, 0x93, 0x46, 0x44, 0x07, 0x3D, 0x04, 0x11, 0x0C, + 0x29, 0x08, 0x19, 0xE3, 0xFA, 0x94, 0x09, 0xD6, 0x64, 0x8A, 0xDD, 0x8C, 0xCB, 0x06, 0x19, 0xF1, 0xEA, 0xF8, 0xA2, 0x48, + 0x5C, 0xF5, 0xBC, 0x39, 0xF8, 0xA9, 0x2C, 0x24, 0x4E, 0xCA, 0xC2, 0x2C, 0x84, 0xA9, 0x42, 0x0D, 0xE8, 0x0F, 0xAA, 0xD6, + 0xF0, 0x79, 0xDA, 0x25, 0x3B, 0x0B, 0x65, 0xCD, 0x3D, 0x96, 0x19, 0x0B, 0x4A, 0xCE, 0x1B, 0x89, 0xDA, 0xB5, 0x46, 0xAD, + 0x8E, 0x28, 0xB3, 0x39, 0xB3, 0x9A, 0xFD, 0xF9, 0x2A, 0x0F, 0xD5, 0xFF, 0x95, 0x0E, 0xDB, 0x42, 0x4B, 0xAC, 0x5B, 0xB8, + 0x03, 0xC6, 0x22, 0x0A, 0xBF, 0x01, 0xC3, 0x8B, 0xCC, 0x24, 0x0B, 0x58, 0xEF, 0x73, 0xED, 0xAB, 0x88, 0x64, 0x3C, 0xB7, + 0xD6, 0x02, 0xF4, 0x51, 0xF9, 0x6D, 0x52, 0x44, 0xB7, 0x5D, 0xE1, 0x3B, 0x8D, 0x65, 0xBC, 0x6E, 0x2B, 0x08, 0x47, 0xB0, + 0x92, 0x6F, 0x6D, 0x61, 0x45, 0x78, 0x57, 0x90, 0xD2, 0x2F, 0xFF, 0x26, 0x28, 0x09, 0x48, 0x2E, 0xCB, 0x41, 0x80, 0x79, + 0xD9, 0x02, 0xDE, 0x95, 0xA7, 0x2D, 0xF6, 0x7D, 0x3E, 0x8B, 0x1C, 0x00, 0x36, 0x95, 0xE2, 0x3D, 0xC1, 0xAF, 0xE6, 0xA3, + 0x38, 0xDB, 0x8D, 0x14, 0x13, 0x11, 0x10, 0x10, 0x37, 0x94, 0x14, 0xB8, 0xE3, 0xB6, 0x23, 0x06, 0xB1, 0x11, 0xF7, 0x78, + 0x3E, 0x67, 0x45, 0x14, 0xDE, 0xB3, 0x2B, 0xA8, 0x6D, 0xA4, 0x12, 0x38, 0x70, 0x92, 0x53, 0xB9, 0xA1, 0xB7, 0x4D, 0x04, + 0xDF, 0xB2, 0x5E, 0x41, 0xE9, 0x5C, 0xC3, 0xA8, 0xD1, 0x31, 0x7C, 0x3F, 0x8E, 0x19, 0xC0, 0xE0, 0xDB, 0xA4, 0x94, 0x70, + 0x2D, 0x5C, 0x8D, 0xCD, 0x74, 0x36, 0x34, 0xF7, 0xDE, 0x1A, 0x95, 0xE8, 0x35, 0x77, 0x03, 0xF5, 0x65, 0x37, 0x64, 0x0A, + 0x75, 0x37, 0x25, 0x77, 0xAA, 0xEA, 0xDF, 0xC1, 0x91, 0xE7, 0xD1, 0x1C, 0xEA, 0x17, 0xF7, 0x1A, 0xC1, 0xC7, 0x14, 0x75, + 0x06, 0xE8, 0xD0, 0x2B, 0x3E, 0x91, 0x7E, 0xB1, 0xEF, 0xAC, 0xFB, 0xB2, 0x2D, 0x7D, 0x07, 0xA1, 0x94, 0x28, 0x9C, 0x08, + 0x3E, 0x9D, 0x36, 0xB9, 0x89, 0x5E, 0xD0, 0x0C, 0xFA, 0xDF, 0x98, 0xEB, 0x45, 0x75, 0x90, 0x18, 0x7B, 0xA6, 0x9F, 0xFF, + 0xAB, 0x19, 0xE6, 0x3E, 0xF9, 0xD2, 0xDE, 0x89, 0x49, 0xB5, 0x47, 0x1C, 0xD6, 0xBB, 0xE1, 0x31, 0x4B, 0xF7, 0xEA, 0x4F, + 0x54, 0xF7, 0x69, 0x95, 0xAA, 0x1A, 0xBB, 0xAD, 0x50, 0x6B, 0x57, 0xBD, 0x41, 0xB2, 0xA7, 0x42, 0xF7, 0x19, 0x26, 0x7E, + 0x26, 0x91, 0xC3, 0x0C, 0x6A, 0x2E, 0x52, 0xCC, 0x59, 0xAF, 0x14, 0x1C, 0xE4, 0xAD, 0x51, 0xAB, 0x7F, 0x12, 0xA8, 0xD5, + 0x38, 0x5D, 0xDD, 0x10, 0x5B, 0x10, 0x69, 0xF5, 0x7D, 0xC6, 0x3F, 0xB6, 0xAC, 0xBC, 0x07, 0x49, 0x83, 0x52, 0xEF, 0x17, + 0x08, 0x1E, 0x17, 0x69, 0x8B, 0xC1, 0x16, 0xFC, 0x0E, 0x0F, 0x10, 0xDC, 0x9F, 0x24, 0xA0, 0x11, 0x8F, 0x12, 0x43, 0x79, + 0xF5, 0xD0, 0xA2, 0x80, 0xEA, 0x8B, 0x3C, 0x74, 0xFF, 0x41, 0xF7, 0x5D, 0xE7, 0xC6, 0x22, 0x61, 0x96, 0xE0, 0xFB, 0x81, + 0xE4, 0x9A, 0x29, 0xD6, 0x3B, 0xE3, 0xF8, 0xB6, 0xBF, 0xCC, 0x86, 0x02, 0x97, 0xF0, 0x7B, 0x02, 0x27, 0xC0, 0x9F, 0x32, + 0x19, 0x04, 0xC7, 0xBF, 0x2D, 0xF3, 0xF9, 0x23, 0x5D, 0x3B, 0xF8, 0xF5, 0xB6, 0x70, 0x6D, 0xB9, 0xFE, 0xAC, 0x95, 0xBC, + 0x24, 0x95, 0xB1, 0x33, 0x5C, 0x3A, 0x48, 0x38, 0xA7, 0x7B, 0x82, 0x56, 0x15, 0x44, 0x97, 0x99, 0xA7, 0x12, 0x30, 0x0F, + 0xDB, 0x52, 0x17, 0x0D, 0xA4, 0xE0, 0xEC, 0x96, 0x1B, 0x5E, 0xBC, 0xF7, 0x04, 0x36, 0x68, 0x9E, 0x6F, 0xA7, 0xD5, 0x21, + 0x04, 0x21, 0xDF, 0x5F, 0x1B, 0x20, 0x0A, 0x8B, 0xE0, 0x8B, 0xB9, 0x62, 0xA9, 0xC6, 0xD6, 0xB1, 0x05, 0x8B, 0xED, 0x73, + 0x91, 0x25, 0xA0, 0x73, 0xBF, 0x78, 0x39, 0x65, 0x28, 0x89, 0xDA, 0xE2, 0x68, 0x03, 0x20, 0x8A, 0x1A, 0x7E, 0x3A, 0x22, + 0xCE, 0x2F, 0x94, 0x1A, 0x00, 0xAA, 0xD2, 0xF2, 0x29, 0xC6, 0xB6, 0x9A, 0x1B, 0x0C, 0x1A, 0x2B, 0xAC, 0xCF, 0x1A, 0x2F, + 0xBC, 0x46, 0xDC, 0xED, 0xBF, 0xF9, 0x63, 0x9E, 0xF2, 0x2B, 0x74, 0xDB, 0xC4, 0xC5, 0xF5, 0x8F, 0x23, 0x6D, 0x72, 0xB3, + 0x2A, 0x50, 0x6B, 0x8E, 0xF3, 0x2A, 0xCD, 0xA2, 0x6E, 0xCD, 0x3C, 0x3D, 0xDF, 0x16, 0x9B, 0x28, 0xF1, 0xE9, 0x70, 0x3E, + 0x52, 0xA5, 0xCB, 0xD2, 0xBD, 0xF1, 0x94, 0x66, 0x5F, 0x7C, 0xC5, 0xB8, 0xA3, 0x70, 0xD2, 0xA1, 0xEA, 0xC1, 0x85, 0x04, + 0xD9, 0x12, 0x3A, 0xFB, 0xF6, 0xE5, 0x5B, 0xC9, 0x64, 0x71, 0xE4, 0xCD, 0x70, 0x7C, 0x8E, 0x2C, 0x33, 0xB8, 0x4C, 0xFC, + 0xCE, 0x11, 0x13, 0xD9, 0x0E, 0x10, 0x0C, 0x9F, 0x93, 0x54, 0x97, 0x04, 0x15, 0x52, 0x7F, 0x82, 0xD7, 0xAE, 0x7E, 0x0F, + 0x4C, 0x71, 0xFA, 0x64, 0x70, 0x35, 0x0A, 0xAE, 0xA6, 0xD2, 0x70, 0x76, 0x2A, 0xF1, 0x39, 0x61, 0x1D, 0x1C, 0x2D, 0xD1, + 0xF7, 0xB3, 0x02, 0xBE, 0xE8, 0x57, 0xBC, 0x32, 0x43, 0x66, 0xE5, 0x07, 0x68, 0x33, 0x5A, 0x85, 0x84, 0x1F, 0x3D, 0xA7, + 0x4C, 0x3B, 0x8D, 0xA2, 0xF2, 0xEA, 0x7B, 0xBB, 0x4E, 0x82, 0xA5, 0xBF, 0x5C, 0xE3, 0x3C, 0xF3, 0xC3, 0x5E, 0xDD, 0x04, + 0x4A, 0xB1, 0xA4, 0x52, 0x94, 0x8F, 0xF3, 0x42, 0x30, 0x8D, 0x98, 0x7D, 0x67, 0xB4, 0x18, 0x78, 0x77, 0x94, 0xAC, 0x42, + 0x95, 0x60, 0xE4, 0x52, 0x31, 0x62, 0x90, 0x60, 0x63, 0xDD, 0xFC, 0xD2, 0xF5, 0xFD, 0x69, 0xA5, 0x95, 0xA5, 0x1A, 0x00, + 0x60, 0xBE, 0xAA, 0xE2, 0xC2, 0x0B, 0x2A, 0xE6, 0xD2, 0x0D, 0xFF, 0xF7, 0xCC, 0x67, 0xD5, 0x29, 0x4A, 0xDB, 0xF9, 0x0E, + 0xEF, 0x96, 0x4B, 0x95, 0x00, 0xF1, 0x7C, 0x05, 0x44, 0x79, 0xC4, 0xCE, 0x3F, 0xF9, 0x48, 0x9F, 0x85, 0x39, 0xF0, 0xC7, + 0x95, 0xC8, 0xD3, 0xE8, 0x1B, 0xC6, 0x38, 0xD9, 0xF7, 0xE9, 0x2A, 0x3E, 0x63, 0x8E, 0x41, 0x3C, 0x97, 0x06, 0xE7, 0x0F, + 0xDD, 0xEB, 0x9D, 0x7C, 0xD0, 0x17, 0x9B, 0x38, 0xF8, 0xD0, 0xCF, 0x2B, 0xFA, 0xDC, 0x29, 0xAE, 0x2D, 0xA5, 0xE7, 0x82, + 0xBB, 0xF9, 0x61, 0x59, 0xE1, 0x99, 0x85, 0x5D, 0x51, 0x06, 0x99, 0x37, 0xD1, 0xDD, 0x05, 0x8E, 0x58, 0x47, 0x2F, 0x46, + 0xCB, 0x5B, 0xFE, 0xD9, 0xDF, 0x90, 0x14, 0xBA, 0x3F, 0xDF, 0xF4, 0xDB, 0x1C, 0x0C, 0xBE, 0x7E, 0x56, 0x22, 0x7A, 0x39, + 0xFF, 0xDD, 0x3E, 0xE3, 0x0B, 0x61, 0xE3, 0xEB, 0x57, 0x2E, 0xF7, 0x7A, 0xDD, 0x9F, 0x14, 0xA8, 0x20, 0xF6, 0x22, 0xAF, + 0x52, 0x16, 0xB6, 0xE6, 0xB9, 0xFD, 0x48, 0xF2, 0xE9, 0x64, 0x53, 0x3F, 0x5C, 0xBE, 0x3E, 0xC9, 0x23, 0x40, 0xBA, 0x80, + 0x31, 0xE3, 0xC4, 0x53, 0x6E, 0x2C, 0x47, 0x57, 0x66, 0xB6, 0x2B, 0x0E, 0x37, 0xF5, 0x64, 0x86, 0x19, 0x2B, 0x1C, 0x30, + 0x22, 0xBE, 0x9E, 0x91, 0x32, 0x21, 0x1D, 0x09, 0x86, 0xB9, 0xBF, 0xB0, 0xB1, 0x80, 0x73, 0x29, 0xC1, 0x02, 0xEF, 0x99, + 0xD9, 0xB8, 0xDC, 0x95, 0xA0, 0x03, 0x09, 0x54, 0x81, 0x8E, 0x67, 0x89, 0x2A, 0xF0, 0x8F, 0x98, 0x3A, 0x10, 0x97, 0x3E, + 0x68, 0x57, 0xD5, 0xC0, 0x3E, 0x14, 0x48, 0x75, 0xB5, 0x21, 0x22, 0x02, 0xDD, 0xE2, 0x88, 0x30, 0x3B, 0x08, 0x58, 0xA4, + 0x1B, 0x2A, 0x0D, 0xE3, 0x33, 0xE8, 0xDC, 0x76, 0x15, 0xF8, 0x3F, 0xFD, 0x8B, 0xDC, 0xC7, 0xE0, 0x9A, 0x02, 0x69, 0x9E, + 0x4D, 0xEB, 0xD5, 0xA5, 0xF6, 0xED, 0x53, 0x50, 0xA0, 0x47, 0x7E, 0xF8, 0x67, 0x74, 0xCC, 0x01, 0x43, 0x58, 0x87, 0x97, + 0x9B, 0xE2, 0x7C, 0xA0, 0xA4, 0x05, 0x57, 0x9F, 0x5B, 0x87, 0x2C, 0x8D, 0xAA, 0x58, 0xA8, 0x9D, 0x6E, 0xC7, 0xF7, 0xF4, + 0x09, 0xDC, 0x8A, 0xEF, 0x6B, 0x01, 0x1B, 0xBA, 0x69, 0xBF, 0xD2, 0xA4, 0xB0, 0x03, 0x7D, 0xA0, 0x61, 0x80, 0xD4, 0x7E, + 0xAE, 0xAC, 0x13, 0x69, 0xCC, 0x62, 0x42, 0xA9, 0xF9, 0x21, 0xDA, 0x26, 0xB7, 0xB4, 0x8A, 0x0C, 0xB7, 0x86, 0x0D, 0x5B, + 0xE6, 0x6B, 0xD9, 0xC2, 0x30, 0x88, 0x5E, 0x58, 0x0C, 0x05, 0x02, 0xAD, 0x01, 0x6D, 0x6C, 0xC0, 0x2B, 0x48, 0xC0, 0x7D, + 0xA1, 0xB1, 0x42, 0x44, 0x0D, 0x04, 0xF4, 0x90, 0x96, 0x4F, 0x64, 0xD1, 0x95, 0x90, 0x83, 0xCA, 0xFE, 0xE4, 0x43, 0xCD, + 0xAB, 0xAC, 0xF9, 0xBE, 0xFE, 0xD1, 0x32, 0x29, 0xB3, 0x20, 0x3F, 0xF6, 0xDB, 0x5C, 0x53, 0x99, 0xC7, 0xA2, 0xB5, 0x68, + 0x72, 0xB5, 0x41, 0x7B, 0x78, 0xE2, 0xDF, 0x1D, 0xCF, 0xE4, 0xA3, 0xBC, 0x5B, 0xB0, 0x3A, 0x01, 0xDB, 0x13, 0x6B, 0xD3, + 0x0E, 0x3C, 0xAF, 0x20, 0x51, 0xB3, 0x0D, 0x14, 0x7D, 0x37, 0x5C, 0xE7, 0x45, 0xE4, 0x1D, 0xC3, 0x5F, 0xA0, 0x5C, 0xD4, + 0x56, 0x7B, 0xC5, 0xE1, 0x2C, 0xA9, 0xBB, 0xB9, 0xBE, 0x9D, 0x72, 0xE1, 0xE4, 0x7A, 0xAB, 0x10, 0xD1, 0x70, 0xAE, 0xAC, + 0x7D, 0x10, 0x9A, 0x7D, 0xBD, 0xEF, 0x63, 0x08, 0x14, 0x57, 0x18, 0x31, 0xD0, 0x19, 0x1E, 0xA0, 0x4A, 0xA7, 0x40, 0x64, + 0x74, 0xE4, 0x02, 0x73, 0x40, 0xF9, 0xA2, 0x02, 0x41, 0xD3, 0x1A, 0x68, 0xC8, 0x71, 0x95, 0xEE, 0x96, 0x83, 0x54, 0x5C, + 0x65, 0x5C, 0xD4, 0xE4, 0xF4, 0x07, 0x3B, 0xC7, 0xC1, 0x33, 0xFB, 0xF1, 0x49, 0x5A, 0xC2, 0x65, 0xC3, 0x57, 0x6D, 0x22, + 0x30, 0x26, 0x75, 0x2E, 0x2C, 0xBA, 0x35, 0x5D, 0x16, 0xB1, 0x5D, 0x75, 0xC2, 0xF5, 0xE7, 0x13, 0xD1, 0x05, 0x5F, 0xA6, + 0x8D, 0x13, 0x36, 0xFB, 0x36, 0xE4, 0x86, 0xB9, 0x46, 0xF5, 0xA8, 0x01, 0x00, 0xD7, 0xF1, 0x70, 0xAF, 0x54, 0x22, 0xEF, + 0x4D, 0xCF, 0x24, 0x08, 0x96, 0x1B, 0x98, 0x19, 0x1A, 0xA6, 0x82, 0x61, 0x62, 0x57, 0x43, 0x47, 0x0B, 0xC5, 0x5D, 0x99, + 0x17, 0xA5, 0x40, 0xD7, 0x78, 0x2B, 0xE3, 0x06, 0xA8, 0x8B, 0xF1, 0xA1, 0x50, 0x8A, 0x07, 0x0C, 0xEF, 0x52, 0x89, 0x10, + 0x12, 0x08, 0x10, 0x57, 0x49, 0x18, 0xC6, 0x2A, 0x09, 0x49, 0x5E, 0xC8, 0x6C, 0x55, 0x13, 0x04, 0x90, 0x31, 0x06, 0xDC, + 0x02, 0x9D, 0x8E, 0x7C, 0x21, 0x7D, 0x0C, 0x1E, 0x7B, 0xF0, 0x53, 0x9C, 0x7F, 0xF0, 0x3E, 0xB8, 0xC8, 0x08, 0x7F, 0xC5, + 0x98, 0xD3, 0x4F, 0x29, 0xA6, 0xF3, 0xC1, 0xD9, 0x5D, 0xD3, 0x43, 0x27, 0xAD, 0x16, 0x27, 0x55, 0x3C, 0x0D, 0x09, 0x1F, + 0xD8, 0x19, 0x27, 0x15, 0x11, 0x32, 0x7B, 0x02, 0x02, 0x70, 0xEA, 0x36, 0xEB, 0x5F, 0x87, 0x23, 0xCB, 0xE0, 0x1C, 0xB9, + 0x57, 0xA2, 0xF9, 0x2D, 0x3B, 0x3D, 0x68, 0x76, 0x04, 0x0C, 0x6F, 0x13, 0xD1, 0xE0, 0x86, 0x9B, 0x9F, 0x6B, 0x45, 0x1C, + 0xEA, 0x57, 0x9B, 0xB7, 0x6B, 0x7D, 0xCC, 0x02, 0x9A, 0xE3, 0x71, 0x47, 0xDB, 0x8E, 0x94, 0x48, 0xF6, 0x83, 0x7B, 0x77, + 0xC5, 0xCD, 0x48, 0x12, 0x52, 0x81, 0xC7, 0x8A, 0x3C, 0xB0, 0x32, 0xA4, 0x16, 0x29, 0xF8, 0x57, 0x7D, 0x65, 0x21, 0x12, + 0xC6, 0xD2, 0x70, 0x80, 0x44, 0xA9, 0x84, 0x21, 0x6D, 0x23, 0x9E, 0xFC, 0xB6, 0x22, 0xC6, 0xF7, 0xB4, 0x38, 0xBD, 0x04, + 0x64, 0x22, 0x37, 0xA5, 0x8F, 0x58, 0xE5, 0xBA, 0x92, 0xA0, 0x79, 0xBF, 0x33, 0x83, 0xE7, 0x53, 0x71, 0xE2, 0xB9, 0x20, + 0xAD, 0xC5, 0xED, 0xD7, 0x76, 0xA8, 0xBD, 0x88, 0x2E, 0xB6, 0x01, 0xFF, 0x70, 0xE3, 0xE2, 0x17, 0x86, 0x3C, 0xC0, 0x0F, + 0x1F, 0xE8, 0x2A, 0x7A, 0xA5, 0xA2, 0xD0, 0x2E, 0xB7, 0x3B, 0x32, 0x1D, 0x55, 0xCB, 0x66, 0x5F, 0x0D, 0x09, 0x96, 0xA1, + 0x4E, 0x6B, 0x84, 0xEE, 0xA6, 0x72, 0xF1, 0xF2, 0xC0, 0xC8, 0xAF, 0x07, 0x9A, 0xA3, 0x71, 0xD0, 0x25, 0x29, 0xBF, 0xF3, + 0x94, 0x89, 0xAC, 0x98, 0x59, 0x3A, 0x7F, 0x6C, 0xE5, 0xEE, 0x05, 0xFE, 0xAD, 0x14, 0xBB, 0x0E, 0x7C, 0x14, 0x7A, 0x6A, + 0x0D, 0xCC, 0xBB, 0xFD, 0xB9, 0x07, 0xC2, 0x1D, 0x40, 0x13, 0xB6, 0x86, 0xB4, 0xA1, 0x10, 0xBA, 0x03, 0x20, 0x12, 0xAF, + 0x7B, 0x6B, 0x04, 0xCB, 0xBA, 0x5E, 0xFC, 0x00, 0x81, 0xA2, 0x7F, 0x5B, 0x67, 0x3D, 0xBF, 0xD9, 0xAD, 0xF9, 0x4D, 0x53, + 0xC0, 0x7F, 0x08, 0xA8, 0x00, 0xE6, 0x38, 0xA9, 0xAE, 0x1D, 0x34, 0xC9, 0xBD, 0x9D, 0x05, 0xCB, 0x40, 0x62, 0xDB, 0x6F, + 0x3E, 0xF4, 0x1A, 0xBF, 0x80, 0x7D, 0x47, 0x75, 0x4C, 0xF2, 0xEC, 0x62, 0x22, 0x7D, 0xEE, 0x59, 0x1E, 0xA3, 0x7C, 0x17, + 0xCE, 0x92, 0xB4, 0x0A, 0xDC, 0xDB, 0x02, 0x06, 0xE8, 0x27, 0xE4, 0xB2, 0x5C, 0x71, 0xE1, 0x70, 0xD8, 0x3F, 0xBD, 0xD7, + 0x5D, 0x71, 0x7F, 0x93, 0x13, 0x2D, 0xCB, 0x0B, 0x1D, 0x31, 0x13, 0xAF, 0x51, 0x22, 0xEF, 0x6C, 0x5C, 0x50, 0x35, 0xB7, + 0xEC, 0xC3, 0x83, 0x02, 0xD6, 0xB3, 0x71, 0xA0, 0x47, 0xB4, 0xBD, 0xE9, 0x55, 0x94, 0xCC, 0xF2, 0xC1, 0x96, 0x18, 0x74, + 0x66, 0xFC, 0x52, 0x6B, 0x4F, 0x98, 0x14, 0xF6, 0x29, 0x7F, 0x79, 0xCD, 0x59, 0x00, 0x1E, 0x02, 0x7F, 0xB4, 0x3D, 0xC7, + 0x8F, 0x16, 0x1D, 0xCF, 0xD5, 0x27, 0x6D, 0xCA, 0xE0, 0xB7, 0x73, 0x95, 0x51, 0xED, 0x92, 0xA0, 0xD5, 0xD5, 0xB4, 0x2F, + 0x12, 0x68, 0xAC, 0x77, 0x94, 0x47, 0xED, 0x62, 0xB3, 0xF6, 0x7F, 0x8E, 0xF9, 0xDD, 0x0A, 0x15, 0x3F, 0x3A, 0xF6, 0xCA, + 0x53, 0x7B, 0xAA, 0xBE, 0x7A, 0xF1, 0x47, 0x70, 0xC6, 0xDA, 0x7F, 0x6D, 0x4F, 0xD5, 0x3F, 0xAB, 0x43, 0x74, 0xED, 0x42, + 0x7D, 0x54, 0x99, 0x0E, 0x79, 0xF8, 0x67, 0xEF, 0x83, 0x19, 0xE6, 0x58, 0x9E, 0xF2, 0x6A, 0x1E, 0xCA, 0x55, 0x8C, 0x3A, + 0x4C, 0x34, 0x91, 0x32, 0x63, 0x14, 0x75, 0x8B, 0xE5, 0x24, 0x6A, 0x8E, 0xBE, 0x54, 0x7E, 0xDF, 0xC5, 0xED, 0xB8, 0x2C, + 0x76, 0x39, 0x56, 0x6E, 0xE1, 0x71, 0xB5, 0xEB, 0x5E, 0x7E, 0x50, 0x67, 0x47, 0x90, 0xCE, 0xB8, 0xCC, 0xD3, 0x2A, 0x7E, + 0x4E, 0xDC, 0xC0, 0xB3, 0x5C, 0x15, 0xD3, 0xA9, 0x45, 0x0F, 0xF5, 0xDE, 0x45, 0xA5, 0x21, 0x78, 0xC8, 0x73, 0x6C, 0x6B, + 0x9F, 0x0F, 0x90, 0xA8, 0xD9, 0xDD, 0x88, 0x9F, 0xEF, 0xA4, 0x77, 0xEF, 0xE9, 0xD6, 0xA6, 0xE4, 0x5A, 0x20, 0x01, 0x66, + 0xFF, 0xDD, 0xE2, 0x04, 0xB7, 0x8B, 0xAA, 0xA5, 0x4E, 0xCA, 0x7C, 0x5B, 0x9A, 0x3A, 0x32, 0x8F, 0xFE, 0x8C, 0xD0, 0x9C, + 0xB9, 0x0C, 0xA7, 0xBF, 0x22, 0x45, 0xF9, 0x74, 0x01, 0x7A, 0x51, 0x76, 0xCC, 0x6E, 0xDD, 0x99, 0x79, 0x09, 0xC6, 0xDA, + 0x7F, 0x2C, 0xCB, 0x27, 0x63, 0xBB, 0xEA, 0xEF, 0x87, 0xE0, 0x49, 0xA0, 0xAE, 0x38, 0x60, 0x4F, 0xA0, 0x47, 0xE8, 0x4F, + 0x76, 0x73, 0x22, 0x51, 0x03, 0x34, 0x00, 0xF1, 0x70, 0xB9, 0xF3, 0x48, 0x9A, 0xA5, 0x8A, 0x4A, 0xF1, 0x01, 0xD8, 0x22, + 0x30, 0x52, 0xCE, 0x6D, 0xFA, 0x94, 0x78, 0x8E, 0xB8, 0xDA, 0xA0, 0x53, 0x30, 0x30, 0x18, 0xD7, 0xE5, 0x66, 0xB9, 0x62, + 0x6B, 0x29, 0x72, 0x55, 0x23, 0xBD, 0x8B, 0xB4, 0x71, 0x03, 0xB1, 0x75, 0x06, 0x85, 0x91, 0x51, 0xDB, 0xB6, 0xEC, 0x58, + 0x77, 0x56, 0xA1, 0x52, 0x3A, 0x36, 0x8D, 0xCF, 0xD6, 0xD5, 0x64, 0x7A, 0x95, 0x4A, 0x73, 0xE8, 0x10, 0xF5, 0xAD, 0xCA, + 0x33, 0x43, 0x10, 0x1A, 0x9B, 0x01, 0xD0, 0x1E, 0xAA, 0xF0, 0xDA, 0x8D, 0x0D, 0x41, 0x25, 0xAF, 0x35, 0xE2, 0x19, 0x0B, + 0x3B, 0x97, 0xFC, 0x4A, 0x65, 0x9C, 0xEC, 0x6E, 0x29, 0xBC, 0x71, 0x2F, 0x9D, 0x04, 0x89, 0x47, 0x78, 0xD7, 0xEA, 0xDD, + 0x95, 0x80, 0x9F, 0x19, 0xDF, 0xD2, 0xBB, 0xD7, 0xAC, 0x7D, 0xEA, 0xDD, 0x8F, 0xCE, 0xE2, 0xFA, 0x1C, 0xCF, 0x67, 0x5D, + 0xFA, 0x8D, 0xAA, 0x4B, 0xB3, 0x1D, 0x4A, 0x78, 0x49, 0x4D, 0x95, 0x5C, 0x68, 0x21, 0x72, 0x1A, 0xB6, 0x41, 0xA2, 0x5B, + 0xB2, 0x1C, 0xEB, 0xD1, 0x8C, 0x17, 0xB3, 0xC9, 0xF4, 0x81, 0x93, 0xE9, 0xCF, 0x93, 0xAB, 0x4A, 0x33, 0x3F, 0x77, 0xC6, + 0x09, 0x0B, 0x0B, 0xB9, 0xBA, 0xF4, 0x63, 0xFB, 0x4B, 0xAE, 0xA3, 0x7F, 0xDD, 0xE2, 0xFC, 0x82, 0x00, 0x52, 0x82, 0x00, + 0x5E, 0x70, 0xAC, 0x5B, 0xED, 0xAD, 0x5D, 0x4B, 0x91, 0xF6, 0xB4, 0xA1, 0x45, 0x5E, 0x94, 0x8D, 0xBE, 0x97, 0xE7, 0x8B, + 0x0D, 0xCA, 0x79, 0xDA, 0x10, 0x75, 0xD3, 0x5A, 0x93, 0xDE, 0xCD, 0x04, 0x59, 0x19, 0x72, 0x5E, 0x15, 0xC4, 0x95, 0x4B, + 0x7D, 0x8F, 0xB5, 0x56, 0x63, 0x33, 0x1F, 0xD5, 0xF9, 0x71, 0x1D, 0x76, 0x1C, 0xE5, 0xE4, 0xCB, 0x90, 0x77, 0x1C, 0xC4, + 0xD3, 0xCD, 0x9B, 0xD1, 0x34, 0xFF, 0x54, 0xA0, 0x3F, 0xD9, 0x95, 0x92, 0xB0, 0x74, 0x97, 0xD2, 0x5C, 0xB4, 0xD4, 0x2C, + 0xEF, 0x8E, 0xF0, 0x83, 0x1B, 0x4E, 0x64, 0x0E, 0x63, 0x38, 0x5D, 0xC5, 0x0B, 0xE0, 0xED, 0x39, 0x5E, 0xCD, 0x2B, 0xD9, + 0x09, 0xE7, 0xDD, 0xD1, 0xC1, 0x1A, 0x12, 0xC4, 0xA5, 0x6C, 0x86, 0x3D, 0x21, 0xFA, 0x38, 0x67, 0x0A, 0xC6, 0xA2, 0x71, + 0x9D, 0x9B, 0x0E, 0x09, 0xC9, 0x57, 0x50, 0xF2, 0xB8, 0x58, 0x4C, 0xAA, 0xDB, 0x81, 0xF7, 0x6C, 0x6C, 0x63, 0x06, 0x98, + 0x2A, 0xF9, 0xD2, 0x7C, 0x3D, 0x77, 0x6B, 0xDE, 0x11, 0x16, 0xA1, 0x5A, 0x12, 0x52, 0x57, 0x19, 0xF8, 0x58, 0xBD, 0x7E, + 0x93, 0x97, 0x76, 0xE9, 0xFC, 0x41, 0xE6, 0xD7, 0x5F, 0x6A, 0x56, 0x0F, 0xCE, 0x9B, 0xC8, 0xBD, 0xE3, 0x7B, 0x5E, 0xDF, + 0x9B, 0x5F, 0x1E, 0xCE, 0xD2, 0x70, 0xFE, 0xB7, 0x0B, 0x5C, 0x3F, 0xC4, 0xDF, 0x43, 0x17, 0x7E, 0x6B, 0x1C, 0xDE, 0xF9, + 0x58, 0xFE, 0x91, 0xB8, 0xD3, 0xD7, 0x18, 0x7E, 0xCE, 0x31, 0x0C, 0x9A, 0x9C, 0x38, 0x1A, 0x8F, 0x6C, 0x11, 0x7B, 0x56, + 0xDD, 0xB8, 0x07, 0xB0, 0x3F, 0x7C, 0x6B, 0x10, 0xEC, 0xBD, 0x11, 0x2B, 0xB4, 0x7A, 0x7C, 0x08, 0xAD, 0xB4, 0xF7, 0xA2, + 0x3A, 0x32, 0x67, 0x16, 0x7E, 0x82, 0x1B, 0x02, 0x74, 0xC2, 0x8F, 0x79, 0xD9, 0x9B, 0xFC, 0x90, 0x36, 0x22, 0x0E, 0xC3, + 0xCB, 0x66, 0xB8, 0xA2, 0x67, 0xE6, 0x60, 0x96, 0xF0, 0xCE, 0x84, 0x0F, 0xFC, 0x8A, 0xEE, 0x4C, 0xC5, 0xA1, 0xE1, 0x9C, + 0x88, 0xAE, 0x52, 0x87, 0xEA, 0x32, 0xA7, 0x27, 0xDA, 0xE2, 0xA3, 0x63, 0x8C, 0x80, 0x09, 0xD8, 0xC4, 0xAF, 0x28, 0x6C, + 0x22, 0x80, 0x45, 0x84, 0xF1, 0xAB, 0x03, 0xC0, 0xEE, 0x6E, 0xB8, 0x48, 0x72, 0x48, 0x76, 0x20, 0xF1, 0xE1, 0x47, 0xBB, + 0x45, 0x11, 0x48, 0x9C, 0xEA, 0xC9, 0x90, 0xD1, 0x31, 0xEB, 0xEC, 0x2C, 0x66, 0xD0, 0xF0, 0xBE, 0x85, 0x68, 0x42, 0x99, + 0xF4, 0xCB, 0x4C, 0x94, 0xD2, 0x67, 0x59, 0x33, 0xCD, 0x8D, 0x74, 0xAB, 0x7A, 0xDD, 0x8C, 0x2D, 0x33, 0x9A, 0x45, 0x85, + 0x7A, 0xE9, 0x71, 0x57, 0x2E, 0x71, 0x97, 0xE6, 0x87, 0x6A, 0x41, 0x8C, 0x44, 0xCA, 0xA0, 0xE5, 0x30, 0xF7, 0x60, 0x06, + 0x0A, 0x80, 0xA4, 0x8A, 0x72, 0x75, 0x6E, 0xCA, 0x48, 0x86, 0xEE, 0xB2, 0xDC, 0xD9, 0xFC, 0xC1, 0x8D, 0x88, 0xF6, 0x9A, + 0x73, 0x51, 0xFA, 0x8F, 0x72, 0xD2, 0x5D, 0xC1, 0xAC, 0x3F, 0x23, 0xCB, 0xC4, 0xC8, 0x83, 0x0A, 0x7D, 0x05, 0x74, 0x8B, + 0x96, 0x93, 0x73, 0x9A, 0xCD, 0x86, 0x72, 0x4D, 0xEE, 0xCB, 0x6B, 0xAA, 0x50, 0xA1, 0x4A, 0x5D, 0x3E, 0xDB, 0x40, 0x78, + 0x3C, 0x4D, 0x02, 0x48, 0x36, 0x81, 0x9C, 0xFA, 0x18, 0x55, 0x89, 0xEE, 0x4C, 0x70, 0x08, 0xEA, 0x63, 0x54, 0x0A, 0x58, + 0x63, 0x80, 0xF2, 0xB6, 0x8D, 0x60, 0x96, 0x09, 0x73, 0x4B, 0xB4, 0xA3, 0xD0, 0xF6, 0x98, 0x6C, 0x2F, 0x71, 0xB8, 0xB3, + 0x72, 0x55, 0xD0, 0x47, 0x12, 0xBF, 0xA3, 0xFF, 0xD2, 0xAC, 0x10, 0x7C, 0x2E, 0x76, 0x12, 0x57, 0x7A, 0xD0, 0x84, 0x08, + 0xFB, 0x49, 0x9D, 0x09, 0x1D, 0xCF, 0x8C, 0xAE, 0x00, 0x91, 0x90, 0xF0, 0xDD, 0xC8, 0x20, 0xE5, 0x85, 0x76, 0xB2, 0x4E, + 0xB2, 0x3B, 0x7C, 0x07, 0x21, 0xB4, 0x61, 0xF4, 0x16, 0x81, 0x3C, 0x48, 0xE8, 0x2C, 0xD8, 0xD0, 0xBF, 0xAB, 0x67, 0x87, + 0x0C, 0xD3, 0xFD, 0x9A, 0x36, 0x6E, 0xA3, 0x58, 0x05, 0x54, 0x35, 0x83, 0x79, 0xE9, 0xBD, 0x7B, 0x27, 0xDE, 0x01, 0xEC, + 0x7F, 0x8B, 0x5A, 0xC9, 0x84, 0xD7, 0xE7, 0xB5, 0xF3, 0x10, 0xAB, 0xDD, 0x1E, 0x40, 0xDA, 0xEB, 0xC2, 0xE5, 0xDD, 0x8C, + 0x48, 0x72, 0x13, 0x16, 0xF6, 0xEB, 0xFE, 0xAC, 0xA6, 0x98, 0x47, 0x73, 0xE2, 0xAB, 0xED, 0xCD, 0x5B, 0x58, 0x14, 0x6E, + 0xF0, 0x77, 0x74, 0xD8, 0xCA, 0x02, 0xBC, 0xD2, 0x3B, 0xD5, 0x4D, 0x08, 0x55, 0x03, 0xEE, 0x6D, 0xF7, 0xB6, 0xD2, 0x91, + 0x06, 0xD5, 0x90, 0x2C, 0x66, 0x6A, 0x06, 0x08, 0xE1, 0xD5, 0x26, 0xD4, 0x88, 0xFE, 0xDD, 0x82, 0x89, 0x67, 0x9D, 0x1D, + 0x2D, 0xB0, 0x4F, 0xD4, 0x0D, 0xDC, 0x72, 0x6E, 0x3A, 0xBA, 0x48, 0xD2, 0x2C, 0xD9, 0x78, 0xD6, 0xB0, 0x4F, 0x67, 0x11, + 0xC8, 0x7F, 0xE7, 0x10, 0xD8, 0x58, 0x8B, 0x18, 0xB5, 0x47, 0x27, 0x8D, 0x91, 0xF8, 0x56, 0x6B, 0xB0, 0xB6, 0x61, 0xAB, + 0xFF, 0xD8, 0x1B, 0x83, 0x9E, 0x7D, 0x50, 0xE5, 0x6B, 0x64, 0xA9, 0x5D, 0xFF, 0x96, 0x2D, 0x59, 0x58, 0x97, 0xB0, 0xD1, + 0xCF, 0xA3, 0xCD, 0x4A, 0x50, 0x13, 0xFE, 0x98, 0x51, 0xD8, 0xC8, 0x3A, 0x16, 0xF1, 0x06, 0xB8, 0xD8, 0xDF, 0xD6, 0x20, + 0x39, 0xF6, 0x26, 0xE5, 0xB6, 0x20, 0x07, 0x8C, 0x84, 0xBD, 0x1E, 0x09, 0x0F, 0x61, 0x8F, 0xAD, 0x41, 0xB0, 0x8E, 0x00, + 0x5D, 0x9C, 0x0A, 0x9C, 0xB5, 0x9D, 0x2F, 0x80, 0x73, 0xAE, 0xF7, 0x5D, 0x51, 0x74, 0x50, 0xA1, 0x1A, 0x43, 0x25, 0xE0, + 0xFF, 0xFF, 0x3A, 0xF3, 0x34, 0x06, 0x2C, 0x97, 0x60, 0x2A, 0x94, 0xD1, 0x38, 0xC0, 0x68, 0xCC, 0x6A, 0x2D, 0xCC, 0x95, + 0x0F, 0x8B, 0x77, 0x16, 0x15, 0xD4, 0xD8, 0xB4, 0xD4, 0xB4, 0xD0, 0x30, 0xD1, 0x21, 0x21, 0x58, 0x21, 0xDD, 0x03, 0xED, + 0xAA, 0x6F, 0xD1, 0xB5, 0xEE, 0x2E, 0x6E, 0x62, 0x1A, 0xF3, 0xCE, 0xB1, 0x20, 0xC3, 0x9A, 0xFD, 0xE7, 0xDE, 0x8B, 0x43, + 0x4C, 0x01, 0x2E, 0x0D, 0xE2, 0x50, 0x1E, 0x6C, 0x06, 0x00, 0x9A, 0x48, 0x9C, 0x3F, 0x02, 0xD6, 0xA9, 0x20, 0x57, 0xE6, + 0xAE, 0x6D, 0x00, 0x5C, 0x05, 0x87, 0x72, 0xAB, 0x9C, 0xA3, 0x9A, 0xDC, 0x0B, 0x15, 0x18, 0xE4, 0x50, 0x06, 0xC8, 0xC5, + 0x8C, 0xBB, 0x63, 0xB3, 0xA1, 0x4D, 0x6F, 0x59, 0x61, 0x04, 0xE9, 0x9A, 0x62, 0x35, 0xD4, 0x11, 0xCB, 0xAC, 0xCD, 0x95, + 0x83, 0x3C, 0xC9, 0x6E, 0xE9, 0xCA, 0xBF, 0x17, 0x51, 0x82, 0x25, 0x25, 0xD4, 0x99, 0x7A, 0x76, 0x97, 0x8E, 0x54, 0x31, + 0x4B, 0x08, 0x2D, 0xCA, 0x6B, 0x40, 0x2D, 0x20, 0x0F, 0x73, 0x86, 0x7A, 0xE6, 0x2D, 0xA2, 0xC7, 0x7A, 0x61, 0x89, 0x7C, + 0x5D, 0x6D, 0x23, 0x19, 0x54, 0x7B, 0x90, 0x4D, 0xDC, 0x31, 0x07, 0x18, 0xFB, 0x79, 0x2B, 0xD2, 0x57, 0xCC, 0x84, 0x9B, + 0x67, 0x20, 0x0B, 0x22, 0xE9, 0x30, 0xA3, 0xBD, 0xCF, 0x17, 0x1B, 0x02, 0xA9, 0x70, 0xD3, 0x4D, 0x8A, 0x7F, 0x90, 0x2A, + 0x67, 0x25, 0xAF, 0x86, 0xF7, 0xED, 0xCA, 0x8E, 0xF6, 0x91, 0x4F, 0x2B, 0x33, 0x06, 0x12, 0x2A, 0xE4, 0x43, 0xA1, 0xFC, + 0x45, 0xC5, 0xE4, 0xC9, 0xD6, 0xCB, 0x83, 0xCC, 0x73, 0x04, 0x43, 0x4F, 0xBB, 0x35, 0x6B, 0x96, 0x7F, 0x2D, 0xAB, 0x9C, + 0xB4, 0x4E, 0x4D, 0xA8, 0xBF, 0x8F, 0xA9, 0x5C, 0x98, 0xED, 0x61, 0x9B, 0x67, 0x40, 0x09, 0xBD, 0xF3, 0x69, 0x3E, 0x73, + 0x34, 0xCB, 0x33, 0xBC, 0x36, 0x8B, 0x76, 0xA1, 0x61, 0xE9, 0x2C, 0x5B, 0x99, 0xE1, 0x2C, 0x69, 0xDE, 0x53, 0x1E, 0xD3, + 0xF3, 0xB1, 0x45, 0xF1, 0xC4, 0xCE, 0xC2, 0x9D, 0x79, 0x75, 0xF7, 0x7C, 0xBE, 0x69, 0x19, 0x9A, 0xDC, 0x9F, 0x4C, 0x08, + 0x45, 0xED, 0x79, 0x3A, 0xF1, 0xD2, 0x52, 0x70, 0xD6, 0xD4, 0xC5, 0x9C, 0x58, 0xD2, 0x7A, 0x76, 0x23, 0x73, 0x9E, 0xC6, + 0x81, 0x8A, 0xC7, 0x07, 0x24, 0x76, 0x32, 0x24, 0x93, 0xCD, 0x42, 0x55, 0x89, 0x10, 0x8A, 0x51, 0x7A, 0xD9, 0x0E, 0xBD, + 0x20, 0x75, 0x5E, 0x2B, 0x52, 0x75, 0x66, 0x77, 0x08, 0xD6, 0x94, 0x50, 0x10, 0x7C, 0xFE, 0x81, 0xB2, 0x54, 0xDD, 0xD8, + 0xB4, 0xB4, 0x6F, 0x59, 0x09, 0x32, 0x03, 0xA2, 0x38, 0x55, 0x13, 0xFD, 0xEF, 0x55, 0xD5, 0xC0, 0x4E, 0xBE, 0x5D, 0x02, + 0x89, 0x82, 0xCB, 0x40, 0x18, 0x33, 0xD9, 0x07, 0x17, 0x1C, 0x2A, 0x1E, 0x78, 0x32, 0x1E, 0x75, 0x5B, 0xDB, 0xCE, 0xBC, + 0x93, 0x49, 0x52, 0x64, 0xC3, 0xE2, 0x0F, 0xDB, 0xFB, 0x3D, 0x9F, 0xA8, 0x79, 0x16, 0x61, 0x7B, 0x7F, 0x1B, 0x58, 0x76, + 0xAE, 0xA1, 0x07, 0xCC, 0x68, 0x97, 0x4D, 0xA8, 0x4F, 0xF7, 0xB7, 0xA8, 0x93, 0x4B, 0xDF, 0x74, 0x29, 0xA0, 0x87, 0x99, + 0xB0, 0xAF, 0xA0, 0x2A, 0xD5, 0x51, 0x24, 0xFD, 0xE9, 0xD6, 0x82, 0xB3, 0x2B, 0x0C, 0x44, 0xAC, 0x3E, 0x38, 0x04, 0x00, + 0x2A, 0x80, 0xEC, 0x5C, 0x86, 0xD3, 0x4A, 0x3A, 0xAB, 0xBD, 0x31, 0x1B, 0xF9, 0x1D, 0x9A, 0x32, 0xD8, 0xD7, 0x0F, 0x78, + 0x39, 0x77, 0x27, 0x7E, 0x89, 0x95, 0x57, 0x25, 0xD1, 0xF3, 0xE7, 0x9E, 0xE4, 0x82, 0x73, 0x8F, 0x05, 0x6B, 0x75, 0x5B, + 0x45, 0x14, 0x87, 0xD4, 0x39, 0xD8, 0xD8, 0x06, 0x02, 0xBC, 0xA0, 0x58, 0x31, 0x72, 0x18, 0x72, 0x0C, 0x89, 0x36, 0x79, + 0xB3, 0xA4, 0x87, 0x17, 0xA5, 0x5F, 0xBC, 0x59, 0xF3, 0xFB, 0x0E, 0x2A, 0x1D, 0xC3, 0xDA, 0x13, 0x51, 0x2C, 0x7C, 0xEF, + 0x44, 0xFA, 0x2D, 0xF1, 0x8B, 0xE9, 0xF6, 0x10, 0xB8, 0x92, 0xA2, 0xEF, 0xF6, 0xEF, 0x4E, 0xDD, 0x49, 0x80, 0xE2, 0x41, + 0x2B, 0x4F, 0xEB, 0xBF, 0xB6, 0x02, 0x51, 0x1F, 0xF6, 0x5C, 0x60, 0x83, 0x60, 0x4A, 0xBF, 0xC6, 0xE5, 0xC3, 0x40, 0x7B, + 0x00, 0xE6, 0xB9, 0xF3, 0xB3, 0x5D, 0xF5, 0xCD, 0x46, 0xE4, 0x47, 0x06, 0x50, 0x66, 0xA8, 0xC2, 0x3A, 0x8F, 0x38, 0x34, + 0xE8, 0x2C, 0xC1, 0x02, 0x07, 0xCE, 0xC0, 0x8C, 0xBE, 0x06, 0x5E, 0x83, 0x9A, 0xEA, 0xF9, 0xC7, 0x14, 0x01, 0xF0, 0x0C, + 0xE5, 0xA6, 0xFC, 0x9C, 0xF8, 0x40, 0x6F, 0xA2, 0xB3, 0x27, 0x69, 0x37, 0xDB, 0x5A, 0x47, 0x01, 0x78, 0x9C, 0xEF, 0x15, + 0x28, 0x6A, 0x1C, 0x27, 0xAB, 0x9A, 0x5A, 0xE6, 0x6E, 0xE5, 0x36, 0x4A, 0x6B, 0x65, 0x92, 0x36, 0xB5, 0x99, 0x39, 0xFC, + 0x3E, 0xA1, 0xF5, 0x7B, 0xC1, 0x68, 0x32, 0x57, 0x4B, 0x0B, 0xAB, 0x3C, 0x51, 0x42, 0xDB, 0xE3, 0xB6, 0x27, 0xDC, 0x30, + 0xA0, 0xE8, 0xB2, 0xEC, 0x0E, 0xAA, 0x2C, 0xCF, 0x9C, 0x45, 0xD3, 0xEB, 0x85, 0x84, 0xF2, 0xA6, 0x38, 0x14, 0xEF, 0xC5, + 0x13, 0xA5, 0xAA, 0xC0, 0xEE, 0x58, 0x42, 0xD3, 0xE7, 0x9D, 0xF8, 0x5A, 0x3F, 0xEC, 0x34, 0x82, 0x69, 0x41, 0x26, 0x90, + 0x3D, 0x36, 0x28, 0x37, 0x0C, 0x2D, 0x50, 0xA1, 0x90, 0x2B, 0xA3, 0x7A, 0x70, 0x6F, 0x82, 0x59, 0xA6, 0xE2, 0x3B, 0x46, + 0x03, 0xCC, 0xC3, 0x0E, 0xAD, 0x25, 0x89, 0x63, 0x59, 0x51, 0x33, 0xEA, 0xF0, 0x73, 0x35, 0x77, 0xCB, 0x8B, 0xEF, 0x9F, + 0xD9, 0xA9, 0x41, 0x88, 0xA1, 0x72, 0xFD, 0xCA, 0x5F, 0xF1, 0xDB, 0x86, 0x5F, 0xBB, 0xFD, 0xB6, 0x91, 0x4F, 0xB6, 0x4A, + 0x04, 0x9D, 0xA1, 0x46, 0x34, 0x5F, 0xEC, 0x6B, 0x08, 0x65, 0x2C, 0x94, 0x31, 0x44, 0xA9, 0x5A, 0x03, 0x2C, 0x7C, 0x33, + 0x80, 0xF9, 0x12, 0x8B, 0x58, 0xE3, 0x09, 0x14, 0x88, 0xB8, 0xCA, 0xA1, 0xE0, 0x27, 0x24, 0xE6, 0xA9, 0x9C, 0xBF, 0xA8, + 0xBD, 0x66, 0x38, 0x7F, 0xD5, 0x4E, 0xC5, 0xCD, 0x6A, 0x75, 0x3C, 0x33, 0xB7, 0xAA, 0x1C, 0x32, 0x00, 0x35, 0xA3, 0xA4, + 0x4B, 0xBD, 0x62, 0x80, 0x06, 0x9F, 0x8F, 0x95, 0x18, 0x5F, 0x52, 0xFE, 0x84, 0x1E, 0x36, 0xA0, 0xC8, 0xDB, 0x2A, 0x22, + 0x3B, 0x2A, 0xC4, 0x09, 0x9E, 0xFA, 0xE4, 0x47, 0xA8, 0x41, 0x65, 0xC5, 0xB4, 0xAD, 0x0C, 0x9C, 0x01, 0x7B, 0x8D, 0xFA, + 0x16, 0x57, 0xA8, 0xE2, 0xB3, 0x38, 0x8F, 0xD6, 0xB4, 0xC7, 0x43, 0x46, 0x8F, 0xDA, 0x29, 0x09, 0x94, 0xBF, 0x35, 0x0E, + 0x57, 0xF1, 0x5E, 0x06, 0x99, 0x47, 0xA3, 0xEA, 0x28, 0xC3, 0xBE, 0xBF, 0x17, 0xA9, 0xD0, 0xF8, 0xEC, 0x13, 0x2E, 0x9C, + 0x39, 0x4C, 0xBE, 0x85, 0x51, 0xC2, 0xAF, 0x5E, 0x69, 0xBB, 0x80, 0xBE, 0x2E, 0x9E, 0x4B, 0x1C, 0x80, 0xB2, 0xA3, 0xCD, + 0x13, 0xDE, 0xB3, 0xAD, 0xEF, 0x57, 0xA8, 0x68, 0xD5, 0x90, 0x3A, 0x77, 0x91, 0x46, 0xEB, 0xC4, 0x4A, 0x66, 0xFD, 0xD3, + 0xFC, 0x5B, 0xC6, 0xB8, 0x4C, 0x5B, 0x86, 0x79, 0x6C, 0xB1, 0x64, 0x0F, 0xDD, 0x21, 0x36, 0x6B, 0x50, 0x61, 0x16, 0x2A, + 0xB1, 0x3C, 0x15, 0x21, 0x1B, 0x16, 0xA8, 0x48, 0x7B, 0xB1, 0xF8, 0x4B, 0xFF, 0x11, 0x19, 0xCC, 0x47, 0xEF, 0x78, 0xAF, + 0xFE, 0x33, 0x8D, 0xFA, 0x80, 0x73, 0x8F, 0xC8, 0x07, 0xF1, 0xEE, 0x28, 0x2B, 0x12, 0x3E, 0x37, 0xD4, 0x7C, 0x58, 0xFD, + 0x3F, 0xBB, 0xC8, 0x4B, 0x03, 0xDC, 0xC0, 0xF9, 0x2D, 0xFD, 0x80, 0x81, 0x1C, 0xA8, 0x06, 0x95, 0xBF, 0x1D, 0x06, 0xC4, + 0x56, 0x80, 0x55, 0x11, 0xB8, 0x6D, 0xCC, 0x95, 0x19, 0x21, 0xD3, 0xB4, 0x4F, 0x89, 0x46, 0xB5, 0x5B, 0x82, 0x13, 0x05, + 0x6B, 0x31, 0x55, 0xA0, 0xBE, 0x01, 0xD1, 0xA4, 0xBF, 0xC9, 0x45, 0x84, 0xDE, 0x89, 0x6F, 0xB0, 0x80, 0x43, 0x4D, 0x10, + 0xDA, 0x4B, 0x21, 0xDF, 0x6D, 0x4E, 0x47, 0xB4, 0xD9, 0x00, 0x04, 0xC1, 0x08, 0x26, 0x94, 0x46, 0x08, 0xF9, 0xD6, 0xC0, + 0x60, 0x44, 0x10, 0xE0, 0xE7, 0x7F, 0x48, 0xF1, 0x03, 0xAF, 0x73, 0x24, 0xAF, 0x2C, 0x16, 0xA1, 0x08, 0x85, 0x23, 0xB6, + 0xF2, 0x7A, 0x05, 0xC0, 0x88, 0x26, 0xDB, 0xEB, 0xB3, 0x96, 0xC5, 0xC4, 0xE4, 0xEC, 0x01, 0x03, 0x2D, 0xEB, 0xC5, 0xF4, + 0xAB, 0x25, 0xC8, 0x2B, 0xF2, 0x50, 0x59, 0xF4, 0xCD, 0xEF, 0x19, 0xF5, 0xD6, 0xFA, 0x26, 0xD7, 0x85, 0x35, 0x56, 0x28, + 0x12, 0x08, 0x04, 0x99, 0xA3, 0x2B, 0xC6, 0xA9, 0x37, 0x83, 0x5F, 0x31, 0xE2, 0x1A, 0x5E, 0x1C, 0x51, 0x43, 0xCA, 0xC8, + 0x4C, 0x0B, 0x4E, 0x39, 0x73, 0x0A, 0x65, 0xA0, 0x77, 0xA7, 0x45, 0x18, 0x92, 0x48, 0x2D, 0x99, 0xFE, 0xE5, 0x47, 0x88, + 0xB6, 0x81, 0x35, 0xB0, 0x8F, 0x89, 0x5F, 0x3C, 0x93, 0x09, 0xDF, 0x6D, 0x68, 0x94, 0x4F, 0x98, 0xF7, 0x48, 0x96, 0xF9, + 0x42, 0x0C, 0xDA, 0x49, 0xEC, 0x79, 0x1C, 0xBC, 0x27, 0xA7, 0xFA, 0x0E, 0xA3, 0x60, 0x9E, 0xD9, 0x64, 0x6F, 0x4E, 0xA1, + 0xE4, 0x6C, 0xDE, 0xDD, 0x07, 0xA6, 0x65, 0x3E, 0xFA, 0x98, 0x17, 0x4C, 0xE1, 0x66, 0xC1, 0x56, 0xB0, 0x2A, 0xD5, 0x9C, + 0x86, 0x4C, 0xEB, 0x13, 0x5B, 0x63, 0x9F, 0x48, 0xA5, 0x6C, 0xF5, 0xFC, 0x19, 0xFE, 0x85, 0x89, 0x80, 0xE5, 0x58, 0xF9, + 0xD5, 0xA3, 0x62, 0x28, 0x21, 0x50, 0x5A, 0x85, 0x12, 0x33, 0x2A, 0x04, 0x66, 0xD2, 0x4A, 0x51, 0x7A, 0x52, 0x19, 0x63, + 0xA5, 0x9C, 0xD4, 0x30, 0x7F, 0xDA, 0xCC, 0xAF, 0x4F, 0x13, 0x48, 0xC0, 0x1C, 0xBA, 0x21, 0x5B, 0xC3, 0x1B, 0x01, 0x21, + 0xBA, 0xD9, 0xDB, 0xE1, 0xA0, 0x86, 0x41, 0xB4, 0xDE, 0x11, 0x5F, 0xAE, 0x4A, 0x77, 0x0F, 0x35, 0x93, 0x53, 0xD9, 0x41, + 0xE7, 0x31, 0x83, 0x60, 0x94, 0xBA, 0x14, 0xC0, 0x06, 0x57, 0xAC, 0xA6, 0xC5, 0x5A, 0xA5, 0x4E, 0xD4, 0x21, 0x61, 0xE8, + 0x74, 0x7E, 0xD6, 0xC5, 0x21, 0x75, 0xD9, 0xA7, 0x15, 0xBC, 0xED, 0x5F, 0xDD, 0x9E, 0xE2, 0xF8, 0x31, 0xCA, 0x51, 0x34, + 0xCD, 0xDF, 0x05, 0x44, 0xED, 0x3E, 0xE0, 0xCE, 0xCD, 0x3D, 0xD5, 0x5A, 0xFA, 0x54, 0x99, 0xD1, 0xA9, 0x35, 0x3C, 0xB5, + 0xF7, 0x9A, 0x8E, 0x2D, 0xD4, 0x0C, 0xE7, 0x0A, 0xF5, 0xC4, 0xC6, 0x18, 0x31, 0x7B, 0x56, 0xAD, 0x76, 0xD3, 0x1C, 0xDB, + 0x4E, 0x57, 0x14, 0x09, 0x56, 0x1B, 0xA9, 0x29, 0x2F, 0x7B, 0xDE, 0x3C, 0x35, 0x1B, 0x18, 0x0D, 0xE1, 0xEA, 0x54, 0xC9, + 0x1C, 0x99, 0x61, 0xEB, 0x43, 0x99, 0xC3, 0x18, 0xDF, 0x1A, 0xA3, 0xDA, 0xC6, 0x55, 0x49, 0xD9, 0x95, 0xD1, 0x55, 0x69, + 0xA8, 0x59, 0x4B, 0x68, 0x92, 0x19, 0x1A, 0xBA, 0xFD, 0xF6, 0x4B, 0x18, 0xD7, 0xD1, 0x02, 0x6D, 0x04, 0x7F, 0x16, 0xBC, + 0x86, 0x37, 0x8F, 0xEB, 0xEE, 0x38, 0x98, 0x68, 0x30, 0x39, 0x90, 0x2D, 0x44, 0xF6, 0x71, 0xAC, 0x33, 0x34, 0x5E, 0x07, + 0x94, 0xA2, 0x4E, 0x8F, 0x5D, 0xF4, 0x45, 0x69, 0x80, 0x3C, 0x06, 0x49, 0x89, 0x5A, 0x75, 0xE9, 0xEA, 0x5E, 0xDF, 0xE8, + 0x85, 0x81, 0x9F, 0xFD, 0x8D, 0x3F, 0x4B, 0x20, 0x44, 0x7E, 0xA0, 0x06, 0x16, 0x59, 0x6E, 0x9D, 0xB3, 0xD2, 0x75, 0x69, + 0x89, 0x36, 0xA0, 0x87, 0x1A, 0xC3, 0x84, 0x40, 0x2C, 0x63, 0xF4, 0xD3, 0x3B, 0x4A, 0x72, 0x10, 0x97, 0x8B, 0xBC, 0x97, + 0x5B, 0x41, 0xC3, 0x75, 0xAC, 0xA2, 0xFC, 0xB7, 0x7B, 0x82, 0x1A, 0x73, 0x04, 0x9D, 0x7F, 0xF2, 0xDF, 0xC1, 0xCE, 0x50, + 0xA6, 0x11, 0xB7, 0x86, 0xFA, 0x81, 0xA9, 0xEE, 0x8D, 0x2E, 0x6D, 0x92, 0xBB, 0x81, 0x5E, 0x49, 0xA4, 0xC7, 0xF7, 0xE6, + 0xBA, 0xC3, 0xB4, 0x42, 0x06, 0x84, 0xD7, 0xC1, 0xFD, 0xE7, 0x3E, 0x73, 0x64, 0xE7, 0x30, 0xE2, 0xBB, 0xEA, 0x68, 0xF7, + 0x29, 0xE6, 0x38, 0x30, 0xEC, 0x3E, 0x36, 0x37, 0x69, 0x86, 0x03, 0xB4, 0xF6, 0x5A, 0x61, 0x43, 0x86, 0x86, 0x21, 0xD6, + 0x98, 0xBD, 0x35, 0xB7, 0x8D, 0x6C, 0xC9, 0x98, 0x55, 0xEB, 0xBD, 0x03, 0xC6, 0x0F, 0xE9, 0xD3, 0xCB, 0xF6, 0xFD, 0x16, + 0xEA, 0xAE, 0x91, 0x15, 0x24, 0x8B, 0x73, 0x4D, 0xC6, 0x4B, 0x7C, 0xDF, 0x13, 0x89, 0x4B, 0x59, 0x6A, 0x41, 0xE6, 0x8B, + 0x72, 0x03, 0x68, 0xE9, 0x3F, 0x7D, 0xFA, 0x1B, 0x17, 0xEB, 0x19, 0x9E, 0x95, 0xAA, 0x6E, 0xBF, 0x11, 0xCA, 0x2B, 0x1A, + 0x65, 0x49, 0xE7, 0x9A, 0xD0, 0xA9, 0x13, 0xA1, 0xCF, 0x4A, 0x6D, 0xFE, 0x97, 0x89, 0xFD, 0x68, 0xE3, 0xE5, 0x75, 0xEA, + 0x97, 0x49, 0xD7, 0x44, 0x07, 0xA8, 0x6F, 0x9A, 0x96, 0x41, 0x68, 0x1A, 0x4F, 0x0C, 0xD8, 0xB5, 0xEB, 0xA0, 0x6C, 0x1B, + 0x27, 0x27, 0x32, 0xEF, 0x01, 0xE6, 0x60, 0x0A, 0x4E, 0x05, 0xD4, 0x42, 0x19, 0x0F, 0x65, 0x03, 0x36, 0x74, 0x3F, 0x86, + 0xB9, 0x56, 0xB7, 0xEE, 0xA0, 0x24, 0xDB, 0x30, 0x1F, 0xA3, 0xAD, 0x9E, 0xA1, 0x77, 0x7B, 0x93, 0x38, 0x15, 0x61, 0x0B, + 0xCF, 0x8C, 0x38, 0x9D, 0x3E, 0x50, 0xE4, 0x06, 0xB2, 0x36, 0x1E, 0x0D, 0x34, 0xFC, 0xE0, 0xD6, 0x85, 0xCF, 0x62, 0x73, + 0x78, 0xB3, 0x60, 0x53, 0xC7, 0x20, 0x7E, 0xD2, 0x1D, 0x3A, 0x7E, 0xAD, 0x4F, 0x2A, 0xF4, 0x12, 0x59, 0xBA, 0xF8, 0x5F, + 0x06, 0xD9, 0xE8, 0xB3, 0x51, 0xB0, 0x91, 0xE1, 0x1B, 0x47, 0xF1, 0x83, 0xB2, 0x73, 0x07, 0x92, 0x82, 0x90, 0x6B, 0xD3, + 0xBC, 0xF1, 0xA9, 0x17, 0xF9, 0xC2, 0x6D, 0x93, 0x9B, 0x90, 0xFD, 0x36, 0xA0, 0xDE, 0x2D, 0x93, 0xD1, 0xB2, 0x24, 0x47, + 0x08, 0xB6, 0xDA, 0xDA, 0x05, 0x40, 0xE7, 0xD9, 0xE8, 0x7B, 0x24, 0x54, 0xC8, 0xF6, 0x2C, 0xD2, 0x6B, 0x97, 0x68, 0xE9, + 0x1D, 0xF4, 0x42, 0x56, 0x06, 0x82, 0x9D, 0x72, 0x3D, 0x6D, 0xA1, 0x66, 0x88, 0xF5, 0x25, 0x56, 0xE7, 0xBE, 0xA5, 0x98, + 0x68, 0x09, 0xAC, 0x43, 0x53, 0xED, 0xA9, 0x76, 0xA7, 0x7C, 0x32, 0x28, 0x93, 0x4C, 0x65, 0x72, 0x0E, 0x94, 0xF5, 0xF2, + 0x0B, 0xD4, 0x9B, 0xB7, 0xD3, 0xC5, 0x26, 0x0F, 0x7B, 0xB3, 0xCD, 0x8D, 0xCD, 0x27, 0x26, 0xAA, 0x5E, 0xDB, 0x55, 0xF1, + 0x46, 0x96, 0x2E, 0x3B, 0x17, 0xD9, 0xB2, 0x1F, 0x4B, 0xF8, 0x6A, 0x1B, 0x53, 0x9A, 0xF4, 0xD0, 0x51, 0x26, 0x67, 0xBA, + 0x9F, 0xF8, 0xA7, 0xAB, 0xE2, 0xBA, 0x33, 0x0A, 0xD2, 0x99, 0xA8, 0xA9, 0x9A, 0x9B, 0x6B, 0x4B, 0x9E, 0xF9, 0x7B, 0xAE, + 0x82, 0x1B, 0x3B, 0x1F, 0xD7, 0x9B, 0xE2, 0x6F, 0x00, 0x9E, 0x19, 0xEA, 0xBC, 0xDB, 0x6C, 0xC5, 0x4F, 0xAC, 0x66, 0x13, + 0x81, 0xBD, 0xBA, 0x2F, 0x40, 0xF6, 0xB4, 0xC3, 0x39, 0x3F, 0x66, 0xEB, 0x86, 0x9E, 0x01, 0xDA, 0xFD, 0xF5, 0x67, 0xDE, + 0xAC, 0xFC, 0x98, 0xAD, 0x41, 0xD2, 0x49, 0x4F, 0x8F, 0xA9, 0x28, 0x10, 0xDA, 0x05, 0xBB, 0x7E, 0xAD, 0x9F, 0x5C, 0xA5, + 0x3E, 0xB2, 0x0D, 0xD5, 0xAF, 0x2B, 0x43, 0x80, 0x5C, 0xBE, 0xA7, 0x2C, 0xE1, 0xAF, 0x93, 0x38, 0x58, 0xB1, 0xD0, 0xB1, + 0x23, 0xBF, 0xD2, 0x77, 0xA1, 0xE9, 0x1F, 0xEF, 0xEA, 0x70, 0x8E, 0x39, 0x70, 0x30, 0x1C, 0x25, 0x47, 0x03, 0x25, 0x44, + 0xE7, 0x68, 0x96, 0xF2, 0xA2, 0xA9, 0xBF, 0x3D, 0xB3, 0x62, 0xD1, 0x25, 0xAA, 0xB5, 0xB1, 0xAF, 0xD1, 0xE0, 0x77, 0x29, + 0x87, 0x41, 0x87, 0x38, 0xB2, 0xF4, 0x63, 0x43, 0x62, 0x26, 0x8D, 0x5A, 0xB0, 0x16, 0xFA, 0x87, 0xC0, 0x54, 0x6C, 0xD7, + 0x34, 0x2E, 0x6E, 0xBC, 0xE5, 0x5F, 0x79, 0x75, 0x78, 0x4C, 0x11, 0x47, 0x64, 0xF5, 0xB6, 0x52, 0xF2, 0xA6, 0x5D, 0x92, + 0x70, 0xE7, 0xE6, 0x15, 0xF0, 0x7E, 0x49, 0x55, 0xE5, 0x56, 0x91, 0xB5, 0x7C, 0x57, 0x13, 0x07, 0x40, 0x45, 0x3C, 0xE7, + 0x7C, 0x6F, 0x89, 0x35, 0x9D, 0x01, 0xE9, 0xA6, 0x1F, 0x2A, 0xE1, 0xF3, 0xE1, 0xB7, 0x7A, 0x03, 0x7F, 0x68, 0x78, 0x7A, + 0xAB, 0x6D, 0x42, 0x89, 0x70, 0x25, 0x6A, 0xAC, 0x4E, 0xC7, 0x8A, 0xB4, 0xE5, 0xE1, 0x19, 0xF8, 0x0D, 0xA9, 0xF4, 0xBC, + 0xF0, 0x98, 0xE5, 0x7F, 0xA0, 0x4A, 0x6F, 0x38, 0xD9, 0x2B, 0x7B, 0x18, 0xF8, 0xA7, 0xFD, 0x30, 0x34, 0x27, 0x2B, 0xD7, + 0x64, 0x47, 0x22, 0x4D, 0x96, 0x1D, 0x9E, 0x69, 0xB9, 0xA3, 0x27, 0x8F, 0xA9, 0x23, 0xFC, 0x47, 0xA8, 0x4F, 0x5B, 0xAC, + 0x38, 0x92, 0x12, 0x41, 0xAB, 0xA3, 0xBF, 0x3E, 0x65, 0x0C, 0x2A, 0x2F, 0xA3, 0x96, 0x8F, 0x74, 0xF7, 0x09, 0x13, 0xC1, + 0xAC, 0x16, 0xF7, 0x16, 0x1D, 0x0F, 0x03, 0x62, 0x4D, 0x64, 0x6E, 0x9E, 0xF7, 0xE6, 0x88, 0x0F, 0xCA, 0x83, 0x38, 0xB6, + 0x69, 0x32, 0x35, 0x08, 0x21, 0x6D, 0xAB, 0x85, 0x82, 0x23, 0x0B, 0xBF, 0xB8, 0x4F, 0x6F, 0x2E, 0xFD, 0xD7, 0xA5, 0x91, + 0x57, 0xE2, 0xDF, 0x9F, 0xDD, 0x46, 0x01, 0x04, 0x26, 0x9F, 0x17, 0xBF, 0xBE, 0xB9, 0x10, 0x88, 0xA8, 0xE1, 0xAA, 0x99, + 0x11, 0x74, 0x2C, 0x24, 0xA3, 0x80, 0x4E, 0x90, 0xD3, 0x58, 0x62, 0x10, 0x8A, 0x20, 0x5C, 0x25, 0x90, 0xAE, 0x3F, 0x63, + 0x0C, 0x1D, 0x19, 0x65, 0xAE, 0x70, 0x86, 0xD3, 0x0B, 0xA3, 0xF7, 0xA7, 0xF1, 0x10, 0x73, 0x60, 0x02, 0x63, 0x8E, 0x11, + 0xBF, 0x92, 0x63, 0x89, 0xE7, 0x11, 0x02, 0x55, 0xA1, 0xAE, 0xFC, 0x28, 0x78, 0x5B, 0x96, 0x14, 0x79, 0x8B, 0x6A, 0x30, + 0xFE, 0x5B, 0xE0, 0xB8, 0x11, 0xEB, 0x87, 0x17, 0xE9, 0x3C, 0xB7, 0xA7, 0x19, 0x9E, 0xDC, 0xE1, 0x45, 0xF8, 0xE6, 0x44, + 0xA7, 0xDA, 0x85, 0x39, 0x1D, 0xBB, 0xFB, 0x60, 0xF1, 0x94, 0x77, 0x92, 0x41, 0x5F, 0xC3, 0xD1, 0x19, 0x32, 0x05, 0xC0, + 0x4A, 0x3E, 0xB5, 0xDD, 0x53, 0xB6, 0x17, 0xC0, 0xC5, 0xD5, 0x79, 0x97, 0xD0, 0x37, 0x38, 0xB0, 0x2E, 0x5A, 0xBC, 0x6E, + 0x94, 0x37, 0x6C, 0xCA, 0x9F, 0x3D, 0x8C, 0xD5, 0x59, 0xF8, 0x76, 0x95, 0xC9, 0xB8, 0x8B, 0xEF, 0x4D, 0x7B, 0x4E, 0xCB, + 0x15, 0x1B, 0x29, 0x85, 0x5D, 0x82, 0x14, 0xFA, 0x94, 0xB1, 0xA1, 0xB1, 0xC0, 0x3E, 0x2F, 0x56, 0x67, 0xFC, 0x2C, 0x1F, + 0x85, 0x1A, 0xAB, 0xA2, 0x2D, 0x84, 0x4B, 0xA8, 0x58, 0x34, 0x5D, 0x6C, 0xE8, 0x1A, 0x60, 0x99, 0x18, 0x60, 0x44, 0x3B, + 0x7D, 0x07, 0xF5, 0x3F, 0xBE, 0xB1, 0x70, 0x4C, 0xC9, 0xD8, 0xE2, 0xA0, 0x93, 0xBD, 0x17, 0xC6, 0xCE, 0xEB, 0x0E, 0x5D, + 0xAE, 0x90, 0xA3, 0x0B, 0x41, 0x46, 0xF8, 0x1E, 0x43, 0xD2, 0x00, 0xAF, 0x55, 0x72, 0x95, 0xD6, 0x51, 0x5A, 0x0E, 0x65, + 0x4D, 0xD3, 0xF1, 0x3D, 0x59, 0xFB, 0xB0, 0x49, 0x5C, 0xB2, 0x1D, 0x0D, 0x0F, 0xC0, 0x9E, 0x9F, 0x14, 0xF2, 0x4E, 0x8F, + 0x10, 0x9E, 0xB5, 0xE2, 0xB9, 0x0D, 0xA5, 0x75, 0x6C, 0x26, 0x49, 0x51, 0x38, 0x49, 0xA8, 0xB2, 0x52, 0x82, 0x71, 0x52, + 0xA0, 0x3E, 0x57, 0x32, 0x13, 0x63, 0x9B, 0x0F, 0x99, 0xC2, 0x83, 0x46, 0xD5, 0xF7, 0x5F, 0x2E, 0x6F, 0x13, 0xA1, 0xC7, + 0x98, 0x59, 0x11, 0xA9, 0xC7, 0x22, 0xB0, 0xA3, 0x96, 0x4E, 0x5B, 0x12, 0x9D, 0xC1, 0x29, 0xE8, 0x77, 0xCA, 0x1F, 0x0B, + 0xBD, 0x63, 0xF1, 0x3B, 0x2D, 0x32, 0x98, 0xAA, 0x48, 0xCB, 0x9E, 0xF2, 0xFF, 0x07, 0x08, 0x94, 0x40, 0x2F, 0x80, 0x04, + 0x65, 0x90, 0x38, 0x4F, 0xA6, 0xE9, 0xBA, 0x0F, 0xFC, 0x26, 0x82, 0x00, 0xC5, 0x11, 0x80, 0x52, 0xB6, 0x4A, 0x31, 0x5F, + 0xDC, 0x80, 0x6A, 0xB4, 0xFC, 0x0B, 0x46, 0x8B, 0x52, 0x3B, 0x63, 0xE5, 0x78, 0x4F, 0x0F, 0x8F, 0xB4, 0x55, 0xD7, 0xF2, + 0xC6, 0x08, 0x25, 0x91, 0x45, 0xC3, 0xE8, 0x84, 0x82, 0xE1, 0x64, 0xFA, 0x6D, 0x71, 0x24, 0x7D, 0x68, 0xCE, 0x21, 0x59, + 0x3C, 0xC3, 0x05, 0x17, 0x5A, 0x39, 0x15, 0xFA, 0x51, 0xCB, 0x15, 0x6E, 0x7A, 0xA2, 0x58, 0x12, 0xA4, 0xB8, 0x0D, 0x07, + 0x79, 0x87, 0x3B, 0x0F, 0x0C, 0xBA, 0xB9, 0xFB, 0xBD, 0x5A, 0xB3, 0x3A, 0xF0, 0xA6, 0x58, 0x30, 0xA4, 0xAB, 0x6D, 0xEB, + 0x6F, 0x72, 0xBD, 0x6C, 0xE9, 0xAD, 0x59, 0x3B, 0xCE, 0x8B, 0x85, 0x9F, 0x1F, 0x7F, 0x9A, 0x2C, 0xF1, 0x8F, 0x36, 0x43, + 0x0A, 0xA8, 0xD2, 0x08, 0xC3, 0xAE, 0x59, 0xA3, 0xFD, 0xEA, 0x92, 0x38, 0xE4, 0x57, 0xA4, 0xA1, 0xF6, 0x0E, 0x7E, 0x09, + 0x0C, 0xB9, 0x68, 0x0D, 0x3B, 0x81, 0xDD, 0x43, 0x6D, 0x0E, 0x4A, 0x3C, 0xF8, 0x24, 0x8E, 0x8B, 0xCA, 0xB5, 0x85, 0xC4, + 0x7D, 0x41, 0x83, 0x4B, 0xBC, 0x5D, 0xA1, 0x8E, 0x68, 0x02, 0x03, 0x69, 0x24, 0x8C, 0x9D, 0xBA, 0xDE, 0xAF, 0x93, 0xAE, + 0x22, 0xC1, 0x10, 0x64, 0xBB, 0x1D, 0x0A, 0x9B, 0x0D, 0x41, 0x73, 0x40, 0xF9, 0xEB, 0xEC, 0x16, 0xC6, 0x0C, 0x3B, 0xE6, + 0xB5, 0x37, 0x24, 0x3A, 0xEA, 0x2C, 0xC2, 0x17, 0x46, 0xD7, 0x02, 0x07, 0xE6, 0x60, 0xF5, 0x15, 0x25, 0x1F, 0x6D, 0xA7, + 0x0D, 0xA3, 0x16, 0xD1, 0x3E, 0xDB, 0x55, 0xB4, 0x5C, 0x9C, 0x8D, 0xD7, 0xE4, 0xF1, 0x5F, 0xF9, 0x10, 0x5A, 0x7D, 0xD6, + 0x1A, 0x57, 0xAF, 0x85, 0xF0, 0x9C, 0xDA, 0x77, 0x75, 0xE1, 0x20, 0xA5, 0xB8, 0xDC, 0xCA, 0xD3, 0xFB, 0x52, 0x12, 0x0E, + 0x14, 0x17, 0x5D, 0x2D, 0xDE, 0xD6, 0x42, 0x22, 0xAD, 0x96, 0x75, 0x72, 0x2C, 0x60, 0x63, 0xBC, 0xC6, 0x49, 0x1E, 0xB4, + 0xD4, 0x3C, 0xF5, 0x82, 0x2E, 0xBA, 0xBF, 0xA7, 0xF2, 0xD3, 0x53, 0x0F, 0x00, 0x8C, 0xA7, 0xFB, 0x44, 0x1A, 0x82, 0x9C, + 0x68, 0x21, 0xC5, 0x97, 0xF3, 0xD2, 0xE6, 0x1B, 0x4F, 0x1F, 0x64, 0x8A, 0xC3, 0xC7, 0x16, 0x38, 0xEC, 0xD0, 0xCE, 0x0A, + 0x4F, 0x1C, 0x51, 0x6A, 0x25, 0x96, 0x11, 0xE2, 0x1C, 0x29, 0x06, 0x49, 0x11, 0xBC, 0xA6, 0xAE, 0x9A, 0xE2, 0xD6, 0x87, + 0xAA, 0xD8, 0x99, 0xB3, 0x32, 0x65, 0x30, 0x2F, 0xEA, 0x55, 0x6D, 0xB2, 0x15, 0xB9, 0x9B, 0x6B, 0x89, 0x94, 0x6F, 0x1A, + 0xAD, 0xF9, 0x07, 0x48, 0xCF, 0x7F, 0xDB, 0xAB, 0xCE, 0xDD, 0xA5, 0xAC, 0x46, 0x46, 0xB2, 0x3F, 0x9D, 0xAC, 0x7E, 0xEF, + 0xF3, 0x21, 0xA5, 0x9D, 0x4A, 0x5D, 0x6C, 0xD3, 0x8A, 0x86, 0x4E, 0xAC, 0x5D, 0x09, 0x00, 0x4B, 0x84, 0x5E, 0x3E, 0x27, + 0x51, 0x62, 0x3E, 0x5A, 0x09, 0x9D, 0xD5, 0xFF, 0x1C, 0x11, 0xDA, 0x99, 0x05, 0x1D, 0xCF, 0x10, 0x17, 0xCF, 0x2D, 0x3D, + 0x9C, 0x3D, 0x91, 0xD8, 0xB9, 0x9D, 0x01, 0x5E, 0x58, 0x82, 0x4B, 0x9D, 0x04, 0x91, 0x59, 0x92, 0xA5, 0xB6, 0xBE, 0x58, + 0x78, 0x2D, 0x5C, 0x33, 0x24, 0x0A, 0x50, 0xB4, 0x0F, 0xF5, 0x70, 0x98, 0xA4, 0x88, 0xB2, 0xA4, 0xFB, 0x8E, 0x7D, 0x4A, + 0xE6, 0x51, 0x1F, 0xB7, 0x85, 0x82, 0x3A, 0x71, 0x00, 0xAD, 0x93, 0x99, 0x7B, 0x66, 0x48, 0xA7, 0x67, 0x59, 0x44, 0x1E, + 0xA2, 0x20, 0x29, 0x82, 0x22, 0x0B, 0x2D, 0x6B, 0x32, 0x46, 0x26, 0xD7, 0x20, 0xEC, 0x3E, 0x9D, 0x5E, 0xCE, 0x8F, 0x7A, + 0x3C, 0xB1, 0x3F, 0x60, 0x9F, 0xA9, 0x90, 0xE4, 0x8E, 0x06, 0x68, 0x9B, 0xDF, 0x7F, 0xEB, 0xF9, 0xDF, 0x56, 0xAA, 0x54, + 0xE4, 0x3E, 0x4E, 0xC0, 0x45, 0x07, 0x99, 0x12, 0x85, 0xBA, 0x12, 0xC5, 0xDE, 0x20, 0xA7, 0x89, 0x6D, 0xAB, 0x95, 0x9F, + 0xA1, 0x30, 0xB5, 0x03, 0x0C, 0x99, 0xA5, 0x22, 0xB5, 0x81, 0x6A, 0x12, 0x36, 0xD1, 0x42, 0x8E, 0x4E, 0xEA, 0x49, 0x4B, + 0x98, 0x92, 0x82, 0x2B, 0x7A, 0xA5, 0x3D, 0xEE, 0x1E, 0x92, 0x5F, 0x17, 0x7C, 0x9D, 0xC3, 0xBE, 0xE9, 0xC5, 0x12, 0x00, + 0x6A, 0x40, 0x26, 0x63, 0xDB, 0xD6, 0xDA, 0x18, 0x49, 0x52, 0x3E, 0x7C, 0x1D, 0xC2, 0x49, 0x99, 0xE1, 0xEB, 0xB3, 0xFD, + 0x67, 0x25, 0x06, 0xAD, 0xBB, 0xDA, 0x45, 0x5D, 0x58, 0xEC, 0xCB, 0xC0, 0xE7, 0x49, 0x30, 0x6D, 0x19, 0xAD, 0xFA, 0x5F, + 0xEA, 0x0B, 0x4D, 0x38, 0xB2, 0x78, 0x7B, 0x3B, 0x30, 0x85, 0x79, 0x3C, 0x9A, 0x83, 0x57, 0x6A, 0x66, 0xC7, 0x18, 0x23, + 0xA7, 0x10, 0xC8, 0xA9, 0x31, 0x6D, 0xEA, 0xCF, 0xB8, 0x6C, 0x9A, 0x6F, 0xB4, 0xC6, 0xE4, 0xAC, 0x30, 0x62, 0x63, 0xDB, + 0x06, 0x06, 0xBB, 0xC5, 0x3F, 0xA7, 0x96, 0x58, 0xA8, 0x0C, 0x7A, 0x13, 0x4F, 0x2F, 0x15, 0xF5, 0x3A, 0x63, 0xF3, 0xA7, + 0x37, 0x22, 0x9E, 0x48, 0xB5, 0x0D, 0x5B, 0x4F, 0x2F, 0x60, 0x57, 0xF3, 0x4C, 0x19, 0xBA, 0xA8, 0x11, 0x70, 0x1C, 0xB4, + 0x89, 0x1A, 0xCE, 0x29, 0x18, 0xF3, 0x34, 0x6F, 0xC8, 0x20, 0x90, 0xF6, 0x79, 0xF0, 0xDC, 0x69, 0x1A, 0x13, 0xC6, 0x38, + 0x19, 0xF2, 0x43, 0xF2, 0x94, 0xB3, 0x99, 0xE7, 0xF8, 0x03, 0x0B, 0x60, 0xC1, 0xD9, 0x55, 0x21, 0x3C, 0x8D, 0xD9, 0x6F, + 0xC2, 0xC9, 0x91, 0x3E, 0x95, 0xBE, 0xD6, 0xC7, 0x1C, 0x58, 0x5D, 0x31, 0x3B, 0x1F, 0x06, 0xCD, 0x23, 0x36, 0xBA, 0xC2, + 0x51, 0xC0, 0x94, 0x65, 0xCB, 0x5E, 0x74, 0x96, 0x10, 0x80, 0x8C, 0xCD, 0xA9, 0x7B, 0x95, 0x7E, 0x96, 0xEA, 0xA3, 0x74, + 0x18, 0x3C, 0xBA, 0x38, 0x10, 0x71, 0x85, 0x51, 0x21, 0xA4, 0x16, 0x36, 0x3E, 0x77, 0xD6, 0xDA, 0x94, 0xDB, 0xAB, 0xE2, + 0xD6, 0x18, 0x73, 0x7D, 0x7D, 0xCA, 0xCC, 0xB3, 0x4C, 0x2C, 0x63, 0xED, 0xE5, 0x35, 0xA4, 0x8F, 0x92, 0x73, 0xC6, 0x51, + 0x46, 0x5A, 0xF8, 0x3D, 0xD3, 0xFB, 0x8B, 0xEF, 0x81, 0x12, 0x56, 0x3C, 0x7C, 0xF3, 0x3A, 0x20, 0xC0, 0xD8, 0x7C, 0x11, + 0x98, 0x7B, 0xB2, 0xCB, 0x6A, 0xFF, 0x5E, 0xC4, 0x86, 0xF2, 0x48, 0xC8, 0xA9, 0x5A, 0xD9, 0x30, 0x47, 0x3C, 0x71, 0x68, + 0xA8, 0xA5, 0x72, 0x9C, 0x9A, 0x38, 0x17, 0x09, 0x24, 0xB6, 0x4B, 0x63, 0x3B, 0xFC, 0x90, 0xA9, 0x35, 0x54, 0x7E, 0x8C, + 0x9B, 0x39, 0x86, 0x58, 0x76, 0x14, 0xA6, 0xAA, 0xC9, 0x2C, 0x6C, 0xA8, 0x76, 0xFC, 0xB7, 0xC8, 0x54, 0xA3, 0x09, 0x5C, + 0x77, 0x3B, 0x31, 0xA2, 0xAD, 0xE2, 0x3C, 0xFC, 0x6A, 0x1D, 0x65, 0x4C, 0x97, 0xA2, 0x81, 0x4D, 0xE8, 0x10, 0x7F, 0x36, + 0x9E, 0x48, 0x85, 0x9A, 0x80, 0x30, 0x68, 0xDD, 0xDB, 0x81, 0xE3, 0xAA, 0x9D, 0xE9, 0xF0, 0x56, 0x40, 0xA2, 0x59, 0x4D, + 0x0A, 0xF0, 0x4F, 0x8F, 0xC8, 0x08, 0x6F, 0x43, 0x05, 0xC0, 0x80, 0xC6, 0x58, 0xED, 0x71, 0x44, 0x67, 0x80, 0x89, 0x61, + 0xBD, 0xF3, 0x6A, 0x63, 0x61, 0x88, 0x17, 0xF4, 0x13, 0x1B, 0x26, 0x6F, 0x66, 0x51, 0xA2, 0x34, 0x97, 0x7A, 0x15, 0xBB, + 0x6D, 0xE8, 0x5E, 0x83, 0xCF, 0xA7, 0x05, 0x9B, 0x2D, 0xC8, 0xD3, 0xAF, 0x3D, 0x01, 0x6B, 0xEF, 0x85, 0x2E, 0xF6, 0xE7, + 0xD5, 0x02, 0x95, 0x40, 0xC2, 0x65, 0xF1, 0x23, 0xBE, 0x00, 0x5E, 0xEE, 0xC4, 0x96, 0x9F, 0x61, 0xB7, 0x7B, 0xB0, 0x75, + 0xCB, 0x86, 0x60, 0xE4, 0xB8, 0xAF, 0x0A, 0xAA, 0x04, 0x45, 0x15, 0x5E, 0xB2, 0x9A, 0x6E, 0xC2, 0x41, 0x87, 0x85, 0x51, + 0xF6, 0xBA, 0x5F, 0xEA, 0xE7, 0x82, 0x55, 0x25, 0x69, 0xEB, 0x33, 0x67, 0xA5, 0xB0, 0xC9, 0x8D, 0x7A, 0xEB, 0x37, 0xFA, + 0x74, 0x2C, 0xE8, 0x31, 0x20, 0xB7, 0x62, 0x8C, 0xA4, 0xB1, 0x4D, 0x15, 0x68, 0xA6, 0xB3, 0x3B, 0x4F, 0x77, 0xB3, 0xFD, + 0x2C, 0x08, 0x7E, 0xED, 0x8E, 0x48, 0xC9, 0xDF, 0x6E, 0xFA, 0x65, 0x23, 0x0B, 0x33, 0xC8, 0x0F, 0x1E, 0xEB, 0x96, 0x49, + 0x4E, 0x6F, 0xE8, 0x79, 0x97, 0xB9, 0x98, 0xBA, 0xB4, 0xC8, 0x28, 0x7C, 0xC9, 0xC6, 0x3B, 0x2F, 0x64, 0x59, 0xED, 0x9F, + 0xD4, 0x47, 0x27, 0x5B, 0x89, 0xAE, 0xAD, 0x2A, 0xD5, 0xFA, 0xB4, 0xFC, 0x0F, 0x4B, 0xB3, 0x3B, 0x54, 0x36, 0xB3, 0xC2, + 0x75, 0x6C, 0x5A, 0x01, 0xAD, 0xED, 0x64, 0xD7, 0x48, 0x8E, 0x2B, 0x71, 0x61, 0x76, 0xAA, 0x47, 0x85, 0xCF, 0x15, 0x2D, + 0x6F, 0xCE, 0xB4, 0x41, 0x3D, 0x40, 0x43, 0x20, 0x7B, 0x4C, 0xA3, 0xDB, 0x09, 0x3E, 0xDD, 0x76, 0xF6, 0xA3, 0x68, 0x2C, + 0xC8, 0x6C, 0x5C, 0x00, 0x03, 0x32, 0xAB, 0x20, 0x02, 0xCD, 0x10, 0xAF, 0xCC, 0x5E, 0x84, 0xFF, 0xB4, 0xA6, 0xC3, 0x4F, + 0x8D, 0x40, 0xB5, 0x11, 0x67, 0x6F, 0x41, 0xE4, 0xCB, 0xDC, 0x06, 0x5D, 0x57, 0x76, 0x74, 0xE0, 0xD5, 0x9C, 0xEC, 0x4B, + 0x5D, 0xD3, 0x62, 0xE5, 0x47, 0x19, 0x5B, 0xC0, 0xA7, 0xD1, 0xEF, 0xE7, 0x4B, 0xFA, 0x1B, 0xAA, 0x66, 0x92, 0x9B, 0x8E, + 0xB2, 0x10, 0x8D, 0x58, 0x69, 0x2F, 0x75, 0x36, 0xBB, 0x5F, 0x62, 0xD2, 0xA4, 0xD3, 0x78, 0x77, 0xBF, 0xF1, 0x35, 0xBE, + 0x67, 0x0F, 0xF9, 0x33, 0xBF, 0xA6, 0xDF, 0x46, 0x64, 0x64, 0x85, 0x3C, 0xD7, 0xCF, 0x22, 0xF1, 0x04, 0x27, 0x0C, 0xEE, + 0xD1, 0xB5, 0x2E, 0xDF, 0x24, 0x15, 0x95, 0x11, 0x33, 0x97, 0xAD, 0x5A, 0x2F, 0x56, 0xB8, 0xB8, 0xF5, 0x12, 0x6D, 0xCF, + 0x29, 0xD4, 0xF6, 0x2B, 0xBE, 0x89, 0x53, 0x4A, 0x88, 0x72, 0x95, 0x50, 0xD1, 0xB4, 0x6B, 0x62, 0x2E, 0xCA, 0x22, 0x55, + 0x59, 0xFC, 0x49, 0x44, 0x1B, 0x14, 0xDF, 0xD3, 0x1E, 0xDC, 0x12, 0x32, 0x2A, 0x22, 0xE0, 0xA0, 0x3D, 0x78, 0xFB, 0x5A, + 0x64, 0xD7, 0xBE, 0xBA, 0x0B, 0x98, 0x08, 0xAF, 0x70, 0x3D, 0x8E, 0x1E, 0x4A, 0x26, 0xC6, 0x52, 0xF7, 0x94, 0x65, 0x44, + 0x02, 0xEB, 0x14, 0x7B, 0xA4, 0x95, 0x7C, 0x8A, 0xC3, 0xA7, 0x6E, 0x85, 0x8F, 0x58, 0x68, 0xC5, 0x7C, 0xF8, 0xB9, 0x5B, + 0x65, 0x5A, 0x70, 0x17, 0x3D, 0xEB, 0xC4, 0xB3, 0x48, 0x24, 0x9F, 0xB3, 0xFB, 0x79, 0x58, 0x7B, 0xA3, 0x1A, 0xDE, 0x34, + 0x92, 0xB1, 0xE6, 0x6E, 0x64, 0x12, 0x90, 0xDA, 0x95, 0xD7, 0xB9, 0x28, 0x0C, 0x7F, 0x5A, 0xBC, 0x1B, 0xA6, 0x7F, 0x9C, + 0x94, 0xCD, 0x80, 0x4E, 0x6F, 0x30, 0x63, 0x8B, 0xC3, 0x33, 0x98, 0xE8, 0x1F, 0x61, 0x2E, 0x48, 0x4B, 0x41, 0x67, 0x07, + 0x6C, 0x33, 0x35, 0x56, 0xC7, 0x1C, 0xC8, 0xB9, 0x48, 0xAF, 0xC7, 0x05, 0xFF, 0x92, 0x81, 0x4E, 0xDB, 0xFF, 0xA3, 0x2C, + 0xDC, 0x71, 0xD9, 0xB9, 0xB5, 0xA0, 0xB7, 0x94, 0x46, 0xC2, 0xB6, 0x10, 0x3C, 0x7B, 0xAD, 0x2C, 0xE0, 0xAE, 0x8C, 0x04, + 0x22, 0xE0, 0x65, 0xB4, 0x0B, 0x55, 0x1F, 0x06, 0x62, 0x15, 0x22, 0x39, 0x58, 0xB3, 0x79, 0x63, 0x6F, 0xA5, 0x19, 0xA5, + 0x8A, 0xDE, 0xB2, 0x53, 0xBB, 0x6D, 0x8C, 0xE2, 0xD1, 0xF7, 0xA9, 0x34, 0x6C, 0xA4, 0xE6, 0x5A, 0x4E, 0xB5, 0x0B, 0xCA, + 0xD7, 0xA8, 0xBB, 0x80, 0x42, 0x89, 0x82, 0x24, 0x0D, 0xA5, 0xD4, 0xE4, 0x79, 0x1C, 0xC6, 0x94, 0xAD, 0x2B, 0xEB, 0xF9, + 0xEA, 0xE4, 0xB6, 0x79, 0x20, 0x34, 0x9E, 0x98, 0x41, 0x08, 0xA2, 0x14, 0x5A, 0xE8, 0x18, 0xC1, 0x25, 0x00, 0x94, 0xA5, + 0xB5, 0xAB, 0x08, 0x65, 0x67, 0x4D, 0x88, 0x54, 0x77, 0x99, 0x31, 0xA0, 0x20, 0xF7, 0xE9, 0x44, 0x72, 0x88, 0x01, 0xF5, + 0xC5, 0xAC, 0xA7, 0x59, 0xB0, 0x16, 0xA2, 0x16, 0x84, 0x05, 0x02, 0x2C, 0x2B, 0x5B, 0x1A, 0x38, 0x3F, 0x68, 0xEE, 0x52, + 0xB3, 0x59, 0x08, 0xE5, 0x01, 0x0D, 0xF8, 0x1D, 0x57, 0x32, 0xB7, 0x46, 0xD4, 0x74, 0xA4, 0x14, 0xD4, 0x9F, 0xEF, 0x9A, + 0x98, 0x02, 0xA3, 0x84, 0x71, 0x69, 0x33, 0x2D, 0xBF, 0x4A, 0xCA, 0xA9, 0x7D, 0x95, 0x8B, 0xE4, 0x89, 0xFF, 0x5A, 0x7B, + 0xD9, 0x64, 0x84, 0xD9, 0xCD, 0x3E, 0xD3, 0x39, 0x05, 0x7A, 0x60, 0xBB, 0x6E, 0x17, 0x57, 0xA4, 0x62, 0x61, 0x65, 0x77, + 0x2E, 0x57, 0xC4, 0x40, 0xE9, 0xA1, 0x74, 0x6C, 0x38, 0x59, 0x4B, 0x65, 0x28, 0x8C, 0x42, 0x6C, 0xAF, 0x8C, 0x61, 0x9C, + 0x47, 0xC0, 0x60, 0x3D, 0xAB, 0x8C, 0xC1, 0xBE, 0xEA, 0x8A, 0xF2, 0x1F, 0xA3, 0x8F, 0x28, 0x9F, 0xFB, 0x1F, 0xD1, 0x39, + 0xD3, 0x14, 0x91, 0x58, 0x3C, 0x2B, 0x61, 0x91, 0x8B, 0x00, 0xDA, 0xF9, 0xD5, 0x95, 0xDF, 0xDE, 0x5F, 0x01, 0x13, 0x74, + 0x48, 0xC1, 0x02, 0xAD, 0xD3, 0xFD, 0xAA, 0x91, 0x18, 0x59, 0xCC, 0x69, 0x0A, 0x9C, 0x8A, 0x34, 0x39, 0x3B, 0xDC, 0x20, + 0x60, 0x13, 0x5C, 0x4C, 0x64, 0x75, 0xD8, 0x90, 0xDB, 0xED, 0xFC, 0xF6, 0x92, 0x7D, 0x45, 0x47, 0xA8, 0x22, 0x6A, 0x21, + 0xC5, 0x9D, 0x73, 0xAC, 0x4A, 0x10, 0xB3, 0x98, 0x3E, 0xB5, 0x5B, 0x7B, 0x5A, 0x11, 0x9F, 0xC7, 0xC2, 0x33, 0x04, 0xA6, + 0x01, 0xD4, 0x86, 0x27, 0xD9, 0x85, 0x8D, 0xDC, 0x59, 0x6A, 0xCD, 0x9F, 0xD1, 0xD4, 0x4E, 0x36, 0x10, 0x17, 0x5F, 0x24, + 0x4B, 0x94, 0xCD, 0x18, 0x0B, 0xDE, 0xDA, 0x14, 0xFE, 0x34, 0x47, 0x27, 0x43, 0x0D, 0x05, 0x55, 0x19, 0x99, 0x8A, 0xF0, + 0xE4, 0x94, 0x44, 0x96, 0xC6, 0xFF, 0xF5, 0xC1, 0x04, 0x7B, 0x5C, 0x3F, 0x16, 0xC8, 0xA2, 0x17, 0xE5, 0xF5, 0x62, 0x07, + 0xD0, 0xFF, 0x38, 0xB4, 0x6A, 0xE7, 0x02, 0x4C, 0x7C, 0x95, 0x50, 0x3B, 0x97, 0x65, 0x6E, 0x44, 0x50, 0x35, 0x06, 0x9C, + 0x01, 0x81, 0x8C, 0xEE, 0x0A, 0x31, 0xC5, 0xB9, 0xE9, 0x19, 0x9C, 0x5A, 0xF6, 0x8F, 0x39, 0x29, 0x25, 0xEC, 0x84, 0x1F, + 0xB4, 0x32, 0xFB, 0x36, 0xE9, 0xDA, 0x68, 0x45, 0xB6, 0x37, 0xCF, 0x09, 0xA8, 0x59, 0x77, 0xB9, 0xD2, 0x2A, 0xC4, 0xB9, + 0x74, 0x86, 0xD7, 0xB9, 0xF0, 0xFF, 0x24, 0xD8, 0x2B, 0x5D, 0xBC, 0xAC, 0x7E, 0xC1, 0x06, 0x17, 0x0B, 0x09, 0xE8, 0xF1, + 0x99, 0x75, 0x04, 0x78, 0xD4, 0xEA, 0x0B, 0xCF, 0x2F, 0xCC, 0xAB, 0x98, 0x73, 0xA0, 0x87, 0xCD, 0xDC, 0x7B, 0x27, 0xCB, + 0xD1, 0x13, 0xC5, 0x3E, 0xC6, 0x3A, 0x4F, 0xF5, 0x17, 0xD7, 0x00, 0x9E, 0xEE, 0xFE, 0x0F, 0x59, 0x42, 0x67, 0xEF, 0x49, + 0x5A, 0x90, 0x45, 0xD6, 0xCA, 0xDF, 0xF7, 0x93, 0xFD, 0xDD, 0x74, 0x11, 0x7C, 0xC4, 0x18, 0xF9, 0xF6, 0x80, 0x64, 0x51, + 0x6E, 0xB9, 0x8E, 0x0F, 0x5A, 0x82, 0xC4, 0x81, 0x1D, 0x89, 0x2A, 0x69, 0xF7, 0xE1, 0x8F, 0x82, 0x43, 0x43, 0xA9, 0x76, + 0x71, 0xA3, 0x07, 0x3B, 0x08, 0x8F, 0xA3, 0xEF, 0xB0, 0xA6, 0x29, 0x07, 0x30, 0xA1, 0xFB, 0x9A, 0x59, 0x44, 0x2B, 0xEE, + 0x8D, 0x87, 0xAF, 0xFF, 0xA7, 0x0E, 0xA5, 0xF4, 0x38, 0x65, 0xA5, 0x54, 0x3E, 0x22, 0x20, 0xB2, 0x0E, 0xCB, 0xA9, 0xAE, + 0x32, 0xE9, 0x4E, 0x2F, 0x67, 0x04, 0xCF, 0x84, 0xBF, 0xD4, 0x52, 0xBA, 0x47, 0xCA, 0x13, 0x2B, 0x34, 0x95, 0x33, 0x94, + 0xC5, 0x11, 0x39, 0xF2, 0x51, 0x43, 0x38, 0x4D, 0x62, 0x47, 0x1E, 0xAF, 0xEE, 0xEB, 0x28, 0x73, 0x63, 0x67, 0xD1, 0xE3, + 0x33, 0x67, 0x30, 0x73, 0x22, 0x26, 0x52, 0x47, 0x7C, 0xD6, 0x21, 0x11, 0x38, 0xDC, 0x39, 0xF2, 0x88, 0x5A, 0xA2, 0xF7, + 0x0C, 0x7C, 0xF2, 0xE8, 0x80, 0xEB, 0xE0, 0x54, 0x86, 0x6B, 0x8C, 0x1B, 0xD1, 0x4E, 0x3D, 0xF7, 0x45, 0x32, 0x06, 0x8C, + 0x55, 0xA3, 0x04, 0x37, 0x8F, 0x69, 0x3A, 0x58, 0x1D, 0xA6, 0xF3, 0xF7, 0x59, 0x71, 0xA5, 0x17, 0x75, 0x5B, 0x3B, 0xAF, + 0x50, 0xE9, 0x21, 0xEF, 0xCA, 0xF1, 0xD4, 0x9F, 0xF6, 0xA0, 0x2E, 0x20, 0xE1, 0x0B, 0x73, 0x33, 0xAE, 0xDA, 0xD9, 0x3E, + 0xDC, 0xC9, 0x73, 0xB5, 0x83, 0x2A, 0xBC, 0x62, 0x16, 0xA8, 0x70, 0x0C, 0xC3, 0x3A, 0x8A, 0x18, 0x3E, 0xBA, 0x95, 0x29, + 0x37, 0xE3, 0x94, 0x72, 0x19, 0x2F, 0xBA, 0x82, 0x5A, 0x8C, 0x85, 0xFA, 0x15, 0x92, 0x72, 0x8B, 0x8A, 0x75, 0xE5, 0x3D, + 0x75, 0xDF, 0x7B, 0x7A, 0x2F, 0x81, 0x33, 0xEB, 0x5B, 0xE3, 0x8C, 0x1B, 0xE1, 0x94, 0x97, 0xAC, 0xEF, 0xED, 0x22, 0x56, + 0xBC, 0xCF, 0xE9, 0x05, 0xD9, 0x8D, 0x62, 0xD8, 0xDB, 0xD2, 0x5B, 0x6E, 0xE4, 0x7D, 0x99, 0xC9, 0x19, 0xDB, 0x8E, 0x40, + 0x72, 0x49, 0x73, 0xF7, 0x4E, 0xF2, 0xD3, 0x12, 0x6C, 0x55, 0xEC, 0xDF, 0x44, 0x4B, 0x2A, 0xC4, 0x8A, 0xEA, 0x63, 0x89, + 0x5F, 0xD0, 0x5A, 0x6A, 0x84, 0x3F, 0xB5, 0x8C, 0xC2, 0x7F, 0xE4, 0xB8, 0xC4, 0x26, 0x2D, 0x8C, 0xC7, 0xD1, 0x0A, 0xA2, + 0x86, 0xE7, 0x8E, 0x02, 0x19, 0x10, 0xFD, 0xD1, 0xD4, 0xE3, 0x3C, 0xD3, 0x15, 0xA1, 0x71, 0x2E, 0x4E, 0xF9, 0xCB, 0x50, + 0xD0, 0xA4, 0xE9, 0x95, 0x6E, 0xFB, 0x2C, 0xB4, 0x65, 0xDA, 0x54, 0xC6, 0xDC, 0x04, 0xFD, 0xCA, 0x54, 0x74, 0x6D, 0xB1, + 0xBD, 0xA5, 0xDD, 0xA3, 0xEA, 0x8D, 0xE7, 0x34, 0xC6, 0xA6, 0x4F, 0x10, 0xDA, 0x72, 0xCF, 0x14, 0xC2, 0x5B, 0x4D, 0xDB, + 0x4E, 0x76, 0xEC, 0xB1, 0xF7, 0x18, 0x27, 0xF7, 0x40, 0x2A, 0xB5, 0xC3, 0x94, 0x85, 0x64, 0xCA, 0x2A, 0x3A, 0x1C, 0x71, + 0x03, 0xA9, 0xF6, 0x3A, 0x41, 0xB6, 0xD6, 0xB0, 0x46, 0xF5, 0x48, 0x61, 0x2B, 0x22, 0x08, 0x81, 0x59, 0x14, 0x58, 0x1F, + 0x6C, 0x41, 0x01, 0x79, 0xBF, 0xB9, 0x4E, 0x74, 0xAA, 0x38, 0xF8, 0x0E, 0xBA, 0x02, 0x88, 0x38, 0x8E, 0x07, 0x1B, 0x3C, + 0x90, 0x05, 0xB3, 0x6A, 0xC7, 0x9B, 0x3D, 0x6D, 0x9C, 0xDB, 0x01, 0x1F, 0xCE, 0x19, 0xB7, 0xB6, 0x00, 0x7D, 0x70, 0xAB, + 0xD1, 0xDE, 0x75, 0xDD, 0x2A, 0x4D, 0x64, 0xCC, 0x4F, 0x8E, 0xE0, 0xC2, 0x78, 0xBE, 0xB8, 0xB8, 0xD0, 0x30, 0x16, 0x5A, + 0x31, 0x17, 0x6C, 0x0C, 0x4E, 0x7C, 0xEC, 0x80, 0x79, 0x9F, 0xFE, 0x3C, 0x2C, 0x4A, 0xBE, 0xFE, 0xDD, 0x1E, 0x65, 0x04, + 0xCF, 0x2E, 0x51, 0x6B, 0xB4, 0xA1, 0x7E, 0x1C, 0x71, 0x97, 0xFF, 0xBD, 0xF7, 0xA4, 0x6D, 0x0C, 0xCE, 0x0F, 0xE6, 0x80, + 0x5C, 0x74, 0xE5, 0x31, 0x34, 0x42, 0x38, 0xFB, 0x00, 0x6D, 0xF3, 0x60, 0x0A, 0xCB, 0x86, 0x88, 0x56, 0xE2, 0xF1, 0x20, + 0xA2, 0x43, 0x48, 0x96, 0x9C, 0xD7, 0xBE, 0xB4, 0x47, 0x47, 0x3B, 0x80, 0x8D, 0x82, 0xC1, 0x79, 0x86, 0xA0, 0x16, 0x42, + 0x9E, 0x60, 0xD4, 0x1C, 0xC6, 0x00, 0x7E, 0xA1, 0xA6, 0xB6, 0xCD, 0x79, 0x7C, 0x0C, 0xC1, 0x10, 0xEE, 0x03, 0x66, 0xB5, + 0xBA, 0x2A, 0xC3, 0xBA, 0xB9, 0x30, 0xE3, 0xF4, 0xDE, 0xE7, 0x00, 0xC0, 0x97, 0x66, 0x10, 0x3B, 0x44, 0x86, 0x41, 0x23, + 0x5C, 0xCB, 0x88, 0xD4, 0x72, 0xFA, 0x0F, 0x96, 0xB2, 0xDA, 0x60, 0x8E, 0xEF, 0x48, 0xA6, 0x59, 0xD1, 0xA2, 0x1B, 0xCE, + 0xEA, 0x85, 0x16, 0x7B, 0x94, 0xA4, 0x90, 0xE3, 0x2C, 0xC0, 0x40, 0x16, 0xEE, 0x04, 0x92, 0x51, 0xE0, 0x71, 0xA1, 0x37, + 0x64, 0x65, 0xA6, 0x55, 0x38, 0xDC, 0x1C, 0x17, 0x2C, 0xBC, 0x04, 0x24, 0x88, 0x66, 0x12, 0xE4, 0x7C, 0x65, 0xD2, 0xAD, + 0xE1, 0x40, 0x52, 0xA8, 0x29, 0x97, 0xF5, 0xF0, 0x6D, 0x44, 0xD3, 0xB1, 0x1F, 0x6B, 0x43, 0x85, 0xEC, 0xC0, 0x8C, 0x90, + 0xB2, 0x2D, 0x93, 0xE1, 0xF0, 0x47, 0x78, 0x89, 0x9E, 0x8E, 0x97, 0xD4, 0xC0, 0x0B, 0x48, 0x2D, 0xBB, 0xFC, 0x94, 0xF9, + 0xD1, 0x10, 0x2F, 0xDA, 0x47, 0x21, 0x9B, 0x59, 0xC5, 0xB0, 0xA1, 0x8D, 0x3F, 0xC4, 0x54, 0xF9, 0x0C, 0x4E, 0xD9, 0x00, + 0x99, 0x21, 0x52, 0xEC, 0x75, 0xD0, 0xD2, 0xE8, 0x5C, 0x4A, 0x8A, 0xB5, 0xDA, 0xD9, 0x66, 0x23, 0xC1, 0xF0, 0xA2, 0x90, + 0x29, 0x00, 0x9A, 0xFE, 0xBD, 0x1B, 0x58, 0xB2, 0xF9, 0x0E, 0xBC, 0x8F, 0x3B, 0xB1, 0xC3, 0x1B, 0xF9, 0x46, 0x13, 0xD0, + 0x3C, 0x64, 0x1A, 0x46, 0xB1, 0x4D, 0xA8, 0x1D, 0xDF, 0x34, 0x41, 0x78, 0xEA, 0x0F, 0xE3, 0x82, 0xAC, 0x6F, 0x4C, 0x05, + 0x13, 0x51, 0xCC, 0x81, 0x4F, 0x10, 0x95, 0x48, 0x5E, 0x1D, 0xD5, 0x20, 0x36, 0x12, 0xCC, 0x4C, 0xDA, 0x53, 0xF3, 0xAB, + 0x29, 0x73, 0xEB, 0xB1, 0x6D, 0xAA, 0xE7, 0x4F, 0xF2, 0x7C, 0xBD, 0xB1, 0x3E, 0x50, 0x15, 0x78, 0xB0, 0x73, 0xEA, 0x25, + 0x8B, 0x2D, 0x55, 0xDD, 0xE5, 0xFF, 0x52, 0xF4, 0xA7, 0x71, 0xD2, 0xF0, 0x58, 0xE3, 0x19, 0x95, 0x08, 0x23, 0x60, 0x77, + 0x50, 0x2C, 0x0C, 0xDC, 0xA0, 0xF3, 0x7C, 0x2B, 0xD3, 0x6B, 0x8F, 0xE0, 0x51, 0xF7, 0x6F, 0x77, 0x46, 0x35, 0x74, 0x2F, + 0xC2, 0x8A, 0x33, 0x13, 0x35, 0x17, 0x9C, 0xB6, 0x65, 0xA6, 0x4D, 0x51, 0x9A, 0xBF, 0xA7, 0xA3, 0x55, 0x73, 0xB8, 0x2F, + 0x31, 0x3B, 0xED, 0xD1, 0x74, 0x14, 0x85, 0xC8, 0x94, 0x77, 0x32, 0x55, 0xE5, 0x45, 0x02, 0x15, 0xE5, 0x2C, 0xEE, 0x75, + 0xA1, 0xA5, 0xCB, 0x97, 0x08, 0xDA, 0x78, 0xCF, 0xFE, 0x12, 0x2A, 0x09, 0xCF, 0xC5, 0xFA, 0x3A, 0x2C, 0x52, 0xFE, 0xCE, + 0xC3, 0x76, 0x57, 0xB1, 0x8C, 0xE6, 0xD8, 0x1E, 0xD7, 0x7F, 0x18, 0x78, 0x25, 0xF4, 0x61, 0xD2, 0x0F, 0xA6, 0x83, 0x74, + 0xA0, 0x5B, 0x17, 0x92, 0xDA, 0x8E, 0x10, 0xDA, 0xB8, 0xDC, 0xAF, 0x47, 0x45, 0x8B, 0x75, 0xF9, 0xAF, 0x00, 0x4F, 0x1C, + 0x1C, 0x3B, 0x1C, 0xFE, 0x2B, 0x3B, 0xA0, 0x14, 0x02, 0xE6, 0x26, 0x7F, 0xEC, 0x11, 0x15, 0xAA, 0x09, 0xDD, 0x3E, 0x8A, + 0x95, 0x52, 0x98, 0x49, 0x89, 0xF7, 0xE7, 0xA6, 0xBE, 0x1B, 0xC8, 0x36, 0x3D, 0x3F, 0xD7, 0x86, 0xEA, 0x50, 0x84, 0x6F, + 0x09, 0x88, 0xBC, 0xEE, 0x0B, 0x61, 0x07, 0x5D, 0x06, 0x45, 0x6F, 0x17, 0xEC, 0xC7, 0xCF, 0xD4, 0x11, 0x3A, 0xB9, 0x5F, + 0x0A, 0x80, 0x47, 0xAF, 0x84, 0xBF, 0xE0, 0xBB, 0x4A, 0xAA, 0x7F, 0x03, 0x02, 0xFE, 0x75, 0x64, 0x02, 0x33, 0x24, 0xFB, + 0x1C, 0xE1, 0x34, 0x06, 0xA5, 0x3F, 0x14, 0x44, 0x52, 0x33, 0xAC, 0xEF, 0x0D, 0xC0, 0xF0, 0x13, 0x05, 0xA5, 0x3C, 0x37, + 0x3A, 0xE1, 0xED, 0xB2, 0x5B, 0xAF, 0x28, 0x44, 0x52, 0x88, 0xF8, 0x3E, 0x31, 0x7B, 0xF1, 0x4E, 0x60, 0x35, 0x12, 0x39, + 0xE6, 0x16, 0x70, 0x2A, 0x20, 0x7C, 0x29, 0xFF, 0xE9, 0xEE, 0xA9, 0xB7, 0xCB, 0x97, 0x80, 0x75, 0x74, 0xDE, 0x26, 0x01, + 0x00, 0xC6, 0xE8, 0xB6, 0x1E, 0xEB, 0x4C, 0x59, 0x40, 0x86, 0x30, 0xE2, 0xA0, 0xE9, 0xA8, 0xC6, 0x09, 0xC7, 0xB1, 0xF3, + 0x11, 0x27, 0x79, 0x14, 0x27, 0x97, 0xFA, 0x04, 0x64, 0xED, 0x5E, 0xC7, 0xC4, 0x94, 0x71, 0xAF, 0xF0, 0xEB, 0x15, 0x9C, + 0xB1, 0xC6, 0x31, 0xDA, 0x30, 0xEE, 0x72, 0x1F, 0x05, 0x60, 0x5C, 0xBA, 0xDF, 0xE5, 0xB9, 0xF7, 0x0D, 0x78, 0x01, 0x53, + 0x76, 0x58, 0x7B, 0x2E, 0xA9, 0x71, 0xDC, 0xBE, 0x7F, 0xDE, 0x3A, 0x2F, 0x33, 0xE8, 0x9A, 0x4C, 0xE9, 0xE4, 0xEA, 0x9E, + 0x34, 0xCB, 0x61, 0xE5, 0x1B, 0x12, 0xC5, 0xBE, 0x26, 0xB6, 0x7A, 0xAF, 0xD4, 0xAB, 0x7B, 0x2F, 0xBF, 0x4B, 0xB5, 0xBF, + 0x9A, 0xE8, 0xA3, 0xC3, 0xA8, 0x87, 0x8B, 0x40, 0x5D, 0xE7, 0x7C, 0x53, 0x02, 0x5D, 0x37, 0x9B, 0xD7, 0x56, 0x84, 0x4B, + 0xC5, 0xC2, 0x7B, 0x44, 0xDB, 0x69, 0x80, 0x34, 0xAD, 0xE9, 0x26, 0x14, 0xFF, 0xD7, 0x29, 0x6A, 0x48, 0xB7, 0xA9, 0x6E, + 0x58, 0x97, 0x15, 0xDE, 0x01, 0xC3, 0x2A, 0xDE, 0xC6, 0x50, 0xC5, 0x38, 0xEE, 0x8F, 0xFA, 0xFA, 0x60, 0x71, 0xDC, 0xA9, + 0x6F, 0x11, 0xE1, 0xA1, 0x25, 0xB1, 0x58, 0x15, 0x4F, 0xC3, 0xD8, 0x4B, 0x25, 0x75, 0xC7, 0xDF, 0x85, 0x75, 0xC3, 0x3D, + 0xAC, 0xEC, 0xBB, 0xC5, 0x6E, 0x30, 0x17, 0x00, 0x15, 0x9E, 0xB4, 0xE4, 0xD3, 0x6D, 0xA4, 0x86, 0x34, 0x3D, 0x7C, 0xA7, + 0x1B, 0xF0, 0xE5, 0x5C, 0x72, 0x32, 0x75, 0xA6, 0x80, 0x47, 0x18, 0x74, 0xFD, 0x32, 0x74, 0x33, 0x8C, 0x41, 0xA3, 0x46, + 0x6B, 0x50, 0x89, 0x1D, 0xA7, 0xA2, 0xC5, 0x30, 0x72, 0xBD, 0xA5, 0x27, 0xA2, 0xE2, 0x74, 0xB6, 0xC2, 0xD7, 0x25, 0x96, + 0xDA, 0xB3, 0x7C, 0xE4, 0x83, 0xDF, 0x4F, 0xB6, 0xB9, 0xC8, 0xEF, 0x33, 0xF3, 0x17, 0xD0, 0xA0, 0xDD, 0xF1, 0x24, 0x42, + 0x9F, 0xF6, 0x75, 0x1E, 0x66, 0xCF, 0xEC, 0x1D, 0x87, 0x77, 0xC0, 0x5D, 0xD8, 0x48, 0xB5, 0x96, 0x54, 0x95, 0xBC, 0x76, + 0xAD, 0x6A, 0x46, 0xC7, 0xD6, 0x8A, 0x5D, 0x3D, 0x0A, 0x9B, 0xA3, 0xCE, 0xB7, 0x16, 0x23, 0x85, 0x86, 0x84, 0x10, 0x1D, + 0xC5, 0x60, 0x8C, 0x2D, 0x5E, 0x11, 0x15, 0x3F, 0x91, 0xFA, 0x26, 0xF3, 0xE1, 0xAC, 0x3D, 0x1E, 0xDB, 0xEC, 0xB6, 0xF9, + 0x30, 0x91, 0xC0, 0x3F, 0x3F, 0x13, 0xA5, 0x2E, 0x6A, 0x5C, 0x49, 0x52, 0x7C, 0x73, 0x96, 0x65, 0x1E, 0xEA, 0x6E, 0x1A, + 0xF1, 0x46, 0xD9, 0xFA, 0x61, 0x22, 0x7E, 0xA9, 0x86, 0x62, 0xB3, 0xBB, 0xC0, 0x85, 0xFD, 0x02, 0xD4, 0xE9, 0xC8, 0xD8, + 0xFC, 0xB4, 0x72, 0x9E, 0x96, 0xB8, 0x97, 0x65, 0x50, 0xF5, 0x74, 0x9F, 0xDE, 0x29, 0x3B, 0x9F, 0xDE, 0xBA, 0xBF, 0x3B, + 0xC2, 0x67, 0x66, 0x31, 0xDF, 0x1A, 0x19, 0x09, 0xF4, 0x6C, 0x5D, 0x94, 0xEF, 0xD1, 0xFB, 0x88, 0x9C, 0xBC, 0x74, 0x5E, + 0x21, 0x01, 0x59, 0xC2, 0x54, 0xEC, 0x7B, 0x06, 0x6F, 0xC6, 0xA7, 0xB7, 0xDA, 0x7D, 0x67, 0x31, 0x4F, 0xE5, 0xEF, 0xCB, + 0x3E, 0xFE, 0xC8, 0xA9, 0x4F, 0x2B, 0x73, 0x29, 0xCA, 0xBF, 0xAF, 0x5E, 0x28, 0xDD, 0xEF, 0xC0, 0x83, 0x12, 0x29, 0x9D, + 0x8F, 0x89, 0x07, 0xDB, 0xFF, 0xFF, 0xA8, 0x31, 0x33, 0xC5, 0xFE, 0x29, 0x9F, 0x8D, 0x2D, 0xA4, 0x46, 0xD1, 0xDA, 0xCB, + 0xF3, 0x6D, 0xF7, 0xF6, 0xE8, 0x10, 0xA8, 0xFE, 0x78, 0x50, 0xE7, 0xC1, 0xE2, 0x01, 0x10, 0x04, 0xB0, 0x6E, 0xB9, 0xF2, + 0xB0, 0x89, 0x92, 0x96, 0x87, 0xA9, 0x29, 0xDF, 0x6C, 0x4F, 0xDB, 0xDE, 0x73, 0x64, 0xA5, 0x82, 0x8E, 0x0B, 0xE8, 0x55, + 0x95, 0x6D, 0x24, 0x03, 0xA1, 0x4A, 0x2D, 0xD7, 0x53, 0x6B, 0x80, 0xA8, 0x7A, 0x02, 0xE8, 0x26, 0xAB, 0x28, 0x82, 0x91, + 0x7E, 0xA1, 0xEA, 0xD4, 0xDA, 0xCB, 0x5F, 0xD2, 0x06, 0xB5, 0x75, 0x16, 0xB2, 0x88, 0x4F, 0x47, 0x28, 0x94, 0xE0, 0x9F, + 0x33, 0x45, 0xC9, 0x48, 0x84, 0x1D, 0xF9, 0x2B, 0x13, 0x2B, 0x0F, 0x59, 0xE3, 0xED, 0x75, 0x41, 0x39, 0x02, 0x89, 0xB9, + 0xFB, 0xFC, 0x9D, 0x12, 0x9D, 0xB8, 0x41, 0x62, 0xF7, 0x56, 0xA6, 0x07, 0xFD, 0xF8, 0x06, 0x2C, 0x8A, 0xEF, 0x94, 0xAC, + 0x70, 0x8A, 0x6C, 0x2E, 0xA1, 0x47, 0x26, 0x3C, 0xFB, 0x6E, 0x9E, 0x3F, 0xA8, 0x8E, 0xBD, 0x98, 0x7F, 0xE6, 0x22, 0xC2, + 0xE5, 0x44, 0xFA, 0x7D, 0xDD, 0x64, 0xD9, 0x6B, 0x6A, 0x5F, 0x93, 0x81, 0x9A, 0x31, 0x41, 0x1E, 0x23, 0x2E, 0x1B, 0x41, + 0x39, 0x65, 0x45, 0x85, 0x25, 0x06, 0x8A, 0x99, 0xF7, 0xCA, 0x64, 0xC8, 0x6A, 0x0B, 0x91, 0x39, 0x7A, 0xE0, 0x58, 0xCC, + 0x54, 0x51, 0xFC, 0xE8, 0x14, 0x93, 0x6C, 0x40, 0x6B, 0x5F, 0x42, 0x2B, 0x80, 0xF1, 0xB5, 0x0A, 0x05, 0x6F, 0x0A, 0xE9, + 0x9C, 0x41, 0x25, 0x0A, 0x21, 0xFC, 0xFA, 0xF6, 0x7F, 0xE6, 0x23, 0x0D, 0xC4, 0x03, 0xD5, 0x2F, 0x65, 0xB3, 0x6D, 0x55, + 0xAA, 0xCE, 0xC9, 0x6F, 0x69, 0xE5, 0x01, 0x5C, 0xA9, 0x02, 0xF5, 0xF9, 0x41, 0x50, 0x20, 0x88, 0xCA, 0x4F, 0x33, 0x41, + 0x30, 0x2B, 0xA8, 0xA4, 0xC1, 0xBF, 0xBC, 0x54, 0xCE, 0x3F, 0x91, 0xE7, 0x81, 0xF6, 0xC1, 0x46, 0xF2, 0x73, 0x46, 0xA0, + 0xD6, 0x2E, 0x84, 0x76, 0x9D, 0xBA, 0x7A, 0x9D, 0x8A, 0x20, 0x19, 0x56, 0xF3, 0x72, 0x10, 0x72, 0x94, 0xBF, 0xE5, 0xC1, + 0x91, 0xB9, 0x06, 0x52, 0x90, 0xDF, 0xD2, 0x47, 0x72, 0x71, 0x2B, 0xB9, 0x02, 0x96, 0x09, 0x77, 0x33, 0x7B, 0x23, 0x89, + 0x89, 0x02, 0x0B, 0x57, 0x73, 0x5B, 0xCC, 0xC9, 0x24, 0x0F, 0xFD, 0x7C, 0xC1, 0x2F, 0xC7, 0x13, 0x16, 0x89, 0xEC, 0x0F, + 0xCD, 0xC9, 0x1C, 0xB2, 0x67, 0x13, 0x7F, 0xE9, 0xCF, 0x36, 0x1A, 0xD8, 0xE3, 0xD9, 0xC7, 0x7E, 0x57, 0x7A, 0x97, 0xBE, + 0x2F, 0x74, 0xB1, 0x41, 0xB8, 0xF8, 0x03, 0xD8, 0x09, 0xE7, 0x30, 0x15, 0x72, 0x69, 0xC5, 0xC8, 0xA5, 0x0C, 0xF7, 0x2F, + 0x48, 0x2C, 0x63, 0xD8, 0x2B, 0x06, 0x84, 0xED, 0x56, 0xA8, 0x58, 0x6A, 0x2C, 0x9D, 0x4F, 0xFE, 0x9B, 0x3E, 0x68, 0x84, + 0x81, 0x29, 0x2F, 0xCE, 0x3B, 0xC7, 0x30, 0x7A, 0x4B, 0xED, 0x06, 0x9E, 0x98, 0xB3, 0x1B, 0xBA, 0xEF, 0xF4, 0x5E, 0x54, + 0x74, 0x7F, 0x15, 0x51, 0x43, 0x5E, 0x0F, 0x59, 0x1B, 0x3C, 0x41, 0x80, 0x03, 0x6B, 0xEF, 0x2F, 0xF1, 0x47, 0xB8, 0x9F, + 0x42, 0xAA, 0x50, 0x7F, 0x15, 0x36, 0x0E, 0x3D, 0x87, 0x2C, 0x17, 0xB9, 0x58, 0xF1, 0x94, 0xEC, 0x2C, 0xFF, 0xB2, 0x48, + 0x54, 0xDD, 0x2E, 0xDA, 0xA2, 0x53, 0xD7, 0x8A, 0x5E, 0xDD, 0xB5, 0x2B, 0x13, 0xB0, 0x86, 0xD5, 0x08, 0x1A, 0x0A, 0xBF, + 0x65, 0x02, 0x7E, 0x8E, 0x19, 0xDA, 0x23, 0xBA, 0xE9, 0x9F, 0x6B, 0x49, 0xB0, 0xC4, 0x03, 0x1A, 0xCC, 0xF3, 0xEF, 0xDD, + 0x45, 0xD1, 0x83, 0x49, 0x40, 0x4E, 0x0F, 0x59, 0xB5, 0x3F, 0x61, 0x5D, 0xE5, 0x20, 0xA1, 0xFA, 0x5A, 0xA0, 0x52, 0xD3, + 0x1E, 0xE5, 0x4C, 0x82, 0x1E, 0x5A, 0x0D, 0x10, 0x24, 0x49, 0xB4, 0xA2, 0x67, 0x78, 0x48, 0xA5, 0x76, 0x8C, 0x38, 0x51, + 0x31, 0xA7, 0x6A, 0x05, 0xAE, 0xA5, 0xB2, 0x26, 0xF6, 0xEC, 0x19, 0xB1, 0x30, 0x00, 0xA9, 0x06, 0xB0, 0xCC, 0x4F, 0x25, + 0x2D, 0xCD, 0xD1, 0x87, 0x68, 0xEF, 0xD2, 0x34, 0x24, 0x7C, 0x21, 0x6F, 0x74, 0xAC, 0x01, 0xDD, 0x69, 0xCE, 0xB3, 0x77, + 0x76, 0xEE, 0xE2, 0xC0, 0x03, 0xA4, 0xDE, 0xE7, 0xC4, 0xFB, 0x56, 0x4B, 0x4F, 0xB1, 0xCA, 0xD6, 0x82, 0x4B, 0x42, 0xD7, + 0x09, 0xE7, 0x28, 0x02, 0x2E, 0xAB, 0xEB, 0x4C, 0x3F, 0x87, 0x87, 0x04, 0x35, 0xA6, 0xA1, 0xAB, 0xE0, 0x7B, 0xBE, 0x27, + 0xE5, 0x13, 0x62, 0x4D, 0xFA, 0x33, 0x55, 0x05, 0xB6, 0xE6, 0x23, 0x52, 0xA5, 0x8A, 0xD1, 0xB8, 0x14, 0xAA, 0xE6, 0xC7, + 0x2E, 0xF6, 0x82, 0x0C, 0xB6, 0x87, 0x42, 0xBD, 0x3B, 0x85, 0xC2, 0x4A, 0x25, 0xEA, 0x9E, 0xB1, 0xB7, 0x95, 0xF8, 0xC1, + 0xFF, 0xEE, 0x12, 0x67, 0x2C, 0x49, 0x8E, 0x7C, 0x5E, 0x16, 0x44, 0x02, 0xB4, 0x1F, 0xC2, 0xBC, 0x7F, 0x49, 0xB8, 0xEB, + 0x80, 0xEF, 0xFA, 0xB2, 0x1E, 0xE2, 0x50, 0x70, 0x41, 0x3C, 0x3B, 0x38, 0xBF, 0xCA, 0x83, 0x8B, 0x08, 0x19, 0xD3, 0x9D, + 0xBF, 0xDE, 0x45, 0x16, 0xEF, 0x26, 0x81, 0xDD, 0x5F, 0xE8, 0xE0, 0xC8, 0x0B, 0x2C, 0x1B, 0x8C, 0xBF, 0x93, 0xB2, 0xDF, + 0xD8, 0x6D, 0x8C, 0x68, 0x8E, 0x88, 0xE2, 0xCE, 0xAE, 0x72, 0x7D, 0xA1, 0xAA, 0x7E, 0x2C, 0x57, 0xA4, 0xBC, 0xA4, 0x9C, + 0x1F, 0x40, 0xA3, 0xA3, 0xE8, 0x88, 0x8B, 0x2D, 0x2D, 0xD3, 0x60, 0x98, 0xBE, 0x13, 0x63, 0xED, 0x5F, 0xB3, 0x3B, 0x39, + 0xCB, 0x89, 0x10, 0x34, 0xE5, 0x10, 0xBB, 0xCE, 0x5D, 0x6E, 0x69, 0x7B, 0xD9, 0x7E, 0x83, 0xBE, 0x53, 0x75, 0xEE, 0x78, + 0x97, 0xB6, 0x0C, 0x58, 0xC8, 0xDD, 0xCB, 0x44, 0xF6, 0xB8, 0xEC, 0x63, 0x1D, 0x1C, 0x51, 0x74, 0x94, 0x3B, 0xC7, 0xC9, + 0x6B, 0x2E, 0xC4, 0x34, 0x70, 0xA1, 0xFA, 0xE3, 0x5C, 0x83, 0xAD, 0x03, 0x15, 0x38, 0x4A, 0xD9, 0x69, 0xB0, 0x37, 0xC5, + 0xB7, 0x4D, 0x50, 0xE0, 0xE6, 0x12, 0xD2, 0x75, 0x19, 0xBE, 0x91, 0xC0, 0xD1, 0x25, 0x85, 0x67, 0x0E, 0xFC, 0x5A, 0x12, + 0x4D, 0x9B, 0xE4, 0x39, 0xC9, 0xF5, 0x2B, 0x82, 0x15, 0x61, 0x40, 0x84, 0x89, 0xB5, 0x52, 0x30, 0x11, 0x0A, 0xFF, 0xE9, + 0x4F, 0xC9, 0xBC, 0xA6, 0x5E, 0xCE, 0xD6, 0x1C, 0x34, 0xFA, 0xE5, 0xF1, 0x9A, 0x29, 0xDD, 0x34, 0x94, 0x63, 0xAA, 0x83, + 0x91, 0x33, 0x35, 0xFA, 0xC2, 0x2B, 0x53, 0xFF, 0x6F, 0x1D, 0x52, 0x98, 0x22, 0x6A, 0x09, 0x77, 0xED, 0x19, 0xD4, 0x88, + 0x36, 0x7D, 0xDD, 0x75, 0x95, 0xF4, 0xEC, 0x31, 0x9F, 0xB5, 0x08, 0x83, 0xBA, 0xD2, 0xD6, 0xEA, 0x28, 0xF5, 0xBD, 0x9C, + 0xE5, 0x28, 0xA6, 0x1A, 0x9C, 0x33, 0x01, 0x29, 0x59, 0x76, 0x36, 0xBF, 0x7B, 0xE2, 0xC0, 0x4B, 0xCD, 0x3E, 0xED, 0x50, + 0x1F, 0xBC, 0xB7, 0x6D, 0x84, 0xB6, 0xFD, 0x54, 0x5F, 0xFC, 0x8B, 0x6A, 0x0E, 0xDB, 0x54, 0x7D, 0x11, 0xB6, 0x2C, 0xC1, + 0x27, 0xEA, 0xA8, 0x3D, 0xF8, 0x5B, 0x1E, 0xF8, 0xE6, 0x93, 0x4F, 0xBC, 0x85, 0xA3, 0x2F, 0x4D, 0xCB, 0x03, 0x71, 0xA6, + 0x5A, 0x77, 0xB8, 0x68, 0x10, 0x94, 0x78, 0xCF, 0x53, 0x36, 0x00, 0x5A, 0x5C, 0xFA, 0xC4, 0x4E, 0x95, 0x52, 0x6F, 0x38, + 0xA7, 0xDC, 0x77, 0xAD, 0x41, 0x6B, 0x76, 0x8D, 0x3A, 0x2F, 0x80, 0xD2, 0x15, 0xBA, 0xB6, 0xEC, 0xA9, 0x66, 0xE7, 0xE3, + 0x54, 0xFB, 0xBF, 0x4E, 0x83, 0xC2, 0x5B, 0xDB, 0x9C, 0x81, 0x93, 0xF3, 0x84, 0x8D, 0x67, 0xC4, 0x40, 0x84, 0xE8, 0xC2, + 0xEC, 0x4F, 0xC9, 0x71, 0xF5, 0xE0, 0x98, 0xB5, 0x69, 0x0C, 0xB2, 0xEF, 0x6E, 0x01, 0x86, 0xF7, 0x8B, 0x0B, 0x67, 0x10, + 0x62, 0x89, 0x53, 0xB2, 0x6B, 0x66, 0xC9, 0x6D, 0xAF, 0x02, 0x37, 0xE0, 0xAD, 0xEF, 0xCF, 0xC7, 0xC0, 0xE7, 0xF6, 0x63, + 0xAF, 0xDC, 0x49, 0x7C, 0xFB, 0x83, 0x11, 0x35, 0x69, 0x21, 0x21, 0xCA, 0xEE, 0x9C, 0x80, 0x34, 0x80, 0x59, 0x65, 0x41, + 0x95, 0x32, 0x2E, 0xF2, 0x96, 0x92, 0x14, 0x6A, 0x53, 0x04, 0x36, 0x65, 0xAF, 0x08, 0x3F, 0xE9, 0xDB, 0xF2, 0x06, 0xEA, + 0x47, 0xB0, 0x18, 0xCA, 0xF2, 0x9A, 0x81, 0xC5, 0xF2, 0x0B, 0x91, 0xDB, 0x69, 0x82, 0xF6, 0xFE, 0x29, 0xF0, 0x8F, 0xD5, + 0xDA, 0x24, 0x37, 0x79, 0xEB, 0x56, 0x1A, 0x46, 0x69, 0x94, 0xF9, 0x4F, 0x4F, 0x93, 0xEE, 0x7C, 0xD5, 0xDC, 0xBD, 0x38, + 0x29, 0xF7, 0x1C, 0x0F, 0xD4, 0x2E, 0x34, 0x75, 0x79, 0xE5, 0xA8, 0xD7, 0x5E, 0x72, 0xBD, 0xB8, 0xFA, 0xB6, 0x42, 0xF4, + 0x1D, 0x6B, 0x52, 0xF8, 0xB5, 0xA0, 0x14, 0x5A, 0xA6, 0x72, 0xB8, 0xB9, 0x16, 0x4B, 0x20, 0xFF, 0x9E, 0x90, 0x0A, 0xEE, + 0x02, 0x40, 0xE1, 0x32, 0xBC, 0x71, 0xF0, 0x9D, 0x8B, 0x43, 0xCF, 0x1A, 0x1B, 0xFF, 0xC0, 0x39, 0x31, 0xC1, 0xF8, 0x4B, + 0x9B, 0xD4, 0x3C, 0x64, 0xE3, 0xED, 0xE4, 0xF6, 0x68, 0x88, 0xE0, 0x77, 0xA6, 0xE7, 0x4E, 0x13, 0xE5, 0xC1, 0xF3, 0x48, + 0xB0, 0xF2, 0x2C, 0x2E, 0xF0, 0x8B, 0xDA, 0x3E, 0xD9, 0x19, 0x9C, 0xCA, 0xD4, 0x10, 0x15, 0x60, 0x61, 0x3F, 0x12, 0xDB, + 0x52, 0x5D, 0x65, 0x6D, 0xA1, 0xCB, 0x50, 0x94, 0xD6, 0x2C, 0x90, 0x59, 0x7B, 0xEE, 0x95, 0xCF, 0x9F, 0xDA, 0x78, 0x76, + 0x13, 0xE4, 0x3C, 0x0F, 0x0D, 0x67, 0x05, 0x66, 0x04, 0x9B, 0x0B, 0x00, 0x32, 0x8C, 0x8A, 0xD3, 0x23, 0xDF, 0x0E, 0x2A, + 0xFD, 0x8D, 0x36, 0x20, 0xCB, 0xBE, 0x11, 0x16, 0xB1, 0x9A, 0x43, 0x4F, 0x67, 0x68, 0x18, 0x49, 0x86, 0x30, 0x6A, 0xBD, + 0x4B, 0x56, 0x3A, 0xB5, 0xB4, 0x9D, 0x17, 0x5E, 0x01, 0x2D, 0xF2, 0xDB, 0x22, 0x7A, 0xA9, 0xB5, 0x23, 0x1B, 0xB5, 0x6A, + 0x93, 0x3E, 0x4B, 0xC2, 0xEE, 0xD1, 0x1C, 0xB7, 0x1C, 0x68, 0xD7, 0xFE, 0x5A, 0xA1, 0x2C, 0x4E, 0x10, 0xE2, 0xD4, 0xFE, + 0x86, 0xA0, 0xEA, 0xFC, 0x13, 0x14, 0xC8, 0x54, 0x29, 0x71, 0x3B, 0x27, 0x4D, 0x98, 0x02, 0xC2, 0x67, 0x19, 0xD8, 0x1C, + 0x41, 0x37, 0x56, 0xFB, 0x9E, 0x0D, 0xBA, 0xB6, 0xCC, 0x97, 0xE3, 0x10, 0x0A, 0x16, 0xCD, 0xE0, 0x99, 0xF5, 0xEA, 0xED, + 0x77, 0xA6, 0x1E, 0x64, 0x45, 0x98, 0x3C, 0xFF, 0x33, 0x23, 0x1D, 0xE7, 0x04, 0xFC, 0xF0, 0x78, 0x20, 0x17, 0x87, 0x64, + 0xEA, 0x75, 0xE9, 0xDB, 0x6F, 0x34, 0xF5, 0xDA, 0x3A, 0x27, 0x3F, 0x38, 0x39, 0x58, 0x17, 0xE3, 0xB4, 0x5B, 0xD6, 0xCD, + 0x88, 0x26, 0x5A, 0x38, 0x1C, 0x7F, 0x97, 0xEB, 0xDF, 0x1A, 0x2B, 0x1E, 0x8D, 0x95, 0xF0, 0x69, 0xB8, 0xFE, 0x2E, 0x6A, + 0x66, 0x72, 0x6F, 0x2A, 0x12, 0x90, 0xDF, 0xFF, 0xA9, 0x20, 0x40, 0xB8, 0x15, 0xD1, 0x5F, 0xC9, 0x6F, 0x17, 0x61, 0xF0, + 0xFA, 0x6D, 0x15, 0xBF, 0x40, 0x9F, 0x71, 0x19, 0xF6, 0xBE, 0x13, 0xD1, 0x7C, 0x3E, 0xE3, 0xA7, 0xB6, 0x41, 0x9D, 0x6D, + 0xC9, 0x92, 0x21, 0x8A, 0x80, 0x9B, 0x5A, 0x0D, 0x19, 0x5D, 0xF4, 0xE0, 0x56, 0x4F, 0xB0, 0x3E, 0xC0, 0x93, 0xBF, 0x63, + 0xC8, 0x88, 0x71, 0xAA, 0x2C, 0x76, 0xF4, 0x97, 0x4A, 0x20, 0x9C, 0xE2, 0xC5, 0xEA, 0x21, 0x6E, 0x80, 0xF9, 0x00, 0xFC, + 0xFD, 0x06, 0x9B, 0x26, 0xA7, 0xE5, 0xDA, 0x82, 0x4F, 0x7A, 0x6B, 0x22, 0x42, 0x30, 0x6D, 0x27, 0x52, 0xFA, 0x24, 0x6C, + 0xA4, 0x09, 0x68, 0x96, 0xCC, 0x5C, 0xC7, 0x48, 0x33, 0x83, 0x14, 0x59, 0x9F, 0x20, 0x7B, 0x1E, 0x27, 0x84, 0x15, 0x83, + 0xCF, 0xE8, 0xA0, 0x5C, 0xAC, 0xDB, 0xC3, 0x68, 0x29, 0x9E, 0xA9, 0xF1, 0xA1, 0x85, 0xBB, 0x13, 0x7E, 0xFA, 0x76, 0x0A, + 0x32, 0xA6, 0x55, 0xA5, 0xD9, 0xEB, 0x57, 0x6A, 0x00, 0x74, 0x40, 0x78, 0x9A, 0x70, 0xD5, 0xE3, 0xC1, 0xD2, 0x74, 0x97, + 0x34, 0xC4, 0x56, 0x6E, 0x7B, 0x2A, 0x8F, 0x52, 0x7C, 0x33, 0xA9, 0xE4, 0x8F, 0xB6, 0x38, 0xF2, 0x62, 0x3A, 0xF0, 0x31, + 0x75, 0x39, 0x02, 0x58, 0x48, 0x0D, 0x21, 0xFD, 0x3D, 0x62, 0xA8, 0x43, 0x73, 0x19, 0xFA, 0x20, 0xFF, 0x54, 0x69, 0x49, + 0x73, 0x53, 0x9F, 0x01, 0x2C, 0x61, 0x99, 0xC0, 0x89, 0xEA, 0x50, 0x12, 0xAD, 0x77, 0x62, 0xD7, 0x41, 0xB3, 0x0A, 0xD5, + 0x4A, 0xC1, 0x36, 0xD3, 0xAB, 0xA9, 0xC6, 0x85, 0x29, 0x84, 0xCA, 0x00, 0xAE, 0xEB, 0xF2, 0xDA, 0x71, 0x64, 0xDC, 0x0A, + 0x5E, 0x8B, 0x43, 0xB8, 0x2F, 0x87, 0x23, 0x8B, 0x96, 0xCE, 0x10, 0x58, 0xA1, 0x63, 0x89, 0xC1, 0x69, 0x86, 0x54, 0x65, + 0x2A, 0x36, 0xE4, 0xC3, 0x9B, 0x11, 0x77, 0x5B, 0x99, 0x64, 0x7B, 0x4B, 0x5F, 0xA9, 0x1C, 0x73, 0xF7, 0x2F, 0x54, 0xBF, + 0xF6, 0xEC, 0x2C, 0xF8, 0x4A, 0x39, 0x8D, 0x10, 0xD3, 0x5A, 0x3C, 0x77, 0xE4, 0xFC, 0x8B, 0x50, 0xCF, 0xD9, 0x99, 0x65, + 0x91, 0x66, 0xFE, 0x0D, 0x43, 0x83, 0x70, 0xB8, 0xFE, 0x13, 0xBD, 0x7D, 0x9A, 0xE2, 0xD3, 0x55, 0x42, 0x1A, 0xBB, 0x6A, + 0xB5, 0x6D, 0xEA, 0x59, 0x7D, 0x7A, 0xCC, 0xAE, 0x03, 0x6D, 0x1C, 0x7F, 0xA4, 0x59, 0x99, 0x6F, 0xDC, 0x2F, 0x0F, 0x60, + 0x88, 0x1D, 0x47, 0xE0, 0xB9, 0x16, 0xF4, 0xCB, 0x0E, 0x74, 0x0B, 0x3D, 0x81, 0x66, 0xCA, 0x10, 0xF1, 0x1E, 0x6C, 0xE2, + 0x99, 0xAA, 0x1C, 0x99, 0x8C, 0x29, 0x2C, 0x3A, 0xF5, 0xEC, 0x5D, 0xA7, 0xA2, 0x09, 0x38, 0x74, 0x89, 0xF3, 0xFD, 0xD6, + 0xAC, 0xCB, 0xBD, 0xA2, 0x8B, 0x2D, 0xED, 0x12, 0x00, 0x93, 0x19, 0x13, 0xD0, 0xCD, 0x25, 0xBE, 0x0E, 0xCA, 0x87, 0x44, + 0xCD, 0x5C, 0x1D, 0xFD, 0x52, 0x41, 0x37, 0xFD, 0x4C, 0x2B, 0x75, 0x11, 0xA4, 0x21, 0x44, 0x99, 0x57, 0x94, 0xFC, 0x15, + 0x25, 0x60, 0x7C, 0xA4, 0xDC, 0x36, 0x9F, 0xED, 0xB9, 0x7A, 0x6E, 0x72, 0x71, 0xCC, 0x72, 0x47, 0xA4, 0x2A, 0x8D, 0x05, + 0x30, 0x43, 0xD5, 0xDD, 0x6A, 0x02, 0xAB, 0x57, 0xFE, 0xED, 0x69, 0x94, 0x26, 0x99, 0xB4, 0x7B, 0x12, 0x30, 0x1A, 0x02, + 0x35, 0x97, 0x02, 0x1F, 0xFE, 0xBA, 0x26, 0x8A, 0x2C, 0x9E, 0xEE, 0x8B, 0x43, 0x47, 0xEB, 0x55, 0x8D, 0x67, 0x27, 0x5D, + 0x08, 0x57, 0x96, 0x9A, 0x2D, 0x99, 0x6E, 0xEA, 0xA6, 0xB1, 0x68, 0xC9, 0x2E, 0x5B, 0x2B, 0x90, 0x19, 0xA4, 0x84, 0x61, + 0xAA, 0xB8, 0x37, 0xAF, 0x84, 0xF8, 0xE8, 0x54, 0xEA, 0xE3, 0xA0, 0x5C, 0x8C, 0x55, 0x2F, 0xE9, 0x2F, 0x4F, 0x2B, 0x62, + 0x4A, 0xFA, 0xC0, 0xC8, 0xEE, 0xB7, 0x53, 0x30, 0xFE, 0x08, 0xC5, 0x66, 0xF2, 0xEF, 0x66, 0xC2, 0x38, 0xFE, 0xD5, 0xDC, + 0xB2, 0x39, 0x89, 0x6A, 0x05, 0x95, 0x54, 0x29, 0xE9, 0x32, 0x02, 0x41, 0x3E, 0xDD, 0xFE, 0xBC, 0xFD, 0x89, 0x7A, 0x0F, + 0x1D, 0xDD, 0x40, 0xCD, 0x7E, 0xFA, 0x83, 0x30, 0x57, 0xAE, 0x09, 0xD8, 0x85, 0x5B, 0x37, 0x7E, 0x03, 0xF4, 0x89, 0x2A, + 0x65, 0x8F, 0xB1, 0x6F, 0xB7, 0xFD, 0x5C, 0xF4, 0x37, 0x74, 0x48, 0x4F, 0xDB, 0xFF, 0x59, 0x2D, 0x73, 0x00, 0x88, 0x81, + 0xB1, 0xAA, 0x3B, 0x53, 0x74, 0xC0, 0xDA, 0xCE, 0xF3, 0x66, 0xD7, 0x00, 0x07, 0xC3, 0x75, 0xF6, 0x93, 0x22, 0x38, 0x93, + 0xA0, 0xEE, 0x77, 0xD6, 0xD3, 0x29, 0xD8, 0x3D, 0xBB, 0xAC, 0xFE, 0xE7, 0x31, 0xA8, 0x6F, 0x1D, 0x88, 0x13, 0x47, 0x80, + 0x71, 0xE8, 0x98, 0x2E, 0x91, 0xD6, 0x3C, 0x77, 0xD0, 0xA3, 0x88, 0x0E, 0xF5, 0xBE, 0x81, 0x47, 0x72, 0x06, 0x0A, 0xBB, + 0x71, 0x04, 0xB8, 0xC6, 0x13, 0xE6, 0x99, 0x9F, 0xA3, 0xC2, 0x58, 0x67, 0xF3, 0xEC, 0x59, 0xA1, 0x71, 0x45, 0xBA, 0x2A, + 0xB0, 0x40, 0x4D, 0xEF, 0xB6, 0xCC, 0xF8, 0x16, 0x12, 0x61, 0x9C, 0x6D, 0xE9, 0x75, 0xFB, 0xA7, 0x10, 0x2E, 0x51, 0x9F, + 0x4F, 0xEB, 0xD5, 0x87, 0x50, 0x2E, 0xFE, 0x64, 0x77, 0xC6, 0x76, 0xB7, 0x11, 0x0F, 0x79, 0x9B, 0x2A, 0x56, 0xA1, 0xF7, + 0xD6, 0xAD, 0x03, 0x33, 0x10, 0x9D, 0xFA, 0x6E, 0x5B, 0x57, 0xBE, 0xBA, 0x08, 0x42, 0xEA, 0xAE, 0x5D, 0xB2, 0xF7, 0x68, + 0xBD, 0x00, 0xD0, 0x01, 0xBA, 0x2F, 0x63, 0x4E, 0xBE, 0xC2, 0x90, 0x38, 0xFA, 0x6F, 0x06, 0x8D, 0xC2, 0x09, 0xFB, 0x8F, + 0xBA, 0x28, 0x87, 0xD9, 0xF4, 0xBB, 0x91, 0xCF, 0x74, 0x67, 0x88, 0x76, 0xE8, 0x7C, 0xDB, 0x33, 0x38, 0xA1, 0x8E, 0x08, + 0xFD, 0x54, 0x13, 0xD1, 0xBA, 0x4B, 0x82, 0x20, 0x7B, 0xA1, 0x62, 0x2E, 0x5B, 0x6C, 0x48, 0x6A, 0xD8, 0x46, 0x88, 0x69, + 0xF9, 0x6A, 0xE6, 0x2A, 0xC1, 0x3C, 0xC1, 0xDE, 0x1E, 0x74, 0x58, 0x9E, 0xC6, 0x56, 0x52, 0x1C, 0x38, 0x96, 0x52, 0xE9, + 0x67, 0x4F, 0xBB, 0x3F, 0x9C, 0x35, 0x55, 0x81, 0xB9, 0x03, 0x5B, 0xA1, 0x79, 0x68, 0x35, 0x70, 0x6A, 0xA9, 0x91, 0x5C, + 0x38, 0x29, 0x3F, 0x1F, 0x01, 0x3E, 0xA3, 0x5A, 0xB8, 0x90, 0x4C, 0xC8, 0x43, 0x62, 0xBC, 0xD4, 0x31, 0x3F, 0x6A, 0x8C, + 0x03, 0x21, 0xEC, 0xC6, 0x31, 0x30, 0xAA, 0x7F, 0xDC, 0x7F, 0x86, 0x9C, 0x92, 0x54, 0xE3, 0x50, 0x67, 0xFC, 0x5B, 0xDA, + 0xF3, 0x92, 0x13, 0xAD, 0xA6, 0x50, 0xE5, 0x25, 0xF8, 0x3F, 0x03, 0x8D, 0x53, 0x9F, 0xED, 0x58, 0x47, 0x30, 0xE8, 0xD1, + 0xB1, 0xEF, 0xD7, 0x88, 0x12, 0x35, 0x1C, 0x4A, 0xE7, 0xD1, 0x8F, 0xC7, 0x52, 0x16, 0xD5, 0x53, 0x33, 0x1E, 0xBC, 0xA6, + 0x73, 0xB4, 0xC5, 0x02, 0xCE, 0xF9, 0xD6, 0x06, 0xF0, 0x3C, 0x6A, 0xE4, 0xAF, 0xB8, 0x96, 0xD5, 0x90, 0x33, 0x02, 0x12, + 0x67, 0xD0, 0x07, 0xAA, 0x0C, 0x9D, 0x0B, 0xD2, 0xCE, 0x52, 0xBD, 0x47, 0xB7, 0xB7, 0xC0, 0x03, 0x0B, 0xDC, 0x40, 0x75, + 0x51, 0x37, 0x07, 0x41, 0xE0, 0xC8, 0xC5, 0xB2, 0x10, 0x31, 0xEE, 0x13, 0x8B, 0xB6, 0x00, 0xFD, 0x12, 0xC8, 0xBB, 0xD7, + 0xC1, 0x49, 0xD6, 0x81, 0x99, 0xB2, 0x30, 0xD3, 0xCB, 0xF5, 0xCC, 0x53, 0xDB, 0x1D, 0xA2, 0x17, 0x2A, 0x09, 0xCA, 0x6C, + 0x63, 0x36, 0x7F, 0xC3, 0xCA, 0x5D, 0xC4, 0x43, 0xDA, 0x7F, 0x05, 0x7A, 0x94, 0xC7, 0xFF, 0x6F, 0x3A, 0x39, 0x12, 0x52, + 0xEE, 0xD8, 0xCD, 0xB8, 0x5B, 0x1F, 0xA4, 0xF6, 0x7C, 0xB6, 0xEF, 0xD9, 0xB6, 0x36, 0x5A, 0x49, 0xFF, 0xAA, 0xCF, 0x99, + 0x18, 0x74, 0x18, 0x2A, 0x2E, 0x5E, 0xCE, 0xEB, 0x99, 0x3A, 0x28, 0xDD, 0x9F, 0xFF, 0x16, 0x15, 0x51, 0xF1, 0xFA, 0xBA, + 0xD4, 0xB9, 0xAE, 0x9C, 0xD4, 0x30, 0x4D, 0xD9, 0x8C, 0x1C, 0x4F, 0xBA, 0x43, 0x7B, 0x87, 0xF1, 0x0B, 0xC1, 0xCF, 0x6A, + 0x5B, 0x31, 0xC5, 0x1A, 0x8E, 0xFE, 0x8E, 0x77, 0x1D, 0x32, 0xD9, 0xDF, 0x63, 0xDE, 0xC5, 0xDC, 0x18, 0x39, 0x3F, 0xBD, + 0x27, 0xD2, 0xFF, 0xA1, 0x5A, 0x1D, 0x38, 0x0B, 0xB9, 0x09, 0xD8, 0x56, 0x58, 0xAF, 0x8A, 0xD9, 0xCB, 0x16, 0xC8, 0xA4, + 0x51, 0xDB, 0x5A, 0xBC, 0x5D, 0x0C, 0xAC, 0xF4, 0x97, 0xA2, 0xAF, 0xD8, 0x80, 0x7C, 0x82, 0xD4, 0xD7, 0xA9, 0x94, 0x63, + 0xC4, 0xFF, 0xC1, 0xA7, 0xDE, 0x29, 0x39, 0x3E, 0xA7, 0xB3, 0xC9, 0xA5, 0xD1, 0x19, 0x57, 0x3E, 0x6E, 0x12, 0x6D, 0xE7, + 0xD9, 0xAC, 0x93, 0xC3, 0xF9, 0x62, 0x62, 0x27, 0x76, 0xE5, 0x71, 0xB1, 0x36, 0xEA, 0xE8, 0xC3, 0xB7, 0x2C, 0x4E, 0x4E, + 0x27, 0xC0, 0x88, 0xE4, 0x74, 0x91, 0x56, 0x7E, 0x66, 0x81, 0xEA, 0xB4, 0x95, 0xAD, 0x62, 0x70, 0x8D, 0xCA, 0x98, 0x32, + 0x58, 0xE8, 0x5F, 0x6A, 0x4C, 0xF7, 0x61, 0xA5, 0x37, 0x2E, 0x0F, 0x81, 0xD4, 0x8B, 0xC9, 0xB7, 0x28, 0xE9, 0x10, 0x20, + 0xB7, 0x0E, 0x29, 0x35, 0xD6, 0x87, 0x31, 0x6B, 0x2E, 0x96, 0xF3, 0x73, 0x74, 0xEA, 0x04, 0x06, 0x74, 0x2C, 0xC2, 0xAE, + 0x4C, 0x23, 0xA3, 0xC0, 0x89, 0x15, 0x3A, 0x2C, 0xFD, 0x62, 0x10, 0xE9, 0x39, 0x24, 0x65, 0x7C, 0x5C, 0x89, 0x3C, 0x16, + 0xA4, 0x98, 0x6E, 0x5C, 0x1E, 0x96, 0xA2, 0x37, 0x84, 0x7D, 0x27, 0xED, 0x1E, 0xE2, 0x99, 0x36, 0x4C, 0x24, 0x5C, 0xCD, + 0x5E, 0x09, 0xBA, 0x5C, 0x47, 0xDB, 0xD3, 0x9D, 0xBF, 0xDE, 0x49, 0x2B, 0x18, 0x46, 0xC3, 0x5D, 0x9C, 0xCB, 0x42, 0xC0, + 0x0F, 0x4C, 0x9A, 0x69, 0xBF, 0x24, 0x8A, 0x62, 0xA7, 0xBD, 0xF8, 0x6F, 0xFD, 0xEA, 0x7F, 0x77, 0x82, 0x20, 0xE2, 0xBC, + 0x9D, 0xA5, 0x69, 0x9C, 0xA6, 0x5C, 0x82, 0xFC, 0x5A, 0x74, 0x45, 0x63, 0xBA, 0x2A, 0xF3, 0xAD, 0x3F, 0x26, 0x8B, 0x83, + 0x2A, 0x63, 0x7B, 0x06, 0xBD, 0xCE, 0xFE, 0xC8, 0x96, 0x22, 0x2B, 0x3D, 0xDC, 0x10, 0xBB, 0x97, 0x4B, 0x62, 0x83, 0xFD, + 0xD6, 0x09, 0xB5, 0x92, 0xCF, 0x01, 0xEE, 0x78, 0x97, 0xBD, 0xF4, 0x26, 0xAE, 0x2F, 0xD4, 0xE6, 0x65, 0x70, 0xEC, 0x16, + 0x54, 0xEE, 0x24, 0x42, 0xD4, 0xBE, 0x44, 0xC4, 0x05, 0x87, 0xE3, 0x85, 0x94, 0x0E, 0x7F, 0x0C, 0xCC, 0xC3, 0xEF, 0x7C, + 0x17, 0xB4, 0xF5, 0x33, 0x2C, 0x2F, 0xCD, 0xD5, 0x0B, 0xB0, 0x12, 0x54, 0x3B, 0x9B, 0xCD, 0xD3, 0xA2, 0xBC, 0xFD, 0x37, + 0x60, 0xDE, 0x3D, 0x4E, 0x5F, 0x27, 0xC0, 0xA0, 0xD5, 0xF1, 0xEC, 0x70, 0x97, 0x3E, 0x0C, 0x60, 0x63, 0xA7, 0x14, 0xCB, + 0x56, 0x85, 0x57, 0x6E, 0xCC, 0x84, 0x8C, 0x96, 0x91, 0xB8, 0x26, 0xF6, 0xC4, 0xD3, 0xDC, 0x61, 0xD6, 0x79, 0x5D, 0xFE, + 0x4D, 0xA7, 0x62, 0x97, 0x97, 0xB9, 0x0D, 0x61, 0xEF, 0x16, 0x75, 0xE4, 0x46, 0xF0, 0x81, 0xA0, 0x9F, 0x31, 0xA7, 0xCA, + 0xF6, 0xB5, 0x71, 0xE3, 0xA7, 0xD8, 0xB7, 0xEA, 0x9C, 0xF8, 0x27, 0xD1, 0x91, 0x24, 0xC6, 0xCA, 0x53, 0x33, 0xC9, 0x2E, + 0x2E, 0xCE, 0x24, 0xB1, 0x10, 0x75, 0x39, 0xE0, 0xA0, 0xEF, 0x39, 0xFC, 0x7E, 0x55, 0x00, 0x96, 0x0C, 0x59, 0x12, 0x2D, + 0x72, 0xF1, 0x19, 0xA7, 0xEC, 0x35, 0x32, 0x6D, 0x3E, 0xB3, 0x88, 0x49, 0xA4, 0x8B, 0xC9, 0x97, 0x15, 0x6B, 0x67, 0x93, + 0x7C, 0xE6, 0xA5, 0x97, 0x1E, 0xB6, 0x67, 0xE9, 0xC9, 0xDD, 0x3F, 0xFE, 0x62, 0x56, 0xAF, 0x3A, 0xAE, 0x83, 0x9E, 0x4C, + 0x3F, 0xBB, 0x16, 0xAB, 0x93, 0x57, 0x77, 0xDC, 0x1E, 0xAC, 0x6C, 0x32, 0xAF, 0x99, 0xD4, 0x3C, 0xBD, 0xB5, 0xC5, 0x98, + 0x2E, 0x9D, 0xB4, 0xE3, 0x6D, 0xB2, 0x79, 0xE3, 0x3C, 0x96, 0xBD, 0xD2, 0x1D, 0xDB, 0x71, 0x09, 0x6C, 0xF6, 0xAE, 0xBE, + 0x59, 0xF3, 0xAE, 0x9C, 0x4E, 0x39, 0x29, 0xCF, 0x1C, 0xB9, 0x07, 0x99, 0xAE, 0xFF, 0x9F, 0xFD, 0x2D, 0xF2, 0x59, 0x54, + 0xA7, 0x4D, 0x86, 0x30, 0xF9, 0xE1, 0x49, 0xBA, 0xA4, 0x2A, 0x5C, 0x11, 0x84, 0x71, 0x0A, 0x6F, 0x40, 0x08, 0x7F, 0x66, + 0xFA, 0xE0, 0x41, 0xAA, 0xA5, 0xCB, 0x09, 0x2F, 0x6D, 0x15, 0xFE, 0xD1, 0x23, 0x09, 0x2D, 0x97, 0x92, 0x2A, 0x31, 0x35, + 0x8A, 0x28, 0x36, 0x0C, 0xF4, 0x96, 0xF1, 0x93, 0x01, 0x55, 0xE9, 0xA6, 0xCB, 0x2E, 0xAE, 0xF4, 0xB6, 0x43, 0x8A, 0xC5, + 0xA9, 0x92, 0x70, 0x2E, 0xA1, 0x61, 0xFD, 0xD4, 0xF9, 0x0E, 0x2E, 0x67, 0xE3, 0x06, 0x5D, 0x79, 0xD2, 0x33, 0xF3, 0x30, + 0x0F, 0xAE, 0x68, 0x26, 0x71, 0x82, 0xD7, 0xF4, 0x4E, 0x03, 0x4F, 0x9E, 0xF6, 0x6C, 0xFC, 0xA3, 0x69, 0x25, 0x9B, 0x9B, + 0xE6, 0x89, 0xDD, 0x6F, 0x4D, 0xEB, 0xEB, 0x9A, 0xB1, 0x42, 0x1D, 0xAE, 0x85, 0x2E, 0x09, 0x10, 0x57, 0x8A, 0x51, 0x75, + 0x6A, 0x54, 0xC0, 0x85, 0xD7, 0x96, 0x3A, 0x5A, 0x4B, 0xF8, 0x7D, 0x7F, 0x7C, 0x44, 0x25, 0xF8, 0x3B, 0x48, 0x52, 0x4D, + 0xB2, 0x65, 0x72, 0x9A, 0x89, 0x5F, 0x06, 0xAF, 0xB8, 0x86, 0x0C, 0x5A, 0xB6, 0x94, 0x86, 0xCF, 0x2D, 0xC2, 0x01, 0x8B, + 0x66, 0x1E, 0x64, 0xCD, 0xC7, 0x68, 0xD3, 0x34, 0xFC, 0xB7, 0xED, 0x89, 0x55, 0xCC, 0x33, 0xC9, 0xD5, 0x8B, 0x9A, 0x3A, + 0x38, 0x84, 0xCF, 0xC7, 0x34, 0xCA, 0x0C, 0x20, 0xEA, 0x4D, 0x6F, 0x2A, 0xF5, 0xA1, 0x0A, 0xC8, 0x17, 0x0A, 0x6C, 0xA8, + 0x4C, 0x24, 0xAC, 0x6A, 0xBB, 0xEF, 0xC8, 0xDC, 0x22, 0x31, 0xB4, 0x98, 0xF2, 0xD5, 0xF6, 0xFC, 0x46, 0x41, 0x21, 0x8C, + 0x94, 0x9C, 0x17, 0x8E, 0x54, 0x06, 0x8B, 0x5D, 0x23, 0xAE, 0xF2, 0xED, 0xC7, 0x91, 0xA1, 0x9E, 0x56, 0x63, 0x75, 0xF8, + 0x28, 0xA2, 0x27, 0xCF, 0xCD, 0x27, 0x13, 0x7D, 0x62, 0x5C, 0xA5, 0x7B, 0x3A, 0xEC, 0xD9, 0x81, 0x40, 0x76, 0xE4, 0xC6, + 0xC1, 0x72, 0x0C, 0xA5, 0x81, 0xFF, 0x98, 0x20, 0x59, 0x75, 0xF5, 0x14, 0x7D, 0x33, 0x38, 0xF6, 0xE0, 0xEC, 0x22, 0x84, + 0x41, 0x5C, 0x61, 0xFA, 0x84, 0x2D, 0x78, 0xFB, 0xC2, 0x16, 0x09, 0x2F, 0x11, 0xED, 0x1E, 0xD3, 0x0B, 0x93, 0xAD, 0x5B, + 0x5C, 0x7F, 0x73, 0x30, 0xE2, 0xF3, 0xA6, 0x6A, 0xCA, 0x13, 0xD9, 0x35, 0xEC, 0x3D, 0xC4, 0x2D, 0x54, 0x8C, 0x35, 0x44, + 0x0B, 0xA3, 0xA2, 0x88, 0x31, 0x3C, 0x6C, 0x0F, 0xEF, 0x16, 0xB4, 0x53, 0x6C, 0x79, 0xA0, 0x4F, 0x22, 0xD5, 0x37, 0x26, + 0x12, 0x96, 0x62, 0xAD, 0x65, 0x3D, 0xE4, 0x0F, 0xFC, 0xA3, 0x7D, 0x3E, 0x4B, 0x75, 0x05, 0xB0, 0x9D, 0x3B, 0xD9, 0xA6, + 0xE3, 0x5D, 0x2E, 0x67, 0x10, 0x36, 0x8D, 0xB0, 0x59, 0xBA, 0x97, 0xD2, 0xB5, 0xDE, 0xFC, 0x9A, 0x5C, 0x39, 0xD5, 0xD4, + 0x71, 0x10, 0x1E, 0x9D, 0xC1, 0x3B, 0x46, 0x49, 0x54, 0xA4, 0x2C, 0x53, 0x6E, 0xE0, 0xA8, 0x90, 0xF5, 0x8E, 0x1B, 0x68, + 0xF9, 0xE8, 0xA1, 0xE3, 0x8E, 0xA4, 0xDF, 0x49, 0x59, 0x59, 0x9F, 0x54, 0x59, 0x34, 0x7D, 0xE9, 0xAC, 0x54, 0x3C, 0xD7, + 0x61, 0xC7, 0xC8, 0xDA, 0xB9, 0x53, 0x9F, 0xA0, 0xD8, 0x38, 0xCF, 0xED, 0x22, 0xB6, 0x9D, 0x9D, 0x46, 0xB6, 0x61, 0x90, + 0x69, 0x39, 0x0A, 0x52, 0x18, 0x28, 0x92, 0x2A, 0x9A, 0x8D, 0x98, 0xAE, 0xC1, 0xB7, 0x96, 0xAD, 0xE7, 0x54, 0x2D, 0x04, + 0xA8, 0x3E, 0x06, 0xDD, 0x54, 0xE2, 0xF4, 0x6C, 0xD9, 0x92, 0x66, 0x68, 0x80, 0xA5, 0xBE, 0x5B, 0x88, 0x70, 0xFD, 0x0E, + 0x60, 0x7D, 0x47, 0xF1, 0x51, 0x7A, 0xD1, 0x6D, 0xE7, 0x81, 0x49, 0xC6, 0xF9, 0x9C, 0xDF, 0xEF, 0x85, 0xEA, 0x6B, 0xA6, + 0x18, 0xB4, 0x05, 0x23, 0x9F, 0xF0, 0x24, 0x7F, 0x19, 0x9F, 0x40, 0xB5, 0x9C, 0x8F, 0xB5, 0x74, 0xEF, 0x55, 0x28, 0xD1, + 0x67, 0x1D, 0x0A, 0xB6, 0x3D, 0xB1, 0x02, 0xC2, 0x59, 0x01, 0x64, 0x23, 0xC1, 0xB0, 0xA8, 0xC3, 0x29, 0xB1, 0x02, 0xC5, + 0x29, 0x8D, 0x41, 0x01, 0x1A, 0x8F, 0xB4, 0x39, 0xA4, 0xE0, 0x63, 0x00, 0x2F, 0x3B, 0xE9, 0x36, 0xE7, 0x06, 0x49, 0xA4, + 0x11, 0x8C, 0x0E, 0x3E, 0x68, 0x3C, 0x59, 0x80, 0x7E, 0x81, 0x79, 0x56, 0x7C, 0x61, 0xF3, 0x22, 0x14, 0xE8, 0x64, 0x34, + 0xFD, 0x5C, 0x2A, 0xBC, 0x32, 0x6B, 0x86, 0x95, 0xDA, 0x39, 0xDF, 0x6E, 0x01, 0x4E, 0x79, 0x16, 0x1B, 0x28, 0x06, 0x75, + 0xE6, 0x87, 0x86, 0x70, 0xB6, 0x66, 0x07, 0xF3, 0x85, 0xE4, 0xDF, 0x86, 0x19, 0x20, 0xD1, 0x11, 0xA4, 0x61, 0x89, 0x97, + 0x9A, 0x17, 0x15, 0x2D, 0x6C, 0xA4, 0x97, 0x96, 0x91, 0xCF, 0xF5, 0x7D, 0x48, 0x6A, 0x8B, 0x84, 0x5B, 0xEA, 0x42, 0x08, + 0x92, 0x85, 0x9C, 0x26, 0x7C, 0xA8, 0xBE, 0xDB, 0xB1, 0xC7, 0xCC, 0x9E, 0x37, 0x8B, 0xDC, 0x15, 0xAE, 0x04, 0x6A, 0x5B, + 0xF7, 0x74, 0xB6, 0xCB, 0xB0, 0xC6, 0x84, 0x07, 0xD0, 0x4F, 0x69, 0x16, 0xCC, 0x8C, 0x5C, 0x7D, 0xEE, 0x75, 0x53, 0x98, + 0x7B, 0x88, 0x4C, 0x5D, 0x37, 0x5B, 0xD4, 0x64, 0xFE, 0x8B, 0xD3, 0x38, 0x60, 0xA4, 0x05, 0x26, 0xAC, 0x57, 0x2C, 0x7F, + 0xD9, 0xC7, 0xCE, 0xD9, 0x20, 0x86, 0x1E, 0x3C, 0xBD, 0x53, 0x3E, 0xEE, 0x43, 0x8A, 0x09, 0x9E, 0xC5, 0x1D, 0x4C, 0x66, + 0x2D, 0x2D, 0x6D, 0x1D, 0x3A, 0xEC, 0x44, 0xBE, 0x49, 0xA5, 0x8C, 0x8D, 0xD3, 0x30, 0xE1, 0x58, 0xA4, 0xED, 0xE5, 0x03, + 0x17, 0xE7, 0x7B, 0x6F, 0x67, 0xDD, 0x8D, 0x69, 0x3F, 0x6D, 0x7C, 0x4A, 0xFB, 0xAA, 0xD1, 0xA0, 0x62, 0xC3, 0xDA, 0xFF, + 0x8E, 0xA7, 0x83, 0x00, 0xFC, 0x4C, 0x70, 0x60, 0x78, 0x67, 0x75, 0x78, 0x5F, 0xBF, 0x0A, 0x96, 0x62, 0xB8, 0x4D, 0x99, + 0x52, 0x50, 0x2E, 0xE0, 0x16, 0x19, 0x84, 0xEC, 0x33, 0xF3, 0x33, 0x4F, 0x8C, 0x49, 0x1B, 0x17, 0x94, 0xCE, 0x27, 0x54, + 0x84, 0xA3, 0xA7, 0xF4, 0xD0, 0xB4, 0xD9, 0x5A, 0xEC, 0x90, 0x65, 0x23, 0xC3, 0x33, 0xD5, 0xD5, 0xE1, 0x95, 0xBE, 0xE9, + 0x16, 0xD6, 0x25, 0xA2, 0x04, 0x7C, 0xC4, 0x4D, 0x0E, 0x2C, 0x34, 0xE6, 0xDB, 0xF8, 0xC3, 0x42, 0x5B, 0x1F, 0xD4, 0x90, + 0x04, 0x73, 0xCC, 0x1D, 0xA0, 0xFC, 0x50, 0x7F, 0x21, 0xFD, 0x30, 0xB4, 0x57, 0x55, 0x34, 0x76, 0x6A, 0xF3, 0xA5, 0x68, + 0x71, 0x1C, 0x03, 0x9F, 0xA7, 0xD6, 0xDD, 0x39, 0xB0, 0x5F, 0xB5, 0xA6, 0x22, 0x7B, 0x74, 0x65, 0x58, 0x09, 0x91, 0xB1, + 0x84, 0xF7, 0x93, 0xD1, 0x56, 0x34, 0x35, 0xE3, 0x5E, 0x57, 0xC8, 0xB7, 0xB3, 0xF1, 0x06, 0xD6, 0x8D, 0x14, 0x19, 0x6C, + 0x74, 0x79, 0x27, 0x59, 0x54, 0x9A, 0x76, 0x2E, 0x79, 0xE3, 0xEA, 0x1C, 0x5D, 0x9A, 0x51, 0xEC, 0xD6, 0x21, 0x46, 0xC9, + 0x5D, 0x9B, 0x17, 0xC0, 0xE8, 0x85, 0xE3, 0x0E, 0xEF, 0xFA, 0x87, 0x19, 0xD7, 0x4A, 0xBB, 0x5E, 0x05, 0xEB, 0x31, 0x2B, + 0xF6, 0xF1, 0x3C, 0x93, 0xE7, 0x11, 0x2F, 0x6B, 0xC5, 0xF9, 0xB3, 0x4F, 0x10, 0xD4, 0x00, 0xF0, 0xFB, 0xD2, 0xE1, 0xC8, + 0xD3, 0x61, 0x94, 0x3D, 0xB2, 0x61, 0x08, 0x2A, 0x87, 0xF6, 0x80, 0x0D, 0x1D, 0xDC, 0x95, 0xEA, 0xFC, 0x32, 0xD6, 0xEE, + 0xB7, 0xA2, 0x74, 0xBF, 0xE0, 0x9F, 0x7E, 0x1E, 0xE3, 0xBC, 0x71, 0xA9, 0xC6, 0x93, 0x9F, 0x4B, 0xD3, 0xD5, 0xB7, 0xAE, + 0x7A, 0x9C, 0x8F, 0xF2, 0x03, 0x77, 0xCF, 0xA9, 0xCD, 0x38, 0xB5, 0xDD, 0x18, 0x1F, 0xF3, 0xB9, 0xEE, 0x5F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xA3, 0xA5, 0xDC, 0x83, 0x34, 0x66, 0xFB, 0xC1, 0xD0, 0xA4, 0xAD, 0x4E, 0xAE, 0x11, 0xF3, 0x10, 0xAD, 0xA5, + 0xE0, 0xAE, 0x19, 0x64, 0x91, 0x3E, 0xE3, 0xF2, 0xE0, 0xFE, 0xA6, 0x1C, 0xF6, 0x71, 0x22, 0xB0, 0x58, 0xC1, 0x2D, 0x96, + 0xAC, 0x8F, 0x29, 0xDE, 0x43, 0x4F, 0x95, 0xEF, 0xE3, 0x27, 0x5C, 0x62, 0xEF, 0x81, 0xB7, 0x21, 0xF0, 0x27, 0x71, 0x53, + 0x32, 0x2D, 0xA7, 0x1C, 0x76, 0x78, 0xED, 0x32, 0xB9, 0xFB, 0x23, 0x86, 0x96, 0x2A, 0x6E, 0x01, 0xE1, 0xEF, 0xEE, 0xC5, + 0x98, 0x95, 0x99, 0xA0, 0xFC, 0x0A, 0x92, 0x51, 0x7B, 0xE6, 0xF4, 0xE2, 0x0F, 0x4D, 0xBE, 0x48, 0xB8, 0x66, 0x9C, 0x79, + 0x00, 0xD2, 0x65, 0xA7, 0xDA, 0x05, 0x05, 0x60, 0x2B, 0x65, 0xAF, 0xC4, 0x3B, 0x65, 0xFD, 0x9E, 0x70, 0xDC, 0xB7, 0xE1, + 0x72, 0x84, 0xD9, 0x10, 0x89, 0xE3, 0x75, 0x0A, 0x19, 0x44, 0xFD, 0x7B, 0x32, 0x64, 0xE3, 0xCC, 0x5C, 0x8C, 0xD2, 0xA9, + 0x17, 0x40, 0x75, 0x5F, 0x6C, 0x27, 0xA7, 0x6B, 0x6B, 0xA8, 0x1F, 0x6F, 0x7D, 0x2A, 0x9E, 0xC5, 0x41, 0x08, 0x0A, 0x4E, + 0xB2, 0x00, 0xE4, 0x49, 0x8C, 0x2A, 0x11, 0x21, 0x50, 0xCB, 0x95, 0x5A, 0xFA, 0x41, 0x92, 0x5E, 0xE4, 0x25, 0x5E, 0xEA, + 0x0D, 0x86, 0x35, 0x0C, 0x78, 0x84, 0xDB, 0xA8, 0xC7, 0xFE, 0xCB, 0x21, 0x89, 0x6D, 0xD7, 0xE8, 0x5E, 0x4C, 0x94, 0xBF, + 0x70, 0x04, 0x80, 0x6E, 0x82, 0xEF, 0x69, 0xFF, 0x78, 0x64, 0x13, 0xDD, 0xAE, 0xB2, 0xAA, 0x42, 0x66, 0x22, 0x00, 0x4F, + 0x23, 0x6E, 0x25, 0x83, 0xB2, 0x6E, 0x98, 0xD8, 0x6B, 0x71, 0x61, 0xA5, 0x4E, 0xE3, 0xF7, 0x4E, 0x6B, 0xB1, 0x52, 0x1E, + 0xF0, 0xEF, 0xF6, 0x1E, 0x51, 0x05, 0x7C, 0x81, 0x9D, 0x74, 0x25, 0x7F, 0x2A, 0xCC, 0x89, 0x82, 0x2C, 0x03, 0x46, 0x25, + 0xC9, 0xD3, 0x72, 0x77, 0xBC, 0x3D, 0x45, 0x12, 0x68, 0x30, 0xD0, 0x9A, 0xAC, 0xF3, 0x5A, 0x28, 0xCA, 0x75, 0x1A, 0x6C, + 0x31, 0x73, 0x49, 0xB1, 0x39, 0xAA, 0xBF, 0x15, 0x90, 0x0E, 0x12, 0x72, 0x24, 0xBF, 0xFA, 0xBB, 0xD4, 0xC7, 0xCA, 0xA0, + 0xC4, 0xF2, 0x36, 0x00, 0x28, 0x31, 0x35, 0x6A, 0xA7, 0xA8, 0x0A, 0xB9, 0x44, 0xBF, 0x1D, 0x95, 0x00, 0xFC, 0x20, 0xF2, + 0x3B, 0x7A, 0xE7, 0xC2, 0x64, 0x49, 0x14, 0xCC, 0x97, 0x9B, 0xD4, 0x0E, 0xD9, 0x4B, 0xAA, 0x44, 0x74, 0x1C, 0x0E, 0xBE, + 0x42, 0x75, 0xF4, 0x2E, 0xF2, 0xBF, 0x74, 0x92, 0x9E, 0x59, 0x08, 0x0E, 0x88, 0x37, 0xE9, 0x53, 0x9E, 0x1C, 0x11, 0x47, + 0x32, 0xAC, 0x95, 0x61, 0xE7, 0x8B, 0x48, 0xDB, 0xD4, 0x83, 0x32, 0x8B, 0x5E, 0x8B, 0x4A, 0x24, 0x10, 0xB7, 0x65, 0x19, + 0xB3, 0x1A, 0x9D, 0xB1, 0x06, 0x7B, 0x9A, 0x97, 0x16, 0x1E, 0xFF, 0x5C, 0x9B, 0x24, 0x07, 0x5B, 0x50, 0xF7, 0xDE, 0x91, + 0x91, 0xFB, 0xA2, 0x68, 0x75, 0xEF, 0xA4, 0x4C, 0x65, 0x21, 0x47, 0x22, 0x8C, 0xA6, 0x9C, 0x52, 0x7F, 0x52, 0xF3, 0x72, + 0x09, 0xE5, 0x9E, 0x7E, 0xDC, 0xC7, 0x86, 0x5A, 0xD4, 0x25, 0xDD, 0xAC, 0x07, 0x87, 0xF0, 0xEB, 0x6B, 0x1B, 0xF1, 0xA8, + 0x36, 0x96, 0xA2, 0xFE, 0x37, 0x53, 0xEB, 0xD3, 0x5A, 0xD6, 0xC1, 0x38, 0x29, 0x8D, 0xF4, 0xDF, 0x99, 0xAD, 0xAD, 0xE0, + 0xCF, 0x23, 0xEE, 0x93, 0xFB, 0x71, 0xED, 0x2B, 0xA7, 0xA0, 0x49, 0x2D, 0x98, 0xBD, 0x23, 0x12, 0xE8, 0x50, 0x1E, 0xB9, + 0x46, 0x73, 0x39, 0xCF, 0x4B, 0x9D, 0xB9, 0xF4, 0x4B, 0xB4, 0xFE, 0x97, 0x7F, 0xD3, 0x64, 0x4D, 0x06, 0x5D, 0x37, 0xD4, + 0x2B, 0x08, 0xFD, 0xCE, 0x18, 0xEE, 0xA0, 0x3B, 0x4A, 0x80, 0xE7, 0x02, 0x78, 0x72, 0x76, 0xA7, 0x02, 0x02, 0x32, 0xF5, + 0x78, 0xCE, 0xE1, 0xDA, 0x44, 0x82, 0x13, 0xE0, 0xF5, 0x8C, 0x56, 0x14, 0xEC, 0xE2, 0x96, 0x22, 0x74, 0xA5, 0x83, 0x70, + 0xE4, 0x3C, 0xE6, 0x53, 0x5D, 0xE2, 0xF5, 0x70, 0xE6, 0x33, 0x9F, 0x32, 0x56, 0x5D, 0xB6, 0x0F, 0x25, 0x7D, 0xD3, 0xB6, + 0xD5, 0x82, 0x7A, 0xE0, 0x09, 0x8E, 0xCB, 0x08, 0x94, 0x63, 0x11, 0x51, 0x2C, 0xB0, 0x7D, 0xF2, 0xD3, 0x98, 0xB7, 0xB2, + 0x81, 0xF5, 0x72, 0xC4, 0xC2, 0x35, 0xD3, 0x91, 0xCA, 0x39, 0x4F, 0xF5, 0x2E, 0x39, 0xCB, 0xA1, 0x8B, 0x88, 0x79, 0x49, + 0x2B, 0x18, 0x5E, 0xC3, 0xCB, 0xA0, 0x4B, 0x4E, 0xAB, 0x54, 0x1F, 0x45, 0x67, 0x05, 0x5E, 0xA5, 0xB2, 0x72, 0x09, 0x70, + 0xA0, 0x82, 0x97, 0x5F, 0xD5, 0x66, 0x90, 0x14, 0x51, 0x8D, 0xF1, 0x4B, 0xA4, 0x1C, 0xCD, 0x11, 0x2C, 0x84, 0x55, 0x08, + 0x1D, 0x56, 0x5D, 0x8E, 0x77, 0xE1, 0xFC, 0x3A, 0x40, 0x03, 0xF2, 0xBB, 0x3A, 0xC6, 0x40, 0x51, 0x34, 0xE5, 0x3C, 0xB3, + 0xE6, 0xCD, 0xBC, 0xEE, 0x8D, 0x58, 0xC1, 0x7D, 0x4B, 0xEB, 0xC4, 0x38, 0xBC, 0x6A, 0x84, 0xA7, 0x65, 0x49, 0x35, 0xF0, + 0xBC, 0x9B, 0x0B, 0xD4, 0x4F, 0xC7, 0xA5, 0x4D, 0xBC, 0xF4, 0x11, 0xAA, 0xE7, 0xC9, 0xD5, 0x19, 0x7C, 0x28, 0xF4, 0xFB, + 0xDD, 0x66, 0x20, 0xCC, 0x51, 0xA9, 0xA2, 0x24, 0x6F, 0xEC, 0x5A, 0xBD, 0x38, 0xBC, 0x8F, 0x18, 0xF9, 0xF3, 0x0D, 0x10, + 0x94, 0x7D, 0x6F, 0xAA, 0x39, 0x1C, 0xCA, 0x93, 0x9F, 0x3D, 0x28, 0x80, 0xB4, 0x8F, 0x9C, 0x47, 0xB4, 0xCE, 0x1C, 0x11, + 0x37, 0x12, 0x5B, 0xBC, 0xB0, 0xA8, 0x0A, 0x55, 0xE0, 0x3B, 0x08, 0x28, 0x37, 0xCD, 0x15, 0x5D, 0x6E, 0x0C, 0xB2, 0xB3, + 0x3A, 0x00, 0x3B, 0x3F, 0x2E, 0xB4, 0xC5, 0xDF, 0x15, 0x7E, 0x89, 0xFD, 0xB9, 0xCF, 0x32, 0x15, 0x0C, 0x1D, 0xB4, 0x83, + 0xA0, 0x2C, 0xAC, 0x8B, 0x14, 0x6B, 0xFD, 0x68, 0xDE, 0x4E, 0x92, 0xA2, 0x54, 0xB5, 0xFB, 0xCD, 0xEA, 0x57, 0xC4, 0x89, + 0x17, 0x24, 0x1F, 0x68, 0x17, 0x67, 0xB4, 0xF7, 0x34, 0xAD, 0x88, 0xFC, 0xE2, 0x99, 0x75, 0x46, 0x16, 0xAF, 0xED, 0x13, + 0xA0, 0x0E, 0xCC, 0xD7, 0xF1, 0x17, 0xB9, 0xF3, 0xA9, 0x5E, 0x69, 0x8C, 0xD3, 0x66, 0xF4, 0x40, 0xA6, 0x8D, 0x9A, 0xFB, + 0xCA, 0xC5, 0xB4, 0x62, 0xBF, 0x96, 0x0F, 0x62, 0x74, 0x48, 0xF2, 0xB0, 0xDC, 0x48, 0xE3, 0xB4, 0x39, 0xD7, 0xBC, 0x93, + 0xAC, 0xD9, 0xD8, 0xD0, 0x57, 0x64, 0x5D, 0x3D, 0x24, 0x92, 0x56, 0xEB, 0x34, 0xB2, 0x69, 0x30, 0x1B, 0xD9, 0x65, 0xC7, + 0xCA, 0xB6, 0x13, 0x76, 0x5E, 0x38, 0x29, 0x07, 0xBF, 0x0E, 0xD9, 0xB1, 0x63, 0xDA, 0x7D, 0xF4, 0x53, 0x5C, 0x0E, 0xE8, + 0xD5, 0x94, 0x34, 0xA6, 0xF4, 0x59, 0x48, 0x9E, 0x87, 0x39, 0xE2, 0x46, 0x74, 0xBA, 0x91, 0xD8, 0x8C, 0x6C, 0x13, 0x1A, + 0x3B, 0x28, 0x5E, 0xD5, 0x6B, 0x9B, 0x1D, 0x1B, 0xA5, 0xBA, 0x1F, 0xF5, 0x2D, 0x97, 0xB2, 0x0B, 0xD9, 0xBC, 0x23, 0x5A, + 0xEA, 0x13, 0xF3, 0x4F, 0x20, 0x79, 0xFA, 0x1F, 0xA3, 0x57, 0x91, 0xAB, 0x1E, 0xDE, 0x2C, 0xD9, 0x06, 0x1A, 0x9C, 0x1E, + 0xE1, 0xFF, 0x34, 0x3B, 0x44, 0x98, 0xFE, 0xDE, 0x0D, 0x0A, 0x89, 0x1A, 0x5F, 0x7D, 0x64, 0xEE, 0xB6, 0x76, 0xCD, 0xED, + 0x4C, 0x99, 0x56, 0x2D, 0x1D, 0xAD, 0x2C, 0xE4, 0x84, 0xB9, 0xC0, 0xD2, 0xF2, 0x5B, 0x39, 0x7F, 0x2A, 0x98, 0xC7, 0xCB, + 0x8D, 0xC8, 0x23, 0x18, 0x6A, 0x53, 0x61, 0x9D, 0x15, 0xAF, 0x17, 0x59, 0x7B, 0xA6, 0x57, 0x2C, 0x95, 0xD3, 0x47, 0x05, + 0x62, 0x22, 0x33, 0x3F, 0x85, 0xBD, 0x9A, 0xEA, 0x63, 0x09, 0xD9, 0x3E, 0x16, 0xEB, 0x2B, 0x91, 0x24, 0xEF, 0x9C, 0xC9, + 0x71, 0x3B, 0xED, 0xAC, 0xEA, 0x65, 0x37, 0xF6, 0x72, 0xE5, 0x66, 0x19, 0xB4, 0xE2, 0x2E, 0xB0, 0x2C, 0xA2, 0x96, 0xF2, + 0x04, 0x89, 0x4A, 0x81, 0xFD, 0xF9, 0x83, 0x5E, 0xA8, 0x73, 0x27, 0xD8, 0xF1, 0xB9, 0x31, 0xEF, 0x2D, 0x0E, 0x18, 0xFF, + 0x60, 0x6C, 0x08, 0xC2, 0xF1, 0xE3, 0xA7, 0xE5, 0xB1, 0xBC, 0x16, 0x5A, 0x60, 0x46, 0x77, 0x6C, 0x14, 0x8D, 0xDE, 0x99, + 0xEF, 0x06, 0x4E, 0x90, 0x31, 0x44, 0x31, 0x6F, 0x6D, 0xD0, 0xDF, 0x2A, 0xD9, 0xB4, 0xD8, 0xB6, 0x1F, 0x46, 0x58, 0x85, + 0x6B, 0x7F, 0x97, 0x5A, 0x63, 0x39, 0x50, 0x02, 0x6F, 0x80, 0x8C, 0x07, 0x3F, 0x4F, 0xA9, 0x41, 0xB9, 0x77, 0x9B, 0xD5, + 0x81, 0xBB, 0x81, 0x41, 0x47, 0xB6, 0xD8, 0x74, 0xE1, 0x67, 0x80, 0x4E, 0xD5, 0xA4, 0xFD, 0xF9, 0xAB, 0x48, 0xA2, 0x45, + 0xA1, 0xA7, 0x83, 0x2A, 0xAA, 0x0A, 0xEC, 0x11, 0xB9, 0xC7, 0x12, 0xEB, 0x8D, 0xA4, 0xB2, 0x2C, 0x4F, 0x86, 0xE7, 0xD4, + 0x49, 0xB2, 0xFC, 0xF9, 0x5A, 0xE3, 0x3D, 0x25, 0x68, 0x8B, 0xDB, 0x5C, 0x25, 0x8B, 0x89, 0x96, 0x21, 0x20, 0x00, 0x5E, + 0xAC, 0x06, 0x73, 0xA9, 0x65, 0xA4, 0x2B, 0x6F, 0xFB, 0x8C, 0x03, 0xC5, 0x25, 0x09, 0xA5, 0x9C, 0xB1, 0x66, 0x1B, 0xF3, + 0xFF, 0x43, 0x65, 0x75, 0x82, 0x7D, 0x53, 0x48, 0x16, 0xEC, 0x28, 0xE8, 0x34, 0x49, 0x95, 0x58, 0x7C, 0x8D, 0xDF, 0xD8, + 0x72, 0x7C, 0xD9, 0xFC, 0x60, 0x8F, 0x92, 0x41, 0xD9, 0x8A, 0x42, 0x36, 0x2D, 0x4F, 0xEC, 0x26, 0x43, 0xDB, 0x93, 0x61, + 0xCA, 0x4A, 0x7F, 0xE9, 0xD0, 0x94, 0x8B, 0xB5, 0x31, 0x09, 0x67, 0x22, 0x51, 0xDE, 0x7B, 0x70, 0xF8, 0xBF, 0x03, 0x1F, + 0x68, 0x0A, 0x92, 0x73, 0x10, 0xBF, 0x1A, 0x78, 0xCD, 0x3F, 0x25, 0xC6, 0xB1, 0xC8, 0x94, 0x49, 0x56, 0xDB, 0x9D, 0xD7, + 0xEB, 0x7B, 0x12, 0x60, 0x52, 0x11, 0x65, 0xCA, 0xC6, 0x21, 0x47, 0x8F, 0x77, 0x1A, 0x10, 0x72, 0x94, 0xBF, 0xDF, 0xE9, + 0x84, 0x70, 0x3E, 0x51, 0x24, 0x23, 0x42, 0x0D, 0x8F, 0x7B, 0x45, 0xC0, 0xA7, 0xDA, 0xF5, 0x65, 0x8A, 0x42, 0xE8, 0xA0, + 0x26, 0xDE, 0xD6, 0xF2, 0xC2, 0xFF, 0x1E, 0x05, 0x81, 0x71, 0x70, 0xA6, 0xC5, 0x51, 0xFC, 0xF4, 0x40, 0x54, 0xAB, 0x23, + 0x74, 0x56, 0x4D, 0x32, 0x8F, 0x9E, 0xF2, 0xEC, 0x45, 0xEA, 0x9C, 0xF0, 0x27, 0x17, 0x4C, 0x70, 0x1D, 0x50, 0x47, 0x23, + 0x0E, 0x9D, 0xFD, 0xF4, 0xCA, 0xC9, 0xD1, 0x65, 0xAE, 0xB9, 0x1A, 0xA5, 0xF6, 0x18, 0x5D, 0x33, 0x21, 0x5F, 0x93, 0x37, + 0xB7, 0x9A, 0x14, 0xF1, 0x63, 0x09, 0xE4, 0xB7, 0x52, 0x6C, 0x7F, 0xF7, 0x48, 0x11, 0x46, 0xF9, 0x5F, 0x65, 0xEB, 0xC7, + 0xE5, 0xFE, 0x2E, 0x3F, 0x56, 0xD5, 0xF5, 0xE6, 0xA8, 0x14, 0x7F, 0x8D, 0xF2, 0x49, 0xD5, 0x48, 0x93, 0x28, 0xD6, 0xA9, + 0x90, 0x3A, 0xF8, 0xF7, 0xCA, 0x6C, 0xFF, 0x8F, 0xF8, 0x6A, 0x9E, 0xE9, 0xEC, 0x7F, 0x47, 0x29, 0x96, 0x58, 0xB0, 0xDB, + 0x08, 0x59, 0xAB, 0x5E, 0x9D, 0xB6, 0xDF, 0xCC, 0x7B, 0x56, 0x67, 0xB5, 0x10, 0x18, 0xCA, 0xAA, 0x69, 0xC3, 0xD7, 0x48, + 0x57, 0x59, 0xF1, 0xDD, 0x6C, 0x85, 0x21, 0x68, 0x1C, 0xB3, 0x76, 0x08, 0xD0, 0x12, 0xD8, 0xE1, 0xC0, 0x90, 0x66, 0x0B, + 0x5B, 0x38, 0x61, 0x78, 0x15, 0x97, 0x3F, 0x4B, 0xA3, 0xA3, 0xFF, 0x37, 0x16, 0x33, 0xCB, 0x6B, 0x06, 0x57, 0xBF, 0x8F, + 0x49, 0x12, 0x2F, 0xDB, 0xD0, 0x12, 0x5C, 0x65, 0x48, 0x51, 0x67, 0x0A, 0xD3, 0xD4, 0x97, 0xE1, 0xC8, 0x88, 0x84, 0x7C, + 0xA7, 0xE5, 0xDE, 0x01, 0xB5, 0x7F, 0xEC, 0xAC, 0x60, 0x4D, 0x4F, 0x55, 0x76, 0xA2, 0x3A, 0x13, 0xFA, 0x0C, 0xA5, 0x68, + 0xDF, 0xB9, 0xF8, 0x47, 0x9D, 0xCC, 0x45, 0xDA, 0x55, 0x5A, 0x9E, 0xE1, 0x6D, 0x08, 0x15, 0x65, 0x1B, 0x04, 0xCC, 0xD3, + 0x27, 0xB3, 0x67, 0xE1, 0x3D, 0x13, 0xFD, 0xED, 0x78, 0x22, 0xA1, 0x2E, 0x74, 0xFC, 0x21, 0xAA, 0xA6, 0x9A, 0xA1, 0xCF, + 0x2D, 0xA1, 0x68, 0xE5, 0x65, 0xA4, 0x5B, 0xD5, 0x62, 0xAE, 0xC8, 0xD0, 0x42, 0xA4, 0x44, 0x41, 0xE7, 0xE8, 0xE8, 0xBA, + 0x5B, 0xC8, 0x7F, 0x5D, 0x2B, 0x95, 0x22, 0xE3, 0x67, 0x85, 0x2A, 0x80, 0xD4, 0xE8, 0x19, 0x05, 0xD6, 0xCA, 0x63, 0x59, + 0xE2, 0x52, 0xB1, 0x06, 0x64, 0x84, 0xC9, 0x8F, 0x2E, 0xA4, 0x31, 0xB3, 0x05, 0xAF, 0x9C, 0x46, 0x65, 0x0A, 0xF8, 0xF7, + 0xB4, 0xF2, 0x80, 0x30, 0x2A, 0x91, 0xB4, 0xF9, 0x60, 0x55, 0x62, 0x7B, 0x88, 0xA5, 0xA7, 0xAE, 0x21, 0x03, 0x38, 0x47, + 0xB5, 0x39, 0x2C, 0x36, 0x8D, 0x1E, 0x61, 0x41, 0xA8, 0x55, 0x98, 0x17, 0xFE, 0x84, 0xC2, 0x19, 0xA0, 0xE6, 0x75, 0x3F, + 0x67, 0x4B, 0xFB, 0x2E, 0x9A, 0x61, 0x0B, 0xCB, 0x8E, 0x41, 0x73, 0x9A, 0x62, 0x37, 0x11, 0xE8, 0xE9, 0x24, 0x6B, 0xF7, + 0x6D, 0xE9, 0x40, 0xDB, 0x89, 0xD0, 0x85, 0x02, 0x26, 0x70, 0x5D, 0x28, 0x4D, 0x33, 0xF5, 0xBC, 0x3D, 0xCC, 0x4C, 0x0E, + 0xC3, 0x4A, 0x0F, 0x10, 0xC8, 0xB3, 0x30, 0x0F, 0xAC, 0xE8, 0xE1, 0xAF, 0xBC, 0xED, 0x25, 0x10, 0x6F, 0x0D, 0x9B, 0x94, + 0xAB, 0xFC, 0x1B, 0xC9, 0x06, 0x86, 0xDD, 0x77, 0x7D, 0xA7, 0xF2, 0x2B, 0x61, 0x8C, 0xCC, 0xE4, 0x65, 0x73, 0x31, 0x0A, + 0x2C, 0xEA, 0xD5, 0x76, 0x99, 0x46, 0xFF, 0xFF, 0xC0, 0x62, 0x4C, 0x56, 0x3E, 0x70, 0xBE, 0x3D, 0xCD, 0x1A, 0xDA, 0x26, + 0xDF, 0x93, 0x2C, 0x4B, 0x07, 0xEB, 0x4C, 0xD5, 0x08, 0x51, 0x14, 0x6D, 0xA6, 0x9C, 0x54, 0x6A, 0xE9, 0x4A, 0x04, 0x59, + 0xD2, 0x5E, 0xEA, 0x16, 0x9E, 0xF2, 0xD8, 0x6F, 0xA4, 0x9C, 0xFC, 0xC0, 0x13, 0xA2, 0xA0, 0x27, 0x89, 0x19, 0xE1, 0x54, + 0xDE, 0x7F, 0xD6, 0x17, 0x8A, 0xC5, 0xEE, 0x7A, 0xB4, 0xEC, 0x25, 0x83, 0x86, 0x17, 0xBB, 0x8B, 0x75, 0x56, 0xB0, 0x44, + 0x32, 0x97, 0xDB, 0x59, 0xC7, 0x62, 0x8B, 0x11, 0x16, 0x7B, 0x34, 0x53, 0x1A, 0xB6, 0xAF, 0x54, 0x2F, 0x91, 0xDB, 0xEF, + 0xC7, 0x24, 0xEB, 0x80, 0xDC, 0x5E, 0x2A, 0x23, 0x76, 0xF7, 0xE4, 0xD6, 0xA0, 0xFD, 0xED, 0xCB, 0x0A, 0xE7, 0x62, 0x10, + 0x92, 0x79, 0x23, 0x9E, 0x7B, 0xB4, 0xED, 0x95, 0xAF, 0xDB, 0x5A, 0xFF, 0x37, 0xA7, 0x07, 0xDA, 0xE1, 0x3E, 0xC3, 0xBA, + 0x78, 0x71, 0x91, 0x5A, 0x5B, 0x98, 0xD9, 0x0A, 0x5B, 0x4C, 0xA7, 0x40, 0xC9, 0x47, 0x6D, 0xB1, 0x03, 0x6A, 0x95, 0x3F, + 0xDE, 0x24, 0xF7, 0x14, 0xD8, 0x16, 0x15, 0x6A, 0xCE, 0x45, 0x7E, 0x4F, 0x22, 0x0D, 0x98, 0xBB, 0xA4, 0x25, 0xFC, 0x90, + 0xC7, 0x20, 0x7D, 0xB6, 0xCD, 0x5A, 0x80, 0x6A, 0x8F, 0xFA, 0x39, 0xAE, 0x46, 0x7A, 0xA7, 0x97, 0x58, 0x14, 0x90, 0xD5, + 0x30, 0x99, 0x69, 0xA1, 0x9B, 0x4F, 0xE1, 0x48, 0xAE, 0x37, 0x53, 0xE3, 0xC6, 0x4D, 0x51, 0x88, 0x4F, 0x3F, 0xF2, 0x2E, + 0x32, 0xFA, 0x24, 0xCF, 0x0D, 0x90, 0x2E, 0x33, 0xE1, 0x36, 0xE0, 0x0E, 0xCE, 0xD6, 0xFA, 0xFA, 0xF0, 0xBC, 0x5F, 0x34, + 0x6F, 0xFC, 0xD4, 0xF3, 0x42, 0x8F, 0x2D, 0x87, 0xD6, 0x9C, 0x5C, 0x22, 0x5F, 0x79, 0x2C, 0x27, 0x2F, 0x64, 0x76, 0xEE, + 0xD3, 0xFD, 0xEC, 0xA0, 0x56, 0x63, 0x53, 0xDB, 0xFF, 0xFF, 0xA8, 0x31, 0xE9, 0x49, 0x1A, 0x62, 0x16, 0xE9, 0x49, 0xA1, + 0xE5, 0x4B, 0xEE, 0x8C, 0x33, 0x36, 0x3D, 0x12, 0xEE, 0x1A, 0xB0, 0xE7, 0x33, 0x4D, 0x20, 0x00, 0x49, 0xBE, 0xA0, 0xCF, + 0x32, 0x17, 0x59, 0x10, 0x86, 0x99, 0x34, 0xF6, 0xEC, 0x47, 0x85, 0xA3, 0x22, 0xD2, 0x06, 0xA1, 0xD6, 0x2E, 0x48, 0x77, + 0x7E, 0xAE, 0xEF, 0xB1, 0x78, 0xD2, 0x23, 0x94, 0x36, 0x58, 0x0E, 0xB1, 0xD7, 0xFA, 0x80, 0xD0, 0x4D, 0x0C, 0x3F, 0xA6, + 0x90, 0x6C, 0x08, 0x65, 0x3D, 0x64, 0x88, 0xF0, 0x25, 0xE3, 0x97, 0x50, 0x27, 0xF8, 0xB0, 0xD6, 0x1A, 0x41, 0x9C, 0xF5, + 0x00, 0xB6, 0x87, 0x8B, 0x55, 0xDE, 0xC5, 0xBC, 0x8A, 0x47, 0x0D, 0x27, 0xD3, 0x06, 0xC1, 0x89, 0xE4, 0x0B, 0x0E, 0xFC, + 0xED, 0x62, 0x53, 0x50, 0xA0, 0x6D, 0xF1, 0x05, 0x91, 0x28, 0xA6, 0x02, 0x97, 0x2B, 0x85, 0x89, 0x31, 0x9C, 0x9A, 0x17, + 0xAB, 0x8D, 0xE4, 0xAD, 0x1B, 0x10, 0x12, 0x4E, 0xC7, 0xBE, 0x3E, 0xB7, 0xD8, 0xE9, 0x53, 0x0C, 0xAC, 0xF8, 0x26, 0x8E, + 0x1D, 0x23, 0x40, 0x3A, 0xDB, 0x41, 0x5F, 0x01, 0x5F, 0x2B, 0xFC, 0xE1, 0x84, 0x45, 0xD3, 0x3C, 0xDC, 0x97, 0xA8, 0x59, + 0x48, 0x55, 0x2C, 0xCD, 0xE8, 0xE1, 0xF3, 0x6B, 0x62, 0x42, 0x08, 0x3D, 0xF1, 0x48, 0x9E, 0xBB, 0x41, 0x33, 0x3D, 0xC6, + 0x30, 0x7B, 0x82, 0xD9, 0x26, 0x81, 0xA2, 0x0C, 0x14, 0x21, 0xB5, 0xA8, 0x46, 0xB7, 0xB5, 0x81, 0xDA, 0xD7, 0x95, 0x59, + 0x2F, 0xA0, 0xC0, 0x4C, 0xB8, 0x20, 0x14, 0xD8, 0xEA, 0x4F, 0xE4, 0x65, 0x7A, 0xBF, 0x25, 0xAB, 0x8B, 0x6E, 0xC9, 0x49, + 0x39, 0x23, 0x57, 0x4D, 0xCC, 0x2C, 0x2C, 0xE9, 0xA1, 0x45, 0xCE, 0xEB, 0x83, 0xEF, 0xC1, 0x7D, 0x38, 0x22, 0x65, 0x74, + 0x44, 0xC9, 0x6C, 0x40, 0xBB, 0xFD, 0x76, 0x84, 0x6C, 0x9D, 0x3F, 0x35, 0xBC, 0x72, 0x4C, 0xA4, 0x48, 0x19, 0x51, 0x99, + 0x76, 0x32, 0x8B, 0x76, 0x12, 0x77, 0xB4, 0xD3, 0xFB, 0x32, 0xDC, 0x34, 0x11, 0x5C, 0x30, 0x2F, 0x9A, 0xC2, 0x5C, 0x00, + 0x07, 0x09, 0x1F, 0xAA, 0x47, 0x57, 0xD5, 0xD5, 0x62, 0xEF, 0x33, 0x21, 0xB2, 0x0C, 0xB5, 0x6F, 0xB1, 0x5E, 0x36, 0x06, + 0xCD, 0x39, 0x63, 0x8C, 0x4D, 0x5E, 0xA7, 0x27, 0xF1, 0xDC, 0xF3, 0xC8, 0x24, 0xAF, 0x04, 0x3C, 0xAD, 0x76, 0x2C, 0x82, + 0x80, 0x34, 0xEE, 0x54, 0x90, 0xDB, 0xE0, 0x4E, 0x22, 0x97, 0x22, 0x24, 0x23, 0x3A, 0xF0, 0xB0, 0x67, 0x7C, 0x86, 0x6F, + 0x1B, 0xC5, 0xD9, 0x45, 0xAC, 0xB9, 0x1B, 0x0B, 0x30, 0x3E, 0xD1, 0x26, 0x62, 0x76, 0x71, 0x96, 0x8E, 0x79, 0x8D, 0x55, + 0x29, 0xE8, 0x65, 0xD0, 0x97, 0x31, 0xD6, 0xB7, 0xE9, 0x4C, 0xA3, 0xF3, 0x12, 0xF4, 0xF9, 0x4F, 0x1B, 0x3E, 0xC2, 0x8E, + 0x70, 0x7A, 0x68, 0x08, 0x9C, 0xA9, 0xC5, 0x5C, 0xE6, 0x89, 0x2E, 0x6B, 0x8A, 0x0B, 0x33, 0xA5, 0xC2, 0x3D, 0xDA, 0xE6, + 0x67, 0x47, 0xDC, 0x58, 0xE4, 0x84, 0xBF, 0x16, 0x5D, 0x93, 0x1D, 0xF3, 0xB9, 0x6A, 0x4E, 0xAC, 0x3D, 0x36, 0x57, 0x29, + 0x89, 0x38, 0xB7, 0xE9, 0x29, 0xBD, 0x89, 0xF2, 0xC1, 0x84, 0x62, 0x4A, 0xCF, 0x8F, 0x32, 0x53, 0x09, 0x28, 0x1F, 0xE0, + 0x2C, 0x5E, 0xE6, 0x95, 0x3C, 0x5E, 0x36, 0x9E, 0x4B, 0x45, 0xA4, 0x1F, 0xF6, 0xD1, 0xD2, 0x5C, 0x25, 0xB2, 0xAE, 0x6F, + 0xAC, 0x30, 0x5E, 0x78, 0xEC, 0xCD, 0xE0, 0xE5, 0xF4, 0xFB, 0x65, 0x32, 0xAC, 0xA5, 0x8E, 0x6D, 0x1B, 0xEE, 0x07, 0xE5, + 0xE4, 0x5D, 0x83, 0x0F, 0xB2, 0xCE, 0xE3, 0x47, 0xA8, 0x87, 0x91, 0xE1, 0xBB, 0x90, 0x06, 0x69, 0x4E, 0x59, 0x00, 0xBD, + 0xF7, 0xD4, 0x5E, 0xDA, 0xA1, 0xEE, 0xF9, 0x9C, 0xF1, 0x21, 0x08, 0xC2, 0x0C, 0x3B, 0x4D, 0x61, 0xAD, 0x96, 0x90, 0x22, + 0xD7, 0xCE, 0x4F, 0xD6, 0x25, 0xE3, 0x68, 0xB6, 0x55, 0x4C, 0xB8, 0xC5, 0x67, 0x6A, 0x43, 0x73, 0x85, 0x20, 0xDE, 0xF8, + 0x6D, 0xCC, 0xB1, 0xA7, 0xFD, 0x1F, 0xCF, 0x8E, 0x35, 0x64, 0x77, 0xCB, 0x8D, 0x98, 0x33, 0x69, 0x94, 0xE0, 0x60, 0x33, + 0x62, 0xC5, 0x5C, 0x0A, 0xD3, 0xA1, 0x5E, 0x5A, 0x89, 0x02, 0xEA, 0x06, 0xB5, 0xA2, 0x74, 0xA2, 0x02, 0x69, 0x8E, 0x60, + 0xB7, 0x67, 0x6C, 0x76, 0x01, 0xE7, 0xEC, 0xB4, 0x95, 0xED, 0xFC, 0x8F, 0x4F, 0x84, 0xB0, 0xF6, 0xAB, 0xC6, 0xE1, 0x03, + 0x8A, 0x7D, 0x69, 0x44, 0x37, 0x2E, 0x72, 0x13, 0xCE, 0xCF, 0x83, 0xE3, 0xC9, 0x8B, 0x27, 0xF3, 0x26, 0xD7, 0xC9, 0x35, + 0xD6, 0xA3, 0xA6, 0x73, 0xE3, 0xC6, 0xA3, 0xED, 0xBF, 0x57, 0x22, 0x6C, 0x4C, 0xC7, 0x62, 0x7A, 0xB9, 0x77, 0x44, 0x90, + 0xEF, 0x89, 0xA9, 0xD5, 0xB5, 0xD8, 0x22, 0x1F, 0x6E, 0x95, 0xCC, 0x7C, 0xF6, 0xCD, 0xEE, 0xBC, 0x25, 0x75, 0xC4, 0x93, + 0xBC, 0x6F, 0x9B, 0xCC, 0x4E, 0x96, 0x1E, 0xFC, 0x18, 0xC9, 0x1E, 0x50, 0x55, 0xB7, 0x4E, 0x68, 0x25, 0x9C, 0xD3, 0xF3, + 0xD1, 0xC6, 0x14, 0x2E, 0x19, 0x54, 0x84, 0x60, 0x34, 0xF2, 0xBB, 0xCC, 0xEB, 0x60, 0x5C, 0x52, 0x81, 0x0A, 0x9A, 0x88, + 0x3E, 0xAD, 0xF6, 0x6E, 0x67, 0x14, 0x8C, 0x68, 0xBF, 0x6F, 0x6E, 0x7E, 0x3C, 0x9C, 0x15, 0x5A, 0x6E, 0xF0, 0xFA, 0x1B, + 0x1A, 0xCE, 0xF2, 0x56, 0x3C, 0x5F, 0x67, 0x0B, 0x82, 0x75, 0x24, 0xC7, 0x7F, 0x11, 0x2A, 0xF6, 0x6B, 0xC7, 0x81, 0xEB, + 0xC1, 0x83, 0xAB, 0xDF, 0x4F, 0x30, 0xD5, 0x82, 0xBC, 0xCF, 0x3F, 0xFA, 0x4D, 0x33, 0xED, 0x66, 0x34, 0xAB, 0x5C, 0x42, + 0x62, 0x8B, 0xA0, 0x38, 0xE9, 0x0D, 0x60, 0xE5, 0x8D, 0xD3, 0x83, 0x0B, 0x80, 0x63, 0x94, 0x6D, 0x16, 0xF4, 0xCE, 0x96, + 0x34, 0xA0, 0x02, 0x8F, 0xAF, 0xF2, 0x2D, 0xA8, 0xF9, 0x05, 0xAD, 0xE5, 0x53, 0x82, 0x0A, 0xA3, 0x49, 0xDC, 0x53, 0x07, + 0x0F, 0x91, 0x02, 0x1E, 0xF2, 0x02, 0x95, 0x0C, 0xB7, 0xDE, 0xF7, 0x1B, 0xC9, 0xF1, 0x43, 0x12, 0x0C, 0x90, 0x1D, 0xED, + 0x40, 0x6F, 0xBB, 0xC3, 0x02, 0x39, 0x73, 0x44, 0xDC, 0xAA, 0x24, 0xEB, 0xC5, 0xCF, 0xF3, 0x1B, 0x52, 0x5B, 0x52, 0xCA, + 0x46, 0xD5, 0x85, 0xB4, 0x5C, 0x64, 0xFB, 0x10, 0xE0, 0x95, 0xA3, 0x93, 0x8A, 0x9B, 0xE0, 0x71, 0xA2, 0x56, 0xC5, 0xDF, + 0x34, 0x11, 0x33, 0x85, 0x64, 0xD5, 0x51, 0x85, 0x0D, 0xB4, 0x75, 0xCA, 0x4E, 0xE7, 0xED, 0x24, 0xCB, 0xB1, 0xD5, 0xF6, + 0x65, 0x9F, 0x9F, 0xE7, 0xD3, 0xEC, 0xC5, 0x4A, 0x68, 0x99, 0x66, 0x1D, 0xC7, 0x33, 0x85, 0x0B, 0x5F, 0x98, 0x99, 0xC1, + 0xA5, 0x2D, 0xA8, 0xE8, 0x1E, 0x99, 0x08, 0xD9, 0xE7, 0x16, 0xFA, 0x70, 0xD6, 0x76, 0x39, 0x92, 0xF2, 0x04, 0xB6, 0x87, + 0x8E, 0xEB, 0x62, 0xB2, 0xBA, 0xF8, 0x9C, 0xEC, 0xE2, 0x06, 0xE6, 0x90, 0xC6, 0xB8, 0xD7, 0x64, 0x2D, 0x3A, 0xFA, 0xED, + 0x7F, 0xBB, 0x6D, 0xA5, 0xC3, 0x99, 0xD9, 0xB9, 0x14, 0x9F, 0x8A, 0x58, 0x2A, 0x96, 0x90, 0x00, 0x9F, 0x17, 0xBC, 0x1A, + 0x62, 0xD3, 0xBD, 0x88, 0x70, 0xBA, 0xEE, 0x9A, 0x23, 0x66, 0xD0, 0x93, 0x5E, 0xFD, 0x1E, 0xBE, 0x4E, 0x56, 0x2A, 0x04, + 0x1F, 0x67, 0xE5, 0xB8, 0xFE, 0x18, 0xB7, 0xCF, 0x55, 0x9D, 0x17, 0xAF, 0xF9, 0xD1, 0xB7, 0xC9, 0xFC, 0x73, 0x6B, 0xFF, + 0x46, 0x0F, 0xB7, 0xAF, 0x56, 0x0F, 0xA0, 0x19, 0x43, 0x54, 0x86, 0x99, 0x72, 0x9D, 0x60, 0x1B, 0x03, 0x0F, 0x84, 0x06, + 0x14, 0xDB, 0xA0, 0xA0, 0xA1, 0x23, 0xD4, 0xB2, 0x33, 0x1E, 0xE4, 0x82, 0x09, 0x09, 0xA8, 0x86, 0x91, 0x29, 0x38, 0x31, + 0x59, 0x91, 0xA2, 0x84, 0xBB, 0xCE, 0x58, 0x1E, 0x65, 0xDD, 0x81, 0xC2, 0x6D, 0xAB, 0x0A, 0xC1, 0x80, 0x72, 0x87, 0x0D, + 0x3B, 0x26, 0x9D, 0x73, 0xC0, 0x0B, 0x0D, 0xE8, 0x99, 0x62, 0x39, 0x03, 0xE5, 0x01, 0x3D, 0x31, 0xDB, 0x3F, 0x14, 0x46, + 0xCA, 0x07, 0x78, 0xBA, 0x71, 0x90, 0x43, 0x9C, 0x06, 0xC9, 0x07, 0x56, 0xAD, 0xB1, 0xF7, 0xD4, 0x05, 0x94, 0xB7, 0xBC, + 0xC5, 0x68, 0x98, 0x04, 0xC8, 0x48, 0x18, 0x24, 0x06, 0x7E, 0xE5, 0xB0, 0x21, 0x46, 0x01, 0x9C, 0xB5, 0x19, 0x2E, 0x91, + 0x12, 0xF7, 0xA9, 0xE1, 0xE5, 0xE8, 0x71, 0xBF, 0x2F, 0x0A, 0xB2, 0xBA, 0x11, 0x23, 0x22, 0x11, 0xD5, 0x2B, 0x5A, 0x13, + 0x28, 0xCA, 0x7A, 0x72, 0x29, 0x88, 0xDB, 0x25, 0x1E, 0x6A, 0x54, 0x0D, 0xA9, 0xEE, 0xEB, 0x43, 0x24, 0x97, 0xA6, 0xE8, + 0x01, 0x9F, 0x66, 0x83, 0x1A, 0x59, 0x1E, 0x1C, 0xA0, 0x39, 0xCD, 0xC7, 0xE8, 0xFA, 0x3B, 0x59, 0x08, 0x05, 0x9E, 0xF2, + 0x71, 0x1A, 0x6B, 0x69, 0xC4, 0xB1, 0x2A, 0x91, 0x2F, 0x57, 0x19, 0xC1, 0x3A, 0x46, 0x4B, 0x99, 0x6F, 0x39, 0x01, 0x3D, + 0xE8, 0x2B, 0xE0, 0x39, 0xD3, 0x37, 0xBF, 0x5B, 0x2C, 0x68, 0xCD, 0x2E, 0x14, 0x4E, 0xED, 0xF2, 0xF5, 0xD1, 0x4E, 0x3E, + 0x74, 0x0F, 0x32, 0x5C, 0xF6, 0x4F, 0xF2, 0x40, 0xC6, 0x10, 0x61, 0xE7, 0xF4, 0x56, 0x27, 0x81, 0x53, 0x2F, 0x65, 0xEC, + 0x0E, 0xA5, 0x07, 0x9D, 0xC4, 0x2D, 0xBF, 0xF6, 0xCB, 0x2E, 0x99, 0x2F, 0x9B, 0x69, 0x8B, 0x61, 0x3E, 0x7B, 0x64, 0x03, + 0x6A, 0xF3, 0x51, 0x1F, 0x38, 0x32, 0x84, 0xF4, 0xE8, 0x1D, 0xBD, 0xF0, 0xA0, 0x0F, 0x14, 0x7A, 0x9C, 0x3D, 0x90, 0x5D, + 0x68, 0x11, 0x6D, 0x83, 0xD1, 0x0F, 0x02, 0x78, 0xFD, 0xDC, 0xAC, 0x7E, 0xC4, 0xB8, 0x66, 0xD0, 0x25, 0x13, 0x3B, 0x89, + 0xA1, 0x72, 0x5F, 0x83, 0x32, 0x18, 0x69, 0x1E, 0x41, 0xBB, 0x4C, 0x89, 0x45, 0xAD, 0xAC, 0x81, 0x24, 0xA3, 0xF2, 0xD6, + 0x54, 0xE5, 0xAD, 0x1F, 0x95, 0x35, 0x50, 0xC5, 0x1C, 0x5A, 0xBA, 0x14, 0x65, 0x30, 0x7C, 0x50, 0x81, 0x51, 0xC5, 0x46, + 0xD8, 0x03, 0xAB, 0x10, 0x6A, 0x48, 0x8D, 0x74, 0xD7, 0x72, 0x49, 0x2E, 0x10, 0xC5, 0x48, 0x25, 0x43, 0x15, 0xDC, 0xB7, + 0x4D, 0x4B, 0x71, 0x0B, 0x75, 0x9C, 0xC0, 0xB3, 0xA4, 0x9E, 0xFD, 0xD5, 0x11, 0x32, 0xEA, 0xAB, 0xF2, 0x52, 0x85, 0xEC, + 0xF4, 0x1E, 0xF5, 0x3E, 0x94, 0x17, 0xAD, 0x66, 0x0D, 0x3A, 0x26, 0x19, 0x5B, 0x18, 0x32, 0x77, 0xD1, 0xC7, 0x14, 0x50, + 0x9B, 0x55, 0x25, 0x66, 0x99, 0xA7, 0x11, 0x40, 0x50, 0x15, 0x33, 0x09, 0xFA, 0xAC, 0x77, 0xFE, 0xA4, 0xAF, 0xB6, 0x62, + 0x95, 0x34, 0xDE, 0x71, 0x0C, 0xAE, 0x2E, 0xB1, 0x7F, 0xF1, 0x78, 0x79, 0xFB, 0xCB, 0x33, 0xEF, 0x43, 0x5F, 0xE8, 0x5B, + 0xC9, 0x6A, 0x25, 0xCF, 0xDB, 0x33, 0xBF, 0xEE, 0xA7, 0xA4, 0x70, 0xB9, 0xBF, 0x19, 0x1B, 0xBC, 0x96, 0x7B, 0x9A, 0xE6, + 0x04, 0xC7, 0x71, 0xF5, 0xDA, 0xCD, 0x9E, 0x48, 0xD3, 0xAD, 0x0F, 0xB0, 0xCF, 0x57, 0x8C, 0xED, 0xD9, 0x30, 0xC7, 0xBE, + 0x43, 0x87, 0xAE, 0x6F, 0x94, 0x32, 0x07, 0xA0, 0xCC, 0xD0, 0xC8, 0x8C, 0x1B, 0x07, 0xC7, 0x2C, 0x3C, 0x05, 0xB5, 0xCC, + 0xF6, 0xB3, 0x17, 0x01, 0x52, 0x13, 0x66, 0x05, 0xE4, 0x33, 0xB7, 0x31, 0xE2, 0x52, 0xEF, 0xC9, 0x39, 0x98, 0x3F, 0x4A, + 0x48, 0x50, 0xA6, 0x9B, 0xD9, 0x72, 0x8C, 0x87, 0xFB, 0x0B, 0x60, 0x82, 0x79, 0xCE, 0xEF, 0x23, 0x60, 0xDB, 0xEA, 0x9D, + 0x3C, 0x38, 0x88, 0x60, 0x67, 0x35, 0xAC, 0x32, 0x6A, 0xA1, 0xC7, 0xB6, 0x3F, 0x6B, 0xCE, 0xC5, 0xD9, 0xA0, 0x69, 0x32, + 0xE5, 0x2D, 0x46, 0x47, 0x98, 0x59, 0x20, 0x45, 0x3F, 0x4F, 0xCF, 0x21, 0x35, 0x61, 0x57, 0x14, 0x78, 0x8C, 0x39, 0xE9, + 0x68, 0x02, 0xF9, 0xA2, 0x61, 0xC9, 0xE3, 0x57, 0xBD, 0xB2, 0x18, 0xC6, 0x5A, 0x68, 0x20, 0x9F, 0x35, 0x1B, 0x9C, 0xF8, + 0x45, 0x64, 0x48, 0x95, 0x1F, 0x91, 0xB8, 0x6D, 0x29, 0x1E, 0x57, 0x11, 0xDD, 0xD4, 0x7A, 0x6B, 0xBD, 0x45, 0xFC, 0xF2, + 0x24, 0x99, 0xE6, 0x41, 0x5B, 0x53, 0xB8, 0xDD, 0x33, 0xD9, 0x4E, 0x73, 0x31, 0xC2, 0xEB, 0x15, 0x2D, 0x1D, 0x69, 0x40, + 0xED, 0xF4, 0xE1, 0xD2, 0x62, 0x01, 0x10, 0x0D, 0x48, 0x41, 0x51, 0x7A, 0xE4, 0x95, 0x7F, 0x0B, 0x3F, 0xFA, 0x9A, 0xF1, + 0xE9, 0xCB, 0x72, 0xC2, 0x74, 0x85, 0xCC, 0x28, 0x3F, 0x5D, 0xBF, 0xF5, 0xEC, 0xEA, 0xD4, 0x18, 0x7E, 0x8C, 0x45, 0xBE, + 0x37, 0x63, 0x2A, 0x5C, 0xEE, 0x8C, 0x9B, 0xE4, 0x65, 0x03, 0x58, 0xFF, 0xBD, 0x5B, 0xCC, 0x58, 0xD8, 0x48, 0xE5, 0x06, + 0x37, 0x8E, 0xD2, 0x65, 0x00, 0xFD, 0x78, 0xEC, 0x11, 0xA6, 0xFB, 0xAA, 0x69, 0xC3, 0x83, 0xD4, 0x71, 0xE6, 0x3C, 0xF2, + 0x06, 0xF9, 0x77, 0xB0, 0xE3, 0xC2, 0x70, 0x2A, 0x56, 0xA4, 0x4A, 0xA9, 0x94, 0x65, 0x4A, 0x53, 0x09, 0x36, 0x57, 0xCD, + 0x23, 0x52, 0x20, 0x7B, 0xE8, 0x8C, 0x9A, 0x60, 0x3A, 0xE0, 0x31, 0xCF, 0xBF, 0x17, 0x00, 0x8F, 0x8A, 0xC2, 0x7C, 0x6F, + 0xFD, 0xFB, 0xFB, 0x6B, 0x59, 0x9E, 0x87, 0xD9, 0x5B, 0x4A, 0xD4, 0x98, 0x41, 0xA7, 0xC0, 0x1B, 0xEB, 0x4D, 0x9B, 0xDF, + 0xC1, 0xE0, 0x1F, 0x62, 0x6C, 0x1B, 0x0D, 0x04, 0xE0, 0xFF, 0xA4, 0x4A, 0x54, 0x92, 0xCF, 0x4E, 0x20, 0xBD, 0x12, 0xE2, + 0x1D, 0x10, 0x51, 0xD8, 0xC0, 0xED, 0x3D, 0x36, 0x63, 0x95, 0xB0, 0x99, 0x5F, 0xA4, 0x6D, 0xAA, 0x24, 0x32, 0x9D, 0x79, + 0x18, 0xBF, 0xF5, 0xB1, 0x69, 0x74, 0xEB, 0xE7, 0xF4, 0x5D, 0x65, 0x60, 0x21, 0x1E, 0x97, 0x7C, 0x06, 0xF2, 0xC6, 0x37, + 0xE3, 0xF5, 0xED, 0x88, 0x89, 0x26, 0x1B, 0x2A, 0x33, 0xD9, 0x18, 0x36, 0x3E, 0xBB, 0xE4, 0x90, 0x55, 0x4C, 0xF2, 0x62, + 0x0D, 0xE8, 0x56, 0x34, 0x37, 0xDA, 0x9E, 0xD7, 0x7B, 0x18, 0x6F, 0x70, 0xE7, 0x3A, 0x8B, 0x74, 0x55, 0xE7, 0xC9, 0x58, + 0xA7, 0x86, 0x85, 0x74, 0x19, 0xBB, 0x8D, 0xC7, 0x07, 0x79, 0xD5, 0xE2, 0xF0, 0x4D, 0x6C, 0x35, 0x22, 0xC6, 0xFE, 0x37, + 0xBB, 0x4C, 0x45, 0x23, 0xBB, 0x78, 0xA7, 0xF4, 0x54, 0x92, 0x74, 0x91, 0xC7, 0xFC, 0xFC, 0x89, 0x54, 0x60, 0x9A, 0x34, + 0x97, 0x9A, 0x25, 0x2A, 0x01, 0x3B, 0x4C, 0x9B, 0x2C, 0x49, 0x18, 0x6D, 0xB1, 0xB4, 0x86, 0x44, 0x90, 0xB7, 0x06, 0x45, + 0x80, 0x95, 0x18, 0x69, 0x51, 0xF4, 0xD9, 0x89, 0x5D, 0x39, 0x68, 0xCE, 0xDF, 0x99, 0x8D, 0x50, 0xCF, 0x2A, 0x75, 0x9A, + 0x7F, 0x04, 0x3F, 0x77, 0xE0, 0xF9, 0xDC, 0xFB, 0xAD, 0x20, 0xD8, 0x7F, 0xCD, 0x5F, 0x91, 0x35, 0x62, 0x11, 0xE2, 0xEA, + 0x41, 0xBC, 0xE3, 0x0A, 0x6A, 0x23, 0xAC, 0xAC, 0xDD, 0xFA, 0x4E, 0x7F, 0xD1, 0x42, 0x2E, 0x3B, 0xAC, 0xA6, 0xA7, 0x85, + 0x69, 0x67, 0x86, 0x38, 0x27, 0xB3, 0x9C, 0x23, 0xBB, 0xD1, 0x77, 0x4B, 0xC5, 0x21, 0xE7, 0xD4, 0xBB, 0x9C, 0xA7, 0xEA, + 0x9D, 0xDE, 0x6D, 0x27, 0xE7, 0x9B, 0xAE, 0xB9, 0xD4, 0xB0, 0x27, 0x04, 0xDC, 0x49, 0x48, 0xDB, 0xFF, 0xFF, 0x3E, 0xAD, + 0x68, 0x0D, 0xFD, 0xC6, 0xB1, 0x26, 0x47, 0x52, 0x64, 0x95, 0x17, 0xFF, 0xAB, 0x0E, 0xF3, 0xE0, 0x20, 0xF0, 0xE8, 0x96, + 0xC5, 0x4E, 0x18, 0x34, 0x1D, 0x10, 0xE0, 0x74, 0x49, 0x23, 0xFE, 0x72, 0xB6, 0x61, 0x22, 0xEF, 0x96, 0x98, 0x40, 0x1E, + 0xFA, 0xD9, 0x2E, 0xBE, 0x25, 0xC4, 0x77, 0x17, 0xE2, 0x26, 0xB1, 0x24, 0xBB, 0x2C, 0xBA, 0x91, 0x1D, 0x60, 0x01, 0x28, + 0x24, 0x97, 0xC7, 0x52, 0x26, 0xAB, 0x7F, 0x75, 0xB3, 0xF5, 0x12, 0x84, 0xB5, 0xD1, 0x82, 0x7A, 0xB9, 0x00, 0x70, 0xAF, + 0xEA, 0x6D, 0xDE, 0x36, 0xE4, 0xD8, 0xDF, 0x5C, 0xCE, 0xC8, 0x14, 0xE4, 0xA4, 0x98, 0xE5, 0x23, 0x75, 0x63, 0x3E, 0xAD, + 0x84, 0x6B, 0x83, 0x5A, 0xAC, 0x04, 0x8B, 0x64, 0x71, 0xCB, 0x5F, 0x33, 0xA7, 0xAC, 0x6A, 0xB7, 0x53, 0x8A, 0xBE, 0x9E, + 0x22, 0x91, 0x75, 0xEB, 0xD0, 0xF5, 0xD1, 0xFB, 0x84, 0x05, 0xE2, 0x12, 0xBF, 0x25, 0xFE, 0x5B, 0x62, 0xCE, 0xEA, 0xA8, + 0x5A, 0xCA, 0x32, 0xEB, 0x63, 0x67, 0xB0, 0xEF, 0x1C, 0x8D, 0x19, 0x78, 0x0D, 0xE2, 0x36, 0xAE, 0x05, 0x63, 0x93, 0xFA, + 0xEA, 0x6F, 0xD5, 0xAD, 0x3B, 0x6B, 0x13, 0x5A, 0xEA, 0xCC, 0x95, 0x69, 0x31, 0x22, 0x6D, 0x25, 0x60, 0xBA, 0x03, 0x58, + 0xBB, 0x3B, 0x4B, 0x21, 0xA2, 0x68, 0x1B, 0x1C, 0xC7, 0x2A, 0x3A, 0x4C, 0xE3, 0x44, 0xBA, 0x7D, 0xBB, 0x8D, 0xAB, 0x52, + 0x78, 0xF9, 0x8C, 0x8E, 0x5E, 0x91, 0x32, 0x5F, 0x2F, 0x0B, 0x6A, 0x2E, 0x79, 0x99, 0x0C, 0xFC, 0x17, 0x1C, 0x03, 0x76, + 0x5D, 0x36, 0x71, 0xBA, 0x0E, 0xAA, 0xFB, 0x7D, 0x6A, 0x81, 0x06, 0x57, 0xA8, 0xBB, 0xE1, 0x5D, 0xFF, 0x2C, 0x1B, 0x51, + 0xE8, 0x2F, 0x0B, 0x3C, 0x66, 0x4A, 0xF7, 0x06, 0x55, 0x12, 0xBF, 0x3D, 0x83, 0xE4, 0xE7, 0x73, 0x16, 0x51, 0x9F, 0xC8, + 0xD9, 0x78, 0xEF, 0x24, 0x62, 0x18, 0x05, 0x57, 0xF4, 0xFD, 0xB3, 0xA1, 0x1F, 0xBE, 0xF7, 0xB3, 0x90, 0x5D, 0x24, 0x5E, + 0xE2, 0x5C, 0x0C, 0x44, 0x14, 0xD0, 0xB2, 0x51, 0xD7, 0x12, 0x45, 0xE4, 0x50, 0x3F, 0x7D, 0xC3, 0x5F, 0x5C, 0xC7, 0xBB, + 0x1B, 0x16, 0xD8, 0xEF, 0xCB, 0x40, 0x6A, 0xEF, 0x67, 0x39, 0x60, 0x73, 0x40, 0x55, 0x0E, 0x46, 0x75, 0xFE, 0x1E, 0x4E, + 0x5E, 0x56, 0xA2, 0x01, 0x31, 0x4D, 0x34, 0xFE, 0x07, 0x59, 0xAA, 0xC9, 0x74, 0x8E, 0x0A, 0xAF, 0x00, 0x67, 0xF4, 0x2E, + 0x9F, 0x38, 0x54, 0xF4, 0x1C, 0x35, 0xCD, 0x70, 0x1E, 0x35, 0x85, 0x87, 0x03, 0x12, 0x7A, 0x41, 0x85, 0x72, 0xAA, 0xA6, + 0x20, 0x36, 0x8B, 0x18, 0x96, 0xCD, 0x17, 0x5C, 0xDF, 0x55, 0xB2, 0xA6, 0xA4, 0x48, 0xE2, 0xC1, 0xE7, 0x51, 0x71, 0x86, + 0x9F, 0xD1, 0x78, 0x24, 0x0C, 0xB5, 0x07, 0xFF, 0x3D, 0x7A, 0xB5, 0x5A, 0x6E, 0xE2, 0xC4, 0x0B, 0x93, 0x1C, 0x59, 0xEB, + 0x1F, 0x9A, 0x3A, 0xE3, 0x9A, 0x94, 0xDE, 0x61, 0xD3, 0x55, 0xCA, 0x4F, 0xFD, 0xF4, 0xD2, 0xB9, 0x57, 0xB5, 0x9B, 0xBF, + 0x4D, 0x35, 0x77, 0x2B, 0x3C, 0x45, 0x07, 0x5D, 0xC1, 0xDB, 0xF0, 0x6A, 0xDB, 0x5A, 0x03, 0xAC, 0x18, 0xBA, 0x27, 0xD2, + 0x68, 0x56, 0xCD, 0xA3, 0x12, 0x1F, 0x86, 0xDF, 0xD1, 0xB1, 0x2A, 0xB7, 0xA4, 0xB7, 0x06, 0x65, 0xC9, 0x5A, 0x43, 0x9F, + 0x1E, 0xDA, 0x8E, 0x5C, 0x5A, 0xA2, 0xEE, 0x56, 0x3A, 0x37, 0x26, 0x9A, 0x9C, 0xA2, 0xE4, 0x6F, 0x43, 0x82, 0x46, 0x4D, + 0xE0, 0x65, 0xE7, 0x27, 0x4B, 0xB7, 0xF4, 0x08, 0x4B, 0xDE, 0x46, 0x2D, 0xEB, 0x12, 0x71, 0xD0, 0x26, 0xA9, 0x95, 0x27, + 0xC7, 0x90, 0x06, 0xF2, 0x0E, 0xE0, 0xE5, 0x6E, 0xCB, 0xA0, 0x3A, 0x00, 0xB7, 0x2D, 0x22, 0xF6, 0x15, 0x01, 0x30, 0xA0, + 0x90, 0x4F, 0x8E, 0x0B, 0x3C, 0x51, 0xB8, 0xE2, 0x24, 0x20, 0x24, 0x27, 0xB4, 0x20, 0x00, 0x59, 0xC4, 0xCC, 0xC6, 0x30, + 0xB4, 0x62, 0x73, 0x73, 0x04, 0x94, 0x2D, 0xF4, 0x99, 0x0F, 0xF1, 0xFA, 0x7E, 0xCE, 0xA7, 0x45, 0xB4, 0xFF, 0xFC, 0xE0, + 0x01, 0x08, 0x81, 0xE4, 0x11, 0x2E, 0x80, 0x71, 0x64, 0xBE, 0x9E, 0xC4, 0x59, 0xA2, 0x18, 0xC0, 0x24, 0x54, 0xD8, 0xB8, + 0xBA, 0xA9, 0xB0, 0xF2, 0x09, 0xCC, 0x8F, 0x5B, 0xBD, 0xA0, 0x0A, 0x52, 0x06, 0x37, 0x28, 0xD7, 0x82, 0xE5, 0xA7, 0x72, + 0x63, 0x87, 0x5C, 0x86, 0x5F, 0xEA, 0x19, 0x67, 0x7B, 0xE8, 0x1E, 0xC5, 0xB0, 0x2E, 0xF5, 0x9E, 0xCE, 0x87, 0xCB, 0xD7, + 0x02, 0x49, 0x33, 0xDE, 0xFB, 0xC5, 0xB6, 0x5B, 0xE0, 0x73, 0xE1, 0xFE, 0xC1, 0xEE, 0x7E, 0x16, 0xA1, 0xA6, 0x15, 0xBB, + 0x3A, 0x27, 0xF0, 0x0D, 0x1A, 0xE1, 0x1A, 0x48, 0xB8, 0xCB, 0xEB, 0x34, 0xB9, 0x69, 0x86, 0x69, 0x33, 0x7F, 0x0A, 0x6C, + 0x7F, 0x8D, 0x97, 0xBE, 0x16, 0xF0, 0xE8, 0x20, 0xB6, 0x8D, 0x87, 0x2F, 0xA2, 0x55, 0x27, 0x3F, 0x3D, 0x05, 0x84, 0x8A, + 0x51, 0x37, 0xA4, 0xDC, 0x58, 0x67, 0x55, 0xB6, 0x64, 0xD8, 0x6B, 0x7E, 0x60, 0xE9, 0x8C, 0x53, 0x3E, 0x74, 0x2B, 0xCF, + 0xFA, 0x4A, 0xA2, 0x5D, 0xF5, 0x07, 0x3D, 0xB4, 0xF7, 0xC6, 0x02, 0x08, 0xCC, 0xCF, 0xAC, 0x42, 0x5E, 0x48, 0x0C, 0xDE, + 0x45, 0xF6, 0x95, 0xDA, 0x78, 0x59, 0xBA, 0x1B, 0xE9, 0xC0, 0x08, 0x1C, 0x7E, 0x2D, 0xA2, 0x76, 0x88, 0xCC, 0x1E, 0xA3, + 0x9E, 0x23, 0x76, 0x89, 0xFD, 0x9A, 0x3A, 0x42, 0x5C, 0xEA, 0xAB, 0xDF, 0xFE, 0x30, 0xD1, 0xA0, 0x62, 0xC3, 0x1B, 0xDB, + 0x93, 0xC0, 0xC3, 0x8E, 0xEB, 0xEF, 0x7D, 0x0C, 0x81, 0x36, 0xA4, 0x75, 0xB0, 0x3D, 0x8D, 0xE0, 0xC5, 0xAD, 0x24, 0x4E, + 0xA0, 0x3D, 0x0C, 0x61, 0x86, 0x83, 0x28, 0xA6, 0x15, 0x1E, 0x8B, 0x13, 0xF8, 0x2C, 0xFB, 0xD0, 0x82, 0x9D, 0x73, 0xF0, + 0xC6, 0x1B, 0xF7, 0x81, 0xB2, 0xFB, 0x1D, 0xC1, 0x10, 0xD1, 0xD3, 0xC6, 0x0B, 0xE9, 0x95, 0xE3, 0x25, 0x35, 0x0D, 0xE5, + 0xD7, 0xF7, 0x90, 0x37, 0xBE, 0xEA, 0x02, 0x29, 0xD1, 0x5C, 0x1A, 0x77, 0xC7, 0x12, 0x44, 0xB4, 0x54, 0x60, 0x0E, 0x82, + 0x42, 0xCF, 0x58, 0x99, 0xBC, 0x85, 0xA9, 0xEF, 0x21, 0xD7, 0x94, 0xA9, 0x16, 0xC7, 0x36, 0xE8, 0xC4, 0x51, 0x2E, 0xD6, + 0x6F, 0xCB, 0x65, 0x30, 0xC0, 0x1D, 0x9B, 0xC0, 0xD5, 0x96, 0xB4, 0x85, 0x15, 0x7B, 0x4E, 0x74, 0xC2, 0xFC, 0xCB, 0x57, + 0xE5, 0xE9, 0xB3, 0x35, 0xB3, 0x32, 0x82, 0x80, 0xA4, 0x43, 0x9D, 0xE9, 0xC5, 0xFA, 0x5E, 0xAE, 0xC5, 0x12, 0x66, 0xEF, + 0xC1, 0xFA, 0x81, 0xDF, 0x9F, 0x67, 0x12, 0xCC, 0x8F, 0x9D, 0x82, 0x05, 0x09, 0x34, 0x77, 0x80, 0x06, 0xE9, 0x56, 0xD8, + 0xD2, 0xD7, 0xC6, 0xA3, 0xBD, 0x36, 0x65, 0x74, 0x45, 0x59, 0xBC, 0xC3, 0x83, 0x9A, 0xCC, 0x2F, 0xEE, 0x92, 0x8F, 0x54, + 0xD8, 0x51, 0xFA, 0xAB, 0xA5, 0x34, 0x6F, 0xFB, 0xE1, 0xF9, 0x07, 0x55, 0x6E, 0xD6, 0x81, 0x1E, 0x96, 0xF4, 0xCA, 0x51, + 0xC5, 0xAF, 0xF4, 0x12, 0x38, 0xE7, 0x0E, 0xF8, 0x87, 0xD3, 0x1A, 0x7C, 0x63, 0xF4, 0x3F, 0x2A, 0xB1, 0x6C, 0xE6, 0xC7, + 0x5C, 0xC2, 0xD9, 0x18, 0xAF, 0x22, 0xA1, 0x39, 0xFD, 0x29, 0x5D, 0x59, 0xAE, 0x31, 0xC6, 0x4B, 0x89, 0x98, 0x6F, 0xEA, + 0xB2, 0x63, 0xF1, 0x9D, 0x5D, 0xBC, 0xAF, 0x5F, 0xDE, 0xDD, 0x78, 0x2C, 0x3B, 0x32, 0xC4, 0x2B, 0xE7, 0x00, 0x61, 0x8D, + 0x94, 0xF0, 0x04, 0x84, 0x5C, 0xEC, 0xCB, 0xE2, 0xB5, 0x4E, 0xE7, 0xA4, 0x2E, 0xD2, 0x6B, 0xA0, 0x6F, 0xFC, 0x7A, 0x11, + 0x59, 0x64, 0x20, 0x38, 0x35, 0x4D, 0x10, 0x39, 0x47, 0xA2, 0x23, 0x6E, 0x57, 0x91, 0x61, 0x1F, 0xED, 0x0F, 0xE3, 0x09, + 0x91, 0x03, 0xFD, 0xA5, 0xCA, 0xB8, 0xBE, 0x5A, 0x09, 0xFE, 0x31, 0xA3, 0xEE, 0x13, 0xB6, 0x9A, 0x6A, 0xBE, 0x06, 0xCE, + 0xF2, 0xB4, 0x08, 0x7B, 0x24, 0x3F, 0xDE, 0xB4, 0xEB, 0xE5, 0x3B, 0x60, 0xCE, 0xB5, 0x70, 0x89, 0xE3, 0x40, 0x45, 0x97, + 0xD6, 0xE9, 0xD6, 0xA4, 0xA2, 0x85, 0xE1, 0x26, 0xF4, 0x35, 0x60, 0xA0, 0x0F, 0x43, 0xE0, 0x8B, 0x30, 0xEA, 0x39, 0x71, + 0xB7, 0x44, 0xE6, 0x7C, 0x03, 0xDB, 0x53, 0xE3, 0x42, 0xDF, 0x83, 0xD6, 0x39, 0x02, 0x31, 0x3A, 0x85, 0xEE, 0x33, 0x7F, + 0xEB, 0xE8, 0xD1, 0x15, 0x60, 0x06, 0x48, 0x86, 0x57, 0xEA, 0x62, 0xBB, 0xBA, 0x83, 0x63, 0xF6, 0x23, 0x60, 0xD2, 0xA9, + 0x8F, 0x0A, 0x3F, 0x53, 0xC5, 0xFD, 0xD5, 0x18, 0x7E, 0x4B, 0x8F, 0x7B, 0x17, 0xD6, 0x43, 0x6B, 0xEC, 0xC9, 0xCA, 0x03, + 0x73, 0x2B, 0x07, 0xEB, 0x08, 0x9A, 0x3F, 0x4A, 0x96, 0xF5, 0xDD, 0x3F, 0xCB, 0x68, 0xC3, 0x16, 0xF2, 0xBF, 0x8B, 0x55, + 0x5A, 0x86, 0x27, 0x66, 0x47, 0xB6, 0xE3, 0x5F, 0x0B, 0x6B, 0x1C, 0x11, 0x24, 0x1A, 0x72, 0x3B, 0x3A, 0x03, 0xC3, 0xBA, + 0x1C, 0x55, 0x74, 0x88, 0xCE, 0xE8, 0x80, 0xDF, 0xB1, 0x08, 0x4F, 0x5A, 0xC5, 0x4C, 0xAA, 0x1C, 0xD4, 0xA6, 0xDA, 0x5C, + 0xFE, 0x0F, 0xA4, 0x7A, 0xBA, 0xEE, 0xF7, 0x3A, 0xB2, 0x01, 0x39, 0x3F, 0x71, 0x67, 0xCC, 0x6E, 0xA1, 0x41, 0x43, 0x9D, + 0x20, 0xDF, 0x2B, 0x47, 0xEE, 0x02, 0xCA, 0xBF, 0x9D, 0x94, 0x9B, 0x41, 0x6A, 0x90, 0xAD, 0x8E, 0x57, 0x2E, 0xA8, 0x12, + 0x22, 0x1A, 0x44, 0xF1, 0xF3, 0x3C, 0xEF, 0xA8, 0xC5, 0xAF, 0x5A, 0x54, 0x8F, 0xDF, 0x6C, 0x27, 0xE1, 0x0A, 0x4C, 0xE1, + 0xF0, 0x3C, 0x5D, 0xD6, 0x17, 0x52, 0x0A, 0xC6, 0x9A, 0xB0, 0x42, 0xE7, 0xE0, 0x5D, 0xBD, 0x75, 0xE8, 0x43, 0x4C, 0x83, + 0x45, 0xA3, 0x84, 0x56, 0xC8, 0xDD, 0x79, 0x15, 0xCF, 0x81, 0x9B, 0xF7, 0x4A, 0xEE, 0xA3, 0xB8, 0xD2, 0xEB, 0xC7, 0x47, + 0x99, 0xB2, 0x3C, 0xC2, 0x32, 0xE9, 0xD4, 0xCD, 0x20, 0x90, 0x41, 0xD1, 0xC3, 0xAB, 0xA2, 0x17, 0xFE, 0x35, 0x16, 0xD1, + 0x80, 0x13, 0x9A, 0x39, 0xA2, 0x6E, 0xE3, 0xC0, 0x42, 0xEA, 0xAE, 0x07, 0xFF, 0x34, 0xBD, 0x43, 0x80, 0xA6, 0xD6, 0x75, + 0x7A, 0x87, 0x6B, 0xC9, 0xCC, 0x89, 0xAB, 0xE3, 0x13, 0xF5, 0x6D, 0xBC, 0x02, 0xE8, 0xAE, 0x2C, 0xF1, 0xAC, 0xE6, 0x41, + 0x7D, 0xC8, 0xA3, 0xF3, 0x12, 0xF4, 0xB9, 0xA5, 0xD7, 0xC5, 0x52, 0x76, 0xBB, 0x35, 0xAE, 0x99, 0x3B, 0x17, 0x56, 0xD9, + 0xA0, 0x75, 0x71, 0xE2, 0x1B, 0x86, 0x2D, 0x3C, 0xE5, 0x1A, 0x47, 0xBC, 0xBC, 0x35, 0x31, 0x87, 0x1D, 0x3B, 0xD6, 0x77, + 0x51, 0x29, 0x7C, 0x09, 0x87, 0xA6, 0xBF, 0x85, 0xCC, 0xA7, 0x8F, 0x25, 0x25, 0x47, 0x6F, 0x2E, 0x69, 0x5B, 0xD5, 0x86, + 0x8D, 0x79, 0xDB, 0xE7, 0xE7, 0x45, 0x81, 0x91, 0x74, 0x86, 0x82, 0x4D, 0x24, 0x96, 0xA5, 0x31, 0xA9, 0xE7, 0xC6, 0x1B, + 0xEE, 0xD1, 0xA4, 0x1F, 0xF6, 0x3D, 0x36, 0xA7, 0x68, 0xFD, 0x26, 0xD5, 0x1F, 0x99, 0xCE, 0x10, 0xBB, 0x31, 0x61, 0xC0, + 0x84, 0xA6, 0xC3, 0x4B, 0xAF, 0x64, 0x22, 0x49, 0xE1, 0xF2, 0x05, 0x5E, 0x01, 0x3A, 0xA9, 0xEA, 0x5B, 0xA1, 0x2F, 0x79, + 0xF9, 0x10, 0xDC, 0x6D, 0x73, 0x8E, 0xE7, 0x62, 0xF9, 0x12, 0xDF, 0x83, 0xDF, 0xF2, 0x40, 0xB1, 0xB6, 0x8F, 0x43, 0xC6, + 0x50, 0x2D, 0x38, 0x2F, 0x77, 0x06, 0x4F, 0x58, 0x62, 0x3F, 0x50, 0x35, 0xA6, 0xC3, 0x50, 0x32, 0x88, 0x1C, 0xA8, 0x40, + 0x76, 0x6D, 0x47, 0xCB, 0x6E, 0x3A, 0x1B, 0x81, 0x50, 0x6B, 0xF8, 0x5E, 0x33, 0xB2, 0xEB, 0x37, 0x41, 0x93, 0x21, 0xCA, + 0x9C, 0x59, 0x28, 0x13, 0xA1, 0x58, 0x04, 0x59, 0x68, 0xFF, 0xC1, 0x17, 0xF6, 0x5B, 0x0F, 0xB3, 0xAE, 0xC8, 0x00, 0xE2, + 0x18, 0xC6, 0x61, 0xC2, 0x65, 0x91, 0xC4, 0x00, 0xB9, 0xDF, 0xAE, 0x84, 0x52, 0xE2, 0xF6, 0x8D, 0x34, 0x07, 0x9A, 0x53, + 0x1B, 0xCB, 0xC0, 0x89, 0x63, 0x1A, 0xEB, 0x14, 0xE8, 0xA8, 0xED, 0x0C, 0x79, 0xC4, 0x81, 0x18, 0x35, 0xAB, 0xF9, 0x05, + 0x35, 0xD6, 0x47, 0x1A, 0xD2, 0xA4, 0xD1, 0xAC, 0x05, 0x84, 0xC9, 0x56, 0x1A, 0xAF, 0xC6, 0x42, 0x66, 0x38, 0x1C, 0x98, + 0xC5, 0xAA, 0x94, 0xF7, 0x2D, 0xCA, 0xF8, 0x09, 0x28, 0xEA, 0x8A, 0xCA, 0x2B, 0x65, 0x88, 0xC5, 0xE5, 0x84, 0xF5, 0x7A, + 0x0B, 0xC1, 0xF0, 0x36, 0x21, 0x06, 0x91, 0xF7, 0xEC, 0xC2, 0xE0, 0x85, 0x65, 0xAB, 0xFE, 0x02, 0xFB, 0x6F, 0x3D, 0xFB, + 0x3D, 0x55, 0xBE, 0xCB, 0xEB, 0xCC, 0xD5, 0x63, 0xDF, 0x83, 0xE3, 0xF3, 0x63, 0xC6, 0x0B, 0x6D, 0xFF, 0x0C, 0x20, 0xD3, + 0xC8, 0x86, 0x25, 0xB5, 0x7C, 0xE2, 0x67, 0xA8, 0x3D, 0x2E, 0x63, 0xCA, 0x65, 0xB1, 0xC9, 0xCF, 0xB9, 0x61, 0x90, 0x6E, + 0xE9, 0x80, 0x0A, 0xFA, 0x53, 0x82, 0x6B, 0x1E, 0xA6, 0xE3, 0x44, 0x07, 0x39, 0x62, 0x6A, 0x8E, 0xC0, 0x1C, 0x33, 0x57, + 0xDE, 0xC3, 0xDD, 0x2B, 0x11, 0x28, 0x2B, 0x56, 0x25, 0x8A, 0xCC, 0xE0, 0x3F, 0xB8, 0x0B, 0xFB, 0xD7, 0x02, 0x79, 0xDB, + 0xE6, 0x81, 0xDF, 0x19, 0xEB, 0x62, 0x85, 0x79, 0x3E, 0x6C, 0x60, 0xCC, 0xA6, 0x77, 0x3A, 0x72, 0x95, 0x4F, 0x49, 0x5D, + 0x57, 0x95, 0xD2, 0x8F, 0x81, 0x56, 0xD3, 0x7A, 0x65, 0xD3, 0x0C, 0xE4, 0x57, 0x16, 0x43, 0x75, 0xBB, 0x4C, 0xAD, 0xA9, + 0x4D, 0x55, 0x07, 0x07, 0xCA, 0x99, 0xFF, 0xBE, 0x88, 0x1D, 0x8D, 0x59, 0xF4, 0x9F, 0xA4, 0x67, 0xB8, 0x26, 0x69, 0x73, + 0xA3, 0x70, 0x6D, 0xE2, 0x76, 0xBF, 0xDE, 0x73, 0xBD, 0xC8, 0x2F, 0x82, 0xBD, 0x32, 0x04, 0x86, 0x2D, 0x1F, 0xB2, 0x2B, + 0x76, 0xEF, 0x17, 0xC6, 0xDB, 0x2B, 0x8F, 0x1D, 0x49, 0xF6, 0x77, 0xB0, 0xD8, 0x19, 0x8F, 0x2B, 0x34, 0x6E, 0x43, 0xCF, + 0x98, 0x58, 0x3C, 0x76, 0x72, 0x8E, 0xE1, 0x21, 0x24, 0x92, 0x82, 0x3E, 0x66, 0x2D, 0xA1, 0x70, 0x47, 0x09, 0x2C, 0xD2, + 0x4D, 0xE9, 0xA9, 0x56, 0xA9, 0x1D, 0x8E, 0x53, 0xEC, 0x7B, 0xAE, 0xD7, 0x68, 0x7A, 0xEA, 0x1B, 0x49, 0xCC, 0x1C, 0x0E, + 0x26, 0xD5, 0x9E, 0x7E, 0x72, 0xC9, 0xD1, 0xCC, 0xDB, 0xC8, 0x88, 0x9A, 0xF1, 0x7E, 0x14, 0x72, 0xC3, 0xD6, 0xB8, 0xFC, + 0xC6, 0x64, 0xED, 0x1A, 0x80, 0x29, 0x28, 0x4C, 0x5C, 0x0B, 0x27, 0x8B, 0xAC, 0x9A, 0x67, 0xFA, 0x6D, 0xB7, 0x8F, 0x44, + 0x90, 0x87, 0xB1, 0xEF, 0x37, 0x57, 0x4F, 0x2C, 0x8A, 0x80, 0x7B, 0x65, 0x3E, 0xB6, 0x66, 0xE7, 0x48, 0x7A, 0xE5, 0x56, + 0xC5, 0xB9, 0x62, 0x48, 0x2B, 0x06, 0x4E, 0xC7, 0x1A, 0x37, 0x26, 0x79, 0x0C, 0x71, 0xF7, 0x06, 0x7E, 0xBE, 0x24, 0xDF, + 0x83, 0x92, 0xD4, 0x6E, 0xD3, 0x12, 0x40, 0xCF, 0x07, 0xD0, 0x3C, 0x8C, 0xDC, 0x98, 0x1F, 0xB4, 0x6F, 0xFC, 0xBA, 0xF2, + 0x55, 0xFA, 0xE0, 0x78, 0xC0, 0x9F, 0xAF, 0xF0, 0x7C, 0xFD, 0x7F, 0xCE, 0xEB, 0x99, 0x4B, 0xFB, 0xDC, 0x08, 0x80, 0x88, + 0x8B, 0xBC, 0x40, 0x1D, 0xDB, 0xFF, 0x59, 0x8A, 0xE5, 0xAF, 0xE6, 0x59, 0x50, 0xDF, 0x22, 0x11, 0x2E, 0xBF, 0x3B, 0x4A, + 0x85, 0x9C, 0x58, 0x21, 0xA0, 0xFE, 0xC4, 0x04, 0xE6, 0xDC, 0x66, 0xA6, 0x9D, 0xA7, 0x8E, 0x41, 0xBA, 0x88, 0x96, 0x09, + 0x65, 0xAD, 0x2D, 0x76, 0x97, 0x84, 0x2F, 0xC3, 0xAA, 0x81, 0x2C, 0x7A, 0x39, 0x93, 0x37, 0x2C, 0xAF, 0xDC, 0x25, 0x87, + 0x81, 0x29, 0x23, 0xC2, 0x0B, 0xE8, 0xA4, 0x04, 0xE0, 0xCC, 0x5A, 0x44, 0x21, 0x4C, 0x7F, 0xA6, 0xCF, 0xB9, 0xEF, 0xA7, + 0x80, 0x04, 0x10, 0x19, 0x34, 0xC9, 0xF7, 0xB6, 0x30, 0xF5, 0x91, 0xC8, 0xB6, 0xB4, 0xDC, 0x35, 0x1A, 0x05, 0xCE, 0xD5, + 0xB8, 0x46, 0xE9, 0x48, 0xB1, 0x24, 0x6E, 0xE5, 0xC6, 0xD6, 0x59, 0x74, 0xA9, 0x3E, 0x05, 0xE1, 0xBC, 0x30, 0xB1, 0x23, + 0x68, 0x4E, 0x36, 0xF5, 0xD3, 0xC7, 0xC9, 0xF5, 0xAA, 0xE2, 0x62, 0xC4, 0xF1, 0xC8, 0xBD, 0x38, 0x84, 0xF7, 0x43, 0x72, + 0x95, 0xAE, 0x70, 0x2C, 0x80, 0x8B, 0x8B, 0x28, 0x79, 0xFC, 0x53, 0x0D, 0xDC, 0x65, 0x29, 0xFE, 0xF9, 0xD6, 0x64, 0xA3, + 0x22, 0xDF, 0x36, 0x7E, 0xDA, 0xBD, 0x39, 0xB5, 0x7F, 0xF7, 0x82, 0xCD, 0xDA, 0xD7, 0xF0, 0x3A, 0xA6, 0xBC, 0x7F, 0xAD, + 0x24, 0x4A, 0xCF, 0x47, 0x87, 0x15, 0xD2, 0x8E, 0x3C, 0x94, 0x9B, 0xCA, 0x2D, 0xE4, 0x79, 0x22, 0x17, 0xC0, 0x22, 0x56, + 0xEE, 0x87, 0x69, 0x36, 0xCF, 0xB3, 0x92, 0x81, 0x95, 0x0E, 0x82, 0xE8, 0x34, 0x7A, 0x4D, 0xDC, 0x70, 0x10, 0x88, 0x26, + 0xBC, 0x2B, 0xEE, 0xFC, 0x78, 0xD2, 0x61, 0xCD, 0x2F, 0xC2, 0xC3, 0xAB, 0xAA, 0x4E, 0x6C, 0x33, 0x47, 0x35, 0x8A, 0x3D, + 0xCC, 0xC4, 0xC5, 0x50, 0x31, 0x9F, 0x8B, 0xA1, 0x33, 0xA2, 0x9B, 0x54, 0x38, 0x34, 0x9B, 0x24, 0xB9, 0x0E, 0x48, 0x6C, + 0xFD, 0x6B, 0xFE, 0x88, 0xDD, 0xDF, 0xFC, 0xB6, 0x43, 0x30, 0xA6, 0x12, 0x70, 0x95, 0x38, 0x01, 0xA5, 0x13, 0x32, 0x30, + 0x41, 0x51, 0xDA, 0x76, 0xE8, 0xCC, 0x2F, 0xB8, 0x85, 0xE4, 0xBB, 0xAA, 0xA1, 0xDA, 0xDE, 0x9E, 0xDF, 0x88, 0x93, 0xED, + 0x4F, 0xAF, 0x63, 0x8B, 0xDE, 0x97, 0x3E, 0x6F, 0x4B, 0xDD, 0x72, 0xE3, 0xCB, 0xE2, 0xA2, 0x6F, 0x48, 0x92, 0xC2, 0xB1, + 0x62, 0x5D, 0x38, 0xB1, 0x76, 0x65, 0xBB, 0x3C, 0x24, 0x56, 0x9B, 0x22, 0x34, 0x17, 0x32, 0x92, 0xC1, 0xA9, 0x14, 0x60, + 0x03, 0x8B, 0x72, 0x8C, 0xE9, 0x4D, 0x84, 0xD0, 0xB6, 0x67, 0xA3, 0x8B, 0x0B, 0x58, 0x1C, 0x70, 0x02, 0xCA, 0xCC, 0x1B, + 0x86, 0x7A, 0x2E, 0x41, 0xC1, 0x17, 0x43, 0x83, 0x8A, 0x5B, 0x8F, 0x6A, 0x9A, 0x95, 0x2D, 0x66, 0x31, 0x18, 0x5D, 0x24, + 0xC7, 0x91, 0x4B, 0x93, 0x18, 0x8C, 0x1D, 0x0C, 0xDE, 0xDA, 0x7D, 0x0C, 0x43, 0xE2, 0xBE, 0x73, 0xC9, 0x7A, 0xF6, 0x97, + 0x4C, 0x43, 0xC6, 0x32, 0x83, 0xD5, 0xA2, 0x70, 0xEB, 0xD4, 0x4A, 0x62, 0x95, 0x34, 0xA6, 0x28, 0xCE, 0xF4, 0x1C, 0x4C, + 0xA8, 0x26, 0xB8, 0xD5, 0x8B, 0x6A, 0xC8, 0x28, 0x1C, 0xD7, 0xA6, 0xCF, 0xC9, 0x4A, 0xE1, 0xFC, 0x1A, 0x71, 0x6D, 0x98, + 0xA8, 0x6B, 0x4B, 0x72, 0x2C, 0xE6, 0x94, 0x59, 0xE1, 0x14, 0x62, 0xBF, 0xB9, 0x2E, 0x60, 0x94, 0x3F, 0xC7, 0x98, 0xF1, + 0x1B, 0x97, 0x54, 0x18, 0xF5, 0xED, 0x55, 0xAB, 0x74, 0xA3, 0x48, 0xAA, 0xD0, 0x5F, 0xD6, 0xAF, 0x78, 0xBC, 0x25, 0x7C, + 0x06, 0x6A, 0x5A, 0x01, 0x73, 0x3C, 0xEC, 0x34, 0x22, 0x65, 0x97, 0xFA, 0xD1, 0x1D, 0x97, 0x9C, 0x18, 0x53, 0x68, 0x2A, + 0x2C, 0x76, 0x10, 0x38, 0x4A, 0xB0, 0x34, 0x2E, 0x95, 0xB2, 0x67, 0x3E, 0x39, 0x57, 0x68, 0x49, 0xFD, 0x45, 0x5D, 0xF1, + 0x70, 0x1B, 0x0C, 0x79, 0xCE, 0x2B, 0x86, 0xD3, 0xAC, 0xD0, 0xD6, 0x22, 0x3F, 0x66, 0xF7, 0x12, 0x72, 0x8E, 0xC9, 0x56, + 0x51, 0x5D, 0x94, 0x41, 0x7F, 0x67, 0xC6, 0xA9, 0x3E, 0x57, 0x86, 0xFA, 0xD7, 0xFD, 0x81, 0xED, 0xFD, 0xAD, 0x4F, 0x11, + 0x41, 0xD4, 0x31, 0x55, 0x3F, 0x34, 0xE9, 0x12, 0x12, 0x2E, 0x10, 0x48, 0x93, 0x7B, 0x6A, 0xC0, 0x1D, 0x6E, 0xB8, 0xC4, + 0x07, 0x4C, 0xF8, 0x85, 0xC4, 0xD4, 0xA6, 0x39, 0xB1, 0xA2, 0x10, 0xD5, 0xD4, 0xC9, 0xDC, 0x42, 0x8A, 0x47, 0xD0, 0xB2, + 0x05, 0xC8, 0xEB, 0x30, 0xE0, 0xB5, 0x1E, 0x10, 0xB0, 0x4E, 0xFD, 0x9E, 0x73, 0xA8, 0x69, 0xA1, 0xB5, 0xB4, 0xB1, 0x5A, + 0x35, 0xBD, 0x33, 0x81, 0xC0, 0x2F, 0xCF, 0xD6, 0x34, 0xC6, 0x6B, 0xB5, 0x81, 0x7D, 0x51, 0xA8, 0x91, 0x4E, 0x0E, 0x4E, + 0xC1, 0x2E, 0x87, 0xC3, 0xE4, 0xF4, 0x72, 0x3B, 0xAD, 0x77, 0x3A, 0x02, 0x9C, 0x2F, 0x63, 0xB8, 0x4C, 0x67, 0x00, 0xDD, + 0xB0, 0x43, 0xFF, 0x78, 0xF2, 0xEC, 0x3D, 0x55, 0xA0, 0x95, 0xD2, 0xB0, 0x6F, 0x1F, 0x12, 0xB4, 0xA4, 0x35, 0x1D, 0x36, + 0x8A, 0x69, 0x33, 0x10, 0xE8, 0x1E, 0x10, 0xDA, 0x50, 0xAA, 0x85, 0x23, 0x37, 0x6F, 0x13, 0xF3, 0x4F, 0x77, 0x95, 0x6A, + 0x55, 0x21, 0x44, 0x71, 0x70, 0xD7, 0x80, 0x61, 0xEE, 0x2B, 0x3C, 0xB7, 0x6A, 0x37, 0x0D, 0xCC, 0x9E, 0x17, 0x13, 0x08, + 0xC3, 0x1A, 0xD2, 0x7B, 0x6D, 0x2D, 0x7A, 0x53, 0xE8, 0x00, 0x35, 0x5A, 0x19, 0x76, 0xED, 0xFE, 0x22, 0xDB, 0x2F, 0x18, + 0xB4, 0x0E, 0x72, 0xCF, 0xE3, 0xCE, 0xDB, 0x6F, 0x77, 0xFE, 0x3B, 0x63, 0xAD, 0x79, 0x4B, 0x9C, 0xB8, 0xF5, 0x0B, 0x45, + 0xBD, 0x80, 0xED, 0xA2, 0x9B, 0xED, 0xC0, 0x99, 0xC9, 0x26, 0xA1, 0xF0, 0xB7, 0x2C, 0xCC, 0x12, 0x00, 0x1D, 0x0D, 0xB9, + 0x40, 0x4D, 0x54, 0xFC, 0x7B, 0xDD, 0x47, 0x89, 0x8A, 0x0C, 0xD6, 0xD4, 0x67, 0xD0, 0x13, 0xAF, 0xCE, 0x6C, 0x85, 0xF5, + 0xAF, 0x09, 0x17, 0x74, 0xF6, 0xB7, 0x7C, 0x11, 0x43, 0x82, 0x71, 0x14, 0x15, 0x6D, 0x2D, 0xFF, 0x05, 0x8D, 0x08, 0xF8, + 0x21, 0xAF, 0xC1, 0x13, 0x59, 0xB3, 0xFE, 0x6D, 0x4C, 0x12, 0x75, 0xE7, 0x86, 0x64, 0x0A, 0x93, 0xC6, 0xD1, 0xE9, 0x2F, + 0x6E, 0x2B, 0x9A, 0x62, 0xDF, 0xF7, 0x76, 0x0F, 0x6E, 0xD0, 0x6E, 0x99, 0x1F, 0x57, 0xAC, 0x2B, 0x0C, 0x38, 0xBD, 0xA5, + 0x4B, 0x34, 0x36, 0xF3, 0x5A, 0xDC, 0x3C, 0x3F, 0x12, 0x08, 0xBA, 0xAF, 0xD1, 0x73, 0x49, 0x54, 0xB9, 0xBC, 0xF5, 0x0E, + 0xE6, 0x0B, 0xED, 0xEB, 0x0A, 0x15, 0xE4, 0xB3, 0xCB, 0xD5, 0xEF, 0x28, 0x56, 0x14, 0x7B, 0x77, 0x8A, 0xE0, 0xE3, 0x46, + 0xD4, 0x97, 0x8A, 0xC8, 0xAF, 0x4C, 0x9E, 0x71, 0xCD, 0xFA, 0xA7, 0x2E, 0x61, 0x17, 0x0E, 0xD3, 0x5D, 0xB2, 0x7F, 0x81, + 0x17, 0x34, 0x96, 0x61, 0xB2, 0xCF, 0x87, 0xE5, 0x6B, 0x42, 0xFA, 0xC1, 0xDA, 0xE2, 0xF5, 0x94, 0xC2, 0x0E, 0xE8, 0x2A, + 0x4B, 0xDF, 0x0F, 0xCB, 0xDA, 0x26, 0x08, 0x4F, 0xEC, 0xE1, 0x7C, 0x6A, 0x0E, 0xDB, 0x14, 0x11, 0xBC, 0x7B, 0xD9, 0xFC, + 0x04, 0xD1, 0x38, 0x59, 0xD9, 0x06, 0x3F, 0xCA, 0x28, 0xD7, 0x75, 0x30, 0x55, 0xB4, 0x4D, 0x08, 0x32, 0x6C, 0x29, 0xEF, + 0x5A, 0x07, 0x56, 0x25, 0xCD, 0xDD, 0x5B, 0x7F, 0x8B, 0xBE, 0xC1, 0xA0, 0x69, 0x86, 0x46, 0x01, 0x9E, 0x22, 0x57, 0x49, + 0x40, 0x88, 0xE7, 0xDC, 0x90, 0x96, 0x9C, 0x24, 0xCA, 0x42, 0xF7, 0xCB, 0xCD, 0x9C, 0xEB, 0x9E, 0xF6, 0xBF, 0xD8, 0xE2, + 0x4F, 0x6E, 0xED, 0x79, 0x3B, 0x4E, 0x44, 0xB8, 0x21, 0xF5, 0x09, 0x20, 0x18, 0xB0, 0x97, 0x86, 0x15, 0x4A, 0x4E, 0xCF, + 0x14, 0x43, 0x83, 0xDB, 0xA1, 0xBF, 0xC8, 0x55, 0x95, 0xDC, 0xE8, 0x50, 0x3E, 0xAA, 0x5B, 0xC1, 0xFE, 0x21, 0x60, 0xC7, + 0x35, 0xCE, 0xBE, 0x11, 0x0D, 0x60, 0xB9, 0xD5, 0x4F, 0x2D, 0x68, 0xDA, 0xAB, 0x3D, 0x01, 0x57, 0xE3, 0x8A, 0xC9, 0x54, + 0x0B, 0x0B, 0x8D, 0xF7, 0x13, 0x6B, 0x47, 0xDE, 0xE3, 0x40, 0x0F, 0xDD, 0x4D, 0x2C, 0x9F, 0x20, 0xBE, 0xF5, 0xB6, 0xA2, + 0x02, 0x6B, 0xE5, 0xC0, 0x0A, 0x47, 0x7C, 0x26, 0xD1, 0xB0, 0x88, 0xA4, 0x82, 0xDE, 0x30, 0xBC, 0xD5, 0xEA, 0xC6, 0x84, + 0xB2, 0x4A, 0xBE, 0x70, 0x38, 0xE3, 0xF0, 0x7D, 0xF9, 0xE6, 0x98, 0xEF, 0x35, 0x36, 0x0B, 0x01, 0xFE, 0x04, 0x33, 0x7A, + 0x1C, 0xCD, 0xFF, 0xAC, 0xA2, 0x72, 0x90, 0xFB, 0x34, 0x3C, 0x99, 0x04, 0x63, 0x4A, 0x59, 0x2A, 0x2A, 0x9B, 0x94, 0xA8, + 0x10, 0x99, 0x99, 0x7E, 0xBB, 0x2E, 0x6B, 0xD3, 0xBC, 0x97, 0x93, 0xCA, 0xA7, 0x73, 0x40, 0xA5, 0x0F, 0x61, 0x4A, 0xF4, + 0x67, 0xD5, 0xFA, 0x07, 0x6D, 0x52, 0x36, 0xA2, 0x5A, 0xEA, 0xBC, 0x19, 0x86, 0x68, 0x0B, 0x64, 0x3B, 0x4F, 0xA4, 0xD6, + 0x4B, 0x44, 0xF0, 0x5B, 0x2F, 0x97, 0xAA, 0x67, 0x36, 0x65, 0x30, 0x42, 0x9F, 0x20, 0xF9, 0x4F, 0xE8, 0x73, 0x5B, 0x49, + 0x5B, 0x96, 0xD5, 0x66, 0x7E, 0xB7, 0x6C, 0xAA, 0x29, 0x59, 0xAB, 0x4F, 0xEB, 0x33, 0x8C, 0xF2, 0x5A, 0x98, 0xD5, 0x1E, + 0x2F, 0x96, 0x90, 0x94, 0xBC, 0xA0, 0x12, 0x71, 0x9E, 0x10, 0xE0, 0x8F, 0x89, 0xB1, 0x5B, 0xB1, 0x14, 0x4C, 0x99, 0x49, + 0x3D, 0x3E, 0xFF, 0xF6, 0x7F, 0x98, 0x34, 0x9C, 0x00, 0x1E, 0xFD, 0xA0, 0xAA, 0x74, 0x92, 0xDA, 0x7C, 0x84, 0xF0, 0x26, + 0x76, 0xB3, 0x62, 0x23, 0x06, 0x12, 0xC4, 0xC5, 0xBE, 0x9B, 0x93, 0x6C, 0xBA, 0xFD, 0x0C, 0x24, 0x65, 0x1A, 0x6C, 0xA6, + 0x64, 0x32, 0x77, 0xB4, 0xAE, 0x13, 0xD5, 0x83, 0x55, 0xB0, 0x2B, 0x34, 0x6B, 0x9F, 0xA7, 0x52, 0x61, 0xCC, 0x01, 0x63, + 0xF4, 0x3B, 0xDB, 0x67, 0xEC, 0xB7, 0xD5, 0x15, 0x03, 0x49, 0x0F, 0x6E, 0xF3, 0xD2, 0xBA, 0x90, 0x2C, 0x1F, 0xF5, 0x66, + 0x85, 0x30, 0xDD, 0x85, 0xB5, 0xDE, 0x65, 0xA8, 0x71, 0x1F, 0x7C, 0xBD, 0x01, 0xC6, 0x22, 0xB6, 0xD9, 0x92, 0xAB, 0xE0, + 0x9D, 0xAB, 0x63, 0xC0, 0xFD, 0x76, 0xB3, 0x62, 0x2E, 0xD7, 0xF7, 0x8A, 0xEE, 0x88, 0xA3, 0x0F, 0x63, 0x75, 0xB4, 0x8B, + 0x13, 0x35, 0x25, 0xF6, 0x8B, 0x1B, 0x9B, 0x57, 0xB6, 0xEA, 0xAE, 0x1E, 0xEA, 0x56, 0x62, 0xE4, 0x7F, 0x7A, 0x2D, 0xE6, + 0x8E, 0x1A, 0x62, 0xCB, 0x65, 0xC3, 0xC6, 0xDF, 0x96, 0xE2, 0xA3, 0x62, 0x12, 0xA4, 0x6E, 0x96, 0xDF, 0xEC, 0x05, 0x80, + 0x0B, 0x8A, 0x4F, 0x3E, 0x8F, 0x43, 0x06, 0x0C, 0x6C, 0xB0, 0x5E, 0x66, 0x25, 0xB2, 0x1F, 0x03, 0xD2, 0x68, 0x1F, 0x5E, + 0x5A, 0x4E, 0x3D, 0x84, 0xD8, 0xC6, 0xF8, 0x78, 0x17, 0x29, 0x3F, 0x72, 0x35, 0x97, 0x61, 0x4F, 0x6D, 0x28, 0xC7, 0xAD, + 0xF5, 0x7C, 0xF2, 0x89, 0xC2, 0x64, 0xD2, 0x9C, 0x00, 0x57, 0xE7, 0xB1, 0x4E, 0x4B, 0x87, 0x05, 0x92, 0xAA, 0xBD, 0xB7, + 0x5F, 0xE3, 0x21, 0x3F, 0xE0, 0x97, 0xCD, 0x4B, 0x1F, 0x9B, 0xA8, 0x7A, 0x11, 0xDA, 0xD1, 0x38, 0x67, 0x06, 0x65, 0x83, + 0x86, 0xC1, 0x5E, 0xF8, 0x6B, 0xFD, 0xE4, 0x0F, 0xAD, 0xD2, 0x27, 0xFE, 0xC3, 0x13, 0xA4, 0xC9, 0x6F, 0x63, 0xCC, 0x53, + 0x9F, 0x32, 0x57, 0x1C, 0x38, 0xFE, 0xAF, 0xA7, 0x4C, 0x5D, 0x6C, 0xEB, 0x67, 0xDA, 0x5F, 0xF9, 0xEB, 0xBF, 0x38, 0x0C, + 0x21, 0x6F, 0xE0, 0x47, 0x82, 0x88, 0x2D, 0x84, 0x15, 0xC3, 0xDC, 0xB0, 0x08, 0xC8, 0x70, 0xA2, 0x24, 0xED, 0xAC, 0x20, + 0x0B, 0xE3, 0xA0, 0x31, 0xF4, 0xAE, 0x20, 0xDF, 0x45, 0x9A, 0x54, 0xA5, 0x39, 0x7C, 0xE5, 0x7C, 0xEF, 0x8D, 0xFB, 0x06, + 0x37, 0xA4, 0x75, 0xDF, 0x6C, 0x39, 0xCA, 0x00, 0x75, 0x5D, 0x63, 0xAE, 0x83, 0xEB, 0x76, 0xBA, 0x93, 0x52, 0xBB, 0x41, + 0x3E, 0x81, 0xDF, 0x03, 0xD4, 0x81, 0x64, 0xBF, 0x06, 0x5F, 0xBC, 0xD0, 0xFF, 0x2E, 0x5F, 0x18, 0x9F, 0x54, 0x5F, 0x78, + 0xB2, 0x10, 0x31, 0xD4, 0x60, 0x9D, 0x24, 0x49, 0xB4, 0x20, 0xD7, 0x56, 0x4F, 0xC5, 0xA6, 0x44, 0x17, 0xA9, 0x09, 0xC7, + 0x8E, 0xD8, 0xF3, 0xB9, 0x69, 0x0B, 0x51, 0x2D, 0x1B, 0x7B, 0x47, 0x96, 0x3E, 0xE2, 0x09, 0x64, 0xA6, 0x8A, 0x16, 0xBF, + 0x05, 0x0A, 0x7D, 0x72, 0xCF, 0xE7, 0x98, 0x64, 0xBD, 0x73, 0x83, 0x4D, 0xB1, 0xCA, 0x5B, 0x8C, 0x1D, 0xCD, 0xE8, 0x35, + 0x7F, 0x0E, 0xEB, 0x21, 0xB5, 0x29, 0xEA, 0x5F, 0x93, 0x02, 0xF4, 0x33, 0x15, 0x22, 0xE5, 0x5A, 0x4B, 0xB2, 0x42, 0x24, + 0x39, 0x5D, 0xAF, 0x8D, 0x8D, 0x9A, 0xF9, 0x0E, 0x3F, 0xEB, 0xF1, 0x0F, 0xBB, 0x6C, 0x4B, 0x27, 0x35, 0x0B, 0xAB, 0xF9, + 0x0D, 0x4B, 0x54, 0xEC, 0xED, 0x04, 0x3E, 0xC7, 0x07, 0x30, 0x2D, 0xD7, 0x90, 0x16, 0x9D, 0x3A, 0x4B, 0x87, 0x9A, 0xB8, + 0x0E, 0x51, 0x8D, 0x6B, 0x4E, 0xCC, 0xD4, 0xDA, 0x86, 0x47, 0x52, 0xA4, 0xF2, 0x54, 0x5D, 0x5F, 0x92, 0xA1, 0x7E, 0x85, + 0x47, 0xAD, 0xAA, 0xE0, 0xA4, 0x16, 0x74, 0xC9, 0x62, 0xC7, 0x19, 0x6B, 0x11, 0xAC, 0x73, 0x6A, 0xC6, 0x31, 0x56, 0x7B, + 0x59, 0xF8, 0x94, 0xD9, 0x63, 0x06, 0x83, 0x41, 0x59, 0x5B, 0x84, 0x84, 0xCF, 0xCF, 0xFB, 0xBD, 0x5C, 0xA9, 0xE4, 0x73, + 0x9B, 0x32, 0xC2, 0xAA, 0x37, 0xA2, 0xCC, 0xE4, 0x3E, 0x7B, 0x30, 0x57, 0x08, 0xF0, 0x55, 0x69, 0x4E, 0xEE, 0x76, 0x75, + 0xB8, 0x4C, 0xC4, 0x96, 0xB0, 0x6C, 0x2F, 0xB6, 0x1E, 0x00, 0x7B, 0x6C, 0xF4, 0x91, 0x0A, 0xEC, 0x69, 0xF0, 0x69, 0x35, + 0xD7, 0xE0, 0xE5, 0x93, 0xB0, 0x59, 0xEC, 0x89, 0x52, 0x27, 0xCB, 0xAE, 0x40, 0x15, 0x96, 0xCC, 0xA7, 0xDA, 0x7E, 0x5B, + 0x19, 0x88, 0x3B, 0x38, 0x02, 0xA8, 0x9A, 0xF5, 0x5D, 0x31, 0x74, 0xE2, 0x66, 0x76, 0x8A, 0x7C, 0xA3, 0x69, 0x93, 0x2C, + 0xDF, 0xCD, 0xE4, 0xCC, 0xFF, 0x9D, 0x7C, 0xF2, 0x67, 0x44, 0x5F, 0xC0, 0xAB, 0x10, 0xDA, 0x88, 0xC5, 0x69, 0x65, 0x81, + 0x24, 0x12, 0x75, 0xE3, 0xE6, 0x75, 0x5E, 0xB8, 0x0F, 0x0A, 0x57, 0x29, 0x4C, 0x94, 0xCA, 0x26, 0x2B, 0xD7, 0x7D, 0xF3, + 0xEF, 0xCE, 0xA3, 0xC4, 0xF3, 0x5C, 0xD9, 0x7B, 0x93, 0xAB, 0xB5, 0x4E, 0x78, 0x6C, 0x76, 0xBA, 0x4F, 0xB0, 0xAE, 0xBD, + 0x08, 0x5B, 0xD3, 0x8A, 0x46, 0xE6, 0x3B, 0x97, 0xBD, 0xF4, 0x46, 0x38, 0x6C, 0xBC, 0xA6, 0x42, 0xE3, 0xBB, 0x77, 0x75, + 0xA0, 0x31, 0xB4, 0x90, 0xC4, 0x8E, 0x57, 0xEB, 0xC2, 0x57, 0x91, 0x92, 0x9A, 0x01, 0xEF, 0x6A, 0x12, 0x39, 0x91, 0xB2, + 0x4E, 0x16, 0x47, 0x46, 0xB9, 0xDF, 0x20, 0x47, 0x8A, 0x1E, 0x5D, 0x8D, 0xE4, 0xC4, 0x0E, 0x44, 0x1C, 0x6A, 0xDE, 0x7B, + 0xEB, 0xAE, 0xC4, 0xEA, 0xFB, 0xEA, 0x7D, 0x5E, 0x42, 0x56, 0x86, 0x58, 0xC3, 0xFC, 0xD6, 0x72, 0xEA, 0x6F, 0xA0, 0xF1, + 0x7B, 0xB3, 0x2F, 0x6B, 0xCD, 0xA5, 0x98, 0x32, 0xBE, 0xB0, 0xDF, 0x67, 0x6B, 0xEC, 0x56, 0xF5, 0x62, 0x4A, 0x57, 0xB2, + 0x8C, 0xFE, 0x03, 0x5F, 0x43, 0x9F, 0xBF, 0x4E, 0x34, 0xC4, 0x9E, 0x5F, 0x29, 0x40, 0xDF, 0x00, 0x83, 0x0E, 0xCA, 0x66, + 0x4D, 0x26, 0x18, 0x34, 0xBD, 0x2E, 0x3B, 0x7B, 0xED, 0x9C, 0x76, 0xA0, 0xBA, 0x8A, 0x27, 0xFF, 0xF8, 0xA9, 0x78, 0x74, + 0x7C, 0x4C, 0xA7, 0x6B, 0xAC, 0x0F, 0xE1, 0x3E, 0xA4, 0x8F, 0x2E, 0xEB, 0x33, 0x24, 0x73, 0xCB, 0xC1, 0x82, 0x51, 0x38, + 0xA2, 0x9E, 0x18, 0x38, 0x32, 0x4E, 0xF1, 0x97, 0x4C, 0x3C, 0x8E, 0xD3, 0xE5, 0x0F, 0xFF, 0xF5, 0xD0, 0x03, 0x78, 0xBF, + 0x61, 0xB0, 0x72, 0x5B, 0xFE, 0x8F, 0xF3, 0x56, 0x9E, 0xA1, 0xB1, 0xC4, 0x84, 0xDB, 0x70, 0xAB, 0x05, 0xBE, 0x48, 0x12, + 0x81, 0x71, 0xD8, 0x36, 0xD1, 0xE1, 0xAA, 0x7C, 0xB7, 0xC2, 0xD2, 0xC5, 0xEF, 0xCD, 0xF7, 0x41, 0xF9, 0xA3, 0x2F, 0x52, + 0xA9, 0xC3, 0xF8, 0x0A, 0x43, 0xA3, 0xD5, 0x2E, 0x68, 0x08, 0xEA, 0x5A, 0x4B, 0x8C, 0x0B, 0x6B, 0x0B, 0xE4, 0xE8, 0xC8, + 0x37, 0xF2, 0xFD, 0xFA, 0x29, 0x18, 0xBC, 0x5D, 0xBB, 0x68, 0x7C, 0x42, 0x6A, 0xA5, 0x35, 0xEC, 0x7C, 0x95, 0x1C, 0xA8, + 0xE2, 0x8A, 0x18, 0xE4, 0xF5, 0x92, 0xB6, 0xB7, 0xF6, 0xC4, 0x1A, 0x23, 0x04, 0x28, 0xC3, 0xC0, 0xED, 0xF7, 0xD8, 0xA3, + 0x79, 0x85, 0x94, 0x8F, 0x03, 0xC7, 0x3F, 0xBE, 0x85, 0x60, 0x51, 0x20, 0xB1, 0x14, 0x93, 0xF0, 0x9D, 0xD0, 0xFA, 0xD7, + 0x28, 0x7D, 0xFB, 0x79, 0x5D, 0xE6, 0x70, 0xB3, 0xFA, 0x03, 0x67, 0x48, 0x9D, 0x3A, 0x75, 0x99, 0xD6, 0x2C, 0xD3, 0x5A, + 0xA2, 0x97, 0x5D, 0xA7, 0xE2, 0x02, 0xCA, 0x9E, 0x98, 0x6B, 0x25, 0x85, 0x4B, 0x43, 0x6D, 0x58, 0xD4, 0x6F, 0xFE, 0xBA, + 0x29, 0x8B, 0x93, 0xD3, 0x61, 0xD5, 0xBB, 0xE3, 0xE8, 0x98, 0xD3, 0xAF, 0x59, 0x28, 0x18, 0xA7, 0xAF, 0x82, 0x7C, 0x79, + 0x19, 0x2B, 0x33, 0xFF, 0x37, 0x0E, 0x6C, 0x7C, 0x56, 0x63, 0x5C, 0x81, 0xD5, 0x1B, 0xE4, 0xC5, 0xBC, 0x3D, 0x54, 0xFB, + 0x42, 0xFE, 0xAE, 0x18, 0x9B, 0x14, 0xD3, 0x91, 0x05, 0xAD, 0x57, 0x96, 0x4E, 0xD9, 0xE3, 0xC2, 0xB7, 0x8E, 0xC6, 0x18, + 0x05, 0xDE, 0x81, 0x7C, 0xA0, 0x53, 0x8F, 0x84, 0x13, 0x73, 0x12, 0xD3, 0x6D, 0xA4, 0xAF, 0x22, 0x03, 0x33, 0xB2, 0xCA, + 0x58, 0x99, 0xD6, 0xA2, 0xCA, 0x3A, 0x27, 0x2A, 0x1A, 0xDE, 0x3D, 0xC7, 0x93, 0xA7, 0x51, 0x44, 0x62, 0x8B, 0x60, 0xA6, + 0x47, 0x3D, 0xB8, 0x08, 0xAC, 0x19, 0x8A, 0xD6, 0x76, 0x38, 0xF3, 0x97, 0xF9, 0x1D, 0x94, 0xB6, 0x44, 0x31, 0x54, 0xE8, + 0x9B, 0xB4, 0xFB, 0x05, 0xEF, 0x35, 0x7A, 0xA1, 0xAA, 0xA4, 0x45, 0x82, 0x96, 0xCB, 0xB2, 0x69, 0x47, 0x80, 0xB4, 0xEB, + 0x22, 0x02, 0xC8, 0xAE, 0x2C, 0x81, 0x12, 0x75, 0xC8, 0xB7, 0xEA, 0xC5, 0xE5, 0x0E, 0x35, 0x7F, 0xD1, 0xA1, 0x82, 0x79, + 0x8B, 0x1A, 0x5B, 0xEB, 0x3E, 0x03, 0x75, 0x52, 0x4C, 0x5E, 0xE8, 0xAB, 0xD9, 0x39, 0x2E, 0xFA, 0x9E, 0x7C, 0x1E, 0xD3, + 0xC4, 0x45, 0x66, 0x3A, 0xB4, 0xD6, 0x3E, 0x4F, 0xF5, 0xE4, 0x35, 0x76, 0x2A, 0x52, 0x13, 0x09, 0xA8, 0x3A, 0xB8, 0x4B, + 0x8B, 0x7A, 0xE9, 0xAB, 0x19, 0xF9, 0x37, 0x49, 0x74, 0x64, 0x26, 0xE3, 0x2C, 0x96, 0x45, 0x63, 0x4A, 0x5D, 0xE7, 0x99, + 0x2C, 0xC6, 0x0E, 0xDC, 0xAA, 0x0C, 0xBD, 0x48, 0x51, 0xC6, 0x66, 0xD7, 0x0E, 0x1E, 0xA9, 0x11, 0x7A, 0x72, 0xCD, 0x66, + 0x6B, 0xB1, 0x62, 0xF8, 0xB4, 0x7C, 0x7E, 0x32, 0x23, 0x9C, 0xBE, 0xB8, 0x74, 0x70, 0xF8, 0xB0, 0x8B, 0x9E, 0x78, 0x91, + 0x9B, 0x7E, 0x8E, 0x96, 0xA2, 0xBF, 0xBF, 0x6B, 0x06, 0x3F, 0xE0, 0xA7, 0x76, 0x5E, 0x23, 0x5D, 0x47, 0x1F, 0x7F, 0xAA, + 0xCF, 0x31, 0x95, 0x03, 0x58, 0x79, 0x98, 0xFD, 0xE7, 0x89, 0xA0, 0xFA, 0xB5, 0xE2, 0x4D, 0x50, 0xD6, 0xDF, 0xC8, 0xA4, + 0x72, 0xA8, 0x97, 0x23, 0x67, 0x2E, 0x77, 0x76, 0x6E, 0xCC, 0xC8, 0xE1, 0x43, 0xCA, 0x30, 0xCF, 0x36, 0xA1, 0x20, 0x87, + 0x9F, 0x4B, 0xA5, 0xC9, 0xE3, 0x47, 0x0A, 0x83, 0x29, 0x20, 0xC9, 0x00, 0x77, 0xE4, 0x7B, 0x1A, 0x3F, 0x23, 0x69, 0xFA, + 0x30, 0x5E, 0x17, 0xB7, 0xC7, 0x7F, 0xC1, 0xB5, 0xF3, 0x6B, 0x9B, 0xB2, 0xD6, 0x55, 0xB2, 0x24, 0x77, 0xF1, 0x4A, 0x91, + 0x22, 0x69, 0x98, 0x78, 0x90, 0x10, 0x17, 0x32, 0x7F, 0xE9, 0x37, 0x5E, 0x49, 0x2E, 0xEA, 0x35, 0x99, 0xCF, 0xA6, 0xE4, + 0x53, 0x4A, 0xA1, 0x37, 0x0D, 0x8B, 0xF9, 0x43, 0x1B, 0xE7, 0xF8, 0xF3, 0x39, 0x6B, 0x17, 0x15, 0x3D, 0x40, 0x0B, 0x43, + 0x84, 0x07, 0xB8, 0x6A, 0x7C, 0xE3, 0x2D, 0x00, 0xA3, 0x47, 0x1A, 0x84, 0x09, 0x4C, 0xCB, 0x79, 0x6E, 0x81, 0xBA, 0x9A, + 0x1A, 0x13, 0x08, 0x6D, 0xD2, 0xB7, 0x22, 0xDE, 0x2F, 0x99, 0x29, 0xE5, 0xEC, 0xEA, 0xC8, 0x1A, 0x1E, 0x29, 0x5F, 0xD1, + 0xAC, 0xDF, 0x19, 0xCD, 0xD1, 0xA8, 0x63, 0x78, 0x90, 0x2B, 0x9A, 0x7C, 0xF8, 0xC6, 0x09, 0xA5, 0x7B, 0x47, 0xCD, 0x29, + 0x3D, 0x69, 0xD0, 0x68, 0xEF, 0x72, 0xAD, 0x2B, 0x1D, 0x95, 0x42, 0x39, 0xC1, 0x89, 0x04, 0x06, 0x36, 0xAF, 0x39, 0x4A, + 0x8E, 0x0C, 0xD8, 0xFE, 0x9E, 0x03, 0x0C, 0x5F, 0xA7, 0x2D, 0x95, 0x66, 0xB5, 0x7A, 0x51, 0xDF, 0x01, 0xEF, 0xBA, 0x63, + 0xF4, 0xE9, 0x6E, 0x41, 0x23, 0x38, 0xC5, 0x21, 0x8B, 0x28, 0x5C, 0x7B, 0x7D, 0x11, 0x47, 0x2D, 0x69, 0x25, 0xDF, 0xF8, + 0xDB, 0xC4, 0x58, 0x15, 0x0B, 0x12, 0x21, 0xC6, 0x74, 0x8C, 0xD1, 0xEF, 0x1F, 0x00, 0xE9, 0xFF, 0xE4, 0x11, 0x5C, 0x48, + 0x34, 0x4A, 0x9D, 0xD3, 0x87, 0x4F, 0xEE, 0x7D, 0x47, 0xB0, 0x9B, 0x54, 0x8D, 0x18, 0x1F, 0xFC, 0x89, 0x6C, 0xA4, 0x90, + 0xD0, 0x9E, 0x40, 0x05, 0x32, 0xB9, 0x44, 0x30, 0xB8, 0xAE, 0x22, 0x42, 0xD4, 0x0E, 0x98, 0xDE, 0x5B, 0x94, 0x65, 0x9A, + 0xC6, 0x4F, 0x4D, 0x84, 0x0D, 0x3A, 0xEF, 0xA0, 0x84, 0xB0, 0x99, 0xEC, 0x06, 0x2E, 0xAF, 0x88, 0xB2, 0xB7, 0x82, 0x51, + 0x41, 0x32, 0xE7, 0xB0, 0x81, 0xB1, 0x88, 0x42, 0xDA, 0xB4, 0x48, 0x84, 0xB5, 0x60, 0x34, 0xDD, 0x6E, 0xB8, 0x7C, 0x86, + 0x97, 0xFB, 0x8E, 0xCD, 0xE9, 0x18, 0x92, 0x45, 0x5C, 0x33, 0xDB, 0x65, 0x86, 0x7A, 0x35, 0x14, 0xF5, 0xBD, 0xC9, 0x81, + 0x25, 0x42, 0x07, 0xD8, 0x78, 0x3B, 0x5D, 0x21, 0x32, 0x10, 0x41, 0x05, 0x74, 0xBE, 0x13, 0x40, 0xCC, 0x11, 0x6D, 0x24, + 0x53, 0x18, 0x1B, 0x02, 0x25, 0x97, 0x37, 0x15, 0x75, 0xBF, 0xE2, 0x0F, 0x6F, 0x6B, 0xA7, 0xF1, 0xB1, 0x1E, 0x0C, 0x0F, + 0xAD, 0xBB, 0x28, 0x5A, 0xDD, 0x47, 0x4E, 0x98, 0xE5, 0x94, 0xE2, 0xED, 0x7E, 0x06, 0xC1, 0x9C, 0x5D, 0x54, 0x01, 0xF1, + 0x1E, 0x4D, 0x47, 0xCF, 0x91, 0x95, 0xEB, 0x4F, 0xB8, 0x4E, 0xE3, 0x7B, 0x6D, 0x62, 0x77, 0x56, 0xD1, 0x86, 0xD0, 0xDC, + 0x6F, 0xAB, 0xF4, 0x9F, 0x68, 0xE6, 0xEB, 0x45, 0x2C, 0xB8, 0xAC, 0x3B, 0x90, 0x30, 0xE6, 0xD0, 0xF8, 0x28, 0x50, 0x3F, + 0xD6, 0xAC, 0x08, 0x74, 0x85, 0x2A, 0xD6, 0x8C, 0x3D, 0x07, 0x10, 0x40, 0xFA, 0xC0, 0xCD, 0xC4, 0xE7, 0x09, 0x1D, 0xA4, + 0x9E, 0x01, 0x05, 0x1C, 0xFD, 0xF5, 0x80, 0x3A, 0x74, 0x8E, 0x99, 0xFD, 0x3B, 0xA8, 0x29, 0x70, 0xFE, 0x71, 0x8F, 0xC8, + 0x5F, 0x74, 0xC4, 0x84, 0x12, 0x63, 0xB1, 0xD0, 0xAD, 0xF1, 0xD0, 0x80, 0x32, 0x0B, 0x3B, 0x9D, 0xBC, 0x08, 0x78, 0x62, + 0x43, 0xFE, 0xFE, 0x03, 0xF1, 0x46, 0x09, 0xA4, 0x17, 0xAA, 0xCE, 0x2B, 0x42, 0x2E, 0x70, 0x72, 0x42, 0xBE, 0x77, 0x66, + 0xEA, 0x9C, 0x40, 0x35, 0xE4, 0x45, 0x2F, 0x8B, 0xA5, 0xB6, 0x79, 0x63, 0xC3, 0x7D, 0x7A, 0xF5, 0x98, 0x44, 0x81, 0x5A, + 0xF3, 0x62, 0xF0, 0x85, 0x06, 0xDD, 0x71, 0x93, 0x88, 0x67, 0x25, 0x86, 0xB0, 0x29, 0x18, 0x57, 0x36, 0x2F, 0xAE, 0x8E, + 0x21, 0xF4, 0x08, 0x68, 0x61, 0x72, 0x07, 0xAC, 0x48, 0x69, 0x94, 0xE5, 0x4C, 0xCE, 0xD0, 0x94, 0x3B, 0x95, 0x37, 0xA0, + 0x9D, 0xF4, 0x17, 0x0F, 0xEE, 0x99, 0x4F, 0xF4, 0x2E, 0xD9, 0x23, 0x6B, 0xD7, 0xCA, 0xD2, 0xC5, 0x84, 0x9F, 0x54, 0xBA, + 0x94, 0xCD, 0x55, 0x9E, 0xA1, 0xA4, 0x2E, 0x1B, 0xB0, 0x01, 0x89, 0xD5, 0xF2, 0x6B, 0xF6, 0xAB, 0x26, 0x88, 0xE6, 0x93, + 0xE7, 0x29, 0x7D, 0x17, 0x5E, 0x05, 0x3A, 0xD8, 0xF5, 0x07, 0x44, 0x88, 0x33, 0xBF, 0x4B, 0x22, 0xAD, 0x9E, 0xFA, 0xEE, + 0xDE, 0x9D, 0xEA, 0x6E, 0xF2, 0xF2, 0xD6, 0xCE, 0x1F, 0x02, 0x28, 0xC6, 0xB4, 0x98, 0xBA, 0xD6, 0xA4, 0xE0, 0x93, 0x4F, + 0xA8, 0x11, 0xD9, 0x4F, 0xE0, 0x68, 0x51, 0x3A, 0xE9, 0x45, 0x03, 0xEA, 0x21, 0xE3, 0x0F, 0x9D, 0xF8, 0x56, 0xF8, 0x6E, + 0xB8, 0x9A, 0xE0, 0x16, 0x96, 0x1E, 0xBB, 0xB7, 0xD8, 0xCB, 0x25, 0x88, 0x48, 0x87, 0x62, 0xBD, 0x96, 0x2C, 0x12, 0x57, + 0x42, 0x20, 0xAD, 0x4B, 0xFB, 0xDD, 0xEC, 0xA3, 0x68, 0x7F, 0xAD, 0x1C, 0x53, 0x80, 0x5A, 0x63, 0x85, 0xE6, 0x7D, 0x7A, + 0x8F, 0x09, 0x86, 0x75, 0x8C, 0x4C, 0xFD, 0x4B, 0x65, 0x40, 0x7B, 0xAB, 0xA1, 0x88, 0xAC, 0x1F, 0xF4, 0xF1, 0xDC, 0xDD, + 0x8D, 0xEB, 0x6B, 0xA3, 0x62, 0xD0, 0x3D, 0x74, 0x2A, 0xE0, 0x6F, 0x5A, 0x7A, 0x03, 0x23, 0x76, 0xA5, 0x60, 0xB0, 0x77, + 0x1A, 0xBB, 0xD4, 0xD5, 0x0B, 0x5D, 0xA6, 0x56, 0x30, 0xEF, 0xA4, 0x94, 0xA6, 0x71, 0xD6, 0x07, 0x47, 0xC4, 0x80, 0xC2, + 0x96, 0x8C, 0xCC, 0x31, 0x33, 0xC4, 0xAD, 0x00, 0x25, 0x02, 0x9D, 0xB8, 0x5B, 0x76, 0x6B, 0x89, 0xE6, 0x8B, 0x3A, 0xDF, + 0x2D, 0x33, 0x9D, 0x31, 0x9D, 0x90, 0x2D, 0x6B, 0xDA, 0x3B, 0xB1, 0x22, 0xD1, 0x59, 0x01, 0xC7, 0x0E, 0x31, 0xE8, 0x5F, + 0x21, 0x24, 0x7B, 0x9A, 0xB1, 0x39, 0xB8, 0x60, 0x9E, 0x74, 0x14, 0x14, 0x55, 0xC5, 0xF5, 0xC1, 0x17, 0x11, 0xC4, 0xD1, + 0x4C, 0x15, 0x76, 0x20, 0xC0, 0xDD, 0xA7, 0xB3, 0xAD, 0x7F, 0x9A, 0x2F, 0xA4, 0xE4, 0x3A, 0xBB, 0x3D, 0xC0, 0xF9, 0xA3, + 0x61, 0xEB, 0x15, 0x84, 0x7B, 0x7B, 0x76, 0x53, 0x49, 0x50, 0x5D, 0x28, 0xB3, 0x76, 0x5C, 0x02, 0x29, 0xFC, 0x5F, 0xAA, + 0x02, 0x8B, 0x5F, 0xA3, 0x8D, 0x13, 0x86, 0x9F, 0x7B, 0x10, 0x02, 0x58, 0x49, 0x89, 0xCC, 0xBF, 0x5A, 0xA8, 0x0C, 0xEB, + 0x34, 0x10, 0xB9, 0x38, 0xC9, 0x1A, 0x61, 0xC5, 0x48, 0x3B, 0x9A, 0x47, 0x06, 0xBB, 0xC0, 0xFA, 0xFD, 0x11, 0x32, 0x2D, + 0x0C, 0xCB, 0xD7, 0xDC, 0x8F, 0x57, 0x81, 0xDE, 0xD5, 0xF3, 0x0D, 0xEB, 0x9A, 0x03, 0x0F, 0xE0, 0xDF, 0x55, 0x45, 0x50, + 0x91, 0x19, 0x1F, 0x4D, 0x31, 0xD6, 0x7E, 0x7A, 0x28, 0xDC, 0xA6, 0x6C, 0x64, 0x31, 0x31, 0xE0, 0xBE, 0x99, 0x7D, 0x97, + 0xAF, 0xCC, 0x16, 0xDD, 0x2D, 0xA6, 0x9E, 0x45, 0x58, 0x1D, 0xFE, 0x09, 0x8B, 0xDD, 0x71, 0xD8, 0x92, 0x87, 0x27, 0xCA, + 0xB7, 0x13, 0xCD, 0xC9, 0x19, 0x38, 0xF0, 0xDE, 0x81, 0xFB, 0xF7, 0x37, 0x27, 0xA3, 0x5E, 0xFD, 0x76, 0x62, 0xB7, 0x5F, + 0x99, 0xCD, 0xF7, 0x73, 0x7F, 0xCB, 0x73, 0x6E, 0xDA, 0x75, 0x79, 0x8A, 0xA1, 0x2B, 0xB2, 0x44, 0x12, 0x8B, 0x28, 0x4C, + 0x65, 0x22, 0x0F, 0xBD, 0xA3, 0xE4, 0x9B, 0xF0, 0x03, 0xDA, 0x38, 0x08, 0x69, 0x55, 0x42, 0x52, 0x47, 0x3D, 0x43, 0x48, + 0x76, 0x61, 0x59, 0xBE, 0x64, 0x7D, 0xCB, 0x1E, 0x14, 0xCF, 0xF1, 0xC2, 0x55, 0x5D, 0xB3, 0x60, 0x2D, 0x14, 0x43, 0x91, + 0x84, 0x64, 0xF9, 0x64, 0xD6, 0x17, 0x02, 0x6C, 0xC3, 0xE8, 0xE2, 0x3B, 0x55, 0x61, 0x8C, 0xD9, 0x05, 0xE4, 0x70, 0x59, + 0x74, 0x2F, 0x12, 0x7C, 0xA2, 0x30, 0x34, 0x9A, 0x56, 0x55, 0x48, 0x95, 0x78, 0x85, 0x4E, 0xAD, 0xEB, 0xB5, 0x26, 0x40, + 0x4F, 0x89, 0x3C, 0x09, 0x59, 0x1A, 0xBE, 0x42, 0xA2, 0x56, 0x24, 0x7A, 0x90, 0xE4, 0xC7, 0x92, 0x2E, 0xA6, 0x0E, 0x19, + 0xA4, 0x8A, 0xF9, 0xD1, 0x8E, 0x5A, 0x29, 0xAE, 0xBA, 0x5A, 0x18, 0x7D, 0x17, 0xB3, 0x69, 0x8A, 0x28, 0x6A, 0x78, 0x0B, + 0xAF, 0xCA, 0xDA, 0x3C, 0x74, 0xA5, 0x46, 0x48, 0xB7, 0x8A, 0x09, 0x5E, 0x54, 0xE1, 0xE5, 0xF2, 0x05, 0xC6, 0x51, 0x61, + 0x7D, 0xA0, 0xBF, 0x38, 0xA8, 0x88, 0xE1, 0x2A, 0xDD, 0xF9, 0xFF, 0xC1, 0x6D, 0x25, 0x5C, 0x7C, 0x3F, 0xC9, 0x6C, 0xD6, + 0xDA, 0x1A, 0x37, 0x91, 0x90, 0x6A, 0x72, 0x99, 0x6A, 0x90, 0xD5, 0xBB, 0x68, 0x28, 0x9C, 0x0E, 0xAE, 0x92, 0x00, 0xCE, + 0x7E, 0xBB, 0x5A, 0x1A, 0x06, 0xCE, 0xCA, 0x2C, 0x7D, 0xDA, 0x55, 0x9B, 0xD2, 0xDE, 0x09, 0x95, 0x6D, 0xCA, 0xFB, 0xD8, + 0xE5, 0xCA, 0xF1, 0xA1, 0xE7, 0x9D, 0x05, 0x87, 0x4F, 0xC3, 0x99, 0xBE, 0x41, 0xF6, 0x69, 0x6F, 0x6F, 0x21, 0xF5, 0xFF, + 0x98, 0xEC, 0x9B, 0xE1, 0xEC, 0x18, 0x49, 0x95, 0x27, 0x82, 0x53, 0xA4, 0x66, 0xDE, 0x2B, 0xA6, 0xB2, 0x73, 0x13, 0xFD, + 0x33, 0x8E, 0xD8, 0x09, 0xA6, 0xE6, 0xDC, 0x6A, 0x61, 0xDD, 0xE4, 0xB9, 0x3C, 0xDC, 0xAA, 0x56, 0x07, 0x2F, 0x7B, 0xE1, + 0xBE, 0x59, 0x75, 0xDA, 0x80, 0xFD, 0x0B, 0x01, 0x5E, 0x17, 0xAA, 0x36, 0x08, 0x1A, 0x7C, 0x5F, 0xB3, 0xF2, 0x0F, 0x53, + 0xF8, 0x6D, 0x8D, 0x45, 0x60, 0x74, 0x4D, 0x53, 0xD1, 0x73, 0xFD, 0xB6, 0x15, 0x0D, 0xCA, 0x53, 0xED, 0xDE, 0x2D, 0x66, + 0x77, 0xF3, 0x05, 0x23, 0x46, 0x03, 0x3E, 0xAF, 0x1C, 0x09, 0xCB, 0x99, 0x93, 0x28, 0xDC, 0x96, 0x3E, 0xBB, 0xD1, 0xF9, + 0x0D, 0xA0, 0xB7, 0x62, 0x49, 0x95, 0x32, 0xB0, 0xE6, 0xF7, 0x94, 0x54, 0x32, 0x7F, 0x9F, 0x09, 0x18, 0xD5, 0xBC, 0xE7, + 0xF7, 0xE5, 0x3F, 0xC4, 0xA0, 0x7F, 0x85, 0x67, 0xE0, 0x3B, 0x36, 0x25, 0x74, 0xD5, 0xA5, 0xEA, 0xBE, 0xF5, 0xA9, 0x56, + 0xE4, 0xB7, 0xB7, 0xD2, 0x14, 0x3A, 0x15, 0x31, 0x61, 0x22, 0xAD, 0x77, 0xBF, 0xB5, 0x30, 0x52, 0x8B, 0xD9, 0x9C, 0x7D, + 0xD8, 0x17, 0x16, 0x61, 0x48, 0x9A, 0x1A, 0x3D, 0x19, 0xF2, 0xEE, 0xEA, 0xD9, 0xDB, 0xD0, 0xAC, 0xB8, 0xAF, 0x06, 0x8A, + 0xBC, 0x76, 0xE3, 0x28, 0x59, 0x74, 0x1D, 0x63, 0x14, 0xD5, 0x11, 0x7E, 0x54, 0xEA, 0xEA, 0x1D, 0x11, 0x7B, 0xB1, 0x52, + 0xBA, 0xB8, 0x30, 0x88, 0xAB, 0x33, 0x8C, 0x85, 0x65, 0x0F, 0x9F, 0xC9, 0x8F, 0x02, 0x44, 0xC1, 0x70, 0x0D, 0x9D, 0x3A, + 0x76, 0x2D, 0x19, 0x4A, 0x45, 0x19, 0xE6, 0xA5, 0x93, 0xA0, 0xA9, 0xA4, 0xFE, 0x9C, 0x16, 0x2A, 0xF7, 0xDF, 0xD7, 0xAC, + 0x9C, 0xD8, 0xC1, 0xB4, 0xDA, 0x26, 0xA0, 0xB4, 0x79, 0x46, 0xA7, 0xBE, 0x6F, 0x43, 0x38, 0x9F, 0x3C, 0x0A, 0xB7, 0x1E, + 0x91, 0x82, 0x37, 0x16, 0x04, 0xBC, 0xF1, 0x2A, 0x0E, 0x13, 0x00, 0x25, 0x9B, 0x64, 0x7F, 0x05, 0xCD, 0x0F, 0x7E, 0xEE, + 0xA0, 0xBE, 0x3A, 0xF3, 0x64, 0xAD, 0x13, 0xEE, 0xB5, 0xDF, 0x5E, 0xF1, 0x64, 0xED, 0xA7, 0xA0, 0x36, 0x4F, 0x40, 0x95, + 0x62, 0xB6, 0x60, 0x35, 0x4F, 0xDC, 0x50, 0xAD, 0xA8, 0x11, 0xDC, 0x52, 0x51, 0x61, 0x93, 0x46, 0x4A, 0xDA, 0xCB, 0x18, + 0xB1, 0xA0, 0x12, 0xE6, 0x02, 0x62, 0x51, 0x90, 0x31, 0x20, 0x1F, 0x25, 0x87, 0xB9, 0xC3, 0x08, 0xB0, 0xA3, 0x5B, 0xCA, + 0x20, 0xBC, 0x99, 0x35, 0x30, 0x78, 0x48, 0x22, 0x26, 0xDF, 0xD6, 0x7D, 0x14, 0xCD, 0x69, 0x44, 0x29, 0x4B, 0x53, 0xE0, + 0x69, 0x6F, 0xDA, 0xA1, 0x7D, 0x14, 0x58, 0xD0, 0x7D, 0x03, 0x26, 0x76, 0xAA, 0x4A, 0xD9, 0x37, 0x4F, 0x49, 0x75, 0xBC, + 0xA3, 0x7D, 0x1B, 0x36, 0xAF, 0x29, 0xD1, 0x53, 0xA2, 0x4F, 0x39, 0xF4, 0xF6, 0x4A, 0x7E, 0x85, 0x73, 0xAD, 0x97, 0x7D, + 0x59, 0x8C, 0x0B, 0x46, 0x28, 0x23, 0x5F, 0x36, 0xDF, 0x47, 0x30, 0x6A, 0x29, 0xA8, 0x84, 0x41, 0x98, 0x38, 0xD2, 0x91, + 0x03, 0x4E, 0x64, 0xCA, 0x6B, 0xC4, 0xB5, 0x09, 0x6D, 0x0D, 0x14, 0x07, 0xF8, 0x26, 0xAE, 0x47, 0xEA, 0x27, 0x31, 0x4F, + 0x06, 0xB8, 0xB4, 0x3D, 0x8E, 0x51, 0xD9, 0xFF, 0xEC, 0x68, 0xE5, 0xAB, 0x3D, 0x45, 0x6B, 0x09, 0x0D, 0x97, 0xB1, 0xF1, + 0x11, 0xC0, 0x34, 0xFB, 0xCD, 0xFC, 0x79, 0xA9, 0x3C, 0xCD, 0x60, 0x4E, 0x86, 0x62, 0x82, 0xAD, 0x59, 0x17, 0xD7, 0x2C, + 0x61, 0x25, 0xC2, 0x0A, 0xB9, 0x29, 0x53, 0x6C, 0x53, 0x8B, 0x4B, 0x2B, 0x67, 0x42, 0xC2, 0x4F, 0x5C, 0x05, 0x61, 0x08, + 0xCB, 0xCB, 0x99, 0x79, 0x52, 0x8A, 0x23, 0x3A, 0xEE, 0x41, 0x98, 0x6E, 0x52, 0x84, 0x6B, 0xAE, 0x08, 0x5E, 0x94, 0x68, + 0xD3, 0x89, 0x12, 0x42, 0x62, 0x1E, 0x7C, 0x74, 0x6F, 0x3E, 0x7B, 0x5D, 0x4A, 0x42, 0x87, 0x7D, 0xDB, 0x2D, 0x64, 0xC4, + 0x2F, 0x1D, 0xBE, 0x35, 0x1A, 0x9F, 0x4E, 0x35, 0x1C, 0x12, 0x69, 0xD6, 0x5E, 0x2F, 0x46, 0x6B, 0x82, 0x50, 0x34, 0xB0, + 0xD0, 0x8E, 0x46, 0x89, 0x1D, 0xFE, 0x86, 0xB6, 0xC2, 0xFA, 0x4F, 0x7F, 0x03, 0x1F, 0x21, 0xFA, 0x13, 0x36, 0x8B, 0xFB, + 0x41, 0x8D, 0x2A, 0xE2, 0x6E, 0x2F, 0x6D, 0xD1, 0x8F, 0x1C, 0xD7, 0xE1, 0xC9, 0x71, 0xBD, 0xC3, 0x83, 0xF4, 0xBD, 0x3F, + 0xF0, 0x13, 0xE7, 0x33, 0xAE, 0x19, 0xBC, 0x46, 0x33, 0x63, 0xA4, 0x82, 0x23, 0x74, 0xD5, 0x24, 0x36, 0xD9, 0xDE, 0x20, + 0x16, 0xB4, 0xF4, 0x04, 0x6F, 0x3A, 0x56, 0xD2, 0xC0, 0x53, 0x4C, 0x09, 0x3B, 0x34, 0xBA, 0xE5, 0x43, 0xB9, 0xFD, 0x15, + 0x45, 0x39, 0x2D, 0x83, 0xA1, 0xA6, 0xCD, 0xD5, 0x09, 0x89, 0xDF, 0x55, 0xCE, 0xDC, 0xAD, 0x95, 0x01, 0xEA, 0x55, 0x53, + 0x16, 0x58, 0x31, 0x8A, 0x29, 0xAA, 0x66, 0xC9, 0xAC, 0x15, 0x9A, 0xD7, 0x99, 0x93, 0x68, 0xAF, 0x9D, 0x57, 0x21, 0xCC, + 0x5C, 0x85, 0x6E, 0x38, 0x77, 0x14, 0xF6, 0x74, 0x35, 0xE5, 0x66, 0xFA, 0xE5, 0x55, 0x21, 0x27, 0x86, 0x38, 0x4D, 0x72, + 0x0B, 0x5B, 0xFF, 0x98, 0x58, 0xEF, 0x87, 0xEB, 0x49, 0x56, 0x3B, 0x36, 0xF9, 0xFA, 0x45, 0x67, 0x0A, 0x1D, 0x23, 0x18, + 0x6C, 0x59, 0xBF, 0xFB, 0x6A, 0xF0, 0x40, 0xBD, 0xDD, 0xF6, 0x7E, 0x0F, 0xE8, 0x3C, 0xBE, 0xEB, 0xC7, 0x33, 0xE2, 0x97, + 0xC9, 0x1D, 0xB5, 0xAC, 0x36, 0x81, 0x8E, 0x28, 0xD9, 0xBD, 0xEE, 0x3A, 0x2B, 0xB0, 0x26, 0x7A, 0x6A, 0x9A, 0x25, 0xD8, + 0xF6, 0xC0, 0x4F, 0xD8, 0x56, 0xDF, 0x57, 0x25, 0x38, 0xB5, 0x37, 0xA9, 0x04, 0xD3, 0xB0, 0x12, 0x0F, 0xE8, 0xDD, 0xAA, + 0xCF, 0x73, 0x37, 0x35, 0x63, 0xB4, 0x67, 0x29, 0x1C, 0x50, 0x38, 0x02, 0x0A, 0xA9, 0xDF, 0x71, 0x51, 0x89, 0xA6, 0xDC, + 0x30, 0x74, 0x30, 0xE2, 0x48, 0x3B, 0xF4, 0xD6, 0x6E, 0x31, 0xEC, 0xC2, 0x7B, 0x4E, 0x7C, 0x0D, 0x77, 0xDC, 0xA8, 0xCF, + 0x45, 0x80, 0x1B, 0xC5, 0xD9, 0xEC, 0xA7, 0x70, 0xB1, 0xE0, 0xF5, 0x18, 0xB2, 0x36, 0x35, 0x07, 0xBB, 0xC2, 0xCF, 0x21, + 0x35, 0x61, 0xB9, 0x71, 0xC6, 0x5C, 0xB1, 0x9A, 0x8B, 0x0E, 0x63, 0x2A, 0xB9, 0x81, 0x46, 0x45, 0x2E, 0xA1, 0x98, 0x4A, + 0xEF, 0xB5, 0x60, 0x3B, 0x70, 0xA2, 0x58, 0x80, 0xC7, 0xA0, 0x6E, 0x83, 0xEB, 0xEB, 0x32, 0x3B, 0x73, 0xC7, 0xED, 0xA6, + 0x93, 0xAA, 0x26, 0xB0, 0x45, 0x87, 0x22, 0x86, 0x5F, 0xEA, 0x99, 0x67, 0xF1, 0xA6, 0xB1, 0xCF, 0xB4, 0xB6, 0x59, 0x65, + 0x47, 0xC8, 0xE3, 0x0B, 0xD0, 0x0F, 0x75, 0x98, 0x26, 0x38, 0x5D, 0xA7, 0x96, 0xA8, 0xB0, 0x4C, 0x44, 0xC9, 0x46, 0xF3, + 0xBA, 0xE2, 0x5A, 0x68, 0x4D, 0xC8, 0xF0, 0x23, 0xF7, 0xEC, 0xAC, 0x78, 0xED, 0x17, 0xED, 0xD3, 0x5A, 0xC3, 0x55, 0xF8, + 0xAC, 0x01, 0x0E, 0x7C, 0xE2, 0x04, 0x9A, 0x48, 0x2F, 0x6E, 0x3A, 0xC7, 0x22, 0x44, 0x5B, 0x2F, 0x2D, 0x00, 0x99, 0xBE, + 0xB2, 0x05, 0x69, 0x03, 0xB0, 0x65, 0x9A, 0xD0, 0xA7, 0xAA, 0x2F, 0xF9, 0xA9, 0x84, 0x7B, 0x32, 0x76, 0xEF, 0x45, 0x3C, + 0x38, 0xC4, 0xA3, 0xD0, 0x24, 0x9A, 0xDD, 0x0D, 0xD4, 0x84, 0xC2, 0x5B, 0x7D, 0x88, 0x1A, 0x6C, 0xCD, 0xA8, 0xC9, 0x8C, + 0xF2, 0x51, 0xD5, 0xAA, 0xE3, 0x5C, 0x92, 0xF8, 0x0F, 0xEC, 0xAA, 0xF8, 0x4E, 0xAA, 0x16, 0xEC, 0x5B, 0xE5, 0x61, 0x57, + 0x78, 0x4E, 0x9B, 0x68, 0xFD, 0xA2, 0x1B, 0x89, 0x4D, 0xC3, 0x8B, 0x4B, 0x37, 0xE7, 0x15, 0x5D, 0x6E, 0x0C, 0x8B, 0x1F, + 0x21, 0x22, 0x41, 0x99, 0x4D, 0xC7, 0xF8, 0x0C, 0xFE, 0x69, 0xAC, 0x56, 0xC5, 0x9F, 0xCD, 0x6D, 0xCB, 0x3B, 0x5C, 0x2A, + 0x62, 0x6B, 0xCA, 0x92, 0x17, 0xA9, 0x66, 0x69, 0x86, 0x97, 0x83, 0xE9, 0x96, 0x01, 0x06, 0x50, 0xE7, 0xF9, 0x66, 0xD4, + 0x8A, 0x9F, 0x45, 0x23, 0xFA, 0x9F, 0x3F, 0xBE, 0xB2, 0x9B, 0x0C, 0x21, 0xE5, 0xB5, 0xA3, 0x93, 0xF2, 0x1B, 0x7D, 0x0A, + 0x44, 0x9C, 0xDA, 0x01, 0x6E, 0xF2, 0x99, 0xD1, 0xA4, 0xF3, 0xDF, 0xB6, 0xF4, 0xC3, 0x06, 0xD3, 0x27, 0x39, 0x3B, 0x20, + 0x26, 0x3F, 0x4C, 0x32, 0x3A, 0x5C, 0x0F, 0xC2, 0x97, 0x6B, 0x97, 0x22, 0x5F, 0x44, 0xCC, 0x30, 0x04, 0x2E, 0x0E, 0x8C, + 0xC4, 0xB0, 0x5C, 0x84, 0x01, 0x5A, 0xF5, 0xFC, 0x8F, 0x1B, 0x1A, 0x21, 0x57, 0xAD, 0x7D, 0x01, 0x64, 0xDE, 0xB2, 0x98, + 0x8E, 0x59, 0xAD, 0xB2, 0x4D, 0x6A, 0x15, 0xF3, 0x84, 0x5B, 0xC2, 0x11, 0xC3, 0x23, 0x59, 0x95, 0x87, 0x68, 0x46, 0x94, + 0x49, 0x95, 0x7D, 0x1D, 0x43, 0xB1, 0x4E, 0x68, 0xEF, 0xD6, 0x09, 0x1C, 0x78, 0x58, 0xEE, 0x7B, 0xC1, 0xDB, 0x7C, 0x6C, + 0x0E, 0x4E, 0x46, 0x78, 0xCC, 0x9A, 0xD6, 0xAF, 0x19, 0x54, 0x47, 0x2B, 0xB2, 0x95, 0x67, 0xCB, 0xBB, 0xF8, 0x97, 0x69, + 0x60, 0xD4, 0x00, 0x9B, 0xFA, 0x30, 0x6B, 0xFD, 0xE7, 0x31, 0x6F, 0x2B, 0x16, 0xA0, 0x05, 0x45, 0x8E, 0x1F, 0x2D, 0xF8, + 0x3F, 0x5B, 0x1E, 0x3A, 0x09, 0x4D, 0x5E, 0xDE, 0x99, 0xFE, 0x61, 0x6E, 0x2F, 0x15, 0xC9, 0x0E, 0xD5, 0x00, 0x16, 0x2A, + 0x73, 0x6C, 0x56, 0x19, 0xFD, 0xFD, 0xBE, 0x8F, 0x08, 0x70, 0xDA, 0xB3, 0xDE, 0xF4, 0xA7, 0xAA, 0x27, 0x13, 0xB8, 0x9B, + 0x8D, 0x52, 0x2D, 0xEC, 0x86, 0x6F, 0xCC, 0xB0, 0xDA, 0xF8, 0x90, 0xC7, 0x59, 0xCF, 0xE7, 0xD7, 0xB9, 0x7E, 0xE6, 0x19, + 0x8C, 0x6B, 0x7B, 0xFB, 0x98, 0x4E, 0x3E, 0x1D, 0xE3, 0x09, 0x78, 0x86, 0x11, 0x57, 0x6F, 0xA4, 0x7B, 0x37, 0x07, 0xDB, + 0xB1, 0xE3, 0xC8, 0xE9, 0x31, 0x40, 0x39, 0x30, 0x93, 0x22, 0x60, 0xB2, 0x9C, 0x3E, 0x3C, 0x4F, 0xF2, 0x20, 0x85, 0x05, + 0xD1, 0x37, 0xF9, 0x15, 0x33, 0x6C, 0x81, 0xA3, 0x1D, 0xCD, 0x41, 0x3A, 0x54, 0xCD, 0x37, 0xD8, 0x0C, 0x85, 0x0D, 0x67, + 0x32, 0x20, 0xA6, 0xD3, 0x43, 0xBF, 0xDF, 0xFC, 0x38, 0x59, 0x9F, 0x41, 0x06, 0x9D, 0x3F, 0xBB, 0xED, 0xDB, 0xAF, 0x9F, + 0xBD, 0xBB, 0x2F, 0x9B, 0xAD, 0x9B, 0x11, 0xC6, 0xE4, 0x44, 0x37, 0xAB, 0xEC, 0xDA, 0xA7, 0x8F, 0xBC, 0xBA, 0x27, 0x8B, + 0xAC, 0x9A, 0xF8, 0x3E, 0xE2, 0xE6, 0x3E, 0xBA, 0x6D, 0xD9, 0xAE, 0x9E, 0x3D, 0xB9, 0x2E, 0x9A, 0x2D, 0x99, 0xB6, 0xAE, + 0x7C, 0xF8, 0x36, 0xAA, 0x6C, 0xD8, 0xA6, 0x8E, 0x3C, 0xB8, 0x26, 0x8A, 0x2C, 0x98, 0xC1, 0xC8, 0x50, 0xBD, 0x7D, 0xF7, + 0x9A, 0x2B, 0xEB, 0x53, 0xEB, 0x4E, 0x52, 0xD5, 0x36, 0x65, 0xCA, 0xE1, 0x67, 0xD4, 0x1A, 0x6E, 0x1F, 0xB2, 0x0C, 0x5A, + 0x21, 0x44, 0x0A, 0xBE, 0x58, 0x11, 0x4E, 0x18, 0x93, 0xB7, 0x07, 0xFD, 0x90, 0x25, 0xBC, 0xC2, 0xEC, 0xB7, 0x68, 0x0A, + 0x79, 0x95, 0x73, 0x3E, 0x74, 0x04, 0xAD, 0xED, 0x91, 0x24, 0x09, 0xF6, 0xCF, 0xC3, 0xC1, 0x38, 0x7A, 0x6D, 0xBD, 0xB7, + 0xF5, 0xF3, 0x3D, 0xB3, 0xE5, 0xD3, 0xAD, 0x97, 0xB5, 0xB3, 0x2D, 0x93, 0xA5, 0x93, 0xB5, 0xA7, 0xF4, 0xF2, 0x35, 0xA3, + 0xE4, 0xD2, 0xA5, 0x87, 0xB4, 0xB2, 0x25, 0x83, 0xA4, 0x92, 0xBC, 0xB6, 0x75, 0xF1, 0x3C, 0xB2, 0x65, 0xD1, 0xAC, 0x96, + 0x35, 0xB1, 0x2C, 0x92, 0x25, 0x91, 0xB4, 0xA6, 0x74, 0xF0, 0x34, 0xA2, 0x64, 0xD0, 0xA4, 0x86, 0x34, 0xB0, 0x24, 0x82, + 0x24, 0x90, 0xC4, 0x75, 0x23, 0x52, 0xFC, 0x34, 0x92, 0x9F, 0x44, 0x5F, 0x9B, 0x56, 0x54, 0x25, 0xD5, 0xD2, 0xB9, 0xB4, + 0xC0, 0xEE, 0xD3, 0xF4, 0x8D, 0xFB, 0x24, 0x5B, 0x45, 0xDA, 0x5C, 0x55, 0xA3, 0x33, 0x5A, 0x3A, 0xA6, 0x5B, 0x21, 0xA1, + 0xC3, 0x94, 0x1D, 0x5E, 0x41, 0x53, 0xDB, 0x74, 0xBB, 0x33, 0x57, 0x75, 0xDD, 0x51, 0x3C, 0x44, 0xCE, 0x3A, 0x19, 0x35, + 0x92, 0xF7, 0xD9, 0xD3, 0xC5, 0x26, 0xBB, 0x3F, 0xDD, 0xEB, 0x3B, 0x3B, 0xCD, 0xCB, 0xAB, 0x1F, 0x9D, 0xAB, 0x2B, 0x1B, + 0x8D, 0x8B, 0xB3, 0x2F, 0xDC, 0xEA, 0x33, 0x2B, 0xCC, 0xCA, 0xA3, 0x0F, 0x9C, 0xAA, 0x23, 0x0B, 0x8C, 0x8A, 0xBA, 0x3E, + 0x5D, 0xE9, 0x3A, 0x3A, 0x4D, 0xC9, 0xAA, 0x1E, 0x1D, 0xA9, 0x2A, 0x1A, 0x0D, 0x89, 0xB2, 0x2E, 0x5C, 0xE8, 0x32, 0x2A, + 0x4C, 0xC8, 0xA2, 0x0E, 0x1C, 0xA8, 0x22, 0x0A, 0x0C, 0x88, 0x1A, 0xCB, 0x89, 0xC7, 0x5D, 0x03, 0x3C, 0x53, 0xAB, 0x4A, + 0xEA, 0xA4, 0x27, 0x82, 0x5C, 0x03, 0xF9, 0x94, 0x82, 0x59, 0x75, 0xEF, 0x18, 0xED, 0x9E, 0x40, 0xDF, 0x5F, 0xB7, 0x40, + 0xAB, 0x39, 0xAB, 0x0C, 0x0B, 0xEA, 0x66, 0x65, 0xB0, 0x77, 0x6E, 0xDA, 0xA1, 0x55, 0xCE, 0xDF, 0x03, 0x81, 0x52, 0xD5, + 0xDE, 0x1F, 0xF7, 0xAF, 0x42, 0x79, 0x97, 0x64, 0x8A, 0x3B, 0xC0, 0x5C, 0xFF, 0x63, 0xB9, 0x37, 0xD5, 0xE3, 0x39, 0x33, + 0xC5, 0xC3, 0xA9, 0x17, 0x95, 0xA3, 0x29, 0x13, 0x85, 0x83, 0xB1, 0x27, 0xD4, 0xE2, 0x31, 0x23, 0xC4, 0xC2, 0xA1, 0x07, + 0x94, 0xA2, 0x21, 0x03, 0x84, 0x82, 0xB8, 0x36, 0x55, 0xE1, 0x38, 0x32, 0x45, 0xC1, 0xA8, 0x16, 0x15, 0xA1, 0x28, 0x12, + 0x05, 0x81, 0xB0, 0x26, 0x54, 0xE0, 0x30, 0x22, 0x44, 0xC0, 0xA0, 0x06, 0x14, 0xA0, 0x20, 0x02, 0x04, 0x80, 0xB0, 0x22, + 0x1E, 0x82, 0xC0, 0x59, 0xA7, 0xDD, 0x34, 0xA6, 0x4E, 0x85, 0xB8, 0x6A, 0xB5, 0xEF, 0x4A, 0x2A, 0x17, 0xCC, 0xC8, 0x57, + 0xEC, 0xAC, 0xCB, 0xF5, 0x47, 0x34, 0x65, 0x0E, 0x2A, 0xE1, 0xCD, 0xEB, 0x74, 0xCF, 0xD9, 0x03, 0xE7, 0xF5, 0x68, 0x7E, + 0xC0, 0xE0, 0x21, 0x7C, 0x29, 0x5E, 0x33, 0x11, 0x47, 0xA7, 0xE3, 0xE9, 0x36, 0xC6, 0x3D, 0x74, 0x44, 0xCD, 0x62, 0x93, + 0xD1, 0x58, 0x9F, 0xBD, 0xF9, 0x7B, 0x1F, 0xB9, 0xE9, 0x5B, 0x8F, 0x9D, 0xB9, 0x3B, 0x0F, 0x99, 0xA9, 0x1B, 0x97, 0xAD, + 0xF8, 0x7A, 0x17, 0xA9, 0xE8, 0x5A, 0x87, 0x8D, 0xB8, 0x3A, 0x07, 0x89, 0xA8, 0x1A, 0x9E, 0xBC, 0x79, 0x79, 0x1E, 0xB8, + 0x69, 0x59, 0x8E, 0x9C, 0x39, 0x39, 0x0E, 0x98, 0x29, 0x19, 0x96, 0xAC, 0x78, 0x78, 0x16, 0xA8, 0x68, 0x58, 0x86, 0x8C, + 0x38, 0x38, 0x06, 0x88, 0x28, 0x18, 0x2A, 0x0E, 0x83, 0xC9, 0x9A, 0xDE, 0xEB, 0xEA, 0x32, 0xDB, 0x80, 0xE8, 0xEE, 0x75, + 0xA1, 0x54, 0xBE, 0x69, 0x52, 0x82, 0xD2, 0x1A, 0xFD, 0x28, 0x8D, 0x1E, 0xCF, 0xC1, 0x61, 0x9A, 0x59, 0x52, 0x8F, 0x2F, + 0x8A, 0xF1, 0xA9, 0x2B, 0xB8, 0x01, 0x33, 0xE9, 0x4F, 0x8C, 0x6E, 0xAF, 0xA3, 0x7B, 0x28, 0xEA, 0xD2, 0x74, 0xB3, 0xEC, + 0x19, 0x06, 0x86, 0xCB, 0xC5, 0xC4, 0xE7, 0xBB, 0xF6, 0x7D, 0x9D, 0xB5, 0xF1, 0x73, 0x1D, 0xB1, 0xE1, 0x53, 0x8D, 0x95, + 0xB1, 0x33, 0x0D, 0x91, 0xA1, 0x13, 0x95, 0xA5, 0xF0, 0x72, 0x15, 0xA1, 0xE0, 0x52, 0x85, 0x85, 0xB0, 0x32, 0x05, 0x81, + 0xA0, 0x12, 0x9C, 0xB4, 0x71, 0x71, 0x1C, 0xB0, 0x61, 0x51, 0x8C, 0x94, 0x31, 0x31, 0x0C, 0x90, 0x21, 0x11, 0x94, 0xA4, + 0x70, 0x70, 0x14, 0xA0, 0x60, 0x50, 0x84, 0x84, 0x30, 0x30, 0x04, 0x80, 0x20, 0x10, 0xFB, 0xD7, 0x5F, 0xFD, 0xF9, 0x29, + 0x10, 0x4D, 0x4C, 0x26, 0x01, 0x42, 0x4B, 0x5B, 0x13, 0x2B, 0x34, 0x87, 0xA7, 0xB9, 0x13, 0x0D, 0xCA, 0xF0, 0x3E, 0x50, + 0x41, 0x93, 0xDC, 0xF6, 0xDB, 0xFC, 0xE5, 0x6E, 0x01, 0x6F, 0x49, 0x1C, 0xB5, 0x32, 0x55, 0xE7, 0x68, 0x59, 0x35, 0xA3, + 0xCB, 0x61, 0x89, 0xF1, 0xE4, 0xB3, 0x01, 0xEC, 0x6B, 0x4C, 0xE0, 0x62, 0x9A, 0xDA, 0x42, 0xC5, 0x56, 0x0E, 0x9B, 0x3D, + 0xD9, 0x6B, 0x1B, 0x39, 0xC9, 0x4B, 0x8B, 0x1D, 0x99, 0x2B, 0x0B, 0x19, 0x89, 0x0B, 0x93, 0x2D, 0xD8, 0x6A, 0x13, 0x29, + 0xC8, 0x4A, 0x83, 0x0D, 0x98, 0x2A, 0x03, 0x09, 0x88, 0x0A, 0x9A, 0x3C, 0x59, 0x69, 0x1A, 0x38, 0x49, 0x49, 0x8A, 0x1C, + 0x19, 0x29, 0x0A, 0x18, 0x09, 0x09, 0x92, 0x2C, 0x58, 0x68, 0x12, 0x28, 0x48, 0x48, 0x82, 0x0C, 0x18, 0x28, 0x02, 0x08, + 0x08, 0x08, 0x5E, 0xAE, 0x1F, 0xB8, 0x36, 0x91, 0xB8, 0x6C, 0xED, 0x89, 0x6A, 0xE0, 0xCE, 0x8A, 0xF9, 0xA9, 0x0F, 0xEC, + 0xFB, 0x1B, 0x6B, 0xE5, 0x9E, 0xDC, 0xBE, 0x56, 0x61, 0x54, 0xE7, 0xF7, 0xDA, 0xB8, 0x9F, 0x75, 0x21, 0x81, 0x03, 0xE0, + 0x9D, 0x7A, 0x88, 0x2F, 0xC1, 0x0B, 0x1B, 0x5F, 0xF8, 0x0C, 0x09, 0xFB, 0x0E, 0x1E, 0x8F, 0x68, 0x99, 0x36, 0x41, 0x66, + 0xDE, 0xFB, 0xE6, 0x39, 0x18, 0x44, 0x99, 0x35, 0xD1, 0x63, 0x19, 0x31, 0xC1, 0x43, 0x89, 0x15, 0x91, 0x23, 0x09, 0x11, + 0x81, 0x03, 0x91, 0x25, 0xD0, 0x62, 0x11, 0x21, 0xC0, 0x42, 0x81, 0x05, 0x90, 0x22, 0x01, 0x01, 0x80, 0x02, 0x98, 0x34, + 0x51, 0x61, 0x18, 0x30, 0x41, 0x41, 0x88, 0x14, 0x11, 0x21, 0x08, 0x10, 0x01, 0x01, 0x90, 0x24, 0x50, 0x60, 0x10, 0x20, + 0x40, 0x40, 0x80, 0x04, 0x10, 0x20, 0x00, 0x00, 0x97, 0x4A, 0x80, 0x05, 0x76, 0x8D, 0xDE, 0x85, 0xB1, 0x8B, 0x52, 0x92, + 0x14, 0x40, 0xCE, 0xA1, 0x58, 0xCB, 0xAC, 0x72, 0x40, 0x81, 0x90, 0xE5, 0x5B, 0x21, 0x24, 0xB2, 0x41, 0xA7, 0xC6, 0xB5, + 0xD3, 0xCA, 0x7F, 0x19, 0x02, 0x2A, 0x41, 0x05, 0xFB, 0xA0, 0x19, 0x24, 0xC4, 0x62, 0x90, 0x05, 0x50, 0x48, 0x71, 0xEC, + 0xC1, 0x41, 0xD7, 0x1D, 0xB1, 0x88, 0x47, 0xD3, 0xCD, 0xC6, 0x59, 0x35, 0xBA, 0xE1, 0x7E, 0x48, 0xC0, 0x06, 0x3F, 0xBA, + 0x14, 0xE4, 0x46, 0xF1, 0xA9, 0xE6, 0xF9, 0x23, 0x7C, 0xE8, 0xFB, 0xC0, 0x05, 0xA5, 0x08, 0x40, 0x82, 0xA8, 0x1A, 0x03, + 0x5F, 0x4C, 0xF1, 0x73, 0x52, 0xE5, 0x49, 0xC5, 0x7E, 0xA4, 0xD4, 0xC1, 0xD6, 0xBB, 0xEA, 0xD0, 0x80, 0xE9, 0x9B, 0x78, + 0x93, 0x67, 0x05, 0x23, 0xEB, 0xA5, 0x36, 0xD1, 0xD7, 0xD2, 0x2F, 0xF3, 0xCA, 0x3A, 0xA3, 0xA1, 0x53, 0x47, 0x80, 0x6A, + 0x73, 0xDA, 0x87, 0x0C, 0x9A, 0x20, 0x3C, 0x2F, 0x20, 0x47, 0x82, 0xDD, 0x12, 0x68, 0x7A, 0x5E, 0xF5, 0x4B, 0xEA, 0x5C, + 0x0C, 0x26, 0x1A, 0x7B, 0x4D, 0x49, 0x9B, 0x1C, 0xD9, 0xA8, 0xDC, 0x08, 0x8E, 0x8A, 0x0E, 0xFD, 0x90, 0x25, 0x3D, 0x2E, + 0xE7, 0x0A, 0xCD, 0xA8, 0xD0, 0xC1, 0x89, 0x63, 0x0B, 0x23, 0x0B, 0x1C, 0x30, 0x80, 0xF1, 0x3D, 0xC9, 0xE4, 0xC5, 0xBC, + 0x5B, 0xC0, 0xBD, 0x3B, 0x48, 0x8F, 0x02, 0x5D, 0x8D, 0x6E, 0x08, 0x75, 0xE9, 0x4A, 0x58, 0x9A, 0x85, 0xE1, 0x74, 0x54, + 0x6A, 0xED, 0xB5, 0xA6, 0xE4, 0xF2, 0xDA, 0x9A, 0xEA, 0xB2, 0xD8, 0x74, 0x59, 0x6C, 0x03, 0xB7, 0x0A, 0x5E, 0x41, 0xF7, + 0x7B, 0x51, 0x5F, 0x07, 0x6B, 0xC6, 0xF3, 0x60, 0xD2, 0x2E, 0x53, 0x4C, 0x77, 0xAD, 0x0B, 0x4D, 0xB1, 0xA2, 0x11, 0x78, + 0x28, 0xC5, 0xD3, 0x7F, 0x59, 0x8F, 0xBF, 0xE2, 0x61, 0x50, 0x03, 0x75, 0x3A, 0x36, 0xBA, 0x51, 0x6A, 0x5C, 0x95, 0x84, + 0x1B, 0x40, 0x74, 0xE3, 0x71, 0x18, 0xCE, 0x1E, 0x5A, 0x93, 0x62, 0x20, 0x8A, 0xF3, 0xD8, 0x36, 0x1A, 0x33, 0x7D, 0xE3, + 0xE3, 0xCD, 0xDB, 0x01, 0xB0, 0x99, 0x4B, 0x25, 0xE0, 0xDF, 0x95, 0xA7, 0xB2, 0xD9, 0x4C, 0x6C, 0xC7, 0x51, 0x8D, 0x64, + 0xA1, 0x23, 0x43, 0xB9, 0xC1, 0xFC, 0x9D, 0x44, 0xB3, 0x7D, 0x3A, 0xCD, 0xAD, 0xB9, 0x04, 0xD0, 0xC3, 0x2F, 0x6C, 0xB0, + 0x66, 0x5B, 0xEE, 0x63, 0xDE, 0x2B, 0x4D, 0x42, 0x23, 0x1D, 0xB3, 0x56, 0xB3, 0x35, 0x26, 0x20, 0x6B, 0x8A, 0xE6, 0x73, + 0xDF, 0x69, 0x40, 0x53, 0x22, 0xBB, 0x3A, 0xB7, 0x55, 0x28, 0x6D, 0x1E, 0xA1, 0x76, 0xEF, 0x62, 0x5E, 0x69, 0x09, 0x20, + 0xB7, 0x13, 0x12, 0xD5, 0xC4, 0x3D, 0xE2, 0x21, 0x14, 0x8F, 0xF3, 0xF3, 0x62, 0x2B, 0x84, 0x62, 0x57, 0x10, 0xD8, 0x85, + 0x38, 0x78, 0x13, 0x2A, 0x69, 0x20, 0xC8, 0x3D, 0x78, 0xF5, 0x70, 0x1A, 0x28, 0xFE, 0xEE, 0x6D, 0x3F, 0x39, 0x26, 0x49, + 0x6F, 0x59, 0xDE, 0x4F, 0x61, 0x7F, 0xDC, 0x8D, 0xAE, 0xBA, 0x83, 0xEE, 0xD3, 0x18, 0x37, 0x3D, 0x83, 0x78, 0xE9, 0x28, + 0x93, 0x6A, 0x55, 0x98, 0x0A, 0xB4, 0xD1, 0x0D, 0x19, 0x90, 0x41, 0x29, 0xC9, 0xF0, 0x97, 0xF0, 0x9A, 0x1B, 0x1C, 0xCA, + 0x42, 0x2C, 0xFC, 0x2E, 0x96, 0xC2, 0x2E, 0x19, 0x3A, 0x7C, 0xF8, 0xEB, 0xEF, 0x73, 0x18, 0xD0, 0xC0, 0x0D, 0xFE, 0x62, + 0x50, 0x09, 0x26, 0x8B, 0x3B, 0x56, 0xF7, 0xB2, 0xB2, 0x19, 0x39, 0xC0, 0xC9, 0xE1, 0xBC, 0x13, 0x0D, 0x95, 0x37, 0x29, + 0x24, 0xD3, 0x63, 0xA7, 0x33, 0x3A, 0x6F, 0xCD, 0x63, 0x2F, 0xCF, 0x2C, 0x33, 0xC0, 0x24, 0x99, 0xBC, 0x54, 0x76, 0x22, + 0x42, 0xA1, 0x9D, 0xF2, 0x58, 0x8F, 0xE4, 0x84, 0x7F, 0xE2, 0xB0, 0x23, 0x44, 0x80, 0x70, 0x26, 0x3F, 0x62, 0x22, 0x16, + 0xA6, 0x8C, 0xF6, 0x87, 0x15, 0x0A, 0x68, 0x36, 0x4D, 0xE9, 0xE6, 0xB3, 0x5D, 0x4A, 0x41, 0x42, 0x31, 0x8F, 0xA1, 0xF6, + 0xD6, 0xA6, 0x35, 0xBE, 0xC0, 0xE2, 0xB9, 0xD6, 0x9E, 0xE2, 0xD6, 0xC3, 0x8D, 0x0C, 0xA8, 0x97, 0x15, 0xA2, 0xB9, 0x32, + 0x82, 0x83, 0xB8, 0x17, 0x55, 0xA1, 0xD3, 0xD2, 0x00, 0x24, 0x1D, 0xBD, 0xE5, 0x5B, 0x74, 0x9C, 0xBB, 0x4E, 0xF2, 0x14, + 0x21, 0xC4, 0x32, 0x4F, 0xA4, 0x83, 0xD2, 0xB9, 0xEC, 0x3A, 0xF0, 0x4E, 0xA6, 0xCA, 0x07, 0xA6, 0x29, 0xE6, 0x2D, 0xC1, + 0x8F, 0xFB, 0x1A, 0xC3, 0x9A, 0xCB, 0x8A, 0x3F, 0x65, 0xC0, 0x15, 0x07, 0x24, 0x83, 0x65, 0x3D, 0x26, 0x0F, 0x16, 0xA9, + 0x91, 0x27, 0x19, 0x33, 0xDA, 0x4C, 0xC7, 0x7E, 0x94, 0x15, 0x68, 0x0B, 0xFB, 0x75, 0xFC, 0x8F, 0x9E, 0x03, 0x36, 0x5A, + 0x48, 0xE8, 0xEC, 0xAF, 0xDE, 0x43, 0x4A, 0x5B, 0xF0, 0x02, 0xCA, 0xEF, 0x57, 0xA9, 0xBA, 0x3B, 0x9F, 0x89, 0xA2, 0xCF, + 0x17, 0xE9, 0x69, 0xF5, 0xD9, 0x85, 0x63, 0x0F, 0xF7, 0x28, 0x6D, 0x2F, 0xC4, 0xDE, 0x73, 0x2F, 0xB7, 0x68, 0xAC, 0xF9, + 0x0F, 0xA3, 0xF5, 0x17, 0x8D, 0xAF, 0x3F, 0x99, 0xC9, 0xEB, 0xE5, 0xBA, 0xD5, 0x40, 0xE2, 0xA8, 0xAF, 0x73, 0x3A, 0x3C, + 0xE1, 0x73, 0xF6, 0x88, 0xCC, 0xC4, 0x09, 0x1C, 0xD0, 0x89, 0x6E, 0xA4, 0xF2, 0x07, 0x68, 0xDE, 0x19, 0x6D, 0x76, 0x05, + 0x2C, 0x3D, 0xB0, 0x3C, 0x37, 0xE0, 0x29, 0x4A, 0x6D, 0x04, 0x23, 0x5E, 0x95, 0xEC, 0xFA, 0x19, 0x6D, 0xC8, 0xEB, 0x6E, + 0x8A, 0x12, 0x90, 0x07, 0x2C, 0x02, 0x63, 0x7B, 0x1A, 0x5A, 0x03, 0xF9, 0xC6, 0x12, 0xE3, 0x55, 0xDE, 0xF8, 0x55, 0x44, + 0xD4, 0xDE, 0xE2, 0x86, 0xB4, 0xD3, 0x72, 0xA2, 0x0F, 0xC0, 0xCC, 0x24, 0x7D, 0x8D, 0x76, 0x93, 0x86, 0x97, 0x6C, 0x96, + 0x5E, 0x33, 0x5C, 0xF2, 0x78, 0x5C, 0xB0, 0xD8, 0xD4, 0x79, 0x92, 0x01, 0xA1, 0x63, 0xFB, 0x06, 0x36, 0x19, 0x25, 0x52, + 0xFC, 0xD2, 0xEF, 0xBA, 0x57, 0xF4, 0xA5, 0xAF, 0x06, 0x95, 0x85, 0x66, 0xFF, 0xB3, 0x45, 0x31, 0xE4, 0x8B, 0x3D, 0x55, + 0x54, 0x0C, 0xE5, 0x33, 0x3A, 0xB4, 0x64, 0xC3, 0xE0, 0xF4, 0x3F, 0x0D, 0x9D, 0x2B, 0x4A, 0xE4, 0x80, 0x20, 0x5F, 0x42, + 0xDB, 0xD7, 0x58, 0x3C, 0xD6, 0xD3, 0xBC, 0xE6, 0x44, 0x97, 0x7B, 0xED, 0x75, 0xBB, 0xD0, 0xCF, 0x5E, 0x34, 0xE5, 0xC2, + 0x57, 0xD0, 0x8E, 0x67, 0xA2, 0x58, 0xF2, 0xF8, 0xA2, 0x62, 0xDE, 0x52, 0xA1, 0x17, 0x59, 0x97, 0xBB, 0x78, 0x7B, 0x0A, + 0x98, 0x87, 0x8B, 0xB1, 0x51, 0xBB, 0x6E, 0x1D, 0x8D, 0x91, 0xF8, 0x86, 0x3E, 0xBC, 0x34, 0x48, 0x68, 0xF8, 0xFC, 0xAF, + 0x9F, 0x72, 0x16, 0x69, 0x39, 0x14, 0xF0, 0x1A, 0x3D, 0x34, 0x60, 0x3E, 0x6D, 0x72, 0x45, 0xE2, 0xDE, 0x97, 0xDE, 0x09, + 0xAF, 0x7C, 0xA8, 0x7E, 0xB6, 0xBC, 0x0B, 0x5A, 0xE6, 0xD6, 0xB3, 0x51, 0x01, 0x70, 0x51, 0x1E, 0x44, 0xCB, 0xD1, 0x0F, + 0x56, 0x19, 0x7D, 0xFB, 0x6D, 0xEB, 0x81, 0xB6, 0x3F, 0xFB, 0xBE, 0xF5, 0x3A, 0x47, 0xC6, 0xCF, 0x99, 0xAC, 0xB6, 0xFE, + 0x79, 0x9E, 0x82, 0x13, 0x40, 0xBE, 0x10, 0x5E, 0xDA, 0x3E, 0xD4, 0x59, 0x93, 0xA2, 0x7E, 0x7E, 0x2B, 0x79, 0x3E, 0xEA, + 0x83, 0x08, 0x67, 0xB4, 0xC6, 0xDC, 0x08, 0x3D, 0x3E, 0x8F, 0xF5, 0x65, 0xE8, 0xDE, 0x75, 0xD0, 0x02, 0x9C, 0x2B, 0x28, + 0xA5, 0x62, 0xA5, 0xCA, 0xDF, 0x2F, 0xBF, 0xEA, 0x3D, 0x52, 0xF8, 0x7B, 0xBB, 0x0A, 0xB7, 0x1C, 0x06, 0xC0, 0x24, 0x66, + 0x33, 0x40, 0x63, 0x66, 0xEA, 0xBB, 0x94, 0x63, 0xD2, 0x68, 0x78, 0x56, 0xA3, 0xFF, 0x68, 0x1C, 0x33, 0x31, 0xAF, 0xB5, + 0x47, 0x81, 0xBE, 0xEF, 0x05, 0xC5, 0xB6, 0xFC, 0x90, 0x4C, 0x6D, 0x07, 0x98, 0x4E, 0x91, 0xA5, 0x84, 0xB7, 0xA0, 0x47, + 0x3B, 0xD2, 0xF0, 0x57, 0x6B, 0xA7, 0x8C, 0x06, 0xDF, 0x67, 0xAE, 0x0E, 0x9D, 0x01, 0x72, 0x28, 0x19, 0x9D, 0x38, 0x22, + 0x41, 0xF4, 0x2F, 0x36, 0xB1, 0x65, 0xE3, 0x79, 0xBE, 0x94, 0xD0, 0x64, 0x52, 0x64, 0x40, 0xE2, 0xF6, 0x0A, 0xB0, 0x73, + 0x37, 0x25, 0x5C, 0x37, 0xC1, 0x4D, 0xD8, 0x74, 0x53, 0x65, 0x4B, 0x01, 0x21, 0x00, 0xC5, 0x65, 0x92, 0x26, 0xC1, 0xA6, + 0xC0, 0xB3, 0xD1, 0x65, 0xD2, 0x66, 0xFD, 0x2E, 0x20, 0x46, 0xC9, 0x55, 0x93, 0x27, 0xEB, 0x13, 0x28, 0xF7, 0xD9, 0x75, + 0xD3, 0x67, 0x42, 0x0E, 0xC0, 0xF8, 0xA4, 0x98, 0x94, 0xA3, 0x90, 0x17, 0xB4, 0x4A, 0xD2, 0xAA, 0xA4, 0x9D, 0x08, 0xDE, + 0xAB, 0x4C, 0x71, 0x3A, 0x09, 0xA4, 0x99, 0x3E, 0x81, 0xF9, 0x19, 0x06, 0x01, 0x28, 0xA7, 0xF5, 0x08, 0xF1, 0x87, 0xEF, + 0x9E, 0xEA, 0xD3, 0x3D, 0x34, 0xEE, 0xD3, 0x13, 0x84, 0xDF, 0x79, 0xBC, 0x2D, 0xEC, 0x5F, 0xE2, 0x1A, 0x25, 0xBF, 0x5B, + 0x65, 0xB4, 0x77, 0xBD, 0x25, 0x4B, 0xAA, 0xFB, 0x8F, 0x4B, 0xC2, 0x4C, 0x1A, 0x2C, 0x74, 0xB7, 0x1E, 0x0A, 0xD2, 0x6C, + 0x5A, 0x6C, 0x3E, 0xA5, 0x2A, 0x4F, 0xCA, 0x5C, 0x1B, 0x2D, 0xD9, 0x5C, 0xC4, 0x4F, 0xDA, 0x7C, 0x5B, 0x6D, 0x83, 0x5D, + 0x78, 0x42, 0xC3, 0x4D, 0x9A, 0x2E, 0xE4, 0x57, 0x92, 0xBB, 0xD3, 0x6D, 0xDA, 0x6E, 0xC9, 0x66, 0x0E, 0x08, 0xCB, 0x5D, + 0x9B, 0x2F, 0xEC, 0x78, 0x46, 0x49, 0xDB, 0x7D, 0xDB, 0x6F, 0x80, 0x04, 0x64, 0xE5, 0x0C, 0x86, 0xC5, 0x3F, 0x74, 0xE4, + 0x6F, 0x5D, 0xBC, 0x66, 0xF2, 0x78, 0xBB, 0xAF, 0x79, 0x53, 0x48, 0x11, 0x72, 0xC2, 0x94, 0xC8, 0x80, 0x5E, 0xFC, 0xF4, + 0x8A, 0x7C, 0x3F, 0x7E, 0xA6, 0xD2, 0x31, 0xFA, 0x13, 0x8F, 0x5F, 0x7E, 0x43, 0x54, 0x7A, 0x55, 0xA8, 0x7D, 0x8F, 0xAE, + 0x5D, 0xC3, 0xED, 0xD1, 0x8C, 0x3C, 0x7D, 0xF5, 0xD8, 0x5C, 0xEF, 0xAC, 0xB1, 0x88, 0x3C, 0xE4, 0xA7, 0x33, 0xC4, 0xC4, + 0x32, 0x34, 0x94, 0xF4, 0x9E, 0x18, 0xD4, 0xE4, 0x72, 0x74, 0xFB, 0x2D, 0x33, 0x5B, 0xCC, 0xD4, 0x33, 0x35, 0xF4, 0x53, + 0x1C, 0xD5, 0xDC, 0xF4, 0x73, 0x75, 0x9A, 0xD0, 0xA4, 0xD6, 0xC5, 0xC5, 0xB2, 0x36, 0x25, 0x27, 0x48, 0x17, 0xD5, 0xE5, + 0xF2, 0x76, 0x3D, 0xF7, 0x41, 0x74, 0xCD, 0xD5, 0xB3, 0x37, 0x9D, 0xE5, 0x1F, 0x1B, 0xDD, 0xF5, 0xF3, 0x77, 0xC6, 0x9C, + 0xD4, 0xBC, 0x16, 0x92, 0x60, 0xCC, 0xA2, 0x4A, 0xEA, 0x10, 0x92, 0xAE, 0x7C, 0x83, 0xAA, 0x65, 0xA9, 0xC2, 0x7E, 0x18, + 0x7D, 0xAE, 0x66, 0xDA, 0x2A, 0xE6, 0x29, 0x98, 0xFC, 0x5E, 0x47, 0x8F, 0x60, 0xEA, 0x04, 0x4B, 0x52, 0x76, 0xDB, 0xCB, + 0xAB, 0x85, 0x97, 0x6F, 0x7B, 0x3C, 0x0E, 0x5F, 0x0B, 0x5E, 0x27, 0x3E, 0xC6, 0x3A, 0x67, 0xE6, 0x1C, 0xA7, 0x40, 0xAC, + 0xFF, 0xBB, 0xEE, 0x6A, 0xF5, 0xF3, 0xC6, 0xCC, 0x3A, 0x3C, 0x26, 0x2E, 0xC0, 0x1D, 0xD6, 0xEC, 0x7A, 0x7C, 0xB1, 0xFC, + 0xA9, 0x15, 0xCE, 0xDC, 0x3B, 0x3D, 0xF2, 0xBA, 0xE8, 0x53, 0xDE, 0xFC, 0x7B, 0x7D, 0xEF, 0x6B, 0x2D, 0x39, 0xC7, 0xCD, + 0xBA, 0x3E, 0xBB, 0x69, 0x16, 0x7E, 0xD7, 0xED, 0xFA, 0x7E, 0xF9, 0xBB, 0x5C, 0x19, 0xCF, 0xDD, 0xBB, 0x3F, 0x37, 0x7F, + 0x17, 0x1E, 0xDF, 0xFD, 0xFB, 0x7F, 0xF4, 0x44, 0xA6, 0x7E, 0x40, 0x39, 0x30, 0x1C, 0xF0, 0x36, 0xB8, 0xBE, 0x1C, 0xA4, + 0x55, 0x65, 0xC3, 0x69, 0x9A, 0xBC, 0x2C, 0xE7, 0xB6, 0xA3, 0x4C, 0xB6, 0x0D, 0x9F, 0xD7, 0x2A, 0x9D, 0x3F, 0x5B, 0x87, + 0xC8, 0x92, 0x1E, 0x5C, 0x6D, 0x28, 0x48, 0x65, 0x66, 0x8C, 0x89, 0xD4, 0x8C, 0x46, 0x81, 0xB1, 0x02, 0xA4, 0x9B, 0xE8, + 0x17, 0xEB, 0xF9, 0x27, 0x54, 0x82, 0x3E, 0x24, 0x0A, 0xE1, 0x88, 0xE1, 0x00, 0x24, 0xE0, 0x46, 0x16, 0xA4, 0x78, 0x50, + 0xE7, 0x6B, 0xF0, 0x66, 0x56, 0xE4, 0xF8, 0xD0, 0x06, 0xF2, 0xE8, 0x56, 0x17, 0xA5, 0x98, 0x4D, 0xB3, 0x75, 0xF8, 0x76, + 0x57, 0xE5, 0x88, 0xC7, 0xC2, 0x9A, 0xE1, 0x47, 0x96, 0xA6, 0x76, 0x70, 0x1D, 0x16, 0xF1, 0x67, 0xD6, 0xE6, 0x53, 0xB1, + 0x05, 0x8F, 0xE9, 0x57, 0x97, 0xA7, 0xCE, 0x6F, 0xE3, 0x3A, 0xF9, 0x77, 0xD7, 0xE7, 0xB2, 0x14, 0x54, 0x7C, 0x82, 0x6C, + 0xAB, 0xCD, 0x99, 0x51, 0x99, 0x35, 0x52, 0x11, 0xA0, 0xEA, 0x6A, 0xDC, 0xE7, 0xC5, 0x13, 0x4F, 0xBE, 0x76, 0x62, 0x07, + 0xCF, 0xC1, 0x89, 0x27, 0x79, 0x87, 0xA0, 0x11, 0xD0, 0x3E, 0x9B, 0xDF, 0x41, 0xD5, 0x71, 0x4B, 0xD4, 0x4A, 0x00, 0x32, + 0x24, 0x3A, 0xDB, 0x5D, 0x27, 0x70, 0x16, 0x42, 0x62, 0xAD, 0xEF, 0x49, 0x6E, 0x8A, 0xFB, 0x00, 0xD5, 0x87, 0x93, 0x28, + 0x4D, 0x53, 0xE2, 0x4E, 0x1E, 0xAC, 0xAD, 0x62, 0x60, 0x8A, 0xF2, 0x6E, 0x5E, 0xEC, 0x12, 0xD8, 0x0E, 0x9A, 0xEA, 0x5E, + 0x1F, 0xAD, 0x0A, 0xA5, 0xA0, 0x8C, 0xFA, 0x7E, 0x5F, 0xED, 0x1B, 0x29, 0xCD, 0x7E, 0xE3, 0x4F, 0x9E, 0xAE, 0x81, 0xAD, + 0x6C, 0x82, 0xF3, 0x6F, 0xDE, 0xEE, 0xD0, 0xB9, 0x23, 0x72, 0xEB, 0x5F, 0x9F, 0xAF, 0xD3, 0xD8, 0xB0, 0x0F, 0xFB, 0x7F, + 0xDF, 0xEF, 0x56, 0x27, 0xA1, 0x97, 0x64, 0x92, 0xC8, 0x45, 0xF4, 0xB3, 0x48, 0xD6, 0x03, 0x5B, 0x38, 0xBE, 0x2D, 0x4D, + 0x86, 0xEF, 0x1B, 0x8F, 0x33, 0x71, 0x44, 0x96, 0xEA, 0xD3, 0x45, 0x70, 0xD7, 0xB4, 0xCE, 0x74, 0xA2, 0x72, 0x61, 0x03, + 0xF0, 0x47, 0x3D, 0x06, 0x87, 0xF2, 0xC5, 0xE1, 0x56, 0x0C, 0x16, 0xD5, 0x07, 0xDD, 0x1A, 0xA8, 0xE1, 0xF1, 0x8A, 0xB2, + 0x68, 0xDF, 0xCF, 0x31, 0xED, 0xBF, 0x6C, 0xF5, 0x87, 0xF8, 0xE4, 0xC6, 0x36, 0xB4, 0x14, 0xA2, 0x6A, 0x29, 0xF4, 0xE6, + 0x76, 0xF4, 0xE8, 0x15, 0xA7, 0xB5, 0xEC, 0xD6, 0x37, 0xB5, 0x26, 0xF3, 0xC4, 0x94, 0xFC, 0xF6, 0x77, 0xF5, 0x86, 0x84, + 0x78, 0x9E, 0xE5, 0xC7, 0xB6, 0xB6, 0x0D, 0x61, 0xE7, 0x96, 0xF5, 0xE7, 0xF6, 0xF6, 0xC1, 0x13, 0x04, 0xD6, 0xED, 0xD7, + 0xB7, 0xB7, 0x1D, 0xB3, 0xFA, 0x5C, 0xFD, 0xF7, 0xF7, 0xF7, 0x52, 0xAE, 0xF8, 0x28, 0x24, 0xB1, 0xB9, 0xBF, 0x5E, 0xB4, + 0x2A, 0x2C, 0xC6, 0x8E, 0x64, 0x35, 0x09, 0x1A, 0xAA, 0x3E, 0x47, 0x1A, 0x79, 0xA5, 0x81, 0xDA, 0xDA, 0x7D, 0x84, 0x5C, + 0xFF, 0xF1, 0x80, 0x97, 0x7C, 0x6A, 0x4F, 0x2C, 0xBA, 0x1A, 0xF1, 0x2F, 0xA4, 0xAD, 0x27, 0x2D, 0xFD, 0x1D, 0x87, 0x3D, + 0xAB, 0x5B, 0x3F, 0x58, 0xBF, 0x4E, 0xF9, 0xBD, 0x25, 0x19, 0x4D, 0xDD, 0xBE, 0x24, 0x8A, 0x4A, 0xD2, 0xBC, 0xE6, 0xCE, + 0x3E, 0xBC, 0xF2, 0x08, 0xEC, 0xD4, 0xF6, 0xEE, 0x7E, 0xFC, 0x56, 0x29, 0x77, 0x39, 0xEE, 0xDE, 0x3F, 0xBD, 0x1E, 0xBA, + 0xC2, 0x20, 0xFE, 0xFE, 0x7F, 0xFD, 0xCB, 0x49, 0xAF, 0xCB, 0xE7, 0xCF, 0xBE, 0xBE, 0xFE, 0x99, 0x4D, 0x9F, 0xF7, 0xEF, + 0xFE, 0xFE, 0x80, 0xC7, 0x29, 0x6A, 0xEF, 0xDF, 0xBF, 0xBF, 0x07, 0xDF, 0x6D, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x04, 0x10, 0x20, 0x10, 0x20, 0x40, 0x40, 0x90, 0x24, 0x50, 0x60, 0x08, 0x10, 0x01, 0x01, 0x88, 0x14, + 0x11, 0x21, 0x18, 0x30, 0x41, 0x41, 0x98, 0x34, 0x51, 0x61, 0x01, 0x01, 0x80, 0x02, 0x81, 0x05, 0x90, 0x22, 0x11, 0x21, + 0xC0, 0x42, 0x91, 0x25, 0xD0, 0x62, 0x09, 0x11, 0x81, 0x03, 0x89, 0x15, 0x91, 0x23, 0x19, 0x31, 0xC1, 0x43, 0x99, 0x35, + 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, 0x52, 0x64, 0x48, 0x50, + 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, 0x82, 0x06, 0xC1, 0x45, + 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, 0x93, 0x27, 0x59, 0x71, + 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0x02, 0x08, 0x08, 0x08, 0x82, 0x0C, 0x18, 0x28, 0x12, 0x28, 0x48, 0x48, 0x92, 0x2C, + 0x58, 0x68, 0x0A, 0x18, 0x09, 0x09, 0x8A, 0x1C, 0x19, 0x29, 0x1A, 0x38, 0x49, 0x49, 0x9A, 0x3C, 0x59, 0x69, 0x03, 0x09, + 0x88, 0x0A, 0x83, 0x0D, 0x98, 0x2A, 0x13, 0x29, 0xC8, 0x4A, 0x93, 0x2D, 0xD8, 0x6A, 0x0B, 0x19, 0x89, 0x0B, 0x8B, 0x1D, + 0x99, 0x2B, 0x1B, 0x39, 0xC9, 0x4B, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, 0x1A, 0x2C, 0x52, 0x68, + 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, 0x4B, 0x4D, 0xDA, 0x7C, + 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, 0xDA, 0x6E, 0x4B, 0x59, + 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, 0x20, 0x10, 0x84, 0x84, + 0x30, 0x30, 0x14, 0xA0, 0x60, 0x50, 0x94, 0xA4, 0x70, 0x70, 0x0C, 0x90, 0x21, 0x11, 0x8C, 0x94, 0x31, 0x31, 0x1C, 0xB0, + 0x61, 0x51, 0x9C, 0xB4, 0x71, 0x71, 0x05, 0x81, 0xA0, 0x12, 0x85, 0x85, 0xB0, 0x32, 0x15, 0xA1, 0xE0, 0x52, 0x95, 0xA5, + 0xF0, 0x72, 0x0D, 0x91, 0xA1, 0x13, 0x8D, 0x95, 0xB1, 0x33, 0x1D, 0xB1, 0xE1, 0x53, 0x9D, 0xB5, 0xF1, 0x73, 0x44, 0xC0, + 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, 0x23, 0x15, 0xCC, 0xD4, + 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, 0xB2, 0x36, 0x55, 0xE1, + 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, 0xE3, 0x57, 0xDD, 0xF5, + 0xF3, 0x77, 0x06, 0x88, 0x28, 0x18, 0x86, 0x8C, 0x38, 0x38, 0x16, 0xA8, 0x68, 0x58, 0x96, 0xAC, 0x78, 0x78, 0x0E, 0x98, + 0x29, 0x19, 0x8E, 0x9C, 0x39, 0x39, 0x1E, 0xB8, 0x69, 0x59, 0x9E, 0xBC, 0x79, 0x79, 0x07, 0x89, 0xA8, 0x1A, 0x87, 0x8D, + 0xB8, 0x3A, 0x17, 0xA9, 0xE8, 0x5A, 0x97, 0xAD, 0xF8, 0x7A, 0x0F, 0x99, 0xA9, 0x1B, 0x8F, 0x9D, 0xB9, 0x3B, 0x1F, 0xB9, + 0xE9, 0x5B, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, 0x6A, 0x5C, 0xD6, 0xEC, + 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, 0x7B, 0x7D, 0x47, 0xC9, + 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, 0xAB, 0x1F, 0xCF, 0xDD, + 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x20, 0x02, 0x04, 0x80, 0xA0, 0x06, 0x14, 0xA0, 0x30, 0x22, + 0x44, 0xC0, 0xB0, 0x26, 0x54, 0xE0, 0x28, 0x12, 0x05, 0x81, 0xA8, 0x16, 0x15, 0xA1, 0x38, 0x32, 0x45, 0xC1, 0xB8, 0x36, + 0x55, 0xE1, 0x21, 0x03, 0x84, 0x82, 0xA1, 0x07, 0x94, 0xA2, 0x31, 0x23, 0xC4, 0xC2, 0xB1, 0x27, 0xD4, 0xE2, 0x29, 0x13, + 0x85, 0x83, 0xA9, 0x17, 0x95, 0xA3, 0x39, 0x33, 0xC5, 0xC3, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, 0x06, 0x84, 0xE0, 0x46, + 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, 0x17, 0xA5, 0x78, 0x72, + 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, 0xC6, 0xC6, 0xF1, 0x67, + 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, 0xD7, 0xE7, 0x22, 0x0A, + 0x0C, 0x88, 0xA2, 0x0E, 0x1C, 0xA8, 0x32, 0x2A, 0x4C, 0xC8, 0xB2, 0x2E, 0x5C, 0xE8, 0x2A, 0x1A, 0x0D, 0x89, 0xAA, 0x1E, + 0x1D, 0xA9, 0x3A, 0x3A, 0x4D, 0xC9, 0xBA, 0x3E, 0x5D, 0xE9, 0x23, 0x0B, 0x8C, 0x8A, 0xA3, 0x0F, 0x9C, 0xAA, 0x33, 0x2B, + 0xCC, 0xCA, 0xB3, 0x2F, 0xDC, 0xEA, 0x2B, 0x1B, 0x8D, 0x8B, 0xAB, 0x1F, 0x9D, 0xAB, 0x3B, 0x3B, 0xCD, 0xCB, 0xBB, 0x3F, + 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, 0x5E, 0xEC, 0x6A, 0x5A, + 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, 0x8E, 0x8E, 0xE3, 0x4F, + 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, 0x9F, 0xAF, 0x7B, 0x7B, + 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x24, 0x82, 0x24, 0x90, 0xA4, 0x86, 0x34, 0xB0, 0x34, 0xA2, 0x64, 0xD0, 0xB4, 0xA6, + 0x74, 0xF0, 0x2C, 0x92, 0x25, 0x91, 0xAC, 0x96, 0x35, 0xB1, 0x3C, 0xB2, 0x65, 0xD1, 0xBC, 0xB6, 0x75, 0xF1, 0x25, 0x83, + 0xA4, 0x92, 0xA5, 0x87, 0xB4, 0xB2, 0x35, 0xA3, 0xE4, 0xD2, 0xB5, 0xA7, 0xF4, 0xF2, 0x2D, 0x93, 0xA5, 0x93, 0xAD, 0x97, + 0xB5, 0xB3, 0x3D, 0xB3, 0xE5, 0xD3, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, 0x36, 0xB4, 0x74, 0xE2, + 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, 0x67, 0xD5, 0xFC, 0xF6, + 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, 0xF6, 0xF6, 0x6D, 0xD3, + 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x8A, 0x2C, 0x98, 0xA6, 0x8E, + 0x3C, 0xB8, 0x36, 0xAA, 0x6C, 0xD8, 0xB6, 0xAE, 0x7C, 0xF8, 0x2E, 0x9A, 0x2D, 0x99, 0xAE, 0x9E, 0x3D, 0xB9, 0x3E, 0xBA, + 0x6D, 0xD9, 0xBE, 0xBE, 0x7D, 0xF9, 0x27, 0x8B, 0xAC, 0x9A, 0xA7, 0x8F, 0xBC, 0xBA, 0x37, 0xAB, 0xEC, 0xDA, 0xB7, 0xAF, + 0xFC, 0xFA, 0x2F, 0x9B, 0xAD, 0x9B, 0xAF, 0x9F, 0xBD, 0xBB, 0x3F, 0xBB, 0xED, 0xDB, 0xBF, 0xBF, 0xFD, 0xFB, 0x66, 0xCA, + 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, 0x2F, 0x9D, 0xEE, 0xDE, + 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, 0xBE, 0xBE, 0x77, 0xEB, + 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, 0xEF, 0xDF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x10, 0x20, 0x10, 0x20, 0x40, 0x40, 0x90, 0x24, 0x50, 0x60, 0x08, 0x10, + 0x01, 0x01, 0x88, 0x14, 0x11, 0x21, 0x18, 0x30, 0x41, 0x41, 0x98, 0x34, 0x51, 0x61, 0x01, 0x01, 0x80, 0x02, 0x81, 0x05, + 0x90, 0x22, 0x11, 0x21, 0xC0, 0x42, 0x91, 0x25, 0xD0, 0x62, 0x09, 0x11, 0x81, 0x03, 0x89, 0x15, 0x91, 0x23, 0x19, 0x31, + 0xC1, 0x43, 0x99, 0x35, 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, + 0x52, 0x64, 0x48, 0x50, 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, + 0x82, 0x06, 0xC1, 0x45, 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, + 0x93, 0x27, 0x59, 0x71, 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0x02, 0x08, 0x08, 0x08, 0x82, 0x0C, 0x18, 0x28, 0x12, 0x28, + 0x48, 0x48, 0x92, 0x2C, 0x58, 0x68, 0x0A, 0x18, 0x09, 0x09, 0x8A, 0x1C, 0x19, 0x29, 0x1A, 0x38, 0x49, 0x49, 0x9A, 0x3C, + 0x59, 0x69, 0x03, 0x09, 0x88, 0x0A, 0x83, 0x0D, 0x98, 0x2A, 0x13, 0x29, 0xC8, 0x4A, 0x93, 0x2D, 0xD8, 0x6A, 0x0B, 0x19, + 0x89, 0x0B, 0x8B, 0x1D, 0x99, 0x2B, 0x1B, 0x39, 0xC9, 0x4B, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, + 0x1A, 0x2C, 0x52, 0x68, 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, + 0x4B, 0x4D, 0xDA, 0x7C, 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, + 0xDA, 0x6E, 0x4B, 0x59, 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, + 0x20, 0x10, 0x84, 0x84, 0x30, 0x30, 0x14, 0xA0, 0x60, 0x50, 0x94, 0xA4, 0x70, 0x70, 0x0C, 0x90, 0x21, 0x11, 0x8C, 0x94, + 0x31, 0x31, 0x1C, 0xB0, 0x61, 0x51, 0x9C, 0xB4, 0x71, 0x71, 0x05, 0x81, 0xA0, 0x12, 0x85, 0x85, 0xB0, 0x32, 0x15, 0xA1, + 0xE0, 0x52, 0x95, 0xA5, 0xF0, 0x72, 0x0D, 0x91, 0xA1, 0x13, 0x8D, 0x95, 0xB1, 0x33, 0x1D, 0xB1, 0xE1, 0x53, 0x9D, 0xB5, + 0xF1, 0x73, 0x44, 0xC0, 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, + 0x23, 0x15, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, + 0xB2, 0x36, 0x55, 0xE1, 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, + 0xE3, 0x57, 0xDD, 0xF5, 0xF3, 0x77, 0x06, 0x88, 0x28, 0x18, 0x86, 0x8C, 0x38, 0x38, 0x16, 0xA8, 0x68, 0x58, 0x96, 0xAC, + 0x78, 0x78, 0x0E, 0x98, 0x29, 0x19, 0x8E, 0x9C, 0x39, 0x39, 0x1E, 0xB8, 0x69, 0x59, 0x9E, 0xBC, 0x79, 0x79, 0x07, 0x89, + 0xA8, 0x1A, 0x87, 0x8D, 0xB8, 0x3A, 0x17, 0xA9, 0xE8, 0x5A, 0x97, 0xAD, 0xF8, 0x7A, 0x0F, 0x99, 0xA9, 0x1B, 0x8F, 0x9D, + 0xB9, 0x3B, 0x1F, 0xB9, 0xE9, 0x5B, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, + 0x6A, 0x5C, 0xD6, 0xEC, 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, + 0x7B, 0x7D, 0x47, 0xC9, 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, + 0xAB, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x20, 0x02, 0x04, 0x80, 0xA0, 0x06, + 0x14, 0xA0, 0x30, 0x22, 0x44, 0xC0, 0xB0, 0x26, 0x54, 0xE0, 0x28, 0x12, 0x05, 0x81, 0xA8, 0x16, 0x15, 0xA1, 0x38, 0x32, + 0x45, 0xC1, 0xB8, 0x36, 0x55, 0xE1, 0x21, 0x03, 0x84, 0x82, 0xA1, 0x07, 0x94, 0xA2, 0x31, 0x23, 0xC4, 0xC2, 0xB1, 0x27, + 0xD4, 0xE2, 0x29, 0x13, 0x85, 0x83, 0xA9, 0x17, 0x95, 0xA3, 0x39, 0x33, 0xC5, 0xC3, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, + 0x06, 0x84, 0xE0, 0x46, 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, + 0x17, 0xA5, 0x78, 0x72, 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, + 0xC6, 0xC6, 0xF1, 0x67, 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, + 0xD7, 0xE7, 0x22, 0x0A, 0x0C, 0x88, 0xA2, 0x0E, 0x1C, 0xA8, 0x32, 0x2A, 0x4C, 0xC8, 0xB2, 0x2E, 0x5C, 0xE8, 0x2A, 0x1A, + 0x0D, 0x89, 0xAA, 0x1E, 0x1D, 0xA9, 0x3A, 0x3A, 0x4D, 0xC9, 0xBA, 0x3E, 0x5D, 0xE9, 0x23, 0x0B, 0x8C, 0x8A, 0xA3, 0x0F, + 0x9C, 0xAA, 0x33, 0x2B, 0xCC, 0xCA, 0xB3, 0x2F, 0xDC, 0xEA, 0x2B, 0x1B, 0x8D, 0x8B, 0xAB, 0x1F, 0x9D, 0xAB, 0x3B, 0x3B, + 0xCD, 0xCB, 0xBB, 0x3F, 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, + 0x5E, 0xEC, 0x6A, 0x5A, 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, + 0x8E, 0x8E, 0xE3, 0x4F, 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, + 0x9F, 0xAF, 0x7B, 0x7B, 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x24, 0x82, 0x24, 0x90, 0xA4, 0x86, 0x34, 0xB0, 0x34, 0xA2, + 0x64, 0xD0, 0xB4, 0xA6, 0x74, 0xF0, 0x2C, 0x92, 0x25, 0x91, 0xAC, 0x96, 0x35, 0xB1, 0x3C, 0xB2, 0x65, 0xD1, 0xBC, 0xB6, + 0x75, 0xF1, 0x25, 0x83, 0xA4, 0x92, 0xA5, 0x87, 0xB4, 0xB2, 0x35, 0xA3, 0xE4, 0xD2, 0xB5, 0xA7, 0xF4, 0xF2, 0x2D, 0x93, + 0xA5, 0x93, 0xAD, 0x97, 0xB5, 0xB3, 0x3D, 0xB3, 0xE5, 0xD3, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, + 0x36, 0xB4, 0x74, 0xE2, 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, + 0x67, 0xD5, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, + 0xF6, 0xF6, 0x6D, 0xD3, 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x8A, + 0x2C, 0x98, 0xA6, 0x8E, 0x3C, 0xB8, 0x36, 0xAA, 0x6C, 0xD8, 0xB6, 0xAE, 0x7C, 0xF8, 0x2E, 0x9A, 0x2D, 0x99, 0xAE, 0x9E, + 0x3D, 0xB9, 0x3E, 0xBA, 0x6D, 0xD9, 0xBE, 0xBE, 0x7D, 0xF9, 0x27, 0x8B, 0xAC, 0x9A, 0xA7, 0x8F, 0xBC, 0xBA, 0x37, 0xAB, + 0xEC, 0xDA, 0xB7, 0xAF, 0xFC, 0xFA, 0x2F, 0x9B, 0xAD, 0x9B, 0xAF, 0x9F, 0xBD, 0xBB, 0x3F, 0xBB, 0xED, 0xDB, 0xBF, 0xBF, + 0xFD, 0xFB, 0x66, 0xCA, 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, + 0x2F, 0x9D, 0xEE, 0xDE, 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, + 0xBE, 0xBE, 0x77, 0xEB, 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, + 0xEF, 0xDF, 0xFF, 0xFF, 0x90, 0xAF +}; + +unsigned char gt915_FW[] = { + 0x00, 0x01, 0x60, 0x00, 0x39, 0x31, 0x37, 0x44, 0x00, 0x00, 0x00, 0x00, 0x50, 0x03, 0x80, 0x00, 0x55, 0x40, 0xBD, 0xDA, + 0xFD, 0x24, 0x34, 0xDF, 0x44, 0x40, 0x44, 0x02, 0xBE, 0x03, 0x08, 0xB4, 0x27, 0x41, 0x8C, 0x90, 0x4C, 0xA4, 0x22, 0xB7, + 0xED, 0x5E, 0x58, 0x34, 0x17, 0xBF, 0x01, 0x08, 0x84, 0x00, 0x72, 0xFC, 0x81, 0xD9, 0x39, 0x25, 0xC8, 0xE2, 0x39, 0x87, + 0x0F, 0xED, 0x09, 0x1D, 0xC9, 0x1A, 0xE9, 0xD5, 0x5F, 0x2E, 0x23, 0xB6, 0x6D, 0x4B, 0xA6, 0xE6, 0xA3, 0x7E, 0x3F, 0x64, + 0xFB, 0x1B, 0x67, 0xA6, 0xF2, 0xB5, 0xF4, 0x02, 0xA9, 0x4B, 0x2B, 0x1F, 0x7C, 0xDB, 0x58, 0x96, 0x51, 0xDA, 0x75, 0x4A, + 0xB0, 0xA0, 0x5D, 0x1B, 0x2B, 0x01, 0x0C, 0x9B, 0x51, 0x8B, 0x3F, 0xA3, 0x77, 0x82, 0xEE, 0xF4, 0x31, 0xB9, 0xE5, 0x03, + 0xE6, 0x4C, 0xEA, 0xC0, 0x21, 0x1B, 0x7E, 0xB3, 0xE8, 0x08, 0x32, 0x7E, 0x30, 0x5A, 0x20, 0x67, 0x60, 0x57, 0x5D, 0xFE, + 0xD2, 0xE7, 0xD2, 0xAC, 0x2E, 0x48, 0x98, 0x22, 0x39, 0xB8, 0x96, 0xDE, 0xC8, 0x68, 0x3A, 0x8E, 0xDF, 0x4F, 0x9A, 0x18, + 0x09, 0x49, 0xC2, 0x8F, 0xF8, 0x26, 0x3A, 0x11, 0xA8, 0x2F, 0x35, 0x42, 0x84, 0x94, 0x8C, 0x7B, 0x2B, 0x6F, 0x43, 0x51, + 0x03, 0x2C, 0xEB, 0x21, 0x17, 0xC5, 0x03, 0xA9, 0xD0, 0x1C, 0xCE, 0x8B, 0x89, 0x0B, 0xEB, 0xDD, 0x5B, 0x24, 0xAF, 0xD3, + 0x8A, 0xAB, 0x44, 0x35, 0xF7, 0x2D, 0x43, 0x37, 0x76, 0xF3, 0x65, 0xAE, 0xFA, 0xD0, 0xE8, 0x4C, 0xF4, 0x93, 0x6F, 0xE7, + 0xE5, 0x9C, 0xCC, 0xD2, 0x08, 0xCD, 0x9F, 0xA2, 0xFA, 0xBE, 0x23, 0x1E, 0xA0, 0x42, 0x23, 0x58, 0x68, 0x7F, 0x7C, 0xEC, + 0x71, 0x06, 0xED, 0xAF, 0xEE, 0x92, 0xD2, 0x02, 0xA2, 0x0A, 0xBA, 0x1E, 0x3B, 0x51, 0x25, 0xBB, 0x2C, 0x4E, 0xB0, 0x33, + 0x7B, 0x9E, 0x5A, 0x1F, 0xEF, 0xE2, 0x64, 0x40, 0x24, 0xB2, 0x04, 0x80, 0x78, 0xF8, 0xBE, 0x7B, 0x36, 0xC1, 0x74, 0x7C, + 0xAD, 0xDD, 0x04, 0xDB, 0xA8, 0x7F, 0xDE, 0xB0, 0x26, 0xE9, 0xAF, 0x3C, 0xE9, 0x02, 0x6F, 0x97, 0x9E, 0xDB, 0xBF, 0x56, + 0x91, 0x60, 0x4F, 0x28, 0x82, 0x11, 0x94, 0x81, 0xC5, 0xA9, 0xCE, 0xA0, 0x6E, 0x5B, 0xA7, 0x8F, 0x53, 0x8E, 0x02, 0x1D, + 0x24, 0xE6, 0x2C, 0x39, 0x2D, 0x40, 0xCA, 0x11, 0x08, 0x63, 0x36, 0xAE, 0x52, 0xF6, 0xBB, 0xB2, 0xF4, 0xCB, 0xFB, 0x4A, + 0xC3, 0x02, 0xC4, 0x20, 0x7A, 0x69, 0xFF, 0x0B, 0x56, 0xDF, 0x76, 0x4B, 0xD8, 0x98, 0xCF, 0x27, 0xB7, 0xE8, 0x5D, 0xC6, + 0xC0, 0x14, 0x23, 0x8A, 0x5D, 0xAA, 0x85, 0xC0, 0x2D, 0x7A, 0xFB, 0xC3, 0x20, 0x3E, 0x43, 0xE7, 0x73, 0x99, 0xAD, 0x65, + 0x0F, 0x87, 0x2E, 0x2B, 0x23, 0x77, 0x28, 0x2B, 0x4A, 0x61, 0xA8, 0x0F, 0xFB, 0x6A, 0xE2, 0x50, 0x08, 0xEB, 0xC6, 0x55, + 0x4C, 0x03, 0x2D, 0xF3, 0xED, 0x76, 0x5C, 0x35, 0x9F, 0xD5, 0x05, 0x52, 0x5C, 0xEF, 0x71, 0x1A, 0xA1, 0x11, 0xFA, 0x61, + 0x07, 0x7B, 0x9D, 0xE7, 0x2A, 0x55, 0x8B, 0xC3, 0xA1, 0x76, 0xF8, 0xFB, 0x4F, 0x04, 0xF1, 0xCB, 0x1E, 0x76, 0xF3, 0x8E, + 0xC9, 0x7A, 0x97, 0xA0, 0x0E, 0x7A, 0xD0, 0xDB, 0xDE, 0xE3, 0x8B, 0x0E, 0x45, 0x28, 0x09, 0xDB, 0xC8, 0x4E, 0xBD, 0x42, + 0x01, 0x74, 0x86, 0xC9, 0xA5, 0x1F, 0xB9, 0xB6, 0xA0, 0xA3, 0x40, 0xEE, 0xFB, 0x13, 0x02, 0xB6, 0xEB, 0x1F, 0xA9, 0x27, + 0xCA, 0xCB, 0xF4, 0x82, 0x84, 0xB0, 0xCE, 0x92, 0xB7, 0x52, 0x3B, 0x86, 0xED, 0x60, 0x29, 0xDC, 0x27, 0x93, 0x40, 0x1E, + 0x19, 0xF0, 0x69, 0x0B, 0xFA, 0x11, 0xFE, 0x6D, 0x35, 0x9E, 0xB4, 0xFD, 0x62, 0x10, 0xE0, 0x33, 0x5A, 0xA3, 0x6D, 0xA3, + 0x77, 0x50, 0xBA, 0xBD, 0xEF, 0xC2, 0x20, 0x02, 0x04, 0xC0, 0x7F, 0xAB, 0x12, 0x52, 0x22, 0x3A, 0xD5, 0xAC, 0x42, 0xE0, + 0xF6, 0xAC, 0x28, 0x12, 0x05, 0xC1, 0xAA, 0xEB, 0x74, 0x7A, 0x32, 0x12, 0xD4, 0xA5, 0x4D, 0x37, 0x11, 0xD5, 0x21, 0x1F, + 0x84, 0x82, 0x58, 0x41, 0x60, 0xEE, 0xE5, 0x71, 0x87, 0x32, 0xC1, 0xF8, 0x3B, 0xA3, 0x29, 0x92, 0x85, 0x83, 0xA9, 0x93, + 0xDA, 0x4E, 0x31, 0x23, 0x26, 0x09, 0x19, 0x39, 0x59, 0xEE, 0xCC, 0xC8, 0xFD, 0x74, 0x4B, 0xF7, 0xB5, 0x1B, 0xD4, 0x4E, + 0xAD, 0xA0, 0x24, 0x98, 0xAF, 0x87, 0xC0, 0x81, 0xF6, 0x86, 0xB6, 0xB4, 0x07, 0x0E, 0xCC, 0x19, 0xC9, 0x84, 0xD5, 0xD3, + 0xCE, 0xE7, 0x0F, 0xA1, 0x33, 0xC7, 0xDB, 0xFF, 0x65, 0xE7, 0x4C, 0xE4, 0x2D, 0xC9, 0x8E, 0x1D, 0xF8, 0x79, 0xD7, 0x5A, + 0x21, 0x29, 0x49, 0x57, 0x6A, 0x56, 0x00, 0xDC, 0xCF, 0xE5, 0x17, 0x66, 0x49, 0xDA, 0x22, 0x0A, 0x0C, 0xC8, 0xC2, 0x4E, + 0xA2, 0x23, 0x12, 0x2B, 0x09, 0x07, 0x22, 0xEE, 0x58, 0x05, 0x2A, 0x1A, 0x0D, 0xC9, 0x42, 0x21, 0x9F, 0x7D, 0x3E, 0x3E, + 0x0D, 0xD9, 0x06, 0x1A, 0xC5, 0xAD, 0x23, 0x8F, 0x8C, 0x8A, 0xA7, 0xED, 0x1B, 0xFF, 0xDC, 0x59, 0x4C, 0xBA, 0x23, 0x80, + 0x2B, 0xAA, 0x66, 0xDD, 0x8D, 0x8B, 0x58, 0xEF, 0x8C, 0xA4, 0x7B, 0x1B, 0xCC, 0xCF, 0x1A, 0x38, 0x3C, 0x8D, 0x58, 0x0D, + 0xD4, 0x33, 0x1D, 0x30, 0x30, 0x73, 0x4C, 0x6C, 0x76, 0x63, 0x13, 0x2E, 0x12, 0x71, 0x3A, 0x2D, 0x45, 0xCA, 0x3E, 0x04, + 0xD6, 0xE9, 0x04, 0x7D, 0xFE, 0xC2, 0x87, 0x63, 0xCC, 0xE0, 0x59, 0xD1, 0x7D, 0x53, 0xCC, 0xEA, 0x47, 0x32, 0xD3, 0x18, + 0x42, 0x9D, 0x16, 0x95, 0x67, 0xB8, 0x05, 0x29, 0x02, 0x79, 0x3F, 0x0C, 0x1B, 0xD9, 0x45, 0x99, 0x63, 0xC0, 0xC1, 0x34, + 0x68, 0x62, 0x1E, 0x60, 0x88, 0x6E, 0x64, 0x87, 0xAA, 0x45, 0x3C, 0x08, 0x85, 0xB6, 0x24, 0xD4, 0xA5, 0xEF, 0x2C, 0x6F, + 0x25, 0x1C, 0x73, 0x9E, 0xB2, 0xB6, 0x88, 0x58, 0x84, 0xB7, 0x2B, 0x49, 0x80, 0x92, 0x5E, 0x5D, 0x13, 0x89, 0xF0, 0x03, + 0xBC, 0xC4, 0x81, 0x4D, 0x05, 0xB4, 0xEB, 0x45, 0xE4, 0x0F, 0xD5, 0x9B, 0x7A, 0x0C, 0x05, 0x35, 0x6A, 0xEC, 0x89, 0xF9, + 0x2C, 0x97, 0x46, 0xCD, 0xDB, 0x6C, 0x1D, 0xE5, 0x87, 0x85, 0x99, 0xEC, 0xB2, 0xF5, 0x46, 0xDA, 0x95, 0xE9, 0x11, 0x1D, + 0x87, 0xA2, 0x52, 0xD4, 0x6D, 0xD1, 0xEC, 0x1F, 0x81, 0xB5, 0x07, 0xFC, 0xC4, 0x68, 0x7B, 0x25, 0xD4, 0xAB, 0x1D, 0x90, + 0x05, 0x89, 0x94, 0xC7, 0x3F, 0x81, 0xD6, 0x01, 0x06, 0x47, 0x8E, 0x8D, 0x6C, 0xE9, 0x35, 0xD7, 0xED, 0xF3, 0xFA, 0xAD, + 0x2B, 0xB8, 0x4F, 0xCB, 0x14, 0x8A, 0xC7, 0xAC, 0x48, 0x7A, 0x78, 0xA8, 0xF9, 0x33, 0x0E, 0x3D, 0xF4, 0xCB, 0x1F, 0xE4, + 0xA5, 0xBC, 0x0D, 0x35, 0x8D, 0xEE, 0x1E, 0x6B, 0x00, 0xE9, 0x75, 0x9C, 0x42, 0x39, 0x10, 0xBC, 0xFC, 0x85, 0xD9, 0x40, + 0x21, 0x57, 0xA2, 0xD0, 0xC7, 0x0A, 0x07, 0x9C, 0x8A, 0xDE, 0x9E, 0x49, 0x40, 0xC6, 0xBF, 0xBE, 0x0F, 0x27, 0x71, 0x90, + 0xAD, 0x30, 0x47, 0x3D, 0x19, 0x3C, 0x11, 0xBC, 0x78, 0x25, 0xC7, 0xD4, 0x1C, 0x27, 0x5E, 0x62, 0x8D, 0xDD, 0xC4, 0x91, + 0xEB, 0x00, 0xD5, 0x08, 0x8E, 0x60, 0xDD, 0x00, 0x9F, 0xE0, 0xCE, 0xF3, 0xC4, 0xD9, 0x93, 0x36, 0x2D, 0x40, 0x4C, 0xC3, + 0xBE, 0xCE, 0x80, 0x1C, 0xCA, 0x2B, 0x92, 0xCA, 0xAC, 0x33, 0x9C, 0xBC, 0x1D, 0xC2, 0x46, 0x09, 0x72, 0xD1, 0x8A, 0xCB, + 0x43, 0x08, 0x51, 0xDC, 0x99, 0x30, 0x78, 0x20, 0x4A, 0xDC, 0x69, 0x19, 0x14, 0xE2, 0x77, 0x1D, 0x46, 0x49, 0x88, 0xE2, + 0xF1, 0x89, 0x33, 0xBC, 0xEC, 0x93, 0xAF, 0xC6, 0x64, 0x55, 0x15, 0x67, 0x43, 0x4C, 0x69, 0x41, 0xA2, 0x40, 0x88, 0x90, + 0x15, 0x30, 0x70, 0x37, 0xC2, 0x05, 0x0E, 0xD9, 0xB8, 0x5B, 0x21, 0x4B, 0xE1, 0x06, 0xAE, 0x6A, 0x49, 0xB9, 0xB1, 0x32, + 0x4C, 0x4D, 0x33, 0x66, 0x60, 0x20, 0xB4, 0x8E, 0x6A, 0x0C, 0xAE, 0xBD, 0xB3, 0x22, 0xD9, 0x21, 0x57, 0x01, 0xDB, 0xCE, + 0x38, 0x50, 0x08, 0x44, 0x8B, 0xCA, 0x88, 0x40, 0xBB, 0x4A, 0x2E, 0x20, 0xEB, 0xF5, 0x6E, 0xE1, 0xA5, 0xC9, 0xA2, 0x41, + 0x69, 0xA8, 0x4C, 0x27, 0x65, 0xAA, 0x27, 0x88, 0x43, 0xE4, 0x0E, 0x0A, 0x21, 0xCA, 0x81, 0x74, 0x16, 0x2A, 0xFF, 0xF8, + 0x71, 0x2D, 0x57, 0xD0, 0x2B, 0x1C, 0x42, 0xE0, 0xAA, 0xC9, 0xDE, 0x77, 0x6E, 0x65, 0xD1, 0xCC, 0x7A, 0xD4, 0x61, 0x8E, + 0x32, 0x05, 0x0B, 0xB2, 0x3A, 0x84, 0xBB, 0x96, 0x0D, 0x07, 0xC7, 0xE4, 0x67, 0xE5, 0x10, 0xA6, 0x4E, 0xC8, 0x3E, 0xB7, + 0x5B, 0xCA, 0x33, 0x82, 0x40, 0x06, 0xCE, 0x98, 0x75, 0xFF, 0x20, 0xDD, 0xA8, 0x2F, 0xE5, 0x4F, 0x63, 0x05, 0x3E, 0x92, + 0x8D, 0x05, 0x2F, 0x9F, 0x9C, 0x20, 0xF2, 0xAD, 0x88, 0x1C, 0xAD, 0xE4, 0xB8, 0xB5, 0x9B, 0x73, 0xA8, 0xFB, 0xD4, 0x09, + 0x9F, 0x0B, 0xAF, 0x6A, 0x45, 0xE7, 0xFC, 0x7D, 0xDD, 0x47, 0x3C, 0xED, 0xE3, 0x0F, 0xD4, 0x2E, 0xE5, 0x81, 0xC4, 0x11, + 0xA3, 0x7F, 0xB4, 0xC8, 0xB3, 0x4F, 0x1A, 0x66, 0x77, 0x16, 0x31, 0x7B, 0xBA, 0x41, 0x71, 0xB8, 0x57, 0x0F, 0x0B, 0xF8, + 0x37, 0x8C, 0x87, 0xBA, 0xE8, 0xA3, 0x10, 0xC9, 0xF6, 0xFF, 0x4B, 0xE9, 0xCC, 0xAF, 0x13, 0x58, 0x97, 0x66, 0xCF, 0x07, + 0x2F, 0xE2, 0xAD, 0xE8, 0x72, 0xEC, 0xCD, 0x77, 0x22, 0xFC, 0x1B, 0x48, 0xA9, 0x67, 0x6D, 0x63, 0x04, 0xDD, 0x27, 0x25, + 0xEC, 0x73, 0x15, 0x50, 0x64, 0x36, 0x14, 0xE7, 0xB7, 0x32, 0x0D, 0xE6, 0xD6, 0x01, 0xD5, 0x90, 0xE4, 0x74, 0xF8, 0x56, + 0x02, 0xD1, 0xE2, 0x08, 0xF8, 0xBF, 0x7E, 0x89, 0x45, 0xAD, 0xBB, 0x25, 0x44, 0xC3, 0xED, 0xA9, 0x83, 0x32, 0x03, 0x57, + 0x9A, 0xE1, 0xB7, 0x6E, 0x85, 0x9E, 0x33, 0x10, 0x64, 0x51, 0xC1, 0x83, 0x89, 0x17, 0x9B, 0x04, 0x18, 0x29, 0x0C, 0x50, + 0x24, 0xF5, 0x57, 0x37, 0x4A, 0x51, 0x94, 0xD5, 0x81, 0xF7, 0x14, 0x23, 0x9B, 0x97, 0x9F, 0x97, 0xCA, 0xA6, 0xC0, 0xE5, + 0x92, 0xCA, 0x5C, 0x83, 0x19, 0xF4, 0x1C, 0xC1, 0x3E, 0x7D, 0x3F, 0x70, 0xD0, 0xB9, 0xFD, 0x36, 0xC6, 0x9B, 0x06, 0x12, + 0x94, 0x8D, 0xB3, 0x55, 0x1B, 0x15, 0xAA, 0x22, 0xAA, 0xBA, 0xF3, 0x95, 0xB5, 0xD6, 0x94, 0x02, 0xEA, 0x8A, 0x5F, 0x71, + 0x9F, 0x7D, 0xE2, 0x72, 0x4B, 0x38, 0xEF, 0x66, 0xD3, 0xBB, 0x68, 0xAE, 0x81, 0x57, 0x84, 0xAD, 0x87, 0xF5, 0xEA, 0x66, + 0x4A, 0x79, 0xD8, 0xEF, 0x53, 0x55, 0x8E, 0xCB, 0x3E, 0x52, 0xCB, 0xDC, 0x33, 0x17, 0xE3, 0x72, 0xCB, 0x5A, 0x24, 0x28, + 0x59, 0x95, 0x41, 0xAE, 0x03, 0x3E, 0x57, 0x98, 0x81, 0xD7, 0xEB, 0x66, 0x8D, 0x86, 0xED, 0x95, 0xB8, 0x7B, 0x9F, 0xDA, + 0x26, 0x19, 0xFD, 0xBC, 0xFA, 0x3B, 0x15, 0x56, 0xC1, 0x14, 0x55, 0x32, 0x96, 0x31, 0x00, 0x50, 0x81, 0x54, 0x16, 0xF9, + 0xE9, 0xDC, 0x14, 0xDC, 0x43, 0xAE, 0xA8, 0xE0, 0xD2, 0x8C, 0x16, 0x9A, 0x0A, 0x7D, 0x84, 0xFD, 0xD8, 0x88, 0x7B, 0xF0, + 0xE2, 0xBD, 0x38, 0x0A, 0x53, 0x4D, 0x6B, 0xD0, 0xEC, 0xBF, 0x81, 0xCE, 0xE1, 0x3F, 0x31, 0x60, 0x4A, 0xBC, 0xD5, 0xDF, + 0x08, 0x92, 0x07, 0xFD, 0x42, 0x31, 0x88, 0xC3, 0x89, 0x3D, 0x1B, 0x45, 0x0A, 0x1F, 0x8C, 0xFF, 0x04, 0xE2, 0x48, 0x71, + 0xC8, 0xDC, 0x5A, 0x55, 0x2E, 0x11, 0xEC, 0xEC, 0xF8, 0xE3, 0x88, 0x0A, 0x13, 0x40, 0x8C, 0x61, 0xC9, 0x6D, 0xFF, 0x27, + 0x3F, 0xA3, 0x1E, 0x86, 0x7F, 0x5F, 0x37, 0x90, 0xEF, 0xC2, 0x1F, 0x25, 0x55, 0xCD, 0xCF, 0x9A, 0x21, 0xE6, 0xD6, 0xD9, + 0x2E, 0xC2, 0x4A, 0xEE, 0xD9, 0xE1, 0x41, 0x60, 0x49, 0xDF, 0x2F, 0x04, 0xD3, 0x02, 0xA4, 0x1C, 0x08, 0x9A, 0xFA, 0x44, + 0xA5, 0x79, 0x67, 0x91, 0x4F, 0x59, 0xE0, 0xE2, 0x3A, 0x31, 0x38, 0xCD, 0xEC, 0x86, 0x68, 0x35, 0x98, 0x88, 0x22, 0x8C, + 0x2F, 0x76, 0x00, 0x7E, 0xBE, 0x06, 0x18, 0xBC, 0x0B, 0x2B, 0xFB, 0x45, 0x04, 0xAE, 0x51, 0x4F, 0x8E, 0x65, 0xB9, 0x72, + 0x3F, 0x25, 0x57, 0x6E, 0x51, 0x28, 0xC6, 0xD3, 0xFB, 0xAD, 0x07, 0xCA, 0xA4, 0x38, 0x01, 0x9F, 0xEC, 0xAA, 0x1B, 0x6A, + 0x50, 0x75, 0xA6, 0x4D, 0x44, 0xEA, 0x1C, 0x2C, 0xDD, 0x89, 0x29, 0xAA, 0x30, 0x74, 0xFE, 0xE4, 0xF4, 0xEA, 0x6A, 0x1F, + 0x94, 0x12, 0x00, 0xBD, 0xEA, 0xD9, 0xA8, 0xC0, 0xA2, 0x44, 0x8F, 0xAE, 0x73, 0x57, 0x35, 0x98, 0xE7, 0x0A, 0x5B, 0x2C, + 0x4F, 0x8E, 0xFB, 0xBB, 0x35, 0xB0, 0x54, 0x61, 0xA3, 0x14, 0xAA, 0x9B, 0x99, 0xBA, 0x61, 0x3A, 0x43, 0x84, 0xEA, 0x78, + 0x03, 0xE3, 0xF5, 0xCE, 0x62, 0xF7, 0xDA, 0x3E, 0x16, 0xA7, 0x24, 0xD2, 0xA5, 0x5F, 0xF0, 0x88, 0x58, 0x0D, 0x54, 0x93, + 0x4D, 0x32, 0x3D, 0x6F, 0xBE, 0x52, 0x46, 0xBD, 0xA6, 0xFE, 0x4D, 0xC7, 0xAB, 0x7E, 0x5D, 0xE3, 0xAF, 0x5C, 0x63, 0x2C, + 0x11, 0x03, 0x4D, 0xC3, 0xED, 0x8E, 0xBB, 0xEB, 0x92, 0xF0, 0x55, 0xF2, 0x02, 0x39, 0xD5, 0xE3, 0x99, 0x4E, 0x23, 0x7F, + 0x66, 0xA1, 0x3B, 0xA6, 0x0D, 0xEB, 0xDE, 0x8A, 0xDD, 0x5F, 0x80, 0x4D, 0x57, 0x4F, 0xFB, 0x2B, 0xB0, 0x43, 0x98, 0x70, + 0x9D, 0x43, 0x93, 0x64, 0x01, 0x0C, 0x92, 0x27, 0xD7, 0xA1, 0xAA, 0x41, 0x53, 0xB4, 0x82, 0x0E, 0xB7, 0xF1, 0x24, 0xFD, + 0x43, 0x82, 0xDB, 0x3B, 0x5F, 0x41, 0x92, 0x1A, 0xE2, 0x33, 0xD3, 0x6B, 0x1F, 0x01, 0x55, 0xB4, 0x5C, 0x9C, 0xAD, 0xD7, + 0xB1, 0x9F, 0x05, 0x40, 0xDB, 0x7E, 0xC3, 0x0B, 0x7C, 0x3D, 0x37, 0x31, 0x54, 0xD6, 0x35, 0xB6, 0xB6, 0xA2, 0xB4, 0xD7, + 0x0A, 0x96, 0x7B, 0x87, 0x52, 0x01, 0x52, 0x1B, 0x65, 0x6A, 0x39, 0x49, 0xC2, 0x3C, 0xBC, 0xC7, 0x93, 0xDF, 0x2C, 0xCA, + 0x71, 0xDD, 0xF3, 0x99, 0xA5, 0x04, 0xED, 0xBE, 0x39, 0x1B, 0xE3, 0x5B, 0xE7, 0x06, 0x6B, 0x95, 0x01, 0x7D, 0x53, 0x7A, + 0x2A, 0x61, 0xCD, 0x3D, 0x5E, 0xE4, 0xFB, 0x80, 0x81, 0x98, 0x45, 0x88, 0x54, 0x7C, 0x92, 0xF4, 0x8F, 0xFD, 0x4C, 0x0C, + 0x74, 0x53, 0xFF, 0x45, 0x5B, 0xD8, 0xB0, 0x1F, 0x7A, 0x19, 0xD6, 0x92, 0xD4, 0xD6, 0x08, 0xBD, 0x81, 0x9C, 0x41, 0x42, + 0x6D, 0x9B, 0x61, 0xCD, 0x4F, 0xF0, 0x98, 0x69, 0x88, 0x07, 0xB1, 0xED, 0x93, 0x9F, 0x84, 0x13, 0x10, 0x69, 0x81, 0x51, + 0xFA, 0x1B, 0x2E, 0xE5, 0x0A, 0x8B, 0x04, 0xBC, 0x1A, 0x97, 0xBF, 0x93, 0x31, 0xE8, 0xBC, 0x78, 0x3F, 0xDB, 0x2E, 0x4E, + 0x28, 0x7D, 0xFC, 0xCC, 0xAC, 0xB4, 0x77, 0x99, 0x00, 0x93, 0xD6, 0xD2, 0x78, 0xD4, 0x08, 0x16, 0xC4, 0xB5, 0x2A, 0x24, + 0xC2, 0xDF, 0xA8, 0x69, 0x0D, 0x70, 0x79, 0xC3, 0x80, 0x2D, 0xC6, 0x8C, 0x47, 0x2D, 0x2C, 0xB1, 0x1A, 0x53, 0x4B, 0xD0, + 0x61, 0x73, 0x4C, 0x9D, 0x5D, 0x75, 0x51, 0x63, 0x6D, 0x9F, 0x90, 0xAC, 0xC7, 0xFA, 0xAB, 0x7F, 0x83, 0x37, 0x0C, 0xF3, + 0x4E, 0xBE, 0x3A, 0xF3, 0x30, 0xBF, 0x91, 0x08, 0x16, 0x11, 0x2A, 0xC8, 0xC7, 0x0F, 0x6F, 0x5A, 0x82, 0xBF, 0xCC, 0x63, + 0x20, 0x63, 0x4E, 0xC3, 0x91, 0x20, 0x41, 0xF3, 0xE4, 0xBE, 0x74, 0x4B, 0x8B, 0xEA, 0x3F, 0xDC, 0x24, 0xEF, 0x41, 0xC5, + 0xD8, 0x60, 0x50, 0xC7, 0x40, 0x60, 0xA6, 0x0C, 0xA3, 0x62, 0x77, 0x38, 0x68, 0x2A, 0xD0, 0x67, 0xF2, 0x63, 0xF5, 0xAA, + 0xC0, 0xE3, 0xB9, 0xDF, 0xA4, 0x75, 0xC0, 0x86, 0x28, 0x07, 0x99, 0x47, 0xB3, 0xDB, 0x09, 0xB6, 0xE5, 0x05, 0x32, 0x17, + 0x0D, 0x2B, 0x10, 0xF4, 0x30, 0x6F, 0xC9, 0x2B, 0xB4, 0x64, 0xA7, 0x0E, 0x6D, 0x9A, 0x48, 0x0F, 0x9B, 0x3F, 0x15, 0x89, + 0x6B, 0x6C, 0x75, 0x27, 0x4F, 0x69, 0xAA, 0x1E, 0xAA, 0x4B, 0xD0, 0x16, 0xF3, 0x29, 0xF1, 0xB1, 0xFB, 0x45, 0x74, 0xAA, + 0xE4, 0x27, 0x03, 0x11, 0xBF, 0xE8, 0xA1, 0x47, 0x2C, 0x0B, 0x1A, 0x19, 0x63, 0x19, 0x7A, 0x0E, 0x46, 0x6A, 0xAD, 0xB3, + 0xEF, 0x4C, 0x9A, 0x20, 0x6B, 0xC6, 0x1D, 0x1D, 0x2B, 0x58, 0x32, 0x2D, 0x29, 0x66, 0xE2, 0xD0, 0xC2, 0x04, 0x22, 0x84, + 0xD9, 0x7B, 0x07, 0xF0, 0x8C, 0x09, 0x45, 0xDA, 0xAB, 0xA7, 0x11, 0x5B, 0xFB, 0x64, 0x2B, 0x14, 0x7F, 0x78, 0x08, 0x5E, + 0xBA, 0x17, 0x33, 0xDA, 0x5B, 0x0B, 0xF7, 0xAB, 0xDD, 0x43, 0x37, 0x4F, 0x13, 0x5A, 0x84, 0x1C, 0x0B, 0x4C, 0x7A, 0xB6, + 0x0A, 0x61, 0xF2, 0x98, 0xE2, 0x9F, 0xEC, 0xC1, 0x84, 0x93, 0x8A, 0xCD, 0x65, 0x63, 0x31, 0x7B, 0xBA, 0x43, 0xEE, 0x1A, + 0xF4, 0xE0, 0x6C, 0x1C, 0xF8, 0x90, 0x63, 0xF0, 0xB9, 0x80, 0xBC, 0x49, 0x92, 0x02, 0x2D, 0x6E, 0x6B, 0x11, 0xED, 0xC1, + 0xFE, 0x68, 0xF4, 0xCA, 0xAA, 0xA2, 0xAD, 0x1C, 0x72, 0x27, 0x8E, 0x48, 0x6A, 0xB0, 0x6F, 0x9F, 0xA8, 0x8A, 0x14, 0xBD, + 0x67, 0x0B, 0xDB, 0x6C, 0xEC, 0xFD, 0x10, 0x84, 0x40, 0x21, 0xC2, 0x4C, 0xAC, 0xBD, 0x74, 0x81, 0xC1, 0x90, 0x73, 0x6F, + 0xBE, 0x9C, 0x0C, 0x98, 0x0C, 0x13, 0x23, 0x2F, 0x12, 0x75, 0x8B, 0xE7, 0x5F, 0xB9, 0x41, 0x00, 0xF3, 0xC1, 0x97, 0x81, + 0xC2, 0x32, 0x39, 0x20, 0x0B, 0x1E, 0x0B, 0x6F, 0x92, 0x99, 0x45, 0x0E, 0xD2, 0x37, 0x17, 0x5A, 0x08, 0x39, 0xE4, 0xC9, + 0x63, 0x79, 0x84, 0x55, 0x4C, 0x78, 0x9D, 0xDE, 0x97, 0xC2, 0x32, 0x02, 0x46, 0x59, 0xC4, 0xD6, 0xBA, 0x7B, 0x76, 0x43, + 0x7C, 0x57, 0x5B, 0x32, 0x21, 0x78, 0x6F, 0xDC, 0x2B, 0x04, 0x96, 0xE9, 0x57, 0x88, 0x7F, 0x52, 0x83, 0xA9, 0x55, 0xBB, + 0x4D, 0x7B, 0xAE, 0xC6, 0x43, 0xE9, 0x42, 0x16, 0xD0, 0x4B, 0x8B, 0x3D, 0xA0, 0xD7, 0x9F, 0xD5, 0x14, 0x76, 0x07, 0xB1, + 0x93, 0xF8, 0xCA, 0x06, 0x77, 0xFA, 0xBE, 0x72, 0xA7, 0xCE, 0xFF, 0xFD, 0x33, 0x2E, 0x4E, 0xE9, 0x5B, 0xF3, 0x12, 0x5D, + 0x0D, 0x3B, 0xB6, 0x5F, 0xEB, 0x39, 0x69, 0x63, 0xD8, 0xBF, 0xE1, 0xC6, 0x4B, 0xB4, 0x0B, 0xB8, 0x70, 0x1D, 0x0F, 0x91, + 0x9B, 0x54, 0xCF, 0x90, 0x35, 0xB7, 0xAF, 0x57, 0xF8, 0x17, 0xC7, 0x85, 0xB0, 0x7B, 0x47, 0xBD, 0xCA, 0x3B, 0x8F, 0x19, + 0xFF, 0x64, 0x99, 0xFE, 0x08, 0xAD, 0x33, 0xCE, 0x8C, 0xDD, 0x86, 0x5D, 0xE6, 0xB7, 0x39, 0x30, 0x3A, 0x7E, 0xF6, 0x9A, + 0x08, 0x78, 0x05, 0x1F, 0xF6, 0x3D, 0x16, 0xC8, 0x40, 0xE4, 0xD9, 0x2F, 0x43, 0xB0, 0xE5, 0x07, 0x9F, 0x0C, 0x21, 0x14, + 0xE1, 0x30, 0xDC, 0xC5, 0x43, 0xC7, 0xC3, 0x8E, 0x4F, 0x9F, 0x29, 0xEE, 0x13, 0x51, 0xB7, 0xEF, 0xDD, 0x73, 0xCF, 0xFD, + 0x26, 0xB2, 0x99, 0xE5, 0x50, 0xAE, 0x59, 0xD5, 0x88, 0x57, 0x24, 0xBA, 0x25, 0x3E, 0x98, 0x91, 0x34, 0xCF, 0xA8, 0x86, + 0xF5, 0xEF, 0x32, 0xE4, 0x38, 0x4D, 0xCF, 0x54, 0x96, 0xE0, 0xD0, 0xFA, 0xC8, 0xCC, 0xBD, 0x92, 0x16, 0x61, 0x61, 0xF1, + 0xE0, 0x60, 0x3F, 0x71, 0x66, 0x4F, 0x60, 0x65, 0x46, 0x82, 0xF1, 0x2F, 0x88, 0xE0, 0xC9, 0x83, 0xB8, 0x90, 0x71, 0xB2, + 0xE3, 0xE8, 0x28, 0xB3, 0x68, 0x81, 0xF7, 0x6A, 0xD5, 0xEF, 0x28, 0xD5, 0x2C, 0xA9, 0x01, 0xA4, 0xED, 0xAC, 0xAF, 0xC6, + 0x48, 0x7F, 0xFA, 0x44, 0xA5, 0x79, 0x4E, 0xCE, 0x68, 0x1B, 0xAF, 0x06, 0x3D, 0x27, 0xCE, 0xA3, 0x72, 0xC6, 0x44, 0x25, + 0x10, 0x03, 0xD8, 0x82, 0xEF, 0x16, 0xE3, 0x9E, 0x45, 0xA8, 0x69, 0x4B, 0x80, 0x64, 0xFB, 0x45, 0x04, 0xE7, 0x2B, 0x03, + 0xBA, 0x69, 0x71, 0x43, 0x37, 0x49, 0x49, 0x7B, 0x08, 0x7A, 0xF1, 0x24, 0xC8, 0x2E, 0x07, 0x74, 0x66, 0x86, 0x99, 0x69, + 0xAC, 0xE8, 0x72, 0x33, 0x08, 0xC6, 0x76, 0x2A, 0x3C, 0xB9, 0x2A, 0x2E, 0xAD, 0x87, 0xF3, 0x48, 0x9E, 0xE8, 0x84, 0xEA, + 0x05, 0xC6, 0x3F, 0x1A, 0x35, 0x27, 0x58, 0x32, 0x4C, 0x09, 0x84, 0x42, 0x7E, 0xFB, 0x30, 0xCD, 0xF4, 0x91, 0x23, 0x2E, + 0x5F, 0xA9, 0x6A, 0xE8, 0x69, 0xA4, 0x4B, 0xDE, 0xA9, 0xBA, 0x2A, 0xEB, 0xFD, 0xC4, 0x6B, 0x8A, 0xD8, 0xA1, 0x01, 0xDD, + 0xA6, 0x32, 0xB7, 0xF3, 0xDB, 0x09, 0x04, 0x63, 0x6D, 0x88, 0xC2, 0xA4, 0xF7, 0x86, 0xDE, 0x82, 0x9A, 0x81, 0x92, 0x70, + 0x74, 0xE1, 0x6C, 0xDE, 0x41, 0x69, 0xB3, 0xDD, 0xBA, 0x72, 0x60, 0x78, 0xA4, 0xC2, 0x6A, 0x1C, 0xE4, 0x61, 0x1A, 0x37, + 0x1C, 0x86, 0xF9, 0x4D, 0x0C, 0xEF, 0x15, 0xAF, 0x27, 0xE4, 0x93, 0x71, 0x4A, 0xE1, 0x4B, 0xCA, 0xBC, 0x01, 0xEA, 0x98, + 0x3A, 0x50, 0x3A, 0x1D, 0xAE, 0xCB, 0xB1, 0x62, 0xB4, 0xE0, 0x04, 0x16, 0xD5, 0x3B, 0xAC, 0x83, 0x14, 0x61, 0xCB, 0xD0, + 0xB2, 0x0F, 0xA5, 0x55, 0x01, 0x9E, 0x2A, 0x6C, 0xD8, 0xFF, 0xCA, 0xBE, 0xDE, 0x68, 0x02, 0x73, 0x63, 0x33, 0x82, 0x6B, + 0x73, 0x13, 0x5D, 0x92, 0x44, 0x13, 0xE8, 0xC0, 0x5D, 0x6B, 0x99, 0xDC, 0x2E, 0x98, 0x8B, 0x63, 0x3E, 0xFB, 0xCE, 0xD3, + 0xBF, 0x88, 0xF5, 0x93, 0x32, 0x90, 0xE2, 0x73, 0xA5, 0x06, 0xB2, 0x77, 0xBD, 0xB1, 0xAC, 0x51, 0x07, 0x39, 0x08, 0xB5, + 0x4E, 0x32, 0xE7, 0x11, 0xE2, 0x59, 0xCC, 0x1A, 0x76, 0xE8, 0x24, 0x43, 0x21, 0x57, 0xEC, 0xF2, 0xB5, 0x99, 0xEC, 0x0C, + 0xCB, 0xD8, 0xC4, 0x09, 0xD2, 0x03, 0xAA, 0x47, 0xE8, 0x2E, 0x1A, 0xB4, 0xC6, 0x30, 0x27, 0xE0, 0x0D, 0xB2, 0xCA, 0xAD, + 0xE6, 0xB7, 0x95, 0x13, 0xA5, 0x8C, 0xE2, 0xB5, 0x40, 0xD2, 0xD1, 0x60, 0x99, 0x28, 0x02, 0x7F, 0x52, 0x71, 0xCE, 0xEC, + 0x4D, 0xB8, 0xF6, 0x2F, 0x15, 0xFA, 0x7A, 0x95, 0x6B, 0xC3, 0x74, 0x48, 0x7F, 0xC8, 0xD6, 0x12, 0x88, 0x38, 0x16, 0x64, + 0x2D, 0xF4, 0x76, 0x3E, 0x98, 0x96, 0x12, 0x2D, 0x4D, 0x56, 0x3F, 0x87, 0xCF, 0xDA, 0x61, 0x3E, 0x8F, 0x34, 0x5E, 0x2F, + 0xAA, 0x65, 0x89, 0xD3, 0xDD, 0x5A, 0x3E, 0x7D, 0x2D, 0xA9, 0xD0, 0xD8, 0x40, 0x0D, 0x3E, 0xC4, 0x4A, 0xD8, 0x24, 0xCC, + 0x88, 0xF0, 0x8C, 0xAC, 0x46, 0x8D, 0xDE, 0x31, 0x1A, 0xA7, 0xCD, 0x79, 0x18, 0x03, 0xF6, 0x10, 0xF1, 0x41, 0x68, 0x9A, + 0x3F, 0x36, 0xD6, 0x81, 0x98, 0xAD, 0x64, 0xF8, 0xDC, 0x80, 0x9E, 0xFC, 0x02, 0xF0, 0x9F, 0xAD, 0x23, 0x18, 0xEC, 0xAD, + 0x41, 0xDB, 0x9B, 0x84, 0x30, 0x03, 0x10, 0x95, 0x28, 0xBF, 0xF0, 0xDE, 0x8B, 0x12, 0x50, 0x39, 0x9B, 0xA4, 0x65, 0xF9, + 0x7D, 0x9E, 0x00, 0x03, 0xFF, 0x64, 0x00, 0xF9, 0x14, 0x42, 0xC3, 0x86, 0x9D, 0x6A, 0x2A, 0xC8, 0xDA, 0x0F, 0xC9, 0x75, + 0x56, 0x10, 0x36, 0x38, 0x69, 0x0C, 0x44, 0x72, 0x32, 0x03, 0xAC, 0xD2, 0x65, 0x47, 0x23, 0xD6, 0xFD, 0x9C, 0x05, 0x42, + 0x0F, 0x43, 0xB9, 0xE5, 0xD6, 0x39, 0x71, 0x62, 0xB8, 0x4D, 0xD1, 0xA1, 0x80, 0xA9, 0x1B, 0xBA, 0x6A, 0x47, 0xD0, 0x30, + 0x34, 0x28, 0x35, 0x7A, 0x60, 0xC3, 0xE1, 0xDD, 0x98, 0x2E, 0x43, 0x48, 0xA3, 0x9B, 0xA0, 0x03, 0x15, 0x2B, 0x68, 0x9F, + 0xCF, 0xE9, 0xD6, 0x22, 0x38, 0x9F, 0x4B, 0x99, 0x05, 0xBF, 0x64, 0x90, 0xB2, 0x2C, 0x3A, 0x70, 0x42, 0x57, 0x60, 0xA4, + 0x0F, 0x9A, 0xF5, 0x23, 0x79, 0x44, 0x7E, 0xA5, 0x88, 0x20, 0xC2, 0xFE, 0x2B, 0xF7, 0x2E, 0x41, 0xE1, 0xA1, 0x02, 0x4F, + 0xBF, 0xF3, 0x0D, 0xD7, 0x16, 0x77, 0xB1, 0xEC, 0xC5, 0xD7, 0x02, 0x75, 0xE0, 0x13, 0x38, 0xB8, 0x8D, 0xA7, 0x06, 0x08, + 0x4B, 0x5C, 0x6A, 0x4A, 0xC5, 0xCE, 0x6B, 0x24, 0xFD, 0x17, 0x1C, 0x7A, 0x69, 0xE7, 0x32, 0x8C, 0xBE, 0x2D, 0x24, 0x61, + 0xEE, 0x59, 0xC8, 0xC3, 0xAE, 0x07, 0xA7, 0x2D, 0x61, 0x1B, 0x6B, 0x90, 0xAB, 0x4B, 0x93, 0x0D, 0xFB, 0x12, 0x81, 0x4B, + 0x27, 0x37, 0x75, 0x1F, 0x68, 0x88, 0x8D, 0xF5, 0xB5, 0xA0, 0x25, 0x65, 0x6E, 0x0A, 0xFB, 0x7E, 0x88, 0x66, 0x51, 0xCC, + 0x5A, 0xCE, 0xFA, 0x5C, 0xB9, 0x21, 0x1F, 0xEC, 0x1A, 0x5C, 0x6A, 0x96, 0x4A, 0x21, 0x35, 0xDC, 0x17, 0x54, 0xC9, 0x2E, + 0x99, 0x41, 0x22, 0xFC, 0x57, 0x14, 0x61, 0xD9, 0x91, 0x60, 0x7B, 0xB3, 0x26, 0x03, 0x2F, 0xDF, 0xD2, 0x26, 0xE8, 0x8B, + 0x66, 0xB3, 0xAC, 0xE9, 0xD2, 0x42, 0x8B, 0x80, 0xD8, 0xDB, 0x03, 0xBF, 0x1B, 0x0F, 0x9B, 0x61, 0x8D, 0x92, 0xA4, 0x87, + 0xE8, 0xEF, 0xD5, 0x31, 0x83, 0x51, 0x63, 0xC4, 0x34, 0x1C, 0xEB, 0xD2, 0x4E, 0x8F, 0xEC, 0x83, 0x8D, 0x7F, 0x6E, 0x0C, + 0xA3, 0x3D, 0xD4, 0x90, 0xB8, 0xB4, 0xA8, 0xCF, 0xC2, 0x10, 0x9D, 0xD2, 0xCE, 0xF0, 0x65, 0xC2, 0xF1, 0x1F, 0xB4, 0x01, + 0xE0, 0xFC, 0x85, 0x5E, 0x15, 0x5D, 0xCC, 0xED, 0x55, 0x2D, 0x80, 0xF3, 0x63, 0x13, 0xB7, 0x6E, 0x4D, 0x22, 0x22, 0x4D, + 0xE1, 0xF2, 0x23, 0x4A, 0x44, 0xF0, 0x55, 0x22, 0xCB, 0xEC, 0xD4, 0x59, 0x66, 0x99, 0xAB, 0x08, 0xE6, 0x99, 0x2B, 0x23, + 0xEC, 0xA9, 0x44, 0xE1, 0x17, 0x57, 0x6C, 0xA2, 0x10, 0x25, 0xE7, 0x12, 0xE4, 0xA7, 0x83, 0x92, 0x80, 0x65, 0x37, 0xC5, + 0xBE, 0x9D, 0x09, 0x25, 0xEA, 0x2D, 0xAE, 0x9C, 0xC3, 0xD6, 0x34, 0x25, 0xB4, 0x6D, 0xCC, 0xB2, 0x02, 0x9F, 0x94, 0xF0, + 0x16, 0x3E, 0x04, 0x34, 0x46, 0xA8, 0x65, 0x0E, 0x0E, 0xC1, 0x96, 0x0A, 0xA8, 0xA0, 0x46, 0xB5, 0x08, 0x3E, 0xC3, 0x57, + 0x9D, 0xFB, 0x69, 0x52, 0xFA, 0x54, 0x9E, 0x1A, 0xA0, 0x61, 0x3A, 0xE3, 0x9A, 0x82, 0x08, 0x90, 0xDA, 0x14, 0xA6, 0x47, + 0xF6, 0x8F, 0x3F, 0x59, 0xA4, 0xE5, 0xAB, 0xC0, 0x4D, 0x35, 0xC6, 0x8D, 0x8B, 0xF0, 0x98, 0xCF, 0x0B, 0x1F, 0x37, 0x67, + 0x05, 0x16, 0x8B, 0xA2, 0x89, 0x79, 0x8F, 0x46, 0x1C, 0x14, 0xA4, 0x23, 0xF8, 0x89, 0x66, 0x2A, 0x62, 0x4D, 0x42, 0x48, + 0x6D, 0xDF, 0x4C, 0xE9, 0x4B, 0x8C, 0xED, 0x9C, 0xFA, 0x63, 0xCF, 0x9F, 0xD6, 0x12, 0x33, 0x30, 0x3B, 0x90, 0x46, 0xC9, + 0x82, 0xD7, 0xD6, 0x7D, 0x59, 0xDE, 0x27, 0x8A, 0xB7, 0x5C, 0x57, 0x25, 0x58, 0x73, 0x37, 0xAE, 0xED, 0x53, 0x6C, 0x9D, + 0x7A, 0x68, 0x2F, 0x9A, 0xF2, 0x5D, 0x40, 0x3D, 0xF7, 0x24, 0x07, 0xE9, 0x02, 0x6E, 0x5C, 0x15, 0x49, 0x32, 0x88, 0xF1, + 0x88, 0xC1, 0x24, 0xE0, 0x7F, 0xF1, 0x4E, 0x25, 0xE5, 0x6F, 0x57, 0xA4, 0xDD, 0x98, 0x28, 0x2C, 0x33, 0x74, 0x96, 0x4B, + 0x74, 0x81, 0x6A, 0x16, 0xD8, 0x3C, 0x78, 0x3B, 0x60, 0x5D, 0x1F, 0xCF, 0x7F, 0x19, 0x26, 0x75, 0x7F, 0x93, 0xE5, 0x04, + 0x65, 0x6D, 0x89, 0xB9, 0xD5, 0x70, 0xFC, 0x17, 0x8D, 0xED, 0xF1, 0x13, 0x1C, 0xB6, 0x94, 0x7D, 0x30, 0x9F, 0x04, 0x6C, + 0x04, 0xBE, 0x77, 0x5D, 0x72, 0x31, 0xDA, 0xC4, 0x93, 0xF4, 0x08, 0x45, 0xBB, 0xCB, 0x30, 0x76, 0x0C, 0xFF, 0x7B, 0x6C, + 0x3B, 0xC7, 0xD0, 0x27, 0x27, 0xAC, 0x21, 0x74, 0xA2, 0x87, 0x40, 0x8D, 0xD8, 0x13, 0xF2, 0x79, 0xFE, 0x73, 0x99, 0xC5, + 0x1B, 0xCC, 0x77, 0x4B, 0x6E, 0xF5, 0xD9, 0x01, 0x25, 0xF6, 0xF6, 0x76, 0x7A, 0x8E, 0xEF, 0x24, 0xA7, 0xA8, 0xF8, 0xB8, + 0x3A, 0xC8, 0xC2, 0xE9, 0xD4, 0x07, 0xD9, 0x75, 0x64, 0x85, 0x9C, 0xCB, 0x3F, 0xE8, 0x08, 0xC1, 0xFF, 0x89, 0x99, 0xAA, + 0x54, 0xC4, 0x0C, 0xD6, 0xAE, 0x0C, 0xBB, 0xF6, 0x8F, 0xE4, 0x95, 0xD8, 0xE1, 0x34, 0x07, 0xA1, 0xA2, 0xB4, 0xDC, 0x75, + 0xA8, 0x37, 0x8F, 0x25, 0x7D, 0x05, 0x8B, 0xD4, 0xDC, 0x87, 0x73, 0x37, 0xBB, 0x86, 0x3D, 0xB6, 0x72, 0x26, 0x54, 0x6C, + 0xAD, 0xC7, 0x43, 0x1F, 0xAD, 0x4B, 0x58, 0xBD, 0x54, 0x93, 0xBC, 0xCE, 0x5E, 0x42, 0x0A, 0xD3, 0xFF, 0xAA, 0x4C, 0x43, + 0x0F, 0xC8, 0x5E, 0x15, 0xC0, 0x71, 0x30, 0x1A, 0x67, 0xDC, 0x2D, 0x5B, 0xF6, 0xBC, 0xFE, 0x3F, 0x7F, 0xCF, 0x01, 0x5A, + 0x6C, 0x86, 0x7B, 0x37, 0xC6, 0xBF, 0xC7, 0x13, 0x3D, 0xAD, 0x0D, 0x43, 0x33, 0xC7, 0x12, 0x2F, 0xD2, 0x15, 0xAB, 0x57, + 0x26, 0x22, 0x93, 0xFF, 0x99, 0x2D, 0x1B, 0x38, 0xDA, 0xC2, 0x43, 0x81, 0xCF, 0xA2, 0xDB, 0xA6, 0xDB, 0x9D, 0xB3, 0xAE, + 0xB6, 0x9C, 0x35, 0xDD, 0xC3, 0x91, 0x74, 0xBE, 0x35, 0xFA, 0x80, 0x0D, 0xD4, 0x17, 0x13, 0x74, 0xC9, 0xA0, 0x9C, 0x41, + 0xE9, 0x4C, 0x43, 0xD8, 0xA7, 0x2E, 0x5E, 0xA4, 0x05, 0x2D, 0xAA, 0xF9, 0x17, 0xD7, 0x4B, 0xA5, 0x05, 0x51, 0x74, 0xE0, + 0x49, 0x44, 0x2D, 0xB7, 0x6F, 0xF0, 0x6D, 0x07, 0x41, 0xF1, 0x45, 0x97, 0x67, 0xF7, 0xE4, 0xE6, 0xF3, 0x83, 0xE5, 0x85, + 0xDB, 0x9B, 0x6B, 0xA0, 0x81, 0xA4, 0x6C, 0x7B, 0x6B, 0xC5, 0xF6, 0x17, 0xD5, 0xE4, 0xED, 0x19, 0xDA, 0x9A, 0xB5, 0x3E, + 0xAB, 0xF8, 0x44, 0x0C, 0xA6, 0xB7, 0x84, 0xF4, 0x73, 0xB9, 0xA5, 0xDB, 0x61, 0xD4, 0x5D, 0x28, 0xB0, 0xCE, 0x7D, 0x61, + 0x66, 0x7D, 0xC7, 0x65, 0x77, 0xA6, 0x6B, 0xFF, 0xEF, 0xC6, 0x96, 0xDF, 0x12, 0x08, 0xB9, 0x23, 0xEB, 0xD4, 0xAB, 0x1F, + 0x19, 0xBA, 0x18, 0x2E, 0x4D, 0x9C, 0x23, 0xE2, 0xB1, 0x3E, 0xBD, 0xC8, 0x4D, 0x98, 0xF6, 0xF5, 0xC1, 0x44, 0x96, 0x60, + 0x3D, 0xD4, 0xE6, 0xD2, 0xB0, 0xFB, 0x00, 0x7F, 0x4E, 0xF8, 0xBA, 0x79, 0x88, 0xF6, 0x5E, 0xAF, 0x9F, 0x82, 0xE2, 0xF1, + 0x7E, 0xBA, 0x0B, 0x12, 0x69, 0x28, 0x9C, 0xC1, 0x2D, 0xB8, 0x50, 0x9F, 0xA5, 0xF5, 0xAC, 0xCF, 0xBE, 0x0B, 0x66, 0xBD, + 0x08, 0xD0, 0x0B, 0xC0, 0x5E, 0xB9, 0x06, 0xC8, 0x61, 0x91, 0x4A, 0x4A, 0x23, 0xB8, 0x4E, 0x6E, 0x61, 0xCD, 0xF4, 0x1F, + 0xDD, 0xEC, 0x89, 0xA9, 0x13, 0x1B, 0xD5, 0x50, 0x3C, 0xED, 0x24, 0xFB, 0xCC, 0x91, 0xBE, 0xEF, 0x79, 0xCF, 0x98, 0x8C, + 0x47, 0x0F, 0xEF, 0xC2, 0x47, 0xC8, 0x0F, 0x69, 0x63, 0x94, 0xC5, 0x10, 0xDA, 0xFD, 0x6F, 0x1B, 0xF7, 0xFA, 0xB6, 0x64, + 0x1A, 0xB4, 0xB8, 0xF9, 0xA7, 0x52, 0xD4, 0xB9, 0xFD, 0xBE, 0x50, 0x29, 0x58, 0x42, 0xE0, 0x47, 0x89, 0x2F, 0xDB, 0x11, + 0xFC, 0xDA, 0xE9, 0xA6, 0xD5, 0xBA, 0x49, 0x63, 0x70, 0x86, 0x70, 0xFC, 0x26, 0x63, 0xC7, 0x12, 0x36, 0x14, 0xD7, 0x56, + 0x87, 0x69, 0x48, 0xC9, 0xA0, 0x72, 0xD8, 0xF0, 0x37, 0x32, 0xA0, 0xEC, 0x21, 0xFD, 0xA9, 0xBA, 0x52, 0x2E, 0x89, 0x15, + 0x01, 0x21, 0x0C, 0x16, 0x1E, 0x38, 0xD9, 0xE5, 0x83, 0x2D, 0x9F, 0x47, 0x53, 0x4F, 0x1F, 0x20, 0x71, 0x21, 0x44, 0x58, + 0x14, 0x74, 0x48, 0x4C, 0xAB, 0x2E, 0x28, 0x40, 0x54, 0x14, 0x36, 0x90, 0x81, 0x69, 0x14, 0xA0, 0x53, 0xA8, 0x66, 0xB5, + 0x60, 0x25, 0xB9, 0x53, 0xF2, 0x9A, 0x81, 0x81, 0x75, 0x8B, 0xB1, 0x05, 0x8A, 0x3D, 0x33, 0x60, 0xC1, 0xC7, 0xBB, 0xA5, + 0xD6, 0x42, 0x50, 0xB3, 0x85, 0xC6, 0xA9, 0x17, 0x6E, 0x28, 0xE6, 0x11, 0x8B, 0x44, 0x62, 0xB2, 0x0D, 0x6F, 0x12, 0x0D, + 0x04, 0x4A, 0x64, 0x88, 0x0C, 0x4F, 0x4B, 0xAA, 0x4E, 0x18, 0xBF, 0xCE, 0x5E, 0x22, 0xCA, 0xDD, 0x29, 0x08, 0xD2, 0x18, + 0x9C, 0xFB, 0xFE, 0x5E, 0xBE, 0x59, 0x5A, 0xC0, 0x57, 0x2B, 0xCF, 0x9B, 0x0D, 0x6A, 0x8B, 0x19, 0x71, 0x40, 0xE7, 0x69, + 0xE0, 0x51, 0x29, 0xA9, 0x93, 0x27, 0x1E, 0x0D, 0x8F, 0x91, 0xEB, 0x1F, 0xE4, 0x26, 0xA3, 0xC6, 0xFA, 0x3F, 0xDC, 0x61, + 0x38, 0x6D, 0x04, 0xCC, 0x0C, 0xE5, 0x9B, 0xA9, 0xFF, 0xA6, 0x44, 0x6C, 0xC2, 0x56, 0x52, 0x6F, 0xC8, 0x77, 0x12, 0x49, + 0x2B, 0xDF, 0xD2, 0x59, 0xE5, 0xAD, 0x42, 0x7D, 0x78, 0xD6, 0xFE, 0xF6, 0x7B, 0xAC, 0xEB, 0x7D, 0x63, 0xF6, 0x44, 0xB2, + 0xFB, 0x6E, 0x0A, 0x6F, 0x2F, 0xB1, 0xE7, 0x0B, 0xFB, 0x2E, 0xCB, 0xAA, 0x84, 0x14, 0x49, 0xDF, 0x1A, 0xD2, 0xA3, 0x0A, + 0xC4, 0xC6, 0x5B, 0x7E, 0x49, 0x2D, 0x15, 0x04, 0x40, 0x6F, 0x98, 0x00, 0x2C, 0x08, 0x6C, 0xD2, 0x8B, 0xA8, 0xF4, 0xA6, + 0x25, 0x7D, 0x17, 0x22, 0x61, 0x63, 0xD5, 0xF2, 0xEF, 0x23, 0x1D, 0xD6, 0x52, 0xEA, 0xD6, 0x29, 0x51, 0x7C, 0xC5, 0x89, + 0xA0, 0xBF, 0x45, 0x88, 0x03, 0x29, 0x4C, 0x3F, 0x45, 0xAD, 0x6A, 0x20, 0xFE, 0x10, 0x53, 0x50, 0x21, 0xB8, 0x35, 0x0B, + 0xB0, 0x53, 0xB2, 0x57, 0xF1, 0xAE, 0xD9, 0x31, 0xD2, 0x73, 0x9A, 0x26, 0x32, 0x5B, 0xC2, 0xBB, 0x53, 0x54, 0x34, 0xA6, + 0x39, 0x5B, 0xCC, 0xE0, 0xFA, 0x6E, 0x5C, 0xD0, 0x25, 0x74, 0x74, 0xC4, 0x94, 0x33, 0x04, 0x74, 0x7F, 0xBB, 0x9C, 0x70, + 0x6F, 0x66, 0x85, 0x78, 0xB2, 0x54, 0x9D, 0x7D, 0x81, 0x00, 0xE1, 0x03, 0x60, 0x52, 0x8C, 0x00, 0x17, 0x7D, 0xA6, 0x55, + 0x91, 0x17, 0xED, 0x35, 0x12, 0xC8, 0x55, 0xFC, 0x61, 0x53, 0x66, 0x71, 0xE7, 0x60, 0xCE, 0x88, 0x57, 0x11, 0xBC, 0x7F, + 0x65, 0x7A, 0xEE, 0xAA, 0x0E, 0x43, 0xCF, 0x4C, 0x9D, 0x71, 0x61, 0xEB, 0x26, 0x12, 0xD7, 0x3A, 0x9C, 0xC6, 0x47, 0x41, + 0x6F, 0xC9, 0x92, 0xC8, 0x4A, 0xD2, 0xDC, 0xAA, 0xAE, 0x99, 0x02, 0xA5, 0xBB, 0x69, 0xE7, 0xCF, 0x9F, 0x5A, 0x91, 0x0D, + 0xFE, 0x3A, 0x8E, 0x1D, 0xB5, 0x0A, 0x23, 0x75, 0x69, 0x76, 0x70, 0x3D, 0xF5, 0x4A, 0x2D, 0x6D, 0xCE, 0x5E, 0x86, 0x15, + 0xC2, 0x1F, 0x7E, 0x0B, 0xE4, 0x36, 0x8A, 0x8A, 0x95, 0x81, 0xDE, 0xF9, 0x49, 0x17, 0xF6, 0x48, 0x8C, 0x50, 0x55, 0xA6, + 0xB9, 0x11, 0x3F, 0x10, 0x44, 0x90, 0xFE, 0x8E, 0xF9, 0x31, 0x53, 0xD0, 0x99, 0xE5, 0xD0, 0xBF, 0x45, 0x7C, 0xB0, 0xA9, + 0xEE, 0x7A, 0x0D, 0x6D, 0xFC, 0xEE, 0x17, 0xC8, 0x2E, 0x3E, 0x5C, 0xBF, 0xC7, 0x30, 0x2D, 0xF8, 0xBF, 0x1D, 0x90, 0x1F, + 0x57, 0x70, 0x12, 0x06, 0x57, 0x13, 0xB8, 0xE6, 0x12, 0xD0, 0x88, 0xD8, 0x54, 0x8D, 0x98, 0x5C, 0xF7, 0xA2, 0xF1, 0x31, + 0x3A, 0x88, 0x58, 0x51, 0x13, 0xD1, 0x18, 0xD8, 0xB4, 0x48, 0xE2, 0x54, 0x77, 0x0C, 0xFA, 0x90, 0xFB, 0x8B, 0xB0, 0xC7, + 0xE4, 0xB9, 0x4E, 0xBC, 0x31, 0x4B, 0x6B, 0x07, 0x56, 0xE6, 0x77, 0x52, 0x8D, 0x28, 0x7A, 0xE7, 0x15, 0xE1, 0x19, 0xB9, + 0xC4, 0xA3, 0x7D, 0xB5, 0x14, 0x62, 0x3B, 0x24, 0x45, 0x8B, 0xD8, 0x56, 0xB5, 0xBF, 0x74, 0x02, 0x42, 0xED, 0xF3, 0x69, + 0x55, 0xA4, 0x10, 0xB4, 0xA2, 0x0F, 0xEE, 0xD2, 0x03, 0xA2, 0x32, 0x90, 0x66, 0x85, 0x78, 0x9E, 0x36, 0x6E, 0x79, 0x4F, + 0x23, 0x07, 0x3D, 0x31, 0x74, 0x26, 0x03, 0x8B, 0xE9, 0x0B, 0xD5, 0xED, 0xBD, 0x1E, 0xEE, 0xBB, 0x03, 0x48, 0xE1, 0x5E, + 0x15, 0xAB, 0x5D, 0xBB, 0xF4, 0xAC, 0xFF, 0x91, 0xE4, 0xD1, 0xAA, 0x28, 0x77, 0x81, 0x23, 0xA0, 0x1D, 0xC8, 0x22, 0x9A, + 0x04, 0x65, 0x8A, 0xDD, 0x07, 0x65, 0xDB, 0x9E, 0x14, 0xBF, 0x25, 0xAC, 0x19, 0x4B, 0x5A, 0x79, 0x31, 0xC4, 0x7A, 0xD3, + 0x1A, 0x64, 0x78, 0x84, 0x8A, 0x79, 0xB3, 0xBF, 0xCE, 0x07, 0x2C, 0x99, 0x5C, 0xB8, 0xD3, 0x6C, 0xAC, 0xE5, 0xF4, 0x1A, + 0x8B, 0x7A, 0xF2, 0xF7, 0x38, 0x0A, 0x63, 0x3E, 0xAE, 0x8B, 0x44, 0xBB, 0xF5, 0x13, 0x5C, 0x8F, 0x2D, 0x2C, 0x5D, 0x2C, + 0x91, 0x2A, 0xC8, 0x8A, 0x1E, 0x8E, 0xA8, 0x91, 0xD6, 0x6A, 0xEF, 0x29, 0x52, 0x0A, 0xA3, 0xB6, 0x30, 0x60, 0x23, 0x9F, + 0x28, 0xED, 0x7A, 0x7D, 0xCD, 0xF6, 0x3A, 0x4D, 0x6B, 0x87, 0xE5, 0x0F, 0x9A, 0x8A, 0xF2, 0xC9, 0xCD, 0x2E, 0xAA, 0x97, + 0x7B, 0xE5, 0xEB, 0x4F, 0x6E, 0x94, 0x14, 0x2F, 0x97, 0xA6, 0xBB, 0x63, 0x4F, 0x42, 0x27, 0x09, 0x9C, 0x1F, 0x6C, 0x93, + 0xC5, 0x6F, 0x43, 0x76, 0xB4, 0xF2, 0x7C, 0x97, 0xE9, 0x6D, 0x69, 0xC6, 0xA9, 0x8D, 0xA1, 0x71, 0x07, 0xD3, 0xBC, 0x26, + 0x59, 0x1C, 0x27, 0x38, 0x64, 0xB1, 0xDC, 0xB4, 0x72, 0xFC, 0xE5, 0x5E, 0xF4, 0xD0, 0x24, 0x29, 0xB5, 0xD2, 0xD2, 0x53, + 0x64, 0xCD, 0x1A, 0xF9, 0x41, 0x2E, 0xA9, 0x17, 0xF6, 0x00, 0x22, 0x25, 0xBD, 0xF2, 0x2D, 0x03, 0xF3, 0x7E, 0xC2, 0x4F, + 0xF5, 0x57, 0xA4, 0x8F, 0xF0, 0xD6, 0x84, 0x85, 0x4E, 0xB9, 0xF5, 0x40, 0x67, 0xE4, 0x94, 0xE4, 0x59, 0xF9, 0xE3, 0xA2, + 0x2F, 0x9C, 0xB0, 0xB4, 0xC8, 0xD9, 0x46, 0x70, 0xE6, 0x28, 0x50, 0x69, 0x76, 0xB5, 0xFA, 0x8B, 0x82, 0x3B, 0x36, 0x25, + 0x34, 0xB2, 0x2C, 0x06, 0x81, 0x96, 0x0A, 0x0F, 0x6C, 0xBB, 0x6B, 0xA1, 0x94, 0xFC, 0x8D, 0x94, 0xC3, 0xBA, 0x05, 0x1B, + 0xC8, 0x1A, 0xD9, 0x7D, 0xC4, 0x9C, 0xE6, 0x87, 0x53, 0xDA, 0xC6, 0xC8, 0x6B, 0xB5, 0xB9, 0x4A, 0x2A, 0xDE, 0x7B, 0x92, + 0xB4, 0x62, 0xCB, 0x3A, 0x4F, 0xF9, 0x06, 0x47, 0x9C, 0x3A, 0x46, 0xD8, 0x4E, 0xB9, 0x65, 0x9D, 0x02, 0xF0, 0x24, 0x1D, + 0xAA, 0x61, 0xB1, 0xEE, 0x1F, 0xBC, 0x1B, 0x96, 0x4D, 0x58, 0x20, 0x2B, 0xFF, 0xF2, 0xEF, 0x36, 0x7D, 0xD9, 0xAF, 0x7D, + 0xBB, 0xCB, 0x61, 0xE6, 0xE5, 0x56, 0x0A, 0x67, 0x49, 0x81, 0x9C, 0xEE, 0x1D, 0xB9, 0x01, 0x4C, 0xB7, 0x0D, 0x04, 0xEE, + 0x76, 0x9E, 0x4C, 0x5C, 0x7C, 0xBE, 0x6A, 0x1A, 0x05, 0x86, 0xEB, 0x2F, 0x62, 0xFD, 0x27, 0x1F, 0x08, 0xBD, 0x3E, 0xF2, + 0xCD, 0xF7, 0xDF, 0x34, 0x21, 0x18, 0xDF, 0x5D, 0xBE, 0xB6, 0xF6, 0x49, 0xED, 0x5E, 0x37, 0xE2, 0xCC, 0x23, 0x18, 0xBD, + 0xCE, 0x3F, 0xB6, 0x54, 0xDC, 0x40, 0x26, 0x1E, 0x0A, 0x58, 0xFA, 0x17, 0xD0, 0x34, 0x10, 0x72, 0x82, 0x0C, 0x44, 0x5A, + 0x1E, 0x3E, 0xA8, 0xDF, 0x61, 0xC2, 0x5E, 0x91, 0x98, 0x7A, 0xB2, 0xA2, 0x21, 0xB1, 0xA4, 0xDB, 0x72, 0x8B, 0x9F, 0xC1, + 0x1C, 0x01, 0xBE, 0xE0, 0x6B, 0xC5, 0xBE, 0xE3, 0xB3, 0x69, 0xFC, 0xA5, 0x31, 0x62, 0xD1, 0x39, 0x5C, 0x4A, 0x43, 0x36, + 0x9B, 0x71, 0xC9, 0x1C, 0xB3, 0xDE, 0x9F, 0x28, 0x22, 0x6E, 0xA6, 0x61, 0xC2, 0x0C, 0xD4, 0x99, 0x19, 0x39, 0x18, 0x95, + 0xEB, 0xC7, 0x7B, 0x34, 0x92, 0x8B, 0xC7, 0x68, 0xC2, 0xE4, 0xF0, 0x8E, 0xA7, 0xED, 0xDC, 0x23, 0x79, 0x47, 0xE8, 0xC7, + 0xB0, 0x64, 0x9C, 0xBA, 0xF8, 0x46, 0xB2, 0x07, 0x58, 0x2A, 0xAD, 0xD3, 0x8A, 0x0C, 0xB9, 0xCD, 0x37, 0xAF, 0xFA, 0x26, + 0xCC, 0x9A, 0xF1, 0xEF, 0xF6, 0x7D, 0x4A, 0x2D, 0x6A, 0x94, 0x09, 0x45, 0xFC, 0x3C, 0x61, 0xE9, 0xA0, 0xED, 0xD8, 0x06, + 0xD4, 0x28, 0xC2, 0x04, 0xBA, 0x00, 0xDA, 0x08, 0x91, 0x56, 0x4B, 0xA3, 0x2B, 0x97, 0x47, 0x5F, 0x6A, 0xEA, 0x5A, 0xF0, + 0x26, 0xC4, 0xEA, 0x5F, 0x04, 0x6B, 0x24, 0xFD, 0x6A, 0x39, 0x1B, 0x1A, 0xB2, 0xFA, 0x01, 0xE1, 0xA7, 0xC1, 0xE3, 0x5F, + 0xF0, 0x27, 0xEB, 0x5B, 0x6B, 0x0B, 0x53, 0xB9, 0x0B, 0x28, 0x79, 0xB9, 0x8F, 0x49, 0x88, 0x79, 0x98, 0x2A, 0x42, 0x3F, + 0x2C, 0x40, 0x2F, 0x5F, 0x32, 0xD8, 0x58, 0x4A, 0x98, 0x06, 0xED, 0x2A, 0xE9, 0x3C, 0x44, 0x55, 0xF9, 0xC1, 0x42, 0x9C, + 0x78, 0xCD, 0x49, 0x24, 0xE2, 0xDE, 0x31, 0x54, 0xBE, 0xD2, 0x6B, 0x45, 0x5B, 0x49, 0x88, 0x3F, 0xB0, 0x09, 0x05, 0x3A, + 0xF4, 0x4C, 0x7B, 0xB6, 0x8A, 0x63, 0xAB, 0x79, 0xBD, 0x4E, 0xC2, 0x9E, 0x5E, 0xE3, 0x51, 0x5B, 0x19, 0x07, 0x5B, 0x3F, + 0x68, 0x4A, 0x5D, 0x3E, 0xE5, 0x93, 0x4B, 0x0E, 0xCC, 0xC4, 0xBB, 0xE2, 0x60, 0x1F, 0xDE, 0x55, 0x58, 0xC1, 0xC0, 0x51, + 0x02, 0xD0, 0xEA, 0xE5, 0x99, 0x23, 0x04, 0x81, 0x27, 0x41, 0xB6, 0x6B, 0xCC, 0x5D, 0x3C, 0x46, 0xC0, 0x58, 0x9E, 0x30, + 0x37, 0x6C, 0x5C, 0x64, 0x45, 0x95, 0xFC, 0xF7, 0x17, 0x73, 0x4B, 0x10, 0xA8, 0x54, 0xD7, 0x5A, 0x19, 0x41, 0x7D, 0xD1, + 0xB9, 0x15, 0xEB, 0x55, 0xB2, 0x71, 0x1E, 0xD3, 0x1E, 0xDF, 0x5D, 0xB9, 0x55, 0xAC, 0x64, 0x4A, 0x21, 0x76, 0x3B, 0xB7, + 0x39, 0xE2, 0x0E, 0xE1, 0x15, 0x54, 0x44, 0x41, 0x85, 0x89, 0x9C, 0x54, 0x3F, 0x14, 0x04, 0x47, 0x66, 0x98, 0x5A, 0xB7, + 0x4D, 0x89, 0x8E, 0xC3, 0x84, 0x34, 0xFA, 0x52, 0x8C, 0xBB, 0x3E, 0xE1, 0x3F, 0x9B, 0x64, 0xDC, 0xF2, 0x52, 0xC7, 0x85, + 0x0D, 0xAB, 0x45, 0xDC, 0x4A, 0x64, 0xC2, 0xA5, 0x33, 0x28, 0x89, 0xAF, 0x70, 0x68, 0x22, 0x86, 0x8B, 0x81, 0x2E, 0xF7, + 0x89, 0x76, 0xDC, 0xA3, 0x44, 0x97, 0x5C, 0xB5, 0x83, 0xDB, 0x22, 0xCE, 0x87, 0x7E, 0x8E, 0x51, 0xAD, 0x02, 0xF0, 0x9B, + 0x98, 0x90, 0x48, 0x3A, 0xE8, 0xE4, 0xA0, 0x08, 0xF6, 0xCF, 0x65, 0x98, 0xA9, 0x7A, 0x27, 0xFF, 0xDA, 0xDF, 0x2F, 0x79, + 0xB4, 0xF5, 0x3B, 0xD5, 0x59, 0xC5, 0xD3, 0xEF, 0x56, 0x92, 0x18, 0xFD, 0xB5, 0xCB, 0x27, 0x57, 0x45, 0x56, 0x97, 0xA4, + 0x10, 0x28, 0x04, 0x37, 0xC3, 0x2F, 0xF8, 0x0D, 0x5B, 0x38, 0xA9, 0x6A, 0xEB, 0xE1, 0x8C, 0xEE, 0xC9, 0xD5, 0x98, 0xAB, + 0x09, 0x71, 0x75, 0x52, 0xCC, 0x80, 0x66, 0xA5, 0xC8, 0x1C, 0x87, 0x2B, 0xDC, 0x6D, 0xA0, 0x09, 0xAE, 0x50, 0xA6, 0xE9, + 0x24, 0xC1, 0x6F, 0xB5, 0x49, 0x3B, 0xC4, 0x67, 0xDE, 0xF3, 0x2D, 0xDD, 0xAA, 0xDF, 0xAA, 0x26, 0x4A, 0x29, 0x20, 0x8B, + 0x14, 0x1D, 0x27, 0xD9, 0x79, 0x73, 0xA5, 0xAA, 0xF1, 0xC2, 0xC0, 0x41, 0x2D, 0xBB, 0xB2, 0xCA, 0x6B, 0x0F, 0x8E, 0x8F, + 0x14, 0xA2, 0x71, 0xF7, 0x62, 0x89, 0xE0, 0x82, 0x97, 0xED, 0x46, 0xF7, 0x76, 0x85, 0x08, 0xC5, 0x23, 0x84, 0xA0, 0xA9, + 0x87, 0xB2, 0x2B, 0x83, 0x88, 0xBF, 0x68, 0xDB, 0x63, 0x4F, 0x73, 0xFD, 0xD2, 0xB2, 0x13, 0x91, 0x04, 0x7E, 0x2F, 0x75, + 0x17, 0x8F, 0xC3, 0x17, 0x19, 0x32, 0x81, 0xC4, 0xAB, 0x4E, 0xE5, 0x31, 0x38, 0x06, 0xD8, 0xBD, 0xBA, 0xA9, 0xA4, 0x3C, + 0xD5, 0xFB, 0x88, 0x62, 0xB6, 0x31, 0x20, 0x56, 0x80, 0x66, 0x50, 0xB9, 0x07, 0xE8, 0x58, 0x5E, 0x24, 0xE5, 0xBE, 0x14, + 0xE4, 0x80, 0x1E, 0x30, 0xBC, 0x30, 0x1A, 0x60, 0x37, 0x59, 0x8E, 0xE1, 0x4B, 0x9F, 0x89, 0x43, 0x54, 0xEA, 0x57, 0xFF, + 0xE7, 0x58, 0x94, 0x5F, 0x32, 0xF8, 0xA2, 0x73, 0x77, 0x36, 0xC1, 0x9C, 0x7B, 0xEA, 0x5A, 0xE2, 0x23, 0x45, 0xAD, 0x8A, + 0x4C, 0xE1, 0x52, 0x78, 0x28, 0xC5, 0x63, 0xBE, 0xA3, 0x45, 0x3A, 0x7A, 0x01, 0x7E, 0xE0, 0xF6, 0x04, 0xEB, 0x5A, 0x38, + 0xBE, 0xC4, 0x83, 0xBA, 0x49, 0xAC, 0x69, 0x16, 0x73, 0x03, 0xAB, 0x03, 0x1E, 0xC6, 0x6B, 0x2F, 0x45, 0xB4, 0xE2, 0xBF, + 0xDA, 0x28, 0x23, 0x0F, 0x0F, 0x87, 0x2E, 0x75, 0x9C, 0xBB, 0x65, 0x9F, 0xCD, 0x64, 0xC5, 0x7F, 0x71, 0xE6, 0x1D, 0x39, + 0x60, 0xE0, 0xE3, 0x28, 0x83, 0xB3, 0x73, 0x68, 0x06, 0xA0, 0x0B, 0x49, 0xFF, 0x93, 0x54, 0x1B, 0x09, 0x1D, 0x11, 0x56, + 0xBA, 0x52, 0x13, 0x91, 0xB0, 0xCB, 0xB9, 0x8D, 0xDB, 0x60, 0x04, 0x0B, 0xAA, 0xE0, 0x73, 0xA7, 0xF5, 0xE3, 0xA7, 0x35, + 0xE0, 0x12, 0x63, 0x5E, 0x7F, 0x6F, 0xF0, 0x28, 0x8E, 0x06, 0x47, 0x2C, 0x98, 0x59, 0x53, 0x00, 0x4F, 0x4D, 0xA9, 0x60, + 0x34, 0x8B, 0x64, 0xE2, 0x64, 0x6D, 0x84, 0xEC, 0xD5, 0x1F, 0xC9, 0xEE, 0x45, 0x20, 0xF6, 0x3D, 0x8F, 0x5D, 0x49, 0xF4, + 0x65, 0xDE, 0xB2, 0x56, 0x14, 0xD3, 0x67, 0xB2, 0x1E, 0x91, 0x3C, 0xF5, 0xF4, 0x5C, 0x57, 0x23, 0xEC, 0x89, 0xF5, 0x74, + 0x9E, 0x4F, 0x86, 0x07, 0x18, 0xB1, 0x63, 0xE0, 0x2E, 0xF8, 0xED, 0x9E, 0x66, 0x9B, 0x6D, 0x5A, 0x04, 0xDF, 0xFD, 0xB7, + 0xD5, 0x07, 0xED, 0x05, 0xFD, 0x33, 0x5A, 0x63, 0xEC, 0x17, 0x9F, 0xB4, 0x09, 0x25, 0xBB, 0x9E, 0x9B, 0x75, 0xB2, 0x62, + 0x36, 0x8D, 0xC0, 0x40, 0x2F, 0x9D, 0x00, 0xD2, 0x77, 0x25, 0x03, 0x76, 0x38, 0x0C, 0x51, 0x89, 0xEA, 0xA9, 0x2D, 0xDA, + 0x4F, 0x95, 0x3C, 0xC6, 0x0D, 0xA9, 0x4D, 0x1C, 0x13, 0x97, 0x95, 0xA5, 0xEC, 0xB7, 0x6C, 0xA0, 0x8D, 0x31, 0x8D, 0x95, + 0xFD, 0xBA, 0xC2, 0xC2, 0x46, 0x28, 0x46, 0xB9, 0xD3, 0x01, 0xB0, 0xAD, 0x8D, 0x67, 0x98, 0x46, 0xF6, 0x52, 0xE6, 0xB5, + 0x42, 0x94, 0x88, 0x0F, 0x1D, 0x98, 0xE9, 0x72, 0xA9, 0x54, 0x90, 0x4A, 0xF7, 0x13, 0x95, 0x90, 0x11, 0xC9, 0xA4, 0xBF, + 0x5E, 0x43, 0x9C, 0x4C, 0x72, 0x90, 0xA5, 0x7C, 0x9E, 0xD6, 0xE1, 0xC4, 0x39, 0x87, 0xAF, 0xB7, 0x15, 0xF9, 0x77, 0x17, + 0x9E, 0x00, 0xAD, 0x6C, 0x97, 0x1F, 0x1F, 0xAA, 0x38, 0xB7, 0x81, 0x1E, 0x9C, 0x7B, 0x30, 0x8A, 0x2A, 0xD2, 0x9D, 0xE9, + 0x9F, 0x03, 0xCD, 0xCE, 0xE3, 0x51, 0x4D, 0x9E, 0xFE, 0xE3, 0x0E, 0x9D, 0x1A, 0x90, 0xD6, 0xFA, 0xCC, 0xD1, 0x18, 0x27, + 0x98, 0xC6, 0x6E, 0xB9, 0x4C, 0xC3, 0xB1, 0xEB, 0xC0, 0x5C, 0x53, 0xAD, 0x49, 0xDB, 0x11, 0x8B, 0x11, 0x53, 0x4E, 0x9F, + 0x7E, 0xE8, 0x94, 0xFC, 0x0E, 0x8A, 0x50, 0x44, 0x4E, 0x36, 0xA5, 0xBC, 0x4A, 0x29, 0x47, 0x6D, 0xF7, 0xBE, 0x3A, 0xE8, + 0x24, 0x4F, 0x7F, 0x77, 0x64, 0x4C, 0xEB, 0x53, 0x21, 0x2C, 0x21, 0xDB, 0xB9, 0x23, 0x6E, 0x65, 0xEA, 0xD0, 0x3E, 0x53, + 0xF8, 0x7B, 0x0A, 0xCE, 0xAA, 0xC8, 0xCC, 0xE4, 0xE5, 0xDE, 0xAD, 0xE9, 0x14, 0xCF, 0x66, 0x45, 0x94, 0x03, 0xF2, 0x61, + 0x88, 0xBF, 0xDB, 0x0B, 0x27, 0xCF, 0x50, 0x0A, 0x87, 0x4B, 0xEF, 0x28, 0x6E, 0x5E, 0x40, 0xB9, 0x28, 0xCA, 0xA7, 0x95, + 0x92, 0x32, 0x41, 0x26, 0xFD, 0x46, 0xFA, 0xAC, 0x1E, 0x6B, 0xC1, 0x20, 0x66, 0x06, 0xCC, 0x82, 0xD0, 0xB0, 0xF0, 0xAE, + 0x13, 0x48, 0x59, 0xAB, 0x9E, 0x83, 0x66, 0x59, 0xCE, 0xE3, 0x5C, 0x12, 0xDE, 0x93, 0x4E, 0xBD, 0xB1, 0xA4, 0x98, 0x74, + 0x37, 0x87, 0xD9, 0x65, 0x29, 0x57, 0x0A, 0x07, 0x2D, 0x7D, 0xB6, 0xD5, 0xDA, 0xDC, 0x58, 0x95, 0x97, 0xDC, 0x48, 0xB1, + 0xD5, 0x5C, 0xD1, 0x64, 0x32, 0x28, 0x43, 0x1B, 0xAB, 0xF9, 0x6E, 0x93, 0x19, 0x48, 0xEA, 0xC0, 0x60, 0x05, 0xE9, 0x5F, + 0x2C, 0xC3, 0x34, 0x25, 0x28, 0x89, 0xF4, 0xB9, 0xF2, 0x6A, 0xE2, 0x98, 0x05, 0x79, 0xEE, 0xCF, 0xDD, 0xE4, 0x5A, 0x1B, + 0xEF, 0xFA, 0x2E, 0x72, 0x05, 0xA7, 0x05, 0x59, 0xFB, 0x78, 0xEB, 0x25, 0x38, 0xEB, 0xF1, 0xF1, 0x51, 0xCB, 0xF5, 0xBC, + 0x72, 0x28, 0xA3, 0xD1, 0xDB, 0x04, 0xC9, 0x26, 0x32, 0x0F, 0x22, 0x56, 0x0F, 0x01, 0x3D, 0x3F, 0x26, 0x42, 0x56, 0x0E, + 0x0A, 0x03, 0x12, 0xB5, 0x9F, 0x2D, 0x42, 0x5D, 0xE2, 0xE4, 0x8A, 0x3A, 0x38, 0xED, 0x64, 0x51, 0x23, 0xA4, 0xF2, 0x7B, + 0xDA, 0x29, 0xEF, 0xA1, 0x1E, 0xC8, 0x24, 0x0D, 0xF4, 0x35, 0x31, 0x68, 0xCB, 0x6C, 0xFB, 0x0F, 0x5B, 0x61, 0x33, 0x2B, + 0x09, 0xDB, 0xC9, 0xBB, 0x7A, 0x34, 0xA4, 0xFD, 0x8E, 0x42, 0xF3, 0xBF, 0xB0, 0x61, 0x5D, 0x81, 0x87, 0x0B, 0x50, 0xD9, + 0xDB, 0x53, 0xB2, 0xD3, 0xC3, 0x9F, 0x54, 0xE5, 0xAB, 0x7D, 0x4B, 0x12, 0x03, 0xE1, 0x5C, 0xE7, 0x1B, 0x89, 0xBE, 0xCF, + 0x86, 0xDC, 0x68, 0xC5, 0xD2, 0x30, 0xC0, 0x67, 0x82, 0x30, 0xBB, 0x21, 0xE5, 0x9D, 0xD5, 0x74, 0x56, 0x49, 0xCC, 0xB2, + 0x94, 0x74, 0x35, 0xD6, 0x6B, 0x9A, 0xF3, 0x34, 0x58, 0x30, 0x7D, 0xAF, 0x9E, 0x5C, 0x35, 0x00, 0xF7, 0xB9, 0xE3, 0xE9, + 0x11, 0xD0, 0x84, 0xA2, 0x70, 0x7B, 0x41, 0x92, 0x9D, 0x4F, 0x60, 0x86, 0x8D, 0x72, 0x13, 0x51, 0x25, 0x46, 0xDA, 0xA1, + 0xCC, 0x77, 0x3C, 0xEE, 0x22, 0x58, 0xA4, 0x76, 0xF2, 0x28, 0xFF, 0x3E, 0x9D, 0x47, 0xE5, 0xCD, 0x5B, 0x07, 0x15, 0x87, + 0xC3, 0x46, 0xFD, 0x8A, 0x53, 0x87, 0x39, 0xCE, 0x93, 0xBA, 0x47, 0xB7, 0x31, 0xE3, 0xF1, 0x62, 0xDB, 0xA8, 0xE5, 0x49, + 0x50, 0x6C, 0x5F, 0xA9, 0x8F, 0x55, 0x8D, 0x7F, 0x1A, 0x48, 0x76, 0xAA, 0xEC, 0x55, 0xFC, 0x44, 0x3A, 0x35, 0x74, 0x88, + 0x8E, 0x14, 0x5A, 0x4C, 0x72, 0xC6, 0x9E, 0x55, 0x61, 0xF4, 0x4D, 0x5A, 0xFE, 0x9A, 0xF8, 0x29, 0x45, 0x0A, 0x06, 0x8F, + 0x2D, 0x97, 0xBB, 0x2C, 0x57, 0x51, 0x00, 0x4B, 0xEA, 0x37, 0x71, 0xE9, 0x2E, 0xFB, 0xB1, 0x39, 0xFA, 0x91, 0xD6, 0xB6, + 0x4A, 0xDF, 0x5F, 0x69, 0x3A, 0x60, 0x57, 0x3A, 0x0B, 0x7C, 0x95, 0xAE, 0xC5, 0x91, 0xE9, 0x2F, 0xA8, 0x1C, 0x46, 0x8A, + 0x5B, 0x3C, 0x6F, 0xAE, 0x40, 0x12, 0x4A, 0x58, 0x2C, 0xF5, 0xA5, 0x38, 0x2B, 0xD0, 0xC4, 0xFD, 0x5A, 0x3D, 0x61, 0xE1, + 0x92, 0x05, 0x56, 0x0A, 0x64, 0x36, 0x5F, 0xE0, 0x17, 0xD8, 0xE3, 0x69, 0x13, 0xD7, 0xC8, 0xEB, 0x98, 0xFB, 0x96, 0xDC, + 0x1E, 0x34, 0x06, 0x79, 0x4C, 0x59, 0xFB, 0x66, 0x79, 0xAB, 0x79, 0x19, 0xE1, 0xEE, 0x59, 0x68, 0x99, 0x06, 0x69, 0xAB, + 0xAD, 0x49, 0x70, 0x36, 0x69, 0x40, 0xF2, 0x1E, 0x36, 0x05, 0x5E, 0x3B, 0xFE, 0xE5, 0x58, 0x92, 0x5D, 0xCE, 0x4C, 0x56, + 0xBC, 0x08, 0x43, 0x0F, 0x85, 0x42, 0x36, 0xC7, 0xB6, 0x29, 0xC9, 0xCB, 0xD6, 0x8F, 0x22, 0x26, 0x2F, 0xE4, 0xF3, 0x0E, + 0x83, 0xCB, 0x93, 0xA7, 0x15, 0x0C, 0x60, 0xBA, 0x60, 0xC5, 0xC1, 0xDF, 0x41, 0x2E, 0x47, 0xA0, 0x35, 0xE6, 0x64, 0xA0, + 0x25, 0xA6, 0xB0, 0xBB, 0x83, 0xC0, 0xB0, 0xC6, 0x4E, 0x06, 0x2E, 0xB4, 0x17, 0xCA, 0x8A, 0x46, 0x16, 0xE4, 0x80, 0x9A, + 0x23, 0x88, 0x0C, 0xF0, 0x6D, 0xA9, 0x99, 0x4B, 0x21, 0x9D, 0x59, 0x57, 0x31, 0xCA, 0x73, 0x11, 0xF5, 0xE6, 0x19, 0x76, + 0x72, 0x56, 0x09, 0x0C, 0x66, 0xC5, 0x89, 0x55, 0xEC, 0xAA, 0x86, 0x9B, 0xD9, 0x8A, 0x28, 0xF3, 0x8C, 0xB9, 0x6A, 0x88, + 0x2E, 0xB8, 0x06, 0x6C, 0xA7, 0x25, 0x62, 0x37, 0xEF, 0xA4, 0x06, 0xCC, 0x67, 0x58, 0xAC, 0x68, 0x3E, 0x88, 0xD1, 0x54, + 0xA4, 0xB5, 0x44, 0x06, 0x7E, 0xDD, 0x39, 0x58, 0xF1, 0xE6, 0x1B, 0xF8, 0xED, 0xC6, 0x7C, 0x0E, 0x6B, 0x15, 0x0D, 0x5B, + 0x06, 0x23, 0x0F, 0x08, 0x7F, 0xF1, 0xD3, 0xF3, 0x8F, 0xC4, 0x6B, 0x0F, 0xBF, 0x06, 0xFB, 0x7F, 0xDF, 0xD0, 0x0F, 0xCF, + 0xD5, 0xE4, 0xEA, 0x1A, 0x65, 0xDD, 0xA8, 0xEE, 0xE1, 0x5B, 0x70, 0x8C, 0xC1, 0x3A, 0xAD, 0x6C, 0xBF, 0x13, 0x95, 0xB7, + 0x3B, 0x00, 0xB2, 0x4F, 0x2C, 0xE9, 0x40, 0x9C, 0x49, 0x55, 0xF8, 0x5D, 0x52, 0xEB, 0x9C, 0xA3, 0x1E, 0x43, 0xA3, 0xCF, + 0x77, 0xC4, 0x3B, 0x6F, 0xE7, 0x54, 0x33, 0xBE, 0xAD, 0xA0, 0x14, 0xDF, 0xB9, 0xA8, 0x51, 0x3F, 0xD3, 0xB4, 0x9F, 0x64, + 0xFB, 0x1B, 0xAB, 0x79, 0x7E, 0x30, 0x7D, 0xA3, 0x81, 0x8B, 0x5F, 0xF5, 0x1E, 0x3A, 0x4A, 0x9F, 0x8D, 0x8A, 0x76, 0xC0, + 0x08, 0xBF, 0x42, 0xE1, 0x44, 0xFF, 0xE6, 0x07, 0xC6, 0x1C, 0x44, 0xD2, 0x61, 0x71, 0xDC, 0xA8, 0xAD, 0xFC, 0x35, 0x65, + 0xA2, 0x48, 0xEB, 0x7C, 0x5D, 0xB1, 0x90, 0x41, 0x24, 0x7F, 0xF4, 0xC1, 0x82, 0xBD, 0x4B, 0xE6, 0xA6, 0x33, 0x3E, 0x66, + 0x16, 0xA3, 0xAA, 0xC0, 0xF2, 0x72, 0xBF, 0x55, 0x77, 0x27, 0xF6, 0x3D, 0x20, 0xAE, 0x22, 0x2E, 0x34, 0xF9, 0xD7, 0xB2, + 0x8F, 0xE5, 0x83, 0x84, 0x55, 0x76, 0x0C, 0x94, 0x7E, 0x9A, 0x1D, 0xC9, 0x07, 0xAE, 0x5E, 0x01, 0x57, 0xCE, 0x25, 0x1E, + 0x3F, 0x08, 0xE7, 0xBD, 0x4D, 0xE7, 0xBD, 0x43, 0xB0, 0x5C, 0x0D, 0x12, 0x45, 0x26, 0x42, 0x8B, 0xF0, 0x0C, 0x34, 0x57, + 0x02, 0x68, 0x4F, 0xA1, 0xDE, 0xA6, 0x5C, 0x87, 0xC6, 0x55, 0x05, 0xC8, 0xCA, 0xB5, 0x18, 0xFF, 0x6C, 0x37, 0x94, 0xBE, + 0xC4, 0x17, 0xA1, 0x3A, 0xA4, 0x29, 0x65, 0xCC, 0x5D, 0xEB, 0xD1, 0xDD, 0x1E, 0xCD, 0xD0, 0x99, 0x3B, 0x39, 0xC6, 0xC8, + 0xD2, 0x76, 0xA4, 0xAE, 0x5E, 0xFA, 0x3D, 0x63, 0x8C, 0xD7, 0x07, 0xFD, 0xDE, 0x0E, 0x4F, 0xB9, 0xDF, 0x68, 0xD7, 0xB1, + 0x24, 0xF7, 0x95, 0x04, 0x52, 0x19, 0x32, 0xEC, 0x93, 0x31, 0xAC, 0x53, 0xB7, 0x96, 0xE6, 0x3A, 0x58, 0x24, 0x58, 0xE6, + 0xA3, 0x6A, 0xFE, 0xDA, 0xDA, 0xAD, 0x48, 0xC2, 0x5D, 0x18, 0x3D, 0x82, 0x4D, 0x1C, 0x50, 0xF7, 0x21, 0xFF, 0xD0, 0x1B, + 0x1E, 0x7D, 0x3E, 0x0A, 0x67, 0x92, 0x49, 0x93, 0x79, 0x07, 0x2F, 0xCF, 0x72, 0xCF, 0xDD, 0x27, 0xB2, 0xF1, 0xED, 0x8B, + 0xB6, 0xC5, 0x48, 0x09, 0x7E, 0xBC, 0x25, 0x66, 0x22, 0x39, 0xB6, 0xDA, 0x1A, 0x1E, 0x26, 0xED, 0x0B, 0xCE, 0x26, 0x17, + 0xB3, 0x02, 0xF8, 0x3F, 0x35, 0x42, 0xD9, 0x1E, 0x54, 0x23, 0x8A, 0xC2, 0xA0, 0xBF, 0x81, 0x37, 0x47, 0x6F, 0xB7, 0xF6, + 0x07, 0xF2, 0xD2, 0x15, 0xB6, 0x6D, 0x23, 0xA3, 0xE2, 0x9E, 0xE6, 0x0C, 0xB0, 0xCE, 0xCA, 0x6D, 0xB3, 0xA2, 0x02, 0xBC, + 0xA3, 0x63, 0xBD, 0x5A, 0x1E, 0xBD, 0xA3, 0x36, 0x73, 0x13, 0xC8, 0xF9, 0xDD, 0x4E, 0x8B, 0x91, 0xCA, 0x20, 0xA4, 0x00, + 0xF8, 0xFC, 0x8C, 0x46, 0xE9, 0x0F, 0x7E, 0x68, 0x23, 0x86, 0xD1, 0x67, 0x77, 0x65, 0xE8, 0x9B, 0xCF, 0xB9, 0xC2, 0x4F, + 0xB9, 0x20, 0x81, 0xAF, 0xEA, 0x74, 0xDA, 0x09, 0xF8, 0x61, 0x50, 0x78, 0x63, 0x24, 0x6C, 0x53, 0xF2, 0xFA, 0xED, 0x32, + 0xF2, 0xA0, 0xFF, 0x6D, 0xFA, 0x2B, 0x36, 0x13, 0x00, 0x46, 0xEB, 0xD5, 0x5B, 0x27, 0x2B, 0x51, 0x85, 0xD4, 0xF3, 0xE5, + 0x1A, 0x88, 0x5F, 0x99, 0xCC, 0xCC, 0x6D, 0x17, 0x28, 0x25, 0x7D, 0x2E, 0x12, 0x85, 0xA2, 0xAD, 0x1E, 0x92, 0x28, 0x8D, + 0xBB, 0x0A, 0xF4, 0xE0, 0x59, 0x28, 0x6A, 0x06, 0xF3, 0x04, 0x75, 0xF4, 0x3D, 0x64, 0xA1, 0xDE, 0x59, 0xB4, 0x9A, 0x5E, + 0x78, 0x29, 0xD7, 0x59, 0x08, 0xF5, 0xD3, 0xE5, 0x8E, 0x67, 0x17, 0x6A, 0xFB, 0x1A, 0xBF, 0xD2, 0xDE, 0x99, 0xF0, 0x4B, + 0xA7, 0x68, 0x27, 0x82, 0x9A, 0x7B, 0xE3, 0xC0, 0xC1, 0xE6, 0xB7, 0xDE, 0x30, 0xFA, 0x1F, 0xCC, 0x7C, 0xB8, 0x66, 0x2E, + 0xED, 0x49, 0x56, 0x8E, 0x79, 0x77, 0x19, 0x6C, 0xD7, 0x91, 0x8A, 0xE5, 0x0B, 0x86, 0xDC, 0x3E, 0x7B, 0x94, 0x01, 0xEE, + 0x4A, 0x0D, 0xDA, 0x58, 0xEE, 0xCC, 0x4B, 0x4D, 0x03, 0x21, 0xFB, 0x69, 0x73, 0x3F, 0xEB, 0x96, 0x45, 0x55, 0xB1, 0x6F, + 0x2F, 0xE8, 0x4F, 0xBB, 0x43, 0x3E, 0xB5, 0x5B, 0x7A, 0xAC, 0xE4, 0x8F, 0xF8, 0x2B, 0xE3, 0x4D, 0x9E, 0xC0, 0xF9, 0xB1, + 0x19, 0xAF, 0x44, 0x41, 0xE1, 0x3E, 0x5A, 0x58, 0x66, 0xBA, 0xCE, 0xC0, 0x76, 0xA3, 0x96, 0x83, 0x04, 0x1E, 0x28, 0x56, + 0x92, 0x3F, 0x46, 0xB8, 0xC2, 0xFC, 0x94, 0xB0, 0xF8, 0x5E, 0x3F, 0x24, 0x53, 0xBF, 0xED, 0x47, 0x34, 0x3C, 0x91, 0x23, + 0xE1, 0xBC, 0x31, 0x21, 0x86, 0xC6, 0x3F, 0x6E, 0x55, 0x1C, 0xB5, 0x31, 0x50, 0x9C, 0x03, 0x76, 0x2B, 0x9A, 0xA3, 0x7C, + 0xB3, 0xDA, 0x29, 0x28, 0xE2, 0x59, 0x68, 0xE0, 0x87, 0x9F, 0xAB, 0x9E, 0x03, 0x50, 0xAA, 0xE3, 0x56, 0xC0, 0x14, 0xD4, + 0xAA, 0x3A, 0xE1, 0x27, 0xB7, 0xB8, 0xE4, 0x0F, 0x65, 0x86, 0x27, 0xD3, 0xD2, 0x34, 0x1D, 0xC5, 0xB0, 0x5B, 0xBD, 0xD1, + 0x52, 0xB7, 0x37, 0xE3, 0xE1, 0xB6, 0x75, 0xFF, 0x7E, 0x7B, 0x73, 0x05, 0xCA, 0xBD, 0x9F, 0x92, 0x97, 0x9A, 0x32, 0x8E, + 0x40, 0x4C, 0x87, 0x24, 0xC7, 0x68, 0xC6, 0x89, 0xA1, 0x03, 0x17, 0x7F, 0x7B, 0x23, 0x1E, 0x49, 0x89, 0xA7, 0x87, 0xCC, + 0x3A, 0xA3, 0xB1, 0x7E, 0x9D, 0x60, 0xD6, 0x95, 0x0A, 0xDF, 0x00, 0xB8, 0xCF, 0xA9, 0x57, 0x43, 0x8C, 0xDA, 0x06, 0xF7, + 0x0F, 0x0A, 0x4B, 0x6B, 0x51, 0xC2, 0xD7, 0x74, 0xCE, 0xF1, 0x97, 0xDE, 0x88, 0xDB, 0x6F, 0x87, 0x53, 0x16, 0x4F, 0x21, + 0x0D, 0x33, 0x46, 0xB2, 0xAD, 0x15, 0x0A, 0x39, 0x8F, 0x40, 0x1E, 0xD0, 0xA7, 0xB1, 0xD7, 0xFD, 0x9B, 0xBD, 0x18, 0x6C, + 0x2A, 0x34, 0x69, 0x0A, 0x19, 0xD6, 0x2C, 0xC8, 0x2A, 0x5D, 0x9C, 0x9F, 0xD0, 0x59, 0x20, 0xFE, 0x8A, 0xDE, 0x4E, 0x0F, + 0xF7, 0xD0, 0x0E, 0x5A, 0xE5, 0x70, 0x62, 0x3E, 0x3E, 0xB3, 0x0D, 0x7D, 0x82, 0x0F, 0x46, 0x07, 0x5F, 0x81, 0x63, 0x3A, + 0x26, 0xB2, 0xF7, 0x27, 0x17, 0x32, 0xF3, 0x0A, 0x67, 0x1D, 0xCE, 0x1F, 0x57, 0xD2, 0x6A, 0x40, 0x59, 0x08, 0x60, 0x43, + 0x37, 0xBB, 0x2E, 0x90, 0x4C, 0xA0, 0xA6, 0x44, 0xAB, 0x4D, 0xE8, 0xCF, 0x10, 0x9A, 0x88, 0x1F, 0x26, 0xE0, 0x26, 0x43, + 0x20, 0xCA, 0xC3, 0x11, 0xF4, 0x5E, 0x71, 0xEC, 0x78, 0x4B, 0x31, 0x61, 0xD4, 0xED, 0x76, 0x21, 0xD4, 0x6F, 0x24, 0xA3, + 0xA2, 0x19, 0x2F, 0x75, 0x7A, 0x98, 0x93, 0xF1, 0x12, 0x23, 0xB9, 0xCA, 0xC9, 0x6E, 0x55, 0xDF, 0xEA, 0xAE, 0x2E, 0x51, + 0x3E, 0x4E, 0xCC, 0x62, 0xFF, 0xB5, 0xC8, 0x9C, 0x56, 0x89, 0x50, 0x14, 0x34, 0x68, 0x79, 0x9A, 0x34, 0xBE, 0x96, 0x50, + 0xF6, 0x26, 0x40, 0x42, 0x1B, 0x6A, 0x5C, 0x51, 0xFB, 0xE8, 0x47, 0x6B, 0xC9, 0x22, 0xF7, 0x25, 0xF6, 0x5E, 0x8E, 0x10, + 0x85, 0x67, 0x61, 0x7C, 0x52, 0x72, 0x91, 0xBB, 0x0B, 0x1A, 0xC5, 0xA4, 0x1B, 0x7A, 0xD9, 0x01, 0xA5, 0x8B, 0x00, 0x50, + 0x76, 0x98, 0xA4, 0x6C, 0xF7, 0x93, 0x62, 0xDB, 0xC4, 0xEA, 0x2C, 0xBA, 0xB3, 0x8D, 0xD5, 0x54, 0x5A, 0x3B, 0x9F, 0x73, + 0x0B, 0x73, 0x12, 0xFE, 0x0D, 0xAF, 0x8A, 0x27, 0xCB, 0x9A, 0xC6, 0x4D, 0x4A, 0x6B, 0xE0, 0x6D, 0x67, 0x62, 0x2B, 0x65, + 0xAF, 0xEB, 0x34, 0x8C, 0x4A, 0xF9, 0xC3, 0x6F, 0xD8, 0xC6, 0xE1, 0xF3, 0xDB, 0xC6, 0x08, 0x5B, 0x3C, 0x54, 0xFB, 0xE2, + 0x5A, 0x89, 0xA5, 0x16, 0xFC, 0x7B, 0x9A, 0x42, 0xF7, 0xC3, 0x9A, 0x69, 0xE3, 0xA3, 0x0C, 0x6D, 0xBB, 0xC3, 0x62, 0x7D, + 0x78, 0xA8, 0x79, 0x64, 0x33, 0xCF, 0x68, 0x6C, 0x7F, 0x54, 0xA9, 0xA1, 0x2C, 0x32, 0xA0, 0x56, 0x6B, 0x42, 0x59, 0xB8, + 0xD9, 0x7B, 0x73, 0x21, 0xF5, 0xA1, 0xC7, 0x14, 0x6D, 0x8C, 0xD5, 0xCE, 0x52, 0xAF, 0x24, 0xC1, 0x89, 0x0F, 0x95, 0x59, + 0x7E, 0x2C, 0x03, 0x3C, 0x32, 0x49, 0x5B, 0x0D, 0xBD, 0x63, 0x7C, 0x86, 0x90, 0xC9, 0x24, 0xE5, 0x38, 0x3D, 0xF2, 0x64, + 0x24, 0xEB, 0x74, 0x1A, 0xAC, 0xF8, 0xD3, 0x6D, 0xC4, 0x12, 0x00, 0x05, 0x2E, 0xB9, 0x99, 0x24, 0x64, 0x3B, 0xA9, 0xD6, + 0x3F, 0x5C, 0x7C, 0x93, 0x01, 0x13, 0xDB, 0xAF, 0x5D, 0xA3, 0x10, 0xD4, 0x69, 0xC9, 0x35, 0xE4, 0x5F, 0x5F, 0xD2, 0x6D, + 0x5D, 0x5A, 0x2D, 0xF4, 0xB9, 0x38, 0x95, 0xAE, 0xD6, 0xE7, 0xAE, 0x86, 0x54, 0x0C, 0xAE, 0x51, 0x6D, 0x6B, 0x74, 0x57, + 0x06, 0x00, 0x76, 0x8F, 0x05, 0x54, 0xE1, 0x04, 0x52, 0x27, 0x6D, 0xA1, 0x34, 0x3C, 0xFD, 0x27, 0x94, 0xF5, 0x7A, 0x22, + 0x8E, 0x5F, 0x78, 0xF2, 0x7F, 0x9B, 0x89, 0x51, 0xE6, 0x9E, 0x45, 0xDD, 0x3A, 0x1B, 0x63, 0xCF, 0x0D, 0x87, 0x0E, 0x1F, + 0xF6, 0x4D, 0xA3, 0x33, 0xA3, 0xBB, 0x6D, 0xC7, 0x6E, 0xEA, 0xD1, 0x61, 0xBB, 0xDD, 0xDB, 0xCF, 0x73, 0x53, 0x7D, 0x8A, + 0x2A, 0xB8, 0xDD, 0xBF, 0x0C, 0x17, 0xEC, 0xAA, 0x24, 0x91, 0x88, 0x83, 0x52, 0x27, 0x15, 0x26, 0xDE, 0x34, 0xD0, 0x99, + 0x9C, 0xB2, 0x00, 0xDE, 0xB3, 0xD1, 0x1A, 0x3A, 0x0B, 0x4D, 0x0B, 0xF4, 0x98, 0x25, 0x07, 0xFD, 0xDE, 0x6E, 0x6E, 0xBB, + 0x49, 0x25, 0xED, 0x73, 0xFA, 0x29, 0xB7, 0xAA, 0x0C, 0x3F, 0x2F, 0xDC, 0x42, 0x16, 0xB5, 0x4A, 0xC8, 0xDB, 0xB7, 0xBB, + 0x74, 0xD4, 0x1A, 0x8D, 0xC7, 0x86, 0xF0, 0xAC, 0x5E, 0x35, 0xB6, 0xFB, 0x56, 0x7C, 0x63, 0xE9, 0x5A, 0x58, 0xD1, 0xCA, + 0xFB, 0x92, 0xC4, 0x2D, 0xB3, 0xFC, 0xFE, 0xD9, 0xB7, 0x7D, 0x5A, 0xDA, 0xFD, 0xF5, 0x01, 0x1E, 0xEE, 0x41, 0x99, 0xC9, + 0x5F, 0x3D, 0x64, 0x98, 0x9E, 0xD7, 0x64, 0xE9, 0x36, 0x4F, 0x5D, 0x24, 0x9C, 0x9B, 0xD1, 0xF7, 0xD7, 0xB2, 0xEA, 0xD8, + 0x37, 0x7F, 0x43, 0x80, 0x5C, 0xBE, 0x3E, 0xC5, 0x21, 0x30, 0x08, 0xF7, 0x9C, 0x8D, 0xB4, 0xDA, 0xCF, 0xBD, 0x5F, 0xA6, + 0xD0, 0x65, 0x1A, 0x1C, 0xA2, 0x05, 0x1D, 0xF6, 0x17, 0xD3, 0x99, 0x5F, 0xBA, 0xBC, 0x30, 0x20, 0xF2, 0x6C, 0x61, 0x53, + 0x0A, 0x0F, 0x10, 0xE7, 0x3C, 0x8F, 0x76, 0x5F, 0x12, 0x4A, 0xA9, 0xF5, 0x8C, 0x64, 0x0F, 0x63, 0x03, 0x8F, 0x68, 0x91, + 0xCF, 0x1D, 0x7E, 0xCE, 0x34, 0xC5, 0x75, 0xA7, 0x95, 0x6B, 0xC5, 0x22, 0x82, 0xA4, 0x3F, 0xC0, 0x7C, 0x81, 0xAF, 0x88, + 0x96, 0x06, 0xEA, 0x59, 0x61, 0xA8, 0xE3, 0x9A, 0xB8, 0x3E, 0xF6, 0x9C, 0x9E, 0xD3, 0xF7, 0x8C, 0x43, 0x5E, 0x99, 0x92, + 0x55, 0x8F, 0xED, 0xE4, 0x57, 0x65, 0xFF, 0x8C, 0xD0, 0xD9, 0xD4, 0x34, 0x1F, 0x3B, 0x29, 0x1B, 0xB0, 0x46, 0xEA, 0xB6, + 0x76, 0x35, 0x81, 0x4D, 0x5B, 0x3D, 0xFE, 0xF5, 0xDF, 0x45, 0x16, 0xF7, 0x2D, 0x98, 0x66, 0xEA, 0x3F, 0xF8, 0x42, 0x91, + 0x65, 0x85, 0x12, 0x2A, 0x0A, 0x35, 0x16, 0xDC, 0x1C, 0x67, 0x73, 0x7E, 0x2A, 0x49, 0x1F, 0xFE, 0x7A, 0x6C, 0x61, 0x7F, + 0xB0, 0xEF, 0x99, 0xAA, 0xDB, 0x25, 0xC2, 0xF9, 0xC3, 0x5B, 0x12, 0xEF, 0x34, 0x87, 0x84, 0xD2, 0x29, 0x99, 0x53, 0x20, + 0xA7, 0x28, 0x1F, 0x50, 0x35, 0xB1, 0x1A, 0xF7, 0x3C, 0x47, 0xBB, 0x43, 0x03, 0x2F, 0x19, 0x5F, 0x22, 0x6D, 0xBE, 0xA0, + 0x1F, 0x41, 0xC3, 0x3E, 0xA5, 0x97, 0xE9, 0x97, 0x79, 0x4A, 0xEA, 0x3E, 0xE9, 0xE6, 0xA6, 0xB0, 0x89, 0x40, 0x1C, 0x6F, + 0xD3, 0x37, 0x83, 0xFC, 0x57, 0x69, 0x6E, 0x1E, 0x9A, 0xE7, 0xB8, 0x41, 0x2F, 0xF1, 0xC7, 0x72, 0x8D, 0x6C, 0x93, 0x64, + 0x87, 0x55, 0xAB, 0x27, 0xEB, 0x61, 0xAC, 0x27, 0x8D, 0x5F, 0xCA, 0x4C, 0x83, 0x2B, 0xCB, 0xFD, 0xD4, 0x52, 0x5C, 0x35, + 0x78, 0xC2, 0x7A, 0xB8, 0x8C, 0x1D, 0x44, 0x19, 0xE1, 0xBB, 0x83, 0x8D, 0xE0, 0xD3, 0xB4, 0xB5, 0xFD, 0x13, 0x93, 0xF2, + 0xCA, 0xC0, 0x74, 0xFA, 0x10, 0x71, 0x45, 0x92, 0xC4, 0x2E, 0xE1, 0x5D, 0xBF, 0x1E, 0x7B, 0xB8, 0xA6, 0xE0, 0x35, 0xA9, + 0x03, 0xCF, 0x28, 0x81, 0x41, 0x30, 0x3E, 0x00, 0x25, 0x6C, 0xB9, 0xF3, 0x4A, 0xE2, 0x89, 0x05, 0x95, 0x4F, 0x2A, 0x8C, + 0x11, 0x82, 0x26, 0x3C, 0x5E, 0x68, 0x62, 0xF8, 0x7D, 0xB0, 0xBB, 0x39, 0x3A, 0x76, 0xB8, 0x73, 0x71, 0x5C, 0x2B, 0x06, + 0xFF, 0x72, 0x5F, 0xC3, 0x76, 0xA4, 0xC0, 0x6A, 0xB1, 0x39, 0x12, 0xF9, 0x8A, 0x65, 0x27, 0x76, 0x8D, 0x8A, 0x52, 0xA1, + 0x6A, 0xAE, 0x13, 0xF6, 0xFA, 0x26, 0xD5, 0x80, 0xF7, 0xF2, 0xFD, 0xE5, 0x53, 0xF0, 0xF0, 0xEB, 0xFA, 0xA2, 0xC9, 0x51, + 0xC5, 0xE1, 0xB1, 0x62, 0xA4, 0x5D, 0xE5, 0x67, 0xF3, 0x7F, 0x3C, 0x63, 0x2E, 0xEA, 0x39, 0xC3, 0xBA, 0x14, 0xA1, 0x85, + 0x9C, 0x09, 0x74, 0xCA, 0x87, 0x68, 0xF1, 0x8B, 0x51, 0x5D, 0xEE, 0x9E, 0x7A, 0x34, 0x8F, 0xA7, 0x55, 0x64, 0x66, 0xB4, + 0x84, 0x36, 0x51, 0x0D, 0xF6, 0xEA, 0x94, 0xEF, 0x9B, 0x78, 0xD7, 0x79, 0x0C, 0x8E, 0x2F, 0x45, 0x24, 0x86, 0x29, 0xA1, + 0x25, 0x55, 0xD1, 0x40, 0xB9, 0x94, 0x0F, 0xDA, 0xE7, 0x40, 0xC6, 0xA6, 0xFF, 0x0B, 0xCD, 0x4C, 0x36, 0x16, 0x9F, 0xC5, + 0x3C, 0xBC, 0x1E, 0xD7, 0x7A, 0x87, 0xD4, 0x1D, 0x6E, 0x83, 0x4E, 0x29, 0x53, 0xE2, 0x0E, 0x60, 0x85, 0x58, 0x5E, 0x7C, + 0x63, 0x71, 0xE6, 0x0F, 0x6F, 0xDD, 0x4F, 0xDD, 0xC1, 0x8F, 0x97, 0x4F, 0x3B, 0x1E, 0x57, 0xD2, 0xFD, 0xC5, 0x47, 0x6F, + 0x7B, 0x7E, 0x69, 0xE1, 0xF2, 0xBB, 0x0F, 0x61, 0x6D, 0x7D, 0xE0, 0xC8, 0xF3, 0xA0, 0x5E, 0xD9, 0x1A, 0xD0, 0xE0, 0x9F, + 0xB6, 0x8D, 0x64, 0xF9, 0x77, 0x0A, 0x78, 0x2E, 0xF9, 0x31, 0x90, 0x81, 0xF5, 0xE9, 0x90, 0xFD, 0x27, 0xD3, 0x6C, 0x2B, + 0xEA, 0xE3, 0x15, 0x62, 0x4D, 0xFD, 0x98, 0x27, 0xD8, 0x82, 0x79, 0x93, 0xB7, 0x14, 0x30, 0xED, 0x31, 0xCE, 0xCE, 0x51, + 0xB2, 0x1D, 0x71, 0xA3, 0xC8, 0xEF, 0x2E, 0x91, 0x44, 0xA5, 0x6E, 0x4D, 0xE2, 0xA3, 0x29, 0x86, 0x27, 0x17, 0x12, 0x92, + 0x00, 0xFD, 0x11, 0x02, 0x4E, 0x59, 0xD5, 0x35, 0x5D, 0xAD, 0x10, 0x20, 0x4E, 0x86, 0x7F, 0x86, 0x08, 0xE2, 0xD5, 0x32, + 0x76, 0x21, 0x17, 0x24, 0xEC, 0x5E, 0x78, 0x72, 0xC5, 0xC9, 0x98, 0xC9, 0xA8, 0xE8, 0x99, 0x4B, 0x7B, 0xC9, 0x64, 0xB4, + 0x8E, 0xDD, 0x73, 0x64, 0xC6, 0xC6, 0x59, 0x73, 0x77, 0x19, 0xA6, 0x6B, 0x4F, 0x8E, 0x16, 0xD3, 0xF9, 0x02, 0x7F, 0xF7, + 0x87, 0xA3, 0x02, 0x50, 0x76, 0xFB, 0x1A, 0x4D, 0xCE, 0x93, 0xF8, 0x28, 0x28, 0xB7, 0xA3, 0x35, 0x70, 0xF5, 0xCF, 0xC7, + 0x41, 0x87, 0xBF, 0xF5, 0x0B, 0x7B, 0x94, 0xC7, 0x90, 0xCB, 0x2B, 0x29, 0x35, 0xF8, 0x9A, 0x98, 0xFC, 0xE0, 0x6B, 0x1B, + 0xEF, 0x13, 0x1B, 0xF4, 0xEF, 0xAA, 0x6B, 0x37, 0x04, 0x5B, 0x08, 0xA6, 0x73, 0xEC, 0xCA, 0xE8, 0x01, 0x86, 0x56, 0x9B, + 0xDE, 0x6E, 0x1D, 0x07, 0xF9, 0x6F, 0x7B, 0xBB, 0xC1, 0xE6, 0x75, 0x70, 0x51, 0x39, 0xDC, 0x82, 0x5C, 0x53, 0x72, 0x6A, + 0x4E, 0xCC, 0x4D, 0x24, 0x4E, 0xE8, 0x62, 0x4E, 0x64, 0x1C, 0xA2, 0x46, 0xD7, 0x67, 0x02, 0x5D, 0xEC, 0x69, 0x51, 0xFB, + 0xCC, 0xD2, 0x7B, 0xCF, 0x92, 0x84, 0xDD, 0x9B, 0x13, 0x58, 0x49, 0xE9, 0x30, 0x31, 0xF5, 0x31, 0x53, 0x8C, 0x6B, 0xAA, + 0xF7, 0x70, 0xEE, 0xB2, 0x97, 0x22, 0xB5, 0x73, 0x26, 0xDF, 0x83, 0x01, 0x5D, 0x18, 0xF2, 0x80, 0x6A, 0xAD, 0xBC, 0x04, + 0xB4, 0xDA, 0x04, 0xC4, 0xDB, 0x65, 0x90, 0x24, 0xF4, 0x57, 0x3D, 0x8D, 0x1D, 0xD3, 0xD2, 0xCA, 0xB7, 0x65, 0x29, 0x8C, + 0x55, 0x93, 0x39, 0xD4, 0xF5, 0x51, 0x33, 0xE1, 0x1F, 0x46, 0x9D, 0x76, 0xED, 0xB2, 0x22, 0x99, 0x94, 0x27, 0x8D, 0xC7, + 0xF2, 0xB0, 0xEA, 0xD7, 0xA3, 0x61, 0x7A, 0xF5, 0x94, 0x91, 0x77, 0x85, 0x31, 0xC2, 0x11, 0x12, 0x20, 0x90, 0x73, 0x9E, + 0x15, 0x52, 0x60, 0xB6, 0xD7, 0x45, 0x4F, 0x5E, 0x60, 0x07, 0xE5, 0x16, 0x3D, 0x55, 0x8A, 0x56, 0x3B, 0x3D, 0xBE, 0xD7, + 0x25, 0xFA, 0x83, 0x76, 0x66, 0xD5, 0x7C, 0xF5, 0xDA, 0x58, 0xA5, 0xCE, 0xF6, 0x8D, 0xBC, 0x95, 0x11, 0x6B, 0x28, 0x1D, + 0x4A, 0xDB, 0xE4, 0x0D, 0x53, 0xFD, 0x34, 0x9F, 0xA1, 0xE7, 0x2D, 0x6B, 0x29, 0xAC, 0x43, 0xFB, 0x8E, 0xCD, 0xEC, 0x73, + 0xA9, 0x34, 0xA1, 0x75, 0xE4, 0x49, 0xC6, 0x8D, 0x3E, 0xB5, 0x91, 0x83, 0x6A, 0x2A, 0x1D, 0x64, 0xC7, 0xC3, 0x86, 0x2F, + 0x90, 0x38, 0x49, 0x6D, 0x1C, 0x14, 0xFE, 0x27, 0x07, 0x9B, 0x42, 0x3C, 0xFD, 0x7E, 0x83, 0x98, 0xD0, 0xDE, 0x58, 0xC8, + 0x55, 0xB3, 0x46, 0x5B, 0xE4, 0xD5, 0xD7, 0x48, 0x09, 0xC8, 0x8F, 0x60, 0x4C, 0x38, 0x60, 0x0D, 0xBD, 0x14, 0xF8, 0x70, + 0xEB, 0x29, 0x87, 0xDF, 0xFB, 0xB9, 0x65, 0x22, 0x33, 0xDE, 0xE3, 0x4A, 0x7E, 0xBF, 0x2E, 0xC7, 0x87, 0x36, 0x41, 0xE8, + 0x95, 0x8D, 0xB5, 0xDA, 0x1C, 0x29, 0x3D, 0x71, 0x39, 0x6E, 0x40, 0x36, 0x8C, 0x5D, 0x3E, 0x63, 0x72, 0x08, 0xE2, 0x9A, + 0x13, 0x61, 0x87, 0x8D, 0xF6, 0xFC, 0x6F, 0xF7, 0x05, 0xCE, 0x50, 0xD7, 0x17, 0xEF, 0xAF, 0xD6, 0xAD, 0x42, 0x0A, 0x5B, + 0xB3, 0x36, 0x80, 0x89, 0x50, 0x64, 0x5F, 0x0C, 0x87, 0x0B, 0x93, 0x84, 0x5E, 0x80, 0xD9, 0x02, 0xF5, 0x29, 0x9F, 0xA4, + 0x20, 0xBD, 0x24, 0x46, 0x63, 0x80, 0xC8, 0x8D, 0x47, 0xAE, 0x44, 0xF4, 0x0D, 0x3A, 0xDA, 0xB4, 0x1F, 0xB1, 0x5C, 0xFE, + 0xEA, 0x9E, 0xFC, 0x4F, 0x75, 0x5E, 0x01, 0x46, 0xD2, 0x8F, 0x59, 0xA5, 0xC6, 0xB0, 0x3A, 0x62, 0xDE, 0xBE, 0xAD, 0x73, + 0x6A, 0x32, 0x45, 0x73, 0xB2, 0xE3, 0xE6, 0xB5, 0x9F, 0xD8, 0xC3, 0x5F, 0xB9, 0x72, 0x58, 0xC4, 0xE3, 0x0B, 0xBE, 0x42, + 0xF3, 0xA7, 0x83, 0xEC, 0xE3, 0x47, 0xC6, 0xDD, 0xB9, 0xD7, 0x02, 0x4D, 0x30, 0x32, 0xB0, 0x45, 0x23, 0x88, 0xDE, 0x0F, + 0xA1, 0x65, 0x8B, 0x50, 0xBA, 0xD6, 0x18, 0xF7, 0x27, 0x8A, 0x62, 0xB6, 0x1E, 0xAB, 0xED, 0x64, 0xE2, 0x07, 0x6A, 0xD4, + 0xA0, 0xC9, 0xB1, 0xD5, 0x9E, 0x53, 0xD8, 0xE7, 0xCF, 0xF9, 0x5C, 0xD1, 0xE7, 0x87, 0xCB, 0x8A, 0x38, 0x94, 0xB6, 0x6A, + 0xE3, 0x59, 0xE2, 0x4E, 0x16, 0x25, 0xD2, 0xB5, 0x5F, 0x0A, 0xEC, 0x2A, 0xB9, 0xEB, 0x31, 0x7A, 0xFA, 0x6C, 0xFF, 0xFA, + 0x2A, 0xEE, 0x24, 0x10, 0x21, 0x44, 0xE5, 0xB8, 0x0E, 0x04, 0x5E, 0x08, 0x8E, 0xF8, 0x9B, 0x1D, 0x79, 0x31, 0x01, 0x56, + 0xC9, 0x32, 0xBF, 0xDE, 0x54, 0x67, 0x33, 0xE6, 0x5C, 0x96, 0x33, 0x4F, 0xDA, 0xDB, 0x09, 0x36, 0x22, 0x0F, 0xA5, 0xF8, + 0xF8, 0x1A, 0x22, 0x0A, 0x48, 0x03, 0x02, 0x2C, 0x1A, 0x6E, 0x32, 0x76, 0xDF, 0xC7, 0xEC, 0xD4, 0x38, 0x93, 0x2C, 0x98, + 0x89, 0xD9, 0xB7, 0xD8, 0x04, 0xAC, 0xDB, 0xFC, 0x3D, 0x1F, 0x5A, 0x54, 0x8F, 0x9C, 0xD3, 0x0E, 0x63, 0x84, 0xDC, 0x06, + 0x9C, 0x6D, 0x57, 0x8B, 0xEA, 0xCF, 0xAD, 0xD1, 0xFE, 0x2C, 0xF6, 0xBB, 0x43, 0x85, 0x0B, 0x11, 0x45, 0x29, 0x63, 0xD9, + 0x66, 0x2F, 0x7C, 0xDD, 0x2F, 0x3C, 0xFB, 0xD2, 0x63, 0xE0, 0x95, 0xC3, 0xEE, 0x38, 0xAB, 0x24, 0x3E, 0x69, 0xF6, 0xA0, + 0x71, 0x90, 0x88, 0xCF, 0x9C, 0xED, 0xC2, 0xA5, 0x01, 0x2E, 0x64, 0x34, 0x3F, 0xCA, 0xE4, 0xB6, 0x31, 0xD1, 0x15, 0xE3, + 0xA4, 0x29, 0x05, 0xA6, 0x6D, 0xB9, 0x2E, 0x43, 0x4C, 0xEF, 0xAF, 0x27, 0x71, 0xF0, 0xA6, 0xFF, 0x74, 0x6F, 0x35, 0xF5, + 0xC2, 0x9E, 0xDD, 0x2C, 0xF6, 0xEC, 0x8C, 0x96, 0xCF, 0xDE, 0xED, 0x22, 0xA0, 0xC0, 0xBA, 0x71, 0xBD, 0x92, 0xF7, 0x5F, + 0xC1, 0x50, 0xEA, 0x28, 0x1A, 0x57, 0xE0, 0x43, 0x0A, 0x1A, 0xEC, 0x3E, 0xDA, 0xF6, 0x4D, 0x80, 0x3F, 0x5E, 0x8C, 0x07, + 0x51, 0x34, 0xD6, 0xA3, 0x83, 0xD6, 0x95, 0xB6, 0xCE, 0xBF, 0x54, 0xF0, 0xD2, 0xFB, 0xAB, 0x44, 0x13, 0xD5, 0x6D, 0xD5, + 0x26, 0x96, 0xD7, 0xD7, 0x21, 0x76, 0xE8, 0x19, 0x4B, 0x1A, 0xE3, 0x39, 0xB1, 0x88, 0x3B, 0xC7, 0xD0, 0x89, 0x97, 0xBD, + 0x99, 0xB9, 0xD6, 0x35, 0xC7, 0xF3, 0x5A, 0x4C, 0x18, 0x3A, 0xC3, 0x1C, 0x77, 0x58, 0xDC, 0xDF, 0xD2, 0x5D, 0x1C, 0xE3, + 0x98, 0x56, 0xB6, 0x2C, 0xD8, 0x15, 0x34, 0xA4, 0xAE, 0x52, 0x08, 0x7E, 0x3C, 0xB7, 0x6F, 0xAD, 0x15, 0x18, 0x1A, 0xA3, + 0x07, 0x7C, 0xA2, 0xF2, 0x34, 0xAE, 0xB7, 0x63, 0x15, 0x36, 0xAB, 0xC2, 0x4A, 0xAB, 0x78, 0x7D, 0xEB, 0x76, 0x7C, 0x3B, + 0x25, 0x67, 0x9C, 0xEE, 0x52, 0x8F, 0x24, 0xE9, 0x6C, 0x5F, 0xE8, 0x44, 0xF7, 0x8A, 0x95, 0xEF, 0x2D, 0xC7, 0x98, 0x64, + 0xD0, 0x59, 0x9E, 0x44, 0x0D, 0x46, 0x21, 0x8F, 0x07, 0x11, 0xC0, 0x32, 0xD5, 0xC5, 0xB9, 0xCB, 0xD9, 0x6B, 0x45, 0xF4, + 0xD9, 0x1A, 0x47, 0x9E, 0xE1, 0xFC, 0x33, 0xAA, 0xA8, 0x14, 0x5F, 0x22, 0x5A, 0x5C, 0x97, 0x7D, 0x9D, 0x9C, 0x38, 0xD9, + 0x12, 0x25, 0x8B, 0x86, 0x5A, 0x1D, 0x5F, 0xEE, 0xAE, 0xED, 0x0A, 0x92, 0xCD, 0x82, 0x70, 0x6B, 0x6D, 0x7F, 0xEB, 0x96, + 0x5B, 0xEE, 0x10, 0x27, 0x3C, 0xEE, 0xFF, 0x16, 0x43, 0x33, 0xC7, 0x4C, 0x37, 0x81, 0xE1, 0x9E, 0x14, 0x88, 0x0D, 0x98, + 0x97, 0xB2, 0xF6, 0x3E, 0x3B, 0x80, 0x05, 0x45, 0xB4, 0xE2, 0x11, 0xE9, 0x29, 0x8E, 0x93, 0xFF, 0x67, 0xEC, 0x62, 0xB7, + 0x9B, 0x33, 0xC2, 0xF0, 0xE6, 0xF7, 0x28, 0xBE, 0xD3, 0x7F, 0x43, 0x29, 0xB7, 0xBF, 0x60, 0x46, 0x4C, 0xC7, 0x47, 0xCB, + 0x25, 0xE4, 0x17, 0xD6, 0x50, 0xAA, 0xBF, 0x67, 0xB6, 0x5A, 0xB9, 0x10, 0x65, 0xA8, 0x07, 0x89, 0xB6, 0x66, 0x2F, 0xAE, + 0xDA, 0x0B, 0xD5, 0xA1, 0xB2, 0x0B, 0x63, 0xFE, 0xC0, 0x15, 0x61, 0x14, 0xC1, 0x67, 0x57, 0x93, 0xA4, 0xC5, 0xD7, 0xEF, + 0xB9, 0x78, 0x38, 0xF1, 0x13, 0x30, 0x06, 0x53, 0xE4, 0x63, 0xDD, 0x54, 0xFD, 0x54, 0x9C, 0x53, 0x7D, 0x88, 0xCD, 0xAE, + 0x12, 0x0A, 0x0A, 0xB5, 0x4E, 0xA5, 0xED, 0x10, 0x0E, 0xF9, 0x90, 0xED, 0x2D, 0xB2, 0xC5, 0xBE, 0x13, 0x31, 0xAF, 0x79, + 0x9F, 0xA9, 0xE3, 0x96, 0x23, 0xC8, 0xFB, 0x0B, 0x34, 0x56, 0xF3, 0xB6, 0xB4, 0x47, 0xD0, 0xEF, 0x9E, 0x47, 0x4B, 0x19, + 0xE6, 0x86, 0xCA, 0x79, 0x62, 0x06, 0x44, 0xBF, 0x93, 0x56, 0xF3, 0x2B, 0x20, 0x87, 0x5C, 0x8F, 0x2D, 0x5C, 0xB8, 0x2E, + 0x62, 0x03, 0x4A, 0xD8, 0x46, 0xEE, 0x4A, 0xFD, 0x30, 0x41, 0x6F, 0xB2, 0x8F, 0x42, 0x94, 0x59, 0xBE, 0xEC, 0xE9, 0x8A, + 0x13, 0xC2, 0x82, 0xF6, 0xFA, 0x64, 0x3A, 0x68, 0x2B, 0x85, 0x43, 0xBF, 0x36, 0x7D, 0x9B, 0x5B, 0x4C, 0x1A, 0x21, 0x1F, + 0x5E, 0x41, 0x6A, 0xAD, 0x0D, 0x5B, 0x95, 0xEB, 0x33, 0xA2, 0xD3, 0x5F, 0x2E, 0xC9, 0xDB, 0xEC, 0x7C, 0xAE, 0xB7, 0xB8, + 0x5C, 0x65, 0xFD, 0x93, 0xE1, 0xDC, 0xC3, 0xA7, 0xA3, 0x70, 0xA2, 0xC7, 0xD7, 0x7D, 0xA4, 0x5F, 0x23, 0x63, 0xD1, 0x69, + 0x56, 0xED, 0x5E, 0xAF, 0x66, 0x91, 0x04, 0xD6, 0x25, 0x5C, 0xB4, 0xBD, 0x9C, 0xD0, 0x61, 0xD9, 0xBA, 0xAC, 0x24, 0xD0, + 0xD4, 0xBE, 0xEC, 0x1D, 0x53, 0xE2, 0xEF, 0x17, 0xFB, 0x22, 0xBB, 0xBF, 0x5E, 0xF7, 0x21, 0xD0, 0xC1, 0x6C, 0x32, 0xC7, + 0xFD, 0xFA, 0xE4, 0x81, 0x9B, 0xD6, 0x1F, 0x81, 0xDF, 0x97, 0x2D, 0xBB, 0x60, 0x07, 0xB6, 0x19, 0x9F, 0x25, 0x01, 0x56, + 0x1A, 0x5D, 0xBC, 0x48, 0xDC, 0xB6, 0xBC, 0xB7, 0x8C, 0x58, 0xCC, 0xC7, 0x5D, 0x5A, 0x2F, 0xC6, 0xA0, 0xBF, 0x02, 0x34, + 0x9C, 0x1B, 0xA7, 0x67, 0x9B, 0x6F, 0x59, 0x78, 0xD2, 0x7D, 0xAD, 0xBF, 0xD3, 0xD5, 0x7D, 0x72, 0x40, 0xDB, 0x03, 0xDB, + 0x84, 0xED, 0x5D, 0x07, 0x43, 0x54, 0x7C, 0xFA, 0x44, 0x89, 0x9C, 0x3E, 0xB5, 0x17, 0xF6, 0x73, 0x3F, 0xB6, 0x34, 0x2C, + 0xFD, 0x9A, 0x76, 0xF3, 0x2B, 0x6B, 0x65, 0xF9, 0xE1, 0x88, 0x5C, 0xBB, 0x49, 0xD8, 0xC9, 0xD8, 0x5E, 0xEB, 0x5E, 0xED, + 0xCD, 0xBA, 0x03, 0xED, 0x47, 0xF8, 0x88, 0x39, 0xEC, 0x07, 0xED, 0xAE, 0x5F, 0xE1, 0x2D, 0x64, 0xAB, 0x69, 0x6F, 0xD2, + 0x84, 0x64, 0x6D, 0xBF, 0x64, 0x59, 0xDF, 0xFD, 0xF3, 0xF6, 0x2F, 0xD8, 0x28, 0x35, 0xD8, 0x77, 0xE0, 0x13, 0x60, 0xC2, + 0x85, 0x98, 0xA6, 0x1D, 0xF2, 0xBD, 0x0E, 0xC4, 0xBA, 0x90, 0x90, 0x66, 0x1B, 0x48, 0xDA, 0x98, 0x4C, 0x6D, 0x80, 0x43, + 0x9E, 0xBC, 0x24, 0xB9, 0x45, 0x8F, 0xB0, 0xBC, 0xCC, 0x68, 0x4D, 0x5B, 0x63, 0x71, 0xC9, 0x56, 0x9E, 0xDE, 0x90, 0x3B, + 0xBB, 0xDD, 0x26, 0x23, 0xBF, 0x42, 0x25, 0x81, 0x87, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, 0xF3, 0x34, 0xAF, 0xBA, 0xEF, + 0xA3, 0xD5, 0x11, 0x53, 0x38, 0x0F, 0xE8, 0x20, 0xE9, 0xE5, 0x09, 0xF6, 0x76, 0xF5, 0x0C, 0x64, 0x22, 0x5F, 0x66, 0x1D, + 0xA0, 0xE2, 0xA6, 0xD6, 0x33, 0x84, 0x94, 0xE9, 0x29, 0x4D, 0xD5, 0x3B, 0xB2, 0x60, 0x2F, 0x08, 0xA8, 0x33, 0x83, 0x55, + 0x3B, 0x26, 0xD6, 0x89, 0xBE, 0x0B, 0x32, 0xF3, 0x81, 0xDE, 0x88, 0xC2, 0xF5, 0x58, 0xE7, 0x32, 0x70, 0x3C, 0x21, 0x00, + 0x06, 0x4A, 0x63, 0xB2, 0x92, 0xA4, 0x41, 0xA7, 0xFF, 0x06, 0x8E, 0x4C, 0x46, 0x26, 0x58, 0x6C, 0x01, 0x1E, 0x08, 0xC1, + 0xA8, 0x2D, 0xB0, 0xD0, 0xC4, 0x54, 0x58, 0x65, 0x2B, 0x98, 0x97, 0xE1, 0xEC, 0xA4, 0x98, 0x5B, 0xF5, 0x06, 0x97, 0x1E, + 0xC3, 0x06, 0xC2, 0xEC, 0xF0, 0x6B, 0x64, 0xD5, 0xCD, 0x25, 0xCF, 0xBD, 0x47, 0xEA, 0xF5, 0x99, 0x54, 0x0A, 0xF3, 0xF0, + 0x90, 0x87, 0xFB, 0xF3, 0x0E, 0xC2, 0x7A, 0x28, 0x9D, 0xCB, 0xB5, 0x5E, 0xC5, 0x2A, 0x26, 0x4E, 0xD5, 0xDE, 0x41, 0xF0, + 0xE0, 0x44, 0x1B, 0xEC, 0xE6, 0x66, 0x52, 0x90, 0x4F, 0xAB, 0x36, 0xA3, 0xB2, 0xB8, 0x41, 0xF1, 0x54, 0xB1, 0xDA, 0x9E, + 0x3D, 0x85, 0xBF, 0xAD, 0x86, 0xD6, 0xEC, 0x43, 0x0A, 0xD6, 0x75, 0x58, 0x99, 0x46, 0xB5, 0x31, 0x14, 0x8D, 0x7F, 0xC9, + 0xC1, 0x44, 0xA4, 0xA3, 0x32, 0xDA, 0x43, 0xCC, 0x44, 0x1D, 0xDA, 0x48, 0x9D, 0x7D, 0x30, 0x79, 0x58, 0x01, 0x82, 0x0E, + 0x5E, 0xCC, 0x42, 0x59, 0x2F, 0x63, 0xF4, 0x84, 0x73, 0x20, 0x4A, 0x44, 0x32, 0x4E, 0xBA, 0x3D, 0xE0, 0x60, 0xAF, 0xCD, + 0xCA, 0x9E, 0x18, 0x6E, 0xE5, 0x27, 0x31, 0x69, 0xCB, 0xD7, 0x40, 0xBE, 0xEA, 0x13, 0xDB, 0x1E, 0xAF, 0x43, 0x36, 0x2E, + 0x84, 0x4C, 0x4C, 0x51, 0xF8, 0x89, 0x91, 0x83, 0x78, 0x69, 0x91, 0xB1, 0x81, 0xEF, 0xFA, 0xB9, 0xEC, 0x33, 0x6A, 0xA6, + 0x03, 0xF6, 0x52, 0x17, 0xD1, 0xEF, 0x20, 0xE3, 0x19, 0x6E, 0xBB, 0xB8, 0x37, 0xBB, 0x22, 0x7C, 0x09, 0x0B, 0x30, 0x31, + 0x86, 0xCC, 0x3B, 0xAD, 0xA6, 0xF0, 0x5E, 0xB2, 0xCF, 0x3B, 0x46, 0x9A, 0x64, 0xCD, 0x21, 0xC7, 0x0B, 0xEF, 0xD4, 0x91, + 0xDA, 0x16, 0xE6, 0xE7, 0x0A, 0x9E, 0xE0, 0x35, 0xFA, 0x6C, 0x59, 0x4A, 0x7C, 0xDE, 0x9B, 0xC5, 0x24, 0xE5, 0xFC, 0x94, + 0x36, 0x3B, 0x1C, 0xB4, 0x05, 0x14, 0xAA, 0xCD, 0xF2, 0x84, 0x93, 0xD4, 0x25, 0xE4, 0x86, 0x2F, 0x90, 0x33, 0xE4, 0x1E, + 0x73, 0x18, 0xDD, 0xB4, 0x3B, 0xDE, 0x54, 0x45, 0x81, 0x16, 0xA5, 0x84, 0x45, 0x3B, 0x75, 0xA5, 0xD1, 0x90, 0xEB, 0xDC, + 0x7F, 0xF0, 0x5C, 0x16, 0x90, 0x49, 0xC1, 0x2E, 0x12, 0xBF, 0xA0, 0x09, 0xE3, 0xEC, 0xC8, 0xF4, 0x73, 0x17, 0x5D, 0xA6, + 0x2E, 0xC9, 0x4F, 0xBC, 0xCF, 0xC7, 0x36, 0x28, 0x5B, 0xAC, 0x85, 0x33, 0x91, 0x09, 0xC8, 0x2B, 0xDC, 0x16, 0x94, 0x8F, + 0x1B, 0x7D, 0x35, 0xF8, 0x25, 0x1B, 0x48, 0x4C, 0x5B, 0xD8, 0x16, 0xFA, 0x98, 0x58, 0xBA, 0xCA, 0x66, 0x30, 0xAD, 0x6E, + 0xEE, 0xB8, 0x74, 0x6D, 0xFC, 0x34, 0xBB, 0xE6, 0x0A, 0xB6, 0xA9, 0xA0, 0x35, 0x90, 0xD9, 0x3A, 0x48, 0xD3, 0x0E, 0x39, + 0xB7, 0xDD, 0xFE, 0x5A, 0x22, 0x0E, 0x46, 0x2E, 0x51, 0x2D, 0xD6, 0x17, 0xBF, 0x01, 0x88, 0xC5, 0x85, 0xD1, 0xCE, 0xB9, + 0x3B, 0x06, 0xDE, 0xBE, 0x3F, 0x9D, 0xF2, 0x10, 0xCE, 0x1F, 0xD6, 0xE0, 0x9A, 0xD2, 0xFF, 0x5B, 0xAA, 0x14, 0x46, 0x49, + 0xCA, 0x0C, 0xFC, 0x6D, 0xEE, 0x4F, 0xC4, 0xAA, 0x38, 0x6E, 0xAD, 0xBF, 0x5C, 0x0F, 0x5A, 0xA2, 0x7A, 0x5D, 0x9D, 0x07, + 0xE8, 0x4E, 0x4E, 0x8E, 0x8F, 0xF9, 0x5E, 0x46, 0x3B, 0x89, 0xED, 0x46, 0x1C, 0xE1, 0x0E, 0x0A, 0x8C, 0x9A, 0xE0, 0x51, + 0x48, 0x8C, 0xF3, 0x25, 0x03, 0x72, 0xBB, 0x65, 0x02, 0x20, 0xE8, 0xC1, 0x6B, 0x60, 0x2B, 0x44, 0x9F, 0x50, 0xF8, 0x34, + 0xFB, 0x8B, 0x9B, 0xF4, 0xA8, 0x0D, 0x49, 0x11, 0x0C, 0xCD, 0x8B, 0xB4, 0xA0, 0x4D, 0xD8, 0x60, 0x92, 0x02, 0x52, 0xFC, + 0x5D, 0xF2, 0x01, 0xC8, 0x2C, 0x80, 0xC7, 0x0E, 0x3C, 0x32, 0x71, 0x04, 0x3A, 0xC8, 0x19, 0x34, 0xED, 0xE4, 0xC8, 0x9C, + 0x56, 0x89, 0xFC, 0x9D, 0xF7, 0x6E, 0xE6, 0x97, 0x01, 0xDD, 0x7D, 0xA5, 0x67, 0x0A, 0xFC, 0xF6, 0x4F, 0xE9, 0x54, 0xE4, + 0x47, 0xED, 0xF0, 0x05, 0xA4, 0xC4, 0x2B, 0xD7, 0x77, 0x09, 0x8E, 0x9B, 0xC6, 0x7D, 0x0A, 0x85, 0x3F, 0x97, 0x17, 0xD7, + 0xB7, 0x87, 0xFE, 0xA4, 0xE3, 0xA1, 0x3E, 0xF7, 0xC3, 0xD6, 0x7C, 0x04, 0xAF, 0x61, 0xD9, 0xF9, 0x34, 0x05, 0xDA, 0x3C, + 0x77, 0xA7, 0xE6, 0xD0, 0x2F, 0x57, 0xA4, 0x16, 0xB7, 0x79, 0x86, 0x89, 0x16, 0x81, 0xD4, 0x18, 0xF4, 0xA6, 0x4F, 0x82, + 0xB1, 0x8D, 0xC4, 0x13, 0x45, 0xED, 0x5D, 0x23, 0x65, 0x9B, 0x23, 0x3D, 0xFC, 0x30, 0x24, 0xD8, 0x48, 0x41, 0x8D, 0x16, + 0xB6, 0x9B, 0xAB, 0x1A, 0x68, 0x26, 0xF9, 0x00, 0x61, 0xEF, 0xC0, 0xCB, 0xEC, 0x7A, 0x5B, 0x4C, 0xE9, 0xA9, 0x5C, 0x37, + 0x83, 0x0A, 0x6A, 0x0B, 0xBF, 0x26, 0x9E, 0x82, 0xEB, 0x8E, 0xF3, 0x2E, 0x16, 0x47, 0x79, 0xDF, 0x2F, 0x5C, 0x13, 0x3C, + 0x5C, 0x12, 0x5A, 0x36, 0x7C, 0x19, 0xC4, 0x53, 0xD2, 0x6B, 0xE7, 0x8B, 0xC8, 0x8D, 0x18, 0xAD, 0x1C, 0x86, 0xB1, 0x95, + 0xCF, 0x8E, 0xE6, 0x6B, 0x5E, 0x9C, 0x2B, 0x7B, 0x9F, 0x3F, 0x93, 0xDD, 0x96, 0x90, 0xC1, 0x3C, 0x0D, 0x8F, 0xFA, 0x3F, + 0x97, 0x62, 0x31, 0x79, 0x57, 0x90, 0xDC, 0x82, 0x8D, 0xF2, 0xB4, 0x40, 0x2C, 0xC1, 0x8C, 0x14, 0x78, 0x90, 0xFC, 0x6F, + 0x85, 0x4A, 0x18, 0xF4, 0xCA, 0x1A, 0xE3, 0x2A, 0x9D, 0xEB, 0x83, 0x25, 0x05, 0x5E, 0xF8, 0xBB, 0xCF, 0x9A, 0xA7, 0xDC, + 0x15, 0x6D, 0x31, 0x17, 0x93, 0x26, 0x05, 0x12, 0xD0, 0x9E, 0x9C, 0x17, 0xAE, 0xE8, 0xD5, 0x93, 0x0C, 0x36, 0x66, 0xB3, + 0xE3, 0x79, 0x2E, 0xCD, 0x3F, 0x82, 0xDC, 0x3D, 0x15, 0xB9, 0xAE, 0xD3, 0x16, 0xB9, 0x2F, 0xE2, 0x1D, 0x54, 0xF5, 0xA6, + 0x6A, 0x5F, 0x91, 0x15, 0x21, 0x77, 0xFD, 0xB9, 0xB5, 0x9D, 0xC5, 0xAC, 0x61, 0x95, 0xA2, 0xDF, 0x88, 0x5E, 0xDD, 0x2D, + 0xB6, 0xDB, 0x65, 0xD6, 0xC6, 0x18, 0xDA, 0x8C, 0x3B, 0x0A, 0x64, 0xE2, 0x76, 0x36, 0xD2, 0x93, 0xEB, 0x94, 0x90, 0xB5, + 0xF4, 0x08, 0x6C, 0xB4, 0xD4, 0x49, 0x6C, 0x08, 0x1E, 0xC6, 0x8A, 0x62, 0x89, 0xD5, 0xB4, 0xEE, 0xD7, 0xFC, 0xF6, 0xB5, + 0x46, 0x0C, 0xC8, 0x97, 0xF3, 0x55, 0xEE, 0x0F, 0x25, 0x93, 0xD0, 0x99, 0x9C, 0x26, 0xAD, 0x84, 0x72, 0x2C, 0x71, 0xCE, + 0xFD, 0xE6, 0x41, 0xB2, 0x45, 0x0B, 0x99, 0x6D, 0xDE, 0x5F, 0x67, 0xB0, 0x90, 0x4E, 0x24, 0x3C, 0xDD, 0x57, 0xA9, 0xE8, + 0xDD, 0xD4, 0x1B, 0xFD, 0x46, 0x10, 0x74, 0x3F, 0xA3, 0xC6, 0x81, 0x86, 0x9C, 0xFF, 0x77, 0x46, 0xA9, 0xED, 0x9E, 0xAC, + 0x7F, 0x9C, 0xB6, 0x7E, 0x99, 0xD6, 0xEC, 0xEA, 0x5F, 0x7C, 0xD9, 0xBA, 0x5C, 0x9D, 0xD6, 0x0E, 0xC4, 0xB2, 0x76, 0xE6, + 0xE8, 0xCC, 0x9E, 0xBF, 0xC4, 0xF0, 0x47, 0x5F, 0x5A, 0x64, 0x9F, 0x4D, 0xB7, 0x01, 0xB3, 0x6F, 0xA0, 0xE1, 0xC9, 0xC6, + 0xDD, 0x1E, 0x30, 0xDF, 0xA9, 0xDF, 0xD7, 0x8F, 0xB7, 0xB0, 0x97, 0xC7, 0x0E, 0xC4, 0xF5, 0xFB, 0x5C, 0x52, 0x91, 0xF2, + 0x21, 0xE0, 0xBD, 0x44, 0x52, 0x62, 0xD0, 0x2C, 0xF9, 0x48, 0xB6, 0x42, 0xBB, 0xC3, 0x02, 0x14, 0xA2, 0xAC, 0x48, 0x0C, + 0x33, 0x63, 0xD8, 0x28, 0x63, 0x03, 0x34, 0x47, 0x37, 0xC7, 0x61, 0x40, 0x7B, 0x0F, 0x04, 0x0E, 0x5A, 0x2D, 0xD1, 0xA5, + 0x90, 0xDE, 0x90, 0x43, 0x3B, 0xA1, 0x1C, 0xA3, 0x7E, 0x63, 0x08, 0x33, 0x97, 0x53, 0x98, 0x17, 0xC7, 0x33, 0x49, 0xC6, + 0xB7, 0xCE, 0x16, 0x7E, 0x2C, 0xF1, 0xA1, 0xE4, 0xC4, 0x9B, 0xF3, 0x56, 0x9E, 0xA1, 0x67, 0x16, 0xB9, 0xF5, 0xFB, 0xE5, + 0xFF, 0x16, 0xB6, 0xFD, 0xFA, 0x36, 0x6A, 0x74, 0xC6, 0x53, 0xA0, 0xF0, 0x40, 0x1B, 0x13, 0xC5, 0xD2, 0x53, 0xFF, 0xEC, + 0xFA, 0xD1, 0x0F, 0x52, 0xC6, 0xED, 0xB1, 0x25, 0xC3, 0xEB, 0x32, 0xAA, 0x85, 0x47, 0x9F, 0xEB, 0x78, 0x34, 0xF8, 0x6B, + 0x5F, 0xF3, 0x87, 0xCD, 0xC3, 0x18, 0xDD, 0xF7, 0x2C, 0xA5, 0xC3, 0x4C, 0x58, 0xB4, 0x53, 0x68, 0x08, 0xD4, 0xC4, 0xBF, + 0x72, 0xC7, 0x9A, 0xE5, 0x68, 0x4B, 0x0D, 0x19, 0x66, 0x09, 0x4D, 0x7F, 0x93, 0x41, 0xB3, 0xC3, 0xB8, 0xCA, 0x92, 0x38, + 0xB0, 0xF5, 0x89, 0x05, 0x49, 0xBD, 0x19, 0x28, 0x19, 0xE7, 0xC5, 0x5E, 0xBA, 0xEB, 0x44, 0x4D, 0x0B, 0x43, 0x1B, 0x04, + 0x60, 0xA2, 0x9C, 0x42, 0x36, 0x09, 0x4F, 0xC3, 0x54, 0x96, 0x2F, 0x36, 0x8B, 0x01, 0xFC, 0xF9, 0x70, 0x9B, 0x0C, 0x67, + 0x04, 0x02, 0x0B, 0x2E, 0xA1, 0xF7, 0x1C, 0x67, 0x6D, 0x4F, 0x9C, 0xE6, 0xF0, 0xEE, 0x60, 0x8B, 0x8D, 0xE2, 0xD3, 0x85, + 0x4B, 0xF6, 0xFC, 0x0B, 0x2B, 0xDB, 0xBD, 0xF8, 0x73, 0xED, 0x32, 0xC9, 0x1C, 0xF1, 0xB0, 0x92, 0xDC, 0x4E, 0x48, 0x77, + 0x08, 0x02, 0x7C, 0xF4, 0x6F, 0x3C, 0xBD, 0x88, 0x01, 0x5F, 0xDB, 0x80, 0xDB, 0xB4, 0x0C, 0x9F, 0x29, 0x52, 0xA4, 0x00, + 0x03, 0x98, 0x3F, 0xDB, 0x08, 0xC3, 0xAA, 0x14, 0xBA, 0xB3, 0xCC, 0x88, 0x41, 0xA5, 0x34, 0x67, 0x03, 0x37, 0xB0, 0xCF, + 0xAB, 0x6B, 0x94, 0xAC, 0x98, 0xB2, 0x06, 0xB1, 0x7C, 0x81, 0x3D, 0x76, 0xDE, 0x22, 0xEA, 0xD3, 0xCE, 0x8D, 0xAB, 0x00, + 0x3A, 0xD1, 0x5A, 0xFE, 0x80, 0x91, 0xAD, 0x4D, 0xB7, 0x43, 0x47, 0xB3, 0x52, 0x8A, 0x8F, 0x4A, 0x1A, 0xF0, 0x26, 0xDE, + 0xF4, 0xE0, 0xBB, 0x26, 0xB0, 0x1C, 0xD0, 0x26, 0xF0, 0x57, 0xDC, 0x53, 0x93, 0x7B, 0x2F, 0xD4, 0xDF, 0x51, 0xB4, 0x56, + 0x30, 0x93, 0x09, 0xE3, 0x95, 0x46, 0xBC, 0xB4, 0x7D, 0x78, 0xA2, 0x32, 0x78, 0xBD, 0x61, 0xA7, 0xF3, 0x16, 0xB6, 0x1A, + 0x2A, 0xA1, 0xB5, 0xA5, 0x4C, 0x79, 0xFE, 0xD6, 0x77, 0xD2, 0xF5, 0x26, 0x8F, 0x9A, 0x7B, 0x4A, 0x8D, 0xF3, 0x97, 0x2A, + 0x50, 0x7A, 0xB5, 0x34, 0xD4, 0xEB, 0xF3, 0x7D, 0x9B, 0x39, 0x77, 0x68, 0x74, 0x1A, 0xA8, 0x1D, 0x1A, 0x87, 0xCE, 0x9C, + 0x19, 0x75, 0xF0, 0x38, 0x9D, 0xF9, 0x3C, 0x3C, 0x7D, 0x64, 0xCC, 0x2F, 0x5B, 0xD4, 0x5C, 0x89, 0xD3, 0x7A, 0xB5, 0x9E, + 0x1B, 0x19, 0x14, 0x1C, 0xEE, 0x0A, 0xE9, 0x08, 0x75, 0xD7, 0x35, 0x06, 0x42, 0xE8, 0xB5, 0x38, 0xC0, 0x32, 0x17, 0x3D, + 0xEF, 0xCB, 0x4B, 0x2E, 0x85, 0x71, 0xE1, 0xFF, 0x41, 0xB9, 0x57, 0x8B, 0x34, 0x35, 0x25, 0x5C, 0xA2, 0xDF, 0x9C, 0x53, + 0xD9, 0x7A, 0xE6, 0x52, 0xBF, 0x89, 0x5F, 0x0C, 0x33, 0x92, 0x64, 0x0B, 0xA1, 0xF6, 0x20, 0x1E, 0x10, 0x99, 0xC7, 0x38, + 0x4A, 0x5E, 0x03, 0xBE, 0x86, 0x97, 0xB5, 0xFA, 0x80, 0xB8, 0xDB, 0xEA, 0x5B, 0xF4, 0xEA, 0xC2, 0xC0, 0x6B, 0xDC, 0xAE, + 0x8F, 0xB5, 0x3D, 0xFD, 0x17, 0x1B, 0xDB, 0x7F, 0xF8, 0xF9, 0xE6, 0x60, 0xFB, 0x0C, 0xA2, 0x66, 0x10, 0x84, 0xB5, 0xA0, + 0x86, 0xC0, 0xD6, 0x86, 0xA1, 0x46, 0xF9, 0x0D, 0x3B, 0xFD, 0x83, 0x69, 0xC4, 0x1C, 0xB9, 0x59, 0x44, 0x63, 0x6A, 0x06, + 0xC4, 0x1E, 0x6B, 0x1E, 0xA0, 0x56, 0xB8, 0xFA, 0x94, 0xE3, 0xF1, 0x2F, 0x04, 0x80, 0x26, 0x67, 0xD2, 0x4F, 0x16, 0x5C, + 0x4D, 0x79, 0xB1, 0x87, 0xA6, 0xBB, 0x06, 0xB7, 0xD9, 0x17, 0x83, 0x86, 0xBF, 0x3C, 0x9F, 0x80, 0xA7, 0x5B, 0xD7, 0xF3, + 0xE5, 0xAA, 0x0E, 0xF0, 0xBA, 0x80, 0xD8, 0xE2, 0x4F, 0x17, 0x84, 0xD2, 0xFB, 0xA5, 0x4F, 0x7A, 0x95, 0xAF, 0xDF, 0xED, + 0xAC, 0x73, 0xFE, 0x4E, 0xBE, 0x74, 0xA1, 0x46, 0xE7, 0xC7, 0x89, 0xC1, 0x6A, 0xE7, 0xC2, 0x64, 0x12, 0x10, 0x4E, 0x3B, + 0xF7, 0xC4, 0xC5, 0x11, 0x04, 0x53, 0x0F, 0x35, 0x75, 0xF2, 0x27, 0xE9, 0xC3, 0x13, 0x55, 0xE5, 0xDB, 0xEF, 0xF1, 0x19, + 0x2D, 0x7B, 0x1A, 0xFD, 0x72, 0xB8, 0x50, 0x2A, 0x4A, 0x58, 0x5E, 0x5D, 0x3E, 0x1E, 0x71, 0x1A, 0x76, 0xC9, 0x8A, 0xD3, + 0x1B, 0xD9, 0xFA, 0x37, 0x5F, 0xC1, 0x38, 0xCE, 0x16, 0x78, 0x90, 0xD6, 0x70, 0x83, 0x1B, 0xFC, 0xAE, 0xAC, 0x63, 0xAF, + 0xD8, 0x8F, 0x8D, 0x8A, 0x0A, 0xE2, 0xEB, 0x1F, 0xBD, 0x5F, 0xDE, 0xEE, 0x3E, 0xA9, 0x39, 0x61, 0x8C, 0x8B, 0xC2, 0x4D, + 0x7A, 0x87, 0x30, 0x55, 0x64, 0x38, 0x63, 0xCC, 0x1D, 0x2A, 0xC0, 0x75, 0xA2, 0x63, 0x1E, 0xEC, 0x57, 0x01, 0x14, 0xCC, + 0xE4, 0x6B, 0x75, 0x3E, 0x4B, 0xAB, 0xD2, 0xF0, 0xDB, 0x59, 0x01, 0xFC, 0x5C, 0x6B, 0xC3, 0x51, 0x02, 0x03, 0xDB, 0xB0, + 0x32, 0xA3, 0x45, 0x9A, 0x2E, 0x8E, 0xA9, 0x95, 0x7D, 0xEA, 0x35, 0xC8, 0x9F, 0x20, 0xE7, 0xD8, 0x3E, 0x25, 0xDE, 0x60, + 0xA4, 0xBB, 0xC5, 0x53, 0x7C, 0xE9, 0x1E, 0x1C, 0xCF, 0x43, 0xE0, 0xFC, 0x5C, 0xBD, 0xE2, 0x26, 0x34, 0xD3, 0x36, 0xB5, + 0x08, 0x93, 0x13, 0xA3, 0x5F, 0x6E, 0x96, 0x26, 0xBC, 0xF3, 0xB9, 0x3A, 0x64, 0x51, 0x82, 0x06, 0xBF, 0xF2, 0x7A, 0x82, + 0x45, 0x0D, 0xB7, 0xFE, 0x5F, 0xF6, 0xF5, 0xAF, 0x40, 0x90, 0x93, 0x07, 0x96, 0x9E, 0x17, 0x36, 0x52, 0xFF, 0xAE, 0xB5, + 0x86, 0x57, 0x16, 0xE3, 0xA5, 0x4F, 0xC3, 0x07, 0x1C, 0x90, 0x20, 0x04, 0xB4, 0x97, 0xE0, 0x39, 0xDF, 0xC5, 0xC7, 0xE5, + 0xB2, 0x02, 0xCC, 0x54, 0x89, 0x3B, 0x8E, 0xC1, 0x4D, 0x73, 0xD2, 0xFA, 0x5F, 0xB8, 0xFC, 0x03, 0xB5, 0x95, 0xB4, 0x65, + 0x9E, 0x84, 0x86, 0x38, 0x6E, 0x15, 0xAF, 0x39, 0x36, 0x46, 0xD2, 0x7C, 0x8D, 0x60, 0x35, 0xBB, 0x6D, 0xF0, 0x57, 0x20, + 0x6D, 0x3C, 0x12, 0xA6, 0x8B, 0x3D, 0xDE, 0xC5, 0x3B, 0x32, 0x85, 0x75, 0xF4, 0x71, 0x99, 0x19, 0x3B, 0x13, 0x86, 0x93, + 0xCD, 0x19, 0x08, 0x12, 0xE1, 0x6E, 0xD0, 0x93, 0x97, 0x9B, 0x66, 0x97, 0x2B, 0x09, 0x0E, 0xEC, 0x5F, 0x95, 0x1B, 0x29, + 0xCE, 0x9B, 0xEE, 0x4D, 0x1B, 0x54, 0x07, 0x61, 0xD9, 0x8C, 0x9F, 0xBF, 0xE1, 0x15, 0x3F, 0xB2, 0xEA, 0xAA, 0x1B, 0xDC, + 0x9A, 0x5C, 0x04, 0x1F, 0xB9, 0x1F, 0x6F, 0x87, 0x1D, 0xA0, 0xBE, 0xA9, 0xEB, 0x8B, 0xE9, 0x2C, 0x81, 0x54, 0x04, 0xCE, + 0xD2, 0xD8, 0x66, 0x3D, 0x4E, 0x11, 0x28, 0xD9, 0x6A, 0x77, 0x8E, 0x6C, 0x7F, 0xE4, 0xC9, 0x45, 0x44, 0x2B, 0x90, 0xF3, + 0xD6, 0x2C, 0xDF, 0xE0, 0xF3, 0x69, 0x56, 0x5D, 0x00, 0x3D, 0xD4, 0xCC, 0x7A, 0x48, 0x72, 0x1F, 0xB6, 0x46, 0x45, 0xEF, + 0x6B, 0xC8, 0xAD, 0xEE, 0x5D, 0xBF, 0xEF, 0x2A, 0x7D, 0xDF, 0xF7, 0x36, 0xB9, 0x45, 0x21, 0xF4, 0xA9, 0x91, 0x3F, 0x26, + 0x3D, 0xBE, 0x50, 0x0D, 0x7B, 0x4C, 0xD9, 0xAB, 0xB5, 0x81, 0x70, 0x3E, 0x62, 0x4D, 0x91, 0x26, 0x54, 0x0C, 0x58, 0x80, + 0x7D, 0xBA, 0x30, 0xEF, 0x22, 0x56, 0x40, 0xB1, 0x72, 0x2B, 0x9F, 0x8F, 0x11, 0x24, 0x43, 0x85, 0xAB, 0xDC, 0x9D, 0xE3, + 0xA3, 0x85, 0x09, 0x5C, 0x29, 0x28, 0x45, 0xEF, 0x23, 0x5D, 0x0A, 0xE9, 0x81, 0xF8, 0x31, 0x52, 0x4B, 0x2B, 0xA1, 0xD1, + 0x91, 0x42, 0xF9, 0x37, 0x84, 0x6E, 0xE1, 0xE0, 0x9E, 0x27, 0xB9, 0x22, 0xF9, 0x55, 0xE9, 0xFA, 0x43, 0xF5, 0xE8, 0x9F, + 0xDF, 0x99, 0x19, 0xD2, 0x83, 0x4A, 0x8E, 0x79, 0xFA, 0x54, 0xBB, 0x8A, 0xCE, 0xE8, 0x75, 0x0B, 0xCE, 0x3A, 0x6C, 0x3E, + 0x1B, 0x4A, 0x8B, 0x58, 0xB3, 0xE5, 0x6B, 0xFE, 0x39, 0xCB, 0xB6, 0x9A, 0x27, 0xF0, 0x71, 0xA0, 0x20, 0x57, 0x83, 0x48, + 0xB2, 0xE5, 0xCE, 0xEA, 0x32, 0xCE, 0xEE, 0x4C, 0x23, 0xF6, 0xDB, 0xF4, 0x88, 0x4A, 0x83, 0x7E, 0xBF, 0x38, 0x86, 0x21, + 0x6A, 0x59, 0x56, 0xA9, 0x1B, 0x9B, 0x8F, 0x8F, 0x36, 0xD6, 0x5E, 0xA3, 0xE6, 0xC9, 0x4A, 0x98, 0x51, 0x4F, 0xE7, 0x57, + 0x2D, 0xB6, 0x4D, 0x8D, 0x7D, 0x48, 0x7B, 0x05, 0x3F, 0x66, 0x91, 0x09, 0xF4, 0x2A, 0x83, 0x4F, 0xDC, 0xE7, 0xCB, 0xB9, + 0x6E, 0x65, 0xB1, 0xE3, 0xAA, 0x5C, 0xB8, 0x78, 0x68, 0x4D, 0x83, 0x2C, 0x56, 0xED, 0x70, 0xB7, 0xFE, 0x03, 0x92, 0x69, + 0x1E, 0x05, 0x72, 0x82, 0xA3, 0x9D, 0x65, 0x45, 0x5C, 0x4F, 0x72, 0xA2, 0x86, 0x90, 0xDF, 0xD8, 0x6E, 0x58, 0x1B, 0x90, + 0x83, 0x00, 0x0C, 0x78, 0x72, 0x71, 0x7E, 0xCD, 0xF0, 0x70, 0xAE, 0x3F, 0x61, 0xDB, 0x49, 0x6B, 0x58, 0x44, 0xA8, 0xEB, + 0xB4, 0x6D, 0x51, 0x5B, 0x49, 0x6B, 0xAB, 0x1A, 0xAA, 0x22, 0x20, 0x71, 0x6E, 0xF0, 0xC7, 0xBA, 0xDD, 0xDC, 0x00, 0x73, + 0xA2, 0xC4, 0xBF, 0x43, 0xEE, 0x38, 0xD4, 0x69, 0x77, 0xAB, 0x6C, 0x4C, 0x8A, 0x3D, 0x54, 0x80, 0x8D, 0x1C, 0xD5, 0x33, + 0x94, 0x6E, 0x7C, 0x87, 0x40, 0xDA, 0xDD, 0x52, 0x61, 0x3C, 0xAB, 0xE3, 0xC1, 0xCA, 0x01, 0xFF, 0x6E, 0x4D, 0x91, 0x25, + 0x9C, 0x43, 0x0E, 0xC5, 0xBE, 0xFF, 0x17, 0x83, 0x80, 0xC3, 0x30, 0x52, 0x27, 0x39, 0x36, 0x53, 0x82, 0xB8, 0x62, 0x72, + 0x33, 0x73, 0x79, 0x44, 0x54, 0x14, 0x8E, 0x26, 0x11, 0x74, 0x37, 0xA0, 0x4C, 0xD9, 0x2B, 0x9A, 0xFF, 0x82, 0x56, 0xD2, + 0xE1, 0x71, 0x0C, 0xA8, 0x65, 0xC1, 0xA7, 0xB7, 0x8A, 0x76, 0x83, 0xF5, 0x8F, 0x44, 0x7D, 0x3B, 0x2F, 0x8B, 0xD9, 0x0E, + 0x4E, 0x07, 0xB2, 0x1E, 0x03, 0x80, 0xDD, 0xE1, 0x72, 0x06, 0x05, 0xE1, 0x4A, 0x34, 0x5C, 0x51, 0xAC, 0x2A, 0xBA, 0x8F, + 0x82, 0x53, 0x1D, 0x89, 0x4F, 0xD7, 0x66, 0x96, 0xB9, 0x15, 0x01, 0x7C, 0x30, 0x24, 0xD6, 0xA5, 0xBA, 0x23, 0x9E, 0xB9, + 0x85, 0xFE, 0x6E, 0x86, 0xE4, 0x14, 0x0E, 0xDB, 0x17, 0x27, 0x1A, 0x3C, 0x22, 0xAC, 0x4E, 0x54, 0x83, 0xA4, 0x05, 0x6B, + 0x8B, 0xDA, 0xB8, 0xC7, 0xA8, 0x3E, 0x6C, 0x45, 0x14, 0xA1, 0x90, 0x6D, 0xFC, 0x34, 0x0D, 0x7B, 0x2B, 0xCF, 0xF4, 0x63, + 0x39, 0x2A, 0x25, 0x3B, 0x3D, 0x58, 0x67, 0x99, 0xCA, 0xEC, 0xA1, 0xB6, 0x4B, 0x18, 0x06, 0x70, 0x6E, 0xB7, 0x2F, 0x9B, + 0x48, 0xD5, 0x1A, 0xEE, 0x3E, 0x3E, 0x6E, 0x52, 0x2A, 0xDF, 0xD8, 0xF1, 0xD0, 0x4C, 0x07, 0xEF, 0xCE, 0x82, 0xA6, 0x0C, + 0x1A, 0xDC, 0x3E, 0xBA, 0x88, 0x97, 0x38, 0x2F, 0xD9, 0x31, 0x77, 0x63, 0xE9, 0x8C, 0x04, 0xF1, 0x13, 0x4F, 0x72, 0x5D, + 0xDD, 0x1F, 0x85, 0x3F, 0x98, 0x04, 0x5E, 0x9F, 0x14, 0x62, 0xCA, 0x17, 0x12, 0x0E, 0x40, 0x1C, 0x95, 0x8D, 0x58, 0x04, + 0x2D, 0x57, 0x93, 0x1F, 0xE7, 0x81, 0xB3, 0x66, 0x44, 0x6D, 0x86, 0x70, 0xC7, 0x59, 0x88, 0x72, 0x62, 0x71, 0x60, 0x7F, + 0xC7, 0x15, 0x03, 0x34, 0x49, 0xFA, 0x43, 0x23, 0x06, 0x56, 0x5A, 0x17, 0xE3, 0x12, 0x0F, 0x42, 0xA5, 0xE2, 0xE8, 0x9D, + 0x73, 0xF2, 0x21, 0x06, 0xE6, 0x5B, 0x93, 0xEC, 0xF6, 0x53, 0xAE, 0x51, 0x87, 0xCC, 0xCE, 0x51, 0x2A, 0x8D, 0x28, 0xDE, + 0xEF, 0x75, 0xE2, 0xA4, 0x5E, 0xCE, 0x4D, 0xE6, 0x3C, 0xBA, 0xDA, 0xE2, 0x20, 0x25, 0x11, 0x21, 0x73, 0x0C, 0xFE, 0x7F, + 0xFC, 0xE1, 0x00, 0xF0, 0xCA, 0xFC, 0xC5, 0xF2, 0x21, 0x24, 0x86, 0x3D, 0xE7, 0x82, 0xFD, 0x8C, 0xF5, 0x9C, 0x4A, 0x81, + 0x6A, 0x7B, 0xB9, 0x6F, 0xD0, 0x55, 0x49, 0xD9, 0x86, 0x85, 0xD3, 0xE7, 0x1A, 0x08, 0x41, 0x93, 0xC3, 0x89, 0xF1, 0x46, + 0x23, 0xFD, 0x5A, 0x2D, 0x6F, 0x0C, 0xB5, 0xFD, 0x98, 0x25, 0x6A, 0x6F, 0xB7, 0x53, 0xD0, 0x36, 0x5D, 0x28, 0xAE, 0xFC, + 0x0B, 0xF9, 0x92, 0xE4, 0x3C, 0x31, 0x77, 0xF6, 0x36, 0xC9, 0x6A, 0x1A, 0xA0, 0xE2, 0x5B, 0xE3, 0xDC, 0x01, 0xF1, 0x4D, + 0x77, 0xCE, 0x53, 0xD6, 0xC4, 0x88, 0x89, 0xA7, 0x7B, 0xA6, 0x99, 0xBB, 0x91, 0xCB, 0x07, 0x60, 0x4F, 0xD4, 0x60, 0x19, + 0xB2, 0xEB, 0xB9, 0xD7, 0x27, 0x36, 0x5F, 0xCE, 0x74, 0xF2, 0x46, 0x3C, 0xBD, 0x27, 0x23, 0x82, 0xDE, 0x8E, 0xC5, 0xA7, + 0xDC, 0x80, 0x0A, 0x08, 0x67, 0x80, 0x39, 0xC2, 0xFE, 0xA2, 0x7A, 0x18, 0xF8, 0xA8, 0x34, 0xB9, 0x8D, 0xE5, 0x59, 0xA9, + 0x22, 0x81, 0x68, 0x7E, 0xA6, 0xEC, 0xA0, 0x0E, 0xC8, 0x1D, 0xE8, 0x0D, 0x2D, 0x43, 0x33, 0x5F, 0x08, 0x9C, 0xF7, 0x94, + 0x76, 0xDE, 0x43, 0xBC, 0x15, 0x92, 0xFE, 0x04, 0x9D, 0x79, 0x8A, 0xE0, 0xDB, 0xF5, 0xC4, 0xC4, 0x20, 0xBD, 0x4C, 0x64, + 0x78, 0xCB, 0x0C, 0x86, 0x99, 0x90, 0xCA, 0x7F, 0x92, 0xD3, 0x97, 0x51, 0xA3, 0xB9, 0x67, 0x50, 0xE7, 0x05, 0xCF, 0xD0, + 0x8A, 0x9F, 0x1D, 0xDC, 0xA2, 0xE2, 0x5C, 0xC0, 0x66, 0xCD, 0x36, 0x45, 0x66, 0x06, 0x0D, 0xB7, 0x53, 0xE9, 0x7D, 0x65, + 0x27, 0x47, 0xAB, 0xF5, 0x0A, 0x2E, 0x10, 0x51, 0xD6, 0xC1, 0xDF, 0xB3, 0xF4, 0x83, 0x5E, 0x20, 0x8A, 0x9B, 0xF4, 0xE3, + 0x08, 0xB2, 0xB4, 0x5E, 0x66, 0x09, 0x0C, 0xF7, 0x4E, 0x59, 0x34, 0xDA, 0xA5, 0x19, 0xBA, 0x52, 0x4D, 0x39, 0x1C, 0xB5, + 0x24, 0xD8, 0xB4, 0xF2, 0x7E, 0x6A, 0x05, 0x85, 0xEA, 0x9B, 0xC5, 0x21, 0x17, 0xBF, 0x0D, 0xC4, 0x1B, 0xD9, 0xE0, 0xA0, + 0x34, 0x06, 0xFF, 0xB1, 0x84, 0xD7, 0xD5, 0x2D, 0x1B, 0xBA, 0x25, 0xFB, 0x65, 0x5B, 0x6D, 0xD7, 0xB7, 0xB7, 0x55, 0xE8, + 0xD3, 0xDA, 0x43, 0x61, 0x0F, 0xDF, 0x8E, 0x28, 0xB8, 0x4F, 0x09, 0xFE, 0xFC, 0xB7, 0xEE, 0x47, 0x7D, 0x62, 0xCD, 0x5E, + 0x65, 0x32, 0xE1, 0xBB, 0x6B, 0x73, 0xE8, 0xF8, 0x5B, 0xB8, 0xAD, 0xE9, 0xD3, 0xBA, 0x1F, 0x75, 0x01, 0xD4, 0x4F, 0x8F, + 0xDB, 0x2F, 0x8A, 0xCF, 0xF8, 0xB4, 0xAF, 0x9F, 0xD1, 0x8A, 0xAB, 0xD5, 0x44, 0xA7, 0x88, 0x9F, 0x0C, 0xE4, 0x9C, 0x83, + 0x25, 0x0A, 0x8E, 0x62, 0x1D, 0x58, 0x99, 0x89, 0xC3, 0x0A, 0xE4, 0x88, 0x4D, 0x9C, 0xD2, 0x34, 0x5C, 0xCC, 0x39, 0x15, + 0x8E, 0xC2, 0x90, 0xE6, 0x39, 0x0E, 0xEE, 0x88, 0x84, 0xEC, 0x9E, 0xA1, 0xDC, 0xF0, 0xA7, 0x77, 0x83, 0xDC, 0x99, 0xF6, + 0x4B, 0x28, 0x9F, 0x43, 0x4A, 0xCD, 0x35, 0x4F, 0xB6, 0x9C, 0xDB, 0xB9, 0x20, 0x29, 0xD2, 0xBD, 0x4C, 0xDA, 0x25, 0x8B, + 0x87, 0xEE, 0x8D, 0xFA, 0xF3, 0x91, 0x20, 0x01, 0x8D, 0x08, 0xE9, 0x77, 0x64, 0x23, 0x70, 0x64, 0xC0, 0x4D, 0x28, 0x34, + 0xF7, 0x0E, 0x0D, 0x56, 0x49, 0x1A, 0xEE, 0x29, 0xFA, 0xD0, 0x5C, 0x56, 0x20, 0x61, 0xA6, 0xF5, 0x30, 0x65, 0x81, 0x02, + 0x53, 0x4E, 0x3F, 0x9C, 0x1D, 0xAF, 0x1B, 0x23, 0x63, 0x59, 0xAF, 0x84, 0x1A, 0x28, 0x99, 0x77, 0xA0, 0x43, 0xB3, 0x86, + 0xE5, 0x8C, 0x41, 0x98, 0x43, 0x4B, 0xE0, 0x46, 0xF3, 0xEA, 0x32, 0x48, 0x02, 0x0C, 0x1E, 0x9F, 0x6D, 0x64, 0xC6, 0xBE, + 0x43, 0x86, 0x01, 0xE6, 0xD2, 0xAC, 0x9A, 0x49, 0x6B, 0x08, 0xAE, 0xD6, 0x93, 0xDC, 0x4E, 0xD1, 0xA8, 0x66, 0xF8, 0x34, + 0xF0, 0x61, 0xC1, 0x02, 0x14, 0x00, 0x01, 0x78, 0xA2, 0x0B, 0x57, 0x58, 0xA1, 0x99, 0x8B, 0x9A, 0x71, 0x60, 0x95, 0x12, + 0xD9, 0x2B, 0xF1, 0xB5, 0xC7, 0x8A, 0x03, 0x8E, 0xA9, 0x44, 0xD8, 0x84, 0xAA, 0x73, 0x26, 0xD2, 0x2A, 0xEA, 0x11, 0xCB, + 0xF1, 0xD9, 0x3A, 0x4A, 0xBF, 0x2D, 0xB2, 0xA6, 0x59, 0x18, 0x32, 0xAA, 0x05, 0x69, 0x4A, 0xC5, 0xE0, 0x21, 0xEC, 0x4A, + 0xEA, 0x4F, 0xCE, 0xF8, 0x6A, 0xCF, 0x47, 0x8B, 0x55, 0x05, 0xE5, 0xAC, 0x71, 0x29, 0x2B, 0xD6, 0x4A, 0x42, 0xB5, 0x8D, + 0xD3, 0xCE, 0xE7, 0x1B, 0x81, 0x67, 0x09, 0x0E, 0xED, 0x28, 0x13, 0x8B, 0x68, 0xD4, 0xA5, 0x99, 0x7E, 0xC0, 0xD4, 0x0B, + 0x68, 0x20, 0x4D, 0xFE, 0x1E, 0x1C, 0x2C, 0xC8, 0xA3, 0x9D, 0xF2, 0x69, 0x31, 0xD5, 0xD6, 0x1B, 0x68, 0x21, 0x6C, 0xBE, + 0xF8, 0x48, 0x42, 0xF5, 0x4D, 0xAC, 0xCF, 0x1C, 0x43, 0x6B, 0x4F, 0x0A, 0xC1, 0x22, 0xA3, 0x4F, 0xEA, 0xA5, 0x4B, 0xF4, + 0x23, 0xBF, 0xF6, 0x1E, 0xA3, 0xC7, 0xE9, 0xDD, 0xE7, 0x03, 0xB3, 0xD9, 0x82, 0x00, 0xE5, 0x1B, 0x29, 0x6F, 0xFB, 0x45, + 0x32, 0xD6, 0xEC, 0x84, 0xA5, 0x90, 0xFC, 0x80, 0x36, 0xB0, 0x6C, 0xD2, 0x9B, 0xAF, 0xEA, 0x9D, 0x85, 0xD3, 0x88, 0x72, + 0xA3, 0x59, 0xB4, 0x6B, 0xF9, 0x80, 0xD9, 0x94, 0x88, 0xF8, 0x4C, 0xB7, 0x90, 0x30, 0x65, 0xC5, 0xE7, 0x99, 0xAA, 0xE7, + 0x47, 0x57, 0xD5, 0xFC, 0x00, 0x1E, 0x86, 0x56, 0x80, 0xD2, 0xC4, 0x73, 0x23, 0x5B, 0x2D, 0x86, 0xC1, 0x57, 0x45, 0xB4, + 0xE7, 0x89, 0xA3, 0x69, 0xD2, 0x33, 0x53, 0x44, 0x4E, 0xB1, 0xFC, 0x94, 0x36, 0x3B, 0x6C, 0x52, 0x32, 0x54, 0x64, 0x93, + 0x7C, 0xAB, 0x32, 0x71, 0xD6, 0xB6, 0x5B, 0x36, 0xB1, 0x31, 0x3C, 0x44, 0xB6, 0xF4, 0x75, 0x8A, 0xE6, 0x80, 0xBE, 0xBE, + 0xCA, 0x35, 0xFD, 0x37, 0x30, 0x32, 0x5D, 0xE5, 0x4B, 0xF0, 0x61, 0x87, 0xFC, 0x09, 0x1D, 0x22, 0x81, 0xBA, 0x94, 0xB7, + 0x4C, 0x33, 0x65, 0x14, 0x6A, 0x9A, 0x8B, 0x8A, 0xDD, 0xD1, 0x1E, 0x78, 0x57, 0x17, 0xBE, 0x76, 0x94, 0x35, 0xCF, 0x2C, + 0x27, 0x38, 0xBA, 0x07, 0x7E, 0x82, 0x6E, 0xDC, 0x26, 0x14, 0x5D, 0x6F, 0x4D, 0x57, 0x1F, 0x5A, 0xEC, 0xD9, 0xCA, 0xCF, + 0x6E, 0x06, 0xB3, 0x79, 0x57, 0x15, 0x10, 0x7E, 0xC4, 0xA7, 0x77, 0xE9, 0x27, 0xD1, 0xD2, 0xB3, 0xDA, 0x8E, 0x05, 0x98, + 0x0A, 0x1D, 0xB1, 0xA0, 0x73, 0x32, 0x8F, 0xA7, 0x99, 0xAF, 0x46, 0xBD, 0x02, 0xE0, 0xD5, 0x28, 0x67, 0xBC, 0x80, 0x8A, + 0x28, 0x3A, 0x7A, 0x86, 0xE3, 0x01, 0xEE, 0x12, 0x87, 0xCD, 0x70, 0xE4, 0x0A, 0xBD, 0x35, 0x3E, 0x9A, 0xB7, 0x62, 0xF1, + 0xC2, 0xFE, 0xE1, 0xCD, 0xDA, 0x82, 0x50, 0x4D, 0xC6, 0x12, 0xE7, 0xF1, 0x1B, 0xB4, 0x7B, 0x97, 0x63, 0x01, 0xA8, 0x93, + 0x88, 0xE1, 0x8F, 0xEC, 0x60, 0x17, 0xB0, 0x3F, 0x1A, 0xB0, 0x63, 0x38, 0x42, 0x26, 0xE4, 0x79, 0x8D, 0x84, 0x28, 0x06, + 0x8C, 0x1E, 0x86, 0x3B, 0x3E, 0xCC, 0x84, 0x40, 0xC9, 0x36, 0xC8, 0x22, 0xBD, 0xA3, 0x92, 0xF2, 0x01, 0xA5, 0x96, 0x4F, + 0x74, 0xA5, 0x87, 0xDA, 0x41, 0x1D, 0x18, 0x45, 0xF6, 0x62, 0x89, 0x96, 0xB7, 0x16, 0x9F, 0xA6, 0x5E, 0x7A, 0xCE, 0x59, + 0x12, 0x1D, 0x83, 0x17, 0xF5, 0x4D, 0x80, 0xB3, 0xD1, 0x81, 0xD0, 0x64, 0xB7, 0x2A, 0x95, 0xB6, 0x10, 0xA1, 0x0F, 0xC4, + 0x59, 0x4E, 0xA0, 0x77, 0xCD, 0x8C, 0xDA, 0xB9, 0x10, 0x55, 0x32, 0xE6, 0x2A, 0x29, 0x88, 0x94, 0xFA, 0xEB, 0xFE, 0x61, + 0x01, 0x64, 0x7F, 0x7E, 0x6C, 0xA5, 0x2C, 0x4C, 0x65, 0x87, 0x2A, 0x79, 0x39, 0x50, 0x3F, 0x52, 0xFE, 0xC4, 0xF0, 0xBA, + 0x9A, 0xE4, 0x2B, 0x13, 0x65, 0x33, 0x61, 0x78, 0xBC, 0x52, 0x71, 0xD7, 0xEB, 0x59, 0xB2, 0x37, 0xE8, 0x87, 0xF6, 0x12, + 0x3B, 0xE4, 0xFC, 0x48, 0xC7, 0xA5, 0xCA, 0x8A, 0x3F, 0x9A, 0x82, 0x84, 0x1F, 0x50, 0x5B, 0xC1, 0xB3, 0xCE, 0xE2, 0xCC, + 0xF0, 0x45, 0x52, 0xF2, 0x17, 0xC4, 0xB9, 0x19, 0xF4, 0xF3, 0x8E, 0x45, 0xEE, 0xCF, 0xE4, 0xDC, 0x59, 0x6C, 0x9B, 0x89, + 0xAE, 0xBA, 0x85, 0x36, 0x18, 0x0E, 0x3B, 0x99, 0x39, 0xC5, 0xE7, 0xCD, 0x35, 0xB0, 0x4B, 0xBB, 0xD1, 0x84, 0xE9, 0xCF, + 0x6A, 0x00, 0x33, 0x8C, 0xAE, 0xEB, 0x08, 0xDD, 0xB5, 0x5A, 0x6A, 0x22, 0x46, 0x3D, 0x22, 0xAA, 0xAD, 0xA8, 0xC1, 0xCA, + 0x48, 0x76, 0x3D, 0x12, 0x87, 0x11, 0xAA, 0x6F, 0x54, 0x20, 0xEB, 0xDC, 0x9F, 0x7C, 0x84, 0x5E, 0x87, 0x74, 0xC5, 0x4F, + 0xFE, 0x12, 0x5D, 0x87, 0xEE, 0xAE, 0xFB, 0x89, 0x8C, 0xE0, 0x10, 0x7A, 0xB6, 0xEB, 0xDC, 0x35, 0x2B, 0x72, 0xFC, 0xBB, + 0x90, 0x2F, 0xD3, 0x0F, 0x97, 0xA0, 0x6E, 0xF9, 0x4F, 0xC7, 0xC0, 0xFB, 0xA9, 0x14, 0x28, 0x85, 0x85, 0x18, 0x9A, 0x5B, + 0x32, 0x0A, 0x23, 0xD0, 0x8F, 0x93, 0xB4, 0x22, 0x7C, 0x9E, 0xE8, 0xF0, 0x64, 0xD1, 0xE6, 0x94, 0x7F, 0xDD, 0x71, 0xF2, + 0x61, 0xF4, 0x0B, 0x17, 0xAC, 0x8C, 0x65, 0x61, 0x26, 0x9A, 0x9A, 0xC7, 0xF4, 0xA9, 0x0B, 0x07, 0x69, 0x74, 0x12, 0x9A, + 0x00, 0xF1, 0x55, 0xF1, 0xE4, 0x13, 0x97, 0x04, 0x94, 0x4C, 0x90, 0xC0, 0xF2, 0x6C, 0x92, 0x4F, 0xF5, 0xB1, 0x31, 0xD3, + 0x5E, 0x1F, 0x84, 0xC4, 0x4A, 0xBB, 0x48, 0x1E, 0xCF, 0x60, 0x0F, 0xC1, 0xD7, 0x0B, 0xAC, 0xE7, 0xF0, 0x9F, 0x63, 0xD4, + 0x03, 0x4E, 0x40, 0x61, 0xE2, 0x97, 0xF4, 0xE2, 0xA2, 0xA8, 0xE5, 0x47, 0xCA, 0xDA, 0xDF, 0x38, 0xB0, 0x97, 0x49, 0x65, + 0x61, 0x94, 0x19, 0x68, 0x03, 0xA0, 0x6B, 0x57, 0xCB, 0x39, 0x69, 0x53, 0xCB, 0xA6, 0x41, 0x60, 0x06, 0x28, 0x56, 0xA8, + 0x4A, 0x0B, 0x5E, 0xE8, 0x6D, 0x99, 0x9C, 0x1D, 0x63, 0x67, 0x6D, 0xAA, 0x53, 0xDB, 0xB2, 0x69, 0xA4, 0x29, 0x56, 0x18, + 0x28, 0xBD, 0x15, 0x1A, 0x66, 0x04, 0x6B, 0xBE, 0x91, 0x68, 0xA9, 0xF9, 0xBF, 0xE9, 0x5F, 0xE9, 0xED, 0x92, 0x0B, 0xFC, + 0xC0, 0x4C, 0x69, 0x03, 0x98, 0x71, 0x8D, 0x5C, 0x84, 0x57, 0x17, 0xCB, 0xA5, 0x94, 0xE7, 0x8E, 0x8E, 0x53, 0x8C, 0x83, + 0xEB, 0xC3, 0xF7, 0xE1, 0x14, 0x4A, 0x6E, 0xE2, 0x66, 0x2D, 0x26, 0x26, 0x3E, 0xBA, 0xB6, 0x37, 0xF3, 0x51, 0xC8, 0x5A, + 0x16, 0xEC, 0xAE, 0xEF, 0x74, 0x30, 0x96, 0x5A, 0x58, 0xC3, 0x42, 0x69, 0x10, 0xBD, 0xE8, 0xF7, 0x94, 0xCD, 0x59, 0x07, + 0xC6, 0x93, 0xAF, 0x58, 0xDD, 0xAE, 0x88, 0x6F, 0xB1, 0xE9, 0x89, 0xE7, 0x17, 0x1D, 0xF8, 0xBB, 0xE7, 0xDD, 0xCF, 0x4A, + 0xB9, 0x35, 0xBF, 0xC6, 0xDF, 0x9D, 0x7F, 0xBF, 0xFF, 0xFF, 0x60, 0x52, 0x64, 0x0D, 0xFF, 0x77, 0xB3, 0x73, 0xEF, 0x67, + 0xC2, 0x4C, 0xC9, 0x7F, 0x56, 0x82, 0x36, 0xD5, 0x22, 0x41, 0x41, 0xF6, 0xF1, 0x85, 0x78, 0x72, 0xB8, 0x4C, 0xA5, 0x76, + 0xF0, 0x3C, 0x59, 0x05, 0x88, 0x5F, 0xFA, 0x76, 0xE8, 0x86, 0xAA, 0x43, 0x1E, 0x4D, 0x80, 0x4F, 0x51, 0x6F, 0x0D, 0x92, + 0x60, 0xBC, 0xF1, 0x54, 0x7A, 0x6B, 0xFA, 0xD3, 0x99, 0x63, 0xB1, 0x57, 0x6C, 0x6F, 0x1E, 0x04, 0xA2, 0xBF, 0xD0, 0xCC, + 0x02, 0x3F, 0xE7, 0x12, 0xBD, 0x40, 0xB6, 0xD5, 0x51, 0x04, 0x9F, 0xFE, 0x74, 0x20, 0xF2, 0xF8, 0xA4, 0xD0, 0x00, 0xED, + 0xC1, 0x41, 0x8E, 0x4B, 0x75, 0x24, 0x59, 0xB9, 0x1C, 0x44, 0xD7, 0x23, 0xAE, 0x59, 0x45, 0x89, 0xC8, 0x0B, 0x0E, 0x9A, + 0xF6, 0xA3, 0x96, 0x31, 0x85, 0x84, 0x9B, 0x44, 0xF1, 0x65, 0x17, 0x13, 0x80, 0xB7, 0xE3, 0x86, 0xE7, 0xC8, 0x5B, 0x82, + 0xAD, 0xF7, 0x2D, 0x63, 0xC5, 0xF4, 0x52, 0x5A, 0xCA, 0x44, 0xAA, 0x5F, 0x76, 0xC9, 0x8A, 0x19, 0xBC, 0x82, 0x53, 0x2B, + 0x1F, 0xDA, 0x7A, 0x7F, 0x7C, 0x46, 0x5A, 0xA9, 0xD0, 0xC4, 0x3C, 0x4E, 0x56, 0x02, 0x3A, 0x53, 0xA7, 0x23, 0x2C, 0xCB, + 0x64, 0x45, 0xAB, 0xD2, 0x31, 0x29, 0x45, 0x20, 0x3A, 0x46, 0x7A, 0xEC, 0xED, 0xCE, 0xAF, 0xDB, 0x4B, 0x6F, 0x88, 0xD2, + 0xEE, 0x6B, 0x2D, 0xCC, 0x5D, 0x56, 0x0F, 0x4C, 0xC6, 0x4F, 0x0C, 0x8A, 0x5E, 0xC9, 0x47, 0x9F, 0x2A, 0xC3, 0x09, 0xDC, + 0x35, 0x99, 0xB5, 0xA2, 0x1D, 0x6D, 0xB6, 0xE7, 0xA2, 0x42, 0x62, 0x83, 0xE6, 0x01, 0x0B, 0x79, 0xA8, 0x8D, 0xF9, 0xA6, + 0x29, 0xB1, 0xAC, 0x81, 0xCA, 0x03, 0xC4, 0x82, 0xE9, 0x49, 0x12, 0xFF, 0x2E, 0xF0, 0xA6, 0xB5, 0xD7, 0x6D, 0x41, 0x7B, + 0x78, 0xC4, 0x3C, 0x3D, 0xDF, 0x4B, 0x05, 0x82, 0x68, 0x7C, 0x13, 0xAA, 0x44, 0xC5, 0x74, 0xE7, 0x59, 0x5F, 0xBB, 0x20, + 0x30, 0x9B, 0x65, 0x7B, 0xDE, 0x7D, 0x5B, 0x3A, 0xD8, 0xA0, 0x56, 0xAD, 0x40, 0x91, 0xE2, 0x11, 0x90, 0xD2, 0xD1, 0xDF, + 0x8E, 0xCE, 0xD1, 0xBB, 0x92, 0x70, 0x75, 0xA2, 0x02, 0x5F, 0xAB, 0x9D, 0x98, 0x11, 0x6D, 0xD6, 0x9C, 0x1E, 0x4D, 0x00, + 0x6F, 0x92, 0x43, 0x53, 0xA9, 0xD6, 0x4D, 0x46, 0xD7, 0xD3, 0x46, 0x28, 0x70, 0x59, 0x23, 0x84, 0x76, 0x76, 0xF8, 0x73, + 0x0F, 0xFB, 0xC3, 0x97, 0x02, 0xFD, 0x34, 0xE2, 0xDC, 0x0E, 0xB4, 0xA7, 0x11, 0x3C, 0x05, 0xEB, 0x86, 0xD7, 0xC6, 0xF6, + 0xE1, 0x7F, 0xBA, 0xB2, 0x93, 0xE2, 0xC9, 0x33, 0x5B, 0x55, 0x05, 0x10, 0xC8, 0xA6, 0xF5, 0x0F, 0x1B, 0x67, 0xCD, 0x37, + 0x90, 0xD7, 0x8C, 0x92, 0x79, 0xF4, 0x43, 0xC9, 0xC0, 0xF7, 0x5F, 0xE6, 0xC3, 0xE6, 0xE1, 0x6A, 0xAA, 0x74, 0x11, 0x7F, + 0x44, 0xE5, 0x36, 0xA9, 0x89, 0x5E, 0x03, 0xAE, 0x9C, 0x39, 0x6E, 0xDA, 0xD0, 0x14, 0x4E, 0x09, 0xE3, 0x98, 0x3A, 0x0B, + 0xC8, 0xD3, 0xC6, 0xDC, 0x4A, 0x5B, 0x9E, 0xEB, 0x7E, 0x15, 0xD1, 0xB1, 0x53, 0xEB, 0xBF, 0xBC, 0x4B, 0x5C, 0x3F, 0x18, + 0x11, 0x63, 0xF4, 0xBE, 0x08, 0x07, 0xDB, 0x6E, 0x93, 0xE6, 0x98, 0xD9, 0xAD, 0xF0, 0x27, 0x5D, 0xB9, 0xD6, 0xFE, 0xF5, + 0x8D, 0x91, 0x8E, 0x49, 0xC6, 0x3F, 0x0F, 0xFA, 0x8F, 0xF3, 0xF0, 0xC5, 0x02, 0xD1, 0xF6, 0x1F, 0xE9, 0x94, 0xB0, 0x79, + 0xB6, 0x9B, 0xDE, 0x68, 0x80, 0x9E, 0xE4, 0x0F, 0x4B, 0xD2, 0x39, 0xA1, 0x41, 0x37, 0x07, 0x04, 0xFE, 0xE3, 0x03, 0xAE, + 0xEC, 0x16, 0xC6, 0x4D, 0x17, 0xDE, 0x47, 0xC1, 0x0E, 0x9E, 0x99, 0x1D, 0xFF, 0x9B, 0x01, 0x48, 0x14, 0xD2, 0xCA, 0x3A, + 0x12, 0x4E, 0x78, 0x7A, 0x86, 0xEC, 0xFE, 0x3B, 0x35, 0x0B, 0xC0, 0x40, 0x07, 0x30, 0xEF, 0x04, 0x27, 0xB5, 0x10, 0x58, + 0xFC, 0x9D, 0xB0, 0x05, 0x6D, 0xD0, 0x3E, 0x00, 0xC5, 0xE1, 0x80, 0xD9, 0xD6, 0xEC, 0xB8, 0x61, 0x73, 0xE7, 0xF1, 0x30, + 0xFF, 0x81, 0x29, 0x37, 0xAF, 0xCD, 0x71, 0x1B, 0xE4, 0xEC, 0x28, 0x11, 0xCD, 0x5F, 0x97, 0x3A, 0xB4, 0xB0, 0x03, 0xB1, + 0x04, 0x62, 0x40, 0xF5, 0x74, 0xDC, 0x8C, 0xAA, 0xD6, 0xC9, 0xE2, 0xDF, 0x83, 0x79, 0x50, 0xE8, 0x47, 0x64, 0x26, 0x39, + 0xEB, 0x18, 0x10, 0xDA, 0xA2, 0x0C, 0x28, 0x17, 0xCE, 0xF8, 0x78, 0x52, 0x41, 0x45, 0x14, 0xE4, 0x5B, 0xED, 0x86, 0xB3, + 0x06, 0x29, 0x48, 0x08, 0x6B, 0xDA, 0xAE, 0x62, 0xC0, 0xDC, 0x31, 0xB2, 0xFC, 0x1B, 0x49, 0xC0, 0x24, 0x8F, 0x91, 0x70, + 0x2A, 0xA8, 0x43, 0x9B, 0xC7, 0x88, 0x7F, 0x05, 0x3C, 0xF6, 0x8E, 0x8F, 0xD9, 0xEA, 0x9C, 0xAF, 0x7C, 0x28, 0x4A, 0xA8, + 0xC4, 0xAF, 0xDA, 0x4C, 0xEF, 0x95, 0xED, 0xEA, 0x05, 0x52, 0xD1, 0xEF, 0x14, 0xA9, 0xB8, 0xCB, 0xEE, 0x69, 0x41, 0x55, + 0x27, 0x56, 0x4A, 0xE0, 0xAE, 0x87, 0xDC, 0x7D, 0xF6, 0xA9, 0x0B, 0xFB, 0x90, 0xC3, 0x24, 0xD0, 0x69, 0x39, 0x2B, 0x51, + 0x74, 0x97, 0x8D, 0x27, 0x98, 0xDE, 0x09, 0x39, 0xC5, 0x46, 0x82, 0x87, 0x2E, 0xF0, 0x60, 0x8C, 0x66, 0x88, 0x9C, 0xEB, + 0xEB, 0xA5, 0xE2, 0x75, 0x3E, 0x78, 0x8C, 0x47, 0xD6, 0xBD, 0x4A, 0xC0, 0x70, 0x9C, 0x2A, 0x1F, 0xF8, 0xA0, 0xAA, 0x47, + 0x49, 0xE5, 0x84, 0x56, 0xF3, 0xE0, 0x65, 0xCF, 0xD9, 0xB6, 0x67, 0xBE, 0xB0, 0x51, 0x64, 0x64, 0xBA, 0x45, 0x33, 0x22, + 0x8D, 0xE3, 0x32, 0xDA, 0x2A, 0x84, 0x14, 0x2C, 0xB1, 0xC1, 0xC3, 0x19, 0x24, 0x4C, 0x85, 0x56, 0x52, 0x49, 0x1B, 0xC8, + 0x34, 0x94, 0xF2, 0x26, 0xDF, 0xB3, 0x4C, 0xB3, 0x84, 0xD4, 0x78, 0x46, 0x73, 0xF3, 0x87, 0x17, 0xB6, 0xAE, 0x96, 0x65, + 0x13, 0x1E, 0x76, 0x50, 0x41, 0x93, 0xB7, 0x70, 0x1B, 0xB3, 0x23, 0xDD, 0x29, 0xF0, 0xE3, 0xAA, 0x34, 0x3E, 0x31, 0xD1, + 0x66, 0xBE, 0x35, 0xFA, 0xD4, 0x11, 0x7D, 0xF1, 0xFB, 0x18, 0x79, 0x7F, 0x6C, 0xF1, 0xFB, 0xD9, 0x0C, 0x89, 0xEE, 0xFB, + 0x72, 0x63, 0x07, 0x24, 0x4D, 0xBD, 0x30, 0x77, 0xFE, 0xB7, 0x0A, 0xDF, 0x8F, 0x25, 0x96, 0x19, 0x9F, 0xE5, 0x6E, 0x34, + 0x21, 0x4F, 0xBC, 0x97, 0x92, 0xF7, 0xFC, 0x93, 0x5A, 0x97, 0xF4, 0xE2, 0x1C, 0xE4, 0x61, 0x2B, 0xA6, 0xDB, 0x35, 0xD6, + 0xCA, 0x16, 0xD9, 0x70, 0xCC, 0xDE, 0xEF, 0xE5, 0x34, 0x02, 0xA4, 0x13, 0xBB, 0x96, 0xE1, 0xB9, 0x16, 0x48, 0x71, 0xA8, + 0x46, 0x08, 0x7A, 0x06, 0xCF, 0x08, 0x22, 0x76, 0x2C, 0x84, 0xA4, 0x3C, 0x3C, 0xB8, 0x24, 0x54, 0x87, 0x49, 0x76, 0x6B, + 0xBE, 0xB6, 0x28, 0xDD, 0x03, 0x45, 0x3B, 0xED, 0x01, 0xD5, 0x29, 0xC9, 0x7A, 0x72, 0xA6, 0x52, 0xD5, 0x82, 0x18, 0xC1, + 0xBC, 0x9E, 0xA7, 0x8F, 0x5D, 0x15, 0x09, 0x62, 0xAE, 0x75, 0x33, 0x53, 0x36, 0x01, 0xFB, 0xC5, 0x3E, 0xA4, 0xC9, 0xA6, + 0xBE, 0xD1, 0x47, 0xBF, 0x0D, 0xAA, 0xA7, 0x4E, 0xF4, 0xDB, 0x70, 0xC2, 0x0E, 0xEC, 0xD8, 0x7F, 0xB1, 0x4A, 0xC2, 0x88, + 0xD1, 0x80, 0xAC, 0xE3, 0x02, 0x53, 0xEE, 0xD7, 0xCE, 0x86, 0x57, 0xAD, 0x55, 0xB2, 0xC6, 0x05, 0x86, 0xDE, 0x80, 0xF9, + 0xDE, 0x42, 0x61, 0xB8, 0xDF, 0x19, 0xEF, 0xDB, 0xB8, 0x96, 0xCC, 0xA5, 0xDD, 0x2C, 0x57, 0x9D, 0x9C, 0xF2, 0x6F, 0x3D, + 0xA9, 0x65, 0xDE, 0xE3, 0x5A, 0xD1, 0xD3, 0x64, 0xEE, 0xAF, 0x4C, 0xD7, 0x03, 0xCE, 0x5B, 0x00, 0x06, 0x20, 0x5F, 0x64, + 0x67, 0xC5, 0x2E, 0xC2, 0x22, 0xA5, 0xE8, 0x57, 0x60, 0x6B, 0x42, 0xF2, 0x90, 0x18, 0xB2, 0xFF, 0xA8, 0x63, 0xAC, 0x4F, + 0xE2, 0xEC, 0xE1, 0x52, 0xAA, 0xEA, 0x2D, 0x7F, 0x41, 0x1D, 0x41, 0xC4, 0x2A, 0x63, 0x6F, 0x26, 0x35, 0x4D, 0xAB, 0xD5, + 0x9B, 0x53, 0x77, 0x39, 0x7C, 0x8F, 0x4E, 0xA1, 0x69, 0x67, 0xD0, 0x01, 0xC9, 0xBC, 0x29, 0x1C, 0x62, 0xDE, 0x1E, 0xA2, + 0x46, 0x81, 0x9A, 0x66, 0x7A, 0xB5, 0xAB, 0x90, 0x63, 0xB5, 0x8A, 0x51, 0x26, 0x7B, 0x72, 0xE0, 0x8E, 0xAA, 0x9E, 0x79, + 0xF8, 0x41, 0x8B, 0x83, 0xCF, 0x48, 0x66, 0xF1, 0xA8, 0xF8, 0x53, 0x0E, 0x69, 0x42, 0xBF, 0x43, 0xF1, 0x73, 0x2F, 0x67, + 0xA1, 0x63, 0x69, 0x22, 0x08, 0x23, 0xED, 0x75, 0xE0, 0x72, 0x59, 0x37, 0x20, 0x42, 0xC9, 0x8F, 0x6F, 0x4A, 0x81, 0x64, + 0xB0, 0x6D, 0x48, 0x15, 0x19, 0xA7, 0xF9, 0x67, 0x1E, 0xDA, 0x28, 0x8D, 0xBF, 0xB5, 0x6A, 0xDC, 0x68, 0x59, 0x34, 0x34, + 0x68, 0x0D, 0x1F, 0x03, 0x69, 0xA2, 0xA1, 0x89, 0x79, 0xE6, 0xE2, 0x57, 0x5F, 0x9B, 0x16, 0xCE, 0x42, 0x7B, 0x0F, 0x32, + 0x1C, 0x85, 0x05, 0x00, 0x23, 0x7B, 0x53, 0xB0, 0x66, 0xE7, 0x72, 0x6A, 0xB9, 0x82, 0xC5, 0x34, 0x2A, 0x66, 0x0A, 0x28, + 0xB9, 0x4F, 0x7E, 0xB9, 0x87, 0xDA, 0x54, 0x64, 0xE1, 0x48, 0xFA, 0xA7, 0xB6, 0x21, 0xBE, 0xF3, 0xBB, 0xC5, 0xC7, 0x6E, + 0x12, 0xC1, 0xEE, 0x7C, 0x68, 0xD5, 0xF3, 0x78, 0x28, 0xCC, 0x7A, 0xF2, 0x6F, 0x4B, 0xA4, 0x7A, 0xBA, 0xEE, 0x79, 0xF9, + 0x66, 0xA1, 0x3A, 0x6A, 0x3B, 0x51, 0x73, 0x83, 0x3F, 0xC7, 0xCE, 0x44, 0xBA, 0x64, 0x5D, 0x71, 0x60, 0x4B, 0x73, 0xD8, + 0x1D, 0xED, 0x73, 0x68, 0x6A, 0xD0, 0xFC, 0x8E, 0x57, 0xD2, 0x5D, 0x8B, 0xC9, 0x81, 0xFD, 0xF6, 0x97, 0x15, 0x2C, 0xDF, + 0xE1, 0x5D, 0x14, 0x87, 0x64, 0x31, 0xF4, 0xB4, 0x01, 0x92, 0x0E, 0x6B, 0x88, 0x73, 0xD5, 0x5F, 0x56, 0x51, 0x0D, 0x86, + 0x11, 0x4D, 0xFD, 0x89, 0x49, 0xA3, 0x70, 0xEE, 0xB6, 0xC0, 0xD5, 0xEC, 0xF5, 0xFF, 0xCB, 0x47, 0xF4, 0xDF, 0x8D, 0xB2, + 0xED, 0x12, 0x4A, 0x1D, 0x5A, 0x57, 0x75, 0xD3, 0x1E, 0x5D, 0xE3, 0xB3, 0x18, 0x7C, 0x3A, 0xC6, 0xCB, 0x1B, 0xCE, 0xC6, + 0x91, 0x58, 0xAB, 0x82, 0x95, 0x31, 0xBC, 0xFA, 0xB4, 0x80, 0xF7, 0x32, 0x8F, 0xE8, 0x5A, 0x3E, 0x96, 0x59, 0xF5, 0x82, + 0xD8, 0x4A, 0x82, 0x66, 0x77, 0xA9, 0x17, 0xF6, 0x49, 0x72, 0x9F, 0xC4, 0x60, 0xB7, 0x6D, 0x0E, 0x77, 0x8B, 0x33, 0x97, + 0x19, 0xD0, 0x35, 0xF5, 0x48, 0x53, 0x09, 0x2A, 0xD0, 0x3D, 0xCD, 0x1B, 0x5E, 0xA6, 0xE6, 0xAB, 0x2E, 0xCA, 0xD4, 0x8C, + 0x80, 0xF8, 0xBE, 0x7F, 0x00, 0x5D, 0x2E, 0x56, 0x6E, 0x72, 0xC4, 0x9B, 0x93, 0x1C, 0xC7, 0xB1, 0xC8, 0xB6, 0x2E, 0x86, + 0xB5, 0x34, 0x1E, 0xC7, 0x09, 0x79, 0x61, 0xCF, 0x41, 0xD2, 0x59, 0xA1, 0xA8, 0xBE, 0xBF, 0x7E, 0x8C, 0x8E, 0x62, 0x96, + 0xFF, 0x81, 0xAF, 0x53, 0x54, 0x77, 0x1C, 0xEA, 0xD9, 0x77, 0x76, 0xBA, 0x18, 0xB4, 0x60, 0xC7, 0xC7, 0xC4, 0xE7, 0xA9, + 0x19, 0xFA, 0x7C, 0x78, 0xAF, 0xB3, 0xD0, 0xA5, 0xD1, 0x78, 0xA9, 0x86, 0x1C, 0x83, 0x79, 0xF2, 0xAC, 0x88, 0xB5, 0xD0, + 0x8E, 0xE2, 0x6A, 0xA3, 0x98, 0x06, 0x0D, 0x02, 0x6F, 0xDD, 0xBD, 0xF8, 0xAE, 0x20, 0xE3, 0xAB, 0x8E, 0x53, 0xFD, 0x7D, + 0x62, 0x91, 0x6A, 0x50, 0x11, 0x43, 0x30, 0x1E, 0x20, 0xD5, 0x11, 0x3B, 0xAF, 0xB2, 0xCB, 0x35, 0xED, 0x72, 0xC2, 0x09, + 0x75, 0xFE, 0x74, 0xA2, 0x46, 0x83, 0x00, 0x88, 0x05, 0x40, 0xF8, 0x23, 0x12, 0x52, 0x43, 0x50, 0xAF, 0xD1, 0x8D, 0xA2, + 0x0A, 0xEB, 0x3D, 0x3F, 0x03, 0xF9, 0x13, 0xE4, 0x36, 0xE1, 0x46, 0x1F, 0xAE, 0x50, 0x86, 0x1A, 0xF6, 0xE5, 0x07, 0x2B, + 0xB0, 0x26, 0x0D, 0xF5, 0xB7, 0xE2, 0x4F, 0x0A, 0x2F, 0x93, 0x8F, 0x0E, 0x77, 0x87, 0x62, 0x60, 0xB5, 0x8C, 0x9D, 0xB8, + 0xFE, 0xB2, 0x07, 0x0B, 0x48, 0x65, 0x3A, 0xB3, 0x84, 0x8E, 0x5A, 0xF2, 0x83, 0x2B, 0x50, 0xD2, 0xF7, 0xC7, 0xC4, 0x00, + 0xBD, 0xA1, 0x88, 0x19, 0xD9, 0x62, 0xDC, 0x30, 0xFC, 0xC7, 0x50, 0x11, 0x19, 0xA3, 0x87, 0x56, 0xC8, 0x88, 0xFC, 0xEC, + 0xA4, 0xA0, 0xC5, 0x67, 0x27, 0x19, 0x9A, 0x77, 0xFA, 0xB9, 0x49, 0x9D, 0x6A, 0xCB, 0xF5, 0x27, 0x82, 0x6D, 0x26, 0x8B, + 0x08, 0x7A, 0xCE, 0x97, 0x34, 0xBC, 0x1F, 0xB7, 0x2E, 0xED, 0x3B, 0x05, 0xF9, 0x7E, 0x96, 0x79, 0x34, 0x87, 0x26, 0x8A, + 0x42, 0x81, 0x7F, 0xEA, 0x05, 0x8A, 0x85, 0x16, 0xAC, 0x99, 0x8F, 0x69, 0x39, 0xC6, 0xD2, 0x6D, 0x2D, 0xA2, 0x22, 0xC5, + 0xB8, 0x4A, 0x7A, 0x66, 0xF0, 0xD9, 0xA6, 0x6A, 0x4A, 0x91, 0xF9, 0xF0, 0x3F, 0xCF, 0xBE, 0xB9, 0x31, 0x4B, 0x04, 0x03, + 0x28, 0xDB, 0x2A, 0x68, 0xB1, 0xC4, 0xD1, 0xEF, 0x39, 0x9A, 0xDE, 0xC5, 0x38, 0xC7, 0x86, 0x4F, 0x81, 0xE2, 0x00, 0x4A, + 0xFB, 0x0A, 0x47, 0x38, 0xE9, 0xC2, 0x68, 0x68, 0xA5, 0xC3, 0xAA, 0x7E, 0x46, 0xE8, 0x5A, 0xBC, 0x1D, 0xC0, 0xD2, 0x0E, + 0x1E, 0xA2, 0x1C, 0x98, 0x6B, 0x8F, 0xC8, 0x5A, 0xD0, 0xEF, 0xE3, 0x6F, 0x2B, 0x0F, 0x81, 0x4E, 0x9F, 0xCF, 0x32, 0x0D, + 0xAF, 0xCA, 0xF7, 0x66, 0x8A, 0xEA, 0x39, 0x5B, 0x28, 0xCE, 0xD0, 0x3F, 0xDF, 0xA2, 0x79, 0x16, 0x4D, 0x38, 0x4C, 0x7E, + 0x52, 0xE3, 0x42, 0x4B, 0x27, 0x23, 0xFC, 0x82, 0x81, 0x3F, 0x0B, 0x93, 0x5C, 0x7F, 0xE8, 0x55, 0xF0, 0x7D, 0x34, 0xAF, + 0xCE, 0xD5, 0x28, 0x12, 0x6B, 0x98, 0x42, 0x9A, 0x98, 0x70, 0x2C, 0x47, 0xD6, 0xB1, 0xE5, 0xCE, 0x66, 0x19, 0xFD, 0xD2, + 0xDF, 0xA3, 0x20, 0xD9, 0x8E, 0xC3, 0xE7, 0xE0, 0x1F, 0x96, 0x77, 0x1C, 0xD3, 0x3C, 0x16, 0x75, 0x19, 0x4E, 0xA8, 0x40, + 0xD9, 0x0E, 0x83, 0x9B, 0x15, 0x72, 0x36, 0xF0, 0x02, 0xD9, 0x19, 0xB5, 0x0F, 0xC5, 0x3E, 0x11, 0xE2, 0x59, 0x57, 0xD0, + 0xAA, 0x11, 0xD4, 0x62, 0xDC, 0x0A, 0x57, 0x91, 0xA9, 0xE8, 0xEC, 0x76, 0x6F, 0xF9, 0x7C, 0xB0, 0xE5, 0x51, 0x77, 0xC3, + 0x5D, 0x84, 0x18, 0xB5, 0x98, 0xE9, 0x27, 0xA5, 0x0D, 0xB2, 0x8B, 0xD4, 0x9D, 0x73, 0x50, 0xF7, 0x4C, 0xF3, 0xF7, 0xD5, + 0x04, 0x3C, 0x1D, 0xB1, 0xFF, 0xDA, 0xF1, 0xED, 0x3F, 0xBF, 0x82, 0xE8, 0xDB, 0xFD, 0xDE, 0x9D, 0x4C, 0xFC, 0x60, 0x86, + 0x87, 0x89, 0x08, 0x5D, 0xF8, 0x55, 0xAE, 0xE9, 0x5D, 0x1C, 0x69, 0xEB, 0xD4, 0x88, 0xFE, 0xF7, 0x78, 0x74, 0x1A, 0xDC, + 0x8A, 0x9C, 0x1F, 0x74, 0xC7, 0x95, 0x81, 0xA2, 0x30, 0xF8, 0x31, 0x93, 0x6C, 0x5D, 0xCF, 0x1F, 0x10, 0x55, 0x3D, 0xFB, + 0x46, 0xDF, 0xD7, 0xB8, 0x54, 0xEA, 0x72, 0x54, 0xDA, 0xDB, 0x87, 0x40, 0x14, 0xCA, 0x5E, 0x30, 0x82, 0x91, 0xC6, 0x44, + 0x3D, 0x14, 0x09, 0xCE, 0x68, 0xFC, 0xD1, 0x1F, 0xE2, 0x9C, 0xFE, 0x24, 0xD2, 0x3C, 0x42, 0xA0, 0xE1, 0x3C, 0x00, 0x42, + 0x9A, 0x7E, 0x81, 0x03, 0x7F, 0xF3, 0x18, 0xB5, 0xC6, 0x93, 0xBE, 0xC0, 0x5B, 0x41, 0x9B, 0x94, 0x86, 0x4D, 0x1F, 0x65, + 0xDC, 0x28, 0x57, 0x24, 0x5A, 0xFC, 0x79, 0x35, 0x1A, 0x00, 0xAA, 0x08, 0xD1, 0x9E, 0x97, 0x79, 0x03, 0xBE, 0xA3, 0xA8, + 0xDC, 0x33, 0x78, 0x0C, 0xE9, 0x6F, 0x28, 0xCE, 0xC3, 0x4D, 0x69, 0x5F, 0xCA, 0x5F, 0xB9, 0xD0, 0x17, 0x07, 0xA8, 0x09, + 0x9C, 0x3A, 0x30, 0x21, 0x47, 0x92, 0x0D, 0x0B, 0x21, 0xEC, 0x58, 0x83, 0x86, 0xD1, 0xD8, 0xAF, 0x6D, 0x6D, 0x6C, 0xE3, + 0x61, 0x44, 0xAA, 0xAF, 0x63, 0xB7, 0xA1, 0x05, 0x20, 0xFC, 0xA5, 0x73, 0x4B, 0x31, 0x36, 0xB3, 0x40, 0x43, 0xE2, 0xCE, + 0x5E, 0x21, 0xE4, 0x64, 0x31, 0x50, 0x92, 0x47, 0x14, 0x6C, 0xF0, 0x12, 0x28, 0x20, 0xE8, 0xE6, 0x70, 0x94, 0x11, 0x70, + 0xA6, 0xDA, 0x68, 0x26, 0x71, 0x01, 0xA7, 0x0A, 0x45, 0xB7, 0xE0, 0xA4, 0x0F, 0x9A, 0xFB, 0xD2, 0xEF, 0xF9, 0xD3, 0x75, + 0x33, 0x89, 0x91, 0xFC, 0xD5, 0xB7, 0xA9, 0xE7, 0x52, 0xDF, 0xE5, 0x2E, 0x55, 0x46, 0x09, 0x11, 0x91, 0x65, 0xE5, 0x6F, + 0xA1, 0xB3, 0x75, 0xE7, 0xDF, 0x6F, 0x1A, 0x8D, 0xE1, 0x3B, 0x3A, 0x96, 0x1B, 0x88, 0x2A, 0x19, 0x72, 0x47, 0x90, 0x34, + 0x59, 0xC8, 0x2A, 0x09, 0xDC, 0x65, 0x72, 0x01, 0x99, 0xEF, 0x4C, 0x90, 0xEA, 0x08, 0x0A, 0xB8, 0x17, 0xAC, 0x2A, 0x76, + 0x19, 0x1A, 0xB8, 0xEB, 0x88, 0x97, 0x73, 0x96, 0x37, 0x47, 0x83, 0x08, 0xDC, 0x04, 0xCF, 0x47, 0x87, 0x15, 0xEB, 0x1F, + 0xCC, 0x26, 0x21, 0xD1, 0x27, 0x04, 0xA2, 0x7F, 0x78, 0x70, 0x3C, 0x4F, 0xAB, 0x93, 0xC9, 0x08, 0xF3, 0x44, 0x04, 0x1B, + 0x6C, 0xCD, 0x52, 0x91, 0x56, 0x91, 0x14, 0xBA, 0x57, 0x89, 0xB1, 0x7B, 0xBA, 0x41, 0x0C, 0xD9, 0xA0, 0x29, 0x1F, 0x9E, + 0xD9, 0xB9, 0xF7, 0x2B, 0x71, 0x4F, 0x03, 0x0C, 0x11, 0x23, 0x51, 0x9A, 0x4E, 0xC3, 0xC1, 0x69, 0x58, 0x6D, 0xB1, 0x2A, + 0xFF, 0xA4, 0x2C, 0x27, 0x4D, 0x25, 0xE2, 0x9B, 0x67, 0x32, 0x04, 0x1F, 0x9B, 0x60, 0xB3, 0x89, 0xD3, 0xAF, 0x2C, 0x90, + 0x91, 0xCF, 0xB0, 0xDF, 0x66, 0x28, 0x90, 0x64, 0x34, 0x6B, 0x64, 0xF2, 0x9E, 0x1F, 0xA5, 0xEB, 0xA0, 0x21, 0x24, 0x4B, + 0xEE, 0xF7, 0x1C, 0x73, 0x55, 0x1D, 0xFE, 0x05, 0xA4, 0x2C, 0xDF, 0x4D, 0xC7, 0x72, 0x89, 0xC3, 0x13, 0x37, 0x59, 0xC3, + 0x12, 0x52, 0x35, 0x7F, 0x22, 0x1E, 0xAD, 0x84, 0x3C, 0x50, 0x08, 0xCB, 0x2B, 0x42, 0x0D, 0xC6, 0x89, 0xD2, 0x6C, 0x33, + 0xAE, 0x55, 0x04, 0x80, 0x30, 0x76, 0x94, 0xE1, 0xEB, 0x08, 0xAC, 0xF6, 0x8D, 0xA9, 0x4D, 0xB6, 0xFE, 0x1A, 0x15, 0xCA, + 0x08, 0x45, 0xF1, 0xCF, 0x4D, 0x8E, 0xCA, 0x96, 0x07, 0x8A, 0x1C, 0xD8, 0x07, 0xE9, 0xCE, 0x81, 0x8D, 0x16, 0xEE, 0xAF, + 0x7F, 0xAB, 0x9F, 0xE4, 0x05, 0x8B, 0xF9, 0xAE, 0x00, 0x56, 0x0D, 0x91, 0x91, 0x75, 0x5D, 0xCB, 0x9F, 0xE2, 0x84, 0x6C, + 0x56, 0xD6, 0x7B, 0x4A, 0x89, 0x1E, 0x2D, 0x29, 0xED, 0x26, 0x1E, 0x3D, 0x5B, 0x33, 0x01, 0x9D, 0xD9, 0xF9, 0x21, 0x1A, + 0xA8, 0xB9, 0x1B, 0x74, 0xA0, 0x7B, 0x20, 0x91, 0xCE, 0x42, 0xCC, 0xA7, 0x92, 0x1D, 0x2F, 0x88, 0xAE, 0xC9, 0xFA, 0x7E, + 0xC8, 0xEE, 0x29, 0x81, 0x4F, 0x4A, 0xAA, 0x5E, 0x7C, 0xF7, 0xCF, 0x24, 0xF1, 0x17, 0x49, 0x1C, 0xBF, 0xD9, 0xE9, 0xDF, + 0xF9, 0x14, 0x0F, 0x55, 0x69, 0xB6, 0x26, 0x68, 0x3A, 0x97, 0x46, 0x3C, 0xC1, 0x52, 0x06, 0x6C, 0x62, 0x70, 0xEE, 0x12, + 0x87, 0xA8, 0xCD, 0x3A, 0x0F, 0xC9, 0xB6, 0x9C, 0x23, 0x7F, 0x9E, 0x65, 0xC6, 0x1F, 0xC8, 0x9E, 0x13, 0x70, 0x43, 0x2B, + 0x28, 0x1D, 0x78, 0x56, 0x4F, 0x98, 0xEA, 0xD4, 0x15, 0x03, 0xAF, 0xFF, 0x13, 0x71, 0xD8, 0xC6, 0x89, 0x8B, 0x47, 0x7D, + 0x4E, 0xCB, 0x98, 0x5A, 0x1E, 0x50, 0xCD, 0xC6, 0x10, 0x3B, 0x5D, 0xF1, 0x3E, 0x54, 0x64, 0x83, 0x57, 0x53, 0x4E, 0x0A, + 0xAF, 0xF1, 0xDF, 0xA2, 0x1A, 0xC2, 0xE8, 0xAF, 0x5D, 0x8D, 0x74, 0x70, 0xEA, 0xB1, 0xC0, 0xDA, 0xF7, 0x8E, 0x07, 0xB2, + 0x1B, 0x2B, 0x70, 0x81, 0x05, 0xA2, 0xB1, 0x65, 0xCC, 0xB9, 0x68, 0xC6, 0x63, 0xD2, 0xD9, 0x45, 0x67, 0x8E, 0x11, 0x78, + 0x04, 0x8E, 0x11, 0xFF, 0x14, 0x5F, 0x60, 0x71, 0x62, 0xD3, 0xF1, 0x2B, 0xE6, 0x5D, 0x18, 0x5F, 0xC6, 0xC5, 0x61, 0x35, + 0x1B, 0xE6, 0x08, 0xE6, 0x18, 0xE3, 0xC8, 0x98, 0xA9, 0xFF, 0xDC, 0x30, 0xF8, 0x28, 0x5C, 0x29, 0xB4, 0x08, 0xB8, 0xEF, + 0xED, 0xA0, 0xE0, 0x52, 0x64, 0x57, 0x1F, 0x44, 0x27, 0x59, 0xED, 0x84, 0x63, 0xA9, 0x49, 0x9C, 0x6A, 0xCB, 0xD7, 0x11, + 0x2D, 0x69, 0x63, 0x62, 0x26, 0xC6, 0xE3, 0x66, 0x36, 0x26, 0xCD, 0x2C, 0x64, 0xA2, 0x41, 0x8D, 0x3E, 0xBD, 0x9B, 0x48, + 0xAD, 0xF5, 0x5A, 0x06, 0xE1, 0xE7, 0xCA, 0xD5, 0x7F, 0xEF, 0x72, 0xBB, 0x6C, 0xAA, 0x9D, 0xB3, 0x90, 0x74, 0xF4, 0x26, + 0x0E, 0x04, 0xD9, 0xFA, 0x64, 0x6D, 0x7C, 0xEA, 0x5C, 0x19, 0x0B, 0x69, 0x78, 0x99, 0x33, 0xFE, 0xA0, 0xEA, 0x8B, 0xD5, + 0x31, 0xA6, 0x75, 0x57, 0x51, 0xA8, 0x86, 0x9F, 0xFB, 0x47, 0x24, 0xFF, 0x8B, 0xAD, 0xBC, 0x3D, 0x05, 0x1B, 0x85, 0xFA, + 0x52, 0x6D, 0x3C, 0xA8, 0x0A, 0x21, 0xE2, 0xBD, 0x9A, 0x21, 0xCD, 0x88, 0xC3, 0x47, 0xD1, 0x8C, 0x9E, 0x13, 0x4C, 0xB8, + 0x83, 0xCC, 0xF8, 0x6E, 0x3F, 0x02, 0x40, 0xE8, 0x4F, 0x12, 0xD8, 0x0D, 0xFC, 0xE4, 0xEF, 0x79, 0x65, 0xCA, 0xB1, 0x49, + 0x98, 0xE6, 0xF7, 0xF8, 0xE0, 0x31, 0xCD, 0xA3, 0x0E, 0xE1, 0x15, 0x5D, 0x6E, 0x0C, 0x4B, 0x2D, 0xFD, 0xEB, 0x48, 0xCB, + 0x37, 0x6C, 0xFF, 0x62, 0x26, 0x1B, 0x1C, 0xE9, 0xA5, 0x9D, 0x16, 0xC1, 0x32, 0x30, 0x17, 0x8A, 0xBC, 0xE1, 0xA6, 0x02, + 0x9F, 0xB4, 0x04, 0xF0, 0xD1, 0x82, 0x84, 0x07, 0x94, 0xAE, 0x6C, 0x5A, 0x4A, 0x9C, 0x18, 0x92, 0x16, 0xF5, 0x9C, 0xC1, + 0x05, 0xEF, 0xA6, 0x47, 0x92, 0xB4, 0x74, 0xDC, 0x43, 0xD6, 0x8F, 0x17, 0x20, 0x5D, 0x9A, 0x3A, 0x38, 0x6E, 0x19, 0xB0, + 0x19, 0xAE, 0xC4, 0xBB, 0x40, 0xAC, 0xAB, 0x8F, 0x1E, 0xB7, 0x30, 0xD9, 0x00, 0xE0, 0x9C, 0x42, 0x32, 0x21, 0xC0, 0x9D, + 0xC5, 0x01, 0xCE, 0x56, 0xAE, 0xB6, 0xAC, 0x4F, 0x9F, 0xD7, 0x40, 0x44, 0x6B, 0xBF, 0x46, 0x01, 0x6A, 0x71, 0x07, 0xD1, + 0xD6, 0x0A, 0xB1, 0x47, 0xF8, 0xB1, 0xE3, 0x82, 0x5F, 0xDE, 0x27, 0xDC, 0x8C, 0x97, 0x7D, 0x67, 0x5A, 0xFB, 0xAA, 0x70, + 0x06, 0x48, 0x6D, 0x96, 0x0A, 0xF6, 0xF1, 0xA3, 0xC5, 0x67, 0x9D, 0x53, 0xB6, 0xB5, 0x8B, 0x0E, 0x5A, 0x54, 0x8E, 0xEC, + 0x0F, 0x84, 0x9A, 0x31, 0xD9, 0x4E, 0x8C, 0x1E, 0xA8, 0x57, 0xD5, 0x1E, 0x29, 0xA7, 0x96, 0x74, 0xB0, 0x44, 0x87, 0x5C, + 0x7D, 0xA4, 0xA8, 0x1E, 0x96, 0xBD, 0x90, 0x83, 0x5F, 0x25, 0x67, 0x1A, 0xB6, 0xB4, 0x7F, 0x3B, 0xDF, 0xD6, 0x13, 0x8B, + 0x9F, 0x33, 0x47, 0xF9, 0x12, 0x95, 0x4A, 0x70, 0x48, 0xED, 0xC7, 0x53, 0xC2, 0x46, 0x85, 0x0F, 0x53, 0x54, 0xD2, 0xA8, + 0x12, 0x63, 0x26, 0x8A, 0x3D, 0xFE, 0xF4, 0x1A, 0x6F, 0x7D, 0xF4, 0x83, 0x7A, 0x26, 0xCE, 0xC0, 0xA3, 0x30, 0xBE, 0xD7, + 0x9C, 0xA6, 0x74, 0xCB, 0xCE, 0x5C, 0xC0, 0xD7, 0xF2, 0x5B, 0xDC, 0x67, 0x59, 0x2A, 0xEB, 0x14, 0x1F, 0xB8, 0x7D, 0x18, + 0xAF, 0x73, 0x16, 0x9D, 0x15, 0xCF, 0xCF, 0xEB, 0xEF, 0x30, 0x4D, 0x5B, 0xB6, 0x41, 0x57, 0x08, 0x6B, 0x52, 0xB7, 0x3F, + 0xCC, 0x74, 0xE5, 0x31, 0x38, 0x42, 0x40, 0xDC, 0x3B, 0xFB, 0xCE, 0xC8, 0x4F, 0x0D, 0x81, 0x57, 0x60, 0x0C, 0x52, 0x3F, + 0x69, 0x30, 0xD9, 0x7B, 0x22, 0x4F, 0x41, 0xD8, 0xD5, 0x0C, 0xC2, 0xCE, 0x39, 0x70, 0xD2, 0x5D, 0xA1, 0x7B, 0x37, 0xF8, + 0xB1, 0x60, 0x49, 0xC5, 0xC6, 0x3A, 0xF7, 0xEC, 0xD3, 0x1B, 0xC9, 0xAD, 0x87, 0x0E, 0x31, 0x52, 0x53, 0x21, 0x8E, 0xB9, + 0x64, 0x90, 0xE7, 0x33, 0x30, 0xE0, 0xF4, 0x3B, 0xA1, 0x1F, 0x99, 0xCC, 0xFB, 0xB5, 0xAF, 0x0E, 0x20, 0x9B, 0x10, 0x65, + 0x43, 0xC9, 0x88, 0x48, 0xE1, 0x1E, 0xB0, 0xBC, 0x09, 0x88, 0xB4, 0x0B, 0x81, 0x99, 0xE6, 0x5C, 0x7D, 0xBA, 0x0D, 0xC3, + 0x0F, 0xBF, 0x39, 0xC7, 0xB0, 0x16, 0x7E, 0x1E, 0x1B, 0xD9, 0xC4, 0x54, 0x73, 0x99, 0x42, 0xD3, 0x0E, 0xED, 0xDE, 0xB3, + 0x11, 0x24, 0x62, 0xE3, 0xC3, 0x4F, 0x83, 0xAD, 0xAF, 0xC8, 0x78, 0xE8, 0x29, 0xA7, 0xCA, 0x95, 0xBD, 0xA8, 0x42, 0x5F, + 0x14, 0x53, 0x31, 0xDF, 0xD4, 0x65, 0x6C, 0xD8, 0x0A, 0xE3, 0xD3, 0x47, 0x1F, 0xCB, 0xE2, 0x5E, 0xC6, 0xCF, 0xC4, 0xDE, + 0x5D, 0xEC, 0x92, 0x7A, 0xBC, 0x66, 0x7B, 0x8F, 0x19, 0x18, 0xE0, 0x4F, 0xA0, 0x63, 0xCB, 0x19, 0x31, 0x30, 0x35, 0x30, + 0xE0, 0x5A, 0xCC, 0x62, 0xA5, 0xD4, 0x1D, 0x79, 0xD2, 0x07, 0x66, 0x13, 0x7A, 0x29, 0x82, 0x50, 0xE8, 0x0A, 0x45, 0xAE, + 0x29, 0x9C, 0x17, 0x13, 0x2A, 0x0F, 0x72, 0x9C, 0x86, 0xBF, 0x00, 0x45, 0xB4, 0x4F, 0x35, 0xD8, 0x04, 0x39, 0xA1, 0xFA, + 0xC3, 0xCF, 0x6E, 0x1E, 0x68, 0x53, 0x63, 0x6B, 0x2B, 0x82, 0x7B, 0xB3, 0x8A, 0x63, 0xAC, 0x13, 0xA8, 0xB1, 0xAD, 0x6A, + 0x7B, 0x91, 0x48, 0xE7, 0x8D, 0x2F, 0xAB, 0x5F, 0xE0, 0x22, 0x63, 0x82, 0xB8, 0x4F, 0x74, 0x9B, 0xCB, 0x92, 0xC4, 0xF4, + 0xB2, 0xE5, 0x20, 0x84, 0x30, 0x30, 0xAC, 0x4F, 0x1C, 0x0D, 0xF2, 0x68, 0x73, 0x01, 0x56, 0xBF, 0x49, 0x40, 0x74, 0x16, + 0xB0, 0x93, 0x45, 0x0F, 0xC4, 0xF0, 0xE2, 0xB2, 0x12, 0x24, 0x94, 0x05, 0xBB, 0x47, 0x85, 0xF7, 0x83, 0x5C, 0xC6, 0x01, + 0x0D, 0xA2, 0xCF, 0x87, 0x98, 0x23, 0xCD, 0x2D, 0xA7, 0x1E, 0xD4, 0x4E, 0xB7, 0xD1, 0x01, 0x57, 0x44, 0x3D, 0xCB, 0x9C, + 0x1A, 0x17, 0xEF, 0x45, 0xB1, 0x2B, 0xB4, 0x40, 0x69, 0x13, 0x6C, 0x1F, 0x15, 0x54, 0x2C, 0xEC, 0xD5, 0x38, 0x4F, 0x83, + 0xFE, 0x68, 0x17, 0x97, 0x4C, 0x36, 0xE1, 0xAB, 0x65, 0x86, 0xD8, 0xF5, 0x7B, 0x55, 0x25, 0x87, 0xDA, 0x54, 0x8D, 0xC1, + 0x37, 0xE7, 0x7E, 0x8F, 0x33, 0xEA, 0xC4, 0xC1, 0xFA, 0x76, 0xE2, 0xBE, 0xA5, 0x87, 0x78, 0x1C, 0x52, 0x88, 0x60, 0x09, + 0xE3, 0x15, 0x22, 0xF4, 0xF3, 0x77, 0xF9, 0x7A, 0x09, 0x6A, 0xC1, 0x4B, 0x3E, 0xB8, 0x74, 0x34, 0x69, 0xD9, 0xAE, 0x4C, + 0x72, 0x3A, 0x27, 0xE7, 0xB8, 0x09, 0x48, 0xE4, 0xC6, 0x22, 0x93, 0x50, 0x1A, 0x59, 0x09, 0x4F, 0xFD, 0xF2, 0x5D, 0x88, + 0xDF, 0x1A, 0x84, 0xCD, 0xA0, 0x78, 0xBF, 0x0C, 0xCC, 0x18, 0xD8, 0x5B, 0x9B, 0x73, 0x2F, 0x88, 0x24, 0x78, 0xE0, 0x19, + 0xF9, 0xD0, 0x40, 0xBD, 0xEF, 0x1B, 0xAB, 0x01, 0x12, 0x1F, 0xB5, 0x20, 0x7B, 0x5E, 0x46, 0x10, 0x91, 0x27, 0x52, 0x2F, + 0x97, 0xFD, 0xD6, 0xED, 0x72, 0x83, 0xCE, 0x86, 0xA6, 0x7F, 0xCF, 0xBA, 0xD0, 0x0C, 0x08, 0x55, 0x80, 0x2E, 0x21, 0x03, + 0x7B, 0x7D, 0xC2, 0x49, 0x57, 0x05, 0xF9, 0xAB, 0x51, 0x2F, 0x04, 0x1A, 0x98, 0x83, 0xD3, 0x12, 0xF2, 0x1E, 0xE4, 0x5C, + 0x38, 0x20, 0xD9, 0xBF, 0x44, 0x92, 0xA4, 0xC6, 0x99, 0x1E, 0x20, 0xFD, 0x04, 0x80, 0x38, 0x5B, 0x67, 0xF6, 0x1B, 0xAA, + 0xE3, 0x1D, 0xE4, 0x06, 0x37, 0xC0, 0xFF, 0xD0, 0xA9, 0x61, 0xA3, 0x72, 0x44, 0x34, 0xD3, 0x94, 0x94, 0x93, 0x29, 0xF5, + 0x76, 0x55, 0x8C, 0xC8, 0xB4, 0x5E, 0x37, 0x2F, 0x82, 0x51, 0xF4, 0xFC, 0x65, 0xB1, 0x6E, 0x33, 0xC2, 0x82, 0xA9, 0xD8, + 0x21, 0x61, 0xB8, 0x2C, 0xBD, 0xC1, 0x29, 0x07, 0xA8, 0xA5, 0x81, 0xAC, 0x30, 0x4A, 0x79, 0xE3, 0x97, 0x4E, 0x4C, 0x3D, + 0x35, 0xC4, 0xF0, 0x35, 0x02, 0x5F, 0xB0, 0xDE, 0xFF, 0x86, 0x08, 0x9A, 0x8A, 0x1F, 0xAC, 0x98, 0xBC, 0x83, 0x37, 0x52, + 0x11, 0x5F, 0x27, 0x2C, 0xC5, 0xE1, 0x78, 0x8D, 0xB6, 0x46, 0xCA, 0x04, 0x88, 0x5A, 0x61, 0xC3, 0xC9, 0xDA, 0xA2, 0x85, + 0xB5, 0xC6, 0xBA, 0x14, 0xEE, 0x67, 0xC5, 0x82, 0x81, 0x17, 0x9C, 0xD3, 0x85, 0xA7, 0x3F, 0x11, 0x38, 0x1C, 0xE8, 0x8D, + 0xD1, 0x4D, 0x39, 0x81, 0x83, 0x93, 0x8A, 0x87, 0x1A, 0x4A, 0x12, 0xD9, 0xEF, 0xDA, 0x7B, 0x1F, 0x68, 0x47, 0x92, 0x84, + 0x0C, 0xEA, 0x6A, 0x0E, 0x47, 0xEB, 0x42, 0xFA, 0x15, 0xD2, 0xC4, 0x17, 0xDD, 0x8A, 0x83, 0x6D, 0x52, 0x98, 0x3C, 0xF0, + 0xAF, 0x2A, 0x8B, 0x5B, 0x4C, 0x6C, 0x22, 0x5D, 0xB6, 0xDB, 0x1C, 0x32, 0x71, 0xDA, 0x6D, 0xC1, 0x9B, 0x2B, 0x1E, 0x5D, + 0x7A, 0xDB, 0x81, 0xC4, 0x24, 0x87, 0x4C, 0x25, 0x08, 0x1C, 0x82, 0x4C, 0x3C, 0xEE, 0x72, 0xEE, 0x38, 0xF1, 0x32, 0x11, + 0x0B, 0xE7, 0xEF, 0xDA, 0xF2, 0x96, 0xF9, 0xBC, 0xB3, 0x00, 0x82, 0x96, 0x4B, 0xB6, 0xF2, 0x73, 0xD8, 0xFC, 0x90, 0xA3, + 0x85, 0xCC, 0x6B, 0x1F, 0x32, 0x03, 0x28, 0x6B, 0xC8, 0x1D, 0xF2, 0xEB, 0x90, 0xD1, 0xEB, 0x05, 0x02, 0xED, 0xFC, 0xBD, + 0x99, 0xB5, 0x7B, 0xF9, 0x31, 0x50, 0x6B, 0x0D, 0xEC, 0xD1, 0x8F, 0x27, 0xF1, 0x8E, 0x64, 0xC7, 0x5E, 0xBA, 0x25, 0xE5, + 0x57, 0x44, 0x8E, 0x44, 0xD8, 0xFF, 0x96, 0xCE, 0xC2, 0x81, 0xAE, 0x70, 0x90, 0x17, 0x84, 0x3C, 0x96, 0xBD, 0xE4, 0xB2, + 0x3D, 0xC0, 0x58, 0x7C, 0x97, 0x96, 0xE5, 0x6F, 0x19, 0xFF, 0x8D, 0x2C, 0x1F, 0xC0, 0xB3, 0x8B, 0x1D, 0xA3, 0x97, 0xCE, + 0x42, 0x33, 0x3C, 0xD7, 0xA1, 0x18, 0x02, 0x37, 0xF8, 0xD7, 0xBA, 0xB5, 0x28, 0x53, 0x9B, 0x40, 0xA3, 0x24, 0xF5, 0x63, + 0xC1, 0x49, 0xD3, 0xDA, 0x60, 0xAE, 0x0F, 0x19, 0x7E, 0xF4, 0x14, 0xF6, 0xBA, 0x68, 0x3F, 0x28, 0xCA, 0xAE, 0xC3, 0x10, + 0xAF, 0x44, 0xFC, 0xF6, 0x77, 0x55, 0xDE, 0x21, 0x0A, 0x6B, 0xF7, 0xC0, 0x49, 0x3B, 0x75, 0x61, 0x32, 0xF5, 0x0A, 0x18, + 0xF6, 0xD6, 0xC0, 0x9D, 0x52, 0xCB, 0x6B, 0x89, 0x3A, 0xD5, 0x6A, 0x53, 0xED, 0xD5, 0xFD, 0xF7, 0xF7, 0x17, 0xB7, 0x88, + 0x88, 0x38, 0x39, 0x9A, 0xB9, 0xDB, 0x7E, 0xBE, 0x8D, 0xC3, 0xA7, 0xAC, 0xA8, 0xB9, 0x77, 0x21, 0x88, 0x92, 0x56, 0xBA, + 0xDC, 0x16, 0xAE, 0x4B, 0x59, 0xF9, 0xBF, 0xD8, 0x86, 0xFF, 0x32, 0xEA, 0x1F, 0xDB, 0x37, 0xFD, 0x8F, 0xD7, 0xC4, 0x4D, + 0xFC, 0x95, 0xEE, 0xAC, 0x59, 0x65, 0xF2, 0xE8, 0xA2, 0x90, 0xBA, 0x6C, 0x89, 0x14, 0xE4, 0x8C, 0x92, 0xD2, 0x17, 0xB2, + 0x0C, 0xF4, 0x5C, 0x39, 0x10, 0x33, 0x4D, 0x4B, 0xAD, 0x83, 0x2F, 0xCB, 0xCB, 0x7D, 0xF6, 0xEE, 0x7E, 0x5E, 0x6E, 0xB4, + 0xED, 0xDD, 0x90, 0x66, 0x44, 0xBD, 0xF8, 0xEE, 0x93, 0x4C, 0xFE, 0xFE, 0x7F, 0x6C, 0x34, 0x0C, 0x13, 0x18, 0x3E, 0xD0, + 0x81, 0x24, 0x64, 0x18, 0x96, 0xDD, 0xF7, 0xEF, 0xFE, 0x5D, 0x67, 0x66, 0x4E, 0xEE, 0xB4, 0x3D, 0x5E, 0x40, 0x01, 0xC3, + 0x33, 0x6E, 0xFF, 0xFF, 0xF7, 0xE6, 0xDB, 0x02, 0x7F, 0x44, 0x63, 0x17, 0x72, 0xD6, 0xBC, 0x53, 0x2A, 0xC6, 0x9E, 0x96, + 0x73, 0xA0, 0x28, 0xF2, 0x83, 0xD5, 0x08, 0xE7, 0xF5, 0x8E, 0x22, 0xA3, 0x27, 0xBE, 0xB8, 0x24, 0xE5, 0xB6, 0x61, 0x1F, + 0x01, 0x89, 0xFF, 0x9E, 0xFB, 0xB4, 0x13, 0xE1, 0x9A, 0x2E, 0xCB, 0x7F, 0x67, 0x1D, 0x57, 0x62, 0xEC, 0x0C, 0x3F, 0xE4, + 0x79, 0x33, 0x43, 0x21, 0x0B, 0xE0, 0x2C, 0x8A, 0x0C, 0x1E, 0x29, 0xBC, 0x1A, 0x46, 0xD8, 0x37, 0x05, 0xA5, 0x68, 0x8F, + 0xB7, 0x27, 0x37, 0x1A, 0x33, 0x60, 0xBE, 0xA0, 0x0B, 0x0A, 0xB6, 0x68, 0xFA, 0xF4, 0xF3, 0x98, 0x47, 0x99, 0xB9, 0x50, + 0xD1, 0x61, 0x0A, 0x55, 0x00, 0x0E, 0x3A, 0xB6, 0xEE, 0xAB, 0xA8, 0x1A, 0x17, 0xDB, 0xA8, 0x1F, 0xB3, 0x62, 0x29, 0x15, + 0x8C, 0x0A, 0x65, 0xC6, 0x88, 0x2D, 0xF5, 0xF4, 0x16, 0x25, 0x96, 0x17, 0x90, 0x68, 0x5D, 0x09, 0xF1, 0x64, 0xFC, 0x3E, + 0x9D, 0x3E, 0xE9, 0xAC, 0x0D, 0x11, 0x3D, 0x72, 0xED, 0xB4, 0xAD, 0x1E, 0xDD, 0x6D, 0xDF, 0xEF, 0xC1, 0x84, 0x40, 0x28, + 0x9F, 0x96, 0x0A, 0x4F, 0x28, 0xE0, 0x61, 0x1C, 0x8B, 0x62, 0x2F, 0x7E, 0xFE, 0x8C, 0xBF, 0x5B, 0x16, 0xB5, 0xFB, 0xEF, + 0x5E, 0x9F, 0xBF, 0x7B, 0x7A, 0x80, 0xDD, 0x8F, 0x99, 0x84, 0x4B, 0x4E, 0xFB, 0xC6, 0x1F, 0xDD, 0xD8, 0xB0, 0x08, 0xB6, + 0xA9, 0x0A, 0x93, 0x3F, 0x26, 0xAD, 0x3B, 0x83, 0x76, 0xF3, 0xF8, 0xBC, 0x06, 0x2D, 0xFE, 0xBA, 0x89, 0x45, 0x5B, 0xA2, + 0x70, 0x05, 0x85, 0x87, 0x6F, 0xB1, 0x25, 0x0F, 0x6B, 0x0E, 0xCB, 0x29, 0x6B, 0x01, 0xC1, 0xB2, 0x7B, 0x8D, 0xE8, 0xC5, + 0xEB, 0x2E, 0xED, 0x44, 0xB2, 0x63, 0x82, 0xBB, 0x09, 0x47, 0xCB, 0x4E, 0xE7, 0x67, 0x64, 0x26, 0xEF, 0xC2, 0x20, 0x59, + 0xAC, 0x6B, 0xF9, 0xC7, 0xD1, 0x66, 0xC4, 0xBB, 0x38, 0x5C, 0x2A, 0x09, 0x16, 0x8F, 0x71, 0x20, 0x69, 0x7D, 0x72, 0x96, + 0xC0, 0x92, 0x2B, 0x03, 0x5A, 0x97, 0xA7, 0x23, 0x0F, 0x59, 0x9E, 0xD9, 0xF3, 0x7D, 0x7E, 0x71, 0xCB, 0xA3, 0xAD, 0x47, + 0x64, 0xF4, 0xB9, 0xDE, 0x2A, 0x41, 0xF5, 0xE7, 0xBA, 0x30, 0xAE, 0x62, 0x2D, 0x8E, 0x0D, 0x64, 0x73, 0x73, 0x9C, 0xC2, + 0xD3, 0xD2, 0xD8, 0x31, 0xB1, 0x17, 0x3C, 0x42, 0x2B, 0x70, 0x7F, 0x75, 0x06, 0x9B, 0x2A, 0xE6, 0x83, 0xD7, 0xF4, 0x60, + 0x39, 0x36, 0xDC, 0x9B, 0xDE, 0x29, 0xE0, 0xF0, 0xDA, 0x44, 0x4E, 0xFF, 0x88, 0x11, 0xDE, 0x99, 0x04, 0x90, 0x7D, 0x11, + 0x5F, 0x19, 0x54, 0xD4, 0xC6, 0x32, 0x79, 0x65, 0x94, 0x8F, 0xB5, 0xE6, 0x82, 0x36, 0x70, 0x29, 0xA3, 0x96, 0xDB, 0xB7, + 0x4C, 0x9A, 0x67, 0x41, 0x6A, 0xF8, 0x02, 0x95, 0x80, 0x73, 0x7E, 0x91, 0x4B, 0x78, 0xBC, 0x7F, 0xEE, 0x97, 0xE9, 0x57, + 0x81, 0xBB, 0x96, 0xAC, 0x78, 0x78, 0xF5, 0x9A, 0xC7, 0x02, 0xF0, 0x06, 0xD2, 0xFC, 0xF2, 0x38, 0x95, 0x79, 0xE6, 0x38, + 0x22, 0x19, 0x90, 0x76, 0x49, 0xC9, 0x60, 0x7C, 0x62, 0x2A, 0x45, 0x56, 0x1F, 0x1B, 0xAD, 0x2F, 0x2D, 0x14, 0xAE, 0xEF, + 0x2B, 0xCF, 0xF1, 0xAA, 0xD2, 0x9E, 0xB3, 0xFB, 0x6A, 0x8F, 0xC1, 0xC5, 0xB9, 0x3A, 0x58, 0x37, 0xDB, 0x9F, 0x57, 0x69, + 0xCD, 0xC1, 0xF2, 0x92, 0xC9, 0x39, 0x89, 0xB9, 0x45, 0x11, 0x30, 0xDF, 0x8A, 0x71, 0x9C, 0x53, 0xC8, 0x7C, 0x66, 0xC8, + 0x12, 0xF2, 0xDE, 0x04, 0xDA, 0xF0, 0xB3, 0x37, 0x76, 0x5A, 0xD5, 0xAD, 0x41, 0xE3, 0x68, 0x0B, 0x1F, 0xFF, 0x17, 0x24, + 0x41, 0xC5, 0x8B, 0x22, 0x07, 0x12, 0xE9, 0xC0, 0x3F, 0x9B, 0xFF, 0x8B, 0x89, 0x73, 0x20, 0x79, 0xE0, 0x25, 0x08, 0x3B, + 0xEF, 0xC4, 0x83, 0xF7, 0x88, 0xC0, 0xCB, 0xDD, 0xC4, 0xA3, 0xD6, 0xDB, 0x75, 0xA2, 0x8C, 0x68, 0xA6, 0x75, 0xD7, 0x5C, + 0xA8, 0xBD, 0xE9, 0x41, 0x2F, 0x67, 0x78, 0x26, 0x3A, 0xFA, 0x1B, 0xB3, 0x50, 0x2D, 0x49, 0x8D, 0xB6, 0x74, 0xDD, 0x50, + 0xA2, 0x64, 0xBC, 0x45, 0xE7, 0xDE, 0x89, 0x0D, 0x09, 0xE6, 0x1B, 0xA5, 0x85, 0x66, 0x6C, 0x73, 0xF5, 0x6E, 0x94, 0x51, + 0x26, 0xF3, 0xAA, 0xA0, 0x84, 0xCC, 0x55, 0x7F, 0xA2, 0x35, 0x8F, 0x1D, 0xCB, 0x62, 0x2F, 0x33, 0x2D, 0xA9, 0x10, 0x75, + 0xA6, 0x0F, 0x28, 0xEB, 0xA1, 0x08, 0xCD, 0x4F, 0x41, 0x16, 0x82, 0x66, 0xD5, 0xC1, 0x41, 0x21, 0xC5, 0x7D, 0xD6, 0x6A, + 0x66, 0xF7, 0x39, 0xA3, 0x9F, 0x4D, 0x31, 0xAA, 0x66, 0x1B, 0x92, 0xB1, 0x05, 0x8F, 0x7E, 0xD3, 0xD9, 0x51, 0xB9, 0x11, + 0x30, 0x48, 0xEC, 0x95, 0x55, 0xE3, 0x96, 0x68, 0x64, 0x85, 0xD4, 0x24, 0x2E, 0x6D, 0xE0, 0xB9, 0x7A, 0x37, 0x0A, 0xD5, + 0x4C, 0xA5, 0x54, 0x1C, 0xEC, 0x0A, 0x75, 0x1E, 0x9E, 0xA7, 0xC1, 0xBE, 0x08, 0x90, 0xE3, 0xE5, 0x5B, 0x69, 0x58, 0xFB, + 0xEF, 0x3B, 0x90, 0x07, 0x78, 0x1F, 0x0D, 0x9A, 0x06, 0xF9, 0x48, 0x27, 0x79, 0x15, 0x88, 0xE8, 0x01, 0x86, 0x4B, 0x20, + 0xB9, 0xC5, 0x05, 0x97, 0xB1, 0x34, 0x65, 0xC2, 0xFC, 0x30, 0xA6, 0x28, 0x4D, 0x7B, 0xF4, 0x77, 0xF5, 0x1D, 0x6A, 0xD7, + 0x2D, 0x45, 0xAC, 0x0C, 0x9F, 0x8E, 0x12, 0x38, 0x4C, 0xF2, 0xF9, 0xDA, 0x51, 0x1B, 0xFD, 0x9A, 0x29, 0x10, 0xBE, 0x87, + 0x74, 0x76, 0x1B, 0x29, 0xCD, 0x70, 0x58, 0xFE, 0xEE, 0x01, 0xE0, 0x81, 0x6B, 0x44, 0xB9, 0x7A, 0xFC, 0xE3, 0x13, 0x39, + 0xCC, 0x30, 0xFD, 0x72, 0x74, 0xDE, 0x6D, 0x19, 0xAF, 0x37, 0xFB, 0x82, 0xCE, 0x34, 0xF9, 0x60, 0xD8, 0x19, 0x25, 0x75, + 0xD4, 0xFC, 0xE0, 0xBD, 0x06, 0x44, 0x74, 0x0E, 0xC9, 0xEB, 0x8F, 0x33, 0xD8, 0x9E, 0x07, 0x7E, 0x71, 0xDD, 0x69, 0x43, + 0xC6, 0x91, 0x04, 0x4D, 0x65, 0xBC, 0xE5, 0x4E, 0xA4, 0x94, 0xC4, 0xFC, 0x61, 0x2F, 0x63, 0xB8, 0x82, 0x7F, 0x9A, 0xC1, + 0x07, 0xE2, 0xBD, 0x8D, 0xCF, 0x67, 0x79, 0xC9, 0x9B, 0x6F, 0x0F, 0x82, 0x87, 0x2C, 0x46, 0xBF, 0x50, 0x0C, 0x73, 0x39, + 0xD7, 0xF7, 0x67, 0xC1, 0x8B, 0x1F, 0xB4, 0x5E, 0x13, 0x55, 0xAF, 0xD1, 0x0D, 0xFD, 0xC8, 0xF5, 0x8B, 0x98, 0xC3, 0xA5, + 0x07, 0x14, 0x2E, 0xB1, 0x8C, 0xB1, 0xFC, 0x1A, 0xD6, 0x78, 0x1E, 0xDC, 0x22, 0x42, 0x9D, 0xC3, 0xB2, 0x36, 0x40, 0x10, + 0x62, 0x5B, 0xAB, 0x53, 0x17, 0x8D, 0xC1, 0x56, 0xD0, 0x97, 0xD5, 0xE7, 0xCE, 0x18, 0x46, 0x11, 0x4B, 0x6A, 0x02, 0x73, + 0xBC, 0x02, 0xF4, 0x90, 0x42, 0x2C, 0xCF, 0x65, 0xD7, 0x0C, 0x08, 0x48, 0x06, 0xBB, 0x26, 0x8E, 0x62, 0x72, 0x50, 0x36, + 0xC4, 0x7A, 0x2E, 0x58, 0xAF, 0xBA, 0x04, 0x49, 0xA7, 0x72, 0x06, 0x0C, 0x75, 0xFB, 0x76, 0xF9, 0xC4, 0x89, 0x04, 0x95, + 0xD7, 0xCE, 0x49, 0x3D, 0x30, 0x3C, 0x5F, 0x22, 0xCF, 0xD8, 0x7D, 0x61, 0x46, 0xA8, 0x4C, 0x64, 0x54, 0x1C, 0x5D, 0xBF, + 0x25, 0xB8, 0x7F, 0x62, 0x01, 0x00, 0x71, 0x35, 0xDB, 0x0F, 0x46, 0xBC, 0x5C, 0x90, 0x0E, 0xF7, 0xEE, 0x69, 0x66, 0x9D, + 0x03, 0xF5, 0x34, 0x0A, 0x17, 0xDF, 0xB7, 0x27, 0x9A, 0x62, 0x20, 0xD7, 0x4E, 0x76, 0xF6, 0x7E, 0x08, 0xD8, 0x48, 0xB4, + 0x77, 0x01, 0x99, 0xC8, 0x1F, 0xFF, 0xE7, 0x1A, 0xDA, 0x78, 0xFC, 0x28, 0x3C, 0x1E, 0xE7, 0x63, 0x0E, 0x3E, 0xEE, 0xB9, + 0x40, 0xFE, 0x6C, 0xCC, 0x84, 0x6E, 0x20, 0x9F, 0xC0, 0xFF, 0xD9, 0x14, 0xE1, 0xBF, 0x7F, 0x43, 0xDA, 0xF1, 0x53, 0xD1, + 0xFF, 0x20, 0x37, 0x1D, 0xD2, 0xB4, 0x97, 0x34, 0x83, 0xB5, 0x9D, 0x90, 0x4F, 0x84, 0x61, 0xCB, 0xB5, 0x9E, 0x06, 0xDB, + 0x31, 0xEB, 0xC1, 0xD5, 0xC2, 0xA0, 0x3A, 0x96, 0xE8, 0x28, 0x4F, 0xCE, 0xE2, 0x41, 0x19, 0x47, 0x5D, 0xC4, 0x3A, 0xE1, + 0x89, 0x0C, 0x25, 0x6A, 0x0F, 0xFE, 0xAE, 0xCE, 0x42, 0x4D, 0x59, 0x71, 0xA3, 0x6E, 0x21, 0xE0, 0xD4, 0xBB, 0xA2, 0x41, + 0x13, 0x3A, 0xF8, 0xEA, 0xD6, 0xD0, 0x1E, 0x17, 0x45, 0xDB, 0xA8, 0x6F, 0x27, 0x06, 0xB3, 0xB6, 0x93, 0xFA, 0xD8, 0xB6, + 0xD1, 0x46, 0x73, 0x2B, 0xEE, 0x99, 0x9E, 0x41, 0x01, 0x08, 0xA1, 0x04, 0x7F, 0xAD, 0xF4, 0x7A, 0xA9, 0x32, 0x8A, 0x65, + 0x07, 0x3B, 0x0C, 0xC9, 0xA3, 0x37, 0x09, 0x88, 0xF7, 0x21, 0xBA, 0x8A, 0xBC, 0x47, 0x19, 0x74, 0x5C, 0x9B, 0xD9, 0x9B, + 0x77, 0x01, 0x63, 0xCC, 0x46, 0x9C, 0xF2, 0x17, 0x6C, 0xE3, 0x6B, 0xAE, 0x8C, 0xBB, 0x6C, 0xE5, 0x28, 0x4B, 0x3E, 0x7E, + 0xEE, 0x4C, 0x64, 0x05, 0xA2, 0x4A, 0xA8, 0xC7, 0xA9, 0x66, 0xC3, 0xD1, 0xA3, 0xD1, 0x23, 0x17, 0x14, 0x4F, 0x80, 0x28, + 0xAB, 0xB5, 0xAB, 0xDC, 0x7B, 0xEA, 0x5A, 0x76, 0x8F, 0xE9, 0xB3, 0x2C, 0xED, 0xD4, 0x42, 0x22, 0x2C, 0xE0, 0x2C, 0x04, + 0xDF, 0x4B, 0x07, 0xCA, 0xDE, 0xBB, 0xCE, 0x4B, 0xBB, 0xA6, 0x3A, 0xAA, 0xCC, 0xB9, 0xED, 0x33, 0xA7, 0x02, 0x8A, 0x99, + 0xE4, 0x0E, 0x2C, 0xAC, 0xAF, 0x22, 0x65, 0xA8, 0x47, 0xE6, 0x7D, 0xA8, 0x7F, 0x90, 0x7B, 0xB2, 0x6B, 0xF1, 0x3D, 0xAF, + 0x18, 0x24, 0xC3, 0x32, 0x37, 0xF2, 0xB5, 0xB9, 0xDB, 0x0E, 0x0F, 0xF8, 0x09, 0xDB, 0x5B, 0x1B, 0x50, 0x32, 0x23, 0xF9, + 0x2B, 0xB0, 0x77, 0xEE, 0x90, 0x65, 0x92, 0xA4, 0xAF, 0x12, 0x81, 0xF7, 0x41, 0xB9, 0x51, 0x9F, 0x10, 0x12, 0x1C, 0xC6, + 0x30, 0x7F, 0x64, 0x8E, 0xD6, 0xE5, 0x97, 0x95, 0xD8, 0xA8, 0x7A, 0x10, 0x94, 0xF7, 0x98, 0xF3, 0xF0, 0x7F, 0xB2, 0x80, + 0x2D, 0x1E, 0x05, 0xE5, 0xBC, 0x99, 0x58, 0xB5, 0x6D, 0xAF, 0x05, 0x62, 0xF2, 0x87, 0xF2, 0x60, 0x1E, 0x20, 0xFF, 0x91, + 0xE9, 0xC8, 0x8A, 0x71, 0xAD, 0x87, 0x3E, 0x23, 0x2D, 0x95, 0x14, 0x41, 0x72, 0xB9, 0x21, 0x2B, 0xD3, 0x62, 0xC9, 0x02, + 0xE0, 0x50, 0xAC, 0x66, 0x77, 0xED, 0x04, 0xC1, 0x5C, 0xD7, 0xF6, 0x5E, 0x80, 0x31, 0x3E, 0xF9, 0x62, 0x95, 0xC1, 0x16, + 0xDF, 0x7A, 0x5B, 0x86, 0x68, 0x6F, 0x3C, 0xB7, 0x28, 0x09, 0x73, 0x83, 0x1D, 0x3A, 0xEF, 0x07, 0x70, 0x3E, 0x8D, 0x1D, + 0x25, 0x56, 0x49, 0x51, 0xBF, 0xBE, 0xE2, 0x36, 0x21, 0x48, 0xBD, 0xB1, 0xFC, 0x7A, 0x56, 0x76, 0x24, 0xB3, 0x02, 0x08, + 0x44, 0x29, 0x81, 0xB7, 0x4A, 0xFC, 0xC8, 0x3F, 0x7C, 0xD3, 0xCE, 0x69, 0x96, 0xBB, 0x0E, 0x18, 0x45, 0x28, 0x3E, 0xDA, + 0x80, 0x88, 0x31, 0x4D, 0xAF, 0x79, 0xFA, 0x99, 0xC3, 0x65, 0x47, 0x65, 0x56, 0xC1, 0x04, 0x95, 0xA0, 0xCB, 0xF5, 0xA9, + 0x25, 0xC7, 0x51, 0x76, 0xF9, 0x18, 0xB1, 0xE5, 0x5B, 0x1B, 0x64, 0xCA, 0x95, 0xA4, 0x38, 0x22, 0x92, 0xCD, 0xAA, 0x48, + 0xD6, 0x3C, 0x96, 0x1F, 0x62, 0xB1, 0x5E, 0xFC, 0xE8, 0x14, 0x9C, 0x12, 0xD9, 0x71, 0x5C, 0xDC, 0xC0, 0xFB, 0x2D, 0x22, + 0xDA, 0x8B, 0xCE, 0x8A, 0x80, 0xEC, 0x65, 0xA3, 0x7D, 0xA5, 0xEB, 0x8B, 0x29, 0xE3, 0x6B, 0x52, 0x45, 0xB3, 0xCA, 0x8B, + 0x96, 0x51, 0x9D, 0x16, 0x59, 0x82, 0x75, 0x65, 0x40, 0xD9, 0xB0, 0xAF, 0x69, 0xA0, 0x9F, 0x31, 0x74, 0xF4, 0xB9, 0x7F, + 0xFA, 0x1C, 0xA7, 0xEA, 0x9D, 0xC2, 0x9E, 0x3F, 0x62, 0xCC, 0x48, 0x3F, 0xA4, 0xDB, 0x5C, 0x48, 0x28, 0x1F, 0xEF, 0x96, + 0x5E, 0xE1, 0x57, 0x0D, 0x91, 0x35, 0x46, 0x0B, 0x67, 0xE3, 0x43, 0x49, 0x5B, 0x1E, 0x23, 0xF6, 0x82, 0xD3, 0x65, 0xF9, + 0x69, 0xC0, 0x13, 0x17, 0xA4, 0xCD, 0x8B, 0x9B, 0x59, 0x80, 0x79, 0x3B, 0x87, 0x82, 0x0D, 0x69, 0x36, 0xC6, 0xB8, 0xDB, + 0xE5, 0x8E, 0x02, 0x57, 0x95, 0xB8, 0x17, 0x20, 0x67, 0xA4, 0xB0, 0x31, 0x4A, 0xE3, 0x10, 0x26, 0xC6, 0xC9, 0x70, 0x79, + 0x1D, 0xA5, 0x24, 0xA5, 0xEE, 0x2C, 0x15, 0x24, 0x81, 0xFA, 0xD7, 0x9D, 0xF2, 0x6D, 0xBA, 0x16, 0x4F, 0x65, 0x1E, 0xBE, + 0xC0, 0xC6, 0x8F, 0x35, 0x1B, 0xD0, 0x88, 0x44, 0x67, 0x4C, 0x5A, 0x1C, 0x03, 0x1B, 0xC5, 0xC0, 0xB2, 0x8D, 0xD3, 0xDC, + 0x2C, 0x2A, 0x01, 0x8D, 0x7A, 0x3F, 0xA1, 0xC6, 0x55, 0xEF, 0xB7, 0x13, 0x2E, 0xE9, 0x1D, 0xEC, 0x38, 0xA9, 0xCD, 0x6D, + 0xA5, 0x79, 0x4D, 0x2C, 0x50, 0xB4, 0x2A, 0x12, 0x6A, 0xA9, 0x12, 0xE1, 0x9F, 0x7D, 0x29, 0x3B, 0xA4, 0x58, 0x2F, 0xBA, + 0x58, 0x7A, 0xA5, 0xE3, 0xE3, 0x41, 0x26, 0x5A, 0xAF, 0xB8, 0xD4, 0xD8, 0xB4, 0x61, 0x0C, 0x61, 0xBF, 0x60, 0x83, 0x2E, + 0xA9, 0xC5, 0xF4, 0x7D, 0xE0, 0xA2, 0x97, 0xA8, 0xB5, 0xC1, 0x02, 0xDD, 0x5F, 0x3F, 0xE4, 0x38, 0xF1, 0xCE, 0x83, 0xA4, + 0xEF, 0xAF, 0x8D, 0xE8, 0x4B, 0xC8, 0x26, 0x1C, 0xFD, 0xAD, 0x3A, 0x53, 0x47, 0x00, 0x2A, 0x03, 0x10, 0xEF, 0x02, 0x01, + 0x41, 0xAF, 0xB0, 0xA1, 0xFC, 0xEB, 0xAA, 0xCD, 0x0E, 0x9E, 0x5D, 0xDA, 0x38, 0x00, 0xC8, 0x89, 0x62, 0x33, 0x93, 0x2B, + 0xD1, 0xE3, 0x94, 0xDF, 0xD0, 0xCC, 0x6F, 0x2F, 0x7E, 0xC3, 0x31, 0xC6, 0x4D, 0x87, 0x73, 0x9A, 0xBC, 0xCF, 0x5D, 0x79, + 0x4F, 0xEF, 0xE7, 0x7B, 0x30, 0xF2, 0x0F, 0x5C, 0x40, 0x04, 0x31, 0xD4, 0x9F, 0x66, 0xD3, 0x63, 0x9A, 0xA2, 0x14, 0x51, + 0xF7, 0x91, 0xFB, 0xF5, 0x9A, 0xBF, 0x01, 0xE9, 0xA1, 0x34, 0xE4, 0x99, 0x53, 0x26, 0x6A, 0x2C, 0x87, 0x22, 0x22, 0xBC, + 0x90, 0x90, 0x1E, 0xC9, 0x21, 0x0E, 0x7D, 0x6D, 0xA9, 0x38, 0xA5, 0x9B, 0xDE, 0x2A, 0x5B, 0x8F, 0x10, 0x75, 0x1A, 0x80, + 0x9E, 0x56, 0x3A, 0x51, 0x22, 0x3F, 0x74, 0x89, 0xCB, 0xC8, 0x27, 0xC2, 0xD9, 0x8F, 0xAE, 0xE7, 0xD5, 0xB5, 0x8F, 0x21, + 0xF9, 0x3E, 0x25, 0x2D, 0x44, 0xB5, 0x83, 0x76, 0x6F, 0xCD, 0xD4, 0xF1, 0xF6, 0xB1, 0x07, 0xD3, 0x47, 0x39, 0x4C, 0xB9, + 0x23, 0x1B, 0x5D, 0x18, 0x95, 0xD2, 0xDD, 0x85, 0x77, 0xF9, 0x0A, 0xDB, 0x4C, 0x01, 0x2D, 0xD6, 0x38, 0x4A, 0x22, 0xD3, + 0x94, 0xD7, 0xD5, 0x35, 0x9C, 0xF9, 0xDB, 0x9A, 0x47, 0xE7, 0x26, 0xFC, 0x0F, 0xD2, 0x21, 0xEA, 0x78, 0x9A, 0x96, 0x5F, + 0x9C, 0x78, 0x70, 0x75, 0x79, 0x9A, 0x71, 0x9F, 0x3B, 0x43, 0xDB, 0xC4, 0xFB, 0xD3, 0x9D, 0xAD, 0x09, 0x4D, 0xE7, 0x7A, + 0x13, 0x38, 0x5F, 0xC9, 0x8C, 0xFB, 0xF0, 0x98, 0x63, 0x27, 0x1F, 0x25, 0x34, 0x4B, 0x56, 0x60, 0xC6, 0xE4, 0xAC, 0xBB, + 0x69, 0x2A, 0xFD, 0x3F, 0xB3, 0xB7, 0xE1, 0xB0, 0xB9, 0xB5, 0xCD, 0xB0, 0xFB, 0x60, 0x0A, 0x5D, 0x2D, 0xB4, 0xA9, 0xEA, + 0x19, 0xD0, 0xB6, 0x6A, 0x50, 0x41, 0xC9, 0xED, 0x44, 0x38, 0xEF, 0xA1, 0xB2, 0x1B, 0xF5, 0x9A, 0x65, 0x7D, 0x96, 0xF9, + 0xFC, 0xF2, 0x58, 0x94, 0x7A, 0x5B, 0xE5, 0xD0, 0xAD, 0xBA, 0xB7, 0xA2, 0x90, 0x23, 0x9F, 0x2D, 0x7D, 0xBA, 0xEF, 0x2A, + 0x4F, 0xDF, 0x21, 0x1F, 0xBB, 0x4B, 0x68, 0x88, 0x97, 0xB3, 0x97, 0x9D, 0xD9, 0xFF, 0x60, 0x02, 0x79, 0x0D, 0x37, 0x05, + 0x9D, 0x2C, 0xB7, 0x26, 0x94, 0x24, 0xB8, 0xE6, 0x84, 0xA6, 0xCD, 0xF2, 0x32, 0xB1, 0x6E, 0x66, 0xFA, 0x87, 0xDC, 0xE0, + 0x4D, 0x47, 0xFE, 0xC5, 0x93, 0x21, 0x4B, 0x1C, 0x02, 0x01, 0xE9, 0x1B, 0x56, 0xD6, 0x29, 0xCE, 0xCE, 0x20, 0x36, 0xB2, + 0x31, 0xCD, 0xB1, 0xEF, 0x91, 0x4E, 0xD7, 0x87, 0x95, 0x8C, 0x91, 0xFC, 0x62, 0x3E, 0xE7, 0x03, 0x3A, 0x86, 0xF8, 0x07, + 0xC8, 0x4D, 0xA0, 0x03, 0x5D, 0x20, 0xAB, 0x90, 0x4A, 0x22, 0xEE, 0xA8, 0x32, 0xBB, 0x7A, 0xAE, 0xFE, 0xD4, 0x08, 0x59, + 0x13, 0x23, 0xF4, 0xE3, 0x26, 0x4F, 0xA0, 0x46, 0xAC, 0x7E, 0x03, 0x52, 0xE7, 0x09, 0x07, 0xC7, 0x1F, 0x8C, 0xAE, 0x13, + 0x39, 0xFB, 0x2E, 0x16, 0xC9, 0x92, 0xB2, 0x7E, 0xEA, 0x52, 0x61, 0x6C, 0x32, 0xD8, 0x1E, 0xF5, 0xDF, 0x3B, 0xE7, 0x06, + 0x70, 0x28, 0xFD, 0x8C, 0x17, 0x1C, 0x61, 0xFF, 0xC6, 0x83, 0x58, 0x3D, 0xCA, 0x4B, 0xCC, 0x1F, 0x48, 0xC7, 0x6A, 0xB8, + 0x11, 0x06, 0x21, 0x66, 0xCC, 0xD5, 0x56, 0xC8, 0x45, 0x46, 0xB9, 0x27, 0x81, 0xC2, 0x5A, 0x81, 0x2D, 0xF5, 0xE4, 0x05, + 0x73, 0xBC, 0x50, 0xCB, 0x4A, 0x02, 0xA1, 0x6B, 0x4A, 0xFE, 0x52, 0x90, 0xAB, 0x29, 0xB4, 0x42, 0x4D, 0xEE, 0x3C, 0x3F, + 0x19, 0x2F, 0x3E, 0xB5, 0x5E, 0x7D, 0xD8, 0x26, 0x2B, 0xDE, 0x76, 0x2E, 0x29, 0x06, 0x68, 0xEF, 0xB9, 0xC7, 0xD3, 0x13, + 0xFD, 0x2D, 0x30, 0x38, 0x45, 0xF1, 0x32, 0xDE, 0x9E, 0x9D, 0x60, 0xFC, 0x57, 0x31, 0x79, 0xDD, 0xFA, 0xD2, 0x83, 0x84, + 0x95, 0x91, 0x6C, 0xAB, 0x8A, 0xD3, 0x7B, 0x50, 0xCC, 0xDE, 0x83, 0x71, 0xB8, 0x68, 0x70, 0x06, 0xE8, 0x09, 0x0B, 0x50, + 0xB4, 0x6E, 0x61, 0xFE, 0x38, 0xE2, 0xC3, 0x44, 0xEC, 0x8A, 0xE8, 0x00, 0xDC, 0x30, 0xBC, 0xF4, 0x84, 0x39, 0xDA, 0xC0, + 0x34, 0xD1, 0x37, 0x32, 0xAC, 0x96, 0xEE, 0x8F, 0xEF, 0x9C, 0x8D, 0x09, 0x52, 0x22, 0x4E, 0xAE, 0x8A, 0x35, 0xFE, 0xB0, + 0x9A, 0xA7, 0xA9, 0xC3, 0x23, 0xC6, 0x05, 0xC2, 0x94, 0xC9, 0xE8, 0x52, 0x64, 0xDF, 0xAF, 0x56, 0x3A, 0xD9, 0x73, 0x02, + 0xCA, 0x95, 0x1A, 0x66, 0x35, 0xBE, 0x25, 0xD1, 0xE5, 0xF1, 0xE3, 0x2A, 0x9A, 0xC5, 0x7A, 0x04, 0xFC, 0xB9, 0x21, 0x3E, + 0x01, 0x13, 0x5E, 0xE4, 0x89, 0xF2, 0x09, 0xC6, 0x45, 0x54, 0x5A, 0x52, 0xA6, 0xAD, 0x0C, 0x1D, 0x88, 0x2E, 0xEE, 0xEF, + 0x8F, 0xFE, 0x1C, 0xA8, 0x70, 0x34, 0x09, 0x52, 0x01, 0x1C, 0x7D, 0xF4, 0x13, 0x49, 0x0B, 0x73, 0xE6, 0x82, 0x8A, 0x85, + 0x81, 0x00, 0x75, 0x96, 0x61, 0x95, 0x3C, 0xB3, 0x51, 0x27, 0x6B, 0xF5, 0x88, 0xD2, 0x7A, 0xB0, 0x74, 0x47, 0x86, 0x92, + 0xFE, 0xAC, 0xD4, 0x8E, 0xD3, 0x5C, 0xD8, 0xDB, 0x73, 0xDA, 0x97, 0x5F, 0xAA, 0xA4, 0x70, 0x02, 0xFC, 0x44, 0x19, 0x6F, + 0xBD, 0xB4, 0xF9, 0x78, 0x6B, 0xD2, 0x31, 0xA2, 0x9D, 0x8D, 0xE0, 0x78, 0x72, 0x0A, 0xBF, 0x73, 0xDB, 0x39, 0xE8, 0xDA, + 0xFB, 0x36, 0xAC, 0xF3, 0x25, 0xC7, 0xA4, 0xC6, 0x14, 0xE7, 0xDD, 0x9F, 0x52, 0x5F, 0x60, 0x88, 0xFA, 0xF4, 0x29, 0x4E, + 0x11, 0xD0, 0x0E, 0x50, 0xF7, 0xA1, 0x42, 0x0A, 0x14, 0x7D, 0xD6, 0xAE, 0xF8, 0x08, 0x7E, 0xFC, 0x49, 0x8C, 0x76, 0x9F, + 0xF5, 0xB2, 0x36, 0xF8, 0xBE, 0x0C, 0xFB, 0x70, 0xEC, 0x4B, 0xA9, 0x9E, 0xBA, 0x1E, 0xE8, 0x4B, 0x2A, 0x74, 0x9E, 0x63, + 0x1F, 0xBE, 0x74, 0xE6, 0x32, 0xF5, 0x6F, 0x16, 0x78, 0xAA, 0xC4, 0xAB, 0x69, 0x1F, 0x67, 0xE1, 0x3E, 0x8E, 0x0F, 0x67, + 0x10, 0xA4, 0x0B, 0x2D, 0x7A, 0xF7, 0x23, 0x64, 0x86, 0x83, 0x07, 0x31, 0x7F, 0x05, 0x08, 0xDD, 0x85, 0xA2, 0xE0, 0xB8, + 0xAF, 0xFC, 0x2F, 0x60, 0xA6, 0x85, 0x00, 0x9C, 0x81, 0x35, 0x58, 0x76, 0x16, 0xCE, 0xB9, 0x00, 0xBF, 0xF4, 0xA6, 0xE1, + 0x06, 0x81, 0x21, 0xF6, 0x74, 0xE2, 0xF5, 0xA6, 0x87, 0xE2, 0x0C, 0x6D, 0x30, 0x65, 0x28, 0x6C, 0x22, 0x85, 0x0C, 0x0C, + 0xFE, 0xD7, 0x86, 0x61, 0xCB, 0x49, 0xB1, 0x01, 0x25, 0xF3, 0xF5, 0xB1, 0x82, 0x09, 0xB0, 0xF6, 0x70, 0xA5, 0xEA, 0x5B, + 0x26, 0xC8, 0x2D, 0x06, 0x3D, 0x55, 0x50, 0xA9, 0x01, 0x5F, 0xFE, 0x34, 0xEC, 0x08, 0x58, 0xA9, 0x63, 0xAB, 0x27, 0x16, + 0x20, 0x93, 0x33, 0x5D, 0x6D, 0xE2, 0x35, 0xE2, 0x7F, 0x3C, 0xB1, 0x7B, 0x27, 0x76, 0xF5, 0x96, 0xA2, 0xE3, 0x96, 0xDF, + 0xD3, 0xF7, 0x24, 0xF2, 0x64, 0x2C, 0x39, 0x4C, 0xCF, 0xAB, 0x39, 0x2E, 0x1E, 0x3C, 0x72, 0x13, 0x6F, 0xA8, 0x22, 0xC8, + 0x8E, 0xAB, 0xB6, 0x0D, 0xEF, 0x7C, 0x00, 0x15, 0x23, 0xE8, 0xB7, 0xE2, 0x8D, 0x32, 0xC2, 0xDC, 0x9B, 0x5C, 0x70, 0x2F, + 0xCF, 0x81, 0x2A, 0xF9, 0x5F, 0x1C, 0x5B, 0xF7, 0x0C, 0x71, 0x40, 0xF4, 0xE3, 0xAA, 0x93, 0x31, 0x40, 0xC7, 0xDB, 0xED, + 0x5A, 0x1F, 0x30, 0x1F, 0x8E, 0x8F, 0x3B, 0x9D, 0x1D, 0x28, 0xA3, 0xD9, 0xE9, 0x66, 0xBF, 0x78, 0x5C, 0xE5, 0x42, 0x95, + 0x2A, 0x30, 0xFA, 0x77, 0xF5, 0xE8, 0x5A, 0xA8, 0x92, 0x88, 0x44, 0x93, 0x7F, 0x97, 0x20, 0x38, 0x64, 0x82, 0x4A, 0xA0, + 0xE6, 0x2C, 0x98, 0x69, 0xCB, 0x2B, 0x7C, 0xFA, 0x18, 0x45, 0xDC, 0x10, 0x0C, 0x8A, 0xB9, 0xDC, 0xEC, 0x5B, 0xD0, 0x6C, + 0x06, 0xAA, 0xC3, 0x83, 0xD6, 0x55, 0xEF, 0x69, 0x70, 0xE3, 0xF3, 0xA4, 0x6E, 0x2C, 0x44, 0x29, 0x8C, 0xC0, 0x20, 0x48, + 0xA0, 0xE6, 0x87, 0xB4, 0xF8, 0x75, 0x9C, 0xFA, 0x15, 0xF0, 0x94, 0xD0, 0x06, 0x04, 0x86, 0xA2, 0xF1, 0xE6, 0xAC, 0xD4, + 0xB7, 0x35, 0x94, 0x6A, 0xB5, 0x4A, 0xBC, 0xA3, 0x76, 0x7C, 0xE2, 0xB9, 0x71, 0xBF, 0x5B, 0xB0, 0xCF, 0x17, 0x09, 0xA3, + 0x49, 0xB9, 0x4B, 0xA4, 0x45, 0xDB, 0x14, 0xBD, 0x68, 0x46, 0xBE, 0x89, 0x6D, 0x62, 0xFD, 0x6E, 0xF5, 0x2C, 0x73, 0xD3, + 0xE1, 0x71, 0xDC, 0x17, 0x23, 0x4C, 0x1A, 0x9B, 0xCF, 0x4C, 0x4C, 0xFE, 0x30, 0x56, 0x74, 0x20, 0xE5, 0x92, 0x84, 0x09, + 0x8A, 0x3D, 0x52, 0x8B, 0x45, 0x6A, 0xB5, 0x81, 0x54, 0xF5, 0x24, 0x7F, 0xE8, 0xCE, 0x7B, 0x90, 0xC8, 0x78, 0x77, 0xB9, + 0x4D, 0x9F, 0x0B, 0x2F, 0x5B, 0xF9, 0xC2, 0xC7, 0x0F, 0x2E, 0x35, 0x3A, 0xE3, 0xED, 0x13, 0x0E, 0x83, 0xD5, 0x15, 0xDF, + 0xD4, 0xAD, 0x9B, 0x77, 0xF3, 0xB0, 0x83, 0xA2, 0x0F, 0x3E, 0x01, 0x7B, 0xB0, 0xF8, 0x66, 0x5F, 0x3A, 0x45, 0x78, 0xD9, + 0x7B, 0x5A, 0x69, 0xAE, 0xFF, 0xF6, 0x51, 0x67, 0x2D, 0x97, 0x3E, 0x59, 0x19, 0xD7, 0xD9, 0x7A, 0x69, 0x79, 0xE6, 0xAE, + 0x94, 0xB0, 0xCF, 0x01, 0x8E, 0x4C, 0x2C, 0xEF, 0xB8, 0xD6, 0xC8, 0xD8, 0xAB, 0xB6, 0x57, 0x90, 0xD8, 0x47, 0x47, 0x1D, + 0x51, 0xDA, 0xEF, 0xA0, 0xB5, 0xD7, 0xF5, 0x9F, 0x62, 0xD9, 0x9F, 0xAA, 0xCE, 0x7B, 0xF9, 0xE4, 0xD3, 0x3D, 0x1E, 0xBC, + 0x0D, 0x68, 0x3E, 0x6F, 0xEC, 0x90, 0x41, 0x9A, 0x78, 0x06, 0xCE, 0xA8, 0x4D, 0x67, 0x14, 0xAC, 0x0C, 0x3C, 0x1E, 0xBD, + 0x16, 0xC6, 0xC0, 0xBB, 0xDC, 0x7D, 0x5F, 0xFB, 0x8B, 0x31, 0x1D, 0xC7, 0x57, 0xB7, 0xF2, 0x6F, 0xF2, 0xDE, 0x3D, 0x6D, + 0xDC, 0xCE, 0x11, 0xDC, 0x4E, 0xF9, 0x17, 0x5B, 0xE4, 0xDF, 0x33, 0x7F, 0xF3, 0x74, 0x9F, 0x5F, 0xA3, 0xF0, 0x80, 0xD5, + 0x0C, 0x7B, 0x7B, 0xF5, 0x19, 0x20, 0x08, 0x35, 0x23, 0xBF, 0x94, 0xC6, 0xD2, 0x9C, 0x0E, 0xEC, 0xB1, 0x43, 0x58, 0x3A, + 0x3B, 0x94, 0x60, 0xB2, 0xC9, 0x10, 0xF8, 0x6B, 0xB6, 0xCC, 0x86, 0x73, 0x7B, 0xF9, 0xA7, 0xC9, 0x95, 0x57, 0x69, 0xA3, + 0x40, 0x8A, 0xEB, 0xD5, 0x03, 0x6D, 0xC2, 0xF2, 0x60, 0xAC, 0xDB, 0x2F, 0xBF, 0x63, 0x21, 0x83, 0xC9, 0xE1, 0x17, 0xD7, + 0x7D, 0xCE, 0xE0, 0xB6, 0x31, 0x93, 0xE0, 0x37, 0x36, 0x89, 0x9B, 0x29, 0xAB, 0x5D, 0x6F, 0x82, 0x76, 0x9B, 0xA8, 0x61, + 0xFE, 0x06, 0xC0, 0x51, 0x31, 0x15, 0xA4, 0xF4, 0x1C, 0x33, 0xA7, 0xF0, 0x42, 0xDC, 0xF9, 0xBE, 0xE2, 0xF9, 0xDF, 0x02, + 0x58, 0xEF, 0xFD, 0xF3, 0xD6, 0x4E, 0x69, 0x9F, 0xC2, 0x2B, 0xF7, 0x40, 0x93, 0x4A, 0x0A, 0xD1, 0xC8, 0x75, 0x99, 0xAD, + 0xCD, 0x46, 0x49, 0xF7, 0xF1, 0x95, 0x17, 0x7B, 0x30, 0x64, 0x55, 0xA2, 0x97, 0x2A, 0x28, 0xCA, 0x3F, 0x4C, 0x9B, 0xCE, + 0xFC, 0x5B, 0x50, 0x97, 0x61, 0x38, 0xE2, 0x02, 0xDF, 0xDD, 0xDA, 0xF5, 0xF9, 0xB4, 0x4E, 0xEC, 0xD8, 0xD1, 0x65, 0xD9, + 0x8B, 0x68, 0x34, 0x0C, 0x15, 0x26, 0xCC, 0x7C, 0xB3, 0x27, 0xA9, 0x88, 0x19, 0x09, 0xCB, 0xA5, 0x20, 0x06, 0x6D, 0xEC, + 0x53, 0x6B, 0x43, 0x2C, 0x36, 0x09, 0x60, 0x1B, 0xEF, 0xE6, 0x1B, 0x4E, 0xED, 0x4D, 0x92, 0x51, 0x52, 0x2F, 0x51, 0x6D, + 0x4C, 0xDF, 0xEA, 0xBC, 0xAD, 0x63, 0xE6, 0x1A, 0x88, 0xA6, 0x9A, 0xC8, 0x53, 0x6F, 0xDF, 0x7D, 0x4D, 0xBD, 0xA2, 0xFE, + 0x79, 0x9F, 0xAF, 0xC9, 0x76, 0x2E, 0x01, 0x5C, 0x1A, 0x3E, 0xDA, 0x2F, 0x9A, 0x4F, 0xB3, 0x29, 0x9D, 0xE3, 0xA9, 0x59, + 0x53, 0xE9, 0x04, 0xDF, 0x1B, 0x4F, 0xA5, 0xFD, 0xCB, 0x8F, 0xE3, 0xAD, 0x20, 0x60, 0xC4, 0x49, 0x37, 0x8B, 0xF3, 0xBE, + 0xC2, 0x3E, 0xB0, 0x32, 0x60, 0x8F, 0xC6, 0x20, 0x78, 0x06, 0xDE, 0x14, 0x1E, 0x11, 0x60, 0x14, 0xCD, 0x11, 0xE3, 0xC2, + 0x0B, 0x35, 0x79, 0xA7, 0x5F, 0x35, 0x21, 0x78, 0x00, 0xB9, 0xED, 0x03, 0x4C, 0x73, 0x85, 0xCE, 0x88, 0x16, 0x22, 0x14, + 0xF6, 0x52, 0xD4, 0x93, 0xDE, 0x33, 0x21, 0xD7, 0x32, 0xE7, 0xE6, 0xF6, 0x1C, 0xE5, 0xBB, 0x11, 0x7D, 0x7E, 0x2C, 0x02, + 0xA4, 0xE1, 0x06, 0x83, 0xF0, 0xB4, 0x9E, 0x10, 0x6E, 0x5B, 0xF3, 0x92, 0x81, 0xC9, 0x48, 0x97, 0xA2, 0x1B, 0xEC, 0xC4, + 0xCA, 0xB4, 0x8C, 0x0D, 0x22, 0x53, 0x85, 0xFE, 0x96, 0xCC, 0xD5, 0x06, 0xA0, 0xE3, 0x8D, 0xD5, 0xC1, 0x36, 0x6F, 0x1E, + 0xE4, 0xAC, 0x79, 0x7F, 0xF1, 0x04, 0x72, 0x83, 0xE0, 0x18, 0xB6, 0x2F, 0x42, 0x55, 0x7A, 0x9A, 0x02, 0x58, 0xC5, 0x71, + 0x90, 0x73, 0xC6, 0x59, 0xD4, 0x43, 0x64, 0x93, 0xF6, 0xB5, 0xAD, 0x32, 0x6B, 0x78, 0x22, 0x53, 0x7E, 0x58, 0x5D, 0x99, + 0x52, 0x19, 0x8C, 0x6F, 0xDD, 0x96, 0xB1, 0xC3, 0xB4, 0x18, 0x36, 0x1E, 0xFE, 0x5E, 0xB1, 0x64, 0x89, 0xB1, 0xF9, 0x1E, + 0xD3, 0xBC, 0x87, 0xF7, 0x19, 0x86, 0x72, 0x7E, 0x9E, 0x95, 0x54, 0x9B, 0xD6, 0x3B, 0x39, 0x6C, 0x51, 0x2B, 0xBC, 0x18, + 0x35, 0x18, 0x5F, 0x65, 0xD1, 0x3B, 0x4C, 0xC0, 0xC1, 0xBA, 0x02, 0x49, 0x79, 0xCE, 0xE2, 0x37, 0x99, 0x1D, 0xC1, 0x68, + 0x73, 0xA1, 0xFC, 0xC7, 0xC7, 0xB6, 0x3D, 0xCC, 0xA8, 0xC1, 0x0E, 0x4D, 0x2F, 0x5B, 0x96, 0xE8, 0xA6, 0xE0, 0x19, 0x52, + 0xBA, 0xCA, 0x58, 0xAD, 0xFA, 0xEE, 0x6D, 0x16, 0x1D, 0xE1, 0xEF, 0x17, 0x77, 0x88, 0x79, 0xDF, 0xC0, 0x9A, 0x74, 0x82, + 0x9F, 0x24, 0xFC, 0x45, 0x4A, 0xEE, 0x70, 0xA3, 0x02, 0xA3, 0x38, 0x13, 0xF8, 0xB1, 0xFE, 0x94, 0x10, 0x2D, 0xA7, 0x0A, + 0x42, 0x79, 0x64, 0x74, 0x7A, 0x6A, 0x3D, 0x10, 0xE0, 0x9A, 0xF6, 0x25, 0x01, 0x0E, 0x9B, 0x35, 0xF8, 0x70, 0x32, 0x6E, + 0xE9, 0x49, 0xE1, 0xCA, 0x30, 0x22, 0xDF, 0x31, 0x7F, 0x47, 0xF3, 0x07, 0x18, 0x86, 0x89, 0x7B, 0x2F, 0x46, 0x0F, 0xE7, + 0x7A, 0x2E, 0x9B, 0x51, 0x07, 0x37, 0xC6, 0x41, 0xB7, 0x1C, 0x39, 0xFB, 0xF5, 0x77, 0x3E, 0xD1, 0x1A, 0x09, 0x20, 0x9B, + 0xDE, 0xE6, 0xB0, 0xCB, 0x85, 0xC0, 0x90, 0xC6, 0x0C, 0x69, 0xCF, 0x65, 0x6C, 0x20, 0x09, 0xF0, 0x4F, 0xA4, 0x40, 0x22, + 0x43, 0xCA, 0xC0, 0xA6, 0x0B, 0xE3, 0x1F, 0xD1, 0x52, 0x43, 0x6A, 0x4A, 0x90, 0x7C, 0x9F, 0xE1, 0xE4, 0x34, 0x89, 0xE5, + 0x56, 0x5F, 0xED, 0xA2, 0x67, 0xA7, 0xEC, 0x53, 0xDF, 0x0E, 0x19, 0xD3, 0x9D, 0x4C, 0xA9, 0xFA, 0x74, 0xA5, 0x68, 0x6A, + 0x48, 0xB3, 0x81, 0x15, 0xC4, 0x03, 0xDE, 0x59, 0xC8, 0x3E, 0x62, 0x35, 0x72, 0xBC, 0xD0, 0x3E, 0x76, 0x89, 0xFA, 0x80, + 0xE6, 0x5C, 0x39, 0x55, 0xB2, 0x64, 0xF5, 0x29, 0x22, 0xA9, 0x8F, 0x6C, 0x01, 0xE8, 0x06, 0x87, 0x1B, 0xBC, 0x0D, 0x2C, + 0x1A, 0xC2, 0xE1, 0x20, 0xB6, 0xA8, 0x70, 0x19, 0xF2, 0xAB, 0x5C, 0x21, 0x6B, 0x1E, 0x9B, 0xA4, 0x32, 0x66, 0x7B, 0x3E, + 0x17, 0x1E, 0xCA, 0xC0, 0x9A, 0x18, 0x72, 0x3C, 0xE9, 0x27, 0x76, 0x88, 0xCC, 0xCF, 0x3F, 0xAF, 0x58, 0x6C, 0x2B, 0x9C, + 0x9D, 0x8E, 0xD0, 0xEE, 0x9E, 0x02, 0x02, 0xF8, 0x6D, 0x1F, 0xB4, 0x5A, 0x20, 0x12, 0xC6, 0x50, 0xE5, 0xFA, 0x64, 0x73, + 0x75, 0xEA, 0xB4, 0x09, 0x8F, 0xEE, 0x57, 0xFE, 0x95, 0x44, 0x88, 0xA0, 0xF0, 0x8F, 0x4F, 0x3D, 0x64, 0xA6, 0x41, 0x99, + 0x4D, 0x87, 0xC1, 0x81, 0x24, 0xF4, 0xE4, 0x83, 0x35, 0x4B, 0xDA, 0xB4, 0xB1, 0xA6, 0x0A, 0x6E, 0xBC, 0xDF, 0x7B, 0xE1, + 0x56, 0x73, 0xEC, 0x6B, 0x04, 0x0A, 0x8F, 0x89, 0xED, 0x1A, 0x02, 0x50, 0x4B, 0x0E, 0x7C, 0xF6, 0xA7, 0x7C, 0x01, 0x7E, + 0x04, 0xE9, 0x0A, 0xFC, 0x69, 0x1D, 0x07, 0x92, 0x45, 0x2D, 0x26, 0x23, 0xB5, 0xE9, 0x9B, 0x97, 0xBE, 0xAC, 0x08, 0x1F, + 0x32, 0xA5, 0x82, 0x83, 0xC4, 0x7C, 0xDD, 0xF5, 0xE1, 0xFC, 0x66, 0x84, 0xB4, 0xC0, 0x48, 0xA0, 0xC1, 0xA4, 0x0B, 0x60, + 0xB2, 0x07, 0xF3, 0xE4, 0xA5, 0x08, 0xC9, 0x4A, 0xA0, 0x83, 0x22, 0xD1, 0x04, 0xD9, 0xD0, 0x68, 0x64, 0x17, 0xF4, 0x59, + 0x96, 0xFA, 0x46, 0xCC, 0x7E, 0x3D, 0x5D, 0x2F, 0x7E, 0xF4, 0x4D, 0xDA, 0x15, 0x6B, 0x4E, 0xB8, 0xD2, 0xF0, 0x3D, 0x4D, + 0x5C, 0x6C, 0x56, 0x31, 0xA7, 0x4A, 0xD0, 0x88, 0x7A, 0x67, 0x9D, 0xB7, 0x41, 0xFA, 0x46, 0x88, 0x2D, 0x95, 0xF6, 0x10, + 0xC7, 0x6D, 0x64, 0xD4, 0x0E, 0xFD, 0x76, 0xB3, 0x37, 0xBA, 0xFC, 0x34, 0xAF, 0x9D, 0xC6, 0x18, 0xC1, 0xF8, 0xA9, 0x49, + 0xE9, 0x52, 0xB8, 0x56, 0x72, 0xB4, 0x5D, 0xEB, 0xAA, 0xD8, 0x54, 0xB0, 0x42, 0xB4, 0x49, 0x0E, 0x8F, 0xD3, 0xE7, 0x51, + 0xDE, 0xB9, 0x27, 0xF9, 0xCC, 0xCE, 0xCF, 0xC0, 0x1E, 0x30, 0x59, 0x07, 0x11, 0x9F, 0xA7, 0xAF, 0x1C, 0xE0, 0x66, 0x08, + 0xAD, 0xDA, 0x1E, 0xC6, 0x9B, 0x63, 0x2C, 0xBE, 0x52, 0x73, 0xBC, 0x10, 0xDD, 0xF1, 0xA0, 0x5E, 0x7C, 0x0E, 0x2E, 0x0B, + 0xB3, 0xA6, 0x00, 0xFD, 0xCE, 0x2C, 0xF6, 0x54, 0x8A, 0xF2, 0xD0, 0xEF, 0xA8, 0x07, 0xE6, 0xA9, 0x8D, 0x5A, 0xD7, 0x99, + 0x8C, 0xD2, 0xBD, 0xF2, 0x5D, 0xF8, 0x7F, 0xDF, 0xBB, 0xDD, 0xC1, 0xA1, 0x18, 0xAF, 0x80, 0x89, 0x99, 0x00, 0x4B, 0x80, + 0x5C, 0xBE, 0xA7, 0x28, 0x33, 0x22, 0xF8, 0xB4, 0xE0, 0x8F, 0xD0, 0x79, 0x6E, 0x01, 0x5F, 0x63, 0xB1, 0xCF, 0x98, 0x63, + 0x31, 0x0A, 0x48, 0x58, 0x08, 0xD5, 0x02, 0x31, 0x62, 0x20, 0x38, 0xC2, 0x26, 0xBD, 0xB9, 0x70, 0xB0, 0x0B, 0x25, 0x21, + 0x4C, 0xC1, 0x71, 0x3F, 0x7D, 0x4F, 0x1E, 0xD6, 0xDF, 0x79, 0x0A, 0xF9, 0xD3, 0x4E, 0xD8, 0x6A, 0xEE, 0x23, 0x67, 0x18, + 0x28, 0x72, 0x46, 0xE4, 0xEE, 0x93, 0x93, 0x2F, 0x23, 0x76, 0x1B, 0x45, 0x71, 0x8F, 0x90, 0xF5, 0x95, 0x06, 0x6A, 0xEC, + 0xA7, 0xAB, 0x36, 0x56, 0xE2, 0xA6, 0x9A, 0x4A, 0xF8, 0x41, 0x58, 0x70, 0xA2, 0x5E, 0xE2, 0x8E, 0xA8, 0x1E, 0x84, 0x32, + 0xF4, 0x77, 0x52, 0xB6, 0x16, 0xAB, 0x53, 0x66, 0xC2, 0x46, 0xD0, 0x1A, 0x35, 0x27, 0x1E, 0xA2, 0x0F, 0x0A, 0xF1, 0xAE, + 0x6E, 0x4B, 0xB5, 0x97, 0xF0, 0x2A, 0x99, 0x99, 0xBF, 0x58, 0x5C, 0xEA, 0x76, 0x8D, 0x79, 0xAC, 0x12, 0x5A, 0xBE, 0xBB, + 0x4B, 0x42, 0xED, 0xA8, 0x0F, 0x47, 0x08, 0xE5, 0x89, 0xD2, 0x5C, 0xE3, 0x1F, 0x71, 0x0F, 0xBC, 0x3F, 0x91, 0x47, 0x21, + 0xB8, 0xD6, 0xFC, 0x37, 0x2B, 0x0E, 0xDA, 0x2D, 0x3D, 0x8B, 0xD2, 0xD9, 0x56, 0xEB, 0x48, 0x6A, 0xA7, 0x50, 0x8B, 0x9D, + 0xDA, 0xCB, 0x86, 0x46, 0x64, 0x97, 0x03, 0x20, 0x35, 0x7A, 0x5B, 0xE1, 0x72, 0xB0, 0xBD, 0x3B, 0x78, 0x7D, 0xA5, 0x0C, + 0x5A, 0xFC, 0xAA, 0x4C, 0x9F, 0xB1, 0xAB, 0xE8, 0x5E, 0x52, 0x9F, 0xAB, 0x87, 0xF0, 0xE2, 0x60, 0xF0, 0x69, 0xA1, 0x0B, + 0x22, 0x44, 0x87, 0x74, 0x68, 0x6D, 0x3D, 0x4F, 0x6B, 0xAD, 0x30, 0x59, 0x27, 0xA5, 0xF8, 0x1A, 0xA3, 0x9F, 0x0E, 0x54, + 0xED, 0x19, 0x33, 0x5B, 0x2E, 0x4E, 0xF1, 0xED, 0x4F, 0x80, 0x1F, 0x89, 0x8E, 0x9E, 0x1B, 0x20, 0x81, 0x69, 0x00, 0x0F, + 0xDC, 0x93, 0x7B, 0xF6, 0x46, 0xEF, 0xD4, 0xE7, 0x81, 0xA6, 0x54, 0x18, 0x71, 0xFB, 0xF3, 0x14, 0x29, 0x67, 0x33, 0x72, + 0x51, 0x33, 0x3C, 0x04, 0xC2, 0x34, 0x3C, 0xC6, 0x13, 0x64, 0xC5, 0x80, 0x3E, 0x9F, 0xDC, 0x44, 0x17, 0x22, 0xEA, 0xD3, + 0x36, 0x54, 0x93, 0x94, 0x92, 0xDD, 0x62, 0x7A, 0x24, 0x14, 0xD4, 0xCC, 0x16, 0xBE, 0xA2, 0x53, 0x96, 0x57, 0xE3, 0xB2, + 0x18, 0x23, 0xBB, 0xA2, 0x02, 0x19, 0x08, 0xD5, 0x0A, 0x30, 0xAB, 0x93, 0x25, 0x38, 0x50, 0x19, 0xC6, 0x35, 0x16, 0xA4, + 0x5B, 0x57, 0x6C, 0xA6, 0x90, 0x33, 0x96, 0x83, 0x2C, 0x5C, 0x07, 0xD7, 0x0C, 0x7C, 0x38, 0xE5, 0x43, 0xA9, 0x7D, 0xE1, + 0x30, 0x7E, 0xB2, 0x21, 0xE6, 0xF6, 0x7A, 0x9E, 0x2F, 0x37, 0x41, 0x3F, 0x02, 0xBC, 0x1D, 0x91, 0x10, 0x52, 0xDD, 0x60, + 0xAC, 0xFA, 0x00, 0xDD, 0x98, 0x7F, 0xEE, 0x2B, 0x2E, 0x82, 0x55, 0x04, 0x9F, 0x78, 0xC9, 0x00, 0x1B, 0x5C, 0xEE, 0x88, + 0xF9, 0x75, 0x5E, 0x1D, 0x19, 0x1F, 0xE0, 0xB8, 0xE9, 0x1A, 0x9E, 0x71, 0xD2, 0x5F, 0xB6, 0xBA, 0xF8, 0x77, 0x13, 0x8D, + 0xF7, 0x76, 0x89, 0x7F, 0xBE, 0xA0, 0x48, 0x09, 0xD7, 0x4A, 0xBF, 0x4F, 0x79, 0x1E, 0x2F, 0x68, 0x08, 0xE4, 0xA8, 0x39, + 0xBF, 0x81, 0x13, 0xBE, 0x48, 0xD3, 0xC1, 0x7F, 0xEB, 0x39, 0x3E, 0xDD, 0xCA, 0xC9, 0xBE, 0x4E, 0x3F, 0x87, 0x1B, 0x78, + 0x95, 0xF1, 0x47, 0xD7, 0x29, 0xE9, 0xE2, 0x5D, 0xFE, 0x7F, 0x1E, 0x8C, 0x1F, 0xB6, 0xDE, 0xE9, 0x78, 0x1C, 0xF8, 0xD4, + 0x70, 0xD9, 0x3F, 0x21, 0xA6, 0xC2, 0x9D, 0xC9, 0x19, 0x38, 0x1E, 0xAE, 0x34, 0x54, 0x1A, 0x69, 0xF1, 0x05, 0x26, 0x32, + 0x54, 0x94, 0x41, 0xE1, 0x50, 0x7B, 0x61, 0x8D, 0x54, 0xE2, 0xCA, 0x39, 0xC8, 0xD4, 0x40, 0x42, 0xEA, 0x0B, 0x9F, 0xF8, + 0xFD, 0xB3, 0xF0, 0xEF, 0xF5, 0x82, 0x1B, 0xDB, 0x35, 0x9B, 0x16, 0x3A, 0xA2, 0xC0, 0xCF, 0x56, 0x55, 0xDC, 0xB8, 0xFB, + 0xF1, 0x61, 0x73, 0xD5, 0x89, 0x62, 0x25, 0xE1, 0xB7, 0xA0, 0x5C, 0x68, 0x6B, 0xCC, 0xF8, 0x94, 0x38, 0xF3, 0x36, 0x55, + 0x2F, 0xA2, 0x8A, 0xB6, 0x59, 0x00, 0x52, 0x6C, 0x6A, 0xE2, 0x2C, 0x31, 0x1A, 0x82, 0x79, 0x13, 0x0F, 0xF8, 0x00, 0x1D, + 0xB9, 0x79, 0x44, 0x24, 0xE9, 0xE5, 0x0E, 0x64, 0xA7, 0x47, 0xA0, 0xF2, 0xB7, 0xEB, 0x57, 0xB0, 0x85, 0x79, 0xFD, 0x11, + 0xDD, 0xAF, 0x87, 0x00, 0xBC, 0x87, 0xD5, 0x0D, 0xCE, 0x68, 0x19, 0xC1, 0x5B, 0xD9, 0xDB, 0xB4, 0xAE, 0x0B, 0xD2, 0x90, + 0x4A, 0xCB, 0x45, 0x18, 0x75, 0xA7, 0x14, 0x3C, 0x24, 0x81, 0xA1, 0xC2, 0xF4, 0xD2, 0xB2, 0x8C, 0xC1, 0xBD, 0x86, 0x8D, + 0xCD, 0x1A, 0xE2, 0xD3, 0x98, 0x73, 0x1D, 0x6E, 0x30, 0x03, 0x52, 0x28, 0x2E, 0x43, 0x1E, 0xAA, 0x2A, 0x02, 0x10, 0xE5, + 0x0B, 0xA9, 0xD2, 0xF6, 0x95, 0xEB, 0xE5, 0x9A, 0x36, 0xA9, 0xB2, 0xD6, 0x94, 0xAB, 0xA3, 0x8F, 0x84, 0xFC, 0xDB, 0x2F, + 0x7C, 0x7F, 0x82, 0xC9, 0xBB, 0xCE, 0xA1, 0x64, 0xDA, 0x39, 0xCE, 0x24, 0xA3, 0xC9, 0xA8, 0xC4, 0xFD, 0xA3, 0x60, 0x3B, + 0xCB, 0x61, 0x68, 0xEA, 0xBD, 0x06, 0xCD, 0xA0, 0xE7, 0x14, 0xF4, 0x67, 0x18, 0x7F, 0xBF, 0x95, 0x35, 0x8C, 0xE7, 0xEA, + 0x42, 0x50, 0x30, 0x5B, 0xAC, 0x8E, 0xF2, 0x4B, 0xE7, 0x9C, 0x34, 0x1A, 0x4B, 0x6F, 0xA9, 0x84, 0xE6, 0xE6, 0x1B, 0xC9, + 0x8F, 0xF3, 0x23, 0x2D, 0x61, 0x21, 0xF3, 0xB7, 0x31, 0x63, 0xCB, 0x56, 0x25, 0x63, 0x94, 0xA0, 0x0D, 0x87, 0x2B, 0x23, + 0xF2, 0x0F, 0x35, 0x08, 0xD8, 0x4D, 0x87, 0x04, 0x8E, 0xE4, 0x0E, 0x07, 0x67, 0x70, 0x02, 0x7B, 0x14, 0xF2, 0x35, 0x40, + 0xE6, 0xD8, 0x7B, 0x29, 0xF6, 0xF8, 0xA9, 0x17, 0xA7, 0x25, 0x6C, 0x97, 0xAB, 0x44, 0x5C, 0xF2, 0x70, 0x53, 0xB0, 0xB1, + 0xD4, 0x79, 0x35, 0xE1, 0xF6, 0x93, 0xA1, 0x14, 0x48, 0x91, 0xB8, 0x53, 0xE0, 0xDD, 0x41, 0xD5, 0x57, 0xF4, 0x1E, 0xF1, + 0x84, 0x23, 0x7D, 0x13, 0xEE, 0x35, 0x45, 0x31, 0xE0, 0x22, 0xB9, 0x55, 0x76, 0xFD, 0xFE, 0xFB, 0x20, 0xBC, 0xDE, 0x76, + 0xE2, 0x1B, 0xE1, 0x0D, 0x87, 0xB7, 0xCA, 0xCA, 0xD1, 0xE4, 0x1B, 0x44, 0xFC, 0xD4, 0xA3, 0x32, 0x04, 0x8E, 0xC5, 0x82, + 0xE7, 0xCA, 0x43, 0xC7, 0xD6, 0x54, 0x9C, 0xBC, 0x05, 0x26, 0x41, 0xA5, 0x92, 0xF4, 0x8C, 0x9C, 0x6B, 0xA0, 0xCB, 0xCA, + 0x51, 0xB7, 0xB6, 0x40, 0xD8, 0x9E, 0x57, 0x2D, 0xA7, 0x7A, 0x27, 0xF1, 0x75, 0xDF, 0xC5, 0xC7, 0xB1, 0x58, 0xF9, 0x8F, + 0x2A, 0x69, 0x66, 0x56, 0x14, 0x23, 0x4E, 0x28, 0x69, 0x09, 0xDE, 0xA8, 0xFF, 0x9C, 0xF1, 0x9E, 0x2B, 0x68, 0x75, 0x41, + 0x3B, 0xA3, 0x46, 0xBE, 0x8D, 0x58, 0x6E, 0xA0, 0x43, 0x0D, 0x36, 0x0F, 0x8F, 0xF6, 0xE5, 0xFD, 0x47, 0x45, 0x0D, 0x49, + 0xC8, 0x71, 0xDF, 0x4D, 0x7F, 0xF7, 0x3E, 0x1F, 0x8F, 0x9B, 0xBC, 0x45, 0x5A, 0xFB, 0x37, 0x48, 0x69, 0x76, 0xEC, 0xA5, + 0x87, 0x4F, 0xA6, 0x62, 0x93, 0xDE, 0x99, 0x89, 0xC3, 0x0A, 0xF2, 0xD5, 0x0B, 0x9D, 0x56, 0x9C, 0x1C, 0x90, 0xAE, 0x4F, + 0x7F, 0x86, 0x42, 0xA5, 0xFD, 0xF3, 0x7C, 0x85, 0xB5, 0x22, 0x4A, 0x9C, 0x84, 0x98, 0xA1, 0xD6, 0x9D, 0x20, 0x98, 0xB1, + 0x6C, 0x21, 0xC8, 0xAC, 0x34, 0xD6, 0x89, 0xE8, 0x5F, 0x61, 0x42, 0x5F, 0xE1, 0x0F, 0xD4, 0x4D, 0xBF, 0xB7, 0xEF, 0x06, + 0xEF, 0x9E, 0xC7, 0x01, 0x53, 0xF2, 0xFF, 0xE8, 0x4B, 0x40, 0x0E, 0xE2, 0x34, 0xAD, 0x1C, 0x33, 0x13, 0x08, 0x70, 0x1B, + 0xA4, 0x91, 0xFE, 0x62, 0xA2, 0x07, 0x70, 0x52, 0x6D, 0x31, 0x98, 0x8D, 0xF7, 0x03, 0x27, 0x6A, 0xD6, 0xC6, 0x03, 0xDC, + 0x02, 0x0A, 0xFF, 0x78, 0xA3, 0x0C, 0xA6, 0x19, 0x34, 0x33, 0x26, 0x85, 0xF4, 0xBE, 0x01, 0xA7, 0x20, 0x89, 0x71, 0xFD, + 0x52, 0x6C, 0x56, 0xD5, 0xF2, 0x78, 0x31, 0x93, 0xD7, 0x92, 0xEC, 0x3F, 0xD8, 0xFB, 0x57, 0xBB, 0xF3, 0xA7, 0x90, 0xA0, + 0x42, 0x42, 0xAF, 0xE0, 0x45, 0xFA, 0xF6, 0x58, 0x8E, 0x88, 0x6C, 0x2F, 0xB0, 0x64, 0x20, 0x54, 0xA2, 0xDA, 0x18, 0x64, + 0xDF, 0xC7, 0xFA, 0xDB, 0x75, 0x05, 0x11, 0x5A, 0x16, 0x89, 0xD9, 0x66, 0xA1, 0xC6, 0x41, 0xE1, 0xCD, 0xAE, 0xAE, 0xAE, + 0x62, 0xD1, 0x6E, 0x7D, 0x95, 0x57, 0x1E, 0xF5, 0xDF, 0x3B, 0x97, 0xA4, 0x98, 0x26, 0xF9, 0xEA, 0xA9, 0x82, 0x83, 0xEA, + 0x08, 0x67, 0xA9, 0xDE, 0x58, 0xB5, 0xEB, 0x6A, 0xF2, 0x29, 0x6A, 0x58, 0xEB, 0xD4, 0x5A, 0x38, 0x9B, 0x2A, 0x02, 0x3D, + 0xB7, 0x29, 0xEA, 0xFA, 0xF3, 0x28, 0x84, 0x59, 0x89, 0x05, 0x2B, 0xAC, 0xF3, 0xF3, 0xE9, 0xAD, 0x98, 0x60, 0x53, 0x2C, + 0x46, 0x26, 0x73, 0x3E, 0x74, 0x04, 0xCA, 0xBD, 0xC1, 0x3B, 0x9F, 0x3D, 0x9A, 0xFC, 0xA5, 0xE1, 0x54, 0xED, 0xB9, 0x6C, + 0x2E, 0x4E, 0x70, 0xC8, 0x45, 0x50, 0x6A, 0x50, 0xB9, 0xF1, 0x12, 0xA1, 0x1F, 0x2E, 0x42, 0x3A, 0xE9, 0x58, 0xBF, 0xCD, + 0x4C, 0x80, 0xF5, 0x5C, 0xC9, 0x4E, 0x6B, 0x52, 0x7F, 0x6B, 0x09, 0xA9, 0x08, 0x0A, 0x74, 0x65, 0x9E, 0xD4, 0x0B, 0x9F, + 0x17, 0xD3, 0xD1, 0x6A, 0xEE, 0x3B, 0xCD, 0xA9, 0x74, 0x00, 0x00, 0xD9, 0x88, 0xC0, 0xDF, 0x0B, 0x68, 0x4C, 0xD3, 0xDA, + 0x7A, 0x90, 0x83, 0xC6, 0x78, 0x9D, 0x4B, 0x97, 0x36, 0x58, 0x2C, 0x70, 0x97, 0x5F, 0x9C, 0xA0, 0xFF, 0x31, 0x29, 0x66, + 0xA4, 0xF3, 0x3A, 0xF6, 0xC6, 0x37, 0x64, 0x97, 0x02, 0xA1, 0xC6, 0xB6, 0x0D, 0x33, 0x5C, 0x9B, 0x47, 0x09, 0xDD, 0xA1, + 0x32, 0x3A, 0xA1, 0xC3, 0xA3, 0x8D, 0x39, 0x81, 0x11, 0x8D, 0x73, 0xE0, 0x4A, 0x5A, 0x85, 0xA2, 0x10, 0x5F, 0x65, 0x33, + 0xE8, 0x8E, 0x91, 0xCB, 0x50, 0xAC, 0xC0, 0xC5, 0x26, 0xCE, 0xEB, 0x29, 0x30, 0xCF, 0x8B, 0x80, 0x15, 0x22, 0x25, 0x02, + 0x56, 0x38, 0xDC, 0x17, 0x21, 0xE0, 0x07, 0x37, 0xB1, 0xC9, 0x5B, 0xB3, 0x3F, 0x79, 0x93, 0x66, 0x57, 0x88, 0x70, 0x45, + 0xF1, 0xA1, 0xD6, 0x39, 0x94, 0x76, 0xD5, 0x20, 0x58, 0x7A, 0xA1, 0x18, 0xB2, 0x34, 0x49, 0x96, 0x22, 0x19, 0xB7, 0xA7, + 0x10, 0x43, 0xDC, 0xB2, 0xA3, 0x73, 0xCF, 0xE0, 0x18, 0x8E, 0xAE, 0x81, 0xAD, 0x58, 0x65, 0xCB, 0xE6, 0x30, 0x2E, 0xF8, + 0x6C, 0x57, 0x3A, 0x29, 0xDB, 0x88, 0x3A, 0x65, 0x08, 0x62, 0x22, 0x5C, 0x9A, 0x78, 0xDE, 0xB5, 0x69, 0x5F, 0x57, 0xE8, + 0x4A, 0x69, 0xEF, 0x99, 0x8C, 0xC1, 0x03, 0x4A, 0x38, 0x1A, 0x87, 0x2B, 0x65, 0xD8, 0x60, 0xA1, 0x53, 0x3A, 0x9E, 0x68, + 0xA8, 0x0A, 0x63, 0xE2, 0x63, 0xE6, 0xB7, 0xB1, 0xDA, 0x71, 0x27, 0x4E, 0xB0, 0x6B, 0x46, 0x39, 0xE6, 0x3C, 0xCD, 0x21, + 0x32, 0x7C, 0x9A, 0xE8, 0xE3, 0x7D, 0x46, 0xEC, 0x7A, 0x7C, 0xF9, 0xFC, 0xA4, 0xB0, 0xB4, 0x2C, 0x33, 0x32, 0x20, 0x9C, + 0xE9, 0x55, 0xDE, 0xFC, 0x7B, 0x7D, 0x47, 0x0B, 0x29, 0x58, 0x0E, 0xED, 0x38, 0xC2, 0x57, 0x9B, 0x01, 0xF7, 0xD7, 0xED, + 0xFA, 0x7E, 0x87, 0x4A, 0x8A, 0xB2, 0xE9, 0x88, 0xEA, 0x7F, 0xAA, 0x1B, 0xAB, 0x50, 0xDF, 0xFD, 0xFB, 0x7F, 0xB0, 0x44, + 0xAE, 0x7B, 0xFA, 0x00, 0xB7, 0xC5, 0xF0, 0xFE, 0xFC, 0x81, 0x73, 0xE6, 0x0C, 0x55, 0xF7, 0x07, 0x82, 0x86, 0xF2, 0x15, + 0xB6, 0xC4, 0xC0, 0xB6, 0x12, 0xD6, 0x78, 0xFE, 0xBA, 0x3C, 0x27, 0x87, 0x8C, 0xF4, 0xFB, 0x47, 0x37, 0xE3, 0x68, 0x54, + 0x61, 0x42, 0x7A, 0x36, 0x83, 0x5F, 0x81, 0xB1, 0x5A, 0xDC, 0xF3, 0x55, 0x36, 0xE2, 0x60, 0x44, 0x60, 0xAD, 0xC1, 0x10, + 0x28, 0xEC, 0x00, 0x40, 0x43, 0x8B, 0xD8, 0xB8, 0xBA, 0xA9, 0x8F, 0x99, 0xC4, 0xC7, 0xCA, 0x84, 0xAB, 0xEB, 0xA8, 0x4A, + 0x0C, 0x8E, 0x65, 0xA6, 0x1B, 0xAA, 0xE8, 0xF0, 0x4E, 0x18, 0xE8, 0xF2, 0x5B, 0xA7, 0xF1, 0xC7, 0x99, 0x6F, 0x1E, 0x63, + 0x14, 0xAE, 0xF5, 0x93, 0xCE, 0xC9, 0x61, 0xE3, 0x86, 0x3B, 0xED, 0x57, 0xD4, 0x30, 0x89, 0x17, 0x82, 0x2A, 0x41, 0xA3, + 0x3C, 0xC8, 0x66, 0x6D, 0xF3, 0xE1, 0xCA, 0xA8, 0xA8, 0x0F, 0x62, 0xD7, 0x0A, 0xEF, 0x50, 0x22, 0x4D, 0xD8, 0x22, 0x0E, + 0x24, 0xEA, 0x3A, 0xAF, 0xE8, 0xC8, 0xA9, 0xEF, 0x74, 0x56, 0xF3, 0x42, 0xCA, 0xF8, 0xD8, 0x06, 0x4F, 0xA4, 0xC3, 0xBE, + 0x09, 0x8D, 0xA4, 0x7C, 0xF5, 0xA1, 0xF3, 0x07, 0x92, 0x88, 0x5F, 0xC7, 0x4D, 0xA7, 0xEB, 0x52, 0x26, 0xC7, 0x6B, 0xCB, + 0x75, 0xE9, 0xAB, 0xB9, 0xC4, 0x76, 0xA1, 0x3D, 0x1F, 0xCF, 0x95, 0x4B, 0x02, 0xCE, 0x9A, 0x6A, 0xC7, 0x51, 0x12, 0x2B, + 0xB7, 0xC1, 0x51, 0xD0, 0xFF, 0x53, 0xA7, 0x2F, 0x09, 0x1D, 0xEA, 0xA2, 0x39, 0xED, 0x21, 0xE9, 0x34, 0xC4, 0xC8, 0x38, + 0x71, 0x81, 0xA8, 0x60, 0xAA, 0xCC, 0xCC, 0xA2, 0xEE, 0x55, 0x79, 0x6A, 0x6D, 0x8F, 0x2C, 0x6E, 0xDA, 0x16, 0x27, 0x3B, + 0x83, 0x78, 0x20, 0xBC, 0x46, 0x52, 0xCE, 0xA3, 0x7B, 0xB5, 0xA1, 0x77, 0x01, 0xF4, 0x13, 0x5A, 0xD4, 0xEA, 0xC7, 0xC6, + 0x78, 0x4D, 0xF4, 0xAF, 0x60, 0xD6, 0x0C, 0x55, 0x31, 0xEB, 0x72, 0xE1, 0x15, 0xDE, 0x57, 0xB2, 0xB8, 0x0C, 0xE0, 0xB6, + 0x2C, 0x5E, 0xBD, 0xD0, 0x9E, 0xE9, 0xE5, 0x42, 0x9B, 0x89, 0xC2, 0x78, 0x41, 0x24, 0x19, 0xF4, 0xE2, 0xA2, 0x34, 0xC1, + 0x1F, 0x1A, 0x2C, 0xE0, 0x9D, 0xDC, 0x4A, 0x68, 0x44, 0x65, 0x63, 0x72, 0x65, 0x78, 0x2D, 0xC7, 0x75, 0xEC, 0xAB, 0xB2, + 0xA6, 0x8B, 0x2D, 0xE6, 0x7B, 0x78, 0x9C, 0xCC, 0x42, 0x29, 0xF4, 0xE6, 0x76, 0xF4, 0x0D, 0xF6, 0x14, 0x15, 0x62, 0x10, + 0x7A, 0xAB, 0xC3, 0x69, 0x98, 0x94, 0xFC, 0xF6, 0x77, 0xF5, 0x5B, 0x02, 0xC7, 0x92, 0x6B, 0x8C, 0xFB, 0x0A, 0x99, 0x78, + 0xE7, 0x56, 0xF5, 0xE7, 0xF6, 0xF6, 0xD5, 0x94, 0x6D, 0xDE, 0x63, 0x08, 0x4A, 0x13, 0xD1, 0x88, 0x39, 0x28, 0xFD, 0xF7, + 0xF7, 0xF7, 0xB6, 0x0E, 0x62, 0x85, 0x5D, 0xAA, 0xB3, 0xBA, 0xFE, 0xAA, 0x5F, 0x73, 0x88, 0x92, 0x1D, 0xFC, 0x3D, 0xFA, + 0x56, 0x90, 0xA6, 0xA8, 0x9C, 0x16, 0x64, 0x45, 0xCA, 0x54, 0xA8, 0xDC, 0x82, 0x54, 0x79, 0xA6, 0x66, 0x31, 0x10, 0x8E, + 0x31, 0xBC, 0x6D, 0x56, 0x4B, 0xCA, 0xD6, 0x8B, 0x15, 0xAB, 0x74, 0xB8, 0x65, 0xE1, 0x38, 0x8C, 0x62, 0xB8, 0x66, 0x6B, + 0x4A, 0xC0, 0xAA, 0x1A, 0x0A, 0xBA, 0x24, 0xD9, 0x4B, 0x93, 0x2F, 0x2C, 0xDE, 0x0D, 0xE6, 0xF5, 0xEA, 0x08, 0xF6, 0xEE, + 0x7E, 0xFC, 0x05, 0xFE, 0xAD, 0xD5, 0x15, 0xFA, 0xD6, 0x74, 0xBB, 0x81, 0xCC, 0xB8, 0xFE, 0xFE, 0x7F, 0xFD, 0x55, 0x30, + 0xA8, 0xC4, 0x18, 0xBD, 0xD4, 0xB1, 0xD3, 0x84, 0xCF, 0x1E, 0xF7, 0xEF, 0xFE, 0xFE, 0xA0, 0x2B, 0xA3, 0x90, 0xC9, 0xBB, + 0x1C, 0x3A, 0x5F, 0x0C, 0xCB, 0x52, 0xFF, 0xFF, 0x58, 0x62, 0xA8, 0xB5, 0xE1, 0x1B, 0x0B, 0x66, 0xD1, 0x42, 0x5A, 0xC2, + 0x73, 0x98, 0xC9, 0x27, 0xF5, 0xBF, 0xE0, 0x94, 0x86, 0x51, 0x4C, 0xB3, 0x97, 0x73, 0x9F, 0x20, 0x72, 0x17, 0xC1, 0xF0, + 0xF4, 0x97, 0xA1, 0xF7, 0x05, 0xA3, 0x45, 0x80, 0xD3, 0x02, 0xE9, 0x43, 0x01, 0xC8, 0x90, 0x43, 0x2F, 0x0C, 0x50, 0x8A, + 0x26, 0x05, 0xE9, 0x17, 0xCA, 0x2E, 0xE1, 0x57, 0x36, 0xCA, 0xD8, 0x53, 0x07, 0x69, 0x94, 0xAE, 0x31, 0x20, 0x09, 0x37, + 0x09, 0x80, 0x30, 0x62, 0x67, 0x49, 0x9D, 0x8E, 0xB3, 0x5F, 0xE4, 0xD5, 0xD6, 0x67, 0xB0, 0x99, 0xF8, 0xBF, 0x60, 0x56, + 0xAA, 0x03, 0xE0, 0xFD, 0xFC, 0x63, 0x81, 0x2C, 0x48, 0xDA, 0x08, 0xA7, 0x72, 0x82, 0x85, 0xE7, 0xD8, 0x23, 0xF0, 0x82, + 0x63, 0xC7, 0x20, 0xBA, 0x01, 0x6B, 0xA9, 0x57, 0xF8, 0x2A, 0x1D, 0x99, 0x5F, 0x8C, 0xFD, 0x69, 0x72, 0x61, 0x2A, 0x66, + 0xAB, 0x6D, 0xC8, 0x11, 0x2B, 0x2D, 0x16, 0x48, 0x0C, 0x95, 0x97, 0x53, 0x38, 0x6A, 0x95, 0xF5, 0x1E, 0xB2, 0xD0, 0x0C, + 0xBE, 0x2F, 0x18, 0xD0, 0xDF, 0xB4, 0xDB, 0xDA, 0x6A, 0x43, 0x7B, 0xF5, 0x05, 0xF1, 0x7B, 0x6B, 0xBB, 0x4A, 0xFF, 0xBA, + 0xF4, 0x42, 0x92, 0xCB, 0x39, 0xB9, 0xF4, 0x9D, 0xDE, 0x24, 0xAB, 0xDC, 0x38, 0x30, 0xE3, 0xC5, 0x44, 0xB0, 0x23, 0xC3, + 0xC9, 0x26, 0x0C, 0xCC, 0x37, 0xA3, 0xE8, 0xC9, 0x59, 0xCC, 0x56, 0x80, 0x1C, 0x01, 0x71, 0x72, 0x5C, 0x15, 0x2C, 0x06, + 0x86, 0x6F, 0x03, 0x9B, 0xD9, 0xFD, 0xFF, 0x6C, 0x6B, 0x6F, 0xE2, 0x8D, 0xF8, 0xED, 0x1A, 0x88, 0x8C, 0x77, 0xD3, 0x2F, + 0xFC, 0x83, 0xAC, 0x09, 0xC6, 0x55, 0x65, 0xEF, 0x52, 0x9E, 0xE0, 0xDC, 0x18, 0x30, 0x83, 0x60, 0xA8, 0xCD, 0x5E, 0x0A, + 0xF6, 0xEE, 0xE9, 0x82, 0x59, 0xBB, 0x5D, 0xA5, 0x43, 0x70, 0x7C, 0x06, 0xB0, 0xE6, 0xCB, 0xD0, 0x5F, 0xA0, 0x95, 0xC2, + 0x8B, 0x76, 0x86, 0x68, 0xA1, 0xAA, 0x8A, 0x7D, 0xB5, 0x73, 0x60, 0x32, 0xE1, 0x5B, 0x28, 0xCF, 0xD2, 0x6A, 0xFD, 0x7D, + 0x28, 0xE9, 0xBD, 0x55, 0xEC, 0x3B, 0x2F, 0x5A, 0xE6, 0x88, 0x3D, 0xAD, 0x01, 0x7D, 0x04, 0x7C, 0xE1, 0x51, 0x10, 0xFF, + 0x82, 0x19, 0x25, 0x80, 0x40, 0xF2, 0x96, 0xD3, 0x46, 0x63, 0x2D, 0x2B, 0xDD, 0x12, 0x1B, 0x8C, 0x45, 0x30, 0x44, 0x69, + 0x3A, 0xF0, 0x77, 0x4A, 0xD3, 0x7F, 0xF8, 0xAF, 0x80, 0xCE, 0xE8, 0xEC, 0x35, 0xB5, 0xF0, 0x63, 0x5E, 0x5F, 0xD9, 0x76, + 0xA7, 0x22, 0xED, 0xD8, 0x57, 0x19, 0x05, 0x14, 0xB4, 0x30, 0xCC, 0x95, 0x0B, 0x0F, 0x55, 0xC2, 0x53, 0x7D, 0xEE, 0x2C, + 0x3E, 0x8C, 0x50, 0x57, 0x33, 0x9C, 0xD9, 0xE2, 0xDE, 0x9E, 0xDF, 0x17, 0x5F, 0xFC, 0x4B, 0x63, 0x5F, 0x3C, 0xBC, 0x6A, + 0x28, 0xB3, 0x2E, 0x5B, 0x33, 0x36, 0x2E, 0x43, 0xFA, 0x54, 0x34, 0x63, 0x2F, 0xC3, 0x69, 0xFE, 0x7A, 0xC9, 0x7E, 0xBA, + 0x02, 0x54, 0x23, 0x5E, 0xFB, 0x35, 0xD8, 0xD1, 0x97, 0x90, 0xDF, 0x6B, 0x3A, 0x3E, 0x75, 0x39, 0xE9, 0xEA, 0x39, 0xC3, + 0x5B, 0x1F, 0x73, 0x1D, 0xDC, 0x79, 0x97, 0x8C, 0x82, 0x71, 0x35, 0x69, 0xB5, 0x58, 0x1A, 0xC3, 0x5A, 0x1E, 0x66, 0x31, + 0xE1, 0x67, 0xFE, 0x9E, 0x34, 0xB6, 0x70, 0x85, 0x56, 0xF1, 0xDE, 0x0E, 0xF8, 0x78, 0x95, 0x86, 0x54, 0xFC, 0xF0, 0x04, + 0x72, 0x47, 0x56, 0xFD, 0xA3, 0x04, 0x1A, 0x79, 0x38, 0x8F, 0x57, 0x4D, 0xB1, 0x21, 0x41, 0x48, 0x3C, 0x3E, 0xCE, 0xAE, + 0x20, 0x27, 0xD8, 0x8F, 0x05, 0x1C, 0x14, 0xDB, 0xD0, 0xF8, 0xD7, 0xD0, 0x34, 0x92, 0xCA, 0x8A, 0xD7, 0xFE, 0x1B, 0x7B, + 0xBF, 0x79, 0x1A, 0xEA, 0x84, 0x4F, 0x80, 0xE0, 0xF5, 0xBB, 0xF2, 0xCF, 0x36, 0x7B, 0x4F, 0x61, 0x67, 0x58, 0x71, 0x31, + 0xA2, 0x2E, 0xBB, 0xF4, 0x97, 0xED, 0xE3, 0x74, 0x3A, 0x3B, 0x5B, 0xF6, 0x1D, 0x3C, 0x20, 0xF5, 0x6F, 0x88, 0x44, 0xE1, + 0x16, 0x8E, 0xCE, 0xA7, 0x93, 0xED, 0x09, 0xB8, 0xC6, 0xAF, 0xE5, 0x55, 0xD3, 0x85, 0xA6, 0xF5, 0x17, 0x2F, 0xE4, 0x8B, + 0xBE, 0x3C, 0x41, 0x3F, 0x28, 0xAC, 0x9F, 0xC0, 0x83, 0x35, 0x58, 0xB9, 0xFF, 0xFE, 0xE9, 0x91, 0x73, 0x49, 0x01, 0xE2, + 0x6B, 0x71, 0x10, 0x21, 0x3B, 0x04, 0xD0, 0x06, 0x37, 0xAA, 0xE3, 0x10, 0xB0, 0xA7, 0x80, 0x51, 0x34, 0xED, 0xDA, 0xA1, + 0x2A, 0x7B, 0x4D, 0xD8, 0x95, 0x07, 0x0F, 0x0E, 0x44, 0xC2, 0x91, 0x79, 0x4A, 0x6B, 0x6B, 0xAC, 0x66, 0xE4, 0x32, 0x55, + 0xE8, 0x4F, 0xBD, 0xA3, 0x99, 0x68, 0x81, 0xF5, 0x03, 0x33, 0x8E, 0xCE, 0xAF, 0x8E, 0xB0, 0x7D, 0x47, 0xA7, 0xF2, 0xF6, + 0xE7, 0x13, 0xEB, 0x2D, 0xF9, 0x37, 0x6B, 0x5C, 0x1D, 0xC5, 0x25, 0xF6, 0x95, 0x24, 0xBD, 0x48, 0xB6, 0x8B, 0xF8, 0xBA, + 0x60, 0x46, 0x8B, 0x07, 0x2F, 0xC6, 0x99, 0xF0, 0x9A, 0x8B, 0x9F, 0xD6, 0xD7, 0xB1, 0xB2, 0x49, 0x5E, 0x86, 0xAF, 0xF3, + 0x8D, 0xC4, 0x53, 0x17, 0xFE, 0xA3, 0xF0, 0xD8, 0xBA, 0x17, 0xE2, 0xFE, 0x78, 0x74, 0x99, 0xA2, 0x5F, 0xC1, 0xBD, 0x28, + 0x18, 0xD6, 0xE8, 0x82, 0x12, 0x61, 0xCA, 0x8E, 0x5A, 0x89, 0xAA, 0x37, 0xAF, 0x51, 0x8A, 0x5D, 0x27, 0xA2, 0x32, 0x6E, + 0x7C, 0x1F, 0x59, 0x60, 0xFC, 0x88, 0x18, 0x43, 0x2B, 0x31, 0xD2, 0x30, 0x7D, 0x2E, 0x6E, 0x8D, 0x43, 0x38, 0xCB, 0x8F, + 0xCE, 0xE8, 0xC7, 0xDE, 0x5A, 0xED, 0xB4, 0xBE, 0xEC, 0xAF, 0xC3, 0x93, 0x93, 0x80, 0xA1, 0x97, 0x7C, 0xE9, 0xE4, 0x5A, + 0xB8, 0x96, 0x64, 0xEB, 0x85, 0xAB, 0x0C, 0xA7, 0x0F, 0x6A, 0x0B, 0x44, 0xF6, 0x9C, 0xE8, 0x42, 0x5B, 0xF3, 0xF6, 0xD4, + 0x92, 0xB7, 0x04, 0xE0, 0x6B, 0xB3, 0x83, 0x54, 0xF7, 0x9D, 0x05, 0xDA, 0x05, 0xF0, 0xAE, 0xF5, 0x13, 0xA2, 0x77, 0x21, + 0x64, 0xD8, 0xAA, 0xDD, 0x57, 0x97, 0xCD, 0x0A, 0x27, 0x97, 0x8D, 0x08, 0x14, 0x3F, 0x77, 0xB6, 0x1A, 0xD5, 0x73, 0xD9, + 0x56, 0x96, 0xB9, 0x5E, 0x20, 0xAE, 0xAF, 0x54, 0xC7, 0x19, 0xEE, 0x72, 0x8D, 0xA5, 0xD4, 0xAF, 0xD7, 0x2B, 0x54, 0x02, + 0x79, 0x3A, 0x6D, 0x54, 0xBF, 0xE4, 0x25, 0xE2, 0xC0, 0x78, 0xF2, 0x72, 0x06, 0xC5, 0x18, 0x41, 0x26, 0xDF, 0x28, 0x55, + 0xF6, 0xBE, 0x53, 0x97, 0x45, 0x52, 0x95, 0xE5, 0xE7, 0xED, 0xF4, 0xF4, 0x06, 0x1D, 0xD5, 0xB7, 0xB3, 0x97, 0xE4, 0xC2, + 0xDA, 0x78, 0x9D, 0xF5, 0xEA, 0xFA, 0x2D, 0xE8, 0x1F, 0x8E, 0xEC, 0x93, 0x1D, 0x28, 0xA9, 0x6C, 0xE2, 0xC3, 0x0B, 0x4C, + 0xFE, 0xFC, 0x16, 0x4A, 0x71, 0x36, 0x96, 0x77, 0x64, 0xD6, 0x38, 0xC9, 0x36, 0xB5, 0xF4, 0xA3, 0x96, 0x88, 0xDF, 0x09, + 0x2C, 0x62, 0x9F, 0x5F, 0x1F, 0x1B, 0x54, 0x4D, 0x12, 0xBA, 0x87, 0xCD, 0x03, 0x76, 0xBA, 0x8B, 0x52, 0x17, 0x95, 0x3A, + 0xA7, 0xD4, 0xFB, 0x5D, 0x6F, 0xDF, 0xAD, 0xAF, 0x42, 0x76, 0xA1, 0x39, 0x13, 0xF9, 0xE8, 0xCC, 0xD9, 0x11, 0x3B, 0x02, + 0x20, 0x93, 0x0D, 0x6C, 0xFE, 0xA4, 0x73, 0xB8, 0xEE, 0x17, 0x4C, 0x39, 0x8E, 0x1C, 0x63, 0x09, 0x78, 0x9F, 0xFB, 0x7C, + 0xFF, 0x27, 0x5F, 0x1B, 0xF2, 0x31, 0x2E, 0x25, 0x5F, 0x85, 0x2E, 0x77, 0x4B, 0x7F, 0xAE, 0xA7, 0xF8, 0x67, 0xE8, 0x33, + 0xF9, 0xD0, 0xD7, 0x56, 0x10, 0x12, 0x66, 0xFB, 0xE9, 0xB5, 0xC7, 0x7D, 0x01, 0x60, 0x78, 0x82, 0x80, 0x29, 0x38, 0x24, + 0x1A, 0x30, 0xEA, 0x53, 0x78, 0x2C, 0x50, 0x31, 0xFD, 0x22, 0x70, 0x56, 0xFD, 0x4D, 0xB2, 0xEF, 0x91, 0xE1, 0x26, 0x1C, + 0x8B, 0xA8, 0x98, 0xB6, 0x85, 0x3A, 0x39, 0x83, 0x01, 0x32, 0xFF, 0x50, 0x2C, 0x1B, 0x77, 0x54, 0xC1, 0x20, 0xD0, 0x25, + 0xD6, 0x7A, 0xCC, 0x95, 0x98, 0x2C, 0xF7, 0x40, 0x2D, 0x1A, 0x11, 0x28, 0x24, 0xBC, 0xA1, 0x72, 0x1B, 0x8A, 0x60, 0x5D, + 0x31, 0x50, 0x5B, 0xA4, 0x54, 0xD9, 0x28, 0xE2, 0xCF, 0x1D, 0x0E, 0x94, 0x6E, 0x6B, 0xC0, 0x32, 0x8E, 0xF3, 0xD7, 0xD6, + 0x93, 0xB4, 0x78, 0x9E, 0xE2, 0xC9, 0x92, 0x23, 0x12, 0x75, 0xFB, 0xBE, 0x00, 0xD2, 0xB3, 0x4F, 0x96, 0x89, 0x29, 0x46, + 0x61, 0x40, 0xB1, 0x05, 0xAE, 0x6B, 0x41, 0x54, 0x7E, 0x85, 0xF1, 0xE7, 0x5F, 0x17, 0x13, 0x6C, 0x41, 0x2B, 0xA1, 0x17, + 0x90, 0x78, 0x38, 0xFB, 0x39, 0x13, 0xB5, 0x78, 0xE4, 0xE1, 0x2C, 0x01, 0xC7, 0xBE, 0xCB, 0xB1, 0xFF, 0x6E, 0x6A, 0x1A, + 0x4E, 0x04, 0x41, 0xCF, 0x9B, 0x2A, 0xFD, 0x78, 0x4D, 0x05, 0xDE, 0x1B, 0xB0, 0x58, 0x81, 0xEF, 0x63, 0x23, 0x43, 0xD0, + 0xDF, 0x68, 0x5B, 0x38, 0x21, 0x1B, 0xB3, 0x8D, 0xDE, 0xF3, 0x41, 0x04, 0xE9, 0xAB, 0x0F, 0xED, 0x91, 0x24, 0x1F, 0x99, + 0x9D, 0x8B, 0xE3, 0x1A, 0x30, 0x3A, 0x3A, 0x3A, 0x88, 0xD8, 0x9C, 0x11, 0x1E, 0xA7, 0x49, 0x8A, 0xC8, 0x48, 0xAA, 0xEE, + 0x34, 0x0F, 0xB2, 0x50, 0xAC, 0x16, 0xB2, 0x9A, 0xE7, 0x6C, 0xC8, 0x9A, 0xAA, 0x4B, 0xBA, 0x38, 0x7A, 0xE0, 0x64, 0xAB, + 0xB9, 0x6C, 0xE6, 0xAF, 0x79, 0x4B, 0xAE, 0x0B, 0x48, 0xC2, 0xEB, 0xBD, 0x05, 0x61, 0x0D, 0xBF, 0x9B, 0x40, 0xAB, 0x1D, + 0x95, 0x22, 0xF3, 0x6C, 0x68, 0x49, 0xA3, 0x5A, 0x78, 0x69, 0x3E, 0x62, 0xA5, 0x45, 0x5F, 0x66, 0xB2, 0x34, 0x8A, 0xC2, + 0x9B, 0x8D, 0x6E, 0xE2, 0x50, 0x3C, 0x6C, 0x92, 0x5A, 0x1C, 0x0B, 0x7C, 0x37, 0x7E, 0x1D, 0x56, 0x52, 0x43, 0xA4, 0x5C, + 0x4E, 0xBE, 0x65, 0x21, 0xAC, 0x1D, 0x5E, 0xE7, 0x71, 0xB8, 0x4C, 0xB8, 0x47, 0xEF, 0x01, 0x27, 0x70, 0xB9, 0xD9, 0x17, + 0xF5, 0x10, 0x35, 0xD2, 0x73, 0x93, 0x23, 0x98, 0x46, 0x48, 0x27, 0xF2, 0x33, 0x63, 0xC3, 0xA6, 0xDD, 0xB9, 0xBC, 0x46, + 0x10, 0x56, 0x7E, 0xD4, 0xC3, 0xDE, 0xEC, 0x34, 0xAD, 0x7B, 0xD9, 0xA3, 0x1F, 0xB4, 0x9C, 0xCC, 0x50, 0x55, 0x24, 0xE1, + 0x83, 0x53, 0x96, 0x1B, 0xD0, 0x78, 0xD0, 0x86, 0x7C, 0x1C, 0x9F, 0xD0, 0x11, 0x30, 0xD2, 0x81, 0xF2, 0xFD, 0xB5, 0x50, + 0xDC, 0x7B, 0x75, 0xE1, 0xCF, 0x08, 0xB5, 0x57, 0xB6, 0xCD, 0x77, 0xC0, 0x40, 0x51, 0xD7, 0xF4, 0x50, 0x7A, 0x85, 0xC5, + 0xAA, 0x1C, 0xCE, 0x89, 0x5B, 0x98, 0x53, 0xDB, 0x5C, 0x17, 0xDE, 0xA8, 0x1F, 0x79, 0x6E, 0x9A, 0x5D, 0x14, 0xB6, 0x4C, + 0x65, 0x98, 0x87, 0xF3, 0x6F, 0xAA, 0xC7, 0x45, 0x9E, 0xB4, 0x90, 0xEB, 0x4B, 0xE5, 0x7F, 0x0F, 0x38, 0xE1, 0xD7, 0x69, + 0xE8, 0x18, 0xF7, 0xAF, 0x97, 0x77, 0x90, 0x79, 0xF1, 0x16, 0xB7, 0xAC, 0x18, 0x20, 0xDE, 0x3D, 0xEE, 0xA2, 0x33, 0x2F, + 0xED, 0x71, 0xFE, 0x8F, 0x24, 0xB3, 0xFE, 0x9C, 0x32, 0x33, 0x7C, 0xD9, 0xCB, 0x5A, 0xDC, 0xE8, 0xD9, 0x87, 0x46, 0xCC, + 0x48, 0x22, 0xC4, 0x9C, 0x98, 0x3B, 0x74, 0xCC, 0xCA, 0xA2, 0xBE, 0x49, 0x1B, 0xF0, 0x52, 0x8E, 0x68, 0xFE, 0xA7, 0x6D, + 0x06, 0x33, 0xFB, 0x80, 0x49, 0x58, 0x2E, 0x69, 0xA1, 0xB6, 0x59, 0xF0, 0x40, 0x2E, 0x9F, 0xCC, 0x1A, 0xB7, 0x15, 0xE4, + 0x69, 0x7B, 0xA7, 0xDA, 0x98, 0x80, 0x79, 0x9A, 0xA3, 0xCD, 0xF0, 0x1A, 0x37, 0xA6, 0x60, 0x23, 0x48, 0xC3, 0xC8, 0x06, + 0x5E, 0x80, 0x12, 0xFA, 0x0F, 0xCE, 0x6C, 0x93, 0x56, 0xC1, 0x26, 0x50, 0xAE, 0xF0, 0xF1, 0x94, 0xB4, 0x1E, 0xDE, 0xEB, + 0x80, 0xCD, 0x81, 0xFF, 0x35, 0x2E, 0x77, 0x3B, 0x46, 0xC6, 0x8F, 0x0E, 0x77, 0xA0, 0x96, 0xE2, 0x26, 0x70, 0xF0, 0x9B, + 0x32, 0xAE, 0x8D, 0x51, 0x2E, 0x92, 0x79, 0xEA, 0xF3, 0x6E, 0x00, 0x5C, 0x70, 0x8B, 0xAA, 0xBD, 0xB5, 0xA9, 0x5A, 0x56, + 0xE7, 0x4E, 0x78, 0xBA, 0x16, 0xEB, 0x31, 0x63, 0xA2, 0x3A, 0xE7, 0x86, 0xA8, 0xAA, 0x32, 0x6F, 0x2C, 0xCA, 0x80, 0xF4, + 0x52, 0xBE, 0xBA, 0x01, 0xF9, 0x0C, 0xAB, 0xA8, 0x90, 0x3F, 0x09, 0x03, 0xDA, 0x4A, 0x45, 0x05, 0x97, 0xA6, 0xB4, 0xC5, + 0x81, 0x5D, 0x89, 0xF7, 0x95, 0x2C, 0x7F, 0x41, 0x45, 0x8B, 0xA3, 0x76, 0x74, 0xE1, 0x10, 0xF5, 0xF8, 0x87, 0xE8, 0xB3, + 0x2F, 0x69, 0x9A, 0xBB, 0x33, 0x41, 0xEB, 0xD3, 0xBB, 0xF3, 0x22, 0xAD, 0x6E, 0xA9, 0x2E, 0x2C, 0x76, 0xA6, 0x84, 0xB8, + 0xCD, 0xD0, 0xE3, 0xCE, 0xBA, 0xF2, 0xE3, 0xD3, 0xC8, 0x8C, 0x5B, 0x69, 0xF7, 0xA5, 0xE8, 0x2B, 0xCA, 0x20, 0x6D, 0xD9, + 0xCC, 0x25, 0x53, 0x99, 0x8C, 0xFC, 0xAD, 0x0D, 0x1F, 0x7F, 0x03, 0xC5, 0x4F, 0xCF, 0xE5, 0xC9, 0xEE, 0x30, 0x1E, 0xB6, + 0x8F, 0x77, 0x65, 0xAC, 0x9C, 0xAF, 0xF4, 0x88, 0xCC, 0x80, 0x7A, 0x87, 0xFD, 0xEA, 0xEA, 0xDE, 0x58, 0xA2, 0xE0, 0x4B, + 0xBC, 0xAB, 0x30, 0x98, 0xAE, 0xCB, 0x9A, 0x3A, 0x28, 0x6D, 0xB0, 0xA6, 0x9E, 0x35, 0x52, 0x2D, 0xDD, 0xA1, 0xF5, 0x09, + 0x4C, 0xA2, 0x7B, 0x92, 0x3F, 0xE1, 0x51, 0xA8, 0xB3, 0x94, 0xBB, 0xCE, 0xFC, 0x8F, 0x51, 0x4A, 0x6C, 0xC9, 0x83, 0xFD, + 0xDA, 0xEB, 0xE0, 0x04, 0x36, 0x93, 0xB2, 0x60, 0xB6, 0xB4, 0x6D, 0xBF, 0xC1, 0x6F, 0x34, 0x52, 0x15, 0x2B, 0xE8, 0x17, + 0xA3, 0x81, 0xFF, 0x74, 0x94, 0xDD, 0x36, 0xB0, 0x9A, 0xD7, 0xF1, 0xC4, 0x8E, 0xB3, 0x64, 0x97, 0x05, 0xFE, 0x85, 0xE5, + 0x36, 0x66, 0x85, 0x2A, 0x05, 0xB1, 0x99, 0x5A, 0xD6, 0x87, 0x4D, 0x91, 0x83, 0x9E, 0xCF, 0x9B, 0xB6, 0xD3, 0x9E, 0x08, + 0x44, 0x0C, 0x76, 0x54, 0xF3, 0x4A, 0xA4, 0xAF, 0xD5, 0x16, 0xE5, 0x24, 0x9A, 0x3F, 0x84, 0x00, 0xCA, 0xDB, 0x8C, 0xC1, + 0x15, 0x14, 0x34, 0xC6, 0xA5, 0x41, 0x69, 0xB4, 0x74, 0xBA, 0xC8, 0x10, 0xCB, 0xDA, 0x84, 0x74, 0x55, 0xB4, 0x1D, 0x47, + 0x9B, 0x09, 0x62, 0x25, 0x34, 0xB5, 0xCA, 0xB1, 0xA5, 0x26, 0x8D, 0xC0, 0x95, 0x09, 0xBE, 0xB1, 0xE7, 0x98, 0x95, 0x55, + 0x95, 0x95, 0xD5, 0xE3, 0x8C, 0x6E, 0xC7, 0x15, 0x75, 0xFF, 0x58, 0xA3, 0x80, 0x95, 0xFC, 0x71, 0x9F, 0x63, 0x1C, 0x0F, + 0x42, 0x52, 0x54, 0x46, 0x6E, 0xB5, 0xF7, 0xF8, 0xC6, 0x70, 0x4C, 0x72, 0x3D, 0x34, 0xC3, 0x85, 0x08, 0x9B, 0x12, 0x2D, + 0x10, 0xF3, 0x59, 0xA7, 0x2E, 0x9E, 0x53, 0x72, 0xD9, 0xC1, 0x1F, 0xF6, 0xAD, 0xD9, 0xD7, 0xB1, 0xF9, 0xF5, 0x9B, 0xF9, + 0x9E, 0xCF, 0xD0, 0x1B, 0xFA, 0x39, 0xF0, 0xF7, 0xDE, 0x09, 0xB9, 0xCC, 0x90, 0xF4, 0x60, 0xE7, 0xAE, 0xE0, 0xBC, 0x57, + 0x38, 0xC5, 0x53, 0x98, 0x85, 0x24, 0xFF, 0xFE, 0xDD, 0x71, 0x75, 0x5B, 0xCE, 0x9B, 0xD4, 0x3C, 0xBD, 0xF5, 0x5E, 0xC2, + 0xCE, 0x22, 0xC4, 0x01, 0x7B, 0x07, 0x07, 0x94, 0x4F, 0xDC, 0xC9, 0x4D, 0xBB, 0x74, 0x2E, 0x0E, 0x09, 0xD8, 0x08, 0x6B, + 0xA1, 0xBD, 0x47, 0xA0, 0x0C, 0xFA, 0x26, 0x3D, 0x3D, 0xF7, 0x05, 0x05, 0x43, 0xD2, 0x2C, 0xFF, 0xFF, 0xFF, 0xDB, 0x5E, + 0x7F, 0xE7, 0x3F, 0x54, 0x31, 0x6F, 0xF4, 0x7F, 0xE7, 0x50, 0xAE, 0xE8, 0xF7, 0x95, 0xC8, 0xCC, 0xAA, 0x8C, 0xA2, 0xC4, + 0x4D, 0xA1, 0x41, 0xB3, 0xA0, 0x0E, 0x51, 0xCC, 0x51, 0x23, 0xDC, 0x0C, 0x61, 0xBD, 0xE1, 0x07, 0x06, 0x2F, 0xAE, 0xC7, + 0x39, 0xBD, 0xDC, 0xD9, 0xD0, 0xD7, 0x69, 0x52, 0x94, 0x0C, 0xE9, 0x57, 0x8D, 0x2C, 0x18, 0x4E, 0x66, 0x45, 0x9D, 0x76, + 0x2C, 0xC2, 0x38, 0x67, 0xA1, 0x02, 0x3D, 0x2B, 0x9F, 0x82, 0x30, 0x24, 0x1A, 0x06, 0xAF, 0x3E, 0xAF, 0xF8, 0x28, 0x14, + 0x36, 0x88, 0x5F, 0x84, 0x1B, 0xDA, 0x98, 0xA9, 0x06, 0x43, 0xA6, 0x72, 0xB2, 0xE6, 0x49, 0x66, 0xC2, 0x09, 0x5B, 0x85, + 0xE6, 0x8B, 0xCC, 0xC6, 0xBD, 0xCF, 0x56, 0x95, 0x89, 0xF7, 0x31, 0xD3, 0x8A, 0x43, 0x76, 0x45, 0x24, 0xAC, 0xD1, 0xE4, + 0x62, 0xB8, 0x7A, 0x86, 0x5F, 0xDA, 0xAA, 0xAD, 0x3B, 0x2F, 0xE2, 0x0E, 0x8E, 0x25, 0x32, 0x1A, 0xE9, 0x41, 0xAA, 0xD3, + 0xAD, 0x0B, 0x72, 0x9A, 0x88, 0x8B, 0xA2, 0x04, 0xBA, 0x2F, 0x3A, 0x29, 0xC4, 0x2A, 0xE4, 0x21, 0xAC, 0xEA, 0xFB, 0x8B, + 0x09, 0x68, 0xC9, 0x10, 0xD8, 0x2C, 0xD3, 0xAD, 0xF5, 0x04, 0x68, 0x52, 0xB8, 0x63, 0x73, 0x9B, 0x09, 0xD3, 0xAB, 0x92, + 0x38, 0xA7, 0xB0, 0x9C, 0x1C, 0x55, 0xAF, 0xCE, 0x8D, 0x2A, 0x7A, 0x18, 0x0E, 0x03, 0xA2, 0x61, 0x1C, 0xB5, 0x78, 0xED, + 0x44, 0xC6, 0xAA, 0x61, 0xDA, 0x7B, 0x4E, 0xBA, 0x89, 0x25, 0xD8, 0xDE, 0x1D, 0xB4, 0x3A, 0x3C, 0x43, 0x0F, 0x62, 0x87, + 0x86, 0x10, 0x23, 0x09, 0xA4, 0x85, 0x13, 0x3E, 0xFF, 0x5F, 0xD7, 0xC9, 0x6B, 0x8E, 0x43, 0x0B, 0x29, 0x7E, 0xEB, 0x3B, + 0xC8, 0xB0, 0x1B, 0x62, 0xE7, 0xFA, 0xC6, 0xC3, 0x36, 0xC3, 0x74, 0x23, 0x6E, 0xB3, 0x8B, 0x04, 0x51, 0x83, 0x44, 0x85, + 0x80, 0xAF, 0x9B, 0xC6, 0x97, 0x40, 0xCE, 0xA1, 0xD3, 0x76, 0x77, 0x12, 0xA1, 0x54, 0xB7, 0x66, 0x10, 0x71, 0x7E, 0xD6, + 0xBF, 0x8C, 0xFC, 0xF0, 0x36, 0x7E, 0x65, 0xC7, 0xE4, 0x1F, 0xCF, 0x90, 0x91, 0xF2, 0xAD, 0x5E, 0x6F, 0x49, 0x1D, 0x69, + 0x11, 0x7D, 0x35, 0xF1, 0xA7, 0x51, 0x25, 0x25, 0xD2, 0xC3, 0x07, 0xB3, 0x0A, 0x5C, 0xFD, 0xF1, 0x71, 0x7E, 0x3C, 0x42, + 0x00, 0xF5, 0x70, 0x0B, 0xC1, 0xEF, 0x6C, 0xF4, 0xE0, 0x1C, 0xEC, 0xB4, 0x7A, 0x7B, 0x74, 0x00, 0xD8, 0x1A, 0x17, 0x45, + 0xD2, 0x4A, 0xCC, 0x82, 0xE1, 0x81, 0x10, 0x96, 0x30, 0xAA, 0x3D, 0x43, 0xAB, 0x4B, 0x50, 0x65, 0xB8, 0x76, 0x52, 0x65, + 0xDF, 0xC1, 0x45, 0x07, 0x70, 0x3E, 0x2D, 0x90, 0x1A, 0x55, 0x94, 0x40, 0x16, 0x88, 0x2A, 0x13, 0xC1, 0x75, 0xA5, 0x97, + 0xB0, 0xC8, 0x9B, 0x4E, 0xA8, 0xB8, 0x11, 0x7F, 0xBC, 0xB5, 0x57, 0xCE, 0x09, 0x5C, 0xDC, 0x51, 0xDB, 0x1D, 0xA5, 0x52, + 0x92, 0x22, 0xB5, 0x7E, 0x65, 0xCE, 0xA5, 0x5E, 0x79, 0xA4, 0xFE, 0xFC, 0x7F, 0x74, 0xAB, 0x2C, 0x7D, 0x79, 0xD5, 0xCF, + 0x53, 0x5E, 0x71, 0x4B, 0xE9, 0xFA, 0xAF, 0x7D, 0x0F, 0x75, 0x47, 0x7E, 0x5C, 0x29, 0x8D, 0x4B, 0x58, 0x20, 0xE7, 0x3B, + 0x69, 0xBD, 0xD5, 0x52, 0x5A, 0x76, 0xDB, 0x83, 0xA8, 0x54, 0x7B, 0x8B, 0xE0, 0x36, 0xD1, 0x6A, 0xBE, 0x20, 0xAE, 0xC8, + 0xDB, 0xA7, 0x36, 0x5A, 0x2E, 0xDD, 0xB0, 0xDA, 0xDA, 0xBE, 0x56, 0xEC, 0xE9, 0x89, 0xDF, 0xD8, 0x4C, 0x98, 0xC7, 0xAB, + 0xE9, 0xA1, 0x10, 0x3D, 0x27, 0x4F, 0x6F, 0xAE, 0x28, 0xFC, 0xD7, 0xA7, 0x0B, 0x62, 0x77, 0x09, 0x50, 0x10, 0x6C, 0x2E, + 0x37, 0x32, 0x28, 0x09, 0xE3, 0x50, 0x02, 0x9D, 0x90, 0xEC, 0x18, 0x87, 0x82, 0x03, 0xEA, 0x1B, 0x54, 0xA6, 0x4D, 0xCB, + 0x86, 0xAF, 0xD0, 0x62, 0x25, 0x6D, 0xCF, 0x90, 0x85, 0x97, 0x88, 0x99, 0xB4, 0x2B, 0x18, 0x15, 0xE4, 0xC8, 0x78, 0x5B, + 0x9C, 0xE7, 0x31, 0xB3, 0x80, 0xA3, 0x89, 0x1E, 0x37, 0xA4, 0x8A, 0xAA, 0x6B, 0xC4, 0xC9, 0xA5, 0xD1, 0xDB, 0x11, 0xFB, + 0x67, 0xCC, 0x2E, 0x07, 0x17, 0xAF, 0xF9, 0xB7, 0xF8, 0x8D, 0x31, 0x34, 0x74, 0x69, 0xA0, 0x3A, 0x5F, 0x0C, 0x73, 0x7D, + 0x6E, 0x31, 0xB4, 0xE7, 0x48, 0x4E, 0x30, 0x67, 0xDF, 0x19, 0x95, 0xB0, 0x85, 0xCD, 0xEA, 0xCF, 0xCB, 0x54, 0x18, 0x36, + 0x0F, 0x87, 0x80, 0x66, 0xB7, 0x1A, 0x69, 0xA1, 0x27, 0x0C, 0xF2, 0xAF, 0x9E, 0xE4, 0x75, 0xC3, 0x67, 0x06, 0xA8, 0x63, + 0xF2, 0x4D, 0xCF, 0xA3, 0x8F, 0x88, 0x4A, 0x6B, 0x4F, 0x16, 0xE4, 0xC9, 0x45, 0x8F, 0xC7, 0x95, 0x74, 0x82, 0x96, 0x68, + 0x3F, 0xCF, 0x21, 0xEC, 0xFD, 0x57, 0x12, 0x3B, 0xC1, 0xAB, 0xCD, 0xCC, 0xDE, 0xEB, 0xC9, 0x9E, 0x7C, 0x1A, 0xAE, 0x2E, + 0x93, 0x96, 0x47, 0xD3, 0xCB, 0xA6, 0xC2, 0xBC, 0x58, 0xE0, 0xDB, 0x6D, 0x77, 0x91, 0x1C, 0xF7, 0x9C, 0xD1, 0x98, 0x8E, + 0x19, 0xD4, 0x06, 0x4D, 0x9F, 0x1D, 0x72, 0xA9, 0x28, 0x90, 0x90, 0xAF, 0x1D, 0xF4, 0x80, 0xB2, 0x62, 0xD0, 0xE1, 0x7F, + 0x7E, 0x8E, 0x02, 0xEA, 0x46, 0x01, 0xC1, 0x76, 0x02, 0xA8, 0xB0, 0x08, 0xB1, 0xCF, 0x4D, 0x8C, 0x7A, 0xE1, 0x12, 0xD8, + 0x2D, 0x3F, 0x37, 0x66, 0x9D, 0x79, 0x7F, 0xFE, 0x72, 0x5A, 0xF0, 0x7A, 0xFC, 0xAC, 0x1B, 0xC9, 0xAC, 0xBD, 0xC8, 0x3D, + 0x25, 0x51, 0x4B, 0x7F, 0x4C, 0x86, 0xB9, 0x91, 0x7D, 0xE3, 0x13, 0xD9, 0xAD, 0xFF, 0x65, 0xAF, 0x60, 0xA0, 0xC4, 0x3C, + 0xC1, 0xCC, 0xC3, 0xAF, 0x24, 0xE0, 0xD8, 0x00, 0xA4, 0xB5, 0x50, 0x60, 0xB1, 0x20, 0x0C, 0x72, 0x38, 0xCB, 0xFE, 0x5D, + 0xD7, 0x95, 0xB1, 0x54, 0xA5, 0x31, 0x86, 0x13, 0x3B, 0x3B, 0x76, 0xAF, 0x0E, 0xDE, 0x84, 0x66, 0xAA, 0xFE, 0x1D, 0xE3, + 0xA2, 0xD0, 0xC5, 0x85, 0xE1, 0xBF, 0xC1, 0x45, 0x45, 0x5E, 0x8D, 0x77, 0x0A, 0xFD, 0x81, 0x36, 0x70, 0xF0, 0x29, 0x12, + 0x33, 0x70, 0xBC, 0x81, 0x85, 0x83, 0xDD, 0xF7, 0xF3, 0xFE, 0x04, 0x86, 0x32, 0x99, 0x1D, 0x81, 0xE0, 0xBE, 0x24, 0x6B, + 0x61, 0x96, 0x74, 0x1F, 0x76, 0x6F, 0xE4, 0xCE, 0x86, 0x1F, 0x93, 0x8C, 0x8E, 0x29, 0x44, 0xC3, 0xC6, 0x54, 0xC4, 0x26, + 0x2B, 0x5E, 0x2F, 0x38, 0x05, 0x90, 0x25, 0xA9, 0xD7, 0xD6, 0xEA, 0xCD, 0x1B, 0x77, 0xCD, 0x95, 0x09, 0xB7, 0x12, 0x31, + 0x25, 0xDF, 0xE8, 0x27, 0xFA, 0x26, 0x44, 0x00, 0x63, 0x5A, 0x85, 0xD7, 0x17, 0x98, 0x8D, 0x40, 0x97, 0xA3, 0xF6, 0x3A, + 0x24, 0x1A, 0x6F, 0x19, 0xCB, 0xDE, 0xFC, 0x50, 0xDF, 0x9D, 0xD2, 0x72, 0xFB, 0xD4, 0xE3, 0x78, 0xBD, 0x59, 0xCC, 0x5C, + 0xC8, 0x26, 0x86, 0x6E, 0x86, 0xF6, 0xC0, 0x6C, 0x59, 0xA8, 0x6E, 0x67, 0x16, 0x17, 0x17, 0x31, 0x4D, 0xC1, 0x8F, 0x7F, + 0x43, 0xF5, 0xD0, 0x93, 0x08, 0x80, 0xE9, 0x56, 0x8E, 0x9C, 0x75, 0x59, 0xCE, 0x5B, 0xDF, 0xFB, 0x9D, 0x76, 0x62, 0x4E, + 0x13, 0xFB, 0x98, 0xC8, 0xDF, 0x3F, 0x24, 0xBF, 0x85, 0xB8, 0xC8, 0x0C, 0x64, 0x93, 0xF3, 0x7D, 0xAD, 0xD5, 0x42, 0x4C, + 0x03, 0xB7, 0xE9, 0xE4, 0x1B, 0x69, 0x4A, 0x81, 0xDC, 0xBC, 0x07, 0x8F, 0xE6, 0xDC, 0x44, 0xCD, 0xF8, 0xE3, 0xB7, 0xFB, + 0xB3, 0x2A, 0x67, 0x10, 0x0B, 0xF1, 0x6A, 0x5F, 0x92, 0xF8, 0xAD, 0xB1, 0xDE, 0xDF, 0x68, 0xE1, 0x9F, 0x52, 0xA5, 0x43, + 0x97, 0xCE, 0x7E, 0x06, 0xE1, 0x83, 0xD0, 0x18, 0x1C, 0x23, 0xD6, 0x42, 0xCD, 0x22, 0x14, 0xD4, 0x59, 0x6F, 0x98, 0x72, + 0xFA, 0xDC, 0x8D, 0x96, 0x91, 0x29, 0x14, 0x4B, 0xE0, 0xCB, 0xC1, 0xC9, 0x32, 0xE3, 0x29, 0xF2, 0x0C, 0x0F, 0x85, 0x1D, + 0xB0, 0x80, 0x01, 0x43, 0x69, 0x44, 0x79, 0x04, 0x55, 0x42, 0xF1, 0x6A, 0x91, 0x4C, 0xD3, 0xEA, 0x32, 0x63, 0x66, 0xD3, + 0xBE, 0x03, 0x61, 0x47, 0x53, 0x67, 0x43, 0xA6, 0x80, 0xD0, 0xA2, 0x40, 0x11, 0xA4, 0x28, 0xE2, 0xCA, 0x1C, 0xD0, 0x59, + 0xB9, 0x20, 0x28, 0x4B, 0xF3, 0x8E, 0x08, 0x84, 0x30, 0x21, 0xC7, 0xA8, 0x45, 0x7C, 0x7C, 0x0A, 0xF0, 0x98, 0xD6, 0xB1, + 0xE3, 0x09, 0xC7, 0x6D, 0x12, 0x58, 0x0B, 0x9E, 0x61, 0x04, 0xEB, 0xD5, 0x52, 0xC9, 0x4D, 0xB3, 0x01, 0xD3, 0x70, 0xA9, + 0x13, 0xDC, 0x69, 0x37, 0x3F, 0x05, 0x81, 0x1B, 0xF7, 0x61, 0x92, 0xE0, 0x50, 0x45, 0x9A, 0x0C, 0x1E, 0xF1, 0xD2, 0x15, + 0x78, 0x0A, 0x01, 0xCE, 0x5E, 0x61, 0x72, 0x3F, 0xF4, 0x06, 0x06, 0x3C, 0xB8, 0xD3, 0x02, 0xD3, 0xCB, 0x6D, 0xC5, 0x5E, + 0xFD, 0xA4, 0xFC, 0x01, 0x2D, 0xF6, 0x69, 0x29, 0x9E, 0xB3, 0x86, 0x1D, 0x35, 0xC5, 0x93, 0x09, 0x5A, 0x6E, 0x9B, 0xE9, + 0x29, 0xDA, 0x4B, 0x70, 0x0E, 0x69, 0x92, 0x46, 0x6A, 0x09, 0x7B, 0xB8, 0x5B, 0x6F, 0x12, 0xAA, 0x2E, 0x4E, 0x4C, 0xB4, + 0xF6, 0x97, 0x9D, 0x5C, 0xC8, 0x64, 0xDA, 0xCB, 0xBB, 0x63, 0x70, 0xA7, 0x0D, 0x2D, 0x87, 0xB7, 0x1D, 0x24, 0x22, 0xFA, + 0x48, 0xA9, 0xD0, 0x7D, 0xF8, 0x60, 0x58, 0x61, 0xF9, 0x00, 0xDB, 0xA0, 0x37, 0x6C, 0xEF, 0x0B, 0x8B, 0x0E, 0xB3, 0x2D, + 0x7C, 0x63, 0x42, 0xDB, 0x5F, 0xD8, 0xCB, 0x79, 0x9D, 0xB6, 0x01, 0x69, 0x68, 0x49, 0x91, 0x60, 0x9A, 0x6A, 0xBB, 0x66, + 0x04, 0x16, 0x0A, 0xE6, 0xBD, 0xC6, 0x9A, 0x59, 0xCD, 0x12, 0xF4, 0xBA, 0x5F, 0x32, 0x26, 0x15, 0x62, 0xF1, 0xD6, 0xF4, + 0x4D, 0x9E, 0x1E, 0x76, 0x2B, 0x55, 0x92, 0xD6, 0x52, 0x31, 0x25, 0x70, 0x01, 0xED, 0x8D, 0xA0, 0x51, 0xCD, 0xD8, 0x8B, + 0x1D, 0x5B, 0x08, 0x92, 0x72, 0xA6, 0x9D, 0x73, 0x23, 0x10, 0x2D, 0xE7, 0xD3, 0xD6, 0xC9, 0x48, 0xCA, 0xC8, 0x29, 0xD7, + 0xD2, 0x63, 0x5E, 0x85, 0x01, 0xF7, 0x53, 0x3B, 0x66, 0xE3, 0x58, 0xF5, 0x01, 0x94, 0x5A, 0xB9, 0x2F, 0xFC, 0xB7, 0xAF, + 0x56, 0xEA, 0xBC, 0xB6, 0xD1, 0x60, 0x24, 0x72, 0x6A, 0xF5, 0x96, 0x5D, 0x51, 0x76, 0x25, 0xF6, 0x8F, 0x1B, 0x05, 0xB6, + 0x30, 0x12, 0x2D, 0x63, 0xEB, 0x96, 0xD8, 0x2D, 0xAD, 0x9E, 0x2D, 0xE6, 0xCA, 0x1A, 0x49, 0xAA, 0x92, 0x47, 0x07, 0xEC, + 0x40, 0x51, 0x12, 0x44, 0xD1, 0x74, 0xB3, 0xEA, 0x69, 0x98, 0xF8, 0x8B, 0x99, 0xE7, 0x16, 0x55, 0x79, 0x83, 0xF6, 0xB2, + 0x31, 0x77, 0x0E, 0x64, 0x69, 0x5B, 0x2E, 0xEE, 0x5B, 0x3D, 0x7E, 0xBB, 0x4B, 0x1B, 0xFE, 0xA2, 0x56, 0x74, 0x7F, 0xEB, + 0x8C, 0xE1, 0xDD, 0xD8, 0xC4, 0x95, 0x37, 0x2D, 0xA3, 0x18, 0x23, 0x5D, 0x3E, 0x75, 0x90, 0x86, 0x2B, 0x13, 0xF1, 0x9A, + 0x18, 0xE2, 0x1D, 0xD4, 0x6B, 0x7F, 0xC7, 0xB9, 0x55, 0x76, 0xD9, 0x28, 0x1A, 0x1A, 0x1D, 0xCF, 0x45, 0x39, 0x5A, 0xF8, + 0xC9, 0x1C, 0x02, 0xEC, 0x0D, 0x26, 0x8E, 0x05, 0xD7, 0x1B, 0x0E, 0x00, 0x90, 0x7C, 0x4F, 0x7A, 0xEB, 0x55, 0x01, 0x08, + 0x0C, 0x3D, 0xE4, 0x77, 0x5F, 0x11, 0x1A, 0x49, 0xC1, 0xC1, 0x9D, 0x1D, 0x0B, 0xF1, 0x05, 0x69, 0x97, 0xEC, 0xF9, 0xB5, + 0x0A, 0x96, 0xAF, 0xDE, 0xBA, 0xB4, 0x05, 0x06, 0x48, 0x59, 0x5F, 0x28, 0x16, 0x7F, 0x5E, 0x04, 0xE5, 0x03, 0xA4, 0x4E, + 0x6F, 0xCD, 0xAF, 0xBE, 0xC6, 0xC4, 0x0F, 0x44, 0xD6, 0x34, 0xF1, 0x25, 0x3A, 0x88, 0x68, 0xDB, 0xA5, 0x5C, 0xBB, 0x92, + 0x11, 0x21, 0x3C, 0xC6, 0x73, 0xEE, 0x05, 0xF0, 0x08, 0xC3, 0x7E, 0x67, 0xE3, 0x47, 0x6E, 0x41, 0xEA, 0x84, 0xB9, 0xC5, + 0x75, 0xE9, 0x77, 0xAB, 0x8D, 0x38, 0xF1, 0xC3, 0x17, 0xA7, 0xF9, 0xF2, 0xBF, 0x85, 0xD9, 0x35, 0x76, 0xEE, 0x3A, 0x0A, + 0xA5, 0x82, 0xF1, 0xBE, 0x96, 0x5F, 0x38, 0x74, 0xE5, 0xC2, 0x88, 0xE4, 0x57, 0xE3, 0x72, 0x06, 0x24, 0x7D, 0xD2, 0xA9, + 0xE0, 0x2E, 0xCC, 0x62, 0xE4, 0x87, 0x80, 0x52, 0xBE, 0x2C, 0xD7, 0x23, 0x27, 0x79, 0xE5, 0xC3, 0x9E, 0xBE, 0xF9, 0xCF, + 0x27, 0xC9, 0x4A, 0x85, 0x7A, 0x1B, 0x09, 0x64, 0xA2, 0x8A, 0xF1, 0x6B, 0x7C, 0xE3, 0xE6, 0xA0, 0xAC, 0xD0, 0x15, 0xE5, + 0xD3, 0xEF, 0x22, 0x2E, 0xE7, 0xCC, 0x2C, 0x6C, 0x3F, 0x08, 0x36, 0x28, 0x48, 0x84, 0xA4, 0x4C, 0xAB, 0x65, 0x8E, 0x74, + 0xAE, 0xC8, 0xAD, 0x9C, 0xF1, 0xA0, 0x21, 0x7F, 0x6F, 0xC4, 0xC2, 0x19, 0x88, 0xE6, 0x19, 0xBB, 0x58, 0x25, 0xF9, 0x4E, + 0x3F, 0xAE, 0x37, 0x6D, 0x86, 0x88, 0x67, 0xAD, 0x08, 0x42, 0xD4, 0x69, 0x2A, 0x9B, 0x93, 0xE0, 0x1F, 0xAF, 0x75, 0xC7, + 0x4D, 0x30, 0xDB, 0x3D, 0x76, 0xE6, 0x99, 0x35, 0x7B, 0x73, 0xD8, 0xFE, 0xF2, 0x03, 0x71, 0xAC, 0xFE, 0xCA, 0xF1, 0x1D, + 0x3B, 0x6A, 0xF5, 0xBA, 0x0E, 0x8B, 0xF1, 0xC7, 0xE6, 0xA2, 0x02, 0x3C, 0xBB, 0x83, 0x60, 0x4E, 0xA4, 0x12, 0x03, 0x7C, + 0xEF, 0x83, 0x47, 0x2D, 0x65, 0xEC, 0x7B, 0x8D, 0xAD, 0xEE, 0xF2, 0xAF, 0x9A, 0x43, 0xDD, 0x3A, 0x2E, 0x70, 0x2B, 0x27, + 0xC5, 0xA2, 0xCE, 0xBD, 0x3F, 0xC9, 0x6B, 0x82, 0x97, 0xAE, 0xD0, 0x72, 0x2C, 0x9F, 0xFC, 0x96, 0x68, 0x47, 0x27, 0xC0, + 0x97, 0xB5, 0xEC, 0xAF, 0xF6, 0x24, 0x4C, 0xD3, 0xD0, 0x9C, 0x69, 0x6A, 0xB5, 0x4A, 0xC7, 0x95, 0xC4, 0x2E, 0xE6, 0x8E, + 0xD6, 0xEA, 0x8D, 0x03, 0x21, 0xD2, 0x1D, 0xE1, 0x4A, 0xFF, 0x0D, 0x58, 0x48, 0xDF, 0x69, 0xB7, 0x57, 0x97, 0x67, 0x68, + 0x06, 0x95, 0x23, 0x7A, 0x18, 0x08, 0x89, 0xD1, 0x56, 0xB6, 0xFC, 0xD1, 0x77, 0x27, 0x31, 0x22, 0x60, 0xF1, 0xB1, 0x24, + 0x9A, 0x3F, 0x54, 0xB6, 0xC5, 0x96, 0xF4, 0xE6, 0x76, 0xF4, 0xD8, 0xB0, 0xC5, 0x76, 0x3A, 0x34, 0x9B, 0x3E, 0x75, 0xB4, + 0x73, 0x0E, 0xFC, 0xF6, 0x77, 0xF5, 0x5D, 0x71, 0x8C, 0xB4, 0xB1, 0x25, 0x1A, 0x3D, 0xE8, 0x2D, 0xE0, 0xF6, 0xF5, 0xE7, + 0xF6, 0xF6, 0x6E, 0xF4, 0x06, 0x68, 0xE7, 0x35, 0x1B, 0x3C, 0xCB, 0x0E, 0xC6, 0x6C, 0xFD, 0xF7, 0xF7, 0xF7, 0x2A, 0xF1, + 0x8D, 0x10, 0xBE, 0x76, 0xD0, 0xFA, 0x0E, 0x41, 0xC0, 0xD5, 0xE9, 0x4C, 0xFE, 0x2C, 0xEE, 0x43, 0x68, 0xDB, 0xED, 0x9C, + 0x21, 0xBF, 0x92, 0x3E, 0x2D, 0x49, 0x1F, 0x5C, 0xF8, 0x89, 0xA7, 0x69, 0xD3, 0xD9, 0xEA, 0x64, 0x9E, 0xBA, 0xCE, 0x8C, + 0x4D, 0xA5, 0xE3, 0xCD, 0x7E, 0x2E, 0xE0, 0x14, 0x2F, 0xD3, 0x8F, 0xCA, 0x1C, 0xB0, 0x27, 0xBF, 0x6A, 0x79, 0x85, 0x4C, + 0x8C, 0xE0, 0x7C, 0x9A, 0x0F, 0x7C, 0x62, 0x2C, 0x92, 0x37, 0xCA, 0x6E, 0x71, 0xC9, 0xF6, 0xEE, 0x7E, 0xFC, 0xEE, 0xD8, + 0xD8, 0xDC, 0x29, 0xA1, 0xBD, 0x44, 0xFF, 0xDF, 0x69, 0x27, 0xFE, 0xFE, 0x7F, 0xFD, 0xD8, 0xBB, 0xA1, 0x97, 0xAF, 0x2D, + 0xC1, 0xFC, 0xC8, 0x8B, 0xA8, 0xDF, 0xF7, 0xEF, 0xFE, 0xFE, 0x55, 0x59, 0x27, 0xCE, 0xC7, 0x58, 0x48, 0x34, 0x9A, 0x88, + 0xDF, 0xB3, 0xFF, 0xFF, 0x94, 0x54, 0x26, 0x59, 0x6E, 0xA4, 0x82, 0xF1, 0x58, 0xB1, 0x16, 0x11, 0x78, 0x02, 0x82, 0xDC, + 0xBB, 0x24, 0xB0, 0xE3, 0x3B, 0x11, 0xB6, 0x28, 0x32, 0x61, 0x26, 0x19, 0x29, 0x4C, 0x58, 0xDC, 0xEF, 0xEC, 0x8A, 0xA9, + 0xB3, 0x59, 0x87, 0x28, 0xD8, 0xF3, 0x4C, 0x6D, 0x21, 0x4D, 0xAF, 0xC7, 0xB2, 0xF7, 0xB1, 0xE2, 0xB7, 0x98, 0x8F, 0x2C, + 0x99, 0xD4, 0x0F, 0x53, 0xA1, 0x4C, 0xE7, 0x94, 0x3A, 0x20, 0x1A, 0x41, 0xA1, 0xB4, 0xC8, 0x54, 0xC6, 0x07, 0x09, 0x30, + 0x44, 0x7F, 0x8C, 0x92, 0x42, 0xAB, 0x11, 0xD6, 0x02, 0xC5, 0xCA, 0x36, 0xEC, 0x67, 0x0C, 0x6F, 0x65, 0xE8, 0xF2, 0xA4, + 0x0F, 0x64, 0x81, 0xA9, 0xFE, 0x44, 0x66, 0xE1, 0x10, 0x4A, 0x89, 0x21, 0x82, 0x92, 0xB1, 0x67, 0x87, 0x6B, 0x6F, 0xF4, + 0xA9, 0xA3, 0x90, 0x01, 0x7A, 0x04, 0xC8, 0xF5, 0xF0, 0x8F, 0xE1, 0x71, 0x56, 0xD5, 0xF6, 0xF1, 0xFB, 0xAC, 0x84, 0x20, + 0x10, 0x7D, 0x6C, 0x2E, 0xA9, 0xCB, 0xED, 0x3F, 0x17, 0x39, 0x82, 0xF5, 0x28, 0x52, 0x81, 0x6E, 0xE6, 0xF6, 0x24, 0xE9, + 0x20, 0x83, 0xD3, 0x7C, 0x5D, 0x41, 0xCE, 0x48, 0x40, 0x90, 0x43, 0xE5, 0xCF, 0x22, 0x3B, 0xAD, 0xFB, 0x3D, 0xAD, 0x01, + 0x57, 0xCC, 0xBD, 0xE4, 0xA8, 0xD0, 0xF4, 0xE7, 0x9F, 0x30, 0x43, 0x30, 0x20, 0xA1, 0x0B, 0x4E, 0xED, 0x29, 0x10, 0xEC, + 0x42, 0x7D, 0xBA, 0x6B, 0xF3, 0x6F, 0x6C, 0xC9, 0xE9, 0x29, 0x8B, 0x84, 0xBF, 0xAE, 0x12, 0x5C, 0x43, 0xBC, 0xCC, 0x75, + 0x33, 0x06, 0xCB, 0xFC, 0x34, 0xC1, 0x83, 0x94, 0xBE, 0x7F, 0x45, 0x75, 0x63, 0xDF, 0xBB, 0xC9, 0xE5, 0xA2, 0x6D, 0xCD, + 0x69, 0xBB, 0x92, 0x8D, 0xD2, 0xAC, 0x5F, 0x76, 0xC3, 0x5E, 0xAB, 0x1A, 0xDB, 0x22, 0x01, 0x68, 0xA3, 0x5E, 0x51, 0x9D, + 0xE7, 0x69, 0xD9, 0x04, 0x13, 0x0E, 0x3E, 0x00, 0x03, 0x99, 0x81, 0x67, 0xAA, 0x9A, 0x85, 0xD4, 0x2C, 0x79, 0xB6, 0x78, + 0x56, 0xDE, 0x3E, 0x35, 0x21, 0xF4, 0x0A, 0xD2, 0x9E, 0xFC, 0x84, 0x18, 0x90, 0xDE, 0x0D, 0x95, 0x93, 0x69, 0x8D, 0x90, + 0x83, 0x19, 0x5D, 0xED, 0x09, 0x83, 0x9A, 0xD6, 0xC0, 0xFD, 0x37, 0x13, 0x2C, 0x93, 0x5D, 0xE6, 0xC1, 0x5D, 0x0A, 0x35, + 0xD2, 0xB3, 0x8E, 0xC6, 0x81, 0x1F, 0x14, 0x44, 0x11, 0xCE, 0xA4, 0xB2, 0xBD, 0x82, 0x95, 0xC0, 0x4E, 0xDE, 0xCE, 0xE6, + 0xE0, 0x7C, 0xDB, 0xC3, 0x05, 0x16, 0xD6, 0xD5, 0x12, 0xB7, 0xA3, 0x83, 0x0D, 0xF6, 0x13, 0xBB, 0xF1, 0x19, 0x4D, 0xD5, + 0x6A, 0x35, 0xCD, 0x49, 0x5B, 0xBC, 0x6B, 0x49, 0x8A, 0x05, 0xD3, 0x97, 0x0D, 0x34, 0x17, 0xFF, 0xCB, 0x06, 0x94, 0xD2, + 0xF7, 0xFA, 0x08, 0x0F, 0xE5, 0x4C, 0xDF, 0x97, 0x0C, 0x7C, 0x7E, 0xFB, 0x6B, 0x13, 0xE4, 0x85, 0x39, 0x88, 0x2E, 0x2C, + 0x5B, 0x1E, 0xF1, 0x6C, 0x2A, 0xF3, 0x53, 0x13, 0x56, 0x82, 0x0E, 0x5C, 0x7D, 0x3A, 0x4A, 0xAB, 0x0B, 0x1A, 0xC3, 0x60, + 0xD8, 0xD0, 0x87, 0xE8, 0xFA, 0x58, 0xDE, 0x70, 0x5D, 0xBC, 0x1F, 0xBD, 0x20, 0x39, 0x26, 0x9C, 0x88, 0x38, 0xD4, 0xA3, + 0xAF, 0x21, 0x1B, 0x98, 0xBF, 0x61, 0xDF, 0x51, 0x46, 0x19, 0x8E, 0x5D, 0xA9, 0xF0, 0x86, 0x21, 0x7D, 0x11, 0x2A, 0x5E, + 0x36, 0x34, 0x5C, 0x8A, 0x99, 0x39, 0xD0, 0x04, 0x19, 0xBC, 0x8E, 0x31, 0x3E, 0x10, 0x4B, 0xD4, 0x5C, 0x2A, 0xBD, 0xB8, + 0x11, 0xD0, 0x84, 0x0A, 0x7D, 0x66, 0x39, 0xE1, 0xCA, 0xBE, 0x40, 0x25, 0xD5, 0xF5, 0x6F, 0x2E, 0x34, 0xC3, 0xF7, 0xFD, + 0x1B, 0x65, 0xB0, 0x22, 0x24, 0xB2, 0x27, 0xF8, 0x3B, 0xBF, 0x06, 0x09, 0x0C, 0x1D, 0xB6, 0xBD, 0xB1, 0x82, 0x14, 0x86, + 0x7A, 0xD7, 0x5C, 0xC1, 0x12, 0xC0, 0x2E, 0xEA, 0x67, 0xA0, 0xED, 0xB2, 0xBF, 0x31, 0x77, 0xED, 0x7A, 0x84, 0x72, 0x60, + 0x34, 0x11, 0xF6, 0x1E, 0xAC, 0x90, 0x9E, 0xE7, 0x69, 0x4C, 0x94, 0xDB, 0x30, 0xF8, 0x5B, 0x47, 0xE2, 0xB9, 0xF1, 0xEF, + 0x2A, 0x66, 0x08, 0x9B, 0x3F, 0x53, 0xF2, 0x3D, 0x83, 0x49, 0x69, 0xFE, 0x92, 0xB8, 0xD5, 0xA0, 0xD6, 0xC9, 0x2C, 0xF0, + 0x1F, 0x29, 0x74, 0xD0, 0xFF, 0x8F, 0x9F, 0x01, 0xFF, 0x2E, 0xB0, 0x8B, 0x53, 0x69, 0xD0, 0x3F, 0xF7, 0x86, 0x16, 0x6A, + 0x5D, 0xC7, 0x28, 0xBF, 0xC3, 0xBE, 0xE2, 0x01, 0x73, 0xCA, 0x18, 0xEF, 0xD2, 0x84, 0xE1, 0x02, 0x72, 0x0B, 0x86, 0xAF, + 0x14, 0x69, 0x21, 0x81, 0xC0, 0xFD, 0x35, 0xB7, 0xA8, 0x84, 0x34, 0x57, 0x26, 0x78, 0xB7, 0x31, 0x20, 0xB7, 0x65, 0xFB, + 0x2E, 0x94, 0x51, 0x57, 0x55, 0x8B, 0x60, 0xE7, 0x66, 0x23, 0x7A, 0x98, 0x0E, 0x65, 0xAE, 0x59, 0x78, 0x8A, 0xFA, 0x56, + 0x3F, 0xED, 0x19, 0xD7, 0x72, 0x80, 0xFE, 0xD9, 0xF4, 0xEA, 0x01, 0x86, 0xA6, 0x78, 0xE0, 0x10, 0x37, 0x58, 0x2B, 0xAA, + 0x74, 0x10, 0x63, 0xE7, 0xF0, 0xA2, 0x6A, 0x41, 0x27, 0x1B, 0xA5, 0x13, 0x37, 0xAE, 0xF0, 0x2C, 0x8B, 0xA1, 0xF2, 0xFB, + 0x5B, 0xB9, 0x1D, 0xEA, 0xF1, 0x66, 0xC5, 0x38, 0x7C, 0x44, 0x8E, 0xD9, 0x7E, 0x84, 0x5A, 0xA1, 0x93, 0x21, 0x64, 0x08, + 0xB1, 0x61, 0xF0, 0x0C, 0x7D, 0x2E, 0x7B, 0x21, 0x2C, 0x50, 0x13, 0x99, 0x19, 0xB6, 0x44, 0xDE, 0x91, 0x10, 0x2B, 0x0D, + 0x65, 0x64, 0x61, 0x54, 0xFE, 0x3A, 0x06, 0xA0, 0x7F, 0xF8, 0x26, 0xCE, 0x39, 0xA0, 0x1F, 0x1C, 0xD9, 0x48, 0x15, 0x66, + 0x47, 0x1E, 0xC4, 0x1F, 0xB7, 0xB4, 0xBB, 0x93, 0xA6, 0xC5, 0xDB, 0x95, 0x36, 0xC5, 0x59, 0xF0, 0xCF, 0xA1, 0x52, 0xB9, + 0x0C, 0xB4, 0x6D, 0x9F, 0x93, 0xB5, 0xCA, 0x97, 0x04, 0xB2, 0xF3, 0x04, 0x24, 0xD1, 0x77, 0x78, 0x7D, 0x80, 0x02, 0x17, + 0x13, 0x0E, 0xC4, 0xB4, 0x35, 0x51, 0x1B, 0xAA, 0x29, 0x89, 0x25, 0x7A, 0xE8, 0xF0, 0x0D, 0x92, 0x86, 0x2D, 0xE8, 0xB6, + 0x55, 0x72, 0x39, 0xEF, 0x44, 0x3C, 0xA9, 0xE7, 0x54, 0x1C, 0xE9, 0x20, 0x44, 0x6C, 0xAE, 0xB5, 0x22, 0x5E, 0x34, 0x59, + 0xCF, 0x65, 0xDE, 0x2E, 0xBA, 0x7B, 0x29, 0x26, 0xAC, 0x17, 0xE6, 0xE2, 0x89, 0x79, 0x70, 0x5A, 0xA5, 0xF9, 0x40, 0x2B, + 0x71, 0xCE, 0xEA, 0x32, 0x3B, 0xB9, 0x46, 0x72, 0x4C, 0x90, 0x07, 0xC3, 0xA5, 0xD6, 0xF5, 0xE2, 0xEA, 0x6D, 0x4B, 0x52, + 0xE0, 0xCD, 0x21, 0x19, 0xC5, 0xF0, 0x6F, 0xB1, 0x4C, 0xC6, 0xBE, 0x2E, 0xC4, 0x2C, 0x43, 0x57, 0x2D, 0xC4, 0xF5, 0xE3, + 0x70, 0xF6, 0x72, 0x79, 0x0A, 0x83, 0xB3, 0xFD, 0x04, 0xD4, 0x4D, 0xC5, 0x10, 0x27, 0xA5, 0xD7, 0x5F, 0xFA, 0x2E, 0x9A, + 0x2D, 0x99, 0xB2, 0x06, 0x56, 0xB6, 0x69, 0x41, 0xDC, 0x4A, 0xE3, 0x62, 0x94, 0xE8, 0x1E, 0x0F, 0xEC, 0x1D, 0xC1, 0x5F, + 0xBD, 0xFA, 0x8E, 0x17, 0x1B, 0xE7, 0xED, 0x81, 0x84, 0xB8, 0x15, 0x68, 0xDD, 0x10, 0xAD, 0xEC, 0x85, 0x3E, 0x44, 0x53, + 0x5C, 0x99, 0xC7, 0x3B, 0xC6, 0xBB, 0xD9, 0xAA, 0x7E, 0xDE, 0xD5, 0x4A, 0x25, 0x83, 0x48, 0x5F, 0x68, 0xC7, 0xAF, 0x1A, + 0x19, 0x7E, 0xFF, 0x58, 0xA2, 0x1D, 0x54, 0xBE, 0x33, 0x7F, 0xEA, 0x66, 0x69, 0xC6, 0x80, 0x2E, 0x4C, 0x56, 0x3A, 0xBF, + 0x0F, 0x31, 0xC3, 0xD6, 0x8D, 0x75, 0x69, 0x2B, 0xE2, 0xDF, 0x97, 0xA8, 0xBE, 0xF3, 0x57, 0x4B, 0x0C, 0xDD, 0xCF, 0xCB, + 0x5E, 0xA4, 0x75, 0x7F, 0xD4, 0x94, 0x45, 0x9F, 0xAB, 0x56, 0x4A, 0x60, 0x14, 0x1B, 0x80, 0x66, 0xE7, 0x45, 0xEB, 0xD3, + 0x74, 0x2C, 0x2B, 0xAA, 0xBB, 0xF1, 0x8C, 0xD0, 0x05, 0xC1, 0x59, 0xFA, 0x09, 0x25, 0x7A, 0x32, 0x40, 0x80, 0x50, 0x47, + 0x5A, 0xE8, 0x59, 0x77, 0x0D, 0x84, 0xB9, 0x28, 0x2F, 0xFF, 0x2F, 0x0D, 0xA1, 0x46, 0x7D, 0x56, 0xA8, 0xC4, 0x99, 0x63, + 0xB2, 0x08, 0x8B, 0x04, 0xA5, 0x27, 0xD9, 0xD9, 0xB4, 0x4E, 0xB9, 0xDF, 0x38, 0xF2, 0x40, 0x33, 0x72, 0x0B, 0x85, 0x57, + 0x59, 0x95, 0x45, 0x13, 0x7A, 0x4F, 0x8A, 0x9E, 0x3A, 0x55, 0x88, 0xB8, 0x76, 0x8E, 0x02, 0x94, 0x0F, 0x90, 0x78, 0x12, + 0x13, 0x41, 0xC0, 0x1D, 0xBA, 0x3F, 0xF5, 0x32, 0xFA, 0x09, 0xFF, 0x7C, 0x1D, 0x80, 0xD1, 0x70, 0xF2, 0xB6, 0x11, 0x8C, + 0xA5, 0x6B, 0x41, 0xB3, 0xE0, 0x47, 0xDE, 0x6A, 0xE3, 0x65, 0x74, 0x02, 0xE2, 0xC6, 0xFF, 0x5C, 0x70, 0xE2, 0xF8, 0xE0, + 0x7F, 0xC5, 0x2E, 0x67, 0x39, 0xF8, 0x0A, 0x34, 0x2B, 0x97, 0x88, 0x2E, 0xCA, 0x60, 0xE8, 0xD8, 0x11, 0xF4, 0x37, 0x43, + 0xCC, 0x74, 0x40, 0xC7, 0x23, 0x98, 0xBC, 0x05, 0x5E, 0x6D, 0xFC, 0x4E, 0xBB, 0x71, 0xFC, 0xF5, 0x98, 0xD6, 0x05, 0x14, + 0x23, 0xBB, 0x92, 0x3E, 0xA8, 0x40, 0xA7, 0x8B, 0x99, 0x03, 0x20, 0x99, 0x9D, 0x3A, 0x65, 0x05, 0x49, 0xDB, 0x5E, 0xFA, + 0xEA, 0xA0, 0x54, 0x75, 0xE1, 0xFD, 0x1C, 0x88, 0x52, 0x9D, 0x91, 0x97, 0xAB, 0xEF, 0xF4, 0x8E, 0x66, 0xC3, 0xD9, 0x49, + 0x3F, 0xAD, 0xEA, 0x3E, 0xE3, 0x5C, 0x0D, 0xFC, 0x70, 0x28, 0xE4, 0x54, 0xD6, 0xCB, 0x79, 0xF8, 0xFE, 0xA1, 0xE3, 0x33, + 0xD2, 0xBF, 0x9C, 0x97, 0xCC, 0x75, 0xC0, 0x1F, 0x31, 0x7F, 0xDA, 0x7A, 0x8A, 0x4E, 0x7C, 0x71, 0x9D, 0xC4, 0x53, 0x64, + 0x49, 0x6B, 0x12, 0xBD, 0x98, 0x2D, 0x30, 0x04, 0x2B, 0x27, 0xB3, 0xA8, 0xC9, 0x53, 0xBB, 0x90, 0x68, 0xFF, 0xCE, 0xA6, + 0xC3, 0xA9, 0x51, 0x60, 0xCC, 0x7F, 0xB3, 0x07, 0x76, 0xBA, 0x8F, 0xC3, 0x2A, 0xDB, 0xA2, 0x8D, 0xBB, 0x78, 0x3F, 0x69, + 0xD7, 0xDD, 0xE3, 0xE7, 0x43, 0x5C, 0x82, 0xD3, 0x9E, 0xFD, 0xF4, 0x65, 0x9E, 0x1E, 0x54, 0x68, 0x67, 0x1B, 0xAD, 0x7F, + 0xC0, 0x25, 0x19, 0x42, 0xDD, 0xFE, 0xA3, 0x68, 0x90, 0x77, 0xD5, 0xB3, 0x16, 0x78, 0x0B, 0xB8, 0xCF, 0x95, 0xB8, 0x93, + 0x12, 0xA2, 0xCE, 0x06, 0x74, 0xD7, 0x8C, 0x39, 0x59, 0x1C, 0x95, 0xC1, 0xDA, 0x16, 0x54, 0xE1, 0x50, 0x3F, 0x85, 0x25, + 0x75, 0xF5, 0x23, 0x11, 0xA1, 0x7D, 0xFD, 0x3A, 0x47, 0x74, 0x6B, 0xCC, 0x20, 0x56, 0xFE, 0x61, 0xF1, 0x81, 0xD4, 0xEE, + 0x97, 0x55, 0xB5, 0xF2, 0x5A, 0x74, 0x07, 0xF0, 0x44, 0x51, 0x51, 0x05, 0x80, 0xD6, 0x01, 0xFA, 0x1B, 0x93, 0x8E, 0x88, + 0xB1, 0xCA, 0xDC, 0xB8, 0x83, 0x09, 0xEF, 0xDF, 0x08, 0xF1, 0xA3, 0x9A, 0x25, 0x02, 0xB4, 0x03, 0xC6, 0xB4, 0x78, 0xDA, + 0x9A, 0x35, 0x27, 0xCC, 0xF9, 0xFF, 0xFD, 0x76, 0xAE, 0xE0, 0x47, 0x64, 0x6C, 0x56, 0x20, 0x85, 0x11, 0x39, 0xB7, 0x27, + 0xF9, 0xBB, 0xD4, 0x8D, 0x9A, 0x80, 0x6C, 0x63, 0x34, 0x79, 0x20, 0x2A, 0xFE, 0xD0, 0xBF, 0x7D, 0xA7, 0x39, 0x8B, 0xA2, + 0xCB, 0xA3, 0xBE, 0xE8, 0x3C, 0xC6, 0x7E, 0x92, 0x83, 0xCD, 0x47, 0x68, 0x49, 0xC7, 0x28, 0x10, 0x28, 0x3E, 0x31, 0xA2, + 0x15, 0x48, 0x79, 0xD5, 0x00, 0x8C, 0x01, 0x88, 0x18, 0xFD, 0x74, 0x1C, 0x5B, 0x70, 0x5C, 0xB2, 0xD2, 0x33, 0x2F, 0xCD, + 0x36, 0x0F, 0x17, 0xFD, 0xC7, 0x3C, 0x74, 0x35, 0xAB, 0x5D, 0x5C, 0xF3, 0xC7, 0x0A, 0x5B, 0x08, 0x97, 0xBA, 0xC9, 0xD1, + 0x10, 0x2E, 0xF1, 0xA2, 0x24, 0x63, 0x80, 0x0A, 0xFD, 0x0A, 0xF0, 0xCA, 0x44, 0xCD, 0x08, 0xB5, 0x2C, 0x4D, 0x71, 0xEF, + 0xE2, 0x5A, 0x66, 0x92, 0x6A, 0x50, 0x65, 0x33, 0xC5, 0x01, 0xC0, 0xBE, 0xF0, 0x68, 0x41, 0x44, 0xC4, 0x8F, 0xEB, 0x06, + 0x6F, 0x57, 0xC8, 0x04, 0x65, 0xBD, 0xA2, 0x57, 0x54, 0x4D, 0x01, 0xEE, 0x26, 0xC1, 0x00, 0x69, 0x00, 0xDF, 0x7F, 0x1F, + 0x8F, 0x92, 0x99, 0xA4, 0x76, 0xEB, 0x30, 0x67, 0x02, 0xA8, 0x28, 0xC4, 0x9E, 0x14, 0x76, 0x00, 0xB9, 0x79, 0xAD, 0xC6, + 0xF7, 0x6D, 0x50, 0xB2, 0x03, 0xA9, 0x6C, 0xA7, 0x67, 0xF5, 0x21, 0xB7, 0x24, 0xE5, 0x33, 0x49, 0x27, 0x30, 0x0F, 0xC1, + 0x0E, 0x26, 0xD9, 0xB4, 0xE6, 0xAD, 0x9D, 0xFC, 0xC7, 0x66, 0xF5, 0x87, 0xD7, 0x49, 0x07, 0x74, 0x26, 0x8C, 0x5A, 0xF6, + 0x6B, 0xE4, 0x81, 0x08, 0xAF, 0x56, 0x6C, 0xF3, 0x8C, 0x71, 0x7F, 0x81, 0x0A, 0xB2, 0x1D, 0x41, 0xF5, 0x42, 0x12, 0xE9, + 0xA5, 0x22, 0x34, 0x5D, 0x2C, 0xA7, 0x51, 0x35, 0x5E, 0xDC, 0x3D, 0x64, 0x6B, 0x06, 0x61, 0x3A, 0x25, 0x03, 0xDA, 0x3C, + 0x87, 0xE4, 0x5E, 0xF3, 0x22, 0x31, 0x63, 0xE7, 0x2D, 0x05, 0x15, 0xE7, 0x6F, 0x4F, 0xB2, 0x5C, 0xA4, 0xA5, 0xE6, 0xE6, + 0xAC, 0x50, 0x38, 0x0C, 0xD6, 0xFA, 0xC4, 0x41, 0xA7, 0xC4, 0xC4, 0x78, 0x20, 0x5D, 0xE2, 0x09, 0xC5, 0x21, 0xD5, 0x76, + 0x6D, 0xAC, 0x0C, 0x52, 0xAF, 0x6F, 0xD4, 0x46, 0x15, 0x48, 0x58, 0x49, 0xAC, 0xFC, 0xBE, 0x41, 0x39, 0x18, 0xEB, 0x39, + 0x46, 0xCB, 0x34, 0x6D, 0x67, 0xF7, 0x29, 0xBA, 0x2D, 0xCE, 0x23, 0x4B, 0xAE, 0x7A, 0xE6, 0x98, 0xF2, 0x6E, 0xE2, 0xBB, + 0x16, 0xDF, 0x15, 0x63, 0x6E, 0x20, 0x7E, 0x60, 0xAB, 0xED, 0x5F, 0x6F, 0x6E, 0x30, 0x3B, 0x96, 0xFD, 0x64, 0x9E, 0xE2, + 0x2C, 0x52, 0xFD, 0xDD, 0x37, 0x70, 0x14, 0x48, 0x15, 0xC6, 0xED, 0xA6, 0xD5, 0x2F, 0x51, 0xE1, 0x6A, 0x35, 0x13, 0xD9, + 0x33, 0xAA, 0x76, 0xB3, 0x0C, 0xA0, 0xBC, 0x4F, 0x71, 0xB3, 0xB5, 0xF1, 0x1B, 0xCD, 0x0C, 0xF9, 0x21, 0xCE, 0x7D, 0x8E, + 0x0D, 0x83, 0x01, 0xC5, 0x0B, 0x69, 0xE4, 0x71, 0x45, 0x32, 0x36, 0xF5, 0xD4, 0xBB, 0x65, 0xA7, 0xE3, 0xC8, 0x3D, 0x9F, + 0x24, 0x2E, 0x3D, 0xAC, 0xCD, 0xA5, 0xB4, 0xD9, 0xB2, 0x1B, 0x2A, 0x42, 0x47, 0x70, 0x58, 0x74, 0xD6, 0xFC, 0xDB, 0x03, + 0xDA, 0xFB, 0x5F, 0x34, 0x5F, 0xF6, 0xB6, 0xE1, 0x53, 0x3F, 0xEF, 0x85, 0x07, 0xFE, 0xDC, 0x7F, 0x4D, 0x87, 0x41, 0x43, + 0xB2, 0x3D, 0xE0, 0x32, 0x2E, 0xA7, 0x75, 0xE5, 0xF4, 0x56, 0x0B, 0x07, 0xA4, 0xC5, 0x93, 0x73, 0x42, 0x14, 0x5B, 0xDF, + 0xF4, 0x95, 0x7D, 0xE6, 0xCB, 0x57, 0x68, 0x0E, 0x17, 0x5C, 0xFE, 0x8A, 0xB5, 0x68, 0xAD, 0xC8, 0x4D, 0x88, 0x9D, 0xF5, + 0x81, 0x44, 0x91, 0x2A, 0xD2, 0x36, 0x55, 0xB9, 0x9C, 0x46, 0x66, 0x3F, 0x25, 0x08, 0xC6, 0x99, 0x84, 0xF6, 0x35, 0x75, + 0x47, 0x6B, 0x67, 0x67, 0xBC, 0xB7, 0x31, 0x96, 0x05, 0x2B, 0x77, 0x47, 0xFC, 0x67, 0xBC, 0xE8, 0xE6, 0x1A, 0x03, 0x10, + 0x56, 0x0A, 0x1F, 0xA6, 0xEB, 0xC0, 0x9F, 0xB3, 0xFB, 0xE0, 0x3C, 0xE8, 0x46, 0xAD, 0xB2, 0x3D, 0x14, 0xFD, 0xBF, 0x5D, + 0x8F, 0x73, 0xE7, 0xEC, 0x96, 0x5C, 0x38, 0xF2, 0xC4, 0xF9, 0xFB, 0xAD, 0x07, 0xD1, 0xB0, 0xC2, 0x86, 0x4C, 0x56, 0x8D, + 0x4B, 0xB2, 0x19, 0xCD, 0xCD, 0xCB, 0xDD, 0x3C, 0x8A, 0x11, 0x23, 0x18, 0xC8, 0x7A, 0xE2, 0x8C, 0xC5, 0xE5, 0x57, 0xE2, + 0x54, 0x3F, 0x89, 0x16, 0xBC, 0x54, 0x93, 0x68, 0xFC, 0xD5, 0x6F, 0xFF, 0xFF, 0xFF, 0x3E, 0x3D, 0x68, 0x0D, 0xF9, 0x20, + 0x73, 0x8F, 0x42, 0x1A, 0xAB, 0x24, 0xAA, 0x94, 0x84, 0xCF, 0xF3, 0xE0, 0x20, 0xF0, 0xDA, 0x52, 0xFA, 0x45, 0x60, 0x80, + 0xAD, 0xEE, 0x67, 0x4E, 0x3B, 0x6E, 0xFE, 0x72, 0xF4, 0x61, 0x96, 0xF6, 0x14, 0xAF, 0x81, 0xD2, 0x44, 0xEF, 0x35, 0x01, + 0xA3, 0x62, 0x77, 0x17, 0xE2, 0x26, 0x19, 0x66, 0x86, 0x87, 0xBD, 0x53, 0x36, 0x26, 0x36, 0x11, 0x38, 0x99, 0x0B, 0xBB, + 0xF3, 0x87, 0x00, 0xAC, 0x55, 0xAF, 0x68, 0x9E, 0xEE, 0x49, 0x8E, 0xD4, 0xE5, 0xE9, 0xFA, 0xF5, 0xF4, 0xF8, 0x93, 0x54, + 0x9E, 0x98, 0x40, 0x9F, 0xAA, 0x94, 0x21, 0x87, 0x3D, 0xC1, 0x75, 0xBB, 0x84, 0x1D, 0xC5, 0xA7, 0x6A, 0x7C, 0xAE, 0x12, + 0xBE, 0xE7, 0xAF, 0xD4, 0xB9, 0xA5, 0x5B, 0x31, 0x3C, 0xDA, 0xAF, 0x7C, 0x6C, 0xBA, 0x0F, 0xAC, 0x4E, 0x05, 0xC1, 0x58, + 0x38, 0x76, 0xD1, 0xFB, 0x84, 0x49, 0x93, 0xEE, 0xF8, 0xFD, 0x2A, 0x0C, 0xA3, 0x2B, 0x22, 0x5B, 0x56, 0xB7, 0xF5, 0x6B, + 0x75, 0xA8, 0xF2, 0x2E, 0xE6, 0xFC, 0xF6, 0xAB, 0x6F, 0xE4, 0x0A, 0xC4, 0xD4, 0xD2, 0x3B, 0xF7, 0x24, 0x07, 0xFB, 0x29, + 0x50, 0x70, 0xA7, 0x4B, 0x23, 0xC9, 0xAD, 0x4D, 0xD6, 0x95, 0x13, 0xF6, 0x60, 0xDA, 0xF3, 0x6E, 0xD2, 0x70, 0x4F, 0x49, + 0x49, 0x54, 0x59, 0x0C, 0x78, 0xCA, 0x10, 0x7F, 0xBD, 0xA1, 0xA0, 0x4C, 0xC7, 0xAD, 0x0B, 0x4D, 0x49, 0xDD, 0xEC, 0x44, + 0xD7, 0xCA, 0xC2, 0x2A, 0x69, 0xF2, 0x31, 0xD8, 0x20, 0x98, 0x22, 0x7A, 0x23, 0x0F, 0xCB, 0xF8, 0x44, 0x70, 0x8A, 0x79, + 0x7D, 0xA1, 0x3C, 0x12, 0x67, 0xA4, 0x93, 0x81, 0x3E, 0xC3, 0x99, 0xAD, 0xF0, 0x9B, 0x35, 0x18, 0x08, 0x02, 0x30, 0xD9, + 0xA8, 0x65, 0x02, 0x4F, 0xCD, 0x54, 0xE5, 0xAC, 0x56, 0xC9, 0x7A, 0x87, 0x81, 0x51, 0x15, 0x77, 0xB4, 0xBD, 0x2C, 0x5B, + 0xCC, 0x5D, 0x25, 0x20, 0x37, 0xF2, 0x1E, 0x8D, 0xCA, 0x55, 0xB4, 0xB0, 0xDA, 0x75, 0x45, 0x61, 0x65, 0xD1, 0x8D, 0xF3, + 0xBB, 0x4B, 0x3B, 0xA8, 0xC8, 0x1F, 0xD7, 0xC3, 0x5B, 0x56, 0xEE, 0x86, 0x41, 0xAD, 0xAF, 0x56, 0xC0, 0xDF, 0x37, 0x21, + 0x24, 0xBC, 0xB7, 0x25, 0x3C, 0x9C, 0xD2, 0xDE, 0x3F, 0x8E, 0x95, 0xB1, 0xD8, 0xD9, 0x9B, 0xFD, 0xF6, 0xC5, 0x9E, 0xC5, + 0x91, 0x76, 0x0E, 0xE4, 0x64, 0x6F, 0x50, 0xF7, 0x61, 0x97, 0x6A, 0xF8, 0x80, 0x90, 0xB4, 0xA7, 0x0B, 0x3E, 0x97, 0x74, + 0x58, 0xE5, 0x70, 0x87, 0x19, 0xD3, 0xE2, 0xFC, 0x4B, 0x4C, 0x9C, 0x01, 0xD1, 0x16, 0x62, 0xF8, 0xBA, 0x7E, 0xD3, 0xCD, + 0x72, 0x6A, 0x5B, 0xF8, 0xA5, 0x2C, 0xCF, 0xC4, 0x8B, 0x1F, 0x6A, 0xD8, 0x90, 0x57, 0x8F, 0x06, 0xC9, 0x1B, 0xA2, 0xAC, + 0x4B, 0xCE, 0x22, 0xA8, 0xD1, 0x7B, 0x0C, 0xAA, 0xDB, 0x05, 0xCC, 0x56, 0x10, 0x69, 0x54, 0xB6, 0x5F, 0xB6, 0xDA, 0x39, + 0xCE, 0x55, 0xF2, 0xCB, 0x0F, 0xFF, 0xC6, 0xB8, 0x50, 0x53, 0x11, 0x28, 0x43, 0x5E, 0x91, 0xEF, 0x47, 0x97, 0x0D, 0xAB, + 0x7A, 0x1B, 0x57, 0x44, 0x8F, 0x77, 0xAB, 0xBD, 0x26, 0xB6, 0x30, 0xB9, 0x52, 0x7F, 0x4E, 0xCA, 0x87, 0xD2, 0x5F, 0x54, + 0xA1, 0xFA, 0xE4, 0xF8, 0x2E, 0xB3, 0x13, 0xDD, 0x0A, 0x1D, 0x41, 0x1B, 0x40, 0xC1, 0xE8, 0x59, 0xB0, 0xBF, 0x1E, 0xAB, + 0x13, 0x9C, 0x5D, 0x2F, 0x47, 0x92, 0x04, 0xDE, 0x6D, 0x46, 0x16, 0x6F, 0x51, 0xD0, 0x13, 0xBB, 0xD4, 0xB1, 0x69, 0xE9, + 0x5B, 0x91, 0x84, 0x1A, 0xC8, 0x81, 0xA9, 0x45, 0x75, 0xD3, 0xCF, 0x22, 0x52, 0x73, 0x1B, 0x5F, 0x33, 0x7D, 0x15, 0x9B, + 0x09, 0x7F, 0x93, 0x6E, 0xD9, 0x75, 0x76, 0xDF, 0x8B, 0xDF, 0xA0, 0x3B, 0x30, 0x2B, 0x0E, 0x87, 0x25, 0xC4, 0x88, 0xC9, + 0x70, 0x8E, 0x08, 0xF8, 0xF0, 0x08, 0x08, 0xE6, 0xA1, 0x02, 0x2E, 0x50, 0xBA, 0x6C, 0xC1, 0xC6, 0xD5, 0xF7, 0x9E, 0x8C, + 0x31, 0x0B, 0x91, 0x36, 0xE0, 0x0D, 0x50, 0x07, 0x2D, 0xE1, 0x56, 0x59, 0xB5, 0xE6, 0x09, 0x99, 0xA1, 0x2E, 0xBE, 0xE4, + 0x19, 0xE2, 0x69, 0x17, 0xA6, 0xC6, 0x29, 0x06, 0xFF, 0x4C, 0x9F, 0x80, 0xA7, 0x5B, 0xD8, 0x36, 0x1E, 0xAF, 0xA2, 0x8C, + 0xEA, 0xC9, 0xA2, 0xA6, 0x5A, 0x40, 0xA7, 0x7E, 0xCF, 0x8C, 0x28, 0xBE, 0x5B, 0xE7, 0x6B, 0xF6, 0x74, 0xCB, 0x14, 0xE5, + 0x3D, 0xED, 0xA1, 0xFE, 0x30, 0x22, 0xF3, 0xC3, 0xA5, 0x63, 0xDD, 0xF0, 0xBE, 0x6B, 0xBF, 0xD7, 0x3F, 0x2C, 0xFC, 0x14, + 0x66, 0x21, 0xB0, 0xC7, 0x96, 0x95, 0x31, 0xF7, 0xA4, 0x5D, 0x7D, 0x64, 0x90, 0x44, 0xB1, 0x3B, 0xAD, 0x77, 0xF8, 0x2C, + 0x74, 0x39, 0x24, 0x8B, 0xA7, 0x8C, 0xE6, 0x5C, 0x36, 0xEB, 0x70, 0x7A, 0x71, 0x26, 0xFC, 0x33, 0xF6, 0xCD, 0x44, 0x3D, + 0x69, 0x66, 0xF1, 0x10, 0x42, 0x64, 0x1D, 0x32, 0xA2, 0x55, 0xDD, 0x09, 0xFF, 0xFF, 0x69, 0x05, 0xA6, 0xC9, 0xCD, 0x8F, + 0xF8, 0x9F, 0x8B, 0xEB, 0x61, 0x58, 0x3B, 0xEF, 0x03, 0x0A, 0x9F, 0x59, 0x3E, 0xAE, 0xC4, 0xC2, 0x7D, 0x30, 0x7A, 0xB9, + 0x76, 0x01, 0x22, 0xA7, 0x46, 0x1D, 0xB2, 0x82, 0x52, 0x8E, 0xCC, 0xBB, 0xD3, 0x4A, 0x50, 0xA9, 0x37, 0x38, 0x94, 0xFE, + 0xE8, 0x26, 0x20, 0xE4, 0x49, 0xD6, 0x34, 0xCA, 0xB6, 0xF7, 0x05, 0x96, 0x65, 0x1F, 0x9D, 0xEE, 0x6F, 0x7D, 0x2A, 0xFB, + 0xCF, 0xDE, 0x21, 0xAF, 0xD2, 0x4A, 0x7E, 0x64, 0xBF, 0xCD, 0x0C, 0xDB, 0xAC, 0x25, 0x0B, 0x8B, 0xC7, 0xC0, 0x17, 0xEC, + 0xB1, 0xE7, 0xF4, 0x11, 0x12, 0x3D, 0x9E, 0x36, 0xB1, 0x1F, 0x14, 0x48, 0x8D, 0x73, 0x34, 0x55, 0x5E, 0x7D, 0x12, 0x33, + 0x44, 0x95, 0xBA, 0xBE, 0xDE, 0xF5, 0x67, 0xB2, 0xAD, 0x8B, 0xE8, 0x87, 0xD4, 0x4E, 0x70, 0xF3, 0x24, 0x8D, 0x01, 0xA3, + 0xD7, 0x5D, 0x2F, 0xA1, 0x76, 0x93, 0x66, 0x54, 0xD6, 0x5F, 0x4C, 0xB7, 0xC6, 0x96, 0x97, 0x27, 0x3C, 0x1C, 0x45, 0x81, + 0x11, 0xDC, 0x83, 0x17, 0xDB, 0x6C, 0x02, 0x0E, 0x25, 0x3D, 0xDC, 0x37, 0x95, 0xE4, 0x62, 0x66, 0x55, 0x11, 0x72, 0x95, + 0x35, 0xFD, 0x35, 0x66, 0x90, 0xF0, 0x92, 0x77, 0x9B, 0xB8, 0x25, 0x62, 0x66, 0x87, 0x3C, 0x2E, 0xBC, 0x78, 0xA5, 0x2B, + 0x42, 0xD4, 0xD7, 0xD4, 0x15, 0xB5, 0xB5, 0x0B, 0xAA, 0x94, 0x71, 0x47, 0xE4, 0xE6, 0x55, 0x14, 0x6D, 0xE6, 0x93, 0x73, + 0x35, 0xB3, 0x43, 0x52, 0x3D, 0x28, 0xA4, 0x78, 0x50, 0xB6, 0x30, 0xB7, 0xC7, 0xDC, 0x02, 0xAA, 0x9D, 0x67, 0x20, 0x7B, + 0x48, 0xC3, 0x89, 0x9E, 0x5D, 0x07, 0x50, 0x9D, 0x09, 0x38, 0xC8, 0x3A, 0xC8, 0x1F, 0x86, 0x51, 0x7D, 0x94, 0x05, 0xFC, + 0xDC, 0x04, 0x7D, 0xA5, 0xC6, 0x4B, 0x13, 0xED, 0x43, 0xD4, 0x0E, 0xCD, 0x53, 0xCA, 0x8C, 0x1F, 0x54, 0x25, 0x3E, 0x68, + 0x29, 0x16, 0xFB, 0xBB, 0x56, 0xFF, 0xC6, 0xB3, 0x48, 0xA7, 0x97, 0xDD, 0x04, 0x7A, 0x58, 0xE6, 0x28, 0x87, 0x2A, 0xAC, + 0xB3, 0xDE, 0x48, 0x4A, 0xBC, 0x03, 0x96, 0xAC, 0x8F, 0xF1, 0x37, 0xE4, 0x4C, 0xBD, 0x09, 0x9E, 0x77, 0xB0, 0x27, 0x2E, + 0x0C, 0xFD, 0x77, 0x8D, 0x4D, 0x7B, 0x0F, 0x8B, 0xCE, 0xDC, 0x18, 0xBC, 0x98, 0xD2, 0x2D, 0xC9, 0x92, 0x9C, 0x5B, 0x7D, + 0xCE, 0xF4, 0x17, 0x5F, 0x9C, 0xAF, 0x10, 0x5A, 0x54, 0xFC, 0x07, 0x0B, 0x47, 0x2E, 0x7D, 0x3F, 0xB3, 0x52, 0x55, 0x47, + 0xC2, 0xC0, 0xFE, 0x2C, 0xF9, 0x31, 0x06, 0x42, 0xBF, 0xED, 0x86, 0x0C, 0xBB, 0x24, 0xE4, 0x82, 0x45, 0x0B, 0x08, 0x57, + 0x17, 0x8A, 0x20, 0xCE, 0xED, 0x4C, 0x3C, 0x56, 0x30, 0x01, 0x49, 0x1D, 0x69, 0x31, 0x2D, 0x96, 0x8B, 0x2A, 0x02, 0xA5, + 0xF3, 0xA2, 0xAB, 0x95, 0x59, 0xCD, 0xDB, 0x62, 0xB3, 0x6F, 0xF1, 0x11, 0x78, 0x32, 0xB5, 0xA2, 0xFD, 0xC8, 0x81, 0x31, + 0x58, 0xB3, 0xFF, 0xA2, 0x4A, 0x35, 0x2C, 0xD7, 0x01, 0x2E, 0x18, 0x6D, 0xBA, 0x75, 0x10, 0x8D, 0x7E, 0x69, 0x10, 0x54, + 0x4B, 0x54, 0xB0, 0x66, 0x24, 0x25, 0xB2, 0x61, 0x7B, 0x41, 0x4C, 0x84, 0x32, 0x6A, 0x47, 0x6C, 0x6B, 0x77, 0xD4, 0x3F, + 0x5A, 0x7C, 0xE6, 0x49, 0xC4, 0x8D, 0x89, 0x71, 0xD4, 0x5D, 0x69, 0xD3, 0xCB, 0x16, 0xDF, 0x84, 0x6C, 0x7A, 0xE4, 0x60, + 0xF3, 0x43, 0xDF, 0x49, 0x3A, 0xB6, 0x60, 0x1C, 0x09, 0xF9, 0xB0, 0x3C, 0x39, 0x6A, 0x32, 0xC2, 0xBD, 0xC1, 0xAC, 0xE0, + 0x90, 0x79, 0x0E, 0xFA, 0x6A, 0x19, 0x92, 0x6F, 0x46, 0x6B, 0x45, 0x39, 0xB5, 0xF8, 0x0B, 0xCF, 0x65, 0xE4, 0x63, 0x4A, + 0xF8, 0x81, 0xDA, 0x1E, 0x17, 0x8C, 0x33, 0xA3, 0xCB, 0x9A, 0xEB, 0x1F, 0x10, 0x65, 0x1D, 0xC0, 0x62, 0xB1, 0xD2, 0x28, + 0x9A, 0x6B, 0xA8, 0x01, 0xCF, 0xDA, 0xE5, 0x14, 0x30, 0x5A, 0x76, 0x4C, 0x2E, 0x81, 0x94, 0xAE, 0xED, 0x59, 0xBB, 0x4C, + 0x79, 0x00, 0x8A, 0x68, 0x12, 0xDD, 0x2A, 0x5A, 0x00, 0x00, 0x00, 0x9C, 0x19, 0xA6, 0xF6, 0xEB, 0x4C, 0xD2, 0xFA, 0x22, + 0x7F, 0x2F, 0x23, 0x57, 0xF4, 0x01, 0x8D, 0x22, 0x15, 0x88, 0xEB, 0x96, 0xE9, 0x2C, 0x54, 0x6F, 0x77, 0xDE, 0x12, 0x5B, + 0x2C, 0x09, 0xFB, 0x60, 0x9D, 0x34, 0x61, 0xEA, 0xC0, 0x54, 0x90, 0x07, 0xA4, 0x66, 0x5A, 0x25, 0x64, 0xBD, 0xA4, 0xC4, + 0x64, 0xBB, 0x34, 0x37, 0x89, 0xA1, 0xEA, 0xA2, 0x13, 0xD6, 0x04, 0x94, 0xA9, 0xEF, 0x2C, 0xE6, 0x53, 0xE5, 0x45, 0x3F, + 0x02, 0x71, 0x30, 0x2F, 0x8E, 0xAC, 0x54, 0x46, 0x62, 0xD2, 0x78, 0xB4, 0x80, 0x9D, 0x1B, 0x9D, 0xC1, 0xF2, 0x46, 0x21, + 0xC3, 0x06, 0x33, 0x38, 0x63, 0xD3, 0xF3, 0x92, 0xD2, 0x13, 0xE5, 0xC2, 0xD3, 0x3D, 0xFE, 0xEE, 0x0C, 0xCF, 0x3C, 0x42, + 0xAA, 0x36, 0x3F, 0xB7, 0x25, 0xB4, 0x8B, 0x64, 0x51, 0x2F, 0x14, 0x29, 0xE3, 0x35, 0x15, 0xD2, 0x84, 0x13, 0xB2, 0x70, + 0xCE, 0x94, 0x92, 0x37, 0xA9, 0x4F, 0x92, 0x70, 0x33, 0x1D, 0x7D, 0xA1, 0xE2, 0x1B, 0x69, 0x5E, 0x3F, 0x54, 0x6D, 0x12, + 0xF1, 0xFB, 0x78, 0x9A, 0x6F, 0x6D, 0x6D, 0x22, 0x02, 0x9D, 0xF5, 0x2A, 0x46, 0x54, 0x15, 0xD4, 0x80, 0xCC, 0x60, 0xC4, + 0x52, 0xD6, 0x0E, 0x8C, 0xA0, 0xE6, 0xFE, 0xFF, 0x23, 0xBA, 0x74, 0xAC, 0x6B, 0x98, 0xED, 0x6B, 0x81, 0xFE, 0x1B, 0xEB, + 0x11, 0x75, 0x69, 0x5C, 0x15, 0x92, 0x16, 0xA9, 0x4B, 0xD8, 0xFC, 0xBE, 0x78, 0xB8, 0x39, 0x3D, 0xE8, 0xB5, 0x78, 0xFE, + 0x88, 0x56, 0x29, 0x00, 0x2A, 0x1A, 0x97, 0xD7, 0x99, 0x7E, 0x69, 0x2C, 0xAA, 0x52, 0xF7, 0x99, 0x50, 0x2A, 0x9D, 0xBB, + 0xE9, 0xD6, 0xA1, 0x90, 0x91, 0x76, 0xC1, 0x3B, 0x1A, 0x15, 0x3D, 0xB3, 0x5A, 0x35, 0x96, 0x00, 0x55, 0x51, 0xEE, 0xDC, + 0x3C, 0xD3, 0x36, 0x20, 0xC7, 0xA6, 0x35, 0xE7, 0x1D, 0x7F, 0x9E, 0x10, 0x54, 0x50, 0xA0, 0xFB, 0x7D, 0xFD, 0x45, 0x4B, + 0x7E, 0xAD, 0x38, 0xB3, 0xD8, 0x1B, 0x29, 0x38, 0x89, 0xE5, 0x77, 0x9F, 0x98, 0x12, 0x57, 0xF6, 0xF8, 0x4A, 0x81, 0x95, + 0x43, 0x7C, 0x21, 0x2D, 0xED, 0xD4, 0x42, 0x7F, 0x76, 0xFF, 0x97, 0xA6, 0x02, 0xCA, 0x8C, 0x1A, 0x77, 0x3F, 0xA6, 0x5D, + 0x67, 0x10, 0x1C, 0xB5, 0x43, 0xEA, 0x16, 0xDB, 0x88, 0xE3, 0x73, 0xE6, 0x1D, 0xAE, 0x8F, 0x0B, 0xB1, 0x50, 0x80, 0xC9, + 0xBC, 0xB0, 0xF5, 0xF2, 0xAA, 0xC2, 0xB7, 0x2F, 0x92, 0x99, 0x11, 0xB3, 0x25, 0x7D, 0xAC, 0x54, 0xE8, 0x43, 0xD6, 0x60, + 0xB7, 0xED, 0x97, 0x3F, 0xB4, 0x82, 0xF9, 0x0B, 0xA9, 0x3E, 0x6D, 0xC9, 0xB6, 0x7C, 0xC3, 0xFB, 0x65, 0x94, 0x2A, 0x3D, + 0xB5, 0xD4, 0x2E, 0x84, 0x56, 0x58, 0x2B, 0x45, 0x50, 0x67, 0xC4, 0xC0, 0x03, 0x8D, 0x6B, 0x54, 0xA2, 0x35, 0x06, 0xB6, + 0x63, 0x31, 0xA8, 0xEF, 0x1D, 0xE3, 0x19, 0xAB, 0x2E, 0xCB, 0x66, 0xF8, 0x96, 0x86, 0x89, 0x11, 0x2D, 0xEC, 0x9E, 0xE3, + 0xA5, 0xC9, 0x73, 0xF3, 0xE7, 0xAE, 0xC9, 0x94, 0xB3, 0x53, 0x6C, 0x01, 0x2C, 0xD6, 0xD5, 0x4F, 0x76, 0xEC, 0xC5, 0xCA, + 0x54, 0x25, 0xFC, 0xEC, 0x18, 0x2D, 0x2A, 0x22, 0x04, 0x39, 0x25, 0xDD, 0xD8, 0x63, 0x08, 0xE5, 0xE4, 0xBA, 0x8C, 0xD9, + 0xDF, 0xB9, 0x3C, 0x06, 0x05, 0x98, 0x82, 0xC4, 0xF1, 0xE4, 0xEA, 0xFA, 0x2F, 0xEA, 0xB1, 0xD3, 0x9A, 0xB1, 0x0D, 0x16, + 0xEF, 0x8A, 0xC6, 0x93, 0x37, 0x8E, 0xC7, 0x84, 0x8C, 0xEB, 0x10, 0x6F, 0x1D, 0x2D, 0x1B, 0x0C, 0x85, 0xFA, 0xC4, 0xCF, + 0xFC, 0x1A, 0x02, 0x48, 0x5B, 0x81, 0x32, 0x3D, 0x38, 0x08, 0x4C, 0x42, 0xC3, 0x6A, 0x75, 0xEA, 0x65, 0x0B, 0x3A, 0x38, + 0x48, 0x8B, 0xD5, 0xB2, 0x1F, 0x5C, 0xA1, 0xFE, 0x7C, 0xB6, 0x21, 0xF8, 0x59, 0x77, 0x49, 0xCE, 0xCD, 0x6E, 0x2A, 0xAD, + 0x7E, 0x51, 0x66, 0xAB, 0xCB, 0x45, 0x33, 0x9A, 0xBD, 0xAC, 0xC8, 0xE6, 0xEC, 0xAF, 0x14, 0x31, 0xF5, 0xA0, 0x43, 0x88, + 0x80, 0x44, 0x35, 0x7B, 0x96, 0xB4, 0x1A, 0x32, 0x64, 0x3F, 0x96, 0xB6, 0x11, 0xF2, 0x6D, 0x2D, 0xC3, 0xCB, 0x4B, 0xD5, + 0x40, 0xB2, 0x4A, 0x23, 0x26, 0xDB, 0xAD, 0xE8, 0x54, 0xB5, 0x62, 0x17, 0x21, 0x24, 0x94, 0xB0, 0xF8, 0x94, 0xB4, 0xF0, + 0x90, 0xFE, 0xFC, 0x94, 0x3B, 0x34, 0xD0, 0xC5, 0xC5, 0xB2, 0xEC, 0xB2, 0x75, 0x96, 0x13, 0xBA, 0x6D, 0xC9, 0xCF, 0x95, + 0xB4, 0x63, 0xE9, 0x37, 0xFE, 0xD0, 0x85, 0x2C, 0x0A, 0x53, 0xA9, 0x3F, 0x07, 0x4F, 0xBF, 0xC6, 0x30, 0xF4, 0x6A, 0xA5, + 0x8F, 0x1E, 0xCC, 0xF6, 0xD5, 0xB5, 0x32, 0xFA, 0x2F, 0x38, 0xD3, 0x11, 0xFD, 0xAF, 0x7A, 0x23, 0x61, 0x5E, 0xFC, 0xF6, + 0x77, 0xF5, 0x51, 0x47, 0xAD, 0xA1, 0xF4, 0xE3, 0x4E, 0x5C, 0x13, 0x32, 0xC7, 0x76, 0xF5, 0xE7, 0xF6, 0xF6, 0x20, 0x43, + 0x58, 0x3A, 0xA5, 0xEF, 0x4E, 0xF5, 0x63, 0xE2, 0xA8, 0xD3, 0xFD, 0xF7, 0xF7, 0xF7, 0x5E, 0xB8, 0xD8, 0x97, 0xFC, 0x75, + 0x54, 0xA9, 0xA6, 0x56, 0xB8, 0x23, 0x16, 0x7D, 0xF8, 0xB8, 0x50, 0xA3, 0xDC, 0x4A, 0x0D, 0x6D, 0xB1, 0x32, 0xE7, 0xBA, + 0x8C, 0x66, 0x86, 0x24, 0xFE, 0xBD, 0x7C, 0x8B, 0xC4, 0xCB, 0xD9, 0x89, 0x5D, 0x39, 0x4C, 0xD8, 0xF7, 0xA5, 0xF1, 0xA8, + 0xB6, 0xBE, 0x51, 0xA3, 0x44, 0x2A, 0xAB, 0x7D, 0xDE, 0xB8, 0xFF, 0x6F, 0xAF, 0x56, 0xD7, 0xB8, 0x5E, 0x9E, 0x77, 0x8D, + 0xF0, 0x96, 0xBB, 0x5A, 0xD5, 0x6D, 0x9C, 0x1A, 0x2E, 0x7D, 0xF6, 0xEE, 0x7E, 0xFC, 0x50, 0x16, 0x6D, 0x62, 0x59, 0x0F, + 0xC2, 0xD3, 0x88, 0xDE, 0xB6, 0x20, 0xFE, 0xFE, 0x7F, 0xFD, 0x24, 0x3A, 0x96, 0xBE, 0x5E, 0x73, 0x55, 0x0F, 0x66, 0x18, + 0xDE, 0xDA, 0xF7, 0xEF, 0xFE, 0xFE, 0x51, 0xF2, 0x22, 0x69, 0x89, 0x0B, 0xBC, 0x5D, 0x50, 0xC1, 0xA0, 0x42, 0xFF, 0xFF, + 0xD7, 0xEF, 0x80, 0x0C, 0x8D, 0x40, 0x08, 0xC4, 0x1C, 0x60, 0xBB, 0x67, 0x4E, 0x9C, 0x15, 0x6E, 0xAC, 0x68, 0xA7, 0xE1, + 0xED, 0x0C, 0xC2, 0x15, 0xEE, 0x85, 0xD4, 0xC3, 0x4E, 0x9C, 0xC3, 0x34, 0x57, 0x31, 0x83, 0xDE, 0xEB, 0xC7, 0x01, 0xE2, + 0x79, 0x81, 0xD5, 0xEB, 0x7B, 0xE3, 0x4A, 0x25, 0x28, 0x83, 0x57, 0x22, 0x01, 0xA8, 0x5B, 0x55, 0x78, 0x0B, 0x4F, 0xF5, + 0x2A, 0x09, 0x5C, 0x4A, 0xB9, 0x6E, 0xAD, 0x3E, 0x83, 0x09, 0xC8, 0x60, 0x79, 0x0C, 0x18, 0x5A, 0x1F, 0x4F, 0xD1, 0x74, + 0x2D, 0x64, 0x04, 0x61, 0xA2, 0x84, 0x96, 0x11, 0x8D, 0x8E, 0x26, 0x76, 0x93, 0x21, 0x7F, 0x39, 0x71, 0x35, 0xFE, 0x03, + 0x23, 0xAB, 0x24, 0xB4, 0x97, 0x2F, 0xD1, 0x70, 0x9F, 0xC4, 0xF1, 0x61, 0xAD, 0x46, 0x1A, 0xD5, 0x9F, 0x61, 0xC3, 0x35, + 0x16, 0xD7, 0x67, 0xB4, 0x60, 0xE7, 0xDB, 0x88, 0xD7, 0x63, 0x30, 0x18, 0x8D, 0x1E, 0x98, 0x08, 0x3B, 0x99, 0x38, 0xC2, + 0x0B, 0x47, 0x6D, 0x52, 0x76, 0xB7, 0x2D, 0x19, 0x62, 0x7D, 0x82, 0x19, 0x1D, 0x69, 0x50, 0x25, 0x58, 0xE6, 0x13, 0x42, + 0x3B, 0x1F, 0x5D, 0x13, 0x88, 0xA1, 0xBD, 0xB9, 0x52, 0x69, 0x3A, 0x5A, 0xC7, 0xC6, 0x2C, 0x1D, 0xF9, 0xC5, 0x89, 0xDF, + 0x1B, 0x08, 0x30, 0x6E, 0xFB, 0x28, 0x57, 0x4A, 0xC6, 0xC1, 0xE5, 0x74, 0xF9, 0xDB, 0x69, 0x36, 0xDB, 0xB0, 0x75, 0x60, + 0x6D, 0x2C, 0x5A, 0x98, 0x4E, 0xED, 0x52, 0x91, 0x52, 0x98, 0xB5, 0x9A, 0xAA, 0xD2, 0x0A, 0x50, 0x05, 0xD0, 0x0C, 0x28, + 0xA0, 0xC5, 0x36, 0xEF, 0x46, 0x67, 0xFC, 0x12, 0x09, 0x03, 0xF4, 0x65, 0xE9, 0x2E, 0x5D, 0x9A, 0x83, 0xC3, 0xDB, 0x80, + 0xDE, 0x13, 0xE7, 0x22, 0x55, 0xA0, 0xDD, 0x3F, 0x64, 0xF2, 0x01, 0x7D, 0xA3, 0x57, 0x5F, 0x79, 0x93, 0x0D, 0x7A, 0x86, + 0xC1, 0x93, 0x15, 0xF7, 0x56, 0x5C, 0x6D, 0xF6, 0x95, 0x9C, 0x91, 0x55, 0x33, 0x50, 0x74, 0x81, 0x20, 0xBC, 0x0C, 0x90, + 0x9E, 0x9C, 0xC7, 0xB8, 0x1E, 0x80, 0x56, 0x74, 0xC5, 0xDB, 0x2D, 0x72, 0x2C, 0x9F, 0xE3, 0x20, 0xB1, 0x52, 0x14, 0xF7, + 0x1D, 0x9E, 0xCB, 0x74, 0x28, 0xD9, 0x05, 0x23, 0xF5, 0x8E, 0xDF, 0x6D, 0x35, 0x30, 0xDD, 0xB5, 0x52, 0xF2, 0x5D, 0xB8, + 0xBE, 0x72, 0x3A, 0x9C, 0xA1, 0x19, 0xE4, 0x35, 0xD2, 0xB4, 0xD1, 0x26, 0x99, 0xC1, 0xAC, 0xD6, 0xBA, 0x7B, 0x42, 0xD6, + 0xEB, 0x9D, 0x6B, 0xCF, 0x58, 0x41, 0x7A, 0xBC, 0xE7, 0xF1, 0x5E, 0xE7, 0x1D, 0xDD, 0x96, 0x32, 0xFB, 0xB2, 0x6D, 0x4F, + 0x66, 0xA2, 0x2D, 0x65, 0xB2, 0xBE, 0xDB, 0x16, 0xB7, 0x72, 0xE9, 0xB3, 0x54, 0x72, 0x8E, 0x13, 0x21, 0x34, 0x50, 0xF6, + 0x16, 0x58, 0xFB, 0x5D, 0xB6, 0x35, 0x3C, 0x7B, 0x29, 0xB5, 0xBE, 0x9C, 0x43, 0x3C, 0x2E, 0x98, 0x4C, 0x47, 0x91, 0xA9, + 0x7C, 0x38, 0x3C, 0xA8, 0x3D, 0xE6, 0x4E, 0x91, 0xC9, 0x02, 0xB4, 0xC7, 0xAC, 0xF9, 0xA0, 0xFC, 0xF4, 0xFF, 0x0F, 0x78, + 0x0B, 0x5A, 0xA7, 0x89, 0xC3, 0x3A, 0xBD, 0xD7, 0x2D, 0x4A, 0x26, 0xDF, 0x13, 0x72, 0x31, 0x7B, 0xCB, 0x18, 0xBF, 0x92, + 0xFC, 0x6F, 0x17, 0xCA, 0xE8, 0x37, 0x19, 0xFD, 0xF5, 0x3B, 0x7E, 0x8F, 0xE0, 0x84, 0x25, 0x37, 0x51, 0xFA, 0xE2, 0x97, + 0xC9, 0xD7, 0x53, 0x11, 0xFA, 0x64, 0xB5, 0x5C, 0x37, 0x53, 0xF4, 0x2F, 0xF1, 0x96, 0x94, 0x8A, 0x01, 0xF7, 0xE9, 0xD4, + 0x08, 0x7D, 0xB8, 0xB7, 0x60, 0x66, 0x63, 0x3C, 0x74, 0x7E, 0x53, 0xD8, 0xAD, 0xF1, 0x60, 0xC1, 0x8D, 0x7E, 0xE3, 0x4A, + 0xFE, 0xA0, 0xAD, 0xCD, 0x50, 0xE9, 0x21, 0x28, 0x5C, 0x1D, 0x1F, 0xF1, 0xE5, 0x82, 0xC3, 0xF9, 0x20, 0xC0, 0x98, 0x12, + 0x67, 0xE4, 0xB7, 0xD1, 0x49, 0x6D, 0x23, 0x00, 0x04, 0x6D, 0x9F, 0x13, 0x88, 0x8D, 0xF3, 0x15, 0x6E, 0xAD, 0x30, 0x3F, + 0x76, 0xFC, 0xF2, 0x37, 0x28, 0xE8, 0x26, 0x5B, 0x0B, 0x80, 0xFE, 0x47, 0x14, 0x22, 0x7D, 0xE4, 0x06, 0x31, 0x65, 0xD8, + 0x3D, 0x41, 0x41, 0x33, 0xDD, 0xE3, 0x69, 0x1A, 0x65, 0x98, 0x63, 0xCC, 0x62, 0xD8, 0xFB, 0x44, 0xA1, 0x62, 0x6B, 0x38, + 0xD0, 0x2B, 0x34, 0xB8, 0x34, 0xB4, 0x0E, 0x2A, 0xA7, 0x67, 0xCE, 0xD7, 0x15, 0xC4, 0x50, 0x62, 0x75, 0xC7, 0x17, 0x28, + 0x39, 0x7A, 0x7C, 0xB8, 0x8F, 0x74, 0x78, 0x96, 0x6F, 0x4E, 0xEC, 0x30, 0x8D, 0x27, 0x67, 0x38, 0xFE, 0xAB, 0xFF, 0x90, + 0x8B, 0x86, 0x8F, 0x3F, 0x6B, 0x6F, 0xEC, 0x9C, 0x72, 0x8B, 0xD7, 0xF7, 0x56, 0x2D, 0x71, 0x00, 0xC6, 0xA9, 0x77, 0x70, + 0x3C, 0xFF, 0xA2, 0x0A, 0xE1, 0x23, 0xBA, 0x01, 0x59, 0xFC, 0x88, 0xCC, 0x48, 0x88, 0xFA, 0xD1, 0xBD, 0x6B, 0xA0, 0x68, + 0xE6, 0x81, 0xAD, 0xAF, 0x3F, 0xD9, 0x89, 0xBE, 0x49, 0xD6, 0xE4, 0xEE, 0x55, 0x46, 0xAC, 0x49, 0xE7, 0x80, 0x2D, 0x04, + 0x8D, 0xAB, 0xCF, 0xD7, 0xDC, 0x31, 0x94, 0x64, 0x21, 0xD6, 0x71, 0x4F, 0xE5, 0x83, 0x7B, 0x6C, 0xB3, 0xAF, 0x2D, 0x59, + 0xAD, 0x58, 0xF5, 0x34, 0x9A, 0xEF, 0x5A, 0x35, 0x8F, 0x81, 0x9A, 0x1E, 0x0E, 0x03, 0x10, 0x6A, 0x4F, 0x9F, 0xD4, 0xCA, + 0x4B, 0xEF, 0x78, 0x7E, 0x09, 0xFD, 0xB4, 0x68, 0x93, 0x06, 0x70, 0x7D, 0xEE, 0x12, 0xF4, 0xCB, 0x7C, 0x5D, 0x5D, 0x8A, + 0xE6, 0x83, 0x85, 0xBE, 0x44, 0xBE, 0x55, 0x3A, 0x4A, 0x6A, 0x76, 0x1B, 0x37, 0xFD, 0x8F, 0x99, 0x2E, 0x7E, 0x5D, 0x5F, + 0xF4, 0x0A, 0xCF, 0x19, 0x30, 0x8D, 0xC5, 0x4A, 0x17, 0x8C, 0xDF, 0xFD, 0x45, 0xF0, 0x2A, 0x8D, 0x25, 0xB1, 0x56, 0xA6, + 0x67, 0xB0, 0x34, 0xD8, 0x17, 0x23, 0x14, 0x69, 0x56, 0x91, 0x2E, 0xE5, 0x13, 0x10, 0x3D, 0xA2, 0x1A, 0xF1, 0x86, 0x06, + 0xF4, 0x5E, 0x5B, 0x85, 0x70, 0xF6, 0xA2, 0x8E, 0x96, 0xC2, 0xB5, 0xA3, 0xEB, 0xD3, 0xA3, 0xE7, 0x1F, 0xB6, 0x74, 0xE1, + 0x00, 0x4C, 0xA5, 0x64, 0xB4, 0xB2, 0x1D, 0xB7, 0x9A, 0xD3, 0x19, 0xD5, 0xD4, 0x93, 0x5A, 0x20, 0xEC, 0x2C, 0x9A, 0x59, + 0x5D, 0x02, 0xF1, 0x37, 0x8F, 0xBC, 0xAD, 0xE2, 0xFB, 0x97, 0xCF, 0x16, 0xFB, 0xFF, 0x5E, 0xD1, 0xDC, 0x50, 0xF9, 0xB8, + 0x2D, 0xDD, 0x81, 0xC7, 0x66, 0x5A, 0x1E, 0x47, 0xF6, 0x7E, 0xE4, 0x34, 0x64, 0x1D, 0xB5, 0xEE, 0x6F, 0x94, 0x5E, 0x42, + 0x23, 0xE8, 0x81, 0xA0, 0xA8, 0x11, 0x93, 0xE4, 0xDC, 0x32, 0x5D, 0x4C, 0xAD, 0xFF, 0xF4, 0x89, 0x9D, 0x1F, 0x27, 0xEC, + 0xD3, 0xE3, 0xA1, 0x0E, 0xC1, 0xDB, 0x91, 0xEE, 0xC8, 0x88, 0x36, 0xAA, 0xA0, 0x94, 0x8D, 0x5E, 0xF1, 0xF3, 0xB8, 0xFC, + 0xC2, 0x64, 0xB2, 0x4B, 0x64, 0x99, 0xC0, 0x7F, 0x15, 0xF4, 0xA6, 0x0F, 0xB0, 0xD5, 0xC1, 0xED, 0x4B, 0x47, 0x0D, 0x0E, + 0xAC, 0x75, 0xED, 0xAB, 0x36, 0xD2, 0x11, 0x5E, 0x9E, 0x3B, 0x7B, 0x61, 0x40, 0xF9, 0x01, 0xFA, 0x62, 0x7D, 0xAD, 0x9B, + 0xFB, 0x8B, 0x99, 0xB9, 0x29, 0x1A, 0x66, 0x88, 0xAC, 0x68, 0xF6, 0xEA, 0x9D, 0xD2, 0x88, 0xBB, 0xB6, 0x9F, 0xA6, 0xDA, + 0x44, 0xF7, 0x4B, 0xDA, 0xB8, 0xAB, 0xCB, 0xBF, 0x97, 0xF7, 0xA0, 0xAE, 0x5E, 0xFC, 0x67, 0x8B, 0xEA, 0x35, 0xC4, 0xD0, + 0x66, 0x15, 0x1F, 0x6D, 0x12, 0x9F, 0x7E, 0x1E, 0xF3, 0x88, 0x90, 0xCA, 0xAC, 0x32, 0xBF, 0x41, 0x44, 0xBC, 0xBF, 0xF2, + 0x9B, 0x72, 0x7A, 0x67, 0x16, 0xEC, 0x0E, 0xB5, 0x23, 0xB0, 0xA2, 0x77, 0x09, 0x4E, 0x63, 0xDA, 0xF8, 0x18, 0x37, 0x61, + 0x3B, 0xE8, 0x70, 0x22, 0xC9, 0x0E, 0x3F, 0x50, 0xE5, 0x09, 0x09, 0x5E, 0x60, 0x6A, 0xB8, 0xE1, 0xAB, 0x21, 0x3F, 0x34, + 0x48, 0x41, 0xE3, 0x05, 0x91, 0xC2, 0x2C, 0x41, 0xF7, 0x17, 0x35, 0xD4, 0x99, 0xE2, 0x07, 0xE2, 0xC4, 0x07, 0x49, 0x0D, + 0x02, 0x51, 0x47, 0xDE, 0xCD, 0xE8, 0x0C, 0x46, 0xB3, 0x60, 0x45, 0xB1, 0x1F, 0x24, 0xD6, 0xA4, 0x1E, 0x64, 0x57, 0x26, + 0xD0, 0xEF, 0x89, 0x8B, 0xF7, 0xCB, 0x47, 0x90, 0xBF, 0x7D, 0xD0, 0x51, 0x17, 0x35, 0x7F, 0x81, 0xDF, 0xA5, 0x0C, 0xFC, + 0xF6, 0xCA, 0x1F, 0x19, 0x5A, 0xAD, 0x47, 0xE3, 0xF2, 0xB8, 0x72, 0x61, 0x0A, 0x17, 0x01, 0xED, 0x77, 0xC9, 0xF8, 0x09, + 0x3B, 0xBF, 0x08, 0xBD, 0x2C, 0x6A, 0xB1, 0xFB, 0xA0, 0x67, 0x4A, 0xFD, 0x76, 0xC8, 0x80, 0x1B, 0x66, 0xA0, 0x02, 0x09, + 0xD6, 0x69, 0xEF, 0x88, 0xCD, 0x5E, 0xAA, 0x38, 0x2F, 0x2C, 0x8F, 0xE5, 0x8C, 0xF9, 0x26, 0x5E, 0x9A, 0x84, 0x3D, 0x3C, + 0x22, 0x3D, 0x41, 0x3A, 0x26, 0x69, 0x25, 0xA1, 0xCD, 0x48, 0x6F, 0x8D, 0x64, 0x0A, 0x4D, 0x33, 0xC8, 0xE1, 0x4C, 0x2F, + 0x58, 0xEA, 0x35, 0xB5, 0xE1, 0x06, 0x59, 0x2D, 0x18, 0x84, 0x99, 0xFF, 0x5B, 0x48, 0x38, 0x79, 0x05, 0x03, 0x82, 0x44, + 0x0E, 0xF3, 0xBC, 0x61, 0x08, 0x61, 0x44, 0x31, 0xA1, 0xF4, 0x45, 0x1F, 0x7C, 0xCD, 0xF5, 0x69, 0xAA, 0xF2, 0xB4, 0xFC, + 0x09, 0x60, 0x51, 0x57, 0x56, 0x12, 0x49, 0x4D, 0x27, 0xC2, 0x97, 0xDA, 0x2B, 0xD1, 0xBD, 0x65, 0x88, 0x63, 0x69, 0xD8, + 0x9B, 0xE1, 0x07, 0x9E, 0xE2, 0xC3, 0xF0, 0xFC, 0x7C, 0xF2, 0x34, 0xD8, 0x1D, 0xFF, 0x6E, 0x20, 0xCD, 0x1F, 0x4D, 0x0E, + 0xFD, 0x01, 0xBB, 0x04, 0x3C, 0xF7, 0x50, 0x77, 0x29, 0x8B, 0x03, 0xE9, 0x89, 0xB1, 0xA4, 0xA6, 0x30, 0xAB, 0x82, 0xAF, + 0x30, 0xC5, 0x85, 0x54, 0x3D, 0x71, 0x99, 0xBB, 0x9D, 0xC9, 0x14, 0xAB, 0x7C, 0xDC, 0x23, 0xB8, 0xB9, 0xC7, 0x87, 0xFE, + 0x3F, 0x94, 0xD5, 0xAC, 0x69, 0x10, 0x35, 0x58, 0xD0, 0xA6, 0xEF, 0x8E, 0x6F, 0x9E, 0x0F, 0x5B, 0x4B, 0xB3, 0xA2, 0x14, + 0x2B, 0x5E, 0x14, 0x8B, 0xE8, 0x68, 0x62, 0x94, 0xE4, 0xB0, 0xC1, 0xBB, 0x71, 0xE6, 0x2A, 0xB0, 0xAA, 0x3C, 0x78, 0x62, + 0x2A, 0x89, 0x48, 0x21, 0xE1, 0x35, 0xAC, 0xCF, 0x30, 0x38, 0x64, 0x03, 0x62, 0x30, 0xD8, 0xF6, 0x77, 0x8E, 0xCB, 0x56, + 0xC9, 0xB0, 0x69, 0x40, 0x59, 0xF7, 0xF5, 0xF2, 0xE7, 0x32, 0x85, 0x93, 0xB2, 0x8D, 0x6B, 0x91, 0x75, 0xB3, 0x9D, 0xA2, + 0xF3, 0x79, 0x65, 0x02, 0xEA, 0x54, 0xDD, 0xEA, 0x91, 0x6C, 0x78, 0x1B, 0x43, 0x9E, 0x43, 0xFF, 0x5A, 0x3B, 0xED, 0xD7, + 0x00, 0x55, 0x16, 0xEB, 0x56, 0xA4, 0xE9, 0x6B, 0xF3, 0xB2, 0x51, 0xDC, 0xB9, 0xB9, 0xA1, 0x89, 0x28, 0xF6, 0x8C, 0xAC, + 0x92, 0xD1, 0x87, 0x97, 0x7E, 0xEE, 0xBF, 0x99, 0xCF, 0x7E, 0xE8, 0xD7, 0xC6, 0x85, 0x43, 0xF3, 0x6B, 0x45, 0x6C, 0x9D, + 0x42, 0xDE, 0x54, 0x9E, 0xC6, 0x37, 0x97, 0xC7, 0x83, 0x33, 0x24, 0x0D, 0x75, 0xD4, 0x4A, 0x57, 0x41, 0xAA, 0xC5, 0xCE, + 0x3E, 0x70, 0xB5, 0x13, 0x38, 0x1C, 0x2F, 0x8A, 0x85, 0x7F, 0x68, 0x88, 0xCF, 0xB9, 0xF6, 0x7C, 0xDE, 0xBD, 0x58, 0xA9, + 0xE8, 0x53, 0xFE, 0xF8, 0x0C, 0x7D, 0x46, 0xBB, 0x41, 0x88, 0xC4, 0x4F, 0x62, 0x34, 0xD5, 0x5C, 0xB0, 0x1E, 0xE9, 0xFD, + 0x8D, 0x5E, 0x41, 0xEE, 0xC0, 0xBA, 0x27, 0xD1, 0x3B, 0x7F, 0xBF, 0xC6, 0xCF, 0x53, 0x7C, 0x4C, 0x06, 0xF5, 0xDF, 0x71, + 0x3E, 0xC2, 0x2E, 0x74, 0x76, 0xE4, 0xB7, 0x62, 0xAD, 0xF8, 0x8E, 0x6A, 0xA0, 0xD8, 0x0E, 0x42, 0x00, 0x2C, 0x28, 0xB6, + 0x05, 0xC1, 0x7C, 0x0D, 0x40, 0x14, 0x13, 0x93, 0x80, 0xFF, 0xA4, 0x15, 0x6F, 0xAA, 0xDF, 0x53, 0xFF, 0xBA, 0xDD, 0xB1, + 0xC4, 0xCA, 0xE8, 0x23, 0x59, 0x81, 0xA0, 0xF3, 0x89, 0xC3, 0x93, 0xE4, 0x84, 0x56, 0x35, 0xB7, 0x95, 0xDD, 0xC4, 0x07, + 0xD5, 0x4C, 0x76, 0x07, 0xED, 0xEC, 0x5F, 0xE6, 0xFB, 0xC4, 0xF0, 0x9D, 0x68, 0x62, 0x96, 0xC3, 0x57, 0x64, 0xE0, 0x41, + 0x0A, 0xC1, 0x08, 0x5E, 0xEA, 0xA6, 0x40, 0x8D, 0xB2, 0xA6, 0x4F, 0xD3, 0x8B, 0xB4, 0xDA, 0xF2, 0x83, 0x29, 0x0D, 0x45, + 0x9E, 0xCA, 0x49, 0x9D, 0x3B, 0x67, 0x46, 0xC3, 0x56, 0xA6, 0x17, 0x54, 0x26, 0x28, 0x53, 0x52, 0x18, 0xA3, 0x82, 0x0C, + 0xAF, 0xAF, 0xA0, 0x95, 0x36, 0xA8, 0x24, 0x17, 0xF0, 0x10, 0x33, 0xF2, 0x1C, 0x1D, 0x74, 0x63, 0xA5, 0xC0, 0xBC, 0x50, + 0x3E, 0x8C, 0xD1, 0x65, 0x65, 0x84, 0x2B, 0x93, 0xE0, 0x08, 0xBF, 0x8D, 0xF8, 0x60, 0x84, 0x8E, 0x7F, 0xE4, 0x9C, 0xAE, + 0x46, 0x87, 0xB2, 0xF7, 0x9C, 0xE8, 0xF3, 0x26, 0x45, 0x88, 0xCD, 0x7F, 0x5C, 0xDB, 0xD4, 0x65, 0xA3, 0x54, 0x93, 0xEC, + 0x88, 0x76, 0x2A, 0xDB, 0xE1, 0x6F, 0x39, 0xC3, 0x59, 0x10, 0x6A, 0x6D, 0xAF, 0x23, 0xE6, 0x09, 0x98, 0xDC, 0x0C, 0x2F, + 0xBB, 0x6F, 0xD2, 0x06, 0x6D, 0x93, 0x86, 0xC8, 0x0F, 0x87, 0xBA, 0x2D, 0x13, 0xC3, 0x7B, 0x4B, 0x06, 0x62, 0x42, 0x81, + 0x7D, 0x00, 0x6F, 0x71, 0xBE, 0x13, 0xBA, 0xA5, 0x3B, 0x51, 0xFB, 0x98, 0xCB, 0x45, 0x4B, 0x9C, 0xB8, 0xFC, 0xEF, 0x5F, + 0xCB, 0x41, 0xCB, 0x5E, 0x12, 0xE9, 0x75, 0x09, 0xA5, 0x47, 0x7F, 0xB8, 0x5F, 0xCF, 0x5A, 0xB5, 0x4F, 0x35, 0x07, 0xC2, + 0xE8, 0xD8, 0x4A, 0xE3, 0xE3, 0x20, 0xBE, 0x80, 0x24, 0x7D, 0x4D, 0x61, 0xF5, 0x3A, 0xA2, 0x96, 0xB5, 0x1A, 0x45, 0x49, + 0xAD, 0x26, 0xF6, 0xB7, 0x08, 0xF8, 0x24, 0x70, 0x44, 0xDE, 0xFB, 0xD7, 0x38, 0x19, 0x65, 0x3D, 0x1F, 0xD1, 0x61, 0x58, + 0x1D, 0x51, 0x0A, 0x97, 0xCE, 0xE7, 0xDA, 0x92, 0xAB, 0x1E, 0x82, 0xA0, 0x13, 0x0E, 0xFF, 0xC4, 0x81, 0x72, 0x44, 0xB1, + 0x16, 0x3F, 0x4C, 0xCA, 0xB4, 0x00, 0x4C, 0xA0, 0xC5, 0xD8, 0x33, 0x15, 0x48, 0xEF, 0x5E, 0xA1, 0x41, 0x9E, 0x94, 0x2B, + 0x37, 0xF7, 0x14, 0x03, 0xE4, 0xC5, 0xBD, 0x90, 0x9C, 0xA6, 0x1D, 0xCB, 0x46, 0x39, 0xAD, 0xA5, 0xF5, 0x45, 0xD1, 0xA1, + 0x62, 0xDA, 0x88, 0x81, 0x1D, 0xC5, 0x2F, 0xA0, 0x99, 0x96, 0xEE, 0x39, 0x94, 0x37, 0x1D, 0xB3, 0x18, 0xDA, 0xA4, 0x01, + 0x52, 0x58, 0xA4, 0x4C, 0xBE, 0x9B, 0xF4, 0x2E, 0x9D, 0x78, 0x10, 0x11, 0x95, 0x7C, 0xFE, 0x51, 0x9D, 0x7B, 0xD1, 0x89, + 0xDB, 0x46, 0x8E, 0x8E, 0x4A, 0x9D, 0x7F, 0x36, 0x69, 0x59, 0xE0, 0xF3, 0x75, 0x56, 0xC4, 0x70, 0x64, 0x6D, 0x7C, 0x89, + 0xC3, 0xB3, 0x44, 0xD1, 0x87, 0xA5, 0x90, 0xE4, 0x01, 0xC6, 0x09, 0x20, 0x56, 0x3F, 0x70, 0xFD, 0x69, 0xF3, 0x1A, 0x32, + 0xE9, 0x5B, 0xB4, 0xB4, 0xA4, 0xFF, 0x5E, 0xD7, 0xAB, 0x8A, 0x98, 0xF6, 0xBE, 0xAF, 0x66, 0x88, 0x62, 0x9C, 0x20, 0xE6, + 0xDB, 0x53, 0xFF, 0xC1, 0x44, 0xE9, 0x17, 0x3E, 0x15, 0x16, 0xC6, 0x6A, 0x4C, 0xBD, 0xC0, 0x4F, 0x5D, 0xF0, 0x39, 0xD1, + 0xAE, 0x3A, 0x38, 0xCE, 0xB8, 0x2E, 0x76, 0xCE, 0xDD, 0x51, 0xA6, 0x4F, 0xEE, 0xAC, 0xED, 0x1D, 0x3D, 0x9B, 0xFC, 0xDE, + 0x3F, 0x2E, 0xFF, 0xEE, 0x6F, 0x5E, 0xFE, 0xEC, 0xD1, 0xDC, 0x50, 0x18, 0x10, 0x04, 0x85, 0x31, 0x00, 0x3E, 0xE8, 0x42, + 0xE7, 0x15, 0x50, 0x24, 0x14, 0xDD, 0x58, 0x08, 0x49, 0xA5, 0x0E, 0x72, 0x5D, 0xF5, 0xE0, 0xA0, 0xEA, 0xEC, 0x4C, 0xCA, + 0xAC, 0xC0, 0x41, 0x12, 0xA6, 0x21, 0x80, 0x12, 0x80, 0x81, 0xE9, 0xD5, 0x67, 0xCA, 0x83, 0x24, 0x2F, 0xEF, 0x9E, 0x28, + 0x01, 0x13, 0x0F, 0xBC, 0xD5, 0x4E, 0x65, 0x9A, 0x6A, 0xB7, 0xA1, 0xCA, 0x24, 0x00, 0xF7, 0x64, 0xBC, 0x24, 0xBA, 0x90, + 0x92, 0x04, 0xC0, 0xA0, 0x5A, 0x79, 0x5A, 0x55, 0xF3, 0x9B, 0xEC, 0x32, 0x27, 0x0F, 0xE8, 0x59, 0x1B, 0x65, 0x20, 0x78, + 0xA6, 0x04, 0x67, 0x45, 0x12, 0xCA, 0xC3, 0x4A, 0x06, 0x52, 0x4B, 0xB3, 0x4D, 0xAB, 0x47, 0x67, 0x71, 0x82, 0xEF, 0x34, + 0xFC, 0xB9, 0xC9, 0x26, 0xA7, 0x70, 0xCB, 0x5D, 0x91, 0x26, 0xAC, 0x8F, 0xD7, 0x7A, 0xD3, 0x0B, 0xB9, 0x0F, 0x22, 0x0D, + 0xC0, 0x4B, 0x00, 0x03, 0x5C, 0x4B, 0x6E, 0x5C, 0xE3, 0x40, 0x69, 0x5F, 0x4B, 0x99, 0xE2, 0x18, 0x8B, 0x01, 0x8C, 0x28, + 0x59, 0x55, 0x62, 0xF6, 0xEA, 0xDE, 0x49, 0xCF, 0xD5, 0xE4, 0x57, 0x1A, 0xFC, 0xBB, 0x85, 0xC3, 0xD0, 0x2E, 0x6F, 0xB1, + 0x6B, 0x15, 0xED, 0x2B, 0x31, 0x80, 0xB2, 0xE9, 0x81, 0x04, 0x89, 0x60, 0xD9, 0x69, 0x63, 0x1B, 0x6A, 0xAF, 0x7F, 0xCE, + 0x1F, 0xE0, 0xB9, 0x4C, 0xA7, 0x4D, 0xCA, 0x4E, 0x98, 0x9C, 0x44, 0x6E, 0xF9, 0x01, 0xAC, 0x29, 0x7E, 0x73, 0x70, 0xDF, + 0x2F, 0xF0, 0x2E, 0x3C, 0xE9, 0x48, 0xCA, 0x0B, 0xC7, 0x1C, 0xA5, 0x0F, 0x12, 0xEC, 0x66, 0x4F, 0x1E, 0x6A, 0xCA, 0x3F, + 0xED, 0x0E, 0x2D, 0x8B, 0xDA, 0x03, 0x69, 0x97, 0xCA, 0xA3, 0x6C, 0xBB, 0x6B, 0x1A, 0x34, 0x8D, 0xE5, 0x2C, 0x25, 0x7E, + 0x72, 0x29, 0x58, 0x8E, 0x5F, 0xE2, 0x7F, 0xB6, 0xD3, 0x08, 0xDA, 0x66, 0x34, 0x8D, 0x93, 0x93, 0x3C, 0x56, 0xA6, 0xB4, + 0xF5, 0x66, 0xF1, 0x34, 0x96, 0xFF, 0x68, 0x6A, 0x52, 0x11, 0x9B, 0xF5, 0x3D, 0xF0, 0x98, 0x45, 0xED, 0x91, 0xF8, 0xEE, + 0x1F, 0xC6, 0x45, 0x89, 0x5E, 0xBF, 0x92, 0x49, 0xBC, 0xA8, 0xEB, 0xBF, 0x9B, 0xC6, 0xF4, 0x69, 0x16, 0x72, 0x69, 0x6A, + 0xB5, 0x03, 0x9A, 0xA0, 0xB5, 0x3E, 0x75, 0x3F, 0xD3, 0xA5, 0x15, 0x22, 0x06, 0x63, 0xEA, 0xC2, 0xA3, 0x68, 0x2A, 0xE7, + 0x46, 0x18, 0x44, 0x15, 0xD1, 0x34, 0xED, 0xD7, 0x82, 0xBA, 0x78, 0x9E, 0xFA, 0x71, 0xA6, 0x3A, 0x98, 0xFE, 0xCA, 0xB8, + 0x98, 0x2D, 0x41, 0xCD, 0x3A, 0x52, 0xEB, 0xC2, 0x27, 0x39, 0xE2, 0x09, 0x1D, 0xDB, 0xE7, 0xDB, 0x51, 0x37, 0x35, 0xF6, + 0x02, 0x56, 0xE4, 0x9B, 0x7A, 0x53, 0x6D, 0xAE, 0x88, 0x63, 0x66, 0x44, 0xEA, 0xD8, 0x7B, 0xC6, 0x93, 0x33, 0xF9, 0x9F, + 0x2B, 0x7C, 0x95, 0x17, 0x3C, 0x4E, 0xE9, 0x5D, 0xB2, 0x60, 0x77, 0xE5, 0x9A, 0x6B, 0xF6, 0x98, 0xC0, 0x7B, 0x9D, 0x31, + 0x31, 0x24, 0x2C, 0xE3, 0x12, 0x9C, 0x7A, 0x05, 0x1B, 0x96, 0xA1, 0x58, 0x34, 0x91, 0x94, 0x49, 0xBC, 0xF2, 0xC9, 0x36, + 0xE8, 0xD1, 0xF1, 0xD3, 0x46, 0xD0, 0x0E, 0x2A, 0x58, 0x5D, 0x18, 0x17, 0xB1, 0x4F, 0xA7, 0x4C, 0x11, 0x7F, 0x0E, 0xDC, + 0xE6, 0x13, 0x6F, 0x13, 0x83, 0xE2, 0x56, 0x19, 0xE2, 0xA3, 0xDB, 0xC8, 0xC6, 0xB4, 0xBB, 0x26, 0x67, 0x70, 0x84, 0xF7, + 0x7C, 0x7F, 0x5D, 0x04, 0x8A, 0x3B, 0x5E, 0xF0, 0x76, 0x62, 0x42, 0xBE, 0xB0, 0x5F, 0x79, 0xCF, 0x4C, 0x4B, 0xD7, 0xE4, + 0xEC, 0x1E, 0x66, 0xB8, 0x42, 0x66, 0x31, 0x3B, 0xB3, 0x72, 0x4E, 0xD9, 0x44, 0x5C, 0xEB, 0x13, 0x0A, 0x39, 0x65, 0x07, + 0xEB, 0xB2, 0x70, 0xFD, 0xFF, 0x8E, 0x24, 0xB5, 0x18, 0x4A, 0x48, 0x5F, 0xE7, 0x9A, 0xB4, 0xA1, 0xBF, 0x06, 0x8C, 0xD0, + 0xA6, 0x8F, 0x28, 0xBB, 0x1D, 0x3F, 0x40, 0x1A, 0xE6, 0x53, 0xC6, 0xA4, 0x88, 0x9C, 0x49, 0xC1, 0x00, 0x8C, 0x21, 0xEC, + 0x90, 0xF4, 0x49, 0x76, 0x67, 0x21, 0xEF, 0xB4, 0xC4, 0x6F, 0x11, 0xB7, 0x85, 0x83, 0xAD, 0xEF, 0x1A, 0xA1, 0x41, 0xB7, + 0xC7, 0xC3, 0x16, 0xC4, 0x03, 0x17, 0x18, 0x1D, 0xD6, 0x8B, 0xDE, 0x4F, 0x55, 0x56, 0x0E, 0x80, 0xEA, 0xF9, 0xA6, 0x36, + 0xBD, 0x80, 0x10, 0x60, 0x73, 0x5A, 0xF0, 0x57, 0x43, 0x59, 0x06, 0x90, 0xF2, 0x13, 0x07, 0x72, 0x4B, 0xAA, 0x53, 0x6B, + 0x53, 0x32, 0x1A, 0x35, 0x18, 0xC3, 0x95, 0x47, 0x7B, 0x30, 0xC9, 0x99, 0x7A, 0xEB, 0xF9, 0x00, 0x24, 0x98, 0xA3, 0x15, + 0xFF, 0xAA, 0xF1, 0x91, 0x7E, 0x71, 0xDA, 0x27, 0x0F, 0x4F, 0xDD, 0x28, 0xF3, 0x80, 0x15, 0x0F, 0x91, 0xA4, 0xB5, 0xD5, + 0x10, 0xB7, 0x55, 0xDF, 0x86, 0xF8, 0xD1, 0x3B, 0xF6, 0xA5, 0xE3, 0x71, 0x3E, 0x0B, 0xBD, 0x48, 0x11, 0x27, 0x15, 0xCF, + 0xB1, 0xE4, 0xD8, 0x69, 0x7B, 0x8E, 0xCB, 0x11, 0xD3, 0x5E, 0xB4, 0xDD, 0x90, 0x17, 0xCD, 0xB5, 0xB7, 0x2F, 0x54, 0x7F, + 0x76, 0x0B, 0x0C, 0x19, 0x49, 0xCF, 0xBC, 0x70, 0x91, 0xDC, 0xE5, 0x0C, 0x5D, 0x40, 0xD6, 0x28, 0x3E, 0x83, 0xFA, 0x64, + 0x1F, 0xBB, 0xFA, 0x88, 0xFF, 0x5A, 0xCC, 0xDE, 0x61, 0xCC, 0xCA, 0xCB, 0x8B, 0x86, 0xD0, 0xD9, 0xB3, 0xB2, 0x6C, 0x7C, + 0xA4, 0x89, 0x72, 0x8D, 0x5A, 0x30, 0x4D, 0xA9, 0x3D, 0x23, 0xD9, 0xC8, 0x32, 0xF1, 0x7D, 0x89, 0xEA, 0x4B, 0x2A, 0x69, + 0xFA, 0x4F, 0xEB, 0xCA, 0x03, 0x82, 0xD1, 0xD8, 0x33, 0xB3, 0x45, 0x99, 0xA5, 0xAB, 0xAD, 0x3E, 0x34, 0xC7, 0xDA, 0xB3, + 0xC3, 0x5E, 0xDA, 0x10, 0x57, 0x90, 0x33, 0x72, 0x3C, 0x02, 0xEA, 0x94, 0x34, 0xBC, 0x52, 0x70, 0xCE, 0x54, 0xCA, 0x9E, + 0xD4, 0x1E, 0x3F, 0x52, 0x35, 0xB2, 0xE2, 0xAD, 0x7D, 0x5A, 0xDF, 0x89, 0x43, 0xE1, 0x41, 0x74, 0x7A, 0x19, 0x36, 0xD5, + 0xB4, 0x47, 0xD4, 0x56, 0x24, 0xF2, 0x53, 0x4A, 0x4E, 0x51, 0xCF, 0xF8, 0x4A, 0xDF, 0xB8, 0x41, 0xF9, 0xB4, 0x18, 0x2F, + 0x72, 0xE5, 0x21, 0xE6, 0xBE, 0xD0, 0x82, 0xA4, 0xC1, 0x49, 0xC0, 0xA2, 0x6A, 0x1B, 0x8B, 0xC9, 0x33, 0xA1, 0x12, 0x30, + 0x44, 0xB5, 0x38, 0x28, 0xCA, 0x14, 0x93, 0x00, 0xE7, 0xE4, 0xFC, 0xEA, 0x71, 0xA5, 0xC4, 0xC4, 0x47, 0xF0, 0xF3, 0xA5, + 0x49, 0x6B, 0x55, 0xE2, 0x41, 0xC6, 0x7B, 0xCC, 0xE7, 0xF0, 0x89, 0xF7, 0x19, 0xB7, 0xE3, 0x24, 0xFE, 0x6A, 0x47, 0x74, + 0x4B, 0xC8, 0x66, 0x08, 0x03, 0xF8, 0x5C, 0x49, 0xCF, 0x2C, 0xFC, 0x0E, 0xE2, 0x17, 0xB3, 0x4B, 0x70, 0x69, 0xE6, 0x30, + 0x87, 0xFE, 0xD2, 0xD5, 0x82, 0x4D, 0xD0, 0x00, 0x56, 0x0F, 0xBF, 0x72, 0x79, 0x09, 0x86, 0x40, 0xD1, 0xF4, 0x5D, 0xC7, + 0x4F, 0xCA, 0x40, 0xFD, 0x7E, 0xBA, 0xB6, 0xDC, 0xF8, 0xDF, 0x18, 0xCD, 0x50, 0x9F, 0xD3, 0x5F, 0x02, 0x89, 0xAE, 0xED, + 0x56, 0x2D, 0x3A, 0xFD, 0xF5, 0x70, 0x40, 0x7D, 0x7E, 0xBD, 0x26, 0xB9, 0xAA, 0xAD, 0xB0, 0x9E, 0xD5, 0x34, 0x3C, 0xFF, + 0x0E, 0x4C, 0x2B, 0xF6, 0xF1, 0xFE, 0xBF, 0x29, 0xA3, 0x90, 0xE7, 0xA0, 0x55, 0x55, 0x34, 0xE7, 0x2E, 0xDC, 0x96, 0xE0, + 0xB9, 0x09, 0x19, 0xCD, 0x47, 0xFA, 0x58, 0xFE, 0xAF, 0x11, 0x5E, 0xAC, 0xC0, 0x52, 0x40, 0xEE, 0x73, 0xF2, 0x11, 0x39, + 0x03, 0x92, 0x91, 0x8A, 0x9B, 0x12, 0x56, 0xFC, 0xEE, 0x5F, 0x19, 0x0E, 0x35, 0xEF, 0x3A, 0xF3, 0xC2, 0x94, 0xE0, 0x40, + 0x30, 0x2D, 0x4E, 0x8A, 0x48, 0x46, 0x6F, 0xDB, 0xAF, 0x9F, 0x6F, 0x18, 0xEA, 0x97, 0x3C, 0x76, 0xA6, 0x44, 0x60, 0xF6, + 0xF1, 0x0F, 0x67, 0xCB, 0xAE, 0x9E, 0xE2, 0x1A, 0x5E, 0xA9, 0xF8, 0x22, 0x31, 0x1D, 0x19, 0xC6, 0xA3, 0x62, 0x6E, 0xDA, + 0x2F, 0x9D, 0xC9, 0x11, 0xC5, 0x7E, 0xB1, 0xFA, 0x1C, 0x63, 0xAE, 0xB3, 0xC4, 0x23, 0x66, 0xCA, 0x2E, 0x9C, 0xBF, 0xBF, + 0xFD, 0xFB, 0x3F, 0xBB, 0xED, 0xDB, 0xAF, 0x9F, 0xBD, 0xBB, 0x2F, 0x9B, 0xAD, 0x9B, 0xB7, 0xAF, 0xFC, 0xFA, 0x37, 0xAB, + 0xEC, 0xDA, 0xA7, 0x8F, 0xBC, 0xBA, 0x27, 0x8B, 0xAC, 0x9A, 0xBE, 0xBE, 0x7D, 0xF9, 0x3E, 0xBA, 0x6D, 0xD9, 0xAE, 0x9E, + 0x3D, 0xB9, 0x2E, 0x9A, 0x2D, 0x99, 0xB6, 0xAE, 0x7C, 0xF8, 0x36, 0xAA, 0x6C, 0xD8, 0xA6, 0x8E, 0x3C, 0xB8, 0x26, 0x8A, + 0x2C, 0x98, 0x1A, 0x3C, 0xC9, 0x82, 0x03, 0x3A, 0x97, 0x2A, 0x48, 0x35, 0xEB, 0x4E, 0x6D, 0xD3, 0xA7, 0x97, 0x6C, 0xE9, + 0xD3, 0x19, 0xE2, 0x6F, 0x39, 0x22, 0x9A, 0xDA, 0xE8, 0xC3, 0x65, 0xC3, 0xA6, 0x96, 0x7B, 0x59, 0x98, 0xA5, 0x34, 0x0C, + 0x15, 0x26, 0x9B, 0x2D, 0x69, 0xC2, 0x6C, 0xD2, 0x27, 0x95, 0x55, 0x2F, 0x54, 0xA0, 0x8D, 0x1D, 0xF2, 0xCF, 0xE0, 0xDB, + 0x4B, 0x03, 0x64, 0xC2, 0x26, 0x94, 0xBD, 0xB7, 0xF5, 0xF3, 0x3D, 0xB3, 0xE5, 0xD3, 0xAD, 0x97, 0xB5, 0xB3, 0x2D, 0x93, + 0xA5, 0x93, 0xB5, 0xA7, 0xF4, 0xF2, 0x35, 0xA3, 0xE4, 0xD2, 0xA5, 0x87, 0xB4, 0xB2, 0x25, 0x83, 0xA4, 0x92, 0xBC, 0xB6, + 0x75, 0xF1, 0x3C, 0xB2, 0x65, 0xD1, 0xAC, 0x96, 0x35, 0xB1, 0x2C, 0x92, 0x25, 0x91, 0xB4, 0xA6, 0x74, 0xF0, 0x34, 0xA2, + 0x64, 0xD0, 0xA4, 0x86, 0x34, 0xB0, 0x24, 0x82, 0x24, 0x90, 0x3C, 0x7F, 0xA3, 0x1E, 0x04, 0x86, 0x83, 0x72, 0xC6, 0x40, + 0x3C, 0xFD, 0x6B, 0x5B, 0x8F, 0x8F, 0x4C, 0xAF, 0x29, 0x7D, 0x88, 0xB4, 0x31, 0x31, 0x14, 0xB8, 0x67, 0x31, 0x63, 0x4B, + 0x8E, 0x8E, 0xE5, 0xBE, 0x84, 0x7C, 0x86, 0x22, 0x30, 0x5D, 0xC0, 0xE6, 0x22, 0x12, 0x6A, 0x5A, 0x0F, 0x8D, 0x25, 0x53, + 0xA7, 0xA3, 0x5D, 0x6A, 0x4E, 0xCC, 0x9D, 0xB3, 0xED, 0x11, 0x62, 0x4A, 0x0E, 0x8C, 0xBB, 0x3F, 0xDD, 0xEB, 0x3B, 0x3B, + 0xCD, 0xCB, 0xAB, 0x1F, 0x9D, 0xAB, 0x2B, 0x1B, 0x8D, 0x8B, 0xB3, 0x2F, 0xDC, 0xEA, 0x33, 0x2B, 0xCC, 0xCA, 0xA3, 0x0F, + 0x9C, 0xAA, 0x23, 0x0B, 0x8C, 0x8A, 0xBA, 0x3E, 0x5D, 0xE9, 0x3A, 0x3A, 0x4D, 0xC9, 0xAA, 0x1E, 0x1D, 0xA9, 0x2A, 0x1A, + 0x0D, 0x89, 0xB2, 0x2E, 0x5C, 0xE8, 0x32, 0x2A, 0x4C, 0xC8, 0xA2, 0x0E, 0x1C, 0xA8, 0x22, 0x0A, 0x0C, 0x88, 0x90, 0x79, + 0x97, 0x88, 0x79, 0x73, 0xC7, 0xC7, 0x16, 0x9C, 0x5B, 0x57, 0x69, 0x53, 0x87, 0x87, 0xF3, 0x14, 0xF4, 0xA4, 0x71, 0x63, + 0xC6, 0xC6, 0xF2, 0x38, 0x95, 0x79, 0x61, 0x43, 0x86, 0x86, 0x57, 0x63, 0x53, 0xB1, 0x78, 0x72, 0x47, 0xC5, 0x4D, 0xAC, + 0x4F, 0x1B, 0x68, 0x52, 0x07, 0x85, 0xA0, 0xC7, 0x58, 0xC7, 0x70, 0x62, 0x46, 0xC4, 0xB3, 0xFB, 0x6A, 0xAF, 0x60, 0x42, + 0x06, 0x84, 0xB9, 0x37, 0xD5, 0xE3, 0x39, 0x33, 0xC5, 0xC3, 0xA9, 0x17, 0x95, 0xA3, 0x29, 0x13, 0x85, 0x83, 0xB1, 0x27, + 0xD4, 0xE2, 0x31, 0x23, 0xC4, 0xC2, 0xA1, 0x07, 0x94, 0xA2, 0x21, 0x03, 0x84, 0x82, 0xB8, 0x36, 0x55, 0xE1, 0x38, 0x32, + 0x45, 0xC1, 0xA8, 0x16, 0x15, 0xA1, 0x28, 0x12, 0x05, 0x81, 0xB0, 0x26, 0x54, 0xE0, 0x30, 0x22, 0x44, 0xC0, 0xA0, 0x06, + 0x14, 0xA0, 0x20, 0x02, 0x04, 0x80, 0x96, 0x60, 0x6F, 0x25, 0xA4, 0x06, 0x97, 0xAE, 0xB6, 0xD2, 0x18, 0xCF, 0x4F, 0xD9, + 0xAB, 0x1F, 0x80, 0x98, 0x6E, 0x15, 0x53, 0x09, 0xEA, 0x0A, 0x32, 0x36, 0xE6, 0xCC, 0x47, 0xC9, 0xAA, 0x1E, 0x01, 0xF2, + 0x64, 0x02, 0x41, 0x38, 0xB0, 0x76, 0x51, 0x67, 0x80, 0xCF, 0x4E, 0xD8, 0x2B, 0x1D, 0x29, 0xE2, 0x5D, 0xA3, 0x54, 0xBE, + 0xB7, 0x7C, 0x73, 0xCD, 0x66, 0x81, 0x46, 0xC8, 0x2A, 0x1C, 0x9F, 0xBD, 0xF9, 0x7B, 0x1F, 0xB9, 0xE9, 0x5B, 0x8F, 0x9D, + 0xB9, 0x3B, 0x0F, 0x99, 0xA9, 0x1B, 0x97, 0xAD, 0xF8, 0x7A, 0x17, 0xA9, 0xE8, 0x5A, 0x87, 0x8D, 0xB8, 0x3A, 0x07, 0x89, + 0xA8, 0x1A, 0x9E, 0xBC, 0x79, 0x79, 0x1E, 0xB8, 0x69, 0x59, 0x8E, 0x9C, 0x39, 0x39, 0x0E, 0x98, 0x29, 0x19, 0x96, 0xAC, + 0x78, 0x78, 0x16, 0xA8, 0x68, 0x58, 0x86, 0x8C, 0x38, 0x38, 0x06, 0x88, 0x28, 0x18, 0x7C, 0x05, 0x5E, 0xC6, 0x26, 0xFF, + 0xA3, 0x28, 0x35, 0x87, 0x68, 0xCB, 0x4D, 0xD1, 0xA3, 0x17, 0x4A, 0x45, 0xAC, 0xEC, 0x57, 0x8F, 0x39, 0xEB, 0xF8, 0xBE, + 0x05, 0x4B, 0x45, 0xC1, 0xA2, 0x16, 0x42, 0xAB, 0x5A, 0x35, 0xFD, 0xE0, 0x9A, 0x01, 0x36, 0xB3, 0xEE, 0x1A, 0x4C, 0xD0, + 0x23, 0x15, 0x9F, 0x79, 0x7A, 0xEE, 0xAC, 0x9B, 0x9F, 0xAB, 0x05, 0x16, 0x8F, 0x62, 0x44, 0xC0, 0x22, 0x14, 0x9D, 0xB5, + 0xF1, 0x73, 0x1D, 0xB1, 0xE1, 0x53, 0x8D, 0x95, 0xB1, 0x33, 0x0D, 0x91, 0xA1, 0x13, 0x95, 0xA5, 0xF0, 0x72, 0x15, 0xA1, + 0xE0, 0x52, 0x85, 0x85, 0xB0, 0x32, 0x05, 0x81, 0xA0, 0x12, 0x9C, 0xB4, 0x71, 0x71, 0x1C, 0xB0, 0x61, 0x51, 0x8C, 0x94, + 0x31, 0x31, 0x0C, 0x90, 0x21, 0x11, 0x94, 0xA4, 0x70, 0x70, 0x14, 0xA0, 0x60, 0x50, 0x84, 0x84, 0x30, 0x30, 0x04, 0x80, + 0x20, 0x10, 0xE4, 0x9B, 0x48, 0x3B, 0x5B, 0x79, 0xCB, 0x4F, 0x94, 0xBC, 0xE8, 0x7D, 0x4B, 0x59, 0x8B, 0x0F, 0x53, 0x63, + 0x9A, 0x03, 0x53, 0x69, 0xCA, 0x4E, 0x1A, 0xCD, 0xC6, 0x93, 0x43, 0x49, 0x8A, 0x0E, 0xD8, 0x9F, 0x86, 0x8D, 0x5A, 0x78, + 0x4B, 0x4D, 0x8E, 0x03, 0xBC, 0xC2, 0x4A, 0x58, 0x0B, 0x0D, 0x73, 0x7C, 0xA9, 0x38, 0x52, 0x68, 0x4A, 0x4C, 0xBC, 0x8A, + 0x65, 0x73, 0x42, 0x48, 0x0A, 0x0C, 0x9B, 0x3D, 0xD9, 0x6B, 0x1B, 0x39, 0xC9, 0x4B, 0x8B, 0x1D, 0x99, 0x2B, 0x0B, 0x19, + 0x89, 0x0B, 0x93, 0x2D, 0xD8, 0x6A, 0x13, 0x29, 0xC8, 0x4A, 0x83, 0x0D, 0x98, 0x2A, 0x03, 0x09, 0x88, 0x0A, 0x9A, 0x3C, + 0x59, 0x69, 0x1A, 0x38, 0x49, 0x49, 0x8A, 0x1C, 0x19, 0x29, 0x0A, 0x18, 0x09, 0x09, 0x92, 0x2C, 0x58, 0x68, 0x12, 0x28, + 0x48, 0x48, 0x82, 0x0C, 0x18, 0x28, 0x02, 0x08, 0x08, 0x08, 0xDB, 0x2A, 0x0E, 0x87, 0x59, 0x71, 0xC3, 0x47, 0x4E, 0x8D, + 0x85, 0x25, 0x49, 0x51, 0x83, 0x07, 0xD1, 0x58, 0xAE, 0xDF, 0x51, 0x61, 0xC2, 0x46, 0x89, 0x9E, 0x1A, 0x19, 0x41, 0x41, + 0x82, 0x06, 0x58, 0xB5, 0x5B, 0x6F, 0x58, 0x70, 0x43, 0x45, 0x4F, 0x69, 0x6F, 0x9C, 0x48, 0x50, 0x03, 0x05, 0x98, 0xBF, + 0x28, 0x6E, 0x50, 0x60, 0x42, 0x44, 0x60, 0x39, 0x9E, 0xDB, 0x40, 0x40, 0x02, 0x04, 0x99, 0x35, 0xD1, 0x63, 0x19, 0x31, + 0xC1, 0x43, 0x89, 0x15, 0x91, 0x23, 0x09, 0x11, 0x81, 0x03, 0x91, 0x25, 0xD0, 0x62, 0x11, 0x21, 0xC0, 0x42, 0x81, 0x05, + 0x90, 0x22, 0x01, 0x01, 0x80, 0x02, 0x98, 0x34, 0x51, 0x61, 0x18, 0x30, 0x41, 0x41, 0x88, 0x14, 0x11, 0x21, 0x08, 0x10, + 0x01, 0x01, 0x90, 0x24, 0x50, 0x60, 0x10, 0x20, 0x40, 0x40, 0x80, 0x04, 0x10, 0x20, 0x00, 0x00, 0xF3, 0x6E, 0x80, 0x00, + 0x0C, 0x4C, 0x40, 0x05, 0x97, 0x9B, 0x10, 0x20, 0x40, 0x40, 0xF0, 0x65, 0x9C, 0xEB, 0x51, 0xEF, 0xE0, 0xCE, 0x88, 0xE8, + 0x90, 0x63, 0x9F, 0xD2, 0xC3, 0x69, 0x7E, 0xC4, 0x41, 0x6E, 0xB6, 0x85, 0x8C, 0xCC, 0xA1, 0xFD, 0x90, 0xD9, 0x11, 0x21, + 0x6C, 0xC9, 0x95, 0xC7, 0x52, 0x68, 0x60, 0xEA, 0xEA, 0x06, 0x09, 0x35, 0xA2, 0x01, 0xA0, 0x53, 0x80, 0x03, 0xF9, 0x74, + 0x5D, 0x6E, 0xE0, 0x53, 0x16, 0x60, 0xDB, 0x36, 0xB1, 0x22, 0xE7, 0x68, 0x44, 0x44, 0x29, 0xA2, 0xF0, 0x21, 0xA0, 0xF2, + 0xA7, 0x82, 0xB0, 0xD6, 0x16, 0x4F, 0x58, 0x48, 0x8B, 0x35, 0xA8, 0x54, 0x53, 0xA8, 0x9A, 0x43, 0xFD, 0x86, 0x49, 0x2C, + 0x31, 0x43, 0x42, 0x5E, 0xDA, 0x04, 0xA3, 0xE3, 0xD2, 0x2A, 0x9D, 0x77, 0x6D, 0x64, 0xF1, 0x85, 0x64, 0x28, 0xF9, 0x62, + 0xD7, 0x23, 0x49, 0xB3, 0x39, 0x2B, 0xA9, 0xE0, 0x08, 0xF3, 0x39, 0xFA, 0x08, 0xD5, 0x6A, 0x4A, 0x0B, 0x97, 0xD8, 0xC3, + 0xFB, 0x65, 0xE5, 0xE2, 0x62, 0x99, 0xD0, 0x08, 0xBA, 0x2F, 0x1A, 0x38, 0x49, 0x49, 0xD2, 0xAB, 0x3A, 0x59, 0x03, 0x7B, + 0x2F, 0x1A, 0x79, 0x8F, 0x9B, 0xCC, 0x6B, 0x29, 0xC8, 0x4A, 0x99, 0x25, 0x7B, 0x6C, 0x24, 0xE8, 0xD1, 0x0E, 0x83, 0x50, + 0xFA, 0x0B, 0x1B, 0x39, 0xC9, 0x4B, 0xE3, 0xD5, 0xDB, 0xA0, 0xEA, 0xEA, 0xD5, 0x83, 0xFA, 0x9C, 0xE1, 0x23, 0x8D, 0x6A, + 0x3D, 0x5C, 0x22, 0xE8, 0x56, 0xBB, 0x75, 0x97, 0xB2, 0x41, 0x4E, 0x05, 0x99, 0x25, 0x8E, 0x3E, 0xE9, 0x93, 0x1A, 0x7C, + 0x2B, 0x21, 0x83, 0x49, 0xF0, 0xD0, 0x6C, 0x33, 0x47, 0x6C, 0xBB, 0xCB, 0x6E, 0xC9, 0x7B, 0xCE, 0xA5, 0x67, 0x3B, 0x9F, + 0x21, 0x4E, 0x1F, 0xAD, 0x93, 0x20, 0xA5, 0xFD, 0xCB, 0xFC, 0xAB, 0xBB, 0x71, 0x2D, 0x04, 0x80, 0x78, 0xF8, 0x56, 0x72, + 0x20, 0xFD, 0x2C, 0xF0, 0x20, 0x5F, 0x14, 0x8F, 0x91, 0x8F, 0xDE, 0xB0, 0x26, 0xE9, 0xEC, 0xD5, 0xDC, 0xBA, 0x18, 0x52, + 0xE3, 0x19, 0x5C, 0xB1, 0xA9, 0x33, 0x4F, 0x28, 0x82, 0x11, 0xC4, 0xD1, 0x91, 0x22, 0x75, 0xE5, 0x9C, 0xD9, 0x6E, 0x21, + 0xFC, 0x53, 0x02, 0x1D, 0x23, 0x3B, 0x70, 0x77, 0x31, 0xEC, 0x8E, 0x53, 0x63, 0x59, 0x19, 0x83, 0xF7, 0x73, 0x72, 0xCC, + 0xC9, 0x91, 0xC4, 0xFC, 0xB7, 0x33, 0xAB, 0x64, 0x62, 0xC5, 0x0B, 0xF0, 0x74, 0x74, 0x77, 0x8E, 0x10, 0xD5, 0x14, 0x50, + 0x3F, 0x69, 0x4F, 0xCF, 0x7F, 0x17, 0xA8, 0xD0, 0xF6, 0x52, 0xED, 0x4B, 0x5B, 0xCA, 0x2D, 0x66, 0xB4, 0x56, 0xE2, 0xED, + 0xE4, 0x56, 0xC6, 0xA3, 0x50, 0x38, 0xE1, 0x74, 0x76, 0x74, 0x5D, 0xAA, 0xF0, 0x57, 0x5D, 0xC9, 0x2B, 0x67, 0x02, 0xE5, + 0xF5, 0x77, 0xBB, 0x78, 0x74, 0x17, 0xE6, 0xCD, 0x85, 0xB3, 0xF0, 0x58, 0x20, 0x57, 0xC1, 0x88, 0xAC, 0x68, 0x04, 0x9C, + 0x8A, 0x14, 0x37, 0xFE, 0x78, 0x79, 0x1A, 0x5A, 0xC5, 0xD4, 0xB9, 0xB1, 0xFE, 0xDE, 0x67, 0xC8, 0x1D, 0x17, 0x00, 0x6F, + 0x3A, 0x12, 0x77, 0xE9, 0xFD, 0xD1, 0x30, 0xA4, 0x28, 0x2A, 0x45, 0x67, 0x0A, 0x1B, 0xF7, 0xFF, 0x46, 0xB1, 0x67, 0x3B, + 0xE0, 0x26, 0x37, 0x1B, 0x7C, 0x5C, 0xED, 0x02, 0x91, 0xB3, 0xB9, 0x4E, 0x3F, 0x38, 0xF6, 0xFB, 0x7A, 0x38, 0xC5, 0xAA, + 0xD8, 0x32, 0xEB, 0xDC, 0xAC, 0x0B, 0x84, 0x26, 0x84, 0x60, 0x5E, 0xC0, 0xF4, 0x42, 0xDE, 0xFC, 0x7B, 0x7D, 0x60, 0xD7, + 0x7A, 0xB5, 0xFF, 0x23, 0x16, 0x33, 0x6F, 0xCE, 0x15, 0x1C, 0xA3, 0xC9, 0xDE, 0x7E, 0x1F, 0x47, 0x50, 0xCA, 0xB4, 0xB2, + 0xE2, 0x80, 0xF7, 0x5B, 0x6C, 0x78, 0xDF, 0xFD, 0xFB, 0x7F, 0x7E, 0x1F, 0x54, 0x2B, 0xD8, 0xEB, 0x94, 0x1B, 0x30, 0x05, + 0x27, 0x30, 0xB4, 0xCE, 0x56, 0x2D, 0xD7, 0x16, 0x05, 0x59, 0xA8, 0xEA, 0x14, 0xE3, 0x00, 0x62, 0x41, 0xCE, 0xED, 0x56, + 0x31, 0xEA, 0x04, 0x03, 0xEF, 0xA6, 0xA1, 0xFF, 0x15, 0x59, 0x49, 0xA1, 0xCD, 0x9F, 0xE9, 0xC8, 0xD2, 0xE2, 0x96, 0xEE, + 0x95, 0xE0, 0xAD, 0xD1, 0xEE, 0xA7, 0x01, 0x63, 0xCD, 0xCC, 0xAB, 0xB3, 0xD9, 0x34, 0x8C, 0xC2, 0xFA, 0xA4, 0x70, 0x58, + 0x06, 0x50, 0x9F, 0x80, 0xD9, 0x59, 0x74, 0x82, 0x50, 0x84, 0x8A, 0x4D, 0xC9, 0x2E, 0x18, 0xD2, 0x1B, 0x72, 0xE8, 0x6C, + 0x57, 0x31, 0x27, 0x67, 0x51, 0xE5, 0xCD, 0x01, 0x05, 0x52, 0xE4, 0x81, 0x7C, 0xEA, 0xD9, 0xC1, 0x41, 0xE1, 0x58, 0x43, + 0x53, 0xC1, 0x0F, 0x57, 0xEC, 0x01, 0x41, 0xF4, 0xE8, 0xA6, 0x7C, 0x69, 0xD3, 0x73, 0xEA, 0x8A, 0xC7, 0xA9, 0xC2, 0xBC, + 0x8B, 0x8F, 0xF9, 0x0E, 0x63, 0xA8, 0x6D, 0x02, 0x33, 0xE8, 0x88, 0xC1, 0xA7, 0x77, 0xBA, 0x1E, 0x10, 0x0B, 0xBA, 0xF6, + 0x1B, 0x54, 0x72, 0xAD, 0x2E, 0x49, 0xA3, 0x4C, 0xE2, 0x56, 0x8B, 0xA9, 0x53, 0x65, 0x78, 0x4D, 0x9A, 0xEA, 0xF3, 0x2F, + 0x21, 0xCC, 0x4C, 0xD1, 0xDA, 0xAA, 0xBB, 0xF9, 0x21, 0xCA, 0x39, 0xE9, 0x8F, 0x76, 0x43, 0xB9, 0xC4, 0xAF, 0xC0, 0xC0, + 0x2A, 0xA9, 0xE2, 0x38, 0xE5, 0x5A, 0x22, 0x4E, 0x6E, 0x21, 0xF7, 0xAC, 0xA4, 0x80, 0x82, 0x48, 0xBC, 0x8F, 0x6B, 0xA9, + 0xDD, 0x22, 0x5D, 0x56, 0x19, 0xAD, 0xD2, 0xD9, 0x30, 0x8D, 0x52, 0xDC, 0xD8, 0xCA, 0x1D, 0xD4, 0xE5, 0x38, 0x1C, 0xCB, + 0x9E, 0x3F, 0x83, 0xEF, 0xC2, 0x19, 0x5B, 0xCD, 0x01, 0x01, 0xD9, 0xA8, 0x63, 0x24, 0xF8, 0x60, 0x87, 0xED, 0xBB, 0x7B, + 0xBF, 0x42, 0x04, 0x5B, 0x5A, 0xC8, 0x24, 0x82, 0x24, 0x90, 0xA0, 0x74, 0x77, 0x90, 0x6E, 0xBF, 0xC7, 0xD6, 0x6B, 0x0B, + 0x72, 0xF0, 0x2C, 0x92, 0x25, 0xF4, 0x27, 0x74, 0xB7, 0xBB, 0xBC, 0x50, 0xC4, 0x2E, 0xBC, 0x8E, 0x89, 0xE1, 0x25, 0x83, + 0xA4, 0x92, 0x5E, 0xF8, 0xF7, 0x6D, 0x39, 0xCD, 0x45, 0x5A, 0xA6, 0xD5, 0x0B, 0xB0, 0x77, 0x8E, 0x06, 0x95, 0x4B, 0x67, + 0xF9, 0xBC, 0x77, 0xB2, 0x06, 0x59, 0x7D, 0xB7, 0x85, 0x06, 0x97, 0xFD, 0xD8, 0x9A, 0x84, 0x82, 0xB6, 0x29, 0xB4, 0xE7, + 0x41, 0x96, 0xF4, 0xE6, 0x76, 0xF4, 0xCF, 0xDA, 0xFB, 0xA5, 0x53, 0x53, 0x39, 0x3F, 0x43, 0xAC, 0x9A, 0x57, 0xFC, 0xF6, + 0x77, 0xF5, 0x0D, 0x45, 0x5A, 0xD7, 0x9D, 0xE0, 0x4F, 0xB9, 0xF1, 0xAD, 0xC2, 0x0A, 0xF5, 0xE7, 0xF6, 0xF6, 0x4E, 0xDF, + 0x7F, 0xE7, 0x3A, 0x55, 0xB2, 0xCE, 0x65, 0xFA, 0xA7, 0xDC, 0xFD, 0xF7, 0xF7, 0xF7, 0x2A, 0xE4, 0x8D, 0x10, 0xC6, 0xCA, + 0x48, 0x35, 0x32, 0x54, 0x91, 0x52, 0xB3, 0x2A, 0x7C, 0x69, 0x2A, 0x78, 0x2D, 0x99, 0xD6, 0x1C, 0x34, 0xDF, 0x1E, 0x43, + 0x6D, 0x42, 0x16, 0x1C, 0xA2, 0xA6, 0xA7, 0x69, 0x0D, 0x12, 0xDF, 0x0D, 0xBD, 0xE2, 0xCC, 0xF7, 0x4F, 0xA1, 0x68, 0xA7, + 0x7B, 0xFD, 0x2F, 0x9B, 0xAD, 0x9B, 0x97, 0xCF, 0xB9, 0xB4, 0x17, 0xC9, 0x12, 0x04, 0x17, 0x0C, 0x35, 0x8B, 0x8E, 0x79, + 0xAB, 0xDB, 0x9E, 0xEA, 0xBB, 0x9B, 0xE1, 0x68, 0x6F, 0xBF, 0xF6, 0xEE, 0x7E, 0xFC, 0xAE, 0xDA, 0x5F, 0x10, 0xFD, 0x23, + 0x73, 0xF3, 0xF6, 0x3F, 0xCE, 0x57, 0xFE, 0xFE, 0x7F, 0xFD, 0xCF, 0x68, 0xD1, 0xFE, 0x38, 0xDE, 0xB8, 0xBE, 0x4D, 0x09, + 0xCA, 0xD8, 0xF7, 0xEF, 0xFE, 0xFE, 0x90, 0x5F, 0xAF, 0x0E, 0x9F, 0x99, 0x1D, 0x41, 0x90, 0x19, 0x6D, 0x97, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x10, 0x20, 0x10, 0x20, 0x40, 0x40, 0x90, 0x24, 0x50, 0x60, 0x08, 0x10, + 0x01, 0x01, 0x88, 0x14, 0x11, 0x21, 0x18, 0x30, 0x41, 0x41, 0x98, 0x34, 0x51, 0x61, 0x01, 0x01, 0x80, 0x02, 0x81, 0x05, + 0x90, 0x22, 0x11, 0x21, 0xC0, 0x42, 0x91, 0x25, 0xD0, 0x62, 0x09, 0x11, 0x81, 0x03, 0x89, 0x15, 0x91, 0x23, 0x19, 0x31, + 0xC1, 0x43, 0x99, 0x35, 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, + 0x52, 0x64, 0x48, 0x50, 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, + 0x82, 0x06, 0xC1, 0x45, 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, + 0x93, 0x27, 0x59, 0x71, 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0x02, 0x08, 0x08, 0x08, 0x82, 0x0C, 0x18, 0x28, 0x12, 0x28, + 0x48, 0x48, 0x92, 0x2C, 0x58, 0x68, 0x0A, 0x18, 0x09, 0x09, 0x8A, 0x1C, 0x19, 0x29, 0x1A, 0x38, 0x49, 0x49, 0x9A, 0x3C, + 0x59, 0x69, 0x03, 0x09, 0x88, 0x0A, 0x83, 0x0D, 0x98, 0x2A, 0x13, 0x29, 0xC8, 0x4A, 0x93, 0x2D, 0xD8, 0x6A, 0x0B, 0x19, + 0x89, 0x0B, 0x8B, 0x1D, 0x99, 0x2B, 0x1B, 0x39, 0xC9, 0x4B, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, + 0x1A, 0x2C, 0x52, 0x68, 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, + 0x4B, 0x4D, 0xDA, 0x7C, 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, + 0xDA, 0x6E, 0x4B, 0x59, 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, + 0x20, 0x10, 0x84, 0x84, 0x30, 0x30, 0x14, 0xA0, 0x60, 0x50, 0x94, 0xA4, 0x70, 0x70, 0x0C, 0x90, 0x21, 0x11, 0x8C, 0x94, + 0x31, 0x31, 0x1C, 0xB0, 0x61, 0x51, 0x9C, 0xB4, 0x71, 0x71, 0x05, 0x81, 0xA0, 0x12, 0x85, 0x85, 0xB0, 0x32, 0x15, 0xA1, + 0xE0, 0x52, 0x95, 0xA5, 0xF0, 0x72, 0x0D, 0x91, 0xA1, 0x13, 0x8D, 0x95, 0xB1, 0x33, 0x1D, 0xB1, 0xE1, 0x53, 0x9D, 0xB5, + 0xF1, 0x73, 0x44, 0xC0, 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, + 0x23, 0x15, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, + 0xB2, 0x36, 0x55, 0xE1, 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, + 0xE3, 0x57, 0xDD, 0xF5, 0xF3, 0x77, 0x06, 0x88, 0x28, 0x18, 0x86, 0x8C, 0x38, 0x38, 0x16, 0xA8, 0x68, 0x58, 0x96, 0xAC, + 0x78, 0x78, 0x0E, 0x98, 0x29, 0x19, 0x8E, 0x9C, 0x39, 0x39, 0x1E, 0xB8, 0x69, 0x59, 0x9E, 0xBC, 0x79, 0x79, 0x07, 0x89, + 0xA8, 0x1A, 0x87, 0x8D, 0xB8, 0x3A, 0x17, 0xA9, 0xE8, 0x5A, 0x97, 0xAD, 0xF8, 0x7A, 0x0F, 0x99, 0xA9, 0x1B, 0x8F, 0x9D, + 0xB9, 0x3B, 0x1F, 0xB9, 0xE9, 0x5B, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, + 0x6A, 0x5C, 0xD6, 0xEC, 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, + 0x7B, 0x7D, 0x47, 0xC9, 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, + 0xAB, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x20, 0x02, 0x04, 0x80, 0xA0, 0x06, + 0x14, 0xA0, 0x30, 0x22, 0x44, 0xC0, 0xB0, 0x26, 0x54, 0xE0, 0x28, 0x12, 0x05, 0x81, 0xA8, 0x16, 0x15, 0xA1, 0x38, 0x32, + 0x45, 0xC1, 0xB8, 0x36, 0x55, 0xE1, 0x21, 0x03, 0x84, 0x82, 0xA1, 0x07, 0x94, 0xA2, 0x31, 0x23, 0xC4, 0xC2, 0xB1, 0x27, + 0xD4, 0xE2, 0x29, 0x13, 0x85, 0x83, 0xA9, 0x17, 0x95, 0xA3, 0x39, 0x33, 0xC5, 0xC3, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, + 0x06, 0x84, 0xE0, 0x46, 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, + 0x17, 0xA5, 0x78, 0x72, 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, + 0xC6, 0xC6, 0xF1, 0x67, 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, + 0xD7, 0xE7, 0x22, 0x0A, 0x0C, 0x88, 0xA2, 0x0E, 0x1C, 0xA8, 0x32, 0x2A, 0x4C, 0xC8, 0xB2, 0x2E, 0x5C, 0xE8, 0x2A, 0x1A, + 0x0D, 0x89, 0xAA, 0x1E, 0x1D, 0xA9, 0x3A, 0x3A, 0x4D, 0xC9, 0xBA, 0x3E, 0x5D, 0xE9, 0x23, 0x0B, 0x8C, 0x8A, 0xA3, 0x0F, + 0x9C, 0xAA, 0x33, 0x2B, 0xCC, 0xCA, 0xB3, 0x2F, 0xDC, 0xEA, 0x2B, 0x1B, 0x8D, 0x8B, 0xAB, 0x1F, 0x9D, 0xAB, 0x3B, 0x3B, + 0xCD, 0xCB, 0xBB, 0x3F, 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, + 0x5E, 0xEC, 0x6A, 0x5A, 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, + 0x8E, 0x8E, 0xE3, 0x4F, 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, + 0x9F, 0xAF, 0x7B, 0x7B, 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x24, 0x82, 0x24, 0x90, 0xA4, 0x86, 0x34, 0xB0, 0x34, 0xA2, + 0x64, 0xD0, 0xB4, 0xA6, 0x74, 0xF0, 0x2C, 0x92, 0x25, 0x91, 0xAC, 0x96, 0x35, 0xB1, 0x3C, 0xB2, 0x65, 0xD1, 0xBC, 0xB6, + 0x75, 0xF1, 0x25, 0x83, 0xA4, 0x92, 0xA5, 0x87, 0xB4, 0xB2, 0x35, 0xA3, 0xE4, 0xD2, 0xB5, 0xA7, 0xF4, 0xF2, 0x2D, 0x93, + 0xA5, 0x93, 0xAD, 0x97, 0xB5, 0xB3, 0x3D, 0xB3, 0xE5, 0xD3, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, + 0x36, 0xB4, 0x74, 0xE2, 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, + 0x67, 0xD5, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, + 0xF6, 0xF6, 0x6D, 0xD3, 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x8A, + 0x2C, 0x98, 0xA6, 0x8E, 0x3C, 0xB8, 0x36, 0xAA, 0x6C, 0xD8, 0xB6, 0xAE, 0x7C, 0xF8, 0x2E, 0x9A, 0x2D, 0x99, 0xAE, 0x9E, + 0x3D, 0xB9, 0x3E, 0xBA, 0x6D, 0xD9, 0xBE, 0xBE, 0x7D, 0xF9, 0x27, 0x8B, 0xAC, 0x9A, 0xA7, 0x8F, 0xBC, 0xBA, 0x37, 0xAB, + 0xEC, 0xDA, 0xB7, 0xAF, 0xFC, 0xFA, 0x2F, 0x9B, 0xAD, 0x9B, 0xAF, 0x9F, 0xBD, 0xBB, 0x3F, 0xBB, 0xED, 0xDB, 0xBF, 0xBF, + 0xFD, 0xFB, 0x66, 0xCA, 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, + 0x2F, 0x9D, 0xEE, 0xDE, 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, + 0xBE, 0xBE, 0x77, 0xEB, 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, + 0xEF, 0xDF, 0xFF, 0xFF, 0x80, 0xD7, 0x80, 0x00, 0x0C, 0x4C, 0xF8, 0x86, 0x19, 0x44, 0x0A, 0x28, 0x63, 0xD8, 0x78, 0x97, + 0xD5, 0x27, 0x51, 0xEF, 0xE0, 0xCE, 0xB0, 0x44, 0x01, 0x2E, 0x38, 0xCB, 0x32, 0x4D, 0x58, 0x34, 0x21, 0x94, 0xB6, 0x85, + 0x84, 0xD3, 0xB9, 0xD5, 0x2F, 0x2D, 0x4F, 0xA1, 0xC8, 0x39, 0x39, 0x86, 0xAF, 0x11, 0x60, 0xEA, 0xEA, 0x06, 0xE9, 0xD5, + 0x5F, 0xA8, 0xE6, 0xCF, 0xC7, 0x63, 0xD9, 0xB1, 0xD1, 0xF2, 0x6F, 0x3F, 0xDB, 0xB9, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, + 0x42, 0x44, 0xD0, 0x64, 0x52, 0x64, 0x08, 0x62, 0xFC, 0x03, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, + 0x53, 0x65, 0x0B, 0x44, 0xE9, 0x09, 0xC1, 0x45, 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0xC1, 0x53, + 0x22, 0x58, 0xC9, 0x55, 0x93, 0x27, 0x59, 0x71, 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0xA9, 0xE0, 0x08, 0xF3, 0xFF, 0xEE, + 0x2B, 0x0A, 0x4B, 0xD1, 0xC8, 0xD3, 0x25, 0x24, 0x5E, 0x68, 0xE5, 0xE2, 0x62, 0x99, 0x30, 0xFC, 0xA6, 0x69, 0x32, 0xBC, + 0x41, 0x9B, 0x9A, 0x04, 0x26, 0x79, 0x03, 0x7B, 0x2F, 0x1A, 0x59, 0x0C, 0xAB, 0x08, 0x13, 0xD4, 0xC8, 0x91, 0x80, 0x12, + 0xC0, 0x28, 0x24, 0xE8, 0xD1, 0x0E, 0x8B, 0xB4, 0x16, 0x29, 0x42, 0xBD, 0x3C, 0x84, 0x73, 0x9F, 0x5C, 0x6C, 0xF6, 0x2A, + 0x49, 0xF0, 0xC2, 0x4C, 0x1A, 0x2C, 0x52, 0x68, 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0xB1, 0x37, 0x56, 0xF2, 0xCA, 0x5C, + 0x1B, 0x2D, 0x5A, 0x78, 0x4B, 0x4D, 0xDA, 0x7C, 0x5B, 0x6D, 0xBE, 0x27, 0xC3, 0x01, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, + 0xCA, 0x4E, 0xD3, 0x6D, 0xDA, 0x6E, 0x2B, 0x1D, 0x0B, 0xD2, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, + 0xDB, 0x6F, 0x04, 0x80, 0x78, 0xF8, 0xFA, 0xB6, 0xB5, 0x26, 0xCB, 0xA0, 0x17, 0x5C, 0xA9, 0xE2, 0xD2, 0x3E, 0xDE, 0xB0, + 0x26, 0xE9, 0xD5, 0x80, 0xBC, 0x52, 0xD8, 0xCF, 0x05, 0x9E, 0x37, 0xCB, 0x33, 0x78, 0x4F, 0x28, 0x82, 0x11, 0xBA, 0xDB, + 0x41, 0xEE, 0xD5, 0xA0, 0xB6, 0x49, 0xE1, 0x81, 0x25, 0xCF, 0x02, 0x1D, 0xDA, 0x02, 0x26, 0x30, 0x64, 0x2D, 0x5C, 0xCF, + 0x87, 0x9C, 0x98, 0xA5, 0xD2, 0x82, 0x44, 0xC0, 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, + 0x72, 0x74, 0x4C, 0xD0, 0x23, 0x15, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, + 0xA2, 0x16, 0xC5, 0xC5, 0xB2, 0x36, 0x55, 0xE1, 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, + 0xB3, 0x37, 0x5D, 0xF1, 0xE3, 0x57, 0xDD, 0xF5, 0xF3, 0x77, 0xD9, 0x89, 0x2E, 0x38, 0xFB, 0x7F, 0xE0, 0xEC, 0x4F, 0x2D, + 0x8D, 0x4A, 0xF6, 0xEC, 0x56, 0xF5, 0x36, 0x70, 0x6B, 0xD6, 0x66, 0x16, 0x1B, 0xEF, 0x12, 0xCF, 0x0A, 0x26, 0x52, 0xDE, + 0x3A, 0x87, 0xAD, 0x0B, 0xAB, 0xFC, 0xA4, 0x7C, 0x24, 0x7A, 0x9D, 0xC9, 0xF8, 0x5C, 0xEF, 0x89, 0x7A, 0x32, 0x55, 0x6B, + 0x0A, 0x1D, 0xF0, 0xEE, 0x53, 0x93, 0x67, 0xBB, 0x1E, 0x5D, 0xE7, 0x3F, 0xFC, 0xE2, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, + 0x3A, 0x3C, 0x56, 0xE8, 0x6A, 0x5C, 0xD6, 0xEC, 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, + 0x6B, 0x5D, 0xDE, 0xFC, 0x7B, 0x7D, 0x47, 0xC9, 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, + 0xFA, 0x7E, 0x4F, 0xD9, 0xAB, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x7E, 0x1F, + 0x54, 0x2B, 0x17, 0x07, 0x99, 0xAC, 0x31, 0x5D, 0xA3, 0xC6, 0x5F, 0xC8, 0xD1, 0x47, 0xD7, 0x16, 0x05, 0x59, 0x4E, 0xE7, + 0xDF, 0xE1, 0x40, 0xB0, 0x44, 0xB9, 0x39, 0x31, 0x22, 0xE5, 0x04, 0x03, 0xEF, 0xA6, 0xC9, 0x19, 0x52, 0x56, 0x79, 0xB4, + 0xA7, 0x0D, 0x97, 0x2A, 0x50, 0x46, 0x96, 0xEE, 0x95, 0xE0, 0xF7, 0x85, 0x91, 0x2E, 0x63, 0x32, 0x66, 0xB8, 0x66, 0x27, + 0x52, 0xE4, 0x18, 0x65, 0xFB, 0x8B, 0xE0, 0x46, 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0xBF, 0xD0, + 0x02, 0xFC, 0xE8, 0x56, 0x17, 0xA5, 0x78, 0x72, 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x5E, 0xC6, 0x88, 0x0C, 0xE1, 0x47, + 0x96, 0xA6, 0x71, 0x63, 0xC6, 0xC6, 0xF1, 0x67, 0xD6, 0xE6, 0x11, 0x77, 0xA3, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, + 0xC7, 0xC7, 0xF9, 0x77, 0xD7, 0xE7, 0xC2, 0xBC, 0x8B, 0x8F, 0xDC, 0x90, 0xF7, 0x5E, 0x12, 0xD3, 0x4C, 0x53, 0x02, 0x9C, + 0x72, 0xAD, 0xBA, 0x1E, 0x10, 0x0B, 0xC9, 0xED, 0xF9, 0x06, 0x32, 0xBE, 0x45, 0xD2, 0x55, 0xCC, 0x5B, 0xE9, 0x8B, 0xA9, + 0x53, 0x65, 0xFD, 0x94, 0x8C, 0x05, 0x1B, 0xD6, 0xCC, 0x11, 0x45, 0x8A, 0x59, 0xED, 0xBB, 0xF9, 0x21, 0xCA, 0x1D, 0xEE, + 0x75, 0xFB, 0x64, 0x39, 0xBE, 0xCB, 0xEC, 0xE1, 0x24, 0x95, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, + 0x4E, 0xCC, 0xF2, 0x6E, 0x5E, 0xEC, 0x6A, 0x5A, 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, + 0x5F, 0xED, 0x63, 0x4B, 0x8E, 0x8E, 0xE3, 0x4F, 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, + 0x8F, 0x8F, 0xEB, 0x5F, 0x9F, 0xAF, 0x7B, 0x7B, 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x28, 0x85, 0x85, 0x18, 0xD6, 0x66, + 0x70, 0x3B, 0x7C, 0x35, 0x07, 0x3F, 0x8E, 0x44, 0xF6, 0xB8, 0xBB, 0x62, 0x2D, 0x9E, 0xAE, 0xB8, 0xC3, 0xC4, 0x06, 0x50, + 0xE7, 0xD9, 0xDC, 0xF2, 0x7A, 0xFC, 0x27, 0x61, 0x26, 0xDA, 0x8E, 0x69, 0x0B, 0xB6, 0x4D, 0x21, 0xE1, 0x03, 0xA8, 0x45, + 0x58, 0xFD, 0x4D, 0xD7, 0xD1, 0x9C, 0x5A, 0xC8, 0x08, 0x4F, 0xB4, 0x51, 0x67, 0xFB, 0xF7, 0x49, 0x56, 0xFE, 0x64, 0xC2, + 0x26, 0x94, 0xE4, 0xC6, 0x36, 0xB4, 0x74, 0xE2, 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, + 0x37, 0xB5, 0x7C, 0xF2, 0x67, 0xD5, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, + 0xE6, 0xD6, 0xF5, 0xE7, 0xF6, 0xF6, 0x6D, 0xD3, 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, + 0xF7, 0xF7, 0x46, 0x4A, 0xE2, 0x13, 0x0D, 0xE0, 0xE9, 0xB6, 0xD2, 0xC8, 0x2D, 0x98, 0xFC, 0x55, 0xDF, 0x04, 0xA7, 0x6A, + 0x25, 0x96, 0x0D, 0x96, 0xE1, 0x89, 0x64, 0xBB, 0xCE, 0xDF, 0xBE, 0x3C, 0x7C, 0x9A, 0x59, 0x69, 0x2E, 0x92, 0xCF, 0x09, + 0x40, 0xFB, 0x4F, 0x29, 0xE5, 0x3E, 0x0C, 0xF0, 0xFA, 0xBA, 0x9B, 0xE9, 0x0E, 0x56, 0x8C, 0x93, 0x65, 0xCB, 0x77, 0x2C, + 0x8E, 0xC4, 0xE5, 0xBE, 0x5E, 0xBA, 0x66, 0xCA, 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, + 0x7E, 0xFC, 0x6E, 0xDA, 0x2F, 0x9D, 0xEE, 0xDE, 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, + 0xAE, 0x9E, 0xE7, 0xCF, 0xBE, 0xBE, 0x77, 0xEB, 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, + 0xBF, 0xBF, 0x7F, 0xFB, 0xEF, 0xDF, 0xFF, 0xFF, 0x8B, 0xCC, 0x80, 0x00, 0x0C, 0x4C, 0x04, 0x44, 0xCA, 0x26, 0x11, 0xD4, + 0x40, 0xBD, 0xA2, 0x62, 0xC2, 0xDD, 0x51, 0xEF, 0xE0, 0xCE, 0xE8, 0x54, 0x0C, 0xAA, 0x41, 0xB1, 0xA0, 0x80, 0x1A, 0x73, + 0x7F, 0xBD, 0xB6, 0x85, 0x8C, 0x80, 0x09, 0x39, 0x71, 0x2D, 0xBD, 0xA4, 0xE1, 0xC0, 0x3A, 0x5F, 0x05, 0x79, 0x60, 0xEA, + 0xEA, 0x06, 0x0D, 0xF7, 0x13, 0x2B, 0xE3, 0xB9, 0xA2, 0x41, 0x4D, 0x6B, 0x42, 0x5C, 0xE8, 0xE2, 0x85, 0x23, 0x00, 0x44, + 0x62, 0x68, 0x90, 0x65, 0x52, 0x05, 0xD0, 0x64, 0x52, 0x64, 0x4D, 0x4A, 0x17, 0xB1, 0x60, 0xF7, 0x6C, 0xA5, 0xB0, 0xC3, + 0xC6, 0x02, 0xD8, 0x74, 0x53, 0x65, 0xD1, 0x5F, 0x92, 0xF2, 0xB1, 0x83, 0x38, 0x67, 0xF2, 0x69, 0x1E, 0x76, 0xD1, 0x65, + 0xD2, 0x66, 0xCC, 0x97, 0x69, 0x4B, 0x09, 0x55, 0xE3, 0x6B, 0x99, 0x75, 0x30, 0x0B, 0xD9, 0x75, 0xD3, 0x67, 0xA9, 0xE0, + 0x08, 0xF3, 0x0B, 0x7E, 0xBB, 0x2E, 0xC0, 0xDE, 0x7B, 0x2A, 0xEC, 0x37, 0x8C, 0xFC, 0xE5, 0xE2, 0x62, 0x99, 0xF2, 0x9E, + 0x18, 0x4B, 0x40, 0xB8, 0x2F, 0x86, 0xFB, 0x9C, 0x8F, 0xD6, 0x03, 0x7B, 0x2F, 0x1A, 0xCB, 0x9F, 0xFB, 0xD5, 0x29, 0x1D, + 0x2F, 0x58, 0xCD, 0x22, 0xDC, 0x24, 0x24, 0xE8, 0xD1, 0x0E, 0xB3, 0xCD, 0x76, 0x24, 0x21, 0xD1, 0x8F, 0x84, 0xA5, 0x8E, + 0x90, 0xEC, 0xB2, 0x0E, 0xA0, 0xF7, 0xB2, 0x8A, 0xB0, 0x6D, 0x26, 0x95, 0x6A, 0x0E, 0xD2, 0x6C, 0x5A, 0x6C, 0x70, 0xA7, + 0x0D, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x9A, 0x78, 0x3B, 0xB8, 0xDA, 0x7C, 0x5B, 0x6D, 0xC7, 0xCD, 0x8A, 0x9F, 0x53, 0x4D, + 0x9A, 0x2E, 0x53, 0x51, 0x2B, 0xB1, 0xD3, 0x6D, 0xDA, 0x6E, 0x58, 0x66, 0x9B, 0x4D, 0xCB, 0x5D, 0x9B, 0x2F, 0x5A, 0xFD, + 0xCB, 0xDE, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, 0x78, 0xF8, 0x44, 0x80, 0x78, 0xBD, 0xC9, 0x80, 0x66, 0x70, 0xE2, 0xE2, + 0xD6, 0x3C, 0xDE, 0xB0, 0x26, 0xE9, 0x77, 0x10, 0x35, 0xF9, 0x26, 0x52, 0x1A, 0x55, 0x9C, 0x8C, 0x90, 0x8E, 0x4F, 0x28, + 0x82, 0x11, 0x78, 0x7E, 0x43, 0xCD, 0xE3, 0x23, 0xE1, 0x2A, 0xE1, 0x58, 0xCE, 0x30, 0x02, 0x1D, 0x92, 0xD1, 0xB7, 0x6A, + 0x46, 0x71, 0x66, 0x4E, 0x96, 0x5F, 0x5D, 0xB5, 0x81, 0x86, 0x7F, 0x86, 0x80, 0x5A, 0xC4, 0xC4, 0x32, 0x34, 0x24, 0xC6, + 0x80, 0x12, 0xD4, 0xE4, 0x72, 0x74, 0xEB, 0xD9, 0xF3, 0x45, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0x86, 0x47, 0x1B, 0xDC, 0xF4, + 0x73, 0x75, 0x31, 0xE5, 0x76, 0x06, 0xC5, 0xC5, 0xB2, 0x36, 0x55, 0xA7, 0x40, 0x57, 0xD5, 0xE5, 0xF2, 0x76, 0x6A, 0xDC, + 0x24, 0xB0, 0xCD, 0xD5, 0xB3, 0x37, 0x2B, 0xB7, 0x45, 0x15, 0xDD, 0xF5, 0xF3, 0x77, 0xDC, 0x84, 0x1B, 0xDA, 0x06, 0x9E, + 0x3E, 0x78, 0xD6, 0xA9, 0x33, 0x43, 0x97, 0x28, 0x78, 0xE9, 0x6E, 0xD8, 0x27, 0x14, 0x4E, 0x9C, 0x43, 0x3D, 0xA1, 0x4E, + 0xEB, 0x51, 0x8D, 0x41, 0x69, 0x37, 0xC5, 0xFF, 0x8B, 0x45, 0x2A, 0x09, 0xBC, 0xB7, 0x55, 0xD7, 0x0F, 0x4A, 0x20, 0xA4, + 0xFE, 0x7A, 0x05, 0x91, 0x0A, 0x16, 0xE3, 0x5A, 0xBB, 0xCE, 0x92, 0x49, 0xE1, 0x54, 0xEF, 0xFB, 0x5B, 0x85, 0xEE, 0x6E, + 0x2C, 0x5C, 0xC6, 0xCC, 0x3A, 0x3C, 0xD6, 0x12, 0xEF, 0x7B, 0xD6, 0xEC, 0x7A, 0x7C, 0xCE, 0x5C, 0x2B, 0x8C, 0xCE, 0xDC, + 0x3B, 0x3D, 0x4D, 0xBE, 0xC9, 0x13, 0xDE, 0xFC, 0x7B, 0x7D, 0x3C, 0x8F, 0x00, 0xE5, 0xC7, 0xCD, 0xBA, 0x3E, 0x88, 0x89, + 0xEC, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x75, 0x26, 0xAD, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x2B, 0x7D, 0xEF, 0x58, 0xDF, 0xFD, + 0xFB, 0x7F, 0x7E, 0x1F, 0x54, 0x2B, 0x98, 0xD6, 0xE9, 0xAF, 0x50, 0x66, 0x38, 0x4B, 0xE8, 0x32, 0x37, 0x7C, 0xD7, 0x16, + 0x05, 0x59, 0xAC, 0xF4, 0x97, 0xA9, 0xAB, 0xD0, 0xC7, 0xC9, 0x09, 0x88, 0xE9, 0x16, 0x04, 0x03, 0xEF, 0xA6, 0xC1, 0x47, + 0x7A, 0x29, 0x35, 0xC1, 0x46, 0x8A, 0x48, 0xC8, 0x54, 0x62, 0x96, 0xEE, 0x95, 0xE0, 0x5C, 0xF5, 0x95, 0x08, 0xB4, 0xD1, + 0x47, 0xCB, 0x16, 0x58, 0x08, 0x3F, 0x60, 0x7A, 0xFA, 0xB4, 0xE0, 0x46, 0x16, 0xA4, 0xC7, 0x6B, 0x40, 0xC4, 0xF0, 0x66, + 0x56, 0xE4, 0xED, 0x54, 0xCF, 0xD5, 0xE8, 0x56, 0x17, 0xA5, 0x0C, 0xF6, 0x43, 0xC2, 0xF8, 0x76, 0x57, 0xE5, 0xA1, 0x43, + 0xF6, 0x22, 0xE1, 0x47, 0x96, 0xA6, 0x62, 0x25, 0x64, 0x88, 0xF1, 0x67, 0xD6, 0xE6, 0xCD, 0xAE, 0x07, 0x5C, 0xE9, 0x57, + 0x97, 0xA7, 0xB9, 0x76, 0xD7, 0x86, 0xF9, 0x77, 0xD7, 0xE7, 0xC2, 0xBC, 0x8B, 0x8F, 0x04, 0x0F, 0x1C, 0xA1, 0xBB, 0xC8, + 0x7F, 0x8A, 0x0B, 0x70, 0xDF, 0xE6, 0xBA, 0x1E, 0x10, 0x0B, 0x2A, 0xE4, 0xFC, 0xD6, 0xC5, 0xD2, 0x4F, 0x04, 0xBB, 0x21, + 0x45, 0x7D, 0x8B, 0xA9, 0x53, 0x65, 0xDE, 0xEF, 0x73, 0xE8, 0x89, 0xD5, 0xDC, 0x07, 0x53, 0x10, 0xF8, 0x3E, 0xBB, 0xF9, + 0x21, 0xCA, 0xD4, 0xE5, 0x62, 0x74, 0x40, 0x33, 0x28, 0x74, 0x3A, 0x24, 0xC1, 0xA5, 0x63, 0x8C, 0xAC, 0xC9, 0xE2, 0x4E, + 0x1E, 0xAC, 0xDA, 0xC9, 0x31, 0x6C, 0xF2, 0x6E, 0x5E, 0xEC, 0x81, 0xAD, 0x09, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0xFC, 0xBC, + 0xED, 0x81, 0xFA, 0x7E, 0x5F, 0xED, 0x11, 0xEE, 0x0B, 0x89, 0xE3, 0x4F, 0x9E, 0xAE, 0xB3, 0x6B, 0xBE, 0x35, 0xF3, 0x6F, + 0xDE, 0xEE, 0x3C, 0x84, 0x2C, 0xF1, 0xEB, 0x5F, 0x9F, 0xAF, 0x0B, 0xA4, 0x78, 0x81, 0xFB, 0x7F, 0xDF, 0xEF, 0x2E, 0x02, + 0x87, 0x96, 0xA0, 0xC1, 0xB5, 0xBE, 0x6B, 0xA0, 0x17, 0xD0, 0x4D, 0xE0, 0x9E, 0x54, 0xEA, 0x64, 0x16, 0x93, 0xF2, 0x05, + 0x31, 0x1A, 0xFC, 0xB3, 0x3E, 0xCA, 0x18, 0x4A, 0xF5, 0x0A, 0x6D, 0x11, 0x05, 0x89, 0x06, 0x11, 0x68, 0x54, 0xEA, 0xA3, + 0x93, 0xDE, 0x30, 0xA1, 0x3C, 0xA2, 0xF7, 0xF1, 0xB5, 0x58, 0xCF, 0x93, 0x54, 0x1C, 0x7B, 0xCC, 0x81, 0x1C, 0xBF, 0x71, + 0x57, 0xB6, 0x77, 0xFD, 0x32, 0xD6, 0xE4, 0xC6, 0x36, 0xB4, 0xB4, 0xE7, 0x76, 0x95, 0xF4, 0xE6, 0x76, 0xF4, 0xAC, 0xD2, + 0x57, 0x31, 0xEC, 0xD6, 0x37, 0xB5, 0xBC, 0xF2, 0x17, 0x2E, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xFB, 0x5A, 0xE6, 0xE5, 0xC7, + 0xB6, 0xB6, 0xDD, 0x40, 0x99, 0x76, 0xF5, 0xE7, 0xF6, 0xF6, 0x68, 0xD5, 0x6F, 0x87, 0xED, 0xD7, 0xB7, 0xB7, 0x7C, 0x35, + 0x45, 0x92, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x62, 0x62, 0x55, 0x45, 0x7D, 0xE2, 0x13, 0x77, 0xD4, 0x0A, 0x17, 0xC4, 0x0B, + 0xD8, 0x1F, 0x16, 0x8A, 0x4A, 0x9C, 0xD0, 0xA8, 0xD6, 0x5C, 0x26, 0xB3, 0x5E, 0x1B, 0xC4, 0x3A, 0x7D, 0x4A, 0xD8, 0x63, + 0xAA, 0x99, 0xC0, 0x87, 0x57, 0x2C, 0x36, 0xDD, 0xFE, 0x12, 0x63, 0xE9, 0x5E, 0x04, 0x0F, 0x9F, 0xCA, 0x92, 0xF1, 0xAC, + 0xA9, 0x14, 0x85, 0xAF, 0x60, 0x5D, 0x54, 0xC4, 0x62, 0xC6, 0xC2, 0xA8, 0x82, 0x63, 0xE6, 0xCE, 0x3E, 0xBC, 0x04, 0x4F, + 0xEB, 0xDB, 0xF6, 0xEE, 0x7E, 0xFC, 0x17, 0x9C, 0x8D, 0xD3, 0xEE, 0xDE, 0x3F, 0xBD, 0x96, 0x59, 0x90, 0x9C, 0xFE, 0xFE, + 0x7F, 0xFD, 0xA7, 0xCB, 0xDE, 0xE0, 0xE7, 0xCF, 0xBE, 0xBE, 0x98, 0x1C, 0x6B, 0xD9, 0xF7, 0xEF, 0xFE, 0xFE, 0x1B, 0x5F, + 0xAB, 0x98, 0xEF, 0xDF, 0xBF, 0xBF, 0xD7, 0x58, 0x90, 0x1F, 0xFF, 0xFF, 0x57, 0x3D, 0x26, 0x59, 0x70, 0xA4, 0xE1, 0x62, + 0xEF, 0x8D, 0x18, 0x24, 0x68, 0x5E, 0x8D, 0xAD, 0xBB, 0x04, 0x1D, 0xE0, 0x1A, 0xA0, 0x08, 0x35, 0xD2, 0x8C, 0xD8, 0x58, + 0x46, 0x4C, 0xE0, 0xC5, 0xF2, 0x21, 0x8A, 0x38, 0x61, 0xAD, 0x10, 0x42, 0x4E, 0x28, 0x4B, 0xAE, 0xA8, 0x73, 0x2A, 0xC7, + 0x7C, 0x9F, 0x1C, 0x95, 0xB0, 0x50, 0x1C, 0xC5, 0xCD, 0x2A, 0x41, 0x35, 0xE9, 0xCD, 0xA7, 0x1C, 0x31, 0xE2, 0x78, 0xB3, + 0x3E, 0xA9, 0xF8, 0xBB, 0xF0, 0xDB, 0x2A, 0x80, 0x50, 0xF1, 0x43, 0x40, 0x8E, 0xD5, 0x51, 0x05, 0xA2, 0x8A, 0xDD, 0xD0, + 0x22, 0xCD, 0xC2, 0xFA, 0xAA, 0x46, 0x4F, 0x9E, 0xF6, 0xEF, 0x11, 0x70, 0xBA, 0x44, 0x85, 0x36, 0xB0, 0x87, 0xC0, 0x5E, + 0xFA, 0x04, 0x39, 0xD0, 0xB1, 0xEF, 0x51, 0x55, 0x8A, 0xF1, 0xF7, 0x7C, 0x95, 0x3E, 0x4F, 0x58, 0xC5, 0x5E, 0xA1, 0xB2, + 0x11, 0x65, 0x3A, 0x68, 0x53, 0x83, 0x06, 0xC9, 0x24, 0x27, 0x48, 0x07, 0x20, 0x79, 0x2C, 0xA8, 0x69, 0x88, 0x13, 0x89, + 0xA8, 0x02, 0x15, 0x33, 0xC0, 0x14, 0x67, 0xCA, 0x6A, 0x09, 0xA4, 0x10, 0x5F, 0x50, 0xD8, 0x38, 0xB0, 0x48, 0x2C, 0x66, + 0x45, 0x68, 0xD3, 0x41, 0x82, 0x47, 0x68, 0x0A, 0x79, 0x95, 0xC7, 0xE9, 0xE8, 0xAA, 0xA4, 0x22, 0xA1, 0x69, 0x0F, 0x81, + 0xAA, 0xC2, 0x8D, 0xCE, 0x55, 0xB6, 0x7C, 0x61, 0x4A, 0xA3, 0x4A, 0x3F, 0x22, 0x23, 0xDC, 0x98, 0x42, 0x0E, 0xDA, 0x68, + 0xF2, 0x1E, 0x2C, 0x98, 0x0A, 0x4D, 0x46, 0x23, 0xB8, 0x8D, 0x22, 0x7A, 0x0B, 0xED, 0x19, 0x8C, 0x53, 0xB6, 0xD2, 0x3A, + 0xBE, 0x62, 0xE3, 0x5C, 0x9C, 0x37, 0x4A, 0x2D, 0xA9, 0x6E, 0x64, 0x54, 0xDC, 0xB7, 0x47, 0xC6, 0x62, 0x5E, 0x5A, 0x1C, + 0x3D, 0x8F, 0xCA, 0x38, 0x81, 0xEF, 0xDB, 0x57, 0xA3, 0x7F, 0xBC, 0xC4, 0x1C, 0x14, 0x44, 0xEC, 0x7A, 0x3D, 0xD4, 0xC8, + 0x06, 0x5D, 0x6F, 0xDB, 0x25, 0x8F, 0x36, 0x6F, 0xA1, 0x73, 0xE6, 0xE7, 0x09, 0x73, 0x09, 0x34, 0x50, 0xF3, 0x64, 0xB6, + 0x69, 0xD1, 0xC4, 0x70, 0x9C, 0x32, 0xFF, 0xE5, 0xB4, 0x13, 0x4D, 0x10, 0x83, 0x89, 0xFD, 0xC7, 0x43, 0x8F, 0x33, 0xBC, + 0xE2, 0x1C, 0x94, 0x6F, 0x46, 0x56, 0x25, 0x21, 0x42, 0xD8, 0x0C, 0xC6, 0xC5, 0x1F, 0xE8, 0x33, 0xAE, 0x19, 0xDC, 0xF9, + 0xDB, 0x05, 0x94, 0x85, 0x05, 0x4F, 0xAA, 0xD8, 0x9B, 0x17, 0x55, 0x1C, 0xDC, 0x9E, 0x5D, 0x93, 0xF9, 0xBF, 0x18, 0xB7, + 0xE1, 0x81, 0x70, 0x6B, 0x72, 0x35, 0x5A, 0xA1, 0xAC, 0x54, 0xC7, 0x36, 0x86, 0x9B, 0x61, 0x87, 0x00, 0x76, 0x97, 0x1A, + 0x1B, 0xA7, 0x8B, 0xE0, 0xD3, 0xB8, 0x85, 0xF0, 0xB5, 0x2E, 0xA8, 0x93, 0x29, 0x86, 0xF9, 0x5F, 0x1A, 0xA6, 0x1E, 0x91, + 0xC9, 0xB7, 0xBE, 0x4B, 0xF2, 0x89, 0xCD, 0x99, 0x5C, 0x1A, 0xF4, 0xB1, 0x79, 0x6C, 0x18, 0xB1, 0x2F, 0x00, 0x53, 0xEE, + 0xD2, 0x68, 0x66, 0x83, 0x51, 0xAC, 0x0E, 0x4D, 0x05, 0x2C, 0x92, 0x76, 0xCB, 0x20, 0x3C, 0x1E, 0xC8, 0x32, 0x0E, 0x38, + 0x49, 0xDA, 0x91, 0x84, 0xF0, 0x01, 0xDE, 0xEB, 0x0A, 0x90, 0x4F, 0xF5, 0xDF, 0x36, 0x8E, 0x3D, 0x9C, 0xB2, 0xC1, 0x1D, + 0x59, 0x00, 0xE6, 0xBA, 0x48, 0x70, 0x4A, 0xAE, 0xC5, 0x91, 0x36, 0xF6, 0xDC, 0x51, 0xD4, 0x1F, 0x06, 0xD1, 0x16, 0x45, + 0x2D, 0x04, 0xD7, 0x89, 0x9A, 0xC4, 0x7E, 0xE5, 0xE6, 0x5B, 0xD6, 0xF8, 0xF3, 0xFA, 0x39, 0xCE, 0x0B, 0xE7, 0x97, 0xFC, + 0x82, 0x7C, 0x31, 0xD0, 0xEB, 0xBC, 0x40, 0xAA, 0x30, 0x1D, 0x86, 0x26, 0xAD, 0xC5, 0x97, 0xC0, 0x52, 0x6E, 0xFC, 0xE6, + 0x4A, 0xF9, 0x85, 0x9D, 0x93, 0xAE, 0x35, 0xE8, 0xA1, 0x2F, 0xBF, 0x6E, 0x77, 0xD6, 0x25, 0xC8, 0xE1, 0x6F, 0xC8, 0x01, + 0xA9, 0xEF, 0x3D, 0x96, 0x34, 0x37, 0x60, 0x74, 0xEA, 0x2A, 0xC7, 0x59, 0xC8, 0x37, 0x78, 0x5E, 0xDC, 0x1E, 0xB4, 0xF3, + 0xD1, 0x23, 0xB7, 0x2E, 0x92, 0xBB, 0xA4, 0xCB, 0x56, 0x8F, 0xEB, 0x36, 0xBC, 0xD3, 0x11, 0xEC, 0x6C, 0xF2, 0xE4, 0x3E, + 0x93, 0xBA, 0x31, 0xEA, 0x2C, 0xB2, 0xE3, 0x11, 0xBD, 0xB2, 0x76, 0x20, 0x6E, 0x89, 0xF5, 0x07, 0xF2, 0x29, 0x65, 0x43, + 0xE1, 0x49, 0xD0, 0x77, 0xDB, 0x87, 0xE4, 0x30, 0xE4, 0x8E, 0x44, 0xC5, 0x54, 0xAF, 0xD4, 0xE1, 0x04, 0xCF, 0x85, 0x89, + 0xA2, 0xFE, 0x1F, 0x7B, 0x80, 0x9F, 0x9F, 0x6E, 0x7F, 0x97, 0x0F, 0x4A, 0x2F, 0xF7, 0x5A, 0xC2, 0x03, 0xF8, 0xF2, 0xD7, + 0xAA, 0x4C, 0xE0, 0xA7, 0x09, 0x06, 0xA3, 0x00, 0xFF, 0x47, 0xD9, 0xA3, 0x3C, 0xC4, 0x7A, 0x86, 0x8B, 0x49, 0x73, 0x71, + 0xBF, 0x23, 0x78, 0xC8, 0x6F, 0x22, 0xCB, 0x51, 0xFB, 0x63, 0xA0, 0x7A, 0x01, 0x74, 0x3F, 0xF8, 0x35, 0x27, 0x82, 0xC5, + 0xA4, 0x98, 0x83, 0x7C, 0xFC, 0xA4, 0x7A, 0x08, 0x69, 0x98, 0xB9, 0x26, 0x2F, 0x07, 0x4D, 0x07, 0xFF, 0xDC, 0xA9, 0x1E, + 0xE8, 0xF5, 0x33, 0x0E, 0xBE, 0xDD, 0xF1, 0x30, 0xF5, 0x9A, 0x97, 0xA4, 0xCE, 0x38, 0x44, 0xD7, 0x88, 0xA6, 0x38, 0xDE, + 0x66, 0xFD, 0xF7, 0xCA, 0x2F, 0xE6, 0x0C, 0x46, 0xA7, 0x9D, 0x4D, 0x66, 0x19, 0x43, 0x30, 0xCF, 0x67, 0xFC, 0xBA, 0x6F, + 0x27, 0xEF, 0xE0, 0xFE, 0x7E, 0xA5, 0xED, 0xFA, 0x6E, 0x4F, 0xA3, 0x23, 0xD9, 0x31, 0xDB, 0x2F, 0xA8, 0x03, 0xDF, 0xF8, + 0x8D, 0xC4, 0x23, 0x9F, 0xA9, 0x4F, 0x15, 0x5D, 0x6E, 0x0C, 0xF2, 0x0A, 0x3E, 0x20, 0x43, 0x89, 0xEC, 0xB5, 0xC3, 0x8C, + 0xF1, 0x62, 0x3E, 0xB3, 0x1C, 0x8F, 0xFC, 0xEF, 0x32, 0xA9, 0xF4, 0xCA, 0x3E, 0x2D, 0x33, 0x5F, 0x8B, 0x05, 0xA7, 0xA3, + 0x1D, 0xD3, 0x77, 0xA7, 0x01, 0xF3, 0xFC, 0xDA, 0x53, 0x5C, 0x77, 0x55, 0x57, 0x70, 0x1B, 0xAE, 0x03, 0x19, 0xE2, 0xF8, + 0x17, 0x39, 0x4D, 0x53, 0xFF, 0xE3, 0xE5, 0x99, 0x88, 0xB0, 0x34, 0x08, 0x58, 0x9C, 0xB4, 0x06, 0xD6, 0x93, 0x45, 0xA2, + 0xEA, 0x58, 0x3D, 0xF6, 0x59, 0x7E, 0xD8, 0x7D, 0x22, 0x36, 0xF2, 0xA4, 0x5E, 0xB9, 0xE7, 0x60, 0xB2, 0x00, 0x34, 0x8E, + 0x3C, 0xF9, 0x54, 0x41, 0x53, 0x93, 0x5B, 0xFF, 0x31, 0x7C, 0xFE, 0x02, 0x98, 0x7A, 0x6B, 0x72, 0x46, 0x57, 0xC9, 0x41, + 0x72, 0x02, 0x9B, 0xFF, 0x4E, 0xE7, 0x4D, 0x70, 0x9E, 0xDE, 0x0A, 0x17, 0xD7, 0x57, 0xCE, 0xDC, 0x06, 0x31, 0x8C, 0xC6, + 0x83, 0xB3, 0x6A, 0x00, 0x93, 0x7A, 0xC5, 0x0C, 0xF1, 0x6E, 0x20, 0xA3, 0xC5, 0xA9, 0xDE, 0x7F, 0x9F, 0xF8, 0x83, 0x9B, + 0x54, 0x9A, 0xC8, 0x87, 0x95, 0xC9, 0x14, 0x69, 0x15, 0x34, 0xAC, 0x60, 0x91, 0xB4, 0x46, 0xB8, 0x2D, 0x79, 0x3E, 0xDF, + 0x16, 0x54, 0x3D, 0x96, 0x8F, 0xBC, 0x99, 0xA6, 0xBA, 0xA3, 0x2E, 0x3A, 0x8F, 0x25, 0x1B, 0x3C, 0xFF, 0xF2, 0x3A, 0xDC, + 0x67, 0x91, 0x50, 0xEC, 0x89, 0xF9, 0xAE, 0xBA, 0x0B, 0xC0, 0xAA, 0x8E, 0x5C, 0x5A, 0x71, 0x8A, 0x6A, 0x17, 0x0C, 0xDF, + 0x06, 0xB8, 0xE5, 0x18, 0x4D, 0xBC, 0x93, 0xA1, 0x83, 0x80, 0xFD, 0xA9, 0x5B, 0x12, 0x59, 0xF7, 0x39, 0x24, 0xEE, 0x89, + 0x4D, 0x7C, 0xE9, 0xCF, 0xDE, 0x5C, 0x98, 0x38, 0xD6, 0x31, 0x93, 0xEB, 0x46, 0xEF, 0x49, 0xD2, 0x0D, 0xD5, 0x5E, 0x91, + 0x6B, 0x53, 0x37, 0xDE, 0x46, 0x2E, 0x8A, 0xC1, 0xC7, 0x4B, 0x6A, 0x7F, 0xDE, 0x37, 0xC7, 0x0C, 0xDD, 0xBD, 0x19, 0xF3, + 0xC2, 0xA0, 0x13, 0x06, 0x9B, 0xD5, 0xC4, 0xDE, 0xCF, 0x3D, 0x98, 0x20, 0xD7, 0x21, 0x74, 0x82, 0x49, 0x09, 0xD2, 0x15, + 0x66, 0x21, 0x19, 0x43, 0x67, 0xE9, 0xE0, 0x47, 0x21, 0xE7, 0x49, 0x14, 0x86, 0x1B, 0xD1, 0x81, 0x8B, 0x77, 0xF6, 0x4F, + 0x16, 0x4A, 0x7D, 0x56, 0xA8, 0xE4, 0x8A, 0xD6, 0xB2, 0xBB, 0xB8, 0x2C, 0x81, 0x27, 0x4D, 0xD1, 0xC5, 0x66, 0x99, 0xF5, + 0xC1, 0x9E, 0x7E, 0x5F, 0x76, 0xA9, 0x82, 0xBB, 0xFB, 0xD5, 0x2E, 0x4C, 0x01, 0x4B, 0xD6, 0x59, 0xDB, 0xBB, 0x76, 0x6C, + 0x8C, 0x83, 0x92, 0x7B, 0x7B, 0xD4, 0x4E, 0x59, 0x45, 0x7C, 0x03, 0x49, 0x55, 0x7C, 0xD6, 0x61, 0x2F, 0x36, 0x6D, 0xDA, + 0x91, 0xBD, 0x09, 0x6D, 0xA1, 0xDB, 0x41, 0x7A, 0xE6, 0xED, 0x5B, 0x11, 0xDD, 0x03, 0x09, 0x3D, 0xD9, 0x2A, 0x1D, 0x81, + 0xCB, 0x48, 0x9F, 0x17, 0x38, 0x16, 0xBA, 0x87, 0x1A, 0x45, 0x84, 0x4B, 0x36, 0xF4, 0xD7, 0x53, 0x9D, 0xD5, 0xF0, 0xCE, + 0xAD, 0xEE, 0xDC, 0x1A, 0x59, 0x67, 0x4A, 0x75, 0x33, 0x68, 0xCE, 0x66, 0x67, 0x95, 0x39, 0x83, 0x3A, 0x49, 0xE2, 0x49, + 0x8A, 0x46, 0x57, 0x53, 0x0B, 0x15, 0xB8, 0xC1, 0xCC, 0x26, 0x93, 0x6D, 0x9C, 0x6C, 0x52, 0xDD, 0x2C, 0x7D, 0x56, 0x00, + 0xE2, 0xF0, 0x72, 0xD2, 0x36, 0x25, 0xE3, 0x4E, 0xED, 0xE1, 0xC4, 0x3B, 0x7E, 0x62, 0xDC, 0x75, 0x39, 0xB5, 0x54, 0x41, + 0xA3, 0x7D, 0x12, 0x10, 0x0C, 0xE1, 0x10, 0xA4, 0x63, 0x7C, 0x9A, 0x2F, 0x39, 0x41, 0x3A, 0x66, 0xF6, 0x40, 0x4F, 0xBC, + 0x73, 0xE6, 0x21, 0xCB, 0x8B, 0xCC, 0xFD, 0x70, 0xDA, 0x81, 0x21, 0x74, 0x49, 0x0F, 0x28, 0x13, 0x57, 0xC8, 0x8B, 0x31, + 0xC1, 0x02, 0xAD, 0x9D, 0x98, 0x26, 0x19, 0x9B, 0xA8, 0x39, 0xC3, 0x41, 0xDD, 0x76, 0x20, 0xE7, 0xD7, 0x20, 0xDC, 0x80, + 0xB9, 0x39, 0x40, 0x52, 0x53, 0x54, 0x90, 0xC4, 0x4D, 0x1E, 0xD8, 0xCE, 0x0F, 0xCD, 0xF5, 0xF2, 0xDA, 0x60, 0xD3, 0x46, + 0x45, 0x57, 0xA2, 0x8C, 0xB3, 0x41, 0xB9, 0x69, 0xA4, 0x7E, 0xDF, 0xF5, 0xD8, 0x43, 0xDF, 0x57, 0xF0, 0x9F, 0xAB, 0x9C, + 0x32, 0x7B, 0x64, 0x7A, 0x5E, 0x88, 0x4D, 0xFD, 0x2B, 0x3E, 0xAB, 0xD1, 0x40, 0xFC, 0x95, 0xB1, 0x71, 0x6B, 0xD1, 0xFF, + 0x1A, 0x56, 0x53, 0x40, 0x57, 0x22, 0xAB, 0x9B, 0x0A, 0x59, 0xAD, 0x82, 0x31, 0x7B, 0x72, 0xED, 0x03, 0xF8, 0x0C, 0xBC, + 0x79, 0xBE, 0x5E, 0x00, 0x25, 0xE4, 0xCE, 0x16, 0x06, 0x7E, 0xD8, 0x02, 0xA1, 0xE6, 0x9F, 0xEA, 0xDA, 0x35, 0x43, 0x83, + 0x19, 0x8D, 0x2E, 0x0D, 0xA7, 0x3B, 0x4B, 0x94, 0xDF, 0x13, 0x32, 0x37, 0x4F, 0xC6, 0x9D, 0x99, 0xB4, 0xC8, 0x4A, 0x71, + 0xC2, 0x77, 0x06, 0x71, 0x24, 0x5A, 0xF8, 0xB1, 0xC0, 0x49, 0x46, 0x59, 0x1C, 0x78, 0x3A, 0xD3, 0xBA, 0x7D, 0xE9, 0xF6, + 0xFF, 0x11, 0x03, 0x82, 0x49, 0xCD, 0xCA, 0x78, 0x59, 0xD2, 0x9D, 0xCF, 0x01, 0xFF, 0x03, 0x4E, 0x27, 0x67, 0x30, 0xA4, + 0xBE, 0xA3, 0x29, 0x95, 0x65, 0xFC, 0x2C, 0x3F, 0xF8, 0x70, 0xC3, 0xEA, 0x8F, 0xB3, 0x98, 0xDA, 0x50, 0x8A, 0x07, 0x88, + 0x9D, 0x19, 0xB7, 0xCE, 0x89, 0xFD, 0x66, 0xC0, 0x27, 0xED, 0x06, 0x05, 0x8E, 0x91, 0x0C, 0x7C, 0x16, 0x1E, 0xAD, 0xCB, + 0xDB, 0xC3, 0xD9, 0x25, 0x2D, 0x04, 0x4C, 0xAF, 0x19, 0x94, 0x56, 0xE8, 0x54, 0x7D, 0x9B, 0x78, 0x4A, 0x5A, 0x46, 0xCB, + 0xA6, 0x74, 0x50, 0xBC, 0xCE, 0x37, 0x4E, 0x35, 0x65, 0xC8, 0xE9, 0xC1, 0xFC, 0x47, 0x2A, 0xAA, 0xD7, 0x10, 0x5C, 0x3D, + 0xB5, 0xB4, 0x7F, 0xFD, 0xD4, 0x5F, 0x1F, 0x95, 0x41, 0x3D, 0x61, 0x64, 0x92, 0x88, 0xFB, 0x31, 0x6B, 0x22, 0x8D, 0xBD, + 0xF1, 0x16, 0xC8, 0xDD, 0x75, 0x02, 0xFC, 0x62, 0x01, 0x8A, 0xD5, 0x64, 0xFE, 0x90, 0x80, 0xCD, 0xAC, 0xCB, 0x80, 0xCC, + 0xAC, 0x8D, 0xA1, 0x45, 0xEA, 0x2F, 0x7A, 0x2D, 0x92, 0x98, 0x39, 0x2F, 0xF7, 0xE7, 0xE8, 0x7B, 0x71, 0x63, 0x20, 0x2C, + 0xA7, 0xC1, 0x97, 0x3E, 0x18, 0x05, 0xD5, 0xAC, 0xC6, 0xBA, 0xDA, 0x77, 0x85, 0x1E, 0x22, 0xA0, 0x65, 0xF1, 0xBA, 0x69, + 0x7E, 0xA7, 0x67, 0xE6, 0x77, 0x8E, 0xB6, 0x04, 0xAD, 0x1D, 0x2E, 0xA2, 0xF8, 0x8A, 0xF6, 0x6F, 0x34, 0xAF, 0xF7, 0x10, + 0xCA, 0x13, 0xEF, 0xF2, 0x66, 0x47, 0x77, 0x6A, 0x80, 0x9F, 0x21, 0x2F, 0xDC, 0xAB, 0x49, 0x9D, 0xC0, 0xDF, 0xE9, 0xE2, + 0xB5, 0x93, 0x49, 0xF7, 0x6E, 0x76, 0xDE, 0xF7, 0x6B, 0x56, 0x31, 0x62, 0xC1, 0xDE, 0xA3, 0x88, 0x74, 0x6C, 0xBD, 0x41, + 0xF1, 0xE4, 0xEA, 0x4E, 0x18, 0x84, 0x34, 0x17, 0x65, 0xA6, 0xD0, 0xB6, 0xA9, 0x6E, 0xEA, 0x72, 0xA6, 0x0F, 0xBF, 0x9A, + 0x2C, 0x0B, 0x6A, 0x8F, 0x4F, 0x64, 0xBA, 0xC3, 0x0F, 0xEF, 0x41, 0x1B, 0x8D, 0x1B, 0xB9, 0xFF, 0x20, 0x0B, 0x35, 0x17, + 0xE5, 0x86, 0xB3, 0xEF, 0x9C, 0x31, 0x29, 0x5B, 0xE5, 0xB0, 0x93, 0xEC, 0xA1, 0x24, 0xEB, 0xC9, 0x32, 0x66, 0x18, 0x71, + 0x7C, 0x62, 0x72, 0x2D, 0x76, 0x01, 0x22, 0x36, 0x84, 0xC2, 0xFD, 0x14, 0xED, 0x47, 0x29, 0x5F, 0x6A, 0xAE, 0x7F, 0xDE, + 0x32, 0xA3, 0xAB, 0x38, 0xC9, 0xA5, 0xB2, 0x08, 0xEC, 0x30, 0x82, 0x62, 0xDF, 0xD3, 0x9E, 0x70, 0xB2, 0x7B, 0xBA, 0x49, + 0x3B, 0x58, 0x96, 0x52, 0xC8, 0xD7, 0xEA, 0xFE, 0x7F, 0x6C, 0x63, 0x57, 0x93, 0x3A, 0x3C, 0x64, 0xBD, 0x5A, 0x6D, 0x19, + 0xA7, 0xC2, 0xA1, 0x0F, 0xB7, 0xBE, 0x70, 0x62, 0x7D, 0xD1, 0xC6, 0xC6, 0xDD, 0x21, 0x2D, 0x33, 0xC5, 0x7F, 0x30, 0xE6, + 0x70, 0xF4, 0xC9, 0x1A, 0x80, 0xC7, 0x80, 0xAA, 0xC9, 0xC0, 0xFC, 0xC6, 0xF7, 0x5A, 0x5B, 0xC5, 0x05, 0x27, 0x89, 0x6B, + 0x20, 0xDF, 0xC7, 0x87, 0xB7, 0xF2, 0xA2, 0x58, 0x18, 0xD1, 0x61, 0x60, 0x1D, 0x43, 0x65, 0xD7, 0x4C, 0xD0, 0x6D, 0xEB, + 0x44, 0xDD, 0x88, 0x82, 0x99, 0x91, 0xB5, 0xAF, 0x2C, 0x0E, 0x62, 0xEB, 0x8E, 0x05, 0xE0, 0x3A, 0x36, 0xA1, 0xCF, 0x32, + 0x6E, 0xAD, 0xED, 0xF3, 0x85, 0x91, 0x2E, 0xE3, 0x1F, 0xD7, 0x40, 0x73, 0xE2, 0xD6, 0xEB, 0x01, 0xE3, 0x58, 0x3C, 0x9F, + 0x1F, 0xB7, 0x5F, 0x30, 0x9E, 0x1D, 0xF2, 0xCF, 0x36, 0x16, 0x6D, 0xFB, 0x85, 0x14, 0xCD, 0x1C, 0x1F, 0xA7, 0x74, 0x90, + 0x86, 0x96, 0x46, 0x1D, 0x0C, 0xF5, 0x2F, 0xB4, 0x0C, 0xB3, 0xE4, 0x54, 0x94, 0x57, 0x28, 0x2B, 0x0F, 0x0B, 0x98, 0xB7, + 0xFE, 0xB2, 0x2F, 0x3B, 0x0F, 0x27, 0x99, 0xF4, 0x89, 0x64, 0x55, 0x92, 0x88, 0x26, 0xE6, 0x96, 0xC0, 0x3F, 0x29, 0x3E, + 0x5C, 0x7B, 0x9E, 0xAE, 0x85, 0x48, 0xB7, 0x63, 0x24, 0xD7, 0x99, 0xB7, 0x7E, 0xBA, 0x4F, 0x5B, 0x9B, 0x7B, 0x00, 0x96, + 0x08, 0x6B, 0x39, 0xF9, 0x52, 0x06, 0xE7, 0xE1, 0x7F, 0xBB, 0x07, 0x2B, 0x4E, 0x7B, 0x8C, 0x87, 0xFB, 0x02, 0x3C, 0x36, + 0x46, 0xAD, 0xFB, 0x6F, 0x5D, 0x67, 0x4D, 0x08, 0x32, 0x6C, 0x61, 0x6A, 0x4F, 0xD0, 0x36, 0x4E, 0x4C, 0x14, 0xA8, 0xBC, + 0x7D, 0xB2, 0x69, 0xE1, 0x1B, 0x50, 0x6F, 0x14, 0x82, 0xB2, 0xA7, 0xA3, 0xE4, 0x93, 0xF1, 0xF6, 0xB8, 0xA7, 0x9C, 0x2C, + 0xCA, 0x2A, 0x08, 0x1F, 0x5A, 0x5F, 0x79, 0xF2, 0x1C, 0xD2, 0xE9, 0x7F, 0x3F, 0x89, 0x01, 0xC6, 0x06, 0xD5, 0x6F, 0xFF, + 0xFF, 0xFF, 0xBF, 0xF1, 0xA3, 0x40, 0xFE, 0x02, 0xF1, 0xA3, 0xF7, 0x5E, 0x21, 0x44, 0xD6, 0x46, 0x73, 0xB1, 0xA8, 0x63, + 0xA2, 0x82, 0x18, 0xE7, 0x95, 0xAC, 0x88, 0xC3, 0xC5, 0xCC, 0x58, 0x58, 0xEF, 0x0D, 0x33, 0x31, 0x19, 0xAD, 0x29, 0xF6, + 0x1C, 0x2F, 0x68, 0xD1, 0x40, 0x54, 0xA6, 0x19, 0x2C, 0x93, 0xBF, 0xE2, 0x0D, 0x0E, 0xDB, 0x53, 0x7A, 0x47, 0x4B, 0x72, + 0x2A, 0x27, 0x26, 0xA6, 0xB3, 0xBE, 0x3B, 0x87, 0xFB, 0xF2, 0x3F, 0xB4, 0x64, 0x85, 0xB1, 0x20, 0x1E, 0xCF, 0x94, 0x06, + 0x71, 0x86, 0x6E, 0xF0, 0x3D, 0x70, 0xF0, 0xAC, 0x13, 0xD4, 0x1E, 0x80, 0xBC, 0x4A, 0x18, 0x18, 0xED, 0x09, 0x7A, 0xDF, + 0x83, 0xB6, 0x90, 0xC1, 0xAB, 0x16, 0xE4, 0x5C, 0xC4, 0x5F, 0xE6, 0x49, 0x2E, 0x57, 0x1D, 0x6A, 0xE1, 0x92, 0x36, 0x2F, + 0xE5, 0xF8, 0x99, 0x19, 0xC9, 0x4A, 0x66, 0xE6, 0xAB, 0xBA, 0x92, 0xF8, 0x7F, 0xA9, 0x12, 0xFF, 0x9C, 0xA5, 0x82, 0xDB, + 0xCC, 0xC5, 0xF4, 0x89, 0x5B, 0x88, 0x58, 0x2F, 0xE2, 0x6D, 0x1A, 0xED, 0xBA, 0xE9, 0x8A, 0xC8, 0x1C, 0xE8, 0xBC, 0x00, + 0x73, 0xDC, 0x16, 0xFA, 0x0C, 0x87, 0xD1, 0x13, 0x73, 0x4E, 0x41, 0x6A, 0x23, 0x2E, 0x30, 0x88, 0x04, 0xE9, 0x9B, 0x22, + 0xBD, 0xFE, 0xB9, 0x2D, 0xB2, 0x84, 0x8E, 0xCA, 0x4D, 0xC6, 0x08, 0x02, 0xFB, 0x29, 0x96, 0x77, 0x76, 0x08, 0x98, 0x26, + 0x72, 0x3F, 0x10, 0x8A, 0x16, 0x48, 0xB4, 0x54, 0x59, 0x8C, 0xFF, 0xFC, 0xF3, 0xCE, 0x57, 0xF1, 0xC2, 0xD0, 0x62, 0xBF, + 0x89, 0x6D, 0xFC, 0x50, 0x67, 0xCD, 0xC6, 0x5A, 0xF6, 0x7D, 0x03, 0x25, 0x10, 0x6C, 0x7F, 0xED, 0xFB, 0x6C, 0x70, 0x55, + 0x06, 0xDF, 0x78, 0xE8, 0x77, 0x0C, 0xE4, 0x07, 0x6E, 0xB3, 0x53, 0x68, 0x37, 0x7E, 0x4A, 0x0E, 0xEF, 0x03, 0xA0, 0xA4, + 0x83, 0xBD, 0x96, 0xF3, 0x14, 0x9F, 0x84, 0x53, 0xE4, 0xDD, 0xAA, 0x01, 0x93, 0x79, 0xAC, 0xE2, 0x4B, 0xE0, 0x3A, 0xB0, + 0xED, 0x80, 0x24, 0x94, 0x8A, 0x35, 0xFE, 0x94, 0x98, 0x12, 0x55, 0xB0, 0x94, 0xBD, 0x25, 0xF6, 0x13, 0xB1, 0x47, 0x8B, + 0x0B, 0x36, 0x8C, 0x62, 0x19, 0xF1, 0x73, 0x96, 0x85, 0x98, 0x4D, 0xE9, 0xE7, 0x35, 0x43, 0x53, 0xE5, 0xFE, 0xFF, 0xB4, + 0xF2, 0xC9, 0xD5, 0x44, 0x13, 0xFD, 0x10, 0x3E, 0x34, 0x8E, 0x4D, 0xE0, 0x95, 0x31, 0x14, 0x8D, 0x7F, 0xDB, 0xD9, 0xF7, + 0x82, 0xBA, 0x93, 0x2B, 0x4C, 0x40, 0xF0, 0x75, 0xB6, 0x37, 0x68, 0x87, 0x0B, 0x7A, 0x85, 0xA9, 0xEE, 0xB9, 0x8E, 0xE1, + 0x8D, 0xC6, 0x6D, 0x09, 0xAE, 0x8A, 0x71, 0x96, 0x82, 0x79, 0x5E, 0xEA, 0x97, 0xE2, 0x16, 0xE2, 0xB5, 0xED, 0x34, 0x1A, + 0x1C, 0xDC, 0xDB, 0xDC, 0xDA, 0xFD, 0xE3, 0xB5, 0xC3, 0x5C, 0x30, 0xEC, 0x99, 0x97, 0x85, 0x2C, 0x28, 0xE4, 0xA8, 0x18, + 0xBA, 0x79, 0xAA, 0xBC, 0x4A, 0xDB, 0xDE, 0x6C, 0xC6, 0x96, 0x61, 0xC7, 0x01, 0x54, 0xD6, 0x79, 0x90, 0x7A, 0x3D, 0x39, + 0x2D, 0xB5, 0x10, 0xAA, 0x19, 0x95, 0x2F, 0x53, 0x44, 0x57, 0xA9, 0x1C, 0x3A, 0x5A, 0x19, 0xA1, 0x42, 0x5F, 0x5B, 0x6E, + 0xDB, 0x94, 0x8F, 0x49, 0x95, 0xAA, 0x5F, 0xD5, 0x4C, 0x39, 0x53, 0x4C, 0x4F, 0xF3, 0xBA, 0xBE, 0xD1, 0x0D, 0xC1, 0xD9, + 0x58, 0x1E, 0x46, 0x83, 0x59, 0x1D, 0x28, 0x18, 0x28, 0x2E, 0x86, 0x1C, 0x50, 0xB6, 0x5E, 0xC5, 0x94, 0xC0, 0x6A, 0x9E, + 0x48, 0x9D, 0x7D, 0x36, 0x57, 0x72, 0xF9, 0xE4, 0x37, 0x98, 0x4E, 0x8B, 0x4B, 0xC5, 0x17, 0x85, 0xFA, 0xA1, 0x15, 0xF6, + 0xD7, 0x5D, 0x2A, 0xEC, 0x83, 0x7D, 0x8C, 0x07, 0x88, 0x03, 0x74, 0xBA, 0xF5, 0xA3, 0x35, 0x86, 0x7D, 0x99, 0x00, 0x74, + 0x76, 0xCC, 0x62, 0x64, 0xAF, 0xA4, 0x29, 0x89, 0xD9, 0x1D, 0x9D, 0xE2, 0x9B, 0x20, 0x9A, 0x26, 0x88, 0x0E, 0x40, 0x00, + 0x3D, 0x3E, 0xEE, 0xF6, 0x19, 0x35, 0x96, 0x2F, 0x82, 0x7B, 0x31, 0xF6, 0x37, 0x62, 0xA1, 0x19, 0x67, 0x6D, 0xD7, 0x93, + 0x21, 0x44, 0x3C, 0xE0, 0x01, 0x0E, 0x09, 0x65, 0xF7, 0xCF, 0x07, 0xD1, 0xB7, 0x1C, 0xEF, 0x28, 0xB3, 0x47, 0xA0, 0x3B, + 0x02, 0x0F, 0x20, 0x47, 0x9F, 0xF8, 0xB0, 0x07, 0xC2, 0x86, 0x92, 0x7B, 0x57, 0x78, 0x71, 0xC3, 0x64, 0xA5, 0x45, 0x6C, + 0x2D, 0x10, 0xF8, 0x63, 0xBB, 0xF4, 0x6E, 0x86, 0xEB, 0x44, 0xBA, 0x72, 0xFE, 0xC4, 0x5A, 0x09, 0x0B, 0x5B, 0x68, 0xE2, + 0x67, 0x41, 0xCF, 0x4A, 0x35, 0xEF, 0x11, 0x77, 0x66, 0x28, 0x38, 0x69, 0xAD, 0x52, 0xB9, 0x1A, 0xD2, 0x67, 0xEC, 0xF3, + 0xE6, 0x45, 0x70, 0x4C, 0xE7, 0xEC, 0x32, 0xF1, 0x2F, 0xAC, 0xA2, 0xD9, 0xC0, 0x55, 0x21, 0x8A, 0x14, 0x39, 0x3C, 0x36, + 0xE6, 0xCD, 0x10, 0x43, 0xFA, 0xE8, 0xAA, 0x45, 0x26, 0xC6, 0x3D, 0x7E, 0xE1, 0x44, 0x1B, 0xF4, 0xEF, 0xB0, 0x19, 0x53, + 0x7B, 0xBA, 0x4B, 0x0C, 0x35, 0xC5, 0x8D, 0x13, 0x51, 0x6C, 0x11, 0xAB, 0x00, 0x24, 0xF5, 0xFD, 0x99, 0x2E, 0xBB, 0x09, + 0xAD, 0x26, 0xE9, 0xCD, 0xFE, 0x8B, 0x77, 0xCE, 0x3F, 0xAE, 0x33, 0xCA, 0x16, 0x80, 0x67, 0x19, 0x76, 0xA0, 0xCC, 0x43, + 0xFD, 0x6D, 0x62, 0xAB, 0xF3, 0xBC, 0x3B, 0xA0, 0x3B, 0xA0, 0x76, 0xDB, 0x6B, 0x39, 0xC2, 0x6E, 0xFC, 0x40, 0x5B, 0x8C, + 0x4C, 0xAE, 0x5C, 0x62, 0x61, 0x73, 0x11, 0x76, 0xCD, 0x8E, 0x28, 0xEB, 0xEF, 0x4C, 0xAB, 0x27, 0xD9, 0x7B, 0xFD, 0x3D, + 0x64, 0x22, 0xAD, 0x60, 0xFD, 0x8D, 0xEE, 0xFB, 0xEE, 0xF6, 0x1E, 0x32, 0xA9, 0x3F, 0xF2, 0x75, 0x52, 0x3D, 0x4A, 0xA4, + 0x85, 0x53, 0xAD, 0xB3, 0x83, 0x95, 0x72, 0x70, 0x21, 0x14, 0xBA, 0xAA, 0x33, 0xA8, 0x02, 0x1F, 0x0E, 0xDE, 0x82, 0x13, + 0x03, 0x2E, 0x81, 0xE1, 0x80, 0x6F, 0xDB, 0xBB, 0xD7, 0x88, 0x9D, 0x50, 0x68, 0x93, 0x8D, 0x96, 0x96, 0x0D, 0x3F, 0x88, + 0x81, 0x9C, 0x7C, 0xF5, 0x94, 0xFB, 0xBD, 0x81, 0x85, 0x67, 0xE3, 0x55, 0xF1, 0x5E, 0x7D, 0x53, 0x87, 0x3D, 0xFD, 0x02, + 0x97, 0xBD, 0x62, 0x4A, 0x60, 0xCD, 0x30, 0x2C, 0xCD, 0x5B, 0x75, 0xA7, 0x21, 0x8C, 0xFF, 0x25, 0x4F, 0x1A, 0xDF, 0x5B, + 0xBB, 0x86, 0x3C, 0x9E, 0xEF, 0xF8, 0x70, 0x23, 0x9A, 0xD4, 0x7B, 0x37, 0x49, 0x19, 0x50, 0x67, 0xDB, 0xA5, 0xA5, 0x17, + 0x63, 0x47, 0xEB, 0x29, 0x0B, 0x9A, 0x78, 0xA5, 0x5C, 0xE6, 0x43, 0x46, 0xE1, 0xCE, 0x86, 0x07, 0x8B, 0x46, 0x19, 0x7B, + 0x8F, 0xD8, 0xFC, 0xF4, 0x54, 0x69, 0xA6, 0xD9, 0x4E, 0x59, 0x21, 0x9C, 0x1C, 0x4C, 0x3C, 0x9E, 0xD2, 0x14, 0xF6, 0x36, + 0x5E, 0x62, 0x13, 0xC5, 0xE0, 0x98, 0x0A, 0xDC, 0x15, 0x3A, 0x15, 0xBB, 0x41, 0xDB, 0x67, 0xE6, 0xB6, 0xB7, 0xB7, 0x54, + 0xEA, 0x23, 0x77, 0xC7, 0xB0, 0x65, 0xFB, 0x65, 0x5C, 0xF5, 0xB9, 0xA3, 0xBB, 0xA2, 0x29, 0xD9, 0x8D, 0x2B, 0xC0, 0xCC, + 0x97, 0x68, 0x19, 0x22, 0x77, 0xD1, 0xBC, 0x07, 0x56, 0xED, 0x2A, 0x6E, 0x5F, 0x3C, 0x88, 0xE8, 0x9F, 0x7F, 0xD6, 0x6B, + 0x13, 0xC2, 0xF6, 0xFF, 0x5C, 0x20, 0xF8, 0xA4, 0xE2, 0xBF, 0xE7, 0x55, 0x79, 0xE4, 0x71, 0xF3, 0x11, 0x8C, 0x27, 0xA7, + 0x88, 0xB3, 0x8C, 0xCC, 0x4F, 0xC5, 0x5F, 0xED, 0x9E, 0xBC, 0x83, 0xA0, 0x31, 0x02, 0xF9, 0xF3, 0xB9, 0x86, 0xD4, 0x7E, + 0x7C, 0xE0, 0x79, 0x01, 0x53, 0xF2, 0x59, 0x15, 0xD5, 0x6C, 0xB6, 0x20, 0x16, 0x39, 0x6D, 0xDF, 0x23, 0x5D, 0xED, 0xDB, + 0x33, 0x3C, 0x75, 0xE3, 0x23, 0x8A, 0xF1, 0x33, 0xB0, 0x8E, 0x7C, 0x52, 0xBA, 0x03, 0x27, 0xB0, 0x60, 0x98, 0xC5, 0x5F, + 0x8E, 0x1C, 0xB8, 0x81, 0xA1, 0xC2, 0x07, 0x80, 0xC6, 0x5B, 0x04, 0xA1, 0xE1, 0x56, 0x30, 0x28, 0x87, 0x1A, 0x29, 0x1F, + 0x1D, 0x4F, 0xD2, 0x56, 0x3C, 0xEC, 0x59, 0x5D, 0x9D, 0xBC, 0xFB, 0xB2, 0x23, 0xC6, 0x94, 0xB4, 0x64, 0x85, 0xE4, 0x0F, + 0x44, 0x5D, 0x4E, 0x77, 0x1A, 0x55, 0x51, 0xFC, 0xE2, 0x0A, 0xF0, 0xAB, 0x70, 0x38, 0xA1, 0x57, 0xE2, 0x3A, 0x5F, 0x34, + 0xBA, 0x24, 0x1B, 0x88, 0xF6, 0x44, 0x91, 0xC1, 0xAB, 0x16, 0xCE, 0xE5, 0xF3, 0xA6, 0xEF, 0x4C, 0x5F, 0xE0, 0x13, 0x0D, + 0xF7, 0x45, 0xDF, 0xF5, 0x95, 0x3E, 0xE6, 0x40, 0x62, 0xC6, 0xB9, 0x76, 0x86, 0x6A, 0x66, 0x6A, 0xFB, 0x83, 0xE0, 0x8E, + 0xF1, 0x4C, 0x6A, 0x1A, 0xB3, 0xE5, 0x26, 0x4E, 0x6B, 0x88, 0x30, 0xA8, 0x8C, 0xA6, 0xB5, 0x8E, 0x9B, 0xB4, 0x8A, 0x27, + 0x2B, 0xFD, 0x5E, 0xF6, 0xE2, 0x96, 0xD0, 0x30, 0x63, 0x4E, 0xE1, 0x0D, 0x99, 0xE9, 0xC3, 0xAD, 0xF9, 0xEF, 0x38, 0x6A, + 0xD6, 0xB6, 0xAF, 0x7B, 0x32, 0x96, 0xE9, 0x1D, 0x98, 0xFA, 0x4D, 0xBD, 0xF8, 0x4B, 0xC1, 0x57, 0xE5, 0x29, 0x5B, 0xD3, + 0xEB, 0x03, 0xA6, 0x2E, 0xE1, 0x6E, 0x4D, 0x9B, 0xCE, 0xC1, 0xD8, 0x6E, 0xF9, 0x2E, 0x70, 0xBE, 0x57, 0x09, 0xB2, 0x6E, + 0xE0, 0xB8, 0xE3, 0x9A, 0xE7, 0x30, 0x51, 0x1E, 0x7A, 0xFD, 0x19, 0x39, 0xFE, 0x11, 0x08, 0x2A, 0x67, 0x81, 0x01, 0x2A, + 0x21, 0x2A, 0x18, 0xD8, 0x58, 0x4A, 0x3D, 0x7D, 0x12, 0xF2, 0xB3, 0x2E, 0xB1, 0x6D, 0x23, 0x89, 0x83, 0xFE, 0xE5, 0x15, + 0x54, 0xE9, 0xFF, 0xEB, 0x26, 0x09, 0x44, 0xEC, 0x81, 0x72, 0x2F, 0xFF, 0x66, 0x8A, 0x34, 0xD6, 0x12, 0x3C, 0x9C, 0xD7, + 0x05, 0xE5, 0xD6, 0x6B, 0x92, 0x54, 0x4E, 0x34, 0x50, 0x06, 0x01, 0xC7, 0x2C, 0x7A, 0xDA, 0xC1, 0xA4, 0x7C, 0x98, 0xC0, + 0x5B, 0x56, 0xA9, 0xBE, 0x86, 0xFF, 0xEB, 0xA2, 0xF4, 0xF2, 0x5D, 0x8A, 0x8B, 0x51, 0xF5, 0xB1, 0xD2, 0x46, 0xDD, 0xD9, + 0xAD, 0x8C, 0xD5, 0x95, 0xA7, 0xCB, 0x5C, 0xED, 0x24, 0x0D, 0xCC, 0xC1, 0x4D, 0x34, 0x6E, 0x50, 0xEB, 0x16, 0x8E, 0x58, + 0x0E, 0x36, 0x55, 0xB8, 0x25, 0x0C, 0x17, 0xD6, 0x4C, 0xDD, 0x24, 0xE4, 0x83, 0xD4, 0x4C, 0x04, 0x2C, 0x84, 0x03, 0xBB, + 0x01, 0x54, 0x55, 0x38, 0xBA, 0x77, 0x4C, 0x42, 0x1F, 0xFD, 0xC8, 0xEC, 0x07, 0x79, 0xCB, 0x3F, 0x0F, 0x1A, 0x92, 0xB2, + 0xB5, 0x4D, 0x70, 0x02, 0x67, 0xDA, 0xA3, 0xF3, 0x12, 0xF4, 0x1F, 0x88, 0xDF, 0x7D, 0x11, 0x08, 0x09, 0x9A, 0xA2, 0xCA, + 0x5B, 0xB8, 0xAC, 0x53, 0x85, 0x14, 0xA2, 0x1D, 0xFC, 0x7B, 0x4E, 0xF4, 0x73, 0xB2, 0xDA, 0x72, 0xD2, 0xC6, 0x5E, 0xD4, + 0x24, 0x74, 0x3F, 0x61, 0xE4, 0xC6, 0x3A, 0x6F, 0xD8, 0xE1, 0xBC, 0xEE, 0xE6, 0x86, 0xF1, 0x6D, 0xFB, 0xD2, 0x66, 0x72, + 0x56, 0x90, 0x8B, 0x7F, 0xBF, 0x22, 0x21, 0x08, 0xEF, 0x62, 0x87, 0x05, 0x9A, 0x0E, 0xBB, 0x8F, 0xF4, 0x41, 0xF7, 0xB3, + 0x1B, 0xBE, 0x04, 0xAF, 0x6C, 0x45, 0x7E, 0x1F, 0xF6, 0x71, 0xF7, 0x86, 0xF6, 0x60, 0xD2, 0x3A, 0x9E, 0x53, 0xFE, 0x8A, + 0x09, 0x71, 0xA0, 0xFA, 0x9A, 0xFE, 0xA4, 0x09, 0xB2, 0xC2, 0x9E, 0x56, 0x1F, 0x9F, 0xFE, 0xD9, 0x93, 0xF1, 0x2C, 0x1D, + 0xDB, 0x8F, 0xE0, 0x82, 0x5A, 0xA3, 0xAD, 0x4D, 0xBA, 0xAF, 0x9F, 0x91, 0x41, 0xD4, 0x77, 0x0E, 0x77, 0x72, 0x32, 0x06, + 0xFB, 0x0D, 0x60, 0x6E, 0x79, 0xE2, 0xCB, 0x05, 0xE5, 0xDB, 0xA9, 0xA5, 0xA9, 0xEF, 0xE8, 0x7A, 0x7A, 0x89, 0x90, 0xE5, + 0x91, 0xB5, 0x93, 0xB7, 0xD6, 0xFE, 0x80, 0x06, 0x13, 0xA3, 0xF5, 0xFD, 0x6D, 0x81, 0xB8, 0x12, 0x27, 0xC7, 0xB7, 0x7D, + 0x49, 0xA0, 0x8E, 0x16, 0x75, 0x43, 0xAB, 0x78, 0x83, 0x9A, 0x0D, 0xD0, 0x57, 0xAF, 0x42, 0x40, 0xAF, 0x81, 0xA0, 0xEB, + 0x26, 0x86, 0x4D, 0xB2, 0xF9, 0x7B, 0xF9, 0x71, 0x32, 0x09, 0xB0, 0x0A, 0xCF, 0x1B, 0xEA, 0xA6, 0x1E, 0xA6, 0x13, 0xA1, + 0x69, 0x18, 0x88, 0x11, 0x26, 0xA8, 0xC3, 0x94, 0x63, 0x71, 0x78, 0xAE, 0x25, 0x6E, 0x9A, 0x78, 0x85, 0x0B, 0x2D, 0xF5, + 0x9E, 0x14, 0x2B, 0xB2, 0xBA, 0xD9, 0x3E, 0xE8, 0x56, 0x3B, 0xC5, 0xC0, 0x84, 0x8D, 0xF1, 0xC2, 0xB7, 0x26, 0xEA, 0x0C, + 0xAC, 0xC8, 0x50, 0x4A, 0xD1, 0xFE, 0x7B, 0xCA, 0x4E, 0x25, 0x9C, 0x09, 0xDE, 0xA8, 0x2B, 0x2B, 0xBB, 0xAD, 0x8A, 0xD5, + 0xF0, 0xE5, 0x22, 0x07, 0xFC, 0x08, 0xBC, 0xB3, 0x1B, 0xB0, 0x96, 0xBF, 0x98, 0xAB, 0x07, 0x0F, 0xFC, 0x48, 0x73, 0x8F, + 0xBD, 0x91, 0xEB, 0x87, 0xFF, 0xDF, 0x0B, 0xC3, 0x80, 0x16, 0x48, 0x08, 0x7D, 0x15, 0xAB, 0xE4, 0x6C, 0xE8, 0xED, 0xEF, + 0x62, 0xA4, 0x52, 0xD0, 0x36, 0x37, 0x83, 0x0F, 0x82, 0x44, 0xB2, 0xBA, 0xB2, 0x1D, 0xA0, 0x89, 0xE3, 0x2A, 0xF0, 0x58, + 0x2E, 0x35, 0xD7, 0x0C, 0xA9, 0xAE, 0x77, 0xBA, 0x67, 0xF8, 0xA2, 0x56, 0xE6, 0x2B, 0xD6, 0xFE, 0x7E, 0x91, 0xA0, 0x14, + 0x23, 0xAF, 0xA3, 0x23, 0xC4, 0x83, 0xF2, 0x31, 0x5C, 0xAE, 0x0D, 0x6D, 0x2F, 0x4D, 0xEA, 0xB4, 0x2B, 0xE1, 0xBD, 0x4A, + 0xE1, 0x04, 0xFA, 0x25, 0x5D, 0xAF, 0x69, 0x26, 0x24, 0x8B, 0xE2, 0xFC, 0x7E, 0x30, 0x8D, 0xB3, 0x0E, 0xD2, 0x3A, 0x02, + 0x0D, 0xD8, 0x67, 0x26, 0x55, 0x30, 0x23, 0x22, 0x45, 0x52, 0xEC, 0x4E, 0x88, 0x65, 0x01, 0xED, 0xA8, 0x0D, 0xBA, 0xEC, + 0xE8, 0xB3, 0xA5, 0x4C, 0x86, 0x94, 0x3C, 0x88, 0x05, 0x2D, 0x65, 0xEF, 0x1E, 0xF3, 0xCE, 0x84, 0x45, 0xC9, 0x8D, 0x59, + 0x09, 0xB0, 0xFD, 0xE0, 0x87, 0xD1, 0x12, 0xCC, 0xDE, 0xBC, 0x96, 0x36, 0x76, 0xEC, 0x85, 0x4C, 0xC6, 0xAB, 0x67, 0xC0, + 0xB7, 0x68, 0x84, 0x87, 0xBA, 0xB9, 0xC4, 0xDF, 0xD5, 0x99, 0x58, 0x78, 0x36, 0x0B, 0x14, 0xD6, 0xDE, 0xD7, 0xD6, 0x3E, + 0xED, 0xFA, 0x05, 0x8C, 0xC0, 0x94, 0x78, 0x08, 0x08, 0xD5, 0x5A, 0x9C, 0x82, 0x3D, 0xEF, 0xC6, 0x15, 0xF7, 0x8E, 0x13, + 0xAD, 0x27, 0x65, 0x98, 0xA3, 0xFD, 0x74, 0xC3, 0x10, 0xF2, 0x7D, 0xA5, 0x5C, 0x86, 0xDA, 0x53, 0xE1, 0xCE, 0xC2, 0xAF, + 0xD4, 0x97, 0x3B, 0x32, 0x2A, 0x81, 0x26, 0xF5, 0x3A, 0xA1, 0x49, 0xF5, 0x9D, 0x24, 0x0E, 0x40, 0x6C, 0xB5, 0x77, 0x8F, + 0xF8, 0xF5, 0xF7, 0x8B, 0xE8, 0xD5, 0x40, 0x58, 0x8D, 0x66, 0x85, 0x30, 0x7C, 0x79, 0xA1, 0x75, 0x00, 0x97, 0xA5, 0x71, + 0x10, 0xB7, 0xF7, 0x77, 0x41, 0x27, 0x4A, 0x68, 0x05, 0x8C, 0xEB, 0xC5, 0xA3, 0x85, 0x6B, 0xC1, 0xB3, 0xA5, 0x01, 0x0F, + 0xEB, 0xC2, 0x57, 0x23, 0x7D, 0xA9, 0x5E, 0x25, 0xD3, 0x3D, 0xBC, 0x32, 0x56, 0x8D, 0x19, 0x88, 0x91, 0x57, 0x8D, 0x17, + 0x76, 0xBE, 0xCE, 0xA8, 0x4D, 0xB1, 0x02, 0x4C, 0x37, 0xB5, 0x67, 0xF1, 0xCE, 0x62, 0x7A, 0x03, 0x80, 0xBC, 0x5F, 0xFB, + 0xF3, 0x31, 0x27, 0xA7, 0xF4, 0xB3, 0xDE, 0xDA, 0xCC, 0x9C, 0xF3, 0x28, 0x0B, 0xF7, 0x11, 0xDC, 0x1A, 0x90, 0xE9, 0xE0, + 0x87, 0xFD, 0xBF, 0x27, 0x42, 0x2B, 0x6F, 0xFF, 0xDA, 0x49, 0x5E, 0x28, 0xEC, 0xAB, 0xE0, 0x1A, 0xDD, 0xFD, 0xA8, 0xBB, + 0x23, 0x44, 0xCB, 0x24, 0x2F, 0x69, 0x68, 0x12, 0x6A, 0x0C, 0x24, 0x86, 0xD1, 0xFC, 0x02, 0x32, 0x8B, 0x4E, 0x73, 0x2A, + 0x61, 0x95, 0x14, 0x61, 0x05, 0x93, 0xF9, 0x22, 0x6D, 0x2D, 0x6F, 0xC3, 0xD2, 0x0F, 0x4A, 0x12, 0xD6, 0x79, 0xF6, 0x43, + 0x8F, 0x89, 0xEB, 0x49, 0x90, 0x83, 0x51, 0x90, 0x3C, 0x21, 0x8C, 0x0B, 0x88, 0x96, 0x58, 0x44, 0x0B, 0x4A, 0xF8, 0x94, + 0xE9, 0x2B, 0x45, 0x93, 0x7A, 0xC9, 0xD8, 0x43, 0xB3, 0x6B, 0x6E, 0x7C, 0x0A, 0xA1, 0x82, 0xAF, 0xB0, 0x23, 0x66, 0x5D, + 0x2B, 0x48, 0xB8, 0x34, 0xF5, 0x68, 0x9A, 0xD2, 0xFD, 0x0F, 0xA1, 0x04, 0x35, 0x2B, 0x37, 0x49, 0x29, 0x57, 0xB1, 0x25, + 0x7C, 0x69, 0xDC, 0x15, 0xBC, 0x0E, 0xC5, 0xA3, 0x32, 0xAD, 0xA6, 0x02, 0xF7, 0x24, 0x93, 0x68, 0x92, 0x66, 0x84, 0xA8, + 0xA9, 0x48, 0xB8, 0x8E, 0xCC, 0x2B, 0xD6, 0xF8, 0x36, 0xB7, 0x19, 0xA8, 0x33, 0x61, 0xB2, 0xF8, 0x0D, 0x1B, 0x8A, 0xE1, + 0x2E, 0xF2, 0xFD, 0xB0, 0xEC, 0xC0, 0xC0, 0x39, 0xFE, 0x6D, 0x07, 0x4F, 0xBB, 0x54, 0xFB, 0xF4, 0xC8, 0xB1, 0xBF, 0xC1, + 0x1B, 0x07, 0xDB, 0x38, 0xEB, 0xFA, 0xB3, 0xF9, 0x99, 0x49, 0xAB, 0x99, 0xD2, 0x69, 0x3B, 0xAA, 0x6A, 0x41, 0xCD, 0xFA, + 0x5B, 0xBF, 0x9B, 0x6B, 0x71, 0x05, 0xBD, 0xAE, 0x98, 0x04, 0xA9, 0x98, 0x6B, 0xBD, 0xAA, 0xEE, 0x5B, 0x6B, 0xBB, 0xDC, + 0x60, 0x60, 0xB2, 0xDE, 0x12, 0x90, 0x89, 0x8B, 0xC7, 0xE0, 0xA2, 0xFE, 0x5A, 0x8F, 0x18, 0xC6, 0x8C, 0xFD, 0x38, 0x2F, + 0xD9, 0x91, 0x2D, 0x6F, 0xA9, 0xAB, 0xE8, 0x8F, 0x76, 0xD3, 0x15, 0x71, 0x8B, 0xA0, 0xF3, 0x8D, 0x6C, 0x20, 0x4A, 0x9B, + 0x67, 0xE2, 0x64, 0x9F, 0x59, 0x27, 0x7A, 0x86, 0xC9, 0x01, 0xE4, 0x9A, 0x3D, 0x3D, 0x4E, 0x92, 0x44, 0xDD, 0xF4, 0xBA, + 0x79, 0xFB, 0xBC, 0xE7, 0x2F, 0x4E, 0x98, 0x4F, 0x46, 0xD4, 0x7C, 0xAE, 0x68, 0xDA, 0x24, 0x4A, 0x61, 0x3C, 0xD6, 0x72, + 0x2C, 0x1F, 0x9F, 0x84, 0x93, 0x72, 0x75, 0xBA, 0x10, 0x5D, 0x8F, 0x47, 0xC3, 0x2A, 0xB9, 0xF3, 0xAF, 0x6C, 0x52, 0xF5, + 0xB7, 0x98, 0xCD, 0x53, 0x00, 0x48, 0x62, 0x31, 0x9A, 0x7A, 0xA3, 0x30, 0xA2, 0x0B, 0xFE, 0x26, 0xB0, 0x1C, 0x2C, 0x62, + 0xB6, 0xCF, 0xB4, 0x44, 0xCE, 0x79, 0xC8, 0x96, 0x3F, 0x54, 0xB4, 0x56, 0x36, 0x6C, 0x3E, 0xE0, 0x62, 0x95, 0x54, 0x31, + 0xD2, 0xFD, 0x5B, 0x00, 0x30, 0x1E, 0x65, 0xA7, 0xF1, 0x89, 0x6D, 0xF1, 0x41, 0x3A, 0x9F, 0x5A, 0x51, 0x70, 0x96, 0x42, + 0xDC, 0x1E, 0x97, 0xD4, 0x10, 0x31, 0xF5, 0xFC, 0x64, 0xD5, 0x5D, 0x17, 0x52, 0xFF, 0x39, 0xB9, 0x89, 0xE7, 0x34, 0x08, + 0x5F, 0xA1, 0x15, 0x4E, 0x5F, 0xBD, 0xDE, 0xA1, 0x99, 0x7E, 0x45, 0xA5, 0xC2, 0x5D, 0xD5, 0xAB, 0x42, 0x30, 0x1A, 0x41, + 0xDE, 0xC2, 0xC7, 0xA4, 0x1A, 0x59, 0x3C, 0x2C, 0x5F, 0x91, 0x5C, 0x1E, 0xC7, 0x33, 0xCA, 0xC9, 0x83, 0xC9, 0x34, 0x0D, + 0x5B, 0x3B, 0x55, 0x86, 0xDF, 0xB4, 0xA9, 0x50, 0xB0, 0x9F, 0xA8, 0x44, 0xE1, 0x19, 0x67, 0x99, 0x31, 0x01, 0x9F, 0xFF, + 0x15, 0x15, 0xCE, 0x49, 0x9B, 0xB4, 0xBA, 0xCC, 0xE8, 0x88, 0xD2, 0x0E, 0xF8, 0x34, 0xDB, 0x75, 0x50, 0x14, 0xCC, 0x3E, + 0xB9, 0x35, 0x3E, 0xE6, 0x18, 0x50, 0xBE, 0xB8, 0x0A, 0x72, 0x61, 0xE5, 0x9C, 0xBA, 0x47, 0x2F, 0x1B, 0xB6, 0x7A, 0x8B, + 0xC9, 0x4C, 0xCA, 0x1D, 0xF2, 0x71, 0x14, 0x56, 0xAD, 0xF4, 0x0F, 0xBF, 0xFA, 0x1F, 0x4D, 0x0D, 0x00, 0x1B, 0xBF, 0xBC, + 0x35, 0xFF, 0xA9, 0xF1, 0x02, 0x9B, 0x03, 0x2E, 0xC8, 0x91, 0xF3, 0xCA, 0x90, 0x0D, 0x3A, 0x44, 0x9E, 0xD1, 0x16, 0x74, + 0xF2, 0x91, 0xB6, 0x3E, 0x36, 0x21, 0xBC, 0x26, 0xC5, 0xA3, 0xDE, 0x1E, 0x54, 0x70, 0xDE, 0x02, 0x7A, 0x99, 0xC1, 0x30, + 0xF5, 0xAF, 0x9D, 0xB1, 0xC8, 0xC8, 0xD1, 0x39, 0x9D, 0xEF, 0x91, 0xE8, 0x54, 0x5E, 0x1D, 0x75, 0xFC, 0x92, 0xD1, 0x1B, + 0x42, 0x12, 0x55, 0xB5, 0x01, 0x68, 0x75, 0xBF, 0x27, 0x5F, 0xD8, 0x16, 0x12, 0xAB, 0x65, 0x80, 0xC4, 0x10, 0xD4, 0x04, + 0x17, 0xC4, 0x31, 0xC1, 0xEE, 0xB4, 0xB6, 0x5D, 0x95, 0x8D, 0x78, 0xD7, 0x69, 0xA6, 0xC0, 0x26, 0xD7, 0xEA, 0x55, 0xC7, + 0xE4, 0x38, 0x81, 0x06, 0x3D, 0xE4, 0x2A, 0x01, 0xAD, 0xB7, 0x89, 0xE5, 0xD3, 0xE2, 0x91, 0x6C, 0x80, 0x52, 0x97, 0xD3, + 0xFC, 0x93, 0x33, 0x99, 0x2C, 0x96, 0x99, 0x33, 0x90, 0x6C, 0x09, 0x71, 0x56, 0x83, 0xBA, 0x0A, 0x34, 0x16, 0x08, 0xC2, + 0x98, 0x07, 0x8A, 0xBD, 0x5B, 0xEE, 0x12, 0xE5, 0xFC, 0xEA, 0xD2, 0xF6, 0x0F, 0xE4, 0x58, 0x3B, 0x4E, 0xA9, 0xF6, 0x7E, + 0x07, 0xF2, 0x27, 0x93, 0x75, 0x2B, 0x99, 0x8D, 0x48, 0xC2, 0x9F, 0xC3, 0x57, 0x87, 0x10, 0xCA, 0x7D, 0x4C, 0xD0, 0x68, + 0xB5, 0x7A, 0x54, 0x9B, 0xB2, 0x46, 0xFB, 0xCA, 0x6B, 0x89, 0xB8, 0xCF, 0xD9, 0xA4, 0x2E, 0xCE, 0x35, 0xAE, 0x82, 0x0F, + 0xE5, 0xEE, 0x48, 0x5B, 0x72, 0x33, 0x76, 0x8C, 0xDC, 0xA4, 0x0A, 0x44, 0x0E, 0x80, 0x4A, 0x3C, 0x5E, 0xED, 0x81, 0xFE, + 0x20, 0x9B, 0xE2, 0x8E, 0x20, 0xE2, 0xC0, 0x8A, 0x52, 0xC4, 0xBD, 0x44, 0x1C, 0x86, 0x4D, 0x47, 0xAC, 0xC8, 0x3A, 0x8D, + 0x5C, 0xA6, 0x94, 0x9C, 0x66, 0xC5, 0x93, 0xDD, 0x9E, 0xCC, 0x41, 0xF9, 0x1B, 0xF3, 0x4F, 0x8F, 0x20, 0xE0, 0x80, 0xEC, + 0xB8, 0x9F, 0xEF, 0xC2, 0x0B, 0xB9, 0x30, 0xEA, 0xE6, 0x35, 0x25, 0xB5, 0x27, 0x81, 0x27, 0x72, 0xE0, 0xFD, 0x5D, 0x12, + 0x5E, 0xDC, 0x64, 0xA2, 0xC9, 0xDC, 0xCE, 0xB3, 0x29, 0x6A, 0xE5, 0x87, 0xF3, 0x2F, 0x7C, 0xA4, 0xB2, 0x41, 0xAD, 0xC1, + 0x85, 0x4E, 0xD5, 0xB9, 0x6D, 0xFF, 0x74, 0x5D, 0x00, 0x15, 0xF3, 0xBF, 0xB5, 0x1C, 0x27, 0x46, 0xC4, 0xC3, 0xDB, 0x4E, + 0xD4, 0x86, 0x68, 0x3E, 0xCA, 0x6F, 0x9C, 0xE1, 0x97, 0x3C, 0x4E, 0x52, 0xB2, 0x7B, 0x8C, 0x64, 0x73, 0x85, 0xFD, 0x2B, + 0x2F, 0xD7, 0xE4, 0x34, 0xB5, 0xBD, 0xF6, 0x90, 0xE5, 0x01, 0x78, 0x74, 0xA3, 0x1E, 0x7D, 0xEC, 0x9A, 0xC3, 0xF5, 0x25, + 0x17, 0x3E, 0xD1, 0x81, 0x19, 0x94, 0xB7, 0x05, 0xD2, 0x2D, 0xA5, 0xFC, 0xD0, 0x72, 0x2D, 0xB5, 0xF6, 0xF7, 0x50, 0x03, + 0xEF, 0xD8, 0xC5, 0x0C, 0x0A, 0x99, 0x20, 0x02, 0x89, 0x1E, 0xB3, 0x73, 0x1D, 0x63, 0x0C, 0x28, 0xB8, 0x34, 0x23, 0x80, + 0x48, 0x03, 0x89, 0xEC, 0xD2, 0xFB, 0xF7, 0x0D, 0xD4, 0x88, 0x5E, 0x8D, 0x4C, 0xD4, 0xF2, 0x15, 0xFF, 0x2D, 0x27, 0xCB, + 0xBD, 0x81, 0x93, 0x0B, 0xDE, 0x04, 0x4F, 0x8C, 0x4F, 0x9B, 0xAF, 0x53, 0x62, 0xB8, 0x50, 0xDC, 0x9E, 0xD6, 0x57, 0xEC, + 0xA6, 0x04, 0xC4, 0x9C, 0x4C, 0x24, 0x92, 0xDD, 0x9C, 0x7B, 0xB9, 0xAA, 0xD6, 0xED, 0x9E, 0xAC, 0x7F, 0x3C, 0x16, 0xF4, + 0xF7, 0xD1, 0x91, 0x2E, 0x3E, 0x27, 0xAE, 0xC4, 0x1F, 0x69, 0xB4, 0xDF, 0x9C, 0xBB, 0x1E, 0xBE, 0xA3, 0x50, 0x5D, 0x16, + 0xDE, 0x42, 0x54, 0xE7, 0xA8, 0x34, 0x9F, 0x4D, 0xBB, 0x3F, 0x75, 0x09, 0x63, 0x9F, 0xF3, 0xED, 0xAE, 0xF8, 0x7A, 0x9C, + 0x4E, 0x39, 0xE7, 0xB8, 0x1C, 0xB9, 0x07, 0x79, 0xE6, 0x02, 0x40, 0x38, 0x25, 0xF5, 0x80, 0xFC, 0x04, 0x8B, 0x40, 0x43, + 0xF1, 0xD6, 0x4B, 0x03, 0x46, 0xB3, 0x07, 0xD7, 0xD4, 0xCD, 0x32, 0xA0, 0xD5, 0xAE, 0x48, 0xE5, 0xCC, 0xAA, 0x00, 0x1F, + 0x3D, 0x14, 0x08, 0x56, 0x12, 0xBE, 0x5F, 0x3D, 0x6B, 0x46, 0xFE, 0x77, 0x46, 0xBD, 0xE0, 0xDD, 0x2C, 0xB9, 0xC3, 0x99, + 0x3B, 0x06, 0xAD, 0x73, 0xEA, 0x92, 0x42, 0x28, 0x7A, 0x67, 0x8A, 0x0A, 0xB9, 0xD6, 0xE1, 0x57, 0x92, 0xDC, 0x9F, 0x20, + 0x80, 0xD0, 0x53, 0x36, 0xB1, 0x8F, 0x36, 0xB8, 0xAB, 0x17, 0x83, 0x9E, 0x54, 0xCF, 0x48, 0xA9, 0x83, 0x9E, 0xE0, 0xAF, + 0x60, 0x33, 0x98, 0x81, 0x28, 0x48, 0xA6, 0x72, 0xBA, 0x76, 0xE0, 0x23, 0x3D, 0x5D, 0x92, 0x4D, 0x2D, 0x7D, 0x37, 0xAC, + 0xC1, 0x0C, 0xBC, 0x16, 0xE8, 0x97, 0x49, 0xD5, 0xE4, 0x9E, 0x36, 0xD1, 0x9B, 0x3F, 0xA2, 0x56, 0x62, 0x38, 0x19, 0x84, + 0x55, 0xC7, 0x02, 0xFB, 0x70, 0x83, 0xD8, 0x13, 0x1E, 0x83, 0x01, 0xAC, 0x2F, 0xD1, 0xEA, 0x08, 0x2E, 0xC7, 0x30, 0xA8, + 0xDD, 0xA6, 0x31, 0xAC, 0x11, 0x86, 0xCA, 0x94, 0x81, 0x2A, 0xA5, 0xDE, 0x7D, 0x32, 0xD9, 0x35, 0x63, 0x4E, 0x63, 0x72, + 0xF8, 0x4A, 0xD3, 0xD8, 0x56, 0xEE, 0x37, 0x57, 0x7B, 0x0F, 0xAF, 0x7B, 0x04, 0xAD, 0x1A, 0xE4, 0x99, 0xB0, 0xCE, 0xC0, + 0xE8, 0xD0, 0x2D, 0xD0, 0xF8, 0x97, 0x9B, 0xDB, 0x35, 0x05, 0x9D, 0x44, 0x69, 0x2C, 0xFB, 0x16, 0xDF, 0x11, 0x85, 0x1F, + 0x20, 0x67, 0xFC, 0xA1, 0x2A, 0xA9, 0x0A, 0x15, 0x65, 0xD0, 0x23, 0x46, 0x2D, 0xB8, 0xAF, 0x58, 0x8F, 0xFC, 0x83, 0xB8, + 0x54, 0x95, 0x1C, 0x4D, 0xED, 0x22, 0x87, 0xFA, 0x6B, 0x71, 0xA4, 0x7C, 0xA8, 0x6A, 0xDA, 0x18, 0x43, 0x7E, 0x40, 0x3D, + 0x8B, 0x29, 0x8D, 0x07, 0xE5, 0xE9, 0x7C, 0x44, 0xB0, 0x9E, 0x3E, 0x30, 0xDF, 0xED, 0x11, 0x7B, 0x36, 0x9A, 0xEE, 0x60, + 0x64, 0x75, 0xAC, 0x5B, 0x99, 0x0A, 0xD8, 0x35, 0x62, 0x0E, 0xF2, 0xAC, 0x52, 0x11, 0xF0, 0x22, 0x2D, 0x59, 0x31, 0xCB, + 0xEC, 0x2D, 0x5B, 0x20, 0xA0, 0x71, 0x32, 0xF7, 0xD8, 0xA3, 0xDA, 0x49, 0x80, 0x1F, 0x41, 0x5B, 0x0D, 0x33, 0x73, 0x31, + 0x40, 0xB2, 0xDB, 0xB8, 0x5A, 0x42, 0x9D, 0x92, 0xBE, 0x48, 0x26, 0xFB, 0xD5, 0xDE, 0x22, 0x2D, 0x03, 0xA8, 0x54, 0xDA, + 0x50, 0xC0, 0xDB, 0x79, 0xBB, 0xA9, 0x9A, 0xDB, 0x93, 0xD5, 0x67, 0xC3, 0x17, 0x46, 0x1A, 0xDA, 0x01, 0x41, 0x9C, 0x01, + 0x08, 0xC8, 0xD8, 0x45, 0x0F, 0xDA, 0xF8, 0x9A, 0x73, 0x4B, 0x93, 0xDF, 0xD4, 0x82, 0x7A, 0xBB, 0x17, 0xCA, 0x85, 0x16, + 0xD0, 0xFD, 0x6B, 0xFC, 0x9D, 0x55, 0x98, 0xA7, 0x58, 0xA4, 0x25, 0xD6, 0x1A, 0x58, 0x4A, 0x87, 0x9B, 0xC6, 0x52, 0x77, + 0xC1, 0x1B, 0xBC, 0xBD, 0x4C, 0x97, 0x04, 0xCE, 0x28, 0x17, 0xC6, 0x9D, 0xD9, 0x87, 0x57, 0xE8, 0x5E, 0xFC, 0x99, 0x6F, + 0x41, 0x9B, 0x1A, 0x5E, 0x7B, 0x14, 0x0E, 0xCF, 0x03, 0xD8, 0x55, 0x0B, 0x5F, 0x58, 0x14, 0x7D, 0xB0, 0x99, 0x4E, 0x67, + 0x4D, 0xDB, 0xA9, 0x90, 0xD6, 0xA5, 0xD0, 0xF9, 0x15, 0x78, 0x1E, 0x9F, 0x36, 0x7A, 0x4D, 0xB9, 0x4E, 0x16, 0xA7, 0x42, + 0x10, 0xE8, 0x98, 0x89, 0x5D, 0xBA, 0xB8, 0x75, 0xB7, 0x91, 0x50, 0x45, 0x83, 0x2F, 0xA8, 0xD5, 0x19, 0x5C, 0xFC, 0xDC, + 0x4C, 0x84, 0x9D, 0x4F, 0x0D, 0x37, 0x7E, 0xDF, 0x4F, 0x11, 0x98, 0xC0, 0xFB, 0x33, 0x98, 0xA9, 0xAC, 0xB5, 0x90, 0x5E, + 0x84, 0x93, 0x0F, 0xDE, 0xA2, 0x0D, 0x81, 0xD5, 0x11, 0xEF, 0xB0, 0x5D, 0x84, 0xF2, 0x9C, 0x59, 0xD0, 0x01, 0xE8, 0x8B, + 0x1C, 0x59, 0x4F, 0xBA, 0xC8, 0x41, 0x37, 0xF1, 0x78, 0x0D, 0xD8, 0x74, 0xEB, 0xE2, 0x04, 0x26, 0x2B, 0xE8, 0x0D, 0x79, + 0x81, 0xBD, 0x97, 0x55, 0xCF, 0x30, 0x0F, 0xE7, 0x65, 0x3B, 0xAF, 0x3A, 0xE0, 0x6E, 0xEC, 0x54, 0xAE, 0x7A, 0x47, 0x3B, + 0x6F, 0x53, 0xEC, 0xCB, 0xFF, 0xD3, 0x68, 0x50, 0x61, 0x6D, 0x1A, 0x03, 0x56, 0x36, 0x57, 0x2A, 0x64, 0x25, 0xF7, 0x2E, + 0x36, 0x08, 0x69, 0xDB, 0x5E, 0x8E, 0xB9, 0xDA, 0x55, 0xB8, 0xE8, 0xC6, 0x78, 0xD3, 0xEC, 0x31, 0x75, 0x3B, 0x48, 0x99, + 0xB5, 0x86, 0x46, 0x97, 0x74, 0xED, 0xB2, 0x8A, 0xDE, 0x78, 0x27, 0x62, 0x95, 0xAD, 0x40, 0x0D, 0xC6, 0xC8, 0xFC, 0x08, + 0x35, 0xC5, 0x38, 0xCB, 0x23, 0xC4, 0x99, 0x45, 0x61, 0xE4, 0xF1, 0xA8, 0x33, 0xCA, 0x31, 0x96, 0x2C, 0x67, 0x46, 0x09, + 0x72, 0x1B, 0x2D, 0x35, 0xD4, 0x50, 0xCA, 0xDB, 0x3B, 0xF4, 0x87, 0x4B, 0x3E, 0x36, 0x31, 0xF9, 0x7C, 0x2C, 0x31, 0x0E, + 0xF5, 0xF9, 0xC9, 0x22, 0xE9, 0x37, 0xB2, 0x0A, 0x4C, 0xA5, 0xFE, 0x45, 0xF8, 0x75, 0x78, 0x31, 0x69, 0xFC, 0x32, 0xD6, + 0x9F, 0xF6, 0x02, 0x8E, 0x55, 0xA6, 0xEE, 0xAF, 0x44, 0x10, 0xBB, 0x26, 0x7D, 0x05, 0x09, 0xD1, 0x37, 0xB1, 0xA1, 0x2F, + 0x7B, 0xF8, 0x94, 0x2B, 0x72, 0x74, 0xBC, 0x24, 0xED, 0x3E, 0x42, 0x7C, 0xCB, 0xAB, 0x2B, 0x4C, 0x8E, 0x4A, 0xB9, 0xD9, + 0x71, 0x85, 0x9A, 0x2C, 0x5D, 0x52, 0xB2, 0x9B, 0xDF, 0x91, 0xEA, 0x42, 0xBF, 0x43, 0xAA, 0xAE, 0x7E, 0x56, 0xD2, 0x8E, + 0xF0, 0xA2, 0x03, 0xB8, 0xEE, 0x32, 0xE9, 0x45, 0x7D, 0x78, 0xD6, 0x62, 0x3A, 0x9F, 0x9B, 0xCD, 0x97, 0xCA, 0xA7, 0xF8, + 0x6F, 0xF1, 0x21, 0x40, 0xA6, 0xBB, 0xDD, 0xA6, 0xAE, 0xD4, 0xD3, 0x0F, 0xDF, 0xA0, 0x13, 0x19, 0x38, 0x8D, 0x6C, 0x82, + 0xD7, 0xAD, 0x95, 0x26, 0x5F, 0x99, 0xFF, 0x86, 0x4F, 0xF0, 0x4F, 0xAA, 0xC1, 0x6F, 0x60, 0x58, 0x50, 0x5B, 0x59, 0xE0, + 0x4D, 0xB2, 0x92, 0x52, 0xEB, 0x6C, 0x77, 0x8F, 0x8E, 0x95, 0xBC, 0x5E, 0xBF, 0xBC, 0x7E, 0xA0, 0xA2, 0xB8, 0x65, 0x83, + 0x84, 0xDE, 0xF5, 0x52, 0x39, 0x59, 0xF9, 0xA5, 0x9F, 0xB8, 0xD2, 0xE0, 0x87, 0x10, 0xB7, 0x95, 0x06, 0x1E, 0x67, 0xAC, + 0xE3, 0x78, 0x2D, 0xA4, 0xEA, 0xA2, 0xBF, 0xF5, 0x59, 0x9D, 0xDA, 0x73, 0x4A, 0x1B, 0x78, 0xE5, 0xC7, 0x5C, 0x4C, 0x74, + 0x7E, 0xFE, 0xAC, 0x3A, 0xF0, 0xD4, 0x92, 0xD1, 0x96, 0x2A, 0x75, 0x80, 0xC4, 0xD3, 0x54, 0xDB, 0xF2, 0xA4, 0x52, 0xEE, + 0x56, 0xC7, 0x45, 0xB4, 0xD0, 0x65, 0x74, 0x01, 0x64, 0xDE, 0x71, 0x63, 0x9D, 0xB1, 0xCE, 0x63, 0x7B, 0x34, 0x59, 0xB5, + 0x4C, 0x1A, 0x75, 0x54, 0x44, 0xD1, 0x15, 0xDF, 0x70, 0x26, 0x47, 0x74, 0x2A, 0x83, 0xEA, 0xFE, 0xBC, 0xAE, 0xD6, 0x56, + 0xB0, 0x23, 0x90, 0x76, 0x40, 0xFE, 0x08, 0x3E, 0x24, 0x3D, 0x96, 0x61, 0xD4, 0xEA, 0x3A, 0x41, 0x8C, 0x7A, 0x64, 0x66, + 0xA9, 0xE8, 0x3D, 0x0F, 0xC7, 0xEC, 0x37, 0xFC, 0x82, 0x1B, 0x7C, 0xD8, 0xCE, 0x5B, 0x14, 0x56, 0x5D, 0xB8, 0xFB, 0xDF, + 0xD6, 0x92, 0x7B, 0x61, 0x54, 0x18, 0xA8, 0x41, 0xEB, 0x71, 0x18, 0x96, 0x8A, 0x5D, 0x45, 0x7E, 0xF6, 0x7F, 0xB0, 0xF3, + 0xD5, 0xF8, 0x7E, 0xA7, 0x0D, 0x9C, 0xCC, 0x06, 0xAA, 0x33, 0x54, 0x29, 0x19, 0x32, 0x4A, 0xBC, 0xC8, 0xD8, 0x3C, 0x18, + 0xED, 0x95, 0xA7, 0x01, 0x7B, 0x76, 0xC6, 0x63, 0x32, 0xAD, 0xD9, 0x7F, 0xC8, 0x11, 0x0F, 0x69, 0xEF, 0x86, 0x37, 0xA3, + 0x15, 0xBC, 0xBA, 0x9C, 0x46, 0xEC, 0xD7, 0xE6, 0x44, 0x62, 0xE8, 0x19, 0x6D, 0x97, 0xCD, 0xFF, 0xFF, 0xFF, 0x3A, 0xF3, + 0x78, 0xAF, 0x27, 0xFD, 0x43, 0x3B, 0x08, 0xD3, 0x32, 0x02, 0x90, 0x24, 0x50, 0x60, 0x99, 0xEC, 0xCB, 0xFA, 0x30, 0xFB, + 0x6E, 0x28, 0xC1, 0x07, 0x7E, 0x48, 0x98, 0x34, 0x51, 0x61, 0x12, 0xF2, 0xBC, 0xAD, 0xBF, 0x63, 0x27, 0x32, 0x48, 0xAE, + 0xE1, 0x00, 0x91, 0x25, 0xD0, 0x62, 0x11, 0x2A, 0xD2, 0x96, 0x52, 0x22, 0x95, 0x09, 0x3F, 0x85, 0xB3, 0x01, 0x99, 0x35, + 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, 0x52, 0x64, 0x48, 0x50, + 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, 0x82, 0x06, 0xC1, 0x45, + 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, 0x93, 0x27, 0x59, 0x71, + 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0xCF, 0x8C, 0x43, 0x4A, 0xF7, 0x4B, 0xED, 0xA1, 0x4B, 0xA7, 0x69, 0x88, 0x92, 0x2C, + 0x58, 0x68, 0x2D, 0x35, 0xD9, 0x58, 0x8B, 0x5B, 0xF8, 0xDF, 0x1E, 0xDA, 0x6D, 0xFC, 0x9A, 0x3C, 0x59, 0x69, 0xA4, 0x30, + 0x5C, 0x9B, 0xA3, 0x9F, 0x18, 0x20, 0x73, 0x37, 0xC5, 0xC1, 0x93, 0x2D, 0xD8, 0x6A, 0xB0, 0x5B, 0x28, 0xF6, 0x74, 0x6F, + 0x4F, 0xF4, 0x4D, 0x03, 0xAB, 0xB0, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, 0x1A, 0x2C, 0x52, 0x68, + 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, 0x4B, 0x4D, 0xDA, 0x7C, + 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, 0xDA, 0x6E, 0x4B, 0x59, + 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x5E, 0xAE, 0x83, 0x75, 0x84, 0x84, + 0x30, 0x30, 0x4A, 0xDB, 0x53, 0x42, 0x94, 0xA4, 0x70, 0x70, 0xB7, 0x72, 0x8D, 0xEC, 0x8C, 0x94, 0x31, 0x31, 0x64, 0x32, + 0xB5, 0x72, 0x9C, 0xB4, 0x71, 0x71, 0x5F, 0x50, 0x03, 0x77, 0x85, 0x85, 0xB0, 0x32, 0xAD, 0x23, 0x34, 0xE9, 0x95, 0xA5, + 0xF0, 0x72, 0x75, 0xB6, 0x54, 0x1C, 0x8D, 0x95, 0xB1, 0x33, 0x25, 0x33, 0x35, 0x07, 0x9D, 0xB5, 0xF1, 0x73, 0x44, 0xC0, + 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, 0x23, 0x15, 0xCC, 0xD4, + 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, 0xB2, 0x36, 0x55, 0xE1, + 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, 0xE3, 0x57, 0xDD, 0xF5, + 0xF3, 0x77, 0xB2, 0xF7, 0x8B, 0xC3, 0x86, 0x8C, 0x38, 0x38, 0x6E, 0x2A, 0xBC, 0x30, 0x96, 0xAC, 0x78, 0x78, 0x8C, 0x1C, + 0x7E, 0x4D, 0x8E, 0x9C, 0x39, 0x39, 0x24, 0x47, 0x6F, 0xA3, 0x9E, 0xBC, 0x79, 0x79, 0x27, 0x74, 0xC0, 0xA1, 0x87, 0x8D, + 0xB8, 0x3A, 0x2F, 0x1B, 0xE0, 0xFA, 0x97, 0xAD, 0xF8, 0x7A, 0xB0, 0x6B, 0xE9, 0x1D, 0x8F, 0x9D, 0xB9, 0x3B, 0x1C, 0x9D, + 0x39, 0xCA, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, 0x6A, 0x5C, 0xD6, 0xEC, + 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, 0x7B, 0x7D, 0x47, 0xC9, + 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, 0xAB, 0x1F, 0xCF, 0xDD, + 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x08, 0x60, 0xF0, 0xFA, 0x30, 0x22, 0x14, 0xA0, 0x34, 0xA6, + 0x4C, 0xD8, 0xB0, 0x26, 0x54, 0xE0, 0x01, 0x60, 0xBE, 0x9E, 0xA8, 0x16, 0x15, 0xA1, 0x06, 0xEA, 0x25, 0xE1, 0xB8, 0x36, + 0x55, 0xE1, 0x96, 0xDB, 0x82, 0x29, 0xA1, 0x07, 0x94, 0xA2, 0xEA, 0x14, 0xBB, 0xCB, 0xB1, 0x27, 0xD4, 0xE2, 0x41, 0x71, + 0x7A, 0x8D, 0xA9, 0x17, 0x95, 0xA3, 0x46, 0x41, 0xAF, 0xB9, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, 0x06, 0x84, 0xE0, 0x46, + 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, 0x17, 0xA5, 0x78, 0x72, + 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, 0xC6, 0xC6, 0xF1, 0x67, + 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, 0xD7, 0xE7, 0x1A, 0xF4, + 0x0A, 0xE8, 0xA2, 0x0E, 0x1C, 0xA8, 0x49, 0xAE, 0x07, 0x8A, 0xB2, 0x2E, 0x5C, 0xE8, 0x39, 0x01, 0x31, 0x1D, 0xAA, 0x1E, + 0x1D, 0xA9, 0x21, 0x3F, 0xAC, 0xCF, 0xBA, 0x3E, 0x5D, 0xE9, 0x39, 0x14, 0xF4, 0x5E, 0xA3, 0x0F, 0x9C, 0xAA, 0x8C, 0x77, + 0xE8, 0x61, 0xB3, 0x2F, 0xDC, 0xEA, 0xBA, 0x99, 0x0D, 0x2A, 0xAB, 0x1F, 0x9D, 0xAB, 0x98, 0x7E, 0x6E, 0x89, 0xBB, 0x3F, + 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, 0x5E, 0xEC, 0x6A, 0x5A, + 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, 0x8E, 0x8E, 0xE3, 0x4F, + 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, 0x9F, 0xAF, 0x7B, 0x7B, + 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x04, 0xAF, 0x87, 0xD1, 0xA4, 0x86, 0x34, 0xB0, 0x13, 0x9B, 0x62, 0x7A, 0xB4, 0xA6, + 0x74, 0xF0, 0xEC, 0x63, 0xDF, 0x10, 0xAC, 0x96, 0x35, 0xB1, 0x6C, 0xA9, 0x19, 0x45, 0xBC, 0xB6, 0x75, 0xF1, 0x86, 0x33, + 0x78, 0x31, 0xA5, 0x87, 0xB4, 0xB2, 0xF5, 0xBC, 0xCE, 0x06, 0xB5, 0xA7, 0xF4, 0xF2, 0x09, 0x6C, 0x44, 0x40, 0xAD, 0x97, + 0xB5, 0xB3, 0xAE, 0x8D, 0x95, 0x26, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, 0x36, 0xB4, 0x74, 0xE2, + 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, 0x67, 0xD5, 0xFC, 0xF6, + 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, 0xF6, 0xF6, 0x6D, 0xD3, + 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0xDD, 0xF5, 0x1F, 0x78, 0xA6, 0x8E, + 0x3C, 0xB8, 0x21, 0x2E, 0x07, 0xC4, 0xB6, 0xAE, 0x7C, 0xF8, 0xEA, 0x50, 0x96, 0x36, 0xAE, 0x9E, 0x3D, 0xB9, 0x6A, 0x84, + 0x4F, 0x9B, 0xBE, 0xBE, 0x7D, 0xF9, 0x8C, 0xCC, 0xA2, 0x46, 0xA7, 0x8F, 0xBC, 0xBA, 0x0D, 0x40, 0x5F, 0x2F, 0xB7, 0xAF, + 0xFC, 0xFA, 0xFD, 0x77, 0x41, 0xE0, 0xAF, 0x9F, 0xBD, 0xBB, 0xBB, 0xCB, 0xC9, 0x40, 0xBF, 0xBF, 0xFD, 0xFB, 0x66, 0xCA, + 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, 0x2F, 0x9D, 0xEE, 0xDE, + 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, 0xBE, 0xBE, 0x77, 0xEB, + 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, 0xEF, 0xDF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x10, 0x20, 0x10, 0x20, 0x40, 0x40, 0x90, 0x24, 0x50, 0x60, 0x08, 0x10, + 0x01, 0x01, 0x88, 0x14, 0x11, 0x21, 0x18, 0x30, 0x41, 0x41, 0x98, 0x34, 0x51, 0x61, 0x01, 0x01, 0x80, 0x02, 0x81, 0x05, + 0x90, 0x22, 0x11, 0x21, 0xC0, 0x42, 0x91, 0x25, 0xD0, 0x62, 0x09, 0x11, 0x81, 0x03, 0x89, 0x15, 0x91, 0x23, 0x19, 0x31, + 0xC1, 0x43, 0x99, 0x35, 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, + 0x52, 0x64, 0x48, 0x50, 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, + 0x82, 0x06, 0xC1, 0x45, 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, + 0x93, 0x27, 0x59, 0x71, 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0x02, 0x08, 0x08, 0x08, 0x82, 0x0C, 0x18, 0x28, 0x12, 0x28, + 0x48, 0x48, 0x92, 0x2C, 0x58, 0x68, 0x0A, 0x18, 0x09, 0x09, 0x8A, 0x1C, 0x19, 0x29, 0x1A, 0x38, 0x49, 0x49, 0x9A, 0x3C, + 0x59, 0x69, 0x03, 0x09, 0x88, 0x0A, 0x83, 0x0D, 0x98, 0x2A, 0x13, 0x29, 0xC8, 0x4A, 0x93, 0x2D, 0xD8, 0x6A, 0x0B, 0x19, + 0x89, 0x0B, 0x8B, 0x1D, 0x99, 0x2B, 0x1B, 0x39, 0xC9, 0x4B, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, + 0x1A, 0x2C, 0x52, 0x68, 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, + 0x4B, 0x4D, 0xDA, 0x7C, 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, + 0xDA, 0x6E, 0x4B, 0x59, 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, + 0x20, 0x10, 0x84, 0x84, 0x30, 0x30, 0x14, 0xA0, 0x60, 0x50, 0x94, 0xA4, 0x70, 0x70, 0x0C, 0x90, 0x21, 0x11, 0x8C, 0x94, + 0x31, 0x31, 0x1C, 0xB0, 0x61, 0x51, 0x9C, 0xB4, 0x71, 0x71, 0x05, 0x81, 0xA0, 0x12, 0x85, 0x85, 0xB0, 0x32, 0x15, 0xA1, + 0xE0, 0x52, 0x95, 0xA5, 0xF0, 0x72, 0x0D, 0x91, 0xA1, 0x13, 0x8D, 0x95, 0xB1, 0x33, 0x1D, 0xB1, 0xE1, 0x53, 0x9D, 0xB5, + 0xF1, 0x73, 0x44, 0xC0, 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, + 0x23, 0x15, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, + 0xB2, 0x36, 0x55, 0xE1, 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, + 0xE3, 0x57, 0xDD, 0xF5, 0xF3, 0x77, 0x06, 0x88, 0x28, 0x18, 0x86, 0x8C, 0x38, 0x38, 0x16, 0xA8, 0x68, 0x58, 0x96, 0xAC, + 0x78, 0x78, 0x0E, 0x98, 0x29, 0x19, 0x8E, 0x9C, 0x39, 0x39, 0x1E, 0xB8, 0x69, 0x59, 0x9E, 0xBC, 0x79, 0x79, 0x07, 0x89, + 0xA8, 0x1A, 0x87, 0x8D, 0xB8, 0x3A, 0x17, 0xA9, 0xE8, 0x5A, 0x97, 0xAD, 0xF8, 0x7A, 0x0F, 0x99, 0xA9, 0x1B, 0x8F, 0x9D, + 0xB9, 0x3B, 0x1F, 0xB9, 0xE9, 0x5B, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, + 0x6A, 0x5C, 0xD6, 0xEC, 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, + 0x7B, 0x7D, 0x47, 0xC9, 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, + 0xAB, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x20, 0x02, 0x04, 0x80, 0xA0, 0x06, + 0x14, 0xA0, 0x30, 0x22, 0x44, 0xC0, 0xB0, 0x26, 0x54, 0xE0, 0x28, 0x12, 0x05, 0x81, 0xA8, 0x16, 0x15, 0xA1, 0x38, 0x32, + 0x45, 0xC1, 0xB8, 0x36, 0x55, 0xE1, 0x21, 0x03, 0x84, 0x82, 0xA1, 0x07, 0x94, 0xA2, 0x31, 0x23, 0xC4, 0xC2, 0xB1, 0x27, + 0xD4, 0xE2, 0x29, 0x13, 0x85, 0x83, 0xA9, 0x17, 0x95, 0xA3, 0x39, 0x33, 0xC5, 0xC3, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, + 0x06, 0x84, 0xE0, 0x46, 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, + 0x17, 0xA5, 0x78, 0x72, 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, + 0xC6, 0xC6, 0xF1, 0x67, 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, + 0xD7, 0xE7, 0x22, 0x0A, 0x0C, 0x88, 0xA2, 0x0E, 0x1C, 0xA8, 0x32, 0x2A, 0x4C, 0xC8, 0xB2, 0x2E, 0x5C, 0xE8, 0x2A, 0x1A, + 0x0D, 0x89, 0xAA, 0x1E, 0x1D, 0xA9, 0x3A, 0x3A, 0x4D, 0xC9, 0xBA, 0x3E, 0x5D, 0xE9, 0x23, 0x0B, 0x8C, 0x8A, 0xA3, 0x0F, + 0x9C, 0xAA, 0x33, 0x2B, 0xCC, 0xCA, 0xB3, 0x2F, 0xDC, 0xEA, 0x2B, 0x1B, 0x8D, 0x8B, 0xAB, 0x1F, 0x9D, 0xAB, 0x3B, 0x3B, + 0xCD, 0xCB, 0xBB, 0x3F, 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, + 0x5E, 0xEC, 0x6A, 0x5A, 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, + 0x8E, 0x8E, 0xE3, 0x4F, 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, + 0x9F, 0xAF, 0x7B, 0x7B, 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x24, 0x82, 0x24, 0x90, 0xA4, 0x86, 0x34, 0xB0, 0x34, 0xA2, + 0x64, 0xD0, 0xB4, 0xA6, 0x74, 0xF0, 0x2C, 0x92, 0x25, 0x91, 0xAC, 0x96, 0x35, 0xB1, 0x3C, 0xB2, 0x65, 0xD1, 0xBC, 0xB6, + 0x75, 0xF1, 0x25, 0x83, 0xA4, 0x92, 0xA5, 0x87, 0xB4, 0xB2, 0x35, 0xA3, 0xE4, 0xD2, 0xB5, 0xA7, 0xF4, 0xF2, 0x2D, 0x93, + 0xA5, 0x93, 0xAD, 0x97, 0xB5, 0xB3, 0x3D, 0xB3, 0xE5, 0xD3, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, + 0x36, 0xB4, 0x74, 0xE2, 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, + 0x67, 0xD5, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, + 0xF6, 0xF6, 0x6D, 0xD3, 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x8A, + 0x2C, 0x98, 0xA6, 0x8E, 0x3C, 0xB8, 0x36, 0xAA, 0x6C, 0xD8, 0xB6, 0xAE, 0x7C, 0xF8, 0x2E, 0x9A, 0x2D, 0x99, 0xAE, 0x9E, + 0x3D, 0xB9, 0x3E, 0xBA, 0x6D, 0xD9, 0xBE, 0xBE, 0x7D, 0xF9, 0x27, 0x8B, 0xAC, 0x9A, 0xA7, 0x8F, 0xBC, 0xBA, 0x37, 0xAB, + 0xEC, 0xDA, 0xB7, 0xAF, 0xFC, 0xFA, 0x2F, 0x9B, 0xAD, 0x9B, 0xAF, 0x9F, 0xBD, 0xBB, 0x3F, 0xBB, 0xED, 0xDB, 0xBF, 0xBF, + 0xFD, 0xFB, 0x66, 0xCA, 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, + 0x2F, 0x9D, 0xEE, 0xDE, 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, + 0xBE, 0xBE, 0x77, 0xEB, 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, + 0xEF, 0xDF, 0xFF, 0xFF, 0x68, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x07, 0xFF, 0x80, 0x00, 0x55, 0x40, 0xA9, 0x57, 0x94, 0x3C, 0x0F, 0x02, 0x2B, 0xFA, 0xCA, 0x0A, 0xF3, 0x2E, 0x88, 0x98, + 0x01, 0x41, 0x67, 0x7F, 0xC6, 0xCC, 0x46, 0x33, 0xBE, 0x01, 0x60, 0xB0, 0x58, 0x10, 0x01, 0x80, 0x05, 0x42, 0x28, 0x56, + 0x1C, 0x7E, 0x0A, 0xD0, 0x58, 0x42, 0x83, 0x57, 0xE3, 0x92, 0x09, 0x95, 0x22, 0x66, 0xA9, 0xAB, 0x14, 0xA2, 0x19, 0x7A, + 0xC5, 0x63, 0x31, 0x0A, 0xD7, 0xD8, 0xE8, 0xE2, 0xDD, 0x5B, 0xFE, 0xE0, 0x73, 0x04, 0x80, 0x23, 0xB9, 0xE9, 0x10, 0xE1, + 0x5D, 0x65, 0xE8, 0x43, 0x2D, 0x61, 0x96, 0xF0, 0x1B, 0x88, 0x74, 0x97, 0x45, 0xD6, 0xAA, 0x70, 0x4B, 0x0B, 0xE9, 0xF2, + 0x4A, 0x85, 0x99, 0x41, 0x1B, 0x99, 0x18, 0x41, 0x67, 0x06, 0xE9, 0x4D, 0x3B, 0xF6, 0x92, 0x53, 0xFC, 0x87, 0x05, 0xD0, + 0x95, 0xA5, 0x1F, 0x6E, 0xE5, 0x6B, 0x19, 0xE5, 0x62, 0x6F, 0x92, 0xAC, 0x2E, 0x48, 0xDD, 0x44, 0x67, 0x08, 0x91, 0x5A, + 0xC6, 0x2D, 0xF7, 0xAE, 0x51, 0x05, 0x0A, 0x18, 0x09, 0x49, 0x86, 0x62, 0xB8, 0xA3, 0x12, 0x3D, 0xAE, 0x4D, 0xFA, 0xFC, + 0x95, 0xE2, 0xDA, 0x97, 0xAE, 0x49, 0x43, 0x75, 0x2D, 0x2C, 0x6A, 0x5B, 0x46, 0x2F, 0xAB, 0x7D, 0xDC, 0x65, 0xC9, 0x49, + 0x89, 0x0B, 0x70, 0xFF, 0x35, 0xA0, 0x1F, 0xDF, 0xD9, 0xB5, 0x99, 0xDF, 0x5B, 0x61, 0xAA, 0xEA, 0xAE, 0x8B, 0x4A, 0x3F, + 0x4E, 0x4E, 0x2D, 0x1B, 0x59, 0x4D, 0x56, 0x9D, 0x7C, 0x4C, 0xE2, 0xFA, 0xD4, 0x82, 0x88, 0x17, 0x78, 0x29, 0x64, 0x75, + 0x23, 0xDD, 0x5B, 0x6E, 0x33, 0x5D, 0x97, 0x6F, 0x64, 0x6D, 0x07, 0x9D, 0xE4, 0x6C, 0xEF, 0x6D, 0x43, 0x21, 0xED, 0x71, + 0xB1, 0x61, 0x8B, 0x59, 0xDF, 0xD1, 0xAA, 0x9D, 0x9F, 0x03, 0xA4, 0x0B, 0xE5, 0x90, 0x24, 0x0F, 0xF5, 0xB0, 0x04, 0x80, + 0x78, 0xF8, 0xDE, 0x80, 0x93, 0x36, 0x91, 0xA1, 0x64, 0xD0, 0x21, 0x62, 0x80, 0x76, 0xDE, 0xB0, 0x26, 0xE9, 0xEC, 0xD0, + 0x4D, 0x3E, 0x3C, 0x32, 0x5E, 0xB5, 0xE4, 0x36, 0x78, 0xB1, 0x4F, 0x28, 0x82, 0x11, 0x8D, 0xC9, 0xF2, 0x3D, 0x14, 0x21, + 0xC0, 0x5A, 0x99, 0xB0, 0x93, 0xB2, 0x02, 0x1D, 0x24, 0xE6, 0xED, 0xD1, 0xC5, 0xBE, 0x27, 0x4D, 0xE9, 0x35, 0xE5, 0x37, + 0xF8, 0xD3, 0x97, 0xD0, 0x3A, 0xCE, 0xE8, 0x23, 0x4D, 0x14, 0xD3, 0x10, 0x52, 0xF5, 0xAB, 0x60, 0x3E, 0x47, 0x12, 0xA1, + 0x27, 0x71, 0x1C, 0x3C, 0x1F, 0x78, 0x9C, 0x94, 0x07, 0xA2, 0xF0, 0x13, 0x9A, 0x9F, 0xC1, 0x6C, 0x8F, 0x56, 0x05, 0x09, + 0xAE, 0xC2, 0x01, 0x0B, 0x47, 0xA9, 0xDD, 0xE1, 0x7B, 0xC9, 0x52, 0xD5, 0x29, 0xEE, 0x32, 0xEE, 0xA3, 0x75, 0x59, 0xF5, + 0x63, 0xD5, 0xCD, 0x92, 0xF7, 0x5B, 0xC6, 0x71, 0xB2, 0x1E, 0xFE, 0x61, 0x18, 0x87, 0x0E, 0x12, 0xC4, 0xA7, 0xCC, 0xB1, + 0xDB, 0x7E, 0x8E, 0x12, 0x08, 0xAB, 0xAE, 0x18, 0x31, 0x67, 0x1B, 0x68, 0x37, 0x86, 0x54, 0x34, 0xAD, 0x5A, 0xAC, 0x94, + 0x09, 0x01, 0xDC, 0xCF, 0x47, 0xE1, 0x5D, 0x14, 0xCA, 0xF7, 0x9B, 0xBD, 0x5B, 0x3A, 0x56, 0x66, 0x48, 0xD4, 0xD0, 0xBD, + 0xCA, 0x3B, 0x25, 0x3E, 0x45, 0x52, 0x38, 0x19, 0x29, 0x18, 0x40, 0xE4, 0x05, 0x9C, 0x99, 0xA9, 0xC7, 0x5E, 0x68, 0x49, + 0xE7, 0xFA, 0x2A, 0x68, 0x36, 0x7C, 0x90, 0xCC, 0xDE, 0x46, 0x71, 0x9E, 0x9A, 0x26, 0x49, 0xC9, 0x41, 0x42, 0x1E, 0x78, + 0xF1, 0x13, 0x95, 0x3D, 0xA6, 0xAF, 0x03, 0x1D, 0xC4, 0xC1, 0x54, 0x29, 0xEC, 0xD5, 0x3B, 0x72, 0xF9, 0x9E, 0x4D, 0xC7, + 0x2F, 0x9F, 0xDD, 0xBB, 0x40, 0xCA, 0xE7, 0x06, 0xED, 0x16, 0x38, 0xBD, 0xF7, 0xD4, 0x20, 0x02, 0x04, 0xC0, 0x27, 0xE4, + 0x96, 0x88, 0x4A, 0x20, 0x7C, 0x4D, 0x12, 0xC4, 0xD6, 0xA8, 0x28, 0x12, 0x05, 0xC1, 0xD0, 0x64, 0x97, 0x85, 0xBE, 0x02, + 0x15, 0xDD, 0xBA, 0xD4, 0x53, 0x5A, 0xE7, 0x6C, 0x84, 0x82, 0x1A, 0x65, 0xD5, 0xE2, 0xD5, 0x04, 0x77, 0x48, 0x60, 0x55, + 0x77, 0x87, 0x29, 0x87, 0x85, 0x83, 0x38, 0xF5, 0x17, 0xA9, 0x95, 0x96, 0x04, 0x49, 0x52, 0xCA, 0xEB, 0xA1, 0x5F, 0x8D, + 0xBF, 0xC8, 0x9F, 0x35, 0x3C, 0x2D, 0xDC, 0x1D, 0x84, 0xA4, 0x30, 0xE2, 0xA0, 0xA6, 0xD7, 0xAF, 0x17, 0xE6, 0x97, 0xA5, + 0x31, 0x89, 0x58, 0xB2, 0x4B, 0x6E, 0x99, 0xB6, 0x5B, 0x4E, 0x11, 0x85, 0x2C, 0xC7, 0x65, 0x27, 0x92, 0x8A, 0xCA, 0x13, + 0x46, 0x40, 0xB3, 0x2D, 0xB5, 0xE2, 0x89, 0xE5, 0x00, 0x80, 0x96, 0x24, 0x84, 0xA6, 0xA9, 0x72, 0xC1, 0xCC, 0x29, 0x76, + 0xE4, 0xF6, 0x22, 0x0A, 0x0C, 0xC8, 0x44, 0x6C, 0x7D, 0xFD, 0xB5, 0x7A, 0x6C, 0xD4, 0x25, 0xC0, 0x37, 0xFF, 0x2A, 0x1A, + 0x0D, 0xC9, 0x0E, 0x7C, 0x5C, 0xB9, 0xF0, 0x38, 0x45, 0x01, 0xB2, 0xD8, 0x3E, 0xC9, 0x23, 0x9E, 0x8C, 0x8A, 0xBB, 0xCA, + 0x1E, 0x82, 0x97, 0x6B, 0x8C, 0x45, 0xB0, 0xE9, 0x6C, 0xEC, 0x72, 0xC8, 0x8D, 0x8B, 0xD3, 0x9D, 0x9C, 0xD3, 0xC1, 0xE4, + 0x2C, 0xCF, 0xC3, 0x79, 0x29, 0xA5, 0xCA, 0xE8, 0xD1, 0x63, 0xD8, 0x4A, 0x97, 0xC3, 0xF4, 0xD5, 0x46, 0xAC, 0x4A, 0x95, + 0xBF, 0x13, 0x14, 0xFF, 0xF2, 0xCF, 0x3A, 0x1D, 0xE4, 0x00, 0x04, 0xDB, 0xA6, 0xEE, 0x7D, 0x96, 0x6F, 0xA0, 0xF3, 0x39, + 0x65, 0xCD, 0x23, 0x1A, 0xA7, 0x5A, 0x2D, 0xCF, 0xC6, 0x43, 0x33, 0x7A, 0xE4, 0xE6, 0xAB, 0xF3, 0x83, 0xD3, 0xA2, 0x7F, + 0x3E, 0xEF, 0xD7, 0xE8, 0xD3, 0xC5, 0x04, 0x0C, 0xCB, 0x6D, 0x4D, 0x79, 0xA6, 0xB4, 0x7B, 0x86, 0x43, 0xBC, 0x30, 0xBE, + 0xB9, 0x5A, 0x93, 0x16, 0xF3, 0x57, 0xA3, 0xE0, 0x86, 0xF4, 0x27, 0xF6, 0x25, 0xB7, 0x0D, 0xF2, 0xD7, 0x5C, 0x63, 0x1B, + 0x73, 0xB1, 0x2D, 0x7E, 0x25, 0x49, 0x65, 0xEE, 0x76, 0x4F, 0x1D, 0x92, 0x45, 0xDB, 0x1D, 0x01, 0x71, 0xD5, 0xC2, 0x69, + 0x72, 0xCC, 0xA1, 0xE0, 0xD6, 0x2C, 0xD9, 0x94, 0x52, 0x5E, 0xAC, 0xC5, 0x0A, 0xB1, 0xCA, 0xC5, 0x6E, 0x54, 0xE5, 0x42, + 0x4D, 0xDD, 0xE6, 0x5D, 0x6E, 0x74, 0x24, 0xE7, 0x45, 0xE5, 0x6A, 0x95, 0x9B, 0x55, 0xD4, 0x29, 0xC2, 0xD9, 0x79, 0xE3, + 0x4D, 0x78, 0x66, 0x72, 0x79, 0x0D, 0x47, 0xD7, 0xF5, 0xC3, 0x4E, 0xB8, 0x63, 0xB8, 0x2B, 0x47, 0xEE, 0xD2, 0x4D, 0x18, + 0xF0, 0xCC, 0xFF, 0x7D, 0xE3, 0x52, 0x0A, 0x17, 0xBB, 0x1C, 0x29, 0xB4, 0x25, 0x77, 0xAD, 0x95, 0xF3, 0xDB, 0x7F, 0x8A, + 0x53, 0x98, 0xDE, 0x8C, 0xCB, 0xFA, 0xD2, 0x8D, 0xDF, 0x55, 0x36, 0x86, 0x80, 0xDB, 0x55, 0x6B, 0x8D, 0x45, 0x0A, 0xFC, + 0x7E, 0x56, 0x9E, 0xF0, 0xF8, 0x75, 0x6E, 0x3A, 0x79, 0xE8, 0x1D, 0x6D, 0xBC, 0x64, 0xF8, 0x04, 0x3E, 0x92, 0xD3, 0x8C, + 0x7D, 0x76, 0x77, 0xAB, 0xCC, 0x0F, 0x71, 0xE3, 0x74, 0x30, 0xD7, 0x1D, 0xBE, 0x5D, 0x9B, 0xF5, 0x4E, 0xBE, 0x60, 0xB7, + 0x7A, 0xFC, 0x93, 0xCA, 0x2E, 0x5C, 0x36, 0xCF, 0x38, 0xFE, 0x7E, 0xA0, 0x68, 0x7F, 0x89, 0x9D, 0x2E, 0x75, 0x52, 0xDE, + 0xA6, 0xF2, 0xA6, 0xDB, 0x54, 0xFE, 0x2A, 0xBD, 0xAD, 0xBD, 0x81, 0x16, 0x07, 0xB0, 0x18, 0xB8, 0xBD, 0x9F, 0x83, 0x4B, + 0xF8, 0xBF, 0xF8, 0xF4, 0xC4, 0x73, 0x77, 0x8F, 0xFA, 0xD2, 0xAF, 0x47, 0xCC, 0x6B, 0xEB, 0x5B, 0xF3, 0x4F, 0x37, 0xFF, + 0x66, 0x60, 0x00, 0x7B, 0x90, 0xDE, 0xBF, 0x70, 0x08, 0x09, 0x88, 0x00, 0x99, 0x9F, 0xF7, 0xE0, 0x58, 0x02, 0x28, 0xDA, + 0x56, 0x22, 0xF4, 0x63, 0x4E, 0x00, 0x98, 0x66, 0x15, 0x0D, 0x10, 0x34, 0xC8, 0xFE, 0x34, 0xAB, 0xDE, 0xE7, 0x81, 0x42, + 0x7B, 0x2E, 0xAD, 0xE2, 0x79, 0xC8, 0xD1, 0xA2, 0x4D, 0xB4, 0xB7, 0xA1, 0xD6, 0x64, 0x33, 0x15, 0x08, 0x6C, 0x75, 0x91, + 0xDD, 0x31, 0x35, 0xD6, 0x28, 0x59, 0x98, 0xF5, 0x9B, 0x21, 0x81, 0xC4, 0x04, 0xAF, 0x1F, 0x45, 0x14, 0x7E, 0x0E, 0xC4, + 0x4A, 0xE4, 0xF0, 0xF0, 0x61, 0xE1, 0xF7, 0xA1, 0xA0, 0xB5, 0x3E, 0xC8, 0xB2, 0xDA, 0x88, 0x16, 0xBC, 0x3E, 0xE7, 0xB4, + 0x4B, 0x7E, 0x3E, 0xC5, 0xF9, 0x6F, 0x44, 0x5A, 0xB4, 0x20, 0x05, 0x63, 0x1D, 0x5D, 0x66, 0x6D, 0xD4, 0x86, 0x7B, 0x96, + 0x49, 0xD7, 0xF7, 0x5D, 0xB7, 0x3C, 0xD9, 0xF5, 0xCD, 0x5B, 0xEF, 0x4A, 0xCB, 0x25, 0x38, 0xF7, 0x0E, 0x52, 0x2E, 0x93, + 0x19, 0xC8, 0x02, 0x4A, 0x4C, 0x64, 0x52, 0x92, 0xF9, 0x97, 0xCA, 0x9B, 0x0F, 0xCB, 0x6D, 0x5C, 0x15, 0x82, 0xB6, 0xA7, + 0x48, 0xA9, 0x5A, 0x44, 0xA2, 0x2B, 0x86, 0x16, 0xAE, 0x48, 0x43, 0x89, 0x12, 0x44, 0xEF, 0xAD, 0x84, 0x4A, 0xC9, 0xA2, + 0xAC, 0x28, 0x1B, 0x59, 0xC1, 0xF6, 0x5B, 0x1C, 0xAA, 0xEA, 0xDB, 0xBD, 0x43, 0x27, 0xC4, 0x58, 0x24, 0x05, 0x18, 0x4A, + 0xB9, 0xA5, 0xD3, 0x2A, 0xE5, 0x6E, 0x8F, 0x79, 0x4C, 0x0E, 0x54, 0x17, 0x5B, 0xDC, 0x14, 0xFC, 0x03, 0xA0, 0xF0, 0xA3, + 0x1D, 0x77, 0x12, 0x7D, 0x20, 0x0E, 0x83, 0x4E, 0xB2, 0x7D, 0x3B, 0xC3, 0x8B, 0x6E, 0x8E, 0x39, 0x67, 0x6F, 0x6B, 0xED, + 0x80, 0x7E, 0xE9, 0x85, 0x36, 0x21, 0x48, 0x9E, 0x49, 0x0F, 0x4E, 0x42, 0xBD, 0x29, 0x5F, 0x0A, 0xD7, 0x21, 0x23, 0x75, + 0x32, 0x5F, 0xE8, 0x1F, 0x21, 0x70, 0xE4, 0x37, 0x16, 0x3D, 0x2D, 0xE0, 0x64, 0x7C, 0xEB, 0xE7, 0xDF, 0xDD, 0x9C, 0xF6, + 0xDE, 0x53, 0x2C, 0x54, 0x2D, 0x54, 0xD2, 0x90, 0xCC, 0x11, 0xB0, 0x53, 0x1A, 0x52, 0x5B, 0x25, 0xA8, 0x09, 0x69, 0xF5, + 0x30, 0xB4, 0x6A, 0xE2, 0x4F, 0xFF, 0x5B, 0x85, 0x51, 0x32, 0x40, 0xE5, 0x5C, 0x5B, 0xB5, 0xE5, 0x31, 0xB5, 0x31, 0x56, + 0x9E, 0x73, 0x99, 0x31, 0xBB, 0x7A, 0xFB, 0x53, 0x3A, 0xC9, 0x7F, 0x56, 0x32, 0x75, 0x72, 0x20, 0x72, 0x38, 0x46, 0x17, + 0xF6, 0xF9, 0x12, 0x74, 0x2B, 0xB8, 0x73, 0x46, 0x77, 0xE8, 0xFC, 0x30, 0x6F, 0xFE, 0x85, 0xC7, 0x75, 0x95, 0x27, 0xC1, + 0xA3, 0x76, 0x05, 0x7C, 0xF9, 0x58, 0xEA, 0x91, 0x62, 0xD0, 0x87, 0x53, 0x19, 0x12, 0xC8, 0x16, 0x61, 0x57, 0xAF, 0xD5, + 0x97, 0x9A, 0x8D, 0xF0, 0xAB, 0x74, 0xE1, 0xB5, 0xB7, 0xFA, 0xD6, 0x60, 0x0C, 0x55, 0x26, 0x4C, 0x34, 0xC3, 0xD6, 0x64, + 0x74, 0xAC, 0xDE, 0x35, 0x1B, 0x3B, 0xCE, 0x8D, 0x68, 0x13, 0x7D, 0xFE, 0xC6, 0x94, 0x56, 0xAD, 0x6F, 0x1B, 0x6A, 0xFB, + 0x18, 0x7D, 0x45, 0x72, 0x49, 0xE5, 0x83, 0xA9, 0xBE, 0x78, 0xC7, 0x2D, 0xAE, 0x6A, 0x81, 0x0C, 0xFE, 0x38, 0x8C, 0x71, + 0x8D, 0x56, 0x8A, 0xDA, 0x67, 0x31, 0x7B, 0x7E, 0x37, 0x53, 0xFD, 0xBE, 0xF8, 0x6B, 0x0E, 0xC0, 0xC3, 0x8C, 0x08, 0x1C, + 0xBE, 0x37, 0x76, 0x36, 0x59, 0x1F, 0x8F, 0xDB, 0xDD, 0x83, 0x62, 0x23, 0xA2, 0x72, 0x38, 0x3D, 0x9A, 0xB4, 0x18, 0x4E, + 0xE6, 0xF0, 0x73, 0x14, 0x97, 0x30, 0x25, 0xCD, 0xA9, 0x5E, 0x47, 0x32, 0x9E, 0x38, 0xEF, 0x10, 0xA2, 0x1C, 0x47, 0xFC, + 0x9E, 0x7A, 0x71, 0x11, 0x8B, 0xB2, 0xCB, 0xBD, 0xB7, 0xC4, 0xDC, 0x66, 0x0A, 0x89, 0xDD, 0x1B, 0x84, 0x5F, 0x46, 0x0A, + 0x07, 0xE0, 0x18, 0xF9, 0x12, 0x9A, 0xD7, 0xE2, 0x48, 0x6B, 0xD2, 0x2E, 0x55, 0x80, 0xBA, 0x74, 0xFA, 0xC3, 0x84, 0xED, + 0xFC, 0x4B, 0x80, 0xCD, 0x43, 0xFB, 0x78, 0xC7, 0xAE, 0xA3, 0x7F, 0xA7, 0x8C, 0x99, 0x3B, 0x78, 0x91, 0xE1, 0xE1, 0x22, + 0xF7, 0xD3, 0xEF, 0x83, 0xDC, 0xA0, 0x64, 0x67, 0x08, 0x08, 0xB9, 0x64, 0x91, 0x8F, 0xA3, 0xB7, 0xCB, 0x3B, 0xE6, 0x52, + 0x28, 0x48, 0x28, 0x46, 0x8F, 0x3B, 0x16, 0xDA, 0xB7, 0x5B, 0x12, 0x62, 0x47, 0xFE, 0x08, 0x14, 0xBD, 0x25, 0x78, 0x24, + 0x03, 0xA9, 0xF9, 0x30, 0xE8, 0xE7, 0x68, 0x05, 0x43, 0xC1, 0x79, 0xB6, 0x23, 0x6E, 0x4D, 0xA4, 0x6F, 0x9C, 0xDF, 0x4F, + 0xB2, 0xBD, 0x51, 0x3A, 0x2F, 0xDC, 0xCF, 0x53, 0x5B, 0x40, 0x95, 0xD7, 0x81, 0x50, 0xA4, 0x23, 0x6A, 0xE6, 0xF3, 0x82, + 0xED, 0xE7, 0x3C, 0x46, 0xB3, 0x48, 0x26, 0x95, 0x09, 0xCB, 0x5E, 0x7D, 0x00, 0x21, 0x62, 0x48, 0x48, 0xE4, 0xCA, 0x22, + 0x5A, 0x4A, 0x3A, 0x7C, 0x09, 0xA5, 0x2F, 0x6E, 0x11, 0xA0, 0xBA, 0x5A, 0x49, 0xE5, 0x9A, 0xD4, 0x3E, 0xED, 0x0F, 0xF0, + 0x65, 0x60, 0x23, 0x6F, 0x84, 0x07, 0x4C, 0x58, 0x9C, 0x43, 0xA6, 0x5C, 0x7F, 0x63, 0xD7, 0x9F, 0xC1, 0x99, 0x2F, 0xEE, + 0xBB, 0x8B, 0x44, 0x7C, 0xCB, 0x49, 0xDA, 0xFF, 0xD9, 0xC7, 0x5A, 0xB5, 0xE7, 0x5C, 0xBB, 0x67, 0xBB, 0x53, 0xB2, 0xFB, + 0x6F, 0xC6, 0x52, 0x1C, 0x3C, 0x2B, 0x15, 0x25, 0x77, 0x72, 0x7A, 0xDA, 0x65, 0x07, 0x2E, 0xFE, 0x49, 0xAA, 0x3A, 0x6B, + 0xF6, 0xE7, 0x3D, 0xA9, 0x82, 0x0A, 0x23, 0x86, 0xFB, 0x53, 0x34, 0x9B, 0xE8, 0x6F, 0x8D, 0x68, 0xED, 0x6B, 0x51, 0xFE, + 0x78, 0xE1, 0x47, 0x20, 0x5D, 0x8F, 0x97, 0x0B, 0x4F, 0x49, 0x3B, 0x8F, 0x41, 0x4E, 0x26, 0x7D, 0xCD, 0xC0, 0x24, 0x84, + 0x3C, 0xDC, 0xB0, 0x53, 0x42, 0xF0, 0x58, 0xD9, 0x15, 0xF4, 0x26, 0xD2, 0x29, 0x3A, 0xA8, 0x12, 0x79, 0x50, 0xF8, 0x77, + 0x47, 0xDC, 0xE2, 0x12, 0x7D, 0x51, 0x67, 0x78, 0xA2, 0x72, 0xAD, 0x82, 0xDF, 0xF1, 0xF5, 0xB6, 0xB8, 0x90, 0xD7, 0xA0, + 0xF5, 0x92, 0xFD, 0x92, 0x4C, 0x03, 0xB7, 0x96, 0x94, 0x13, 0xBD, 0xF0, 0x1E, 0x7E, 0xE9, 0xB5, 0x22, 0x5E, 0xE4, 0x81, + 0x89, 0x3F, 0xE4, 0xE2, 0xD7, 0xB2, 0x7C, 0xE7, 0x0D, 0x97, 0x64, 0x84, 0x89, 0xB9, 0x74, 0x12, 0x75, 0x1E, 0x9A, 0x35, + 0x96, 0xBC, 0x1E, 0xF2, 0x66, 0xF7, 0x43, 0xB1, 0xB5, 0x35, 0x31, 0xC2, 0xA0, 0x34, 0x13, 0x26, 0x15, 0xB0, 0x71, 0x90, + 0xFA, 0xB8, 0x8A, 0x63, 0x8D, 0x9F, 0xBD, 0xE2, 0x8D, 0xD5, 0x6B, 0xA5, 0x84, 0x52, 0x5D, 0xE2, 0x0E, 0x3D, 0x6D, 0x91, + 0x0C, 0xB5, 0x3C, 0x8B, 0x0D, 0xF8, 0x66, 0x9B, 0x1E, 0xB3, 0x35, 0xDA, 0x68, 0xD1, 0x33, 0xDE, 0x78, 0xF3, 0x39, 0x1E, + 0x2B, 0x1D, 0x90, 0x93, 0x5C, 0xD9, 0xAE, 0xDC, 0x92, 0xC2, 0xE6, 0x9F, 0x7B, 0x19, 0x79, 0x2F, 0xA4, 0x81, 0x23, 0x7E, + 0x9A, 0x9A, 0xB7, 0xE8, 0x17, 0xC1, 0x25, 0x2B, 0xB0, 0x1B, 0xD0, 0xE8, 0xBD, 0xF5, 0xF7, 0xB6, 0x8E, 0xEA, 0xAD, 0xDD, + 0x60, 0x2D, 0xEF, 0xCF, 0xF5, 0xF0, 0xA6, 0x6D, 0xA1, 0x15, 0x1E, 0x2C, 0xC1, 0xFD, 0x66, 0x9C, 0x26, 0x77, 0xA9, 0x8B, + 0x83, 0x90, 0xEF, 0xA5, 0x4E, 0x99, 0x6E, 0xDC, 0x7C, 0xA6, 0xBE, 0x22, 0xB3, 0x29, 0xFD, 0xEF, 0xFA, 0x6D, 0x47, 0x59, + 0x26, 0x96, 0x27, 0x9F, 0xC2, 0xB6, 0xA7, 0xEA, 0x6E, 0x7E, 0x95, 0xE7, 0xDA, 0xFD, 0x0D, 0xCC, 0xAC, 0xFF, 0x59, 0xB9, + 0x9C, 0xFF, 0xAF, 0xC4, 0xC9, 0x9E, 0x3F, 0x56, 0xA8, 0xBE, 0xA8, 0x31, 0xE1, 0x1B, 0x07, 0x66, 0xD1, 0xAA, 0x28, 0xD3, + 0x5F, 0x46, 0x77, 0xE4, 0x14, 0x7B, 0x76, 0x49, 0x84, 0x60, 0xBA, 0xFD, 0xDF, 0x4E, 0x9F, 0xC1, 0xE2, 0x11, 0x60, 0x14, + 0x5F, 0xD1, 0x34, 0xE7, 0x05, 0x43, 0x06, 0xF4, 0x33, 0x23, 0x31, 0x0A, 0x61, 0xC8, 0x54, 0x43, 0xE3, 0xB2, 0x77, 0x49, + 0xB2, 0xE6, 0xB7, 0xF7, 0x8B, 0x4C, 0x2B, 0xB3, 0x23, 0xD1, 0xBF, 0x44, 0xF0, 0xCE, 0xD7, 0xA8, 0x90, 0x49, 0x81, 0x22, + 0x21, 0x44, 0xD2, 0x86, 0xA9, 0xDE, 0xEE, 0x59, 0x98, 0x4D, 0xDB, 0xA8, 0x03, 0x47, 0xFA, 0xAB, 0xE7, 0x2A, 0x4A, 0x61, + 0x70, 0x57, 0x3F, 0xB4, 0x57, 0x2B, 0xBE, 0xBD, 0x82, 0xB3, 0x39, 0xB4, 0x31, 0xD5, 0x31, 0x63, 0x60, 0x4B, 0xD9, 0x70, + 0x3B, 0x97, 0xC5, 0x23, 0xB0, 0x11, 0x09, 0xB9, 0x50, 0x65, 0xA1, 0xF3, 0x43, 0x7C, 0xCF, 0xF7, 0x53, 0xBF, 0xFA, 0x4E, + 0x56, 0x44, 0xB8, 0xE4, 0xAC, 0x67, 0x6A, 0x6E, 0x1E, 0x4E, 0x8C, 0x6B, 0x92, 0xA1, 0x72, 0xE9, 0x55, 0xF6, 0xD1, 0x1E, + 0x62, 0x87, 0x7A, 0x3A, 0xA1, 0x44, 0x82, 0x2F, 0x3C, 0x6A, 0x13, 0x8B, 0x62, 0x25, 0x58, 0x13, 0xE7, 0x64, 0x33, 0x1F, + 0x69, 0x95, 0xDB, 0x28, 0x10, 0xA3, 0x6B, 0x1B, 0xCE, 0x06, 0x56, 0x3D, 0x9F, 0x10, 0x64, 0x47, 0x22, 0xA1, 0xA5, 0x4C, + 0x54, 0xCD, 0xBA, 0xA0, 0xD6, 0x41, 0xC8, 0x10, 0x98, 0x24, 0x6A, 0xED, 0x44, 0x2E, 0xEA, 0x2B, 0x54, 0x6D, 0xDD, 0xDC, + 0x06, 0x80, 0x7B, 0xDE, 0x39, 0x4D, 0x59, 0x9A, 0xEA, 0x46, 0x3A, 0x7C, 0xDB, 0xED, 0xBC, 0xB5, 0x8A, 0xBB, 0x36, 0x3F, + 0x39, 0x62, 0x19, 0xF4, 0x48, 0xC9, 0xEB, 0x79, 0x7E, 0x3E, 0x12, 0x46, 0x2C, 0x4D, 0xB3, 0xB5, 0xC7, 0x62, 0xDF, 0x89, + 0x97, 0x40, 0x6B, 0xF9, 0x5D, 0x6F, 0xD9, 0x10, 0x5B, 0xEF, 0xFA, 0xF4, 0x91, 0xBC, 0x5E, 0xBD, 0x8B, 0x53, 0x82, 0xD4, + 0x9B, 0xFA, 0x7A, 0x6D, 0xC2, 0x6A, 0x74, 0x16, 0xB1, 0x78, 0x18, 0x32, 0xE1, 0xA9, 0xBC, 0x9E, 0xD0, 0xFD, 0xC5, 0x78, + 0x8B, 0xC9, 0xCF, 0x98, 0x83, 0x40, 0x4D, 0xA4, 0x8B, 0x51, 0x55, 0xE8, 0x61, 0x74, 0x0B, 0xE3, 0x5A, 0x51, 0xB5, 0x30, + 0x37, 0x51, 0x25, 0xE3, 0xA2, 0xA3, 0xD7, 0xA8, 0xC2, 0x65, 0x7A, 0x10, 0x49, 0x1B, 0x9A, 0xA6, 0x3C, 0x56, 0x34, 0xE2, + 0xD1, 0x59, 0xB4, 0xE6, 0x47, 0x79, 0xA9, 0xA3, 0x80, 0x5A, 0xCE, 0xF2, 0x35, 0x73, 0xA7, 0x12, 0xE1, 0x51, 0xE4, 0x0F, + 0x86, 0x6E, 0x47, 0xF3, 0x5D, 0x0D, 0x8F, 0x78, 0x90, 0x3B, 0x1F, 0xFC, 0x60, 0x31, 0x2E, 0x67, 0x72, 0x4F, 0x4C, 0xAE, + 0x04, 0xBA, 0x4B, 0x57, 0x33, 0x8C, 0x20, 0x93, 0x22, 0xDD, 0xDE, 0x13, 0x0A, 0x67, 0x59, 0x69, 0x5F, 0xC4, 0x32, 0xEE, + 0x9C, 0x95, 0x14, 0x40, 0xD8, 0x17, 0x6E, 0xCE, 0x3B, 0x88, 0x34, 0x63, 0x2F, 0xA2, 0x54, 0x9D, 0x0A, 0x4B, 0x06, 0xAC, + 0x94, 0x37, 0xFF, 0xDA, 0x5A, 0x19, 0xD8, 0x9F, 0x97, 0xBA, 0x67, 0x91, 0x8B, 0xCE, 0xAF, 0x56, 0x89, 0x7A, 0xCE, 0xB2, + 0x5F, 0x61, 0x53, 0xEB, 0x9A, 0x29, 0x37, 0x62, 0x98, 0x5B, 0x79, 0x19, 0xE8, 0x9B, 0xC5, 0xAC, 0x5E, 0x60, 0x8A, 0x39, + 0x89, 0x9C, 0xFE, 0x69, 0xBC, 0x6C, 0xD1, 0x6A, 0xC4, 0xC3, 0x2E, 0x6E, 0xFA, 0xF6, 0x36, 0x3E, 0x3B, 0xE0, 0xEE, 0x30, + 0x9A, 0x92, 0x66, 0x28, 0x37, 0x5B, 0xFE, 0x39, 0xDA, 0xD6, 0x75, 0x36, 0xBA, 0xB3, 0x97, 0xC1, 0xDC, 0x38, 0x2F, 0x6B, + 0x6A, 0x61, 0xEF, 0x1E, 0xED, 0x78, 0xB7, 0x5B, 0x2B, 0x27, 0xD3, 0xFA, 0x1A, 0x24, 0xAB, 0x06, 0x48, 0xD2, 0xD6, 0xFD, + 0x10, 0x47, 0x0A, 0xD2, 0x58, 0x00, 0x34, 0xFA, 0xC1, 0x5B, 0x0F, 0xD1, 0x57, 0xC6, 0x2A, 0x66, 0x58, 0x44, 0x12, 0x90, + 0xEF, 0x16, 0x5E, 0xFB, 0x43, 0xE3, 0xE7, 0xD4, 0xAC, 0xDB, 0xAE, 0x56, 0x17, 0x4E, 0x41, 0xB0, 0x22, 0x8D, 0xEA, 0xFF, + 0x14, 0x19, 0x11, 0x14, 0x65, 0xD9, 0xAF, 0x87, 0x3D, 0xE1, 0x51, 0x55, 0xDD, 0x98, 0xF4, 0x32, 0x17, 0xA7, 0x37, 0xE6, + 0xE6, 0x53, 0xE9, 0x24, 0xF4, 0xEC, 0xFB, 0xA0, 0xEF, 0xEE, 0xFA, 0x42, 0x37, 0x3F, 0x10, 0x60, 0xFA, 0xC9, 0x2F, 0x16, + 0x21, 0xE4, 0x4E, 0xB0, 0x4C, 0x2A, 0x92, 0xA9, 0x95, 0xA1, 0x8C, 0x89, 0xE4, 0xC3, 0x7F, 0x10, 0x36, 0xA5, 0x47, 0x93, + 0x25, 0x03, 0x81, 0x45, 0xEA, 0xAB, 0x5B, 0xB3, 0x9A, 0xC0, 0x31, 0x8A, 0xA4, 0xFD, 0xA3, 0x02, 0xCC, 0x8C, 0x7A, 0x35, + 0xEA, 0xAC, 0x59, 0x5C, 0x66, 0x4D, 0xA1, 0x73, 0x7F, 0x87, 0xC3, 0xFC, 0x1C, 0x47, 0x3A, 0x6C, 0x5F, 0x5A, 0x8A, 0xCA, + 0x54, 0x63, 0x90, 0xC6, 0xCC, 0x27, 0x4A, 0xA9, 0xCA, 0x86, 0xE0, 0x83, 0xF6, 0x60, 0x45, 0xCA, 0x41, 0x86, 0xC4, 0xFB, + 0x6E, 0x8B, 0x5D, 0x47, 0x67, 0xF2, 0xDD, 0x7E, 0x30, 0xA7, 0xFD, 0xB6, 0xA7, 0xD0, 0x8D, 0x5E, 0xB4, 0x23, 0xF0, 0xA8, + 0xF2, 0xF5, 0x1F, 0x7D, 0xDE, 0x5B, 0x5B, 0x39, 0x90, 0xC6, 0x43, 0xD7, 0xC3, 0xA6, 0xE2, 0x4B, 0x29, 0xE2, 0xE5, 0x2C, + 0x10, 0xEA, 0xF5, 0xE8, 0xAC, 0xCC, 0x92, 0x6C, 0x6F, 0xE1, 0x54, 0x8B, 0xCD, 0x0D, 0xD2, 0x19, 0x11, 0xCF, 0x42, 0x28, + 0x0C, 0x3D, 0xC2, 0x85, 0xAA, 0x42, 0x5D, 0x9F, 0x4C, 0x13, 0x23, 0xEF, 0x98, 0x6E, 0x0B, 0xE9, 0x4E, 0xD1, 0x08, 0xED, + 0x5E, 0x07, 0x63, 0x5F, 0x87, 0xC4, 0x0B, 0x4E, 0x1D, 0xAB, 0x1B, 0xCC, 0xD1, 0xC0, 0xE8, 0x04, 0x34, 0x5E, 0xDC, 0x6A, + 0x78, 0xDD, 0xFD, 0x99, 0x70, 0xB1, 0x0A, 0x02, 0x24, 0xCB, 0x13, 0xC0, 0x57, 0x90, 0x20, 0x67, 0xA0, 0xD3, 0xBA, 0xE7, + 0xDE, 0x18, 0x8D, 0xD0, 0x44, 0x51, 0x9C, 0xEF, 0xD4, 0x93, 0x3F, 0x87, 0x87, 0xD2, 0x26, 0x8E, 0x5D, 0x7B, 0x04, 0x45, + 0x66, 0xD6, 0xEF, 0xAF, 0x53, 0xF4, 0x85, 0x82, 0x44, 0x88, 0x97, 0x64, 0xD0, 0xB5, 0x05, 0x5B, 0x2F, 0x9C, 0x79, 0x32, + 0xB6, 0x01, 0x5C, 0x3C, 0xA4, 0x90, 0x47, 0x30, 0xB4, 0xB0, 0x14, 0x51, 0xC1, 0xDB, 0xAD, 0x61, 0x97, 0xBB, 0x66, 0x7F, + 0xA5, 0x91, 0x58, 0xB4, 0xDC, 0x44, 0x36, 0xEF, 0xE5, 0x52, 0x9C, 0xF4, 0xE5, 0xF8, 0x6C, 0x2B, 0x91, 0xD4, 0x35, 0xA5, + 0x5D, 0x67, 0x15, 0xE0, 0xF2, 0xDB, 0xF4, 0x94, 0xE1, 0xB9, 0xE0, 0xB1, 0x50, 0x91, 0xBD, 0xD6, 0xE1, 0xB6, 0x79, 0x11, + 0x46, 0x7C, 0x02, 0x1F, 0xF2, 0x7A, 0x26, 0x6C, 0xCD, 0x9E, 0x86, 0xF2, 0x9D, 0x67, 0x6F, 0x3C, 0x8D, 0x97, 0xE6, 0xCC, + 0x6C, 0x5C, 0xB5, 0x17, 0x2B, 0x22, 0xD0, 0xFE, 0x0E, 0x69, 0x5E, 0xB8, 0xBB, 0xD4, 0x29, 0xBC, 0x39, 0x5D, 0x03, 0xD7, + 0x0F, 0xD8, 0x63, 0x0A, 0xFF, 0x48, 0x36, 0x5B, 0xED, 0x95, 0x7B, 0x93, 0x34, 0x70, 0x3E, 0x19, 0x2D, 0x03, 0x91, 0xEF, + 0x1A, 0xD7, 0x15, 0x6B, 0xB1, 0xD2, 0xF5, 0x83, 0x35, 0x91, 0x46, 0x86, 0x1D, 0x27, 0x61, 0x43, 0xD7, 0x6D, 0x0E, 0xE6, + 0x8E, 0xD3, 0x0E, 0xE6, 0x83, 0xB3, 0xD9, 0x5E, 0x00, 0x83, 0xAC, 0xA8, 0xC0, 0x10, 0x54, 0x2A, 0x33, 0xDB, 0xFD, 0x8D, + 0x0F, 0xB2, 0xA7, 0x9B, 0x90, 0xD2, 0x0B, 0x5C, 0x97, 0xB6, 0x17, 0xE8, 0xFA, 0xD3, 0xA7, 0xFA, 0xC3, 0xE5, 0x55, 0x28, + 0x8A, 0x84, 0x7C, 0x40, 0xBC, 0x0F, 0x09, 0x55, 0x4C, 0xC4, 0xFE, 0x8C, 0x87, 0xB0, 0x60, 0x02, 0x79, 0x0D, 0xD9, 0x95, + 0xB7, 0x62, 0xD0, 0x3D, 0x74, 0xBD, 0x4B, 0x46, 0x91, 0xEA, 0x92, 0xF2, 0x83, 0x05, 0xED, 0x90, 0x0E, 0xDC, 0xDC, 0x6E, + 0x4F, 0x5F, 0x20, 0x73, 0x93, 0xC1, 0x4B, 0x1C, 0x02, 0xD6, 0x1B, 0x9D, 0x96, 0x08, 0x48, 0x25, 0x15, 0x2E, 0x16, 0xCD, + 0xD6, 0x2D, 0x39, 0x73, 0xC2, 0xF3, 0x49, 0xE5, 0x3E, 0x38, 0x64, 0xC2, 0xD6, 0xBC, 0xD1, 0x30, 0xB2, 0xC3, 0x5E, 0xC4, + 0x28, 0xDA, 0x7D, 0x74, 0x16, 0xA3, 0xB1, 0x62, 0xF2, 0x40, 0xD8, 0x71, 0xC0, 0x6E, 0xEB, 0x2C, 0xA2, 0x69, 0x5C, 0x71, + 0x5A, 0x61, 0xF1, 0x72, 0x6D, 0x71, 0x48, 0x33, 0xC1, 0xDA, 0x81, 0x85, 0xAB, 0x00, 0xC3, 0x45, 0x91, 0xD3, 0xB8, 0x63, + 0x67, 0x42, 0x53, 0xB6, 0x71, 0x29, 0x2F, 0x30, 0xB0, 0x95, 0x5D, 0xD7, 0xC7, 0x5E, 0xF9, 0x7F, 0x4F, 0xDA, 0x5E, 0xA6, + 0x70, 0x3A, 0x7C, 0xA8, 0x87, 0x8E, 0x01, 0x6A, 0xE3, 0x6D, 0x4B, 0xAF, 0xA9, 0x07, 0x6A, 0xAE, 0xD8, 0xB3, 0x5A, 0x0C, + 0x8B, 0x0D, 0xAA, 0xE3, 0xF0, 0x40, 0x13, 0x03, 0x50, 0x52, 0xA2, 0x0D, 0xF8, 0x72, 0x81, 0x49, 0x84, 0xA1, 0x47, 0x7F, + 0xB6, 0xA2, 0x12, 0x56, 0x6F, 0xDF, 0xAB, 0xFD, 0x84, 0xCB, 0xFF, 0x7B, 0xA8, 0x09, 0xA1, 0xB8, 0xB7, 0xA1, 0x93, 0x5F, + 0x3E, 0x5B, 0x8B, 0xDB, 0x5B, 0x6F, 0xBA, 0x3A, 0xF5, 0x4E, 0x1E, 0xE3, 0x12, 0xEC, 0xAB, 0x1A, 0xC4, 0x29, 0x42, 0x2A, + 0x91, 0xF1, 0xA2, 0x67, 0x2F, 0xE0, 0xF2, 0x78, 0x18, 0x6D, 0x71, 0x2B, 0xC7, 0xD1, 0xB4, 0x0E, 0xD6, 0xDB, 0x1C, 0x7A, + 0x0F, 0x6E, 0xE6, 0x4B, 0x0E, 0x4A, 0x7A, 0x3A, 0x4E, 0x52, 0x83, 0x1A, 0xC2, 0x29, 0x4E, 0xAF, 0x9B, 0xF1, 0x75, 0x79, + 0x25, 0xF0, 0x23, 0x5E, 0x5A, 0xE3, 0xA4, 0x0F, 0x09, 0xF0, 0x6D, 0x6B, 0x1B, 0x96, 0x44, 0x7C, 0xAD, 0x72, 0xAC, 0x40, + 0x78, 0x4B, 0x69, 0x20, 0x7D, 0xA9, 0x6C, 0x92, 0x85, 0x1C, 0x08, 0x64, 0x39, 0x3E, 0x1D, 0x40, 0x4E, 0x1E, 0xA4, 0x4A, + 0x77, 0x73, 0xF9, 0xFF, 0xBA, 0x7D, 0xDE, 0x6A, 0x32, 0x31, 0x16, 0x51, 0xEE, 0x1D, 0xFD, 0xC7, 0x0F, 0x7C, 0x15, 0xF9, + 0xA7, 0x9B, 0x9D, 0x99, 0xB5, 0x1F, 0x0D, 0x80, 0xF5, 0x55, 0xB2, 0xAA, 0xD8, 0x75, 0x41, 0x26, 0x32, 0xEA, 0xC4, 0xED, + 0xCF, 0x80, 0xF5, 0xE7, 0x93, 0x0B, 0xEE, 0x7B, 0x8D, 0xF9, 0xEC, 0xCA, 0xAF, 0x78, 0xB4, 0xF0, 0xD2, 0xA9, 0xFC, 0xBA, + 0xB2, 0xF9, 0xA4, 0x1E, 0xDF, 0x78, 0xBC, 0xC3, 0x81, 0x02, 0xBD, 0xD7, 0x4D, 0x83, 0x6D, 0xC6, 0x73, 0xFA, 0x36, 0x1B, + 0xD6, 0xDA, 0x48, 0x33, 0x0F, 0xE9, 0xB4, 0x24, 0x10, 0x27, 0xF9, 0xAB, 0x40, 0x32, 0xCC, 0x17, 0x3A, 0x78, 0x48, 0x8A, + 0x60, 0x74, 0xC2, 0xAC, 0x38, 0x78, 0x36, 0xD9, 0xC9, 0xF7, 0xB6, 0x41, 0x7E, 0x10, 0x67, 0x73, 0x12, 0x71, 0x36, 0xEC, + 0x3D, 0x32, 0x89, 0x3C, 0x64, 0xB0, 0xB6, 0xDE, 0x84, 0x75, 0xD3, 0xD7, 0x86, 0xC6, 0xAB, 0x0C, 0x8B, 0xCA, 0x84, 0x8E, + 0x49, 0xF5, 0x8D, 0x29, 0xB9, 0x68, 0xF3, 0xE7, 0xB3, 0x74, 0x0F, 0xDE, 0xB3, 0x3D, 0xA8, 0x85, 0xEF, 0xD3, 0xA7, 0x39, + 0xF4, 0xE7, 0xBF, 0xCA, 0x4B, 0x28, 0x79, 0xF1, 0xC5, 0xE1, 0x7F, 0xBB, 0xEE, 0x40, 0xAF, 0x9F, 0xFE, 0xDE, 0xFA, 0x2E, + 0x3B, 0xE3, 0xB5, 0xA2, 0xE1, 0xA0, 0xB1, 0x96, 0xBC, 0x40, 0x7A, 0x9E, 0x49, 0x72, 0xE7, 0xC7, 0x26, 0x13, 0x13, 0x33, + 0x4B, 0x5D, 0x7C, 0xBA, 0x66, 0xC2, 0x77, 0x0D, 0xFE, 0xDC, 0xB6, 0xDB, 0xB8, 0x2B, 0xAE, 0x9D, 0xF3, 0xA0, 0x7F, 0x36, + 0x73, 0x1B, 0x4F, 0x52, 0xF3, 0x7D, 0xE0, 0x52, 0x4F, 0x84, 0x88, 0x5B, 0x55, 0xA3, 0x88, 0xDD, 0x42, 0x30, 0x90, 0x44, + 0xD6, 0x34, 0xFC, 0x4C, 0x96, 0xBE, 0xF7, 0x9F, 0x26, 0xD3, 0x00, 0xC9, 0x36, 0xC1, 0xDA, 0x3A, 0x56, 0x81, 0x27, 0x44, + 0xAA, 0x5E, 0x5C, 0x38, 0xB5, 0xE0, 0xA0, 0xA1, 0x44, 0xA8, 0x67, 0xC5, 0x75, 0x8E, 0x57, 0x5A, 0x51, 0x9B, 0x11, 0x37, + 0xC1, 0xB3, 0xF9, 0x2E, 0xB7, 0xD8, 0xE3, 0xC8, 0x76, 0xE5, 0x99, 0x40, 0x43, 0x69, 0x60, 0x21, 0x32, 0x90, 0xD0, 0x28, + 0x97, 0x68, 0x4B, 0xC6, 0xBB, 0x46, 0x91, 0x50, 0x71, 0x91, 0x0C, 0x72, 0xEA, 0x11, 0x93, 0x05, 0xC7, 0x75, 0x1F, 0x89, + 0xB6, 0x33, 0x64, 0xA5, 0x96, 0x78, 0x41, 0x49, 0x1A, 0x2B, 0xD5, 0x39, 0x19, 0xFB, 0x01, 0xB4, 0x37, 0x8A, 0xC9, 0x49, + 0x0B, 0x6A, 0x91, 0x65, 0x27, 0xA8, 0x5C, 0x75, 0x53, 0xA3, 0x02, 0xF3, 0x8B, 0x74, 0x42, 0x08, 0xAA, 0x85, 0xDC, 0x5F, + 0xA0, 0x21, 0xBA, 0x54, 0xEB, 0xD8, 0x92, 0xC2, 0x5A, 0x80, 0x64, 0x18, 0x45, 0xE5, 0xD4, 0x4F, 0xA1, 0x20, 0x88, 0xF6, + 0x7E, 0x79, 0x92, 0x5C, 0xA0, 0xE5, 0x3B, 0x8F, 0x8A, 0x02, 0x99, 0xF4, 0x1C, 0x6A, 0x8C, 0xCD, 0xFF, 0x2C, 0xA9, 0xAB, + 0x9D, 0xF8, 0xFF, 0x45, 0xA3, 0x57, 0x9C, 0x7F, 0x61, 0xA2, 0x83, 0xDB, 0xC9, 0xD9, 0x83, 0xBB, 0xD0, 0x77, 0x67, 0xA8, + 0xA2, 0x72, 0x4D, 0x54, 0xBD, 0x29, 0x48, 0xED, 0xE2, 0x03, 0x5E, 0x1C, 0x84, 0x53, 0x6F, 0xAC, 0x1F, 0x73, 0xD8, 0x62, + 0xE8, 0xEC, 0x83, 0x51, 0xEC, 0x70, 0x7E, 0xFA, 0x03, 0x7E, 0x9A, 0x49, 0xA8, 0xE3, 0xF2, 0x11, 0x46, 0xA1, 0x72, 0xB4, + 0x75, 0x53, 0xC9, 0xF5, 0x2D, 0xEA, 0x92, 0x59, 0xBC, 0xE2, 0x98, 0x5F, 0x83, 0x78, 0x86, 0x5F, 0x57, 0x8B, 0xAB, 0xAC, + 0x93, 0x83, 0x04, 0x52, 0xA6, 0x94, 0x84, 0x7E, 0x95, 0x3C, 0xF5, 0xE0, 0xC5, 0x2D, 0x49, 0x22, 0x79, 0x29, 0xAB, 0x10, + 0xF1, 0x58, 0xF5, 0x02, 0x92, 0xBC, 0x17, 0x5D, 0x63, 0xB9, 0x84, 0x48, 0x73, 0xF3, 0x3A, 0xE1, 0x65, 0x18, 0x61, 0x02, + 0xF7, 0xD2, 0x1D, 0xC1, 0xE2, 0xBA, 0xDD, 0xC5, 0x0B, 0xFC, 0x55, 0x11, 0x25, 0xB4, 0xE7, 0x2A, 0x86, 0x92, 0xA6, 0x71, + 0x44, 0x2C, 0x92, 0x5F, 0x21, 0x0E, 0xC4, 0xCC, 0xAA, 0x99, 0x5F, 0x5D, 0xC1, 0x44, 0xD5, 0xE5, 0x87, 0xB2, 0xCA, 0xE0, + 0x4E, 0x5B, 0x95, 0xD0, 0x76, 0x91, 0x47, 0x2D, 0x13, 0x08, 0x01, 0xF0, 0xB6, 0xC1, 0x82, 0xF1, 0xD6, 0x5A, 0xD1, 0x25, + 0xB6, 0x68, 0x8B, 0x25, 0x0F, 0x3B, 0xC1, 0x05, 0xF6, 0x28, 0x55, 0x94, 0x7A, 0xA5, 0x85, 0xD1, 0x10, 0x93, 0x94, 0x24, + 0x14, 0x6A, 0x05, 0x8C, 0xC6, 0xF7, 0x85, 0xD0, 0x56, 0xB6, 0x1E, 0xEA, 0x21, 0x95, 0x5E, 0xE8, 0x57, 0xB7, 0x5E, 0xC8, + 0x9B, 0x9A, 0x4C, 0x52, 0xD2, 0x03, 0x23, 0xA4, 0x3C, 0x66, 0xA8, 0x8C, 0xBF, 0x6D, 0x81, 0x5C, 0xE0, 0x74, 0xBE, 0xCC, + 0x86, 0xBB, 0x79, 0xC3, 0xAC, 0x35, 0x23, 0xBD, 0xD7, 0xB5, 0x77, 0xF0, 0xDF, 0x58, 0x2D, 0x42, 0x3A, 0xA1, 0x74, 0x9B, + 0xD6, 0xFB, 0xF7, 0x7D, 0x3F, 0xBF, 0xA8, 0x28, 0x99, 0x2A, 0x65, 0xA0, 0xFB, 0xA0, 0xCC, 0xC8, 0xED, 0x98, 0xC4, 0xEE, + 0xB9, 0x2E, 0xF5, 0xB6, 0x4F, 0xB0, 0xBE, 0xE7, 0xC7, 0x5D, 0xBA, 0xD8, 0x2D, 0x99, 0x96, 0xD6, 0xC2, 0x4C, 0xFE, 0x48, + 0x2F, 0xDD, 0xFF, 0x88, 0x5B, 0x8A, 0x7A, 0xC9, 0x09, 0x9A, 0x1C, 0xF4, 0x1D, 0x15, 0x56, 0x09, 0x17, 0x5F, 0x57, 0x05, + 0x3A, 0xF1, 0xDD, 0xD9, 0x1A, 0x9B, 0x10, 0xA4, 0x91, 0x00, 0x37, 0x50, 0x04, 0x9B, 0x04, 0xF3, 0x46, 0x5E, 0xA0, 0xEA, + 0xA5, 0xAF, 0xFD, 0xEA, 0x34, 0x3B, 0x3F, 0x89, 0xB7, 0xCD, 0xF9, 0xC7, 0x74, 0x7D, 0x36, 0x17, 0x35, 0xAE, 0x33, 0xB1, + 0xE6, 0x9C, 0x0F, 0x6E, 0x2B, 0x4E, 0x4C, 0xCB, 0xA4, 0x02, 0x79, 0x09, 0x25, 0x43, 0xC0, 0x7A, 0xEC, 0xDD, 0x42, 0xDB, + 0x75, 0xC7, 0x89, 0x38, 0x2D, 0x0E, 0xAD, 0x7A, 0x0F, 0xAC, 0x5D, 0xEE, 0x60, 0x40, 0x66, 0x43, 0xB3, 0xDC, 0x62, 0x4E, + 0xFF, 0xDC, 0x6E, 0x47, 0x93, 0xA8, 0xBE, 0x42, 0x71, 0xC3, 0xF4, 0x02, 0x52, 0xBB, 0xA8, 0x9A, 0xAF, 0xC5, 0x66, 0x57, + 0xCA, 0x0A, 0xF6, 0x68, 0x7B, 0x28, 0xF8, 0x02, 0x21, 0x82, 0x23, 0x50, 0x28, 0xA5, 0xE1, 0x0B, 0x21, 0x63, 0x12, 0xB6, + 0x1E, 0x67, 0xE9, 0x51, 0xDC, 0xE9, 0xE9, 0x9A, 0x27, 0x05, 0x67, 0x56, 0x12, 0xAB, 0xDB, 0x75, 0x78, 0x63, 0x27, 0x76, + 0x62, 0x06, 0x6E, 0x69, 0xA4, 0x67, 0x7A, 0x2F, 0xB1, 0x6E, 0xF9, 0x47, 0x36, 0x14, 0x82, 0xD9, 0xEB, 0x58, 0xA9, 0x89, + 0xAB, 0x76, 0x4E, 0x6B, 0x8D, 0x38, 0xB7, 0x92, 0x18, 0xC9, 0x8D, 0xC7, 0xBC, 0x2A, 0x9B, 0x4A, 0xA2, 0x79, 0x93, 0xE3, + 0x36, 0x2A, 0xC3, 0xDA, 0xD0, 0x5C, 0x4D, 0x2F, 0xC8, 0xB7, 0xEF, 0x09, 0x3D, 0xF5, 0x75, 0x1F, 0x60, 0x6F, 0xB0, 0x92, + 0x6A, 0x16, 0xE0, 0x62, 0xE7, 0xF7, 0x21, 0xC3, 0xC9, 0xA6, 0xE2, 0x02, 0x2E, 0x02, 0xF8, 0xFC, 0xF4, 0x83, 0xAD, 0x98, + 0x5C, 0xED, 0x89, 0x6C, 0x5C, 0x9C, 0xAE, 0xBE, 0x1B, 0x86, 0xF2, 0xA3, 0x68, 0x2D, 0x08, 0xCE, 0xA0, 0x29, 0x36, 0xE3, + 0xAA, 0xBB, 0xE7, 0x8B, 0x0E, 0x83, 0x67, 0x2F, 0x6D, 0x4B, 0xD2, 0x9A, 0x4E, 0xC3, 0x42, 0x85, 0xFC, 0x23, 0x4F, 0xDE, + 0x2C, 0x1F, 0x94, 0x58, 0x9D, 0xDF, 0x63, 0x5D, 0x6A, 0xB0, 0x4B, 0x95, 0xB5, 0xE4, 0xFC, 0xA4, 0x91, 0xE4, 0x02, 0x0B, + 0xC1, 0x66, 0xFE, 0xD2, 0xB5, 0x2F, 0x95, 0xDF, 0x97, 0x60, 0x74, 0xA2, 0x51, 0x8E, 0xB3, 0x1B, 0xCA, 0xAC, 0x37, 0x5B, + 0xD1, 0x15, 0x66, 0x90, 0x80, 0x7E, 0x7D, 0xB3, 0x71, 0x66, 0xBC, 0x0E, 0xB1, 0x62, 0x2F, 0xFA, 0x57, 0xDF, 0x2E, 0x53, + 0xE0, 0x8F, 0x30, 0x8F, 0x02, 0x96, 0x6C, 0x6F, 0x00, 0x05, 0x8D, 0x1B, 0xE1, 0x7F, 0x29, 0xCE, 0x52, 0x16, 0x84, 0x30, + 0x2A, 0x72, 0xBB, 0xAA, 0x40, 0xAB, 0x42, 0xEC, 0x89, 0x10, 0xEE, 0x54, 0x98, 0xDB, 0xA8, 0x3A, 0x40, 0x35, 0x6C, 0x24, + 0xDF, 0xE6, 0xF8, 0xD4, 0xBD, 0xAA, 0xE6, 0x0E, 0x88, 0xAA, 0x1D, 0xD8, 0x0E, 0x73, 0x9F, 0xA5, 0xCE, 0x99, 0x6F, 0x51, + 0x04, 0xF9, 0x71, 0xC1, 0xCD, 0x44, 0xA9, 0x22, 0x27, 0x03, 0xB3, 0xD2, 0x97, 0x5B, 0x67, 0x63, 0xE3, 0x2B, 0x24, 0x1E, + 0x40, 0x37, 0x15, 0x72, 0xBC, 0x17, 0xFF, 0x91, 0xF3, 0x37, 0x63, 0xA8, 0x73, 0x0F, 0x2D, 0x4E, 0xD4, 0x85, 0xB7, 0x86, + 0x8A, 0x9C, 0xB4, 0xC6, 0x8E, 0xB4, 0x66, 0xAA, 0xB4, 0x85, 0x9F, 0xC7, 0xDE, 0x69, 0x38, 0xBB, 0xD8, 0x85, 0x6E, 0xFF, + 0x61, 0x45, 0x17, 0x90, 0x19, 0x2E, 0xEF, 0x89, 0x09, 0x35, 0x20, 0xB3, 0x0A, 0x6F, 0xA6, 0x76, 0x9D, 0x46, 0x30, 0x43, + 0x00, 0x54, 0x24, 0x5B, 0xE9, 0x86, 0xE2, 0xBA, 0x05, 0x97, 0x9C, 0xCD, 0xE4, 0x74, 0xE9, 0xA7, 0xDD, 0xD1, 0x96, 0xA8, + 0xF8, 0x9B, 0xF1, 0xFF, 0x87, 0x78, 0xF6, 0x59, 0x35, 0x5F, 0x25, 0x03, 0x9C, 0x1F, 0xE6, 0x17, 0xD7, 0x70, 0xC7, 0x4E, + 0x9B, 0x17, 0x17, 0x4F, 0x3A, 0x95, 0x2A, 0x03, 0x16, 0xEF, 0x37, 0x8F, 0x49, 0x1B, 0x6F, 0x06, 0x40, 0x5B, 0x85, 0x40, + 0x9F, 0x80, 0x1F, 0xBD, 0xD4, 0x5D, 0x26, 0xDA, 0x5A, 0x00, 0xF1, 0xF1, 0x88, 0x9D, 0x41, 0xED, 0x48, 0xBE, 0x1B, 0x87, + 0x95, 0x6C, 0x4F, 0x02, 0xF5, 0x7F, 0x50, 0x36, 0x06, 0xB1, 0x92, 0x4C, 0xAA, 0xE0, 0xDD, 0x49, 0xD3, 0x5C, 0x80, 0xC8, + 0xF9, 0xEC, 0x59, 0x70, 0x27, 0xE7, 0x99, 0x75, 0x0D, 0xFD, 0x91, 0x86, 0x0D, 0x86, 0x05, 0x45, 0x2F, 0x87, 0x14, 0x22, + 0x01, 0x9F, 0xF7, 0xF5, 0x97, 0x5E, 0x5C, 0x40, 0x41, 0xD5, 0x46, 0x13, 0x34, 0x85, 0x3A, 0x46, 0x88, 0xCB, 0x71, 0xDF, + 0x10, 0x54, 0x4E, 0x57, 0xA6, 0x45, 0x74, 0x80, 0x65, 0x67, 0x90, 0xA2, 0x47, 0xEE, 0xD0, 0x66, 0x37, 0x0A, 0x00, 0xC2, + 0xBB, 0x6A, 0x80, 0xF4, 0xB9, 0x57, 0x60, 0xB3, 0x8A, 0xE0, 0x85, 0x34, 0xEE, 0x07, 0x69, 0x90, 0x42, 0x6B, 0x09, 0xE5, + 0x38, 0xED, 0x5B, 0x62, 0x03, 0x28, 0x49, 0x25, 0xF5, 0x40, 0xDD, 0x0C, 0x64, 0x4C, 0x81, 0x05, 0x55, 0x00, 0xD8, 0x02, + 0xE8, 0x87, 0x35, 0xF1, 0xE9, 0xCB, 0x3A, 0x32, 0xA7, 0x8C, 0xC9, 0xDE, 0x54, 0x8E, 0x17, 0x2B, 0x89, 0x95, 0x81, 0xBB, + 0xCC, 0xB5, 0xDB, 0xC1, 0xBC, 0xFF, 0x41, 0xCE, 0x51, 0x8F, 0xB3, 0xA4, 0x7B, 0xBA, 0x58, 0x74, 0xB2, 0x15, 0x88, 0xA4, + 0x3B, 0x77, 0xCC, 0xDF, 0xD8, 0x8C, 0xD3, 0x68, 0x2E, 0x9B, 0x7F, 0x55, 0x9F, 0x45, 0x40, 0x26, 0x06, 0xC4, 0x44, 0x1B, + 0x2C, 0x24, 0xC2, 0x39, 0xAD, 0x2F, 0x9C, 0x49, 0x3A, 0x5D, 0xA2, 0x5B, 0x22, 0x63, 0xAE, 0x8C, 0x3D, 0x8C, 0x02, 0x5D, + 0x8C, 0xC9, 0x39, 0xAD, 0x93, 0xA0, 0x04, 0x7D, 0xEE, 0x32, 0x02, 0x5A, 0x3C, 0xAE, 0xC7, 0xB8, 0x02, 0xCF, 0x9D, 0x49, + 0xFD, 0x4B, 0xD3, 0x19, 0xAC, 0x69, 0x0B, 0x1D, 0xED, 0xE6, 0x12, 0x29, 0x01, 0x84, 0x12, 0x78, 0x3E, 0x1E, 0xEB, 0x99, + 0xAC, 0x99, 0xED, 0x4A, 0x34, 0xAB, 0x5C, 0xB0, 0x5C, 0x0C, 0x43, 0x75, 0x97, 0xED, 0x99, 0x49, 0x57, 0xC2, 0x4C, 0x82, + 0xC4, 0xB4, 0x11, 0x8D, 0x86, 0x14, 0xCB, 0xD2, 0x96, 0xAC, 0xE8, 0x4C, 0x9C, 0xB2, 0x18, 0x74, 0xF1, 0xB3, 0x74, 0xB2, + 0x07, 0x2D, 0x46, 0xC3, 0x17, 0x8F, 0x8A, 0x9E, 0x1B, 0x0F, 0x93, 0xA0, 0x57, 0xFC, 0x3E, 0xC8, 0xCF, 0x9C, 0xCE, 0xC6, + 0x16, 0xF2, 0x42, 0xC9, 0xCB, 0x4C, 0xF9, 0x5C, 0xF3, 0xD1, 0x5E, 0x72, 0xC0, 0x3B, 0xBA, 0x24, 0x76, 0x19, 0x4E, 0x0C, + 0xDD, 0xCB, 0x64, 0x0E, 0x50, 0xB9, 0x93, 0xB4, 0x47, 0xE3, 0x92, 0xD0, 0xDE, 0xBA, 0x47, 0xB8, 0xFE, 0x68, 0x07, 0x89, + 0xF8, 0x23, 0xC1, 0x2B, 0xC2, 0x9B, 0x74, 0xF5, 0xD6, 0xEB, 0xB5, 0x63, 0x3F, 0xCA, 0xAB, 0x05, 0xFA, 0x72, 0x13, 0xD5, + 0x46, 0x14, 0xBF, 0x95, 0x5C, 0xD3, 0x50, 0xBD, 0x12, 0x8B, 0x6D, 0xB0, 0x1E, 0xE6, 0x5D, 0xE5, 0xF8, 0x97, 0x9F, 0xEE, + 0x60, 0x25, 0x8B, 0x0F, 0xD3, 0xDA, 0xCB, 0x2A, 0x76, 0xC7, 0x93, 0x85, 0x8E, 0x1C, 0x6A, 0x65, 0xC8, 0xDB, 0x3C, 0xD5, + 0xF7, 0xA6, 0x62, 0xCC, 0xF3, 0x9C, 0x15, 0x75, 0x14, 0x95, 0x0B, 0x0A, 0x4F, 0x07, 0xD9, 0xAE, 0x76, 0xD2, 0x77, 0x2E, + 0x47, 0x77, 0x80, 0xC8, 0x0E, 0x4A, 0x54, 0xE0, 0xB3, 0x44, 0xB8, 0x71, 0x04, 0x56, 0x91, 0xB8, 0x34, 0xF4, 0x94, 0x39, + 0xA2, 0x91, 0xDC, 0x2C, 0x92, 0xFD, 0xDB, 0x95, 0xF3, 0x9D, 0xEC, 0xEC, 0xBC, 0xF8, 0x7C, 0x57, 0xC4, 0xD9, 0xDC, 0xEF, + 0x51, 0x26, 0x81, 0x89, 0x53, 0xBE, 0x3A, 0x2E, 0x01, 0x22, 0xF7, 0x23, 0x9E, 0xD3, 0xDA, 0x3E, 0x1D, 0x4E, 0x49, 0xD3, + 0x86, 0xD3, 0x67, 0x9C, 0xAA, 0x9C, 0x55, 0x6B, 0x49, 0x30, 0xEF, 0x20, 0x4E, 0x1C, 0x84, 0x0B, 0xCF, 0x2E, 0x40, 0xDB, + 0x00, 0x93, 0x3E, 0x08, 0xDE, 0xAF, 0xD2, 0x3B, 0xFB, 0x44, 0xEF, 0x52, 0x82, 0x40, 0xF2, 0x24, 0xBB, 0xE3, 0x76, 0xBD, + 0x25, 0xAC, 0x18, 0x2B, 0x45, 0xAC, 0x20, 0x01, 0xE0, 0xC0, 0xA6, 0x19, 0x39, 0x62, 0x52, 0x73, 0x42, 0x02, 0x3E, 0xE7, + 0xD8, 0xC3, 0x81, 0x52, 0xF4, 0xE3, 0xCB, 0xAA, 0xAC, 0x23, 0xD8, 0x9E, 0x34, 0x8A, 0x65, 0xEF, 0x6A, 0xFC, 0x9C, 0xC2, + 0x45, 0xCE, 0xE7, 0x33, 0x30, 0xC0, 0x72, 0x64, 0xEB, 0xB5, 0xE1, 0x32, 0x72, 0xDB, 0x12, 0x5F, 0x2B, 0x06, 0x8E, 0xB9, + 0x52, 0x23, 0xD8, 0xD2, 0xED, 0xD7, 0x33, 0x6F, 0x32, 0xBE, 0xE7, 0x96, 0xBF, 0x8C, 0x30, 0xF5, 0xD4, 0x05, 0x21, 0x7D, + 0x7A, 0x60, 0x3E, 0x37, 0xF0, 0xD9, 0x0E, 0xB0, 0xF1, 0xE6, 0x54, 0x8D, 0x0A, 0xA6, 0x71, 0xAE, 0x6A, 0x17, 0xC9, 0xD1, + 0xCF, 0x76, 0x99, 0x89, 0xE4, 0x5C, 0x63, 0x32, 0xE0, 0x93, 0x22, 0xE2, 0xE1, 0x3B, 0x02, 0x8D, 0x47, 0x2E, 0x40, 0x9E, + 0xA3, 0x2C, 0x03, 0xDF, 0xD4, 0x65, 0xB9, 0xB0, 0xF5, 0x3A, 0xF2, 0x0D, 0xF9, 0xA8, 0x24, 0x14, 0x21, 0x44, 0xCA, 0xCF, + 0xDD, 0xE4, 0x19, 0x0B, 0x1A, 0x4B, 0xF1, 0x0D, 0x39, 0x81, 0x29, 0xCB, 0x64, 0x0B, 0x03, 0x5E, 0xA0, 0xCB, 0xCB, 0x04, + 0xBD, 0x97, 0x0F, 0xE2, 0x78, 0x88, 0x0D, 0x5B, 0xA9, 0xFB, 0xCD, 0x05, 0x32, 0x0F, 0xAE, 0xD7, 0x2E, 0xF0, 0x7D, 0x60, + 0xE1, 0xB1, 0xD4, 0x17, 0xED, 0x48, 0x30, 0x2C, 0x03, 0x20, 0xE1, 0x7C, 0x89, 0xEA, 0xF2, 0x4F, 0x3A, 0x22, 0x05, 0xA9, + 0x78, 0xAD, 0xDA, 0x94, 0x53, 0x20, 0xFE, 0x16, 0x5F, 0x53, 0x10, 0xB7, 0x27, 0x8F, 0x93, 0x56, 0xAF, 0x0C, 0x56, 0x85, + 0x02, 0xA5, 0xAB, 0x5D, 0x81, 0x53, 0xF9, 0xA2, 0x16, 0x92, 0xE4, 0x9F, 0x37, 0xE6, 0xD9, 0x9B, 0x7E, 0x74, 0x3A, 0x20, + 0x40, 0x30, 0x82, 0xB6, 0xC4, 0x3F, 0x6C, 0x87, 0x9D, 0x5F, 0xC7, 0x9A, 0x16, 0x85, 0x9C, 0xF2, 0xDE, 0xBC, 0xB6, 0x7F, + 0x82, 0x70, 0x24, 0xF7, 0xBF, 0x8C, 0x4C, 0xB0, 0x2D, 0x20, 0xFA, 0xF3, 0x8E, 0xCD, 0x78, 0xCB, 0x45, 0x6E, 0x85, 0xC3, + 0x13, 0x37, 0x43, 0x5D, 0xF0, 0xC9, 0xDC, 0xA0, 0xCF, 0x0C, 0x49, 0x10, 0xF2, 0xC0, 0x07, 0xB3, 0x52, 0x12, 0xA3, 0x98, + 0x8D, 0xDC, 0x7A, 0xF8, 0x85, 0x55, 0xC5, 0xB7, 0x6D, 0x9D, 0xE3, 0x80, 0x64, 0xEF, 0x16, 0x82, 0x8D, 0x6F, 0x64, 0xD7, + 0xA2, 0x51, 0x48, 0xA7, 0x6C, 0xB7, 0xA3, 0x18, 0x2F, 0x18, 0x94, 0xF8, 0x75, 0x3C, 0x6D, 0xA3, 0x23, 0x19, 0xDD, 0x25, + 0xB6, 0x8D, 0x10, 0x09, 0xAA, 0x1B, 0x12, 0x83, 0x7F, 0x80, 0x65, 0x13, 0xC8, 0x19, 0x32, 0xF3, 0xA3, 0x50, 0x22, 0x19, + 0xFD, 0x1A, 0x68, 0x1D, 0xAD, 0x3A, 0xBC, 0x73, 0x2E, 0xB3, 0x79, 0xEA, 0xCF, 0xC5, 0x49, 0xA1, 0x9C, 0xBB, 0x36, 0xDF, + 0x4C, 0xAB, 0x2E, 0x72, 0xDC, 0x90, 0xF0, 0x20, 0xD8, 0xBF, 0x9E, 0xA5, 0x5D, 0xE6, 0xA0, 0x85, 0x05, 0xD6, 0x61, 0xF6, + 0x8C, 0x93, 0x6B, 0x13, 0x9C, 0xCC, 0xA0, 0x01, 0x9B, 0x5A, 0xE9, 0xAA, 0x59, 0x3B, 0x2F, 0x13, 0x8D, 0xCE, 0x8F, 0x6E, + 0xC3, 0x7A, 0x45, 0x21, 0x95, 0xF4, 0x3F, 0xCE, 0x89, 0xA8, 0x06, 0x68, 0x72, 0x4E, 0x26, 0xF9, 0x9E, 0x4C, 0x28, 0xB9, + 0xD6, 0xD5, 0xD4, 0x0A, 0xFA, 0x4C, 0xAE, 0xF0, 0x40, 0x95, 0x76, 0x2F, 0x7A, 0x2D, 0x9B, 0x9E, 0xD0, 0xFC, 0x36, 0xF9, + 0x7D, 0x66, 0xEF, 0xFC, 0x0E, 0x6E, 0x27, 0xE5, 0x89, 0x2E, 0x97, 0x11, 0x77, 0x45, 0x8E, 0x70, 0x1B, 0x31, 0x4F, 0x28, + 0xE2, 0x1F, 0x77, 0x2E, 0xF2, 0x24, 0x45, 0x02, 0x0A, 0x3C, 0x96, 0x79, 0xD2, 0x6D, 0x9B, 0x58, 0xDD, 0x7D, 0xD8, 0xF8, + 0x30, 0xBB, 0x4E, 0x24, 0xA5, 0x43, 0x88, 0x02, 0xDB, 0x1D, 0x3E, 0x1E, 0xEE, 0xC5, 0xAA, 0x24, 0xEA, 0xCF, 0x40, 0x15, + 0x61, 0x3E, 0xB8, 0x12, 0xDA, 0x4C, 0x0E, 0x27, 0xE7, 0xA1, 0x71, 0x61, 0xFF, 0xAD, 0xC3, 0xD0, 0x48, 0x4F, 0xD3, 0xB7, + 0x21, 0x64, 0x13, 0xA3, 0x6F, 0x2C, 0x97, 0x0B, 0x4B, 0xE2, 0x81, 0x74, 0x1B, 0x3C, 0x6A, 0xA5, 0xD5, 0x4E, 0x9F, 0xC0, + 0xE8, 0x56, 0x07, 0xB9, 0xE7, 0x02, 0xB0, 0x9A, 0x61, 0xDF, 0xD1, 0xF0, 0x57, 0x77, 0x8B, 0x76, 0x7C, 0x85, 0xF2, 0xAD, + 0xF6, 0xC6, 0xB5, 0x0D, 0x74, 0x15, 0xA1, 0xF4, 0x13, 0xE6, 0x59, 0xBD, 0x7B, 0xEA, 0x99, 0xB9, 0x2F, 0x07, 0x77, 0x1C, + 0x61, 0x84, 0xA8, 0x66, 0x37, 0xA9, 0xB4, 0xAC, 0xF0, 0x87, 0x92, 0xD3, 0xCB, 0xF6, 0xC1, 0x88, 0x63, 0xA5, 0x78, 0xD3, + 0xF5, 0xE7, 0x86, 0x68, 0x28, 0x27, 0x9C, 0x13, 0x9E, 0x79, 0x08, 0xB8, 0x4C, 0x17, 0xE5, 0x5E, 0xDC, 0x6E, 0x7F, 0x2A, + 0x05, 0x36, 0xD2, 0x0A, 0xF4, 0x48, 0xC5, 0x5C, 0x31, 0xA5, 0x45, 0x4C, 0x73, 0x36, 0x87, 0x69, 0x73, 0x27, 0x94, 0x88, + 0xB8, 0x01, 0x09, 0xD1, 0x37, 0x8B, 0x93, 0x0B, 0xB4, 0xE7, 0x11, 0xBE, 0x7E, 0xCA, 0x99, 0x3B, 0xF6, 0xA4, 0xFF, 0x1C, + 0x32, 0x46, 0xE0, 0x3F, 0xD9, 0x1B, 0xE2, 0x56, 0xB3, 0x97, 0xBB, 0x42, 0xEB, 0xE3, 0x48, 0xCF, 0x0F, 0xC8, 0x65, 0x86, + 0x00, 0x6C, 0xD2, 0x7E, 0x3C, 0x1E, 0xEE, 0x2D, 0x40, 0x2A, 0xAE, 0xDF, 0x0C, 0xC1, 0xA1, 0xCA, 0xDF, 0x6C, 0x71, 0x2D, + 0x71, 0x9C, 0xE2, 0x30, 0x39, 0x15, 0x8C, 0x18, 0xE3, 0x42, 0x0B, 0x29, 0xD2, 0xAC, 0x55, 0x76, 0x28, 0x9F, 0xEF, 0x5A, + 0xC5, 0xAB, 0xF4, 0x2B, 0xED, 0xB0, 0x3B, 0x87, 0xB9, 0xF4, 0x73, 0xBD, 0x52, 0x0B, 0x9A, 0x8A, 0x76, 0x4F, 0x94, 0xD0, + 0x06, 0x17, 0xCA, 0xA1, 0xD5, 0xB1, 0xAB, 0xBE, 0xAA, 0x3C, 0x3C, 0xE4, 0x96, 0x1C, 0x65, 0x96, 0xC0, 0x2E, 0x8B, 0x31, + 0x8A, 0x5C, 0x25, 0x7A, 0xB0, 0xD2, 0x9B, 0x26, 0x39, 0x44, 0x4B, 0xA4, 0x45, 0x93, 0x8B, 0x9B, 0x76, 0x23, 0x38, 0xE3, + 0x25, 0x15, 0xAC, 0xB0, 0x16, 0xD6, 0x64, 0x87, 0x40, 0x25, 0xAA, 0x30, 0xD1, 0x5E, 0x3A, 0x96, 0x26, 0x3F, 0x65, 0xA0, + 0xDD, 0x7C, 0x0F, 0x0A, 0x6E, 0x99, 0x9C, 0x24, 0xF5, 0xB0, 0x93, 0x56, 0x04, 0xFB, 0x2C, 0x36, 0xB8, 0xF7, 0x04, 0xC0, + 0x98, 0x00, 0x94, 0x94, 0x51, 0xF9, 0xEB, 0xC3, 0x47, 0x29, 0xE4, 0xA1, 0x5D, 0x5E, 0x88, 0x90, 0xC7, 0xA2, 0x9D, 0xE0, + 0x75, 0xF9, 0x51, 0xB1, 0x94, 0x65, 0x33, 0x19, 0x35, 0xBF, 0x05, 0x77, 0xBB, 0x86, 0xC5, 0xB5, 0x7B, 0xFB, 0x06, 0xAE, + 0xD7, 0x13, 0x9C, 0x6C, 0x90, 0xF9, 0xA6, 0x95, 0x58, 0x78, 0x35, 0x5F, 0xDF, 0x38, 0x14, 0x2A, 0xCB, 0x36, 0x99, 0x19, + 0x19, 0xD5, 0x47, 0xDC, 0x2D, 0x98, 0x5D, 0x9A, 0x82, 0x52, 0x44, 0xB6, 0x47, 0xDE, 0x99, 0xB7, 0x3E, 0x6B, 0xA6, 0x5B, + 0x94, 0x2B, 0x95, 0x51, 0x01, 0x96, 0x8B, 0xF9, 0x20, 0x2D, 0xC8, 0x6C, 0xD7, 0x36, 0x41, 0xBD, 0x04, 0xD4, 0xC7, 0xAF, + 0x14, 0xAA, 0xDE, 0xAA, 0x2A, 0xB1, 0x08, 0x3E, 0x2E, 0xB3, 0x2F, 0xE2, 0x9B, 0x93, 0x56, 0xFF, 0x5B, 0xFA, 0x6A, 0xBA, + 0x2B, 0xB0, 0xF6, 0x9E, 0x56, 0x30, 0xE4, 0x89, 0x42, 0xD6, 0x86, 0x3C, 0xFB, 0xF3, 0x14, 0xB8, 0xF1, 0x17, 0xD9, 0x12, + 0x31, 0x18, 0x76, 0x94, 0x49, 0x8B, 0x54, 0x47, 0x5F, 0x7E, 0xB9, 0xA8, 0x82, 0x94, 0x10, 0x5B, 0xC4, 0x1A, 0xFF, 0xD5, + 0x86, 0xC4, 0x5B, 0x3D, 0x5E, 0xBC, 0xA8, 0x21, 0x33, 0x25, 0x8F, 0x14, 0x92, 0xA7, 0x4B, 0x20, 0x88, 0xEA, 0x10, 0x45, + 0x32, 0x63, 0x68, 0xA2, 0x51, 0x0C, 0xFE, 0xF2, 0xB0, 0x4F, 0xD8, 0xD4, 0x60, 0x9A, 0xA2, 0xB6, 0xBB, 0xF6, 0xB9, 0x30, + 0xD3, 0x4D, 0x85, 0x67, 0x6F, 0x24, 0x43, 0x32, 0x87, 0xE1, 0x85, 0x21, 0xF9, 0xE1, 0xF6, 0x77, 0x0E, 0xF5, 0x6E, 0x55, + 0x9D, 0xDE, 0x2D, 0xCC, 0xE0, 0x36, 0xE1, 0xF3, 0x87, 0x65, 0x60, 0xA0, 0x00, 0xA9, 0x39, 0x36, 0xB1, 0x22, 0x68, 0x50, + 0x0E, 0xEB, 0x00, 0xE0, 0x5C, 0xB3, 0xCF, 0xD2, 0xE9, 0x3A, 0xA8, 0xE7, 0xA8, 0x28, 0x26, 0x77, 0xA2, 0x4A, 0x29, 0x0F, + 0xF0, 0xC8, 0x4A, 0x71, 0x03, 0xA9, 0xB7, 0xDC, 0x33, 0xD9, 0xF1, 0x13, 0xA0, 0x81, 0xE9, 0x9E, 0xD4, 0x04, 0x31, 0x76, + 0x62, 0x08, 0xB1, 0x72, 0x32, 0xDF, 0xED, 0x0A, 0x60, 0x57, 0x4F, 0x44, 0x72, 0x25, 0x0A, 0x18, 0xE9, 0x13, 0xDA, 0x05, + 0x9A, 0x8F, 0xD8, 0x06, 0x03, 0xF3, 0x64, 0xCD, 0xFB, 0xC7, 0xCA, 0x61, 0x82, 0x08, 0xF2, 0x1E, 0x15, 0x41, 0xC2, 0xE7, + 0xA8, 0xE6, 0x1A, 0xB8, 0x60, 0xB4, 0xB5, 0xEF, 0x0D, 0xCB, 0x7B, 0x6F, 0xF0, 0xB0, 0x0B, 0xD1, 0x60, 0x08, 0x12, 0xDE, + 0x80, 0x91, 0x4D, 0x1C, 0x8F, 0x70, 0x84, 0x15, 0x70, 0x53, 0x92, 0xBD, 0xF8, 0x25, 0x87, 0x8D, 0x38, 0x6D, 0xBA, 0x4A, + 0x04, 0xB1, 0xBA, 0xCE, 0xF0, 0x7B, 0xEA, 0x93, 0xB7, 0xED, 0x12, 0x7F, 0xA1, 0xE7, 0x84, 0x88, 0x8F, 0x04, 0x32, 0x3E, + 0x96, 0xDB, 0x5F, 0x8B, 0xCF, 0xC0, 0x7A, 0x0E, 0x39, 0xAA, 0x31, 0x4D, 0xD6, 0xA3, 0xFB, 0xB2, 0x18, 0x89, 0x6B, 0x58, + 0x6B, 0xCF, 0x16, 0x5C, 0xB6, 0xC1, 0x4E, 0xA8, 0xD7, 0x93, 0x83, 0x58, 0xF0, 0xDF, 0x09, 0xCF, 0x20, 0x2B, 0xA5, 0x7A, + 0x22, 0x60, 0x90, 0x10, 0x26, 0x89, 0xCC, 0x81, 0x12, 0xE2, 0x74, 0x17, 0x4B, 0x5F, 0x81, 0xD7, 0x64, 0x1E, 0x5C, 0xBD, + 0x2D, 0x53, 0xF2, 0x8D, 0xB3, 0xD6, 0x45, 0x87, 0xC6, 0xFC, 0x80, 0x9D, 0xF3, 0x96, 0xE0, 0x05, 0xD3, 0x6F, 0x00, 0xF7, + 0x5B, 0x62, 0x6B, 0xF9, 0x0B, 0x02, 0xF7, 0xA7, 0xF1, 0x32, 0x45, 0xCF, 0x1D, 0xD9, 0xD1, 0x77, 0x31, 0x83, 0x96, 0x51, + 0xF3, 0x48, 0xC1, 0xD7, 0xD2, 0x33, 0xFC, 0x3F, 0x55, 0x14, 0xDC, 0xC1, 0x93, 0xB4, 0x74, 0x3D, 0xE5, 0xA6, 0x8E, 0x68, + 0x1A, 0x24, 0xF3, 0x32, 0x33, 0x58, 0xF2, 0xD8, 0xBE, 0xB3, 0x24, 0x74, 0x7D, 0x4D, 0x2E, 0x07, 0xFF, 0xC8, 0xF1, 0xBF, + 0x01, 0x73, 0xBD, 0xC1, 0xC1, 0xEC, 0x35, 0xA1, 0x0C, 0xDB, 0xAB, 0xE3, 0x13, 0xF5, 0x32, 0x29, 0xA3, 0x72, 0x4D, 0x15, + 0xFB, 0x75, 0x9D, 0xA1, 0xB6, 0x54, 0xA5, 0x05, 0x6D, 0x86, 0xB7, 0x59, 0xC9, 0xA7, 0xE6, 0x3F, 0xF7, 0x35, 0x23, 0xCE, + 0x97, 0x51, 0x8A, 0x85, 0x7E, 0x98, 0xCE, 0x6C, 0xF5, 0x5B, 0xB6, 0x67, 0x3F, 0x28, 0x15, 0x49, 0xCA, 0x49, 0x86, 0xB8, + 0x70, 0x6E, 0xD8, 0xE9, 0xDF, 0xAF, 0x78, 0x0F, 0x52, 0x04, 0xD7, 0x6F, 0xC4, 0xF5, 0x18, 0xD2, 0x99, 0x5A, 0xDB, 0xB7, + 0x2B, 0xBC, 0x8F, 0x1F, 0x5B, 0xA9, 0x2D, 0x3B, 0x03, 0xB5, 0xA1, 0xE4, 0xD8, 0x3B, 0x7D, 0x2A, 0x86, 0xA1, 0x02, 0x57, + 0xC5, 0x7D, 0x46, 0xFC, 0x8B, 0xE3, 0x16, 0x68, 0x0B, 0x83, 0xFA, 0xA7, 0x88, 0x78, 0x31, 0xAE, 0x59, 0xC2, 0xF6, 0x65, + 0xE9, 0x59, 0xA6, 0x78, 0x3D, 0x1E, 0x3F, 0xEE, 0x5F, 0x11, 0xF9, 0xC1, 0xDA, 0xC1, 0xA8, 0x6D, 0x9B, 0x03, 0x17, 0x69, + 0x0C, 0x83, 0x74, 0x3B, 0x07, 0xA2, 0x34, 0xAE, 0xAF, 0x51, 0x01, 0x9B, 0xE5, 0x3D, 0x73, 0x62, 0xC8, 0x3C, 0xBB, 0x86, + 0x7A, 0x0C, 0xF8, 0x17, 0x27, 0x95, 0x50, 0x20, 0x2F, 0xCD, 0xC6, 0x9C, 0xF7, 0xAC, 0xF1, 0x31, 0x3A, 0x88, 0xF1, 0x35, + 0xB2, 0xA7, 0x72, 0xAF, 0x65, 0xCC, 0xDA, 0x37, 0x54, 0x71, 0xFA, 0x90, 0xFB, 0x8B, 0x19, 0x67, 0xFB, 0x2F, 0xCE, 0xA6, + 0xCA, 0xA0, 0x72, 0x54, 0x8D, 0x8C, 0x77, 0x53, 0x89, 0x28, 0xDF, 0xC1, 0x34, 0xA8, 0xBD, 0xB7, 0xA6, 0x7B, 0x83, 0xC4, + 0x8C, 0x4C, 0xA0, 0x12, 0x55, 0x9F, 0x1F, 0xC4, 0xFC, 0x16, 0x4A, 0x80, 0xEA, 0x79, 0xCE, 0x53, 0x3E, 0xE9, 0x74, 0x73, + 0x34, 0x60, 0x90, 0x24, 0xFC, 0xF5, 0x40, 0x62, 0xE4, 0xC1, 0xA2, 0xF9, 0x3F, 0x04, 0xD7, 0xA5, 0x03, 0xE7, 0xD9, 0xA7, + 0x92, 0x26, 0x09, 0xE1, 0x2C, 0x74, 0x31, 0xE3, 0xE3, 0x59, 0xD1, 0x23, 0x83, 0x8E, 0x89, 0xE4, 0x34, 0xA8, 0x55, 0x82, + 0x9B, 0x5B, 0x87, 0x71, 0x36, 0x64, 0x2E, 0x0A, 0x77, 0x81, 0x23, 0x8C, 0xF6, 0xE7, 0x62, 0x0F, 0x5E, 0xA4, 0xB5, 0xC6, + 0xB0, 0xA7, 0xF8, 0x9E, 0x6E, 0x2B, 0x5C, 0xFF, 0xBE, 0x04, 0x22, 0xBB, 0xAC, 0xD2, 0x84, 0x32, 0xD0, 0x6F, 0x78, 0x84, + 0x8A, 0x73, 0xDB, 0xFC, 0x88, 0xAC, 0x0D, 0x77, 0x06, 0x92, 0xD3, 0x9C, 0x77, 0xE5, 0x7B, 0x8A, 0xC9, 0xC9, 0xA4, 0xD8, + 0x5F, 0x8B, 0x0E, 0xDD, 0x48, 0xAA, 0xBB, 0xFF, 0xD9, 0xC2, 0xE2, 0x2B, 0x26, 0x21, 0x82, 0xFD, 0xB9, 0xA3, 0x48, 0x82, + 0xA2, 0x83, 0x00, 0x9D, 0xD2, 0x51, 0xEA, 0x3B, 0x27, 0xCF, 0x9C, 0x88, 0xF6, 0xD5, 0x44, 0x23, 0xAD, 0xED, 0x0F, 0x8E, + 0x41, 0x1C, 0xAD, 0x9B, 0x0A, 0x85, 0x23, 0xA2, 0x71, 0xA8, 0x0D, 0x33, 0x4E, 0xF7, 0x8B, 0x7E, 0xB2, 0xEA, 0x61, 0x83, + 0xBC, 0x0A, 0x93, 0xB7, 0x27, 0xE2, 0x7D, 0x09, 0x24, 0x77, 0x3B, 0xFB, 0x13, 0x50, 0x51, 0xE0, 0x4C, 0x48, 0x9C, 0x79, + 0xBB, 0x36, 0x4C, 0x20, 0x8E, 0xEE, 0xB8, 0x0C, 0x56, 0x91, 0xD9, 0x70, 0x06, 0x31, 0xFE, 0x14, 0xDF, 0x26, 0xA5, 0xE7, + 0x63, 0x59, 0xC1, 0x5B, 0x51, 0x4E, 0x5D, 0xE1, 0x26, 0x35, 0xA5, 0x47, 0xB0, 0x9B, 0x6F, 0x4D, 0x47, 0x90, 0xBB, 0x5B, + 0x1E, 0x09, 0x4D, 0x20, 0x0A, 0x13, 0x95, 0xA6, 0xE6, 0xBC, 0xAA, 0x73, 0xA5, 0xDE, 0x7D, 0x4E, 0xDE, 0xE8, 0x1C, 0xB0, + 0x8A, 0x9B, 0x86, 0x86, 0x37, 0x1E, 0xB0, 0x32, 0x38, 0xD7, 0x0C, 0x0E, 0x4C, 0xB9, 0xD8, 0x30, 0xA5, 0x32, 0xCC, 0x16, + 0x62, 0x18, 0xC4, 0x70, 0x8D, 0x67, 0x50, 0x69, 0x9C, 0x25, 0xD1, 0x21, 0x0A, 0x99, 0xDB, 0xCB, 0x39, 0x30, 0x4D, 0xEA, + 0xD5, 0x77, 0x0A, 0x0F, 0xFF, 0xBB, 0x2A, 0x31, 0x25, 0x30, 0x6C, 0x90, 0xB9, 0x18, 0x05, 0xF1, 0xBB, 0x7A, 0x9D, 0x44, + 0xD1, 0xFA, 0x5E, 0x66, 0x84, 0xE3, 0xF6, 0x12, 0x78, 0xB5, 0x20, 0x72, 0xCF, 0xDE, 0x00, 0xC8, 0x87, 0x7F, 0x85, 0xF4, + 0xF8, 0x9F, 0x2F, 0x1C, 0xD7, 0x2E, 0x3B, 0x38, 0xED, 0x8C, 0xF4, 0xB8, 0x8A, 0x74, 0x3F, 0xD4, 0x11, 0x66, 0x0B, 0x1D, + 0xF8, 0xB0, 0x9C, 0x66, 0x4D, 0xD3, 0xB3, 0x36, 0x15, 0x10, 0x0F, 0x5F, 0x0C, 0x24, 0x97, 0xD8, 0x63, 0xB1, 0x07, 0xDB, + 0xE1, 0xB3, 0xE7, 0xBA, 0x08, 0x72, 0x21, 0xA8, 0xD1, 0xF0, 0x67, 0xBC, 0xD5, 0x5D, 0xF7, 0xFA, 0xEC, 0x7B, 0x09, 0x9E, + 0x32, 0xF5, 0x37, 0xE8, 0x8A, 0x22, 0x6F, 0x1E, 0x49, 0x10, 0x76, 0xBA, 0x63, 0x56, 0xE6, 0xFB, 0x82, 0xF6, 0x05, 0xDA, + 0xAD, 0x3D, 0xD9, 0xFA, 0x33, 0x18, 0x30, 0x09, 0x61, 0x58, 0xF6, 0x90, 0x9F, 0xDE, 0xD0, 0xEA, 0x0E, 0x3E, 0x79, 0xEE, + 0x1E, 0x3E, 0x77, 0x19, 0x6D, 0x78, 0x79, 0x17, 0x91, 0x74, 0x04, 0xE6, 0x80, 0x80, 0x40, 0x9A, 0x7B, 0x2F, 0xA3, 0x08, + 0xBC, 0x71, 0x27, 0xD4, 0x71, 0xC1, 0xC8, 0x80, 0x65, 0xFE, 0x9A, 0x75, 0x17, 0x63, 0x4D, 0xB4, 0x1D, 0xD2, 0x58, 0xA5, + 0x51, 0x65, 0x3B, 0xE9, 0xEE, 0x4D, 0x05, 0x76, 0xFC, 0xA7, 0x2F, 0x2D, 0xC6, 0xC0, 0x07, 0xD6, 0x54, 0xEF, 0xE5, 0x61, + 0x01, 0x85, 0xBF, 0xE4, 0x32, 0x43, 0xBA, 0x19, 0x1D, 0x72, 0x20, 0x0A, 0xC5, 0x21, 0x80, 0xC4, 0xF8, 0x09, 0x5C, 0xC0, + 0x1C, 0x8B, 0x54, 0x00, 0x56, 0x5F, 0xCD, 0x9A, 0x42, 0x26, 0x0A, 0xEE, 0x05, 0xA7, 0x17, 0x55, 0x37, 0x67, 0x15, 0x04, + 0xBD, 0x65, 0x3B, 0xB4, 0x47, 0x75, 0x21, 0xF7, 0x8A, 0x44, 0x2D, 0xDB, 0x93, 0x46, 0x44, 0x07, 0x3D, 0x04, 0x11, 0x0C, + 0x29, 0x08, 0x19, 0xE3, 0xFA, 0x94, 0x09, 0xD6, 0x64, 0x8A, 0xDD, 0x8C, 0xCB, 0x06, 0x19, 0xF1, 0xEA, 0xF8, 0xA2, 0x48, + 0x5C, 0xF5, 0xBC, 0x39, 0xF8, 0xA9, 0x2C, 0x24, 0x4E, 0xCA, 0xC2, 0x2C, 0x84, 0xA9, 0x42, 0x0D, 0xE8, 0x0F, 0xAA, 0xD6, + 0xF0, 0x79, 0xDA, 0x25, 0x3B, 0x0B, 0x65, 0xCD, 0x3D, 0x96, 0x19, 0x0B, 0x4A, 0xCE, 0x1B, 0x89, 0xDA, 0xB5, 0x46, 0xAD, + 0x8E, 0x28, 0xB3, 0x39, 0xB3, 0x9A, 0xFD, 0xF9, 0x2A, 0x0F, 0xD5, 0xFF, 0x95, 0x0E, 0xDB, 0x42, 0x4B, 0xAC, 0x5B, 0xB8, + 0x03, 0xC6, 0x22, 0x0A, 0xBF, 0x01, 0xC3, 0x8B, 0xCC, 0x24, 0x0B, 0x58, 0xEF, 0x73, 0xED, 0xAB, 0x88, 0x64, 0x3C, 0xB7, + 0xD6, 0x02, 0xF4, 0x51, 0xF9, 0x6D, 0x52, 0x44, 0xB7, 0x5D, 0xE1, 0x3B, 0x8D, 0x65, 0xBC, 0x6E, 0x2B, 0x08, 0x47, 0xB0, + 0x92, 0x6F, 0x6D, 0x61, 0x45, 0x78, 0x57, 0x90, 0xD2, 0x2F, 0xFF, 0x26, 0x28, 0x09, 0x48, 0x2E, 0xCB, 0x41, 0x80, 0x79, + 0xD9, 0x02, 0xDE, 0x95, 0xA7, 0x2D, 0xF6, 0x7D, 0x3E, 0x8B, 0x1C, 0x00, 0x36, 0x95, 0xE2, 0x3D, 0xC1, 0xAF, 0xE6, 0xA3, + 0x38, 0xDB, 0x8D, 0x14, 0x13, 0x11, 0x10, 0x10, 0x37, 0x94, 0x14, 0xB8, 0xE3, 0xB6, 0x23, 0x06, 0xB1, 0x11, 0xF7, 0x78, + 0x3E, 0x67, 0x45, 0x14, 0xDE, 0xB3, 0x2B, 0xA8, 0x6D, 0xA4, 0x12, 0x38, 0x70, 0x92, 0x53, 0xB9, 0xA1, 0xB7, 0x4D, 0x04, + 0xDF, 0xB2, 0x5E, 0x41, 0xE9, 0x5C, 0xC3, 0xA8, 0xD1, 0x31, 0x7C, 0x3F, 0x8E, 0x19, 0xC0, 0xE0, 0xDB, 0xA4, 0x94, 0x70, + 0x2D, 0x5C, 0x8D, 0xCD, 0x74, 0x36, 0x34, 0xF7, 0xDE, 0x1A, 0x95, 0xE8, 0x35, 0x77, 0x03, 0xF5, 0x65, 0x37, 0x64, 0x0A, + 0x75, 0x37, 0x25, 0x77, 0xAA, 0xEA, 0xDF, 0xC1, 0x91, 0xE7, 0xD1, 0x1C, 0xEA, 0x17, 0xF7, 0x1A, 0xC1, 0xC7, 0x14, 0x75, + 0x06, 0xE8, 0xD0, 0x2B, 0x3E, 0x91, 0x7E, 0xB1, 0xEF, 0xAC, 0xFB, 0xB2, 0x2D, 0x7D, 0x07, 0xA1, 0x94, 0x28, 0x9C, 0x08, + 0x3E, 0x9D, 0x36, 0xB9, 0x89, 0x5E, 0xD0, 0x0C, 0xFA, 0xDF, 0x98, 0xEB, 0x45, 0x75, 0x90, 0x18, 0x7B, 0xA6, 0x9F, 0xFF, + 0xAB, 0x19, 0xE6, 0x3E, 0xF9, 0xD2, 0xDE, 0x89, 0x49, 0xB5, 0x47, 0x1C, 0xD6, 0xBB, 0xE1, 0x31, 0x4B, 0xF7, 0xEA, 0x4F, + 0x54, 0xF7, 0x69, 0x95, 0xAA, 0x1A, 0xBB, 0xAD, 0x50, 0x6B, 0x57, 0xBD, 0x41, 0xB2, 0xA7, 0x42, 0xF7, 0x19, 0x26, 0x7E, + 0x26, 0x91, 0xC3, 0x0C, 0x6A, 0x2E, 0x52, 0xCC, 0x59, 0xAF, 0x14, 0x1C, 0xE4, 0xAD, 0x51, 0xAB, 0x7F, 0x12, 0xA8, 0xD5, + 0x38, 0x5D, 0xDD, 0x10, 0x5B, 0x10, 0x69, 0xF5, 0x7D, 0xC6, 0x3F, 0xB6, 0xAC, 0xBC, 0x07, 0x49, 0x83, 0x52, 0xEF, 0x17, + 0x08, 0x1E, 0x17, 0x69, 0x8B, 0xC1, 0x16, 0xFC, 0x0E, 0x0F, 0x10, 0xDC, 0x9F, 0x24, 0xA0, 0x11, 0x8F, 0x12, 0x43, 0x79, + 0xF5, 0xD0, 0xA2, 0x80, 0xEA, 0x8B, 0x3C, 0x74, 0xFF, 0x41, 0xF7, 0x5D, 0xE7, 0xC6, 0x22, 0x61, 0x96, 0xE0, 0xFB, 0x81, + 0xE4, 0x9A, 0x29, 0xD6, 0x3B, 0xE3, 0xF8, 0xB6, 0xBF, 0xCC, 0x86, 0x02, 0x97, 0xF0, 0x7B, 0x02, 0x27, 0xC0, 0x9F, 0x32, + 0x19, 0x04, 0xC7, 0xBF, 0x2D, 0xF3, 0xF9, 0x23, 0x5D, 0x3B, 0xF8, 0xF5, 0xB6, 0x70, 0x6D, 0xB9, 0xFE, 0xAC, 0x95, 0xBC, + 0x24, 0x95, 0xB1, 0x33, 0x5C, 0x3A, 0x48, 0x38, 0xA7, 0x7B, 0x82, 0x56, 0x15, 0x44, 0x97, 0x99, 0xA7, 0x12, 0x30, 0x0F, + 0xDB, 0x52, 0x17, 0x0D, 0xA4, 0xE0, 0xEC, 0x96, 0x1B, 0x5E, 0xBC, 0xF7, 0x04, 0x36, 0x68, 0x9E, 0x6F, 0xA7, 0xD5, 0x21, + 0x04, 0x21, 0xDF, 0x5F, 0x1B, 0x20, 0x0A, 0x8B, 0xE0, 0x8B, 0xB9, 0x62, 0xA9, 0xC6, 0xD6, 0xB1, 0x05, 0x8B, 0xED, 0x73, + 0x91, 0x25, 0xA0, 0x73, 0xBF, 0x78, 0x39, 0x65, 0x28, 0x89, 0xDA, 0xE2, 0x68, 0x03, 0x20, 0x8A, 0x1A, 0x7E, 0x3A, 0x22, + 0xCE, 0x2F, 0x94, 0x1A, 0x00, 0xAA, 0xD2, 0xF2, 0x29, 0xC6, 0xB6, 0x9A, 0x1B, 0x0C, 0x1A, 0x2B, 0xAC, 0xCF, 0x1A, 0x2F, + 0xBC, 0x46, 0xDC, 0xED, 0xBF, 0xF9, 0x63, 0x9E, 0xF2, 0x2B, 0x74, 0xDB, 0xC4, 0xC5, 0xF5, 0x8F, 0x23, 0x6D, 0x72, 0xB3, + 0x2A, 0x50, 0x6B, 0x8E, 0xF3, 0x2A, 0xCD, 0xA2, 0x6E, 0xCD, 0x3C, 0x3D, 0xDF, 0x16, 0x9B, 0x28, 0xF1, 0xE9, 0x70, 0x3E, + 0x52, 0xA5, 0xCB, 0xD2, 0xBD, 0xF1, 0x94, 0x66, 0x5F, 0x7C, 0xC5, 0xB8, 0xA3, 0x70, 0xD2, 0xA1, 0xEA, 0xC1, 0x85, 0x04, + 0xD9, 0x12, 0x3A, 0xFB, 0xF6, 0xE5, 0x5B, 0xC9, 0x64, 0x71, 0xE4, 0xCD, 0x70, 0x7C, 0x8E, 0x2C, 0x33, 0xB8, 0x4C, 0xFC, + 0xCE, 0x11, 0x13, 0xD9, 0x0E, 0x10, 0x0C, 0x9F, 0x93, 0x54, 0x97, 0x04, 0x15, 0x52, 0x7F, 0x82, 0xD7, 0xAE, 0x7E, 0x0F, + 0x4C, 0x71, 0xFA, 0x64, 0x70, 0x35, 0x0A, 0xAE, 0xA6, 0xD2, 0x70, 0x76, 0x2A, 0xF1, 0x39, 0x61, 0x1D, 0x1C, 0x2D, 0xD1, + 0xF7, 0xB3, 0x02, 0xBE, 0xE8, 0x57, 0xBC, 0x32, 0x43, 0x66, 0xE5, 0x07, 0x68, 0x33, 0x5A, 0x85, 0x84, 0x1F, 0x3D, 0xA7, + 0x4C, 0x3B, 0x8D, 0xA2, 0xF2, 0xEA, 0x7B, 0xBB, 0x4E, 0x82, 0xA5, 0xBF, 0x5C, 0xE3, 0x3C, 0xF3, 0xC3, 0x5E, 0xDD, 0x04, + 0x4A, 0xB1, 0xA4, 0x52, 0x94, 0x8F, 0xF3, 0x42, 0x30, 0x8D, 0x98, 0x7D, 0x67, 0xB4, 0x18, 0x78, 0x77, 0x94, 0xAC, 0x42, + 0x95, 0x60, 0xE4, 0x52, 0x31, 0x62, 0x90, 0x60, 0x63, 0xDD, 0xFC, 0xD2, 0xF5, 0xFD, 0x69, 0xA5, 0x95, 0xA5, 0x1A, 0x00, + 0x60, 0xBE, 0xAA, 0xE2, 0xC2, 0x0B, 0x2A, 0xE6, 0xD2, 0x0D, 0xFF, 0xF7, 0xCC, 0x67, 0xD5, 0x29, 0x4A, 0xDB, 0xF9, 0x0E, + 0xEF, 0x96, 0x4B, 0x95, 0x00, 0xF1, 0x7C, 0x05, 0x44, 0x79, 0xC4, 0xCE, 0x3F, 0xF9, 0x48, 0x9F, 0x85, 0x39, 0xF0, 0xC7, + 0x95, 0xC8, 0xD3, 0xE8, 0x1B, 0xC6, 0x38, 0xD9, 0xF7, 0xE9, 0x2A, 0x3E, 0x63, 0x8E, 0x41, 0x3C, 0x97, 0x06, 0xE7, 0x0F, + 0xDD, 0xEB, 0x9D, 0x7C, 0xD0, 0x17, 0x9B, 0x38, 0xF8, 0xD0, 0xCF, 0x2B, 0xFA, 0xDC, 0x29, 0xAE, 0x2D, 0xA5, 0xE7, 0x82, + 0xBB, 0xF9, 0x61, 0x59, 0xE1, 0x99, 0x85, 0x5D, 0x51, 0x06, 0x99, 0x37, 0xD1, 0xDD, 0x05, 0x8E, 0x58, 0x47, 0x2F, 0x46, + 0xCB, 0x5B, 0xFE, 0xD9, 0xDF, 0x90, 0x14, 0xBA, 0x3F, 0xDF, 0xF4, 0xDB, 0x1C, 0x0C, 0xBE, 0x7E, 0x56, 0x22, 0x7A, 0x39, + 0xFF, 0xDD, 0x3E, 0xE3, 0x0B, 0x61, 0xE3, 0xEB, 0x57, 0x2E, 0xF7, 0x7A, 0xDD, 0x9F, 0x14, 0xA8, 0x20, 0xF6, 0x22, 0xAF, + 0x52, 0x16, 0xB6, 0xE6, 0xB9, 0xFD, 0x48, 0xF2, 0xE9, 0x64, 0x53, 0x3F, 0x5C, 0xBE, 0x3E, 0xC9, 0x23, 0x40, 0xBA, 0x80, + 0x31, 0xE3, 0xC4, 0x53, 0x6E, 0x2C, 0x47, 0x57, 0x66, 0xB6, 0x2B, 0x0E, 0x37, 0xF5, 0x64, 0x86, 0x19, 0x2B, 0x1C, 0x30, + 0x22, 0xBE, 0x9E, 0x91, 0x32, 0x21, 0x1D, 0x09, 0x86, 0xB9, 0xBF, 0xB0, 0xB1, 0x80, 0x73, 0x29, 0xC1, 0x02, 0xEF, 0x99, + 0xD9, 0xB8, 0xDC, 0x95, 0xA0, 0x03, 0x09, 0x54, 0x81, 0x8E, 0x67, 0x89, 0x2A, 0xF0, 0x8F, 0x98, 0x3A, 0x10, 0x97, 0x3E, + 0x68, 0x57, 0xD5, 0xC0, 0x3E, 0x14, 0x48, 0x75, 0xB5, 0x21, 0x22, 0x02, 0xDD, 0xE2, 0x88, 0x30, 0x3B, 0x08, 0x58, 0xA4, + 0x1B, 0x2A, 0x0D, 0xE3, 0x33, 0xE8, 0xDC, 0x76, 0x15, 0xF8, 0x3F, 0xFD, 0x8B, 0xDC, 0xC7, 0xE0, 0x9A, 0x02, 0x69, 0x9E, + 0x4D, 0xEB, 0xD5, 0xA5, 0xF6, 0xED, 0x53, 0x50, 0xA0, 0x47, 0x7E, 0xF8, 0x67, 0x74, 0xCC, 0x01, 0x43, 0x58, 0x87, 0x97, + 0x9B, 0xE2, 0x7C, 0xA0, 0xA4, 0x05, 0x57, 0x9F, 0x5B, 0x87, 0x2C, 0x8D, 0xAA, 0x58, 0xA8, 0x9D, 0x6E, 0xC7, 0xF7, 0xF4, + 0x09, 0xDC, 0x8A, 0xEF, 0x6B, 0x01, 0x1B, 0xBA, 0x69, 0xBF, 0xD2, 0xA4, 0xB0, 0x03, 0x7D, 0xA0, 0x61, 0x80, 0xD4, 0x7E, + 0xAE, 0xAC, 0x13, 0x69, 0xCC, 0x62, 0x42, 0xA9, 0xF9, 0x21, 0xDA, 0x26, 0xB7, 0xB4, 0x8A, 0x0C, 0xB7, 0x86, 0x0D, 0x5B, + 0xE6, 0x6B, 0xD9, 0xC2, 0x30, 0x88, 0x5E, 0x58, 0x0C, 0x05, 0x02, 0xAD, 0x01, 0x6D, 0x6C, 0xC0, 0x2B, 0x48, 0xC0, 0x7D, + 0xA1, 0xB1, 0x42, 0x44, 0x0D, 0x04, 0xF4, 0x90, 0x96, 0x4F, 0x64, 0xD1, 0x95, 0x90, 0x83, 0xCA, 0xFE, 0xE4, 0x43, 0xCD, + 0xAB, 0xAC, 0xF9, 0xBE, 0xFE, 0xD1, 0x32, 0x29, 0xB3, 0x20, 0x3F, 0xF6, 0xDB, 0x5C, 0x53, 0x99, 0xC7, 0xA2, 0xB5, 0x68, + 0x72, 0xB5, 0x41, 0x7B, 0x78, 0xE2, 0xDF, 0x1D, 0xCF, 0xE4, 0xA3, 0xBC, 0x5B, 0xB0, 0x3A, 0x01, 0xDB, 0x13, 0x6B, 0xD3, + 0x0E, 0x3C, 0xAF, 0x20, 0x51, 0xB3, 0x0D, 0x14, 0x7D, 0x37, 0x5C, 0xE7, 0x45, 0xE4, 0x1D, 0xC3, 0x5F, 0xA0, 0x5C, 0xD4, + 0x56, 0x7B, 0xC5, 0xE1, 0x2C, 0xA9, 0xBB, 0xB9, 0xBE, 0x9D, 0x72, 0xE1, 0xE4, 0x7A, 0xAB, 0x10, 0xD1, 0x70, 0xAE, 0xAC, + 0x7D, 0x10, 0x9A, 0x7D, 0xBD, 0xEF, 0x63, 0x08, 0x14, 0x57, 0x18, 0x31, 0xD0, 0x19, 0x1E, 0xA0, 0x4A, 0xA7, 0x40, 0x64, + 0x74, 0xE4, 0x02, 0x73, 0x40, 0xF9, 0xA2, 0x02, 0x41, 0xD3, 0x1A, 0x68, 0xC8, 0x71, 0x95, 0xEE, 0x96, 0x83, 0x54, 0x5C, + 0x65, 0x5C, 0xD4, 0xE4, 0xF4, 0x07, 0x3B, 0xC7, 0xC1, 0x33, 0xFB, 0xF1, 0x49, 0x5A, 0xC2, 0x65, 0xC3, 0x57, 0x6D, 0x22, + 0x30, 0x26, 0x75, 0x2E, 0x2C, 0xBA, 0x35, 0x5D, 0x16, 0xB1, 0x5D, 0x75, 0xC2, 0xF5, 0xE7, 0x13, 0xD1, 0x05, 0x5F, 0xA6, + 0x8D, 0x13, 0x36, 0xFB, 0x36, 0xE4, 0x86, 0xB9, 0x46, 0xF5, 0xA8, 0x01, 0x00, 0xD7, 0xF1, 0x70, 0xAF, 0x54, 0x22, 0xEF, + 0x4D, 0xCF, 0x24, 0x08, 0x96, 0x1B, 0x98, 0x19, 0x1A, 0xA6, 0x82, 0x61, 0x62, 0x57, 0x43, 0x47, 0x0B, 0xC5, 0x5D, 0x99, + 0x17, 0xA5, 0x40, 0xD7, 0x78, 0x2B, 0xE3, 0x06, 0xA8, 0x8B, 0xF1, 0xA1, 0x50, 0x8A, 0x07, 0x0C, 0xEF, 0x52, 0x89, 0x10, + 0x12, 0x08, 0x10, 0x57, 0x49, 0x18, 0xC6, 0x2A, 0x09, 0x49, 0x5E, 0xC8, 0x6C, 0x55, 0x13, 0x04, 0x90, 0x31, 0x06, 0xDC, + 0x02, 0x9D, 0x8E, 0x7C, 0x21, 0x7D, 0x0C, 0x1E, 0x7B, 0xF0, 0x53, 0x9C, 0x7F, 0xF0, 0x3E, 0xB8, 0xC8, 0x08, 0x7F, 0xC5, + 0x98, 0xD3, 0x4F, 0x29, 0xA6, 0xF3, 0xC1, 0xD9, 0x5D, 0xD3, 0x43, 0x27, 0xAD, 0x16, 0x27, 0x55, 0x3C, 0x0D, 0x09, 0x1F, + 0xD8, 0x19, 0x27, 0x15, 0x11, 0x32, 0x7B, 0x02, 0x02, 0x70, 0xEA, 0x36, 0xEB, 0x5F, 0x87, 0x23, 0xCB, 0xE0, 0x1C, 0xB9, + 0x57, 0xA2, 0xF9, 0x2D, 0x3B, 0x3D, 0x68, 0x76, 0x04, 0x0C, 0x6F, 0x13, 0xD1, 0xE0, 0x86, 0x9B, 0x9F, 0x6B, 0x45, 0x1C, + 0xEA, 0x57, 0x9B, 0xB7, 0x6B, 0x7D, 0xCC, 0x02, 0x9A, 0xE3, 0x71, 0x47, 0xDB, 0x8E, 0x94, 0x48, 0xF6, 0x83, 0x7B, 0x77, + 0xC5, 0xCD, 0x48, 0x12, 0x52, 0x81, 0xC7, 0x8A, 0x3C, 0xB0, 0x32, 0xA4, 0x16, 0x29, 0xF8, 0x57, 0x7D, 0x65, 0x21, 0x12, + 0xC6, 0xD2, 0x70, 0x80, 0x44, 0xA9, 0x84, 0x21, 0x6D, 0x23, 0x9E, 0xFC, 0xB6, 0x22, 0xC6, 0xF7, 0xB4, 0x38, 0xBD, 0x04, + 0x64, 0x22, 0x37, 0xA5, 0x8F, 0x58, 0xE5, 0xBA, 0x92, 0xA0, 0x79, 0xBF, 0x33, 0x83, 0xE7, 0x53, 0x71, 0xE2, 0xB9, 0x20, + 0xAD, 0xC5, 0xED, 0xD7, 0x76, 0xA8, 0xBD, 0x88, 0x2E, 0xB6, 0x01, 0xFF, 0x70, 0xE3, 0xE2, 0x17, 0x86, 0x3C, 0xC0, 0x0F, + 0x1F, 0xE8, 0x2A, 0x7A, 0xA5, 0xA2, 0xD0, 0x2E, 0xB7, 0x3B, 0x32, 0x1D, 0x55, 0xCB, 0x66, 0x5F, 0x0D, 0x09, 0x96, 0xA1, + 0x4E, 0x6B, 0x84, 0xEE, 0xA6, 0x72, 0xF1, 0xF2, 0xC0, 0xC8, 0xAF, 0x07, 0x9A, 0xA3, 0x71, 0xD0, 0x25, 0x29, 0xBF, 0xF3, + 0x94, 0x89, 0xAC, 0x98, 0x59, 0x3A, 0x7F, 0x6C, 0xE5, 0xEE, 0x05, 0xFE, 0xAD, 0x14, 0xBB, 0x0E, 0x7C, 0x14, 0x7A, 0x6A, + 0x0D, 0xCC, 0xBB, 0xFD, 0xB9, 0x07, 0xC2, 0x1D, 0x40, 0x13, 0xB6, 0x86, 0xB4, 0xA1, 0x10, 0xBA, 0x03, 0x20, 0x12, 0xAF, + 0x7B, 0x6B, 0x04, 0xCB, 0xBA, 0x5E, 0xFC, 0x00, 0x81, 0xA2, 0x7F, 0x5B, 0x67, 0x3D, 0xBF, 0xD9, 0xAD, 0xF9, 0x4D, 0x53, + 0xC0, 0x7F, 0x08, 0xA8, 0x00, 0xE6, 0x38, 0xA9, 0xAE, 0x1D, 0x34, 0xC9, 0xBD, 0x9D, 0x05, 0xCB, 0x40, 0x62, 0xDB, 0x6F, + 0x3E, 0xF4, 0x1A, 0xBF, 0x80, 0x7D, 0x47, 0x75, 0x4C, 0xF2, 0xEC, 0x62, 0x22, 0x7D, 0xEE, 0x59, 0x1E, 0xA3, 0x7C, 0x17, + 0xCE, 0x92, 0xB4, 0x0A, 0xDC, 0xDB, 0x02, 0x06, 0xE8, 0x27, 0xE4, 0xB2, 0x5C, 0x71, 0xE1, 0x70, 0xD8, 0x3F, 0xBD, 0xD7, + 0x5D, 0x71, 0x7F, 0x93, 0x13, 0x2D, 0xCB, 0x0B, 0x1D, 0x31, 0x13, 0xAF, 0x51, 0x22, 0xEF, 0x6C, 0x5C, 0x50, 0x35, 0xB7, + 0xEC, 0xC3, 0x83, 0x02, 0xD6, 0xB3, 0x71, 0xA0, 0x47, 0xB4, 0xBD, 0xE9, 0x55, 0x94, 0xCC, 0xF2, 0xC1, 0x96, 0x18, 0x74, + 0x66, 0xFC, 0x52, 0x6B, 0x4F, 0x98, 0x14, 0xF6, 0x29, 0x7F, 0x79, 0xCD, 0x59, 0x00, 0x1E, 0x02, 0x7F, 0xB4, 0x3D, 0xC7, + 0x8F, 0x16, 0x1D, 0xCF, 0xD5, 0x27, 0x6D, 0xCA, 0xE0, 0xB7, 0x73, 0x95, 0x51, 0xED, 0x92, 0xA0, 0xD5, 0xD5, 0xB4, 0x2F, + 0x12, 0x68, 0xAC, 0x77, 0x94, 0x47, 0xED, 0x62, 0xB3, 0xF6, 0x7F, 0x8E, 0xF9, 0xDD, 0x0A, 0x15, 0x3F, 0x3A, 0xF6, 0xCA, + 0x53, 0x7B, 0xAA, 0xBE, 0x7A, 0xF1, 0x47, 0x70, 0xC6, 0xDA, 0x7F, 0x6D, 0x4F, 0xD5, 0x3F, 0xAB, 0x43, 0x74, 0xED, 0x42, + 0x7D, 0x54, 0x99, 0x0E, 0x79, 0xF8, 0x67, 0xEF, 0x83, 0x19, 0xE6, 0x58, 0x9E, 0xF2, 0x6A, 0x1E, 0xCA, 0x55, 0x8C, 0x3A, + 0x4C, 0x34, 0x91, 0x32, 0x63, 0x14, 0x75, 0x8B, 0xE5, 0x24, 0x6A, 0x8E, 0xBE, 0x54, 0x7E, 0xDF, 0xC5, 0xED, 0xB8, 0x2C, + 0x76, 0x39, 0x56, 0x6E, 0xE1, 0x71, 0xB5, 0xEB, 0x5E, 0x7E, 0x50, 0x67, 0x47, 0x90, 0xCE, 0xB8, 0xCC, 0xD3, 0x2A, 0x7E, + 0x4E, 0xDC, 0xC0, 0xB3, 0x5C, 0x15, 0xD3, 0xA9, 0x45, 0x0F, 0xF5, 0xDE, 0x45, 0xA5, 0x21, 0x78, 0xC8, 0x73, 0x6C, 0x6B, + 0x9F, 0x0F, 0x90, 0xA8, 0xD9, 0xDD, 0x88, 0x9F, 0xEF, 0xA4, 0x77, 0xEF, 0xE9, 0xD6, 0xA6, 0xE4, 0x5A, 0x20, 0x01, 0x66, + 0xFF, 0xDD, 0xE2, 0x04, 0xB7, 0x8B, 0xAA, 0xA5, 0x4E, 0xCA, 0x7C, 0x5B, 0x9A, 0x3A, 0x32, 0x8F, 0xFE, 0x8C, 0xD0, 0x9C, + 0xB9, 0x0C, 0xA7, 0xBF, 0x22, 0x45, 0xF9, 0x74, 0x01, 0x7A, 0x51, 0x76, 0xCC, 0x6E, 0xDD, 0x99, 0x79, 0x09, 0xC6, 0xDA, + 0x7F, 0x2C, 0xCB, 0x27, 0x63, 0xBB, 0xEA, 0xEF, 0x87, 0xE0, 0x49, 0xA0, 0xAE, 0x38, 0x60, 0x4F, 0xA0, 0x47, 0xE8, 0x4F, + 0x76, 0x73, 0x22, 0x51, 0x03, 0x34, 0x00, 0xF1, 0x70, 0xB9, 0xF3, 0x48, 0x9A, 0xA5, 0x8A, 0x4A, 0xF1, 0x01, 0xD8, 0x22, + 0x30, 0x52, 0xCE, 0x6D, 0xFA, 0x94, 0x78, 0x8E, 0xB8, 0xDA, 0xA0, 0x53, 0x30, 0x30, 0x18, 0xD7, 0xE5, 0x66, 0xB9, 0x62, + 0x6B, 0x29, 0x72, 0x55, 0x23, 0xBD, 0x8B, 0xB4, 0x71, 0x03, 0xB1, 0x75, 0x06, 0x85, 0x91, 0x51, 0xDB, 0xB6, 0xEC, 0x58, + 0x77, 0x56, 0xA1, 0x52, 0x3A, 0x36, 0x8D, 0xCF, 0xD6, 0xD5, 0x64, 0x7A, 0x95, 0x4A, 0x73, 0xE8, 0x10, 0xF5, 0xAD, 0xCA, + 0x33, 0x43, 0x10, 0x1A, 0x9B, 0x01, 0xD0, 0x1E, 0xAA, 0xF0, 0xDA, 0x8D, 0x0D, 0x41, 0x25, 0xAF, 0x35, 0xE2, 0x19, 0x0B, + 0x3B, 0x97, 0xFC, 0x4A, 0x65, 0x9C, 0xEC, 0x6E, 0x29, 0xBC, 0x71, 0x2F, 0x9D, 0x04, 0x89, 0x47, 0x78, 0xD7, 0xEA, 0xDD, + 0x95, 0x80, 0x9F, 0x19, 0xDF, 0xD2, 0xBB, 0xD7, 0xAC, 0x7D, 0xEA, 0xDD, 0x8F, 0xCE, 0xE2, 0xFA, 0x1C, 0xCF, 0x67, 0x5D, + 0xFA, 0x8D, 0xAA, 0x4B, 0xB3, 0x1D, 0x4A, 0x78, 0x49, 0x4D, 0x95, 0x5C, 0x68, 0x21, 0x72, 0x1A, 0xB6, 0x41, 0xA2, 0x5B, + 0xB2, 0x1C, 0xEB, 0xD1, 0x8C, 0x17, 0xB3, 0xC9, 0xF4, 0x81, 0x93, 0xE9, 0xCF, 0x93, 0xAB, 0x4A, 0x33, 0x3F, 0x77, 0xC6, + 0x09, 0x0B, 0x0B, 0xB9, 0xBA, 0xF4, 0x63, 0xFB, 0x4B, 0xAE, 0xA3, 0x7F, 0xDD, 0xE2, 0xFC, 0x82, 0x00, 0x52, 0x82, 0x00, + 0x5E, 0x70, 0xAC, 0x5B, 0xED, 0xAD, 0x5D, 0x4B, 0x91, 0xF6, 0xB4, 0xA1, 0x45, 0x5E, 0x94, 0x8D, 0xBE, 0x97, 0xE7, 0x8B, + 0x0D, 0xCA, 0x79, 0xDA, 0x10, 0x75, 0xD3, 0x5A, 0x93, 0xDE, 0xCD, 0x04, 0x59, 0x19, 0x72, 0x5E, 0x15, 0xC4, 0x95, 0x4B, + 0x7D, 0x8F, 0xB5, 0x56, 0x63, 0x33, 0x1F, 0xD5, 0xF9, 0x71, 0x1D, 0x76, 0x1C, 0xE5, 0xE4, 0xCB, 0x90, 0x77, 0x1C, 0xC4, + 0xD3, 0xCD, 0x9B, 0xD1, 0x34, 0xFF, 0x54, 0xA0, 0x3F, 0xD9, 0x95, 0x92, 0xB0, 0x74, 0x97, 0xD2, 0x5C, 0xB4, 0xD4, 0x2C, + 0xEF, 0x8E, 0xF0, 0x83, 0x1B, 0x4E, 0x64, 0x0E, 0x63, 0x38, 0x5D, 0xC5, 0x0B, 0xE0, 0xED, 0x39, 0x5E, 0xCD, 0x2B, 0xD9, + 0x09, 0xE7, 0xDD, 0xD1, 0xC1, 0x1A, 0x12, 0xC4, 0xA5, 0x6C, 0x86, 0x3D, 0x21, 0xFA, 0x38, 0x67, 0x0A, 0xC6, 0xA2, 0x71, + 0x9D, 0x9B, 0x0E, 0x09, 0xC9, 0x57, 0x50, 0xF2, 0xB8, 0x58, 0x4C, 0xAA, 0xDB, 0x81, 0xF7, 0x6C, 0x6C, 0x63, 0x06, 0x98, + 0x2A, 0xF9, 0xD2, 0x7C, 0x3D, 0x77, 0x6B, 0xDE, 0x11, 0x16, 0xA1, 0x5A, 0x12, 0x52, 0x57, 0x19, 0xF8, 0x58, 0xBD, 0x7E, + 0x93, 0x97, 0x76, 0xE9, 0xFC, 0x41, 0xE6, 0xD7, 0x5F, 0x6A, 0x56, 0x0F, 0xCE, 0x9B, 0xC8, 0xBD, 0xE3, 0x7B, 0x5E, 0xDF, + 0x9B, 0x5F, 0x1E, 0xCE, 0xD2, 0x70, 0xFE, 0xB7, 0x0B, 0x5C, 0x3F, 0xC4, 0xDF, 0x43, 0x17, 0x7E, 0x6B, 0x1C, 0xDE, 0xF9, + 0x58, 0xFE, 0x91, 0xB8, 0xD3, 0xD7, 0x18, 0x7E, 0xCE, 0x31, 0x0C, 0x9A, 0x9C, 0x38, 0x1A, 0x8F, 0x6C, 0x11, 0x7B, 0x56, + 0xDD, 0xB8, 0x07, 0xB0, 0x3F, 0x7C, 0x6B, 0x10, 0xEC, 0xBD, 0x11, 0x2B, 0xB4, 0x7A, 0x7C, 0x08, 0xAD, 0xB4, 0xF7, 0xA2, + 0x3A, 0x32, 0x67, 0x16, 0x7E, 0x82, 0x1B, 0x02, 0x74, 0xC2, 0x8F, 0x79, 0xD9, 0x9B, 0xFC, 0x90, 0x36, 0x22, 0x0E, 0xC3, + 0xCB, 0x66, 0xB8, 0xA2, 0x67, 0xE6, 0x60, 0x96, 0xF0, 0xCE, 0x84, 0x0F, 0xFC, 0x8A, 0xEE, 0x4C, 0xC5, 0xA1, 0xE1, 0x9C, + 0x88, 0xAE, 0x52, 0x87, 0xEA, 0x32, 0xA7, 0x27, 0xDA, 0xE2, 0xA3, 0x63, 0x8C, 0x80, 0x09, 0xD8, 0xC4, 0xAF, 0x28, 0x6C, + 0x22, 0x80, 0x45, 0x84, 0xF1, 0xAB, 0x03, 0xC0, 0xEE, 0x6E, 0xB8, 0x48, 0x72, 0x48, 0x76, 0x20, 0xF1, 0xE1, 0x47, 0xBB, + 0x45, 0x11, 0x48, 0x9C, 0xEA, 0xC9, 0x90, 0xD1, 0x31, 0xEB, 0xEC, 0x2C, 0x66, 0xD0, 0xF0, 0xBE, 0x85, 0x68, 0x42, 0x99, + 0xF4, 0xCB, 0x4C, 0x94, 0xD2, 0x67, 0x59, 0x33, 0xCD, 0x8D, 0x74, 0xAB, 0x7A, 0xDD, 0x8C, 0x2D, 0x33, 0x9A, 0x45, 0x85, + 0x7A, 0xE9, 0x71, 0x57, 0x2E, 0x71, 0x97, 0xE6, 0x87, 0x6A, 0x41, 0x8C, 0x44, 0xCA, 0xA0, 0xE5, 0x30, 0xF7, 0x60, 0x06, + 0x0A, 0x80, 0xA4, 0x8A, 0x72, 0x75, 0x6E, 0xCA, 0x48, 0x86, 0xEE, 0xB2, 0xDC, 0xD9, 0xFC, 0xC1, 0x8D, 0x88, 0xF6, 0x9A, + 0x73, 0x51, 0xFA, 0x8F, 0x72, 0xD2, 0x5D, 0xC1, 0xAC, 0x3F, 0x23, 0xCB, 0xC4, 0xC8, 0x83, 0x0A, 0x7D, 0x05, 0x74, 0x8B, + 0x96, 0x93, 0x73, 0x9A, 0xCD, 0x86, 0x72, 0x4D, 0xEE, 0xCB, 0x6B, 0xAA, 0x50, 0xA1, 0x4A, 0x5D, 0x3E, 0xDB, 0x40, 0x78, + 0x3C, 0x4D, 0x02, 0x48, 0x36, 0x81, 0x9C, 0xFA, 0x18, 0x55, 0x89, 0xEE, 0x4C, 0x70, 0x08, 0xEA, 0x63, 0x54, 0x0A, 0x58, + 0x63, 0x80, 0xF2, 0xB6, 0x8D, 0x60, 0x96, 0x09, 0x73, 0x4B, 0xB4, 0xA3, 0xD0, 0xF6, 0x98, 0x6C, 0x2F, 0x71, 0xB8, 0xB3, + 0x72, 0x55, 0xD0, 0x47, 0x12, 0xBF, 0xA3, 0xFF, 0xD2, 0xAC, 0x10, 0x7C, 0x2E, 0x76, 0x12, 0x57, 0x7A, 0xD0, 0x84, 0x08, + 0xFB, 0x49, 0x9D, 0x09, 0x1D, 0xCF, 0x8C, 0xAE, 0x00, 0x91, 0x90, 0xF0, 0xDD, 0xC8, 0x20, 0xE5, 0x85, 0x76, 0xB2, 0x4E, + 0xB2, 0x3B, 0x7C, 0x07, 0x21, 0xB4, 0x61, 0xF4, 0x16, 0x81, 0x3C, 0x48, 0xE8, 0x2C, 0xD8, 0xD0, 0xBF, 0xAB, 0x67, 0x87, + 0x0C, 0xD3, 0xFD, 0x9A, 0x36, 0x6E, 0xA3, 0x58, 0x05, 0x54, 0x35, 0x83, 0x79, 0xE9, 0xBD, 0x7B, 0x27, 0xDE, 0x01, 0xEC, + 0x7F, 0x8B, 0x5A, 0xC9, 0x84, 0xD7, 0xE7, 0xB5, 0xF3, 0x10, 0xAB, 0xDD, 0x1E, 0x40, 0xDA, 0xEB, 0xC2, 0xE5, 0xDD, 0x8C, + 0x48, 0x72, 0x13, 0x16, 0xF6, 0xEB, 0xFE, 0xAC, 0xA6, 0x98, 0x47, 0x73, 0xE2, 0xAB, 0xED, 0xCD, 0x5B, 0x58, 0x14, 0x6E, + 0xF0, 0x77, 0x74, 0xD8, 0xCA, 0x02, 0xBC, 0xD2, 0x3B, 0xD5, 0x4D, 0x08, 0x55, 0x03, 0xEE, 0x6D, 0xF7, 0xB6, 0xD2, 0x91, + 0x06, 0xD5, 0x90, 0x2C, 0x66, 0x6A, 0x06, 0x08, 0xE1, 0xD5, 0x26, 0xD4, 0x88, 0xFE, 0xDD, 0x82, 0x89, 0x67, 0x9D, 0x1D, + 0x2D, 0xB0, 0x4F, 0xD4, 0x0D, 0xDC, 0x72, 0x6E, 0x3A, 0xBA, 0x48, 0xD2, 0x2C, 0xD9, 0x78, 0xD6, 0xB0, 0x4F, 0x67, 0x11, + 0xC8, 0x7F, 0xE7, 0x10, 0xD8, 0x58, 0x8B, 0x18, 0xB5, 0x47, 0x27, 0x8D, 0x91, 0xF8, 0x56, 0x6B, 0xB0, 0xB6, 0x61, 0xAB, + 0xFF, 0xD8, 0x1B, 0x83, 0x9E, 0x7D, 0x50, 0xE5, 0x6B, 0x64, 0xA9, 0x5D, 0xFF, 0x96, 0x2D, 0x59, 0x58, 0x97, 0xB0, 0xD1, + 0xCF, 0xA3, 0xCD, 0x4A, 0x50, 0x13, 0xFE, 0x98, 0x51, 0xD8, 0xC8, 0x3A, 0x16, 0xF1, 0x06, 0xB8, 0xD8, 0xDF, 0xD6, 0x20, + 0x39, 0xF6, 0x26, 0xE5, 0xB6, 0x20, 0x07, 0x8C, 0x84, 0xBD, 0x1E, 0x09, 0x0F, 0x61, 0x8F, 0xAD, 0x41, 0xB0, 0x8E, 0x00, + 0x5D, 0x9C, 0x0A, 0x9C, 0xB5, 0x9D, 0x2F, 0x80, 0x73, 0xAE, 0xF7, 0x5D, 0x51, 0x74, 0x50, 0xA1, 0x1A, 0x43, 0x25, 0xE0, + 0xFF, 0xFF, 0x3A, 0xF3, 0x34, 0x06, 0x2C, 0x97, 0x60, 0x2A, 0x94, 0xD1, 0x38, 0xC0, 0x68, 0xCC, 0x6A, 0x2D, 0xCC, 0x95, + 0x0F, 0x8B, 0x77, 0x16, 0x15, 0xD4, 0xD8, 0xB4, 0xD4, 0xB4, 0xD0, 0x30, 0xD1, 0x21, 0x21, 0x58, 0x21, 0xDD, 0x03, 0xED, + 0xAA, 0x6F, 0xD1, 0xB5, 0xEE, 0x2E, 0x6E, 0x62, 0x1A, 0xF3, 0xCE, 0xB1, 0x20, 0xC3, 0x9A, 0xFD, 0xE7, 0xDE, 0x8B, 0x43, + 0x4C, 0x01, 0x2E, 0x0D, 0xE2, 0x50, 0x1E, 0x6C, 0x06, 0x00, 0x9A, 0x48, 0x9C, 0x3F, 0x02, 0xD6, 0xA9, 0x20, 0x57, 0xE6, + 0xAE, 0x6D, 0x00, 0x5C, 0x05, 0x87, 0x72, 0xAB, 0x9C, 0xA3, 0x9A, 0xDC, 0x0B, 0x15, 0x18, 0xE4, 0x50, 0x06, 0xC8, 0xC5, + 0x8C, 0xBB, 0x63, 0xB3, 0xA1, 0x4D, 0x6F, 0x59, 0x61, 0x04, 0xE9, 0x9A, 0x62, 0x35, 0xD4, 0x11, 0xCB, 0xAC, 0xCD, 0x95, + 0x83, 0x3C, 0xC9, 0x6E, 0xE9, 0xCA, 0xBF, 0x17, 0x51, 0x82, 0x25, 0x25, 0xD4, 0x99, 0x7A, 0x76, 0x97, 0x8E, 0x54, 0x31, + 0x4B, 0x08, 0x2D, 0xCA, 0x6B, 0x40, 0x2D, 0x20, 0x0F, 0x73, 0x86, 0x7A, 0xE6, 0x2D, 0xA2, 0xC7, 0x7A, 0x61, 0x89, 0x7C, + 0x5D, 0x6D, 0x23, 0x19, 0x54, 0x7B, 0x90, 0x4D, 0xDC, 0x31, 0x07, 0x18, 0xFB, 0x79, 0x2B, 0xD2, 0x57, 0xCC, 0x84, 0x9B, + 0x67, 0x20, 0x0B, 0x22, 0xE9, 0x30, 0xA3, 0xBD, 0xCF, 0x17, 0x1B, 0x02, 0xA9, 0x70, 0xD3, 0x4D, 0x8A, 0x7F, 0x90, 0x2A, + 0x67, 0x25, 0xAF, 0x86, 0xF7, 0xED, 0xCA, 0x8E, 0xF6, 0x91, 0x4F, 0x2B, 0x33, 0x06, 0x12, 0x2A, 0xE4, 0x43, 0xA1, 0xFC, + 0x45, 0xC5, 0xE4, 0xC9, 0xD6, 0xCB, 0x83, 0xCC, 0x73, 0x04, 0x43, 0x4F, 0xBB, 0x35, 0x6B, 0x96, 0x7F, 0x2D, 0xAB, 0x9C, + 0xB4, 0x4E, 0x4D, 0xA8, 0xBF, 0x8F, 0xA9, 0x5C, 0x98, 0xED, 0x61, 0x9B, 0x67, 0x40, 0x09, 0xBD, 0xF3, 0x69, 0x3E, 0x73, + 0x34, 0xCB, 0x33, 0xBC, 0x36, 0x8B, 0x76, 0xA1, 0x61, 0xE9, 0x2C, 0x5B, 0x99, 0xE1, 0x2C, 0x69, 0xDE, 0x53, 0x1E, 0xD3, + 0xF3, 0xB1, 0x45, 0xF1, 0xC4, 0xCE, 0xC2, 0x9D, 0x79, 0x75, 0xF7, 0x7C, 0xBE, 0x69, 0x19, 0x9A, 0xDC, 0x9F, 0x4C, 0x08, + 0x45, 0xED, 0x79, 0x3A, 0xF1, 0xD2, 0x52, 0x70, 0xD6, 0xD4, 0xC5, 0x9C, 0x58, 0xD2, 0x7A, 0x76, 0x23, 0x73, 0x9E, 0xC6, + 0x81, 0x8A, 0xC7, 0x07, 0x24, 0x76, 0x32, 0x24, 0x93, 0xCD, 0x42, 0x55, 0x89, 0x10, 0x8A, 0x51, 0x7A, 0xD9, 0x0E, 0xBD, + 0x20, 0x75, 0x5E, 0x2B, 0x52, 0x75, 0x66, 0x77, 0x08, 0xD6, 0x94, 0x50, 0x10, 0x7C, 0xFE, 0x81, 0xB2, 0x54, 0xDD, 0xD8, + 0xB4, 0xB4, 0x6F, 0x59, 0x09, 0x32, 0x03, 0xA2, 0x38, 0x55, 0x13, 0xFD, 0xEF, 0x55, 0xD5, 0xC0, 0x4E, 0xBE, 0x5D, 0x02, + 0x89, 0x82, 0xCB, 0x40, 0x18, 0x33, 0xD9, 0x07, 0x17, 0x1C, 0x2A, 0x1E, 0x78, 0x32, 0x1E, 0x75, 0x5B, 0xDB, 0xCE, 0xBC, + 0x93, 0x49, 0x52, 0x64, 0xC3, 0xE2, 0x0F, 0xDB, 0xFB, 0x3D, 0x9F, 0xA8, 0x79, 0x16, 0x61, 0x7B, 0x7F, 0x1B, 0x58, 0x76, + 0xAE, 0xA1, 0x07, 0xCC, 0x68, 0x97, 0x4D, 0xA8, 0x4F, 0xF7, 0xB7, 0xA8, 0x93, 0x4B, 0xDF, 0x74, 0x29, 0xA0, 0x87, 0x99, + 0xB0, 0xAF, 0xA0, 0x2A, 0xD5, 0x51, 0x24, 0xFD, 0xE9, 0xD6, 0x82, 0xB3, 0x2B, 0x0C, 0x44, 0xAC, 0x3E, 0x38, 0x04, 0x00, + 0x2A, 0x80, 0xEC, 0x5C, 0x86, 0xD3, 0x4A, 0x3A, 0xAB, 0xBD, 0x31, 0x1B, 0xF9, 0x1D, 0x9A, 0x32, 0xD8, 0xD7, 0x0F, 0x78, + 0x39, 0x77, 0x27, 0x7E, 0x89, 0x95, 0x57, 0x25, 0xD1, 0xF3, 0xE7, 0x9E, 0xE4, 0x82, 0x73, 0x8F, 0x05, 0x6B, 0x75, 0x5B, + 0x45, 0x14, 0x87, 0xD4, 0x39, 0xD8, 0xD8, 0x06, 0x02, 0xBC, 0xA0, 0x58, 0x31, 0x72, 0x18, 0x72, 0x0C, 0x89, 0x36, 0x79, + 0xB3, 0xA4, 0x87, 0x17, 0xA5, 0x5F, 0xBC, 0x59, 0xF3, 0xFB, 0x0E, 0x2A, 0x1D, 0xC3, 0xDA, 0x13, 0x51, 0x2C, 0x7C, 0xEF, + 0x44, 0xFA, 0x2D, 0xF1, 0x8B, 0xE9, 0xF6, 0x10, 0xB8, 0x92, 0xA2, 0xEF, 0xF6, 0xEF, 0x4E, 0xDD, 0x49, 0x80, 0xE2, 0x41, + 0x2B, 0x4F, 0xEB, 0xBF, 0xB6, 0x02, 0x51, 0x1F, 0xF6, 0x5C, 0x60, 0x83, 0x60, 0x4A, 0xBF, 0xC6, 0xE5, 0xC3, 0x40, 0x7B, + 0x00, 0xE6, 0xB9, 0xF3, 0xB3, 0x5D, 0xF5, 0xCD, 0x46, 0xE4, 0x47, 0x06, 0x50, 0x66, 0xA8, 0xC2, 0x3A, 0x8F, 0x38, 0x34, + 0xE8, 0x2C, 0xC1, 0x02, 0x07, 0xCE, 0xC0, 0x8C, 0xBE, 0x06, 0x5E, 0x83, 0x9A, 0xEA, 0xF9, 0xC7, 0x14, 0x01, 0xF0, 0x0C, + 0xE5, 0xA6, 0xFC, 0x9C, 0xF8, 0x40, 0x6F, 0xA2, 0xB3, 0x27, 0x69, 0x37, 0xDB, 0x5A, 0x47, 0x01, 0x78, 0x9C, 0xEF, 0x15, + 0x28, 0x6A, 0x1C, 0x27, 0xAB, 0x9A, 0x5A, 0xE6, 0x6E, 0xE5, 0x36, 0x4A, 0x6B, 0x65, 0x92, 0x36, 0xB5, 0x99, 0x39, 0xFC, + 0x3E, 0xA1, 0xF5, 0x7B, 0xC1, 0x68, 0x32, 0x57, 0x4B, 0x0B, 0xAB, 0x3C, 0x51, 0x42, 0xDB, 0xE3, 0xB6, 0x27, 0xDC, 0x30, + 0xA0, 0xE8, 0xB2, 0xEC, 0x0E, 0xAA, 0x2C, 0xCF, 0x9C, 0x45, 0xD3, 0xEB, 0x85, 0x84, 0xF2, 0xA6, 0x38, 0x14, 0xEF, 0xC5, + 0x13, 0xA5, 0xAA, 0xC0, 0xEE, 0x58, 0x42, 0xD3, 0xE7, 0x9D, 0xF8, 0x5A, 0x3F, 0xEC, 0x34, 0x82, 0x69, 0x41, 0x26, 0x90, + 0x3D, 0x36, 0x28, 0x37, 0x0C, 0x2D, 0x50, 0xA1, 0x90, 0x2B, 0xA3, 0x7A, 0x70, 0x6F, 0x82, 0x59, 0xA6, 0xE2, 0x3B, 0x46, + 0x03, 0xCC, 0xC3, 0x0E, 0xAD, 0x25, 0x89, 0x63, 0x59, 0x51, 0x33, 0xEA, 0xF0, 0x73, 0x35, 0x77, 0xCB, 0x8B, 0xEF, 0x9F, + 0xD9, 0xA9, 0x41, 0x88, 0xA1, 0x72, 0xFD, 0xCA, 0x5F, 0xF1, 0xDB, 0x86, 0x5F, 0xBB, 0xFD, 0xB6, 0x91, 0x4F, 0xB6, 0x4A, + 0x04, 0x9D, 0xA1, 0x46, 0x34, 0x5F, 0xEC, 0x6B, 0x08, 0x65, 0x2C, 0x94, 0x31, 0x44, 0xA9, 0x5A, 0x03, 0x2C, 0x7C, 0x33, + 0x80, 0xF9, 0x12, 0x8B, 0x58, 0xE3, 0x09, 0x14, 0x88, 0xB8, 0xCA, 0xA1, 0xE0, 0x27, 0x24, 0xE6, 0xA9, 0x9C, 0xBF, 0xA8, + 0xBD, 0x66, 0x38, 0x7F, 0xD5, 0x4E, 0xC5, 0xCD, 0x6A, 0x75, 0x3C, 0x33, 0xB7, 0xAA, 0x1C, 0x32, 0x00, 0x35, 0xA3, 0xA4, + 0x4B, 0xBD, 0x62, 0x80, 0x06, 0x9F, 0x8F, 0x95, 0x18, 0x5F, 0x52, 0xFE, 0x84, 0x1E, 0x36, 0xA0, 0xC8, 0xDB, 0x2A, 0x22, + 0x3B, 0x2A, 0xC4, 0x09, 0x9E, 0xFA, 0xE4, 0x47, 0xA8, 0x41, 0x65, 0xC5, 0xB4, 0xAD, 0x0C, 0x9C, 0x01, 0x7B, 0x8D, 0xFA, + 0x16, 0x57, 0xA8, 0xE2, 0xB3, 0x38, 0x8F, 0xD6, 0xB4, 0xC7, 0x43, 0x46, 0x8F, 0xDA, 0x29, 0x09, 0x94, 0xBF, 0x35, 0x0E, + 0x57, 0xF1, 0x5E, 0x06, 0x99, 0x47, 0xA3, 0xEA, 0x28, 0xC3, 0xBE, 0xBF, 0x17, 0xA9, 0xD0, 0xF8, 0xEC, 0x13, 0x2E, 0x9C, + 0x39, 0x4C, 0xBE, 0x85, 0x51, 0xC2, 0xAF, 0x5E, 0x69, 0xBB, 0x80, 0xBE, 0x2E, 0x9E, 0x4B, 0x1C, 0x80, 0xB2, 0xA3, 0xCD, + 0x13, 0xDE, 0xB3, 0xAD, 0xEF, 0x57, 0xA8, 0x68, 0xD5, 0x90, 0x3A, 0x77, 0x91, 0x46, 0xEB, 0xC4, 0x4A, 0x66, 0xFD, 0xD3, + 0xFC, 0x5B, 0xC6, 0xB8, 0x4C, 0x5B, 0x86, 0x79, 0x6C, 0xB1, 0x64, 0x0F, 0xDD, 0x21, 0x36, 0x6B, 0x50, 0x61, 0x16, 0x2A, + 0xB1, 0x3C, 0x15, 0x21, 0x1B, 0x16, 0xA8, 0x48, 0x7B, 0xB1, 0xF8, 0x4B, 0xFF, 0x11, 0x19, 0xCC, 0x47, 0xEF, 0x78, 0xAF, + 0xFE, 0x33, 0x8D, 0xFA, 0x80, 0x73, 0x8F, 0xC8, 0x07, 0xF1, 0xEE, 0x28, 0x2B, 0x12, 0x3E, 0x37, 0xD4, 0x7C, 0x58, 0xFD, + 0x3F, 0xBB, 0xC8, 0x4B, 0x03, 0xDC, 0xC0, 0xF9, 0x2D, 0xFD, 0x80, 0x81, 0x1C, 0xA8, 0x06, 0x95, 0xBF, 0x1D, 0x06, 0xC4, + 0x56, 0x80, 0x55, 0x11, 0xB8, 0x6D, 0xCC, 0x95, 0x19, 0x21, 0xD3, 0xB4, 0x4F, 0x89, 0x46, 0xB5, 0x5B, 0x82, 0x13, 0x05, + 0x6B, 0x31, 0x55, 0xA0, 0xBE, 0x01, 0xD1, 0xA4, 0xBF, 0xC9, 0x45, 0x84, 0xDE, 0x89, 0x6F, 0xB0, 0x80, 0x43, 0x4D, 0x10, + 0xDA, 0x4B, 0x21, 0xDF, 0x6D, 0x4E, 0x47, 0xB4, 0xD9, 0x00, 0x04, 0xC1, 0x08, 0x26, 0x94, 0x46, 0x08, 0xF9, 0xD6, 0xC0, + 0x60, 0x44, 0x10, 0xE0, 0xE7, 0x7F, 0x48, 0xF1, 0x03, 0xAF, 0x73, 0x24, 0xAF, 0x2C, 0x16, 0xA1, 0x08, 0x85, 0x23, 0xB6, + 0xF2, 0x7A, 0x05, 0xC0, 0x88, 0x26, 0xDB, 0xEB, 0xB3, 0x96, 0xC5, 0xC4, 0xE4, 0xEC, 0x01, 0x03, 0x2D, 0xEB, 0xC5, 0xF4, + 0xAB, 0x25, 0xC8, 0x2B, 0xF2, 0x50, 0x59, 0xF4, 0xCD, 0xEF, 0x19, 0xF5, 0xD6, 0xFA, 0x26, 0xD7, 0x85, 0x35, 0x56, 0x28, + 0x12, 0x08, 0x04, 0x99, 0xA3, 0x2B, 0xC6, 0xA9, 0x37, 0x83, 0x5F, 0x31, 0xE2, 0x1A, 0x5E, 0x1C, 0x51, 0x43, 0xCA, 0xC8, + 0x4C, 0x0B, 0x4E, 0x39, 0x73, 0x0A, 0x65, 0xA0, 0x77, 0xA7, 0x45, 0x18, 0x92, 0x48, 0x2D, 0x99, 0xFE, 0xE5, 0x47, 0x88, + 0xB6, 0x81, 0x35, 0xB0, 0x8F, 0x89, 0x5F, 0x3C, 0x93, 0x09, 0xDF, 0x6D, 0x68, 0x94, 0x4F, 0x98, 0xF7, 0x48, 0x96, 0xF9, + 0x42, 0x0C, 0xDA, 0x49, 0xEC, 0x79, 0x1C, 0xBC, 0x27, 0xA7, 0xFA, 0x0E, 0xA3, 0x60, 0x9E, 0xD9, 0x64, 0x6F, 0x4E, 0xA1, + 0xE4, 0x6C, 0xDE, 0xDD, 0x07, 0xA6, 0x65, 0x3E, 0xFA, 0x98, 0x17, 0x4C, 0xE1, 0x66, 0xC1, 0x56, 0xB0, 0x2A, 0xD5, 0x9C, + 0x86, 0x4C, 0xEB, 0x13, 0x5B, 0x63, 0x9F, 0x48, 0xA5, 0x6C, 0xF5, 0xFC, 0x19, 0xFE, 0x85, 0x89, 0x80, 0xE5, 0x58, 0xF9, + 0xD5, 0xA3, 0x62, 0x28, 0x21, 0x50, 0x5A, 0x85, 0x12, 0x33, 0x2A, 0x04, 0x66, 0xD2, 0x4A, 0x51, 0x7A, 0x52, 0x19, 0x63, + 0xA5, 0x9C, 0xD4, 0x30, 0x7F, 0xDA, 0xCC, 0xAF, 0x4F, 0x13, 0x48, 0xC0, 0x1C, 0xBA, 0x21, 0x5B, 0xC3, 0x1B, 0x01, 0x21, + 0xBA, 0xD9, 0xDB, 0xE1, 0xA0, 0x86, 0x41, 0xB4, 0xDE, 0x11, 0x5F, 0xAE, 0x4A, 0x77, 0x0F, 0x35, 0x93, 0x53, 0xD9, 0x41, + 0xE7, 0x31, 0x83, 0x60, 0x94, 0xBA, 0x14, 0xC0, 0x06, 0x57, 0xAC, 0xA6, 0xC5, 0x5A, 0xA5, 0x4E, 0xD4, 0x21, 0x61, 0xE8, + 0x74, 0x7E, 0xD6, 0xC5, 0x21, 0x75, 0xD9, 0xA7, 0x15, 0xBC, 0xED, 0x5F, 0xDD, 0x9E, 0xE2, 0xF8, 0x31, 0xCA, 0x51, 0x34, + 0xCD, 0xDF, 0x05, 0x44, 0xED, 0x3E, 0xE0, 0xCE, 0xCD, 0x3D, 0xD5, 0x5A, 0xFA, 0x54, 0x99, 0xD1, 0xA9, 0x35, 0x3C, 0xB5, + 0xF7, 0x9A, 0x8E, 0x2D, 0xD4, 0x0C, 0xE7, 0x0A, 0xF5, 0xC4, 0xC6, 0x18, 0x31, 0x7B, 0x56, 0xAD, 0x76, 0xD3, 0x1C, 0xDB, + 0x4E, 0x57, 0x14, 0x09, 0x56, 0x1B, 0xA9, 0x29, 0x2F, 0x7B, 0xDE, 0x3C, 0x35, 0x1B, 0x18, 0x0D, 0xE1, 0xEA, 0x54, 0xC9, + 0x1C, 0x99, 0x61, 0xEB, 0x43, 0x99, 0xC3, 0x18, 0xDF, 0x1A, 0xA3, 0xDA, 0xC6, 0x55, 0x49, 0xD9, 0x95, 0xD1, 0x55, 0x69, + 0xA8, 0x59, 0x4B, 0x68, 0x92, 0x19, 0x1A, 0xBA, 0xFD, 0xF6, 0x4B, 0x18, 0xD7, 0xD1, 0x02, 0x6D, 0x04, 0x7F, 0x16, 0xBC, + 0x86, 0x37, 0x8F, 0xEB, 0xEE, 0x38, 0x98, 0x68, 0x30, 0x39, 0x90, 0x2D, 0x44, 0xF6, 0x71, 0xAC, 0x33, 0x34, 0x5E, 0x07, + 0x94, 0xA2, 0x4E, 0x8F, 0x5D, 0xF4, 0x45, 0x69, 0x80, 0x3C, 0x06, 0x49, 0x89, 0x5A, 0x75, 0xE9, 0xEA, 0x5E, 0xDF, 0xE8, + 0x85, 0x81, 0x9F, 0xFD, 0x8D, 0x3F, 0x4B, 0x20, 0x44, 0x7E, 0xA0, 0x06, 0x16, 0x59, 0x6E, 0x9D, 0xB3, 0xD2, 0x75, 0x69, + 0x89, 0x36, 0xA0, 0x87, 0x1A, 0xC3, 0x84, 0x40, 0x2C, 0x63, 0xF4, 0xD3, 0x3B, 0x4A, 0x72, 0x10, 0x97, 0x8B, 0xBC, 0x97, + 0x5B, 0x41, 0xC3, 0x75, 0xAC, 0xA2, 0xFC, 0xB7, 0x7B, 0x82, 0x1A, 0x73, 0x04, 0x9D, 0x7F, 0xF2, 0xDF, 0xC1, 0xCE, 0x50, + 0xA6, 0x11, 0xB7, 0x86, 0xFA, 0x81, 0xA9, 0xEE, 0x8D, 0x2E, 0x6D, 0x92, 0xBB, 0x81, 0x5E, 0x49, 0xA4, 0xC7, 0xF7, 0xE6, + 0xBA, 0xC3, 0xB4, 0x42, 0x06, 0x84, 0xD7, 0xC1, 0xFD, 0xE7, 0x3E, 0x73, 0x64, 0xE7, 0x30, 0xE2, 0xBB, 0xEA, 0x68, 0xF7, + 0x29, 0xE6, 0x38, 0x30, 0xEC, 0x3E, 0x36, 0x37, 0x69, 0x86, 0x03, 0xB4, 0xF6, 0x5A, 0x61, 0x43, 0x86, 0x86, 0x21, 0xD6, + 0x98, 0xBD, 0x35, 0xB7, 0x8D, 0x6C, 0xC9, 0x98, 0x55, 0xEB, 0xBD, 0x03, 0xC6, 0x0F, 0xE9, 0xD3, 0xCB, 0xF6, 0xFD, 0x16, + 0xEA, 0xAE, 0x91, 0x15, 0x24, 0x8B, 0x73, 0x4D, 0xC6, 0x4B, 0x7C, 0xDF, 0x13, 0x89, 0x4B, 0x59, 0x6A, 0x41, 0xE6, 0x8B, + 0x72, 0x03, 0x68, 0xE9, 0x3F, 0x7D, 0xFA, 0x1B, 0x17, 0xEB, 0x19, 0x9E, 0x95, 0xAA, 0x6E, 0xBF, 0x11, 0xCA, 0x2B, 0x1A, + 0x65, 0x49, 0xE7, 0x9A, 0xD0, 0xA9, 0x13, 0xA1, 0xCF, 0x4A, 0x6D, 0xFE, 0x97, 0x89, 0xFD, 0x68, 0xE3, 0xE5, 0x75, 0xEA, + 0x97, 0x49, 0xD7, 0x44, 0x07, 0xA8, 0x6F, 0x9A, 0x96, 0x41, 0x68, 0x1A, 0x4F, 0x0C, 0xD8, 0xB5, 0xEB, 0xA0, 0x6C, 0x1B, + 0x27, 0x27, 0x32, 0xEF, 0x01, 0xE6, 0x60, 0x0A, 0x4E, 0x05, 0xD4, 0x42, 0x19, 0x0F, 0x65, 0x03, 0x36, 0x74, 0x3F, 0x86, + 0xB9, 0x56, 0xB7, 0xEE, 0xA0, 0x24, 0xDB, 0x30, 0x1F, 0xA3, 0xAD, 0x9E, 0xA1, 0x77, 0x7B, 0x93, 0x38, 0x15, 0x61, 0x0B, + 0xCF, 0x8C, 0x38, 0x9D, 0x3E, 0x50, 0xE4, 0x06, 0xB2, 0x36, 0x1E, 0x0D, 0x34, 0xFC, 0xE0, 0xD6, 0x85, 0xCF, 0x62, 0x73, + 0x78, 0xB3, 0x60, 0x53, 0xC7, 0x20, 0x7E, 0xD2, 0x1D, 0x3A, 0x7E, 0xAD, 0x4F, 0x2A, 0xF4, 0x12, 0x59, 0xBA, 0xF8, 0x5F, + 0x06, 0xD9, 0xE8, 0xB3, 0x51, 0xB0, 0x91, 0xE1, 0x1B, 0x47, 0xF1, 0x83, 0xB2, 0x73, 0x07, 0x92, 0x82, 0x90, 0x6B, 0xD3, + 0xBC, 0xF1, 0xA9, 0x17, 0xF9, 0xC2, 0x6D, 0x93, 0x9B, 0x90, 0xFD, 0x36, 0xA0, 0xDE, 0x2D, 0x93, 0xD1, 0xB2, 0x24, 0x47, + 0x08, 0xB6, 0xDA, 0xDA, 0x05, 0x40, 0xE7, 0xD9, 0xE8, 0x7B, 0x24, 0x54, 0xC8, 0xF6, 0x2C, 0xD2, 0x6B, 0x97, 0x68, 0xE9, + 0x1D, 0xF4, 0x42, 0x56, 0x06, 0x82, 0x9D, 0x72, 0x3D, 0x6D, 0xA1, 0x66, 0x88, 0xF5, 0x25, 0x56, 0xE7, 0xBE, 0xA5, 0x98, + 0x68, 0x09, 0xAC, 0x43, 0x53, 0xED, 0xA9, 0x76, 0xA7, 0x7C, 0x32, 0x28, 0x93, 0x4C, 0x65, 0x72, 0x0E, 0x94, 0xF5, 0xF2, + 0x0B, 0xD4, 0x9B, 0xB7, 0xD3, 0xC5, 0x26, 0x0F, 0x7B, 0xB3, 0xCD, 0x8D, 0xCD, 0x27, 0x26, 0xAA, 0x5E, 0xDB, 0x55, 0xF1, + 0x46, 0x96, 0x2E, 0x3B, 0x17, 0xD9, 0xB2, 0x1F, 0x4B, 0xF8, 0x6A, 0x1B, 0x53, 0x9A, 0xF4, 0xD0, 0x51, 0x26, 0x67, 0xBA, + 0x9F, 0xF8, 0xA7, 0xAB, 0xE2, 0xBA, 0x33, 0x0A, 0xD2, 0x99, 0xA8, 0xA9, 0x9A, 0x9B, 0x6B, 0x4B, 0x9E, 0xF9, 0x7B, 0xAE, + 0x82, 0x1B, 0x3B, 0x1F, 0xD7, 0x9B, 0xE2, 0x6F, 0x00, 0x9E, 0x19, 0xEA, 0xBC, 0xDB, 0x6C, 0xC5, 0x4F, 0xAC, 0x66, 0x13, + 0x81, 0xBD, 0xBA, 0x2F, 0x40, 0xF6, 0xB4, 0xC3, 0x39, 0x3F, 0x66, 0xEB, 0x86, 0x9E, 0x01, 0xDA, 0xFD, 0xF5, 0x67, 0xDE, + 0xAC, 0xFC, 0x98, 0xAD, 0x41, 0xD2, 0x49, 0x4F, 0x8F, 0xA9, 0x28, 0x10, 0xDA, 0x05, 0xBB, 0x7E, 0xAD, 0x9F, 0x5C, 0xA5, + 0x3E, 0xB2, 0x0D, 0xD5, 0xAF, 0x2B, 0x43, 0x80, 0x5C, 0xBE, 0xA7, 0x2C, 0xE1, 0xAF, 0x93, 0x38, 0x58, 0xB1, 0xD0, 0xB1, + 0x23, 0xBF, 0xD2, 0x77, 0xA1, 0xE9, 0x1F, 0xEF, 0xEA, 0x70, 0x8E, 0x39, 0x70, 0x30, 0x1C, 0x25, 0x47, 0x03, 0x25, 0x44, + 0xE7, 0x68, 0x96, 0xF2, 0xA2, 0xA9, 0xBF, 0x3D, 0xB3, 0x62, 0xD1, 0x25, 0xAA, 0xB5, 0xB1, 0xAF, 0xD1, 0xE0, 0x77, 0x29, + 0x87, 0x41, 0x87, 0x38, 0xB2, 0xF4, 0x63, 0x43, 0x62, 0x26, 0x8D, 0x5A, 0xB0, 0x16, 0xFA, 0x87, 0xC0, 0x54, 0x6C, 0xD7, + 0x34, 0x2E, 0x6E, 0xBC, 0xE5, 0x5F, 0x79, 0x75, 0x78, 0x4C, 0x11, 0x47, 0x64, 0xF5, 0xB6, 0x52, 0xF2, 0xA6, 0x5D, 0x92, + 0x70, 0xE7, 0xE6, 0x15, 0xF0, 0x7E, 0x49, 0x55, 0xE5, 0x56, 0x91, 0xB5, 0x7C, 0x57, 0x13, 0x07, 0x40, 0x45, 0x3C, 0xE7, + 0x7C, 0x6F, 0x89, 0x35, 0x9D, 0x01, 0xE9, 0xA6, 0x1F, 0x2A, 0xE1, 0xF3, 0xE1, 0xB7, 0x7A, 0x03, 0x7F, 0x68, 0x78, 0x7A, + 0xAB, 0x6D, 0x42, 0x89, 0x70, 0x25, 0x6A, 0xAC, 0x4E, 0xC7, 0x8A, 0xB4, 0xE5, 0xE1, 0x19, 0xF8, 0x0D, 0xA9, 0xF4, 0xBC, + 0xF0, 0x98, 0xE5, 0x7F, 0xA0, 0x4A, 0x6F, 0x38, 0xD9, 0x2B, 0x7B, 0x18, 0xF8, 0xA7, 0xFD, 0x30, 0x34, 0x27, 0x2B, 0xD7, + 0x64, 0x47, 0x22, 0x4D, 0x96, 0x1D, 0x9E, 0x69, 0xB9, 0xA3, 0x27, 0x8F, 0xA9, 0x23, 0xFC, 0x47, 0xA8, 0x4F, 0x5B, 0xAC, + 0x38, 0x92, 0x12, 0x41, 0xAB, 0xA3, 0xBF, 0x3E, 0x65, 0x0C, 0x2A, 0x2F, 0xA3, 0x96, 0x8F, 0x74, 0xF7, 0x09, 0x13, 0xC1, + 0xAC, 0x16, 0xF7, 0x16, 0x1D, 0x0F, 0x03, 0x62, 0x4D, 0x64, 0x6E, 0x9E, 0xF7, 0xE6, 0x88, 0x0F, 0xCA, 0x83, 0x38, 0xB6, + 0x69, 0x32, 0x35, 0x08, 0x21, 0x6D, 0xAB, 0x85, 0x82, 0x23, 0x0B, 0xBF, 0xB8, 0x4F, 0x6F, 0x2E, 0xFD, 0xD7, 0xA5, 0x91, + 0x57, 0xE2, 0xDF, 0x9F, 0xDD, 0x46, 0x01, 0x04, 0x26, 0x9F, 0x17, 0xBF, 0xBE, 0xB9, 0x10, 0x88, 0xA8, 0xE1, 0xAA, 0x99, + 0x11, 0x74, 0x2C, 0x24, 0xA3, 0x80, 0x4E, 0x90, 0xD3, 0x58, 0x62, 0x10, 0x8A, 0x20, 0x5C, 0x25, 0x90, 0xAE, 0x3F, 0x63, + 0x0C, 0x1D, 0x19, 0x65, 0xAE, 0x70, 0x86, 0xD3, 0x0B, 0xA3, 0xF7, 0xA7, 0xF1, 0x10, 0x73, 0x60, 0x02, 0x63, 0x8E, 0x11, + 0xBF, 0x92, 0x63, 0x89, 0xE7, 0x11, 0x02, 0x55, 0xA1, 0xAE, 0xFC, 0x28, 0x78, 0x5B, 0x96, 0x14, 0x79, 0x8B, 0x6A, 0x30, + 0xFE, 0x5B, 0xE0, 0xB8, 0x11, 0xEB, 0x87, 0x17, 0xE9, 0x3C, 0xB7, 0xA7, 0x19, 0x9E, 0xDC, 0xE1, 0x45, 0xF8, 0xE6, 0x44, + 0xA7, 0xDA, 0x85, 0x39, 0x1D, 0xBB, 0xFB, 0x60, 0xF1, 0x94, 0x77, 0x92, 0x41, 0x5F, 0xC3, 0xD1, 0x19, 0x32, 0x05, 0xC0, + 0x4A, 0x3E, 0xB5, 0xDD, 0x53, 0xB6, 0x17, 0xC0, 0xC5, 0xD5, 0x79, 0x97, 0xD0, 0x37, 0x38, 0xB0, 0x2E, 0x5A, 0xBC, 0x6E, + 0x94, 0x37, 0x6C, 0xCA, 0x9F, 0x3D, 0x8C, 0xD5, 0x59, 0xF8, 0x76, 0x95, 0xC9, 0xB8, 0x8B, 0xEF, 0x4D, 0x7B, 0x4E, 0xCB, + 0x15, 0x1B, 0x29, 0x85, 0x5D, 0x82, 0x14, 0xFA, 0x94, 0xB1, 0xA1, 0xB1, 0xC0, 0x3E, 0x2F, 0x56, 0x67, 0xFC, 0x2C, 0x1F, + 0x85, 0x1A, 0xAB, 0xA2, 0x2D, 0x84, 0x4B, 0xA8, 0x58, 0x34, 0x5D, 0x6C, 0xE8, 0x1A, 0x60, 0x99, 0x18, 0x60, 0x44, 0x3B, + 0x7D, 0x07, 0xF5, 0x3F, 0xBE, 0xB1, 0x70, 0x4C, 0xC9, 0xD8, 0xE2, 0xA0, 0x93, 0xBD, 0x17, 0xC6, 0xCE, 0xEB, 0x0E, 0x5D, + 0xAE, 0x90, 0xA3, 0x0B, 0x41, 0x46, 0xF8, 0x1E, 0x43, 0xD2, 0x00, 0xAF, 0x55, 0x72, 0x95, 0xD6, 0x51, 0x5A, 0x0E, 0x65, + 0x4D, 0xD3, 0xF1, 0x3D, 0x59, 0xFB, 0xB0, 0x49, 0x5C, 0xB2, 0x1D, 0x0D, 0x0F, 0xC0, 0x9E, 0x9F, 0x14, 0xF2, 0x4E, 0x8F, + 0x10, 0x9E, 0xB5, 0xE2, 0xB9, 0x0D, 0xA5, 0x75, 0x6C, 0x26, 0x49, 0x51, 0x38, 0x49, 0xA8, 0xB2, 0x52, 0x82, 0x71, 0x52, + 0xA0, 0x3E, 0x57, 0x32, 0x13, 0x63, 0x9B, 0x0F, 0x99, 0xC2, 0x83, 0x46, 0xD5, 0xF7, 0x5F, 0x2E, 0x6F, 0x13, 0xA1, 0xC7, + 0x98, 0x59, 0x11, 0xA9, 0xC7, 0x22, 0xB0, 0xA3, 0x96, 0x4E, 0x5B, 0x12, 0x9D, 0xC1, 0x29, 0xE8, 0x77, 0xCA, 0x1F, 0x0B, + 0xBD, 0x63, 0xF1, 0x3B, 0x2D, 0x32, 0x98, 0xAA, 0x48, 0xCB, 0x9E, 0xF2, 0xFF, 0x07, 0x08, 0x94, 0x40, 0x2F, 0x80, 0x04, + 0x65, 0x90, 0x38, 0x4F, 0xA6, 0xE9, 0xBA, 0x0F, 0xFC, 0x26, 0x82, 0x00, 0xC5, 0x11, 0x80, 0x52, 0xB6, 0x4A, 0x31, 0x5F, + 0xDC, 0x80, 0x6A, 0xB4, 0xFC, 0x0B, 0x46, 0x8B, 0x52, 0x3B, 0x63, 0xE5, 0x78, 0x4F, 0x0F, 0x8F, 0xB4, 0x55, 0xD7, 0xF2, + 0xC6, 0x08, 0x25, 0x91, 0x45, 0xC3, 0xE8, 0x84, 0x82, 0xE1, 0x64, 0xFA, 0x6D, 0x71, 0x24, 0x7D, 0x68, 0xCE, 0x21, 0x59, + 0x3C, 0xC3, 0x05, 0x17, 0x5A, 0x39, 0x15, 0xFA, 0x51, 0xCB, 0x15, 0x6E, 0x7A, 0xA2, 0x58, 0x12, 0xA4, 0xB8, 0x0D, 0x07, + 0x79, 0x87, 0x3B, 0x0F, 0x0C, 0xBA, 0xB9, 0xFB, 0xBD, 0x5A, 0xB3, 0x3A, 0xF0, 0xA6, 0x58, 0x30, 0xA4, 0xAB, 0x6D, 0xEB, + 0x6F, 0x72, 0xBD, 0x6C, 0xE9, 0xAD, 0x59, 0x3B, 0xCE, 0x8B, 0x85, 0x9F, 0x1F, 0x7F, 0x9A, 0x2C, 0xF1, 0x8F, 0x36, 0x43, + 0x0A, 0xA8, 0xD2, 0x08, 0xC3, 0xAE, 0x59, 0xA3, 0xFD, 0xEA, 0x92, 0x38, 0xE4, 0x57, 0xA4, 0xA1, 0xF6, 0x0E, 0x7E, 0x09, + 0x0C, 0xB9, 0x68, 0x0D, 0x3B, 0x81, 0xDD, 0x43, 0x6D, 0x0E, 0x4A, 0x3C, 0xF8, 0x24, 0x8E, 0x8B, 0xCA, 0xB5, 0x85, 0xC4, + 0x7D, 0x41, 0x83, 0x4B, 0xBC, 0x5D, 0xA1, 0x8E, 0x68, 0x02, 0x03, 0x69, 0x24, 0x8C, 0x9D, 0xBA, 0xDE, 0xAF, 0x93, 0xAE, + 0x22, 0xC1, 0x10, 0x64, 0xBB, 0x1D, 0x0A, 0x9B, 0x0D, 0x41, 0x73, 0x40, 0xF9, 0xEB, 0xEC, 0x16, 0xC6, 0x0C, 0x3B, 0xE6, + 0xB5, 0x37, 0x24, 0x3A, 0xEA, 0x2C, 0xC2, 0x17, 0x46, 0xD7, 0x02, 0x07, 0xE6, 0x60, 0xF5, 0x15, 0x25, 0x1F, 0x6D, 0xA7, + 0x0D, 0xA3, 0x16, 0xD1, 0x3E, 0xDB, 0x55, 0xB4, 0x5C, 0x9C, 0x8D, 0xD7, 0xE4, 0xF1, 0x5F, 0xF9, 0x10, 0x5A, 0x7D, 0xD6, + 0x1A, 0x57, 0xAF, 0x85, 0xF0, 0x9C, 0xDA, 0x77, 0x75, 0xE1, 0x20, 0xA5, 0xB8, 0xDC, 0xCA, 0xD3, 0xFB, 0x52, 0x12, 0x0E, + 0x14, 0x17, 0x5D, 0x2D, 0xDE, 0xD6, 0x42, 0x22, 0xAD, 0x96, 0x75, 0x72, 0x2C, 0x60, 0x63, 0xBC, 0xC6, 0x49, 0x1E, 0xB4, + 0xD4, 0x3C, 0xF5, 0x82, 0x2E, 0xBA, 0xBF, 0xA7, 0xF2, 0xD3, 0x53, 0x0F, 0x00, 0x8C, 0xA7, 0xFB, 0x44, 0x1A, 0x82, 0x9C, + 0x68, 0x21, 0xC5, 0x97, 0xF3, 0xD2, 0xE6, 0x1B, 0x4F, 0x1F, 0x64, 0x8A, 0xC3, 0xC7, 0x16, 0x38, 0xEC, 0xD0, 0xCE, 0x0A, + 0x4F, 0x1C, 0x51, 0x6A, 0x25, 0x96, 0x11, 0xE2, 0x1C, 0x29, 0x06, 0x49, 0x11, 0xBC, 0xA6, 0xAE, 0x9A, 0xE2, 0xD6, 0x87, + 0xAA, 0xD8, 0x99, 0xB3, 0x32, 0x65, 0x30, 0x2F, 0xEA, 0x55, 0x6D, 0xB2, 0x15, 0xB9, 0x9B, 0x6B, 0x89, 0x94, 0x6F, 0x1A, + 0xAD, 0xF9, 0x07, 0x48, 0xCF, 0x7F, 0xDB, 0xAB, 0xCE, 0xDD, 0xA5, 0xAC, 0x46, 0x46, 0xB2, 0x3F, 0x9D, 0xAC, 0x7E, 0xEF, + 0xF3, 0x21, 0xA5, 0x9D, 0x4A, 0x5D, 0x6C, 0xD3, 0x8A, 0x86, 0x4E, 0xAC, 0x5D, 0x09, 0x00, 0x4B, 0x84, 0x5E, 0x3E, 0x27, + 0x51, 0x62, 0x3E, 0x5A, 0x09, 0x9D, 0xD5, 0xFF, 0x1C, 0x11, 0xDA, 0x99, 0x05, 0x1D, 0xCF, 0x10, 0x17, 0xCF, 0x2D, 0x3D, + 0x9C, 0x3D, 0x91, 0xD8, 0xB9, 0x9D, 0x01, 0x5E, 0x58, 0x82, 0x4B, 0x9D, 0x04, 0x91, 0x59, 0x92, 0xA5, 0xB6, 0xBE, 0x58, + 0x78, 0x2D, 0x5C, 0x33, 0x24, 0x0A, 0x50, 0xB4, 0x0F, 0xF5, 0x70, 0x98, 0xA4, 0x88, 0xB2, 0xA4, 0xFB, 0x8E, 0x7D, 0x4A, + 0xE6, 0x51, 0x1F, 0xB7, 0x85, 0x82, 0x3A, 0x71, 0x00, 0xAD, 0x93, 0x99, 0x7B, 0x66, 0x48, 0xA7, 0x67, 0x59, 0x44, 0x1E, + 0xA2, 0x20, 0x29, 0x82, 0x22, 0x0B, 0x2D, 0x6B, 0x32, 0x46, 0x26, 0xD7, 0x20, 0xEC, 0x3E, 0x9D, 0x5E, 0xCE, 0x8F, 0x7A, + 0x3C, 0xB1, 0x3F, 0x60, 0x9F, 0xA9, 0x90, 0xE4, 0x8E, 0x06, 0x68, 0x9B, 0xDF, 0x7F, 0xEB, 0xF9, 0xDF, 0x56, 0xAA, 0x54, + 0xE4, 0x3E, 0x4E, 0xC0, 0x45, 0x07, 0x99, 0x12, 0x85, 0xBA, 0x12, 0xC5, 0xDE, 0x20, 0xA7, 0x89, 0x6D, 0xAB, 0x95, 0x9F, + 0xA1, 0x30, 0xB5, 0x03, 0x0C, 0x99, 0xA5, 0x22, 0xB5, 0x81, 0x6A, 0x12, 0x36, 0xD1, 0x42, 0x8E, 0x4E, 0xEA, 0x49, 0x4B, + 0x98, 0x92, 0x82, 0x2B, 0x7A, 0xA5, 0x3D, 0xEE, 0x1E, 0x92, 0x5F, 0x17, 0x7C, 0x9D, 0xC3, 0xBE, 0xE9, 0xC5, 0x12, 0x00, + 0x6A, 0x40, 0x26, 0x63, 0xDB, 0xD6, 0xDA, 0x18, 0x49, 0x52, 0x3E, 0x7C, 0x1D, 0xC2, 0x49, 0x99, 0xE1, 0xEB, 0xB3, 0xFD, + 0x67, 0x25, 0x06, 0xAD, 0xBB, 0xDA, 0x45, 0x5D, 0x58, 0xEC, 0xCB, 0xC0, 0xE7, 0x49, 0x30, 0x6D, 0x19, 0xAD, 0xFA, 0x5F, + 0xEA, 0x0B, 0x4D, 0x38, 0xB2, 0x78, 0x7B, 0x3B, 0x30, 0x85, 0x79, 0x3C, 0x9A, 0x83, 0x57, 0x6A, 0x66, 0xC7, 0x18, 0x23, + 0xA7, 0x10, 0xC8, 0xA9, 0x31, 0x6D, 0xEA, 0xCF, 0xB8, 0x6C, 0x9A, 0x6F, 0xB4, 0xC6, 0xE4, 0xAC, 0x30, 0x62, 0x63, 0xDB, + 0x06, 0x06, 0xBB, 0xC5, 0x3F, 0xA7, 0x96, 0x58, 0xA8, 0x0C, 0x7A, 0x13, 0x4F, 0x2F, 0x15, 0xF5, 0x3A, 0x63, 0xF3, 0xA7, + 0x37, 0x22, 0x9E, 0x48, 0xB5, 0x0D, 0x5B, 0x4F, 0x2F, 0x60, 0x57, 0xF3, 0x4C, 0x19, 0xBA, 0xA8, 0x11, 0x70, 0x1C, 0xB4, + 0x89, 0x1A, 0xCE, 0x29, 0x18, 0xF3, 0x34, 0x6F, 0xC8, 0x20, 0x90, 0xF6, 0x79, 0xF0, 0xDC, 0x69, 0x1A, 0x13, 0xC6, 0x38, + 0x19, 0xF2, 0x43, 0xF2, 0x94, 0xB3, 0x99, 0xE7, 0xF8, 0x03, 0x0B, 0x60, 0xC1, 0xD9, 0x55, 0x21, 0x3C, 0x8D, 0xD9, 0x6F, + 0xC2, 0xC9, 0x91, 0x3E, 0x95, 0xBE, 0xD6, 0xC7, 0x1C, 0x58, 0x5D, 0x31, 0x3B, 0x1F, 0x06, 0xCD, 0x23, 0x36, 0xBA, 0xC2, + 0x51, 0xC0, 0x94, 0x65, 0xCB, 0x5E, 0x74, 0x96, 0x10, 0x80, 0x8C, 0xCD, 0xA9, 0x7B, 0x95, 0x7E, 0x96, 0xEA, 0xA3, 0x74, + 0x18, 0x3C, 0xBA, 0x38, 0x10, 0x71, 0x85, 0x51, 0x21, 0xA4, 0x16, 0x36, 0x3E, 0x77, 0xD6, 0xDA, 0x94, 0xDB, 0xAB, 0xE2, + 0xD6, 0x18, 0x73, 0x7D, 0x7D, 0xCA, 0xCC, 0xB3, 0x4C, 0x2C, 0x63, 0xED, 0xE5, 0x35, 0xA4, 0x8F, 0x92, 0x73, 0xC6, 0x51, + 0x46, 0x5A, 0xF8, 0x3D, 0xD3, 0xFB, 0x8B, 0xEF, 0x81, 0x12, 0x56, 0x3C, 0x7C, 0xF3, 0x3A, 0x20, 0xC0, 0xD8, 0x7C, 0x11, + 0x98, 0x7B, 0xB2, 0xCB, 0x6A, 0xFF, 0x5E, 0xC4, 0x86, 0xF2, 0x48, 0xC8, 0xA9, 0x5A, 0xD9, 0x30, 0x47, 0x3C, 0x71, 0x68, + 0xA8, 0xA5, 0x72, 0x9C, 0x9A, 0x38, 0x17, 0x09, 0x24, 0xB6, 0x4B, 0x63, 0x3B, 0xFC, 0x90, 0xA9, 0x35, 0x54, 0x7E, 0x8C, + 0x9B, 0x39, 0x86, 0x58, 0x76, 0x14, 0xA6, 0xAA, 0xC9, 0x2C, 0x6C, 0xA8, 0x76, 0xFC, 0xB7, 0xC8, 0x54, 0xA3, 0x09, 0x5C, + 0x77, 0x3B, 0x31, 0xA2, 0xAD, 0xE2, 0x3C, 0xFC, 0x6A, 0x1D, 0x65, 0x4C, 0x97, 0xA2, 0x81, 0x4D, 0xE8, 0x10, 0x7F, 0x36, + 0x9E, 0x48, 0x85, 0x9A, 0x80, 0x30, 0x68, 0xDD, 0xDB, 0x81, 0xE3, 0xAA, 0x9D, 0xE9, 0xF0, 0x56, 0x40, 0xA2, 0x59, 0x4D, + 0x0A, 0xF0, 0x4F, 0x8F, 0xC8, 0x08, 0x6F, 0x43, 0x05, 0xC0, 0x80, 0xC6, 0x58, 0xED, 0x71, 0x44, 0x67, 0x80, 0x89, 0x61, + 0xBD, 0xF3, 0x6A, 0x63, 0x61, 0x88, 0x17, 0xF4, 0x13, 0x1B, 0x26, 0x6F, 0x66, 0x51, 0xA2, 0x34, 0x97, 0x7A, 0x15, 0xBB, + 0x6D, 0xE8, 0x5E, 0x83, 0xCF, 0xA7, 0x05, 0x9B, 0x2D, 0xC8, 0xD3, 0xAF, 0x3D, 0x01, 0x6B, 0xEF, 0x85, 0x2E, 0xF6, 0xE7, + 0xD5, 0x02, 0x95, 0x40, 0xC2, 0x65, 0xF1, 0x23, 0xBE, 0x00, 0x5E, 0xEE, 0xC4, 0x96, 0x9F, 0x61, 0xB7, 0x7B, 0xB0, 0x75, + 0xCB, 0x86, 0x60, 0xE4, 0xB8, 0xAF, 0x0A, 0xAA, 0x04, 0x45, 0x15, 0x5E, 0xB2, 0x9A, 0x6E, 0xC2, 0x41, 0x87, 0x85, 0x51, + 0xF6, 0xBA, 0x5F, 0xEA, 0xE7, 0x82, 0x55, 0x25, 0x69, 0xEB, 0x33, 0x67, 0xA5, 0xB0, 0xC9, 0x8D, 0x7A, 0xEB, 0x37, 0xFA, + 0x74, 0x2C, 0xE8, 0x31, 0x20, 0xB7, 0x62, 0x8C, 0xA4, 0xB1, 0x4D, 0x15, 0x68, 0xA6, 0xB3, 0x3B, 0x4F, 0x77, 0xB3, 0xFD, + 0x2C, 0x08, 0x7E, 0xED, 0x8E, 0x48, 0xC9, 0xDF, 0x6E, 0xFA, 0x65, 0x23, 0x0B, 0x33, 0xC8, 0x0F, 0x1E, 0xEB, 0x96, 0x49, + 0x4E, 0x6F, 0xE8, 0x79, 0x97, 0xB9, 0x98, 0xBA, 0xB4, 0xC8, 0x28, 0x7C, 0xC9, 0xC6, 0x3B, 0x2F, 0x64, 0x59, 0xED, 0x9F, + 0xD4, 0x47, 0x27, 0x5B, 0x89, 0xAE, 0xAD, 0x2A, 0xD5, 0xFA, 0xB4, 0xFC, 0x0F, 0x4B, 0xB3, 0x3B, 0x54, 0x36, 0xB3, 0xC2, + 0x75, 0x6C, 0x5A, 0x01, 0xAD, 0xED, 0x64, 0xD7, 0x48, 0x8E, 0x2B, 0x71, 0x61, 0x76, 0xAA, 0x47, 0x85, 0xCF, 0x15, 0x2D, + 0x6F, 0xCE, 0xB4, 0x41, 0x3D, 0x40, 0x43, 0x20, 0x7B, 0x4C, 0xA3, 0xDB, 0x09, 0x3E, 0xDD, 0x76, 0xF6, 0xA3, 0x68, 0x2C, + 0xC8, 0x6C, 0x5C, 0x00, 0x03, 0x32, 0xAB, 0x20, 0x02, 0xCD, 0x10, 0xAF, 0xCC, 0x5E, 0x84, 0xFF, 0xB4, 0xA6, 0xC3, 0x4F, + 0x8D, 0x40, 0xB5, 0x11, 0x67, 0x6F, 0x41, 0xE4, 0xCB, 0xDC, 0x06, 0x5D, 0x57, 0x76, 0x74, 0xE0, 0xD5, 0x9C, 0xEC, 0x4B, + 0x5D, 0xD3, 0x62, 0xE5, 0x47, 0x19, 0x5B, 0xC0, 0xA7, 0xD1, 0xEF, 0xE7, 0x4B, 0xFA, 0x1B, 0xAA, 0x66, 0x92, 0x9B, 0x8E, + 0xB2, 0x10, 0x8D, 0x58, 0x69, 0x2F, 0x75, 0x36, 0xBB, 0x5F, 0x62, 0xD2, 0xA4, 0xD3, 0x78, 0x77, 0xBF, 0xF1, 0x35, 0xBE, + 0x67, 0x0F, 0xF9, 0x33, 0xBF, 0xA6, 0xDF, 0x46, 0x64, 0x64, 0x85, 0x3C, 0xD7, 0xCF, 0x22, 0xF1, 0x04, 0x27, 0x0C, 0xEE, + 0xD1, 0xB5, 0x2E, 0xDF, 0x24, 0x15, 0x95, 0x11, 0x33, 0x97, 0xAD, 0x5A, 0x2F, 0x56, 0xB8, 0xB8, 0xF5, 0x12, 0x6D, 0xCF, + 0x29, 0xD4, 0xF6, 0x2B, 0xBE, 0x89, 0x53, 0x4A, 0x88, 0x72, 0x95, 0x50, 0xD1, 0xB4, 0x6B, 0x62, 0x2E, 0xCA, 0x22, 0x55, + 0x59, 0xFC, 0x49, 0x44, 0x1B, 0x14, 0xDF, 0xD3, 0x1E, 0xDC, 0x12, 0x32, 0x2A, 0x22, 0xE0, 0xA0, 0x3D, 0x78, 0xFB, 0x5A, + 0x64, 0xD7, 0xBE, 0xBA, 0x0B, 0x98, 0x08, 0xAF, 0x70, 0x3D, 0x8E, 0x1E, 0x4A, 0x26, 0xC6, 0x52, 0xF7, 0x94, 0x65, 0x44, + 0x02, 0xEB, 0x14, 0x7B, 0xA4, 0x95, 0x7C, 0x8A, 0xC3, 0xA7, 0x6E, 0x85, 0x8F, 0x58, 0x68, 0xC5, 0x7C, 0xF8, 0xB9, 0x5B, + 0x65, 0x5A, 0x70, 0x17, 0x3D, 0xEB, 0xC4, 0xB3, 0x48, 0x24, 0x9F, 0xB3, 0xFB, 0x79, 0x58, 0x7B, 0xA3, 0x1A, 0xDE, 0x34, + 0x92, 0xB1, 0xE6, 0x6E, 0x64, 0x12, 0x90, 0xDA, 0x95, 0xD7, 0xB9, 0x28, 0x0C, 0x7F, 0x5A, 0xBC, 0x1B, 0xA6, 0x7F, 0x9C, + 0x94, 0xCD, 0x80, 0x4E, 0x6F, 0x30, 0x63, 0x8B, 0xC3, 0x33, 0x98, 0xE8, 0x1F, 0x61, 0x2E, 0x48, 0x4B, 0x41, 0x67, 0x07, + 0x6C, 0x33, 0x35, 0x56, 0xC7, 0x1C, 0xC8, 0xB9, 0x48, 0xAF, 0xC7, 0x05, 0xFF, 0x92, 0x81, 0x4E, 0xDB, 0xFF, 0xA3, 0x2C, + 0xDC, 0x71, 0xD9, 0xB9, 0xB5, 0xA0, 0xB7, 0x94, 0x46, 0xC2, 0xB6, 0x10, 0x3C, 0x7B, 0xAD, 0x2C, 0xE0, 0xAE, 0x8C, 0x04, + 0x22, 0xE0, 0x65, 0xB4, 0x0B, 0x55, 0x1F, 0x06, 0x62, 0x15, 0x22, 0x39, 0x58, 0xB3, 0x79, 0x63, 0x6F, 0xA5, 0x19, 0xA5, + 0x8A, 0xDE, 0xB2, 0x53, 0xBB, 0x6D, 0x8C, 0xE2, 0xD1, 0xF7, 0xA9, 0x34, 0x6C, 0xA4, 0xE6, 0x5A, 0x4E, 0xB5, 0x0B, 0xCA, + 0xD7, 0xA8, 0xBB, 0x80, 0x42, 0x89, 0x82, 0x24, 0x0D, 0xA5, 0xD4, 0xE4, 0x79, 0x1C, 0xC6, 0x94, 0xAD, 0x2B, 0xEB, 0xF9, + 0xEA, 0xE4, 0xB6, 0x79, 0x20, 0x34, 0x9E, 0x98, 0x41, 0x08, 0xA2, 0x14, 0x5A, 0xE8, 0x18, 0xC1, 0x25, 0x00, 0x94, 0xA5, + 0xB5, 0xAB, 0x08, 0x65, 0x67, 0x4D, 0x88, 0x54, 0x77, 0x99, 0x31, 0xA0, 0x20, 0xF7, 0xE9, 0x44, 0x72, 0x88, 0x01, 0xF5, + 0xC5, 0xAC, 0xA7, 0x59, 0xB0, 0x16, 0xA2, 0x16, 0x84, 0x05, 0x02, 0x2C, 0x2B, 0x5B, 0x1A, 0x38, 0x3F, 0x68, 0xEE, 0x52, + 0xB3, 0x59, 0x08, 0xE5, 0x01, 0x0D, 0xF8, 0x1D, 0x57, 0x32, 0xB7, 0x46, 0xD4, 0x74, 0xA4, 0x14, 0xD4, 0x9F, 0xEF, 0x9A, + 0x98, 0x02, 0xA3, 0x84, 0x71, 0x69, 0x33, 0x2D, 0xBF, 0x4A, 0xCA, 0xA9, 0x7D, 0x95, 0x8B, 0xE4, 0x89, 0xFF, 0x5A, 0x7B, + 0xD9, 0x64, 0x84, 0xD9, 0xCD, 0x3E, 0xD3, 0x39, 0x05, 0x7A, 0x60, 0xBB, 0x6E, 0x17, 0x57, 0xA4, 0x62, 0x61, 0x65, 0x77, + 0x2E, 0x57, 0xC4, 0x40, 0xE9, 0xA1, 0x74, 0x6C, 0x38, 0x59, 0x4B, 0x65, 0x28, 0x8C, 0x42, 0x6C, 0xAF, 0x8C, 0x61, 0x9C, + 0x47, 0xC0, 0x60, 0x3D, 0xAB, 0x8C, 0xC1, 0xBE, 0xEA, 0x8A, 0xF2, 0x1F, 0xA3, 0x8F, 0x28, 0x9F, 0xFB, 0x1F, 0xD1, 0x39, + 0xD3, 0x14, 0x91, 0x58, 0x3C, 0x2B, 0x61, 0x91, 0x8B, 0x00, 0xDA, 0xF9, 0xD5, 0x95, 0xDF, 0xDE, 0x5F, 0x01, 0x13, 0x74, + 0x48, 0xC1, 0x02, 0xAD, 0xD3, 0xFD, 0xAA, 0x91, 0x18, 0x59, 0xCC, 0x69, 0x0A, 0x9C, 0x8A, 0x34, 0x39, 0x3B, 0xDC, 0x20, + 0x60, 0x13, 0x5C, 0x4C, 0x64, 0x75, 0xD8, 0x90, 0xDB, 0xED, 0xFC, 0xF6, 0x92, 0x7D, 0x45, 0x47, 0xA8, 0x22, 0x6A, 0x21, + 0xC5, 0x9D, 0x73, 0xAC, 0x4A, 0x10, 0xB3, 0x98, 0x3E, 0xB5, 0x5B, 0x7B, 0x5A, 0x11, 0x9F, 0xC7, 0xC2, 0x33, 0x04, 0xA6, + 0x01, 0xD4, 0x86, 0x27, 0xD9, 0x85, 0x8D, 0xDC, 0x59, 0x6A, 0xCD, 0x9F, 0xD1, 0xD4, 0x4E, 0x36, 0x10, 0x17, 0x5F, 0x24, + 0x4B, 0x94, 0xCD, 0x18, 0x0B, 0xDE, 0xDA, 0x14, 0xFE, 0x34, 0x47, 0x27, 0x43, 0x0D, 0x05, 0x55, 0x19, 0x99, 0x8A, 0xF0, + 0xE4, 0x94, 0x44, 0x96, 0xC6, 0xFF, 0xF5, 0xC1, 0x04, 0x7B, 0x5C, 0x3F, 0x16, 0xC8, 0xA2, 0x17, 0xE5, 0xF5, 0x62, 0x07, + 0xD0, 0xFF, 0x38, 0xB4, 0x6A, 0xE7, 0x02, 0x4C, 0x7C, 0x95, 0x50, 0x3B, 0x97, 0x65, 0x6E, 0x44, 0x50, 0x35, 0x06, 0x9C, + 0x01, 0x81, 0x8C, 0xEE, 0x0A, 0x31, 0xC5, 0xB9, 0xE9, 0x19, 0x9C, 0x5A, 0xF6, 0x8F, 0x39, 0x29, 0x25, 0xEC, 0x84, 0x1F, + 0xB4, 0x32, 0xFB, 0x36, 0xE9, 0xDA, 0x68, 0x45, 0xB6, 0x37, 0xCF, 0x09, 0xA8, 0x59, 0x77, 0xB9, 0xD2, 0x2A, 0xC4, 0xB9, + 0x74, 0x86, 0xD7, 0xB9, 0xF0, 0xFF, 0x24, 0xD8, 0x2B, 0x5D, 0xBC, 0xAC, 0x7E, 0xC1, 0x06, 0x17, 0x0B, 0x09, 0xE8, 0xF1, + 0x99, 0x75, 0x04, 0x78, 0xD4, 0xEA, 0x0B, 0xCF, 0x2F, 0xCC, 0xAB, 0x98, 0x73, 0xA0, 0x87, 0xCD, 0xDC, 0x7B, 0x27, 0xCB, + 0xD1, 0x13, 0xC5, 0x3E, 0xC6, 0x3A, 0x4F, 0xF5, 0x17, 0xD7, 0x00, 0x9E, 0xEE, 0xFE, 0x0F, 0x59, 0x42, 0x67, 0xEF, 0x49, + 0x5A, 0x90, 0x45, 0xD6, 0xCA, 0xDF, 0xF7, 0x93, 0xFD, 0xDD, 0x74, 0x11, 0x7C, 0xC4, 0x18, 0xF9, 0xF6, 0x80, 0x64, 0x51, + 0x6E, 0xB9, 0x8E, 0x0F, 0x5A, 0x82, 0xC4, 0x81, 0x1D, 0x89, 0x2A, 0x69, 0xF7, 0xE1, 0x8F, 0x82, 0x43, 0x43, 0xA9, 0x76, + 0x71, 0xA3, 0x07, 0x3B, 0x08, 0x8F, 0xA3, 0xEF, 0xB0, 0xA6, 0x29, 0x07, 0x30, 0xA1, 0xFB, 0x9A, 0x59, 0x44, 0x2B, 0xEE, + 0x8D, 0x87, 0xAF, 0xFF, 0xA7, 0x0E, 0xA5, 0xF4, 0x38, 0x65, 0xA5, 0x54, 0x3E, 0x22, 0x20, 0xB2, 0x0E, 0xCB, 0xA9, 0xAE, + 0x32, 0xE9, 0x4E, 0x2F, 0x67, 0x04, 0xCF, 0x84, 0xBF, 0xD4, 0x52, 0xBA, 0x47, 0xCA, 0x13, 0x2B, 0x34, 0x95, 0x33, 0x94, + 0xC5, 0x11, 0x39, 0xF2, 0x51, 0x43, 0x38, 0x4D, 0x62, 0x47, 0x1E, 0xAF, 0xEE, 0xEB, 0x28, 0x73, 0x63, 0x67, 0xD1, 0xE3, + 0x33, 0x67, 0x30, 0x73, 0x22, 0x26, 0x52, 0x47, 0x7C, 0xD6, 0x21, 0x11, 0x38, 0xDC, 0x39, 0xF2, 0x88, 0x5A, 0xA2, 0xF7, + 0x0C, 0x7C, 0xF2, 0xE8, 0x80, 0xEB, 0xE0, 0x54, 0x86, 0x6B, 0x8C, 0x1B, 0xD1, 0x4E, 0x3D, 0xF7, 0x45, 0x32, 0x06, 0x8C, + 0x55, 0xA3, 0x04, 0x37, 0x8F, 0x69, 0x3A, 0x58, 0x1D, 0xA6, 0xF3, 0xF7, 0x59, 0x71, 0xA5, 0x17, 0x75, 0x5B, 0x3B, 0xAF, + 0x50, 0xE9, 0x21, 0xEF, 0xCA, 0xF1, 0xD4, 0x9F, 0xF6, 0xA0, 0x2E, 0x20, 0xE1, 0x0B, 0x73, 0x33, 0xAE, 0xDA, 0xD9, 0x3E, + 0xDC, 0xC9, 0x73, 0xB5, 0x83, 0x2A, 0xBC, 0x62, 0x16, 0xA8, 0x70, 0x0C, 0xC3, 0x3A, 0x8A, 0x18, 0x3E, 0xBA, 0x95, 0x29, + 0x37, 0xE3, 0x94, 0x72, 0x19, 0x2F, 0xBA, 0x82, 0x5A, 0x8C, 0x85, 0xFA, 0x15, 0x92, 0x72, 0x8B, 0x8A, 0x75, 0xE5, 0x3D, + 0x75, 0xDF, 0x7B, 0x7A, 0x2F, 0x81, 0x33, 0xEB, 0x5B, 0xE3, 0x8C, 0x1B, 0xE1, 0x94, 0x97, 0xAC, 0xEF, 0xED, 0x22, 0x56, + 0xBC, 0xCF, 0xE9, 0x05, 0xD9, 0x8D, 0x62, 0xD8, 0xDB, 0xD2, 0x5B, 0x6E, 0xE4, 0x7D, 0x99, 0xC9, 0x19, 0xDB, 0x8E, 0x40, + 0x72, 0x49, 0x73, 0xF7, 0x4E, 0xF2, 0xD3, 0x12, 0x6C, 0x55, 0xEC, 0xDF, 0x44, 0x4B, 0x2A, 0xC4, 0x8A, 0xEA, 0x63, 0x89, + 0x5F, 0xD0, 0x5A, 0x6A, 0x84, 0x3F, 0xB5, 0x8C, 0xC2, 0x7F, 0xE4, 0xB8, 0xC4, 0x26, 0x2D, 0x8C, 0xC7, 0xD1, 0x0A, 0xA2, + 0x86, 0xE7, 0x8E, 0x02, 0x19, 0x10, 0xFD, 0xD1, 0xD4, 0xE3, 0x3C, 0xD3, 0x15, 0xA1, 0x71, 0x2E, 0x4E, 0xF9, 0xCB, 0x50, + 0xD0, 0xA4, 0xE9, 0x95, 0x6E, 0xFB, 0x2C, 0xB4, 0x65, 0xDA, 0x54, 0xC6, 0xDC, 0x04, 0xFD, 0xCA, 0x54, 0x74, 0x6D, 0xB1, + 0xBD, 0xA5, 0xDD, 0xA3, 0xEA, 0x8D, 0xE7, 0x34, 0xC6, 0xA6, 0x4F, 0x10, 0xDA, 0x72, 0xCF, 0x14, 0xC2, 0x5B, 0x4D, 0xDB, + 0x4E, 0x76, 0xEC, 0xB1, 0xF7, 0x18, 0x27, 0xF7, 0x40, 0x2A, 0xB5, 0xC3, 0x94, 0x85, 0x64, 0xCA, 0x2A, 0x3A, 0x1C, 0x71, + 0x03, 0xA9, 0xF6, 0x3A, 0x41, 0xB6, 0xD6, 0xB0, 0x46, 0xF5, 0x48, 0x61, 0x2B, 0x22, 0x08, 0x81, 0x59, 0x14, 0x58, 0x1F, + 0x6C, 0x41, 0x01, 0x79, 0xBF, 0xB9, 0x4E, 0x74, 0xAA, 0x38, 0xF8, 0x0E, 0xBA, 0x02, 0x88, 0x38, 0x8E, 0x07, 0x1B, 0x3C, + 0x90, 0x05, 0xB3, 0x6A, 0xC7, 0x9B, 0x3D, 0x6D, 0x9C, 0xDB, 0x01, 0x1F, 0xCE, 0x19, 0xB7, 0xB6, 0x00, 0x7D, 0x70, 0xAB, + 0xD1, 0xDE, 0x75, 0xDD, 0x2A, 0x4D, 0x64, 0xCC, 0x4F, 0x8E, 0xE0, 0xC2, 0x78, 0xBE, 0xB8, 0xB8, 0xD0, 0x30, 0x16, 0x5A, + 0x31, 0x17, 0x6C, 0x0C, 0x4E, 0x7C, 0xEC, 0x80, 0x79, 0x9F, 0xFE, 0x3C, 0x2C, 0x4A, 0xBE, 0xFE, 0xDD, 0x1E, 0x65, 0x04, + 0xCF, 0x2E, 0x51, 0x6B, 0xB4, 0xA1, 0x7E, 0x1C, 0x71, 0x97, 0xFF, 0xBD, 0xF7, 0xA4, 0x6D, 0x0C, 0xCE, 0x0F, 0xE6, 0x80, + 0x5C, 0x74, 0xE5, 0x31, 0x34, 0x42, 0x38, 0xFB, 0x00, 0x6D, 0xF3, 0x60, 0x0A, 0xCB, 0x86, 0x88, 0x56, 0xE2, 0xF1, 0x20, + 0xA2, 0x43, 0x48, 0x96, 0x9C, 0xD7, 0xBE, 0xB4, 0x47, 0x47, 0x3B, 0x80, 0x8D, 0x82, 0xC1, 0x79, 0x86, 0xA0, 0x16, 0x42, + 0x9E, 0x60, 0xD4, 0x1C, 0xC6, 0x00, 0x7E, 0xA1, 0xA6, 0xB6, 0xCD, 0x79, 0x7C, 0x0C, 0xC1, 0x10, 0xEE, 0x03, 0x66, 0xB5, + 0xBA, 0x2A, 0xC3, 0xBA, 0xB9, 0x30, 0xE3, 0xF4, 0xDE, 0xE7, 0x00, 0xC0, 0x97, 0x66, 0x10, 0x3B, 0x44, 0x86, 0x41, 0x23, + 0x5C, 0xCB, 0x88, 0xD4, 0x72, 0xFA, 0x0F, 0x96, 0xB2, 0xDA, 0x60, 0x8E, 0xEF, 0x48, 0xA6, 0x59, 0xD1, 0xA2, 0x1B, 0xCE, + 0xEA, 0x85, 0x16, 0x7B, 0x94, 0xA4, 0x90, 0xE3, 0x2C, 0xC0, 0x40, 0x16, 0xEE, 0x04, 0x92, 0x51, 0xE0, 0x71, 0xA1, 0x37, + 0x64, 0x65, 0xA6, 0x55, 0x38, 0xDC, 0x1C, 0x17, 0x2C, 0xBC, 0x04, 0x24, 0x88, 0x66, 0x12, 0xE4, 0x7C, 0x65, 0xD2, 0xAD, + 0xE1, 0x40, 0x52, 0xA8, 0x29, 0x97, 0xF5, 0xF0, 0x6D, 0x44, 0xD3, 0xB1, 0x1F, 0x6B, 0x43, 0x85, 0xEC, 0xC0, 0x8C, 0x90, + 0xB2, 0x2D, 0x93, 0xE1, 0xF0, 0x47, 0x78, 0x89, 0x9E, 0x8E, 0x97, 0xD4, 0xC0, 0x0B, 0x48, 0x2D, 0xBB, 0xFC, 0x94, 0xF9, + 0xD1, 0x10, 0x2F, 0xDA, 0x47, 0x21, 0x9B, 0x59, 0xC5, 0xB0, 0xA1, 0x8D, 0x3F, 0xC4, 0x54, 0xF9, 0x0C, 0x4E, 0xD9, 0x00, + 0x99, 0x21, 0x52, 0xEC, 0x75, 0xD0, 0xD2, 0xE8, 0x5C, 0x4A, 0x8A, 0xB5, 0xDA, 0xD9, 0x66, 0x23, 0xC1, 0xF0, 0xA2, 0x90, + 0x29, 0x00, 0x9A, 0xFE, 0xBD, 0x1B, 0x58, 0xB2, 0xF9, 0x0E, 0xBC, 0x8F, 0x3B, 0xB1, 0xC3, 0x1B, 0xF9, 0x46, 0x13, 0xD0, + 0x3C, 0x64, 0x1A, 0x46, 0xB1, 0x4D, 0xA8, 0x1D, 0xDF, 0x34, 0x41, 0x78, 0xEA, 0x0F, 0xE3, 0x82, 0xAC, 0x6F, 0x4C, 0x05, + 0x13, 0x51, 0xCC, 0x81, 0x4F, 0x10, 0x95, 0x48, 0x5E, 0x1D, 0xD5, 0x20, 0x36, 0x12, 0xCC, 0x4C, 0xDA, 0x53, 0xF3, 0xAB, + 0x29, 0x73, 0xEB, 0xB1, 0x6D, 0xAA, 0xE7, 0x4F, 0xF2, 0x7C, 0xBD, 0xB1, 0x3E, 0x50, 0x15, 0x78, 0xB0, 0x73, 0xEA, 0x25, + 0x8B, 0x2D, 0x55, 0xDD, 0xE5, 0xFF, 0x52, 0xF4, 0xA7, 0x71, 0xD2, 0xF0, 0x58, 0xE3, 0x19, 0x95, 0x08, 0x23, 0x60, 0x77, + 0x50, 0x2C, 0x0C, 0xDC, 0xA0, 0xF3, 0x7C, 0x2B, 0xD3, 0x6B, 0x8F, 0xE0, 0x51, 0xF7, 0x6F, 0x77, 0x46, 0x35, 0x74, 0x2F, + 0xC2, 0x8A, 0x33, 0x13, 0x35, 0x17, 0x9C, 0xB6, 0x65, 0xA6, 0x4D, 0x51, 0x9A, 0xBF, 0xA7, 0xA3, 0x55, 0x73, 0xB8, 0x2F, + 0x31, 0x3B, 0xED, 0xD1, 0x74, 0x14, 0x85, 0xC8, 0x94, 0x77, 0x32, 0x55, 0xE5, 0x45, 0x02, 0x15, 0xE5, 0x2C, 0xEE, 0x75, + 0xA1, 0xA5, 0xCB, 0x97, 0x08, 0xDA, 0x78, 0xCF, 0xFE, 0x12, 0x2A, 0x09, 0xCF, 0xC5, 0xFA, 0x3A, 0x2C, 0x52, 0xFE, 0xCE, + 0xC3, 0x76, 0x57, 0xB1, 0x8C, 0xE6, 0xD8, 0x1E, 0xD7, 0x7F, 0x18, 0x78, 0x25, 0xF4, 0x61, 0xD2, 0x0F, 0xA6, 0x83, 0x74, + 0xA0, 0x5B, 0x17, 0x92, 0xDA, 0x8E, 0x10, 0xDA, 0xB8, 0xDC, 0xAF, 0x47, 0x45, 0x8B, 0x75, 0xF9, 0xAF, 0x00, 0x4F, 0x1C, + 0x1C, 0x3B, 0x1C, 0xFE, 0x2B, 0x3B, 0xA0, 0x14, 0x02, 0xE6, 0x26, 0x7F, 0xEC, 0x11, 0x15, 0xAA, 0x09, 0xDD, 0x3E, 0x8A, + 0x95, 0x52, 0x98, 0x49, 0x89, 0xF7, 0xE7, 0xA6, 0xBE, 0x1B, 0xC8, 0x36, 0x3D, 0x3F, 0xD7, 0x86, 0xEA, 0x50, 0x84, 0x6F, + 0x09, 0x88, 0xBC, 0xEE, 0x0B, 0x61, 0x07, 0x5D, 0x06, 0x45, 0x6F, 0x17, 0xEC, 0xC7, 0xCF, 0xD4, 0x11, 0x3A, 0xB9, 0x5F, + 0x0A, 0x80, 0x47, 0xAF, 0x84, 0xBF, 0xE0, 0xBB, 0x4A, 0xAA, 0x7F, 0x03, 0x02, 0xFE, 0x75, 0x64, 0x02, 0x33, 0x24, 0xFB, + 0x1C, 0xE1, 0x34, 0x06, 0xA5, 0x3F, 0x14, 0x44, 0x52, 0x33, 0xAC, 0xEF, 0x0D, 0xC0, 0xF0, 0x13, 0x05, 0xA5, 0x3C, 0x37, + 0x3A, 0xE1, 0xED, 0xB2, 0x5B, 0xAF, 0x28, 0x44, 0x52, 0x88, 0xF8, 0x3E, 0x31, 0x7B, 0xF1, 0x4E, 0x60, 0x35, 0x12, 0x39, + 0xE6, 0x16, 0x70, 0x2A, 0x20, 0x7C, 0x29, 0xFF, 0xE9, 0xEE, 0xA9, 0xB7, 0xCB, 0x97, 0x80, 0x75, 0x74, 0xDE, 0x26, 0x01, + 0x00, 0xC6, 0xE8, 0xB6, 0x1E, 0xEB, 0x4C, 0x59, 0x40, 0x86, 0x30, 0xE2, 0xA0, 0xE9, 0xA8, 0xC6, 0x09, 0xC7, 0xB1, 0xF3, + 0x11, 0x27, 0x79, 0x14, 0x27, 0x97, 0xFA, 0x04, 0x64, 0xED, 0x5E, 0xC7, 0xC4, 0x94, 0x71, 0xAF, 0xF0, 0xEB, 0x15, 0x9C, + 0xB1, 0xC6, 0x31, 0xDA, 0x30, 0xEE, 0x72, 0x1F, 0x05, 0x60, 0x5C, 0xBA, 0xDF, 0xE5, 0xB9, 0xF7, 0x0D, 0x78, 0x01, 0x53, + 0x76, 0x58, 0x7B, 0x2E, 0xA9, 0x71, 0xDC, 0xBE, 0x7F, 0xDE, 0x3A, 0x2F, 0x33, 0xE8, 0x9A, 0x4C, 0xE9, 0xE4, 0xEA, 0x9E, + 0x34, 0xCB, 0x61, 0xE5, 0x1B, 0x12, 0xC5, 0xBE, 0x26, 0xB6, 0x7A, 0xAF, 0xD4, 0xAB, 0x7B, 0x2F, 0xBF, 0x4B, 0xB5, 0xBF, + 0x9A, 0xE8, 0xA3, 0xC3, 0xA8, 0x87, 0x8B, 0x40, 0x5D, 0xE7, 0x7C, 0x53, 0x02, 0x5D, 0x37, 0x9B, 0xD7, 0x56, 0x84, 0x4B, + 0xC5, 0xC2, 0x7B, 0x44, 0xDB, 0x69, 0x80, 0x34, 0xAD, 0xE9, 0x26, 0x14, 0xFF, 0xD7, 0x29, 0x6A, 0x48, 0xB7, 0xA9, 0x6E, + 0x58, 0x97, 0x15, 0xDE, 0x01, 0xC3, 0x2A, 0xDE, 0xC6, 0x50, 0xC5, 0x38, 0xEE, 0x8F, 0xFA, 0xFA, 0x60, 0x71, 0xDC, 0xA9, + 0x6F, 0x11, 0xE1, 0xA1, 0x25, 0xB1, 0x58, 0x15, 0x4F, 0xC3, 0xD8, 0x4B, 0x25, 0x75, 0xC7, 0xDF, 0x85, 0x75, 0xC3, 0x3D, + 0xAC, 0xEC, 0xBB, 0xC5, 0x6E, 0x30, 0x17, 0x00, 0x15, 0x9E, 0xB4, 0xE4, 0xD3, 0x6D, 0xA4, 0x86, 0x34, 0x3D, 0x7C, 0xA7, + 0x1B, 0xF0, 0xE5, 0x5C, 0x72, 0x32, 0x75, 0xA6, 0x80, 0x47, 0x18, 0x74, 0xFD, 0x32, 0x74, 0x33, 0x8C, 0x41, 0xA3, 0x46, + 0x6B, 0x50, 0x89, 0x1D, 0xA7, 0xA2, 0xC5, 0x30, 0x72, 0xBD, 0xA5, 0x27, 0xA2, 0xE2, 0x74, 0xB6, 0xC2, 0xD7, 0x25, 0x96, + 0xDA, 0xB3, 0x7C, 0xE4, 0x83, 0xDF, 0x4F, 0xB6, 0xB9, 0xC8, 0xEF, 0x33, 0xF3, 0x17, 0xD0, 0xA0, 0xDD, 0xF1, 0x24, 0x42, + 0x9F, 0xF6, 0x75, 0x1E, 0x66, 0xCF, 0xEC, 0x1D, 0x87, 0x77, 0xC0, 0x5D, 0xD8, 0x48, 0xB5, 0x96, 0x54, 0x95, 0xBC, 0x76, + 0xAD, 0x6A, 0x46, 0xC7, 0xD6, 0x8A, 0x5D, 0x3D, 0x0A, 0x9B, 0xA3, 0xCE, 0xB7, 0x16, 0x23, 0x85, 0x86, 0x84, 0x10, 0x1D, + 0xC5, 0x60, 0x8C, 0x2D, 0x5E, 0x11, 0x15, 0x3F, 0x91, 0xFA, 0x26, 0xF3, 0xE1, 0xAC, 0x3D, 0x1E, 0xDB, 0xEC, 0xB6, 0xF9, + 0x30, 0x91, 0xC0, 0x3F, 0x3F, 0x13, 0xA5, 0x2E, 0x6A, 0x5C, 0x49, 0x52, 0x7C, 0x73, 0x96, 0x65, 0x1E, 0xEA, 0x6E, 0x1A, + 0xF1, 0x46, 0xD9, 0xFA, 0x61, 0x22, 0x7E, 0xA9, 0x86, 0x62, 0xB3, 0xBB, 0xC0, 0x85, 0xFD, 0x02, 0xD4, 0xE9, 0xC8, 0xD8, + 0xFC, 0xB4, 0x72, 0x9E, 0x96, 0xB8, 0x97, 0x65, 0x50, 0xF5, 0x74, 0x9F, 0xDE, 0x29, 0x3B, 0x9F, 0xDE, 0xBA, 0xBF, 0x3B, + 0xC2, 0x67, 0x66, 0x31, 0xDF, 0x1A, 0x19, 0x09, 0xF4, 0x6C, 0x5D, 0x94, 0xEF, 0xD1, 0xFB, 0x88, 0x9C, 0xBC, 0x74, 0x5E, + 0x21, 0x01, 0x59, 0xC2, 0x54, 0xEC, 0x7B, 0x06, 0x6F, 0xC6, 0xA7, 0xB7, 0xDA, 0x7D, 0x67, 0x31, 0x4F, 0xE5, 0xEF, 0xCB, + 0x3E, 0xFE, 0xC8, 0xA9, 0x4F, 0x2B, 0x73, 0x29, 0xCA, 0xBF, 0xAF, 0x5E, 0x28, 0xDD, 0xEF, 0xC0, 0x83, 0x12, 0x29, 0x9D, + 0x8F, 0x89, 0x07, 0xDB, 0xFF, 0xFF, 0xA8, 0x31, 0x33, 0xC5, 0xFE, 0x29, 0x9F, 0x8D, 0x2D, 0xA4, 0x46, 0xD1, 0xDA, 0xCB, + 0xF3, 0x6D, 0xF7, 0xF6, 0xE8, 0x10, 0xA8, 0xFE, 0x78, 0x50, 0xE7, 0xC1, 0xE2, 0x01, 0x10, 0x04, 0xB0, 0x6E, 0xB9, 0xF2, + 0xB0, 0x89, 0x92, 0x96, 0x87, 0xA9, 0x29, 0xDF, 0x6C, 0x4F, 0xDB, 0xDE, 0x73, 0x64, 0xA5, 0x82, 0x8E, 0x0B, 0xE8, 0x55, + 0x95, 0x6D, 0x24, 0x03, 0xA1, 0x4A, 0x2D, 0xD7, 0x53, 0x6B, 0x80, 0xA8, 0x7A, 0x02, 0xE8, 0x26, 0xAB, 0x28, 0x82, 0x91, + 0x7E, 0xA1, 0xEA, 0xD4, 0xDA, 0xCB, 0x5F, 0xD2, 0x06, 0xB5, 0x75, 0x16, 0xB2, 0x88, 0x4F, 0x47, 0x28, 0x94, 0xE0, 0x9F, + 0x33, 0x45, 0xC9, 0x48, 0x84, 0x1D, 0xF9, 0x2B, 0x13, 0x2B, 0x0F, 0x59, 0xE3, 0xED, 0x75, 0x41, 0x39, 0x02, 0x89, 0xB9, + 0xFB, 0xFC, 0x9D, 0x12, 0x9D, 0xB8, 0x41, 0x62, 0xF7, 0x56, 0xA6, 0x07, 0xFD, 0xF8, 0x06, 0x2C, 0x8A, 0xEF, 0x94, 0xAC, + 0x70, 0x8A, 0x6C, 0x2E, 0xA1, 0x47, 0x26, 0x3C, 0xFB, 0x6E, 0x9E, 0x3F, 0xA8, 0x8E, 0xBD, 0x98, 0x7F, 0xE6, 0x22, 0xC2, + 0xE5, 0x44, 0xFA, 0x7D, 0xDD, 0x64, 0xD9, 0x6B, 0x6A, 0x5F, 0x93, 0x81, 0x9A, 0x31, 0x41, 0x1E, 0x23, 0x2E, 0x1B, 0x41, + 0x39, 0x65, 0x45, 0x85, 0x25, 0x06, 0x8A, 0x99, 0xF7, 0xCA, 0x64, 0xC8, 0x6A, 0x0B, 0x91, 0x39, 0x7A, 0xE0, 0x58, 0xCC, + 0x54, 0x51, 0xFC, 0xE8, 0x14, 0x93, 0x6C, 0x40, 0x6B, 0x5F, 0x42, 0x2B, 0x80, 0xF1, 0xB5, 0x0A, 0x05, 0x6F, 0x0A, 0xE9, + 0x9C, 0x41, 0x25, 0x0A, 0x21, 0xFC, 0xFA, 0xF6, 0x7F, 0xE6, 0x23, 0x0D, 0xC4, 0x03, 0xD5, 0x2F, 0x65, 0xB3, 0x6D, 0x55, + 0xAA, 0xCE, 0xC9, 0x6F, 0x69, 0xE5, 0x01, 0x5C, 0xA9, 0x02, 0xF5, 0xF9, 0x41, 0x50, 0x20, 0x88, 0xCA, 0x4F, 0x33, 0x41, + 0x30, 0x2B, 0xA8, 0xA4, 0xC1, 0xBF, 0xBC, 0x54, 0xCE, 0x3F, 0x91, 0xE7, 0x81, 0xF6, 0xC1, 0x46, 0xF2, 0x73, 0x46, 0xA0, + 0xD6, 0x2E, 0x84, 0x76, 0x9D, 0xBA, 0x7A, 0x9D, 0x8A, 0x20, 0x19, 0x56, 0xF3, 0x72, 0x10, 0x72, 0x94, 0xBF, 0xE5, 0xC1, + 0x91, 0xB9, 0x06, 0x52, 0x90, 0xDF, 0xD2, 0x47, 0x72, 0x71, 0x2B, 0xB9, 0x02, 0x96, 0x09, 0x77, 0x33, 0x7B, 0x23, 0x89, + 0x89, 0x02, 0x0B, 0x57, 0x73, 0x5B, 0xCC, 0xC9, 0x24, 0x0F, 0xFD, 0x7C, 0xC1, 0x2F, 0xC7, 0x13, 0x16, 0x89, 0xEC, 0x0F, + 0xCD, 0xC9, 0x1C, 0xB2, 0x67, 0x13, 0x7F, 0xE9, 0xCF, 0x36, 0x1A, 0xD8, 0xE3, 0xD9, 0xC7, 0x7E, 0x57, 0x7A, 0x97, 0xBE, + 0x2F, 0x74, 0xB1, 0x41, 0xB8, 0xF8, 0x03, 0xD8, 0x09, 0xE7, 0x30, 0x15, 0x72, 0x69, 0xC5, 0xC8, 0xA5, 0x0C, 0xF7, 0x2F, + 0x48, 0x2C, 0x63, 0xD8, 0x2B, 0x06, 0x84, 0xED, 0x56, 0xA8, 0x58, 0x6A, 0x2C, 0x9D, 0x4F, 0xFE, 0x9B, 0x3E, 0x68, 0x84, + 0x81, 0x29, 0x2F, 0xCE, 0x3B, 0xC7, 0x30, 0x7A, 0x4B, 0xED, 0x06, 0x9E, 0x98, 0xB3, 0x1B, 0xBA, 0xEF, 0xF4, 0x5E, 0x54, + 0x74, 0x7F, 0x15, 0x51, 0x43, 0x5E, 0x0F, 0x59, 0x1B, 0x3C, 0x41, 0x80, 0x03, 0x6B, 0xEF, 0x2F, 0xF1, 0x47, 0xB8, 0x9F, + 0x42, 0xAA, 0x50, 0x7F, 0x15, 0x36, 0x0E, 0x3D, 0x87, 0x2C, 0x17, 0xB9, 0x58, 0xF1, 0x94, 0xEC, 0x2C, 0xFF, 0xB2, 0x48, + 0x54, 0xDD, 0x2E, 0xDA, 0xA2, 0x53, 0xD7, 0x8A, 0x5E, 0xDD, 0xB5, 0x2B, 0x13, 0xB0, 0x86, 0xD5, 0x08, 0x1A, 0x0A, 0xBF, + 0x65, 0x02, 0x7E, 0x8E, 0x19, 0xDA, 0x23, 0xBA, 0xE9, 0x9F, 0x6B, 0x49, 0xB0, 0xC4, 0x03, 0x1A, 0xCC, 0xF3, 0xEF, 0xDD, + 0x45, 0xD1, 0x83, 0x49, 0x40, 0x4E, 0x0F, 0x59, 0xB5, 0x3F, 0x61, 0x5D, 0xE5, 0x20, 0xA1, 0xFA, 0x5A, 0xA0, 0x52, 0xD3, + 0x1E, 0xE5, 0x4C, 0x82, 0x1E, 0x5A, 0x0D, 0x10, 0x24, 0x49, 0xB4, 0xA2, 0x67, 0x78, 0x48, 0xA5, 0x76, 0x8C, 0x38, 0x51, + 0x31, 0xA7, 0x6A, 0x05, 0xAE, 0xA5, 0xB2, 0x26, 0xF6, 0xEC, 0x19, 0xB1, 0x30, 0x00, 0xA9, 0x06, 0xB0, 0xCC, 0x4F, 0x25, + 0x2D, 0xCD, 0xD1, 0x87, 0x68, 0xEF, 0xD2, 0x34, 0x24, 0x7C, 0x21, 0x6F, 0x74, 0xAC, 0x01, 0xDD, 0x69, 0xCE, 0xB3, 0x77, + 0x76, 0xEE, 0xE2, 0xC0, 0x03, 0xA4, 0xDE, 0xE7, 0xC4, 0xFB, 0x56, 0x4B, 0x4F, 0xB1, 0xCA, 0xD6, 0x82, 0x4B, 0x42, 0xD7, + 0x09, 0xE7, 0x28, 0x02, 0x2E, 0xAB, 0xEB, 0x4C, 0x3F, 0x87, 0x87, 0x04, 0x35, 0xA6, 0xA1, 0xAB, 0xE0, 0x7B, 0xBE, 0x27, + 0xE5, 0x13, 0x62, 0x4D, 0xFA, 0x33, 0x55, 0x05, 0xB6, 0xE6, 0x23, 0x52, 0xA5, 0x8A, 0xD1, 0xB8, 0x14, 0xAA, 0xE6, 0xC7, + 0x2E, 0xF6, 0x82, 0x0C, 0xB6, 0x87, 0x42, 0xBD, 0x3B, 0x85, 0xC2, 0x4A, 0x25, 0xEA, 0x9E, 0xB1, 0xB7, 0x95, 0xF8, 0xC1, + 0xFF, 0xEE, 0x12, 0x67, 0x2C, 0x49, 0x8E, 0x7C, 0x5E, 0x16, 0x44, 0x02, 0xB4, 0x1F, 0xC2, 0xBC, 0x7F, 0x49, 0xB8, 0xEB, + 0x80, 0xEF, 0xFA, 0xB2, 0x1E, 0xE2, 0x50, 0x70, 0x41, 0x3C, 0x3B, 0x38, 0xBF, 0xCA, 0x83, 0x8B, 0x08, 0x19, 0xD3, 0x9D, + 0xBF, 0xDE, 0x45, 0x16, 0xEF, 0x26, 0x81, 0xDD, 0x5F, 0xE8, 0xE0, 0xC8, 0x0B, 0x2C, 0x1B, 0x8C, 0xBF, 0x93, 0xB2, 0xDF, + 0xD8, 0x6D, 0x8C, 0x68, 0x8E, 0x88, 0xE2, 0xCE, 0xAE, 0x72, 0x7D, 0xA1, 0xAA, 0x7E, 0x2C, 0x57, 0xA4, 0xBC, 0xA4, 0x9C, + 0x1F, 0x40, 0xA3, 0xA3, 0xE8, 0x88, 0x8B, 0x2D, 0x2D, 0xD3, 0x60, 0x98, 0xBE, 0x13, 0x63, 0xED, 0x5F, 0xB3, 0x3B, 0x39, + 0xCB, 0x89, 0x10, 0x34, 0xE5, 0x10, 0xBB, 0xCE, 0x5D, 0x6E, 0x69, 0x7B, 0xD9, 0x7E, 0x83, 0xBE, 0x53, 0x75, 0xEE, 0x78, + 0x97, 0xB6, 0x0C, 0x58, 0xC8, 0xDD, 0xCB, 0x44, 0xF6, 0xB8, 0xEC, 0x63, 0x1D, 0x1C, 0x51, 0x74, 0x94, 0x3B, 0xC7, 0xC9, + 0x6B, 0x2E, 0xC4, 0x34, 0x70, 0xA1, 0xFA, 0xE3, 0x5C, 0x83, 0xAD, 0x03, 0x15, 0x38, 0x4A, 0xD9, 0x69, 0xB0, 0x37, 0xC5, + 0xB7, 0x4D, 0x50, 0xE0, 0xE6, 0x12, 0xD2, 0x75, 0x19, 0xBE, 0x91, 0xC0, 0xD1, 0x25, 0x85, 0x67, 0x0E, 0xFC, 0x5A, 0x12, + 0x4D, 0x9B, 0xE4, 0x39, 0xC9, 0xF5, 0x2B, 0x82, 0x15, 0x61, 0x40, 0x84, 0x89, 0xB5, 0x52, 0x30, 0x11, 0x0A, 0xFF, 0xE9, + 0x4F, 0xC9, 0xBC, 0xA6, 0x5E, 0xCE, 0xD6, 0x1C, 0x34, 0xFA, 0xE5, 0xF1, 0x9A, 0x29, 0xDD, 0x34, 0x94, 0x63, 0xAA, 0x83, + 0x91, 0x33, 0x35, 0xFA, 0xC2, 0x2B, 0x53, 0xFF, 0x6F, 0x1D, 0x52, 0x98, 0x22, 0x6A, 0x09, 0x77, 0xED, 0x19, 0xD4, 0x88, + 0x36, 0x7D, 0xDD, 0x75, 0x95, 0xF4, 0xEC, 0x31, 0x9F, 0xB5, 0x08, 0x83, 0xBA, 0xD2, 0xD6, 0xEA, 0x28, 0xF5, 0xBD, 0x9C, + 0xE5, 0x28, 0xA6, 0x1A, 0x9C, 0x33, 0x01, 0x29, 0x59, 0x76, 0x36, 0xBF, 0x7B, 0xE2, 0xC0, 0x4B, 0xCD, 0x3E, 0xED, 0x50, + 0x1F, 0xBC, 0xB7, 0x6D, 0x84, 0xB6, 0xFD, 0x54, 0x5F, 0xFC, 0x8B, 0x6A, 0x0E, 0xDB, 0x54, 0x7D, 0x11, 0xB6, 0x2C, 0xC1, + 0x27, 0xEA, 0xA8, 0x3D, 0xF8, 0x5B, 0x1E, 0xF8, 0xE6, 0x93, 0x4F, 0xBC, 0x85, 0xA3, 0x2F, 0x4D, 0xCB, 0x03, 0x71, 0xA6, + 0x5A, 0x77, 0xB8, 0x68, 0x10, 0x94, 0x78, 0xCF, 0x53, 0x36, 0x00, 0x5A, 0x5C, 0xFA, 0xC4, 0x4E, 0x95, 0x52, 0x6F, 0x38, + 0xA7, 0xDC, 0x77, 0xAD, 0x41, 0x6B, 0x76, 0x8D, 0x3A, 0x2F, 0x80, 0xD2, 0x15, 0xBA, 0xB6, 0xEC, 0xA9, 0x66, 0xE7, 0xE3, + 0x54, 0xFB, 0xBF, 0x4E, 0x83, 0xC2, 0x5B, 0xDB, 0x9C, 0x81, 0x93, 0xF3, 0x84, 0x8D, 0x67, 0xC4, 0x40, 0x84, 0xE8, 0xC2, + 0xEC, 0x4F, 0xC9, 0x71, 0xF5, 0xE0, 0x98, 0xB5, 0x69, 0x0C, 0xB2, 0xEF, 0x6E, 0x01, 0x86, 0xF7, 0x8B, 0x0B, 0x67, 0x10, + 0x62, 0x89, 0x53, 0xB2, 0x6B, 0x66, 0xC9, 0x6D, 0xAF, 0x02, 0x37, 0xE0, 0xAD, 0xEF, 0xCF, 0xC7, 0xC0, 0xE7, 0xF6, 0x63, + 0xAF, 0xDC, 0x49, 0x7C, 0xFB, 0x83, 0x11, 0x35, 0x69, 0x21, 0x21, 0xCA, 0xEE, 0x9C, 0x80, 0x34, 0x80, 0x59, 0x65, 0x41, + 0x95, 0x32, 0x2E, 0xF2, 0x96, 0x92, 0x14, 0x6A, 0x53, 0x04, 0x36, 0x65, 0xAF, 0x08, 0x3F, 0xE9, 0xDB, 0xF2, 0x06, 0xEA, + 0x47, 0xB0, 0x18, 0xCA, 0xF2, 0x9A, 0x81, 0xC5, 0xF2, 0x0B, 0x91, 0xDB, 0x69, 0x82, 0xF6, 0xFE, 0x29, 0xF0, 0x8F, 0xD5, + 0xDA, 0x24, 0x37, 0x79, 0xEB, 0x56, 0x1A, 0x46, 0x69, 0x94, 0xF9, 0x4F, 0x4F, 0x93, 0xEE, 0x7C, 0xD5, 0xDC, 0xBD, 0x38, + 0x29, 0xF7, 0x1C, 0x0F, 0xD4, 0x2E, 0x34, 0x75, 0x79, 0xE5, 0xA8, 0xD7, 0x5E, 0x72, 0xBD, 0xB8, 0xFA, 0xB6, 0x42, 0xF4, + 0x1D, 0x6B, 0x52, 0xF8, 0xB5, 0xA0, 0x14, 0x5A, 0xA6, 0x72, 0xB8, 0xB9, 0x16, 0x4B, 0x20, 0xFF, 0x9E, 0x90, 0x0A, 0xEE, + 0x02, 0x40, 0xE1, 0x32, 0xBC, 0x71, 0xF0, 0x9D, 0x8B, 0x43, 0xCF, 0x1A, 0x1B, 0xFF, 0xC0, 0x39, 0x31, 0xC1, 0xF8, 0x4B, + 0x9B, 0xD4, 0x3C, 0x64, 0xE3, 0xED, 0xE4, 0xF6, 0x68, 0x88, 0xE0, 0x77, 0xA6, 0xE7, 0x4E, 0x13, 0xE5, 0xC1, 0xF3, 0x48, + 0xB0, 0xF2, 0x2C, 0x2E, 0xF0, 0x8B, 0xDA, 0x3E, 0xD9, 0x19, 0x9C, 0xCA, 0xD4, 0x10, 0x15, 0x60, 0x61, 0x3F, 0x12, 0xDB, + 0x52, 0x5D, 0x65, 0x6D, 0xA1, 0xCB, 0x50, 0x94, 0xD6, 0x2C, 0x90, 0x59, 0x7B, 0xEE, 0x95, 0xCF, 0x9F, 0xDA, 0x78, 0x76, + 0x13, 0xE4, 0x3C, 0x0F, 0x0D, 0x67, 0x05, 0x66, 0x04, 0x9B, 0x0B, 0x00, 0x32, 0x8C, 0x8A, 0xD3, 0x23, 0xDF, 0x0E, 0x2A, + 0xFD, 0x8D, 0x36, 0x20, 0xCB, 0xBE, 0x11, 0x16, 0xB1, 0x9A, 0x43, 0x4F, 0x67, 0x68, 0x18, 0x49, 0x86, 0x30, 0x6A, 0xBD, + 0x4B, 0x56, 0x3A, 0xB5, 0xB4, 0x9D, 0x17, 0x5E, 0x01, 0x2D, 0xF2, 0xDB, 0x22, 0x7A, 0xA9, 0xB5, 0x23, 0x1B, 0xB5, 0x6A, + 0x93, 0x3E, 0x4B, 0xC2, 0xEE, 0xD1, 0x1C, 0xB7, 0x1C, 0x68, 0xD7, 0xFE, 0x5A, 0xA1, 0x2C, 0x4E, 0x10, 0xE2, 0xD4, 0xFE, + 0x86, 0xA0, 0xEA, 0xFC, 0x13, 0x14, 0xC8, 0x54, 0x29, 0x71, 0x3B, 0x27, 0x4D, 0x98, 0x02, 0xC2, 0x67, 0x19, 0xD8, 0x1C, + 0x41, 0x37, 0x56, 0xFB, 0x9E, 0x0D, 0xBA, 0xB6, 0xCC, 0x97, 0xE3, 0x10, 0x0A, 0x16, 0xCD, 0xE0, 0x99, 0xF5, 0xEA, 0xED, + 0x77, 0xA6, 0x1E, 0x64, 0x45, 0x98, 0x3C, 0xFF, 0x33, 0x23, 0x1D, 0xE7, 0x04, 0xFC, 0xF0, 0x78, 0x20, 0x17, 0x87, 0x64, + 0xEA, 0x75, 0xE9, 0xDB, 0x6F, 0x34, 0xF5, 0xDA, 0x3A, 0x27, 0x3F, 0x38, 0x39, 0x58, 0x17, 0xE3, 0xB4, 0x5B, 0xD6, 0xCD, + 0x88, 0x26, 0x5A, 0x38, 0x1C, 0x7F, 0x97, 0xEB, 0xDF, 0x1A, 0x2B, 0x1E, 0x8D, 0x95, 0xF0, 0x69, 0xB8, 0xFE, 0x2E, 0x6A, + 0x66, 0x72, 0x6F, 0x2A, 0x12, 0x90, 0xDF, 0xFF, 0xA9, 0x20, 0x40, 0xB8, 0x15, 0xD1, 0x5F, 0xC9, 0x6F, 0x17, 0x61, 0xF0, + 0xFA, 0x6D, 0x15, 0xBF, 0x40, 0x9F, 0x71, 0x19, 0xF6, 0xBE, 0x13, 0xD1, 0x7C, 0x3E, 0xE3, 0xA7, 0xB6, 0x41, 0x9D, 0x6D, + 0xC9, 0x92, 0x21, 0x8A, 0x80, 0x9B, 0x5A, 0x0D, 0x19, 0x5D, 0xF4, 0xE0, 0x56, 0x4F, 0xB0, 0x3E, 0xC0, 0x93, 0xBF, 0x63, + 0xC8, 0x88, 0x71, 0xAA, 0x2C, 0x76, 0xF4, 0x97, 0x4A, 0x20, 0x9C, 0xE2, 0xC5, 0xEA, 0x21, 0x6E, 0x80, 0xF9, 0x00, 0xFC, + 0xFD, 0x06, 0x9B, 0x26, 0xA7, 0xE5, 0xDA, 0x82, 0x4F, 0x7A, 0x6B, 0x22, 0x42, 0x30, 0x6D, 0x27, 0x52, 0xFA, 0x24, 0x6C, + 0xA4, 0x09, 0x68, 0x96, 0xCC, 0x5C, 0xC7, 0x48, 0x33, 0x83, 0x14, 0x59, 0x9F, 0x20, 0x7B, 0x1E, 0x27, 0x84, 0x15, 0x83, + 0xCF, 0xE8, 0xA0, 0x5C, 0xAC, 0xDB, 0xC3, 0x68, 0x29, 0x9E, 0xA9, 0xF1, 0xA1, 0x85, 0xBB, 0x13, 0x7E, 0xFA, 0x76, 0x0A, + 0x32, 0xA6, 0x55, 0xA5, 0xD9, 0xEB, 0x57, 0x6A, 0x00, 0x74, 0x40, 0x78, 0x9A, 0x70, 0xD5, 0xE3, 0xC1, 0xD2, 0x74, 0x97, + 0x34, 0xC4, 0x56, 0x6E, 0x7B, 0x2A, 0x8F, 0x52, 0x7C, 0x33, 0xA9, 0xE4, 0x8F, 0xB6, 0x38, 0xF2, 0x62, 0x3A, 0xF0, 0x31, + 0x75, 0x39, 0x02, 0x58, 0x48, 0x0D, 0x21, 0xFD, 0x3D, 0x62, 0xA8, 0x43, 0x73, 0x19, 0xFA, 0x20, 0xFF, 0x54, 0x69, 0x49, + 0x73, 0x53, 0x9F, 0x01, 0x2C, 0x61, 0x99, 0xC0, 0x89, 0xEA, 0x50, 0x12, 0xAD, 0x77, 0x62, 0xD7, 0x41, 0xB3, 0x0A, 0xD5, + 0x4A, 0xC1, 0x36, 0xD3, 0xAB, 0xA9, 0xC6, 0x85, 0x29, 0x84, 0xCA, 0x00, 0xAE, 0xEB, 0xF2, 0xDA, 0x71, 0x64, 0xDC, 0x0A, + 0x5E, 0x8B, 0x43, 0xB8, 0x2F, 0x87, 0x23, 0x8B, 0x96, 0xCE, 0x10, 0x58, 0xA1, 0x63, 0x89, 0xC1, 0x69, 0x86, 0x54, 0x65, + 0x2A, 0x36, 0xE4, 0xC3, 0x9B, 0x11, 0x77, 0x5B, 0x99, 0x64, 0x7B, 0x4B, 0x5F, 0xA9, 0x1C, 0x73, 0xF7, 0x2F, 0x54, 0xBF, + 0xF6, 0xEC, 0x2C, 0xF8, 0x4A, 0x39, 0x8D, 0x10, 0xD3, 0x5A, 0x3C, 0x77, 0xE4, 0xFC, 0x8B, 0x50, 0xCF, 0xD9, 0x99, 0x65, + 0x91, 0x66, 0xFE, 0x0D, 0x43, 0x83, 0x70, 0xB8, 0xFE, 0x13, 0xBD, 0x7D, 0x9A, 0xE2, 0xD3, 0x55, 0x42, 0x1A, 0xBB, 0x6A, + 0xB5, 0x6D, 0xEA, 0x59, 0x7D, 0x7A, 0xCC, 0xAE, 0x03, 0x6D, 0x1C, 0x7F, 0xA4, 0x59, 0x99, 0x6F, 0xDC, 0x2F, 0x0F, 0x60, + 0x88, 0x1D, 0x47, 0xE0, 0xB9, 0x16, 0xF4, 0xCB, 0x0E, 0x74, 0x0B, 0x3D, 0x81, 0x66, 0xCA, 0x10, 0xF1, 0x1E, 0x6C, 0xE2, + 0x99, 0xAA, 0x1C, 0x99, 0x8C, 0x29, 0x2C, 0x3A, 0xF5, 0xEC, 0x5D, 0xA7, 0xA2, 0x09, 0x38, 0x74, 0x89, 0xF3, 0xFD, 0xD6, + 0xAC, 0xCB, 0xBD, 0xA2, 0x8B, 0x2D, 0xED, 0x12, 0x00, 0x93, 0x19, 0x13, 0xD0, 0xCD, 0x25, 0xBE, 0x0E, 0xCA, 0x87, 0x44, + 0xCD, 0x5C, 0x1D, 0xFD, 0x52, 0x41, 0x37, 0xFD, 0x4C, 0x2B, 0x75, 0x11, 0xA4, 0x21, 0x44, 0x99, 0x57, 0x94, 0xFC, 0x15, + 0x25, 0x60, 0x7C, 0xA4, 0xDC, 0x36, 0x9F, 0xED, 0xB9, 0x7A, 0x6E, 0x72, 0x71, 0xCC, 0x72, 0x47, 0xA4, 0x2A, 0x8D, 0x05, + 0x30, 0x43, 0xD5, 0xDD, 0x6A, 0x02, 0xAB, 0x57, 0xFE, 0xED, 0x69, 0x94, 0x26, 0x99, 0xB4, 0x7B, 0x12, 0x30, 0x1A, 0x02, + 0x35, 0x97, 0x02, 0x1F, 0xFE, 0xBA, 0x26, 0x8A, 0x2C, 0x9E, 0xEE, 0x8B, 0x43, 0x47, 0xEB, 0x55, 0x8D, 0x67, 0x27, 0x5D, + 0x08, 0x57, 0x96, 0x9A, 0x2D, 0x99, 0x6E, 0xEA, 0xA6, 0xB1, 0x68, 0xC9, 0x2E, 0x5B, 0x2B, 0x90, 0x19, 0xA4, 0x84, 0x61, + 0xAA, 0xB8, 0x37, 0xAF, 0x84, 0xF8, 0xE8, 0x54, 0xEA, 0xE3, 0xA0, 0x5C, 0x8C, 0x55, 0x2F, 0xE9, 0x2F, 0x4F, 0x2B, 0x62, + 0x4A, 0xFA, 0xC0, 0xC8, 0xEE, 0xB7, 0x53, 0x30, 0xFE, 0x08, 0xC5, 0x66, 0xF2, 0xEF, 0x66, 0xC2, 0x38, 0xFE, 0xD5, 0xDC, + 0xB2, 0x39, 0x89, 0x6A, 0x05, 0x95, 0x54, 0x29, 0xE9, 0x32, 0x02, 0x41, 0x3E, 0xDD, 0xFE, 0xBC, 0xFD, 0x89, 0x7A, 0x0F, + 0x1D, 0xDD, 0x40, 0xCD, 0x7E, 0xFA, 0x83, 0x30, 0x57, 0xAE, 0x09, 0xD8, 0x85, 0x5B, 0x37, 0x7E, 0x03, 0xF4, 0x89, 0x2A, + 0x65, 0x8F, 0xB1, 0x6F, 0xB7, 0xFD, 0x5C, 0xF4, 0x37, 0x74, 0x48, 0x4F, 0xDB, 0xFF, 0x59, 0x2D, 0x73, 0x00, 0x88, 0x81, + 0xB1, 0xAA, 0x3B, 0x53, 0x74, 0xC0, 0xDA, 0xCE, 0xF3, 0x66, 0xD7, 0x00, 0x07, 0xC3, 0x75, 0xF6, 0x93, 0x22, 0x38, 0x93, + 0xA0, 0xEE, 0x77, 0xD6, 0xD3, 0x29, 0xD8, 0x3D, 0xBB, 0xAC, 0xFE, 0xE7, 0x31, 0xA8, 0x6F, 0x1D, 0x88, 0x13, 0x47, 0x80, + 0x71, 0xE8, 0x98, 0x2E, 0x91, 0xD6, 0x3C, 0x77, 0xD0, 0xA3, 0x88, 0x0E, 0xF5, 0xBE, 0x81, 0x47, 0x72, 0x06, 0x0A, 0xBB, + 0x71, 0x04, 0xB8, 0xC6, 0x13, 0xE6, 0x99, 0x9F, 0xA3, 0xC2, 0x58, 0x67, 0xF3, 0xEC, 0x59, 0xA1, 0x71, 0x45, 0xBA, 0x2A, + 0xB0, 0x40, 0x4D, 0xEF, 0xB6, 0xCC, 0xF8, 0x16, 0x12, 0x61, 0x9C, 0x6D, 0xE9, 0x75, 0xFB, 0xA7, 0x10, 0x2E, 0x51, 0x9F, + 0x4F, 0xEB, 0xD5, 0x87, 0x50, 0x2E, 0xFE, 0x64, 0x77, 0xC6, 0x76, 0xB7, 0x11, 0x0F, 0x79, 0x9B, 0x2A, 0x56, 0xA1, 0xF7, + 0xD6, 0xAD, 0x03, 0x33, 0x10, 0x9D, 0xFA, 0x6E, 0x5B, 0x57, 0xBE, 0xBA, 0x08, 0x42, 0xEA, 0xAE, 0x5D, 0xB2, 0xF7, 0x68, + 0xBD, 0x00, 0xD0, 0x01, 0xBA, 0x2F, 0x63, 0x4E, 0xBE, 0xC2, 0x90, 0x38, 0xFA, 0x6F, 0x06, 0x8D, 0xC2, 0x09, 0xFB, 0x8F, + 0xBA, 0x28, 0x87, 0xD9, 0xF4, 0xBB, 0x91, 0xCF, 0x74, 0x67, 0x88, 0x76, 0xE8, 0x7C, 0xDB, 0x33, 0x38, 0xA1, 0x8E, 0x08, + 0xFD, 0x54, 0x13, 0xD1, 0xBA, 0x4B, 0x82, 0x20, 0x7B, 0xA1, 0x62, 0x2E, 0x5B, 0x6C, 0x48, 0x6A, 0xD8, 0x46, 0x88, 0x69, + 0xF9, 0x6A, 0xE6, 0x2A, 0xC1, 0x3C, 0xC1, 0xDE, 0x1E, 0x74, 0x58, 0x9E, 0xC6, 0x56, 0x52, 0x1C, 0x38, 0x96, 0x52, 0xE9, + 0x67, 0x4F, 0xBB, 0x3F, 0x9C, 0x35, 0x55, 0x81, 0xB9, 0x03, 0x5B, 0xA1, 0x79, 0x68, 0x35, 0x70, 0x6A, 0xA9, 0x91, 0x5C, + 0x38, 0x29, 0x3F, 0x1F, 0x01, 0x3E, 0xA3, 0x5A, 0xB8, 0x90, 0x4C, 0xC8, 0x43, 0x62, 0xBC, 0xD4, 0x31, 0x3F, 0x6A, 0x8C, + 0x03, 0x21, 0xEC, 0xC6, 0x31, 0x30, 0xAA, 0x7F, 0xDC, 0x7F, 0x86, 0x9C, 0x92, 0x54, 0xE3, 0x50, 0x67, 0xFC, 0x5B, 0xDA, + 0xF3, 0x92, 0x13, 0xAD, 0xA6, 0x50, 0xE5, 0x25, 0xF8, 0x3F, 0x03, 0x8D, 0x53, 0x9F, 0xED, 0x58, 0x47, 0x30, 0xE8, 0xD1, + 0xB1, 0xEF, 0xD7, 0x88, 0x12, 0x35, 0x1C, 0x4A, 0xE7, 0xD1, 0x8F, 0xC7, 0x52, 0x16, 0xD5, 0x53, 0x33, 0x1E, 0xBC, 0xA6, + 0x73, 0xB4, 0xC5, 0x02, 0xCE, 0xF9, 0xD6, 0x06, 0xF0, 0x3C, 0x6A, 0xE4, 0xAF, 0xB8, 0x96, 0xD5, 0x90, 0x33, 0x02, 0x12, + 0x67, 0xD0, 0x07, 0xAA, 0x0C, 0x9D, 0x0B, 0xD2, 0xCE, 0x52, 0xBD, 0x47, 0xB7, 0xB7, 0xC0, 0x03, 0x0B, 0xDC, 0x40, 0x75, + 0x51, 0x37, 0x07, 0x41, 0xE0, 0xC8, 0xC5, 0xB2, 0x10, 0x31, 0xEE, 0x13, 0x8B, 0xB6, 0x00, 0xFD, 0x12, 0xC8, 0xBB, 0xD7, + 0xC1, 0x49, 0xD6, 0x81, 0x99, 0xB2, 0x30, 0xD3, 0xCB, 0xF5, 0xCC, 0x53, 0xDB, 0x1D, 0xA2, 0x17, 0x2A, 0x09, 0xCA, 0x6C, + 0x63, 0x36, 0x7F, 0xC3, 0xCA, 0x5D, 0xC4, 0x43, 0xDA, 0x7F, 0x05, 0x7A, 0x94, 0xC7, 0xFF, 0x6F, 0x3A, 0x39, 0x12, 0x52, + 0xEE, 0xD8, 0xCD, 0xB8, 0x5B, 0x1F, 0xA4, 0xF6, 0x7C, 0xB6, 0xEF, 0xD9, 0xB6, 0x36, 0x5A, 0x49, 0xFF, 0xAA, 0xCF, 0x99, + 0x18, 0x74, 0x18, 0x2A, 0x2E, 0x5E, 0xCE, 0xEB, 0x99, 0x3A, 0x28, 0xDD, 0x9F, 0xFF, 0x16, 0x15, 0x51, 0xF1, 0xFA, 0xBA, + 0xD4, 0xB9, 0xAE, 0x9C, 0xD4, 0x30, 0x4D, 0xD9, 0x8C, 0x1C, 0x4F, 0xBA, 0x43, 0x7B, 0x87, 0xF1, 0x0B, 0xC1, 0xCF, 0x6A, + 0x5B, 0x31, 0xC5, 0x1A, 0x8E, 0xFE, 0x8E, 0x77, 0x1D, 0x32, 0xD9, 0xDF, 0x63, 0xDE, 0xC5, 0xDC, 0x18, 0x39, 0x3F, 0xBD, + 0x27, 0xD2, 0xFF, 0xA1, 0x5A, 0x1D, 0x38, 0x0B, 0xB9, 0x09, 0xD8, 0x56, 0x58, 0xAF, 0x8A, 0xD9, 0xCB, 0x16, 0xC8, 0xA4, + 0x51, 0xDB, 0x5A, 0xBC, 0x5D, 0x0C, 0xAC, 0xF4, 0x97, 0xA2, 0xAF, 0xD8, 0x80, 0x7C, 0x82, 0xD4, 0xD7, 0xA9, 0x94, 0x63, + 0xC4, 0xFF, 0xC1, 0xA7, 0xDE, 0x29, 0x39, 0x3E, 0xA7, 0xB3, 0xC9, 0xA5, 0xD1, 0x19, 0x57, 0x3E, 0x6E, 0x12, 0x6D, 0xE7, + 0xD9, 0xAC, 0x93, 0xC3, 0xF9, 0x62, 0x62, 0x27, 0x76, 0xE5, 0x71, 0xB1, 0x36, 0xEA, 0xE8, 0xC3, 0xB7, 0x2C, 0x4E, 0x4E, + 0x27, 0xC0, 0x88, 0xE4, 0x74, 0x91, 0x56, 0x7E, 0x66, 0x81, 0xEA, 0xB4, 0x95, 0xAD, 0x62, 0x70, 0x8D, 0xCA, 0x98, 0x32, + 0x58, 0xE8, 0x5F, 0x6A, 0x4C, 0xF7, 0x61, 0xA5, 0x37, 0x2E, 0x0F, 0x81, 0xD4, 0x8B, 0xC9, 0xB7, 0x28, 0xE9, 0x10, 0x20, + 0xB7, 0x0E, 0x29, 0x35, 0xD6, 0x87, 0x31, 0x6B, 0x2E, 0x96, 0xF3, 0x73, 0x74, 0xEA, 0x04, 0x06, 0x74, 0x2C, 0xC2, 0xAE, + 0x4C, 0x23, 0xA3, 0xC0, 0x89, 0x15, 0x3A, 0x2C, 0xFD, 0x62, 0x10, 0xE9, 0x39, 0x24, 0x65, 0x7C, 0x5C, 0x89, 0x3C, 0x16, + 0xA4, 0x98, 0x6E, 0x5C, 0x1E, 0x96, 0xA2, 0x37, 0x84, 0x7D, 0x27, 0xED, 0x1E, 0xE2, 0x99, 0x36, 0x4C, 0x24, 0x5C, 0xCD, + 0x5E, 0x09, 0xBA, 0x5C, 0x47, 0xDB, 0xD3, 0x9D, 0xBF, 0xDE, 0x49, 0x2B, 0x18, 0x46, 0xC3, 0x5D, 0x9C, 0xCB, 0x42, 0xC0, + 0x0F, 0x4C, 0x9A, 0x69, 0xBF, 0x24, 0x8A, 0x62, 0xA7, 0xBD, 0xF8, 0x6F, 0xFD, 0xEA, 0x7F, 0x77, 0x82, 0x20, 0xE2, 0xBC, + 0x9D, 0xA5, 0x69, 0x9C, 0xA6, 0x5C, 0x82, 0xFC, 0x5A, 0x74, 0x45, 0x63, 0xBA, 0x2A, 0xF3, 0xAD, 0x3F, 0x26, 0x8B, 0x83, + 0x2A, 0x63, 0x7B, 0x06, 0xBD, 0xCE, 0xFE, 0xC8, 0x96, 0x22, 0x2B, 0x3D, 0xDC, 0x10, 0xBB, 0x97, 0x4B, 0x62, 0x83, 0xFD, + 0xD6, 0x09, 0xB5, 0x92, 0xCF, 0x01, 0xEE, 0x78, 0x97, 0xBD, 0xF4, 0x26, 0xAE, 0x2F, 0xD4, 0xE6, 0x65, 0x70, 0xEC, 0x16, + 0x54, 0xEE, 0x24, 0x42, 0xD4, 0xBE, 0x44, 0xC4, 0x05, 0x87, 0xE3, 0x85, 0x94, 0x0E, 0x7F, 0x0C, 0xCC, 0xC3, 0xEF, 0x7C, + 0x17, 0xB4, 0xF5, 0x33, 0x2C, 0x2F, 0xCD, 0xD5, 0x0B, 0xB0, 0x12, 0x54, 0x3B, 0x9B, 0xCD, 0xD3, 0xA2, 0xBC, 0xFD, 0x37, + 0x60, 0xDE, 0x3D, 0x4E, 0x5F, 0x27, 0xC0, 0xA0, 0xD5, 0xF1, 0xEC, 0x70, 0x97, 0x3E, 0x0C, 0x60, 0x63, 0xA7, 0x14, 0xCB, + 0x56, 0x85, 0x57, 0x6E, 0xCC, 0x84, 0x8C, 0x96, 0x91, 0xB8, 0x26, 0xF6, 0xC4, 0xD3, 0xDC, 0x61, 0xD6, 0x79, 0x5D, 0xFE, + 0x4D, 0xA7, 0x62, 0x97, 0x97, 0xB9, 0x0D, 0x61, 0xEF, 0x16, 0x75, 0xE4, 0x46, 0xF0, 0x81, 0xA0, 0x9F, 0x31, 0xA7, 0xCA, + 0xF6, 0xB5, 0x71, 0xE3, 0xA7, 0xD8, 0xB7, 0xEA, 0x9C, 0xF8, 0x27, 0xD1, 0x91, 0x24, 0xC6, 0xCA, 0x53, 0x33, 0xC9, 0x2E, + 0x2E, 0xCE, 0x24, 0xB1, 0x10, 0x75, 0x39, 0xE0, 0xA0, 0xEF, 0x39, 0xFC, 0x7E, 0x55, 0x00, 0x96, 0x0C, 0x59, 0x12, 0x2D, + 0x72, 0xF1, 0x19, 0xA7, 0xEC, 0x35, 0x32, 0x6D, 0x3E, 0xB3, 0x88, 0x49, 0xA4, 0x8B, 0xC9, 0x97, 0x15, 0x6B, 0x67, 0x93, + 0x7C, 0xE6, 0xA5, 0x97, 0x1E, 0xB6, 0x67, 0xE9, 0xC9, 0xDD, 0x3F, 0xFE, 0x62, 0x56, 0xAF, 0x3A, 0xAE, 0x83, 0x9E, 0x4C, + 0x3F, 0xBB, 0x16, 0xAB, 0x93, 0x57, 0x77, 0xDC, 0x1E, 0xAC, 0x6C, 0x32, 0xAF, 0x99, 0xD4, 0x3C, 0xBD, 0xB5, 0xC5, 0x98, + 0x2E, 0x9D, 0xB4, 0xE3, 0x6D, 0xB2, 0x79, 0xE3, 0x3C, 0x96, 0xBD, 0xD2, 0x1D, 0xDB, 0x71, 0x09, 0x6C, 0xF6, 0xAE, 0xBE, + 0x59, 0xF3, 0xAE, 0x9C, 0x4E, 0x39, 0x29, 0xCF, 0x1C, 0xB9, 0x07, 0x99, 0xAE, 0xFF, 0x9F, 0xFD, 0x2D, 0xF2, 0x59, 0x54, + 0xA7, 0x4D, 0x86, 0x30, 0xF9, 0xE1, 0x49, 0xBA, 0xA4, 0x2A, 0x5C, 0x11, 0x84, 0x71, 0x0A, 0x6F, 0x40, 0x08, 0x7F, 0x66, + 0xFA, 0xE0, 0x41, 0xAA, 0xA5, 0xCB, 0x09, 0x2F, 0x6D, 0x15, 0xFE, 0xD1, 0x23, 0x09, 0x2D, 0x97, 0x92, 0x2A, 0x31, 0x35, + 0x8A, 0x28, 0x36, 0x0C, 0xF4, 0x96, 0xF1, 0x93, 0x01, 0x55, 0xE9, 0xA6, 0xCB, 0x2E, 0xAE, 0xF4, 0xB6, 0x43, 0x8A, 0xC5, + 0xA9, 0x92, 0x70, 0x2E, 0xA1, 0x61, 0xFD, 0xD4, 0xF9, 0x0E, 0x2E, 0x67, 0xE3, 0x06, 0x5D, 0x79, 0xD2, 0x33, 0xF3, 0x30, + 0x0F, 0xAE, 0x68, 0x26, 0x71, 0x82, 0xD7, 0xF4, 0x4E, 0x03, 0x4F, 0x9E, 0xF6, 0x6C, 0xFC, 0xA3, 0x69, 0x25, 0x9B, 0x9B, + 0xE6, 0x89, 0xDD, 0x6F, 0x4D, 0xEB, 0xEB, 0x9A, 0xB1, 0x42, 0x1D, 0xAE, 0x85, 0x2E, 0x09, 0x10, 0x57, 0x8A, 0x51, 0x75, + 0x6A, 0x54, 0xC0, 0x85, 0xD7, 0x96, 0x3A, 0x5A, 0x4B, 0xF8, 0x7D, 0x7F, 0x7C, 0x44, 0x25, 0xF8, 0x3B, 0x48, 0x52, 0x4D, + 0xB2, 0x65, 0x72, 0x9A, 0x89, 0x5F, 0x06, 0xAF, 0xB8, 0x86, 0x0C, 0x5A, 0xB6, 0x94, 0x86, 0xCF, 0x2D, 0xC2, 0x01, 0x8B, + 0x66, 0x1E, 0x64, 0xCD, 0xC7, 0x68, 0xD3, 0x34, 0xFC, 0xB7, 0xED, 0x89, 0x55, 0xCC, 0x33, 0xC9, 0xD5, 0x8B, 0x9A, 0x3A, + 0x38, 0x84, 0xCF, 0xC7, 0x34, 0xCA, 0x0C, 0x20, 0xEA, 0x4D, 0x6F, 0x2A, 0xF5, 0xA1, 0x0A, 0xC8, 0x17, 0x0A, 0x6C, 0xA8, + 0x4C, 0x24, 0xAC, 0x6A, 0xBB, 0xEF, 0xC8, 0xDC, 0x22, 0x31, 0xB4, 0x98, 0xF2, 0xD5, 0xF6, 0xFC, 0x46, 0x41, 0x21, 0x8C, + 0x94, 0x9C, 0x17, 0x8E, 0x54, 0x06, 0x8B, 0x5D, 0x23, 0xAE, 0xF2, 0xED, 0xC7, 0x91, 0xA1, 0x9E, 0x56, 0x63, 0x75, 0xF8, + 0x28, 0xA2, 0x27, 0xCF, 0xCD, 0x27, 0x13, 0x7D, 0x62, 0x5C, 0xA5, 0x7B, 0x3A, 0xEC, 0xD9, 0x81, 0x40, 0x76, 0xE4, 0xC6, + 0xC1, 0x72, 0x0C, 0xA5, 0x81, 0xFF, 0x98, 0x20, 0x59, 0x75, 0xF5, 0x14, 0x7D, 0x33, 0x38, 0xF6, 0xE0, 0xEC, 0x22, 0x84, + 0x41, 0x5C, 0x61, 0xFA, 0x84, 0x2D, 0x78, 0xFB, 0xC2, 0x16, 0x09, 0x2F, 0x11, 0xED, 0x1E, 0xD3, 0x0B, 0x93, 0xAD, 0x5B, + 0x5C, 0x7F, 0x73, 0x30, 0xE2, 0xF3, 0xA6, 0x6A, 0xCA, 0x13, 0xD9, 0x35, 0xEC, 0x3D, 0xC4, 0x2D, 0x54, 0x8C, 0x35, 0x44, + 0x0B, 0xA3, 0xA2, 0x88, 0x31, 0x3C, 0x6C, 0x0F, 0xEF, 0x16, 0xB4, 0x53, 0x6C, 0x79, 0xA0, 0x4F, 0x22, 0xD5, 0x37, 0x26, + 0x12, 0x96, 0x62, 0xAD, 0x65, 0x3D, 0xE4, 0x0F, 0xFC, 0xA3, 0x7D, 0x3E, 0x4B, 0x75, 0x05, 0xB0, 0x9D, 0x3B, 0xD9, 0xA6, + 0xE3, 0x5D, 0x2E, 0x67, 0x10, 0x36, 0x8D, 0xB0, 0x59, 0xBA, 0x97, 0xD2, 0xB5, 0xDE, 0xFC, 0x9A, 0x5C, 0x39, 0xD5, 0xD4, + 0x71, 0x10, 0x1E, 0x9D, 0xC1, 0x3B, 0x46, 0x49, 0x54, 0xA4, 0x2C, 0x53, 0x6E, 0xE0, 0xA8, 0x90, 0xF5, 0x8E, 0x1B, 0x68, + 0xF9, 0xE8, 0xA1, 0xE3, 0x8E, 0xA4, 0xDF, 0x49, 0x59, 0x59, 0x9F, 0x54, 0x59, 0x34, 0x7D, 0xE9, 0xAC, 0x54, 0x3C, 0xD7, + 0x61, 0xC7, 0xC8, 0xDA, 0xB9, 0x53, 0x9F, 0xA0, 0xD8, 0x38, 0xCF, 0xED, 0x22, 0xB6, 0x9D, 0x9D, 0x46, 0xB6, 0x61, 0x90, + 0x69, 0x39, 0x0A, 0x52, 0x18, 0x28, 0x92, 0x2A, 0x9A, 0x8D, 0x98, 0xAE, 0xC1, 0xB7, 0x96, 0xAD, 0xE7, 0x54, 0x2D, 0x04, + 0xA8, 0x3E, 0x06, 0xDD, 0x54, 0xE2, 0xF4, 0x6C, 0xD9, 0x92, 0x66, 0x68, 0x80, 0xA5, 0xBE, 0x5B, 0x88, 0x70, 0xFD, 0x0E, + 0x60, 0x7D, 0x47, 0xF1, 0x51, 0x7A, 0xD1, 0x6D, 0xE7, 0x81, 0x49, 0xC6, 0xF9, 0x9C, 0xDF, 0xEF, 0x85, 0xEA, 0x6B, 0xA6, + 0x18, 0xB4, 0x05, 0x23, 0x9F, 0xF0, 0x24, 0x7F, 0x19, 0x9F, 0x40, 0xB5, 0x9C, 0x8F, 0xB5, 0x74, 0xEF, 0x55, 0x28, 0xD1, + 0x67, 0x1D, 0x0A, 0xB6, 0x3D, 0xB1, 0x02, 0xC2, 0x59, 0x01, 0x64, 0x23, 0xC1, 0xB0, 0xA8, 0xC3, 0x29, 0xB1, 0x02, 0xC5, + 0x29, 0x8D, 0x41, 0x01, 0x1A, 0x8F, 0xB4, 0x39, 0xA4, 0xE0, 0x63, 0x00, 0x2F, 0x3B, 0xE9, 0x36, 0xE7, 0x06, 0x49, 0xA4, + 0x11, 0x8C, 0x0E, 0x3E, 0x68, 0x3C, 0x59, 0x80, 0x7E, 0x81, 0x79, 0x56, 0x7C, 0x61, 0xF3, 0x22, 0x14, 0xE8, 0x64, 0x34, + 0xFD, 0x5C, 0x2A, 0xBC, 0x32, 0x6B, 0x86, 0x95, 0xDA, 0x39, 0xDF, 0x6E, 0x01, 0x4E, 0x79, 0x16, 0x1B, 0x28, 0x06, 0x75, + 0xE6, 0x87, 0x86, 0x70, 0xB6, 0x66, 0x07, 0xF3, 0x85, 0xE4, 0xDF, 0x86, 0x19, 0x20, 0xD1, 0x11, 0xA4, 0x61, 0x89, 0x97, + 0x9A, 0x17, 0x15, 0x2D, 0x6C, 0xA4, 0x97, 0x96, 0x91, 0xCF, 0xF5, 0x7D, 0x48, 0x6A, 0x8B, 0x84, 0x5B, 0xEA, 0x42, 0x08, + 0x92, 0x85, 0x9C, 0x26, 0x7C, 0xA8, 0xBE, 0xDB, 0xB1, 0xC7, 0xCC, 0x9E, 0x37, 0x8B, 0xDC, 0x15, 0xAE, 0x04, 0x6A, 0x5B, + 0xF7, 0x74, 0xB6, 0xCB, 0xB0, 0xC6, 0x84, 0x07, 0xD0, 0x4F, 0x69, 0x16, 0xCC, 0x8C, 0x5C, 0x7D, 0xEE, 0x75, 0x53, 0x98, + 0x7B, 0x88, 0x4C, 0x5D, 0x37, 0x5B, 0xD4, 0x64, 0xFE, 0x8B, 0xD3, 0x38, 0x60, 0xA4, 0x05, 0x26, 0xAC, 0x57, 0x2C, 0x7F, + 0xD9, 0xC7, 0xCE, 0xD9, 0x20, 0x86, 0x1E, 0x3C, 0xBD, 0x53, 0x3E, 0xEE, 0x43, 0x8A, 0x09, 0x9E, 0xC5, 0x1D, 0x4C, 0x66, + 0x2D, 0x2D, 0x6D, 0x1D, 0x3A, 0xEC, 0x44, 0xBE, 0x49, 0xA5, 0x8C, 0x8D, 0xD3, 0x30, 0xE1, 0x58, 0xA4, 0xED, 0xE5, 0x03, + 0x17, 0xE7, 0x7B, 0x6F, 0x67, 0xDD, 0x8D, 0x69, 0x3F, 0x6D, 0x7C, 0x4A, 0xFB, 0xAA, 0xD1, 0xA0, 0x62, 0xC3, 0xDA, 0xFF, + 0x8E, 0xA7, 0x83, 0x00, 0xFC, 0x4C, 0x70, 0x60, 0x78, 0x67, 0x75, 0x78, 0x5F, 0xBF, 0x0A, 0x96, 0x62, 0xB8, 0x4D, 0x99, + 0x52, 0x50, 0x2E, 0xE0, 0x16, 0x19, 0x84, 0xEC, 0x33, 0xF3, 0x33, 0x4F, 0x8C, 0x49, 0x1B, 0x17, 0x94, 0xCE, 0x27, 0x54, + 0x84, 0xA3, 0xA7, 0xF4, 0xD0, 0xB4, 0xD9, 0x5A, 0xEC, 0x90, 0x65, 0x23, 0xC3, 0x33, 0xD5, 0xD5, 0xE1, 0x95, 0xBE, 0xE9, + 0x16, 0xD6, 0x25, 0xA2, 0x04, 0x7C, 0xC4, 0x4D, 0x0E, 0x2C, 0x34, 0xE6, 0xDB, 0xF8, 0xC3, 0x42, 0x5B, 0x1F, 0xD4, 0x90, + 0x04, 0x73, 0xCC, 0x1D, 0xA0, 0xFC, 0x50, 0x7F, 0x21, 0xFD, 0x30, 0xB4, 0x57, 0x55, 0x34, 0x76, 0x6A, 0xF3, 0xA5, 0x68, + 0x71, 0x1C, 0x03, 0x9F, 0xA7, 0xD6, 0xDD, 0x39, 0xB0, 0x5F, 0xB5, 0xA6, 0x22, 0x7B, 0x74, 0x65, 0x58, 0x09, 0x91, 0xB1, + 0x84, 0xF7, 0x93, 0xD1, 0x56, 0x34, 0x35, 0xE3, 0x5E, 0x57, 0xC8, 0xB7, 0xB3, 0xF1, 0x06, 0xD6, 0x8D, 0x14, 0x19, 0x6C, + 0x74, 0x79, 0x27, 0x59, 0x54, 0x9A, 0x76, 0x2E, 0x79, 0xE3, 0xEA, 0x1C, 0x5D, 0x9A, 0x51, 0xEC, 0xD6, 0x21, 0x46, 0xC9, + 0x5D, 0x9B, 0x17, 0xC0, 0xE8, 0x85, 0xE3, 0x0E, 0xEF, 0xFA, 0x87, 0x19, 0xD7, 0x4A, 0xBB, 0x5E, 0x05, 0xEB, 0x31, 0x2B, + 0xF6, 0xF1, 0x3C, 0x93, 0xE7, 0x11, 0x2F, 0x6B, 0xC5, 0xF9, 0xB3, 0x4F, 0x10, 0xD4, 0x00, 0xF0, 0xFB, 0xD2, 0xE1, 0xC8, + 0xD3, 0x61, 0x94, 0x3D, 0xB2, 0x61, 0x08, 0x2A, 0x87, 0xF6, 0x80, 0x0D, 0x1D, 0xDC, 0x95, 0xEA, 0xFC, 0x32, 0xD6, 0xEE, + 0xB7, 0xA2, 0x74, 0xBF, 0xE0, 0x9F, 0x7E, 0x1E, 0xE3, 0xBC, 0x71, 0xA9, 0xC6, 0x93, 0x9F, 0x4B, 0xD3, 0xD5, 0xB7, 0xAE, + 0x7A, 0x9C, 0x8F, 0xF2, 0x03, 0x77, 0xCF, 0xA9, 0xCD, 0x38, 0xB5, 0xDD, 0x18, 0x1F, 0xF3, 0xB9, 0xEE, 0x5F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xA3, 0xA5, 0xDC, 0x83, 0x34, 0x66, 0xFB, 0xC1, 0xD0, 0xA4, 0xAD, 0x4E, 0xAE, 0x11, 0xF3, 0x10, 0xAD, 0xA5, + 0xE0, 0xAE, 0x19, 0x64, 0x91, 0x3E, 0xE3, 0xF2, 0xE0, 0xFE, 0xA6, 0x1C, 0xF6, 0x71, 0x22, 0xB0, 0x58, 0xC1, 0x2D, 0x96, + 0xAC, 0x8F, 0x29, 0xDE, 0x43, 0x4F, 0x95, 0xEF, 0xE3, 0x27, 0x5C, 0x62, 0xEF, 0x81, 0xB7, 0x21, 0xF0, 0x27, 0x71, 0x53, + 0x32, 0x2D, 0xA7, 0x1C, 0x76, 0x78, 0xED, 0x32, 0xB9, 0xFB, 0x23, 0x86, 0x96, 0x2A, 0x6E, 0x01, 0xE1, 0xEF, 0xEE, 0xC5, + 0x98, 0x95, 0x99, 0xA0, 0xFC, 0x0A, 0x92, 0x51, 0x7B, 0xE6, 0xF4, 0xE2, 0x0F, 0x4D, 0xBE, 0x48, 0xB8, 0x66, 0x9C, 0x79, + 0x00, 0xD2, 0x65, 0xA7, 0xDA, 0x05, 0x05, 0x60, 0x2B, 0x65, 0xAF, 0xC4, 0x3B, 0x65, 0xFD, 0x9E, 0x70, 0xDC, 0xB7, 0xE1, + 0x72, 0x84, 0xD9, 0x10, 0x89, 0xE3, 0x75, 0x0A, 0x19, 0x44, 0xFD, 0x7B, 0x32, 0x64, 0xE3, 0xCC, 0x5C, 0x8C, 0xD2, 0xA9, + 0x17, 0x40, 0x75, 0x5F, 0x6C, 0x27, 0xA7, 0x6B, 0x6B, 0xA8, 0x1F, 0x6F, 0x7D, 0x2A, 0x9E, 0xC5, 0x41, 0x08, 0x0A, 0x4E, + 0xB2, 0x00, 0xE4, 0x49, 0x8C, 0x2A, 0x11, 0x21, 0x50, 0xCB, 0x95, 0x5A, 0xFA, 0x41, 0x92, 0x5E, 0xE4, 0x25, 0x5E, 0xEA, + 0x0D, 0x86, 0x35, 0x0C, 0x78, 0x84, 0xDB, 0xA8, 0xC7, 0xFE, 0xCB, 0x21, 0x89, 0x6D, 0xD7, 0xE8, 0x5E, 0x4C, 0x94, 0xBF, + 0x70, 0x04, 0x80, 0x6E, 0x82, 0xEF, 0x69, 0xFF, 0x78, 0x64, 0x13, 0xDD, 0xAE, 0xB2, 0xAA, 0x42, 0x66, 0x22, 0x00, 0x4F, + 0x23, 0x6E, 0x25, 0x83, 0xB2, 0x6E, 0x98, 0xD8, 0x6B, 0x71, 0x61, 0xA5, 0x4E, 0xE3, 0xF7, 0x4E, 0x6B, 0xB1, 0x52, 0x1E, + 0xF0, 0xEF, 0xF6, 0x1E, 0x51, 0x05, 0x7C, 0x81, 0x9D, 0x74, 0x25, 0x7F, 0x2A, 0xCC, 0x89, 0x82, 0x2C, 0x03, 0x46, 0x25, + 0xC9, 0xD3, 0x72, 0x77, 0xBC, 0x3D, 0x45, 0x12, 0x68, 0x30, 0xD0, 0x9A, 0xAC, 0xF3, 0x5A, 0x28, 0xCA, 0x75, 0x1A, 0x6C, + 0x31, 0x73, 0x49, 0xB1, 0x39, 0xAA, 0xBF, 0x15, 0x90, 0x0E, 0x12, 0x72, 0x24, 0xBF, 0xFA, 0xBB, 0xD4, 0xC7, 0xCA, 0xA0, + 0xC4, 0xF2, 0x36, 0x00, 0x28, 0x31, 0x35, 0x6A, 0xA7, 0xA8, 0x0A, 0xB9, 0x44, 0xBF, 0x1D, 0x95, 0x00, 0xFC, 0x20, 0xF2, + 0x3B, 0x7A, 0xE7, 0xC2, 0x64, 0x49, 0x14, 0xCC, 0x97, 0x9B, 0xD4, 0x0E, 0xD9, 0x4B, 0xAA, 0x44, 0x74, 0x1C, 0x0E, 0xBE, + 0x42, 0x75, 0xF4, 0x2E, 0xF2, 0xBF, 0x74, 0x92, 0x9E, 0x59, 0x08, 0x0E, 0x88, 0x37, 0xE9, 0x53, 0x9E, 0x1C, 0x11, 0x47, + 0x32, 0xAC, 0x95, 0x61, 0xE7, 0x8B, 0x48, 0xDB, 0xD4, 0x83, 0x32, 0x8B, 0x5E, 0x8B, 0x4A, 0x24, 0x10, 0xB7, 0x65, 0x19, + 0xB3, 0x1A, 0x9D, 0xB1, 0x06, 0x7B, 0x9A, 0x97, 0x16, 0x1E, 0xFF, 0x5C, 0x9B, 0x24, 0x07, 0x5B, 0x50, 0xF7, 0xDE, 0x91, + 0x91, 0xFB, 0xA2, 0x68, 0x75, 0xEF, 0xA4, 0x4C, 0x65, 0x21, 0x47, 0x22, 0x8C, 0xA6, 0x9C, 0x52, 0x7F, 0x52, 0xF3, 0x72, + 0x09, 0xE5, 0x9E, 0x7E, 0xDC, 0xC7, 0x86, 0x5A, 0xD4, 0x25, 0xDD, 0xAC, 0x07, 0x87, 0xF0, 0xEB, 0x6B, 0x1B, 0xF1, 0xA8, + 0x36, 0x96, 0xA2, 0xFE, 0x37, 0x53, 0xEB, 0xD3, 0x5A, 0xD6, 0xC1, 0x38, 0x29, 0x8D, 0xF4, 0xDF, 0x99, 0xAD, 0xAD, 0xE0, + 0xCF, 0x23, 0xEE, 0x93, 0xFB, 0x71, 0xED, 0x2B, 0xA7, 0xA0, 0x49, 0x2D, 0x98, 0xBD, 0x23, 0x12, 0xE8, 0x50, 0x1E, 0xB9, + 0x46, 0x73, 0x39, 0xCF, 0x4B, 0x9D, 0xB9, 0xF4, 0x4B, 0xB4, 0xFE, 0x97, 0x7F, 0xD3, 0x64, 0x4D, 0x06, 0x5D, 0x37, 0xD4, + 0x2B, 0x08, 0xFD, 0xCE, 0x18, 0xEE, 0xA0, 0x3B, 0x4A, 0x80, 0xE7, 0x02, 0x78, 0x72, 0x76, 0xA7, 0x02, 0x02, 0x32, 0xF5, + 0x78, 0xCE, 0xE1, 0xDA, 0x44, 0x82, 0x13, 0xE0, 0xF5, 0x8C, 0x56, 0x14, 0xEC, 0xE2, 0x96, 0x22, 0x74, 0xA5, 0x83, 0x70, + 0xE4, 0x3C, 0xE6, 0x53, 0x5D, 0xE2, 0xF5, 0x70, 0xE6, 0x33, 0x9F, 0x32, 0x56, 0x5D, 0xB6, 0x0F, 0x25, 0x7D, 0xD3, 0xB6, + 0xD5, 0x82, 0x7A, 0xE0, 0x09, 0x8E, 0xCB, 0x08, 0x94, 0x63, 0x11, 0x51, 0x2C, 0xB0, 0x7D, 0xF2, 0xD3, 0x98, 0xB7, 0xB2, + 0x81, 0xF5, 0x72, 0xC4, 0xC2, 0x35, 0xD3, 0x91, 0xCA, 0x39, 0x4F, 0xF5, 0x2E, 0x39, 0xCB, 0xA1, 0x8B, 0x88, 0x79, 0x49, + 0x2B, 0x18, 0x5E, 0xC3, 0xCB, 0xA0, 0x4B, 0x4E, 0xAB, 0x54, 0x1F, 0x45, 0x67, 0x05, 0x5E, 0xA5, 0xB2, 0x72, 0x09, 0x70, + 0xA0, 0x82, 0x97, 0x5F, 0xD5, 0x66, 0x90, 0x14, 0x51, 0x8D, 0xF1, 0x4B, 0xA4, 0x1C, 0xCD, 0x11, 0x2C, 0x84, 0x55, 0x08, + 0x1D, 0x56, 0x5D, 0x8E, 0x77, 0xE1, 0xFC, 0x3A, 0x40, 0x03, 0xF2, 0xBB, 0x3A, 0xC6, 0x40, 0x51, 0x34, 0xE5, 0x3C, 0xB3, + 0xE6, 0xCD, 0xBC, 0xEE, 0x8D, 0x58, 0xC1, 0x7D, 0x4B, 0xEB, 0xC4, 0x38, 0xBC, 0x6A, 0x84, 0xA7, 0x65, 0x49, 0x35, 0xF0, + 0xBC, 0x9B, 0x0B, 0xD4, 0x4F, 0xC7, 0xA5, 0x4D, 0xBC, 0xF4, 0x11, 0xAA, 0xE7, 0xC9, 0xD5, 0x19, 0x7C, 0x28, 0xF4, 0xFB, + 0xDD, 0x66, 0x20, 0xCC, 0x51, 0xA9, 0xA2, 0x24, 0x6F, 0xEC, 0x5A, 0xBD, 0x38, 0xBC, 0x8F, 0x18, 0xF9, 0xF3, 0x0D, 0x10, + 0x94, 0x7D, 0x6F, 0xAA, 0x39, 0x1C, 0xCA, 0x93, 0x9F, 0x3D, 0x28, 0x80, 0xB4, 0x8F, 0x9C, 0x47, 0xB4, 0xCE, 0x1C, 0x11, + 0x37, 0x12, 0x5B, 0xBC, 0xB0, 0xA8, 0x0A, 0x55, 0xE0, 0x3B, 0x08, 0x28, 0x37, 0xCD, 0x15, 0x5D, 0x6E, 0x0C, 0xB2, 0xB3, + 0x3A, 0x00, 0x3B, 0x3F, 0x2E, 0xB4, 0xC5, 0xDF, 0x15, 0x7E, 0x89, 0xFD, 0xB9, 0xCF, 0x32, 0x15, 0x0C, 0x1D, 0xB4, 0x83, + 0xA0, 0x2C, 0xAC, 0x8B, 0x14, 0x6B, 0xFD, 0x68, 0xDE, 0x4E, 0x92, 0xA2, 0x54, 0xB5, 0xFB, 0xCD, 0xEA, 0x57, 0xC4, 0x89, + 0x17, 0x24, 0x1F, 0x68, 0x17, 0x67, 0xB4, 0xF7, 0x34, 0xAD, 0x88, 0xFC, 0xE2, 0x99, 0x75, 0x46, 0x16, 0xAF, 0xED, 0x13, + 0xA0, 0x0E, 0xCC, 0xD7, 0xF1, 0x17, 0xB9, 0xF3, 0xA9, 0x5E, 0x69, 0x8C, 0xD3, 0x66, 0xF4, 0x40, 0xA6, 0x8D, 0x9A, 0xFB, + 0xCA, 0xC5, 0xB4, 0x62, 0xBF, 0x96, 0x0F, 0x62, 0x74, 0x48, 0xF2, 0xB0, 0xDC, 0x48, 0xE3, 0xB4, 0x39, 0xD7, 0xBC, 0x93, + 0xAC, 0xD9, 0xD8, 0xD0, 0x57, 0x64, 0x5D, 0x3D, 0x24, 0x92, 0x56, 0xEB, 0x34, 0xB2, 0x69, 0x30, 0x1B, 0xD9, 0x65, 0xC7, + 0xCA, 0xB6, 0x13, 0x76, 0x5E, 0x38, 0x29, 0x07, 0xBF, 0x0E, 0xD9, 0xB1, 0x63, 0xDA, 0x7D, 0xF4, 0x53, 0x5C, 0x0E, 0xE8, + 0xD5, 0x94, 0x34, 0xA6, 0xF4, 0x59, 0x48, 0x9E, 0x87, 0x39, 0xE2, 0x46, 0x74, 0xBA, 0x91, 0xD8, 0x8C, 0x6C, 0x13, 0x1A, + 0x3B, 0x28, 0x5E, 0xD5, 0x6B, 0x9B, 0x1D, 0x1B, 0xA5, 0xBA, 0x1F, 0xF5, 0x2D, 0x97, 0xB2, 0x0B, 0xD9, 0xBC, 0x23, 0x5A, + 0xEA, 0x13, 0xF3, 0x4F, 0x20, 0x79, 0xFA, 0x1F, 0xA3, 0x57, 0x91, 0xAB, 0x1E, 0xDE, 0x2C, 0xD9, 0x06, 0x1A, 0x9C, 0x1E, + 0xE1, 0xFF, 0x34, 0x3B, 0x44, 0x98, 0xFE, 0xDE, 0x0D, 0x0A, 0x89, 0x1A, 0x5F, 0x7D, 0x64, 0xEE, 0xB6, 0x76, 0xCD, 0xED, + 0x4C, 0x99, 0x56, 0x2D, 0x1D, 0xAD, 0x2C, 0xE4, 0x84, 0xB9, 0xC0, 0xD2, 0xF2, 0x5B, 0x39, 0x7F, 0x2A, 0x98, 0xC7, 0xCB, + 0x8D, 0xC8, 0x23, 0x18, 0x6A, 0x53, 0x61, 0x9D, 0x15, 0xAF, 0x17, 0x59, 0x7B, 0xA6, 0x57, 0x2C, 0x95, 0xD3, 0x47, 0x05, + 0x62, 0x22, 0x33, 0x3F, 0x85, 0xBD, 0x9A, 0xEA, 0x63, 0x09, 0xD9, 0x3E, 0x16, 0xEB, 0x2B, 0x91, 0x24, 0xEF, 0x9C, 0xC9, + 0x71, 0x3B, 0xED, 0xAC, 0xEA, 0x65, 0x37, 0xF6, 0x72, 0xE5, 0x66, 0x19, 0xB4, 0xE2, 0x2E, 0xB0, 0x2C, 0xA2, 0x96, 0xF2, + 0x04, 0x89, 0x4A, 0x81, 0xFD, 0xF9, 0x83, 0x5E, 0xA8, 0x73, 0x27, 0xD8, 0xF1, 0xB9, 0x31, 0xEF, 0x2D, 0x0E, 0x18, 0xFF, + 0x60, 0x6C, 0x08, 0xC2, 0xF1, 0xE3, 0xA7, 0xE5, 0xB1, 0xBC, 0x16, 0x5A, 0x60, 0x46, 0x77, 0x6C, 0x14, 0x8D, 0xDE, 0x99, + 0xEF, 0x06, 0x4E, 0x90, 0x31, 0x44, 0x31, 0x6F, 0x6D, 0xD0, 0xDF, 0x2A, 0xD9, 0xB4, 0xD8, 0xB6, 0x1F, 0x46, 0x58, 0x85, + 0x6B, 0x7F, 0x97, 0x5A, 0x63, 0x39, 0x50, 0x02, 0x6F, 0x80, 0x8C, 0x07, 0x3F, 0x4F, 0xA9, 0x41, 0xB9, 0x77, 0x9B, 0xD5, + 0x81, 0xBB, 0x81, 0x41, 0x47, 0xB6, 0xD8, 0x74, 0xE1, 0x67, 0x80, 0x4E, 0xD5, 0xA4, 0xFD, 0xF9, 0xAB, 0x48, 0xA2, 0x45, + 0xA1, 0xA7, 0x83, 0x2A, 0xAA, 0x0A, 0xEC, 0x11, 0xB9, 0xC7, 0x12, 0xEB, 0x8D, 0xA4, 0xB2, 0x2C, 0x4F, 0x86, 0xE7, 0xD4, + 0x49, 0xB2, 0xFC, 0xF9, 0x5A, 0xE3, 0x3D, 0x25, 0x68, 0x8B, 0xDB, 0x5C, 0x25, 0x8B, 0x89, 0x96, 0x21, 0x20, 0x00, 0x5E, + 0xAC, 0x06, 0x73, 0xA9, 0x65, 0xA4, 0x2B, 0x6F, 0xFB, 0x8C, 0x03, 0xC5, 0x25, 0x09, 0xA5, 0x9C, 0xB1, 0x66, 0x1B, 0xF3, + 0xFF, 0x43, 0x65, 0x75, 0x82, 0x7D, 0x53, 0x48, 0x16, 0xEC, 0x28, 0xE8, 0x34, 0x49, 0x95, 0x58, 0x7C, 0x8D, 0xDF, 0xD8, + 0x72, 0x7C, 0xD9, 0xFC, 0x60, 0x8F, 0x92, 0x41, 0xD9, 0x8A, 0x42, 0x36, 0x2D, 0x4F, 0xEC, 0x26, 0x43, 0xDB, 0x93, 0x61, + 0xCA, 0x4A, 0x7F, 0xE9, 0xD0, 0x94, 0x8B, 0xB5, 0x31, 0x09, 0x67, 0x22, 0x51, 0xDE, 0x7B, 0x70, 0xF8, 0xBF, 0x03, 0x1F, + 0x68, 0x0A, 0x92, 0x73, 0x10, 0xBF, 0x1A, 0x78, 0xCD, 0x3F, 0x25, 0xC6, 0xB1, 0xC8, 0x94, 0x49, 0x56, 0xDB, 0x9D, 0xD7, + 0xEB, 0x7B, 0x12, 0x60, 0x52, 0x11, 0x65, 0xCA, 0xC6, 0x21, 0x47, 0x8F, 0x77, 0x1A, 0x10, 0x72, 0x94, 0xBF, 0xDF, 0xE9, + 0x84, 0x70, 0x3E, 0x51, 0x24, 0x23, 0x42, 0x0D, 0x8F, 0x7B, 0x45, 0xC0, 0xA7, 0xDA, 0xF5, 0x65, 0x8A, 0x42, 0xE8, 0xA0, + 0x26, 0xDE, 0xD6, 0xF2, 0xC2, 0xFF, 0x1E, 0x05, 0x81, 0x71, 0x70, 0xA6, 0xC5, 0x51, 0xFC, 0xF4, 0x40, 0x54, 0xAB, 0x23, + 0x74, 0x56, 0x4D, 0x32, 0x8F, 0x9E, 0xF2, 0xEC, 0x45, 0xEA, 0x9C, 0xF0, 0x27, 0x17, 0x4C, 0x70, 0x1D, 0x50, 0x47, 0x23, + 0x0E, 0x9D, 0xFD, 0xF4, 0xCA, 0xC9, 0xD1, 0x65, 0xAE, 0xB9, 0x1A, 0xA5, 0xF6, 0x18, 0x5D, 0x33, 0x21, 0x5F, 0x93, 0x37, + 0xB7, 0x9A, 0x14, 0xF1, 0x63, 0x09, 0xE4, 0xB7, 0x52, 0x6C, 0x7F, 0xF7, 0x48, 0x11, 0x46, 0xF9, 0x5F, 0x65, 0xEB, 0xC7, + 0xE5, 0xFE, 0x2E, 0x3F, 0x56, 0xD5, 0xF5, 0xE6, 0xA8, 0x14, 0x7F, 0x8D, 0xF2, 0x49, 0xD5, 0x48, 0x93, 0x28, 0xD6, 0xA9, + 0x90, 0x3A, 0xF8, 0xF7, 0xCA, 0x6C, 0xFF, 0x8F, 0xF8, 0x6A, 0x9E, 0xE9, 0xEC, 0x7F, 0x47, 0x29, 0x96, 0x58, 0xB0, 0xDB, + 0x08, 0x59, 0xAB, 0x5E, 0x9D, 0xB6, 0xDF, 0xCC, 0x7B, 0x56, 0x67, 0xB5, 0x10, 0x18, 0xCA, 0xAA, 0x69, 0xC3, 0xD7, 0x48, + 0x57, 0x59, 0xF1, 0xDD, 0x6C, 0x85, 0x21, 0x68, 0x1C, 0xB3, 0x76, 0x08, 0xD0, 0x12, 0xD8, 0xE1, 0xC0, 0x90, 0x66, 0x0B, + 0x5B, 0x38, 0x61, 0x78, 0x15, 0x97, 0x3F, 0x4B, 0xA3, 0xA3, 0xFF, 0x37, 0x16, 0x33, 0xCB, 0x6B, 0x06, 0x57, 0xBF, 0x8F, + 0x49, 0x12, 0x2F, 0xDB, 0xD0, 0x12, 0x5C, 0x65, 0x48, 0x51, 0x67, 0x0A, 0xD3, 0xD4, 0x97, 0xE1, 0xC8, 0x88, 0x84, 0x7C, + 0xA7, 0xE5, 0xDE, 0x01, 0xB5, 0x7F, 0xEC, 0xAC, 0x60, 0x4D, 0x4F, 0x55, 0x76, 0xA2, 0x3A, 0x13, 0xFA, 0x0C, 0xA5, 0x68, + 0xDF, 0xB9, 0xF8, 0x47, 0x9D, 0xCC, 0x45, 0xDA, 0x55, 0x5A, 0x9E, 0xE1, 0x6D, 0x08, 0x15, 0x65, 0x1B, 0x04, 0xCC, 0xD3, + 0x27, 0xB3, 0x67, 0xE1, 0x3D, 0x13, 0xFD, 0xED, 0x78, 0x22, 0xA1, 0x2E, 0x74, 0xFC, 0x21, 0xAA, 0xA6, 0x9A, 0xA1, 0xCF, + 0x2D, 0xA1, 0x68, 0xE5, 0x65, 0xA4, 0x5B, 0xD5, 0x62, 0xAE, 0xC8, 0xD0, 0x42, 0xA4, 0x44, 0x41, 0xE7, 0xE8, 0xE8, 0xBA, + 0x5B, 0xC8, 0x7F, 0x5D, 0x2B, 0x95, 0x22, 0xE3, 0x67, 0x85, 0x2A, 0x80, 0xD4, 0xE8, 0x19, 0x05, 0xD6, 0xCA, 0x63, 0x59, + 0xE2, 0x52, 0xB1, 0x06, 0x64, 0x84, 0xC9, 0x8F, 0x2E, 0xA4, 0x31, 0xB3, 0x05, 0xAF, 0x9C, 0x46, 0x65, 0x0A, 0xF8, 0xF7, + 0xB4, 0xF2, 0x80, 0x30, 0x2A, 0x91, 0xB4, 0xF9, 0x60, 0x55, 0x62, 0x7B, 0x88, 0xA5, 0xA7, 0xAE, 0x21, 0x03, 0x38, 0x47, + 0xB5, 0x39, 0x2C, 0x36, 0x8D, 0x1E, 0x61, 0x41, 0xA8, 0x55, 0x98, 0x17, 0xFE, 0x84, 0xC2, 0x19, 0xA0, 0xE6, 0x75, 0x3F, + 0x67, 0x4B, 0xFB, 0x2E, 0x9A, 0x61, 0x0B, 0xCB, 0x8E, 0x41, 0x73, 0x9A, 0x62, 0x37, 0x11, 0xE8, 0xE9, 0x24, 0x6B, 0xF7, + 0x6D, 0xE9, 0x40, 0xDB, 0x89, 0xD0, 0x85, 0x02, 0x26, 0x70, 0x5D, 0x28, 0x4D, 0x33, 0xF5, 0xBC, 0x3D, 0xCC, 0x4C, 0x0E, + 0xC3, 0x4A, 0x0F, 0x10, 0xC8, 0xB3, 0x30, 0x0F, 0xAC, 0xE8, 0xE1, 0xAF, 0xBC, 0xED, 0x25, 0x10, 0x6F, 0x0D, 0x9B, 0x94, + 0xAB, 0xFC, 0x1B, 0xC9, 0x06, 0x86, 0xDD, 0x77, 0x7D, 0xA7, 0xF2, 0x2B, 0x61, 0x8C, 0xCC, 0xE4, 0x65, 0x73, 0x31, 0x0A, + 0x2C, 0xEA, 0xD5, 0x76, 0x99, 0x46, 0xFF, 0xFF, 0xC0, 0x62, 0x4C, 0x56, 0x3E, 0x70, 0xBE, 0x3D, 0xCD, 0x1A, 0xDA, 0x26, + 0xDF, 0x93, 0x2C, 0x4B, 0x07, 0xEB, 0x4C, 0xD5, 0x08, 0x51, 0x14, 0x6D, 0xA6, 0x9C, 0x54, 0x6A, 0xE9, 0x4A, 0x04, 0x59, + 0xD2, 0x5E, 0xEA, 0x16, 0x9E, 0xF2, 0xD8, 0x6F, 0xA4, 0x9C, 0xFC, 0xC0, 0x13, 0xA2, 0xA0, 0x27, 0x89, 0x19, 0xE1, 0x54, + 0xDE, 0x7F, 0xD6, 0x17, 0x8A, 0xC5, 0xEE, 0x7A, 0xB4, 0xEC, 0x25, 0x83, 0x86, 0x17, 0xBB, 0x8B, 0x75, 0x56, 0xB0, 0x44, + 0x32, 0x97, 0xDB, 0x59, 0xC7, 0x62, 0x8B, 0x11, 0x16, 0x7B, 0x34, 0x53, 0x1A, 0xB6, 0xAF, 0x54, 0x2F, 0x91, 0xDB, 0xEF, + 0xC7, 0x24, 0xEB, 0x80, 0xDC, 0x5E, 0x2A, 0x23, 0x76, 0xF7, 0xE4, 0xD6, 0xA0, 0xFD, 0xED, 0xCB, 0x0A, 0xE7, 0x62, 0x10, + 0x92, 0x79, 0x23, 0x9E, 0x7B, 0xB4, 0xED, 0x95, 0xAF, 0xDB, 0x5A, 0xFF, 0x37, 0xA7, 0x07, 0xDA, 0xE1, 0x3E, 0xC3, 0xBA, + 0x78, 0x71, 0x91, 0x5A, 0x5B, 0x98, 0xD9, 0x0A, 0x5B, 0x4C, 0xA7, 0x40, 0xC9, 0x47, 0x6D, 0xB1, 0x03, 0x6A, 0x95, 0x3F, + 0xDE, 0x24, 0xF7, 0x14, 0xD8, 0x16, 0x15, 0x6A, 0xCE, 0x45, 0x7E, 0x4F, 0x22, 0x0D, 0x98, 0xBB, 0xA4, 0x25, 0xFC, 0x90, + 0xC7, 0x20, 0x7D, 0xB6, 0xCD, 0x5A, 0x80, 0x6A, 0x8F, 0xFA, 0x39, 0xAE, 0x46, 0x7A, 0xA7, 0x97, 0x58, 0x14, 0x90, 0xD5, + 0x30, 0x99, 0x69, 0xA1, 0x9B, 0x4F, 0xE1, 0x48, 0xAE, 0x37, 0x53, 0xE3, 0xC6, 0x4D, 0x51, 0x88, 0x4F, 0x3F, 0xF2, 0x2E, + 0x32, 0xFA, 0x24, 0xCF, 0x0D, 0x90, 0x2E, 0x33, 0xE1, 0x36, 0xE0, 0x0E, 0xCE, 0xD6, 0xFA, 0xFA, 0xF0, 0xBC, 0x5F, 0x34, + 0x6F, 0xFC, 0xD4, 0xF3, 0x42, 0x8F, 0x2D, 0x87, 0xD6, 0x9C, 0x5C, 0x22, 0x5F, 0x79, 0x2C, 0x27, 0x2F, 0x64, 0x76, 0xEE, + 0xD3, 0xFD, 0xEC, 0xA0, 0x56, 0x63, 0x53, 0xDB, 0xFF, 0xFF, 0xA8, 0x31, 0xE9, 0x49, 0x1A, 0x62, 0x16, 0xE9, 0x49, 0xA1, + 0xE5, 0x4B, 0xEE, 0x8C, 0x33, 0x36, 0x3D, 0x12, 0xEE, 0x1A, 0xB0, 0xE7, 0x33, 0x4D, 0x20, 0x00, 0x49, 0xBE, 0xA0, 0xCF, + 0x32, 0x17, 0x59, 0x10, 0x86, 0x99, 0x34, 0xF6, 0xEC, 0x47, 0x85, 0xA3, 0x22, 0xD2, 0x06, 0xA1, 0xD6, 0x2E, 0x48, 0x77, + 0x7E, 0xAE, 0xEF, 0xB1, 0x78, 0xD2, 0x23, 0x94, 0x36, 0x58, 0x0E, 0xB1, 0xD7, 0xFA, 0x80, 0xD0, 0x4D, 0x0C, 0x3F, 0xA6, + 0x90, 0x6C, 0x08, 0x65, 0x3D, 0x64, 0x88, 0xF0, 0x25, 0xE3, 0x97, 0x50, 0x27, 0xF8, 0xB0, 0xD6, 0x1A, 0x41, 0x9C, 0xF5, + 0x00, 0xB6, 0x87, 0x8B, 0x55, 0xDE, 0xC5, 0xBC, 0x8A, 0x47, 0x0D, 0x27, 0xD3, 0x06, 0xC1, 0x89, 0xE4, 0x0B, 0x0E, 0xFC, + 0xED, 0x62, 0x53, 0x50, 0xA0, 0x6D, 0xF1, 0x05, 0x91, 0x28, 0xA6, 0x02, 0x97, 0x2B, 0x85, 0x89, 0x31, 0x9C, 0x9A, 0x17, + 0xAB, 0x8D, 0xE4, 0xAD, 0x1B, 0x10, 0x12, 0x4E, 0xC7, 0xBE, 0x3E, 0xB7, 0xD8, 0xE9, 0x53, 0x0C, 0xAC, 0xF8, 0x26, 0x8E, + 0x1D, 0x23, 0x40, 0x3A, 0xDB, 0x41, 0x5F, 0x01, 0x5F, 0x2B, 0xFC, 0xE1, 0x84, 0x45, 0xD3, 0x3C, 0xDC, 0x97, 0xA8, 0x59, + 0x48, 0x55, 0x2C, 0xCD, 0xE8, 0xE1, 0xF3, 0x6B, 0x62, 0x42, 0x08, 0x3D, 0xF1, 0x48, 0x9E, 0xBB, 0x41, 0x33, 0x3D, 0xC6, + 0x30, 0x7B, 0x82, 0xD9, 0x26, 0x81, 0xA2, 0x0C, 0x14, 0x21, 0xB5, 0xA8, 0x46, 0xB7, 0xB5, 0x81, 0xDA, 0xD7, 0x95, 0x59, + 0x2F, 0xA0, 0xC0, 0x4C, 0xB8, 0x20, 0x14, 0xD8, 0xEA, 0x4F, 0xE4, 0x65, 0x7A, 0xBF, 0x25, 0xAB, 0x8B, 0x6E, 0xC9, 0x49, + 0x39, 0x23, 0x57, 0x4D, 0xCC, 0x2C, 0x2C, 0xE9, 0xA1, 0x45, 0xCE, 0xEB, 0x83, 0xEF, 0xC1, 0x7D, 0x38, 0x22, 0x65, 0x74, + 0x44, 0xC9, 0x6C, 0x40, 0xBB, 0xFD, 0x76, 0x84, 0x6C, 0x9D, 0x3F, 0x35, 0xBC, 0x72, 0x4C, 0xA4, 0x48, 0x19, 0x51, 0x99, + 0x76, 0x32, 0x8B, 0x76, 0x12, 0x77, 0xB4, 0xD3, 0xFB, 0x32, 0xDC, 0x34, 0x11, 0x5C, 0x30, 0x2F, 0x9A, 0xC2, 0x5C, 0x00, + 0x07, 0x09, 0x1F, 0xAA, 0x47, 0x57, 0xD5, 0xD5, 0x62, 0xEF, 0x33, 0x21, 0xB2, 0x0C, 0xB5, 0x6F, 0xB1, 0x5E, 0x36, 0x06, + 0xCD, 0x39, 0x63, 0x8C, 0x4D, 0x5E, 0xA7, 0x27, 0xF1, 0xDC, 0xF3, 0xC8, 0x24, 0xAF, 0x04, 0x3C, 0xAD, 0x76, 0x2C, 0x82, + 0x80, 0x34, 0xEE, 0x54, 0x90, 0xDB, 0xE0, 0x4E, 0x22, 0x97, 0x22, 0x24, 0x23, 0x3A, 0xF0, 0xB0, 0x67, 0x7C, 0x86, 0x6F, + 0x1B, 0xC5, 0xD9, 0x45, 0xAC, 0xB9, 0x1B, 0x0B, 0x30, 0x3E, 0xD1, 0x26, 0x62, 0x76, 0x71, 0x96, 0x8E, 0x79, 0x8D, 0x55, + 0x29, 0xE8, 0x65, 0xD0, 0x97, 0x31, 0xD6, 0xB7, 0xE9, 0x4C, 0xA3, 0xF3, 0x12, 0xF4, 0xF9, 0x4F, 0x1B, 0x3E, 0xC2, 0x8E, + 0x70, 0x7A, 0x68, 0x08, 0x9C, 0xA9, 0xC5, 0x5C, 0xE6, 0x89, 0x2E, 0x6B, 0x8A, 0x0B, 0x33, 0xA5, 0xC2, 0x3D, 0xDA, 0xE6, + 0x67, 0x47, 0xDC, 0x58, 0xE4, 0x84, 0xBF, 0x16, 0x5D, 0x93, 0x1D, 0xF3, 0xB9, 0x6A, 0x4E, 0xAC, 0x3D, 0x36, 0x57, 0x29, + 0x89, 0x38, 0xB7, 0xE9, 0x29, 0xBD, 0x89, 0xF2, 0xC1, 0x84, 0x62, 0x4A, 0xCF, 0x8F, 0x32, 0x53, 0x09, 0x28, 0x1F, 0xE0, + 0x2C, 0x5E, 0xE6, 0x95, 0x3C, 0x5E, 0x36, 0x9E, 0x4B, 0x45, 0xA4, 0x1F, 0xF6, 0xD1, 0xD2, 0x5C, 0x25, 0xB2, 0xAE, 0x6F, + 0xAC, 0x30, 0x5E, 0x78, 0xEC, 0xCD, 0xE0, 0xE5, 0xF4, 0xFB, 0x65, 0x32, 0xAC, 0xA5, 0x8E, 0x6D, 0x1B, 0xEE, 0x07, 0xE5, + 0xE4, 0x5D, 0x83, 0x0F, 0xB2, 0xCE, 0xE3, 0x47, 0xA8, 0x87, 0x91, 0xE1, 0xBB, 0x90, 0x06, 0x69, 0x4E, 0x59, 0x00, 0xBD, + 0xF7, 0xD4, 0x5E, 0xDA, 0xA1, 0xEE, 0xF9, 0x9C, 0xF1, 0x21, 0x08, 0xC2, 0x0C, 0x3B, 0x4D, 0x61, 0xAD, 0x96, 0x90, 0x22, + 0xD7, 0xCE, 0x4F, 0xD6, 0x25, 0xE3, 0x68, 0xB6, 0x55, 0x4C, 0xB8, 0xC5, 0x67, 0x6A, 0x43, 0x73, 0x85, 0x20, 0xDE, 0xF8, + 0x6D, 0xCC, 0xB1, 0xA7, 0xFD, 0x1F, 0xCF, 0x8E, 0x35, 0x64, 0x77, 0xCB, 0x8D, 0x98, 0x33, 0x69, 0x94, 0xE0, 0x60, 0x33, + 0x62, 0xC5, 0x5C, 0x0A, 0xD3, 0xA1, 0x5E, 0x5A, 0x89, 0x02, 0xEA, 0x06, 0xB5, 0xA2, 0x74, 0xA2, 0x02, 0x69, 0x8E, 0x60, + 0xB7, 0x67, 0x6C, 0x76, 0x01, 0xE7, 0xEC, 0xB4, 0x95, 0xED, 0xFC, 0x8F, 0x4F, 0x84, 0xB0, 0xF6, 0xAB, 0xC6, 0xE1, 0x03, + 0x8A, 0x7D, 0x69, 0x44, 0x37, 0x2E, 0x72, 0x13, 0xCE, 0xCF, 0x83, 0xE3, 0xC9, 0x8B, 0x27, 0xF3, 0x26, 0xD7, 0xC9, 0x35, + 0xD6, 0xA3, 0xA6, 0x73, 0xE3, 0xC6, 0xA3, 0xED, 0xBF, 0x57, 0x22, 0x6C, 0x4C, 0xC7, 0x62, 0x7A, 0xB9, 0x77, 0x44, 0x90, + 0xEF, 0x89, 0xA9, 0xD5, 0xB5, 0xD8, 0x22, 0x1F, 0x6E, 0x95, 0xCC, 0x7C, 0xF6, 0xCD, 0xEE, 0xBC, 0x25, 0x75, 0xC4, 0x93, + 0xBC, 0x6F, 0x9B, 0xCC, 0x4E, 0x96, 0x1E, 0xFC, 0x18, 0xC9, 0x1E, 0x50, 0x55, 0xB7, 0x4E, 0x68, 0x25, 0x9C, 0xD3, 0xF3, + 0xD1, 0xC6, 0x14, 0x2E, 0x19, 0x54, 0x84, 0x60, 0x34, 0xF2, 0xBB, 0xCC, 0xEB, 0x60, 0x5C, 0x52, 0x81, 0x0A, 0x9A, 0x88, + 0x3E, 0xAD, 0xF6, 0x6E, 0x67, 0x14, 0x8C, 0x68, 0xBF, 0x6F, 0x6E, 0x7E, 0x3C, 0x9C, 0x15, 0x5A, 0x6E, 0xF0, 0xFA, 0x1B, + 0x1A, 0xCE, 0xF2, 0x56, 0x3C, 0x5F, 0x67, 0x0B, 0x82, 0x75, 0x24, 0xC7, 0x7F, 0x11, 0x2A, 0xF6, 0x6B, 0xC7, 0x81, 0xEB, + 0xC1, 0x83, 0xAB, 0xDF, 0x4F, 0x30, 0xD5, 0x82, 0xBC, 0xCF, 0x3F, 0xFA, 0x4D, 0x33, 0xED, 0x66, 0x34, 0xAB, 0x5C, 0x42, + 0x62, 0x8B, 0xA0, 0x38, 0xE9, 0x0D, 0x60, 0xE5, 0x8D, 0xD3, 0x83, 0x0B, 0x80, 0x63, 0x94, 0x6D, 0x16, 0xF4, 0xCE, 0x96, + 0x34, 0xA0, 0x02, 0x8F, 0xAF, 0xF2, 0x2D, 0xA8, 0xF9, 0x05, 0xAD, 0xE5, 0x53, 0x82, 0x0A, 0xA3, 0x49, 0xDC, 0x53, 0x07, + 0x0F, 0x91, 0x02, 0x1E, 0xF2, 0x02, 0x95, 0x0C, 0xB7, 0xDE, 0xF7, 0x1B, 0xC9, 0xF1, 0x43, 0x12, 0x0C, 0x90, 0x1D, 0xED, + 0x40, 0x6F, 0xBB, 0xC3, 0x02, 0x39, 0x73, 0x44, 0xDC, 0xAA, 0x24, 0xEB, 0xC5, 0xCF, 0xF3, 0x1B, 0x52, 0x5B, 0x52, 0xCA, + 0x46, 0xD5, 0x85, 0xB4, 0x5C, 0x64, 0xFB, 0x10, 0xE0, 0x95, 0xA3, 0x93, 0x8A, 0x9B, 0xE0, 0x71, 0xA2, 0x56, 0xC5, 0xDF, + 0x34, 0x11, 0x33, 0x85, 0x64, 0xD5, 0x51, 0x85, 0x0D, 0xB4, 0x75, 0xCA, 0x4E, 0xE7, 0xED, 0x24, 0xCB, 0xB1, 0xD5, 0xF6, + 0x65, 0x9F, 0x9F, 0xE7, 0xD3, 0xEC, 0xC5, 0x4A, 0x68, 0x99, 0x66, 0x1D, 0xC7, 0x33, 0x85, 0x0B, 0x5F, 0x98, 0x99, 0xC1, + 0xA5, 0x2D, 0xA8, 0xE8, 0x1E, 0x99, 0x08, 0xD9, 0xE7, 0x16, 0xFA, 0x70, 0xD6, 0x76, 0x39, 0x92, 0xF2, 0x04, 0xB6, 0x87, + 0x8E, 0xEB, 0x62, 0xB2, 0xBA, 0xF8, 0x9C, 0xEC, 0xE2, 0x06, 0xE6, 0x90, 0xC6, 0xB8, 0xD7, 0x64, 0x2D, 0x3A, 0xFA, 0xED, + 0x7F, 0xBB, 0x6D, 0xA5, 0xC3, 0x99, 0xD9, 0xB9, 0x14, 0x9F, 0x8A, 0x58, 0x2A, 0x96, 0x90, 0x00, 0x9F, 0x17, 0xBC, 0x1A, + 0x62, 0xD3, 0xBD, 0x88, 0x70, 0xBA, 0xEE, 0x9A, 0x23, 0x66, 0xD0, 0x93, 0x5E, 0xFD, 0x1E, 0xBE, 0x4E, 0x56, 0x2A, 0x04, + 0x1F, 0x67, 0xE5, 0xB8, 0xFE, 0x18, 0xB7, 0xCF, 0x55, 0x9D, 0x17, 0xAF, 0xF9, 0xD1, 0xB7, 0xC9, 0xFC, 0x73, 0x6B, 0xFF, + 0x46, 0x0F, 0xB7, 0xAF, 0x56, 0x0F, 0xA0, 0x19, 0x43, 0x54, 0x86, 0x99, 0x72, 0x9D, 0x60, 0x1B, 0x03, 0x0F, 0x84, 0x06, + 0x14, 0xDB, 0xA0, 0xA0, 0xA1, 0x23, 0xD4, 0xB2, 0x33, 0x1E, 0xE4, 0x82, 0x09, 0x09, 0xA8, 0x86, 0x91, 0x29, 0x38, 0x31, + 0x59, 0x91, 0xA2, 0x84, 0xBB, 0xCE, 0x58, 0x1E, 0x65, 0xDD, 0x81, 0xC2, 0x6D, 0xAB, 0x0A, 0xC1, 0x80, 0x72, 0x87, 0x0D, + 0x3B, 0x26, 0x9D, 0x73, 0xC0, 0x0B, 0x0D, 0xE8, 0x99, 0x62, 0x39, 0x03, 0xE5, 0x01, 0x3D, 0x31, 0xDB, 0x3F, 0x14, 0x46, + 0xCA, 0x07, 0x78, 0xBA, 0x71, 0x90, 0x43, 0x9C, 0x06, 0xC9, 0x07, 0x56, 0xAD, 0xB1, 0xF7, 0xD4, 0x05, 0x94, 0xB7, 0xBC, + 0xC5, 0x68, 0x98, 0x04, 0xC8, 0x48, 0x18, 0x24, 0x06, 0x7E, 0xE5, 0xB0, 0x21, 0x46, 0x01, 0x9C, 0xB5, 0x19, 0x2E, 0x91, + 0x12, 0xF7, 0xA9, 0xE1, 0xE5, 0xE8, 0x71, 0xBF, 0x2F, 0x0A, 0xB2, 0xBA, 0x11, 0x23, 0x22, 0x11, 0xD5, 0x2B, 0x5A, 0x13, + 0x28, 0xCA, 0x7A, 0x72, 0x29, 0x88, 0xDB, 0x25, 0x1E, 0x6A, 0x54, 0x0D, 0xA9, 0xEE, 0xEB, 0x43, 0x24, 0x97, 0xA6, 0xE8, + 0x01, 0x9F, 0x66, 0x83, 0x1A, 0x59, 0x1E, 0x1C, 0xA0, 0x39, 0xCD, 0xC7, 0xE8, 0xFA, 0x3B, 0x59, 0x08, 0x05, 0x9E, 0xF2, + 0x71, 0x1A, 0x6B, 0x69, 0xC4, 0xB1, 0x2A, 0x91, 0x2F, 0x57, 0x19, 0xC1, 0x3A, 0x46, 0x4B, 0x99, 0x6F, 0x39, 0x01, 0x3D, + 0xE8, 0x2B, 0xE0, 0x39, 0xD3, 0x37, 0xBF, 0x5B, 0x2C, 0x68, 0xCD, 0x2E, 0x14, 0x4E, 0xED, 0xF2, 0xF5, 0xD1, 0x4E, 0x3E, + 0x74, 0x0F, 0x32, 0x5C, 0xF6, 0x4F, 0xF2, 0x40, 0xC6, 0x10, 0x61, 0xE7, 0xF4, 0x56, 0x27, 0x81, 0x53, 0x2F, 0x65, 0xEC, + 0x0E, 0xA5, 0x07, 0x9D, 0xC4, 0x2D, 0xBF, 0xF6, 0xCB, 0x2E, 0x99, 0x2F, 0x9B, 0x69, 0x8B, 0x61, 0x3E, 0x7B, 0x64, 0x03, + 0x6A, 0xF3, 0x51, 0x1F, 0x38, 0x32, 0x84, 0xF4, 0xE8, 0x1D, 0xBD, 0xF0, 0xA0, 0x0F, 0x14, 0x7A, 0x9C, 0x3D, 0x90, 0x5D, + 0x68, 0x11, 0x6D, 0x83, 0xD1, 0x0F, 0x02, 0x78, 0xFD, 0xDC, 0xAC, 0x7E, 0xC4, 0xB8, 0x66, 0xD0, 0x25, 0x13, 0x3B, 0x89, + 0xA1, 0x72, 0x5F, 0x83, 0x32, 0x18, 0x69, 0x1E, 0x41, 0xBB, 0x4C, 0x89, 0x45, 0xAD, 0xAC, 0x81, 0x24, 0xA3, 0xF2, 0xD6, + 0x54, 0xE5, 0xAD, 0x1F, 0x95, 0x35, 0x50, 0xC5, 0x1C, 0x5A, 0xBA, 0x14, 0x65, 0x30, 0x7C, 0x50, 0x81, 0x51, 0xC5, 0x46, + 0xD8, 0x03, 0xAB, 0x10, 0x6A, 0x48, 0x8D, 0x74, 0xD7, 0x72, 0x49, 0x2E, 0x10, 0xC5, 0x48, 0x25, 0x43, 0x15, 0xDC, 0xB7, + 0x4D, 0x4B, 0x71, 0x0B, 0x75, 0x9C, 0xC0, 0xB3, 0xA4, 0x9E, 0xFD, 0xD5, 0x11, 0x32, 0xEA, 0xAB, 0xF2, 0x52, 0x85, 0xEC, + 0xF4, 0x1E, 0xF5, 0x3E, 0x94, 0x17, 0xAD, 0x66, 0x0D, 0x3A, 0x26, 0x19, 0x5B, 0x18, 0x32, 0x77, 0xD1, 0xC7, 0x14, 0x50, + 0x9B, 0x55, 0x25, 0x66, 0x99, 0xA7, 0x11, 0x40, 0x50, 0x15, 0x33, 0x09, 0xFA, 0xAC, 0x77, 0xFE, 0xA4, 0xAF, 0xB6, 0x62, + 0x95, 0x34, 0xDE, 0x71, 0x0C, 0xAE, 0x2E, 0xB1, 0x7F, 0xF1, 0x78, 0x79, 0xFB, 0xCB, 0x33, 0xEF, 0x43, 0x5F, 0xE8, 0x5B, + 0xC9, 0x6A, 0x25, 0xCF, 0xDB, 0x33, 0xBF, 0xEE, 0xA7, 0xA4, 0x70, 0xB9, 0xBF, 0x19, 0x1B, 0xBC, 0x96, 0x7B, 0x9A, 0xE6, + 0x04, 0xC7, 0x71, 0xF5, 0xDA, 0xCD, 0x9E, 0x48, 0xD3, 0xAD, 0x0F, 0xB0, 0xCF, 0x57, 0x8C, 0xED, 0xD9, 0x30, 0xC7, 0xBE, + 0x43, 0x87, 0xAE, 0x6F, 0x94, 0x32, 0x07, 0xA0, 0xCC, 0xD0, 0xC8, 0x8C, 0x1B, 0x07, 0xC7, 0x2C, 0x3C, 0x05, 0xB5, 0xCC, + 0xF6, 0xB3, 0x17, 0x01, 0x52, 0x13, 0x66, 0x05, 0xE4, 0x33, 0xB7, 0x31, 0xE2, 0x52, 0xEF, 0xC9, 0x39, 0x98, 0x3F, 0x4A, + 0x48, 0x50, 0xA6, 0x9B, 0xD9, 0x72, 0x8C, 0x87, 0xFB, 0x0B, 0x60, 0x82, 0x79, 0xCE, 0xEF, 0x23, 0x60, 0xDB, 0xEA, 0x9D, + 0x3C, 0x38, 0x88, 0x60, 0x67, 0x35, 0xAC, 0x32, 0x6A, 0xA1, 0xC7, 0xB6, 0x3F, 0x6B, 0xCE, 0xC5, 0xD9, 0xA0, 0x69, 0x32, + 0xE5, 0x2D, 0x46, 0x47, 0x98, 0x59, 0x20, 0x45, 0x3F, 0x4F, 0xCF, 0x21, 0x35, 0x61, 0x57, 0x14, 0x78, 0x8C, 0x39, 0xE9, + 0x68, 0x02, 0xF9, 0xA2, 0x61, 0xC9, 0xE3, 0x57, 0xBD, 0xB2, 0x18, 0xC6, 0x5A, 0x68, 0x20, 0x9F, 0x35, 0x1B, 0x9C, 0xF8, + 0x45, 0x64, 0x48, 0x95, 0x1F, 0x91, 0xB8, 0x6D, 0x29, 0x1E, 0x57, 0x11, 0xDD, 0xD4, 0x7A, 0x6B, 0xBD, 0x45, 0xFC, 0xF2, + 0x24, 0x99, 0xE6, 0x41, 0x5B, 0x53, 0xB8, 0xDD, 0x33, 0xD9, 0x4E, 0x73, 0x31, 0xC2, 0xEB, 0x15, 0x2D, 0x1D, 0x69, 0x40, + 0xED, 0xF4, 0xE1, 0xD2, 0x62, 0x01, 0x10, 0x0D, 0x48, 0x41, 0x51, 0x7A, 0xE4, 0x95, 0x7F, 0x0B, 0x3F, 0xFA, 0x9A, 0xF1, + 0xE9, 0xCB, 0x72, 0xC2, 0x74, 0x85, 0xCC, 0x28, 0x3F, 0x5D, 0xBF, 0xF5, 0xEC, 0xEA, 0xD4, 0x18, 0x7E, 0x8C, 0x45, 0xBE, + 0x37, 0x63, 0x2A, 0x5C, 0xEE, 0x8C, 0x9B, 0xE4, 0x65, 0x03, 0x58, 0xFF, 0xBD, 0x5B, 0xCC, 0x58, 0xD8, 0x48, 0xE5, 0x06, + 0x37, 0x8E, 0xD2, 0x65, 0x00, 0xFD, 0x78, 0xEC, 0x11, 0xA6, 0xFB, 0xAA, 0x69, 0xC3, 0x83, 0xD4, 0x71, 0xE6, 0x3C, 0xF2, + 0x06, 0xF9, 0x77, 0xB0, 0xE3, 0xC2, 0x70, 0x2A, 0x56, 0xA4, 0x4A, 0xA9, 0x94, 0x65, 0x4A, 0x53, 0x09, 0x36, 0x57, 0xCD, + 0x23, 0x52, 0x20, 0x7B, 0xE8, 0x8C, 0x9A, 0x60, 0x3A, 0xE0, 0x31, 0xCF, 0xBF, 0x17, 0x00, 0x8F, 0x8A, 0xC2, 0x7C, 0x6F, + 0xFD, 0xFB, 0xFB, 0x6B, 0x59, 0x9E, 0x87, 0xD9, 0x5B, 0x4A, 0xD4, 0x98, 0x41, 0xA7, 0xC0, 0x1B, 0xEB, 0x4D, 0x9B, 0xDF, + 0xC1, 0xE0, 0x1F, 0x62, 0x6C, 0x1B, 0x0D, 0x04, 0xE0, 0xFF, 0xA4, 0x4A, 0x54, 0x92, 0xCF, 0x4E, 0x20, 0xBD, 0x12, 0xE2, + 0x1D, 0x10, 0x51, 0xD8, 0xC0, 0xED, 0x3D, 0x36, 0x63, 0x95, 0xB0, 0x99, 0x5F, 0xA4, 0x6D, 0xAA, 0x24, 0x32, 0x9D, 0x79, + 0x18, 0xBF, 0xF5, 0xB1, 0x69, 0x74, 0xEB, 0xE7, 0xF4, 0x5D, 0x65, 0x60, 0x21, 0x1E, 0x97, 0x7C, 0x06, 0xF2, 0xC6, 0x37, + 0xE3, 0xF5, 0xED, 0x88, 0x89, 0x26, 0x1B, 0x2A, 0x33, 0xD9, 0x18, 0x36, 0x3E, 0xBB, 0xE4, 0x90, 0x55, 0x4C, 0xF2, 0x62, + 0x0D, 0xE8, 0x56, 0x34, 0x37, 0xDA, 0x9E, 0xD7, 0x7B, 0x18, 0x6F, 0x70, 0xE7, 0x3A, 0x8B, 0x74, 0x55, 0xE7, 0xC9, 0x58, + 0xA7, 0x86, 0x85, 0x74, 0x19, 0xBB, 0x8D, 0xC7, 0x07, 0x79, 0xD5, 0xE2, 0xF0, 0x4D, 0x6C, 0x35, 0x22, 0xC6, 0xFE, 0x37, + 0xBB, 0x4C, 0x45, 0x23, 0xBB, 0x78, 0xA7, 0xF4, 0x54, 0x92, 0x74, 0x91, 0xC7, 0xFC, 0xFC, 0x89, 0x54, 0x60, 0x9A, 0x34, + 0x97, 0x9A, 0x25, 0x2A, 0x01, 0x3B, 0x4C, 0x9B, 0x2C, 0x49, 0x18, 0x6D, 0xB1, 0xB4, 0x86, 0x44, 0x90, 0xB7, 0x06, 0x45, + 0x80, 0x95, 0x18, 0x69, 0x51, 0xF4, 0xD9, 0x89, 0x5D, 0x39, 0x68, 0xCE, 0xDF, 0x99, 0x8D, 0x50, 0xCF, 0x2A, 0x75, 0x9A, + 0x7F, 0x04, 0x3F, 0x77, 0xE0, 0xF9, 0xDC, 0xFB, 0xAD, 0x20, 0xD8, 0x7F, 0xCD, 0x5F, 0x91, 0x35, 0x62, 0x11, 0xE2, 0xEA, + 0x41, 0xBC, 0xE3, 0x0A, 0x6A, 0x23, 0xAC, 0xAC, 0xDD, 0xFA, 0x4E, 0x7F, 0xD1, 0x42, 0x2E, 0x3B, 0xAC, 0xA6, 0xA7, 0x85, + 0x69, 0x67, 0x86, 0x38, 0x27, 0xB3, 0x9C, 0x23, 0xBB, 0xD1, 0x77, 0x4B, 0xC5, 0x21, 0xE7, 0xD4, 0xBB, 0x9C, 0xA7, 0xEA, + 0x9D, 0xDE, 0x6D, 0x27, 0xE7, 0x9B, 0xAE, 0xB9, 0xD4, 0xB0, 0x27, 0x04, 0xDC, 0x49, 0x48, 0xDB, 0xFF, 0xFF, 0x3E, 0xAD, + 0x68, 0x0D, 0xFD, 0xC6, 0xB1, 0x26, 0x47, 0x52, 0x64, 0x95, 0x17, 0xFF, 0xAB, 0x0E, 0xF3, 0xE0, 0x20, 0xF0, 0xE8, 0x96, + 0xC5, 0x4E, 0x18, 0x34, 0x1D, 0x10, 0xE0, 0x74, 0x49, 0x23, 0xFE, 0x72, 0xB6, 0x61, 0x22, 0xEF, 0x96, 0x98, 0x40, 0x1E, + 0xFA, 0xD9, 0x2E, 0xBE, 0x25, 0xC4, 0x77, 0x17, 0xE2, 0x26, 0xB1, 0x24, 0xBB, 0x2C, 0xBA, 0x91, 0x1D, 0x60, 0x01, 0x28, + 0x24, 0x97, 0xC7, 0x52, 0x26, 0xAB, 0x7F, 0x75, 0xB3, 0xF5, 0x12, 0x84, 0xB5, 0xD1, 0x82, 0x7A, 0xB9, 0x00, 0x70, 0xAF, + 0xEA, 0x6D, 0xDE, 0x36, 0xE4, 0xD8, 0xDF, 0x5C, 0xCE, 0xC8, 0x14, 0xE4, 0xA4, 0x98, 0xE5, 0x23, 0x75, 0x63, 0x3E, 0xAD, + 0x84, 0x6B, 0x83, 0x5A, 0xAC, 0x04, 0x8B, 0x64, 0x71, 0xCB, 0x5F, 0x33, 0xA7, 0xAC, 0x6A, 0xB7, 0x53, 0x8A, 0xBE, 0x9E, + 0x22, 0x91, 0x75, 0xEB, 0xD0, 0xF5, 0xD1, 0xFB, 0x84, 0x05, 0xE2, 0x12, 0xBF, 0x25, 0xFE, 0x5B, 0x62, 0xCE, 0xEA, 0xA8, + 0x5A, 0xCA, 0x32, 0xEB, 0x63, 0x67, 0xB0, 0xEF, 0x1C, 0x8D, 0x19, 0x78, 0x0D, 0xE2, 0x36, 0xAE, 0x05, 0x63, 0x93, 0xFA, + 0xEA, 0x6F, 0xD5, 0xAD, 0x3B, 0x6B, 0x13, 0x5A, 0xEA, 0xCC, 0x95, 0x69, 0x31, 0x22, 0x6D, 0x25, 0x60, 0xBA, 0x03, 0x58, + 0xBB, 0x3B, 0x4B, 0x21, 0xA2, 0x68, 0x1B, 0x1C, 0xC7, 0x2A, 0x3A, 0x4C, 0xE3, 0x44, 0xBA, 0x7D, 0xBB, 0x8D, 0xAB, 0x52, + 0x78, 0xF9, 0x8C, 0x8E, 0x5E, 0x91, 0x32, 0x5F, 0x2F, 0x0B, 0x6A, 0x2E, 0x79, 0x99, 0x0C, 0xFC, 0x17, 0x1C, 0x03, 0x76, + 0x5D, 0x36, 0x71, 0xBA, 0x0E, 0xAA, 0xFB, 0x7D, 0x6A, 0x81, 0x06, 0x57, 0xA8, 0xBB, 0xE1, 0x5D, 0xFF, 0x2C, 0x1B, 0x51, + 0xE8, 0x2F, 0x0B, 0x3C, 0x66, 0x4A, 0xF7, 0x06, 0x55, 0x12, 0xBF, 0x3D, 0x83, 0xE4, 0xE7, 0x73, 0x16, 0x51, 0x9F, 0xC8, + 0xD9, 0x78, 0xEF, 0x24, 0x62, 0x18, 0x05, 0x57, 0xF4, 0xFD, 0xB3, 0xA1, 0x1F, 0xBE, 0xF7, 0xB3, 0x90, 0x5D, 0x24, 0x5E, + 0xE2, 0x5C, 0x0C, 0x44, 0x14, 0xD0, 0xB2, 0x51, 0xD7, 0x12, 0x45, 0xE4, 0x50, 0x3F, 0x7D, 0xC3, 0x5F, 0x5C, 0xC7, 0xBB, + 0x1B, 0x16, 0xD8, 0xEF, 0xCB, 0x40, 0x6A, 0xEF, 0x67, 0x39, 0x60, 0x73, 0x40, 0x55, 0x0E, 0x46, 0x75, 0xFE, 0x1E, 0x4E, + 0x5E, 0x56, 0xA2, 0x01, 0x31, 0x4D, 0x34, 0xFE, 0x07, 0x59, 0xAA, 0xC9, 0x74, 0x8E, 0x0A, 0xAF, 0x00, 0x67, 0xF4, 0x2E, + 0x9F, 0x38, 0x54, 0xF4, 0x1C, 0x35, 0xCD, 0x70, 0x1E, 0x35, 0x85, 0x87, 0x03, 0x12, 0x7A, 0x41, 0x85, 0x72, 0xAA, 0xA6, + 0x20, 0x36, 0x8B, 0x18, 0x96, 0xCD, 0x17, 0x5C, 0xDF, 0x55, 0xB2, 0xA6, 0xA4, 0x48, 0xE2, 0xC1, 0xE7, 0x51, 0x71, 0x86, + 0x9F, 0xD1, 0x78, 0x24, 0x0C, 0xB5, 0x07, 0xFF, 0x3D, 0x7A, 0xB5, 0x5A, 0x6E, 0xE2, 0xC4, 0x0B, 0x93, 0x1C, 0x59, 0xEB, + 0x1F, 0x9A, 0x3A, 0xE3, 0x9A, 0x94, 0xDE, 0x61, 0xD3, 0x55, 0xCA, 0x4F, 0xFD, 0xF4, 0xD2, 0xB9, 0x57, 0xB5, 0x9B, 0xBF, + 0x4D, 0x35, 0x77, 0x2B, 0x3C, 0x45, 0x07, 0x5D, 0xC1, 0xDB, 0xF0, 0x6A, 0xDB, 0x5A, 0x03, 0xAC, 0x18, 0xBA, 0x27, 0xD2, + 0x68, 0x56, 0xCD, 0xA3, 0x12, 0x1F, 0x86, 0xDF, 0xD1, 0xB1, 0x2A, 0xB7, 0xA4, 0xB7, 0x06, 0x65, 0xC9, 0x5A, 0x43, 0x9F, + 0x1E, 0xDA, 0x8E, 0x5C, 0x5A, 0xA2, 0xEE, 0x56, 0x3A, 0x37, 0x26, 0x9A, 0x9C, 0xA2, 0xE4, 0x6F, 0x43, 0x82, 0x46, 0x4D, + 0xE0, 0x65, 0xE7, 0x27, 0x4B, 0xB7, 0xF4, 0x08, 0x4B, 0xDE, 0x46, 0x2D, 0xEB, 0x12, 0x71, 0xD0, 0x26, 0xA9, 0x95, 0x27, + 0xC7, 0x90, 0x06, 0xF2, 0x0E, 0xE0, 0xE5, 0x6E, 0xCB, 0xA0, 0x3A, 0x00, 0xB7, 0x2D, 0x22, 0xF6, 0x15, 0x01, 0x30, 0xA0, + 0x90, 0x4F, 0x8E, 0x0B, 0x3C, 0x51, 0xB8, 0xE2, 0x24, 0x20, 0x24, 0x27, 0xB4, 0x20, 0x00, 0x59, 0xC4, 0xCC, 0xC6, 0x30, + 0xB4, 0x62, 0x73, 0x73, 0x04, 0x94, 0x2D, 0xF4, 0x99, 0x0F, 0xF1, 0xFA, 0x7E, 0xCE, 0xA7, 0x45, 0xB4, 0xFF, 0xFC, 0xE0, + 0x01, 0x08, 0x81, 0xE4, 0x11, 0x2E, 0x80, 0x71, 0x64, 0xBE, 0x9E, 0xC4, 0x59, 0xA2, 0x18, 0xC0, 0x24, 0x54, 0xD8, 0xB8, + 0xBA, 0xA9, 0xB0, 0xF2, 0x09, 0xCC, 0x8F, 0x5B, 0xBD, 0xA0, 0x0A, 0x52, 0x06, 0x37, 0x28, 0xD7, 0x82, 0xE5, 0xA7, 0x72, + 0x63, 0x87, 0x5C, 0x86, 0x5F, 0xEA, 0x19, 0x67, 0x7B, 0xE8, 0x1E, 0xC5, 0xB0, 0x2E, 0xF5, 0x9E, 0xCE, 0x87, 0xCB, 0xD7, + 0x02, 0x49, 0x33, 0xDE, 0xFB, 0xC5, 0xB6, 0x5B, 0xE0, 0x73, 0xE1, 0xFE, 0xC1, 0xEE, 0x7E, 0x16, 0xA1, 0xA6, 0x15, 0xBB, + 0x3A, 0x27, 0xF0, 0x0D, 0x1A, 0xE1, 0x1A, 0x48, 0xB8, 0xCB, 0xEB, 0x34, 0xB9, 0x69, 0x86, 0x69, 0x33, 0x7F, 0x0A, 0x6C, + 0x7F, 0x8D, 0x97, 0xBE, 0x16, 0xF0, 0xE8, 0x20, 0xB6, 0x8D, 0x87, 0x2F, 0xA2, 0x55, 0x27, 0x3F, 0x3D, 0x05, 0x84, 0x8A, + 0x51, 0x37, 0xA4, 0xDC, 0x58, 0x67, 0x55, 0xB6, 0x64, 0xD8, 0x6B, 0x7E, 0x60, 0xE9, 0x8C, 0x53, 0x3E, 0x74, 0x2B, 0xCF, + 0xFA, 0x4A, 0xA2, 0x5D, 0xF5, 0x07, 0x3D, 0xB4, 0xF7, 0xC6, 0x02, 0x08, 0xCC, 0xCF, 0xAC, 0x42, 0x5E, 0x48, 0x0C, 0xDE, + 0x45, 0xF6, 0x95, 0xDA, 0x78, 0x59, 0xBA, 0x1B, 0xE9, 0xC0, 0x08, 0x1C, 0x7E, 0x2D, 0xA2, 0x76, 0x88, 0xCC, 0x1E, 0xA3, + 0x9E, 0x23, 0x76, 0x89, 0xFD, 0x9A, 0x3A, 0x42, 0x5C, 0xEA, 0xAB, 0xDF, 0xFE, 0x30, 0xD1, 0xA0, 0x62, 0xC3, 0x1B, 0xDB, + 0x93, 0xC0, 0xC3, 0x8E, 0xEB, 0xEF, 0x7D, 0x0C, 0x81, 0x36, 0xA4, 0x75, 0xB0, 0x3D, 0x8D, 0xE0, 0xC5, 0xAD, 0x24, 0x4E, + 0xA0, 0x3D, 0x0C, 0x61, 0x86, 0x83, 0x28, 0xA6, 0x15, 0x1E, 0x8B, 0x13, 0xF8, 0x2C, 0xFB, 0xD0, 0x82, 0x9D, 0x73, 0xF0, + 0xC6, 0x1B, 0xF7, 0x81, 0xB2, 0xFB, 0x1D, 0xC1, 0x10, 0xD1, 0xD3, 0xC6, 0x0B, 0xE9, 0x95, 0xE3, 0x25, 0x35, 0x0D, 0xE5, + 0xD7, 0xF7, 0x90, 0x37, 0xBE, 0xEA, 0x02, 0x29, 0xD1, 0x5C, 0x1A, 0x77, 0xC7, 0x12, 0x44, 0xB4, 0x54, 0x60, 0x0E, 0x82, + 0x42, 0xCF, 0x58, 0x99, 0xBC, 0x85, 0xA9, 0xEF, 0x21, 0xD7, 0x94, 0xA9, 0x16, 0xC7, 0x36, 0xE8, 0xC4, 0x51, 0x2E, 0xD6, + 0x6F, 0xCB, 0x65, 0x30, 0xC0, 0x1D, 0x9B, 0xC0, 0xD5, 0x96, 0xB4, 0x85, 0x15, 0x7B, 0x4E, 0x74, 0xC2, 0xFC, 0xCB, 0x57, + 0xE5, 0xE9, 0xB3, 0x35, 0xB3, 0x32, 0x82, 0x80, 0xA4, 0x43, 0x9D, 0xE9, 0xC5, 0xFA, 0x5E, 0xAE, 0xC5, 0x12, 0x66, 0xEF, + 0xC1, 0xFA, 0x81, 0xDF, 0x9F, 0x67, 0x12, 0xCC, 0x8F, 0x9D, 0x82, 0x05, 0x09, 0x34, 0x77, 0x80, 0x06, 0xE9, 0x56, 0xD8, + 0xD2, 0xD7, 0xC6, 0xA3, 0xBD, 0x36, 0x65, 0x74, 0x45, 0x59, 0xBC, 0xC3, 0x83, 0x9A, 0xCC, 0x2F, 0xEE, 0x92, 0x8F, 0x54, + 0xD8, 0x51, 0xFA, 0xAB, 0xA5, 0x34, 0x6F, 0xFB, 0xE1, 0xF9, 0x07, 0x55, 0x6E, 0xD6, 0x81, 0x1E, 0x96, 0xF4, 0xCA, 0x51, + 0xC5, 0xAF, 0xF4, 0x12, 0x38, 0xE7, 0x0E, 0xF8, 0x87, 0xD3, 0x1A, 0x7C, 0x63, 0xF4, 0x3F, 0x2A, 0xB1, 0x6C, 0xE6, 0xC7, + 0x5C, 0xC2, 0xD9, 0x18, 0xAF, 0x22, 0xA1, 0x39, 0xFD, 0x29, 0x5D, 0x59, 0xAE, 0x31, 0xC6, 0x4B, 0x89, 0x98, 0x6F, 0xEA, + 0xB2, 0x63, 0xF1, 0x9D, 0x5D, 0xBC, 0xAF, 0x5F, 0xDE, 0xDD, 0x78, 0x2C, 0x3B, 0x32, 0xC4, 0x2B, 0xE7, 0x00, 0x61, 0x8D, + 0x94, 0xF0, 0x04, 0x84, 0x5C, 0xEC, 0xCB, 0xE2, 0xB5, 0x4E, 0xE7, 0xA4, 0x2E, 0xD2, 0x6B, 0xA0, 0x6F, 0xFC, 0x7A, 0x11, + 0x59, 0x64, 0x20, 0x38, 0x35, 0x4D, 0x10, 0x39, 0x47, 0xA2, 0x23, 0x6E, 0x57, 0x91, 0x61, 0x1F, 0xED, 0x0F, 0xE3, 0x09, + 0x91, 0x03, 0xFD, 0xA5, 0xCA, 0xB8, 0xBE, 0x5A, 0x09, 0xFE, 0x31, 0xA3, 0xEE, 0x13, 0xB6, 0x9A, 0x6A, 0xBE, 0x06, 0xCE, + 0xF2, 0xB4, 0x08, 0x7B, 0x24, 0x3F, 0xDE, 0xB4, 0xEB, 0xE5, 0x3B, 0x60, 0xCE, 0xB5, 0x70, 0x89, 0xE3, 0x40, 0x45, 0x97, + 0xD6, 0xE9, 0xD6, 0xA4, 0xA2, 0x85, 0xE1, 0x26, 0xF4, 0x35, 0x60, 0xA0, 0x0F, 0x43, 0xE0, 0x8B, 0x30, 0xEA, 0x39, 0x71, + 0xB7, 0x44, 0xE6, 0x7C, 0x03, 0xDB, 0x53, 0xE3, 0x42, 0xDF, 0x83, 0xD6, 0x39, 0x02, 0x31, 0x3A, 0x85, 0xEE, 0x33, 0x7F, + 0xEB, 0xE8, 0xD1, 0x15, 0x60, 0x06, 0x48, 0x86, 0x57, 0xEA, 0x62, 0xBB, 0xBA, 0x83, 0x63, 0xF6, 0x23, 0x60, 0xD2, 0xA9, + 0x8F, 0x0A, 0x3F, 0x53, 0xC5, 0xFD, 0xD5, 0x18, 0x7E, 0x4B, 0x8F, 0x7B, 0x17, 0xD6, 0x43, 0x6B, 0xEC, 0xC9, 0xCA, 0x03, + 0x73, 0x2B, 0x07, 0xEB, 0x08, 0x9A, 0x3F, 0x4A, 0x96, 0xF5, 0xDD, 0x3F, 0xCB, 0x68, 0xC3, 0x16, 0xF2, 0xBF, 0x8B, 0x55, + 0x5A, 0x86, 0x27, 0x66, 0x47, 0xB6, 0xE3, 0x5F, 0x0B, 0x6B, 0x1C, 0x11, 0x24, 0x1A, 0x72, 0x3B, 0x3A, 0x03, 0xC3, 0xBA, + 0x1C, 0x55, 0x74, 0x88, 0xCE, 0xE8, 0x80, 0xDF, 0xB1, 0x08, 0x4F, 0x5A, 0xC5, 0x4C, 0xAA, 0x1C, 0xD4, 0xA6, 0xDA, 0x5C, + 0xFE, 0x0F, 0xA4, 0x7A, 0xBA, 0xEE, 0xF7, 0x3A, 0xB2, 0x01, 0x39, 0x3F, 0x71, 0x67, 0xCC, 0x6E, 0xA1, 0x41, 0x43, 0x9D, + 0x20, 0xDF, 0x2B, 0x47, 0xEE, 0x02, 0xCA, 0xBF, 0x9D, 0x94, 0x9B, 0x41, 0x6A, 0x90, 0xAD, 0x8E, 0x57, 0x2E, 0xA8, 0x12, + 0x22, 0x1A, 0x44, 0xF1, 0xF3, 0x3C, 0xEF, 0xA8, 0xC5, 0xAF, 0x5A, 0x54, 0x8F, 0xDF, 0x6C, 0x27, 0xE1, 0x0A, 0x4C, 0xE1, + 0xF0, 0x3C, 0x5D, 0xD6, 0x17, 0x52, 0x0A, 0xC6, 0x9A, 0xB0, 0x42, 0xE7, 0xE0, 0x5D, 0xBD, 0x75, 0xE8, 0x43, 0x4C, 0x83, + 0x45, 0xA3, 0x84, 0x56, 0xC8, 0xDD, 0x79, 0x15, 0xCF, 0x81, 0x9B, 0xF7, 0x4A, 0xEE, 0xA3, 0xB8, 0xD2, 0xEB, 0xC7, 0x47, + 0x99, 0xB2, 0x3C, 0xC2, 0x32, 0xE9, 0xD4, 0xCD, 0x20, 0x90, 0x41, 0xD1, 0xC3, 0xAB, 0xA2, 0x17, 0xFE, 0x35, 0x16, 0xD1, + 0x80, 0x13, 0x9A, 0x39, 0xA2, 0x6E, 0xE3, 0xC0, 0x42, 0xEA, 0xAE, 0x07, 0xFF, 0x34, 0xBD, 0x43, 0x80, 0xA6, 0xD6, 0x75, + 0x7A, 0x87, 0x6B, 0xC9, 0xCC, 0x89, 0xAB, 0xE3, 0x13, 0xF5, 0x6D, 0xBC, 0x02, 0xE8, 0xAE, 0x2C, 0xF1, 0xAC, 0xE6, 0x41, + 0x7D, 0xC8, 0xA3, 0xF3, 0x12, 0xF4, 0xB9, 0xA5, 0xD7, 0xC5, 0x52, 0x76, 0xBB, 0x35, 0xAE, 0x99, 0x3B, 0x17, 0x56, 0xD9, + 0xA0, 0x75, 0x71, 0xE2, 0x1B, 0x86, 0x2D, 0x3C, 0xE5, 0x1A, 0x47, 0xBC, 0xBC, 0x35, 0x31, 0x87, 0x1D, 0x3B, 0xD6, 0x77, + 0x51, 0x29, 0x7C, 0x09, 0x87, 0xA6, 0xBF, 0x85, 0xCC, 0xA7, 0x8F, 0x25, 0x25, 0x47, 0x6F, 0x2E, 0x69, 0x5B, 0xD5, 0x86, + 0x8D, 0x79, 0xDB, 0xE7, 0xE7, 0x45, 0x81, 0x91, 0x74, 0x86, 0x82, 0x4D, 0x24, 0x96, 0xA5, 0x31, 0xA9, 0xE7, 0xC6, 0x1B, + 0xEE, 0xD1, 0xA4, 0x1F, 0xF6, 0x3D, 0x36, 0xA7, 0x68, 0xFD, 0x26, 0xD5, 0x1F, 0x99, 0xCE, 0x10, 0xBB, 0x31, 0x61, 0xC0, + 0x84, 0xA6, 0xC3, 0x4B, 0xAF, 0x64, 0x22, 0x49, 0xE1, 0xF2, 0x05, 0x5E, 0x01, 0x3A, 0xA9, 0xEA, 0x5B, 0xA1, 0x2F, 0x79, + 0xF9, 0x10, 0xDC, 0x6D, 0x73, 0x8E, 0xE7, 0x62, 0xF9, 0x12, 0xDF, 0x83, 0xDF, 0xF2, 0x40, 0xB1, 0xB6, 0x8F, 0x43, 0xC6, + 0x50, 0x2D, 0x38, 0x2F, 0x77, 0x06, 0x4F, 0x58, 0x62, 0x3F, 0x50, 0x35, 0xA6, 0xC3, 0x50, 0x32, 0x88, 0x1C, 0xA8, 0x40, + 0x76, 0x6D, 0x47, 0xCB, 0x6E, 0x3A, 0x1B, 0x81, 0x50, 0x6B, 0xF8, 0x5E, 0x33, 0xB2, 0xEB, 0x37, 0x41, 0x93, 0x21, 0xCA, + 0x9C, 0x59, 0x28, 0x13, 0xA1, 0x58, 0x04, 0x59, 0x68, 0xFF, 0xC1, 0x17, 0xF6, 0x5B, 0x0F, 0xB3, 0xAE, 0xC8, 0x00, 0xE2, + 0x18, 0xC6, 0x61, 0xC2, 0x65, 0x91, 0xC4, 0x00, 0xB9, 0xDF, 0xAE, 0x84, 0x52, 0xE2, 0xF6, 0x8D, 0x34, 0x07, 0x9A, 0x53, + 0x1B, 0xCB, 0xC0, 0x89, 0x63, 0x1A, 0xEB, 0x14, 0xE8, 0xA8, 0xED, 0x0C, 0x79, 0xC4, 0x81, 0x18, 0x35, 0xAB, 0xF9, 0x05, + 0x35, 0xD6, 0x47, 0x1A, 0xD2, 0xA4, 0xD1, 0xAC, 0x05, 0x84, 0xC9, 0x56, 0x1A, 0xAF, 0xC6, 0x42, 0x66, 0x38, 0x1C, 0x98, + 0xC5, 0xAA, 0x94, 0xF7, 0x2D, 0xCA, 0xF8, 0x09, 0x28, 0xEA, 0x8A, 0xCA, 0x2B, 0x65, 0x88, 0xC5, 0xE5, 0x84, 0xF5, 0x7A, + 0x0B, 0xC1, 0xF0, 0x36, 0x21, 0x06, 0x91, 0xF7, 0xEC, 0xC2, 0xE0, 0x85, 0x65, 0xAB, 0xFE, 0x02, 0xFB, 0x6F, 0x3D, 0xFB, + 0x3D, 0x55, 0xBE, 0xCB, 0xEB, 0xCC, 0xD5, 0x63, 0xDF, 0x83, 0xE3, 0xF3, 0x63, 0xC6, 0x0B, 0x6D, 0xFF, 0x0C, 0x20, 0xD3, + 0xC8, 0x86, 0x25, 0xB5, 0x7C, 0xE2, 0x67, 0xA8, 0x3D, 0x2E, 0x63, 0xCA, 0x65, 0xB1, 0xC9, 0xCF, 0xB9, 0x61, 0x90, 0x6E, + 0xE9, 0x80, 0x0A, 0xFA, 0x53, 0x82, 0x6B, 0x1E, 0xA6, 0xE3, 0x44, 0x07, 0x39, 0x62, 0x6A, 0x8E, 0xC0, 0x1C, 0x33, 0x57, + 0xDE, 0xC3, 0xDD, 0x2B, 0x11, 0x28, 0x2B, 0x56, 0x25, 0x8A, 0xCC, 0xE0, 0x3F, 0xB8, 0x0B, 0xFB, 0xD7, 0x02, 0x79, 0xDB, + 0xE6, 0x81, 0xDF, 0x19, 0xEB, 0x62, 0x85, 0x79, 0x3E, 0x6C, 0x60, 0xCC, 0xA6, 0x77, 0x3A, 0x72, 0x95, 0x4F, 0x49, 0x5D, + 0x57, 0x95, 0xD2, 0x8F, 0x81, 0x56, 0xD3, 0x7A, 0x65, 0xD3, 0x0C, 0xE4, 0x57, 0x16, 0x43, 0x75, 0xBB, 0x4C, 0xAD, 0xA9, + 0x4D, 0x55, 0x07, 0x07, 0xCA, 0x99, 0xFF, 0xBE, 0x88, 0x1D, 0x8D, 0x59, 0xF4, 0x9F, 0xA4, 0x67, 0xB8, 0x26, 0x69, 0x73, + 0xA3, 0x70, 0x6D, 0xE2, 0x76, 0xBF, 0xDE, 0x73, 0xBD, 0xC8, 0x2F, 0x82, 0xBD, 0x32, 0x04, 0x86, 0x2D, 0x1F, 0xB2, 0x2B, + 0x76, 0xEF, 0x17, 0xC6, 0xDB, 0x2B, 0x8F, 0x1D, 0x49, 0xF6, 0x77, 0xB0, 0xD8, 0x19, 0x8F, 0x2B, 0x34, 0x6E, 0x43, 0xCF, + 0x98, 0x58, 0x3C, 0x76, 0x72, 0x8E, 0xE1, 0x21, 0x24, 0x92, 0x82, 0x3E, 0x66, 0x2D, 0xA1, 0x70, 0x47, 0x09, 0x2C, 0xD2, + 0x4D, 0xE9, 0xA9, 0x56, 0xA9, 0x1D, 0x8E, 0x53, 0xEC, 0x7B, 0xAE, 0xD7, 0x68, 0x7A, 0xEA, 0x1B, 0x49, 0xCC, 0x1C, 0x0E, + 0x26, 0xD5, 0x9E, 0x7E, 0x72, 0xC9, 0xD1, 0xCC, 0xDB, 0xC8, 0x88, 0x9A, 0xF1, 0x7E, 0x14, 0x72, 0xC3, 0xD6, 0xB8, 0xFC, + 0xC6, 0x64, 0xED, 0x1A, 0x80, 0x29, 0x28, 0x4C, 0x5C, 0x0B, 0x27, 0x8B, 0xAC, 0x9A, 0x67, 0xFA, 0x6D, 0xB7, 0x8F, 0x44, + 0x90, 0x87, 0xB1, 0xEF, 0x37, 0x57, 0x4F, 0x2C, 0x8A, 0x80, 0x7B, 0x65, 0x3E, 0xB6, 0x66, 0xE7, 0x48, 0x7A, 0xE5, 0x56, + 0xC5, 0xB9, 0x62, 0x48, 0x2B, 0x06, 0x4E, 0xC7, 0x1A, 0x37, 0x26, 0x79, 0x0C, 0x71, 0xF7, 0x06, 0x7E, 0xBE, 0x24, 0xDF, + 0x83, 0x92, 0xD4, 0x6E, 0xD3, 0x12, 0x40, 0xCF, 0x07, 0xD0, 0x3C, 0x8C, 0xDC, 0x98, 0x1F, 0xB4, 0x6F, 0xFC, 0xBA, 0xF2, + 0x55, 0xFA, 0xE0, 0x78, 0xC0, 0x9F, 0xAF, 0xF0, 0x7C, 0xFD, 0x7F, 0xCE, 0xEB, 0x99, 0x4B, 0xFB, 0xDC, 0x08, 0x80, 0x88, + 0x8B, 0xBC, 0x40, 0x1D, 0xDB, 0xFF, 0x59, 0x8A, 0xE5, 0xAF, 0xE6, 0x59, 0x50, 0xDF, 0x22, 0x11, 0x2E, 0xBF, 0x3B, 0x4A, + 0x85, 0x9C, 0x58, 0x21, 0xA0, 0xFE, 0xC4, 0x04, 0xE6, 0xDC, 0x66, 0xA6, 0x9D, 0xA7, 0x8E, 0x41, 0xBA, 0x88, 0x96, 0x09, + 0x65, 0xAD, 0x2D, 0x76, 0x97, 0x84, 0x2F, 0xC3, 0xAA, 0x81, 0x2C, 0x7A, 0x39, 0x93, 0x37, 0x2C, 0xAF, 0xDC, 0x25, 0x87, + 0x81, 0x29, 0x23, 0xC2, 0x0B, 0xE8, 0xA4, 0x04, 0xE0, 0xCC, 0x5A, 0x44, 0x21, 0x4C, 0x7F, 0xA6, 0xCF, 0xB9, 0xEF, 0xA7, + 0x80, 0x04, 0x10, 0x19, 0x34, 0xC9, 0xF7, 0xB6, 0x30, 0xF5, 0x91, 0xC8, 0xB6, 0xB4, 0xDC, 0x35, 0x1A, 0x05, 0xCE, 0xD5, + 0xB8, 0x46, 0xE9, 0x48, 0xB1, 0x24, 0x6E, 0xE5, 0xC6, 0xD6, 0x59, 0x74, 0xA9, 0x3E, 0x05, 0xE1, 0xBC, 0x30, 0xB1, 0x23, + 0x68, 0x4E, 0x36, 0xF5, 0xD3, 0xC7, 0xC9, 0xF5, 0xAA, 0xE2, 0x62, 0xC4, 0xF1, 0xC8, 0xBD, 0x38, 0x84, 0xF7, 0x43, 0x72, + 0x95, 0xAE, 0x70, 0x2C, 0x80, 0x8B, 0x8B, 0x28, 0x79, 0xFC, 0x53, 0x0D, 0xDC, 0x65, 0x29, 0xFE, 0xF9, 0xD6, 0x64, 0xA3, + 0x22, 0xDF, 0x36, 0x7E, 0xDA, 0xBD, 0x39, 0xB5, 0x7F, 0xF7, 0x82, 0xCD, 0xDA, 0xD7, 0xF0, 0x3A, 0xA6, 0xBC, 0x7F, 0xAD, + 0x24, 0x4A, 0xCF, 0x47, 0x87, 0x15, 0xD2, 0x8E, 0x3C, 0x94, 0x9B, 0xCA, 0x2D, 0xE4, 0x79, 0x22, 0x17, 0xC0, 0x22, 0x56, + 0xEE, 0x87, 0x69, 0x36, 0xCF, 0xB3, 0x92, 0x81, 0x95, 0x0E, 0x82, 0xE8, 0x34, 0x7A, 0x4D, 0xDC, 0x70, 0x10, 0x88, 0x26, + 0xBC, 0x2B, 0xEE, 0xFC, 0x78, 0xD2, 0x61, 0xCD, 0x2F, 0xC2, 0xC3, 0xAB, 0xAA, 0x4E, 0x6C, 0x33, 0x47, 0x35, 0x8A, 0x3D, + 0xCC, 0xC4, 0xC5, 0x50, 0x31, 0x9F, 0x8B, 0xA1, 0x33, 0xA2, 0x9B, 0x54, 0x38, 0x34, 0x9B, 0x24, 0xB9, 0x0E, 0x48, 0x6C, + 0xFD, 0x6B, 0xFE, 0x88, 0xDD, 0xDF, 0xFC, 0xB6, 0x43, 0x30, 0xA6, 0x12, 0x70, 0x95, 0x38, 0x01, 0xA5, 0x13, 0x32, 0x30, + 0x41, 0x51, 0xDA, 0x76, 0xE8, 0xCC, 0x2F, 0xB8, 0x85, 0xE4, 0xBB, 0xAA, 0xA1, 0xDA, 0xDE, 0x9E, 0xDF, 0x88, 0x93, 0xED, + 0x4F, 0xAF, 0x63, 0x8B, 0xDE, 0x97, 0x3E, 0x6F, 0x4B, 0xDD, 0x72, 0xE3, 0xCB, 0xE2, 0xA2, 0x6F, 0x48, 0x92, 0xC2, 0xB1, + 0x62, 0x5D, 0x38, 0xB1, 0x76, 0x65, 0xBB, 0x3C, 0x24, 0x56, 0x9B, 0x22, 0x34, 0x17, 0x32, 0x92, 0xC1, 0xA9, 0x14, 0x60, + 0x03, 0x8B, 0x72, 0x8C, 0xE9, 0x4D, 0x84, 0xD0, 0xB6, 0x67, 0xA3, 0x8B, 0x0B, 0x58, 0x1C, 0x70, 0x02, 0xCA, 0xCC, 0x1B, + 0x86, 0x7A, 0x2E, 0x41, 0xC1, 0x17, 0x43, 0x83, 0x8A, 0x5B, 0x8F, 0x6A, 0x9A, 0x95, 0x2D, 0x66, 0x31, 0x18, 0x5D, 0x24, + 0xC7, 0x91, 0x4B, 0x93, 0x18, 0x8C, 0x1D, 0x0C, 0xDE, 0xDA, 0x7D, 0x0C, 0x43, 0xE2, 0xBE, 0x73, 0xC9, 0x7A, 0xF6, 0x97, + 0x4C, 0x43, 0xC6, 0x32, 0x83, 0xD5, 0xA2, 0x70, 0xEB, 0xD4, 0x4A, 0x62, 0x95, 0x34, 0xA6, 0x28, 0xCE, 0xF4, 0x1C, 0x4C, + 0xA8, 0x26, 0xB8, 0xD5, 0x8B, 0x6A, 0xC8, 0x28, 0x1C, 0xD7, 0xA6, 0xCF, 0xC9, 0x4A, 0xE1, 0xFC, 0x1A, 0x71, 0x6D, 0x98, + 0xA8, 0x6B, 0x4B, 0x72, 0x2C, 0xE6, 0x94, 0x59, 0xE1, 0x14, 0x62, 0xBF, 0xB9, 0x2E, 0x60, 0x94, 0x3F, 0xC7, 0x98, 0xF1, + 0x1B, 0x97, 0x54, 0x18, 0xF5, 0xED, 0x55, 0xAB, 0x74, 0xA3, 0x48, 0xAA, 0xD0, 0x5F, 0xD6, 0xAF, 0x78, 0xBC, 0x25, 0x7C, + 0x06, 0x6A, 0x5A, 0x01, 0x73, 0x3C, 0xEC, 0x34, 0x22, 0x65, 0x97, 0xFA, 0xD1, 0x1D, 0x97, 0x9C, 0x18, 0x53, 0x68, 0x2A, + 0x2C, 0x76, 0x10, 0x38, 0x4A, 0xB0, 0x34, 0x2E, 0x95, 0xB2, 0x67, 0x3E, 0x39, 0x57, 0x68, 0x49, 0xFD, 0x45, 0x5D, 0xF1, + 0x70, 0x1B, 0x0C, 0x79, 0xCE, 0x2B, 0x86, 0xD3, 0xAC, 0xD0, 0xD6, 0x22, 0x3F, 0x66, 0xF7, 0x12, 0x72, 0x8E, 0xC9, 0x56, + 0x51, 0x5D, 0x94, 0x41, 0x7F, 0x67, 0xC6, 0xA9, 0x3E, 0x57, 0x86, 0xFA, 0xD7, 0xFD, 0x81, 0xED, 0xFD, 0xAD, 0x4F, 0x11, + 0x41, 0xD4, 0x31, 0x55, 0x3F, 0x34, 0xE9, 0x12, 0x12, 0x2E, 0x10, 0x48, 0x93, 0x7B, 0x6A, 0xC0, 0x1D, 0x6E, 0xB8, 0xC4, + 0x07, 0x4C, 0xF8, 0x85, 0xC4, 0xD4, 0xA6, 0x39, 0xB1, 0xA2, 0x10, 0xD5, 0xD4, 0xC9, 0xDC, 0x42, 0x8A, 0x47, 0xD0, 0xB2, + 0x05, 0xC8, 0xEB, 0x30, 0xE0, 0xB5, 0x1E, 0x10, 0xB0, 0x4E, 0xFD, 0x9E, 0x73, 0xA8, 0x69, 0xA1, 0xB5, 0xB4, 0xB1, 0x5A, + 0x35, 0xBD, 0x33, 0x81, 0xC0, 0x2F, 0xCF, 0xD6, 0x34, 0xC6, 0x6B, 0xB5, 0x81, 0x7D, 0x51, 0xA8, 0x91, 0x4E, 0x0E, 0x4E, + 0xC1, 0x2E, 0x87, 0xC3, 0xE4, 0xF4, 0x72, 0x3B, 0xAD, 0x77, 0x3A, 0x02, 0x9C, 0x2F, 0x63, 0xB8, 0x4C, 0x67, 0x00, 0xDD, + 0xB0, 0x43, 0xFF, 0x78, 0xF2, 0xEC, 0x3D, 0x55, 0xA0, 0x95, 0xD2, 0xB0, 0x6F, 0x1F, 0x12, 0xB4, 0xA4, 0x35, 0x1D, 0x36, + 0x8A, 0x69, 0x33, 0x10, 0xE8, 0x1E, 0x10, 0xDA, 0x50, 0xAA, 0x85, 0x23, 0x37, 0x6F, 0x13, 0xF3, 0x4F, 0x77, 0x95, 0x6A, + 0x55, 0x21, 0x44, 0x71, 0x70, 0xD7, 0x80, 0x61, 0xEE, 0x2B, 0x3C, 0xB7, 0x6A, 0x37, 0x0D, 0xCC, 0x9E, 0x17, 0x13, 0x08, + 0xC3, 0x1A, 0xD2, 0x7B, 0x6D, 0x2D, 0x7A, 0x53, 0xE8, 0x00, 0x35, 0x5A, 0x19, 0x76, 0xED, 0xFE, 0x22, 0xDB, 0x2F, 0x18, + 0xB4, 0x0E, 0x72, 0xCF, 0xE3, 0xCE, 0xDB, 0x6F, 0x77, 0xFE, 0x3B, 0x63, 0xAD, 0x79, 0x4B, 0x9C, 0xB8, 0xF5, 0x0B, 0x45, + 0xBD, 0x80, 0xED, 0xA2, 0x9B, 0xED, 0xC0, 0x99, 0xC9, 0x26, 0xA1, 0xF0, 0xB7, 0x2C, 0xCC, 0x12, 0x00, 0x1D, 0x0D, 0xB9, + 0x40, 0x4D, 0x54, 0xFC, 0x7B, 0xDD, 0x47, 0x89, 0x8A, 0x0C, 0xD6, 0xD4, 0x67, 0xD0, 0x13, 0xAF, 0xCE, 0x6C, 0x85, 0xF5, + 0xAF, 0x09, 0x17, 0x74, 0xF6, 0xB7, 0x7C, 0x11, 0x43, 0x82, 0x71, 0x14, 0x15, 0x6D, 0x2D, 0xFF, 0x05, 0x8D, 0x08, 0xF8, + 0x21, 0xAF, 0xC1, 0x13, 0x59, 0xB3, 0xFE, 0x6D, 0x4C, 0x12, 0x75, 0xE7, 0x86, 0x64, 0x0A, 0x93, 0xC6, 0xD1, 0xE9, 0x2F, + 0x6E, 0x2B, 0x9A, 0x62, 0xDF, 0xF7, 0x76, 0x0F, 0x6E, 0xD0, 0x6E, 0x99, 0x1F, 0x57, 0xAC, 0x2B, 0x0C, 0x38, 0xBD, 0xA5, + 0x4B, 0x34, 0x36, 0xF3, 0x5A, 0xDC, 0x3C, 0x3F, 0x12, 0x08, 0xBA, 0xAF, 0xD1, 0x73, 0x49, 0x54, 0xB9, 0xBC, 0xF5, 0x0E, + 0xE6, 0x0B, 0xED, 0xEB, 0x0A, 0x15, 0xE4, 0xB3, 0xCB, 0xD5, 0xEF, 0x28, 0x56, 0x14, 0x7B, 0x77, 0x8A, 0xE0, 0xE3, 0x46, + 0xD4, 0x97, 0x8A, 0xC8, 0xAF, 0x4C, 0x9E, 0x71, 0xCD, 0xFA, 0xA7, 0x2E, 0x61, 0x17, 0x0E, 0xD3, 0x5D, 0xB2, 0x7F, 0x81, + 0x17, 0x34, 0x96, 0x61, 0xB2, 0xCF, 0x87, 0xE5, 0x6B, 0x42, 0xFA, 0xC1, 0xDA, 0xE2, 0xF5, 0x94, 0xC2, 0x0E, 0xE8, 0x2A, + 0x4B, 0xDF, 0x0F, 0xCB, 0xDA, 0x26, 0x08, 0x4F, 0xEC, 0xE1, 0x7C, 0x6A, 0x0E, 0xDB, 0x14, 0x11, 0xBC, 0x7B, 0xD9, 0xFC, + 0x04, 0xD1, 0x38, 0x59, 0xD9, 0x06, 0x3F, 0xCA, 0x28, 0xD7, 0x75, 0x30, 0x55, 0xB4, 0x4D, 0x08, 0x32, 0x6C, 0x29, 0xEF, + 0x5A, 0x07, 0x56, 0x25, 0xCD, 0xDD, 0x5B, 0x7F, 0x8B, 0xBE, 0xC1, 0xA0, 0x69, 0x86, 0x46, 0x01, 0x9E, 0x22, 0x57, 0x49, + 0x40, 0x88, 0xE7, 0xDC, 0x90, 0x96, 0x9C, 0x24, 0xCA, 0x42, 0xF7, 0xCB, 0xCD, 0x9C, 0xEB, 0x9E, 0xF6, 0xBF, 0xD8, 0xE2, + 0x4F, 0x6E, 0xED, 0x79, 0x3B, 0x4E, 0x44, 0xB8, 0x21, 0xF5, 0x09, 0x20, 0x18, 0xB0, 0x97, 0x86, 0x15, 0x4A, 0x4E, 0xCF, + 0x14, 0x43, 0x83, 0xDB, 0xA1, 0xBF, 0xC8, 0x55, 0x95, 0xDC, 0xE8, 0x50, 0x3E, 0xAA, 0x5B, 0xC1, 0xFE, 0x21, 0x60, 0xC7, + 0x35, 0xCE, 0xBE, 0x11, 0x0D, 0x60, 0xB9, 0xD5, 0x4F, 0x2D, 0x68, 0xDA, 0xAB, 0x3D, 0x01, 0x57, 0xE3, 0x8A, 0xC9, 0x54, + 0x0B, 0x0B, 0x8D, 0xF7, 0x13, 0x6B, 0x47, 0xDE, 0xE3, 0x40, 0x0F, 0xDD, 0x4D, 0x2C, 0x9F, 0x20, 0xBE, 0xF5, 0xB6, 0xA2, + 0x02, 0x6B, 0xE5, 0xC0, 0x0A, 0x47, 0x7C, 0x26, 0xD1, 0xB0, 0x88, 0xA4, 0x82, 0xDE, 0x30, 0xBC, 0xD5, 0xEA, 0xC6, 0x84, + 0xB2, 0x4A, 0xBE, 0x70, 0x38, 0xE3, 0xF0, 0x7D, 0xF9, 0xE6, 0x98, 0xEF, 0x35, 0x36, 0x0B, 0x01, 0xFE, 0x04, 0x33, 0x7A, + 0x1C, 0xCD, 0xFF, 0xAC, 0xA2, 0x72, 0x90, 0xFB, 0x34, 0x3C, 0x99, 0x04, 0x63, 0x4A, 0x59, 0x2A, 0x2A, 0x9B, 0x94, 0xA8, + 0x10, 0x99, 0x99, 0x7E, 0xBB, 0x2E, 0x6B, 0xD3, 0xBC, 0x97, 0x93, 0xCA, 0xA7, 0x73, 0x40, 0xA5, 0x0F, 0x61, 0x4A, 0xF4, + 0x67, 0xD5, 0xFA, 0x07, 0x6D, 0x52, 0x36, 0xA2, 0x5A, 0xEA, 0xBC, 0x19, 0x86, 0x68, 0x0B, 0x64, 0x3B, 0x4F, 0xA4, 0xD6, + 0x4B, 0x44, 0xF0, 0x5B, 0x2F, 0x97, 0xAA, 0x67, 0x36, 0x65, 0x30, 0x42, 0x9F, 0x20, 0xF9, 0x4F, 0xE8, 0x73, 0x5B, 0x49, + 0x5B, 0x96, 0xD5, 0x66, 0x7E, 0xB7, 0x6C, 0xAA, 0x29, 0x59, 0xAB, 0x4F, 0xEB, 0x33, 0x8C, 0xF2, 0x5A, 0x98, 0xD5, 0x1E, + 0x2F, 0x96, 0x90, 0x94, 0xBC, 0xA0, 0x12, 0x71, 0x9E, 0x10, 0xE0, 0x8F, 0x89, 0xB1, 0x5B, 0xB1, 0x14, 0x4C, 0x99, 0x49, + 0x3D, 0x3E, 0xFF, 0xF6, 0x7F, 0x98, 0x34, 0x9C, 0x00, 0x1E, 0xFD, 0xA0, 0xAA, 0x74, 0x92, 0xDA, 0x7C, 0x84, 0xF0, 0x26, + 0x76, 0xB3, 0x62, 0x23, 0x06, 0x12, 0xC4, 0xC5, 0xBE, 0x9B, 0x93, 0x6C, 0xBA, 0xFD, 0x0C, 0x24, 0x65, 0x1A, 0x6C, 0xA6, + 0x64, 0x32, 0x77, 0xB4, 0xAE, 0x13, 0xD5, 0x83, 0x55, 0xB0, 0x2B, 0x34, 0x6B, 0x9F, 0xA7, 0x52, 0x61, 0xCC, 0x01, 0x63, + 0xF4, 0x3B, 0xDB, 0x67, 0xEC, 0xB7, 0xD5, 0x15, 0x03, 0x49, 0x0F, 0x6E, 0xF3, 0xD2, 0xBA, 0x90, 0x2C, 0x1F, 0xF5, 0x66, + 0x85, 0x30, 0xDD, 0x85, 0xB5, 0xDE, 0x65, 0xA8, 0x71, 0x1F, 0x7C, 0xBD, 0x01, 0xC6, 0x22, 0xB6, 0xD9, 0x92, 0xAB, 0xE0, + 0x9D, 0xAB, 0x63, 0xC0, 0xFD, 0x76, 0xB3, 0x62, 0x2E, 0xD7, 0xF7, 0x8A, 0xEE, 0x88, 0xA3, 0x0F, 0x63, 0x75, 0xB4, 0x8B, + 0x13, 0x35, 0x25, 0xF6, 0x8B, 0x1B, 0x9B, 0x57, 0xB6, 0xEA, 0xAE, 0x1E, 0xEA, 0x56, 0x62, 0xE4, 0x7F, 0x7A, 0x2D, 0xE6, + 0x8E, 0x1A, 0x62, 0xCB, 0x65, 0xC3, 0xC6, 0xDF, 0x96, 0xE2, 0xA3, 0x62, 0x12, 0xA4, 0x6E, 0x96, 0xDF, 0xEC, 0x05, 0x80, + 0x0B, 0x8A, 0x4F, 0x3E, 0x8F, 0x43, 0x06, 0x0C, 0x6C, 0xB0, 0x5E, 0x66, 0x25, 0xB2, 0x1F, 0x03, 0xD2, 0x68, 0x1F, 0x5E, + 0x5A, 0x4E, 0x3D, 0x84, 0xD8, 0xC6, 0xF8, 0x78, 0x17, 0x29, 0x3F, 0x72, 0x35, 0x97, 0x61, 0x4F, 0x6D, 0x28, 0xC7, 0xAD, + 0xF5, 0x7C, 0xF2, 0x89, 0xC2, 0x64, 0xD2, 0x9C, 0x00, 0x57, 0xE7, 0xB1, 0x4E, 0x4B, 0x87, 0x05, 0x92, 0xAA, 0xBD, 0xB7, + 0x5F, 0xE3, 0x21, 0x3F, 0xE0, 0x97, 0xCD, 0x4B, 0x1F, 0x9B, 0xA8, 0x7A, 0x11, 0xDA, 0xD1, 0x38, 0x67, 0x06, 0x65, 0x83, + 0x86, 0xC1, 0x5E, 0xF8, 0x6B, 0xFD, 0xE4, 0x0F, 0xAD, 0xD2, 0x27, 0xFE, 0xC3, 0x13, 0xA4, 0xC9, 0x6F, 0x63, 0xCC, 0x53, + 0x9F, 0x32, 0x57, 0x1C, 0x38, 0xFE, 0xAF, 0xA7, 0x4C, 0x5D, 0x6C, 0xEB, 0x67, 0xDA, 0x5F, 0xF9, 0xEB, 0xBF, 0x38, 0x0C, + 0x21, 0x6F, 0xE0, 0x47, 0x82, 0x88, 0x2D, 0x84, 0x15, 0xC3, 0xDC, 0xB0, 0x08, 0xC8, 0x70, 0xA2, 0x24, 0xED, 0xAC, 0x20, + 0x0B, 0xE3, 0xA0, 0x31, 0xF4, 0xAE, 0x20, 0xDF, 0x45, 0x9A, 0x54, 0xA5, 0x39, 0x7C, 0xE5, 0x7C, 0xEF, 0x8D, 0xFB, 0x06, + 0x37, 0xA4, 0x75, 0xDF, 0x6C, 0x39, 0xCA, 0x00, 0x75, 0x5D, 0x63, 0xAE, 0x83, 0xEB, 0x76, 0xBA, 0x93, 0x52, 0xBB, 0x41, + 0x3E, 0x81, 0xDF, 0x03, 0xD4, 0x81, 0x64, 0xBF, 0x06, 0x5F, 0xBC, 0xD0, 0xFF, 0x2E, 0x5F, 0x18, 0x9F, 0x54, 0x5F, 0x78, + 0xB2, 0x10, 0x31, 0xD4, 0x60, 0x9D, 0x24, 0x49, 0xB4, 0x20, 0xD7, 0x56, 0x4F, 0xC5, 0xA6, 0x44, 0x17, 0xA9, 0x09, 0xC7, + 0x8E, 0xD8, 0xF3, 0xB9, 0x69, 0x0B, 0x51, 0x2D, 0x1B, 0x7B, 0x47, 0x96, 0x3E, 0xE2, 0x09, 0x64, 0xA6, 0x8A, 0x16, 0xBF, + 0x05, 0x0A, 0x7D, 0x72, 0xCF, 0xE7, 0x98, 0x64, 0xBD, 0x73, 0x83, 0x4D, 0xB1, 0xCA, 0x5B, 0x8C, 0x1D, 0xCD, 0xE8, 0x35, + 0x7F, 0x0E, 0xEB, 0x21, 0xB5, 0x29, 0xEA, 0x5F, 0x93, 0x02, 0xF4, 0x33, 0x15, 0x22, 0xE5, 0x5A, 0x4B, 0xB2, 0x42, 0x24, + 0x39, 0x5D, 0xAF, 0x8D, 0x8D, 0x9A, 0xF9, 0x0E, 0x3F, 0xEB, 0xF1, 0x0F, 0xBB, 0x6C, 0x4B, 0x27, 0x35, 0x0B, 0xAB, 0xF9, + 0x0D, 0x4B, 0x54, 0xEC, 0xED, 0x04, 0x3E, 0xC7, 0x07, 0x30, 0x2D, 0xD7, 0x90, 0x16, 0x9D, 0x3A, 0x4B, 0x87, 0x9A, 0xB8, + 0x0E, 0x51, 0x8D, 0x6B, 0x4E, 0xCC, 0xD4, 0xDA, 0x86, 0x47, 0x52, 0xA4, 0xF2, 0x54, 0x5D, 0x5F, 0x92, 0xA1, 0x7E, 0x85, + 0x47, 0xAD, 0xAA, 0xE0, 0xA4, 0x16, 0x74, 0xC9, 0x62, 0xC7, 0x19, 0x6B, 0x11, 0xAC, 0x73, 0x6A, 0xC6, 0x31, 0x56, 0x7B, + 0x59, 0xF8, 0x94, 0xD9, 0x63, 0x06, 0x83, 0x41, 0x59, 0x5B, 0x84, 0x84, 0xCF, 0xCF, 0xFB, 0xBD, 0x5C, 0xA9, 0xE4, 0x73, + 0x9B, 0x32, 0xC2, 0xAA, 0x37, 0xA2, 0xCC, 0xE4, 0x3E, 0x7B, 0x30, 0x57, 0x08, 0xF0, 0x55, 0x69, 0x4E, 0xEE, 0x76, 0x75, + 0xB8, 0x4C, 0xC4, 0x96, 0xB0, 0x6C, 0x2F, 0xB6, 0x1E, 0x00, 0x7B, 0x6C, 0xF4, 0x91, 0x0A, 0xEC, 0x69, 0xF0, 0x69, 0x35, + 0xD7, 0xE0, 0xE5, 0x93, 0xB0, 0x59, 0xEC, 0x89, 0x52, 0x27, 0xCB, 0xAE, 0x40, 0x15, 0x96, 0xCC, 0xA7, 0xDA, 0x7E, 0x5B, + 0x19, 0x88, 0x3B, 0x38, 0x02, 0xA8, 0x9A, 0xF5, 0x5D, 0x31, 0x74, 0xE2, 0x66, 0x76, 0x8A, 0x7C, 0xA3, 0x69, 0x93, 0x2C, + 0xDF, 0xCD, 0xE4, 0xCC, 0xFF, 0x9D, 0x7C, 0xF2, 0x67, 0x44, 0x5F, 0xC0, 0xAB, 0x10, 0xDA, 0x88, 0xC5, 0x69, 0x65, 0x81, + 0x24, 0x12, 0x75, 0xE3, 0xE6, 0x75, 0x5E, 0xB8, 0x0F, 0x0A, 0x57, 0x29, 0x4C, 0x94, 0xCA, 0x26, 0x2B, 0xD7, 0x7D, 0xF3, + 0xEF, 0xCE, 0xA3, 0xC4, 0xF3, 0x5C, 0xD9, 0x7B, 0x93, 0xAB, 0xB5, 0x4E, 0x78, 0x6C, 0x76, 0xBA, 0x4F, 0xB0, 0xAE, 0xBD, + 0x08, 0x5B, 0xD3, 0x8A, 0x46, 0xE6, 0x3B, 0x97, 0xBD, 0xF4, 0x46, 0x38, 0x6C, 0xBC, 0xA6, 0x42, 0xE3, 0xBB, 0x77, 0x75, + 0xA0, 0x31, 0xB4, 0x90, 0xC4, 0x8E, 0x57, 0xEB, 0xC2, 0x57, 0x91, 0x92, 0x9A, 0x01, 0xEF, 0x6A, 0x12, 0x39, 0x91, 0xB2, + 0x4E, 0x16, 0x47, 0x46, 0xB9, 0xDF, 0x20, 0x47, 0x8A, 0x1E, 0x5D, 0x8D, 0xE4, 0xC4, 0x0E, 0x44, 0x1C, 0x6A, 0xDE, 0x7B, + 0xEB, 0xAE, 0xC4, 0xEA, 0xFB, 0xEA, 0x7D, 0x5E, 0x42, 0x56, 0x86, 0x58, 0xC3, 0xFC, 0xD6, 0x72, 0xEA, 0x6F, 0xA0, 0xF1, + 0x7B, 0xB3, 0x2F, 0x6B, 0xCD, 0xA5, 0x98, 0x32, 0xBE, 0xB0, 0xDF, 0x67, 0x6B, 0xEC, 0x56, 0xF5, 0x62, 0x4A, 0x57, 0xB2, + 0x8C, 0xFE, 0x03, 0x5F, 0x43, 0x9F, 0xBF, 0x4E, 0x34, 0xC4, 0x9E, 0x5F, 0x29, 0x40, 0xDF, 0x00, 0x83, 0x0E, 0xCA, 0x66, + 0x4D, 0x26, 0x18, 0x34, 0xBD, 0x2E, 0x3B, 0x7B, 0xED, 0x9C, 0x76, 0xA0, 0xBA, 0x8A, 0x27, 0xFF, 0xF8, 0xA9, 0x78, 0x74, + 0x7C, 0x4C, 0xA7, 0x6B, 0xAC, 0x0F, 0xE1, 0x3E, 0xA4, 0x8F, 0x2E, 0xEB, 0x33, 0x24, 0x73, 0xCB, 0xC1, 0x82, 0x51, 0x38, + 0xA2, 0x9E, 0x18, 0x38, 0x32, 0x4E, 0xF1, 0x97, 0x4C, 0x3C, 0x8E, 0xD3, 0xE5, 0x0F, 0xFF, 0xF5, 0xD0, 0x03, 0x78, 0xBF, + 0x61, 0xB0, 0x72, 0x5B, 0xFE, 0x8F, 0xF3, 0x56, 0x9E, 0xA1, 0xB1, 0xC4, 0x84, 0xDB, 0x70, 0xAB, 0x05, 0xBE, 0x48, 0x12, + 0x81, 0x71, 0xD8, 0x36, 0xD1, 0xE1, 0xAA, 0x7C, 0xB7, 0xC2, 0xD2, 0xC5, 0xEF, 0xCD, 0xF7, 0x41, 0xF9, 0xA3, 0x2F, 0x52, + 0xA9, 0xC3, 0xF8, 0x0A, 0x43, 0xA3, 0xD5, 0x2E, 0x68, 0x08, 0xEA, 0x5A, 0x4B, 0x8C, 0x0B, 0x6B, 0x0B, 0xE4, 0xE8, 0xC8, + 0x37, 0xF2, 0xFD, 0xFA, 0x29, 0x18, 0xBC, 0x5D, 0xBB, 0x68, 0x7C, 0x42, 0x6A, 0xA5, 0x35, 0xEC, 0x7C, 0x95, 0x1C, 0xA8, + 0xE2, 0x8A, 0x18, 0xE4, 0xF5, 0x92, 0xB6, 0xB7, 0xF6, 0xC4, 0x1A, 0x23, 0x04, 0x28, 0xC3, 0xC0, 0xED, 0xF7, 0xD8, 0xA3, + 0x79, 0x85, 0x94, 0x8F, 0x03, 0xC7, 0x3F, 0xBE, 0x85, 0x60, 0x51, 0x20, 0xB1, 0x14, 0x93, 0xF0, 0x9D, 0xD0, 0xFA, 0xD7, + 0x28, 0x7D, 0xFB, 0x79, 0x5D, 0xE6, 0x70, 0xB3, 0xFA, 0x03, 0x67, 0x48, 0x9D, 0x3A, 0x75, 0x99, 0xD6, 0x2C, 0xD3, 0x5A, + 0xA2, 0x97, 0x5D, 0xA7, 0xE2, 0x02, 0xCA, 0x9E, 0x98, 0x6B, 0x25, 0x85, 0x4B, 0x43, 0x6D, 0x58, 0xD4, 0x6F, 0xFE, 0xBA, + 0x29, 0x8B, 0x93, 0xD3, 0x61, 0xD5, 0xBB, 0xE3, 0xE8, 0x98, 0xD3, 0xAF, 0x59, 0x28, 0x18, 0xA7, 0xAF, 0x82, 0x7C, 0x79, + 0x19, 0x2B, 0x33, 0xFF, 0x37, 0x0E, 0x6C, 0x7C, 0x56, 0x63, 0x5C, 0x81, 0xD5, 0x1B, 0xE4, 0xC5, 0xBC, 0x3D, 0x54, 0xFB, + 0x42, 0xFE, 0xAE, 0x18, 0x9B, 0x14, 0xD3, 0x91, 0x05, 0xAD, 0x57, 0x96, 0x4E, 0xD9, 0xE3, 0xC2, 0xB7, 0x8E, 0xC6, 0x18, + 0x05, 0xDE, 0x81, 0x7C, 0xA0, 0x53, 0x8F, 0x84, 0x13, 0x73, 0x12, 0xD3, 0x6D, 0xA4, 0xAF, 0x22, 0x03, 0x33, 0xB2, 0xCA, + 0x58, 0x99, 0xD6, 0xA2, 0xCA, 0x3A, 0x27, 0x2A, 0x1A, 0xDE, 0x3D, 0xC7, 0x93, 0xA7, 0x51, 0x44, 0x62, 0x8B, 0x60, 0xA6, + 0x47, 0x3D, 0xB8, 0x08, 0xAC, 0x19, 0x8A, 0xD6, 0x76, 0x38, 0xF3, 0x97, 0xF9, 0x1D, 0x94, 0xB6, 0x44, 0x31, 0x54, 0xE8, + 0x9B, 0xB4, 0xFB, 0x05, 0xEF, 0x35, 0x7A, 0xA1, 0xAA, 0xA4, 0x45, 0x82, 0x96, 0xCB, 0xB2, 0x69, 0x47, 0x80, 0xB4, 0xEB, + 0x22, 0x02, 0xC8, 0xAE, 0x2C, 0x81, 0x12, 0x75, 0xC8, 0xB7, 0xEA, 0xC5, 0xE5, 0x0E, 0x35, 0x7F, 0xD1, 0xA1, 0x82, 0x79, + 0x8B, 0x1A, 0x5B, 0xEB, 0x3E, 0x03, 0x75, 0x52, 0x4C, 0x5E, 0xE8, 0xAB, 0xD9, 0x39, 0x2E, 0xFA, 0x9E, 0x7C, 0x1E, 0xD3, + 0xC4, 0x45, 0x66, 0x3A, 0xB4, 0xD6, 0x3E, 0x4F, 0xF5, 0xE4, 0x35, 0x76, 0x2A, 0x52, 0x13, 0x09, 0xA8, 0x3A, 0xB8, 0x4B, + 0x8B, 0x7A, 0xE9, 0xAB, 0x19, 0xF9, 0x37, 0x49, 0x74, 0x64, 0x26, 0xE3, 0x2C, 0x96, 0x45, 0x63, 0x4A, 0x5D, 0xE7, 0x99, + 0x2C, 0xC6, 0x0E, 0xDC, 0xAA, 0x0C, 0xBD, 0x48, 0x51, 0xC6, 0x66, 0xD7, 0x0E, 0x1E, 0xA9, 0x11, 0x7A, 0x72, 0xCD, 0x66, + 0x6B, 0xB1, 0x62, 0xF8, 0xB4, 0x7C, 0x7E, 0x32, 0x23, 0x9C, 0xBE, 0xB8, 0x74, 0x70, 0xF8, 0xB0, 0x8B, 0x9E, 0x78, 0x91, + 0x9B, 0x7E, 0x8E, 0x96, 0xA2, 0xBF, 0xBF, 0x6B, 0x06, 0x3F, 0xE0, 0xA7, 0x76, 0x5E, 0x23, 0x5D, 0x47, 0x1F, 0x7F, 0xAA, + 0xCF, 0x31, 0x95, 0x03, 0x58, 0x79, 0x98, 0xFD, 0xE7, 0x89, 0xA0, 0xFA, 0xB5, 0xE2, 0x4D, 0x50, 0xD6, 0xDF, 0xC8, 0xA4, + 0x72, 0xA8, 0x97, 0x23, 0x67, 0x2E, 0x77, 0x76, 0x6E, 0xCC, 0xC8, 0xE1, 0x43, 0xCA, 0x30, 0xCF, 0x36, 0xA1, 0x20, 0x87, + 0x9F, 0x4B, 0xA5, 0xC9, 0xE3, 0x47, 0x0A, 0x83, 0x29, 0x20, 0xC9, 0x00, 0x77, 0xE4, 0x7B, 0x1A, 0x3F, 0x23, 0x69, 0xFA, + 0x30, 0x5E, 0x17, 0xB7, 0xC7, 0x7F, 0xC1, 0xB5, 0xF3, 0x6B, 0x9B, 0xB2, 0xD6, 0x55, 0xB2, 0x24, 0x77, 0xF1, 0x4A, 0x91, + 0x22, 0x69, 0x98, 0x78, 0x90, 0x10, 0x17, 0x32, 0x7F, 0xE9, 0x37, 0x5E, 0x49, 0x2E, 0xEA, 0x35, 0x99, 0xCF, 0xA6, 0xE4, + 0x53, 0x4A, 0xA1, 0x37, 0x0D, 0x8B, 0xF9, 0x43, 0x1B, 0xE7, 0xF8, 0xF3, 0x39, 0x6B, 0x17, 0x15, 0x3D, 0x40, 0x0B, 0x43, + 0x84, 0x07, 0xB8, 0x6A, 0x7C, 0xE3, 0x2D, 0x00, 0xA3, 0x47, 0x1A, 0x84, 0x09, 0x4C, 0xCB, 0x79, 0x6E, 0x81, 0xBA, 0x9A, + 0x1A, 0x13, 0x08, 0x6D, 0xD2, 0xB7, 0x22, 0xDE, 0x2F, 0x99, 0x29, 0xE5, 0xEC, 0xEA, 0xC8, 0x1A, 0x1E, 0x29, 0x5F, 0xD1, + 0xAC, 0xDF, 0x19, 0xCD, 0xD1, 0xA8, 0x63, 0x78, 0x90, 0x2B, 0x9A, 0x7C, 0xF8, 0xC6, 0x09, 0xA5, 0x7B, 0x47, 0xCD, 0x29, + 0x3D, 0x69, 0xD0, 0x68, 0xEF, 0x72, 0xAD, 0x2B, 0x1D, 0x95, 0x42, 0x39, 0xC1, 0x89, 0x04, 0x06, 0x36, 0xAF, 0x39, 0x4A, + 0x8E, 0x0C, 0xD8, 0xFE, 0x9E, 0x03, 0x0C, 0x5F, 0xA7, 0x2D, 0x95, 0x66, 0xB5, 0x7A, 0x51, 0xDF, 0x01, 0xEF, 0xBA, 0x63, + 0xF4, 0xE9, 0x6E, 0x41, 0x23, 0x38, 0xC5, 0x21, 0x8B, 0x28, 0x5C, 0x7B, 0x7D, 0x11, 0x47, 0x2D, 0x69, 0x25, 0xDF, 0xF8, + 0xDB, 0xC4, 0x58, 0x15, 0x0B, 0x12, 0x21, 0xC6, 0x74, 0x8C, 0xD1, 0xEF, 0x1F, 0x00, 0xE9, 0xFF, 0xE4, 0x11, 0x5C, 0x48, + 0x34, 0x4A, 0x9D, 0xD3, 0x87, 0x4F, 0xEE, 0x7D, 0x47, 0xB0, 0x9B, 0x54, 0x8D, 0x18, 0x1F, 0xFC, 0x89, 0x6C, 0xA4, 0x90, + 0xD0, 0x9E, 0x40, 0x05, 0x32, 0xB9, 0x44, 0x30, 0xB8, 0xAE, 0x22, 0x42, 0xD4, 0x0E, 0x98, 0xDE, 0x5B, 0x94, 0x65, 0x9A, + 0xC6, 0x4F, 0x4D, 0x84, 0x0D, 0x3A, 0xEF, 0xA0, 0x84, 0xB0, 0x99, 0xEC, 0x06, 0x2E, 0xAF, 0x88, 0xB2, 0xB7, 0x82, 0x51, + 0x41, 0x32, 0xE7, 0xB0, 0x81, 0xB1, 0x88, 0x42, 0xDA, 0xB4, 0x48, 0x84, 0xB5, 0x60, 0x34, 0xDD, 0x6E, 0xB8, 0x7C, 0x86, + 0x97, 0xFB, 0x8E, 0xCD, 0xE9, 0x18, 0x92, 0x45, 0x5C, 0x33, 0xDB, 0x65, 0x86, 0x7A, 0x35, 0x14, 0xF5, 0xBD, 0xC9, 0x81, + 0x25, 0x42, 0x07, 0xD8, 0x78, 0x3B, 0x5D, 0x21, 0x32, 0x10, 0x41, 0x05, 0x74, 0xBE, 0x13, 0x40, 0xCC, 0x11, 0x6D, 0x24, + 0x53, 0x18, 0x1B, 0x02, 0x25, 0x97, 0x37, 0x15, 0x75, 0xBF, 0xE2, 0x0F, 0x6F, 0x6B, 0xA7, 0xF1, 0xB1, 0x1E, 0x0C, 0x0F, + 0xAD, 0xBB, 0x28, 0x5A, 0xDD, 0x47, 0x4E, 0x98, 0xE5, 0x94, 0xE2, 0xED, 0x7E, 0x06, 0xC1, 0x9C, 0x5D, 0x54, 0x01, 0xF1, + 0x1E, 0x4D, 0x47, 0xCF, 0x91, 0x95, 0xEB, 0x4F, 0xB8, 0x4E, 0xE3, 0x7B, 0x6D, 0x62, 0x77, 0x56, 0xD1, 0x86, 0xD0, 0xDC, + 0x6F, 0xAB, 0xF4, 0x9F, 0x68, 0xE6, 0xEB, 0x45, 0x2C, 0xB8, 0xAC, 0x3B, 0x90, 0x30, 0xE6, 0xD0, 0xF8, 0x28, 0x50, 0x3F, + 0xD6, 0xAC, 0x08, 0x74, 0x85, 0x2A, 0xD6, 0x8C, 0x3D, 0x07, 0x10, 0x40, 0xFA, 0xC0, 0xCD, 0xC4, 0xE7, 0x09, 0x1D, 0xA4, + 0x9E, 0x01, 0x05, 0x1C, 0xFD, 0xF5, 0x80, 0x3A, 0x74, 0x8E, 0x99, 0xFD, 0x3B, 0xA8, 0x29, 0x70, 0xFE, 0x71, 0x8F, 0xC8, + 0x5F, 0x74, 0xC4, 0x84, 0x12, 0x63, 0xB1, 0xD0, 0xAD, 0xF1, 0xD0, 0x80, 0x32, 0x0B, 0x3B, 0x9D, 0xBC, 0x08, 0x78, 0x62, + 0x43, 0xFE, 0xFE, 0x03, 0xF1, 0x46, 0x09, 0xA4, 0x17, 0xAA, 0xCE, 0x2B, 0x42, 0x2E, 0x70, 0x72, 0x42, 0xBE, 0x77, 0x66, + 0xEA, 0x9C, 0x40, 0x35, 0xE4, 0x45, 0x2F, 0x8B, 0xA5, 0xB6, 0x79, 0x63, 0xC3, 0x7D, 0x7A, 0xF5, 0x98, 0x44, 0x81, 0x5A, + 0xF3, 0x62, 0xF0, 0x85, 0x06, 0xDD, 0x71, 0x93, 0x88, 0x67, 0x25, 0x86, 0xB0, 0x29, 0x18, 0x57, 0x36, 0x2F, 0xAE, 0x8E, + 0x21, 0xF4, 0x08, 0x68, 0x61, 0x72, 0x07, 0xAC, 0x48, 0x69, 0x94, 0xE5, 0x4C, 0xCE, 0xD0, 0x94, 0x3B, 0x95, 0x37, 0xA0, + 0x9D, 0xF4, 0x17, 0x0F, 0xEE, 0x99, 0x4F, 0xF4, 0x2E, 0xD9, 0x23, 0x6B, 0xD7, 0xCA, 0xD2, 0xC5, 0x84, 0x9F, 0x54, 0xBA, + 0x94, 0xCD, 0x55, 0x9E, 0xA1, 0xA4, 0x2E, 0x1B, 0xB0, 0x01, 0x89, 0xD5, 0xF2, 0x6B, 0xF6, 0xAB, 0x26, 0x88, 0xE6, 0x93, + 0xE7, 0x29, 0x7D, 0x17, 0x5E, 0x05, 0x3A, 0xD8, 0xF5, 0x07, 0x44, 0x88, 0x33, 0xBF, 0x4B, 0x22, 0xAD, 0x9E, 0xFA, 0xEE, + 0xDE, 0x9D, 0xEA, 0x6E, 0xF2, 0xF2, 0xD6, 0xCE, 0x1F, 0x02, 0x28, 0xC6, 0xB4, 0x98, 0xBA, 0xD6, 0xA4, 0xE0, 0x93, 0x4F, + 0xA8, 0x11, 0xD9, 0x4F, 0xE0, 0x68, 0x51, 0x3A, 0xE9, 0x45, 0x03, 0xEA, 0x21, 0xE3, 0x0F, 0x9D, 0xF8, 0x56, 0xF8, 0x6E, + 0xB8, 0x9A, 0xE0, 0x16, 0x96, 0x1E, 0xBB, 0xB7, 0xD8, 0xCB, 0x25, 0x88, 0x48, 0x87, 0x62, 0xBD, 0x96, 0x2C, 0x12, 0x57, + 0x42, 0x20, 0xAD, 0x4B, 0xFB, 0xDD, 0xEC, 0xA3, 0x68, 0x7F, 0xAD, 0x1C, 0x53, 0x80, 0x5A, 0x63, 0x85, 0xE6, 0x7D, 0x7A, + 0x8F, 0x09, 0x86, 0x75, 0x8C, 0x4C, 0xFD, 0x4B, 0x65, 0x40, 0x7B, 0xAB, 0xA1, 0x88, 0xAC, 0x1F, 0xF4, 0xF1, 0xDC, 0xDD, + 0x8D, 0xEB, 0x6B, 0xA3, 0x62, 0xD0, 0x3D, 0x74, 0x2A, 0xE0, 0x6F, 0x5A, 0x7A, 0x03, 0x23, 0x76, 0xA5, 0x60, 0xB0, 0x77, + 0x1A, 0xBB, 0xD4, 0xD5, 0x0B, 0x5D, 0xA6, 0x56, 0x30, 0xEF, 0xA4, 0x94, 0xA6, 0x71, 0xD6, 0x07, 0x47, 0xC4, 0x80, 0xC2, + 0x96, 0x8C, 0xCC, 0x31, 0x33, 0xC4, 0xAD, 0x00, 0x25, 0x02, 0x9D, 0xB8, 0x5B, 0x76, 0x6B, 0x89, 0xE6, 0x8B, 0x3A, 0xDF, + 0x2D, 0x33, 0x9D, 0x31, 0x9D, 0x90, 0x2D, 0x6B, 0xDA, 0x3B, 0xB1, 0x22, 0xD1, 0x59, 0x01, 0xC7, 0x0E, 0x31, 0xE8, 0x5F, + 0x21, 0x24, 0x7B, 0x9A, 0xB1, 0x39, 0xB8, 0x60, 0x9E, 0x74, 0x14, 0x14, 0x55, 0xC5, 0xF5, 0xC1, 0x17, 0x11, 0xC4, 0xD1, + 0x4C, 0x15, 0x76, 0x20, 0xC0, 0xDD, 0xA7, 0xB3, 0xAD, 0x7F, 0x9A, 0x2F, 0xA4, 0xE4, 0x3A, 0xBB, 0x3D, 0xC0, 0xF9, 0xA3, + 0x61, 0xEB, 0x15, 0x84, 0x7B, 0x7B, 0x76, 0x53, 0x49, 0x50, 0x5D, 0x28, 0xB3, 0x76, 0x5C, 0x02, 0x29, 0xFC, 0x5F, 0xAA, + 0x02, 0x8B, 0x5F, 0xA3, 0x8D, 0x13, 0x86, 0x9F, 0x7B, 0x10, 0x02, 0x58, 0x49, 0x89, 0xCC, 0xBF, 0x5A, 0xA8, 0x0C, 0xEB, + 0x34, 0x10, 0xB9, 0x38, 0xC9, 0x1A, 0x61, 0xC5, 0x48, 0x3B, 0x9A, 0x47, 0x06, 0xBB, 0xC0, 0xFA, 0xFD, 0x11, 0x32, 0x2D, + 0x0C, 0xCB, 0xD7, 0xDC, 0x8F, 0x57, 0x81, 0xDE, 0xD5, 0xF3, 0x0D, 0xEB, 0x9A, 0x03, 0x0F, 0xE0, 0xDF, 0x55, 0x45, 0x50, + 0x91, 0x19, 0x1F, 0x4D, 0x31, 0xD6, 0x7E, 0x7A, 0x28, 0xDC, 0xA6, 0x6C, 0x64, 0x31, 0x31, 0xE0, 0xBE, 0x99, 0x7D, 0x97, + 0xAF, 0xCC, 0x16, 0xDD, 0x2D, 0xA6, 0x9E, 0x45, 0x58, 0x1D, 0xFE, 0x09, 0x8B, 0xDD, 0x71, 0xD8, 0x92, 0x87, 0x27, 0xCA, + 0xB7, 0x13, 0xCD, 0xC9, 0x19, 0x38, 0xF0, 0xDE, 0x81, 0xFB, 0xF7, 0x37, 0x27, 0xA3, 0x5E, 0xFD, 0x76, 0x62, 0xB7, 0x5F, + 0x99, 0xCD, 0xF7, 0x73, 0x7F, 0xCB, 0x73, 0x6E, 0xDA, 0x75, 0x79, 0x8A, 0xA1, 0x2B, 0xB2, 0x44, 0x12, 0x8B, 0x28, 0x4C, + 0x65, 0x22, 0x0F, 0xBD, 0xA3, 0xE4, 0x9B, 0xF0, 0x03, 0xDA, 0x38, 0x08, 0x69, 0x55, 0x42, 0x52, 0x47, 0x3D, 0x43, 0x48, + 0x76, 0x61, 0x59, 0xBE, 0x64, 0x7D, 0xCB, 0x1E, 0x14, 0xCF, 0xF1, 0xC2, 0x55, 0x5D, 0xB3, 0x60, 0x2D, 0x14, 0x43, 0x91, + 0x84, 0x64, 0xF9, 0x64, 0xD6, 0x17, 0x02, 0x6C, 0xC3, 0xE8, 0xE2, 0x3B, 0x55, 0x61, 0x8C, 0xD9, 0x05, 0xE4, 0x70, 0x59, + 0x74, 0x2F, 0x12, 0x7C, 0xA2, 0x30, 0x34, 0x9A, 0x56, 0x55, 0x48, 0x95, 0x78, 0x85, 0x4E, 0xAD, 0xEB, 0xB5, 0x26, 0x40, + 0x4F, 0x89, 0x3C, 0x09, 0x59, 0x1A, 0xBE, 0x42, 0xA2, 0x56, 0x24, 0x7A, 0x90, 0xE4, 0xC7, 0x92, 0x2E, 0xA6, 0x0E, 0x19, + 0xA4, 0x8A, 0xF9, 0xD1, 0x8E, 0x5A, 0x29, 0xAE, 0xBA, 0x5A, 0x18, 0x7D, 0x17, 0xB3, 0x69, 0x8A, 0x28, 0x6A, 0x78, 0x0B, + 0xAF, 0xCA, 0xDA, 0x3C, 0x74, 0xA5, 0x46, 0x48, 0xB7, 0x8A, 0x09, 0x5E, 0x54, 0xE1, 0xE5, 0xF2, 0x05, 0xC6, 0x51, 0x61, + 0x7D, 0xA0, 0xBF, 0x38, 0xA8, 0x88, 0xE1, 0x2A, 0xDD, 0xF9, 0xFF, 0xC1, 0x6D, 0x25, 0x5C, 0x7C, 0x3F, 0xC9, 0x6C, 0xD6, + 0xDA, 0x1A, 0x37, 0x91, 0x90, 0x6A, 0x72, 0x99, 0x6A, 0x90, 0xD5, 0xBB, 0x68, 0x28, 0x9C, 0x0E, 0xAE, 0x92, 0x00, 0xCE, + 0x7E, 0xBB, 0x5A, 0x1A, 0x06, 0xCE, 0xCA, 0x2C, 0x7D, 0xDA, 0x55, 0x9B, 0xD2, 0xDE, 0x09, 0x95, 0x6D, 0xCA, 0xFB, 0xD8, + 0xE5, 0xCA, 0xF1, 0xA1, 0xE7, 0x9D, 0x05, 0x87, 0x4F, 0xC3, 0x99, 0xBE, 0x41, 0xF6, 0x69, 0x6F, 0x6F, 0x21, 0xF5, 0xFF, + 0x98, 0xEC, 0x9B, 0xE1, 0xEC, 0x18, 0x49, 0x95, 0x27, 0x82, 0x53, 0xA4, 0x66, 0xDE, 0x2B, 0xA6, 0xB2, 0x73, 0x13, 0xFD, + 0x33, 0x8E, 0xD8, 0x09, 0xA6, 0xE6, 0xDC, 0x6A, 0x61, 0xDD, 0xE4, 0xB9, 0x3C, 0xDC, 0xAA, 0x56, 0x07, 0x2F, 0x7B, 0xE1, + 0xBE, 0x59, 0x75, 0xDA, 0x80, 0xFD, 0x0B, 0x01, 0x5E, 0x17, 0xAA, 0x36, 0x08, 0x1A, 0x7C, 0x5F, 0xB3, 0xF2, 0x0F, 0x53, + 0xF8, 0x6D, 0x8D, 0x45, 0x60, 0x74, 0x4D, 0x53, 0xD1, 0x73, 0xFD, 0xB6, 0x15, 0x0D, 0xCA, 0x53, 0xED, 0xDE, 0x2D, 0x66, + 0x77, 0xF3, 0x05, 0x23, 0x46, 0x03, 0x3E, 0xAF, 0x1C, 0x09, 0xCB, 0x99, 0x93, 0x28, 0xDC, 0x96, 0x3E, 0xBB, 0xD1, 0xF9, + 0x0D, 0xA0, 0xB7, 0x62, 0x49, 0x95, 0x32, 0xB0, 0xE6, 0xF7, 0x94, 0x54, 0x32, 0x7F, 0x9F, 0x09, 0x18, 0xD5, 0xBC, 0xE7, + 0xF7, 0xE5, 0x3F, 0xC4, 0xA0, 0x7F, 0x85, 0x67, 0xE0, 0x3B, 0x36, 0x25, 0x74, 0xD5, 0xA5, 0xEA, 0xBE, 0xF5, 0xA9, 0x56, + 0xE4, 0xB7, 0xB7, 0xD2, 0x14, 0x3A, 0x15, 0x31, 0x61, 0x22, 0xAD, 0x77, 0xBF, 0xB5, 0x30, 0x52, 0x8B, 0xD9, 0x9C, 0x7D, + 0xD8, 0x17, 0x16, 0x61, 0x48, 0x9A, 0x1A, 0x3D, 0x19, 0xF2, 0xEE, 0xEA, 0xD9, 0xDB, 0xD0, 0xAC, 0xB8, 0xAF, 0x06, 0x8A, + 0xBC, 0x76, 0xE3, 0x28, 0x59, 0x74, 0x1D, 0x63, 0x14, 0xD5, 0x11, 0x7E, 0x54, 0xEA, 0xEA, 0x1D, 0x11, 0x7B, 0xB1, 0x52, + 0xBA, 0xB8, 0x30, 0x88, 0xAB, 0x33, 0x8C, 0x85, 0x65, 0x0F, 0x9F, 0xC9, 0x8F, 0x02, 0x44, 0xC1, 0x70, 0x0D, 0x9D, 0x3A, + 0x76, 0x2D, 0x19, 0x4A, 0x45, 0x19, 0xE6, 0xA5, 0x93, 0xA0, 0xA9, 0xA4, 0xFE, 0x9C, 0x16, 0x2A, 0xF7, 0xDF, 0xD7, 0xAC, + 0x9C, 0xD8, 0xC1, 0xB4, 0xDA, 0x26, 0xA0, 0xB4, 0x79, 0x46, 0xA7, 0xBE, 0x6F, 0x43, 0x38, 0x9F, 0x3C, 0x0A, 0xB7, 0x1E, + 0x91, 0x82, 0x37, 0x16, 0x04, 0xBC, 0xF1, 0x2A, 0x0E, 0x13, 0x00, 0x25, 0x9B, 0x64, 0x7F, 0x05, 0xCD, 0x0F, 0x7E, 0xEE, + 0xA0, 0xBE, 0x3A, 0xF3, 0x64, 0xAD, 0x13, 0xEE, 0xB5, 0xDF, 0x5E, 0xF1, 0x64, 0xED, 0xA7, 0xA0, 0x36, 0x4F, 0x40, 0x95, + 0x62, 0xB6, 0x60, 0x35, 0x4F, 0xDC, 0x50, 0xAD, 0xA8, 0x11, 0xDC, 0x52, 0x51, 0x61, 0x93, 0x46, 0x4A, 0xDA, 0xCB, 0x18, + 0xB1, 0xA0, 0x12, 0xE6, 0x02, 0x62, 0x51, 0x90, 0x31, 0x20, 0x1F, 0x25, 0x87, 0xB9, 0xC3, 0x08, 0xB0, 0xA3, 0x5B, 0xCA, + 0x20, 0xBC, 0x99, 0x35, 0x30, 0x78, 0x48, 0x22, 0x26, 0xDF, 0xD6, 0x7D, 0x14, 0xCD, 0x69, 0x44, 0x29, 0x4B, 0x53, 0xE0, + 0x69, 0x6F, 0xDA, 0xA1, 0x7D, 0x14, 0x58, 0xD0, 0x7D, 0x03, 0x26, 0x76, 0xAA, 0x4A, 0xD9, 0x37, 0x4F, 0x49, 0x75, 0xBC, + 0xA3, 0x7D, 0x1B, 0x36, 0xAF, 0x29, 0xD1, 0x53, 0xA2, 0x4F, 0x39, 0xF4, 0xF6, 0x4A, 0x7E, 0x85, 0x73, 0xAD, 0x97, 0x7D, + 0x59, 0x8C, 0x0B, 0x46, 0x28, 0x23, 0x5F, 0x36, 0xDF, 0x47, 0x30, 0x6A, 0x29, 0xA8, 0x84, 0x41, 0x98, 0x38, 0xD2, 0x91, + 0x03, 0x4E, 0x64, 0xCA, 0x6B, 0xC4, 0xB5, 0x09, 0x6D, 0x0D, 0x14, 0x07, 0xF8, 0x26, 0xAE, 0x47, 0xEA, 0x27, 0x31, 0x4F, + 0x06, 0xB8, 0xB4, 0x3D, 0x8E, 0x51, 0xD9, 0xFF, 0xEC, 0x68, 0xE5, 0xAB, 0x3D, 0x45, 0x6B, 0x09, 0x0D, 0x97, 0xB1, 0xF1, + 0x11, 0xC0, 0x34, 0xFB, 0xCD, 0xFC, 0x79, 0xA9, 0x3C, 0xCD, 0x60, 0x4E, 0x86, 0x62, 0x82, 0xAD, 0x59, 0x17, 0xD7, 0x2C, + 0x61, 0x25, 0xC2, 0x0A, 0xB9, 0x29, 0x53, 0x6C, 0x53, 0x8B, 0x4B, 0x2B, 0x67, 0x42, 0xC2, 0x4F, 0x5C, 0x05, 0x61, 0x08, + 0xCB, 0xCB, 0x99, 0x79, 0x52, 0x8A, 0x23, 0x3A, 0xEE, 0x41, 0x98, 0x6E, 0x52, 0x84, 0x6B, 0xAE, 0x08, 0x5E, 0x94, 0x68, + 0xD3, 0x89, 0x12, 0x42, 0x62, 0x1E, 0x7C, 0x74, 0x6F, 0x3E, 0x7B, 0x5D, 0x4A, 0x42, 0x87, 0x7D, 0xDB, 0x2D, 0x64, 0xC4, + 0x2F, 0x1D, 0xBE, 0x35, 0x1A, 0x9F, 0x4E, 0x35, 0x1C, 0x12, 0x69, 0xD6, 0x5E, 0x2F, 0x46, 0x6B, 0x82, 0x50, 0x34, 0xB0, + 0xD0, 0x8E, 0x46, 0x89, 0x1D, 0xFE, 0x86, 0xB6, 0xC2, 0xFA, 0x4F, 0x7F, 0x03, 0x1F, 0x21, 0xFA, 0x13, 0x36, 0x8B, 0xFB, + 0x41, 0x8D, 0x2A, 0xE2, 0x6E, 0x2F, 0x6D, 0xD1, 0x8F, 0x1C, 0xD7, 0xE1, 0xC9, 0x71, 0xBD, 0xC3, 0x83, 0xF4, 0xBD, 0x3F, + 0xF0, 0x13, 0xE7, 0x33, 0xAE, 0x19, 0xBC, 0x46, 0x33, 0x63, 0xA4, 0x82, 0x23, 0x74, 0xD5, 0x24, 0x36, 0xD9, 0xDE, 0x20, + 0x16, 0xB4, 0xF4, 0x04, 0x6F, 0x3A, 0x56, 0xD2, 0xC0, 0x53, 0x4C, 0x09, 0x3B, 0x34, 0xBA, 0xE5, 0x43, 0xB9, 0xFD, 0x15, + 0x45, 0x39, 0x2D, 0x83, 0xA1, 0xA6, 0xCD, 0xD5, 0x09, 0x89, 0xDF, 0x55, 0xCE, 0xDC, 0xAD, 0x95, 0x01, 0xEA, 0x55, 0x53, + 0x16, 0x58, 0x31, 0x8A, 0x29, 0xAA, 0x66, 0xC9, 0xAC, 0x15, 0x9A, 0xD7, 0x99, 0x93, 0x68, 0xAF, 0x9D, 0x57, 0x21, 0xCC, + 0x5C, 0x85, 0x6E, 0x38, 0x77, 0x14, 0xF6, 0x74, 0x35, 0xE5, 0x66, 0xFA, 0xE5, 0x55, 0x21, 0x27, 0x86, 0x38, 0x4D, 0x72, + 0x0B, 0x5B, 0xFF, 0x98, 0x58, 0xEF, 0x87, 0xEB, 0x49, 0x56, 0x3B, 0x36, 0xF9, 0xFA, 0x45, 0x67, 0x0A, 0x1D, 0x23, 0x18, + 0x6C, 0x59, 0xBF, 0xFB, 0x6A, 0xF0, 0x40, 0xBD, 0xDD, 0xF6, 0x7E, 0x0F, 0xE8, 0x3C, 0xBE, 0xEB, 0xC7, 0x33, 0xE2, 0x97, + 0xC9, 0x1D, 0xB5, 0xAC, 0x36, 0x81, 0x8E, 0x28, 0xD9, 0xBD, 0xEE, 0x3A, 0x2B, 0xB0, 0x26, 0x7A, 0x6A, 0x9A, 0x25, 0xD8, + 0xF6, 0xC0, 0x4F, 0xD8, 0x56, 0xDF, 0x57, 0x25, 0x38, 0xB5, 0x37, 0xA9, 0x04, 0xD3, 0xB0, 0x12, 0x0F, 0xE8, 0xDD, 0xAA, + 0xCF, 0x73, 0x37, 0x35, 0x63, 0xB4, 0x67, 0x29, 0x1C, 0x50, 0x38, 0x02, 0x0A, 0xA9, 0xDF, 0x71, 0x51, 0x89, 0xA6, 0xDC, + 0x30, 0x74, 0x30, 0xE2, 0x48, 0x3B, 0xF4, 0xD6, 0x6E, 0x31, 0xEC, 0xC2, 0x7B, 0x4E, 0x7C, 0x0D, 0x77, 0xDC, 0xA8, 0xCF, + 0x45, 0x80, 0x1B, 0xC5, 0xD9, 0xEC, 0xA7, 0x70, 0xB1, 0xE0, 0xF5, 0x18, 0xB2, 0x36, 0x35, 0x07, 0xBB, 0xC2, 0xCF, 0x21, + 0x35, 0x61, 0xB9, 0x71, 0xC6, 0x5C, 0xB1, 0x9A, 0x8B, 0x0E, 0x63, 0x2A, 0xB9, 0x81, 0x46, 0x45, 0x2E, 0xA1, 0x98, 0x4A, + 0xEF, 0xB5, 0x60, 0x3B, 0x70, 0xA2, 0x58, 0x80, 0xC7, 0xA0, 0x6E, 0x83, 0xEB, 0xEB, 0x32, 0x3B, 0x73, 0xC7, 0xED, 0xA6, + 0x93, 0xAA, 0x26, 0xB0, 0x45, 0x87, 0x22, 0x86, 0x5F, 0xEA, 0x99, 0x67, 0xF1, 0xA6, 0xB1, 0xCF, 0xB4, 0xB6, 0x59, 0x65, + 0x47, 0xC8, 0xE3, 0x0B, 0xD0, 0x0F, 0x75, 0x98, 0x26, 0x38, 0x5D, 0xA7, 0x96, 0xA8, 0xB0, 0x4C, 0x44, 0xC9, 0x46, 0xF3, + 0xBA, 0xE2, 0x5A, 0x68, 0x4D, 0xC8, 0xF0, 0x23, 0xF7, 0xEC, 0xAC, 0x78, 0xED, 0x17, 0xED, 0xD3, 0x5A, 0xC3, 0x55, 0xF8, + 0xAC, 0x01, 0x0E, 0x7C, 0xE2, 0x04, 0x9A, 0x48, 0x2F, 0x6E, 0x3A, 0xC7, 0x22, 0x44, 0x5B, 0x2F, 0x2D, 0x00, 0x99, 0xBE, + 0xB2, 0x05, 0x69, 0x03, 0xB0, 0x65, 0x9A, 0xD0, 0xA7, 0xAA, 0x2F, 0xF9, 0xA9, 0x84, 0x7B, 0x32, 0x76, 0xEF, 0x45, 0x3C, + 0x38, 0xC4, 0xA3, 0xD0, 0x24, 0x9A, 0xDD, 0x0D, 0xD4, 0x84, 0xC2, 0x5B, 0x7D, 0x88, 0x1A, 0x6C, 0xCD, 0xA8, 0xC9, 0x8C, + 0xF2, 0x51, 0xD5, 0xAA, 0xE3, 0x5C, 0x92, 0xF8, 0x0F, 0xEC, 0xAA, 0xF8, 0x4E, 0xAA, 0x16, 0xEC, 0x5B, 0xE5, 0x61, 0x57, + 0x78, 0x4E, 0x9B, 0x68, 0xFD, 0xA2, 0x1B, 0x89, 0x4D, 0xC3, 0x8B, 0x4B, 0x37, 0xE7, 0x15, 0x5D, 0x6E, 0x0C, 0x8B, 0x1F, + 0x21, 0x22, 0x41, 0x99, 0x4D, 0xC7, 0xF8, 0x0C, 0xFE, 0x69, 0xAC, 0x56, 0xC5, 0x9F, 0xCD, 0x6D, 0xCB, 0x3B, 0x5C, 0x2A, + 0x62, 0x6B, 0xCA, 0x92, 0x17, 0xA9, 0x66, 0x69, 0x86, 0x97, 0x83, 0xE9, 0x96, 0x01, 0x06, 0x50, 0xE7, 0xF9, 0x66, 0xD4, + 0x8A, 0x9F, 0x45, 0x23, 0xFA, 0x9F, 0x3F, 0xBE, 0xB2, 0x9B, 0x0C, 0x21, 0xE5, 0xB5, 0xA3, 0x93, 0xF2, 0x1B, 0x7D, 0x0A, + 0x44, 0x9C, 0xDA, 0x01, 0x6E, 0xF2, 0x99, 0xD1, 0xA4, 0xF3, 0xDF, 0xB6, 0xF4, 0xC3, 0x06, 0xD3, 0x27, 0x39, 0x3B, 0x20, + 0x26, 0x3F, 0x4C, 0x32, 0x3A, 0x5C, 0x0F, 0xC2, 0x97, 0x6B, 0x97, 0x22, 0x5F, 0x44, 0xCC, 0x30, 0x04, 0x2E, 0x0E, 0x8C, + 0xC4, 0xB0, 0x5C, 0x84, 0x01, 0x5A, 0xF5, 0xFC, 0x8F, 0x1B, 0x1A, 0x21, 0x57, 0xAD, 0x7D, 0x01, 0x64, 0xDE, 0xB2, 0x98, + 0x8E, 0x59, 0xAD, 0xB2, 0x4D, 0x6A, 0x15, 0xF3, 0x84, 0x5B, 0xC2, 0x11, 0xC3, 0x23, 0x59, 0x95, 0x87, 0x68, 0x46, 0x94, + 0x49, 0x95, 0x7D, 0x1D, 0x43, 0xB1, 0x4E, 0x68, 0xEF, 0xD6, 0x09, 0x1C, 0x78, 0x58, 0xEE, 0x7B, 0xC1, 0xDB, 0x7C, 0x6C, + 0x0E, 0x4E, 0x46, 0x78, 0xCC, 0x9A, 0xD6, 0xAF, 0x19, 0x54, 0x47, 0x2B, 0xB2, 0x95, 0x67, 0xCB, 0xBB, 0xF8, 0x97, 0x69, + 0x60, 0xD4, 0x00, 0x9B, 0xFA, 0x30, 0x6B, 0xFD, 0xE7, 0x31, 0x6F, 0x2B, 0x16, 0xA0, 0x05, 0x45, 0x8E, 0x1F, 0x2D, 0xF8, + 0x3F, 0x5B, 0x1E, 0x3A, 0x09, 0x4D, 0x5E, 0xDE, 0x99, 0xFE, 0x61, 0x6E, 0x2F, 0x15, 0xC9, 0x0E, 0xD5, 0x00, 0x16, 0x2A, + 0x73, 0x6C, 0x56, 0x19, 0xFD, 0xFD, 0xBE, 0x8F, 0x08, 0x70, 0xDA, 0xB3, 0xDE, 0xF4, 0xA7, 0xAA, 0x27, 0x13, 0xB8, 0x9B, + 0x8D, 0x52, 0x2D, 0xEC, 0x86, 0x6F, 0xCC, 0xB0, 0xDA, 0xF8, 0x90, 0xC7, 0x59, 0xCF, 0xE7, 0xD7, 0xB9, 0x7E, 0xE6, 0x19, + 0x8C, 0x6B, 0x7B, 0xFB, 0x98, 0x4E, 0x3E, 0x1D, 0xE3, 0x09, 0x78, 0x86, 0x11, 0x57, 0x6F, 0xA4, 0x7B, 0x37, 0x07, 0xDB, + 0xB1, 0xE3, 0xC8, 0xE9, 0x31, 0x40, 0x39, 0x30, 0x93, 0x22, 0x60, 0xB2, 0x9C, 0x3E, 0x3C, 0x4F, 0xF2, 0x20, 0x85, 0x05, + 0xD1, 0x37, 0xF9, 0x15, 0x33, 0x6C, 0x81, 0xA3, 0x1D, 0xCD, 0x41, 0x3A, 0x54, 0xCD, 0x37, 0xD8, 0x0C, 0x85, 0x0D, 0x67, + 0x32, 0x20, 0xA6, 0xD3, 0x43, 0xBF, 0xDF, 0xFC, 0x38, 0x59, 0x9F, 0x41, 0x06, 0x9D, 0x3F, 0xBB, 0xED, 0xDB, 0xAF, 0x9F, + 0xBD, 0xBB, 0x2F, 0x9B, 0xAD, 0x9B, 0x11, 0xC6, 0xE4, 0x44, 0x37, 0xAB, 0xEC, 0xDA, 0xA7, 0x8F, 0xBC, 0xBA, 0x27, 0x8B, + 0xAC, 0x9A, 0xF8, 0x3E, 0xE2, 0xE6, 0x3E, 0xBA, 0x6D, 0xD9, 0xAE, 0x9E, 0x3D, 0xB9, 0x2E, 0x9A, 0x2D, 0x99, 0xB6, 0xAE, + 0x7C, 0xF8, 0x36, 0xAA, 0x6C, 0xD8, 0xA6, 0x8E, 0x3C, 0xB8, 0x26, 0x8A, 0x2C, 0x98, 0xC1, 0xC8, 0x50, 0xBD, 0x7D, 0xF7, + 0x9A, 0x2B, 0xEB, 0x53, 0xEB, 0x4E, 0x52, 0xD5, 0x36, 0x65, 0xCA, 0xE1, 0x67, 0xD4, 0x1A, 0x6E, 0x1F, 0xB2, 0x0C, 0x5A, + 0x21, 0x44, 0x0A, 0xBE, 0x58, 0x11, 0x4E, 0x18, 0x93, 0xB7, 0x07, 0xFD, 0x90, 0x25, 0xBC, 0xC2, 0xEC, 0xB7, 0x68, 0x0A, + 0x79, 0x95, 0x73, 0x3E, 0x74, 0x04, 0xAD, 0xED, 0x91, 0x24, 0x09, 0xF6, 0xCF, 0xC3, 0xC1, 0x38, 0x7A, 0x6D, 0xBD, 0xB7, + 0xF5, 0xF3, 0x3D, 0xB3, 0xE5, 0xD3, 0xAD, 0x97, 0xB5, 0xB3, 0x2D, 0x93, 0xA5, 0x93, 0xB5, 0xA7, 0xF4, 0xF2, 0x35, 0xA3, + 0xE4, 0xD2, 0xA5, 0x87, 0xB4, 0xB2, 0x25, 0x83, 0xA4, 0x92, 0xBC, 0xB6, 0x75, 0xF1, 0x3C, 0xB2, 0x65, 0xD1, 0xAC, 0x96, + 0x35, 0xB1, 0x2C, 0x92, 0x25, 0x91, 0xB4, 0xA6, 0x74, 0xF0, 0x34, 0xA2, 0x64, 0xD0, 0xA4, 0x86, 0x34, 0xB0, 0x24, 0x82, + 0x24, 0x90, 0xC4, 0x75, 0x23, 0x52, 0xFC, 0x34, 0x92, 0x9F, 0x44, 0x5F, 0x9B, 0x56, 0x54, 0x25, 0xD5, 0xD2, 0xB9, 0xB4, + 0xC0, 0xEE, 0xD3, 0xF4, 0x8D, 0xFB, 0x24, 0x5B, 0x45, 0xDA, 0x5C, 0x55, 0xA3, 0x33, 0x5A, 0x3A, 0xA6, 0x5B, 0x21, 0xA1, + 0xC3, 0x94, 0x1D, 0x5E, 0x41, 0x53, 0xDB, 0x74, 0xBB, 0x33, 0x57, 0x75, 0xDD, 0x51, 0x3C, 0x44, 0xCE, 0x3A, 0x19, 0x35, + 0x92, 0xF7, 0xD9, 0xD3, 0xC5, 0x26, 0xBB, 0x3F, 0xDD, 0xEB, 0x3B, 0x3B, 0xCD, 0xCB, 0xAB, 0x1F, 0x9D, 0xAB, 0x2B, 0x1B, + 0x8D, 0x8B, 0xB3, 0x2F, 0xDC, 0xEA, 0x33, 0x2B, 0xCC, 0xCA, 0xA3, 0x0F, 0x9C, 0xAA, 0x23, 0x0B, 0x8C, 0x8A, 0xBA, 0x3E, + 0x5D, 0xE9, 0x3A, 0x3A, 0x4D, 0xC9, 0xAA, 0x1E, 0x1D, 0xA9, 0x2A, 0x1A, 0x0D, 0x89, 0xB2, 0x2E, 0x5C, 0xE8, 0x32, 0x2A, + 0x4C, 0xC8, 0xA2, 0x0E, 0x1C, 0xA8, 0x22, 0x0A, 0x0C, 0x88, 0x1A, 0xCB, 0x89, 0xC7, 0x5D, 0x03, 0x3C, 0x53, 0xAB, 0x4A, + 0xEA, 0xA4, 0x27, 0x82, 0x5C, 0x03, 0xF9, 0x94, 0x82, 0x59, 0x75, 0xEF, 0x18, 0xED, 0x9E, 0x40, 0xDF, 0x5F, 0xB7, 0x40, + 0xAB, 0x39, 0xAB, 0x0C, 0x0B, 0xEA, 0x66, 0x65, 0xB0, 0x77, 0x6E, 0xDA, 0xA1, 0x55, 0xCE, 0xDF, 0x03, 0x81, 0x52, 0xD5, + 0xDE, 0x1F, 0xF7, 0xAF, 0x42, 0x79, 0x97, 0x64, 0x8A, 0x3B, 0xC0, 0x5C, 0xFF, 0x63, 0xB9, 0x37, 0xD5, 0xE3, 0x39, 0x33, + 0xC5, 0xC3, 0xA9, 0x17, 0x95, 0xA3, 0x29, 0x13, 0x85, 0x83, 0xB1, 0x27, 0xD4, 0xE2, 0x31, 0x23, 0xC4, 0xC2, 0xA1, 0x07, + 0x94, 0xA2, 0x21, 0x03, 0x84, 0x82, 0xB8, 0x36, 0x55, 0xE1, 0x38, 0x32, 0x45, 0xC1, 0xA8, 0x16, 0x15, 0xA1, 0x28, 0x12, + 0x05, 0x81, 0xB0, 0x26, 0x54, 0xE0, 0x30, 0x22, 0x44, 0xC0, 0xA0, 0x06, 0x14, 0xA0, 0x20, 0x02, 0x04, 0x80, 0xB0, 0x22, + 0x1E, 0x82, 0xC0, 0x59, 0xA7, 0xDD, 0x34, 0xA6, 0x4E, 0x85, 0xB8, 0x6A, 0xB5, 0xEF, 0x4A, 0x2A, 0x17, 0xCC, 0xC8, 0x57, + 0xEC, 0xAC, 0xCB, 0xF5, 0x47, 0x34, 0x65, 0x0E, 0x2A, 0xE1, 0xCD, 0xEB, 0x74, 0xCF, 0xD9, 0x03, 0xE7, 0xF5, 0x68, 0x7E, + 0xC0, 0xE0, 0x21, 0x7C, 0x29, 0x5E, 0x33, 0x11, 0x47, 0xA7, 0xE3, 0xE9, 0x36, 0xC6, 0x3D, 0x74, 0x44, 0xCD, 0x62, 0x93, + 0xD1, 0x58, 0x9F, 0xBD, 0xF9, 0x7B, 0x1F, 0xB9, 0xE9, 0x5B, 0x8F, 0x9D, 0xB9, 0x3B, 0x0F, 0x99, 0xA9, 0x1B, 0x97, 0xAD, + 0xF8, 0x7A, 0x17, 0xA9, 0xE8, 0x5A, 0x87, 0x8D, 0xB8, 0x3A, 0x07, 0x89, 0xA8, 0x1A, 0x9E, 0xBC, 0x79, 0x79, 0x1E, 0xB8, + 0x69, 0x59, 0x8E, 0x9C, 0x39, 0x39, 0x0E, 0x98, 0x29, 0x19, 0x96, 0xAC, 0x78, 0x78, 0x16, 0xA8, 0x68, 0x58, 0x86, 0x8C, + 0x38, 0x38, 0x06, 0x88, 0x28, 0x18, 0x2A, 0x0E, 0x83, 0xC9, 0x9A, 0xDE, 0xEB, 0xEA, 0x32, 0xDB, 0x80, 0xE8, 0xEE, 0x75, + 0xA1, 0x54, 0xBE, 0x69, 0x52, 0x82, 0xD2, 0x1A, 0xFD, 0x28, 0x8D, 0x1E, 0xCF, 0xC1, 0x61, 0x9A, 0x59, 0x52, 0x8F, 0x2F, + 0x8A, 0xF1, 0xA9, 0x2B, 0xB8, 0x01, 0x33, 0xE9, 0x4F, 0x8C, 0x6E, 0xAF, 0xA3, 0x7B, 0x28, 0xEA, 0xD2, 0x74, 0xB3, 0xEC, + 0x19, 0x06, 0x86, 0xCB, 0xC5, 0xC4, 0xE7, 0xBB, 0xF6, 0x7D, 0x9D, 0xB5, 0xF1, 0x73, 0x1D, 0xB1, 0xE1, 0x53, 0x8D, 0x95, + 0xB1, 0x33, 0x0D, 0x91, 0xA1, 0x13, 0x95, 0xA5, 0xF0, 0x72, 0x15, 0xA1, 0xE0, 0x52, 0x85, 0x85, 0xB0, 0x32, 0x05, 0x81, + 0xA0, 0x12, 0x9C, 0xB4, 0x71, 0x71, 0x1C, 0xB0, 0x61, 0x51, 0x8C, 0x94, 0x31, 0x31, 0x0C, 0x90, 0x21, 0x11, 0x94, 0xA4, + 0x70, 0x70, 0x14, 0xA0, 0x60, 0x50, 0x84, 0x84, 0x30, 0x30, 0x04, 0x80, 0x20, 0x10, 0xFB, 0xD7, 0x5F, 0xFD, 0xF9, 0x29, + 0x10, 0x4D, 0x4C, 0x26, 0x01, 0x42, 0x4B, 0x5B, 0x13, 0x2B, 0x34, 0x87, 0xA7, 0xB9, 0x13, 0x0D, 0xCA, 0xF0, 0x3E, 0x50, + 0x41, 0x93, 0xDC, 0xF6, 0xDB, 0xFC, 0xE5, 0x6E, 0x01, 0x6F, 0x49, 0x1C, 0xB5, 0x32, 0x55, 0xE7, 0x68, 0x59, 0x35, 0xA3, + 0xCB, 0x61, 0x89, 0xF1, 0xE4, 0xB3, 0x01, 0xEC, 0x6B, 0x4C, 0xE0, 0x62, 0x9A, 0xDA, 0x42, 0xC5, 0x56, 0x0E, 0x9B, 0x3D, + 0xD9, 0x6B, 0x1B, 0x39, 0xC9, 0x4B, 0x8B, 0x1D, 0x99, 0x2B, 0x0B, 0x19, 0x89, 0x0B, 0x93, 0x2D, 0xD8, 0x6A, 0x13, 0x29, + 0xC8, 0x4A, 0x83, 0x0D, 0x98, 0x2A, 0x03, 0x09, 0x88, 0x0A, 0x9A, 0x3C, 0x59, 0x69, 0x1A, 0x38, 0x49, 0x49, 0x8A, 0x1C, + 0x19, 0x29, 0x0A, 0x18, 0x09, 0x09, 0x92, 0x2C, 0x58, 0x68, 0x12, 0x28, 0x48, 0x48, 0x82, 0x0C, 0x18, 0x28, 0x02, 0x08, + 0x08, 0x08, 0x5E, 0xAE, 0x1F, 0xB8, 0x36, 0x91, 0xB8, 0x6C, 0xED, 0x89, 0x6A, 0xE0, 0xCE, 0x8A, 0xF9, 0xA9, 0x0F, 0xEC, + 0xFB, 0x1B, 0x6B, 0xE5, 0x9E, 0xDC, 0xBE, 0x56, 0x61, 0x54, 0xE7, 0xF7, 0xDA, 0xB8, 0x9F, 0x75, 0x21, 0x81, 0x03, 0xE0, + 0x9D, 0x7A, 0x88, 0x2F, 0xC1, 0x0B, 0x1B, 0x5F, 0xF8, 0x0C, 0x09, 0xFB, 0x0E, 0x1E, 0x8F, 0x68, 0x99, 0x36, 0x41, 0x66, + 0xDE, 0xFB, 0xE6, 0x39, 0x18, 0x44, 0x99, 0x35, 0xD1, 0x63, 0x19, 0x31, 0xC1, 0x43, 0x89, 0x15, 0x91, 0x23, 0x09, 0x11, + 0x81, 0x03, 0x91, 0x25, 0xD0, 0x62, 0x11, 0x21, 0xC0, 0x42, 0x81, 0x05, 0x90, 0x22, 0x01, 0x01, 0x80, 0x02, 0x98, 0x34, + 0x51, 0x61, 0x18, 0x30, 0x41, 0x41, 0x88, 0x14, 0x11, 0x21, 0x08, 0x10, 0x01, 0x01, 0x90, 0x24, 0x50, 0x60, 0x10, 0x20, + 0x40, 0x40, 0x80, 0x04, 0x10, 0x20, 0x00, 0x00, 0x97, 0x4A, 0x80, 0x05, 0x76, 0x8D, 0xDE, 0x85, 0xB1, 0x8B, 0x52, 0x92, + 0x14, 0x40, 0xCE, 0xA1, 0x58, 0xCB, 0xAC, 0x72, 0x40, 0x81, 0x90, 0xE5, 0x5B, 0x21, 0x24, 0xB2, 0x41, 0xA7, 0xC6, 0xB5, + 0xD3, 0xCA, 0x7F, 0x19, 0x02, 0x2A, 0x41, 0x05, 0xFB, 0xA0, 0x19, 0x24, 0xC4, 0x62, 0x90, 0x05, 0x50, 0x48, 0x71, 0xEC, + 0xC1, 0x41, 0xD7, 0x1D, 0xB1, 0x88, 0x47, 0xD3, 0xCD, 0xC6, 0x59, 0x35, 0xBA, 0xE1, 0x7E, 0x48, 0xC0, 0x06, 0x3F, 0xBA, + 0x14, 0xE4, 0x46, 0xF1, 0xA9, 0xE6, 0xF9, 0x23, 0x7C, 0xE8, 0xFB, 0xC0, 0x05, 0xA5, 0x08, 0x40, 0x82, 0xA8, 0x1A, 0x03, + 0x5F, 0x4C, 0xF1, 0x73, 0x52, 0xE5, 0x49, 0xC5, 0x7E, 0xA4, 0xD4, 0xC1, 0xD6, 0xBB, 0xEA, 0xD0, 0x80, 0xE9, 0x9B, 0x78, + 0x93, 0x67, 0x05, 0x23, 0xEB, 0xA5, 0x36, 0xD1, 0xD7, 0xD2, 0x2F, 0xF3, 0xCA, 0x3A, 0xA3, 0xA1, 0x53, 0x47, 0x80, 0x6A, + 0x73, 0xDA, 0x87, 0x0C, 0x9A, 0x20, 0x3C, 0x2F, 0x20, 0x47, 0x82, 0xDD, 0x12, 0x68, 0x7A, 0x5E, 0xF5, 0x4B, 0xEA, 0x5C, + 0x0C, 0x26, 0x1A, 0x7B, 0x4D, 0x49, 0x9B, 0x1C, 0xD9, 0xA8, 0xDC, 0x08, 0x8E, 0x8A, 0x0E, 0xFD, 0x90, 0x25, 0x3D, 0x2E, + 0xE7, 0x0A, 0xCD, 0xA8, 0xD0, 0xC1, 0x89, 0x63, 0x0B, 0x23, 0x0B, 0x1C, 0x30, 0x80, 0xF1, 0x3D, 0xC9, 0xE4, 0xC5, 0xBC, + 0x5B, 0xC0, 0xBD, 0x3B, 0x48, 0x8F, 0x02, 0x5D, 0x8D, 0x6E, 0x08, 0x75, 0xE9, 0x4A, 0x58, 0x9A, 0x85, 0xE1, 0x74, 0x54, + 0x6A, 0xED, 0xB5, 0xA6, 0xE4, 0xF2, 0xDA, 0x9A, 0xEA, 0xB2, 0xD8, 0x74, 0x59, 0x6C, 0x03, 0xB7, 0x0A, 0x5E, 0x41, 0xF7, + 0x7B, 0x51, 0x5F, 0x07, 0x6B, 0xC6, 0xF3, 0x60, 0xD2, 0x2E, 0x53, 0x4C, 0x77, 0xAD, 0x0B, 0x4D, 0xB1, 0xA2, 0x11, 0x78, + 0x28, 0xC5, 0xD3, 0x7F, 0x59, 0x8F, 0xBF, 0xE2, 0x61, 0x50, 0x03, 0x75, 0x3A, 0x36, 0xBA, 0x51, 0x6A, 0x5C, 0x95, 0x84, + 0x1B, 0x40, 0x74, 0xE3, 0x71, 0x18, 0xCE, 0x1E, 0x5A, 0x93, 0x62, 0x20, 0x8A, 0xF3, 0xD8, 0x36, 0x1A, 0x33, 0x7D, 0xE3, + 0xE3, 0xCD, 0xDB, 0x01, 0xB0, 0x99, 0x4B, 0x25, 0xE0, 0xDF, 0x95, 0xA7, 0xB2, 0xD9, 0x4C, 0x6C, 0xC7, 0x51, 0x8D, 0x64, + 0xA1, 0x23, 0x43, 0xB9, 0xC1, 0xFC, 0x9D, 0x44, 0xB3, 0x7D, 0x3A, 0xCD, 0xAD, 0xB9, 0x04, 0xD0, 0xC3, 0x2F, 0x6C, 0xB0, + 0x66, 0x5B, 0xEE, 0x63, 0xDE, 0x2B, 0x4D, 0x42, 0x23, 0x1D, 0xB3, 0x56, 0xB3, 0x35, 0x26, 0x20, 0x6B, 0x8A, 0xE6, 0x73, + 0xDF, 0x69, 0x40, 0x53, 0x22, 0xBB, 0x3A, 0xB7, 0x55, 0x28, 0x6D, 0x1E, 0xA1, 0x76, 0xEF, 0x62, 0x5E, 0x69, 0x09, 0x20, + 0xB7, 0x13, 0x12, 0xD5, 0xC4, 0x3D, 0xE2, 0x21, 0x14, 0x8F, 0xF3, 0xF3, 0x62, 0x2B, 0x84, 0x62, 0x57, 0x10, 0xD8, 0x85, + 0x38, 0x78, 0x13, 0x2A, 0x69, 0x20, 0xC8, 0x3D, 0x78, 0xF5, 0x70, 0x1A, 0x28, 0xFE, 0xEE, 0x6D, 0x3F, 0x39, 0x26, 0x49, + 0x6F, 0x59, 0xDE, 0x4F, 0x61, 0x7F, 0xDC, 0x8D, 0xAE, 0xBA, 0x83, 0xEE, 0xD3, 0x18, 0x37, 0x3D, 0x83, 0x78, 0xE9, 0x28, + 0x93, 0x6A, 0x55, 0x98, 0x0A, 0xB4, 0xD1, 0x0D, 0x19, 0x90, 0x41, 0x29, 0xC9, 0xF0, 0x97, 0xF0, 0x9A, 0x1B, 0x1C, 0xCA, + 0x42, 0x2C, 0xFC, 0x2E, 0x96, 0xC2, 0x2E, 0x19, 0x3A, 0x7C, 0xF8, 0xEB, 0xEF, 0x73, 0x18, 0xD0, 0xC0, 0x0D, 0xFE, 0x62, + 0x50, 0x09, 0x26, 0x8B, 0x3B, 0x56, 0xF7, 0xB2, 0xB2, 0x19, 0x39, 0xC0, 0xC9, 0xE1, 0xBC, 0x13, 0x0D, 0x95, 0x37, 0x29, + 0x24, 0xD3, 0x63, 0xA7, 0x33, 0x3A, 0x6F, 0xCD, 0x63, 0x2F, 0xCF, 0x2C, 0x33, 0xC0, 0x24, 0x99, 0xBC, 0x54, 0x76, 0x22, + 0x42, 0xA1, 0x9D, 0xF2, 0x58, 0x8F, 0xE4, 0x84, 0x7F, 0xE2, 0xB0, 0x23, 0x44, 0x80, 0x70, 0x26, 0x3F, 0x62, 0x22, 0x16, + 0xA6, 0x8C, 0xF6, 0x87, 0x15, 0x0A, 0x68, 0x36, 0x4D, 0xE9, 0xE6, 0xB3, 0x5D, 0x4A, 0x41, 0x42, 0x31, 0x8F, 0xA1, 0xF6, + 0xD6, 0xA6, 0x35, 0xBE, 0xC0, 0xE2, 0xB9, 0xD6, 0x9E, 0xE2, 0xD6, 0xC3, 0x8D, 0x0C, 0xA8, 0x97, 0x15, 0xA2, 0xB9, 0x32, + 0x82, 0x83, 0xB8, 0x17, 0x55, 0xA1, 0xD3, 0xD2, 0x00, 0x24, 0x1D, 0xBD, 0xE5, 0x5B, 0x74, 0x9C, 0xBB, 0x4E, 0xF2, 0x14, + 0x21, 0xC4, 0x32, 0x4F, 0xA4, 0x83, 0xD2, 0xB9, 0xEC, 0x3A, 0xF0, 0x4E, 0xA6, 0xCA, 0x07, 0xA6, 0x29, 0xE6, 0x2D, 0xC1, + 0x8F, 0xFB, 0x1A, 0xC3, 0x9A, 0xCB, 0x8A, 0x3F, 0x65, 0xC0, 0x15, 0x07, 0x24, 0x83, 0x65, 0x3D, 0x26, 0x0F, 0x16, 0xA9, + 0x91, 0x27, 0x19, 0x33, 0xDA, 0x4C, 0xC7, 0x7E, 0x94, 0x15, 0x68, 0x0B, 0xFB, 0x75, 0xFC, 0x8F, 0x9E, 0x03, 0x36, 0x5A, + 0x48, 0xE8, 0xEC, 0xAF, 0xDE, 0x43, 0x4A, 0x5B, 0xF0, 0x02, 0xCA, 0xEF, 0x57, 0xA9, 0xBA, 0x3B, 0x9F, 0x89, 0xA2, 0xCF, + 0x17, 0xE9, 0x69, 0xF5, 0xD9, 0x85, 0x63, 0x0F, 0xF7, 0x28, 0x6D, 0x2F, 0xC4, 0xDE, 0x73, 0x2F, 0xB7, 0x68, 0xAC, 0xF9, + 0x0F, 0xA3, 0xF5, 0x17, 0x8D, 0xAF, 0x3F, 0x99, 0xC9, 0xEB, 0xE5, 0xBA, 0xD5, 0x40, 0xE2, 0xA8, 0xAF, 0x73, 0x3A, 0x3C, + 0xE1, 0x73, 0xF6, 0x88, 0xCC, 0xC4, 0x09, 0x1C, 0xD0, 0x89, 0x6E, 0xA4, 0xF2, 0x07, 0x68, 0xDE, 0x19, 0x6D, 0x76, 0x05, + 0x2C, 0x3D, 0xB0, 0x3C, 0x37, 0xE0, 0x29, 0x4A, 0x6D, 0x04, 0x23, 0x5E, 0x95, 0xEC, 0xFA, 0x19, 0x6D, 0xC8, 0xEB, 0x6E, + 0x8A, 0x12, 0x90, 0x07, 0x2C, 0x02, 0x63, 0x7B, 0x1A, 0x5A, 0x03, 0xF9, 0xC6, 0x12, 0xE3, 0x55, 0xDE, 0xF8, 0x55, 0x44, + 0xD4, 0xDE, 0xE2, 0x86, 0xB4, 0xD3, 0x72, 0xA2, 0x0F, 0xC0, 0xCC, 0x24, 0x7D, 0x8D, 0x76, 0x93, 0x86, 0x97, 0x6C, 0x96, + 0x5E, 0x33, 0x5C, 0xF2, 0x78, 0x5C, 0xB0, 0xD8, 0xD4, 0x79, 0x92, 0x01, 0xA1, 0x63, 0xFB, 0x06, 0x36, 0x19, 0x25, 0x52, + 0xFC, 0xD2, 0xEF, 0xBA, 0x57, 0xF4, 0xA5, 0xAF, 0x06, 0x95, 0x85, 0x66, 0xFF, 0xB3, 0x45, 0x31, 0xE4, 0x8B, 0x3D, 0x55, + 0x54, 0x0C, 0xE5, 0x33, 0x3A, 0xB4, 0x64, 0xC3, 0xE0, 0xF4, 0x3F, 0x0D, 0x9D, 0x2B, 0x4A, 0xE4, 0x80, 0x20, 0x5F, 0x42, + 0xDB, 0xD7, 0x58, 0x3C, 0xD6, 0xD3, 0xBC, 0xE6, 0x44, 0x97, 0x7B, 0xED, 0x75, 0xBB, 0xD0, 0xCF, 0x5E, 0x34, 0xE5, 0xC2, + 0x57, 0xD0, 0x8E, 0x67, 0xA2, 0x58, 0xF2, 0xF8, 0xA2, 0x62, 0xDE, 0x52, 0xA1, 0x17, 0x59, 0x97, 0xBB, 0x78, 0x7B, 0x0A, + 0x98, 0x87, 0x8B, 0xB1, 0x51, 0xBB, 0x6E, 0x1D, 0x8D, 0x91, 0xF8, 0x86, 0x3E, 0xBC, 0x34, 0x48, 0x68, 0xF8, 0xFC, 0xAF, + 0x9F, 0x72, 0x16, 0x69, 0x39, 0x14, 0xF0, 0x1A, 0x3D, 0x34, 0x60, 0x3E, 0x6D, 0x72, 0x45, 0xE2, 0xDE, 0x97, 0xDE, 0x09, + 0xAF, 0x7C, 0xA8, 0x7E, 0xB6, 0xBC, 0x0B, 0x5A, 0xE6, 0xD6, 0xB3, 0x51, 0x01, 0x70, 0x51, 0x1E, 0x44, 0xCB, 0xD1, 0x0F, + 0x56, 0x19, 0x7D, 0xFB, 0x6D, 0xEB, 0x81, 0xB6, 0x3F, 0xFB, 0xBE, 0xF5, 0x3A, 0x47, 0xC6, 0xCF, 0x99, 0xAC, 0xB6, 0xFE, + 0x79, 0x9E, 0x82, 0x13, 0x40, 0xBE, 0x10, 0x5E, 0xDA, 0x3E, 0xD4, 0x59, 0x93, 0xA2, 0x7E, 0x7E, 0x2B, 0x79, 0x3E, 0xEA, + 0x83, 0x08, 0x67, 0xB4, 0xC6, 0xDC, 0x08, 0x3D, 0x3E, 0x8F, 0xF5, 0x65, 0xE8, 0xDE, 0x75, 0xD0, 0x02, 0x9C, 0x2B, 0x28, + 0xA5, 0x62, 0xA5, 0xCA, 0xDF, 0x2F, 0xBF, 0xEA, 0x3D, 0x52, 0xF8, 0x7B, 0xBB, 0x0A, 0xB7, 0x1C, 0x06, 0xC0, 0x24, 0x66, + 0x33, 0x40, 0x63, 0x66, 0xEA, 0xBB, 0x94, 0x63, 0xD2, 0x68, 0x78, 0x56, 0xA3, 0xFF, 0x68, 0x1C, 0x33, 0x31, 0xAF, 0xB5, + 0x47, 0x81, 0xBE, 0xEF, 0x05, 0xC5, 0xB6, 0xFC, 0x90, 0x4C, 0x6D, 0x07, 0x98, 0x4E, 0x91, 0xA5, 0x84, 0xB7, 0xA0, 0x47, + 0x3B, 0xD2, 0xF0, 0x57, 0x6B, 0xA7, 0x8C, 0x06, 0xDF, 0x67, 0xAE, 0x0E, 0x9D, 0x01, 0x72, 0x28, 0x19, 0x9D, 0x38, 0x22, + 0x41, 0xF4, 0x2F, 0x36, 0xB1, 0x65, 0xE3, 0x79, 0xBE, 0x94, 0xD0, 0x64, 0x52, 0x64, 0x40, 0xE2, 0xF6, 0x0A, 0xB0, 0x73, + 0x37, 0x25, 0x5C, 0x37, 0xC1, 0x4D, 0xD8, 0x74, 0x53, 0x65, 0x4B, 0x01, 0x21, 0x00, 0xC5, 0x65, 0x92, 0x26, 0xC1, 0xA6, + 0xC0, 0xB3, 0xD1, 0x65, 0xD2, 0x66, 0xFD, 0x2E, 0x20, 0x46, 0xC9, 0x55, 0x93, 0x27, 0xEB, 0x13, 0x28, 0xF7, 0xD9, 0x75, + 0xD3, 0x67, 0x42, 0x0E, 0xC0, 0xF8, 0xA4, 0x98, 0x94, 0xA3, 0x90, 0x17, 0xB4, 0x4A, 0xD2, 0xAA, 0xA4, 0x9D, 0x08, 0xDE, + 0xAB, 0x4C, 0x71, 0x3A, 0x09, 0xA4, 0x99, 0x3E, 0x81, 0xF9, 0x19, 0x06, 0x01, 0x28, 0xA7, 0xF5, 0x08, 0xF1, 0x87, 0xEF, + 0x9E, 0xEA, 0xD3, 0x3D, 0x34, 0xEE, 0xD3, 0x13, 0x84, 0xDF, 0x79, 0xBC, 0x2D, 0xEC, 0x5F, 0xE2, 0x1A, 0x25, 0xBF, 0x5B, + 0x65, 0xB4, 0x77, 0xBD, 0x25, 0x4B, 0xAA, 0xFB, 0x8F, 0x4B, 0xC2, 0x4C, 0x1A, 0x2C, 0x74, 0xB7, 0x1E, 0x0A, 0xD2, 0x6C, + 0x5A, 0x6C, 0x3E, 0xA5, 0x2A, 0x4F, 0xCA, 0x5C, 0x1B, 0x2D, 0xD9, 0x5C, 0xC4, 0x4F, 0xDA, 0x7C, 0x5B, 0x6D, 0x83, 0x5D, + 0x78, 0x42, 0xC3, 0x4D, 0x9A, 0x2E, 0xE4, 0x57, 0x92, 0xBB, 0xD3, 0x6D, 0xDA, 0x6E, 0xC9, 0x66, 0x0E, 0x08, 0xCB, 0x5D, + 0x9B, 0x2F, 0xEC, 0x78, 0x46, 0x49, 0xDB, 0x7D, 0xDB, 0x6F, 0x80, 0x04, 0x64, 0xE5, 0x0C, 0x86, 0xC5, 0x3F, 0x74, 0xE4, + 0x6F, 0x5D, 0xBC, 0x66, 0xF2, 0x78, 0xBB, 0xAF, 0x79, 0x53, 0x48, 0x11, 0x72, 0xC2, 0x94, 0xC8, 0x80, 0x5E, 0xFC, 0xF4, + 0x8A, 0x7C, 0x3F, 0x7E, 0xA6, 0xD2, 0x31, 0xFA, 0x13, 0x8F, 0x5F, 0x7E, 0x43, 0x54, 0x7A, 0x55, 0xA8, 0x7D, 0x8F, 0xAE, + 0x5D, 0xC3, 0xED, 0xD1, 0x8C, 0x3C, 0x7D, 0xF5, 0xD8, 0x5C, 0xEF, 0xAC, 0xB1, 0x88, 0x3C, 0xE4, 0xA7, 0x33, 0xC4, 0xC4, + 0x32, 0x34, 0x94, 0xF4, 0x9E, 0x18, 0xD4, 0xE4, 0x72, 0x74, 0xFB, 0x2D, 0x33, 0x5B, 0xCC, 0xD4, 0x33, 0x35, 0xF4, 0x53, + 0x1C, 0xD5, 0xDC, 0xF4, 0x73, 0x75, 0x9A, 0xD0, 0xA4, 0xD6, 0xC5, 0xC5, 0xB2, 0x36, 0x25, 0x27, 0x48, 0x17, 0xD5, 0xE5, + 0xF2, 0x76, 0x3D, 0xF7, 0x41, 0x74, 0xCD, 0xD5, 0xB3, 0x37, 0x9D, 0xE5, 0x1F, 0x1B, 0xDD, 0xF5, 0xF3, 0x77, 0xC6, 0x9C, + 0xD4, 0xBC, 0x16, 0x92, 0x60, 0xCC, 0xA2, 0x4A, 0xEA, 0x10, 0x92, 0xAE, 0x7C, 0x83, 0xAA, 0x65, 0xA9, 0xC2, 0x7E, 0x18, + 0x7D, 0xAE, 0x66, 0xDA, 0x2A, 0xE6, 0x29, 0x98, 0xFC, 0x5E, 0x47, 0x8F, 0x60, 0xEA, 0x04, 0x4B, 0x52, 0x76, 0xDB, 0xCB, + 0xAB, 0x85, 0x97, 0x6F, 0x7B, 0x3C, 0x0E, 0x5F, 0x0B, 0x5E, 0x27, 0x3E, 0xC6, 0x3A, 0x67, 0xE6, 0x1C, 0xA7, 0x40, 0xAC, + 0xFF, 0xBB, 0xEE, 0x6A, 0xF5, 0xF3, 0xC6, 0xCC, 0x3A, 0x3C, 0x26, 0x2E, 0xC0, 0x1D, 0xD6, 0xEC, 0x7A, 0x7C, 0xB1, 0xFC, + 0xA9, 0x15, 0xCE, 0xDC, 0x3B, 0x3D, 0xF2, 0xBA, 0xE8, 0x53, 0xDE, 0xFC, 0x7B, 0x7D, 0xEF, 0x6B, 0x2D, 0x39, 0xC7, 0xCD, + 0xBA, 0x3E, 0xBB, 0x69, 0x16, 0x7E, 0xD7, 0xED, 0xFA, 0x7E, 0xF9, 0xBB, 0x5C, 0x19, 0xCF, 0xDD, 0xBB, 0x3F, 0x37, 0x7F, + 0x17, 0x1E, 0xDF, 0xFD, 0xFB, 0x7F, 0xF4, 0x44, 0xA6, 0x7E, 0x40, 0x39, 0x30, 0x1C, 0xF0, 0x36, 0xB8, 0xBE, 0x1C, 0xA4, + 0x55, 0x65, 0xC3, 0x69, 0x9A, 0xBC, 0x2C, 0xE7, 0xB6, 0xA3, 0x4C, 0xB6, 0x0D, 0x9F, 0xD7, 0x2A, 0x9D, 0x3F, 0x5B, 0x87, + 0xC8, 0x92, 0x1E, 0x5C, 0x6D, 0x28, 0x48, 0x65, 0x66, 0x8C, 0x89, 0xD4, 0x8C, 0x46, 0x81, 0xB1, 0x02, 0xA4, 0x9B, 0xE8, + 0x17, 0xEB, 0xF9, 0x27, 0x54, 0x82, 0x3E, 0x24, 0x0A, 0xE1, 0x88, 0xE1, 0x00, 0x24, 0xE0, 0x46, 0x16, 0xA4, 0x78, 0x50, + 0xE7, 0x6B, 0xF0, 0x66, 0x56, 0xE4, 0xF8, 0xD0, 0x06, 0xF2, 0xE8, 0x56, 0x17, 0xA5, 0x98, 0x4D, 0xB3, 0x75, 0xF8, 0x76, + 0x57, 0xE5, 0x88, 0xC7, 0xC2, 0x9A, 0xE1, 0x47, 0x96, 0xA6, 0x76, 0x70, 0x1D, 0x16, 0xF1, 0x67, 0xD6, 0xE6, 0x53, 0xB1, + 0x05, 0x8F, 0xE9, 0x57, 0x97, 0xA7, 0xCE, 0x6F, 0xE3, 0x3A, 0xF9, 0x77, 0xD7, 0xE7, 0xB2, 0x14, 0x54, 0x7C, 0x82, 0x6C, + 0xAB, 0xCD, 0x99, 0x51, 0x99, 0x35, 0x52, 0x11, 0xA0, 0xEA, 0x6A, 0xDC, 0xE7, 0xC5, 0x13, 0x4F, 0xBE, 0x76, 0x62, 0x07, + 0xCF, 0xC1, 0x89, 0x27, 0x79, 0x87, 0xA0, 0x11, 0xD0, 0x3E, 0x9B, 0xDF, 0x41, 0xD5, 0x71, 0x4B, 0xD4, 0x4A, 0x00, 0x32, + 0x24, 0x3A, 0xDB, 0x5D, 0x27, 0x70, 0x16, 0x42, 0x62, 0xAD, 0xEF, 0x49, 0x6E, 0x8A, 0xFB, 0x00, 0xD5, 0x87, 0x93, 0x28, + 0x4D, 0x53, 0xE2, 0x4E, 0x1E, 0xAC, 0xAD, 0x62, 0x60, 0x8A, 0xF2, 0x6E, 0x5E, 0xEC, 0x12, 0xD8, 0x0E, 0x9A, 0xEA, 0x5E, + 0x1F, 0xAD, 0x0A, 0xA5, 0xA0, 0x8C, 0xFA, 0x7E, 0x5F, 0xED, 0x1B, 0x29, 0xCD, 0x7E, 0xE3, 0x4F, 0x9E, 0xAE, 0x81, 0xAD, + 0x6C, 0x82, 0xF3, 0x6F, 0xDE, 0xEE, 0xD0, 0xB9, 0x23, 0x72, 0xEB, 0x5F, 0x9F, 0xAF, 0xD3, 0xD8, 0xB0, 0x0F, 0xFB, 0x7F, + 0xDF, 0xEF, 0x56, 0x27, 0xA1, 0x97, 0x64, 0x92, 0xC8, 0x45, 0xF4, 0xB3, 0x48, 0xD6, 0x03, 0x5B, 0x38, 0xBE, 0x2D, 0x4D, + 0x86, 0xEF, 0x1B, 0x8F, 0x33, 0x71, 0x44, 0x96, 0xEA, 0xD3, 0x45, 0x70, 0xD7, 0xB4, 0xCE, 0x74, 0xA2, 0x72, 0x61, 0x03, + 0xF0, 0x47, 0x3D, 0x06, 0x87, 0xF2, 0xC5, 0xE1, 0x56, 0x0C, 0x16, 0xD5, 0x07, 0xDD, 0x1A, 0xA8, 0xE1, 0xF1, 0x8A, 0xB2, + 0x68, 0xDF, 0xCF, 0x31, 0xED, 0xBF, 0x6C, 0xF5, 0x87, 0xF8, 0xE4, 0xC6, 0x36, 0xB4, 0x14, 0xA2, 0x6A, 0x29, 0xF4, 0xE6, + 0x76, 0xF4, 0xE8, 0x15, 0xA7, 0xB5, 0xEC, 0xD6, 0x37, 0xB5, 0x26, 0xF3, 0xC4, 0x94, 0xFC, 0xF6, 0x77, 0xF5, 0x86, 0x84, + 0x78, 0x9E, 0xE5, 0xC7, 0xB6, 0xB6, 0x0D, 0x61, 0xE7, 0x96, 0xF5, 0xE7, 0xF6, 0xF6, 0xC1, 0x13, 0x04, 0xD6, 0xED, 0xD7, + 0xB7, 0xB7, 0x1D, 0xB3, 0xFA, 0x5C, 0xFD, 0xF7, 0xF7, 0xF7, 0x52, 0xAE, 0xF8, 0x28, 0x24, 0xB1, 0xB9, 0xBF, 0x5E, 0xB4, + 0x2A, 0x2C, 0xC6, 0x8E, 0x64, 0x35, 0x09, 0x1A, 0xAA, 0x3E, 0x47, 0x1A, 0x79, 0xA5, 0x81, 0xDA, 0xDA, 0x7D, 0x84, 0x5C, + 0xFF, 0xF1, 0x80, 0x97, 0x7C, 0x6A, 0x4F, 0x2C, 0xBA, 0x1A, 0xF1, 0x2F, 0xA4, 0xAD, 0x27, 0x2D, 0xFD, 0x1D, 0x87, 0x3D, + 0xAB, 0x5B, 0x3F, 0x58, 0xBF, 0x4E, 0xF9, 0xBD, 0x25, 0x19, 0x4D, 0xDD, 0xBE, 0x24, 0x8A, 0x4A, 0xD2, 0xBC, 0xE6, 0xCE, + 0x3E, 0xBC, 0xF2, 0x08, 0xEC, 0xD4, 0xF6, 0xEE, 0x7E, 0xFC, 0x56, 0x29, 0x77, 0x39, 0xEE, 0xDE, 0x3F, 0xBD, 0x1E, 0xBA, + 0xC2, 0x20, 0xFE, 0xFE, 0x7F, 0xFD, 0xCB, 0x49, 0xAF, 0xCB, 0xE7, 0xCF, 0xBE, 0xBE, 0xFE, 0x99, 0x4D, 0x9F, 0xF7, 0xEF, + 0xFE, 0xFE, 0x80, 0xC7, 0x29, 0x6A, 0xEF, 0xDF, 0xBF, 0xBF, 0x07, 0xDF, 0x6D, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x04, 0x10, 0x20, 0x10, 0x20, 0x40, 0x40, 0x90, 0x24, 0x50, 0x60, 0x08, 0x10, 0x01, 0x01, 0x88, 0x14, + 0x11, 0x21, 0x18, 0x30, 0x41, 0x41, 0x98, 0x34, 0x51, 0x61, 0x01, 0x01, 0x80, 0x02, 0x81, 0x05, 0x90, 0x22, 0x11, 0x21, + 0xC0, 0x42, 0x91, 0x25, 0xD0, 0x62, 0x09, 0x11, 0x81, 0x03, 0x89, 0x15, 0x91, 0x23, 0x19, 0x31, 0xC1, 0x43, 0x99, 0x35, + 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, 0x52, 0x64, 0x48, 0x50, + 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, 0x82, 0x06, 0xC1, 0x45, + 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, 0x93, 0x27, 0x59, 0x71, + 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0x02, 0x08, 0x08, 0x08, 0x82, 0x0C, 0x18, 0x28, 0x12, 0x28, 0x48, 0x48, 0x92, 0x2C, + 0x58, 0x68, 0x0A, 0x18, 0x09, 0x09, 0x8A, 0x1C, 0x19, 0x29, 0x1A, 0x38, 0x49, 0x49, 0x9A, 0x3C, 0x59, 0x69, 0x03, 0x09, + 0x88, 0x0A, 0x83, 0x0D, 0x98, 0x2A, 0x13, 0x29, 0xC8, 0x4A, 0x93, 0x2D, 0xD8, 0x6A, 0x0B, 0x19, 0x89, 0x0B, 0x8B, 0x1D, + 0x99, 0x2B, 0x1B, 0x39, 0xC9, 0x4B, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, 0x1A, 0x2C, 0x52, 0x68, + 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, 0x4B, 0x4D, 0xDA, 0x7C, + 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, 0xDA, 0x6E, 0x4B, 0x59, + 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, 0x20, 0x10, 0x84, 0x84, + 0x30, 0x30, 0x14, 0xA0, 0x60, 0x50, 0x94, 0xA4, 0x70, 0x70, 0x0C, 0x90, 0x21, 0x11, 0x8C, 0x94, 0x31, 0x31, 0x1C, 0xB0, + 0x61, 0x51, 0x9C, 0xB4, 0x71, 0x71, 0x05, 0x81, 0xA0, 0x12, 0x85, 0x85, 0xB0, 0x32, 0x15, 0xA1, 0xE0, 0x52, 0x95, 0xA5, + 0xF0, 0x72, 0x0D, 0x91, 0xA1, 0x13, 0x8D, 0x95, 0xB1, 0x33, 0x1D, 0xB1, 0xE1, 0x53, 0x9D, 0xB5, 0xF1, 0x73, 0x44, 0xC0, + 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, 0x23, 0x15, 0xCC, 0xD4, + 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, 0xB2, 0x36, 0x55, 0xE1, + 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, 0xE3, 0x57, 0xDD, 0xF5, + 0xF3, 0x77, 0x06, 0x88, 0x28, 0x18, 0x86, 0x8C, 0x38, 0x38, 0x16, 0xA8, 0x68, 0x58, 0x96, 0xAC, 0x78, 0x78, 0x0E, 0x98, + 0x29, 0x19, 0x8E, 0x9C, 0x39, 0x39, 0x1E, 0xB8, 0x69, 0x59, 0x9E, 0xBC, 0x79, 0x79, 0x07, 0x89, 0xA8, 0x1A, 0x87, 0x8D, + 0xB8, 0x3A, 0x17, 0xA9, 0xE8, 0x5A, 0x97, 0xAD, 0xF8, 0x7A, 0x0F, 0x99, 0xA9, 0x1B, 0x8F, 0x9D, 0xB9, 0x3B, 0x1F, 0xB9, + 0xE9, 0x5B, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, 0x6A, 0x5C, 0xD6, 0xEC, + 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, 0x7B, 0x7D, 0x47, 0xC9, + 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, 0xAB, 0x1F, 0xCF, 0xDD, + 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x20, 0x02, 0x04, 0x80, 0xA0, 0x06, 0x14, 0xA0, 0x30, 0x22, + 0x44, 0xC0, 0xB0, 0x26, 0x54, 0xE0, 0x28, 0x12, 0x05, 0x81, 0xA8, 0x16, 0x15, 0xA1, 0x38, 0x32, 0x45, 0xC1, 0xB8, 0x36, + 0x55, 0xE1, 0x21, 0x03, 0x84, 0x82, 0xA1, 0x07, 0x94, 0xA2, 0x31, 0x23, 0xC4, 0xC2, 0xB1, 0x27, 0xD4, 0xE2, 0x29, 0x13, + 0x85, 0x83, 0xA9, 0x17, 0x95, 0xA3, 0x39, 0x33, 0xC5, 0xC3, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, 0x06, 0x84, 0xE0, 0x46, + 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, 0x17, 0xA5, 0x78, 0x72, + 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, 0xC6, 0xC6, 0xF1, 0x67, + 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, 0xD7, 0xE7, 0x22, 0x0A, + 0x0C, 0x88, 0xA2, 0x0E, 0x1C, 0xA8, 0x32, 0x2A, 0x4C, 0xC8, 0xB2, 0x2E, 0x5C, 0xE8, 0x2A, 0x1A, 0x0D, 0x89, 0xAA, 0x1E, + 0x1D, 0xA9, 0x3A, 0x3A, 0x4D, 0xC9, 0xBA, 0x3E, 0x5D, 0xE9, 0x23, 0x0B, 0x8C, 0x8A, 0xA3, 0x0F, 0x9C, 0xAA, 0x33, 0x2B, + 0xCC, 0xCA, 0xB3, 0x2F, 0xDC, 0xEA, 0x2B, 0x1B, 0x8D, 0x8B, 0xAB, 0x1F, 0x9D, 0xAB, 0x3B, 0x3B, 0xCD, 0xCB, 0xBB, 0x3F, + 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, 0x5E, 0xEC, 0x6A, 0x5A, + 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, 0x8E, 0x8E, 0xE3, 0x4F, + 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, 0x9F, 0xAF, 0x7B, 0x7B, + 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x24, 0x82, 0x24, 0x90, 0xA4, 0x86, 0x34, 0xB0, 0x34, 0xA2, 0x64, 0xD0, 0xB4, 0xA6, + 0x74, 0xF0, 0x2C, 0x92, 0x25, 0x91, 0xAC, 0x96, 0x35, 0xB1, 0x3C, 0xB2, 0x65, 0xD1, 0xBC, 0xB6, 0x75, 0xF1, 0x25, 0x83, + 0xA4, 0x92, 0xA5, 0x87, 0xB4, 0xB2, 0x35, 0xA3, 0xE4, 0xD2, 0xB5, 0xA7, 0xF4, 0xF2, 0x2D, 0x93, 0xA5, 0x93, 0xAD, 0x97, + 0xB5, 0xB3, 0x3D, 0xB3, 0xE5, 0xD3, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, 0x36, 0xB4, 0x74, 0xE2, + 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, 0x67, 0xD5, 0xFC, 0xF6, + 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, 0xF6, 0xF6, 0x6D, 0xD3, + 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x8A, 0x2C, 0x98, 0xA6, 0x8E, + 0x3C, 0xB8, 0x36, 0xAA, 0x6C, 0xD8, 0xB6, 0xAE, 0x7C, 0xF8, 0x2E, 0x9A, 0x2D, 0x99, 0xAE, 0x9E, 0x3D, 0xB9, 0x3E, 0xBA, + 0x6D, 0xD9, 0xBE, 0xBE, 0x7D, 0xF9, 0x27, 0x8B, 0xAC, 0x9A, 0xA7, 0x8F, 0xBC, 0xBA, 0x37, 0xAB, 0xEC, 0xDA, 0xB7, 0xAF, + 0xFC, 0xFA, 0x2F, 0x9B, 0xAD, 0x9B, 0xAF, 0x9F, 0xBD, 0xBB, 0x3F, 0xBB, 0xED, 0xDB, 0xBF, 0xBF, 0xFD, 0xFB, 0x66, 0xCA, + 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, 0x2F, 0x9D, 0xEE, 0xDE, + 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, 0xBE, 0xBE, 0x77, 0xEB, + 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, 0xEF, 0xDF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x10, 0x20, 0x10, 0x20, 0x40, 0x40, 0x90, 0x24, 0x50, 0x60, 0x08, 0x10, + 0x01, 0x01, 0x88, 0x14, 0x11, 0x21, 0x18, 0x30, 0x41, 0x41, 0x98, 0x34, 0x51, 0x61, 0x01, 0x01, 0x80, 0x02, 0x81, 0x05, + 0x90, 0x22, 0x11, 0x21, 0xC0, 0x42, 0x91, 0x25, 0xD0, 0x62, 0x09, 0x11, 0x81, 0x03, 0x89, 0x15, 0x91, 0x23, 0x19, 0x31, + 0xC1, 0x43, 0x99, 0x35, 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, + 0x52, 0x64, 0x48, 0x50, 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, + 0x82, 0x06, 0xC1, 0x45, 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, + 0x93, 0x27, 0x59, 0x71, 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0x02, 0x08, 0x08, 0x08, 0x82, 0x0C, 0x18, 0x28, 0x12, 0x28, + 0x48, 0x48, 0x92, 0x2C, 0x58, 0x68, 0x0A, 0x18, 0x09, 0x09, 0x8A, 0x1C, 0x19, 0x29, 0x1A, 0x38, 0x49, 0x49, 0x9A, 0x3C, + 0x59, 0x69, 0x03, 0x09, 0x88, 0x0A, 0x83, 0x0D, 0x98, 0x2A, 0x13, 0x29, 0xC8, 0x4A, 0x93, 0x2D, 0xD8, 0x6A, 0x0B, 0x19, + 0x89, 0x0B, 0x8B, 0x1D, 0x99, 0x2B, 0x1B, 0x39, 0xC9, 0x4B, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, + 0x1A, 0x2C, 0x52, 0x68, 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, + 0x4B, 0x4D, 0xDA, 0x7C, 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, + 0xDA, 0x6E, 0x4B, 0x59, 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, + 0x20, 0x10, 0x84, 0x84, 0x30, 0x30, 0x14, 0xA0, 0x60, 0x50, 0x94, 0xA4, 0x70, 0x70, 0x0C, 0x90, 0x21, 0x11, 0x8C, 0x94, + 0x31, 0x31, 0x1C, 0xB0, 0x61, 0x51, 0x9C, 0xB4, 0x71, 0x71, 0x05, 0x81, 0xA0, 0x12, 0x85, 0x85, 0xB0, 0x32, 0x15, 0xA1, + 0xE0, 0x52, 0x95, 0xA5, 0xF0, 0x72, 0x0D, 0x91, 0xA1, 0x13, 0x8D, 0x95, 0xB1, 0x33, 0x1D, 0xB1, 0xE1, 0x53, 0x9D, 0xB5, + 0xF1, 0x73, 0x44, 0xC0, 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, + 0x23, 0x15, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, + 0xB2, 0x36, 0x55, 0xE1, 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, + 0xE3, 0x57, 0xDD, 0xF5, 0xF3, 0x77, 0x06, 0x88, 0x28, 0x18, 0x86, 0x8C, 0x38, 0x38, 0x16, 0xA8, 0x68, 0x58, 0x96, 0xAC, + 0x78, 0x78, 0x0E, 0x98, 0x29, 0x19, 0x8E, 0x9C, 0x39, 0x39, 0x1E, 0xB8, 0x69, 0x59, 0x9E, 0xBC, 0x79, 0x79, 0x07, 0x89, + 0xA8, 0x1A, 0x87, 0x8D, 0xB8, 0x3A, 0x17, 0xA9, 0xE8, 0x5A, 0x97, 0xAD, 0xF8, 0x7A, 0x0F, 0x99, 0xA9, 0x1B, 0x8F, 0x9D, + 0xB9, 0x3B, 0x1F, 0xB9, 0xE9, 0x5B, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, + 0x6A, 0x5C, 0xD6, 0xEC, 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, + 0x7B, 0x7D, 0x47, 0xC9, 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, + 0xAB, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x20, 0x02, 0x04, 0x80, 0xA0, 0x06, + 0x14, 0xA0, 0x30, 0x22, 0x44, 0xC0, 0xB0, 0x26, 0x54, 0xE0, 0x28, 0x12, 0x05, 0x81, 0xA8, 0x16, 0x15, 0xA1, 0x38, 0x32, + 0x45, 0xC1, 0xB8, 0x36, 0x55, 0xE1, 0x21, 0x03, 0x84, 0x82, 0xA1, 0x07, 0x94, 0xA2, 0x31, 0x23, 0xC4, 0xC2, 0xB1, 0x27, + 0xD4, 0xE2, 0x29, 0x13, 0x85, 0x83, 0xA9, 0x17, 0x95, 0xA3, 0x39, 0x33, 0xC5, 0xC3, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, + 0x06, 0x84, 0xE0, 0x46, 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, + 0x17, 0xA5, 0x78, 0x72, 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, + 0xC6, 0xC6, 0xF1, 0x67, 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, + 0xD7, 0xE7, 0x22, 0x0A, 0x0C, 0x88, 0xA2, 0x0E, 0x1C, 0xA8, 0x32, 0x2A, 0x4C, 0xC8, 0xB2, 0x2E, 0x5C, 0xE8, 0x2A, 0x1A, + 0x0D, 0x89, 0xAA, 0x1E, 0x1D, 0xA9, 0x3A, 0x3A, 0x4D, 0xC9, 0xBA, 0x3E, 0x5D, 0xE9, 0x23, 0x0B, 0x8C, 0x8A, 0xA3, 0x0F, + 0x9C, 0xAA, 0x33, 0x2B, 0xCC, 0xCA, 0xB3, 0x2F, 0xDC, 0xEA, 0x2B, 0x1B, 0x8D, 0x8B, 0xAB, 0x1F, 0x9D, 0xAB, 0x3B, 0x3B, + 0xCD, 0xCB, 0xBB, 0x3F, 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, + 0x5E, 0xEC, 0x6A, 0x5A, 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, + 0x8E, 0x8E, 0xE3, 0x4F, 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, + 0x9F, 0xAF, 0x7B, 0x7B, 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x24, 0x82, 0x24, 0x90, 0xA4, 0x86, 0x34, 0xB0, 0x34, 0xA2, + 0x64, 0xD0, 0xB4, 0xA6, 0x74, 0xF0, 0x2C, 0x92, 0x25, 0x91, 0xAC, 0x96, 0x35, 0xB1, 0x3C, 0xB2, 0x65, 0xD1, 0xBC, 0xB6, + 0x75, 0xF1, 0x25, 0x83, 0xA4, 0x92, 0xA5, 0x87, 0xB4, 0xB2, 0x35, 0xA3, 0xE4, 0xD2, 0xB5, 0xA7, 0xF4, 0xF2, 0x2D, 0x93, + 0xA5, 0x93, 0xAD, 0x97, 0xB5, 0xB3, 0x3D, 0xB3, 0xE5, 0xD3, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, + 0x36, 0xB4, 0x74, 0xE2, 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, + 0x67, 0xD5, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, + 0xF6, 0xF6, 0x6D, 0xD3, 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x8A, + 0x2C, 0x98, 0xA6, 0x8E, 0x3C, 0xB8, 0x36, 0xAA, 0x6C, 0xD8, 0xB6, 0xAE, 0x7C, 0xF8, 0x2E, 0x9A, 0x2D, 0x99, 0xAE, 0x9E, + 0x3D, 0xB9, 0x3E, 0xBA, 0x6D, 0xD9, 0xBE, 0xBE, 0x7D, 0xF9, 0x27, 0x8B, 0xAC, 0x9A, 0xA7, 0x8F, 0xBC, 0xBA, 0x37, 0xAB, + 0xEC, 0xDA, 0xB7, 0xAF, 0xFC, 0xFA, 0x2F, 0x9B, 0xAD, 0x9B, 0xAF, 0x9F, 0xBD, 0xBB, 0x3F, 0xBB, 0xED, 0xDB, 0xBF, 0xBF, + 0xFD, 0xFB, 0x66, 0xCA, 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, + 0x2F, 0x9D, 0xEE, 0xDE, 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, + 0xBE, 0xBE, 0x77, 0xEB, 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, + 0xEF, 0xDF, 0xFF, 0xFF, 0x90, 0xAF +}; +#endif + +/* +*[HW INFO]00900600 +*[PID]910 +*[VID]1010 +*[GENERATED]2013/08/27 20:59:13 +*/ +#if GTP_COMPATIBLE_MODE +unsigned char gtp_default_FW_fl[] = { + 0x00, 0x01, 0x60, 0x00, 0x39, 0x31, 0x37, 0x44, 0x00, 0x00, 0x00, 0x00, 0x50, 0x03, 0x80, 0x00, 0x55, 0x40, 0xBD, 0xDA, + 0xFD, 0x24, 0x34, 0xDF, 0x44, 0x40, 0x44, 0x02, 0xBE, 0x03, 0xB3, 0xB4, 0x27, 0x41, 0x8C, 0x90, 0x12, 0x21, 0x22, 0xB7, + 0xED, 0x5E, 0x58, 0x34, 0x17, 0xBF, 0x01, 0x08, 0x84, 0x92, 0x72, 0xFC, 0x81, 0xD9, 0x39, 0x25, 0xC8, 0xE2, 0x39, 0x87, + 0x0F, 0xED, 0x09, 0x1D, 0xC9, 0x1A, 0xE9, 0xD5, 0x5F, 0x2E, 0x23, 0xB6, 0x6D, 0x4B, 0xA6, 0xE6, 0xA3, 0x7E, 0x3F, 0x64, + 0xFB, 0x1B, 0x67, 0xA6, 0xF2, 0xB5, 0xF4, 0x02, 0xA9, 0x4B, 0x2B, 0x1F, 0x7C, 0xDB, 0x58, 0x96, 0x51, 0xDA, 0x75, 0x4A, + 0xB0, 0xA0, 0x5D, 0x1B, 0x2B, 0x01, 0x0C, 0x9B, 0x51, 0x8B, 0x3F, 0xA3, 0x77, 0x82, 0xEE, 0xF4, 0x31, 0xB9, 0xE5, 0x03, + 0xE6, 0x4C, 0xEA, 0xC0, 0x21, 0x1B, 0x7E, 0xB3, 0xE8, 0x08, 0x32, 0x7E, 0x30, 0x5A, 0x20, 0x67, 0x60, 0x57, 0x5D, 0xFE, + 0xD2, 0xE7, 0xD2, 0xAC, 0x2E, 0x48, 0x98, 0x22, 0x39, 0xB8, 0x96, 0xDE, 0xC8, 0x68, 0x3A, 0x8E, 0xDF, 0x4F, 0x9A, 0x18, + 0x09, 0x49, 0xC2, 0x8F, 0xF8, 0x26, 0x3A, 0x11, 0xA8, 0x2F, 0x35, 0x42, 0x84, 0x94, 0x48, 0x04, 0x2B, 0x6F, 0x43, 0x50, + 0xC6, 0x2C, 0xEB, 0x21, 0x17, 0xC5, 0x03, 0xA9, 0xD0, 0x1C, 0xCE, 0x8B, 0x89, 0x0B, 0xEB, 0xDD, 0x5B, 0x24, 0xAF, 0xD3, + 0x8A, 0xAB, 0x44, 0x35, 0xF7, 0x2D, 0x43, 0x37, 0x76, 0xF3, 0x65, 0xAE, 0xFA, 0xD0, 0xE8, 0x4C, 0xF4, 0x93, 0x6F, 0xE7, + 0xE5, 0x9C, 0xCC, 0xD2, 0x08, 0xCD, 0x9F, 0xA2, 0xFA, 0xBE, 0x23, 0x1E, 0xA0, 0x42, 0x23, 0x58, 0x68, 0x7F, 0x7C, 0xEC, + 0x71, 0x06, 0xED, 0xAF, 0xEE, 0x92, 0xD2, 0x02, 0xA2, 0x0A, 0xBA, 0x1E, 0x3B, 0x51, 0x25, 0xBB, 0x2C, 0x4E, 0xB0, 0x33, + 0x7B, 0x9E, 0x5A, 0x1F, 0xEF, 0xE2, 0x64, 0x40, 0x24, 0xB2, 0x04, 0x80, 0x78, 0xF8, 0xBE, 0x7B, 0x36, 0x43, 0x74, 0x7C, + 0xD5, 0xDD, 0x04, 0xDB, 0xA8, 0x7F, 0xDE, 0xB0, 0x26, 0xE9, 0xAF, 0x3C, 0xE9, 0x02, 0x6F, 0x97, 0x9E, 0xDB, 0xBF, 0x56, + 0x91, 0x60, 0x4F, 0x28, 0x82, 0x11, 0x27, 0x81, 0xC5, 0xE4, 0xCE, 0xA0, 0x6E, 0x5B, 0xA7, 0x8F, 0x53, 0x8E, 0x02, 0x1D, + 0x24, 0xE6, 0x2C, 0x39, 0x2D, 0x40, 0xCA, 0x11, 0x08, 0x63, 0x36, 0xAE, 0x52, 0xF6, 0xBB, 0xB2, 0xF4, 0xCB, 0xFB, 0x4A, + 0xC3, 0x02, 0xC4, 0x20, 0x7A, 0x69, 0xFF, 0x0B, 0x56, 0xDF, 0x76, 0x4B, 0xD8, 0x98, 0xCF, 0x27, 0xB7, 0xE8, 0x5D, 0xC6, + 0xC0, 0x14, 0x23, 0x8A, 0x5D, 0xAA, 0x85, 0xC0, 0x2D, 0x7A, 0xFB, 0xC3, 0x20, 0x3E, 0x43, 0xE7, 0x73, 0x99, 0xAD, 0x65, + 0x0F, 0x87, 0x2E, 0x2B, 0x23, 0x77, 0x28, 0x2B, 0x4A, 0x61, 0xA8, 0x0F, 0xFB, 0x6A, 0xE2, 0x50, 0x08, 0xEB, 0xC6, 0x1D, + 0xCB, 0x03, 0x2D, 0xF3, 0xED, 0x76, 0x5C, 0x35, 0x9F, 0xD5, 0x05, 0x52, 0x5C, 0xEF, 0x71, 0x1A, 0xA1, 0x11, 0xFA, 0x61, + 0x07, 0x7B, 0x9D, 0xE7, 0x2A, 0x55, 0x8B, 0xC3, 0xA1, 0x76, 0xF8, 0xFB, 0x4F, 0x04, 0xF1, 0xCB, 0x1E, 0x76, 0xF3, 0x8E, + 0xC9, 0x7A, 0x97, 0xA0, 0x0E, 0x7A, 0xD0, 0xDB, 0xDE, 0xE3, 0x8B, 0x0E, 0x45, 0x28, 0x09, 0xDB, 0xC8, 0x4E, 0xBD, 0x42, + 0x01, 0x74, 0x86, 0xC9, 0xA5, 0x1F, 0xB9, 0xB6, 0xA0, 0xA3, 0x40, 0xEE, 0xFB, 0x13, 0x02, 0xB6, 0xEB, 0x1F, 0xA9, 0x27, + 0xCA, 0xCB, 0xF4, 0x82, 0x84, 0xB0, 0xCE, 0x92, 0xB7, 0x52, 0x3B, 0x86, 0xED, 0x60, 0x29, 0xDC, 0x27, 0x93, 0x40, 0x1E, + 0x19, 0xF0, 0x69, 0x0B, 0xFA, 0x11, 0xFE, 0x6D, 0x35, 0x9E, 0xB4, 0xFD, 0x62, 0x10, 0xE0, 0x33, 0x5A, 0xA3, 0x6D, 0xA3, + 0x77, 0x50, 0xBA, 0xBD, 0xEF, 0xC2, 0x20, 0x02, 0x04, 0xC0, 0x7F, 0xAB, 0x12, 0x52, 0x22, 0x3A, 0xD5, 0xAC, 0x42, 0xE0, + 0xF6, 0xAC, 0x28, 0x12, 0x05, 0xC1, 0xAA, 0xEB, 0x74, 0x7A, 0x32, 0x12, 0xD4, 0xA5, 0x4D, 0x37, 0x11, 0xD5, 0x21, 0x1F, + 0x84, 0x82, 0x58, 0x41, 0x60, 0xEE, 0xE5, 0x71, 0x87, 0x32, 0xC1, 0xF8, 0x3B, 0xA3, 0x29, 0x92, 0x85, 0x83, 0xA9, 0x93, + 0xC6, 0xD6, 0x31, 0x23, 0x26, 0x09, 0x19, 0x39, 0x59, 0xEE, 0xCC, 0xC8, 0xFD, 0x74, 0x4B, 0xF7, 0xB5, 0x1B, 0xD4, 0x4E, + 0xAD, 0xA0, 0x24, 0x98, 0xAF, 0x87, 0xC0, 0x81, 0xF6, 0x86, 0xB6, 0xB4, 0x07, 0x0E, 0xCC, 0x19, 0xC9, 0x84, 0xD5, 0xD3, + 0xCE, 0xE7, 0x0F, 0xA1, 0x33, 0xC7, 0xDB, 0xFF, 0x65, 0xE7, 0x4C, 0xE4, 0x2D, 0xC9, 0x8E, 0x1D, 0xF8, 0x79, 0xD7, 0x5A, + 0x21, 0x29, 0x49, 0x57, 0x6A, 0x56, 0x00, 0xDC, 0xCF, 0xE5, 0x17, 0x66, 0x49, 0xDA, 0x22, 0x0A, 0x0C, 0xC8, 0xC2, 0x4E, + 0xA2, 0x23, 0x12, 0x2B, 0x09, 0x07, 0x22, 0xEE, 0x58, 0x05, 0x2A, 0x1A, 0x0D, 0xC9, 0x42, 0x21, 0x9F, 0x7D, 0x3E, 0x3E, + 0x0D, 0xD9, 0x06, 0x1A, 0xC5, 0xAD, 0x23, 0x8F, 0x8C, 0x8A, 0xA7, 0xED, 0x1B, 0xFF, 0xDC, 0x59, 0x4C, 0xBA, 0x23, 0x80, + 0x2B, 0xAA, 0x66, 0xCC, 0x8D, 0x8B, 0x58, 0xEF, 0x8C, 0xA4, 0x7B, 0x1B, 0xCC, 0xCF, 0x1A, 0x38, 0x3C, 0x8D, 0x58, 0x0D, + 0xD4, 0x33, 0x1D, 0x30, 0x30, 0x73, 0x4C, 0x6C, 0x76, 0x63, 0x13, 0x2E, 0x12, 0x71, 0x3A, 0x2D, 0x45, 0xCA, 0x3E, 0x04, + 0xD6, 0xE9, 0x04, 0x7D, 0xFE, 0xC2, 0x87, 0x63, 0xCC, 0xE0, 0x59, 0xD1, 0x7D, 0x53, 0xCC, 0xEA, 0x47, 0x32, 0xD3, 0x18, + 0x42, 0x9D, 0x16, 0x95, 0x67, 0xB8, 0x05, 0x29, 0x02, 0x79, 0x3F, 0x0C, 0x1B, 0xD9, 0x45, 0x99, 0x63, 0xC0, 0xC1, 0x34, + 0x68, 0x62, 0x1E, 0x60, 0x88, 0x6E, 0x64, 0x87, 0xAA, 0x45, 0x3C, 0x08, 0x85, 0xB6, 0x24, 0xD4, 0xA5, 0xEF, 0x2C, 0x6F, + 0x25, 0x1C, 0x73, 0x9E, 0xB2, 0xB6, 0x88, 0x58, 0x84, 0xB7, 0x2B, 0x49, 0x80, 0x92, 0x5E, 0x5D, 0x13, 0x89, 0xF0, 0x03, + 0xBC, 0xC4, 0x81, 0x4D, 0x05, 0xB4, 0xEB, 0x45, 0xE4, 0x0F, 0xD5, 0x9B, 0x7A, 0x0C, 0x05, 0x35, 0x6A, 0xEC, 0x89, 0xF9, + 0x2C, 0x97, 0x46, 0xCD, 0xDB, 0x6C, 0x1D, 0xE5, 0x87, 0x85, 0x99, 0xEC, 0xB2, 0xF5, 0x46, 0xDA, 0x95, 0xE9, 0x11, 0x1D, + 0x87, 0xA2, 0x52, 0xD4, 0x6D, 0xD1, 0xEC, 0x1F, 0x81, 0xB5, 0x07, 0xFC, 0xC4, 0x68, 0x7B, 0x25, 0xD4, 0xAB, 0x1D, 0x90, + 0x05, 0x89, 0x94, 0xC7, 0x3F, 0x81, 0xD6, 0x01, 0x06, 0x47, 0x8E, 0x8D, 0x6C, 0xE9, 0x35, 0xD7, 0xED, 0xF3, 0xFA, 0xAD, + 0x2B, 0xB8, 0x4F, 0xCB, 0x14, 0x8A, 0xC7, 0xAC, 0x48, 0x7A, 0x78, 0xA8, 0xF9, 0x33, 0x0E, 0x3D, 0xF4, 0xCB, 0x1F, 0xE4, + 0xA5, 0xBC, 0x0D, 0x35, 0x8D, 0xEE, 0x1E, 0x6B, 0x00, 0xE9, 0x75, 0x9C, 0x42, 0x39, 0x10, 0xBC, 0xFC, 0x85, 0xD9, 0x40, + 0x21, 0x57, 0xA2, 0xD0, 0xC7, 0x0A, 0x07, 0x9C, 0x8A, 0xDE, 0x9E, 0x49, 0x40, 0xC6, 0xBF, 0xBE, 0x0F, 0x27, 0x71, 0x90, + 0xAD, 0x30, 0x47, 0x3D, 0x19, 0x3C, 0x11, 0xBC, 0x78, 0x25, 0xC7, 0xD4, 0x1C, 0x27, 0x5E, 0x62, 0x8D, 0xDD, 0xC4, 0x91, + 0xEB, 0x00, 0xD5, 0x08, 0x8E, 0x60, 0xDD, 0x00, 0x9F, 0xE0, 0xCE, 0xF3, 0xC4, 0xD9, 0x93, 0x36, 0x2D, 0x40, 0x4C, 0xC3, + 0xBE, 0xCE, 0x80, 0x1C, 0xCA, 0x2B, 0x92, 0xCA, 0xAC, 0x33, 0x9C, 0xBC, 0x1D, 0xC2, 0x46, 0x09, 0x72, 0xD1, 0x8A, 0xCB, + 0x43, 0x08, 0x51, 0xDC, 0x99, 0x30, 0x78, 0x20, 0x4A, 0xDC, 0x69, 0x19, 0x14, 0xE2, 0x77, 0x1D, 0x46, 0x49, 0x88, 0xE2, + 0xF1, 0x89, 0x33, 0xBC, 0xEC, 0x93, 0xAF, 0xC6, 0x64, 0x55, 0x15, 0x67, 0x43, 0x4C, 0x69, 0x41, 0xA2, 0x40, 0x88, 0x90, + 0x15, 0x30, 0x70, 0x37, 0xC2, 0x05, 0x4D, 0x25, 0xB8, 0x5B, 0x21, 0x4B, 0xE1, 0x06, 0xAE, 0x6A, 0x49, 0xB9, 0xB1, 0x32, + 0x4C, 0x4D, 0x33, 0x66, 0x60, 0x20, 0xB4, 0x8E, 0x6A, 0x0C, 0xAE, 0xBD, 0xB3, 0x62, 0xD9, 0x21, 0x57, 0x01, 0xDB, 0xCE, + 0x38, 0x50, 0x08, 0x44, 0x8B, 0xCA, 0x88, 0x40, 0xBB, 0x4A, 0x2E, 0x20, 0xEB, 0xF5, 0x6E, 0xE1, 0xA5, 0xC9, 0xA2, 0x41, + 0x69, 0xA8, 0x4C, 0x27, 0x65, 0xAA, 0x27, 0x88, 0x43, 0xE4, 0x0E, 0x0A, 0x21, 0xCA, 0x81, 0xEC, 0xC0, 0x2A, 0xFF, 0xF8, + 0x71, 0x2D, 0x57, 0xD0, 0x2B, 0x1C, 0x42, 0xE0, 0xAA, 0xC9, 0xDE, 0x77, 0x6E, 0x65, 0xD1, 0xCC, 0x7A, 0xD4, 0x61, 0x8E, + 0x32, 0x05, 0x0B, 0xB2, 0x3A, 0x84, 0xBB, 0x96, 0x0D, 0x07, 0xC7, 0xE4, 0x67, 0xE5, 0x10, 0xA6, 0x4E, 0xC8, 0x3E, 0xB7, + 0x5B, 0xCA, 0x33, 0x82, 0x40, 0x06, 0xCE, 0x98, 0x27, 0x38, 0x20, 0xDD, 0xA8, 0x2F, 0xE5, 0x4F, 0x63, 0x05, 0x3E, 0x92, + 0x8D, 0x05, 0x2F, 0x9F, 0x9C, 0x20, 0xF2, 0xAD, 0x88, 0x1C, 0xAD, 0xE4, 0xB8, 0xB5, 0x9B, 0x73, 0xA8, 0xFB, 0xD4, 0x09, + 0x9F, 0x0B, 0xAF, 0x6A, 0x45, 0xE7, 0xFC, 0x7D, 0xDD, 0x47, 0x3C, 0xED, 0xE3, 0x0F, 0xD4, 0x2E, 0xE5, 0x81, 0x83, 0x9F, + 0xA3, 0x7F, 0xB4, 0xC8, 0xB3, 0x4F, 0x1A, 0x66, 0x77, 0x16, 0x31, 0x7B, 0xBA, 0x41, 0x90, 0xB8, 0x57, 0x0F, 0x0B, 0xF8, + 0x6D, 0x4A, 0x87, 0xBA, 0xE8, 0xA3, 0x10, 0xC9, 0xAC, 0x39, 0x4B, 0xE9, 0xCC, 0x3D, 0x13, 0xC1, 0x51, 0x66, 0xCF, 0x07, + 0x2F, 0xE2, 0xAD, 0xE8, 0x72, 0xEC, 0x8E, 0xE9, 0x22, 0xFC, 0x1B, 0xD1, 0x1E, 0x67, 0x6D, 0x63, 0x04, 0xDD, 0x27, 0x25, + 0xEC, 0x73, 0x15, 0x50, 0x64, 0x36, 0x14, 0xE7, 0xB7, 0x32, 0x0D, 0xE6, 0xD6, 0x01, 0xD5, 0x90, 0xE4, 0x74, 0xF8, 0x56, + 0x02, 0xD1, 0xE2, 0x08, 0xF8, 0xBF, 0x7E, 0x89, 0x45, 0xAD, 0xBB, 0x25, 0x44, 0xC3, 0xED, 0xA9, 0x83, 0x32, 0x40, 0x59, + 0x9A, 0xE1, 0xB7, 0x6E, 0x85, 0x9E, 0x33, 0x10, 0x64, 0x51, 0xC1, 0x83, 0x89, 0x17, 0x9B, 0x04, 0x18, 0x29, 0x0C, 0x50, + 0x24, 0x67, 0xB5, 0x37, 0x4A, 0x51, 0x94, 0x4D, 0x15, 0xF7, 0x14, 0x23, 0x9B, 0x97, 0x9F, 0x97, 0xCA, 0xA6, 0xC0, 0xE5, + 0x92, 0xCA, 0x5C, 0x83, 0x19, 0xF4, 0x1C, 0x58, 0xF8, 0x7D, 0x9E, 0x70, 0xD0, 0xB9, 0xFD, 0x36, 0xC6, 0x9B, 0x06, 0x12, + 0x94, 0x8D, 0xB3, 0x55, 0x1B, 0x15, 0xAA, 0x22, 0xAA, 0xBA, 0xF3, 0x95, 0xB5, 0x64, 0x94, 0x02, 0xEA, 0x8A, 0x5F, 0x71, + 0xC5, 0x29, 0xE2, 0x72, 0x4B, 0x38, 0xEF, 0x66, 0xD3, 0xBB, 0x68, 0xAE, 0x81, 0x57, 0x84, 0xAD, 0x87, 0xF5, 0xEA, 0x66, + 0x4A, 0x79, 0xD8, 0xEF, 0x53, 0x55, 0x8E, 0xCB, 0x3E, 0x52, 0xCB, 0xDC, 0x33, 0x17, 0xE3, 0x72, 0xCB, 0x5A, 0x24, 0x28, + 0x59, 0x95, 0x41, 0xAE, 0x03, 0x3E, 0x57, 0x01, 0x17, 0xD7, 0xEB, 0x66, 0x8D, 0x86, 0xED, 0x95, 0xB8, 0x7B, 0x9F, 0xDA, + 0x26, 0x19, 0xFD, 0xBC, 0xFA, 0x3B, 0x15, 0x56, 0xC1, 0x14, 0xB7, 0x32, 0x96, 0x31, 0x00, 0x50, 0x81, 0x54, 0x16, 0xF9, + 0xE9, 0xDC, 0x14, 0xDC, 0x43, 0xAE, 0xA8, 0xE0, 0xD2, 0x8C, 0xB7, 0x9A, 0x0A, 0x7D, 0x84, 0xFD, 0xD8, 0x88, 0x7B, 0xF0, + 0xE2, 0xBD, 0x38, 0x0A, 0x53, 0x4D, 0x6B, 0xD0, 0xEC, 0x0D, 0x81, 0xCE, 0xE1, 0x3F, 0x31, 0x60, 0x4A, 0xBC, 0xD5, 0xDF, + 0x08, 0x92, 0x07, 0xFD, 0x42, 0x31, 0x88, 0xC3, 0x89, 0x3D, 0x1B, 0x45, 0x0A, 0x1F, 0x8C, 0xFF, 0x04, 0xE2, 0x48, 0x71, + 0xC8, 0xDC, 0x5A, 0x55, 0x2E, 0x11, 0xEC, 0xEC, 0xF8, 0xE3, 0x88, 0x0A, 0x13, 0xD2, 0x8C, 0x61, 0xC9, 0x6D, 0xFF, 0x27, + 0x3F, 0xA3, 0x1E, 0x86, 0x7F, 0x5F, 0x74, 0x26, 0xEF, 0xC2, 0x1F, 0x25, 0x55, 0xCD, 0xCF, 0x9A, 0x21, 0xE6, 0xD6, 0xD9, + 0x2E, 0xC2, 0xB8, 0xEE, 0xD9, 0xE1, 0x41, 0x60, 0x49, 0xDF, 0x6C, 0x0A, 0xD3, 0xB0, 0xA4, 0x1C, 0x08, 0x9A, 0xFA, 0x44, + 0xA5, 0x79, 0x67, 0x91, 0x4F, 0x59, 0xE0, 0xE2, 0x68, 0xF7, 0x38, 0xCD, 0xEC, 0x86, 0x68, 0x35, 0x98, 0x88, 0x22, 0x8C, + 0x2F, 0x76, 0x00, 0x7E, 0xBE, 0x06, 0x18, 0xBC, 0x0B, 0x2B, 0xFB, 0x45, 0x04, 0xAE, 0x51, 0x4F, 0x8E, 0x65, 0xB9, 0x72, + 0x3F, 0x25, 0x57, 0x6E, 0x51, 0x28, 0xC6, 0xD3, 0xA1, 0xF9, 0x07, 0xCA, 0xA4, 0x38, 0x01, 0x9F, 0xEC, 0xAA, 0x1B, 0x6A, + 0x50, 0x75, 0xA6, 0x4D, 0x44, 0xEA, 0x1C, 0x2C, 0xDD, 0x89, 0xCB, 0xAA, 0x62, 0x22, 0xFE, 0xE4, 0xF4, 0xEA, 0x6A, 0x1F, + 0x94, 0x12, 0x00, 0xBD, 0xEA, 0xD9, 0xA8, 0xC0, 0xA2, 0x44, 0x8F, 0xAE, 0x73, 0x57, 0x76, 0x2E, 0xE7, 0x0A, 0x5B, 0x2C, + 0x4F, 0x8E, 0xFB, 0xBB, 0x35, 0xB0, 0x54, 0x61, 0xA3, 0x14, 0xAA, 0x9B, 0x99, 0xBA, 0x61, 0x3A, 0x43, 0x84, 0xEA, 0x78, + 0x03, 0xE3, 0xF5, 0xCE, 0x30, 0x2C, 0xDA, 0x3E, 0x16, 0xA7, 0x24, 0xD2, 0xA5, 0x5F, 0xF0, 0x88, 0x58, 0xBF, 0x54, 0x93, + 0x4D, 0x32, 0x3D, 0x6F, 0xBE, 0x52, 0x46, 0xBD, 0xA6, 0xFE, 0x4D, 0xC7, 0xAB, 0x7E, 0x5D, 0xE3, 0xAF, 0x5C, 0x63, 0x2C, + 0x11, 0x03, 0x4D, 0xC3, 0xED, 0x8E, 0x1A, 0xEB, 0x92, 0xF0, 0x55, 0xF2, 0x02, 0x39, 0xD5, 0xE3, 0x99, 0xFC, 0x23, 0x7F, + 0x66, 0xA1, 0x3B, 0xA6, 0x21, 0xEB, 0xDE, 0x8A, 0xDD, 0x5F, 0x80, 0x4D, 0x57, 0x4F, 0xFB, 0x1A, 0xB0, 0x43, 0x98, 0x70, + 0x9D, 0x43, 0x93, 0x64, 0x01, 0x0C, 0x92, 0x27, 0xD7, 0xA1, 0x48, 0x41, 0x53, 0xB4, 0x82, 0x0E, 0xB7, 0xF1, 0x24, 0xFD, + 0x43, 0x82, 0xDB, 0x3B, 0x5F, 0x41, 0x92, 0x1A, 0xE2, 0x81, 0xD3, 0x6B, 0x1F, 0x01, 0x55, 0xB4, 0x5C, 0x9C, 0xAD, 0xD7, + 0xB1, 0x9F, 0x05, 0x40, 0xDB, 0x7E, 0xC3, 0x0B, 0x7C, 0x3D, 0x37, 0x31, 0x54, 0xD6, 0x35, 0xB6, 0xB6, 0xA2, 0xB4, 0x4E, + 0xCC, 0x96, 0x7B, 0xD1, 0x52, 0x01, 0x52, 0x1B, 0x65, 0x6A, 0x39, 0x49, 0xC2, 0x3C, 0xBC, 0x5F, 0x55, 0xDF, 0x2C, 0xCA, + 0x71, 0xDD, 0xB0, 0x17, 0xA5, 0x04, 0xED, 0xBE, 0x39, 0x1B, 0xA4, 0xB5, 0xE7, 0x06, 0x6B, 0x95, 0x01, 0x7D, 0x53, 0x7A, + 0x2A, 0x61, 0xCD, 0x3D, 0x5E, 0xE4, 0xFB, 0x80, 0x81, 0x98, 0x45, 0x88, 0x54, 0x7C, 0x92, 0xF4, 0x8F, 0xFD, 0x4C, 0x0C, + 0x74, 0x53, 0xFF, 0x45, 0x5B, 0xD8, 0xB0, 0x1F, 0x7A, 0x8B, 0xD6, 0x92, 0xD4, 0xD6, 0x08, 0xBD, 0x81, 0x9C, 0x41, 0x42, + 0x6D, 0x9B, 0xBB, 0xCD, 0x4F, 0xF0, 0x98, 0x69, 0x88, 0x07, 0xB1, 0xED, 0x93, 0x9F, 0x84, 0x13, 0x10, 0x69, 0x20, 0x51, + 0xFA, 0x89, 0x2E, 0xE5, 0x0A, 0x8B, 0x04, 0xBC, 0x1A, 0x97, 0xBF, 0x93, 0x31, 0xE8, 0xBC, 0x78, 0x3F, 0xDB, 0x2E, 0x4E, + 0x28, 0xEF, 0xFC, 0xCC, 0xAC, 0xB4, 0x77, 0x99, 0x00, 0x93, 0xD6, 0xD2, 0x78, 0xD4, 0x08, 0x16, 0xC4, 0xB5, 0x2A, 0x24, + 0xC2, 0xDF, 0xA8, 0x69, 0x0D, 0x70, 0x79, 0xC3, 0x80, 0x2D, 0x25, 0x8C, 0x47, 0x2D, 0x2C, 0xB1, 0x1A, 0x53, 0x4B, 0xD0, + 0x61, 0x73, 0x4C, 0x9D, 0x5D, 0x75, 0x51, 0x63, 0x6D, 0x9F, 0x90, 0xAC, 0xC7, 0xFA, 0xAB, 0x7F, 0xD9, 0xF1, 0x0C, 0xF3, + 0x4E, 0xBE, 0x3A, 0xF3, 0x30, 0xBF, 0x11, 0x08, 0x16, 0x11, 0x2A, 0xC8, 0xC7, 0x0F, 0x6F, 0x5A, 0x82, 0xBF, 0xCC, 0x63, + 0x20, 0x63, 0x99, 0x67, 0x91, 0x20, 0x41, 0xF3, 0xE4, 0xBE, 0x74, 0x4B, 0x8B, 0xEA, 0x3F, 0xDC, 0x24, 0xEF, 0x02, 0xC5, + 0xD8, 0x60, 0x50, 0xC7, 0x40, 0x60, 0xA6, 0x0C, 0xA3, 0x62, 0x77, 0x38, 0x68, 0x2A, 0xD0, 0x67, 0xF2, 0x63, 0xF5, 0xAA, + 0xC0, 0xE3, 0xB9, 0xDF, 0xA4, 0x75, 0xC0, 0x86, 0x2C, 0x07, 0x99, 0x47, 0xB3, 0xDB, 0x09, 0xB6, 0xE5, 0x05, 0x32, 0x17, + 0x0D, 0x2B, 0x10, 0xF4, 0x30, 0x6F, 0xC9, 0x2B, 0xB4, 0x64, 0xA7, 0x0E, 0x6D, 0x9A, 0x48, 0x0F, 0x9B, 0x3F, 0x95, 0x89, + 0x6B, 0x6C, 0x75, 0x27, 0x4F, 0x69, 0xAA, 0x1E, 0xAA, 0x4B, 0xD0, 0x16, 0xF3, 0x29, 0xF1, 0xB1, 0xFB, 0x45, 0x74, 0xAA, + 0xE4, 0x27, 0x03, 0x11, 0xBF, 0xE8, 0xA1, 0x47, 0x2C, 0x0B, 0x1A, 0x19, 0x63, 0x19, 0x7A, 0x0E, 0x46, 0x6A, 0xAD, 0xB3, + 0xEF, 0x4C, 0x9A, 0x20, 0x6B, 0xC6, 0x9D, 0x1D, 0x2B, 0x98, 0x32, 0x2D, 0x29, 0x66, 0xE2, 0xD0, 0xC2, 0x04, 0x22, 0x84, + 0xD9, 0x7B, 0x07, 0xF0, 0x8C, 0x09, 0x92, 0x7E, 0xAB, 0xA7, 0x11, 0x5B, 0xFB, 0x64, 0x2B, 0x14, 0x7F, 0x78, 0x08, 0x5E, + 0xBA, 0x17, 0x33, 0xDA, 0x5B, 0x0B, 0xF7, 0xAB, 0xDD, 0x43, 0x37, 0x4F, 0x13, 0x5A, 0x53, 0x98, 0x0B, 0x4C, 0x7A, 0xB6, + 0x0A, 0x61, 0xF2, 0x98, 0xE2, 0x9F, 0xEC, 0xC1, 0x84, 0x93, 0x8A, 0x70, 0x42, 0x63, 0x31, 0x7B, 0xBA, 0x43, 0xEE, 0x1A, + 0xF4, 0xE0, 0x6C, 0x1C, 0xF8, 0x90, 0x63, 0xF0, 0xB9, 0x80, 0xBC, 0x49, 0x92, 0x02, 0x2D, 0x6E, 0x6B, 0x11, 0xED, 0xC1, + 0xFE, 0x68, 0xF4, 0xCA, 0xAA, 0xA2, 0xAD, 0x1C, 0x72, 0x27, 0x8E, 0x48, 0x6A, 0xB0, 0x6F, 0x9F, 0xA8, 0x8A, 0x14, 0x21, + 0x67, 0x0B, 0xDB, 0x6C, 0xEC, 0xFD, 0x10, 0x84, 0x40, 0xE1, 0x18, 0x4C, 0xAC, 0xBD, 0x74, 0x81, 0xC1, 0x90, 0x73, 0x6F, + 0xBE, 0x9C, 0x0C, 0x9C, 0x0C, 0x13, 0x23, 0x2F, 0x12, 0x75, 0x8B, 0xE7, 0x5F, 0xB9, 0x41, 0x00, 0xF3, 0xC1, 0x97, 0x81, + 0xC6, 0x32, 0x39, 0x20, 0x0B, 0x1E, 0x0B, 0x6F, 0x92, 0x99, 0x45, 0x0E, 0xD2, 0x37, 0x17, 0x5A, 0x08, 0x39, 0xE4, 0xC9, + 0x63, 0x79, 0x84, 0xE8, 0x6B, 0x78, 0x9D, 0xDE, 0x97, 0xC2, 0x32, 0x02, 0x46, 0x59, 0xC4, 0xD6, 0xBA, 0x7B, 0x76, 0x43, + 0x7C, 0x57, 0xF4, 0x2A, 0x9F, 0x38, 0x6F, 0xDC, 0x2B, 0x04, 0x96, 0xE9, 0x57, 0x6E, 0x7F, 0x52, 0x83, 0xA9, 0x55, 0x47, + 0x3B, 0x8E, 0xAE, 0xC6, 0x43, 0xE9, 0x42, 0x16, 0xD0, 0x4B, 0x5C, 0xDB, 0xA0, 0xD7, 0x32, 0xF1, 0x46, 0xC8, 0x07, 0xB1, + 0x93, 0xF8, 0xD4, 0x93, 0x00, 0x67, 0xBE, 0x72, 0xA7, 0xCE, 0xFF, 0xFD, 0x33, 0x2E, 0x4E, 0xE9, 0x5B, 0xF3, 0x12, 0x5D, + 0x0D, 0x3B, 0xB6, 0x5F, 0xEB, 0x39, 0x69, 0x63, 0xD8, 0xBF, 0xE1, 0xC6, 0x4B, 0xB4, 0x89, 0xB8, 0x70, 0x1D, 0x0F, 0x91, + 0x9B, 0x54, 0xCF, 0x90, 0x35, 0xB7, 0xAF, 0x57, 0xF8, 0x17, 0xC7, 0x81, 0xB0, 0x7B, 0x47, 0xBD, 0xCA, 0x3B, 0x8F, 0x19, + 0x89, 0x2B, 0x99, 0xFE, 0x08, 0xAD, 0x33, 0xCE, 0x8C, 0xDD, 0x86, 0xE0, 0xE0, 0xB7, 0x7E, 0xF1, 0x9D, 0x2E, 0xF6, 0x9A, + 0x08, 0x78, 0x6E, 0x17, 0x7E, 0x5C, 0x16, 0xC8, 0x40, 0xE4, 0x5E, 0x23, 0x4C, 0x3D, 0xE5, 0x07, 0x9F, 0x0C, 0x7E, 0x8E, + 0x0D, 0xD2, 0xDC, 0xC5, 0x43, 0xC7, 0x7F, 0x7D, 0xBA, 0x71, 0x29, 0xEE, 0x13, 0x51, 0x3B, 0x92, 0x82, 0xD1, 0xCF, 0xFD, + 0x26, 0xB2, 0x0F, 0xDC, 0x32, 0xE2, 0x59, 0xD5, 0x88, 0x57, 0x7B, 0xD9, 0x79, 0x7B, 0x98, 0x91, 0x34, 0xCF, 0xA8, 0x86, + 0xF5, 0xEF, 0x32, 0xE4, 0x6E, 0x4D, 0xCF, 0x54, 0x96, 0xE0, 0xD0, 0xFA, 0xC8, 0xCC, 0xBD, 0x0A, 0x16, 0x61, 0x61, 0xF1, + 0xE0, 0x60, 0x3F, 0x71, 0x66, 0x4F, 0x60, 0x65, 0x46, 0x82, 0xF1, 0x2B, 0x88, 0xE0, 0xC9, 0x83, 0xEE, 0x90, 0x71, 0x0F, + 0x44, 0xE8, 0x28, 0xB3, 0x68, 0x81, 0xF7, 0x6A, 0xD5, 0xEF, 0x28, 0xD5, 0x2C, 0xA9, 0x01, 0xA4, 0xED, 0xAC, 0xAF, 0xC6, + 0x36, 0x30, 0xFA, 0x44, 0xA5, 0x79, 0x4E, 0xCE, 0x68, 0x1B, 0xAF, 0x06, 0x3D, 0x27, 0x0E, 0xA3, 0x72, 0xC6, 0x44, 0x25, + 0x10, 0x03, 0xD8, 0x82, 0xEF, 0x16, 0xE3, 0x9E, 0x45, 0xA8, 0x69, 0x4B, 0x80, 0x97, 0xFB, 0x45, 0x04, 0xE7, 0x2B, 0x03, + 0xBA, 0x69, 0x71, 0x43, 0x37, 0x49, 0x49, 0x7B, 0x08, 0x7A, 0xF1, 0x24, 0xC8, 0x2E, 0x07, 0x74, 0x66, 0x86, 0x99, 0x69, + 0xAC, 0xE8, 0x72, 0x37, 0x08, 0xC6, 0xF4, 0x2A, 0x3C, 0xF9, 0x2A, 0x2E, 0xAD, 0x87, 0xF3, 0x48, 0x9E, 0xE8, 0x84, 0xEA, + 0x05, 0xC6, 0xBD, 0x1A, 0x35, 0x27, 0x58, 0x32, 0x4C, 0x09, 0x84, 0x42, 0x7E, 0xFB, 0xB0, 0xCD, 0xF0, 0x91, 0x23, 0x2E, + 0x5F, 0xA9, 0x6A, 0xE8, 0x69, 0xA4, 0x4B, 0xDE, 0xA9, 0xBA, 0x2A, 0xEB, 0xFD, 0xC4, 0x6B, 0x37, 0xDE, 0xA1, 0x01, 0xDD, + 0xA6, 0x32, 0xB7, 0xF3, 0xDB, 0xFA, 0x04, 0x63, 0x6D, 0x88, 0xC2, 0xA4, 0xF7, 0x86, 0xDE, 0x82, 0x9A, 0x81, 0x92, 0x70, + 0x74, 0xE1, 0x6C, 0xDE, 0x3F, 0x2B, 0xB3, 0xDD, 0xBA, 0x72, 0x60, 0x78, 0xA4, 0xC2, 0x6A, 0x1C, 0xE4, 0x61, 0x1A, 0x37, + 0x1C, 0x86, 0xF9, 0x4D, 0x0C, 0xEF, 0x15, 0xAF, 0x27, 0xE4, 0x93, 0x71, 0x4A, 0xE1, 0x4B, 0xCA, 0xBC, 0x01, 0xEA, 0x98, + 0x3A, 0x50, 0x3A, 0x1D, 0xAE, 0xCB, 0xB1, 0x62, 0xB4, 0xE0, 0x04, 0x16, 0xD5, 0x3B, 0xAC, 0x83, 0x14, 0xB3, 0xCB, 0xD0, + 0xB2, 0x0F, 0xA5, 0x55, 0x01, 0x9E, 0x2A, 0x6C, 0xD8, 0xFF, 0xCA, 0xBE, 0xDE, 0x68, 0x02, 0x73, 0x63, 0xC0, 0x82, 0x6B, + 0x73, 0xE0, 0x5D, 0x92, 0x44, 0x13, 0xE8, 0xC0, 0x5D, 0x6B, 0x99, 0xDC, 0x2E, 0x98, 0x8B, 0x63, 0x3E, 0xFB, 0xCE, 0xD3, + 0xBF, 0x88, 0xF5, 0x93, 0x32, 0xD0, 0x1A, 0x73, 0xA5, 0x06, 0x70, 0x77, 0xBD, 0xB1, 0xAC, 0x51, 0x07, 0x39, 0xF2, 0xFF, + 0xDD, 0x05, 0xE7, 0x11, 0xE2, 0x59, 0x2C, 0x84, 0x89, 0xEF, 0x24, 0x43, 0x21, 0x84, 0xFF, 0x11, 0xDE, 0x04, 0xEC, 0x0C, + 0xCB, 0xD8, 0x1B, 0xD2, 0xD6, 0x2E, 0xAA, 0x47, 0x96, 0xEC, 0xDF, 0x76, 0xC6, 0x19, 0x27, 0xE0, 0x0D, 0xB2, 0x90, 0x81, + 0x01, 0x9A, 0x6D, 0x13, 0xA5, 0x8C, 0x8F, 0x28, 0x5E, 0x26, 0xD1, 0x60, 0x99, 0x28, 0xFD, 0xBD, 0x0E, 0xEB, 0xCE, 0xEC, + 0x4D, 0xB8, 0xF6, 0x2B, 0x15, 0xFA, 0x7A, 0x95, 0x6B, 0xC3, 0xA7, 0xAE, 0x7F, 0xC8, 0xD6, 0x12, 0x88, 0x38, 0x16, 0x64, + 0x2D, 0xF4, 0x76, 0x3E, 0x98, 0x96, 0x12, 0x2D, 0x4D, 0x56, 0x3F, 0x87, 0xCF, 0xDA, 0xB6, 0xCA, 0x8F, 0x34, 0x5E, 0x2F, + 0xDC, 0xAA, 0x89, 0xD3, 0xDD, 0x5A, 0x3E, 0x7D, 0x2D, 0xA9, 0xD0, 0xD8, 0x40, 0x0D, 0x3E, 0xC4, 0x4A, 0xD8, 0x24, 0xCC, + 0x88, 0xF0, 0x8C, 0xAC, 0x46, 0x8D, 0x84, 0xCE, 0x1A, 0xA7, 0xCD, 0x79, 0x18, 0x03, 0xF7, 0xCA, 0xDF, 0x03, 0x68, 0x9A, + 0x3F, 0x36, 0xD6, 0x81, 0x98, 0xAD, 0x64, 0xF8, 0xDC, 0x80, 0x46, 0x6C, 0x7F, 0x22, 0x9F, 0xAD, 0x23, 0x18, 0xEC, 0xAD, + 0x41, 0xDB, 0x9B, 0x84, 0x30, 0x03, 0x4F, 0x70, 0x01, 0xEC, 0xF0, 0xDE, 0x8B, 0x12, 0x50, 0x39, 0x9B, 0xA4, 0x65, 0xF9, + 0x7D, 0x9E, 0x13, 0x84, 0x21, 0x62, 0xE3, 0x24, 0x82, 0x04, 0x04, 0x80, 0x1F, 0xAE, 0x2A, 0xC8, 0xDA, 0x0F, 0x50, 0x28, + 0xFE, 0x68, 0x08, 0xE8, 0x01, 0xBA, 0x90, 0x34, 0x2D, 0xE1, 0xAC, 0xD2, 0x65, 0x47, 0x63, 0x3C, 0xF4, 0x9E, 0x9E, 0x63, + 0x7F, 0xD9, 0x29, 0x00, 0x96, 0x48, 0x71, 0x62, 0xB8, 0x4D, 0x85, 0xCD, 0x5E, 0x2F, 0x88, 0x95, 0x89, 0x2F, 0x49, 0xCD, + 0x4A, 0x63, 0x35, 0x7A, 0x60, 0xC3, 0xC0, 0x3A, 0x74, 0xFC, 0xC1, 0xE7, 0x03, 0xC4, 0x00, 0x1C, 0x97, 0x35, 0x90, 0xA5, + 0x26, 0x06, 0xD6, 0x22, 0x3C, 0x9F, 0xE0, 0x70, 0x81, 0x01, 0xD8, 0x74, 0x17, 0x8A, 0x9C, 0xF4, 0x19, 0x9D, 0x60, 0xA4, + 0x0F, 0x9A, 0x7F, 0x84, 0xA1, 0x46, 0xFF, 0x18, 0xB1, 0x86, 0x9B, 0x45, 0xC4, 0x9D, 0x2E, 0x41, 0xE1, 0xA1, 0xD6, 0x33, + 0xA2, 0x0C, 0x05, 0xBD, 0xE0, 0x6A, 0x63, 0xF3, 0x42, 0xDA, 0x02, 0x75, 0xE0, 0x13, 0xEE, 0x2C, 0xE1, 0x19, 0xC9, 0xD4, + 0x6F, 0x8E, 0x6A, 0x4A, 0xC5, 0xCE, 0x93, 0x4A, 0xA3, 0x9E, 0x74, 0x1E, 0xE8, 0x8A, 0x57, 0x7C, 0x72, 0x01, 0x24, 0x61, + 0xEE, 0x59, 0xA1, 0x4C, 0xD9, 0x7F, 0x15, 0x6B, 0xE8, 0x3D, 0x5C, 0x6D, 0xAF, 0x0F, 0x93, 0x0D, 0xFB, 0x12, 0x28, 0x5D, + 0x58, 0x75, 0xA3, 0xEA, 0x05, 0x4A, 0x8F, 0xEC, 0x9C, 0x2E, 0x25, 0x65, 0x6E, 0x0A, 0x93, 0x38, 0xF9, 0xA8, 0x82, 0x45, + 0x3A, 0x06, 0x88, 0xAE, 0x3B, 0x7C, 0x2A, 0xEC, 0x2D, 0x4D, 0x6A, 0x96, 0x4A, 0x21, 0x8A, 0x55, 0x7D, 0x86, 0x72, 0x8C, + 0x47, 0x36, 0x0A, 0x0F, 0x45, 0x4B, 0x61, 0xD9, 0x91, 0x60, 0x50, 0xA1, 0x2C, 0x62, 0x7B, 0x7D, 0x39, 0x61, 0x33, 0x6B, + 0xA9, 0x43, 0xAC, 0xE9, 0xD2, 0x42, 0x6B, 0xDD, 0x9F, 0x58, 0x6B, 0xAB, 0x72, 0x45, 0x71, 0x49, 0x6A, 0xE0, 0xA4, 0x87, + 0xE8, 0xEF, 0x94, 0xFB, 0xE8, 0x4A, 0x5B, 0xE4, 0x47, 0x15, 0xEB, 0xD2, 0x4E, 0x8F, 0x46, 0x4C, 0xD6, 0x3D, 0xF3, 0xE3, + 0x17, 0xB2, 0x40, 0x74, 0x25, 0x73, 0xA8, 0xCF, 0xC2, 0x10, 0x5C, 0xAC, 0xAA, 0x33, 0x7D, 0xB3, 0xC8, 0x61, 0x45, 0x35, + 0x6B, 0x9F, 0x85, 0x5E, 0x15, 0x5D, 0x4E, 0xA5, 0xC3, 0xC9, 0x75, 0xB5, 0x23, 0x3F, 0x08, 0xBD, 0xB2, 0x93, 0x22, 0x4D, + 0xE1, 0xF2, 0x18, 0x9D, 0xF2, 0x92, 0xCB, 0x44, 0x3E, 0x05, 0xB7, 0x64, 0x1E, 0x84, 0xEE, 0x80, 0x2A, 0x57, 0x2B, 0x23, + 0xEC, 0xA9, 0xF4, 0x2F, 0xAE, 0x0E, 0x34, 0xB2, 0x10, 0x95, 0x05, 0x01, 0x87, 0xDF, 0x83, 0x92, 0x80, 0x65, 0x0D, 0x6D, + 0x91, 0x51, 0x9C, 0x38, 0x17, 0xB4, 0x95, 0xE5, 0x4B, 0xDC, 0x34, 0x25, 0xB4, 0x6D, 0x6E, 0xB7, 0x7D, 0x9C, 0x65, 0xF0, + 0xB5, 0x4F, 0x84, 0xD2, 0xDC, 0x5E, 0x65, 0x0E, 0x0E, 0xC1, 0x0D, 0xEA, 0xEA, 0xCA, 0xBC, 0x73, 0x3E, 0xC2, 0xC3, 0x57, + 0x9D, 0xFB, 0x3A, 0xD7, 0xA6, 0xF3, 0x6C, 0x98, 0x0D, 0x1F, 0xDE, 0x18, 0x35, 0x7B, 0x08, 0x90, 0xDA, 0x14, 0x96, 0xB9, + 0x59, 0xBA, 0x67, 0xCA, 0xB5, 0x17, 0x10, 0x09, 0xA5, 0x15, 0xC6, 0x8D, 0x8B, 0xF0, 0xB7, 0x47, 0x89, 0x6C, 0x2F, 0xC0, + 0x08, 0x91, 0xC4, 0x45, 0xBF, 0x4B, 0x8F, 0x46, 0x1C, 0x14, 0x5E, 0xCE, 0xA4, 0x70, 0x66, 0x4C, 0x3E, 0x4B, 0x25, 0x48, + 0x47, 0x24, 0xF9, 0x87, 0xB7, 0x80, 0xED, 0x9C, 0xFA, 0x63, 0xD8, 0xAB, 0x76, 0x9A, 0x33, 0x30, 0x3B, 0x90, 0x96, 0x9A, + 0x90, 0xC6, 0xD6, 0x7D, 0x59, 0x9E, 0x4F, 0xCC, 0x8A, 0xDD, 0x57, 0x25, 0x58, 0x73, 0xEE, 0xB7, 0x68, 0x5A, 0x6C, 0x9D, + 0x7A, 0x68, 0x4B, 0xFD, 0x29, 0x53, 0x40, 0x3D, 0xF7, 0x24, 0x5F, 0xEA, 0xF4, 0x8E, 0x5C, 0x15, 0x49, 0x32, 0x1E, 0x2A, + 0x6C, 0x8D, 0xFF, 0x66, 0x67, 0xD6, 0x4E, 0x25, 0xE5, 0x6F, 0xB6, 0x55, 0x2D, 0x67, 0x12, 0xA2, 0x80, 0x2E, 0xA5, 0x9D, + 0x6A, 0x81, 0x6A, 0x16, 0xD8, 0x3C, 0x2F, 0x54, 0x76, 0x81, 0x33, 0xD4, 0x6F, 0xC6, 0x61, 0x5E, 0x5D, 0xE0, 0xE5, 0x04, + 0x65, 0x6D, 0x90, 0xAA, 0x56, 0xCE, 0x8D, 0x37, 0x6C, 0xD9, 0x69, 0xBA, 0x51, 0xE1, 0x94, 0x7D, 0x30, 0x9F, 0xE3, 0x33, + 0x76, 0x6E, 0x68, 0x47, 0x26, 0x47, 0xB8, 0x57, 0x25, 0xE0, 0x3F, 0x10, 0xC4, 0xE8, 0x30, 0x76, 0x0C, 0xFF, 0xE8, 0xC7, + 0x34, 0x9E, 0x67, 0xE4, 0x13, 0x65, 0xB2, 0x00, 0xB8, 0x87, 0x40, 0x8D, 0xD8, 0x13, 0x22, 0x30, 0xDB, 0x01, 0x5B, 0x27, + 0x8A, 0x0B, 0x62, 0x81, 0xC0, 0xBD, 0xD9, 0x01, 0x25, 0xF6, 0xD1, 0x62, 0xAE, 0xC5, 0xD3, 0xBF, 0xF8, 0xE8, 0xE9, 0xD1, + 0x45, 0xC3, 0xC2, 0xE9, 0xD4, 0x07, 0x5D, 0xF2, 0x0C, 0x5D, 0x36, 0xF0, 0x1A, 0xB8, 0x08, 0xC1, 0xFF, 0x89, 0xCC, 0x73, + 0x6F, 0x3E, 0x2E, 0xDD, 0xFA, 0x74, 0xA8, 0x93, 0x76, 0x83, 0x95, 0xD8, 0xE1, 0x34, 0xE3, 0xC7, 0x80, 0xA6, 0xF2, 0x34, + 0xB2, 0xCA, 0xA3, 0x7C, 0xED, 0x2D, 0x8B, 0xD4, 0xDC, 0x87, 0x0B, 0xD0, 0xCC, 0xA7, 0x3D, 0x79, 0x72, 0x56, 0x8B, 0xEE, + 0x9A, 0xAB, 0x43, 0x1F, 0xAD, 0x4B, 0xBA, 0x40, 0x7A, 0xEF, 0xE7, 0x8E, 0x08, 0x1C, 0xE3, 0xA8, 0x18, 0x1F, 0xF9, 0x08, + 0xB1, 0xAE, 0x5E, 0x15, 0xC0, 0x71, 0x8D, 0xD2, 0xAA, 0x5B, 0x2A, 0xCA, 0xD0, 0xEF, 0x6A, 0x18, 0x45, 0x8F, 0x01, 0x5A, + 0x6C, 0x86, 0xE3, 0xA3, 0xBD, 0xC3, 0xA1, 0xCB, 0xB6, 0x87, 0xB7, 0xEE, 0x8D, 0x3C, 0x12, 0x2F, 0xD2, 0x15, 0x63, 0x5E, + 0x6E, 0x20, 0xBA, 0x5F, 0x99, 0x55, 0x23, 0x7B, 0xFC, 0xC4, 0x43, 0x81, 0xCF, 0xA2, 0xA0, 0x7D, 0x00, 0x96, 0x7B, 0x02, + 0x64, 0x76, 0x35, 0xDD, 0xC3, 0x91, 0x76, 0x24, 0xFD, 0x01, 0x98, 0xF0, 0xDA, 0xD0, 0x7E, 0x93, 0x33, 0x50, 0x9C, 0x41, + 0xE9, 0x4C, 0xE4, 0xB3, 0x1E, 0x09, 0x09, 0xCE, 0x05, 0x4D, 0x65, 0x7A, 0x2A, 0xB1, 0x4B, 0xA5, 0x05, 0x51, 0x8D, 0x37, + 0x57, 0xFF, 0xD2, 0xF1, 0x56, 0xF6, 0xFE, 0x13, 0xE2, 0xAB, 0x45, 0x97, 0xC7, 0xA2, 0xB9, 0xC5, 0x77, 0xDF, 0xAF, 0xA0, + 0x4E, 0xBD, 0x6B, 0xA0, 0x81, 0xA4, 0x52, 0x3A, 0x1A, 0x96, 0xF6, 0x17, 0xD5, 0xE4, 0x54, 0x62, 0x27, 0x9A, 0xB5, 0x3E, + 0xAB, 0xF8, 0xA3, 0x92, 0xDB, 0x4F, 0x84, 0xF4, 0x73, 0xB9, 0x1D, 0x41, 0x23, 0x2C, 0x5D, 0x28, 0xB0, 0xCE, 0x3D, 0xE1, + 0x91, 0xF3, 0xC7, 0x65, 0x77, 0xA6, 0xAD, 0xCB, 0xA3, 0x91, 0x96, 0xDF, 0x12, 0x08, 0xCC, 0x3E, 0x9C, 0xDE, 0x2B, 0x1F, + 0x19, 0xBA, 0x1E, 0x71, 0xA1, 0x6E, 0x13, 0x56, 0x88, 0xC2, 0x31, 0x2E, 0x7F, 0x7C, 0x9B, 0x4C, 0x4F, 0x13, 0x48, 0x3F, + 0xC4, 0xDA, 0x75, 0xB0, 0x3B, 0x73, 0x25, 0x08, 0x69, 0x99, 0x67, 0x3A, 0x61, 0xDD, 0x1C, 0x19, 0xAC, 0xDB, 0x9D, 0x74, + 0xC3, 0xBF, 0x27, 0xA6, 0xFE, 0x77, 0x4F, 0xA7, 0x5B, 0xE1, 0x35, 0x99, 0x1E, 0xDA, 0xE5, 0x58, 0x8E, 0xBD, 0x1F, 0x3A, + 0xCD, 0xBB, 0x53, 0x57, 0x33, 0xB9, 0xCE, 0x16, 0x8F, 0x6A, 0x4A, 0x4A, 0x23, 0xB8, 0x2D, 0xC9, 0x68, 0xF6, 0xF4, 0x1F, + 0xDD, 0xEC, 0x8D, 0x9A, 0x67, 0x10, 0xD5, 0x50, 0x3C, 0xED, 0x1E, 0xBD, 0x5E, 0xD2, 0xBE, 0xEF, 0x79, 0xCF, 0x07, 0x8D, + 0xF5, 0x93, 0xEF, 0xC2, 0x47, 0xC8, 0xA4, 0x99, 0x05, 0xD4, 0xC5, 0x10, 0xDA, 0xFD, 0x0F, 0x98, 0x36, 0x90, 0xB6, 0x64, + 0x1A, 0xB4, 0xBF, 0xCA, 0xFD, 0x9D, 0xD4, 0xB9, 0xFD, 0xBE, 0x60, 0x03, 0x55, 0x0D, 0x1C, 0x80, 0x4B, 0xDB, 0xF4, 0xA4, + 0x5C, 0xE8, 0x90, 0x64, 0x42, 0x2E, 0xA0, 0x31, 0xE8, 0x6B, 0x48, 0x0C, 0x31, 0x2C, 0x7A, 0x30, 0x42, 0xE9, 0x58, 0x2C, + 0x57, 0xBC, 0x19, 0x05, 0x89, 0x81, 0x22, 0x28, 0x4C, 0xB3, 0xBD, 0xB3, 0xDA, 0x9F, 0x85, 0xA1, 0x80, 0x0B, 0x51, 0x30, + 0xB2, 0x47, 0xF2, 0x32, 0x30, 0x9C, 0xB5, 0xB5, 0x91, 0x9B, 0xE1, 0x12, 0x2C, 0x6C, 0x88, 0x22, 0x23, 0x66, 0xC2, 0x50, + 0x90, 0x28, 0x0B, 0x86, 0xAB, 0x2E, 0xC1, 0x60, 0xDA, 0xDF, 0x4A, 0xB2, 0xA2, 0x6B, 0x91, 0xB1, 0xF6, 0xA2, 0x44, 0xFB, + 0x70, 0x2E, 0x58, 0x77, 0x28, 0xCE, 0x21, 0x07, 0x96, 0x0B, 0x7E, 0x27, 0xD2, 0x29, 0x4B, 0x60, 0xE3, 0x06, 0x11, 0x7D, + 0x4E, 0x6C, 0x2B, 0x40, 0x82, 0x97, 0xCB, 0x44, 0x95, 0x77, 0xE3, 0xA1, 0x60, 0x4E, 0x56, 0x71, 0xE0, 0xEE, 0xB8, 0xE8, + 0x5A, 0x0E, 0x42, 0x01, 0x51, 0x6A, 0x5A, 0x31, 0x7B, 0xE0, 0x52, 0x21, 0x11, 0x2A, 0xC8, 0xF0, 0x06, 0x44, 0x2D, 0x20, + 0xE1, 0xF8, 0x9F, 0x77, 0xBC, 0x46, 0x2E, 0x43, 0xFA, 0xC9, 0xAF, 0xCD, 0x29, 0x01, 0xCC, 0xF0, 0x4C, 0x9B, 0xD3, 0x24, + 0xCA, 0x08, 0x90, 0x0D, 0x2D, 0x65, 0x53, 0x98, 0xBA, 0x6A, 0xB8, 0x24, 0x65, 0xBA, 0xAF, 0x46, 0x6A, 0x25, 0x8A, 0x3C, + 0xC4, 0x70, 0x78, 0xCA, 0x87, 0x46, 0xB2, 0x0C, 0x02, 0x2A, 0xD2, 0x6B, 0x30, 0x57, 0x88, 0x7D, 0xFD, 0x77, 0x2A, 0x1E, + 0x1F, 0x02, 0xA8, 0x4D, 0x1A, 0x6D, 0x9A, 0x74, 0xE9, 0x47, 0x87, 0x94, 0x28, 0x20, 0x3B, 0x4B, 0x82, 0x83, 0xEB, 0x32, + 0x3B, 0x40, 0x8F, 0x1F, 0xE9, 0xDE, 0xB6, 0x9D, 0x25, 0x4A, 0x2B, 0x1E, 0x84, 0x02, 0xEF, 0xE4, 0xA8, 0x44, 0xDD, 0x91, + 0xE4, 0x84, 0x83, 0x79, 0x53, 0xD4, 0x10, 0x1F, 0xC9, 0x7A, 0x92, 0xA8, 0x36, 0x60, 0x38, 0x24, 0x7C, 0x2C, 0xEC, 0x62, + 0x58, 0x6B, 0x36, 0x63, 0x11, 0x0A, 0xF4, 0x85, 0x05, 0x37, 0xA5, 0x2E, 0xE3, 0x7D, 0x98, 0xD4, 0x25, 0x77, 0x5D, 0x85, + 0x88, 0xE4, 0xB9, 0xE7, 0xF1, 0x36, 0xB9, 0xCE, 0x3E, 0xAD, 0x59, 0xC3, 0x0F, 0xFB, 0x6C, 0xF7, 0x5E, 0xBE, 0xA1, 0xD8, + 0xB7, 0x63, 0x90, 0x53, 0x4D, 0xAE, 0x31, 0x71, 0x50, 0x7A, 0xFE, 0x20, 0x32, 0x0F, 0xE8, 0xF8, 0x93, 0xC5, 0xEE, 0x52, + 0x6A, 0x84, 0x7C, 0x3D, 0xD1, 0x11, 0x8C, 0x0C, 0x34, 0x54, 0xF4, 0x68, 0x90, 0x33, 0x59, 0x18, 0x4C, 0x9E, 0xE4, 0x0B, + 0x40, 0x43, 0xD1, 0xA7, 0x83, 0x76, 0xBD, 0x47, 0x3B, 0x87, 0x95, 0xED, 0x40, 0x5E, 0xAD, 0x67, 0x72, 0x1D, 0x73, 0x8C, + 0xC2, 0x37, 0xED, 0x34, 0x12, 0xC8, 0xDD, 0x83, 0x61, 0x5B, 0x65, 0xB2, 0x2D, 0x7F, 0x17, 0xCF, 0xF6, 0x10, 0x2A, 0xF3, + 0x9B, 0x3E, 0x6E, 0x2C, 0x74, 0xF0, 0x80, 0xDF, 0x3B, 0x73, 0x0D, 0x4E, 0x0A, 0x59, 0x22, 0xE3, 0x9A, 0x7B, 0x7C, 0xA8, + 0x68, 0x0B, 0xD9, 0xF9, 0x49, 0x71, 0x87, 0xA8, 0x76, 0x58, 0xAB, 0xD4, 0xBE, 0x6A, 0xFB, 0x3B, 0x05, 0x87, 0x95, 0xDE, + 0xC0, 0x73, 0x1B, 0x16, 0x48, 0xA4, 0x8C, 0x4B, 0xBF, 0x6B, 0xDF, 0xA1, 0xBC, 0x51, 0xFF, 0xBF, 0x92, 0x76, 0x5E, 0xD9, + 0xCB, 0x07, 0x6A, 0x4E, 0xB3, 0xED, 0xE9, 0x0A, 0x59, 0x37, 0x56, 0xEF, 0x01, 0x67, 0x7A, 0xBE, 0xD4, 0x73, 0xD9, 0xBE, + 0xF9, 0x3D, 0x9E, 0xF4, 0xC9, 0x57, 0x1E, 0x78, 0x67, 0x6E, 0x9B, 0x3F, 0x8E, 0x05, 0xFF, 0x52, 0x38, 0x12, 0xED, 0x5B, + 0xEE, 0x6E, 0x0B, 0x9B, 0x18, 0x7C, 0x2D, 0xD8, 0xA8, 0x3C, 0xC7, 0xD4, 0xD0, 0xC7, 0x5D, 0x11, 0xC4, 0x94, 0x64, 0x79, + 0xEF, 0x68, 0x98, 0xE2, 0x08, 0xC0, 0x13, 0x2B, 0x12, 0x59, 0x50, 0x61, 0x15, 0xCD, 0x10, 0x50, 0x52, 0xB0, 0x71, 0x37, + 0xA0, 0x03, 0x68, 0x0E, 0xD2, 0xA8, 0xB5, 0x50, 0x87, 0x81, 0xAD, 0x66, 0xD5, 0x4E, 0x6A, 0x51, 0x03, 0xA3, 0x35, 0x78, + 0xB5, 0x49, 0x53, 0x85, 0x46, 0xEE, 0xDC, 0x58, 0x77, 0x4F, 0xD1, 0x11, 0xCD, 0x98, 0x32, 0x06, 0xAD, 0x28, 0x31, 0x16, + 0xF6, 0x6B, 0xA8, 0x48, 0xF4, 0x83, 0x7E, 0x6A, 0x27, 0x24, 0x5A, 0xB9, 0x77, 0x84, 0x74, 0xE6, 0x16, 0xC0, 0xA9, 0x83, + 0xB3, 0x6E, 0x7C, 0x20, 0x85, 0xA1, 0x6C, 0xB6, 0x65, 0xBE, 0x00, 0x55, 0xE4, 0xC3, 0xAF, 0x9E, 0x78, 0x28, 0x5F, 0x6B, + 0x25, 0xC8, 0xF9, 0x56, 0x6B, 0x2F, 0x4B, 0xE1, 0x43, 0x7C, 0x76, 0x07, 0xD2, 0xC2, 0xE2, 0xB1, 0xA5, 0xA6, 0x8C, 0x31, + 0xD7, 0xE8, 0x59, 0x93, 0xC1, 0xB7, 0xA1, 0xF7, 0xD1, 0x97, 0xB6, 0xFA, 0x00, 0xC7, 0xAA, 0x3F, 0x28, 0xEA, 0x8A, 0xC4, + 0x5C, 0x85, 0x3E, 0x06, 0x5E, 0xEE, 0x54, 0x33, 0xE4, 0x71, 0xD2, 0x6D, 0x40, 0x2E, 0x15, 0x55, 0x94, 0x55, 0xE3, 0x38, + 0xB8, 0x36, 0x7D, 0x27, 0xD0, 0x07, 0x22, 0x6C, 0x75, 0xBB, 0xCE, 0xAF, 0xD0, 0x62, 0x9F, 0x63, 0x7D, 0x15, 0x31, 0x1A, + 0xAE, 0xCB, 0x2B, 0x12, 0xFE, 0xA3, 0x82, 0x61, 0xCB, 0xEB, 0x24, 0x5F, 0x9D, 0x36, 0xE6, 0x39, 0x3E, 0x83, 0x82, 0x4C, + 0x3D, 0xA1, 0x4E, 0x2A, 0x52, 0xCA, 0xA3, 0x10, 0x58, 0xBC, 0x7E, 0x46, 0xE6, 0xE7, 0xA2, 0x67, 0xFE, 0x52, 0xC1, 0xE5, + 0x4E, 0x8D, 0x26, 0x8A, 0x5D, 0xAF, 0x33, 0xCF, 0xCC, 0x8F, 0x1C, 0x29, 0x11, 0x58, 0x53, 0x8E, 0x6F, 0x31, 0x82, 0x2F, + 0x92, 0xF5, 0x33, 0x42, 0xBC, 0xCB, 0x2B, 0x23, 0x6E, 0xA9, 0x5F, 0x82, 0xFC, 0xA4, 0xF8, 0x7D, 0x3E, 0xE9, 0x93, 0xAA, + 0x22, 0x21, 0xC9, 0xF9, 0x97, 0x10, 0x72, 0xE5, 0x85, 0x26, 0x4F, 0xF4, 0x7A, 0x92, 0x97, 0x70, 0x89, 0x6C, 0x8C, 0x43, + 0x94, 0x4E, 0xC7, 0x5A, 0x2C, 0x93, 0x7C, 0x73, 0x45, 0xFE, 0x37, 0x01, 0x2D, 0xEA, 0x34, 0x96, 0x80, 0xB4, 0xCA, 0x53, + 0xAC, 0x04, 0xFF, 0xA2, 0xD6, 0xFF, 0x55, 0x6A, 0xAD, 0x66, 0x01, 0xE4, 0xC5, 0x45, 0xB8, 0x33, 0xE3, 0xA3, 0xDD, 0xF0, + 0xF2, 0x78, 0x3D, 0x79, 0x83, 0x1D, 0x64, 0x2E, 0xAC, 0x3F, 0xF0, 0x0A, 0x49, 0x19, 0xBC, 0xEF, 0x45, 0x9F, 0xA0, 0x40, + 0x2F, 0x9F, 0x69, 0x08, 0x34, 0xF5, 0xFD, 0x50, 0x66, 0xE5, 0xD4, 0x89, 0xD4, 0xEE, 0x63, 0xA3, 0x92, 0x3B, 0x1A, 0x21, + 0x92, 0xF4, 0x07, 0xE6, 0xB2, 0x94, 0x2F, 0xC7, 0x17, 0xF0, 0x7F, 0xA0, 0xA8, 0x9C, 0xC9, 0x2E, 0x1B, 0xBA, 0x24, 0x16, + 0x80, 0x57, 0x21, 0x81, 0x15, 0xF6, 0x37, 0x0E, 0x54, 0x19, 0x98, 0xA3, 0xFE, 0xB8, 0x9B, 0xD4, 0xCF, 0xBD, 0xB2, 0x4C, + 0xF9, 0xD9, 0x56, 0xBD, 0xD0, 0x96, 0x51, 0xD9, 0xD4, 0x68, 0xFE, 0xD8, 0x9E, 0xBC, 0x12, 0x7A, 0xDE, 0x04, 0x47, 0xC8, + 0xF5, 0x47, 0xEF, 0x96, 0x10, 0xB7, 0x88, 0x49, 0xEA, 0x4A, 0x97, 0xBE, 0x1D, 0xFC, 0x98, 0xB3, 0xAB, 0x19, 0x48, 0xEC, + 0xC5, 0x3D, 0x07, 0x40, 0xEB, 0x4B, 0xE7, 0x36, 0x7F, 0x97, 0xE2, 0xB5, 0x0F, 0x3C, 0x19, 0xB0, 0xB1, 0x4A, 0x4C, 0x68, + 0xEF, 0x21, 0xF1, 0x6A, 0x62, 0xEF, 0x39, 0x32, 0xAB, 0x50, 0xB7, 0xFD, 0x9A, 0xB4, 0x34, 0xE7, 0x90, 0x54, 0xF6, 0xEE, + 0x4C, 0x96, 0x37, 0xFE, 0xAA, 0xBA, 0xEF, 0xCB, 0x36, 0x05, 0x0F, 0x03, 0xC1, 0x13, 0x4C, 0x6B, 0xEA, 0xE9, 0x90, 0xBB, + 0xA3, 0x84, 0x6F, 0xDC, 0xC4, 0xBE, 0xFF, 0x9B, 0xE3, 0x28, 0x25, 0x5F, 0xCC, 0x94, 0xBA, 0xB2, 0x22, 0x42, 0x40, 0x1C, + 0x61, 0x28, 0x95, 0xC8, 0xC4, 0x8D, 0xC3, 0x03, 0xF1, 0xCF, 0xC8, 0x1C, 0xB3, 0x0B, 0xD1, 0x40, 0x17, 0x51, 0xE2, 0xD8, + 0x32, 0x0E, 0x58, 0xA0, 0xD8, 0x23, 0xC1, 0x0C, 0xB2, 0xDF, 0x91, 0x87, 0x1D, 0x1B, 0x49, 0x35, 0xF3, 0x29, 0xC6, 0x56, + 0xEA, 0xE2, 0x0C, 0xF9, 0xAE, 0xC8, 0x71, 0xD5, 0xD7, 0x25, 0x23, 0xC2, 0xCE, 0x58, 0x18, 0x13, 0x3A, 0xB0, 0x93, 0x30, + 0x82, 0x12, 0x69, 0xC0, 0x4C, 0xE6, 0x70, 0x71, 0xCF, 0x27, 0x17, 0xF0, 0x54, 0x96, 0x0A, 0xAB, 0xEA, 0x36, 0xDD, 0x73, + 0xB2, 0x8A, 0x25, 0x8F, 0xC1, 0x29, 0x83, 0xF0, 0x0D, 0x3F, 0x49, 0x4C, 0x6B, 0x75, 0xBF, 0x42, 0x33, 0x89, 0xFA, 0xC4, + 0x17, 0x58, 0x56, 0x9A, 0xD4, 0x94, 0x2E, 0x91, 0x87, 0x49, 0x58, 0xBC, 0x9B, 0x65, 0xC0, 0x73, 0xF7, 0xCC, 0x19, 0xE0, + 0x62, 0x6F, 0x0A, 0x7A, 0x8A, 0x04, 0x2A, 0x19, 0xB9, 0x2E, 0xB2, 0xDE, 0x6C, 0xBC, 0x26, 0x4E, 0xB3, 0x9B, 0xB0, 0xC8, + 0x55, 0xF6, 0x91, 0x5C, 0x0D, 0x2F, 0x22, 0xD8, 0x4D, 0x65, 0xA4, 0x94, 0x1B, 0x2B, 0xBC, 0xEB, 0xBB, 0x61, 0xAF, 0x54, + 0x9E, 0xBA, 0x84, 0xAB, 0x09, 0x8B, 0xAD, 0x81, 0x9A, 0x95, 0x11, 0x39, 0xA8, 0x6B, 0x27, 0xCD, 0xAA, 0x13, 0x33, 0xBB, + 0x49, 0xD4, 0x59, 0x66, 0xDF, 0x3B, 0x17, 0x3B, 0x3C, 0x8D, 0x05, 0x36, 0xBB, 0xB3, 0x56, 0x94, 0x4A, 0x59, 0x5F, 0x1F, + 0x6A, 0xCD, 0xE6, 0xC3, 0x0A, 0x4C, 0xF1, 0x02, 0x1D, 0xDF, 0xF6, 0xDD, 0x9E, 0x2E, 0x7A, 0x0E, 0x39, 0x41, 0xB8, 0xB2, + 0x63, 0xED, 0x77, 0x2F, 0x65, 0xF2, 0xC4, 0x61, 0x4A, 0xEE, 0xEB, 0x5D, 0x46, 0xC1, 0xA7, 0x2A, 0x82, 0x4D, 0xF0, 0xD9, + 0xC5, 0x3B, 0xF0, 0xB3, 0x70, 0xB0, 0x1B, 0xE0, 0x87, 0x90, 0x5D, 0x65, 0xC5, 0xEF, 0x9A, 0xB9, 0x11, 0x50, 0x2B, 0xC2, + 0xD7, 0x35, 0xF3, 0xE4, 0x28, 0xDD, 0xB3, 0x22, 0x03, 0xB1, 0xF2, 0x34, 0xDA, 0x12, 0x9B, 0x8E, 0x47, 0xA4, 0xA2, 0x01, + 0xFC, 0xC7, 0x1F, 0x01, 0x81, 0x92, 0x02, 0x87, 0x01, 0xBF, 0x2D, 0x4E, 0xF5, 0x5B, 0x44, 0x35, 0x2A, 0xCD, 0x54, 0x1A, + 0x04, 0x93, 0x32, 0xE4, 0xB2, 0x3A, 0xC9, 0x49, 0xE1, 0xE8, 0xD5, 0xB1, 0x78, 0xD6, 0xE8, 0x52, 0x26, 0x1C, 0x99, 0xC1, + 0xEF, 0x49, 0xC4, 0x1B, 0x83, 0xAB, 0xEB, 0x06, 0x74, 0x86, 0x1E, 0x10, 0x7B, 0xB8, 0x61, 0xBF, 0xAE, 0x80, 0x4A, 0x92, + 0x9C, 0x88, 0xA3, 0x70, 0x2D, 0x1A, 0xC7, 0xB2, 0x88, 0xB0, 0x6A, 0x9B, 0x07, 0xEA, 0x95, 0x3C, 0x2A, 0xAB, 0x8E, 0x61, + 0xAC, 0x2C, 0x1D, 0x96, 0x61, 0x37, 0xDE, 0xEF, 0x8F, 0x75, 0xCD, 0x0A, 0xE5, 0xAD, 0x83, 0x17, 0xF7, 0x8A, 0xFE, 0x0C, + 0x34, 0xC6, 0x42, 0x08, 0x27, 0x85, 0x96, 0x2C, 0x6C, 0x49, 0xA8, 0x0C, 0x9A, 0x58, 0xF1, 0xE6, 0xA6, 0xEF, 0x40, 0x8C, + 0xD2, 0x3A, 0xB6, 0x11, 0xD4, 0x85, 0x1A, 0xDC, 0x29, 0xD4, 0x0F, 0xBC, 0x04, 0x17, 0x2B, 0xFE, 0xAB, 0x9C, 0xB4, 0x0D, + 0x34, 0x39, 0x15, 0xDE, 0xD2, 0xF3, 0x47, 0x04, 0x9A, 0x5F, 0x23, 0xEE, 0xFE, 0x9D, 0xA6, 0xE7, 0x59, 0xAA, 0xCF, 0xCD, + 0xF1, 0x70, 0x4E, 0xC0, 0xC3, 0x3F, 0x4E, 0x01, 0x3C, 0xCE, 0x70, 0x97, 0x02, 0x51, 0x16, 0xFC, 0xA3, 0xE1, 0xA6, 0x71, + 0x0B, 0x2E, 0xF9, 0xE0, 0xCB, 0x8C, 0x20, 0xD0, 0x08, 0xF7, 0x59, 0x43, 0x77, 0xB3, 0x21, 0x78, 0xAB, 0x5E, 0x57, 0x82, + 0x03, 0x42, 0xA8, 0x97, 0xCE, 0xD3, 0xAF, 0xCA, 0x03, 0x71, 0x8D, 0x5B, 0x26, 0x46, 0x78, 0xF1, 0x4F, 0x0E, 0x49, 0xD1, + 0x58, 0x12, 0xD9, 0xD5, 0x12, 0x6E, 0xD7, 0x42, 0x40, 0x86, 0x60, 0x0B, 0xB3, 0xA8, 0x08, 0xD3, 0x62, 0xC0, 0x00, 0xD5, + 0x55, 0x85, 0x50, 0xFA, 0x2A, 0x4C, 0x3F, 0xFC, 0xF4, 0xEE, 0x3A, 0xC3, 0x2F, 0x61, 0x69, 0xA6, 0xAA, 0x4C, 0x09, 0x7C, + 0x25, 0x02, 0xA0, 0xF7, 0xDF, 0x03, 0x4F, 0x86, 0xAF, 0x41, 0x89, 0xD4, 0xDD, 0x4F, 0x5B, 0x53, 0xCD, 0xC1, 0x39, 0x65, + 0x6A, 0x5E, 0x59, 0x31, 0x22, 0xCE, 0xEC, 0x27, 0xD3, 0x21, 0x63, 0xAA, 0xEF, 0x8C, 0xA8, 0xDA, 0x10, 0x56, 0x10, 0x20, + 0xBF, 0xC0, 0x30, 0xFB, 0x72, 0xA6, 0xAC, 0x2D, 0xCD, 0xE6, 0xD0, 0xA9, 0xC2, 0x38, 0x78, 0x58, 0x3B, 0xD5, 0x7F, 0x89, + 0x51, 0x17, 0x7B, 0x41, 0x14, 0x8C, 0x1D, 0x25, 0x65, 0xC3, 0x33, 0x93, 0xCE, 0x1D, 0x36, 0x9F, 0xD0, 0x14, 0x57, 0xF7, + 0x81, 0xF7, 0x42, 0xD3, 0xC9, 0xC8, 0x59, 0x62, 0x4A, 0xA4, 0x3B, 0xF3, 0x89, 0x56, 0xA3, 0xA8, 0x0D, 0xB8, 0x0E, 0x9D, + 0x1F, 0xA2, 0x2A, 0x32, 0xED, 0x37, 0x9D, 0xAA, 0x48, 0xAD, 0xC6, 0x88, 0x45, 0x81, 0xD4, 0x18, 0xFC, 0x2A, 0x68, 0x58, + 0x0E, 0x39, 0xDA, 0x79, 0x2C, 0xE4, 0x43, 0x49, 0x71, 0x87, 0x63, 0xFF, 0x20, 0x5B, 0x19, 0xFB, 0x90, 0x65, 0x48, 0x08, + 0x7D, 0x15, 0xAF, 0x1F, 0x96, 0x6F, 0x1D, 0xEC, 0x11, 0xA6, 0x45, 0x8A, 0x4F, 0xC7, 0xC4, 0x4C, 0xBB, 0x85, 0x72, 0x0A, + 0x12, 0x21, 0x22, 0xD3, 0x8E, 0xA6, 0xD9, 0xCF, 0x9B, 0xD2, 0xC8, 0x91, 0x58, 0x1E, 0x3F, 0xC5, 0x0C, 0xCD, 0xD2, 0xA1, + 0xDE, 0x27, 0x45, 0x18, 0x1A, 0xC2, 0xC1, 0x01, 0x59, 0x1F, 0xB6, 0xDB, 0x71, 0x23, 0x66, 0xCD, 0x1E, 0x05, 0x0E, 0x94, + 0x4C, 0xC2, 0x7C, 0x94, 0xD8, 0x1C, 0x83, 0xF2, 0x66, 0x8C, 0x6C, 0x7F, 0x3E, 0xEF, 0xCF, 0x19, 0x92, 0xC0, 0xE6, 0x05, + 0x7C, 0x8A, 0x9E, 0x62, 0x32, 0x8B, 0xEA, 0x96, 0xDF, 0x93, 0x35, 0xA0, 0x2C, 0x0C, 0xFB, 0xD5, 0x5E, 0x79, 0x6E, 0x16, + 0x75, 0xE5, 0xE5, 0x22, 0xFD, 0x1B, 0x55, 0x59, 0x47, 0xDC, 0x6E, 0x71, 0xB7, 0xD1, 0x7E, 0xE5, 0x5B, 0x9B, 0x83, 0x52, + 0xDA, 0x16, 0x99, 0x26, 0x31, 0xB0, 0xB7, 0x47, 0xBB, 0x5F, 0x25, 0x8E, 0xCE, 0x6B, 0xFC, 0x84, 0xF2, 0x80, 0xBD, 0xF0, + 0x64, 0x58, 0xF5, 0x92, 0x1C, 0x40, 0x5C, 0x3C, 0x8A, 0x99, 0x24, 0x82, 0x29, 0xF6, 0x2C, 0xE6, 0xCF, 0x4A, 0x58, 0x74, + 0x2A, 0xFE, 0x6A, 0x8C, 0xAA, 0xF7, 0xFB, 0x26, 0x56, 0x14, 0xAE, 0xCD, 0xE3, 0x7A, 0x83, 0x72, 0x2C, 0x0E, 0x54, 0xFE, + 0xB6, 0x92, 0x22, 0x53, 0xB0, 0x44, 0x4B, 0xCB, 0xE0, 0x24, 0x75, 0xA4, 0x61, 0xB7, 0xC6, 0x56, 0x34, 0xA8, 0xFC, 0x3D, + 0x12, 0x3E, 0xE8, 0xEC, 0x97, 0x7A, 0x11, 0x88, 0x35, 0xF7, 0xA6, 0xF5, 0x6D, 0x92, 0x80, 0x47, 0x0A, 0x1C, 0x78, 0x9B, + 0x10, 0xC7, 0x76, 0xB6, 0x4F, 0x55, 0xD5, 0x7C, 0xCC, 0x96, 0xEC, 0x1A, 0x7B, 0x95, 0x16, 0x38, 0xAC, 0x78, 0xF6, 0x2F, + 0x94, 0x0A, 0xDF, 0x63, 0x36, 0x11, 0x6E, 0x22, 0x55, 0xA9, 0x8F, 0x4B, 0xE8, 0xF6, 0xE4, 0xDF, 0x7C, 0xEC, 0xBF, 0xE8, + 0xA2, 0x90, 0x6F, 0x93, 0x19, 0x14, 0x07, 0x39, 0x64, 0xA3, 0x7F, 0xA7, 0xCE, 0x56, 0x36, 0xA8, 0x7C, 0x17, 0xE2, 0x2E, + 0x07, 0xFE, 0x67, 0x6E, 0x30, 0xB4, 0x4D, 0x7C, 0x76, 0xBD, 0x54, 0x3C, 0x6F, 0x46, 0x29, 0x83, 0x39, 0x5F, 0xD9, 0xC6, + 0x69, 0x2F, 0x7A, 0x1C, 0xFD, 0xF5, 0x29, 0xFA, 0xD2, 0x81, 0x20, 0xDF, 0x41, 0xFC, 0xC0, 0xED, 0x05, 0x6F, 0x97, 0xAF, + 0xE3, 0x75, 0x6F, 0xF1, 0xD3, 0x8F, 0xD6, 0x1F, 0xB9, 0xFD, 0x7D, 0x14, 0x7A, 0x02, 0x76, 0x8D, 0x5C, 0xBE, 0x3A, 0xE8, + 0x24, 0x4F, 0x7F, 0x77, 0x64, 0x4C, 0xEB, 0x53, 0x21, 0x2C, 0x21, 0xDB, 0xB9, 0x23, 0x6E, 0x65, 0xEA, 0xD0, 0x3E, 0x53, + 0xF8, 0x7B, 0x0A, 0xCE, 0xAA, 0xC8, 0xCC, 0xE4, 0xE5, 0xDE, 0xAD, 0xE9, 0x14, 0xCF, 0x66, 0x45, 0x94, 0x03, 0xF2, 0x61, + 0x88, 0xBF, 0xDB, 0x0B, 0x27, 0xCF, 0x50, 0x0A, 0x87, 0x4B, 0xEF, 0x28, 0x6E, 0x5E, 0x40, 0xB9, 0x28, 0xCA, 0xA7, 0x95, + 0x92, 0x32, 0x41, 0x26, 0xFD, 0x46, 0xFA, 0xAC, 0x1E, 0x6B, 0xC1, 0x20, 0x66, 0x06, 0xCC, 0x82, 0xD0, 0xB0, 0xF0, 0xAE, + 0x13, 0x48, 0x59, 0xAB, 0x9E, 0x83, 0x66, 0x59, 0xCE, 0xE3, 0x5C, 0x12, 0xDE, 0x93, 0x4E, 0xBD, 0xB1, 0xA4, 0x98, 0x74, + 0x37, 0x87, 0xD9, 0x65, 0x29, 0x57, 0x0A, 0x07, 0x2D, 0x7D, 0xB6, 0xD5, 0xDA, 0xDC, 0x58, 0x95, 0x97, 0xDC, 0x48, 0xB1, + 0xD5, 0x5C, 0xD1, 0x64, 0x32, 0x28, 0x43, 0x1B, 0xAB, 0xF9, 0x6E, 0x93, 0x19, 0x48, 0xEA, 0xC0, 0x60, 0x05, 0xE9, 0x5F, + 0x2C, 0xC3, 0x34, 0x25, 0x28, 0x89, 0xF4, 0xB9, 0xF2, 0x6A, 0xE2, 0x98, 0x05, 0x79, 0xEE, 0xCF, 0xDD, 0xE4, 0x5A, 0x1B, + 0xEF, 0xFA, 0x2E, 0x72, 0x05, 0xA7, 0x05, 0x59, 0xFB, 0x78, 0xEB, 0x25, 0x38, 0xEB, 0xF1, 0xF1, 0x51, 0xCB, 0xF5, 0xBC, + 0x72, 0x28, 0xA3, 0xD1, 0xDB, 0x04, 0xC9, 0x26, 0x32, 0x0F, 0x22, 0x56, 0x0F, 0x01, 0x3D, 0x3F, 0x26, 0x42, 0x56, 0x0E, + 0x0A, 0x03, 0x12, 0xB5, 0xE3, 0x2D, 0x42, 0x5D, 0xE2, 0xE4, 0x8A, 0x3A, 0x38, 0xED, 0x64, 0x51, 0x23, 0xA4, 0xF2, 0x7B, + 0xDA, 0x29, 0xEF, 0xA1, 0x1E, 0xC8, 0x24, 0x0D, 0xF4, 0x35, 0x31, 0x68, 0xCB, 0x6C, 0xFB, 0x0F, 0x5B, 0x61, 0x33, 0x2B, + 0x09, 0xDB, 0xC9, 0xBB, 0x7A, 0x34, 0xA4, 0xFD, 0x8E, 0x42, 0xF3, 0xBF, 0xB0, 0x61, 0x5D, 0x81, 0x87, 0x0B, 0x50, 0xD9, + 0xDB, 0x53, 0xB2, 0xD3, 0xC3, 0x9F, 0x54, 0xE5, 0xAB, 0x7D, 0x4B, 0x12, 0x03, 0xE1, 0x5C, 0xE7, 0x1B, 0x89, 0xBE, 0xCF, + 0x86, 0xDC, 0x68, 0xC5, 0xD2, 0x30, 0xC0, 0x67, 0x82, 0x30, 0xBB, 0x21, 0xE5, 0x9D, 0xD5, 0x69, 0xE0, 0x49, 0xCC, 0xB2, + 0x94, 0x74, 0x35, 0xD6, 0x6B, 0x9A, 0xF3, 0x34, 0x58, 0x30, 0x7D, 0xAF, 0x9E, 0x5C, 0x35, 0x1C, 0xF7, 0x99, 0xE3, 0xE9, + 0x11, 0xD0, 0x84, 0xA2, 0x70, 0x7B, 0x41, 0x92, 0x9D, 0x4F, 0x60, 0x86, 0x8D, 0x72, 0x13, 0x51, 0x25, 0xE4, 0xDA, 0xA1, + 0xCC, 0x77, 0x3C, 0xEE, 0x22, 0x58, 0xA4, 0x76, 0xF2, 0x28, 0xFF, 0x3E, 0x9D, 0x47, 0xE5, 0xCD, 0x5B, 0x07, 0x15, 0x87, + 0xC3, 0x46, 0xFD, 0x8A, 0x53, 0x87, 0x5F, 0xCE, 0x93, 0xBA, 0x47, 0xB7, 0x31, 0xE3, 0xF1, 0x62, 0xDB, 0xA8, 0xE5, 0x49, + 0x50, 0x6C, 0x5F, 0xA9, 0x8F, 0x55, 0x8D, 0x7F, 0x1A, 0x48, 0x76, 0xAA, 0xEC, 0x55, 0xD4, 0x44, 0x3A, 0x35, 0x74, 0x88, + 0x8E, 0x14, 0x5A, 0x4C, 0x72, 0xC6, 0x9E, 0x55, 0x61, 0xF4, 0x4D, 0x5A, 0xFE, 0x4A, 0xF8, 0x29, 0x45, 0x0A, 0x06, 0x8F, + 0x2D, 0x97, 0xBB, 0x2C, 0x57, 0x51, 0x00, 0x4B, 0xEA, 0x37, 0x71, 0xE9, 0x2E, 0xFB, 0xB1, 0x39, 0xFA, 0x91, 0xD6, 0xB6, + 0x4A, 0xDF, 0x5F, 0x68, 0xBB, 0x60, 0x57, 0x3A, 0x0B, 0x7C, 0x95, 0xAE, 0xC5, 0x91, 0xE9, 0x2F, 0xA8, 0x1C, 0x46, 0x8A, + 0x5B, 0x3C, 0x6F, 0xAE, 0x40, 0x12, 0x4A, 0x58, 0x2C, 0x45, 0xA5, 0x38, 0x2B, 0xD0, 0xC4, 0xFD, 0x5A, 0x3D, 0x61, 0xE1, + 0x92, 0x05, 0x56, 0x0A, 0x64, 0x36, 0x5F, 0xE0, 0x17, 0xD8, 0xE3, 0x69, 0x13, 0xD7, 0xC8, 0xEB, 0x98, 0xFB, 0x96, 0xDC, + 0x1E, 0x34, 0x06, 0x79, 0x4C, 0x59, 0xFB, 0x66, 0x79, 0xAB, 0x79, 0x19, 0xE1, 0xEE, 0x59, 0x68, 0x99, 0x06, 0x69, 0xAB, + 0xAD, 0x49, 0x70, 0x36, 0x69, 0x40, 0xF2, 0x1E, 0x36, 0x05, 0x5E, 0x3B, 0xFE, 0xE5, 0x58, 0x92, 0x5D, 0xCE, 0x4C, 0x56, + 0xBC, 0x08, 0x43, 0x0F, 0x85, 0x42, 0x36, 0xC7, 0xB6, 0x29, 0xC9, 0xCB, 0xD6, 0x8F, 0x22, 0x26, 0x2F, 0xE4, 0xF3, 0x0E, + 0x83, 0xCB, 0x93, 0xA7, 0x15, 0x0C, 0x60, 0xBA, 0x60, 0xC5, 0xC1, 0xDF, 0x41, 0x2E, 0x47, 0xA0, 0x35, 0xE6, 0x64, 0xA0, + 0x25, 0xA6, 0xB0, 0xBB, 0xFF, 0xC0, 0xB0, 0xC6, 0x4E, 0x06, 0x2E, 0xB4, 0x17, 0xCA, 0x8A, 0x46, 0x16, 0xE4, 0x80, 0x9A, + 0x23, 0x88, 0x0C, 0xF0, 0x69, 0xA9, 0x99, 0x4B, 0x21, 0x9D, 0x59, 0x57, 0x31, 0xCA, 0x73, 0x11, 0xF5, 0xE6, 0x19, 0x76, + 0x72, 0x56, 0x09, 0x0C, 0x66, 0xC5, 0x89, 0x55, 0xEC, 0xAA, 0x86, 0x9B, 0xD9, 0x8A, 0xAA, 0xF3, 0x8C, 0x58, 0x6A, 0x88, + 0x2E, 0xB8, 0x06, 0x6C, 0xA7, 0x25, 0x62, 0x37, 0xEF, 0xA4, 0x06, 0xCC, 0x67, 0x58, 0xAC, 0x68, 0x3E, 0x88, 0xD1, 0x54, + 0xA4, 0xB5, 0x44, 0x06, 0x7E, 0xDD, 0x39, 0x58, 0xF1, 0xE6, 0x1B, 0xF8, 0xED, 0xC6, 0x7C, 0x0E, 0x6B, 0x15, 0x0D, 0x5B, + 0x06, 0x23, 0x0F, 0x08, 0x7F, 0xF1, 0xD3, 0xF3, 0x8F, 0xC4, 0x6B, 0x0F, 0xBF, 0x06, 0xFB, 0x7F, 0xDF, 0xD0, 0x0F, 0xCF, + 0xD5, 0xE4, 0xEA, 0x1A, 0x65, 0xDD, 0xA8, 0xEE, 0xE1, 0x5B, 0x70, 0x8C, 0xC1, 0x3A, 0xAD, 0x6C, 0xBF, 0x13, 0x95, 0xB7, + 0x3B, 0x00, 0xB2, 0x4F, 0x2C, 0xE9, 0x40, 0x9C, 0x49, 0x55, 0xF8, 0x5D, 0x52, 0xEB, 0x9C, 0xA3, 0x1E, 0x43, 0xA3, 0xCF, + 0x77, 0xC4, 0x3B, 0x6F, 0xE7, 0x54, 0x33, 0xBE, 0x2C, 0xA0, 0x14, 0xDF, 0xF3, 0x0E, 0x51, 0x3F, 0xD3, 0xB4, 0x9F, 0x64, + 0xFB, 0x1B, 0xAB, 0x79, 0x7E, 0x30, 0x7D, 0xA3, 0x81, 0x8B, 0x5F, 0xF5, 0x1E, 0x3A, 0x4A, 0x9F, 0x8D, 0x8A, 0x76, 0xC0, + 0x08, 0xBF, 0x55, 0xE1, 0x44, 0xFF, 0xE6, 0x07, 0xC6, 0x1C, 0x44, 0xD2, 0x61, 0x71, 0xDC, 0xA8, 0xAD, 0xFC, 0x35, 0x65, + 0xA2, 0x48, 0xEB, 0x7C, 0x5D, 0xB1, 0x90, 0x41, 0x24, 0x7F, 0xF4, 0xC1, 0x82, 0xBD, 0x4B, 0xE6, 0xA6, 0x33, 0x3E, 0x66, + 0x16, 0xA3, 0xAA, 0xC0, 0xF2, 0x72, 0xBF, 0x55, 0x77, 0x27, 0xF6, 0x3D, 0x20, 0xAE, 0x22, 0x2E, 0x34, 0xF9, 0xD7, 0xB2, + 0x8F, 0xE5, 0x83, 0x84, 0x55, 0x76, 0x0C, 0x94, 0x7E, 0x9A, 0xEC, 0xC9, 0x07, 0xAE, 0x5E, 0x01, 0x57, 0xCE, 0x98, 0x1E, + 0x3F, 0x08, 0xB1, 0xBD, 0x4D, 0xE7, 0xBD, 0x43, 0xB0, 0xAC, 0x0D, 0x12, 0x45, 0x26, 0x42, 0x8B, 0xF0, 0x0C, 0x34, 0x57, + 0x02, 0x68, 0x4F, 0xA1, 0xDE, 0xA6, 0x5C, 0x87, 0xC6, 0x55, 0x05, 0xC8, 0xCA, 0xB5, 0x18, 0xFF, 0x6C, 0x37, 0x94, 0xBE, + 0xC4, 0x17, 0xA1, 0x3A, 0xA4, 0x29, 0x65, 0xCC, 0x5D, 0xEB, 0xD1, 0xDD, 0x1E, 0xCD, 0xD0, 0x99, 0x3B, 0x39, 0xC6, 0xC8, + 0xD2, 0x76, 0xA4, 0xAE, 0x5E, 0xFA, 0x3D, 0x63, 0x8C, 0xD7, 0x07, 0xFD, 0xDE, 0x0E, 0x4F, 0xB9, 0xDF, 0x68, 0xD7, 0xB1, + 0x24, 0xF7, 0x95, 0x04, 0x52, 0x19, 0x32, 0xEC, 0x93, 0x31, 0xAC, 0x53, 0xB7, 0x96, 0xE6, 0x3A, 0x58, 0x24, 0x58, 0xE6, + 0xA3, 0x6A, 0xFE, 0xDA, 0xDA, 0xAD, 0x48, 0xC2, 0x5D, 0x18, 0x3D, 0xF5, 0x4D, 0x1C, 0x50, 0xF7, 0x21, 0xFF, 0xD0, 0x1B, + 0x1E, 0x7D, 0x3E, 0x0A, 0x67, 0x92, 0x49, 0x93, 0x79, 0x07, 0x2F, 0xCF, 0x72, 0xCF, 0xDD, 0x27, 0xB2, 0xF1, 0xED, 0x8B, + 0xB6, 0xC5, 0x48, 0x09, 0x7E, 0xBC, 0x25, 0x66, 0x22, 0x39, 0xB6, 0xDA, 0x1A, 0x1E, 0x26, 0xED, 0x0B, 0xCE, 0x9B, 0x17, + 0xB3, 0x02, 0xF8, 0x3F, 0x35, 0x42, 0xD9, 0x1E, 0x54, 0x23, 0x8A, 0xC2, 0xA0, 0xBF, 0x81, 0x37, 0x47, 0x6F, 0xB7, 0xF6, + 0x07, 0xF2, 0xD2, 0x15, 0xB6, 0x6D, 0x23, 0xA3, 0xE2, 0x9E, 0xE6, 0x0C, 0xB0, 0xCE, 0xCA, 0x1A, 0xB3, 0xA2, 0x02, 0xBC, + 0xA3, 0x63, 0xBD, 0x5A, 0x1E, 0xBD, 0xA3, 0x36, 0x73, 0x13, 0xDF, 0xF9, 0xDD, 0x4E, 0x8B, 0x91, 0xCA, 0x49, 0xA4, 0x00, + 0xF8, 0xFC, 0x8C, 0x46, 0xE9, 0x0F, 0x7E, 0x68, 0x23, 0x86, 0xD1, 0x67, 0x77, 0x65, 0xE8, 0x9B, 0xCF, 0xB9, 0xC2, 0x4F, + 0xB9, 0x20, 0x81, 0xAF, 0xEA, 0x74, 0xDA, 0x09, 0xF8, 0x61, 0x50, 0x78, 0x63, 0xE4, 0x6C, 0x53, 0xF2, 0xFA, 0xED, 0x32, + 0xF2, 0xA0, 0xFF, 0x6D, 0xFA, 0x2B, 0x36, 0x13, 0x00, 0x46, 0xEB, 0xD5, 0x5B, 0x27, 0x2B, 0x51, 0x85, 0xD4, 0xF3, 0xE5, + 0x1A, 0x88, 0x5F, 0x99, 0xCC, 0xCC, 0x6D, 0x17, 0x28, 0x25, 0x7D, 0x2E, 0x16, 0x85, 0xA2, 0xAD, 0x1E, 0x92, 0x28, 0x8D, + 0xBB, 0x0A, 0xF4, 0xE0, 0x59, 0x28, 0x6A, 0x06, 0xF3, 0x04, 0x75, 0xF4, 0x3D, 0x64, 0xA1, 0xDE, 0x59, 0xB4, 0xDD, 0x5E, + 0x78, 0x29, 0xD7, 0x59, 0x08, 0xF5, 0x4F, 0xE5, 0x8E, 0x67, 0x17, 0x6A, 0xFB, 0x1A, 0xBF, 0xD2, 0xDE, 0x99, 0xF0, 0x4B, + 0xA7, 0x68, 0x27, 0x82, 0x9A, 0x7B, 0xE3, 0xC0, 0xC1, 0xE6, 0xB7, 0xDE, 0x30, 0xFA, 0x64, 0xCC, 0x7C, 0x3A, 0x66, 0x2E, + 0xED, 0x49, 0x56, 0x8E, 0x79, 0x77, 0x19, 0x49, 0xD7, 0x91, 0x8A, 0xE5, 0x51, 0x86, 0xDC, 0x3E, 0x7B, 0x94, 0x01, 0xEE, + 0x4A, 0x0D, 0xDA, 0x58, 0xEE, 0xCC, 0x4B, 0x4D, 0x03, 0x21, 0xFB, 0x69, 0x73, 0x3F, 0xEB, 0x96, 0x45, 0x55, 0xB1, 0x6F, + 0x2F, 0xE8, 0x4F, 0xBB, 0x43, 0x3E, 0xB5, 0x5B, 0x7A, 0xAC, 0xE4, 0x8F, 0xF8, 0x2B, 0xE3, 0x4D, 0x9E, 0xC0, 0xF9, 0xB1, + 0x19, 0xAF, 0x44, 0x54, 0x60, 0x3E, 0x5A, 0x1A, 0x66, 0xBA, 0xCE, 0xC0, 0x76, 0xA3, 0x96, 0x83, 0x04, 0x1E, 0x28, 0x56, + 0x92, 0x3F, 0x46, 0xB8, 0xC2, 0xFC, 0x94, 0xB0, 0xF8, 0x5E, 0x3F, 0x24, 0x53, 0xBF, 0xED, 0x47, 0x34, 0x3C, 0x99, 0x23, + 0xE1, 0xBC, 0x32, 0x21, 0x86, 0x44, 0x3F, 0x6E, 0x55, 0x1C, 0xB5, 0x31, 0x50, 0x9C, 0x03, 0x76, 0x2B, 0x9A, 0xA3, 0x7C, + 0xB3, 0xDA, 0x29, 0x28, 0xE2, 0x59, 0x68, 0xE0, 0x87, 0x9F, 0xAB, 0x9E, 0x03, 0x50, 0xAA, 0xE3, 0x56, 0xC0, 0x14, 0xD4, + 0xAA, 0x3A, 0xE1, 0x27, 0xB7, 0xB8, 0xE4, 0x0F, 0x65, 0x86, 0x27, 0xD3, 0xD2, 0x34, 0x1D, 0xC5, 0xB0, 0x5B, 0xBD, 0xD1, + 0x52, 0xB7, 0x37, 0xE3, 0xE1, 0xB6, 0x75, 0xFF, 0x7E, 0x7B, 0x73, 0x05, 0xCA, 0xBD, 0x9F, 0x92, 0x97, 0x9A, 0xA4, 0x8E, + 0x40, 0x4C, 0x87, 0x24, 0xC7, 0x68, 0xC6, 0x89, 0xA1, 0x03, 0x17, 0x7F, 0x7B, 0x23, 0x1E, 0x49, 0x89, 0xA7, 0x87, 0xCC, + 0x3A, 0xA3, 0xB1, 0x7E, 0x9D, 0x60, 0xD6, 0x95, 0x0A, 0xDF, 0x00, 0xB8, 0xCF, 0xA9, 0x57, 0x43, 0x8C, 0xDA, 0x06, 0xF7, + 0x0F, 0x0A, 0x4B, 0x6B, 0x51, 0xC2, 0xD7, 0x74, 0xF1, 0xF1, 0x97, 0xDE, 0x88, 0xDB, 0x6F, 0x87, 0x53, 0x16, 0x4F, 0x21, + 0x5F, 0x33, 0x46, 0xB2, 0xAD, 0x15, 0x0A, 0x39, 0x8F, 0xDF, 0x1E, 0xD0, 0xA7, 0xB1, 0xD7, 0xFD, 0x9B, 0xBD, 0x18, 0x6C, + 0x2A, 0x34, 0x69, 0x0A, 0x19, 0xD6, 0x2C, 0xC8, 0x2A, 0x5D, 0x9C, 0x9F, 0xD0, 0x59, 0x20, 0xFE, 0x8A, 0xDE, 0x4E, 0x0F, + 0xF7, 0xD0, 0x0E, 0x5A, 0xE5, 0x70, 0x62, 0x3E, 0x3E, 0xB3, 0x0D, 0x7D, 0x82, 0x0F, 0x46, 0x07, 0x5F, 0x81, 0x63, 0x3A, + 0x26, 0xB2, 0xF7, 0x27, 0x17, 0x32, 0xF3, 0x0A, 0x67, 0x1D, 0xCE, 0x1F, 0x57, 0xD2, 0x6A, 0x40, 0x59, 0x08, 0x60, 0x43, + 0x37, 0xBB, 0x2E, 0x90, 0x4C, 0xA0, 0xA6, 0x44, 0xAB, 0x4D, 0xE8, 0xCF, 0x2C, 0x9A, 0x88, 0x1F, 0x26, 0xE0, 0x26, 0x43, + 0x20, 0xCA, 0xC3, 0x11, 0xF4, 0x5E, 0x71, 0xEC, 0x78, 0x4B, 0x31, 0x61, 0xD4, 0xED, 0x76, 0x21, 0xD4, 0x6F, 0x24, 0xA3, + 0xA2, 0x96, 0x2F, 0x75, 0x7A, 0x98, 0x93, 0xF1, 0x12, 0x23, 0xB9, 0xCA, 0xC9, 0x6E, 0x55, 0xDF, 0xEA, 0xAE, 0x2E, 0x51, + 0x3E, 0x4E, 0xCC, 0x62, 0xFF, 0xB5, 0xC8, 0x9C, 0x56, 0x89, 0x50, 0x14, 0x34, 0x68, 0x79, 0x9A, 0x34, 0xBE, 0x96, 0x50, + 0xF6, 0x26, 0x40, 0x42, 0x1B, 0x6A, 0x5C, 0x51, 0xFB, 0xE8, 0x47, 0x6B, 0xC9, 0x22, 0xF7, 0x25, 0xF6, 0x5E, 0x8E, 0x10, + 0x85, 0x67, 0x61, 0x7C, 0x52, 0x72, 0x91, 0xBB, 0x0B, 0x1A, 0xC5, 0xA4, 0x1B, 0x7A, 0xD9, 0x01, 0xA5, 0x8B, 0x00, 0x50, + 0x76, 0x98, 0xA4, 0x6C, 0xF7, 0x93, 0x62, 0xDB, 0xC5, 0xEA, 0x2C, 0xBA, 0xB3, 0x8D, 0xD5, 0x54, 0x5A, 0x3B, 0x9F, 0x73, + 0x0B, 0x73, 0x12, 0xFE, 0x0D, 0xAF, 0x8A, 0x27, 0xCB, 0x5A, 0xC6, 0x4D, 0x4A, 0x6B, 0xE0, 0x6D, 0x67, 0x62, 0x2B, 0x65, + 0xAF, 0xEB, 0x34, 0x8C, 0x4A, 0xB9, 0xC0, 0x6F, 0xD8, 0xC6, 0x34, 0xF3, 0xDB, 0xC6, 0x08, 0x5B, 0x3C, 0x54, 0xFB, 0xE2, + 0x36, 0x89, 0xA5, 0x16, 0xFC, 0x7B, 0x9A, 0x42, 0xF7, 0xC3, 0x9A, 0x69, 0xE3, 0xA3, 0x0C, 0x6D, 0xBB, 0xC3, 0x62, 0x7D, + 0x78, 0xA8, 0x79, 0x64, 0x33, 0xCF, 0x68, 0x6C, 0x7F, 0x54, 0xA9, 0x94, 0x2C, 0x32, 0xA0, 0x56, 0x6B, 0x42, 0x59, 0xB8, + 0xD9, 0x7B, 0x73, 0x21, 0xF5, 0xA1, 0xC7, 0x14, 0x6D, 0x8C, 0xD5, 0xCE, 0x52, 0xAF, 0x24, 0xE4, 0x89, 0x0F, 0x95, 0x59, + 0x7E, 0x2C, 0x03, 0x3C, 0x32, 0x49, 0x5B, 0x0D, 0xBD, 0x63, 0x7C, 0x86, 0x90, 0xC9, 0x24, 0xE5, 0x38, 0x3D, 0x75, 0x64, + 0x24, 0xEB, 0x74, 0x1A, 0xEE, 0xF8, 0xD3, 0x6D, 0xC4, 0x12, 0x00, 0x05, 0x2E, 0xB9, 0x99, 0x24, 0x64, 0x3B, 0xA9, 0xD6, + 0x3F, 0x5C, 0x7C, 0x93, 0x01, 0x13, 0xDB, 0xAF, 0x5D, 0xA3, 0x10, 0xD4, 0x69, 0xC9, 0x35, 0xE4, 0x5F, 0x5F, 0xD2, 0x6D, + 0x5D, 0x5A, 0x2D, 0xF4, 0xB9, 0x38, 0x95, 0xAE, 0xD6, 0xE7, 0xAE, 0x86, 0x54, 0x0C, 0xAE, 0x51, 0x6D, 0x6B, 0x74, 0x57, + 0x06, 0x00, 0x76, 0x8F, 0x05, 0x54, 0xE1, 0x04, 0x52, 0x27, 0x6D, 0xA1, 0x34, 0x3C, 0xFD, 0x27, 0x94, 0xF5, 0x7A, 0x22, + 0x8E, 0x5F, 0x78, 0xF2, 0x7F, 0x9B, 0x89, 0x51, 0xE6, 0x9E, 0x45, 0xDD, 0x3A, 0x1B, 0x63, 0xCF, 0x0D, 0x87, 0x0E, 0x1F, + 0xF6, 0x4D, 0xA3, 0x33, 0xA3, 0xBB, 0x6D, 0xC7, 0x6E, 0xEA, 0xD1, 0x61, 0xBB, 0xDD, 0xDB, 0xCF, 0x73, 0x53, 0x7D, 0x8A, + 0x2A, 0xB8, 0xDD, 0xBF, 0x0C, 0x17, 0xEC, 0xAA, 0x24, 0x91, 0x88, 0x83, 0x52, 0x27, 0x15, 0x26, 0xDE, 0x34, 0xD0, 0x99, + 0x9C, 0xB2, 0x00, 0xDE, 0xB3, 0xD1, 0x19, 0x3A, 0x0B, 0xCF, 0x0B, 0xF4, 0x98, 0x25, 0x07, 0xFD, 0xDE, 0x6E, 0x6E, 0xBB, + 0x49, 0x25, 0xED, 0x73, 0xFA, 0x29, 0xB7, 0xAA, 0x0C, 0x3F, 0x2F, 0xDC, 0x42, 0x16, 0xB5, 0x4A, 0xC8, 0xDB, 0xB7, 0xBB, + 0x74, 0xD4, 0x1A, 0x8D, 0xC7, 0x86, 0xF0, 0xAC, 0x5E, 0x35, 0xB6, 0xFB, 0x56, 0x7C, 0x63, 0xE9, 0x5A, 0x58, 0xD1, 0xCA, + 0xFB, 0x92, 0xC4, 0x2D, 0xB3, 0xFC, 0xFE, 0xD9, 0xB7, 0x7D, 0x5A, 0xDA, 0xFD, 0xF5, 0x01, 0x1E, 0xEE, 0x41, 0x99, 0xC9, + 0x5F, 0x3D, 0x64, 0x98, 0x9E, 0xD7, 0x64, 0xE9, 0x36, 0x4F, 0x5D, 0x24, 0x9C, 0x9B, 0xD1, 0xF7, 0xD7, 0xB2, 0xEA, 0xD8, + 0x37, 0x7F, 0x43, 0x80, 0x5C, 0xBE, 0xC0, 0xCD, 0xF9, 0x06, 0xD9, 0x0E, 0xB5, 0xA1, 0x16, 0x29, 0xC0, 0x75, 0xDF, 0xA0, + 0x0E, 0x77, 0xAC, 0x10, 0x01, 0x01, 0xD1, 0x47, 0x17, 0xF2, 0x66, 0x39, 0x7E, 0xBE, 0xFB, 0x52, 0xEE, 0x62, 0x29, 0x00, + 0x86, 0x82, 0x7E, 0xFA, 0x82, 0x6F, 0x2F, 0xF0, 0xE1, 0x32, 0xA9, 0xC5, 0x92, 0x79, 0x09, 0x93, 0x00, 0xA3, 0xB4, 0x91, + 0xDE, 0xD5, 0x23, 0xCA, 0xBE, 0xBC, 0xDA, 0x2C, 0x53, 0xEF, 0xE4, 0x80, 0x16, 0x79, 0xA0, 0x46, 0xBC, 0x29, 0xFC, 0xE5, + 0xBD, 0xCF, 0x51, 0xCE, 0x53, 0xC4, 0xB3, 0x1B, 0x42, 0x25, 0x71, 0x56, 0x5B, 0x49, 0xF4, 0xF5, 0x3F, 0xBA, 0x20, 0x1B, + 0x72, 0xFC, 0xD6, 0xBE, 0x63, 0xD5, 0xD9, 0xC1, 0x94, 0x56, 0x1F, 0x4D, 0x71, 0x0B, 0x6A, 0x83, 0xC2, 0x9B, 0x64, 0x71, + 0xB9, 0x80, 0x1D, 0x0B, 0xBD, 0xFB, 0x99, 0xEC, 0x12, 0x9C, 0xFF, 0xA8, 0xA3, 0xC3, 0xC2, 0x18, 0x84, 0x08, 0xE2, 0xB3, + 0xE7, 0x25, 0xD2, 0x9D, 0xA0, 0xE5, 0xF6, 0x4E, 0xD5, 0xEE, 0x6A, 0xA7, 0xF6, 0x06, 0xA3, 0x74, 0xBA, 0x4C, 0xD0, 0x7F, + 0x97, 0x43, 0x81, 0x11, 0xE6, 0x2B, 0x03, 0x09, 0x88, 0x87, 0xA9, 0xE7, 0xDB, 0x25, 0xDA, 0xB9, 0x37, 0xE7, 0xCA, 0xED, + 0x98, 0xE1, 0xBF, 0xFB, 0x41, 0xE1, 0xB3, 0x4F, 0xDA, 0xDB, 0x18, 0x2A, 0x8E, 0x7B, 0x5C, 0xB3, 0x32, 0x0F, 0xE1, 0x64, + 0xD6, 0x7D, 0xAB, 0xA7, 0x21, 0x54, 0x52, 0x98, 0xEE, 0x1D, 0xCA, 0x55, 0xAA, 0x96, 0x59, 0x70, 0xC3, 0xBC, 0xAA, 0x5E, + 0xBD, 0x20, 0x5A, 0x0B, 0x10, 0x21, 0x97, 0x3C, 0x1F, 0xC6, 0x7E, 0xA9, 0xDE, 0xAA, 0x3F, 0x33, 0x80, 0x41, 0x2A, 0x0F, + 0x31, 0xD5, 0xE4, 0x0D, 0xDC, 0x1E, 0x5E, 0x4A, 0xFF, 0x5E, 0xD3, 0xD9, 0x9D, 0x5F, 0x9F, 0x96, 0xCD, 0xC5, 0xC8, 0x7D, + 0xB0, 0xDE, 0x12, 0x89, 0xDF, 0x8D, 0x3F, 0x06, 0xCE, 0xCF, 0xC7, 0x8E, 0x66, 0x30, 0x7C, 0x0D, 0xF0, 0x92, 0xF7, 0xB7, + 0x80, 0xEE, 0x8C, 0xF6, 0xF3, 0xEE, 0x36, 0x56, 0x94, 0xD2, 0x3F, 0x9C, 0xAD, 0x40, 0xD6, 0x05, 0xD6, 0xB6, 0xFD, 0xC2, + 0x32, 0x3E, 0x0F, 0xD3, 0x9C, 0x49, 0xA8, 0x94, 0x51, 0x4D, 0xCD, 0xD1, 0xA1, 0xBE, 0xED, 0x2A, 0x4E, 0x3E, 0x19, 0x39, + 0x46, 0x11, 0x5D, 0x28, 0xF4, 0x31, 0x1D, 0xE2, 0x87, 0x6B, 0x41, 0xC7, 0xB0, 0x30, 0x2A, 0x80, 0xE0, 0x50, 0xF2, 0xDD, + 0x27, 0x6F, 0xFB, 0xF9, 0xD7, 0x04, 0x0C, 0xD9, 0x86, 0x31, 0x5C, 0x03, 0x36, 0x53, 0x85, 0x63, 0x75, 0x05, 0x72, 0xF8, + 0x52, 0x87, 0xB3, 0xA7, 0x93, 0x74, 0x99, 0x83, 0x89, 0xEE, 0x37, 0x61, 0xEE, 0xE6, 0x8D, 0x01, 0x46, 0xC3, 0xCB, 0x92, + 0x9D, 0xEB, 0xFE, 0x4C, 0x42, 0x5E, 0x56, 0x1D, 0xE6, 0x35, 0x07, 0xF9, 0x3B, 0x13, 0xE4, 0x8C, 0x39, 0xB8, 0xC5, 0x9F, + 0x5B, 0x68, 0x51, 0xB1, 0x87, 0xDC, 0x8D, 0x6B, 0x39, 0xB4, 0xEE, 0xDE, 0x39, 0x34, 0x36, 0xA9, 0x6F, 0x8A, 0x3E, 0xFA, + 0x43, 0x04, 0x92, 0xFA, 0xE7, 0x13, 0xD9, 0x81, 0x47, 0x7B, 0xD7, 0xB9, 0xCA, 0x5C, 0x04, 0xAA, 0x30, 0x8B, 0xC6, 0x6B, + 0xE9, 0xE4, 0xF1, 0x91, 0xF1, 0x6B, 0xB1, 0x3D, 0x9F, 0xBE, 0x89, 0xBB, 0x02, 0xF6, 0x57, 0xD7, 0x12, 0x5E, 0x12, 0x92, + 0xA9, 0x03, 0x12, 0x6A, 0xE2, 0x5E, 0x53, 0xF4, 0x49, 0x04, 0x36, 0x5C, 0x75, 0xBE, 0x8B, 0x3B, 0xB9, 0x39, 0x46, 0x67, + 0x80, 0x54, 0x21, 0x00, 0x7B, 0x66, 0x80, 0x63, 0xC9, 0x3E, 0x9A, 0x4F, 0x15, 0xE3, 0x6F, 0x16, 0x67, 0xF3, 0x17, 0xE0, + 0xAF, 0x03, 0x8F, 0x44, 0x30, 0x5D, 0xBD, 0xBF, 0x9A, 0x7D, 0x61, 0x24, 0x29, 0x5F, 0xF8, 0x79, 0xE7, 0x7D, 0x21, 0x71, + 0x14, 0xEE, 0xA9, 0xE4, 0xFD, 0x58, 0xED, 0x23, 0xA5, 0x7F, 0x88, 0xD5, 0x24, 0x85, 0x2C, 0x29, 0xCD, 0x2B, 0x2A, 0x74, + 0xEA, 0xA7, 0x0E, 0x23, 0x55, 0xE1, 0x7F, 0x4B, 0xF4, 0x4E, 0x47, 0xCB, 0x85, 0xC2, 0xF9, 0x9A, 0x16, 0xEE, 0xEE, 0x22, + 0xC2, 0x21, 0x89, 0xD4, 0xAC, 0xA0, 0x2C, 0x60, 0x9D, 0xED, 0x5E, 0xE8, 0x34, 0x7C, 0x2D, 0xB1, 0x44, 0xE3, 0x2A, 0x10, + 0x74, 0x4C, 0x46, 0x7F, 0x3A, 0x80, 0x59, 0x44, 0x5E, 0xC8, 0xCA, 0xE6, 0x18, 0x58, 0x0F, 0x75, 0x26, 0x1E, 0xAC, 0xBA, + 0xA7, 0xC8, 0x81, 0xBD, 0x2C, 0x43, 0xC7, 0x94, 0xF2, 0xCC, 0xF7, 0x4E, 0x9F, 0x3D, 0x33, 0x28, 0xA6, 0x8B, 0x35, 0x19, + 0xB8, 0x7A, 0x2B, 0x45, 0xF2, 0xD9, 0xD7, 0x5E, 0xF7, 0x42, 0x94, 0x68, 0xFB, 0x12, 0x15, 0x29, 0x8D, 0xC8, 0xF9, 0x52, + 0xAC, 0x86, 0xEE, 0x18, 0x27, 0x5F, 0x44, 0xDE, 0x0F, 0x82, 0x16, 0x6C, 0x8D, 0x55, 0xF2, 0x96, 0xF8, 0xD3, 0x25, 0x5C, + 0xE7, 0xAA, 0x1D, 0xD6, 0x7E, 0x89, 0x01, 0x59, 0x13, 0x75, 0x5A, 0x78, 0x45, 0x8B, 0x3D, 0xC1, 0x95, 0x58, 0x94, 0x03, + 0xFB, 0x8A, 0x8A, 0x07, 0x1C, 0x0A, 0x36, 0xAF, 0x8C, 0xC9, 0x74, 0x9E, 0xDA, 0x18, 0xEB, 0x1A, 0x04, 0x76, 0x6F, 0xD5, + 0x26, 0xA4, 0xE8, 0x6C, 0x61, 0x89, 0x1B, 0x2C, 0xAD, 0x8F, 0xF1, 0x75, 0x32, 0x59, 0xBB, 0xD8, 0xBB, 0x53, 0xDF, 0x15, + 0xD3, 0xCA, 0xC5, 0x32, 0x58, 0x9C, 0xC9, 0x76, 0xD3, 0xFC, 0x45, 0xB8, 0x0F, 0x50, 0xBA, 0xF8, 0xCF, 0x47, 0xE9, 0x7E, + 0x34, 0x5C, 0xF2, 0xCF, 0xCD, 0x43, 0xE2, 0x29, 0xAD, 0x5A, 0x5F, 0x53, 0x6F, 0xC5, 0xBE, 0x2F, 0x9A, 0x45, 0x56, 0x7B, + 0x26, 0xED, 0x13, 0xB7, 0x47, 0xED, 0x43, 0x8A, 0x90, 0xCF, 0x04, 0x6C, 0xAF, 0x57, 0x1E, 0x6D, 0x5F, 0x6F, 0x34, 0xF5, + 0x3B, 0xB9, 0xF4, 0xA7, 0x05, 0x5D, 0xE2, 0xA1, 0x87, 0x9E, 0x61, 0x02, 0xDA, 0x3C, 0x94, 0xA6, 0x21, 0xBE, 0x87, 0x02, + 0x6D, 0xC3, 0xB4, 0xBA, 0xC8, 0x4E, 0xE5, 0x36, 0x4C, 0x3F, 0xA0, 0x05, 0x75, 0x94, 0xA2, 0x4B, 0x21, 0x9D, 0x0A, 0x3C, + 0x01, 0x64, 0x64, 0xD4, 0x7B, 0x99, 0x8D, 0x86, 0x54, 0xB5, 0xC5, 0x13, 0xFF, 0x63, 0x02, 0x2C, 0x0A, 0x2E, 0xA3, 0x86, + 0xCD, 0xF0, 0x24, 0xCB, 0x83, 0xB0, 0x0A, 0x3F, 0xE4, 0xD0, 0x4F, 0x19, 0x45, 0x20, 0x52, 0xFF, 0x84, 0xD7, 0x38, 0x88, + 0xA4, 0x8A, 0x1C, 0xB4, 0x23, 0xDA, 0x41, 0xA9, 0x00, 0xF5, 0x5B, 0xEF, 0x05, 0xF3, 0xE3, 0x80, 0x98, 0x6A, 0x45, 0x81, + 0xA5, 0x26, 0x35, 0xEA, 0xF5, 0x0A, 0xAA, 0x5D, 0xA1, 0x65, 0xB0, 0xC9, 0x18, 0x6A, 0x45, 0x34, 0x25, 0x17, 0xA4, 0xE8, + 0xF1, 0x87, 0x25, 0x99, 0x3F, 0x88, 0x8C, 0x0D, 0x9F, 0xE3, 0x6F, 0xBC, 0xC9, 0x59, 0xD4, 0xAE, 0xFC, 0x7A, 0x99, 0x56, + 0x2B, 0x7A, 0x3F, 0x74, 0x98, 0xB2, 0x67, 0xFD, 0x6B, 0x0A, 0x6D, 0x44, 0xF0, 0x44, 0x1D, 0x64, 0xD7, 0xBA, 0x20, 0x03, + 0xDF, 0x10, 0xC8, 0x54, 0xFE, 0x97, 0x0A, 0x92, 0x07, 0x77, 0x19, 0x88, 0xBE, 0x8B, 0x2F, 0xDE, 0x09, 0xCE, 0x02, 0x1B, + 0xAB, 0x6B, 0xD9, 0xB9, 0x0C, 0x5D, 0x0B, 0x4E, 0x70, 0x65, 0xA3, 0x29, 0x0D, 0xE4, 0x7E, 0xEF, 0x0D, 0x1C, 0xB6, 0x90, + 0x81, 0xE7, 0x50, 0xF7, 0x8C, 0x16, 0x11, 0x19, 0x0C, 0xBB, 0xBE, 0xE2, 0xA9, 0xDB, 0xA7, 0x12, 0x79, 0x8D, 0x59, 0xE7, + 0x0D, 0xFB, 0x5F, 0x31, 0xAE, 0xF3, 0x0F, 0x6F, 0xF2, 0x25, 0x97, 0x6B, 0xE2, 0xF4, 0xDF, 0xF7, 0x1C, 0xD2, 0x57, 0x40, + 0x4A, 0xFD, 0xD7, 0xEF, 0x4E, 0x60, 0xDB, 0xDB, 0xDF, 0x3C, 0x80, 0x23, 0x4E, 0x1B, 0xA8, 0x81, 0xB1, 0x29, 0x9D, 0x49, + 0xB7, 0x25, 0xC8, 0x28, 0x56, 0xB3, 0x3C, 0x85, 0xE8, 0x6B, 0x7A, 0x72, 0xD0, 0xAB, 0xB4, 0xB5, 0x94, 0x23, 0x1C, 0x14, + 0x31, 0x81, 0xA1, 0x77, 0xA1, 0x42, 0x41, 0x77, 0x33, 0x39, 0x29, 0xC9, 0x8C, 0x9E, 0x03, 0x47, 0xF2, 0x0F, 0x51, 0x1C, + 0xB2, 0x69, 0x0E, 0xFD, 0x2B, 0x6C, 0x70, 0xDA, 0x3E, 0xC8, 0x26, 0x87, 0xD9, 0x53, 0x7B, 0x71, 0x32, 0xAB, 0x00, 0x6C, + 0x85, 0x2C, 0x41, 0xE4, 0x72, 0x28, 0xF6, 0x4D, 0x2A, 0xC9, 0x36, 0x57, 0xE2, 0x0A, 0xF0, 0x04, 0x17, 0x2A, 0x20, 0x03, + 0x7B, 0xFA, 0xE2, 0x87, 0x63, 0xCA, 0xE1, 0x33, 0xE0, 0xD2, 0x47, 0xC1, 0xA2, 0xD0, 0xEA, 0x83, 0x6E, 0xBB, 0xC0, 0xC5, + 0x3F, 0xC6, 0x4F, 0x79, 0x6A, 0x16, 0xCF, 0x7D, 0x1A, 0x2E, 0x02, 0x71, 0xFC, 0xD6, 0xCC, 0xB2, 0x3A, 0x56, 0xBA, 0xE8, + 0x4C, 0x0E, 0x42, 0x41, 0x8C, 0x2E, 0x2B, 0x19, 0x78, 0xE7, 0xC2, 0x1C, 0x1C, 0x6E, 0x08, 0x6A, 0x3A, 0x3E, 0x26, 0x6F, + 0x5A, 0x8F, 0x64, 0x3F, 0xE8, 0xF6, 0xE2, 0x1C, 0x3D, 0x39, 0x2B, 0x8C, 0x29, 0x03, 0xAB, 0x9D, 0x3B, 0x6B, 0xB3, 0x5B, + 0xAA, 0x66, 0x30, 0x63, 0xBB, 0x4A, 0xF3, 0xF1, 0x6F, 0x46, 0xC3, 0x9F, 0x4D, 0x56, 0xDB, 0xE4, 0x8D, 0xE6, 0x5B, 0x81, + 0xBD, 0x66, 0x30, 0x55, 0xDD, 0x4E, 0x19, 0x53, 0x65, 0xBE, 0x0C, 0x28, 0x6C, 0xB7, 0xB0, 0x93, 0xB3, 0x7D, 0xCB, 0xDC, + 0x2D, 0x32, 0x0A, 0x8D, 0x1C, 0xD9, 0x16, 0xD7, 0xC6, 0x56, 0xD2, 0x68, 0x30, 0x7C, 0x5B, 0x49, 0x8C, 0xD7, 0xF4, 0x84, + 0xE9, 0x2E, 0x63, 0x95, 0x7E, 0x0C, 0xC9, 0x6F, 0x18, 0x9A, 0x8B, 0x94, 0xB3, 0x4D, 0x9F, 0x43, 0xB9, 0x9B, 0xE3, 0x1F, + 0x01, 0xFE, 0x5C, 0x8C, 0xE3, 0x90, 0xBC, 0x7F, 0xC9, 0x01, 0x7E, 0x06, 0xE4, 0x6C, 0x96, 0xDF, 0xED, 0xD6, 0x86, 0xD6, + 0xF2, 0xA4, 0x28, 0x56, 0x42, 0xBB, 0xB4, 0xF4, 0x75, 0x5D, 0x7C, 0xF2, 0x23, 0x5E, 0x9A, 0x9C, 0x98, 0x60, 0xA9, 0x1E, + 0xA1, 0x52, 0xFD, 0x07, 0x64, 0xE3, 0x95, 0xE1, 0xAC, 0xDF, 0x62, 0x47, 0x70, 0x62, 0x1B, 0xB9, 0x12, 0x5E, 0xEB, 0xF4, + 0x12, 0x37, 0x3D, 0xA1, 0xA9, 0x42, 0x87, 0xA8, 0xD2, 0x06, 0xE3, 0x39, 0x71, 0x0F, 0x51, 0x37, 0x42, 0x9B, 0x45, 0x2E, + 0x61, 0x47, 0x9E, 0xF9, 0x63, 0xDB, 0x4D, 0xB6, 0xC8, 0x5D, 0x74, 0x2B, 0x8E, 0x59, 0x58, 0x12, 0x8A, 0x44, 0xE2, 0xD8, + 0x12, 0x71, 0x7B, 0xA7, 0x49, 0x3E, 0xD2, 0x2A, 0x81, 0x11, 0x95, 0xC9, 0x3C, 0xDD, 0xC0, 0x22, 0x38, 0x07, 0x90, 0xB1, + 0x94, 0xF2, 0x2A, 0x95, 0xB7, 0x1A, 0x7B, 0x3D, 0x40, 0xD2, 0xA4, 0x86, 0xC3, 0xFE, 0x1E, 0x70, 0xC1, 0x09, 0x06, 0xCA, + 0x5C, 0xB5, 0x32, 0x14, 0x81, 0x32, 0xCF, 0x8F, 0xDD, 0xFF, 0x70, 0x9E, 0xC8, 0x9A, 0xF1, 0x61, 0x4E, 0xE2, 0xBF, 0x47, + 0xEB, 0x55, 0x19, 0x54, 0xFD, 0x3B, 0x11, 0xEB, 0xC8, 0xE2, 0xF9, 0x48, 0x87, 0xCA, 0x4F, 0x99, 0xEE, 0x22, 0x93, 0x29, + 0xDA, 0xBB, 0x23, 0x6A, 0x25, 0x16, 0x39, 0x19, 0xE6, 0xB9, 0x5D, 0xDB, 0x64, 0xAD, 0x4C, 0xF9, 0xCA, 0x31, 0x99, 0xA8, + 0x5D, 0xF9, 0x78, 0x93, 0x87, 0xC0, 0x70, 0x0A, 0x4C, 0xF3, 0xF6, 0x66, 0x7B, 0xBC, 0x87, 0xE8, 0xDC, 0xB2, 0x22, 0x4E, + 0x37, 0x35, 0x60, 0x5C, 0x45, 0xC2, 0xCB, 0xD1, 0x7D, 0x05, 0x87, 0x90, 0x63, 0xB3, 0x07, 0x18, 0x91, 0xC3, 0x83, 0xD8, + 0x4B, 0xE1, 0xF1, 0xC5, 0xCE, 0xDA, 0x5A, 0xAB, 0x40, 0x0E, 0x49, 0xAF, 0x50, 0x2E, 0x05, 0x03, 0x93, 0xF0, 0x94, 0x8E, + 0xCB, 0x70, 0x0A, 0xD2, 0x58, 0x7F, 0xD8, 0x15, 0x57, 0xAA, 0xFC, 0x42, 0x78, 0x82, 0xE0, 0x41, 0x58, 0xE1, 0xCF, 0xD2, + 0x15, 0xCC, 0x75, 0x0B, 0xF4, 0x1E, 0x00, 0x02, 0x45, 0x7E, 0x7F, 0xB2, 0x23, 0x20, 0x78, 0xA8, 0x21, 0xEE, 0x7A, 0x59, + 0xEB, 0x08, 0xBC, 0x4A, 0x37, 0xA7, 0xA3, 0xA6, 0xF6, 0x23, 0x3F, 0x72, 0x22, 0x0E, 0x69, 0xCA, 0xD7, 0x0E, 0x02, 0x83, + 0xC9, 0x5C, 0x81, 0x97, 0x78, 0xF1, 0xE9, 0xDD, 0x84, 0x50, 0x77, 0x5C, 0x62, 0x71, 0x4E, 0x5A, 0x40, 0xD5, 0xAA, 0x6B, + 0x2A, 0x4B, 0x90, 0x76, 0xE6, 0x2A, 0xF9, 0xA0, 0xF6, 0x9A, 0x6B, 0x94, 0x57, 0x68, 0x86, 0x71, 0xF6, 0x5A, 0xDC, 0x21, + 0xB5, 0xA3, 0x2C, 0x78, 0xC5, 0xE4, 0xF6, 0xA3, 0x8A, 0x6B, 0x51, 0x15, 0xB4, 0xEA, 0xF8, 0xA0, 0xBB, 0x9C, 0x90, 0x68, + 0xBD, 0x72, 0x6E, 0x95, 0x2E, 0xF6, 0x4A, 0x5F, 0x2B, 0xD6, 0x7B, 0xB0, 0xAB, 0x25, 0xEA, 0xEE, 0x1A, 0x05, 0xDE, 0xC2, + 0xDC, 0x85, 0xD2, 0x30, 0xA2, 0xE5, 0xAA, 0x19, 0x8A, 0x04, 0x9E, 0x78, 0x3E, 0x99, 0x72, 0xAA, 0xA4, 0xF8, 0x28, 0xBC, + 0x89, 0x38, 0xAC, 0x7B, 0x84, 0x81, 0x6F, 0xEF, 0xC8, 0xB1, 0x54, 0xA3, 0x69, 0x5C, 0xC1, 0x2E, 0xD6, 0xA4, 0x55, 0x33, + 0xBE, 0x9D, 0xF2, 0x1D, 0x7A, 0xBB, 0x97, 0xA9, 0xC9, 0xC1, 0xE1, 0x22, 0x7E, 0xA7, 0x5E, 0xAC, 0x1E, 0xC3, 0xB2, 0xCA, + 0x12, 0x25, 0x64, 0x47, 0xA5, 0xBD, 0xA9, 0x6E, 0x58, 0xCC, 0xB7, 0x1A, 0xB8, 0x32, 0xEB, 0x21, 0xB8, 0xEC, 0xEB, 0x92, + 0x93, 0x00, 0xB0, 0x9C, 0xCE, 0xF4, 0xB8, 0x54, 0xF1, 0x1C, 0xBA, 0x80, 0x6B, 0xE1, 0x49, 0xDA, 0xFA, 0x61, 0xDF, 0x11, + 0x1F, 0xF1, 0xAB, 0x8F, 0xCC, 0x14, 0xD1, 0xAC, 0xAB, 0x00, 0xD7, 0xFE, 0x42, 0x8D, 0x85, 0x57, 0x22, 0x63, 0xDF, 0xA5, + 0x85, 0x8B, 0x9A, 0x46, 0x17, 0xF0, 0x7C, 0x2A, 0xC5, 0x71, 0x74, 0x1A, 0x71, 0xEB, 0x87, 0x17, 0xB6, 0xAE, 0x20, 0x12, + 0x1C, 0x8F, 0x4F, 0x54, 0x75, 0x9C, 0x7C, 0xCB, 0x0C, 0xB3, 0xA3, 0xDD, 0x29, 0xF0, 0x91, 0xF9, 0xB2, 0x38, 0x29, 0x41, + 0x05, 0xC9, 0xBA, 0x23, 0x82, 0xBA, 0xD2, 0x63, 0x30, 0x32, 0x6D, 0xFA, 0x79, 0xF1, 0x25, 0xAB, 0x0C, 0x2B, 0x31, 0x44, + 0x14, 0x5C, 0x5A, 0xEA, 0xAB, 0x32, 0x9A, 0xEF, 0x9F, 0xEA, 0xD4, 0x12, 0xDC, 0x47, 0x40, 0x95, 0x4E, 0xFB, 0x2C, 0xA1, + 0x1B, 0x34, 0x92, 0xFE, 0x9B, 0xB8, 0x64, 0xCB, 0x8C, 0x91, 0x59, 0x85, 0x43, 0xBA, 0x28, 0x83, 0xA2, 0xBB, 0x25, 0x8A, + 0xE5, 0xBB, 0xC2, 0xE5, 0x11, 0x5D, 0x70, 0x84, 0xB3, 0xED, 0x55, 0x2C, 0x4E, 0xC6, 0x93, 0xFE, 0x3A, 0x11, 0x27, 0x60, + 0x95, 0x62, 0xFC, 0x84, 0xCB, 0xB8, 0x37, 0x79, 0xA8, 0x15, 0x3F, 0xF3, 0x3A, 0xA2, 0x2C, 0xAB, 0x4D, 0x18, 0xA7, 0x5E, + 0x67, 0x59, 0x16, 0x61, 0x2B, 0x63, 0x94, 0x6D, 0x0D, 0xBF, 0x3A, 0x58, 0x5E, 0x6E, 0xEC, 0xF9, 0x96, 0x9D, 0x75, 0xC8, + 0x47, 0xFE, 0xD3, 0x0B, 0xD5, 0x28, 0x57, 0xE9, 0xE2, 0x51, 0xA6, 0x5C, 0x78, 0x77, 0xAD, 0x84, 0x95, 0xD9, 0x0C, 0xD1, + 0x1C, 0x44, 0x87, 0x5B, 0xFF, 0xDD, 0x87, 0x5F, 0xA5, 0x70, 0xA6, 0xE2, 0xF3, 0x31, 0xF1, 0xBD, 0x4E, 0x35, 0xD6, 0x10, + 0x87, 0x86, 0xAF, 0xE5, 0x97, 0x6D, 0x31, 0xF8, 0x5C, 0xC8, 0xF4, 0xDC, 0xAD, 0xB7, 0x33, 0x04, 0xEF, 0xDF, 0x06, 0xDA, + 0x82, 0x7C, 0x72, 0x24, 0x99, 0x9E, 0xC7, 0x25, 0x57, 0xAF, 0x61, 0x27, 0x51, 0x9C, 0x0F, 0xE7, 0x17, 0x4F, 0xAF, 0xE7, + 0xCF, 0x32, 0x6D, 0xCC, 0x8F, 0x2E, 0x26, 0xE4, 0x0A, 0xB1, 0x79, 0x0C, 0x82, 0xBE, 0xAC, 0x72, 0xCA, 0x09, 0xA0, 0xEE, + 0xA5, 0xA9, 0x28, 0xDB, 0xEC, 0x4D, 0x82, 0x54, 0xBB, 0x24, 0xF3, 0xF8, 0x66, 0x6D, 0xD1, 0xDF, 0xB4, 0xA7, 0x63, 0x77, + 0xBC, 0xF7, 0xE6, 0x33, 0xF0, 0x3E, 0xFE, 0x73, 0x4A, 0xF8, 0xA1, 0x8F, 0xB4, 0x4E, 0xEA, 0x06, 0x61, 0x03, 0xAF, 0xC7, + 0xB2, 0x87, 0xB1, 0x8E, 0x74, 0x8A, 0x8D, 0x31, 0x14, 0x10, 0x22, 0x41, 0x41, 0x5C, 0x2D, 0x57, 0x5C, 0xD5, 0x15, 0xE0, + 0x38, 0xA6, 0x99, 0x5A, 0x75, 0x04, 0x41, 0x9B, 0x43, 0x04, 0xC3, 0xF5, 0x70, 0x69, 0x65, 0xD4, 0x33, 0xF7, 0xCE, 0xBC, + 0xC7, 0xE8, 0xF4, 0x98, 0xD4, 0x08, 0xF2, 0xF1, 0x10, 0x85, 0x51, 0xE1, 0x80, 0x1D, 0x01, 0x6C, 0xDE, 0x2E, 0xB9, 0xC5, + 0x45, 0x17, 0x51, 0x74, 0xAA, 0x9B, 0x48, 0xD5, 0xB3, 0xC4, 0xD1, 0x51, 0x14, 0xB6, 0x3B, 0x60, 0xD1, 0x0A, 0x89, 0x17, + 0xD7, 0xC7, 0x22, 0xFB, 0xAB, 0x1A, 0xDB, 0x9F, 0xBD, 0x87, 0xA9, 0x58, 0xC8, 0x5E, 0xED, 0x42, 0x8A, 0xD4, 0x72, 0x3C, + 0x0F, 0x89, 0xB4, 0x30, 0x94, 0x8F, 0x56, 0xDE, 0x59, 0xE4, 0xA5, 0xA2, 0xB2, 0xD8, 0xBB, 0x79, 0x08, 0xAC, 0x12, 0xFD, + 0x67, 0x65, 0x83, 0xC1, 0x0B, 0xE7, 0x3F, 0xB2, 0x33, 0xBB, 0xD5, 0xF1, 0x50, 0x46, 0xC6, 0x5D, 0x91, 0x6A, 0xD3, 0xDF, + 0xED, 0xC0, 0xCB, 0x4A, 0xC5, 0x07, 0xAE, 0xCC, 0x4A, 0x9C, 0x19, 0x6F, 0x65, 0x25, 0x30, 0x68, 0x4B, 0xD5, 0x41, 0xBF, + 0x6A, 0x11, 0xDA, 0x1F, 0x2F, 0x41, 0x37, 0x2F, 0x04, 0x4E, 0xCD, 0x50, 0x78, 0x8B, 0x90, 0x82, 0xF8, 0x6B, 0x4B, 0x48, + 0xAE, 0x60, 0xFD, 0x95, 0xF2, 0x23, 0x43, 0xC9, 0xB3, 0x4D, 0xB3, 0x2C, 0x61, 0x63, 0xDA, 0x1F, 0xF3, 0x43, 0x32, 0x2F, + 0x60, 0x6F, 0xE3, 0x87, 0xDB, 0x02, 0xD7, 0x86, 0x7A, 0xE5, 0xA9, 0x6A, 0x04, 0x0B, 0x5F, 0xB3, 0x4F, 0x39, 0x2C, 0x4F, + 0x44, 0xF1, 0x20, 0xC6, 0x8B, 0xED, 0xB4, 0x6F, 0xAC, 0xBC, 0xCF, 0xE6, 0x8A, 0x9C, 0xBC, 0xC2, 0x03, 0xA5, 0x58, 0x4B, + 0xFC, 0xDC, 0x5B, 0xE7, 0x57, 0x02, 0xB2, 0xA9, 0xB6, 0x98, 0x2D, 0x91, 0xB2, 0xFD, 0x39, 0x20, 0x07, 0xCF, 0xC5, 0x0E, + 0x5E, 0xBE, 0x44, 0xA5, 0x46, 0xCC, 0x63, 0xB6, 0xC5, 0x30, 0x8E, 0x2A, 0x18, 0x02, 0xE6, 0x44, 0x0D, 0x95, 0xA4, 0x85, + 0xC5, 0x39, 0x74, 0xA4, 0x51, 0x92, 0xEA, 0xDD, 0xFF, 0xF2, 0xEE, 0x17, 0x10, 0x4B, 0xC0, 0x2F, 0x92, 0xBD, 0xA1, 0x08, + 0x63, 0xEE, 0xC9, 0xF5, 0xF3, 0x15, 0x9A, 0xC5, 0xA4, 0x65, 0x8F, 0x3E, 0x11, 0x30, 0xED, 0x0F, 0xF2, 0x1B, 0xD4, 0xA5, + 0xBA, 0xDD, 0xF5, 0x43, 0xAB, 0x05, 0x4D, 0x37, 0xD8, 0x26, 0xDD, 0x0E, 0x36, 0x0A, 0x83, 0xDC, 0x0C, 0xDA, 0x4A, 0x16, + 0xDF, 0x59, 0xBB, 0xCB, 0xE6, 0x32, 0xED, 0xD7, 0x08, 0x51, 0x75, 0x6C, 0x7C, 0x36, 0x85, 0xEB, 0x70, 0x90, 0xA8, 0xA1, + 0xB5, 0x92, 0xE5, 0x9C, 0x96, 0xF4, 0x0F, 0x38, 0x49, 0x1C, 0xAB, 0xFA, 0xAF, 0xBC, 0x9D, 0x9E, 0x9A, 0x7E, 0xE8, 0xD7, + 0x8A, 0xBF, 0xC2, 0x5D, 0xDA, 0xDB, 0x2F, 0x73, 0x40, 0x31, 0xF7, 0x99, 0x00, 0x79, 0x08, 0x26, 0x8A, 0x5F, 0xA7, 0x0F, + 0xF5, 0x1B, 0xFE, 0x5A, 0x2A, 0x16, 0x47, 0x48, 0x4A, 0x9E, 0xFD, 0x6C, 0x6E, 0x4D, 0xC5, 0xAB, 0xB8, 0x6C, 0xAC, 0xBE, + 0xDC, 0x0D, 0x5B, 0xA3, 0xFA, 0x5F, 0x4F, 0xE0, 0x68, 0x4C, 0x4F, 0x8F, 0x0F, 0xFB, 0xC7, 0xA8, 0xEA, 0x05, 0xD7, 0xAF, + 0xBE, 0x9E, 0xFB, 0x01, 0x4F, 0x1C, 0xDF, 0xF1, 0x1B, 0xD1, 0xF7, 0x26, 0x98, 0x32, 0x85, 0xC8, 0x9B, 0x32, 0x04, 0xF9, + 0x90, 0xDF, 0xDE, 0xBD, 0xE7, 0xD4, 0x5B, 0x0A, 0xA1, 0x3F, 0x9A, 0xF5, 0x28, 0x0F, 0x60, 0x13, 0x74, 0x6F, 0x8A, 0xB5, + 0x20, 0x4F, 0x90, 0xED, 0x21, 0x8C, 0x53, 0xFD, 0xDD, 0xF0, 0x46, 0x35, 0x61, 0x6C, 0xC6, 0x0F, 0xBC, 0x30, 0x20, 0x65, + 0x73, 0x92, 0xB2, 0x74, 0x83, 0x23, 0x91, 0x51, 0xA6, 0xEE, 0x22, 0x55, 0x1E, 0x53, 0x52, 0x34, 0x24, 0x3C, 0xD1, 0x25, + 0xFE, 0xAC, 0xF0, 0xC2, 0x66, 0x83, 0xAF, 0x0F, 0x3E, 0x72, 0x73, 0x04, 0x20, 0xC6, 0x2A, 0x96, 0xF7, 0x0B, 0x8F, 0x9A, + 0x46, 0x7F, 0x0B, 0x84, 0xBF, 0x95, 0x16, 0xD6, 0x63, 0xD4, 0xFF, 0xA5, 0x63, 0xA3, 0x3F, 0xF6, 0x43, 0xD4, 0x7D, 0x05, + 0x2F, 0x63, 0xEF, 0x86, 0x80, 0xDE, 0x74, 0xB4, 0xE6, 0x09, 0xF5, 0xE7, 0xCE, 0xEA, 0x5D, 0xF5, 0xC6, 0xEE, 0x57, 0x2E, + 0x0A, 0x01, 0x61, 0x12, 0x36, 0x2D, 0x95, 0x9B, 0x62, 0x85, 0xF8, 0x37, 0x9F, 0x4C, 0x96, 0x68, 0xFB, 0xED, 0x22, 0x3C, + 0x7C, 0x32, 0x00, 0x14, 0xEF, 0x89, 0x8C, 0x17, 0x36, 0x99, 0x2B, 0x7C, 0xB6, 0x99, 0xF8, 0x01, 0xE1, 0xED, 0x43, 0x1D, + 0xEC, 0xF6, 0x5A, 0x4D, 0x69, 0xAB, 0x1B, 0xF4, 0x29, 0xF5, 0xDD, 0x09, 0x75, 0xA5, 0x53, 0x69, 0x86, 0xC7, 0xCD, 0x02, + 0xC4, 0xEE, 0x93, 0xF5, 0x9D, 0xC6, 0xD5, 0x22, 0x41, 0xA8, 0x8F, 0x59, 0x7A, 0xAE, 0xAA, 0x78, 0x7C, 0x74, 0xE6, 0x8A, + 0x48, 0x8F, 0x19, 0xAC, 0x9C, 0x84, 0x63, 0x72, 0x4F, 0x8C, 0xE7, 0x6A, 0xDE, 0x9E, 0x2A, 0x7A, 0x1F, 0x3D, 0x92, 0xDC, + 0x16, 0x92, 0xC0, 0x3D, 0x8D, 0x8D, 0xFB, 0x3E, 0x17, 0x60, 0xF0, 0xCE, 0xAE, 0x8D, 0x1A, 0x2D, 0xDD, 0x11, 0x53, 0x27, + 0xFD, 0x1A, 0xCD, 0x42, 0x53, 0x68, 0xB4, 0x5E, 0x89, 0xFC, 0xD3, 0x0F, 0x9B, 0xA0, 0x33, 0x2F, 0xA8, 0x8F, 0x85, 0x56, + 0x5F, 0x1F, 0x3E, 0x80, 0xB6, 0xD1, 0xA6, 0xDD, 0x95, 0x6F, 0x4D, 0xD3, 0x14, 0xC6, 0x04, 0x0F, 0x50, 0x9C, 0xD7, 0xE9, + 0xBF, 0x2E, 0xD4, 0x92, 0x8C, 0x34, 0xC4, 0xBA, 0xC2, 0x90, 0x2F, 0xCC, 0xBF, 0x80, 0xC0, 0x7C, 0x51, 0xC4, 0x11, 0xE5, + 0x4B, 0x19, 0xA5, 0xD1, 0xD7, 0x3C, 0x8A, 0x34, 0x84, 0x5D, 0x16, 0x19, 0x56, 0x1E, 0xBF, 0xF7, 0x5E, 0xF7, 0x5D, 0xF1, + 0xAF, 0x91, 0xC3, 0x8E, 0x7A, 0x5E, 0xDC, 0x2C, 0x36, 0xD9, 0x64, 0xD7, 0x46, 0x1A, 0xDB, 0x8D, 0xBB, 0x08, 0x65, 0xE3, + 0xF6, 0x34, 0x13, 0x92, 0x6B, 0x96, 0x91, 0xB4, 0x74, 0x0A, 0x6D, 0xB5, 0x54, 0x4B, 0x6D, 0x09, 0x9E, 0xC4, 0x98, 0x04, + 0xA0, 0x87, 0xF4, 0xA8, 0x34, 0x9E, 0xCC, 0xBD, 0xE0, 0x96, 0xAB, 0xCE, 0x09, 0x5D, 0xFC, 0x5F, 0x20, 0x26, 0x95, 0xB5, + 0xF6, 0x97, 0xBD, 0xDB, 0xB7, 0xDD, 0xE7, 0xF3, 0xD6, 0x77, 0xFB, 0xB2, 0x1B, 0xB8, 0x98, 0x6C, 0x5E, 0x5D, 0x34, 0xC7, + 0xEE, 0xD4, 0x25, 0x3D, 0x5D, 0x55, 0x2C, 0x82, 0xAF, 0x95, 0x1A, 0xFC, 0xC6, 0x12, 0x93, 0xF4, 0x98, 0x85, 0x80, 0x87, + 0x1C, 0xFD, 0x5A, 0x61, 0x23, 0xDA, 0xD9, 0x88, 0x1D, 0x25, 0x72, 0x8F, 0x71, 0x27, 0x78, 0xDF, 0x7C, 0xE5, 0x69, 0xF9, + 0x5E, 0xFE, 0xD7, 0x9B, 0x04, 0x3E, 0xAF, 0x24, 0x18, 0x52, 0xDE, 0xFF, 0xF9, 0xB5, 0x46, 0x5E, 0xDA, 0x66, 0x9E, 0x4C, + 0x37, 0x03, 0xB2, 0x6E, 0x56, 0x3C, 0xC8, 0xC7, 0x5D, 0x1C, 0x31, 0xDE, 0x29, 0xDD, 0xD6, 0x8E, 0x37, 0xB2, 0x96, 0x5A, + 0x8E, 0xC6, 0xF4, 0xFA, 0xDC, 0x50, 0xD0, 0xAB, 0xDD, 0x9E, 0xDF, 0x1F, 0x45, 0xB1, 0x7F, 0xF7, 0x69, 0x8F, 0x97, 0xAE, + 0x45, 0xF3, 0x7E, 0x1C, 0x12, 0xDD, 0xB1, 0xF7, 0xAB, 0xFD, 0xDC, 0x0D, 0x6F, 0x5F, 0x6E, 0x0D, 0xDE, 0x1F, 0x60, 0x41, + 0xFB, 0x0D, 0x05, 0x0F, 0xDA, 0x2F, 0xD0, 0xA4, 0x10, 0xDC, 0x91, 0x42, 0xBB, 0xA3, 0x1D, 0xA2, 0xFE, 0x61, 0x09, 0x32, + 0x17, 0x51, 0x99, 0x16, 0x47, 0x31, 0x48, 0xC7, 0x37, 0xCC, 0x0B, 0x05, 0x23, 0xAF, 0x41, 0x1D, 0xA6, 0x60, 0xD1, 0x39, + 0xF6, 0x00, 0x3D, 0x56, 0xB6, 0xC4, 0xD6, 0xEE, 0xA5, 0xAE, 0xC8, 0x55, 0xD1, 0xBF, 0x58, 0x71, 0x81, 0xDF, 0xCF, 0xA6, + 0xFB, 0xCC, 0x12, 0xC4, 0x52, 0x51, 0xFE, 0xED, 0x7A, 0xD3, 0x0E, 0x53, 0x46, 0xEF, 0xD6, 0xD4, 0x54, 0x1E, 0x33, 0xAB, + 0x05, 0x45, 0x9E, 0xEA, 0xF8, 0x36, 0xF9, 0x6A, 0xDF, 0xF1, 0xA5, 0x9E, 0xA0, 0xDA, 0xF2, 0xF4, 0x7E, 0x15, 0xBF, 0xEC, + 0x7B, 0x35, 0x63, 0x65, 0x47, 0x50, 0xD7, 0x7A, 0xFC, 0xEB, 0x24, 0x2F, 0x02, 0x0A, 0xF7, 0xE0, 0xF9, 0x90, 0x07, 0x7E, + 0x8D, 0x09, 0x22, 0xF1, 0xD7, 0x59, 0x93, 0x39, 0x30, 0xF7, 0x88, 0x04, 0xC9, 0xBF, 0x18, 0x29, 0x99, 0xE5, 0xC4, 0x5F, + 0x3A, 0xE9, 0x45, 0x71, 0x8B, 0x41, 0x1A, 0x05, 0xE0, 0xA0, 0x9D, 0x43, 0xB6, 0x0B, 0x4E, 0xC2, 0xD4, 0x94, 0x93, 0xF4, + 0xE9, 0x48, 0x04, 0x08, 0xE7, 0x0A, 0x44, 0x6E, 0x12, 0x42, 0xBA, 0xD2, 0x39, 0xC9, 0xCD, 0x7B, 0x76, 0x87, 0x89, 0x7D, + 0x9D, 0x0F, 0x9E, 0xBB, 0x0B, 0x4B, 0xFD, 0x9D, 0x2C, 0xCD, 0xFD, 0x0A, 0xAB, 0xD9, 0xBC, 0xF9, 0xF3, 0xEF, 0x33, 0xC8, + 0x9C, 0xF3, 0x8B, 0x79, 0x5C, 0xEC, 0x49, 0x76, 0x88, 0x00, 0x7D, 0xF5, 0xEF, 0x3E, 0xBC, 0x89, 0x81, 0x5D, 0x77, 0x03, + 0xC6, 0x2F, 0x15, 0x76, 0xEC, 0x4C, 0x95, 0xF7, 0x71, 0xED, 0x69, 0x9A, 0x0C, 0xE1, 0x94, 0x23, 0x2F, 0x32, 0xB4, 0x9B, + 0x2A, 0xD0, 0xFC, 0xE8, 0x68, 0x21, 0x25, 0xEB, 0x37, 0x0B, 0xD7, 0x26, 0x6E, 0x60, 0x07, 0xBC, 0xFC, 0x83, 0x3C, 0x77, + 0x5E, 0x20, 0xEB, 0xD2, 0x4E, 0x8F, 0xAA, 0x01, 0xBA, 0xD3, 0x5B, 0xFF, 0x00, 0x93, 0xAC, 0x4C, 0x37, 0x41, 0x46, 0xB2, + 0xD2, 0x88, 0x8E, 0x4B, 0x9A, 0xF2, 0xC5, 0x99, 0xD4, 0xA6, 0x3D, 0x76, 0x82, 0x34, 0xB9, 0xDE, 0x2A, 0x68, 0x9D, 0xBD, + 0x19, 0xB1, 0xBE, 0x2D, 0x5D, 0xE0, 0xF8, 0x64, 0x12, 0x32, 0x7C, 0x71, 0xFD, 0x11, 0xA3, 0x04, 0x93, 0x8C, 0xA3, 0x33, + 0xF8, 0xBF, 0xD7, 0x24, 0x7A, 0x2F, 0xB7, 0x1B, 0xAA, 0xA3, 0x78, 0x77, 0x14, 0x7E, 0xFF, 0xD7, 0xF7, 0xD0, 0x60, 0x50, + 0x36, 0x75, 0x7A, 0x4B, 0x0D, 0xF1, 0x91, 0x51, 0x86, 0xDA, 0x26, 0xC5, 0x5E, 0x52, 0xE7, 0xB3, 0x59, 0x15, 0x00, 0xF2, + 0x14, 0x45, 0x11, 0xDA, 0xD0, 0x34, 0xEA, 0xE6, 0xC8, 0xB2, 0x8F, 0x26, 0xD5, 0x9C, 0x2E, 0x45, 0x2B, 0xD4, 0x09, 0xB2, + 0x39, 0xD4, 0x5D, 0x88, 0x53, 0x78, 0xB4, 0x9F, 0x9B, 0x1B, 0x15, 0xE9, 0x6E, 0x08, 0xE8, 0x09, 0xF5, 0xD5, 0x34, 0x07, + 0xC2, 0xEA, 0xB4, 0x39, 0x40, 0x30, 0x16, 0x3C, 0x6F, 0xC9, 0x4A, 0x2F, 0x05, 0x73, 0xC7, 0x8D, 0x98, 0x76, 0xF9, 0x29, + 0x1C, 0xFA, 0x35, 0x2D, 0xFC, 0x67, 0xC5, 0x3E, 0xDA, 0xD7, 0x35, 0x07, 0x42, 0xC8, 0xCB, 0xE7, 0xD1, 0x36, 0x13, 0x3D, + 0xB9, 0x08, 0x1D, 0xAE, 0x85, 0x18, 0xC6, 0x39, 0xCA, 0x5C, 0x90, 0x33, 0xDB, 0x93, 0xB4, 0xFB, 0x00, 0xBA, 0x9E, 0xF8, + 0xB2, 0x1F, 0xEB, 0xC3, 0x40, 0x69, 0xA8, 0x7D, 0x3A, 0x7D, 0x3C, 0xFC, 0x97, 0x19, 0xD8, 0xC1, 0x33, 0x7E, 0xEF, 0x43, + 0x3E, 0x8A, 0x50, 0xBE, 0xC6, 0x52, 0x6D, 0x1A, 0x20, 0xF5, 0x81, 0xFE, 0xD8, 0x3D, 0x0B, 0x1F, 0x39, 0x1C, 0xF3, 0x03, + 0xBD, 0x17, 0xEC, 0xFE, 0x3F, 0x89, 0xE3, 0x2C, 0xFD, 0x57, 0x6A, 0x1F, 0x20, 0x54, 0xBA, 0xFB, 0x14, 0xE1, 0xF0, 0x2E, + 0x84, 0x82, 0x27, 0x66, 0x52, 0x4D, 0x17, 0x5D, 0xCD, 0x7B, 0xB0, 0x86, 0x26, 0xB9, 0x07, 0xB6, 0x59, 0x15, 0x82, 0x87, + 0x3F, 0x3E, 0xF0, 0x1C, 0xBA, 0xFE, 0x8A, 0x78, 0x45, 0x1F, 0xB0, 0x48, 0xC5, 0x60, 0x63, 0x17, 0x45, 0x1D, 0xFA, 0x00, + 0xA4, 0x70, 0x11, 0xE4, 0xFB, 0xB3, 0x5B, 0x33, 0xC3, 0x53, 0x55, 0x44, 0xB7, 0x15, 0xA0, 0x47, 0x67, 0xC5, 0x88, 0xC0, + 0xEA, 0xE5, 0xC3, 0x65, 0x92, 0x12, 0x44, 0x09, 0xF5, 0x4B, 0xC4, 0x10, 0x84, 0x51, 0x4D, 0x6A, 0x74, 0xE6, 0x26, 0xE8, + 0x43, 0x11, 0xA6, 0xD3, 0xA8, 0xA7, 0x8D, 0xC3, 0x7A, 0xA6, 0x46, 0x7F, 0x4E, 0x17, 0xD6, 0xFC, 0x2D, 0x70, 0x25, 0x19, + 0xF7, 0x86, 0x3B, 0x4C, 0xED, 0x33, 0x7E, 0xD3, 0x9E, 0xEA, 0xCB, 0x6C, 0x2B, 0x68, 0xF5, 0x81, 0x76, 0x18, 0x91, 0xD7, + 0xF0, 0x81, 0x1A, 0xFD, 0x2E, 0xAE, 0xE3, 0xAE, 0x58, 0x8D, 0x8C, 0x8B, 0x8A, 0xE0, 0xEA, 0x1E, 0x3D, 0x5D, 0xDF, 0xEF, + 0xBE, 0xAB, 0x38, 0x60, 0x0C, 0x89, 0xC3, 0x4C, 0xFA, 0x85, 0x78, 0x0B, 0xF7, 0xCA, 0x83, 0xC2, 0x9A, 0xDA, 0xF3, 0x26, + 0xDE, 0xC2, 0x31, 0xDF, 0x97, 0x7B, 0x23, 0x04, 0x84, 0xC9, 0x8B, 0x9B, 0xAE, 0x03, 0x10, 0x40, 0xA5, 0x58, 0x85, 0x8F, + 0x17, 0x28, 0xC2, 0x50, 0x82, 0x01, 0xDA, 0xBD, 0x7C, 0xC0, 0x44, 0x9B, 0xAE, 0x8C, 0xCC, 0xCB, 0xD1, 0x1A, 0x34, 0xC9, + 0x1F, 0x22, 0xB4, 0xFF, 0x43, 0xB6, 0xDF, 0x61, 0x24, 0xB9, 0x00, 0x0D, 0x71, 0xE2, 0x1D, 0xDD, 0x65, 0x68, 0x85, 0x3A, + 0x75, 0xAD, 0xDB, 0xE1, 0x5A, 0x5A, 0xFB, 0x7B, 0xD8, 0xC6, 0x09, 0x45, 0x59, 0x7B, 0xCC, 0x29, 0xDD, 0x06, 0xFF, 0xBD, + 0x5D, 0xCC, 0xC5, 0xDF, 0xFE, 0xFD, 0x7B, 0x83, 0xC5, 0x0F, 0xB6, 0xFF, 0xDF, 0xF4, 0xF4, 0xAE, 0xC0, 0x92, 0x92, 0x06, + 0x16, 0x9C, 0x16, 0x37, 0xD2, 0xFD, 0xAF, 0xB4, 0x06, 0x55, 0x17, 0xE2, 0x25, 0x4D, 0xC2, 0x06, 0x9C, 0x92, 0x1A, 0xB2, + 0xDE, 0x6D, 0x9F, 0x37, 0x3D, 0xF0, 0xB0, 0x2B, 0xE5, 0x52, 0x8B, 0x17, 0x3E, 0xF1, 0x92, 0x00, 0xB2, 0x18, 0x8D, 0x8A, + 0x44, 0x12, 0x03, 0x0B, 0x68, 0x65, 0xDB, 0x8A, 0x1E, 0x90, 0x87, 0x39, 0xEE, 0x17, 0xCB, 0xA4, 0xC1, 0xD1, 0xD3, 0x7D, + 0x0D, 0x62, 0x4D, 0x84, 0x89, 0x59, 0x56, 0x21, 0xED, 0x3E, 0x45, 0x3E, 0x69, 0xF8, 0xDF, 0xC4, 0xBB, 0x30, 0x7E, 0x72, + 0x7E, 0xA8, 0x87, 0xD0, 0xCC, 0x70, 0xDD, 0x28, 0x23, 0x6B, 0xF5, 0x12, 0x34, 0x96, 0xA3, 0x20, 0x28, 0xFE, 0x0F, 0xD7, + 0x5B, 0xD3, 0x12, 0xA4, 0x95, 0xDB, 0x23, 0xC0, 0xE3, 0x7C, 0xC3, 0x46, 0x54, 0xE2, 0x06, 0x60, 0x59, 0x8E, 0x9E, 0xBE, + 0x61, 0x17, 0x3E, 0xB3, 0x6A, 0xA8, 0x1A, 0xDD, 0x1A, 0x5E, 0x05, 0x1E, 0x39, 0x1D, 0x6E, 0x86, 0x9D, 0xA2, 0xBF, 0xA8, + 0x6B, 0x89, 0xE8, 0x2D, 0x01, 0x56, 0x6F, 0x86, 0xAA, 0x0A, 0x07, 0xFD, 0xDE, 0x96, 0x12, 0x38, 0x4F, 0x98, 0xE7, 0x5C, + 0x9A, 0x57, 0xEF, 0x97, 0x14, 0x93, 0x89, 0xF9, 0x56, 0x18, 0x02, 0xFB, 0xAF, 0x99, 0xE9, 0x81, 0xD3, 0x0E, 0xD5, 0xCD, + 0xFA, 0x4A, 0x01, 0x8E, 0x22, 0xBD, 0x44, 0xEE, 0xEB, 0xCA, 0x65, 0x98, 0xF1, 0x5A, 0xEE, 0x2B, 0xFD, 0xDD, 0x56, 0xF3, + 0x80, 0x30, 0x20, 0xF5, 0x29, 0x93, 0x01, 0xDA, 0x9B, 0x5E, 0xC0, 0x54, 0xC5, 0x28, 0x26, 0xC7, 0x8D, 0x1F, 0xD6, 0xF1, + 0x72, 0x6A, 0xA1, 0x2F, 0xF2, 0x05, 0xCC, 0xED, 0x73, 0x7A, 0x3E, 0x31, 0x43, 0x3C, 0x1E, 0x5B, 0x39, 0x60, 0x48, 0x5B, + 0xDB, 0xFF, 0x50, 0x0D, 0x7B, 0x4C, 0xD9, 0xAB, 0xB5, 0x81, 0x70, 0x3E, 0x62, 0x4D, 0x91, 0x26, 0x54, 0x0C, 0x58, 0x80, + 0x7D, 0xBA, 0x30, 0xEF, 0x22, 0x56, 0x40, 0xB1, 0x72, 0x2B, 0x9F, 0x8F, 0x11, 0x24, 0x43, 0x85, 0xAB, 0x70, 0x9D, 0xE3, + 0xA3, 0x85, 0x09, 0x5C, 0x29, 0x28, 0x45, 0xEF, 0x23, 0x5D, 0x0A, 0xE9, 0x81, 0xF8, 0x31, 0x52, 0x4B, 0x2B, 0xA1, 0xD1, + 0x91, 0x42, 0xF9, 0x37, 0x84, 0x6E, 0xE1, 0xE0, 0x9E, 0x27, 0xB9, 0x22, 0xF9, 0x55, 0xE9, 0xFA, 0x43, 0xF5, 0xE8, 0x9F, + 0xDF, 0x99, 0x99, 0xD2, 0x83, 0x4A, 0x8E, 0x79, 0xFA, 0x54, 0xBB, 0x8A, 0xCE, 0xE8, 0x75, 0x0B, 0xCE, 0x3A, 0x6C, 0x3E, + 0x1B, 0x4A, 0x8B, 0x58, 0xB3, 0xE5, 0x6B, 0xFE, 0x39, 0xCB, 0xB6, 0x9A, 0x27, 0xF0, 0x71, 0xA0, 0x20, 0x57, 0x83, 0x48, + 0xB2, 0xE5, 0xCE, 0xEA, 0x32, 0xCE, 0xEE, 0x4C, 0x23, 0xF6, 0xDB, 0xF4, 0x88, 0x4A, 0x83, 0x7E, 0xBF, 0x38, 0x04, 0x21, + 0x6A, 0x19, 0x56, 0xA9, 0x1B, 0x9B, 0x8F, 0x8F, 0x36, 0xD6, 0xDC, 0xA3, 0xE6, 0xC9, 0x4A, 0x9C, 0x51, 0x4F, 0xE7, 0x57, + 0x2D, 0xB6, 0x4D, 0xCD, 0x7D, 0x48, 0x7B, 0x05, 0x3F, 0x66, 0x91, 0x09, 0xB0, 0x2A, 0x83, 0x4F, 0xDC, 0xE7, 0xCB, 0xB9, + 0x6E, 0x65, 0xB1, 0xE3, 0xAA, 0x5C, 0xB8, 0x78, 0x68, 0x4D, 0x83, 0x2C, 0x56, 0xED, 0x70, 0xB7, 0xFE, 0x03, 0x92, 0x7D, + 0x1E, 0x05, 0x72, 0x82, 0xA3, 0x9D, 0x65, 0x45, 0x5C, 0x4F, 0x72, 0xA2, 0x86, 0x90, 0xDF, 0xD8, 0x2E, 0xFC, 0x1B, 0x90, + 0x83, 0x00, 0x8F, 0x78, 0x72, 0x71, 0x7E, 0xCD, 0xF0, 0xE3, 0xAE, 0x3F, 0x61, 0xDB, 0x49, 0x6B, 0x58, 0x44, 0xA8, 0xEB, + 0xE0, 0x6D, 0x51, 0x5B, 0x49, 0x6B, 0xAB, 0x1A, 0xAA, 0x22, 0x20, 0x71, 0x6E, 0xF0, 0xC7, 0xBA, 0xDD, 0xDC, 0x00, 0x73, + 0xA2, 0xC4, 0xBF, 0x43, 0xEE, 0x38, 0xD4, 0x1D, 0xAF, 0xAB, 0x6C, 0x4C, 0x8A, 0x3D, 0x54, 0x80, 0x8D, 0x1C, 0xD5, 0x33, + 0x94, 0x6E, 0x7C, 0x87, 0x40, 0xDA, 0xDD, 0x52, 0x61, 0x3C, 0xAB, 0xE3, 0xC1, 0xCA, 0x01, 0xFF, 0x6E, 0x4D, 0x91, 0x25, + 0xDE, 0x96, 0x0E, 0xC5, 0xBE, 0xFF, 0x17, 0x83, 0x80, 0xC3, 0x30, 0x52, 0x27, 0x39, 0x36, 0x53, 0x82, 0xB8, 0x62, 0x72, + 0x33, 0x73, 0x79, 0x44, 0x54, 0x84, 0x8E, 0x26, 0x11, 0x74, 0x37, 0xA0, 0x4C, 0xD9, 0x2B, 0x9A, 0xFF, 0x82, 0x56, 0xD2, + 0xE1, 0x71, 0x0C, 0xA8, 0x6C, 0xC1, 0xA7, 0xB7, 0x8A, 0x76, 0x83, 0xF5, 0x8F, 0x44, 0x7D, 0x3B, 0x2F, 0x8B, 0xD9, 0x0E, + 0x4E, 0x07, 0xB2, 0x1E, 0x03, 0x80, 0xDD, 0xE1, 0x72, 0x06, 0x05, 0xE1, 0x4A, 0x34, 0x5C, 0x51, 0xAC, 0x8A, 0xBA, 0x8F, + 0x82, 0x53, 0x1D, 0x99, 0x87, 0xD7, 0x66, 0x96, 0xB9, 0x15, 0x01, 0x7C, 0x30, 0x24, 0xD6, 0xA5, 0xBA, 0x23, 0x9E, 0xB9, + 0x85, 0xFE, 0x6E, 0x86, 0xE4, 0x14, 0x0E, 0xDB, 0x17, 0x27, 0x1A, 0x3C, 0x22, 0xA4, 0xCC, 0x54, 0x83, 0xA4, 0x05, 0x6B, + 0x8B, 0xDA, 0xB8, 0xC7, 0xA8, 0x3E, 0x6C, 0x45, 0x14, 0xA1, 0x90, 0x6D, 0xFC, 0x34, 0x0D, 0x7B, 0x2B, 0xCF, 0xF4, 0x63, + 0x39, 0x2A, 0x25, 0x3B, 0x3D, 0x58, 0x67, 0x99, 0xCA, 0xEC, 0xA1, 0xB6, 0x4B, 0x18, 0x06, 0x70, 0x2C, 0xB7, 0x2F, 0x9B, + 0x48, 0xD5, 0x1A, 0xEE, 0x3E, 0x3E, 0x6E, 0x52, 0x2A, 0xDF, 0xD8, 0xF1, 0xD0, 0x4C, 0x07, 0xEF, 0xCE, 0x82, 0xA6, 0x0C, + 0x1A, 0xDC, 0x3E, 0xBA, 0x88, 0x97, 0x38, 0x2F, 0xD9, 0x31, 0x77, 0x63, 0xE9, 0x8C, 0x04, 0x61, 0x13, 0x4F, 0x72, 0x5D, + 0xDD, 0x8F, 0x85, 0x3F, 0x98, 0x04, 0x5E, 0x9F, 0x14, 0x62, 0xCA, 0x17, 0x12, 0x0E, 0x40, 0x1C, 0x95, 0x8D, 0x58, 0x04, + 0x2D, 0x57, 0x93, 0x1F, 0xE7, 0x81, 0xB3, 0x66, 0x44, 0x6D, 0x86, 0x70, 0xC7, 0x59, 0x88, 0x72, 0x62, 0x71, 0x60, 0x7F, + 0xC7, 0x15, 0x03, 0x34, 0x49, 0xFA, 0x43, 0x23, 0x06, 0x56, 0x5A, 0x17, 0xE3, 0x12, 0x0F, 0x42, 0xA5, 0xE2, 0xE8, 0x9D, + 0x73, 0xF2, 0x21, 0x06, 0xE6, 0x5B, 0x93, 0xEC, 0xF6, 0x53, 0xAE, 0x51, 0x87, 0xCC, 0xCE, 0x51, 0x2A, 0x8D, 0x28, 0xDE, + 0xEF, 0x75, 0xE2, 0xA4, 0x5E, 0xCE, 0x4D, 0xE6, 0x3C, 0x29, 0x98, 0xE2, 0x20, 0xA7, 0x11, 0x21, 0x73, 0x0C, 0xFE, 0x7F, + 0xFC, 0xE1, 0x00, 0xF0, 0xCA, 0xFC, 0x86, 0xF2, 0x21, 0xA6, 0x86, 0x3D, 0xE7, 0x82, 0xFD, 0x8C, 0xF5, 0x9C, 0x4A, 0x81, + 0x6A, 0x7B, 0xB9, 0x6F, 0xD0, 0x55, 0x49, 0xD9, 0x86, 0x85, 0xD3, 0xE7, 0x1A, 0x08, 0x41, 0x93, 0xC3, 0x89, 0xF1, 0x46, + 0x23, 0xFD, 0x5A, 0x2D, 0x6F, 0x0C, 0xB5, 0xFD, 0x98, 0x25, 0x6A, 0x6F, 0xB7, 0x53, 0xD0, 0x36, 0x5D, 0x28, 0xAE, 0xFC, + 0x0B, 0xF9, 0x92, 0xE4, 0x3C, 0x31, 0xED, 0xED, 0x36, 0xC9, 0xE8, 0x1A, 0xA0, 0xE2, 0x5B, 0xE3, 0xDC, 0x01, 0xF1, 0x4D, + 0x77, 0xCE, 0x53, 0xD6, 0xC4, 0x88, 0x89, 0xA7, 0x7B, 0xA6, 0x99, 0xBB, 0x91, 0xCB, 0x07, 0x60, 0x4F, 0xD4, 0x60, 0x19, + 0xB2, 0xEB, 0xB9, 0xD7, 0x27, 0x36, 0x5F, 0xCE, 0x74, 0x61, 0x46, 0x3C, 0xBD, 0x27, 0xA3, 0x82, 0xDE, 0x8E, 0xC5, 0xA7, + 0xDC, 0x80, 0x0A, 0x08, 0x67, 0x80, 0x39, 0x72, 0xFE, 0xA2, 0x79, 0x18, 0xF8, 0xA8, 0x34, 0xB9, 0x8D, 0xE5, 0x59, 0xA9, + 0x22, 0x81, 0x68, 0x7E, 0xA6, 0xEC, 0xA0, 0x16, 0xC8, 0x1D, 0xE8, 0x0D, 0x2D, 0x43, 0x33, 0x5F, 0x08, 0xDC, 0xF7, 0x94, + 0x76, 0xDE, 0x43, 0xBC, 0x15, 0x92, 0xFE, 0x04, 0x9D, 0x79, 0x8A, 0xE0, 0xDB, 0xF5, 0xC4, 0xC4, 0x20, 0xBD, 0x4C, 0x64, + 0x78, 0xCB, 0x0C, 0x86, 0x99, 0x90, 0xCA, 0x7F, 0x92, 0xD3, 0x97, 0x51, 0xA3, 0xB9, 0x67, 0x50, 0xE7, 0x05, 0xCF, 0xD0, + 0x8A, 0x9F, 0x1D, 0xDC, 0xA2, 0xE2, 0x5C, 0xC0, 0x66, 0xCD, 0x36, 0x45, 0x66, 0x06, 0x0D, 0xB7, 0x53, 0xE9, 0x7D, 0x65, + 0x27, 0x47, 0xAB, 0xF5, 0x0A, 0x2E, 0x10, 0x51, 0xD6, 0xC1, 0xDF, 0xB3, 0xF4, 0x83, 0x5E, 0x20, 0x8A, 0x9B, 0xF4, 0xF7, + 0x08, 0xB2, 0xB4, 0x5E, 0x36, 0x09, 0x0C, 0xF7, 0x4E, 0x59, 0x34, 0xDA, 0xA5, 0x19, 0xBA, 0x52, 0x4D, 0xBB, 0x1C, 0xB5, + 0x24, 0xD8, 0xB4, 0xF2, 0x7E, 0x6A, 0x05, 0x85, 0xEA, 0x9B, 0xC5, 0x21, 0x17, 0xBF, 0x0D, 0xC4, 0x1B, 0xD9, 0xE0, 0xA0, + 0x34, 0x06, 0xFF, 0xB1, 0x84, 0xD7, 0xD5, 0x2D, 0x1B, 0xBA, 0x25, 0xFB, 0x65, 0x5B, 0x6D, 0xD7, 0xB7, 0xB7, 0x55, 0xE8, + 0xD3, 0xDA, 0x43, 0x61, 0x0F, 0xDF, 0x8E, 0x28, 0xB8, 0x4F, 0x09, 0xFE, 0xFC, 0xB7, 0xEE, 0x47, 0x51, 0x62, 0xCD, 0x5E, + 0x65, 0x32, 0xE1, 0xBB, 0x6B, 0x73, 0x68, 0xF8, 0x1F, 0xB8, 0xAD, 0xE9, 0xD3, 0xBA, 0x1F, 0x75, 0x01, 0xD4, 0x4F, 0x8F, + 0xDB, 0x2F, 0x8A, 0xCF, 0xF8, 0xB4, 0xAF, 0x9F, 0x93, 0x5F, 0xAB, 0xD5, 0x44, 0xA7, 0x80, 0x9F, 0x0C, 0xE4, 0x9C, 0x83, + 0x25, 0x0A, 0x8E, 0x66, 0x1D, 0x58, 0x99, 0x89, 0xC3, 0x0A, 0xE4, 0x88, 0x4D, 0x9C, 0xD2, 0x34, 0x5C, 0xCC, 0x39, 0xAD, + 0x8E, 0xC2, 0x90, 0xE6, 0x39, 0x0E, 0xEE, 0x88, 0x84, 0xEC, 0x9E, 0xA1, 0xDC, 0xF0, 0xA7, 0x77, 0xD3, 0xDC, 0x99, 0xF6, + 0x4B, 0x28, 0x9F, 0x47, 0x4A, 0x8D, 0x35, 0x4F, 0xB6, 0x9C, 0xDB, 0xB9, 0x20, 0x29, 0x91, 0xBD, 0x4C, 0xDA, 0x25, 0x8B, + 0x87, 0xEE, 0x8D, 0xFA, 0xF3, 0x91, 0x20, 0x01, 0x8D, 0x08, 0xE9, 0x77, 0x64, 0x23, 0x70, 0x64, 0xC0, 0x4D, 0x28, 0x34, + 0xF7, 0x0E, 0x0D, 0x56, 0x49, 0x1A, 0xEE, 0x29, 0xFA, 0xD0, 0x5C, 0x56, 0x20, 0x61, 0xA6, 0xF5, 0x30, 0x65, 0x81, 0x02, + 0x53, 0x4E, 0x3F, 0x9C, 0x1D, 0xAF, 0x1B, 0x23, 0x63, 0x59, 0xAF, 0x84, 0x1A, 0x28, 0x99, 0x77, 0xA0, 0x43, 0xB3, 0x86, + 0xE5, 0x8C, 0x41, 0x98, 0x43, 0x4B, 0xE0, 0x46, 0xF3, 0xEA, 0x32, 0x48, 0x02, 0x0C, 0x1E, 0x9F, 0x6D, 0x64, 0x85, 0x08, + 0x43, 0x86, 0x09, 0xE6, 0xD2, 0xAC, 0x9A, 0x49, 0x6B, 0x08, 0xAE, 0xD6, 0x93, 0xDC, 0x4E, 0xD1, 0xA8, 0x66, 0xF8, 0x34, + 0xF0, 0x61, 0xC1, 0x02, 0x14, 0x00, 0x01, 0xE8, 0x56, 0x0B, 0x57, 0x58, 0xA1, 0x99, 0x8B, 0x9A, 0x71, 0x60, 0x95, 0x12, + 0xD9, 0x2B, 0xF1, 0xB5, 0xC7, 0x8A, 0x03, 0x8E, 0xA9, 0x44, 0xD8, 0x84, 0xAA, 0x73, 0x26, 0xD2, 0x2A, 0x1A, 0x11, 0xCB, + 0xF1, 0xD9, 0x3A, 0x4A, 0xBF, 0x2D, 0xB2, 0xA6, 0x59, 0x18, 0x32, 0xAA, 0x05, 0x69, 0x4A, 0xC0, 0x1B, 0x21, 0xEC, 0x4A, + 0xEA, 0x4F, 0xCE, 0xF8, 0x6A, 0xCF, 0x47, 0x8B, 0x55, 0x05, 0xE5, 0xAC, 0x71, 0x29, 0x2B, 0xD6, 0x4A, 0x42, 0xB5, 0x8D, + 0xD3, 0xCE, 0xE7, 0x1B, 0x81, 0x67, 0x09, 0x0E, 0xED, 0x28, 0x13, 0x8B, 0x68, 0xD4, 0xA5, 0x99, 0x7E, 0xC0, 0xD4, 0x0B, + 0x68, 0x20, 0x4D, 0xFE, 0x1E, 0x1C, 0x2C, 0xC8, 0xA3, 0x9D, 0xF2, 0x69, 0x31, 0xD5, 0xD6, 0x1B, 0x68, 0x21, 0x6C, 0xBE, + 0xF8, 0x48, 0x42, 0xF5, 0x4D, 0x3E, 0xCF, 0x1C, 0x43, 0x6B, 0x4F, 0x0A, 0xC1, 0x22, 0xA3, 0x4F, 0xEA, 0xA5, 0x4B, 0xF4, + 0x23, 0xBF, 0xF6, 0x1E, 0xA3, 0xC7, 0xE9, 0xDD, 0xB5, 0x57, 0xB3, 0xD9, 0x82, 0x00, 0x07, 0x1B, 0x29, 0x6F, 0xFB, 0x45, + 0x32, 0xD6, 0xEC, 0x84, 0xA5, 0x90, 0xFC, 0x80, 0x36, 0xB0, 0x6C, 0xD2, 0x9B, 0xAF, 0xEA, 0x9D, 0x85, 0xD3, 0x88, 0x72, + 0xA3, 0x59, 0xB4, 0x6B, 0xF9, 0x80, 0x5B, 0x94, 0x88, 0xF8, 0x4C, 0xB7, 0x90, 0x30, 0x65, 0xC5, 0xE7, 0x99, 0xAA, 0xE7, + 0x47, 0x57, 0xD5, 0x61, 0xE0, 0x1E, 0x86, 0x56, 0x80, 0xD2, 0xC4, 0x73, 0x23, 0x5B, 0x2D, 0x86, 0xC1, 0x57, 0x45, 0xB4, + 0xE7, 0x89, 0xA3, 0x69, 0xD2, 0x33, 0x53, 0x44, 0x1C, 0xE5, 0xFC, 0x94, 0x36, 0x3B, 0x6C, 0x52, 0x32, 0x54, 0x64, 0x93, + 0x7C, 0xAB, 0x32, 0x71, 0xD6, 0xB6, 0x5B, 0x36, 0xB1, 0x31, 0x3C, 0x44, 0xB6, 0xF4, 0x75, 0x8A, 0xE6, 0x80, 0xBE, 0xBE, + 0xCA, 0x35, 0xFD, 0x37, 0x30, 0x32, 0x5D, 0xE5, 0x4B, 0xF0, 0x61, 0x87, 0xFC, 0x09, 0x1D, 0x22, 0x81, 0xBA, 0x94, 0xB7, + 0x4C, 0x33, 0x65, 0x14, 0x6A, 0x9A, 0x8B, 0x8A, 0xDD, 0xD1, 0x1E, 0x78, 0x57, 0x17, 0xBE, 0x76, 0x94, 0x35, 0x71, 0x2C, + 0x27, 0x30, 0xBA, 0x07, 0x7E, 0x82, 0x6E, 0xDC, 0x26, 0x14, 0x5D, 0x6F, 0x4D, 0x57, 0x1F, 0x5A, 0xEC, 0xD9, 0xCA, 0xCF, + 0x6E, 0x06, 0xB3, 0x79, 0x57, 0x15, 0x10, 0x7E, 0xC4, 0xA7, 0x77, 0xE9, 0x27, 0xD1, 0xC4, 0xB3, 0xDA, 0x8E, 0x05, 0x98, + 0x0A, 0x1D, 0xB1, 0xA0, 0x73, 0x32, 0x8F, 0xA7, 0x99, 0xAF, 0x46, 0xBD, 0x02, 0xE0, 0xD5, 0x28, 0x67, 0xBC, 0x80, 0x8A, + 0x2C, 0x3A, 0x7A, 0x86, 0xE3, 0x01, 0xEE, 0x12, 0x87, 0xCD, 0x70, 0xE4, 0x0A, 0xBD, 0x35, 0x3E, 0x9A, 0xB7, 0x62, 0xF1, + 0xC2, 0xFE, 0xE1, 0xCD, 0xDA, 0x82, 0x50, 0x4D, 0x94, 0x46, 0xE7, 0xF1, 0x1B, 0xB4, 0x7B, 0x97, 0x63, 0x01, 0xA8, 0x93, + 0x88, 0xE1, 0x8F, 0x74, 0xF4, 0x17, 0xB0, 0x3F, 0x1A, 0xB0, 0x63, 0x38, 0x42, 0x26, 0xE4, 0x79, 0x8D, 0x0B, 0x28, 0x06, + 0x8C, 0x1E, 0x86, 0x3B, 0x3E, 0xCC, 0x84, 0x40, 0xC9, 0x36, 0xC8, 0x22, 0xBD, 0xA3, 0x92, 0xF2, 0x01, 0xA5, 0x96, 0x4F, + 0x74, 0xA5, 0x87, 0xDA, 0x41, 0x1D, 0x18, 0x45, 0xF6, 0x62, 0x89, 0x8B, 0xB7, 0x16, 0x9F, 0xA6, 0x5E, 0x7A, 0xCE, 0x59, + 0x12, 0x1D, 0x83, 0x17, 0xF5, 0x4D, 0x80, 0xB3, 0xD1, 0x81, 0xD0, 0x64, 0xB7, 0x2A, 0x95, 0xB6, 0x10, 0xA1, 0x0F, 0xC4, + 0x59, 0x4E, 0xA0, 0xEF, 0x59, 0x8C, 0xDA, 0xB9, 0x10, 0xD7, 0x32, 0xE6, 0x78, 0xEF, 0x88, 0x94, 0xFA, 0xEB, 0xBD, 0x6F, + 0x01, 0xD6, 0x3D, 0x40, 0x6C, 0xA5, 0x2C, 0x4C, 0x65, 0x87, 0x2A, 0x79, 0x39, 0x50, 0x3F, 0x52, 0xFE, 0xC4, 0x43, 0xBA, + 0x9A, 0xE4, 0x2B, 0x13, 0x65, 0x33, 0x61, 0x78, 0xBC, 0x52, 0xD0, 0xD7, 0xB9, 0x9E, 0xB2, 0x37, 0xE8, 0x87, 0xF6, 0x44, + 0x3B, 0xE4, 0xFC, 0x48, 0xC7, 0xA5, 0xCA, 0x8A, 0x3F, 0x9A, 0x82, 0x84, 0x1F, 0x50, 0x5B, 0xC1, 0xB3, 0xCE, 0xE2, 0xCC, + 0xF0, 0x45, 0x52, 0xF2, 0x17, 0xC4, 0xB9, 0x19, 0xF4, 0xF3, 0x8E, 0x45, 0xEE, 0xCF, 0xE4, 0xDC, 0x59, 0x6C, 0x9B, 0x89, + 0xAE, 0xBA, 0x85, 0x36, 0x18, 0x0E, 0x3B, 0x99, 0x39, 0xC5, 0xE7, 0xCD, 0x35, 0xB0, 0x4B, 0xBB, 0xD1, 0x84, 0xE9, 0xCF, + 0x6A, 0x00, 0x33, 0x8C, 0xAE, 0xEB, 0x08, 0xDD, 0xB5, 0x5A, 0x6A, 0x22, 0x46, 0x3D, 0x22, 0xAA, 0x74, 0xA8, 0xC1, 0xCA, + 0x48, 0x76, 0x3D, 0x7D, 0x87, 0x11, 0xAA, 0xF6, 0xE2, 0x20, 0xEB, 0xDC, 0x9F, 0x7C, 0x84, 0x5E, 0x87, 0x74, 0xC5, 0x4F, + 0xFE, 0x12, 0x5D, 0x87, 0xEE, 0xAE, 0xFB, 0x89, 0x88, 0xE0, 0x84, 0x7A, 0xB6, 0xEB, 0xDC, 0x35, 0x2B, 0x72, 0xFC, 0xBB, + 0x90, 0x2F, 0xD3, 0x0F, 0x97, 0xA0, 0x6E, 0xF9, 0x4F, 0xC7, 0xC0, 0xFB, 0xA9, 0x9B, 0x28, 0x85, 0x85, 0x18, 0x9A, 0x5B, + 0x32, 0x6A, 0x23, 0xD0, 0x8F, 0x93, 0xB4, 0x22, 0x7C, 0x9E, 0xE8, 0xF0, 0x64, 0xD1, 0xE6, 0x94, 0x7F, 0xDD, 0x71, 0xF2, + 0x61, 0xF4, 0x0B, 0x17, 0xAC, 0x8C, 0x65, 0x61, 0x26, 0x9A, 0xE5, 0xC7, 0xF4, 0xA9, 0x0B, 0x07, 0x69, 0x74, 0x12, 0x9A, + 0x00, 0xF1, 0x55, 0xF1, 0xE4, 0x13, 0x97, 0x04, 0x94, 0x4C, 0x90, 0xC0, 0xF2, 0x6C, 0x92, 0x4F, 0xF5, 0xB1, 0x31, 0xD3, + 0x5E, 0x1F, 0x84, 0xC4, 0x4A, 0xBB, 0x48, 0x1E, 0xCF, 0x60, 0x0F, 0xC1, 0xD7, 0x0B, 0xAC, 0x7F, 0x16, 0x9F, 0x9C, 0xD4, + 0x03, 0x4E, 0x40, 0x61, 0xE2, 0x97, 0xF4, 0xE2, 0xA2, 0xA8, 0xE5, 0x47, 0x98, 0x0E, 0xDF, 0x38, 0xB0, 0xF7, 0x49, 0x65, + 0x61, 0x94, 0x19, 0x68, 0x03, 0xA0, 0x6B, 0x57, 0x99, 0x6D, 0x69, 0x53, 0x89, 0x73, 0x41, 0x60, 0x06, 0x28, 0x56, 0xA8, + 0x4A, 0x0B, 0x5E, 0xE8, 0x6D, 0x99, 0x9C, 0x1D, 0x63, 0x67, 0x6D, 0xAA, 0x53, 0xDB, 0xB2, 0x69, 0xA4, 0x29, 0x56, 0x18, + 0x28, 0xBD, 0x15, 0x1A, 0x6A, 0xBB, 0x6B, 0xBE, 0x91, 0x68, 0xA9, 0xF9, 0xBF, 0xE9, 0x5F, 0xE9, 0xED, 0x92, 0x0B, 0xFC, + 0xC0, 0x4C, 0x69, 0x03, 0x98, 0x71, 0x8D, 0x5C, 0x84, 0x57, 0x17, 0xCB, 0xA5, 0x94, 0xE7, 0x8E, 0x8E, 0x53, 0x8C, 0x83, + 0xEB, 0xC3, 0xF7, 0xE1, 0x14, 0x4A, 0x6E, 0xE2, 0x66, 0x2D, 0x26, 0x26, 0x3E, 0xBA, 0xB6, 0xDF, 0xD9, 0x51, 0xC8, 0x5A, + 0x16, 0xEC, 0xAE, 0x76, 0xC2, 0x30, 0x96, 0x5A, 0x58, 0xC3, 0x42, 0x69, 0x10, 0xBD, 0xE8, 0xF7, 0x94, 0xCD, 0x59, 0x07, + 0xC6, 0x93, 0xAF, 0x58, 0xDD, 0xAE, 0x88, 0x6F, 0xB1, 0xD0, 0x89, 0xE7, 0x17, 0x1D, 0xF8, 0xBB, 0xE7, 0xDD, 0xCF, 0x4A, + 0xB9, 0x35, 0xBF, 0x56, 0x2B, 0x9D, 0x7F, 0xBF, 0xFF, 0xFF, 0x60, 0x52, 0x64, 0x0D, 0xFF, 0x77, 0xB3, 0x73, 0xEF, 0x67, + 0xC2, 0x4C, 0xC9, 0x7F, 0x56, 0x71, 0x36, 0xD5, 0x22, 0x41, 0x41, 0xF6, 0xF1, 0x85, 0x78, 0x72, 0xB8, 0x4C, 0xA5, 0x76, + 0xF0, 0x3C, 0x59, 0x05, 0x88, 0x5F, 0xFA, 0x76, 0xE8, 0x86, 0xAA, 0x43, 0x1E, 0x4D, 0x43, 0x4F, 0x51, 0x6F, 0x0D, 0x92, + 0x60, 0xBC, 0xF1, 0x54, 0x7A, 0x6B, 0xFA, 0xD3, 0x99, 0x63, 0xB1, 0x57, 0x6C, 0x6F, 0x1E, 0x04, 0xA2, 0xBF, 0x93, 0xDA, + 0xF9, 0xB7, 0xFA, 0x12, 0xBD, 0x40, 0xC2, 0x65, 0xB9, 0x97, 0x47, 0x03, 0x74, 0x20, 0xC8, 0x2B, 0x7B, 0x96, 0x00, 0xED, + 0xC1, 0x41, 0xB8, 0xB4, 0x9D, 0x68, 0x59, 0xB9, 0x1C, 0x44, 0x51, 0x7A, 0x85, 0xFD, 0x45, 0x89, 0xC8, 0x0B, 0xEB, 0x41, + 0x0E, 0x37, 0x96, 0x31, 0x85, 0x84, 0xB7, 0xEC, 0x66, 0x84, 0x17, 0x13, 0x80, 0xB7, 0xAB, 0x5B, 0xC7, 0x61, 0x5B, 0x82, + 0xAD, 0xF7, 0x2D, 0x63, 0xC5, 0xF4, 0x52, 0x5A, 0xCA, 0x44, 0xAA, 0x5F, 0x76, 0xC9, 0x8A, 0x19, 0xBC, 0x82, 0x53, 0x2B, + 0x1F, 0x91, 0x7A, 0x7F, 0x7C, 0x46, 0x5A, 0x14, 0x84, 0xC4, 0x3C, 0x4E, 0x56, 0x02, 0x3A, 0x53, 0xA7, 0x23, 0x2C, 0xCB, + 0x64, 0x45, 0xAB, 0xD2, 0x31, 0x29, 0x45, 0x20, 0x3A, 0x46, 0xA5, 0xEC, 0xED, 0xCE, 0xAF, 0xDB, 0x4B, 0x6F, 0x88, 0xD2, + 0xEE, 0x6B, 0x2D, 0xCC, 0x5D, 0xB7, 0x91, 0xBF, 0x68, 0x6D, 0x0C, 0x8A, 0x5E, 0xC9, 0x9A, 0xFE, 0xFB, 0x93, 0x09, 0xDC, + 0x67, 0x9E, 0xB4, 0xE1, 0xF2, 0xBE, 0xB6, 0xE7, 0xA2, 0x42, 0x59, 0xFE, 0x52, 0x0B, 0x0B, 0x79, 0xA8, 0xCD, 0xFD, 0xF4, + 0xFA, 0xD1, 0xAC, 0x81, 0xCA, 0x03, 0x67, 0x0F, 0xA7, 0x67, 0x12, 0xFF, 0x2E, 0xF0, 0x99, 0xA2, 0x70, 0xFC, 0x41, 0x7B, + 0x78, 0xC4, 0xE3, 0xAD, 0x20, 0x60, 0x05, 0x82, 0x68, 0x7C, 0x13, 0xAA, 0x44, 0xC5, 0x74, 0xE7, 0x59, 0x5F, 0xBB, 0x20, + 0x30, 0x9B, 0x65, 0x7B, 0xDE, 0x7D, 0x83, 0xC7, 0xD8, 0xA0, 0x56, 0xAD, 0x40, 0x91, 0xE2, 0x11, 0x90, 0xD2, 0xD1, 0xDF, + 0x8E, 0xCE, 0xD1, 0xBB, 0x92, 0x70, 0x75, 0xA2, 0x02, 0x5F, 0xAB, 0x9D, 0x98, 0x11, 0x6D, 0xD6, 0x9C, 0x1E, 0x4D, 0xBD, + 0x49, 0x92, 0x43, 0x53, 0xA9, 0xD6, 0x4D, 0x46, 0xD7, 0xD3, 0x46, 0x28, 0x70, 0x59, 0xE4, 0x37, 0x91, 0x26, 0x60, 0x5C, + 0x89, 0x30, 0xEA, 0xC9, 0x31, 0xAB, 0x34, 0xE2, 0xDC, 0x0E, 0xB4, 0xF0, 0xDA, 0x6F, 0xE8, 0x92, 0x88, 0xB6, 0xCA, 0x96, + 0x8C, 0xDC, 0xBA, 0xB2, 0x93, 0xE2, 0x7D, 0xB5, 0x32, 0x90, 0x6D, 0xC5, 0x09, 0x95, 0xF5, 0xF8, 0x1B, 0x27, 0xCD, 0x37, + 0x90, 0xD7, 0xDB, 0x74, 0x58, 0x14, 0xB1, 0x62, 0xC1, 0xFA, 0x48, 0x25, 0xF7, 0xD8, 0xE1, 0x6A, 0xAA, 0x74, 0x11, 0x7F, + 0x44, 0xE5, 0x36, 0xA9, 0x89, 0x5E, 0x03, 0xAE, 0x9C, 0x39, 0x6E, 0xDA, 0xD0, 0x14, 0x4E, 0xB4, 0x85, 0x98, 0x3A, 0x0B, + 0xC8, 0xD3, 0xC6, 0xDC, 0x4A, 0x5B, 0x9E, 0xEB, 0x7E, 0x15, 0xD1, 0xB1, 0x53, 0xEB, 0xBF, 0xBC, 0x4B, 0x5C, 0x3F, 0x04, + 0x11, 0x63, 0xF4, 0xBE, 0x08, 0x07, 0xDB, 0x6E, 0x93, 0xE6, 0x98, 0xD9, 0xAD, 0xF0, 0x27, 0x5D, 0xB9, 0xD6, 0xFE, 0xF5, + 0x8D, 0x91, 0xFC, 0x7D, 0x18, 0x93, 0xC1, 0x98, 0xEA, 0x43, 0xC5, 0x9F, 0x46, 0xF6, 0xF6, 0x1F, 0xE9, 0x94, 0x8C, 0x23, + 0xD2, 0x2E, 0x3F, 0xDC, 0x08, 0x58, 0xE0, 0xC4, 0x5A, 0x46, 0x39, 0xA1, 0x41, 0x37, 0x97, 0xE9, 0x53, 0x64, 0x69, 0x5D, + 0x8B, 0x5A, 0xD3, 0xB0, 0x11, 0x0F, 0x47, 0xC1, 0x0E, 0x9E, 0x63, 0x42, 0x9F, 0x92, 0x49, 0x40, 0x00, 0x1B, 0x1F, 0x20, + 0x3E, 0xF2, 0x78, 0x7A, 0x86, 0xEC, 0xFE, 0x3B, 0x35, 0x0B, 0xC0, 0x40, 0x07, 0x30, 0xEF, 0x04, 0x27, 0xB5, 0x10, 0x58, + 0xFC, 0x9D, 0xB0, 0x05, 0x6D, 0xD0, 0x3E, 0x00, 0xC5, 0xE1, 0x80, 0xD9, 0xD6, 0xEC, 0xB8, 0x61, 0x73, 0xE7, 0xF1, 0x30, + 0xFF, 0x81, 0x29, 0x37, 0xAF, 0xCD, 0x71, 0x1B, 0xB4, 0xEC, 0x28, 0x11, 0xCD, 0x5F, 0x97, 0x3A, 0xB4, 0xB0, 0x03, 0xB1, + 0x04, 0x62, 0x40, 0xF5, 0x74, 0xDC, 0x8C, 0xAA, 0xD6, 0xC9, 0x70, 0xC2, 0x12, 0xB5, 0x50, 0xE8, 0x47, 0x64, 0x90, 0x27, + 0xDA, 0xE9, 0x10, 0xDA, 0xA2, 0x0C, 0x5B, 0xFA, 0xEB, 0xD6, 0x6F, 0x52, 0x41, 0x45, 0xB0, 0xE5, 0xF6, 0x4A, 0x86, 0xB3, + 0x06, 0x29, 0x42, 0x7A, 0x4A, 0xA5, 0xAE, 0x62, 0xC0, 0xDC, 0xFB, 0x66, 0x75, 0xE0, 0x49, 0xC0, 0x24, 0x8F, 0xB2, 0x57, + 0xB3, 0x0A, 0x43, 0x9B, 0xC7, 0x88, 0x6C, 0x04, 0xE3, 0x8B, 0x8E, 0x8F, 0xD9, 0xEA, 0x9C, 0xAF, 0x7C, 0x28, 0x4A, 0xA8, + 0xC4, 0xAF, 0xDA, 0x4C, 0xEF, 0x95, 0xED, 0xEA, 0x05, 0x52, 0xD1, 0xEF, 0x14, 0xA9, 0xB8, 0xCB, 0xEE, 0x69, 0x41, 0x55, + 0x27, 0x56, 0x4A, 0xE0, 0xAE, 0x87, 0xDC, 0x7D, 0xF6, 0xA9, 0x0B, 0xFB, 0x90, 0xC3, 0x24, 0xD0, 0x69, 0x39, 0x2B, 0x51, + 0x74, 0x97, 0x8D, 0x27, 0x98, 0xDE, 0x09, 0x39, 0xC5, 0x46, 0x82, 0x87, 0x2E, 0xF0, 0x60, 0x8C, 0x62, 0x88, 0x2B, 0x7E, + 0xE1, 0x53, 0xE2, 0x19, 0x34, 0x6D, 0x36, 0x0E, 0x50, 0x41, 0x4A, 0xC0, 0x70, 0x9C, 0xB3, 0x4C, 0xBA, 0x0B, 0xAE, 0x84, + 0x2C, 0xC4, 0xFE, 0x8D, 0x2F, 0x40, 0x65, 0xCF, 0xD9, 0x17, 0xD9, 0xFF, 0x61, 0xEF, 0x4B, 0x94, 0x27, 0x5D, 0x66, 0x1E, + 0xEA, 0x64, 0x32, 0xDA, 0x2A, 0x84, 0x3D, 0x2C, 0xF9, 0x26, 0xEC, 0x88, 0x4B, 0x44, 0x6A, 0xAF, 0xD7, 0x10, 0x1B, 0xC8, + 0x34, 0x94, 0xF2, 0x26, 0xDF, 0xB3, 0x4C, 0xB3, 0x84, 0xD4, 0x78, 0x46, 0x73, 0xF3, 0x87, 0x17, 0xB6, 0xAE, 0x96, 0x65, + 0x13, 0x1E, 0x76, 0x50, 0x41, 0x93, 0xB7, 0x70, 0x4F, 0xB3, 0x23, 0xDD, 0x29, 0xF0, 0xE3, 0xAA, 0x34, 0x3E, 0x31, 0xD1, + 0x66, 0xBE, 0x35, 0xFA, 0xD4, 0xC1, 0x7D, 0xF1, 0xFB, 0x18, 0x79, 0x7F, 0x6C, 0xF1, 0x2C, 0x45, 0x0C, 0x89, 0xEE, 0x63, + 0x72, 0x63, 0x07, 0x24, 0x4D, 0xBD, 0xA9, 0x56, 0xC9, 0x19, 0x2E, 0xCC, 0x0C, 0x47, 0x8A, 0xDE, 0xF4, 0xFC, 0x6E, 0x34, + 0x21, 0x4F, 0xD2, 0x1A, 0x75, 0x4A, 0x46, 0x57, 0x90, 0xB9, 0xB1, 0xFE, 0x1C, 0x66, 0x61, 0x2B, 0xA6, 0xDB, 0x72, 0x80, + 0x68, 0xF7, 0x0B, 0xE4, 0xC2, 0x29, 0xFC, 0x95, 0x55, 0xB4, 0x32, 0x13, 0xBB, 0x96, 0xD3, 0xEB, 0x3A, 0x41, 0x43, 0x52, + 0x39, 0x78, 0xFC, 0x18, 0xC0, 0xFB, 0x22, 0x76, 0x2C, 0x84, 0xA4, 0x3C, 0x3C, 0xB8, 0x24, 0x54, 0x87, 0x49, 0x76, 0x6B, + 0xBF, 0xB6, 0x28, 0xDD, 0x03, 0x45, 0x3B, 0xED, 0x01, 0xD5, 0x29, 0xC9, 0x7A, 0x72, 0xA6, 0x52, 0xD5, 0x82, 0x18, 0xC1, + 0xBC, 0x9E, 0xA7, 0x8F, 0x5D, 0x15, 0x09, 0x62, 0xAE, 0x75, 0x33, 0x53, 0x36, 0x01, 0xFB, 0xC5, 0x3E, 0xA4, 0xC9, 0xA6, + 0xBE, 0xD1, 0x47, 0xBF, 0x0D, 0xAA, 0xA7, 0x4E, 0xF4, 0xDB, 0xF0, 0xC2, 0x0E, 0xEC, 0x76, 0x3E, 0x9E, 0x1D, 0x22, 0x99, + 0x4C, 0x0A, 0x89, 0x16, 0xAC, 0x03, 0xEE, 0xD7, 0xCE, 0x86, 0x5F, 0x6F, 0x1D, 0x12, 0x85, 0xBD, 0x86, 0x6E, 0xFF, 0x06, + 0x7F, 0x06, 0x61, 0xB8, 0xDF, 0x19, 0xB3, 0x3C, 0x3A, 0x35, 0x09, 0x4B, 0xCA, 0xBD, 0x37, 0xEE, 0xEF, 0x45, 0x6F, 0x3D, + 0xA9, 0x65, 0x4B, 0xFB, 0x56, 0x0C, 0x98, 0x08, 0x95, 0x72, 0xFF, 0x03, 0x7E, 0xBD, 0x0D, 0xBD, 0xFD, 0xD8, 0x86, 0x3C, + 0x90, 0xA7, 0x28, 0xDF, 0x2B, 0x4F, 0xB6, 0x09, 0xDC, 0x22, 0x36, 0x28, 0x8C, 0x87, 0xC5, 0xFB, 0x26, 0x21, 0x0A, 0x50, + 0xAA, 0x05, 0xE0, 0x13, 0xB8, 0x30, 0x19, 0x80, 0xC8, 0x93, 0x41, 0x48, 0x85, 0x8F, 0x91, 0x52, 0xB0, 0xC7, 0x56, 0x50, + 0x39, 0x53, 0x8D, 0x51, 0x0E, 0x05, 0x56, 0x75, 0xE6, 0xC6, 0x27, 0xD3, 0xA3, 0xA6, 0xE1, 0x46, 0xE1, 0x68, 0x38, 0xF0, + 0xEE, 0xAB, 0xFA, 0xF4, 0x97, 0x8B, 0x2F, 0x1E, 0x2A, 0x49, 0x45, 0x8B, 0xB3, 0x07, 0x70, 0xAF, 0xEA, 0x34, 0xE4, 0xD6, + 0x92, 0x15, 0x60, 0x8F, 0xB6, 0x26, 0x61, 0x04, 0xD3, 0x7A, 0xE5, 0x23, 0x75, 0x63, 0x65, 0x61, 0x94, 0x06, 0xC1, 0x9F, + 0x3F, 0xE7, 0x28, 0x1B, 0x5F, 0x10, 0x17, 0xB3, 0xC7, 0x82, 0xF1, 0xAE, 0xB7, 0x65, 0xA2, 0x81, 0xE2, 0xB6, 0x83, 0x77, + 0x41, 0x6D, 0x0E, 0x7F, 0x6B, 0x97, 0x42, 0xCD, 0xA3, 0x69, 0x6C, 0x2F, 0xBD, 0x47, 0xA8, 0xDC, 0x13, 0x59, 0x42, 0x8A, + 0xE0, 0x58, 0x4D, 0xA8, 0xE1, 0x6D, 0xD3, 0x08, 0x41, 0xB6, 0x2A, 0x15, 0xEA, 0xD4, 0x7B, 0x0B, 0x7F, 0x0C, 0xB9, 0xE6, + 0x21, 0x68, 0xA7, 0x56, 0x6B, 0xE7, 0xEA, 0x4B, 0x23, 0xE1, 0x73, 0x9B, 0x88, 0xEC, 0xF0, 0x76, 0x9F, 0xD9, 0x21, 0x9C, + 0x3E, 0xB6, 0x63, 0xCD, 0xE9, 0x5A, 0x50, 0x07, 0xE1, 0x48, 0xC6, 0x8B, 0xE7, 0x8D, 0x2C, 0x6E, 0x29, 0x69, 0xDC, 0x84, + 0xC6, 0xA1, 0xEE, 0x7C, 0x68, 0x78, 0x9C, 0xF1, 0xF0, 0x5E, 0xCA, 0x86, 0xE7, 0x40, 0xC8, 0x49, 0xE8, 0x20, 0x79, 0xF9, + 0x07, 0xA1, 0x90, 0xBE, 0xE8, 0xF3, 0x80, 0x9A, 0x46, 0x43, 0x2C, 0x2A, 0x2F, 0x98, 0x5D, 0x75, 0x60, 0x4B, 0x5B, 0xAD, + 0x3B, 0x8E, 0xB7, 0xE2, 0x3A, 0xC6, 0xA4, 0x8D, 0xB7, 0xBE, 0xFB, 0x76, 0x26, 0xE8, 0xDE, 0x7B, 0x93, 0x55, 0x99, 0x32, + 0x9D, 0xD1, 0x23, 0x88, 0x84, 0x41, 0x32, 0xBD, 0x82, 0x17, 0xF6, 0x64, 0x95, 0x00, 0xF9, 0x4E, 0x94, 0x5D, 0xA1, 0xC4, + 0x2D, 0x78, 0xC2, 0x03, 0xA3, 0xB4, 0xFD, 0xF6, 0x80, 0x39, 0x0D, 0x5E, 0x15, 0xD1, 0x55, 0xFD, 0x5D, 0x42, 0x45, 0x03, + 0x02, 0x15, 0xF4, 0xE7, 0x16, 0x16, 0x25, 0xCE, 0x60, 0x5E, 0x1D, 0x96, 0xB7, 0x32, 0xC4, 0xE4, 0x87, 0x95, 0x10, 0x3E, + 0x52, 0xD5, 0x15, 0x86, 0x03, 0x50, 0xB6, 0xE5, 0x73, 0xA4, 0x1E, 0xD0, 0x84, 0x54, 0xAC, 0xCF, 0x30, 0x3A, 0x5E, 0x9D, + 0xE1, 0xA2, 0x6C, 0x61, 0x92, 0x16, 0x75, 0x27, 0xB0, 0x5B, 0xBC, 0xA3, 0x3F, 0x54, 0x33, 0x03, 0xC6, 0x14, 0x8F, 0xE4, + 0x20, 0xE9, 0x33, 0xD7, 0x4A, 0x18, 0x94, 0xDA, 0x56, 0xE8, 0xA2, 0x93, 0x14, 0x32, 0xC6, 0x15, 0xB3, 0x47, 0x0E, 0xC0, + 0x4B, 0x38, 0x28, 0xE7, 0x3E, 0xCA, 0xD6, 0xE5, 0x7D, 0xF5, 0xC8, 0x4E, 0x7C, 0xD5, 0x8E, 0xBB, 0x27, 0x18, 0x49, 0x14, + 0xD2, 0x5D, 0x76, 0xDA, 0x96, 0x57, 0xE0, 0xBA, 0x90, 0x76, 0x7F, 0xAD, 0x88, 0xD9, 0x05, 0x72, 0x01, 0x78, 0xDE, 0x46, + 0xDF, 0x5A, 0x06, 0x9F, 0x98, 0x46, 0x5E, 0x9D, 0x01, 0x79, 0xB7, 0x6E, 0x81, 0x5E, 0x27, 0x47, 0xEF, 0x71, 0xCD, 0x8A, + 0x12, 0x1F, 0x14, 0xFF, 0xC1, 0x78, 0x2A, 0x5E, 0x32, 0x34, 0x6E, 0x07, 0xFF, 0x81, 0xF6, 0xED, 0x62, 0xAC, 0x36, 0xFC, + 0xC0, 0x59, 0xB6, 0xA6, 0x1A, 0xBD, 0xCE, 0x12, 0xD6, 0xAC, 0x8A, 0xE7, 0x5D, 0x3F, 0xFC, 0x2B, 0x06, 0xE3, 0x53, 0xAF, + 0xFB, 0x36, 0xFE, 0x9B, 0x51, 0x41, 0xF7, 0xDF, 0xDE, 0xEA, 0x75, 0x69, 0x2E, 0xB0, 0xF7, 0x8D, 0x3B, 0x30, 0xA0, 0x97, + 0x9D, 0x80, 0x90, 0xD3, 0x84, 0x7E, 0x1A, 0xE0, 0x86, 0x88, 0x2C, 0x39, 0x90, 0x0F, 0x26, 0x0B, 0xAF, 0xF1, 0x70, 0xBB, + 0xEA, 0x6D, 0xEC, 0x70, 0x46, 0x7F, 0xE6, 0x3F, 0xA6, 0xEC, 0x29, 0x23, 0x35, 0xC5, 0x5D, 0xB2, 0x0B, 0x50, 0xD4, 0xE1, + 0x06, 0x8A, 0x34, 0x18, 0xE4, 0x29, 0x8A, 0x92, 0xF4, 0x6D, 0xC9, 0x4C, 0xD2, 0x10, 0x51, 0x71, 0xC6, 0x74, 0xF1, 0x32, + 0x93, 0x51, 0x4A, 0x41, 0x2E, 0xD2, 0x84, 0xB3, 0x8B, 0xE8, 0x5A, 0xF2, 0xEA, 0x2B, 0xF3, 0xB5, 0x92, 0x2F, 0x50, 0x88, + 0xB3, 0x4D, 0x89, 0x00, 0xDB, 0x52, 0x7E, 0x7A, 0xEC, 0xC1, 0x4C, 0x72, 0xB6, 0xBA, 0x50, 0x63, 0xE6, 0x5A, 0xC3, 0x96, + 0x1F, 0x6E, 0xC5, 0x67, 0xE5, 0x5E, 0x50, 0xF6, 0xAA, 0x09, 0x51, 0xE9, 0xE2, 0xC0, 0x41, 0x10, 0xD8, 0x59, 0x53, 0xE3, + 0x02, 0x28, 0x5D, 0x35, 0x2C, 0xC2, 0xCD, 0x11, 0x3C, 0xA2, 0xB1, 0x5E, 0x57, 0x47, 0x5A, 0x88, 0x05, 0xEC, 0x0E, 0xFC, + 0x3F, 0xE8, 0x4C, 0x03, 0xA7, 0x99, 0x8C, 0x07, 0xFF, 0x8D, 0x74, 0x0D, 0x05, 0x8F, 0x9E, 0x49, 0x76, 0xB8, 0x04, 0x02, + 0xC0, 0x6F, 0x39, 0xBA, 0x0C, 0x84, 0x1B, 0xDB, 0x63, 0x85, 0x18, 0xFD, 0xBF, 0xEA, 0x4D, 0x06, 0x27, 0x5B, 0x8D, 0x03, + 0x7F, 0xEE, 0x63, 0x89, 0x2C, 0x0C, 0x2F, 0x9B, 0xC3, 0x82, 0x76, 0xFB, 0x84, 0x89, 0x8C, 0x07, 0x2D, 0x9A, 0xC6, 0x6E, + 0xAF, 0x13, 0xDA, 0xA0, 0xB2, 0xA1, 0x4A, 0x94, 0xE2, 0xC1, 0xCC, 0x07, 0x66, 0x6D, 0x25, 0xA7, 0x80, 0x70, 0x7C, 0x38, + 0x11, 0xEB, 0x1C, 0xBE, 0xA6, 0xE7, 0xA8, 0x65, 0xB4, 0x89, 0xD7, 0x29, 0x75, 0xCC, 0x1E, 0x25, 0xBA, 0xB5, 0x8C, 0x4F, + 0x41, 0x83, 0xBB, 0x9C, 0x5A, 0x63, 0x09, 0x5B, 0x7A, 0x09, 0x2D, 0x79, 0xD1, 0x22, 0x61, 0x79, 0x24, 0xC0, 0xC4, 0x9D, + 0x22, 0x81, 0x7A, 0xAA, 0x24, 0x34, 0x9C, 0x75, 0x00, 0x04, 0x49, 0x9D, 0x73, 0x0B, 0x8C, 0x58, 0xD8, 0xFD, 0x3F, 0xE1, + 0x55, 0xFD, 0x55, 0xB1, 0x94, 0x3E, 0x43, 0xCC, 0x4B, 0x4E, 0xC4, 0xA2, 0x95, 0x70, 0xEC, 0xAA, 0x45, 0x3D, 0x05, 0x9D, + 0x38, 0xBF, 0x35, 0xDC, 0x84, 0xF2, 0x4A, 0xD4, 0xCC, 0x59, 0x4B, 0x5A, 0xA6, 0x20, 0xF5, 0x93, 0x00, 0x3C, 0x02, 0x82, + 0xDD, 0x7C, 0xE1, 0x44, 0x71, 0x7E, 0xC0, 0xA0, 0x02, 0xD9, 0x48, 0x36, 0x3E, 0x22, 0x49, 0x5B, 0x9D, 0xC9, 0x34, 0xE7, + 0xBC, 0x01, 0x32, 0x30, 0x23, 0x38, 0x40, 0x53, 0xC8, 0x3E, 0xE1, 0x42, 0x98, 0x0A, 0x4B, 0x52, 0x71, 0x4F, 0x9E, 0xCB, + 0x03, 0x69, 0xF7, 0xF2, 0x05, 0xFB, 0x26, 0x19, 0xE2, 0x56, 0xA1, 0x63, 0xFE, 0x80, 0x3F, 0xE1, 0x83, 0xDA, 0xA5, 0xE6, + 0x8E, 0x18, 0xC5, 0x09, 0xF7, 0x9A, 0x0B, 0x73, 0xA4, 0xDF, 0xE6, 0xC7, 0xEE, 0x13, 0xFE, 0xDB, 0x57, 0xA9, 0x23, 0xD0, + 0x06, 0xC9, 0xE4, 0xE9, 0x97, 0x9C, 0x74, 0x15, 0x5B, 0x36, 0x15, 0x7C, 0x91, 0x44, 0xAB, 0x49, 0x51, 0x04, 0x80, 0x92, + 0x9D, 0x78, 0x3F, 0xB6, 0x47, 0xDE, 0x23, 0x0B, 0xE2, 0x93, 0x49, 0x83, 0x11, 0x7B, 0x27, 0x5E, 0x5F, 0xBA, 0x8B, 0xF9, + 0x5A, 0xFE, 0xD7, 0x8C, 0xCD, 0xFF, 0x69, 0x97, 0x06, 0x8A, 0x01, 0x4C, 0x79, 0x56, 0x74, 0xCA, 0xD5, 0x8E, 0x46, 0xBC, + 0x5C, 0x08, 0x09, 0xAD, 0x93, 0x6A, 0xAD, 0x7E, 0x9F, 0x43, 0x53, 0xFE, 0xC4, 0xF9, 0xB3, 0xDF, 0x0C, 0x6F, 0x86, 0xDE, + 0x0C, 0xAB, 0xB7, 0x37, 0xAC, 0x32, 0xDF, 0x7B, 0x55, 0x01, 0x99, 0xC8, 0x43, 0xB1, 0x8F, 0x95, 0x3C, 0xCC, 0x08, 0x13, + 0x21, 0xBC, 0x57, 0x21, 0x03, 0x92, 0x57, 0x30, 0x56, 0x86, 0x69, 0x2B, 0x04, 0x9B, 0x7F, 0x22, 0x5A, 0xFF, 0xA3, 0xA8, + 0xDC, 0x33, 0x78, 0x0C, 0xE9, 0x6F, 0x28, 0xCE, 0xC3, 0x4D, 0x69, 0x5F, 0xCA, 0x5F, 0xFA, 0xD0, 0x17, 0x07, 0xA8, 0x09, + 0x9C, 0x3A, 0x30, 0x21, 0x47, 0x92, 0x0D, 0x0B, 0x21, 0xEC, 0x58, 0x83, 0x86, 0xD1, 0xD8, 0xAF, 0x6D, 0x6D, 0x6C, 0xE3, + 0x61, 0x44, 0xAA, 0xAF, 0x63, 0xB7, 0xA1, 0x05, 0x20, 0xFC, 0xA5, 0x73, 0x4B, 0x31, 0x74, 0xB3, 0x40, 0x43, 0xE2, 0xCE, + 0x5E, 0x21, 0xE4, 0x64, 0x31, 0x50, 0x92, 0x47, 0x14, 0x6C, 0xF0, 0x12, 0x28, 0x20, 0xE8, 0xE6, 0x70, 0x94, 0x11, 0x70, + 0xA6, 0xDA, 0x68, 0x26, 0x71, 0x01, 0xA7, 0x0A, 0x45, 0xB7, 0xE0, 0xA4, 0x0F, 0x9A, 0xFB, 0xD2, 0xEF, 0xF9, 0xD3, 0x75, + 0x33, 0x89, 0x91, 0xFC, 0xD5, 0xB7, 0xA9, 0xE7, 0x52, 0xDF, 0xE5, 0x2E, 0x55, 0x46, 0x09, 0x11, 0x91, 0x65, 0xE5, 0x6F, + 0xA1, 0xB3, 0x75, 0xE7, 0xDF, 0x6F, 0x1A, 0x8D, 0xE1, 0x3B, 0x3A, 0x96, 0x1B, 0x88, 0x2A, 0x19, 0x72, 0x47, 0x90, 0x34, + 0x59, 0xC8, 0x2A, 0x09, 0xDC, 0x65, 0x72, 0x01, 0x99, 0xEF, 0x4C, 0x90, 0xEA, 0x08, 0x0A, 0xB8, 0x69, 0xEE, 0x2A, 0x76, + 0x19, 0x1A, 0xB8, 0xEB, 0x88, 0x97, 0x73, 0x96, 0x37, 0x47, 0x83, 0x1C, 0xDC, 0x04, 0xCF, 0x47, 0x87, 0x15, 0xEB, 0x1F, + 0xCC, 0x26, 0x21, 0xD1, 0x27, 0x04, 0xA2, 0x7F, 0x78, 0x70, 0x3C, 0x4F, 0xAB, 0x93, 0xC9, 0x08, 0xF3, 0x44, 0x04, 0x1B, + 0x6C, 0xCD, 0x52, 0x91, 0x56, 0x91, 0x14, 0xBA, 0x57, 0x89, 0xB1, 0x7B, 0xBA, 0x41, 0x0C, 0xD9, 0xA0, 0x29, 0x1F, 0x9E, + 0xD9, 0xB9, 0xF7, 0x2B, 0x71, 0x4F, 0x03, 0x0C, 0x11, 0x23, 0x51, 0x9A, 0x4E, 0xC3, 0xC1, 0x69, 0x58, 0x6D, 0xB1, 0x2A, + 0xFF, 0xA4, 0x2C, 0x27, 0x4D, 0x25, 0xE2, 0x9B, 0x67, 0x32, 0x04, 0x1F, 0x9B, 0x60, 0xB3, 0x89, 0xD3, 0xAF, 0x2C, 0x90, + 0x91, 0xCF, 0xB0, 0xDF, 0x66, 0x28, 0x90, 0x64, 0x34, 0x6B, 0x64, 0xF2, 0x9E, 0x1F, 0xA5, 0xEB, 0xA0, 0x21, 0x24, 0x4B, + 0xEE, 0xF7, 0x1C, 0x73, 0x55, 0x1D, 0xFE, 0x05, 0xA4, 0x2C, 0xDF, 0x4D, 0xC7, 0x72, 0x89, 0xC3, 0x13, 0x37, 0x59, 0xC3, + 0x12, 0x52, 0x35, 0x7F, 0x22, 0x1E, 0xAD, 0x84, 0x3C, 0x50, 0x08, 0xCB, 0x2B, 0x42, 0x0D, 0xC6, 0x89, 0xD2, 0x6C, 0x33, + 0xAE, 0x55, 0x04, 0x80, 0x30, 0x76, 0x94, 0xE1, 0xEB, 0x08, 0xAC, 0xF6, 0x8D, 0xA9, 0x4D, 0xB6, 0xFE, 0x1A, 0x15, 0xCA, + 0x08, 0x45, 0xF1, 0xCF, 0x4D, 0x8E, 0xCA, 0x96, 0x07, 0x8A, 0x1C, 0xD8, 0x07, 0xE9, 0xCE, 0x81, 0x8D, 0x16, 0xEE, 0xAF, + 0x7F, 0xAB, 0x9F, 0xE4, 0x05, 0x8B, 0xF9, 0xAE, 0x00, 0x56, 0x0D, 0x91, 0x91, 0x75, 0x5D, 0xCB, 0x9F, 0xE2, 0x84, 0x6C, + 0x56, 0xD6, 0x7B, 0x4A, 0x89, 0x1E, 0x2D, 0x29, 0xED, 0x26, 0x1E, 0x3D, 0x5B, 0x33, 0x01, 0x9D, 0xD9, 0xF9, 0x63, 0x1A, + 0xA8, 0xB9, 0x1B, 0x74, 0xA0, 0x7B, 0x20, 0x91, 0xCE, 0x42, 0xCC, 0xA7, 0x92, 0x1D, 0x2F, 0x88, 0xAE, 0xC9, 0xFA, 0x7E, + 0xC8, 0xEE, 0x29, 0x81, 0x4F, 0x4A, 0xAA, 0x5E, 0x7C, 0xF7, 0xCF, 0x24, 0x9D, 0x17, 0x9E, 0x00, 0xBF, 0x2A, 0xE9, 0xDF, + 0xF9, 0x14, 0x0F, 0x55, 0x69, 0xB6, 0x26, 0x68, 0x3A, 0x97, 0x46, 0x3C, 0xC1, 0x52, 0x06, 0x6C, 0x62, 0x70, 0xEE, 0x12, + 0x87, 0xA8, 0xCD, 0x3A, 0x0F, 0xC9, 0xB6, 0x9C, 0x23, 0x7F, 0x9E, 0x65, 0xC6, 0x1F, 0xC8, 0x9E, 0x13, 0x70, 0x43, 0x2B, + 0x28, 0x1D, 0x78, 0x56, 0x4F, 0x98, 0xEA, 0xD4, 0x15, 0x03, 0xAF, 0xFF, 0x13, 0x71, 0xD8, 0xC6, 0x89, 0x8B, 0x47, 0x7D, + 0x4E, 0xCB, 0x98, 0x5A, 0x1E, 0x50, 0xCD, 0xC6, 0x10, 0x3B, 0x5D, 0xF1, 0x3E, 0x54, 0x64, 0x83, 0x57, 0x53, 0x4E, 0x0A, + 0xAF, 0xF1, 0xDF, 0xA2, 0x64, 0x12, 0xE8, 0xAF, 0x31, 0x8D, 0x74, 0x70, 0xEA, 0xB1, 0xC0, 0xDA, 0xF7, 0x8E, 0x07, 0xB2, + 0x65, 0x68, 0x70, 0x81, 0x05, 0xA2, 0xB1, 0x65, 0xCC, 0xB9, 0x68, 0xC6, 0x63, 0xD2, 0xD9, 0x45, 0x67, 0x8E, 0x11, 0x78, + 0x04, 0x8E, 0x11, 0xFF, 0x14, 0x5F, 0x60, 0x71, 0x62, 0xD3, 0xF1, 0x2B, 0xE6, 0x5D, 0x18, 0x5F, 0xC6, 0xC5, 0x61, 0x35, + 0x1B, 0xE6, 0x08, 0xE6, 0x18, 0xE3, 0xC8, 0x98, 0xA9, 0xFF, 0xDC, 0x30, 0xF8, 0x28, 0x5C, 0x29, 0xB4, 0x08, 0xB8, 0xEF, + 0xED, 0xA0, 0xE0, 0x52, 0x64, 0x57, 0x1F, 0x44, 0x27, 0x59, 0xED, 0x84, 0x63, 0xA9, 0x49, 0x9C, 0x6A, 0xCB, 0xD7, 0x11, + 0x2D, 0x69, 0x63, 0x62, 0x26, 0xC6, 0xE3, 0x66, 0x36, 0x26, 0xCD, 0x2C, 0x64, 0xA2, 0x41, 0x8D, 0x3E, 0xBD, 0x9B, 0x48, + 0xAD, 0xF5, 0x5A, 0x06, 0xE1, 0xE7, 0xCA, 0xD5, 0x7F, 0xEF, 0x72, 0x06, 0x3A, 0xAA, 0x9D, 0xB3, 0x90, 0x74, 0xF4, 0x26, + 0x0E, 0x04, 0xD9, 0xFA, 0x64, 0x6D, 0xAB, 0x4E, 0x5C, 0x19, 0x0B, 0x69, 0x78, 0x99, 0x33, 0xFE, 0xA0, 0xEA, 0x8B, 0xD5, + 0x31, 0xA6, 0xA2, 0xC3, 0x51, 0xA8, 0x86, 0x9F, 0xFB, 0xC5, 0x24, 0xFF, 0x8B, 0xAD, 0xBC, 0x3D, 0x05, 0x1B, 0x85, 0xFA, + 0x52, 0x6D, 0x3C, 0xA8, 0x0A, 0x21, 0xE2, 0xBD, 0x9A, 0x21, 0xCD, 0x88, 0xC3, 0x47, 0xD1, 0x8C, 0x9E, 0x13, 0x4C, 0xB8, + 0x83, 0xCC, 0xF8, 0x6E, 0x3F, 0x02, 0x40, 0xE8, 0x4F, 0x12, 0xD8, 0x0D, 0xFC, 0xE4, 0xEF, 0x79, 0x65, 0xCA, 0xB1, 0x49, + 0x98, 0xE6, 0xF7, 0xF8, 0xE0, 0x31, 0xCD, 0xA3, 0x0E, 0xE1, 0x15, 0x5D, 0x6E, 0x0C, 0x4B, 0x2D, 0xFD, 0xEB, 0x48, 0xCB, + 0x37, 0x6C, 0xFF, 0x62, 0x26, 0x1B, 0x1C, 0xE9, 0xA5, 0x9D, 0xD6, 0xC1, 0x32, 0x30, 0x17, 0x8A, 0xBC, 0xE1, 0xA6, 0x02, + 0x9F, 0xB4, 0x04, 0xF0, 0xD1, 0x82, 0x84, 0x07, 0x94, 0xAE, 0x6C, 0x5A, 0x4A, 0x9C, 0x18, 0x92, 0x16, 0xF5, 0x9C, 0xC1, + 0x05, 0xEF, 0xA6, 0x47, 0x92, 0xB4, 0x74, 0xDC, 0x43, 0xD6, 0x8F, 0x17, 0x20, 0x5D, 0x9A, 0x3A, 0x38, 0x6E, 0x19, 0xB0, + 0x19, 0xAE, 0xC4, 0xBB, 0x40, 0xAC, 0xAB, 0x8F, 0x1E, 0xB7, 0x30, 0xD9, 0x00, 0xE0, 0x9C, 0x42, 0x32, 0x21, 0xC0, 0x9D, + 0xC5, 0x01, 0xCE, 0x56, 0xAE, 0xB6, 0xAC, 0x4F, 0x9F, 0xD7, 0x40, 0x44, 0x6B, 0xBF, 0x46, 0x01, 0x6A, 0x71, 0x07, 0xD1, + 0xD6, 0x0A, 0xB1, 0x47, 0xF8, 0xB1, 0xE3, 0x82, 0x5F, 0xDE, 0x27, 0xDC, 0x8C, 0x97, 0x7D, 0x67, 0x5A, 0xFB, 0xAA, 0x70, + 0x06, 0x48, 0x6D, 0x96, 0x0A, 0xF6, 0xF1, 0xA3, 0xC5, 0x67, 0x9D, 0x53, 0xB6, 0xB5, 0x8B, 0x0E, 0x5A, 0xD6, 0x8E, 0xEC, + 0x0F, 0x84, 0x9A, 0x31, 0xD9, 0x4E, 0x8C, 0x1E, 0xA8, 0x57, 0xD5, 0x1E, 0x29, 0xA7, 0x96, 0x74, 0xB0, 0x44, 0x87, 0x5C, + 0x7D, 0xA4, 0xA8, 0x1E, 0x96, 0xBD, 0x90, 0x83, 0x5F, 0x25, 0x67, 0xA7, 0xE2, 0xB4, 0x7F, 0x3B, 0xDF, 0xD6, 0x13, 0x8B, + 0x9F, 0x33, 0x47, 0xF9, 0x12, 0x95, 0x4A, 0x70, 0x48, 0xED, 0xC7, 0x53, 0xC2, 0x46, 0x85, 0x0F, 0x53, 0x54, 0xD2, 0xA8, + 0x12, 0x63, 0x26, 0x8A, 0x3D, 0xFE, 0xF4, 0x1A, 0x6F, 0x7D, 0xF4, 0x83, 0x7A, 0x26, 0xCE, 0xC0, 0xA3, 0x30, 0xBE, 0xD7, + 0x9C, 0xA6, 0x74, 0xCB, 0xCE, 0x5C, 0xC0, 0xD7, 0xF2, 0x5B, 0xDC, 0x67, 0x59, 0x2A, 0xEB, 0x14, 0x1F, 0xB8, 0x7D, 0x18, + 0xAF, 0x73, 0x80, 0x9D, 0x15, 0xCF, 0xCF, 0xEB, 0xEF, 0x30, 0x4D, 0x5B, 0xB6, 0x41, 0x57, 0x08, 0x6B, 0x52, 0xB7, 0x3F, + 0xCC, 0x74, 0xE5, 0x31, 0x38, 0x42, 0x40, 0xDC, 0x9A, 0xFB, 0xCE, 0xC8, 0x4F, 0x0D, 0x81, 0x57, 0x60, 0x0C, 0x52, 0x3F, + 0x69, 0x30, 0xD9, 0x7B, 0x22, 0x4F, 0x41, 0xD8, 0xD5, 0x0C, 0xC2, 0xCE, 0x39, 0x70, 0xD2, 0xCD, 0xA1, 0x7B, 0x37, 0xF8, + 0xB1, 0x60, 0x49, 0xC5, 0xC6, 0x3A, 0xF7, 0xEC, 0xD3, 0x1B, 0xC9, 0xAD, 0xD7, 0x0E, 0x31, 0x52, 0x53, 0x21, 0x8E, 0xB9, + 0x64, 0x90, 0xE7, 0x33, 0x30, 0xE0, 0xF4, 0x3B, 0xA1, 0x1F, 0x99, 0xCC, 0xFB, 0xB5, 0xAF, 0x0E, 0x20, 0x9B, 0x10, 0x65, + 0x43, 0xC9, 0x88, 0x48, 0xE1, 0x1E, 0xB0, 0xBC, 0x09, 0x88, 0xB4, 0x0B, 0x81, 0x99, 0xE6, 0x5C, 0x7D, 0xBA, 0x0D, 0xC3, + 0x0F, 0xBF, 0x39, 0xC7, 0xB0, 0x16, 0x7E, 0x1E, 0x1B, 0xD9, 0xC4, 0x54, 0x73, 0x99, 0x42, 0xD3, 0x0E, 0xED, 0xDE, 0xB3, + 0x11, 0x24, 0x62, 0xE3, 0xC3, 0x4F, 0x83, 0xAD, 0xAF, 0xC8, 0x78, 0xE8, 0x29, 0xA7, 0xCA, 0x95, 0xBD, 0xA8, 0x42, 0x5F, + 0x14, 0x53, 0x31, 0xDF, 0xD4, 0x65, 0x6C, 0xD8, 0x0A, 0xE3, 0xD3, 0x47, 0x1F, 0x38, 0xE2, 0x5E, 0xC6, 0xCF, 0xC4, 0xDE, + 0x5D, 0xEC, 0x92, 0x7A, 0xBC, 0x66, 0x7B, 0x8F, 0x19, 0x18, 0xE0, 0x4F, 0xA0, 0x63, 0xCB, 0x19, 0x31, 0x30, 0x35, 0x30, + 0xE0, 0x5A, 0x1E, 0x62, 0xA5, 0xD4, 0x1D, 0x79, 0xD2, 0x07, 0x66, 0x13, 0x7A, 0x29, 0x82, 0x50, 0xE8, 0x0A, 0x45, 0xAE, + 0x29, 0x9C, 0x17, 0x13, 0x2A, 0x0F, 0x72, 0x9C, 0x86, 0xBF, 0x00, 0x45, 0xB4, 0x4F, 0x35, 0xD8, 0x04, 0x99, 0xA1, 0xFA, + 0xC3, 0xCF, 0x6E, 0x1E, 0x68, 0x53, 0x63, 0x6B, 0x2B, 0x82, 0x7B, 0xB3, 0x8A, 0x63, 0xAC, 0x13, 0xA8, 0xB1, 0xAD, 0x6A, + 0x7B, 0x91, 0x48, 0xE7, 0x8D, 0x2F, 0xAB, 0x5F, 0xE0, 0x22, 0x63, 0x82, 0xB8, 0x4F, 0x74, 0x9B, 0xCB, 0x92, 0xC4, 0xF4, + 0xB2, 0xE5, 0x20, 0x84, 0x30, 0x30, 0xAC, 0x4F, 0x1C, 0x0D, 0xF2, 0x68, 0x73, 0x01, 0x56, 0xBF, 0x49, 0x40, 0x74, 0x16, + 0xB0, 0x93, 0x45, 0x0F, 0xC4, 0xF0, 0xE2, 0xB2, 0x12, 0x24, 0x94, 0x05, 0xBB, 0xE7, 0x85, 0xF7, 0x83, 0x5C, 0xC6, 0x01, + 0x0D, 0xA2, 0xCF, 0x87, 0x98, 0x23, 0xCD, 0x2D, 0xF7, 0x1E, 0xD4, 0x4E, 0xB7, 0x22, 0x01, 0x57, 0x44, 0x3D, 0xCB, 0x9C, + 0x1A, 0x17, 0xEF, 0x45, 0xB1, 0x2B, 0xAB, 0x40, 0x69, 0xBA, 0x6C, 0x1F, 0x15, 0x54, 0x2C, 0xEC, 0xD5, 0x38, 0x4F, 0x83, + 0xFE, 0x68, 0x17, 0x97, 0x4C, 0x36, 0xE1, 0xAB, 0x65, 0xA6, 0xD8, 0xF5, 0x7B, 0x55, 0x25, 0x87, 0xDA, 0x54, 0x8D, 0xC1, + 0x37, 0x35, 0x7E, 0x8F, 0x33, 0xEA, 0x44, 0xC1, 0xFA, 0x76, 0xE2, 0xBE, 0xA5, 0x87, 0x78, 0x1C, 0x52, 0x88, 0xDF, 0x09, + 0xE3, 0x15, 0x22, 0xF4, 0xF3, 0x77, 0xF9, 0x7A, 0x09, 0x6A, 0x13, 0x4B, 0x3E, 0xB8, 0x74, 0x34, 0x69, 0xD9, 0xAE, 0x4C, + 0x72, 0x3A, 0x27, 0xE7, 0xB8, 0x09, 0x9F, 0x70, 0xC6, 0x22, 0x93, 0x50, 0x1A, 0x59, 0x09, 0x4F, 0xFD, 0xF2, 0x5D, 0x88, + 0xDF, 0x1A, 0x84, 0xCD, 0xA0, 0x78, 0xBF, 0x18, 0xCC, 0x18, 0x5C, 0x24, 0x9B, 0x73, 0x2F, 0x88, 0x24, 0x78, 0xE0, 0x19, + 0xF9, 0xD0, 0x40, 0xBD, 0xEF, 0x1B, 0xAB, 0x01, 0x12, 0x1F, 0xB5, 0x20, 0x7B, 0x5E, 0x46, 0x11, 0x78, 0x27, 0x52, 0x2F, + 0x97, 0xFD, 0xD6, 0xED, 0x72, 0x83, 0xCE, 0x86, 0xA6, 0x7F, 0xCF, 0xBA, 0xD0, 0x0C, 0x08, 0x55, 0x80, 0x2E, 0x21, 0x03, + 0x7B, 0x7D, 0xC2, 0x49, 0x57, 0x05, 0xF9, 0xAB, 0x51, 0x2F, 0x04, 0x1A, 0x98, 0x83, 0xD3, 0x12, 0xF2, 0x1E, 0xE4, 0x5C, + 0x38, 0x20, 0xD9, 0xBF, 0x44, 0x92, 0xA4, 0xC6, 0x99, 0x1E, 0x20, 0xFD, 0x04, 0x80, 0x38, 0x5B, 0x67, 0xF6, 0x1B, 0xAA, + 0xE3, 0x1D, 0x66, 0x06, 0x37, 0xC0, 0x7B, 0xAF, 0xA9, 0x61, 0xE1, 0x72, 0x44, 0x34, 0xD3, 0x94, 0x94, 0x93, 0x29, 0xF5, + 0x76, 0x55, 0x8C, 0xC8, 0xB4, 0x5E, 0x37, 0x2F, 0x82, 0x51, 0xF4, 0xFC, 0x65, 0xB1, 0x6E, 0x33, 0xC2, 0x82, 0xA9, 0xD8, + 0x21, 0x61, 0xB8, 0x2C, 0xBD, 0xC1, 0x29, 0x07, 0xA8, 0xA5, 0x81, 0xAC, 0x30, 0x4A, 0x79, 0xE3, 0x96, 0x4E, 0x4C, 0x3D, + 0x35, 0xC4, 0xF0, 0x35, 0x02, 0x5F, 0xB0, 0xDF, 0x02, 0x86, 0x08, 0x9A, 0x8A, 0x1F, 0xAC, 0x98, 0xBC, 0x83, 0x37, 0x52, + 0x11, 0x5F, 0x27, 0x2C, 0xC5, 0xE1, 0x78, 0x8D, 0xB6, 0x46, 0xCA, 0x04, 0x88, 0x5A, 0x61, 0xC3, 0xFA, 0xF9, 0xA6, 0x7E, + 0xB5, 0xC6, 0xBA, 0x14, 0xEE, 0x67, 0xC5, 0x82, 0x81, 0x17, 0x81, 0xD3, 0x85, 0xA7, 0x3F, 0x11, 0x38, 0x1C, 0xE8, 0x8D, + 0xD1, 0x4D, 0x39, 0xC4, 0x83, 0x93, 0x8A, 0x87, 0x1A, 0xB9, 0x12, 0xD9, 0xEF, 0xDA, 0x7B, 0x1F, 0x68, 0x47, 0x92, 0x84, + 0x0C, 0xEA, 0x6A, 0x0E, 0x47, 0xEB, 0x42, 0xFA, 0x15, 0xD2, 0xC4, 0x17, 0xDD, 0x8A, 0x83, 0x6D, 0x52, 0x98, 0xFC, 0xF0, + 0xAF, 0x2A, 0x8B, 0x5B, 0x4C, 0x6C, 0x22, 0x5D, 0xB6, 0xDB, 0x1C, 0x32, 0x71, 0xDA, 0xBA, 0x65, 0x9B, 0x2B, 0x1E, 0x5D, + 0x7A, 0xDB, 0x81, 0xC4, 0x24, 0x87, 0x4C, 0x25, 0x08, 0x1C, 0x82, 0x4C, 0x3C, 0xEE, 0x72, 0xEE, 0x30, 0x0C, 0x3A, 0x11, + 0x0B, 0xE7, 0xEF, 0xDA, 0xF2, 0x96, 0xF9, 0xBC, 0xB3, 0x00, 0xFD, 0x96, 0x4B, 0xB6, 0xF2, 0x73, 0xD8, 0xBC, 0x90, 0xA3, + 0x85, 0xCC, 0x6B, 0x1F, 0x32, 0x03, 0x28, 0x6B, 0xC8, 0x3D, 0xF2, 0xEB, 0xE6, 0x0E, 0xEB, 0x05, 0x02, 0xED, 0xFC, 0xBD, + 0x99, 0xB5, 0x7B, 0xF9, 0x31, 0x50, 0x6B, 0x0D, 0xEC, 0xD1, 0x8F, 0x27, 0xF1, 0x8E, 0x64, 0xC7, 0x5E, 0xBA, 0x25, 0xE5, + 0x57, 0x44, 0x8E, 0x44, 0xD8, 0xFF, 0x96, 0xCE, 0xC2, 0x81, 0xAE, 0x70, 0x90, 0x17, 0x84, 0x3C, 0x96, 0xBD, 0xE4, 0xB2, + 0x3D, 0xC0, 0x58, 0x7C, 0x97, 0x96, 0xE5, 0x6F, 0x19, 0xFF, 0x8D, 0x2C, 0x1F, 0xC0, 0xB3, 0x8B, 0x1D, 0xA3, 0x97, 0xCE, + 0x42, 0x33, 0x3C, 0xD7, 0xA1, 0x18, 0x02, 0x37, 0xF8, 0xD7, 0xBA, 0xB5, 0x28, 0x53, 0x9B, 0x40, 0xA3, 0x24, 0xF5, 0x63, + 0xC1, 0x49, 0xD3, 0xDA, 0x60, 0xAE, 0x0F, 0x19, 0x7E, 0xF4, 0x14, 0xF6, 0xBA, 0x68, 0x3F, 0x28, 0xCA, 0xAE, 0xC3, 0x10, + 0xAF, 0x44, 0xFC, 0xF6, 0x77, 0x55, 0xDE, 0x21, 0x0A, 0x6B, 0xF7, 0xC0, 0x49, 0x3B, 0x73, 0x61, 0x32, 0xF5, 0x0A, 0x18, + 0xF6, 0xD6, 0xC0, 0x9D, 0x52, 0xCB, 0x6B, 0x89, 0x3A, 0xD5, 0x6A, 0x53, 0xED, 0xD5, 0xFD, 0xF7, 0xF7, 0x17, 0xB7, 0x88, + 0x88, 0x38, 0x39, 0x9A, 0xB9, 0x1B, 0x7E, 0xBE, 0x8D, 0xC3, 0xA7, 0xAC, 0xA8, 0xB9, 0x77, 0x21, 0x88, 0x92, 0x56, 0xBA, + 0xDC, 0x16, 0xAE, 0x4B, 0x59, 0xF9, 0xBF, 0xD8, 0x86, 0xFF, 0x32, 0xEA, 0x1F, 0xDB, 0x37, 0xFD, 0x8F, 0xD7, 0xC4, 0x4D, + 0xFC, 0x95, 0xEE, 0xAC, 0x59, 0x65, 0xF2, 0xE8, 0xA2, 0x90, 0xBA, 0x6C, 0x89, 0x14, 0xE4, 0x8C, 0x92, 0xD2, 0x17, 0xB2, + 0x0C, 0xF4, 0x5C, 0x39, 0x10, 0x33, 0x4D, 0x4B, 0xAD, 0x83, 0x2F, 0xCB, 0xCB, 0x7D, 0xF6, 0xEE, 0x7E, 0x5E, 0x6E, 0xB4, + 0xED, 0xDD, 0x90, 0x66, 0x44, 0xBD, 0xF8, 0xEE, 0x93, 0x4C, 0xFE, 0xFE, 0x7F, 0x6C, 0x34, 0x0C, 0x13, 0x18, 0x3E, 0xD0, + 0x81, 0x24, 0x64, 0x18, 0x96, 0xDD, 0xF7, 0xEF, 0xFE, 0x5D, 0x67, 0x66, 0x4E, 0xEE, 0xB4, 0x3D, 0x5E, 0x40, 0x01, 0xC3, + 0x33, 0x6E, 0xFF, 0xFF, 0xF7, 0xE6, 0xDB, 0x02, 0x7F, 0x44, 0x63, 0x17, 0x72, 0xD6, 0xBC, 0x53, 0x2A, 0xC6, 0x9E, 0x96, + 0x73, 0xA0, 0x28, 0xF2, 0x83, 0xD5, 0x08, 0xE7, 0xF5, 0x8E, 0x22, 0xA3, 0x27, 0xBE, 0xB8, 0x24, 0xE5, 0xB6, 0x61, 0x1F, + 0x01, 0x89, 0xFF, 0x9E, 0xFB, 0xB4, 0x13, 0xE1, 0x9A, 0x2E, 0xCB, 0x7F, 0x67, 0x1D, 0x57, 0x62, 0xEC, 0x0C, 0x3F, 0xE4, + 0x79, 0x33, 0x43, 0x21, 0x0B, 0xE0, 0x2C, 0x8A, 0x0C, 0x1E, 0x29, 0xBC, 0x1A, 0x46, 0xD8, 0x37, 0x05, 0xA5, 0x68, 0x8F, + 0xB7, 0x27, 0x37, 0x1A, 0x33, 0x60, 0xBE, 0xA0, 0x0B, 0x0A, 0xB6, 0x68, 0xFA, 0xF4, 0xF3, 0x98, 0x47, 0x99, 0xB9, 0x50, + 0xD1, 0x61, 0x0A, 0x75, 0x00, 0x0E, 0x3A, 0xB6, 0xEE, 0xAB, 0xA8, 0x1A, 0x17, 0xDB, 0xA8, 0x1F, 0xB3, 0x62, 0x29, 0x15, + 0x8C, 0x0A, 0x65, 0xC6, 0x88, 0x2D, 0xF5, 0xF4, 0x16, 0x25, 0x96, 0x17, 0x90, 0x68, 0x5D, 0x09, 0xF1, 0x64, 0xFC, 0x3E, + 0x9D, 0x3E, 0xE9, 0xAC, 0x0D, 0x11, 0x3D, 0x72, 0xED, 0xB4, 0xAD, 0x1E, 0xDD, 0x6D, 0xDF, 0xEF, 0xC1, 0x84, 0x40, 0x28, + 0x9F, 0x96, 0x0A, 0x4F, 0x28, 0xE0, 0x61, 0x1C, 0x8B, 0x62, 0x2F, 0x7E, 0xFE, 0x8C, 0xBF, 0x5B, 0x16, 0xB5, 0xFB, 0xEF, + 0x5E, 0x9F, 0xBF, 0x7B, 0x7A, 0x80, 0xDD, 0x8F, 0x99, 0x84, 0x4B, 0x4E, 0xFB, 0xC6, 0x1F, 0xDD, 0xD8, 0xB0, 0x08, 0xB6, + 0xA9, 0x0A, 0x93, 0x3F, 0x26, 0xAD, 0x3B, 0x83, 0x76, 0xF3, 0xF8, 0xBC, 0x06, 0x2D, 0xFE, 0xBA, 0x89, 0x45, 0x5B, 0xA2, + 0x70, 0x05, 0x85, 0x87, 0x6F, 0xB1, 0x25, 0x0F, 0x6B, 0x0E, 0xCB, 0x29, 0x6B, 0x01, 0xC1, 0xB2, 0x7B, 0x8D, 0xE8, 0xC5, + 0xEB, 0x2E, 0xED, 0x44, 0xB2, 0x63, 0x82, 0xBB, 0x09, 0x47, 0xCB, 0x4E, 0xE7, 0x67, 0x64, 0x26, 0xEF, 0xC2, 0x20, 0x59, + 0xAC, 0x6B, 0xF9, 0xC7, 0xD1, 0x66, 0xC4, 0xBB, 0x38, 0x5C, 0x2A, 0x09, 0x16, 0x8F, 0x71, 0x20, 0x69, 0x7D, 0x72, 0x96, + 0xC0, 0x92, 0x2B, 0x03, 0x5A, 0x97, 0xA7, 0x23, 0x0F, 0x59, 0x9E, 0xD9, 0xF3, 0x7D, 0x7E, 0x71, 0xCB, 0xA3, 0xAD, 0x47, + 0x64, 0xF4, 0xB9, 0xDE, 0x2A, 0x41, 0xF5, 0xE7, 0xBA, 0x30, 0xAE, 0x62, 0x2D, 0x8E, 0x0D, 0x64, 0x73, 0x73, 0x9C, 0xC2, + 0xD3, 0xD2, 0xD8, 0x31, 0xB1, 0x17, 0x3C, 0x42, 0x2B, 0x70, 0x7F, 0x75, 0x06, 0x9B, 0x2A, 0xE6, 0x83, 0xD7, 0xF4, 0x60, + 0x39, 0x3E, 0xDC, 0x9B, 0xDE, 0x29, 0xE0, 0xF0, 0xDA, 0x44, 0x4E, 0xFF, 0x88, 0x11, 0xDE, 0x99, 0x04, 0x90, 0x7D, 0x11, + 0x5F, 0x19, 0x54, 0xD4, 0xC6, 0x32, 0x79, 0x65, 0x94, 0x0D, 0xB5, 0xE6, 0x82, 0x36, 0x70, 0x29, 0xA3, 0x96, 0xDB, 0xB7, + 0x4C, 0x9A, 0x67, 0x41, 0x6A, 0xF8, 0x02, 0x95, 0x80, 0x73, 0x7E, 0x91, 0x4B, 0x78, 0xBC, 0x7F, 0xEE, 0x97, 0xE9, 0x57, + 0x81, 0xBB, 0x96, 0xAC, 0x78, 0x78, 0xF5, 0x9A, 0xC7, 0x02, 0xF0, 0x06, 0xD2, 0xFC, 0xF2, 0x38, 0x95, 0x79, 0xE6, 0x38, + 0x22, 0xEA, 0x90, 0x76, 0x49, 0xC9, 0x60, 0x7C, 0x62, 0x2A, 0x45, 0x56, 0x1F, 0x1B, 0xAD, 0x2F, 0x2D, 0x14, 0xAE, 0xEF, + 0x2B, 0xCF, 0xF1, 0xAA, 0xD2, 0x9E, 0xB3, 0xFB, 0x6A, 0x8F, 0xC1, 0xC5, 0xB9, 0x3A, 0x58, 0x37, 0xDB, 0x9F, 0x57, 0x69, + 0xCD, 0xC1, 0xF2, 0x92, 0xC9, 0x39, 0x89, 0xB9, 0x45, 0x11, 0x30, 0xDF, 0x8A, 0x71, 0x9C, 0x53, 0xC8, 0x7C, 0x66, 0xC8, + 0x12, 0xF2, 0xDE, 0x04, 0xDA, 0xF0, 0xB3, 0x37, 0x76, 0x5A, 0xD5, 0xAD, 0x41, 0xE3, 0x68, 0x0B, 0x1F, 0xFF, 0x17, 0x24, + 0x0D, 0xC5, 0x8B, 0x22, 0x07, 0x12, 0xE9, 0xC0, 0x3F, 0x9B, 0xFF, 0x8B, 0x89, 0x73, 0x20, 0x79, 0x85, 0x91, 0x08, 0x3B, + 0xEF, 0xC4, 0x83, 0xF7, 0x88, 0xC0, 0xCB, 0xDD, 0xC4, 0xA3, 0xD6, 0xDB, 0x75, 0xA2, 0x8C, 0x68, 0xA6, 0x75, 0xD7, 0x5C, + 0xA8, 0xBD, 0xE9, 0x41, 0x2F, 0x67, 0x78, 0x26, 0x3A, 0xFA, 0x1B, 0xB3, 0x50, 0x2D, 0x49, 0x8D, 0xB6, 0x74, 0xDD, 0x50, + 0xA2, 0x64, 0xBC, 0x45, 0xE7, 0xDE, 0x89, 0x0D, 0x09, 0xE6, 0x1B, 0xA5, 0x85, 0x66, 0x6C, 0x73, 0xF5, 0x6E, 0x94, 0x51, + 0x26, 0xF3, 0xAA, 0xA0, 0x84, 0xCC, 0x55, 0x7F, 0xA2, 0x35, 0x8F, 0x1D, 0xCB, 0x62, 0x2F, 0x33, 0x2D, 0xA9, 0x10, 0x75, + 0xA6, 0x0F, 0x28, 0x0F, 0xDE, 0x08, 0xCD, 0x4F, 0x41, 0x16, 0x82, 0x66, 0xD5, 0xC1, 0x41, 0x21, 0xC5, 0x7D, 0xD6, 0x6A, + 0x66, 0xF7, 0x39, 0xA3, 0x9F, 0x4D, 0x31, 0xAA, 0x2E, 0x1B, 0x92, 0xB1, 0x05, 0x8F, 0x7E, 0xD3, 0xA7, 0x12, 0xBA, 0x11, + 0x30, 0x48, 0xEC, 0x95, 0x55, 0xE3, 0x96, 0x68, 0x64, 0x85, 0xD4, 0x24, 0x2E, 0x6D, 0xE0, 0xB9, 0x7A, 0x37, 0x0A, 0xD5, + 0x4C, 0xA5, 0x54, 0x1C, 0xEC, 0x0A, 0x75, 0x1E, 0x9E, 0xA7, 0xC1, 0xBE, 0x08, 0x90, 0xE3, 0xE5, 0x5B, 0x69, 0x58, 0xFB, + 0xEF, 0x3B, 0x90, 0x07, 0x78, 0x1F, 0x0D, 0x9A, 0x06, 0xF9, 0x48, 0x27, 0x79, 0x15, 0x88, 0xE8, 0x01, 0x86, 0x4B, 0x20, + 0xB9, 0xC5, 0x05, 0x97, 0xB1, 0x34, 0x65, 0xC2, 0xFC, 0x30, 0xA6, 0x28, 0x4D, 0x7B, 0xF4, 0x77, 0xF5, 0x1D, 0x6A, 0xD7, + 0x2D, 0x45, 0xAC, 0x0C, 0x9F, 0x8E, 0x12, 0x38, 0x4C, 0xF2, 0xF9, 0xDA, 0x2F, 0xD8, 0xFD, 0x9A, 0x29, 0x10, 0xBE, 0x87, + 0x74, 0x76, 0x1B, 0x29, 0xCD, 0x70, 0x58, 0xFE, 0xEE, 0x01, 0xE0, 0x81, 0x6B, 0x44, 0xB9, 0x7A, 0xFC, 0xE3, 0x13, 0x39, + 0xCC, 0x30, 0xFD, 0x72, 0x74, 0xDE, 0x6D, 0x19, 0xAF, 0x37, 0xFB, 0x82, 0xCE, 0x34, 0xF9, 0x60, 0xD8, 0x19, 0x25, 0x75, + 0xD4, 0xFC, 0xE0, 0xBD, 0x06, 0x44, 0x74, 0x0E, 0xC9, 0xEB, 0x8F, 0x33, 0xD8, 0x9E, 0x07, 0x7E, 0x71, 0xDD, 0x69, 0x43, + 0xC6, 0x91, 0x04, 0x4D, 0x65, 0xBC, 0xE5, 0x4E, 0xEC, 0x94, 0xC4, 0xFC, 0x61, 0x2F, 0x63, 0xB8, 0x82, 0x7F, 0x9A, 0xC1, + 0x07, 0xE2, 0xBD, 0x8D, 0xCF, 0x67, 0x79, 0xC9, 0x9B, 0x6F, 0x0F, 0x82, 0x87, 0x2C, 0x46, 0xBF, 0x50, 0x0C, 0x73, 0x39, + 0xD7, 0xF7, 0x67, 0xC1, 0x8B, 0x1F, 0xB4, 0x5E, 0x51, 0x55, 0xAF, 0xD1, 0x0D, 0xFD, 0xC8, 0xF5, 0x8B, 0x98, 0xC3, 0xA5, + 0x07, 0x14, 0x2E, 0xB1, 0x8C, 0xB1, 0xFC, 0x1A, 0xD6, 0x78, 0x1E, 0xDC, 0x22, 0x42, 0x9D, 0xC3, 0xB2, 0x36, 0x40, 0x10, + 0x62, 0x5B, 0xAB, 0x53, 0x17, 0x8D, 0xC1, 0x56, 0xD0, 0x97, 0xD5, 0xE7, 0xCE, 0x18, 0x46, 0x11, 0x4B, 0x6A, 0x02, 0x73, + 0xBC, 0x0A, 0xF4, 0x90, 0x42, 0x2C, 0xCF, 0x65, 0xD7, 0x0C, 0x08, 0x48, 0x06, 0xBB, 0x26, 0x8E, 0x26, 0x72, 0x50, 0x36, + 0xC4, 0x7A, 0x2E, 0x58, 0xAF, 0xBA, 0x04, 0x49, 0xA7, 0x72, 0x06, 0x0C, 0x75, 0xFB, 0x76, 0xF9, 0xC4, 0x89, 0x04, 0x95, + 0xD7, 0xCE, 0x49, 0x3D, 0x30, 0x3C, 0x5F, 0x36, 0xCF, 0xD8, 0x7D, 0x61, 0x46, 0xA8, 0x4C, 0x64, 0x54, 0x1C, 0x5D, 0xBF, + 0x25, 0xB8, 0x7F, 0x62, 0x38, 0x00, 0x71, 0x35, 0xDB, 0x0F, 0x46, 0xBC, 0x5C, 0x90, 0x0E, 0xF7, 0xEE, 0x69, 0x66, 0x9D, + 0x03, 0xF5, 0x34, 0x0A, 0x17, 0xDF, 0xB7, 0x27, 0x9A, 0x62, 0x20, 0xD7, 0x4E, 0x76, 0xF6, 0x7E, 0x08, 0xD8, 0x48, 0xB4, + 0x77, 0x01, 0x99, 0xC8, 0x1F, 0xFF, 0xE7, 0x1A, 0xDA, 0x78, 0xFC, 0x28, 0x3C, 0x1E, 0xE7, 0x63, 0x0E, 0x3E, 0xEE, 0xB9, + 0x40, 0xFE, 0x6C, 0xCC, 0x84, 0x6E, 0x20, 0x9F, 0xC0, 0xFF, 0xD9, 0x14, 0xE1, 0xBF, 0x7F, 0x43, 0xDA, 0xF1, 0x53, 0xD1, + 0xFF, 0x20, 0x37, 0x1D, 0xD2, 0xB4, 0x97, 0x34, 0x83, 0xB5, 0x9D, 0x90, 0x4F, 0x84, 0x61, 0xCB, 0xB5, 0x9E, 0x06, 0xDB, + 0x31, 0xEB, 0xC1, 0xD5, 0xC3, 0xA0, 0x3A, 0x96, 0xE8, 0x28, 0x4F, 0xCE, 0xE2, 0x41, 0x19, 0x47, 0x5D, 0xC4, 0x3A, 0xE1, + 0x89, 0x0C, 0x25, 0x6A, 0x0F, 0xFE, 0xAE, 0xCE, 0x42, 0x4D, 0x59, 0x71, 0xA3, 0x6E, 0x21, 0xE0, 0xD4, 0xBB, 0x04, 0xC1, + 0x51, 0xD7, 0x56, 0x12, 0xBD, 0x06, 0xB5, 0xE0, 0x5E, 0xED, 0xA8, 0x6F, 0x27, 0x6B, 0xA8, 0x56, 0xDB, 0x28, 0x5B, 0x03, + 0x2A, 0x29, 0xE2, 0xFA, 0xE4, 0xE8, 0x9E, 0x41, 0x01, 0x08, 0xA1, 0x01, 0xAF, 0x29, 0x9E, 0x28, 0xE0, 0x64, 0xEB, 0x22, + 0x4C, 0x19, 0x09, 0x6E, 0x8B, 0x6B, 0x36, 0x12, 0x51, 0x17, 0x3F, 0x1C, 0xC0, 0xE7, 0xBC, 0x9E, 0x32, 0x71, 0xD9, 0x9B, + 0x77, 0x01, 0x63, 0xCC, 0x46, 0x9C, 0xF2, 0x17, 0x6C, 0xE3, 0x6B, 0xAE, 0x8C, 0xBB, 0x6C, 0xE5, 0x28, 0x4B, 0x3E, 0x7E, + 0xEE, 0x4C, 0x64, 0x05, 0xA2, 0x4A, 0xA8, 0xC7, 0xA9, 0x66, 0xC3, 0xD1, 0x02, 0xD1, 0x23, 0x17, 0x14, 0x4F, 0x80, 0x28, + 0xAB, 0xB5, 0xAB, 0xDC, 0x7B, 0xEA, 0x5A, 0x76, 0x8F, 0x1A, 0xB3, 0x2C, 0xED, 0xD4, 0x42, 0x22, 0x2C, 0xE0, 0x2C, 0x04, + 0xDF, 0x4B, 0x6A, 0x8A, 0xDE, 0xCA, 0xCA, 0x58, 0xE7, 0x42, 0x8D, 0xFC, 0x4C, 0x16, 0xAB, 0x6E, 0x56, 0x2E, 0xCA, 0xA9, + 0xC9, 0x4D, 0xAA, 0x18, 0x26, 0x20, 0xED, 0x79, 0xC6, 0x41, 0xDD, 0x0E, 0xD6, 0x9B, 0xE4, 0xDE, 0xE1, 0xA8, 0xA1, 0xA7, + 0x9B, 0xEE, 0xB5, 0x4D, 0x45, 0x4C, 0x57, 0x1D, 0xF8, 0xC0, 0xE4, 0x22, 0x56, 0xA4, 0x5C, 0xBF, 0xBF, 0xA2, 0x33, 0x06, + 0xAB, 0x0F, 0x24, 0x0F, 0x0D, 0xB0, 0x11, 0xA4, 0xAF, 0x12, 0x81, 0xF7, 0x41, 0xB9, 0x51, 0x9F, 0x10, 0x12, 0x1C, 0xC6, + 0x30, 0x7F, 0x64, 0x8E, 0xD6, 0xE5, 0x97, 0x95, 0xD8, 0xA8, 0x7A, 0x10, 0x94, 0xF7, 0x98, 0xF3, 0xF0, 0x7F, 0xB2, 0x80, + 0x2D, 0x1E, 0x05, 0xE5, 0xBC, 0x99, 0x58, 0x04, 0x6D, 0xAF, 0x05, 0x62, 0xF2, 0x87, 0xF2, 0x60, 0x1E, 0x20, 0xFF, 0x91, + 0xE9, 0xC8, 0x8A, 0x71, 0xAD, 0x87, 0x3E, 0x23, 0x2D, 0x95, 0xD7, 0xDB, 0x49, 0x60, 0x80, 0xD5, 0x4A, 0x99, 0x0A, 0xD3, + 0x66, 0xFF, 0x78, 0x77, 0x3D, 0x7E, 0xAF, 0x2B, 0x5C, 0x15, 0xC4, 0x1E, 0xB1, 0x1D, 0xFD, 0xEA, 0xFF, 0xE1, 0x15, 0x0F, + 0x00, 0x75, 0xC7, 0x07, 0x30, 0x15, 0xD2, 0x82, 0x70, 0x56, 0x67, 0xE5, 0x67, 0x40, 0x55, 0xFA, 0xBD, 0xDB, 0x25, 0x13, + 0x25, 0xE2, 0x73, 0x25, 0x40, 0x38, 0x03, 0xFE, 0xE7, 0x19, 0x76, 0x9B, 0x26, 0x8B, 0x56, 0x76, 0x24, 0xB3, 0x02, 0x08, + 0x06, 0xFC, 0x81, 0xB7, 0x4A, 0xFC, 0xAC, 0x5F, 0xB2, 0xD3, 0xCE, 0x69, 0x96, 0xBB, 0x0E, 0x18, 0x07, 0xFD, 0x3E, 0xDA, + 0x80, 0x88, 0x35, 0xE3, 0x80, 0x85, 0xFA, 0x99, 0xC3, 0x65, 0x47, 0x65, 0x56, 0xC1, 0x04, 0x95, 0xA0, 0xCB, 0xF5, 0xA9, + 0x2D, 0xE7, 0x51, 0x76, 0xF9, 0x18, 0xB1, 0xE5, 0x5B, 0x1B, 0x64, 0xCA, 0x95, 0xA4, 0x3C, 0x23, 0x25, 0x8D, 0xD6, 0x68, + 0x34, 0x8E, 0xE6, 0x32, 0x3C, 0xDE, 0x37, 0x48, 0xBC, 0xE3, 0x6B, 0xB3, 0x7C, 0x5C, 0xED, 0x63, 0x8A, 0xA2, 0xF6, 0x0C, + 0xD4, 0x32, 0xBE, 0xC7, 0x4F, 0xE1, 0x61, 0x3B, 0xB1, 0xB7, 0x57, 0xC0, 0xB0, 0x18, 0xBD, 0x4F, 0xB3, 0x5A, 0x88, 0xE9, + 0x69, 0x50, 0x3B, 0xB2, 0x03, 0x82, 0x75, 0x26, 0xAD, 0x55, 0xAF, 0x1D, 0x75, 0xB4, 0xE0, 0xA2, 0x12, 0xD5, 0xD7, 0xF8, + 0x27, 0xB5, 0x67, 0xEA, 0x9D, 0xC2, 0x9E, 0x3F, 0x62, 0xCC, 0x48, 0x3F, 0xA4, 0xDB, 0x5C, 0x48, 0x28, 0x1F, 0xED, 0x96, + 0x5E, 0x12, 0x57, 0x0D, 0x91, 0x35, 0x46, 0x0B, 0x67, 0xE3, 0x43, 0x49, 0x5B, 0x1E, 0x23, 0xF6, 0x82, 0xD3, 0x65, 0xF9, + 0x69, 0xC0, 0x13, 0x17, 0xA4, 0xCD, 0x8B, 0x9B, 0x59, 0x80, 0x79, 0x3F, 0x87, 0x82, 0x0D, 0x69, 0x36, 0xC6, 0xB8, 0xDB, + 0xE5, 0x8E, 0x02, 0x57, 0x95, 0xB8, 0x83, 0x42, 0xDA, 0x72, 0x9E, 0x7F, 0x10, 0x9E, 0x0E, 0xF5, 0xA7, 0x17, 0xCA, 0xFD, + 0xAD, 0x69, 0x16, 0xC8, 0xD2, 0xD8, 0x15, 0xBA, 0x96, 0x1A, 0xF8, 0x83, 0x85, 0x45, 0x47, 0x39, 0xC2, 0x38, 0x3F, 0xD8, + 0x9A, 0x0B, 0xE0, 0xB6, 0xE4, 0xA7, 0x0F, 0xF5, 0xAD, 0x60, 0x92, 0x9D, 0xF2, 0x9A, 0xC2, 0x0C, 0x3A, 0x7B, 0xB2, 0x55, + 0x68, 0xE5, 0x43, 0x80, 0x11, 0x68, 0x50, 0x04, 0xC0, 0x58, 0x35, 0x13, 0x2E, 0x29, 0x1D, 0xEC, 0x38, 0xA9, 0xCD, 0x6D, + 0xA5, 0x79, 0x4D, 0x2C, 0x50, 0xB4, 0x2A, 0x12, 0x6A, 0xA9, 0x12, 0xE1, 0x9F, 0x7D, 0x29, 0x3B, 0xA4, 0x58, 0x2F, 0xBA, + 0x58, 0x7A, 0xA5, 0xE3, 0xE3, 0x41, 0x26, 0x5A, 0xAF, 0xB8, 0xD4, 0xD8, 0xB4, 0x61, 0x0C, 0x61, 0xBF, 0x60, 0x83, 0x32, + 0xA9, 0xC5, 0xF4, 0x7D, 0xE0, 0xA2, 0x97, 0xA8, 0xB5, 0xC1, 0x02, 0xDD, 0x5F, 0x3F, 0xC1, 0x7C, 0xD2, 0x69, 0xE6, 0x06, + 0x65, 0xAD, 0x95, 0x9B, 0x94, 0xDC, 0xA9, 0x6E, 0x58, 0xCC, 0x58, 0x4A, 0x8A, 0x9B, 0x31, 0x1C, 0x19, 0x95, 0xD1, 0x25, + 0xB6, 0x31, 0xB3, 0x3E, 0x1F, 0x19, 0x3D, 0x78, 0x0E, 0x25, 0xB8, 0x4F, 0xE1, 0xAE, 0x0D, 0xF1, 0x1B, 0x53, 0x1F, 0x10, + 0x51, 0x48, 0x4D, 0x62, 0x5F, 0x2B, 0x3C, 0x20, 0xCA, 0xA6, 0xD8, 0x4D, 0x13, 0x2A, 0xB2, 0x7D, 0xCF, 0x12, 0x5D, 0x79, + 0x4F, 0xEF, 0xE7, 0x7B, 0x30, 0xF2, 0x0F, 0x5C, 0x40, 0x04, 0xCA, 0x3D, 0x1F, 0x66, 0xD3, 0x63, 0x9A, 0xA2, 0x14, 0x51, + 0xF7, 0x91, 0xFB, 0xF5, 0x9A, 0xBF, 0x13, 0xD9, 0xA8, 0x25, 0xE4, 0x99, 0x53, 0x26, 0x6A, 0x45, 0x87, 0x22, 0x22, 0xBC, + 0x90, 0x90, 0x35, 0xF9, 0x41, 0x2E, 0x7D, 0x6D, 0xA9, 0x38, 0xA5, 0x9B, 0xDE, 0x2A, 0x5B, 0x8F, 0x10, 0x75, 0x0F, 0xA8, + 0x19, 0x5C, 0xB2, 0x62, 0x2C, 0xB7, 0x55, 0x24, 0x12, 0xF8, 0xF0, 0x13, 0xC5, 0xD6, 0x64, 0x99, 0xFB, 0x52, 0x76, 0xD3, + 0xDC, 0x6E, 0x6B, 0x70, 0xFC, 0x38, 0x5C, 0x90, 0xD0, 0xB0, 0xB2, 0xD2, 0xF5, 0xF6, 0x05, 0xDD, 0x5C, 0x9B, 0x8B, 0xAD, + 0x94, 0x5B, 0x47, 0x1C, 0x64, 0x9E, 0xBB, 0x27, 0xF2, 0x02, 0xAF, 0xD7, 0xA0, 0x74, 0x41, 0x58, 0x08, 0x3A, 0x45, 0x23, + 0x3A, 0xA8, 0xBC, 0x57, 0xAF, 0xE7, 0xDB, 0x9A, 0x47, 0xE7, 0x26, 0xFC, 0x0F, 0xD2, 0x21, 0xEA, 0x78, 0x9A, 0x80, 0x5F, + 0x9C, 0xB8, 0x70, 0x75, 0x79, 0x9A, 0x71, 0x9F, 0x3B, 0x43, 0xDB, 0xC4, 0xFB, 0xD3, 0x9D, 0xAD, 0x78, 0x4D, 0xE7, 0x7A, + 0x13, 0x38, 0x5F, 0xC9, 0x88, 0xFB, 0xF0, 0x98, 0x63, 0x27, 0x1F, 0x25, 0x34, 0xD2, 0x56, 0x60, 0xC6, 0xE4, 0x38, 0xBB, + 0x69, 0x2A, 0xFD, 0x3F, 0xB3, 0xB7, 0xE1, 0xB0, 0xF1, 0xB5, 0x58, 0xBB, 0xA3, 0x3A, 0x07, 0x20, 0xDF, 0x8A, 0xCF, 0xBB, + 0xCD, 0x03, 0xAC, 0xE8, 0xDD, 0x99, 0x91, 0x5E, 0x38, 0x7B, 0xD5, 0x7E, 0xD2, 0x5F, 0xF6, 0xF8, 0x9A, 0xD2, 0xA4, 0xFD, + 0xDC, 0x98, 0xFE, 0x0B, 0xE2, 0x13, 0x9A, 0xBD, 0x2C, 0xA1, 0xCA, 0xB6, 0x11, 0xD8, 0xAD, 0xAF, 0x5D, 0xBF, 0x4F, 0xD3, + 0x8D, 0xAF, 0x1F, 0x0C, 0xB9, 0x47, 0xCB, 0x84, 0x4C, 0x62, 0xA5, 0xBD, 0x5C, 0xBE, 0xAB, 0x7B, 0xD5, 0xFD, 0x4E, 0x64, + 0x44, 0xA1, 0xFC, 0xA0, 0xBC, 0x60, 0xA8, 0x54, 0xE4, 0x69, 0x50, 0xA1, 0x83, 0x09, 0xDA, 0x0A, 0xFA, 0x45, 0xFA, 0x2F, + 0x8F, 0xCC, 0x99, 0xA9, 0x32, 0x72, 0x43, 0x61, 0x98, 0x82, 0x7C, 0xF6, 0x14, 0xAF, 0xBD, 0x63, 0x43, 0x96, 0x11, 0x62, + 0xF4, 0x99, 0xDD, 0x63, 0x22, 0x42, 0xB1, 0x75, 0x95, 0x81, 0x67, 0xA2, 0xAA, 0xC5, 0x0E, 0xC6, 0x55, 0xEE, 0xE3, 0xD6, + 0xDE, 0xE2, 0xCA, 0x40, 0xF9, 0x82, 0x6E, 0xA4, 0x9C, 0xE9, 0x35, 0x9E, 0x61, 0x43, 0x2A, 0x54, 0xE8, 0xD3, 0x7A, 0x4B, + 0xFF, 0x8E, 0x4E, 0xF2, 0xC6, 0xFD, 0x18, 0xBD, 0xA4, 0x7E, 0x7B, 0xB2, 0x48, 0xAD, 0x9F, 0xD7, 0x96, 0xF2, 0x1D, 0xF2, + 0x61, 0x4C, 0x69, 0x54, 0x73, 0x19, 0x37, 0xCE, 0xE8, 0xB1, 0xFF, 0x51, 0xF8, 0xA2, 0x61, 0x36, 0x01, 0xC5, 0x28, 0x13, + 0x31, 0x77, 0x62, 0x4C, 0x07, 0x05, 0x4C, 0x7F, 0x03, 0xAA, 0x92, 0x32, 0x9E, 0xFC, 0xC0, 0x2E, 0xB3, 0x0C, 0x82, 0xFD, + 0x6A, 0x29, 0x6D, 0xDC, 0x1B, 0xA2, 0x64, 0xA2, 0x9C, 0x14, 0x0D, 0xCF, 0xDD, 0xE4, 0x49, 0xD6, 0x2B, 0x0C, 0x7C, 0x7E, + 0x8B, 0x46, 0xF4, 0xD8, 0x12, 0x5A, 0xAB, 0xD3, 0xBB, 0x69, 0x73, 0x9B, 0x8C, 0x92, 0xF4, 0x2C, 0x8A, 0x84, 0xB0, 0x66, + 0x74, 0xB7, 0xC9, 0x3F, 0x32, 0x0F, 0x43, 0xBB, 0xD8, 0xD0, 0x42, 0x0A, 0x88, 0x78, 0x1A, 0xF0, 0x97, 0xF1, 0x56, 0xAA, + 0x30, 0x2D, 0xE5, 0x46, 0xEF, 0xF9, 0x6F, 0xD4, 0x9C, 0x3B, 0x62, 0x3F, 0x95, 0xE2, 0x22, 0x58, 0xDE, 0x1C, 0x78, 0x17, + 0x57, 0xB3, 0xE0, 0x42, 0x42, 0x85, 0xFC, 0xEB, 0x4A, 0x24, 0x8A, 0xC3, 0x7F, 0xEE, 0xFD, 0xAA, 0x63, 0xA4, 0x9B, 0xC3, + 0x60, 0xD4, 0xD0, 0x0B, 0x09, 0x4F, 0x73, 0xDD, 0x5E, 0x9E, 0x64, 0x82, 0x59, 0x1D, 0x33, 0x85, 0xBD, 0x3C, 0xB3, 0xA6, + 0xB4, 0x34, 0xBC, 0x66, 0xA4, 0xB6, 0xC9, 0x72, 0x12, 0xA1, 0x6A, 0xE6, 0xDA, 0x97, 0xD8, 0x60, 0x6D, 0x57, 0xFA, 0x45, + 0xB3, 0x31, 0x4F, 0x9C, 0x22, 0x11, 0xED, 0x9B, 0x76, 0xC6, 0x2D, 0x4E, 0xEE, 0x30, 0x32, 0x32, 0x11, 0xDD, 0xB5, 0x6F, + 0xB1, 0x5E, 0xD3, 0x07, 0xB5, 0x9C, 0x95, 0x7C, 0x42, 0x2E, 0xE3, 0x83, 0x1A, 0x96, 0xFC, 0x87, 0xE8, 0x5D, 0xA4, 0x83, + 0x7D, 0x30, 0xAF, 0x10, 0x6A, 0x32, 0xEA, 0x28, 0x12, 0xAB, 0x7E, 0x2E, 0xDE, 0xC4, 0x0C, 0xD9, 0x33, 0x33, 0xF0, 0x63, + 0x06, 0x5F, 0xA4, 0xC6, 0x8C, 0x6E, 0x07, 0xD2, 0xC7, 0x19, 0x03, 0x47, 0x3F, 0x9C, 0xAA, 0x93, 0x19, 0xEB, 0x2A, 0x96, + 0xE9, 0x82, 0xB6, 0xFE, 0xCA, 0x42, 0x65, 0xEC, 0x12, 0xC8, 0x1A, 0x75, 0xFF, 0xF9, 0xE3, 0x86, 0x50, 0x38, 0xF9, 0x0C, + 0x37, 0xAC, 0x65, 0x7F, 0xE6, 0x93, 0x5C, 0xBD, 0xEA, 0x5B, 0xC8, 0x9F, 0x68, 0xD7, 0x6E, 0x38, 0x31, 0x16, 0x25, 0xE6, + 0xEC, 0xC5, 0x52, 0x48, 0x65, 0x56, 0xBD, 0xA7, 0xA1, 0xD2, 0x5E, 0x01, 0x0D, 0xE5, 0xE0, 0x85, 0x53, 0xAC, 0x54, 0x4B, + 0x6A, 0x12, 0xA5, 0xEB, 0x6A, 0xEE, 0x56, 0x10, 0x8B, 0x39, 0xB0, 0xC2, 0x6D, 0xFE, 0x38, 0xBF, 0x39, 0x3F, 0x3A, 0x35, + 0x7E, 0x6D, 0xDC, 0xA6, 0x0B, 0xCE, 0x72, 0xAE, 0x09, 0x16, 0x6C, 0x6F, 0x99, 0xD7, 0xD7, 0x93, 0xDD, 0x3D, 0x34, 0xB8, + 0x65, 0xE1, 0x36, 0x5E, 0xBE, 0x8D, 0x64, 0x7C, 0x77, 0xF3, 0x7D, 0x5D, 0xDA, 0xC2, 0x87, 0x04, 0x8B, 0x81, 0x68, 0x2B, + 0xAA, 0xC3, 0x7F, 0xD0, 0xEC, 0xCE, 0x87, 0xF1, 0x98, 0x78, 0x74, 0x86, 0xC8, 0x19, 0x0F, 0xD0, 0x94, 0x7E, 0x65, 0x7E, + 0x18, 0xF2, 0xC7, 0xC4, 0xCC, 0x9A, 0x1A, 0xE0, 0x86, 0xC8, 0x00, 0x74, 0x76, 0x74, 0x93, 0x14, 0x98, 0x25, 0x88, 0x5A, + 0x75, 0xA0, 0x48, 0x56, 0x0A, 0x8C, 0x28, 0x07, 0x06, 0x0C, 0xB8, 0x74, 0xD7, 0x65, 0x80, 0xCA, 0xD5, 0x1A, 0x3C, 0xE1, + 0x28, 0x8D, 0xDF, 0x00, 0x35, 0xAB, 0x4F, 0x10, 0xAF, 0x47, 0x1D, 0x03, 0x29, 0xE9, 0x63, 0xED, 0x26, 0x8E, 0xE7, 0x77, + 0x91, 0x01, 0xAA, 0x29, 0x0D, 0x32, 0xE9, 0xCE, 0x95, 0x7C, 0x52, 0x46, 0x83, 0x92, 0xE0, 0x84, 0x95, 0xE2, 0x0E, 0x3B, + 0xAF, 0x1C, 0x58, 0x5A, 0x50, 0xF5, 0x36, 0x5D, 0x03, 0xCB, 0xB0, 0xDB, 0x98, 0xBE, 0x46, 0x2B, 0x25, 0x3A, 0xA1, 0x21, + 0x34, 0xA5, 0xC0, 0x59, 0x1A, 0x32, 0x56, 0x63, 0x7F, 0x5E, 0x63, 0x19, 0x2D, 0xCF, 0xCF, 0x8F, 0x3B, 0xA9, 0x08, 0xF3, + 0x51, 0x38, 0x0F, 0xD3, 0x83, 0xC0, 0x07, 0xAE, 0xE3, 0x85, 0x01, 0x7F, 0xB4, 0xFD, 0x68, 0xF1, 0xAF, 0x74, 0xEC, 0x7D, + 0x0B, 0x2A, 0x15, 0xDB, 0xD0, 0xA8, 0x72, 0xFF, 0x5B, 0x15, 0xC7, 0x98, 0x0C, 0xEA, 0x4D, 0xDE, 0x19, 0x09, 0x45, 0xC7, + 0x4D, 0xC7, 0x2A, 0xF9, 0x79, 0x87, 0x98, 0x54, 0x8A, 0x52, 0x5C, 0x7C, 0xDB, 0xC6, 0xDB, 0xA1, 0xEE, 0x1C, 0x38, 0x4F, + 0xD8, 0x86, 0x71, 0x1A, 0x2E, 0xCA, 0x61, 0x3B, 0x12, 0xA9, 0x53, 0xBD, 0x31, 0x8A, 0xFB, 0x00, 0xD5, 0x87, 0xBD, 0x4A, + 0x8D, 0x82, 0xAA, 0xCB, 0x9C, 0xE0, 0xED, 0x30, 0xB3, 0x6D, 0x0A, 0x1C, 0x6D, 0x38, 0x32, 0x4A, 0xE6, 0xC4, 0x8A, 0x19, + 0x66, 0xB6, 0xDA, 0x08, 0x2D, 0x37, 0x00, 0x0C, 0x6C, 0x6C, 0x83, 0x74, 0xAA, 0x33, 0x66, 0xCB, 0x82, 0xAE, 0x4B, 0x5B, + 0xF5, 0x61, 0x09, 0x67, 0x37, 0xE7, 0x4B, 0x4E, 0xBC, 0x0F, 0xA7, 0xDB, 0x83, 0x04, 0x05, 0x7C, 0x2E, 0xA9, 0x03, 0xFB, + 0x84, 0x7C, 0x27, 0xE4, 0xA6, 0x93, 0x03, 0xB1, 0x5F, 0x15, 0x0C, 0x5D, 0xA5, 0xB2, 0xE4, 0x38, 0x8F, 0xEC, 0x2B, 0xE0, + 0x86, 0x95, 0x04, 0x1C, 0xA1, 0x25, 0x5C, 0xF6, 0x36, 0xDE, 0xBD, 0x80, 0x9F, 0xE4, 0xA2, 0x61, 0x26, 0x91, 0x25, 0x76, + 0x54, 0xF2, 0xF1, 0x26, 0xA7, 0xF2, 0x08, 0xED, 0x10, 0x75, 0x2C, 0xEC, 0x02, 0x95, 0x08, 0x8C, 0xDE, 0xC7, 0x82, 0xE1, + 0xEB, 0x59, 0xB5, 0x81, 0x05, 0xE3, 0xF1, 0x31, 0xA2, 0x19, 0xB4, 0x72, 0x50, 0xB5, 0xEE, 0xDB, 0x06, 0xD8, 0x29, 0x86, + 0x1D, 0x45, 0x54, 0x29, 0x21, 0x6F, 0xFA, 0xB4, 0xCC, 0x18, 0x5C, 0x29, 0x43, 0xBB, 0x23, 0x96, 0x00, 0x83, 0x37, 0xDD, + 0x4D, 0xF2, 0xB3, 0x62, 0x5F, 0x2C, 0xB5, 0xFB, 0x07, 0x66, 0xF1, 0x16, 0x82, 0xF3, 0xFD, 0x5F, 0xF3, 0xE7, 0x20, 0x72, + 0x44, 0x3C, 0x3D, 0xCC, 0xEF, 0xBB, 0x3D, 0xAB, 0xEB, 0x2C, 0x76, 0x93, 0x4F, 0xB8, 0x26, 0x48, 0xAE, 0xBB, 0xB2, 0x8D, + 0xCF, 0x6C, 0x04, 0x95, 0x03, 0xF8, 0xB3, 0x62, 0xAD, 0x22, 0xC6, 0x5C, 0xBB, 0x4C, 0x74, 0xAF, 0xEF, 0x91, 0x2E, 0x79, + 0x7F, 0x0C, 0x5F, 0x77, 0x2C, 0x61, 0x44, 0x74, 0xC3, 0xBA, 0x97, 0xB1, 0x60, 0xD7, 0xDF, 0x6D, 0x7A, 0x0F, 0x34, 0x9F, + 0xAE, 0x97, 0x3F, 0x1D, 0x3D, 0x38, 0xA7, 0x59, 0xC9, 0x76, 0xBB, 0xF8, 0x7C, 0xF5, 0x46, 0x15, 0x0A, 0x20, 0xFE, 0xF7, + 0xD5, 0xF8, 0x5E, 0x28, 0xB2, 0x98, 0x40, 0x13, 0x5F, 0x87, 0x24, 0xB8, 0x44, 0x92, 0x4E, 0x20, 0xC6, 0x3C, 0x9C, 0xE9, + 0xEB, 0x3B, 0x78, 0x7A, 0x38, 0x59, 0xD8, 0x90, 0x2C, 0x9A, 0xBD, 0x5C, 0xCC, 0x4B, 0xD4, 0xEC, 0x26, 0xBA, 0xC7, 0x03, + 0xF6, 0x45, 0xEB, 0xE9, 0x50, 0xF3, 0xF7, 0x24, 0x4E, 0x3C, 0x40, 0xA9, 0xAC, 0xD0, 0x24, 0xC8, 0x80, 0xF6, 0xDD, 0x22, + 0x37, 0x20, 0x24, 0x96, 0x10, 0xFF, 0xD0, 0x9D, 0x8F, 0xDB, 0xE7, 0x1E, 0xA2, 0x6E, 0xC8, 0x4C, 0xC7, 0x40, 0x77, 0x66, + 0x7B, 0x45, 0xCA, 0xB4, 0x7E, 0x41, 0x74, 0xB4, 0xAD, 0x41, 0x5E, 0x61, 0xF3, 0x74, 0x11, 0x6A, 0xF8, 0x66, 0x35, 0xD8, + 0x60, 0xE9, 0xF9, 0xA3, 0x2C, 0x23, 0xAE, 0x54, 0x06, 0x33, 0x72, 0x52, 0x6C, 0x95, 0xC0, 0x33, 0xBE, 0x63, 0x35, 0x77, + 0x52, 0xB7, 0x12, 0xC4, 0x0A, 0x72, 0x0A, 0xB4, 0x1E, 0x2B, 0x38, 0xA2, 0xC4, 0xB1, 0x12, 0x23, 0x90, 0xE4, 0xAD, 0x43, + 0x2D, 0x41, 0xC5, 0xA9, 0x52, 0x23, 0x5C, 0x37, 0xC2, 0x4B, 0xF8, 0x64, 0xAA, 0xE4, 0xF6, 0xF0, 0x84, 0x26, 0xFB, 0xBA, + 0x94, 0xDC, 0xC1, 0xA6, 0xC0, 0xB3, 0x99, 0x75, 0xA1, 0x66, 0x6F, 0xF5, 0x0F, 0x0A, 0xEE, 0x3E, 0x72, 0x28, 0x66, 0x23, + 0x80, 0x48, 0xA2, 0x8F, 0x22, 0x05, 0xAA, 0x18, 0x3B, 0xF8, 0x39, 0x96, 0x1B, 0x08, 0xD2, 0xF9, 0xB5, 0x13, 0x70, 0x33, + 0x96, 0xE5, 0x7D, 0x7A, 0xC8, 0x6A, 0x25, 0x67, 0xC4, 0x68, 0x49, 0x39, 0x32, 0x49, 0x98, 0xCF, 0xBD, 0xC6, 0xBB, 0xF2, + 0x0A, 0xDE, 0x13, 0x53, 0x69, 0xF6, 0xA5, 0xC4, 0xE9, 0xE1, 0xED, 0xBE, 0xB3, 0xEC, 0xDF, 0xC9, 0x08, 0x83, 0x28, 0xBC, + 0x45, 0x68, 0x40, 0x3B, 0xB6, 0x6B, 0x2D, 0xCC, 0x31, 0x7B, 0xF6, 0xB7, 0x0C, 0x2C, 0x76, 0x93, 0xE9, 0x6D, 0x58, 0x60, + 0xA1, 0xEA, 0x16, 0xE9, 0x19, 0x9E, 0xE2, 0xFA, 0x8C, 0x2A, 0x9A, 0xF5, 0x5F, 0x2B, 0xE8, 0x67, 0xA7, 0xE6, 0x29, 0x6C, + 0xC8, 0x91, 0xA6, 0x9A, 0xEC, 0xE1, 0xF9, 0xB2, 0x6D, 0x91, 0x0D, 0xF2, 0xDA, 0x9A, 0x4C, 0x0D, 0x9A, 0xBE, 0x8B, 0x81, + 0x82, 0x4F, 0x68, 0xE1, 0x3A, 0x9E, 0x6D, 0x7F, 0xA0, 0xCA, 0x60, 0x22, 0xFF, 0x74, 0x84, 0x55, 0x2D, 0x6B, 0x7F, 0x75, + 0x39, 0x30, 0x0C, 0xB5, 0x03, 0xAF, 0x90, 0x46, 0xF2, 0x8C, 0x0A, 0x6C, 0x91, 0x53, 0x5C, 0xBA, 0x1B, 0x84, 0x64, 0x32, + 0xE9, 0x00, 0xFC, 0xEB, 0x96, 0xDC, 0x82, 0xF3, 0x5B, 0xE9, 0xA3, 0x49, 0xB5, 0x47, 0x6D, 0x23, 0x60, 0x9A, 0xEF, 0x55, + 0x23, 0x7D, 0xC2, 0x01, 0x40, 0xBC, 0xDF, 0xAF, 0x9F, 0x73, 0x25, 0x03, 0xE9, 0xF1, 0x13, 0x57, 0x5D, 0xDE, 0xE4, 0x36, + 0x11, 0x83, 0xE4, 0xB7, 0x16, 0x99, 0x9F, 0x98, 0x8B, 0x4D, 0x6B, 0x02, 0x56, 0x8B, 0xAC, 0xE5, 0xDE, 0x16, 0xC4, 0xD1, + 0x11, 0x05, 0xA0, 0x74, 0x3C, 0x12, 0xA3, 0x70, 0x62, 0xCC, 0xFD, 0x3E, 0xC2, 0xE9, 0xDB, 0x82, 0x78, 0xFF, 0xF9, 0x73, + 0xF6, 0x5E, 0x6D, 0x1F, 0xE2, 0x3B, 0xF3, 0xC0, 0xB3, 0x5A, 0x0E, 0x51, 0xEE, 0x6A, 0x9D, 0x2D, 0x85, 0x56, 0x4D, 0x77, + 0xD1, 0x85, 0x13, 0xFB, 0x10, 0x74, 0x89, 0xDF, 0xB7, 0x3A, 0x2C, 0x4A, 0x1F, 0x5C, 0x9F, 0x4E, 0xDC, 0x0B, 0x54, 0x17, + 0x41, 0x28, 0xE6, 0x82, 0xFF, 0xCD, 0xDE, 0x75, 0x91, 0xA4, 0x4A, 0x6C, 0xF8, 0xC1, 0x61, 0x59, 0xAB, 0x78, 0x30, 0x8C, + 0x35, 0x36, 0xC8, 0xFC, 0x93, 0x37, 0xAD, 0x08, 0x39, 0x19, 0xCF, 0x25, 0x5E, 0x16, 0x69, 0x6C, 0x73, 0x7B, 0x47, 0xAC, + 0x16, 0x19, 0x64, 0x9B, 0x8B, 0xF6, 0x1F, 0xCE, 0xCD, 0x5D, 0x96, 0xD1, 0x72, 0x3F, 0x55, 0xED, 0x6C, 0xCF, 0xEE, 0x3C, + 0x8D, 0x73, 0xE2, 0x9A, 0xA8, 0xB6, 0x9E, 0x49, 0x73, 0x7F, 0xDB, 0xFD, 0x6D, 0xAD, 0xA6, 0x7E, 0x59, 0x8F, 0xAB, 0x49, + 0x56, 0x3E, 0x01, 0xDC, 0x3A, 0x2E, 0x9D, 0xAF, 0xBA, 0x5F, 0xB7, 0xA9, 0xBD, 0xF3, 0xAD, 0xD9, 0x73, 0xF9, 0x00, 0xEA, + 0x3B, 0x5F, 0xA1, 0x7D, 0xEB, 0x9F, 0xE7, 0x2D, 0x00, 0x70, 0x50, 0xED, 0xF8, 0x49, 0x9E, 0xCA, 0xCC, 0xAF, 0xF0, 0x23, + 0x55, 0x1B, 0xCE, 0x14, 0xD1, 0xF6, 0xAF, 0x74, 0xBA, 0x0C, 0x96, 0xF4, 0x3B, 0x7E, 0xF8, 0xCB, 0x64, 0x5A, 0x9B, 0x29, + 0x8D, 0x4A, 0xE1, 0xDE, 0xAD, 0x99, 0x93, 0x36, 0x35, 0x5D, 0x15, 0xDE, 0x64, 0xB9, 0x1E, 0x5C, 0x09, 0x4D, 0x57, 0x46, + 0x7D, 0x4A, 0x16, 0x27, 0xB4, 0x0C, 0x8F, 0x37, 0xDE, 0x1C, 0x1C, 0xBF, 0x52, 0xF5, 0xAF, 0x24, 0x24, 0x47, 0x9F, 0xC4, + 0xC2, 0x77, 0x72, 0x24, 0xD4, 0x90, 0x5C, 0x00, 0xA1, 0xF4, 0xA8, 0x12, 0xD5, 0x08, 0x44, 0xCC, 0x14, 0x67, 0xDD, 0xEA, + 0xC0, 0xD3, 0x36, 0x31, 0x64, 0x89, 0xF2, 0xC7, 0xC7, 0x9D, 0xD9, 0x7E, 0x65, 0x1B, 0x52, 0x6C, 0x1E, 0x6D, 0x49, 0x8F, + 0x1E, 0xA4, 0x09, 0x11, 0x93, 0x88, 0x44, 0x2C, 0x0A, 0x17, 0x29, 0xED, 0x3C, 0x3C, 0x42, 0x91, 0xC7, 0x1A, 0x95, 0x7E, + 0x0A, 0x72, 0xF0, 0x70, 0x7E, 0x8D, 0x52, 0x28, 0x4D, 0xC5, 0xE2, 0xB0, 0xA7, 0x3D, 0x14, 0x5F, 0xAE, 0x09, 0x3D, 0xED, + 0x99, 0x22, 0xE8, 0x94, 0xCF, 0xCD, 0xD2, 0xB8, 0xA1, 0xA8, 0x3C, 0x89, 0xAE, 0xBA, 0xDD, 0xAA, 0xFF, 0xA3, 0x49, 0x4B, + 0xCA, 0x88, 0x40, 0x10, 0x22, 0xE4, 0x4B, 0xBB, 0xD1, 0x84, 0xCD, 0xA3, 0x61, 0xEF, 0x33, 0x59, 0xAC, 0x9E, 0xDB, 0x60, + 0x7E, 0x60, 0xA2, 0x57, 0x45, 0xCE, 0xB8, 0x1A, 0x22, 0x03, 0x72, 0xA8, 0xCD, 0x8A, 0x0A, 0x66, 0xFB, 0x33, 0x6C, 0xB2, + 0x00, 0xC0, 0x94, 0x59, 0xBE, 0x5C, 0x6F, 0xFE, 0x1C, 0x57, 0x3A, 0xAB, 0xD2, 0xF6, 0x33, 0xB5, 0xAC, 0x0D, 0x43, 0x3D, + 0xFC, 0xA2, 0xC4, 0x4F, 0xC8, 0x27, 0xF2, 0x09, 0xED, 0x0A, 0x73, 0x4B, 0x6E, 0x94, 0x14, 0x2D, 0xE9, 0x70, 0x6B, 0x7F, + 0xDB, 0x8D, 0xD5, 0x01, 0x78, 0xFF, 0x3C, 0x93, 0xD8, 0xA1, 0xFA, 0x14, 0x30, 0x3D, 0xE1, 0xB4, 0x62, 0x69, 0x60, 0xF4, + 0x5A, 0x7A, 0x39, 0x90, 0xC0, 0x8A, 0xF2, 0xA5, 0x21, 0x1E, 0x9F, 0xB5, 0xD8, 0x60, 0x36, 0xEE, 0xC9, 0x59, 0xE5, 0x4A, + 0x58, 0x32, 0xDB, 0xB1, 0x5F, 0x57, 0x64, 0x87, 0x38, 0x96, 0x8D, 0xFB, 0x0F, 0x56, 0x0B, 0x67, 0x5A, 0x3E, 0x9F, 0xD1, + 0x27, 0x27, 0xC2, 0xC1, 0x97, 0x0C, 0x3D, 0x7B, 0x9D, 0x67, 0x3A, 0x51, 0x3A, 0x19, 0x24, 0x1B, 0xE4, 0xF6, 0xB4, 0x4B, + 0xA5, 0xD0, 0x94, 0x46, 0x2C, 0x79, 0xCB, 0xE5, 0x4C, 0x30, 0x9B, 0x70, 0x6F, 0xB4, 0x44, 0xA2, 0x63, 0xDA, 0xC4, 0x26, + 0x2B, 0xF3, 0x1B, 0x51, 0x72, 0x53, 0x6E, 0x06, 0xB0, 0x6C, 0x9B, 0x61, 0xC4, 0x24, 0x8D, 0x65, 0x76, 0x4F, 0xE9, 0x22, + 0x47, 0xB7, 0xE8, 0xD3, 0xFF, 0x1E, 0x1D, 0x53, 0xBD, 0x5C, 0xAD, 0x7A, 0x54, 0xB5, 0x6C, 0xEA, 0x68, 0xA3, 0x85, 0x95, + 0xE4, 0x13, 0xDA, 0xD9, 0xE8, 0x2E, 0x66, 0xB5, 0x52, 0xAC, 0xD4, 0xBE, 0x56, 0x99, 0xFE, 0x00, 0xC6, 0x4C, 0x3D, 0xD5, + 0x92, 0x74, 0xF1, 0x90, 0x02, 0xB9, 0x8B, 0xEC, 0x21, 0xF8, 0x02, 0x07, 0x3B, 0xAC, 0x09, 0xAC, 0x3A, 0xD2, 0xE5, 0xA0, + 0x96, 0xB8, 0x74, 0x99, 0xD2, 0xBB, 0x58, 0xA1, 0x4B, 0x0E, 0x9F, 0x24, 0x12, 0x76, 0x7F, 0xBE, 0x37, 0x0E, 0xCE, 0x40, + 0xBA, 0x08, 0x76, 0xBC, 0xC9, 0x37, 0x72, 0x08, 0xEC, 0xDF, 0x3B, 0x3A, 0x78, 0x7C, 0x2F, 0x1C, 0xBD, 0x9E, 0xD4, 0x6E, + 0xBE, 0x12, 0x06, 0x78, 0x4D, 0x0F, 0xB0, 0xDA, 0x7F, 0xFD, 0xC2, 0xD0, 0xC5, 0xEA, 0x60, 0xF3, 0x55, 0xFA, 0xB0, 0x89, + 0xAF, 0xFE, 0x53, 0x7E, 0xB5, 0x54, 0x8C, 0x20, 0xD0, 0x9F, 0x4B, 0xBD, 0x44, 0xB6, 0x45, 0x19, 0x6D, 0x97, 0xFF, 0xFF, + 0xFF, 0xFF, 0xDF, 0xFF, 0xE1, 0xDF, 0xA0, 0xFD, 0x32, 0x5B, 0x5B, 0x61, 0x44, 0xBA, 0x10, 0x75, 0xB3, 0x22, 0x73, 0x6B, + 0x8C, 0x97, 0xE8, 0x55, 0x9D, 0x2C, 0x78, 0x32, 0x2A, 0x4C, 0xE6, 0x69, 0xBA, 0x0B, 0x7E, 0xE9, 0x58, 0xCF, 0x80, 0x01, + 0x8B, 0xFD, 0xA9, 0x81, 0xCE, 0x53, 0xDE, 0x39, 0xF4, 0xEF, 0x41, 0x9C, 0xB2, 0x17, 0x83, 0x1D, 0x32, 0x25, 0xE6, 0x63, + 0xCF, 0xC9, 0xC0, 0x33, 0x36, 0xB8, 0xE7, 0xF8, 0xD2, 0xB7, 0x3F, 0x60, 0x6D, 0x24, 0x09, 0x2B, 0x44, 0x55, 0x38, 0x1E, + 0x90, 0x64, 0x8D, 0xDD, 0xEA, 0xD6, 0x96, 0x68, 0xF8, 0x61, 0x98, 0x60, 0xCF, 0x45, 0x22, 0x7C, 0xAE, 0xAA, 0x66, 0xFD, + 0x3F, 0x0F, 0x51, 0xB9, 0x9A, 0xAD, 0x90, 0xE5, 0xF2, 0xDB, 0xD9, 0x13, 0xC0, 0xBB, 0xDC, 0xA2, 0x07, 0x8A, 0xF3, 0xE5, + 0x47, 0x88, 0x59, 0x71, 0xC3, 0xCA, 0x49, 0x07, 0x20, 0xD8, 0xB8, 0x71, 0x29, 0x4A, 0x8A, 0x41, 0x7B, 0x68, 0x94, 0x08, + 0xE9, 0xDA, 0x39, 0xD1, 0x13, 0x13, 0x06, 0x66, 0xA8, 0x96, 0xC8, 0xFE, 0x9B, 0x61, 0x3D, 0x02, 0xE8, 0x40, 0xD8, 0xC0, + 0xD4, 0x92, 0x59, 0x0B, 0xF0, 0x48, 0xFB, 0x8F, 0x99, 0x72, 0x03, 0x24, 0xC6, 0x4C, 0x14, 0xD6, 0xDE, 0x90, 0xA7, 0x86, + 0x8A, 0xCB, 0x1C, 0xFF, 0x1B, 0x63, 0x1C, 0xC4, 0xC5, 0x09, 0xD6, 0xD0, 0x85, 0xE6, 0x14, 0xF1, 0xE1, 0x68, 0x66, 0x2E, + 0xE1, 0xD1, 0x0B, 0xAF, 0xED, 0x57, 0x0F, 0xEC, 0x6D, 0x8D, 0xDF, 0xAB, 0x8F, 0x80, 0x49, 0xE2, 0x5F, 0x50, 0xE5, 0x26, + 0xA2, 0xE4, 0xB7, 0x91, 0x23, 0x36, 0x7B, 0xB6, 0x63, 0x9D, 0x6F, 0xD6, 0x9B, 0xAE, 0xEF, 0x8F, 0xEE, 0x92, 0xAE, 0x87, + 0xDC, 0x2E, 0x1D, 0xF4, 0x60, 0x6B, 0x91, 0x1F, 0xEF, 0x80, 0xC8, 0x87, 0x22, 0xE6, 0x2E, 0x94, 0xCB, 0x74, 0x36, 0x7F, + 0xD4, 0x1F, 0x41, 0x6C, 0x10, 0x7D, 0x5C, 0x2C, 0x03, 0x26, 0x54, 0x18, 0x5D, 0xF1, 0xD7, 0x94, 0x27, 0x8B, 0x05, 0xDD, + 0xE8, 0xCC, 0xD5, 0xD0, 0x39, 0xA4, 0xC6, 0xA5, 0x19, 0xF2, 0x25, 0x91, 0xDF, 0x16, 0x93, 0x30, 0x4F, 0x70, 0x03, 0x88, + 0xE6, 0x81, 0x2B, 0x21, 0x86, 0xEA, 0x9F, 0x13, 0xA0, 0xF4, 0xA2, 0xEE, 0x46, 0x9E, 0x08, 0x35, 0xFE, 0xEE, 0xE3, 0xB3, + 0x10, 0xF0, 0x14, 0x3F, 0xD9, 0x12, 0xD1, 0x40, 0x47, 0x21, 0x12, 0x31, 0x8B, 0x0E, 0x8C, 0x07, 0x8B, 0xEC, 0x74, 0x3B, + 0x07, 0x98, 0xEC, 0xB2, 0x17, 0x33, 0xF0, 0x6F, 0x60, 0x15, 0x4C, 0xAB, 0x8A, 0x89, 0x4D, 0x3E, 0x03, 0x17, 0xC3, 0x00, + 0xFA, 0x07, 0x17, 0x1E, 0x0B, 0x9C, 0x8D, 0xE0, 0x8D, 0x23, 0x32, 0x21, 0xC6, 0xA6, 0x45, 0xD3, 0x52, 0x38, 0x5B, 0x25, + 0x0A, 0xBD, 0x4D, 0x09, 0x5B, 0x8C, 0x5C, 0x89, 0x8B, 0x03, 0xD7, 0x63, 0x85, 0xC7, 0xD6, 0x64, 0x9A, 0xAD, 0xA7, 0x5F, + 0xF4, 0xD5, 0x9E, 0x86, 0x07, 0xED, 0x33, 0x62, 0xC0, 0xC6, 0x18, 0x91, 0xE9, 0xA7, 0xA6, 0xFE, 0xDA, 0x75, 0x43, 0xFA, + 0x98, 0x55, 0x6B, 0x16, 0xB9, 0xBA, 0x02, 0xAD, 0xF3, 0xAF, 0x16, 0x4F, 0xDC, 0x76, 0x5D, 0x1D, 0xF2, 0xAE, 0x1F, 0xE2, + 0x98, 0x5A, 0x8F, 0x3B, 0x69, 0xD8, 0x3B, 0xFF, 0x7D, 0x77, 0x86, 0x89, 0x9D, 0x11, 0xA6, 0x68, 0x3F, 0x33, 0x4E, 0xEC, + 0x20, 0xB6, 0xCE, 0x01, 0x4A, 0xD7, 0xFD, 0x3A, 0x18, 0x7D, 0x91, 0x2C, 0x3F, 0x32, 0x60, 0x30, 0xE6, 0xAB, 0xED, 0x31, + 0x7D, 0x57, 0x19, 0x2B, 0xE6, 0x9B, 0x73, 0x2F, 0x38, 0x76, 0x69, 0x20, 0xA8, 0xA1, 0xDF, 0xC1, 0x02, 0xE4, 0xE4, 0x9E, + 0xA5, 0xC3, 0xAF, 0x79, 0xFA, 0x7E, 0x17, 0xFD, 0xA3, 0x45, 0x2A, 0xEE, 0xCB, 0x55, 0x8F, 0x78, 0xD9, 0x5C, 0x33, 0x74, + 0xB7, 0xE1, 0xE5, 0x34, 0x42, 0xCB, 0xCF, 0xA2, 0x0B, 0x62, 0x43, 0x4D, 0xF0, 0x7D, 0xBA, 0x56, 0xFE, 0xE5, 0xED, 0x24, + 0x43, 0xC2, 0x65, 0x2B, 0xB4, 0x5E, 0x1E, 0x5D, 0xDC, 0x86, 0xFF, 0xE5, 0x90, 0x27, 0x31, 0xDE, 0xC0, 0x80, 0x6A, 0x79, + 0xAB, 0x6B, 0xB9, 0x0C, 0xB5, 0x98, 0x97, 0xF5, 0xF7, 0x36, 0x39, 0xB7, 0x9C, 0xA0, 0x39, 0xEA, 0x97, 0x17, 0xDF, 0xA0, + 0x86, 0xC9, 0x40, 0x34, 0x74, 0x70, 0x68, 0xE3, 0x25, 0x0C, 0xF0, 0xE2, 0x0B, 0x8D, 0xD7, 0xB0, 0x85, 0x79, 0x78, 0x24, + 0xFC, 0x94, 0x2A, 0x6C, 0xAC, 0xA1, 0x80, 0x51, 0xAA, 0xEA, 0xF1, 0xC1, 0x5B, 0xF9, 0x9F, 0x40, 0x37, 0x59, 0xE2, 0x90, + 0x42, 0x4B, 0x91, 0xC7, 0x90, 0x6B, 0x90, 0x28, 0x24, 0x81, 0xD7, 0x7E, 0x1A, 0x01, 0x41, 0x8C, 0x26, 0x78, 0x69, 0x3C, + 0x2E, 0xDB, 0x66, 0x6C, 0x65, 0x99, 0xDC, 0x09, 0x38, 0x5C, 0xA2, 0xA8, 0x98, 0xB5, 0xE0, 0xAA, 0x7C, 0xE8, 0x72, 0x02, + 0x3E, 0x1B, 0x0D, 0xB6, 0xE0, 0x52, 0xAE, 0xC9, 0x75, 0x64, 0x26, 0x0E, 0xC4, 0xAB, 0x3B, 0x2F, 0x65, 0x9B, 0x75, 0x8B, + 0x89, 0x92, 0x0B, 0x5B, 0xC4, 0xC1, 0xEA, 0x68, 0xDA, 0x39, 0x93, 0xEA, 0x2E, 0x78, 0xAB, 0xE1, 0xBF, 0x89, 0x2E, 0x7C, + 0x07, 0xC1, 0x68, 0x67, 0xEE, 0x47, 0xCD, 0xA1, 0xB3, 0x83, 0xAA, 0x8E, 0x50, 0x27, 0xB2, 0xB7, 0x6A, 0x8E, 0xC8, 0x95, + 0xAD, 0xDE, 0x61, 0xB8, 0x8D, 0x85, 0x39, 0xC2, 0xBE, 0x52, 0xFA, 0x7E, 0x10, 0x8C, 0x14, 0x1C, 0x27, 0x52, 0x03, 0x14, + 0x3D, 0x23, 0x56, 0x7E, 0xA6, 0xEC, 0xBE, 0x0B, 0x31, 0x75, 0x4C, 0x46, 0xD8, 0x9E, 0xD6, 0xAB, 0x87, 0x80, 0x91, 0x3F, + 0xD3, 0x1A, 0x45, 0xAA, 0xEE, 0x8F, 0xC1, 0xC7, 0x2C, 0xD2, 0xFB, 0x86, 0x22, 0xB0, 0xFA, 0x64, 0x14, 0x35, 0x6E, 0x8C, + 0xC7, 0x0B, 0xDC, 0x57, 0xF7, 0xE2, 0x28, 0x1D, 0xD9, 0xF2, 0x6C, 0x8E, 0xEE, 0x30, 0xB8, 0x4A, 0x65, 0x93, 0xB4, 0x11, + 0x94, 0xFE, 0xC0, 0xF1, 0x5B, 0xD0, 0x16, 0x65, 0x87, 0x96, 0x15, 0x5E, 0xC6, 0x69, 0x75, 0x7A, 0x52, 0xF4, 0xED, 0x92, + 0x3B, 0x66, 0xA5, 0x68, 0x54, 0x60, 0x73, 0x77, 0x68, 0x5E, 0xDD, 0xF6, 0x79, 0xFE, 0xA0, 0x08, 0x9D, 0x6B, 0xBE, 0x93, + 0x42, 0x1B, 0xE4, 0x91, 0x03, 0xAB, 0xD2, 0xCF, 0x71, 0xEF, 0x60, 0x3C, 0xDA, 0x9A, 0x92, 0xD1, 0x96, 0xF4, 0xA8, 0x1C, + 0x9A, 0xB9, 0xFD, 0x85, 0x4B, 0xBA, 0x3F, 0xB7, 0xDE, 0xD4, 0x45, 0xB5, 0xD4, 0x62, 0x4A, 0xCE, 0x59, 0x5B, 0xAB, 0x94, + 0xC2, 0xB9, 0x6A, 0x68, 0x61, 0x29, 0x2D, 0x0E, 0x7D, 0xAC, 0x98, 0x9D, 0x86, 0xD3, 0x6D, 0x88, 0x9F, 0xFA, 0x74, 0x0E, + 0x24, 0xEE, 0x5D, 0x66, 0x37, 0xF7, 0xD1, 0x55, 0x8D, 0x0E, 0xBC, 0xAF, 0xDF, 0xF6, 0xCB, 0x41, 0x96, 0xD5, 0xEE, 0x76, + 0x64, 0xF6, 0x8A, 0xC5, 0xCE, 0x02, 0x1A, 0x7C, 0xDE, 0xF7, 0x1D, 0x74, 0xAA, 0xBA, 0xA6, 0xF0, 0x1B, 0x3B, 0x57, 0xA9, + 0x8A, 0xD5, 0xDF, 0x6D, 0x78, 0xF4, 0x5F, 0x5D, 0x07, 0xD9, 0x95, 0x23, 0xAF, 0xF4, 0x1F, 0x46, 0xDF, 0x40, 0x87, 0x1B, + 0x29, 0x88, 0xF6, 0x36, 0xE4, 0x67, 0xBB, 0xB8, 0xCD, 0xAC, 0x0F, 0x1A, 0xEE, 0xCA, 0xE0, 0x8C, 0x1E, 0x3E, 0xAE, 0xF2, + 0x75, 0x86, 0x89, 0x25, 0xCA, 0x2B, 0xEE, 0x85, 0xE2, 0x6B, 0x52, 0x0D, 0xF3, 0xF0, 0x7F, 0x4F, 0x9C, 0xE3, 0x5D, 0x34, + 0x33, 0x43, 0x7F, 0xEE, 0x12, 0x17, 0x89, 0xE9, 0x1F, 0x7D, 0x00, 0x5F, 0x9F, 0xCD, 0x94, 0x98, 0x46, 0x39, 0x77, 0xEB, + 0x12, 0x69, 0x84, 0xD8, 0x5E, 0x40, 0xB4, 0x62, 0xF7, 0x65, 0x7B, 0xE6, 0xBC, 0xAB, 0x27, 0xF8, 0xB0, 0x3A, 0x2F, 0xBF, + 0xA5, 0xF6, 0x88, 0x00, 0x5E, 0x0D, 0x33, 0x76, 0x50, 0x61, 0x46, 0x43, 0x71, 0x0E, 0x67, 0x4A, 0x83, 0xBE, 0x39, 0xFE, + 0xB3, 0xA8, 0x06, 0xE7, 0x12, 0x0A, 0xD1, 0xE0, 0x7E, 0x59, 0x99, 0x30, 0x2D, 0xD4, 0x31, 0x53, 0x22, 0x0F, 0xF1, 0x31, + 0x13, 0x4F, 0x18, 0x42, 0xF9, 0x0C, 0x09, 0x72, 0x28, 0x95, 0x3E, 0x11, 0x12, 0x49, 0xB8, 0x54, 0xB1, 0x6A, 0x36, 0x00, + 0xAB, 0xBE, 0x38, 0x31, 0xC1, 0x8C, 0xF0, 0xA3, 0x4E, 0x15, 0xAF, 0x14, 0x53, 0xD8, 0x14, 0x00, 0xC3, 0x53, 0xA0, 0x46, + 0x2B, 0x9A, 0x3F, 0x15, 0xB1, 0x56, 0x70, 0x61, 0x6F, 0x48, 0x4B, 0x63, 0x71, 0xEB, 0x3E, 0x1A, 0x1A, 0x3C, 0xF1, 0xA2, + 0x92, 0x46, 0xAE, 0xAA, 0xB7, 0x4B, 0xC9, 0x99, 0x83, 0x0A, 0xE3, 0xC4, 0x70, 0xB8, 0xA6, 0x4A, 0x8C, 0x04, 0xC0, 0x88, + 0x04, 0x28, 0x82, 0xAC, 0x78, 0x87, 0x6D, 0x56, 0x8E, 0xB7, 0xCA, 0xBD, 0xF0, 0x07, 0xC6, 0x98, 0x05, 0x69, 0x09, 0x58, + 0x32, 0x40, 0x9E, 0x7B, 0xDB, 0x61, 0x6B, 0xF8, 0x0B, 0x08, 0xE3, 0x4B, 0x88, 0x31, 0x4D, 0x04, 0x02, 0xE1, 0x03, 0xEA, + 0xDA, 0x9F, 0x63, 0xDB, 0x0D, 0x05, 0xEB, 0x5E, 0x54, 0x69, 0x40, 0x1A, 0x01, 0x31, 0x29, 0x5F, 0x32, 0x9A, 0x58, 0x4A, + 0xB9, 0xA1, 0xFD, 0xD3, 0xE5, 0x6D, 0xFE, 0xFB, 0x6F, 0xCE, 0x42, 0x1F, 0x3F, 0xC8, 0xDA, 0x2B, 0x3F, 0xAC, 0x77, 0x3C, + 0x5F, 0x5F, 0x25, 0xFC, 0x5C, 0x60, 0x1A, 0xB0, 0xF2, 0x2C, 0xD0, 0x39, 0x0A, 0x18, 0x64, 0x4B, 0x4E, 0x4A, 0x75, 0x1D, + 0x69, 0xCB, 0x4B, 0x8F, 0x3A, 0xD1, 0x73, 0xA6, 0x62, 0x3E, 0xF4, 0xBF, 0x37, 0x2B, 0xCB, 0xFB, 0xCE, 0xB5, 0x1B, 0xB0, + 0xC6, 0x2D, 0x94, 0xC6, 0x8A, 0xEB, 0xE8, 0x62, 0xB5, 0x13, 0xA0, 0xDF, 0xC3, 0x11, 0x5F, 0xE3, 0xB2, 0xA2, 0xD3, 0x85, + 0xA6, 0x16, 0x74, 0x9C, 0x96, 0x21, 0x41, 0xCE, 0x86, 0x41, 0x9A, 0x68, 0x88, 0x33, 0x03, 0x05, 0xA8, 0x64, 0x84, 0x63, + 0x83, 0xBC, 0xD5, 0x78, 0x2A, 0x49, 0xDD, 0xBC, 0x08, 0xA8, 0xA5, 0x33, 0x7E, 0x4C, 0x75, 0xD3, 0x9F, 0x98, 0xA2, 0x47, + 0xE7, 0xC3, 0xD0, 0x85, 0x04, 0x7C, 0x1E, 0x3F, 0x81, 0x12, 0x04, 0x0D, 0x52, 0x39, 0x6E, 0x02, 0x40, 0xAB, 0x14, 0xE1, + 0x74, 0x8D, 0x8C, 0x1D, 0x52, 0x57, 0x5C, 0x8F, 0xCE, 0x89, 0x06, 0xF1, 0xC0, 0x14, 0x2F, 0x96, 0x88, 0x8E, 0x65, 0x95, + 0x01, 0x57, 0x3E, 0xE2, 0x13, 0xC9, 0x2A, 0x63, 0xC0, 0x36, 0xF6, 0xC1, 0x70, 0xA2, 0x4E, 0x1C, 0x80, 0x77, 0x10, 0xED, + 0xCC, 0x37, 0x3D, 0xB0, 0x16, 0x5A, 0xD9, 0xF1, 0xF0, 0x77, 0xEE, 0x2A, 0x8C, 0x9F, 0x1D, 0x28, 0x1C, 0x7A, 0xDB, 0xC8, + 0x64, 0xAF, 0x22, 0xD3, 0xDB, 0x39, 0x1E, 0x31, 0xCC, 0x58, 0xB0, 0xED, 0x1A, 0xA9, 0xE4, 0x3C, 0x3E, 0xC5, 0xC7, 0xF6, + 0xDC, 0xFF, 0xE7, 0x20, 0x2D, 0x1D, 0x08, 0xE3, 0x1E, 0x8A, 0x93, 0xAC, 0xEC, 0xC0, 0x87, 0x90, 0xFA, 0x14, 0xCF, 0xD0, + 0x02, 0x57, 0xD1, 0xEC, 0x46, 0x79, 0x8F, 0x51, 0x04, 0x16, 0x8C, 0x35, 0x5C, 0xF2, 0xC6, 0x10, 0xCD, 0xEB, 0x1D, 0x68, + 0x3E, 0xC6, 0x1C, 0x13, 0xC9, 0x5A, 0x7E, 0x5D, 0xF7, 0xF7, 0x65, 0xFC, 0x2D, 0x67, 0x13, 0x5C, 0x44, 0xAC, 0x5A, 0x1A, + 0x4F, 0xC6, 0x26, 0xD8, 0xFE, 0x5A, 0x43, 0xCC, 0xAC, 0xC4, 0x85, 0x96, 0x47, 0x82, 0x5B, 0x92, 0x4B, 0xD6, 0xD6, 0x72, + 0xC9, 0x29, 0x54, 0x5D, 0xFB, 0x65, 0x14, 0x79, 0xBF, 0xC5, 0x39, 0x00, 0xCA, 0x2A, 0x00, 0xE9, 0xFD, 0xC5, 0x84, 0xC0, + 0xA7, 0x8E, 0x25, 0xE3, 0x10, 0x08, 0x3C, 0x31, 0x17, 0x88, 0x96, 0xF9, 0x76, 0xA6, 0xDE, 0x60, 0xA6, 0x87, 0xF6, 0xD2, + 0x15, 0xBA, 0xB8, 0x6B, 0x8C, 0xC7, 0xE8, 0x12, 0x80, 0x1C, 0x19, 0xA7, 0x06, 0x8A, 0xDB, 0xF6, 0x9F, 0xA6, 0x86, 0x1B, + 0x30, 0xB3, 0x06, 0x19, 0xA8, 0x17, 0x21, 0xA5, 0x24, 0x09, 0xF7, 0xE7, 0xEA, 0xEC, 0x31, 0x9C, 0x24, 0xCC, 0x12, 0xF1, + 0x3F, 0xAF, 0xB4, 0xBC, 0x22, 0xE8, 0x1E, 0x62, 0xF7, 0x55, 0x2A, 0x67, 0xE5, 0x86, 0xF2, 0x61, 0x1C, 0x4E, 0x0B, 0xAC, + 0x25, 0x68, 0x4F, 0x50, 0xFC, 0xC1, 0xDC, 0x82, 0x07, 0xCA, 0x35, 0x3B, 0x51, 0x65, 0xDE, 0xD8, 0x79, 0x5B, 0x1E, 0x35, + 0xF4, 0xE5, 0x39, 0x23, 0x44, 0x8E, 0xBF, 0xB6, 0xF2, 0xA4, 0x68, 0x14, 0x66, 0x71, 0xD6, 0xB5, 0xB3, 0x53, 0xE9, 0x01, + 0x34, 0x75, 0x5D, 0x5B, 0x63, 0xB2, 0xD9, 0xE8, 0xAD, 0x02, 0xA3, 0xFE, 0xE3, 0xE7, 0x52, 0x6A, 0xFA, 0xC5, 0x42, 0xAA, + 0x03, 0xB6, 0x4A, 0x5A, 0xEF, 0x54, 0xF3, 0x4B, 0xBA, 0xE8, 0x70, 0x27, 0xEE, 0xCF, 0xBE, 0xB1, 0xD8, 0xEE, 0xA4, 0x5B, + 0x8D, 0x85, 0x99, 0xE7, 0xDF, 0xE5, 0x79, 0xD5, 0x6F, 0xC7, 0x1B, 0x8C, 0xF8, 0xA8, 0x53, 0x3C, 0x70, 0x84, 0x91, 0xEC, + 0xE0, 0xB0, 0x33, 0x91, 0x38, 0xC4, 0x53, 0x9C, 0xF9, 0x46, 0x9D, 0x38, 0xD8, 0x53, 0xF3, 0xCA, 0x02, 0x69, 0xB2, 0x67, + 0x85, 0xC1, 0x43, 0x4A, 0xDC, 0xE4, 0x1A, 0xD8, 0x8F, 0x85, 0xFB, 0x5A, 0x40, 0xA3, 0x80, 0x25, 0xBE, 0x31, 0x82, 0x01, + 0xFC, 0xAC, 0xF3, 0x6F, 0x88, 0x04, 0x23, 0x7A, 0x29, 0x5B, 0x60, 0x91, 0x37, 0xC5, 0x07, 0x0D, 0x21, 0x63, 0x53, 0xE9, + 0x3B, 0x6F, 0xAD, 0x83, 0x76, 0x75, 0xEB, 0xF9, 0xED, 0xAF, 0x3B, 0xFF, 0xDF, 0xEE, 0xA3, 0xC4, 0x7C, 0x1D, 0x6E, 0xF5, + 0x32, 0x4A, 0x36, 0x44, 0x62, 0x0A, 0x94, 0x34, 0xFC, 0xF8, 0x09, 0x64, 0xA0, 0x83, 0x3C, 0x14, 0x34, 0x54, 0xD0, 0x20, + 0x75, 0xD9, 0x2C, 0xC4, 0x8A, 0x7A, 0x7C, 0x99, 0x43, 0x89, 0xC6, 0x03, 0xB9, 0xB9, 0xD8, 0x4B, 0x09, 0x9F, 0x35, 0x60, + 0xD0, 0x9E, 0x53, 0xE2, 0x4E, 0xDA, 0x95, 0x69, 0x37, 0xBB, 0x3C, 0x37, 0xD1, 0xA1, 0x9D, 0x8A, 0xF3, 0xDB, 0x7C, 0xC7, + 0xD8, 0xF4, 0xA6, 0x44, 0xEB, 0x3B, 0x3F, 0xCC, 0x79, 0x2F, 0x02, 0xC2, 0xF3, 0xD3, 0xAC, 0x0A, 0xC0, 0xD4, 0x31, 0xD7, + 0x33, 0xEF, 0x30, 0x19, 0xEE, 0x65, 0x0A, 0xD2, 0x77, 0xF5, 0xE1, 0xC7, 0xF1, 0x0A, 0xDF, 0x25, 0x2A, 0x2E, 0x6D, 0x1F, + 0x78, 0x96, 0x2A, 0xF7, 0xF0, 0x4C, 0x81, 0x53, 0x5B, 0xB7, 0xFB, 0x55, 0x6A, 0x38, 0x51, 0xEE, 0x6E, 0x87, 0xFD, 0xF7, + 0xF7, 0xF7, 0x8E, 0x83, 0xA9, 0xD8, 0x10, 0xEC, 0xB1, 0x6E, 0xF6, 0x66, 0x47, 0x96, 0x0D, 0xCC, 0x8B, 0x94, 0x1A, 0x67, + 0x0C, 0xE2, 0x42, 0x9C, 0x35, 0xD5, 0x01, 0xD8, 0x2E, 0x06, 0x3F, 0x5D, 0x79, 0xA3, 0xCF, 0x9B, 0x88, 0x41, 0x0B, 0x10, + 0xBD, 0xDA, 0xA2, 0x8F, 0x6E, 0xF2, 0x73, 0x4D, 0xA0, 0x0D, 0xBE, 0x6A, 0xAC, 0x8A, 0xE7, 0x7D, 0x99, 0xD5, 0x47, 0x9C, + 0x4C, 0x51, 0x32, 0x57, 0xED, 0xB6, 0xCA, 0x88, 0xAD, 0x9C, 0xBC, 0xCF, 0x9D, 0x18, 0x5A, 0xFA, 0xE6, 0xB6, 0xF6, 0xEE, + 0x7E, 0xFC, 0x06, 0x18, 0xA9, 0x68, 0xF8, 0x8B, 0xFA, 0x55, 0x44, 0x09, 0x06, 0x72, 0xFE, 0xFE, 0x7F, 0xFD, 0x39, 0xDC, + 0xA6, 0x9E, 0x69, 0x97, 0xBA, 0xE4, 0x77, 0xA8, 0xC2, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0xFF, 0x1C, 0x46, 0xD5, 0xC2, 0x8A, + 0x66, 0x57, 0xE7, 0x79, 0xEE, 0xA8, 0xFF, 0xFF, 0x5D, 0xA2, 0xA8, 0xA9, 0xE1, 0x1B, 0x0B, 0x66, 0xD1, 0x42, 0x5A, 0xC2, + 0x73, 0x98, 0xC9, 0x27, 0xF5, 0xBF, 0xE0, 0x94, 0x86, 0x51, 0x4C, 0xB3, 0x97, 0xB3, 0x9F, 0x20, 0x72, 0x17, 0xC1, 0xF0, + 0xF4, 0x97, 0xA1, 0xF7, 0x05, 0xE3, 0x45, 0x80, 0xD3, 0x02, 0xE9, 0x43, 0x01, 0xC8, 0x90, 0x43, 0x2F, 0x0C, 0x50, 0x8A, + 0x26, 0x05, 0xE9, 0x17, 0xCA, 0x2E, 0xE1, 0x57, 0x36, 0xCA, 0xD8, 0x53, 0x07, 0x69, 0x94, 0xAE, 0x31, 0x20, 0x21, 0x37, + 0x09, 0x80, 0x30, 0x62, 0x67, 0x49, 0x9D, 0x8E, 0xB3, 0x5F, 0xE4, 0xD5, 0xD6, 0x67, 0xB0, 0x99, 0xF8, 0xBF, 0x60, 0x56, + 0xAA, 0x03, 0xE0, 0xFD, 0xFC, 0x63, 0x81, 0x39, 0xE5, 0xDA, 0x08, 0xA7, 0x72, 0x82, 0x85, 0xE7, 0xDC, 0x23, 0xF0, 0x82, + 0x63, 0xC7, 0x20, 0xBA, 0x01, 0x6B, 0xA9, 0x57, 0xF8, 0x2A, 0x1D, 0x99, 0x5F, 0x8C, 0xFD, 0x69, 0x72, 0x61, 0x2A, 0x66, + 0xAB, 0x6D, 0xC8, 0x11, 0x2B, 0x2D, 0x16, 0x48, 0x0C, 0x95, 0x97, 0x53, 0x38, 0x6A, 0x95, 0xF5, 0x1E, 0xB2, 0xD0, 0x0C, + 0xBE, 0x2F, 0x18, 0xD0, 0xDF, 0xB4, 0xDB, 0xDA, 0x6A, 0x43, 0x7B, 0xF5, 0x05, 0xF1, 0x7B, 0x6B, 0xBB, 0x4A, 0xFF, 0xBA, + 0xF4, 0x42, 0x92, 0xCB, 0x39, 0xB9, 0xF4, 0x9D, 0xD6, 0x89, 0xAB, 0xDC, 0x38, 0x30, 0xE3, 0xC5, 0x44, 0xB0, 0x23, 0xC3, + 0xC9, 0x26, 0x0C, 0xCC, 0x7B, 0xC2, 0xE8, 0xC9, 0x59, 0xCC, 0x56, 0x80, 0x1C, 0x01, 0x71, 0x72, 0x5C, 0xF5, 0x90, 0x06, + 0x86, 0x6F, 0x03, 0x9B, 0xD9, 0xFD, 0xFF, 0x6C, 0x6B, 0x6F, 0xE2, 0x8D, 0xF8, 0xED, 0x1A, 0x88, 0x8C, 0x97, 0xD3, 0x2F, + 0xFC, 0x83, 0xAC, 0x09, 0xC6, 0x55, 0xF2, 0xEF, 0x52, 0x9E, 0xE0, 0xDC, 0x18, 0x30, 0x83, 0x60, 0xA8, 0xCD, 0x5E, 0x0A, + 0xF6, 0xEE, 0xE9, 0x82, 0x59, 0xBB, 0x5D, 0xA5, 0x43, 0x70, 0x7C, 0x06, 0xB0, 0xE6, 0xCB, 0xD0, 0x5F, 0xA0, 0x95, 0xC2, + 0x8B, 0x76, 0x86, 0x68, 0xA1, 0xAA, 0x8A, 0x7D, 0xB5, 0x73, 0x5E, 0x32, 0xE1, 0x5B, 0x28, 0xCF, 0xD2, 0x6A, 0xFD, 0x7D, + 0x28, 0xE9, 0xBD, 0x55, 0xEC, 0x3B, 0x2F, 0x5A, 0xE6, 0xA8, 0x3D, 0xAD, 0x01, 0x7D, 0x04, 0x7C, 0xE1, 0x51, 0x96, 0xDE, + 0x82, 0x19, 0x25, 0x80, 0x40, 0xF2, 0x96, 0xD3, 0x46, 0x63, 0x2D, 0x2B, 0xDD, 0x12, 0x1B, 0x8C, 0x45, 0x30, 0x44, 0x6D, + 0x3A, 0xF0, 0x77, 0x4A, 0xD3, 0x7F, 0xF8, 0xAF, 0x80, 0xCE, 0xE8, 0xEC, 0x35, 0xB5, 0xF0, 0x63, 0x5E, 0x5F, 0xD9, 0x76, + 0xA7, 0x22, 0xED, 0xD8, 0x57, 0x19, 0x05, 0x14, 0xB5, 0x30, 0xCC, 0x95, 0x0B, 0x0F, 0x55, 0xC2, 0x53, 0x7D, 0xEE, 0x2C, + 0x3E, 0x8C, 0x50, 0x57, 0x33, 0x9C, 0xD9, 0xE2, 0xDE, 0x9E, 0xDF, 0x17, 0x5F, 0xFC, 0x4B, 0x76, 0x5F, 0x3C, 0xBC, 0x6A, + 0x28, 0xB3, 0x2E, 0x5B, 0x33, 0x36, 0x2E, 0x43, 0xFA, 0x54, 0x34, 0x63, 0x2F, 0xE3, 0x69, 0xFE, 0x7A, 0xC9, 0x7E, 0xBA, + 0x02, 0x54, 0x23, 0x5E, 0xFB, 0x35, 0xD8, 0xD1, 0x97, 0x90, 0xDF, 0x6B, 0x3A, 0x3E, 0x75, 0x39, 0xE9, 0xEA, 0x39, 0xC3, + 0x5B, 0x1F, 0x4D, 0x1D, 0xDC, 0xB8, 0x97, 0x8C, 0x82, 0x71, 0x35, 0x69, 0xB5, 0x58, 0x1A, 0xC3, 0x5A, 0x1E, 0x66, 0x31, + 0xE1, 0x67, 0xFE, 0x9E, 0x34, 0xB6, 0x70, 0x85, 0x56, 0xF1, 0xDE, 0x0E, 0xF8, 0x78, 0x95, 0x86, 0x54, 0xFC, 0xF0, 0x04, + 0x72, 0x47, 0x56, 0xFD, 0xA3, 0x04, 0x1A, 0x79, 0x38, 0x8F, 0x57, 0x4D, 0xB1, 0xC1, 0x41, 0x48, 0x3C, 0x3E, 0xCE, 0xAE, + 0x20, 0x27, 0xD8, 0x8F, 0x05, 0x1C, 0x14, 0xDB, 0xD0, 0xF8, 0xD7, 0xD0, 0x34, 0x92, 0xCA, 0x8A, 0xD7, 0xFE, 0x1B, 0x7B, + 0xBF, 0x79, 0x1A, 0xEA, 0x84, 0x4F, 0x80, 0xE0, 0xF5, 0xBB, 0xF2, 0xCF, 0x36, 0x7B, 0x4F, 0x61, 0x67, 0x58, 0x71, 0x31, + 0xA2, 0x2E, 0xBB, 0xF4, 0x97, 0xED, 0xE3, 0x74, 0x3A, 0x3B, 0x5B, 0xF6, 0x1D, 0x3C, 0x20, 0xF5, 0x6F, 0x88, 0x44, 0xE1, + 0x16, 0x8E, 0xCE, 0xA7, 0x9B, 0x40, 0x09, 0xB8, 0xC6, 0xAF, 0xE5, 0x55, 0xA5, 0x85, 0xA6, 0xF5, 0x17, 0x2F, 0xE4, 0x8B, + 0xBE, 0x3C, 0x41, 0x3F, 0x28, 0xAC, 0x9F, 0xC0, 0x83, 0x35, 0x58, 0xB9, 0xFF, 0xFE, 0xE9, 0x91, 0x73, 0x49, 0x01, 0xE2, + 0x27, 0x50, 0x10, 0x21, 0x3B, 0x04, 0xD0, 0x06, 0x37, 0xAA, 0xE3, 0x10, 0xB0, 0xA7, 0x80, 0x51, 0x34, 0xED, 0xDA, 0xA1, + 0x2A, 0x7B, 0x4D, 0xD8, 0x95, 0x07, 0x0F, 0x0E, 0x44, 0xC2, 0x91, 0x79, 0x4A, 0x6B, 0x6B, 0xAC, 0x66, 0xE4, 0x32, 0x55, + 0xE8, 0x4F, 0xBD, 0xA3, 0x99, 0x68, 0x81, 0xF5, 0x03, 0x33, 0x8E, 0xCE, 0xAF, 0x8E, 0xB0, 0x7D, 0x47, 0xA7, 0xF2, 0xF7, + 0x0E, 0x13, 0xEB, 0x2D, 0xF9, 0x37, 0xEB, 0x5C, 0x1D, 0xC5, 0xDA, 0xF6, 0x95, 0x24, 0xBD, 0x48, 0xB6, 0x8B, 0xF8, 0xBA, + 0x2C, 0x27, 0x8B, 0x07, 0x2F, 0xC6, 0x99, 0xF0, 0x9A, 0xEB, 0x9F, 0xD6, 0xD7, 0xB1, 0xB2, 0x49, 0x5E, 0x86, 0xAF, 0xF3, + 0x8D, 0xC4, 0x53, 0x17, 0xFE, 0xA3, 0xF4, 0xAB, 0xBA, 0x17, 0xE2, 0xFE, 0x78, 0x74, 0x99, 0xA2, 0x5F, 0xC1, 0xBD, 0x28, + 0x18, 0xD6, 0xE8, 0x82, 0x12, 0x61, 0xCA, 0x8E, 0x5A, 0x89, 0xAA, 0x22, 0x87, 0x51, 0x8A, 0x5D, 0x27, 0xA2, 0x32, 0x6E, + 0x7C, 0x1F, 0x59, 0x60, 0xFC, 0x88, 0x18, 0x43, 0x2B, 0x31, 0xD4, 0x30, 0x7D, 0x2E, 0x6E, 0x8D, 0x43, 0x38, 0xCB, 0x8F, + 0xCE, 0xE8, 0xC7, 0xDE, 0x5A, 0xED, 0xB4, 0xBE, 0xEC, 0xAF, 0xC3, 0x93, 0x93, 0x80, 0xA1, 0x97, 0x7C, 0xE9, 0xE4, 0x5A, + 0xE5, 0x96, 0x64, 0xFE, 0xAD, 0xAB, 0x0C, 0xA7, 0x0F, 0x6A, 0x0B, 0x44, 0xF6, 0x9C, 0xE8, 0x42, 0x5B, 0xF3, 0xF6, 0xD4, + 0x92, 0xB7, 0x04, 0xE0, 0x6B, 0xB3, 0x83, 0x54, 0xF7, 0x9D, 0x05, 0xDA, 0x05, 0xF0, 0xAE, 0xF5, 0x13, 0xA2, 0x77, 0x21, + 0x64, 0xD8, 0xAA, 0xDD, 0x57, 0x97, 0xCD, 0x0E, 0x27, 0x97, 0x8D, 0x08, 0x14, 0x3F, 0x77, 0xB6, 0x1A, 0xD5, 0x73, 0xD9, + 0x56, 0x96, 0xB9, 0x5E, 0x20, 0xAE, 0xAF, 0x54, 0xC7, 0x19, 0xEE, 0x72, 0x8D, 0xA5, 0xD4, 0xAF, 0xD7, 0x2B, 0x54, 0x02, + 0x79, 0x3A, 0x6D, 0x54, 0xBF, 0xE4, 0x25, 0xE2, 0xC0, 0x78, 0xF2, 0x72, 0x06, 0xA8, 0x9E, 0x41, 0x26, 0xDF, 0x28, 0x55, + 0xF6, 0xBE, 0x53, 0x97, 0x45, 0x52, 0x95, 0xE5, 0xE7, 0xED, 0xF4, 0xF4, 0x06, 0x1D, 0xD5, 0xB7, 0xB3, 0x97, 0xE4, 0xC2, + 0xDA, 0x78, 0x9D, 0xF5, 0xEA, 0xFA, 0x2D, 0xE8, 0x1F, 0x8E, 0xEC, 0x93, 0x1D, 0x28, 0xA8, 0x44, 0xE2, 0xC3, 0x0B, 0x4C, + 0xFE, 0xFC, 0x16, 0x4A, 0x71, 0x36, 0x96, 0x77, 0x64, 0xD6, 0x38, 0xC9, 0x36, 0xB5, 0xF4, 0xA3, 0x96, 0x88, 0xDF, 0x09, + 0x2C, 0x62, 0x9F, 0x5F, 0x1F, 0x1B, 0x54, 0x4D, 0x12, 0xBA, 0x87, 0xCD, 0x03, 0x76, 0xBA, 0x8B, 0x52, 0x17, 0x95, 0x3A, + 0xA7, 0xD4, 0xFB, 0x5D, 0x6F, 0xDF, 0xAD, 0xAF, 0x42, 0x76, 0xA1, 0x39, 0x13, 0xF9, 0xE8, 0xCC, 0xD9, 0x11, 0x3B, 0x02, + 0x20, 0x93, 0x0D, 0x6C, 0xFE, 0xA4, 0x73, 0xB8, 0xEE, 0x17, 0x4C, 0x39, 0x8E, 0x1C, 0x63, 0x09, 0x78, 0x9F, 0x47, 0x7C, + 0xFF, 0x56, 0x5F, 0x1B, 0xF2, 0x31, 0x2E, 0x25, 0x5F, 0x85, 0x2E, 0x77, 0x4B, 0x7F, 0xAE, 0xA7, 0xF8, 0x67, 0xE8, 0x33, + 0xF9, 0xD0, 0xD7, 0x56, 0x10, 0x12, 0x66, 0x98, 0xE9, 0xB5, 0xC7, 0xB8, 0xF1, 0x9D, 0xE0, 0x94, 0xA1, 0x62, 0xCA, 0x46, + 0x4D, 0xA8, 0x28, 0xD3, 0x74, 0x46, 0x4B, 0x83, 0x2F, 0xA9, 0xC3, 0x72, 0x83, 0xF6, 0x48, 0xC9, 0x38, 0x3A, 0x86, 0x17, + 0xE0, 0x5A, 0xA2, 0xCF, 0x57, 0xAB, 0xE1, 0x88, 0x02, 0x06, 0xD1, 0xEA, 0x6C, 0xEB, 0x31, 0xCD, 0x61, 0xED, 0x4C, 0xB3, + 0xE7, 0x62, 0x72, 0xF3, 0x03, 0x07, 0x4A, 0x73, 0xB1, 0x01, 0xB8, 0xC7, 0x28, 0x72, 0xD3, 0xB1, 0x9D, 0x0E, 0xF8, 0xC2, + 0xD6, 0x4C, 0x4F, 0xAC, 0x3D, 0xEB, 0xFD, 0xE2, 0x9F, 0xC9, 0x8F, 0xE2, 0x5A, 0x60, 0x00, 0x41, 0xEA, 0xEC, 0x37, 0xA6, + 0xE4, 0x40, 0x38, 0x32, 0xBA, 0x4A, 0x9E, 0xF0, 0x2A, 0xE4, 0x39, 0x06, 0x48, 0xEF, 0xA1, 0x47, 0xE2, 0x2B, 0x91, 0x19, + 0x65, 0xCB, 0x51, 0x23, 0xDA, 0x2A, 0x31, 0x53, 0xDF, 0x1C, 0xF1, 0x29, 0xB0, 0xE5, 0xED, 0x93, 0x41, 0x2B, 0x89, 0x17, + 0x98, 0xBC, 0x1E, 0x6A, 0x8A, 0x04, 0x83, 0xFF, 0x55, 0x5D, 0xBE, 0xBB, 0x25, 0x40, 0x52, 0xA4, 0x58, 0x2A, 0xA2, 0x81, + 0x0F, 0x31, 0x08, 0xEF, 0x54, 0x5C, 0x84, 0x78, 0x11, 0x84, 0x43, 0x5E, 0xD4, 0xCF, 0x06, 0xEB, 0x0D, 0xFF, 0x9E, 0x7F, + 0x63, 0x2E, 0xD7, 0x5A, 0xFC, 0xEC, 0x9A, 0x2D, 0x5A, 0xBE, 0x77, 0x6B, 0x62, 0x12, 0x96, 0x26, 0xFC, 0xDE, 0xE4, 0x4A, + 0xF1, 0x25, 0x05, 0xD5, 0x87, 0x24, 0xE3, 0x3E, 0xF5, 0x0A, 0x7D, 0xFE, 0x8A, 0x6C, 0xCB, 0x8A, 0xE6, 0x43, 0xF2, 0x91, + 0x17, 0xD7, 0xAD, 0x18, 0x07, 0xF0, 0xD9, 0x3E, 0xF9, 0xC9, 0x70, 0xA8, 0x17, 0x4B, 0x65, 0x1C, 0x1B, 0x23, 0xE0, 0x0D, + 0x2B, 0x62, 0xBD, 0x34, 0x18, 0x2A, 0x33, 0x6B, 0x7D, 0x43, 0x6F, 0xE9, 0xC5, 0xDB, 0x09, 0xBB, 0x6A, 0x09, 0xCE, 0xAC, + 0xC6, 0x6F, 0xF7, 0x01, 0x68, 0x49, 0x9D, 0x7F, 0xF5, 0xD4, 0x7C, 0x04, 0x73, 0xD1, 0x16, 0x62, 0x95, 0x9B, 0x0E, 0x5C, + 0x60, 0x12, 0xCD, 0x51, 0x97, 0x60, 0x08, 0x72, 0xA3, 0x19, 0xF4, 0x85, 0xF1, 0x37, 0x05, 0xD2, 0x96, 0x57, 0xC5, 0x45, + 0x96, 0x6A, 0x65, 0xC1, 0x4E, 0x99, 0xFD, 0x80, 0x50, 0x99, 0x5E, 0x8E, 0x62, 0x56, 0x6F, 0x4D, 0x93, 0xBD, 0xF8, 0xE3, + 0x02, 0x5F, 0x2E, 0x69, 0x12, 0x35, 0x3D, 0xC4, 0x40, 0xEC, 0x46, 0x43, 0x74, 0x32, 0x9B, 0x7C, 0x1D, 0x04, 0xBC, 0x46, + 0x3B, 0x89, 0xFC, 0xF5, 0xC3, 0x52, 0xAD, 0xC3, 0xD3, 0x4B, 0x0E, 0xA2, 0xC8, 0x64, 0x13, 0x70, 0x35, 0x8F, 0x3C, 0xA2, + 0x0B, 0x5A, 0xE4, 0x1B, 0xFE, 0x37, 0x1A, 0xC5, 0xA4, 0xEC, 0xFD, 0x95, 0xB6, 0x39, 0xF9, 0x31, 0x41, 0xDB, 0x61, 0x87, + 0x45, 0x13, 0x14, 0xCC, 0x06, 0xE8, 0xD0, 0x51, 0xEC, 0x70, 0x3D, 0xA3, 0x87, 0x5A, 0xDF, 0xED, 0xD2, 0x37, 0xB7, 0x0A, + 0x0A, 0x78, 0xA6, 0x70, 0x99, 0xB4, 0xAD, 0x40, 0x30, 0x17, 0x3E, 0x9D, 0xFA, 0x7C, 0x36, 0x3D, 0xAF, 0xC9, 0x76, 0xFA, + 0xB4, 0xBF, 0x5F, 0xCB, 0x51, 0x16, 0x64, 0xCA, 0xF4, 0xFF, 0x7F, 0x0B, 0x28, 0xA1, 0xCD, 0x90, 0x8B, 0x78, 0x28, 0xA1, + 0x4F, 0x41, 0x4D, 0xCF, 0xCB, 0x01, 0x5F, 0x85, 0xB4, 0x1D, 0x89, 0x5D, 0xB5, 0xB0, 0x46, 0x30, 0x00, 0x0A, 0x9E, 0x7D, + 0xFD, 0xB0, 0x78, 0xE5, 0xA7, 0xEA, 0xA6, 0x88, 0x74, 0x31, 0x1C, 0xF5, 0x4B, 0x4C, 0x3E, 0x7D, 0x58, 0xAC, 0x58, 0xBA, + 0x4B, 0xFC, 0xF2, 0x5E, 0x32, 0x80, 0x3E, 0xAA, 0x03, 0x52, 0xCE, 0x6D, 0x63, 0x7B, 0x0F, 0xE4, 0x43, 0x6F, 0x6B, 0x48, + 0x9A, 0x33, 0x09, 0x0B, 0xA2, 0xDB, 0x53, 0x4D, 0xF2, 0xEE, 0x36, 0xBF, 0x26, 0x7D, 0xF7, 0x0D, 0x40, 0x30, 0x3F, 0xAB, + 0x83, 0x52, 0xFF, 0xBD, 0x98, 0x80, 0x79, 0x16, 0xA3, 0x2F, 0x3A, 0x82, 0x4B, 0x19, 0xD7, 0xE2, 0x0C, 0x6D, 0xD0, 0x24, + 0x76, 0xA2, 0x10, 0xC2, 0x59, 0x00, 0xF8, 0x13, 0x76, 0x81, 0x90, 0x33, 0x67, 0x11, 0xAD, 0xD4, 0xF9, 0x4C, 0x3D, 0x81, + 0x04, 0x48, 0x61, 0xDB, 0x27, 0xA4, 0xA0, 0xBC, 0xC5, 0x82, 0xAA, 0xC1, 0x78, 0x4F, 0x2F, 0xFB, 0xD7, 0xCC, 0xD1, 0xB7, + 0xC1, 0xA8, 0xBB, 0x93, 0xCD, 0xA3, 0x28, 0xD5, 0xF5, 0xC1, 0xC3, 0x59, 0xA5, 0x9F, 0xBA, 0x4D, 0xB5, 0x2B, 0x50, 0x8D, + 0xE7, 0xC2, 0xAC, 0x9E, 0x56, 0x1F, 0x31, 0xC3, 0xA0, 0x95, 0x78, 0xAB, 0x17, 0x7E, 0x18, 0x34, 0x0B, 0xCA, 0xB6, 0xB2, + 0xD5, 0xC1, 0xA5, 0xA5, 0x96, 0xC9, 0x55, 0xA5, 0x11, 0x53, 0x5B, 0x57, 0x65, 0x4B, 0xF8, 0x9B, 0x56, 0xA4, 0x91, 0xD1, + 0x53, 0x54, 0xEB, 0xD3, 0xEA, 0x80, 0x19, 0x21, 0xA3, 0xCA, 0xA9, 0xF3, 0x97, 0x9E, 0x9A, 0xF5, 0x3F, 0xC8, 0xC2, 0x0C, + 0x6F, 0xA5, 0x62, 0xBB, 0x1C, 0xCE, 0x36, 0x5D, 0x64, 0xE7, 0xD2, 0x65, 0x66, 0x86, 0x2E, 0xF6, 0x0B, 0xE6, 0x2F, 0x1D, + 0xEC, 0x66, 0x45, 0xBA, 0x02, 0xD1, 0xDB, 0x79, 0xBF, 0xA8, 0x89, 0x8A, 0x92, 0x20, 0x13, 0x5A, 0x6D, 0x65, 0x73, 0xE7, + 0x07, 0x67, 0xFC, 0x29, 0x72, 0x5E, 0x93, 0xCF, 0xE3, 0xB0, 0xAA, 0x7D, 0x87, 0x30, 0x81, 0xD7, 0xA2, 0x24, 0x1A, 0xB6, + 0x8F, 0x77, 0x82, 0x0E, 0xB0, 0x27, 0x38, 0x88, 0x6F, 0xBC, 0x92, 0x6D, 0x2E, 0xE1, 0x15, 0xB7, 0xC9, 0xCF, 0x42, 0x5A, + 0x9D, 0x85, 0x02, 0x6B, 0xAF, 0xCB, 0x4E, 0x1C, 0xA8, 0x88, 0x29, 0xA3, 0xE6, 0xC3, 0xE7, 0xAD, 0x1B, 0xAC, 0x59, 0xBB, + 0x92, 0x65, 0x88, 0x48, 0x7F, 0x51, 0xA4, 0xCB, 0xF8, 0x83, 0x50, 0x3D, 0xDC, 0x10, 0xD3, 0x6E, 0x6C, 0xC9, 0xC3, 0x80, + 0x73, 0xE2, 0x04, 0xBF, 0x85, 0x1F, 0xA2, 0x60, 0xB6, 0xB4, 0xCC, 0x26, 0x67, 0xD8, 0xA4, 0x24, 0xF4, 0x1B, 0x14, 0xEF, + 0x06, 0x21, 0xBA, 0xF4, 0x5D, 0xBC, 0xEB, 0x07, 0x63, 0x9B, 0x06, 0xF1, 0xB7, 0xA1, 0xDA, 0x01, 0x24, 0x43, 0x7E, 0xE5, + 0xF7, 0x42, 0xF5, 0xCE, 0x50, 0x90, 0x8D, 0x4F, 0x8F, 0x3D, 0x15, 0x16, 0x23, 0xC1, 0xF4, 0xA6, 0x12, 0xB5, 0x8A, 0x5B, + 0xB9, 0x9E, 0xF5, 0xB3, 0x92, 0x7A, 0x1A, 0xEB, 0xAB, 0x12, 0x3B, 0xC2, 0x30, 0xC7, 0x14, 0xA5, 0x5F, 0xDB, 0x8C, 0xE2, + 0x57, 0xF4, 0x11, 0xE3, 0x1F, 0x3A, 0x53, 0x24, 0x16, 0x8A, 0x83, 0x22, 0x3B, 0xD3, 0x72, 0xAB, 0x2A, 0x7D, 0xE3, 0x83, + 0xE2, 0x1D, 0x47, 0x43, 0x8A, 0xF7, 0x15, 0xB1, 0x82, 0xDB, 0x35, 0x9B, 0x45, 0xB7, 0x78, 0x57, 0xD6, 0x29, 0x8D, 0xD4, + 0xA2, 0x4A, 0x59, 0x55, 0x44, 0xB2, 0xF0, 0x3F, 0xA8, 0x1F, 0x76, 0x06, 0x68, 0x95, 0x86, 0x8C, 0x9D, 0xBE, 0x49, 0x8C, + 0x72, 0x55, 0x6D, 0xED, 0x03, 0xFB, 0x2F, 0x18, 0xAD, 0xDA, 0x02, 0x0C, 0x29, 0xB3, 0x5E, 0xA4, 0x97, 0xD4, 0x7E, 0x63, + 0x3F, 0xBB, 0x8B, 0x0E, 0xA2, 0xDC, 0x04, 0x37, 0x1F, 0xB7, 0xE3, 0xFB, 0x6C, 0x25, 0x02, 0x66, 0x1D, 0x45, 0x17, 0x68, + 0x95, 0xFE, 0x2B, 0x6F, 0x42, 0xB4, 0xC4, 0xE9, 0xC3, 0xB8, 0xA0, 0x15, 0xCE, 0xE9, 0x24, 0x28, 0x28, 0x05, 0x9E, 0x4A, + 0x43, 0xB4, 0x0E, 0x95, 0xAF, 0x56, 0xBC, 0x47, 0x5C, 0xFF, 0xCD, 0x66, 0x8E, 0x1D, 0x3A, 0x58, 0x6B, 0xBE, 0x06, 0xBC, + 0x2F, 0x76, 0x2A, 0xFE, 0x08, 0xA7, 0x08, 0x2B, 0xEA, 0x98, 0x87, 0xCD, 0xC5, 0xB3, 0xF0, 0xCC, 0x4D, 0xBB, 0x38, 0x5E, + 0xDC, 0xFD, 0x17, 0xCA, 0x93, 0x9B, 0x6C, 0xCA, 0xB9, 0x95, 0x60, 0xF0, 0x0E, 0x70, 0x2D, 0xFF, 0xFF, 0xFF, 0x60, 0x40, + 0x0E, 0x0D, 0x0B, 0x66, 0x1E, 0x66, 0x68, 0x07, 0xE3, 0x46, 0xF9, 0xCF, 0x6B, 0xE6, 0x42, 0xFF, 0x07, 0xB8, 0x84, 0x16, + 0x93, 0x25, 0xAC, 0x52, 0x00, 0x01, 0xF8, 0x36, 0xFD, 0x6C, 0x4B, 0xFA, 0x23, 0x0F, 0x53, 0x25, 0xF6, 0x62, 0x99, 0xFD, + 0x80, 0x4D, 0x6D, 0x5B, 0xCA, 0x0D, 0x9A, 0xC1, 0x3E, 0x0C, 0xE8, 0x77, 0xA2, 0xA4, 0x61, 0xB3, 0xC4, 0x18, 0x81, 0xB1, + 0xD7, 0xFA, 0x6A, 0x90, 0x5E, 0x84, 0xBF, 0xC0, 0x6B, 0xF5, 0xC0, 0xE2, 0x47, 0xDD, 0xFA, 0xE1, 0x5C, 0x06, 0x28, 0x52, + 0x9D, 0x08, 0x82, 0xBB, 0xB0, 0x23, 0x45, 0xF4, 0x32, 0x80, 0x5A, 0xF6, 0x56, 0xC5, 0x21, 0x03, 0xDA, 0x09, 0xCB, 0x05, + 0x31, 0x2B, 0x6B, 0x83, 0x40, 0x0E, 0x9B, 0x64, 0xF0, 0x6B, 0x03, 0x4C, 0xC3, 0x01, 0x41, 0x42, 0xF0, 0x07, 0x39, 0x35, + 0x4B, 0x4A, 0x19, 0x0D, 0x09, 0x61, 0x62, 0xA8, 0x0A, 0x83, 0x7A, 0x2B, 0xB9, 0x33, 0x48, 0x29, 0xEB, 0x4E, 0x66, 0x2E, + 0x10, 0x04, 0xBB, 0x7A, 0x4A, 0x06, 0xD3, 0x82, 0x1F, 0x90, 0x92, 0xC5, 0xA8, 0x46, 0xF3, 0xD7, 0x62, 0x2F, 0x84, 0xEB, + 0x0A, 0x09, 0x73, 0xEB, 0x3D, 0x95, 0x9B, 0xC0, 0x6B, 0x4C, 0x47, 0x73, 0xF6, 0xB6, 0x01, 0x0C, 0x2A, 0x0D, 0xCC, 0xF5, + 0x7B, 0x66, 0x7B, 0x7D, 0xBE, 0xCB, 0x67, 0x43, 0xC3, 0x04, 0x6A, 0x54, 0xA9, 0x81, 0xBA, 0xCE, 0x38, 0x8C, 0x18, 0x93, + 0xE9, 0x4A, 0x5A, 0xF8, 0xFB, 0x93, 0x97, 0x59, 0x6B, 0x6B, 0x9F, 0xBE, 0x99, 0x2E, 0xAD, 0x9A, 0xC9, 0x05, 0x52, 0x75, + 0x5D, 0xF4, 0xBC, 0x36, 0xF9, 0x0E, 0xF9, 0xAF, 0x18, 0x2D, 0x03, 0x46, 0x6B, 0xC4, 0x83, 0x0F, 0x9E, 0x68, 0x36, 0x23, + 0xE9, 0x0B, 0x8C, 0xBF, 0x19, 0x2C, 0x43, 0x89, 0xCA, 0x40, 0xBC, 0x02, 0x56, 0x0D, 0x54, 0x91, 0x81, 0x98, 0xC1, 0x63, + 0xB2, 0x34, 0x6C, 0x87, 0x03, 0xAF, 0x72, 0xC6, 0x33, 0x80, 0x8B, 0x72, 0xA3, 0x12, 0x4C, 0xEC, 0x9F, 0x35, 0x64, 0x97, + 0x02, 0xAE, 0xB6, 0x64, 0x2D, 0xDA, 0x04, 0x63, 0x0C, 0x99, 0xB1, 0xE7, 0x91, 0x70, 0x6D, 0x86, 0x83, 0xB2, 0xCC, 0x02, + 0x57, 0x7F, 0x88, 0xF3, 0xE2, 0x1C, 0x8B, 0xD2, 0x9F, 0xEF, 0x65, 0x33, 0xC3, 0x12, 0xE5, 0xB9, 0x11, 0xF2, 0x1D, 0x67, + 0x85, 0x58, 0xBC, 0x46, 0x37, 0x64, 0x6C, 0x30, 0x99, 0x5B, 0xAC, 0x44, 0x6C, 0x3E, 0x74, 0x82, 0x2D, 0x77, 0xAC, 0x90, + 0x67, 0x38, 0x24, 0x92, 0x20, 0xAB, 0xCA, 0x96, 0x1B, 0x78, 0x46, 0x43, 0x22, 0xCE, 0xFD, 0x15, 0x49, 0x39, 0xE1, 0x83, + 0xA1, 0xA1, 0x15, 0x98, 0x23, 0x8B, 0x07, 0xD4, 0xAD, 0x51, 0x87, 0x2E, 0x10, 0x31, 0x25, 0x73, 0xE2, 0x15, 0xCF, 0x9F, + 0x18, 0x33, 0x7E, 0x0A, 0x0A, 0x3A, 0x52, 0xD2, 0xAB, 0x07, 0x2C, 0x4A, 0xEA, 0x50, 0x17, 0x44, 0x92, 0x37, 0xBC, 0x1A, + 0x2C, 0xD3, 0xCB, 0x7B, 0x0A, 0xEF, 0xE1, 0x3C, 0x36, 0x61, 0xC7, 0x0A, 0xDE, 0x34, 0x5D, 0x10, 0xAE, 0x83, 0xDA, 0x12, + 0x17, 0xE7, 0x1E, 0xB9, 0x4B, 0xD7, 0xF7, 0xAF, 0x2A, 0x77, 0x35, 0x7B, 0x2B, 0x53, 0x37, 0x62, 0xA9, 0x76, 0x25, 0x46, + 0xED, 0xA1, 0x60, 0x6D, 0x5A, 0x70, 0x17, 0x68, 0x18, 0x2C, 0x4E, 0xCD, 0x3C, 0xA5, 0x6E, 0x38, 0x9D, 0x53, 0xEC, 0x5C, + 0x37, 0xD3, 0x70, 0x11, 0x8C, 0x19, 0x0E, 0xA4, 0xF9, 0x3B, 0x26, 0x9A, 0x28, 0xE2, 0x79, 0xC1, 0xAF, 0xAC, 0x01, 0x05, + 0x99, 0x39, 0xA5, 0x4F, 0xBF, 0x9E, 0xE3, 0x8B, 0xA9, 0x21, 0x73, 0x69, 0xBA, 0x86, 0xC9, 0x48, 0xB0, 0x04, 0x47, 0xD4, + 0xBD, 0xA6, 0x27, 0x7B, 0xEE, 0xDE, 0xF8, 0xC4, 0x2B, 0xEE, 0x70, 0x93, 0x67, 0xA0, 0xF9, 0x5B, 0x12, 0x19, 0x48, 0xA0, + 0x41, 0xC4, 0xE9, 0x7B, 0xF1, 0x3F, 0x72, 0x07, 0xA6, 0x87, 0x90, 0xEC, 0x97, 0xA5, 0x58, 0x87, 0x6B, 0xCC, 0xE1, 0xA4, + 0xF0, 0x17, 0x59, 0x81, 0xA6, 0xE0, 0xE6, 0x85, 0x11, 0x62, 0x09, 0xF3, 0x1B, 0xCD, 0xB0, 0x41, 0x2B, 0x8C, 0x79, 0x0B, + 0xE6, 0xE3, 0x19, 0x75, 0xB4, 0xE1, 0x73, 0xDC, 0x66, 0xCE, 0x02, 0x47, 0x55, 0x4C, 0x99, 0xC6, 0x0E, 0x91, 0x65, 0xA4, + 0x94, 0xA7, 0xC4, 0x92, 0x4A, 0xCB, 0xA0, 0x04, 0x12, 0xE2, 0xEA, 0x28, 0xE4, 0x8C, 0x51, 0x34, 0x54, 0x1A, 0x00, 0xF0, + 0x42, 0x0F, 0x9F, 0x52, 0xB6, 0xE3, 0x1A, 0x93, 0xCA, 0x8F, 0x77, 0xA5, 0x14, 0x8E, 0x11, 0x27, 0xD1, 0x4B, 0x79, 0x7E, + 0xD0, 0x7F, 0xE9, 0x15, 0xE1, 0x0C, 0x91, 0xD5, 0x9E, 0x9A, 0x01, 0xF1, 0xC2, 0xC3, 0x5A, 0xCC, 0x74, 0xE4, 0x5A, 0x88, + 0x09, 0x72, 0x62, 0x76, 0xB2, 0xAC, 0x38, 0x2B, 0xEF, 0xC5, 0xCA, 0xA6, 0xF9, 0x61, 0x4A, 0xBA, 0xB1, 0x84, 0x7E, 0x40, + 0x8E, 0x96, 0xC3, 0xBE, 0x16, 0xF0, 0xBC, 0x40, 0xFA, 0xF9, 0x1B, 0x5B, 0x84, 0x85, 0xA5, 0x48, 0xB2, 0x76, 0x39, 0x2F, + 0x6F, 0x31, 0x93, 0xBC, 0x7F, 0xE2, 0x21, 0x5B, 0x2E, 0x8D, 0xF6, 0xDF, 0x32, 0x76, 0x5B, 0x8E, 0xAD, 0x46, 0x04, 0xD9, + 0x5F, 0xEF, 0xE5, 0x77, 0xE5, 0xC8, 0x22, 0x36, 0xAA, 0xAA, 0x4A, 0xBA, 0x31, 0xC3, 0xB6, 0x73, 0xDC, 0x38, 0xCE, 0x20, + 0xAC, 0x7D, 0x95, 0xBC, 0x9D, 0xE5, 0x02, 0xF8, 0x4E, 0x8F, 0xBC, 0x3E, 0x1B, 0xEB, 0x59, 0xFB, 0x0F, 0x21, 0x6B, 0x4B, + 0x3F, 0x24, 0xC7, 0x09, 0x8D, 0x11, 0x5E, 0x0D, 0x53, 0x68, 0x9C, 0x4B, 0x48, 0x02, 0x69, 0x3D, 0xDC, 0x10, 0x43, 0xAB, + 0x70, 0xC0, 0x58, 0xC4, 0xBC, 0xCF, 0xED, 0x60, 0xA6, 0xD8, 0xFD, 0x01, 0xE9, 0xFF, 0x7A, 0x5E, 0xB1, 0x2B, 0xB6, 0xD9, + 0x35, 0xF9, 0x4C, 0xF2, 0x59, 0x9C, 0x53, 0x7E, 0xBF, 0x3C, 0x43, 0x36, 0x3A, 0x53, 0x84, 0xE4, 0x36, 0x01, 0xFB, 0x73, + 0x98, 0x9D, 0xA4, 0xF8, 0x13, 0x0F, 0xC3, 0x4E, 0xF8, 0x5F, 0x4D, 0x25, 0x74, 0xA4, 0x67, 0xC4, 0xE4, 0x83, 0x55, 0x9F, + 0x48, 0xFC, 0x07, 0x31, 0x6C, 0x8B, 0xBF, 0x35, 0x74, 0x83, 0x10, 0xB1, 0x31, 0xDB, 0x86, 0x44, 0x33, 0x04, 0x4E, 0x00, + 0xCA, 0xDB, 0xCE, 0x09, 0xCB, 0x98, 0x5B, 0x1E, 0x54, 0x95, 0xF6, 0x52, 0x6C, 0x8C, 0x04, 0x70, 0x62, 0x8C, 0xC2, 0xCB, + 0x34, 0xD5, 0xD2, 0x0A, 0xD1, 0x96, 0x25, 0xBF, 0x74, 0x4D, 0x15, 0xA3, 0x4A, 0x56, 0x93, 0x93, 0xF5, 0x27, 0xAD, 0xD2, + 0x2E, 0x6A, 0x8D, 0x93, 0xF9, 0xBA, 0x47, 0x11, 0x65, 0xFF, 0x02, 0x88, 0xB7, 0xA8, 0x5E, 0xE8, 0x6F, 0x87, 0xC6, 0x8C, + 0xDC, 0xB5, 0x4E, 0xEC, 0x06, 0xC3, 0xCE, 0x2C, 0xFC, 0xAE, 0x16, 0x4A, 0xF2, 0x96, 0x5A, 0x9C, 0x75, 0xD5, 0xFA, 0x58, + 0xEF, 0xD5, 0xDE, 0xFC, 0x2D, 0xF6, 0x5F, 0x09, 0xC2, 0xF9, 0xBF, 0x0B, 0xBA, 0x23, 0x43, 0x4D, 0x6E, 0xD6, 0x8F, 0x7F, + 0xA0, 0x7A, 0x4F, 0xDF, 0x8C, 0x16, 0x7B, 0xC1, 0x93, 0x67, 0x7D, 0x59, 0x6F, 0xDF, 0xDF, 0xBD, 0x63, 0xF6, 0x70, 0xA8, + 0xD1, 0x41, 0x19, 0x9C, 0x30, 0xDE, 0xD6, 0x88, 0x2F, 0x9C, 0xAC, 0x6C, 0x42, 0xBE, 0x76, 0x29, 0x73, 0x40, 0x6C, 0x5C, + 0x3A, 0x9D, 0x24, 0xFB, 0xCC, 0xDB, 0x6B, 0xCE, 0xFD, 0xBF, 0xB3, 0x35, 0x53, 0x1F, 0xAD, 0xCA, 0x9C, 0xB3, 0x0F, 0x69, + 0xEF, 0xBD, 0xE8, 0x6A, 0x17, 0x37, 0x3D, 0xF8, 0x44, 0x4F, 0x2F, 0xA7, 0x65, 0x42, 0x73, 0xFD, 0x4E, 0x55, 0xE0, 0x7A, + 0x03, 0x0E, 0xB3, 0x3C, 0xF8, 0xB1, 0x13, 0xF7, 0x94, 0xAD, 0xBB, 0xA4, 0x48, 0x6C, 0xA8, 0x58, 0x73, 0xE0, 0xC8, 0x00, + 0x5B, 0xF5, 0x18, 0xF8, 0xFD, 0x5A, 0x46, 0xD2, 0x01, 0xC4, 0x6F, 0x52, 0x4F, 0xBA, 0x32, 0x39, 0xB3, 0x22, 0xD3, 0x06, + 0x7B, 0x46, 0xAE, 0xC9, 0xC4, 0x03, 0x16, 0x9A, 0x75, 0x2F, 0x9E, 0x0F, 0xF5, 0xB7, 0x91, 0xE4, 0xE3, 0x03, 0xE6, 0x42, + 0x62, 0x4C, 0xB9, 0xC8, 0x9C, 0x18, 0xF4, 0x22, 0x21, 0x34, 0xB8, 0xC6, 0x92, 0xEC, 0x68, 0x10, 0x78, 0x4F, 0xD8, 0x94, + 0x68, 0x6B, 0x30, 0x77, 0x60, 0x94, 0x08, 0x55, 0x02, 0x69, 0x0C, 0xF1, 0xEF, 0x48, 0x6C, 0x84, 0x3D, 0x6A, 0x21, 0x5F, + 0xAD, 0x86, 0xB9, 0xC1, 0xE3, 0x51, 0x93, 0x46, 0x63, 0xC1, 0x65, 0x95, 0xF8, 0x69, 0x31, 0xB9, 0x91, 0x4A, 0x48, 0xA9, + 0x7F, 0xDC, 0x2B, 0xC4, 0x93, 0x22, 0x6D, 0x85, 0x92, 0x68, 0x15, 0x12, 0x78, 0x78, 0xDD, 0x0C, 0x3C, 0x87, 0xA6, 0x57, + 0xEB, 0x09, 0x2E, 0xD5, 0x79, 0xF3, 0xF5, 0xF5, 0x79, 0x0F, 0xF4, 0x1B, 0xAC, 0x26, 0x22, 0x68, 0x4D, 0x46, 0xCA, 0x3C, + 0x0B, 0x6D, 0x23, 0x53, 0x69, 0x35, 0x23, 0x7F, 0xFA, 0xFE, 0x2B, 0xF9, 0x3F, 0x45, 0x25, 0xA9, 0xC3, 0xB5, 0xA8, 0x4C, + 0xEA, 0xF4, 0x1B, 0xE2, 0x78, 0x64, 0x8B, 0x5B, 0x8A, 0xF4, 0x1E, 0xBF, 0x59, 0x83, 0x22, 0x56, 0x71, 0x03, 0xDA, 0xB5, + 0xB7, 0x6E, 0x6A, 0x97, 0x2B, 0xC4, 0x66, 0x9C, 0x56, 0x63, 0x2A, 0x46, 0x9F, 0x02, 0x08, 0x7C, 0x0F, 0x4C, 0x96, 0x18, + 0x4F, 0x49, 0x05, 0xF8, 0x05, 0x90, 0x23, 0x57, 0xA0, 0x03, 0x0E, 0x76, 0x67, 0x27, 0x4B, 0x7C, 0x37, 0xC7, 0x67, 0x9D, + 0xD9, 0x61, 0xE3, 0x54, 0x6A, 0xA0, 0x0B, 0x80, 0x3D, 0x82, 0xA0, 0x5D, 0x2A, 0x49, 0xBB, 0x08, 0x6A, 0x09, 0x3C, 0x6E, + 0xAD, 0xC6, 0x71, 0x00, 0x38, 0x28, 0x47, 0xA4, 0x1B, 0x50, 0xF4, 0xA6, 0x8D, 0x7D, 0x88, 0x6B, 0xF0, 0x2C, 0x57, 0xA3, + 0x37, 0x4B, 0x8C, 0xD2, 0x22, 0xA1, 0xA4, 0x54, 0x7D, 0xFA, 0x4D, 0x05, 0x15, 0x9B, 0xDA, 0xE2, 0xCF, 0x3B, 0x4E, 0xC3, + 0x01, 0xAD, 0xF5, 0xBB, 0xF1, 0x7D, 0x26, 0x98, 0xC2, 0xFB, 0xBA, 0xEA, 0x92, 0xF9, 0x43, 0x53, 0xC1, 0xD6, 0x4D, 0x57, + 0x73, 0x77, 0xE7, 0x7E, 0x41, 0x0C, 0x04, 0xBD, 0x2A, 0xAF, 0x2C, 0x62, 0x61, 0x90, 0xDE, 0xC6, 0xD1, 0x72, 0x74, 0x2F, + 0x42, 0xDD, 0xC8, 0x9C, 0xD2, 0xCA, 0x66, 0x12, 0xCF, 0xD5, 0x68, 0x8B, 0xD0, 0x34, 0x3D, 0x43, 0x4E, 0x1F, 0xE5, 0x38, + 0xBA, 0x74, 0x2D, 0x63, 0xE7, 0x05, 0xDD, 0x47, 0x07, 0x79, 0x15, 0x8C, 0x21, 0xF2, 0x36, 0x25, 0x92, 0xE6, 0x25, 0x75, + 0x9E, 0x1A, 0xE3, 0x81, 0x7C, 0xF1, 0x15, 0x7B, 0xAC, 0x95, 0xE6, 0x8E, 0x75, 0x35, 0xEA, 0xDB, 0xCB, 0x6A, 0xEE, 0xCE, + 0x10, 0x75, 0xB7, 0xDF, 0xEB, 0x68, 0xF6, 0x9E, 0x61, 0x3F, 0x66, 0x9F, 0x94, 0x56, 0x3D, 0xED, 0xDA, 0x1C, 0x55, 0x97, + 0x28, 0xD8, 0xDF, 0x9C, 0xDB, 0x12, 0xEB, 0x8D, 0x17, 0x87, 0x6C, 0xDF, 0xD6, 0x7C, 0x47, 0x09, 0x1C, 0x92, 0x39, 0xFD, + 0x18, 0xC4, 0x8F, 0x49, 0x9F, 0xFA, 0x34, 0x5F, 0x7B, 0x7F, 0xDE, 0xAA, 0xDD, 0xE1, 0xB8, 0xCA, 0xDB, 0xBF, 0x08, 0x42, + 0x3A, 0x12, 0x56, 0xAC, 0x2A, 0xD1, 0x54, 0xBA, 0x56, 0x16, 0xB1, 0x58, 0x4A, 0xE2, 0x04, 0xF9, 0xC8, 0x11, 0x5C, 0x8F, + 0x1E, 0xFC, 0xDC, 0x36, 0x28, 0xFB, 0x71, 0x3E, 0x36, 0x33, 0x66, 0x6B, 0xEB, 0x11, 0x4D, 0x7F, 0xEA, 0x74, 0x47, 0x5B, + 0x47, 0x36, 0xF0, 0x3F, 0xBD, 0xA6, 0xEC, 0x3F, 0x57, 0x11, 0xA0, 0x02, 0xDF, 0x84, 0x58, 0x25, 0x9B, 0x1F, 0xA1, 0x79, + 0xB3, 0xE1, 0x48, 0x40, 0x05, 0xE0, 0x88, 0xC6, 0x58, 0x6B, 0xA8, 0xEE, 0x4F, 0x0C, 0x57, 0x44, 0x1B, 0x2B, 0xB0, 0xF7, + 0xE4, 0x4B, 0x10, 0x37, 0x66, 0x1A, 0xFA, 0x2E, 0xA6, 0xA0, 0xC1, 0x05, 0xFF, 0xAF, 0x49, 0x07, 0x67, 0xC4, 0xBD, 0xC5, + 0x53, 0x83, 0xD4, 0xFB, 0xCB, 0xCE, 0x2F, 0x33, 0x36, 0xA5, 0xC2, 0xD1, 0x64, 0x49, 0xE3, 0xA7, 0x72, 0x6E, 0x7B, 0xAA, + 0x56, 0xCB, 0xF1, 0x01, 0xD4, 0xE4, 0x54, 0x4E, 0xE5, 0xC2, 0x0B, 0x96, 0x56, 0x15, 0x72, 0xB0, 0x85, 0x31, 0xC8, 0x99, + 0x11, 0x2F, 0x00, 0xF6, 0x3A, 0x1E, 0xD8, 0x85, 0xDB, 0x38, 0x01, 0x5D, 0xFA, 0x0D, 0xA9, 0x57, 0xDE, 0xB7, 0x55, 0x2F, + 0xA5, 0x39, 0x8F, 0x61, 0x37, 0x65, 0x5A, 0xA3, 0x8F, 0x88, 0x99, 0x55, 0x22, 0x7C, 0xB9, 0x1F, 0x4F, 0x8B, 0x81, 0x08, + 0xF4, 0xBA, 0x5D, 0x65, 0x81, 0x3E, 0xF2, 0x21, 0xBD, 0x20, 0x4D, 0xC8, 0x68, 0xC5, 0xD2, 0x2C, 0x28, 0xE7, 0xBF, 0xE9, + 0x89, 0x04, 0x6A, 0x67, 0x7D, 0xA8, 0x13, 0x32, 0x69, 0x92, 0xDA, 0x3C, 0x26, 0xE4, 0x6B, 0xB6, 0xEF, 0xF6, 0xA1, 0xED, + 0x3D, 0xEB, 0xE8, 0x2B, 0x5D, 0x57, 0x73, 0x4F, 0xDC, 0xAB, 0x79, 0x05, 0x66, 0xEF, 0x93, 0xC2, 0x9B, 0x32, 0x8D, 0xD6, + 0xEC, 0x60, 0x0B, 0x49, 0x5B, 0x89, 0x02, 0x54, 0x2C, 0x83, 0xC2, 0xB3, 0x53, 0x37, 0xC5, 0xEE, 0x00, 0x43, 0x62, 0xEC, + 0x5F, 0x8B, 0x31, 0x98, 0xEE, 0x72, 0x56, 0xDA, 0x04, 0x72, 0x70, 0x7E, 0xEC, 0xCB, 0x0A, 0x1C, 0x1E, 0xCD, 0xF3, 0xCF, + 0xF7, 0xBE, 0x55, 0xB6, 0xBF, 0xD5, 0x13, 0x2A, 0x63, 0xC3, 0xC9, 0x8D, 0x5C, 0xE6, 0xAB, 0x5A, 0x9E, 0x89, 0x2B, 0x3F, + 0x9F, 0xEE, 0x33, 0x6C, 0xAC, 0x4F, 0x83, 0x1D, 0x9C, 0x1F, 0xA0, 0x79, 0xF5, 0x6D, 0xC4, 0x84, 0x79, 0xBD, 0x21, 0x51, + 0xE0, 0x5D, 0xC8, 0xC4, 0xF6, 0x24, 0x3F, 0x61, 0xA1, 0x1C, 0x96, 0x69, 0x56, 0xB8, 0x04, 0x96, 0xC4, 0x6E, 0xDC, 0xA8, + 0x3C, 0xFC, 0x0E, 0x9E, 0xC7, 0x28, 0x09, 0x18, 0xB5, 0xD3, 0x67, 0xE1, 0x0F, 0xB6, 0x69, 0x23, 0x85, 0xE6, 0x7F, 0x8D, + 0x4E, 0xF7, 0x3A, 0x64, 0x31, 0x3E, 0x86, 0x55, 0x1C, 0xC3, 0xE5, 0xB3, 0x59, 0xFE, 0x5C, 0x3D, 0x47, 0xFC, 0x1F, 0xA4, + 0x4A, 0x4B, 0x47, 0x60, 0x6F, 0x34, 0xF2, 0xC2, 0x70, 0xED, 0xF0, 0xB0, 0xD0, 0x68, 0x8C, 0xD5, 0x95, 0xB8, 0x70, 0xE6, + 0xC4, 0xD3, 0x7C, 0xF2, 0x24, 0x80, 0x3D, 0x76, 0x24, 0x73, 0x66, 0x79, 0xB0, 0x1B, 0x2F, 0xF7, 0x45, 0xD0, 0xF5, 0x1A, + 0x91, 0x2D, 0xF6, 0x2C, 0x25, 0x72, 0x9F, 0xF9, 0xBB, 0x4A, 0x71, 0xE2, 0x84, 0x27, 0xFD, 0xF7, 0xF7, 0xF7, 0x19, 0x68, + 0x30, 0x9C, 0xF4, 0xB9, 0xD7, 0xDC, 0xCE, 0x8E, 0x5F, 0x68, 0xEE, 0xA6, 0xFE, 0x2C, 0x2F, 0xFC, 0xD6, 0x65, 0x39, 0x6D, + 0xB9, 0x34, 0x91, 0x58, 0xC1, 0x24, 0x5C, 0x5C, 0xFF, 0x2D, 0x56, 0xAF, 0x09, 0x05, 0x9F, 0x71, 0xDF, 0x52, 0x8F, 0x54, + 0xFC, 0x97, 0xB9, 0x4D, 0x50, 0x71, 0x92, 0xC4, 0x78, 0xC6, 0xFD, 0x9D, 0x56, 0xDF, 0x47, 0x9F, 0x8E, 0xDE, 0x63, 0xDD, + 0xDE, 0xBB, 0x78, 0xA8, 0x53, 0x97, 0xFE, 0xC3, 0x49, 0x98, 0x0E, 0x68, 0x67, 0x5C, 0xF6, 0xEE, 0x7E, 0xFC, 0xD5, 0x38, + 0x29, 0x67, 0xB1, 0x21, 0x39, 0x47, 0x44, 0x09, 0x5F, 0xDB, 0xFE, 0xFE, 0x7F, 0xFD, 0x76, 0x49, 0x7A, 0x49, 0x38, 0xED, + 0x81, 0xFC, 0x0F, 0xEF, 0xA9, 0x19, 0xF7, 0xEF, 0xFE, 0xFE, 0xC5, 0x59, 0x43, 0xC6, 0xAD, 0xFB, 0x3D, 0x9B, 0x5F, 0xBB, + 0x8C, 0x20, 0xFF, 0xFF, 0x20, 0x6A, 0x26, 0x59, 0x6E, 0xA4, 0x82, 0xF1, 0x58, 0xB1, 0x16, 0x11, 0x78, 0x02, 0x82, 0xDC, + 0xBB, 0x24, 0xB0, 0xE3, 0x3B, 0x11, 0xB6, 0x28, 0x32, 0x61, 0x26, 0x19, 0x29, 0x4C, 0x58, 0xDC, 0xEF, 0xEC, 0x8A, 0xA9, + 0xB3, 0x59, 0x87, 0x28, 0xD8, 0xF3, 0x4C, 0x6D, 0x21, 0x4D, 0xAF, 0xC7, 0xB2, 0xF7, 0xB1, 0xE2, 0xB7, 0x98, 0x8F, 0x2C, + 0x99, 0xD4, 0x0F, 0x53, 0xA1, 0x4C, 0xE7, 0x94, 0x3A, 0x20, 0x1A, 0x41, 0xA1, 0xB4, 0xC8, 0x54, 0xC6, 0x07, 0x09, 0x30, + 0x44, 0x7F, 0x8C, 0x92, 0x42, 0xAB, 0x11, 0xD6, 0x02, 0xC5, 0xCA, 0x36, 0xEC, 0x67, 0x0C, 0x6F, 0x65, 0xE8, 0xF2, 0xA4, + 0x0F, 0x64, 0x81, 0xA9, 0xFE, 0x44, 0x66, 0xE1, 0x10, 0x4A, 0x89, 0x21, 0x82, 0x92, 0xB1, 0x67, 0x87, 0x6B, 0x6F, 0xF4, + 0xA9, 0xA3, 0x90, 0x01, 0x7A, 0x04, 0xC8, 0xF5, 0xF0, 0x8F, 0xE1, 0x71, 0x56, 0x95, 0xF6, 0xF1, 0xFB, 0xAC, 0x84, 0x20, + 0x10, 0x7D, 0x6C, 0x2E, 0xA9, 0xCB, 0xED, 0x3F, 0x17, 0x39, 0x82, 0xF5, 0x28, 0x52, 0x81, 0x6E, 0xE6, 0xF6, 0x24, 0xE9, + 0x20, 0x83, 0xD3, 0x7C, 0x5D, 0x41, 0xCE, 0x48, 0x40, 0x90, 0x43, 0xE5, 0xCF, 0x22, 0x3B, 0xAD, 0xFB, 0x3D, 0xAD, 0x01, + 0x57, 0xCC, 0xBD, 0xE4, 0xA8, 0xD0, 0xF4, 0xE7, 0x9F, 0x30, 0x43, 0x30, 0x20, 0xA1, 0x0B, 0x4E, 0xED, 0x29, 0x10, 0xEC, + 0x42, 0x7D, 0xBA, 0x6B, 0xF3, 0x6F, 0x6C, 0xC9, 0xE9, 0x29, 0x8B, 0x84, 0xBF, 0xAE, 0x12, 0x5C, 0x43, 0xBC, 0xCC, 0x75, + 0x33, 0x06, 0xCB, 0xFC, 0x34, 0xC1, 0x83, 0x94, 0xBE, 0x7F, 0x45, 0x75, 0x63, 0xDF, 0xBB, 0xC9, 0xE5, 0xA2, 0x6D, 0xCD, + 0x69, 0xBB, 0x92, 0x8D, 0xD2, 0xAC, 0x5F, 0x76, 0xC3, 0x5E, 0xAB, 0x1A, 0xDB, 0x22, 0x01, 0x68, 0xA3, 0x5E, 0x51, 0x9D, + 0xE7, 0x69, 0xF1, 0x04, 0x13, 0x0E, 0x3E, 0x00, 0x03, 0x99, 0x81, 0x67, 0xAA, 0x9A, 0x85, 0xD4, 0x2C, 0x79, 0xB6, 0x78, + 0x56, 0xDE, 0x3E, 0x35, 0x21, 0xF4, 0x0A, 0xD2, 0x9E, 0xFC, 0x84, 0x18, 0x90, 0xDE, 0x0D, 0x95, 0x93, 0x69, 0x8D, 0x90, + 0x83, 0x19, 0x5D, 0xED, 0x09, 0x83, 0x9A, 0xD6, 0xC0, 0xFD, 0x37, 0x13, 0x2C, 0x93, 0x5D, 0xE6, 0xC1, 0x5D, 0x0A, 0x35, + 0xD2, 0xB3, 0x8E, 0xC6, 0x81, 0x1F, 0x14, 0x44, 0x11, 0xCE, 0xA4, 0xB2, 0xBD, 0x82, 0x95, 0xC0, 0x0A, 0xDE, 0xCE, 0xE6, + 0xE0, 0x7C, 0xDB, 0xC3, 0x05, 0x16, 0xD6, 0xD5, 0x12, 0xB7, 0xA3, 0x83, 0x0D, 0xF6, 0x4A, 0x1A, 0xF1, 0x19, 0x4D, 0xD5, + 0x6A, 0x35, 0xCD, 0x49, 0x5B, 0xBC, 0x6B, 0x49, 0x8A, 0x05, 0xD3, 0x97, 0x0D, 0x34, 0x17, 0xFF, 0xCB, 0x06, 0x94, 0xD2, + 0xF7, 0xFA, 0x08, 0x0F, 0xE5, 0x4C, 0xDF, 0x97, 0x0C, 0x7C, 0x7E, 0xFB, 0x6B, 0x13, 0xE4, 0x85, 0x39, 0x88, 0x2E, 0x2C, + 0x5B, 0x1E, 0xF1, 0x6C, 0x2A, 0xF3, 0x53, 0x13, 0x56, 0x82, 0x0E, 0x5C, 0x7D, 0x3A, 0x4A, 0xAB, 0x0B, 0x1A, 0xC3, 0x60, + 0xD8, 0xD0, 0x87, 0xE8, 0xFA, 0x58, 0xDE, 0x70, 0x5D, 0xBC, 0x1F, 0xBD, 0x20, 0x39, 0x26, 0x9C, 0x88, 0x38, 0xD4, 0xA3, + 0xAF, 0x21, 0x99, 0x98, 0xBF, 0x61, 0xDF, 0x51, 0x46, 0x19, 0x8E, 0x5D, 0xA9, 0xF0, 0x86, 0x21, 0x7D, 0x11, 0x2A, 0x5E, + 0x36, 0x34, 0x5C, 0x8A, 0x99, 0x39, 0xD0, 0x04, 0x19, 0xBC, 0x8E, 0x31, 0x3E, 0x10, 0x4B, 0xD4, 0x5C, 0x2A, 0xBD, 0xB8, + 0x11, 0xD0, 0x84, 0x0A, 0x7D, 0x66, 0x39, 0xE1, 0xCA, 0xBE, 0x40, 0x25, 0xD5, 0xF5, 0x6F, 0x2E, 0x34, 0xC3, 0xF7, 0xFD, + 0x1B, 0x65, 0xB0, 0x22, 0x24, 0xB2, 0x27, 0xEC, 0x3B, 0xBF, 0x06, 0x09, 0x0C, 0x1D, 0xB6, 0xBD, 0xB1, 0x82, 0x14, 0x86, + 0x5D, 0x2C, 0x5C, 0xC1, 0x12, 0xC0, 0x2E, 0xEA, 0x67, 0xA0, 0xED, 0xB2, 0xBF, 0x31, 0x77, 0xED, 0x7A, 0x84, 0x72, 0x60, + 0x34, 0x11, 0xF6, 0x1E, 0xAC, 0x90, 0x9E, 0xE7, 0x69, 0x4C, 0x94, 0xDB, 0x30, 0xF8, 0x5B, 0x47, 0xE2, 0xB9, 0xF1, 0xEF, + 0x36, 0x66, 0x08, 0x9B, 0x3F, 0x53, 0xF2, 0x3D, 0x83, 0x49, 0x69, 0xFE, 0x92, 0xB8, 0xD5, 0xA0, 0xD6, 0xC9, 0x2C, 0xF0, + 0x1F, 0x29, 0x74, 0xD0, 0xFF, 0x8F, 0x9F, 0x01, 0xFF, 0x2E, 0xB0, 0x8B, 0x53, 0x69, 0xD0, 0x3F, 0xF7, 0x86, 0x16, 0x6A, + 0x5D, 0xC7, 0x28, 0xBF, 0xC3, 0xBE, 0xE2, 0x01, 0x73, 0xCA, 0x18, 0xEB, 0xD2, 0x44, 0xE1, 0x02, 0x72, 0x0B, 0x86, 0xAF, + 0x14, 0x69, 0x21, 0x81, 0xC0, 0xFD, 0x35, 0xB7, 0xA8, 0x84, 0x34, 0x57, 0x26, 0x78, 0xB7, 0x31, 0x20, 0xB7, 0x65, 0xFB, + 0x2E, 0x94, 0x51, 0x53, 0x55, 0x8B, 0x68, 0xE7, 0x66, 0x23, 0x7A, 0x98, 0x0E, 0x65, 0xAE, 0x59, 0x78, 0x8A, 0xFA, 0x56, + 0x3F, 0xED, 0x19, 0xD7, 0x72, 0x80, 0xFE, 0xD9, 0xF4, 0xEA, 0x01, 0x86, 0xA6, 0x78, 0xE0, 0x10, 0x37, 0x58, 0x2B, 0xAA, + 0x74, 0x10, 0x63, 0xE7, 0xF0, 0xA2, 0x6A, 0x41, 0x27, 0x1B, 0xA5, 0x13, 0x37, 0xAE, 0xF0, 0x2C, 0x8B, 0xA1, 0xF2, 0xFB, + 0x5B, 0xB9, 0x1D, 0xEA, 0xF1, 0x66, 0xC5, 0x38, 0x7C, 0x44, 0x8E, 0xD9, 0x7E, 0x84, 0x5A, 0xA1, 0x93, 0x21, 0x64, 0x08, + 0xB1, 0x61, 0xF0, 0x0C, 0x7D, 0x2E, 0x7B, 0x21, 0x2C, 0x50, 0x13, 0x99, 0x19, 0xB6, 0x44, 0xDE, 0x91, 0x10, 0x2B, 0x0D, + 0x65, 0x64, 0x61, 0x54, 0xFE, 0x3A, 0x06, 0xA0, 0x7F, 0xF8, 0x26, 0xCE, 0x39, 0xA0, 0x1F, 0x1C, 0xD9, 0x48, 0x15, 0x66, + 0x47, 0x1E, 0xC4, 0x1F, 0xB7, 0xB4, 0xBB, 0x93, 0xA6, 0xC5, 0xDB, 0x95, 0x36, 0xC5, 0xDF, 0xF0, 0xCF, 0xA1, 0xD7, 0xB9, + 0x0C, 0xB4, 0x6D, 0x9F, 0x93, 0xB5, 0xCA, 0x97, 0x04, 0xB2, 0xF3, 0x04, 0x24, 0xD1, 0x77, 0x78, 0x7D, 0x80, 0x02, 0x17, + 0x13, 0x0E, 0xC4, 0xB4, 0x35, 0x51, 0x1B, 0xAA, 0x29, 0x89, 0x25, 0x7A, 0xE8, 0xF0, 0x0D, 0x92, 0x86, 0x2D, 0xE8, 0xB6, + 0x55, 0x72, 0x39, 0xEF, 0x44, 0x3C, 0xA9, 0xE7, 0x54, 0x1C, 0xE9, 0x20, 0x44, 0x6C, 0xAE, 0xB5, 0x22, 0x5E, 0x34, 0x59, + 0xCF, 0x65, 0xDE, 0x2E, 0xBA, 0x7B, 0x29, 0x26, 0xAC, 0x17, 0xE6, 0xE2, 0x89, 0x79, 0x70, 0x5A, 0xA5, 0xF9, 0x40, 0x2B, + 0x71, 0xCE, 0xEA, 0x32, 0x3B, 0xB9, 0x46, 0x72, 0x4C, 0x90, 0x07, 0xC3, 0xA5, 0xD6, 0xF5, 0xF6, 0xEA, 0x6D, 0x4B, 0x52, + 0xE0, 0xCD, 0x21, 0x19, 0xC5, 0xF0, 0x6F, 0xB1, 0x4C, 0xC6, 0xBE, 0x2E, 0xC4, 0x2C, 0x43, 0x57, 0x2D, 0xC4, 0xF5, 0xE3, + 0x70, 0xB6, 0x72, 0x79, 0x0A, 0x83, 0xB3, 0xFD, 0x04, 0xD4, 0x4D, 0xC5, 0x10, 0x27, 0xA5, 0xD7, 0x5F, 0xFA, 0x2E, 0x9A, + 0x2D, 0x99, 0xB2, 0x06, 0x56, 0xB6, 0x69, 0x41, 0xDC, 0x4A, 0xE3, 0x62, 0x94, 0xE8, 0x1E, 0x0F, 0xEC, 0x1D, 0xC1, 0x5F, + 0xBD, 0xFA, 0x8E, 0x17, 0x1B, 0xE7, 0xED, 0x81, 0x84, 0xB8, 0x15, 0x68, 0xDD, 0x10, 0xAD, 0xEC, 0x85, 0x3E, 0x44, 0x53, + 0x5C, 0x99, 0xC7, 0x3B, 0xC6, 0xBB, 0xD9, 0xAA, 0x7E, 0xDE, 0xD5, 0x4A, 0x25, 0x63, 0x48, 0x5F, 0x68, 0xC7, 0xAF, 0x1A, + 0x19, 0x7E, 0xFF, 0x58, 0xA2, 0x1D, 0x54, 0xBE, 0x33, 0x7F, 0x68, 0x66, 0x69, 0xC6, 0x80, 0x2E, 0x4C, 0x56, 0x3A, 0xBF, + 0x0F, 0x31, 0xC3, 0xD6, 0x8D, 0x75, 0x69, 0x2B, 0xE2, 0xDF, 0x97, 0xA8, 0xBE, 0xF3, 0x57, 0x4B, 0x0C, 0xDD, 0xCF, 0xCB, + 0x5E, 0xA4, 0x75, 0x7F, 0xD4, 0x94, 0x45, 0x9F, 0xAB, 0x56, 0x4A, 0x60, 0x14, 0x1B, 0x80, 0x66, 0xE7, 0x45, 0xEB, 0xD3, + 0x74, 0x2C, 0x2B, 0xAA, 0xBB, 0xF1, 0x8C, 0xD0, 0x05, 0xC1, 0x59, 0xFA, 0x09, 0x25, 0x7A, 0x32, 0x40, 0x80, 0x50, 0x47, + 0x5A, 0xE8, 0x59, 0x77, 0x0D, 0x84, 0xB9, 0x28, 0x2F, 0xFF, 0x2F, 0x0D, 0xA1, 0x46, 0x7D, 0x56, 0xA8, 0xC4, 0x99, 0x63, + 0xB2, 0x08, 0x8B, 0x04, 0xA5, 0x27, 0xD9, 0xD9, 0xB4, 0x4E, 0xB9, 0xDF, 0x38, 0xF2, 0x40, 0x33, 0x72, 0x0B, 0x85, 0x57, + 0x59, 0x95, 0x45, 0x13, 0x7A, 0x4F, 0x8A, 0x9E, 0x3A, 0x55, 0x88, 0xB8, 0x76, 0x8E, 0x02, 0x94, 0x0F, 0x90, 0x78, 0x12, + 0x13, 0x41, 0xC0, 0x1D, 0xBA, 0x3F, 0xF5, 0x32, 0xFA, 0x09, 0xFF, 0x7C, 0x1D, 0x80, 0xD1, 0x70, 0xF2, 0xB6, 0x11, 0x8C, + 0xA5, 0x6B, 0x41, 0xB3, 0xE0, 0x47, 0xDE, 0x6A, 0xE3, 0x65, 0x74, 0x02, 0xE2, 0xC6, 0xFF, 0x5C, 0x70, 0xE2, 0xF8, 0xE0, + 0x7F, 0xC5, 0x2E, 0x67, 0x39, 0xF8, 0x0A, 0x34, 0x2B, 0x97, 0x88, 0x2E, 0xCA, 0x60, 0xE8, 0xD8, 0x11, 0xF4, 0x37, 0x43, + 0xCC, 0x74, 0x40, 0xC7, 0x23, 0x98, 0xBC, 0x05, 0x5E, 0x6D, 0xFC, 0x4E, 0xBB, 0x71, 0xFC, 0xF5, 0x98, 0xD6, 0x05, 0x14, + 0x23, 0xBB, 0x92, 0x3E, 0xA8, 0x40, 0xA7, 0x8B, 0x99, 0x03, 0x20, 0x99, 0x9D, 0x3A, 0x65, 0x05, 0x49, 0xDB, 0x5E, 0xFA, + 0xEA, 0xA0, 0x54, 0x75, 0xE1, 0xFD, 0x1C, 0x88, 0x52, 0x9D, 0x91, 0x97, 0xAB, 0xEF, 0xF4, 0x8E, 0x66, 0xC3, 0xD9, 0x49, + 0x3F, 0xAD, 0xEA, 0x3E, 0xE3, 0x5C, 0x0D, 0xFC, 0x70, 0x28, 0xE4, 0x54, 0xD6, 0xCB, 0x79, 0xF8, 0xFE, 0xA1, 0xE3, 0x33, + 0xD2, 0xBF, 0x9C, 0x97, 0xCC, 0x75, 0xC0, 0x1F, 0x31, 0x7F, 0xDA, 0x7A, 0x8A, 0x4E, 0x7C, 0x71, 0x9D, 0xC4, 0x53, 0x64, + 0x49, 0x6B, 0x12, 0xBD, 0x98, 0x2D, 0x30, 0x04, 0x2B, 0x2F, 0xB3, 0xA8, 0xC9, 0x53, 0xBB, 0x90, 0x68, 0xFF, 0xCE, 0xA6, + 0xC3, 0xA9, 0x51, 0x60, 0xCC, 0x7F, 0xB3, 0x07, 0x76, 0xBA, 0x8F, 0xC3, 0x2A, 0xDB, 0xA2, 0x8D, 0xBB, 0x78, 0x3F, 0x69, + 0xD7, 0xDD, 0xE3, 0xE7, 0x43, 0x5C, 0x82, 0xD3, 0x9E, 0xFD, 0xF4, 0x65, 0x9E, 0x1E, 0x54, 0x68, 0x67, 0x1B, 0xAD, 0x7F, + 0xC0, 0x25, 0x19, 0x42, 0xDD, 0xFE, 0xA3, 0x68, 0x90, 0x77, 0xD5, 0xB3, 0x16, 0x78, 0x0B, 0xD7, 0xCF, 0x95, 0xB8, 0x93, + 0x12, 0xA2, 0xCE, 0x06, 0x74, 0xD7, 0x8C, 0x39, 0x59, 0x1C, 0x95, 0xC1, 0xDA, 0x16, 0x54, 0xE1, 0x50, 0x3F, 0x85, 0x25, + 0x75, 0xF5, 0x23, 0x11, 0xA1, 0x7D, 0xFD, 0x3A, 0x47, 0x74, 0x6B, 0xCC, 0x20, 0x56, 0xFE, 0x61, 0xF1, 0x89, 0xD4, 0xEE, + 0x97, 0x55, 0xB5, 0xF2, 0x5A, 0x74, 0x07, 0xF0, 0x44, 0x51, 0x51, 0x05, 0x80, 0xD6, 0x01, 0xFA, 0x1B, 0x93, 0x8E, 0x88, + 0xB1, 0xCA, 0xDC, 0xB8, 0x83, 0x09, 0xEF, 0xDF, 0x08, 0xF1, 0xF7, 0x9A, 0x25, 0x02, 0xB4, 0x03, 0xC6, 0xB4, 0x78, 0xDA, + 0x9A, 0x35, 0x27, 0xCC, 0xF9, 0xFF, 0xFD, 0x76, 0xAE, 0xFB, 0x47, 0x64, 0x6C, 0x56, 0x20, 0x85, 0x11, 0x39, 0xB7, 0x27, + 0xF9, 0xBB, 0xD4, 0x8D, 0x9A, 0x80, 0x6C, 0x63, 0x34, 0x79, 0x20, 0x2A, 0xFE, 0xD0, 0xBF, 0x7D, 0xA7, 0x39, 0x8B, 0xB3, + 0xCB, 0xA3, 0xBE, 0xE8, 0x3C, 0xC6, 0x7E, 0x92, 0x83, 0xCD, 0x47, 0x68, 0x49, 0xC7, 0x28, 0x10, 0x28, 0x3E, 0x31, 0xA2, + 0x15, 0x48, 0x79, 0xD5, 0x00, 0x8C, 0x01, 0x88, 0x18, 0xFD, 0x74, 0x1C, 0x5B, 0x70, 0xE1, 0xB2, 0xD2, 0x33, 0x2F, 0xCD, + 0x36, 0x0F, 0x17, 0xFD, 0xC7, 0x3C, 0x74, 0x35, 0xAB, 0x5D, 0x5C, 0xF3, 0xC7, 0x0A, 0x5B, 0x08, 0x97, 0xBA, 0xC9, 0xD1, + 0x10, 0x2E, 0xF1, 0xA2, 0x20, 0x63, 0x80, 0x0A, 0xFD, 0x0A, 0xF0, 0xCA, 0x44, 0xCD, 0x08, 0xB5, 0x2C, 0x4D, 0x71, 0xEF, + 0xE2, 0x5A, 0x66, 0x92, 0x6A, 0x50, 0x65, 0x33, 0xC5, 0x01, 0xC0, 0xBE, 0xF0, 0x68, 0x41, 0x44, 0xC4, 0x8F, 0xEB, 0x06, + 0x6F, 0x57, 0xC8, 0x04, 0x65, 0xBD, 0xA2, 0x57, 0x54, 0x4D, 0x01, 0xEE, 0x26, 0xC1, 0x00, 0x69, 0x00, 0xDF, 0x7F, 0x1F, + 0x8F, 0x92, 0x99, 0xA4, 0x76, 0xEB, 0x30, 0x73, 0x02, 0xA8, 0x28, 0xC4, 0x9E, 0x14, 0x76, 0x00, 0xB9, 0x79, 0xAD, 0xC6, + 0xF7, 0x6D, 0x50, 0xB2, 0x03, 0xA9, 0x6C, 0xA7, 0x67, 0xF5, 0x21, 0xB7, 0x24, 0xE5, 0x33, 0x49, 0x27, 0x30, 0x0F, 0xC1, + 0x0E, 0x26, 0xD9, 0xB4, 0xE6, 0xAD, 0x9D, 0xFC, 0xC7, 0x66, 0xF5, 0x87, 0xD7, 0x49, 0x07, 0x74, 0x26, 0x8C, 0x5A, 0xF6, + 0x6B, 0xE4, 0x81, 0x08, 0xAF, 0x56, 0x6C, 0xF3, 0x8C, 0x10, 0x7F, 0x81, 0x0A, 0xB2, 0x1D, 0x41, 0xF5, 0x42, 0x12, 0xE9, + 0xA5, 0x22, 0x34, 0x5D, 0x2C, 0xA7, 0x51, 0x35, 0x5E, 0xDC, 0x3D, 0x64, 0x6B, 0x06, 0x61, 0x3A, 0x25, 0x03, 0xDA, 0x3C, + 0x87, 0xE4, 0xD8, 0xF3, 0x22, 0x31, 0x63, 0xE7, 0x2D, 0x05, 0x15, 0xE7, 0x6F, 0x4F, 0xB2, 0x5C, 0xA4, 0xA5, 0xE6, 0xE6, + 0xAC, 0x50, 0x38, 0x0C, 0xD6, 0xFA, 0xC4, 0x41, 0xA7, 0xC4, 0xC4, 0x78, 0x20, 0x5D, 0xE2, 0x09, 0xC5, 0x21, 0xD5, 0x76, + 0x6D, 0xAC, 0x0C, 0x52, 0xAF, 0x6F, 0xD4, 0x46, 0x15, 0x48, 0x58, 0x49, 0xAC, 0xFC, 0xBE, 0x41, 0x39, 0x18, 0xEB, 0x39, + 0x46, 0xCB, 0x34, 0x6D, 0x67, 0xF7, 0x29, 0xBA, 0x2D, 0xCE, 0x23, 0x4B, 0xAE, 0x7A, 0xE6, 0x98, 0xF2, 0x6E, 0xE2, 0xBB, + 0x16, 0xDF, 0x15, 0x63, 0x6E, 0x20, 0x7E, 0x60, 0xAB, 0xED, 0x5F, 0x6F, 0x6E, 0x30, 0x3B, 0x96, 0xFD, 0x64, 0x9E, 0xE2, + 0x2C, 0x52, 0xFD, 0xDD, 0x37, 0x70, 0x14, 0x48, 0x15, 0xC6, 0xED, 0xA6, 0xD5, 0x2F, 0x51, 0xE1, 0x6A, 0x35, 0x13, 0xD9, + 0x33, 0xAA, 0x76, 0xB3, 0x0C, 0xA0, 0xBC, 0x4F, 0x71, 0xB3, 0xB5, 0xF1, 0x1B, 0xCD, 0x0C, 0xF9, 0x21, 0xCE, 0x7D, 0x8E, + 0x0D, 0x83, 0x01, 0xC5, 0x0B, 0x69, 0xE4, 0x71, 0x45, 0x32, 0x36, 0xF5, 0xD4, 0xBB, 0x65, 0xA7, 0xE3, 0xC8, 0x3D, 0x9F, + 0x24, 0x2E, 0x3D, 0xAC, 0xCD, 0xA5, 0xB4, 0xD9, 0xB2, 0x1B, 0x2A, 0x42, 0x47, 0x70, 0x58, 0x74, 0xD6, 0xFC, 0xDB, 0x03, + 0xDA, 0xFB, 0x5F, 0x34, 0x5F, 0xF6, 0xB6, 0xE1, 0x53, 0x3F, 0xEF, 0x85, 0x07, 0xFE, 0xDC, 0x7F, 0x4D, 0x87, 0x41, 0x43, + 0xB2, 0x3D, 0xE0, 0x32, 0x2E, 0xA7, 0x75, 0xE5, 0xF4, 0x56, 0x0B, 0x07, 0xA4, 0xC5, 0x93, 0x73, 0x42, 0x14, 0x5B, 0xDF, + 0xF4, 0x95, 0x7D, 0xE6, 0xCB, 0x57, 0x68, 0x0E, 0x17, 0x5C, 0xFE, 0x8A, 0xB5, 0x68, 0xAD, 0xC8, 0x4D, 0x88, 0x9D, 0xF5, + 0x81, 0x44, 0x91, 0x2A, 0xD2, 0x36, 0x55, 0xB9, 0x9C, 0x46, 0x66, 0x3F, 0x25, 0x08, 0xC6, 0x99, 0x84, 0xF6, 0x35, 0x75, + 0x47, 0x6B, 0x67, 0x67, 0xBC, 0xB7, 0x31, 0x96, 0x05, 0x2B, 0x77, 0x47, 0xFC, 0x67, 0xBC, 0xE8, 0xE6, 0x1A, 0x03, 0x10, + 0x56, 0x0A, 0x1F, 0xA6, 0xEB, 0xC0, 0x9F, 0xB3, 0xFB, 0xE0, 0x3C, 0xE8, 0x46, 0xAD, 0xB2, 0x3D, 0x14, 0xFD, 0xBF, 0x50, + 0x8F, 0x73, 0xE7, 0xEC, 0x96, 0x5C, 0x38, 0xF2, 0xC4, 0xF9, 0xFB, 0xAD, 0x07, 0xD1, 0xB0, 0xC2, 0x86, 0x4C, 0x56, 0x8D, + 0x4B, 0xB2, 0x19, 0xCD, 0xCD, 0xCB, 0xDD, 0x3C, 0x8A, 0x11, 0x23, 0x18, 0xC8, 0x7A, 0xE2, 0x8C, 0xC5, 0xE5, 0x57, 0xE2, + 0x54, 0x3F, 0x89, 0x16, 0xBC, 0x54, 0x93, 0x68, 0xFC, 0xD5, 0x6F, 0xFF, 0xFF, 0xFF, 0x3E, 0x3D, 0x68, 0x0D, 0xF9, 0x20, + 0x73, 0x8F, 0x42, 0x1A, 0xAB, 0x24, 0xAA, 0x94, 0x84, 0xCF, 0xF3, 0xE0, 0x20, 0xF0, 0xDA, 0x52, 0xFA, 0x45, 0x60, 0x80, + 0xAD, 0xEE, 0x67, 0x4E, 0x3B, 0x6E, 0xFE, 0x72, 0xF4, 0x61, 0x96, 0xF6, 0x14, 0xAF, 0x81, 0xD2, 0x44, 0xEF, 0x35, 0x01, + 0xA3, 0x62, 0x77, 0x17, 0xE2, 0x26, 0x19, 0x66, 0x86, 0x87, 0xBD, 0x53, 0x36, 0x26, 0x36, 0x11, 0x38, 0x99, 0x0B, 0xBB, + 0xF3, 0x87, 0x00, 0xAC, 0x55, 0xAF, 0x68, 0x9E, 0xEE, 0x49, 0x8E, 0xD4, 0xE5, 0xE9, 0xFA, 0xF5, 0xF4, 0xF8, 0x93, 0x54, + 0x9E, 0x98, 0x40, 0x9F, 0xAA, 0x94, 0x21, 0x87, 0x3D, 0xC1, 0x75, 0xBB, 0x84, 0x1D, 0xC5, 0xA7, 0x6A, 0x7C, 0xAE, 0x12, + 0xBE, 0xE7, 0xAF, 0xD4, 0xB9, 0xA5, 0x5B, 0x31, 0x3C, 0xDA, 0xAF, 0x7C, 0x6C, 0xBA, 0x0F, 0xAC, 0x4E, 0x05, 0xC1, 0x58, + 0x38, 0x76, 0xD1, 0xFB, 0x84, 0x49, 0x93, 0xEE, 0xF8, 0xFD, 0x2A, 0x0C, 0xA3, 0x2B, 0x22, 0x5B, 0x56, 0xB7, 0xF5, 0x6B, + 0x75, 0xA8, 0xF2, 0x2E, 0xE6, 0xFC, 0xF6, 0xAB, 0x6F, 0xE4, 0x0A, 0xC4, 0xD4, 0xD2, 0x3B, 0xF7, 0x24, 0x07, 0xFB, 0x29, + 0x50, 0x70, 0xA7, 0x4B, 0x23, 0xC9, 0xAD, 0x4D, 0xD6, 0x95, 0x13, 0xF6, 0x60, 0xDA, 0xF3, 0x6E, 0xD2, 0x70, 0x4F, 0x49, + 0x49, 0x54, 0x59, 0x0C, 0x78, 0xCA, 0x10, 0x7F, 0xBD, 0xA1, 0xA0, 0x4C, 0xC7, 0xAD, 0x0B, 0x4D, 0x49, 0xDD, 0xEC, 0x44, + 0xD7, 0xCA, 0xC2, 0x2A, 0x69, 0xF2, 0x31, 0xD8, 0x20, 0x98, 0x22, 0x7A, 0x23, 0x0F, 0xCB, 0xF8, 0x44, 0xD0, 0x8A, 0x79, + 0x7D, 0xA1, 0x3C, 0x12, 0x67, 0xA4, 0x93, 0x81, 0x3E, 0xC3, 0x99, 0xAD, 0xF0, 0x9B, 0x35, 0x18, 0x08, 0x02, 0x30, 0xD9, + 0xA8, 0x65, 0x02, 0x4F, 0xCD, 0x54, 0xE5, 0xAC, 0x56, 0xC9, 0x7A, 0x87, 0x81, 0x51, 0x15, 0x77, 0xB4, 0xBD, 0x2C, 0x5B, + 0xCC, 0x5D, 0x25, 0x20, 0x37, 0xFA, 0x1E, 0x8D, 0xCA, 0x55, 0xB4, 0xB0, 0xDA, 0x75, 0x45, 0x61, 0x65, 0xD1, 0x8D, 0xF3, + 0xBB, 0x4B, 0x3B, 0xA8, 0xC8, 0x1F, 0xD7, 0xC3, 0x5B, 0x56, 0xEE, 0x86, 0x41, 0xAD, 0xAF, 0x56, 0xC0, 0xDF, 0x37, 0x21, + 0x24, 0xBC, 0xB7, 0x25, 0x3C, 0x9C, 0xD2, 0xDE, 0x3F, 0x8E, 0x95, 0xB1, 0xD8, 0xD9, 0x9B, 0xFD, 0xF6, 0xC5, 0x9E, 0xC5, + 0x91, 0x76, 0x0E, 0xE4, 0x64, 0x6F, 0x50, 0xF7, 0x61, 0x97, 0x6A, 0xF8, 0x80, 0x90, 0xB4, 0xA7, 0x0B, 0x3E, 0x97, 0x74, + 0x58, 0xE5, 0x70, 0x87, 0x19, 0xD3, 0xE2, 0xFC, 0x4B, 0x4C, 0x9C, 0x01, 0xD1, 0x16, 0x62, 0xF8, 0xBA, 0x7E, 0xD3, 0xCD, + 0x72, 0x6A, 0x5B, 0xF8, 0xA5, 0x2C, 0xCF, 0xC4, 0x8B, 0x1F, 0x6A, 0xD8, 0x90, 0x57, 0x8F, 0x06, 0xC9, 0x1B, 0xA2, 0xAC, + 0x4B, 0xCE, 0x22, 0xA8, 0xD1, 0x7B, 0x0C, 0xAA, 0xDB, 0x05, 0xCC, 0x56, 0x10, 0x69, 0x54, 0xB6, 0x5F, 0xB6, 0xDA, 0x39, + 0xCE, 0x55, 0xF2, 0xCB, 0x0F, 0xFF, 0xC6, 0xB8, 0x50, 0x53, 0x11, 0x28, 0x43, 0x5E, 0x91, 0xEF, 0x47, 0x97, 0x0D, 0xAB, + 0x7A, 0x1B, 0x57, 0x44, 0x8F, 0x77, 0xAB, 0xBD, 0x26, 0xB6, 0x30, 0xB9, 0x52, 0x7F, 0x4E, 0xCA, 0x87, 0xD2, 0x5F, 0x54, + 0xA1, 0xFA, 0xE4, 0xF8, 0x2E, 0xB3, 0x13, 0xDD, 0x0A, 0x1D, 0x41, 0x1B, 0x40, 0xC1, 0xE8, 0x59, 0xB0, 0xBF, 0x1E, 0xAB, + 0x13, 0x9C, 0x5D, 0x2F, 0x47, 0x92, 0x04, 0xDE, 0x6D, 0x46, 0x16, 0x6F, 0x51, 0xD0, 0x13, 0xBB, 0xD4, 0xB1, 0x69, 0xE9, + 0x5B, 0x91, 0x84, 0x1A, 0xC8, 0x81, 0xA9, 0x45, 0x75, 0xD3, 0xCF, 0x22, 0x52, 0x73, 0x1B, 0x5F, 0x33, 0x7D, 0x15, 0x9B, + 0x09, 0x7F, 0x93, 0x6E, 0xD9, 0x75, 0x76, 0xDF, 0x8B, 0xDF, 0xA0, 0x3B, 0x30, 0x2B, 0x0E, 0x87, 0x25, 0xC4, 0x88, 0xC9, + 0x70, 0x8E, 0x08, 0xF8, 0xF0, 0x08, 0x08, 0xE6, 0xA1, 0x02, 0x2E, 0x50, 0xBA, 0x6C, 0xC1, 0xC6, 0xD5, 0xF7, 0x9E, 0x8C, + 0x31, 0x0B, 0x91, 0x36, 0xE0, 0x0D, 0x50, 0x07, 0x2D, 0xE1, 0x56, 0x59, 0xB5, 0xE6, 0x09, 0x99, 0xA1, 0x2E, 0xBE, 0xE4, + 0x19, 0xE2, 0x69, 0x17, 0xA6, 0xC6, 0x29, 0x06, 0xFF, 0x4C, 0x9F, 0x80, 0xA7, 0x5B, 0xD8, 0x36, 0x1E, 0xAF, 0xA2, 0x8C, + 0xEA, 0xC9, 0xA2, 0xA6, 0x5A, 0x40, 0xA7, 0x7E, 0xCF, 0x8C, 0x28, 0xBE, 0x5B, 0xE7, 0x6B, 0xF6, 0x74, 0xCB, 0x14, 0xE5, + 0x3D, 0xED, 0xA1, 0x1A, 0x4F, 0x22, 0xF3, 0xC3, 0xA5, 0x63, 0xDD, 0xF0, 0xBE, 0x6B, 0xBF, 0xD7, 0x3F, 0x2C, 0xFC, 0x14, + 0x66, 0x21, 0xB0, 0xC7, 0x96, 0x95, 0x31, 0xF7, 0xA4, 0x5D, 0x7D, 0x64, 0x90, 0x44, 0xB1, 0x3B, 0xAD, 0x77, 0xF8, 0x2C, + 0x74, 0x39, 0x24, 0x8B, 0xA7, 0x8C, 0xE6, 0x5C, 0x36, 0xEB, 0x70, 0x7A, 0x71, 0x26, 0xFC, 0x33, 0xF6, 0xCD, 0x44, 0x3D, + 0x69, 0x66, 0xF1, 0x10, 0x42, 0x64, 0x1D, 0x32, 0xA2, 0x55, 0xDD, 0x09, 0xFF, 0xFF, 0x69, 0x05, 0xA6, 0xC9, 0xCD, 0x8F, + 0xF8, 0x9F, 0x8B, 0xEB, 0x61, 0x58, 0x3B, 0xEF, 0x03, 0x0A, 0x9F, 0x59, 0x3E, 0xAE, 0xC4, 0xC2, 0x7D, 0x30, 0x7A, 0xB9, + 0x76, 0x01, 0x22, 0xA7, 0x46, 0x1D, 0xB2, 0x82, 0x52, 0x8E, 0xCC, 0xBB, 0xD3, 0x4A, 0x50, 0xA9, 0x37, 0x38, 0x94, 0xFE, + 0xE8, 0x26, 0x20, 0xE4, 0x49, 0xD6, 0x34, 0xCA, 0xB6, 0xF7, 0x05, 0x96, 0x65, 0x1F, 0x9D, 0xEE, 0x6F, 0x7D, 0x2A, 0xFB, + 0xCF, 0xDE, 0x21, 0xAF, 0xD2, 0x4A, 0x7E, 0x64, 0xBF, 0xCD, 0x0C, 0xDB, 0xAC, 0x25, 0x0B, 0x8B, 0xC7, 0xC0, 0x17, 0xEC, + 0xB1, 0xE7, 0xF4, 0x11, 0x12, 0x3D, 0x9E, 0x36, 0xB1, 0x1F, 0x14, 0x48, 0x8D, 0x73, 0x34, 0x55, 0x5E, 0x7D, 0x12, 0x33, + 0x44, 0x95, 0xBA, 0xBE, 0xDE, 0xF5, 0x67, 0xB2, 0xAD, 0x8B, 0xE8, 0x87, 0xD4, 0x4E, 0x70, 0xF3, 0x24, 0x8D, 0x01, 0xA3, + 0xD7, 0x5D, 0x2F, 0xA1, 0x76, 0x93, 0x66, 0x54, 0xD6, 0x5F, 0x4C, 0xB7, 0xC6, 0x96, 0x97, 0x27, 0x3C, 0x1C, 0x45, 0x81, + 0x11, 0xDC, 0x83, 0x17, 0xDB, 0x6C, 0x02, 0x0E, 0x25, 0x3D, 0xDC, 0x37, 0x95, 0xE4, 0x62, 0x66, 0x55, 0x11, 0x72, 0x95, + 0x35, 0xFD, 0x35, 0x66, 0x90, 0xF0, 0x92, 0x77, 0x9B, 0xB8, 0x25, 0x62, 0x66, 0x87, 0x3C, 0x2F, 0x23, 0x78, 0xA5, 0x2B, + 0x42, 0xD4, 0xD7, 0xD4, 0x15, 0xB5, 0xB5, 0x0B, 0xAA, 0x94, 0x71, 0x47, 0xE0, 0xE6, 0x55, 0x14, 0x6D, 0xE6, 0x93, 0x73, + 0x35, 0xB3, 0x43, 0x52, 0x3D, 0x28, 0xA4, 0x78, 0x50, 0xB6, 0x30, 0xB7, 0xC7, 0xDC, 0x02, 0xAA, 0x9D, 0x67, 0x20, 0x7B, + 0x48, 0xC3, 0x89, 0x9E, 0x5D, 0x07, 0x50, 0x9D, 0x09, 0x38, 0xC8, 0x3A, 0xC8, 0x1F, 0x86, 0x51, 0x7D, 0x94, 0x05, 0xFC, + 0xDC, 0x04, 0x7D, 0xA5, 0xC6, 0x4B, 0x13, 0xED, 0x43, 0xD4, 0x0E, 0xCD, 0x53, 0xCA, 0x8C, 0x1F, 0x54, 0x25, 0x3E, 0x68, + 0x29, 0x16, 0xFB, 0xBB, 0x56, 0xFF, 0xC6, 0xB3, 0x48, 0xA7, 0x97, 0xDD, 0x04, 0x7A, 0x58, 0xE6, 0x28, 0x87, 0x2A, 0xAC, + 0xB3, 0xDE, 0x48, 0x4A, 0xBC, 0x03, 0x96, 0xAC, 0x8F, 0xF1, 0x37, 0xE4, 0x4C, 0xBD, 0x09, 0x9E, 0x77, 0xB0, 0x27, 0x2E, + 0x0C, 0xFD, 0x77, 0x8D, 0x4D, 0x7B, 0x0F, 0x8B, 0xCE, 0xDC, 0x18, 0xBC, 0x98, 0xD2, 0x2D, 0xC9, 0x92, 0x9C, 0x5B, 0x7D, + 0xCE, 0xF4, 0x17, 0x5F, 0x9C, 0xAF, 0x10, 0x5A, 0x54, 0xFC, 0x07, 0x0B, 0x47, 0x2E, 0x7D, 0x3F, 0xB3, 0x52, 0x55, 0x47, + 0xC2, 0xC0, 0xFE, 0x2C, 0xF9, 0x31, 0x06, 0x42, 0xBF, 0xED, 0x86, 0x0C, 0xBB, 0x24, 0xE4, 0x82, 0x45, 0x0B, 0x08, 0x57, + 0x17, 0x8A, 0x20, 0xCE, 0xED, 0x4C, 0x3C, 0x56, 0x30, 0x01, 0x49, 0x1D, 0x69, 0x31, 0x2D, 0x96, 0x8B, 0x2A, 0x02, 0xA5, + 0xF3, 0xA2, 0xAB, 0x95, 0x59, 0xCD, 0xDB, 0x62, 0xB3, 0x6F, 0xF1, 0x11, 0x78, 0x32, 0xB5, 0xA2, 0xFD, 0xC8, 0x81, 0x31, + 0x58, 0xB3, 0xFF, 0xA2, 0x4A, 0x35, 0x2C, 0xD7, 0x01, 0x2E, 0x18, 0x6D, 0xBA, 0x75, 0x10, 0x8D, 0x7E, 0x69, 0x10, 0x54, + 0x4B, 0x54, 0xB0, 0x66, 0x24, 0x25, 0xB2, 0x61, 0x7B, 0x41, 0x4C, 0x84, 0x32, 0x6A, 0x47, 0x6C, 0x6B, 0x77, 0xD4, 0x3F, + 0x5A, 0x7C, 0xE6, 0x49, 0xC4, 0x8D, 0x89, 0x71, 0xD4, 0x5D, 0x69, 0xD3, 0xCB, 0x16, 0xDF, 0x84, 0x6C, 0x7A, 0xE4, 0x60, + 0xF3, 0x43, 0xDF, 0x49, 0x3A, 0xB6, 0x60, 0x1C, 0x09, 0xF9, 0xB0, 0x3C, 0x39, 0x6A, 0x32, 0xC2, 0xBD, 0xC1, 0xAC, 0xE0, + 0x90, 0x79, 0x0E, 0xFA, 0x6A, 0x19, 0x92, 0x6F, 0x46, 0x6B, 0x45, 0x39, 0xB5, 0xF8, 0x0B, 0xCF, 0x65, 0xE4, 0x63, 0x4A, + 0xF8, 0x81, 0xDA, 0x1E, 0x17, 0x8C, 0x33, 0xA3, 0xCB, 0x9A, 0xEB, 0x1F, 0x10, 0x65, 0x1D, 0xC0, 0x62, 0xB1, 0xD2, 0x28, + 0x9A, 0x6B, 0xA8, 0x01, 0xCF, 0xDA, 0xE5, 0x14, 0x30, 0x5A, 0x76, 0x4C, 0x2E, 0x81, 0x94, 0xAE, 0xED, 0x59, 0xBB, 0x4C, + 0x79, 0x00, 0x8A, 0x68, 0x12, 0xDD, 0x2A, 0x5A, 0x00, 0x00, 0x00, 0x9C, 0x19, 0xA6, 0xF6, 0xEB, 0x4C, 0xD2, 0xFA, 0x22, + 0x7F, 0x2F, 0x23, 0x57, 0xF4, 0x01, 0x8D, 0x22, 0x15, 0x88, 0xEB, 0x96, 0xE9, 0x2C, 0x54, 0x6F, 0x77, 0xDE, 0x12, 0x5B, + 0x2C, 0x09, 0xFB, 0x60, 0x9D, 0x34, 0x61, 0xEA, 0xC0, 0x54, 0x94, 0x4C, 0xA4, 0x66, 0x5A, 0x25, 0x64, 0xBD, 0xA4, 0xC4, + 0x64, 0xBB, 0x34, 0x37, 0x89, 0xA1, 0xEA, 0xA2, 0x13, 0xD6, 0x04, 0x94, 0xA9, 0xEF, 0x2C, 0xE6, 0x53, 0xE5, 0x45, 0x3F, + 0x02, 0x71, 0x30, 0x2F, 0x8E, 0xAC, 0x54, 0x46, 0x62, 0xD2, 0x78, 0xB4, 0x80, 0x9D, 0x1B, 0x9D, 0xC1, 0xF2, 0x46, 0x21, + 0xC3, 0x06, 0x33, 0x38, 0x63, 0xD3, 0xF3, 0x92, 0xD2, 0x13, 0xE5, 0xC2, 0xD3, 0x3D, 0xFE, 0xEE, 0x0C, 0xCF, 0x3C, 0x42, + 0xAA, 0x36, 0x3F, 0xB7, 0x25, 0xB4, 0x8B, 0x64, 0x51, 0x2F, 0x14, 0x29, 0xAB, 0x35, 0x15, 0xD2, 0x84, 0x13, 0xB2, 0x70, + 0xCE, 0x94, 0x92, 0x37, 0xA9, 0x4F, 0x92, 0x70, 0x33, 0x1D, 0x7D, 0xA1, 0xE2, 0x1B, 0x69, 0x5E, 0x3F, 0x54, 0x6D, 0x12, + 0xF1, 0xFB, 0x78, 0x9A, 0x6F, 0x6D, 0x6D, 0x22, 0x02, 0x9D, 0xF5, 0x2A, 0x46, 0x54, 0x15, 0xD4, 0x80, 0xCC, 0x60, 0xC4, + 0x52, 0xD6, 0x0E, 0x8C, 0xA0, 0xE6, 0xFE, 0xFF, 0x23, 0xBA, 0x74, 0xAC, 0x6B, 0x98, 0xED, 0x6B, 0x81, 0xFE, 0x1B, 0xEB, + 0x11, 0x75, 0x69, 0x5C, 0x15, 0x92, 0x16, 0xA9, 0x4B, 0x98, 0xFC, 0xBE, 0x78, 0xB8, 0x39, 0x3D, 0xE8, 0xB5, 0x78, 0xFE, + 0x88, 0x56, 0x29, 0x00, 0x2A, 0x1A, 0x97, 0xD7, 0x99, 0x7E, 0x69, 0x2C, 0xAA, 0x52, 0xF7, 0x99, 0x50, 0x2A, 0x9D, 0xBB, + 0xE9, 0xD6, 0xA1, 0x90, 0x91, 0x76, 0xC1, 0x3B, 0x1A, 0x15, 0x3D, 0xB3, 0x5A, 0x35, 0x96, 0x00, 0x55, 0x51, 0xEE, 0xDC, + 0x3C, 0xD3, 0x36, 0x20, 0xC7, 0xA6, 0x35, 0xE7, 0x1D, 0x7F, 0x9E, 0x10, 0x54, 0x50, 0xA0, 0xFB, 0x7D, 0xFD, 0x45, 0x4B, + 0x7E, 0xAD, 0x38, 0xB3, 0xD8, 0x1B, 0x29, 0x38, 0x89, 0xE5, 0x77, 0x9F, 0x98, 0x12, 0x57, 0xF6, 0xF8, 0x4A, 0x81, 0xD7, + 0x43, 0x7C, 0x21, 0x2D, 0xED, 0xD4, 0x42, 0x7F, 0x76, 0xFF, 0x97, 0xA6, 0x02, 0xCA, 0x8C, 0x1A, 0x77, 0x3F, 0xA4, 0x5D, + 0x67, 0x10, 0x1C, 0xB5, 0x43, 0xEA, 0x16, 0xDB, 0x88, 0xE3, 0x73, 0xE6, 0x1D, 0xAE, 0x8F, 0x0B, 0xB1, 0x50, 0x80, 0xC9, + 0xBC, 0xB0, 0xFD, 0xF2, 0xAA, 0xC2, 0xB7, 0x2F, 0x92, 0x99, 0x11, 0xB3, 0x25, 0x7D, 0xAC, 0x54, 0xE8, 0x43, 0xD6, 0x60, + 0xB7, 0xED, 0x97, 0x3F, 0xB4, 0x82, 0xF9, 0x0B, 0xE9, 0x3E, 0x6D, 0xC9, 0xB6, 0x7C, 0xC3, 0xFB, 0x65, 0x94, 0x2A, 0x3D, + 0xB5, 0xD4, 0x2E, 0x84, 0x56, 0x58, 0x2B, 0x45, 0x50, 0x67, 0xC4, 0xC0, 0x03, 0x8D, 0x6B, 0x54, 0xA2, 0x35, 0x06, 0xB6, + 0x63, 0x31, 0xA8, 0xEB, 0x1D, 0xE3, 0x19, 0xAB, 0x2E, 0xCB, 0x66, 0xF8, 0x96, 0x86, 0x89, 0x11, 0x2D, 0xEC, 0x9E, 0xE3, + 0xA5, 0xC9, 0x73, 0xF3, 0xE3, 0xAE, 0xC9, 0x94, 0xB3, 0x53, 0x6C, 0x01, 0x2C, 0xD6, 0xD5, 0x4F, 0x76, 0xEC, 0xC5, 0xCA, + 0x54, 0x25, 0xFC, 0xEC, 0x18, 0x2D, 0x2A, 0x22, 0x04, 0x39, 0x25, 0xDD, 0xD8, 0x63, 0x08, 0xE5, 0xE4, 0xBA, 0x8C, 0xD9, + 0xDF, 0xB9, 0x3C, 0x06, 0x05, 0x98, 0x82, 0xC4, 0xF1, 0xE4, 0xEA, 0xFA, 0x2F, 0xEA, 0xB1, 0xD3, 0x9A, 0xB1, 0x0D, 0x16, + 0xEF, 0x8A, 0xC6, 0x93, 0x37, 0x8E, 0xC7, 0x84, 0x8C, 0xEB, 0x10, 0x6F, 0x1D, 0x2D, 0x1B, 0x0C, 0x85, 0xFA, 0xC4, 0xCF, + 0xFC, 0x1A, 0x02, 0x48, 0x5B, 0x81, 0x32, 0x3D, 0x38, 0x08, 0x4C, 0x42, 0xC3, 0x6A, 0x75, 0xEA, 0x65, 0x0B, 0x3A, 0x38, + 0x48, 0x8B, 0xD5, 0xB2, 0x1F, 0x5C, 0xA1, 0xFE, 0x7C, 0xB6, 0x21, 0xF8, 0x59, 0x77, 0x49, 0xCE, 0xCD, 0x6E, 0x2A, 0xAD, + 0x7E, 0x51, 0x66, 0xAB, 0xCB, 0x45, 0x33, 0x9A, 0xBD, 0xAC, 0xC8, 0xE6, 0xEC, 0xAF, 0x14, 0x31, 0xF5, 0xA0, 0x43, 0x88, + 0x80, 0x44, 0x25, 0x7B, 0x96, 0xB4, 0x1A, 0x32, 0x64, 0x3F, 0x96, 0xB6, 0x11, 0xF2, 0x6D, 0x2D, 0xC3, 0xCB, 0x4B, 0xD5, + 0x40, 0xB2, 0x4A, 0x23, 0x26, 0xDB, 0xAD, 0xE8, 0x54, 0xB5, 0x62, 0x17, 0x21, 0x24, 0x94, 0xB0, 0xF8, 0x94, 0xB4, 0xF0, + 0x90, 0xFE, 0xFC, 0x94, 0x3B, 0x34, 0xD0, 0xC5, 0xC5, 0xB2, 0xEC, 0xB2, 0x75, 0x96, 0x13, 0xBA, 0x6D, 0xC9, 0xCF, 0x95, + 0xB4, 0x63, 0xE9, 0x37, 0xFE, 0x69, 0x85, 0x2C, 0x0A, 0x53, 0xA9, 0x3F, 0x07, 0x4F, 0xBF, 0xC6, 0x30, 0xF4, 0x6A, 0xA5, + 0x8F, 0x1E, 0xCC, 0xF6, 0xD5, 0xB5, 0x32, 0xFA, 0x2F, 0x38, 0xD3, 0x11, 0xFD, 0xAF, 0x7A, 0x23, 0x61, 0x5E, 0xFC, 0xF6, + 0x77, 0xF5, 0x51, 0x47, 0xAD, 0xA9, 0xF4, 0xE3, 0x4E, 0x5C, 0x13, 0x32, 0xC7, 0x76, 0xF5, 0xE7, 0xF6, 0xF6, 0x20, 0x43, + 0x58, 0x3A, 0xA5, 0xEF, 0x4E, 0xF5, 0x63, 0xE2, 0xA8, 0xD3, 0xFD, 0xF7, 0xF7, 0xF7, 0x5E, 0xB8, 0xD8, 0x97, 0xFC, 0x75, + 0x54, 0xA9, 0xA6, 0x56, 0xB8, 0x23, 0x16, 0x7D, 0xF8, 0xB8, 0x50, 0xA3, 0xDC, 0x4A, 0x0D, 0x6D, 0xB1, 0x32, 0xE7, 0xBA, + 0x8C, 0x66, 0x86, 0x24, 0xFE, 0xBD, 0x7C, 0x8B, 0xC4, 0xCB, 0xD9, 0x89, 0x5D, 0x39, 0x4C, 0xD8, 0xF7, 0xA5, 0xF1, 0xA8, + 0xB6, 0xBE, 0x51, 0xA3, 0x44, 0x2A, 0xAB, 0x7D, 0xDE, 0xB8, 0xFF, 0x6F, 0xAE, 0x56, 0xD7, 0xB8, 0x5E, 0x9E, 0x77, 0x8D, + 0xF0, 0x96, 0xBB, 0x5A, 0xD5, 0x6D, 0x9C, 0x1A, 0x2E, 0x7D, 0xF6, 0xEE, 0x7E, 0xFC, 0x50, 0x16, 0x6D, 0x62, 0x59, 0x0F, + 0xC2, 0xD3, 0x88, 0xDE, 0xB6, 0x20, 0xFE, 0xFE, 0x7F, 0xFD, 0x24, 0x3A, 0x96, 0xBE, 0x5E, 0x73, 0x55, 0x0F, 0x66, 0x18, + 0xDE, 0xDA, 0xF7, 0xEF, 0xFE, 0xFE, 0x51, 0xF2, 0x22, 0x69, 0x89, 0x0B, 0xBC, 0x5D, 0x50, 0xC1, 0xA0, 0x42, 0xFF, 0xFF, + 0x03, 0xB9, 0x80, 0x0C, 0x8D, 0x40, 0x08, 0xC4, 0x1C, 0x60, 0xBB, 0x67, 0x4E, 0x9C, 0x15, 0x6E, 0xAC, 0x68, 0xA7, 0xE1, + 0xED, 0x0C, 0xC2, 0x15, 0xEE, 0x85, 0xD4, 0xC3, 0x4E, 0x9C, 0xC3, 0x34, 0x57, 0x31, 0x83, 0xDE, 0xEB, 0xC7, 0x01, 0xE2, + 0x79, 0x81, 0xD5, 0xEB, 0x7B, 0xE3, 0x4A, 0x25, 0x28, 0x83, 0x57, 0x22, 0x01, 0xA8, 0x5B, 0x55, 0x78, 0x0B, 0x4F, 0xF5, + 0x2A, 0x09, 0x5C, 0x4A, 0xB9, 0x6E, 0xAD, 0x3E, 0x83, 0x09, 0xC8, 0x60, 0x79, 0x0C, 0x18, 0x5A, 0x1F, 0x4F, 0xD1, 0x74, + 0x2D, 0x64, 0x04, 0x61, 0xA2, 0x84, 0x96, 0x11, 0x8D, 0x8E, 0x26, 0x76, 0x93, 0x21, 0x7F, 0x39, 0x71, 0x35, 0xFE, 0x03, + 0x23, 0xAB, 0x24, 0xB4, 0x97, 0x2F, 0xD1, 0x70, 0x9F, 0xC4, 0xF1, 0x61, 0xAD, 0x46, 0x1A, 0xD5, 0x9F, 0x61, 0xC3, 0x35, + 0x16, 0xD7, 0x67, 0xB4, 0x60, 0xE7, 0xDB, 0x88, 0xD7, 0x63, 0x30, 0x18, 0x8D, 0x1E, 0x98, 0x08, 0x3B, 0x99, 0x38, 0xC2, + 0x0B, 0x47, 0x6D, 0x52, 0x76, 0xB7, 0x2D, 0x19, 0x62, 0x7D, 0x82, 0x19, 0x1D, 0x69, 0x50, 0x25, 0x58, 0xE6, 0x13, 0x42, + 0x3B, 0x1F, 0x5D, 0x13, 0x88, 0xA1, 0xBD, 0xB9, 0x52, 0x69, 0x3A, 0x5A, 0xC7, 0xC6, 0x2C, 0x1D, 0xF9, 0xC5, 0x89, 0xDF, + 0x1B, 0x08, 0x30, 0x6E, 0xFB, 0x28, 0x57, 0x4A, 0xC6, 0xC1, 0xE5, 0x74, 0xF9, 0xDB, 0x69, 0x36, 0xDB, 0xB0, 0x75, 0x60, + 0x6D, 0x2C, 0x5A, 0x98, 0x4E, 0xED, 0x52, 0x91, 0x52, 0x98, 0xB5, 0x9A, 0xAA, 0xD2, 0x0A, 0x50, 0x05, 0xD0, 0x0C, 0x28, + 0xA0, 0xC5, 0x36, 0xEF, 0x46, 0x67, 0xFC, 0x12, 0x09, 0x03, 0xF4, 0x65, 0xE9, 0x2E, 0x5D, 0x9A, 0x83, 0xC3, 0xDB, 0x80, + 0xDE, 0x13, 0xE7, 0x22, 0x55, 0xA0, 0xDD, 0x3F, 0x64, 0xF2, 0x01, 0x7D, 0xA3, 0x57, 0x5F, 0x79, 0x93, 0x0D, 0x7A, 0x86, + 0xC1, 0x93, 0x15, 0xF7, 0x56, 0x5C, 0x6D, 0xF6, 0x95, 0x9C, 0x91, 0x55, 0x33, 0x50, 0x74, 0x81, 0x20, 0xBC, 0x0C, 0x90, + 0x9E, 0x9C, 0xC7, 0xB8, 0x1E, 0x80, 0x56, 0x74, 0xC5, 0xDB, 0x2D, 0x72, 0x2C, 0x9F, 0xE3, 0x20, 0xB1, 0x52, 0x14, 0xF7, + 0x1D, 0x9E, 0xCB, 0x74, 0x28, 0xD9, 0x05, 0x23, 0xF5, 0x8E, 0xDF, 0x6D, 0x35, 0x30, 0xDD, 0xB5, 0x52, 0xF2, 0x5D, 0xB8, + 0xBE, 0x72, 0x3A, 0x9C, 0xA1, 0x19, 0xE4, 0x35, 0xD2, 0xB4, 0xD1, 0x26, 0x99, 0xC1, 0xAC, 0xD6, 0xBA, 0x7B, 0x42, 0xD6, + 0xEB, 0x9D, 0x6B, 0xCF, 0x58, 0x41, 0x7A, 0xBC, 0xE7, 0xF1, 0x5E, 0xE7, 0x1D, 0xDD, 0x96, 0x32, 0xFB, 0xB2, 0x6D, 0x4F, + 0x66, 0xA2, 0x2D, 0x65, 0xB2, 0xBE, 0xDB, 0x16, 0xB7, 0x72, 0xE9, 0xB3, 0x54, 0x72, 0x8E, 0x13, 0x21, 0x34, 0x50, 0xF6, + 0x16, 0x58, 0xFB, 0x5D, 0xB6, 0x35, 0x3C, 0x7B, 0x29, 0xB5, 0xBE, 0x9C, 0x43, 0x3C, 0x2E, 0x98, 0x4C, 0x47, 0x91, 0xA9, + 0x7C, 0x38, 0x3C, 0xA8, 0x3D, 0xE6, 0x4E, 0x91, 0xC9, 0x02, 0xB4, 0xC7, 0xAC, 0xF9, 0xA0, 0xFC, 0xF4, 0xFF, 0x0F, 0x78, + 0x0B, 0x5A, 0xA7, 0x89, 0xC3, 0x3A, 0xBD, 0xD7, 0x2D, 0x4A, 0x26, 0xDF, 0x13, 0x72, 0x31, 0x7B, 0xCB, 0x18, 0xBF, 0x92, + 0xFC, 0x6F, 0x17, 0xCA, 0xE8, 0x37, 0x19, 0xFD, 0xF5, 0x3B, 0x7E, 0x8F, 0xE0, 0x84, 0x25, 0x37, 0x51, 0xFA, 0xE2, 0x97, + 0xC9, 0xD7, 0x53, 0x11, 0xFA, 0x64, 0xB5, 0x5C, 0x37, 0x53, 0xF4, 0x2F, 0xF1, 0x96, 0x94, 0x8A, 0x01, 0xF7, 0xE9, 0xD4, + 0x08, 0x7D, 0xB8, 0xB7, 0x60, 0x66, 0x63, 0x3C, 0x74, 0x7E, 0x53, 0xD8, 0xAD, 0xF1, 0x60, 0xC1, 0x8D, 0x7E, 0xE3, 0x4A, + 0xFE, 0xA0, 0xAD, 0xCD, 0x50, 0xE9, 0x21, 0x28, 0x5C, 0x1D, 0x1F, 0xF1, 0xE5, 0x82, 0xC3, 0xF9, 0x20, 0xC0, 0x98, 0x12, + 0x67, 0xE4, 0xB7, 0xD1, 0x49, 0x6D, 0x23, 0x00, 0x04, 0x6D, 0x9F, 0x13, 0x88, 0x8D, 0xF3, 0x15, 0x6E, 0xAD, 0x30, 0x3F, + 0x76, 0xFC, 0xF2, 0x37, 0x28, 0xE8, 0x26, 0x5B, 0x0B, 0x80, 0xFE, 0x47, 0x14, 0x22, 0x7D, 0xE4, 0x06, 0x31, 0x65, 0xD8, + 0x3D, 0x41, 0x41, 0x33, 0xDD, 0xE3, 0x69, 0x1A, 0x65, 0x98, 0x63, 0xCC, 0x62, 0xD8, 0xFB, 0x44, 0xA1, 0x62, 0x6B, 0x38, + 0xD0, 0x2B, 0x34, 0xB8, 0x34, 0xB4, 0x0E, 0x2A, 0xA7, 0x67, 0xCE, 0xD7, 0x15, 0xC4, 0x50, 0x62, 0x75, 0xC7, 0x17, 0x28, + 0x39, 0x7A, 0x7C, 0xB8, 0x8F, 0x74, 0x78, 0x96, 0x6F, 0x4E, 0xEC, 0x30, 0x8D, 0x27, 0x67, 0x38, 0xFE, 0xAB, 0xFF, 0x90, + 0x8B, 0x86, 0x8F, 0x3F, 0x6B, 0x6F, 0xEC, 0x9C, 0x72, 0x8B, 0xD7, 0xF7, 0x56, 0x2D, 0x71, 0x00, 0xC6, 0xA9, 0x77, 0x70, + 0x3C, 0xFF, 0xA2, 0x0A, 0xE1, 0x23, 0xBA, 0x01, 0x59, 0xFC, 0x88, 0xCC, 0x48, 0x88, 0xFA, 0xD1, 0xBD, 0x6B, 0xA0, 0x68, + 0xE6, 0x81, 0xAD, 0xAF, 0x3F, 0xD9, 0x89, 0xBE, 0x49, 0xD6, 0xE4, 0xEE, 0x55, 0x46, 0xAC, 0x49, 0xE7, 0x80, 0x2D, 0x04, + 0x8D, 0xAB, 0xCF, 0xD7, 0xDC, 0x31, 0x94, 0x64, 0x21, 0xD6, 0x71, 0x4F, 0xE5, 0x83, 0x7B, 0x6C, 0xB3, 0xAF, 0x2D, 0x59, + 0xAD, 0x58, 0xF5, 0x34, 0x9A, 0xEF, 0x5A, 0x35, 0x8F, 0x81, 0x9A, 0x1E, 0x0E, 0x03, 0x10, 0x6A, 0x4F, 0x9F, 0xD4, 0xCA, + 0x4B, 0xEF, 0x78, 0x7E, 0x09, 0xFD, 0xB4, 0x68, 0x93, 0x06, 0x70, 0x7D, 0xEE, 0x12, 0xF4, 0xCB, 0x7C, 0x5D, 0x5D, 0x8A, + 0xE6, 0x83, 0x85, 0xBE, 0x44, 0xBE, 0x55, 0x3A, 0x4A, 0x6A, 0x76, 0x1B, 0x37, 0xFD, 0x8F, 0x99, 0x2E, 0x7E, 0x5D, 0x5F, + 0xF4, 0x0A, 0xCF, 0x19, 0x30, 0x8D, 0xC5, 0x4A, 0x17, 0x8C, 0xDF, 0xFD, 0x45, 0xF0, 0x2A, 0x8D, 0x25, 0xB1, 0x56, 0xA6, + 0x67, 0xB0, 0x34, 0xD8, 0x17, 0x23, 0x14, 0x69, 0x56, 0x91, 0x2E, 0xE5, 0x13, 0x10, 0x3D, 0xA2, 0x1A, 0xF1, 0x86, 0x06, + 0xF4, 0x5E, 0x5B, 0x85, 0x70, 0xF6, 0xA2, 0x8E, 0x96, 0xC2, 0xB5, 0xA3, 0xEB, 0xD3, 0xA3, 0xE7, 0x1F, 0xB6, 0x74, 0xE1, + 0x00, 0x4C, 0xA5, 0x64, 0xB4, 0xB2, 0x1D, 0xB7, 0x9A, 0xD3, 0x19, 0xD5, 0xD4, 0x93, 0x5A, 0x20, 0xEC, 0x2C, 0x9A, 0x59, + 0x5D, 0x02, 0xF1, 0x37, 0x8F, 0xBC, 0xAD, 0xE2, 0xFB, 0x97, 0xCF, 0x16, 0xFB, 0xFF, 0x5E, 0xD1, 0xDC, 0x50, 0xF9, 0xB8, + 0x2D, 0xDD, 0x81, 0xC7, 0x66, 0x5A, 0x1E, 0x47, 0xF6, 0x7E, 0xE4, 0x34, 0x64, 0x1D, 0xB5, 0xEE, 0x6F, 0x94, 0x5E, 0x42, + 0x23, 0xE8, 0x81, 0xA0, 0xA8, 0x11, 0x93, 0xE4, 0xDC, 0x32, 0x5D, 0x4C, 0xAD, 0xFF, 0xF4, 0x89, 0x9D, 0x1F, 0x27, 0xEC, + 0xD3, 0xE3, 0xA1, 0x0E, 0xC1, 0xDB, 0x91, 0xEE, 0xC8, 0x88, 0x36, 0xAA, 0xA0, 0x94, 0x8D, 0x5E, 0xF1, 0xF3, 0xB8, 0xFC, + 0xC2, 0x64, 0xB2, 0x4B, 0x64, 0x99, 0xC0, 0x7F, 0x15, 0xF4, 0xA6, 0x0F, 0xB0, 0xD5, 0xC1, 0xED, 0x4B, 0x47, 0x0D, 0x0E, + 0xAC, 0x75, 0xED, 0xAB, 0x36, 0xD2, 0x11, 0x5E, 0x9E, 0x3B, 0x7B, 0x61, 0x40, 0xF9, 0x01, 0xFA, 0x62, 0x7D, 0xAD, 0x9B, + 0xFB, 0x8B, 0x99, 0xB9, 0x29, 0x1A, 0x66, 0x88, 0xAC, 0x68, 0xF6, 0xEA, 0x9D, 0xD2, 0x88, 0xBB, 0xB6, 0x9F, 0xA6, 0xDA, + 0x44, 0xF7, 0x4B, 0xDA, 0xB8, 0xAB, 0xCB, 0xBF, 0x97, 0xF7, 0xA0, 0xAE, 0x5E, 0xFC, 0x67, 0x8B, 0xEA, 0x35, 0xC4, 0xD0, + 0x66, 0x15, 0x1F, 0x6D, 0x12, 0x9F, 0x7E, 0x1E, 0xF3, 0x88, 0x90, 0xCA, 0xAC, 0x32, 0xBF, 0x41, 0x44, 0xBC, 0xBF, 0xF2, + 0x9B, 0x72, 0x7A, 0x67, 0x16, 0xEC, 0x0E, 0xB5, 0x23, 0xB0, 0xA2, 0x77, 0x09, 0x4E, 0x63, 0xDA, 0xF8, 0x18, 0x37, 0x61, + 0x3B, 0xE8, 0x70, 0x22, 0xC9, 0x0E, 0x3F, 0x50, 0xE5, 0x09, 0x09, 0x5E, 0x60, 0x6A, 0xB8, 0xE1, 0xAB, 0x21, 0x3F, 0x34, + 0x48, 0x41, 0xE3, 0x05, 0x91, 0xC2, 0x2C, 0x41, 0xF7, 0x17, 0x35, 0xD4, 0x99, 0xE2, 0x07, 0xE2, 0xC4, 0x07, 0x49, 0x0D, + 0x02, 0x51, 0x47, 0xDE, 0xCD, 0xE8, 0x0C, 0x46, 0xB3, 0x60, 0x45, 0xB1, 0x1F, 0x24, 0xD6, 0xA4, 0x1E, 0x64, 0x57, 0x26, + 0xD0, 0xEF, 0x89, 0x8B, 0xF7, 0xCB, 0x47, 0x90, 0xBF, 0x7D, 0xD0, 0x51, 0x17, 0x35, 0x7F, 0x81, 0xDF, 0xA5, 0x0C, 0xFC, + 0xF6, 0xCA, 0x1F, 0x19, 0x5A, 0xAD, 0x47, 0xE3, 0xF2, 0xB8, 0x72, 0x61, 0x0A, 0x17, 0x01, 0xED, 0x77, 0xC9, 0xF8, 0x09, + 0x3B, 0xBF, 0x08, 0xBD, 0x2C, 0x6A, 0xB1, 0xFB, 0xA0, 0x67, 0x4A, 0xFD, 0x76, 0xC8, 0x80, 0x1B, 0x66, 0xA0, 0x02, 0x09, + 0xD6, 0x69, 0xEF, 0x88, 0xCD, 0x5E, 0xAA, 0x38, 0x2F, 0x2C, 0x8F, 0xE5, 0x8C, 0xF9, 0x26, 0x5E, 0x9A, 0x84, 0x3D, 0x3C, + 0x22, 0x3D, 0x41, 0x3A, 0x26, 0x69, 0x25, 0xA1, 0xCD, 0x48, 0x6F, 0x8D, 0x64, 0x0A, 0x4D, 0x33, 0xC8, 0xE1, 0x4C, 0x2F, + 0x58, 0xEA, 0x35, 0xB5, 0xE1, 0x06, 0x59, 0x2D, 0x18, 0x84, 0x99, 0xFF, 0x5B, 0x48, 0x38, 0x79, 0x05, 0x03, 0x82, 0x44, + 0x0E, 0xF3, 0xBC, 0x61, 0x08, 0x61, 0x44, 0x31, 0xA1, 0xF4, 0x45, 0x1F, 0x7C, 0xCD, 0xF5, 0x69, 0xAA, 0xF2, 0xB4, 0xFC, + 0x09, 0x60, 0x51, 0x57, 0x56, 0x12, 0x49, 0x4D, 0x27, 0xC2, 0x97, 0xDA, 0x2B, 0xD1, 0xBD, 0x65, 0x88, 0x63, 0x69, 0xD8, + 0x9B, 0xE1, 0x07, 0x9E, 0xE2, 0xC3, 0xF0, 0xFC, 0x7C, 0xF2, 0x34, 0xD8, 0x1D, 0xFF, 0x6E, 0x20, 0xCD, 0x1F, 0x4D, 0x0E, + 0xFD, 0x01, 0xBB, 0x04, 0x3C, 0xF7, 0x50, 0x77, 0x29, 0x8B, 0x03, 0xE9, 0x89, 0xB1, 0xA4, 0xA6, 0x30, 0xAB, 0x82, 0xAF, + 0x30, 0xC5, 0x85, 0x54, 0x3D, 0x71, 0x99, 0xBB, 0x9D, 0xC9, 0x14, 0xAB, 0x7C, 0xDC, 0x23, 0xB8, 0xB9, 0xC7, 0x87, 0xFE, + 0x3F, 0x94, 0xD5, 0xAC, 0x69, 0x10, 0x35, 0x58, 0xD0, 0xA6, 0xEF, 0x8E, 0x6F, 0x9E, 0x0F, 0x5B, 0x4B, 0xB3, 0xA2, 0x14, + 0x2B, 0x5E, 0x14, 0x8B, 0xE8, 0x68, 0x62, 0x94, 0xE4, 0xB0, 0xC1, 0xBB, 0x71, 0xE6, 0x2A, 0xB0, 0xAA, 0x3C, 0x78, 0x62, + 0x2A, 0x89, 0x48, 0x21, 0xE1, 0x35, 0xAC, 0xCF, 0x30, 0x38, 0x64, 0x03, 0x62, 0x30, 0xD8, 0xF6, 0x77, 0x8E, 0xCB, 0x56, + 0xC9, 0xB0, 0x69, 0x40, 0x59, 0xF7, 0xF5, 0xF2, 0xE7, 0x32, 0x85, 0x93, 0xB2, 0x8D, 0x6B, 0x91, 0x75, 0xB3, 0x9D, 0xA2, + 0xF3, 0x79, 0x65, 0x02, 0xEA, 0x54, 0xDD, 0xEA, 0x91, 0x6C, 0x78, 0x1B, 0x43, 0x9E, 0x43, 0xFF, 0x5A, 0x3B, 0xED, 0xD7, + 0x00, 0x55, 0x16, 0xEB, 0x56, 0xA4, 0xE9, 0x6B, 0xF3, 0xB2, 0x51, 0xDC, 0xB9, 0xB9, 0xA1, 0x89, 0x28, 0xF6, 0x8C, 0xAC, + 0x92, 0xD1, 0x87, 0x97, 0x7E, 0xEE, 0xBF, 0x99, 0xCF, 0x7E, 0xE8, 0xD7, 0xC6, 0x85, 0x43, 0xF3, 0x6B, 0x45, 0x6C, 0x9D, + 0x42, 0xDE, 0x54, 0x9E, 0xC6, 0x37, 0x97, 0xC7, 0x83, 0x33, 0x24, 0x0D, 0x75, 0xD4, 0x4A, 0x57, 0x41, 0xAA, 0xC5, 0xCE, + 0x3E, 0x70, 0xB5, 0x13, 0x38, 0x1C, 0x2F, 0x8A, 0x85, 0x7F, 0x68, 0x88, 0xCF, 0xB9, 0xF6, 0x7C, 0xDE, 0xBD, 0x58, 0xA9, + 0xE8, 0x53, 0xFE, 0xF8, 0x0C, 0x7D, 0x46, 0xBB, 0x41, 0x88, 0xC4, 0x4F, 0x62, 0x34, 0xD5, 0x5C, 0xB0, 0x1E, 0xE9, 0xFD, + 0x8D, 0x5E, 0x41, 0xEE, 0xC0, 0xBA, 0x27, 0xD1, 0x3B, 0x7F, 0xBF, 0xC6, 0xCF, 0x53, 0x7C, 0x4C, 0x06, 0xF5, 0xDF, 0x71, + 0x3E, 0xC2, 0x2E, 0x74, 0x76, 0xE4, 0xB7, 0x62, 0xAD, 0xF8, 0x8E, 0x6A, 0xA0, 0xD8, 0x0E, 0x42, 0x00, 0x2C, 0x28, 0xB6, + 0x05, 0xC1, 0x7C, 0x0D, 0x40, 0x14, 0x13, 0x93, 0x80, 0xFF, 0xA4, 0x15, 0x6F, 0xAA, 0xDF, 0x53, 0xFF, 0xBA, 0xDD, 0xB1, + 0xC4, 0xCA, 0xE8, 0x23, 0x59, 0x81, 0xA0, 0xF3, 0x89, 0xC3, 0x93, 0xE4, 0x84, 0x56, 0x35, 0xB7, 0x95, 0xDD, 0xC4, 0x07, + 0xD5, 0x4C, 0x76, 0x07, 0xED, 0xEC, 0x5F, 0xE6, 0xFB, 0xC4, 0xF0, 0x9D, 0x68, 0x62, 0x96, 0xC3, 0x57, 0x64, 0xE0, 0x41, + 0x0A, 0xC1, 0x08, 0x5E, 0xEA, 0xA6, 0x40, 0x8D, 0xB2, 0xA6, 0x4F, 0xD3, 0x8B, 0xB4, 0xDA, 0xF2, 0x83, 0x29, 0x0D, 0x45, + 0x9E, 0xCA, 0x49, 0x9D, 0x3B, 0x67, 0x46, 0xC3, 0x56, 0xA6, 0x17, 0x54, 0x26, 0x28, 0x53, 0x52, 0x18, 0xA3, 0x82, 0x0C, + 0xAF, 0xAF, 0xA0, 0x95, 0x36, 0xA8, 0x24, 0x17, 0xF0, 0x10, 0x33, 0xF2, 0x1C, 0x1D, 0x74, 0x63, 0xA5, 0xC0, 0xBC, 0x50, + 0x3E, 0x8C, 0xD1, 0x65, 0x65, 0x84, 0x2B, 0x93, 0xE0, 0x08, 0xBF, 0x8D, 0xF8, 0x60, 0x84, 0x8E, 0x7F, 0xE4, 0x9C, 0xAE, + 0x46, 0x87, 0xB2, 0xF7, 0x9C, 0xE8, 0xF3, 0x26, 0x45, 0x88, 0xCD, 0x7F, 0x5C, 0xDB, 0xD4, 0x65, 0xA3, 0x54, 0x93, 0xEC, + 0x88, 0x76, 0x2A, 0xDB, 0xE1, 0x6F, 0x39, 0xC3, 0x59, 0x10, 0x6A, 0x6D, 0xAF, 0x23, 0xE6, 0x09, 0x98, 0xDC, 0x0C, 0x2F, + 0xBB, 0x6F, 0xD2, 0x06, 0x6D, 0x93, 0x86, 0xC8, 0x0F, 0x87, 0xBA, 0x2D, 0x13, 0xC3, 0x7B, 0x4B, 0x06, 0x62, 0x42, 0x81, + 0x7D, 0x00, 0x6F, 0x71, 0xBE, 0x13, 0xBA, 0xA5, 0x3B, 0x51, 0xFB, 0x98, 0xCB, 0x45, 0x4B, 0x9C, 0xB8, 0xFC, 0xEF, 0x5F, + 0xCB, 0x41, 0xCB, 0x5E, 0x12, 0xE9, 0x75, 0x09, 0xA5, 0x47, 0x7F, 0xB8, 0x5F, 0xCF, 0x5A, 0xB5, 0x4F, 0x35, 0x07, 0xC2, + 0xE8, 0xD8, 0x4A, 0xE3, 0xE3, 0x20, 0xBE, 0x80, 0x24, 0x7D, 0x4D, 0x61, 0xF5, 0x3A, 0xA2, 0x96, 0xB5, 0x1A, 0x45, 0x49, + 0xAD, 0x26, 0xF6, 0xB7, 0x08, 0xF8, 0x24, 0x70, 0x44, 0xDE, 0xFB, 0xD7, 0x38, 0x19, 0x65, 0x3D, 0x1F, 0xD1, 0x61, 0x58, + 0x1D, 0x51, 0x0A, 0x97, 0xCE, 0xE7, 0xDA, 0x92, 0xAB, 0x1E, 0x82, 0xA0, 0x13, 0x0E, 0xFF, 0xC4, 0x81, 0x72, 0x44, 0xB1, + 0x16, 0x3F, 0x4C, 0xCA, 0xB4, 0x00, 0x4C, 0xA0, 0xC5, 0xD8, 0x33, 0x15, 0x48, 0xEF, 0x5E, 0xA1, 0x41, 0x9E, 0x94, 0x2B, + 0x37, 0xF7, 0x14, 0x03, 0xE4, 0xC5, 0xBD, 0x90, 0x9C, 0xA6, 0x1D, 0xCB, 0x46, 0x39, 0xAD, 0xA5, 0xF5, 0x45, 0xD1, 0xA1, + 0x62, 0xDA, 0x88, 0x81, 0x1D, 0xC5, 0x2F, 0xA0, 0x99, 0x96, 0xEE, 0x39, 0x94, 0x37, 0x1D, 0xB3, 0x18, 0xDA, 0xA4, 0x01, + 0x52, 0x58, 0xA4, 0x4C, 0xBE, 0x9B, 0xF4, 0x2E, 0x9D, 0x78, 0x10, 0x11, 0x95, 0x7C, 0xFE, 0x51, 0x9D, 0x7B, 0xD1, 0x89, + 0xDB, 0x46, 0x8E, 0x8E, 0x4A, 0x9D, 0x7F, 0x36, 0x69, 0x59, 0xE0, 0xF3, 0x75, 0x56, 0xC4, 0x70, 0x64, 0x6D, 0x7C, 0x89, + 0xC3, 0xB3, 0x44, 0xD1, 0x87, 0xA5, 0x90, 0xE4, 0x01, 0xC6, 0x09, 0x20, 0x56, 0x3F, 0x70, 0xFD, 0x69, 0xF3, 0x1A, 0x32, + 0xE9, 0x5B, 0xB4, 0xB4, 0xA4, 0xFF, 0x5E, 0xD7, 0xAB, 0x8A, 0x98, 0xF6, 0xBE, 0xAF, 0x66, 0x88, 0x62, 0x9C, 0x20, 0xE6, + 0xDB, 0x53, 0xFF, 0xC1, 0x44, 0xE9, 0x17, 0x3E, 0x15, 0x16, 0xC6, 0x6A, 0x4C, 0xBD, 0xC0, 0x4F, 0x5D, 0xF0, 0x39, 0xD1, + 0xAE, 0x3A, 0x38, 0xCE, 0xB8, 0x2E, 0x76, 0xCE, 0xDD, 0x51, 0xA6, 0x4F, 0xEE, 0xAC, 0xED, 0x1D, 0x3D, 0x9B, 0xFC, 0xDE, + 0x3F, 0x2E, 0xFF, 0xEE, 0x6F, 0x5E, 0xFE, 0xEC, 0xD1, 0xDC, 0x50, 0x18, 0x10, 0x04, 0x85, 0x31, 0x00, 0x3E, 0xE8, 0x42, + 0xE7, 0x15, 0x50, 0x24, 0x14, 0xDD, 0x58, 0x08, 0x49, 0xA5, 0x0E, 0x72, 0x5D, 0xF5, 0xE0, 0xA0, 0xEA, 0xEC, 0x4C, 0xCA, + 0xAC, 0xC0, 0x41, 0x12, 0xA6, 0x21, 0x80, 0x12, 0x80, 0x81, 0xE9, 0xD5, 0x67, 0xCA, 0x83, 0x24, 0x2F, 0xEF, 0x9E, 0x28, + 0x01, 0x13, 0x0F, 0xBC, 0xD5, 0x4E, 0x65, 0x9A, 0x6A, 0xB7, 0xA1, 0xCA, 0x24, 0x00, 0xF7, 0x64, 0xBC, 0x24, 0xBA, 0x90, + 0x92, 0x04, 0xC0, 0xA0, 0x5A, 0x79, 0x5A, 0x55, 0xF3, 0x9B, 0xEC, 0x32, 0x27, 0x0F, 0xE8, 0x59, 0x1B, 0x65, 0x20, 0x78, + 0xA6, 0x04, 0x67, 0x45, 0x12, 0xCA, 0xC3, 0x4A, 0x06, 0x52, 0x4B, 0xB3, 0x4D, 0xAB, 0x47, 0x67, 0x71, 0x82, 0xEF, 0x34, + 0xFC, 0xB9, 0xC9, 0x26, 0xA7, 0x70, 0xCB, 0x5D, 0x91, 0x26, 0xAC, 0x8F, 0xD7, 0x7A, 0xD3, 0x0B, 0xB9, 0x0F, 0x22, 0x0D, + 0xC0, 0x4B, 0x00, 0x03, 0x5C, 0x4B, 0x6E, 0x5C, 0xE3, 0x40, 0x69, 0x5F, 0x4B, 0x99, 0xE2, 0x18, 0x8B, 0x01, 0x8C, 0x28, + 0x59, 0x55, 0x62, 0xF6, 0xEA, 0xDE, 0x49, 0xCF, 0xD5, 0xE4, 0x57, 0x1A, 0xFC, 0xBB, 0x85, 0xC3, 0xD0, 0x2E, 0x6F, 0xB1, + 0x6B, 0x15, 0xED, 0x2B, 0x31, 0x80, 0xB2, 0xE9, 0x81, 0x04, 0x89, 0x60, 0xD9, 0x69, 0x63, 0x1B, 0x6A, 0xAF, 0x7F, 0xCE, + 0x1F, 0xE0, 0xB9, 0x4C, 0xA7, 0x4D, 0xCA, 0x4E, 0x98, 0x9C, 0x44, 0x6E, 0xF9, 0x01, 0xAC, 0x29, 0x7E, 0x73, 0x70, 0xDF, + 0x2F, 0xF0, 0x2E, 0x3C, 0xE9, 0x48, 0xCA, 0x0B, 0xC7, 0x1C, 0xA5, 0x0F, 0x12, 0xEC, 0x66, 0x4F, 0x1E, 0x6A, 0xCA, 0x3F, + 0xED, 0x0E, 0x2D, 0x8B, 0xDA, 0x03, 0x69, 0x97, 0xCA, 0xA3, 0x6C, 0xBB, 0x6B, 0x1A, 0x34, 0x8D, 0xE5, 0x2C, 0x25, 0x7E, + 0x72, 0x29, 0x58, 0x8E, 0x5F, 0xE2, 0x7F, 0xB6, 0xD3, 0x08, 0xDA, 0x66, 0x34, 0x8D, 0x93, 0x93, 0x3C, 0x56, 0xA6, 0xB4, + 0xF5, 0x66, 0xF1, 0x34, 0x96, 0xFF, 0x68, 0x6A, 0x52, 0x11, 0x9B, 0xF5, 0x3D, 0xF0, 0x98, 0x45, 0xED, 0x91, 0xF8, 0xEE, + 0x1F, 0xC6, 0x45, 0x89, 0x5E, 0xBF, 0x92, 0x49, 0xBC, 0xA8, 0xEB, 0xBF, 0x9B, 0xC6, 0xF4, 0x69, 0x16, 0x72, 0x69, 0x6A, + 0xB5, 0x03, 0x9A, 0xA0, 0xB5, 0x3E, 0x75, 0x3F, 0xD3, 0xA5, 0x15, 0x22, 0x06, 0x63, 0xEA, 0xC2, 0xA3, 0x68, 0x2A, 0xE7, + 0x46, 0x18, 0x44, 0x15, 0xD1, 0x34, 0xED, 0xD7, 0x82, 0xBA, 0x78, 0x9E, 0xFA, 0x71, 0xA6, 0x3A, 0x98, 0xFE, 0xCA, 0xB8, + 0x98, 0x2D, 0x41, 0xCD, 0x3A, 0x52, 0xEB, 0xC2, 0x27, 0x39, 0xE2, 0x09, 0x1D, 0xDB, 0xE7, 0xDB, 0x51, 0x37, 0x35, 0xF6, + 0x02, 0x56, 0xE4, 0x9B, 0x7A, 0x53, 0x6D, 0xAE, 0x88, 0x63, 0x66, 0x44, 0xEA, 0xD8, 0x7B, 0xC6, 0x93, 0x33, 0xF9, 0x9F, + 0x2B, 0x7C, 0x95, 0x17, 0x3C, 0x4E, 0xE9, 0x5D, 0xB2, 0x60, 0x77, 0xE5, 0x9A, 0x6B, 0xF6, 0x98, 0xC0, 0x7B, 0x9D, 0x31, + 0x31, 0x24, 0x2C, 0xE3, 0x12, 0x9C, 0x7A, 0x05, 0x1B, 0x96, 0xA1, 0x58, 0x34, 0x91, 0x94, 0x49, 0xBC, 0xF2, 0xC9, 0x36, + 0xE8, 0xD1, 0xF1, 0xD3, 0x46, 0xD0, 0x0E, 0x2A, 0x58, 0x5D, 0x18, 0x17, 0xB1, 0x4F, 0xA7, 0x4C, 0x11, 0x7F, 0x0E, 0xDC, + 0xE6, 0x13, 0x6F, 0x13, 0x83, 0xE2, 0x56, 0x19, 0xE2, 0xA3, 0xDB, 0xC8, 0xC6, 0xB4, 0xBB, 0x26, 0x67, 0x70, 0x84, 0xF7, + 0x7C, 0x7F, 0x5D, 0x04, 0x8A, 0x3B, 0x5E, 0xF0, 0x76, 0x62, 0x42, 0xBE, 0xB0, 0x5F, 0x79, 0xCF, 0x4C, 0x4B, 0xD7, 0xE4, + 0xEC, 0x1E, 0x66, 0xB8, 0x42, 0x66, 0x31, 0x3B, 0xB3, 0x72, 0x4E, 0xD9, 0x44, 0x5C, 0xEB, 0x13, 0x0A, 0x39, 0x65, 0x07, + 0xEB, 0xB2, 0x70, 0xFD, 0xFF, 0x8E, 0x24, 0xB5, 0x18, 0x4A, 0x48, 0x5F, 0xE7, 0x9A, 0xB4, 0xA1, 0xBF, 0x06, 0x8C, 0xD0, + 0xA6, 0x8F, 0x28, 0xBB, 0x1D, 0x3F, 0x40, 0x1A, 0xE6, 0x53, 0xC6, 0xA4, 0x88, 0x9C, 0x49, 0xC1, 0x00, 0x8C, 0x21, 0xEC, + 0x90, 0xF4, 0x49, 0x76, 0x67, 0x21, 0xEF, 0xB4, 0xC4, 0x6F, 0x11, 0xB7, 0x85, 0x83, 0xAD, 0xEF, 0x1A, 0xA1, 0x41, 0xB7, + 0xC7, 0xC3, 0x16, 0xC4, 0x03, 0x17, 0x18, 0x1D, 0xD6, 0x8B, 0xDE, 0x4F, 0x55, 0x56, 0x0E, 0x80, 0xEA, 0xF9, 0xA6, 0x36, + 0xBD, 0x80, 0x10, 0x60, 0x73, 0x5A, 0xF0, 0x57, 0x43, 0x59, 0x06, 0x90, 0xF2, 0x13, 0x07, 0x72, 0x4B, 0xAA, 0x53, 0x6B, + 0x53, 0x32, 0x1A, 0x35, 0x18, 0xC3, 0x95, 0x47, 0x7B, 0x30, 0xC9, 0x99, 0x7A, 0xEB, 0xF9, 0x00, 0x24, 0x98, 0xA3, 0x15, + 0xFF, 0xAA, 0xF1, 0x91, 0x7E, 0x71, 0xDA, 0x27, 0x0F, 0x4F, 0xDD, 0x28, 0xF3, 0x80, 0x15, 0x0F, 0x91, 0xA4, 0xB5, 0xD5, + 0x10, 0xB7, 0x55, 0xDF, 0x86, 0xF8, 0xD1, 0x3B, 0xF6, 0xA5, 0xE3, 0x71, 0x3E, 0x0B, 0xBD, 0x48, 0x11, 0x27, 0x15, 0xCF, + 0xB1, 0xE4, 0xD8, 0x69, 0x7B, 0x8E, 0xCB, 0x11, 0xD3, 0x5E, 0xB4, 0xDD, 0x90, 0x17, 0xCD, 0xB5, 0xB7, 0x2F, 0x54, 0x7F, + 0x76, 0x0B, 0x0C, 0x19, 0x49, 0xCF, 0xBC, 0x70, 0x91, 0xDC, 0xE5, 0x0C, 0x5D, 0x40, 0xD6, 0x28, 0x3E, 0x83, 0xFA, 0x64, + 0x1F, 0xBB, 0xFA, 0x88, 0xFF, 0x5A, 0xCC, 0xDE, 0x61, 0xCC, 0xCA, 0xCB, 0x8B, 0x86, 0xD0, 0xD9, 0xB3, 0xB2, 0x6C, 0x7C, + 0xA4, 0x89, 0x72, 0x8D, 0x5A, 0x30, 0x4D, 0xA9, 0x3D, 0x23, 0xD9, 0xC8, 0x32, 0xF1, 0x7D, 0x89, 0xEA, 0x4B, 0x2A, 0x69, + 0xFA, 0x4F, 0xEB, 0xCA, 0x03, 0x82, 0xD1, 0xD8, 0x33, 0xB3, 0x45, 0x99, 0xA5, 0xAB, 0xAD, 0x3E, 0x34, 0xC7, 0xDA, 0xB3, + 0xC3, 0x5E, 0xDA, 0x10, 0x57, 0x90, 0x33, 0x72, 0x3C, 0x02, 0xEA, 0x94, 0x34, 0xBC, 0x52, 0x70, 0xCE, 0x54, 0xCA, 0x9E, + 0xD4, 0x1E, 0x3F, 0x52, 0x35, 0xB2, 0xE2, 0xAD, 0x7D, 0x5A, 0xDF, 0x89, 0x43, 0xE1, 0x41, 0x74, 0x7A, 0x19, 0x36, 0xD5, + 0xB4, 0x47, 0xD4, 0x56, 0x24, 0xF2, 0x53, 0x4A, 0x4E, 0x51, 0xCF, 0xF8, 0x4A, 0xDF, 0xB8, 0x41, 0xF9, 0xB4, 0x18, 0x2F, + 0x72, 0xE5, 0x21, 0xE6, 0xBE, 0xD0, 0x82, 0xA4, 0xC1, 0x49, 0xC0, 0xA2, 0x6A, 0x1B, 0x8B, 0xC9, 0x33, 0xA1, 0x12, 0x30, + 0x44, 0xB5, 0x38, 0x28, 0xCA, 0x14, 0x93, 0x00, 0xE7, 0xE4, 0xFC, 0xEA, 0x71, 0xA5, 0xC4, 0xC4, 0x47, 0xF0, 0xF3, 0xA5, + 0x49, 0x6B, 0x55, 0xE2, 0x41, 0xC6, 0x7B, 0xCC, 0xE7, 0xF0, 0x89, 0xF7, 0x19, 0xB7, 0xE3, 0x24, 0xFE, 0x6A, 0x47, 0x74, + 0x4B, 0xC8, 0x66, 0x08, 0x03, 0xF8, 0x5C, 0x49, 0xCF, 0x2C, 0xFC, 0x0E, 0xE2, 0x17, 0xB3, 0x4B, 0x70, 0x69, 0xE6, 0x30, + 0x87, 0xFE, 0xD2, 0xD5, 0x82, 0x4D, 0xD0, 0x00, 0x56, 0x0F, 0xBF, 0x72, 0x79, 0x09, 0x86, 0x40, 0xD1, 0xF4, 0x5D, 0xC7, + 0x4F, 0xCA, 0x40, 0xFD, 0x7E, 0xBA, 0xB6, 0xDC, 0xF8, 0xDF, 0x18, 0xCD, 0x50, 0x9F, 0xD3, 0x5F, 0x02, 0x89, 0xAE, 0xED, + 0x56, 0x2D, 0x3A, 0xFD, 0xF5, 0x70, 0x40, 0x7D, 0x7E, 0xBD, 0x26, 0xB9, 0xAA, 0xAD, 0xB0, 0x9E, 0xD5, 0x34, 0x3C, 0xFF, + 0x0E, 0x4C, 0x2B, 0xF6, 0xF1, 0xFE, 0xBF, 0x29, 0xA3, 0x90, 0xE7, 0xA0, 0x55, 0x55, 0x34, 0xE7, 0x2E, 0xDC, 0x96, 0xE0, + 0xB9, 0x09, 0x19, 0xCD, 0x47, 0xFA, 0x58, 0xFE, 0xAF, 0x11, 0x5E, 0xAC, 0xC0, 0x52, 0x40, 0xEE, 0x73, 0xF2, 0x11, 0x39, + 0x03, 0x92, 0x91, 0x8A, 0x9B, 0x12, 0x56, 0xFC, 0xEE, 0x5F, 0x19, 0x0E, 0x35, 0xEF, 0x3A, 0xF3, 0xC2, 0x94, 0xE0, 0x40, + 0x30, 0x2D, 0x4E, 0x8A, 0x48, 0x46, 0x6F, 0xDB, 0xAF, 0x9F, 0x6F, 0x18, 0xEA, 0x97, 0x3C, 0x76, 0xA6, 0x44, 0x60, 0xF6, + 0xF1, 0x0F, 0x67, 0xCB, 0xAE, 0x9E, 0xE2, 0x1A, 0x5E, 0xA9, 0xF8, 0x22, 0x31, 0x1D, 0x19, 0xC6, 0xA3, 0x62, 0x6E, 0xDA, + 0x2F, 0x9D, 0xC9, 0x11, 0xC5, 0x7E, 0xB1, 0xFA, 0x1C, 0x63, 0xAE, 0xB3, 0xC4, 0x23, 0x66, 0xCA, 0x2E, 0x9C, 0xBF, 0xBF, + 0xFD, 0xFB, 0x3F, 0xBB, 0xED, 0xDB, 0xAF, 0x9F, 0xBD, 0xBB, 0x2F, 0x9B, 0xAD, 0x9B, 0xB7, 0xAF, 0xFC, 0xFA, 0x37, 0xAB, + 0xEC, 0xDA, 0xA7, 0x8F, 0xBC, 0xBA, 0x27, 0x8B, 0xAC, 0x9A, 0xBE, 0xBE, 0x7D, 0xF9, 0x3E, 0xBA, 0x6D, 0xD9, 0xAE, 0x9E, + 0x3D, 0xB9, 0x2E, 0x9A, 0x2D, 0x99, 0xB6, 0xAE, 0x7C, 0xF8, 0x36, 0xAA, 0x6C, 0xD8, 0xA6, 0x8E, 0x3C, 0xB8, 0x26, 0x8A, + 0x2C, 0x98, 0x1A, 0x3C, 0xC9, 0x82, 0x03, 0x3A, 0x97, 0x2A, 0x48, 0x35, 0xEB, 0x4E, 0x6D, 0xD3, 0xA7, 0x97, 0x6C, 0xE9, + 0xD3, 0x19, 0xE2, 0x6F, 0x39, 0x22, 0x9A, 0xDA, 0xE8, 0xC3, 0x65, 0xC3, 0xA6, 0x96, 0x7B, 0x59, 0x98, 0xA5, 0x34, 0x0C, + 0x15, 0x26, 0x9B, 0x2D, 0x69, 0xC2, 0x6C, 0xD2, 0x27, 0x95, 0x55, 0x2F, 0x54, 0xA0, 0x8D, 0x1D, 0xF2, 0xCF, 0xE0, 0xDB, + 0x4B, 0x03, 0x64, 0xC2, 0x26, 0x94, 0xBD, 0xB7, 0xF5, 0xF3, 0x3D, 0xB3, 0xE5, 0xD3, 0xAD, 0x97, 0xB5, 0xB3, 0x2D, 0x93, + 0xA5, 0x93, 0xB5, 0xA7, 0xF4, 0xF2, 0x35, 0xA3, 0xE4, 0xD2, 0xA5, 0x87, 0xB4, 0xB2, 0x25, 0x83, 0xA4, 0x92, 0xBC, 0xB6, + 0x75, 0xF1, 0x3C, 0xB2, 0x65, 0xD1, 0xAC, 0x96, 0x35, 0xB1, 0x2C, 0x92, 0x25, 0x91, 0xB4, 0xA6, 0x74, 0xF0, 0x34, 0xA2, + 0x64, 0xD0, 0xA4, 0x86, 0x34, 0xB0, 0x24, 0x82, 0x24, 0x90, 0x3C, 0x7F, 0xA3, 0x1E, 0x04, 0x86, 0x83, 0x72, 0xC6, 0x40, + 0x3C, 0xFD, 0x6B, 0x5B, 0x8F, 0x8F, 0x4C, 0xAF, 0x29, 0x7D, 0x88, 0xB4, 0x31, 0x31, 0x14, 0xB8, 0x67, 0x31, 0x63, 0x4B, + 0x8E, 0x8E, 0xE5, 0xBE, 0x84, 0x7C, 0x86, 0x22, 0x30, 0x5D, 0xC0, 0xE6, 0x22, 0x12, 0x6A, 0x5A, 0x0F, 0x8D, 0x25, 0x53, + 0xA7, 0xA3, 0x5D, 0x6A, 0x4E, 0xCC, 0x9D, 0xB3, 0xED, 0x11, 0x62, 0x4A, 0x0E, 0x8C, 0xBB, 0x3F, 0xDD, 0xEB, 0x3B, 0x3B, + 0xCD, 0xCB, 0xAB, 0x1F, 0x9D, 0xAB, 0x2B, 0x1B, 0x8D, 0x8B, 0xB3, 0x2F, 0xDC, 0xEA, 0x33, 0x2B, 0xCC, 0xCA, 0xA3, 0x0F, + 0x9C, 0xAA, 0x23, 0x0B, 0x8C, 0x8A, 0xBA, 0x3E, 0x5D, 0xE9, 0x3A, 0x3A, 0x4D, 0xC9, 0xAA, 0x1E, 0x1D, 0xA9, 0x2A, 0x1A, + 0x0D, 0x89, 0xB2, 0x2E, 0x5C, 0xE8, 0x32, 0x2A, 0x4C, 0xC8, 0xA2, 0x0E, 0x1C, 0xA8, 0x22, 0x0A, 0x0C, 0x88, 0x90, 0x79, + 0x97, 0x88, 0x79, 0x73, 0xC7, 0xC7, 0x16, 0x9C, 0x5B, 0x57, 0x69, 0x53, 0x87, 0x87, 0xF3, 0x14, 0xF4, 0xA4, 0x71, 0x63, + 0xC6, 0xC6, 0xF2, 0x38, 0x95, 0x79, 0x61, 0x43, 0x86, 0x86, 0x57, 0x63, 0x53, 0xB1, 0x78, 0x72, 0x47, 0xC5, 0x4D, 0xAC, + 0x4F, 0x1B, 0x68, 0x52, 0x07, 0x85, 0xA0, 0xC7, 0x58, 0xC7, 0x70, 0x62, 0x46, 0xC4, 0xB3, 0xFB, 0x6A, 0xAF, 0x60, 0x42, + 0x06, 0x84, 0xB9, 0x37, 0xD5, 0xE3, 0x39, 0x33, 0xC5, 0xC3, 0xA9, 0x17, 0x95, 0xA3, 0x29, 0x13, 0x85, 0x83, 0xB1, 0x27, + 0xD4, 0xE2, 0x31, 0x23, 0xC4, 0xC2, 0xA1, 0x07, 0x94, 0xA2, 0x21, 0x03, 0x84, 0x82, 0xB8, 0x36, 0x55, 0xE1, 0x38, 0x32, + 0x45, 0xC1, 0xA8, 0x16, 0x15, 0xA1, 0x28, 0x12, 0x05, 0x81, 0xB0, 0x26, 0x54, 0xE0, 0x30, 0x22, 0x44, 0xC0, 0xA0, 0x06, + 0x14, 0xA0, 0x20, 0x02, 0x04, 0x80, 0x96, 0x60, 0x6F, 0x25, 0xA4, 0x06, 0x97, 0xAE, 0xB6, 0xD2, 0x18, 0xCF, 0x4F, 0xD9, + 0xAB, 0x1F, 0x80, 0x98, 0x6E, 0x15, 0x53, 0x09, 0xEA, 0x0A, 0x32, 0x36, 0xE6, 0xCC, 0x47, 0xC9, 0xAA, 0x1E, 0x01, 0xF2, + 0x64, 0x02, 0x41, 0x38, 0xB0, 0x76, 0x51, 0x67, 0x80, 0xCF, 0x4E, 0xD8, 0x2B, 0x1D, 0x29, 0xE2, 0x5D, 0xA3, 0x54, 0xBE, + 0xB7, 0x7C, 0x73, 0xCD, 0x66, 0x81, 0x46, 0xC8, 0x2A, 0x1C, 0x9F, 0xBD, 0xF9, 0x7B, 0x1F, 0xB9, 0xE9, 0x5B, 0x8F, 0x9D, + 0xB9, 0x3B, 0x0F, 0x99, 0xA9, 0x1B, 0x97, 0xAD, 0xF8, 0x7A, 0x17, 0xA9, 0xE8, 0x5A, 0x87, 0x8D, 0xB8, 0x3A, 0x07, 0x89, + 0xA8, 0x1A, 0x9E, 0xBC, 0x79, 0x79, 0x1E, 0xB8, 0x69, 0x59, 0x8E, 0x9C, 0x39, 0x39, 0x0E, 0x98, 0x29, 0x19, 0x96, 0xAC, + 0x78, 0x78, 0x16, 0xA8, 0x68, 0x58, 0x86, 0x8C, 0x38, 0x38, 0x06, 0x88, 0x28, 0x18, 0x7C, 0x05, 0x5E, 0xC6, 0x26, 0xFF, + 0xA3, 0x28, 0x35, 0x87, 0x68, 0xCB, 0x4D, 0xD1, 0xA3, 0x17, 0x4A, 0x45, 0xAC, 0xEC, 0x57, 0x8F, 0x39, 0xEB, 0xF8, 0xBE, + 0x05, 0x4B, 0x45, 0xC1, 0xA2, 0x16, 0x42, 0xAB, 0x5A, 0x35, 0xFD, 0xE0, 0x9A, 0x01, 0x36, 0xB3, 0xEE, 0x1A, 0x4C, 0xD0, + 0x23, 0x15, 0x9F, 0x79, 0x7A, 0xEE, 0xAC, 0x9B, 0x9F, 0xAB, 0x05, 0x16, 0x8F, 0x62, 0x44, 0xC0, 0x22, 0x14, 0x9D, 0xB5, + 0xF1, 0x73, 0x1D, 0xB1, 0xE1, 0x53, 0x8D, 0x95, 0xB1, 0x33, 0x0D, 0x91, 0xA1, 0x13, 0x95, 0xA5, 0xF0, 0x72, 0x15, 0xA1, + 0xE0, 0x52, 0x85, 0x85, 0xB0, 0x32, 0x05, 0x81, 0xA0, 0x12, 0x9C, 0xB4, 0x71, 0x71, 0x1C, 0xB0, 0x61, 0x51, 0x8C, 0x94, + 0x31, 0x31, 0x0C, 0x90, 0x21, 0x11, 0x94, 0xA4, 0x70, 0x70, 0x14, 0xA0, 0x60, 0x50, 0x84, 0x84, 0x30, 0x30, 0x04, 0x80, + 0x20, 0x10, 0xE4, 0x9B, 0x48, 0x3B, 0x5B, 0x79, 0xCB, 0x4F, 0x94, 0xBC, 0xE8, 0x7D, 0x4B, 0x59, 0x8B, 0x0F, 0x53, 0x63, + 0x9A, 0x03, 0x53, 0x69, 0xCA, 0x4E, 0x1A, 0xCD, 0xC6, 0x93, 0x43, 0x49, 0x8A, 0x0E, 0xD8, 0x9F, 0x86, 0x8D, 0x5A, 0x78, + 0x4B, 0x4D, 0x8E, 0x03, 0xBC, 0xC2, 0x4A, 0x58, 0x0B, 0x0D, 0x73, 0x7C, 0xA9, 0x38, 0x52, 0x68, 0x4A, 0x4C, 0xBC, 0x8A, + 0x65, 0x73, 0x42, 0x48, 0x0A, 0x0C, 0x9B, 0x3D, 0xD9, 0x6B, 0x1B, 0x39, 0xC9, 0x4B, 0x8B, 0x1D, 0x99, 0x2B, 0x0B, 0x19, + 0x89, 0x0B, 0x93, 0x2D, 0xD8, 0x6A, 0x13, 0x29, 0xC8, 0x4A, 0x83, 0x0D, 0x98, 0x2A, 0x03, 0x09, 0x88, 0x0A, 0x9A, 0x3C, + 0x59, 0x69, 0x1A, 0x38, 0x49, 0x49, 0x8A, 0x1C, 0x19, 0x29, 0x0A, 0x18, 0x09, 0x09, 0x92, 0x2C, 0x58, 0x68, 0x12, 0x28, + 0x48, 0x48, 0x82, 0x0C, 0x18, 0x28, 0x02, 0x08, 0x08, 0x08, 0xDB, 0x2A, 0x0E, 0x87, 0x59, 0x71, 0xC3, 0x47, 0x4E, 0x8D, + 0x85, 0x25, 0x49, 0x51, 0x83, 0x07, 0xD1, 0x58, 0xAE, 0xDF, 0x51, 0x61, 0xC2, 0x46, 0x89, 0x9E, 0x1A, 0x19, 0x41, 0x41, + 0x82, 0x06, 0x58, 0xB5, 0x5B, 0x6F, 0x58, 0x70, 0x43, 0x45, 0x4F, 0x69, 0x6F, 0x9C, 0x48, 0x50, 0x03, 0x05, 0x98, 0xBF, + 0x28, 0x6E, 0x50, 0x60, 0x42, 0x44, 0x60, 0x39, 0x9E, 0xDB, 0x40, 0x40, 0x02, 0x04, 0x99, 0x35, 0xD1, 0x63, 0x19, 0x31, + 0xC1, 0x43, 0x89, 0x15, 0x91, 0x23, 0x09, 0x11, 0x81, 0x03, 0x91, 0x25, 0xD0, 0x62, 0x11, 0x21, 0xC0, 0x42, 0x81, 0x05, + 0x90, 0x22, 0x01, 0x01, 0x80, 0x02, 0x98, 0x34, 0x51, 0x61, 0x18, 0x30, 0x41, 0x41, 0x88, 0x14, 0x11, 0x21, 0x08, 0x10, + 0x01, 0x01, 0x90, 0x24, 0x50, 0x60, 0x10, 0x20, 0x40, 0x40, 0x80, 0x04, 0x10, 0x20, 0x00, 0x00, 0xF3, 0x6E, 0x80, 0x00, + 0x0C, 0x4C, 0x40, 0x05, 0x97, 0x9B, 0x10, 0x20, 0x40, 0x40, 0xF0, 0x65, 0x9C, 0xEB, 0x51, 0xEF, 0xE0, 0xCE, 0x88, 0xE8, + 0x90, 0x63, 0x9F, 0xD2, 0xC3, 0x69, 0x7E, 0xC4, 0x41, 0x6E, 0xB6, 0x85, 0x8C, 0xCC, 0xA1, 0xFD, 0x90, 0xD9, 0x11, 0x21, + 0x6C, 0xC9, 0x95, 0xC7, 0x52, 0x68, 0x60, 0xEA, 0xEA, 0x06, 0x09, 0x35, 0xA2, 0x01, 0xA0, 0x53, 0x80, 0x03, 0xF9, 0x74, + 0x5D, 0x6E, 0xE0, 0x53, 0x16, 0x60, 0xDB, 0x36, 0xB1, 0x22, 0xE7, 0x68, 0x44, 0x44, 0x29, 0xA2, 0xF0, 0x21, 0xA0, 0xF2, + 0xA7, 0x82, 0xB0, 0xD6, 0x16, 0x4F, 0x58, 0x48, 0x8B, 0x35, 0xA8, 0x54, 0x53, 0xA8, 0x9A, 0x43, 0xFD, 0x86, 0x49, 0x2C, + 0x31, 0x43, 0x42, 0x5E, 0xDA, 0x04, 0xA3, 0xE3, 0xD2, 0x2A, 0x9D, 0x77, 0x6D, 0x64, 0xF1, 0x85, 0x64, 0x28, 0xF9, 0x62, + 0xD7, 0x23, 0x49, 0xB3, 0x39, 0x2B, 0xA9, 0xE0, 0x08, 0xF3, 0x39, 0xFA, 0x08, 0xD5, 0x6A, 0x4A, 0x0B, 0x97, 0xD8, 0xC3, + 0xFB, 0x65, 0xE5, 0xE2, 0x62, 0x99, 0xD0, 0x08, 0xBA, 0x2F, 0x1A, 0x38, 0x49, 0x49, 0xD2, 0xAB, 0x3A, 0x59, 0x03, 0x7B, + 0x2F, 0x1A, 0x79, 0x8F, 0x9B, 0xCC, 0x6B, 0x29, 0xC8, 0x4A, 0x99, 0x25, 0x7B, 0x6C, 0x24, 0xE8, 0xD1, 0x0E, 0x83, 0x50, + 0xFA, 0x0B, 0x1B, 0x39, 0xC9, 0x4B, 0xE3, 0xD5, 0xDB, 0xA0, 0xEA, 0xEA, 0xD5, 0x83, 0xFA, 0x9C, 0xE1, 0x23, 0x8D, 0x6A, + 0x3D, 0x5C, 0x22, 0xE8, 0x56, 0xBB, 0x75, 0x97, 0xB2, 0x41, 0x4E, 0x05, 0x99, 0x25, 0x8E, 0x3E, 0xE9, 0x93, 0x1A, 0x7C, + 0x2B, 0x21, 0x83, 0x49, 0xF0, 0xD0, 0x6C, 0x33, 0x47, 0x6C, 0xBB, 0xCB, 0x6E, 0xC9, 0x7B, 0xCE, 0xA5, 0x67, 0x3B, 0x9F, + 0x21, 0x4E, 0x1F, 0xAD, 0x93, 0x20, 0xA5, 0xFD, 0xCB, 0xFC, 0xAB, 0xBB, 0x71, 0x2D, 0x04, 0x80, 0x78, 0xF8, 0x56, 0x72, + 0x20, 0xFD, 0x2C, 0xF0, 0x20, 0x5F, 0x14, 0x8F, 0x91, 0x8F, 0xDE, 0xB0, 0x26, 0xE9, 0xEC, 0xD5, 0xDC, 0xBA, 0x18, 0x52, + 0xE3, 0x19, 0x5C, 0xB1, 0xA9, 0x33, 0x4F, 0x28, 0x82, 0x11, 0xC4, 0xD1, 0x91, 0x22, 0x75, 0xE5, 0x9C, 0xD9, 0x6E, 0x21, + 0xFC, 0x53, 0x02, 0x1D, 0x23, 0x3B, 0x70, 0x77, 0x31, 0xEC, 0x8E, 0x53, 0x63, 0x59, 0x19, 0x83, 0xF7, 0x73, 0x72, 0xCC, + 0xC9, 0x91, 0xC4, 0xFC, 0xB7, 0x33, 0xAB, 0x64, 0x62, 0xC5, 0x0B, 0xF0, 0x74, 0x74, 0x77, 0x8E, 0x10, 0xD5, 0x14, 0x50, + 0x3F, 0x69, 0x4F, 0xCF, 0x7F, 0x17, 0xA8, 0xD0, 0xF6, 0x52, 0xED, 0x4B, 0x5B, 0xCA, 0x2D, 0x66, 0xB4, 0x56, 0xE2, 0xED, + 0xE4, 0x56, 0xC6, 0xA3, 0x50, 0x38, 0xE1, 0x74, 0x76, 0x74, 0x5D, 0xAA, 0xF0, 0x57, 0x5D, 0xC9, 0x2B, 0x67, 0x02, 0xE5, + 0xF5, 0x77, 0xBB, 0x78, 0x74, 0x17, 0xE6, 0xCD, 0x85, 0xB3, 0xF0, 0x58, 0x20, 0x57, 0xC1, 0x88, 0xAC, 0x68, 0x04, 0x9C, + 0x8A, 0x14, 0x37, 0xFE, 0x78, 0x79, 0x1A, 0x5A, 0xC5, 0xD4, 0xB9, 0xB1, 0xFE, 0xDE, 0x67, 0xC8, 0x1D, 0x17, 0x00, 0x6F, + 0x3A, 0x12, 0x77, 0xE9, 0xFD, 0xD1, 0x30, 0xA4, 0x28, 0x2A, 0x45, 0x67, 0x0A, 0x1B, 0xF7, 0xFF, 0x46, 0xB1, 0x67, 0x3B, + 0xE0, 0x26, 0x37, 0x1B, 0x7C, 0x5C, 0xED, 0x02, 0x91, 0xB3, 0xB9, 0x4E, 0x3F, 0x38, 0xF6, 0xFB, 0x7A, 0x38, 0xC5, 0xAA, + 0xD8, 0x32, 0xEB, 0xDC, 0xAC, 0x0B, 0x84, 0x26, 0x84, 0x60, 0x5E, 0xC0, 0xF4, 0x42, 0xDE, 0xFC, 0x7B, 0x7D, 0x60, 0xD7, + 0x7A, 0xB5, 0xFF, 0x23, 0x16, 0x33, 0x6F, 0xCE, 0x15, 0x1C, 0xA3, 0xC9, 0xDE, 0x7E, 0x1F, 0x47, 0x50, 0xCA, 0xB4, 0xB2, + 0xE2, 0x80, 0xF7, 0x5B, 0x6C, 0x78, 0xDF, 0xFD, 0xFB, 0x7F, 0x7E, 0x1F, 0x54, 0x2B, 0xD8, 0xEB, 0x94, 0x1B, 0x30, 0x05, + 0x27, 0x30, 0xB4, 0xCE, 0x56, 0x2D, 0xD7, 0x16, 0x05, 0x59, 0xA8, 0xEA, 0x14, 0xE3, 0x00, 0x62, 0x41, 0xCE, 0xED, 0x56, + 0x31, 0xEA, 0x04, 0x03, 0xEF, 0xA6, 0xA1, 0xFF, 0x15, 0x59, 0x49, 0xA1, 0xCD, 0x9F, 0xE9, 0xC8, 0xD2, 0xE2, 0x96, 0xEE, + 0x95, 0xE0, 0xAD, 0xD1, 0xEE, 0xA7, 0x01, 0x63, 0xCD, 0xCC, 0xAB, 0xB3, 0xD9, 0x34, 0x8C, 0xC2, 0xFA, 0xA4, 0x70, 0x58, + 0x06, 0x50, 0x9F, 0x80, 0xD9, 0x59, 0x74, 0x82, 0x50, 0x84, 0x8A, 0x4D, 0xC9, 0x2E, 0x18, 0xD2, 0x1B, 0x72, 0xE8, 0x6C, + 0x57, 0x31, 0x27, 0x67, 0x51, 0xE5, 0xCD, 0x01, 0x05, 0x52, 0xE4, 0x81, 0x7C, 0xEA, 0xD9, 0xC1, 0x41, 0xE1, 0x58, 0x43, + 0x53, 0xC1, 0x0F, 0x57, 0xEC, 0x01, 0x41, 0xF4, 0xE8, 0xA6, 0x7C, 0x69, 0xD3, 0x73, 0xEA, 0x8A, 0xC7, 0xA9, 0xC2, 0xBC, + 0x8B, 0x8F, 0xF9, 0x0E, 0x63, 0xA8, 0x6D, 0x02, 0x33, 0xE8, 0x88, 0xC1, 0xA7, 0x77, 0xBA, 0x1E, 0x10, 0x0B, 0xBA, 0xF6, + 0x1B, 0x54, 0x72, 0xAD, 0x2E, 0x49, 0xA3, 0x4C, 0xE2, 0x56, 0x8B, 0xA9, 0x53, 0x65, 0x78, 0x4D, 0x9A, 0xEA, 0xF3, 0x2F, + 0x21, 0xCC, 0x4C, 0xD1, 0xDA, 0xAA, 0xBB, 0xF9, 0x21, 0xCA, 0x39, 0xE9, 0x8F, 0x76, 0x43, 0xB9, 0xC4, 0xAF, 0xC0, 0xC0, + 0x2A, 0xA9, 0xE2, 0x38, 0xE5, 0x5A, 0x22, 0x4E, 0x6E, 0x21, 0xF7, 0xAC, 0xA4, 0x80, 0x82, 0x48, 0xBC, 0x8F, 0x6B, 0xA9, + 0xDD, 0x22, 0x5D, 0x56, 0x19, 0xAD, 0xD2, 0xD9, 0x30, 0x8D, 0x52, 0xDC, 0xD8, 0xCA, 0x1D, 0xD4, 0xE5, 0x38, 0x1C, 0xCB, + 0x9E, 0x3F, 0x83, 0xEF, 0xC2, 0x19, 0x5B, 0xCD, 0x01, 0x01, 0xD9, 0xA8, 0x63, 0x24, 0xF8, 0x60, 0x87, 0xED, 0xBB, 0x7B, + 0xBF, 0x42, 0x04, 0x5B, 0x5A, 0xC8, 0x24, 0x82, 0x24, 0x90, 0xA0, 0x74, 0x77, 0x90, 0x6E, 0xBF, 0xC7, 0xD6, 0x6B, 0x0B, + 0x72, 0xF0, 0x2C, 0x92, 0x25, 0xF4, 0x27, 0x74, 0xB7, 0xBB, 0xBC, 0x50, 0xC4, 0x2E, 0xBC, 0x8E, 0x89, 0xE1, 0x25, 0x83, + 0xA4, 0x92, 0x5E, 0xF8, 0xF7, 0x6D, 0x39, 0xCD, 0x45, 0x5A, 0xA6, 0xD5, 0x0B, 0xB0, 0x77, 0x8E, 0x06, 0x95, 0x4B, 0x67, + 0xF9, 0xBC, 0x77, 0xB2, 0x06, 0x59, 0x7D, 0xB7, 0x85, 0x06, 0x97, 0xFD, 0xD8, 0x9A, 0x84, 0x82, 0xB6, 0x29, 0xB4, 0xE7, + 0x41, 0x96, 0xF4, 0xE6, 0x76, 0xF4, 0xCF, 0xDA, 0xFB, 0xA5, 0x53, 0x53, 0x39, 0x3F, 0x43, 0xAC, 0x9A, 0x57, 0xFC, 0xF6, + 0x77, 0xF5, 0x0D, 0x45, 0x5A, 0xD7, 0x9D, 0xE0, 0x4F, 0xB9, 0xF1, 0xAD, 0xC2, 0x0A, 0xF5, 0xE7, 0xF6, 0xF6, 0x4E, 0xDF, + 0x7F, 0xE7, 0x3A, 0x55, 0xB2, 0xCE, 0x65, 0xFA, 0xA7, 0xDC, 0xFD, 0xF7, 0xF7, 0xF7, 0x2A, 0xE4, 0x8D, 0x10, 0xC6, 0xCA, + 0x48, 0x35, 0x32, 0x54, 0x91, 0x52, 0xB3, 0x2A, 0x7C, 0x69, 0x2A, 0x78, 0x2D, 0x99, 0xD6, 0x1C, 0x34, 0xDF, 0x1E, 0x43, + 0x6D, 0x42, 0x16, 0x1C, 0xA2, 0xA6, 0xA7, 0x69, 0x0D, 0x12, 0xDF, 0x0D, 0xBD, 0xE2, 0xCC, 0xF7, 0x4F, 0xA1, 0x68, 0xA7, + 0x7B, 0xFD, 0x2F, 0x9B, 0xAD, 0x9B, 0x97, 0xCF, 0xB9, 0xB4, 0x17, 0xC9, 0x12, 0x04, 0x17, 0x0C, 0x35, 0x8B, 0x8E, 0x79, + 0xAB, 0xDB, 0x9E, 0xEA, 0xBB, 0x9B, 0xE1, 0x68, 0x6F, 0xBF, 0xF6, 0xEE, 0x7E, 0xFC, 0xAE, 0xDA, 0x5F, 0x10, 0xFD, 0x23, + 0x73, 0xF3, 0xF6, 0x3F, 0xCE, 0x57, 0xFE, 0xFE, 0x7F, 0xFD, 0xCF, 0x68, 0xD1, 0xFE, 0x38, 0xDE, 0xB8, 0xBE, 0x4D, 0x09, + 0xCA, 0xD8, 0xF7, 0xEF, 0xFE, 0xFE, 0x90, 0x5F, 0xAF, 0x0E, 0x9F, 0x99, 0x1D, 0x41, 0x90, 0x19, 0x6D, 0x97, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x10, 0x20, 0x10, 0x20, 0x40, 0x40, 0x90, 0x24, 0x50, 0x60, 0x08, 0x10, + 0x01, 0x01, 0x88, 0x14, 0x11, 0x21, 0x18, 0x30, 0x41, 0x41, 0x98, 0x34, 0x51, 0x61, 0x01, 0x01, 0x80, 0x02, 0x81, 0x05, + 0x90, 0x22, 0x11, 0x21, 0xC0, 0x42, 0x91, 0x25, 0xD0, 0x62, 0x09, 0x11, 0x81, 0x03, 0x89, 0x15, 0x91, 0x23, 0x19, 0x31, + 0xC1, 0x43, 0x99, 0x35, 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, + 0x52, 0x64, 0x48, 0x50, 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, + 0x82, 0x06, 0xC1, 0x45, 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, + 0x93, 0x27, 0x59, 0x71, 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0x02, 0x08, 0x08, 0x08, 0x82, 0x0C, 0x18, 0x28, 0x12, 0x28, + 0x48, 0x48, 0x92, 0x2C, 0x58, 0x68, 0x0A, 0x18, 0x09, 0x09, 0x8A, 0x1C, 0x19, 0x29, 0x1A, 0x38, 0x49, 0x49, 0x9A, 0x3C, + 0x59, 0x69, 0x03, 0x09, 0x88, 0x0A, 0x83, 0x0D, 0x98, 0x2A, 0x13, 0x29, 0xC8, 0x4A, 0x93, 0x2D, 0xD8, 0x6A, 0x0B, 0x19, + 0x89, 0x0B, 0x8B, 0x1D, 0x99, 0x2B, 0x1B, 0x39, 0xC9, 0x4B, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, + 0x1A, 0x2C, 0x52, 0x68, 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, + 0x4B, 0x4D, 0xDA, 0x7C, 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, + 0xDA, 0x6E, 0x4B, 0x59, 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, + 0x20, 0x10, 0x84, 0x84, 0x30, 0x30, 0x14, 0xA0, 0x60, 0x50, 0x94, 0xA4, 0x70, 0x70, 0x0C, 0x90, 0x21, 0x11, 0x8C, 0x94, + 0x31, 0x31, 0x1C, 0xB0, 0x61, 0x51, 0x9C, 0xB4, 0x71, 0x71, 0x05, 0x81, 0xA0, 0x12, 0x85, 0x85, 0xB0, 0x32, 0x15, 0xA1, + 0xE0, 0x52, 0x95, 0xA5, 0xF0, 0x72, 0x0D, 0x91, 0xA1, 0x13, 0x8D, 0x95, 0xB1, 0x33, 0x1D, 0xB1, 0xE1, 0x53, 0x9D, 0xB5, + 0xF1, 0x73, 0x44, 0xC0, 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, + 0x23, 0x15, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, + 0xB2, 0x36, 0x55, 0xE1, 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, + 0xE3, 0x57, 0xDD, 0xF5, 0xF3, 0x77, 0x06, 0x88, 0x28, 0x18, 0x86, 0x8C, 0x38, 0x38, 0x16, 0xA8, 0x68, 0x58, 0x96, 0xAC, + 0x78, 0x78, 0x0E, 0x98, 0x29, 0x19, 0x8E, 0x9C, 0x39, 0x39, 0x1E, 0xB8, 0x69, 0x59, 0x9E, 0xBC, 0x79, 0x79, 0x07, 0x89, + 0xA8, 0x1A, 0x87, 0x8D, 0xB8, 0x3A, 0x17, 0xA9, 0xE8, 0x5A, 0x97, 0xAD, 0xF8, 0x7A, 0x0F, 0x99, 0xA9, 0x1B, 0x8F, 0x9D, + 0xB9, 0x3B, 0x1F, 0xB9, 0xE9, 0x5B, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, + 0x6A, 0x5C, 0xD6, 0xEC, 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, + 0x7B, 0x7D, 0x47, 0xC9, 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, + 0xAB, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x20, 0x02, 0x04, 0x80, 0xA0, 0x06, + 0x14, 0xA0, 0x30, 0x22, 0x44, 0xC0, 0xB0, 0x26, 0x54, 0xE0, 0x28, 0x12, 0x05, 0x81, 0xA8, 0x16, 0x15, 0xA1, 0x38, 0x32, + 0x45, 0xC1, 0xB8, 0x36, 0x55, 0xE1, 0x21, 0x03, 0x84, 0x82, 0xA1, 0x07, 0x94, 0xA2, 0x31, 0x23, 0xC4, 0xC2, 0xB1, 0x27, + 0xD4, 0xE2, 0x29, 0x13, 0x85, 0x83, 0xA9, 0x17, 0x95, 0xA3, 0x39, 0x33, 0xC5, 0xC3, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, + 0x06, 0x84, 0xE0, 0x46, 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, + 0x17, 0xA5, 0x78, 0x72, 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, + 0xC6, 0xC6, 0xF1, 0x67, 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, + 0xD7, 0xE7, 0x22, 0x0A, 0x0C, 0x88, 0xA2, 0x0E, 0x1C, 0xA8, 0x32, 0x2A, 0x4C, 0xC8, 0xB2, 0x2E, 0x5C, 0xE8, 0x2A, 0x1A, + 0x0D, 0x89, 0xAA, 0x1E, 0x1D, 0xA9, 0x3A, 0x3A, 0x4D, 0xC9, 0xBA, 0x3E, 0x5D, 0xE9, 0x23, 0x0B, 0x8C, 0x8A, 0xA3, 0x0F, + 0x9C, 0xAA, 0x33, 0x2B, 0xCC, 0xCA, 0xB3, 0x2F, 0xDC, 0xEA, 0x2B, 0x1B, 0x8D, 0x8B, 0xAB, 0x1F, 0x9D, 0xAB, 0x3B, 0x3B, + 0xCD, 0xCB, 0xBB, 0x3F, 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, + 0x5E, 0xEC, 0x6A, 0x5A, 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, + 0x8E, 0x8E, 0xE3, 0x4F, 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, + 0x9F, 0xAF, 0x7B, 0x7B, 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x24, 0x82, 0x24, 0x90, 0xA4, 0x86, 0x34, 0xB0, 0x34, 0xA2, + 0x64, 0xD0, 0xB4, 0xA6, 0x74, 0xF0, 0x2C, 0x92, 0x25, 0x91, 0xAC, 0x96, 0x35, 0xB1, 0x3C, 0xB2, 0x65, 0xD1, 0xBC, 0xB6, + 0x75, 0xF1, 0x25, 0x83, 0xA4, 0x92, 0xA5, 0x87, 0xB4, 0xB2, 0x35, 0xA3, 0xE4, 0xD2, 0xB5, 0xA7, 0xF4, 0xF2, 0x2D, 0x93, + 0xA5, 0x93, 0xAD, 0x97, 0xB5, 0xB3, 0x3D, 0xB3, 0xE5, 0xD3, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, + 0x36, 0xB4, 0x74, 0xE2, 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, + 0x67, 0xD5, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, + 0xF6, 0xF6, 0x6D, 0xD3, 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x8A, + 0x2C, 0x98, 0xA6, 0x8E, 0x3C, 0xB8, 0x36, 0xAA, 0x6C, 0xD8, 0xB6, 0xAE, 0x7C, 0xF8, 0x2E, 0x9A, 0x2D, 0x99, 0xAE, 0x9E, + 0x3D, 0xB9, 0x3E, 0xBA, 0x6D, 0xD9, 0xBE, 0xBE, 0x7D, 0xF9, 0x27, 0x8B, 0xAC, 0x9A, 0xA7, 0x8F, 0xBC, 0xBA, 0x37, 0xAB, + 0xEC, 0xDA, 0xB7, 0xAF, 0xFC, 0xFA, 0x2F, 0x9B, 0xAD, 0x9B, 0xAF, 0x9F, 0xBD, 0xBB, 0x3F, 0xBB, 0xED, 0xDB, 0xBF, 0xBF, + 0xFD, 0xFB, 0x66, 0xCA, 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, + 0x2F, 0x9D, 0xEE, 0xDE, 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, + 0xBE, 0xBE, 0x77, 0xEB, 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, + 0xEF, 0xDF, 0xFF, 0xFF, 0x80, 0xD7, 0x80, 0x00, 0x0C, 0x4C, 0xF8, 0x86, 0x19, 0x44, 0x0A, 0x28, 0x63, 0xD8, 0x78, 0x97, + 0xD5, 0x27, 0x51, 0xEF, 0xE0, 0xCE, 0xB0, 0x44, 0x01, 0x2E, 0x38, 0xCB, 0x32, 0x4D, 0x58, 0x34, 0x21, 0x94, 0xB6, 0x85, + 0x84, 0xD3, 0xB9, 0xD5, 0x2F, 0x2D, 0x4F, 0xA1, 0xC8, 0x39, 0x39, 0x86, 0xAF, 0x11, 0x60, 0xEA, 0xEA, 0x06, 0xE9, 0xD5, + 0x5F, 0xA8, 0xE6, 0xCF, 0xC7, 0x63, 0xD9, 0xB1, 0xD1, 0xF2, 0x6F, 0x3F, 0xDB, 0xB9, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, + 0x42, 0x44, 0xD0, 0x64, 0x52, 0x64, 0x08, 0x62, 0xFC, 0x03, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, + 0x53, 0x65, 0x0B, 0x44, 0xE9, 0x09, 0xC1, 0x45, 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0xC1, 0x53, + 0x22, 0x58, 0xC9, 0x55, 0x93, 0x27, 0x59, 0x71, 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0xA9, 0xE0, 0x08, 0xF3, 0xFF, 0xEE, + 0x2B, 0x0A, 0x4B, 0xD1, 0xC8, 0xD3, 0x25, 0x24, 0x5E, 0x68, 0xE5, 0xE2, 0x62, 0x99, 0x30, 0xFC, 0xA6, 0x69, 0x32, 0xBC, + 0x41, 0x9B, 0x9A, 0x04, 0x26, 0x79, 0x03, 0x7B, 0x2F, 0x1A, 0x59, 0x0C, 0xAB, 0x08, 0x13, 0xD4, 0xC8, 0x91, 0x80, 0x12, + 0xC0, 0x28, 0x24, 0xE8, 0xD1, 0x0E, 0x8B, 0xB4, 0x16, 0x29, 0x42, 0xBD, 0x3C, 0x84, 0x73, 0x9F, 0x5C, 0x6C, 0xF6, 0x2A, + 0x49, 0xF0, 0xC2, 0x4C, 0x1A, 0x2C, 0x52, 0x68, 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0xB1, 0x37, 0x56, 0xF2, 0xCA, 0x5C, + 0x1B, 0x2D, 0x5A, 0x78, 0x4B, 0x4D, 0xDA, 0x7C, 0x5B, 0x6D, 0xBE, 0x27, 0xC3, 0x01, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, + 0xCA, 0x4E, 0xD3, 0x6D, 0xDA, 0x6E, 0x2B, 0x1D, 0x0B, 0xD2, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, + 0xDB, 0x6F, 0x04, 0x80, 0x78, 0xF8, 0xFA, 0xB6, 0xB5, 0x26, 0xCB, 0xA0, 0x17, 0x5C, 0xA9, 0xE2, 0xD2, 0x3E, 0xDE, 0xB0, + 0x26, 0xE9, 0xD5, 0x80, 0xBC, 0x52, 0xD8, 0xCF, 0x05, 0x9E, 0x37, 0xCB, 0x33, 0x78, 0x4F, 0x28, 0x82, 0x11, 0xBA, 0xDB, + 0x41, 0xEE, 0xD5, 0xA0, 0xB6, 0x49, 0xE1, 0x81, 0x25, 0xCF, 0x02, 0x1D, 0xDA, 0x02, 0x26, 0x30, 0x64, 0x2D, 0x5C, 0xCF, + 0x87, 0x9C, 0x98, 0xA5, 0xD2, 0x82, 0x44, 0xC0, 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, + 0x72, 0x74, 0x4C, 0xD0, 0x23, 0x15, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, + 0xA2, 0x16, 0xC5, 0xC5, 0xB2, 0x36, 0x55, 0xE1, 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, + 0xB3, 0x37, 0x5D, 0xF1, 0xE3, 0x57, 0xDD, 0xF5, 0xF3, 0x77, 0xD9, 0x89, 0x2E, 0x38, 0xFB, 0x7F, 0xE0, 0xEC, 0x4F, 0x2D, + 0x8D, 0x4A, 0xF6, 0xEC, 0x56, 0xF5, 0x36, 0x70, 0x6B, 0xD6, 0x66, 0x16, 0x1B, 0xEF, 0x12, 0xCF, 0x0A, 0x26, 0x52, 0xDE, + 0x3A, 0x87, 0xAD, 0x0B, 0xAB, 0xFC, 0xA4, 0x7C, 0x24, 0x7A, 0x9D, 0xC9, 0xF8, 0x5C, 0xEF, 0x89, 0x7A, 0x32, 0x55, 0x6B, + 0x0A, 0x1D, 0xF0, 0xEE, 0x53, 0x93, 0x67, 0xBB, 0x1E, 0x5D, 0xE7, 0x3F, 0xFC, 0xE2, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, + 0x3A, 0x3C, 0x56, 0xE8, 0x6A, 0x5C, 0xD6, 0xEC, 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, + 0x6B, 0x5D, 0xDE, 0xFC, 0x7B, 0x7D, 0x47, 0xC9, 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, + 0xFA, 0x7E, 0x4F, 0xD9, 0xAB, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x7E, 0x1F, + 0x54, 0x2B, 0x17, 0x07, 0x99, 0xAC, 0x31, 0x5D, 0xA3, 0xC6, 0x5F, 0xC8, 0xD1, 0x47, 0xD7, 0x16, 0x05, 0x59, 0x4E, 0xE7, + 0xDF, 0xE1, 0x40, 0xB0, 0x44, 0xB9, 0x39, 0x31, 0x22, 0xE5, 0x04, 0x03, 0xEF, 0xA6, 0xC9, 0x19, 0x52, 0x56, 0x79, 0xB4, + 0xA7, 0x0D, 0x97, 0x2A, 0x50, 0x46, 0x96, 0xEE, 0x95, 0xE0, 0xF7, 0x85, 0x91, 0x2E, 0x63, 0x32, 0x66, 0xB8, 0x66, 0x27, + 0x52, 0xE4, 0x18, 0x65, 0xFB, 0x8B, 0xE0, 0x46, 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0xBF, 0xD0, + 0x02, 0xFC, 0xE8, 0x56, 0x17, 0xA5, 0x78, 0x72, 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x5E, 0xC6, 0x88, 0x0C, 0xE1, 0x47, + 0x96, 0xA6, 0x71, 0x63, 0xC6, 0xC6, 0xF1, 0x67, 0xD6, 0xE6, 0x11, 0x77, 0xA3, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, + 0xC7, 0xC7, 0xF9, 0x77, 0xD7, 0xE7, 0xC2, 0xBC, 0x8B, 0x8F, 0xDC, 0x90, 0xF7, 0x5E, 0x12, 0xD3, 0x4C, 0x53, 0x02, 0x9C, + 0x72, 0xAD, 0xBA, 0x1E, 0x10, 0x0B, 0xC9, 0xED, 0xF9, 0x06, 0x32, 0xBE, 0x45, 0xD2, 0x55, 0xCC, 0x5B, 0xE9, 0x8B, 0xA9, + 0x53, 0x65, 0xFD, 0x94, 0x8C, 0x05, 0x1B, 0xD6, 0xCC, 0x11, 0x45, 0x8A, 0x59, 0xED, 0xBB, 0xF9, 0x21, 0xCA, 0x1D, 0xEE, + 0x75, 0xFB, 0x64, 0x39, 0xBE, 0xCB, 0xEC, 0xE1, 0x24, 0x95, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, + 0x4E, 0xCC, 0xF2, 0x6E, 0x5E, 0xEC, 0x6A, 0x5A, 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, + 0x5F, 0xED, 0x63, 0x4B, 0x8E, 0x8E, 0xE3, 0x4F, 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, + 0x8F, 0x8F, 0xEB, 0x5F, 0x9F, 0xAF, 0x7B, 0x7B, 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x28, 0x85, 0x85, 0x18, 0xD6, 0x66, + 0x70, 0x3B, 0x7C, 0x35, 0x07, 0x3F, 0x8E, 0x44, 0xF6, 0xB8, 0xBB, 0x62, 0x2D, 0x9E, 0xAE, 0xB8, 0xC3, 0xC4, 0x06, 0x50, + 0xE7, 0xD9, 0xDC, 0xF2, 0x7A, 0xFC, 0x27, 0x61, 0x26, 0xDA, 0x8E, 0x69, 0x0B, 0xB6, 0x4D, 0x21, 0xE1, 0x03, 0xA8, 0x45, + 0x58, 0xFD, 0x4D, 0xD7, 0xD1, 0x9C, 0x5A, 0xC8, 0x08, 0x4F, 0xB4, 0x51, 0x67, 0xFB, 0xF7, 0x49, 0x56, 0xFE, 0x64, 0xC2, + 0x26, 0x94, 0xE4, 0xC6, 0x36, 0xB4, 0x74, 0xE2, 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, + 0x37, 0xB5, 0x7C, 0xF2, 0x67, 0xD5, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, + 0xE6, 0xD6, 0xF5, 0xE7, 0xF6, 0xF6, 0x6D, 0xD3, 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, + 0xF7, 0xF7, 0x46, 0x4A, 0xE2, 0x13, 0x0D, 0xE0, 0xE9, 0xB6, 0xD2, 0xC8, 0x2D, 0x98, 0xFC, 0x55, 0xDF, 0x04, 0xA7, 0x6A, + 0x25, 0x96, 0x0D, 0x96, 0xE1, 0x89, 0x64, 0xBB, 0xCE, 0xDF, 0xBE, 0x3C, 0x7C, 0x9A, 0x59, 0x69, 0x2E, 0x92, 0xCF, 0x09, + 0x40, 0xFB, 0x4F, 0x29, 0xE5, 0x3E, 0x0C, 0xF0, 0xFA, 0xBA, 0x9B, 0xE9, 0x0E, 0x56, 0x8C, 0x93, 0x65, 0xCB, 0x77, 0x2C, + 0x8E, 0xC4, 0xE5, 0xBE, 0x5E, 0xBA, 0x66, 0xCA, 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, + 0x7E, 0xFC, 0x6E, 0xDA, 0x2F, 0x9D, 0xEE, 0xDE, 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, + 0xAE, 0x9E, 0xE7, 0xCF, 0xBE, 0xBE, 0x77, 0xEB, 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, + 0xBF, 0xBF, 0x7F, 0xFB, 0xEF, 0xDF, 0xFF, 0xFF, 0x8B, 0xCC, 0x80, 0x00, 0x0C, 0x4C, 0x04, 0x44, 0xCA, 0x26, 0x11, 0xD4, + 0x40, 0xBD, 0xA2, 0x62, 0xC2, 0xDD, 0x51, 0xEF, 0xE0, 0xCE, 0xE8, 0x54, 0x0C, 0xAA, 0x41, 0xB1, 0xA0, 0x80, 0x1A, 0x73, + 0x7F, 0xBD, 0xB6, 0x85, 0x8C, 0x80, 0x09, 0x39, 0x71, 0x2D, 0xBD, 0xA4, 0xE1, 0xC0, 0x3A, 0x5F, 0x05, 0x79, 0x60, 0xEA, + 0xEA, 0x06, 0x0D, 0xF7, 0x13, 0x2B, 0xE3, 0xB9, 0xA2, 0x41, 0x4D, 0x6B, 0x42, 0x5C, 0xE8, 0xE2, 0x85, 0x23, 0x00, 0x44, + 0x62, 0x68, 0x90, 0x65, 0x52, 0x05, 0xD0, 0x64, 0x52, 0x64, 0x4D, 0x4A, 0x17, 0xB1, 0x60, 0xF7, 0x6C, 0xA5, 0xB0, 0xC3, + 0xC6, 0x02, 0xD8, 0x74, 0x53, 0x65, 0xD1, 0x5F, 0x92, 0xF2, 0xB1, 0x83, 0x38, 0x67, 0xF2, 0x69, 0x1E, 0x76, 0xD1, 0x65, + 0xD2, 0x66, 0xCC, 0x97, 0x69, 0x4B, 0x09, 0x55, 0xE3, 0x6B, 0x99, 0x75, 0x30, 0x0B, 0xD9, 0x75, 0xD3, 0x67, 0xA9, 0xE0, + 0x08, 0xF3, 0x0B, 0x7E, 0xBB, 0x2E, 0xC0, 0xDE, 0x7B, 0x2A, 0xEC, 0x37, 0x8C, 0xFC, 0xE5, 0xE2, 0x62, 0x99, 0xF2, 0x9E, + 0x18, 0x4B, 0x40, 0xB8, 0x2F, 0x86, 0xFB, 0x9C, 0x8F, 0xD6, 0x03, 0x7B, 0x2F, 0x1A, 0xCB, 0x9F, 0xFB, 0xD5, 0x29, 0x1D, + 0x2F, 0x58, 0xCD, 0x22, 0xDC, 0x24, 0x24, 0xE8, 0xD1, 0x0E, 0xB3, 0xCD, 0x76, 0x24, 0x21, 0xD1, 0x8F, 0x84, 0xA5, 0x8E, + 0x90, 0xEC, 0xB2, 0x0E, 0xA0, 0xF7, 0xB2, 0x8A, 0xB0, 0x6D, 0x26, 0x95, 0x6A, 0x0E, 0xD2, 0x6C, 0x5A, 0x6C, 0x70, 0xA7, + 0x0D, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x9A, 0x78, 0x3B, 0xB8, 0xDA, 0x7C, 0x5B, 0x6D, 0xC7, 0xCD, 0x8A, 0x9F, 0x53, 0x4D, + 0x9A, 0x2E, 0x53, 0x51, 0x2B, 0xB1, 0xD3, 0x6D, 0xDA, 0x6E, 0x58, 0x66, 0x9B, 0x4D, 0xCB, 0x5D, 0x9B, 0x2F, 0x5A, 0xFD, + 0xCB, 0xDE, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, 0x78, 0xF8, 0x44, 0x80, 0x78, 0xBD, 0xC9, 0x80, 0x66, 0x70, 0xE2, 0xE2, + 0xD6, 0x3C, 0xDE, 0xB0, 0x26, 0xE9, 0x77, 0x10, 0x35, 0xF9, 0x26, 0x52, 0x1A, 0x55, 0x9C, 0x8C, 0x90, 0x8E, 0x4F, 0x28, + 0x82, 0x11, 0x78, 0x7E, 0x43, 0xCD, 0xE3, 0x23, 0xE1, 0x2A, 0xE1, 0x58, 0xCE, 0x30, 0x02, 0x1D, 0x92, 0xD1, 0xB7, 0x6A, + 0x46, 0x71, 0x66, 0x4E, 0x96, 0x5F, 0x5D, 0xB5, 0x81, 0x86, 0x7F, 0x86, 0x80, 0x5A, 0xC4, 0xC4, 0x32, 0x34, 0x24, 0xC6, + 0x80, 0x12, 0xD4, 0xE4, 0x72, 0x74, 0xEB, 0xD9, 0xF3, 0x45, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0x86, 0x47, 0x1B, 0xDC, 0xF4, + 0x73, 0x75, 0x31, 0xE5, 0x76, 0x06, 0xC5, 0xC5, 0xB2, 0x36, 0x55, 0xA7, 0x40, 0x57, 0xD5, 0xE5, 0xF2, 0x76, 0x6A, 0xDC, + 0x24, 0xB0, 0xCD, 0xD5, 0xB3, 0x37, 0x2B, 0xB7, 0x45, 0x15, 0xDD, 0xF5, 0xF3, 0x77, 0xDC, 0x84, 0x1B, 0xDA, 0x06, 0x9E, + 0x3E, 0x78, 0xD6, 0xA9, 0x33, 0x43, 0x97, 0x28, 0x78, 0xE9, 0x6E, 0xD8, 0x27, 0x14, 0x4E, 0x9C, 0x43, 0x3D, 0xA1, 0x4E, + 0xEB, 0x51, 0x8D, 0x41, 0x69, 0x37, 0xC5, 0xFF, 0x8B, 0x45, 0x2A, 0x09, 0xBC, 0xB7, 0x55, 0xD7, 0x0F, 0x4A, 0x20, 0xA4, + 0xFE, 0x7A, 0x05, 0x91, 0x0A, 0x16, 0xE3, 0x5A, 0xBB, 0xCE, 0x92, 0x49, 0xE1, 0x54, 0xEF, 0xFB, 0x5B, 0x85, 0xEE, 0x6E, + 0x2C, 0x5C, 0xC6, 0xCC, 0x3A, 0x3C, 0xD6, 0x12, 0xEF, 0x7B, 0xD6, 0xEC, 0x7A, 0x7C, 0xCE, 0x5C, 0x2B, 0x8C, 0xCE, 0xDC, + 0x3B, 0x3D, 0x4D, 0xBE, 0xC9, 0x13, 0xDE, 0xFC, 0x7B, 0x7D, 0x3C, 0x8F, 0x00, 0xE5, 0xC7, 0xCD, 0xBA, 0x3E, 0x88, 0x89, + 0xEC, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x75, 0x26, 0xAD, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x2B, 0x7D, 0xEF, 0x58, 0xDF, 0xFD, + 0xFB, 0x7F, 0x7E, 0x1F, 0x54, 0x2B, 0x98, 0xD6, 0xE9, 0xAF, 0x50, 0x66, 0x38, 0x4B, 0xE8, 0x32, 0x37, 0x7C, 0xD7, 0x16, + 0x05, 0x59, 0xAC, 0xF4, 0x97, 0xA9, 0xAB, 0xD0, 0xC7, 0xC9, 0x09, 0x88, 0xE9, 0x16, 0x04, 0x03, 0xEF, 0xA6, 0xC1, 0x47, + 0x7A, 0x29, 0x35, 0xC1, 0x46, 0x8A, 0x48, 0xC8, 0x54, 0x62, 0x96, 0xEE, 0x95, 0xE0, 0x5C, 0xF5, 0x95, 0x08, 0xB4, 0xD1, + 0x47, 0xCB, 0x16, 0x58, 0x08, 0x3F, 0x60, 0x7A, 0xFA, 0xB4, 0xE0, 0x46, 0x16, 0xA4, 0xC7, 0x6B, 0x40, 0xC4, 0xF0, 0x66, + 0x56, 0xE4, 0xED, 0x54, 0xCF, 0xD5, 0xE8, 0x56, 0x17, 0xA5, 0x0C, 0xF6, 0x43, 0xC2, 0xF8, 0x76, 0x57, 0xE5, 0xA1, 0x43, + 0xF6, 0x22, 0xE1, 0x47, 0x96, 0xA6, 0x62, 0x25, 0x64, 0x88, 0xF1, 0x67, 0xD6, 0xE6, 0xCD, 0xAE, 0x07, 0x5C, 0xE9, 0x57, + 0x97, 0xA7, 0xB9, 0x76, 0xD7, 0x86, 0xF9, 0x77, 0xD7, 0xE7, 0xC2, 0xBC, 0x8B, 0x8F, 0x04, 0x0F, 0x1C, 0xA1, 0xBB, 0xC8, + 0x7F, 0x8A, 0x0B, 0x70, 0xDF, 0xE6, 0xBA, 0x1E, 0x10, 0x0B, 0x2A, 0xE4, 0xFC, 0xD6, 0xC5, 0xD2, 0x4F, 0x04, 0xBB, 0x21, + 0x45, 0x7D, 0x8B, 0xA9, 0x53, 0x65, 0xDE, 0xEF, 0x73, 0xE8, 0x89, 0xD5, 0xDC, 0x07, 0x53, 0x10, 0xF8, 0x3E, 0xBB, 0xF9, + 0x21, 0xCA, 0xD4, 0xE5, 0x62, 0x74, 0x40, 0x33, 0x28, 0x74, 0x3A, 0x24, 0xC1, 0xA5, 0x63, 0x8C, 0xAC, 0xC9, 0xE2, 0x4E, + 0x1E, 0xAC, 0xDA, 0xC9, 0x31, 0x6C, 0xF2, 0x6E, 0x5E, 0xEC, 0x81, 0xAD, 0x09, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0xFC, 0xBC, + 0xED, 0x81, 0xFA, 0x7E, 0x5F, 0xED, 0x11, 0xEE, 0x0B, 0x89, 0xE3, 0x4F, 0x9E, 0xAE, 0xB3, 0x6B, 0xBE, 0x35, 0xF3, 0x6F, + 0xDE, 0xEE, 0x3C, 0x84, 0x2C, 0xF1, 0xEB, 0x5F, 0x9F, 0xAF, 0x0B, 0xA4, 0x78, 0x81, 0xFB, 0x7F, 0xDF, 0xEF, 0x2E, 0x02, + 0x87, 0x96, 0xA0, 0xC1, 0xB5, 0xBE, 0x6B, 0xA0, 0x17, 0xD0, 0x4D, 0xE0, 0x9E, 0x54, 0xEA, 0x64, 0x16, 0x93, 0xF2, 0x05, + 0x31, 0x1A, 0xFC, 0xB3, 0x3E, 0xCA, 0x18, 0x4A, 0xF5, 0x0A, 0x6D, 0x11, 0x05, 0x89, 0x06, 0x11, 0x68, 0x54, 0xEA, 0xA3, + 0x93, 0xDE, 0x30, 0xA1, 0x3C, 0xA2, 0xF7, 0xF1, 0xB5, 0x58, 0xCF, 0x93, 0x54, 0x1C, 0x7B, 0xCC, 0x81, 0x1C, 0xBF, 0x71, + 0x57, 0xB6, 0x77, 0xFD, 0x32, 0xD6, 0xE4, 0xC6, 0x36, 0xB4, 0xB4, 0xE7, 0x76, 0x95, 0xF4, 0xE6, 0x76, 0xF4, 0xAC, 0xD2, + 0x57, 0x31, 0xEC, 0xD6, 0x37, 0xB5, 0xBC, 0xF2, 0x17, 0x2E, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xFB, 0x5A, 0xE6, 0xE5, 0xC7, + 0xB6, 0xB6, 0xDD, 0x40, 0x99, 0x76, 0xF5, 0xE7, 0xF6, 0xF6, 0x68, 0xD5, 0x6F, 0x87, 0xED, 0xD7, 0xB7, 0xB7, 0x7C, 0x35, + 0x45, 0x92, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x62, 0x62, 0x55, 0x45, 0x7D, 0xE2, 0x13, 0x77, 0xD4, 0x0A, 0x17, 0xC4, 0x0B, + 0xD8, 0x1F, 0x16, 0x8A, 0x4A, 0x9C, 0xD0, 0xA8, 0xD6, 0x5C, 0x26, 0xB3, 0x5E, 0x1B, 0xC4, 0x3A, 0x7D, 0x4A, 0xD8, 0x63, + 0xAA, 0x99, 0xC0, 0x87, 0x57, 0x2C, 0x36, 0xDD, 0xFE, 0x12, 0x63, 0xE9, 0x5E, 0x04, 0x0F, 0x9F, 0xCA, 0x92, 0xF1, 0xAC, + 0xA9, 0x14, 0x85, 0xAF, 0x60, 0x5D, 0x54, 0xC4, 0x62, 0xC6, 0xC2, 0xA8, 0x82, 0x63, 0xE6, 0xCE, 0x3E, 0xBC, 0x04, 0x4F, + 0xEB, 0xDB, 0xF6, 0xEE, 0x7E, 0xFC, 0x17, 0x9C, 0x8D, 0xD3, 0xEE, 0xDE, 0x3F, 0xBD, 0x96, 0x59, 0x90, 0x9C, 0xFE, 0xFE, + 0x7F, 0xFD, 0xA7, 0xCB, 0xDE, 0xE0, 0xE7, 0xCF, 0xBE, 0xBE, 0x98, 0x1C, 0x6B, 0xD9, 0xF7, 0xEF, 0xFE, 0xFE, 0x1B, 0x5F, + 0xAB, 0x98, 0xEF, 0xDF, 0xBF, 0xBF, 0xD7, 0x58, 0x90, 0x1F, 0xFF, 0xFF, 0x57, 0x3D, 0x26, 0x59, 0x70, 0xA4, 0xE1, 0x62, + 0xEF, 0x8D, 0x18, 0x24, 0x68, 0x5E, 0x8D, 0xAD, 0xBB, 0x04, 0x1D, 0xE0, 0x1A, 0xA0, 0x08, 0x35, 0xD2, 0x8C, 0xD8, 0x58, + 0x46, 0x4C, 0xE0, 0xC5, 0xF2, 0x21, 0x8A, 0x38, 0x61, 0xAD, 0x10, 0x42, 0x4E, 0x28, 0x4B, 0xAE, 0xA8, 0x73, 0x2A, 0xC7, + 0x7C, 0x9F, 0x1C, 0x95, 0xB0, 0x50, 0x1C, 0xC5, 0xCD, 0x2A, 0x41, 0x35, 0xE9, 0xCD, 0xA7, 0x1C, 0x31, 0xE2, 0x78, 0xB3, + 0x3E, 0xA9, 0xF8, 0xBB, 0xF0, 0xDB, 0x2A, 0x80, 0x50, 0xF1, 0x43, 0x40, 0x8E, 0xD5, 0x51, 0x05, 0xA2, 0x8A, 0xDD, 0xD0, + 0x22, 0xCD, 0xC2, 0xFA, 0xAA, 0x46, 0x4F, 0x9E, 0xF6, 0xEF, 0x11, 0x70, 0xBA, 0x44, 0x85, 0x36, 0xB0, 0x87, 0xC0, 0x5E, + 0xFA, 0x04, 0x39, 0xCC, 0xB1, 0xEF, 0x51, 0x55, 0x8A, 0xF1, 0xF7, 0x7C, 0x95, 0x3E, 0x4F, 0x58, 0xC5, 0x5E, 0xA1, 0xB2, + 0x11, 0x65, 0x3A, 0x68, 0x53, 0x83, 0x06, 0xC9, 0x24, 0x27, 0x48, 0x07, 0x20, 0x79, 0x2C, 0xA8, 0x69, 0x88, 0x13, 0x89, + 0xA8, 0x02, 0x15, 0x33, 0xC0, 0x14, 0x67, 0xCA, 0x6A, 0x09, 0xA4, 0x10, 0x5F, 0x50, 0xD8, 0x38, 0xB0, 0x48, 0x2C, 0x66, + 0x45, 0x68, 0xD3, 0x41, 0x82, 0x47, 0x68, 0x0A, 0x79, 0x95, 0xC7, 0xE9, 0xE8, 0xAA, 0xA4, 0x22, 0xA1, 0x69, 0x0F, 0x81, + 0xAA, 0xC2, 0x8D, 0xCE, 0x55, 0xB6, 0x7C, 0x61, 0x4A, 0xA3, 0x4A, 0x3F, 0x22, 0x23, 0xDC, 0x98, 0x42, 0x0E, 0xDA, 0x68, + 0xF2, 0x1E, 0x2C, 0x98, 0x0A, 0x4D, 0x46, 0x23, 0xB8, 0x8D, 0x22, 0x7A, 0x0B, 0xED, 0x15, 0x8C, 0x53, 0xB6, 0xD2, 0x3A, + 0xBE, 0x62, 0xE3, 0x5C, 0x9C, 0x37, 0x4A, 0x2D, 0xA9, 0x6E, 0x64, 0x54, 0xDC, 0xB7, 0x47, 0xC6, 0x62, 0x5E, 0x5A, 0x1C, + 0x3D, 0x8F, 0xCA, 0x38, 0x81, 0xEF, 0xDB, 0x57, 0xA3, 0x7F, 0xBC, 0xC4, 0x1C, 0x14, 0x44, 0xEC, 0x7A, 0x3D, 0xD4, 0xC8, + 0x06, 0x5D, 0x6F, 0xDB, 0x25, 0x8F, 0x36, 0x6F, 0xA1, 0x73, 0xE6, 0xE7, 0x09, 0x73, 0x09, 0x34, 0x50, 0xF3, 0x64, 0xB6, + 0x69, 0xD1, 0xC4, 0x70, 0x9C, 0x32, 0xFF, 0xE5, 0xB4, 0x13, 0x4D, 0x10, 0x83, 0x89, 0xFD, 0xC7, 0x43, 0x8F, 0x33, 0xBC, + 0xE2, 0x1C, 0x94, 0x6F, 0x46, 0x56, 0x25, 0x21, 0x42, 0xD8, 0x0C, 0xC6, 0xC5, 0x1F, 0xE8, 0x33, 0xAE, 0x19, 0xDC, 0xF9, + 0xDB, 0x05, 0x94, 0x85, 0x05, 0x4F, 0xAA, 0xD8, 0x9B, 0x17, 0x55, 0x1C, 0xDC, 0x9E, 0x5D, 0x93, 0xF9, 0xBF, 0x18, 0xB7, + 0xE1, 0x81, 0x70, 0x6B, 0x72, 0x35, 0x5A, 0xA1, 0xAC, 0x54, 0xC7, 0x36, 0x86, 0x9B, 0x61, 0x87, 0x00, 0x76, 0x97, 0x1A, + 0x1B, 0xA7, 0x8B, 0xE0, 0xD3, 0xB8, 0x85, 0xF0, 0xB5, 0x2E, 0xA8, 0x93, 0x29, 0x86, 0xF9, 0x5F, 0x1A, 0xA6, 0x1E, 0x91, + 0xC9, 0xB7, 0xBE, 0x4B, 0xF2, 0x89, 0xCD, 0x99, 0x5C, 0x1A, 0xF4, 0xB1, 0x79, 0x6C, 0x18, 0xB1, 0x2F, 0x00, 0x53, 0xEE, + 0xD2, 0x68, 0x66, 0x83, 0x51, 0xAC, 0x0E, 0x4D, 0x05, 0x2C, 0x92, 0x76, 0xCB, 0x20, 0x3C, 0x1E, 0xC8, 0x32, 0x0E, 0x38, + 0x49, 0xDA, 0x91, 0x84, 0xF0, 0x01, 0xDE, 0xEB, 0x0A, 0x90, 0x4F, 0xF5, 0xDF, 0x36, 0x8E, 0x3D, 0x9C, 0x4E, 0xC1, 0x1D, + 0x59, 0x00, 0xE6, 0xBA, 0x48, 0x70, 0x4A, 0xAE, 0xC5, 0x91, 0x36, 0xF6, 0xDC, 0x51, 0xD4, 0x1F, 0x06, 0xD1, 0x16, 0x45, + 0x2D, 0x04, 0xD7, 0x89, 0x9A, 0xC4, 0x7E, 0xE5, 0xE6, 0x5B, 0xD6, 0xF8, 0xF3, 0xFA, 0x39, 0xCE, 0x0B, 0xE7, 0x97, 0xFC, + 0x82, 0x7C, 0x31, 0xD0, 0xEB, 0xBC, 0x40, 0xAA, 0x30, 0x1D, 0x86, 0x26, 0xAD, 0xE5, 0x97, 0xC0, 0x52, 0x6E, 0xFC, 0xE6, + 0x4A, 0xF9, 0x85, 0x9D, 0x93, 0xAE, 0x35, 0xE8, 0xA1, 0x2F, 0xBF, 0x2D, 0x77, 0xD6, 0x25, 0xC8, 0xE1, 0x6F, 0xC8, 0x01, + 0xA9, 0xEF, 0x3D, 0x96, 0x34, 0x37, 0x60, 0x74, 0xEA, 0x2A, 0xC7, 0x59, 0xC8, 0x37, 0x78, 0x5E, 0xDC, 0x1E, 0xB4, 0xF3, + 0xD1, 0x23, 0xB7, 0x2E, 0x92, 0xBB, 0xA4, 0xCB, 0x56, 0x8F, 0xEB, 0x36, 0xBC, 0xD3, 0x11, 0xEC, 0x6C, 0xF2, 0xE4, 0x3E, + 0x93, 0xBA, 0x31, 0xEA, 0x2C, 0xB2, 0xE3, 0x11, 0xBD, 0xB2, 0x76, 0x20, 0x6E, 0x89, 0xF5, 0x07, 0xF2, 0x29, 0x65, 0x43, + 0xE1, 0x49, 0xD0, 0x77, 0xDB, 0x87, 0xE4, 0x30, 0xE4, 0x8E, 0x44, 0xC5, 0x54, 0xAF, 0xD4, 0xE1, 0x04, 0xCF, 0x85, 0x89, + 0xA2, 0xFE, 0x1F, 0x7B, 0x80, 0x9F, 0x9F, 0x6E, 0x7F, 0x97, 0x0F, 0x4A, 0x2F, 0xF7, 0x5A, 0xC2, 0x03, 0xF8, 0xF2, 0xD7, + 0xAA, 0x4C, 0xE0, 0xA7, 0x09, 0x06, 0xA3, 0x00, 0xFF, 0x47, 0xD9, 0xA3, 0x3C, 0xC4, 0x7A, 0x86, 0x8B, 0x99, 0x73, 0x71, + 0xBF, 0x23, 0x78, 0xC8, 0x6F, 0x22, 0xCB, 0x51, 0xFB, 0x63, 0xA0, 0x7A, 0x01, 0x74, 0x3F, 0xF8, 0x35, 0x27, 0x82, 0xC5, + 0xA4, 0x98, 0x83, 0x7C, 0xFC, 0xA4, 0x7A, 0x08, 0x69, 0x98, 0xB9, 0x26, 0x2F, 0x07, 0x4D, 0x07, 0xFF, 0xDC, 0xA9, 0x1E, + 0xE8, 0xF5, 0x33, 0x0E, 0xBE, 0xDD, 0xF1, 0x30, 0xF5, 0x9A, 0x97, 0xA4, 0xCE, 0x38, 0x44, 0xD7, 0x88, 0xA6, 0x38, 0xDE, + 0x66, 0xFD, 0xF7, 0xCA, 0x2F, 0xE6, 0x0C, 0x46, 0xA7, 0x9D, 0x4D, 0x66, 0x19, 0x43, 0x30, 0xCF, 0x67, 0xFC, 0xBA, 0x6F, + 0x27, 0xEF, 0xE0, 0xFE, 0x7E, 0xA5, 0xED, 0xFA, 0x6E, 0x4F, 0xA3, 0x23, 0xD9, 0x31, 0xDB, 0x2F, 0xA8, 0x03, 0xDF, 0xF8, + 0x8D, 0xC4, 0x23, 0x9F, 0xA9, 0x4F, 0x15, 0x5D, 0x6E, 0x0C, 0xF2, 0x0A, 0x3E, 0x20, 0x43, 0x89, 0xEC, 0xB5, 0xC3, 0x8C, + 0xF1, 0x62, 0x3E, 0xB3, 0x1C, 0x8F, 0xFC, 0xEF, 0x32, 0xA9, 0xF4, 0xCA, 0x3E, 0x2D, 0x33, 0x5F, 0x8B, 0x05, 0xA7, 0xA3, + 0x1D, 0xD3, 0x77, 0xA7, 0x01, 0xF3, 0xFC, 0xDA, 0x53, 0x5C, 0x73, 0x26, 0x57, 0x30, 0x1B, 0xAE, 0x03, 0x19, 0xE2, 0xF8, + 0x17, 0x39, 0x4D, 0x53, 0xFF, 0xE3, 0xE5, 0x99, 0x88, 0xB0, 0x34, 0x08, 0x58, 0x9C, 0xB4, 0x06, 0xD6, 0x93, 0x45, 0xA2, + 0xEA, 0x58, 0x3D, 0xF6, 0x59, 0x7E, 0xE6, 0x7D, 0x22, 0x36, 0xF2, 0xA4, 0x5E, 0xB9, 0xE7, 0x60, 0xB2, 0x00, 0x34, 0x8E, + 0x3C, 0xF9, 0x54, 0x41, 0x53, 0x93, 0x5B, 0xFF, 0x31, 0x7C, 0xFE, 0x02, 0x98, 0x7A, 0x6B, 0x72, 0x46, 0x57, 0xC9, 0x41, + 0x72, 0x02, 0x9B, 0xFF, 0x4E, 0xE7, 0x4D, 0x70, 0x9E, 0xDE, 0x0A, 0x17, 0xD7, 0x57, 0xCE, 0xDC, 0x06, 0x31, 0x8C, 0xC6, + 0x83, 0xB3, 0x6A, 0x00, 0x93, 0x7A, 0xC5, 0x0C, 0xF1, 0x6E, 0x20, 0xA3, 0xC5, 0xA9, 0xDE, 0x7F, 0x9F, 0xF8, 0x83, 0x9B, + 0x54, 0x9A, 0xC8, 0x87, 0x95, 0xC9, 0x14, 0x69, 0x15, 0x34, 0xAC, 0x60, 0x91, 0xB4, 0x46, 0xB8, 0x2D, 0x79, 0x3E, 0xDF, + 0x16, 0x54, 0x3D, 0x96, 0x8F, 0xBC, 0x99, 0xA6, 0xBA, 0xA3, 0x2E, 0x3A, 0x8F, 0x25, 0x1B, 0x3C, 0xFF, 0xF2, 0x3A, 0xDC, + 0x67, 0x91, 0x50, 0xEC, 0x89, 0xF9, 0xAE, 0xBA, 0x0B, 0xC0, 0xAA, 0x8E, 0x5C, 0x5A, 0x71, 0x8A, 0x6A, 0x17, 0x0C, 0xDF, + 0x06, 0xB8, 0xE5, 0x18, 0x4D, 0xBC, 0x1F, 0xA1, 0x83, 0x80, 0xFD, 0xA9, 0x5B, 0x12, 0x59, 0xF7, 0x39, 0x24, 0xEE, 0x89, + 0x4D, 0x7C, 0xE9, 0xCF, 0xDE, 0x5C, 0x98, 0x38, 0xD6, 0x31, 0x93, 0xEB, 0x46, 0xEF, 0x49, 0xD2, 0x0D, 0xD5, 0x5E, 0x91, + 0x6B, 0x53, 0x37, 0xDE, 0x46, 0x2E, 0x06, 0xC1, 0xC7, 0x4B, 0x6A, 0x7F, 0xDE, 0x37, 0xC7, 0x0C, 0xDD, 0xBD, 0x19, 0xF3, + 0xC2, 0xA0, 0x13, 0x06, 0x9B, 0xD5, 0xC4, 0xDE, 0xCF, 0x3D, 0x98, 0x20, 0xD7, 0xE1, 0x74, 0x82, 0x49, 0x09, 0xD2, 0x15, + 0x66, 0x21, 0x19, 0x43, 0x67, 0xE9, 0xE0, 0x47, 0x21, 0xE7, 0x49, 0x14, 0x86, 0x1B, 0xD1, 0x81, 0x8B, 0xD7, 0xF6, 0x4F, + 0x16, 0x4A, 0x7D, 0x56, 0xA8, 0xE4, 0x8A, 0xD6, 0xB2, 0xBB, 0xB8, 0x2C, 0x81, 0x27, 0x4D, 0xD1, 0xC5, 0x66, 0x99, 0xF5, + 0xC1, 0x9E, 0x7E, 0x5F, 0x76, 0xA9, 0x82, 0xBB, 0xFB, 0xD5, 0x2E, 0x4C, 0x01, 0x4B, 0xD6, 0x59, 0xDB, 0xBB, 0x76, 0x6C, + 0x8C, 0x83, 0x92, 0x7B, 0x7B, 0xD4, 0x4E, 0x59, 0x45, 0x7C, 0x03, 0x49, 0x55, 0x7C, 0xD6, 0x61, 0x2F, 0x36, 0x6D, 0xDA, + 0x91, 0xBD, 0x09, 0x6D, 0xA1, 0xDB, 0x41, 0x7A, 0xE6, 0xED, 0x5B, 0x11, 0xDD, 0x03, 0x09, 0x3D, 0xD9, 0x2A, 0x1D, 0x81, + 0xCB, 0x48, 0x9F, 0x17, 0x38, 0x16, 0xBA, 0x87, 0x1A, 0x45, 0x84, 0x4B, 0x36, 0xF4, 0xD7, 0x53, 0x9D, 0xD5, 0xF0, 0xCE, + 0xAD, 0xEE, 0x5F, 0x1A, 0x59, 0x67, 0x4A, 0x75, 0x33, 0x68, 0xCE, 0x66, 0x67, 0x95, 0x39, 0x83, 0x3A, 0x49, 0xE2, 0x49, + 0x8A, 0x46, 0x57, 0x53, 0x0B, 0x15, 0xB8, 0xC1, 0xCC, 0x26, 0x93, 0x6D, 0x9C, 0x6C, 0x52, 0xDD, 0x2C, 0x7D, 0x56, 0x00, + 0xE2, 0xF0, 0x72, 0xD2, 0x36, 0x25, 0xE3, 0x4E, 0xED, 0xE1, 0xC4, 0x3B, 0x7E, 0x62, 0xDC, 0x75, 0x39, 0xB5, 0x54, 0x41, + 0xA3, 0x7D, 0x12, 0x10, 0x05, 0xE1, 0x10, 0xA4, 0x63, 0x7C, 0x9A, 0x2F, 0x39, 0x41, 0x3A, 0x66, 0xF6, 0x40, 0x4F, 0xBC, + 0x73, 0xE6, 0x21, 0xCB, 0x8B, 0xCC, 0xFD, 0x70, 0xDA, 0x81, 0x21, 0x74, 0x49, 0x0F, 0x28, 0x13, 0x57, 0xC8, 0x8B, 0x31, + 0xC1, 0x02, 0xAD, 0x9D, 0x98, 0x26, 0x19, 0x9B, 0xA8, 0x39, 0xC3, 0x41, 0xDD, 0x76, 0x20, 0xE7, 0xD7, 0x20, 0xDC, 0x80, + 0xB9, 0x39, 0x40, 0x52, 0x53, 0x54, 0x90, 0xC4, 0x4D, 0x1E, 0xD8, 0xCE, 0x0F, 0xCD, 0xF5, 0xF2, 0xDA, 0x60, 0xD3, 0x46, + 0x45, 0x57, 0xA2, 0x8C, 0xB3, 0x41, 0xB9, 0x69, 0xA4, 0x7E, 0xDF, 0xF5, 0xD8, 0x43, 0xDF, 0x57, 0xF0, 0x9F, 0xAB, 0x9C, + 0x32, 0x7B, 0x64, 0x7A, 0x5E, 0x88, 0x4D, 0xFD, 0x2B, 0x3E, 0xAB, 0xD1, 0x40, 0xFC, 0x95, 0xB1, 0x71, 0x6B, 0xD1, 0xFF, + 0x1A, 0x56, 0x53, 0x40, 0x57, 0x22, 0xAB, 0x9B, 0x0A, 0x59, 0xAD, 0x82, 0x31, 0x7B, 0x72, 0xED, 0x03, 0xF8, 0x0C, 0xBC, + 0x79, 0xBE, 0x5E, 0x00, 0x25, 0xE4, 0xCE, 0x16, 0x06, 0x7E, 0x5E, 0x45, 0xA1, 0xE6, 0x9F, 0xEA, 0xDA, 0x35, 0x43, 0x83, + 0x19, 0x8D, 0x2E, 0x0D, 0xA7, 0x3B, 0x4B, 0x94, 0xDF, 0x13, 0x32, 0x37, 0x4F, 0xC6, 0x9D, 0x99, 0xB4, 0xC8, 0x4A, 0x71, + 0xC2, 0x77, 0x06, 0x71, 0x24, 0x5A, 0xF8, 0xB1, 0xC0, 0x49, 0x46, 0x59, 0x1C, 0x78, 0x3A, 0xD3, 0xBA, 0x7D, 0xE9, 0xF6, + 0xFF, 0x11, 0xAD, 0x82, 0x49, 0xCD, 0xCA, 0x78, 0x59, 0xD2, 0x9D, 0xCF, 0x01, 0xFF, 0x03, 0x4E, 0x27, 0x67, 0x30, 0xA4, + 0xBE, 0xA3, 0x29, 0x95, 0x65, 0xFC, 0x2C, 0x3F, 0xF8, 0x70, 0xC3, 0xEA, 0x8F, 0xB3, 0x98, 0xDA, 0x50, 0x8A, 0x07, 0x88, + 0x9D, 0x19, 0xB7, 0xCE, 0x89, 0xFD, 0x66, 0xC0, 0x27, 0xED, 0x06, 0x05, 0xC6, 0x91, 0x0C, 0x7C, 0x16, 0x1E, 0xAD, 0xCB, + 0xDB, 0xC3, 0xD9, 0x25, 0x2D, 0x04, 0x4C, 0xAF, 0x19, 0x94, 0x56, 0xE8, 0x54, 0x7D, 0x9B, 0x78, 0x4A, 0x5A, 0x46, 0xCB, + 0xA6, 0x74, 0x50, 0xBC, 0xCE, 0x37, 0x4E, 0x35, 0x65, 0xC8, 0xE9, 0xC1, 0xFC, 0x47, 0x2A, 0xAA, 0xD7, 0x10, 0x5C, 0x3D, + 0xB5, 0xB4, 0x7F, 0xFD, 0xD4, 0x5F, 0x1F, 0x95, 0x41, 0x3D, 0x61, 0x64, 0x92, 0x88, 0xFB, 0x31, 0x6B, 0x22, 0x8D, 0xBD, + 0xF1, 0x16, 0xC8, 0xDD, 0x75, 0x02, 0xFC, 0x62, 0x01, 0x8A, 0x53, 0x64, 0xFE, 0x90, 0x80, 0xCD, 0xAC, 0xCB, 0x80, 0xCC, + 0xAC, 0x8D, 0xA1, 0x45, 0xBE, 0x2F, 0x7A, 0x2D, 0x92, 0x98, 0x39, 0x2F, 0xF7, 0xE7, 0xE8, 0x7B, 0x71, 0x63, 0x20, 0x2C, + 0xA7, 0xC1, 0x97, 0x3E, 0x18, 0x05, 0xD5, 0xAC, 0xC6, 0xBA, 0xDA, 0x77, 0x85, 0x1E, 0x22, 0xA0, 0x65, 0xF1, 0xBA, 0x69, + 0x7E, 0xA7, 0x67, 0xE6, 0x77, 0x8E, 0xB6, 0x04, 0xAD, 0x1D, 0x2E, 0xA2, 0xF8, 0x8A, 0xF6, 0x6F, 0x34, 0xAF, 0xF7, 0x10, + 0xCA, 0x13, 0xEF, 0xF2, 0x66, 0x47, 0x77, 0x6A, 0x80, 0x9F, 0x21, 0x2F, 0xDC, 0xAB, 0x49, 0x9D, 0xC0, 0xDF, 0xE9, 0xE2, + 0xB5, 0x93, 0x49, 0xF7, 0x6E, 0x76, 0xDE, 0xF7, 0x6B, 0x56, 0x31, 0x62, 0xC1, 0xDE, 0xA3, 0x88, 0x74, 0x6C, 0xBD, 0x41, + 0xF1, 0xE4, 0xEA, 0x4E, 0x18, 0x84, 0x34, 0x17, 0x65, 0xA6, 0xD0, 0xB6, 0xA9, 0x6E, 0xEA, 0x72, 0xA6, 0x0F, 0xBF, 0x9A, + 0x2C, 0x0B, 0x6A, 0x93, 0x4F, 0x64, 0xBA, 0xC3, 0x0F, 0xEF, 0x41, 0x1B, 0x8D, 0x1B, 0xB9, 0xFF, 0x20, 0x0B, 0x35, 0x17, + 0xE5, 0x86, 0xB3, 0xEF, 0x9C, 0x31, 0x29, 0x5B, 0xE5, 0xB0, 0x93, 0xEC, 0xA1, 0x24, 0xEB, 0xC9, 0x32, 0x66, 0x18, 0x71, + 0x7C, 0x62, 0x72, 0x2D, 0x76, 0x01, 0x22, 0x36, 0x89, 0xC2, 0xFD, 0x14, 0xED, 0x47, 0x29, 0x5F, 0x6A, 0xAE, 0x7F, 0xDE, + 0x7E, 0xCF, 0xAB, 0x38, 0xC9, 0xA5, 0xB2, 0x08, 0xEC, 0x30, 0x82, 0x62, 0xDF, 0xD3, 0x9E, 0x70, 0xB2, 0x7B, 0xBA, 0x49, + 0x3B, 0x58, 0x96, 0x52, 0xC8, 0xD7, 0xEA, 0xFE, 0x7F, 0x6C, 0x63, 0x57, 0x93, 0x3A, 0x3C, 0x64, 0xBD, 0x5A, 0x6D, 0x19, + 0xA7, 0xC2, 0xA1, 0x0F, 0xB7, 0xBE, 0x70, 0x62, 0x7D, 0xD1, 0xC6, 0xC6, 0xDD, 0x21, 0x2D, 0x33, 0xC5, 0x7F, 0x30, 0xE6, + 0x70, 0xF4, 0xC9, 0x1A, 0x80, 0xC7, 0x80, 0xAA, 0xC9, 0xC0, 0xFC, 0xC6, 0xF7, 0x5A, 0x5B, 0xC5, 0x05, 0x27, 0x89, 0x6B, + 0x20, 0xDF, 0xC7, 0x87, 0xB7, 0xF2, 0xA2, 0x58, 0x18, 0xD1, 0x61, 0x60, 0x1D, 0x43, 0x65, 0xD7, 0x4C, 0xD0, 0x6D, 0xEB, + 0x44, 0xDD, 0x88, 0x82, 0x99, 0x91, 0xB5, 0xAF, 0x2C, 0x0E, 0x62, 0xEB, 0x8E, 0x05, 0xE0, 0x3A, 0x36, 0xA1, 0xCF, 0x32, + 0x6E, 0xAD, 0xED, 0xF3, 0x85, 0x91, 0x2E, 0xE3, 0x1F, 0xD7, 0x40, 0x73, 0xE2, 0xD6, 0xEB, 0x01, 0xE3, 0x58, 0x3C, 0x9F, + 0x1F, 0xB7, 0x5F, 0x30, 0x9E, 0x1D, 0xF2, 0xCF, 0x36, 0x16, 0x6D, 0xFB, 0x85, 0x14, 0xCD, 0x1C, 0x1F, 0xA7, 0x74, 0x90, + 0x86, 0x96, 0x46, 0x1D, 0x0C, 0xF5, 0x2F, 0xB4, 0x0C, 0xB3, 0xE4, 0x54, 0x94, 0x57, 0x28, 0x2B, 0x0F, 0x0B, 0x98, 0xB7, + 0xFE, 0xB2, 0x2F, 0x3B, 0x0F, 0x27, 0x99, 0xF4, 0x89, 0x64, 0x55, 0x92, 0x88, 0x26, 0xE6, 0x96, 0xC0, 0x3F, 0x29, 0x3E, + 0x5C, 0x7B, 0x9E, 0xAE, 0x85, 0x48, 0xB7, 0x63, 0x24, 0xD7, 0x99, 0xB7, 0x7E, 0xBA, 0x4F, 0x5B, 0x9B, 0x7B, 0x00, 0x96, + 0x08, 0x6B, 0x39, 0xF9, 0x52, 0x06, 0xE7, 0xE1, 0x7F, 0xBB, 0x07, 0x2B, 0x4E, 0x7B, 0x8C, 0x87, 0xFB, 0x02, 0x3C, 0x36, + 0x46, 0xAD, 0xFB, 0x6F, 0x5D, 0x67, 0x4D, 0x08, 0x32, 0x6C, 0x61, 0x6A, 0x4F, 0xD0, 0x36, 0x4E, 0x4C, 0x14, 0xA8, 0xBC, + 0x7D, 0xB2, 0x69, 0xE1, 0x1B, 0x50, 0x6F, 0x14, 0x82, 0xB2, 0xA7, 0xA3, 0xE4, 0x93, 0xF1, 0xF6, 0xB8, 0xA7, 0x9C, 0x2C, + 0xCA, 0x2A, 0x08, 0x1F, 0x5A, 0x5F, 0x79, 0xF2, 0x1C, 0xD2, 0xE9, 0x7F, 0x3F, 0x89, 0x01, 0xC6, 0x06, 0xD5, 0x6F, 0xFF, + 0xFF, 0xFF, 0xBF, 0xF1, 0xA3, 0x40, 0xFE, 0x02, 0xF1, 0xA3, 0xF7, 0x5E, 0x21, 0x44, 0xD6, 0x46, 0x73, 0xB1, 0xA8, 0x63, + 0xA2, 0x82, 0x18, 0xE7, 0x95, 0xAC, 0x88, 0xC3, 0xC5, 0xCC, 0x58, 0x58, 0xA2, 0x0D, 0x33, 0x31, 0x19, 0xAD, 0x29, 0xF6, + 0x1C, 0x2F, 0x68, 0xD1, 0x40, 0x54, 0xA6, 0x19, 0x2C, 0x93, 0xBF, 0xE2, 0x0D, 0x0E, 0xDB, 0x53, 0x7A, 0x47, 0x4B, 0x72, + 0x2A, 0x27, 0x26, 0xA6, 0xB3, 0xBE, 0x3B, 0x87, 0xFB, 0xF2, 0x00, 0x2C, 0x12, 0xFB, 0xF7, 0x4C, 0x44, 0x5D, 0xEA, 0xC1, + 0xA1, 0x26, 0x6E, 0xF0, 0x3D, 0x70, 0x63, 0x13, 0x1D, 0xF9, 0x26, 0x5D, 0xEF, 0x48, 0x5F, 0x8D, 0xAC, 0x9E, 0x7A, 0xDF, + 0x83, 0xB6, 0x75, 0x27, 0xA1, 0xC6, 0xCF, 0xE5, 0xF3, 0xA6, 0x9E, 0x98, 0xF6, 0x1D, 0x1D, 0x6A, 0xE1, 0x92, 0x0D, 0x9F, + 0x28, 0xD8, 0x27, 0x49, 0x3B, 0x16, 0x6C, 0x89, 0x3F, 0x25, 0x92, 0xF8, 0x7F, 0xA9, 0x12, 0xFF, 0x9C, 0xA5, 0x82, 0xDB, + 0xCC, 0xC5, 0xF4, 0x89, 0x5B, 0x88, 0x58, 0x2F, 0xE2, 0x6D, 0x1A, 0xED, 0xBA, 0xE9, 0x8A, 0xC8, 0x1C, 0xE8, 0xBC, 0x00, + 0x73, 0xDC, 0x16, 0xFA, 0x0C, 0x87, 0xD1, 0x13, 0x73, 0x4E, 0x41, 0x6A, 0x23, 0x2E, 0x30, 0x88, 0x04, 0xE9, 0x9B, 0x22, + 0xBD, 0xFE, 0xB9, 0x2D, 0xB2, 0x84, 0x8E, 0xCA, 0x4D, 0xC6, 0x08, 0x02, 0xFB, 0x29, 0x96, 0x77, 0x76, 0x08, 0x98, 0x71, + 0x72, 0x3F, 0xE5, 0x41, 0x4C, 0x85, 0x1D, 0xFC, 0xBB, 0xC3, 0xFF, 0xFC, 0xF3, 0xCE, 0x91, 0x5C, 0x67, 0xD2, 0xF6, 0xEB, + 0x48, 0x47, 0xBC, 0xBC, 0x58, 0xC6, 0xC6, 0x5A, 0xF6, 0x7D, 0x03, 0x25, 0x3B, 0x23, 0xAD, 0x1B, 0x35, 0xB3, 0xC6, 0x1E, + 0xE2, 0x02, 0x78, 0xE8, 0x77, 0x0C, 0xF0, 0xE1, 0x6C, 0xA4, 0x0E, 0x89, 0x77, 0xBE, 0x81, 0xF2, 0xB3, 0x5E, 0xA0, 0xA4, + 0x83, 0xBD, 0x96, 0xF3, 0x14, 0x9F, 0x84, 0x53, 0xE4, 0xDD, 0xAA, 0x01, 0x93, 0x79, 0xAC, 0xE2, 0x4B, 0xE0, 0x3A, 0xB0, + 0xED, 0x80, 0x24, 0x94, 0x8A, 0x35, 0xFE, 0x94, 0x98, 0x12, 0x55, 0xB0, 0x94, 0xBD, 0x25, 0xF6, 0x13, 0xB1, 0x47, 0x8B, + 0x0B, 0x36, 0x8C, 0x62, 0x19, 0xF1, 0x73, 0x96, 0x85, 0x98, 0x4D, 0xE9, 0xEE, 0x35, 0x43, 0x53, 0xE5, 0xFE, 0xFF, 0xB4, + 0xF2, 0xC9, 0xCB, 0x33, 0xA6, 0x99, 0xB9, 0x3B, 0x51, 0xE7, 0x6F, 0x6E, 0x63, 0xA4, 0xC9, 0x65, 0xD3, 0x7F, 0x38, 0xAF, + 0x48, 0x1A, 0xC9, 0xB6, 0x40, 0x35, 0x45, 0x61, 0x00, 0xAA, 0xC9, 0x70, 0x46, 0xEA, 0x17, 0x82, 0xA4, 0x0F, 0xD3, 0x6D, + 0xB4, 0x0F, 0x0F, 0xCE, 0x9E, 0x14, 0x13, 0xDE, 0xC6, 0x83, 0xCF, 0xE3, 0xC3, 0x2B, 0x5A, 0x2A, 0x42, 0xE4, 0x25, 0x75, + 0xD2, 0x75, 0x71, 0x8A, 0x39, 0xC6, 0xE3, 0xB5, 0xC3, 0x5C, 0x30, 0xEC, 0x99, 0x97, 0x85, 0x2C, 0x28, 0xE4, 0xA8, 0x18, + 0xBA, 0x79, 0xAA, 0xBC, 0x4A, 0xDB, 0xDE, 0x6C, 0xC6, 0x96, 0x61, 0xC7, 0x01, 0x54, 0xD6, 0x79, 0x90, 0x7A, 0x3D, 0x39, + 0x2D, 0xB5, 0x10, 0xAA, 0x19, 0x95, 0x2F, 0x53, 0x44, 0x57, 0xA9, 0x1C, 0x3A, 0x5A, 0x19, 0xA1, 0x42, 0x5F, 0x5B, 0x6E, + 0xDB, 0x94, 0x8F, 0x49, 0x95, 0xAA, 0x5F, 0xD5, 0x4C, 0x39, 0x38, 0xCE, 0xCB, 0x9F, 0x3D, 0x3C, 0x8B, 0x9D, 0x6E, 0x78, + 0xC9, 0xAC, 0x6D, 0x7F, 0x0A, 0x76, 0x5C, 0xA1, 0xC0, 0x59, 0x0E, 0xB1, 0x48, 0x81, 0x1A, 0x9A, 0xE4, 0xDB, 0xC9, 0xEF, + 0x4F, 0x0C, 0xEB, 0x4D, 0x9B, 0x42, 0x96, 0x49, 0x8B, 0x18, 0x77, 0xAA, 0xEC, 0x47, 0x51, 0xF3, 0x8A, 0x8A, 0x75, 0x69, + 0x22, 0x5D, 0x70, 0x86, 0x6A, 0xE2, 0x5B, 0xB9, 0xA3, 0xAA, 0xD9, 0xD1, 0x12, 0x2E, 0x35, 0x86, 0x7D, 0xB5, 0x00, 0x74, + 0x76, 0xCC, 0x62, 0x64, 0xAF, 0xA4, 0x29, 0xDC, 0xD9, 0x1D, 0x9D, 0xE2, 0x9B, 0x20, 0x9A, 0x26, 0x88, 0x0E, 0x40, 0x00, + 0x3D, 0x3E, 0xEE, 0xF6, 0x19, 0x35, 0x96, 0x2F, 0x82, 0x7B, 0x31, 0xF6, 0x37, 0x62, 0xA1, 0x19, 0x67, 0x6D, 0xD7, 0x93, + 0x21, 0x44, 0x3C, 0xE0, 0x01, 0x0E, 0x09, 0x65, 0xF7, 0xCF, 0x07, 0xD1, 0xB7, 0x1C, 0xEF, 0x28, 0xB3, 0x47, 0xA0, 0x3B, + 0x0B, 0x0F, 0x49, 0x77, 0x24, 0xE6, 0xB0, 0x0A, 0x0C, 0xC9, 0x30, 0x0E, 0x51, 0xE9, 0x71, 0xC3, 0x64, 0xA5, 0xB3, 0x48, + 0x2D, 0x51, 0xB8, 0x1A, 0x2A, 0x87, 0x86, 0x4E, 0xBC, 0x54, 0xBA, 0x72, 0xFE, 0xC4, 0xF8, 0x4C, 0x90, 0xDF, 0x6F, 0x4A, + 0xE5, 0xB7, 0xE9, 0x12, 0xB5, 0x19, 0x11, 0x77, 0x5F, 0x56, 0x38, 0x24, 0xF9, 0xE5, 0x60, 0x66, 0x34, 0xA2, 0x87, 0x5A, + 0x36, 0x48, 0x70, 0x4C, 0xE7, 0xEC, 0x32, 0xF1, 0x2F, 0xAC, 0xA2, 0xD9, 0xC0, 0x55, 0x21, 0x8A, 0x14, 0x39, 0x3C, 0x36, + 0xE6, 0xCD, 0x10, 0x43, 0xFA, 0xE8, 0xAA, 0x45, 0x26, 0xC6, 0x3D, 0x7E, 0xE1, 0x44, 0x1B, 0xF4, 0xEF, 0xB0, 0x19, 0x53, + 0x7B, 0xBA, 0x4B, 0x0C, 0x35, 0xC5, 0x8D, 0x13, 0x51, 0x6C, 0x11, 0xAB, 0x00, 0x24, 0xF5, 0xFD, 0x99, 0x2E, 0xBB, 0x09, + 0xAD, 0x26, 0xE9, 0xCD, 0xFE, 0x8B, 0xDD, 0xBB, 0xAD, 0x4C, 0xFB, 0xAF, 0x18, 0xB5, 0x4A, 0x91, 0x7D, 0x74, 0x63, 0x9E, + 0x45, 0x4D, 0xCA, 0x28, 0x6D, 0xE1, 0xB3, 0x4B, 0xCA, 0xC1, 0x3B, 0x1C, 0x25, 0xBC, 0xC2, 0x1E, 0x77, 0x66, 0x51, 0x7B, + 0xF3, 0x21, 0x65, 0xB1, 0x32, 0xA3, 0xCB, 0x5A, 0xBE, 0xB1, 0x62, 0xEB, 0xEF, 0xBD, 0xAB, 0x33, 0x1A, 0x0E, 0x2F, 0x01, + 0x91, 0xB1, 0x82, 0xBC, 0x36, 0xB9, 0xC0, 0x4E, 0xEB, 0xAD, 0x1E, 0x32, 0xA9, 0x3F, 0xF2, 0x75, 0x52, 0x3D, 0x4A, 0xA4, + 0x85, 0x53, 0xAD, 0xB3, 0x83, 0x95, 0x72, 0x70, 0x21, 0x14, 0xBA, 0xAA, 0x33, 0xA8, 0x02, 0x1F, 0x0E, 0xDE, 0x82, 0x13, + 0x03, 0x2E, 0x81, 0xE1, 0x80, 0x6F, 0xDB, 0xBB, 0xD7, 0x88, 0x9D, 0x50, 0x68, 0x93, 0x8D, 0x96, 0x96, 0x0D, 0x3F, 0x88, + 0x81, 0x9C, 0x7C, 0xF5, 0x94, 0xFB, 0xBD, 0x81, 0x85, 0x67, 0xE3, 0x55, 0xF1, 0x5E, 0x7D, 0x61, 0x45, 0xD1, 0xCF, 0x42, + 0x3E, 0x98, 0x61, 0x66, 0x4B, 0x90, 0x58, 0x74, 0x2A, 0xFC, 0x36, 0x03, 0x5B, 0x8A, 0x53, 0x99, 0xC7, 0x86, 0x0E, 0xF6, + 0x2F, 0x20, 0xE4, 0xC3, 0x14, 0x80, 0xF2, 0x29, 0x03, 0x49, 0x4C, 0xB9, 0x23, 0xCA, 0xB5, 0x8B, 0xEC, 0xDB, 0xDE, 0x94, + 0xCA, 0x79, 0xD6, 0x35, 0x83, 0x1A, 0xDA, 0x7B, 0x43, 0x84, 0x68, 0x77, 0xDE, 0x8F, 0xEB, 0xDE, 0xF1, 0xEE, 0x19, 0x7B, + 0x8F, 0xD8, 0xFC, 0xF4, 0x54, 0x69, 0xA6, 0xD9, 0x4E, 0x59, 0x21, 0x9C, 0x1C, 0x4C, 0x3C, 0x9E, 0xD2, 0x14, 0xF6, 0x36, + 0x5E, 0x62, 0x13, 0xC5, 0xE0, 0x98, 0x0A, 0xDC, 0x15, 0x3A, 0x15, 0xBB, 0x41, 0xDB, 0x67, 0xE6, 0xB6, 0xB7, 0xB7, 0x54, + 0xEA, 0x23, 0x77, 0xC7, 0xB0, 0x65, 0xFB, 0x65, 0x5C, 0xF5, 0xB9, 0xA3, 0xBB, 0xA2, 0x29, 0xD9, 0x8D, 0x2B, 0xC0, 0xCC, + 0x97, 0x68, 0x18, 0xE3, 0x28, 0x85, 0x51, 0x62, 0x38, 0x9C, 0x70, 0xC3, 0x87, 0xED, 0xB0, 0x9D, 0x42, 0xF3, 0x6A, 0x9A, + 0x44, 0x68, 0x55, 0x72, 0xC8, 0xFC, 0xFE, 0xBB, 0x48, 0x9C, 0xB8, 0x9C, 0x3F, 0xF2, 0x23, 0xA9, 0x21, 0x18, 0xCB, 0xB0, + 0x82, 0x41, 0xDB, 0x79, 0xB2, 0xD4, 0xE5, 0x13, 0xF8, 0xE7, 0x7A, 0x5F, 0xDA, 0x65, 0xD7, 0xEE, 0x1E, 0x00, 0xD8, 0x4E, + 0x37, 0xCC, 0xC1, 0xD6, 0xF9, 0xE6, 0x19, 0x84, 0x39, 0x68, 0x2F, 0x7E, 0xCD, 0x62, 0xC4, 0xDE, 0xF9, 0x02, 0xE8, 0xA0, + 0x61, 0x7D, 0x70, 0x37, 0xE8, 0xB0, 0xB6, 0xA4, 0x17, 0x38, 0xF4, 0x14, 0xCC, 0x00, 0x3C, 0xC4, 0xAE, 0x6E, 0x7F, 0x06, + 0x69, 0x93, 0x4E, 0x11, 0x4C, 0xE1, 0x08, 0xDC, 0xC1, 0x02, 0x51, 0x4C, 0xDD, 0xCD, 0x71, 0x00, 0xB9, 0x2A, 0x78, 0x91, + 0xA0, 0xC3, 0xBE, 0x91, 0x19, 0x60, 0x2D, 0xD7, 0xF5, 0xE8, 0x3E, 0x46, 0xE3, 0x87, 0x94, 0xB4, 0x64, 0x85, 0x0A, 0x00, + 0x7E, 0x06, 0x4E, 0x77, 0x1A, 0x55, 0x4A, 0x3D, 0xEA, 0xFD, 0xF0, 0xAB, 0x70, 0x38, 0x98, 0x18, 0x72, 0x07, 0x5F, 0x34, + 0xBA, 0x24, 0xE9, 0xB2, 0x0E, 0x46, 0x91, 0xC1, 0xAB, 0x16, 0x48, 0xF0, 0x33, 0x49, 0xEF, 0x4C, 0x5F, 0xE0, 0x11, 0x91, + 0xA3, 0x06, 0xDF, 0xF5, 0x95, 0x3E, 0x40, 0x64, 0x74, 0x22, 0xB9, 0x76, 0x86, 0x6A, 0x64, 0x2C, 0xB5, 0x03, 0x79, 0x2B, + 0xB9, 0x33, 0xD2, 0x40, 0x48, 0x97, 0x27, 0x11, 0x5E, 0x71, 0xF1, 0x3F, 0xA8, 0x12, 0x21, 0x99, 0x8A, 0x16, 0xB1, 0x7F, + 0x47, 0x95, 0x41, 0xB8, 0x68, 0xCB, 0x97, 0x8D, 0xB9, 0x0A, 0x05, 0x53, 0x15, 0x48, 0xA7, 0x4B, 0xFB, 0xAA, 0xD5, 0x42, + 0x7B, 0xEB, 0x8D, 0x47, 0x04, 0x69, 0xF0, 0x6E, 0xF3, 0x69, 0xDF, 0xF3, 0x72, 0xB4, 0xC1, 0x3C, 0x7A, 0x29, 0x4D, 0x3A, + 0xF5, 0xF1, 0xA6, 0x2E, 0xE1, 0x6E, 0x6A, 0x87, 0xC7, 0xBA, 0xD8, 0x6E, 0xF9, 0x2E, 0x44, 0xDC, 0x3A, 0xF5, 0xB2, 0x6E, + 0xE0, 0xB8, 0xF1, 0x16, 0x9E, 0xB1, 0x51, 0x1E, 0x7A, 0xFD, 0xEF, 0xDA, 0x89, 0x04, 0x0C, 0x59, 0x67, 0x81, 0xEA, 0xF7, + 0xC9, 0x7E, 0x18, 0xA1, 0x58, 0x4A, 0x73, 0x39, 0xF9, 0x84, 0xB3, 0x2E, 0xB1, 0x6D, 0xE6, 0x26, 0x12, 0xD2, 0xE5, 0x15, + 0x54, 0xE9, 0x3C, 0x68, 0x6C, 0xCC, 0x9D, 0xB7, 0x14, 0x72, 0x7D, 0x4B, 0x9F, 0xDB, 0xFD, 0x4F, 0x8F, 0xFB, 0x65, 0x7B, + 0xCA, 0x12, 0x0A, 0x7E, 0x9D, 0x3C, 0x05, 0x33, 0xC0, 0xEE, 0xB9, 0xCB, 0x77, 0x68, 0xA9, 0x04, 0x75, 0x70, 0x9C, 0xEF, + 0xB6, 0x2B, 0x2C, 0x90, 0xCA, 0x10, 0x3C, 0x88, 0xF6, 0x6B, 0x57, 0xFB, 0xD9, 0x51, 0xF3, 0x93, 0x21, 0x57, 0xDD, 0x6C, + 0xA5, 0xAE, 0x02, 0x31, 0xC0, 0x93, 0x85, 0xBE, 0xC1, 0x1D, 0xCC, 0xC1, 0x4D, 0x34, 0x2C, 0xC7, 0xDF, 0x16, 0x8E, 0x58, + 0x0E, 0x36, 0x8C, 0xB8, 0x15, 0x98, 0x17, 0xD6, 0x4C, 0xDD, 0xDA, 0x1E, 0xCF, 0x58, 0x4C, 0x04, 0x2C, 0x84, 0x87, 0x31, + 0xB9, 0xC7, 0x55, 0x38, 0xBA, 0x77, 0x4C, 0x9C, 0xE4, 0x4F, 0xC8, 0xEC, 0x07, 0x79, 0x35, 0x21, 0xF6, 0xC6, 0x92, 0xB2, + 0xB5, 0x4D, 0xA0, 0x8E, 0x8B, 0x5A, 0xA3, 0xF3, 0x12, 0xF4, 0x1F, 0x0B, 0x89, 0x87, 0x2A, 0x1E, 0xBA, 0x95, 0x68, 0x4A, + 0x88, 0xE7, 0x6D, 0x8B, 0xD9, 0x63, 0xAE, 0xEA, 0x4B, 0x55, 0x5C, 0xE7, 0xFB, 0x3F, 0x28, 0x9C, 0xB5, 0xDA, 0x35, 0x39, + 0xEA, 0x46, 0x5D, 0x35, 0xD0, 0xB5, 0x23, 0x1F, 0xB8, 0x32, 0x29, 0x0D, 0xEE, 0x43, 0x11, 0xF3, 0x75, 0x18, 0x71, 0x9E, + 0x08, 0x24, 0xB4, 0x0F, 0xB9, 0x33, 0x38, 0x08, 0xEF, 0x42, 0x60, 0x4D, 0x48, 0x0A, 0x86, 0xA0, 0xF0, 0x91, 0xF1, 0xB3, + 0x1B, 0xBE, 0x44, 0x91, 0x81, 0x18, 0x7E, 0x1F, 0xF6, 0x71, 0x37, 0xAA, 0x8C, 0xED, 0xD2, 0x3A, 0x9E, 0x53, 0xFA, 0x96, + 0xC8, 0x38, 0xA0, 0xFA, 0x9A, 0xFE, 0x3F, 0x39, 0xCB, 0xCF, 0x9E, 0x56, 0x1F, 0x9F, 0x6D, 0x59, 0x63, 0xF1, 0x2C, 0x1D, + 0xDB, 0x8F, 0x6F, 0x6A, 0x8F, 0x23, 0xAD, 0x4D, 0xBA, 0xAF, 0xE2, 0x1B, 0x88, 0xFF, 0x77, 0x0E, 0x77, 0x72, 0x8B, 0x87, + 0x97, 0xBF, 0xBD, 0xBE, 0x12, 0xB9, 0x6A, 0x6C, 0x2C, 0xE3, 0xA9, 0x53, 0x52, 0xD9, 0x3F, 0x96, 0x34, 0xB5, 0xF1, 0x03, + 0xC0, 0xCD, 0x47, 0xB6, 0x1A, 0x01, 0x28, 0x79, 0xAC, 0x9D, 0x5F, 0xA3, 0xE7, 0xDE, 0x27, 0xF9, 0x38, 0xAF, 0xF1, 0x4B, + 0x5C, 0xCF, 0x3D, 0xA3, 0xE5, 0xC5, 0x11, 0xE9, 0xE6, 0x72, 0x6D, 0x49, 0x9B, 0xBD, 0x9E, 0x97, 0x2C, 0xC0, 0x96, 0x48, + 0x0C, 0x48, 0xD5, 0x7F, 0x00, 0x9D, 0xF9, 0x71, 0x32, 0x09, 0x5F, 0x7A, 0xC6, 0xD8, 0xEA, 0xA6, 0x1E, 0xA6, 0xA8, 0x3A, + 0xF4, 0x1A, 0x88, 0x11, 0x26, 0xA8, 0x26, 0x90, 0x43, 0x78, 0x78, 0xAE, 0x04, 0x6E, 0x27, 0x21, 0x71, 0x7B, 0x2D, 0xF5, + 0x9E, 0x14, 0xDE, 0x18, 0x1B, 0x87, 0x3E, 0xC1, 0x56, 0x3B, 0xDD, 0x31, 0x7C, 0x9C, 0xF1, 0xC2, 0xB7, 0x66, 0xB9, 0x1B, + 0x87, 0x98, 0x50, 0x4A, 0xD1, 0xFE, 0x35, 0xF9, 0x88, 0x05, 0xDF, 0xF5, 0xC1, 0x35, 0xF2, 0x43, 0x3E, 0x8A, 0xCA, 0x2A, + 0xA5, 0xAA, 0xEA, 0x72, 0xB7, 0xCB, 0x15, 0xED, 0xBE, 0x2C, 0x02, 0xD2, 0x01, 0x15, 0x82, 0xD6, 0x11, 0x35, 0x71, 0x4D, + 0x0C, 0x0B, 0x0C, 0x8B, 0xC3, 0x6A, 0x2A, 0x3E, 0x3B, 0xAF, 0xAA, 0x3F, 0x2B, 0x8F, 0x32, 0x0E, 0x7A, 0xEE, 0xD4, 0x6C, + 0xFB, 0xE9, 0x97, 0xBE, 0x18, 0xA9, 0x17, 0xBA, 0x08, 0x89, 0xEB, 0x2C, 0xB9, 0x9C, 0xA0, 0x89, 0xE3, 0x2A, 0xC6, 0x08, + 0xF1, 0x31, 0xD7, 0x0C, 0xA9, 0xAE, 0x8F, 0x20, 0x99, 0x85, 0xA2, 0x56, 0xE6, 0x2B, 0x04, 0x7C, 0xAE, 0x4E, 0xA0, 0x14, + 0x23, 0xAF, 0xDB, 0xA4, 0x01, 0x33, 0xF2, 0x31, 0x5C, 0xAE, 0x65, 0x09, 0xAE, 0x36, 0xEA, 0xB4, 0x2B, 0xE1, 0x69, 0x9D, + 0xAF, 0x8B, 0xFA, 0x25, 0x5D, 0xAF, 0x57, 0x88, 0x43, 0x92, 0xE2, 0xFC, 0x7E, 0x30, 0x1F, 0xB2, 0x20, 0x6F, 0x37, 0x02, + 0x05, 0x59, 0x34, 0x5C, 0xC8, 0xDD, 0x74, 0xCE, 0xFE, 0x0D, 0x7C, 0x16, 0x14, 0x6A, 0x18, 0xF4, 0xDE, 0xF5, 0xF8, 0xEC, + 0x6B, 0xCF, 0xAA, 0xD4, 0x15, 0x33, 0x1F, 0x26, 0x53, 0x3F, 0x65, 0xEF, 0xF8, 0xAD, 0x6C, 0xB6, 0x31, 0xBE, 0xCD, 0xDC, + 0x9C, 0xFF, 0x25, 0x87, 0x1C, 0xD1, 0x8C, 0x90, 0x3A, 0x35, 0x40, 0x49, 0x0C, 0x70, 0x7D, 0xDF, 0xA2, 0x6C, 0xDB, 0x89, + 0x45, 0x6B, 0x84, 0x87, 0xBA, 0xB9, 0x63, 0x66, 0x57, 0xF8, 0x58, 0x78, 0x36, 0x0B, 0x56, 0x28, 0xCC, 0x76, 0xD6, 0x3E, + 0xED, 0xFA, 0x05, 0x8C, 0xC0, 0x94, 0x78, 0x08, 0x08, 0xD5, 0x9A, 0x3D, 0x5E, 0x9C, 0xEF, 0xC6, 0x15, 0xF7, 0x8E, 0x13, + 0xAD, 0x27, 0x65, 0x98, 0xA3, 0xFD, 0x56, 0x94, 0x6D, 0x9D, 0x7D, 0xA5, 0x5C, 0x86, 0xDA, 0x53, 0xE1, 0xCE, 0xC2, 0xAF, + 0xD4, 0x97, 0x3F, 0x62, 0x2F, 0x1A, 0x8E, 0xFD, 0xB0, 0x3E, 0xF6, 0xC2, 0x64, 0x07, 0x02, 0xCC, 0x87, 0x9D, 0x77, 0xDA, + 0x71, 0x04, 0x1B, 0xAF, 0x03, 0xFB, 0x95, 0xFD, 0x63, 0x05, 0x41, 0xD1, 0x15, 0xF4, 0x19, 0x2B, 0xAA, 0x83, 0xA7, 0x4F, + 0xAE, 0x31, 0x83, 0xC9, 0xDF, 0x3A, 0x8F, 0x51, 0x50, 0xF7, 0x3D, 0x9F, 0x52, 0x16, 0xB6, 0x0E, 0xDE, 0x44, 0xFB, 0x71, + 0x56, 0x64, 0xA9, 0xDD, 0x9D, 0x01, 0x2E, 0x6E, 0x4D, 0xE9, 0xBC, 0x32, 0x56, 0x8D, 0x19, 0x88, 0x91, 0x57, 0x8D, 0x17, + 0x76, 0xBE, 0x56, 0xB3, 0x0C, 0x3C, 0x02, 0x4C, 0x37, 0xB5, 0x67, 0xF1, 0xCE, 0x62, 0x7A, 0x03, 0x80, 0xBC, 0x74, 0x4F, + 0x9F, 0x3C, 0x27, 0xA7, 0xF4, 0xB3, 0xDE, 0xDA, 0xCC, 0x9C, 0xF3, 0x28, 0x0B, 0xF7, 0xDA, 0x6E, 0xE7, 0x7C, 0xE9, 0xE0, + 0x87, 0xFD, 0xBF, 0x26, 0xAB, 0x2B, 0x6F, 0xFF, 0xAA, 0x3E, 0x3A, 0x82, 0xD8, 0x95, 0xDA, 0x74, 0xB3, 0x3B, 0x28, 0x50, + 0x48, 0x4B, 0xE9, 0x55, 0x5B, 0x76, 0x52, 0xB4, 0xA2, 0x8C, 0x30, 0xEB, 0x17, 0x8A, 0xAE, 0xCD, 0x60, 0x03, 0x08, 0xC8, + 0x9B, 0x9A, 0x79, 0x83, 0x54, 0x2A, 0x08, 0x63, 0x67, 0x32, 0x91, 0x00, 0xD6, 0x99, 0x99, 0x20, 0x55, 0x12, 0x50, 0x09, + 0x26, 0x58, 0x91, 0xD5, 0x8D, 0xAE, 0x47, 0x07, 0xC7, 0x88, 0x81, 0xD9, 0x3D, 0x18, 0x1B, 0x22, 0x42, 0x0B, 0xF8, 0x94, + 0xEC, 0x2B, 0x5C, 0x66, 0xE3, 0xCE, 0x8A, 0x7B, 0x24, 0xCB, 0xCA, 0x16, 0x1F, 0x4B, 0xC2, 0x50, 0xB0, 0x28, 0xC1, 0x80, + 0x4B, 0x4A, 0x18, 0x70, 0x04, 0xD8, 0xED, 0xD3, 0xC2, 0x0E, 0xA1, 0x01, 0x9D, 0x2B, 0x2E, 0x83, 0x40, 0x0E, 0x75, 0x0B, + 0x4E, 0x69, 0x0B, 0x96, 0xA7, 0x01, 0xC3, 0x54, 0x30, 0x21, 0x39, 0x31, 0xCD, 0x4A, 0xD2, 0x95, 0x16, 0x0B, 0xB4, 0xE5, + 0x29, 0xA3, 0xE2, 0x12, 0x3A, 0x27, 0x09, 0xD4, 0x82, 0xB3, 0x8A, 0x3F, 0x6C, 0x3B, 0x51, 0x27, 0x76, 0x29, 0x8E, 0xFA, + 0x3D, 0x8D, 0x02, 0x2B, 0x56, 0x61, 0x82, 0xC4, 0xC7, 0x2B, 0x50, 0x08, 0xF3, 0x55, 0x13, 0xE5, 0xC8, 0xA1, 0x0B, 0xD1, + 0x24, 0xF1, 0xB5, 0x00, 0xE6, 0xD1, 0xCB, 0x18, 0x98, 0x0D, 0x46, 0x31, 0x51, 0xB1, 0x3D, 0xE1, 0xCC, 0x30, 0x45, 0x7C, + 0xAE, 0x8E, 0xE1, 0x03, 0xAB, 0x07, 0x4A, 0x25, 0x79, 0x0C, 0x58, 0x6C, 0xE9, 0x41, 0x8B, 0xA2, 0xFF, 0xEA, 0x72, 0x68, + 0x6C, 0xA2, 0xB2, 0xDE, 0x12, 0xCB, 0x52, 0xFC, 0xEA, 0xC5, 0xDA, 0x3C, 0x4A, 0x76, 0x02, 0xCB, 0x5E, 0x95, 0xBB, 0xCF, + 0x9F, 0xB7, 0x59, 0x79, 0x69, 0x48, 0xD5, 0xE5, 0x7F, 0xE8, 0xEB, 0x2B, 0xE9, 0xDB, 0xC9, 0xBF, 0x19, 0x67, 0x5F, 0x9B, + 0x67, 0x42, 0x7C, 0x0B, 0x24, 0x0D, 0xBF, 0x62, 0x8C, 0xED, 0x03, 0x78, 0xFA, 0xCB, 0x0C, 0x5C, 0x8C, 0x12, 0xAE, 0x37, + 0x40, 0xDF, 0xB7, 0x02, 0x74, 0x19, 0xAA, 0xB9, 0x34, 0x4A, 0xBB, 0x99, 0x95, 0xE9, 0xA4, 0x4B, 0x98, 0x20, 0x7D, 0xC6, + 0x62, 0x96, 0x9D, 0x96, 0x84, 0x1A, 0x4C, 0x7F, 0x34, 0x43, 0x84, 0xD6, 0xCC, 0xD3, 0x0B, 0xE3, 0x23, 0xC7, 0x95, 0x79, + 0x19, 0x88, 0xAA, 0xED, 0xE7, 0xF8, 0x49, 0x4B, 0x92, 0x7A, 0x3C, 0x42, 0x2B, 0x5B, 0x7C, 0x24, 0x22, 0x76, 0x2C, 0x62, + 0x63, 0x33, 0xF4, 0x77, 0xD1, 0x7E, 0x2C, 0x91, 0xC4, 0x18, 0x33, 0xB5, 0x9E, 0x2E, 0x64, 0x20, 0x3F, 0xDD, 0x70, 0x66, + 0x7F, 0x7F, 0x7D, 0x11, 0x59, 0x19, 0x4C, 0x36, 0xB4, 0x2D, 0x2D, 0x63, 0xE3, 0x11, 0x16, 0x0D, 0x26, 0xBB, 0x07, 0x2A, + 0x00, 0x11, 0xF3, 0xB3, 0x44, 0x27, 0x4D, 0x13, 0x61, 0x5F, 0x59, 0xE1, 0x73, 0x15, 0x56, 0x6A, 0x53, 0x88, 0x9E, 0x74, + 0xA6, 0x7A, 0x0E, 0x68, 0x24, 0x43, 0x01, 0x5F, 0xFC, 0xF3, 0xD5, 0x9A, 0x2F, 0xB3, 0x32, 0x6D, 0x09, 0x39, 0x3E, 0x09, + 0xE6, 0x5F, 0xA0, 0x94, 0xDA, 0x1C, 0x5C, 0x89, 0xD7, 0x41, 0x88, 0xDE, 0xBE, 0x91, 0x14, 0x59, 0xE4, 0x15, 0x21, 0x11, + 0x13, 0x1E, 0xC7, 0x87, 0x99, 0xEF, 0xF1, 0xB4, 0xC6, 0x32, 0xBC, 0xED, 0x48, 0xFD, 0xA1, 0x94, 0x5A, 0x7D, 0x4A, 0x36, + 0x8B, 0x96, 0x7E, 0x37, 0xEB, 0xE1, 0x26, 0x92, 0xC9, 0x39, 0x3E, 0xC0, 0xFD, 0x7F, 0x71, 0xBA, 0x68, 0xC2, 0xCA, 0x44, + 0xC2, 0x9C, 0x98, 0x87, 0xC8, 0x5B, 0x72, 0x14, 0xE0, 0x30, 0x38, 0x2B, 0x28, 0x36, 0xEC, 0xB6, 0xE0, 0x35, 0x68, 0x0B, + 0x68, 0x56, 0xED, 0x05, 0x2E, 0xB1, 0x37, 0xBB, 0xEA, 0x5F, 0xF7, 0x22, 0x4A, 0x5C, 0xD7, 0xFA, 0x4A, 0xD7, 0xBD, 0xFC, + 0xF8, 0x1F, 0x96, 0x66, 0xA5, 0x09, 0x35, 0x84, 0xC0, 0x9C, 0x28, 0xCE, 0xEC, 0x82, 0x6F, 0x46, 0xE8, 0x91, 0x10, 0x62, + 0x6A, 0x88, 0xF3, 0x85, 0x6E, 0xA8, 0x84, 0xC3, 0x75, 0xC1, 0x78, 0xF2, 0xE8, 0x3A, 0x0A, 0xE3, 0xC4, 0xE7, 0x99, 0xB5, + 0x98, 0x52, 0x3E, 0x70, 0xC2, 0x69, 0x00, 0x0B, 0xAF, 0xC2, 0x28, 0x61, 0x07, 0x57, 0x1C, 0x3A, 0x21, 0xF2, 0x47, 0x1A, + 0xBA, 0xCA, 0x0F, 0xCA, 0xF4, 0x56, 0x1E, 0x45, 0xA7, 0x7B, 0x75, 0xD6, 0xB5, 0xE5, 0x7A, 0x42, 0xE5, 0xC9, 0x8F, 0x21, + 0x65, 0xA9, 0xCB, 0x19, 0x64, 0xA5, 0xFD, 0x36, 0x92, 0x74, 0x70, 0xF6, 0xE6, 0x4D, 0x86, 0x94, 0x45, 0xA8, 0xA1, 0x17, + 0x27, 0x80, 0xBF, 0x6F, 0x7A, 0x0D, 0x7B, 0x23, 0x65, 0xC0, 0x49, 0xFC, 0xB5, 0xE2, 0x11, 0xD1, 0x53, 0xBB, 0x89, 0x55, + 0xFC, 0xAA, 0xF9, 0x91, 0x66, 0x4F, 0xE3, 0x75, 0x1D, 0xE8, 0x8C, 0xE8, 0xA0, 0x87, 0x7D, 0x6E, 0x6B, 0xDE, 0xE9, 0x09, + 0x4A, 0x4B, 0x27, 0x14, 0x68, 0xAA, 0x12, 0xE4, 0xA1, 0x84, 0x09, 0x55, 0xBC, 0x20, 0x2F, 0xDC, 0xA4, 0xF3, 0x1D, 0x17, + 0xD0, 0x64, 0xB3, 0x89, 0x60, 0x83, 0x63, 0xCE, 0x27, 0xAC, 0x5C, 0xC3, 0x06, 0x67, 0xFD, 0xEB, 0x08, 0xFB, 0xD4, 0x99, + 0x59, 0x67, 0xA9, 0x7F, 0x99, 0x83, 0x44, 0xC3, 0xCD, 0x30, 0xDD, 0x16, 0x36, 0xDA, 0x5A, 0x5A, 0xAD, 0xE0, 0x1D, 0x1C, + 0x10, 0x26, 0x70, 0x88, 0xCC, 0x84, 0xBA, 0xCF, 0xA3, 0x8E, 0x50, 0xB8, 0x8D, 0xA5, 0xF6, 0x28, 0x2C, 0xF3, 0x1A, 0x3A, + 0xE2, 0xC2, 0x56, 0x96, 0x8C, 0xA0, 0xF3, 0xC9, 0x8B, 0x6A, 0x65, 0xEF, 0x3F, 0xEE, 0x61, 0x9B, 0xC6, 0xC1, 0x37, 0xBF, + 0xA0, 0x11, 0xD0, 0x39, 0xCC, 0x30, 0x53, 0xBF, 0x9B, 0xBD, 0x1B, 0x3B, 0x63, 0x42, 0x1C, 0xF7, 0x7A, 0x66, 0x31, 0x00, + 0xC8, 0x19, 0x7F, 0xA5, 0x32, 0x33, 0x21, 0x20, 0xB0, 0x78, 0x17, 0x5E, 0xD5, 0x5B, 0x2E, 0xB5, 0x84, 0x38, 0xB9, 0x70, + 0xC9, 0xFB, 0x2F, 0x75, 0xE7, 0x05, 0x68, 0x66, 0xC6, 0x5E, 0x1D, 0xF2, 0x94, 0x99, 0xCA, 0x6F, 0x7E, 0x1F, 0x0D, 0x30, + 0xD4, 0xDA, 0x20, 0xA7, 0xDA, 0x91, 0x38, 0xF3, 0xA1, 0xB2, 0x1E, 0x56, 0xB3, 0x88, 0x67, 0xD1, 0x2F, 0x99, 0x2C, 0xC5, + 0x9D, 0x82, 0x1C, 0x40, 0x2F, 0xBB, 0x1F, 0xB5, 0x0E, 0x45, 0x70, 0x00, 0xE4, 0x9C, 0x34, 0x17, 0xD0, 0xB6, 0x60, 0x21, + 0x21, 0x3E, 0x3F, 0x25, 0xBB, 0xB8, 0x04, 0x70, 0x62, 0x1F, 0x78, 0x74, 0xA3, 0x1E, 0xA5, 0x32, 0x3E, 0x90, 0x9B, 0xC1, + 0x5F, 0xA7, 0x55, 0x81, 0xA7, 0xD2, 0xAF, 0xD5, 0xD2, 0x2D, 0x48, 0x51, 0xAE, 0x28, 0x5D, 0xA0, 0xB9, 0xE8, 0x27, 0xF6, + 0x44, 0xD1, 0xC5, 0x0C, 0x0A, 0x99, 0xE7, 0xF8, 0xAE, 0x4C, 0xE2, 0x90, 0x37, 0x4C, 0x56, 0xB4, 0x43, 0xD5, 0x49, 0xDD, + 0x48, 0x7B, 0x96, 0x65, 0x2B, 0xF2, 0x96, 0x61, 0xB2, 0x14, 0x67, 0xA2, 0x0E, 0x99, 0x5F, 0xCC, 0xFF, 0x2D, 0xAB, 0x69, + 0x9F, 0x88, 0x6F, 0x0D, 0x68, 0xB2, 0x51, 0x6A, 0xED, 0x68, 0xD7, 0x51, 0xFA, 0x11, 0x91, 0x19, 0x79, 0xF3, 0x67, 0x00, + 0xDE, 0xBF, 0xC7, 0x39, 0x39, 0xF3, 0x92, 0x5D, 0x7F, 0x2F, 0xA6, 0x3B, 0xB6, 0x9A, 0x52, 0xAC, 0x30, 0xC3, 0xFE, 0x26, + 0xCD, 0xDA, 0x91, 0x2E, 0x3E, 0x27, 0xEE, 0x38, 0xAD, 0x95, 0xD5, 0x7B, 0xC8, 0x36, 0x06, 0xDD, 0x0C, 0x22, 0x5D, 0x16, + 0xDE, 0x42, 0x6B, 0xCD, 0x0F, 0x16, 0xD8, 0xFE, 0x1F, 0x41, 0xFF, 0x8B, 0x8D, 0x25, 0xF3, 0xED, 0xAE, 0xF8, 0xBB, 0xA9, + 0x0C, 0x99, 0xA4, 0xE2, 0x54, 0xFB, 0x07, 0x79, 0xCD, 0xAA, 0x40, 0x38, 0x25, 0xF5, 0x80, 0xFC, 0x04, 0x8B, 0x48, 0x43, + 0xF1, 0xD6, 0x4B, 0x03, 0x46, 0xF8, 0x07, 0xD7, 0xD4, 0xCD, 0x32, 0xA0, 0xD5, 0xAE, 0x48, 0xE5, 0xCC, 0xAA, 0x00, 0x1F, + 0x3D, 0x14, 0x08, 0x56, 0x12, 0xBE, 0x5F, 0x3D, 0x6B, 0x46, 0xFE, 0x77, 0x46, 0xBD, 0x3F, 0xDD, 0x2C, 0xB9, 0xC3, 0x99, + 0x3B, 0x06, 0xAD, 0x73, 0xEA, 0x92, 0x42, 0x28, 0x7A, 0x67, 0x8A, 0x0A, 0xB9, 0xD6, 0xE1, 0x57, 0x92, 0xDC, 0x9F, 0x20, + 0x80, 0xD0, 0x53, 0x36, 0xB1, 0x8F, 0x36, 0xB8, 0xAB, 0x17, 0x83, 0x9E, 0x54, 0xCF, 0x48, 0xA9, 0x83, 0x9E, 0xE0, 0xAF, + 0x60, 0x33, 0x98, 0x81, 0x28, 0x48, 0xA6, 0x72, 0xBA, 0x76, 0xE0, 0x23, 0x3D, 0x5D, 0x92, 0x4D, 0x2D, 0x7D, 0x37, 0xAC, + 0xC1, 0x0C, 0xBC, 0x16, 0xE8, 0x97, 0x49, 0xD5, 0xE4, 0x9E, 0x36, 0xD1, 0x9B, 0x3F, 0xA2, 0x56, 0x62, 0x38, 0x19, 0x84, + 0x55, 0xC7, 0x02, 0xFB, 0x70, 0x83, 0xD8, 0x13, 0x1E, 0x83, 0x01, 0xAC, 0x2F, 0xD1, 0xEA, 0x08, 0x2E, 0xC7, 0x30, 0xA8, + 0xDD, 0xA6, 0x31, 0xAC, 0x11, 0x86, 0xCA, 0x94, 0x81, 0x2A, 0xA5, 0xDE, 0x7D, 0x32, 0xD9, 0x35, 0x63, 0x4E, 0x63, 0x72, + 0xF8, 0x4A, 0xD3, 0xD8, 0x56, 0xEE, 0x37, 0x57, 0x7B, 0x0F, 0xAF, 0x7B, 0x04, 0xAD, 0x1A, 0xE4, 0x99, 0xB0, 0xCE, 0xC0, + 0xE8, 0xD0, 0x2D, 0xD0, 0xF8, 0x97, 0x9B, 0xDB, 0x35, 0x05, 0x9D, 0x44, 0x69, 0x2C, 0xFB, 0x16, 0xDF, 0x11, 0x85, 0x1F, + 0x20, 0x67, 0xFC, 0xA1, 0x2A, 0xA9, 0x0A, 0x15, 0x65, 0xD0, 0x23, 0x46, 0x2D, 0xB8, 0xAF, 0x58, 0x8F, 0xFC, 0x83, 0xB8, + 0x54, 0x95, 0x1C, 0x4D, 0xED, 0x22, 0x87, 0xFA, 0x6B, 0x71, 0xA4, 0x7C, 0xA8, 0x6A, 0xDA, 0x18, 0x43, 0x7E, 0x40, 0x3D, + 0x8B, 0x29, 0x8D, 0x07, 0xE5, 0xE9, 0x7C, 0x44, 0xB0, 0x9E, 0x3E, 0x30, 0xDF, 0xED, 0x11, 0x7B, 0x36, 0x9A, 0xEE, 0x60, + 0x64, 0x75, 0xAC, 0x5B, 0x99, 0x0A, 0xD8, 0x35, 0x62, 0x0E, 0xF2, 0xAC, 0x52, 0x11, 0xF0, 0x22, 0x2D, 0x59, 0x31, 0xCB, + 0xEC, 0x2D, 0x5B, 0x20, 0xA0, 0x71, 0x3A, 0xF7, 0xD8, 0xA3, 0xDA, 0x49, 0x80, 0x1F, 0x41, 0x5B, 0x0D, 0x33, 0x73, 0x31, + 0x40, 0xB2, 0xDB, 0xB8, 0x5A, 0x42, 0x9D, 0x92, 0xBE, 0x48, 0x26, 0xFB, 0xD5, 0xDE, 0x22, 0x2D, 0x03, 0xA8, 0x54, 0xDA, + 0x50, 0xC0, 0xDB, 0x85, 0xBB, 0xA9, 0x9A, 0x9B, 0x93, 0xD5, 0x67, 0xC3, 0x17, 0x46, 0x1A, 0xDA, 0x01, 0x41, 0x9C, 0x01, + 0x08, 0xC8, 0xD8, 0x45, 0x0F, 0xDA, 0xF8, 0x9A, 0x73, 0x4B, 0x93, 0xDF, 0xD4, 0x82, 0x7A, 0xBB, 0x17, 0xCA, 0x85, 0x16, + 0xD0, 0xFD, 0x6B, 0xFC, 0x9D, 0x55, 0x98, 0xA7, 0x58, 0xA4, 0x25, 0xD6, 0x1A, 0x58, 0x4A, 0x87, 0x9B, 0xC6, 0x52, 0x77, + 0xC1, 0x1B, 0xBC, 0xBD, 0x4C, 0x97, 0x04, 0xCE, 0x28, 0x17, 0xC6, 0x9D, 0xD9, 0x87, 0x57, 0xE8, 0x5E, 0xFC, 0x99, 0x6F, + 0x41, 0x9B, 0x1A, 0x5E, 0x7B, 0x14, 0x0E, 0xCF, 0x03, 0xD8, 0x55, 0x0B, 0x5F, 0x58, 0x14, 0x7D, 0xB0, 0x99, 0x4E, 0x67, + 0x4D, 0xDB, 0xA9, 0x90, 0xD6, 0xA5, 0xD0, 0xF9, 0x15, 0x78, 0x1E, 0x9F, 0x36, 0x7A, 0x4D, 0xB9, 0x4E, 0x16, 0xA7, 0x42, + 0x10, 0xE8, 0x98, 0x89, 0x5D, 0xBA, 0xB8, 0x75, 0xB7, 0x91, 0x50, 0x45, 0x83, 0x2F, 0xA8, 0xD5, 0x19, 0x5C, 0xFC, 0xDC, + 0x4C, 0x84, 0x9D, 0x4F, 0x0D, 0x37, 0x7E, 0xDF, 0x4F, 0x11, 0x98, 0xC0, 0xFB, 0x33, 0x98, 0xA9, 0xAC, 0xB5, 0x90, 0x5E, + 0x84, 0x93, 0x0F, 0xDE, 0xA2, 0x0D, 0x81, 0xD5, 0x11, 0xEF, 0xB0, 0x5D, 0x84, 0xF2, 0x9C, 0x59, 0xD0, 0x01, 0xE8, 0x8B, + 0x1C, 0x59, 0x4F, 0xBA, 0xC8, 0x41, 0x37, 0xF1, 0x78, 0x0D, 0xD8, 0x74, 0xEB, 0xE2, 0x04, 0x26, 0x2B, 0xE8, 0x0D, 0x79, + 0x81, 0xBD, 0x97, 0x55, 0xCF, 0x30, 0x0F, 0xE7, 0x65, 0x3B, 0xAF, 0x3A, 0xE0, 0x6E, 0xEC, 0x54, 0xAE, 0x7A, 0x47, 0x3B, + 0x6F, 0x53, 0x76, 0xD0, 0xFF, 0xD3, 0x68, 0x50, 0x61, 0x6D, 0x1A, 0x03, 0x56, 0x36, 0x57, 0x2A, 0x64, 0x25, 0xF7, 0x2E, + 0x36, 0x08, 0x69, 0xDB, 0x5E, 0x8E, 0xB9, 0xDA, 0x55, 0xB8, 0xE8, 0xC6, 0x5F, 0x28, 0xEC, 0x31, 0x75, 0x3B, 0x48, 0x99, + 0xB5, 0x86, 0x46, 0x97, 0x74, 0xED, 0xB2, 0x8A, 0xDE, 0x78, 0x2E, 0xA4, 0x95, 0xAD, 0x40, 0x0D, 0xC6, 0xC8, 0xFC, 0x08, + 0x35, 0xC5, 0x38, 0xCB, 0x23, 0xC4, 0x99, 0x45, 0x61, 0xE4, 0xF1, 0xA8, 0x33, 0xCA, 0x31, 0x96, 0x2C, 0x67, 0x46, 0x09, + 0x72, 0x1B, 0x2D, 0x35, 0xD4, 0x50, 0xCA, 0xDB, 0x3B, 0xF4, 0x87, 0x4B, 0x3E, 0x36, 0x31, 0xF9, 0x7C, 0x2C, 0x31, 0x0E, + 0xF5, 0xF9, 0xC9, 0x22, 0xE9, 0x37, 0xB2, 0x0A, 0x4C, 0xA5, 0xFE, 0x45, 0xF8, 0x75, 0x78, 0x31, 0x69, 0xFC, 0x32, 0xD6, + 0x9F, 0xF6, 0x02, 0x8E, 0x55, 0xA6, 0xEE, 0xAF, 0x44, 0x10, 0xBB, 0x26, 0x7D, 0x05, 0x09, 0xD1, 0x37, 0xB1, 0xA1, 0x2F, + 0x7B, 0xF8, 0x94, 0x2B, 0x72, 0x74, 0xBC, 0x24, 0xED, 0x3E, 0x42, 0x7C, 0xCB, 0xAB, 0x2B, 0x4C, 0x8E, 0x4A, 0xB9, 0xD9, + 0x71, 0x85, 0x9A, 0x2C, 0x5D, 0x52, 0xB2, 0x9B, 0xDF, 0x91, 0xEA, 0x42, 0xBF, 0x43, 0xAA, 0xAE, 0x7E, 0x56, 0xD2, 0x8E, + 0xF0, 0xA2, 0x03, 0xB8, 0xEE, 0x32, 0xE9, 0x45, 0x7D, 0x78, 0xD6, 0x62, 0x3A, 0x9F, 0x9B, 0xCD, 0x97, 0xCA, 0xA7, 0xF8, + 0x6F, 0xF1, 0x21, 0x40, 0xA6, 0xBB, 0xDD, 0xA6, 0xAE, 0xD4, 0xD3, 0x0F, 0xDF, 0xA0, 0x13, 0x19, 0x38, 0x8D, 0x6C, 0x82, + 0xD7, 0xAD, 0x95, 0x26, 0x5F, 0x99, 0xFF, 0x86, 0x4F, 0xF0, 0x4F, 0xAA, 0xC1, 0x6F, 0x60, 0x58, 0x50, 0x5B, 0x51, 0xE0, + 0x4D, 0xB2, 0x92, 0x52, 0xEB, 0x6C, 0x77, 0x8F, 0x8E, 0x95, 0xBC, 0x5E, 0xBF, 0xBC, 0x7E, 0xA0, 0xA2, 0xB8, 0x65, 0x83, + 0x84, 0xDE, 0xF5, 0x52, 0x39, 0x59, 0xF9, 0xA5, 0x9F, 0xB8, 0xD2, 0xE0, 0x87, 0x10, 0xB7, 0x95, 0x06, 0x1E, 0x67, 0xAC, + 0xE3, 0x78, 0x2D, 0xA4, 0xEA, 0xA2, 0xBF, 0xF5, 0x59, 0x9D, 0xDA, 0x73, 0x4A, 0x1B, 0x78, 0xE5, 0xC7, 0x5C, 0x4C, 0x74, + 0x7E, 0xFE, 0xAC, 0x3A, 0xF0, 0xD4, 0x92, 0xD1, 0x96, 0x2A, 0x75, 0x80, 0xC4, 0xD3, 0x54, 0xCF, 0xF2, 0x64, 0x52, 0xEE, + 0x56, 0xC7, 0x45, 0xB4, 0xD0, 0x65, 0x74, 0x01, 0x64, 0xDE, 0x71, 0x63, 0x9D, 0xB1, 0xCE, 0x63, 0x7B, 0x34, 0x59, 0xB5, + 0x4C, 0x1A, 0x75, 0x54, 0x44, 0xD1, 0x15, 0xDB, 0x70, 0xF4, 0x47, 0x74, 0x2A, 0x83, 0xEA, 0xFE, 0xBC, 0xAE, 0xD6, 0x56, + 0xB0, 0x23, 0x90, 0x76, 0x40, 0xFE, 0x08, 0x3E, 0x24, 0x3D, 0x96, 0x61, 0xD4, 0xEA, 0x3A, 0x41, 0x8C, 0x7A, 0x64, 0x66, + 0xA9, 0xE8, 0x3D, 0x0F, 0xC7, 0xEC, 0x37, 0xFC, 0x82, 0x1B, 0x7C, 0xD8, 0xCE, 0x5B, 0x14, 0x56, 0x5D, 0xB8, 0xFB, 0xDF, + 0xD6, 0x92, 0x7B, 0x61, 0x54, 0x18, 0xA8, 0x41, 0xEB, 0x71, 0x18, 0x96, 0x8A, 0x5D, 0x45, 0x7E, 0xF6, 0x7F, 0xB0, 0xF3, + 0xD5, 0xF8, 0x7E, 0xA7, 0x0D, 0x9C, 0xCC, 0x06, 0xAA, 0x33, 0x54, 0x29, 0x19, 0x32, 0x4A, 0xBC, 0xC8, 0xD8, 0x3C, 0x18, + 0xED, 0x95, 0xA7, 0x01, 0x7B, 0x76, 0xC6, 0x63, 0x32, 0xAD, 0xD9, 0x7F, 0xC8, 0x11, 0x0F, 0x69, 0xEF, 0x86, 0x37, 0xA3, + 0x15, 0xBC, 0xBA, 0x9C, 0x46, 0xEC, 0xD7, 0xE6, 0x44, 0x62, 0xE8, 0x19, 0x6D, 0x97, 0xCD, 0xFF, 0xFF, 0xFF, 0x3A, 0xF3, + 0x78, 0xAF, 0x27, 0xFD, 0x43, 0x3B, 0x08, 0xD3, 0x32, 0x02, 0x90, 0x24, 0x50, 0x60, 0x99, 0xEC, 0xCB, 0xFA, 0x30, 0xFB, + 0x6E, 0x28, 0xC1, 0x07, 0x7E, 0x48, 0x98, 0x34, 0x51, 0x61, 0x12, 0xF2, 0xBC, 0xAD, 0xBF, 0x63, 0x27, 0x32, 0x48, 0xAE, + 0xE1, 0x00, 0x91, 0x25, 0xD0, 0x62, 0x11, 0x2A, 0xD2, 0x96, 0x52, 0x22, 0x95, 0x09, 0x3F, 0x85, 0xB3, 0x01, 0x99, 0x35, + 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, 0x52, 0x64, 0x48, 0x50, + 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, 0x82, 0x06, 0xC1, 0x45, + 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, 0x93, 0x27, 0x59, 0x71, + 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0xCF, 0x8C, 0x43, 0x42, 0xFF, 0x4B, 0xED, 0xA1, 0x4B, 0xA7, 0x69, 0x88, 0x92, 0x2C, + 0x58, 0x68, 0x2D, 0x35, 0xD9, 0x58, 0x8B, 0x5B, 0xF8, 0xDF, 0x1E, 0xDA, 0x6D, 0xFC, 0x9A, 0x3C, 0x59, 0x69, 0xA4, 0x30, + 0x5C, 0x9B, 0xA3, 0x9F, 0x18, 0x20, 0x73, 0x37, 0xC5, 0xC1, 0x93, 0x2D, 0xD8, 0x6A, 0xB0, 0x5B, 0x28, 0xF6, 0x74, 0x6F, + 0x4F, 0xF4, 0x4D, 0x03, 0xAB, 0xB0, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, 0x1A, 0x2C, 0x52, 0x68, + 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, 0x4B, 0x4D, 0xDA, 0x7C, + 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, 0xDA, 0x6E, 0x4B, 0x59, + 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x5E, 0xAE, 0x83, 0x75, 0x84, 0x84, + 0x30, 0x30, 0x4A, 0xDB, 0x53, 0x42, 0x94, 0xA4, 0x70, 0x70, 0xB7, 0x72, 0x8D, 0xEC, 0x8C, 0x94, 0x31, 0x31, 0x64, 0x32, + 0xB5, 0x72, 0x9C, 0xB4, 0x71, 0x71, 0x5F, 0x50, 0x03, 0x77, 0x85, 0x85, 0xB0, 0x32, 0xAD, 0x23, 0x34, 0xE9, 0x95, 0xA5, + 0xF0, 0x72, 0x75, 0xB6, 0x54, 0x1C, 0x8D, 0x95, 0xB1, 0x33, 0x25, 0x33, 0x35, 0x07, 0x9D, 0xB5, 0xF1, 0x73, 0x44, 0xC0, + 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, 0x23, 0x15, 0xCC, 0xD4, + 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, 0xB2, 0x36, 0x55, 0xE1, + 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, 0xE3, 0x57, 0xDD, 0xF5, + 0xF3, 0x77, 0xB2, 0xF7, 0x8B, 0xC3, 0x86, 0x8C, 0x38, 0x38, 0x6E, 0x2A, 0xBC, 0x30, 0x96, 0xAC, 0x78, 0x78, 0x8C, 0x1C, + 0x7E, 0xAC, 0x8E, 0x9C, 0x39, 0x39, 0x24, 0x47, 0x6F, 0xA3, 0x9E, 0xBC, 0x79, 0x79, 0x27, 0x74, 0xC0, 0xA1, 0x87, 0x8D, + 0xB8, 0x3A, 0x2F, 0x1B, 0xE0, 0xFA, 0x97, 0xAD, 0xF8, 0x7A, 0xB0, 0x6B, 0xE9, 0x1D, 0x8F, 0x9D, 0xB9, 0x3B, 0x88, 0x9D, + 0x39, 0xCA, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, 0x6A, 0x5C, 0xD6, 0xEC, + 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, 0x7B, 0x7D, 0x47, 0xC9, + 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, 0xAB, 0x1F, 0xCF, 0xDD, + 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x08, 0x60, 0xF0, 0xFA, 0x30, 0x22, 0x14, 0xA0, 0x34, 0xA6, + 0x4C, 0xD8, 0xB0, 0x26, 0x54, 0xE0, 0x01, 0x60, 0xBE, 0x9E, 0xA8, 0x16, 0x15, 0xA1, 0x06, 0xEA, 0x25, 0xE1, 0xB8, 0x36, + 0x55, 0xE1, 0x96, 0xDB, 0x82, 0x29, 0xA1, 0x07, 0x94, 0xA2, 0xEA, 0x14, 0xBB, 0xCB, 0xB1, 0x27, 0xD4, 0xE2, 0x41, 0x71, + 0x7A, 0x8D, 0xA9, 0x17, 0x95, 0xA3, 0x46, 0x41, 0xAF, 0xB9, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, 0x06, 0x84, 0xE0, 0x46, + 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, 0x17, 0xA5, 0x78, 0x72, + 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, 0xC6, 0xC6, 0xF1, 0x67, + 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, 0xD7, 0xE7, 0x1A, 0xF4, + 0x0A, 0xE8, 0xA2, 0x0E, 0x1C, 0xA8, 0x49, 0xAE, 0x07, 0x82, 0xB2, 0x2E, 0x5C, 0xE8, 0x39, 0x01, 0x31, 0x1D, 0xAA, 0x1E, + 0x1D, 0xA9, 0x21, 0x3F, 0xAC, 0xCF, 0xBA, 0x3E, 0x5D, 0xE9, 0x39, 0x14, 0xF4, 0x5E, 0xA3, 0x0F, 0x9C, 0xAA, 0x8C, 0x77, + 0xE8, 0x61, 0xB3, 0x2F, 0xDC, 0xEA, 0xBA, 0x99, 0x0D, 0x2A, 0xAB, 0x1F, 0x9D, 0xAB, 0x98, 0x7E, 0x6E, 0x89, 0xBB, 0x3F, + 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, 0x5E, 0xEC, 0x6A, 0x5A, + 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, 0x8E, 0x8E, 0xE3, 0x4F, + 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, 0x9F, 0xAF, 0x7B, 0x7B, + 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x04, 0xAF, 0x87, 0xD1, 0xA4, 0x86, 0x34, 0xB0, 0x13, 0x9B, 0x62, 0x7A, 0xB4, 0xA6, + 0x74, 0xF0, 0xEC, 0x63, 0xDF, 0x10, 0xAC, 0x96, 0x35, 0xB1, 0x6C, 0xA9, 0x19, 0x45, 0xBC, 0xB6, 0x75, 0xF1, 0x86, 0x33, + 0x78, 0x31, 0xA5, 0x87, 0xB4, 0xB2, 0xFD, 0xBC, 0xCE, 0x06, 0xB5, 0xA7, 0xF4, 0xF2, 0x09, 0x6C, 0x44, 0x40, 0xAD, 0x97, + 0xB5, 0xB3, 0xAE, 0x8D, 0x95, 0x26, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, 0x36, 0xB4, 0x74, 0xE2, + 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, 0x67, 0xD5, 0xFC, 0xF6, + 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, 0xF6, 0xF6, 0x6D, 0xD3, + 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0xDD, 0xF5, 0x1F, 0x78, 0xA6, 0x8E, + 0x3C, 0xB8, 0x21, 0x2E, 0x07, 0xC4, 0xB6, 0xAE, 0x7C, 0xF8, 0xEA, 0x50, 0x96, 0x36, 0xAE, 0x9E, 0x3D, 0xB9, 0x6A, 0x84, + 0x4F, 0x9B, 0xBE, 0xBE, 0x7D, 0xF9, 0x8C, 0xCC, 0xA2, 0x46, 0xA7, 0x8F, 0xBC, 0xBA, 0x0D, 0x40, 0x5F, 0x2F, 0xB7, 0xAF, + 0xFC, 0xFA, 0xFD, 0x77, 0x41, 0xE0, 0xAF, 0x9F, 0xBD, 0xBB, 0xBB, 0xCB, 0xC9, 0x40, 0xBF, 0xBF, 0xFD, 0xFB, 0x66, 0xCA, + 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, 0x2F, 0x9D, 0xEE, 0xDE, + 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, 0xBE, 0xBE, 0x77, 0xEB, + 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, 0xEF, 0xDF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x10, 0x20, 0x10, 0x20, 0x40, 0x40, 0x90, 0x24, 0x50, 0x60, 0x08, 0x10, + 0x01, 0x01, 0x88, 0x14, 0x11, 0x21, 0x18, 0x30, 0x41, 0x41, 0x98, 0x34, 0x51, 0x61, 0x01, 0x01, 0x80, 0x02, 0x81, 0x05, + 0x90, 0x22, 0x11, 0x21, 0xC0, 0x42, 0x91, 0x25, 0xD0, 0x62, 0x09, 0x11, 0x81, 0x03, 0x89, 0x15, 0x91, 0x23, 0x19, 0x31, + 0xC1, 0x43, 0x99, 0x35, 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, + 0x52, 0x64, 0x48, 0x50, 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, + 0x82, 0x06, 0xC1, 0x45, 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, + 0x93, 0x27, 0x59, 0x71, 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0x02, 0x08, 0x08, 0x08, 0x82, 0x0C, 0x18, 0x28, 0x12, 0x28, + 0x48, 0x48, 0x92, 0x2C, 0x58, 0x68, 0x0A, 0x18, 0x09, 0x09, 0x8A, 0x1C, 0x19, 0x29, 0x1A, 0x38, 0x49, 0x49, 0x9A, 0x3C, + 0x59, 0x69, 0x03, 0x09, 0x88, 0x0A, 0x83, 0x0D, 0x98, 0x2A, 0x13, 0x29, 0xC8, 0x4A, 0x93, 0x2D, 0xD8, 0x6A, 0x0B, 0x19, + 0x89, 0x0B, 0x8B, 0x1D, 0x99, 0x2B, 0x1B, 0x39, 0xC9, 0x4B, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, + 0x1A, 0x2C, 0x52, 0x68, 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, + 0x4B, 0x4D, 0xDA, 0x7C, 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, + 0xDA, 0x6E, 0x4B, 0x59, 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, + 0x20, 0x10, 0x84, 0x84, 0x30, 0x30, 0x14, 0xA0, 0x60, 0x50, 0x94, 0xA4, 0x70, 0x70, 0x0C, 0x90, 0x21, 0x11, 0x8C, 0x94, + 0x31, 0x31, 0x1C, 0xB0, 0x61, 0x51, 0x9C, 0xB4, 0x71, 0x71, 0x05, 0x81, 0xA0, 0x12, 0x85, 0x85, 0xB0, 0x32, 0x15, 0xA1, + 0xE0, 0x52, 0x95, 0xA5, 0xF0, 0x72, 0x0D, 0x91, 0xA1, 0x13, 0x8D, 0x95, 0xB1, 0x33, 0x1D, 0xB1, 0xE1, 0x53, 0x9D, 0xB5, + 0xF1, 0x73, 0x44, 0xC0, 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, + 0x23, 0x15, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, + 0xB2, 0x36, 0x55, 0xE1, 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, + 0xE3, 0x57, 0xDD, 0xF5, 0xF3, 0x77, 0x06, 0x88, 0x28, 0x18, 0x86, 0x8C, 0x38, 0x38, 0x16, 0xA8, 0x68, 0x58, 0x96, 0xAC, + 0x78, 0x78, 0x0E, 0x98, 0x29, 0x19, 0x8E, 0x9C, 0x39, 0x39, 0x1E, 0xB8, 0x69, 0x59, 0x9E, 0xBC, 0x79, 0x79, 0x07, 0x89, + 0xA8, 0x1A, 0x87, 0x8D, 0xB8, 0x3A, 0x17, 0xA9, 0xE8, 0x5A, 0x97, 0xAD, 0xF8, 0x7A, 0x0F, 0x99, 0xA9, 0x1B, 0x8F, 0x9D, + 0xB9, 0x3B, 0x1F, 0xB9, 0xE9, 0x5B, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, + 0x6A, 0x5C, 0xD6, 0xEC, 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, + 0x7B, 0x7D, 0x47, 0xC9, 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, + 0xAB, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x20, 0x02, 0x04, 0x80, 0xA0, 0x06, + 0x14, 0xA0, 0x30, 0x22, 0x44, 0xC0, 0xB0, 0x26, 0x54, 0xE0, 0x28, 0x12, 0x05, 0x81, 0xA8, 0x16, 0x15, 0xA1, 0x38, 0x32, + 0x45, 0xC1, 0xB8, 0x36, 0x55, 0xE1, 0x21, 0x03, 0x84, 0x82, 0xA1, 0x07, 0x94, 0xA2, 0x31, 0x23, 0xC4, 0xC2, 0xB1, 0x27, + 0xD4, 0xE2, 0x29, 0x13, 0x85, 0x83, 0xA9, 0x17, 0x95, 0xA3, 0x39, 0x33, 0xC5, 0xC3, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, + 0x06, 0x84, 0xE0, 0x46, 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, + 0x17, 0xA5, 0x78, 0x72, 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, + 0xC6, 0xC6, 0xF1, 0x67, 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, + 0xD7, 0xE7, 0x22, 0x0A, 0x0C, 0x88, 0xA2, 0x0E, 0x1C, 0xA8, 0x32, 0x2A, 0x4C, 0xC8, 0xB2, 0x2E, 0x5C, 0xE8, 0x2A, 0x1A, + 0x0D, 0x89, 0xAA, 0x1E, 0x1D, 0xA9, 0x3A, 0x3A, 0x4D, 0xC9, 0xBA, 0x3E, 0x5D, 0xE9, 0x23, 0x0B, 0x8C, 0x8A, 0xA3, 0x0F, + 0x9C, 0xAA, 0x33, 0x2B, 0xCC, 0xCA, 0xB3, 0x2F, 0xDC, 0xEA, 0x2B, 0x1B, 0x8D, 0x8B, 0xAB, 0x1F, 0x9D, 0xAB, 0x3B, 0x3B, + 0xCD, 0xCB, 0xBB, 0x3F, 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, + 0x5E, 0xEC, 0x6A, 0x5A, 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, + 0x8E, 0x8E, 0xE3, 0x4F, 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, + 0x9F, 0xAF, 0x7B, 0x7B, 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x24, 0x82, 0x24, 0x90, 0xA4, 0x86, 0x34, 0xB0, 0x34, 0xA2, + 0x64, 0xD0, 0xB4, 0xA6, 0x74, 0xF0, 0x2C, 0x92, 0x25, 0x91, 0xAC, 0x96, 0x35, 0xB1, 0x3C, 0xB2, 0x65, 0xD1, 0xBC, 0xB6, + 0x75, 0xF1, 0x25, 0x83, 0xA4, 0x92, 0xA5, 0x87, 0xB4, 0xB2, 0x35, 0xA3, 0xE4, 0xD2, 0xB5, 0xA7, 0xF4, 0xF2, 0x2D, 0x93, + 0xA5, 0x93, 0xAD, 0x97, 0xB5, 0xB3, 0x3D, 0xB3, 0xE5, 0xD3, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, + 0x36, 0xB4, 0x74, 0xE2, 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, + 0x67, 0xD5, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, + 0xF6, 0xF6, 0x6D, 0xD3, 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x8A, + 0x2C, 0x98, 0xA6, 0x8E, 0x3C, 0xB8, 0x36, 0xAA, 0x6C, 0xD8, 0xB6, 0xAE, 0x7C, 0xF8, 0x2E, 0x9A, 0x2D, 0x99, 0xAE, 0x9E, + 0x3D, 0xB9, 0x3E, 0xBA, 0x6D, 0xD9, 0xBE, 0xBE, 0x7D, 0xF9, 0x27, 0x8B, 0xAC, 0x9A, 0xA7, 0x8F, 0xBC, 0xBA, 0x37, 0xAB, + 0xEC, 0xDA, 0xB7, 0xAF, 0xFC, 0xFA, 0x2F, 0x9B, 0xAD, 0x9B, 0xAF, 0x9F, 0xBD, 0xBB, 0x3F, 0xBB, 0xED, 0xDB, 0xBF, 0xBF, + 0xFD, 0xFB, 0x66, 0xCA, 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, + 0x2F, 0x9D, 0xEE, 0xDE, 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, + 0xBE, 0xBE, 0x77, 0xEB, 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, + 0xEF, 0xDF, 0xFF, 0xFF, 0x51, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x07, 0xFF, 0x80, 0x00, 0x55, 0x40, 0xA9, 0x57, 0x94, 0x3C, 0x0F, 0x02, 0x2B, 0xFA, 0xCA, 0x0A, 0xF3, 0x2E, 0x88, 0x98, + 0x01, 0x41, 0x67, 0x7F, 0xC6, 0xCC, 0x46, 0x33, 0xBE, 0x01, 0x60, 0xB0, 0x58, 0x10, 0x01, 0x80, 0x05, 0x42, 0x28, 0x56, + 0x1C, 0x7E, 0x0A, 0xD0, 0x58, 0x42, 0x83, 0x57, 0xE3, 0x92, 0x09, 0x95, 0x22, 0x66, 0xA9, 0xAB, 0x14, 0xA2, 0x19, 0x7A, + 0xC5, 0x63, 0x31, 0x0A, 0xD7, 0xD8, 0xE8, 0xE2, 0xDD, 0x5B, 0xFE, 0xE0, 0x73, 0x04, 0x80, 0x23, 0xB9, 0xE9, 0x10, 0xE1, + 0x5D, 0x65, 0xE8, 0x43, 0x2D, 0x61, 0x96, 0xF0, 0x1B, 0x88, 0x74, 0x97, 0x45, 0xD6, 0xAA, 0x70, 0x4B, 0x0B, 0xE9, 0xF2, + 0x4A, 0x85, 0x99, 0x41, 0x1B, 0x99, 0x18, 0x41, 0x67, 0x06, 0xE9, 0x4D, 0x3B, 0xF6, 0x92, 0x53, 0xFC, 0x87, 0x05, 0xD0, + 0x95, 0xA5, 0x1F, 0x6E, 0xE5, 0x6B, 0x19, 0xE5, 0x62, 0x6F, 0x92, 0xAC, 0x2E, 0x48, 0xDD, 0x44, 0x67, 0x08, 0x91, 0x5A, + 0xC6, 0x2D, 0xF7, 0xAE, 0x51, 0x05, 0x0A, 0x18, 0x09, 0x49, 0x86, 0x62, 0xB8, 0xA3, 0x12, 0x3D, 0xAE, 0x4D, 0xFA, 0xFC, + 0x95, 0xE2, 0xDA, 0x97, 0xAE, 0x49, 0x43, 0x75, 0x2D, 0x2C, 0x6A, 0x5B, 0x46, 0x2F, 0xAB, 0x7D, 0xDC, 0x65, 0xC9, 0x49, + 0x89, 0x0B, 0x70, 0xFF, 0x35, 0xA0, 0x1F, 0xDF, 0xD9, 0xB5, 0x99, 0xDF, 0x5B, 0x61, 0xAA, 0xEA, 0xAE, 0x8B, 0x4A, 0x3F, + 0x4E, 0x4E, 0x2D, 0x1B, 0x59, 0x4D, 0x56, 0x9D, 0x7C, 0x4C, 0xE2, 0xFA, 0xD4, 0x82, 0x88, 0x17, 0x78, 0x29, 0x64, 0x75, + 0x23, 0xDD, 0x5B, 0x6E, 0x33, 0x5D, 0x97, 0x6F, 0x64, 0x6D, 0x07, 0x9D, 0xE4, 0x6C, 0xEF, 0x6D, 0x43, 0x21, 0xED, 0x71, + 0xB1, 0x61, 0x8B, 0x59, 0xDF, 0xD1, 0xAA, 0x9D, 0x9F, 0x03, 0xA4, 0x0B, 0xE5, 0x90, 0x24, 0x0F, 0xF5, 0xB0, 0x04, 0x80, + 0x78, 0xF8, 0xDE, 0x80, 0x93, 0x36, 0x91, 0xA1, 0x64, 0xD0, 0x21, 0x62, 0x80, 0x76, 0xDE, 0xB0, 0x26, 0xE9, 0xEC, 0xD0, + 0x4D, 0x3E, 0x3C, 0x32, 0x5E, 0xB5, 0xE4, 0x36, 0x78, 0xB1, 0x4F, 0x28, 0x82, 0x11, 0x8D, 0xC9, 0xF2, 0x3D, 0x14, 0x21, + 0xC0, 0x5A, 0x99, 0xB0, 0x93, 0xB2, 0x02, 0x1D, 0x24, 0xE6, 0xED, 0xD1, 0xC5, 0xBE, 0x27, 0x4D, 0xE9, 0x35, 0xE5, 0x37, + 0xF8, 0xD3, 0x97, 0xD0, 0x3A, 0xCE, 0xE8, 0x23, 0x4D, 0x14, 0xD3, 0x10, 0x52, 0xF5, 0xAB, 0x60, 0x3E, 0x47, 0x12, 0xA1, + 0x27, 0x71, 0x1C, 0x3C, 0x1F, 0x78, 0x9C, 0x94, 0x07, 0xA2, 0xF0, 0x13, 0x9A, 0x9F, 0xC1, 0x6C, 0x8F, 0x56, 0x05, 0x09, + 0xAE, 0xC2, 0x01, 0x0B, 0x47, 0xA9, 0xDD, 0xE1, 0x7B, 0xC9, 0x52, 0xD5, 0x29, 0xEE, 0x32, 0xEE, 0xA3, 0x75, 0x59, 0xF5, + 0x63, 0xD5, 0xCD, 0x92, 0xF7, 0x5B, 0xC6, 0x71, 0xB2, 0x1E, 0xFE, 0x61, 0x18, 0x87, 0x0E, 0x12, 0xC4, 0xA7, 0xCC, 0xB1, + 0xDB, 0x7E, 0x8E, 0x12, 0x08, 0xAB, 0xAE, 0x18, 0x31, 0x67, 0x1B, 0x68, 0x37, 0x86, 0x54, 0x34, 0xAD, 0x5A, 0xAC, 0x94, + 0x09, 0x01, 0xDC, 0xCF, 0x47, 0xE1, 0x5D, 0x14, 0xCA, 0xF7, 0x9B, 0xBD, 0x5B, 0x3A, 0x56, 0x66, 0x48, 0xD4, 0xD0, 0xBD, + 0xCA, 0x3B, 0x25, 0x3E, 0x45, 0x52, 0x38, 0x19, 0x29, 0x18, 0x40, 0xE4, 0x05, 0x9C, 0x99, 0xA9, 0xC7, 0x5E, 0x68, 0x49, + 0xE7, 0xFA, 0x2A, 0x68, 0x36, 0x7C, 0x90, 0xCC, 0xDE, 0x46, 0x71, 0x9E, 0x9A, 0x26, 0x49, 0xC9, 0x41, 0x42, 0x1E, 0x78, + 0xF1, 0x13, 0x95, 0x3D, 0xA6, 0xAF, 0x03, 0x1D, 0xC4, 0xC1, 0x54, 0x29, 0xEC, 0xD5, 0x3B, 0x72, 0xF9, 0x9E, 0x4D, 0xC7, + 0x2F, 0x9F, 0xDD, 0xBB, 0x40, 0xCA, 0xE7, 0x06, 0xED, 0x16, 0x38, 0xBD, 0xF7, 0xD4, 0x20, 0x02, 0x04, 0xC0, 0x27, 0xE4, + 0x96, 0x88, 0x4A, 0x20, 0x7C, 0x4D, 0x12, 0xC4, 0xD6, 0xA8, 0x28, 0x12, 0x05, 0xC1, 0xD0, 0x64, 0x97, 0x85, 0xBE, 0x02, + 0x15, 0xDD, 0xBA, 0xD4, 0x53, 0x5A, 0xE7, 0x6C, 0x84, 0x82, 0x1A, 0x65, 0xD5, 0xE2, 0xD5, 0x04, 0x77, 0x48, 0x60, 0x55, + 0x77, 0x87, 0x29, 0x87, 0x85, 0x83, 0x38, 0xF5, 0x17, 0xA9, 0x95, 0x96, 0x04, 0x49, 0x52, 0xCA, 0xEB, 0xA1, 0x5F, 0x8D, + 0xBF, 0xC8, 0x9F, 0x35, 0x3C, 0x2D, 0xDC, 0x1D, 0x84, 0xA4, 0x30, 0xE2, 0xA0, 0xA6, 0xD7, 0xAF, 0x17, 0xE6, 0x97, 0xA5, + 0x31, 0x89, 0x58, 0xB2, 0x4B, 0x6E, 0x99, 0xB6, 0x5B, 0x4E, 0x11, 0x85, 0x2C, 0xC7, 0x65, 0x27, 0x92, 0x8A, 0xCA, 0x13, + 0x46, 0x40, 0xB3, 0x2D, 0xB5, 0xE2, 0x89, 0xE5, 0x00, 0x80, 0x96, 0x24, 0x84, 0xA6, 0xA9, 0x72, 0xC1, 0xCC, 0x29, 0x76, + 0xE4, 0xF6, 0x22, 0x0A, 0x0C, 0xC8, 0x44, 0x6C, 0x7D, 0xFD, 0xB5, 0x7A, 0x6C, 0xD4, 0x25, 0xC0, 0x37, 0xFF, 0x2A, 0x1A, + 0x0D, 0xC9, 0x0E, 0x7C, 0x5C, 0xB9, 0xF0, 0x38, 0x45, 0x01, 0xB2, 0xD8, 0x3E, 0xC9, 0x23, 0x9E, 0x8C, 0x8A, 0xBB, 0xCA, + 0x1E, 0x82, 0x97, 0x6B, 0x8C, 0x45, 0xB0, 0xE9, 0x6C, 0xEC, 0x72, 0xC8, 0x8D, 0x8B, 0xD3, 0x9D, 0x9C, 0xD3, 0xC1, 0xE4, + 0x2C, 0xCF, 0xC3, 0x79, 0x29, 0xA5, 0xCA, 0xE8, 0xD1, 0x63, 0xD8, 0x4A, 0x97, 0xC3, 0xF4, 0xD5, 0x46, 0xAC, 0x4A, 0x95, + 0xBF, 0x13, 0x14, 0xFF, 0xF2, 0xCF, 0x3A, 0x1D, 0xE4, 0x00, 0x04, 0xDB, 0xA6, 0xEE, 0x7D, 0x96, 0x6F, 0xA0, 0xF3, 0x39, + 0x65, 0xCD, 0x23, 0x1A, 0xA7, 0x5A, 0x2D, 0xCF, 0xC6, 0x43, 0x33, 0x7A, 0xE4, 0xE6, 0xAB, 0xF3, 0x83, 0xD3, 0xA2, 0x7F, + 0x3E, 0xEF, 0xD7, 0xE8, 0xD3, 0xC5, 0x04, 0x0C, 0xCB, 0x6D, 0x4D, 0x79, 0xA6, 0xB4, 0x7B, 0x86, 0x43, 0xBC, 0x30, 0xBE, + 0xB9, 0x5A, 0x93, 0x16, 0xF3, 0x57, 0xA3, 0xE0, 0x86, 0xF4, 0x27, 0xF6, 0x25, 0xB7, 0x0D, 0xF2, 0xD7, 0x5C, 0x63, 0x1B, + 0x73, 0xB1, 0x2D, 0x7E, 0x25, 0x49, 0x65, 0xEE, 0x76, 0x4F, 0x1D, 0x92, 0x45, 0xDB, 0x1D, 0x01, 0x71, 0xD5, 0xC2, 0x69, + 0x72, 0xCC, 0xA1, 0xE0, 0xD6, 0x2C, 0xD9, 0x94, 0x52, 0x5E, 0xAC, 0xC5, 0x0A, 0xB1, 0xCA, 0xC5, 0x6E, 0x54, 0xE5, 0x42, + 0x4D, 0xDD, 0xE6, 0x5D, 0x6E, 0x74, 0x24, 0xE7, 0x45, 0xE5, 0x6A, 0x95, 0x9B, 0x55, 0xD4, 0x29, 0xC2, 0xD9, 0x79, 0xE3, + 0x4D, 0x78, 0x66, 0x72, 0x79, 0x0D, 0x47, 0xD7, 0xF5, 0xC3, 0x4E, 0xB8, 0x63, 0xB8, 0x2B, 0x47, 0xEE, 0xD2, 0x4D, 0x18, + 0xF0, 0xCC, 0xFF, 0x7D, 0xE3, 0x52, 0x0A, 0x17, 0xBB, 0x1C, 0x29, 0xB4, 0x25, 0x77, 0xAD, 0x95, 0xF3, 0xDB, 0x7F, 0x8A, + 0x53, 0x98, 0xDE, 0x8C, 0xCB, 0xFA, 0xD2, 0x8D, 0xDF, 0x55, 0x36, 0x86, 0x80, 0xDB, 0x55, 0x6B, 0x8D, 0x45, 0x0A, 0xFC, + 0x7E, 0x56, 0x9E, 0xF0, 0xF8, 0x75, 0x6E, 0x3A, 0x79, 0xE8, 0x1D, 0x6D, 0xBC, 0x64, 0xF8, 0x04, 0x3E, 0x92, 0xD3, 0x8C, + 0x7D, 0x76, 0x77, 0xAB, 0xCC, 0x0F, 0x71, 0xE3, 0x74, 0x30, 0xD7, 0x1D, 0xBE, 0x5D, 0x9B, 0xF5, 0x4E, 0xBE, 0x60, 0xB7, + 0x7A, 0xFC, 0x93, 0xCA, 0x2E, 0x5C, 0x36, 0xCF, 0x38, 0xFE, 0x7E, 0xA0, 0x68, 0x7F, 0x89, 0x9D, 0x2E, 0x75, 0x52, 0xDE, + 0xA6, 0xF2, 0xA6, 0xDB, 0x54, 0xFE, 0x2A, 0xBD, 0xAD, 0xBD, 0x81, 0x16, 0x07, 0xB0, 0x18, 0xB8, 0xBD, 0x9F, 0x83, 0x4B, + 0xF8, 0xBF, 0xF8, 0xF4, 0xC4, 0x73, 0x77, 0x8F, 0xFA, 0xD2, 0xAF, 0x47, 0xCC, 0x6B, 0xEB, 0x5B, 0xF3, 0x4F, 0x37, 0xFF, + 0x66, 0x60, 0x00, 0x7B, 0x90, 0xDE, 0xBF, 0x70, 0x08, 0x09, 0x88, 0x00, 0x99, 0x9F, 0xF7, 0xE0, 0x58, 0x02, 0x28, 0xDA, + 0x56, 0x22, 0xF4, 0x63, 0x4E, 0x00, 0x98, 0x66, 0x15, 0x0D, 0x10, 0x34, 0xC8, 0xFE, 0x34, 0xAB, 0xDE, 0xE7, 0x81, 0x42, + 0x7B, 0x2E, 0xAD, 0xE2, 0x79, 0xC8, 0xD1, 0xA2, 0x4D, 0xB4, 0xB7, 0xA1, 0xD6, 0x64, 0x33, 0x15, 0x08, 0x6C, 0x75, 0x91, + 0xDD, 0x31, 0x35, 0xD6, 0x28, 0x59, 0x98, 0xF5, 0x9B, 0x21, 0x81, 0xC4, 0x04, 0xAF, 0x1F, 0x45, 0x14, 0x7E, 0x0E, 0xC4, + 0x4A, 0xE4, 0xF0, 0xF0, 0x61, 0xE1, 0xF7, 0xA1, 0xA0, 0xB5, 0x3E, 0xC8, 0xB2, 0xDA, 0x88, 0x16, 0xBC, 0x3E, 0xE7, 0xB4, + 0x4B, 0x7E, 0x3E, 0xC5, 0xF9, 0x6F, 0x44, 0x5A, 0xB4, 0x20, 0x05, 0x63, 0x1D, 0x5D, 0x66, 0x6D, 0xD4, 0x86, 0x7B, 0x96, + 0x49, 0xD7, 0xF7, 0x5D, 0xB7, 0x3C, 0xD9, 0xF5, 0xCD, 0x5B, 0xEF, 0x4A, 0xCB, 0x25, 0x38, 0xF7, 0x0E, 0x52, 0x2E, 0x93, + 0x19, 0xC8, 0x02, 0x4A, 0x4C, 0x64, 0x52, 0x92, 0xF9, 0x97, 0xCA, 0x9B, 0x0F, 0xCB, 0x6D, 0x5C, 0x15, 0x82, 0xB6, 0xA7, + 0x48, 0xA9, 0x5A, 0x44, 0xA2, 0x2B, 0x86, 0x16, 0xAE, 0x48, 0x43, 0x89, 0x12, 0x44, 0xEF, 0xAD, 0x84, 0x4A, 0xC9, 0xA2, + 0xAC, 0x28, 0x1B, 0x59, 0xC1, 0xF6, 0x5B, 0x1C, 0xAA, 0xEA, 0xDB, 0xBD, 0x43, 0x27, 0xC4, 0x58, 0x24, 0x05, 0x18, 0x4A, + 0xB9, 0xA5, 0xD3, 0x2A, 0xE5, 0x6E, 0x8F, 0x79, 0x4C, 0x0E, 0x54, 0x17, 0x5B, 0xDC, 0x14, 0xFC, 0x03, 0xA0, 0xF0, 0xA3, + 0x1D, 0x77, 0x12, 0x7D, 0x20, 0x0E, 0x83, 0x4E, 0xB2, 0x7D, 0x3B, 0xC3, 0x8B, 0x6E, 0x8E, 0x39, 0x67, 0x6F, 0x6B, 0xED, + 0x80, 0x7E, 0xE9, 0x85, 0x36, 0x21, 0x48, 0x9E, 0x49, 0x0F, 0x4E, 0x42, 0xBD, 0x29, 0x5F, 0x0A, 0xD7, 0x21, 0x23, 0x75, + 0x32, 0x5F, 0xE8, 0x1F, 0x21, 0x70, 0xE4, 0x37, 0x16, 0x3D, 0x2D, 0xE0, 0x64, 0x7C, 0xEB, 0xE7, 0xDF, 0xDD, 0x9C, 0xF6, + 0xDE, 0x53, 0x2C, 0x54, 0x2D, 0x54, 0xD2, 0x90, 0xCC, 0x11, 0xB0, 0x53, 0x1A, 0x52, 0x5B, 0x25, 0xA8, 0x09, 0x69, 0xF5, + 0x30, 0xB4, 0x6A, 0xE2, 0x4F, 0xFF, 0x5B, 0x85, 0x51, 0x32, 0x40, 0xE5, 0x5C, 0x5B, 0xB5, 0xE5, 0x31, 0xB5, 0x31, 0x56, + 0x9E, 0x73, 0x99, 0x31, 0xBB, 0x7A, 0xFB, 0x53, 0x3A, 0xC9, 0x7F, 0x56, 0x32, 0x75, 0x72, 0x20, 0x72, 0x38, 0x46, 0x17, + 0xF6, 0xF9, 0x12, 0x74, 0x2B, 0xB8, 0x73, 0x46, 0x77, 0xE8, 0xFC, 0x30, 0x6F, 0xFE, 0x85, 0xC7, 0x75, 0x95, 0x27, 0xC1, + 0xA3, 0x76, 0x05, 0x7C, 0xF9, 0x58, 0xEA, 0x91, 0x62, 0xD0, 0x87, 0x53, 0x19, 0x12, 0xC8, 0x16, 0x61, 0x57, 0xAF, 0xD5, + 0x97, 0x9A, 0x8D, 0xF0, 0xAB, 0x74, 0xE1, 0xB5, 0xB7, 0xFA, 0xD6, 0x60, 0x0C, 0x55, 0x26, 0x4C, 0x34, 0xC3, 0xD6, 0x64, + 0x74, 0xAC, 0xDE, 0x35, 0x1B, 0x3B, 0xCE, 0x8D, 0x68, 0x13, 0x7D, 0xFE, 0xC6, 0x94, 0x56, 0xAD, 0x6F, 0x1B, 0x6A, 0xFB, + 0x18, 0x7D, 0x45, 0x72, 0x49, 0xE5, 0x83, 0xA9, 0xBE, 0x78, 0xC7, 0x2D, 0xAE, 0x6A, 0x81, 0x0C, 0xFE, 0x38, 0x8C, 0x71, + 0x8D, 0x56, 0x8A, 0xDA, 0x67, 0x31, 0x7B, 0x7E, 0x37, 0x53, 0xFD, 0xBE, 0xF8, 0x6B, 0x0E, 0xC0, 0xC3, 0x8C, 0x08, 0x1C, + 0xBE, 0x37, 0x76, 0x36, 0x59, 0x1F, 0x8F, 0xDB, 0xDD, 0x83, 0x62, 0x23, 0xA2, 0x72, 0x38, 0x3D, 0x9A, 0xB4, 0x18, 0x4E, + 0xE6, 0xF0, 0x73, 0x14, 0x97, 0x30, 0x25, 0xCD, 0xA9, 0x5E, 0x47, 0x32, 0x9E, 0x38, 0xEF, 0x10, 0xA2, 0x1C, 0x47, 0xFC, + 0x9E, 0x7A, 0x71, 0x11, 0x8B, 0xB2, 0xCB, 0xBD, 0xB7, 0xC4, 0xDC, 0x66, 0x0A, 0x89, 0xDD, 0x1B, 0x84, 0x5F, 0x46, 0x0A, + 0x07, 0xE0, 0x18, 0xF9, 0x12, 0x9A, 0xD7, 0xE2, 0x48, 0x6B, 0xD2, 0x2E, 0x55, 0x80, 0xBA, 0x74, 0xFA, 0xC3, 0x84, 0xED, + 0xFC, 0x4B, 0x80, 0xCD, 0x43, 0xFB, 0x78, 0xC7, 0xAE, 0xA3, 0x7F, 0xA7, 0x8C, 0x99, 0x3B, 0x78, 0x91, 0xE1, 0xE1, 0x22, + 0xF7, 0xD3, 0xEF, 0x83, 0xDC, 0xA0, 0x64, 0x67, 0x08, 0x08, 0xB9, 0x64, 0x91, 0x8F, 0xA3, 0xB7, 0xCB, 0x3B, 0xE6, 0x52, + 0x28, 0x48, 0x28, 0x46, 0x8F, 0x3B, 0x16, 0xDA, 0xB7, 0x5B, 0x12, 0x62, 0x47, 0xFE, 0x08, 0x14, 0xBD, 0x25, 0x78, 0x24, + 0x03, 0xA9, 0xF9, 0x30, 0xE8, 0xE7, 0x68, 0x05, 0x43, 0xC1, 0x79, 0xB6, 0x23, 0x6E, 0x4D, 0xA4, 0x6F, 0x9C, 0xDF, 0x4F, + 0xB2, 0xBD, 0x51, 0x3A, 0x2F, 0xDC, 0xCF, 0x53, 0x5B, 0x40, 0x95, 0xD7, 0x81, 0x50, 0xA4, 0x23, 0x6A, 0xE6, 0xF3, 0x82, + 0xED, 0xE7, 0x3C, 0x46, 0xB3, 0x48, 0x26, 0x95, 0x09, 0xCB, 0x5E, 0x7D, 0x00, 0x21, 0x62, 0x48, 0x48, 0xE4, 0xCA, 0x22, + 0x5A, 0x4A, 0x3A, 0x7C, 0x09, 0xA5, 0x2F, 0x6E, 0x11, 0xA0, 0xBA, 0x5A, 0x49, 0xE5, 0x9A, 0xD4, 0x3E, 0xED, 0x0F, 0xF0, + 0x65, 0x60, 0x23, 0x6F, 0x84, 0x07, 0x4C, 0x58, 0x9C, 0x43, 0xA6, 0x5C, 0x7F, 0x63, 0xD7, 0x9F, 0xC1, 0x99, 0x2F, 0xEE, + 0xBB, 0x8B, 0x44, 0x7C, 0xCB, 0x49, 0xDA, 0xFF, 0xD9, 0xC7, 0x5A, 0xB5, 0xE7, 0x5C, 0xBB, 0x67, 0xBB, 0x53, 0xB2, 0xFB, + 0x6F, 0xC6, 0x52, 0x1C, 0x3C, 0x2B, 0x15, 0x25, 0x77, 0x72, 0x7A, 0xDA, 0x65, 0x07, 0x2E, 0xFE, 0x49, 0xAA, 0x3A, 0x6B, + 0xF6, 0xE7, 0x3D, 0xA9, 0x82, 0x0A, 0x23, 0x86, 0xFB, 0x53, 0x34, 0x9B, 0xE8, 0x6F, 0x8D, 0x68, 0xED, 0x6B, 0x51, 0xFE, + 0x78, 0xE1, 0x47, 0x20, 0x5D, 0x8F, 0x97, 0x0B, 0x4F, 0x49, 0x3B, 0x8F, 0x41, 0x4E, 0x26, 0x7D, 0xCD, 0xC0, 0x24, 0x84, + 0x3C, 0xDC, 0xB0, 0x53, 0x42, 0xF0, 0x58, 0xD9, 0x15, 0xF4, 0x26, 0xD2, 0x29, 0x3A, 0xA8, 0x12, 0x79, 0x50, 0xF8, 0x77, + 0x47, 0xDC, 0xE2, 0x12, 0x7D, 0x51, 0x67, 0x78, 0xA2, 0x72, 0xAD, 0x82, 0xDF, 0xF1, 0xF5, 0xB6, 0xB8, 0x90, 0xD7, 0xA0, + 0xF5, 0x92, 0xFD, 0x92, 0x4C, 0x03, 0xB7, 0x96, 0x94, 0x13, 0xBD, 0xF0, 0x1E, 0x7E, 0xE9, 0xB5, 0x22, 0x5E, 0xE4, 0x81, + 0x89, 0x3F, 0xE4, 0xE2, 0xD7, 0xB2, 0x7C, 0xE7, 0x0D, 0x97, 0x64, 0x84, 0x89, 0xB9, 0x74, 0x12, 0x75, 0x1E, 0x9A, 0x35, + 0x96, 0xBC, 0x1E, 0xF2, 0x66, 0xF7, 0x43, 0xB1, 0xB5, 0x35, 0x31, 0xC2, 0xA0, 0x34, 0x13, 0x26, 0x15, 0xB0, 0x71, 0x90, + 0xFA, 0xB8, 0x8A, 0x63, 0x8D, 0x9F, 0xBD, 0xE2, 0x8D, 0xD5, 0x6B, 0xA5, 0x84, 0x52, 0x5D, 0xE2, 0x0E, 0x3D, 0x6D, 0x91, + 0x0C, 0xB5, 0x3C, 0x8B, 0x0D, 0xF8, 0x66, 0x9B, 0x1E, 0xB3, 0x35, 0xDA, 0x68, 0xD1, 0x33, 0xDE, 0x78, 0xF3, 0x39, 0x1E, + 0x2B, 0x1D, 0x90, 0x93, 0x5C, 0xD9, 0xAE, 0xDC, 0x92, 0xC2, 0xE6, 0x9F, 0x7B, 0x19, 0x79, 0x2F, 0xA4, 0x81, 0x23, 0x7E, + 0x9A, 0x9A, 0xB7, 0xE8, 0x17, 0xC1, 0x25, 0x2B, 0xB0, 0x1B, 0xD0, 0xE8, 0xBD, 0xF5, 0xF7, 0xB6, 0x8E, 0xEA, 0xAD, 0xDD, + 0x60, 0x2D, 0xEF, 0xCF, 0xF5, 0xF0, 0xA6, 0x6D, 0xA1, 0x15, 0x1E, 0x2C, 0xC1, 0xFD, 0x66, 0x9C, 0x26, 0x77, 0xA9, 0x8B, + 0x83, 0x90, 0xEF, 0xA5, 0x4E, 0x99, 0x6E, 0xDC, 0x7C, 0xA6, 0xBE, 0x22, 0xB3, 0x29, 0xFD, 0xEF, 0xFA, 0x6D, 0x47, 0x59, + 0x26, 0x96, 0x27, 0x9F, 0xC2, 0xB6, 0xA7, 0xEA, 0x6E, 0x7E, 0x95, 0xE7, 0xDA, 0xFD, 0x0D, 0xCC, 0xAC, 0xFF, 0x59, 0xB9, + 0x9C, 0xFF, 0xAF, 0xC4, 0xC9, 0x9E, 0x3F, 0x56, 0xA8, 0xBE, 0xA8, 0x31, 0xE1, 0x1B, 0x07, 0x66, 0xD1, 0xAA, 0x28, 0xD3, + 0x5F, 0x46, 0x77, 0xE4, 0x14, 0x7B, 0x76, 0x49, 0x84, 0x60, 0xBA, 0xFD, 0xDF, 0x4E, 0x9F, 0xC1, 0xE2, 0x11, 0x60, 0x14, + 0x5F, 0xD1, 0x34, 0xE7, 0x05, 0x43, 0x06, 0xF4, 0x33, 0x23, 0x31, 0x0A, 0x61, 0xC8, 0x54, 0x43, 0xE3, 0xB2, 0x77, 0x49, + 0xB2, 0xE6, 0xB7, 0xF7, 0x8B, 0x4C, 0x2B, 0xB3, 0x23, 0xD1, 0xBF, 0x44, 0xF0, 0xCE, 0xD7, 0xA8, 0x90, 0x49, 0x81, 0x22, + 0x21, 0x44, 0xD2, 0x86, 0xA9, 0xDE, 0xEE, 0x59, 0x98, 0x4D, 0xDB, 0xA8, 0x03, 0x47, 0xFA, 0xAB, 0xE7, 0x2A, 0x4A, 0x61, + 0x70, 0x57, 0x3F, 0xB4, 0x57, 0x2B, 0xBE, 0xBD, 0x82, 0xB3, 0x39, 0xB4, 0x31, 0xD5, 0x31, 0x63, 0x60, 0x4B, 0xD9, 0x70, + 0x3B, 0x97, 0xC5, 0x23, 0xB0, 0x11, 0x09, 0xB9, 0x50, 0x65, 0xA1, 0xF3, 0x43, 0x7C, 0xCF, 0xF7, 0x53, 0xBF, 0xFA, 0x4E, + 0x56, 0x44, 0xB8, 0xE4, 0xAC, 0x67, 0x6A, 0x6E, 0x1E, 0x4E, 0x8C, 0x6B, 0x92, 0xA1, 0x72, 0xE9, 0x55, 0xF6, 0xD1, 0x1E, + 0x62, 0x87, 0x7A, 0x3A, 0xA1, 0x44, 0x82, 0x2F, 0x3C, 0x6A, 0x13, 0x8B, 0x62, 0x25, 0x58, 0x13, 0xE7, 0x64, 0x33, 0x1F, + 0x69, 0x95, 0xDB, 0x28, 0x10, 0xA3, 0x6B, 0x1B, 0xCE, 0x06, 0x56, 0x3D, 0x9F, 0x10, 0x64, 0x47, 0x22, 0xA1, 0xA5, 0x4C, + 0x54, 0xCD, 0xBA, 0xA0, 0xD6, 0x41, 0xC8, 0x10, 0x98, 0x24, 0x6A, 0xED, 0x44, 0x2E, 0xEA, 0x2B, 0x54, 0x6D, 0xDD, 0xDC, + 0x06, 0x80, 0x7B, 0xDE, 0x39, 0x4D, 0x59, 0x9A, 0xEA, 0x46, 0x3A, 0x7C, 0xDB, 0xED, 0xBC, 0xB5, 0x8A, 0xBB, 0x36, 0x3F, + 0x39, 0x62, 0x19, 0xF4, 0x48, 0xC9, 0xEB, 0x79, 0x7E, 0x3E, 0x12, 0x46, 0x2C, 0x4D, 0xB3, 0xB5, 0xC7, 0x62, 0xDF, 0x89, + 0x97, 0x40, 0x6B, 0xF9, 0x5D, 0x6F, 0xD9, 0x10, 0x5B, 0xEF, 0xFA, 0xF4, 0x91, 0xBC, 0x5E, 0xBD, 0x8B, 0x53, 0x82, 0xD4, + 0x9B, 0xFA, 0x7A, 0x6D, 0xC2, 0x6A, 0x74, 0x16, 0xB1, 0x78, 0x18, 0x32, 0xE1, 0xA9, 0xBC, 0x9E, 0xD0, 0xFD, 0xC5, 0x78, + 0x8B, 0xC9, 0xCF, 0x98, 0x83, 0x40, 0x4D, 0xA4, 0x8B, 0x51, 0x55, 0xE8, 0x61, 0x74, 0x0B, 0xE3, 0x5A, 0x51, 0xB5, 0x30, + 0x37, 0x51, 0x25, 0xE3, 0xA2, 0xA3, 0xD7, 0xA8, 0xC2, 0x65, 0x7A, 0x10, 0x49, 0x1B, 0x9A, 0xA6, 0x3C, 0x56, 0x34, 0xE2, + 0xD1, 0x59, 0xB4, 0xE6, 0x47, 0x79, 0xA9, 0xA3, 0x80, 0x5A, 0xCE, 0xF2, 0x35, 0x73, 0xA7, 0x12, 0xE1, 0x51, 0xE4, 0x0F, + 0x86, 0x6E, 0x47, 0xF3, 0x5D, 0x0D, 0x8F, 0x78, 0x90, 0x3B, 0x1F, 0xFC, 0x60, 0x31, 0x2E, 0x67, 0x72, 0x4F, 0x4C, 0xAE, + 0x04, 0xBA, 0x4B, 0x57, 0x33, 0x8C, 0x20, 0x93, 0x22, 0xDD, 0xDE, 0x13, 0x0A, 0x67, 0x59, 0x69, 0x5F, 0xC4, 0x32, 0xEE, + 0x9C, 0x95, 0x14, 0x40, 0xD8, 0x17, 0x6E, 0xCE, 0x3B, 0x88, 0x34, 0x63, 0x2F, 0xA2, 0x54, 0x9D, 0x0A, 0x4B, 0x06, 0xAC, + 0x94, 0x37, 0xFF, 0xDA, 0x5A, 0x19, 0xD8, 0x9F, 0x97, 0xBA, 0x67, 0x91, 0x8B, 0xCE, 0xAF, 0x56, 0x89, 0x7A, 0xCE, 0xB2, + 0x5F, 0x61, 0x53, 0xEB, 0x9A, 0x29, 0x37, 0x62, 0x98, 0x5B, 0x79, 0x19, 0xE8, 0x9B, 0xC5, 0xAC, 0x5E, 0x60, 0x8A, 0x39, + 0x89, 0x9C, 0xFE, 0x69, 0xBC, 0x6C, 0xD1, 0x6A, 0xC4, 0xC3, 0x2E, 0x6E, 0xFA, 0xF6, 0x36, 0x3E, 0x3B, 0xE0, 0xEE, 0x30, + 0x9A, 0x92, 0x66, 0x28, 0x37, 0x5B, 0xFE, 0x39, 0xDA, 0xD6, 0x75, 0x36, 0xBA, 0xB3, 0x97, 0xC1, 0xDC, 0x38, 0x2F, 0x6B, + 0x6A, 0x61, 0xEF, 0x1E, 0xED, 0x78, 0xB7, 0x5B, 0x2B, 0x27, 0xD3, 0xFA, 0x1A, 0x24, 0xAB, 0x06, 0x48, 0xD2, 0xD6, 0xFD, + 0x10, 0x47, 0x0A, 0xD2, 0x58, 0x00, 0x34, 0xFA, 0xC1, 0x5B, 0x0F, 0xD1, 0x57, 0xC6, 0x2A, 0x66, 0x58, 0x44, 0x12, 0x90, + 0xEF, 0x16, 0x5E, 0xFB, 0x43, 0xE3, 0xE7, 0xD4, 0xAC, 0xDB, 0xAE, 0x56, 0x17, 0x4E, 0x41, 0xB0, 0x22, 0x8D, 0xEA, 0xFF, + 0x14, 0x19, 0x11, 0x14, 0x65, 0xD9, 0xAF, 0x87, 0x3D, 0xE1, 0x51, 0x55, 0xDD, 0x98, 0xF4, 0x32, 0x17, 0xA7, 0x37, 0xE6, + 0xE6, 0x53, 0xE9, 0x24, 0xF4, 0xEC, 0xFB, 0xA0, 0xEF, 0xEE, 0xFA, 0x42, 0x37, 0x3F, 0x10, 0x60, 0xFA, 0xC9, 0x2F, 0x16, + 0x21, 0xE4, 0x4E, 0xB0, 0x4C, 0x2A, 0x92, 0xA9, 0x95, 0xA1, 0x8C, 0x89, 0xE4, 0xC3, 0x7F, 0x10, 0x36, 0xA5, 0x47, 0x93, + 0x25, 0x03, 0x81, 0x45, 0xEA, 0xAB, 0x5B, 0xB3, 0x9A, 0xC0, 0x31, 0x8A, 0xA4, 0xFD, 0xA3, 0x02, 0xCC, 0x8C, 0x7A, 0x35, + 0xEA, 0xAC, 0x59, 0x5C, 0x66, 0x4D, 0xA1, 0x73, 0x7F, 0x87, 0xC3, 0xFC, 0x1C, 0x47, 0x3A, 0x6C, 0x5F, 0x5A, 0x8A, 0xCA, + 0x54, 0x63, 0x90, 0xC6, 0xCC, 0x27, 0x4A, 0xA9, 0xCA, 0x86, 0xE0, 0x83, 0xF6, 0x60, 0x45, 0xCA, 0x41, 0x86, 0xC4, 0xFB, + 0x6E, 0x8B, 0x5D, 0x47, 0x67, 0xF2, 0xDD, 0x7E, 0x30, 0xA7, 0xFD, 0xB6, 0xA7, 0xD0, 0x8D, 0x5E, 0xB4, 0x23, 0xF0, 0xA8, + 0xF2, 0xF5, 0x1F, 0x7D, 0xDE, 0x5B, 0x5B, 0x39, 0x90, 0xC6, 0x43, 0xD7, 0xC3, 0xA6, 0xE2, 0x4B, 0x29, 0xE2, 0xE5, 0x2C, + 0x10, 0xEA, 0xF5, 0xE8, 0xAC, 0xCC, 0x92, 0x6C, 0x6F, 0xE1, 0x54, 0x8B, 0xCD, 0x0D, 0xD2, 0x19, 0x11, 0xCF, 0x42, 0x28, + 0x0C, 0x3D, 0xC2, 0x85, 0xAA, 0x42, 0x5D, 0x9F, 0x4C, 0x13, 0x23, 0xEF, 0x98, 0x6E, 0x0B, 0xE9, 0x4E, 0xD1, 0x08, 0xED, + 0x5E, 0x07, 0x63, 0x5F, 0x87, 0xC4, 0x0B, 0x4E, 0x1D, 0xAB, 0x1B, 0xCC, 0xD1, 0xC0, 0xE8, 0x04, 0x34, 0x5E, 0xDC, 0x6A, + 0x78, 0xDD, 0xFD, 0x99, 0x70, 0xB1, 0x0A, 0x02, 0x24, 0xCB, 0x13, 0xC0, 0x57, 0x90, 0x20, 0x67, 0xA0, 0xD3, 0xBA, 0xE7, + 0xDE, 0x18, 0x8D, 0xD0, 0x44, 0x51, 0x9C, 0xEF, 0xD4, 0x93, 0x3F, 0x87, 0x87, 0xD2, 0x26, 0x8E, 0x5D, 0x7B, 0x04, 0x45, + 0x66, 0xD6, 0xEF, 0xAF, 0x53, 0xF4, 0x85, 0x82, 0x44, 0x88, 0x97, 0x64, 0xD0, 0xB5, 0x05, 0x5B, 0x2F, 0x9C, 0x79, 0x32, + 0xB6, 0x01, 0x5C, 0x3C, 0xA4, 0x90, 0x47, 0x30, 0xB4, 0xB0, 0x14, 0x51, 0xC1, 0xDB, 0xAD, 0x61, 0x97, 0xBB, 0x66, 0x7F, + 0xA5, 0x91, 0x58, 0xB4, 0xDC, 0x44, 0x36, 0xEF, 0xE5, 0x52, 0x9C, 0xF4, 0xE5, 0xF8, 0x6C, 0x2B, 0x91, 0xD4, 0x35, 0xA5, + 0x5D, 0x67, 0x15, 0xE0, 0xF2, 0xDB, 0xF4, 0x94, 0xE1, 0xB9, 0xE0, 0xB1, 0x50, 0x91, 0xBD, 0xD6, 0xE1, 0xB6, 0x79, 0x11, + 0x46, 0x7C, 0x02, 0x1F, 0xF2, 0x7A, 0x26, 0x6C, 0xCD, 0x9E, 0x86, 0xF2, 0x9D, 0x67, 0x6F, 0x3C, 0x8D, 0x97, 0xE6, 0xCC, + 0x6C, 0x5C, 0xB5, 0x17, 0x2B, 0x22, 0xD0, 0xFE, 0x0E, 0x69, 0x5E, 0xB8, 0xBB, 0xD4, 0x29, 0xBC, 0x39, 0x5D, 0x03, 0xD7, + 0x0F, 0xD8, 0x63, 0x0A, 0xFF, 0x48, 0x36, 0x5B, 0xED, 0x95, 0x7B, 0x93, 0x34, 0x70, 0x3E, 0x19, 0x2D, 0x03, 0x91, 0xEF, + 0x1A, 0xD7, 0x15, 0x6B, 0xB1, 0xD2, 0xF5, 0x83, 0x35, 0x91, 0x46, 0x86, 0x1D, 0x27, 0x61, 0x43, 0xD7, 0x6D, 0x0E, 0xE6, + 0x8E, 0xD3, 0x0E, 0xE6, 0x83, 0xB3, 0xD9, 0x5E, 0x00, 0x83, 0xAC, 0xA8, 0xC0, 0x10, 0x54, 0x2A, 0x33, 0xDB, 0xFD, 0x8D, + 0x0F, 0xB2, 0xA7, 0x9B, 0x90, 0xD2, 0x0B, 0x5C, 0x97, 0xB6, 0x17, 0xE8, 0xFA, 0xD3, 0xA7, 0xFA, 0xC3, 0xE5, 0x55, 0x28, + 0x8A, 0x84, 0x7C, 0x40, 0xBC, 0x0F, 0x09, 0x55, 0x4C, 0xC4, 0xFE, 0x8C, 0x87, 0xB0, 0x60, 0x02, 0x79, 0x0D, 0xD9, 0x95, + 0xB7, 0x62, 0xD0, 0x3D, 0x74, 0xBD, 0x4B, 0x46, 0x91, 0xEA, 0x92, 0xF2, 0x83, 0x05, 0xED, 0x90, 0x0E, 0xDC, 0xDC, 0x6E, + 0x4F, 0x5F, 0x20, 0x73, 0x93, 0xC1, 0x4B, 0x1C, 0x02, 0xD6, 0x1B, 0x9D, 0x96, 0x08, 0x48, 0x25, 0x15, 0x2E, 0x16, 0xCD, + 0xD6, 0x2D, 0x39, 0x73, 0xC2, 0xF3, 0x49, 0xE5, 0x3E, 0x38, 0x64, 0xC2, 0xD6, 0xBC, 0xD1, 0x30, 0xB2, 0xC3, 0x5E, 0xC4, + 0x28, 0xDA, 0x7D, 0x74, 0x16, 0xA3, 0xB1, 0x62, 0xF2, 0x40, 0xD8, 0x71, 0xC0, 0x6E, 0xEB, 0x2C, 0xA2, 0x69, 0x5C, 0x71, + 0x5A, 0x61, 0xF1, 0x72, 0x6D, 0x71, 0x48, 0x33, 0xC1, 0xDA, 0x81, 0x85, 0xAB, 0x00, 0xC3, 0x45, 0x91, 0xD3, 0xB8, 0x63, + 0x67, 0x42, 0x53, 0xB6, 0x71, 0x29, 0x2F, 0x30, 0xB0, 0x95, 0x5D, 0xD7, 0xC7, 0x5E, 0xF9, 0x7F, 0x4F, 0xDA, 0x5E, 0xA6, + 0x70, 0x3A, 0x7C, 0xA8, 0x87, 0x8E, 0x01, 0x6A, 0xE3, 0x6D, 0x4B, 0xAF, 0xA9, 0x07, 0x6A, 0xAE, 0xD8, 0xB3, 0x5A, 0x0C, + 0x8B, 0x0D, 0xAA, 0xE3, 0xF0, 0x40, 0x13, 0x03, 0x50, 0x52, 0xA2, 0x0D, 0xF8, 0x72, 0x81, 0x49, 0x84, 0xA1, 0x47, 0x7F, + 0xB6, 0xA2, 0x12, 0x56, 0x6F, 0xDF, 0xAB, 0xFD, 0x84, 0xCB, 0xFF, 0x7B, 0xA8, 0x09, 0xA1, 0xB8, 0xB7, 0xA1, 0x93, 0x5F, + 0x3E, 0x5B, 0x8B, 0xDB, 0x5B, 0x6F, 0xBA, 0x3A, 0xF5, 0x4E, 0x1E, 0xE3, 0x12, 0xEC, 0xAB, 0x1A, 0xC4, 0x29, 0x42, 0x2A, + 0x91, 0xF1, 0xA2, 0x67, 0x2F, 0xE0, 0xF2, 0x78, 0x18, 0x6D, 0x71, 0x2B, 0xC7, 0xD1, 0xB4, 0x0E, 0xD6, 0xDB, 0x1C, 0x7A, + 0x0F, 0x6E, 0xE6, 0x4B, 0x0E, 0x4A, 0x7A, 0x3A, 0x4E, 0x52, 0x83, 0x1A, 0xC2, 0x29, 0x4E, 0xAF, 0x9B, 0xF1, 0x75, 0x79, + 0x25, 0xF0, 0x23, 0x5E, 0x5A, 0xE3, 0xA4, 0x0F, 0x09, 0xF0, 0x6D, 0x6B, 0x1B, 0x96, 0x44, 0x7C, 0xAD, 0x72, 0xAC, 0x40, + 0x78, 0x4B, 0x69, 0x20, 0x7D, 0xA9, 0x6C, 0x92, 0x85, 0x1C, 0x08, 0x64, 0x39, 0x3E, 0x1D, 0x40, 0x4E, 0x1E, 0xA4, 0x4A, + 0x77, 0x73, 0xF9, 0xFF, 0xBA, 0x7D, 0xDE, 0x6A, 0x32, 0x31, 0x16, 0x51, 0xEE, 0x1D, 0xFD, 0xC7, 0x0F, 0x7C, 0x15, 0xF9, + 0xA7, 0x9B, 0x9D, 0x99, 0xB5, 0x1F, 0x0D, 0x80, 0xF5, 0x55, 0xB2, 0xAA, 0xD8, 0x75, 0x41, 0x26, 0x32, 0xEA, 0xC4, 0xED, + 0xCF, 0x80, 0xF5, 0xE7, 0x93, 0x0B, 0xEE, 0x7B, 0x8D, 0xF9, 0xEC, 0xCA, 0xAF, 0x78, 0xB4, 0xF0, 0xD2, 0xA9, 0xFC, 0xBA, + 0xB2, 0xF9, 0xA4, 0x1E, 0xDF, 0x78, 0xBC, 0xC3, 0x81, 0x02, 0xBD, 0xD7, 0x4D, 0x83, 0x6D, 0xC6, 0x73, 0xFA, 0x36, 0x1B, + 0xD6, 0xDA, 0x48, 0x33, 0x0F, 0xE9, 0xB4, 0x24, 0x10, 0x27, 0xF9, 0xAB, 0x40, 0x32, 0xCC, 0x17, 0x3A, 0x78, 0x48, 0x8A, + 0x60, 0x74, 0xC2, 0xAC, 0x38, 0x78, 0x36, 0xD9, 0xC9, 0xF7, 0xB6, 0x41, 0x7E, 0x10, 0x67, 0x73, 0x12, 0x71, 0x36, 0xEC, + 0x3D, 0x32, 0x89, 0x3C, 0x64, 0xB0, 0xB6, 0xDE, 0x84, 0x75, 0xD3, 0xD7, 0x86, 0xC6, 0xAB, 0x0C, 0x8B, 0xCA, 0x84, 0x8E, + 0x49, 0xF5, 0x8D, 0x29, 0xB9, 0x68, 0xF3, 0xE7, 0xB3, 0x74, 0x0F, 0xDE, 0xB3, 0x3D, 0xA8, 0x85, 0xEF, 0xD3, 0xA7, 0x39, + 0xF4, 0xE7, 0xBF, 0xCA, 0x4B, 0x28, 0x79, 0xF1, 0xC5, 0xE1, 0x7F, 0xBB, 0xEE, 0x40, 0xAF, 0x9F, 0xFE, 0xDE, 0xFA, 0x2E, + 0x3B, 0xE3, 0xB5, 0xA2, 0xE1, 0xA0, 0xB1, 0x96, 0xBC, 0x40, 0x7A, 0x9E, 0x49, 0x72, 0xE7, 0xC7, 0x26, 0x13, 0x13, 0x33, + 0x4B, 0x5D, 0x7C, 0xBA, 0x66, 0xC2, 0x77, 0x0D, 0xFE, 0xDC, 0xB6, 0xDB, 0xB8, 0x2B, 0xAE, 0x9D, 0xF3, 0xA0, 0x7F, 0x36, + 0x73, 0x1B, 0x4F, 0x52, 0xF3, 0x7D, 0xE0, 0x52, 0x4F, 0x84, 0x88, 0x5B, 0x55, 0xA3, 0x88, 0xDD, 0x42, 0x30, 0x90, 0x44, + 0xD6, 0x34, 0xFC, 0x4C, 0x96, 0xBE, 0xF7, 0x9F, 0x26, 0xD3, 0x00, 0xC9, 0x36, 0xC1, 0xDA, 0x3A, 0x56, 0x81, 0x27, 0x44, + 0xAA, 0x5E, 0x5C, 0x38, 0xB5, 0xE0, 0xA0, 0xA1, 0x44, 0xA8, 0x67, 0xC5, 0x75, 0x8E, 0x57, 0x5A, 0x51, 0x9B, 0x11, 0x37, + 0xC1, 0xB3, 0xF9, 0x2E, 0xB7, 0xD8, 0xE3, 0xC8, 0x76, 0xE5, 0x99, 0x40, 0x43, 0x69, 0x60, 0x21, 0x32, 0x90, 0xD0, 0x28, + 0x97, 0x68, 0x4B, 0xC6, 0xBB, 0x46, 0x91, 0x50, 0x71, 0x91, 0x0C, 0x72, 0xEA, 0x11, 0x93, 0x05, 0xC7, 0x75, 0x1F, 0x89, + 0xB6, 0x33, 0x64, 0xA5, 0x96, 0x78, 0x41, 0x49, 0x1A, 0x2B, 0xD5, 0x39, 0x19, 0xFB, 0x01, 0xB4, 0x37, 0x8A, 0xC9, 0x49, + 0x0B, 0x6A, 0x91, 0x65, 0x27, 0xA8, 0x5C, 0x75, 0x53, 0xA3, 0x02, 0xF3, 0x8B, 0x74, 0x42, 0x08, 0xAA, 0x85, 0xDC, 0x5F, + 0xA0, 0x21, 0xBA, 0x54, 0xEB, 0xD8, 0x92, 0xC2, 0x5A, 0x80, 0x64, 0x18, 0x45, 0xE5, 0xD4, 0x4F, 0xA1, 0x20, 0x88, 0xF6, + 0x7E, 0x79, 0x92, 0x5C, 0xA0, 0xE5, 0x3B, 0x8F, 0x8A, 0x02, 0x99, 0xF4, 0x1C, 0x6A, 0x8C, 0xCD, 0xFF, 0x2C, 0xA9, 0xAB, + 0x9D, 0xF8, 0xFF, 0x45, 0xA3, 0x57, 0x9C, 0x7F, 0x61, 0xA2, 0x83, 0xDB, 0xC9, 0xD9, 0x83, 0xBB, 0xD0, 0x77, 0x67, 0xA8, + 0xA2, 0x72, 0x4D, 0x54, 0xBD, 0x29, 0x48, 0xED, 0xE2, 0x03, 0x5E, 0x1C, 0x84, 0x53, 0x6F, 0xAC, 0x1F, 0x73, 0xD8, 0x62, + 0xE8, 0xEC, 0x83, 0x51, 0xEC, 0x70, 0x7E, 0xFA, 0x03, 0x7E, 0x9A, 0x49, 0xA8, 0xE3, 0xF2, 0x11, 0x46, 0xA1, 0x72, 0xB4, + 0x75, 0x53, 0xC9, 0xF5, 0x2D, 0xEA, 0x92, 0x59, 0xBC, 0xE2, 0x98, 0x5F, 0x83, 0x78, 0x86, 0x5F, 0x57, 0x8B, 0xAB, 0xAC, + 0x93, 0x83, 0x04, 0x52, 0xA6, 0x94, 0x84, 0x7E, 0x95, 0x3C, 0xF5, 0xE0, 0xC5, 0x2D, 0x49, 0x22, 0x79, 0x29, 0xAB, 0x10, + 0xF1, 0x58, 0xF5, 0x02, 0x92, 0xBC, 0x17, 0x5D, 0x63, 0xB9, 0x84, 0x48, 0x73, 0xF3, 0x3A, 0xE1, 0x65, 0x18, 0x61, 0x02, + 0xF7, 0xD2, 0x1D, 0xC1, 0xE2, 0xBA, 0xDD, 0xC5, 0x0B, 0xFC, 0x55, 0x11, 0x25, 0xB4, 0xE7, 0x2A, 0x86, 0x92, 0xA6, 0x71, + 0x44, 0x2C, 0x92, 0x5F, 0x21, 0x0E, 0xC4, 0xCC, 0xAA, 0x99, 0x5F, 0x5D, 0xC1, 0x44, 0xD5, 0xE5, 0x87, 0xB2, 0xCA, 0xE0, + 0x4E, 0x5B, 0x95, 0xD0, 0x76, 0x91, 0x47, 0x2D, 0x13, 0x08, 0x01, 0xF0, 0xB6, 0xC1, 0x82, 0xF1, 0xD6, 0x5A, 0xD1, 0x25, + 0xB6, 0x68, 0x8B, 0x25, 0x0F, 0x3B, 0xC1, 0x05, 0xF6, 0x28, 0x55, 0x94, 0x7A, 0xA5, 0x85, 0xD1, 0x10, 0x93, 0x94, 0x24, + 0x14, 0x6A, 0x05, 0x8C, 0xC6, 0xF7, 0x85, 0xD0, 0x56, 0xB6, 0x1E, 0xEA, 0x21, 0x95, 0x5E, 0xE8, 0x57, 0xB7, 0x5E, 0xC8, + 0x9B, 0x9A, 0x4C, 0x52, 0xD2, 0x03, 0x23, 0xA4, 0x3C, 0x66, 0xA8, 0x8C, 0xBF, 0x6D, 0x81, 0x5C, 0xE0, 0x74, 0xBE, 0xCC, + 0x86, 0xBB, 0x79, 0xC3, 0xAC, 0x35, 0x23, 0xBD, 0xD7, 0xB5, 0x77, 0xF0, 0xDF, 0x58, 0x2D, 0x42, 0x3A, 0xA1, 0x74, 0x9B, + 0xD6, 0xFB, 0xF7, 0x7D, 0x3F, 0xBF, 0xA8, 0x28, 0x99, 0x2A, 0x65, 0xA0, 0xFB, 0xA0, 0xCC, 0xC8, 0xED, 0x98, 0xC4, 0xEE, + 0xB9, 0x2E, 0xF5, 0xB6, 0x4F, 0xB0, 0xBE, 0xE7, 0xC7, 0x5D, 0xBA, 0xD8, 0x2D, 0x99, 0x96, 0xD6, 0xC2, 0x4C, 0xFE, 0x48, + 0x2F, 0xDD, 0xFF, 0x88, 0x5B, 0x8A, 0x7A, 0xC9, 0x09, 0x9A, 0x1C, 0xF4, 0x1D, 0x15, 0x56, 0x09, 0x17, 0x5F, 0x57, 0x05, + 0x3A, 0xF1, 0xDD, 0xD9, 0x1A, 0x9B, 0x10, 0xA4, 0x91, 0x00, 0x37, 0x50, 0x04, 0x9B, 0x04, 0xF3, 0x46, 0x5E, 0xA0, 0xEA, + 0xA5, 0xAF, 0xFD, 0xEA, 0x34, 0x3B, 0x3F, 0x89, 0xB7, 0xCD, 0xF9, 0xC7, 0x74, 0x7D, 0x36, 0x17, 0x35, 0xAE, 0x33, 0xB1, + 0xE6, 0x9C, 0x0F, 0x6E, 0x2B, 0x4E, 0x4C, 0xCB, 0xA4, 0x02, 0x79, 0x09, 0x25, 0x43, 0xC0, 0x7A, 0xEC, 0xDD, 0x42, 0xDB, + 0x75, 0xC7, 0x89, 0x38, 0x2D, 0x0E, 0xAD, 0x7A, 0x0F, 0xAC, 0x5D, 0xEE, 0x60, 0x40, 0x66, 0x43, 0xB3, 0xDC, 0x62, 0x4E, + 0xFF, 0xDC, 0x6E, 0x47, 0x93, 0xA8, 0xBE, 0x42, 0x71, 0xC3, 0xF4, 0x02, 0x52, 0xBB, 0xA8, 0x9A, 0xAF, 0xC5, 0x66, 0x57, + 0xCA, 0x0A, 0xF6, 0x68, 0x7B, 0x28, 0xF8, 0x02, 0x21, 0x82, 0x23, 0x50, 0x28, 0xA5, 0xE1, 0x0B, 0x21, 0x63, 0x12, 0xB6, + 0x1E, 0x67, 0xE9, 0x51, 0xDC, 0xE9, 0xE9, 0x9A, 0x27, 0x05, 0x67, 0x56, 0x12, 0xAB, 0xDB, 0x75, 0x78, 0x63, 0x27, 0x76, + 0x62, 0x06, 0x6E, 0x69, 0xA4, 0x67, 0x7A, 0x2F, 0xB1, 0x6E, 0xF9, 0x47, 0x36, 0x14, 0x82, 0xD9, 0xEB, 0x58, 0xA9, 0x89, + 0xAB, 0x76, 0x4E, 0x6B, 0x8D, 0x38, 0xB7, 0x92, 0x18, 0xC9, 0x8D, 0xC7, 0xBC, 0x2A, 0x9B, 0x4A, 0xA2, 0x79, 0x93, 0xE3, + 0x36, 0x2A, 0xC3, 0xDA, 0xD0, 0x5C, 0x4D, 0x2F, 0xC8, 0xB7, 0xEF, 0x09, 0x3D, 0xF5, 0x75, 0x1F, 0x60, 0x6F, 0xB0, 0x92, + 0x6A, 0x16, 0xE0, 0x62, 0xE7, 0xF7, 0x21, 0xC3, 0xC9, 0xA6, 0xE2, 0x02, 0x2E, 0x02, 0xF8, 0xFC, 0xF4, 0x83, 0xAD, 0x98, + 0x5C, 0xED, 0x89, 0x6C, 0x5C, 0x9C, 0xAE, 0xBE, 0x1B, 0x86, 0xF2, 0xA3, 0x68, 0x2D, 0x08, 0xCE, 0xA0, 0x29, 0x36, 0xE3, + 0xAA, 0xBB, 0xE7, 0x8B, 0x0E, 0x83, 0x67, 0x2F, 0x6D, 0x4B, 0xD2, 0x9A, 0x4E, 0xC3, 0x42, 0x85, 0xFC, 0x23, 0x4F, 0xDE, + 0x2C, 0x1F, 0x94, 0x58, 0x9D, 0xDF, 0x63, 0x5D, 0x6A, 0xB0, 0x4B, 0x95, 0xB5, 0xE4, 0xFC, 0xA4, 0x91, 0xE4, 0x02, 0x0B, + 0xC1, 0x66, 0xFE, 0xD2, 0xB5, 0x2F, 0x95, 0xDF, 0x97, 0x60, 0x74, 0xA2, 0x51, 0x8E, 0xB3, 0x1B, 0xCA, 0xAC, 0x37, 0x5B, + 0xD1, 0x15, 0x66, 0x90, 0x80, 0x7E, 0x7D, 0xB3, 0x71, 0x66, 0xBC, 0x0E, 0xB1, 0x62, 0x2F, 0xFA, 0x57, 0xDF, 0x2E, 0x53, + 0xE0, 0x8F, 0x30, 0x8F, 0x02, 0x96, 0x6C, 0x6F, 0x00, 0x05, 0x8D, 0x1B, 0xE1, 0x7F, 0x29, 0xCE, 0x52, 0x16, 0x84, 0x30, + 0x2A, 0x72, 0xBB, 0xAA, 0x40, 0xAB, 0x42, 0xEC, 0x89, 0x10, 0xEE, 0x54, 0x98, 0xDB, 0xA8, 0x3A, 0x40, 0x35, 0x6C, 0x24, + 0xDF, 0xE6, 0xF8, 0xD4, 0xBD, 0xAA, 0xE6, 0x0E, 0x88, 0xAA, 0x1D, 0xD8, 0x0E, 0x73, 0x9F, 0xA5, 0xCE, 0x99, 0x6F, 0x51, + 0x04, 0xF9, 0x71, 0xC1, 0xCD, 0x44, 0xA9, 0x22, 0x27, 0x03, 0xB3, 0xD2, 0x97, 0x5B, 0x67, 0x63, 0xE3, 0x2B, 0x24, 0x1E, + 0x40, 0x37, 0x15, 0x72, 0xBC, 0x17, 0xFF, 0x91, 0xF3, 0x37, 0x63, 0xA8, 0x73, 0x0F, 0x2D, 0x4E, 0xD4, 0x85, 0xB7, 0x86, + 0x8A, 0x9C, 0xB4, 0xC6, 0x8E, 0xB4, 0x66, 0xAA, 0xB4, 0x85, 0x9F, 0xC7, 0xDE, 0x69, 0x38, 0xBB, 0xD8, 0x85, 0x6E, 0xFF, + 0x61, 0x45, 0x17, 0x90, 0x19, 0x2E, 0xEF, 0x89, 0x09, 0x35, 0x20, 0xB3, 0x0A, 0x6F, 0xA6, 0x76, 0x9D, 0x46, 0x30, 0x43, + 0x00, 0x54, 0x24, 0x5B, 0xE9, 0x86, 0xE2, 0xBA, 0x05, 0x97, 0x9C, 0xCD, 0xE4, 0x74, 0xE9, 0xA7, 0xDD, 0xD1, 0x96, 0xA8, + 0xF8, 0x9B, 0xF1, 0xFF, 0x87, 0x78, 0xF6, 0x59, 0x35, 0x5F, 0x25, 0x03, 0x9C, 0x1F, 0xE6, 0x17, 0xD7, 0x70, 0xC7, 0x4E, + 0x9B, 0x17, 0x17, 0x4F, 0x3A, 0x95, 0x2A, 0x03, 0x16, 0xEF, 0x37, 0x8F, 0x49, 0x1B, 0x6F, 0x06, 0x40, 0x5B, 0x85, 0x40, + 0x9F, 0x80, 0x1F, 0xBD, 0xD4, 0x5D, 0x26, 0xDA, 0x5A, 0x00, 0xF1, 0xF1, 0x88, 0x9D, 0x41, 0xED, 0x48, 0xBE, 0x1B, 0x87, + 0x95, 0x6C, 0x4F, 0x02, 0xF5, 0x7F, 0x50, 0x36, 0x06, 0xB1, 0x92, 0x4C, 0xAA, 0xE0, 0xDD, 0x49, 0xD3, 0x5C, 0x80, 0xC8, + 0xF9, 0xEC, 0x59, 0x70, 0x27, 0xE7, 0x99, 0x75, 0x0D, 0xFD, 0x91, 0x86, 0x0D, 0x86, 0x05, 0x45, 0x2F, 0x87, 0x14, 0x22, + 0x01, 0x9F, 0xF7, 0xF5, 0x97, 0x5E, 0x5C, 0x40, 0x41, 0xD5, 0x46, 0x13, 0x34, 0x85, 0x3A, 0x46, 0x88, 0xCB, 0x71, 0xDF, + 0x10, 0x54, 0x4E, 0x57, 0xA6, 0x45, 0x74, 0x80, 0x65, 0x67, 0x90, 0xA2, 0x47, 0xEE, 0xD0, 0x66, 0x37, 0x0A, 0x00, 0xC2, + 0xBB, 0x6A, 0x80, 0xF4, 0xB9, 0x57, 0x60, 0xB3, 0x8A, 0xE0, 0x85, 0x34, 0xEE, 0x07, 0x69, 0x90, 0x42, 0x6B, 0x09, 0xE5, + 0x38, 0xED, 0x5B, 0x62, 0x03, 0x28, 0x49, 0x25, 0xF5, 0x40, 0xDD, 0x0C, 0x64, 0x4C, 0x81, 0x05, 0x55, 0x00, 0xD8, 0x02, + 0xE8, 0x87, 0x35, 0xF1, 0xE9, 0xCB, 0x3A, 0x32, 0xA7, 0x8C, 0xC9, 0xDE, 0x54, 0x8E, 0x17, 0x2B, 0x89, 0x95, 0x81, 0xBB, + 0xCC, 0xB5, 0xDB, 0xC1, 0xBC, 0xFF, 0x41, 0xCE, 0x51, 0x8F, 0xB3, 0xA4, 0x7B, 0xBA, 0x58, 0x74, 0xB2, 0x15, 0x88, 0xA4, + 0x3B, 0x77, 0xCC, 0xDF, 0xD8, 0x8C, 0xD3, 0x68, 0x2E, 0x9B, 0x7F, 0x55, 0x9F, 0x45, 0x40, 0x26, 0x06, 0xC4, 0x44, 0x1B, + 0x2C, 0x24, 0xC2, 0x39, 0xAD, 0x2F, 0x9C, 0x49, 0x3A, 0x5D, 0xA2, 0x5B, 0x22, 0x63, 0xAE, 0x8C, 0x3D, 0x8C, 0x02, 0x5D, + 0x8C, 0xC9, 0x39, 0xAD, 0x93, 0xA0, 0x04, 0x7D, 0xEE, 0x32, 0x02, 0x5A, 0x3C, 0xAE, 0xC7, 0xB8, 0x02, 0xCF, 0x9D, 0x49, + 0xFD, 0x4B, 0xD3, 0x19, 0xAC, 0x69, 0x0B, 0x1D, 0xED, 0xE6, 0x12, 0x29, 0x01, 0x84, 0x12, 0x78, 0x3E, 0x1E, 0xEB, 0x99, + 0xAC, 0x99, 0xED, 0x4A, 0x34, 0xAB, 0x5C, 0xB0, 0x5C, 0x0C, 0x43, 0x75, 0x97, 0xED, 0x99, 0x49, 0x57, 0xC2, 0x4C, 0x82, + 0xC4, 0xB4, 0x11, 0x8D, 0x86, 0x14, 0xCB, 0xD2, 0x96, 0xAC, 0xE8, 0x4C, 0x9C, 0xB2, 0x18, 0x74, 0xF1, 0xB3, 0x74, 0xB2, + 0x07, 0x2D, 0x46, 0xC3, 0x17, 0x8F, 0x8A, 0x9E, 0x1B, 0x0F, 0x93, 0xA0, 0x57, 0xFC, 0x3E, 0xC8, 0xCF, 0x9C, 0xCE, 0xC6, + 0x16, 0xF2, 0x42, 0xC9, 0xCB, 0x4C, 0xF9, 0x5C, 0xF3, 0xD1, 0x5E, 0x72, 0xC0, 0x3B, 0xBA, 0x24, 0x76, 0x19, 0x4E, 0x0C, + 0xDD, 0xCB, 0x64, 0x0E, 0x50, 0xB9, 0x93, 0xB4, 0x47, 0xE3, 0x92, 0xD0, 0xDE, 0xBA, 0x47, 0xB8, 0xFE, 0x68, 0x07, 0x89, + 0xF8, 0x23, 0xC1, 0x2B, 0xC2, 0x9B, 0x74, 0xF5, 0xD6, 0xEB, 0xB5, 0x63, 0x3F, 0xCA, 0xAB, 0x05, 0xFA, 0x72, 0x13, 0xD5, + 0x46, 0x14, 0xBF, 0x95, 0x5C, 0xD3, 0x50, 0xBD, 0x12, 0x8B, 0x6D, 0xB0, 0x1E, 0xE6, 0x5D, 0xE5, 0xF8, 0x97, 0x9F, 0xEE, + 0x60, 0x25, 0x8B, 0x0F, 0xD3, 0xDA, 0xCB, 0x2A, 0x76, 0xC7, 0x93, 0x85, 0x8E, 0x1C, 0x6A, 0x65, 0xC8, 0xDB, 0x3C, 0xD5, + 0xF7, 0xA6, 0x62, 0xCC, 0xF3, 0x9C, 0x15, 0x75, 0x14, 0x95, 0x0B, 0x0A, 0x4F, 0x07, 0xD9, 0xAE, 0x76, 0xD2, 0x77, 0x2E, + 0x47, 0x77, 0x80, 0xC8, 0x0E, 0x4A, 0x54, 0xE0, 0xB3, 0x44, 0xB8, 0x71, 0x04, 0x56, 0x91, 0xB8, 0x34, 0xF4, 0x94, 0x39, + 0xA2, 0x91, 0xDC, 0x2C, 0x92, 0xFD, 0xDB, 0x95, 0xF3, 0x9D, 0xEC, 0xEC, 0xBC, 0xF8, 0x7C, 0x57, 0xC4, 0xD9, 0xDC, 0xEF, + 0x51, 0x26, 0x81, 0x89, 0x53, 0xBE, 0x3A, 0x2E, 0x01, 0x22, 0xF7, 0x23, 0x9E, 0xD3, 0xDA, 0x3E, 0x1D, 0x4E, 0x49, 0xD3, + 0x86, 0xD3, 0x67, 0x9C, 0xAA, 0x9C, 0x55, 0x6B, 0x49, 0x30, 0xEF, 0x20, 0x4E, 0x1C, 0x84, 0x0B, 0xCF, 0x2E, 0x40, 0xDB, + 0x00, 0x93, 0x3E, 0x08, 0xDE, 0xAF, 0xD2, 0x3B, 0xFB, 0x44, 0xEF, 0x52, 0x82, 0x40, 0xF2, 0x24, 0xBB, 0xE3, 0x76, 0xBD, + 0x25, 0xAC, 0x18, 0x2B, 0x45, 0xAC, 0x20, 0x01, 0xE0, 0xC0, 0xA6, 0x19, 0x39, 0x62, 0x52, 0x73, 0x42, 0x02, 0x3E, 0xE7, + 0xD8, 0xC3, 0x81, 0x52, 0xF4, 0xE3, 0xCB, 0xAA, 0xAC, 0x23, 0xD8, 0x9E, 0x34, 0x8A, 0x65, 0xEF, 0x6A, 0xFC, 0x9C, 0xC2, + 0x45, 0xCE, 0xE7, 0x33, 0x30, 0xC0, 0x72, 0x64, 0xEB, 0xB5, 0xE1, 0x32, 0x72, 0xDB, 0x12, 0x5F, 0x2B, 0x06, 0x8E, 0xB9, + 0x52, 0x23, 0xD8, 0xD2, 0xED, 0xD7, 0x33, 0x6F, 0x32, 0xBE, 0xE7, 0x96, 0xBF, 0x8C, 0x30, 0xF5, 0xD4, 0x05, 0x21, 0x7D, + 0x7A, 0x60, 0x3E, 0x37, 0xF0, 0xD9, 0x0E, 0xB0, 0xF1, 0xE6, 0x54, 0x8D, 0x0A, 0xA6, 0x71, 0xAE, 0x6A, 0x17, 0xC9, 0xD1, + 0xCF, 0x76, 0x99, 0x89, 0xE4, 0x5C, 0x63, 0x32, 0xE0, 0x93, 0x22, 0xE2, 0xE1, 0x3B, 0x02, 0x8D, 0x47, 0x2E, 0x40, 0x9E, + 0xA3, 0x2C, 0x03, 0xDF, 0xD4, 0x65, 0xB9, 0xB0, 0xF5, 0x3A, 0xF2, 0x0D, 0xF9, 0xA8, 0x24, 0x14, 0x21, 0x44, 0xCA, 0xCF, + 0xDD, 0xE4, 0x19, 0x0B, 0x1A, 0x4B, 0xF1, 0x0D, 0x39, 0x81, 0x29, 0xCB, 0x64, 0x0B, 0x03, 0x5E, 0xA0, 0xCB, 0xCB, 0x04, + 0xBD, 0x97, 0x0F, 0xE2, 0x78, 0x88, 0x0D, 0x5B, 0xA9, 0xFB, 0xCD, 0x05, 0x32, 0x0F, 0xAE, 0xD7, 0x2E, 0xF0, 0x7D, 0x60, + 0xE1, 0xB1, 0xD4, 0x17, 0xED, 0x48, 0x30, 0x2C, 0x03, 0x20, 0xE1, 0x7C, 0x89, 0xEA, 0xF2, 0x4F, 0x3A, 0x22, 0x05, 0xA9, + 0x78, 0xAD, 0xDA, 0x94, 0x53, 0x20, 0xFE, 0x16, 0x5F, 0x53, 0x10, 0xB7, 0x27, 0x8F, 0x93, 0x56, 0xAF, 0x0C, 0x56, 0x85, + 0x02, 0xA5, 0xAB, 0x5D, 0x81, 0x53, 0xF9, 0xA2, 0x16, 0x92, 0xE4, 0x9F, 0x37, 0xE6, 0xD9, 0x9B, 0x7E, 0x74, 0x3A, 0x20, + 0x40, 0x30, 0x82, 0xB6, 0xC4, 0x3F, 0x6C, 0x87, 0x9D, 0x5F, 0xC7, 0x9A, 0x16, 0x85, 0x9C, 0xF2, 0xDE, 0xBC, 0xB6, 0x7F, + 0x82, 0x70, 0x24, 0xF7, 0xBF, 0x8C, 0x4C, 0xB0, 0x2D, 0x20, 0xFA, 0xF3, 0x8E, 0xCD, 0x78, 0xCB, 0x45, 0x6E, 0x85, 0xC3, + 0x13, 0x37, 0x43, 0x5D, 0xF0, 0xC9, 0xDC, 0xA0, 0xCF, 0x0C, 0x49, 0x10, 0xF2, 0xC0, 0x07, 0xB3, 0x52, 0x12, 0xA3, 0x98, + 0x8D, 0xDC, 0x7A, 0xF8, 0x85, 0x55, 0xC5, 0xB7, 0x6D, 0x9D, 0xE3, 0x80, 0x64, 0xEF, 0x16, 0x82, 0x8D, 0x6F, 0x64, 0xD7, + 0xA2, 0x51, 0x48, 0xA7, 0x6C, 0xB7, 0xA3, 0x18, 0x2F, 0x18, 0x94, 0xF8, 0x75, 0x3C, 0x6D, 0xA3, 0x23, 0x19, 0xDD, 0x25, + 0xB6, 0x8D, 0x10, 0x09, 0xAA, 0x1B, 0x12, 0x83, 0x7F, 0x80, 0x65, 0x13, 0xC8, 0x19, 0x32, 0xF3, 0xA3, 0x50, 0x22, 0x19, + 0xFD, 0x1A, 0x68, 0x1D, 0xAD, 0x3A, 0xBC, 0x73, 0x2E, 0xB3, 0x79, 0xEA, 0xCF, 0xC5, 0x49, 0xA1, 0x9C, 0xBB, 0x36, 0xDF, + 0x4C, 0xAB, 0x2E, 0x72, 0xDC, 0x90, 0xF0, 0x20, 0xD8, 0xBF, 0x9E, 0xA5, 0x5D, 0xE6, 0xA0, 0x85, 0x05, 0xD6, 0x61, 0xF6, + 0x8C, 0x93, 0x6B, 0x13, 0x9C, 0xCC, 0xA0, 0x01, 0x9B, 0x5A, 0xE9, 0xAA, 0x59, 0x3B, 0x2F, 0x13, 0x8D, 0xCE, 0x8F, 0x6E, + 0xC3, 0x7A, 0x45, 0x21, 0x95, 0xF4, 0x3F, 0xCE, 0x89, 0xA8, 0x06, 0x68, 0x72, 0x4E, 0x26, 0xF9, 0x9E, 0x4C, 0x28, 0xB9, + 0xD6, 0xD5, 0xD4, 0x0A, 0xFA, 0x4C, 0xAE, 0xF0, 0x40, 0x95, 0x76, 0x2F, 0x7A, 0x2D, 0x9B, 0x9E, 0xD0, 0xFC, 0x36, 0xF9, + 0x7D, 0x66, 0xEF, 0xFC, 0x0E, 0x6E, 0x27, 0xE5, 0x89, 0x2E, 0x97, 0x11, 0x77, 0x45, 0x8E, 0x70, 0x1B, 0x31, 0x4F, 0x28, + 0xE2, 0x1F, 0x77, 0x2E, 0xF2, 0x24, 0x45, 0x02, 0x0A, 0x3C, 0x96, 0x79, 0xD2, 0x6D, 0x9B, 0x58, 0xDD, 0x7D, 0xD8, 0xF8, + 0x30, 0xBB, 0x4E, 0x24, 0xA5, 0x43, 0x88, 0x02, 0xDB, 0x1D, 0x3E, 0x1E, 0xEE, 0xC5, 0xAA, 0x24, 0xEA, 0xCF, 0x40, 0x15, + 0x61, 0x3E, 0xB8, 0x12, 0xDA, 0x4C, 0x0E, 0x27, 0xE7, 0xA1, 0x71, 0x61, 0xFF, 0xAD, 0xC3, 0xD0, 0x48, 0x4F, 0xD3, 0xB7, + 0x21, 0x64, 0x13, 0xA3, 0x6F, 0x2C, 0x97, 0x0B, 0x4B, 0xE2, 0x81, 0x74, 0x1B, 0x3C, 0x6A, 0xA5, 0xD5, 0x4E, 0x9F, 0xC0, + 0xE8, 0x56, 0x07, 0xB9, 0xE7, 0x02, 0xB0, 0x9A, 0x61, 0xDF, 0xD1, 0xF0, 0x57, 0x77, 0x8B, 0x76, 0x7C, 0x85, 0xF2, 0xAD, + 0xF6, 0xC6, 0xB5, 0x0D, 0x74, 0x15, 0xA1, 0xF4, 0x13, 0xE6, 0x59, 0xBD, 0x7B, 0xEA, 0x99, 0xB9, 0x2F, 0x07, 0x77, 0x1C, + 0x61, 0x84, 0xA8, 0x66, 0x37, 0xA9, 0xB4, 0xAC, 0xF0, 0x87, 0x92, 0xD3, 0xCB, 0xF6, 0xC1, 0x88, 0x63, 0xA5, 0x78, 0xD3, + 0xF5, 0xE7, 0x86, 0x68, 0x28, 0x27, 0x9C, 0x13, 0x9E, 0x79, 0x08, 0xB8, 0x4C, 0x17, 0xE5, 0x5E, 0xDC, 0x6E, 0x7F, 0x2A, + 0x05, 0x36, 0xD2, 0x0A, 0xF4, 0x48, 0xC5, 0x5C, 0x31, 0xA5, 0x45, 0x4C, 0x73, 0x36, 0x87, 0x69, 0x73, 0x27, 0x94, 0x88, + 0xB8, 0x01, 0x09, 0xD1, 0x37, 0x8B, 0x93, 0x0B, 0xB4, 0xE7, 0x11, 0xBE, 0x7E, 0xCA, 0x99, 0x3B, 0xF6, 0xA4, 0xFF, 0x1C, + 0x32, 0x46, 0xE0, 0x3F, 0xD9, 0x1B, 0xE2, 0x56, 0xB3, 0x97, 0xBB, 0x42, 0xEB, 0xE3, 0x48, 0xCF, 0x0F, 0xC8, 0x65, 0x86, + 0x00, 0x6C, 0xD2, 0x7E, 0x3C, 0x1E, 0xEE, 0x2D, 0x40, 0x2A, 0xAE, 0xDF, 0x0C, 0xC1, 0xA1, 0xCA, 0xDF, 0x6C, 0x71, 0x2D, + 0x71, 0x9C, 0xE2, 0x30, 0x39, 0x15, 0x8C, 0x18, 0xE3, 0x42, 0x0B, 0x29, 0xD2, 0xAC, 0x55, 0x76, 0x28, 0x9F, 0xEF, 0x5A, + 0xC5, 0xAB, 0xF4, 0x2B, 0xED, 0xB0, 0x3B, 0x87, 0xB9, 0xF4, 0x73, 0xBD, 0x52, 0x0B, 0x9A, 0x8A, 0x76, 0x4F, 0x94, 0xD0, + 0x06, 0x17, 0xCA, 0xA1, 0xD5, 0xB1, 0xAB, 0xBE, 0xAA, 0x3C, 0x3C, 0xE4, 0x96, 0x1C, 0x65, 0x96, 0xC0, 0x2E, 0x8B, 0x31, + 0x8A, 0x5C, 0x25, 0x7A, 0xB0, 0xD2, 0x9B, 0x26, 0x39, 0x44, 0x4B, 0xA4, 0x45, 0x93, 0x8B, 0x9B, 0x76, 0x23, 0x38, 0xE3, + 0x25, 0x15, 0xAC, 0xB0, 0x16, 0xD6, 0x64, 0x87, 0x40, 0x25, 0xAA, 0x30, 0xD1, 0x5E, 0x3A, 0x96, 0x26, 0x3F, 0x65, 0xA0, + 0xDD, 0x7C, 0x0F, 0x0A, 0x6E, 0x99, 0x9C, 0x24, 0xF5, 0xB0, 0x93, 0x56, 0x04, 0xFB, 0x2C, 0x36, 0xB8, 0xF7, 0x04, 0xC0, + 0x98, 0x00, 0x94, 0x94, 0x51, 0xF9, 0xEB, 0xC3, 0x47, 0x29, 0xE4, 0xA1, 0x5D, 0x5E, 0x88, 0x90, 0xC7, 0xA2, 0x9D, 0xE0, + 0x75, 0xF9, 0x51, 0xB1, 0x94, 0x65, 0x33, 0x19, 0x35, 0xBF, 0x05, 0x77, 0xBB, 0x86, 0xC5, 0xB5, 0x7B, 0xFB, 0x06, 0xAE, + 0xD7, 0x13, 0x9C, 0x6C, 0x90, 0xF9, 0xA6, 0x95, 0x58, 0x78, 0x35, 0x5F, 0xDF, 0x38, 0x14, 0x2A, 0xCB, 0x36, 0x99, 0x19, + 0x19, 0xD5, 0x47, 0xDC, 0x2D, 0x98, 0x5D, 0x9A, 0x82, 0x52, 0x44, 0xB6, 0x47, 0xDE, 0x99, 0xB7, 0x3E, 0x6B, 0xA6, 0x5B, + 0x94, 0x2B, 0x95, 0x51, 0x01, 0x96, 0x8B, 0xF9, 0x20, 0x2D, 0xC8, 0x6C, 0xD7, 0x36, 0x41, 0xBD, 0x04, 0xD4, 0xC7, 0xAF, + 0x14, 0xAA, 0xDE, 0xAA, 0x2A, 0xB1, 0x08, 0x3E, 0x2E, 0xB3, 0x2F, 0xE2, 0x9B, 0x93, 0x56, 0xFF, 0x5B, 0xFA, 0x6A, 0xBA, + 0x2B, 0xB0, 0xF6, 0x9E, 0x56, 0x30, 0xE4, 0x89, 0x42, 0xD6, 0x86, 0x3C, 0xFB, 0xF3, 0x14, 0xB8, 0xF1, 0x17, 0xD9, 0x12, + 0x31, 0x18, 0x76, 0x94, 0x49, 0x8B, 0x54, 0x47, 0x5F, 0x7E, 0xB9, 0xA8, 0x82, 0x94, 0x10, 0x5B, 0xC4, 0x1A, 0xFF, 0xD5, + 0x86, 0xC4, 0x5B, 0x3D, 0x5E, 0xBC, 0xA8, 0x21, 0x33, 0x25, 0x8F, 0x14, 0x92, 0xA7, 0x4B, 0x20, 0x88, 0xEA, 0x10, 0x45, + 0x32, 0x63, 0x68, 0xA2, 0x51, 0x0C, 0xFE, 0xF2, 0xB0, 0x4F, 0xD8, 0xD4, 0x60, 0x9A, 0xA2, 0xB6, 0xBB, 0xF6, 0xB9, 0x30, + 0xD3, 0x4D, 0x85, 0x67, 0x6F, 0x24, 0x43, 0x32, 0x87, 0xE1, 0x85, 0x21, 0xF9, 0xE1, 0xF6, 0x77, 0x0E, 0xF5, 0x6E, 0x55, + 0x9D, 0xDE, 0x2D, 0xCC, 0xE0, 0x36, 0xE1, 0xF3, 0x87, 0x65, 0x60, 0xA0, 0x00, 0xA9, 0x39, 0x36, 0xB1, 0x22, 0x68, 0x50, + 0x0E, 0xEB, 0x00, 0xE0, 0x5C, 0xB3, 0xCF, 0xD2, 0xE9, 0x3A, 0xA8, 0xE7, 0xA8, 0x28, 0x26, 0x77, 0xA2, 0x4A, 0x29, 0x0F, + 0xF0, 0xC8, 0x4A, 0x71, 0x03, 0xA9, 0xB7, 0xDC, 0x33, 0xD9, 0xF1, 0x13, 0xA0, 0x81, 0xE9, 0x9E, 0xD4, 0x04, 0x31, 0x76, + 0x62, 0x08, 0xB1, 0x72, 0x32, 0xDF, 0xED, 0x0A, 0x60, 0x57, 0x4F, 0x44, 0x72, 0x25, 0x0A, 0x18, 0xE9, 0x13, 0xDA, 0x05, + 0x9A, 0x8F, 0xD8, 0x06, 0x03, 0xF3, 0x64, 0xCD, 0xFB, 0xC7, 0xCA, 0x61, 0x82, 0x08, 0xF2, 0x1E, 0x15, 0x41, 0xC2, 0xE7, + 0xA8, 0xE6, 0x1A, 0xB8, 0x60, 0xB4, 0xB5, 0xEF, 0x0D, 0xCB, 0x7B, 0x6F, 0xF0, 0xB0, 0x0B, 0xD1, 0x60, 0x08, 0x12, 0xDE, + 0x80, 0x91, 0x4D, 0x1C, 0x8F, 0x70, 0x84, 0x15, 0x70, 0x53, 0x92, 0xBD, 0xF8, 0x25, 0x87, 0x8D, 0x38, 0x6D, 0xBA, 0x4A, + 0x04, 0xB1, 0xBA, 0xCE, 0xF0, 0x7B, 0xEA, 0x93, 0xB7, 0xED, 0x12, 0x7F, 0xA1, 0xE7, 0x84, 0x88, 0x8F, 0x04, 0x32, 0x3E, + 0x96, 0xDB, 0x5F, 0x8B, 0xCF, 0xC0, 0x7A, 0x0E, 0x39, 0xAA, 0x31, 0x4D, 0xD6, 0xA3, 0xFB, 0xB2, 0x18, 0x89, 0x6B, 0x58, + 0x6B, 0xCF, 0x16, 0x5C, 0xB6, 0xC1, 0x4E, 0xA8, 0xD7, 0x93, 0x83, 0x58, 0xF0, 0xDF, 0x09, 0xCF, 0x20, 0x2B, 0xA5, 0x7A, + 0x22, 0x60, 0x90, 0x10, 0x26, 0x89, 0xCC, 0x81, 0x12, 0xE2, 0x74, 0x17, 0x4B, 0x5F, 0x81, 0xD7, 0x64, 0x1E, 0x5C, 0xBD, + 0x2D, 0x53, 0xF2, 0x8D, 0xB3, 0xD6, 0x45, 0x87, 0xC6, 0xFC, 0x80, 0x9D, 0xF3, 0x96, 0xE0, 0x05, 0xD3, 0x6F, 0x00, 0xF7, + 0x5B, 0x62, 0x6B, 0xF9, 0x0B, 0x02, 0xF7, 0xA7, 0xF1, 0x32, 0x45, 0xCF, 0x1D, 0xD9, 0xD1, 0x77, 0x31, 0x83, 0x96, 0x51, + 0xF3, 0x48, 0xC1, 0xD7, 0xD2, 0x33, 0xFC, 0x3F, 0x55, 0x14, 0xDC, 0xC1, 0x93, 0xB4, 0x74, 0x3D, 0xE5, 0xA6, 0x8E, 0x68, + 0x1A, 0x24, 0xF3, 0x32, 0x33, 0x58, 0xF2, 0xD8, 0xBE, 0xB3, 0x24, 0x74, 0x7D, 0x4D, 0x2E, 0x07, 0xFF, 0xC8, 0xF1, 0xBF, + 0x01, 0x73, 0xBD, 0xC1, 0xC1, 0xEC, 0x35, 0xA1, 0x0C, 0xDB, 0xAB, 0xE3, 0x13, 0xF5, 0x32, 0x29, 0xA3, 0x72, 0x4D, 0x15, + 0xFB, 0x75, 0x9D, 0xA1, 0xB6, 0x54, 0xA5, 0x05, 0x6D, 0x86, 0xB7, 0x59, 0xC9, 0xA7, 0xE6, 0x3F, 0xF7, 0x35, 0x23, 0xCE, + 0x97, 0x51, 0x8A, 0x85, 0x7E, 0x98, 0xCE, 0x6C, 0xF5, 0x5B, 0xB6, 0x67, 0x3F, 0x28, 0x15, 0x49, 0xCA, 0x49, 0x86, 0xB8, + 0x70, 0x6E, 0xD8, 0xE9, 0xDF, 0xAF, 0x78, 0x0F, 0x52, 0x04, 0xD7, 0x6F, 0xC4, 0xF5, 0x18, 0xD2, 0x99, 0x5A, 0xDB, 0xB7, + 0x2B, 0xBC, 0x8F, 0x1F, 0x5B, 0xA9, 0x2D, 0x3B, 0x03, 0xB5, 0xA1, 0xE4, 0xD8, 0x3B, 0x7D, 0x2A, 0x86, 0xA1, 0x02, 0x57, + 0xC5, 0x7D, 0x46, 0xFC, 0x8B, 0xE3, 0x16, 0x68, 0x0B, 0x83, 0xFA, 0xA7, 0x88, 0x78, 0x31, 0xAE, 0x59, 0xC2, 0xF6, 0x65, + 0xE9, 0x59, 0xA6, 0x78, 0x3D, 0x1E, 0x3F, 0xEE, 0x5F, 0x11, 0xF9, 0xC1, 0xDA, 0xC1, 0xA8, 0x6D, 0x9B, 0x03, 0x17, 0x69, + 0x0C, 0x83, 0x74, 0x3B, 0x07, 0xA2, 0x34, 0xAE, 0xAF, 0x51, 0x01, 0x9B, 0xE5, 0x3D, 0x73, 0x62, 0xC8, 0x3C, 0xBB, 0x86, + 0x7A, 0x0C, 0xF8, 0x17, 0x27, 0x95, 0x50, 0x20, 0x2F, 0xCD, 0xC6, 0x9C, 0xF7, 0xAC, 0xF1, 0x31, 0x3A, 0x88, 0xF1, 0x35, + 0xB2, 0xA7, 0x72, 0xAF, 0x65, 0xCC, 0xDA, 0x37, 0x54, 0x71, 0xFA, 0x90, 0xFB, 0x8B, 0x19, 0x67, 0xFB, 0x2F, 0xCE, 0xA6, + 0xCA, 0xA0, 0x72, 0x54, 0x8D, 0x8C, 0x77, 0x53, 0x89, 0x28, 0xDF, 0xC1, 0x34, 0xA8, 0xBD, 0xB7, 0xA6, 0x7B, 0x83, 0xC4, + 0x8C, 0x4C, 0xA0, 0x12, 0x55, 0x9F, 0x1F, 0xC4, 0xFC, 0x16, 0x4A, 0x80, 0xEA, 0x79, 0xCE, 0x53, 0x3E, 0xE9, 0x74, 0x73, + 0x34, 0x60, 0x90, 0x24, 0xFC, 0xF5, 0x40, 0x62, 0xE4, 0xC1, 0xA2, 0xF9, 0x3F, 0x04, 0xD7, 0xA5, 0x03, 0xE7, 0xD9, 0xA7, + 0x92, 0x26, 0x09, 0xE1, 0x2C, 0x74, 0x31, 0xE3, 0xE3, 0x59, 0xD1, 0x23, 0x83, 0x8E, 0x89, 0xE4, 0x34, 0xA8, 0x55, 0x82, + 0x9B, 0x5B, 0x87, 0x71, 0x36, 0x64, 0x2E, 0x0A, 0x77, 0x81, 0x23, 0x8C, 0xF6, 0xE7, 0x62, 0x0F, 0x5E, 0xA4, 0xB5, 0xC6, + 0xB0, 0xA7, 0xF8, 0x9E, 0x6E, 0x2B, 0x5C, 0xFF, 0xBE, 0x04, 0x22, 0xBB, 0xAC, 0xD2, 0x84, 0x32, 0xD0, 0x6F, 0x78, 0x84, + 0x8A, 0x73, 0xDB, 0xFC, 0x88, 0xAC, 0x0D, 0x77, 0x06, 0x92, 0xD3, 0x9C, 0x77, 0xE5, 0x7B, 0x8A, 0xC9, 0xC9, 0xA4, 0xD8, + 0x5F, 0x8B, 0x0E, 0xDD, 0x48, 0xAA, 0xBB, 0xFF, 0xD9, 0xC2, 0xE2, 0x2B, 0x26, 0x21, 0x82, 0xFD, 0xB9, 0xA3, 0x48, 0x82, + 0xA2, 0x83, 0x00, 0x9D, 0xD2, 0x51, 0xEA, 0x3B, 0x27, 0xCF, 0x9C, 0x88, 0xF6, 0xD5, 0x44, 0x23, 0xAD, 0xED, 0x0F, 0x8E, + 0x41, 0x1C, 0xAD, 0x9B, 0x0A, 0x85, 0x23, 0xA2, 0x71, 0xA8, 0x0D, 0x33, 0x4E, 0xF7, 0x8B, 0x7E, 0xB2, 0xEA, 0x61, 0x83, + 0xBC, 0x0A, 0x93, 0xB7, 0x27, 0xE2, 0x7D, 0x09, 0x24, 0x77, 0x3B, 0xFB, 0x13, 0x50, 0x51, 0xE0, 0x4C, 0x48, 0x9C, 0x79, + 0xBB, 0x36, 0x4C, 0x20, 0x8E, 0xEE, 0xB8, 0x0C, 0x56, 0x91, 0xD9, 0x70, 0x06, 0x31, 0xFE, 0x14, 0xDF, 0x26, 0xA5, 0xE7, + 0x63, 0x59, 0xC1, 0x5B, 0x51, 0x4E, 0x5D, 0xE1, 0x26, 0x35, 0xA5, 0x47, 0xB0, 0x9B, 0x6F, 0x4D, 0x47, 0x90, 0xBB, 0x5B, + 0x1E, 0x09, 0x4D, 0x20, 0x0A, 0x13, 0x95, 0xA6, 0xE6, 0xBC, 0xAA, 0x73, 0xA5, 0xDE, 0x7D, 0x4E, 0xDE, 0xE8, 0x1C, 0xB0, + 0x8A, 0x9B, 0x86, 0x86, 0x37, 0x1E, 0xB0, 0x32, 0x38, 0xD7, 0x0C, 0x0E, 0x4C, 0xB9, 0xD8, 0x30, 0xA5, 0x32, 0xCC, 0x16, + 0x62, 0x18, 0xC4, 0x70, 0x8D, 0x67, 0x50, 0x69, 0x9C, 0x25, 0xD1, 0x21, 0x0A, 0x99, 0xDB, 0xCB, 0x39, 0x30, 0x4D, 0xEA, + 0xD5, 0x77, 0x0A, 0x0F, 0xFF, 0xBB, 0x2A, 0x31, 0x25, 0x30, 0x6C, 0x90, 0xB9, 0x18, 0x05, 0xF1, 0xBB, 0x7A, 0x9D, 0x44, + 0xD1, 0xFA, 0x5E, 0x66, 0x84, 0xE3, 0xF6, 0x12, 0x78, 0xB5, 0x20, 0x72, 0xCF, 0xDE, 0x00, 0xC8, 0x87, 0x7F, 0x85, 0xF4, + 0xF8, 0x9F, 0x2F, 0x1C, 0xD7, 0x2E, 0x3B, 0x38, 0xED, 0x8C, 0xF4, 0xB8, 0x8A, 0x74, 0x3F, 0xD4, 0x11, 0x66, 0x0B, 0x1D, + 0xF8, 0xB0, 0x9C, 0x66, 0x4D, 0xD3, 0xB3, 0x36, 0x15, 0x10, 0x0F, 0x5F, 0x0C, 0x24, 0x97, 0xD8, 0x63, 0xB1, 0x07, 0xDB, + 0xE1, 0xB3, 0xE7, 0xBA, 0x08, 0x72, 0x21, 0xA8, 0xD1, 0xF0, 0x67, 0xBC, 0xD5, 0x5D, 0xF7, 0xFA, 0xEC, 0x7B, 0x09, 0x9E, + 0x32, 0xF5, 0x37, 0xE8, 0x8A, 0x22, 0x6F, 0x1E, 0x49, 0x10, 0x76, 0xBA, 0x63, 0x56, 0xE6, 0xFB, 0x82, 0xF6, 0x05, 0xDA, + 0xAD, 0x3D, 0xD9, 0xFA, 0x33, 0x18, 0x30, 0x09, 0x61, 0x58, 0xF6, 0x90, 0x9F, 0xDE, 0xD0, 0xEA, 0x0E, 0x3E, 0x79, 0xEE, + 0x1E, 0x3E, 0x77, 0x19, 0x6D, 0x78, 0x79, 0x17, 0x91, 0x74, 0x04, 0xE6, 0x80, 0x80, 0x40, 0x9A, 0x7B, 0x2F, 0xA3, 0x08, + 0xBC, 0x71, 0x27, 0xD4, 0x71, 0xC1, 0xC8, 0x80, 0x65, 0xFE, 0x9A, 0x75, 0x17, 0x63, 0x4D, 0xB4, 0x1D, 0xD2, 0x58, 0xA5, + 0x51, 0x65, 0x3B, 0xE9, 0xEE, 0x4D, 0x05, 0x76, 0xFC, 0xA7, 0x2F, 0x2D, 0xC6, 0xC0, 0x07, 0xD6, 0x54, 0xEF, 0xE5, 0x61, + 0x01, 0x85, 0xBF, 0xE4, 0x32, 0x43, 0xBA, 0x19, 0x1D, 0x72, 0x20, 0x0A, 0xC5, 0x21, 0x80, 0xC4, 0xF8, 0x09, 0x5C, 0xC0, + 0x1C, 0x8B, 0x54, 0x00, 0x56, 0x5F, 0xCD, 0x9A, 0x42, 0x26, 0x0A, 0xEE, 0x05, 0xA7, 0x17, 0x55, 0x37, 0x67, 0x15, 0x04, + 0xBD, 0x65, 0x3B, 0xB4, 0x47, 0x75, 0x21, 0xF7, 0x8A, 0x44, 0x2D, 0xDB, 0x93, 0x46, 0x44, 0x07, 0x3D, 0x04, 0x11, 0x0C, + 0x29, 0x08, 0x19, 0xE3, 0xFA, 0x94, 0x09, 0xD6, 0x64, 0x8A, 0xDD, 0x8C, 0xCB, 0x06, 0x19, 0xF1, 0xEA, 0xF8, 0xA2, 0x48, + 0x5C, 0xF5, 0xBC, 0x39, 0xF8, 0xA9, 0x2C, 0x24, 0x4E, 0xCA, 0xC2, 0x2C, 0x84, 0xA9, 0x42, 0x0D, 0xE8, 0x0F, 0xAA, 0xD6, + 0xF0, 0x79, 0xDA, 0x25, 0x3B, 0x0B, 0x65, 0xCD, 0x3D, 0x96, 0x19, 0x0B, 0x4A, 0xCE, 0x1B, 0x89, 0xDA, 0xB5, 0x46, 0xAD, + 0x8E, 0x28, 0xB3, 0x39, 0xB3, 0x9A, 0xFD, 0xF9, 0x2A, 0x0F, 0xD5, 0xFF, 0x95, 0x0E, 0xDB, 0x42, 0x4B, 0xAC, 0x5B, 0xB8, + 0x03, 0xC6, 0x22, 0x0A, 0xBF, 0x01, 0xC3, 0x8B, 0xCC, 0x24, 0x0B, 0x58, 0xEF, 0x73, 0xED, 0xAB, 0x88, 0x64, 0x3C, 0xB7, + 0xD6, 0x02, 0xF4, 0x51, 0xF9, 0x6D, 0x52, 0x44, 0xB7, 0x5D, 0xE1, 0x3B, 0x8D, 0x65, 0xBC, 0x6E, 0x2B, 0x08, 0x47, 0xB0, + 0x92, 0x6F, 0x6D, 0x61, 0x45, 0x78, 0x57, 0x90, 0xD2, 0x2F, 0xFF, 0x26, 0x28, 0x09, 0x48, 0x2E, 0xCB, 0x41, 0x80, 0x79, + 0xD9, 0x02, 0xDE, 0x95, 0xA7, 0x2D, 0xF6, 0x7D, 0x3E, 0x8B, 0x1C, 0x00, 0x36, 0x95, 0xE2, 0x3D, 0xC1, 0xAF, 0xE6, 0xA3, + 0x38, 0xDB, 0x8D, 0x14, 0x13, 0x11, 0x10, 0x10, 0x37, 0x94, 0x14, 0xB8, 0xE3, 0xB6, 0x23, 0x06, 0xB1, 0x11, 0xF7, 0x78, + 0x3E, 0x67, 0x45, 0x14, 0xDE, 0xB3, 0x2B, 0xA8, 0x6D, 0xA4, 0x12, 0x38, 0x70, 0x92, 0x53, 0xB9, 0xA1, 0xB7, 0x4D, 0x04, + 0xDF, 0xB2, 0x5E, 0x41, 0xE9, 0x5C, 0xC3, 0xA8, 0xD1, 0x31, 0x7C, 0x3F, 0x8E, 0x19, 0xC0, 0xE0, 0xDB, 0xA4, 0x94, 0x70, + 0x2D, 0x5C, 0x8D, 0xCD, 0x74, 0x36, 0x34, 0xF7, 0xDE, 0x1A, 0x95, 0xE8, 0x35, 0x77, 0x03, 0xF5, 0x65, 0x37, 0x64, 0x0A, + 0x75, 0x37, 0x25, 0x77, 0xAA, 0xEA, 0xDF, 0xC1, 0x91, 0xE7, 0xD1, 0x1C, 0xEA, 0x17, 0xF7, 0x1A, 0xC1, 0xC7, 0x14, 0x75, + 0x06, 0xE8, 0xD0, 0x2B, 0x3E, 0x91, 0x7E, 0xB1, 0xEF, 0xAC, 0xFB, 0xB2, 0x2D, 0x7D, 0x07, 0xA1, 0x94, 0x28, 0x9C, 0x08, + 0x3E, 0x9D, 0x36, 0xB9, 0x89, 0x5E, 0xD0, 0x0C, 0xFA, 0xDF, 0x98, 0xEB, 0x45, 0x75, 0x90, 0x18, 0x7B, 0xA6, 0x9F, 0xFF, + 0xAB, 0x19, 0xE6, 0x3E, 0xF9, 0xD2, 0xDE, 0x89, 0x49, 0xB5, 0x47, 0x1C, 0xD6, 0xBB, 0xE1, 0x31, 0x4B, 0xF7, 0xEA, 0x4F, + 0x54, 0xF7, 0x69, 0x95, 0xAA, 0x1A, 0xBB, 0xAD, 0x50, 0x6B, 0x57, 0xBD, 0x41, 0xB2, 0xA7, 0x42, 0xF7, 0x19, 0x26, 0x7E, + 0x26, 0x91, 0xC3, 0x0C, 0x6A, 0x2E, 0x52, 0xCC, 0x59, 0xAF, 0x14, 0x1C, 0xE4, 0xAD, 0x51, 0xAB, 0x7F, 0x12, 0xA8, 0xD5, + 0x38, 0x5D, 0xDD, 0x10, 0x5B, 0x10, 0x69, 0xF5, 0x7D, 0xC6, 0x3F, 0xB6, 0xAC, 0xBC, 0x07, 0x49, 0x83, 0x52, 0xEF, 0x17, + 0x08, 0x1E, 0x17, 0x69, 0x8B, 0xC1, 0x16, 0xFC, 0x0E, 0x0F, 0x10, 0xDC, 0x9F, 0x24, 0xA0, 0x11, 0x8F, 0x12, 0x43, 0x79, + 0xF5, 0xD0, 0xA2, 0x80, 0xEA, 0x8B, 0x3C, 0x74, 0xFF, 0x41, 0xF7, 0x5D, 0xE7, 0xC6, 0x22, 0x61, 0x96, 0xE0, 0xFB, 0x81, + 0xE4, 0x9A, 0x29, 0xD6, 0x3B, 0xE3, 0xF8, 0xB6, 0xBF, 0xCC, 0x86, 0x02, 0x97, 0xF0, 0x7B, 0x02, 0x27, 0xC0, 0x9F, 0x32, + 0x19, 0x04, 0xC7, 0xBF, 0x2D, 0xF3, 0xF9, 0x23, 0x5D, 0x3B, 0xF8, 0xF5, 0xB6, 0x70, 0x6D, 0xB9, 0xFE, 0xAC, 0x95, 0xBC, + 0x24, 0x95, 0xB1, 0x33, 0x5C, 0x3A, 0x48, 0x38, 0xA7, 0x7B, 0x82, 0x56, 0x15, 0x44, 0x97, 0x99, 0xA7, 0x12, 0x30, 0x0F, + 0xDB, 0x52, 0x17, 0x0D, 0xA4, 0xE0, 0xEC, 0x96, 0x1B, 0x5E, 0xBC, 0xF7, 0x04, 0x36, 0x68, 0x9E, 0x6F, 0xA7, 0xD5, 0x21, + 0x04, 0x21, 0xDF, 0x5F, 0x1B, 0x20, 0x0A, 0x8B, 0xE0, 0x8B, 0xB9, 0x62, 0xA9, 0xC6, 0xD6, 0xB1, 0x05, 0x8B, 0xED, 0x73, + 0x91, 0x25, 0xA0, 0x73, 0xBF, 0x78, 0x39, 0x65, 0x28, 0x89, 0xDA, 0xE2, 0x68, 0x03, 0x20, 0x8A, 0x1A, 0x7E, 0x3A, 0x22, + 0xCE, 0x2F, 0x94, 0x1A, 0x00, 0xAA, 0xD2, 0xF2, 0x29, 0xC6, 0xB6, 0x9A, 0x1B, 0x0C, 0x1A, 0x2B, 0xAC, 0xCF, 0x1A, 0x2F, + 0xBC, 0x46, 0xDC, 0xED, 0xBF, 0xF9, 0x63, 0x9E, 0xF2, 0x2B, 0x74, 0xDB, 0xC4, 0xC5, 0xF5, 0x8F, 0x23, 0x6D, 0x72, 0xB3, + 0x2A, 0x50, 0x6B, 0x8E, 0xF3, 0x2A, 0xCD, 0xA2, 0x6E, 0xCD, 0x3C, 0x3D, 0xDF, 0x16, 0x9B, 0x28, 0xF1, 0xE9, 0x70, 0x3E, + 0x52, 0xA5, 0xCB, 0xD2, 0xBD, 0xF1, 0x94, 0x66, 0x5F, 0x7C, 0xC5, 0xB8, 0xA3, 0x70, 0xD2, 0xA1, 0xEA, 0xC1, 0x85, 0x04, + 0xD9, 0x12, 0x3A, 0xFB, 0xF6, 0xE5, 0x5B, 0xC9, 0x64, 0x71, 0xE4, 0xCD, 0x70, 0x7C, 0x8E, 0x2C, 0x33, 0xB8, 0x4C, 0xFC, + 0xCE, 0x11, 0x13, 0xD9, 0x0E, 0x10, 0x0C, 0x9F, 0x93, 0x54, 0x97, 0x04, 0x15, 0x52, 0x7F, 0x82, 0xD7, 0xAE, 0x7E, 0x0F, + 0x4C, 0x71, 0xFA, 0x64, 0x70, 0x35, 0x0A, 0xAE, 0xA6, 0xD2, 0x70, 0x76, 0x2A, 0xF1, 0x39, 0x61, 0x1D, 0x1C, 0x2D, 0xD1, + 0xF7, 0xB3, 0x02, 0xBE, 0xE8, 0x57, 0xBC, 0x32, 0x43, 0x66, 0xE5, 0x07, 0x68, 0x33, 0x5A, 0x85, 0x84, 0x1F, 0x3D, 0xA7, + 0x4C, 0x3B, 0x8D, 0xA2, 0xF2, 0xEA, 0x7B, 0xBB, 0x4E, 0x82, 0xA5, 0xBF, 0x5C, 0xE3, 0x3C, 0xF3, 0xC3, 0x5E, 0xDD, 0x04, + 0x4A, 0xB1, 0xA4, 0x52, 0x94, 0x8F, 0xF3, 0x42, 0x30, 0x8D, 0x98, 0x7D, 0x67, 0xB4, 0x18, 0x78, 0x77, 0x94, 0xAC, 0x42, + 0x95, 0x60, 0xE4, 0x52, 0x31, 0x62, 0x90, 0x60, 0x63, 0xDD, 0xFC, 0xD2, 0xF5, 0xFD, 0x69, 0xA5, 0x95, 0xA5, 0x1A, 0x00, + 0x60, 0xBE, 0xAA, 0xE2, 0xC2, 0x0B, 0x2A, 0xE6, 0xD2, 0x0D, 0xFF, 0xF7, 0xCC, 0x67, 0xD5, 0x29, 0x4A, 0xDB, 0xF9, 0x0E, + 0xEF, 0x96, 0x4B, 0x95, 0x00, 0xF1, 0x7C, 0x05, 0x44, 0x79, 0xC4, 0xCE, 0x3F, 0xF9, 0x48, 0x9F, 0x85, 0x39, 0xF0, 0xC7, + 0x95, 0xC8, 0xD3, 0xE8, 0x1B, 0xC6, 0x38, 0xD9, 0xF7, 0xE9, 0x2A, 0x3E, 0x63, 0x8E, 0x41, 0x3C, 0x97, 0x06, 0xE7, 0x0F, + 0xDD, 0xEB, 0x9D, 0x7C, 0xD0, 0x17, 0x9B, 0x38, 0xF8, 0xD0, 0xCF, 0x2B, 0xFA, 0xDC, 0x29, 0xAE, 0x2D, 0xA5, 0xE7, 0x82, + 0xBB, 0xF9, 0x61, 0x59, 0xE1, 0x99, 0x85, 0x5D, 0x51, 0x06, 0x99, 0x37, 0xD1, 0xDD, 0x05, 0x8E, 0x58, 0x47, 0x2F, 0x46, + 0xCB, 0x5B, 0xFE, 0xD9, 0xDF, 0x90, 0x14, 0xBA, 0x3F, 0xDF, 0xF4, 0xDB, 0x1C, 0x0C, 0xBE, 0x7E, 0x56, 0x22, 0x7A, 0x39, + 0xFF, 0xDD, 0x3E, 0xE3, 0x0B, 0x61, 0xE3, 0xEB, 0x57, 0x2E, 0xF7, 0x7A, 0xDD, 0x9F, 0x14, 0xA8, 0x20, 0xF6, 0x22, 0xAF, + 0x52, 0x16, 0xB6, 0xE6, 0xB9, 0xFD, 0x48, 0xF2, 0xE9, 0x64, 0x53, 0x3F, 0x5C, 0xBE, 0x3E, 0xC9, 0x23, 0x40, 0xBA, 0x80, + 0x31, 0xE3, 0xC4, 0x53, 0x6E, 0x2C, 0x47, 0x57, 0x66, 0xB6, 0x2B, 0x0E, 0x37, 0xF5, 0x64, 0x86, 0x19, 0x2B, 0x1C, 0x30, + 0x22, 0xBE, 0x9E, 0x91, 0x32, 0x21, 0x1D, 0x09, 0x86, 0xB9, 0xBF, 0xB0, 0xB1, 0x80, 0x73, 0x29, 0xC1, 0x02, 0xEF, 0x99, + 0xD9, 0xB8, 0xDC, 0x95, 0xA0, 0x03, 0x09, 0x54, 0x81, 0x8E, 0x67, 0x89, 0x2A, 0xF0, 0x8F, 0x98, 0x3A, 0x10, 0x97, 0x3E, + 0x68, 0x57, 0xD5, 0xC0, 0x3E, 0x14, 0x48, 0x75, 0xB5, 0x21, 0x22, 0x02, 0xDD, 0xE2, 0x88, 0x30, 0x3B, 0x08, 0x58, 0xA4, + 0x1B, 0x2A, 0x0D, 0xE3, 0x33, 0xE8, 0xDC, 0x76, 0x15, 0xF8, 0x3F, 0xFD, 0x8B, 0xDC, 0xC7, 0xE0, 0x9A, 0x02, 0x69, 0x9E, + 0x4D, 0xEB, 0xD5, 0xA5, 0xF6, 0xED, 0x53, 0x50, 0xA0, 0x47, 0x7E, 0xF8, 0x67, 0x74, 0xCC, 0x01, 0x43, 0x58, 0x87, 0x97, + 0x9B, 0xE2, 0x7C, 0xA0, 0xA4, 0x05, 0x57, 0x9F, 0x5B, 0x87, 0x2C, 0x8D, 0xAA, 0x58, 0xA8, 0x9D, 0x6E, 0xC7, 0xF7, 0xF4, + 0x09, 0xDC, 0x8A, 0xEF, 0x6B, 0x01, 0x1B, 0xBA, 0x69, 0xBF, 0xD2, 0xA4, 0xB0, 0x03, 0x7D, 0xA0, 0x61, 0x80, 0xD4, 0x7E, + 0xAE, 0xAC, 0x13, 0x69, 0xCC, 0x62, 0x42, 0xA9, 0xF9, 0x21, 0xDA, 0x26, 0xB7, 0xB4, 0x8A, 0x0C, 0xB7, 0x86, 0x0D, 0x5B, + 0xE6, 0x6B, 0xD9, 0xC2, 0x30, 0x88, 0x5E, 0x58, 0x0C, 0x05, 0x02, 0xAD, 0x01, 0x6D, 0x6C, 0xC0, 0x2B, 0x48, 0xC0, 0x7D, + 0xA1, 0xB1, 0x42, 0x44, 0x0D, 0x04, 0xF4, 0x90, 0x96, 0x4F, 0x64, 0xD1, 0x95, 0x90, 0x83, 0xCA, 0xFE, 0xE4, 0x43, 0xCD, + 0xAB, 0xAC, 0xF9, 0xBE, 0xFE, 0xD1, 0x32, 0x29, 0xB3, 0x20, 0x3F, 0xF6, 0xDB, 0x5C, 0x53, 0x99, 0xC7, 0xA2, 0xB5, 0x68, + 0x72, 0xB5, 0x41, 0x7B, 0x78, 0xE2, 0xDF, 0x1D, 0xCF, 0xE4, 0xA3, 0xBC, 0x5B, 0xB0, 0x3A, 0x01, 0xDB, 0x13, 0x6B, 0xD3, + 0x0E, 0x3C, 0xAF, 0x20, 0x51, 0xB3, 0x0D, 0x14, 0x7D, 0x37, 0x5C, 0xE7, 0x45, 0xE4, 0x1D, 0xC3, 0x5F, 0xA0, 0x5C, 0xD4, + 0x56, 0x7B, 0xC5, 0xE1, 0x2C, 0xA9, 0xBB, 0xB9, 0xBE, 0x9D, 0x72, 0xE1, 0xE4, 0x7A, 0xAB, 0x10, 0xD1, 0x70, 0xAE, 0xAC, + 0x7D, 0x10, 0x9A, 0x7D, 0xBD, 0xEF, 0x63, 0x08, 0x14, 0x57, 0x18, 0x31, 0xD0, 0x19, 0x1E, 0xA0, 0x4A, 0xA7, 0x40, 0x64, + 0x74, 0xE4, 0x02, 0x73, 0x40, 0xF9, 0xA2, 0x02, 0x41, 0xD3, 0x1A, 0x68, 0xC8, 0x71, 0x95, 0xEE, 0x96, 0x83, 0x54, 0x5C, + 0x65, 0x5C, 0xD4, 0xE4, 0xF4, 0x07, 0x3B, 0xC7, 0xC1, 0x33, 0xFB, 0xF1, 0x49, 0x5A, 0xC2, 0x65, 0xC3, 0x57, 0x6D, 0x22, + 0x30, 0x26, 0x75, 0x2E, 0x2C, 0xBA, 0x35, 0x5D, 0x16, 0xB1, 0x5D, 0x75, 0xC2, 0xF5, 0xE7, 0x13, 0xD1, 0x05, 0x5F, 0xA6, + 0x8D, 0x13, 0x36, 0xFB, 0x36, 0xE4, 0x86, 0xB9, 0x46, 0xF5, 0xA8, 0x01, 0x00, 0xD7, 0xF1, 0x70, 0xAF, 0x54, 0x22, 0xEF, + 0x4D, 0xCF, 0x24, 0x08, 0x96, 0x1B, 0x98, 0x19, 0x1A, 0xA6, 0x82, 0x61, 0x62, 0x57, 0x43, 0x47, 0x0B, 0xC5, 0x5D, 0x99, + 0x17, 0xA5, 0x40, 0xD7, 0x78, 0x2B, 0xE3, 0x06, 0xA8, 0x8B, 0xF1, 0xA1, 0x50, 0x8A, 0x07, 0x0C, 0xEF, 0x52, 0x89, 0x10, + 0x12, 0x08, 0x10, 0x57, 0x49, 0x18, 0xC6, 0x2A, 0x09, 0x49, 0x5E, 0xC8, 0x6C, 0x55, 0x13, 0x04, 0x90, 0x31, 0x06, 0xDC, + 0x02, 0x9D, 0x8E, 0x7C, 0x21, 0x7D, 0x0C, 0x1E, 0x7B, 0xF0, 0x53, 0x9C, 0x7F, 0xF0, 0x3E, 0xB8, 0xC8, 0x08, 0x7F, 0xC5, + 0x98, 0xD3, 0x4F, 0x29, 0xA6, 0xF3, 0xC1, 0xD9, 0x5D, 0xD3, 0x43, 0x27, 0xAD, 0x16, 0x27, 0x55, 0x3C, 0x0D, 0x09, 0x1F, + 0xD8, 0x19, 0x27, 0x15, 0x11, 0x32, 0x7B, 0x02, 0x02, 0x70, 0xEA, 0x36, 0xEB, 0x5F, 0x87, 0x23, 0xCB, 0xE0, 0x1C, 0xB9, + 0x57, 0xA2, 0xF9, 0x2D, 0x3B, 0x3D, 0x68, 0x76, 0x04, 0x0C, 0x6F, 0x13, 0xD1, 0xE0, 0x86, 0x9B, 0x9F, 0x6B, 0x45, 0x1C, + 0xEA, 0x57, 0x9B, 0xB7, 0x6B, 0x7D, 0xCC, 0x02, 0x9A, 0xE3, 0x71, 0x47, 0xDB, 0x8E, 0x94, 0x48, 0xF6, 0x83, 0x7B, 0x77, + 0xC5, 0xCD, 0x48, 0x12, 0x52, 0x81, 0xC7, 0x8A, 0x3C, 0xB0, 0x32, 0xA4, 0x16, 0x29, 0xF8, 0x57, 0x7D, 0x65, 0x21, 0x12, + 0xC6, 0xD2, 0x70, 0x80, 0x44, 0xA9, 0x84, 0x21, 0x6D, 0x23, 0x9E, 0xFC, 0xB6, 0x22, 0xC6, 0xF7, 0xB4, 0x38, 0xBD, 0x04, + 0x64, 0x22, 0x37, 0xA5, 0x8F, 0x58, 0xE5, 0xBA, 0x92, 0xA0, 0x79, 0xBF, 0x33, 0x83, 0xE7, 0x53, 0x71, 0xE2, 0xB9, 0x20, + 0xAD, 0xC5, 0xED, 0xD7, 0x76, 0xA8, 0xBD, 0x88, 0x2E, 0xB6, 0x01, 0xFF, 0x70, 0xE3, 0xE2, 0x17, 0x86, 0x3C, 0xC0, 0x0F, + 0x1F, 0xE8, 0x2A, 0x7A, 0xA5, 0xA2, 0xD0, 0x2E, 0xB7, 0x3B, 0x32, 0x1D, 0x55, 0xCB, 0x66, 0x5F, 0x0D, 0x09, 0x96, 0xA1, + 0x4E, 0x6B, 0x84, 0xEE, 0xA6, 0x72, 0xF1, 0xF2, 0xC0, 0xC8, 0xAF, 0x07, 0x9A, 0xA3, 0x71, 0xD0, 0x25, 0x29, 0xBF, 0xF3, + 0x94, 0x89, 0xAC, 0x98, 0x59, 0x3A, 0x7F, 0x6C, 0xE5, 0xEE, 0x05, 0xFE, 0xAD, 0x14, 0xBB, 0x0E, 0x7C, 0x14, 0x7A, 0x6A, + 0x0D, 0xCC, 0xBB, 0xFD, 0xB9, 0x07, 0xC2, 0x1D, 0x40, 0x13, 0xB6, 0x86, 0xB4, 0xA1, 0x10, 0xBA, 0x03, 0x20, 0x12, 0xAF, + 0x7B, 0x6B, 0x04, 0xCB, 0xBA, 0x5E, 0xFC, 0x00, 0x81, 0xA2, 0x7F, 0x5B, 0x67, 0x3D, 0xBF, 0xD9, 0xAD, 0xF9, 0x4D, 0x53, + 0xC0, 0x7F, 0x08, 0xA8, 0x00, 0xE6, 0x38, 0xA9, 0xAE, 0x1D, 0x34, 0xC9, 0xBD, 0x9D, 0x05, 0xCB, 0x40, 0x62, 0xDB, 0x6F, + 0x3E, 0xF4, 0x1A, 0xBF, 0x80, 0x7D, 0x47, 0x75, 0x4C, 0xF2, 0xEC, 0x62, 0x22, 0x7D, 0xEE, 0x59, 0x1E, 0xA3, 0x7C, 0x17, + 0xCE, 0x92, 0xB4, 0x0A, 0xDC, 0xDB, 0x02, 0x06, 0xE8, 0x27, 0xE4, 0xB2, 0x5C, 0x71, 0xE1, 0x70, 0xD8, 0x3F, 0xBD, 0xD7, + 0x5D, 0x71, 0x7F, 0x93, 0x13, 0x2D, 0xCB, 0x0B, 0x1D, 0x31, 0x13, 0xAF, 0x51, 0x22, 0xEF, 0x6C, 0x5C, 0x50, 0x35, 0xB7, + 0xEC, 0xC3, 0x83, 0x02, 0xD6, 0xB3, 0x71, 0xA0, 0x47, 0xB4, 0xBD, 0xE9, 0x55, 0x94, 0xCC, 0xF2, 0xC1, 0x96, 0x18, 0x74, + 0x66, 0xFC, 0x52, 0x6B, 0x4F, 0x98, 0x14, 0xF6, 0x29, 0x7F, 0x79, 0xCD, 0x59, 0x00, 0x1E, 0x02, 0x7F, 0xB4, 0x3D, 0xC7, + 0x8F, 0x16, 0x1D, 0xCF, 0xD5, 0x27, 0x6D, 0xCA, 0xE0, 0xB7, 0x73, 0x95, 0x51, 0xED, 0x92, 0xA0, 0xD5, 0xD5, 0xB4, 0x2F, + 0x12, 0x68, 0xAC, 0x77, 0x94, 0x47, 0xED, 0x62, 0xB3, 0xF6, 0x7F, 0x8E, 0xF9, 0xDD, 0x0A, 0x15, 0x3F, 0x3A, 0xF6, 0xCA, + 0x53, 0x7B, 0xAA, 0xBE, 0x7A, 0xF1, 0x47, 0x70, 0xC6, 0xDA, 0x7F, 0x6D, 0x4F, 0xD5, 0x3F, 0xAB, 0x43, 0x74, 0xED, 0x42, + 0x7D, 0x54, 0x99, 0x0E, 0x79, 0xF8, 0x67, 0xEF, 0x83, 0x19, 0xE6, 0x58, 0x9E, 0xF2, 0x6A, 0x1E, 0xCA, 0x55, 0x8C, 0x3A, + 0x4C, 0x34, 0x91, 0x32, 0x63, 0x14, 0x75, 0x8B, 0xE5, 0x24, 0x6A, 0x8E, 0xBE, 0x54, 0x7E, 0xDF, 0xC5, 0xED, 0xB8, 0x2C, + 0x76, 0x39, 0x56, 0x6E, 0xE1, 0x71, 0xB5, 0xEB, 0x5E, 0x7E, 0x50, 0x67, 0x47, 0x90, 0xCE, 0xB8, 0xCC, 0xD3, 0x2A, 0x7E, + 0x4E, 0xDC, 0xC0, 0xB3, 0x5C, 0x15, 0xD3, 0xA9, 0x45, 0x0F, 0xF5, 0xDE, 0x45, 0xA5, 0x21, 0x78, 0xC8, 0x73, 0x6C, 0x6B, + 0x9F, 0x0F, 0x90, 0xA8, 0xD9, 0xDD, 0x88, 0x9F, 0xEF, 0xA4, 0x77, 0xEF, 0xE9, 0xD6, 0xA6, 0xE4, 0x5A, 0x20, 0x01, 0x66, + 0xFF, 0xDD, 0xE2, 0x04, 0xB7, 0x8B, 0xAA, 0xA5, 0x4E, 0xCA, 0x7C, 0x5B, 0x9A, 0x3A, 0x32, 0x8F, 0xFE, 0x8C, 0xD0, 0x9C, + 0xB9, 0x0C, 0xA7, 0xBF, 0x22, 0x45, 0xF9, 0x74, 0x01, 0x7A, 0x51, 0x76, 0xCC, 0x6E, 0xDD, 0x99, 0x79, 0x09, 0xC6, 0xDA, + 0x7F, 0x2C, 0xCB, 0x27, 0x63, 0xBB, 0xEA, 0xEF, 0x87, 0xE0, 0x49, 0xA0, 0xAE, 0x38, 0x60, 0x4F, 0xA0, 0x47, 0xE8, 0x4F, + 0x76, 0x73, 0x22, 0x51, 0x03, 0x34, 0x00, 0xF1, 0x70, 0xB9, 0xF3, 0x48, 0x9A, 0xA5, 0x8A, 0x4A, 0xF1, 0x01, 0xD8, 0x22, + 0x30, 0x52, 0xCE, 0x6D, 0xFA, 0x94, 0x78, 0x8E, 0xB8, 0xDA, 0xA0, 0x53, 0x30, 0x30, 0x18, 0xD7, 0xE5, 0x66, 0xB9, 0x62, + 0x6B, 0x29, 0x72, 0x55, 0x23, 0xBD, 0x8B, 0xB4, 0x71, 0x03, 0xB1, 0x75, 0x06, 0x85, 0x91, 0x51, 0xDB, 0xB6, 0xEC, 0x58, + 0x77, 0x56, 0xA1, 0x52, 0x3A, 0x36, 0x8D, 0xCF, 0xD6, 0xD5, 0x64, 0x7A, 0x95, 0x4A, 0x73, 0xE8, 0x10, 0xF5, 0xAD, 0xCA, + 0x33, 0x43, 0x10, 0x1A, 0x9B, 0x01, 0xD0, 0x1E, 0xAA, 0xF0, 0xDA, 0x8D, 0x0D, 0x41, 0x25, 0xAF, 0x35, 0xE2, 0x19, 0x0B, + 0x3B, 0x97, 0xFC, 0x4A, 0x65, 0x9C, 0xEC, 0x6E, 0x29, 0xBC, 0x71, 0x2F, 0x9D, 0x04, 0x89, 0x47, 0x78, 0xD7, 0xEA, 0xDD, + 0x95, 0x80, 0x9F, 0x19, 0xDF, 0xD2, 0xBB, 0xD7, 0xAC, 0x7D, 0xEA, 0xDD, 0x8F, 0xCE, 0xE2, 0xFA, 0x1C, 0xCF, 0x67, 0x5D, + 0xFA, 0x8D, 0xAA, 0x4B, 0xB3, 0x1D, 0x4A, 0x78, 0x49, 0x4D, 0x95, 0x5C, 0x68, 0x21, 0x72, 0x1A, 0xB6, 0x41, 0xA2, 0x5B, + 0xB2, 0x1C, 0xEB, 0xD1, 0x8C, 0x17, 0xB3, 0xC9, 0xF4, 0x81, 0x93, 0xE9, 0xCF, 0x93, 0xAB, 0x4A, 0x33, 0x3F, 0x77, 0xC6, + 0x09, 0x0B, 0x0B, 0xB9, 0xBA, 0xF4, 0x63, 0xFB, 0x4B, 0xAE, 0xA3, 0x7F, 0xDD, 0xE2, 0xFC, 0x82, 0x00, 0x52, 0x82, 0x00, + 0x5E, 0x70, 0xAC, 0x5B, 0xED, 0xAD, 0x5D, 0x4B, 0x91, 0xF6, 0xB4, 0xA1, 0x45, 0x5E, 0x94, 0x8D, 0xBE, 0x97, 0xE7, 0x8B, + 0x0D, 0xCA, 0x79, 0xDA, 0x10, 0x75, 0xD3, 0x5A, 0x93, 0xDE, 0xCD, 0x04, 0x59, 0x19, 0x72, 0x5E, 0x15, 0xC4, 0x95, 0x4B, + 0x7D, 0x8F, 0xB5, 0x56, 0x63, 0x33, 0x1F, 0xD5, 0xF9, 0x71, 0x1D, 0x76, 0x1C, 0xE5, 0xE4, 0xCB, 0x90, 0x77, 0x1C, 0xC4, + 0xD3, 0xCD, 0x9B, 0xD1, 0x34, 0xFF, 0x54, 0xA0, 0x3F, 0xD9, 0x95, 0x92, 0xB0, 0x74, 0x97, 0xD2, 0x5C, 0xB4, 0xD4, 0x2C, + 0xEF, 0x8E, 0xF0, 0x83, 0x1B, 0x4E, 0x64, 0x0E, 0x63, 0x38, 0x5D, 0xC5, 0x0B, 0xE0, 0xED, 0x39, 0x5E, 0xCD, 0x2B, 0xD9, + 0x09, 0xE7, 0xDD, 0xD1, 0xC1, 0x1A, 0x12, 0xC4, 0xA5, 0x6C, 0x86, 0x3D, 0x21, 0xFA, 0x38, 0x67, 0x0A, 0xC6, 0xA2, 0x71, + 0x9D, 0x9B, 0x0E, 0x09, 0xC9, 0x57, 0x50, 0xF2, 0xB8, 0x58, 0x4C, 0xAA, 0xDB, 0x81, 0xF7, 0x6C, 0x6C, 0x63, 0x06, 0x98, + 0x2A, 0xF9, 0xD2, 0x7C, 0x3D, 0x77, 0x6B, 0xDE, 0x11, 0x16, 0xA1, 0x5A, 0x12, 0x52, 0x57, 0x19, 0xF8, 0x58, 0xBD, 0x7E, + 0x93, 0x97, 0x76, 0xE9, 0xFC, 0x41, 0xE6, 0xD7, 0x5F, 0x6A, 0x56, 0x0F, 0xCE, 0x9B, 0xC8, 0xBD, 0xE3, 0x7B, 0x5E, 0xDF, + 0x9B, 0x5F, 0x1E, 0xCE, 0xD2, 0x70, 0xFE, 0xB7, 0x0B, 0x5C, 0x3F, 0xC4, 0xDF, 0x43, 0x17, 0x7E, 0x6B, 0x1C, 0xDE, 0xF9, + 0x58, 0xFE, 0x91, 0xB8, 0xD3, 0xD7, 0x18, 0x7E, 0xCE, 0x31, 0x0C, 0x9A, 0x9C, 0x38, 0x1A, 0x8F, 0x6C, 0x11, 0x7B, 0x56, + 0xDD, 0xB8, 0x07, 0xB0, 0x3F, 0x7C, 0x6B, 0x10, 0xEC, 0xBD, 0x11, 0x2B, 0xB4, 0x7A, 0x7C, 0x08, 0xAD, 0xB4, 0xF7, 0xA2, + 0x3A, 0x32, 0x67, 0x16, 0x7E, 0x82, 0x1B, 0x02, 0x74, 0xC2, 0x8F, 0x79, 0xD9, 0x9B, 0xFC, 0x90, 0x36, 0x22, 0x0E, 0xC3, + 0xCB, 0x66, 0xB8, 0xA2, 0x67, 0xE6, 0x60, 0x96, 0xF0, 0xCE, 0x84, 0x0F, 0xFC, 0x8A, 0xEE, 0x4C, 0xC5, 0xA1, 0xE1, 0x9C, + 0x88, 0xAE, 0x52, 0x87, 0xEA, 0x32, 0xA7, 0x27, 0xDA, 0xE2, 0xA3, 0x63, 0x8C, 0x80, 0x09, 0xD8, 0xC4, 0xAF, 0x28, 0x6C, + 0x22, 0x80, 0x45, 0x84, 0xF1, 0xAB, 0x03, 0xC0, 0xEE, 0x6E, 0xB8, 0x48, 0x72, 0x48, 0x76, 0x20, 0xF1, 0xE1, 0x47, 0xBB, + 0x45, 0x11, 0x48, 0x9C, 0xEA, 0xC9, 0x90, 0xD1, 0x31, 0xEB, 0xEC, 0x2C, 0x66, 0xD0, 0xF0, 0xBE, 0x85, 0x68, 0x42, 0x99, + 0xF4, 0xCB, 0x4C, 0x94, 0xD2, 0x67, 0x59, 0x33, 0xCD, 0x8D, 0x74, 0xAB, 0x7A, 0xDD, 0x8C, 0x2D, 0x33, 0x9A, 0x45, 0x85, + 0x7A, 0xE9, 0x71, 0x57, 0x2E, 0x71, 0x97, 0xE6, 0x87, 0x6A, 0x41, 0x8C, 0x44, 0xCA, 0xA0, 0xE5, 0x30, 0xF7, 0x60, 0x06, + 0x0A, 0x80, 0xA4, 0x8A, 0x72, 0x75, 0x6E, 0xCA, 0x48, 0x86, 0xEE, 0xB2, 0xDC, 0xD9, 0xFC, 0xC1, 0x8D, 0x88, 0xF6, 0x9A, + 0x73, 0x51, 0xFA, 0x8F, 0x72, 0xD2, 0x5D, 0xC1, 0xAC, 0x3F, 0x23, 0xCB, 0xC4, 0xC8, 0x83, 0x0A, 0x7D, 0x05, 0x74, 0x8B, + 0x96, 0x93, 0x73, 0x9A, 0xCD, 0x86, 0x72, 0x4D, 0xEE, 0xCB, 0x6B, 0xAA, 0x50, 0xA1, 0x4A, 0x5D, 0x3E, 0xDB, 0x40, 0x78, + 0x3C, 0x4D, 0x02, 0x48, 0x36, 0x81, 0x9C, 0xFA, 0x18, 0x55, 0x89, 0xEE, 0x4C, 0x70, 0x08, 0xEA, 0x63, 0x54, 0x0A, 0x58, + 0x63, 0x80, 0xF2, 0xB6, 0x8D, 0x60, 0x96, 0x09, 0x73, 0x4B, 0xB4, 0xA3, 0xD0, 0xF6, 0x98, 0x6C, 0x2F, 0x71, 0xB8, 0xB3, + 0x72, 0x55, 0xD0, 0x47, 0x12, 0xBF, 0xA3, 0xFF, 0xD2, 0xAC, 0x10, 0x7C, 0x2E, 0x76, 0x12, 0x57, 0x7A, 0xD0, 0x84, 0x08, + 0xFB, 0x49, 0x9D, 0x09, 0x1D, 0xCF, 0x8C, 0xAE, 0x00, 0x91, 0x90, 0xF0, 0xDD, 0xC8, 0x20, 0xE5, 0x85, 0x76, 0xB2, 0x4E, + 0xB2, 0x3B, 0x7C, 0x07, 0x21, 0xB4, 0x61, 0xF4, 0x16, 0x81, 0x3C, 0x48, 0xE8, 0x2C, 0xD8, 0xD0, 0xBF, 0xAB, 0x67, 0x87, + 0x0C, 0xD3, 0xFD, 0x9A, 0x36, 0x6E, 0xA3, 0x58, 0x05, 0x54, 0x35, 0x83, 0x79, 0xE9, 0xBD, 0x7B, 0x27, 0xDE, 0x01, 0xEC, + 0x7F, 0x8B, 0x5A, 0xC9, 0x84, 0xD7, 0xE7, 0xB5, 0xF3, 0x10, 0xAB, 0xDD, 0x1E, 0x40, 0xDA, 0xEB, 0xC2, 0xE5, 0xDD, 0x8C, + 0x48, 0x72, 0x13, 0x16, 0xF6, 0xEB, 0xFE, 0xAC, 0xA6, 0x98, 0x47, 0x73, 0xE2, 0xAB, 0xED, 0xCD, 0x5B, 0x58, 0x14, 0x6E, + 0xF0, 0x77, 0x74, 0xD8, 0xCA, 0x02, 0xBC, 0xD2, 0x3B, 0xD5, 0x4D, 0x08, 0x55, 0x03, 0xEE, 0x6D, 0xF7, 0xB6, 0xD2, 0x91, + 0x06, 0xD5, 0x90, 0x2C, 0x66, 0x6A, 0x06, 0x08, 0xE1, 0xD5, 0x26, 0xD4, 0x88, 0xFE, 0xDD, 0x82, 0x89, 0x67, 0x9D, 0x1D, + 0x2D, 0xB0, 0x4F, 0xD4, 0x0D, 0xDC, 0x72, 0x6E, 0x3A, 0xBA, 0x48, 0xD2, 0x2C, 0xD9, 0x78, 0xD6, 0xB0, 0x4F, 0x67, 0x11, + 0xC8, 0x7F, 0xE7, 0x10, 0xD8, 0x58, 0x8B, 0x18, 0xB5, 0x47, 0x27, 0x8D, 0x91, 0xF8, 0x56, 0x6B, 0xB0, 0xB6, 0x61, 0xAB, + 0xFF, 0xD8, 0x1B, 0x83, 0x9E, 0x7D, 0x50, 0xE5, 0x6B, 0x64, 0xA9, 0x5D, 0xFF, 0x96, 0x2D, 0x59, 0x58, 0x97, 0xB0, 0xD1, + 0xCF, 0xA3, 0xCD, 0x4A, 0x50, 0x13, 0xFE, 0x98, 0x51, 0xD8, 0xC8, 0x3A, 0x16, 0xF1, 0x06, 0xB8, 0xD8, 0xDF, 0xD6, 0x20, + 0x39, 0xF6, 0x26, 0xE5, 0xB6, 0x20, 0x07, 0x8C, 0x84, 0xBD, 0x1E, 0x09, 0x0F, 0x61, 0x8F, 0xAD, 0x41, 0xB0, 0x8E, 0x00, + 0x5D, 0x9C, 0x0A, 0x9C, 0xB5, 0x9D, 0x2F, 0x80, 0x73, 0xAE, 0xF7, 0x5D, 0x51, 0x74, 0x50, 0xA1, 0x1A, 0x43, 0x25, 0xE0, + 0xFF, 0xFF, 0x3A, 0xF3, 0x34, 0x06, 0x2C, 0x97, 0x60, 0x2A, 0x94, 0xD1, 0x38, 0xC0, 0x68, 0xCC, 0x6A, 0x2D, 0xCC, 0x95, + 0x0F, 0x8B, 0x77, 0x16, 0x15, 0xD4, 0xD8, 0xB4, 0xD4, 0xB4, 0xD0, 0x30, 0xD1, 0x21, 0x21, 0x58, 0x21, 0xDD, 0x03, 0xED, + 0xAA, 0x6F, 0xD1, 0xB5, 0xEE, 0x2E, 0x6E, 0x62, 0x1A, 0xF3, 0xCE, 0xB1, 0x20, 0xC3, 0x9A, 0xFD, 0xE7, 0xDE, 0x8B, 0x43, + 0x4C, 0x01, 0x2E, 0x0D, 0xE2, 0x50, 0x1E, 0x6C, 0x06, 0x00, 0x9A, 0x48, 0x9C, 0x3F, 0x02, 0xD6, 0xA9, 0x20, 0x57, 0xE6, + 0xAE, 0x6D, 0x00, 0x5C, 0x05, 0x87, 0x72, 0xAB, 0x9C, 0xA3, 0x9A, 0xDC, 0x0B, 0x15, 0x18, 0xE4, 0x50, 0x06, 0xC8, 0xC5, + 0x8C, 0xBB, 0x63, 0xB3, 0xA1, 0x4D, 0x6F, 0x59, 0x61, 0x04, 0xE9, 0x9A, 0x62, 0x35, 0xD4, 0x11, 0xCB, 0xAC, 0xCD, 0x95, + 0x83, 0x3C, 0xC9, 0x6E, 0xE9, 0xCA, 0xBF, 0x17, 0x51, 0x82, 0x25, 0x25, 0xD4, 0x99, 0x7A, 0x76, 0x97, 0x8E, 0x54, 0x31, + 0x4B, 0x08, 0x2D, 0xCA, 0x6B, 0x40, 0x2D, 0x20, 0x0F, 0x73, 0x86, 0x7A, 0xE6, 0x2D, 0xA2, 0xC7, 0x7A, 0x61, 0x89, 0x7C, + 0x5D, 0x6D, 0x23, 0x19, 0x54, 0x7B, 0x90, 0x4D, 0xDC, 0x31, 0x07, 0x18, 0xFB, 0x79, 0x2B, 0xD2, 0x57, 0xCC, 0x84, 0x9B, + 0x67, 0x20, 0x0B, 0x22, 0xE9, 0x30, 0xA3, 0xBD, 0xCF, 0x17, 0x1B, 0x02, 0xA9, 0x70, 0xD3, 0x4D, 0x8A, 0x7F, 0x90, 0x2A, + 0x67, 0x25, 0xAF, 0x86, 0xF7, 0xED, 0xCA, 0x8E, 0xF6, 0x91, 0x4F, 0x2B, 0x33, 0x06, 0x12, 0x2A, 0xE4, 0x43, 0xA1, 0xFC, + 0x45, 0xC5, 0xE4, 0xC9, 0xD6, 0xCB, 0x83, 0xCC, 0x73, 0x04, 0x43, 0x4F, 0xBB, 0x35, 0x6B, 0x96, 0x7F, 0x2D, 0xAB, 0x9C, + 0xB4, 0x4E, 0x4D, 0xA8, 0xBF, 0x8F, 0xA9, 0x5C, 0x98, 0xED, 0x61, 0x9B, 0x67, 0x40, 0x09, 0xBD, 0xF3, 0x69, 0x3E, 0x73, + 0x34, 0xCB, 0x33, 0xBC, 0x36, 0x8B, 0x76, 0xA1, 0x61, 0xE9, 0x2C, 0x5B, 0x99, 0xE1, 0x2C, 0x69, 0xDE, 0x53, 0x1E, 0xD3, + 0xF3, 0xB1, 0x45, 0xF1, 0xC4, 0xCE, 0xC2, 0x9D, 0x79, 0x75, 0xF7, 0x7C, 0xBE, 0x69, 0x19, 0x9A, 0xDC, 0x9F, 0x4C, 0x08, + 0x45, 0xED, 0x79, 0x3A, 0xF1, 0xD2, 0x52, 0x70, 0xD6, 0xD4, 0xC5, 0x9C, 0x58, 0xD2, 0x7A, 0x76, 0x23, 0x73, 0x9E, 0xC6, + 0x81, 0x8A, 0xC7, 0x07, 0x24, 0x76, 0x32, 0x24, 0x93, 0xCD, 0x42, 0x55, 0x89, 0x10, 0x8A, 0x51, 0x7A, 0xD9, 0x0E, 0xBD, + 0x20, 0x75, 0x5E, 0x2B, 0x52, 0x75, 0x66, 0x77, 0x08, 0xD6, 0x94, 0x50, 0x10, 0x7C, 0xFE, 0x81, 0xB2, 0x54, 0xDD, 0xD8, + 0xB4, 0xB4, 0x6F, 0x59, 0x09, 0x32, 0x03, 0xA2, 0x38, 0x55, 0x13, 0xFD, 0xEF, 0x55, 0xD5, 0xC0, 0x4E, 0xBE, 0x5D, 0x02, + 0x89, 0x82, 0xCB, 0x40, 0x18, 0x33, 0xD9, 0x07, 0x17, 0x1C, 0x2A, 0x1E, 0x78, 0x32, 0x1E, 0x75, 0x5B, 0xDB, 0xCE, 0xBC, + 0x93, 0x49, 0x52, 0x64, 0xC3, 0xE2, 0x0F, 0xDB, 0xFB, 0x3D, 0x9F, 0xA8, 0x79, 0x16, 0x61, 0x7B, 0x7F, 0x1B, 0x58, 0x76, + 0xAE, 0xA1, 0x07, 0xCC, 0x68, 0x97, 0x4D, 0xA8, 0x4F, 0xF7, 0xB7, 0xA8, 0x93, 0x4B, 0xDF, 0x74, 0x29, 0xA0, 0x87, 0x99, + 0xB0, 0xAF, 0xA0, 0x2A, 0xD5, 0x51, 0x24, 0xFD, 0xE9, 0xD6, 0x82, 0xB3, 0x2B, 0x0C, 0x44, 0xAC, 0x3E, 0x38, 0x04, 0x00, + 0x2A, 0x80, 0xEC, 0x5C, 0x86, 0xD3, 0x4A, 0x3A, 0xAB, 0xBD, 0x31, 0x1B, 0xF9, 0x1D, 0x9A, 0x32, 0xD8, 0xD7, 0x0F, 0x78, + 0x39, 0x77, 0x27, 0x7E, 0x89, 0x95, 0x57, 0x25, 0xD1, 0xF3, 0xE7, 0x9E, 0xE4, 0x82, 0x73, 0x8F, 0x05, 0x6B, 0x75, 0x5B, + 0x45, 0x14, 0x87, 0xD4, 0x39, 0xD8, 0xD8, 0x06, 0x02, 0xBC, 0xA0, 0x58, 0x31, 0x72, 0x18, 0x72, 0x0C, 0x89, 0x36, 0x79, + 0xB3, 0xA4, 0x87, 0x17, 0xA5, 0x5F, 0xBC, 0x59, 0xF3, 0xFB, 0x0E, 0x2A, 0x1D, 0xC3, 0xDA, 0x13, 0x51, 0x2C, 0x7C, 0xEF, + 0x44, 0xFA, 0x2D, 0xF1, 0x8B, 0xE9, 0xF6, 0x10, 0xB8, 0x92, 0xA2, 0xEF, 0xF6, 0xEF, 0x4E, 0xDD, 0x49, 0x80, 0xE2, 0x41, + 0x2B, 0x4F, 0xEB, 0xBF, 0xB6, 0x02, 0x51, 0x1F, 0xF6, 0x5C, 0x60, 0x83, 0x60, 0x4A, 0xBF, 0xC6, 0xE5, 0xC3, 0x40, 0x7B, + 0x00, 0xE6, 0xB9, 0xF3, 0xB3, 0x5D, 0xF5, 0xCD, 0x46, 0xE4, 0x47, 0x06, 0x50, 0x66, 0xA8, 0xC2, 0x3A, 0x8F, 0x38, 0x34, + 0xE8, 0x2C, 0xC1, 0x02, 0x07, 0xCE, 0xC0, 0x8C, 0xBE, 0x06, 0x5E, 0x83, 0x9A, 0xEA, 0xF9, 0xC7, 0x14, 0x01, 0xF0, 0x0C, + 0xE5, 0xA6, 0xFC, 0x9C, 0xF8, 0x40, 0x6F, 0xA2, 0xB3, 0x27, 0x69, 0x37, 0xDB, 0x5A, 0x47, 0x01, 0x78, 0x9C, 0xEF, 0x15, + 0x28, 0x6A, 0x1C, 0x27, 0xAB, 0x9A, 0x5A, 0xE6, 0x6E, 0xE5, 0x36, 0x4A, 0x6B, 0x65, 0x92, 0x36, 0xB5, 0x99, 0x39, 0xFC, + 0x3E, 0xA1, 0xF5, 0x7B, 0xC1, 0x68, 0x32, 0x57, 0x4B, 0x0B, 0xAB, 0x3C, 0x51, 0x42, 0xDB, 0xE3, 0xB6, 0x27, 0xDC, 0x30, + 0xA0, 0xE8, 0xB2, 0xEC, 0x0E, 0xAA, 0x2C, 0xCF, 0x9C, 0x45, 0xD3, 0xEB, 0x85, 0x84, 0xF2, 0xA6, 0x38, 0x14, 0xEF, 0xC5, + 0x13, 0xA5, 0xAA, 0xC0, 0xEE, 0x58, 0x42, 0xD3, 0xE7, 0x9D, 0xF8, 0x5A, 0x3F, 0xEC, 0x34, 0x82, 0x69, 0x41, 0x26, 0x90, + 0x3D, 0x36, 0x28, 0x37, 0x0C, 0x2D, 0x50, 0xA1, 0x90, 0x2B, 0xA3, 0x7A, 0x70, 0x6F, 0x82, 0x59, 0xA6, 0xE2, 0x3B, 0x46, + 0x03, 0xCC, 0xC3, 0x0E, 0xAD, 0x25, 0x89, 0x63, 0x59, 0x51, 0x33, 0xEA, 0xF0, 0x73, 0x35, 0x77, 0xCB, 0x8B, 0xEF, 0x9F, + 0xD9, 0xA9, 0x41, 0x88, 0xA1, 0x72, 0xFD, 0xCA, 0x5F, 0xF1, 0xDB, 0x86, 0x5F, 0xBB, 0xFD, 0xB6, 0x91, 0x4F, 0xB6, 0x4A, + 0x04, 0x9D, 0xA1, 0x46, 0x34, 0x5F, 0xEC, 0x6B, 0x08, 0x65, 0x2C, 0x94, 0x31, 0x44, 0xA9, 0x5A, 0x03, 0x2C, 0x7C, 0x33, + 0x80, 0xF9, 0x12, 0x8B, 0x58, 0xE3, 0x09, 0x14, 0x88, 0xB8, 0xCA, 0xA1, 0xE0, 0x27, 0x24, 0xE6, 0xA9, 0x9C, 0xBF, 0xA8, + 0xBD, 0x66, 0x38, 0x7F, 0xD5, 0x4E, 0xC5, 0xCD, 0x6A, 0x75, 0x3C, 0x33, 0xB7, 0xAA, 0x1C, 0x32, 0x00, 0x35, 0xA3, 0xA4, + 0x4B, 0xBD, 0x62, 0x80, 0x06, 0x9F, 0x8F, 0x95, 0x18, 0x5F, 0x52, 0xFE, 0x84, 0x1E, 0x36, 0xA0, 0xC8, 0xDB, 0x2A, 0x22, + 0x3B, 0x2A, 0xC4, 0x09, 0x9E, 0xFA, 0xE4, 0x47, 0xA8, 0x41, 0x65, 0xC5, 0xB4, 0xAD, 0x0C, 0x9C, 0x01, 0x7B, 0x8D, 0xFA, + 0x16, 0x57, 0xA8, 0xE2, 0xB3, 0x38, 0x8F, 0xD6, 0xB4, 0xC7, 0x43, 0x46, 0x8F, 0xDA, 0x29, 0x09, 0x94, 0xBF, 0x35, 0x0E, + 0x57, 0xF1, 0x5E, 0x06, 0x99, 0x47, 0xA3, 0xEA, 0x28, 0xC3, 0xBE, 0xBF, 0x17, 0xA9, 0xD0, 0xF8, 0xEC, 0x13, 0x2E, 0x9C, + 0x39, 0x4C, 0xBE, 0x85, 0x51, 0xC2, 0xAF, 0x5E, 0x69, 0xBB, 0x80, 0xBE, 0x2E, 0x9E, 0x4B, 0x1C, 0x80, 0xB2, 0xA3, 0xCD, + 0x13, 0xDE, 0xB3, 0xAD, 0xEF, 0x57, 0xA8, 0x68, 0xD5, 0x90, 0x3A, 0x77, 0x91, 0x46, 0xEB, 0xC4, 0x4A, 0x66, 0xFD, 0xD3, + 0xFC, 0x5B, 0xC6, 0xB8, 0x4C, 0x5B, 0x86, 0x79, 0x6C, 0xB1, 0x64, 0x0F, 0xDD, 0x21, 0x36, 0x6B, 0x50, 0x61, 0x16, 0x2A, + 0xB1, 0x3C, 0x15, 0x21, 0x1B, 0x16, 0xA8, 0x48, 0x7B, 0xB1, 0xF8, 0x4B, 0xFF, 0x11, 0x19, 0xCC, 0x47, 0xEF, 0x78, 0xAF, + 0xFE, 0x33, 0x8D, 0xFA, 0x80, 0x73, 0x8F, 0xC8, 0x07, 0xF1, 0xEE, 0x28, 0x2B, 0x12, 0x3E, 0x37, 0xD4, 0x7C, 0x58, 0xFD, + 0x3F, 0xBB, 0xC8, 0x4B, 0x03, 0xDC, 0xC0, 0xF9, 0x2D, 0xFD, 0x80, 0x81, 0x1C, 0xA8, 0x06, 0x95, 0xBF, 0x1D, 0x06, 0xC4, + 0x56, 0x80, 0x55, 0x11, 0xB8, 0x6D, 0xCC, 0x95, 0x19, 0x21, 0xD3, 0xB4, 0x4F, 0x89, 0x46, 0xB5, 0x5B, 0x82, 0x13, 0x05, + 0x6B, 0x31, 0x55, 0xA0, 0xBE, 0x01, 0xD1, 0xA4, 0xBF, 0xC9, 0x45, 0x84, 0xDE, 0x89, 0x6F, 0xB0, 0x80, 0x43, 0x4D, 0x10, + 0xDA, 0x4B, 0x21, 0xDF, 0x6D, 0x4E, 0x47, 0xB4, 0xD9, 0x00, 0x04, 0xC1, 0x08, 0x26, 0x94, 0x46, 0x08, 0xF9, 0xD6, 0xC0, + 0x60, 0x44, 0x10, 0xE0, 0xE7, 0x7F, 0x48, 0xF1, 0x03, 0xAF, 0x73, 0x24, 0xAF, 0x2C, 0x16, 0xA1, 0x08, 0x85, 0x23, 0xB6, + 0xF2, 0x7A, 0x05, 0xC0, 0x88, 0x26, 0xDB, 0xEB, 0xB3, 0x96, 0xC5, 0xC4, 0xE4, 0xEC, 0x01, 0x03, 0x2D, 0xEB, 0xC5, 0xF4, + 0xAB, 0x25, 0xC8, 0x2B, 0xF2, 0x50, 0x59, 0xF4, 0xCD, 0xEF, 0x19, 0xF5, 0xD6, 0xFA, 0x26, 0xD7, 0x85, 0x35, 0x56, 0x28, + 0x12, 0x08, 0x04, 0x99, 0xA3, 0x2B, 0xC6, 0xA9, 0x37, 0x83, 0x5F, 0x31, 0xE2, 0x1A, 0x5E, 0x1C, 0x51, 0x43, 0xCA, 0xC8, + 0x4C, 0x0B, 0x4E, 0x39, 0x73, 0x0A, 0x65, 0xA0, 0x77, 0xA7, 0x45, 0x18, 0x92, 0x48, 0x2D, 0x99, 0xFE, 0xE5, 0x47, 0x88, + 0xB6, 0x81, 0x35, 0xB0, 0x8F, 0x89, 0x5F, 0x3C, 0x93, 0x09, 0xDF, 0x6D, 0x68, 0x94, 0x4F, 0x98, 0xF7, 0x48, 0x96, 0xF9, + 0x42, 0x0C, 0xDA, 0x49, 0xEC, 0x79, 0x1C, 0xBC, 0x27, 0xA7, 0xFA, 0x0E, 0xA3, 0x60, 0x9E, 0xD9, 0x64, 0x6F, 0x4E, 0xA1, + 0xE4, 0x6C, 0xDE, 0xDD, 0x07, 0xA6, 0x65, 0x3E, 0xFA, 0x98, 0x17, 0x4C, 0xE1, 0x66, 0xC1, 0x56, 0xB0, 0x2A, 0xD5, 0x9C, + 0x86, 0x4C, 0xEB, 0x13, 0x5B, 0x63, 0x9F, 0x48, 0xA5, 0x6C, 0xF5, 0xFC, 0x19, 0xFE, 0x85, 0x89, 0x80, 0xE5, 0x58, 0xF9, + 0xD5, 0xA3, 0x62, 0x28, 0x21, 0x50, 0x5A, 0x85, 0x12, 0x33, 0x2A, 0x04, 0x66, 0xD2, 0x4A, 0x51, 0x7A, 0x52, 0x19, 0x63, + 0xA5, 0x9C, 0xD4, 0x30, 0x7F, 0xDA, 0xCC, 0xAF, 0x4F, 0x13, 0x48, 0xC0, 0x1C, 0xBA, 0x21, 0x5B, 0xC3, 0x1B, 0x01, 0x21, + 0xBA, 0xD9, 0xDB, 0xE1, 0xA0, 0x86, 0x41, 0xB4, 0xDE, 0x11, 0x5F, 0xAE, 0x4A, 0x77, 0x0F, 0x35, 0x93, 0x53, 0xD9, 0x41, + 0xE7, 0x31, 0x83, 0x60, 0x94, 0xBA, 0x14, 0xC0, 0x06, 0x57, 0xAC, 0xA6, 0xC5, 0x5A, 0xA5, 0x4E, 0xD4, 0x21, 0x61, 0xE8, + 0x74, 0x7E, 0xD6, 0xC5, 0x21, 0x75, 0xD9, 0xA7, 0x15, 0xBC, 0xED, 0x5F, 0xDD, 0x9E, 0xE2, 0xF8, 0x31, 0xCA, 0x51, 0x34, + 0xCD, 0xDF, 0x05, 0x44, 0xED, 0x3E, 0xE0, 0xCE, 0xCD, 0x3D, 0xD5, 0x5A, 0xFA, 0x54, 0x99, 0xD1, 0xA9, 0x35, 0x3C, 0xB5, + 0xF7, 0x9A, 0x8E, 0x2D, 0xD4, 0x0C, 0xE7, 0x0A, 0xF5, 0xC4, 0xC6, 0x18, 0x31, 0x7B, 0x56, 0xAD, 0x76, 0xD3, 0x1C, 0xDB, + 0x4E, 0x57, 0x14, 0x09, 0x56, 0x1B, 0xA9, 0x29, 0x2F, 0x7B, 0xDE, 0x3C, 0x35, 0x1B, 0x18, 0x0D, 0xE1, 0xEA, 0x54, 0xC9, + 0x1C, 0x99, 0x61, 0xEB, 0x43, 0x99, 0xC3, 0x18, 0xDF, 0x1A, 0xA3, 0xDA, 0xC6, 0x55, 0x49, 0xD9, 0x95, 0xD1, 0x55, 0x69, + 0xA8, 0x59, 0x4B, 0x68, 0x92, 0x19, 0x1A, 0xBA, 0xFD, 0xF6, 0x4B, 0x18, 0xD7, 0xD1, 0x02, 0x6D, 0x04, 0x7F, 0x16, 0xBC, + 0x86, 0x37, 0x8F, 0xEB, 0xEE, 0x38, 0x98, 0x68, 0x30, 0x39, 0x90, 0x2D, 0x44, 0xF6, 0x71, 0xAC, 0x33, 0x34, 0x5E, 0x07, + 0x94, 0xA2, 0x4E, 0x8F, 0x5D, 0xF4, 0x45, 0x69, 0x80, 0x3C, 0x06, 0x49, 0x89, 0x5A, 0x75, 0xE9, 0xEA, 0x5E, 0xDF, 0xE8, + 0x85, 0x81, 0x9F, 0xFD, 0x8D, 0x3F, 0x4B, 0x20, 0x44, 0x7E, 0xA0, 0x06, 0x16, 0x59, 0x6E, 0x9D, 0xB3, 0xD2, 0x75, 0x69, + 0x89, 0x36, 0xA0, 0x87, 0x1A, 0xC3, 0x84, 0x40, 0x2C, 0x63, 0xF4, 0xD3, 0x3B, 0x4A, 0x72, 0x10, 0x97, 0x8B, 0xBC, 0x97, + 0x5B, 0x41, 0xC3, 0x75, 0xAC, 0xA2, 0xFC, 0xB7, 0x7B, 0x82, 0x1A, 0x73, 0x04, 0x9D, 0x7F, 0xF2, 0xDF, 0xC1, 0xCE, 0x50, + 0xA6, 0x11, 0xB7, 0x86, 0xFA, 0x81, 0xA9, 0xEE, 0x8D, 0x2E, 0x6D, 0x92, 0xBB, 0x81, 0x5E, 0x49, 0xA4, 0xC7, 0xF7, 0xE6, + 0xBA, 0xC3, 0xB4, 0x42, 0x06, 0x84, 0xD7, 0xC1, 0xFD, 0xE7, 0x3E, 0x73, 0x64, 0xE7, 0x30, 0xE2, 0xBB, 0xEA, 0x68, 0xF7, + 0x29, 0xE6, 0x38, 0x30, 0xEC, 0x3E, 0x36, 0x37, 0x69, 0x86, 0x03, 0xB4, 0xF6, 0x5A, 0x61, 0x43, 0x86, 0x86, 0x21, 0xD6, + 0x98, 0xBD, 0x35, 0xB7, 0x8D, 0x6C, 0xC9, 0x98, 0x55, 0xEB, 0xBD, 0x03, 0xC6, 0x0F, 0xE9, 0xD3, 0xCB, 0xF6, 0xFD, 0x16, + 0xEA, 0xAE, 0x91, 0x15, 0x24, 0x8B, 0x73, 0x4D, 0xC6, 0x4B, 0x7C, 0xDF, 0x13, 0x89, 0x4B, 0x59, 0x6A, 0x41, 0xE6, 0x8B, + 0x72, 0x03, 0x68, 0xE9, 0x3F, 0x7D, 0xFA, 0x1B, 0x17, 0xEB, 0x19, 0x9E, 0x95, 0xAA, 0x6E, 0xBF, 0x11, 0xCA, 0x2B, 0x1A, + 0x65, 0x49, 0xE7, 0x9A, 0xD0, 0xA9, 0x13, 0xA1, 0xCF, 0x4A, 0x6D, 0xFE, 0x97, 0x89, 0xFD, 0x68, 0xE3, 0xE5, 0x75, 0xEA, + 0x97, 0x49, 0xD7, 0x44, 0x07, 0xA8, 0x6F, 0x9A, 0x96, 0x41, 0x68, 0x1A, 0x4F, 0x0C, 0xD8, 0xB5, 0xEB, 0xA0, 0x6C, 0x1B, + 0x27, 0x27, 0x32, 0xEF, 0x01, 0xE6, 0x60, 0x0A, 0x4E, 0x05, 0xD4, 0x42, 0x19, 0x0F, 0x65, 0x03, 0x36, 0x74, 0x3F, 0x86, + 0xB9, 0x56, 0xB7, 0xEE, 0xA0, 0x24, 0xDB, 0x30, 0x1F, 0xA3, 0xAD, 0x9E, 0xA1, 0x77, 0x7B, 0x93, 0x38, 0x15, 0x61, 0x0B, + 0xCF, 0x8C, 0x38, 0x9D, 0x3E, 0x50, 0xE4, 0x06, 0xB2, 0x36, 0x1E, 0x0D, 0x34, 0xFC, 0xE0, 0xD6, 0x85, 0xCF, 0x62, 0x73, + 0x78, 0xB3, 0x60, 0x53, 0xC7, 0x20, 0x7E, 0xD2, 0x1D, 0x3A, 0x7E, 0xAD, 0x4F, 0x2A, 0xF4, 0x12, 0x59, 0xBA, 0xF8, 0x5F, + 0x06, 0xD9, 0xE8, 0xB3, 0x51, 0xB0, 0x91, 0xE1, 0x1B, 0x47, 0xF1, 0x83, 0xB2, 0x73, 0x07, 0x92, 0x82, 0x90, 0x6B, 0xD3, + 0xBC, 0xF1, 0xA9, 0x17, 0xF9, 0xC2, 0x6D, 0x93, 0x9B, 0x90, 0xFD, 0x36, 0xA0, 0xDE, 0x2D, 0x93, 0xD1, 0xB2, 0x24, 0x47, + 0x08, 0xB6, 0xDA, 0xDA, 0x05, 0x40, 0xE7, 0xD9, 0xE8, 0x7B, 0x24, 0x54, 0xC8, 0xF6, 0x2C, 0xD2, 0x6B, 0x97, 0x68, 0xE9, + 0x1D, 0xF4, 0x42, 0x56, 0x06, 0x82, 0x9D, 0x72, 0x3D, 0x6D, 0xA1, 0x66, 0x88, 0xF5, 0x25, 0x56, 0xE7, 0xBE, 0xA5, 0x98, + 0x68, 0x09, 0xAC, 0x43, 0x53, 0xED, 0xA9, 0x76, 0xA7, 0x7C, 0x32, 0x28, 0x93, 0x4C, 0x65, 0x72, 0x0E, 0x94, 0xF5, 0xF2, + 0x0B, 0xD4, 0x9B, 0xB7, 0xD3, 0xC5, 0x26, 0x0F, 0x7B, 0xB3, 0xCD, 0x8D, 0xCD, 0x27, 0x26, 0xAA, 0x5E, 0xDB, 0x55, 0xF1, + 0x46, 0x96, 0x2E, 0x3B, 0x17, 0xD9, 0xB2, 0x1F, 0x4B, 0xF8, 0x6A, 0x1B, 0x53, 0x9A, 0xF4, 0xD0, 0x51, 0x26, 0x67, 0xBA, + 0x9F, 0xF8, 0xA7, 0xAB, 0xE2, 0xBA, 0x33, 0x0A, 0xD2, 0x99, 0xA8, 0xA9, 0x9A, 0x9B, 0x6B, 0x4B, 0x9E, 0xF9, 0x7B, 0xAE, + 0x82, 0x1B, 0x3B, 0x1F, 0xD7, 0x9B, 0xE2, 0x6F, 0x00, 0x9E, 0x19, 0xEA, 0xBC, 0xDB, 0x6C, 0xC5, 0x4F, 0xAC, 0x66, 0x13, + 0x81, 0xBD, 0xBA, 0x2F, 0x40, 0xF6, 0xB4, 0xC3, 0x39, 0x3F, 0x66, 0xEB, 0x86, 0x9E, 0x01, 0xDA, 0xFD, 0xF5, 0x67, 0xDE, + 0xAC, 0xFC, 0x98, 0xAD, 0x41, 0xD2, 0x49, 0x4F, 0x8F, 0xA9, 0x28, 0x10, 0xDA, 0x05, 0xBB, 0x7E, 0xAD, 0x9F, 0x5C, 0xA5, + 0x3E, 0xB2, 0x0D, 0xD5, 0xAF, 0x2B, 0x43, 0x80, 0x5C, 0xBE, 0xA7, 0x2C, 0xE1, 0xAF, 0x93, 0x38, 0x58, 0xB1, 0xD0, 0xB1, + 0x23, 0xBF, 0xD2, 0x77, 0xA1, 0xE9, 0x1F, 0xEF, 0xEA, 0x70, 0x8E, 0x39, 0x70, 0x30, 0x1C, 0x25, 0x47, 0x03, 0x25, 0x44, + 0xE7, 0x68, 0x96, 0xF2, 0xA2, 0xA9, 0xBF, 0x3D, 0xB3, 0x62, 0xD1, 0x25, 0xAA, 0xB5, 0xB1, 0xAF, 0xD1, 0xE0, 0x77, 0x29, + 0x87, 0x41, 0x87, 0x38, 0xB2, 0xF4, 0x63, 0x43, 0x62, 0x26, 0x8D, 0x5A, 0xB0, 0x16, 0xFA, 0x87, 0xC0, 0x54, 0x6C, 0xD7, + 0x34, 0x2E, 0x6E, 0xBC, 0xE5, 0x5F, 0x79, 0x75, 0x78, 0x4C, 0x11, 0x47, 0x64, 0xF5, 0xB6, 0x52, 0xF2, 0xA6, 0x5D, 0x92, + 0x70, 0xE7, 0xE6, 0x15, 0xF0, 0x7E, 0x49, 0x55, 0xE5, 0x56, 0x91, 0xB5, 0x7C, 0x57, 0x13, 0x07, 0x40, 0x45, 0x3C, 0xE7, + 0x7C, 0x6F, 0x89, 0x35, 0x9D, 0x01, 0xE9, 0xA6, 0x1F, 0x2A, 0xE1, 0xF3, 0xE1, 0xB7, 0x7A, 0x03, 0x7F, 0x68, 0x78, 0x7A, + 0xAB, 0x6D, 0x42, 0x89, 0x70, 0x25, 0x6A, 0xAC, 0x4E, 0xC7, 0x8A, 0xB4, 0xE5, 0xE1, 0x19, 0xF8, 0x0D, 0xA9, 0xF4, 0xBC, + 0xF0, 0x98, 0xE5, 0x7F, 0xA0, 0x4A, 0x6F, 0x38, 0xD9, 0x2B, 0x7B, 0x18, 0xF8, 0xA7, 0xFD, 0x30, 0x34, 0x27, 0x2B, 0xD7, + 0x64, 0x47, 0x22, 0x4D, 0x96, 0x1D, 0x9E, 0x69, 0xB9, 0xA3, 0x27, 0x8F, 0xA9, 0x23, 0xFC, 0x47, 0xA8, 0x4F, 0x5B, 0xAC, + 0x38, 0x92, 0x12, 0x41, 0xAB, 0xA3, 0xBF, 0x3E, 0x65, 0x0C, 0x2A, 0x2F, 0xA3, 0x96, 0x8F, 0x74, 0xF7, 0x09, 0x13, 0xC1, + 0xAC, 0x16, 0xF7, 0x16, 0x1D, 0x0F, 0x03, 0x62, 0x4D, 0x64, 0x6E, 0x9E, 0xF7, 0xE6, 0x88, 0x0F, 0xCA, 0x83, 0x38, 0xB6, + 0x69, 0x32, 0x35, 0x08, 0x21, 0x6D, 0xAB, 0x85, 0x82, 0x23, 0x0B, 0xBF, 0xB8, 0x4F, 0x6F, 0x2E, 0xFD, 0xD7, 0xA5, 0x91, + 0x57, 0xE2, 0xDF, 0x9F, 0xDD, 0x46, 0x01, 0x04, 0x26, 0x9F, 0x17, 0xBF, 0xBE, 0xB9, 0x10, 0x88, 0xA8, 0xE1, 0xAA, 0x99, + 0x11, 0x74, 0x2C, 0x24, 0xA3, 0x80, 0x4E, 0x90, 0xD3, 0x58, 0x62, 0x10, 0x8A, 0x20, 0x5C, 0x25, 0x90, 0xAE, 0x3F, 0x63, + 0x0C, 0x1D, 0x19, 0x65, 0xAE, 0x70, 0x86, 0xD3, 0x0B, 0xA3, 0xF7, 0xA7, 0xF1, 0x10, 0x73, 0x60, 0x02, 0x63, 0x8E, 0x11, + 0xBF, 0x92, 0x63, 0x89, 0xE7, 0x11, 0x02, 0x55, 0xA1, 0xAE, 0xFC, 0x28, 0x78, 0x5B, 0x96, 0x14, 0x79, 0x8B, 0x6A, 0x30, + 0xFE, 0x5B, 0xE0, 0xB8, 0x11, 0xEB, 0x87, 0x17, 0xE9, 0x3C, 0xB7, 0xA7, 0x19, 0x9E, 0xDC, 0xE1, 0x45, 0xF8, 0xE6, 0x44, + 0xA7, 0xDA, 0x85, 0x39, 0x1D, 0xBB, 0xFB, 0x60, 0xF1, 0x94, 0x77, 0x92, 0x41, 0x5F, 0xC3, 0xD1, 0x19, 0x32, 0x05, 0xC0, + 0x4A, 0x3E, 0xB5, 0xDD, 0x53, 0xB6, 0x17, 0xC0, 0xC5, 0xD5, 0x79, 0x97, 0xD0, 0x37, 0x38, 0xB0, 0x2E, 0x5A, 0xBC, 0x6E, + 0x94, 0x37, 0x6C, 0xCA, 0x9F, 0x3D, 0x8C, 0xD5, 0x59, 0xF8, 0x76, 0x95, 0xC9, 0xB8, 0x8B, 0xEF, 0x4D, 0x7B, 0x4E, 0xCB, + 0x15, 0x1B, 0x29, 0x85, 0x5D, 0x82, 0x14, 0xFA, 0x94, 0xB1, 0xA1, 0xB1, 0xC0, 0x3E, 0x2F, 0x56, 0x67, 0xFC, 0x2C, 0x1F, + 0x85, 0x1A, 0xAB, 0xA2, 0x2D, 0x84, 0x4B, 0xA8, 0x58, 0x34, 0x5D, 0x6C, 0xE8, 0x1A, 0x60, 0x99, 0x18, 0x60, 0x44, 0x3B, + 0x7D, 0x07, 0xF5, 0x3F, 0xBE, 0xB1, 0x70, 0x4C, 0xC9, 0xD8, 0xE2, 0xA0, 0x93, 0xBD, 0x17, 0xC6, 0xCE, 0xEB, 0x0E, 0x5D, + 0xAE, 0x90, 0xA3, 0x0B, 0x41, 0x46, 0xF8, 0x1E, 0x43, 0xD2, 0x00, 0xAF, 0x55, 0x72, 0x95, 0xD6, 0x51, 0x5A, 0x0E, 0x65, + 0x4D, 0xD3, 0xF1, 0x3D, 0x59, 0xFB, 0xB0, 0x49, 0x5C, 0xB2, 0x1D, 0x0D, 0x0F, 0xC0, 0x9E, 0x9F, 0x14, 0xF2, 0x4E, 0x8F, + 0x10, 0x9E, 0xB5, 0xE2, 0xB9, 0x0D, 0xA5, 0x75, 0x6C, 0x26, 0x49, 0x51, 0x38, 0x49, 0xA8, 0xB2, 0x52, 0x82, 0x71, 0x52, + 0xA0, 0x3E, 0x57, 0x32, 0x13, 0x63, 0x9B, 0x0F, 0x99, 0xC2, 0x83, 0x46, 0xD5, 0xF7, 0x5F, 0x2E, 0x6F, 0x13, 0xA1, 0xC7, + 0x98, 0x59, 0x11, 0xA9, 0xC7, 0x22, 0xB0, 0xA3, 0x96, 0x4E, 0x5B, 0x12, 0x9D, 0xC1, 0x29, 0xE8, 0x77, 0xCA, 0x1F, 0x0B, + 0xBD, 0x63, 0xF1, 0x3B, 0x2D, 0x32, 0x98, 0xAA, 0x48, 0xCB, 0x9E, 0xF2, 0xFF, 0x07, 0x08, 0x94, 0x40, 0x2F, 0x80, 0x04, + 0x65, 0x90, 0x38, 0x4F, 0xA6, 0xE9, 0xBA, 0x0F, 0xFC, 0x26, 0x82, 0x00, 0xC5, 0x11, 0x80, 0x52, 0xB6, 0x4A, 0x31, 0x5F, + 0xDC, 0x80, 0x6A, 0xB4, 0xFC, 0x0B, 0x46, 0x8B, 0x52, 0x3B, 0x63, 0xE5, 0x78, 0x4F, 0x0F, 0x8F, 0xB4, 0x55, 0xD7, 0xF2, + 0xC6, 0x08, 0x25, 0x91, 0x45, 0xC3, 0xE8, 0x84, 0x82, 0xE1, 0x64, 0xFA, 0x6D, 0x71, 0x24, 0x7D, 0x68, 0xCE, 0x21, 0x59, + 0x3C, 0xC3, 0x05, 0x17, 0x5A, 0x39, 0x15, 0xFA, 0x51, 0xCB, 0x15, 0x6E, 0x7A, 0xA2, 0x58, 0x12, 0xA4, 0xB8, 0x0D, 0x07, + 0x79, 0x87, 0x3B, 0x0F, 0x0C, 0xBA, 0xB9, 0xFB, 0xBD, 0x5A, 0xB3, 0x3A, 0xF0, 0xA6, 0x58, 0x30, 0xA4, 0xAB, 0x6D, 0xEB, + 0x6F, 0x72, 0xBD, 0x6C, 0xE9, 0xAD, 0x59, 0x3B, 0xCE, 0x8B, 0x85, 0x9F, 0x1F, 0x7F, 0x9A, 0x2C, 0xF1, 0x8F, 0x36, 0x43, + 0x0A, 0xA8, 0xD2, 0x08, 0xC3, 0xAE, 0x59, 0xA3, 0xFD, 0xEA, 0x92, 0x38, 0xE4, 0x57, 0xA4, 0xA1, 0xF6, 0x0E, 0x7E, 0x09, + 0x0C, 0xB9, 0x68, 0x0D, 0x3B, 0x81, 0xDD, 0x43, 0x6D, 0x0E, 0x4A, 0x3C, 0xF8, 0x24, 0x8E, 0x8B, 0xCA, 0xB5, 0x85, 0xC4, + 0x7D, 0x41, 0x83, 0x4B, 0xBC, 0x5D, 0xA1, 0x8E, 0x68, 0x02, 0x03, 0x69, 0x24, 0x8C, 0x9D, 0xBA, 0xDE, 0xAF, 0x93, 0xAE, + 0x22, 0xC1, 0x10, 0x64, 0xBB, 0x1D, 0x0A, 0x9B, 0x0D, 0x41, 0x73, 0x40, 0xF9, 0xEB, 0xEC, 0x16, 0xC6, 0x0C, 0x3B, 0xE6, + 0xB5, 0x37, 0x24, 0x3A, 0xEA, 0x2C, 0xC2, 0x17, 0x46, 0xD7, 0x02, 0x07, 0xE6, 0x60, 0xF5, 0x15, 0x25, 0x1F, 0x6D, 0xA7, + 0x0D, 0xA3, 0x16, 0xD1, 0x3E, 0xDB, 0x55, 0xB4, 0x5C, 0x9C, 0x8D, 0xD7, 0xE4, 0xF1, 0x5F, 0xF9, 0x10, 0x5A, 0x7D, 0xD6, + 0x1A, 0x57, 0xAF, 0x85, 0xF0, 0x9C, 0xDA, 0x77, 0x75, 0xE1, 0x20, 0xA5, 0xB8, 0xDC, 0xCA, 0xD3, 0xFB, 0x52, 0x12, 0x0E, + 0x14, 0x17, 0x5D, 0x2D, 0xDE, 0xD6, 0x42, 0x22, 0xAD, 0x96, 0x75, 0x72, 0x2C, 0x60, 0x63, 0xBC, 0xC6, 0x49, 0x1E, 0xB4, + 0xD4, 0x3C, 0xF5, 0x82, 0x2E, 0xBA, 0xBF, 0xA7, 0xF2, 0xD3, 0x53, 0x0F, 0x00, 0x8C, 0xA7, 0xFB, 0x44, 0x1A, 0x82, 0x9C, + 0x68, 0x21, 0xC5, 0x97, 0xF3, 0xD2, 0xE6, 0x1B, 0x4F, 0x1F, 0x64, 0x8A, 0xC3, 0xC7, 0x16, 0x38, 0xEC, 0xD0, 0xCE, 0x0A, + 0x4F, 0x1C, 0x51, 0x6A, 0x25, 0x96, 0x11, 0xE2, 0x1C, 0x29, 0x06, 0x49, 0x11, 0xBC, 0xA6, 0xAE, 0x9A, 0xE2, 0xD6, 0x87, + 0xAA, 0xD8, 0x99, 0xB3, 0x32, 0x65, 0x30, 0x2F, 0xEA, 0x55, 0x6D, 0xB2, 0x15, 0xB9, 0x9B, 0x6B, 0x89, 0x94, 0x6F, 0x1A, + 0xAD, 0xF9, 0x07, 0x48, 0xCF, 0x7F, 0xDB, 0xAB, 0xCE, 0xDD, 0xA5, 0xAC, 0x46, 0x46, 0xB2, 0x3F, 0x9D, 0xAC, 0x7E, 0xEF, + 0xF3, 0x21, 0xA5, 0x9D, 0x4A, 0x5D, 0x6C, 0xD3, 0x8A, 0x86, 0x4E, 0xAC, 0x5D, 0x09, 0x00, 0x4B, 0x84, 0x5E, 0x3E, 0x27, + 0x51, 0x62, 0x3E, 0x5A, 0x09, 0x9D, 0xD5, 0xFF, 0x1C, 0x11, 0xDA, 0x99, 0x05, 0x1D, 0xCF, 0x10, 0x17, 0xCF, 0x2D, 0x3D, + 0x9C, 0x3D, 0x91, 0xD8, 0xB9, 0x9D, 0x01, 0x5E, 0x58, 0x82, 0x4B, 0x9D, 0x04, 0x91, 0x59, 0x92, 0xA5, 0xB6, 0xBE, 0x58, + 0x78, 0x2D, 0x5C, 0x33, 0x24, 0x0A, 0x50, 0xB4, 0x0F, 0xF5, 0x70, 0x98, 0xA4, 0x88, 0xB2, 0xA4, 0xFB, 0x8E, 0x7D, 0x4A, + 0xE6, 0x51, 0x1F, 0xB7, 0x85, 0x82, 0x3A, 0x71, 0x00, 0xAD, 0x93, 0x99, 0x7B, 0x66, 0x48, 0xA7, 0x67, 0x59, 0x44, 0x1E, + 0xA2, 0x20, 0x29, 0x82, 0x22, 0x0B, 0x2D, 0x6B, 0x32, 0x46, 0x26, 0xD7, 0x20, 0xEC, 0x3E, 0x9D, 0x5E, 0xCE, 0x8F, 0x7A, + 0x3C, 0xB1, 0x3F, 0x60, 0x9F, 0xA9, 0x90, 0xE4, 0x8E, 0x06, 0x68, 0x9B, 0xDF, 0x7F, 0xEB, 0xF9, 0xDF, 0x56, 0xAA, 0x54, + 0xE4, 0x3E, 0x4E, 0xC0, 0x45, 0x07, 0x99, 0x12, 0x85, 0xBA, 0x12, 0xC5, 0xDE, 0x20, 0xA7, 0x89, 0x6D, 0xAB, 0x95, 0x9F, + 0xA1, 0x30, 0xB5, 0x03, 0x0C, 0x99, 0xA5, 0x22, 0xB5, 0x81, 0x6A, 0x12, 0x36, 0xD1, 0x42, 0x8E, 0x4E, 0xEA, 0x49, 0x4B, + 0x98, 0x92, 0x82, 0x2B, 0x7A, 0xA5, 0x3D, 0xEE, 0x1E, 0x92, 0x5F, 0x17, 0x7C, 0x9D, 0xC3, 0xBE, 0xE9, 0xC5, 0x12, 0x00, + 0x6A, 0x40, 0x26, 0x63, 0xDB, 0xD6, 0xDA, 0x18, 0x49, 0x52, 0x3E, 0x7C, 0x1D, 0xC2, 0x49, 0x99, 0xE1, 0xEB, 0xB3, 0xFD, + 0x67, 0x25, 0x06, 0xAD, 0xBB, 0xDA, 0x45, 0x5D, 0x58, 0xEC, 0xCB, 0xC0, 0xE7, 0x49, 0x30, 0x6D, 0x19, 0xAD, 0xFA, 0x5F, + 0xEA, 0x0B, 0x4D, 0x38, 0xB2, 0x78, 0x7B, 0x3B, 0x30, 0x85, 0x79, 0x3C, 0x9A, 0x83, 0x57, 0x6A, 0x66, 0xC7, 0x18, 0x23, + 0xA7, 0x10, 0xC8, 0xA9, 0x31, 0x6D, 0xEA, 0xCF, 0xB8, 0x6C, 0x9A, 0x6F, 0xB4, 0xC6, 0xE4, 0xAC, 0x30, 0x62, 0x63, 0xDB, + 0x06, 0x06, 0xBB, 0xC5, 0x3F, 0xA7, 0x96, 0x58, 0xA8, 0x0C, 0x7A, 0x13, 0x4F, 0x2F, 0x15, 0xF5, 0x3A, 0x63, 0xF3, 0xA7, + 0x37, 0x22, 0x9E, 0x48, 0xB5, 0x0D, 0x5B, 0x4F, 0x2F, 0x60, 0x57, 0xF3, 0x4C, 0x19, 0xBA, 0xA8, 0x11, 0x70, 0x1C, 0xB4, + 0x89, 0x1A, 0xCE, 0x29, 0x18, 0xF3, 0x34, 0x6F, 0xC8, 0x20, 0x90, 0xF6, 0x79, 0xF0, 0xDC, 0x69, 0x1A, 0x13, 0xC6, 0x38, + 0x19, 0xF2, 0x43, 0xF2, 0x94, 0xB3, 0x99, 0xE7, 0xF8, 0x03, 0x0B, 0x60, 0xC1, 0xD9, 0x55, 0x21, 0x3C, 0x8D, 0xD9, 0x6F, + 0xC2, 0xC9, 0x91, 0x3E, 0x95, 0xBE, 0xD6, 0xC7, 0x1C, 0x58, 0x5D, 0x31, 0x3B, 0x1F, 0x06, 0xCD, 0x23, 0x36, 0xBA, 0xC2, + 0x51, 0xC0, 0x94, 0x65, 0xCB, 0x5E, 0x74, 0x96, 0x10, 0x80, 0x8C, 0xCD, 0xA9, 0x7B, 0x95, 0x7E, 0x96, 0xEA, 0xA3, 0x74, + 0x18, 0x3C, 0xBA, 0x38, 0x10, 0x71, 0x85, 0x51, 0x21, 0xA4, 0x16, 0x36, 0x3E, 0x77, 0xD6, 0xDA, 0x94, 0xDB, 0xAB, 0xE2, + 0xD6, 0x18, 0x73, 0x7D, 0x7D, 0xCA, 0xCC, 0xB3, 0x4C, 0x2C, 0x63, 0xED, 0xE5, 0x35, 0xA4, 0x8F, 0x92, 0x73, 0xC6, 0x51, + 0x46, 0x5A, 0xF8, 0x3D, 0xD3, 0xFB, 0x8B, 0xEF, 0x81, 0x12, 0x56, 0x3C, 0x7C, 0xF3, 0x3A, 0x20, 0xC0, 0xD8, 0x7C, 0x11, + 0x98, 0x7B, 0xB2, 0xCB, 0x6A, 0xFF, 0x5E, 0xC4, 0x86, 0xF2, 0x48, 0xC8, 0xA9, 0x5A, 0xD9, 0x30, 0x47, 0x3C, 0x71, 0x68, + 0xA8, 0xA5, 0x72, 0x9C, 0x9A, 0x38, 0x17, 0x09, 0x24, 0xB6, 0x4B, 0x63, 0x3B, 0xFC, 0x90, 0xA9, 0x35, 0x54, 0x7E, 0x8C, + 0x9B, 0x39, 0x86, 0x58, 0x76, 0x14, 0xA6, 0xAA, 0xC9, 0x2C, 0x6C, 0xA8, 0x76, 0xFC, 0xB7, 0xC8, 0x54, 0xA3, 0x09, 0x5C, + 0x77, 0x3B, 0x31, 0xA2, 0xAD, 0xE2, 0x3C, 0xFC, 0x6A, 0x1D, 0x65, 0x4C, 0x97, 0xA2, 0x81, 0x4D, 0xE8, 0x10, 0x7F, 0x36, + 0x9E, 0x48, 0x85, 0x9A, 0x80, 0x30, 0x68, 0xDD, 0xDB, 0x81, 0xE3, 0xAA, 0x9D, 0xE9, 0xF0, 0x56, 0x40, 0xA2, 0x59, 0x4D, + 0x0A, 0xF0, 0x4F, 0x8F, 0xC8, 0x08, 0x6F, 0x43, 0x05, 0xC0, 0x80, 0xC6, 0x58, 0xED, 0x71, 0x44, 0x67, 0x80, 0x89, 0x61, + 0xBD, 0xF3, 0x6A, 0x63, 0x61, 0x88, 0x17, 0xF4, 0x13, 0x1B, 0x26, 0x6F, 0x66, 0x51, 0xA2, 0x34, 0x97, 0x7A, 0x15, 0xBB, + 0x6D, 0xE8, 0x5E, 0x83, 0xCF, 0xA7, 0x05, 0x9B, 0x2D, 0xC8, 0xD3, 0xAF, 0x3D, 0x01, 0x6B, 0xEF, 0x85, 0x2E, 0xF6, 0xE7, + 0xD5, 0x02, 0x95, 0x40, 0xC2, 0x65, 0xF1, 0x23, 0xBE, 0x00, 0x5E, 0xEE, 0xC4, 0x96, 0x9F, 0x61, 0xB7, 0x7B, 0xB0, 0x75, + 0xCB, 0x86, 0x60, 0xE4, 0xB8, 0xAF, 0x0A, 0xAA, 0x04, 0x45, 0x15, 0x5E, 0xB2, 0x9A, 0x6E, 0xC2, 0x41, 0x87, 0x85, 0x51, + 0xF6, 0xBA, 0x5F, 0xEA, 0xE7, 0x82, 0x55, 0x25, 0x69, 0xEB, 0x33, 0x67, 0xA5, 0xB0, 0xC9, 0x8D, 0x7A, 0xEB, 0x37, 0xFA, + 0x74, 0x2C, 0xE8, 0x31, 0x20, 0xB7, 0x62, 0x8C, 0xA4, 0xB1, 0x4D, 0x15, 0x68, 0xA6, 0xB3, 0x3B, 0x4F, 0x77, 0xB3, 0xFD, + 0x2C, 0x08, 0x7E, 0xED, 0x8E, 0x48, 0xC9, 0xDF, 0x6E, 0xFA, 0x65, 0x23, 0x0B, 0x33, 0xC8, 0x0F, 0x1E, 0xEB, 0x96, 0x49, + 0x4E, 0x6F, 0xE8, 0x79, 0x97, 0xB9, 0x98, 0xBA, 0xB4, 0xC8, 0x28, 0x7C, 0xC9, 0xC6, 0x3B, 0x2F, 0x64, 0x59, 0xED, 0x9F, + 0xD4, 0x47, 0x27, 0x5B, 0x89, 0xAE, 0xAD, 0x2A, 0xD5, 0xFA, 0xB4, 0xFC, 0x0F, 0x4B, 0xB3, 0x3B, 0x54, 0x36, 0xB3, 0xC2, + 0x75, 0x6C, 0x5A, 0x01, 0xAD, 0xED, 0x64, 0xD7, 0x48, 0x8E, 0x2B, 0x71, 0x61, 0x76, 0xAA, 0x47, 0x85, 0xCF, 0x15, 0x2D, + 0x6F, 0xCE, 0xB4, 0x41, 0x3D, 0x40, 0x43, 0x20, 0x7B, 0x4C, 0xA3, 0xDB, 0x09, 0x3E, 0xDD, 0x76, 0xF6, 0xA3, 0x68, 0x2C, + 0xC8, 0x6C, 0x5C, 0x00, 0x03, 0x32, 0xAB, 0x20, 0x02, 0xCD, 0x10, 0xAF, 0xCC, 0x5E, 0x84, 0xFF, 0xB4, 0xA6, 0xC3, 0x4F, + 0x8D, 0x40, 0xB5, 0x11, 0x67, 0x6F, 0x41, 0xE4, 0xCB, 0xDC, 0x06, 0x5D, 0x57, 0x76, 0x74, 0xE0, 0xD5, 0x9C, 0xEC, 0x4B, + 0x5D, 0xD3, 0x62, 0xE5, 0x47, 0x19, 0x5B, 0xC0, 0xA7, 0xD1, 0xEF, 0xE7, 0x4B, 0xFA, 0x1B, 0xAA, 0x66, 0x92, 0x9B, 0x8E, + 0xB2, 0x10, 0x8D, 0x58, 0x69, 0x2F, 0x75, 0x36, 0xBB, 0x5F, 0x62, 0xD2, 0xA4, 0xD3, 0x78, 0x77, 0xBF, 0xF1, 0x35, 0xBE, + 0x67, 0x0F, 0xF9, 0x33, 0xBF, 0xA6, 0xDF, 0x46, 0x64, 0x64, 0x85, 0x3C, 0xD7, 0xCF, 0x22, 0xF1, 0x04, 0x27, 0x0C, 0xEE, + 0xD1, 0xB5, 0x2E, 0xDF, 0x24, 0x15, 0x95, 0x11, 0x33, 0x97, 0xAD, 0x5A, 0x2F, 0x56, 0xB8, 0xB8, 0xF5, 0x12, 0x6D, 0xCF, + 0x29, 0xD4, 0xF6, 0x2B, 0xBE, 0x89, 0x53, 0x4A, 0x88, 0x72, 0x95, 0x50, 0xD1, 0xB4, 0x6B, 0x62, 0x2E, 0xCA, 0x22, 0x55, + 0x59, 0xFC, 0x49, 0x44, 0x1B, 0x14, 0xDF, 0xD3, 0x1E, 0xDC, 0x12, 0x32, 0x2A, 0x22, 0xE0, 0xA0, 0x3D, 0x78, 0xFB, 0x5A, + 0x64, 0xD7, 0xBE, 0xBA, 0x0B, 0x98, 0x08, 0xAF, 0x70, 0x3D, 0x8E, 0x1E, 0x4A, 0x26, 0xC6, 0x52, 0xF7, 0x94, 0x65, 0x44, + 0x02, 0xEB, 0x14, 0x7B, 0xA4, 0x95, 0x7C, 0x8A, 0xC3, 0xA7, 0x6E, 0x85, 0x8F, 0x58, 0x68, 0xC5, 0x7C, 0xF8, 0xB9, 0x5B, + 0x65, 0x5A, 0x70, 0x17, 0x3D, 0xEB, 0xC4, 0xB3, 0x48, 0x24, 0x9F, 0xB3, 0xFB, 0x79, 0x58, 0x7B, 0xA3, 0x1A, 0xDE, 0x34, + 0x92, 0xB1, 0xE6, 0x6E, 0x64, 0x12, 0x90, 0xDA, 0x95, 0xD7, 0xB9, 0x28, 0x0C, 0x7F, 0x5A, 0xBC, 0x1B, 0xA6, 0x7F, 0x9C, + 0x94, 0xCD, 0x80, 0x4E, 0x6F, 0x30, 0x63, 0x8B, 0xC3, 0x33, 0x98, 0xE8, 0x1F, 0x61, 0x2E, 0x48, 0x4B, 0x41, 0x67, 0x07, + 0x6C, 0x33, 0x35, 0x56, 0xC7, 0x1C, 0xC8, 0xB9, 0x48, 0xAF, 0xC7, 0x05, 0xFF, 0x92, 0x81, 0x4E, 0xDB, 0xFF, 0xA3, 0x2C, + 0xDC, 0x71, 0xD9, 0xB9, 0xB5, 0xA0, 0xB7, 0x94, 0x46, 0xC2, 0xB6, 0x10, 0x3C, 0x7B, 0xAD, 0x2C, 0xE0, 0xAE, 0x8C, 0x04, + 0x22, 0xE0, 0x65, 0xB4, 0x0B, 0x55, 0x1F, 0x06, 0x62, 0x15, 0x22, 0x39, 0x58, 0xB3, 0x79, 0x63, 0x6F, 0xA5, 0x19, 0xA5, + 0x8A, 0xDE, 0xB2, 0x53, 0xBB, 0x6D, 0x8C, 0xE2, 0xD1, 0xF7, 0xA9, 0x34, 0x6C, 0xA4, 0xE6, 0x5A, 0x4E, 0xB5, 0x0B, 0xCA, + 0xD7, 0xA8, 0xBB, 0x80, 0x42, 0x89, 0x82, 0x24, 0x0D, 0xA5, 0xD4, 0xE4, 0x79, 0x1C, 0xC6, 0x94, 0xAD, 0x2B, 0xEB, 0xF9, + 0xEA, 0xE4, 0xB6, 0x79, 0x20, 0x34, 0x9E, 0x98, 0x41, 0x08, 0xA2, 0x14, 0x5A, 0xE8, 0x18, 0xC1, 0x25, 0x00, 0x94, 0xA5, + 0xB5, 0xAB, 0x08, 0x65, 0x67, 0x4D, 0x88, 0x54, 0x77, 0x99, 0x31, 0xA0, 0x20, 0xF7, 0xE9, 0x44, 0x72, 0x88, 0x01, 0xF5, + 0xC5, 0xAC, 0xA7, 0x59, 0xB0, 0x16, 0xA2, 0x16, 0x84, 0x05, 0x02, 0x2C, 0x2B, 0x5B, 0x1A, 0x38, 0x3F, 0x68, 0xEE, 0x52, + 0xB3, 0x59, 0x08, 0xE5, 0x01, 0x0D, 0xF8, 0x1D, 0x57, 0x32, 0xB7, 0x46, 0xD4, 0x74, 0xA4, 0x14, 0xD4, 0x9F, 0xEF, 0x9A, + 0x98, 0x02, 0xA3, 0x84, 0x71, 0x69, 0x33, 0x2D, 0xBF, 0x4A, 0xCA, 0xA9, 0x7D, 0x95, 0x8B, 0xE4, 0x89, 0xFF, 0x5A, 0x7B, + 0xD9, 0x64, 0x84, 0xD9, 0xCD, 0x3E, 0xD3, 0x39, 0x05, 0x7A, 0x60, 0xBB, 0x6E, 0x17, 0x57, 0xA4, 0x62, 0x61, 0x65, 0x77, + 0x2E, 0x57, 0xC4, 0x40, 0xE9, 0xA1, 0x74, 0x6C, 0x38, 0x59, 0x4B, 0x65, 0x28, 0x8C, 0x42, 0x6C, 0xAF, 0x8C, 0x61, 0x9C, + 0x47, 0xC0, 0x60, 0x3D, 0xAB, 0x8C, 0xC1, 0xBE, 0xEA, 0x8A, 0xF2, 0x1F, 0xA3, 0x8F, 0x28, 0x9F, 0xFB, 0x1F, 0xD1, 0x39, + 0xD3, 0x14, 0x91, 0x58, 0x3C, 0x2B, 0x61, 0x91, 0x8B, 0x00, 0xDA, 0xF9, 0xD5, 0x95, 0xDF, 0xDE, 0x5F, 0x01, 0x13, 0x74, + 0x48, 0xC1, 0x02, 0xAD, 0xD3, 0xFD, 0xAA, 0x91, 0x18, 0x59, 0xCC, 0x69, 0x0A, 0x9C, 0x8A, 0x34, 0x39, 0x3B, 0xDC, 0x20, + 0x60, 0x13, 0x5C, 0x4C, 0x64, 0x75, 0xD8, 0x90, 0xDB, 0xED, 0xFC, 0xF6, 0x92, 0x7D, 0x45, 0x47, 0xA8, 0x22, 0x6A, 0x21, + 0xC5, 0x9D, 0x73, 0xAC, 0x4A, 0x10, 0xB3, 0x98, 0x3E, 0xB5, 0x5B, 0x7B, 0x5A, 0x11, 0x9F, 0xC7, 0xC2, 0x33, 0x04, 0xA6, + 0x01, 0xD4, 0x86, 0x27, 0xD9, 0x85, 0x8D, 0xDC, 0x59, 0x6A, 0xCD, 0x9F, 0xD1, 0xD4, 0x4E, 0x36, 0x10, 0x17, 0x5F, 0x24, + 0x4B, 0x94, 0xCD, 0x18, 0x0B, 0xDE, 0xDA, 0x14, 0xFE, 0x34, 0x47, 0x27, 0x43, 0x0D, 0x05, 0x55, 0x19, 0x99, 0x8A, 0xF0, + 0xE4, 0x94, 0x44, 0x96, 0xC6, 0xFF, 0xF5, 0xC1, 0x04, 0x7B, 0x5C, 0x3F, 0x16, 0xC8, 0xA2, 0x17, 0xE5, 0xF5, 0x62, 0x07, + 0xD0, 0xFF, 0x38, 0xB4, 0x6A, 0xE7, 0x02, 0x4C, 0x7C, 0x95, 0x50, 0x3B, 0x97, 0x65, 0x6E, 0x44, 0x50, 0x35, 0x06, 0x9C, + 0x01, 0x81, 0x8C, 0xEE, 0x0A, 0x31, 0xC5, 0xB9, 0xE9, 0x19, 0x9C, 0x5A, 0xF6, 0x8F, 0x39, 0x29, 0x25, 0xEC, 0x84, 0x1F, + 0xB4, 0x32, 0xFB, 0x36, 0xE9, 0xDA, 0x68, 0x45, 0xB6, 0x37, 0xCF, 0x09, 0xA8, 0x59, 0x77, 0xB9, 0xD2, 0x2A, 0xC4, 0xB9, + 0x74, 0x86, 0xD7, 0xB9, 0xF0, 0xFF, 0x24, 0xD8, 0x2B, 0x5D, 0xBC, 0xAC, 0x7E, 0xC1, 0x06, 0x17, 0x0B, 0x09, 0xE8, 0xF1, + 0x99, 0x75, 0x04, 0x78, 0xD4, 0xEA, 0x0B, 0xCF, 0x2F, 0xCC, 0xAB, 0x98, 0x73, 0xA0, 0x87, 0xCD, 0xDC, 0x7B, 0x27, 0xCB, + 0xD1, 0x13, 0xC5, 0x3E, 0xC6, 0x3A, 0x4F, 0xF5, 0x17, 0xD7, 0x00, 0x9E, 0xEE, 0xFE, 0x0F, 0x59, 0x42, 0x67, 0xEF, 0x49, + 0x5A, 0x90, 0x45, 0xD6, 0xCA, 0xDF, 0xF7, 0x93, 0xFD, 0xDD, 0x74, 0x11, 0x7C, 0xC4, 0x18, 0xF9, 0xF6, 0x80, 0x64, 0x51, + 0x6E, 0xB9, 0x8E, 0x0F, 0x5A, 0x82, 0xC4, 0x81, 0x1D, 0x89, 0x2A, 0x69, 0xF7, 0xE1, 0x8F, 0x82, 0x43, 0x43, 0xA9, 0x76, + 0x71, 0xA3, 0x07, 0x3B, 0x08, 0x8F, 0xA3, 0xEF, 0xB0, 0xA6, 0x29, 0x07, 0x30, 0xA1, 0xFB, 0x9A, 0x59, 0x44, 0x2B, 0xEE, + 0x8D, 0x87, 0xAF, 0xFF, 0xA7, 0x0E, 0xA5, 0xF4, 0x38, 0x65, 0xA5, 0x54, 0x3E, 0x22, 0x20, 0xB2, 0x0E, 0xCB, 0xA9, 0xAE, + 0x32, 0xE9, 0x4E, 0x2F, 0x67, 0x04, 0xCF, 0x84, 0xBF, 0xD4, 0x52, 0xBA, 0x47, 0xCA, 0x13, 0x2B, 0x34, 0x95, 0x33, 0x94, + 0xC5, 0x11, 0x39, 0xF2, 0x51, 0x43, 0x38, 0x4D, 0x62, 0x47, 0x1E, 0xAF, 0xEE, 0xEB, 0x28, 0x73, 0x63, 0x67, 0xD1, 0xE3, + 0x33, 0x67, 0x30, 0x73, 0x22, 0x26, 0x52, 0x47, 0x7C, 0xD6, 0x21, 0x11, 0x38, 0xDC, 0x39, 0xF2, 0x88, 0x5A, 0xA2, 0xF7, + 0x0C, 0x7C, 0xF2, 0xE8, 0x80, 0xEB, 0xE0, 0x54, 0x86, 0x6B, 0x8C, 0x1B, 0xD1, 0x4E, 0x3D, 0xF7, 0x45, 0x32, 0x06, 0x8C, + 0x55, 0xA3, 0x04, 0x37, 0x8F, 0x69, 0x3A, 0x58, 0x1D, 0xA6, 0xF3, 0xF7, 0x59, 0x71, 0xA5, 0x17, 0x75, 0x5B, 0x3B, 0xAF, + 0x50, 0xE9, 0x21, 0xEF, 0xCA, 0xF1, 0xD4, 0x9F, 0xF6, 0xA0, 0x2E, 0x20, 0xE1, 0x0B, 0x73, 0x33, 0xAE, 0xDA, 0xD9, 0x3E, + 0xDC, 0xC9, 0x73, 0xB5, 0x83, 0x2A, 0xBC, 0x62, 0x16, 0xA8, 0x70, 0x0C, 0xC3, 0x3A, 0x8A, 0x18, 0x3E, 0xBA, 0x95, 0x29, + 0x37, 0xE3, 0x94, 0x72, 0x19, 0x2F, 0xBA, 0x82, 0x5A, 0x8C, 0x85, 0xFA, 0x15, 0x92, 0x72, 0x8B, 0x8A, 0x75, 0xE5, 0x3D, + 0x75, 0xDF, 0x7B, 0x7A, 0x2F, 0x81, 0x33, 0xEB, 0x5B, 0xE3, 0x8C, 0x1B, 0xE1, 0x94, 0x97, 0xAC, 0xEF, 0xED, 0x22, 0x56, + 0xBC, 0xCF, 0xE9, 0x05, 0xD9, 0x8D, 0x62, 0xD8, 0xDB, 0xD2, 0x5B, 0x6E, 0xE4, 0x7D, 0x99, 0xC9, 0x19, 0xDB, 0x8E, 0x40, + 0x72, 0x49, 0x73, 0xF7, 0x4E, 0xF2, 0xD3, 0x12, 0x6C, 0x55, 0xEC, 0xDF, 0x44, 0x4B, 0x2A, 0xC4, 0x8A, 0xEA, 0x63, 0x89, + 0x5F, 0xD0, 0x5A, 0x6A, 0x84, 0x3F, 0xB5, 0x8C, 0xC2, 0x7F, 0xE4, 0xB8, 0xC4, 0x26, 0x2D, 0x8C, 0xC7, 0xD1, 0x0A, 0xA2, + 0x86, 0xE7, 0x8E, 0x02, 0x19, 0x10, 0xFD, 0xD1, 0xD4, 0xE3, 0x3C, 0xD3, 0x15, 0xA1, 0x71, 0x2E, 0x4E, 0xF9, 0xCB, 0x50, + 0xD0, 0xA4, 0xE9, 0x95, 0x6E, 0xFB, 0x2C, 0xB4, 0x65, 0xDA, 0x54, 0xC6, 0xDC, 0x04, 0xFD, 0xCA, 0x54, 0x74, 0x6D, 0xB1, + 0xBD, 0xA5, 0xDD, 0xA3, 0xEA, 0x8D, 0xE7, 0x34, 0xC6, 0xA6, 0x4F, 0x10, 0xDA, 0x72, 0xCF, 0x14, 0xC2, 0x5B, 0x4D, 0xDB, + 0x4E, 0x76, 0xEC, 0xB1, 0xF7, 0x18, 0x27, 0xF7, 0x40, 0x2A, 0xB5, 0xC3, 0x94, 0x85, 0x64, 0xCA, 0x2A, 0x3A, 0x1C, 0x71, + 0x03, 0xA9, 0xF6, 0x3A, 0x41, 0xB6, 0xD6, 0xB0, 0x46, 0xF5, 0x48, 0x61, 0x2B, 0x22, 0x08, 0x81, 0x59, 0x14, 0x58, 0x1F, + 0x6C, 0x41, 0x01, 0x79, 0xBF, 0xB9, 0x4E, 0x74, 0xAA, 0x38, 0xF8, 0x0E, 0xBA, 0x02, 0x88, 0x38, 0x8E, 0x07, 0x1B, 0x3C, + 0x90, 0x05, 0xB3, 0x6A, 0xC7, 0x9B, 0x3D, 0x6D, 0x9C, 0xDB, 0x01, 0x1F, 0xCE, 0x19, 0xB7, 0xB6, 0x00, 0x7D, 0x70, 0xAB, + 0xD1, 0xDE, 0x75, 0xDD, 0x2A, 0x4D, 0x64, 0xCC, 0x4F, 0x8E, 0xE0, 0xC2, 0x78, 0xBE, 0xB8, 0xB8, 0xD0, 0x30, 0x16, 0x5A, + 0x31, 0x17, 0x6C, 0x0C, 0x4E, 0x7C, 0xEC, 0x80, 0x79, 0x9F, 0xFE, 0x3C, 0x2C, 0x4A, 0xBE, 0xFE, 0xDD, 0x1E, 0x65, 0x04, + 0xCF, 0x2E, 0x51, 0x6B, 0xB4, 0xA1, 0x7E, 0x1C, 0x71, 0x97, 0xFF, 0xBD, 0xF7, 0xA4, 0x6D, 0x0C, 0xCE, 0x0F, 0xE6, 0x80, + 0x5C, 0x74, 0xE5, 0x31, 0x34, 0x42, 0x38, 0xFB, 0x00, 0x6D, 0xF3, 0x60, 0x0A, 0xCB, 0x86, 0x88, 0x56, 0xE2, 0xF1, 0x20, + 0xA2, 0x43, 0x48, 0x96, 0x9C, 0xD7, 0xBE, 0xB4, 0x47, 0x47, 0x3B, 0x80, 0x8D, 0x82, 0xC1, 0x79, 0x86, 0xA0, 0x16, 0x42, + 0x9E, 0x60, 0xD4, 0x1C, 0xC6, 0x00, 0x7E, 0xA1, 0xA6, 0xB6, 0xCD, 0x79, 0x7C, 0x0C, 0xC1, 0x10, 0xEE, 0x03, 0x66, 0xB5, + 0xBA, 0x2A, 0xC3, 0xBA, 0xB9, 0x30, 0xE3, 0xF4, 0xDE, 0xE7, 0x00, 0xC0, 0x97, 0x66, 0x10, 0x3B, 0x44, 0x86, 0x41, 0x23, + 0x5C, 0xCB, 0x88, 0xD4, 0x72, 0xFA, 0x0F, 0x96, 0xB2, 0xDA, 0x60, 0x8E, 0xEF, 0x48, 0xA6, 0x59, 0xD1, 0xA2, 0x1B, 0xCE, + 0xEA, 0x85, 0x16, 0x7B, 0x94, 0xA4, 0x90, 0xE3, 0x2C, 0xC0, 0x40, 0x16, 0xEE, 0x04, 0x92, 0x51, 0xE0, 0x71, 0xA1, 0x37, + 0x64, 0x65, 0xA6, 0x55, 0x38, 0xDC, 0x1C, 0x17, 0x2C, 0xBC, 0x04, 0x24, 0x88, 0x66, 0x12, 0xE4, 0x7C, 0x65, 0xD2, 0xAD, + 0xE1, 0x40, 0x52, 0xA8, 0x29, 0x97, 0xF5, 0xF0, 0x6D, 0x44, 0xD3, 0xB1, 0x1F, 0x6B, 0x43, 0x85, 0xEC, 0xC0, 0x8C, 0x90, + 0xB2, 0x2D, 0x93, 0xE1, 0xF0, 0x47, 0x78, 0x89, 0x9E, 0x8E, 0x97, 0xD4, 0xC0, 0x0B, 0x48, 0x2D, 0xBB, 0xFC, 0x94, 0xF9, + 0xD1, 0x10, 0x2F, 0xDA, 0x47, 0x21, 0x9B, 0x59, 0xC5, 0xB0, 0xA1, 0x8D, 0x3F, 0xC4, 0x54, 0xF9, 0x0C, 0x4E, 0xD9, 0x00, + 0x99, 0x21, 0x52, 0xEC, 0x75, 0xD0, 0xD2, 0xE8, 0x5C, 0x4A, 0x8A, 0xB5, 0xDA, 0xD9, 0x66, 0x23, 0xC1, 0xF0, 0xA2, 0x90, + 0x29, 0x00, 0x9A, 0xFE, 0xBD, 0x1B, 0x58, 0xB2, 0xF9, 0x0E, 0xBC, 0x8F, 0x3B, 0xB1, 0xC3, 0x1B, 0xF9, 0x46, 0x13, 0xD0, + 0x3C, 0x64, 0x1A, 0x46, 0xB1, 0x4D, 0xA8, 0x1D, 0xDF, 0x34, 0x41, 0x78, 0xEA, 0x0F, 0xE3, 0x82, 0xAC, 0x6F, 0x4C, 0x05, + 0x13, 0x51, 0xCC, 0x81, 0x4F, 0x10, 0x95, 0x48, 0x5E, 0x1D, 0xD5, 0x20, 0x36, 0x12, 0xCC, 0x4C, 0xDA, 0x53, 0xF3, 0xAB, + 0x29, 0x73, 0xEB, 0xB1, 0x6D, 0xAA, 0xE7, 0x4F, 0xF2, 0x7C, 0xBD, 0xB1, 0x3E, 0x50, 0x15, 0x78, 0xB0, 0x73, 0xEA, 0x25, + 0x8B, 0x2D, 0x55, 0xDD, 0xE5, 0xFF, 0x52, 0xF4, 0xA7, 0x71, 0xD2, 0xF0, 0x58, 0xE3, 0x19, 0x95, 0x08, 0x23, 0x60, 0x77, + 0x50, 0x2C, 0x0C, 0xDC, 0xA0, 0xF3, 0x7C, 0x2B, 0xD3, 0x6B, 0x8F, 0xE0, 0x51, 0xF7, 0x6F, 0x77, 0x46, 0x35, 0x74, 0x2F, + 0xC2, 0x8A, 0x33, 0x13, 0x35, 0x17, 0x9C, 0xB6, 0x65, 0xA6, 0x4D, 0x51, 0x9A, 0xBF, 0xA7, 0xA3, 0x55, 0x73, 0xB8, 0x2F, + 0x31, 0x3B, 0xED, 0xD1, 0x74, 0x14, 0x85, 0xC8, 0x94, 0x77, 0x32, 0x55, 0xE5, 0x45, 0x02, 0x15, 0xE5, 0x2C, 0xEE, 0x75, + 0xA1, 0xA5, 0xCB, 0x97, 0x08, 0xDA, 0x78, 0xCF, 0xFE, 0x12, 0x2A, 0x09, 0xCF, 0xC5, 0xFA, 0x3A, 0x2C, 0x52, 0xFE, 0xCE, + 0xC3, 0x76, 0x57, 0xB1, 0x8C, 0xE6, 0xD8, 0x1E, 0xD7, 0x7F, 0x18, 0x78, 0x25, 0xF4, 0x61, 0xD2, 0x0F, 0xA6, 0x83, 0x74, + 0xA0, 0x5B, 0x17, 0x92, 0xDA, 0x8E, 0x10, 0xDA, 0xB8, 0xDC, 0xAF, 0x47, 0x45, 0x8B, 0x75, 0xF9, 0xAF, 0x00, 0x4F, 0x1C, + 0x1C, 0x3B, 0x1C, 0xFE, 0x2B, 0x3B, 0xA0, 0x14, 0x02, 0xE6, 0x26, 0x7F, 0xEC, 0x11, 0x15, 0xAA, 0x09, 0xDD, 0x3E, 0x8A, + 0x95, 0x52, 0x98, 0x49, 0x89, 0xF7, 0xE7, 0xA6, 0xBE, 0x1B, 0xC8, 0x36, 0x3D, 0x3F, 0xD7, 0x86, 0xEA, 0x50, 0x84, 0x6F, + 0x09, 0x88, 0xBC, 0xEE, 0x0B, 0x61, 0x07, 0x5D, 0x06, 0x45, 0x6F, 0x17, 0xEC, 0xC7, 0xCF, 0xD4, 0x11, 0x3A, 0xB9, 0x5F, + 0x0A, 0x80, 0x47, 0xAF, 0x84, 0xBF, 0xE0, 0xBB, 0x4A, 0xAA, 0x7F, 0x03, 0x02, 0xFE, 0x75, 0x64, 0x02, 0x33, 0x24, 0xFB, + 0x1C, 0xE1, 0x34, 0x06, 0xA5, 0x3F, 0x14, 0x44, 0x52, 0x33, 0xAC, 0xEF, 0x0D, 0xC0, 0xF0, 0x13, 0x05, 0xA5, 0x3C, 0x37, + 0x3A, 0xE1, 0xED, 0xB2, 0x5B, 0xAF, 0x28, 0x44, 0x52, 0x88, 0xF8, 0x3E, 0x31, 0x7B, 0xF1, 0x4E, 0x60, 0x35, 0x12, 0x39, + 0xE6, 0x16, 0x70, 0x2A, 0x20, 0x7C, 0x29, 0xFF, 0xE9, 0xEE, 0xA9, 0xB7, 0xCB, 0x97, 0x80, 0x75, 0x74, 0xDE, 0x26, 0x01, + 0x00, 0xC6, 0xE8, 0xB6, 0x1E, 0xEB, 0x4C, 0x59, 0x40, 0x86, 0x30, 0xE2, 0xA0, 0xE9, 0xA8, 0xC6, 0x09, 0xC7, 0xB1, 0xF3, + 0x11, 0x27, 0x79, 0x14, 0x27, 0x97, 0xFA, 0x04, 0x64, 0xED, 0x5E, 0xC7, 0xC4, 0x94, 0x71, 0xAF, 0xF0, 0xEB, 0x15, 0x9C, + 0xB1, 0xC6, 0x31, 0xDA, 0x30, 0xEE, 0x72, 0x1F, 0x05, 0x60, 0x5C, 0xBA, 0xDF, 0xE5, 0xB9, 0xF7, 0x0D, 0x78, 0x01, 0x53, + 0x76, 0x58, 0x7B, 0x2E, 0xA9, 0x71, 0xDC, 0xBE, 0x7F, 0xDE, 0x3A, 0x2F, 0x33, 0xE8, 0x9A, 0x4C, 0xE9, 0xE4, 0xEA, 0x9E, + 0x34, 0xCB, 0x61, 0xE5, 0x1B, 0x12, 0xC5, 0xBE, 0x26, 0xB6, 0x7A, 0xAF, 0xD4, 0xAB, 0x7B, 0x2F, 0xBF, 0x4B, 0xB5, 0xBF, + 0x9A, 0xE8, 0xA3, 0xC3, 0xA8, 0x87, 0x8B, 0x40, 0x5D, 0xE7, 0x7C, 0x53, 0x02, 0x5D, 0x37, 0x9B, 0xD7, 0x56, 0x84, 0x4B, + 0xC5, 0xC2, 0x7B, 0x44, 0xDB, 0x69, 0x80, 0x34, 0xAD, 0xE9, 0x26, 0x14, 0xFF, 0xD7, 0x29, 0x6A, 0x48, 0xB7, 0xA9, 0x6E, + 0x58, 0x97, 0x15, 0xDE, 0x01, 0xC3, 0x2A, 0xDE, 0xC6, 0x50, 0xC5, 0x38, 0xEE, 0x8F, 0xFA, 0xFA, 0x60, 0x71, 0xDC, 0xA9, + 0x6F, 0x11, 0xE1, 0xA1, 0x25, 0xB1, 0x58, 0x15, 0x4F, 0xC3, 0xD8, 0x4B, 0x25, 0x75, 0xC7, 0xDF, 0x85, 0x75, 0xC3, 0x3D, + 0xAC, 0xEC, 0xBB, 0xC5, 0x6E, 0x30, 0x17, 0x00, 0x15, 0x9E, 0xB4, 0xE4, 0xD3, 0x6D, 0xA4, 0x86, 0x34, 0x3D, 0x7C, 0xA7, + 0x1B, 0xF0, 0xE5, 0x5C, 0x72, 0x32, 0x75, 0xA6, 0x80, 0x47, 0x18, 0x74, 0xFD, 0x32, 0x74, 0x33, 0x8C, 0x41, 0xA3, 0x46, + 0x6B, 0x50, 0x89, 0x1D, 0xA7, 0xA2, 0xC5, 0x30, 0x72, 0xBD, 0xA5, 0x27, 0xA2, 0xE2, 0x74, 0xB6, 0xC2, 0xD7, 0x25, 0x96, + 0xDA, 0xB3, 0x7C, 0xE4, 0x83, 0xDF, 0x4F, 0xB6, 0xB9, 0xC8, 0xEF, 0x33, 0xF3, 0x17, 0xD0, 0xA0, 0xDD, 0xF1, 0x24, 0x42, + 0x9F, 0xF6, 0x75, 0x1E, 0x66, 0xCF, 0xEC, 0x1D, 0x87, 0x77, 0xC0, 0x5D, 0xD8, 0x48, 0xB5, 0x96, 0x54, 0x95, 0xBC, 0x76, + 0xAD, 0x6A, 0x46, 0xC7, 0xD6, 0x8A, 0x5D, 0x3D, 0x0A, 0x9B, 0xA3, 0xCE, 0xB7, 0x16, 0x23, 0x85, 0x86, 0x84, 0x10, 0x1D, + 0xC5, 0x60, 0x8C, 0x2D, 0x5E, 0x11, 0x15, 0x3F, 0x91, 0xFA, 0x26, 0xF3, 0xE1, 0xAC, 0x3D, 0x1E, 0xDB, 0xEC, 0xB6, 0xF9, + 0x30, 0x91, 0xC0, 0x3F, 0x3F, 0x13, 0xA5, 0x2E, 0x6A, 0x5C, 0x49, 0x52, 0x7C, 0x73, 0x96, 0x65, 0x1E, 0xEA, 0x6E, 0x1A, + 0xF1, 0x46, 0xD9, 0xFA, 0x61, 0x22, 0x7E, 0xA9, 0x86, 0x62, 0xB3, 0xBB, 0xC0, 0x85, 0xFD, 0x02, 0xD4, 0xE9, 0xC8, 0xD8, + 0xFC, 0xB4, 0x72, 0x9E, 0x96, 0xB8, 0x97, 0x65, 0x50, 0xF5, 0x74, 0x9F, 0xDE, 0x29, 0x3B, 0x9F, 0xDE, 0xBA, 0xBF, 0x3B, + 0xC2, 0x67, 0x66, 0x31, 0xDF, 0x1A, 0x19, 0x09, 0xF4, 0x6C, 0x5D, 0x94, 0xEF, 0xD1, 0xFB, 0x88, 0x9C, 0xBC, 0x74, 0x5E, + 0x21, 0x01, 0x59, 0xC2, 0x54, 0xEC, 0x7B, 0x06, 0x6F, 0xC6, 0xA7, 0xB7, 0xDA, 0x7D, 0x67, 0x31, 0x4F, 0xE5, 0xEF, 0xCB, + 0x3E, 0xFE, 0xC8, 0xA9, 0x4F, 0x2B, 0x73, 0x29, 0xCA, 0xBF, 0xAF, 0x5E, 0x28, 0xDD, 0xEF, 0xC0, 0x83, 0x12, 0x29, 0x9D, + 0x8F, 0x89, 0x07, 0xDB, 0xFF, 0xFF, 0xA8, 0x31, 0x33, 0xC5, 0xFE, 0x29, 0x9F, 0x8D, 0x2D, 0xA4, 0x46, 0xD1, 0xDA, 0xCB, + 0xF3, 0x6D, 0xF7, 0xF6, 0xE8, 0x10, 0xA8, 0xFE, 0x78, 0x50, 0xE7, 0xC1, 0xE2, 0x01, 0x10, 0x04, 0xB0, 0x6E, 0xB9, 0xF2, + 0xB0, 0x89, 0x92, 0x96, 0x87, 0xA9, 0x29, 0xDF, 0x6C, 0x4F, 0xDB, 0xDE, 0x73, 0x64, 0xA5, 0x82, 0x8E, 0x0B, 0xE8, 0x55, + 0x95, 0x6D, 0x24, 0x03, 0xA1, 0x4A, 0x2D, 0xD7, 0x53, 0x6B, 0x80, 0xA8, 0x7A, 0x02, 0xE8, 0x26, 0xAB, 0x28, 0x82, 0x91, + 0x7E, 0xA1, 0xEA, 0xD4, 0xDA, 0xCB, 0x5F, 0xD2, 0x06, 0xB5, 0x75, 0x16, 0xB2, 0x88, 0x4F, 0x47, 0x28, 0x94, 0xE0, 0x9F, + 0x33, 0x45, 0xC9, 0x48, 0x84, 0x1D, 0xF9, 0x2B, 0x13, 0x2B, 0x0F, 0x59, 0xE3, 0xED, 0x75, 0x41, 0x39, 0x02, 0x89, 0xB9, + 0xFB, 0xFC, 0x9D, 0x12, 0x9D, 0xB8, 0x41, 0x62, 0xF7, 0x56, 0xA6, 0x07, 0xFD, 0xF8, 0x06, 0x2C, 0x8A, 0xEF, 0x94, 0xAC, + 0x70, 0x8A, 0x6C, 0x2E, 0xA1, 0x47, 0x26, 0x3C, 0xFB, 0x6E, 0x9E, 0x3F, 0xA8, 0x8E, 0xBD, 0x98, 0x7F, 0xE6, 0x22, 0xC2, + 0xE5, 0x44, 0xFA, 0x7D, 0xDD, 0x64, 0xD9, 0x6B, 0x6A, 0x5F, 0x93, 0x81, 0x9A, 0x31, 0x41, 0x1E, 0x23, 0x2E, 0x1B, 0x41, + 0x39, 0x65, 0x45, 0x85, 0x25, 0x06, 0x8A, 0x99, 0xF7, 0xCA, 0x64, 0xC8, 0x6A, 0x0B, 0x91, 0x39, 0x7A, 0xE0, 0x58, 0xCC, + 0x54, 0x51, 0xFC, 0xE8, 0x14, 0x93, 0x6C, 0x40, 0x6B, 0x5F, 0x42, 0x2B, 0x80, 0xF1, 0xB5, 0x0A, 0x05, 0x6F, 0x0A, 0xE9, + 0x9C, 0x41, 0x25, 0x0A, 0x21, 0xFC, 0xFA, 0xF6, 0x7F, 0xE6, 0x23, 0x0D, 0xC4, 0x03, 0xD5, 0x2F, 0x65, 0xB3, 0x6D, 0x55, + 0xAA, 0xCE, 0xC9, 0x6F, 0x69, 0xE5, 0x01, 0x5C, 0xA9, 0x02, 0xF5, 0xF9, 0x41, 0x50, 0x20, 0x88, 0xCA, 0x4F, 0x33, 0x41, + 0x30, 0x2B, 0xA8, 0xA4, 0xC1, 0xBF, 0xBC, 0x54, 0xCE, 0x3F, 0x91, 0xE7, 0x81, 0xF6, 0xC1, 0x46, 0xF2, 0x73, 0x46, 0xA0, + 0xD6, 0x2E, 0x84, 0x76, 0x9D, 0xBA, 0x7A, 0x9D, 0x8A, 0x20, 0x19, 0x56, 0xF3, 0x72, 0x10, 0x72, 0x94, 0xBF, 0xE5, 0xC1, + 0x91, 0xB9, 0x06, 0x52, 0x90, 0xDF, 0xD2, 0x47, 0x72, 0x71, 0x2B, 0xB9, 0x02, 0x96, 0x09, 0x77, 0x33, 0x7B, 0x23, 0x89, + 0x89, 0x02, 0x0B, 0x57, 0x73, 0x5B, 0xCC, 0xC9, 0x24, 0x0F, 0xFD, 0x7C, 0xC1, 0x2F, 0xC7, 0x13, 0x16, 0x89, 0xEC, 0x0F, + 0xCD, 0xC9, 0x1C, 0xB2, 0x67, 0x13, 0x7F, 0xE9, 0xCF, 0x36, 0x1A, 0xD8, 0xE3, 0xD9, 0xC7, 0x7E, 0x57, 0x7A, 0x97, 0xBE, + 0x2F, 0x74, 0xB1, 0x41, 0xB8, 0xF8, 0x03, 0xD8, 0x09, 0xE7, 0x30, 0x15, 0x72, 0x69, 0xC5, 0xC8, 0xA5, 0x0C, 0xF7, 0x2F, + 0x48, 0x2C, 0x63, 0xD8, 0x2B, 0x06, 0x84, 0xED, 0x56, 0xA8, 0x58, 0x6A, 0x2C, 0x9D, 0x4F, 0xFE, 0x9B, 0x3E, 0x68, 0x84, + 0x81, 0x29, 0x2F, 0xCE, 0x3B, 0xC7, 0x30, 0x7A, 0x4B, 0xED, 0x06, 0x9E, 0x98, 0xB3, 0x1B, 0xBA, 0xEF, 0xF4, 0x5E, 0x54, + 0x74, 0x7F, 0x15, 0x51, 0x43, 0x5E, 0x0F, 0x59, 0x1B, 0x3C, 0x41, 0x80, 0x03, 0x6B, 0xEF, 0x2F, 0xF1, 0x47, 0xB8, 0x9F, + 0x42, 0xAA, 0x50, 0x7F, 0x15, 0x36, 0x0E, 0x3D, 0x87, 0x2C, 0x17, 0xB9, 0x58, 0xF1, 0x94, 0xEC, 0x2C, 0xFF, 0xB2, 0x48, + 0x54, 0xDD, 0x2E, 0xDA, 0xA2, 0x53, 0xD7, 0x8A, 0x5E, 0xDD, 0xB5, 0x2B, 0x13, 0xB0, 0x86, 0xD5, 0x08, 0x1A, 0x0A, 0xBF, + 0x65, 0x02, 0x7E, 0x8E, 0x19, 0xDA, 0x23, 0xBA, 0xE9, 0x9F, 0x6B, 0x49, 0xB0, 0xC4, 0x03, 0x1A, 0xCC, 0xF3, 0xEF, 0xDD, + 0x45, 0xD1, 0x83, 0x49, 0x40, 0x4E, 0x0F, 0x59, 0xB5, 0x3F, 0x61, 0x5D, 0xE5, 0x20, 0xA1, 0xFA, 0x5A, 0xA0, 0x52, 0xD3, + 0x1E, 0xE5, 0x4C, 0x82, 0x1E, 0x5A, 0x0D, 0x10, 0x24, 0x49, 0xB4, 0xA2, 0x67, 0x78, 0x48, 0xA5, 0x76, 0x8C, 0x38, 0x51, + 0x31, 0xA7, 0x6A, 0x05, 0xAE, 0xA5, 0xB2, 0x26, 0xF6, 0xEC, 0x19, 0xB1, 0x30, 0x00, 0xA9, 0x06, 0xB0, 0xCC, 0x4F, 0x25, + 0x2D, 0xCD, 0xD1, 0x87, 0x68, 0xEF, 0xD2, 0x34, 0x24, 0x7C, 0x21, 0x6F, 0x74, 0xAC, 0x01, 0xDD, 0x69, 0xCE, 0xB3, 0x77, + 0x76, 0xEE, 0xE2, 0xC0, 0x03, 0xA4, 0xDE, 0xE7, 0xC4, 0xFB, 0x56, 0x4B, 0x4F, 0xB1, 0xCA, 0xD6, 0x82, 0x4B, 0x42, 0xD7, + 0x09, 0xE7, 0x28, 0x02, 0x2E, 0xAB, 0xEB, 0x4C, 0x3F, 0x87, 0x87, 0x04, 0x35, 0xA6, 0xA1, 0xAB, 0xE0, 0x7B, 0xBE, 0x27, + 0xE5, 0x13, 0x62, 0x4D, 0xFA, 0x33, 0x55, 0x05, 0xB6, 0xE6, 0x23, 0x52, 0xA5, 0x8A, 0xD1, 0xB8, 0x14, 0xAA, 0xE6, 0xC7, + 0x2E, 0xF6, 0x82, 0x0C, 0xB6, 0x87, 0x42, 0xBD, 0x3B, 0x85, 0xC2, 0x4A, 0x25, 0xEA, 0x9E, 0xB1, 0xB7, 0x95, 0xF8, 0xC1, + 0xFF, 0xEE, 0x12, 0x67, 0x2C, 0x49, 0x8E, 0x7C, 0x5E, 0x16, 0x44, 0x02, 0xB4, 0x1F, 0xC2, 0xBC, 0x7F, 0x49, 0xB8, 0xEB, + 0x80, 0xEF, 0xFA, 0xB2, 0x1E, 0xE2, 0x50, 0x70, 0x41, 0x3C, 0x3B, 0x38, 0xBF, 0xCA, 0x83, 0x8B, 0x08, 0x19, 0xD3, 0x9D, + 0xBF, 0xDE, 0x45, 0x16, 0xEF, 0x26, 0x81, 0xDD, 0x5F, 0xE8, 0xE0, 0xC8, 0x0B, 0x2C, 0x1B, 0x8C, 0xBF, 0x93, 0xB2, 0xDF, + 0xD8, 0x6D, 0x8C, 0x68, 0x8E, 0x88, 0xE2, 0xCE, 0xAE, 0x72, 0x7D, 0xA1, 0xAA, 0x7E, 0x2C, 0x57, 0xA4, 0xBC, 0xA4, 0x9C, + 0x1F, 0x40, 0xA3, 0xA3, 0xE8, 0x88, 0x8B, 0x2D, 0x2D, 0xD3, 0x60, 0x98, 0xBE, 0x13, 0x63, 0xED, 0x5F, 0xB3, 0x3B, 0x39, + 0xCB, 0x89, 0x10, 0x34, 0xE5, 0x10, 0xBB, 0xCE, 0x5D, 0x6E, 0x69, 0x7B, 0xD9, 0x7E, 0x83, 0xBE, 0x53, 0x75, 0xEE, 0x78, + 0x97, 0xB6, 0x0C, 0x58, 0xC8, 0xDD, 0xCB, 0x44, 0xF6, 0xB8, 0xEC, 0x63, 0x1D, 0x1C, 0x51, 0x74, 0x94, 0x3B, 0xC7, 0xC9, + 0x6B, 0x2E, 0xC4, 0x34, 0x70, 0xA1, 0xFA, 0xE3, 0x5C, 0x83, 0xAD, 0x03, 0x15, 0x38, 0x4A, 0xD9, 0x69, 0xB0, 0x37, 0xC5, + 0xB7, 0x4D, 0x50, 0xE0, 0xE6, 0x12, 0xD2, 0x75, 0x19, 0xBE, 0x91, 0xC0, 0xD1, 0x25, 0x85, 0x67, 0x0E, 0xFC, 0x5A, 0x12, + 0x4D, 0x9B, 0xE4, 0x39, 0xC9, 0xF5, 0x2B, 0x82, 0x15, 0x61, 0x40, 0x84, 0x89, 0xB5, 0x52, 0x30, 0x11, 0x0A, 0xFF, 0xE9, + 0x4F, 0xC9, 0xBC, 0xA6, 0x5E, 0xCE, 0xD6, 0x1C, 0x34, 0xFA, 0xE5, 0xF1, 0x9A, 0x29, 0xDD, 0x34, 0x94, 0x63, 0xAA, 0x83, + 0x91, 0x33, 0x35, 0xFA, 0xC2, 0x2B, 0x53, 0xFF, 0x6F, 0x1D, 0x52, 0x98, 0x22, 0x6A, 0x09, 0x77, 0xED, 0x19, 0xD4, 0x88, + 0x36, 0x7D, 0xDD, 0x75, 0x95, 0xF4, 0xEC, 0x31, 0x9F, 0xB5, 0x08, 0x83, 0xBA, 0xD2, 0xD6, 0xEA, 0x28, 0xF5, 0xBD, 0x9C, + 0xE5, 0x28, 0xA6, 0x1A, 0x9C, 0x33, 0x01, 0x29, 0x59, 0x76, 0x36, 0xBF, 0x7B, 0xE2, 0xC0, 0x4B, 0xCD, 0x3E, 0xED, 0x50, + 0x1F, 0xBC, 0xB7, 0x6D, 0x84, 0xB6, 0xFD, 0x54, 0x5F, 0xFC, 0x8B, 0x6A, 0x0E, 0xDB, 0x54, 0x7D, 0x11, 0xB6, 0x2C, 0xC1, + 0x27, 0xEA, 0xA8, 0x3D, 0xF8, 0x5B, 0x1E, 0xF8, 0xE6, 0x93, 0x4F, 0xBC, 0x85, 0xA3, 0x2F, 0x4D, 0xCB, 0x03, 0x71, 0xA6, + 0x5A, 0x77, 0xB8, 0x68, 0x10, 0x94, 0x78, 0xCF, 0x53, 0x36, 0x00, 0x5A, 0x5C, 0xFA, 0xC4, 0x4E, 0x95, 0x52, 0x6F, 0x38, + 0xA7, 0xDC, 0x77, 0xAD, 0x41, 0x6B, 0x76, 0x8D, 0x3A, 0x2F, 0x80, 0xD2, 0x15, 0xBA, 0xB6, 0xEC, 0xA9, 0x66, 0xE7, 0xE3, + 0x54, 0xFB, 0xBF, 0x4E, 0x83, 0xC2, 0x5B, 0xDB, 0x9C, 0x81, 0x93, 0xF3, 0x84, 0x8D, 0x67, 0xC4, 0x40, 0x84, 0xE8, 0xC2, + 0xEC, 0x4F, 0xC9, 0x71, 0xF5, 0xE0, 0x98, 0xB5, 0x69, 0x0C, 0xB2, 0xEF, 0x6E, 0x01, 0x86, 0xF7, 0x8B, 0x0B, 0x67, 0x10, + 0x62, 0x89, 0x53, 0xB2, 0x6B, 0x66, 0xC9, 0x6D, 0xAF, 0x02, 0x37, 0xE0, 0xAD, 0xEF, 0xCF, 0xC7, 0xC0, 0xE7, 0xF6, 0x63, + 0xAF, 0xDC, 0x49, 0x7C, 0xFB, 0x83, 0x11, 0x35, 0x69, 0x21, 0x21, 0xCA, 0xEE, 0x9C, 0x80, 0x34, 0x80, 0x59, 0x65, 0x41, + 0x95, 0x32, 0x2E, 0xF2, 0x96, 0x92, 0x14, 0x6A, 0x53, 0x04, 0x36, 0x65, 0xAF, 0x08, 0x3F, 0xE9, 0xDB, 0xF2, 0x06, 0xEA, + 0x47, 0xB0, 0x18, 0xCA, 0xF2, 0x9A, 0x81, 0xC5, 0xF2, 0x0B, 0x91, 0xDB, 0x69, 0x82, 0xF6, 0xFE, 0x29, 0xF0, 0x8F, 0xD5, + 0xDA, 0x24, 0x37, 0x79, 0xEB, 0x56, 0x1A, 0x46, 0x69, 0x94, 0xF9, 0x4F, 0x4F, 0x93, 0xEE, 0x7C, 0xD5, 0xDC, 0xBD, 0x38, + 0x29, 0xF7, 0x1C, 0x0F, 0xD4, 0x2E, 0x34, 0x75, 0x79, 0xE5, 0xA8, 0xD7, 0x5E, 0x72, 0xBD, 0xB8, 0xFA, 0xB6, 0x42, 0xF4, + 0x1D, 0x6B, 0x52, 0xF8, 0xB5, 0xA0, 0x14, 0x5A, 0xA6, 0x72, 0xB8, 0xB9, 0x16, 0x4B, 0x20, 0xFF, 0x9E, 0x90, 0x0A, 0xEE, + 0x02, 0x40, 0xE1, 0x32, 0xBC, 0x71, 0xF0, 0x9D, 0x8B, 0x43, 0xCF, 0x1A, 0x1B, 0xFF, 0xC0, 0x39, 0x31, 0xC1, 0xF8, 0x4B, + 0x9B, 0xD4, 0x3C, 0x64, 0xE3, 0xED, 0xE4, 0xF6, 0x68, 0x88, 0xE0, 0x77, 0xA6, 0xE7, 0x4E, 0x13, 0xE5, 0xC1, 0xF3, 0x48, + 0xB0, 0xF2, 0x2C, 0x2E, 0xF0, 0x8B, 0xDA, 0x3E, 0xD9, 0x19, 0x9C, 0xCA, 0xD4, 0x10, 0x15, 0x60, 0x61, 0x3F, 0x12, 0xDB, + 0x52, 0x5D, 0x65, 0x6D, 0xA1, 0xCB, 0x50, 0x94, 0xD6, 0x2C, 0x90, 0x59, 0x7B, 0xEE, 0x95, 0xCF, 0x9F, 0xDA, 0x78, 0x76, + 0x13, 0xE4, 0x3C, 0x0F, 0x0D, 0x67, 0x05, 0x66, 0x04, 0x9B, 0x0B, 0x00, 0x32, 0x8C, 0x8A, 0xD3, 0x23, 0xDF, 0x0E, 0x2A, + 0xFD, 0x8D, 0x36, 0x20, 0xCB, 0xBE, 0x11, 0x16, 0xB1, 0x9A, 0x43, 0x4F, 0x67, 0x68, 0x18, 0x49, 0x86, 0x30, 0x6A, 0xBD, + 0x4B, 0x56, 0x3A, 0xB5, 0xB4, 0x9D, 0x17, 0x5E, 0x01, 0x2D, 0xF2, 0xDB, 0x22, 0x7A, 0xA9, 0xB5, 0x23, 0x1B, 0xB5, 0x6A, + 0x93, 0x3E, 0x4B, 0xC2, 0xEE, 0xD1, 0x1C, 0xB7, 0x1C, 0x68, 0xD7, 0xFE, 0x5A, 0xA1, 0x2C, 0x4E, 0x10, 0xE2, 0xD4, 0xFE, + 0x86, 0xA0, 0xEA, 0xFC, 0x13, 0x14, 0xC8, 0x54, 0x29, 0x71, 0x3B, 0x27, 0x4D, 0x98, 0x02, 0xC2, 0x67, 0x19, 0xD8, 0x1C, + 0x41, 0x37, 0x56, 0xFB, 0x9E, 0x0D, 0xBA, 0xB6, 0xCC, 0x97, 0xE3, 0x10, 0x0A, 0x16, 0xCD, 0xE0, 0x99, 0xF5, 0xEA, 0xED, + 0x77, 0xA6, 0x1E, 0x64, 0x45, 0x98, 0x3C, 0xFF, 0x33, 0x23, 0x1D, 0xE7, 0x04, 0xFC, 0xF0, 0x78, 0x20, 0x17, 0x87, 0x64, + 0xEA, 0x75, 0xE9, 0xDB, 0x6F, 0x34, 0xF5, 0xDA, 0x3A, 0x27, 0x3F, 0x38, 0x39, 0x58, 0x17, 0xE3, 0xB4, 0x5B, 0xD6, 0xCD, + 0x88, 0x26, 0x5A, 0x38, 0x1C, 0x7F, 0x97, 0xEB, 0xDF, 0x1A, 0x2B, 0x1E, 0x8D, 0x95, 0xF0, 0x69, 0xB8, 0xFE, 0x2E, 0x6A, + 0x66, 0x72, 0x6F, 0x2A, 0x12, 0x90, 0xDF, 0xFF, 0xA9, 0x20, 0x40, 0xB8, 0x15, 0xD1, 0x5F, 0xC9, 0x6F, 0x17, 0x61, 0xF0, + 0xFA, 0x6D, 0x15, 0xBF, 0x40, 0x9F, 0x71, 0x19, 0xF6, 0xBE, 0x13, 0xD1, 0x7C, 0x3E, 0xE3, 0xA7, 0xB6, 0x41, 0x9D, 0x6D, + 0xC9, 0x92, 0x21, 0x8A, 0x80, 0x9B, 0x5A, 0x0D, 0x19, 0x5D, 0xF4, 0xE0, 0x56, 0x4F, 0xB0, 0x3E, 0xC0, 0x93, 0xBF, 0x63, + 0xC8, 0x88, 0x71, 0xAA, 0x2C, 0x76, 0xF4, 0x97, 0x4A, 0x20, 0x9C, 0xE2, 0xC5, 0xEA, 0x21, 0x6E, 0x80, 0xF9, 0x00, 0xFC, + 0xFD, 0x06, 0x9B, 0x26, 0xA7, 0xE5, 0xDA, 0x82, 0x4F, 0x7A, 0x6B, 0x22, 0x42, 0x30, 0x6D, 0x27, 0x52, 0xFA, 0x24, 0x6C, + 0xA4, 0x09, 0x68, 0x96, 0xCC, 0x5C, 0xC7, 0x48, 0x33, 0x83, 0x14, 0x59, 0x9F, 0x20, 0x7B, 0x1E, 0x27, 0x84, 0x15, 0x83, + 0xCF, 0xE8, 0xA0, 0x5C, 0xAC, 0xDB, 0xC3, 0x68, 0x29, 0x9E, 0xA9, 0xF1, 0xA1, 0x85, 0xBB, 0x13, 0x7E, 0xFA, 0x76, 0x0A, + 0x32, 0xA6, 0x55, 0xA5, 0xD9, 0xEB, 0x57, 0x6A, 0x00, 0x74, 0x40, 0x78, 0x9A, 0x70, 0xD5, 0xE3, 0xC1, 0xD2, 0x74, 0x97, + 0x34, 0xC4, 0x56, 0x6E, 0x7B, 0x2A, 0x8F, 0x52, 0x7C, 0x33, 0xA9, 0xE4, 0x8F, 0xB6, 0x38, 0xF2, 0x62, 0x3A, 0xF0, 0x31, + 0x75, 0x39, 0x02, 0x58, 0x48, 0x0D, 0x21, 0xFD, 0x3D, 0x62, 0xA8, 0x43, 0x73, 0x19, 0xFA, 0x20, 0xFF, 0x54, 0x69, 0x49, + 0x73, 0x53, 0x9F, 0x01, 0x2C, 0x61, 0x99, 0xC0, 0x89, 0xEA, 0x50, 0x12, 0xAD, 0x77, 0x62, 0xD7, 0x41, 0xB3, 0x0A, 0xD5, + 0x4A, 0xC1, 0x36, 0xD3, 0xAB, 0xA9, 0xC6, 0x85, 0x29, 0x84, 0xCA, 0x00, 0xAE, 0xEB, 0xF2, 0xDA, 0x71, 0x64, 0xDC, 0x0A, + 0x5E, 0x8B, 0x43, 0xB8, 0x2F, 0x87, 0x23, 0x8B, 0x96, 0xCE, 0x10, 0x58, 0xA1, 0x63, 0x89, 0xC1, 0x69, 0x86, 0x54, 0x65, + 0x2A, 0x36, 0xE4, 0xC3, 0x9B, 0x11, 0x77, 0x5B, 0x99, 0x64, 0x7B, 0x4B, 0x5F, 0xA9, 0x1C, 0x73, 0xF7, 0x2F, 0x54, 0xBF, + 0xF6, 0xEC, 0x2C, 0xF8, 0x4A, 0x39, 0x8D, 0x10, 0xD3, 0x5A, 0x3C, 0x77, 0xE4, 0xFC, 0x8B, 0x50, 0xCF, 0xD9, 0x99, 0x65, + 0x91, 0x66, 0xFE, 0x0D, 0x43, 0x83, 0x70, 0xB8, 0xFE, 0x13, 0xBD, 0x7D, 0x9A, 0xE2, 0xD3, 0x55, 0x42, 0x1A, 0xBB, 0x6A, + 0xB5, 0x6D, 0xEA, 0x59, 0x7D, 0x7A, 0xCC, 0xAE, 0x03, 0x6D, 0x1C, 0x7F, 0xA4, 0x59, 0x99, 0x6F, 0xDC, 0x2F, 0x0F, 0x60, + 0x88, 0x1D, 0x47, 0xE0, 0xB9, 0x16, 0xF4, 0xCB, 0x0E, 0x74, 0x0B, 0x3D, 0x81, 0x66, 0xCA, 0x10, 0xF1, 0x1E, 0x6C, 0xE2, + 0x99, 0xAA, 0x1C, 0x99, 0x8C, 0x29, 0x2C, 0x3A, 0xF5, 0xEC, 0x5D, 0xA7, 0xA2, 0x09, 0x38, 0x74, 0x89, 0xF3, 0xFD, 0xD6, + 0xAC, 0xCB, 0xBD, 0xA2, 0x8B, 0x2D, 0xED, 0x12, 0x00, 0x93, 0x19, 0x13, 0xD0, 0xCD, 0x25, 0xBE, 0x0E, 0xCA, 0x87, 0x44, + 0xCD, 0x5C, 0x1D, 0xFD, 0x52, 0x41, 0x37, 0xFD, 0x4C, 0x2B, 0x75, 0x11, 0xA4, 0x21, 0x44, 0x99, 0x57, 0x94, 0xFC, 0x15, + 0x25, 0x60, 0x7C, 0xA4, 0xDC, 0x36, 0x9F, 0xED, 0xB9, 0x7A, 0x6E, 0x72, 0x71, 0xCC, 0x72, 0x47, 0xA4, 0x2A, 0x8D, 0x05, + 0x30, 0x43, 0xD5, 0xDD, 0x6A, 0x02, 0xAB, 0x57, 0xFE, 0xED, 0x69, 0x94, 0x26, 0x99, 0xB4, 0x7B, 0x12, 0x30, 0x1A, 0x02, + 0x35, 0x97, 0x02, 0x1F, 0xFE, 0xBA, 0x26, 0x8A, 0x2C, 0x9E, 0xEE, 0x8B, 0x43, 0x47, 0xEB, 0x55, 0x8D, 0x67, 0x27, 0x5D, + 0x08, 0x57, 0x96, 0x9A, 0x2D, 0x99, 0x6E, 0xEA, 0xA6, 0xB1, 0x68, 0xC9, 0x2E, 0x5B, 0x2B, 0x90, 0x19, 0xA4, 0x84, 0x61, + 0xAA, 0xB8, 0x37, 0xAF, 0x84, 0xF8, 0xE8, 0x54, 0xEA, 0xE3, 0xA0, 0x5C, 0x8C, 0x55, 0x2F, 0xE9, 0x2F, 0x4F, 0x2B, 0x62, + 0x4A, 0xFA, 0xC0, 0xC8, 0xEE, 0xB7, 0x53, 0x30, 0xFE, 0x08, 0xC5, 0x66, 0xF2, 0xEF, 0x66, 0xC2, 0x38, 0xFE, 0xD5, 0xDC, + 0xB2, 0x39, 0x89, 0x6A, 0x05, 0x95, 0x54, 0x29, 0xE9, 0x32, 0x02, 0x41, 0x3E, 0xDD, 0xFE, 0xBC, 0xFD, 0x89, 0x7A, 0x0F, + 0x1D, 0xDD, 0x40, 0xCD, 0x7E, 0xFA, 0x83, 0x30, 0x57, 0xAE, 0x09, 0xD8, 0x85, 0x5B, 0x37, 0x7E, 0x03, 0xF4, 0x89, 0x2A, + 0x65, 0x8F, 0xB1, 0x6F, 0xB7, 0xFD, 0x5C, 0xF4, 0x37, 0x74, 0x48, 0x4F, 0xDB, 0xFF, 0x59, 0x2D, 0x73, 0x00, 0x88, 0x81, + 0xB1, 0xAA, 0x3B, 0x53, 0x74, 0xC0, 0xDA, 0xCE, 0xF3, 0x66, 0xD7, 0x00, 0x07, 0xC3, 0x75, 0xF6, 0x93, 0x22, 0x38, 0x93, + 0xA0, 0xEE, 0x77, 0xD6, 0xD3, 0x29, 0xD8, 0x3D, 0xBB, 0xAC, 0xFE, 0xE7, 0x31, 0xA8, 0x6F, 0x1D, 0x88, 0x13, 0x47, 0x80, + 0x71, 0xE8, 0x98, 0x2E, 0x91, 0xD6, 0x3C, 0x77, 0xD0, 0xA3, 0x88, 0x0E, 0xF5, 0xBE, 0x81, 0x47, 0x72, 0x06, 0x0A, 0xBB, + 0x71, 0x04, 0xB8, 0xC6, 0x13, 0xE6, 0x99, 0x9F, 0xA3, 0xC2, 0x58, 0x67, 0xF3, 0xEC, 0x59, 0xA1, 0x71, 0x45, 0xBA, 0x2A, + 0xB0, 0x40, 0x4D, 0xEF, 0xB6, 0xCC, 0xF8, 0x16, 0x12, 0x61, 0x9C, 0x6D, 0xE9, 0x75, 0xFB, 0xA7, 0x10, 0x2E, 0x51, 0x9F, + 0x4F, 0xEB, 0xD5, 0x87, 0x50, 0x2E, 0xFE, 0x64, 0x77, 0xC6, 0x76, 0xB7, 0x11, 0x0F, 0x79, 0x9B, 0x2A, 0x56, 0xA1, 0xF7, + 0xD6, 0xAD, 0x03, 0x33, 0x10, 0x9D, 0xFA, 0x6E, 0x5B, 0x57, 0xBE, 0xBA, 0x08, 0x42, 0xEA, 0xAE, 0x5D, 0xB2, 0xF7, 0x68, + 0xBD, 0x00, 0xD0, 0x01, 0xBA, 0x2F, 0x63, 0x4E, 0xBE, 0xC2, 0x90, 0x38, 0xFA, 0x6F, 0x06, 0x8D, 0xC2, 0x09, 0xFB, 0x8F, + 0xBA, 0x28, 0x87, 0xD9, 0xF4, 0xBB, 0x91, 0xCF, 0x74, 0x67, 0x88, 0x76, 0xE8, 0x7C, 0xDB, 0x33, 0x38, 0xA1, 0x8E, 0x08, + 0xFD, 0x54, 0x13, 0xD1, 0xBA, 0x4B, 0x82, 0x20, 0x7B, 0xA1, 0x62, 0x2E, 0x5B, 0x6C, 0x48, 0x6A, 0xD8, 0x46, 0x88, 0x69, + 0xF9, 0x6A, 0xE6, 0x2A, 0xC1, 0x3C, 0xC1, 0xDE, 0x1E, 0x74, 0x58, 0x9E, 0xC6, 0x56, 0x52, 0x1C, 0x38, 0x96, 0x52, 0xE9, + 0x67, 0x4F, 0xBB, 0x3F, 0x9C, 0x35, 0x55, 0x81, 0xB9, 0x03, 0x5B, 0xA1, 0x79, 0x68, 0x35, 0x70, 0x6A, 0xA9, 0x91, 0x5C, + 0x38, 0x29, 0x3F, 0x1F, 0x01, 0x3E, 0xA3, 0x5A, 0xB8, 0x90, 0x4C, 0xC8, 0x43, 0x62, 0xBC, 0xD4, 0x31, 0x3F, 0x6A, 0x8C, + 0x03, 0x21, 0xEC, 0xC6, 0x31, 0x30, 0xAA, 0x7F, 0xDC, 0x7F, 0x86, 0x9C, 0x92, 0x54, 0xE3, 0x50, 0x67, 0xFC, 0x5B, 0xDA, + 0xF3, 0x92, 0x13, 0xAD, 0xA6, 0x50, 0xE5, 0x25, 0xF8, 0x3F, 0x03, 0x8D, 0x53, 0x9F, 0xED, 0x58, 0x47, 0x30, 0xE8, 0xD1, + 0xB1, 0xEF, 0xD7, 0x88, 0x12, 0x35, 0x1C, 0x4A, 0xE7, 0xD1, 0x8F, 0xC7, 0x52, 0x16, 0xD5, 0x53, 0x33, 0x1E, 0xBC, 0xA6, + 0x73, 0xB4, 0xC5, 0x02, 0xCE, 0xF9, 0xD6, 0x06, 0xF0, 0x3C, 0x6A, 0xE4, 0xAF, 0xB8, 0x96, 0xD5, 0x90, 0x33, 0x02, 0x12, + 0x67, 0xD0, 0x07, 0xAA, 0x0C, 0x9D, 0x0B, 0xD2, 0xCE, 0x52, 0xBD, 0x47, 0xB7, 0xB7, 0xC0, 0x03, 0x0B, 0xDC, 0x40, 0x75, + 0x51, 0x37, 0x07, 0x41, 0xE0, 0xC8, 0xC5, 0xB2, 0x10, 0x31, 0xEE, 0x13, 0x8B, 0xB6, 0x00, 0xFD, 0x12, 0xC8, 0xBB, 0xD7, + 0xC1, 0x49, 0xD6, 0x81, 0x99, 0xB2, 0x30, 0xD3, 0xCB, 0xF5, 0xCC, 0x53, 0xDB, 0x1D, 0xA2, 0x17, 0x2A, 0x09, 0xCA, 0x6C, + 0x63, 0x36, 0x7F, 0xC3, 0xCA, 0x5D, 0xC4, 0x43, 0xDA, 0x7F, 0x05, 0x7A, 0x94, 0xC7, 0xFF, 0x6F, 0x3A, 0x39, 0x12, 0x52, + 0xEE, 0xD8, 0xCD, 0xB8, 0x5B, 0x1F, 0xA4, 0xF6, 0x7C, 0xB6, 0xEF, 0xD9, 0xB6, 0x36, 0x5A, 0x49, 0xFF, 0xAA, 0xCF, 0x99, + 0x18, 0x74, 0x18, 0x2A, 0x2E, 0x5E, 0xCE, 0xEB, 0x99, 0x3A, 0x28, 0xDD, 0x9F, 0xFF, 0x16, 0x15, 0x51, 0xF1, 0xFA, 0xBA, + 0xD4, 0xB9, 0xAE, 0x9C, 0xD4, 0x30, 0x4D, 0xD9, 0x8C, 0x1C, 0x4F, 0xBA, 0x43, 0x7B, 0x87, 0xF1, 0x0B, 0xC1, 0xCF, 0x6A, + 0x5B, 0x31, 0xC5, 0x1A, 0x8E, 0xFE, 0x8E, 0x77, 0x1D, 0x32, 0xD9, 0xDF, 0x63, 0xDE, 0xC5, 0xDC, 0x18, 0x39, 0x3F, 0xBD, + 0x27, 0xD2, 0xFF, 0xA1, 0x5A, 0x1D, 0x38, 0x0B, 0xB9, 0x09, 0xD8, 0x56, 0x58, 0xAF, 0x8A, 0xD9, 0xCB, 0x16, 0xC8, 0xA4, + 0x51, 0xDB, 0x5A, 0xBC, 0x5D, 0x0C, 0xAC, 0xF4, 0x97, 0xA2, 0xAF, 0xD8, 0x80, 0x7C, 0x82, 0xD4, 0xD7, 0xA9, 0x94, 0x63, + 0xC4, 0xFF, 0xC1, 0xA7, 0xDE, 0x29, 0x39, 0x3E, 0xA7, 0xB3, 0xC9, 0xA5, 0xD1, 0x19, 0x57, 0x3E, 0x6E, 0x12, 0x6D, 0xE7, + 0xD9, 0xAC, 0x93, 0xC3, 0xF9, 0x62, 0x62, 0x27, 0x76, 0xE5, 0x71, 0xB1, 0x36, 0xEA, 0xE8, 0xC3, 0xB7, 0x2C, 0x4E, 0x4E, + 0x27, 0xC0, 0x88, 0xE4, 0x74, 0x91, 0x56, 0x7E, 0x66, 0x81, 0xEA, 0xB4, 0x95, 0xAD, 0x62, 0x70, 0x8D, 0xCA, 0x98, 0x32, + 0x58, 0xE8, 0x5F, 0x6A, 0x4C, 0xF7, 0x61, 0xA5, 0x37, 0x2E, 0x0F, 0x81, 0xD4, 0x8B, 0xC9, 0xB7, 0x28, 0xE9, 0x10, 0x20, + 0xB7, 0x0E, 0x29, 0x35, 0xD6, 0x87, 0x31, 0x6B, 0x2E, 0x96, 0xF3, 0x73, 0x74, 0xEA, 0x04, 0x06, 0x74, 0x2C, 0xC2, 0xAE, + 0x4C, 0x23, 0xA3, 0xC0, 0x89, 0x15, 0x3A, 0x2C, 0xFD, 0x62, 0x10, 0xE9, 0x39, 0x24, 0x65, 0x7C, 0x5C, 0x89, 0x3C, 0x16, + 0xA4, 0x98, 0x6E, 0x5C, 0x1E, 0x96, 0xA2, 0x37, 0x84, 0x7D, 0x27, 0xED, 0x1E, 0xE2, 0x99, 0x36, 0x4C, 0x24, 0x5C, 0xCD, + 0x5E, 0x09, 0xBA, 0x5C, 0x47, 0xDB, 0xD3, 0x9D, 0xBF, 0xDE, 0x49, 0x2B, 0x18, 0x46, 0xC3, 0x5D, 0x9C, 0xCB, 0x42, 0xC0, + 0x0F, 0x4C, 0x9A, 0x69, 0xBF, 0x24, 0x8A, 0x62, 0xA7, 0xBD, 0xF8, 0x6F, 0xFD, 0xEA, 0x7F, 0x77, 0x82, 0x20, 0xE2, 0xBC, + 0x9D, 0xA5, 0x69, 0x9C, 0xA6, 0x5C, 0x82, 0xFC, 0x5A, 0x74, 0x45, 0x63, 0xBA, 0x2A, 0xF3, 0xAD, 0x3F, 0x26, 0x8B, 0x83, + 0x2A, 0x63, 0x7B, 0x06, 0xBD, 0xCE, 0xFE, 0xC8, 0x96, 0x22, 0x2B, 0x3D, 0xDC, 0x10, 0xBB, 0x97, 0x4B, 0x62, 0x83, 0xFD, + 0xD6, 0x09, 0xB5, 0x92, 0xCF, 0x01, 0xEE, 0x78, 0x97, 0xBD, 0xF4, 0x26, 0xAE, 0x2F, 0xD4, 0xE6, 0x65, 0x70, 0xEC, 0x16, + 0x54, 0xEE, 0x24, 0x42, 0xD4, 0xBE, 0x44, 0xC4, 0x05, 0x87, 0xE3, 0x85, 0x94, 0x0E, 0x7F, 0x0C, 0xCC, 0xC3, 0xEF, 0x7C, + 0x17, 0xB4, 0xF5, 0x33, 0x2C, 0x2F, 0xCD, 0xD5, 0x0B, 0xB0, 0x12, 0x54, 0x3B, 0x9B, 0xCD, 0xD3, 0xA2, 0xBC, 0xFD, 0x37, + 0x60, 0xDE, 0x3D, 0x4E, 0x5F, 0x27, 0xC0, 0xA0, 0xD5, 0xF1, 0xEC, 0x70, 0x97, 0x3E, 0x0C, 0x60, 0x63, 0xA7, 0x14, 0xCB, + 0x56, 0x85, 0x57, 0x6E, 0xCC, 0x84, 0x8C, 0x96, 0x91, 0xB8, 0x26, 0xF6, 0xC4, 0xD3, 0xDC, 0x61, 0xD6, 0x79, 0x5D, 0xFE, + 0x4D, 0xA7, 0x62, 0x97, 0x97, 0xB9, 0x0D, 0x61, 0xEF, 0x16, 0x75, 0xE4, 0x46, 0xF0, 0x81, 0xA0, 0x9F, 0x31, 0xA7, 0xCA, + 0xF6, 0xB5, 0x71, 0xE3, 0xA7, 0xD8, 0xB7, 0xEA, 0x9C, 0xF8, 0x27, 0xD1, 0x91, 0x24, 0xC6, 0xCA, 0x53, 0x33, 0xC9, 0x2E, + 0x2E, 0xCE, 0x24, 0xB1, 0x10, 0x75, 0x39, 0xE0, 0xA0, 0xEF, 0x39, 0xFC, 0x7E, 0x55, 0x00, 0x96, 0x0C, 0x59, 0x12, 0x2D, + 0x72, 0xF1, 0x19, 0xA7, 0xEC, 0x35, 0x32, 0x6D, 0x3E, 0xB3, 0x88, 0x49, 0xA4, 0x8B, 0xC9, 0x97, 0x15, 0x6B, 0x67, 0x93, + 0x7C, 0xE6, 0xA5, 0x97, 0x1E, 0xB6, 0x67, 0xE9, 0xC9, 0xDD, 0x3F, 0xFE, 0x62, 0x56, 0xAF, 0x3A, 0xAE, 0x83, 0x9E, 0x4C, + 0x3F, 0xBB, 0x16, 0xAB, 0x93, 0x57, 0x77, 0xDC, 0x1E, 0xAC, 0x6C, 0x32, 0xAF, 0x99, 0xD4, 0x3C, 0xBD, 0xB5, 0xC5, 0x98, + 0x2E, 0x9D, 0xB4, 0xE3, 0x6D, 0xB2, 0x79, 0xE3, 0x3C, 0x96, 0xBD, 0xD2, 0x1D, 0xDB, 0x71, 0x09, 0x6C, 0xF6, 0xAE, 0xBE, + 0x59, 0xF3, 0xAE, 0x9C, 0x4E, 0x39, 0x29, 0xCF, 0x1C, 0xB9, 0x07, 0x99, 0xAE, 0xFF, 0x9F, 0xFD, 0x2D, 0xF2, 0x59, 0x54, + 0xA7, 0x4D, 0x86, 0x30, 0xF9, 0xE1, 0x49, 0xBA, 0xA4, 0x2A, 0x5C, 0x11, 0x84, 0x71, 0x0A, 0x6F, 0x40, 0x08, 0x7F, 0x66, + 0xFA, 0xE0, 0x41, 0xAA, 0xA5, 0xCB, 0x09, 0x2F, 0x6D, 0x15, 0xFE, 0xD1, 0x23, 0x09, 0x2D, 0x97, 0x92, 0x2A, 0x31, 0x35, + 0x8A, 0x28, 0x36, 0x0C, 0xF4, 0x96, 0xF1, 0x93, 0x01, 0x55, 0xE9, 0xA6, 0xCB, 0x2E, 0xAE, 0xF4, 0xB6, 0x43, 0x8A, 0xC5, + 0xA9, 0x92, 0x70, 0x2E, 0xA1, 0x61, 0xFD, 0xD4, 0xF9, 0x0E, 0x2E, 0x67, 0xE3, 0x06, 0x5D, 0x79, 0xD2, 0x33, 0xF3, 0x30, + 0x0F, 0xAE, 0x68, 0x26, 0x71, 0x82, 0xD7, 0xF4, 0x4E, 0x03, 0x4F, 0x9E, 0xF6, 0x6C, 0xFC, 0xA3, 0x69, 0x25, 0x9B, 0x9B, + 0xE6, 0x89, 0xDD, 0x6F, 0x4D, 0xEB, 0xEB, 0x9A, 0xB1, 0x42, 0x1D, 0xAE, 0x85, 0x2E, 0x09, 0x10, 0x57, 0x8A, 0x51, 0x75, + 0x6A, 0x54, 0xC0, 0x85, 0xD7, 0x96, 0x3A, 0x5A, 0x4B, 0xF8, 0x7D, 0x7F, 0x7C, 0x44, 0x25, 0xF8, 0x3B, 0x48, 0x52, 0x4D, + 0xB2, 0x65, 0x72, 0x9A, 0x89, 0x5F, 0x06, 0xAF, 0xB8, 0x86, 0x0C, 0x5A, 0xB6, 0x94, 0x86, 0xCF, 0x2D, 0xC2, 0x01, 0x8B, + 0x66, 0x1E, 0x64, 0xCD, 0xC7, 0x68, 0xD3, 0x34, 0xFC, 0xB7, 0xED, 0x89, 0x55, 0xCC, 0x33, 0xC9, 0xD5, 0x8B, 0x9A, 0x3A, + 0x38, 0x84, 0xCF, 0xC7, 0x34, 0xCA, 0x0C, 0x20, 0xEA, 0x4D, 0x6F, 0x2A, 0xF5, 0xA1, 0x0A, 0xC8, 0x17, 0x0A, 0x6C, 0xA8, + 0x4C, 0x24, 0xAC, 0x6A, 0xBB, 0xEF, 0xC8, 0xDC, 0x22, 0x31, 0xB4, 0x98, 0xF2, 0xD5, 0xF6, 0xFC, 0x46, 0x41, 0x21, 0x8C, + 0x94, 0x9C, 0x17, 0x8E, 0x54, 0x06, 0x8B, 0x5D, 0x23, 0xAE, 0xF2, 0xED, 0xC7, 0x91, 0xA1, 0x9E, 0x56, 0x63, 0x75, 0xF8, + 0x28, 0xA2, 0x27, 0xCF, 0xCD, 0x27, 0x13, 0x7D, 0x62, 0x5C, 0xA5, 0x7B, 0x3A, 0xEC, 0xD9, 0x81, 0x40, 0x76, 0xE4, 0xC6, + 0xC1, 0x72, 0x0C, 0xA5, 0x81, 0xFF, 0x98, 0x20, 0x59, 0x75, 0xF5, 0x14, 0x7D, 0x33, 0x38, 0xF6, 0xE0, 0xEC, 0x22, 0x84, + 0x41, 0x5C, 0x61, 0xFA, 0x84, 0x2D, 0x78, 0xFB, 0xC2, 0x16, 0x09, 0x2F, 0x11, 0xED, 0x1E, 0xD3, 0x0B, 0x93, 0xAD, 0x5B, + 0x5C, 0x7F, 0x73, 0x30, 0xE2, 0xF3, 0xA6, 0x6A, 0xCA, 0x13, 0xD9, 0x35, 0xEC, 0x3D, 0xC4, 0x2D, 0x54, 0x8C, 0x35, 0x44, + 0x0B, 0xA3, 0xA2, 0x88, 0x31, 0x3C, 0x6C, 0x0F, 0xEF, 0x16, 0xB4, 0x53, 0x6C, 0x79, 0xA0, 0x4F, 0x22, 0xD5, 0x37, 0x26, + 0x12, 0x96, 0x62, 0xAD, 0x65, 0x3D, 0xE4, 0x0F, 0xFC, 0xA3, 0x7D, 0x3E, 0x4B, 0x75, 0x05, 0xB0, 0x9D, 0x3B, 0xD9, 0xA6, + 0xE3, 0x5D, 0x2E, 0x67, 0x10, 0x36, 0x8D, 0xB0, 0x59, 0xBA, 0x97, 0xD2, 0xB5, 0xDE, 0xFC, 0x9A, 0x5C, 0x39, 0xD5, 0xD4, + 0x71, 0x10, 0x1E, 0x9D, 0xC1, 0x3B, 0x46, 0x49, 0x54, 0xA4, 0x2C, 0x53, 0x6E, 0xE0, 0xA8, 0x90, 0xF5, 0x8E, 0x1B, 0x68, + 0xF9, 0xE8, 0xA1, 0xE3, 0x8E, 0xA4, 0xDF, 0x49, 0x59, 0x59, 0x9F, 0x54, 0x59, 0x34, 0x7D, 0xE9, 0xAC, 0x54, 0x3C, 0xD7, + 0x61, 0xC7, 0xC8, 0xDA, 0xB9, 0x53, 0x9F, 0xA0, 0xD8, 0x38, 0xCF, 0xED, 0x22, 0xB6, 0x9D, 0x9D, 0x46, 0xB6, 0x61, 0x90, + 0x69, 0x39, 0x0A, 0x52, 0x18, 0x28, 0x92, 0x2A, 0x9A, 0x8D, 0x98, 0xAE, 0xC1, 0xB7, 0x96, 0xAD, 0xE7, 0x54, 0x2D, 0x04, + 0xA8, 0x3E, 0x06, 0xDD, 0x54, 0xE2, 0xF4, 0x6C, 0xD9, 0x92, 0x66, 0x68, 0x80, 0xA5, 0xBE, 0x5B, 0x88, 0x70, 0xFD, 0x0E, + 0x60, 0x7D, 0x47, 0xF1, 0x51, 0x7A, 0xD1, 0x6D, 0xE7, 0x81, 0x49, 0xC6, 0xF9, 0x9C, 0xDF, 0xEF, 0x85, 0xEA, 0x6B, 0xA6, + 0x18, 0xB4, 0x05, 0x23, 0x9F, 0xF0, 0x24, 0x7F, 0x19, 0x9F, 0x40, 0xB5, 0x9C, 0x8F, 0xB5, 0x74, 0xEF, 0x55, 0x28, 0xD1, + 0x67, 0x1D, 0x0A, 0xB6, 0x3D, 0xB1, 0x02, 0xC2, 0x59, 0x01, 0x64, 0x23, 0xC1, 0xB0, 0xA8, 0xC3, 0x29, 0xB1, 0x02, 0xC5, + 0x29, 0x8D, 0x41, 0x01, 0x1A, 0x8F, 0xB4, 0x39, 0xA4, 0xE0, 0x63, 0x00, 0x2F, 0x3B, 0xE9, 0x36, 0xE7, 0x06, 0x49, 0xA4, + 0x11, 0x8C, 0x0E, 0x3E, 0x68, 0x3C, 0x59, 0x80, 0x7E, 0x81, 0x79, 0x56, 0x7C, 0x61, 0xF3, 0x22, 0x14, 0xE8, 0x64, 0x34, + 0xFD, 0x5C, 0x2A, 0xBC, 0x32, 0x6B, 0x86, 0x95, 0xDA, 0x39, 0xDF, 0x6E, 0x01, 0x4E, 0x79, 0x16, 0x1B, 0x28, 0x06, 0x75, + 0xE6, 0x87, 0x86, 0x70, 0xB6, 0x66, 0x07, 0xF3, 0x85, 0xE4, 0xDF, 0x86, 0x19, 0x20, 0xD1, 0x11, 0xA4, 0x61, 0x89, 0x97, + 0x9A, 0x17, 0x15, 0x2D, 0x6C, 0xA4, 0x97, 0x96, 0x91, 0xCF, 0xF5, 0x7D, 0x48, 0x6A, 0x8B, 0x84, 0x5B, 0xEA, 0x42, 0x08, + 0x92, 0x85, 0x9C, 0x26, 0x7C, 0xA8, 0xBE, 0xDB, 0xB1, 0xC7, 0xCC, 0x9E, 0x37, 0x8B, 0xDC, 0x15, 0xAE, 0x04, 0x6A, 0x5B, + 0xF7, 0x74, 0xB6, 0xCB, 0xB0, 0xC6, 0x84, 0x07, 0xD0, 0x4F, 0x69, 0x16, 0xCC, 0x8C, 0x5C, 0x7D, 0xEE, 0x75, 0x53, 0x98, + 0x7B, 0x88, 0x4C, 0x5D, 0x37, 0x5B, 0xD4, 0x64, 0xFE, 0x8B, 0xD3, 0x38, 0x60, 0xA4, 0x05, 0x26, 0xAC, 0x57, 0x2C, 0x7F, + 0xD9, 0xC7, 0xCE, 0xD9, 0x20, 0x86, 0x1E, 0x3C, 0xBD, 0x53, 0x3E, 0xEE, 0x43, 0x8A, 0x09, 0x9E, 0xC5, 0x1D, 0x4C, 0x66, + 0x2D, 0x2D, 0x6D, 0x1D, 0x3A, 0xEC, 0x44, 0xBE, 0x49, 0xA5, 0x8C, 0x8D, 0xD3, 0x30, 0xE1, 0x58, 0xA4, 0xED, 0xE5, 0x03, + 0x17, 0xE7, 0x7B, 0x6F, 0x67, 0xDD, 0x8D, 0x69, 0x3F, 0x6D, 0x7C, 0x4A, 0xFB, 0xAA, 0xD1, 0xA0, 0x62, 0xC3, 0xDA, 0xFF, + 0x8E, 0xA7, 0x83, 0x00, 0xFC, 0x4C, 0x70, 0x60, 0x78, 0x67, 0x75, 0x78, 0x5F, 0xBF, 0x0A, 0x96, 0x62, 0xB8, 0x4D, 0x99, + 0x52, 0x50, 0x2E, 0xE0, 0x16, 0x19, 0x84, 0xEC, 0x33, 0xF3, 0x33, 0x4F, 0x8C, 0x49, 0x1B, 0x17, 0x94, 0xCE, 0x27, 0x54, + 0x84, 0xA3, 0xA7, 0xF4, 0xD0, 0xB4, 0xD9, 0x5A, 0xEC, 0x90, 0x65, 0x23, 0xC3, 0x33, 0xD5, 0xD5, 0xE1, 0x95, 0xBE, 0xE9, + 0x16, 0xD6, 0x25, 0xA2, 0x04, 0x7C, 0xC4, 0x4D, 0x0E, 0x2C, 0x34, 0xE6, 0xDB, 0xF8, 0xC3, 0x42, 0x5B, 0x1F, 0xD4, 0x90, + 0x04, 0x73, 0xCC, 0x1D, 0xA0, 0xFC, 0x50, 0x7F, 0x21, 0xFD, 0x30, 0xB4, 0x57, 0x55, 0x34, 0x76, 0x6A, 0xF3, 0xA5, 0x68, + 0x71, 0x1C, 0x03, 0x9F, 0xA7, 0xD6, 0xDD, 0x39, 0xB0, 0x5F, 0xB5, 0xA6, 0x22, 0x7B, 0x74, 0x65, 0x58, 0x09, 0x91, 0xB1, + 0x84, 0xF7, 0x93, 0xD1, 0x56, 0x34, 0x35, 0xE3, 0x5E, 0x57, 0xC8, 0xB7, 0xB3, 0xF1, 0x06, 0xD6, 0x8D, 0x14, 0x19, 0x6C, + 0x74, 0x79, 0x27, 0x59, 0x54, 0x9A, 0x76, 0x2E, 0x79, 0xE3, 0xEA, 0x1C, 0x5D, 0x9A, 0x51, 0xEC, 0xD6, 0x21, 0x46, 0xC9, + 0x5D, 0x9B, 0x17, 0xC0, 0xE8, 0x85, 0xE3, 0x0E, 0xEF, 0xFA, 0x87, 0x19, 0xD7, 0x4A, 0xBB, 0x5E, 0x05, 0xEB, 0x31, 0x2B, + 0xF6, 0xF1, 0x3C, 0x93, 0xE7, 0x11, 0x2F, 0x6B, 0xC5, 0xF9, 0xB3, 0x4F, 0x10, 0xD4, 0x00, 0xF0, 0xFB, 0xD2, 0xE1, 0xC8, + 0xD3, 0x61, 0x94, 0x3D, 0xB2, 0x61, 0x08, 0x2A, 0x87, 0xF6, 0x80, 0x0D, 0x1D, 0xDC, 0x95, 0xEA, 0xFC, 0x32, 0xD6, 0xEE, + 0xB7, 0xA2, 0x74, 0xBF, 0xE0, 0x9F, 0x7E, 0x1E, 0xE3, 0xBC, 0x71, 0xA9, 0xC6, 0x93, 0x9F, 0x4B, 0xD3, 0xD5, 0xB7, 0xAE, + 0x7A, 0x9C, 0x8F, 0xF2, 0x03, 0x77, 0xCF, 0xA9, 0xCD, 0x38, 0xB5, 0xDD, 0x18, 0x1F, 0xF3, 0xB9, 0xEE, 0x5F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xA3, 0xA5, 0xDC, 0x83, 0x34, 0x66, 0xFB, 0xC1, 0xD0, 0xA4, 0xAD, 0x4E, 0xAE, 0x11, 0xF3, 0x10, 0xAD, 0xA5, + 0xE0, 0xAE, 0x19, 0x64, 0x91, 0x3E, 0xE3, 0xF2, 0xE0, 0xFE, 0xA6, 0x1C, 0xF6, 0x71, 0x22, 0xB0, 0x58, 0xC1, 0x2D, 0x96, + 0xAC, 0x8F, 0x29, 0xDE, 0x43, 0x4F, 0x95, 0xEF, 0xE3, 0x27, 0x5C, 0x62, 0xEF, 0x81, 0xB7, 0x21, 0xF0, 0x27, 0x71, 0x53, + 0x32, 0x2D, 0xA7, 0x1C, 0x76, 0x78, 0xED, 0x32, 0xB9, 0xFB, 0x23, 0x86, 0x96, 0x2A, 0x6E, 0x01, 0xE1, 0xEF, 0xEE, 0xC5, + 0x98, 0x95, 0x99, 0xA0, 0xFC, 0x0A, 0x92, 0x51, 0x7B, 0xE6, 0xF4, 0xE2, 0x0F, 0x4D, 0xBE, 0x48, 0xB8, 0x66, 0x9C, 0x79, + 0x00, 0xD2, 0x65, 0xA7, 0xDA, 0x05, 0x05, 0x60, 0x2B, 0x65, 0xAF, 0xC4, 0x3B, 0x65, 0xFD, 0x9E, 0x70, 0xDC, 0xB7, 0xE1, + 0x72, 0x84, 0xD9, 0x10, 0x89, 0xE3, 0x75, 0x0A, 0x19, 0x44, 0xFD, 0x7B, 0x32, 0x64, 0xE3, 0xCC, 0x5C, 0x8C, 0xD2, 0xA9, + 0x17, 0x40, 0x75, 0x5F, 0x6C, 0x27, 0xA7, 0x6B, 0x6B, 0xA8, 0x1F, 0x6F, 0x7D, 0x2A, 0x9E, 0xC5, 0x41, 0x08, 0x0A, 0x4E, + 0xB2, 0x00, 0xE4, 0x49, 0x8C, 0x2A, 0x11, 0x21, 0x50, 0xCB, 0x95, 0x5A, 0xFA, 0x41, 0x92, 0x5E, 0xE4, 0x25, 0x5E, 0xEA, + 0x0D, 0x86, 0x35, 0x0C, 0x78, 0x84, 0xDB, 0xA8, 0xC7, 0xFE, 0xCB, 0x21, 0x89, 0x6D, 0xD7, 0xE8, 0x5E, 0x4C, 0x94, 0xBF, + 0x70, 0x04, 0x80, 0x6E, 0x82, 0xEF, 0x69, 0xFF, 0x78, 0x64, 0x13, 0xDD, 0xAE, 0xB2, 0xAA, 0x42, 0x66, 0x22, 0x00, 0x4F, + 0x23, 0x6E, 0x25, 0x83, 0xB2, 0x6E, 0x98, 0xD8, 0x6B, 0x71, 0x61, 0xA5, 0x4E, 0xE3, 0xF7, 0x4E, 0x6B, 0xB1, 0x52, 0x1E, + 0xF0, 0xEF, 0xF6, 0x1E, 0x51, 0x05, 0x7C, 0x81, 0x9D, 0x74, 0x25, 0x7F, 0x2A, 0xCC, 0x89, 0x82, 0x2C, 0x03, 0x46, 0x25, + 0xC9, 0xD3, 0x72, 0x77, 0xBC, 0x3D, 0x45, 0x12, 0x68, 0x30, 0xD0, 0x9A, 0xAC, 0xF3, 0x5A, 0x28, 0xCA, 0x75, 0x1A, 0x6C, + 0x31, 0x73, 0x49, 0xB1, 0x39, 0xAA, 0xBF, 0x15, 0x90, 0x0E, 0x12, 0x72, 0x24, 0xBF, 0xFA, 0xBB, 0xD4, 0xC7, 0xCA, 0xA0, + 0xC4, 0xF2, 0x36, 0x00, 0x28, 0x31, 0x35, 0x6A, 0xA7, 0xA8, 0x0A, 0xB9, 0x44, 0xBF, 0x1D, 0x95, 0x00, 0xFC, 0x20, 0xF2, + 0x3B, 0x7A, 0xE7, 0xC2, 0x64, 0x49, 0x14, 0xCC, 0x97, 0x9B, 0xD4, 0x0E, 0xD9, 0x4B, 0xAA, 0x44, 0x74, 0x1C, 0x0E, 0xBE, + 0x42, 0x75, 0xF4, 0x2E, 0xF2, 0xBF, 0x74, 0x92, 0x9E, 0x59, 0x08, 0x0E, 0x88, 0x37, 0xE9, 0x53, 0x9E, 0x1C, 0x11, 0x47, + 0x32, 0xAC, 0x95, 0x61, 0xE7, 0x8B, 0x48, 0xDB, 0xD4, 0x83, 0x32, 0x8B, 0x5E, 0x8B, 0x4A, 0x24, 0x10, 0xB7, 0x65, 0x19, + 0xB3, 0x1A, 0x9D, 0xB1, 0x06, 0x7B, 0x9A, 0x97, 0x16, 0x1E, 0xFF, 0x5C, 0x9B, 0x24, 0x07, 0x5B, 0x50, 0xF7, 0xDE, 0x91, + 0x91, 0xFB, 0xA2, 0x68, 0x75, 0xEF, 0xA4, 0x4C, 0x65, 0x21, 0x47, 0x22, 0x8C, 0xA6, 0x9C, 0x52, 0x7F, 0x52, 0xF3, 0x72, + 0x09, 0xE5, 0x9E, 0x7E, 0xDC, 0xC7, 0x86, 0x5A, 0xD4, 0x25, 0xDD, 0xAC, 0x07, 0x87, 0xF0, 0xEB, 0x6B, 0x1B, 0xF1, 0xA8, + 0x36, 0x96, 0xA2, 0xFE, 0x37, 0x53, 0xEB, 0xD3, 0x5A, 0xD6, 0xC1, 0x38, 0x29, 0x8D, 0xF4, 0xDF, 0x99, 0xAD, 0xAD, 0xE0, + 0xCF, 0x23, 0xEE, 0x93, 0xFB, 0x71, 0xED, 0x2B, 0xA7, 0xA0, 0x49, 0x2D, 0x98, 0xBD, 0x23, 0x12, 0xE8, 0x50, 0x1E, 0xB9, + 0x46, 0x73, 0x39, 0xCF, 0x4B, 0x9D, 0xB9, 0xF4, 0x4B, 0xB4, 0xFE, 0x97, 0x7F, 0xD3, 0x64, 0x4D, 0x06, 0x5D, 0x37, 0xD4, + 0x2B, 0x08, 0xFD, 0xCE, 0x18, 0xEE, 0xA0, 0x3B, 0x4A, 0x80, 0xE7, 0x02, 0x78, 0x72, 0x76, 0xA7, 0x02, 0x02, 0x32, 0xF5, + 0x78, 0xCE, 0xE1, 0xDA, 0x44, 0x82, 0x13, 0xE0, 0xF5, 0x8C, 0x56, 0x14, 0xEC, 0xE2, 0x96, 0x22, 0x74, 0xA5, 0x83, 0x70, + 0xE4, 0x3C, 0xE6, 0x53, 0x5D, 0xE2, 0xF5, 0x70, 0xE6, 0x33, 0x9F, 0x32, 0x56, 0x5D, 0xB6, 0x0F, 0x25, 0x7D, 0xD3, 0xB6, + 0xD5, 0x82, 0x7A, 0xE0, 0x09, 0x8E, 0xCB, 0x08, 0x94, 0x63, 0x11, 0x51, 0x2C, 0xB0, 0x7D, 0xF2, 0xD3, 0x98, 0xB7, 0xB2, + 0x81, 0xF5, 0x72, 0xC4, 0xC2, 0x35, 0xD3, 0x91, 0xCA, 0x39, 0x4F, 0xF5, 0x2E, 0x39, 0xCB, 0xA1, 0x8B, 0x88, 0x79, 0x49, + 0x2B, 0x18, 0x5E, 0xC3, 0xCB, 0xA0, 0x4B, 0x4E, 0xAB, 0x54, 0x1F, 0x45, 0x67, 0x05, 0x5E, 0xA5, 0xB2, 0x72, 0x09, 0x70, + 0xA0, 0x82, 0x97, 0x5F, 0xD5, 0x66, 0x90, 0x14, 0x51, 0x8D, 0xF1, 0x4B, 0xA4, 0x1C, 0xCD, 0x11, 0x2C, 0x84, 0x55, 0x08, + 0x1D, 0x56, 0x5D, 0x8E, 0x77, 0xE1, 0xFC, 0x3A, 0x40, 0x03, 0xF2, 0xBB, 0x3A, 0xC6, 0x40, 0x51, 0x34, 0xE5, 0x3C, 0xB3, + 0xE6, 0xCD, 0xBC, 0xEE, 0x8D, 0x58, 0xC1, 0x7D, 0x4B, 0xEB, 0xC4, 0x38, 0xBC, 0x6A, 0x84, 0xA7, 0x65, 0x49, 0x35, 0xF0, + 0xBC, 0x9B, 0x0B, 0xD4, 0x4F, 0xC7, 0xA5, 0x4D, 0xBC, 0xF4, 0x11, 0xAA, 0xE7, 0xC9, 0xD5, 0x19, 0x7C, 0x28, 0xF4, 0xFB, + 0xDD, 0x66, 0x20, 0xCC, 0x51, 0xA9, 0xA2, 0x24, 0x6F, 0xEC, 0x5A, 0xBD, 0x38, 0xBC, 0x8F, 0x18, 0xF9, 0xF3, 0x0D, 0x10, + 0x94, 0x7D, 0x6F, 0xAA, 0x39, 0x1C, 0xCA, 0x93, 0x9F, 0x3D, 0x28, 0x80, 0xB4, 0x8F, 0x9C, 0x47, 0xB4, 0xCE, 0x1C, 0x11, + 0x37, 0x12, 0x5B, 0xBC, 0xB0, 0xA8, 0x0A, 0x55, 0xE0, 0x3B, 0x08, 0x28, 0x37, 0xCD, 0x15, 0x5D, 0x6E, 0x0C, 0xB2, 0xB3, + 0x3A, 0x00, 0x3B, 0x3F, 0x2E, 0xB4, 0xC5, 0xDF, 0x15, 0x7E, 0x89, 0xFD, 0xB9, 0xCF, 0x32, 0x15, 0x0C, 0x1D, 0xB4, 0x83, + 0xA0, 0x2C, 0xAC, 0x8B, 0x14, 0x6B, 0xFD, 0x68, 0xDE, 0x4E, 0x92, 0xA2, 0x54, 0xB5, 0xFB, 0xCD, 0xEA, 0x57, 0xC4, 0x89, + 0x17, 0x24, 0x1F, 0x68, 0x17, 0x67, 0xB4, 0xF7, 0x34, 0xAD, 0x88, 0xFC, 0xE2, 0x99, 0x75, 0x46, 0x16, 0xAF, 0xED, 0x13, + 0xA0, 0x0E, 0xCC, 0xD7, 0xF1, 0x17, 0xB9, 0xF3, 0xA9, 0x5E, 0x69, 0x8C, 0xD3, 0x66, 0xF4, 0x40, 0xA6, 0x8D, 0x9A, 0xFB, + 0xCA, 0xC5, 0xB4, 0x62, 0xBF, 0x96, 0x0F, 0x62, 0x74, 0x48, 0xF2, 0xB0, 0xDC, 0x48, 0xE3, 0xB4, 0x39, 0xD7, 0xBC, 0x93, + 0xAC, 0xD9, 0xD8, 0xD0, 0x57, 0x64, 0x5D, 0x3D, 0x24, 0x92, 0x56, 0xEB, 0x34, 0xB2, 0x69, 0x30, 0x1B, 0xD9, 0x65, 0xC7, + 0xCA, 0xB6, 0x13, 0x76, 0x5E, 0x38, 0x29, 0x07, 0xBF, 0x0E, 0xD9, 0xB1, 0x63, 0xDA, 0x7D, 0xF4, 0x53, 0x5C, 0x0E, 0xE8, + 0xD5, 0x94, 0x34, 0xA6, 0xF4, 0x59, 0x48, 0x9E, 0x87, 0x39, 0xE2, 0x46, 0x74, 0xBA, 0x91, 0xD8, 0x8C, 0x6C, 0x13, 0x1A, + 0x3B, 0x28, 0x5E, 0xD5, 0x6B, 0x9B, 0x1D, 0x1B, 0xA5, 0xBA, 0x1F, 0xF5, 0x2D, 0x97, 0xB2, 0x0B, 0xD9, 0xBC, 0x23, 0x5A, + 0xEA, 0x13, 0xF3, 0x4F, 0x20, 0x79, 0xFA, 0x1F, 0xA3, 0x57, 0x91, 0xAB, 0x1E, 0xDE, 0x2C, 0xD9, 0x06, 0x1A, 0x9C, 0x1E, + 0xE1, 0xFF, 0x34, 0x3B, 0x44, 0x98, 0xFE, 0xDE, 0x0D, 0x0A, 0x89, 0x1A, 0x5F, 0x7D, 0x64, 0xEE, 0xB6, 0x76, 0xCD, 0xED, + 0x4C, 0x99, 0x56, 0x2D, 0x1D, 0xAD, 0x2C, 0xE4, 0x84, 0xB9, 0xC0, 0xD2, 0xF2, 0x5B, 0x39, 0x7F, 0x2A, 0x98, 0xC7, 0xCB, + 0x8D, 0xC8, 0x23, 0x18, 0x6A, 0x53, 0x61, 0x9D, 0x15, 0xAF, 0x17, 0x59, 0x7B, 0xA6, 0x57, 0x2C, 0x95, 0xD3, 0x47, 0x05, + 0x62, 0x22, 0x33, 0x3F, 0x85, 0xBD, 0x9A, 0xEA, 0x63, 0x09, 0xD9, 0x3E, 0x16, 0xEB, 0x2B, 0x91, 0x24, 0xEF, 0x9C, 0xC9, + 0x71, 0x3B, 0xED, 0xAC, 0xEA, 0x65, 0x37, 0xF6, 0x72, 0xE5, 0x66, 0x19, 0xB4, 0xE2, 0x2E, 0xB0, 0x2C, 0xA2, 0x96, 0xF2, + 0x04, 0x89, 0x4A, 0x81, 0xFD, 0xF9, 0x83, 0x5E, 0xA8, 0x73, 0x27, 0xD8, 0xF1, 0xB9, 0x31, 0xEF, 0x2D, 0x0E, 0x18, 0xFF, + 0x60, 0x6C, 0x08, 0xC2, 0xF1, 0xE3, 0xA7, 0xE5, 0xB1, 0xBC, 0x16, 0x5A, 0x60, 0x46, 0x77, 0x6C, 0x14, 0x8D, 0xDE, 0x99, + 0xEF, 0x06, 0x4E, 0x90, 0x31, 0x44, 0x31, 0x6F, 0x6D, 0xD0, 0xDF, 0x2A, 0xD9, 0xB4, 0xD8, 0xB6, 0x1F, 0x46, 0x58, 0x85, + 0x6B, 0x7F, 0x97, 0x5A, 0x63, 0x39, 0x50, 0x02, 0x6F, 0x80, 0x8C, 0x07, 0x3F, 0x4F, 0xA9, 0x41, 0xB9, 0x77, 0x9B, 0xD5, + 0x81, 0xBB, 0x81, 0x41, 0x47, 0xB6, 0xD8, 0x74, 0xE1, 0x67, 0x80, 0x4E, 0xD5, 0xA4, 0xFD, 0xF9, 0xAB, 0x48, 0xA2, 0x45, + 0xA1, 0xA7, 0x83, 0x2A, 0xAA, 0x0A, 0xEC, 0x11, 0xB9, 0xC7, 0x12, 0xEB, 0x8D, 0xA4, 0xB2, 0x2C, 0x4F, 0x86, 0xE7, 0xD4, + 0x49, 0xB2, 0xFC, 0xF9, 0x5A, 0xE3, 0x3D, 0x25, 0x68, 0x8B, 0xDB, 0x5C, 0x25, 0x8B, 0x89, 0x96, 0x21, 0x20, 0x00, 0x5E, + 0xAC, 0x06, 0x73, 0xA9, 0x65, 0xA4, 0x2B, 0x6F, 0xFB, 0x8C, 0x03, 0xC5, 0x25, 0x09, 0xA5, 0x9C, 0xB1, 0x66, 0x1B, 0xF3, + 0xFF, 0x43, 0x65, 0x75, 0x82, 0x7D, 0x53, 0x48, 0x16, 0xEC, 0x28, 0xE8, 0x34, 0x49, 0x95, 0x58, 0x7C, 0x8D, 0xDF, 0xD8, + 0x72, 0x7C, 0xD9, 0xFC, 0x60, 0x8F, 0x92, 0x41, 0xD9, 0x8A, 0x42, 0x36, 0x2D, 0x4F, 0xEC, 0x26, 0x43, 0xDB, 0x93, 0x61, + 0xCA, 0x4A, 0x7F, 0xE9, 0xD0, 0x94, 0x8B, 0xB5, 0x31, 0x09, 0x67, 0x22, 0x51, 0xDE, 0x7B, 0x70, 0xF8, 0xBF, 0x03, 0x1F, + 0x68, 0x0A, 0x92, 0x73, 0x10, 0xBF, 0x1A, 0x78, 0xCD, 0x3F, 0x25, 0xC6, 0xB1, 0xC8, 0x94, 0x49, 0x56, 0xDB, 0x9D, 0xD7, + 0xEB, 0x7B, 0x12, 0x60, 0x52, 0x11, 0x65, 0xCA, 0xC6, 0x21, 0x47, 0x8F, 0x77, 0x1A, 0x10, 0x72, 0x94, 0xBF, 0xDF, 0xE9, + 0x84, 0x70, 0x3E, 0x51, 0x24, 0x23, 0x42, 0x0D, 0x8F, 0x7B, 0x45, 0xC0, 0xA7, 0xDA, 0xF5, 0x65, 0x8A, 0x42, 0xE8, 0xA0, + 0x26, 0xDE, 0xD6, 0xF2, 0xC2, 0xFF, 0x1E, 0x05, 0x81, 0x71, 0x70, 0xA6, 0xC5, 0x51, 0xFC, 0xF4, 0x40, 0x54, 0xAB, 0x23, + 0x74, 0x56, 0x4D, 0x32, 0x8F, 0x9E, 0xF2, 0xEC, 0x45, 0xEA, 0x9C, 0xF0, 0x27, 0x17, 0x4C, 0x70, 0x1D, 0x50, 0x47, 0x23, + 0x0E, 0x9D, 0xFD, 0xF4, 0xCA, 0xC9, 0xD1, 0x65, 0xAE, 0xB9, 0x1A, 0xA5, 0xF6, 0x18, 0x5D, 0x33, 0x21, 0x5F, 0x93, 0x37, + 0xB7, 0x9A, 0x14, 0xF1, 0x63, 0x09, 0xE4, 0xB7, 0x52, 0x6C, 0x7F, 0xF7, 0x48, 0x11, 0x46, 0xF9, 0x5F, 0x65, 0xEB, 0xC7, + 0xE5, 0xFE, 0x2E, 0x3F, 0x56, 0xD5, 0xF5, 0xE6, 0xA8, 0x14, 0x7F, 0x8D, 0xF2, 0x49, 0xD5, 0x48, 0x93, 0x28, 0xD6, 0xA9, + 0x90, 0x3A, 0xF8, 0xF7, 0xCA, 0x6C, 0xFF, 0x8F, 0xF8, 0x6A, 0x9E, 0xE9, 0xEC, 0x7F, 0x47, 0x29, 0x96, 0x58, 0xB0, 0xDB, + 0x08, 0x59, 0xAB, 0x5E, 0x9D, 0xB6, 0xDF, 0xCC, 0x7B, 0x56, 0x67, 0xB5, 0x10, 0x18, 0xCA, 0xAA, 0x69, 0xC3, 0xD7, 0x48, + 0x57, 0x59, 0xF1, 0xDD, 0x6C, 0x85, 0x21, 0x68, 0x1C, 0xB3, 0x76, 0x08, 0xD0, 0x12, 0xD8, 0xE1, 0xC0, 0x90, 0x66, 0x0B, + 0x5B, 0x38, 0x61, 0x78, 0x15, 0x97, 0x3F, 0x4B, 0xA3, 0xA3, 0xFF, 0x37, 0x16, 0x33, 0xCB, 0x6B, 0x06, 0x57, 0xBF, 0x8F, + 0x49, 0x12, 0x2F, 0xDB, 0xD0, 0x12, 0x5C, 0x65, 0x48, 0x51, 0x67, 0x0A, 0xD3, 0xD4, 0x97, 0xE1, 0xC8, 0x88, 0x84, 0x7C, + 0xA7, 0xE5, 0xDE, 0x01, 0xB5, 0x7F, 0xEC, 0xAC, 0x60, 0x4D, 0x4F, 0x55, 0x76, 0xA2, 0x3A, 0x13, 0xFA, 0x0C, 0xA5, 0x68, + 0xDF, 0xB9, 0xF8, 0x47, 0x9D, 0xCC, 0x45, 0xDA, 0x55, 0x5A, 0x9E, 0xE1, 0x6D, 0x08, 0x15, 0x65, 0x1B, 0x04, 0xCC, 0xD3, + 0x27, 0xB3, 0x67, 0xE1, 0x3D, 0x13, 0xFD, 0xED, 0x78, 0x22, 0xA1, 0x2E, 0x74, 0xFC, 0x21, 0xAA, 0xA6, 0x9A, 0xA1, 0xCF, + 0x2D, 0xA1, 0x68, 0xE5, 0x65, 0xA4, 0x5B, 0xD5, 0x62, 0xAE, 0xC8, 0xD0, 0x42, 0xA4, 0x44, 0x41, 0xE7, 0xE8, 0xE8, 0xBA, + 0x5B, 0xC8, 0x7F, 0x5D, 0x2B, 0x95, 0x22, 0xE3, 0x67, 0x85, 0x2A, 0x80, 0xD4, 0xE8, 0x19, 0x05, 0xD6, 0xCA, 0x63, 0x59, + 0xE2, 0x52, 0xB1, 0x06, 0x64, 0x84, 0xC9, 0x8F, 0x2E, 0xA4, 0x31, 0xB3, 0x05, 0xAF, 0x9C, 0x46, 0x65, 0x0A, 0xF8, 0xF7, + 0xB4, 0xF2, 0x80, 0x30, 0x2A, 0x91, 0xB4, 0xF9, 0x60, 0x55, 0x62, 0x7B, 0x88, 0xA5, 0xA7, 0xAE, 0x21, 0x03, 0x38, 0x47, + 0xB5, 0x39, 0x2C, 0x36, 0x8D, 0x1E, 0x61, 0x41, 0xA8, 0x55, 0x98, 0x17, 0xFE, 0x84, 0xC2, 0x19, 0xA0, 0xE6, 0x75, 0x3F, + 0x67, 0x4B, 0xFB, 0x2E, 0x9A, 0x61, 0x0B, 0xCB, 0x8E, 0x41, 0x73, 0x9A, 0x62, 0x37, 0x11, 0xE8, 0xE9, 0x24, 0x6B, 0xF7, + 0x6D, 0xE9, 0x40, 0xDB, 0x89, 0xD0, 0x85, 0x02, 0x26, 0x70, 0x5D, 0x28, 0x4D, 0x33, 0xF5, 0xBC, 0x3D, 0xCC, 0x4C, 0x0E, + 0xC3, 0x4A, 0x0F, 0x10, 0xC8, 0xB3, 0x30, 0x0F, 0xAC, 0xE8, 0xE1, 0xAF, 0xBC, 0xED, 0x25, 0x10, 0x6F, 0x0D, 0x9B, 0x94, + 0xAB, 0xFC, 0x1B, 0xC9, 0x06, 0x86, 0xDD, 0x77, 0x7D, 0xA7, 0xF2, 0x2B, 0x61, 0x8C, 0xCC, 0xE4, 0x65, 0x73, 0x31, 0x0A, + 0x2C, 0xEA, 0xD5, 0x76, 0x99, 0x46, 0xFF, 0xFF, 0xC0, 0x62, 0x4C, 0x56, 0x3E, 0x70, 0xBE, 0x3D, 0xCD, 0x1A, 0xDA, 0x26, + 0xDF, 0x93, 0x2C, 0x4B, 0x07, 0xEB, 0x4C, 0xD5, 0x08, 0x51, 0x14, 0x6D, 0xA6, 0x9C, 0x54, 0x6A, 0xE9, 0x4A, 0x04, 0x59, + 0xD2, 0x5E, 0xEA, 0x16, 0x9E, 0xF2, 0xD8, 0x6F, 0xA4, 0x9C, 0xFC, 0xC0, 0x13, 0xA2, 0xA0, 0x27, 0x89, 0x19, 0xE1, 0x54, + 0xDE, 0x7F, 0xD6, 0x17, 0x8A, 0xC5, 0xEE, 0x7A, 0xB4, 0xEC, 0x25, 0x83, 0x86, 0x17, 0xBB, 0x8B, 0x75, 0x56, 0xB0, 0x44, + 0x32, 0x97, 0xDB, 0x59, 0xC7, 0x62, 0x8B, 0x11, 0x16, 0x7B, 0x34, 0x53, 0x1A, 0xB6, 0xAF, 0x54, 0x2F, 0x91, 0xDB, 0xEF, + 0xC7, 0x24, 0xEB, 0x80, 0xDC, 0x5E, 0x2A, 0x23, 0x76, 0xF7, 0xE4, 0xD6, 0xA0, 0xFD, 0xED, 0xCB, 0x0A, 0xE7, 0x62, 0x10, + 0x92, 0x79, 0x23, 0x9E, 0x7B, 0xB4, 0xED, 0x95, 0xAF, 0xDB, 0x5A, 0xFF, 0x37, 0xA7, 0x07, 0xDA, 0xE1, 0x3E, 0xC3, 0xBA, + 0x78, 0x71, 0x91, 0x5A, 0x5B, 0x98, 0xD9, 0x0A, 0x5B, 0x4C, 0xA7, 0x40, 0xC9, 0x47, 0x6D, 0xB1, 0x03, 0x6A, 0x95, 0x3F, + 0xDE, 0x24, 0xF7, 0x14, 0xD8, 0x16, 0x15, 0x6A, 0xCE, 0x45, 0x7E, 0x4F, 0x22, 0x0D, 0x98, 0xBB, 0xA4, 0x25, 0xFC, 0x90, + 0xC7, 0x20, 0x7D, 0xB6, 0xCD, 0x5A, 0x80, 0x6A, 0x8F, 0xFA, 0x39, 0xAE, 0x46, 0x7A, 0xA7, 0x97, 0x58, 0x14, 0x90, 0xD5, + 0x30, 0x99, 0x69, 0xA1, 0x9B, 0x4F, 0xE1, 0x48, 0xAE, 0x37, 0x53, 0xE3, 0xC6, 0x4D, 0x51, 0x88, 0x4F, 0x3F, 0xF2, 0x2E, + 0x32, 0xFA, 0x24, 0xCF, 0x0D, 0x90, 0x2E, 0x33, 0xE1, 0x36, 0xE0, 0x0E, 0xCE, 0xD6, 0xFA, 0xFA, 0xF0, 0xBC, 0x5F, 0x34, + 0x6F, 0xFC, 0xD4, 0xF3, 0x42, 0x8F, 0x2D, 0x87, 0xD6, 0x9C, 0x5C, 0x22, 0x5F, 0x79, 0x2C, 0x27, 0x2F, 0x64, 0x76, 0xEE, + 0xD3, 0xFD, 0xEC, 0xA0, 0x56, 0x63, 0x53, 0xDB, 0xFF, 0xFF, 0xA8, 0x31, 0xE9, 0x49, 0x1A, 0x62, 0x16, 0xE9, 0x49, 0xA1, + 0xE5, 0x4B, 0xEE, 0x8C, 0x33, 0x36, 0x3D, 0x12, 0xEE, 0x1A, 0xB0, 0xE7, 0x33, 0x4D, 0x20, 0x00, 0x49, 0xBE, 0xA0, 0xCF, + 0x32, 0x17, 0x59, 0x10, 0x86, 0x99, 0x34, 0xF6, 0xEC, 0x47, 0x85, 0xA3, 0x22, 0xD2, 0x06, 0xA1, 0xD6, 0x2E, 0x48, 0x77, + 0x7E, 0xAE, 0xEF, 0xB1, 0x78, 0xD2, 0x23, 0x94, 0x36, 0x58, 0x0E, 0xB1, 0xD7, 0xFA, 0x80, 0xD0, 0x4D, 0x0C, 0x3F, 0xA6, + 0x90, 0x6C, 0x08, 0x65, 0x3D, 0x64, 0x88, 0xF0, 0x25, 0xE3, 0x97, 0x50, 0x27, 0xF8, 0xB0, 0xD6, 0x1A, 0x41, 0x9C, 0xF5, + 0x00, 0xB6, 0x87, 0x8B, 0x55, 0xDE, 0xC5, 0xBC, 0x8A, 0x47, 0x0D, 0x27, 0xD3, 0x06, 0xC1, 0x89, 0xE4, 0x0B, 0x0E, 0xFC, + 0xED, 0x62, 0x53, 0x50, 0xA0, 0x6D, 0xF1, 0x05, 0x91, 0x28, 0xA6, 0x02, 0x97, 0x2B, 0x85, 0x89, 0x31, 0x9C, 0x9A, 0x17, + 0xAB, 0x8D, 0xE4, 0xAD, 0x1B, 0x10, 0x12, 0x4E, 0xC7, 0xBE, 0x3E, 0xB7, 0xD8, 0xE9, 0x53, 0x0C, 0xAC, 0xF8, 0x26, 0x8E, + 0x1D, 0x23, 0x40, 0x3A, 0xDB, 0x41, 0x5F, 0x01, 0x5F, 0x2B, 0xFC, 0xE1, 0x84, 0x45, 0xD3, 0x3C, 0xDC, 0x97, 0xA8, 0x59, + 0x48, 0x55, 0x2C, 0xCD, 0xE8, 0xE1, 0xF3, 0x6B, 0x62, 0x42, 0x08, 0x3D, 0xF1, 0x48, 0x9E, 0xBB, 0x41, 0x33, 0x3D, 0xC6, + 0x30, 0x7B, 0x82, 0xD9, 0x26, 0x81, 0xA2, 0x0C, 0x14, 0x21, 0xB5, 0xA8, 0x46, 0xB7, 0xB5, 0x81, 0xDA, 0xD7, 0x95, 0x59, + 0x2F, 0xA0, 0xC0, 0x4C, 0xB8, 0x20, 0x14, 0xD8, 0xEA, 0x4F, 0xE4, 0x65, 0x7A, 0xBF, 0x25, 0xAB, 0x8B, 0x6E, 0xC9, 0x49, + 0x39, 0x23, 0x57, 0x4D, 0xCC, 0x2C, 0x2C, 0xE9, 0xA1, 0x45, 0xCE, 0xEB, 0x83, 0xEF, 0xC1, 0x7D, 0x38, 0x22, 0x65, 0x74, + 0x44, 0xC9, 0x6C, 0x40, 0xBB, 0xFD, 0x76, 0x84, 0x6C, 0x9D, 0x3F, 0x35, 0xBC, 0x72, 0x4C, 0xA4, 0x48, 0x19, 0x51, 0x99, + 0x76, 0x32, 0x8B, 0x76, 0x12, 0x77, 0xB4, 0xD3, 0xFB, 0x32, 0xDC, 0x34, 0x11, 0x5C, 0x30, 0x2F, 0x9A, 0xC2, 0x5C, 0x00, + 0x07, 0x09, 0x1F, 0xAA, 0x47, 0x57, 0xD5, 0xD5, 0x62, 0xEF, 0x33, 0x21, 0xB2, 0x0C, 0xB5, 0x6F, 0xB1, 0x5E, 0x36, 0x06, + 0xCD, 0x39, 0x63, 0x8C, 0x4D, 0x5E, 0xA7, 0x27, 0xF1, 0xDC, 0xF3, 0xC8, 0x24, 0xAF, 0x04, 0x3C, 0xAD, 0x76, 0x2C, 0x82, + 0x80, 0x34, 0xEE, 0x54, 0x90, 0xDB, 0xE0, 0x4E, 0x22, 0x97, 0x22, 0x24, 0x23, 0x3A, 0xF0, 0xB0, 0x67, 0x7C, 0x86, 0x6F, + 0x1B, 0xC5, 0xD9, 0x45, 0xAC, 0xB9, 0x1B, 0x0B, 0x30, 0x3E, 0xD1, 0x26, 0x62, 0x76, 0x71, 0x96, 0x8E, 0x79, 0x8D, 0x55, + 0x29, 0xE8, 0x65, 0xD0, 0x97, 0x31, 0xD6, 0xB7, 0xE9, 0x4C, 0xA3, 0xF3, 0x12, 0xF4, 0xF9, 0x4F, 0x1B, 0x3E, 0xC2, 0x8E, + 0x70, 0x7A, 0x68, 0x08, 0x9C, 0xA9, 0xC5, 0x5C, 0xE6, 0x89, 0x2E, 0x6B, 0x8A, 0x0B, 0x33, 0xA5, 0xC2, 0x3D, 0xDA, 0xE6, + 0x67, 0x47, 0xDC, 0x58, 0xE4, 0x84, 0xBF, 0x16, 0x5D, 0x93, 0x1D, 0xF3, 0xB9, 0x6A, 0x4E, 0xAC, 0x3D, 0x36, 0x57, 0x29, + 0x89, 0x38, 0xB7, 0xE9, 0x29, 0xBD, 0x89, 0xF2, 0xC1, 0x84, 0x62, 0x4A, 0xCF, 0x8F, 0x32, 0x53, 0x09, 0x28, 0x1F, 0xE0, + 0x2C, 0x5E, 0xE6, 0x95, 0x3C, 0x5E, 0x36, 0x9E, 0x4B, 0x45, 0xA4, 0x1F, 0xF6, 0xD1, 0xD2, 0x5C, 0x25, 0xB2, 0xAE, 0x6F, + 0xAC, 0x30, 0x5E, 0x78, 0xEC, 0xCD, 0xE0, 0xE5, 0xF4, 0xFB, 0x65, 0x32, 0xAC, 0xA5, 0x8E, 0x6D, 0x1B, 0xEE, 0x07, 0xE5, + 0xE4, 0x5D, 0x83, 0x0F, 0xB2, 0xCE, 0xE3, 0x47, 0xA8, 0x87, 0x91, 0xE1, 0xBB, 0x90, 0x06, 0x69, 0x4E, 0x59, 0x00, 0xBD, + 0xF7, 0xD4, 0x5E, 0xDA, 0xA1, 0xEE, 0xF9, 0x9C, 0xF1, 0x21, 0x08, 0xC2, 0x0C, 0x3B, 0x4D, 0x61, 0xAD, 0x96, 0x90, 0x22, + 0xD7, 0xCE, 0x4F, 0xD6, 0x25, 0xE3, 0x68, 0xB6, 0x55, 0x4C, 0xB8, 0xC5, 0x67, 0x6A, 0x43, 0x73, 0x85, 0x20, 0xDE, 0xF8, + 0x6D, 0xCC, 0xB1, 0xA7, 0xFD, 0x1F, 0xCF, 0x8E, 0x35, 0x64, 0x77, 0xCB, 0x8D, 0x98, 0x33, 0x69, 0x94, 0xE0, 0x60, 0x33, + 0x62, 0xC5, 0x5C, 0x0A, 0xD3, 0xA1, 0x5E, 0x5A, 0x89, 0x02, 0xEA, 0x06, 0xB5, 0xA2, 0x74, 0xA2, 0x02, 0x69, 0x8E, 0x60, + 0xB7, 0x67, 0x6C, 0x76, 0x01, 0xE7, 0xEC, 0xB4, 0x95, 0xED, 0xFC, 0x8F, 0x4F, 0x84, 0xB0, 0xF6, 0xAB, 0xC6, 0xE1, 0x03, + 0x8A, 0x7D, 0x69, 0x44, 0x37, 0x2E, 0x72, 0x13, 0xCE, 0xCF, 0x83, 0xE3, 0xC9, 0x8B, 0x27, 0xF3, 0x26, 0xD7, 0xC9, 0x35, + 0xD6, 0xA3, 0xA6, 0x73, 0xE3, 0xC6, 0xA3, 0xED, 0xBF, 0x57, 0x22, 0x6C, 0x4C, 0xC7, 0x62, 0x7A, 0xB9, 0x77, 0x44, 0x90, + 0xEF, 0x89, 0xA9, 0xD5, 0xB5, 0xD8, 0x22, 0x1F, 0x6E, 0x95, 0xCC, 0x7C, 0xF6, 0xCD, 0xEE, 0xBC, 0x25, 0x75, 0xC4, 0x93, + 0xBC, 0x6F, 0x9B, 0xCC, 0x4E, 0x96, 0x1E, 0xFC, 0x18, 0xC9, 0x1E, 0x50, 0x55, 0xB7, 0x4E, 0x68, 0x25, 0x9C, 0xD3, 0xF3, + 0xD1, 0xC6, 0x14, 0x2E, 0x19, 0x54, 0x84, 0x60, 0x34, 0xF2, 0xBB, 0xCC, 0xEB, 0x60, 0x5C, 0x52, 0x81, 0x0A, 0x9A, 0x88, + 0x3E, 0xAD, 0xF6, 0x6E, 0x67, 0x14, 0x8C, 0x68, 0xBF, 0x6F, 0x6E, 0x7E, 0x3C, 0x9C, 0x15, 0x5A, 0x6E, 0xF0, 0xFA, 0x1B, + 0x1A, 0xCE, 0xF2, 0x56, 0x3C, 0x5F, 0x67, 0x0B, 0x82, 0x75, 0x24, 0xC7, 0x7F, 0x11, 0x2A, 0xF6, 0x6B, 0xC7, 0x81, 0xEB, + 0xC1, 0x83, 0xAB, 0xDF, 0x4F, 0x30, 0xD5, 0x82, 0xBC, 0xCF, 0x3F, 0xFA, 0x4D, 0x33, 0xED, 0x66, 0x34, 0xAB, 0x5C, 0x42, + 0x62, 0x8B, 0xA0, 0x38, 0xE9, 0x0D, 0x60, 0xE5, 0x8D, 0xD3, 0x83, 0x0B, 0x80, 0x63, 0x94, 0x6D, 0x16, 0xF4, 0xCE, 0x96, + 0x34, 0xA0, 0x02, 0x8F, 0xAF, 0xF2, 0x2D, 0xA8, 0xF9, 0x05, 0xAD, 0xE5, 0x53, 0x82, 0x0A, 0xA3, 0x49, 0xDC, 0x53, 0x07, + 0x0F, 0x91, 0x02, 0x1E, 0xF2, 0x02, 0x95, 0x0C, 0xB7, 0xDE, 0xF7, 0x1B, 0xC9, 0xF1, 0x43, 0x12, 0x0C, 0x90, 0x1D, 0xED, + 0x40, 0x6F, 0xBB, 0xC3, 0x02, 0x39, 0x73, 0x44, 0xDC, 0xAA, 0x24, 0xEB, 0xC5, 0xCF, 0xF3, 0x1B, 0x52, 0x5B, 0x52, 0xCA, + 0x46, 0xD5, 0x85, 0xB4, 0x5C, 0x64, 0xFB, 0x10, 0xE0, 0x95, 0xA3, 0x93, 0x8A, 0x9B, 0xE0, 0x71, 0xA2, 0x56, 0xC5, 0xDF, + 0x34, 0x11, 0x33, 0x85, 0x64, 0xD5, 0x51, 0x85, 0x0D, 0xB4, 0x75, 0xCA, 0x4E, 0xE7, 0xED, 0x24, 0xCB, 0xB1, 0xD5, 0xF6, + 0x65, 0x9F, 0x9F, 0xE7, 0xD3, 0xEC, 0xC5, 0x4A, 0x68, 0x99, 0x66, 0x1D, 0xC7, 0x33, 0x85, 0x0B, 0x5F, 0x98, 0x99, 0xC1, + 0xA5, 0x2D, 0xA8, 0xE8, 0x1E, 0x99, 0x08, 0xD9, 0xE7, 0x16, 0xFA, 0x70, 0xD6, 0x76, 0x39, 0x92, 0xF2, 0x04, 0xB6, 0x87, + 0x8E, 0xEB, 0x62, 0xB2, 0xBA, 0xF8, 0x9C, 0xEC, 0xE2, 0x06, 0xE6, 0x90, 0xC6, 0xB8, 0xD7, 0x64, 0x2D, 0x3A, 0xFA, 0xED, + 0x7F, 0xBB, 0x6D, 0xA5, 0xC3, 0x99, 0xD9, 0xB9, 0x14, 0x9F, 0x8A, 0x58, 0x2A, 0x96, 0x90, 0x00, 0x9F, 0x17, 0xBC, 0x1A, + 0x62, 0xD3, 0xBD, 0x88, 0x70, 0xBA, 0xEE, 0x9A, 0x23, 0x66, 0xD0, 0x93, 0x5E, 0xFD, 0x1E, 0xBE, 0x4E, 0x56, 0x2A, 0x04, + 0x1F, 0x67, 0xE5, 0xB8, 0xFE, 0x18, 0xB7, 0xCF, 0x55, 0x9D, 0x17, 0xAF, 0xF9, 0xD1, 0xB7, 0xC9, 0xFC, 0x73, 0x6B, 0xFF, + 0x46, 0x0F, 0xB7, 0xAF, 0x56, 0x0F, 0xA0, 0x19, 0x43, 0x54, 0x86, 0x99, 0x72, 0x9D, 0x60, 0x1B, 0x03, 0x0F, 0x84, 0x06, + 0x14, 0xDB, 0xA0, 0xA0, 0xA1, 0x23, 0xD4, 0xB2, 0x33, 0x1E, 0xE4, 0x82, 0x09, 0x09, 0xA8, 0x86, 0x91, 0x29, 0x38, 0x31, + 0x59, 0x91, 0xA2, 0x84, 0xBB, 0xCE, 0x58, 0x1E, 0x65, 0xDD, 0x81, 0xC2, 0x6D, 0xAB, 0x0A, 0xC1, 0x80, 0x72, 0x87, 0x0D, + 0x3B, 0x26, 0x9D, 0x73, 0xC0, 0x0B, 0x0D, 0xE8, 0x99, 0x62, 0x39, 0x03, 0xE5, 0x01, 0x3D, 0x31, 0xDB, 0x3F, 0x14, 0x46, + 0xCA, 0x07, 0x78, 0xBA, 0x71, 0x90, 0x43, 0x9C, 0x06, 0xC9, 0x07, 0x56, 0xAD, 0xB1, 0xF7, 0xD4, 0x05, 0x94, 0xB7, 0xBC, + 0xC5, 0x68, 0x98, 0x04, 0xC8, 0x48, 0x18, 0x24, 0x06, 0x7E, 0xE5, 0xB0, 0x21, 0x46, 0x01, 0x9C, 0xB5, 0x19, 0x2E, 0x91, + 0x12, 0xF7, 0xA9, 0xE1, 0xE5, 0xE8, 0x71, 0xBF, 0x2F, 0x0A, 0xB2, 0xBA, 0x11, 0x23, 0x22, 0x11, 0xD5, 0x2B, 0x5A, 0x13, + 0x28, 0xCA, 0x7A, 0x72, 0x29, 0x88, 0xDB, 0x25, 0x1E, 0x6A, 0x54, 0x0D, 0xA9, 0xEE, 0xEB, 0x43, 0x24, 0x97, 0xA6, 0xE8, + 0x01, 0x9F, 0x66, 0x83, 0x1A, 0x59, 0x1E, 0x1C, 0xA0, 0x39, 0xCD, 0xC7, 0xE8, 0xFA, 0x3B, 0x59, 0x08, 0x05, 0x9E, 0xF2, + 0x71, 0x1A, 0x6B, 0x69, 0xC4, 0xB1, 0x2A, 0x91, 0x2F, 0x57, 0x19, 0xC1, 0x3A, 0x46, 0x4B, 0x99, 0x6F, 0x39, 0x01, 0x3D, + 0xE8, 0x2B, 0xE0, 0x39, 0xD3, 0x37, 0xBF, 0x5B, 0x2C, 0x68, 0xCD, 0x2E, 0x14, 0x4E, 0xED, 0xF2, 0xF5, 0xD1, 0x4E, 0x3E, + 0x74, 0x0F, 0x32, 0x5C, 0xF6, 0x4F, 0xF2, 0x40, 0xC6, 0x10, 0x61, 0xE7, 0xF4, 0x56, 0x27, 0x81, 0x53, 0x2F, 0x65, 0xEC, + 0x0E, 0xA5, 0x07, 0x9D, 0xC4, 0x2D, 0xBF, 0xF6, 0xCB, 0x2E, 0x99, 0x2F, 0x9B, 0x69, 0x8B, 0x61, 0x3E, 0x7B, 0x64, 0x03, + 0x6A, 0xF3, 0x51, 0x1F, 0x38, 0x32, 0x84, 0xF4, 0xE8, 0x1D, 0xBD, 0xF0, 0xA0, 0x0F, 0x14, 0x7A, 0x9C, 0x3D, 0x90, 0x5D, + 0x68, 0x11, 0x6D, 0x83, 0xD1, 0x0F, 0x02, 0x78, 0xFD, 0xDC, 0xAC, 0x7E, 0xC4, 0xB8, 0x66, 0xD0, 0x25, 0x13, 0x3B, 0x89, + 0xA1, 0x72, 0x5F, 0x83, 0x32, 0x18, 0x69, 0x1E, 0x41, 0xBB, 0x4C, 0x89, 0x45, 0xAD, 0xAC, 0x81, 0x24, 0xA3, 0xF2, 0xD6, + 0x54, 0xE5, 0xAD, 0x1F, 0x95, 0x35, 0x50, 0xC5, 0x1C, 0x5A, 0xBA, 0x14, 0x65, 0x30, 0x7C, 0x50, 0x81, 0x51, 0xC5, 0x46, + 0xD8, 0x03, 0xAB, 0x10, 0x6A, 0x48, 0x8D, 0x74, 0xD7, 0x72, 0x49, 0x2E, 0x10, 0xC5, 0x48, 0x25, 0x43, 0x15, 0xDC, 0xB7, + 0x4D, 0x4B, 0x71, 0x0B, 0x75, 0x9C, 0xC0, 0xB3, 0xA4, 0x9E, 0xFD, 0xD5, 0x11, 0x32, 0xEA, 0xAB, 0xF2, 0x52, 0x85, 0xEC, + 0xF4, 0x1E, 0xF5, 0x3E, 0x94, 0x17, 0xAD, 0x66, 0x0D, 0x3A, 0x26, 0x19, 0x5B, 0x18, 0x32, 0x77, 0xD1, 0xC7, 0x14, 0x50, + 0x9B, 0x55, 0x25, 0x66, 0x99, 0xA7, 0x11, 0x40, 0x50, 0x15, 0x33, 0x09, 0xFA, 0xAC, 0x77, 0xFE, 0xA4, 0xAF, 0xB6, 0x62, + 0x95, 0x34, 0xDE, 0x71, 0x0C, 0xAE, 0x2E, 0xB1, 0x7F, 0xF1, 0x78, 0x79, 0xFB, 0xCB, 0x33, 0xEF, 0x43, 0x5F, 0xE8, 0x5B, + 0xC9, 0x6A, 0x25, 0xCF, 0xDB, 0x33, 0xBF, 0xEE, 0xA7, 0xA4, 0x70, 0xB9, 0xBF, 0x19, 0x1B, 0xBC, 0x96, 0x7B, 0x9A, 0xE6, + 0x04, 0xC7, 0x71, 0xF5, 0xDA, 0xCD, 0x9E, 0x48, 0xD3, 0xAD, 0x0F, 0xB0, 0xCF, 0x57, 0x8C, 0xED, 0xD9, 0x30, 0xC7, 0xBE, + 0x43, 0x87, 0xAE, 0x6F, 0x94, 0x32, 0x07, 0xA0, 0xCC, 0xD0, 0xC8, 0x8C, 0x1B, 0x07, 0xC7, 0x2C, 0x3C, 0x05, 0xB5, 0xCC, + 0xF6, 0xB3, 0x17, 0x01, 0x52, 0x13, 0x66, 0x05, 0xE4, 0x33, 0xB7, 0x31, 0xE2, 0x52, 0xEF, 0xC9, 0x39, 0x98, 0x3F, 0x4A, + 0x48, 0x50, 0xA6, 0x9B, 0xD9, 0x72, 0x8C, 0x87, 0xFB, 0x0B, 0x60, 0x82, 0x79, 0xCE, 0xEF, 0x23, 0x60, 0xDB, 0xEA, 0x9D, + 0x3C, 0x38, 0x88, 0x60, 0x67, 0x35, 0xAC, 0x32, 0x6A, 0xA1, 0xC7, 0xB6, 0x3F, 0x6B, 0xCE, 0xC5, 0xD9, 0xA0, 0x69, 0x32, + 0xE5, 0x2D, 0x46, 0x47, 0x98, 0x59, 0x20, 0x45, 0x3F, 0x4F, 0xCF, 0x21, 0x35, 0x61, 0x57, 0x14, 0x78, 0x8C, 0x39, 0xE9, + 0x68, 0x02, 0xF9, 0xA2, 0x61, 0xC9, 0xE3, 0x57, 0xBD, 0xB2, 0x18, 0xC6, 0x5A, 0x68, 0x20, 0x9F, 0x35, 0x1B, 0x9C, 0xF8, + 0x45, 0x64, 0x48, 0x95, 0x1F, 0x91, 0xB8, 0x6D, 0x29, 0x1E, 0x57, 0x11, 0xDD, 0xD4, 0x7A, 0x6B, 0xBD, 0x45, 0xFC, 0xF2, + 0x24, 0x99, 0xE6, 0x41, 0x5B, 0x53, 0xB8, 0xDD, 0x33, 0xD9, 0x4E, 0x73, 0x31, 0xC2, 0xEB, 0x15, 0x2D, 0x1D, 0x69, 0x40, + 0xED, 0xF4, 0xE1, 0xD2, 0x62, 0x01, 0x10, 0x0D, 0x48, 0x41, 0x51, 0x7A, 0xE4, 0x95, 0x7F, 0x0B, 0x3F, 0xFA, 0x9A, 0xF1, + 0xE9, 0xCB, 0x72, 0xC2, 0x74, 0x85, 0xCC, 0x28, 0x3F, 0x5D, 0xBF, 0xF5, 0xEC, 0xEA, 0xD4, 0x18, 0x7E, 0x8C, 0x45, 0xBE, + 0x37, 0x63, 0x2A, 0x5C, 0xEE, 0x8C, 0x9B, 0xE4, 0x65, 0x03, 0x58, 0xFF, 0xBD, 0x5B, 0xCC, 0x58, 0xD8, 0x48, 0xE5, 0x06, + 0x37, 0x8E, 0xD2, 0x65, 0x00, 0xFD, 0x78, 0xEC, 0x11, 0xA6, 0xFB, 0xAA, 0x69, 0xC3, 0x83, 0xD4, 0x71, 0xE6, 0x3C, 0xF2, + 0x06, 0xF9, 0x77, 0xB0, 0xE3, 0xC2, 0x70, 0x2A, 0x56, 0xA4, 0x4A, 0xA9, 0x94, 0x65, 0x4A, 0x53, 0x09, 0x36, 0x57, 0xCD, + 0x23, 0x52, 0x20, 0x7B, 0xE8, 0x8C, 0x9A, 0x60, 0x3A, 0xE0, 0x31, 0xCF, 0xBF, 0x17, 0x00, 0x8F, 0x8A, 0xC2, 0x7C, 0x6F, + 0xFD, 0xFB, 0xFB, 0x6B, 0x59, 0x9E, 0x87, 0xD9, 0x5B, 0x4A, 0xD4, 0x98, 0x41, 0xA7, 0xC0, 0x1B, 0xEB, 0x4D, 0x9B, 0xDF, + 0xC1, 0xE0, 0x1F, 0x62, 0x6C, 0x1B, 0x0D, 0x04, 0xE0, 0xFF, 0xA4, 0x4A, 0x54, 0x92, 0xCF, 0x4E, 0x20, 0xBD, 0x12, 0xE2, + 0x1D, 0x10, 0x51, 0xD8, 0xC0, 0xED, 0x3D, 0x36, 0x63, 0x95, 0xB0, 0x99, 0x5F, 0xA4, 0x6D, 0xAA, 0x24, 0x32, 0x9D, 0x79, + 0x18, 0xBF, 0xF5, 0xB1, 0x69, 0x74, 0xEB, 0xE7, 0xF4, 0x5D, 0x65, 0x60, 0x21, 0x1E, 0x97, 0x7C, 0x06, 0xF2, 0xC6, 0x37, + 0xE3, 0xF5, 0xED, 0x88, 0x89, 0x26, 0x1B, 0x2A, 0x33, 0xD9, 0x18, 0x36, 0x3E, 0xBB, 0xE4, 0x90, 0x55, 0x4C, 0xF2, 0x62, + 0x0D, 0xE8, 0x56, 0x34, 0x37, 0xDA, 0x9E, 0xD7, 0x7B, 0x18, 0x6F, 0x70, 0xE7, 0x3A, 0x8B, 0x74, 0x55, 0xE7, 0xC9, 0x58, + 0xA7, 0x86, 0x85, 0x74, 0x19, 0xBB, 0x8D, 0xC7, 0x07, 0x79, 0xD5, 0xE2, 0xF0, 0x4D, 0x6C, 0x35, 0x22, 0xC6, 0xFE, 0x37, + 0xBB, 0x4C, 0x45, 0x23, 0xBB, 0x78, 0xA7, 0xF4, 0x54, 0x92, 0x74, 0x91, 0xC7, 0xFC, 0xFC, 0x89, 0x54, 0x60, 0x9A, 0x34, + 0x97, 0x9A, 0x25, 0x2A, 0x01, 0x3B, 0x4C, 0x9B, 0x2C, 0x49, 0x18, 0x6D, 0xB1, 0xB4, 0x86, 0x44, 0x90, 0xB7, 0x06, 0x45, + 0x80, 0x95, 0x18, 0x69, 0x51, 0xF4, 0xD9, 0x89, 0x5D, 0x39, 0x68, 0xCE, 0xDF, 0x99, 0x8D, 0x50, 0xCF, 0x2A, 0x75, 0x9A, + 0x7F, 0x04, 0x3F, 0x77, 0xE0, 0xF9, 0xDC, 0xFB, 0xAD, 0x20, 0xD8, 0x7F, 0xCD, 0x5F, 0x91, 0x35, 0x62, 0x11, 0xE2, 0xEA, + 0x41, 0xBC, 0xE3, 0x0A, 0x6A, 0x23, 0xAC, 0xAC, 0xDD, 0xFA, 0x4E, 0x7F, 0xD1, 0x42, 0x2E, 0x3B, 0xAC, 0xA6, 0xA7, 0x85, + 0x69, 0x67, 0x86, 0x38, 0x27, 0xB3, 0x9C, 0x23, 0xBB, 0xD1, 0x77, 0x4B, 0xC5, 0x21, 0xE7, 0xD4, 0xBB, 0x9C, 0xA7, 0xEA, + 0x9D, 0xDE, 0x6D, 0x27, 0xE7, 0x9B, 0xAE, 0xB9, 0xD4, 0xB0, 0x27, 0x04, 0xDC, 0x49, 0x48, 0xDB, 0xFF, 0xFF, 0x3E, 0xAD, + 0x68, 0x0D, 0xFD, 0xC6, 0xB1, 0x26, 0x47, 0x52, 0x64, 0x95, 0x17, 0xFF, 0xAB, 0x0E, 0xF3, 0xE0, 0x20, 0xF0, 0xE8, 0x96, + 0xC5, 0x4E, 0x18, 0x34, 0x1D, 0x10, 0xE0, 0x74, 0x49, 0x23, 0xFE, 0x72, 0xB6, 0x61, 0x22, 0xEF, 0x96, 0x98, 0x40, 0x1E, + 0xFA, 0xD9, 0x2E, 0xBE, 0x25, 0xC4, 0x77, 0x17, 0xE2, 0x26, 0xB1, 0x24, 0xBB, 0x2C, 0xBA, 0x91, 0x1D, 0x60, 0x01, 0x28, + 0x24, 0x97, 0xC7, 0x52, 0x26, 0xAB, 0x7F, 0x75, 0xB3, 0xF5, 0x12, 0x84, 0xB5, 0xD1, 0x82, 0x7A, 0xB9, 0x00, 0x70, 0xAF, + 0xEA, 0x6D, 0xDE, 0x36, 0xE4, 0xD8, 0xDF, 0x5C, 0xCE, 0xC8, 0x14, 0xE4, 0xA4, 0x98, 0xE5, 0x23, 0x75, 0x63, 0x3E, 0xAD, + 0x84, 0x6B, 0x83, 0x5A, 0xAC, 0x04, 0x8B, 0x64, 0x71, 0xCB, 0x5F, 0x33, 0xA7, 0xAC, 0x6A, 0xB7, 0x53, 0x8A, 0xBE, 0x9E, + 0x22, 0x91, 0x75, 0xEB, 0xD0, 0xF5, 0xD1, 0xFB, 0x84, 0x05, 0xE2, 0x12, 0xBF, 0x25, 0xFE, 0x5B, 0x62, 0xCE, 0xEA, 0xA8, + 0x5A, 0xCA, 0x32, 0xEB, 0x63, 0x67, 0xB0, 0xEF, 0x1C, 0x8D, 0x19, 0x78, 0x0D, 0xE2, 0x36, 0xAE, 0x05, 0x63, 0x93, 0xFA, + 0xEA, 0x6F, 0xD5, 0xAD, 0x3B, 0x6B, 0x13, 0x5A, 0xEA, 0xCC, 0x95, 0x69, 0x31, 0x22, 0x6D, 0x25, 0x60, 0xBA, 0x03, 0x58, + 0xBB, 0x3B, 0x4B, 0x21, 0xA2, 0x68, 0x1B, 0x1C, 0xC7, 0x2A, 0x3A, 0x4C, 0xE3, 0x44, 0xBA, 0x7D, 0xBB, 0x8D, 0xAB, 0x52, + 0x78, 0xF9, 0x8C, 0x8E, 0x5E, 0x91, 0x32, 0x5F, 0x2F, 0x0B, 0x6A, 0x2E, 0x79, 0x99, 0x0C, 0xFC, 0x17, 0x1C, 0x03, 0x76, + 0x5D, 0x36, 0x71, 0xBA, 0x0E, 0xAA, 0xFB, 0x7D, 0x6A, 0x81, 0x06, 0x57, 0xA8, 0xBB, 0xE1, 0x5D, 0xFF, 0x2C, 0x1B, 0x51, + 0xE8, 0x2F, 0x0B, 0x3C, 0x66, 0x4A, 0xF7, 0x06, 0x55, 0x12, 0xBF, 0x3D, 0x83, 0xE4, 0xE7, 0x73, 0x16, 0x51, 0x9F, 0xC8, + 0xD9, 0x78, 0xEF, 0x24, 0x62, 0x18, 0x05, 0x57, 0xF4, 0xFD, 0xB3, 0xA1, 0x1F, 0xBE, 0xF7, 0xB3, 0x90, 0x5D, 0x24, 0x5E, + 0xE2, 0x5C, 0x0C, 0x44, 0x14, 0xD0, 0xB2, 0x51, 0xD7, 0x12, 0x45, 0xE4, 0x50, 0x3F, 0x7D, 0xC3, 0x5F, 0x5C, 0xC7, 0xBB, + 0x1B, 0x16, 0xD8, 0xEF, 0xCB, 0x40, 0x6A, 0xEF, 0x67, 0x39, 0x60, 0x73, 0x40, 0x55, 0x0E, 0x46, 0x75, 0xFE, 0x1E, 0x4E, + 0x5E, 0x56, 0xA2, 0x01, 0x31, 0x4D, 0x34, 0xFE, 0x07, 0x59, 0xAA, 0xC9, 0x74, 0x8E, 0x0A, 0xAF, 0x00, 0x67, 0xF4, 0x2E, + 0x9F, 0x38, 0x54, 0xF4, 0x1C, 0x35, 0xCD, 0x70, 0x1E, 0x35, 0x85, 0x87, 0x03, 0x12, 0x7A, 0x41, 0x85, 0x72, 0xAA, 0xA6, + 0x20, 0x36, 0x8B, 0x18, 0x96, 0xCD, 0x17, 0x5C, 0xDF, 0x55, 0xB2, 0xA6, 0xA4, 0x48, 0xE2, 0xC1, 0xE7, 0x51, 0x71, 0x86, + 0x9F, 0xD1, 0x78, 0x24, 0x0C, 0xB5, 0x07, 0xFF, 0x3D, 0x7A, 0xB5, 0x5A, 0x6E, 0xE2, 0xC4, 0x0B, 0x93, 0x1C, 0x59, 0xEB, + 0x1F, 0x9A, 0x3A, 0xE3, 0x9A, 0x94, 0xDE, 0x61, 0xD3, 0x55, 0xCA, 0x4F, 0xFD, 0xF4, 0xD2, 0xB9, 0x57, 0xB5, 0x9B, 0xBF, + 0x4D, 0x35, 0x77, 0x2B, 0x3C, 0x45, 0x07, 0x5D, 0xC1, 0xDB, 0xF0, 0x6A, 0xDB, 0x5A, 0x03, 0xAC, 0x18, 0xBA, 0x27, 0xD2, + 0x68, 0x56, 0xCD, 0xA3, 0x12, 0x1F, 0x86, 0xDF, 0xD1, 0xB1, 0x2A, 0xB7, 0xA4, 0xB7, 0x06, 0x65, 0xC9, 0x5A, 0x43, 0x9F, + 0x1E, 0xDA, 0x8E, 0x5C, 0x5A, 0xA2, 0xEE, 0x56, 0x3A, 0x37, 0x26, 0x9A, 0x9C, 0xA2, 0xE4, 0x6F, 0x43, 0x82, 0x46, 0x4D, + 0xE0, 0x65, 0xE7, 0x27, 0x4B, 0xB7, 0xF4, 0x08, 0x4B, 0xDE, 0x46, 0x2D, 0xEB, 0x12, 0x71, 0xD0, 0x26, 0xA9, 0x95, 0x27, + 0xC7, 0x90, 0x06, 0xF2, 0x0E, 0xE0, 0xE5, 0x6E, 0xCB, 0xA0, 0x3A, 0x00, 0xB7, 0x2D, 0x22, 0xF6, 0x15, 0x01, 0x30, 0xA0, + 0x90, 0x4F, 0x8E, 0x0B, 0x3C, 0x51, 0xB8, 0xE2, 0x24, 0x20, 0x24, 0x27, 0xB4, 0x20, 0x00, 0x59, 0xC4, 0xCC, 0xC6, 0x30, + 0xB4, 0x62, 0x73, 0x73, 0x04, 0x94, 0x2D, 0xF4, 0x99, 0x0F, 0xF1, 0xFA, 0x7E, 0xCE, 0xA7, 0x45, 0xB4, 0xFF, 0xFC, 0xE0, + 0x01, 0x08, 0x81, 0xE4, 0x11, 0x2E, 0x80, 0x71, 0x64, 0xBE, 0x9E, 0xC4, 0x59, 0xA2, 0x18, 0xC0, 0x24, 0x54, 0xD8, 0xB8, + 0xBA, 0xA9, 0xB0, 0xF2, 0x09, 0xCC, 0x8F, 0x5B, 0xBD, 0xA0, 0x0A, 0x52, 0x06, 0x37, 0x28, 0xD7, 0x82, 0xE5, 0xA7, 0x72, + 0x63, 0x87, 0x5C, 0x86, 0x5F, 0xEA, 0x19, 0x67, 0x7B, 0xE8, 0x1E, 0xC5, 0xB0, 0x2E, 0xF5, 0x9E, 0xCE, 0x87, 0xCB, 0xD7, + 0x02, 0x49, 0x33, 0xDE, 0xFB, 0xC5, 0xB6, 0x5B, 0xE0, 0x73, 0xE1, 0xFE, 0xC1, 0xEE, 0x7E, 0x16, 0xA1, 0xA6, 0x15, 0xBB, + 0x3A, 0x27, 0xF0, 0x0D, 0x1A, 0xE1, 0x1A, 0x48, 0xB8, 0xCB, 0xEB, 0x34, 0xB9, 0x69, 0x86, 0x69, 0x33, 0x7F, 0x0A, 0x6C, + 0x7F, 0x8D, 0x97, 0xBE, 0x16, 0xF0, 0xE8, 0x20, 0xB6, 0x8D, 0x87, 0x2F, 0xA2, 0x55, 0x27, 0x3F, 0x3D, 0x05, 0x84, 0x8A, + 0x51, 0x37, 0xA4, 0xDC, 0x58, 0x67, 0x55, 0xB6, 0x64, 0xD8, 0x6B, 0x7E, 0x60, 0xE9, 0x8C, 0x53, 0x3E, 0x74, 0x2B, 0xCF, + 0xFA, 0x4A, 0xA2, 0x5D, 0xF5, 0x07, 0x3D, 0xB4, 0xF7, 0xC6, 0x02, 0x08, 0xCC, 0xCF, 0xAC, 0x42, 0x5E, 0x48, 0x0C, 0xDE, + 0x45, 0xF6, 0x95, 0xDA, 0x78, 0x59, 0xBA, 0x1B, 0xE9, 0xC0, 0x08, 0x1C, 0x7E, 0x2D, 0xA2, 0x76, 0x88, 0xCC, 0x1E, 0xA3, + 0x9E, 0x23, 0x76, 0x89, 0xFD, 0x9A, 0x3A, 0x42, 0x5C, 0xEA, 0xAB, 0xDF, 0xFE, 0x30, 0xD1, 0xA0, 0x62, 0xC3, 0x1B, 0xDB, + 0x93, 0xC0, 0xC3, 0x8E, 0xEB, 0xEF, 0x7D, 0x0C, 0x81, 0x36, 0xA4, 0x75, 0xB0, 0x3D, 0x8D, 0xE0, 0xC5, 0xAD, 0x24, 0x4E, + 0xA0, 0x3D, 0x0C, 0x61, 0x86, 0x83, 0x28, 0xA6, 0x15, 0x1E, 0x8B, 0x13, 0xF8, 0x2C, 0xFB, 0xD0, 0x82, 0x9D, 0x73, 0xF0, + 0xC6, 0x1B, 0xF7, 0x81, 0xB2, 0xFB, 0x1D, 0xC1, 0x10, 0xD1, 0xD3, 0xC6, 0x0B, 0xE9, 0x95, 0xE3, 0x25, 0x35, 0x0D, 0xE5, + 0xD7, 0xF7, 0x90, 0x37, 0xBE, 0xEA, 0x02, 0x29, 0xD1, 0x5C, 0x1A, 0x77, 0xC7, 0x12, 0x44, 0xB4, 0x54, 0x60, 0x0E, 0x82, + 0x42, 0xCF, 0x58, 0x99, 0xBC, 0x85, 0xA9, 0xEF, 0x21, 0xD7, 0x94, 0xA9, 0x16, 0xC7, 0x36, 0xE8, 0xC4, 0x51, 0x2E, 0xD6, + 0x6F, 0xCB, 0x65, 0x30, 0xC0, 0x1D, 0x9B, 0xC0, 0xD5, 0x96, 0xB4, 0x85, 0x15, 0x7B, 0x4E, 0x74, 0xC2, 0xFC, 0xCB, 0x57, + 0xE5, 0xE9, 0xB3, 0x35, 0xB3, 0x32, 0x82, 0x80, 0xA4, 0x43, 0x9D, 0xE9, 0xC5, 0xFA, 0x5E, 0xAE, 0xC5, 0x12, 0x66, 0xEF, + 0xC1, 0xFA, 0x81, 0xDF, 0x9F, 0x67, 0x12, 0xCC, 0x8F, 0x9D, 0x82, 0x05, 0x09, 0x34, 0x77, 0x80, 0x06, 0xE9, 0x56, 0xD8, + 0xD2, 0xD7, 0xC6, 0xA3, 0xBD, 0x36, 0x65, 0x74, 0x45, 0x59, 0xBC, 0xC3, 0x83, 0x9A, 0xCC, 0x2F, 0xEE, 0x92, 0x8F, 0x54, + 0xD8, 0x51, 0xFA, 0xAB, 0xA5, 0x34, 0x6F, 0xFB, 0xE1, 0xF9, 0x07, 0x55, 0x6E, 0xD6, 0x81, 0x1E, 0x96, 0xF4, 0xCA, 0x51, + 0xC5, 0xAF, 0xF4, 0x12, 0x38, 0xE7, 0x0E, 0xF8, 0x87, 0xD3, 0x1A, 0x7C, 0x63, 0xF4, 0x3F, 0x2A, 0xB1, 0x6C, 0xE6, 0xC7, + 0x5C, 0xC2, 0xD9, 0x18, 0xAF, 0x22, 0xA1, 0x39, 0xFD, 0x29, 0x5D, 0x59, 0xAE, 0x31, 0xC6, 0x4B, 0x89, 0x98, 0x6F, 0xEA, + 0xB2, 0x63, 0xF1, 0x9D, 0x5D, 0xBC, 0xAF, 0x5F, 0xDE, 0xDD, 0x78, 0x2C, 0x3B, 0x32, 0xC4, 0x2B, 0xE7, 0x00, 0x61, 0x8D, + 0x94, 0xF0, 0x04, 0x84, 0x5C, 0xEC, 0xCB, 0xE2, 0xB5, 0x4E, 0xE7, 0xA4, 0x2E, 0xD2, 0x6B, 0xA0, 0x6F, 0xFC, 0x7A, 0x11, + 0x59, 0x64, 0x20, 0x38, 0x35, 0x4D, 0x10, 0x39, 0x47, 0xA2, 0x23, 0x6E, 0x57, 0x91, 0x61, 0x1F, 0xED, 0x0F, 0xE3, 0x09, + 0x91, 0x03, 0xFD, 0xA5, 0xCA, 0xB8, 0xBE, 0x5A, 0x09, 0xFE, 0x31, 0xA3, 0xEE, 0x13, 0xB6, 0x9A, 0x6A, 0xBE, 0x06, 0xCE, + 0xF2, 0xB4, 0x08, 0x7B, 0x24, 0x3F, 0xDE, 0xB4, 0xEB, 0xE5, 0x3B, 0x60, 0xCE, 0xB5, 0x70, 0x89, 0xE3, 0x40, 0x45, 0x97, + 0xD6, 0xE9, 0xD6, 0xA4, 0xA2, 0x85, 0xE1, 0x26, 0xF4, 0x35, 0x60, 0xA0, 0x0F, 0x43, 0xE0, 0x8B, 0x30, 0xEA, 0x39, 0x71, + 0xB7, 0x44, 0xE6, 0x7C, 0x03, 0xDB, 0x53, 0xE3, 0x42, 0xDF, 0x83, 0xD6, 0x39, 0x02, 0x31, 0x3A, 0x85, 0xEE, 0x33, 0x7F, + 0xEB, 0xE8, 0xD1, 0x15, 0x60, 0x06, 0x48, 0x86, 0x57, 0xEA, 0x62, 0xBB, 0xBA, 0x83, 0x63, 0xF6, 0x23, 0x60, 0xD2, 0xA9, + 0x8F, 0x0A, 0x3F, 0x53, 0xC5, 0xFD, 0xD5, 0x18, 0x7E, 0x4B, 0x8F, 0x7B, 0x17, 0xD6, 0x43, 0x6B, 0xEC, 0xC9, 0xCA, 0x03, + 0x73, 0x2B, 0x07, 0xEB, 0x08, 0x9A, 0x3F, 0x4A, 0x96, 0xF5, 0xDD, 0x3F, 0xCB, 0x68, 0xC3, 0x16, 0xF2, 0xBF, 0x8B, 0x55, + 0x5A, 0x86, 0x27, 0x66, 0x47, 0xB6, 0xE3, 0x5F, 0x0B, 0x6B, 0x1C, 0x11, 0x24, 0x1A, 0x72, 0x3B, 0x3A, 0x03, 0xC3, 0xBA, + 0x1C, 0x55, 0x74, 0x88, 0xCE, 0xE8, 0x80, 0xDF, 0xB1, 0x08, 0x4F, 0x5A, 0xC5, 0x4C, 0xAA, 0x1C, 0xD4, 0xA6, 0xDA, 0x5C, + 0xFE, 0x0F, 0xA4, 0x7A, 0xBA, 0xEE, 0xF7, 0x3A, 0xB2, 0x01, 0x39, 0x3F, 0x71, 0x67, 0xCC, 0x6E, 0xA1, 0x41, 0x43, 0x9D, + 0x20, 0xDF, 0x2B, 0x47, 0xEE, 0x02, 0xCA, 0xBF, 0x9D, 0x94, 0x9B, 0x41, 0x6A, 0x90, 0xAD, 0x8E, 0x57, 0x2E, 0xA8, 0x12, + 0x22, 0x1A, 0x44, 0xF1, 0xF3, 0x3C, 0xEF, 0xA8, 0xC5, 0xAF, 0x5A, 0x54, 0x8F, 0xDF, 0x6C, 0x27, 0xE1, 0x0A, 0x4C, 0xE1, + 0xF0, 0x3C, 0x5D, 0xD6, 0x17, 0x52, 0x0A, 0xC6, 0x9A, 0xB0, 0x42, 0xE7, 0xE0, 0x5D, 0xBD, 0x75, 0xE8, 0x43, 0x4C, 0x83, + 0x45, 0xA3, 0x84, 0x56, 0xC8, 0xDD, 0x79, 0x15, 0xCF, 0x81, 0x9B, 0xF7, 0x4A, 0xEE, 0xA3, 0xB8, 0xD2, 0xEB, 0xC7, 0x47, + 0x99, 0xB2, 0x3C, 0xC2, 0x32, 0xE9, 0xD4, 0xCD, 0x20, 0x90, 0x41, 0xD1, 0xC3, 0xAB, 0xA2, 0x17, 0xFE, 0x35, 0x16, 0xD1, + 0x80, 0x13, 0x9A, 0x39, 0xA2, 0x6E, 0xE3, 0xC0, 0x42, 0xEA, 0xAE, 0x07, 0xFF, 0x34, 0xBD, 0x43, 0x80, 0xA6, 0xD6, 0x75, + 0x7A, 0x87, 0x6B, 0xC9, 0xCC, 0x89, 0xAB, 0xE3, 0x13, 0xF5, 0x6D, 0xBC, 0x02, 0xE8, 0xAE, 0x2C, 0xF1, 0xAC, 0xE6, 0x41, + 0x7D, 0xC8, 0xA3, 0xF3, 0x12, 0xF4, 0xB9, 0xA5, 0xD7, 0xC5, 0x52, 0x76, 0xBB, 0x35, 0xAE, 0x99, 0x3B, 0x17, 0x56, 0xD9, + 0xA0, 0x75, 0x71, 0xE2, 0x1B, 0x86, 0x2D, 0x3C, 0xE5, 0x1A, 0x47, 0xBC, 0xBC, 0x35, 0x31, 0x87, 0x1D, 0x3B, 0xD6, 0x77, + 0x51, 0x29, 0x7C, 0x09, 0x87, 0xA6, 0xBF, 0x85, 0xCC, 0xA7, 0x8F, 0x25, 0x25, 0x47, 0x6F, 0x2E, 0x69, 0x5B, 0xD5, 0x86, + 0x8D, 0x79, 0xDB, 0xE7, 0xE7, 0x45, 0x81, 0x91, 0x74, 0x86, 0x82, 0x4D, 0x24, 0x96, 0xA5, 0x31, 0xA9, 0xE7, 0xC6, 0x1B, + 0xEE, 0xD1, 0xA4, 0x1F, 0xF6, 0x3D, 0x36, 0xA7, 0x68, 0xFD, 0x26, 0xD5, 0x1F, 0x99, 0xCE, 0x10, 0xBB, 0x31, 0x61, 0xC0, + 0x84, 0xA6, 0xC3, 0x4B, 0xAF, 0x64, 0x22, 0x49, 0xE1, 0xF2, 0x05, 0x5E, 0x01, 0x3A, 0xA9, 0xEA, 0x5B, 0xA1, 0x2F, 0x79, + 0xF9, 0x10, 0xDC, 0x6D, 0x73, 0x8E, 0xE7, 0x62, 0xF9, 0x12, 0xDF, 0x83, 0xDF, 0xF2, 0x40, 0xB1, 0xB6, 0x8F, 0x43, 0xC6, + 0x50, 0x2D, 0x38, 0x2F, 0x77, 0x06, 0x4F, 0x58, 0x62, 0x3F, 0x50, 0x35, 0xA6, 0xC3, 0x50, 0x32, 0x88, 0x1C, 0xA8, 0x40, + 0x76, 0x6D, 0x47, 0xCB, 0x6E, 0x3A, 0x1B, 0x81, 0x50, 0x6B, 0xF8, 0x5E, 0x33, 0xB2, 0xEB, 0x37, 0x41, 0x93, 0x21, 0xCA, + 0x9C, 0x59, 0x28, 0x13, 0xA1, 0x58, 0x04, 0x59, 0x68, 0xFF, 0xC1, 0x17, 0xF6, 0x5B, 0x0F, 0xB3, 0xAE, 0xC8, 0x00, 0xE2, + 0x18, 0xC6, 0x61, 0xC2, 0x65, 0x91, 0xC4, 0x00, 0xB9, 0xDF, 0xAE, 0x84, 0x52, 0xE2, 0xF6, 0x8D, 0x34, 0x07, 0x9A, 0x53, + 0x1B, 0xCB, 0xC0, 0x89, 0x63, 0x1A, 0xEB, 0x14, 0xE8, 0xA8, 0xED, 0x0C, 0x79, 0xC4, 0x81, 0x18, 0x35, 0xAB, 0xF9, 0x05, + 0x35, 0xD6, 0x47, 0x1A, 0xD2, 0xA4, 0xD1, 0xAC, 0x05, 0x84, 0xC9, 0x56, 0x1A, 0xAF, 0xC6, 0x42, 0x66, 0x38, 0x1C, 0x98, + 0xC5, 0xAA, 0x94, 0xF7, 0x2D, 0xCA, 0xF8, 0x09, 0x28, 0xEA, 0x8A, 0xCA, 0x2B, 0x65, 0x88, 0xC5, 0xE5, 0x84, 0xF5, 0x7A, + 0x0B, 0xC1, 0xF0, 0x36, 0x21, 0x06, 0x91, 0xF7, 0xEC, 0xC2, 0xE0, 0x85, 0x65, 0xAB, 0xFE, 0x02, 0xFB, 0x6F, 0x3D, 0xFB, + 0x3D, 0x55, 0xBE, 0xCB, 0xEB, 0xCC, 0xD5, 0x63, 0xDF, 0x83, 0xE3, 0xF3, 0x63, 0xC6, 0x0B, 0x6D, 0xFF, 0x0C, 0x20, 0xD3, + 0xC8, 0x86, 0x25, 0xB5, 0x7C, 0xE2, 0x67, 0xA8, 0x3D, 0x2E, 0x63, 0xCA, 0x65, 0xB1, 0xC9, 0xCF, 0xB9, 0x61, 0x90, 0x6E, + 0xE9, 0x80, 0x0A, 0xFA, 0x53, 0x82, 0x6B, 0x1E, 0xA6, 0xE3, 0x44, 0x07, 0x39, 0x62, 0x6A, 0x8E, 0xC0, 0x1C, 0x33, 0x57, + 0xDE, 0xC3, 0xDD, 0x2B, 0x11, 0x28, 0x2B, 0x56, 0x25, 0x8A, 0xCC, 0xE0, 0x3F, 0xB8, 0x0B, 0xFB, 0xD7, 0x02, 0x79, 0xDB, + 0xE6, 0x81, 0xDF, 0x19, 0xEB, 0x62, 0x85, 0x79, 0x3E, 0x6C, 0x60, 0xCC, 0xA6, 0x77, 0x3A, 0x72, 0x95, 0x4F, 0x49, 0x5D, + 0x57, 0x95, 0xD2, 0x8F, 0x81, 0x56, 0xD3, 0x7A, 0x65, 0xD3, 0x0C, 0xE4, 0x57, 0x16, 0x43, 0x75, 0xBB, 0x4C, 0xAD, 0xA9, + 0x4D, 0x55, 0x07, 0x07, 0xCA, 0x99, 0xFF, 0xBE, 0x88, 0x1D, 0x8D, 0x59, 0xF4, 0x9F, 0xA4, 0x67, 0xB8, 0x26, 0x69, 0x73, + 0xA3, 0x70, 0x6D, 0xE2, 0x76, 0xBF, 0xDE, 0x73, 0xBD, 0xC8, 0x2F, 0x82, 0xBD, 0x32, 0x04, 0x86, 0x2D, 0x1F, 0xB2, 0x2B, + 0x76, 0xEF, 0x17, 0xC6, 0xDB, 0x2B, 0x8F, 0x1D, 0x49, 0xF6, 0x77, 0xB0, 0xD8, 0x19, 0x8F, 0x2B, 0x34, 0x6E, 0x43, 0xCF, + 0x98, 0x58, 0x3C, 0x76, 0x72, 0x8E, 0xE1, 0x21, 0x24, 0x92, 0x82, 0x3E, 0x66, 0x2D, 0xA1, 0x70, 0x47, 0x09, 0x2C, 0xD2, + 0x4D, 0xE9, 0xA9, 0x56, 0xA9, 0x1D, 0x8E, 0x53, 0xEC, 0x7B, 0xAE, 0xD7, 0x68, 0x7A, 0xEA, 0x1B, 0x49, 0xCC, 0x1C, 0x0E, + 0x26, 0xD5, 0x9E, 0x7E, 0x72, 0xC9, 0xD1, 0xCC, 0xDB, 0xC8, 0x88, 0x9A, 0xF1, 0x7E, 0x14, 0x72, 0xC3, 0xD6, 0xB8, 0xFC, + 0xC6, 0x64, 0xED, 0x1A, 0x80, 0x29, 0x28, 0x4C, 0x5C, 0x0B, 0x27, 0x8B, 0xAC, 0x9A, 0x67, 0xFA, 0x6D, 0xB7, 0x8F, 0x44, + 0x90, 0x87, 0xB1, 0xEF, 0x37, 0x57, 0x4F, 0x2C, 0x8A, 0x80, 0x7B, 0x65, 0x3E, 0xB6, 0x66, 0xE7, 0x48, 0x7A, 0xE5, 0x56, + 0xC5, 0xB9, 0x62, 0x48, 0x2B, 0x06, 0x4E, 0xC7, 0x1A, 0x37, 0x26, 0x79, 0x0C, 0x71, 0xF7, 0x06, 0x7E, 0xBE, 0x24, 0xDF, + 0x83, 0x92, 0xD4, 0x6E, 0xD3, 0x12, 0x40, 0xCF, 0x07, 0xD0, 0x3C, 0x8C, 0xDC, 0x98, 0x1F, 0xB4, 0x6F, 0xFC, 0xBA, 0xF2, + 0x55, 0xFA, 0xE0, 0x78, 0xC0, 0x9F, 0xAF, 0xF0, 0x7C, 0xFD, 0x7F, 0xCE, 0xEB, 0x99, 0x4B, 0xFB, 0xDC, 0x08, 0x80, 0x88, + 0x8B, 0xBC, 0x40, 0x1D, 0xDB, 0xFF, 0x59, 0x8A, 0xE5, 0xAF, 0xE6, 0x59, 0x50, 0xDF, 0x22, 0x11, 0x2E, 0xBF, 0x3B, 0x4A, + 0x85, 0x9C, 0x58, 0x21, 0xA0, 0xFE, 0xC4, 0x04, 0xE6, 0xDC, 0x66, 0xA6, 0x9D, 0xA7, 0x8E, 0x41, 0xBA, 0x88, 0x96, 0x09, + 0x65, 0xAD, 0x2D, 0x76, 0x97, 0x84, 0x2F, 0xC3, 0xAA, 0x81, 0x2C, 0x7A, 0x39, 0x93, 0x37, 0x2C, 0xAF, 0xDC, 0x25, 0x87, + 0x81, 0x29, 0x23, 0xC2, 0x0B, 0xE8, 0xA4, 0x04, 0xE0, 0xCC, 0x5A, 0x44, 0x21, 0x4C, 0x7F, 0xA6, 0xCF, 0xB9, 0xEF, 0xA7, + 0x80, 0x04, 0x10, 0x19, 0x34, 0xC9, 0xF7, 0xB6, 0x30, 0xF5, 0x91, 0xC8, 0xB6, 0xB4, 0xDC, 0x35, 0x1A, 0x05, 0xCE, 0xD5, + 0xB8, 0x46, 0xE9, 0x48, 0xB1, 0x24, 0x6E, 0xE5, 0xC6, 0xD6, 0x59, 0x74, 0xA9, 0x3E, 0x05, 0xE1, 0xBC, 0x30, 0xB1, 0x23, + 0x68, 0x4E, 0x36, 0xF5, 0xD3, 0xC7, 0xC9, 0xF5, 0xAA, 0xE2, 0x62, 0xC4, 0xF1, 0xC8, 0xBD, 0x38, 0x84, 0xF7, 0x43, 0x72, + 0x95, 0xAE, 0x70, 0x2C, 0x80, 0x8B, 0x8B, 0x28, 0x79, 0xFC, 0x53, 0x0D, 0xDC, 0x65, 0x29, 0xFE, 0xF9, 0xD6, 0x64, 0xA3, + 0x22, 0xDF, 0x36, 0x7E, 0xDA, 0xBD, 0x39, 0xB5, 0x7F, 0xF7, 0x82, 0xCD, 0xDA, 0xD7, 0xF0, 0x3A, 0xA6, 0xBC, 0x7F, 0xAD, + 0x24, 0x4A, 0xCF, 0x47, 0x87, 0x15, 0xD2, 0x8E, 0x3C, 0x94, 0x9B, 0xCA, 0x2D, 0xE4, 0x79, 0x22, 0x17, 0xC0, 0x22, 0x56, + 0xEE, 0x87, 0x69, 0x36, 0xCF, 0xB3, 0x92, 0x81, 0x95, 0x0E, 0x82, 0xE8, 0x34, 0x7A, 0x4D, 0xDC, 0x70, 0x10, 0x88, 0x26, + 0xBC, 0x2B, 0xEE, 0xFC, 0x78, 0xD2, 0x61, 0xCD, 0x2F, 0xC2, 0xC3, 0xAB, 0xAA, 0x4E, 0x6C, 0x33, 0x47, 0x35, 0x8A, 0x3D, + 0xCC, 0xC4, 0xC5, 0x50, 0x31, 0x9F, 0x8B, 0xA1, 0x33, 0xA2, 0x9B, 0x54, 0x38, 0x34, 0x9B, 0x24, 0xB9, 0x0E, 0x48, 0x6C, + 0xFD, 0x6B, 0xFE, 0x88, 0xDD, 0xDF, 0xFC, 0xB6, 0x43, 0x30, 0xA6, 0x12, 0x70, 0x95, 0x38, 0x01, 0xA5, 0x13, 0x32, 0x30, + 0x41, 0x51, 0xDA, 0x76, 0xE8, 0xCC, 0x2F, 0xB8, 0x85, 0xE4, 0xBB, 0xAA, 0xA1, 0xDA, 0xDE, 0x9E, 0xDF, 0x88, 0x93, 0xED, + 0x4F, 0xAF, 0x63, 0x8B, 0xDE, 0x97, 0x3E, 0x6F, 0x4B, 0xDD, 0x72, 0xE3, 0xCB, 0xE2, 0xA2, 0x6F, 0x48, 0x92, 0xC2, 0xB1, + 0x62, 0x5D, 0x38, 0xB1, 0x76, 0x65, 0xBB, 0x3C, 0x24, 0x56, 0x9B, 0x22, 0x34, 0x17, 0x32, 0x92, 0xC1, 0xA9, 0x14, 0x60, + 0x03, 0x8B, 0x72, 0x8C, 0xE9, 0x4D, 0x84, 0xD0, 0xB6, 0x67, 0xA3, 0x8B, 0x0B, 0x58, 0x1C, 0x70, 0x02, 0xCA, 0xCC, 0x1B, + 0x86, 0x7A, 0x2E, 0x41, 0xC1, 0x17, 0x43, 0x83, 0x8A, 0x5B, 0x8F, 0x6A, 0x9A, 0x95, 0x2D, 0x66, 0x31, 0x18, 0x5D, 0x24, + 0xC7, 0x91, 0x4B, 0x93, 0x18, 0x8C, 0x1D, 0x0C, 0xDE, 0xDA, 0x7D, 0x0C, 0x43, 0xE2, 0xBE, 0x73, 0xC9, 0x7A, 0xF6, 0x97, + 0x4C, 0x43, 0xC6, 0x32, 0x83, 0xD5, 0xA2, 0x70, 0xEB, 0xD4, 0x4A, 0x62, 0x95, 0x34, 0xA6, 0x28, 0xCE, 0xF4, 0x1C, 0x4C, + 0xA8, 0x26, 0xB8, 0xD5, 0x8B, 0x6A, 0xC8, 0x28, 0x1C, 0xD7, 0xA6, 0xCF, 0xC9, 0x4A, 0xE1, 0xFC, 0x1A, 0x71, 0x6D, 0x98, + 0xA8, 0x6B, 0x4B, 0x72, 0x2C, 0xE6, 0x94, 0x59, 0xE1, 0x14, 0x62, 0xBF, 0xB9, 0x2E, 0x60, 0x94, 0x3F, 0xC7, 0x98, 0xF1, + 0x1B, 0x97, 0x54, 0x18, 0xF5, 0xED, 0x55, 0xAB, 0x74, 0xA3, 0x48, 0xAA, 0xD0, 0x5F, 0xD6, 0xAF, 0x78, 0xBC, 0x25, 0x7C, + 0x06, 0x6A, 0x5A, 0x01, 0x73, 0x3C, 0xEC, 0x34, 0x22, 0x65, 0x97, 0xFA, 0xD1, 0x1D, 0x97, 0x9C, 0x18, 0x53, 0x68, 0x2A, + 0x2C, 0x76, 0x10, 0x38, 0x4A, 0xB0, 0x34, 0x2E, 0x95, 0xB2, 0x67, 0x3E, 0x39, 0x57, 0x68, 0x49, 0xFD, 0x45, 0x5D, 0xF1, + 0x70, 0x1B, 0x0C, 0x79, 0xCE, 0x2B, 0x86, 0xD3, 0xAC, 0xD0, 0xD6, 0x22, 0x3F, 0x66, 0xF7, 0x12, 0x72, 0x8E, 0xC9, 0x56, + 0x51, 0x5D, 0x94, 0x41, 0x7F, 0x67, 0xC6, 0xA9, 0x3E, 0x57, 0x86, 0xFA, 0xD7, 0xFD, 0x81, 0xED, 0xFD, 0xAD, 0x4F, 0x11, + 0x41, 0xD4, 0x31, 0x55, 0x3F, 0x34, 0xE9, 0x12, 0x12, 0x2E, 0x10, 0x48, 0x93, 0x7B, 0x6A, 0xC0, 0x1D, 0x6E, 0xB8, 0xC4, + 0x07, 0x4C, 0xF8, 0x85, 0xC4, 0xD4, 0xA6, 0x39, 0xB1, 0xA2, 0x10, 0xD5, 0xD4, 0xC9, 0xDC, 0x42, 0x8A, 0x47, 0xD0, 0xB2, + 0x05, 0xC8, 0xEB, 0x30, 0xE0, 0xB5, 0x1E, 0x10, 0xB0, 0x4E, 0xFD, 0x9E, 0x73, 0xA8, 0x69, 0xA1, 0xB5, 0xB4, 0xB1, 0x5A, + 0x35, 0xBD, 0x33, 0x81, 0xC0, 0x2F, 0xCF, 0xD6, 0x34, 0xC6, 0x6B, 0xB5, 0x81, 0x7D, 0x51, 0xA8, 0x91, 0x4E, 0x0E, 0x4E, + 0xC1, 0x2E, 0x87, 0xC3, 0xE4, 0xF4, 0x72, 0x3B, 0xAD, 0x77, 0x3A, 0x02, 0x9C, 0x2F, 0x63, 0xB8, 0x4C, 0x67, 0x00, 0xDD, + 0xB0, 0x43, 0xFF, 0x78, 0xF2, 0xEC, 0x3D, 0x55, 0xA0, 0x95, 0xD2, 0xB0, 0x6F, 0x1F, 0x12, 0xB4, 0xA4, 0x35, 0x1D, 0x36, + 0x8A, 0x69, 0x33, 0x10, 0xE8, 0x1E, 0x10, 0xDA, 0x50, 0xAA, 0x85, 0x23, 0x37, 0x6F, 0x13, 0xF3, 0x4F, 0x77, 0x95, 0x6A, + 0x55, 0x21, 0x44, 0x71, 0x70, 0xD7, 0x80, 0x61, 0xEE, 0x2B, 0x3C, 0xB7, 0x6A, 0x37, 0x0D, 0xCC, 0x9E, 0x17, 0x13, 0x08, + 0xC3, 0x1A, 0xD2, 0x7B, 0x6D, 0x2D, 0x7A, 0x53, 0xE8, 0x00, 0x35, 0x5A, 0x19, 0x76, 0xED, 0xFE, 0x22, 0xDB, 0x2F, 0x18, + 0xB4, 0x0E, 0x72, 0xCF, 0xE3, 0xCE, 0xDB, 0x6F, 0x77, 0xFE, 0x3B, 0x63, 0xAD, 0x79, 0x4B, 0x9C, 0xB8, 0xF5, 0x0B, 0x45, + 0xBD, 0x80, 0xED, 0xA2, 0x9B, 0xED, 0xC0, 0x99, 0xC9, 0x26, 0xA1, 0xF0, 0xB7, 0x2C, 0xCC, 0x12, 0x00, 0x1D, 0x0D, 0xB9, + 0x40, 0x4D, 0x54, 0xFC, 0x7B, 0xDD, 0x47, 0x89, 0x8A, 0x0C, 0xD6, 0xD4, 0x67, 0xD0, 0x13, 0xAF, 0xCE, 0x6C, 0x85, 0xF5, + 0xAF, 0x09, 0x17, 0x74, 0xF6, 0xB7, 0x7C, 0x11, 0x43, 0x82, 0x71, 0x14, 0x15, 0x6D, 0x2D, 0xFF, 0x05, 0x8D, 0x08, 0xF8, + 0x21, 0xAF, 0xC1, 0x13, 0x59, 0xB3, 0xFE, 0x6D, 0x4C, 0x12, 0x75, 0xE7, 0x86, 0x64, 0x0A, 0x93, 0xC6, 0xD1, 0xE9, 0x2F, + 0x6E, 0x2B, 0x9A, 0x62, 0xDF, 0xF7, 0x76, 0x0F, 0x6E, 0xD0, 0x6E, 0x99, 0x1F, 0x57, 0xAC, 0x2B, 0x0C, 0x38, 0xBD, 0xA5, + 0x4B, 0x34, 0x36, 0xF3, 0x5A, 0xDC, 0x3C, 0x3F, 0x12, 0x08, 0xBA, 0xAF, 0xD1, 0x73, 0x49, 0x54, 0xB9, 0xBC, 0xF5, 0x0E, + 0xE6, 0x0B, 0xED, 0xEB, 0x0A, 0x15, 0xE4, 0xB3, 0xCB, 0xD5, 0xEF, 0x28, 0x56, 0x14, 0x7B, 0x77, 0x8A, 0xE0, 0xE3, 0x46, + 0xD4, 0x97, 0x8A, 0xC8, 0xAF, 0x4C, 0x9E, 0x71, 0xCD, 0xFA, 0xA7, 0x2E, 0x61, 0x17, 0x0E, 0xD3, 0x5D, 0xB2, 0x7F, 0x81, + 0x17, 0x34, 0x96, 0x61, 0xB2, 0xCF, 0x87, 0xE5, 0x6B, 0x42, 0xFA, 0xC1, 0xDA, 0xE2, 0xF5, 0x94, 0xC2, 0x0E, 0xE8, 0x2A, + 0x4B, 0xDF, 0x0F, 0xCB, 0xDA, 0x26, 0x08, 0x4F, 0xEC, 0xE1, 0x7C, 0x6A, 0x0E, 0xDB, 0x14, 0x11, 0xBC, 0x7B, 0xD9, 0xFC, + 0x04, 0xD1, 0x38, 0x59, 0xD9, 0x06, 0x3F, 0xCA, 0x28, 0xD7, 0x75, 0x30, 0x55, 0xB4, 0x4D, 0x08, 0x32, 0x6C, 0x29, 0xEF, + 0x5A, 0x07, 0x56, 0x25, 0xCD, 0xDD, 0x5B, 0x7F, 0x8B, 0xBE, 0xC1, 0xA0, 0x69, 0x86, 0x46, 0x01, 0x9E, 0x22, 0x57, 0x49, + 0x40, 0x88, 0xE7, 0xDC, 0x90, 0x96, 0x9C, 0x24, 0xCA, 0x42, 0xF7, 0xCB, 0xCD, 0x9C, 0xEB, 0x9E, 0xF6, 0xBF, 0xD8, 0xE2, + 0x4F, 0x6E, 0xED, 0x79, 0x3B, 0x4E, 0x44, 0xB8, 0x21, 0xF5, 0x09, 0x20, 0x18, 0xB0, 0x97, 0x86, 0x15, 0x4A, 0x4E, 0xCF, + 0x14, 0x43, 0x83, 0xDB, 0xA1, 0xBF, 0xC8, 0x55, 0x95, 0xDC, 0xE8, 0x50, 0x3E, 0xAA, 0x5B, 0xC1, 0xFE, 0x21, 0x60, 0xC7, + 0x35, 0xCE, 0xBE, 0x11, 0x0D, 0x60, 0xB9, 0xD5, 0x4F, 0x2D, 0x68, 0xDA, 0xAB, 0x3D, 0x01, 0x57, 0xE3, 0x8A, 0xC9, 0x54, + 0x0B, 0x0B, 0x8D, 0xF7, 0x13, 0x6B, 0x47, 0xDE, 0xE3, 0x40, 0x0F, 0xDD, 0x4D, 0x2C, 0x9F, 0x20, 0xBE, 0xF5, 0xB6, 0xA2, + 0x02, 0x6B, 0xE5, 0xC0, 0x0A, 0x47, 0x7C, 0x26, 0xD1, 0xB0, 0x88, 0xA4, 0x82, 0xDE, 0x30, 0xBC, 0xD5, 0xEA, 0xC6, 0x84, + 0xB2, 0x4A, 0xBE, 0x70, 0x38, 0xE3, 0xF0, 0x7D, 0xF9, 0xE6, 0x98, 0xEF, 0x35, 0x36, 0x0B, 0x01, 0xFE, 0x04, 0x33, 0x7A, + 0x1C, 0xCD, 0xFF, 0xAC, 0xA2, 0x72, 0x90, 0xFB, 0x34, 0x3C, 0x99, 0x04, 0x63, 0x4A, 0x59, 0x2A, 0x2A, 0x9B, 0x94, 0xA8, + 0x10, 0x99, 0x99, 0x7E, 0xBB, 0x2E, 0x6B, 0xD3, 0xBC, 0x97, 0x93, 0xCA, 0xA7, 0x73, 0x40, 0xA5, 0x0F, 0x61, 0x4A, 0xF4, + 0x67, 0xD5, 0xFA, 0x07, 0x6D, 0x52, 0x36, 0xA2, 0x5A, 0xEA, 0xBC, 0x19, 0x86, 0x68, 0x0B, 0x64, 0x3B, 0x4F, 0xA4, 0xD6, + 0x4B, 0x44, 0xF0, 0x5B, 0x2F, 0x97, 0xAA, 0x67, 0x36, 0x65, 0x30, 0x42, 0x9F, 0x20, 0xF9, 0x4F, 0xE8, 0x73, 0x5B, 0x49, + 0x5B, 0x96, 0xD5, 0x66, 0x7E, 0xB7, 0x6C, 0xAA, 0x29, 0x59, 0xAB, 0x4F, 0xEB, 0x33, 0x8C, 0xF2, 0x5A, 0x98, 0xD5, 0x1E, + 0x2F, 0x96, 0x90, 0x94, 0xBC, 0xA0, 0x12, 0x71, 0x9E, 0x10, 0xE0, 0x8F, 0x89, 0xB1, 0x5B, 0xB1, 0x14, 0x4C, 0x99, 0x49, + 0x3D, 0x3E, 0xFF, 0xF6, 0x7F, 0x98, 0x34, 0x9C, 0x00, 0x1E, 0xFD, 0xA0, 0xAA, 0x74, 0x92, 0xDA, 0x7C, 0x84, 0xF0, 0x26, + 0x76, 0xB3, 0x62, 0x23, 0x06, 0x12, 0xC4, 0xC5, 0xBE, 0x9B, 0x93, 0x6C, 0xBA, 0xFD, 0x0C, 0x24, 0x65, 0x1A, 0x6C, 0xA6, + 0x64, 0x32, 0x77, 0xB4, 0xAE, 0x13, 0xD5, 0x83, 0x55, 0xB0, 0x2B, 0x34, 0x6B, 0x9F, 0xA7, 0x52, 0x61, 0xCC, 0x01, 0x63, + 0xF4, 0x3B, 0xDB, 0x67, 0xEC, 0xB7, 0xD5, 0x15, 0x03, 0x49, 0x0F, 0x6E, 0xF3, 0xD2, 0xBA, 0x90, 0x2C, 0x1F, 0xF5, 0x66, + 0x85, 0x30, 0xDD, 0x85, 0xB5, 0xDE, 0x65, 0xA8, 0x71, 0x1F, 0x7C, 0xBD, 0x01, 0xC6, 0x22, 0xB6, 0xD9, 0x92, 0xAB, 0xE0, + 0x9D, 0xAB, 0x63, 0xC0, 0xFD, 0x76, 0xB3, 0x62, 0x2E, 0xD7, 0xF7, 0x8A, 0xEE, 0x88, 0xA3, 0x0F, 0x63, 0x75, 0xB4, 0x8B, + 0x13, 0x35, 0x25, 0xF6, 0x8B, 0x1B, 0x9B, 0x57, 0xB6, 0xEA, 0xAE, 0x1E, 0xEA, 0x56, 0x62, 0xE4, 0x7F, 0x7A, 0x2D, 0xE6, + 0x8E, 0x1A, 0x62, 0xCB, 0x65, 0xC3, 0xC6, 0xDF, 0x96, 0xE2, 0xA3, 0x62, 0x12, 0xA4, 0x6E, 0x96, 0xDF, 0xEC, 0x05, 0x80, + 0x0B, 0x8A, 0x4F, 0x3E, 0x8F, 0x43, 0x06, 0x0C, 0x6C, 0xB0, 0x5E, 0x66, 0x25, 0xB2, 0x1F, 0x03, 0xD2, 0x68, 0x1F, 0x5E, + 0x5A, 0x4E, 0x3D, 0x84, 0xD8, 0xC6, 0xF8, 0x78, 0x17, 0x29, 0x3F, 0x72, 0x35, 0x97, 0x61, 0x4F, 0x6D, 0x28, 0xC7, 0xAD, + 0xF5, 0x7C, 0xF2, 0x89, 0xC2, 0x64, 0xD2, 0x9C, 0x00, 0x57, 0xE7, 0xB1, 0x4E, 0x4B, 0x87, 0x05, 0x92, 0xAA, 0xBD, 0xB7, + 0x5F, 0xE3, 0x21, 0x3F, 0xE0, 0x97, 0xCD, 0x4B, 0x1F, 0x9B, 0xA8, 0x7A, 0x11, 0xDA, 0xD1, 0x38, 0x67, 0x06, 0x65, 0x83, + 0x86, 0xC1, 0x5E, 0xF8, 0x6B, 0xFD, 0xE4, 0x0F, 0xAD, 0xD2, 0x27, 0xFE, 0xC3, 0x13, 0xA4, 0xC9, 0x6F, 0x63, 0xCC, 0x53, + 0x9F, 0x32, 0x57, 0x1C, 0x38, 0xFE, 0xAF, 0xA7, 0x4C, 0x5D, 0x6C, 0xEB, 0x67, 0xDA, 0x5F, 0xF9, 0xEB, 0xBF, 0x38, 0x0C, + 0x21, 0x6F, 0xE0, 0x47, 0x82, 0x88, 0x2D, 0x84, 0x15, 0xC3, 0xDC, 0xB0, 0x08, 0xC8, 0x70, 0xA2, 0x24, 0xED, 0xAC, 0x20, + 0x0B, 0xE3, 0xA0, 0x31, 0xF4, 0xAE, 0x20, 0xDF, 0x45, 0x9A, 0x54, 0xA5, 0x39, 0x7C, 0xE5, 0x7C, 0xEF, 0x8D, 0xFB, 0x06, + 0x37, 0xA4, 0x75, 0xDF, 0x6C, 0x39, 0xCA, 0x00, 0x75, 0x5D, 0x63, 0xAE, 0x83, 0xEB, 0x76, 0xBA, 0x93, 0x52, 0xBB, 0x41, + 0x3E, 0x81, 0xDF, 0x03, 0xD4, 0x81, 0x64, 0xBF, 0x06, 0x5F, 0xBC, 0xD0, 0xFF, 0x2E, 0x5F, 0x18, 0x9F, 0x54, 0x5F, 0x78, + 0xB2, 0x10, 0x31, 0xD4, 0x60, 0x9D, 0x24, 0x49, 0xB4, 0x20, 0xD7, 0x56, 0x4F, 0xC5, 0xA6, 0x44, 0x17, 0xA9, 0x09, 0xC7, + 0x8E, 0xD8, 0xF3, 0xB9, 0x69, 0x0B, 0x51, 0x2D, 0x1B, 0x7B, 0x47, 0x96, 0x3E, 0xE2, 0x09, 0x64, 0xA6, 0x8A, 0x16, 0xBF, + 0x05, 0x0A, 0x7D, 0x72, 0xCF, 0xE7, 0x98, 0x64, 0xBD, 0x73, 0x83, 0x4D, 0xB1, 0xCA, 0x5B, 0x8C, 0x1D, 0xCD, 0xE8, 0x35, + 0x7F, 0x0E, 0xEB, 0x21, 0xB5, 0x29, 0xEA, 0x5F, 0x93, 0x02, 0xF4, 0x33, 0x15, 0x22, 0xE5, 0x5A, 0x4B, 0xB2, 0x42, 0x24, + 0x39, 0x5D, 0xAF, 0x8D, 0x8D, 0x9A, 0xF9, 0x0E, 0x3F, 0xEB, 0xF1, 0x0F, 0xBB, 0x6C, 0x4B, 0x27, 0x35, 0x0B, 0xAB, 0xF9, + 0x0D, 0x4B, 0x54, 0xEC, 0xED, 0x04, 0x3E, 0xC7, 0x07, 0x30, 0x2D, 0xD7, 0x90, 0x16, 0x9D, 0x3A, 0x4B, 0x87, 0x9A, 0xB8, + 0x0E, 0x51, 0x8D, 0x6B, 0x4E, 0xCC, 0xD4, 0xDA, 0x86, 0x47, 0x52, 0xA4, 0xF2, 0x54, 0x5D, 0x5F, 0x92, 0xA1, 0x7E, 0x85, + 0x47, 0xAD, 0xAA, 0xE0, 0xA4, 0x16, 0x74, 0xC9, 0x62, 0xC7, 0x19, 0x6B, 0x11, 0xAC, 0x73, 0x6A, 0xC6, 0x31, 0x56, 0x7B, + 0x59, 0xF8, 0x94, 0xD9, 0x63, 0x06, 0x83, 0x41, 0x59, 0x5B, 0x84, 0x84, 0xCF, 0xCF, 0xFB, 0xBD, 0x5C, 0xA9, 0xE4, 0x73, + 0x9B, 0x32, 0xC2, 0xAA, 0x37, 0xA2, 0xCC, 0xE4, 0x3E, 0x7B, 0x30, 0x57, 0x08, 0xF0, 0x55, 0x69, 0x4E, 0xEE, 0x76, 0x75, + 0xB8, 0x4C, 0xC4, 0x96, 0xB0, 0x6C, 0x2F, 0xB6, 0x1E, 0x00, 0x7B, 0x6C, 0xF4, 0x91, 0x0A, 0xEC, 0x69, 0xF0, 0x69, 0x35, + 0xD7, 0xE0, 0xE5, 0x93, 0xB0, 0x59, 0xEC, 0x89, 0x52, 0x27, 0xCB, 0xAE, 0x40, 0x15, 0x96, 0xCC, 0xA7, 0xDA, 0x7E, 0x5B, + 0x19, 0x88, 0x3B, 0x38, 0x02, 0xA8, 0x9A, 0xF5, 0x5D, 0x31, 0x74, 0xE2, 0x66, 0x76, 0x8A, 0x7C, 0xA3, 0x69, 0x93, 0x2C, + 0xDF, 0xCD, 0xE4, 0xCC, 0xFF, 0x9D, 0x7C, 0xF2, 0x67, 0x44, 0x5F, 0xC0, 0xAB, 0x10, 0xDA, 0x88, 0xC5, 0x69, 0x65, 0x81, + 0x24, 0x12, 0x75, 0xE3, 0xE6, 0x75, 0x5E, 0xB8, 0x0F, 0x0A, 0x57, 0x29, 0x4C, 0x94, 0xCA, 0x26, 0x2B, 0xD7, 0x7D, 0xF3, + 0xEF, 0xCE, 0xA3, 0xC4, 0xF3, 0x5C, 0xD9, 0x7B, 0x93, 0xAB, 0xB5, 0x4E, 0x78, 0x6C, 0x76, 0xBA, 0x4F, 0xB0, 0xAE, 0xBD, + 0x08, 0x5B, 0xD3, 0x8A, 0x46, 0xE6, 0x3B, 0x97, 0xBD, 0xF4, 0x46, 0x38, 0x6C, 0xBC, 0xA6, 0x42, 0xE3, 0xBB, 0x77, 0x75, + 0xA0, 0x31, 0xB4, 0x90, 0xC4, 0x8E, 0x57, 0xEB, 0xC2, 0x57, 0x91, 0x92, 0x9A, 0x01, 0xEF, 0x6A, 0x12, 0x39, 0x91, 0xB2, + 0x4E, 0x16, 0x47, 0x46, 0xB9, 0xDF, 0x20, 0x47, 0x8A, 0x1E, 0x5D, 0x8D, 0xE4, 0xC4, 0x0E, 0x44, 0x1C, 0x6A, 0xDE, 0x7B, + 0xEB, 0xAE, 0xC4, 0xEA, 0xFB, 0xEA, 0x7D, 0x5E, 0x42, 0x56, 0x86, 0x58, 0xC3, 0xFC, 0xD6, 0x72, 0xEA, 0x6F, 0xA0, 0xF1, + 0x7B, 0xB3, 0x2F, 0x6B, 0xCD, 0xA5, 0x98, 0x32, 0xBE, 0xB0, 0xDF, 0x67, 0x6B, 0xEC, 0x56, 0xF5, 0x62, 0x4A, 0x57, 0xB2, + 0x8C, 0xFE, 0x03, 0x5F, 0x43, 0x9F, 0xBF, 0x4E, 0x34, 0xC4, 0x9E, 0x5F, 0x29, 0x40, 0xDF, 0x00, 0x83, 0x0E, 0xCA, 0x66, + 0x4D, 0x26, 0x18, 0x34, 0xBD, 0x2E, 0x3B, 0x7B, 0xED, 0x9C, 0x76, 0xA0, 0xBA, 0x8A, 0x27, 0xFF, 0xF8, 0xA9, 0x78, 0x74, + 0x7C, 0x4C, 0xA7, 0x6B, 0xAC, 0x0F, 0xE1, 0x3E, 0xA4, 0x8F, 0x2E, 0xEB, 0x33, 0x24, 0x73, 0xCB, 0xC1, 0x82, 0x51, 0x38, + 0xA2, 0x9E, 0x18, 0x38, 0x32, 0x4E, 0xF1, 0x97, 0x4C, 0x3C, 0x8E, 0xD3, 0xE5, 0x0F, 0xFF, 0xF5, 0xD0, 0x03, 0x78, 0xBF, + 0x61, 0xB0, 0x72, 0x5B, 0xFE, 0x8F, 0xF3, 0x56, 0x9E, 0xA1, 0xB1, 0xC4, 0x84, 0xDB, 0x70, 0xAB, 0x05, 0xBE, 0x48, 0x12, + 0x81, 0x71, 0xD8, 0x36, 0xD1, 0xE1, 0xAA, 0x7C, 0xB7, 0xC2, 0xD2, 0xC5, 0xEF, 0xCD, 0xF7, 0x41, 0xF9, 0xA3, 0x2F, 0x52, + 0xA9, 0xC3, 0xF8, 0x0A, 0x43, 0xA3, 0xD5, 0x2E, 0x68, 0x08, 0xEA, 0x5A, 0x4B, 0x8C, 0x0B, 0x6B, 0x0B, 0xE4, 0xE8, 0xC8, + 0x37, 0xF2, 0xFD, 0xFA, 0x29, 0x18, 0xBC, 0x5D, 0xBB, 0x68, 0x7C, 0x42, 0x6A, 0xA5, 0x35, 0xEC, 0x7C, 0x95, 0x1C, 0xA8, + 0xE2, 0x8A, 0x18, 0xE4, 0xF5, 0x92, 0xB6, 0xB7, 0xF6, 0xC4, 0x1A, 0x23, 0x04, 0x28, 0xC3, 0xC0, 0xED, 0xF7, 0xD8, 0xA3, + 0x79, 0x85, 0x94, 0x8F, 0x03, 0xC7, 0x3F, 0xBE, 0x85, 0x60, 0x51, 0x20, 0xB1, 0x14, 0x93, 0xF0, 0x9D, 0xD0, 0xFA, 0xD7, + 0x28, 0x7D, 0xFB, 0x79, 0x5D, 0xE6, 0x70, 0xB3, 0xFA, 0x03, 0x67, 0x48, 0x9D, 0x3A, 0x75, 0x99, 0xD6, 0x2C, 0xD3, 0x5A, + 0xA2, 0x97, 0x5D, 0xA7, 0xE2, 0x02, 0xCA, 0x9E, 0x98, 0x6B, 0x25, 0x85, 0x4B, 0x43, 0x6D, 0x58, 0xD4, 0x6F, 0xFE, 0xBA, + 0x29, 0x8B, 0x93, 0xD3, 0x61, 0xD5, 0xBB, 0xE3, 0xE8, 0x98, 0xD3, 0xAF, 0x59, 0x28, 0x18, 0xA7, 0xAF, 0x82, 0x7C, 0x79, + 0x19, 0x2B, 0x33, 0xFF, 0x37, 0x0E, 0x6C, 0x7C, 0x56, 0x63, 0x5C, 0x81, 0xD5, 0x1B, 0xE4, 0xC5, 0xBC, 0x3D, 0x54, 0xFB, + 0x42, 0xFE, 0xAE, 0x18, 0x9B, 0x14, 0xD3, 0x91, 0x05, 0xAD, 0x57, 0x96, 0x4E, 0xD9, 0xE3, 0xC2, 0xB7, 0x8E, 0xC6, 0x18, + 0x05, 0xDE, 0x81, 0x7C, 0xA0, 0x53, 0x8F, 0x84, 0x13, 0x73, 0x12, 0xD3, 0x6D, 0xA4, 0xAF, 0x22, 0x03, 0x33, 0xB2, 0xCA, + 0x58, 0x99, 0xD6, 0xA2, 0xCA, 0x3A, 0x27, 0x2A, 0x1A, 0xDE, 0x3D, 0xC7, 0x93, 0xA7, 0x51, 0x44, 0x62, 0x8B, 0x60, 0xA6, + 0x47, 0x3D, 0xB8, 0x08, 0xAC, 0x19, 0x8A, 0xD6, 0x76, 0x38, 0xF3, 0x97, 0xF9, 0x1D, 0x94, 0xB6, 0x44, 0x31, 0x54, 0xE8, + 0x9B, 0xB4, 0xFB, 0x05, 0xEF, 0x35, 0x7A, 0xA1, 0xAA, 0xA4, 0x45, 0x82, 0x96, 0xCB, 0xB2, 0x69, 0x47, 0x80, 0xB4, 0xEB, + 0x22, 0x02, 0xC8, 0xAE, 0x2C, 0x81, 0x12, 0x75, 0xC8, 0xB7, 0xEA, 0xC5, 0xE5, 0x0E, 0x35, 0x7F, 0xD1, 0xA1, 0x82, 0x79, + 0x8B, 0x1A, 0x5B, 0xEB, 0x3E, 0x03, 0x75, 0x52, 0x4C, 0x5E, 0xE8, 0xAB, 0xD9, 0x39, 0x2E, 0xFA, 0x9E, 0x7C, 0x1E, 0xD3, + 0xC4, 0x45, 0x66, 0x3A, 0xB4, 0xD6, 0x3E, 0x4F, 0xF5, 0xE4, 0x35, 0x76, 0x2A, 0x52, 0x13, 0x09, 0xA8, 0x3A, 0xB8, 0x4B, + 0x8B, 0x7A, 0xE9, 0xAB, 0x19, 0xF9, 0x37, 0x49, 0x74, 0x64, 0x26, 0xE3, 0x2C, 0x96, 0x45, 0x63, 0x4A, 0x5D, 0xE7, 0x99, + 0x2C, 0xC6, 0x0E, 0xDC, 0xAA, 0x0C, 0xBD, 0x48, 0x51, 0xC6, 0x66, 0xD7, 0x0E, 0x1E, 0xA9, 0x11, 0x7A, 0x72, 0xCD, 0x66, + 0x6B, 0xB1, 0x62, 0xF8, 0xB4, 0x7C, 0x7E, 0x32, 0x23, 0x9C, 0xBE, 0xB8, 0x74, 0x70, 0xF8, 0xB0, 0x8B, 0x9E, 0x78, 0x91, + 0x9B, 0x7E, 0x8E, 0x96, 0xA2, 0xBF, 0xBF, 0x6B, 0x06, 0x3F, 0xE0, 0xA7, 0x76, 0x5E, 0x23, 0x5D, 0x47, 0x1F, 0x7F, 0xAA, + 0xCF, 0x31, 0x95, 0x03, 0x58, 0x79, 0x98, 0xFD, 0xE7, 0x89, 0xA0, 0xFA, 0xB5, 0xE2, 0x4D, 0x50, 0xD6, 0xDF, 0xC8, 0xA4, + 0x72, 0xA8, 0x97, 0x23, 0x67, 0x2E, 0x77, 0x76, 0x6E, 0xCC, 0xC8, 0xE1, 0x43, 0xCA, 0x30, 0xCF, 0x36, 0xA1, 0x20, 0x87, + 0x9F, 0x4B, 0xA5, 0xC9, 0xE3, 0x47, 0x0A, 0x83, 0x29, 0x20, 0xC9, 0x00, 0x77, 0xE4, 0x7B, 0x1A, 0x3F, 0x23, 0x69, 0xFA, + 0x30, 0x5E, 0x17, 0xB7, 0xC7, 0x7F, 0xC1, 0xB5, 0xF3, 0x6B, 0x9B, 0xB2, 0xD6, 0x55, 0xB2, 0x24, 0x77, 0xF1, 0x4A, 0x91, + 0x22, 0x69, 0x98, 0x78, 0x90, 0x10, 0x17, 0x32, 0x7F, 0xE9, 0x37, 0x5E, 0x49, 0x2E, 0xEA, 0x35, 0x99, 0xCF, 0xA6, 0xE4, + 0x53, 0x4A, 0xA1, 0x37, 0x0D, 0x8B, 0xF9, 0x43, 0x1B, 0xE7, 0xF8, 0xF3, 0x39, 0x6B, 0x17, 0x15, 0x3D, 0x40, 0x0B, 0x43, + 0x84, 0x07, 0xB8, 0x6A, 0x7C, 0xE3, 0x2D, 0x00, 0xA3, 0x47, 0x1A, 0x84, 0x09, 0x4C, 0xCB, 0x79, 0x6E, 0x81, 0xBA, 0x9A, + 0x1A, 0x13, 0x08, 0x6D, 0xD2, 0xB7, 0x22, 0xDE, 0x2F, 0x99, 0x29, 0xE5, 0xEC, 0xEA, 0xC8, 0x1A, 0x1E, 0x29, 0x5F, 0xD1, + 0xAC, 0xDF, 0x19, 0xCD, 0xD1, 0xA8, 0x63, 0x78, 0x90, 0x2B, 0x9A, 0x7C, 0xF8, 0xC6, 0x09, 0xA5, 0x7B, 0x47, 0xCD, 0x29, + 0x3D, 0x69, 0xD0, 0x68, 0xEF, 0x72, 0xAD, 0x2B, 0x1D, 0x95, 0x42, 0x39, 0xC1, 0x89, 0x04, 0x06, 0x36, 0xAF, 0x39, 0x4A, + 0x8E, 0x0C, 0xD8, 0xFE, 0x9E, 0x03, 0x0C, 0x5F, 0xA7, 0x2D, 0x95, 0x66, 0xB5, 0x7A, 0x51, 0xDF, 0x01, 0xEF, 0xBA, 0x63, + 0xF4, 0xE9, 0x6E, 0x41, 0x23, 0x38, 0xC5, 0x21, 0x8B, 0x28, 0x5C, 0x7B, 0x7D, 0x11, 0x47, 0x2D, 0x69, 0x25, 0xDF, 0xF8, + 0xDB, 0xC4, 0x58, 0x15, 0x0B, 0x12, 0x21, 0xC6, 0x74, 0x8C, 0xD1, 0xEF, 0x1F, 0x00, 0xE9, 0xFF, 0xE4, 0x11, 0x5C, 0x48, + 0x34, 0x4A, 0x9D, 0xD3, 0x87, 0x4F, 0xEE, 0x7D, 0x47, 0xB0, 0x9B, 0x54, 0x8D, 0x18, 0x1F, 0xFC, 0x89, 0x6C, 0xA4, 0x90, + 0xD0, 0x9E, 0x40, 0x05, 0x32, 0xB9, 0x44, 0x30, 0xB8, 0xAE, 0x22, 0x42, 0xD4, 0x0E, 0x98, 0xDE, 0x5B, 0x94, 0x65, 0x9A, + 0xC6, 0x4F, 0x4D, 0x84, 0x0D, 0x3A, 0xEF, 0xA0, 0x84, 0xB0, 0x99, 0xEC, 0x06, 0x2E, 0xAF, 0x88, 0xB2, 0xB7, 0x82, 0x51, + 0x41, 0x32, 0xE7, 0xB0, 0x81, 0xB1, 0x88, 0x42, 0xDA, 0xB4, 0x48, 0x84, 0xB5, 0x60, 0x34, 0xDD, 0x6E, 0xB8, 0x7C, 0x86, + 0x97, 0xFB, 0x8E, 0xCD, 0xE9, 0x18, 0x92, 0x45, 0x5C, 0x33, 0xDB, 0x65, 0x86, 0x7A, 0x35, 0x14, 0xF5, 0xBD, 0xC9, 0x81, + 0x25, 0x42, 0x07, 0xD8, 0x78, 0x3B, 0x5D, 0x21, 0x32, 0x10, 0x41, 0x05, 0x74, 0xBE, 0x13, 0x40, 0xCC, 0x11, 0x6D, 0x24, + 0x53, 0x18, 0x1B, 0x02, 0x25, 0x97, 0x37, 0x15, 0x75, 0xBF, 0xE2, 0x0F, 0x6F, 0x6B, 0xA7, 0xF1, 0xB1, 0x1E, 0x0C, 0x0F, + 0xAD, 0xBB, 0x28, 0x5A, 0xDD, 0x47, 0x4E, 0x98, 0xE5, 0x94, 0xE2, 0xED, 0x7E, 0x06, 0xC1, 0x9C, 0x5D, 0x54, 0x01, 0xF1, + 0x1E, 0x4D, 0x47, 0xCF, 0x91, 0x95, 0xEB, 0x4F, 0xB8, 0x4E, 0xE3, 0x7B, 0x6D, 0x62, 0x77, 0x56, 0xD1, 0x86, 0xD0, 0xDC, + 0x6F, 0xAB, 0xF4, 0x9F, 0x68, 0xE6, 0xEB, 0x45, 0x2C, 0xB8, 0xAC, 0x3B, 0x90, 0x30, 0xE6, 0xD0, 0xF8, 0x28, 0x50, 0x3F, + 0xD6, 0xAC, 0x08, 0x74, 0x85, 0x2A, 0xD6, 0x8C, 0x3D, 0x07, 0x10, 0x40, 0xFA, 0xC0, 0xCD, 0xC4, 0xE7, 0x09, 0x1D, 0xA4, + 0x9E, 0x01, 0x05, 0x1C, 0xFD, 0xF5, 0x80, 0x3A, 0x74, 0x8E, 0x99, 0xFD, 0x3B, 0xA8, 0x29, 0x70, 0xFE, 0x71, 0x8F, 0xC8, + 0x5F, 0x74, 0xC4, 0x84, 0x12, 0x63, 0xB1, 0xD0, 0xAD, 0xF1, 0xD0, 0x80, 0x32, 0x0B, 0x3B, 0x9D, 0xBC, 0x08, 0x78, 0x62, + 0x43, 0xFE, 0xFE, 0x03, 0xF1, 0x46, 0x09, 0xA4, 0x17, 0xAA, 0xCE, 0x2B, 0x42, 0x2E, 0x70, 0x72, 0x42, 0xBE, 0x77, 0x66, + 0xEA, 0x9C, 0x40, 0x35, 0xE4, 0x45, 0x2F, 0x8B, 0xA5, 0xB6, 0x79, 0x63, 0xC3, 0x7D, 0x7A, 0xF5, 0x98, 0x44, 0x81, 0x5A, + 0xF3, 0x62, 0xF0, 0x85, 0x06, 0xDD, 0x71, 0x93, 0x88, 0x67, 0x25, 0x86, 0xB0, 0x29, 0x18, 0x57, 0x36, 0x2F, 0xAE, 0x8E, + 0x21, 0xF4, 0x08, 0x68, 0x61, 0x72, 0x07, 0xAC, 0x48, 0x69, 0x94, 0xE5, 0x4C, 0xCE, 0xD0, 0x94, 0x3B, 0x95, 0x37, 0xA0, + 0x9D, 0xF4, 0x17, 0x0F, 0xEE, 0x99, 0x4F, 0xF4, 0x2E, 0xD9, 0x23, 0x6B, 0xD7, 0xCA, 0xD2, 0xC5, 0x84, 0x9F, 0x54, 0xBA, + 0x94, 0xCD, 0x55, 0x9E, 0xA1, 0xA4, 0x2E, 0x1B, 0xB0, 0x01, 0x89, 0xD5, 0xF2, 0x6B, 0xF6, 0xAB, 0x26, 0x88, 0xE6, 0x93, + 0xE7, 0x29, 0x7D, 0x17, 0x5E, 0x05, 0x3A, 0xD8, 0xF5, 0x07, 0x44, 0x88, 0x33, 0xBF, 0x4B, 0x22, 0xAD, 0x9E, 0xFA, 0xEE, + 0xDE, 0x9D, 0xEA, 0x6E, 0xF2, 0xF2, 0xD6, 0xCE, 0x1F, 0x02, 0x28, 0xC6, 0xB4, 0x98, 0xBA, 0xD6, 0xA4, 0xE0, 0x93, 0x4F, + 0xA8, 0x11, 0xD9, 0x4F, 0xE0, 0x68, 0x51, 0x3A, 0xE9, 0x45, 0x03, 0xEA, 0x21, 0xE3, 0x0F, 0x9D, 0xF8, 0x56, 0xF8, 0x6E, + 0xB8, 0x9A, 0xE0, 0x16, 0x96, 0x1E, 0xBB, 0xB7, 0xD8, 0xCB, 0x25, 0x88, 0x48, 0x87, 0x62, 0xBD, 0x96, 0x2C, 0x12, 0x57, + 0x42, 0x20, 0xAD, 0x4B, 0xFB, 0xDD, 0xEC, 0xA3, 0x68, 0x7F, 0xAD, 0x1C, 0x53, 0x80, 0x5A, 0x63, 0x85, 0xE6, 0x7D, 0x7A, + 0x8F, 0x09, 0x86, 0x75, 0x8C, 0x4C, 0xFD, 0x4B, 0x65, 0x40, 0x7B, 0xAB, 0xA1, 0x88, 0xAC, 0x1F, 0xF4, 0xF1, 0xDC, 0xDD, + 0x8D, 0xEB, 0x6B, 0xA3, 0x62, 0xD0, 0x3D, 0x74, 0x2A, 0xE0, 0x6F, 0x5A, 0x7A, 0x03, 0x23, 0x76, 0xA5, 0x60, 0xB0, 0x77, + 0x1A, 0xBB, 0xD4, 0xD5, 0x0B, 0x5D, 0xA6, 0x56, 0x30, 0xEF, 0xA4, 0x94, 0xA6, 0x71, 0xD6, 0x07, 0x47, 0xC4, 0x80, 0xC2, + 0x96, 0x8C, 0xCC, 0x31, 0x33, 0xC4, 0xAD, 0x00, 0x25, 0x02, 0x9D, 0xB8, 0x5B, 0x76, 0x6B, 0x89, 0xE6, 0x8B, 0x3A, 0xDF, + 0x2D, 0x33, 0x9D, 0x31, 0x9D, 0x90, 0x2D, 0x6B, 0xDA, 0x3B, 0xB1, 0x22, 0xD1, 0x59, 0x01, 0xC7, 0x0E, 0x31, 0xE8, 0x5F, + 0x21, 0x24, 0x7B, 0x9A, 0xB1, 0x39, 0xB8, 0x60, 0x9E, 0x74, 0x14, 0x14, 0x55, 0xC5, 0xF5, 0xC1, 0x17, 0x11, 0xC4, 0xD1, + 0x4C, 0x15, 0x76, 0x20, 0xC0, 0xDD, 0xA7, 0xB3, 0xAD, 0x7F, 0x9A, 0x2F, 0xA4, 0xE4, 0x3A, 0xBB, 0x3D, 0xC0, 0xF9, 0xA3, + 0x61, 0xEB, 0x15, 0x84, 0x7B, 0x7B, 0x76, 0x53, 0x49, 0x50, 0x5D, 0x28, 0xB3, 0x76, 0x5C, 0x02, 0x29, 0xFC, 0x5F, 0xAA, + 0x02, 0x8B, 0x5F, 0xA3, 0x8D, 0x13, 0x86, 0x9F, 0x7B, 0x10, 0x02, 0x58, 0x49, 0x89, 0xCC, 0xBF, 0x5A, 0xA8, 0x0C, 0xEB, + 0x34, 0x10, 0xB9, 0x38, 0xC9, 0x1A, 0x61, 0xC5, 0x48, 0x3B, 0x9A, 0x47, 0x06, 0xBB, 0xC0, 0xFA, 0xFD, 0x11, 0x32, 0x2D, + 0x0C, 0xCB, 0xD7, 0xDC, 0x8F, 0x57, 0x81, 0xDE, 0xD5, 0xF3, 0x0D, 0xEB, 0x9A, 0x03, 0x0F, 0xE0, 0xDF, 0x55, 0x45, 0x50, + 0x91, 0x19, 0x1F, 0x4D, 0x31, 0xD6, 0x7E, 0x7A, 0x28, 0xDC, 0xA6, 0x6C, 0x64, 0x31, 0x31, 0xE0, 0xBE, 0x99, 0x7D, 0x97, + 0xAF, 0xCC, 0x16, 0xDD, 0x2D, 0xA6, 0x9E, 0x45, 0x58, 0x1D, 0xFE, 0x09, 0x8B, 0xDD, 0x71, 0xD8, 0x92, 0x87, 0x27, 0xCA, + 0xB7, 0x13, 0xCD, 0xC9, 0x19, 0x38, 0xF0, 0xDE, 0x81, 0xFB, 0xF7, 0x37, 0x27, 0xA3, 0x5E, 0xFD, 0x76, 0x62, 0xB7, 0x5F, + 0x99, 0xCD, 0xF7, 0x73, 0x7F, 0xCB, 0x73, 0x6E, 0xDA, 0x75, 0x79, 0x8A, 0xA1, 0x2B, 0xB2, 0x44, 0x12, 0x8B, 0x28, 0x4C, + 0x65, 0x22, 0x0F, 0xBD, 0xA3, 0xE4, 0x9B, 0xF0, 0x03, 0xDA, 0x38, 0x08, 0x69, 0x55, 0x42, 0x52, 0x47, 0x3D, 0x43, 0x48, + 0x76, 0x61, 0x59, 0xBE, 0x64, 0x7D, 0xCB, 0x1E, 0x14, 0xCF, 0xF1, 0xC2, 0x55, 0x5D, 0xB3, 0x60, 0x2D, 0x14, 0x43, 0x91, + 0x84, 0x64, 0xF9, 0x64, 0xD6, 0x17, 0x02, 0x6C, 0xC3, 0xE8, 0xE2, 0x3B, 0x55, 0x61, 0x8C, 0xD9, 0x05, 0xE4, 0x70, 0x59, + 0x74, 0x2F, 0x12, 0x7C, 0xA2, 0x30, 0x34, 0x9A, 0x56, 0x55, 0x48, 0x95, 0x78, 0x85, 0x4E, 0xAD, 0xEB, 0xB5, 0x26, 0x40, + 0x4F, 0x89, 0x3C, 0x09, 0x59, 0x1A, 0xBE, 0x42, 0xA2, 0x56, 0x24, 0x7A, 0x90, 0xE4, 0xC7, 0x92, 0x2E, 0xA6, 0x0E, 0x19, + 0xA4, 0x8A, 0xF9, 0xD1, 0x8E, 0x5A, 0x29, 0xAE, 0xBA, 0x5A, 0x18, 0x7D, 0x17, 0xB3, 0x69, 0x8A, 0x28, 0x6A, 0x78, 0x0B, + 0xAF, 0xCA, 0xDA, 0x3C, 0x74, 0xA5, 0x46, 0x48, 0xB7, 0x8A, 0x09, 0x5E, 0x54, 0xE1, 0xE5, 0xF2, 0x05, 0xC6, 0x51, 0x61, + 0x7D, 0xA0, 0xBF, 0x38, 0xA8, 0x88, 0xE1, 0x2A, 0xDD, 0xF9, 0xFF, 0xC1, 0x6D, 0x25, 0x5C, 0x7C, 0x3F, 0xC9, 0x6C, 0xD6, + 0xDA, 0x1A, 0x37, 0x91, 0x90, 0x6A, 0x72, 0x99, 0x6A, 0x90, 0xD5, 0xBB, 0x68, 0x28, 0x9C, 0x0E, 0xAE, 0x92, 0x00, 0xCE, + 0x7E, 0xBB, 0x5A, 0x1A, 0x06, 0xCE, 0xCA, 0x2C, 0x7D, 0xDA, 0x55, 0x9B, 0xD2, 0xDE, 0x09, 0x95, 0x6D, 0xCA, 0xFB, 0xD8, + 0xE5, 0xCA, 0xF1, 0xA1, 0xE7, 0x9D, 0x05, 0x87, 0x4F, 0xC3, 0x99, 0xBE, 0x41, 0xF6, 0x69, 0x6F, 0x6F, 0x21, 0xF5, 0xFF, + 0x98, 0xEC, 0x9B, 0xE1, 0xEC, 0x18, 0x49, 0x95, 0x27, 0x82, 0x53, 0xA4, 0x66, 0xDE, 0x2B, 0xA6, 0xB2, 0x73, 0x13, 0xFD, + 0x33, 0x8E, 0xD8, 0x09, 0xA6, 0xE6, 0xDC, 0x6A, 0x61, 0xDD, 0xE4, 0xB9, 0x3C, 0xDC, 0xAA, 0x56, 0x07, 0x2F, 0x7B, 0xE1, + 0xBE, 0x59, 0x75, 0xDA, 0x80, 0xFD, 0x0B, 0x01, 0x5E, 0x17, 0xAA, 0x36, 0x08, 0x1A, 0x7C, 0x5F, 0xB3, 0xF2, 0x0F, 0x53, + 0xF8, 0x6D, 0x8D, 0x45, 0x60, 0x74, 0x4D, 0x53, 0xD1, 0x73, 0xFD, 0xB6, 0x15, 0x0D, 0xCA, 0x53, 0xED, 0xDE, 0x2D, 0x66, + 0x77, 0xF3, 0x05, 0x23, 0x46, 0x03, 0x3E, 0xAF, 0x1C, 0x09, 0xCB, 0x99, 0x93, 0x28, 0xDC, 0x96, 0x3E, 0xBB, 0xD1, 0xF9, + 0x0D, 0xA0, 0xB7, 0x62, 0x49, 0x95, 0x32, 0xB0, 0xE6, 0xF7, 0x94, 0x54, 0x32, 0x7F, 0x9F, 0x09, 0x18, 0xD5, 0xBC, 0xE7, + 0xF7, 0xE5, 0x3F, 0xC4, 0xA0, 0x7F, 0x85, 0x67, 0xE0, 0x3B, 0x36, 0x25, 0x74, 0xD5, 0xA5, 0xEA, 0xBE, 0xF5, 0xA9, 0x56, + 0xE4, 0xB7, 0xB7, 0xD2, 0x14, 0x3A, 0x15, 0x31, 0x61, 0x22, 0xAD, 0x77, 0xBF, 0xB5, 0x30, 0x52, 0x8B, 0xD9, 0x9C, 0x7D, + 0xD8, 0x17, 0x16, 0x61, 0x48, 0x9A, 0x1A, 0x3D, 0x19, 0xF2, 0xEE, 0xEA, 0xD9, 0xDB, 0xD0, 0xAC, 0xB8, 0xAF, 0x06, 0x8A, + 0xBC, 0x76, 0xE3, 0x28, 0x59, 0x74, 0x1D, 0x63, 0x14, 0xD5, 0x11, 0x7E, 0x54, 0xEA, 0xEA, 0x1D, 0x11, 0x7B, 0xB1, 0x52, + 0xBA, 0xB8, 0x30, 0x88, 0xAB, 0x33, 0x8C, 0x85, 0x65, 0x0F, 0x9F, 0xC9, 0x8F, 0x02, 0x44, 0xC1, 0x70, 0x0D, 0x9D, 0x3A, + 0x76, 0x2D, 0x19, 0x4A, 0x45, 0x19, 0xE6, 0xA5, 0x93, 0xA0, 0xA9, 0xA4, 0xFE, 0x9C, 0x16, 0x2A, 0xF7, 0xDF, 0xD7, 0xAC, + 0x9C, 0xD8, 0xC1, 0xB4, 0xDA, 0x26, 0xA0, 0xB4, 0x79, 0x46, 0xA7, 0xBE, 0x6F, 0x43, 0x38, 0x9F, 0x3C, 0x0A, 0xB7, 0x1E, + 0x91, 0x82, 0x37, 0x16, 0x04, 0xBC, 0xF1, 0x2A, 0x0E, 0x13, 0x00, 0x25, 0x9B, 0x64, 0x7F, 0x05, 0xCD, 0x0F, 0x7E, 0xEE, + 0xA0, 0xBE, 0x3A, 0xF3, 0x64, 0xAD, 0x13, 0xEE, 0xB5, 0xDF, 0x5E, 0xF1, 0x64, 0xED, 0xA7, 0xA0, 0x36, 0x4F, 0x40, 0x95, + 0x62, 0xB6, 0x60, 0x35, 0x4F, 0xDC, 0x50, 0xAD, 0xA8, 0x11, 0xDC, 0x52, 0x51, 0x61, 0x93, 0x46, 0x4A, 0xDA, 0xCB, 0x18, + 0xB1, 0xA0, 0x12, 0xE6, 0x02, 0x62, 0x51, 0x90, 0x31, 0x20, 0x1F, 0x25, 0x87, 0xB9, 0xC3, 0x08, 0xB0, 0xA3, 0x5B, 0xCA, + 0x20, 0xBC, 0x99, 0x35, 0x30, 0x78, 0x48, 0x22, 0x26, 0xDF, 0xD6, 0x7D, 0x14, 0xCD, 0x69, 0x44, 0x29, 0x4B, 0x53, 0xE0, + 0x69, 0x6F, 0xDA, 0xA1, 0x7D, 0x14, 0x58, 0xD0, 0x7D, 0x03, 0x26, 0x76, 0xAA, 0x4A, 0xD9, 0x37, 0x4F, 0x49, 0x75, 0xBC, + 0xA3, 0x7D, 0x1B, 0x36, 0xAF, 0x29, 0xD1, 0x53, 0xA2, 0x4F, 0x39, 0xF4, 0xF6, 0x4A, 0x7E, 0x85, 0x73, 0xAD, 0x97, 0x7D, + 0x59, 0x8C, 0x0B, 0x46, 0x28, 0x23, 0x5F, 0x36, 0xDF, 0x47, 0x30, 0x6A, 0x29, 0xA8, 0x84, 0x41, 0x98, 0x38, 0xD2, 0x91, + 0x03, 0x4E, 0x64, 0xCA, 0x6B, 0xC4, 0xB5, 0x09, 0x6D, 0x0D, 0x14, 0x07, 0xF8, 0x26, 0xAE, 0x47, 0xEA, 0x27, 0x31, 0x4F, + 0x06, 0xB8, 0xB4, 0x3D, 0x8E, 0x51, 0xD9, 0xFF, 0xEC, 0x68, 0xE5, 0xAB, 0x3D, 0x45, 0x6B, 0x09, 0x0D, 0x97, 0xB1, 0xF1, + 0x11, 0xC0, 0x34, 0xFB, 0xCD, 0xFC, 0x79, 0xA9, 0x3C, 0xCD, 0x60, 0x4E, 0x86, 0x62, 0x82, 0xAD, 0x59, 0x17, 0xD7, 0x2C, + 0x61, 0x25, 0xC2, 0x0A, 0xB9, 0x29, 0x53, 0x6C, 0x53, 0x8B, 0x4B, 0x2B, 0x67, 0x42, 0xC2, 0x4F, 0x5C, 0x05, 0x61, 0x08, + 0xCB, 0xCB, 0x99, 0x79, 0x52, 0x8A, 0x23, 0x3A, 0xEE, 0x41, 0x98, 0x6E, 0x52, 0x84, 0x6B, 0xAE, 0x08, 0x5E, 0x94, 0x68, + 0xD3, 0x89, 0x12, 0x42, 0x62, 0x1E, 0x7C, 0x74, 0x6F, 0x3E, 0x7B, 0x5D, 0x4A, 0x42, 0x87, 0x7D, 0xDB, 0x2D, 0x64, 0xC4, + 0x2F, 0x1D, 0xBE, 0x35, 0x1A, 0x9F, 0x4E, 0x35, 0x1C, 0x12, 0x69, 0xD6, 0x5E, 0x2F, 0x46, 0x6B, 0x82, 0x50, 0x34, 0xB0, + 0xD0, 0x8E, 0x46, 0x89, 0x1D, 0xFE, 0x86, 0xB6, 0xC2, 0xFA, 0x4F, 0x7F, 0x03, 0x1F, 0x21, 0xFA, 0x13, 0x36, 0x8B, 0xFB, + 0x41, 0x8D, 0x2A, 0xE2, 0x6E, 0x2F, 0x6D, 0xD1, 0x8F, 0x1C, 0xD7, 0xE1, 0xC9, 0x71, 0xBD, 0xC3, 0x83, 0xF4, 0xBD, 0x3F, + 0xF0, 0x13, 0xE7, 0x33, 0xAE, 0x19, 0xBC, 0x46, 0x33, 0x63, 0xA4, 0x82, 0x23, 0x74, 0xD5, 0x24, 0x36, 0xD9, 0xDE, 0x20, + 0x16, 0xB4, 0xF4, 0x04, 0x6F, 0x3A, 0x56, 0xD2, 0xC0, 0x53, 0x4C, 0x09, 0x3B, 0x34, 0xBA, 0xE5, 0x43, 0xB9, 0xFD, 0x15, + 0x45, 0x39, 0x2D, 0x83, 0xA1, 0xA6, 0xCD, 0xD5, 0x09, 0x89, 0xDF, 0x55, 0xCE, 0xDC, 0xAD, 0x95, 0x01, 0xEA, 0x55, 0x53, + 0x16, 0x58, 0x31, 0x8A, 0x29, 0xAA, 0x66, 0xC9, 0xAC, 0x15, 0x9A, 0xD7, 0x99, 0x93, 0x68, 0xAF, 0x9D, 0x57, 0x21, 0xCC, + 0x5C, 0x85, 0x6E, 0x38, 0x77, 0x14, 0xF6, 0x74, 0x35, 0xE5, 0x66, 0xFA, 0xE5, 0x55, 0x21, 0x27, 0x86, 0x38, 0x4D, 0x72, + 0x0B, 0x5B, 0xFF, 0x98, 0x58, 0xEF, 0x87, 0xEB, 0x49, 0x56, 0x3B, 0x36, 0xF9, 0xFA, 0x45, 0x67, 0x0A, 0x1D, 0x23, 0x18, + 0x6C, 0x59, 0xBF, 0xFB, 0x6A, 0xF0, 0x40, 0xBD, 0xDD, 0xF6, 0x7E, 0x0F, 0xE8, 0x3C, 0xBE, 0xEB, 0xC7, 0x33, 0xE2, 0x97, + 0xC9, 0x1D, 0xB5, 0xAC, 0x36, 0x81, 0x8E, 0x28, 0xD9, 0xBD, 0xEE, 0x3A, 0x2B, 0xB0, 0x26, 0x7A, 0x6A, 0x9A, 0x25, 0xD8, + 0xF6, 0xC0, 0x4F, 0xD8, 0x56, 0xDF, 0x57, 0x25, 0x38, 0xB5, 0x37, 0xA9, 0x04, 0xD3, 0xB0, 0x12, 0x0F, 0xE8, 0xDD, 0xAA, + 0xCF, 0x73, 0x37, 0x35, 0x63, 0xB4, 0x67, 0x29, 0x1C, 0x50, 0x38, 0x02, 0x0A, 0xA9, 0xDF, 0x71, 0x51, 0x89, 0xA6, 0xDC, + 0x30, 0x74, 0x30, 0xE2, 0x48, 0x3B, 0xF4, 0xD6, 0x6E, 0x31, 0xEC, 0xC2, 0x7B, 0x4E, 0x7C, 0x0D, 0x77, 0xDC, 0xA8, 0xCF, + 0x45, 0x80, 0x1B, 0xC5, 0xD9, 0xEC, 0xA7, 0x70, 0xB1, 0xE0, 0xF5, 0x18, 0xB2, 0x36, 0x35, 0x07, 0xBB, 0xC2, 0xCF, 0x21, + 0x35, 0x61, 0xB9, 0x71, 0xC6, 0x5C, 0xB1, 0x9A, 0x8B, 0x0E, 0x63, 0x2A, 0xB9, 0x81, 0x46, 0x45, 0x2E, 0xA1, 0x98, 0x4A, + 0xEF, 0xB5, 0x60, 0x3B, 0x70, 0xA2, 0x58, 0x80, 0xC7, 0xA0, 0x6E, 0x83, 0xEB, 0xEB, 0x32, 0x3B, 0x73, 0xC7, 0xED, 0xA6, + 0x93, 0xAA, 0x26, 0xB0, 0x45, 0x87, 0x22, 0x86, 0x5F, 0xEA, 0x99, 0x67, 0xF1, 0xA6, 0xB1, 0xCF, 0xB4, 0xB6, 0x59, 0x65, + 0x47, 0xC8, 0xE3, 0x0B, 0xD0, 0x0F, 0x75, 0x98, 0x26, 0x38, 0x5D, 0xA7, 0x96, 0xA8, 0xB0, 0x4C, 0x44, 0xC9, 0x46, 0xF3, + 0xBA, 0xE2, 0x5A, 0x68, 0x4D, 0xC8, 0xF0, 0x23, 0xF7, 0xEC, 0xAC, 0x78, 0xED, 0x17, 0xED, 0xD3, 0x5A, 0xC3, 0x55, 0xF8, + 0xAC, 0x01, 0x0E, 0x7C, 0xE2, 0x04, 0x9A, 0x48, 0x2F, 0x6E, 0x3A, 0xC7, 0x22, 0x44, 0x5B, 0x2F, 0x2D, 0x00, 0x99, 0xBE, + 0xB2, 0x05, 0x69, 0x03, 0xB0, 0x65, 0x9A, 0xD0, 0xA7, 0xAA, 0x2F, 0xF9, 0xA9, 0x84, 0x7B, 0x32, 0x76, 0xEF, 0x45, 0x3C, + 0x38, 0xC4, 0xA3, 0xD0, 0x24, 0x9A, 0xDD, 0x0D, 0xD4, 0x84, 0xC2, 0x5B, 0x7D, 0x88, 0x1A, 0x6C, 0xCD, 0xA8, 0xC9, 0x8C, + 0xF2, 0x51, 0xD5, 0xAA, 0xE3, 0x5C, 0x92, 0xF8, 0x0F, 0xEC, 0xAA, 0xF8, 0x4E, 0xAA, 0x16, 0xEC, 0x5B, 0xE5, 0x61, 0x57, + 0x78, 0x4E, 0x9B, 0x68, 0xFD, 0xA2, 0x1B, 0x89, 0x4D, 0xC3, 0x8B, 0x4B, 0x37, 0xE7, 0x15, 0x5D, 0x6E, 0x0C, 0x8B, 0x1F, + 0x21, 0x22, 0x41, 0x99, 0x4D, 0xC7, 0xF8, 0x0C, 0xFE, 0x69, 0xAC, 0x56, 0xC5, 0x9F, 0xCD, 0x6D, 0xCB, 0x3B, 0x5C, 0x2A, + 0x62, 0x6B, 0xCA, 0x92, 0x17, 0xA9, 0x66, 0x69, 0x86, 0x97, 0x83, 0xE9, 0x96, 0x01, 0x06, 0x50, 0xE7, 0xF9, 0x66, 0xD4, + 0x8A, 0x9F, 0x45, 0x23, 0xFA, 0x9F, 0x3F, 0xBE, 0xB2, 0x9B, 0x0C, 0x21, 0xE5, 0xB5, 0xA3, 0x93, 0xF2, 0x1B, 0x7D, 0x0A, + 0x44, 0x9C, 0xDA, 0x01, 0x6E, 0xF2, 0x99, 0xD1, 0xA4, 0xF3, 0xDF, 0xB6, 0xF4, 0xC3, 0x06, 0xD3, 0x27, 0x39, 0x3B, 0x20, + 0x26, 0x3F, 0x4C, 0x32, 0x3A, 0x5C, 0x0F, 0xC2, 0x97, 0x6B, 0x97, 0x22, 0x5F, 0x44, 0xCC, 0x30, 0x04, 0x2E, 0x0E, 0x8C, + 0xC4, 0xB0, 0x5C, 0x84, 0x01, 0x5A, 0xF5, 0xFC, 0x8F, 0x1B, 0x1A, 0x21, 0x57, 0xAD, 0x7D, 0x01, 0x64, 0xDE, 0xB2, 0x98, + 0x8E, 0x59, 0xAD, 0xB2, 0x4D, 0x6A, 0x15, 0xF3, 0x84, 0x5B, 0xC2, 0x11, 0xC3, 0x23, 0x59, 0x95, 0x87, 0x68, 0x46, 0x94, + 0x49, 0x95, 0x7D, 0x1D, 0x43, 0xB1, 0x4E, 0x68, 0xEF, 0xD6, 0x09, 0x1C, 0x78, 0x58, 0xEE, 0x7B, 0xC1, 0xDB, 0x7C, 0x6C, + 0x0E, 0x4E, 0x46, 0x78, 0xCC, 0x9A, 0xD6, 0xAF, 0x19, 0x54, 0x47, 0x2B, 0xB2, 0x95, 0x67, 0xCB, 0xBB, 0xF8, 0x97, 0x69, + 0x60, 0xD4, 0x00, 0x9B, 0xFA, 0x30, 0x6B, 0xFD, 0xE7, 0x31, 0x6F, 0x2B, 0x16, 0xA0, 0x05, 0x45, 0x8E, 0x1F, 0x2D, 0xF8, + 0x3F, 0x5B, 0x1E, 0x3A, 0x09, 0x4D, 0x5E, 0xDE, 0x99, 0xFE, 0x61, 0x6E, 0x2F, 0x15, 0xC9, 0x0E, 0xD5, 0x00, 0x16, 0x2A, + 0x73, 0x6C, 0x56, 0x19, 0xFD, 0xFD, 0xBE, 0x8F, 0x08, 0x70, 0xDA, 0xB3, 0xDE, 0xF4, 0xA7, 0xAA, 0x27, 0x13, 0xB8, 0x9B, + 0x8D, 0x52, 0x2D, 0xEC, 0x86, 0x6F, 0xCC, 0xB0, 0xDA, 0xF8, 0x90, 0xC7, 0x59, 0xCF, 0xE7, 0xD7, 0xB9, 0x7E, 0xE6, 0x19, + 0x8C, 0x6B, 0x7B, 0xFB, 0x98, 0x4E, 0x3E, 0x1D, 0xE3, 0x09, 0x78, 0x86, 0x11, 0x57, 0x6F, 0xA4, 0x7B, 0x37, 0x07, 0xDB, + 0xB1, 0xE3, 0xC8, 0xE9, 0x31, 0x40, 0x39, 0x30, 0x93, 0x22, 0x60, 0xB2, 0x9C, 0x3E, 0x3C, 0x4F, 0xF2, 0x20, 0x85, 0x05, + 0xD1, 0x37, 0xF9, 0x15, 0x33, 0x6C, 0x81, 0xA3, 0x1D, 0xCD, 0x41, 0x3A, 0x54, 0xCD, 0x37, 0xD8, 0x0C, 0x85, 0x0D, 0x67, + 0x32, 0x20, 0xA6, 0xD3, 0x43, 0xBF, 0xDF, 0xFC, 0x38, 0x59, 0x9F, 0x41, 0x06, 0x9D, 0x3F, 0xBB, 0xED, 0xDB, 0xAF, 0x9F, + 0xBD, 0xBB, 0x2F, 0x9B, 0xAD, 0x9B, 0x11, 0xC6, 0xE4, 0x44, 0x37, 0xAB, 0xEC, 0xDA, 0xA7, 0x8F, 0xBC, 0xBA, 0x27, 0x8B, + 0xAC, 0x9A, 0xF8, 0x3E, 0xE2, 0xE6, 0x3E, 0xBA, 0x6D, 0xD9, 0xAE, 0x9E, 0x3D, 0xB9, 0x2E, 0x9A, 0x2D, 0x99, 0xB6, 0xAE, + 0x7C, 0xF8, 0x36, 0xAA, 0x6C, 0xD8, 0xA6, 0x8E, 0x3C, 0xB8, 0x26, 0x8A, 0x2C, 0x98, 0xC1, 0xC8, 0x50, 0xBD, 0x7D, 0xF7, + 0x9A, 0x2B, 0xEB, 0x53, 0xEB, 0x4E, 0x52, 0xD5, 0x36, 0x65, 0xCA, 0xE1, 0x67, 0xD4, 0x1A, 0x6E, 0x1F, 0xB2, 0x0C, 0x5A, + 0x21, 0x44, 0x0A, 0xBE, 0x58, 0x11, 0x4E, 0x18, 0x93, 0xB7, 0x07, 0xFD, 0x90, 0x25, 0xBC, 0xC2, 0xEC, 0xB7, 0x68, 0x0A, + 0x79, 0x95, 0x73, 0x3E, 0x74, 0x04, 0xAD, 0xED, 0x91, 0x24, 0x09, 0xF6, 0xCF, 0xC3, 0xC1, 0x38, 0x7A, 0x6D, 0xBD, 0xB7, + 0xF5, 0xF3, 0x3D, 0xB3, 0xE5, 0xD3, 0xAD, 0x97, 0xB5, 0xB3, 0x2D, 0x93, 0xA5, 0x93, 0xB5, 0xA7, 0xF4, 0xF2, 0x35, 0xA3, + 0xE4, 0xD2, 0xA5, 0x87, 0xB4, 0xB2, 0x25, 0x83, 0xA4, 0x92, 0xBC, 0xB6, 0x75, 0xF1, 0x3C, 0xB2, 0x65, 0xD1, 0xAC, 0x96, + 0x35, 0xB1, 0x2C, 0x92, 0x25, 0x91, 0xB4, 0xA6, 0x74, 0xF0, 0x34, 0xA2, 0x64, 0xD0, 0xA4, 0x86, 0x34, 0xB0, 0x24, 0x82, + 0x24, 0x90, 0xC4, 0x75, 0x23, 0x52, 0xFC, 0x34, 0x92, 0x9F, 0x44, 0x5F, 0x9B, 0x56, 0x54, 0x25, 0xD5, 0xD2, 0xB9, 0xB4, + 0xC0, 0xEE, 0xD3, 0xF4, 0x8D, 0xFB, 0x24, 0x5B, 0x45, 0xDA, 0x5C, 0x55, 0xA3, 0x33, 0x5A, 0x3A, 0xA6, 0x5B, 0x21, 0xA1, + 0xC3, 0x94, 0x1D, 0x5E, 0x41, 0x53, 0xDB, 0x74, 0xBB, 0x33, 0x57, 0x75, 0xDD, 0x51, 0x3C, 0x44, 0xCE, 0x3A, 0x19, 0x35, + 0x92, 0xF7, 0xD9, 0xD3, 0xC5, 0x26, 0xBB, 0x3F, 0xDD, 0xEB, 0x3B, 0x3B, 0xCD, 0xCB, 0xAB, 0x1F, 0x9D, 0xAB, 0x2B, 0x1B, + 0x8D, 0x8B, 0xB3, 0x2F, 0xDC, 0xEA, 0x33, 0x2B, 0xCC, 0xCA, 0xA3, 0x0F, 0x9C, 0xAA, 0x23, 0x0B, 0x8C, 0x8A, 0xBA, 0x3E, + 0x5D, 0xE9, 0x3A, 0x3A, 0x4D, 0xC9, 0xAA, 0x1E, 0x1D, 0xA9, 0x2A, 0x1A, 0x0D, 0x89, 0xB2, 0x2E, 0x5C, 0xE8, 0x32, 0x2A, + 0x4C, 0xC8, 0xA2, 0x0E, 0x1C, 0xA8, 0x22, 0x0A, 0x0C, 0x88, 0x1A, 0xCB, 0x89, 0xC7, 0x5D, 0x03, 0x3C, 0x53, 0xAB, 0x4A, + 0xEA, 0xA4, 0x27, 0x82, 0x5C, 0x03, 0xF9, 0x94, 0x82, 0x59, 0x75, 0xEF, 0x18, 0xED, 0x9E, 0x40, 0xDF, 0x5F, 0xB7, 0x40, + 0xAB, 0x39, 0xAB, 0x0C, 0x0B, 0xEA, 0x66, 0x65, 0xB0, 0x77, 0x6E, 0xDA, 0xA1, 0x55, 0xCE, 0xDF, 0x03, 0x81, 0x52, 0xD5, + 0xDE, 0x1F, 0xF7, 0xAF, 0x42, 0x79, 0x97, 0x64, 0x8A, 0x3B, 0xC0, 0x5C, 0xFF, 0x63, 0xB9, 0x37, 0xD5, 0xE3, 0x39, 0x33, + 0xC5, 0xC3, 0xA9, 0x17, 0x95, 0xA3, 0x29, 0x13, 0x85, 0x83, 0xB1, 0x27, 0xD4, 0xE2, 0x31, 0x23, 0xC4, 0xC2, 0xA1, 0x07, + 0x94, 0xA2, 0x21, 0x03, 0x84, 0x82, 0xB8, 0x36, 0x55, 0xE1, 0x38, 0x32, 0x45, 0xC1, 0xA8, 0x16, 0x15, 0xA1, 0x28, 0x12, + 0x05, 0x81, 0xB0, 0x26, 0x54, 0xE0, 0x30, 0x22, 0x44, 0xC0, 0xA0, 0x06, 0x14, 0xA0, 0x20, 0x02, 0x04, 0x80, 0xB0, 0x22, + 0x1E, 0x82, 0xC0, 0x59, 0xA7, 0xDD, 0x34, 0xA6, 0x4E, 0x85, 0xB8, 0x6A, 0xB5, 0xEF, 0x4A, 0x2A, 0x17, 0xCC, 0xC8, 0x57, + 0xEC, 0xAC, 0xCB, 0xF5, 0x47, 0x34, 0x65, 0x0E, 0x2A, 0xE1, 0xCD, 0xEB, 0x74, 0xCF, 0xD9, 0x03, 0xE7, 0xF5, 0x68, 0x7E, + 0xC0, 0xE0, 0x21, 0x7C, 0x29, 0x5E, 0x33, 0x11, 0x47, 0xA7, 0xE3, 0xE9, 0x36, 0xC6, 0x3D, 0x74, 0x44, 0xCD, 0x62, 0x93, + 0xD1, 0x58, 0x9F, 0xBD, 0xF9, 0x7B, 0x1F, 0xB9, 0xE9, 0x5B, 0x8F, 0x9D, 0xB9, 0x3B, 0x0F, 0x99, 0xA9, 0x1B, 0x97, 0xAD, + 0xF8, 0x7A, 0x17, 0xA9, 0xE8, 0x5A, 0x87, 0x8D, 0xB8, 0x3A, 0x07, 0x89, 0xA8, 0x1A, 0x9E, 0xBC, 0x79, 0x79, 0x1E, 0xB8, + 0x69, 0x59, 0x8E, 0x9C, 0x39, 0x39, 0x0E, 0x98, 0x29, 0x19, 0x96, 0xAC, 0x78, 0x78, 0x16, 0xA8, 0x68, 0x58, 0x86, 0x8C, + 0x38, 0x38, 0x06, 0x88, 0x28, 0x18, 0x2A, 0x0E, 0x83, 0xC9, 0x9A, 0xDE, 0xEB, 0xEA, 0x32, 0xDB, 0x80, 0xE8, 0xEE, 0x75, + 0xA1, 0x54, 0xBE, 0x69, 0x52, 0x82, 0xD2, 0x1A, 0xFD, 0x28, 0x8D, 0x1E, 0xCF, 0xC1, 0x61, 0x9A, 0x59, 0x52, 0x8F, 0x2F, + 0x8A, 0xF1, 0xA9, 0x2B, 0xB8, 0x01, 0x33, 0xE9, 0x4F, 0x8C, 0x6E, 0xAF, 0xA3, 0x7B, 0x28, 0xEA, 0xD2, 0x74, 0xB3, 0xEC, + 0x19, 0x06, 0x86, 0xCB, 0xC5, 0xC4, 0xE7, 0xBB, 0xF6, 0x7D, 0x9D, 0xB5, 0xF1, 0x73, 0x1D, 0xB1, 0xE1, 0x53, 0x8D, 0x95, + 0xB1, 0x33, 0x0D, 0x91, 0xA1, 0x13, 0x95, 0xA5, 0xF0, 0x72, 0x15, 0xA1, 0xE0, 0x52, 0x85, 0x85, 0xB0, 0x32, 0x05, 0x81, + 0xA0, 0x12, 0x9C, 0xB4, 0x71, 0x71, 0x1C, 0xB0, 0x61, 0x51, 0x8C, 0x94, 0x31, 0x31, 0x0C, 0x90, 0x21, 0x11, 0x94, 0xA4, + 0x70, 0x70, 0x14, 0xA0, 0x60, 0x50, 0x84, 0x84, 0x30, 0x30, 0x04, 0x80, 0x20, 0x10, 0xFB, 0xD7, 0x5F, 0xFD, 0xF9, 0x29, + 0x10, 0x4D, 0x4C, 0x26, 0x01, 0x42, 0x4B, 0x5B, 0x13, 0x2B, 0x34, 0x87, 0xA7, 0xB9, 0x13, 0x0D, 0xCA, 0xF0, 0x3E, 0x50, + 0x41, 0x93, 0xDC, 0xF6, 0xDB, 0xFC, 0xE5, 0x6E, 0x01, 0x6F, 0x49, 0x1C, 0xB5, 0x32, 0x55, 0xE7, 0x68, 0x59, 0x35, 0xA3, + 0xCB, 0x61, 0x89, 0xF1, 0xE4, 0xB3, 0x01, 0xEC, 0x6B, 0x4C, 0xE0, 0x62, 0x9A, 0xDA, 0x42, 0xC5, 0x56, 0x0E, 0x9B, 0x3D, + 0xD9, 0x6B, 0x1B, 0x39, 0xC9, 0x4B, 0x8B, 0x1D, 0x99, 0x2B, 0x0B, 0x19, 0x89, 0x0B, 0x93, 0x2D, 0xD8, 0x6A, 0x13, 0x29, + 0xC8, 0x4A, 0x83, 0x0D, 0x98, 0x2A, 0x03, 0x09, 0x88, 0x0A, 0x9A, 0x3C, 0x59, 0x69, 0x1A, 0x38, 0x49, 0x49, 0x8A, 0x1C, + 0x19, 0x29, 0x0A, 0x18, 0x09, 0x09, 0x92, 0x2C, 0x58, 0x68, 0x12, 0x28, 0x48, 0x48, 0x82, 0x0C, 0x18, 0x28, 0x02, 0x08, + 0x08, 0x08, 0x5E, 0xAE, 0x1F, 0xB8, 0x36, 0x91, 0xB8, 0x6C, 0xED, 0x89, 0x6A, 0xE0, 0xCE, 0x8A, 0xF9, 0xA9, 0x0F, 0xEC, + 0xFB, 0x1B, 0x6B, 0xE5, 0x9E, 0xDC, 0xBE, 0x56, 0x61, 0x54, 0xE7, 0xF7, 0xDA, 0xB8, 0x9F, 0x75, 0x21, 0x81, 0x03, 0xE0, + 0x9D, 0x7A, 0x88, 0x2F, 0xC1, 0x0B, 0x1B, 0x5F, 0xF8, 0x0C, 0x09, 0xFB, 0x0E, 0x1E, 0x8F, 0x68, 0x99, 0x36, 0x41, 0x66, + 0xDE, 0xFB, 0xE6, 0x39, 0x18, 0x44, 0x99, 0x35, 0xD1, 0x63, 0x19, 0x31, 0xC1, 0x43, 0x89, 0x15, 0x91, 0x23, 0x09, 0x11, + 0x81, 0x03, 0x91, 0x25, 0xD0, 0x62, 0x11, 0x21, 0xC0, 0x42, 0x81, 0x05, 0x90, 0x22, 0x01, 0x01, 0x80, 0x02, 0x98, 0x34, + 0x51, 0x61, 0x18, 0x30, 0x41, 0x41, 0x88, 0x14, 0x11, 0x21, 0x08, 0x10, 0x01, 0x01, 0x90, 0x24, 0x50, 0x60, 0x10, 0x20, + 0x40, 0x40, 0x80, 0x04, 0x10, 0x20, 0x00, 0x00, 0x97, 0x4A, 0x80, 0x05, 0x76, 0x8D, 0xDE, 0x85, 0xB1, 0x8B, 0x52, 0x92, + 0x14, 0x40, 0xCE, 0xA1, 0x58, 0xCB, 0xAC, 0x72, 0x40, 0x81, 0x90, 0xE5, 0x5B, 0x21, 0x24, 0xB2, 0x41, 0xA7, 0xC6, 0xB5, + 0xD3, 0xCA, 0x7F, 0x19, 0x02, 0x2A, 0x41, 0x05, 0xFB, 0xA0, 0x19, 0x24, 0xC4, 0x62, 0x90, 0x05, 0x50, 0x48, 0x71, 0xEC, + 0xC1, 0x41, 0xD7, 0x1D, 0xB1, 0x88, 0x47, 0xD3, 0xCD, 0xC6, 0x59, 0x35, 0xBA, 0xE1, 0x7E, 0x48, 0xC0, 0x06, 0x3F, 0xBA, + 0x14, 0xE4, 0x46, 0xF1, 0xA9, 0xE6, 0xF9, 0x23, 0x7C, 0xE8, 0xFB, 0xC0, 0x05, 0xA5, 0x08, 0x40, 0x82, 0xA8, 0x1A, 0x03, + 0x5F, 0x4C, 0xF1, 0x73, 0x52, 0xE5, 0x49, 0xC5, 0x7E, 0xA4, 0xD4, 0xC1, 0xD6, 0xBB, 0xEA, 0xD0, 0x80, 0xE9, 0x9B, 0x78, + 0x93, 0x67, 0x05, 0x23, 0xEB, 0xA5, 0x36, 0xD1, 0xD7, 0xD2, 0x2F, 0xF3, 0xCA, 0x3A, 0xA3, 0xA1, 0x53, 0x47, 0x80, 0x6A, + 0x73, 0xDA, 0x87, 0x0C, 0x9A, 0x20, 0x3C, 0x2F, 0x20, 0x47, 0x82, 0xDD, 0x12, 0x68, 0x7A, 0x5E, 0xF5, 0x4B, 0xEA, 0x5C, + 0x0C, 0x26, 0x1A, 0x7B, 0x4D, 0x49, 0x9B, 0x1C, 0xD9, 0xA8, 0xDC, 0x08, 0x8E, 0x8A, 0x0E, 0xFD, 0x90, 0x25, 0x3D, 0x2E, + 0xE7, 0x0A, 0xCD, 0xA8, 0xD0, 0xC1, 0x89, 0x63, 0x0B, 0x23, 0x0B, 0x1C, 0x30, 0x80, 0xF1, 0x3D, 0xC9, 0xE4, 0xC5, 0xBC, + 0x5B, 0xC0, 0xBD, 0x3B, 0x48, 0x8F, 0x02, 0x5D, 0x8D, 0x6E, 0x08, 0x75, 0xE9, 0x4A, 0x58, 0x9A, 0x85, 0xE1, 0x74, 0x54, + 0x6A, 0xED, 0xB5, 0xA6, 0xE4, 0xF2, 0xDA, 0x9A, 0xEA, 0xB2, 0xD8, 0x74, 0x59, 0x6C, 0x03, 0xB7, 0x0A, 0x5E, 0x41, 0xF7, + 0x7B, 0x51, 0x5F, 0x07, 0x6B, 0xC6, 0xF3, 0x60, 0xD2, 0x2E, 0x53, 0x4C, 0x77, 0xAD, 0x0B, 0x4D, 0xB1, 0xA2, 0x11, 0x78, + 0x28, 0xC5, 0xD3, 0x7F, 0x59, 0x8F, 0xBF, 0xE2, 0x61, 0x50, 0x03, 0x75, 0x3A, 0x36, 0xBA, 0x51, 0x6A, 0x5C, 0x95, 0x84, + 0x1B, 0x40, 0x74, 0xE3, 0x71, 0x18, 0xCE, 0x1E, 0x5A, 0x93, 0x62, 0x20, 0x8A, 0xF3, 0xD8, 0x36, 0x1A, 0x33, 0x7D, 0xE3, + 0xE3, 0xCD, 0xDB, 0x01, 0xB0, 0x99, 0x4B, 0x25, 0xE0, 0xDF, 0x95, 0xA7, 0xB2, 0xD9, 0x4C, 0x6C, 0xC7, 0x51, 0x8D, 0x64, + 0xA1, 0x23, 0x43, 0xB9, 0xC1, 0xFC, 0x9D, 0x44, 0xB3, 0x7D, 0x3A, 0xCD, 0xAD, 0xB9, 0x04, 0xD0, 0xC3, 0x2F, 0x6C, 0xB0, + 0x66, 0x5B, 0xEE, 0x63, 0xDE, 0x2B, 0x4D, 0x42, 0x23, 0x1D, 0xB3, 0x56, 0xB3, 0x35, 0x26, 0x20, 0x6B, 0x8A, 0xE6, 0x73, + 0xDF, 0x69, 0x40, 0x53, 0x22, 0xBB, 0x3A, 0xB7, 0x55, 0x28, 0x6D, 0x1E, 0xA1, 0x76, 0xEF, 0x62, 0x5E, 0x69, 0x09, 0x20, + 0xB7, 0x13, 0x12, 0xD5, 0xC4, 0x3D, 0xE2, 0x21, 0x14, 0x8F, 0xF3, 0xF3, 0x62, 0x2B, 0x84, 0x62, 0x57, 0x10, 0xD8, 0x85, + 0x38, 0x78, 0x13, 0x2A, 0x69, 0x20, 0xC8, 0x3D, 0x78, 0xF5, 0x70, 0x1A, 0x28, 0xFE, 0xEE, 0x6D, 0x3F, 0x39, 0x26, 0x49, + 0x6F, 0x59, 0xDE, 0x4F, 0x61, 0x7F, 0xDC, 0x8D, 0xAE, 0xBA, 0x83, 0xEE, 0xD3, 0x18, 0x37, 0x3D, 0x83, 0x78, 0xE9, 0x28, + 0x93, 0x6A, 0x55, 0x98, 0x0A, 0xB4, 0xD1, 0x0D, 0x19, 0x90, 0x41, 0x29, 0xC9, 0xF0, 0x97, 0xF0, 0x9A, 0x1B, 0x1C, 0xCA, + 0x42, 0x2C, 0xFC, 0x2E, 0x96, 0xC2, 0x2E, 0x19, 0x3A, 0x7C, 0xF8, 0xEB, 0xEF, 0x73, 0x18, 0xD0, 0xC0, 0x0D, 0xFE, 0x62, + 0x50, 0x09, 0x26, 0x8B, 0x3B, 0x56, 0xF7, 0xB2, 0xB2, 0x19, 0x39, 0xC0, 0xC9, 0xE1, 0xBC, 0x13, 0x0D, 0x95, 0x37, 0x29, + 0x24, 0xD3, 0x63, 0xA7, 0x33, 0x3A, 0x6F, 0xCD, 0x63, 0x2F, 0xCF, 0x2C, 0x33, 0xC0, 0x24, 0x99, 0xBC, 0x54, 0x76, 0x22, + 0x42, 0xA1, 0x9D, 0xF2, 0x58, 0x8F, 0xE4, 0x84, 0x7F, 0xE2, 0xB0, 0x23, 0x44, 0x80, 0x70, 0x26, 0x3F, 0x62, 0x22, 0x16, + 0xA6, 0x8C, 0xF6, 0x87, 0x15, 0x0A, 0x68, 0x36, 0x4D, 0xE9, 0xE6, 0xB3, 0x5D, 0x4A, 0x41, 0x42, 0x31, 0x8F, 0xA1, 0xF6, + 0xD6, 0xA6, 0x35, 0xBE, 0xC0, 0xE2, 0xB9, 0xD6, 0x9E, 0xE2, 0xD6, 0xC3, 0x8D, 0x0C, 0xA8, 0x97, 0x15, 0xA2, 0xB9, 0x32, + 0x82, 0x83, 0xB8, 0x17, 0x55, 0xA1, 0xD3, 0xD2, 0x00, 0x24, 0x1D, 0xBD, 0xE5, 0x5B, 0x74, 0x9C, 0xBB, 0x4E, 0xF2, 0x14, + 0x21, 0xC4, 0x32, 0x4F, 0xA4, 0x83, 0xD2, 0xB9, 0xEC, 0x3A, 0xF0, 0x4E, 0xA6, 0xCA, 0x07, 0xA6, 0x29, 0xE6, 0x2D, 0xC1, + 0x8F, 0xFB, 0x1A, 0xC3, 0x9A, 0xCB, 0x8A, 0x3F, 0x65, 0xC0, 0x15, 0x07, 0x24, 0x83, 0x65, 0x3D, 0x26, 0x0F, 0x16, 0xA9, + 0x91, 0x27, 0x19, 0x33, 0xDA, 0x4C, 0xC7, 0x7E, 0x94, 0x15, 0x68, 0x0B, 0xFB, 0x75, 0xFC, 0x8F, 0x9E, 0x03, 0x36, 0x5A, + 0x48, 0xE8, 0xEC, 0xAF, 0xDE, 0x43, 0x4A, 0x5B, 0xF0, 0x02, 0xCA, 0xEF, 0x57, 0xA9, 0xBA, 0x3B, 0x9F, 0x89, 0xA2, 0xCF, + 0x17, 0xE9, 0x69, 0xF5, 0xD9, 0x85, 0x63, 0x0F, 0xF7, 0x28, 0x6D, 0x2F, 0xC4, 0xDE, 0x73, 0x2F, 0xB7, 0x68, 0xAC, 0xF9, + 0x0F, 0xA3, 0xF5, 0x17, 0x8D, 0xAF, 0x3F, 0x99, 0xC9, 0xEB, 0xE5, 0xBA, 0xD5, 0x40, 0xE2, 0xA8, 0xAF, 0x73, 0x3A, 0x3C, + 0xE1, 0x73, 0xF6, 0x88, 0xCC, 0xC4, 0x09, 0x1C, 0xD0, 0x89, 0x6E, 0xA4, 0xF2, 0x07, 0x68, 0xDE, 0x19, 0x6D, 0x76, 0x05, + 0x2C, 0x3D, 0xB0, 0x3C, 0x37, 0xE0, 0x29, 0x4A, 0x6D, 0x04, 0x23, 0x5E, 0x95, 0xEC, 0xFA, 0x19, 0x6D, 0xC8, 0xEB, 0x6E, + 0x8A, 0x12, 0x90, 0x07, 0x2C, 0x02, 0x63, 0x7B, 0x1A, 0x5A, 0x03, 0xF9, 0xC6, 0x12, 0xE3, 0x55, 0xDE, 0xF8, 0x55, 0x44, + 0xD4, 0xDE, 0xE2, 0x86, 0xB4, 0xD3, 0x72, 0xA2, 0x0F, 0xC0, 0xCC, 0x24, 0x7D, 0x8D, 0x76, 0x93, 0x86, 0x97, 0x6C, 0x96, + 0x5E, 0x33, 0x5C, 0xF2, 0x78, 0x5C, 0xB0, 0xD8, 0xD4, 0x79, 0x92, 0x01, 0xA1, 0x63, 0xFB, 0x06, 0x36, 0x19, 0x25, 0x52, + 0xFC, 0xD2, 0xEF, 0xBA, 0x57, 0xF4, 0xA5, 0xAF, 0x06, 0x95, 0x85, 0x66, 0xFF, 0xB3, 0x45, 0x31, 0xE4, 0x8B, 0x3D, 0x55, + 0x54, 0x0C, 0xE5, 0x33, 0x3A, 0xB4, 0x64, 0xC3, 0xE0, 0xF4, 0x3F, 0x0D, 0x9D, 0x2B, 0x4A, 0xE4, 0x80, 0x20, 0x5F, 0x42, + 0xDB, 0xD7, 0x58, 0x3C, 0xD6, 0xD3, 0xBC, 0xE6, 0x44, 0x97, 0x7B, 0xED, 0x75, 0xBB, 0xD0, 0xCF, 0x5E, 0x34, 0xE5, 0xC2, + 0x57, 0xD0, 0x8E, 0x67, 0xA2, 0x58, 0xF2, 0xF8, 0xA2, 0x62, 0xDE, 0x52, 0xA1, 0x17, 0x59, 0x97, 0xBB, 0x78, 0x7B, 0x0A, + 0x98, 0x87, 0x8B, 0xB1, 0x51, 0xBB, 0x6E, 0x1D, 0x8D, 0x91, 0xF8, 0x86, 0x3E, 0xBC, 0x34, 0x48, 0x68, 0xF8, 0xFC, 0xAF, + 0x9F, 0x72, 0x16, 0x69, 0x39, 0x14, 0xF0, 0x1A, 0x3D, 0x34, 0x60, 0x3E, 0x6D, 0x72, 0x45, 0xE2, 0xDE, 0x97, 0xDE, 0x09, + 0xAF, 0x7C, 0xA8, 0x7E, 0xB6, 0xBC, 0x0B, 0x5A, 0xE6, 0xD6, 0xB3, 0x51, 0x01, 0x70, 0x51, 0x1E, 0x44, 0xCB, 0xD1, 0x0F, + 0x56, 0x19, 0x7D, 0xFB, 0x6D, 0xEB, 0x81, 0xB6, 0x3F, 0xFB, 0xBE, 0xF5, 0x3A, 0x47, 0xC6, 0xCF, 0x99, 0xAC, 0xB6, 0xFE, + 0x79, 0x9E, 0x82, 0x13, 0x40, 0xBE, 0x10, 0x5E, 0xDA, 0x3E, 0xD4, 0x59, 0x93, 0xA2, 0x7E, 0x7E, 0x2B, 0x79, 0x3E, 0xEA, + 0x83, 0x08, 0x67, 0xB4, 0xC6, 0xDC, 0x08, 0x3D, 0x3E, 0x8F, 0xF5, 0x65, 0xE8, 0xDE, 0x75, 0xD0, 0x02, 0x9C, 0x2B, 0x28, + 0xA5, 0x62, 0xA5, 0xCA, 0xDF, 0x2F, 0xBF, 0xEA, 0x3D, 0x52, 0xF8, 0x7B, 0xBB, 0x0A, 0xB7, 0x1C, 0x06, 0xC0, 0x24, 0x66, + 0x33, 0x40, 0x63, 0x66, 0xEA, 0xBB, 0x94, 0x63, 0xD2, 0x68, 0x78, 0x56, 0xA3, 0xFF, 0x68, 0x1C, 0x33, 0x31, 0xAF, 0xB5, + 0x47, 0x81, 0xBE, 0xEF, 0x05, 0xC5, 0xB6, 0xFC, 0x90, 0x4C, 0x6D, 0x07, 0x98, 0x4E, 0x91, 0xA5, 0x84, 0xB7, 0xA0, 0x47, + 0x3B, 0xD2, 0xF0, 0x57, 0x6B, 0xA7, 0x8C, 0x06, 0xDF, 0x67, 0xAE, 0x0E, 0x9D, 0x01, 0x72, 0x28, 0x19, 0x9D, 0x38, 0x22, + 0x41, 0xF4, 0x2F, 0x36, 0xB1, 0x65, 0xE3, 0x79, 0xBE, 0x94, 0xD0, 0x64, 0x52, 0x64, 0x40, 0xE2, 0xF6, 0x0A, 0xB0, 0x73, + 0x37, 0x25, 0x5C, 0x37, 0xC1, 0x4D, 0xD8, 0x74, 0x53, 0x65, 0x4B, 0x01, 0x21, 0x00, 0xC5, 0x65, 0x92, 0x26, 0xC1, 0xA6, + 0xC0, 0xB3, 0xD1, 0x65, 0xD2, 0x66, 0xFD, 0x2E, 0x20, 0x46, 0xC9, 0x55, 0x93, 0x27, 0xEB, 0x13, 0x28, 0xF7, 0xD9, 0x75, + 0xD3, 0x67, 0x42, 0x0E, 0xC0, 0xF8, 0xA4, 0x98, 0x94, 0xA3, 0x90, 0x17, 0xB4, 0x4A, 0xD2, 0xAA, 0xA4, 0x9D, 0x08, 0xDE, + 0xAB, 0x4C, 0x71, 0x3A, 0x09, 0xA4, 0x99, 0x3E, 0x81, 0xF9, 0x19, 0x06, 0x01, 0x28, 0xA7, 0xF5, 0x08, 0xF1, 0x87, 0xEF, + 0x9E, 0xEA, 0xD3, 0x3D, 0x34, 0xEE, 0xD3, 0x13, 0x84, 0xDF, 0x79, 0xBC, 0x2D, 0xEC, 0x5F, 0xE2, 0x1A, 0x25, 0xBF, 0x5B, + 0x65, 0xB4, 0x77, 0xBD, 0x25, 0x4B, 0xAA, 0xFB, 0x8F, 0x4B, 0xC2, 0x4C, 0x1A, 0x2C, 0x74, 0xB7, 0x1E, 0x0A, 0xD2, 0x6C, + 0x5A, 0x6C, 0x3E, 0xA5, 0x2A, 0x4F, 0xCA, 0x5C, 0x1B, 0x2D, 0xD9, 0x5C, 0xC4, 0x4F, 0xDA, 0x7C, 0x5B, 0x6D, 0x83, 0x5D, + 0x78, 0x42, 0xC3, 0x4D, 0x9A, 0x2E, 0xE4, 0x57, 0x92, 0xBB, 0xD3, 0x6D, 0xDA, 0x6E, 0xC9, 0x66, 0x0E, 0x08, 0xCB, 0x5D, + 0x9B, 0x2F, 0xEC, 0x78, 0x46, 0x49, 0xDB, 0x7D, 0xDB, 0x6F, 0x80, 0x04, 0x64, 0xE5, 0x0C, 0x86, 0xC5, 0x3F, 0x74, 0xE4, + 0x6F, 0x5D, 0xBC, 0x66, 0xF2, 0x78, 0xBB, 0xAF, 0x79, 0x53, 0x48, 0x11, 0x72, 0xC2, 0x94, 0xC8, 0x80, 0x5E, 0xFC, 0xF4, + 0x8A, 0x7C, 0x3F, 0x7E, 0xA6, 0xD2, 0x31, 0xFA, 0x13, 0x8F, 0x5F, 0x7E, 0x43, 0x54, 0x7A, 0x55, 0xA8, 0x7D, 0x8F, 0xAE, + 0x5D, 0xC3, 0xED, 0xD1, 0x8C, 0x3C, 0x7D, 0xF5, 0xD8, 0x5C, 0xEF, 0xAC, 0xB1, 0x88, 0x3C, 0xE4, 0xA7, 0x33, 0xC4, 0xC4, + 0x32, 0x34, 0x94, 0xF4, 0x9E, 0x18, 0xD4, 0xE4, 0x72, 0x74, 0xFB, 0x2D, 0x33, 0x5B, 0xCC, 0xD4, 0x33, 0x35, 0xF4, 0x53, + 0x1C, 0xD5, 0xDC, 0xF4, 0x73, 0x75, 0x9A, 0xD0, 0xA4, 0xD6, 0xC5, 0xC5, 0xB2, 0x36, 0x25, 0x27, 0x48, 0x17, 0xD5, 0xE5, + 0xF2, 0x76, 0x3D, 0xF7, 0x41, 0x74, 0xCD, 0xD5, 0xB3, 0x37, 0x9D, 0xE5, 0x1F, 0x1B, 0xDD, 0xF5, 0xF3, 0x77, 0xC6, 0x9C, + 0xD4, 0xBC, 0x16, 0x92, 0x60, 0xCC, 0xA2, 0x4A, 0xEA, 0x10, 0x92, 0xAE, 0x7C, 0x83, 0xAA, 0x65, 0xA9, 0xC2, 0x7E, 0x18, + 0x7D, 0xAE, 0x66, 0xDA, 0x2A, 0xE6, 0x29, 0x98, 0xFC, 0x5E, 0x47, 0x8F, 0x60, 0xEA, 0x04, 0x4B, 0x52, 0x76, 0xDB, 0xCB, + 0xAB, 0x85, 0x97, 0x6F, 0x7B, 0x3C, 0x0E, 0x5F, 0x0B, 0x5E, 0x27, 0x3E, 0xC6, 0x3A, 0x67, 0xE6, 0x1C, 0xA7, 0x40, 0xAC, + 0xFF, 0xBB, 0xEE, 0x6A, 0xF5, 0xF3, 0xC6, 0xCC, 0x3A, 0x3C, 0x26, 0x2E, 0xC0, 0x1D, 0xD6, 0xEC, 0x7A, 0x7C, 0xB1, 0xFC, + 0xA9, 0x15, 0xCE, 0xDC, 0x3B, 0x3D, 0xF2, 0xBA, 0xE8, 0x53, 0xDE, 0xFC, 0x7B, 0x7D, 0xEF, 0x6B, 0x2D, 0x39, 0xC7, 0xCD, + 0xBA, 0x3E, 0xBB, 0x69, 0x16, 0x7E, 0xD7, 0xED, 0xFA, 0x7E, 0xF9, 0xBB, 0x5C, 0x19, 0xCF, 0xDD, 0xBB, 0x3F, 0x37, 0x7F, + 0x17, 0x1E, 0xDF, 0xFD, 0xFB, 0x7F, 0xF4, 0x44, 0xA6, 0x7E, 0x40, 0x39, 0x30, 0x1C, 0xF0, 0x36, 0xB8, 0xBE, 0x1C, 0xA4, + 0x55, 0x65, 0xC3, 0x69, 0x9A, 0xBC, 0x2C, 0xE7, 0xB6, 0xA3, 0x4C, 0xB6, 0x0D, 0x9F, 0xD7, 0x2A, 0x9D, 0x3F, 0x5B, 0x87, + 0xC8, 0x92, 0x1E, 0x5C, 0x6D, 0x28, 0x48, 0x65, 0x66, 0x8C, 0x89, 0xD4, 0x8C, 0x46, 0x81, 0xB1, 0x02, 0xA4, 0x9B, 0xE8, + 0x17, 0xEB, 0xF9, 0x27, 0x54, 0x82, 0x3E, 0x24, 0x0A, 0xE1, 0x88, 0xE1, 0x00, 0x24, 0xE0, 0x46, 0x16, 0xA4, 0x78, 0x50, + 0xE7, 0x6B, 0xF0, 0x66, 0x56, 0xE4, 0xF8, 0xD0, 0x06, 0xF2, 0xE8, 0x56, 0x17, 0xA5, 0x98, 0x4D, 0xB3, 0x75, 0xF8, 0x76, + 0x57, 0xE5, 0x88, 0xC7, 0xC2, 0x9A, 0xE1, 0x47, 0x96, 0xA6, 0x76, 0x70, 0x1D, 0x16, 0xF1, 0x67, 0xD6, 0xE6, 0x53, 0xB1, + 0x05, 0x8F, 0xE9, 0x57, 0x97, 0xA7, 0xCE, 0x6F, 0xE3, 0x3A, 0xF9, 0x77, 0xD7, 0xE7, 0xB2, 0x14, 0x54, 0x7C, 0x82, 0x6C, + 0xAB, 0xCD, 0x99, 0x51, 0x99, 0x35, 0x52, 0x11, 0xA0, 0xEA, 0x6A, 0xDC, 0xE7, 0xC5, 0x13, 0x4F, 0xBE, 0x76, 0x62, 0x07, + 0xCF, 0xC1, 0x89, 0x27, 0x79, 0x87, 0xA0, 0x11, 0xD0, 0x3E, 0x9B, 0xDF, 0x41, 0xD5, 0x71, 0x4B, 0xD4, 0x4A, 0x00, 0x32, + 0x24, 0x3A, 0xDB, 0x5D, 0x27, 0x70, 0x16, 0x42, 0x62, 0xAD, 0xEF, 0x49, 0x6E, 0x8A, 0xFB, 0x00, 0xD5, 0x87, 0x93, 0x28, + 0x4D, 0x53, 0xE2, 0x4E, 0x1E, 0xAC, 0xAD, 0x62, 0x60, 0x8A, 0xF2, 0x6E, 0x5E, 0xEC, 0x12, 0xD8, 0x0E, 0x9A, 0xEA, 0x5E, + 0x1F, 0xAD, 0x0A, 0xA5, 0xA0, 0x8C, 0xFA, 0x7E, 0x5F, 0xED, 0x1B, 0x29, 0xCD, 0x7E, 0xE3, 0x4F, 0x9E, 0xAE, 0x81, 0xAD, + 0x6C, 0x82, 0xF3, 0x6F, 0xDE, 0xEE, 0xD0, 0xB9, 0x23, 0x72, 0xEB, 0x5F, 0x9F, 0xAF, 0xD3, 0xD8, 0xB0, 0x0F, 0xFB, 0x7F, + 0xDF, 0xEF, 0x56, 0x27, 0xA1, 0x97, 0x64, 0x92, 0xC8, 0x45, 0xF4, 0xB3, 0x48, 0xD6, 0x03, 0x5B, 0x38, 0xBE, 0x2D, 0x4D, + 0x86, 0xEF, 0x1B, 0x8F, 0x33, 0x71, 0x44, 0x96, 0xEA, 0xD3, 0x45, 0x70, 0xD7, 0xB4, 0xCE, 0x74, 0xA2, 0x72, 0x61, 0x03, + 0xF0, 0x47, 0x3D, 0x06, 0x87, 0xF2, 0xC5, 0xE1, 0x56, 0x0C, 0x16, 0xD5, 0x07, 0xDD, 0x1A, 0xA8, 0xE1, 0xF1, 0x8A, 0xB2, + 0x68, 0xDF, 0xCF, 0x31, 0xED, 0xBF, 0x6C, 0xF5, 0x87, 0xF8, 0xE4, 0xC6, 0x36, 0xB4, 0x14, 0xA2, 0x6A, 0x29, 0xF4, 0xE6, + 0x76, 0xF4, 0xE8, 0x15, 0xA7, 0xB5, 0xEC, 0xD6, 0x37, 0xB5, 0x26, 0xF3, 0xC4, 0x94, 0xFC, 0xF6, 0x77, 0xF5, 0x86, 0x84, + 0x78, 0x9E, 0xE5, 0xC7, 0xB6, 0xB6, 0x0D, 0x61, 0xE7, 0x96, 0xF5, 0xE7, 0xF6, 0xF6, 0xC1, 0x13, 0x04, 0xD6, 0xED, 0xD7, + 0xB7, 0xB7, 0x1D, 0xB3, 0xFA, 0x5C, 0xFD, 0xF7, 0xF7, 0xF7, 0x52, 0xAE, 0xF8, 0x28, 0x24, 0xB1, 0xB9, 0xBF, 0x5E, 0xB4, + 0x2A, 0x2C, 0xC6, 0x8E, 0x64, 0x35, 0x09, 0x1A, 0xAA, 0x3E, 0x47, 0x1A, 0x79, 0xA5, 0x81, 0xDA, 0xDA, 0x7D, 0x84, 0x5C, + 0xFF, 0xF1, 0x80, 0x97, 0x7C, 0x6A, 0x4F, 0x2C, 0xBA, 0x1A, 0xF1, 0x2F, 0xA4, 0xAD, 0x27, 0x2D, 0xFD, 0x1D, 0x87, 0x3D, + 0xAB, 0x5B, 0x3F, 0x58, 0xBF, 0x4E, 0xF9, 0xBD, 0x25, 0x19, 0x4D, 0xDD, 0xBE, 0x24, 0x8A, 0x4A, 0xD2, 0xBC, 0xE6, 0xCE, + 0x3E, 0xBC, 0xF2, 0x08, 0xEC, 0xD4, 0xF6, 0xEE, 0x7E, 0xFC, 0x56, 0x29, 0x77, 0x39, 0xEE, 0xDE, 0x3F, 0xBD, 0x1E, 0xBA, + 0xC2, 0x20, 0xFE, 0xFE, 0x7F, 0xFD, 0xCB, 0x49, 0xAF, 0xCB, 0xE7, 0xCF, 0xBE, 0xBE, 0xFE, 0x99, 0x4D, 0x9F, 0xF7, 0xEF, + 0xFE, 0xFE, 0x80, 0xC7, 0x29, 0x6A, 0xEF, 0xDF, 0xBF, 0xBF, 0x07, 0xDF, 0x6D, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x04, 0x10, 0x20, 0x10, 0x20, 0x40, 0x40, 0x90, 0x24, 0x50, 0x60, 0x08, 0x10, 0x01, 0x01, 0x88, 0x14, + 0x11, 0x21, 0x18, 0x30, 0x41, 0x41, 0x98, 0x34, 0x51, 0x61, 0x01, 0x01, 0x80, 0x02, 0x81, 0x05, 0x90, 0x22, 0x11, 0x21, + 0xC0, 0x42, 0x91, 0x25, 0xD0, 0x62, 0x09, 0x11, 0x81, 0x03, 0x89, 0x15, 0x91, 0x23, 0x19, 0x31, 0xC1, 0x43, 0x99, 0x35, + 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, 0x52, 0x64, 0x48, 0x50, + 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, 0x82, 0x06, 0xC1, 0x45, + 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, 0x93, 0x27, 0x59, 0x71, + 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0x02, 0x08, 0x08, 0x08, 0x82, 0x0C, 0x18, 0x28, 0x12, 0x28, 0x48, 0x48, 0x92, 0x2C, + 0x58, 0x68, 0x0A, 0x18, 0x09, 0x09, 0x8A, 0x1C, 0x19, 0x29, 0x1A, 0x38, 0x49, 0x49, 0x9A, 0x3C, 0x59, 0x69, 0x03, 0x09, + 0x88, 0x0A, 0x83, 0x0D, 0x98, 0x2A, 0x13, 0x29, 0xC8, 0x4A, 0x93, 0x2D, 0xD8, 0x6A, 0x0B, 0x19, 0x89, 0x0B, 0x8B, 0x1D, + 0x99, 0x2B, 0x1B, 0x39, 0xC9, 0x4B, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, 0x1A, 0x2C, 0x52, 0x68, + 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, 0x4B, 0x4D, 0xDA, 0x7C, + 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, 0xDA, 0x6E, 0x4B, 0x59, + 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, 0x20, 0x10, 0x84, 0x84, + 0x30, 0x30, 0x14, 0xA0, 0x60, 0x50, 0x94, 0xA4, 0x70, 0x70, 0x0C, 0x90, 0x21, 0x11, 0x8C, 0x94, 0x31, 0x31, 0x1C, 0xB0, + 0x61, 0x51, 0x9C, 0xB4, 0x71, 0x71, 0x05, 0x81, 0xA0, 0x12, 0x85, 0x85, 0xB0, 0x32, 0x15, 0xA1, 0xE0, 0x52, 0x95, 0xA5, + 0xF0, 0x72, 0x0D, 0x91, 0xA1, 0x13, 0x8D, 0x95, 0xB1, 0x33, 0x1D, 0xB1, 0xE1, 0x53, 0x9D, 0xB5, 0xF1, 0x73, 0x44, 0xC0, + 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, 0x23, 0x15, 0xCC, 0xD4, + 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, 0xB2, 0x36, 0x55, 0xE1, + 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, 0xE3, 0x57, 0xDD, 0xF5, + 0xF3, 0x77, 0x06, 0x88, 0x28, 0x18, 0x86, 0x8C, 0x38, 0x38, 0x16, 0xA8, 0x68, 0x58, 0x96, 0xAC, 0x78, 0x78, 0x0E, 0x98, + 0x29, 0x19, 0x8E, 0x9C, 0x39, 0x39, 0x1E, 0xB8, 0x69, 0x59, 0x9E, 0xBC, 0x79, 0x79, 0x07, 0x89, 0xA8, 0x1A, 0x87, 0x8D, + 0xB8, 0x3A, 0x17, 0xA9, 0xE8, 0x5A, 0x97, 0xAD, 0xF8, 0x7A, 0x0F, 0x99, 0xA9, 0x1B, 0x8F, 0x9D, 0xB9, 0x3B, 0x1F, 0xB9, + 0xE9, 0x5B, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, 0x6A, 0x5C, 0xD6, 0xEC, + 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, 0x7B, 0x7D, 0x47, 0xC9, + 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, 0xAB, 0x1F, 0xCF, 0xDD, + 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x20, 0x02, 0x04, 0x80, 0xA0, 0x06, 0x14, 0xA0, 0x30, 0x22, + 0x44, 0xC0, 0xB0, 0x26, 0x54, 0xE0, 0x28, 0x12, 0x05, 0x81, 0xA8, 0x16, 0x15, 0xA1, 0x38, 0x32, 0x45, 0xC1, 0xB8, 0x36, + 0x55, 0xE1, 0x21, 0x03, 0x84, 0x82, 0xA1, 0x07, 0x94, 0xA2, 0x31, 0x23, 0xC4, 0xC2, 0xB1, 0x27, 0xD4, 0xE2, 0x29, 0x13, + 0x85, 0x83, 0xA9, 0x17, 0x95, 0xA3, 0x39, 0x33, 0xC5, 0xC3, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, 0x06, 0x84, 0xE0, 0x46, + 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, 0x17, 0xA5, 0x78, 0x72, + 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, 0xC6, 0xC6, 0xF1, 0x67, + 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, 0xD7, 0xE7, 0x22, 0x0A, + 0x0C, 0x88, 0xA2, 0x0E, 0x1C, 0xA8, 0x32, 0x2A, 0x4C, 0xC8, 0xB2, 0x2E, 0x5C, 0xE8, 0x2A, 0x1A, 0x0D, 0x89, 0xAA, 0x1E, + 0x1D, 0xA9, 0x3A, 0x3A, 0x4D, 0xC9, 0xBA, 0x3E, 0x5D, 0xE9, 0x23, 0x0B, 0x8C, 0x8A, 0xA3, 0x0F, 0x9C, 0xAA, 0x33, 0x2B, + 0xCC, 0xCA, 0xB3, 0x2F, 0xDC, 0xEA, 0x2B, 0x1B, 0x8D, 0x8B, 0xAB, 0x1F, 0x9D, 0xAB, 0x3B, 0x3B, 0xCD, 0xCB, 0xBB, 0x3F, + 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, 0x5E, 0xEC, 0x6A, 0x5A, + 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, 0x8E, 0x8E, 0xE3, 0x4F, + 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, 0x9F, 0xAF, 0x7B, 0x7B, + 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x24, 0x82, 0x24, 0x90, 0xA4, 0x86, 0x34, 0xB0, 0x34, 0xA2, 0x64, 0xD0, 0xB4, 0xA6, + 0x74, 0xF0, 0x2C, 0x92, 0x25, 0x91, 0xAC, 0x96, 0x35, 0xB1, 0x3C, 0xB2, 0x65, 0xD1, 0xBC, 0xB6, 0x75, 0xF1, 0x25, 0x83, + 0xA4, 0x92, 0xA5, 0x87, 0xB4, 0xB2, 0x35, 0xA3, 0xE4, 0xD2, 0xB5, 0xA7, 0xF4, 0xF2, 0x2D, 0x93, 0xA5, 0x93, 0xAD, 0x97, + 0xB5, 0xB3, 0x3D, 0xB3, 0xE5, 0xD3, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, 0x36, 0xB4, 0x74, 0xE2, + 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, 0x67, 0xD5, 0xFC, 0xF6, + 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, 0xF6, 0xF6, 0x6D, 0xD3, + 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x8A, 0x2C, 0x98, 0xA6, 0x8E, + 0x3C, 0xB8, 0x36, 0xAA, 0x6C, 0xD8, 0xB6, 0xAE, 0x7C, 0xF8, 0x2E, 0x9A, 0x2D, 0x99, 0xAE, 0x9E, 0x3D, 0xB9, 0x3E, 0xBA, + 0x6D, 0xD9, 0xBE, 0xBE, 0x7D, 0xF9, 0x27, 0x8B, 0xAC, 0x9A, 0xA7, 0x8F, 0xBC, 0xBA, 0x37, 0xAB, 0xEC, 0xDA, 0xB7, 0xAF, + 0xFC, 0xFA, 0x2F, 0x9B, 0xAD, 0x9B, 0xAF, 0x9F, 0xBD, 0xBB, 0x3F, 0xBB, 0xED, 0xDB, 0xBF, 0xBF, 0xFD, 0xFB, 0x66, 0xCA, + 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, 0x2F, 0x9D, 0xEE, 0xDE, + 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, 0xBE, 0xBE, 0x77, 0xEB, + 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, 0xEF, 0xDF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x10, 0x20, 0x10, 0x20, 0x40, 0x40, 0x90, 0x24, 0x50, 0x60, 0x08, 0x10, + 0x01, 0x01, 0x88, 0x14, 0x11, 0x21, 0x18, 0x30, 0x41, 0x41, 0x98, 0x34, 0x51, 0x61, 0x01, 0x01, 0x80, 0x02, 0x81, 0x05, + 0x90, 0x22, 0x11, 0x21, 0xC0, 0x42, 0x91, 0x25, 0xD0, 0x62, 0x09, 0x11, 0x81, 0x03, 0x89, 0x15, 0x91, 0x23, 0x19, 0x31, + 0xC1, 0x43, 0x99, 0x35, 0xD1, 0x63, 0x40, 0x40, 0x02, 0x04, 0xC0, 0x44, 0x12, 0x24, 0x50, 0x60, 0x42, 0x44, 0xD0, 0x64, + 0x52, 0x64, 0x48, 0x50, 0x03, 0x05, 0xC8, 0x54, 0x13, 0x25, 0x58, 0x70, 0x43, 0x45, 0xD8, 0x74, 0x53, 0x65, 0x41, 0x41, + 0x82, 0x06, 0xC1, 0x45, 0x92, 0x26, 0x51, 0x61, 0xC2, 0x46, 0xD1, 0x65, 0xD2, 0x66, 0x49, 0x51, 0x83, 0x07, 0xC9, 0x55, + 0x93, 0x27, 0x59, 0x71, 0xC3, 0x47, 0xD9, 0x75, 0xD3, 0x67, 0x02, 0x08, 0x08, 0x08, 0x82, 0x0C, 0x18, 0x28, 0x12, 0x28, + 0x48, 0x48, 0x92, 0x2C, 0x58, 0x68, 0x0A, 0x18, 0x09, 0x09, 0x8A, 0x1C, 0x19, 0x29, 0x1A, 0x38, 0x49, 0x49, 0x9A, 0x3C, + 0x59, 0x69, 0x03, 0x09, 0x88, 0x0A, 0x83, 0x0D, 0x98, 0x2A, 0x13, 0x29, 0xC8, 0x4A, 0x93, 0x2D, 0xD8, 0x6A, 0x0B, 0x19, + 0x89, 0x0B, 0x8B, 0x1D, 0x99, 0x2B, 0x1B, 0x39, 0xC9, 0x4B, 0x9B, 0x3D, 0xD9, 0x6B, 0x42, 0x48, 0x0A, 0x0C, 0xC2, 0x4C, + 0x1A, 0x2C, 0x52, 0x68, 0x4A, 0x4C, 0xD2, 0x6C, 0x5A, 0x6C, 0x4A, 0x58, 0x0B, 0x0D, 0xCA, 0x5C, 0x1B, 0x2D, 0x5A, 0x78, + 0x4B, 0x4D, 0xDA, 0x7C, 0x5B, 0x6D, 0x43, 0x49, 0x8A, 0x0E, 0xC3, 0x4D, 0x9A, 0x2E, 0x53, 0x69, 0xCA, 0x4E, 0xD3, 0x6D, + 0xDA, 0x6E, 0x4B, 0x59, 0x8B, 0x0F, 0xCB, 0x5D, 0x9B, 0x2F, 0x5B, 0x79, 0xCB, 0x4F, 0xDB, 0x7D, 0xDB, 0x6F, 0x04, 0x80, + 0x20, 0x10, 0x84, 0x84, 0x30, 0x30, 0x14, 0xA0, 0x60, 0x50, 0x94, 0xA4, 0x70, 0x70, 0x0C, 0x90, 0x21, 0x11, 0x8C, 0x94, + 0x31, 0x31, 0x1C, 0xB0, 0x61, 0x51, 0x9C, 0xB4, 0x71, 0x71, 0x05, 0x81, 0xA0, 0x12, 0x85, 0x85, 0xB0, 0x32, 0x15, 0xA1, + 0xE0, 0x52, 0x95, 0xA5, 0xF0, 0x72, 0x0D, 0x91, 0xA1, 0x13, 0x8D, 0x95, 0xB1, 0x33, 0x1D, 0xB1, 0xE1, 0x53, 0x9D, 0xB5, + 0xF1, 0x73, 0x44, 0xC0, 0x22, 0x14, 0xC4, 0xC4, 0x32, 0x34, 0x54, 0xE0, 0x62, 0x54, 0xD4, 0xE4, 0x72, 0x74, 0x4C, 0xD0, + 0x23, 0x15, 0xCC, 0xD4, 0x33, 0x35, 0x5C, 0xF0, 0x63, 0x55, 0xDC, 0xF4, 0x73, 0x75, 0x45, 0xC1, 0xA2, 0x16, 0xC5, 0xC5, + 0xB2, 0x36, 0x55, 0xE1, 0xE2, 0x56, 0xD5, 0xE5, 0xF2, 0x76, 0x4D, 0xD1, 0xA3, 0x17, 0xCD, 0xD5, 0xB3, 0x37, 0x5D, 0xF1, + 0xE3, 0x57, 0xDD, 0xF5, 0xF3, 0x77, 0x06, 0x88, 0x28, 0x18, 0x86, 0x8C, 0x38, 0x38, 0x16, 0xA8, 0x68, 0x58, 0x96, 0xAC, + 0x78, 0x78, 0x0E, 0x98, 0x29, 0x19, 0x8E, 0x9C, 0x39, 0x39, 0x1E, 0xB8, 0x69, 0x59, 0x9E, 0xBC, 0x79, 0x79, 0x07, 0x89, + 0xA8, 0x1A, 0x87, 0x8D, 0xB8, 0x3A, 0x17, 0xA9, 0xE8, 0x5A, 0x97, 0xAD, 0xF8, 0x7A, 0x0F, 0x99, 0xA9, 0x1B, 0x8F, 0x9D, + 0xB9, 0x3B, 0x1F, 0xB9, 0xE9, 0x5B, 0x9F, 0xBD, 0xF9, 0x7B, 0x46, 0xC8, 0x2A, 0x1C, 0xC6, 0xCC, 0x3A, 0x3C, 0x56, 0xE8, + 0x6A, 0x5C, 0xD6, 0xEC, 0x7A, 0x7C, 0x4E, 0xD8, 0x2B, 0x1D, 0xCE, 0xDC, 0x3B, 0x3D, 0x5E, 0xF8, 0x6B, 0x5D, 0xDE, 0xFC, + 0x7B, 0x7D, 0x47, 0xC9, 0xAA, 0x1E, 0xC7, 0xCD, 0xBA, 0x3E, 0x57, 0xE9, 0xEA, 0x5E, 0xD7, 0xED, 0xFA, 0x7E, 0x4F, 0xD9, + 0xAB, 0x1F, 0xCF, 0xDD, 0xBB, 0x3F, 0x5F, 0xF9, 0xEB, 0x5F, 0xDF, 0xFD, 0xFB, 0x7F, 0x20, 0x02, 0x04, 0x80, 0xA0, 0x06, + 0x14, 0xA0, 0x30, 0x22, 0x44, 0xC0, 0xB0, 0x26, 0x54, 0xE0, 0x28, 0x12, 0x05, 0x81, 0xA8, 0x16, 0x15, 0xA1, 0x38, 0x32, + 0x45, 0xC1, 0xB8, 0x36, 0x55, 0xE1, 0x21, 0x03, 0x84, 0x82, 0xA1, 0x07, 0x94, 0xA2, 0x31, 0x23, 0xC4, 0xC2, 0xB1, 0x27, + 0xD4, 0xE2, 0x29, 0x13, 0x85, 0x83, 0xA9, 0x17, 0x95, 0xA3, 0x39, 0x33, 0xC5, 0xC3, 0xB9, 0x37, 0xD5, 0xE3, 0x60, 0x42, + 0x06, 0x84, 0xE0, 0x46, 0x16, 0xA4, 0x70, 0x62, 0x46, 0xC4, 0xF0, 0x66, 0x56, 0xE4, 0x68, 0x52, 0x07, 0x85, 0xE8, 0x56, + 0x17, 0xA5, 0x78, 0x72, 0x47, 0xC5, 0xF8, 0x76, 0x57, 0xE5, 0x61, 0x43, 0x86, 0x86, 0xE1, 0x47, 0x96, 0xA6, 0x71, 0x63, + 0xC6, 0xC6, 0xF1, 0x67, 0xD6, 0xE6, 0x69, 0x53, 0x87, 0x87, 0xE9, 0x57, 0x97, 0xA7, 0x79, 0x73, 0xC7, 0xC7, 0xF9, 0x77, + 0xD7, 0xE7, 0x22, 0x0A, 0x0C, 0x88, 0xA2, 0x0E, 0x1C, 0xA8, 0x32, 0x2A, 0x4C, 0xC8, 0xB2, 0x2E, 0x5C, 0xE8, 0x2A, 0x1A, + 0x0D, 0x89, 0xAA, 0x1E, 0x1D, 0xA9, 0x3A, 0x3A, 0x4D, 0xC9, 0xBA, 0x3E, 0x5D, 0xE9, 0x23, 0x0B, 0x8C, 0x8A, 0xA3, 0x0F, + 0x9C, 0xAA, 0x33, 0x2B, 0xCC, 0xCA, 0xB3, 0x2F, 0xDC, 0xEA, 0x2B, 0x1B, 0x8D, 0x8B, 0xAB, 0x1F, 0x9D, 0xAB, 0x3B, 0x3B, + 0xCD, 0xCB, 0xBB, 0x3F, 0xDD, 0xEB, 0x62, 0x4A, 0x0E, 0x8C, 0xE2, 0x4E, 0x1E, 0xAC, 0x72, 0x6A, 0x4E, 0xCC, 0xF2, 0x6E, + 0x5E, 0xEC, 0x6A, 0x5A, 0x0F, 0x8D, 0xEA, 0x5E, 0x1F, 0xAD, 0x7A, 0x7A, 0x4F, 0xCD, 0xFA, 0x7E, 0x5F, 0xED, 0x63, 0x4B, + 0x8E, 0x8E, 0xE3, 0x4F, 0x9E, 0xAE, 0x73, 0x6B, 0xCE, 0xCE, 0xF3, 0x6F, 0xDE, 0xEE, 0x6B, 0x5B, 0x8F, 0x8F, 0xEB, 0x5F, + 0x9F, 0xAF, 0x7B, 0x7B, 0xCF, 0xCF, 0xFB, 0x7F, 0xDF, 0xEF, 0x24, 0x82, 0x24, 0x90, 0xA4, 0x86, 0x34, 0xB0, 0x34, 0xA2, + 0x64, 0xD0, 0xB4, 0xA6, 0x74, 0xF0, 0x2C, 0x92, 0x25, 0x91, 0xAC, 0x96, 0x35, 0xB1, 0x3C, 0xB2, 0x65, 0xD1, 0xBC, 0xB6, + 0x75, 0xF1, 0x25, 0x83, 0xA4, 0x92, 0xA5, 0x87, 0xB4, 0xB2, 0x35, 0xA3, 0xE4, 0xD2, 0xB5, 0xA7, 0xF4, 0xF2, 0x2D, 0x93, + 0xA5, 0x93, 0xAD, 0x97, 0xB5, 0xB3, 0x3D, 0xB3, 0xE5, 0xD3, 0xBD, 0xB7, 0xF5, 0xF3, 0x64, 0xC2, 0x26, 0x94, 0xE4, 0xC6, + 0x36, 0xB4, 0x74, 0xE2, 0x66, 0xD4, 0xF4, 0xE6, 0x76, 0xF4, 0x6C, 0xD2, 0x27, 0x95, 0xEC, 0xD6, 0x37, 0xB5, 0x7C, 0xF2, + 0x67, 0xD5, 0xFC, 0xF6, 0x77, 0xF5, 0x65, 0xC3, 0xA6, 0x96, 0xE5, 0xC7, 0xB6, 0xB6, 0x75, 0xE3, 0xE6, 0xD6, 0xF5, 0xE7, + 0xF6, 0xF6, 0x6D, 0xD3, 0xA7, 0x97, 0xED, 0xD7, 0xB7, 0xB7, 0x7D, 0xF3, 0xE7, 0xD7, 0xFD, 0xF7, 0xF7, 0xF7, 0x26, 0x8A, + 0x2C, 0x98, 0xA6, 0x8E, 0x3C, 0xB8, 0x36, 0xAA, 0x6C, 0xD8, 0xB6, 0xAE, 0x7C, 0xF8, 0x2E, 0x9A, 0x2D, 0x99, 0xAE, 0x9E, + 0x3D, 0xB9, 0x3E, 0xBA, 0x6D, 0xD9, 0xBE, 0xBE, 0x7D, 0xF9, 0x27, 0x8B, 0xAC, 0x9A, 0xA7, 0x8F, 0xBC, 0xBA, 0x37, 0xAB, + 0xEC, 0xDA, 0xB7, 0xAF, 0xFC, 0xFA, 0x2F, 0x9B, 0xAD, 0x9B, 0xAF, 0x9F, 0xBD, 0xBB, 0x3F, 0xBB, 0xED, 0xDB, 0xBF, 0xBF, + 0xFD, 0xFB, 0x66, 0xCA, 0x2E, 0x9C, 0xE6, 0xCE, 0x3E, 0xBC, 0x76, 0xEA, 0x6E, 0xDC, 0xF6, 0xEE, 0x7E, 0xFC, 0x6E, 0xDA, + 0x2F, 0x9D, 0xEE, 0xDE, 0x3F, 0xBD, 0x7E, 0xFA, 0x6F, 0xDD, 0xFE, 0xFE, 0x7F, 0xFD, 0x67, 0xCB, 0xAE, 0x9E, 0xE7, 0xCF, + 0xBE, 0xBE, 0x77, 0xEB, 0xEE, 0xDE, 0xF7, 0xEF, 0xFE, 0xFE, 0x6F, 0xDB, 0xAF, 0x9F, 0xEF, 0xDF, 0xBF, 0xBF, 0x7F, 0xFB, + 0xEF, 0xDF, 0xFF, 0xFF, 0x90, 0xAF +}; +#endif + +#endif diff --git a/drivers/input/touchscreen/gt9xx_mido/gt9xx_update.c b/drivers/input/touchscreen/gt9xx_mido/gt9xx_update.c new file mode 100644 index 0000000000000..7bf104fbf0cb2 --- /dev/null +++ b/drivers/input/touchscreen/gt9xx_mido/gt9xx_update.c @@ -0,0 +1,3177 @@ +/* + * Goodix GT9xx touchscreen driver + * + * Copyright (C) 2010 - 2014 Goodix. Ltd. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be a reference + * to you, when you are integrating the GOODiX's CTP IC into your system, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Version: 2.4 + * Release Date: 2014/11/28 + */ +#include +#include "gt9xx.h" + +#include +#include +#if ((GTP_AUTO_UPDATE && GTP_HEADER_FW_UPDATE) || GTP_COMPATIBLE_MODE) + #include "gt9xx_firmware.h" +#endif + +#define GUP_REG_HW_INFO 0x4220 +#define GUP_REG_FW_MSG 0x41E4 +#define GUP_REG_PID_VID 0x8140 + +#define GUP_SEARCH_FILE_TIMES 50 + +#define UPDATE_FILE_PATH_1 "/data/_goodix_update_.bin" +#define UPDATE_FILE_PATH_2 "/sdcard/_goodix_update_.bin" + +#define CONFIG_FILE_PATH_1 "/data/_goodix_config_.cfg" +#define CONFIG_FILE_PATH_2 "/sdcard/_goodix_config_.cfg" + +#define FW_HEAD_LENGTH 14 +#define FW_SECTION_LENGTH 0x2000 +#define FW_DSP_ISP_LENGTH 0x1000 +#define FW_DSP_LENGTH 0x1000 +#define FW_BOOT_LENGTH 0x800 +#define FW_SS51_LENGTH (4 * FW_SECTION_LENGTH) +#define FW_BOOT_ISP_LENGTH 0x800 +#define FW_GLINK_LENGTH 0x3000 +#define FW_GWAKE_LENGTH (4 * FW_SECTION_LENGTH) + +#define PACK_SIZE 256 +#define MAX_FRAME_CHECK_TIME 5 + +#define _bRW_MISCTL__SRAM_BANK 0x4048 +#define _bRW_MISCTL__MEM_CD_EN 0x4049 +#define _bRW_MISCTL__CACHE_EN 0x404B +#define _bRW_MISCTL__TMR0_EN 0x40B0 +#define _rRW_MISCTL__SWRST_B0_ 0x4180 +#define _bWO_MISCTL__CPU_SWRST_PULSE 0x4184 +#define _rRW_MISCTL__BOOTCTL_B0_ 0x4190 +#define _rRW_MISCTL__BOOT_OPT_B0_ 0x4218 +#define _rRW_MISCTL__BOOT_CTL_ 0x5094 + +#define AUTO_SEARCH_BIN 0x01 +#define AUTO_SEARCH_CFG 0x02 +#define BIN_FILE_READY 0x80 +#define CFG_FILE_READY 0x08 +#define HEADER_FW_READY 0x00 + +#pragma pack(1) +typedef struct { + u8 hw_info[4]; + u8 pid[8]; + u16 vid; +} st_fw_head; +#pragma pack() + +typedef struct { + u8 force_update; + u8 fw_flag; + struct file *file; + struct file *cfg_file; + st_fw_head ic_fw_msg; + mm_segment_t old_fs; + u32 fw_total_len; + u32 fw_burned_len; +} st_update_msg; + +st_update_msg update_msg; +u16 show_len; +u16 total_len; +u8 got_file_flag = 0; +u8 searching_file = 0; + +extern u8 config[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH]; +extern void gtp_reset_guitar(struct i2c_client *client, s32 ms); +extern s32 gtp_send_cfg(struct i2c_client *client); +extern s32 gtp_read_version(struct i2c_client *, u16*); +extern struct i2c_client *i2c_connect_client; +extern void gtp_irq_enable(struct goodix_ts_data *ts); +extern void gtp_irq_disable(struct goodix_ts_data *ts); +extern s32 gtp_i2c_read_dbl_check(struct i2c_client *, u16, u8 *, int); +static u8 gup_burn_fw_gwake_section(struct i2c_client *client, u8 *fw_section, u16 start_addr, u32 len, u8 bank_cmd); +s32 i2c_read_bytes(struct i2c_client *client, u16 addr, u8 *buf, s32 len); + +#define _CLOSE_FILE(p_file) if (p_file && !IS_ERR(p_file)) \ + { \ + filp_close(p_file, NULL); \ + } + +#if GTP_ESD_PROTECT +extern void gtp_esd_switch(struct i2c_client *, s32); +#endif + +#if GTP_COMPATIBLE_MODE +s32 gup_fw_download_proc(void *dir, u8 dwn_mode); +#endif +/******************************************************* +Function: + Read data from the i2c slave device. +Input: + client: i2c device. + buf[0~1]: read start address. + buf[2~len-1]: read data buffer. + len: GTP_ADDR_LENGTH + read bytes count +Output: + numbers of i2c_msgs to transfer: + 2: succeed, otherwise: failed +*********************************************************/ +s32 gup_i2c_read(struct i2c_client *client, u8 *buf, s32 len) +{ + struct i2c_msg msgs[2]; + s32 ret = -1; + s32 retries = 0; + + GTP_DEBUG_FUNC(); + + msgs[0].flags = !I2C_M_RD; + msgs[0].addr = client->addr; + msgs[0].len = GTP_ADDR_LENGTH; + msgs[0].buf = &buf[0]; + + + msgs[1].flags = I2C_M_RD; + msgs[1].addr = client->addr; + msgs[1].len = len - GTP_ADDR_LENGTH; + msgs[1].buf = &buf[GTP_ADDR_LENGTH]; + + + while (retries < 5) { + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret == 2) + break; + retries++; + } + + return ret; +} + +/******************************************************* +Function: + Write data to the i2c slave device. +Input: + client: i2c device. + buf[0~1]: write start address. + buf[2~len-1]: data buffer + len: GTP_ADDR_LENGTH + write bytes count +Output: + numbers of i2c_msgs to transfer: + 1: succeed, otherwise: failed +*********************************************************/ +s32 gup_i2c_write(struct i2c_client *client, u8 *buf, s32 len) +{ + struct i2c_msg msg; + s32 ret = -1; + s32 retries = 0; + + GTP_DEBUG_FUNC(); + + msg.flags = !I2C_M_RD; + msg.addr = client->addr; + msg.len = len; + msg.buf = buf; + + + while (retries < 5) { + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret == 1) + break; + retries++; + } + + return ret; +} + +static s32 gup_init_panel(struct goodix_ts_data *ts) +{ + s32 ret = 0; + s32 i = 0; + u8 check_sum = 0; + u8 opr_buf[16]; + u8 sensor_id = 0; + u16 version = 0; + u8 drv_cfg_version; + u8 flash_cfg_version; + +#ifndef GTP_CONFIG_OF + u8 cfg_info_group0[] = CTP_CFG_GROUP0; + u8 cfg_info_group1[] = CTP_CFG_GROUP1; + u8 cfg_info_group2[] = CTP_CFG_GROUP2; + u8 cfg_info_group3[] = CTP_CFG_GROUP3; + u8 cfg_info_group4[] = CTP_CFG_GROUP4; + u8 cfg_info_group5[] = CTP_CFG_GROUP5; + u8 *send_cfg_buf[] = {cfg_info_group0, cfg_info_group1, + cfg_info_group2, cfg_info_group3, + cfg_info_group4, cfg_info_group5}; + u8 cfg_info_len[] = { CFG_GROUP_LEN(cfg_info_group0), + CFG_GROUP_LEN(cfg_info_group1), + CFG_GROUP_LEN(cfg_info_group2), + CFG_GROUP_LEN(cfg_info_group3), + CFG_GROUP_LEN(cfg_info_group4), + CFG_GROUP_LEN(cfg_info_group5)}; + #endif + + ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID, &sensor_id, 1); + if (SUCCESS == ret) { + if (sensor_id >= 0x06) { + GTP_ERROR("Invalid sensor_id(0x%02X), No Config Sent!", sensor_id); + return -EPERM; + } + } else { + GTP_ERROR("Failed to get sensor_id, No config sent!"); + return -EPERM; + } + + /* parse config data*/ +#ifdef GTP_CONFIG_OF + GTP_DEBUG("Get config data from dts file."); + ret = gtp_parse_dt_cfg(&ts->client->dev, &config[GTP_ADDR_LENGTH], &ts->gtp_cfg_len, sensor_id); + if (ret < 0) { + GTP_ERROR("Failed to parse config data form dts file."); + ts->pnl_init_error = 1; + return -EPERM; + } +#else + GTP_DEBUG("Get config data from header file."); + if ((!cfg_info_len[1]) && (!cfg_info_len[2]) && + (!cfg_info_len[3]) && (!cfg_info_len[4]) && + (!cfg_info_len[5])) { + sensor_id = 0; + } + ts->gtp_cfg_len = cfg_info_len[sensor_id]; + memset(&config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); + memcpy(&config[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id], ts->gtp_cfg_len); +#endif + + GTP_DEBUG("Sensor_ID: %d", sensor_id); + + if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH) { + GTP_ERROR("Sensor_ID(%d) matches with NULL or INVALID CONFIG GROUP! NO Config Sent! You need to check you header file CFG_GROUP section!", sensor_id); + return -EPERM; + } + + ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA, &opr_buf[0], 1); + if (ret == SUCCESS) { + GTP_DEBUG("CFG_GROUP%d Config Version: %d, IC Config Version: %d", sensor_id, + config[GTP_ADDR_LENGTH], opr_buf[0]); + + flash_cfg_version = opr_buf[0]; + drv_cfg_version = config[GTP_ADDR_LENGTH]; + + if (flash_cfg_version < 90 && flash_cfg_version > drv_cfg_version) { + config[GTP_ADDR_LENGTH] = 0x00; + } + } else { + GTP_ERROR("Failed to get ic config version!No config sent!"); + return -EPERM; + } + + GTP_DEBUG("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x", + ts->abs_x_max, ts->abs_y_max, ts->int_trigger_type); + + config[RESOLUTION_LOC] = (u8)GTP_MAX_WIDTH; + config[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8); + config[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT; + config[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8); + + if (GTP_INT_TRIGGER == 0) { + config[TRIGGER_LOC] &= 0xfe; + } else if (GTP_INT_TRIGGER == 1) { + config[TRIGGER_LOC] |= 0x01; + } + + check_sum = 0; + for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++) { + check_sum += config[i]; + } + config[ts->gtp_cfg_len] = (~check_sum) + 1; + + GTP_DEBUG_FUNC(); + ret = gtp_send_cfg(ts->client); + if (ret < 0) { + GTP_ERROR("Send config error."); + } + + if (flash_cfg_version < 90 && flash_cfg_version > drv_cfg_version) { + check_sum = 0; + config[GTP_ADDR_LENGTH] = drv_cfg_version; + for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++) { + check_sum += config[i]; + } + config[ts->gtp_cfg_len] = (~check_sum) + 1; + } + gtp_read_version(ts->client, &version); + msleep(10); + return 0; +} + + +static u8 gup_get_ic_msg(struct i2c_client *client, u16 addr, u8 *msg, s32 len) +{ + s32 i = 0; + + msg[0] = (addr >> 8) & 0xff; + msg[1] = addr & 0xff; + + for (i = 0; i < 5; i++) { + if (gup_i2c_read(client, msg, GTP_ADDR_LENGTH + len) > 0) { + break; + } + } + + if (i >= 5) { + GTP_ERROR("Read data from 0x%02x%02x failed!", msg[0], msg[1]); + return FAIL; + } + + return SUCCESS; +} + +static u8 gup_set_ic_msg(struct i2c_client *client, u16 addr, u8 val) +{ + s32 i = 0; + u8 msg[3]; + + msg[0] = (addr >> 8) & 0xff; + msg[1] = addr & 0xff; + msg[2] = val; + + for (i = 0; i < 5; i++) { + if (gup_i2c_write(client, msg, GTP_ADDR_LENGTH + 1) > 0) { + break; + } + } + + if (i >= 5) { + GTP_ERROR("Set data to 0x%02x%02x failed!", msg[0], msg[1]); + return FAIL; + } + + return SUCCESS; +} + +static u8 gup_get_ic_fw_msg(struct i2c_client *client) +{ + s32 ret = -1; + u8 retry = 0; + u8 buf[16]; + u8 i; + + + ret = gtp_i2c_read_dbl_check(client, GUP_REG_HW_INFO, &buf[GTP_ADDR_LENGTH], 4); + if (FAIL == ret) { + GTP_ERROR("[get_ic_fw_msg]get hw_info failed,exit"); + return FAIL; + } + + + + for (i = 0; i < 4; i++) { + update_msg.ic_fw_msg.hw_info[i] = buf[GTP_ADDR_LENGTH + 3 - i]; + } + GTP_DEBUG("IC Hardware info:%02x%02x%02x%02x", update_msg.ic_fw_msg.hw_info[0], update_msg.ic_fw_msg.hw_info[1], + update_msg.ic_fw_msg.hw_info[2], update_msg.ic_fw_msg.hw_info[3]); + + for (retry = 0; retry < 2; retry++) { + ret = gup_get_ic_msg(client, GUP_REG_FW_MSG, buf, 1); + if (FAIL == ret) { + GTP_ERROR("Read firmware message fail."); + return ret; + } + + update_msg.force_update = buf[GTP_ADDR_LENGTH]; + if ((0xBE != update_msg.force_update) && (!retry)) { + GTP_INFO("The check sum in ic is error."); + GTP_INFO("The IC will be updated by force."); + continue; + } + break; + } + GTP_DEBUG("IC force update flag:0x%x", update_msg.force_update); + + + ret = gtp_i2c_read_dbl_check(client, GUP_REG_PID_VID, &buf[GTP_ADDR_LENGTH], 6); + if (FAIL == ret) { + GTP_ERROR("[get_ic_fw_msg]get pid & vid failed,exit"); + return FAIL; + } + + memset(update_msg.ic_fw_msg.pid, 0, sizeof(update_msg.ic_fw_msg.pid)); + memcpy(update_msg.ic_fw_msg.pid, &buf[GTP_ADDR_LENGTH], 4); + GTP_DEBUG("IC Product id:%s", update_msg.ic_fw_msg.pid); + + + /*|-----FLASH-----RAM-----| + |------918------918-----| + |------968------968-----| + |------913------913-----| + |------913P-----913P----| + |------927------927-----| + |------927P-----927P----| + |------9110-----9110----| + |------9110P----9111----|*/ + if (update_msg.ic_fw_msg.pid[0] != 0) { + if (!memcmp(update_msg.ic_fw_msg.pid, "9111", 4)) { + GTP_DEBUG("IC Mapping Product id:%s",update_msg.ic_fw_msg.pid); + memcpy(update_msg.ic_fw_msg.pid, "9110P", 5); + } + } + + update_msg.ic_fw_msg.vid = buf[GTP_ADDR_LENGTH+4] +(buf[GTP_ADDR_LENGTH+5]<<8); + GTP_DEBUG("IC version id:%04x", update_msg.ic_fw_msg.vid); + + return SUCCESS; +} + +s32 gup_enter_update_mode(struct i2c_client *client) +{ + s32 ret = -1; + s32 retry = 0; + u8 rd_buf[3]; + + + GTP_GPIO_OUTPUT(gtp_rst_gpio, 0); + msleep(2); + + + GTP_GPIO_OUTPUT(gtp_int_gpio, (client->addr == 0x14)); + msleep(2); + + + GTP_GPIO_OUTPUT(gtp_rst_gpio, 1); + + + msleep(5); + while (retry++ < 200) { + + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + GTP_DEBUG("Hold ss51 & dsp I2C error,retry:%d", retry); + continue; + } + + ret = gup_get_ic_msg(client, _rRW_MISCTL__SWRST_B0_, rd_buf, 1); + if (ret <= 0) { + GTP_DEBUG("Hold ss51 & dsp I2C error,retry:%d", retry); + continue; + } + if (0x0C == rd_buf[GTP_ADDR_LENGTH]) { + GTP_DEBUG("Hold ss51 & dsp confirm SUCCESS"); + break; + } + GTP_DEBUG("Hold ss51 & dsp confirm 0x4180 failed,value:%d", rd_buf[GTP_ADDR_LENGTH]); + } + if (retry >= 200) { + GTP_ERROR("Enter update Hold ss51 failed."); + return FAIL; + } + + ret = gup_set_ic_msg(client, 0x4010, 0x00); + + return ret; +} + +void gup_leave_update_mode(void) +{ + GTP_GPIO_AS_INT(gtp_int_gpio); + + GTP_DEBUG("[leave_update_mode]reset chip."); + gtp_reset_guitar(i2c_connect_client, 20); +} + + + +/* Update Conditions: + 1. Same hardware info + 2. Same PID + 3. File VID > IC VID + Force Update Conditions: + 1. Wrong ic firmware checksum + 2. INVALID IC PID or VID + 3. (IC PID == 91XX || File PID == 91XX) && (File VID > IC VID) +*/ + +static u8 gup_enter_update_judge(st_fw_head *fw_head) +{ + u16 u16_tmp; + s32 i = 0; + u32 fw_len = 0; + s32 pid_cmp_len = 0; + u16_tmp = fw_head->vid; + fw_head->vid = (u16)(u16_tmp>>8) + (u16)(u16_tmp<<8); + + GTP_INFO("FILE HARDWARE INFO:%02x%02x%02x%02x", fw_head->hw_info[0], fw_head->hw_info[1], fw_head->hw_info[2], fw_head->hw_info[3]); + GTP_INFO("FILE PID:%s", fw_head->pid); + GTP_INFO("FILE VID:%04x", fw_head->vid); + GTP_INFO("IC HARDWARE INFO:%02x%02x%02x%02x", update_msg.ic_fw_msg.hw_info[0], update_msg.ic_fw_msg.hw_info[1], + update_msg.ic_fw_msg.hw_info[2], update_msg.ic_fw_msg.hw_info[3]); + GTP_INFO("IC PID:%s", update_msg.ic_fw_msg.pid); + GTP_INFO("IC VID:%04x", update_msg.ic_fw_msg.vid); + + if (!memcmp(fw_head->pid, "9158", 4) && !memcmp(update_msg.ic_fw_msg.pid, "915S", 4)) { + GTP_INFO("Update GT915S to GT9158 directly!"); + return SUCCESS; + } + + if (!memcmp(fw_head->hw_info, update_msg.ic_fw_msg.hw_info, sizeof(update_msg.ic_fw_msg.hw_info))) { + fw_len = 42 * 1024; + } else { + fw_len = fw_head->hw_info[3]; + fw_len += (((u32)fw_head->hw_info[2]) << 8); + fw_len += (((u32)fw_head->hw_info[1]) << 16); + fw_len += (((u32)fw_head->hw_info[0]) << 24); + } + if (update_msg.fw_total_len != fw_len) { + GTP_ERROR("Inconsistent firmware size, Update aborted! Default size: %d(%dK), actual size: %d(%dK)", fw_len, fw_len/1024, update_msg.fw_total_len, update_msg.fw_total_len/1024); + return FAIL; + } + GTP_INFO("Firmware length:%d(%dK)", update_msg.fw_total_len, update_msg.fw_total_len/1024); + + if (update_msg.force_update != 0xBE) { + GTP_INFO("FW chksum error,need enter update."); + return SUCCESS; + } + + + if (strlen(update_msg.ic_fw_msg.pid) < 3) { + GTP_INFO("Illegal IC pid, need enter update"); + return SUCCESS; + } else { + for (i = 0; i < 3; i++) { + if ((update_msg.ic_fw_msg.pid[i] < 0x30) || (update_msg.ic_fw_msg.pid[i] > 0x39)) { + GTP_INFO("Illegal IC pid, out of bound, need enter update"); + return SUCCESS; + } + } + } + + + pid_cmp_len = strlen(fw_head->pid); + if (pid_cmp_len < strlen(update_msg.ic_fw_msg.pid)) { + pid_cmp_len = strlen(update_msg.ic_fw_msg.pid); + } + + if ((!memcmp(fw_head->pid, update_msg.ic_fw_msg.pid, pid_cmp_len)) || + (!memcmp(update_msg.ic_fw_msg.pid, "91XX", 4)) || + (!memcmp(fw_head->pid, "91XX", 4))) { + if (!memcmp(fw_head->pid, "91XX", 4)) { + GTP_DEBUG("Force none same pid update mode."); + } else { + GTP_DEBUG("Get the same pid."); + } + + + if (fw_head->vid > update_msg.ic_fw_msg.vid) { + GTP_INFO("Need enter update."); + return SUCCESS; + } + GTP_ERROR("Don't meet the third condition."); + GTP_ERROR("File VID <= Ic VID, update aborted!"); + } else { + GTP_ERROR("File PID != Ic PID, update aborted!"); + } + + return FAIL; +} + + + +#if GTP_AUTO_UPDATE_CFG +static u8 ascii2hex(u8 a) +{ + s8 value = 0; + + if (a >= '0' && a <= '9') { + value = a - '0'; + } else if (a >= 'A' && a <= 'F') { + value = a - 'A' + 0x0A; + } else if (a >= 'a' && a <= 'f') { + value = a - 'a' + 0x0A; + } else { + value = 0xff; + } + + return value; +} + +static s8 gup_update_config(struct i2c_client *client) +{ + s32 file_len = 0; + s32 ret = 0; + s32 i = 0; + s32 file_cfg_len = 0; + s32 chip_cfg_len = 0; + s32 count = 0; + u8 *buf; + u8 *pre_buf; + u8 *file_config; + + struct goodix_ts_data *ts = i2c_get_clientdata(client); + + if (NULL == update_msg.cfg_file) { + GTP_ERROR("[update_cfg]No need to upgrade config!"); + return FAIL; + } + file_len = update_msg.cfg_file->f_op->llseek(update_msg.cfg_file, 0, SEEK_END); + + chip_cfg_len = ts->gtp_cfg_len; + + GTP_DEBUG("[update_cfg]config file len:%d", file_len); + GTP_DEBUG("[update_cfg]need config len:%d", chip_cfg_len); + if ((file_len+5) < chip_cfg_len*5) { + GTP_ERROR("Config length error"); + return -EPERM; + } + + buf = (u8 *)kzalloc(file_len, GFP_KERNEL); + pre_buf = (u8 *)kzalloc(file_len, GFP_KERNEL); + file_config = (u8 *)kzalloc(chip_cfg_len + GTP_ADDR_LENGTH, GFP_KERNEL); + update_msg.cfg_file->f_op->llseek(update_msg.cfg_file, 0, SEEK_SET); + + GTP_DEBUG("[update_cfg]Read config from file."); + ret = update_msg.cfg_file->f_op->read(update_msg.cfg_file, (char *)pre_buf, file_len, &update_msg.cfg_file->f_pos); + if (ret < 0) { + GTP_ERROR("[update_cfg]Read config file failed."); + goto update_cfg_file_failed; + } + + GTP_DEBUG("[update_cfg]Delete illgal charactor."); + for (i = 0, count = 0; i < file_len; i++) { + if (pre_buf[i] == ' ' || pre_buf[i] == '\r' || pre_buf[i] == '\n') { + continue; + } + buf[count++] = pre_buf[i]; + } + + GTP_DEBUG("[update_cfg]Ascii to hex."); + file_config[0] = GTP_REG_CONFIG_DATA >> 8; + file_config[1] = GTP_REG_CONFIG_DATA & 0xff; + for (i = 0, file_cfg_len = GTP_ADDR_LENGTH; i < count; i += 5) { + if ((buf[i] == '0') && ((buf[i+1] == 'x') || (buf[i+1] == 'X'))) { + u8 high, low; + high = ascii2hex(buf[i+2]); + low = ascii2hex(buf[i+3]); + + if ((high == 0xFF) || (low == 0xFF)) { + ret = 0; + GTP_ERROR("[update_cfg]Illegal config file."); + goto update_cfg_file_failed; + } + file_config[file_cfg_len++] = (high<<4) + low; + } else { + ret = 0; + GTP_ERROR("[update_cfg]Illegal config file."); + goto update_cfg_file_failed; + } + } + + + GTP_DEBUG("config:"); + GTP_DEBUG_ARRAY(file_config+2, file_cfg_len); + + i = 0; + while (i++ < 5) { + ret = gup_i2c_write(client, file_config, file_cfg_len); + if (ret > 0) { + GTP_INFO("[update_cfg]Send config SUCCESS."); + break; + } + GTP_ERROR("[update_cfg]Send config i2c error."); + } + +update_cfg_file_failed: + kfree(pre_buf); + kfree(buf); + kfree(file_config); + return ret; +} + +#endif + +#if (GTP_AUTO_UPDATE && (!GTP_HEADER_FW_UPDATE || GTP_AUTO_UPDATE_CFG)) +static void gup_search_file(s32 search_type) +{ + s32 i = 0; + struct file *pfile = NULL; + + got_file_flag = 0x00; + + searching_file = 1; + for (i = 0; i < GUP_SEARCH_FILE_TIMES; ++i) { + if (0 == searching_file) { + GTP_INFO("Force exiting file searching"); + got_file_flag = 0x00; + return; + } + + if (search_type & AUTO_SEARCH_BIN) { + GTP_DEBUG("Search for %s, %s for fw update.(%d/%d)", UPDATE_FILE_PATH_1, UPDATE_FILE_PATH_2, i+1, GUP_SEARCH_FILE_TIMES); + pfile = filp_open(UPDATE_FILE_PATH_1, O_RDONLY, 0); + if (IS_ERR(pfile)) { + pfile = filp_open(UPDATE_FILE_PATH_2, O_RDONLY, 0); + if (!IS_ERR(pfile)) { + GTP_INFO("Bin file: %s for fw update.", UPDATE_FILE_PATH_2); + got_file_flag |= BIN_FILE_READY; + update_msg.file = pfile; + } + } else { + GTP_INFO("Bin file: %s for fw update.", UPDATE_FILE_PATH_1); + got_file_flag |= BIN_FILE_READY; + update_msg.file = pfile; + } + if (got_file_flag & BIN_FILE_READY) { + #if GTP_AUTO_UPDATE_CFG + if (search_type & AUTO_SEARCH_CFG) { + i = GUP_SEARCH_FILE_TIMES; + } else + #endif + { + searching_file = 0; + return; + } + } + } + + #if GTP_AUTO_UPDATE_CFG + if ((search_type & AUTO_SEARCH_CFG) && !(got_file_flag & CFG_FILE_READY)) { + GTP_DEBUG("Search for %s, %s for config update.(%d/%d)", CONFIG_FILE_PATH_1, CONFIG_FILE_PATH_2, i+1, GUP_SEARCH_FILE_TIMES); + pfile = filp_open(CONFIG_FILE_PATH_1, O_RDONLY, 0); + if (IS_ERR(pfile)) { + pfile = filp_open(CONFIG_FILE_PATH_2, O_RDONLY, 0); + if (!IS_ERR(pfile)) { + GTP_INFO("Cfg file: %s for config update.", CONFIG_FILE_PATH_2); + got_file_flag |= CFG_FILE_READY; + update_msg.cfg_file = pfile; + } + } else { + GTP_INFO("Cfg file: %s for config update.", CONFIG_FILE_PATH_1); + got_file_flag |= CFG_FILE_READY; + update_msg.cfg_file = pfile; + } + if (got_file_flag & CFG_FILE_READY) { + searching_file = 0; + return; + } + } + #endif + msleep(3000); + } + searching_file = 0; +} +#endif + +extern int gt9xx_id; + +static u8 gup_check_update_file(struct i2c_client *client, st_fw_head *fw_head, u8 *path) +{ + s32 ret = 0; + s32 i = 0; + s32 fw_checksum = 0; + u8 buf[FW_HEAD_LENGTH]; + + got_file_flag = 0x00; + if (path) { + GTP_DEBUG("Update File path:%s, %zd", path, strlen(path)); + update_msg.file = filp_open(path, O_RDONLY, 0); + + if (IS_ERR(update_msg.file)) { + GTP_ERROR("Open update file(%s) error!", path); + return FAIL; + } + got_file_flag = BIN_FILE_READY; + } else { +#if GTP_AUTO_UPDATE + #if GTP_HEADER_FW_UPDATE + if (gt9xx_id == 0) { + GTP_INFO("Update by gt915 firmware array"); + update_msg.fw_total_len = sizeof(gt915_FW) - FW_HEAD_LENGTH; + if (sizeof(gt915_FW) < (FW_HEAD_LENGTH+FW_SECTION_LENGTH*4+FW_DSP_ISP_LENGTH+FW_DSP_LENGTH+FW_BOOT_LENGTH)) { + GTP_ERROR("INVALID gt915_FW, check your gt9xx_firmware.h file!"); + return FAIL; + } + GTP_DEBUG("Firmware actual size: %d(%dK)", update_msg.fw_total_len, update_msg.fw_total_len/1024); + memcpy(fw_head, >915_FW[0], FW_HEAD_LENGTH); + + fw_checksum = 0; + for (i = 0; i < update_msg.fw_total_len; i += 2) { + fw_checksum += (gt915_FW[FW_HEAD_LENGTH + i] << 8) + gt915_FW[FW_HEAD_LENGTH + i + 1]; + } + GTP_DEBUG("firmware checksum:%x", fw_checksum&0xFFFF); + if (fw_checksum&0xFFFF) { + GTP_ERROR("Illegal firmware file."); + return FAIL; + } + got_file_flag = HEADER_FW_READY; + return SUCCESS; + } else { + GTP_INFO("Update by gt917 firmware array"); + + update_msg.fw_total_len = sizeof(gt917_FW) - FW_HEAD_LENGTH; + if (sizeof(gt917_FW) < (FW_HEAD_LENGTH+FW_SECTION_LENGTH*4+FW_DSP_ISP_LENGTH+FW_DSP_LENGTH+FW_BOOT_LENGTH)) { + GTP_ERROR("INVALID gt917_FW, check your gt9xx_firmware.h file!"); + return FAIL; + } + GTP_DEBUG("Firmware actual size: %d(%dK)", update_msg.fw_total_len, update_msg.fw_total_len/1024); + memcpy(fw_head, >917_FW[0], FW_HEAD_LENGTH); + + fw_checksum = 0; + for (i = 0; i < update_msg.fw_total_len; i += 2) { + fw_checksum += (gt917_FW[FW_HEAD_LENGTH + i] << 8) + gt917_FW[FW_HEAD_LENGTH + i + 1]; + } + + GTP_DEBUG("firmware checksum:%x", fw_checksum&0xFFFF); + if (fw_checksum&0xFFFF) { + GTP_ERROR("Illegal firmware file."); + return FAIL; + } + got_file_flag = HEADER_FW_READY; + return SUCCESS; + } + #else + + #if GTP_AUTO_UPDATE_CFG + gup_search_file(AUTO_SEARCH_BIN | AUTO_SEARCH_CFG); + if (got_file_flag & CFG_FILE_READY) { + ret = gup_update_config(i2c_connect_client); + if (ret <= 0) { + GTP_ERROR("Update config failed."); + } + _CLOSE_FILE(update_msg.cfg_file); + msleep(500); + } + #else + gup_search_file(AUTO_SEARCH_BIN); + #endif + + if (!(got_file_flag & BIN_FILE_READY)) { + GTP_ERROR("No bin file for fw update"); + return FAIL; + } + #endif + +#else + { + GTP_ERROR("NULL file for firmware update"); + return FAIL; + } +#endif + } + + update_msg.old_fs = get_fs(); + set_fs(KERNEL_DS); + + update_msg.file->f_op->llseek(update_msg.file, 0, SEEK_SET); + update_msg.fw_total_len = update_msg.file->f_op->llseek(update_msg.file, 0, SEEK_END); + if (update_msg.fw_total_len < (FW_HEAD_LENGTH + FW_SECTION_LENGTH*4+FW_DSP_ISP_LENGTH+FW_DSP_LENGTH+FW_BOOT_LENGTH)) { + GTP_ERROR("INVALID bin file(size: %d), update aborted.", update_msg.fw_total_len); + return FAIL; + } + + update_msg.fw_total_len -= FW_HEAD_LENGTH; + + GTP_DEBUG("Bin firmware actual size: %d(%dK)", update_msg.fw_total_len, update_msg.fw_total_len/1024); + + update_msg.file->f_op->llseek(update_msg.file, 0, SEEK_SET); + ret = update_msg.file->f_op->read(update_msg.file, (char *)buf, FW_HEAD_LENGTH, &update_msg.file->f_pos); + if (ret < 0) { + GTP_ERROR("Read firmware head in update file error."); + return FAIL; + } + + memcpy(fw_head, buf, FW_HEAD_LENGTH); + + + fw_checksum = 0; + for (i = 0; i < update_msg.fw_total_len; i += 2) { + u16 temp; + ret = update_msg.file->f_op->read(update_msg.file, (char *)buf, 2, &update_msg.file->f_pos); + if (ret < 0) { + GTP_ERROR("Read firmware file error."); + return FAIL; + } + + temp = (buf[0]<<8) + buf[1]; + fw_checksum += temp; + } + + GTP_DEBUG("firmware checksum:%x", fw_checksum&0xFFFF); + if (fw_checksum&0xFFFF) { + GTP_ERROR("Illegal firmware file."); + return FAIL; + } + + return SUCCESS; +} + +static u8 gup_burn_proc(struct i2c_client *client, u8 *burn_buf, u16 start_addr, u16 total_length) +{ + s32 ret = 0; + u16 burn_addr = start_addr; + u16 frame_length = 0; + u16 burn_length = 0; + u8 wr_buf[PACK_SIZE + GTP_ADDR_LENGTH]; + u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH]; + u8 retry = 0; + + GTP_DEBUG("Begin burn %dk data to addr 0x%x", (total_length/1024), start_addr); + while (burn_length < total_length) { + GTP_DEBUG("B/T:%04d/%04d", burn_length, total_length); + frame_length = ((total_length - burn_length) > PACK_SIZE) ? PACK_SIZE : (total_length - burn_length); + wr_buf[0] = (u8)(burn_addr>>8); + rd_buf[0] = wr_buf[0]; + wr_buf[1] = (u8)burn_addr; + rd_buf[1] = wr_buf[1]; + memcpy(&wr_buf[GTP_ADDR_LENGTH], &burn_buf[burn_length], frame_length); + + for (retry = 0; retry < MAX_FRAME_CHECK_TIME; retry++) { + ret = gup_i2c_write(client, wr_buf, GTP_ADDR_LENGTH + frame_length); + if (ret <= 0) { + GTP_ERROR("Write frame data i2c error."); + continue; + } + ret = gup_i2c_read(client, rd_buf, GTP_ADDR_LENGTH + frame_length); + if (ret <= 0) { + GTP_ERROR("Read back frame data i2c error."); + continue; + } + + if (memcmp(&wr_buf[GTP_ADDR_LENGTH], &rd_buf[GTP_ADDR_LENGTH], frame_length)) { + GTP_ERROR("Check frame data fail,not equal."); + GTP_DEBUG("write array:"); + GTP_DEBUG_ARRAY(&wr_buf[GTP_ADDR_LENGTH], frame_length); + GTP_DEBUG("read array:"); + GTP_DEBUG_ARRAY(&rd_buf[GTP_ADDR_LENGTH], frame_length); + continue; + } else { + + break; + } + } + if (retry >= MAX_FRAME_CHECK_TIME) { + GTP_ERROR("Burn frame data time out,exit."); + return FAIL; + } + burn_length += frame_length; + burn_addr += frame_length; + } + return SUCCESS; +} + +static u8 gup_load_section_file(u8 *buf, u32 offset, u16 length, u8 set_or_end) +{ +#if (GTP_AUTO_UPDATE && GTP_HEADER_FW_UPDATE) + if (got_file_flag == HEADER_FW_READY) { + if(SEEK_SET == set_or_end) { + memcpy(buf, >915_FW[FW_HEAD_LENGTH + offset], length); + } else { + memcpy(buf, >915_FW[update_msg.fw_total_len + FW_HEAD_LENGTH - offset], length); + } + return SUCCESS; + } +#endif + { + s32 ret = 0; + + if ((update_msg.file == NULL) || IS_ERR(update_msg.file)) { + GTP_ERROR("cannot find update file,load section file fail."); + return FAIL; + } + + if (SEEK_SET == set_or_end) { + update_msg.file->f_pos = FW_HEAD_LENGTH + offset; + } else { + update_msg.file->f_pos = update_msg.fw_total_len + FW_HEAD_LENGTH - offset; + } + + ret = update_msg.file->f_op->read(update_msg.file, (char *)buf, length, &update_msg.file->f_pos); + + if (ret < 0) { + GTP_ERROR("Read update file fail."); + return FAIL; + } + + return SUCCESS; + } +} + +static u8 gup_recall_check(struct i2c_client *client, u8 *chk_src, u16 start_rd_addr, u16 chk_length) +{ + u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH]; + s32 ret = 0; + u16 recall_addr = start_rd_addr; + u16 recall_length = 0; + u16 frame_length = 0; + + while (recall_length < chk_length) { + frame_length = ((chk_length - recall_length) > PACK_SIZE)? PACK_SIZE : (chk_length - recall_length); + ret = gup_get_ic_msg(client, recall_addr, rd_buf, frame_length); + if (ret <= 0) { + GTP_ERROR("recall i2c error,exit"); + return FAIL; + } + + if (memcmp(&rd_buf[GTP_ADDR_LENGTH], &chk_src[recall_length], frame_length)) { + GTP_ERROR("Recall frame data fail,not equal."); + GTP_DEBUG("chk_src array:"); + GTP_DEBUG_ARRAY(&chk_src[recall_length], frame_length); + GTP_DEBUG("recall array:"); + GTP_DEBUG_ARRAY(&rd_buf[GTP_ADDR_LENGTH], frame_length); + return FAIL; + } + + recall_length += frame_length; + recall_addr += frame_length; + } + GTP_DEBUG("Recall check %dk firmware success.", (chk_length/1024)); + + return SUCCESS; +} + +static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section, u16 start_addr, u8 bank_cmd) +{ + s32 ret = 0; + u8 rd_buf[5]; + + + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + GTP_ERROR("[burn_fw_section]hold ss51 & dsp fail."); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); + if (ret <= 0) { + GTP_ERROR("[burn_fw_section]set scramble fail."); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, (bank_cmd >> 4)&0x0F); + if (ret <= 0) { + GTP_ERROR("[burn_fw_section]select bank %d fail.", (bank_cmd >> 4)&0x0F); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); + if (ret <= 0) { + GTP_ERROR("[burn_fw_section]enable accessing code fail."); + return FAIL; + } + + + ret = gup_burn_proc(client, fw_section, start_addr, FW_SECTION_LENGTH); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_section]burn fw_section fail."); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); + if (ret <= 0) { + GTP_ERROR("[burn_fw_section]hold ss51 & release dsp fail."); + return FAIL; + } + + msleep(1); + + + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0f); + if (ret <= 0) { + GTP_ERROR("[burn_fw_section]send burn cmd fail."); + return FAIL; + } + GTP_DEBUG("[burn_fw_section]Wait for the burn is complete......"); + do { + ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); + if (ret <= 0) { + GTP_ERROR("[burn_fw_section]Get burn state fail"); + return FAIL; + } + msleep(10); + + } while (rd_buf[GTP_ADDR_LENGTH]); + + + ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, (bank_cmd >> 4)&0x0F); + if (ret <= 0) { + GTP_ERROR("[burn_fw_section]select bank %d fail.", (bank_cmd >> 4)&0x0F); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); + if (ret <= 0) { + GTP_ERROR("[burn_fw_section]enable accessing code fail."); + return FAIL; + } + + + ret = gup_recall_check(client, fw_section, start_addr, FW_SECTION_LENGTH); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_section]recall check %dk firmware fail.", FW_SECTION_LENGTH/1024); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x00); + if (ret <= 0) { + GTP_ERROR("[burn_fw_section]disable accessing code fail."); + return FAIL; + } + + return SUCCESS; +} + +static u8 gup_burn_dsp_isp(struct i2c_client *client) +{ + s32 ret = 0; + u8 *fw_dsp_isp = NULL; + u8 retry = 0; + + GTP_INFO("[burn_dsp_isp]Begin burn dsp isp---->>"); + + + GTP_DEBUG("[burn_dsp_isp]step1:alloc memory"); + while (retry++ < 5) { + fw_dsp_isp = (u8 *)kzalloc(FW_DSP_ISP_LENGTH, GFP_KERNEL); + if (fw_dsp_isp == NULL) { + continue; + } else { + GTP_INFO("[burn_dsp_isp]Alloc %dk byte memory success.", (FW_DSP_ISP_LENGTH/1024)); + break; + } + } + if (retry >= 5) { + GTP_ERROR("[burn_dsp_isp]Alloc memory fail,exit."); + return FAIL; + } + + + GTP_DEBUG("[burn_dsp_isp]step2:load dsp isp file data"); + ret = gup_load_section_file(fw_dsp_isp, FW_DSP_ISP_LENGTH, FW_DSP_ISP_LENGTH, SEEK_END); + if (FAIL == ret) { + GTP_ERROR("[burn_dsp_isp]load firmware dsp_isp fail."); + goto exit_burn_dsp_isp; + } + + + GTP_DEBUG("[burn_dsp_isp]step3:disable wdt,clear cache enable"); + ret = gup_set_ic_msg(client, _bRW_MISCTL__TMR0_EN, 0x00); + if (ret <= 0) { + GTP_ERROR("[burn_dsp_isp]disable wdt fail."); + ret = FAIL; + goto exit_burn_dsp_isp; + } + ret = gup_set_ic_msg(client, _bRW_MISCTL__CACHE_EN, 0x00); + if (ret <= 0) { + GTP_ERROR("[burn_dsp_isp]clear cache enable fail."); + ret = FAIL; + goto exit_burn_dsp_isp; + } + + + GTP_DEBUG("[burn_dsp_isp]step4:hold ss51 & dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + GTP_ERROR("[burn_dsp_isp]hold ss51 & dsp fail."); + ret = FAIL; + goto exit_burn_dsp_isp; + } + + + GTP_DEBUG("[burn_dsp_isp]step5:set boot from sram"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOTCTL_B0_, 0x02); + if (ret <= 0) { + GTP_ERROR("[burn_dsp_isp]set boot from sram fail."); + ret = FAIL; + goto exit_burn_dsp_isp; + } + + + GTP_DEBUG("[burn_dsp_isp]step6:software reboot"); + ret = gup_set_ic_msg(client, _bWO_MISCTL__CPU_SWRST_PULSE, 0x01); + if (ret <= 0) { + GTP_ERROR("[burn_dsp_isp]software reboot fail."); + ret = FAIL; + goto exit_burn_dsp_isp; + } + + + GTP_DEBUG("[burn_dsp_isp]step7:select bank2"); + ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x02); + if (ret <= 0) { + GTP_ERROR("[burn_dsp_isp]select bank2 fail."); + ret = FAIL; + goto exit_burn_dsp_isp; + } + + + GTP_DEBUG("[burn_dsp_isp]step8:enable accessing code"); + ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); + if (ret <= 0) { + GTP_ERROR("[burn_dsp_isp]enable accessing code fail."); + ret = FAIL; + goto exit_burn_dsp_isp; + } + + + GTP_DEBUG("[burn_dsp_isp]step9:burn 4k dsp_isp"); + ret = gup_burn_proc(client, fw_dsp_isp, 0xC000, FW_DSP_ISP_LENGTH); + if (FAIL == ret) { + GTP_ERROR("[burn_dsp_isp]burn dsp_isp fail."); + goto exit_burn_dsp_isp; + } + + + GTP_DEBUG("[burn_dsp_isp]step10:set scramble"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); + if (ret <= 0) { + GTP_ERROR("[burn_dsp_isp]set scramble fail."); + ret = FAIL; + goto exit_burn_dsp_isp; + } + update_msg.fw_burned_len += FW_DSP_ISP_LENGTH; + GTP_DEBUG("[burn_dsp_isp]Burned length:%d", update_msg.fw_burned_len); + ret = SUCCESS; + +exit_burn_dsp_isp: + kfree(fw_dsp_isp); + return ret; +} + +static u8 gup_burn_fw_ss51(struct i2c_client *client) +{ + u8 *fw_ss51 = NULL; + u8 retry = 0; + s32 ret = 0; + + GTP_INFO("[burn_fw_ss51]Begin burn ss51 firmware---->>"); + + + GTP_DEBUG("[burn_fw_ss51]step1:alloc memory"); + while (retry++ < 5) { + fw_ss51 = (u8 *)kzalloc(FW_SECTION_LENGTH, GFP_KERNEL); + if (fw_ss51 == NULL) { + continue; + } else { + GTP_DEBUG("[burn_fw_ss51]Alloc %dk byte memory success.", (FW_SECTION_LENGTH / 1024)); + break; + } + } + if (retry >= 5) { + GTP_ERROR("[burn_fw_ss51]Alloc memory fail,exit."); + return FAIL; + } + + + GTP_INFO("[burn_fw_ss51]Reset first 8K of ss51 to 0xFF."); + GTP_DEBUG("[burn_fw_ss51]step2: reset bank0 0xC000~0xD000"); + memset(fw_ss51, 0xFF, FW_SECTION_LENGTH); + + + GTP_DEBUG("[burn_fw_ss51]step3:clear control flag"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00); + if (ret <= 0) { + GTP_ERROR("[burn_fw_ss51]clear control flag fail."); + ret = FAIL; + goto exit_burn_fw_ss51; + } + + + GTP_DEBUG("[burn_fw_ss51]step4:burn ss51 firmware section 1"); + ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 1 fail."); + goto exit_burn_fw_ss51; + } + + + GTP_DEBUG("[burn_fw_ss51]step5:load ss51 firmware section 2 file data"); + ret = gup_load_section_file(fw_ss51, FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 2 fail."); + goto exit_burn_fw_ss51; + } + + + GTP_DEBUG("[burn_fw_ss51]step6:burn ss51 firmware section 2"); + ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x02); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 2 fail."); + goto exit_burn_fw_ss51; + } + + + GTP_DEBUG("[burn_fw_ss51]step7:load ss51 firmware section 3 file data"); + ret = gup_load_section_file(fw_ss51, 2 * FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 3 fail."); + goto exit_burn_fw_ss51; + } + + + GTP_DEBUG("[burn_fw_ss51]step8:burn ss51 firmware section 3"); + ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x13); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 3 fail."); + goto exit_burn_fw_ss51; + } + + + GTP_DEBUG("[burn_fw_ss51]step9:load ss51 firmware section 4 file data"); + ret = gup_load_section_file(fw_ss51, 3 * FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 4 fail."); + goto exit_burn_fw_ss51; + } + + + GTP_DEBUG("[burn_fw_ss51]step10:burn ss51 firmware section 4"); + ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x14); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 4 fail."); + goto exit_burn_fw_ss51; + } + + update_msg.fw_burned_len += (FW_SECTION_LENGTH*4); + GTP_DEBUG("[burn_fw_ss51]Burned length:%d", update_msg.fw_burned_len); + ret = SUCCESS; + +exit_burn_fw_ss51: + kfree(fw_ss51); + return ret; +} + +static u8 gup_burn_fw_dsp(struct i2c_client *client) +{ + s32 ret = 0; + u8 *fw_dsp = NULL; + u8 retry = 0; + u8 rd_buf[5]; + + GTP_INFO("[burn_fw_dsp]Begin burn dsp firmware---->>"); + + GTP_DEBUG("[burn_fw_dsp]step1:alloc memory"); + while (retry++ < 5) { + fw_dsp = (u8 *)kzalloc(FW_DSP_LENGTH, GFP_KERNEL); + if (fw_dsp == NULL) { + continue; + } else { + GTP_DEBUG("[burn_fw_dsp]Alloc %dk byte memory success.", (FW_SECTION_LENGTH / 1024)); + break; + } + } + if (retry >= 5) { + GTP_ERROR("[burn_fw_dsp]Alloc memory fail,exit."); + return FAIL; + } + + + GTP_DEBUG("[burn_fw_dsp]step2:load firmware dsp"); + ret = gup_load_section_file(fw_dsp, 4 * FW_SECTION_LENGTH, FW_DSP_LENGTH, SEEK_SET); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_dsp]load firmware dsp fail."); + goto exit_burn_fw_dsp; + } + + + GTP_DEBUG("[burn_fw_dsp]step3:select bank3"); + ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03); + if (ret <= 0) { + GTP_ERROR("[burn_fw_dsp]select bank3 fail."); + ret = FAIL; + goto exit_burn_fw_dsp; + } + + + GTP_DEBUG("[burn_fw_dsp]step4:hold ss51 & dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + GTP_ERROR("[burn_fw_dsp]hold ss51 & dsp fail."); + ret = FAIL; + goto exit_burn_fw_dsp; + } + + + GTP_DEBUG("[burn_fw_dsp]step5:set scramble"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); + if (ret <= 0) { + GTP_ERROR("[burn_fw_dsp]set scramble fail."); + ret = FAIL; + goto exit_burn_fw_dsp; + } + + + GTP_DEBUG("[burn_fw_dsp]step6:release ss51 & dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); + if (ret <= 0) { + GTP_ERROR("[burn_fw_dsp]release ss51 & dsp fail."); + ret = FAIL; + goto exit_burn_fw_dsp; + } + + msleep(1); + + + GTP_DEBUG("[burn_fw_dsp]step7:burn 4k dsp firmware"); + ret = gup_burn_proc(client, fw_dsp, 0x9000, FW_DSP_LENGTH); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_dsp]burn fw_section fail."); + goto exit_burn_fw_dsp; + } + + + GTP_DEBUG("[burn_fw_dsp]step8:send burn cmd to move data to flash from sram"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x05); + if (ret <= 0) { + GTP_ERROR("[burn_fw_dsp]send burn cmd fail."); + goto exit_burn_fw_dsp; + } + GTP_DEBUG("[burn_fw_dsp]Wait for the burn is complete......"); + do { + ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); + if (ret <= 0) { + GTP_ERROR("[burn_fw_dsp]Get burn state fail"); + goto exit_burn_fw_dsp; + } + msleep(10); + + } while(rd_buf[GTP_ADDR_LENGTH]); + + + GTP_DEBUG("[burn_fw_dsp]step9:recall check 4k dsp firmware"); + ret = gup_recall_check(client, fw_dsp, 0x9000, FW_DSP_LENGTH); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_dsp]recall check 4k dsp firmware fail."); + goto exit_burn_fw_dsp; + } + + update_msg.fw_burned_len += FW_DSP_LENGTH; + GTP_DEBUG("[burn_fw_dsp]Burned length:%d", update_msg.fw_burned_len); + ret = SUCCESS; + +exit_burn_fw_dsp: + kfree(fw_dsp); + return ret; +} + +static u8 gup_burn_fw_boot(struct i2c_client *client) +{ + s32 ret = 0; + u8 *fw_boot = NULL; + u8 retry = 0; + u8 rd_buf[5]; + + GTP_INFO("[burn_fw_boot]Begin burn bootloader firmware---->>"); + + + GTP_DEBUG("[burn_fw_boot]step1:Alloc memory"); + while (retry++ < 5) { + fw_boot = (u8 *)kzalloc(FW_BOOT_LENGTH, GFP_KERNEL); + if (fw_boot == NULL) { + continue; + } else { + GTP_DEBUG("[burn_fw_boot]Alloc %dk byte memory success.", (FW_BOOT_LENGTH/1024)); + break; + } + } + if (retry >= 5) { + GTP_ERROR("[burn_fw_boot]Alloc memory fail,exit."); + return FAIL; + } + + + GTP_DEBUG("[burn_fw_boot]step2:load firmware bootloader"); + ret = gup_load_section_file(fw_boot, (4 * FW_SECTION_LENGTH + FW_DSP_LENGTH), FW_BOOT_LENGTH, SEEK_SET); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_boot]load firmware bootcode fail."); + goto exit_burn_fw_boot; + } + + + GTP_DEBUG("[burn_fw_boot]step3:hold ss51 & dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + GTP_ERROR("[burn_fw_boot]hold ss51 & dsp fail."); + ret = FAIL; + goto exit_burn_fw_boot; + } + + + GTP_DEBUG("[burn_fw_boot]step4:set scramble"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); + if (ret <= 0) { + GTP_ERROR("[burn_fw_boot]set scramble fail."); + ret = FAIL; + goto exit_burn_fw_boot; + } + + + GTP_DEBUG("[burn_fw_boot]step5:hold ss51 & release dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); + if (ret <= 0) { + GTP_ERROR("[burn_fw_boot]release ss51 & dsp fail."); + ret = FAIL; + goto exit_burn_fw_boot; + } + + msleep(1); + + + GTP_DEBUG("[burn_fw_boot]step6:select bank3"); + ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03); + if (ret <= 0) { + GTP_ERROR("[burn_fw_boot]select bank3 fail."); + ret = FAIL; + goto exit_burn_fw_boot; + } + + + GTP_DEBUG("[burn_fw_boot]step6:burn 2k bootloader firmware"); + ret = gup_burn_proc(client, fw_boot, 0x9000, FW_BOOT_LENGTH); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_boot]burn fw_boot fail."); + goto exit_burn_fw_boot; + } + + + GTP_DEBUG("[burn_fw_boot]step7:send burn cmd to move data to flash from sram"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x06); + if (ret <= 0) { + GTP_ERROR("[burn_fw_boot]send burn cmd fail."); + goto exit_burn_fw_boot; + } + GTP_DEBUG("[burn_fw_boot]Wait for the burn is complete......"); + do { + ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); + if (ret <= 0) { + GTP_ERROR("[burn_fw_boot]Get burn state fail"); + goto exit_burn_fw_boot; + } + msleep(10); + + } while(rd_buf[GTP_ADDR_LENGTH]); + + + GTP_DEBUG("[burn_fw_boot]step8:recall check 2k bootloader firmware"); + ret = gup_recall_check(client, fw_boot, 0x9000, FW_BOOT_LENGTH); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_boot]recall check 2k bootcode firmware fail."); + goto exit_burn_fw_boot; + } + + update_msg.fw_burned_len += FW_BOOT_LENGTH; + GTP_DEBUG("[burn_fw_boot]Burned length:%d", update_msg.fw_burned_len); + ret = SUCCESS; + +exit_burn_fw_boot: + kfree(fw_boot); + return ret; +} +static u8 gup_burn_fw_boot_isp(struct i2c_client *client) +{ + s32 ret = 0; + u8 *fw_boot_isp = NULL; + u8 retry = 0; + u8 rd_buf[5]; + + if (update_msg.fw_burned_len >= update_msg.fw_total_len) { + GTP_DEBUG("No need to upgrade the boot_isp code!"); + return SUCCESS; + } + GTP_INFO("[burn_fw_boot_isp]Begin burn boot_isp firmware---->>"); + + + GTP_DEBUG("[burn_fw_boot_isp]step1:Alloc memory"); + while (retry++ < 5) { + fw_boot_isp = (u8 *)kzalloc(FW_BOOT_ISP_LENGTH, GFP_KERNEL); + if (fw_boot_isp == NULL) { + continue; + } else { + GTP_DEBUG("[burn_fw_boot_isp]Alloc %dk byte memory success.", (FW_BOOT_ISP_LENGTH/1024)); + break; + } + } + if (retry >= 5) { + GTP_ERROR("[burn_fw_boot_isp]Alloc memory fail,exit."); + return FAIL; + } + + + GTP_DEBUG("[burn_fw_boot_isp]step2:load firmware bootloader isp"); + + ret = gup_load_section_file(fw_boot_isp, (update_msg.fw_burned_len - FW_DSP_ISP_LENGTH), FW_BOOT_ISP_LENGTH, SEEK_SET); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_boot_isp]load firmware boot_isp fail."); + goto exit_burn_fw_boot_isp; + } + + + GTP_DEBUG("[burn_fw_boot_isp]step3:hold ss51 & dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + GTP_ERROR("[burn_fw_boot_isp]hold ss51 & dsp fail."); + ret = FAIL; + goto exit_burn_fw_boot_isp; + } + + + GTP_DEBUG("[burn_fw_boot_isp]step4:set scramble"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); + if (ret <= 0) { + GTP_ERROR("[burn_fw_boot_isp]set scramble fail."); + ret = FAIL; + goto exit_burn_fw_boot_isp; + } + + + + GTP_DEBUG("[burn_fw_boot_isp]step5:hold ss51 & release dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); + if (ret <= 0) { + GTP_ERROR("[burn_fw_boot_isp]release ss51 & dsp fail."); + ret = FAIL; + goto exit_burn_fw_boot_isp; + } + + msleep(1); + + + GTP_DEBUG("[burn_fw_boot_isp]step6:select bank3"); + ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03); + if (ret <= 0) { + GTP_ERROR("[burn_fw_boot_isp]select bank3 fail."); + ret = FAIL; + goto exit_burn_fw_boot_isp; + } + + + GTP_DEBUG("[burn_fw_boot_isp]step7:burn 2k bootloader firmware"); + ret = gup_burn_proc(client, fw_boot_isp, 0x9000, FW_BOOT_ISP_LENGTH); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_boot_isp]burn fw_section fail."); + goto exit_burn_fw_boot_isp; + } + + + GTP_DEBUG("[burn_fw_boot_isp]step8:send burn cmd to move data to flash from sram"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x07); + if (ret <= 0) { + GTP_ERROR("[burn_fw_boot_isp]send burn cmd fail."); + goto exit_burn_fw_boot_isp; + } + GTP_DEBUG("[burn_fw_boot_isp]Wait for the burn is complete......"); + do { + ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); + if (ret <= 0) { + GTP_ERROR("[burn_fw_boot_isp]Get burn state fail"); + goto exit_burn_fw_boot_isp; + } + msleep(10); + + } while(rd_buf[GTP_ADDR_LENGTH]); + + + GTP_DEBUG("[burn_fw_boot_isp]step9:recall check 2k bootloader firmware"); + ret = gup_recall_check(client, fw_boot_isp, 0x9000, FW_BOOT_ISP_LENGTH); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_boot_isp]recall check 2k bootcode_isp firmware fail."); + goto exit_burn_fw_boot_isp; + } + + update_msg.fw_burned_len += FW_BOOT_ISP_LENGTH; + GTP_DEBUG("[burn_fw_boot_isp]Burned length:%d", update_msg.fw_burned_len); + ret = SUCCESS; + +exit_burn_fw_boot_isp: + kfree(fw_boot_isp); + return ret; +} + +static u8 gup_burn_fw_link(struct i2c_client *client) +{ + s32 ret = 0; + u8 *fw_link = NULL; + u8 retry = 0; + u32 offset; + + if (update_msg.fw_burned_len >= update_msg.fw_total_len) { + GTP_DEBUG("No need to upgrade the link code!"); + return SUCCESS; + } + GTP_INFO("[burn_fw_link]Begin burn link firmware---->>"); + + + GTP_DEBUG("[burn_fw_link]step1:Alloc memory"); + while (retry++ < 5) { + fw_link = (u8 *)kzalloc(FW_SECTION_LENGTH, GFP_KERNEL); + if (fw_link == NULL) { + continue; + } else { + GTP_DEBUG("[burn_fw_link]Alloc %dk byte memory success.", (FW_SECTION_LENGTH/1024)); + break; + } + } + if (retry >= 5) { + GTP_ERROR("[burn_fw_link]Alloc memory fail,exit."); + return FAIL; + } + + + GTP_DEBUG("[burn_fw_link]step2:load firmware link section 1"); + offset = update_msg.fw_burned_len - FW_DSP_ISP_LENGTH; + ret = gup_load_section_file(fw_link, offset, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_link]load firmware link section 1 fail."); + goto exit_burn_fw_link; + } + + + GTP_DEBUG("[burn_fw_link]step3:burn link firmware section 1"); + ret = gup_burn_fw_gwake_section(client, fw_link, 0x9000, FW_SECTION_LENGTH, 0x38); + + if (FAIL == ret) { + GTP_ERROR("[burn_fw_link]burn link firmware section 1 fail."); + goto exit_burn_fw_link; + } + + + GTP_DEBUG("[burn_fw_link]step4:load link firmware section 2 file data"); + offset += FW_SECTION_LENGTH; + ret = gup_load_section_file(fw_link, offset, FW_GLINK_LENGTH - FW_SECTION_LENGTH, SEEK_SET); + + if (FAIL == ret) { + GTP_ERROR("[burn_fw_link]load link firmware section 2 fail."); + goto exit_burn_fw_link; + } + + + GTP_DEBUG("[burn_fw_link]step4:burn link firmware section 2"); + ret = gup_burn_fw_gwake_section(client, fw_link, 0x9000, FW_GLINK_LENGTH - FW_SECTION_LENGTH, 0x39); + + if (FAIL == ret) { + GTP_ERROR("[burn_fw_link]burn link firmware section 2 fail."); + goto exit_burn_fw_link; + } + + update_msg.fw_burned_len += FW_GLINK_LENGTH; + GTP_DEBUG("[burn_fw_link]Burned length:%d", update_msg.fw_burned_len); + ret = SUCCESS; + +exit_burn_fw_link: + kfree(fw_link); + return ret; +} + +static u8 gup_burn_fw_gwake_section(struct i2c_client *client, u8 *fw_section, u16 start_addr, u32 len, u8 bank_cmd) +{ + s32 ret = 0; + u8 rd_buf[5]; + + + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + GTP_ERROR("[burn_fw_app_section]hold ss51 & dsp fail."); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); + if (ret <= 0) { + GTP_ERROR("[burn_fw_app_section]set scramble fail."); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); + if (ret <= 0) { + GTP_ERROR("[burn_fw_app_section]hold ss51 & release dsp fail."); + return FAIL; + } + + msleep(1); + + + ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, (bank_cmd >> 4)&0x0F); + if (ret <= 0) { + GTP_ERROR("[burn_fw_section]select bank %d fail.", (bank_cmd >> 4)&0x0F); + return FAIL; + } + + + ret = gup_burn_proc(client, fw_section, start_addr, len); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_app_section]burn fw_section fail."); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0F); + if (ret <= 0) { + GTP_ERROR("[burn_fw_app_section]send burn cmd fail."); + return FAIL; + } + GTP_DEBUG("[burn_fw_section]Wait for the burn is complete......"); + do { + ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); + if (ret <= 0) { + GTP_ERROR("[burn_fw_app_section]Get burn state fail"); + return FAIL; + } + msleep(10); + + } while(rd_buf[GTP_ADDR_LENGTH]); + + + ret = gup_recall_check(client, fw_section, start_addr, len); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_app_section]recall check %dk firmware fail.", len/1024); + return FAIL; + } + + return SUCCESS; +} + +static u8 gup_burn_fw_gwake(struct i2c_client *client) +{ + u8 *fw_gwake = NULL; + u8 retry = 0; + s32 ret = 0; + u16 start_index = 4*FW_SECTION_LENGTH+FW_DSP_LENGTH+FW_BOOT_LENGTH + FW_BOOT_ISP_LENGTH + FW_GLINK_LENGTH; + + + if (update_msg.fw_burned_len >= update_msg.fw_total_len) { + GTP_DEBUG("No need to upgrade the gwake code!"); + return SUCCESS; + } + + GTP_INFO("[burn_fw_gwake]Begin burn gwake firmware---->>"); + + + GTP_DEBUG("[burn_fw_gwake]step1:alloc memory"); + while (retry++ < 5) { + fw_gwake = (u8 *)kzalloc(FW_SECTION_LENGTH, GFP_KERNEL); + if (fw_gwake == NULL) { + continue; + } else { + GTP_DEBUG("[burn_fw_gwake]Alloc %dk byte memory success.", (FW_SECTION_LENGTH/1024)); + break; + } + } + if (retry >= 5) { + GTP_ERROR("[burn_fw_gwake]Alloc memory fail,exit."); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00); + if (ret <= 0) { + GTP_ERROR("[burn_fw_finish]clear control flag fail."); + goto exit_burn_fw_gwake; + } + + + GTP_DEBUG("[burn_fw_gwake]step2:load app_code firmware section 1 file data"); + ret = gup_load_section_file(fw_gwake, start_index, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_gwake]load app_code firmware section 1 fail."); + goto exit_burn_fw_gwake; + } + + + GTP_DEBUG("[burn_fw_gwake]step3:burn app_code firmware section 1"); + ret = gup_burn_fw_gwake_section(client, fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3A); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_gwake]burn app_code firmware section 1 fail."); + goto exit_burn_fw_gwake; + } + + + GTP_DEBUG("[burn_fw_gwake]step5:load app_code firmware section 2 file data"); + ret = gup_load_section_file(fw_gwake, start_index+FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_gwake]load app_code firmware section 2 fail."); + goto exit_burn_fw_gwake; + } + + + GTP_DEBUG("[burn_fw_gwake]step6:burn app_code firmware section 2"); + ret = gup_burn_fw_gwake_section(client, fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3B); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_gwake]burn app_code firmware section 2 fail."); + goto exit_burn_fw_gwake; + } + + + GTP_DEBUG("[burn_fw_gwake]step7:load app_code firmware section 3 file data"); + ret = gup_load_section_file(fw_gwake, start_index+2*FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_gwake]load app_code firmware section 3 fail."); + goto exit_burn_fw_gwake; + } + + + GTP_DEBUG("[burn_fw_gwake]step8:burn app_code firmware section 3"); + ret = gup_burn_fw_gwake_section(client, fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3C); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_gwake]burn app_code firmware section 3 fail."); + goto exit_burn_fw_gwake; + } + + + GTP_DEBUG("[burn_fw_gwake]step9:load app_code firmware section 4 file data"); + ret = gup_load_section_file(fw_gwake, start_index + 3*FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_gwake]load app_code firmware section 4 fail."); + goto exit_burn_fw_gwake; + } + + + GTP_DEBUG("[burn_fw_gwake]step10:burn app_code firmware section 4"); + ret = gup_burn_fw_gwake_section(client, fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3D); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_gwake]burn app_code firmware section 4 fail."); + goto exit_burn_fw_gwake; + } + + + GTP_DEBUG("[burn_fw_gwake]Burned length:%d", update_msg.fw_burned_len); + ret = SUCCESS; + +exit_burn_fw_gwake: + kfree(fw_gwake); + return ret; +} + +static u8 gup_burn_fw_finish(struct i2c_client *client) +{ + u8 *fw_ss51 = NULL; + u8 retry = 0; + s32 ret = 0; + + GTP_INFO("[burn_fw_finish]burn first 8K of ss51 and finish update."); + + GTP_DEBUG("[burn_fw_finish]step1:alloc memory"); + while (retry++ < 5) { + fw_ss51 = (u8 *)kzalloc(FW_SECTION_LENGTH, GFP_KERNEL); + if (fw_ss51 == NULL) { + continue; + } else { + GTP_DEBUG("[burn_fw_finish]Alloc %dk byte memory success.", (FW_SECTION_LENGTH/1024)); + break; + } + } + if (retry >= 5) { + GTP_ERROR("[burn_fw_finish]Alloc memory fail,exit."); + return FAIL; + } + + GTP_DEBUG("[burn_fw_finish]step2: burn ss51 first 8K."); + ret = gup_load_section_file(fw_ss51, 0, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_finish]load ss51 firmware section 1 fail."); + goto exit_burn_fw_finish; + } + + GTP_DEBUG("[burn_fw_finish]step3:clear control flag"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00); + if (ret <= 0) { + GTP_ERROR("[burn_fw_finish]clear control flag fail."); + goto exit_burn_fw_finish; + } + + GTP_DEBUG("[burn_fw_finish]step4:burn ss51 firmware section 1"); + ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01); + if (FAIL == ret) { + GTP_ERROR("[burn_fw_finish]burn ss51 firmware section 1 fail."); + goto exit_burn_fw_finish; + } + + + GTP_DEBUG("[burn_fw_finish]step5:enable download DSP code "); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x99); + if (ret <= 0) { + GTP_ERROR("[burn_fw_finish]enable download DSP code fail."); + goto exit_burn_fw_finish; + } + + + GTP_DEBUG("[burn_fw_finish]step6:release ss51 & hold dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x08); + if (ret <= 0) { + GTP_ERROR("[burn_fw_finish]release ss51 & hold dsp fail."); + goto exit_burn_fw_finish; + } + + if (fw_ss51) { + kfree(fw_ss51); + } + return SUCCESS; + +exit_burn_fw_finish: + if (fw_ss51) { + kfree(fw_ss51); + } + return FAIL; +} +s32 gup_update_proc(void *dir) +{ + s32 ret = 0; + s32 update_ret = FAIL; + u8 retry = 0; + st_fw_head fw_head; + struct goodix_ts_data *ts = NULL; + + GTP_DEBUG("[update_proc]Begin update ......"); + + ts = i2c_get_clientdata(i2c_connect_client); + +#if GTP_AUTO_UPDATE + if (searching_file) { + u8 timeout = 0; + searching_file = 0; + GTP_INFO("Exiting searching .bin update file..."); + while ((show_len != 200) && (show_len != 100) && (timeout++ < 100)) { + msleep(100); + } + } +#endif + + show_len = 1; + total_len = 100; + +#if GTP_COMPATIBLE_MODE + if (CHIP_TYPE_GT9F == ts->chip_type) { + return gup_fw_download_proc(dir, GTP_FL_FW_BURN); + } +#endif + + update_msg.file = NULL; + ret = gup_check_update_file(i2c_connect_client, &fw_head, (u8 *)dir); + if (FAIL == ret) { + GTP_ERROR("[update_proc]check update file fail."); + goto file_fail; + } + + ret = gup_get_ic_fw_msg(i2c_connect_client); + if (FAIL == ret) { + GTP_ERROR("[update_proc]get ic message fail."); + goto file_fail; + } + + ret = gup_enter_update_judge(&fw_head); + if (FAIL == ret) { + GTP_ERROR("[update_proc]Check *.bin file fail."); + goto file_fail; + } + + ts->enter_update = 1; + gtp_irq_disable(ts); +#if GTP_ESD_PROTECT + gtp_esd_switch(ts->client, SWITCH_OFF); +#endif + ret = gup_enter_update_mode(i2c_connect_client); + if (FAIL == ret) { + GTP_ERROR("[update_proc]enter update mode fail."); + goto update_fail; + } + + while (retry++ < 5) { + show_len = 10; + total_len = 100; + update_msg.fw_burned_len = 0; + ret = gup_burn_dsp_isp(i2c_connect_client); + if (FAIL == ret) { + GTP_ERROR("[update_proc]burn dsp isp fail."); + continue; + } + + show_len = 20; + ret = gup_burn_fw_gwake(i2c_connect_client); + if (FAIL == ret) { + GTP_ERROR("[update_proc]burn app_code firmware fail."); + continue; + } + + show_len = 30; + ret = gup_burn_fw_ss51(i2c_connect_client); + if (FAIL == ret) { + GTP_ERROR("[update_proc]burn ss51 firmware fail."); + continue; + } + + show_len = 40; + ret = gup_burn_fw_dsp(i2c_connect_client); + if (FAIL == ret) { + GTP_ERROR("[update_proc]burn dsp firmware fail."); + continue; + } + + show_len = 50; + ret = gup_burn_fw_boot(i2c_connect_client); + if (FAIL == ret) { + GTP_ERROR("[update_proc]burn bootloader firmware fail."); + continue; + } + show_len = 60; + + ret = gup_burn_fw_boot_isp(i2c_connect_client); + if (FAIL == ret) { + GTP_ERROR("[update_proc]burn boot_isp firmware fail."); + continue; + } + + show_len = 70; + ret = gup_burn_fw_link(i2c_connect_client); + if (FAIL == ret) { + GTP_ERROR("[update_proc]burn link firmware fail."); + continue; + } + + show_len = 80; + ret = gup_burn_fw_finish(i2c_connect_client); + if (FAIL == ret) { + GTP_ERROR("[update_proc]burn finish fail."); + continue; + } + show_len = 90; + GTP_INFO("[update_proc]UPDATE SUCCESS."); + retry = 0; + break; + } + if (retry >= 5) { + GTP_ERROR("[update_proc]retry timeout,UPDATE FAIL."); + update_ret = FAIL; + } else { + update_ret = SUCCESS; + } + +update_fail: + GTP_DEBUG("[update_proc]leave update mode."); + gup_leave_update_mode(); + + msleep(100); + + if (SUCCESS == update_ret) { + if (ts->fw_error) { + GTP_INFO("firmware error auto update, resent config!"); + gup_init_panel(ts); + } else { + GTP_DEBUG("[update_proc]send config."); + ret = gtp_send_cfg(i2c_connect_client); + if (ret < 0) { + GTP_ERROR("[update_proc]send config fail."); + } else { + msleep(100); + } + } + } + ts->enter_update = 0; + gtp_irq_enable(ts); + +#if GTP_ESD_PROTECT + gtp_esd_switch(ts->client, SWITCH_ON); +#endif + +file_fail: + if (update_msg.file && !IS_ERR(update_msg.file)) { + if (update_msg.old_fs) { + set_fs(update_msg.old_fs); + } + filp_close(update_msg.file, NULL); + } +#if (GTP_AUTO_UPDATE && GTP_AUTO_UPDATE_CFG && GTP_HEADER_FW_UPDATE) + if (NULL == dir) { + gup_search_file(AUTO_SEARCH_CFG); + if (got_file_flag & CFG_FILE_READY) { + ret = gup_update_config(i2c_connect_client); + if (ret <= 0) { + GTP_ERROR("Update config failed."); + } + _CLOSE_FILE(update_msg.cfg_file); + msleep(500); + } + } +#endif + + total_len = 100; + if (SUCCESS == update_ret) { + show_len = 100; + return SUCCESS; + } else { + show_len = 200; + return FAIL; + } +} + +#if GTP_AUTO_UPDATE +u8 gup_init_update_proc(struct goodix_ts_data *ts) +{ + struct task_struct *thread = NULL; + + GTP_INFO("Ready to run update thread."); + +#if GTP_COMPATIBLE_MODE + if (CHIP_TYPE_GT9F == ts->chip_type) { + thread = kthread_run(gup_update_proc, "update", "fl update"); + } else +#endif + { + thread = kthread_run(gup_update_proc, (void *)NULL, "guitar_update"); + } + if (IS_ERR(thread)) { + GTP_ERROR("Failed to create update thread.\n"); + return -EPERM; + } + + return 0; +} +#endif + + + +#define FW_DOWNLOAD_LENGTH 0x4000 +#define FW_SS51_SECTION_LEN 0x2000 +#define FL_PACK_SIZE 1024 +#define GUP_FW_CHK_SIZE FL_PACK_SIZE + +#define FL_UPDATE_PATH "/data/_fl_update_.bin" +#define FL_UPDATE_PATH_SD "/sdcard/_fl_update_.bin" + +#define PULSE_LENGTH (200) +#define INIT_CLK_DAC (50) +#define MAX_CLK_DAC (120) +#define CLK_AVG_TIME (1) +#define MILLION 1000000 + +#define _wRW_MISCTL__RG_DMY 0x4282 +#define _bRW_MISCTL__RG_OSC_CALIB 0x4268 +#define _fRW_MISCTL__GIO0 0x41e9 +#define _fRW_MISCTL__GIO1 0x41ed +#define _fRW_MISCTL__GIO2 0x41f1 +#define _fRW_MISCTL__GIO3 0x41f5 +#define _fRW_MISCTL__GIO4 0x41f9 +#define _fRW_MISCTL__GIO5 0x41fd +#define _fRW_MISCTL__GIO6 0x4201 +#define _fRW_MISCTL__GIO7 0x4205 +#define _fRW_MISCTL__GIO8 0x4209 +#define _fRW_MISCTL__GIO9 0x420d +#define _fRW_MISCTL__MEA 0x41a0 +#define _bRW_MISCTL__MEA_MODE 0x41a1 +#define _wRW_MISCTL__MEA_MAX_NUM 0x41a4 +#define _dRO_MISCTL__MEA_VAL 0x41b0 +#define _bRW_MISCTL__MEA_SRCSEL 0x41a3 +#define _bRO_MISCTL__MEA_RDY 0x41a8 +#define _rRW_MISCTL__ANA_RXADC_B0_ 0x4250 +#define _bRW_MISCTL__RG_LDO_A18_PWD 0x426f +#define _bRW_MISCTL__RG_BG_PWD 0x426a +#define _bRW_MISCTL__RG_CLKGEN_PWD 0x4269 +#define _fRW_MISCTL__RG_RXADC_PWD 0x426a +#define _bRW_MISCTL__OSC_CK_SEL 0x4030 +#define _rRW_MISCTL_RG_DMY83 0x4283 +#define _rRW_MISCTL__GIO1CTL_B2_ 0x41ee +#define _rRW_MISCTL__GIO1CTL_B1_ 0x41ed + + +#if GTP_COMPATIBLE_MODE + +u8 i2c_opr_buf[GTP_ADDR_LENGTH + FL_PACK_SIZE] = {0}; +u8 chk_cmp_buf[FL_PACK_SIZE] = {0}; + +extern s32 gtp_fw_startup(struct i2c_client *client); +static u8 gup_download_fw_dsp(struct i2c_client *client, u8 dwn_mode); +static s32 gup_burn_fw_proc(struct i2c_client *client, u16 start_addr, s32 start_index, s32 burn_len); +static s32 gup_check_and_repair(struct i2c_client *client, u16 start_addr, s32 start_index, s32 chk_len); + + + + +u8 gup_check_fs_mounted(char *path_name) +{ + struct path root_path; + struct path path; + int err = -1; + err = kern_path("/", LOOKUP_FOLLOW, &root_path); + + if (err) { + GTP_DEBUG("\"/\" NOT Mounted: %d", err); + return FAIL; + } + err = kern_path(path_name, LOOKUP_FOLLOW, &path); + + if (err) { + GTP_DEBUG("%s NOT Mounted: %d", path_name, err); + err = FAIL; + goto exit_chk; + } + + if (path.mnt->mnt_sb == root_path.mnt->mnt_sb) { + err = FAIL; + } else { + err = SUCCESS; + } + + path_put(&path); +exit_chk: + path_put(&root_path); + return err; +} + +s32 i2c_write_bytes(struct i2c_client *client, u16 addr, u8 *buf, s32 len) +{ + s32 ret = 0; + s32 write_bytes = 0; + s32 retry = 0; + u8 *tx_buf = buf; + + while (len > 0) { + i2c_opr_buf[0] = (u8)(addr >> 8); + i2c_opr_buf[1] = (u8)(addr & 0xFF); + if (len > FL_PACK_SIZE) { + write_bytes = FL_PACK_SIZE; + } else { + write_bytes = len; + } + memcpy(i2c_opr_buf + 2, tx_buf, write_bytes); + for (retry = 0; retry < 5; ++retry) { + ret = gup_i2c_write(client, i2c_opr_buf, write_bytes + GTP_ADDR_LENGTH); + if (ret == 1) { + break; + } + } + if (retry >= 5) { + GTP_ERROR("retry timeout, I2C write 0x%04X %d bytes failed!", addr, write_bytes); + return -EPERM; + } + addr += write_bytes; + len -= write_bytes; + tx_buf += write_bytes; + } + + return 1; +} + +s32 i2c_read_bytes(struct i2c_client *client, u16 addr, u8 *buf, s32 len) +{ + s32 ret = 0; + s32 read_bytes = 0; + s32 retry = 0; + u8 *tx_buf = buf; + + while (len > 0) { + i2c_opr_buf[0] = (u8)(addr >> 8); + i2c_opr_buf[1] = (u8)(addr & 0xFF); + if (len > FL_PACK_SIZE) { + read_bytes = FL_PACK_SIZE; + } else { + read_bytes = len; + } + for (retry = 0; retry < 5; ++retry) { + ret = gup_i2c_read(client, i2c_opr_buf, read_bytes + GTP_ADDR_LENGTH); + if (ret == 2) { + break; + } + } + if (retry >= 5) { + GTP_ERROR("retry timeout, I2C read 0x%04X %d bytes failed!", addr, read_bytes); + return -EPERM; + } + memcpy(tx_buf, i2c_opr_buf + 2, read_bytes); + addr += read_bytes; + len -= read_bytes; + tx_buf += read_bytes; + } + return 2; +} + + + + + +static void gup_bit_write(s32 addr, s32 bit, s32 val) +{ + u8 buf; + i2c_read_bytes(i2c_connect_client, addr, &buf, 1); + + buf = (buf & (~((u8)1 << bit))) | ((u8)val << bit); + + i2c_write_bytes(i2c_connect_client, addr, &buf, 1); +} + +static void gup_clk_count_init(s32 bCh, s32 bCNT) +{ + u8 buf; + + + gup_bit_write(_fRW_MISCTL__MEA, 0, 0); + + gup_bit_write(_fRW_MISCTL__MEA, 1, 1); + + buf = 0; + i2c_write_bytes(i2c_connect_client, _bRW_MISCTL__MEA_MODE, &buf, 1); + + buf = 8 + bCh; + i2c_write_bytes(i2c_connect_client, _bRW_MISCTL__MEA_SRCSEL, &buf, 1); + + buf = bCNT; + i2c_write_bytes(i2c_connect_client, _wRW_MISCTL__MEA_MAX_NUM, &buf, 1); + + gup_bit_write(_fRW_MISCTL__MEA, 1, 0); + + gup_bit_write(_fRW_MISCTL__MEA, 0, 1); +} + +static u32 gup_clk_count_get(void) +{ + s32 ready = 0; + s32 temp; + s8 buf[4]; + + while ((ready == 0)) { + i2c_read_bytes(i2c_connect_client, _bRO_MISCTL__MEA_RDY, buf, 1); + ready = buf[0]; + } + + msleep(50); + + + gup_bit_write(_fRW_MISCTL__MEA, 0, 0); + i2c_read_bytes(i2c_connect_client, _dRO_MISCTL__MEA_VAL, buf, 4); + GTP_DEBUG("Clk_count 0: %2X", buf[0]); + GTP_DEBUG("Clk_count 1: %2X", buf[1]); + GTP_DEBUG("Clk_count 2: %2X", buf[2]); + GTP_DEBUG("Clk_count 3: %2X", buf[3]); + + temp = (s32)buf[0] + ((s32)buf[1] << 8) + ((s32)buf[2] << 16) + ((s32)buf[3] << 24); + GTP_INFO("Clk_count : %d", temp); + return temp; +} +u8 gup_clk_dac_setting(int dac) +{ + s8 buf1, buf2; + + i2c_read_bytes(i2c_connect_client, _wRW_MISCTL__RG_DMY, &buf1, 1); + i2c_read_bytes(i2c_connect_client, _bRW_MISCTL__RG_OSC_CALIB, &buf2, 1); + + buf1 = (buf1 & 0xFFCF) | ((dac & 0x03) << 4); + buf2 = (dac >> 2) & 0x3f; + + i2c_write_bytes(i2c_connect_client, _wRW_MISCTL__RG_DMY, &buf1, 1); + i2c_write_bytes(i2c_connect_client, _bRW_MISCTL__RG_OSC_CALIB, &buf2, 1); + + return 0; +} + +static u8 gup_clk_calibration_pin_select(s32 bCh) +{ + s32 i2c_addr; + + switch (bCh) { + case 0: + i2c_addr = _fRW_MISCTL__GIO0; + break; + + case 1: + i2c_addr = _fRW_MISCTL__GIO1; + break; + + case 2: + i2c_addr = _fRW_MISCTL__GIO2; + break; + + case 3: + i2c_addr = _fRW_MISCTL__GIO3; + break; + + case 4: + i2c_addr = _fRW_MISCTL__GIO4; + break; + + case 5: + i2c_addr = _fRW_MISCTL__GIO5; + break; + + case 6: + i2c_addr = _fRW_MISCTL__GIO6; + break; + + case 7: + i2c_addr = _fRW_MISCTL__GIO7; + break; + + case 8: + i2c_addr = _fRW_MISCTL__GIO8; + break; + + case 9: + i2c_addr = _fRW_MISCTL__GIO9; + break; + } + + gup_bit_write(i2c_addr, 1, 0); + + return 0; +} + +void gup_output_pulse(int t) +{ + unsigned long flags; + + + GTP_GPIO_OUTPUT(gtp_int_gpio, 0); + msleep(10); + + local_irq_save(flags); + + GTP_GPIO_OUTPUT(gtp_int_gpio, 1); + msleep(50); + GTP_GPIO_OUTPUT(gtp_int_gpio, 0); + msleep(t - 50); + GTP_GPIO_OUTPUT(gtp_int_gpio, 1); + + local_irq_restore(flags); + + msleep(20); + GTP_GPIO_OUTPUT(gtp_int_gpio, 0); +} + +static void gup_sys_clk_init(void) +{ + u8 buf; + + + gup_bit_write(_rRW_MISCTL__ANA_RXADC_B0_, 5, 0); + + buf = 0; + i2c_write_bytes(i2c_connect_client, _bRW_MISCTL__RG_LDO_A18_PWD, &buf, 1); + + buf = 0; + i2c_write_bytes(i2c_connect_client, _bRW_MISCTL__RG_BG_PWD, &buf, 1); + + buf = 0; + i2c_write_bytes(i2c_connect_client, _bRW_MISCTL__RG_CLKGEN_PWD, &buf, 1); + + gup_bit_write(_rRW_MISCTL__ANA_RXADC_B0_, 0, 0); + + gup_bit_write(_rRW_MISCTL__ANA_RXADC_B0_, 1, 0); + + + buf = 1; + i2c_write_bytes(i2c_connect_client, _bRW_MISCTL__OSC_CK_SEL, &buf, 1); +} + +s32 gup_clk_calibration(void) +{ + u8 buf; + + s32 i; + struct timeval start, end; + s32 count; + s32 count_ref; + s32 sec; + s32 usec; + + struct goodix_ts_data *ts; + + buf = 0x0C; + i2c_write_bytes(i2c_connect_client, _rRW_MISCTL__SWRST_B0_, &buf, 1); + gup_bit_write(_rRW_MISCTL_RG_DMY83, 7, 0); + gup_bit_write(_rRW_MISCTL__GIO1CTL_B2_, 0, 0); + gup_bit_write(_rRW_MISCTL__GIO1CTL_B1_, 1, 0); + + GTP_INFO("CLK calibration GO"); + gup_sys_clk_init(); + gup_clk_calibration_pin_select(1); + + GTP_GPIO_OUTPUT(gtp_int_gpio, 0); + + ts = i2c_get_clientdata(i2c_connect_client); + + for (i = INIT_CLK_DAC; i < MAX_CLK_DAC; i++) { + GTP_INFO("CLK calibration DAC %d", i); + + if (ts->gtp_is_suspend) { + i = 72; + break; + } + + gup_clk_dac_setting(i); + gup_clk_count_init(1, CLK_AVG_TIME); + + GTP_GPIO_OUTPUT(gtp_int_gpio, 0); + + + do_gettimeofday(&start); + GTP_GPIO_OUTPUT(gtp_int_gpio, 1); + + + msleep(1); + GTP_GPIO_OUTPUT(gtp_int_gpio, 0); + msleep(1); + + + do_gettimeofday(&end); + GTP_GPIO_OUTPUT(gtp_int_gpio, 1); + + + count = gup_clk_count_get(); + msleep(20); + GTP_GPIO_OUTPUT(gtp_int_gpio, 0); + + usec = end.tv_usec - start.tv_usec; + sec = end.tv_sec - start.tv_sec; + count_ref = 60 * (usec + sec * MILLION); + + GTP_DEBUG("== time %d, %d, %d", sec, usec, count_ref); + + if (count > count_ref) { + GTP_DEBUG("== count_diff %d", count - count_ref); + break; + } + } + + gtp_reset_guitar(i2c_connect_client, 20); + + GTP_GPIO_AS_INT(gtp_int_gpio); + return i; +} + +s32 gup_hold_ss51_dsp(struct i2c_client *client) +{ + s32 ret = -1; + s32 retry = 0; + u8 rd_buf[3]; + + while (retry++ < 200) { + + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + GTP_DEBUG("Hold ss51 & dsp I2C error,retry:%d", retry); + continue; + } + + + ret = gup_get_ic_msg(client, _rRW_MISCTL__SWRST_B0_, rd_buf, 1); + if (ret <= 0) { + GTP_DEBUG("Hold ss51 & dsp I2C error,retry:%d", retry); + continue; + } + if (0x0C == rd_buf[GTP_ADDR_LENGTH]) { + GTP_DEBUG("[enter_update_mode]Hold ss51 & dsp confirm SUCCESS"); + break; + } + GTP_DEBUG("Hold ss51 & dsp confirm 0x4180 failed,value:%d", rd_buf[GTP_ADDR_LENGTH]); + } + if (retry >= 200) { + GTP_ERROR("Enter update Hold ss51 failed."); + return FAIL; + } + + ret = gup_set_ic_msg(client, 0x4010, 0x00); + if (ret <= 0) { + GTP_ERROR("[enter_update_mode]DSP_CK and DSP_ALU_CK PowerOn fail."); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _bRW_MISCTL__TMR0_EN, 0x00); + + if (ret <= 0) { + GTP_ERROR("[enter_update_mode]disable wdt fail."); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _bRW_MISCTL__CACHE_EN, 0x00); + + if (ret <= 0) { + GTP_ERROR("[enter_update_mode]clear cache enable fail."); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOTCTL_B0_, 0x02); + + if (ret <= 0) { + GTP_ERROR("[enter_update_mode]set boot from sram fail."); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _bWO_MISCTL__CPU_SWRST_PULSE, 0x01); + if (ret <= 0) { + GTP_ERROR("[enter_update_mode]software reboot fail."); + return FAIL; + } + + return SUCCESS; +} + +s32 gup_enter_update_mode_fl(struct i2c_client *client) +{ + s32 ret = -1; + + GTP_GPIO_OUTPUT(gtp_rst_gpio, 0); + msleep(2); + + GTP_GPIO_OUTPUT(gtp_int_gpio, (client->addr == 0x14)); + msleep(2); + + GTP_GPIO_OUTPUT(gtp_rst_gpio, 1); + + msleep(5); + + ret = gup_hold_ss51_dsp(client); + if (ret <= 0) { + GTP_ERROR("[enter_update_mode]hold ss51 & dsp failed."); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00); + + if (ret <= 0) { + GTP_ERROR("[enter_update_mode]clear control flag fail."); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); + + if (ret <= 0) { + GTP_ERROR("[enter_update_mode]set scramble fail."); + return FAIL; + } + + + ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); + + if (ret <= 0) { + GTP_ERROR("[enter_update_mode]enable accessing code fail."); + return FAIL; + } + + return SUCCESS; +} + +static u8 gup_download_fw_dsp(struct i2c_client *client, u8 dwn_mode) +{ + s32 ret = 0; + + + GTP_DEBUG("[download_fw_dsp]step1:select bank2"); + ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x02); + if (ret == FAIL) { + GTP_ERROR("select bank 2 fail"); + return FAIL; + } + + if (GTP_FL_FW_BURN == dwn_mode) { + GTP_INFO("[download_fw_dsp]Begin download dsp fw---->>"); + + if (ret <= 0) { + GTP_ERROR("[download_fw_dsp]select bank2 fail."); + return FAIL; + } + GTP_DEBUG("burn fw dsp"); + ret = gup_burn_fw_proc(client, 0xC000, 2 * FW_DOWNLOAD_LENGTH, FW_DSP_LENGTH); + if (FAIL == ret) { + GTP_ERROR("[download_fw_dsp]download FW dsp fail."); + return FAIL; + } + GTP_INFO("check firmware dsp"); + ret = gup_check_and_repair(client, 0xC000, 2 * FW_DOWNLOAD_LENGTH, FW_DSP_LENGTH); + if (FAIL == ret) { + GTP_ERROR("check fw dsp failed!"); + return FAIL; + } + } else if (GTP_FL_ESD_RECOVERY == dwn_mode) { + GTP_INFO("[download_fw_dsp]Begin esd check dsp fw---->>"); + + + + + { + + GTP_INFO("esd recovery redownload firmware dsp code"); + ret = gup_burn_fw_proc(client, 0xC000, 2 * FW_DOWNLOAD_LENGTH, FW_DSP_LENGTH); + if (FAIL == ret) { + GTP_ERROR("redownload fw dsp failed!"); + return FAIL; + } + } + } else { + GTP_INFO("check firmware dsp"); + ret = gup_check_and_repair(client, 0xC000, 2 * FW_DOWNLOAD_LENGTH, FW_DSP_LENGTH); + if (FAIL == ret) { + GTP_ERROR("check fw dsp failed!"); + return FAIL; + } + } + return SUCCESS; +} + +static s32 gup_burn_fw_proc(struct i2c_client *client, u16 start_addr, s32 start_index, s32 burn_len) +{ + s32 ret = 0; + GTP_DEBUG("burn firmware: 0x%04X, %d bytes, start_index: 0x%04X", start_addr, burn_len, start_index); + + ret = i2c_write_bytes(client, start_addr, (u8*)>915_FW_fl[FW_HEAD_LENGTH + start_index], burn_len); + if (ret < 0) { + GTP_ERROR("burn 0x%04X, %d bytes failed!", start_addr, burn_len); + return FAIL; + } + return SUCCESS; +} + +static s32 gup_check_and_repair(struct i2c_client *client, u16 start_addr, s32 start_index, s32 chk_len) +{ + s32 ret = 0; + s32 cmp_len = 0; + u16 cmp_addr = start_addr; + s32 i = 0; + s32 chked_times = 0; + u8 chk_fail = 0; + + GTP_DEBUG("check firmware: start 0x%04X, %d bytes", start_addr, chk_len); + while ((chk_len > 0) && (chked_times < GTP_CHK_FW_MAX)) { + if (chk_len >= GUP_FW_CHK_SIZE) { + cmp_len = GUP_FW_CHK_SIZE; + } else { + cmp_len = chk_len; + } + ret = i2c_read_bytes(client, cmp_addr, chk_cmp_buf, cmp_len); + if (ret < 0) { + chk_fail = 1; + break; + } + for (i = 0; i < cmp_len; ++i) { + if (chk_cmp_buf[i] != gt915_FW_fl[FW_HEAD_LENGTH + start_index + i]) { + chk_fail = 1; + i2c_write_bytes(client, cmp_addr+i, >915_FW_fl[FW_HEAD_LENGTH + start_index + i], cmp_len-i); + GTP_ERROR("Check failed index: %d(%d != %d), redownload chuck", i, chk_cmp_buf[i], + gt915_FW_fl[FW_HEAD_LENGTH + start_index +i]); + break; + } + } + if (chk_fail == 1) { + chk_fail = 0; + chked_times++; + } else { + cmp_addr += cmp_len; + start_index += cmp_len; + chk_len -= cmp_len; + } + } + if (chk_len > 0) { + GTP_ERROR("cmp_addr: 0x%04X, start_index: 0x%02X, chk_len: 0x%04X", cmp_addr, + start_index, chk_len); + return FAIL; + } + return SUCCESS; +} + +static u8 gup_download_fw_ss51(struct i2c_client *client, u8 dwn_mode) +{ + s32 section = 0; + s32 ret = 0; + s32 start_index = 0; + u8 bank = 0; + u16 burn_addr = 0xC000; + + if (GTP_FL_FW_BURN == dwn_mode) { + GTP_INFO("download firmware ss51"); + } else { + GTP_INFO("check firmware ss51"); + } + for (section = 1; section <= 4; section += 2) { + switch (section) { + case 1: + bank = 0x00; + burn_addr = (section - 1) * FW_SS51_SECTION_LEN + 0xC000; + break; + case 3: + bank = 0x01; + burn_addr = (section - 3) * FW_SS51_SECTION_LEN + 0xC000; + break; + } + start_index = (section - 1) * FW_SS51_SECTION_LEN; + + GTP_DEBUG("download firmware ss51: select bank%d", bank); + ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, bank); + if (GTP_FL_FW_BURN == dwn_mode) { + GTP_DEBUG("download firmware ss51 section%d & %d", section, section+1); + ret = gup_burn_fw_proc(client, burn_addr, start_index, 2 * FW_SS51_SECTION_LEN); + if (ret == FAIL) { + GTP_ERROR("download fw ss51 section%d & %d failed!", section, section+1); + return FAIL; + } + GTP_DEBUG("check firmware ss51 section%d & %d", section, section+1); + ret = gup_check_and_repair(client, burn_addr, start_index, 2 * FW_SS51_SECTION_LEN); + if (ret == FAIL) { + GTP_ERROR("check ss51 section%d & %d failed!", section, section+1); + return FAIL; + } + } else if (GTP_FL_ESD_RECOVERY == dwn_mode) { + + + + { + + GTP_DEBUG("esd recovery redownload ss51 section%d & %d", section, section+1); + ret = gup_burn_fw_proc(client, burn_addr, start_index, 2 * FW_SS51_SECTION_LEN); + if (ret == FAIL) { + GTP_ERROR("download fw ss51 section%d failed!", section); + return FAIL; + } + } + } else { + GTP_DEBUG("check firmware ss51 section%d & %d", section, section+1); + ret = gup_check_and_repair(client, burn_addr, start_index, 2 * FW_SS51_SECTION_LEN); + if (ret == FAIL) { + GTP_ERROR("check ss51 section%d & %d failed!", section, section+1); + return FAIL; + } + } + } + + return SUCCESS; +} + + +static s32 gup_prepare_fl_fw(char *path, st_fw_head *fw_head) +{ + s32 ret = 0; + s32 i = 0; + s32 timeout = 0; + struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client); + + if (!memcmp(path, "update", 6)) { + GTP_INFO("Search for GT9XXF firmware file to update"); + + searching_file = 1; + for (i = 0; i < GUP_SEARCH_FILE_TIMES; ++i) { + if (0 == searching_file) { + GTP_INFO("Force terminate auto update for GT9XXF..."); + return FAIL; + } + GTP_DEBUG("Search for %s, %s for fw update.(%d/%d)", FL_UPDATE_PATH, FL_UPDATE_PATH_SD, i+1, GUP_SEARCH_FILE_TIMES); + update_msg.file = filp_open(FL_UPDATE_PATH, O_RDONLY, 0); + if (IS_ERR(update_msg.file)) { + update_msg.file = filp_open(FL_UPDATE_PATH_SD, O_RDONLY, 0); + if (IS_ERR(update_msg.file)) { + msleep(3000); + continue; + } else { + path = FL_UPDATE_PATH_SD; + break; + } + } else { + path = FL_UPDATE_PATH; + break; + } + } + searching_file = 0; + if (i == 50) { + GTP_INFO("Search timeout, update aborted"); + return FAIL; + } else { + GTP_INFO("GT9XXF firmware file %s found!", path); + _CLOSE_FILE(update_msg.file); + } + while (ts->rqst_processing && (timeout++ < 5)) { + GTP_DEBUG("request processing, waiting for accomplishment"); + msleep(1000); + } + } + GTP_INFO("Firmware update file path: %s", path); + + update_msg.file = filp_open(path, O_RDONLY, 0); + + if (IS_ERR(update_msg.file)) { + GTP_ERROR("Open update file(%s) error!", path); + return FAIL; + } + + update_msg.old_fs = get_fs(); + set_fs(KERNEL_DS); + + update_msg.file->f_op->llseek(update_msg.file, 0, SEEK_SET); + update_msg.fw_total_len = update_msg.file->f_op->llseek(update_msg.file, 0, SEEK_END); + + update_msg.force_update = 0xBE; + if (update_msg.fw_total_len != sizeof(gt915_FW_fl)) { + GTP_ERROR("Inconsistent fw size. default size: %d(%dK), file size: %d(%dK)", sizeof(gt915_FW_fl), sizeof(gt915_FW_fl)/1024, update_msg.fw_total_len, update_msg.fw_total_len/1024); + set_fs(update_msg.old_fs); + _CLOSE_FILE(update_msg.file); + return FAIL; + } + + update_msg.fw_total_len -= FW_HEAD_LENGTH; + GTP_DEBUG("Fimrware size: %d(%dK)", update_msg.fw_total_len, update_msg.fw_total_len / 1024); + + update_msg.file->f_op->llseek(update_msg.file, 0, SEEK_SET); + ret = update_msg.file->f_op->read(update_msg.file, (char*)gt915_FW_fl, + update_msg.fw_total_len + FW_HEAD_LENGTH, + &update_msg.file->f_pos); + update_msg.fw_total_len += FW_HEAD_LENGTH; + set_fs(update_msg.old_fs); + _CLOSE_FILE(update_msg.file); + + if (ret < 0) { + GTP_ERROR("read %s failed, err-code: %d", path, ret); + return FAIL; + } + return SUCCESS; +} +static u8 gup_check_update_file_fl(struct i2c_client *client, st_fw_head *fw_head, char *path) +{ + s32 ret = 0; + s32 i = 0; + s32 fw_checksum = 0; + + if (NULL != path) { + ret = gup_prepare_fl_fw(path, fw_head); + if (FAIL == ret) { + return FAIL; + } + } else { + update_msg.fw_total_len = sizeof(gt915_FW_fl); + } + + memcpy(fw_head, gt915_FW_fl, FW_HEAD_LENGTH); + GTP_INFO("FILE HARDWARE INFO: %02x%02x%02x%02x", fw_head->hw_info[0], fw_head->hw_info[1], fw_head->hw_info[2], fw_head->hw_info[3]); + GTP_INFO("FILE PID: %s", fw_head->pid); + fw_head->vid = ((fw_head->vid & 0xFF00) >> 8) + ((fw_head->vid & 0x00FF) << 8); + GTP_INFO("FILE VID: %04x", fw_head->vid); + + fw_checksum = 0; + for(i = FW_HEAD_LENGTH; i < update_msg.fw_total_len; i += 2) { + fw_checksum += (gt915_FW_fl[i] << 8) + gt915_FW_fl[i+1]; + } + ret = SUCCESS; + + GTP_DEBUG("firmware checksum: %x", fw_checksum&0xFFFF); + if (fw_checksum & 0xFFFF) { + GTP_ERROR("Illegal firmware file."); + ret = FAIL; + } + + return ret; +} + +s32 gup_fw_download_proc(void *dir, u8 dwn_mode) +{ + s32 ret = 0; + u8 retry = 0; + st_fw_head fw_head; + struct goodix_ts_data *ts; + + ts = i2c_get_clientdata(i2c_connect_client); + if (NULL == dir) { + if (GTP_FL_FW_BURN == dwn_mode) { + GTP_INFO("[fw_download_proc]Begin fw download ......"); + } else if (GTP_FL_ESD_RECOVERY == dwn_mode) { + GTP_INFO("[fw_download_proc]Begin fw esd recovery check ......"); + } else { + GTP_INFO("[fw_download_proc]Being fw repair check......"); + } + } else { + GTP_INFO("[fw_download_proc]Begin firmware update by bin file"); + } + + total_len = 100; + show_len = 0; + + ret = gup_check_update_file_fl(i2c_connect_client, &fw_head, (char *)dir); + show_len = 10; + + if (FAIL == ret) { + GTP_ERROR("[fw_download_proc]check update file fail."); + goto file_fail; + } + + if (!memcmp(fw_head.pid, "950", 3)) { + ts->is_950 = 1; + GTP_DEBUG("GT9XXF Ic Type: gt950"); + } else { + ts->is_950 = 0; + } + + if (NULL != dir) { + gtp_irq_disable(ts); +#if GTP_ESD_PROTECT + gtp_esd_switch(ts->client, SWITCH_OFF); +#endif + } + + ret = gup_enter_update_mode_fl(i2c_connect_client); + show_len = 20; + if (FAIL == ret) { + GTP_ERROR("[fw_download_proc]enter update mode fail."); + goto download_fail; + } + + while (retry++ < 5) { + ret = gup_download_fw_ss51(i2c_connect_client, dwn_mode); + show_len = 60; + if (FAIL == ret) { + GTP_ERROR("[fw_download_proc]burn ss51 firmware fail."); + continue; + } + + ret = gup_download_fw_dsp(i2c_connect_client, dwn_mode); + show_len = 80; + if (FAIL == ret) { + GTP_ERROR("[fw_download_proc]burn dsp firmware fail."); + continue; + } + + GTP_INFO("[fw_download_proc]UPDATE SUCCESS."); + break; + } + + if (retry >= 5) { + GTP_ERROR("[fw_download_proc]retry timeout,UPDATE FAIL."); + goto download_fail; + } + + if (NULL != dir) { + gtp_irq_enable(ts); + gtp_fw_startup(ts->client); + #if GTP_ESD_PROTECT + gtp_esd_switch(ts->client, SWITCH_ON); + #endif + } + show_len = 100; + return SUCCESS; + +download_fail: + if (NULL != dir) { + gtp_irq_enable(ts); + gtp_fw_startup(ts->client); + #if GTP_ESD_PROTECT + gtp_esd_switch(ts->client, SWITCH_ON); + #endif + } +file_fail: + show_len = 200; + + return FAIL; +} + +#endif diff --git a/drivers/input/touchscreen/ist3038c/IST3038C1_00000C6GFF_VER000007.h b/drivers/input/touchscreen/ist3038c/IST3038C1_00000C6GFF_VER000007.h new file mode 100644 index 0000000000000..253dd8aee6cd1 --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/IST3038C1_00000C6GFF_VER000007.h @@ -0,0 +1,4054 @@ + +#ifndef __IST30XXC_FW_H__ +#define __IST30XXC_FW_H__ + + + + + + + +static unsigned char ist30xxc_fw[] = { + 0x80, 0x00, 0x00, 0x80, 0x0C, 0x01, 0x00, 0x80, 0x94, 0x0D, 0x00, 0x80, 0xFC, 0x00, 0x00, 0x80, + 0x04, 0x01, 0x00, 0x80, 0x18, 0x0E, 0x00, 0x80, 0xC8, 0x0D, 0x00, 0x80, 0xF0, 0x0D, 0x00, 0x80, + 0x0C, 0x01, 0x00, 0x80, 0x0C, 0x01, 0x00, 0x80, 0x0C, 0x01, 0x00, 0x80, 0x60, 0x0E, 0x00, 0x80, + 0x84, 0x0E, 0x00, 0x80, 0x0C, 0x01, 0x00, 0x80, 0x0C, 0x01, 0x00, 0x80, 0x0C, 0x01, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x10, 0x00, 0x27, 0x08, 0x80, 0x00, 0x80, 0x2C, 0x80, 0xEC, 0x9C, 0xAB, 0x0B, 0x00, 0x00, + 0x08, 0x70, 0x00, 0x40, 0x04, 0x61, 0x99, 0x67, 0x10, 0x00, 0x91, 0x67, 0x08, 0x70, 0x0F, 0x00, + 0x11, 0x17, 0x0C, 0x70, 0xC0, 0x17, 0x0C, 0x60, 0xC0, 0x17, 0xC6, 0x76, 0xB2, 0x04, 0xB1, 0x07, + 0x24, 0x74, 0xF2, 0xFC, 0x08, 0x30, 0x00, 0x80, 0x04, 0x70, 0x0C, 0x40, 0xC0, 0x17, 0x0C, 0x50, + 0x64, 0x19, 0x2C, 0x30, 0x24, 0xA2, 0x2F, 0x64, 0x07, 0x00, 0xC6, 0x65, 0xB2, 0x07, 0x2F, 0x23, + 0x07, 0x00, 0x30, 0x22, 0x24, 0x74, 0xB1, 0x26, 0xF2, 0xF7, 0x0C, 0x70, 0x64, 0x19, 0x0C, 0x60, + 0xD0, 0x1B, 0xC6, 0x76, 0xB2, 0x04, 0xB1, 0x07, 0x24, 0x74, 0xF2, 0xFC, 0x4B, 0x10, 0x00, 0x00, + 0x4B, 0xE6, 0x04, 0x00, 0xB9, 0x20, 0x88, 0x27, 0x04, 0x22, 0xF2, 0x0D, 0xB9, 0x20, 0x88, 0x27, + 0x04, 0x23, 0xF2, 0x09, 0xB9, 0x20, 0x88, 0x27, 0x04, 0x24, 0xF2, 0x05, 0xB9, 0x20, 0x88, 0x27, + 0x04, 0x21, 0xF2, 0x01, 0xB9, 0x10, 0x84, 0x27, 0xB9, 0x30, 0x8C, 0x27, 0x08, 0x30, 0x00, 0x50, + 0xB9, 0x03, 0x00, 0x10, 0xD9, 0x40, 0x90, 0x27, 0xD9, 0x80, 0xA0, 0x27, 0xD9, 0xC0, 0xB0, 0x27, + 0x01, 0x40, 0x01, 0x51, 0xC9, 0x40, 0xC0, 0x27, 0x99, 0x20, 0x80, 0x27, 0x08, 0x20, 0x01, 0x00, + 0xB1, 0x23, 0x98, 0x40, 0x80, 0x27, 0x92, 0xFE, 0x09, 0x00, 0x01, 0x00, 0x04, 0x23, 0xB9, 0x23, + 0x00, 0x10, 0xF2, 0x01, 0x48, 0x40, 0xC0, 0x27, 0x11, 0x15, 0x11, 0x04, 0x58, 0xC0, 0xB0, 0x27, + 0x58, 0x80, 0xA0, 0x27, 0x58, 0x40, 0x90, 0x27, 0x48, 0x20, 0x88, 0x27, 0x38, 0x10, 0x84, 0x27, + 0x61, 0x00, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0x2B, 0xEF, 0x00, 0x00, + 0x0B, 0xF6, 0x00, 0x00, 0x2B, 0xF7, 0x00, 0x00, 0xCB, 0xCD, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0xAB, 0xFC, 0x00, 0x00, 0xAB, 0x0A, 0x01, 0x00, + 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0xCB, 0x0D, 0x01, 0x00, + 0x4B, 0xFF, 0x00, 0x00, 0x6B, 0xFE, 0x00, 0x00, 0x2B, 0xFD, 0x00, 0x00, 0x8B, 0x00, 0x01, 0x00, + 0x4B, 0x01, 0x01, 0x00, 0xAB, 0x03, 0x01, 0x00, 0x2B, 0x29, 0x01, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0xAB, 0x11, 0x01, 0x00, 0xAB, 0xF1, 0x00, 0x00, + 0x4B, 0xA4, 0x04, 0x00, 0xAB, 0x0A, 0x01, 0x00, 0x8B, 0x16, 0x01, 0x00, 0x4B, 0x82, 0x00, 0x00, + 0x6B, 0xA0, 0x00, 0x00, 0x28, 0x20, 0x80, 0x1B, 0x54, 0x24, 0xA3, 0x22, 0x92, 0x03, 0x6B, 0x35, + 0x01, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0xAB, 0xE9, + 0x00, 0x00, 0xAB, 0xEE, 0x00, 0x00, 0xCB, 0x13, 0x00, 0x00, 0xCB, 0x0B, 0x00, 0x00, 0xAB, 0x0C, + 0x00, 0x00, 0x4B, 0x0D, 0x00, 0x00, 0x4B, 0xE4, 0x00, 0x00, 0x8B, 0x8D, 0x01, 0x00, 0xAB, 0x0E, + 0x00, 0x00, 0x8B, 0x8C, 0x01, 0x00, 0x8B, 0x16, 0x01, 0x00, 0x98, 0x70, 0xA9, 0x1B, 0x92, 0xFA, + 0x18, 0x70, 0xA0, 0x1B, 0xC4, 0x71, 0x82, 0xF6, 0x98, 0x70, 0x9F, 0x1B, 0x82, 0x04, 0x6B, 0xDE, + 0x04, 0x00, 0xF2, 0xF0, 0x2B, 0x8B, 0x01, 0x00, 0xCB, 0x31, 0x00, 0x00, 0x2B, 0x4A, 0x01, 0x00, + 0x6B, 0x32, 0x00, 0x00, 0x4B, 0x89, 0x01, 0x00, 0x6B, 0x8A, 0x01, 0x00, 0xAB, 0x8B, 0x01, 0x00, + 0x6B, 0x3C, 0x01, 0x00, 0xF2, 0xDF, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0x04, 0x61, 0xB9, 0x67, + 0x00, 0x80, 0xB9, 0x07, 0x0C, 0x80, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x80, 0xC6, 0x27, 0x34, 0x14, + 0xB1, 0xF1, 0x82, 0x03, 0xC6, 0x37, 0x92, 0x04, 0x6B, 0x1B, 0x00, 0x00, 0xF2, 0x09, 0x08, 0x70, + 0x00, 0x40, 0xB9, 0x27, 0x04, 0x80, 0xB9, 0x37, 0x08, 0x80, 0x38, 0x27, 0x10, 0x80, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x27, 0x18, 0x80, 0xB9, 0x37, 0x1C, 0x80, + 0x06, 0x67, 0x38, 0x76, 0x28, 0x80, 0xD4, 0x71, 0x82, 0xFD, 0x38, 0x26, 0x20, 0x80, 0xE1, 0xF0, + 0x04, 0x50, 0xC6, 0x25, 0x32, 0x03, 0x16, 0x22, 0x04, 0x51, 0x04, 0x60, 0xC6, 0x36, 0x32, 0x03, + 0x16, 0x33, 0x04, 0x61, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x27, 0x18, 0x80, 0xB9, 0x37, 0x1C, 0x80, + 0x06, 0x47, 0x38, 0x74, 0x28, 0x80, 0xD4, 0x71, 0x82, 0xFD, 0xC6, 0x56, 0x38, 0x24, 0x20, 0x80, + 0x82, 0x02, 0x16, 0x22, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x27, 0x18, 0x80, + 0xB9, 0x37, 0x1C, 0x80, 0x06, 0x67, 0x38, 0x76, 0x28, 0x80, 0xD4, 0x71, 0x82, 0xFD, 0x38, 0x26, + 0x24, 0x80, 0xE1, 0xF0, 0x04, 0x50, 0xC6, 0x25, 0x34, 0x18, 0xC1, 0xE1, 0x06, 0xE2, 0x32, 0x03, + 0x16, 0xE2, 0x04, 0x51, 0x04, 0x60, 0xC6, 0x36, 0x32, 0x03, 0x16, 0x33, 0x04, 0x61, 0x08, 0x70, + 0x00, 0x40, 0xB9, 0xE7, 0x18, 0x80, 0xB9, 0x37, 0x1C, 0x80, 0x06, 0x47, 0x38, 0x74, 0x28, 0x80, + 0xD4, 0x71, 0x82, 0xFD, 0xC6, 0x56, 0x38, 0x24, 0x20, 0x80, 0x82, 0x02, 0x16, 0x22, 0x4B, 0x14, + 0x00, 0x00, 0x3F, 0x22, 0x0E, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0xC4, 0x30, 0x04, 0x40, + 0x04, 0x50, 0x0C, 0x60, 0x20, 0x00, 0x52, 0x03, 0xA6, 0x42, 0x25, 0x50, 0xB4, 0x61, 0x02, 0x06, + 0xA6, 0x44, 0x25, 0x55, 0xA6, 0x33, 0x42, 0xF9, 0xF2, 0xFA, 0x06, 0x24, 0x06, 0x35, 0xE1, 0xF0, + 0x04, 0x40, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x9E, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, + 0xC6, 0x43, 0xBA, 0x9D, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x9C, 0x00, 0x00, + 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x9B, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, + 0xBA, 0x9A, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x99, 0x00, 0x00, 0xA6, 0x22, + 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x98, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x97, + 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x96, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, + 0xC6, 0x43, 0xBA, 0x95, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x94, 0x00, 0x00, + 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x93, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, + 0xBA, 0x92, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x91, 0x00, 0x00, 0xA6, 0x22, + 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x90, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x8F, + 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x8E, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, + 0xC6, 0x43, 0xBA, 0x8D, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x8C, 0x00, 0x00, + 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x8B, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, + 0xBA, 0x8A, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x89, 0x00, 0x00, 0xA6, 0x22, + 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x88, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x87, + 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x86, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, + 0xC6, 0x43, 0xBA, 0x85, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x84, 0x00, 0x00, + 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x83, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, + 0xBA, 0x82, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x81, 0x00, 0x00, 0xA6, 0x22, + 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x80, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x7F, + 0x00, 0x00, 0xE1, 0xF0, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x62, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x63, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x64, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x65, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x66, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x67, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x68, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x69, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x6A, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x6B, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x6C, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x6D, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x6E, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x6F, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x70, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x71, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x72, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x73, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x74, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x75, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x76, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x77, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x78, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x79, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x7A, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x7B, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x7C, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x7D, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x7E, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xFA, 0x7F, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x80, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, + 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x04, 0x70, 0x6C, 0x70, 0x40, 0x00, + 0x66, 0x72, 0xB9, 0x76, 0x04, 0x70, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x60, 0x71, + 0x08, 0x50, 0x40, 0x00, 0x66, 0x75, 0xB9, 0x76, 0x60, 0x71, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, + 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x60, 0x71, 0x08, 0x50, 0x40, 0x00, 0x66, 0x75, 0xB9, 0x76, + 0x60, 0x71, 0x0C, 0x20, 0x64, 0x00, 0x2B, 0xED, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, + 0x08, 0x50, 0x00, 0x40, 0x38, 0x75, 0x60, 0x71, 0x08, 0x60, 0xBF, 0xFF, 0x2C, 0x60, 0xFF, 0xFF, + 0x56, 0x76, 0xB9, 0x75, 0x60, 0x71, 0xE1, 0xF0, 0x34, 0x14, 0x0C, 0x20, 0x00, 0x60, 0xB1, 0xF1, + 0x2B, 0x60, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x98, 0x70, 0xA0, 0x1B, + 0x34, 0x14, 0xB1, 0xF1, 0x92, 0x05, 0x0C, 0x20, 0x00, 0x60, 0x0B, 0x61, 0x00, 0x00, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0x0C, 0x20, 0x00, 0x60, 0xB1, 0xF1, 0x2B, 0x60, 0x00, 0x00, + 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x60, 0x71, 0x08, 0x50, 0x40, 0x00, 0x66, 0x75, 0xB9, 0x76, + 0x60, 0x71, 0x0C, 0x20, 0x64, 0x00, 0x2B, 0xED, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, + 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x04, 0x70, 0x1C, 0x50, 0x1D, 0x00, 0x56, 0x75, 0x66, 0x72, + 0xB9, 0x76, 0x04, 0x70, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x04, 0x35, + 0x06, 0xE2, 0x04, 0x21, 0xCB, 0x78, 0x00, 0x00, 0x04, 0x24, 0x04, 0x30, 0xCB, 0x5E, 0x00, 0x00, + 0x08, 0xD0, 0x00, 0x40, 0x38, 0x7D, 0x08, 0x70, 0xD6, 0x7E, 0x92, 0x0A, 0x04, 0x21, 0x4B, 0x77, + 0x00, 0x00, 0xCB, 0x5A, 0x00, 0x00, 0x04, 0x21, 0x0B, 0x78, 0x00, 0x00, 0xF2, 0xF4, 0x04, 0x24, + 0x04, 0x31, 0xCB, 0x5E, 0x00, 0x00, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x18, 0x70, 0x9C, 0x1B, 0x34, 0x14, 0x93, 0x07, 0xB1, 0xF1, 0x92, 0x02, 0x51, 0x00, 0x08, 0x60, + 0x00, 0x40, 0x38, 0x76, 0x04, 0x70, 0x1C, 0x50, 0x41, 0x70, 0x56, 0x75, 0xB9, 0x76, 0x04, 0x70, + 0x04, 0x24, 0x04, 0x31, 0xCB, 0x5E, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, + 0x08, 0x70, 0x00, 0x40, 0x38, 0x67, 0x08, 0x70, 0xB9, 0x67, 0x08, 0x70, 0xE1, 0xF0, 0x00, 0x00, + 0x34, 0x18, 0xC1, 0xE1, 0x06, 0xE2, 0x0B, 0x39, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0xB9, 0xE7, + 0x00, 0x70, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xE2, + 0x06, 0xD3, 0x0B, 0x39, 0x00, 0x00, 0x04, 0x24, 0x04, 0x30, 0xCB, 0x5E, 0x00, 0x00, 0x06, 0x2D, + 0xAB, 0x2E, 0x00, 0x00, 0x99, 0x00, 0x9C, 0x1B, 0x08, 0x70, 0x00, 0x40, 0xB9, 0xE7, 0x00, 0x70, + 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x80, 0x18, 0x67, 0x67, 0xDC, + 0x08, 0x70, 0x00, 0x40, 0xB9, 0x67, 0x7C, 0x70, 0x38, 0x67, 0x70, 0x70, 0x64, 0x62, 0xB9, 0x67, + 0x70, 0x70, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x70, 0x70, 0x64, 0x71, 0xB9, 0x76, + 0x70, 0x70, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x70, 0x70, 0x14, 0x52, 0x56, 0x75, + 0xB9, 0x76, 0x70, 0x70, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0x38, 0x27, 0xE0, 0x70, + 0x5C, 0x20, 0xFF, 0x7F, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0x38, 0x27, 0xE4, 0x70, + 0x5C, 0x20, 0xFF, 0x01, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0x38, 0x27, 0xEC, 0x70, + 0x5C, 0x20, 0xFF, 0x0F, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0x38, 0x27, 0x5C, 0x70, + 0x5C, 0x20, 0x7F, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0xC4, 0x20, 0x08, 0x60, 0x00, 0x40, 0x82, 0x08, + 0x08, 0x70, 0x0F, 0xC0, 0x2C, 0x70, 0xFF, 0xFF, 0xB9, 0x76, 0x3C, 0x71, 0xF2, 0x03, 0xB9, 0x06, + 0x3C, 0x71, 0xE1, 0xF0, 0x08, 0x20, 0x00, 0x40, 0x08, 0x30, 0x00, 0x80, 0x34, 0x18, 0x2C, 0x20, + 0x08, 0x70, 0x2C, 0x30, 0x08, 0xE2, 0x0C, 0x40, 0xBE, 0x00, 0xC1, 0xE1, 0x0C, 0xF0, 0x5C, 0x01, + 0xF1, 0xF0, 0x0C, 0x20, 0x00, 0x40, 0x08, 0xE0, 0x00, 0x30, 0x08, 0x30, 0x00, 0x80, 0x26, 0x2E, + 0x2C, 0x30, 0x00, 0xE5, 0x0C, 0x40, 0x40, 0x02, 0x0C, 0xF0, 0x5C, 0x01, 0xF1, 0xF0, 0x0C, 0x20, + 0xC4, 0x52, 0x08, 0x30, 0x00, 0x80, 0x26, 0x2E, 0x2C, 0x30, 0x00, 0xEE, 0x0C, 0x40, 0x54, 0x00, + 0x0C, 0xF0, 0x5C, 0x01, 0xF1, 0xF0, 0x08, 0x70, 0x00, 0x80, 0x28, 0x77, 0x28, 0xDC, 0x0C, 0x20, + 0x00, 0x49, 0x06, 0x37, 0x57, 0x38, 0x26, 0x2E, 0x66, 0x37, 0x0C, 0x40, 0x69, 0x01, 0x0C, 0xF0, + 0xD8, 0x01, 0xF1, 0xF0, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, 0x04, 0x7F, 0x56, 0x72, + 0xC4, 0x71, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x92, 0x04, 0x38, 0x70, 0x68, 0x1A, 0xF2, 0x03, + 0x38, 0x70, 0x6C, 0x1A, 0xC4, 0x28, 0x38, 0x67, 0x50, 0x00, 0x38, 0x57, 0x74, 0x00, 0x38, 0x37, + 0x68, 0x00, 0x38, 0xF7, 0x8C, 0x00, 0x38, 0x47, 0x94, 0x00, 0x82, 0x49, 0xC4, 0x28, 0xD2, 0x07, + 0xC4, 0x22, 0x82, 0x16, 0xC4, 0x23, 0x82, 0x38, 0xC4, 0x21, 0xF2, 0x09, 0xCC, 0x20, 0x82, 0x00, + 0x82, 0x13, 0xCC, 0x20, 0x82, 0x00, 0xD2, 0x05, 0xCC, 0x20, 0x81, 0x00, 0x92, 0x7B, 0xF2, 0x3F, + 0xCC, 0x20, 0x83, 0x00, 0x82, 0x29, 0xCC, 0x20, 0x88, 0x00, 0x82, 0x31, 0xF2, 0x73, 0x98, 0x20, + 0xB0, 0x1B, 0x82, 0x35, 0xF2, 0x1C, 0x98, 0x20, 0xB0, 0x1B, 0x82, 0x31, 0x08, 0x50, 0x00, 0x80, + 0x2C, 0x50, 0x0C, 0xDC, 0x28, 0x60, 0x0E, 0x0B, 0x18, 0x25, 0x73, 0x00, 0xC6, 0x26, 0xD2, 0x06, + 0x38, 0x67, 0x60, 0x00, 0x38, 0x57, 0x84, 0x00, 0xF2, 0x22, 0x18, 0x55, 0x74, 0x00, 0xC6, 0x56, + 0xD2, 0x06, 0x38, 0x67, 0x64, 0x00, 0x38, 0x57, 0x88, 0x00, 0xF2, 0x19, 0x38, 0x67, 0x5C, 0x00, + 0x38, 0x57, 0x80, 0x00, 0xF2, 0x14, 0x38, 0x67, 0x54, 0x00, 0x38, 0x57, 0x78, 0x00, 0x38, 0x37, + 0x6C, 0x00, 0x38, 0xF7, 0x90, 0x00, 0x38, 0x47, 0x98, 0x00, 0xF2, 0x09, 0x38, 0x67, 0x58, 0x00, + 0x38, 0x57, 0x7C, 0x00, 0x38, 0x37, 0x70, 0x00, 0x38, 0x47, 0x9C, 0x00, 0x98, 0x70, 0xA1, 0x1B, + 0x82, 0x05, 0x08, 0x60, 0x22, 0x00, 0x2C, 0x60, 0x20, 0x20, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x67, + 0x34, 0x70, 0xB9, 0x57, 0x64, 0x70, 0xB9, 0x37, 0x54, 0x70, 0xB9, 0xF7, 0x6C, 0x70, 0xB9, 0x47, + 0x1C, 0x71, 0x06, 0x65, 0x0C, 0x60, 0xFC, 0x0A, 0x38, 0x66, 0x0C, 0x00, 0x08, 0x40, 0x10, 0x00, + 0xD6, 0x64, 0x06, 0xD5, 0x82, 0x0C, 0xB8, 0x60, 0x8C, 0x19, 0x92, 0x09, 0x08, 0x60, 0x00, 0x8E, + 0x2C, 0x60, 0x80, 0x0F, 0xB9, 0x67, 0x6C, 0x70, 0xAB, 0x3C, 0x00, 0x00, 0xB8, 0x70, 0x8C, 0x19, + 0x82, 0x11, 0x38, 0x70, 0xFC, 0x0A, 0x08, 0x60, 0x00, 0x40, 0xCC, 0x70, 0xC7, 0x00, 0xD2, 0x04, + 0x08, 0x70, 0x00, 0x8E, 0xF2, 0x03, 0x08, 0x70, 0x80, 0x8F, 0x2C, 0x70, 0x80, 0x0F, 0xB9, 0x76, + 0x6C, 0x70, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x54, 0x2F, 0xC4, 0x21, + 0x92, 0x04, 0x38, 0x70, 0x68, 0x1A, 0xF2, 0x03, 0x38, 0x70, 0x6C, 0x1A, 0x38, 0x57, 0x4C, 0x00, + 0x98, 0x70, 0xB0, 0x1B, 0x08, 0x70, 0x00, 0x80, 0x82, 0x06, 0x2C, 0x70, 0xBC, 0xDC, 0x38, 0x77, + 0x04, 0x00, 0xF2, 0x03, 0x38, 0x77, 0xBC, 0xDC, 0xB8, 0x60, 0x8C, 0x19, 0x82, 0x03, 0x0C, 0x70, + 0xFF, 0x3F, 0x08, 0x60, 0x00, 0x40, 0xB9, 0x56, 0x30, 0x70, 0xB9, 0x76, 0x58, 0x70, 0xE1, 0xF0, + 0x54, 0x2F, 0xC4, 0x21, 0x92, 0x04, 0x38, 0x60, 0x68, 0x1A, 0xF2, 0x03, 0x38, 0x60, 0x6C, 0x1A, + 0x38, 0x56, 0x08, 0x00, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x57, 0xB4, 0x70, 0x38, 0x56, 0x0C, 0x00, + 0x08, 0x40, 0xDF, 0xFF, 0xB9, 0x57, 0xB8, 0x70, 0x38, 0x56, 0x10, 0x00, 0x2C, 0x40, 0xFF, 0xFF, + 0x56, 0x54, 0xB9, 0x57, 0xC0, 0x70, 0x38, 0x56, 0x14, 0x00, 0xB9, 0x57, 0xC4, 0x70, 0x98, 0x50, + 0xA2, 0x1B, 0x82, 0x0C, 0x08, 0x60, 0x01, 0x00, 0x2C, 0x60, 0x81, 0x11, 0xB9, 0x67, 0xAC, 0x70, + 0x08, 0x60, 0x10, 0x00, 0x2C, 0x60, 0x10, 0x00, 0xF2, 0x06, 0x30, 0x56, 0xB9, 0x57, 0xAC, 0x70, + 0x38, 0x66, 0x04, 0x00, 0xB9, 0x67, 0xB0, 0x70, 0x28, 0x70, 0x80, 0x1B, 0xD4, 0x74, 0x82, 0x1D, + 0x08, 0x60, 0x01, 0x00, 0x08, 0x70, 0x00, 0x40, 0x2C, 0x60, 0x40, 0x82, 0xB9, 0x67, 0xAC, 0x70, + 0xB9, 0x07, 0xB0, 0x70, 0x08, 0x60, 0x08, 0x00, 0xB9, 0x67, 0xB4, 0x70, 0x08, 0x60, 0x88, 0x00, + 0xB9, 0x07, 0xB8, 0x70, 0x2C, 0x60, 0x00, 0x10, 0xB9, 0x67, 0xC0, 0x70, 0x08, 0x60, 0x10, 0x1F, + 0x2C, 0x60, 0x10, 0x1F, 0xB9, 0x67, 0xC4, 0x70, 0xE1, 0xF0, 0x00, 0x00, 0x54, 0x2F, 0xC4, 0x21, + 0x92, 0x04, 0x38, 0x60, 0x68, 0x1A, 0xF2, 0x03, 0x38, 0x60, 0x6C, 0x1A, 0x38, 0x56, 0x2C, 0x00, + 0x08, 0x70, 0x00, 0x40, 0xB9, 0x57, 0x8C, 0x70, 0x38, 0x56, 0x30, 0x00, 0xB9, 0x57, 0x90, 0x70, + 0x38, 0x56, 0x34, 0x00, 0xB9, 0x57, 0x94, 0x70, 0x38, 0x56, 0x38, 0x00, 0xB9, 0x57, 0x98, 0x70, + 0x38, 0x56, 0x3C, 0x00, 0xB9, 0x57, 0x9C, 0x70, 0x38, 0x56, 0x40, 0x00, 0xB9, 0x57, 0xA0, 0x70, + 0x38, 0x56, 0x44, 0x00, 0xB9, 0x57, 0xA4, 0x70, 0x38, 0x66, 0x48, 0x00, 0xB9, 0x67, 0xA8, 0x70, + 0x28, 0x60, 0x80, 0x1B, 0xD4, 0x64, 0x82, 0x18, 0x08, 0x60, 0x01, 0x80, 0xB9, 0x67, 0x8C, 0x70, + 0x08, 0x50, 0x01, 0x00, 0x0C, 0x60, 0x20, 0x00, 0x26, 0x65, 0xB9, 0x67, 0x90, 0x70, 0xB9, 0x07, + 0x94, 0x70, 0xB9, 0x07, 0x98, 0x70, 0xB9, 0x57, 0x9C, 0x70, 0xB9, 0x67, 0xA0, 0x70, 0xB9, 0x07, + 0xA4, 0x70, 0xB9, 0x07, 0xA8, 0x70, 0xE1, 0xF0, 0x51, 0x00, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x40, + 0xC4, 0x20, 0x38, 0x67, 0x34, 0x10, 0x82, 0x03, 0x64, 0x63, 0xF2, 0x03, 0x14, 0x54, 0x56, 0x65, + 0xB9, 0x67, 0x34, 0x10, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0xAD, 0xDE, 0x2C, 0x70, 0x8C, 0x03, + 0x08, 0x60, 0x00, 0x40, 0xB9, 0x76, 0x00, 0x10, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0xAD, 0xDE, + 0x08, 0x60, 0x00, 0x40, 0x2C, 0x70, 0x8C, 0x03, 0xB9, 0x76, 0x00, 0x10, 0xB9, 0x26, 0x6C, 0x10, + 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x60, 0xAD, 0xDE, 0x08, 0x70, 0x00, 0x40, 0x2C, 0x60, 0x8C, 0x03, + 0xB9, 0x67, 0x00, 0x10, 0x0C, 0x50, 0x10, 0x00, 0xB9, 0x57, 0x20, 0x10, 0x08, 0x50, 0x38, 0x03, + 0xB9, 0x67, 0x00, 0x10, 0x2C, 0x50, 0x80, 0x88, 0xB9, 0x57, 0x24, 0x10, 0xB9, 0x67, 0x00, 0x10, + 0xB9, 0x07, 0x28, 0x10, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x60, 0xAD, 0xDE, 0x08, 0x70, 0x00, 0x40, + 0x2C, 0x60, 0x8C, 0x03, 0xB9, 0x67, 0x00, 0x10, 0xC4, 0x30, 0x38, 0x67, 0x50, 0x10, 0x82, 0x05, + 0x66, 0x62, 0xB9, 0x67, 0x50, 0x10, 0xF2, 0x05, 0x15, 0x22, 0x56, 0x26, 0xB9, 0x27, 0x50, 0x10, + 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x60, 0xAD, 0xDE, 0x08, 0x70, 0x00, 0x40, 0x2C, 0x60, 0x8C, 0x03, + 0xB9, 0x67, 0x00, 0x10, 0x38, 0x67, 0x54, 0x10, 0x66, 0x62, 0xB9, 0x67, 0x54, 0x10, 0xE1, 0xF0, + 0x08, 0x60, 0xAD, 0xDE, 0x08, 0x70, 0x00, 0x40, 0x2C, 0x60, 0x8C, 0x03, 0xB9, 0x67, 0x00, 0x10, + 0x38, 0x67, 0x54, 0x10, 0x15, 0x22, 0x56, 0x26, 0xB9, 0x27, 0x54, 0x10, 0xE1, 0xF0, 0x00, 0x00, + 0x08, 0x60, 0xAD, 0xDE, 0x08, 0x70, 0x00, 0x40, 0x2C, 0x60, 0x8C, 0x03, 0xB9, 0x67, 0x00, 0x10, + 0x38, 0x57, 0x58, 0x10, 0xCC, 0x20, 0xFF, 0x00, 0x1C, 0x40, 0x00, 0x01, 0x56, 0x54, 0x92, 0x0A, + 0xB9, 0x57, 0x58, 0x10, 0xB9, 0x67, 0x00, 0x10, 0x38, 0x67, 0x4C, 0x10, 0x14, 0x52, 0x56, 0x65, + 0xF2, 0x09, 0x66, 0x52, 0xB9, 0x57, 0x58, 0x10, 0xB9, 0x67, 0x00, 0x10, 0x38, 0x67, 0x4C, 0x10, + 0x64, 0x61, 0xB9, 0x67, 0x4C, 0x10, 0xE1, 0xF0, 0x08, 0x60, 0xAD, 0xDE, 0x08, 0x70, 0x00, 0x40, + 0x2C, 0x60, 0x8C, 0x03, 0xB9, 0x67, 0x00, 0x10, 0xC4, 0x30, 0x38, 0x67, 0x4C, 0x10, 0x82, 0x05, + 0x66, 0x62, 0xB9, 0x67, 0x4C, 0x10, 0xF2, 0x05, 0x15, 0x22, 0x56, 0x26, 0xB9, 0x27, 0x4C, 0x10, + 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0xAD, 0xDE, 0x08, 0x60, 0x00, 0x40, 0x2C, 0x70, 0x8C, 0x03, + 0xB9, 0x76, 0x00, 0x10, 0x04, 0x73, 0xB9, 0x76, 0x44, 0x10, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x40, + 0x38, 0x76, 0x08, 0x10, 0x66, 0x72, 0xB9, 0x76, 0x08, 0x10, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x40, + 0x38, 0x76, 0x64, 0x10, 0x66, 0x72, 0xB9, 0x76, 0x64, 0x10, 0xE1, 0xF0, 0x04, 0x62, 0x08, 0x70, + 0x00, 0x40, 0xB9, 0x67, 0x14, 0x10, 0xE1, 0xF0, 0x23, 0x22, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x27, + 0x10, 0x10, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x14, 0x10, 0x1C, 0x50, 0x11, 0x00, + 0x56, 0x75, 0x64, 0x71, 0xB9, 0x76, 0x14, 0x10, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, + 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x14, 0x10, 0x14, 0x52, 0x56, 0x75, 0x6C, 0x70, 0x10, 0x00, + 0xB9, 0x76, 0x14, 0x10, 0x0C, 0x20, 0x28, 0x00, 0x8B, 0xEA, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0xC4, 0x20, 0x04, 0x7F, 0x82, 0x03, 0x0C, 0x70, 0x9C, 0x00, 0x6C, 0x70, + 0x00, 0x01, 0x08, 0x60, 0x00, 0x40, 0xB9, 0x76, 0x74, 0x10, 0xE1, 0xF0, 0x04, 0x61, 0x08, 0x70, + 0x00, 0x40, 0xB9, 0x67, 0x70, 0x10, 0xE1, 0xF0, 0xC4, 0x20, 0x08, 0x70, 0x00, 0x40, 0x82, 0x04, + 0x04, 0x61, 0xB1, 0x67, 0xF2, 0x02, 0xB1, 0x07, 0xE1, 0xF0, 0x00, 0x00, 0xC4, 0x30, 0x57, 0x21, + 0x08, 0x70, 0x00, 0x40, 0x26, 0x72, 0x82, 0x04, 0x04, 0x61, 0xB1, 0x67, 0xF2, 0x02, 0xB1, 0x07, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0xCB, 0xB9, 0x00, 0x00, 0x08, 0x70, + 0x1C, 0xE1, 0x08, 0x60, 0x00, 0x30, 0x2C, 0x70, 0x04, 0xE9, 0xB9, 0x76, 0x04, 0x01, 0x08, 0xE0, + 0x00, 0x40, 0xB9, 0x76, 0x08, 0x01, 0x2C, 0xE0, 0x70, 0x10, 0x04, 0xD1, 0xB1, 0xDE, 0x04, 0x2A, + 0xAB, 0xED, 0x00, 0x00, 0xF2, 0xFC, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xC1, 0x61, 0x01, 0x61, + 0x01, 0x70, 0xC9, 0x61, 0x08, 0x00, 0x04, 0x61, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x67, 0x14, 0x40, + 0x48, 0x61, 0x08, 0x00, 0x11, 0x16, 0x11, 0x07, 0x40, 0x61, 0x2C, 0x10, 0x10, 0x00, 0x61, 0x00, + 0x3C, 0x10, 0x10, 0x00, 0xC1, 0x61, 0x01, 0x61, 0x01, 0x70, 0xC9, 0x61, 0x08, 0x00, 0x04, 0x61, + 0x08, 0x70, 0x00, 0x40, 0xB9, 0x67, 0x14, 0x50, 0x48, 0x61, 0x08, 0x00, 0x11, 0x16, 0x11, 0x07, + 0x40, 0x61, 0x2C, 0x10, 0x10, 0x00, 0x61, 0x00, 0x3C, 0x10, 0x24, 0x00, 0xD9, 0x41, 0x08, 0x00, + 0x01, 0x61, 0x01, 0x70, 0xC9, 0x61, 0x1C, 0x00, 0xC1, 0x21, 0x04, 0x61, 0x0C, 0x20, 0x28, 0x00, + 0xB9, 0xF1, 0x18, 0x00, 0x99, 0x60, 0x9D, 0x1B, 0x8B, 0xEA, 0x00, 0x00, 0x04, 0x61, 0x08, 0x70, + 0x00, 0x40, 0xB9, 0x67, 0x78, 0x10, 0x48, 0x61, 0x1C, 0x00, 0x38, 0xF1, 0x18, 0x00, 0x40, 0x21, + 0x11, 0x16, 0x11, 0x07, 0x58, 0x41, 0x08, 0x00, 0x2C, 0x10, 0x24, 0x00, 0x61, 0x00, 0x00, 0x00, + 0x3C, 0x10, 0x10, 0x00, 0xC1, 0x61, 0x01, 0x61, 0x01, 0x70, 0xC9, 0x61, 0x08, 0x00, 0x04, 0x61, + 0x99, 0x60, 0x9C, 0x1B, 0x48, 0x61, 0x08, 0x00, 0x11, 0x16, 0x11, 0x07, 0x40, 0x61, 0x2C, 0x10, + 0x10, 0x00, 0x61, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xC1, 0x61, 0x01, 0x61, 0x01, 0x70, 0xC9, 0x61, + 0x08, 0x00, 0x08, 0x70, 0x00, 0x40, 0x38, 0x67, 0x08, 0x70, 0xB9, 0x67, 0x08, 0x70, 0x48, 0x61, + 0x08, 0x00, 0x11, 0x16, 0x11, 0x07, 0x40, 0x61, 0x2C, 0x10, 0x10, 0x00, 0x61, 0x00, 0x00, 0x00, + 0x08, 0x70, 0x04, 0x00, 0x24, 0x74, 0x26, 0x27, 0x08, 0x70, 0xFF, 0xBF, 0x57, 0x26, 0x2C, 0x70, + 0x00, 0xC0, 0xB1, 0x42, 0x26, 0x27, 0x0C, 0x40, 0x04, 0x40, 0x08, 0x70, 0x00, 0x40, 0x26, 0x47, + 0x26, 0x42, 0xB1, 0x34, 0x0C, 0x40, 0x10, 0x40, 0x26, 0x47, 0x26, 0x42, 0x2C, 0x70, 0x08, 0x40, + 0xB1, 0x54, 0x26, 0x27, 0xB1, 0x62, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x40, 0x2C, 0x70, 0x08, 0x40, + 0x57, 0x26, 0x26, 0x27, 0x30, 0x72, 0x6C, 0x70, 0x00, 0x01, 0xB1, 0x72, 0xE1, 0xF0, 0x00, 0x00, + 0x08, 0x70, 0x00, 0x40, 0x2C, 0x70, 0x08, 0x40, 0x57, 0x26, 0x26, 0x27, 0x30, 0x72, 0x1C, 0x60, + 0x01, 0x01, 0x56, 0x76, 0xB1, 0x72, 0xE1, 0xF0, 0x08, 0x70, 0x04, 0x00, 0x24, 0x74, 0x26, 0x27, + 0x57, 0x26, 0xB1, 0x32, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0x57, 0x26, 0x2C, 0x70, + 0x0C, 0x40, 0x26, 0x72, 0x30, 0x27, 0xE1, 0xF0, 0x08, 0x70, 0x0F, 0x00, 0xD6, 0x72, 0x3C, 0x10, + 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xE2, 0x06, 0xC3, 0x82, 0x04, 0x1C, 0x70, 0x01, 0x10, 0x56, 0xE7, + 0x08, 0xD0, 0x00, 0x30, 0xCB, 0xB9, 0x00, 0x00, 0xB9, 0xED, 0x04, 0x01, 0xEB, 0x6A, 0x00, 0x00, + 0x0C, 0x20, 0xE8, 0x03, 0xAB, 0xED, 0x00, 0x00, 0xC4, 0xC0, 0x92, 0xF5, 0x50, 0xC1, 0x2C, 0x10, + 0x10, 0x00, 0xE1, 0xF0, 0x34, 0x18, 0x08, 0x50, 0x00, 0x80, 0xB9, 0xF1, 0x04, 0x00, 0xB1, 0x01, + 0x04, 0x70, 0x2C, 0x50, 0xAC, 0x9D, 0xC6, 0x73, 0x82, 0x0F, 0x04, 0x63, 0x56, 0x67, 0x26, 0x61, + 0x2F, 0x47, 0x02, 0x00, 0x10, 0xF6, 0x10, 0x44, 0x24, 0x71, 0x76, 0x4F, 0x13, 0x44, 0x26, 0x45, + 0x10, 0x44, 0x91, 0x46, 0xF2, 0xF1, 0x38, 0xF1, 0x04, 0x00, 0x30, 0x21, 0x24, 0x18, 0xE1, 0xF0, + 0x34, 0x18, 0x08, 0x70, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0xC1, 0xE1, 0x2C, 0x40, 0x5C, 0x04, + 0x06, 0xE2, 0x06, 0x27, 0x2C, 0x20, 0x80, 0x02, 0x36, 0x42, 0x08, 0x30, 0x00, 0x80, 0x2C, 0x30, + 0x48, 0xA0, 0x77, 0x41, 0x0C, 0xF0, 0x5C, 0x01, 0xF1, 0xF0, 0x0C, 0x20, 0x98, 0x01, 0x04, 0x30, + 0x0C, 0x40, 0x80, 0x04, 0x0C, 0x50, 0x00, 0x01, 0x04, 0x61, 0x0C, 0xF0, 0x98, 0x03, 0xF1, 0xF0, + 0xC4, 0x20, 0x82, 0x26, 0x04, 0x21, 0xCB, 0x3F, 0x00, 0x00, 0x0C, 0x50, 0x80, 0x04, 0x0C, 0x70, + 0x88, 0x04, 0x06, 0x2E, 0x2C, 0x50, 0xC8, 0x01, 0x30, 0x67, 0x5C, 0x60, 0xFF, 0x03, 0x57, 0x61, + 0xB1, 0x62, 0x30, 0x67, 0x77, 0x64, 0x5C, 0x60, 0xFC, 0x0F, 0xB9, 0x62, 0x04, 0x00, 0x30, 0x67, + 0x24, 0x74, 0x77, 0x69, 0xC6, 0x75, 0x5C, 0x60, 0xFC, 0x0F, 0xB9, 0x62, 0x08, 0x00, 0x24, 0x2C, + 0x92, 0xEC, 0x04, 0x20, 0xCB, 0x3F, 0x00, 0x00, 0x38, 0x20, 0x84, 0x04, 0xF2, 0x03, 0x08, 0x20, + 0x01, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x08, 0x20, 0x00, 0x30, 0x34, 0x18, 0x2C, 0x20, + 0x00, 0x40, 0xC1, 0xE1, 0x8B, 0x7D, 0x00, 0x00, 0x08, 0x70, 0x00, 0xFF, 0x2C, 0x70, 0xFF, 0x00, + 0x08, 0x60, 0x00, 0xAA, 0x0C, 0x50, 0x55, 0x00, 0x56, 0x72, 0x26, 0x56, 0xC6, 0x75, 0x06, 0xE2, + 0x92, 0x19, 0x0C, 0x70, 0x00, 0x10, 0xD6, 0x72, 0x82, 0x18, 0x0C, 0x20, 0x98, 0x01, 0x04, 0x34, + 0x0C, 0x40, 0xC4, 0x01, 0x0C, 0xF0, 0x04, 0x04, 0xF1, 0xF0, 0x38, 0x70, 0x80, 0x04, 0xC6, 0x27, + 0x82, 0x05, 0x08, 0x70, 0x02, 0x00, 0x66, 0xE7, 0xF2, 0x08, 0x04, 0x61, 0x99, 0x60, 0x9E, 0x1B, + 0xF2, 0x08, 0x06, 0xE6, 0x2C, 0xE0, 0x55, 0x01, 0x06, 0x2E, 0x04, 0x30, 0xCB, 0x79, 0x00, 0x00, + 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x08, 0x40, + 0x00, 0x00, 0x06, 0xC2, 0x08, 0x20, 0x00, 0x00, 0x2C, 0x20, 0x80, 0x02, 0x2C, 0x40, 0x5C, 0x04, + 0x06, 0xE3, 0x36, 0x42, 0x08, 0x30, 0x00, 0x80, 0x2C, 0x30, 0x48, 0xA0, 0x77, 0x41, 0x0C, 0xF0, + 0x5C, 0x01, 0xF1, 0xF0, 0x0C, 0xF0, 0xA4, 0x02, 0xF1, 0xF0, 0x04, 0x30, 0x0C, 0x20, 0x98, 0x01, + 0x0C, 0x40, 0x80, 0x04, 0x0C, 0x50, 0x00, 0x01, 0x06, 0x63, 0x0C, 0xF0, 0x98, 0x03, 0xF1, 0xF0, + 0xC4, 0x20, 0x82, 0x4B, 0x0C, 0xD0, 0x00, 0x10, 0x66, 0xDE, 0x0C, 0xF0, 0x80, 0x04, 0xB9, 0xD0, + 0x84, 0x04, 0x06, 0x6C, 0x0C, 0x40, 0x88, 0x04, 0x2C, 0xF0, 0xC8, 0x01, 0x78, 0x76, 0x02, 0x00, + 0x78, 0x56, 0x04, 0x00, 0x77, 0x71, 0x77, 0x51, 0x57, 0x5A, 0x57, 0x75, 0x66, 0x75, 0x70, 0x56, + 0x24, 0x66, 0x77, 0x51, 0x66, 0x75, 0xB1, 0x74, 0x24, 0x44, 0xC6, 0x4F, 0x92, 0xF0, 0x0C, 0x30, + 0xC0, 0x01, 0x0C, 0x20, 0x84, 0x04, 0xAB, 0x7B, 0x00, 0x00, 0xB9, 0x20, 0x80, 0x04, 0x04, 0x30, + 0x0C, 0x20, 0x38, 0x00, 0x0C, 0xF0, 0xE8, 0x02, 0xF1, 0xF0, 0x0C, 0x20, 0x58, 0x01, 0x04, 0x30, + 0x0C, 0x40, 0x80, 0x04, 0x0C, 0x50, 0x00, 0x01, 0x0C, 0xF0, 0x34, 0x03, 0xF1, 0xF0, 0x0C, 0xF0, + 0xC0, 0x02, 0xF1, 0xF0, 0x0C, 0x20, 0x98, 0x01, 0x04, 0x34, 0x0C, 0x40, 0xC4, 0x01, 0x0C, 0xF0, + 0x04, 0x04, 0xF1, 0xF0, 0x38, 0x70, 0x80, 0x04, 0xC6, 0x27, 0x82, 0x0A, 0x08, 0x20, 0x02, 0x00, + 0x2C, 0x20, 0x00, 0x10, 0x66, 0x2E, 0xF2, 0x05, 0x08, 0x20, 0x01, 0x00, 0xF2, 0x02, 0x06, 0x2D, + 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x18, 0x70, + 0xB2, 0x1B, 0x1C, 0x60, 0x10, 0x00, 0x56, 0x76, 0x06, 0x43, 0x64, 0x78, 0xF7, 0x40, 0x04, 0x30, + 0x99, 0x70, 0xB2, 0x1B, 0x06, 0xD2, 0x0C, 0xF0, 0xC4, 0x01, 0xF1, 0xF0, 0x18, 0x20, 0xB2, 0x1B, + 0x6B, 0x44, 0x00, 0x00, 0x18, 0x20, 0xB2, 0x1B, 0xEB, 0x4E, 0x00, 0x00, 0xAB, 0x0A, 0x01, 0x00, + 0x2B, 0x33, 0x00, 0x00, 0x0C, 0xE0, 0x15, 0x00, 0xB4, 0xE1, 0x82, 0x09, 0x04, 0x21, 0x0C, 0x30, + 0x00, 0x20, 0x4B, 0x3A, 0x00, 0x00, 0x8B, 0x37, 0x00, 0x00, 0xF2, 0xF7, 0x08, 0x60, 0x00, 0x30, + 0x0C, 0x70, 0x00, 0x49, 0x0C, 0x50, 0x40, 0x4E, 0x06, 0x2D, 0x26, 0x76, 0x26, 0x56, 0x30, 0x67, + 0x24, 0x74, 0xC6, 0x75, 0x5C, 0x60, 0xFF, 0x0F, 0xA1, 0x62, 0x24, 0x22, 0x92, 0xF9, 0x50, 0xC1, + 0x08, 0x20, 0x00, 0xAA, 0x2C, 0x20, 0x55, 0x00, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0x2D, 0x0C, 0x20, 0x80, 0x02, 0x0C, 0x30, 0xD2, 0x02, + 0x4B, 0x8D, 0x00, 0x00, 0x08, 0x70, 0x00, 0xAA, 0x2C, 0x70, 0x55, 0x00, 0xD6, 0x72, 0x06, 0xE2, + 0x06, 0x2D, 0x82, 0x03, 0x6C, 0xE0, 0x00, 0x20, 0x0C, 0x70, 0x00, 0x20, 0xD6, 0x7E, 0x82, 0x07, + 0x06, 0x3E, 0x0C, 0x20, 0x80, 0x02, 0xCB, 0x85, 0x00, 0x00, 0x66, 0xE2, 0x06, 0x2E, 0x04, 0x31, + 0xB9, 0x00, 0x68, 0x19, 0xCB, 0x79, 0x00, 0x00, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, + 0x3C, 0x10, 0xA0, 0x01, 0x06, 0x21, 0x04, 0x30, 0x0C, 0x40, 0x69, 0x01, 0xD9, 0x81, 0x80, 0x01, + 0xD9, 0xC1, 0x90, 0x01, 0xAB, 0xE5, 0x04, 0x00, 0x08, 0x90, 0x00, 0x30, 0x0C, 0x70, 0x00, 0x49, + 0x26, 0x79, 0x08, 0xB0, 0xFF, 0xC0, 0x0C, 0xA0, 0x15, 0x00, 0xB9, 0x71, 0x6C, 0x01, 0x2C, 0x90, + 0x00, 0x40, 0x2C, 0xB0, 0xFF, 0xFF, 0xCB, 0x3B, 0x00, 0x00, 0x04, 0x21, 0x0C, 0x30, 0x00, 0x20, + 0x4B, 0x3A, 0x00, 0x00, 0x8B, 0x37, 0x00, 0x00, 0x04, 0xE0, 0x06, 0xDE, 0x06, 0xCE, 0x57, 0xC1, + 0x04, 0x80, 0x2F, 0xFE, 0x01, 0x00, 0x26, 0xF8, 0x90, 0x4F, 0x92, 0x60, 0x38, 0x71, 0x6C, 0x01, + 0x1C, 0x20, 0xAC, 0x0D, 0x26, 0x7C, 0x30, 0x37, 0x5C, 0x30, 0xFF, 0x0F, 0x26, 0x23, 0xC3, 0x22, + 0x02, 0x2C, 0x2F, 0x69, 0x0C, 0x00, 0x30, 0x56, 0x08, 0x70, 0x00, 0x3F, 0x56, 0x75, 0x77, 0x7C, + 0xC4, 0x70, 0x82, 0x23, 0x34, 0x71, 0x1C, 0x30, 0x90, 0x01, 0xB9, 0x51, 0x74, 0x01, 0xB9, 0x61, + 0x7C, 0x01, 0xB9, 0x41, 0x70, 0x01, 0xB9, 0x71, 0x78, 0x01, 0x8B, 0x16, 0x00, 0x00, 0x38, 0x71, + 0x78, 0x01, 0x38, 0x41, 0x70, 0x01, 0x26, 0x27, 0x43, 0x22, 0x06, 0x34, 0x0C, 0xF0, 0xBC, 0x00, + 0xF1, 0xF0, 0x38, 0x51, 0x74, 0x01, 0x38, 0x61, 0x7C, 0x01, 0x5C, 0x20, 0x3F, 0x00, 0x57, 0x2C, + 0x56, 0x5B, 0x66, 0x25, 0xB1, 0x26, 0xF2, 0x25, 0x0C, 0x70, 0x2C, 0x01, 0x3F, 0x33, 0x07, 0x00, + 0xC4, 0x30, 0x02, 0x22, 0x2F, 0x79, 0x0C, 0x00, 0x30, 0x67, 0x08, 0x20, 0x00, 0x3F, 0x56, 0x26, + 0x77, 0x2C, 0xCC, 0x20, 0x3F, 0x00, 0x82, 0x18, 0x24, 0x21, 0x0C, 0x30, 0x3F, 0x00, 0xB9, 0x61, + 0x7C, 0x01, 0xB9, 0x71, 0x78, 0x01, 0x0C, 0xF0, 0x98, 0x00, 0xF1, 0xF0, 0x38, 0x61, 0x7C, 0x01, + 0x38, 0x71, 0x78, 0x01, 0x5C, 0x20, 0x3F, 0x00, 0x57, 0x2C, 0x56, 0x6B, 0x66, 0x26, 0xB1, 0x27, + 0x24, 0xD1, 0x23, 0xDD, 0xF2, 0x03, 0x04, 0x71, 0x91, 0x7F, 0x24, 0x81, 0xCC, 0x80, 0x13, 0x00, + 0x24, 0xC4, 0x92, 0x98, 0x2C, 0xE0, 0x13, 0x00, 0xCC, 0xE0, 0xBE, 0x00, 0x92, 0x90, 0xC4, 0xD0, + 0x82, 0x05, 0x34, 0xA1, 0xA3, 0xAA, 0x9A, 0x80, 0xFF, 0xFF, 0x58, 0xC1, 0x90, 0x01, 0x58, 0x81, + 0x80, 0x01, 0x2C, 0x10, 0xA0, 0x01, 0xE1, 0xF0, 0x2F, 0x72, 0x02, 0x00, 0x26, 0x72, 0xD7, 0x71, + 0xCC, 0x30, 0x16, 0x00, 0x26, 0x73, 0xB1, 0x74, 0xC2, 0x13, 0x06, 0x65, 0x0C, 0x60, 0x74, 0x1A, + 0x28, 0x50, 0x74, 0x1A, 0xC6, 0x75, 0x82, 0x10, 0x28, 0x56, 0x02, 0x00, 0xC6, 0x75, 0x82, 0x0C, + 0x28, 0x66, 0x04, 0x00, 0x04, 0x21, 0xC6, 0x76, 0x82, 0x08, 0x04, 0x20, 0xF2, 0x06, 0xC4, 0x2D, + 0xD2, 0xED, 0x04, 0x22, 0xF2, 0x02, 0x04, 0x21, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0xA4, 0x01, + 0x06, 0x21, 0x04, 0x30, 0x0C, 0x40, 0x69, 0x01, 0xD9, 0xC1, 0x94, 0x01, 0xD9, 0x81, 0x84, 0x01, + 0xAB, 0xE5, 0x04, 0x00, 0xB8, 0x70, 0x8C, 0x19, 0x9A, 0xBA, 0x00, 0x00, 0xCB, 0x31, 0x00, 0x00, + 0x04, 0x23, 0x6B, 0x44, 0x00, 0x00, 0x04, 0x23, 0xEB, 0x4E, 0x00, 0x00, 0xAB, 0x3C, 0x00, 0x00, + 0x4B, 0x2F, 0x00, 0x00, 0x0C, 0x70, 0x15, 0x00, 0xB9, 0x71, 0x70, 0x01, 0x08, 0xA0, 0x00, 0x30, + 0x0C, 0x70, 0x00, 0x49, 0x26, 0x7A, 0x08, 0xB0, 0xFF, 0xC0, 0xB9, 0x71, 0x74, 0x01, 0x2C, 0xB0, + 0xFF, 0xFF, 0xCB, 0x3B, 0x00, 0x00, 0x04, 0x21, 0x0C, 0x30, 0x00, 0x20, 0x04, 0x80, 0x4B, 0x3A, + 0x00, 0x00, 0x06, 0xD8, 0x8B, 0x37, 0x00, 0x00, 0x06, 0xE1, 0x04, 0xC0, 0x2F, 0x7C, 0x0E, 0x00, + 0x90, 0x97, 0x92, 0x73, 0x0C, 0x40, 0x6C, 0x01, 0x06, 0x28, 0x06, 0x3C, 0x26, 0x41, 0x4B, 0x9E, + 0x00, 0x00, 0xC4, 0x20, 0x82, 0x6A, 0x38, 0xF1, 0x6C, 0x01, 0x38, 0x71, 0x74, 0x01, 0x06, 0x3F, + 0x57, 0x31, 0x26, 0x73, 0x30, 0x67, 0x1C, 0x20, 0xAC, 0x0D, 0x5C, 0x60, 0xFF, 0x0F, 0x26, 0x26, + 0xC3, 0x22, 0x02, 0x2A, 0x0C, 0x50, 0x00, 0x40, 0x26, 0x5A, 0x26, 0x53, 0x30, 0x45, 0x08, 0x70, + 0x00, 0x3F, 0x56, 0x74, 0x77, 0x7C, 0xC4, 0x70, 0x82, 0x1F, 0x34, 0x71, 0x1C, 0x30, 0xC8, 0x00, + 0xB9, 0x41, 0x78, 0x01, 0xB9, 0x51, 0x7C, 0x01, 0xB9, 0x71, 0x80, 0x01, 0x8B, 0x16, 0x00, 0x00, + 0x38, 0x71, 0x80, 0x01, 0x06, 0x39, 0x26, 0x27, 0x43, 0x22, 0x0C, 0xF0, 0xBC, 0x00, 0xF1, 0xF0, + 0x38, 0x41, 0x78, 0x01, 0x38, 0x51, 0x7C, 0x01, 0x5C, 0x20, 0x3F, 0x00, 0x57, 0x2C, 0x56, 0x4B, + 0x66, 0x24, 0xB1, 0x25, 0xF2, 0x2C, 0x0C, 0x20, 0x2C, 0x01, 0x36, 0x26, 0xC4, 0x20, 0x02, 0x2A, + 0x0C, 0x90, 0x00, 0x40, 0x26, 0x9A, 0x26, 0x93, 0x30, 0x79, 0x08, 0x50, 0x00, 0x3F, 0x56, 0x57, + 0x77, 0x5C, 0xCC, 0x50, 0x3F, 0x00, 0x82, 0x1E, 0x24, 0x51, 0x0C, 0x30, 0xC8, 0x00, 0xB9, 0x71, + 0x80, 0x01, 0xB9, 0x51, 0x7C, 0x01, 0x8B, 0x16, 0x00, 0x00, 0x38, 0x51, 0x7C, 0x01, 0x0C, 0x30, + 0x3F, 0x00, 0x26, 0x25, 0x43, 0x22, 0x0C, 0xF0, 0x98, 0x00, 0xF1, 0xF0, 0x38, 0x71, 0x80, 0x01, + 0x5C, 0x20, 0x3F, 0x00, 0x57, 0x2C, 0x56, 0x7B, 0x66, 0x27, 0xB1, 0x29, 0x24, 0xD1, 0x23, 0xDD, + 0xF2, 0x04, 0x26, 0xF1, 0x04, 0x71, 0x91, 0x7F, 0x24, 0xC1, 0xCC, 0xC0, 0x18, 0x00, 0x92, 0x87, + 0x24, 0x81, 0xC4, 0x8E, 0x2C, 0xE0, 0x18, 0x00, 0x9A, 0x81, 0xFF, 0xFF, 0xC4, 0xD0, 0x82, 0x09, + 0x38, 0x71, 0x70, 0x01, 0x34, 0x71, 0xA3, 0x77, 0xB9, 0x71, 0x70, 0x01, 0x9A, 0x6B, 0xFF, 0xFF, + 0x0B, 0x31, 0x00, 0x00, 0x2B, 0x3D, 0x00, 0x00, 0x6B, 0x32, 0x00, 0x00, 0x58, 0xC1, 0x94, 0x01, + 0x58, 0x81, 0x84, 0x01, 0x2C, 0x10, 0xA4, 0x01, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0xA4, 0x01, + 0x06, 0x21, 0x04, 0x30, 0x0C, 0x40, 0x69, 0x01, 0xD9, 0x81, 0x84, 0x01, 0xD9, 0xC1, 0x94, 0x01, + 0xAB, 0xE5, 0x04, 0x00, 0x0C, 0x70, 0x15, 0x00, 0xB9, 0x71, 0x70, 0x01, 0x08, 0x90, 0x00, 0x30, + 0x0C, 0x70, 0x00, 0x49, 0x26, 0x79, 0x08, 0xA0, 0xFF, 0xC0, 0xB9, 0x71, 0x74, 0x01, 0x2C, 0xA0, + 0xFF, 0xFF, 0xCB, 0x3B, 0x00, 0x00, 0x04, 0x21, 0x0C, 0x30, 0x00, 0x20, 0x04, 0xB0, 0x4B, 0x3A, + 0x00, 0x00, 0x06, 0xDB, 0x8B, 0x37, 0x00, 0x00, 0x06, 0xE1, 0x04, 0xC0, 0x2F, 0x7C, 0x0E, 0x00, + 0x90, 0x87, 0x9A, 0x7F, 0x00, 0x00, 0x0C, 0x40, 0x6C, 0x01, 0x06, 0x2B, 0x06, 0x3C, 0x26, 0x41, + 0x4B, 0x9E, 0x00, 0x00, 0xC4, 0x20, 0x82, 0x75, 0x38, 0x61, 0x6C, 0x01, 0x0C, 0x30, 0x18, 0x00, + 0x06, 0x26, 0xB9, 0x61, 0x78, 0x01, 0x4B, 0x18, 0x00, 0x00, 0xC4, 0x2E, 0x38, 0x61, 0x78, 0x01, + 0xD2, 0x68, 0x38, 0x71, 0x74, 0x01, 0x06, 0xF6, 0x57, 0xF1, 0x26, 0x7F, 0x30, 0x37, 0x1C, 0x20, + 0xAC, 0x0D, 0x5C, 0x30, 0xFF, 0x0F, 0x26, 0x23, 0xC3, 0x22, 0x02, 0x2A, 0x0C, 0x50, 0x00, 0x40, + 0x26, 0x59, 0x26, 0x5F, 0x30, 0x45, 0x08, 0x70, 0x00, 0x3F, 0x56, 0x74, 0x77, 0x7C, 0xC4, 0x70, + 0x82, 0x1F, 0x34, 0x71, 0x1C, 0x30, 0x90, 0x01, 0xB9, 0x41, 0x78, 0x01, 0xB9, 0x51, 0x80, 0x01, + 0xB9, 0x71, 0x7C, 0x01, 0x8B, 0x16, 0x00, 0x00, 0x38, 0x71, 0x7C, 0x01, 0x06, 0x38, 0x26, 0x27, + 0x43, 0x22, 0x0C, 0xF0, 0xBC, 0x00, 0xF1, 0xF0, 0x38, 0x41, 0x78, 0x01, 0x38, 0x51, 0x80, 0x01, + 0x5C, 0x20, 0x3F, 0x00, 0x57, 0x2C, 0x56, 0x4A, 0x66, 0x24, 0xB1, 0x25, 0xF2, 0x2C, 0x0C, 0x20, + 0xF4, 0x01, 0x36, 0x23, 0xC4, 0x20, 0x02, 0x2A, 0x0C, 0x80, 0x00, 0x40, 0x26, 0x89, 0x26, 0x8F, + 0x30, 0x58, 0x08, 0x70, 0x00, 0x3F, 0x56, 0x75, 0x77, 0x7C, 0xCC, 0x70, 0x3F, 0x00, 0x82, 0x1E, + 0x24, 0x71, 0x0C, 0x30, 0x90, 0x01, 0xB9, 0x51, 0x80, 0x01, 0xB9, 0x71, 0x7C, 0x01, 0x8B, 0x16, + 0x00, 0x00, 0x38, 0x71, 0x7C, 0x01, 0x0C, 0x30, 0x3F, 0x00, 0x26, 0x27, 0x43, 0x22, 0x0C, 0xF0, + 0x98, 0x00, 0xF1, 0xF0, 0x38, 0x51, 0x80, 0x01, 0x5C, 0x20, 0x3F, 0x00, 0x57, 0x2C, 0x56, 0x5A, + 0x66, 0x25, 0xB1, 0x28, 0x24, 0xD1, 0x23, 0xDD, 0xF2, 0x04, 0x26, 0x61, 0x04, 0x71, 0x91, 0x76, + 0x24, 0xC1, 0xCC, 0xC0, 0x18, 0x00, 0x9A, 0x7B, 0xFF, 0xFF, 0x24, 0xB1, 0xC4, 0xBE, 0x2C, 0xE0, + 0x18, 0x00, 0x9A, 0x74, 0xFF, 0xFF, 0xC4, 0xD0, 0x82, 0x09, 0x38, 0x71, 0x70, 0x01, 0x34, 0x71, + 0xA3, 0x77, 0xB9, 0x71, 0x70, 0x01, 0x9A, 0x5E, 0xFF, 0xFF, 0x58, 0xC1, 0x94, 0x01, 0x58, 0x81, + 0x84, 0x01, 0x2C, 0x10, 0xA4, 0x01, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x30, 0x38, 0x76, 0x28, 0x00, + 0xD4, 0x74, 0x92, 0xFD, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x60, 0x00, 0x30, 0x38, 0x76, 0x40, 0x01, + 0x23, 0x77, 0xB9, 0x76, 0x40, 0x01, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x30, 0x38, 0x27, 0x28, 0x00, + 0x54, 0x22, 0xE1, 0xF0, 0x04, 0x62, 0x08, 0x70, 0x00, 0x30, 0xB9, 0x67, 0x28, 0x00, 0xE1, 0xF0, + 0x08, 0x70, 0x00, 0x30, 0x38, 0x27, 0x40, 0x01, 0xF7, 0x2F, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, + 0x8B, 0xBB, 0x00, 0x00, 0x04, 0x70, 0xC6, 0x27, 0x82, 0x0D, 0xCB, 0xB9, 0x00, 0x00, 0x08, 0x70, + 0x00, 0x30, 0x08, 0x60, 0x00, 0x80, 0xB9, 0x67, 0x40, 0x01, 0x38, 0x77, 0x3C, 0x01, 0xB9, 0x70, + 0x68, 0x19, 0x30, 0xF1, 0x06, 0x27, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x06, 0x72, 0x77, 0x78, + 0xCC, 0x70, 0x15, 0x00, 0x3C, 0x10, 0x14, 0x00, 0xD9, 0xC1, 0x04, 0x00, 0xB1, 0xB1, 0x0C, 0xE0, + 0xFF, 0xFF, 0x56, 0xE2, 0x82, 0x52, 0xCC, 0x70, 0x15, 0x00, 0xD2, 0x1B, 0xCC, 0x70, 0x10, 0x00, + 0x82, 0x3C, 0xCC, 0x70, 0x10, 0x00, 0xD2, 0x08, 0xC4, 0x71, 0x82, 0x33, 0xC4, 0x72, 0x92, 0x55, + 0x99, 0xE0, 0xA9, 0x1B, 0xF2, 0x77, 0xCC, 0x70, 0x13, 0x00, 0x82, 0x33, 0xCC, 0x70, 0x13, 0x00, + 0xD2, 0x34, 0xCC, 0x70, 0x12, 0x00, 0x92, 0x49, 0x99, 0xE0, 0x9F, 0x1B, 0xFA, 0xA8, 0x00, 0x00, + 0xCC, 0x70, 0x23, 0x00, 0x82, 0x39, 0xCC, 0x70, 0x23, 0x00, 0xD2, 0x0E, 0xCC, 0x70, 0x21, 0x00, + 0x82, 0x28, 0xCC, 0x70, 0x21, 0x00, 0xD2, 0x2D, 0xCC, 0x70, 0x20, 0x00, 0x92, 0x36, 0xA9, 0xE0, + 0x82, 0x1B, 0xFA, 0xA3, 0x00, 0x00, 0xCC, 0x70, 0x81, 0x00, 0x82, 0x29, 0xCC, 0x70, 0xE0, 0x00, + 0x82, 0x29, 0xCC, 0x70, 0x80, 0x00, 0x92, 0x29, 0x99, 0xE0, 0xA1, 0x1B, 0xFA, 0x8E, 0x00, 0x00, + 0x99, 0x70, 0xAA, 0x1B, 0xFA, 0x92, 0x00, 0x00, 0x99, 0xE0, 0xA8, 0x1B, 0xFA, 0x8E, 0x00, 0x00, + 0x99, 0xE0, 0xA6, 0x1B, 0xFA, 0x8A, 0x00, 0x00, 0x99, 0xE0, 0xA5, 0x1B, 0xFA, 0x86, 0x00, 0x00, + 0xA9, 0xE0, 0x84, 0x1B, 0xFA, 0x82, 0x00, 0x00, 0x99, 0xE0, 0xA4, 0x1B, 0xFA, 0x7E, 0x00, 0x00, + 0xA9, 0xE0, 0x80, 0x1B, 0xF2, 0x78, 0xA9, 0xE0, 0x7E, 0x1B, 0xF2, 0x77, 0x99, 0xE0, 0xA2, 0x1B, + 0xF2, 0x74, 0x99, 0xE0, 0xA0, 0x1B, 0xF2, 0x71, 0xCC, 0x70, 0x30, 0x00, 0x82, 0x43, 0xCC, 0x70, + 0x30, 0x00, 0xD2, 0x0A, 0xCC, 0x70, 0x12, 0x00, 0x82, 0x5A, 0xCC, 0x70, 0x22, 0x00, 0x82, 0x63, + 0xC4, 0x72, 0x92, 0x63, 0xF2, 0x17, 0xCC, 0x70, 0x80, 0x00, 0x82, 0x57, 0xCC, 0x70, 0x80, 0x00, + 0xD2, 0x07, 0xCC, 0x70, 0x33, 0x00, 0x92, 0x59, 0x8B, 0x91, 0x00, 0x00, 0xF2, 0x56, 0xCC, 0x70, + 0x90, 0x00, 0x82, 0x4E, 0xCC, 0x70, 0xE1, 0x00, 0x92, 0x50, 0x13, 0x2E, 0xAB, 0x90, 0x01, 0x00, + 0xF2, 0x4C, 0xCB, 0x5B, 0x00, 0x00, 0xC4, 0xE0, 0x82, 0x0E, 0x08, 0x50, 0x00, 0x40, 0x38, 0x75, + 0x54, 0x10, 0x08, 0x40, 0x00, 0x80, 0x66, 0x74, 0xB9, 0x70, 0x64, 0x19, 0x14, 0x71, 0xB9, 0x75, + 0x54, 0x10, 0xF2, 0x3B, 0xB8, 0x50, 0x64, 0x19, 0x32, 0x0A, 0x08, 0x70, 0xFF, 0x7F, 0x2C, 0x70, + 0xFF, 0xFF, 0x56, 0x75, 0x08, 0x50, 0x00, 0x40, 0xB9, 0x75, 0x54, 0x10, 0xB9, 0x00, 0x64, 0x19, + 0xF2, 0x2C, 0x04, 0x20, 0x4B, 0x6B, 0x00, 0x00, 0x0C, 0xB0, 0x40, 0x01, 0x08, 0xE0, 0x00, 0x30, + 0x08, 0xD0, 0x30, 0x00, 0x06, 0xCE, 0x26, 0xBE, 0x24, 0xD1, 0x08, 0x60, 0x00, 0x80, 0xB8, 0x7E, + 0x40, 0x01, 0x32, 0xFE, 0x38, 0x7E, 0x28, 0x00, 0xD4, 0x74, 0x92, 0xFD, 0xB1, 0x6B, 0x38, 0x7C, + 0x3C, 0x01, 0xC6, 0x7D, 0x92, 0xF5, 0x04, 0x74, 0xF1, 0x70, 0xF2, 0xF0, 0x98, 0x70, 0x9F, 0x1B, + 0x82, 0x0C, 0x6B, 0xDB, 0x04, 0x00, 0xF2, 0x09, 0x6B, 0x13, 0x01, 0x00, 0xF2, 0x06, 0xEB, 0x6A, + 0x00, 0x00, 0xF2, 0x03, 0xAB, 0x11, 0x01, 0x00, 0x58, 0xC1, 0x04, 0x00, 0x30, 0xB1, 0x2C, 0x10, + 0x14, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x08, 0xE0, 0x00, 0x30, 0x0C, 0xD0, + 0x00, 0x01, 0x26, 0xDE, 0xCB, 0xB9, 0x00, 0x00, 0x06, 0x2D, 0x04, 0x30, 0x0C, 0x40, 0x10, 0x00, + 0x0C, 0xF0, 0xD8, 0x01, 0xF1, 0xF0, 0x38, 0x7E, 0x28, 0x00, 0xD4, 0x72, 0x82, 0x05, 0x04, 0x72, + 0xB9, 0x7E, 0x28, 0x00, 0xF2, 0xF0, 0x38, 0x7E, 0x40, 0x01, 0xB9, 0x7E, 0x40, 0x01, 0x50, 0xC1, + 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x18, 0x0C, 0x20, 0x00, 0x00, 0x04, 0x30, + 0x0C, 0x40, 0x20, 0x00, 0xC1, 0xE1, 0x0C, 0xF0, 0xD8, 0x01, 0xF1, 0xF0, 0x06, 0x2E, 0x0C, 0x20, + 0x00, 0x27, 0x04, 0x30, 0x0C, 0x40, 0x20, 0x00, 0x0C, 0xF0, 0xD8, 0x01, 0xF1, 0xF0, 0x08, 0x70, + 0x00, 0x80, 0x2C, 0x70, 0x00, 0xFA, 0x38, 0x67, 0xF8, 0x01, 0xB9, 0x60, 0x00, 0x00, 0x38, 0x67, + 0xFC, 0x01, 0xB9, 0x60, 0x04, 0x00, 0x08, 0x60, 0x00, 0x80, 0x38, 0x66, 0x04, 0xDC, 0xB9, 0x60, + 0x08, 0x00, 0x38, 0x67, 0xF0, 0x01, 0xB9, 0x60, 0x0C, 0x00, 0x38, 0x67, 0xF4, 0x01, 0x38, 0x77, + 0xCC, 0x01, 0xC4, 0x60, 0xB9, 0x70, 0x1C, 0x00, 0x08, 0x70, 0x35, 0x45, 0x2C, 0x70, 0x01, 0x32, + 0xB9, 0x70, 0x24, 0x00, 0x08, 0x70, 0x01, 0xC6, 0x2C, 0x70, 0x01, 0x45, 0xB9, 0x60, 0x10, 0x00, + 0xB9, 0x70, 0x28, 0x00, 0x82, 0x04, 0x08, 0x70, 0x02, 0x64, 0xF2, 0x03, 0x08, 0x70, 0x02, 0x07, + 0xB9, 0x70, 0x2C, 0x00, 0x04, 0x71, 0xB9, 0x70, 0x34, 0x00, 0x08, 0x70, 0x80, 0x07, 0x2C, 0x70, + 0x38, 0x04, 0xB9, 0x70, 0x40, 0x00, 0x08, 0x70, 0x18, 0x00, 0x24, 0x7E, 0xB9, 0x70, 0x44, 0x00, + 0x08, 0x70, 0x03, 0x01, 0x2C, 0x70, 0x02, 0x17, 0xB9, 0x70, 0x48, 0x00, 0x08, 0x70, 0x06, 0x17, + 0x2C, 0x70, 0x0B, 0x17, 0xB9, 0x70, 0x4C, 0x00, 0x08, 0x70, 0xFF, 0xFF, 0xB9, 0x70, 0x50, 0x00, + 0x08, 0x70, 0x17, 0x00, 0x24, 0x7E, 0xB9, 0x70, 0x54, 0x00, 0x08, 0x60, 0x00, 0x80, 0x08, 0x70, + 0xFF, 0x00, 0x2C, 0x60, 0x0C, 0xDC, 0x2C, 0x70, 0x00, 0xFF, 0xB9, 0x70, 0x58, 0x00, 0x18, 0x76, + 0x2D, 0x00, 0xB9, 0x00, 0x30, 0x00, 0x0C, 0xE0, 0x00, 0x27, 0xB9, 0x70, 0x5C, 0x00, 0x18, 0x76, + 0x2C, 0x00, 0xB9, 0xE0, 0x70, 0x00, 0xB9, 0x70, 0x60, 0x00, 0x28, 0x76, 0x1E, 0x00, 0x28, 0x66, + 0x1C, 0x00, 0x57, 0x78, 0x66, 0x76, 0x08, 0x60, 0x00, 0x80, 0x2C, 0x60, 0x44, 0xDF, 0xB9, 0x70, + 0x64, 0x00, 0x28, 0x76, 0x32, 0x00, 0x28, 0x66, 0x2C, 0x00, 0x57, 0x78, 0x66, 0x76, 0xB9, 0x70, + 0x68, 0x00, 0x0C, 0x60, 0x00, 0x49, 0x08, 0x70, 0x00, 0x30, 0x26, 0x67, 0x2C, 0x70, 0x00, 0xA0, + 0xB9, 0x70, 0x6C, 0x00, 0x0C, 0x70, 0xFC, 0x0A, 0xB9, 0x70, 0x78, 0x00, 0xB9, 0x60, 0x74, 0x00, + 0x0C, 0x70, 0xE8, 0x19, 0x08, 0x60, 0x00, 0x80, 0x66, 0x76, 0xB9, 0x70, 0x38, 0x00, 0x04, 0x72, + 0xB9, 0x70, 0x18, 0x00, 0xAB, 0xCB, 0x00, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x0C, 0xE0, 0xFC, 0x0A, 0x18, 0x7E, 0x74, 0x0C, 0x06, 0x43, + 0x04, 0x30, 0xC6, 0x73, 0x06, 0xD2, 0x82, 0x1B, 0x0C, 0xF0, 0xD8, 0x01, 0xF1, 0xF0, 0x38, 0x7E, + 0x3C, 0x0C, 0x0C, 0x50, 0x74, 0x0C, 0xB1, 0x7D, 0x0C, 0x70, 0x3C, 0x17, 0x26, 0x5E, 0x04, 0x61, + 0xB0, 0x37, 0x82, 0x06, 0x06, 0x46, 0x57, 0x41, 0x26, 0x4D, 0xB1, 0x34, 0x24, 0x61, 0x24, 0x74, + 0xC6, 0x75, 0x92, 0xF7, 0x18, 0x3E, 0x74, 0x0C, 0x99, 0x0E, 0x74, 0x0C, 0x50, 0xC1, 0x06, 0x23, + 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x04, 0x70, 0x06, 0x67, 0x3F, 0x57, 0x03, 0x00, + 0xC4, 0x50, 0x02, 0x08, 0x2F, 0x57, 0x02, 0x00, 0x10, 0x55, 0x24, 0x71, 0x26, 0x65, 0x13, 0x66, + 0xF2, 0xF6, 0x06, 0x26, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x30, 0xE2, + 0x08, 0x70, 0xFF, 0x00, 0x2C, 0x70, 0xFF, 0xFF, 0x56, 0xE7, 0x6C, 0xE0, 0x00, 0x0C, 0xB1, 0xE2, + 0x57, 0x31, 0x06, 0xD2, 0xCB, 0xDB, 0x00, 0x00, 0x57, 0x2C, 0x66, 0x2E, 0xB1, 0x2D, 0x50, 0xC1, + 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x50, 0x00, 0xD9, 0xC1, 0x40, 0x00, + 0x4B, 0xE5, 0x00, 0x00, 0x06, 0x21, 0x0C, 0x30, 0x10, 0x00, 0x0B, 0xD9, 0x00, 0x00, 0x86, 0xE2, + 0x82, 0x25, 0x06, 0x21, 0x06, 0x3E, 0xCB, 0xDC, 0x00, 0x00, 0x98, 0x70, 0xA3, 0x1B, 0x82, 0x07, + 0x6B, 0xE5, 0x00, 0x00, 0x06, 0x7E, 0x57, 0x71, 0x26, 0x71, 0xB1, 0x27, 0x08, 0xD0, 0x00, 0x30, + 0x0C, 0xC0, 0x04, 0x01, 0x26, 0xCD, 0xCB, 0xB9, 0x00, 0x00, 0x06, 0x2C, 0x06, 0x31, 0x04, 0x4B, + 0x0C, 0xF0, 0x5C, 0x01, 0xF1, 0xF0, 0x38, 0x7D, 0x28, 0x00, 0xD4, 0x72, 0x82, 0x05, 0x04, 0x72, + 0xB9, 0x7D, 0x28, 0x00, 0xF2, 0xF1, 0x4B, 0xBA, 0x00, 0x00, 0x18, 0x70, 0xBB, 0x1B, 0xC4, 0x71, + 0x92, 0x11, 0x2B, 0xA8, 0x01, 0x00, 0x98, 0x70, 0xB6, 0x1B, 0x82, 0x05, 0xC4, 0x71, 0x92, 0x0A, + 0xC4, 0xE0, 0x92, 0x08, 0x08, 0x60, 0xDB, 0xDB, 0x08, 0x70, 0x00, 0x30, 0xB9, 0x67, 0x04, 0x01, + 0x04, 0xE1, 0x18, 0x60, 0xA0, 0x1B, 0xC4, 0x62, 0x92, 0x12, 0x04, 0x61, 0x99, 0x60, 0xA0, 0x1B, + 0x18, 0x70, 0xB6, 0x1B, 0x04, 0x21, 0xC4, 0x70, 0x92, 0x0B, 0x08, 0x70, 0xA0, 0x8C, 0x2C, 0x70, + 0x0E, 0xD0, 0x08, 0x60, 0x00, 0x30, 0xB9, 0x76, 0x04, 0x01, 0xF2, 0x02, 0x06, 0x2E, 0x58, 0xC1, + 0x40, 0x00, 0x2C, 0x10, 0x50, 0x00, 0xE1, 0xF0, 0x0C, 0x50, 0x00, 0x00, 0x0C, 0x70, 0x78, 0x00, + 0x34, 0x54, 0x04, 0x60, 0x30, 0x47, 0x34, 0x74, 0xC6, 0x75, 0x26, 0x64, 0x92, 0xFC, 0xB9, 0x60, + 0x7C, 0x00, 0xE1, 0xF0, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, + 0x0C, 0x70, 0xFC, 0x0A, 0x38, 0x27, 0x3C, 0x0C, 0x08, 0x60, 0xE0, 0x00, 0xD6, 0x26, 0x92, 0x17, + 0xA8, 0x77, 0x14, 0x03, 0x82, 0x34, 0xCC, 0x70, 0xFF, 0x0F, 0x82, 0x31, 0x26, 0x77, 0x06, 0x27, + 0x57, 0x22, 0x36, 0x27, 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x2C, 0x20, 0x90, 0x01, + 0xCC, 0x20, 0x58, 0x02, 0xC2, 0x24, 0x0C, 0x20, 0x58, 0x02, 0xF2, 0x21, 0x28, 0x27, 0x18, 0x03, + 0x1C, 0x70, 0xA5, 0x01, 0x26, 0x72, 0xCC, 0x70, 0xE8, 0x03, 0xD2, 0x0F, 0x3C, 0x20, 0x8D, 0x05, + 0x06, 0x32, 0x4B, 0x14, 0x00, 0x00, 0x0C, 0x30, 0xE9, 0x03, 0xAB, 0x15, 0x00, 0x00, 0x0C, 0x70, + 0x8D, 0x05, 0x3F, 0x22, 0x07, 0x00, 0xF2, 0x0B, 0xCC, 0x20, 0x8D, 0x05, 0xC2, 0x08, 0x3C, 0x20, + 0x8D, 0x05, 0x04, 0x33, 0xAB, 0x15, 0x00, 0x00, 0x2C, 0x20, 0x8D, 0x05, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x01, 0x00, 0x34, 0x14, 0x2C, 0x70, 0xF8, 0x24, 0xB1, 0x71, + 0x30, 0x71, 0x14, 0x61, 0xC4, 0x70, 0x26, 0x67, 0xB1, 0x61, 0x92, 0xFB, 0x24, 0x14, 0xE1, 0xF0, + 0x06, 0x72, 0x57, 0x71, 0x26, 0x27, 0x34, 0x14, 0xF7, 0x20, 0xB1, 0x21, 0x30, 0x71, 0x14, 0x61, + 0xC4, 0x70, 0x26, 0x67, 0xB1, 0x61, 0x92, 0xFB, 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0x04, 0x3A, + 0xB1, 0xF1, 0xAB, 0x15, 0x00, 0x00, 0x23, 0x32, 0x04, 0x21, 0xCB, 0x78, 0x00, 0x00, 0x04, 0x21, + 0x4B, 0x77, 0x00, 0x00, 0x04, 0x24, 0x04, 0x30, 0xCB, 0x5E, 0x00, 0x00, 0xCB, 0x5A, 0x00, 0x00, + 0x04, 0x24, 0x04, 0x31, 0xCB, 0x5E, 0x00, 0x00, 0x04, 0x21, 0x0B, 0x78, 0x00, 0x00, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, 0x6B, 0xEB, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x06, 0x72, 0x06, 0x62, 0xD7, 0x63, 0x57, 0x71, 0x3F, 0x77, 0x06, 0x00, + 0x26, 0x27, 0x34, 0x14, 0xD7, 0x21, 0xB1, 0xF1, 0x6B, 0xEB, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x04, 0x20, 0xB1, 0xF1, 0x6B, 0x5C, 0x00, 0x00, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x00, 0x08, 0x70, 0x00, 0x00, 0x2C, 0x60, 0x80, 0x00, + 0x2C, 0x70, 0x1C, 0x02, 0x36, 0x76, 0xC4, 0x70, 0x34, 0x14, 0xB1, 0xF1, 0x32, 0x02, 0x24, 0x73, + 0x06, 0x47, 0x08, 0x50, 0x00, 0x80, 0x67, 0x41, 0x04, 0x70, 0x2C, 0x50, 0xAC, 0x9E, 0x14, 0x21, + 0xC6, 0x74, 0x04, 0x34, 0x26, 0x36, 0x32, 0x05, 0x30, 0xF5, 0x24, 0x54, 0xB1, 0xF6, 0xF2, 0x02, + 0xB1, 0x26, 0x24, 0x71, 0xCC, 0x70, 0x80, 0x00, 0x82, 0x03, 0x06, 0x63, 0xF2, 0xF2, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x28, 0x60, 0x82, 0x1B, 0xCC, 0x60, 0xFF, 0xFF, 0x92, 0x10, 0x38, 0x60, + 0x08, 0x0B, 0xD4, 0x61, 0x08, 0x60, 0x00, 0x80, 0x2C, 0x60, 0x0C, 0xDC, 0x82, 0x04, 0x38, 0x66, + 0x40, 0x00, 0xF2, 0x03, 0x38, 0x66, 0x3C, 0x00, 0xA9, 0x60, 0x82, 0x1B, 0x28, 0x60, 0x84, 0x1B, + 0xCC, 0x60, 0xFF, 0xFF, 0x92, 0x07, 0x08, 0x60, 0x00, 0x80, 0x38, 0x66, 0x44, 0xDC, 0xA9, 0x60, + 0x84, 0x1B, 0xE1, 0xF0, 0x08, 0x40, 0x00, 0x80, 0x34, 0x14, 0x08, 0x70, 0x00, 0x80, 0x2C, 0x40, + 0x0C, 0xDC, 0xB1, 0xF1, 0x2C, 0x70, 0x1A, 0xDC, 0x0C, 0x60, 0x7A, 0x1A, 0x24, 0x4A, 0x14, 0x21, + 0x10, 0x57, 0xCC, 0x50, 0xFF, 0x00, 0x82, 0x0D, 0x18, 0x37, 0x04, 0x00, 0xCC, 0x30, 0xFF, 0x00, + 0x82, 0x08, 0x2F, 0xF5, 0x05, 0x00, 0x26, 0x5F, 0xD7, 0x51, 0x26, 0x53, 0xA1, 0x56, 0xF2, 0x02, + 0xA1, 0x26, 0x34, 0x71, 0xC6, 0x74, 0x34, 0x62, 0x92, 0xEC, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, + 0x34, 0x14, 0x0C, 0x20, 0xFC, 0x0A, 0x04, 0x30, 0x0C, 0x40, 0xC4, 0x0C, 0xB1, 0xF1, 0x0C, 0xF0, + 0xB0, 0x01, 0xF1, 0xF0, 0xAB, 0xF3, 0x00, 0x00, 0x2B, 0xF8, 0x01, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x0C, 0x60, 0xF4, 0x01, 0xB9, 0x60, 0x80, 0x19, 0x99, 0x00, 0xB6, 0x1B, + 0x14, 0x61, 0x99, 0x60, 0xB5, 0x1B, 0xA9, 0x00, 0x86, 0x1B, 0xB9, 0x00, 0x7C, 0x19, 0xB9, 0x00, + 0x78, 0x19, 0x99, 0x00, 0xB4, 0x1B, 0xB9, 0x00, 0x74, 0x19, 0xB9, 0x00, 0x70, 0x19, 0x99, 0x00, + 0xB3, 0x1B, 0x04, 0x63, 0x99, 0x60, 0xB2, 0x1B, 0x99, 0x00, 0xAA, 0x1B, 0x99, 0x00, 0xA9, 0x1B, + 0x04, 0x71, 0x99, 0x70, 0xA8, 0x1B, 0x99, 0x00, 0xA7, 0x1B, 0x99, 0x70, 0xA6, 0x1B, 0x99, 0x00, + 0xA5, 0x1B, 0x14, 0x61, 0xA9, 0x60, 0x84, 0x1B, 0xA9, 0x60, 0x82, 0x1B, 0x08, 0x60, 0x00, 0x80, + 0x2C, 0x60, 0x00, 0xDC, 0x18, 0x46, 0x09, 0x00, 0x99, 0x40, 0xA4, 0x1B, 0x18, 0x56, 0x08, 0x00, + 0xA9, 0x50, 0x80, 0x1B, 0xA9, 0x00, 0x7E, 0x1B, 0x99, 0x00, 0xA3, 0x1B, 0x99, 0x00, 0xA2, 0x1B, + 0x99, 0x00, 0xA1, 0x1B, 0x0C, 0x50, 0xFC, 0x0A, 0xB9, 0x00, 0x6C, 0x19, 0x99, 0x70, 0xB0, 0x1B, + 0x38, 0x65, 0x0C, 0x00, 0x64, 0x64, 0xB9, 0x65, 0x0C, 0x00, 0x99, 0x00, 0xAF, 0x1B, 0x08, 0x60, + 0x00, 0x80, 0x18, 0x56, 0x79, 0xDC, 0x99, 0x50, 0xAE, 0x1B, 0x99, 0x00, 0xAD, 0x1B, 0x99, 0x70, + 0xBA, 0x1B, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, 0xAB, 0x40, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0x2B, 0x5D, 0x00, 0x00, 0x04, 0x20, 0x2B, 0x6A, + 0x00, 0x00, 0xAB, 0xAC, 0x01, 0x00, 0x08, 0x70, 0x00, 0x40, 0x38, 0x77, 0x10, 0x20, 0x30, 0xF1, + 0xF7, 0x70, 0xB9, 0x70, 0x20, 0x00, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x0C, 0x20, + 0x11, 0x00, 0xB1, 0xF1, 0x8B, 0x34, 0x00, 0x00, 0x04, 0x2B, 0x04, 0x31, 0xEB, 0x6B, 0x00, 0x00, + 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x04, 0x21, 0xB1, 0xF1, 0xEB, 0x66, + 0x00, 0x00, 0x04, 0x24, 0xEB, 0x66, 0x00, 0x00, 0x0C, 0x20, 0x40, 0x00, 0xEB, 0x66, 0x00, 0x00, + 0x0C, 0x20, 0x10, 0x00, 0x6B, 0x66, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, + 0x34, 0x14, 0xB1, 0xF1, 0x6B, 0x67, 0x00, 0x00, 0x04, 0x25, 0x04, 0x31, 0xEB, 0x6B, 0x00, 0x00, + 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x0C, 0x20, 0x00, 0x01, 0xB1, 0xF1, + 0x2B, 0x60, 0x00, 0x00, 0x0C, 0x20, 0x80, 0x00, 0x2B, 0x60, 0x00, 0x00, 0x04, 0x20, 0x06, 0x52, + 0x0C, 0x30, 0x27, 0x00, 0x0C, 0x40, 0xFF, 0xFF, 0x0C, 0x60, 0x01, 0x02, 0x8B, 0x75, 0x00, 0x00, + 0x04, 0x21, 0x0C, 0x30, 0x8F, 0x01, 0x0C, 0x40, 0xFF, 0xFF, 0x04, 0x50, 0x0C, 0x60, 0x01, 0x02, + 0x8B, 0x75, 0x00, 0x00, 0x04, 0x27, 0x04, 0x31, 0xEB, 0x6B, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x04, 0x21, 0xB1, 0xF1, 0x4B, 0x6B, 0x00, 0x00, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x08, 0x60, 0x00, 0x40, 0x38, 0xE6, + 0x70, 0x60, 0x06, 0x72, 0x23, 0xEE, 0xCC, 0xE0, 0x00, 0xC9, 0x06, 0xC3, 0xC2, 0x05, 0x08, 0x60, + 0x04, 0x00, 0x66, 0xE6, 0xF7, 0xE1, 0x06, 0x37, 0x06, 0x2E, 0x4B, 0x14, 0x00, 0x00, 0x0C, 0x30, + 0xA0, 0x0F, 0xAB, 0x15, 0x00, 0x00, 0x24, 0x25, 0x04, 0x3A, 0xAB, 0x15, 0x00, 0x00, 0x08, 0x70, + 0x00, 0x40, 0x38, 0x77, 0xCC, 0x71, 0x06, 0xD2, 0x77, 0x7C, 0x24, 0x72, 0xC6, 0x27, 0xB2, 0x02, + 0x06, 0xD7, 0xC4, 0xC0, 0x82, 0x18, 0x06, 0x7E, 0xD7, 0x71, 0x2F, 0x2E, 0x0E, 0x00, 0x26, 0x27, + 0x06, 0x3D, 0xAB, 0x15, 0x00, 0x00, 0x3C, 0xE0, 0xB0, 0x9A, 0xCC, 0xE0, 0x20, 0x03, 0x04, 0x71, + 0xD2, 0x02, 0x04, 0x70, 0xD7, 0x7F, 0x66, 0x72, 0x0C, 0x60, 0x00, 0x00, 0xB9, 0x76, 0x3C, 0x00, + 0x4B, 0xE4, 0x00, 0x00, 0x06, 0x2D, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x38, 0x70, 0x70, 0x1A, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x38, 0xE7, 0x04, 0x00, 0x18, 0x27, + 0x05, 0x00, 0x04, 0x30, 0x0C, 0xC0, 0xFF, 0x00, 0x2B, 0x04, 0x01, 0x00, 0x56, 0xCE, 0x06, 0xD2, + 0x04, 0x30, 0x06, 0x2C, 0x2B, 0x04, 0x01, 0x00, 0x08, 0x70, 0xFF, 0xFF, 0x56, 0x7E, 0x57, 0xD4, + 0x66, 0x72, 0x66, 0x7D, 0x08, 0x60, 0x00, 0x40, 0xB9, 0x76, 0x6C, 0x72, 0x50, 0xC1, 0x2C, 0x10, + 0x10, 0x00, 0xE1, 0xF0, 0x38, 0x70, 0x70, 0x1A, 0x34, 0x14, 0xB1, 0xF1, 0x18, 0x27, 0x08, 0x00, + 0x04, 0x31, 0x2B, 0x04, 0x01, 0x00, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x27, 0x18, 0x70, 0x8B, 0x08, + 0x01, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x40, 0x38, 0x57, 0x64, 0x71, + 0x38, 0x77, 0x9C, 0x60, 0x06, 0x65, 0xC4, 0x71, 0x77, 0x6A, 0x54, 0x6F, 0x02, 0x14, 0x34, 0x78, + 0x26, 0x76, 0xC4, 0x7C, 0x02, 0x02, 0x04, 0x7C, 0x86, 0x67, 0x32, 0x02, 0x04, 0x60, 0x08, 0x70, + 0x0F, 0xFF, 0x2C, 0x70, 0xFF, 0xFF, 0x56, 0x75, 0x57, 0x6A, 0x66, 0x67, 0x08, 0x70, 0x00, 0x40, + 0xB9, 0x67, 0x64, 0x71, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0xAB, 0x65, 0x00, 0x00, + 0x04, 0x31, 0x0C, 0x20, 0x20, 0x00, 0x4B, 0x64, 0x00, 0x00, 0x0C, 0x20, 0xFF, 0x00, 0x0B, 0x62, + 0x00, 0x00, 0x04, 0x31, 0x04, 0x24, 0xCB, 0x5E, 0x00, 0x00, 0x04, 0x21, 0xEB, 0x5A, 0x00, 0x00, + 0xCB, 0x0B, 0x01, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x98, 0x70, 0xAA, 0x1B, + 0x82, 0x09, 0xC4, 0x20, 0x82, 0x05, 0x04, 0x61, 0x99, 0x60, 0xB8, 0x1B, 0xF2, 0x03, 0x99, 0x00, + 0xB8, 0x1B, 0xE1, 0xF0, 0xC4, 0x20, 0x34, 0x18, 0xC1, 0xE1, 0x82, 0x0A, 0x04, 0x21, 0x6B, 0xFD, + 0x03, 0x00, 0x18, 0x60, 0xB2, 0x1B, 0x1C, 0x70, 0x80, 0x00, 0x66, 0x76, 0xF2, 0x07, 0x6B, 0xFD, + 0x03, 0x00, 0x18, 0x70, 0xB2, 0x1B, 0x5C, 0x70, 0x7F, 0x00, 0x99, 0x70, 0xB2, 0x1B, 0x40, 0xE1, + 0x24, 0x18, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x80, 0x98, 0x77, 0x68, 0xDC, 0x34, 0x18, 0xC1, 0xE1, + 0x82, 0x04, 0x28, 0xE0, 0x80, 0x1B, 0xF2, 0x05, 0x08, 0x70, 0x00, 0x80, 0x18, 0xE7, 0x08, 0xDC, + 0x04, 0x21, 0x56, 0x2E, 0x2B, 0x10, 0x01, 0x00, 0x54, 0xE4, 0xA3, 0x2E, 0x82, 0x02, 0x04, 0x21, + 0x6B, 0x0F, 0x01, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x04, 0x21, + 0xB1, 0xF1, 0x2B, 0x6A, 0x00, 0x00, 0x98, 0x70, 0xA1, 0x1B, 0x82, 0x27, 0x5C, 0x70, 0xF0, 0x00, + 0xCC, 0x70, 0x80, 0x00, 0x82, 0x08, 0xCC, 0x70, 0xC0, 0x00, 0x92, 0x1F, 0x04, 0x61, 0x99, 0x60, + 0xA3, 0x1B, 0xF2, 0x1B, 0x04, 0x71, 0x99, 0x70, 0xA3, 0x1B, 0x99, 0x70, 0xA5, 0x1B, 0x99, 0x00, + 0xA6, 0x1B, 0x08, 0x60, 0x00, 0x80, 0x98, 0x66, 0xA9, 0xDC, 0x92, 0x04, 0x99, 0x00, 0xA2, 0x1B, + 0xF2, 0x03, 0x99, 0x70, 0xA2, 0x1B, 0x04, 0x20, 0x6B, 0xFD, 0x03, 0x00, 0x18, 0x60, 0xB2, 0x1B, + 0x5C, 0x60, 0x7F, 0x00, 0x99, 0x60, 0xB2, 0x1B, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, + 0x98, 0x70, 0xB8, 0x1B, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x8A, 0xDD, 0x00, 0x00, 0xB8, 0xD0, + 0x8C, 0x19, 0x9A, 0x1D, 0x01, 0x00, 0x14, 0x61, 0x99, 0x00, 0xB6, 0x1B, 0x99, 0x60, 0xB5, 0x1B, + 0xA9, 0x00, 0x86, 0x1B, 0xB9, 0x00, 0x7C, 0x19, 0xB9, 0x00, 0x78, 0x19, 0x99, 0x00, 0xB4, 0x1B, + 0xB9, 0x00, 0x74, 0x19, 0xB9, 0x00, 0x70, 0x19, 0x99, 0x00, 0xB3, 0x1B, 0x0B, 0x31, 0x00, 0x00, + 0x6B, 0x32, 0x00, 0x00, 0xCB, 0x31, 0x00, 0x00, 0xAB, 0x40, 0x00, 0x00, 0x08, 0xC0, 0x00, 0x30, + 0x0C, 0x20, 0x00, 0x40, 0x06, 0x3D, 0x0C, 0x40, 0x40, 0x02, 0x26, 0x2C, 0x0C, 0xF0, 0xD8, 0x01, + 0xF1, 0xF0, 0x18, 0x20, 0xB2, 0x1B, 0x5C, 0x20, 0xF0, 0x00, 0x64, 0x23, 0x99, 0x20, 0xB2, 0x1B, + 0x6B, 0x44, 0x00, 0x00, 0x18, 0x20, 0xB2, 0x1B, 0xEB, 0x4E, 0x00, 0x00, 0x08, 0x60, 0x00, 0x8E, + 0x08, 0x70, 0x00, 0x40, 0x2C, 0x60, 0x80, 0x0F, 0xB9, 0x67, 0x6C, 0x70, 0x08, 0x60, 0x20, 0x00, + 0x2C, 0x60, 0x40, 0x26, 0xB9, 0x67, 0xEC, 0x71, 0x08, 0x60, 0x0E, 0x18, 0x2C, 0x60, 0x0E, 0x18, + 0xB9, 0x67, 0x0C, 0x70, 0x08, 0x60, 0xA8, 0x00, 0x2C, 0x60, 0x04, 0x62, 0xB9, 0x67, 0x64, 0x71, + 0x0C, 0x60, 0xFF, 0x3F, 0xB9, 0x67, 0x58, 0x70, 0x04, 0x68, 0xB9, 0x67, 0x2C, 0x70, 0x0C, 0x60, + 0x40, 0x03, 0xB9, 0x67, 0x28, 0x71, 0x0C, 0x50, 0x40, 0x82, 0x08, 0x60, 0x01, 0x00, 0x26, 0x56, + 0xB9, 0x57, 0xAC, 0x70, 0xB9, 0x07, 0xB0, 0x70, 0x08, 0x50, 0x08, 0x00, 0xB9, 0x57, 0xB4, 0x70, + 0x08, 0x50, 0x88, 0x00, 0xB9, 0x07, 0xB8, 0x70, 0x2C, 0x50, 0x00, 0x10, 0xB9, 0x57, 0xC0, 0x70, + 0x08, 0x50, 0x10, 0x1F, 0x2C, 0x50, 0x10, 0x1F, 0xB9, 0x57, 0xC4, 0x70, 0x0C, 0x50, 0x80, 0x00, + 0xB9, 0x57, 0xC8, 0x70, 0x08, 0x50, 0x02, 0x01, 0xB9, 0x57, 0xCC, 0x70, 0x04, 0x51, 0xB9, 0x57, + 0xD4, 0x70, 0x08, 0x50, 0x01, 0x80, 0xB9, 0x57, 0x8C, 0x70, 0x0C, 0x50, 0x20, 0x00, 0x26, 0x56, + 0xB9, 0x57, 0x90, 0x70, 0xB9, 0x07, 0x94, 0x70, 0xB9, 0x07, 0x98, 0x70, 0xB9, 0x67, 0x9C, 0x70, + 0xB9, 0x57, 0xA0, 0x70, 0xB9, 0x07, 0xA4, 0x70, 0xB9, 0x07, 0xA8, 0x70, 0x0C, 0x70, 0x00, 0x40, + 0x08, 0x30, 0xFF, 0x00, 0x26, 0x7C, 0x0C, 0x40, 0xC0, 0x17, 0x2C, 0x30, 0xFF, 0xFF, 0x2C, 0xC0, + 0x40, 0x45, 0x30, 0x57, 0x56, 0x53, 0xB1, 0x57, 0x10, 0x64, 0x24, 0x41, 0x57, 0x6C, 0x66, 0x65, + 0xB1, 0x67, 0x24, 0x74, 0xC6, 0x7C, 0x92, 0xF6, 0x4B, 0x2F, 0x00, 0x00, 0x04, 0xC5, 0xAB, 0x3C, + 0x00, 0x00, 0x04, 0x21, 0x0C, 0x30, 0x00, 0x20, 0x4B, 0x3A, 0x00, 0x00, 0x8B, 0x37, 0x00, 0x00, + 0xB4, 0xC1, 0x92, 0xF8, 0x6B, 0xAD, 0x00, 0x00, 0xEB, 0xAF, 0x01, 0x00, 0x0B, 0x31, 0x00, 0x00, + 0x2B, 0x3D, 0x00, 0x00, 0x38, 0x70, 0x08, 0x0B, 0xD4, 0x71, 0x18, 0x70, 0xB2, 0x1B, 0x82, 0x07, + 0x5C, 0x70, 0x70, 0x00, 0x1C, 0x60, 0x7F, 0x00, 0x66, 0x76, 0xF2, 0x05, 0x1C, 0x60, 0x10, 0x00, + 0x56, 0x76, 0x64, 0x71, 0x99, 0x70, 0xB2, 0x1B, 0x6B, 0x32, 0x00, 0x00, 0x04, 0x71, 0xB9, 0x70, + 0x8C, 0x19, 0xF2, 0x45, 0xB8, 0x70, 0x8C, 0x19, 0x82, 0x42, 0x99, 0x00, 0xB6, 0x1B, 0x14, 0x61, + 0x99, 0x60, 0xB5, 0x1B, 0xA9, 0x00, 0x86, 0x1B, 0xB9, 0x00, 0x7C, 0x19, 0xB9, 0x00, 0x78, 0x19, + 0x99, 0x00, 0xB4, 0x1B, 0xB9, 0x00, 0x74, 0x19, 0xB9, 0x00, 0x70, 0x19, 0x99, 0x00, 0xB3, 0x1B, + 0xCB, 0x31, 0x00, 0x00, 0xAB, 0x40, 0x00, 0x00, 0x18, 0x20, 0xB2, 0x1B, 0x5C, 0x20, 0xF0, 0x00, + 0x64, 0x23, 0x99, 0x20, 0xB2, 0x1B, 0x6B, 0x44, 0x00, 0x00, 0x18, 0x20, 0xB2, 0x1B, 0x04, 0xD5, + 0xEB, 0x4E, 0x00, 0x00, 0xAB, 0x3C, 0x00, 0x00, 0x4B, 0x2F, 0x00, 0x00, 0x04, 0x21, 0x0C, 0x30, + 0x00, 0x20, 0x4B, 0x3A, 0x00, 0x00, 0x8B, 0x37, 0x00, 0x00, 0xB4, 0xD1, 0x92, 0xF8, 0xEB, 0xAF, + 0x01, 0x00, 0x0B, 0x31, 0x00, 0x00, 0x2B, 0x3D, 0x00, 0x00, 0x6B, 0x32, 0x00, 0x00, 0x98, 0x70, + 0x9F, 0x1B, 0xB9, 0x00, 0x8C, 0x19, 0x82, 0x03, 0x6B, 0xDB, 0x04, 0x00, 0x50, 0xC1, 0x2C, 0x10, + 0x10, 0x00, 0xE1, 0xF0, 0x08, 0x20, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x2C, 0x20, 0x80, 0x02, + 0x2C, 0x40, 0x5C, 0x04, 0x36, 0x42, 0x08, 0x30, 0x00, 0x80, 0x3C, 0x10, 0x10, 0x00, 0x2C, 0x30, + 0x48, 0xA0, 0x77, 0x41, 0xD1, 0xC1, 0x0C, 0xF0, 0x5C, 0x01, 0xF1, 0xF0, 0x08, 0x40, 0x00, 0x80, + 0x0C, 0x20, 0x90, 0x01, 0x04, 0x30, 0x2C, 0x40, 0x00, 0xF0, 0x0C, 0xF0, 0x04, 0x04, 0xF1, 0xF0, + 0xB9, 0x20, 0x14, 0x00, 0x08, 0x70, 0x00, 0x80, 0x38, 0xD7, 0xD0, 0xFB, 0x06, 0xE2, 0xCC, 0xD0, + 0xFF, 0x00, 0x82, 0x17, 0xC6, 0xD2, 0x82, 0x15, 0xCB, 0xB9, 0x00, 0x00, 0x08, 0x60, 0x1C, 0xE1, + 0x08, 0x70, 0x00, 0x30, 0x2C, 0x60, 0x01, 0xE9, 0xB9, 0x67, 0x04, 0x01, 0xB9, 0xD7, 0x08, 0x01, + 0xB9, 0xE7, 0x0C, 0x01, 0xEB, 0x6A, 0x00, 0x00, 0x04, 0x2A, 0xAB, 0xED, 0x00, 0x00, 0xF2, 0xFB, + 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x98, 0x60, 0xAE, 0x1B, 0x3C, 0x10, 0x10, 0x00, + 0xD1, 0xC1, 0x82, 0x0F, 0x34, 0x61, 0x93, 0x66, 0x99, 0x60, 0xAE, 0x1B, 0x92, 0x67, 0x0C, 0x60, + 0xFC, 0x0A, 0x99, 0x00, 0xB0, 0x1B, 0x38, 0x76, 0x0C, 0x00, 0x14, 0x45, 0x56, 0x74, 0xF2, 0x5C, + 0xDC, 0x20, 0x80, 0x00, 0x08, 0xE0, 0x00, 0x80, 0x2C, 0xE0, 0x0C, 0xDC, 0x82, 0x04, 0x18, 0xDE, + 0x6F, 0x00, 0xF2, 0x03, 0x18, 0xDE, 0x6E, 0x00, 0x4B, 0x3F, 0x00, 0x00, 0xC6, 0x2D, 0xA2, 0x0A, + 0x38, 0x50, 0x78, 0x19, 0x18, 0x60, 0xAF, 0x1B, 0x34, 0x53, 0xC6, 0x65, 0xB2, 0x1A, 0x24, 0x61, + 0xF2, 0x16, 0x98, 0x60, 0xAF, 0x1B, 0x82, 0x15, 0x98, 0x50, 0xB6, 0x1B, 0x82, 0x04, 0xB8, 0x50, + 0x7C, 0x19, 0x92, 0x0F, 0x18, 0x5E, 0x70, 0x00, 0x36, 0xD5, 0xC6, 0x2D, 0xD2, 0x0A, 0x18, 0x40, + 0xAD, 0x1B, 0x28, 0x5E, 0x76, 0x00, 0xC6, 0x45, 0xD2, 0x04, 0x34, 0x61, 0x99, 0x60, 0xAF, 0x1B, + 0x98, 0x50, 0xB0, 0x1B, 0x18, 0x50, 0xAF, 0x1B, 0x92, 0x0E, 0x18, 0x7E, 0x71, 0x00, 0xC6, 0x57, + 0xA2, 0x18, 0x04, 0x71, 0x0C, 0x50, 0xFC, 0x0A, 0x99, 0x70, 0xB0, 0x1B, 0x38, 0x75, 0x0C, 0x00, + 0x64, 0x74, 0xF2, 0x0D, 0x18, 0x7E, 0x72, 0x00, 0xC6, 0x57, 0xD2, 0x0B, 0x0C, 0x50, 0xFC, 0x0A, + 0x38, 0x75, 0x0C, 0x00, 0x99, 0x00, 0xB0, 0x1B, 0x14, 0x45, 0x56, 0x74, 0xB9, 0x75, 0x0C, 0x00, + 0xB8, 0x70, 0x8C, 0x19, 0x82, 0x0B, 0x04, 0x71, 0x99, 0x70, 0xB0, 0x1B, 0x0C, 0x60, 0xFC, 0x0A, + 0x38, 0x76, 0x0C, 0x00, 0x64, 0x74, 0xB9, 0x76, 0x0C, 0x00, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x18, 0xC1, 0xE1, 0x06, 0xE2, 0x6B, 0x56, 0x00, 0x00, 0x06, 0x2E, + 0x0B, 0x51, 0x00, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x14, 0x00, + 0xD9, 0xC1, 0x04, 0x00, 0xB1, 0xB1, 0x06, 0xD2, 0xCB, 0x31, 0x00, 0x00, 0x18, 0x20, 0xB2, 0x1B, + 0x5C, 0x20, 0xF0, 0x00, 0x64, 0x23, 0x99, 0x20, 0xB2, 0x1B, 0x6B, 0x44, 0x00, 0x00, 0x18, 0x20, + 0xB2, 0x1B, 0xEB, 0x4E, 0x00, 0x00, 0x4B, 0x2F, 0x00, 0x00, 0x04, 0x20, 0xAB, 0x39, 0x04, 0x00, + 0xAB, 0x3C, 0x00, 0x00, 0xC4, 0xD0, 0x92, 0x08, 0x04, 0x21, 0x0C, 0x30, 0x00, 0x20, 0x4B, 0x3A, + 0x00, 0x00, 0x8B, 0x37, 0x00, 0x00, 0xCB, 0x3B, 0x00, 0x00, 0x08, 0x70, 0x00, 0x80, 0x18, 0xB7, + 0x66, 0xDC, 0x04, 0xE0, 0xC6, 0xBE, 0x82, 0x16, 0x04, 0x21, 0x0C, 0x30, 0x00, 0x20, 0x4B, 0x3A, + 0x00, 0x00, 0x8B, 0x37, 0x00, 0x00, 0xC4, 0xD0, 0x92, 0x09, 0xB8, 0x70, 0x8C, 0x19, 0x92, 0x1B, + 0x0C, 0x20, 0xD0, 0x07, 0x6B, 0xEB, 0x00, 0x00, 0xF2, 0x16, 0x8B, 0xBB, 0x00, 0x00, 0xC4, 0x20, + 0x82, 0xF5, 0xEB, 0xAF, 0x01, 0x00, 0x0B, 0x31, 0x00, 0x00, 0x2B, 0x3D, 0x00, 0x00, 0x04, 0x61, + 0x99, 0x60, 0xB3, 0x1B, 0x6B, 0x32, 0x00, 0x00, 0x58, 0xC1, 0x04, 0x00, 0x30, 0xB1, 0x2C, 0x10, + 0x14, 0x00, 0xE1, 0xF0, 0x24, 0xE1, 0xF2, 0xD7, 0x34, 0x18, 0xC1, 0xE1, 0x08, 0x70, 0x00, 0x40, + 0x38, 0x77, 0x14, 0x10, 0xDC, 0x70, 0x00, 0x01, 0x92, 0x0F, 0x99, 0x00, 0x9D, 0x1B, 0xCB, 0x67, + 0x00, 0x00, 0x2B, 0x68, 0x00, 0x00, 0x18, 0x70, 0x9D, 0x1B, 0x93, 0x07, 0x92, 0x03, 0xCB, 0x5A, + 0x00, 0x00, 0xEB, 0x68, 0x00, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x98, 0x70, 0xA3, 0x1B, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xE2, 0x92, 0x0A, 0x0C, 0x70, 0xFC, 0x0A, 0xA8, 0x67, + 0x10, 0x00, 0x82, 0x05, 0x34, 0x61, 0xA9, 0x67, 0x10, 0x00, 0xF2, 0x4C, 0x18, 0x70, 0xB6, 0x1B, + 0xC4, 0x71, 0x92, 0x07, 0x98, 0x60, 0xB5, 0x1B, 0x92, 0x04, 0xA9, 0x70, 0x0C, 0x0B, 0xF2, 0x42, + 0x38, 0x50, 0x6C, 0x19, 0xCC, 0x50, 0xE8, 0x03, 0xC2, 0x04, 0x0C, 0x50, 0xE9, 0x03, 0xF2, 0x02, + 0x24, 0x51, 0xC4, 0x70, 0xB9, 0x50, 0x6C, 0x19, 0x82, 0x04, 0x28, 0x70, 0x82, 0x1B, 0xF2, 0x18, + 0x08, 0xD0, 0x00, 0x80, 0x38, 0xC0, 0x70, 0x19, 0x2C, 0xD0, 0x0C, 0xDC, 0x38, 0x2D, 0x48, 0x00, + 0x38, 0x3D, 0x38, 0x00, 0x04, 0x61, 0x26, 0x6C, 0xB9, 0x60, 0x70, 0x19, 0xAB, 0x15, 0x00, 0x00, + 0xC6, 0xC2, 0xA2, 0x04, 0x38, 0x7D, 0x4C, 0x00, 0xF2, 0x03, 0x28, 0x70, 0x84, 0x1B, 0xC6, 0x7E, + 0xC2, 0x19, 0x3F, 0xEE, 0x07, 0x00, 0x06, 0x2E, 0x06, 0x7E, 0xD7, 0x72, 0xD7, 0x21, 0x26, 0x27, + 0x36, 0x2E, 0xD7, 0x21, 0x0C, 0x30, 0x10, 0x27, 0xAB, 0x15, 0x00, 0x00, 0xC4, 0x2A, 0xC2, 0x0A, + 0x98, 0x70, 0xA4, 0x1B, 0x82, 0x04, 0xCB, 0x3A, 0x01, 0x00, 0xF2, 0x04, 0x06, 0x2E, 0x8B, 0xEA, + 0x00, 0x00, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x98, 0x70, 0xA2, 0x1B, + 0x82, 0x06, 0x08, 0x70, 0x00, 0x80, 0x28, 0x47, 0xAE, 0xDC, 0xF2, 0x05, 0x38, 0x70, 0x70, 0x1A, + 0x28, 0x47, 0x28, 0x00, 0x98, 0x60, 0xAC, 0x1B, 0x82, 0x06, 0x34, 0x61, 0x99, 0x60, 0xAC, 0x1B, + 0x04, 0x21, 0xF2, 0x33, 0x0C, 0x70, 0xFC, 0x0A, 0x38, 0x57, 0x0C, 0x00, 0x08, 0x60, 0x08, 0x00, + 0xD6, 0x65, 0x82, 0x08, 0x08, 0x60, 0xF7, 0xFF, 0x2C, 0x60, 0xFF, 0xFF, 0x56, 0x65, 0xB9, 0x67, + 0x0C, 0x00, 0x28, 0x67, 0x12, 0x03, 0x26, 0x46, 0x28, 0x67, 0x18, 0x03, 0xC6, 0x46, 0x02, 0x1A, + 0x98, 0x67, 0x8D, 0x06, 0x92, 0x17, 0x98, 0x67, 0xA2, 0x06, 0x92, 0x14, 0x38, 0x77, 0x0C, 0x00, + 0xDC, 0x70, 0x00, 0xF0, 0x92, 0x0F, 0x38, 0x60, 0x74, 0x19, 0x04, 0x21, 0x24, 0x61, 0xB9, 0x60, + 0x74, 0x19, 0x38, 0x50, 0x70, 0x1A, 0x18, 0x55, 0x2A, 0x00, 0xC6, 0x65, 0xD2, 0x06, 0x06, 0x27, + 0xF2, 0x04, 0xB9, 0x00, 0x74, 0x19, 0x04, 0x20, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, + 0x08, 0x70, 0x00, 0x40, 0xB9, 0x07, 0xF0, 0x70, 0xB9, 0x07, 0xF4, 0x70, 0xC4, 0x21, 0xB9, 0x07, + 0xF8, 0x70, 0xB9, 0x07, 0x34, 0x71, 0x08, 0x60, 0x01, 0x00, 0x92, 0x05, 0x66, 0x63, 0xB9, 0x67, + 0xF0, 0x70, 0xF2, 0x15, 0xC4, 0x22, 0x92, 0x05, 0x66, 0x63, 0xB9, 0x67, 0xF4, 0x70, 0xF2, 0x0F, + 0xC4, 0x23, 0x92, 0x05, 0x66, 0x63, 0xB9, 0x67, 0xF8, 0x70, 0xF2, 0x09, 0x0C, 0x50, 0x80, 0x02, + 0x66, 0x56, 0xB9, 0x57, 0xF0, 0x70, 0x66, 0x63, 0xB9, 0x67, 0x34, 0x71, 0x0C, 0x20, 0x10, 0x00, + 0x0C, 0x30, 0x00, 0x50, 0x4B, 0x3A, 0x00, 0x00, 0x8B, 0x37, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x18, 0x00, 0xD9, 0xC1, 0x08, 0x00, 0x18, 0xD0, 0xB6, 0x1B, + 0x18, 0x60, 0xB5, 0x1B, 0xC1, 0xA1, 0xC6, 0x6D, 0x82, 0x61, 0x99, 0xD0, 0xB5, 0x1B, 0xC4, 0xD0, + 0x18, 0x70, 0xB2, 0x1B, 0x1C, 0x60, 0x10, 0x00, 0x56, 0x76, 0x82, 0x05, 0x64, 0x72, 0x99, 0x70, + 0xB2, 0x1B, 0xF2, 0x48, 0x64, 0x71, 0x99, 0x70, 0xB2, 0x1B, 0x4B, 0xFD, 0x01, 0x00, 0xCB, 0xFB, + 0x01, 0x00, 0xA9, 0x00, 0x86, 0x1B, 0xB9, 0x00, 0x7C, 0x19, 0xB9, 0x00, 0x74, 0x19, 0xA9, 0x00, + 0x88, 0x1B, 0x14, 0x61, 0x99, 0x00, 0xC6, 0x1B, 0x99, 0x60, 0x60, 0x19, 0x06, 0x6D, 0x06, 0x7D, + 0x0C, 0xA0, 0x38, 0x19, 0x1C, 0x40, 0x64, 0x00, 0x0C, 0xB0, 0x10, 0x19, 0x0C, 0xD0, 0xC4, 0x1A, + 0x14, 0x51, 0x0C, 0xF0, 0xB0, 0x1A, 0x0C, 0x20, 0x88, 0x1A, 0x2F, 0x3A, 0x07, 0x00, 0xB1, 0x43, + 0x2F, 0x3B, 0x07, 0x00, 0xB1, 0x43, 0x2F, 0x3D, 0x06, 0x00, 0xA1, 0x53, 0x2F, 0x3F, 0x06, 0x00, + 0xA1, 0x53, 0x2F, 0x32, 0x07, 0x00, 0x24, 0x74, 0xCC, 0x70, 0x28, 0x00, 0xB1, 0x03, 0x24, 0x62, + 0x92, 0xED, 0x38, 0x70, 0x70, 0x1A, 0x04, 0x50, 0x18, 0x27, 0x47, 0x00, 0x18, 0x37, 0x90, 0x00, + 0x18, 0x47, 0x8F, 0x00, 0x18, 0x67, 0x2A, 0x00, 0x0C, 0xF0, 0xE0, 0x00, 0xF1, 0xF0, 0xB9, 0x20, + 0x78, 0x19, 0x98, 0x70, 0xB6, 0x1B, 0x82, 0x06, 0x04, 0x20, 0x0C, 0x30, 0x54, 0x05, 0xEB, 0x46, + 0x01, 0x00, 0x18, 0x20, 0xB2, 0x1B, 0xAB, 0x34, 0x01, 0x00, 0x18, 0x20, 0xB2, 0x1B, 0x6B, 0x44, + 0x00, 0x00, 0x18, 0x20, 0xB2, 0x1B, 0x4B, 0x2D, 0x01, 0x00, 0x18, 0x20, 0xB2, 0x1B, 0xEB, 0x4E, + 0x00, 0x00, 0xCB, 0xAF, 0x01, 0x00, 0x58, 0xC1, 0x08, 0x00, 0x40, 0xA1, 0x2C, 0x10, 0x18, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x04, 0x24, 0xB1, 0xF1, 0x8B, 0x34, 0x00, 0x00, 0x04, 0x24, + 0x0C, 0x30, 0x00, 0x30, 0x4B, 0x3A, 0x00, 0x00, 0x8B, 0x37, 0x00, 0x00, 0x0C, 0x20, 0x11, 0x00, + 0x8B, 0x34, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x04, 0x28, + 0x0C, 0x30, 0x00, 0x40, 0xB1, 0xF1, 0x4B, 0x3A, 0x00, 0x00, 0x8B, 0x37, 0x00, 0x00, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0x04, 0x62, 0xB1, 0xF1, 0x99, 0x60, 0xB3, 0x1B, 0xCB, 0x31, + 0x00, 0x00, 0xAB, 0x3C, 0x00, 0x00, 0x4B, 0x2F, 0x00, 0x00, 0x0C, 0x30, 0x00, 0x20, 0x04, 0x21, + 0x4B, 0x3A, 0x00, 0x00, 0x2B, 0x07, 0x02, 0x00, 0x8B, 0x37, 0x00, 0x00, 0x6B, 0xA4, 0x04, 0x00, + 0x2B, 0x52, 0x01, 0x00, 0x6B, 0x53, 0x01, 0x00, 0xCB, 0x92, 0x01, 0x00, 0x0B, 0x93, 0x03, 0x00, + 0x93, 0x22, 0x92, 0x0C, 0x18, 0x70, 0xA1, 0x1B, 0x5C, 0x70, 0xF0, 0x00, 0xCC, 0x70, 0x40, 0x00, + 0x82, 0x0D, 0x04, 0x61, 0x99, 0x60, 0xB6, 0x1B, 0xF2, 0x09, 0xCB, 0x39, 0x04, 0x00, 0x04, 0x20, + 0x06, 0x32, 0x4B, 0xB3, 0x01, 0x00, 0x0B, 0x92, 0x01, 0x00, 0x0B, 0x31, 0x00, 0x00, 0x6B, 0x32, + 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0xB8, 0x70, 0x8C, 0x19, 0x3C, 0x10, 0x48, 0x00, + 0xD9, 0xC1, 0x38, 0x00, 0xD9, 0x81, 0x28, 0x00, 0x9A, 0x92, 0x02, 0x00, 0x38, 0x80, 0x08, 0x0B, + 0xD4, 0x81, 0x9A, 0x8D, 0x02, 0x00, 0x08, 0x40, 0x00, 0x30, 0xB9, 0x81, 0x10, 0x00, 0x06, 0xC8, + 0x06, 0xD8, 0xB9, 0x81, 0x0C, 0x00, 0xB9, 0x81, 0x08, 0x00, 0x06, 0xA8, 0x06, 0xE8, 0xB9, 0x81, + 0x04, 0x00, 0xB1, 0x81, 0x06, 0x98, 0x06, 0xB8, 0xB9, 0x81, 0x14, 0x00, 0x2C, 0x40, 0x00, 0x49, + 0x06, 0x78, 0x57, 0x71, 0x26, 0x74, 0x30, 0x77, 0xB9, 0x41, 0x24, 0x00, 0x0C, 0x60, 0xFF, 0x0F, + 0x23, 0x58, 0x56, 0x67, 0x77, 0x78, 0x5C, 0x70, 0xFF, 0x0F, 0x06, 0x25, 0x0C, 0x30, 0x18, 0x00, + 0xB9, 0x51, 0x20, 0x00, 0xB9, 0x61, 0x18, 0x00, 0xB9, 0x71, 0x1C, 0x00, 0x4B, 0x18, 0x00, 0x00, + 0x23, 0x22, 0xC4, 0x2A, 0x38, 0x41, 0x24, 0x00, 0x38, 0x51, 0x20, 0x00, 0x38, 0x61, 0x18, 0x00, + 0x38, 0x71, 0x1C, 0x00, 0xD2, 0x31, 0xCC, 0x50, 0xA7, 0x00, 0xD2, 0x1A, 0x3F, 0x57, 0x06, 0x00, + 0xCC, 0x50, 0x14, 0x00, 0x02, 0x0A, 0x38, 0x61, 0x14, 0x00, 0x04, 0x71, 0x26, 0x65, 0x26, 0x79, + 0xB9, 0x61, 0x14, 0x00, 0x23, 0x97, 0xF2, 0x57, 0x36, 0x76, 0xCC, 0x70, 0x14, 0x00, 0x02, 0x53, + 0x38, 0x71, 0x0C, 0x00, 0x24, 0x71, 0x23, 0x77, 0xB9, 0x71, 0x0C, 0x00, 0xF2, 0x4C, 0xCC, 0x50, + 0xD7, 0x00, 0xC2, 0x49, 0x3F, 0x57, 0x06, 0x00, 0xCC, 0x50, 0x14, 0x00, 0x02, 0x06, 0x30, 0x71, + 0x24, 0x71, 0x23, 0x77, 0xB1, 0x71, 0xF2, 0x3F, 0x36, 0x76, 0xC4, 0x7A, 0x02, 0x3C, 0x24, 0xD1, + 0x26, 0xA7, 0x23, 0xDD, 0xF2, 0x38, 0xCC, 0x50, 0xA7, 0x00, 0xD2, 0x1C, 0xCC, 0x20, 0x17, 0x00, + 0x82, 0x32, 0x3F, 0x57, 0x06, 0x00, 0xCC, 0x50, 0x14, 0x00, 0x02, 0x08, 0x38, 0x71, 0x04, 0x00, + 0x24, 0x71, 0x23, 0x77, 0xB9, 0x71, 0x04, 0x00, 0xF2, 0x26, 0x36, 0x76, 0xCC, 0x70, 0x14, 0x00, + 0x02, 0x22, 0x38, 0x61, 0x08, 0x00, 0x24, 0xC1, 0x26, 0x67, 0xB9, 0x61, 0x08, 0x00, 0x23, 0xCC, + 0xF2, 0x1A, 0xCC, 0x50, 0xD7, 0x00, 0xC2, 0x17, 0xCC, 0x20, 0x17, 0x00, 0x82, 0x14, 0x3F, 0x57, + 0x06, 0x00, 0xCC, 0x50, 0x14, 0x00, 0x02, 0x05, 0x24, 0xE1, 0x26, 0xB5, 0x23, 0xEE, 0xF2, 0x0B, + 0x36, 0x76, 0xCC, 0x70, 0x14, 0x00, 0x02, 0x07, 0x38, 0x71, 0x10, 0x00, 0x24, 0x71, 0x23, 0x77, + 0xB9, 0x71, 0x10, 0x00, 0x24, 0x81, 0xCC, 0x80, 0x50, 0x01, 0x9A, 0x73, 0xFF, 0xFF, 0x18, 0x20, + 0xAC, 0x1B, 0x04, 0x70, 0x08, 0x30, 0x00, 0x30, 0x06, 0x67, 0x0C, 0x80, 0x74, 0x1A, 0x2C, 0x30, + 0x00, 0x49, 0x0C, 0x50, 0x84, 0x19, 0x2F, 0x48, 0x07, 0x00, 0x20, 0x44, 0x0C, 0xF0, 0xFF, 0x0F, + 0x57, 0x41, 0x26, 0x43, 0x30, 0x44, 0x56, 0xF4, 0x77, 0x48, 0x5C, 0x40, 0xFF, 0x0F, 0xC6, 0x4F, + 0xC2, 0x18, 0x36, 0x4F, 0xCC, 0x40, 0x64, 0x00, 0x02, 0x08, 0xCC, 0x40, 0x78, 0x00, 0x12, 0x03, + 0x24, 0x61, 0xF2, 0x02, 0x24, 0x62, 0x23, 0x66, 0xC4, 0x62, 0xC2, 0x0A, 0x30, 0x45, 0x24, 0x41, + 0xC4, 0x4A, 0xB1, 0x45, 0x02, 0x06, 0xB1, 0x05, 0x0C, 0x20, 0x96, 0x00, 0xF2, 0x02, 0xB1, 0x05, + 0x24, 0x72, 0xC4, 0x76, 0x92, 0xD9, 0x99, 0x20, 0xAC, 0x1B, 0x38, 0x21, 0x14, 0x00, 0x04, 0x31, + 0x26, 0x39, 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x18, 0x00, 0x06, 0x82, 0x02, 0x2E, 0xCC, 0x90, + 0x10, 0x00, 0xC2, 0x31, 0x04, 0x31, 0x06, 0x2A, 0x26, 0x3D, 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, + 0x18, 0x00, 0x02, 0x26, 0xCC, 0xD0, 0x20, 0x00, 0xC2, 0x23, 0x30, 0x61, 0xC4, 0x6F, 0xD2, 0x20, + 0x38, 0x21, 0x08, 0x00, 0x04, 0x31, 0x26, 0x3C, 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x50, 0x00, + 0x02, 0x17, 0xCC, 0xC0, 0x30, 0x00, 0xC2, 0x14, 0x38, 0x71, 0x04, 0x00, 0xC4, 0x7F, 0xD2, 0x10, + 0x04, 0x31, 0x06, 0x2B, 0x26, 0x3E, 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x40, 0x00, 0x02, 0x08, + 0xCC, 0xE0, 0x20, 0x00, 0xD2, 0x64, 0xF2, 0x04, 0xCC, 0x20, 0x10, 0x00, 0x02, 0x32, 0xCC, 0x90, + 0x14, 0x00, 0xD2, 0x2F, 0x38, 0x61, 0x0C, 0x00, 0xCC, 0x60, 0x15, 0x00, 0xC2, 0x5D, 0x04, 0x31, + 0x06, 0x2A, 0x26, 0x3D, 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x40, 0x00, 0x02, 0x22, 0xCC, 0xD0, + 0x30, 0x00, 0xC2, 0x1F, 0x30, 0x71, 0xC4, 0x7F, 0xD2, 0x1C, 0x38, 0x21, 0x08, 0x00, 0x04, 0x31, + 0x26, 0x3C, 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x40, 0x00, 0x02, 0x13, 0xCC, 0xC0, 0x40, 0x00, + 0xC2, 0x10, 0x38, 0x61, 0x04, 0x00, 0xC4, 0x6F, 0xD2, 0x0C, 0x04, 0x31, 0x06, 0x2B, 0x26, 0x3E, + 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x50, 0x00, 0x02, 0x04, 0xCC, 0xE0, 0x30, 0x00, 0xD2, 0x2F, + 0x38, 0x71, 0x0C, 0x00, 0xCC, 0x70, 0x30, 0x00, 0xC2, 0x2F, 0x04, 0x31, 0x06, 0x2A, 0x26, 0x3D, + 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x50, 0x00, 0x02, 0x27, 0xCC, 0xD0, 0x30, 0x00, 0xC2, 0x24, + 0x30, 0x61, 0xC4, 0x6F, 0xD2, 0x21, 0x38, 0x21, 0x08, 0x00, 0x04, 0x31, 0x26, 0x3C, 0x8B, 0x16, + 0x00, 0x00, 0xCC, 0x20, 0x80, 0x00, 0x02, 0x18, 0xCC, 0xC0, 0x40, 0x00, 0xC2, 0x15, 0x38, 0x71, + 0x04, 0x00, 0xC4, 0x7F, 0xD2, 0x11, 0x04, 0x31, 0x06, 0x2B, 0x26, 0x3E, 0x8B, 0x16, 0x00, 0x00, + 0xCC, 0x20, 0x40, 0x00, 0x02, 0x09, 0xCC, 0xE0, 0x30, 0x00, 0xC2, 0x06, 0x38, 0x61, 0x10, 0x00, + 0xC4, 0x6F, 0xCA, 0x05, 0x01, 0x00, 0xCC, 0x80, 0x14, 0x00, 0x0A, 0xA9, 0x00, 0x00, 0xC4, 0x90, + 0x82, 0x6D, 0x38, 0x71, 0x0C, 0x00, 0xCC, 0x70, 0x1F, 0x00, 0xD2, 0x2F, 0x04, 0x31, 0x06, 0x2A, + 0x26, 0x3D, 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x20, 0x00, 0x02, 0x27, 0xCC, 0xD0, 0x30, 0x00, + 0xC2, 0x24, 0x30, 0x61, 0xC4, 0x61, 0xD2, 0x21, 0x38, 0x21, 0x08, 0x00, 0x04, 0x31, 0x26, 0x3C, + 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x30, 0x00, 0x02, 0x18, 0xCC, 0xC0, 0x40, 0x00, 0xC2, 0x15, + 0x38, 0x71, 0x04, 0x00, 0xC4, 0x71, 0xD2, 0x11, 0x04, 0x31, 0x06, 0x2B, 0x26, 0x3E, 0x8B, 0x16, + 0x00, 0x00, 0xCC, 0x20, 0x20, 0x00, 0x02, 0x09, 0xCC, 0xE0, 0x20, 0x00, 0xC2, 0x06, 0x38, 0x61, + 0x10, 0x00, 0xC4, 0x61, 0xCA, 0xCC, 0x00, 0x00, 0xCC, 0x80, 0x30, 0x00, 0x02, 0x3B, 0xCC, 0x90, + 0x20, 0x00, 0xC2, 0x3B, 0x38, 0x71, 0x0C, 0x00, 0xC4, 0x79, 0xD2, 0x37, 0x04, 0x31, 0x06, 0x2A, + 0x26, 0x3D, 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x1A, 0x00, 0x02, 0x2F, 0xCC, 0xD0, 0x20, 0x00, + 0xC2, 0x2C, 0x30, 0x61, 0xC4, 0x61, 0xD2, 0x29, 0x38, 0x21, 0x08, 0x00, 0x04, 0x31, 0x26, 0x3C, + 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x1A, 0x00, 0x02, 0x20, 0xCC, 0xC0, 0x20, 0x00, 0xC2, 0x1D, + 0x38, 0x71, 0x04, 0x00, 0xC4, 0x79, 0xD2, 0x19, 0x04, 0x31, 0x06, 0x2B, 0x26, 0x3E, 0x8B, 0x16, + 0x00, 0x00, 0xCC, 0x20, 0x50, 0x00, 0x02, 0x11, 0xCC, 0xE0, 0x26, 0x00, 0xC2, 0x0E, 0x38, 0x61, + 0x10, 0x00, 0xC4, 0x61, 0xD2, 0x0A, 0xFA, 0x93, 0x00, 0x00, 0xCC, 0x80, 0x30, 0x00, 0x1A, 0x9D, + 0x00, 0x00, 0xCC, 0x80, 0x20, 0x00, 0x02, 0x33, 0xCC, 0x90, 0x10, 0x00, 0xC2, 0x33, 0x38, 0x71, + 0x0C, 0x00, 0xC4, 0x79, 0xD2, 0x31, 0x04, 0x31, 0x06, 0x2A, 0x26, 0x3D, 0x8B, 0x16, 0x00, 0x00, + 0xC4, 0x2A, 0x02, 0x2A, 0xC4, 0xD7, 0xC2, 0x28, 0x30, 0x61, 0xC4, 0x61, 0xD2, 0x25, 0x38, 0x21, + 0x08, 0x00, 0x04, 0x31, 0x26, 0x3C, 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x10, 0x00, 0x02, 0x1C, + 0xC4, 0xC8, 0xC2, 0x1A, 0x38, 0x71, 0x04, 0x00, 0xC4, 0x79, 0xD2, 0x16, 0x04, 0x31, 0x06, 0x2B, + 0x26, 0x3E, 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x2A, 0x00, 0x02, 0x0E, 0xCC, 0xE0, 0x20, 0x00, + 0xC2, 0x0B, 0x38, 0x61, 0x10, 0x00, 0xC4, 0x61, 0xD2, 0x07, 0xF2, 0x59, 0xCC, 0x80, 0x18, 0x00, + 0x02, 0x64, 0xC4, 0x96, 0xC2, 0x31, 0x38, 0x71, 0x0C, 0x00, 0xC4, 0x74, 0xD2, 0x2F, 0x04, 0x31, + 0x06, 0x2A, 0x26, 0x3D, 0x8B, 0x16, 0x00, 0x00, 0xC4, 0x26, 0x02, 0x28, 0xC4, 0xD8, 0xC2, 0x26, + 0x30, 0x61, 0xC4, 0x61, 0xD2, 0x23, 0x38, 0x21, 0x08, 0x00, 0x04, 0x31, 0x26, 0x3C, 0x8B, 0x16, + 0x00, 0x00, 0xCC, 0x20, 0x14, 0x00, 0x02, 0x1A, 0xCC, 0xC0, 0x10, 0x00, 0xC2, 0x17, 0x38, 0x71, + 0x04, 0x00, 0xC4, 0x71, 0xD2, 0x13, 0x04, 0x31, 0x06, 0x2B, 0x26, 0x3E, 0x8B, 0x16, 0x00, 0x00, + 0xCC, 0x20, 0x16, 0x00, 0x02, 0x0B, 0xCC, 0xE0, 0x28, 0x00, 0xC2, 0x08, 0x38, 0x61, 0x10, 0x00, + 0xC4, 0x61, 0xD2, 0x04, 0xF2, 0x24, 0xC4, 0x94, 0xC2, 0x30, 0xB8, 0x71, 0x0C, 0x00, 0x92, 0x2D, + 0x04, 0x31, 0x06, 0x2A, 0x26, 0x3D, 0x8B, 0x16, 0x00, 0x00, 0xC4, 0x26, 0x02, 0x26, 0xC4, 0xD2, + 0xC2, 0x24, 0xB0, 0x61, 0x92, 0x22, 0xC4, 0xC0, 0x92, 0x20, 0xB8, 0x71, 0x04, 0x00, 0x92, 0x1D, + 0x04, 0x31, 0x06, 0x2B, 0x26, 0x3E, 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x16, 0x00, 0x02, 0x15, + 0xCC, 0xE0, 0x10, 0x00, 0xC2, 0x12, 0xB8, 0x61, 0x10, 0x00, 0x92, 0x0F, 0x38, 0x70, 0x88, 0x19, + 0x24, 0x71, 0xC4, 0x7A, 0xB9, 0x70, 0x88, 0x19, 0x02, 0x0A, 0x1C, 0x60, 0x6A, 0x00, 0x99, 0x60, + 0xAC, 0x1B, 0x99, 0x00, 0xC6, 0x1B, 0xF2, 0x03, 0xB9, 0x00, 0x88, 0x19, 0x58, 0xC1, 0x38, 0x00, + 0x58, 0x81, 0x28, 0x00, 0x2C, 0x10, 0x48, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x18, 0x04, 0x63, + 0xC1, 0xE1, 0x99, 0x60, 0xB3, 0x1B, 0xCB, 0x31, 0x00, 0x00, 0x6B, 0x42, 0x01, 0x00, 0xC4, 0x20, + 0x82, 0x09, 0xAB, 0x3C, 0x00, 0x00, 0x04, 0x20, 0x0C, 0x30, 0x54, 0x05, 0xEB, 0x46, 0x01, 0x00, + 0xF2, 0x03, 0x2B, 0x3D, 0x00, 0x00, 0x4B, 0x2F, 0x00, 0x00, 0x04, 0x21, 0x0C, 0x30, 0x80, 0x02, + 0xEB, 0x46, 0x01, 0x00, 0x0C, 0x30, 0x28, 0x08, 0x04, 0x23, 0xEB, 0x46, 0x01, 0x00, 0x04, 0x21, + 0x8B, 0x39, 0x00, 0x00, 0xAB, 0x07, 0x02, 0x00, 0x06, 0xE2, 0x04, 0x21, 0x4B, 0x35, 0x00, 0x00, + 0x6B, 0xA4, 0x04, 0x00, 0x0B, 0x31, 0x00, 0x00, 0xCB, 0x57, 0x01, 0x00, 0x2B, 0x52, 0x01, 0x00, + 0x4B, 0xFD, 0x03, 0x00, 0x6B, 0x53, 0x01, 0x00, 0x06, 0x2E, 0xEB, 0x0A, 0x02, 0x00, 0xCB, 0x92, + 0x01, 0x00, 0xEB, 0x99, 0x01, 0x00, 0xAB, 0xA4, 0x01, 0x00, 0x6B, 0x32, 0x00, 0x00, 0x98, 0x70, + 0x19, 0x0E, 0x82, 0x0E, 0xB9, 0x00, 0x70, 0x19, 0x28, 0x60, 0x86, 0x1B, 0xB9, 0x00, 0x7C, 0x19, + 0xCC, 0x60, 0xEF, 0x00, 0xD2, 0x0A, 0x24, 0x61, 0xA9, 0x60, 0x86, 0x1B, 0xF2, 0x06, 0x38, 0x60, + 0x7C, 0x19, 0x24, 0x61, 0xB9, 0x60, 0x7C, 0x19, 0x38, 0x60, 0x78, 0x19, 0x38, 0x70, 0x7C, 0x19, + 0x24, 0x63, 0xC6, 0x76, 0xA2, 0x05, 0x99, 0x00, 0xB6, 0x1B, 0x99, 0x00, 0xAD, 0x1B, 0x98, 0x60, + 0xB4, 0x1B, 0x82, 0x10, 0x18, 0x50, 0xB7, 0x1B, 0x99, 0x00, 0xB4, 0x1B, 0x04, 0x20, 0x24, 0x51, + 0x99, 0x50, 0xB7, 0x1B, 0x99, 0x00, 0xB6, 0x1B, 0x0B, 0x78, 0x00, 0x00, 0x04, 0x21, 0x6B, 0x35, + 0x01, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x98, 0x70, 0xB6, 0x1B, 0x34, 0x14, 0xB1, 0xF1, + 0x92, 0x04, 0x98, 0x70, 0xB1, 0x1B, 0x82, 0x04, 0xEB, 0x81, 0x01, 0x00, 0xF2, 0x03, 0x2B, 0x54, + 0x01, 0x00, 0x0B, 0xF5, 0x01, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, + 0x4B, 0xDE, 0x00, 0x00, 0xC4, 0x20, 0x82, 0x03, 0xEB, 0x6A, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x04, 0x20, 0xB1, 0xF1, 0x4B, 0x77, 0x00, 0x00, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x18, 0x04, 0x20, 0xC1, 0xE1, 0x4B, 0x79, 0x00, 0x00, 0x06, 0xE2, + 0x04, 0x20, 0x0B, 0x78, 0x00, 0x00, 0x06, 0x2E, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, + 0x34, 0x18, 0xC1, 0xE1, 0xEB, 0xBB, 0x00, 0x00, 0xC4, 0x20, 0x82, 0x07, 0x38, 0x20, 0x68, 0x19, + 0x6B, 0xBD, 0x00, 0x00, 0xB9, 0x00, 0x68, 0x19, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, + 0x34, 0x18, 0x04, 0x21, 0xC1, 0xE1, 0x4B, 0x77, 0x00, 0x00, 0xEB, 0xBB, 0x00, 0x00, 0xC4, 0x20, + 0x92, 0x03, 0x2B, 0xE5, 0x00, 0x00, 0x08, 0xE0, 0x07, 0x00, 0x2C, 0xE0, 0x20, 0xA1, 0x8B, 0x8C, + 0x01, 0x00, 0x98, 0x70, 0xAA, 0x1B, 0x92, 0x14, 0x04, 0x21, 0x4B, 0x79, 0x00, 0x00, 0x26, 0x22, + 0x06, 0x72, 0x57, 0x71, 0x26, 0x27, 0xC6, 0x2E, 0xC2, 0xF3, 0x98, 0x70, 0xA9, 0x1B, 0x82, 0x08, + 0x04, 0x21, 0x0B, 0x78, 0x00, 0x00, 0x04, 0x21, 0x4B, 0x77, 0x00, 0x00, 0xF2, 0xE9, 0x04, 0x21, + 0x0B, 0x78, 0x00, 0x00, 0x04, 0x61, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x67, 0x14, 0x50, 0x40, 0xE1, + 0x24, 0x18, 0xE1, 0xF0, 0xC4, 0x20, 0x34, 0x14, 0xB1, 0xF1, 0x82, 0x05, 0x04, 0x61, 0x99, 0x60, + 0xBB, 0x1B, 0xF2, 0x03, 0x99, 0x00, 0xBB, 0x1B, 0x0C, 0x20, 0xE8, 0x19, 0x04, 0x30, 0x0C, 0x40, + 0x80, 0x00, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, + 0x98, 0x70, 0xBB, 0x1B, 0x82, 0x08, 0x98, 0x70, 0xBA, 0x1B, 0x82, 0x05, 0xB9, 0x00, 0xE0, 0x19, + 0xB9, 0x00, 0xDC, 0x19, 0xE1, 0xF0, 0x00, 0x00, 0x98, 0x70, 0xBB, 0x1B, 0x3C, 0x10, 0x10, 0x00, + 0xD1, 0xC1, 0x82, 0x68, 0xB9, 0x00, 0xE4, 0x19, 0x4B, 0x3F, 0x00, 0x00, 0x38, 0x70, 0xE4, 0x19, + 0x1C, 0x60, 0x80, 0x00, 0x56, 0x76, 0x18, 0x60, 0xB0, 0x1B, 0x5C, 0x20, 0x7F, 0x00, 0x08, 0x50, + 0xFD, 0xFF, 0x2C, 0x50, 0xFF, 0xFF, 0x66, 0x72, 0x54, 0x61, 0xD7, 0x68, 0x56, 0x75, 0x66, 0x76, + 0x18, 0x60, 0xB6, 0x1B, 0x08, 0x50, 0xFB, 0xFF, 0x2C, 0x50, 0xFF, 0xFF, 0x54, 0x61, 0x57, 0x69, + 0x56, 0x75, 0x66, 0x76, 0xB9, 0x70, 0xE4, 0x19, 0x04, 0xD0, 0x08, 0x70, 0x00, 0x30, 0x08, 0x50, + 0x07, 0x00, 0x2C, 0x70, 0x00, 0x49, 0x06, 0x6D, 0x2C, 0x50, 0xFF, 0xFF, 0x30, 0x47, 0x0C, 0x30, + 0xFF, 0x0F, 0x56, 0x34, 0x77, 0x48, 0x5C, 0x40, 0xFF, 0x0F, 0x36, 0x34, 0x38, 0x40, 0xE4, 0x19, + 0x23, 0x23, 0x06, 0xF4, 0xF7, 0xF9, 0xC6, 0x3F, 0x02, 0x08, 0x06, 0x32, 0xD7, 0x39, 0x56, 0x45, + 0x66, 0x43, 0xB9, 0x40, 0xE4, 0x19, 0x43, 0xD6, 0x24, 0x61, 0xCC, 0x60, 0x50, 0x01, 0x24, 0x74, + 0x92, 0xE6, 0xC4, 0xD0, 0x82, 0x1F, 0x0C, 0x30, 0x18, 0x00, 0x06, 0x2D, 0x2B, 0x19, 0x00, 0x00, + 0x38, 0xE0, 0xE4, 0x19, 0x1C, 0x70, 0x81, 0x0F, 0x5C, 0x20, 0x1F, 0x00, 0x56, 0xE7, 0xD7, 0x23, + 0x66, 0xE2, 0x0C, 0x30, 0x18, 0x00, 0x06, 0x2D, 0x8B, 0x16, 0x00, 0x00, 0x08, 0x70, 0xFE, 0xFF, + 0x5C, 0x20, 0x1F, 0x00, 0x2C, 0x70, 0xFF, 0x0F, 0x57, 0x26, 0x56, 0x7E, 0x66, 0x72, 0xB9, 0x70, + 0xE4, 0x19, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x80, + 0x28, 0x67, 0x28, 0xDC, 0x98, 0x70, 0xBB, 0x1B, 0x3C, 0x10, 0x38, 0x00, 0xD9, 0xC1, 0x28, 0x00, + 0xD9, 0x81, 0x18, 0x00, 0x8A, 0x99, 0x00, 0x00, 0xF7, 0x60, 0x08, 0xC0, 0x00, 0x30, 0x08, 0xB0, + 0xC0, 0xFF, 0xB1, 0x61, 0x99, 0x00, 0xB9, 0x1B, 0x0C, 0xE0, 0x94, 0x0F, 0x04, 0x80, 0x2C, 0xC0, + 0x00, 0x49, 0x2C, 0xB0, 0xFF, 0x07, 0x0C, 0x60, 0xFC, 0x0A, 0x18, 0x76, 0x8C, 0x06, 0xC6, 0x78, + 0xCA, 0x83, 0x00, 0x00, 0x98, 0x7E, 0x1E, 0x00, 0x82, 0x04, 0x04, 0x71, 0x26, 0x78, 0x13, 0x87, + 0x06, 0x2E, 0x0B, 0xED, 0x01, 0x00, 0xC4, 0x20, 0x92, 0x08, 0x2C, 0xE0, 0x26, 0x00, 0x0C, 0x70, + 0x82, 0x11, 0xC6, 0xE7, 0x92, 0xE9, 0xF2, 0x70, 0x18, 0x7E, 0x1E, 0x00, 0xC4, 0x71, 0x92, 0x09, + 0x18, 0x60, 0xB9, 0x1B, 0x64, 0x61, 0x99, 0x60, 0xB9, 0x1B, 0x0C, 0x70, 0xB8, 0x19, 0xF2, 0x0A, + 0xC4, 0x72, 0x92, 0xEC, 0x18, 0x60, 0xB9, 0x1B, 0x64, 0x62, 0x99, 0x60, 0xB9, 0x1B, 0x0C, 0x70, + 0x94, 0x19, 0x18, 0x6E, 0x15, 0x00, 0x08, 0x90, 0x3F, 0x00, 0x34, 0x61, 0x2F, 0x56, 0x06, 0x00, + 0x26, 0x56, 0x2C, 0x90, 0xFF, 0xFF, 0xD7, 0x51, 0x04, 0x40, 0xB9, 0x61, 0x0C, 0x00, 0xB9, 0x91, + 0x10, 0x00, 0x38, 0x61, 0x0C, 0x00, 0x26, 0x64, 0xC4, 0x6D, 0xD2, 0x40, 0x18, 0x6E, 0x14, 0x00, + 0x04, 0x30, 0x2F, 0x26, 0x05, 0x00, 0x57, 0x21, 0x34, 0x24, 0x34, 0x61, 0x26, 0x2C, 0xB9, 0x61, + 0x08, 0x00, 0x38, 0x61, 0x08, 0x00, 0x26, 0x63, 0xCC, 0x60, 0x16, 0x00, 0xD2, 0x2B, 0x30, 0xA1, + 0x30, 0xD2, 0x1C, 0x90, 0x00, 0x08, 0x36, 0xDA, 0x5C, 0xD0, 0xFF, 0x07, 0x23, 0xFD, 0xB9, 0xF1, + 0x14, 0x00, 0x30, 0x67, 0x56, 0x69, 0x66, 0x6F, 0xB1, 0x67, 0x28, 0xF2, 0x02, 0x00, 0x56, 0x6B, + 0x36, 0xFA, 0x5C, 0xF0, 0xFF, 0x07, 0x23, 0xAF, 0x06, 0x9A, 0xD7, 0x95, 0x66, 0x69, 0xB1, 0x67, + 0x38, 0x91, 0x14, 0x00, 0x04, 0x60, 0xC6, 0x9A, 0x02, 0x05, 0x3F, 0x6F, 0x0D, 0x00, 0x5C, 0x60, + 0xFF, 0x03, 0x30, 0xF7, 0x38, 0xA1, 0x10, 0x00, 0x57, 0x6B, 0x56, 0xFA, 0x66, 0xF6, 0xB1, 0xF7, + 0x24, 0x74, 0x24, 0x31, 0xC4, 0x33, 0x24, 0x24, 0x92, 0xCD, 0x24, 0x41, 0xC4, 0x43, 0x2C, 0x50, + 0x18, 0x00, 0x92, 0xB8, 0xF2, 0x8B, 0x58, 0xC1, 0x28, 0x00, 0x58, 0x81, 0x18, 0x00, 0x2C, 0x10, + 0x38, 0x00, 0xE1, 0xF0, 0x98, 0x70, 0xBB, 0x1B, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x82, 0x2F, + 0x06, 0xED, 0x0C, 0xE0, 0x90, 0x19, 0xB9, 0x00, 0x90, 0x19, 0x4B, 0x3E, 0x00, 0x00, 0x18, 0x70, + 0xB6, 0x1B, 0xC4, 0x71, 0x92, 0x24, 0x98, 0x70, 0x19, 0x0E, 0x82, 0x21, 0x23, 0xC2, 0xCB, 0x3D, + 0x00, 0x00, 0xA9, 0x2E, 0x02, 0x00, 0x0C, 0x30, 0x18, 0x00, 0x06, 0x2C, 0x4B, 0x18, 0x00, 0x00, + 0x38, 0xE0, 0x90, 0x19, 0x1C, 0x70, 0x20, 0x00, 0x56, 0xE7, 0x5C, 0x20, 0x1F, 0x00, 0x66, 0xE2, + 0x0C, 0x30, 0x18, 0x00, 0x06, 0x2C, 0xAB, 0x15, 0x00, 0x00, 0x5C, 0x20, 0x1F, 0x00, 0x1C, 0x70, + 0xE1, 0x03, 0xD7, 0x22, 0x56, 0xE7, 0x66, 0xE2, 0xB9, 0xE0, 0x90, 0x19, 0x50, 0xC1, 0x2C, 0x10, + 0x10, 0x00, 0xE1, 0xF0, 0x38, 0x60, 0xE4, 0x19, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0x7E, + 0x0C, 0x70, 0xE8, 0x19, 0xB9, 0x67, 0x08, 0x00, 0x38, 0x60, 0xE0, 0x19, 0xB9, 0x67, 0x0C, 0x00, + 0x38, 0x60, 0xDC, 0x19, 0x06, 0xD7, 0xB9, 0x67, 0x10, 0x00, 0x38, 0x60, 0x90, 0x19, 0x0C, 0x20, + 0x00, 0x1A, 0xB9, 0x67, 0x14, 0x00, 0x18, 0x30, 0xB9, 0x1B, 0x06, 0xC6, 0xD4, 0x31, 0x82, 0x08, + 0x0C, 0x30, 0xB8, 0x19, 0x04, 0x49, 0x0C, 0xF0, 0x5C, 0x01, 0xF1, 0xF0, 0xF2, 0x05, 0x04, 0x49, + 0x0C, 0xF0, 0xD8, 0x01, 0xF1, 0xF0, 0x18, 0x30, 0xB9, 0x1B, 0x54, 0x32, 0x93, 0x33, 0x0C, 0x20, + 0x24, 0x1A, 0x82, 0x08, 0x0C, 0x30, 0x94, 0x19, 0x04, 0x49, 0x0C, 0xF0, 0x5C, 0x01, 0xF1, 0xF0, + 0xF2, 0x05, 0x04, 0x49, 0x0C, 0xF0, 0xD8, 0x01, 0xF1, 0xF0, 0x38, 0x70, 0x08, 0x0B, 0xB9, 0x7D, + 0x04, 0x00, 0x38, 0x70, 0xE8, 0x19, 0x24, 0x71, 0xB9, 0x70, 0xE8, 0x19, 0x50, 0xC1, 0x2C, 0x10, + 0x10, 0x00, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x40, 0x0C, 0x60, 0xFE, 0x00, 0xB9, 0x67, 0x0C, 0x20, + 0xB9, 0x07, 0x18, 0x20, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x27, 0x04, 0x30, + 0xB9, 0x37, 0x08, 0x30, 0xB9, 0x47, 0x00, 0x30, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x60, 0x00, 0x40, + 0x38, 0x76, 0x00, 0x30, 0x64, 0x71, 0xB9, 0x76, 0x00, 0x30, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x40, + 0x38, 0x76, 0x00, 0x30, 0x14, 0x52, 0x56, 0x75, 0xB9, 0x76, 0x00, 0x30, 0xE1, 0xF0, 0x00, 0x00, + 0x08, 0x70, 0x00, 0x40, 0xB9, 0x27, 0x08, 0x30, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, + 0x38, 0x27, 0x0C, 0x30, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x14, 0x00, + 0x08, 0x70, 0x00, 0x80, 0xD9, 0xC1, 0x04, 0x00, 0x18, 0xC7, 0x67, 0xDC, 0xB1, 0xB1, 0x28, 0xB0, + 0x80, 0x1B, 0x08, 0xE0, 0x00, 0x30, 0x54, 0xB4, 0x23, 0xBB, 0x06, 0x5C, 0x2C, 0xE0, 0x00, 0x49, + 0x04, 0xD0, 0xC4, 0xB0, 0x82, 0x0A, 0x06, 0x2D, 0x0C, 0x30, 0x18, 0x00, 0x4B, 0x18, 0x00, 0x00, + 0xC4, 0x2E, 0x04, 0x50, 0xD2, 0x02, 0x06, 0x5C, 0x30, 0x7E, 0x5C, 0x70, 0xFF, 0x0F, 0x2F, 0x67, + 0x05, 0x00, 0xCC, 0x60, 0xFF, 0x0F, 0xC2, 0x03, 0x0C, 0x60, 0xFF, 0x0F, 0x24, 0xD1, 0x57, 0x68, + 0xCC, 0xD0, 0x50, 0x01, 0x66, 0x67, 0xB1, 0x6E, 0x24, 0xE4, 0x92, 0xE4, 0x58, 0xC1, 0x04, 0x00, + 0x30, 0xB1, 0x2C, 0x10, 0x14, 0x00, 0xE1, 0xF0, 0xE1, 0xF0, 0x00, 0x00, 0x2F, 0x72, 0x02, 0x00, + 0x26, 0x27, 0x57, 0x21, 0x0C, 0x60, 0xFC, 0x0A, 0x34, 0x18, 0x2C, 0x20, 0xB8, 0x09, 0xC1, 0xE1, + 0x26, 0x26, 0x14, 0x71, 0xA1, 0x72, 0xA9, 0x72, 0x02, 0x00, 0xA9, 0x72, 0x04, 0x00, 0xA9, 0x72, + 0x06, 0x00, 0xA9, 0x02, 0x08, 0x00, 0xA9, 0x02, 0x0A, 0x00, 0x38, 0xE6, 0x3C, 0x0C, 0xDC, 0xE0, + 0xFF, 0x03, 0x92, 0x10, 0x0C, 0x20, 0x56, 0x15, 0x06, 0x3E, 0x04, 0x48, 0x0C, 0xF0, 0xB0, 0x01, + 0xF1, 0xF0, 0x0C, 0x20, 0x5E, 0x15, 0x06, 0x3E, 0x0C, 0x40, 0x1A, 0x00, 0x0C, 0xF0, 0xB0, 0x01, + 0xF1, 0xF0, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x34, 0x18, 0xC1, 0xE1, 0x04, 0xE0, 0x06, 0x2E, + 0x6B, 0xB3, 0x01, 0x00, 0x24, 0xE1, 0xC4, 0xED, 0x92, 0xFB, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, + 0x3C, 0x10, 0x20, 0x00, 0xB1, 0x21, 0x28, 0x71, 0x02, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0xC9, 0xA1, + 0x08, 0x00, 0xC6, 0x47, 0x13, 0xD2, 0x06, 0xC4, 0x18, 0x21, 0x01, 0x00, 0x23, 0x33, 0x22, 0x03, + 0x43, 0x23, 0xF2, 0x1F, 0xC6, 0x4D, 0x43, 0xA2, 0x43, 0xDD, 0x32, 0x0C, 0x04, 0xE0, 0xC6, 0x2E, + 0x06, 0xBD, 0x82, 0x05, 0x04, 0x3A, 0xAB, 0x15, 0x00, 0x00, 0x13, 0xE2, 0x06, 0x3A, 0x04, 0xD0, + 0xF2, 0x04, 0x43, 0xB7, 0x06, 0xEA, 0x43, 0x33, 0x36, 0x3E, 0x3F, 0x2D, 0x0C, 0x00, 0x4B, 0x14, + 0x00, 0x00, 0x43, 0x22, 0x3F, 0x3D, 0x0B, 0x00, 0x8B, 0x16, 0x00, 0x00, 0x26, 0x2E, 0x43, 0x22, + 0x58, 0xC1, 0x10, 0x00, 0x48, 0xA1, 0x08, 0x00, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x3C, 0x10, 0x64, 0x00, 0xD9, 0xC1, 0x54, 0x00, 0x0C, 0x70, 0xFC, 0x0A, 0xD9, 0x81, 0x44, 0x00, + 0x98, 0x67, 0x74, 0x0C, 0x06, 0xE7, 0x92, 0x0F, 0x98, 0x67, 0xB0, 0x0C, 0x9A, 0x12, 0x03, 0x00, + 0x38, 0x77, 0x3C, 0x0C, 0xDC, 0x70, 0xFF, 0x03, 0x9A, 0x0C, 0x03, 0x00, 0x4B, 0xB6, 0x01, 0x00, + 0xFA, 0x08, 0x03, 0x00, 0x98, 0x70, 0xB0, 0x1B, 0x38, 0x6E, 0x0C, 0x00, 0x28, 0x7E, 0x12, 0x00, + 0x08, 0xB0, 0x00, 0x80, 0x2C, 0xB0, 0x0C, 0xDC, 0x92, 0x36, 0xD4, 0x61, 0x18, 0x6B, 0x74, 0x00, + 0x82, 0x21, 0xC6, 0x67, 0xC2, 0x0E, 0x0C, 0x70, 0x14, 0x00, 0x99, 0x7E, 0x54, 0x0A, 0x0C, 0x60, + 0x46, 0x00, 0x0C, 0x70, 0x78, 0x00, 0xA9, 0x7E, 0x56, 0x0A, 0x99, 0x6E, 0x55, 0x0A, 0xF2, 0x79, + 0x18, 0x6B, 0x73, 0x00, 0xC6, 0x67, 0xC2, 0x04, 0x0C, 0x70, 0x1E, 0x00, 0xF2, 0x24, 0x0C, 0x70, + 0x28, 0x00, 0x99, 0x7E, 0x54, 0x0A, 0x0C, 0x70, 0x78, 0x00, 0xA9, 0x7E, 0x56, 0x0A, 0x04, 0x75, + 0xF2, 0x64, 0xC6, 0x67, 0xD2, 0xE1, 0x18, 0x6B, 0x73, 0x00, 0xC6, 0x67, 0xC2, 0xF1, 0x0C, 0x70, + 0x1E, 0x00, 0x99, 0x7E, 0x54, 0x0A, 0x0C, 0x70, 0x78, 0x00, 0xA9, 0x7E, 0x56, 0x0A, 0x0C, 0x70, + 0x46, 0x00, 0xF2, 0x24, 0xD4, 0x61, 0x18, 0x6B, 0x74, 0x00, 0x82, 0x30, 0xC6, 0x67, 0xC2, 0x10, + 0x0C, 0x70, 0x14, 0x00, 0x99, 0x7E, 0x54, 0x0A, 0x0C, 0x70, 0x78, 0x00, 0xA9, 0x7E, 0x56, 0x0A, + 0x0C, 0x70, 0x32, 0x00, 0x99, 0x7E, 0x55, 0x0A, 0x0C, 0x70, 0x6E, 0x00, 0xF2, 0x42, 0x18, 0x6B, + 0x73, 0x00, 0xC6, 0x67, 0xC2, 0x10, 0x0C, 0x70, 0x14, 0x00, 0x99, 0x7E, 0x54, 0x0A, 0x0C, 0x70, + 0x78, 0x00, 0xA9, 0x7E, 0x56, 0x0A, 0x0C, 0x70, 0x28, 0x00, 0x99, 0x7E, 0x55, 0x0A, 0x0C, 0x70, + 0x64, 0x00, 0xF2, 0x2F, 0x0C, 0x70, 0x1E, 0x00, 0x99, 0x7E, 0x54, 0x0A, 0x0C, 0x70, 0x78, 0x00, + 0xA9, 0x7E, 0x56, 0x0A, 0x0C, 0x70, 0x14, 0x00, 0xF2, 0x11, 0xC6, 0x67, 0xD2, 0xD2, 0x18, 0x6B, + 0x73, 0x00, 0xC6, 0x67, 0xC2, 0x10, 0x0C, 0x70, 0x14, 0x00, 0x99, 0x7E, 0x54, 0x0A, 0x0C, 0x70, + 0x78, 0x00, 0xA9, 0x7E, 0x56, 0x0A, 0x0C, 0x70, 0x28, 0x00, 0x99, 0x7E, 0x55, 0x0A, 0x0C, 0x70, + 0x5A, 0x00, 0xF2, 0x0F, 0x0C, 0x70, 0x1E, 0x00, 0x99, 0x7E, 0x54, 0x0A, 0x0C, 0x70, 0x78, 0x00, + 0xA9, 0x7E, 0x56, 0x0A, 0x0C, 0x70, 0x14, 0x00, 0x99, 0x7E, 0x55, 0x0A, 0x0C, 0x70, 0x50, 0x00, + 0x28, 0x6E, 0x12, 0x00, 0xA9, 0x7E, 0x58, 0x0A, 0x04, 0x50, 0xA9, 0x60, 0x88, 0x1B, 0xB9, 0x51, + 0x04, 0x00, 0xB9, 0x51, 0x18, 0x00, 0xB9, 0x51, 0x14, 0x00, 0xB9, 0x51, 0x30, 0x00, 0xB9, 0x51, + 0x2C, 0x00, 0xB9, 0x51, 0x20, 0x00, 0x08, 0x50, 0x00, 0xFF, 0x0C, 0x70, 0x5F, 0x15, 0x2C, 0x50, + 0xFF, 0x0F, 0xB9, 0x71, 0x10, 0x00, 0x0C, 0xD0, 0xB4, 0x14, 0xB9, 0x51, 0x1C, 0x00, 0x18, 0x7E, + 0x74, 0x0C, 0x38, 0x51, 0x20, 0x00, 0xC6, 0x75, 0xCA, 0x3C, 0x02, 0x00, 0x38, 0x7E, 0x3C, 0x0C, + 0x38, 0x61, 0x04, 0x00, 0x5C, 0x70, 0xFF, 0x03, 0x63, 0x76, 0xD4, 0x71, 0x92, 0x06, 0x06, 0x26, + 0x6B, 0xB3, 0x01, 0x00, 0xFA, 0x20, 0x02, 0x00, 0x38, 0x81, 0x04, 0x00, 0xF0, 0x5D, 0x24, 0x81, + 0x06, 0x78, 0x57, 0x71, 0x26, 0x7E, 0x38, 0x67, 0x3C, 0x0C, 0x06, 0x76, 0x77, 0x76, 0x5C, 0x70, + 0xFF, 0x0F, 0x5C, 0x60, 0xFF, 0x0F, 0x32, 0x0C, 0x38, 0x41, 0x10, 0x00, 0x38, 0x21, 0x10, 0x00, + 0xA1, 0x7D, 0xA9, 0x6D, 0x02, 0x00, 0x04, 0x51, 0x34, 0x41, 0x91, 0x54, 0x91, 0x52, 0x70, 0x5D, + 0x36, 0x75, 0xB9, 0x71, 0x08, 0x00, 0x78, 0x7D, 0x02, 0x00, 0x38, 0x51, 0x08, 0x00, 0x36, 0x67, + 0xB9, 0x61, 0x0C, 0x00, 0x86, 0x65, 0xB9, 0x51, 0x24, 0x00, 0x32, 0x04, 0x16, 0x76, 0xB9, 0x71, + 0x24, 0x00, 0x38, 0x51, 0x0C, 0x00, 0x86, 0x65, 0xB9, 0x51, 0x28, 0x00, 0x32, 0x04, 0x16, 0x76, + 0xB9, 0x71, 0x28, 0x00, 0x38, 0x51, 0x24, 0x00, 0x38, 0x61, 0x28, 0x00, 0x43, 0x25, 0x43, 0x36, + 0x0C, 0xF0, 0xBC, 0x00, 0xF1, 0xF0, 0x98, 0x70, 0xB0, 0x1B, 0x06, 0xC2, 0x92, 0x0B, 0x38, 0x2E, + 0x54, 0x0A, 0x38, 0x3E, 0x58, 0x0A, 0x06, 0x4C, 0x0B, 0xB7, 0x01, 0x00, 0x06, 0xA2, 0x06, 0x92, + 0xF2, 0x2D, 0x28, 0x7E, 0x12, 0x00, 0x18, 0x6B, 0x74, 0x00, 0xC6, 0x67, 0xC2, 0x04, 0x26, 0x22, + 0x04, 0x33, 0xF2, 0x08, 0x18, 0x6B, 0x73, 0x00, 0xC6, 0x67, 0xC2, 0x0C, 0x26, 0x22, 0x26, 0x2C, + 0x04, 0x35, 0x8B, 0x16, 0x00, 0x00, 0x43, 0x42, 0x38, 0x3E, 0x58, 0x0A, 0x38, 0x2E, 0x54, 0x0A, + 0xF2, 0x0A, 0x06, 0x42, 0xF7, 0x4F, 0x26, 0x42, 0x38, 0x3E, 0x58, 0x0A, 0x38, 0x2E, 0x54, 0x0A, + 0xE7, 0x40, 0x43, 0x44, 0x0B, 0xB7, 0x01, 0x00, 0x06, 0x92, 0x38, 0x3E, 0x58, 0x0A, 0x38, 0x2E, + 0x54, 0x0A, 0x06, 0x4C, 0x0B, 0xB7, 0x01, 0x00, 0x06, 0xA2, 0x18, 0x7E, 0x8E, 0x06, 0xC4, 0x72, + 0xD2, 0x0F, 0x38, 0x70, 0x70, 0x1A, 0x78, 0x57, 0xBC, 0x00, 0xA9, 0x5E, 0x5C, 0x0A, 0xA9, 0x5E, + 0x5A, 0x0A, 0x78, 0x77, 0xBE, 0x00, 0xA9, 0x7E, 0x60, 0x0A, 0xA9, 0x7E, 0x5E, 0x0A, 0x57, 0x81, + 0x26, 0x8E, 0x38, 0x78, 0x3C, 0x0C, 0x77, 0x7E, 0x34, 0x71, 0x06, 0x47, 0x06, 0x57, 0x57, 0x41, + 0x57, 0x52, 0x26, 0x54, 0x3F, 0x77, 0x05, 0x00, 0x26, 0x77, 0x26, 0x7E, 0x28, 0x77, 0xAE, 0x04, + 0xCC, 0x70, 0x64, 0x00, 0x38, 0x70, 0x70, 0x1A, 0xC2, 0x2D, 0x18, 0x67, 0xB9, 0x00, 0x18, 0x87, + 0xB8, 0x00, 0x18, 0x77, 0xBA, 0x00, 0x26, 0x86, 0x26, 0x87, 0x28, 0x6E, 0x5E, 0x0A, 0x28, 0x7E, + 0x5A, 0x0A, 0x06, 0x29, 0x26, 0x76, 0x26, 0x77, 0x06, 0x67, 0x57, 0x62, 0xD7, 0x92, 0xD7, 0x21, + 0x3F, 0x77, 0x06, 0x00, 0x26, 0x29, 0x26, 0x27, 0x43, 0x22, 0x06, 0x38, 0x8B, 0x16, 0x00, 0x00, + 0x28, 0x6E, 0x60, 0x0A, 0x28, 0x7E, 0x5C, 0x0A, 0x43, 0x92, 0x26, 0x76, 0x26, 0x77, 0x06, 0x2A, + 0x06, 0x67, 0xD7, 0x21, 0xD7, 0xA2, 0x57, 0x62, 0x26, 0x2A, 0x3F, 0x77, 0x06, 0x00, 0x26, 0x27, + 0xF2, 0x51, 0x18, 0x57, 0xB9, 0x00, 0x18, 0x67, 0xB8, 0x00, 0x28, 0x3E, 0x5E, 0x0A, 0x18, 0x77, + 0xBA, 0x00, 0xB9, 0x51, 0x3C, 0x00, 0x2F, 0x85, 0x06, 0x00, 0x06, 0x25, 0x26, 0x87, 0xB9, 0x71, + 0x40, 0x00, 0xB9, 0x61, 0x38, 0x00, 0x4B, 0x14, 0x00, 0x00, 0x38, 0x61, 0x38, 0x00, 0x28, 0x3E, + 0x5A, 0x0A, 0x06, 0x42, 0x06, 0x26, 0xB9, 0x41, 0x34, 0x00, 0x4B, 0x14, 0x00, 0x00, 0x38, 0x71, + 0x40, 0x00, 0x38, 0x41, 0x34, 0x00, 0x06, 0x39, 0x26, 0x42, 0x06, 0x27, 0xB9, 0x41, 0x34, 0x00, + 0x4B, 0x14, 0x00, 0x00, 0x38, 0x41, 0x34, 0x00, 0x06, 0x38, 0x26, 0x24, 0x43, 0x22, 0x8B, 0x16, + 0x00, 0x00, 0x38, 0x51, 0x3C, 0x00, 0x28, 0x3E, 0x60, 0x0A, 0x43, 0x92, 0x06, 0x25, 0x4B, 0x14, + 0x00, 0x00, 0x38, 0x61, 0x38, 0x00, 0x28, 0x3E, 0x5C, 0x0A, 0x06, 0x52, 0x06, 0x26, 0xB9, 0x51, + 0x3C, 0x00, 0x4B, 0x14, 0x00, 0x00, 0x38, 0x51, 0x3C, 0x00, 0x38, 0x71, 0x40, 0x00, 0x26, 0x52, + 0x06, 0x3A, 0x06, 0x27, 0xB9, 0x51, 0x3C, 0x00, 0x4B, 0x14, 0x00, 0x00, 0x38, 0x51, 0x3C, 0x00, + 0x26, 0x25, 0x06, 0x38, 0x43, 0x22, 0x8B, 0x16, 0x00, 0x00, 0x43, 0x72, 0x38, 0x21, 0x24, 0x00, + 0xB9, 0x71, 0x40, 0x00, 0x06, 0x39, 0x4B, 0x14, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0x8B, 0x16, + 0x00, 0x00, 0x38, 0x71, 0x40, 0x00, 0x06, 0x82, 0x38, 0x21, 0x28, 0x00, 0x06, 0x37, 0x4B, 0x14, + 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0x8B, 0x16, 0x00, 0x00, 0x38, 0x51, 0x18, 0x00, 0x38, 0x71, + 0x40, 0x00, 0xC6, 0x95, 0x06, 0xA2, 0x06, 0x69, 0x32, 0x02, 0x06, 0x65, 0x38, 0x51, 0x14, 0x00, + 0x43, 0x66, 0xC6, 0x75, 0xB9, 0x61, 0x18, 0x00, 0x06, 0x67, 0x32, 0x02, 0x06, 0x65, 0x38, 0x51, + 0x0C, 0x00, 0x43, 0x66, 0x15, 0x95, 0x38, 0x51, 0x10, 0x00, 0xB9, 0x61, 0x14, 0x00, 0x38, 0x61, + 0x08, 0x00, 0x34, 0x51, 0x15, 0x76, 0x60, 0x35, 0xF7, 0x7F, 0x33, 0x47, 0xC6, 0x34, 0xF7, 0x9F, + 0x33, 0x69, 0x92, 0x04, 0x04, 0x21, 0xB9, 0x21, 0x2C, 0x00, 0x38, 0x21, 0x10, 0x00, 0x60, 0x32, + 0xC6, 0x36, 0x92, 0x04, 0x04, 0x31, 0xB9, 0x31, 0x30, 0x00, 0x91, 0x45, 0x38, 0x51, 0x10, 0x00, + 0x06, 0x3D, 0x91, 0x65, 0x04, 0x44, 0x06, 0x21, 0xB9, 0x71, 0x40, 0x00, 0xEB, 0xE4, 0x04, 0x00, + 0xCB, 0x3D, 0x00, 0x00, 0x18, 0x6E, 0x8F, 0x06, 0x38, 0x71, 0x40, 0x00, 0xC4, 0x61, 0xD2, 0x16, + 0x28, 0x6E, 0x06, 0x03, 0x23, 0x22, 0xC6, 0x62, 0xC2, 0x11, 0x78, 0x6D, 0x08, 0x00, 0xC6, 0x68, + 0x02, 0x05, 0xB8, 0x51, 0x2C, 0x00, 0x82, 0x02, 0x06, 0x86, 0x78, 0x6D, 0x0A, 0x00, 0xC6, 0x6A, + 0x02, 0x05, 0xB8, 0x51, 0x30, 0x00, 0x82, 0x02, 0x06, 0xA6, 0xC4, 0x70, 0x20, 0x61, 0x92, 0x02, + 0x16, 0x88, 0x23, 0x88, 0x26, 0x86, 0xC4, 0x90, 0x23, 0x88, 0xA1, 0x81, 0x28, 0x71, 0x02, 0x00, + 0x92, 0x02, 0x16, 0xAA, 0x23, 0xAA, 0x26, 0xA7, 0xC4, 0xC0, 0x23, 0xAA, 0xA9, 0xA1, 0x02, 0x00, + 0x02, 0x16, 0xB8, 0x71, 0x08, 0x00, 0x04, 0x61, 0x12, 0x05, 0x16, 0x67, 0x66, 0x67, 0xE7, 0x6F, + 0x23, 0x66, 0xB8, 0x51, 0x0C, 0x00, 0x26, 0x68, 0xA1, 0x61, 0x04, 0x71, 0x12, 0x05, 0x16, 0x75, + 0x66, 0x75, 0xE7, 0x7F, 0x23, 0x77, 0x26, 0x7A, 0xA9, 0x71, 0x02, 0x00, 0x06, 0x21, 0xEB, 0x39, + 0x04, 0x00, 0x70, 0x7D, 0x70, 0xA1, 0x3F, 0x77, 0x0A, 0x00, 0xC4, 0x70, 0x32, 0x02, 0x16, 0x77, + 0xA9, 0x7D, 0x08, 0x00, 0x78, 0xC1, 0x02, 0x00, 0x78, 0x7D, 0x02, 0x00, 0x3F, 0x77, 0x0C, 0x00, + 0xC4, 0x70, 0x32, 0x02, 0x16, 0x77, 0x04, 0x24, 0x06, 0x3D, 0x04, 0x44, 0x26, 0x2D, 0xA9, 0x7D, + 0x0A, 0x00, 0xEB, 0xE4, 0x04, 0x00, 0x06, 0x2D, 0x06, 0x31, 0x04, 0x44, 0xEB, 0xE4, 0x04, 0x00, + 0x18, 0x7B, 0x2D, 0x00, 0x04, 0x62, 0xD6, 0x67, 0x82, 0x06, 0x0C, 0x60, 0x7F, 0x07, 0x3F, 0xAA, + 0x06, 0x00, 0x43, 0xAA, 0x04, 0x64, 0xD6, 0x67, 0x82, 0x06, 0x0C, 0x60, 0x37, 0x04, 0x3F, 0xCC, + 0x06, 0x00, 0x43, 0xCC, 0x38, 0x61, 0x04, 0x00, 0xD4, 0x71, 0x24, 0x61, 0x57, 0x61, 0x23, 0xAA, + 0x23, 0xCC, 0x26, 0x6E, 0x82, 0x11, 0x38, 0x76, 0x3C, 0x0C, 0x38, 0x51, 0x1C, 0x00, 0x1C, 0x20, + 0x00, 0x10, 0x5C, 0xA0, 0xFF, 0x0F, 0x56, 0x72, 0x66, 0x7A, 0x5C, 0xC0, 0xFF, 0x0F, 0x57, 0xC6, + 0x56, 0x75, 0x66, 0x7C, 0xF2, 0x10, 0x38, 0x76, 0x3C, 0x0C, 0x38, 0x51, 0x1C, 0x00, 0x1C, 0x20, + 0x00, 0x10, 0x5C, 0xC0, 0xFF, 0x0F, 0x56, 0x72, 0x66, 0x7C, 0x5C, 0xA0, 0xFF, 0x0F, 0x57, 0xA6, + 0x56, 0x75, 0x66, 0x7A, 0xB9, 0x76, 0x3C, 0x0C, 0x38, 0x71, 0x20, 0x00, 0x24, 0x71, 0x13, 0x77, + 0xB9, 0x71, 0x20, 0x00, 0x38, 0x61, 0x04, 0x00, 0x38, 0x71, 0x10, 0x00, 0x24, 0x61, 0xC4, 0x6D, + 0x24, 0x72, 0xB9, 0x61, 0x04, 0x00, 0xB9, 0x71, 0x10, 0x00, 0x24, 0xDC, 0x9A, 0xC1, 0xFD, 0xFF, + 0x0C, 0x20, 0x5E, 0x0A, 0x26, 0x2E, 0x14, 0x34, 0x26, 0x32, 0x04, 0x44, 0xEB, 0xE4, 0x04, 0x00, + 0x38, 0x61, 0x18, 0x00, 0x38, 0x71, 0x14, 0x00, 0xA9, 0x6E, 0x5A, 0x0A, 0xA9, 0x7E, 0x5C, 0x0A, + 0x58, 0xC1, 0x54, 0x00, 0x58, 0x81, 0x44, 0x00, 0x2C, 0x10, 0x64, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x98, 0x50, 0xED, 0x0B, 0x38, 0x60, 0x70, 0x1A, 0x34, 0x14, 0xB1, 0xF1, 0x18, 0x46, 0x8E, 0x00, + 0x18, 0x66, 0x8D, 0x00, 0x06, 0x72, 0x92, 0x05, 0x18, 0x50, 0xEE, 0x0B, 0x26, 0x65, 0x13, 0x66, + 0x98, 0x50, 0xB0, 0x1B, 0x82, 0x11, 0xB8, 0x50, 0x8C, 0x19, 0x92, 0x0E, 0x08, 0x50, 0x00, 0x80, + 0x2C, 0x50, 0x0C, 0xDC, 0x18, 0x35, 0x7A, 0x00, 0x18, 0x55, 0x7B, 0x00, 0x26, 0x63, 0x26, 0x54, + 0x13, 0x66, 0x13, 0x55, 0xF2, 0x02, 0x06, 0x54, 0x18, 0x37, 0x22, 0x00, 0xD4, 0x31, 0x18, 0x37, + 0x20, 0x00, 0x92, 0x14, 0x98, 0x67, 0x23, 0x00, 0x92, 0x10, 0xC4, 0x31, 0xC2, 0x0E, 0xC6, 0x45, + 0x92, 0x0C, 0x28, 0x67, 0x1C, 0x00, 0xCC, 0x60, 0x28, 0x00, 0xD2, 0x07, 0x28, 0x60, 0x0E, 0x0B, + 0xC4, 0x66, 0xD2, 0x03, 0x24, 0x52, 0x13, 0x55, 0x06, 0x65, 0xC6, 0x36, 0xB2, 0x06, 0x18, 0x67, + 0x23, 0x00, 0x04, 0x20, 0xC4, 0x61, 0x92, 0x1F, 0x04, 0x61, 0x99, 0x67, 0x23, 0x00, 0xF8, 0x67, + 0x0C, 0x00, 0x22, 0x13, 0xF8, 0x57, 0x0E, 0x00, 0x22, 0x10, 0xCC, 0x60, 0x31, 0x00, 0x12, 0x0D, + 0x70, 0x57, 0x2C, 0x60, 0x1D, 0x00, 0xC6, 0x65, 0x32, 0x08, 0x04, 0x3C, 0x06, 0x27, 0x26, 0x37, + 0x04, 0x44, 0xEB, 0xE4, 0x04, 0x00, 0x06, 0x72, 0x14, 0x61, 0xA9, 0x67, 0x0C, 0x00, 0xA9, 0x67, + 0x0E, 0x00, 0x04, 0x21, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x98, 0x60, 0xB0, 0x1B, + 0x38, 0x70, 0x70, 0x1A, 0x18, 0x77, 0x8E, 0x00, 0x82, 0x0A, 0xB8, 0x60, 0x8C, 0x19, 0x92, 0x07, + 0x08, 0x60, 0x00, 0x80, 0x18, 0x66, 0x87, 0xDC, 0x26, 0x76, 0x13, 0x77, 0x18, 0x52, 0x01, 0x00, + 0x04, 0x61, 0xC6, 0x57, 0xB2, 0x02, 0x04, 0x60, 0x04, 0x21, 0x56, 0x26, 0xE1, 0xF0, 0x00, 0x00, + 0x0C, 0x50, 0xFC, 0x0A, 0x18, 0x60, 0x1A, 0x0E, 0x30, 0x75, 0x16, 0x66, 0x24, 0x71, 0xB1, 0x75, + 0xF7, 0x6F, 0xD7, 0x7A, 0x57, 0x6A, 0x6C, 0x70, 0x75, 0x00, 0x66, 0x76, 0x08, 0x60, 0x00, 0x30, + 0xB9, 0x76, 0x00, 0x01, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x0C, 0x20, 0x80, 0x02, 0x04, 0x30, + 0x0C, 0x40, 0xD2, 0x02, 0xB1, 0xF1, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x0C, 0x20, 0x54, 0x05, + 0x04, 0x30, 0x0C, 0x40, 0xD2, 0x02, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x0C, 0x20, 0x28, 0x08, + 0x04, 0x30, 0x0C, 0x40, 0xD2, 0x02, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x80, 0x28, 0x77, 0x6A, 0xDC, 0x34, 0x14, 0xB1, 0xF1, + 0xA9, 0x70, 0x0C, 0x0B, 0x4B, 0xF6, 0x01, 0x00, 0x08, 0x70, 0x00, 0x80, 0x18, 0x27, 0x08, 0xDC, + 0x6B, 0xFD, 0x03, 0x00, 0xEB, 0x7C, 0x02, 0x00, 0x0C, 0x20, 0x5F, 0x00, 0x0C, 0x30, 0x64, 0x00, + 0xCB, 0x3E, 0x04, 0x00, 0x2B, 0x83, 0x02, 0x00, 0x4B, 0xB6, 0x01, 0x00, 0x8B, 0x7C, 0x02, 0x00, + 0xAB, 0x7C, 0x02, 0x00, 0x38, 0x70, 0x70, 0x1A, 0x04, 0x61, 0x30, 0x77, 0xD6, 0x67, 0x82, 0x04, + 0x0C, 0x50, 0x28, 0x08, 0xF2, 0x03, 0x0C, 0x50, 0x80, 0x02, 0xD4, 0x72, 0xB9, 0x50, 0x80, 0x1A, + 0x82, 0x04, 0x0C, 0x60, 0x28, 0x08, 0xF2, 0x03, 0x0C, 0x60, 0x80, 0x02, 0x30, 0xF1, 0xB9, 0x60, + 0x7C, 0x1A, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0x8B, 0x7A, 0x04, 0x00, + 0xEB, 0xCA, 0x03, 0x00, 0x6B, 0x0C, 0x02, 0x00, 0x8B, 0x00, 0x04, 0x00, 0xEB, 0x0D, 0x02, 0x00, + 0xAB, 0xFB, 0x02, 0x00, 0x30, 0xF1, 0x99, 0x00, 0xD8, 0x0B, 0xA9, 0x00, 0xB0, 0x17, 0x99, 0x00, + 0xBC, 0x17, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0x4B, 0x5A, 0x04, 0x00, + 0x30, 0xF1, 0x99, 0x00, 0xDA, 0x0B, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, + 0x0B, 0x37, 0x03, 0x00, 0xCB, 0x7C, 0x02, 0x00, 0x8B, 0xDF, 0x02, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x98, 0x50, 0x19, 0x0E, 0x34, 0x14, 0xB1, 0xF1, 0x92, 0x08, 0x98, 0x70, + 0x88, 0x11, 0x92, 0x05, 0xB8, 0x70, 0x7C, 0x19, 0x82, 0x0D, 0xF2, 0x14, 0x18, 0x70, 0x8A, 0x11, + 0xCC, 0x70, 0xC7, 0x00, 0xD2, 0x04, 0x24, 0x71, 0x99, 0x70, 0x8A, 0x11, 0xC4, 0x50, 0x92, 0x15, + 0xF2, 0xF2, 0x98, 0x70, 0x88, 0x11, 0x92, 0x03, 0xAB, 0x0D, 0x02, 0x00, 0xEB, 0x3E, 0x04, 0x00, + 0xF2, 0x0C, 0xC4, 0x72, 0x92, 0x04, 0x99, 0x00, 0xBC, 0x17, 0xF2, 0x07, 0xC4, 0x74, 0x92, 0x05, + 0xEB, 0x0D, 0x02, 0x00, 0x8B, 0x00, 0x04, 0x00, 0x18, 0x70, 0xDA, 0x0B, 0xCC, 0x70, 0xF9, 0x00, + 0xD2, 0x04, 0x24, 0x71, 0x99, 0x70, 0xDA, 0x0B, 0x38, 0x50, 0x38, 0x17, 0x06, 0x75, 0x18, 0x40, + 0x8B, 0x11, 0x77, 0x76, 0x54, 0x7F, 0xC6, 0x47, 0x32, 0x04, 0x99, 0x70, 0x8B, 0x11, 0xF2, 0x0A, + 0x06, 0x75, 0xDC, 0x70, 0x00, 0xF0, 0x92, 0x06, 0x98, 0x70, 0x88, 0x11, 0x92, 0x03, 0x99, 0x00, + 0x8B, 0x11, 0x98, 0x70, 0xAC, 0x17, 0x82, 0x0A, 0x18, 0x70, 0xD8, 0x0B, 0xCC, 0x70, 0xFF, 0x00, + 0x82, 0x07, 0x24, 0x71, 0x99, 0x70, 0xD8, 0x0B, 0xF2, 0x03, 0x99, 0x00, 0xD8, 0x0B, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x18, 0x70, 0xB4, 0x1B, 0x34, 0x14, 0xC4, 0x70, 0xB1, 0xF1, 0x04, 0x21, + 0x82, 0x15, 0x38, 0x70, 0x08, 0x0B, 0x1C, 0x60, 0x01, 0xF0, 0x56, 0x76, 0xB9, 0x70, 0x08, 0x0B, + 0x6B, 0x0C, 0x02, 0x00, 0xEB, 0xFD, 0x01, 0x00, 0xAB, 0x5B, 0x04, 0x00, 0x2B, 0x5E, 0x04, 0x00, + 0x99, 0x00, 0x52, 0x0C, 0x99, 0x00, 0x1A, 0x0E, 0x04, 0x20, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, + 0x34, 0x14, 0xB1, 0xF1, 0xAB, 0x71, 0x04, 0x00, 0xC4, 0x21, 0x92, 0x09, 0x2B, 0x5E, 0x04, 0x00, + 0x2B, 0xAB, 0x02, 0x00, 0x8B, 0xBA, 0x01, 0x00, 0xCB, 0x76, 0x04, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0x6B, 0x8E, 0x03, 0x00, 0x30, 0xF1, 0x04, 0x20, + 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, 0xEB, 0xFD, 0x01, 0x00, 0x0B, 0x01, 0x04, 0x00, + 0xEB, 0x45, 0x03, 0x00, 0x4B, 0xF7, 0x03, 0x00, 0xCB, 0x7F, 0x04, 0x00, 0xC4, 0x20, 0x92, 0x03, + 0x4B, 0x7B, 0x04, 0x00, 0x2B, 0x04, 0x02, 0x00, 0xC4, 0x21, 0x92, 0x1D, 0x98, 0x70, 0xDB, 0x0B, + 0x82, 0x04, 0x98, 0x70, 0xDC, 0x0B, 0x92, 0x0E, 0x8B, 0xF9, 0x03, 0x00, 0x18, 0x70, 0xB1, 0x1B, + 0xC4, 0x71, 0x92, 0x04, 0xCB, 0x45, 0x03, 0x00, 0xF2, 0x05, 0x4B, 0x88, 0x03, 0x00, 0x2B, 0x06, + 0x03, 0x00, 0x8B, 0x7B, 0x02, 0x00, 0xC4, 0x21, 0x92, 0x06, 0x98, 0x70, 0xDC, 0x0B, 0x92, 0x03, + 0x0B, 0x06, 0x02, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0xC4, 0x20, 0x34, 0x14, + 0xB1, 0xF1, 0x82, 0x10, 0x2B, 0xA3, 0x04, 0x00, 0x18, 0x70, 0xDC, 0x0B, 0xC4, 0x71, 0x92, 0x0A, + 0x38, 0x70, 0x08, 0x0B, 0x1C, 0x60, 0x01, 0x03, 0x56, 0x76, 0xB9, 0x70, 0x08, 0x0B, 0x0B, 0x06, + 0x02, 0x00, 0xAB, 0xFE, 0x01, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0x0C, 0x20, + 0x94, 0x0F, 0x04, 0x30, 0x0C, 0x40, 0xFC, 0x01, 0xB1, 0xF1, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, + 0x0C, 0x20, 0x90, 0x11, 0x04, 0x30, 0x04, 0x4F, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x99, 0x00, 0x8A, 0x11, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x0C, 0x20, + 0xE4, 0x0B, 0x04, 0x30, 0x04, 0x4C, 0xB1, 0xF1, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x04, 0x70, 0x2F, 0x67, 0x02, 0x00, 0x91, 0x06, 0x2F, 0x67, 0x03, 0x00, + 0x24, 0x7C, 0xCC, 0x70, 0x9C, 0x00, 0x91, 0x06, 0x92, 0xF7, 0xE1, 0xF0, 0x34, 0x18, 0xC1, 0xE1, + 0x04, 0x71, 0x99, 0x32, 0x01, 0x00, 0x91, 0x72, 0x20, 0x75, 0x06, 0xE2, 0xA9, 0x72, 0x02, 0x00, + 0x28, 0x75, 0x02, 0x00, 0x06, 0x34, 0xA9, 0x72, 0x04, 0x00, 0x06, 0x24, 0x4B, 0x14, 0x00, 0x00, + 0xB9, 0x2E, 0x08, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, 0xB9, 0x20, 0x84, 0x1A, + 0x99, 0x30, 0xBD, 0x1B, 0x99, 0x40, 0xBC, 0x1B, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x34, 0x00, + 0xD9, 0x81, 0x14, 0x00, 0xD9, 0xC1, 0x24, 0x00, 0x06, 0xB2, 0xB1, 0x31, 0xB9, 0x41, 0x04, 0x00, + 0x04, 0x70, 0x2F, 0x67, 0x0B, 0x00, 0x24, 0x78, 0xCC, 0x70, 0x48, 0x05, 0xB1, 0x06, 0x92, 0xFA, + 0x30, 0xE1, 0x04, 0xD0, 0x06, 0x9D, 0x06, 0xAD, 0x90, 0x7E, 0x92, 0x07, 0x04, 0xE0, 0x06, 0xCE, + 0x06, 0x9E, 0x06, 0x8E, 0xFA, 0x98, 0x00, 0x00, 0x30, 0x61, 0xB8, 0x76, 0x08, 0x00, 0x82, 0x05, + 0x38, 0x7E, 0x08, 0x00, 0xB9, 0x70, 0x84, 0x1A, 0x38, 0xC1, 0x04, 0x00, 0x04, 0x80, 0x90, 0x7C, + 0x82, 0x63, 0x98, 0x70, 0xBD, 0x1B, 0x92, 0x03, 0xC6, 0x98, 0x82, 0x59, 0x78, 0x7C, 0x02, 0x00, + 0x78, 0x2E, 0x02, 0x00, 0x78, 0x6E, 0x04, 0x00, 0x36, 0x27, 0x78, 0x7C, 0x04, 0x00, 0xB9, 0x51, + 0x10, 0x00, 0x06, 0x32, 0x3F, 0x77, 0x06, 0x00, 0xB9, 0x71, 0x08, 0x00, 0x4B, 0x14, 0x00, 0x00, + 0x38, 0x71, 0x08, 0x00, 0x06, 0x62, 0x06, 0x37, 0x06, 0x27, 0xB9, 0x61, 0x0C, 0x00, 0x4B, 0x14, + 0x00, 0x00, 0x38, 0x51, 0x10, 0x00, 0x38, 0x61, 0x0C, 0x00, 0x38, 0x70, 0x84, 0x1A, 0x26, 0x62, + 0xC6, 0x76, 0xA2, 0x35, 0x06, 0x7B, 0x04, 0x40, 0xC6, 0x4D, 0x04, 0x21, 0x26, 0x24, 0x82, 0x07, + 0x24, 0x78, 0x14, 0x38, 0x26, 0x37, 0x30, 0x33, 0xC6, 0x36, 0xC2, 0x27, 0xD7, 0x21, 0x14, 0x78, + 0x26, 0x72, 0x26, 0x7B, 0x3F, 0x44, 0x0D, 0x00, 0x06, 0x37, 0x26, 0x2B, 0xD7, 0x41, 0xB9, 0x51, + 0x10, 0x00, 0xB9, 0x61, 0x0C, 0x00, 0xB9, 0x71, 0x08, 0x00, 0x0C, 0xF0, 0x00, 0x01, 0xF1, 0xF0, + 0x38, 0x61, 0x0C, 0x00, 0x38, 0x71, 0x08, 0x00, 0x24, 0xD1, 0xB1, 0x67, 0x18, 0x6E, 0x01, 0x00, + 0x24, 0xA1, 0x99, 0x67, 0x04, 0x00, 0x18, 0x6C, 0x01, 0x00, 0x13, 0xDD, 0x99, 0x67, 0x05, 0x00, + 0x13, 0xAA, 0x38, 0x51, 0x10, 0x00, 0xF2, 0x03, 0x13, 0x42, 0xF2, 0xCF, 0x24, 0x81, 0x13, 0x88, + 0xC4, 0x8D, 0x24, 0xCC, 0x92, 0x9D, 0x24, 0x91, 0x13, 0x99, 0xC4, 0x9D, 0x24, 0xEC, 0x92, 0x85, + 0xF2, 0x86, 0x06, 0x39, 0xD7, 0x31, 0x2F, 0x23, 0x0B, 0x00, 0x18, 0x42, 0x04, 0x00, 0x04, 0x71, + 0x06, 0xF7, 0x53, 0xF4, 0x06, 0x4F, 0x06, 0xFC, 0xD6, 0xF4, 0x82, 0x18, 0x34, 0xA1, 0x3F, 0x49, + 0x0A, 0x00, 0x24, 0x38, 0x26, 0x3B, 0xD7, 0x41, 0xB9, 0x51, 0x10, 0x00, 0xB9, 0x61, 0x0C, 0x00, + 0x0C, 0xF0, 0x28, 0x01, 0xF1, 0xF0, 0x38, 0x51, 0x10, 0x00, 0x38, 0x61, 0x0C, 0x00, 0x13, 0xAA, + 0x24, 0x81, 0x13, 0x88, 0xC6, 0x8D, 0x92, 0xDE, 0xF2, 0x14, 0x18, 0xF2, 0x05, 0x00, 0x53, 0x7F, + 0x06, 0xFE, 0xD6, 0xF7, 0x92, 0xE4, 0x98, 0x30, 0xBC, 0x1B, 0x92, 0x02, 0x66, 0xC4, 0x98, 0x30, + 0xBD, 0x1B, 0x66, 0xE7, 0x92, 0x03, 0x66, 0x74, 0x66, 0xC7, 0x24, 0x91, 0x13, 0x99, 0xF2, 0xE9, + 0x58, 0xC1, 0x24, 0x00, 0x06, 0x2A, 0x58, 0x81, 0x14, 0x00, 0x2C, 0x10, 0x34, 0x00, 0xE1, 0xF0, + 0x3C, 0x10, 0x30, 0x00, 0xD9, 0xC1, 0x20, 0x00, 0xD9, 0x81, 0x10, 0x00, 0x0C, 0xE0, 0xFC, 0x0A, + 0x18, 0x4E, 0x8C, 0x06, 0x04, 0x60, 0xC4, 0x49, 0xDA, 0xC1, 0x00, 0x00, 0x0C, 0x50, 0xB2, 0x0F, + 0x06, 0xD6, 0x90, 0x75, 0x82, 0x07, 0x24, 0xD1, 0x13, 0xDD, 0xC4, 0xDD, 0x2C, 0x50, 0x26, 0x00, + 0x92, 0xF9, 0x06, 0x72, 0xD7, 0x72, 0x2F, 0x97, 0x0E, 0x00, 0x28, 0x69, 0x5C, 0x01, 0x0C, 0x50, + 0x28, 0x08, 0x26, 0x66, 0x26, 0x65, 0x70, 0x36, 0x28, 0x5E, 0x08, 0x03, 0x04, 0x60, 0xC6, 0x35, + 0x2A, 0xA5, 0x00, 0x00, 0x04, 0x61, 0x06, 0xAD, 0x06, 0xBD, 0x26, 0x6D, 0x57, 0xA1, 0x57, 0xB2, + 0x13, 0x66, 0x2F, 0xCB, 0x0A, 0x00, 0xB1, 0x61, 0x36, 0xCD, 0x30, 0x51, 0x26, 0xCC, 0x26, 0xCE, + 0x0C, 0x60, 0x1C, 0x00, 0x26, 0x6C, 0x99, 0x56, 0x9A, 0x04, 0x0C, 0x80, 0x98, 0x04, 0x0C, 0x50, + 0x70, 0x01, 0x26, 0x8C, 0x26, 0x59, 0x24, 0x41, 0x99, 0x4E, 0x8C, 0x06, 0x06, 0x35, 0x04, 0x44, + 0x06, 0x28, 0xB9, 0x61, 0x0C, 0x00, 0xB9, 0x71, 0x08, 0x00, 0xB9, 0x51, 0x04, 0x00, 0xEB, 0xE4, + 0x04, 0x00, 0x38, 0x51, 0x04, 0x00, 0x0C, 0x20, 0xA8, 0x04, 0x06, 0x35, 0x26, 0x2C, 0x04, 0x44, + 0xEB, 0xE4, 0x04, 0x00, 0x0C, 0x20, 0x9C, 0x04, 0x26, 0x2C, 0x06, 0x38, 0x04, 0x44, 0xEB, 0xE4, + 0x04, 0x00, 0x0C, 0x20, 0xA0, 0x04, 0x26, 0x2C, 0x06, 0x38, 0x04, 0x44, 0xEB, 0xE4, 0x04, 0x00, + 0x38, 0x61, 0x0C, 0x00, 0x28, 0x59, 0x78, 0x01, 0x2C, 0xC0, 0x20, 0x00, 0x99, 0x56, 0x9B, 0x04, + 0x98, 0x6E, 0x8D, 0x06, 0x38, 0x71, 0x08, 0x00, 0x92, 0x0C, 0x04, 0x62, 0x99, 0x6C, 0x9A, 0x04, + 0x38, 0x6E, 0x0C, 0x00, 0x08, 0x50, 0x00, 0x01, 0x66, 0x65, 0xB9, 0x6E, 0x0C, 0x00, 0xF2, 0x04, + 0x04, 0x61, 0x99, 0x6C, 0x9A, 0x04, 0x2F, 0xCB, 0x0A, 0x00, 0x36, 0xCD, 0x26, 0xCC, 0x26, 0x7E, + 0x26, 0xCE, 0x28, 0x77, 0x5E, 0x01, 0x0C, 0x60, 0x20, 0x00, 0x26, 0x6C, 0x04, 0x51, 0x0C, 0x90, + 0x14, 0x00, 0x99, 0x06, 0x9B, 0x04, 0x99, 0x56, 0x98, 0x04, 0x99, 0x06, 0x99, 0x04, 0x26, 0x9C, + 0xA9, 0x79, 0x98, 0x04, 0x0C, 0x70, 0xF4, 0x01, 0xA9, 0x7C, 0xB4, 0x04, 0x0C, 0x70, 0x18, 0x00, + 0x26, 0x7C, 0xA9, 0x09, 0x9A, 0x04, 0x0C, 0x20, 0xA4, 0x04, 0x0C, 0x30, 0x98, 0x04, 0xA9, 0x07, + 0x98, 0x04, 0xA9, 0x07, 0x9A, 0x04, 0x26, 0x2C, 0x26, 0x3C, 0x04, 0x44, 0xEB, 0xE4, 0x04, 0x00, + 0x18, 0x79, 0x98, 0x04, 0xC4, 0x71, 0xD2, 0x0B, 0x18, 0x79, 0x99, 0x04, 0x34, 0x72, 0x13, 0x77, + 0xC4, 0x7A, 0xD2, 0x05, 0x04, 0x75, 0x99, 0x7C, 0xBC, 0x04, 0xF2, 0x08, 0x26, 0xBA, 0x36, 0xBD, + 0x26, 0xBB, 0x26, 0xBE, 0x04, 0x71, 0x99, 0x7B, 0xBC, 0x04, 0x38, 0x6E, 0x88, 0x06, 0x04, 0x71, + 0x53, 0x7D, 0x66, 0x76, 0x30, 0x61, 0xB9, 0x7E, 0x88, 0x06, 0x58, 0xC1, 0x20, 0x00, 0x58, 0x81, + 0x10, 0x00, 0x06, 0x26, 0x2C, 0x10, 0x30, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x04, 0x60, 0x06, 0x52, + 0x63, 0x56, 0xD4, 0x51, 0x13, 0x76, 0x92, 0x05, 0x24, 0x61, 0xC4, 0x64, 0x92, 0xF9, 0x06, 0x76, + 0x0C, 0x60, 0xFC, 0x0A, 0x18, 0x56, 0xA1, 0x06, 0x04, 0x41, 0x24, 0x51, 0x99, 0x56, 0xA1, 0x06, + 0x2F, 0x57, 0x07, 0x00, 0x26, 0x57, 0x26, 0x56, 0x26, 0x47, 0x99, 0x45, 0x94, 0x06, 0x04, 0x41, + 0x99, 0x45, 0x95, 0x06, 0x99, 0x05, 0x96, 0x06, 0x04, 0x51, 0x53, 0x57, 0x18, 0x76, 0xA0, 0x06, + 0x66, 0x57, 0x99, 0x56, 0xA0, 0x06, 0xE1, 0xF0, 0x38, 0x70, 0x70, 0x1A, 0x3C, 0x10, 0x20, 0x00, + 0xD9, 0xC1, 0x10, 0x00, 0xD1, 0x81, 0x18, 0xF7, 0x8F, 0x00, 0x0C, 0x70, 0xFC, 0x0A, 0x18, 0xA7, + 0x24, 0x03, 0x18, 0x37, 0xA2, 0x06, 0xC4, 0xA0, 0x06, 0xE7, 0x92, 0x12, 0xC4, 0x30, 0x92, 0x1A, + 0x18, 0x67, 0x8D, 0x06, 0x06, 0x23, 0xC4, 0x60, 0x9A, 0x9E, 0x00, 0x00, 0xF8, 0x67, 0xB4, 0x0C, + 0x0A, 0x9A, 0x00, 0x00, 0x34, 0x61, 0xA9, 0x67, 0xB4, 0x0C, 0xFA, 0x95, 0x00, 0x00, 0xC4, 0xA1, + 0x92, 0x09, 0xC4, 0x30, 0x92, 0x07, 0x18, 0x77, 0x8C, 0x06, 0x06, 0x23, 0xC4, 0x71, 0x8A, 0x8B, + 0x00, 0x00, 0xC4, 0x30, 0x99, 0x0E, 0xA1, 0x06, 0x06, 0x2E, 0x82, 0x0B, 0x04, 0xC0, 0x04, 0xDC, + 0x26, 0xDE, 0x06, 0x7E, 0x06, 0x5C, 0x06, 0x4C, 0x04, 0xB1, 0x1C, 0x90, 0x10, 0x00, 0xF2, 0x12, + 0x0C, 0x20, 0x90, 0x11, 0x04, 0x4C, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x18, 0x2E, 0x23, 0x03, + 0xEB, 0x2B, 0x02, 0x00, 0xF2, 0x68, 0x98, 0x87, 0x94, 0x06, 0x92, 0x07, 0x24, 0x73, 0xC6, 0x7D, + 0x82, 0x21, 0xC6, 0x43, 0xA2, 0xF9, 0xF2, 0x1E, 0x18, 0x6E, 0x23, 0x03, 0x34, 0x81, 0x63, 0x68, + 0xD4, 0x61, 0x82, 0x15, 0x98, 0x67, 0x96, 0x06, 0x82, 0x06, 0x99, 0x07, 0x96, 0x06, 0x99, 0x97, + 0x95, 0x06, 0xF2, 0x09, 0x18, 0x67, 0x95, 0x06, 0xCC, 0x60, 0xEF, 0x00, 0xD2, 0x04, 0x24, 0x61, + 0x99, 0x67, 0x95, 0x06, 0x06, 0x6B, 0x53, 0x68, 0x66, 0x56, 0x66, 0xC6, 0x24, 0x41, 0x13, 0x44, + 0xF2, 0xDE, 0x04, 0x60, 0x99, 0x3E, 0xA1, 0x06, 0x06, 0x72, 0x06, 0x46, 0x04, 0xD1, 0xC6, 0x63, + 0xB2, 0x22, 0x98, 0x27, 0x94, 0x06, 0x82, 0x1B, 0x06, 0x2D, 0x53, 0x24, 0xD6, 0x25, 0x92, 0x15, + 0x18, 0x27, 0x96, 0x06, 0xC6, 0x2F, 0xB2, 0x05, 0x24, 0x21, 0x99, 0x27, 0x96, 0x06, 0xF2, 0x0D, + 0x98, 0x2E, 0xA1, 0x06, 0x82, 0x04, 0x34, 0x21, 0x99, 0x2E, 0xA1, 0x06, 0x99, 0x07, 0x94, 0x06, + 0x99, 0x07, 0x95, 0x06, 0x99, 0x07, 0x96, 0x06, 0x24, 0x61, 0x13, 0x66, 0x24, 0x41, 0xC4, 0x44, + 0x24, 0x73, 0x92, 0xDE, 0x04, 0xB0, 0x06, 0xDB, 0x04, 0x91, 0xC6, 0xBA, 0xB2, 0x14, 0x18, 0x7E, + 0x23, 0x03, 0x63, 0x7D, 0xD4, 0x71, 0x82, 0x0C, 0x06, 0x7C, 0x73, 0x7D, 0xD4, 0x71, 0x92, 0x06, + 0x06, 0x29, 0x53, 0x2D, 0x13, 0x22, 0xEB, 0x2B, 0x02, 0x00, 0x24, 0xB1, 0x13, 0xBB, 0x24, 0xD1, + 0xC4, 0xD4, 0x92, 0xEC, 0x78, 0x7E, 0xB4, 0x0C, 0x04, 0x21, 0xC4, 0x70, 0x02, 0x04, 0x26, 0x72, + 0xA9, 0x7E, 0xB4, 0x0C, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, + 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0xD1, 0x81, 0x06, 0xE2, 0x78, 0x7E, 0x04, 0x00, + 0x70, 0x22, 0x36, 0x27, 0xC4, 0x20, 0x32, 0x02, 0x16, 0x22, 0x78, 0xDE, 0x02, 0x00, 0x78, 0x7E, + 0x06, 0x00, 0x36, 0xD7, 0xC4, 0xD0, 0x32, 0x02, 0x16, 0xDD, 0x06, 0x32, 0x4B, 0x14, 0x00, 0x00, + 0x06, 0x3D, 0x06, 0xC2, 0x06, 0x2D, 0x4B, 0x14, 0x00, 0x00, 0x26, 0x2C, 0x0C, 0x30, 0x00, 0x01, + 0x0C, 0xF0, 0xE8, 0x01, 0xF1, 0xF0, 0x86, 0xD2, 0x8A, 0xE3, 0x00, 0x00, 0x0C, 0xA0, 0xFC, 0x0A, + 0x38, 0x6A, 0x0C, 0x00, 0x08, 0x70, 0x02, 0x00, 0x2C, 0x70, 0x00, 0x03, 0xD6, 0x67, 0x82, 0x05, + 0x0C, 0x70, 0xF4, 0x01, 0xFA, 0xD3, 0x00, 0x00, 0x98, 0x3E, 0x21, 0x00, 0x82, 0x0F, 0x28, 0x7E, + 0x1A, 0x00, 0xC4, 0x7A, 0xCA, 0xCD, 0x00, 0x00, 0x28, 0x2E, 0x1C, 0x00, 0x24, 0x31, 0x4B, 0x14, + 0x00, 0x00, 0xA9, 0x2E, 0x1C, 0x00, 0xFA, 0xC4, 0x00, 0x00, 0x78, 0x2E, 0x18, 0x00, 0x04, 0x31, + 0x0C, 0xF0, 0xBC, 0x00, 0xF1, 0xF0, 0xA8, 0x8E, 0x16, 0x00, 0x06, 0xC2, 0x2F, 0xBD, 0x0D, 0x00, + 0x92, 0x04, 0xA9, 0xDE, 0x16, 0x00, 0xF2, 0x14, 0x2F, 0x7D, 0x0B, 0x00, 0x06, 0x67, 0x57, 0x62, + 0x3F, 0x27, 0x06, 0x00, 0x0C, 0x30, 0x64, 0x00, 0x26, 0x22, 0xAB, 0x15, 0x00, 0x00, 0x06, 0x92, + 0x04, 0x3A, 0x06, 0x28, 0x8B, 0x16, 0x00, 0x00, 0x26, 0x29, 0xA9, 0x2E, 0x16, 0x00, 0xA8, 0x7E, + 0x16, 0x00, 0x92, 0x04, 0x04, 0x71, 0xA9, 0x7E, 0x16, 0x00, 0x06, 0x2D, 0xD7, 0x21, 0x0C, 0x30, + 0x64, 0x00, 0x26, 0x2B, 0xAB, 0x15, 0x00, 0x00, 0x28, 0x7E, 0x1A, 0x00, 0x06, 0x92, 0x2F, 0x67, + 0x07, 0x00, 0x26, 0x76, 0x06, 0x67, 0x57, 0x62, 0x3F, 0x27, 0x06, 0x00, 0x26, 0x22, 0x0C, 0x30, + 0x64, 0x00, 0x8B, 0x16, 0x00, 0x00, 0x26, 0x29, 0xA3, 0x22, 0x82, 0x04, 0xA9, 0x2E, 0x1A, 0x00, + 0xF2, 0x04, 0x04, 0x71, 0xA9, 0x7E, 0x1A, 0x00, 0x26, 0xBD, 0xD7, 0xB1, 0x2F, 0x2D, 0x0B, 0x00, + 0x26, 0x22, 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x28, 0x7E, 0x18, 0x00, 0xE7, 0x70, + 0x26, 0x27, 0xA3, 0x72, 0x92, 0x02, 0x04, 0x71, 0xA9, 0x7E, 0x18, 0x00, 0x28, 0xDE, 0x18, 0x00, + 0xC6, 0xDC, 0xA2, 0x0B, 0x2F, 0x7D, 0x0D, 0x00, 0x26, 0x7D, 0x06, 0x67, 0xD7, 0x62, 0x2F, 0x26, + 0x07, 0x00, 0x26, 0x2D, 0x06, 0x3C, 0xF2, 0x0A, 0x2F, 0x7C, 0x0C, 0x00, 0x26, 0x7C, 0x06, 0x67, + 0xD7, 0x62, 0x2F, 0x26, 0x07, 0x00, 0x26, 0x2C, 0x06, 0x3D, 0xAB, 0x15, 0x00, 0x00, 0x06, 0x3D, + 0x4B, 0x14, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x28, 0xCE, 0x1A, 0x00, + 0x28, 0x7E, 0x16, 0x00, 0x26, 0xCD, 0x26, 0xC7, 0x26, 0xC2, 0x06, 0x3D, 0x06, 0x2D, 0x4B, 0x14, + 0x00, 0x00, 0x06, 0x3C, 0x4B, 0x14, 0x00, 0x00, 0x08, 0x30, 0x03, 0x00, 0x2C, 0x30, 0x90, 0xD0, + 0xAB, 0x15, 0x00, 0x00, 0x2F, 0xBC, 0x0D, 0x00, 0xB8, 0x60, 0x8C, 0x19, 0x3F, 0x22, 0x0B, 0x00, + 0x23, 0x22, 0xA9, 0x2E, 0x1C, 0x00, 0x82, 0x07, 0xCC, 0x20, 0x77, 0x00, 0x0C, 0x60, 0x78, 0x00, + 0xC2, 0x07, 0xF2, 0x08, 0xCC, 0x20, 0x27, 0x00, 0xD2, 0x05, 0x0C, 0x60, 0x28, 0x00, 0xA9, 0x6E, + 0x1C, 0x00, 0xB8, 0x60, 0x8C, 0x19, 0x92, 0x0D, 0x98, 0x60, 0xBE, 0x1B, 0x82, 0x0A, 0x28, 0x6E, + 0x1C, 0x00, 0xCC, 0x60, 0x9F, 0x00, 0xD2, 0x05, 0x0C, 0x60, 0xA0, 0x00, 0xA9, 0x6E, 0x1C, 0x00, + 0xB8, 0x70, 0x8C, 0x19, 0x92, 0x0D, 0x98, 0x7A, 0xE0, 0x00, 0x92, 0x0A, 0x28, 0x7E, 0x1C, 0x00, + 0xCC, 0x70, 0xC7, 0x00, 0xD2, 0x05, 0x0C, 0x70, 0xC8, 0x00, 0xA9, 0x7E, 0x1C, 0x00, 0x58, 0xC1, + 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x20, 0x00, + 0xD9, 0xC1, 0x10, 0x00, 0x04, 0xC4, 0x06, 0xE2, 0x26, 0xC2, 0x04, 0x28, 0x06, 0xD3, 0x04, 0x44, + 0x06, 0x3C, 0x26, 0x2E, 0xD1, 0x81, 0xEB, 0xE4, 0x04, 0x00, 0x06, 0x2C, 0x06, 0x3E, 0x04, 0x44, + 0x0C, 0xC0, 0x14, 0x00, 0xEB, 0xE4, 0x04, 0x00, 0x26, 0xCD, 0x06, 0x2E, 0x06, 0x3C, 0x04, 0x44, + 0xEB, 0xE4, 0x04, 0x00, 0x0C, 0xB0, 0xFC, 0x0A, 0x18, 0x7B, 0x8C, 0x06, 0xC4, 0x71, 0x92, 0x49, + 0x18, 0x7E, 0x24, 0x00, 0xC4, 0x73, 0xD2, 0x45, 0x70, 0x2E, 0x78, 0x7E, 0x04, 0x00, 0x36, 0x27, + 0xC4, 0x20, 0x32, 0x02, 0x16, 0x22, 0x78, 0x6E, 0x02, 0x00, 0x78, 0x7E, 0x06, 0x00, 0x43, 0x22, + 0x3F, 0x77, 0x06, 0x00, 0xC4, 0x70, 0x32, 0x02, 0x16, 0x77, 0x06, 0x32, 0x43, 0x97, 0x4B, 0x14, + 0x00, 0x00, 0x06, 0xA2, 0x06, 0x39, 0x06, 0x29, 0x4B, 0x14, 0x00, 0x00, 0x26, 0x2A, 0x0C, 0x30, + 0x00, 0x01, 0x0C, 0xF0, 0xE8, 0x01, 0xF1, 0xF0, 0x18, 0x7E, 0x24, 0x00, 0xCC, 0x20, 0x19, 0x00, + 0x24, 0x71, 0x13, 0x77, 0x99, 0x7E, 0x24, 0x00, 0xD2, 0x1C, 0xC4, 0x74, 0x92, 0x1D, 0x70, 0x2E, + 0x78, 0x7E, 0x04, 0x00, 0x04, 0x33, 0x26, 0x27, 0x78, 0x7E, 0x08, 0x00, 0x26, 0x27, 0x8B, 0x16, + 0x00, 0x00, 0xA1, 0x2E, 0x78, 0x7E, 0x06, 0x00, 0x78, 0x2E, 0x02, 0x00, 0x04, 0x33, 0x26, 0x27, + 0x78, 0x7E, 0x0A, 0x00, 0x26, 0x27, 0x8B, 0x16, 0x00, 0x00, 0xA9, 0x2E, 0x02, 0x00, 0xF2, 0x04, + 0x04, 0x75, 0x99, 0x7E, 0x24, 0x00, 0x0C, 0x20, 0x10, 0x00, 0x26, 0x2E, 0x06, 0x3C, 0x04, 0x44, + 0xEB, 0xE4, 0x04, 0x00, 0x28, 0x7D, 0x1C, 0x00, 0x99, 0x7E, 0x1F, 0x00, 0x98, 0x7E, 0x21, 0x00, + 0x82, 0x04, 0x99, 0x0E, 0x21, 0x00, 0xF2, 0x15, 0x18, 0x7E, 0x20, 0x00, 0xCC, 0x70, 0xEF, 0x00, + 0xD2, 0x15, 0x06, 0x2E, 0x0B, 0xED, 0x01, 0x00, 0xC4, 0x20, 0x92, 0x0B, 0x20, 0x7D, 0x0C, 0x60, + 0x28, 0x08, 0x26, 0x77, 0x26, 0x76, 0x70, 0x67, 0x28, 0x7B, 0x08, 0x03, 0xC6, 0x67, 0x02, 0x06, + 0x18, 0x7E, 0x20, 0x00, 0x24, 0x71, 0x99, 0x7E, 0x20, 0x00, 0x06, 0x2E, 0x0B, 0x3A, 0x02, 0x00, + 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0xB8, 0x06, + 0xD9, 0xC1, 0xA8, 0x06, 0xD9, 0x81, 0x98, 0x06, 0x0C, 0xE0, 0xFC, 0x0A, 0x18, 0xCE, 0x8D, 0x06, + 0x38, 0x70, 0x70, 0x1A, 0xC4, 0xC2, 0x18, 0x87, 0x8F, 0x00, 0x92, 0x2C, 0x78, 0x5E, 0xE8, 0x00, + 0x78, 0x6E, 0xEC, 0x00, 0x3F, 0x66, 0x05, 0x00, 0xC4, 0x60, 0x32, 0x02, 0x16, 0x66, 0x99, 0x0E, + 0xF2, 0x00, 0x28, 0x47, 0x92, 0x00, 0x78, 0x5E, 0xEE, 0x00, 0x43, 0x36, 0xC6, 0x34, 0x78, 0x6E, + 0xEA, 0x00, 0x32, 0x18, 0x36, 0x65, 0xC4, 0x60, 0x32, 0x02, 0x16, 0x66, 0x28, 0x57, 0x94, 0x00, + 0x43, 0x66, 0xC6, 0x65, 0x32, 0x04, 0x18, 0x67, 0x99, 0x00, 0xF2, 0x0A, 0x28, 0x57, 0x96, 0x00, + 0xC6, 0x65, 0x32, 0x04, 0x18, 0x67, 0x9A, 0x00, 0xF2, 0x03, 0x18, 0x67, 0x9B, 0x00, 0x99, 0x6E, + 0xF2, 0x00, 0x18, 0x6E, 0x8E, 0x06, 0x18, 0x77, 0x98, 0x00, 0xC6, 0x67, 0xB2, 0x07, 0x98, 0x7E, + 0xF0, 0x00, 0x82, 0x04, 0x04, 0x71, 0x99, 0x7E, 0xF1, 0x00, 0x98, 0x70, 0xB0, 0x1B, 0x82, 0x0C, + 0x08, 0x70, 0x00, 0x80, 0x18, 0x77, 0x88, 0xDC, 0xB8, 0x60, 0x8C, 0x19, 0x26, 0x87, 0x13, 0x88, + 0x82, 0x03, 0x26, 0x87, 0x13, 0x88, 0x38, 0x7E, 0x0C, 0x00, 0xDC, 0x70, 0x00, 0xF0, 0x82, 0x06, + 0x6B, 0x0C, 0x02, 0x00, 0x04, 0xC0, 0xFA, 0x04, 0x02, 0x00, 0x98, 0xAE, 0x1F, 0x03, 0x92, 0x0C, + 0xC4, 0xC0, 0x92, 0x0A, 0xF8, 0x7E, 0xB4, 0x0C, 0x0A, 0xFB, 0x01, 0x00, 0x34, 0x71, 0xA9, 0x7E, + 0xB4, 0x0C, 0xFA, 0xF6, 0x01, 0x00, 0xC4, 0xC0, 0x99, 0x0E, 0x8C, 0x06, 0x92, 0x10, 0x0C, 0x20, + 0x94, 0x0F, 0x06, 0x3C, 0x0C, 0x40, 0xEE, 0x01, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0xC6, 0xCA, + 0x32, 0x58, 0x13, 0x2C, 0x8B, 0x1E, 0x02, 0x00, 0x24, 0xC1, 0xF2, 0xFA, 0x04, 0xD0, 0x04, 0x62, + 0x06, 0xBD, 0x06, 0x7D, 0xB9, 0x61, 0x80, 0x06, 0xC6, 0xA7, 0xC2, 0x1C, 0x38, 0x61, 0x80, 0x06, + 0xC4, 0xA1, 0x34, 0x61, 0x13, 0x66, 0xB9, 0x61, 0x80, 0x06, 0x9A, 0xAC, 0x00, 0x00, 0xC4, 0xC1, + 0x9A, 0xA9, 0x00, 0x00, 0x18, 0x6E, 0xDF, 0x00, 0xC4, 0x61, 0x92, 0x4D, 0x18, 0x6E, 0xE0, 0x00, + 0xC4, 0x61, 0x92, 0x49, 0x38, 0xBE, 0x88, 0x06, 0x06, 0xDA, 0x06, 0x7A, 0xB8, 0x61, 0x80, 0x06, + 0x92, 0xE4, 0x04, 0x90, 0x99, 0xCE, 0x8C, 0x06, 0x06, 0x79, 0x04, 0x51, 0xC6, 0x7A, 0x32, 0x14, + 0x06, 0x6D, 0x73, 0x67, 0xD4, 0x61, 0x9A, 0x65, 0x01, 0x00, 0x13, 0x27, 0xB9, 0x51, 0x8C, 0x06, + 0xB9, 0x71, 0x94, 0x06, 0x8B, 0x1E, 0x02, 0x00, 0x86, 0x22, 0x38, 0x51, 0x8C, 0x06, 0x38, 0x71, + 0x94, 0x06, 0x9A, 0x51, 0x01, 0x00, 0x04, 0x70, 0x08, 0x60, 0xFF, 0xFE, 0x0C, 0xD0, 0x94, 0x0F, + 0x06, 0xA7, 0x2C, 0x60, 0xFF, 0xFF, 0x2F, 0x59, 0x0C, 0x00, 0xC6, 0x75, 0x32, 0x0A, 0x98, 0x5D, + 0x1E, 0x00, 0x9A, 0x4A, 0x01, 0x00, 0x24, 0xA1, 0xC4, 0xAD, 0x2C, 0xD0, 0x26, 0x00, 0x92, 0xF4, + 0x98, 0x7E, 0x8C, 0x06, 0x92, 0x08, 0x0C, 0x70, 0x14, 0x00, 0xA9, 0x7E, 0xB4, 0x0C, 0x04, 0xC1, + 0xFA, 0x87, 0x01, 0x00, 0x04, 0xC1, 0xC6, 0x7C, 0xCA, 0x83, 0x01, 0x00, 0x4B, 0x7B, 0x04, 0x00, + 0xFA, 0x7F, 0x01, 0x00, 0x38, 0x2E, 0x88, 0x06, 0xB9, 0x71, 0x94, 0x06, 0x0C, 0xF0, 0x80, 0x00, + 0xF1, 0xF0, 0x06, 0x92, 0x06, 0x62, 0x57, 0x62, 0x57, 0x91, 0x26, 0x96, 0x3F, 0x22, 0x09, 0x00, + 0x26, 0x22, 0x2F, 0x92, 0x0E, 0x00, 0x2C, 0x90, 0x98, 0x04, 0x78, 0x59, 0x10, 0x00, 0x78, 0x6E, + 0x70, 0x01, 0x38, 0x71, 0x94, 0x06, 0x3F, 0x66, 0x05, 0x00, 0xC4, 0x60, 0x32, 0x02, 0x16, 0x66, + 0x78, 0x29, 0x12, 0x00, 0x78, 0x5E, 0x72, 0x01, 0x36, 0x25, 0xC4, 0x20, 0x32, 0x02, 0x16, 0x22, + 0x28, 0x59, 0x1C, 0x00, 0xB9, 0x71, 0x94, 0x06, 0x06, 0x32, 0xB9, 0x51, 0x8C, 0x06, 0xB9, 0x61, + 0x90, 0x06, 0x4B, 0x14, 0x00, 0x00, 0x38, 0x61, 0x90, 0x06, 0x06, 0x42, 0x06, 0x36, 0x06, 0x26, + 0xB9, 0x41, 0x88, 0x06, 0x4B, 0x14, 0x00, 0x00, 0x38, 0x51, 0x8C, 0x06, 0x38, 0x41, 0x88, 0x06, + 0x06, 0x35, 0x26, 0x42, 0x06, 0x25, 0xB9, 0x41, 0x88, 0x06, 0x4B, 0x14, 0x00, 0x00, 0x38, 0x41, + 0x88, 0x06, 0x38, 0x71, 0x94, 0x06, 0xC6, 0x42, 0xBA, 0x72, 0xFF, 0xFF, 0x06, 0x29, 0x0C, 0x30, + 0x58, 0x0C, 0xEB, 0x4A, 0x02, 0x00, 0x04, 0xD1, 0x38, 0xBE, 0x88, 0x06, 0x06, 0x7D, 0xFA, 0x67, + 0xFF, 0xFF, 0x0C, 0x20, 0xE4, 0x05, 0x0C, 0x30, 0x48, 0x05, 0x26, 0x21, 0x26, 0x31, 0xAB, 0x0E, + 0x02, 0x00, 0x04, 0x70, 0x0C, 0x90, 0x94, 0x0F, 0x0C, 0x40, 0xA4, 0x0F, 0x06, 0x57, 0x06, 0x67, + 0xC6, 0x7C, 0xB2, 0x58, 0x98, 0x39, 0x1E, 0x00, 0x82, 0x4E, 0x04, 0x31, 0x53, 0x36, 0xD6, 0x3B, + 0x92, 0x48, 0x06, 0x29, 0xB9, 0x41, 0x88, 0x06, 0xB9, 0x51, 0x8C, 0x06, 0xB9, 0x61, 0x90, 0x06, + 0xB9, 0x71, 0x94, 0x06, 0x0B, 0xED, 0x01, 0x00, 0x38, 0x31, 0x80, 0x06, 0x38, 0x41, 0x88, 0x06, + 0x38, 0x51, 0x8C, 0x06, 0x38, 0x61, 0x90, 0x06, 0x38, 0x71, 0x94, 0x06, 0xC6, 0x23, 0x92, 0x31, + 0x2F, 0x35, 0x05, 0x00, 0x04, 0x21, 0x26, 0x25, 0x26, 0x53, 0x0C, 0x30, 0xE4, 0x05, 0x26, 0x31, + 0x57, 0x51, 0x26, 0x53, 0x04, 0x31, 0x91, 0x35, 0x20, 0x34, 0xB9, 0x21, 0x84, 0x06, 0x28, 0x29, + 0x1C, 0x00, 0xA9, 0x35, 0x02, 0x00, 0x28, 0x34, 0x02, 0x00, 0x99, 0x65, 0x01, 0x00, 0xA9, 0x35, + 0x04, 0x00, 0x06, 0x32, 0xB9, 0x41, 0x88, 0x06, 0xB9, 0x51, 0x8C, 0x06, 0xB9, 0x61, 0x90, 0x06, + 0xB9, 0x71, 0x94, 0x06, 0x4B, 0x14, 0x00, 0x00, 0x38, 0x51, 0x8C, 0x06, 0x38, 0x71, 0x94, 0x06, + 0x38, 0x61, 0x90, 0x06, 0xB9, 0x25, 0x08, 0x00, 0x38, 0x41, 0x88, 0x06, 0x38, 0x51, 0x84, 0x06, + 0x24, 0x71, 0x13, 0x77, 0x24, 0x61, 0xC4, 0x6D, 0x2C, 0x90, 0x26, 0x00, 0x2C, 0x40, 0x26, 0x00, + 0x92, 0xA8, 0x04, 0x70, 0x06, 0x4E, 0x06, 0x67, 0x04, 0x31, 0xC6, 0x6A, 0x32, 0x1F, 0x06, 0x53, + 0x53, 0x56, 0xD6, 0x5D, 0x92, 0x17, 0x2F, 0x57, 0x07, 0x00, 0x26, 0x57, 0x0C, 0x20, 0x48, 0x05, + 0x26, 0x21, 0x57, 0x51, 0x26, 0x52, 0x28, 0x24, 0x70, 0x01, 0x91, 0x35, 0x99, 0x65, 0x01, 0x00, + 0xA9, 0x25, 0x02, 0x00, 0x28, 0x24, 0x72, 0x01, 0xB9, 0x05, 0x08, 0x00, 0x24, 0x71, 0xA9, 0x25, + 0x04, 0x00, 0x24, 0x61, 0x2C, 0x40, 0x20, 0x00, 0xF2, 0xE1, 0x04, 0x61, 0xB9, 0x00, 0x84, 0x1A, + 0x0C, 0x30, 0xE4, 0x05, 0x0C, 0x40, 0x48, 0x05, 0x99, 0x60, 0xBD, 0x1B, 0x06, 0x21, 0x26, 0x31, + 0x26, 0x41, 0x99, 0x00, 0xBC, 0x1B, 0x04, 0x94, 0x6B, 0x11, 0x02, 0x00, 0x06, 0x72, 0x26, 0x91, + 0x04, 0x60, 0x04, 0x51, 0xC6, 0x67, 0x3A, 0xC3, 0xFE, 0xFF, 0x10, 0x49, 0x06, 0x24, 0x06, 0x34, + 0x57, 0x21, 0x57, 0x32, 0x26, 0x32, 0x3F, 0x44, 0x03, 0x00, 0x18, 0x39, 0x01, 0x00, 0xB9, 0x51, + 0x8C, 0x06, 0x26, 0x44, 0xD7, 0x32, 0x2F, 0x24, 0x0E, 0x00, 0x26, 0x3E, 0x2C, 0x20, 0x98, 0x04, + 0x2C, 0x30, 0x5C, 0x01, 0xB9, 0x61, 0x90, 0x06, 0xB9, 0x71, 0x94, 0x06, 0xEB, 0x4A, 0x02, 0x00, + 0x38, 0x51, 0x8C, 0x06, 0x10, 0x49, 0x38, 0x61, 0x90, 0x06, 0x38, 0x71, 0x94, 0x06, 0x06, 0x35, + 0x53, 0x34, 0x18, 0x49, 0x01, 0x00, 0x06, 0x25, 0x53, 0x24, 0x66, 0xB3, 0x66, 0xD2, 0x24, 0x61, + 0x24, 0x98, 0xF2, 0xD1, 0x34, 0x21, 0x06, 0x65, 0x53, 0x62, 0x24, 0x91, 0x66, 0xB6, 0x13, 0x99, + 0x24, 0x71, 0xFA, 0x95, 0xFE, 0xFF, 0x06, 0x5B, 0x73, 0x5A, 0xD4, 0x51, 0x92, 0x45, 0x18, 0x5D, + 0x21, 0x00, 0xC6, 0x58, 0xB2, 0x1F, 0x06, 0x2D, 0xB9, 0x61, 0x90, 0x06, 0xB9, 0x71, 0x94, 0x06, + 0x0B, 0xED, 0x01, 0x00, 0xC4, 0x21, 0x38, 0x61, 0x90, 0x06, 0x38, 0x71, 0x94, 0x06, 0x92, 0x12, + 0x18, 0x5D, 0x21, 0x00, 0x06, 0x2D, 0x24, 0x51, 0x99, 0x5D, 0x21, 0x00, 0xB9, 0x61, 0x90, 0x06, + 0xB9, 0x71, 0x94, 0x06, 0x0B, 0x3A, 0x02, 0x00, 0x38, 0x61, 0x90, 0x06, 0x38, 0x71, 0x94, 0x06, + 0xF2, 0x23, 0x98, 0x5E, 0x8C, 0x06, 0x82, 0x04, 0x34, 0x51, 0x99, 0x5E, 0x8C, 0x06, 0x04, 0x41, + 0x38, 0x3E, 0x88, 0x06, 0x06, 0x54, 0x53, 0x5A, 0x15, 0x55, 0x56, 0x53, 0xB9, 0x5E, 0x88, 0x06, + 0x99, 0x0D, 0x1E, 0x00, 0x99, 0x0D, 0x20, 0x00, 0x99, 0x0D, 0x21, 0x00, 0x99, 0x0D, 0x23, 0x00, + 0x99, 0x4E, 0xF0, 0x00, 0x18, 0x5D, 0x22, 0x00, 0xC4, 0x52, 0x92, 0x06, 0x38, 0x5E, 0x0C, 0x00, + 0x56, 0x56, 0xB9, 0x5E, 0x0C, 0x00, 0x24, 0x71, 0x13, 0x77, 0xFA, 0x6E, 0xFE, 0xFF, 0x06, 0x2C, + 0x58, 0xC1, 0xA8, 0x06, 0x58, 0x81, 0x98, 0x06, 0x2C, 0x10, 0xB8, 0x06, 0xE1, 0xF0, 0x00, 0x00, + 0x34, 0x18, 0xC1, 0xE1, 0xEB, 0x54, 0x02, 0x00, 0xC4, 0x21, 0x06, 0xE2, 0x92, 0x03, 0xAB, 0xF1, + 0x02, 0x00, 0x4B, 0x2E, 0x02, 0x00, 0x66, 0x2E, 0x40, 0xE1, 0x13, 0x22, 0x24, 0x18, 0xE1, 0xF0, + 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, + 0xD1, 0xC1, 0x08, 0xD0, 0x06, 0x00, 0x0C, 0xC0, 0x14, 0x0B, 0x04, 0xE0, 0x2C, 0xD0, 0x00, 0xBD, + 0x06, 0x2E, 0x0C, 0x30, 0x17, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x2C, 0xE0, 0x00, 0x4B, 0xC6, 0xED, + 0x2C, 0x20, 0xA1, 0x01, 0xB1, 0x2C, 0x24, 0xC4, 0x92, 0xF4, 0x08, 0xD0, 0x02, 0x00, 0x0C, 0xC0, + 0x74, 0x0B, 0x04, 0xE0, 0x2C, 0xD0, 0xA0, 0x4E, 0x06, 0x2E, 0x04, 0x3E, 0xAB, 0x15, 0x00, 0x00, + 0x2C, 0xE0, 0x30, 0x2A, 0xC6, 0xED, 0x2C, 0x20, 0x81, 0x01, 0xB1, 0x2C, 0x24, 0xC4, 0x92, 0xF5, + 0x50, 0xC1, 0x0C, 0x60, 0x2B, 0x00, 0xB9, 0x60, 0xD4, 0x0B, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, + 0x2F, 0x72, 0x02, 0x00, 0x34, 0x18, 0x26, 0x72, 0xC1, 0xE1, 0x06, 0xE7, 0x57, 0xE2, 0x26, 0x7E, + 0x26, 0x27, 0x2C, 0x20, 0xA4, 0x06, 0x0C, 0xE0, 0xFC, 0x0A, 0x26, 0xE2, 0x14, 0x71, 0x04, 0x26, + 0xA1, 0x7E, 0xA9, 0x7E, 0x02, 0x00, 0x26, 0x2E, 0x04, 0x30, 0x0C, 0x40, 0x24, 0x00, 0x0C, 0xF0, + 0xB0, 0x01, 0xF1, 0xF0, 0x04, 0x71, 0x99, 0x7E, 0x04, 0x00, 0x38, 0x70, 0x70, 0x1A, 0xA9, 0x0E, + 0x2A, 0x00, 0x0C, 0x20, 0x2E, 0x00, 0x18, 0x77, 0x9D, 0x00, 0x26, 0x2E, 0x99, 0x7E, 0x2C, 0x00, + 0x04, 0x30, 0x04, 0x46, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x99, 0x0E, 0x2D, 0x00, 0x40, 0xE1, + 0x24, 0x18, 0xE1, 0xF0, 0x34, 0x18, 0xC1, 0xE1, 0x04, 0xE0, 0x06, 0x2E, 0x0B, 0x80, 0x02, 0x00, + 0x24, 0xE1, 0xC4, 0xED, 0x92, 0xFB, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x3C, 0x10, 0x20, 0x00, + 0xD9, 0xC1, 0x10, 0x00, 0xD1, 0x81, 0x06, 0xE2, 0x06, 0x93, 0x06, 0x25, 0x06, 0x36, 0x06, 0xC4, + 0x06, 0xA5, 0x18, 0x81, 0x20, 0x00, 0x28, 0xD1, 0x24, 0x00, 0x28, 0xB1, 0x28, 0x00, 0x0C, 0xF0, + 0x98, 0x00, 0xF1, 0xF0, 0x06, 0x32, 0x06, 0x2E, 0x8B, 0x16, 0x00, 0x00, 0x06, 0xE2, 0x06, 0x38, + 0x06, 0x2A, 0x0C, 0xF0, 0x98, 0x00, 0xF1, 0xF0, 0xC6, 0xCD, 0x06, 0x32, 0x32, 0x03, 0x43, 0x2E, + 0xF2, 0x14, 0x06, 0x29, 0x8B, 0x16, 0x00, 0x00, 0xC6, 0xCB, 0x06, 0x32, 0x32, 0x0D, 0x36, 0x3E, + 0x3F, 0x2D, 0x0C, 0x00, 0x4B, 0x14, 0x00, 0x00, 0x3F, 0x3D, 0x0B, 0x00, 0x8B, 0x16, 0x00, 0x00, + 0x26, 0x2E, 0x43, 0x22, 0xF2, 0x02, 0x43, 0x22, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, + 0x20, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x28, 0xD4, 0x0E, 0x00, 0x38, 0xF1, + 0x10, 0x00, 0x78, 0xE1, 0x14, 0x00, 0xC6, 0x5D, 0x04, 0x75, 0x12, 0x11, 0x28, 0xD4, 0x0A, 0x00, + 0x04, 0x74, 0xC6, 0x5D, 0x12, 0x0C, 0x28, 0xD4, 0x06, 0x00, 0x04, 0x73, 0xC6, 0x5D, 0x12, 0x07, + 0x28, 0x44, 0x02, 0x00, 0x04, 0x71, 0xC6, 0x54, 0x02, 0x02, 0x04, 0x72, 0x10, 0x56, 0x36, 0x75, + 0xB3, 0x57, 0x70, 0x7F, 0x02, 0x05, 0xC6, 0x7E, 0x92, 0x0F, 0xA1, 0x0F, 0xF2, 0x0F, 0xC4, 0x50, + 0x82, 0x05, 0x16, 0x5E, 0xC6, 0x75, 0x92, 0x04, 0xF2, 0xF9, 0xC4, 0x70, 0x02, 0x03, 0x34, 0x71, + 0xF2, 0x04, 0xC4, 0x70, 0x82, 0x03, 0x24, 0x71, 0xA1, 0x7F, 0x70, 0x5F, 0x10, 0x76, 0xC6, 0x5E, + 0x92, 0x05, 0xC4, 0x74, 0xD2, 0x0A, 0x24, 0x71, 0xF2, 0x07, 0x16, 0xEE, 0xC6, 0x5E, 0x92, 0x05, + 0xC4, 0x71, 0xC2, 0x03, 0x34, 0x71, 0x91, 0x76, 0x10, 0x76, 0x6B, 0xE6, 0x04, 0x00, 0x01, 0x00, + 0x05, 0x00, 0x30, 0x00, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, 0x04, 0x79, + 0x91, 0x72, 0x04, 0x77, 0xF2, 0x10, 0x04, 0x77, 0x91, 0x72, 0x04, 0x75, 0xF2, 0x0C, 0x04, 0x75, + 0x91, 0x72, 0x04, 0x73, 0xF2, 0x08, 0x04, 0x73, 0x91, 0x72, 0x04, 0x72, 0xF2, 0x04, 0x04, 0x72, + 0x91, 0x72, 0x04, 0x71, 0x50, 0xC1, 0x91, 0x73, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x2F, 0x72, 0x02, 0x00, 0x26, 0x72, 0x06, 0x67, 0x3C, 0x10, 0x40, 0x00, 0x57, 0x62, 0xD9, 0xC1, + 0x30, 0x00, 0x26, 0x76, 0x04, 0xC1, 0x26, 0xC2, 0x26, 0x27, 0x0C, 0xE0, 0xFC, 0x0A, 0x57, 0xC1, + 0x2C, 0x20, 0xA4, 0x06, 0xD9, 0x81, 0x20, 0x00, 0x26, 0xCE, 0x26, 0xE2, 0x18, 0x7E, 0x04, 0x00, + 0x99, 0x01, 0x0D, 0x00, 0x99, 0x01, 0x0C, 0x00, 0xC4, 0x71, 0x06, 0xB3, 0x0C, 0xD0, 0x64, 0x00, + 0xC2, 0x17, 0x78, 0x2E, 0x06, 0x00, 0x78, 0x7E, 0x0A, 0x00, 0x36, 0x27, 0xC4, 0x20, 0x32, 0x02, + 0x16, 0x22, 0x78, 0x3E, 0x08, 0x00, 0x78, 0x7E, 0x0C, 0x00, 0x43, 0x22, 0x36, 0x37, 0xC4, 0x30, + 0x32, 0x02, 0x16, 0x33, 0x43, 0x33, 0x0C, 0xF0, 0xBC, 0x00, 0xF1, 0xF0, 0x06, 0xD2, 0x78, 0x7E, + 0x2E, 0x00, 0x78, 0x2E, 0x30, 0x00, 0x18, 0x3E, 0x2D, 0x00, 0xA9, 0x7E, 0x30, 0x00, 0xA9, 0x2E, + 0x32, 0x00, 0x26, 0x27, 0x24, 0x31, 0x26, 0x2D, 0x8B, 0x16, 0x00, 0x00, 0x99, 0xD0, 0xAD, 0x1B, + 0x0C, 0x70, 0x2A, 0x00, 0xA9, 0xDE, 0x2E, 0x00, 0x26, 0x7E, 0xB1, 0x71, 0x38, 0x70, 0x70, 0x1A, + 0x06, 0x52, 0x18, 0x77, 0x9C, 0x00, 0x04, 0x2D, 0x04, 0x3C, 0x0C, 0x60, 0x2C, 0x00, 0xB9, 0x71, + 0x04, 0x00, 0x26, 0x21, 0x26, 0x31, 0x06, 0x4B, 0x26, 0x6E, 0xAB, 0x87, 0x02, 0x00, 0x18, 0x7E, + 0x2C, 0x00, 0x68, 0x61, 0x0D, 0x00, 0x04, 0x5C, 0x26, 0x51, 0x60, 0x55, 0x34, 0x71, 0x26, 0x77, + 0x33, 0x77, 0x14, 0x41, 0x26, 0x46, 0xB9, 0x71, 0x10, 0x00, 0xB9, 0x51, 0x14, 0x00, 0x04, 0x70, + 0x34, 0x51, 0xB9, 0x41, 0x18, 0x00, 0xB9, 0x51, 0x1C, 0x00, 0x06, 0xA7, 0x06, 0x5E, 0x06, 0x37, + 0x06, 0x97, 0x06, 0x27, 0x06, 0xF7, 0x06, 0x47, 0x78, 0x85, 0x06, 0x00, 0x26, 0x48, 0x78, 0x85, + 0x08, 0x00, 0x26, 0xF8, 0x38, 0x81, 0x18, 0x00, 0xC6, 0x78, 0x82, 0x08, 0x38, 0x81, 0x1C, 0x00, + 0xC6, 0x78, 0x92, 0x06, 0x06, 0xAF, 0x06, 0x34, 0xF2, 0x03, 0x06, 0x9F, 0x06, 0x24, 0x24, 0x71, + 0xC4, 0x79, 0x24, 0x54, 0x92, 0xEA, 0x38, 0x71, 0x10, 0x00, 0x38, 0x41, 0x14, 0x00, 0x18, 0x5E, + 0x04, 0x00, 0x26, 0x77, 0x2F, 0x87, 0x0B, 0x00, 0x24, 0x72, 0x26, 0xB7, 0x13, 0x74, 0xB1, 0x71, + 0x20, 0x78, 0x06, 0x4D, 0xB9, 0x71, 0x04, 0x00, 0x20, 0x7B, 0x13, 0x66, 0xB9, 0x71, 0x08, 0x00, + 0xEB, 0x83, 0x02, 0x00, 0x38, 0x7C, 0x3C, 0x0C, 0x08, 0x60, 0x00, 0xFF, 0x2C, 0x60, 0xFF, 0x0F, + 0x5C, 0x20, 0xFF, 0x0F, 0x57, 0x26, 0x56, 0x76, 0x66, 0x72, 0xB9, 0x7C, 0x3C, 0x0C, 0x18, 0x71, + 0x0C, 0x00, 0x18, 0x5E, 0x04, 0x00, 0x18, 0x61, 0x0D, 0x00, 0xB1, 0x71, 0x20, 0x78, 0x06, 0x29, + 0xB9, 0x71, 0x04, 0x00, 0x20, 0x7B, 0x06, 0x3A, 0xB9, 0x71, 0x08, 0x00, 0x06, 0x4D, 0xEB, 0x83, + 0x02, 0x00, 0x38, 0x7C, 0x3C, 0x0C, 0x1C, 0x50, 0x00, 0x10, 0x5C, 0x20, 0xFF, 0x0F, 0x56, 0x75, + 0x66, 0x72, 0xB9, 0x7C, 0x3C, 0x0C, 0x58, 0xC1, 0x30, 0x00, 0x58, 0x81, 0x20, 0x00, 0x2C, 0x10, + 0x40, 0x00, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, 0x0C, 0x60, 0xFC, 0x0A, 0x18, 0xF6, 0xC0, 0x0C, + 0x06, 0x52, 0xC4, 0xF0, 0x04, 0x72, 0x82, 0x05, 0x38, 0x70, 0x70, 0x1A, 0x28, 0x77, 0xB4, 0x00, + 0x3F, 0x24, 0x03, 0x00, 0xC4, 0x20, 0x32, 0x02, 0x16, 0x22, 0xC4, 0xF0, 0x23, 0x22, 0x92, 0x06, + 0xC4, 0x22, 0xC2, 0x04, 0x04, 0xF1, 0x99, 0xF6, 0xC0, 0x0C, 0x18, 0xF6, 0x1E, 0x03, 0xC4, 0xF2, + 0x92, 0x10, 0xCC, 0x50, 0x14, 0x00, 0x92, 0x09, 0x38, 0x66, 0x0C, 0x00, 0x0C, 0x70, 0x28, 0x00, + 0xD4, 0x61, 0x82, 0x2B, 0x06, 0x75, 0xF2, 0x29, 0xC4, 0x51, 0x92, 0x27, 0x06, 0x7F, 0xF2, 0x25, + 0xC4, 0xF1, 0x92, 0x23, 0xCC, 0x50, 0x14, 0x00, 0x92, 0x1D, 0x38, 0x76, 0x0C, 0x00, 0x28, 0x66, + 0x12, 0x00, 0xD4, 0x71, 0x82, 0x09, 0xC4, 0x60, 0x06, 0x75, 0x82, 0x17, 0x2F, 0x76, 0x06, 0x00, + 0x26, 0x76, 0x23, 0x77, 0xF2, 0x12, 0xC4, 0x60, 0x0C, 0x70, 0x1E, 0x00, 0x82, 0x0E, 0x06, 0x76, + 0x57, 0x71, 0x26, 0x76, 0x23, 0x77, 0xCC, 0x70, 0x1D, 0x00, 0xD2, 0x07, 0x0C, 0x70, 0x1E, 0x00, + 0xF2, 0x04, 0xC4, 0x51, 0x92, 0x02, 0x04, 0x72, 0xC6, 0x27, 0xC2, 0x08, 0xC6, 0x34, 0xC2, 0x04, + 0x3F, 0x77, 0x03, 0x00, 0xF2, 0x02, 0x26, 0x73, 0x23, 0x47, 0x30, 0xF1, 0x06, 0x24, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x86, 0x22, 0x34, 0x14, 0xB1, 0xF1, 0x32, 0x02, 0x16, 0x22, 0x43, 0x72, + 0xC4, 0x72, 0x04, 0x20, 0x02, 0x08, 0x14, 0x22, 0x26, 0x27, 0x57, 0x21, 0x04, 0x36, 0x8B, 0x16, + 0x00, 0x00, 0x43, 0x22, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x20, 0x00, + 0xD9, 0xC1, 0x10, 0x00, 0xD1, 0x81, 0x0C, 0xE0, 0xFC, 0x0A, 0x98, 0x7E, 0xDC, 0x00, 0x92, 0x74, + 0x38, 0x7E, 0x3C, 0x0C, 0xDC, 0x70, 0x00, 0xF0, 0x82, 0x6F, 0x38, 0xDE, 0x40, 0x0C, 0x38, 0xAE, + 0xB8, 0x0C, 0x38, 0x7E, 0xBC, 0x0C, 0x06, 0xBD, 0x77, 0xB6, 0x5C, 0xB0, 0xFF, 0x0F, 0x0C, 0x40, + 0xFF, 0x0F, 0x56, 0x4B, 0x06, 0xCA, 0x08, 0x60, 0x00, 0xFF, 0x2C, 0x60, 0xFF, 0x0F, 0x06, 0x54, + 0x77, 0xC6, 0x57, 0x56, 0x56, 0x76, 0x5C, 0xC0, 0xFF, 0x0F, 0x66, 0x75, 0x36, 0xBC, 0x5C, 0xD0, + 0xFF, 0x0F, 0x0C, 0x50, 0xFF, 0x0F, 0x1C, 0x60, 0x00, 0x10, 0x56, 0x5D, 0x56, 0x76, 0xC4, 0xB0, + 0x66, 0x75, 0xB9, 0x7E, 0xBC, 0x0C, 0x5C, 0xA0, 0xFF, 0x0F, 0x06, 0x7B, 0x32, 0x02, 0x16, 0x7B, + 0x23, 0x77, 0xC4, 0x78, 0xD2, 0x32, 0x36, 0xDA, 0xC4, 0xD0, 0x06, 0x7D, 0x32, 0x02, 0x16, 0x7D, + 0x23, 0x77, 0xC4, 0x78, 0xD2, 0x2A, 0x06, 0x2B, 0xAB, 0xA1, 0x02, 0x00, 0x06, 0x92, 0x06, 0x2D, + 0xAB, 0xA1, 0x02, 0x00, 0xC4, 0xB0, 0x22, 0x03, 0x26, 0xC9, 0xF2, 0x02, 0x36, 0xC9, 0x38, 0x7E, + 0x40, 0x0C, 0x08, 0x60, 0x00, 0xFF, 0x5C, 0xC0, 0xFF, 0x0F, 0x2C, 0x60, 0xFF, 0x0F, 0x57, 0xC6, + 0x56, 0x76, 0xC4, 0xD0, 0x66, 0x7C, 0xB9, 0x7E, 0x40, 0x0C, 0x22, 0x03, 0x26, 0xA2, 0xF2, 0x02, + 0x36, 0xA2, 0x38, 0x7E, 0x40, 0x0C, 0x1C, 0x60, 0x00, 0x10, 0x5C, 0xA0, 0xFF, 0x0F, 0x56, 0x76, + 0x66, 0x7A, 0xB9, 0x7E, 0x40, 0x0C, 0xF2, 0x10, 0x38, 0x7E, 0xB8, 0x0C, 0x08, 0x60, 0x00, 0xFF, + 0x2C, 0x60, 0xFF, 0x0F, 0x56, 0x76, 0x57, 0x46, 0x66, 0x74, 0x1C, 0x60, 0x00, 0x10, 0x56, 0x76, + 0x66, 0x75, 0xB9, 0x7E, 0xB8, 0x0C, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x38, 0x30, 0x70, 0x1A, 0x3C, 0x10, 0x7C, 0x00, 0x0C, 0x50, 0xB2, 0x00, + 0xD9, 0xC1, 0x6C, 0x00, 0xD9, 0x81, 0x5C, 0x00, 0x26, 0x53, 0x10, 0x55, 0x06, 0x21, 0x2C, 0x30, + 0x9E, 0x00, 0x04, 0x4A, 0xB9, 0x51, 0x38, 0x00, 0x0C, 0xD0, 0xFC, 0x0A, 0x0C, 0xF0, 0x40, 0x01, + 0xF1, 0xF0, 0x98, 0x7D, 0x8C, 0x06, 0x92, 0x05, 0x2B, 0x83, 0x02, 0x00, 0xFA, 0x23, 0x03, 0x00, + 0x18, 0xCD, 0xE5, 0x00, 0x2F, 0x7C, 0x0C, 0x00, 0x2F, 0x6C, 0x07, 0x00, 0x06, 0x56, 0x57, 0x52, + 0x26, 0x65, 0x26, 0x6C, 0x0C, 0x20, 0xB0, 0x1A, 0x2F, 0x8D, 0x06, 0x00, 0x06, 0x67, 0x26, 0x72, + 0xB9, 0x71, 0x18, 0x00, 0x06, 0x7C, 0xD7, 0x71, 0x0C, 0x40, 0x28, 0x1B, 0x06, 0x97, 0x26, 0x74, + 0xB9, 0x71, 0x30, 0x00, 0x06, 0xAC, 0x06, 0x7C, 0x57, 0xA1, 0x57, 0x72, 0x26, 0x7A, 0x36, 0x7C, + 0x26, 0x77, 0xB9, 0xA1, 0x28, 0x00, 0x0C, 0xF0, 0xC4, 0x1A, 0x26, 0x7D, 0x26, 0x6F, 0x2C, 0x70, + 0xB8, 0x04, 0x0C, 0x50, 0x38, 0x19, 0x38, 0xB1, 0x28, 0x00, 0x38, 0xE1, 0x28, 0x00, 0xB9, 0x61, + 0x1C, 0x00, 0x26, 0xA5, 0xB9, 0x71, 0x34, 0x00, 0x0C, 0x70, 0x88, 0x1A, 0xB9, 0xA1, 0x44, 0x00, + 0x0C, 0x60, 0x10, 0x19, 0x38, 0xA1, 0x28, 0x00, 0x26, 0xB6, 0x26, 0xE7, 0x0C, 0x30, 0xD8, 0x1A, + 0x0C, 0x70, 0x40, 0x0C, 0x26, 0x93, 0xB9, 0xB1, 0x40, 0x00, 0x26, 0x7D, 0x08, 0xB0, 0x00, 0xFF, + 0xB9, 0x91, 0x24, 0x00, 0x26, 0xA7, 0x04, 0x90, 0x2C, 0xB0, 0xFF, 0x0F, 0xB9, 0xE1, 0x48, 0x00, + 0xB9, 0x91, 0x20, 0x00, 0xB9, 0xA1, 0x4C, 0x00, 0xB9, 0xB1, 0x2C, 0x00, 0x18, 0x7D, 0xE6, 0x00, + 0xC6, 0xC7, 0x3A, 0x89, 0x02, 0x00, 0x38, 0x61, 0x20, 0x00, 0x38, 0x51, 0x4C, 0x00, 0x26, 0x56, + 0x30, 0x75, 0x08, 0x60, 0x00, 0xF0, 0xD6, 0x76, 0x06, 0xE5, 0x92, 0x06, 0x06, 0x2C, 0x0B, 0x80, + 0x02, 0x00, 0xFA, 0x55, 0x02, 0x00, 0x0C, 0xA0, 0xA4, 0x06, 0x26, 0xA8, 0x04, 0x98, 0x06, 0xBA, + 0x0C, 0x20, 0x26, 0x00, 0x0C, 0x30, 0x22, 0x00, 0x26, 0x2A, 0x26, 0x3A, 0x04, 0x44, 0xEB, 0xE4, + 0x04, 0x00, 0x34, 0x91, 0xC4, 0x90, 0x34, 0xA4, 0x92, 0xF4, 0x30, 0x7E, 0x13, 0x2C, 0x77, 0x76, + 0x5C, 0x70, 0xFF, 0x0F, 0xA9, 0x78, 0xAA, 0x06, 0x30, 0x7E, 0x06, 0x31, 0x5C, 0x70, 0xFF, 0x0F, + 0xA9, 0x78, 0xAC, 0x06, 0x0B, 0x8E, 0x02, 0x00, 0xF8, 0x28, 0xA4, 0x06, 0x30, 0xAE, 0x22, 0x4E, + 0xF8, 0x78, 0xA6, 0x06, 0x22, 0x4B, 0x38, 0x51, 0x38, 0x00, 0x0C, 0x90, 0x64, 0x00, 0x06, 0x79, + 0x36, 0x75, 0x06, 0x37, 0xB9, 0x71, 0x54, 0x00, 0x4B, 0x14, 0x00, 0x00, 0x38, 0x31, 0x38, 0x00, + 0x06, 0x62, 0x06, 0x2A, 0x77, 0x26, 0x5C, 0x20, 0xFF, 0x0F, 0xB9, 0x61, 0x50, 0x00, 0x4B, 0x14, + 0x00, 0x00, 0x38, 0x61, 0x50, 0x00, 0x06, 0x39, 0x26, 0x26, 0x8B, 0x16, 0x00, 0x00, 0x38, 0x61, + 0x2C, 0x00, 0x5C, 0x20, 0xFF, 0x0F, 0x56, 0xA6, 0x57, 0x26, 0x66, 0xA2, 0xB1, 0xAE, 0x38, 0x71, + 0x54, 0x00, 0x78, 0x28, 0xA6, 0x06, 0x06, 0x37, 0x4B, 0x14, 0x00, 0x00, 0x38, 0x31, 0x38, 0x00, + 0x06, 0x72, 0x0C, 0x20, 0xFF, 0x0F, 0x56, 0x2A, 0xB9, 0x71, 0x54, 0x00, 0x4B, 0x14, 0x00, 0x00, + 0x38, 0x71, 0x54, 0x00, 0x06, 0x39, 0x26, 0x27, 0x8B, 0x16, 0x00, 0x00, 0x1C, 0x70, 0x00, 0x10, + 0x5C, 0x20, 0xFF, 0x0F, 0x56, 0xA7, 0x66, 0xA2, 0x0C, 0x20, 0x14, 0x00, 0xB1, 0xAE, 0x26, 0x21, + 0x06, 0x3B, 0x04, 0x44, 0xEB, 0xE4, 0x04, 0x00, 0xF2, 0x0B, 0x06, 0x7A, 0x77, 0x76, 0x5C, 0x70, + 0xFF, 0x0F, 0x5C, 0xA0, 0xFF, 0x0F, 0xA9, 0x71, 0x14, 0x00, 0xA9, 0xA1, 0x16, 0x00, 0x18, 0x78, + 0xA8, 0x06, 0xC4, 0x78, 0xD2, 0x04, 0x24, 0x71, 0x99, 0x78, 0xA8, 0x06, 0x18, 0x78, 0xD1, 0x06, + 0xC4, 0x71, 0xD2, 0x04, 0x24, 0x71, 0x99, 0x78, 0xD1, 0x06, 0x30, 0x7E, 0x77, 0x76, 0x5C, 0x70, + 0xFF, 0x0F, 0xA9, 0x78, 0xA4, 0x06, 0x30, 0x7E, 0x5C, 0x70, 0xFF, 0x0F, 0xA9, 0x78, 0xA6, 0x06, + 0x18, 0x70, 0xA6, 0x1B, 0xC4, 0x71, 0x92, 0x25, 0x30, 0x6E, 0x0C, 0x20, 0x14, 0x00, 0x06, 0x76, + 0x77, 0x76, 0x5C, 0x70, 0xFF, 0x0F, 0x5C, 0x60, 0xFF, 0x0F, 0x26, 0x21, 0x06, 0x3C, 0xA9, 0x71, + 0x14, 0x00, 0xA9, 0x61, 0x16, 0x00, 0x0B, 0x3F, 0x04, 0x00, 0x28, 0x61, 0x14, 0x00, 0x30, 0x7E, + 0x38, 0x91, 0x2C, 0x00, 0x5C, 0x60, 0xFF, 0x0F, 0x57, 0x66, 0x56, 0x79, 0x66, 0x76, 0x28, 0x61, + 0x16, 0x00, 0x1C, 0xA0, 0x00, 0x10, 0x5C, 0x60, 0xFF, 0x0F, 0x56, 0x7A, 0x66, 0x76, 0xB1, 0x7E, + 0x38, 0x7D, 0x0C, 0x00, 0x38, 0xB1, 0x34, 0x00, 0xD4, 0x71, 0x10, 0x3B, 0x82, 0x06, 0x0C, 0x50, + 0x1E, 0x00, 0x0C, 0xF0, 0x14, 0x00, 0xF2, 0x04, 0x0C, 0x50, 0x28, 0x00, 0x06, 0xF5, 0x0C, 0x40, + 0x1E, 0x03, 0x26, 0x4D, 0x10, 0x44, 0x06, 0x74, 0x34, 0x71, 0xC4, 0x71, 0xB9, 0x41, 0x3C, 0x00, + 0xDA, 0xEC, 0x00, 0x00, 0x38, 0x91, 0x24, 0x00, 0x38, 0x61, 0x30, 0x00, 0x38, 0xB1, 0x30, 0x00, + 0x38, 0x79, 0x04, 0x00, 0x38, 0x46, 0x04, 0x00, 0xB1, 0x79, 0x04, 0x71, 0x26, 0x7C, 0x57, 0x71, + 0x0C, 0xA0, 0xFC, 0x0A, 0xB1, 0x46, 0x26, 0x7A, 0x38, 0x67, 0x3C, 0x0C, 0xC4, 0x31, 0x06, 0x76, + 0x77, 0x76, 0x5C, 0x70, 0xFF, 0x0F, 0x5C, 0x60, 0xFF, 0x0F, 0xB9, 0x7B, 0x04, 0x00, 0xB9, 0x69, + 0x04, 0x00, 0xCA, 0xFD, 0x00, 0x00, 0x38, 0x21, 0x44, 0x00, 0x38, 0x91, 0x20, 0x00, 0x1C, 0x30, + 0x64, 0x00, 0x26, 0x29, 0x30, 0xA2, 0xC6, 0xA3, 0x92, 0x04, 0x5C, 0x40, 0xFF, 0x0F, 0xF2, 0x04, + 0x0C, 0x40, 0xFF, 0x0F, 0x56, 0x4A, 0xC6, 0x47, 0x02, 0x06, 0x38, 0xB1, 0x1C, 0x00, 0x36, 0x47, + 0xA1, 0x4B, 0xF2, 0x06, 0x38, 0x91, 0x1C, 0x00, 0x3F, 0x44, 0x07, 0x00, 0xA1, 0x49, 0x38, 0xB1, + 0x20, 0x00, 0x38, 0x31, 0x40, 0x00, 0x1C, 0x40, 0x64, 0x00, 0x26, 0x3B, 0x30, 0xB3, 0xC6, 0xB4, + 0x92, 0x07, 0x38, 0x91, 0x24, 0x00, 0x30, 0x49, 0x5C, 0x40, 0xFF, 0x0F, 0xF2, 0x04, 0x0C, 0x40, + 0xFF, 0x0F, 0x56, 0x4B, 0xC6, 0x46, 0x02, 0x03, 0x36, 0x46, 0xF2, 0x03, 0x3F, 0x44, 0x06, 0x00, + 0x38, 0x91, 0x18, 0x00, 0xA1, 0x49, 0x0C, 0x40, 0x60, 0x19, 0x60, 0x44, 0x14, 0x91, 0xC6, 0x49, + 0xB9, 0x41, 0x58, 0x00, 0x82, 0x2B, 0xC6, 0x4C, 0x92, 0x27, 0x36, 0x7A, 0xC4, 0x70, 0x32, 0x02, + 0x16, 0x77, 0xC6, 0x75, 0x12, 0x07, 0x36, 0x6B, 0xC4, 0x60, 0x32, 0x02, 0x16, 0x66, 0xC6, 0x65, + 0x02, 0x18, 0x04, 0x70, 0x1C, 0x60, 0x64, 0x00, 0x0C, 0x50, 0x38, 0x19, 0x26, 0x57, 0xB1, 0x65, + 0x0C, 0x50, 0x10, 0x19, 0x26, 0x57, 0x24, 0x74, 0xCC, 0x70, 0x28, 0x00, 0xB1, 0x65, 0x92, 0xF5, + 0x04, 0x61, 0x99, 0x60, 0x61, 0x19, 0x14, 0x71, 0x99, 0x70, 0x60, 0x19, 0xFA, 0x96, 0x00, 0x00, + 0x0C, 0x60, 0x14, 0x00, 0xF2, 0x02, 0x04, 0x61, 0xF2, 0x4E, 0x38, 0x91, 0x1C, 0x00, 0xF0, 0xB9, + 0x22, 0x09, 0xC6, 0xBF, 0x32, 0x07, 0x38, 0xA1, 0x18, 0x00, 0xF0, 0xBA, 0x22, 0x03, 0xC6, 0xBF, + 0x22, 0x05, 0x04, 0x70, 0x1C, 0x60, 0x64, 0x00, 0xF2, 0x43, 0x38, 0xB1, 0x20, 0x00, 0x38, 0xF1, + 0x48, 0x00, 0x26, 0xFB, 0xB0, 0xBF, 0x92, 0x03, 0xB1, 0x72, 0xB1, 0x63, 0x38, 0x41, 0x3C, 0x00, + 0x24, 0xB1, 0xC4, 0x41, 0xB1, 0xBF, 0x04, 0xFA, 0x92, 0x02, 0x04, 0xF5, 0xC6, 0xBF, 0xC2, 0x6F, + 0x30, 0xF2, 0xC6, 0x7F, 0x02, 0x0B, 0x36, 0x7F, 0xC6, 0x75, 0x32, 0x05, 0x04, 0x71, 0x99, 0x70, + 0xC0, 0x1B, 0xF2, 0x07, 0x99, 0x00, 0xC0, 0x1B, 0xF2, 0x04, 0x3F, 0x77, 0x0F, 0x00, 0xF2, 0xF5, + 0x30, 0x33, 0xC6, 0x63, 0x02, 0x0B, 0x36, 0x63, 0xC6, 0x65, 0x32, 0x05, 0x04, 0x61, 0x99, 0x60, + 0xBF, 0x1B, 0xF2, 0x07, 0x99, 0x00, 0xBF, 0x1B, 0xF2, 0x04, 0x3F, 0x66, 0x03, 0x00, 0xF2, 0xF5, + 0x18, 0x60, 0xC0, 0x1B, 0x18, 0x70, 0xBF, 0x1B, 0xD6, 0x76, 0x82, 0x08, 0x99, 0xC0, 0x60, 0x19, + 0x0C, 0x60, 0x14, 0x00, 0x99, 0x60, 0x61, 0x19, 0xF2, 0x42, 0x04, 0x61, 0xF2, 0xFC, 0x0C, 0x50, + 0x38, 0x19, 0x26, 0x57, 0xB1, 0x65, 0x0C, 0x50, 0x10, 0x19, 0x26, 0x57, 0x24, 0x74, 0xCC, 0x70, + 0x28, 0x00, 0xB1, 0x65, 0x92, 0xF5, 0xF2, 0x2E, 0x04, 0x50, 0x0C, 0x30, 0x28, 0x1B, 0x0C, 0x40, + 0xD8, 0x1A, 0x06, 0x75, 0x14, 0x61, 0x1C, 0x20, 0x64, 0x00, 0x0C, 0xF0, 0x38, 0x19, 0x26, 0xF7, + 0xB1, 0x2F, 0x0C, 0xF0, 0x10, 0x19, 0x26, 0xF7, 0xB1, 0x2F, 0x0C, 0xF0, 0xC4, 0x1A, 0x26, 0xF5, + 0xA1, 0x6F, 0x0C, 0xF0, 0xB0, 0x1A, 0x26, 0xF5, 0xA1, 0x6F, 0x0C, 0xF0, 0x88, 0x1A, 0x26, 0xF7, + 0x24, 0x74, 0xCC, 0x70, 0x28, 0x00, 0xB1, 0x63, 0xB9, 0x63, 0x04, 0x00, 0xB1, 0x64, 0xB9, 0x64, + 0x04, 0x00, 0xB1, 0x0F, 0x24, 0x38, 0x24, 0x48, 0x24, 0x52, 0x92, 0xE0, 0x14, 0x61, 0x99, 0x60, + 0x60, 0x19, 0x04, 0x61, 0x99, 0x60, 0x61, 0x19, 0x99, 0x00, 0xBE, 0x1B, 0x18, 0x20, 0x61, 0x19, + 0xCC, 0x20, 0x14, 0x00, 0x92, 0x04, 0x04, 0x61, 0x99, 0x60, 0xBE, 0x1B, 0x38, 0x61, 0x28, 0x00, + 0x38, 0x71, 0x20, 0x00, 0x0C, 0xB0, 0xFC, 0x0A, 0x2C, 0xB0, 0x7C, 0x0C, 0x26, 0xB6, 0x26, 0xB7, + 0x30, 0x4B, 0x08, 0x70, 0x00, 0xF0, 0xD6, 0x74, 0x82, 0x48, 0x08, 0x70, 0x00, 0x80, 0x18, 0x77, + 0x39, 0xDC, 0x28, 0x31, 0x14, 0x00, 0xD4, 0x71, 0x82, 0x1F, 0x5C, 0x40, 0xFF, 0x0F, 0xAB, 0x9B, + 0x02, 0x00, 0x30, 0x7E, 0x38, 0x91, 0x2C, 0x00, 0x5C, 0x20, 0xFF, 0x0F, 0x57, 0x26, 0x56, 0x79, + 0x66, 0x72, 0xB1, 0x7E, 0x30, 0x4B, 0x18, 0x20, 0x61, 0x19, 0x28, 0x31, 0x16, 0x00, 0x77, 0x46, + 0x5C, 0x40, 0xFF, 0x0F, 0xAB, 0x9B, 0x02, 0x00, 0x30, 0x7E, 0x1C, 0xA0, 0x00, 0x10, 0x5C, 0x20, + 0xFF, 0x0F, 0x56, 0x7A, 0xF2, 0x20, 0x18, 0x28, 0xD0, 0x06, 0x77, 0x46, 0x5C, 0x40, 0xFF, 0x0F, + 0xAB, 0x9B, 0x02, 0x00, 0x30, 0x7E, 0x38, 0x51, 0x2C, 0x00, 0x5C, 0x20, 0xFF, 0x0F, 0x57, 0x26, + 0x56, 0x75, 0x66, 0x72, 0xB1, 0x7E, 0x30, 0x4B, 0x18, 0x28, 0xD0, 0x06, 0x28, 0x31, 0x16, 0x00, + 0x5C, 0x40, 0xFF, 0x0F, 0xAB, 0x9B, 0x02, 0x00, 0x30, 0x7E, 0x1C, 0x60, 0x00, 0x10, 0x5C, 0x20, + 0xFF, 0x0F, 0x56, 0x76, 0x66, 0x72, 0xB1, 0x7E, 0xEB, 0xA2, 0x02, 0x00, 0x38, 0x71, 0x20, 0x00, + 0x38, 0x91, 0x1C, 0x00, 0x38, 0xA1, 0x18, 0x00, 0x38, 0xB1, 0x24, 0x00, 0x38, 0xE1, 0x30, 0x00, + 0x38, 0x51, 0x34, 0x00, 0x24, 0x74, 0x24, 0x92, 0x24, 0xA2, 0x24, 0xB8, 0x24, 0xE8, 0x2C, 0x50, + 0x26, 0x00, 0x24, 0xC1, 0xB9, 0x71, 0x20, 0x00, 0x2C, 0x80, 0x34, 0x00, 0xB9, 0x91, 0x1C, 0x00, + 0xB9, 0xA1, 0x18, 0x00, 0xB9, 0xB1, 0x24, 0x00, 0xB9, 0xE1, 0x30, 0x00, 0xB9, 0x51, 0x34, 0x00, + 0xFA, 0x76, 0xFD, 0xFF, 0x0C, 0x60, 0xFC, 0x0A, 0x18, 0xF6, 0x8C, 0x06, 0xC4, 0xF2, 0xD2, 0x3A, + 0x78, 0x26, 0xE8, 0x00, 0x78, 0x36, 0xEA, 0x00, 0x78, 0x56, 0xEC, 0x00, 0x78, 0x66, 0xEE, 0x00, + 0x04, 0x40, 0x0C, 0x70, 0xFC, 0x0A, 0x06, 0xE4, 0xC6, 0x4F, 0xB2, 0x24, 0x24, 0xE1, 0x06, 0xCE, + 0x57, 0xC1, 0x26, 0xCD, 0x38, 0xCC, 0x3C, 0x0C, 0x77, 0xCE, 0xC4, 0xC0, 0x82, 0x17, 0xC4, 0xF1, + 0x92, 0x08, 0x78, 0x67, 0xA6, 0x06, 0x78, 0x57, 0xA4, 0x06, 0x06, 0x36, 0x06, 0x25, 0xF2, 0x0C, + 0xC4, 0x40, 0x92, 0x06, 0x78, 0x37, 0xA6, 0x06, 0x78, 0x27, 0xA4, 0x06, 0xF2, 0x05, 0x78, 0x67, + 0xA6, 0x06, 0x78, 0x57, 0xA4, 0x06, 0x24, 0x41, 0x13, 0x44, 0xC4, 0xED, 0x2C, 0x70, 0x34, 0x00, + 0x92, 0xDC, 0xA9, 0x2D, 0xE8, 0x00, 0xA9, 0x3D, 0xEA, 0x00, 0xA9, 0x5D, 0xEC, 0x00, 0xA9, 0x6D, + 0xEE, 0x00, 0x58, 0xC1, 0x6C, 0x00, 0x58, 0x81, 0x5C, 0x00, 0x2C, 0x10, 0x7C, 0x00, 0xE1, 0xF0, + 0xA9, 0x00, 0x0E, 0x0B, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0xC0, 0x06, 0xD9, 0xC1, 0xB0, 0x06, + 0x0C, 0x60, 0xFC, 0x0A, 0xD9, 0x81, 0xA0, 0x06, 0x38, 0x76, 0x0C, 0x00, 0x08, 0x50, 0x02, 0x00, + 0xD6, 0x57, 0x06, 0xD6, 0x82, 0x05, 0x1C, 0x30, 0x01, 0x01, 0x56, 0x73, 0xF2, 0x08, 0x18, 0x56, + 0x1F, 0x03, 0xC4, 0x51, 0xD2, 0x08, 0x1C, 0x40, 0x01, 0x01, 0x56, 0x74, 0xB9, 0x76, 0x0C, 0x00, + 0xFA, 0xFB, 0x00, 0x00, 0xDC, 0x70, 0x00, 0x01, 0x08, 0x60, 0x00, 0x80, 0x2C, 0x60, 0x0C, 0xDC, + 0x82, 0x0B, 0x28, 0x56, 0x82, 0x00, 0x28, 0x76, 0x7E, 0x00, 0x28, 0xE6, 0x80, 0x00, 0x2F, 0x25, + 0x07, 0x00, 0x26, 0xE5, 0xF2, 0x05, 0x28, 0x26, 0x7E, 0x00, 0x28, 0xE6, 0x80, 0x00, 0x98, 0x60, + 0xBE, 0x1B, 0x82, 0x02, 0x26, 0x22, 0x06, 0x32, 0x4B, 0x14, 0x00, 0x00, 0x06, 0x3E, 0x06, 0x92, + 0x06, 0x2E, 0x4B, 0x14, 0x00, 0x00, 0x26, 0x92, 0x0C, 0x30, 0x48, 0x05, 0x0C, 0x20, 0xE4, 0x05, + 0x26, 0x21, 0x26, 0x31, 0xAB, 0x0E, 0x02, 0x00, 0x06, 0xAD, 0x04, 0xE0, 0x18, 0x7D, 0x1F, 0x03, + 0xC6, 0x7E, 0xC2, 0x1F, 0x06, 0xCE, 0x2F, 0xBE, 0x0E, 0x00, 0xD7, 0xC2, 0x26, 0xBE, 0x26, 0xCA, + 0x0C, 0x20, 0xE4, 0x05, 0x2C, 0xC0, 0x70, 0x01, 0x57, 0xB1, 0x26, 0x21, 0x06, 0x3E, 0x26, 0x2B, + 0x04, 0x40, 0x06, 0x5C, 0x6B, 0x0F, 0x02, 0x00, 0x0C, 0x20, 0x48, 0x05, 0x26, 0x21, 0x06, 0x3E, + 0x26, 0x2B, 0x04, 0x40, 0x06, 0x5C, 0x6B, 0x0F, 0x02, 0x00, 0x24, 0xE1, 0x13, 0xEE, 0xF2, 0xDF, + 0x06, 0x29, 0x04, 0x30, 0x04, 0x41, 0xEB, 0x10, 0x02, 0x00, 0x0C, 0x30, 0xE4, 0x05, 0x0C, 0x40, + 0x48, 0x05, 0x06, 0x21, 0x26, 0x31, 0x26, 0x41, 0x6B, 0x11, 0x02, 0x00, 0x86, 0x22, 0xB9, 0x21, + 0x88, 0x06, 0x82, 0x07, 0x04, 0xA4, 0x04, 0x60, 0x26, 0xA1, 0xB9, 0x61, 0x80, 0x06, 0xF2, 0x0A, + 0x38, 0x7A, 0x0C, 0x00, 0x1C, 0xF0, 0x01, 0x01, 0x56, 0x7F, 0xB9, 0x7A, 0x0C, 0x00, 0xFA, 0x8C, + 0x00, 0x00, 0x10, 0x5A, 0x0C, 0xC0, 0x5C, 0x01, 0x06, 0x75, 0xD7, 0x72, 0x26, 0x7D, 0x26, 0xC7, + 0xB9, 0x51, 0x84, 0x06, 0x38, 0x67, 0x60, 0x01, 0x38, 0x97, 0x64, 0x01, 0x38, 0x57, 0x68, 0x01, + 0x38, 0x8C, 0x10, 0x00, 0x06, 0xE1, 0x04, 0xB0, 0x18, 0x7E, 0x04, 0x00, 0x38, 0xF1, 0x84, 0x06, + 0xC6, 0x7F, 0x92, 0x45, 0xB0, 0x7E, 0x82, 0x43, 0x18, 0x7E, 0x05, 0x00, 0x0C, 0x20, 0x5C, 0x01, + 0xD7, 0x72, 0x26, 0x7D, 0x38, 0x47, 0x60, 0x01, 0x26, 0x27, 0x26, 0x64, 0x38, 0x47, 0x64, 0x01, + 0x26, 0x94, 0x38, 0x47, 0x68, 0x01, 0x0C, 0x30, 0x28, 0x08, 0x26, 0x54, 0x38, 0x42, 0x10, 0x00, + 0x26, 0x84, 0x20, 0x42, 0x06, 0xF4, 0x26, 0xF4, 0x26, 0x3F, 0xB9, 0x31, 0x94, 0x06, 0x20, 0x3C, + 0xB9, 0x41, 0x9C, 0x06, 0x26, 0x33, 0x0C, 0x40, 0x28, 0x08, 0x26, 0x43, 0xB9, 0x41, 0x98, 0x06, + 0x38, 0xF1, 0x98, 0x06, 0x38, 0x41, 0x94, 0x06, 0x70, 0x3F, 0x70, 0x44, 0xC6, 0x43, 0x02, 0x08, + 0x28, 0x77, 0x5E, 0x01, 0x38, 0x31, 0x9C, 0x06, 0xA9, 0x7C, 0x02, 0x00, 0xA1, 0x3C, 0x04, 0x30, + 0x0C, 0x40, 0x20, 0x00, 0xB9, 0x51, 0x8C, 0x06, 0xB9, 0x61, 0x90, 0x06, 0x0C, 0xF0, 0xB0, 0x01, + 0xF1, 0xF0, 0xB1, 0x0E, 0x38, 0x61, 0x90, 0x06, 0x38, 0x51, 0x8C, 0x06, 0x38, 0x71, 0x88, 0x06, + 0x24, 0xB1, 0x13, 0xBB, 0xC6, 0xB7, 0x24, 0xE8, 0x92, 0xB0, 0x06, 0x36, 0x06, 0x25, 0x8B, 0x16, + 0x00, 0x00, 0x04, 0x3A, 0x43, 0x22, 0x8B, 0x16, 0x00, 0x00, 0xA9, 0x2C, 0x14, 0x00, 0x06, 0x39, + 0x06, 0x28, 0x8B, 0x16, 0x00, 0x00, 0x43, 0x22, 0x04, 0x3A, 0x8B, 0x16, 0x00, 0x00, 0x38, 0x71, + 0x80, 0x06, 0xA9, 0x2C, 0x16, 0x00, 0x24, 0xA8, 0x24, 0x71, 0x13, 0x77, 0xC6, 0x7B, 0xB9, 0x71, + 0x80, 0x06, 0x9A, 0x80, 0xFF, 0xFF, 0x38, 0x7D, 0x0C, 0x00, 0x6C, 0x70, 0x00, 0x01, 0xB9, 0x7D, + 0x0C, 0x00, 0x2B, 0x8A, 0x03, 0x00, 0x58, 0xC1, 0xB0, 0x06, 0x58, 0x81, 0xA0, 0x06, 0x2C, 0x10, + 0xC0, 0x06, 0xE1, 0xF0, 0x3C, 0x10, 0x18, 0x00, 0xD9, 0xC1, 0x08, 0x00, 0x0C, 0xD0, 0xFC, 0x0A, + 0xC1, 0xA1, 0x18, 0x7D, 0x8C, 0x06, 0x06, 0xED, 0xC4, 0x72, 0x92, 0x05, 0x18, 0x7D, 0x8F, 0x06, + 0xC4, 0x72, 0x82, 0x3D, 0x14, 0x71, 0xB9, 0x7E, 0x34, 0x0C, 0x08, 0x70, 0x00, 0x80, 0x2C, 0x70, + 0x0C, 0xDC, 0x28, 0x67, 0x82, 0x00, 0x28, 0xC7, 0x7E, 0x00, 0x28, 0xD7, 0x80, 0x00, 0xA9, 0x0E, + 0x38, 0x0C, 0x26, 0xC6, 0x0C, 0x20, 0x14, 0x00, 0x26, 0x2C, 0x26, 0xD6, 0x06, 0x32, 0x0C, 0xA0, + 0x14, 0x00, 0x4B, 0x14, 0x00, 0x00, 0x26, 0xAD, 0x06, 0xB2, 0x06, 0x3A, 0x06, 0x2A, 0x4B, 0x14, + 0x00, 0x00, 0x26, 0x2B, 0xB9, 0x2E, 0x2C, 0x0C, 0x0C, 0x20, 0x78, 0x00, 0x26, 0x2C, 0x06, 0x32, + 0x4B, 0x14, 0x00, 0x00, 0x2C, 0xD0, 0x78, 0x00, 0x06, 0xC2, 0x06, 0x3D, 0x06, 0x2D, 0x4B, 0x14, + 0x00, 0x00, 0x38, 0x7E, 0x0C, 0x00, 0x08, 0x60, 0xFD, 0xFF, 0x2C, 0x60, 0xFF, 0xFF, 0x26, 0x2C, + 0x56, 0x76, 0xB9, 0x2E, 0x30, 0x0C, 0xB9, 0x7E, 0x0C, 0x00, 0xF2, 0x4E, 0x38, 0xCD, 0x0C, 0x00, + 0x08, 0x70, 0x02, 0x00, 0xD6, 0x7C, 0x92, 0x48, 0x98, 0x7D, 0xB6, 0x04, 0x82, 0x45, 0x98, 0x7D, + 0xDC, 0x04, 0x82, 0x42, 0x78, 0x7D, 0xBE, 0x04, 0x78, 0x2D, 0x98, 0x04, 0x78, 0xAD, 0x9A, 0x04, + 0x36, 0x27, 0x78, 0x7D, 0xC0, 0x04, 0x06, 0x32, 0x36, 0xA7, 0x4B, 0x14, 0x00, 0x00, 0x06, 0xB2, + 0x06, 0x3A, 0x06, 0x2A, 0x4B, 0x14, 0x00, 0x00, 0xF8, 0x7D, 0x38, 0x0C, 0x26, 0x2B, 0x02, 0x22, + 0x38, 0x6D, 0x34, 0x0C, 0xC6, 0x62, 0xC2, 0x13, 0xCC, 0x70, 0x13, 0x00, 0x12, 0x04, 0x24, 0x71, + 0xA9, 0x7D, 0x38, 0x0C, 0x38, 0x7E, 0x2C, 0x0C, 0xC6, 0x72, 0xC2, 0x06, 0x08, 0x70, 0x02, 0x00, + 0x66, 0x7C, 0xB9, 0x7E, 0x0C, 0x00, 0xB9, 0x2E, 0x34, 0x0C, 0xF2, 0x16, 0x34, 0x71, 0xC3, 0x77, + 0xA9, 0x7D, 0x38, 0x0C, 0x92, 0x11, 0x14, 0x71, 0xB9, 0x7D, 0x34, 0x0C, 0xA9, 0x0D, 0x38, 0x0C, + 0xF2, 0x0B, 0x38, 0x7D, 0x30, 0x0C, 0xC6, 0x72, 0xB2, 0x07, 0x04, 0x73, 0xA9, 0x7D, 0x38, 0x0C, + 0x14, 0x71, 0xB9, 0x7D, 0x34, 0x0C, 0x58, 0xC1, 0x08, 0x00, 0x40, 0xA1, 0x2C, 0x10, 0x18, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x18, 0xC1, 0xE1, 0x0C, 0x60, 0xFC, 0x0A, 0x38, 0x56, 0x0C, 0x00, + 0x0C, 0x20, 0x50, 0x01, 0x54, 0x51, 0x26, 0x26, 0x06, 0x76, 0x0C, 0xF0, 0x32, 0x00, 0x0C, 0xE0, + 0x3C, 0x00, 0x04, 0x40, 0xC4, 0x50, 0x2F, 0x34, 0x06, 0x00, 0x82, 0x04, 0x99, 0xE3, 0x28, 0x03, + 0xF2, 0x03, 0x99, 0xF3, 0x28, 0x03, 0x24, 0x41, 0xCC, 0x40, 0x17, 0x00, 0x92, 0xF4, 0x2C, 0x60, + 0x18, 0x00, 0xC6, 0x62, 0x92, 0xEF, 0xC4, 0x50, 0x0C, 0x60, 0x32, 0x00, 0x99, 0x67, 0x91, 0x04, + 0x0C, 0x60, 0x1E, 0x00, 0x92, 0x03, 0x0C, 0x60, 0x14, 0x00, 0x99, 0x67, 0x92, 0x04, 0x04, 0x62, + 0x99, 0x67, 0x93, 0x04, 0x04, 0x65, 0x99, 0x67, 0x94, 0x04, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, + 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0x0C, 0xE0, 0xFC, 0x0A, 0x2F, 0xDE, 0x04, 0x00, + 0x26, 0x44, 0xD1, 0x81, 0x2F, 0xC4, 0x05, 0x00, 0xF0, 0x7C, 0x06, 0x92, 0x06, 0xA3, 0x92, 0x05, + 0x18, 0x7E, 0x91, 0x04, 0x99, 0x7D, 0x28, 0x03, 0x28, 0x7E, 0x14, 0x00, 0x68, 0xBD, 0x28, 0x03, + 0x28, 0x2E, 0x14, 0x03, 0x06, 0x3B, 0x26, 0x27, 0x4B, 0x14, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, + 0x8B, 0x16, 0x00, 0x00, 0x70, 0x7C, 0x0C, 0x60, 0xFF, 0xFF, 0x56, 0x62, 0xC6, 0x76, 0x23, 0x52, + 0x22, 0x13, 0x38, 0x7E, 0x0C, 0x00, 0xDC, 0x70, 0x00, 0x02, 0x18, 0x7E, 0x94, 0x04, 0x36, 0xB7, + 0x82, 0x02, 0x34, 0xB3, 0x99, 0xBD, 0x28, 0x03, 0x18, 0x7E, 0x92, 0x04, 0x68, 0x6D, 0x28, 0x03, + 0xC6, 0x67, 0x32, 0x32, 0xF2, 0x2F, 0x18, 0x7E, 0x92, 0x04, 0xC6, 0xB7, 0x92, 0x21, 0xC4, 0x90, + 0x02, 0x0A, 0x14, 0x72, 0x26, 0x7C, 0x70, 0x47, 0x04, 0x20, 0xC6, 0x46, 0x12, 0x26, 0xCC, 0x90, + 0x15, 0x00, 0x12, 0x06, 0x78, 0x4C, 0x02, 0x00, 0x04, 0x20, 0xC6, 0x46, 0x12, 0x1E, 0xC4, 0xA0, + 0x02, 0x0A, 0x1C, 0x70, 0x30, 0x00, 0x26, 0x7C, 0x70, 0x47, 0x04, 0x20, 0xC6, 0x46, 0x12, 0x15, + 0xC4, 0xAC, 0x12, 0x06, 0x78, 0x4C, 0x30, 0x00, 0x04, 0x20, 0xC6, 0x46, 0x12, 0x0E, 0x18, 0x7E, + 0x93, 0x04, 0x26, 0xB7, 0x33, 0xBB, 0x99, 0xBD, 0x28, 0x03, 0x18, 0x7E, 0x91, 0x04, 0xC6, 0xB7, + 0x02, 0x03, 0x99, 0x7D, 0x28, 0x03, 0x06, 0x25, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, + 0x20, 0x00, 0xE1, 0xF0, 0x38, 0x70, 0x70, 0x1A, 0x3C, 0x10, 0x34, 0x02, 0x0C, 0x60, 0x7A, 0x00, + 0xD9, 0xC1, 0x24, 0x02, 0xD9, 0x81, 0x14, 0x02, 0x26, 0x67, 0x10, 0x66, 0x18, 0xE7, 0x79, 0x00, + 0x18, 0x77, 0x7C, 0x00, 0xB9, 0x61, 0xDC, 0x01, 0x0C, 0xD0, 0xFC, 0x0A, 0x38, 0x6D, 0x0C, 0x00, + 0x04, 0x51, 0xD6, 0x56, 0x28, 0x5D, 0x18, 0x03, 0x82, 0x0B, 0xCC, 0x50, 0xF3, 0x01, 0xD2, 0x11, + 0x04, 0xF6, 0x04, 0x71, 0xB9, 0xF1, 0xDC, 0x01, 0x0C, 0xE0, 0x28, 0x00, 0xF2, 0x0A, 0xCC, 0x50, + 0xC1, 0x01, 0xD2, 0x07, 0x04, 0x23, 0x04, 0x71, 0xB9, 0x21, 0xDC, 0x01, 0x0C, 0xE0, 0x14, 0x00, + 0x98, 0x5D, 0x1F, 0x03, 0x92, 0x0C, 0xAB, 0xFB, 0x02, 0x00, 0x38, 0x7D, 0x0C, 0x00, 0x1C, 0x30, + 0x01, 0x02, 0x56, 0x73, 0xB9, 0x7D, 0x0C, 0x00, 0xFA, 0xBF, 0x02, 0x00, 0x0C, 0x40, 0x00, 0x02, + 0xD6, 0x46, 0x82, 0x0B, 0x38, 0x41, 0xDC, 0x01, 0xC6, 0x47, 0xC2, 0x04, 0x36, 0x47, 0x13, 0x74, + 0xF2, 0x02, 0x04, 0x71, 0xB9, 0x71, 0xDC, 0x01, 0xC4, 0x51, 0x92, 0x0E, 0x18, 0x7D, 0x25, 0x03, + 0x38, 0xF1, 0xDC, 0x01, 0xC6, 0x7F, 0xB2, 0x08, 0x1C, 0x20, 0x01, 0x02, 0x56, 0x62, 0xB9, 0x6D, + 0x0C, 0x00, 0xFA, 0xA2, 0x02, 0x00, 0x38, 0x30, 0x80, 0x1A, 0x0C, 0x60, 0x20, 0x01, 0x26, 0x61, + 0x06, 0x26, 0xB9, 0x31, 0xEC, 0x01, 0x0C, 0x40, 0xB5, 0x00, 0x04, 0x30, 0xB9, 0x61, 0xD8, 0x01, + 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x0C, 0x40, 0x20, 0x01, 0x06, 0x21, 0x04, 0x30, 0x0C, 0xF0, + 0xB0, 0x01, 0xF1, 0xF0, 0x28, 0x7D, 0x14, 0x00, 0x28, 0x2D, 0x14, 0x03, 0x06, 0x3E, 0x26, 0x27, + 0x4B, 0x14, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x0C, 0x70, 0x74, 0x0B, + 0xB9, 0x71, 0x00, 0x02, 0x04, 0x70, 0xB9, 0x71, 0xE8, 0x01, 0xB9, 0x71, 0xE4, 0x01, 0x04, 0x71, + 0x23, 0x52, 0xB9, 0x71, 0xE0, 0x01, 0x04, 0xC0, 0x18, 0x7D, 0x8F, 0x06, 0x38, 0xA1, 0xE8, 0x01, + 0xC4, 0x71, 0x26, 0xAC, 0x23, 0xAA, 0xC2, 0x0B, 0x38, 0x61, 0xE4, 0x01, 0x38, 0x51, 0xEC, 0x01, + 0x43, 0x2C, 0x43, 0x36, 0x43, 0x4A, 0x0B, 0xFF, 0x02, 0x00, 0x06, 0x52, 0x38, 0x61, 0xEC, 0x01, + 0xB9, 0xA1, 0xF0, 0x01, 0x2F, 0x7A, 0x0A, 0x00, 0x26, 0x76, 0x70, 0x77, 0xC6, 0x75, 0x2A, 0x5B, + 0x01, 0x00, 0x04, 0x71, 0x26, 0x7C, 0x38, 0xE1, 0xE0, 0x01, 0x04, 0x80, 0x23, 0x77, 0xB9, 0x81, + 0xF4, 0x01, 0xB9, 0x81, 0xF8, 0x01, 0xB9, 0x81, 0xFC, 0x01, 0x06, 0x98, 0xB9, 0x71, 0x04, 0x02, + 0x18, 0x4D, 0x8F, 0x06, 0x23, 0xB8, 0xC4, 0x41, 0x2F, 0x6A, 0x0B, 0x00, 0x2F, 0x7C, 0x0B, 0x00, + 0x23, 0x66, 0x23, 0x77, 0xC2, 0x13, 0x38, 0xF1, 0xE4, 0x01, 0x38, 0x51, 0xEC, 0x01, 0xB9, 0x61, + 0x10, 0x02, 0x43, 0x27, 0x43, 0x46, 0x43, 0x3F, 0xB9, 0x71, 0x08, 0x02, 0x0B, 0xFF, 0x02, 0x00, + 0x38, 0x71, 0x08, 0x02, 0x38, 0x61, 0x10, 0x02, 0x06, 0x52, 0x38, 0x21, 0xEC, 0x01, 0x26, 0x66, + 0x26, 0x62, 0x70, 0x36, 0xC6, 0x35, 0x2A, 0xC1, 0x00, 0x00, 0x38, 0x4D, 0x0C, 0x00, 0x0C, 0x60, + 0x64, 0x00, 0xDC, 0x40, 0x00, 0x02, 0x92, 0x02, 0x23, 0x63, 0x04, 0x46, 0x26, 0x47, 0x57, 0x41, + 0x26, 0x4D, 0x30, 0x34, 0xB9, 0x51, 0x0C, 0x02, 0x06, 0x26, 0xB9, 0x71, 0x08, 0x02, 0xB9, 0x61, + 0x10, 0x02, 0x4B, 0x14, 0x00, 0x00, 0x38, 0x31, 0xF4, 0x01, 0x38, 0x41, 0x00, 0x02, 0x38, 0x61, + 0x10, 0x02, 0x26, 0x32, 0xB9, 0x31, 0xF4, 0x01, 0x30, 0x34, 0x06, 0x26, 0x4B, 0x14, 0x00, 0x00, + 0x38, 0xF1, 0xF8, 0x01, 0x38, 0x61, 0x10, 0x02, 0x38, 0x51, 0x0C, 0x02, 0x38, 0x71, 0x08, 0x02, + 0x26, 0xF2, 0x38, 0x21, 0xFC, 0x01, 0xB9, 0xF1, 0xF8, 0x01, 0x04, 0x31, 0x26, 0x26, 0xB8, 0x61, + 0xE4, 0x01, 0xB9, 0x21, 0xFC, 0x01, 0x26, 0x3B, 0x23, 0x33, 0x82, 0x7A, 0x1C, 0x60, 0x18, 0x00, + 0xC4, 0x90, 0x26, 0x6A, 0x26, 0x6B, 0x23, 0x66, 0x92, 0x2F, 0x06, 0x46, 0x0C, 0xF0, 0x20, 0x01, + 0xF7, 0x40, 0x26, 0xF1, 0x26, 0x4F, 0x10, 0x44, 0x04, 0x21, 0x56, 0x26, 0x57, 0x21, 0x63, 0x42, + 0xD4, 0x4F, 0x82, 0x03, 0x13, 0xE4, 0xF2, 0x63, 0xC4, 0x70, 0x82, 0x0F, 0x14, 0x41, 0x26, 0x46, + 0x06, 0x74, 0x0C, 0x20, 0x20, 0x01, 0xE7, 0x70, 0x26, 0x21, 0x26, 0x72, 0x10, 0x77, 0x54, 0x41, + 0x57, 0x41, 0x63, 0x74, 0xD4, 0x7F, 0x92, 0x0E, 0x24, 0x61, 0x06, 0x76, 0x0C, 0x40, 0x20, 0x01, + 0xE7, 0x70, 0x26, 0x41, 0x26, 0x74, 0x10, 0x77, 0x54, 0x61, 0x57, 0x61, 0x63, 0x76, 0xD4, 0x7F, + 0x82, 0x47, 0x13, 0xE7, 0xF2, 0x44, 0x04, 0x21, 0x26, 0x26, 0x06, 0x42, 0x0C, 0xF0, 0x20, 0x01, + 0xE7, 0x40, 0x26, 0xF1, 0x26, 0x4F, 0x10, 0x44, 0x54, 0x21, 0x57, 0x21, 0x63, 0x42, 0xD4, 0x4F, + 0x82, 0x03, 0xC6, 0x4E, 0x92, 0x10, 0x06, 0x46, 0x0C, 0x20, 0x20, 0x01, 0x26, 0x21, 0xF7, 0x40, + 0x26, 0x42, 0x10, 0x44, 0x04, 0x21, 0x56, 0x26, 0x57, 0x21, 0x63, 0x42, 0xD4, 0x4F, 0x82, 0x05, + 0xC6, 0x4E, 0x82, 0x03, 0x13, 0x44, 0xF2, 0x14, 0xC4, 0x70, 0x82, 0x21, 0x34, 0x61, 0x06, 0x76, + 0x0C, 0x40, 0x20, 0x01, 0xE7, 0x70, 0x26, 0x41, 0x26, 0x74, 0x10, 0x77, 0x54, 0x61, 0x57, 0x61, + 0x63, 0x76, 0xD4, 0x7F, 0x04, 0x91, 0x82, 0x14, 0xC6, 0x7E, 0x82, 0x12, 0x13, 0x47, 0xC6, 0x4E, + 0x06, 0x64, 0xC2, 0x02, 0x06, 0x6E, 0x34, 0x41, 0x14, 0x71, 0x57, 0x42, 0x26, 0x7E, 0x26, 0x41, + 0x57, 0x72, 0x99, 0x64, 0x0E, 0x00, 0x26, 0x71, 0x99, 0x67, 0x0E, 0x00, 0x04, 0x91, 0x38, 0x61, + 0x04, 0x02, 0x24, 0x81, 0x26, 0xB6, 0x2F, 0x68, 0x0C, 0x00, 0x23, 0x66, 0xCC, 0x60, 0x16, 0x00, + 0x23, 0x7B, 0xCA, 0x1F, 0xFF, 0xFF, 0x06, 0xB3, 0xC4, 0x90, 0x06, 0xC7, 0x92, 0x07, 0x38, 0x71, + 0xE0, 0x01, 0x24, 0x71, 0x13, 0x77, 0xB9, 0x71, 0xE0, 0x01, 0x04, 0x71, 0xD6, 0x7A, 0x06, 0x3E, + 0x57, 0x32, 0x82, 0x11, 0x06, 0x7A, 0x0C, 0xF0, 0x20, 0x01, 0xF7, 0x70, 0x26, 0xF1, 0x26, 0x7F, + 0x10, 0x67, 0x24, 0xA1, 0xB9, 0xA1, 0xF0, 0x01, 0x14, 0xA1, 0x66, 0x63, 0x26, 0xAB, 0x91, 0x67, + 0x23, 0xAA, 0xF2, 0x02, 0x06, 0xAB, 0x38, 0x21, 0xF0, 0x01, 0xB9, 0x51, 0x0C, 0x02, 0x0C, 0x40, + 0x20, 0x01, 0x26, 0x41, 0xF7, 0x20, 0x26, 0x24, 0x06, 0x4A, 0x66, 0x3E, 0xF7, 0x40, 0x33, 0x33, + 0x23, 0x44, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x04, 0x71, 0xD6, 0x7A, 0x38, 0x51, 0x0C, 0x02, + 0x82, 0x12, 0x38, 0x71, 0xF0, 0x01, 0x34, 0x71, 0x26, 0xA7, 0x06, 0x6A, 0x0C, 0x70, 0x20, 0x01, + 0x26, 0x71, 0xF7, 0x60, 0x26, 0x67, 0x10, 0x46, 0x54, 0xA1, 0x57, 0xA1, 0x06, 0x7E, 0x53, 0x7A, + 0x66, 0x74, 0x91, 0x76, 0x34, 0xE1, 0x57, 0xE2, 0x26, 0xE1, 0x30, 0x7E, 0x38, 0x61, 0xF4, 0x01, + 0x26, 0x76, 0xB1, 0x7E, 0x38, 0x61, 0xF8, 0x01, 0x38, 0x7E, 0x04, 0x00, 0x26, 0x76, 0xB9, 0x7E, + 0x04, 0x00, 0x38, 0x61, 0xFC, 0x01, 0x38, 0x7E, 0x08, 0x00, 0x26, 0x76, 0xB9, 0x7E, 0x08, 0x00, + 0x28, 0x7E, 0x0C, 0x00, 0x26, 0xB7, 0x38, 0x71, 0xE0, 0x01, 0xA9, 0xBE, 0x0C, 0x00, 0xCC, 0x70, + 0x10, 0x00, 0xD2, 0x1F, 0x24, 0xC1, 0x23, 0xCC, 0xCC, 0xC0, 0x16, 0x00, 0xCA, 0x86, 0xFE, 0xFF, + 0x38, 0x71, 0xE4, 0x01, 0x38, 0x61, 0x00, 0x02, 0x24, 0x71, 0x23, 0x77, 0xB9, 0x71, 0xE4, 0x01, + 0x38, 0x71, 0xE8, 0x01, 0x24, 0x64, 0x2C, 0x70, 0x18, 0x00, 0x23, 0x77, 0xB9, 0x71, 0xE8, 0x01, + 0x38, 0x71, 0xE4, 0x01, 0xB9, 0x61, 0x00, 0x02, 0xC4, 0x7E, 0x9A, 0x6E, 0xFE, 0xFF, 0xF2, 0x05, + 0x0C, 0x60, 0x11, 0x00, 0xB9, 0x61, 0xE0, 0x01, 0x06, 0xE1, 0x04, 0x60, 0x38, 0x21, 0xE0, 0x01, + 0x13, 0x76, 0xC6, 0x72, 0xB2, 0x36, 0x18, 0x3E, 0x0E, 0x00, 0x14, 0x71, 0x26, 0x73, 0xC6, 0x67, + 0x0C, 0x40, 0x10, 0x00, 0x06, 0x56, 0x26, 0x4E, 0x92, 0x29, 0x06, 0x74, 0x38, 0xF1, 0xE0, 0x01, + 0x24, 0x51, 0xC6, 0x5F, 0x32, 0x23, 0x68, 0x27, 0x0E, 0x00, 0xC6, 0x32, 0x92, 0x1C, 0x28, 0xF7, + 0x0C, 0x00, 0x28, 0x2E, 0x0C, 0x00, 0x26, 0x2F, 0xA9, 0x2E, 0x0C, 0x00, 0x30, 0xFE, 0x30, 0x27, + 0x26, 0x2F, 0xB1, 0x2E, 0x38, 0xFE, 0x04, 0x00, 0x38, 0x27, 0x04, 0x00, 0x26, 0x2F, 0xB9, 0x2E, + 0x04, 0x00, 0x38, 0xFE, 0x08, 0x00, 0x38, 0x27, 0x08, 0x00, 0x26, 0x2F, 0xB9, 0x2E, 0x08, 0x00, + 0xA9, 0x07, 0x0C, 0x00, 0x2C, 0x70, 0x10, 0x00, 0xF2, 0xDA, 0x24, 0x61, 0x06, 0xE4, 0xF2, 0xC7, + 0x04, 0x90, 0x06, 0xB9, 0x06, 0xCD, 0x04, 0x61, 0x0C, 0x80, 0x28, 0x08, 0x18, 0x7D, 0x1F, 0x03, + 0xC6, 0x7B, 0xC2, 0x7A, 0x06, 0x4B, 0xD7, 0x42, 0x26, 0x4C, 0x28, 0x74, 0x5C, 0x01, 0x0C, 0x30, + 0x20, 0x01, 0x06, 0x57, 0xF7, 0x50, 0x26, 0x31, 0x26, 0x53, 0x10, 0xE5, 0x04, 0x51, 0x56, 0x57, + 0x57, 0x51, 0x63, 0xE5, 0xD4, 0xEF, 0x0C, 0xA0, 0x5C, 0x01, 0x26, 0xA4, 0x82, 0x5A, 0x34, 0xE1, + 0x57, 0xE2, 0x26, 0xE1, 0xE8, 0x5E, 0x0E, 0x00, 0x82, 0x05, 0x14, 0xE1, 0x26, 0xE5, 0x57, 0xE2, + 0x26, 0xE1, 0xA8, 0x5E, 0x0C, 0x00, 0x92, 0x1A, 0x18, 0x5E, 0x0F, 0x00, 0x2F, 0x27, 0x07, 0x00, + 0xD7, 0x52, 0x26, 0x5D, 0x28, 0x35, 0x5C, 0x01, 0x26, 0x28, 0x26, 0x33, 0x26, 0x38, 0x70, 0x22, + 0x70, 0x33, 0xC6, 0x23, 0x02, 0x07, 0x28, 0x44, 0x5E, 0x01, 0xA9, 0x75, 0x5C, 0x01, 0xA9, 0x45, + 0x5E, 0x01, 0xA9, 0x0A, 0x1C, 0x00, 0x24, 0x91, 0xF2, 0x34, 0x38, 0x71, 0xDC, 0x01, 0xA9, 0x5A, + 0x1C, 0x00, 0xC6, 0x57, 0xA2, 0x2E, 0xB8, 0x7E, 0x08, 0x00, 0x92, 0x03, 0xB9, 0x6E, 0x08, 0x00, + 0x38, 0x7E, 0x08, 0x00, 0x38, 0x2E, 0x04, 0x00, 0xB9, 0x61, 0x10, 0x02, 0x06, 0x37, 0xB9, 0x71, + 0x08, 0x02, 0xAB, 0x15, 0x00, 0x00, 0x38, 0x71, 0x08, 0x02, 0x43, 0x52, 0x30, 0x2E, 0xB9, 0x51, + 0x0C, 0x02, 0x06, 0x37, 0xAB, 0x15, 0x00, 0x00, 0x04, 0x3A, 0x43, 0x22, 0x8B, 0x16, 0x00, 0x00, + 0x38, 0x51, 0x0C, 0x02, 0xA9, 0x2A, 0x14, 0x00, 0x04, 0x3A, 0x06, 0x25, 0x8B, 0x16, 0x00, 0x00, + 0x99, 0xBE, 0x0F, 0x00, 0x38, 0x61, 0x10, 0x02, 0xA9, 0x2A, 0x16, 0x00, 0xA9, 0x0E, 0x0C, 0x00, + 0x28, 0x7A, 0x1C, 0x00, 0x28, 0x5D, 0x12, 0x00, 0xC6, 0x57, 0xB2, 0x03, 0xA9, 0x7C, 0x12, 0x00, + 0x24, 0xB1, 0x13, 0xBB, 0xF2, 0x84, 0x38, 0x7C, 0x0C, 0x00, 0x08, 0x60, 0x02, 0x00, 0xD6, 0x67, + 0x82, 0x07, 0x1C, 0xF0, 0x01, 0x02, 0x56, 0x7F, 0xB9, 0x7C, 0x0C, 0x00, 0xF2, 0x0D, 0xC4, 0x90, + 0x82, 0x04, 0x6C, 0x70, 0x00, 0x02, 0xF2, 0x04, 0x1C, 0x20, 0x01, 0x02, 0x56, 0x72, 0xB9, 0x7C, + 0x0C, 0x00, 0x2B, 0x8A, 0x03, 0x00, 0x58, 0xC1, 0x24, 0x02, 0x58, 0x81, 0x14, 0x02, 0x2C, 0x10, + 0x34, 0x02, 0xE1, 0xF0, 0x0C, 0x70, 0xFC, 0x0A, 0x14, 0x61, 0x99, 0x07, 0x1C, 0x03, 0x99, 0x07, + 0x1F, 0x03, 0x99, 0x07, 0x24, 0x03, 0x99, 0x67, 0x22, 0x03, 0x99, 0x07, 0x23, 0x03, 0xE1, 0xF0, + 0x34, 0x18, 0xC1, 0xE1, 0x0C, 0xE0, 0xFC, 0x0A, 0x18, 0x7E, 0xDF, 0x00, 0x04, 0x4D, 0x06, 0x27, + 0xD7, 0x22, 0x36, 0x47, 0x26, 0x2E, 0x2C, 0x20, 0x5C, 0x01, 0x04, 0x30, 0xD7, 0x42, 0x0C, 0xF0, + 0xB0, 0x01, 0xF1, 0xF0, 0x98, 0x7E, 0xDF, 0x00, 0x92, 0x03, 0x2B, 0x36, 0x03, 0x00, 0xB9, 0x0E, + 0xFC, 0x02, 0xB9, 0x0E, 0x00, 0x03, 0x99, 0x0E, 0x25, 0x03, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, + 0x2F, 0x75, 0x05, 0x00, 0xC4, 0x50, 0x3C, 0x10, 0x18, 0x00, 0x26, 0x75, 0xD7, 0x71, 0xD9, 0xC1, + 0x08, 0x00, 0xC1, 0xA1, 0x2F, 0x64, 0x07, 0x00, 0x82, 0x06, 0xC4, 0x5D, 0x14, 0x71, 0x04, 0xC0, + 0x82, 0x04, 0xF2, 0x02, 0x06, 0x75, 0x04, 0xC1, 0xC4, 0x40, 0x82, 0x07, 0xCC, 0x40, 0x16, 0x00, + 0x14, 0xD1, 0x04, 0xB0, 0x82, 0x04, 0xF2, 0x02, 0x06, 0xD4, 0x04, 0xB1, 0x26, 0x66, 0x26, 0x63, + 0x70, 0xF6, 0x2F, 0x67, 0x05, 0x00, 0x2F, 0xE6, 0x06, 0x00, 0x26, 0xE6, 0xD7, 0xE1, 0x06, 0x6D, + 0x2F, 0xA6, 0x04, 0x00, 0x26, 0xAE, 0x26, 0xAA, 0x26, 0xA3, 0x70, 0xAA, 0xC6, 0xAF, 0x12, 0x11, + 0x24, 0x61, 0x43, 0x66, 0xC6, 0x6B, 0x02, 0xF5, 0x24, 0x71, 0x43, 0x77, 0xC6, 0x7C, 0x02, 0xEA, + 0x28, 0x60, 0x16, 0x0E, 0x04, 0x70, 0xC6, 0xF6, 0x22, 0x05, 0xA1, 0xF2, 0x04, 0x71, 0xF2, 0x02, + 0x04, 0x70, 0x58, 0xC1, 0x08, 0x00, 0x40, 0xA1, 0x06, 0x27, 0x2C, 0x10, 0x18, 0x00, 0xE1, 0xF0, + 0x3C, 0x10, 0x28, 0x00, 0xD9, 0x81, 0x08, 0x00, 0x86, 0xB6, 0xD9, 0xC1, 0x18, 0x00, 0x06, 0xA3, + 0x06, 0xD2, 0x06, 0xE4, 0x06, 0xC5, 0x92, 0x13, 0x30, 0x74, 0x38, 0xB4, 0x04, 0x00, 0x26, 0xB7, + 0x38, 0x74, 0x08, 0x00, 0x26, 0xB7, 0x38, 0x74, 0x0C, 0x00, 0x26, 0xB7, 0x38, 0x74, 0x10, 0x00, + 0xA6, 0xB7, 0x92, 0x05, 0x38, 0xE5, 0x08, 0x00, 0x04, 0xB1, 0xF2, 0x35, 0x30, 0x3C, 0x30, 0x2E, + 0x4B, 0x14, 0x00, 0x00, 0xB1, 0x2E, 0x06, 0x72, 0x38, 0x3C, 0x04, 0x00, 0x38, 0x2E, 0x04, 0x00, + 0xB9, 0x71, 0x04, 0x00, 0x4B, 0x14, 0x00, 0x00, 0xB9, 0x2E, 0x04, 0x00, 0x06, 0x62, 0x38, 0x3C, + 0x08, 0x00, 0x38, 0x2E, 0x08, 0x00, 0xB1, 0x61, 0x4B, 0x14, 0x00, 0x00, 0xB9, 0x2E, 0x08, 0x00, + 0x38, 0x3C, 0x0C, 0x00, 0x06, 0x82, 0x38, 0x2E, 0x0C, 0x00, 0x4B, 0x14, 0x00, 0x00, 0xB9, 0x2E, + 0x0C, 0x00, 0x06, 0x92, 0x38, 0x3C, 0x10, 0x00, 0x38, 0x2E, 0x10, 0x00, 0x4B, 0x14, 0x00, 0x00, + 0x30, 0x61, 0x38, 0x71, 0x04, 0x00, 0xB9, 0x2E, 0x10, 0x00, 0x2F, 0xE7, 0x06, 0x00, 0x26, 0xE8, + 0x26, 0xE9, 0x26, 0xE2, 0x06, 0x3B, 0x06, 0x2E, 0xAB, 0x15, 0x00, 0x00, 0x04, 0x3A, 0xAB, 0x15, + 0x00, 0x00, 0xC4, 0xA0, 0x92, 0x08, 0xB9, 0xBD, 0x04, 0x00, 0xB9, 0xED, 0x0C, 0x00, 0xA9, 0x2D, + 0x14, 0x00, 0xF2, 0x11, 0xC4, 0xA1, 0x92, 0x08, 0xB9, 0xBD, 0x08, 0x00, 0xB9, 0xED, 0x10, 0x00, + 0xA9, 0x2D, 0x16, 0x00, 0xF2, 0x08, 0xC4, 0xA2, 0x92, 0x04, 0xA9, 0x2D, 0x18, 0x00, 0xF2, 0x03, + 0xA9, 0x2D, 0x1A, 0x00, 0x58, 0xC1, 0x18, 0x00, 0x58, 0x81, 0x08, 0x00, 0x2C, 0x10, 0x28, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0x0B, 0xCB, 0x03, 0x00, 0x30, 0xF1, 0x16, 0x22, + 0xF7, 0x2F, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, + 0xD1, 0xC1, 0x0C, 0xE0, 0xFC, 0x0A, 0x18, 0x7E, 0x8D, 0x06, 0xC4, 0x72, 0xC2, 0x06, 0x38, 0x70, + 0x70, 0x1A, 0x28, 0x77, 0x30, 0x00, 0xF2, 0x14, 0xC4, 0x72, 0x92, 0x06, 0x38, 0x70, 0x70, 0x1A, + 0x28, 0x77, 0x2E, 0x00, 0xF2, 0x0D, 0x98, 0x70, 0xA2, 0x1B, 0x82, 0x06, 0x08, 0x70, 0x00, 0x80, + 0x28, 0x77, 0xB0, 0xDC, 0xF2, 0x05, 0x38, 0x70, 0x70, 0x1A, 0x28, 0x77, 0x2C, 0x00, 0xA9, 0x7E, + 0x04, 0x03, 0x28, 0x7E, 0x04, 0x03, 0x28, 0x5E, 0x12, 0x03, 0x26, 0x57, 0x38, 0x70, 0x70, 0x1A, + 0x23, 0x55, 0xA9, 0x5E, 0x06, 0x03, 0x28, 0x67, 0x32, 0x00, 0x98, 0x70, 0xB0, 0x1B, 0xA9, 0x6E, + 0x20, 0x03, 0x82, 0x0C, 0x38, 0x7E, 0x0C, 0x00, 0xD4, 0x71, 0x82, 0x08, 0x08, 0x70, 0x00, 0x80, + 0x28, 0x77, 0x84, 0xDC, 0x26, 0x57, 0xA9, 0x5E, 0x06, 0x03, 0x98, 0x70, 0xCD, 0x1B, 0x92, 0x04, + 0x98, 0x70, 0xC1, 0x1B, 0x82, 0x0B, 0xB8, 0x70, 0x8C, 0x19, 0x92, 0x08, 0x28, 0x7E, 0x06, 0x03, + 0x2F, 0x57, 0x07, 0x00, 0x26, 0x75, 0xA9, 0x7E, 0x06, 0x03, 0x18, 0x70, 0xCC, 0x1B, 0x93, 0x07, + 0x92, 0x05, 0x18, 0x70, 0xCB, 0x1B, 0x93, 0x07, 0x82, 0x0C, 0xB8, 0x70, 0x8C, 0x19, 0x92, 0x09, + 0x28, 0x7E, 0x06, 0x03, 0xD7, 0x61, 0xD7, 0x71, 0xA9, 0x7E, 0x06, 0x03, 0xA9, 0x6E, 0x20, 0x03, + 0x4B, 0x3E, 0x00, 0x00, 0x23, 0x22, 0x0C, 0x30, 0x18, 0x00, 0x4B, 0x18, 0x00, 0x00, 0xA3, 0x22, + 0x82, 0x04, 0xCC, 0x20, 0x16, 0x00, 0x92, 0x0A, 0x38, 0x70, 0x70, 0x1A, 0x28, 0x67, 0x34, 0x00, + 0x28, 0x7E, 0x06, 0x03, 0x26, 0x76, 0xA9, 0x7E, 0x06, 0x03, 0x28, 0x2E, 0x06, 0x03, 0x38, 0x70, + 0x70, 0x1A, 0xA9, 0x2E, 0x08, 0x03, 0x18, 0x37, 0x8C, 0x00, 0x4B, 0x14, 0x00, 0x00, 0x0C, 0x30, + 0x64, 0x00, 0x8B, 0x16, 0x00, 0x00, 0xA9, 0x2E, 0x06, 0x03, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x50, 0x01, 0x0C, 0x20, 0x68, 0x00, + 0x0C, 0x40, 0x2E, 0x00, 0x26, 0x21, 0x04, 0x30, 0xD9, 0xC1, 0x40, 0x01, 0xD9, 0x81, 0x30, 0x01, + 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x0C, 0x70, 0xFC, 0x0A, 0x0C, 0x60, 0xFF, 0x0F, 0xA9, 0x67, + 0x14, 0x03, 0x38, 0x40, 0x80, 0x1A, 0xA9, 0x07, 0x16, 0x03, 0x38, 0x50, 0x7C, 0x1A, 0xA9, 0x07, + 0x18, 0x03, 0x18, 0xD7, 0xE2, 0x00, 0xB9, 0x41, 0x10, 0x01, 0x06, 0x87, 0x0C, 0x70, 0x66, 0x00, + 0x26, 0x71, 0xB9, 0x51, 0x14, 0x01, 0xB9, 0x71, 0xFC, 0x00, 0x18, 0x78, 0xE4, 0x00, 0xC6, 0x7D, + 0xCA, 0x9C, 0x01, 0x00, 0x38, 0x78, 0x00, 0x03, 0x73, 0x7D, 0xD4, 0x71, 0x8A, 0x39, 0x02, 0x00, + 0x2F, 0x7D, 0x0D, 0x00, 0x0C, 0x90, 0x1C, 0x00, 0x26, 0x7D, 0x26, 0x9D, 0xD7, 0x71, 0x57, 0x91, + 0x18, 0xC8, 0xE1, 0x00, 0xB9, 0x71, 0x04, 0x01, 0xB9, 0x91, 0x0C, 0x01, 0xF2, 0x08, 0x18, 0x68, + 0x8D, 0x06, 0xC4, 0x62, 0x8A, 0x8C, 0x01, 0x00, 0x24, 0xC1, 0x13, 0xCC, 0x18, 0x78, 0xE3, 0x00, + 0xC6, 0x7C, 0xCA, 0x1E, 0x02, 0x00, 0x38, 0x78, 0xFC, 0x02, 0x73, 0x7C, 0xD4, 0x71, 0x82, 0xF5, + 0x38, 0xE1, 0x04, 0x01, 0x26, 0xEC, 0xB9, 0xE1, 0x08, 0x01, 0x43, 0xEE, 0x2F, 0xBE, 0x0E, 0x00, + 0x0C, 0x70, 0x28, 0x08, 0x26, 0x7B, 0x70, 0x67, 0x78, 0x78, 0x06, 0x03, 0xC6, 0x67, 0x22, 0xE5, + 0x06, 0x9E, 0x0C, 0x70, 0x68, 0x00, 0xF7, 0x91, 0x26, 0x71, 0x38, 0xA1, 0x08, 0x01, 0x26, 0x79, + 0x10, 0x77, 0x54, 0xA7, 0x63, 0x7A, 0xD4, 0x71, 0x92, 0xD8, 0x43, 0x7C, 0x43, 0x6D, 0x0C, 0x20, + 0xFA, 0x00, 0x06, 0x47, 0x26, 0x21, 0x0C, 0x30, 0x28, 0x08, 0x06, 0x56, 0xB9, 0x71, 0x28, 0x01, + 0xA9, 0x01, 0xFA, 0x00, 0xB9, 0x61, 0x00, 0x01, 0x0B, 0x39, 0x03, 0x00, 0xC4, 0x20, 0x38, 0x71, + 0x28, 0x01, 0x82, 0xBE, 0x06, 0x2C, 0x06, 0x3D, 0x2B, 0x45, 0x03, 0x00, 0xC4, 0x20, 0x92, 0xBD, + 0x78, 0x71, 0xFA, 0x00, 0x28, 0x68, 0x18, 0x03, 0xC6, 0x76, 0x22, 0x03, 0xA9, 0x78, 0x18, 0x03, + 0x0C, 0x70, 0x68, 0x00, 0x26, 0x71, 0x26, 0x97, 0x10, 0x59, 0x04, 0x71, 0x06, 0x67, 0x53, 0x6A, + 0xCC, 0xC0, 0x17, 0x00, 0x66, 0x65, 0x91, 0x69, 0x82, 0x0E, 0x06, 0x57, 0x26, 0x5E, 0x06, 0x65, + 0x0C, 0x90, 0x68, 0x00, 0xE7, 0x61, 0x26, 0x91, 0x26, 0x69, 0x54, 0x57, 0x53, 0x75, 0x10, 0x56, + 0x66, 0x75, 0x91, 0x76, 0xC4, 0xDD, 0x9A, 0x32, 0x01, 0x00, 0x38, 0xE1, 0x14, 0x01, 0x38, 0x70, + 0x70, 0x1A, 0x26, 0xBE, 0x28, 0x37, 0x3E, 0x00, 0x70, 0x2B, 0x14, 0xB1, 0x4B, 0x14, 0x00, 0x00, + 0x0C, 0x30, 0x64, 0x00, 0x8B, 0x16, 0x00, 0x00, 0x0C, 0x40, 0x14, 0x00, 0x26, 0x48, 0x20, 0x44, + 0x13, 0x22, 0xB9, 0x41, 0x00, 0x01, 0x04, 0x40, 0x06, 0x74, 0x14, 0x62, 0xB9, 0x21, 0x1C, 0x01, + 0x2F, 0xA6, 0x0D, 0x00, 0x13, 0xAA, 0x33, 0x5A, 0x2F, 0xF5, 0x05, 0x00, 0x26, 0x5F, 0x0C, 0x20, + 0x34, 0x00, 0xD7, 0x51, 0x23, 0x55, 0x26, 0x21, 0xB9, 0x51, 0x18, 0x01, 0x2F, 0x34, 0x01, 0x00, + 0x26, 0x24, 0x14, 0x52, 0xC4, 0xAD, 0xCA, 0x38, 0x01, 0x00, 0xA1, 0x02, 0xA1, 0x03, 0x24, 0x51, + 0x43, 0x55, 0xC4, 0x53, 0x24, 0x22, 0x24, 0x32, 0x92, 0xF6, 0x24, 0x4A, 0xCC, 0x40, 0x32, 0x00, + 0x24, 0x61, 0x43, 0x66, 0x92, 0xDE, 0x78, 0x61, 0x4C, 0x00, 0x28, 0x58, 0x14, 0x03, 0xA9, 0x61, + 0xFA, 0x00, 0xC6, 0x56, 0x02, 0x03, 0xA9, 0x68, 0x14, 0x03, 0x28, 0x58, 0x16, 0x03, 0xC6, 0x56, + 0x32, 0x03, 0xA9, 0x68, 0x16, 0x03, 0x0C, 0x50, 0x34, 0x00, 0x04, 0x42, 0x04, 0x34, 0x04, 0x28, + 0x56, 0x47, 0x56, 0x37, 0x56, 0x27, 0x26, 0x51, 0x5C, 0x70, 0x10, 0x00, 0x06, 0x65, 0x13, 0x44, + 0x13, 0x33, 0x13, 0x22, 0x13, 0x77, 0xC4, 0x40, 0x92, 0x02, 0xA1, 0x05, 0xC4, 0x30, 0x92, 0x03, + 0xA9, 0x05, 0x28, 0x00, 0xC4, 0x20, 0x92, 0x02, 0xA1, 0x06, 0xC4, 0x70, 0x92, 0x03, 0xA9, 0x06, + 0x08, 0x00, 0x38, 0xE1, 0xFC, 0x00, 0x24, 0x6A, 0xC6, 0x6E, 0x24, 0x52, 0x92, 0xED, 0x0C, 0x60, + 0x34, 0x00, 0x26, 0x61, 0x06, 0xE1, 0x06, 0x41, 0x06, 0x56, 0x04, 0x70, 0x78, 0x25, 0x0A, 0x00, + 0x70, 0xF5, 0x0C, 0x30, 0xD4, 0x00, 0x26, 0xF2, 0x78, 0x25, 0x14, 0x00, 0x26, 0x31, 0x26, 0xF2, + 0x78, 0x25, 0x1E, 0x00, 0x26, 0x37, 0x26, 0xF2, 0x78, 0x25, 0x28, 0x00, 0x24, 0x42, 0x26, 0x2F, + 0xB1, 0x23, 0x70, 0xF6, 0x78, 0x26, 0x02, 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x26, 0xF2, 0x78, 0x26, + 0x04, 0x00, 0x26, 0x31, 0x26, 0xF2, 0x78, 0x26, 0x06, 0x00, 0x26, 0x37, 0x26, 0xF2, 0x78, 0x26, + 0x08, 0x00, 0x24, 0x52, 0x26, 0x2F, 0xB1, 0x23, 0x78, 0xF4, 0x08, 0x00, 0x78, 0x24, 0x12, 0x00, + 0x0C, 0x30, 0xAC, 0x00, 0x26, 0xF2, 0x78, 0x24, 0x1C, 0x00, 0x26, 0x31, 0x26, 0x37, 0x26, 0x2F, + 0xB1, 0x23, 0x78, 0xFE, 0x02, 0x00, 0x78, 0x2E, 0x04, 0x00, 0x0C, 0x30, 0x98, 0x00, 0x26, 0xF2, + 0x26, 0x31, 0x78, 0x2E, 0x06, 0x00, 0x26, 0x37, 0x24, 0x74, 0xCC, 0x70, 0x14, 0x00, 0x26, 0x2F, + 0xB1, 0x23, 0x24, 0x6A, 0x24, 0xEA, 0x92, 0xBB, 0x18, 0x28, 0x1F, 0x03, 0x38, 0xE1, 0x0C, 0x01, + 0xD7, 0x22, 0x26, 0xE8, 0x26, 0x28, 0x0C, 0x40, 0xC0, 0x00, 0x06, 0x5E, 0x2C, 0x20, 0x5C, 0x01, + 0x04, 0x31, 0x26, 0x41, 0x04, 0x60, 0x8B, 0x3D, 0x03, 0x00, 0x18, 0x28, 0x1F, 0x03, 0x0C, 0x40, + 0x98, 0x00, 0xD7, 0x22, 0x26, 0x28, 0x06, 0x5E, 0x2C, 0x20, 0x5C, 0x01, 0x04, 0x33, 0x26, 0x41, + 0x04, 0x60, 0x8B, 0x3D, 0x03, 0x00, 0x18, 0x28, 0x1F, 0x03, 0x04, 0xE4, 0x26, 0xEC, 0x57, 0xE1, + 0xD7, 0x22, 0x26, 0xE8, 0x04, 0x30, 0x26, 0x28, 0x0C, 0x40, 0xD4, 0x00, 0x06, 0x63, 0x2C, 0x20, + 0x5C, 0x01, 0x26, 0x41, 0x06, 0x5E, 0x8B, 0x3D, 0x03, 0x00, 0x18, 0x28, 0x1F, 0x03, 0x0C, 0x40, + 0xAC, 0x00, 0xD7, 0x22, 0x26, 0x28, 0x06, 0x5E, 0x04, 0x60, 0x2C, 0x20, 0x5C, 0x01, 0x04, 0x32, + 0x26, 0x41, 0x8B, 0x3D, 0x03, 0x00, 0x18, 0x68, 0x1F, 0x03, 0x38, 0xF1, 0x08, 0x01, 0x18, 0x58, + 0x25, 0x03, 0x06, 0x76, 0xD7, 0x72, 0x26, 0x78, 0x99, 0xC7, 0x5E, 0x01, 0x99, 0xD7, 0x5F, 0x01, + 0xA9, 0xF7, 0x5C, 0x01, 0xA9, 0x57, 0x78, 0x01, 0x04, 0x71, 0x26, 0x76, 0x13, 0x77, 0xC4, 0x7D, + 0x99, 0x78, 0x1F, 0x03, 0x9A, 0x82, 0xFE, 0xFF, 0x18, 0x68, 0x1F, 0x03, 0x98, 0x78, 0xDD, 0x00, + 0x99, 0x68, 0x1D, 0x03, 0x9A, 0xA1, 0x00, 0x00, 0xFA, 0xA4, 0x00, 0x00, 0x38, 0x31, 0x10, 0x01, + 0x38, 0x51, 0x00, 0x01, 0x0C, 0x20, 0xFA, 0x00, 0x26, 0x21, 0x06, 0x47, 0x0B, 0x39, 0x03, 0x00, + 0xC4, 0x20, 0x8A, 0x6B, 0xFE, 0xFF, 0xFA, 0xA7, 0xFE, 0xFF, 0x0C, 0x70, 0x18, 0x00, 0x26, 0x7E, + 0x0C, 0x50, 0x68, 0x00, 0xE7, 0x71, 0x26, 0x51, 0x26, 0x57, 0x04, 0x67, 0x04, 0x71, 0x56, 0x6E, + 0x10, 0x45, 0x06, 0xF7, 0x53, 0xF6, 0x06, 0x6F, 0xC4, 0xC0, 0x66, 0x64, 0x91, 0x65, 0x92, 0x11, + 0x2C, 0xE0, 0x19, 0x00, 0x06, 0x6E, 0x0C, 0x40, 0x68, 0x00, 0xE7, 0x61, 0x26, 0x41, 0x26, 0x64, + 0x10, 0x56, 0x54, 0xE7, 0x04, 0x71, 0x53, 0x7E, 0x66, 0x75, 0x91, 0x76, 0xFA, 0xAF, 0xFE, 0xFF, + 0x0C, 0x50, 0x17, 0x00, 0x26, 0x5E, 0x06, 0x65, 0x0C, 0x90, 0x68, 0x00, 0xE7, 0x61, 0x26, 0x91, + 0x26, 0x69, 0x54, 0x57, 0x53, 0x75, 0x10, 0x56, 0xCC, 0xC0, 0x17, 0x00, 0x66, 0x75, 0x91, 0x76, + 0x8A, 0x9D, 0xFE, 0xFF, 0xF2, 0xDE, 0x2F, 0xF5, 0x0C, 0x00, 0x13, 0xFF, 0xCC, 0xF0, 0x16, 0x00, + 0xDA, 0xC5, 0xFE, 0xFF, 0x38, 0x91, 0x18, 0x01, 0x38, 0xE1, 0x10, 0x01, 0x33, 0xFF, 0x26, 0xF9, + 0x43, 0xFF, 0x26, 0xFF, 0x26, 0xEF, 0x20, 0x9E, 0x06, 0xE9, 0x38, 0x91, 0x00, 0x01, 0x36, 0xE9, + 0xB9, 0xE1, 0x2C, 0x01, 0x06, 0x9E, 0xC3, 0xEE, 0x32, 0x02, 0x04, 0x90, 0x0C, 0xE0, 0x28, 0x08, + 0x26, 0xEF, 0xA1, 0x92, 0x20, 0x9E, 0x06, 0xE9, 0x38, 0x91, 0x00, 0x01, 0x36, 0xE9, 0xB9, 0xE1, + 0x2C, 0x01, 0x06, 0x9E, 0xC3, 0xEE, 0x32, 0x02, 0x04, 0x90, 0xA1, 0x93, 0x14, 0x92, 0xC6, 0x69, + 0x8A, 0x9F, 0xFE, 0xFF, 0xC4, 0x62, 0x8A, 0x9C, 0xFE, 0xFF, 0xC6, 0x59, 0x8A, 0x99, 0xFE, 0xFF, + 0xC4, 0x52, 0x8A, 0x96, 0xFE, 0xFF, 0x38, 0xE1, 0x14, 0x01, 0x38, 0x91, 0x1C, 0x01, 0x26, 0xFE, + 0x70, 0xFF, 0xC6, 0xF9, 0x0A, 0x8D, 0xFE, 0xFF, 0xC6, 0x6B, 0x92, 0x03, 0x64, 0x72, 0xF2, 0x04, + 0xC4, 0x61, 0x92, 0x02, 0x64, 0x74, 0xC6, 0x5B, 0x92, 0x04, 0x64, 0x78, 0xFA, 0x81, 0xFE, 0xFF, + 0xC4, 0x51, 0x9A, 0x7E, 0xFE, 0xFF, 0x6C, 0x70, 0x10, 0x00, 0xFA, 0x7A, 0xFE, 0xFF, 0x24, 0xD1, + 0x13, 0xDD, 0xFA, 0xBC, 0xFD, 0xFF, 0xCC, 0x70, 0xF9, 0x00, 0xD2, 0x08, 0x24, 0x71, 0xF2, 0x04, + 0xC4, 0x60, 0x82, 0x04, 0x04, 0x71, 0x99, 0x78, 0xDD, 0x00, 0x0C, 0x20, 0xE8, 0x00, 0x0C, 0x40, + 0x12, 0x00, 0x26, 0x21, 0x04, 0x30, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x18, 0x98, 0x1F, 0x03, + 0x14, 0x41, 0x26, 0x49, 0x08, 0xB0, 0xE4, 0xFF, 0x08, 0xA0, 0xA9, 0x00, 0xB9, 0x41, 0x04, 0x01, + 0x04, 0xE0, 0x2C, 0xB0, 0xDC, 0x30, 0x2C, 0xA0, 0xDC, 0xF1, 0x04, 0x71, 0x38, 0x41, 0x04, 0x01, + 0x06, 0x6E, 0xC6, 0xE4, 0x32, 0x44, 0x06, 0xCE, 0xD7, 0xC2, 0x24, 0xE1, 0x0C, 0xF0, 0xE8, 0x00, + 0x26, 0xC8, 0x43, 0xEE, 0x26, 0xF1, 0x2C, 0xC0, 0x5C, 0x01, 0x06, 0xDE, 0x26, 0x6F, 0xC6, 0xD9, + 0x32, 0xEE, 0x06, 0x5D, 0xD7, 0x52, 0x26, 0x58, 0x78, 0x45, 0x70, 0x01, 0x78, 0x2C, 0x14, 0x00, + 0x2C, 0x50, 0x5C, 0x01, 0x78, 0x55, 0x16, 0x00, 0x36, 0x24, 0x78, 0x4C, 0x16, 0x00, 0xB9, 0x61, + 0x24, 0x01, 0x06, 0x32, 0x36, 0x45, 0xB9, 0x71, 0x28, 0x01, 0xB9, 0x41, 0x20, 0x01, 0x4B, 0x14, + 0x00, 0x00, 0x38, 0x41, 0x20, 0x01, 0x06, 0x52, 0x06, 0x34, 0x06, 0x24, 0xB9, 0x51, 0x20, 0x01, + 0x4B, 0x14, 0x00, 0x00, 0x38, 0x51, 0x20, 0x01, 0x38, 0x61, 0x24, 0x01, 0x38, 0x71, 0x28, 0x01, + 0x26, 0x25, 0x2F, 0x5B, 0x02, 0x00, 0xC6, 0x5A, 0xD2, 0x07, 0x0C, 0x50, 0xE8, 0x00, 0x26, 0x51, + 0x91, 0x76, 0x26, 0x5D, 0x91, 0x75, 0x24, 0xD1, 0x43, 0xDD, 0xF2, 0xCA, 0x04, 0x60, 0x06, 0x58, + 0x18, 0x78, 0x1F, 0x03, 0xC6, 0x67, 0x32, 0x16, 0x0C, 0x70, 0xE8, 0x00, 0x26, 0x71, 0x26, 0x76, + 0x10, 0x77, 0xC4, 0x71, 0x92, 0x0C, 0x06, 0x76, 0xD7, 0x72, 0x26, 0x75, 0x28, 0x47, 0x74, 0x01, + 0xA9, 0x47, 0x70, 0x01, 0x28, 0x47, 0x76, 0x01, 0xA9, 0x47, 0x72, 0x01, 0x24, 0x61, 0x43, 0x66, + 0xF2, 0xE8, 0x58, 0xC1, 0x40, 0x01, 0x58, 0x81, 0x30, 0x01, 0x2C, 0x10, 0x50, 0x01, 0xE1, 0xF0, + 0x0C, 0x70, 0xFC, 0x0A, 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0x28, 0xD7, 0x20, 0x03, + 0x68, 0xF7, 0x1F, 0x03, 0xD1, 0x81, 0x04, 0x60, 0x14, 0x41, 0x99, 0x07, 0x24, 0x03, 0x43, 0x9D, + 0x23, 0x30, 0x06, 0x26, 0x06, 0x54, 0x0C, 0xC0, 0x74, 0x1A, 0x0C, 0xB0, 0x80, 0x02, 0x2F, 0xE6, + 0x06, 0x00, 0x26, 0xEC, 0x70, 0xEE, 0x06, 0xAB, 0x26, 0xEE, 0x26, 0xEB, 0x70, 0xEE, 0xC6, 0xE9, + 0x22, 0x0B, 0xC6, 0x3E, 0x32, 0x09, 0x04, 0x81, 0x26, 0x8F, 0x24, 0x21, 0x06, 0x5F, 0x33, 0x46, + 0x13, 0x22, 0x23, 0x3E, 0x33, 0xF8, 0x24, 0x61, 0xC4, 0x63, 0x92, 0xEA, 0xA9, 0x37, 0x1A, 0x03, + 0x99, 0x20, 0xC1, 0x1B, 0x43, 0x33, 0x04, 0x60, 0x2F, 0x26, 0x06, 0x00, 0x0C, 0xF0, 0x74, 0x1A, + 0x26, 0x2F, 0x20, 0x22, 0x26, 0x22, 0x26, 0x2A, 0xF0, 0x22, 0x02, 0x06, 0x43, 0xF6, 0xC6, 0x4F, + 0x82, 0x03, 0x36, 0x32, 0x43, 0x33, 0x24, 0x61, 0xC4, 0x63, 0x92, 0xEF, 0xC6, 0x3D, 0x32, 0x04, + 0xA9, 0x07, 0x1A, 0x03, 0xF2, 0x1D, 0x14, 0x61, 0xC6, 0x56, 0x82, 0x1A, 0x98, 0x67, 0xA2, 0x06, + 0x82, 0x0B, 0x18, 0x67, 0xA0, 0x06, 0x99, 0x57, 0x22, 0x03, 0x99, 0x67, 0x23, 0x03, 0x04, 0x61, + 0x99, 0x67, 0x24, 0x03, 0xF2, 0x0D, 0x04, 0x31, 0x06, 0x63, 0x53, 0x64, 0x18, 0x47, 0x23, 0x03, + 0x99, 0x57, 0x22, 0x03, 0x99, 0x37, 0x24, 0x03, 0x66, 0x64, 0x99, 0x67, 0x23, 0x03, 0x58, 0xC1, + 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x18, 0xC1, 0xE1, + 0x0C, 0xE0, 0xFC, 0x0A, 0x98, 0x6E, 0x1F, 0x03, 0x06, 0x7E, 0x82, 0x24, 0x98, 0x5E, 0x24, 0x03, + 0x82, 0x21, 0x28, 0x4E, 0x18, 0x03, 0x28, 0x5E, 0x1A, 0x03, 0xC6, 0x45, 0xD2, 0x03, 0xC4, 0x61, + 0xC2, 0x0B, 0x14, 0x51, 0x99, 0x57, 0x22, 0x03, 0x99, 0x07, 0x23, 0x03, 0x99, 0x67, 0x1C, 0x03, + 0x99, 0x07, 0x24, 0x03, 0xF2, 0x0F, 0x0C, 0x20, 0x58, 0x0C, 0x04, 0x30, 0x0C, 0x40, 0x20, 0x00, + 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x18, 0x7E, 0x24, 0x03, 0x99, 0x0E, 0x1F, 0x03, 0x99, 0x7E, + 0x1C, 0x03, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x34, 0x18, 0xC1, 0xE1, 0x8B, 0x7E, 0x03, 0x00, + 0xCB, 0x4E, 0x03, 0x00, 0x0C, 0xE0, 0xFC, 0x0A, 0x18, 0x6E, 0x1F, 0x03, 0x18, 0x7E, 0x24, 0x03, + 0x26, 0x76, 0x13, 0x77, 0x99, 0x7E, 0x1C, 0x03, 0x99, 0x7E, 0x1D, 0x03, 0x6B, 0x85, 0x03, 0x00, + 0xCB, 0xDF, 0x02, 0x00, 0x18, 0x7E, 0x1C, 0x03, 0x99, 0x7E, 0x1E, 0x03, 0x40, 0xE1, 0x24, 0x18, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x18, 0x00, 0xC1, 0xA1, 0x0C, 0xB0, 0xFC, 0x0A, 0x18, 0xAB, + 0x1F, 0x03, 0xD9, 0xC1, 0x08, 0x00, 0x04, 0xE0, 0x06, 0xCE, 0x06, 0xDB, 0x18, 0x4B, 0x1F, 0x03, + 0xC6, 0xC4, 0xB2, 0x1A, 0x06, 0x3C, 0xD7, 0x32, 0x26, 0x3D, 0x2C, 0x30, 0x5C, 0x01, 0xA8, 0x73, + 0x1C, 0x00, 0x82, 0x0F, 0xC6, 0xCE, 0x82, 0x0B, 0x06, 0x2E, 0xD7, 0x22, 0x26, 0x2D, 0x2C, 0x20, + 0x5C, 0x01, 0x0C, 0x40, 0x20, 0x00, 0x0C, 0xF0, 0x28, 0x01, 0xF1, 0xF0, 0x24, 0xE1, 0x13, 0xEE, + 0x24, 0xC1, 0x13, 0xCC, 0xF2, 0xE4, 0x06, 0x2E, 0xD7, 0x22, 0x26, 0x2D, 0x36, 0x4E, 0x2C, 0x20, + 0x5C, 0x01, 0x04, 0x30, 0xD7, 0x42, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x18, 0x7D, 0x1C, 0x03, + 0x99, 0xED, 0x1F, 0x03, 0x3F, 0xAA, 0x07, 0x00, 0x26, 0xEA, 0x99, 0xED, 0x1C, 0x03, 0x58, 0xC1, + 0x08, 0x00, 0x40, 0xA1, 0x2C, 0x10, 0x18, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x38, 0x70, 0x70, 0x1A, 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0xD1, 0x81, 0x28, 0x47, + 0x32, 0x00, 0x06, 0xD4, 0x18, 0x50, 0xCD, 0x1B, 0xD7, 0xD1, 0x04, 0x70, 0x08, 0x30, 0x00, 0x30, + 0x23, 0xDD, 0x06, 0x27, 0x0C, 0xC0, 0x74, 0x1A, 0x2C, 0x30, 0x00, 0x49, 0x2F, 0x6C, 0x07, 0x00, + 0x20, 0x66, 0x0C, 0x80, 0xFF, 0x0F, 0x57, 0x61, 0x26, 0x63, 0x30, 0x66, 0x04, 0x90, 0x56, 0x86, + 0x77, 0x68, 0x5C, 0x60, 0xFF, 0x0F, 0xC6, 0x86, 0x02, 0x03, 0x3F, 0x96, 0x08, 0x00, 0x18, 0x60, + 0xCC, 0x1B, 0x93, 0x06, 0x92, 0x05, 0x18, 0x60, 0xCB, 0x1B, 0x93, 0x06, 0x82, 0x04, 0xB8, 0x60, + 0x8C, 0x19, 0x82, 0x03, 0x06, 0x64, 0xF2, 0x02, 0x06, 0x6D, 0xC6, 0x96, 0x22, 0x03, 0x04, 0x51, + 0x06, 0x25, 0x24, 0x72, 0xC4, 0x76, 0x92, 0xDB, 0xC4, 0x20, 0x99, 0x50, 0xCD, 0x1B, 0x92, 0x03, + 0x99, 0x00, 0xCD, 0x1B, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, + 0x98, 0x70, 0xA2, 0x1B, 0x3C, 0x10, 0x50, 0x00, 0xD9, 0xC1, 0x40, 0x00, 0xD9, 0x81, 0x30, 0x00, + 0x82, 0x06, 0x08, 0x70, 0x00, 0x80, 0x28, 0xE7, 0xAE, 0xDC, 0xF2, 0x05, 0x38, 0x70, 0x70, 0x1A, + 0x28, 0xE7, 0x28, 0x00, 0xB8, 0x70, 0x8C, 0x19, 0x82, 0x08, 0x2F, 0x2E, 0x0E, 0x00, 0x26, 0x2E, + 0x04, 0x35, 0xAB, 0x15, 0x00, 0x00, 0x06, 0xE2, 0x4B, 0x3E, 0x00, 0x00, 0xB8, 0x70, 0x8C, 0x19, + 0x82, 0x0D, 0xA3, 0x22, 0x82, 0x0B, 0x0C, 0x30, 0x18, 0x00, 0xAB, 0x15, 0x00, 0x00, 0xA3, 0x22, + 0x82, 0x03, 0xC4, 0x2D, 0x92, 0x03, 0x2C, 0xE0, 0x90, 0x01, 0xB8, 0xD0, 0x8C, 0x19, 0x9A, 0x12, + 0x02, 0x00, 0x08, 0xB0, 0x00, 0x30, 0xB9, 0xD1, 0x1C, 0x00, 0x06, 0xCD, 0xB1, 0xD1, 0xB9, 0xD1, + 0x18, 0x00, 0xB9, 0xD1, 0x14, 0x00, 0x06, 0x6D, 0xB9, 0xD1, 0x10, 0x00, 0x06, 0x4D, 0xB9, 0xD1, + 0x0C, 0x00, 0x06, 0xAD, 0x06, 0x9D, 0xB9, 0xD1, 0x08, 0x00, 0xB9, 0xD1, 0x04, 0x00, 0x2C, 0xB0, + 0x00, 0x49, 0x06, 0x7D, 0x57, 0x71, 0x26, 0x7B, 0x30, 0x87, 0xB9, 0x41, 0x20, 0x00, 0x23, 0x5D, + 0x0C, 0x70, 0xFF, 0x0F, 0x56, 0x78, 0x06, 0x25, 0x0C, 0x30, 0x18, 0x00, 0xB9, 0x51, 0x2C, 0x00, + 0xB9, 0x61, 0x24, 0x00, 0xB9, 0x71, 0x28, 0x00, 0x4B, 0x18, 0x00, 0x00, 0x23, 0x22, 0xC4, 0x2A, + 0x77, 0x88, 0x5C, 0x80, 0xFF, 0x0F, 0x38, 0x41, 0x20, 0x00, 0x38, 0x51, 0x2C, 0x00, 0x38, 0x61, + 0x24, 0x00, 0x38, 0x71, 0x28, 0x00, 0xD2, 0x28, 0xCC, 0x50, 0xA7, 0x00, 0x3F, 0x38, 0x07, 0x00, + 0xD2, 0x0B, 0xC4, 0x3A, 0x12, 0x5C, 0x3F, 0x57, 0x08, 0x00, 0xC4, 0x5A, 0x02, 0x58, 0x24, 0x61, + 0x26, 0x45, 0x23, 0x66, 0xF2, 0x54, 0xCC, 0x50, 0xD7, 0x00, 0xC2, 0x51, 0xC4, 0x3A, 0x02, 0x09, + 0x38, 0x51, 0x04, 0x00, 0x24, 0x91, 0x26, 0x53, 0xB9, 0x51, 0x04, 0x00, 0x23, 0x99, 0xF2, 0x47, + 0x3F, 0x57, 0x08, 0x00, 0xC4, 0x5A, 0x02, 0x43, 0x38, 0x51, 0x14, 0x00, 0x24, 0x51, 0x23, 0x55, + 0xB9, 0x51, 0x14, 0x00, 0xF2, 0x3C, 0xCC, 0x50, 0xA7, 0x00, 0xD2, 0x1B, 0xCC, 0x20, 0x17, 0x00, + 0x82, 0x36, 0x3F, 0x58, 0x07, 0x00, 0xC4, 0x5A, 0x02, 0x09, 0x38, 0x31, 0x08, 0x00, 0x24, 0xA1, + 0x26, 0x35, 0xB9, 0x31, 0x08, 0x00, 0x23, 0xAA, 0xF2, 0x2A, 0x3F, 0x57, 0x08, 0x00, 0xC4, 0x5A, + 0x02, 0x26, 0x38, 0x51, 0x18, 0x00, 0x24, 0x51, 0x23, 0x55, 0xB9, 0x51, 0x18, 0x00, 0xF2, 0x1F, + 0xCC, 0x50, 0xD7, 0x00, 0xC2, 0x1C, 0xCC, 0x20, 0x17, 0x00, 0x82, 0x19, 0x3F, 0x58, 0x07, 0x00, + 0xC4, 0x5A, 0x02, 0x08, 0x38, 0x51, 0x0C, 0x00, 0x24, 0x51, 0x23, 0x55, 0xB9, 0x51, 0x0C, 0x00, + 0xF2, 0x0E, 0x3F, 0x57, 0x08, 0x00, 0xC4, 0x5A, 0x02, 0x0A, 0x38, 0x31, 0x10, 0x00, 0x26, 0x35, + 0x30, 0x51, 0xB9, 0x31, 0x10, 0x00, 0x24, 0x51, 0x23, 0x55, 0xB1, 0x51, 0x3F, 0x58, 0x07, 0x00, + 0xC4, 0x50, 0x02, 0x04, 0xC6, 0x5C, 0x02, 0x02, 0x23, 0xC5, 0x36, 0x87, 0xC4, 0x80, 0x02, 0x08, + 0x38, 0x51, 0x1C, 0x00, 0xC6, 0x85, 0x02, 0x04, 0x23, 0x88, 0xB9, 0x81, 0x1C, 0x00, 0x24, 0xD1, + 0xCC, 0xD0, 0x50, 0x01, 0x9A, 0x67, 0xFF, 0xFF, 0x04, 0x31, 0x26, 0x36, 0x06, 0x24, 0xB9, 0x61, + 0x24, 0x00, 0x8B, 0x16, 0x00, 0x00, 0xC4, 0x25, 0x06, 0xB7, 0x0C, 0xB0, 0xFC, 0x0A, 0x38, 0x61, + 0x24, 0x00, 0x02, 0x44, 0xC4, 0x60, 0x82, 0x42, 0x38, 0x21, 0x04, 0x00, 0x04, 0x31, 0x26, 0x39, + 0x8B, 0x16, 0x00, 0x00, 0xCC, 0x20, 0x80, 0x00, 0x02, 0x39, 0xCC, 0x90, 0x2F, 0x00, 0xD2, 0x36, + 0xB8, 0x71, 0x14, 0x00, 0x92, 0x33, 0x38, 0x21, 0x08, 0x00, 0x04, 0x31, 0x26, 0x3A, 0x8B, 0x16, + 0x00, 0x00, 0xCC, 0x20, 0x10, 0x00, 0x02, 0x2A, 0xCC, 0xA0, 0x3F, 0x00, 0xD2, 0x27, 0xB8, 0x91, + 0x18, 0x00, 0x92, 0x24, 0x30, 0x31, 0x38, 0x21, 0x10, 0x00, 0x24, 0x31, 0x8B, 0x16, 0x00, 0x00, + 0xCC, 0x20, 0x40, 0x00, 0x02, 0x1B, 0x30, 0x51, 0xCC, 0x50, 0x30, 0x00, 0xC2, 0x17, 0xB8, 0x71, + 0x0C, 0x00, 0x92, 0x14, 0x38, 0x5B, 0x0C, 0x00, 0x04, 0x61, 0xD6, 0x65, 0x92, 0x0F, 0xCC, 0xC0, + 0x6F, 0x02, 0xD2, 0x0C, 0x08, 0x60, 0x40, 0x00, 0x66, 0x65, 0xB9, 0x6B, 0x0C, 0x00, 0x04, 0x61, + 0x99, 0x60, 0xCC, 0x1B, 0xA9, 0x00, 0x8A, 0x1B, 0xF2, 0x1C, 0x18, 0x60, 0xCC, 0x1B, 0x93, 0x06, + 0x82, 0x06, 0x28, 0x60, 0x8A, 0x1B, 0x24, 0x61, 0xA9, 0x60, 0x8A, 0x1B, 0x28, 0x60, 0x8A, 0x1B, + 0xCC, 0x60, 0x32, 0x00, 0xC2, 0x0E, 0xA9, 0x00, 0x8A, 0x1B, 0x38, 0x6B, 0x0C, 0x00, 0x99, 0x00, + 0xCC, 0x1B, 0x08, 0x50, 0xBF, 0xFF, 0x2C, 0x50, 0xFF, 0xFF, 0x56, 0x65, 0xB9, 0x6B, 0x0C, 0x00, + 0xCB, 0x3D, 0x00, 0x00, 0x23, 0x62, 0x23, 0x22, 0x2C, 0x20, 0x20, 0x00, 0xC6, 0xC2, 0xA9, 0x6B, + 0x18, 0x03, 0x02, 0x04, 0x04, 0x21, 0xFA, 0x8E, 0x01, 0x00, 0x38, 0x5B, 0x0C, 0x00, 0x04, 0x41, + 0xD6, 0x45, 0x92, 0x04, 0xCC, 0xC0, 0xFF, 0x03, 0xD2, 0xF6, 0xCC, 0x60, 0xFE, 0x0F, 0xD2, 0xF3, + 0x18, 0x60, 0xCC, 0x1B, 0x93, 0x06, 0x92, 0x0A, 0x38, 0x81, 0x1C, 0x00, 0xCC, 0x80, 0x78, 0x00, + 0xC2, 0x05, 0x08, 0x60, 0x10, 0x00, 0x66, 0x65, 0xF2, 0x06, 0x08, 0x60, 0xEF, 0xFF, 0x2C, 0x60, + 0xFF, 0xFF, 0x56, 0x65, 0xB9, 0x6B, 0x0C, 0x00, 0x38, 0x7B, 0x0C, 0x00, 0x0C, 0xF0, 0x50, 0x00, + 0xD4, 0x71, 0x82, 0x03, 0x0C, 0xF0, 0x60, 0x00, 0x1C, 0x90, 0x1F, 0x00, 0x18, 0x70, 0xC7, 0x1B, + 0x04, 0x60, 0x08, 0xC0, 0x00, 0x30, 0x26, 0x9F, 0x06, 0x26, 0x06, 0x36, 0x0C, 0xA0, 0x74, 0x1A, + 0x2C, 0xC0, 0x00, 0x49, 0xB1, 0x91, 0x2F, 0x5A, 0x06, 0x00, 0x20, 0x55, 0x57, 0x51, 0x26, 0x5C, + 0x30, 0x95, 0x0C, 0x50, 0xFF, 0x0F, 0x56, 0x59, 0x77, 0x98, 0x5C, 0x90, 0xFF, 0x0F, 0xC6, 0x59, + 0xC2, 0x10, 0x3F, 0x99, 0x05, 0x00, 0xC6, 0x9F, 0x02, 0x06, 0xCC, 0x90, 0xFF, 0x00, 0x12, 0x03, + 0x24, 0x31, 0x23, 0x33, 0xC4, 0x32, 0xC2, 0x06, 0x04, 0x81, 0x99, 0x80, 0xCB, 0x1B, 0xF2, 0x02, + 0x36, 0x95, 0xCC, 0x90, 0x00, 0x04, 0x02, 0x04, 0x99, 0x70, 0xC7, 0x1B, 0xF2, 0xA4, 0xC4, 0x70, + 0x82, 0x17, 0x0C, 0x90, 0x78, 0x1B, 0x26, 0x96, 0x20, 0x99, 0xC6, 0x95, 0xC2, 0x11, 0x18, 0x80, + 0xCB, 0x1B, 0x93, 0x08, 0x82, 0x0D, 0x3F, 0x55, 0x09, 0x00, 0x30, 0x91, 0xC6, 0x95, 0x12, 0x08, + 0x24, 0x21, 0x23, 0x22, 0xC4, 0x21, 0xC2, 0x04, 0x99, 0x00, 0xCB, 0x1B, 0x04, 0x70, 0x24, 0x62, + 0xC4, 0x66, 0x92, 0xC2, 0x18, 0x60, 0xCB, 0x1B, 0x99, 0x70, 0xC7, 0x1B, 0x93, 0x06, 0x82, 0x1F, + 0xC4, 0x70, 0x92, 0x1D, 0x08, 0x30, 0x00, 0x30, 0x0C, 0xF0, 0x78, 0x1B, 0x2C, 0x30, 0x00, 0x49, + 0x0C, 0x60, 0x74, 0x1A, 0x26, 0x67, 0x20, 0x66, 0x2F, 0x2F, 0x07, 0x00, 0x57, 0x61, 0x26, 0x63, + 0x30, 0x66, 0x24, 0x72, 0xC4, 0x76, 0x5C, 0x60, 0xFF, 0x0F, 0xA1, 0x62, 0x92, 0xF2, 0x18, 0x70, + 0xCB, 0x1B, 0x93, 0x07, 0x82, 0x04, 0x04, 0x71, 0x99, 0x70, 0xC7, 0x1B, 0x18, 0x70, 0xCC, 0x1B, + 0x93, 0x07, 0x92, 0x05, 0x18, 0x30, 0xCB, 0x1B, 0x93, 0x03, 0x82, 0x07, 0xD7, 0xE1, 0xA9, 0x00, + 0x8C, 0x1B, 0x99, 0x00, 0xC8, 0x1B, 0xF2, 0x2E, 0x98, 0x30, 0xC8, 0x1B, 0x92, 0x0E, 0x18, 0x30, + 0xC9, 0x1B, 0x93, 0x03, 0x82, 0x0A, 0x18, 0x20, 0xC9, 0x1B, 0x18, 0x30, 0xCB, 0x1B, 0xC6, 0x23, + 0x82, 0x04, 0x04, 0x31, 0x99, 0x30, 0xC8, 0x1B, 0x98, 0x30, 0xC8, 0x1B, 0x92, 0x0E, 0x18, 0x30, + 0xCA, 0x1B, 0x93, 0x03, 0x82, 0x0A, 0x18, 0x20, 0xCA, 0x1B, 0x18, 0x30, 0xCC, 0x1B, 0xC6, 0x23, + 0x82, 0x04, 0x04, 0x21, 0x99, 0x20, 0xC8, 0x1B, 0x98, 0x70, 0xC8, 0x1B, 0x82, 0x13, 0x28, 0x30, + 0x8C, 0x1B, 0x24, 0x31, 0x23, 0x33, 0xCC, 0x30, 0x31, 0x00, 0xA9, 0x30, 0x8C, 0x1B, 0xD2, 0x06, + 0xD7, 0xE1, 0x04, 0x31, 0x99, 0x30, 0xC6, 0x1B, 0xF2, 0x05, 0xA9, 0x00, 0x8C, 0x1B, 0x99, 0x00, + 0xC8, 0x1B, 0x18, 0x70, 0xCB, 0x1B, 0x99, 0x70, 0xC9, 0x1B, 0x18, 0x70, 0xCC, 0x1B, 0x99, 0x70, + 0xCA, 0x1B, 0x0C, 0xA0, 0xFC, 0x0A, 0x38, 0xDA, 0x0C, 0x00, 0xD4, 0xD1, 0x9A, 0x90, 0x00, 0x00, + 0x08, 0xC0, 0x00, 0x30, 0x2C, 0xC0, 0x00, 0x49, 0x06, 0x8D, 0x06, 0xBD, 0x06, 0x9D, 0x30, 0x7C, + 0x38, 0x5C, 0x04, 0x00, 0x06, 0x29, 0x0C, 0x30, 0x18, 0x00, 0xB9, 0x51, 0x2C, 0x00, 0xB9, 0x71, + 0x28, 0x00, 0x4B, 0x18, 0x00, 0x00, 0x3C, 0x20, 0x16, 0x00, 0x23, 0x22, 0xC4, 0x21, 0x38, 0x51, + 0x2C, 0x00, 0x38, 0x71, 0x28, 0x00, 0xC2, 0x2F, 0x0C, 0x40, 0xFF, 0x0F, 0x56, 0x47, 0x77, 0x78, + 0x5C, 0x70, 0xFF, 0x0F, 0x3F, 0x37, 0x04, 0x00, 0x23, 0x33, 0x43, 0x63, 0x0C, 0x20, 0xFF, 0x0F, + 0xC4, 0x60, 0x56, 0x25, 0x77, 0x58, 0x5C, 0x50, 0xFF, 0x0F, 0x3F, 0x55, 0x02, 0x00, 0x02, 0x06, + 0xC4, 0x50, 0x32, 0x0E, 0x3F, 0x55, 0x06, 0x00, 0xF2, 0x06, 0xC4, 0x60, 0x82, 0x09, 0xC4, 0x50, + 0x02, 0x07, 0x36, 0x56, 0xCC, 0x50, 0x1E, 0x00, 0x02, 0x03, 0x24, 0xB1, 0x23, 0xBB, 0xC6, 0x47, + 0xC2, 0x05, 0xC6, 0x86, 0x32, 0x08, 0x06, 0x83, 0xF2, 0x06, 0x36, 0x74, 0xC6, 0x7D, 0x23, 0x67, + 0x02, 0x02, 0x06, 0xD6, 0x24, 0x91, 0x23, 0x99, 0xCC, 0x90, 0x50, 0x01, 0x24, 0xC4, 0x92, 0xB8, + 0x3C, 0x80, 0x29, 0x00, 0xCC, 0x80, 0x6C, 0x00, 0xD2, 0x1B, 0x34, 0xD6, 0xCC, 0xD0, 0x39, 0x00, + 0xD2, 0x17, 0xC4, 0xB6, 0xC2, 0x15, 0x18, 0x70, 0xCC, 0x1B, 0x93, 0x07, 0x92, 0x11, 0x18, 0x70, + 0xCB, 0x1B, 0x93, 0x07, 0x92, 0x0D, 0xB8, 0x70, 0x8C, 0x19, 0x92, 0x29, 0x04, 0x61, 0x99, 0x60, + 0xC5, 0x1B, 0x99, 0x00, 0xC4, 0x1B, 0xD7, 0xE1, 0x99, 0x00, 0xC3, 0x1B, 0xF2, 0x20, 0x99, 0x00, + 0xC5, 0x1B, 0x98, 0x70, 0xC3, 0x1B, 0x92, 0x07, 0x98, 0x50, 0xC2, 0x1B, 0x82, 0x04, 0x04, 0x51, + 0x99, 0x50, 0xC3, 0x1B, 0x98, 0x60, 0xC3, 0x1B, 0x82, 0x10, 0x18, 0x50, 0xC4, 0x1B, 0x24, 0x51, + 0x13, 0x55, 0xCC, 0x50, 0x31, 0x00, 0xD2, 0x05, 0x99, 0x50, 0xC4, 0x1B, 0xD7, 0xE1, 0xF2, 0x05, + 0x99, 0x00, 0xC4, 0x1B, 0x99, 0x00, 0xC3, 0x1B, 0x99, 0x00, 0xC2, 0x1B, 0xCB, 0x3D, 0x00, 0x00, + 0xA9, 0x2A, 0x18, 0x03, 0x23, 0x22, 0xC6, 0x2E, 0xA2, 0x05, 0x8B, 0x8E, 0x03, 0x00, 0x04, 0xE0, + 0xF2, 0x06, 0x8B, 0x8E, 0x03, 0x00, 0x14, 0xE1, 0x26, 0xE2, 0xF7, 0xEF, 0x6B, 0xE2, 0x04, 0x00, + 0x06, 0x2E, 0x58, 0xC1, 0x40, 0x00, 0x58, 0x81, 0x30, 0x00, 0x2C, 0x10, 0x50, 0x00, 0xE1, 0xF0, + 0x3C, 0x10, 0x24, 0x00, 0xD9, 0xC1, 0x14, 0x00, 0x38, 0xE0, 0x70, 0x1A, 0xD9, 0x81, 0x04, 0x00, + 0x06, 0xC2, 0x04, 0x30, 0x06, 0x2D, 0x0C, 0x20, 0xF0, 0x0B, 0x0C, 0x40, 0x62, 0x00, 0x0C, 0x90, + 0xFC, 0x0A, 0x0C, 0x80, 0x22, 0x01, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x0C, 0xD0, 0xF0, 0x0B, + 0x26, 0x89, 0x06, 0xBC, 0x38, 0x3B, 0xC4, 0x00, 0x18, 0x2E, 0x13, 0x00, 0x4B, 0x14, 0x00, 0x00, + 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x06, 0x62, 0x30, 0x3B, 0x18, 0x2E, 0x12, 0x00, + 0xB1, 0x61, 0x4B, 0x14, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x28, 0x7E, + 0x1A, 0x00, 0x30, 0x61, 0xC6, 0x27, 0x06, 0xA2, 0x02, 0x02, 0x06, 0xA7, 0x06, 0x26, 0x04, 0x3E, + 0x8B, 0x16, 0x00, 0x00, 0x28, 0x7E, 0x1C, 0x00, 0xC6, 0x27, 0x02, 0x02, 0x06, 0x27, 0x18, 0x3E, + 0x15, 0x00, 0x3F, 0x22, 0x0A, 0x00, 0x4B, 0x14, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0x8B, 0x16, + 0x00, 0x00, 0xA1, 0x2D, 0x24, 0xD2, 0xC6, 0xD8, 0x24, 0xB4, 0x92, 0xCD, 0x06, 0xB9, 0x0C, 0xD0, + 0x20, 0x0C, 0x2C, 0xB0, 0x40, 0x01, 0x38, 0x3C, 0x24, 0x01, 0x18, 0x2E, 0x11, 0x00, 0x4B, 0x14, + 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x38, 0x3C, 0x60, 0x00, 0x06, 0x92, + 0x18, 0x2E, 0x10, 0x00, 0x4B, 0x14, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, + 0x28, 0x7E, 0x16, 0x00, 0x06, 0xA2, 0xC6, 0x27, 0x02, 0x02, 0x06, 0xA7, 0x06, 0x29, 0x0C, 0x30, + 0x17, 0x00, 0x8B, 0x16, 0x00, 0x00, 0x28, 0x7E, 0x18, 0x00, 0xC6, 0x27, 0x02, 0x02, 0x06, 0x27, + 0x18, 0x3E, 0x14, 0x00, 0x3F, 0x22, 0x0A, 0x00, 0x4B, 0x14, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, + 0x8B, 0x16, 0x00, 0x00, 0xA1, 0x2D, 0x24, 0xD2, 0xC6, 0xDB, 0x24, 0xC4, 0x92, 0xCD, 0x58, 0xC1, + 0x14, 0x00, 0x58, 0x81, 0x04, 0x00, 0x2C, 0x10, 0x24, 0x00, 0xE1, 0xF0, 0xE1, 0xF0, 0x00, 0x00, + 0x04, 0x20, 0xE1, 0xF0, 0x38, 0x50, 0x70, 0x1A, 0x3C, 0x10, 0x50, 0x00, 0xD9, 0xC1, 0x40, 0x00, + 0xD9, 0x81, 0x30, 0x00, 0x28, 0xC5, 0xC0, 0x00, 0xB8, 0x70, 0x8C, 0x19, 0x18, 0x95, 0x79, 0x00, + 0xB9, 0x51, 0x08, 0x00, 0x06, 0xD2, 0xB9, 0x03, 0x0C, 0x00, 0x2F, 0x2C, 0x0C, 0x00, 0xB9, 0x03, + 0x08, 0x00, 0xB9, 0x03, 0x04, 0x00, 0xB1, 0x03, 0x06, 0xE3, 0x23, 0xB2, 0x82, 0x0D, 0x26, 0x2C, + 0x04, 0x35, 0x8B, 0x16, 0x00, 0x00, 0x23, 0xC2, 0x2F, 0x2B, 0x0B, 0x00, 0x26, 0x2B, 0x04, 0x35, + 0x8B, 0x16, 0x00, 0x00, 0x23, 0xB2, 0x0C, 0xA0, 0xFC, 0x0A, 0x28, 0x2A, 0x14, 0x03, 0x06, 0x39, + 0x4B, 0x14, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x0C, 0x60, 0x06, 0x03, + 0x26, 0x6A, 0x20, 0x66, 0x04, 0x30, 0x0C, 0x80, 0x28, 0x08, 0x23, 0x22, 0xB1, 0x61, 0x06, 0x7D, + 0x06, 0x43, 0x3C, 0x80, 0x30, 0x00, 0xB9, 0x21, 0x14, 0x00, 0x04, 0x91, 0x0C, 0xA0, 0x80, 0x02, + 0x0C, 0xF0, 0x54, 0x05, 0x53, 0x94, 0x26, 0xA3, 0x26, 0xF3, 0xB9, 0x91, 0x04, 0x00, 0x2F, 0x53, + 0x08, 0x00, 0x06, 0x2D, 0x04, 0x60, 0xB9, 0xA1, 0x0C, 0x00, 0xB9, 0xF1, 0x10, 0x00, 0x38, 0xA1, + 0x0C, 0x00, 0x38, 0x91, 0x10, 0x00, 0x2F, 0xF6, 0x06, 0x00, 0x26, 0xAF, 0x26, 0xF9, 0x20, 0xFF, + 0x20, 0xAA, 0x36, 0xAF, 0x23, 0xAA, 0xC3, 0xFA, 0x02, 0x51, 0x78, 0xA5, 0x30, 0x00, 0x30, 0x91, + 0xC6, 0xA9, 0x02, 0x2A, 0xC4, 0x60, 0x82, 0x05, 0x78, 0x95, 0x2E, 0x00, 0xC6, 0x9A, 0x12, 0x24, + 0x78, 0x95, 0x32, 0x00, 0xC6, 0x9A, 0x32, 0x20, 0xC4, 0x40, 0x82, 0x06, 0x70, 0x95, 0xC6, 0x9A, + 0x12, 0x1B, 0xC4, 0x4D, 0x82, 0x05, 0x78, 0x95, 0x60, 0x00, 0xC6, 0x9A, 0x32, 0x15, 0x0C, 0x90, + 0xFC, 0x0A, 0x38, 0x99, 0xFC, 0x02, 0x04, 0xA1, 0x53, 0xA6, 0x66, 0xA9, 0x0C, 0x90, 0xFC, 0x0A, + 0xB9, 0xA9, 0xFC, 0x02, 0x38, 0xA9, 0x00, 0x03, 0x38, 0x91, 0x04, 0x00, 0x66, 0xA9, 0x0C, 0x90, + 0xFC, 0x0A, 0xB9, 0xA9, 0x00, 0x03, 0x30, 0xA2, 0x26, 0xAF, 0xB1, 0xA2, 0x38, 0xA7, 0x60, 0x00, + 0x26, 0xAF, 0xB9, 0xA7, 0x60, 0x00, 0x38, 0xA1, 0x14, 0x00, 0xC6, 0xFA, 0x02, 0x08, 0x0C, 0x90, + 0xFC, 0x0A, 0x18, 0xA9, 0x25, 0x03, 0x24, 0xA1, 0x99, 0xA9, 0x25, 0x03, 0xC6, 0xFC, 0x02, 0x26, + 0x38, 0xAE, 0x08, 0x00, 0xC6, 0xFB, 0x24, 0xA1, 0xB9, 0xAE, 0x08, 0x00, 0x02, 0x1F, 0x38, 0xFE, + 0x0C, 0x00, 0x24, 0xF1, 0xB9, 0xFE, 0x0C, 0x00, 0xF2, 0x19, 0x16, 0xFA, 0x38, 0xA2, 0xC4, 0x00, + 0x43, 0xFF, 0x26, 0xAF, 0xB9, 0xA2, 0xC4, 0x00, 0x38, 0xA7, 0x24, 0x01, 0xC6, 0xFC, 0x26, 0xAF, + 0xB9, 0xA7, 0x24, 0x01, 0x02, 0x0B, 0x30, 0xAE, 0xC6, 0xFB, 0x24, 0xA1, 0xB1, 0xAE, 0x02, 0x06, + 0x38, 0xFE, 0x04, 0x00, 0x24, 0xF1, 0xB9, 0xFE, 0x04, 0x00, 0x24, 0x61, 0xCC, 0x60, 0x17, 0x00, + 0x24, 0x24, 0x24, 0x52, 0x92, 0x85, 0x38, 0x67, 0x60, 0x00, 0x38, 0x5D, 0xC0, 0x00, 0x24, 0x41, + 0x26, 0x65, 0xB9, 0x6D, 0xC0, 0x00, 0x38, 0x67, 0x24, 0x01, 0x38, 0x5D, 0x84, 0x01, 0xC4, 0x4E, + 0x26, 0x65, 0xB9, 0x6D, 0x84, 0x01, 0x24, 0x74, 0x2C, 0x30, 0x30, 0x00, 0x9A, 0x5F, 0xFF, 0xFF, + 0x0C, 0xA0, 0xFC, 0x0A, 0x38, 0x8A, 0x0C, 0x00, 0x04, 0xE1, 0xD6, 0xE8, 0x9A, 0xD8, 0x00, 0x00, + 0x0C, 0x90, 0x80, 0x02, 0x0C, 0xA0, 0x54, 0x05, 0x06, 0xDE, 0x06, 0xCE, 0x06, 0xBE, 0x70, 0x49, + 0x78, 0x69, 0x02, 0x00, 0x70, 0x5A, 0x78, 0x7A, 0x02, 0x00, 0xB9, 0x41, 0x20, 0x00, 0x06, 0x2B, + 0x0C, 0x30, 0x18, 0x00, 0xB9, 0x51, 0x1C, 0x00, 0xB9, 0x61, 0x24, 0x00, 0xB9, 0x71, 0x28, 0x00, + 0x4B, 0x18, 0x00, 0x00, 0x3C, 0x20, 0x16, 0x00, 0x23, 0x22, 0xC4, 0x21, 0x38, 0x41, 0x20, 0x00, + 0x38, 0x51, 0x1C, 0x00, 0x38, 0x61, 0x24, 0x00, 0x38, 0x71, 0x28, 0x00, 0xC2, 0x2B, 0x5C, 0x40, + 0xFF, 0x0F, 0x5C, 0x50, 0xFF, 0x0F, 0x3F, 0x25, 0x04, 0x00, 0x23, 0x22, 0xC3, 0x32, 0x5C, 0x60, + 0xFF, 0x0F, 0x5C, 0x70, 0xFF, 0x0F, 0x36, 0x67, 0x02, 0x06, 0xC4, 0x60, 0x32, 0x0E, 0x3F, 0x66, + 0x03, 0x00, 0xF2, 0x06, 0xC4, 0x30, 0x82, 0x09, 0xC4, 0x60, 0x02, 0x07, 0x36, 0x63, 0xCC, 0x60, + 0x14, 0x00, 0x02, 0x03, 0x24, 0xC1, 0x23, 0xCC, 0xC6, 0x45, 0xC2, 0x05, 0xC6, 0xD3, 0x32, 0x0A, + 0x06, 0xD2, 0xF2, 0x08, 0x36, 0x54, 0x23, 0x55, 0xC6, 0x5E, 0x06, 0x75, 0xB2, 0x02, 0x06, 0x7E, + 0x23, 0xE7, 0x24, 0xB1, 0x23, 0xBB, 0xCC, 0xB0, 0x50, 0x01, 0x24, 0x92, 0x24, 0xA2, 0x92, 0xB0, + 0xCC, 0xD0, 0x2C, 0x01, 0xC2, 0x05, 0x04, 0x61, 0xA9, 0x60, 0x8E, 0x1B, 0xF2, 0x03, 0xA9, 0x00, + 0x8E, 0x1B, 0x28, 0x40, 0x76, 0x1A, 0x26, 0x44, 0x0C, 0x70, 0x54, 0x05, 0x0C, 0xF0, 0x80, 0x02, + 0x26, 0x74, 0x26, 0x4F, 0x20, 0x57, 0x20, 0x64, 0x5C, 0x50, 0xFF, 0x0F, 0x5C, 0x60, 0xFF, 0x0F, + 0xC6, 0x56, 0x04, 0x70, 0x02, 0x04, 0x3F, 0x76, 0x05, 0x00, 0x23, 0x77, 0x98, 0x50, 0xC5, 0x1B, + 0x06, 0x46, 0x82, 0x09, 0x0C, 0x50, 0x20, 0x00, 0x04, 0x35, 0x0C, 0x20, 0xFA, 0x00, 0x0C, 0x60, + 0x14, 0x00, 0xF2, 0x08, 0x0C, 0x50, 0x30, 0x00, 0x04, 0x3A, 0x0C, 0x20, 0x2C, 0x01, 0x0C, 0x60, + 0x19, 0x00, 0xC6, 0xD6, 0xC2, 0x4A, 0xC6, 0xD2, 0xB2, 0x0E, 0xC6, 0xC3, 0xC2, 0x0C, 0xC6, 0x75, + 0xC2, 0x0A, 0x28, 0x50, 0x96, 0x1B, 0xCC, 0x50, 0x1F, 0x00, 0xD2, 0x05, 0x28, 0x50, 0x94, 0x1B, + 0xC4, 0x54, 0xC2, 0x18, 0xC6, 0xD6, 0xC2, 0x39, 0xCC, 0xD0, 0x5F, 0x00, 0xD2, 0x36, 0xC4, 0xC1, + 0xC2, 0x34, 0xC4, 0x76, 0xC2, 0x32, 0xA8, 0x70, 0x96, 0x1B, 0x92, 0x2F, 0x28, 0x70, 0x94, 0x1B, + 0xC4, 0x72, 0xD2, 0x2B, 0xA8, 0x70, 0x9A, 0x1B, 0x92, 0x28, 0x28, 0x70, 0x98, 0x1B, 0xC4, 0x72, + 0xD2, 0x24, 0xCC, 0xE0, 0x9F, 0x00, 0xD2, 0x21, 0x38, 0x70, 0xFC, 0x0A, 0xCC, 0x70, 0x64, 0x00, + 0xC2, 0x1C, 0xB8, 0x70, 0x8C, 0x19, 0x92, 0x1B, 0x28, 0x50, 0x90, 0x1B, 0x24, 0x51, 0x23, 0x55, + 0xC4, 0x55, 0xA9, 0x50, 0x90, 0x1B, 0xC2, 0x13, 0x1C, 0x50, 0x6A, 0x00, 0x99, 0x50, 0xAC, 0x1B, + 0xA9, 0x00, 0x90, 0x1B, 0x08, 0x70, 0x08, 0x00, 0x66, 0x78, 0x0C, 0x50, 0xFC, 0x0A, 0xB9, 0x75, + 0x0C, 0x00, 0x99, 0x00, 0xC5, 0x1B, 0xF2, 0x03, 0xA9, 0x00, 0x90, 0x1B, 0xB8, 0x70, 0x8C, 0x19, + 0x8A, 0xCF, 0x00, 0x00, 0x04, 0xC0, 0x0C, 0xD0, 0x50, 0x02, 0x0C, 0xE0, 0x24, 0x05, 0xB9, 0xC1, + 0x04, 0x00, 0xB1, 0xC1, 0x06, 0xBC, 0x0C, 0x50, 0x60, 0x00, 0x26, 0x5D, 0x70, 0x55, 0x70, 0x4E, + 0x78, 0xAE, 0x2E, 0x00, 0xB9, 0x51, 0x14, 0x00, 0x0C, 0x60, 0x30, 0x00, 0x0C, 0x70, 0x30, 0x00, + 0x26, 0x6D, 0x26, 0x7E, 0x70, 0x66, 0x70, 0x77, 0x78, 0x8E, 0x32, 0x00, 0xB9, 0x61, 0x0C, 0x00, + 0x0C, 0x50, 0x60, 0x00, 0x26, 0x5E, 0x78, 0x6D, 0x2E, 0x00, 0x70, 0x55, 0xB9, 0x71, 0x10, 0x00, + 0x78, 0x7D, 0x32, 0x00, 0x70, 0x9D, 0xB9, 0x51, 0x18, 0x00, 0x06, 0x2B, 0x0C, 0x30, 0x18, 0x00, + 0xB9, 0x41, 0x20, 0x00, 0xB9, 0x61, 0x24, 0x00, 0xB9, 0x71, 0x28, 0x00, 0x4B, 0x18, 0x00, 0x00, + 0x34, 0x21, 0x23, 0x22, 0xCC, 0x20, 0x14, 0x00, 0x38, 0x41, 0x20, 0x00, 0x38, 0x61, 0x24, 0x00, + 0x38, 0x71, 0x28, 0x00, 0xD2, 0x61, 0x1C, 0x50, 0x18, 0x00, 0x26, 0x5B, 0xCC, 0x50, 0x1F, 0x01, + 0xD2, 0x5B, 0x0C, 0x20, 0xFF, 0x0F, 0x0C, 0x50, 0xFF, 0x0F, 0x56, 0x28, 0x56, 0x59, 0x38, 0x81, + 0x0C, 0x00, 0x38, 0x91, 0x10, 0x00, 0x5C, 0x80, 0xFF, 0x0F, 0x5C, 0x90, 0xFF, 0x0F, 0x0C, 0xF0, + 0xFF, 0x0F, 0x0C, 0x30, 0xFF, 0x0F, 0x3F, 0x99, 0x08, 0x00, 0x56, 0xF6, 0x56, 0x37, 0x38, 0x61, + 0x18, 0x00, 0x38, 0x71, 0x14, 0x00, 0xC4, 0x90, 0x5C, 0xA0, 0xFF, 0x0F, 0x5C, 0x40, 0xFF, 0x0F, + 0x5C, 0x70, 0xFF, 0x0F, 0x5C, 0x60, 0xFF, 0x0F, 0x02, 0x1D, 0x36, 0xFA, 0x3C, 0xF0, 0x15, 0x00, + 0xCC, 0xF0, 0x30, 0x00, 0xD2, 0x31, 0x36, 0x32, 0xCC, 0x30, 0x14, 0x00, 0x02, 0x2D, 0x36, 0x54, + 0xCC, 0x50, 0x14, 0x00, 0x02, 0x29, 0x36, 0x76, 0xCC, 0x70, 0x14, 0x00, 0x02, 0x25, 0x30, 0x71, + 0xCC, 0x90, 0x46, 0x00, 0x24, 0x71, 0x23, 0x77, 0xB1, 0x71, 0x02, 0x1E, 0x24, 0xC1, 0x23, 0xCC, + 0xF2, 0x1B, 0x3F, 0xFF, 0x0A, 0x00, 0xCC, 0xF0, 0x1E, 0x00, 0x02, 0x16, 0x3F, 0x33, 0x02, 0x00, + 0xCC, 0x30, 0x1E, 0x00, 0x02, 0x11, 0x3F, 0x55, 0x04, 0x00, 0xCC, 0x50, 0x1E, 0x00, 0x02, 0x0C, + 0x3F, 0x77, 0x06, 0x00, 0xCC, 0x70, 0x1E, 0x00, 0x02, 0x07, 0x38, 0x71, 0x04, 0x00, 0x24, 0x71, + 0x23, 0x77, 0xB9, 0x71, 0x04, 0x00, 0x24, 0xB1, 0x23, 0xBB, 0xCC, 0xB0, 0x50, 0x01, 0x24, 0xD2, + 0x24, 0xE2, 0x9A, 0x62, 0xFF, 0xFF, 0x30, 0x61, 0xC4, 0x64, 0xD2, 0x20, 0x38, 0x71, 0x04, 0x00, + 0x3C, 0x70, 0x11, 0x00, 0xCC, 0x70, 0x3E, 0x00, 0xD2, 0x19, 0xC4, 0xC1, 0xD2, 0x17, 0x98, 0x70, + 0xAC, 0x1B, 0x92, 0x14, 0x38, 0x70, 0xFC, 0x0A, 0xCC, 0x70, 0x64, 0x00, 0xC2, 0x11, 0x28, 0x50, + 0x92, 0x1B, 0x24, 0x51, 0x23, 0x55, 0xCC, 0x50, 0x32, 0x00, 0xA9, 0x50, 0x92, 0x1B, 0xC2, 0x08, + 0x0C, 0x50, 0x64, 0x00, 0x99, 0x50, 0xAC, 0x1B, 0xF2, 0x01, 0xA9, 0x00, 0x92, 0x1B, 0xCB, 0xE4, + 0x04, 0x00, 0x38, 0x91, 0x08, 0x00, 0x28, 0x79, 0x38, 0x00, 0x0C, 0xA0, 0xFC, 0x0A, 0xA9, 0x7A, + 0x14, 0x00, 0x58, 0xC1, 0x40, 0x00, 0x58, 0x81, 0x30, 0x00, 0x2C, 0x10, 0x50, 0x00, 0xE1, 0xF0, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x0C, 0xE0, 0x17, 0x00, 0x0C, 0xD0, 0x80, 0x02, 0x06, 0x2E, + 0xEB, 0xE0, 0x04, 0x00, 0xC4, 0x20, 0x92, 0x05, 0x2F, 0x7E, 0x0E, 0x00, 0x26, 0x7D, 0xA1, 0x07, + 0x2C, 0xE0, 0x18, 0x00, 0xCC, 0xE0, 0x67, 0x01, 0x92, 0xF3, 0x6B, 0xE2, 0x04, 0x00, 0x50, 0xC1, + 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x18, 0x00, 0xC9, 0xE1, 0x10, 0x00, + 0x0C, 0x40, 0x88, 0x01, 0x06, 0x2E, 0x0C, 0x20, 0x78, 0x15, 0x04, 0x30, 0x0C, 0xF0, 0xB0, 0x01, + 0xF1, 0xF0, 0x06, 0x31, 0x06, 0x2E, 0x0C, 0x20, 0x78, 0x15, 0x2B, 0xCB, 0x03, 0x00, 0x8B, 0xF5, + 0x03, 0x00, 0x06, 0x2E, 0x0C, 0x20, 0x78, 0x15, 0x0B, 0xC2, 0x03, 0x00, 0x38, 0x20, 0xFC, 0x16, + 0x06, 0x31, 0x6B, 0x03, 0x04, 0x00, 0x48, 0xE1, 0x10, 0x00, 0x2C, 0x10, 0x18, 0x00, 0xE1, 0xF0, + 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0xD1, 0x81, 0x0C, 0x30, 0x20, 0x0C, 0x04, 0x60, + 0x0C, 0xC0, 0x80, 0x02, 0x0C, 0xE0, 0x54, 0x05, 0x0C, 0xA0, 0xFC, 0x0A, 0x70, 0xB3, 0x04, 0x70, + 0x06, 0x57, 0x2F, 0xDC, 0x06, 0x00, 0x2F, 0xFE, 0x06, 0x00, 0x2F, 0x27, 0x0D, 0x00, 0x2F, 0x47, + 0x0F, 0x00, 0x70, 0x92, 0x70, 0x44, 0xCC, 0x50, 0x17, 0x00, 0x3F, 0x44, 0x09, 0x00, 0x36, 0x4B, + 0x82, 0x06, 0x2F, 0x9A, 0x07, 0x00, 0x78, 0x99, 0xF4, 0x00, 0x36, 0x49, 0x86, 0x44, 0x32, 0x02, + 0x04, 0x40, 0x24, 0x51, 0xCC, 0x50, 0x18, 0x00, 0xA1, 0x42, 0x24, 0x72, 0x92, 0xE7, 0x2C, 0x60, + 0x30, 0x00, 0xCC, 0x60, 0xA0, 0x02, 0x24, 0x32, 0x92, 0xDA, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, + 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0xC4, 0x20, 0x0C, 0x70, + 0xFC, 0x0A, 0x38, 0x67, 0x0C, 0x00, 0x82, 0x15, 0x64, 0x61, 0xB9, 0x67, 0x0C, 0x00, 0x08, 0x70, + 0x00, 0x80, 0x2C, 0x70, 0x20, 0xE0, 0xB9, 0x70, 0x70, 0x1A, 0x08, 0x70, 0x00, 0x80, 0x2C, 0x70, + 0x04, 0xDE, 0xB9, 0x70, 0x6C, 0x1A, 0x08, 0x70, 0x00, 0x80, 0x2C, 0x70, 0xC4, 0xDC, 0xF2, 0x15, + 0x14, 0x22, 0x56, 0x62, 0xB9, 0x67, 0x0C, 0x00, 0x08, 0x70, 0x00, 0x80, 0x2C, 0x70, 0x44, 0xDF, + 0xB9, 0x70, 0x70, 0x1A, 0x08, 0x70, 0x00, 0x80, 0x2C, 0x70, 0xA4, 0xDE, 0xB9, 0x70, 0x6C, 0x1A, + 0x08, 0x70, 0x00, 0x80, 0x2C, 0x70, 0x64, 0xDD, 0xB9, 0x70, 0x68, 0x1A, 0xE1, 0xF0, 0x00, 0x00, + 0x0C, 0x70, 0xFC, 0x0A, 0x99, 0x07, 0x59, 0x01, 0x99, 0x07, 0x58, 0x01, 0xE1, 0xF0, 0x00, 0x00, + 0x38, 0x60, 0x70, 0x1A, 0x0C, 0x70, 0xFC, 0x0A, 0x18, 0x57, 0x56, 0x01, 0x18, 0x66, 0xC2, 0x00, + 0xC6, 0x56, 0xA2, 0x15, 0x38, 0x60, 0x6C, 0x19, 0xCC, 0x60, 0x1F, 0x03, 0xD2, 0x17, 0x38, 0x67, + 0x0C, 0x00, 0x6C, 0x60, 0x00, 0x04, 0xB9, 0x67, 0x0C, 0x00, 0x04, 0x61, 0x99, 0x60, 0xB4, 0x1B, + 0x18, 0x60, 0xAB, 0x1B, 0x24, 0x61, 0x99, 0x60, 0xAB, 0x1B, 0xF2, 0x08, 0x38, 0x67, 0x0C, 0x00, + 0x1C, 0x50, 0x01, 0x04, 0x56, 0x65, 0xB9, 0x67, 0x0C, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x34, 0x00, + 0xD9, 0x81, 0x14, 0x00, 0x06, 0xB3, 0x38, 0x30, 0x70, 0x1A, 0xD9, 0xC1, 0x24, 0x00, 0x06, 0xC2, + 0xB1, 0x31, 0x4B, 0x3E, 0x00, 0x00, 0x0C, 0x30, 0x18, 0x00, 0x4B, 0x18, 0x00, 0x00, 0x23, 0x82, + 0x4B, 0x3E, 0x00, 0x00, 0x0C, 0x30, 0x18, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x06, 0x74, 0x0C, 0x70, + 0xFC, 0x0A, 0x38, 0x97, 0x0C, 0x00, 0x23, 0x52, 0xD4, 0x91, 0x82, 0x05, 0x04, 0x6A, 0x0C, 0xD0, + 0xFA, 0x00, 0xF2, 0x04, 0x04, 0x68, 0x0C, 0xD0, 0x64, 0x00, 0x38, 0xEB, 0x08, 0x00, 0xB9, 0x41, + 0x0C, 0x00, 0x06, 0x2C, 0x0C, 0x30, 0x42, 0x01, 0xB9, 0x51, 0x08, 0x00, 0xB9, 0x61, 0x04, 0x00, + 0xB9, 0x71, 0x10, 0x00, 0xAB, 0x15, 0x00, 0x00, 0xC6, 0x2D, 0x30, 0xCB, 0x38, 0xDB, 0x04, 0x00, + 0x38, 0x41, 0x0C, 0x00, 0x38, 0xBB, 0x0C, 0x00, 0x38, 0x51, 0x08, 0x00, 0x38, 0x61, 0x04, 0x00, + 0x38, 0x71, 0x10, 0x00, 0x06, 0xA2, 0xDA, 0xE4, 0x01, 0x00, 0xCC, 0xD0, 0x14, 0x00, 0x02, 0x0B, + 0xCC, 0xC0, 0x40, 0x00, 0x02, 0x08, 0xC4, 0xB3, 0x12, 0x06, 0xCC, 0xE0, 0x1F, 0x00, 0x0A, 0xD8, + 0x01, 0x00, 0xF2, 0x03, 0xC4, 0xE0, 0x02, 0x1A, 0x2F, 0x3E, 0x0E, 0x00, 0xC6, 0xC3, 0x02, 0x0B, + 0xC4, 0xD3, 0x02, 0x14, 0xCC, 0xE0, 0x1F, 0x00, 0x12, 0x11, 0xC6, 0xB6, 0x2A, 0xC9, 0x01, 0x00, + 0xFA, 0xE4, 0x02, 0x00, 0xCC, 0xC0, 0x19, 0x00, 0x02, 0x09, 0xC4, 0xD3, 0x02, 0x07, 0xCC, 0xE0, + 0x1F, 0x00, 0x12, 0x04, 0xC6, 0xB6, 0x2A, 0xBC, 0x01, 0x00, 0xC6, 0xD6, 0x02, 0x1D, 0xCC, 0xC0, + 0x14, 0x00, 0x02, 0x0A, 0xCC, 0xE0, 0x13, 0x00, 0x12, 0x07, 0xC4, 0xB2, 0x12, 0x05, 0xCC, 0xA0, + 0x13, 0x00, 0xDA, 0xAE, 0x01, 0x00, 0xC4, 0xDA, 0x02, 0x11, 0x14, 0x31, 0x26, 0x3B, 0xC4, 0x32, + 0xD2, 0x0D, 0xCC, 0xC0, 0x1E, 0x00, 0x02, 0x0A, 0xCC, 0xE0, 0x1D, 0x00, 0x12, 0x07, 0xC4, 0xAF, + 0xDA, 0x9F, 0x01, 0x00, 0xF2, 0x03, 0xC4, 0xD3, 0x02, 0x0F, 0xC4, 0xB2, 0x02, 0x0D, 0xCC, 0xE0, + 0x13, 0x00, 0x12, 0x0A, 0xC6, 0xB6, 0x32, 0x08, 0xC6, 0xCE, 0x02, 0x06, 0xC6, 0xDB, 0x02, 0x04, + 0xC6, 0xA6, 0xBA, 0x8E, 0x01, 0x00, 0xCC, 0xC0, 0x70, 0x00, 0x02, 0x0B, 0xCC, 0xD0, 0x40, 0x00, + 0x02, 0x08, 0xCC, 0xE0, 0x2F, 0x00, 0x12, 0x05, 0xCC, 0xA0, 0x20, 0x00, 0xDA, 0x81, 0x01, 0x00, + 0x38, 0x60, 0xFC, 0x0A, 0xCC, 0x60, 0xF3, 0x01, 0xD2, 0x11, 0xCC, 0xC0, 0x40, 0x00, 0x02, 0x0E, + 0xCC, 0xD0, 0x20, 0x00, 0x02, 0x0B, 0xCC, 0xE0, 0x2F, 0x00, 0x12, 0x08, 0xCC, 0xB0, 0x15, 0x00, + 0x12, 0x05, 0xCC, 0xA0, 0x10, 0x00, 0xDA, 0x6C, 0x01, 0x00, 0xC4, 0x90, 0x92, 0x6A, 0xC4, 0x85, + 0xC2, 0x11, 0xC4, 0x59, 0xD2, 0x0F, 0xCC, 0xC0, 0x10, 0x00, 0x02, 0x1A, 0xC4, 0xDA, 0x02, 0x0A, + 0xCC, 0xE0, 0x1F, 0x00, 0x12, 0x07, 0xC4, 0xB5, 0x12, 0x05, 0xCC, 0xA0, 0x30, 0x00, 0xDA, 0x5C, + 0x01, 0x00, 0xCC, 0xC0, 0x40, 0x00, 0x02, 0x0C, 0xCC, 0xD0, 0x30, 0x00, 0x02, 0x09, 0x14, 0x61, + 0x26, 0x6B, 0xC4, 0x6E, 0xD2, 0x05, 0xCC, 0xA0, 0x30, 0x00, 0xDA, 0x4E, 0x01, 0x00, 0xC6, 0xDB, + 0x02, 0x48, 0xCC, 0xD0, 0x26, 0x00, 0x02, 0x08, 0xCC, 0xB0, 0x21, 0x00, 0x12, 0x05, 0xCC, 0xA0, + 0x38, 0x00, 0xDA, 0x42, 0x01, 0x00, 0xC4, 0xDE, 0x02, 0x13, 0xC6, 0xCE, 0x0A, 0x5C, 0x02, 0x00, + 0xCC, 0xE0, 0x29, 0x00, 0x1A, 0x5E, 0x02, 0x00, 0x14, 0x61, 0x26, 0x6B, 0xC4, 0x66, 0xDA, 0x59, + 0x02, 0x00, 0xCC, 0xA0, 0x22, 0x00, 0xDA, 0x30, 0x01, 0x00, 0xFA, 0x53, 0x02, 0x00, 0xCC, 0xD0, + 0x15, 0x00, 0x02, 0x0D, 0xC6, 0xCE, 0x12, 0x04, 0xCC, 0xC0, 0x30, 0x00, 0x02, 0x17, 0xCC, 0xB0, + 0x11, 0x00, 0x12, 0x05, 0xCC, 0xA0, 0x27, 0x00, 0xDA, 0x1F, 0x01, 0x00, 0xCC, 0xD0, 0x10, 0x00, + 0x02, 0x0D, 0xC6, 0xCE, 0x02, 0x16, 0xCC, 0xE0, 0x35, 0x00, 0x1A, 0x41, 0x02, 0x00, 0xCC, 0xA0, + 0x27, 0x00, 0xDA, 0x12, 0x01, 0x00, 0xFA, 0x3B, 0x02, 0x00, 0xCC, 0xD0, 0x13, 0x00, 0x02, 0x09, + 0xC6, 0xCE, 0x02, 0x07, 0xC4, 0xB7, 0x12, 0x05, 0xCC, 0xA0, 0x20, 0x00, 0xDA, 0x05, 0x01, 0x00, + 0xCC, 0xC0, 0x70, 0x00, 0x02, 0x0F, 0xCC, 0xD0, 0x40, 0x00, 0x02, 0x0F, 0xCC, 0xE0, 0x4F, 0x00, + 0x12, 0x0E, 0xCC, 0xB0, 0x29, 0x00, 0x12, 0x0B, 0xCC, 0xA0, 0x50, 0x00, 0xDA, 0xF1, 0x00, 0x00, + 0xF2, 0x06, 0xCC, 0xC0, 0x20, 0x00, 0x02, 0x3C, 0xC4, 0xDA, 0x02, 0x0A, 0x1C, 0x60, 0x17, 0x00, + 0x26, 0x6E, 0xCC, 0x60, 0x28, 0x00, 0xD2, 0x04, 0xC4, 0xBF, 0x0A, 0xE2, 0x00, 0x00, 0xCC, 0xC0, + 0x40, 0x00, 0x02, 0x0F, 0xCC, 0xD0, 0x18, 0x00, 0x02, 0x20, 0xCC, 0xE0, 0x40, 0x00, 0x02, 0x0C, + 0xCC, 0xB0, 0x1F, 0x00, 0x12, 0x09, 0xCC, 0xA0, 0x28, 0x00, 0xDA, 0xD2, 0x00, 0x00, 0xF2, 0x04, + 0xCC, 0xC0, 0x30, 0x00, 0x02, 0x0F, 0xCC, 0xD0, 0x20, 0x00, 0x02, 0x0F, 0xCC, 0xE0, 0xC0, 0x00, + 0x02, 0x45, 0xCC, 0xB0, 0x7F, 0x00, 0x12, 0x42, 0xCC, 0xA0, 0x28, 0x00, 0xDA, 0xC1, 0x00, 0x00, + 0xF2, 0x3D, 0xCC, 0xC0, 0x20, 0x00, 0x02, 0x0C, 0xC4, 0xD1, 0x12, 0x38, 0xC4, 0xEF, 0x12, 0x0D, + 0xC4, 0xB2, 0x12, 0x0B, 0xCC, 0xA0, 0x1A, 0x00, 0xDA, 0xB3, 0x00, 0x00, 0xF2, 0x06, 0xCC, 0xC0, + 0x18, 0x00, 0x02, 0x21, 0xC4, 0xD1, 0x12, 0x2A, 0x2F, 0x6E, 0x0E, 0x00, 0x26, 0x6E, 0x06, 0x26, + 0x57, 0x22, 0x36, 0x26, 0x57, 0x21, 0x0C, 0x30, 0x64, 0x00, 0xB9, 0x41, 0x0C, 0x00, 0xB9, 0x51, + 0x08, 0x00, 0xB9, 0x71, 0x10, 0x00, 0x8B, 0x16, 0x00, 0x00, 0x23, 0x22, 0xC6, 0xC2, 0x38, 0x41, + 0x0C, 0x00, 0x38, 0x51, 0x08, 0x00, 0x38, 0x71, 0x10, 0x00, 0x02, 0x10, 0xC4, 0xB2, 0x0A, 0x90, + 0x00, 0x00, 0xF2, 0x0C, 0xC4, 0xCF, 0x12, 0x0A, 0xC4, 0xD4, 0x12, 0x08, 0xCC, 0xE0, 0x80, 0x00, + 0x02, 0x05, 0xCC, 0xB0, 0x40, 0x00, 0x1A, 0x84, 0x00, 0x00, 0x18, 0x67, 0x8C, 0x06, 0xC4, 0x62, + 0xC2, 0x0B, 0xCC, 0xC0, 0x10, 0x00, 0x02, 0x0A, 0xC4, 0xD4, 0x12, 0x08, 0xC4, 0xEF, 0x12, 0x06, + 0xC4, 0xB4, 0x02, 0x76, 0xF2, 0x05, 0xC4, 0x62, 0x92, 0x10, 0xC6, 0xCE, 0x02, 0x0E, 0xC6, 0xDB, + 0x02, 0x0C, 0xCC, 0xC0, 0x20, 0x00, 0x02, 0x12, 0xC4, 0xD8, 0x02, 0x0A, 0xCC, 0xE0, 0x20, 0x00, + 0x02, 0x07, 0xC4, 0xB8, 0x12, 0x65, 0xF2, 0x04, 0xCC, 0xC0, 0x20, 0x00, 0x02, 0x07, 0xC4, 0xD4, + 0x12, 0x05, 0xC4, 0xE4, 0x12, 0x03, 0xC4, 0xB4, 0x02, 0x5B, 0x04, 0x60, 0xC6, 0x96, 0x9A, 0xEE, + 0x00, 0x00, 0xCC, 0x80, 0x16, 0x00, 0x06, 0x69, 0x8A, 0xE9, 0x00, 0x00, 0xC4, 0x80, 0x8A, 0xE6, + 0x00, 0x00, 0xC4, 0x5D, 0x8A, 0xE3, 0x00, 0x00, 0xC4, 0x50, 0x8A, 0xE0, 0x00, 0x00, 0xC4, 0xC5, + 0x02, 0x31, 0xC4, 0xD1, 0x02, 0x07, 0xC4, 0xE0, 0x12, 0x05, 0xC4, 0xB0, 0x12, 0x03, 0xC4, 0xA4, + 0xD2, 0x43, 0xC4, 0xCE, 0x02, 0x19, 0xC4, 0xD0, 0x02, 0x08, 0xC4, 0xE6, 0x12, 0x06, 0xC4, 0xB9, + 0x12, 0x04, 0xCC, 0xA0, 0x10, 0x00, 0xD2, 0x38, 0xCC, 0xC0, 0x40, 0x00, 0x02, 0x0D, 0xCC, 0xD0, + 0x14, 0x00, 0x02, 0x0D, 0xCC, 0xE0, 0x2F, 0x00, 0x12, 0x0C, 0xC4, 0xB6, 0x12, 0x0A, 0xCC, 0xA0, + 0x2A, 0x00, 0xD2, 0x2A, 0xF2, 0x06, 0xCC, 0xC0, 0x20, 0x00, 0x02, 0x0C, 0xC4, 0xDA, 0x02, 0x0F, + 0xCC, 0xE0, 0x1F, 0x00, 0x12, 0x10, 0xC4, 0xB9, 0x12, 0x0E, 0xCC, 0xA0, 0x18, 0x00, 0xD2, 0x1C, + 0xF2, 0x0A, 0xCC, 0xC0, 0x1A, 0x00, 0x04, 0x60, 0x0A, 0xA9, 0x00, 0x00, 0xC4, 0xD8, 0x04, 0x60, + 0x0A, 0xA5, 0x00, 0x00, 0xCC, 0xE0, 0x19, 0x00, 0x04, 0x60, 0x1A, 0xA0, 0x00, 0x00, 0xC4, 0xB4, + 0x1A, 0x9D, 0x00, 0x00, 0xCC, 0xA0, 0x10, 0x00, 0xCA, 0x99, 0x00, 0x00, 0xF2, 0x05, 0xC4, 0x90, + 0x04, 0x61, 0x9A, 0x94, 0x00, 0x00, 0x14, 0x66, 0x26, 0x6E, 0xC4, 0x69, 0xD2, 0x0A, 0x14, 0x61, + 0x26, 0x6B, 0xC4, 0x63, 0xD2, 0x17, 0xC4, 0xCF, 0x04, 0x60, 0x0A, 0x88, 0x00, 0x00, 0xF2, 0x12, + 0xC4, 0xE1, 0x12, 0x10, 0xC4, 0xB0, 0x12, 0x0E, 0x1C, 0x60, 0x11, 0x00, 0x26, 0x6C, 0xC4, 0x6E, + 0xD2, 0x09, 0x14, 0x63, 0x26, 0x6D, 0xC4, 0x6C, 0xD2, 0x05, 0xCC, 0xA0, 0x1F, 0x00, 0x04, 0x60, + 0xC2, 0x75, 0xC4, 0x8B, 0xD2, 0x42, 0xC4, 0x58, 0xC2, 0x40, 0xCC, 0xC0, 0x35, 0x00, 0x12, 0x0A, + 0xC4, 0xDF, 0x12, 0x08, 0xCC, 0xE0, 0x13, 0x00, 0x02, 0x05, 0xCC, 0xA0, 0x23, 0x00, 0x04, 0x60, + 0xC2, 0x65, 0xC4, 0x59, 0xC2, 0x10, 0xCC, 0xC0, 0x3F, 0x00, 0x12, 0x0D, 0xCC, 0xD0, 0x19, 0x00, + 0x12, 0x0A, 0xCC, 0xE0, 0x1A, 0x00, 0x02, 0x07, 0xC4, 0xB0, 0x02, 0x05, 0xCC, 0xA0, 0x27, 0x00, + 0x04, 0x60, 0xC2, 0x54, 0xCC, 0xC0, 0x25, 0x00, 0x12, 0x15, 0xC4, 0xD3, 0x12, 0x07, 0xC4, 0xED, + 0x02, 0x05, 0xCC, 0xA0, 0x19, 0x00, 0x04, 0x60, 0xC2, 0x49, 0xCC, 0xC0, 0x19, 0x00, 0x12, 0x0A, + 0xC4, 0xD2, 0x12, 0x0B, 0xC4, 0xE5, 0x02, 0x09, 0xCC, 0xA0, 0x2F, 0x00, 0x04, 0x60, 0xC2, 0x3E, + 0xF2, 0x04, 0xCC, 0xC0, 0x2F, 0x00, 0x12, 0x09, 0xC4, 0xD9, 0x12, 0x07, 0xC4, 0xED, 0x02, 0x05, + 0xCC, 0xA0, 0x1F, 0x00, 0x04, 0x60, 0xC2, 0x32, 0xCC, 0xC0, 0x45, 0x00, 0x12, 0x0D, 0xCC, 0xD0, + 0x1F, 0x00, 0x12, 0x0A, 0xCC, 0xE0, 0x30, 0x00, 0x02, 0x07, 0xC4, 0xB4, 0x02, 0x05, 0xCC, 0xA0, + 0x2F, 0x00, 0x04, 0x60, 0xC2, 0x23, 0x18, 0x67, 0x8C, 0x06, 0xC4, 0x62, 0xD2, 0x0E, 0xCC, 0xC0, + 0x14, 0x00, 0x12, 0x0B, 0xC4, 0xD5, 0x12, 0x09, 0xC4, 0xE3, 0x02, 0x0B, 0xC4, 0xB0, 0x02, 0x05, + 0xCC, 0xA0, 0x29, 0x00, 0x04, 0x60, 0xC2, 0x12, 0xCC, 0xE0, 0x13, 0x00, 0x04, 0x61, 0x12, 0x0E, + 0x04, 0x61, 0xC6, 0xB6, 0x12, 0x0B, 0xCC, 0xC0, 0x13, 0x00, 0x12, 0x08, 0xC6, 0xD6, 0x12, 0x06, + 0xCC, 0xA0, 0x13, 0x00, 0xD2, 0x02, 0x04, 0x60, 0x23, 0x66, 0xB8, 0x30, 0x8C, 0x19, 0x82, 0x4E, + 0x38, 0x40, 0xFC, 0x0A, 0x04, 0x60, 0xCC, 0x40, 0x32, 0x00, 0xC2, 0x48, 0xCC, 0xC0, 0x50, 0x00, + 0x02, 0x1B, 0xCC, 0xD0, 0x10, 0x00, 0x02, 0x09, 0xC4, 0xE9, 0x12, 0x07, 0xC6, 0xB6, 0x12, 0x05, + 0xCC, 0xA0, 0x20, 0x00, 0x04, 0x61, 0xD2, 0x3A, 0xCC, 0xC0, 0x80, 0x00, 0x02, 0x0F, 0xCC, 0xD0, + 0x30, 0x00, 0x02, 0x0C, 0xC4, 0xEF, 0x12, 0x0A, 0xC4, 0xB0, 0x12, 0x08, 0xCC, 0xA0, 0x20, 0x00, + 0x04, 0x61, 0xD2, 0x2C, 0xF2, 0x03, 0xC4, 0xC4, 0x02, 0x0A, 0xC4, 0xD0, 0x92, 0x08, 0xC4, 0xE2, + 0x12, 0x06, 0xC4, 0xB0, 0x12, 0x04, 0xC4, 0xA8, 0x04, 0x61, 0xD2, 0x20, 0x04, 0x60, 0xC6, 0x96, + 0x92, 0x1D, 0xCC, 0xC0, 0x1A, 0x00, 0x02, 0x0B, 0xC4, 0xD3, 0x12, 0x0C, 0xC4, 0xE4, 0x12, 0x0A, + 0xC6, 0xB6, 0x12, 0x08, 0xC4, 0xA8, 0x04, 0x61, 0xD2, 0x11, 0xF2, 0x04, 0xC4, 0xC2, 0x06, 0x69, + 0x02, 0x0D, 0x04, 0x60, 0xC6, 0xD6, 0x12, 0x0A, 0xC6, 0xE6, 0x12, 0x08, 0xC6, 0xB6, 0x12, 0x06, + 0xC4, 0xAB, 0x04, 0x41, 0xD2, 0x02, 0x06, 0x46, 0x23, 0x64, 0xA9, 0xC0, 0x9A, 0x1B, 0xA9, 0xD0, + 0x98, 0x1B, 0xA9, 0xE0, 0x96, 0x1B, 0xA9, 0xB0, 0x94, 0x1B, 0x98, 0x40, 0xB0, 0x1B, 0x82, 0x07, + 0xC4, 0x90, 0x92, 0x05, 0xB8, 0x50, 0x8C, 0x19, 0x92, 0x02, 0x06, 0x69, 0x38, 0x50, 0x6C, 0x19, + 0xCC, 0x50, 0x1F, 0x03, 0xD2, 0x38, 0xC4, 0x60, 0x82, 0x10, 0x18, 0x67, 0x56, 0x01, 0xCC, 0x60, + 0xFF, 0x00, 0x82, 0x04, 0x24, 0x61, 0x99, 0x67, 0x56, 0x01, 0x98, 0x67, 0x57, 0x01, 0x82, 0x2B, + 0x34, 0x61, 0x99, 0x67, 0x57, 0x01, 0xF2, 0x27, 0x18, 0x67, 0x57, 0x01, 0x30, 0x41, 0x99, 0x07, + 0x56, 0x01, 0x24, 0x61, 0x13, 0x66, 0x99, 0x67, 0x57, 0x01, 0x18, 0x54, 0xC3, 0x00, 0xC6, 0x56, + 0x92, 0x1A, 0x99, 0x07, 0x57, 0x01, 0xF2, 0x17, 0xCC, 0xC0, 0x19, 0x00, 0x1A, 0x24, 0xFD, 0xFF, + 0xFA, 0x25, 0xFD, 0xFF, 0xCC, 0xD0, 0x15, 0x00, 0x1A, 0xB8, 0xFD, 0xFF, 0xFA, 0xC0, 0xFD, 0xFF, + 0xCC, 0xD0, 0x15, 0x00, 0x1A, 0xB5, 0xFD, 0xFF, 0xFA, 0xBA, 0xFD, 0xFF, 0xCC, 0xD0, 0x13, 0x00, + 0xFA, 0xC9, 0xFD, 0xFF, 0x58, 0xC1, 0x24, 0x00, 0x58, 0x81, 0x14, 0x00, 0x2C, 0x10, 0x34, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x18, 0x60, 0xA6, 0x1B, + 0x04, 0x70, 0xC4, 0x61, 0x92, 0x05, 0x08, 0x70, 0x00, 0x80, 0x18, 0x77, 0x3B, 0xDC, 0x70, 0x52, + 0xC6, 0x57, 0x32, 0x03, 0xA1, 0x72, 0xF2, 0x07, 0x0C, 0x60, 0x7F, 0x07, 0x36, 0x67, 0xC6, 0x56, + 0x02, 0x02, 0xA1, 0x62, 0x78, 0x62, 0x02, 0x00, 0xC6, 0x67, 0x22, 0x07, 0x0C, 0x50, 0x37, 0x04, + 0x3F, 0x77, 0x05, 0x00, 0xC6, 0x67, 0x02, 0x03, 0xA9, 0x72, 0x02, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x18, 0x60, 0xA6, 0x1B, 0x04, 0x70, 0xC4, 0x61, 0x92, 0x0C, 0x08, 0x70, 0x00, 0x80, 0x18, 0x67, + 0x3B, 0xDC, 0x2F, 0x76, 0x06, 0x00, 0x26, 0x76, 0x06, 0x57, 0xD7, 0x52, 0x26, 0x75, 0x26, 0x76, + 0x30, 0x52, 0xC6, 0x57, 0x32, 0x03, 0xB1, 0x72, 0xF2, 0x09, 0x08, 0x60, 0x02, 0x00, 0x2C, 0x60, + 0xFF, 0xED, 0x36, 0x67, 0xC6, 0x56, 0x02, 0x02, 0xB1, 0x62, 0x38, 0x52, 0x04, 0x00, 0xC6, 0x57, + 0x22, 0x09, 0x08, 0x60, 0x01, 0x00, 0x2C, 0x60, 0xDF, 0xA5, 0x3F, 0x77, 0x06, 0x00, 0xC6, 0x57, + 0x02, 0x03, 0xB9, 0x72, 0x04, 0x00, 0xE1, 0xF0, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x3C, 0x10, 0x3C, 0x00, 0xD9, 0x81, 0x1C, 0x00, 0x0C, 0xA0, 0x10, 0x03, 0x26, 0xA3, 0x0C, 0x90, + 0xFC, 0x0A, 0x57, 0xA1, 0xD9, 0xC1, 0x2C, 0x00, 0x26, 0xA9, 0x30, 0xEA, 0x98, 0x70, 0xA2, 0x1B, + 0x77, 0xEE, 0x2C, 0x30, 0x1F, 0x03, 0x2C, 0xE0, 0x29, 0x01, 0x57, 0x31, 0xD7, 0xE1, 0x08, 0x70, + 0x00, 0x80, 0x06, 0xD2, 0x26, 0x39, 0x26, 0xE9, 0x2C, 0x70, 0x0C, 0xDC, 0x82, 0x0C, 0x28, 0x87, + 0xA6, 0x00, 0x78, 0x47, 0xA8, 0x00, 0x78, 0x57, 0xAA, 0x00, 0x78, 0x67, 0xAC, 0x00, 0x78, 0x77, + 0xAE, 0x00, 0xF2, 0x0B, 0x18, 0x87, 0x2E, 0x00, 0x78, 0x47, 0x30, 0x00, 0x78, 0x57, 0x32, 0x00, + 0x78, 0x67, 0x34, 0x00, 0x78, 0x77, 0x36, 0x00, 0x2F, 0xC4, 0x04, 0x00, 0x26, 0xC4, 0x06, 0x2C, + 0xD7, 0x22, 0x2F, 0xB5, 0x05, 0x00, 0x26, 0xB5, 0x26, 0xC2, 0x26, 0xC4, 0x06, 0x4B, 0xD7, 0x42, + 0x26, 0xB4, 0x26, 0xB5, 0x2F, 0x56, 0x06, 0x00, 0x26, 0x56, 0x06, 0x45, 0xD7, 0x42, 0x26, 0x54, + 0x26, 0x56, 0x2F, 0x67, 0x07, 0x00, 0x26, 0x67, 0xB9, 0x51, 0x0C, 0x00, 0x06, 0x56, 0xD7, 0x52, + 0x26, 0x65, 0x26, 0x67, 0x70, 0x7D, 0xB9, 0x61, 0x10, 0x00, 0x06, 0x21, 0x2F, 0x67, 0x07, 0x00, + 0x26, 0x67, 0x06, 0x56, 0xD7, 0x52, 0x26, 0x65, 0x26, 0x76, 0x26, 0x7C, 0xB1, 0x71, 0x78, 0x7D, + 0x02, 0x00, 0xB9, 0x31, 0x14, 0x00, 0x2F, 0x67, 0x07, 0x00, 0x26, 0x67, 0x06, 0x56, 0xD7, 0x52, + 0x26, 0x65, 0x26, 0x76, 0x26, 0x7B, 0xB9, 0x71, 0x04, 0x00, 0x0B, 0x3C, 0x04, 0x00, 0x38, 0x31, + 0x14, 0x00, 0x30, 0x5A, 0x70, 0x6D, 0x30, 0x73, 0xB9, 0x61, 0x08, 0x00, 0x76, 0x75, 0x08, 0x50, + 0x00, 0xF0, 0xD6, 0x75, 0x78, 0x6D, 0x02, 0x00, 0x0C, 0xA0, 0x32, 0x00, 0x82, 0x06, 0xB1, 0x0E, + 0xB9, 0x0E, 0x04, 0x00, 0x0C, 0xA0, 0x64, 0x00, 0x04, 0x72, 0xD6, 0x78, 0x82, 0x6B, 0x26, 0x66, + 0x06, 0x76, 0x57, 0x71, 0x26, 0x67, 0x23, 0x66, 0x43, 0x56, 0xCC, 0x50, 0x41, 0x04, 0x12, 0x16, + 0x0C, 0x70, 0x47, 0x04, 0x36, 0x76, 0x43, 0x27, 0x2F, 0x62, 0x02, 0x00, 0x26, 0x62, 0x06, 0x56, + 0xD7, 0x52, 0x26, 0x65, 0x38, 0x59, 0x78, 0x00, 0x0C, 0x30, 0x42, 0x04, 0x36, 0x35, 0x26, 0x26, + 0x43, 0x33, 0x8B, 0x16, 0x00, 0x00, 0x16, 0x72, 0xF2, 0x18, 0xCC, 0x50, 0x66, 0x26, 0x04, 0x70, + 0x02, 0x14, 0x1C, 0x70, 0x61, 0x26, 0x26, 0x76, 0x23, 0x27, 0x2F, 0x62, 0x02, 0x00, 0x26, 0x62, + 0x38, 0x39, 0xAC, 0x00, 0x06, 0x56, 0xD7, 0x52, 0x26, 0x65, 0x3C, 0x30, 0x66, 0x26, 0x26, 0x26, + 0x43, 0x33, 0x8B, 0x16, 0x00, 0x00, 0x06, 0x72, 0x06, 0x37, 0x06, 0x27, 0xB9, 0x71, 0x18, 0x00, + 0x4B, 0x14, 0x00, 0x00, 0x38, 0x71, 0x18, 0x00, 0x06, 0x32, 0x06, 0x27, 0x4B, 0x14, 0x00, 0x00, + 0x38, 0x3E, 0x04, 0x00, 0x0C, 0x70, 0x64, 0x00, 0x06, 0x52, 0x3F, 0x2A, 0x07, 0x00, 0xB9, 0x51, + 0x14, 0x00, 0xB9, 0x71, 0x18, 0x00, 0x4B, 0x14, 0x00, 0x00, 0x38, 0x71, 0x18, 0x00, 0x06, 0x37, + 0x8B, 0x16, 0x00, 0x00, 0x38, 0x51, 0x14, 0x00, 0x06, 0x62, 0x0C, 0x30, 0x10, 0x27, 0x06, 0x25, + 0xB9, 0x61, 0x14, 0x00, 0x8B, 0x16, 0x00, 0x00, 0x06, 0x3A, 0x4B, 0x14, 0x00, 0x00, 0x38, 0x71, + 0x18, 0x00, 0x06, 0x37, 0x8B, 0x16, 0x00, 0x00, 0x38, 0x61, 0x14, 0x00, 0x26, 0x26, 0xB9, 0x2E, + 0x04, 0x00, 0xD4, 0x81, 0x82, 0x5D, 0x38, 0x71, 0x08, 0x00, 0x26, 0x77, 0x06, 0x67, 0x57, 0x61, + 0x26, 0x76, 0x23, 0x77, 0x43, 0x67, 0xCC, 0x60, 0xAB, 0x03, 0x12, 0x17, 0x0C, 0x60, 0xB1, 0x03, + 0x3F, 0x77, 0x06, 0x00, 0x43, 0x27, 0x2F, 0x62, 0x02, 0x00, 0x26, 0x62, 0x06, 0x56, 0xD7, 0x52, + 0x26, 0x65, 0x38, 0x59, 0x18, 0x00, 0x0C, 0x30, 0xAC, 0x03, 0x36, 0x35, 0x26, 0x26, 0x43, 0x33, + 0x8B, 0x16, 0x00, 0x00, 0x16, 0x82, 0xF2, 0x17, 0xCC, 0x60, 0x3C, 0x46, 0x04, 0x80, 0x02, 0x13, + 0x3C, 0x70, 0x37, 0x46, 0x23, 0x27, 0x2F, 0x62, 0x02, 0x00, 0x26, 0x62, 0x38, 0x39, 0x70, 0x00, + 0x06, 0x56, 0xD7, 0x52, 0x26, 0x65, 0x3C, 0x30, 0x3C, 0x46, 0x26, 0x26, 0x43, 0x33, 0x8B, 0x16, + 0x00, 0x00, 0x06, 0x82, 0x06, 0x38, 0x06, 0x28, 0x4B, 0x14, 0x00, 0x00, 0x06, 0x32, 0x06, 0x28, + 0x4B, 0x14, 0x00, 0x00, 0x30, 0x3E, 0x0C, 0x90, 0x64, 0x00, 0x06, 0x72, 0x3F, 0x2A, 0x09, 0x00, + 0xB9, 0x71, 0x18, 0x00, 0x4B, 0x14, 0x00, 0x00, 0x06, 0x39, 0x8B, 0x16, 0x00, 0x00, 0x38, 0x71, + 0x18, 0x00, 0x06, 0x82, 0x0C, 0x30, 0x10, 0x27, 0x06, 0x27, 0x8B, 0x16, 0x00, 0x00, 0x06, 0x3A, + 0x4B, 0x14, 0x00, 0x00, 0x06, 0x39, 0x8B, 0x16, 0x00, 0x00, 0x26, 0x28, 0xB1, 0x2E, 0x30, 0x2E, + 0x0C, 0x30, 0x11, 0x0F, 0x4B, 0x14, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0x8B, 0x16, 0x00, 0x00, + 0x30, 0xA1, 0x0C, 0x30, 0x4D, 0x10, 0x26, 0xA2, 0x38, 0x2E, 0x04, 0x00, 0xB1, 0xA1, 0x4B, 0x14, + 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0x8B, 0x16, 0x00, 0x00, 0x38, 0x71, 0x04, 0x00, 0xC4, 0xB0, + 0x26, 0x27, 0x06, 0x7B, 0x32, 0x02, 0x16, 0x7B, 0x38, 0x61, 0x10, 0x00, 0xC4, 0xB0, 0x26, 0x76, + 0x22, 0x08, 0xC6, 0x27, 0x22, 0x0E, 0xC4, 0xB0, 0x82, 0x04, 0xB9, 0x21, 0x04, 0x00, 0xF2, 0x0B, + 0x08, 0x60, 0x01, 0x00, 0x2C, 0x60, 0xE0, 0xA5, 0x3F, 0x77, 0x06, 0x00, 0xC6, 0x27, 0x02, 0xF6, + 0xB9, 0x71, 0x04, 0x00, 0xC4, 0xC0, 0x06, 0x7C, 0x32, 0x02, 0x16, 0x7C, 0x38, 0x61, 0x0C, 0x00, + 0xC4, 0xC0, 0x26, 0x76, 0x22, 0x05, 0xC6, 0xA7, 0x22, 0x0B, 0xC4, 0xC0, 0x92, 0x0A, 0x08, 0x60, + 0x02, 0x00, 0x2C, 0x60, 0x00, 0xEE, 0x3F, 0x77, 0x06, 0x00, 0xC6, 0xA7, 0x02, 0x02, 0xB1, 0x71, + 0x06, 0x21, 0x0B, 0x3C, 0x04, 0x00, 0x30, 0x21, 0x0C, 0x30, 0x64, 0x00, 0x2C, 0x20, 0x32, 0x00, + 0x8B, 0x16, 0x00, 0x00, 0xA1, 0x2D, 0x38, 0x21, 0x04, 0x00, 0x0C, 0x30, 0x64, 0x00, 0x2C, 0x20, + 0x32, 0x00, 0x8B, 0x16, 0x00, 0x00, 0xA9, 0x2D, 0x02, 0x00, 0x58, 0xC1, 0x2C, 0x00, 0x58, 0x81, + 0x1C, 0x00, 0x2C, 0x10, 0x3C, 0x00, 0xE1, 0xF0, 0x34, 0x14, 0x0C, 0x20, 0x38, 0x17, 0x04, 0x30, + 0x0C, 0x40, 0x3C, 0x00, 0xB1, 0xF1, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x0C, 0x20, 0x74, 0x17, + 0x04, 0x30, 0x0C, 0x40, 0x3C, 0x00, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x18, 0xC1, 0xE1, 0x0C, 0xE0, 0xFC, 0x0A, 0x98, 0x7E, 0xB0, 0x0C, + 0x82, 0x1A, 0x0C, 0x20, 0x78, 0x17, 0x04, 0x30, 0x0C, 0x40, 0x34, 0x00, 0x99, 0x0E, 0xB0, 0x0C, + 0xB9, 0x0E, 0x78, 0x0C, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x04, 0x71, 0x99, 0x7E, 0x74, 0x0C, + 0xB9, 0x0E, 0x3C, 0x0C, 0x0C, 0x20, 0x3C, 0x17, 0x04, 0x30, 0x0C, 0x40, 0x34, 0x00, 0x0C, 0xF0, + 0xB0, 0x01, 0xF1, 0xF0, 0x2B, 0x83, 0x02, 0x00, 0x4B, 0xB6, 0x01, 0x00, 0x40, 0xE1, 0x24, 0x18, + 0xE1, 0xF0, 0x00, 0x00, 0x0C, 0x70, 0xFC, 0x0A, 0x18, 0x67, 0x8C, 0x06, 0x99, 0x67, 0x8D, 0x06, + 0x18, 0x67, 0xA1, 0x06, 0x99, 0x67, 0xA2, 0x06, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x28, 0x00, + 0xD9, 0xC1, 0x18, 0x00, 0x0C, 0xD0, 0xFC, 0x0A, 0x18, 0xCD, 0xE5, 0x00, 0xD9, 0x81, 0x08, 0x00, + 0x04, 0xB0, 0x06, 0xEC, 0x06, 0x7C, 0x57, 0xE1, 0x57, 0x72, 0x26, 0xE7, 0x36, 0xEC, 0x26, 0xEE, + 0x2C, 0xE0, 0x98, 0x04, 0x08, 0x90, 0x00, 0xFF, 0x08, 0x80, 0xFF, 0xF0, 0x26, 0xED, 0x06, 0xAB, + 0x2C, 0x90, 0xFF, 0x0F, 0x2C, 0x80, 0xFF, 0xFF, 0x08, 0x50, 0xFF, 0x0F, 0x18, 0x7D, 0xE6, 0x00, + 0x2F, 0x6C, 0x0B, 0x00, 0xC6, 0x67, 0x32, 0x73, 0x18, 0x7D, 0x8C, 0x06, 0xC6, 0x7A, 0xC2, 0x6F, + 0x98, 0x7E, 0x1E, 0x00, 0x82, 0x68, 0x06, 0x2E, 0xB9, 0x51, 0x04, 0x00, 0xB1, 0x61, 0x0B, 0xED, + 0x01, 0x00, 0xC4, 0x20, 0x24, 0xA1, 0x13, 0xAA, 0x38, 0x51, 0x04, 0x00, 0x30, 0x61, 0x82, 0x5B, + 0x98, 0x7E, 0x21, 0x00, 0x82, 0x0B, 0x18, 0x7E, 0x24, 0x00, 0xC4, 0x74, 0xD2, 0x03, 0x99, 0x0E, + 0x21, 0x00, 0x04, 0x75, 0x99, 0x7E, 0x24, 0x00, 0xF2, 0x09, 0x18, 0x7E, 0x20, 0x00, 0xC4, 0x73, + 0xD2, 0x05, 0x18, 0x7E, 0x24, 0x00, 0xC4, 0x73, 0xC2, 0x46, 0x98, 0x7E, 0x21, 0x00, 0x92, 0x43, + 0x24, 0x61, 0x57, 0x61, 0x26, 0x6D, 0x20, 0x4E, 0x38, 0x76, 0x3C, 0x0C, 0x5C, 0x40, 0xFF, 0x0F, + 0x57, 0x46, 0x56, 0x79, 0x66, 0x74, 0xB9, 0x76, 0x3C, 0x0C, 0x28, 0x4E, 0x02, 0x00, 0x1C, 0x30, + 0x00, 0x10, 0x5C, 0x40, 0xFF, 0x0F, 0x56, 0x73, 0x66, 0x74, 0xB9, 0x76, 0x3C, 0x0C, 0x18, 0x4E, + 0x1F, 0x00, 0x56, 0x78, 0x54, 0x4F, 0x57, 0x4C, 0x66, 0x74, 0xB9, 0x76, 0x3C, 0x0C, 0x18, 0x3E, + 0x1E, 0x00, 0x0C, 0x40, 0xFF, 0xFF, 0x26, 0x45, 0x57, 0x3E, 0x56, 0x47, 0x66, 0x43, 0xB9, 0x46, + 0x3C, 0x0C, 0x18, 0x6E, 0x1E, 0x00, 0x04, 0x71, 0x34, 0x61, 0x53, 0x76, 0x38, 0x6D, 0x3C, 0x0C, + 0x1C, 0x40, 0x00, 0x04, 0x66, 0x76, 0x5C, 0x70, 0xFF, 0x03, 0x56, 0x64, 0x66, 0x67, 0x06, 0x76, + 0x77, 0x76, 0x24, 0x71, 0x54, 0x7F, 0x1C, 0x30, 0x01, 0xF0, 0x57, 0x76, 0x56, 0x63, 0x66, 0x67, + 0xB9, 0x6D, 0x3C, 0x0C, 0x24, 0xB1, 0x2C, 0xE0, 0x26, 0x00, 0xF2, 0x89, 0x58, 0xC1, 0x18, 0x00, + 0x58, 0x81, 0x08, 0x00, 0x2C, 0x10, 0x28, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x20, 0x00, + 0xD9, 0xC1, 0x10, 0x00, 0x0C, 0xD0, 0xFC, 0x0A, 0x38, 0x7D, 0x3C, 0x0C, 0xD1, 0x81, 0xDC, 0x70, + 0x00, 0xF0, 0x92, 0x3A, 0xF8, 0x6D, 0xB4, 0x0C, 0x12, 0x37, 0x0C, 0xE0, 0x90, 0x11, 0x04, 0x9C, + 0x08, 0xB0, 0xE0, 0xFF, 0x08, 0xA0, 0x1F, 0xFF, 0x26, 0x9E, 0x06, 0xC7, 0x04, 0x81, 0x2C, 0xB0, + 0xFF, 0xFF, 0x2C, 0xA0, 0xFF, 0xFF, 0x18, 0x7D, 0xA1, 0x06, 0xC6, 0x7C, 0xC2, 0x25, 0x90, 0x7E, + 0x82, 0x03, 0x24, 0xC1, 0x13, 0xCC, 0x06, 0x2E, 0x6B, 0xF3, 0x01, 0x00, 0xC4, 0x20, 0x82, 0x19, + 0x10, 0x7E, 0x06, 0x68, 0x34, 0x71, 0x53, 0x67, 0x06, 0x76, 0x38, 0x6D, 0x3C, 0x0C, 0x06, 0x56, + 0x77, 0x58, 0x66, 0x75, 0x5C, 0x70, 0x1F, 0x00, 0x57, 0x78, 0x56, 0x6B, 0x66, 0x67, 0x06, 0x76, + 0xF7, 0x7A, 0x24, 0x71, 0x54, 0x77, 0xD7, 0x7A, 0x56, 0x6A, 0x66, 0x67, 0xB9, 0x6D, 0x3C, 0x0C, + 0x24, 0xE3, 0xC6, 0xE9, 0x92, 0xD9, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x0C, 0x50, 0xFC, 0x0A, 0x38, 0x45, + 0x3C, 0x0C, 0x06, 0x64, 0x77, 0x66, 0x54, 0x6F, 0xC4, 0x6A, 0x02, 0x30, 0x38, 0xF5, 0x78, 0x0C, + 0x14, 0x3A, 0x26, 0x36, 0x13, 0x33, 0x5C, 0xF0, 0xFF, 0x03, 0x5C, 0x40, 0xFF, 0x03, 0x0C, 0x20, + 0x6C, 0x17, 0x04, 0x7C, 0x04, 0xD1, 0x14, 0xC1, 0xC4, 0x30, 0x82, 0x16, 0x06, 0xEF, 0x63, 0xE7, + 0xD4, 0xE1, 0x92, 0x0E, 0x06, 0xE4, 0x63, 0xE7, 0xD4, 0xE1, 0x82, 0x0A, 0x06, 0xED, 0x53, 0xE7, + 0x15, 0xEE, 0x24, 0x6F, 0x34, 0x31, 0xB1, 0x02, 0x13, 0x33, 0x54, 0x6F, 0x56, 0x4E, 0x34, 0x71, + 0xC6, 0x7C, 0x34, 0x24, 0x92, 0xEA, 0x38, 0x75, 0x3C, 0x0C, 0x1C, 0x30, 0x00, 0xF4, 0x56, 0x73, + 0x57, 0x66, 0x66, 0x74, 0x66, 0x76, 0xB9, 0x75, 0x3C, 0x0C, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x0C, 0xE0, 0xFC, 0x0A, 0x18, 0xCE, + 0xB0, 0x0C, 0x0C, 0x20, 0x74, 0x17, 0x06, 0x3D, 0x0C, 0x30, 0x38, 0x17, 0x0C, 0x40, 0x3C, 0x00, + 0x0C, 0xF0, 0x28, 0x01, 0xF1, 0xF0, 0x06, 0x2D, 0x0C, 0x20, 0x38, 0x17, 0x04, 0x30, 0x0C, 0x40, + 0x3C, 0x00, 0x99, 0xCE, 0xB0, 0x0C, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0xEB, 0x5E, 0x04, 0x00, + 0xEB, 0x68, 0x04, 0x00, 0xAB, 0x6D, 0x04, 0x00, 0x38, 0x6E, 0x3C, 0x0C, 0x0C, 0x70, 0x00, 0xF0, + 0xD6, 0x76, 0x06, 0x7E, 0x82, 0x05, 0x77, 0x66, 0x54, 0x6F, 0x24, 0x61, 0xF2, 0x06, 0x08, 0x50, + 0xE0, 0x00, 0xD6, 0x56, 0x82, 0x05, 0x04, 0x61, 0x99, 0x67, 0x74, 0x0C, 0xF2, 0x03, 0x99, 0x0E, + 0x74, 0x0C, 0x98, 0x67, 0x74, 0x0C, 0x82, 0x05, 0x99, 0x67, 0xB0, 0x0C, 0x04, 0x21, 0xF2, 0x10, + 0x18, 0x67, 0xB0, 0x0C, 0x04, 0x21, 0xC4, 0x60, 0x82, 0x0B, 0x98, 0xE7, 0x8C, 0x06, 0x92, 0x08, + 0x99, 0x27, 0xB0, 0x0C, 0x6B, 0x0C, 0x02, 0x00, 0xAB, 0x5B, 0x04, 0x00, 0x06, 0x2E, 0x50, 0xC1, + 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x18, 0x70, 0xA5, 0x1B, 0x34, 0x18, 0xC4, 0x70, + 0xC1, 0xE1, 0x04, 0x21, 0x92, 0x33, 0x0C, 0x60, 0xFC, 0x0A, 0x38, 0x76, 0x78, 0x0C, 0x38, 0x36, + 0x3C, 0x0C, 0x08, 0x40, 0xFF, 0x00, 0x0C, 0x50, 0xFF, 0xF3, 0x76, 0x73, 0x26, 0x54, 0xD6, 0x75, + 0x06, 0xF6, 0x92, 0x24, 0x77, 0x36, 0x54, 0x3F, 0x0C, 0x50, 0x3C, 0x17, 0x06, 0x67, 0x2C, 0x40, + 0xFF, 0xFF, 0xC6, 0x73, 0xB2, 0x16, 0x04, 0xE1, 0x26, 0xE6, 0x06, 0x6E, 0x57, 0x61, 0x26, 0x6F, + 0x38, 0x26, 0x3C, 0x0C, 0x77, 0x2E, 0xC4, 0x20, 0x82, 0x08, 0x38, 0x65, 0x3C, 0x00, 0x30, 0x25, + 0x76, 0x62, 0xD6, 0x64, 0x92, 0x0A, 0x24, 0x71, 0xC4, 0xED, 0x06, 0x6E, 0x24, 0x54, 0x92, 0xEA, + 0x99, 0x0F, 0x74, 0x0C, 0x04, 0x20, 0xF2, 0x02, 0x04, 0x21, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, + 0x34, 0x14, 0x0C, 0x20, 0xDB, 0x0B, 0x04, 0x30, 0x04, 0x48, 0xB1, 0xF1, 0x0C, 0xF0, 0xB0, 0x01, + 0xF1, 0xF0, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x0C, 0x70, 0xFC, 0x0A, 0x0C, 0x60, 0x18, 0x00, + 0x99, 0x67, 0xE3, 0x00, 0x04, 0x6E, 0x34, 0x14, 0x99, 0x67, 0xE4, 0x00, 0x04, 0x6D, 0xB1, 0xF1, + 0x99, 0x07, 0xE0, 0x00, 0x99, 0x07, 0xE1, 0x00, 0x99, 0x07, 0xE2, 0x00, 0x99, 0x07, 0xE5, 0x00, + 0x99, 0x67, 0xE6, 0x00, 0x2B, 0x36, 0x03, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, + 0x04, 0x70, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xC7, 0x06, 0xF7, 0x06, 0xD7, 0x13, 0xE7, + 0xC6, 0xE4, 0xB2, 0x1B, 0x06, 0x65, 0x73, 0x67, 0x54, 0x61, 0x26, 0xD6, 0x13, 0xDD, 0xC4, 0xD2, + 0xD2, 0x16, 0xC4, 0xF0, 0x92, 0x05, 0xC4, 0x61, 0x92, 0x0E, 0x91, 0xE2, 0xF2, 0x0B, 0xC4, 0xC0, + 0x92, 0x07, 0xC4, 0x60, 0x04, 0xF1, 0x92, 0x07, 0x91, 0xE3, 0x06, 0xCF, 0xF2, 0x04, 0xC4, 0x61, + 0x82, 0x06, 0x04, 0xF1, 0x24, 0x71, 0xF2, 0xE4, 0x04, 0x21, 0xF2, 0x02, 0x04, 0x20, 0x50, 0xC1, + 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x0C, 0xE0, + 0xFC, 0x0A, 0x98, 0x7E, 0xDF, 0x00, 0x92, 0x03, 0x4B, 0x7B, 0x04, 0x00, 0x18, 0x7E, 0x8D, 0x06, + 0xC4, 0x71, 0xC2, 0x03, 0x04, 0x20, 0xF2, 0x3B, 0xB8, 0x5E, 0xFC, 0x02, 0x82, 0xFC, 0xB8, 0x7E, + 0x00, 0x03, 0x82, 0xF9, 0x38, 0x7E, 0x0C, 0x00, 0xD4, 0x76, 0x92, 0xF5, 0x78, 0x4E, 0x20, 0x03, + 0x0C, 0x30, 0x74, 0x1A, 0x0C, 0x20, 0x80, 0x02, 0x0C, 0xF0, 0x54, 0x05, 0x2F, 0x63, 0x07, 0x00, + 0x20, 0x66, 0x26, 0x66, 0x2F, 0xD6, 0x02, 0x00, 0x26, 0x6F, 0x70, 0xDD, 0x70, 0x66, 0x3F, 0x66, + 0x0D, 0x00, 0xC6, 0x64, 0x12, 0xE0, 0x24, 0x72, 0xC4, 0x76, 0x92, 0xF1, 0x04, 0x71, 0x99, 0x7E, + 0xE0, 0x00, 0x0C, 0x20, 0xDD, 0x0B, 0x0C, 0x30, 0xDF, 0x0B, 0x0C, 0x40, 0x18, 0x00, 0x0B, 0x7D, + 0x04, 0x00, 0xC4, 0x20, 0x82, 0xD0, 0x38, 0x5E, 0x00, 0x03, 0x0C, 0x20, 0xDE, 0x0B, 0x0C, 0x30, + 0xE0, 0x0B, 0x04, 0x4E, 0x0B, 0x7D, 0x04, 0x00, 0x16, 0x22, 0xF7, 0x2F, 0x50, 0xC1, 0x2C, 0x10, + 0x10, 0x00, 0xE1, 0xF0, 0x2F, 0x73, 0x03, 0x00, 0x26, 0x37, 0x3C, 0x10, 0x10, 0x00, 0xD7, 0x31, + 0xD1, 0xC1, 0x2F, 0xF3, 0x02, 0x00, 0x08, 0xE0, 0x00, 0x30, 0x04, 0x20, 0x06, 0x62, 0x2C, 0xE0, + 0x00, 0x49, 0xC6, 0x65, 0xB2, 0x15, 0x06, 0x7F, 0x57, 0x71, 0x26, 0x7E, 0x30, 0xD7, 0x30, 0x77, + 0x5C, 0xD0, 0xFF, 0x0F, 0x77, 0x78, 0x5C, 0x70, 0xFF, 0x0F, 0x3F, 0x77, 0x0D, 0x00, 0xC4, 0x70, + 0x02, 0x02, 0x26, 0x27, 0x24, 0x61, 0x26, 0xF4, 0x23, 0x66, 0x23, 0xFF, 0xF2, 0xEB, 0x06, 0x35, + 0xAB, 0x15, 0x00, 0x00, 0x50, 0xC1, 0x23, 0x22, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x3C, 0x10, 0x84, 0x00, 0xD9, 0xC1, 0x74, 0x00, 0xD9, 0x81, 0x64, 0x00, 0x0C, 0xE0, 0xFC, 0x0A, + 0x28, 0xBE, 0x06, 0x03, 0xA9, 0x0E, 0x18, 0x03, 0xCB, 0x3D, 0x00, 0x00, 0x23, 0xD2, 0xC6, 0xDB, + 0x04, 0xC0, 0x06, 0x8E, 0xCA, 0x3C, 0x01, 0x00, 0x0C, 0x20, 0x14, 0x00, 0x26, 0x21, 0x06, 0x3C, + 0x04, 0x45, 0x0C, 0xF0, 0xD8, 0x01, 0xF1, 0xF0, 0x04, 0x45, 0x06, 0x3C, 0x06, 0x21, 0x0C, 0xF0, + 0xD8, 0x01, 0xF1, 0xF0, 0xA9, 0xDE, 0x18, 0x03, 0x4B, 0x3E, 0x00, 0x00, 0x23, 0xD2, 0xA9, 0xDE, + 0x5C, 0x01, 0x06, 0x2D, 0x0C, 0x30, 0x18, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x13, 0xE2, 0x99, 0xE8, + 0x5F, 0x01, 0x06, 0x2D, 0x0C, 0x30, 0x18, 0x00, 0x4B, 0x18, 0x00, 0x00, 0x13, 0x22, 0x14, 0x62, + 0x26, 0x62, 0x33, 0x66, 0xB9, 0x61, 0x40, 0x00, 0x14, 0x62, 0x26, 0x6E, 0x99, 0x28, 0x5E, 0x01, + 0x24, 0xE2, 0x24, 0x22, 0x33, 0x66, 0x33, 0x7E, 0x33, 0x22, 0x08, 0xE0, 0x00, 0x30, 0xB9, 0x21, + 0x54, 0x00, 0xB9, 0x61, 0x44, 0x00, 0xB9, 0x71, 0x58, 0x00, 0x06, 0xA6, 0x06, 0xDC, 0x2C, 0xE0, + 0x00, 0x49, 0x38, 0x71, 0x58, 0x00, 0xC6, 0xA7, 0x1A, 0xAE, 0x00, 0x00, 0x13, 0x7A, 0xC4, 0x7D, + 0xB9, 0x71, 0x48, 0x00, 0xDA, 0xA2, 0x00, 0x00, 0x38, 0x71, 0x44, 0x00, 0x38, 0x31, 0x48, 0x00, + 0x06, 0xBA, 0x04, 0x20, 0x04, 0x41, 0x0C, 0x50, 0x17, 0x00, 0x36, 0xB7, 0xAB, 0x84, 0x04, 0x00, + 0x2F, 0x6B, 0x0B, 0x00, 0x26, 0x61, 0xA9, 0x26, 0x28, 0x00, 0x2F, 0x6A, 0x0A, 0x00, 0x26, 0xA6, + 0x06, 0x7B, 0xD7, 0xA1, 0x57, 0x71, 0x38, 0x61, 0x40, 0x00, 0xB9, 0x21, 0x4C, 0x00, 0x23, 0xAA, + 0x26, 0x71, 0xB9, 0xA1, 0x5C, 0x00, 0xB9, 0x71, 0x50, 0x00, 0x38, 0x71, 0x54, 0x00, 0xC6, 0x67, + 0x12, 0x77, 0x13, 0xA6, 0xCC, 0xA0, 0x16, 0x00, 0xD2, 0x70, 0x38, 0x71, 0x40, 0x00, 0xC4, 0xC0, + 0x06, 0x96, 0x36, 0x97, 0x92, 0x11, 0x04, 0x5E, 0x06, 0x2A, 0x06, 0x3C, 0x0C, 0x40, 0x18, 0x00, + 0xB9, 0x61, 0x60, 0x00, 0xAB, 0x84, 0x04, 0x00, 0x2F, 0x59, 0x09, 0x00, 0x38, 0x61, 0x60, 0x00, + 0x26, 0x51, 0xA9, 0x25, 0x34, 0x00, 0x38, 0x71, 0x5C, 0x00, 0x28, 0x28, 0x14, 0x00, 0x26, 0x67, + 0x23, 0x36, 0x06, 0x43, 0x57, 0x41, 0x2F, 0x5E, 0x04, 0x00, 0x30, 0x65, 0x30, 0x55, 0x38, 0x71, + 0x4C, 0x00, 0x77, 0x58, 0x5C, 0x50, 0xFF, 0x0F, 0x5C, 0x60, 0xFF, 0x0F, 0x36, 0x65, 0x18, 0x58, + 0x5F, 0x01, 0x36, 0x67, 0xC4, 0x5A, 0x36, 0x62, 0x92, 0x0B, 0x18, 0x58, 0x5E, 0x01, 0x3C, 0x50, + 0x10, 0x00, 0x13, 0x55, 0xC4, 0x51, 0xD2, 0x2B, 0xCC, 0x30, 0x02, 0x01, 0xF2, 0x0C, 0xC4, 0x53, + 0x92, 0x26, 0x18, 0x58, 0x5E, 0x01, 0x3C, 0x50, 0x10, 0x00, 0x13, 0x55, 0xC4, 0x51, 0xD2, 0x1F, + 0xCC, 0x30, 0x5A, 0x00, 0x92, 0x1C, 0x34, 0x44, 0x26, 0x4E, 0x30, 0x34, 0x30, 0x54, 0x5C, 0x30, + 0xFF, 0x0F, 0x77, 0x58, 0x5C, 0x50, 0xFF, 0x0F, 0xC6, 0x35, 0xC2, 0x11, 0x30, 0x24, 0x30, 0x54, + 0xB9, 0x61, 0x60, 0x00, 0x5C, 0x20, 0xFF, 0x0F, 0x77, 0x58, 0x5C, 0x50, 0xFF, 0x0F, 0x36, 0x25, + 0x04, 0x36, 0xAB, 0x15, 0x00, 0x00, 0x38, 0x61, 0x60, 0x00, 0x26, 0x62, 0xC4, 0x60, 0x22, 0x0D, + 0x57, 0x91, 0x26, 0x91, 0x38, 0x59, 0x14, 0x00, 0x38, 0x71, 0x50, 0x00, 0x26, 0x56, 0xB9, 0x59, + 0x14, 0x00, 0x30, 0x57, 0x26, 0x65, 0xB1, 0x67, 0x24, 0xA1, 0x33, 0x6A, 0xF2, 0x87, 0x57, 0xB1, + 0x26, 0xB1, 0x30, 0x6B, 0x04, 0xC1, 0x26, 0xD6, 0x38, 0xA1, 0x48, 0x00, 0x24, 0xA1, 0x33, 0xAA, + 0xFA, 0x51, 0xFF, 0xFF, 0x28, 0x58, 0x5C, 0x01, 0x28, 0x41, 0x38, 0x00, 0x08, 0x60, 0x00, 0x30, + 0x57, 0x51, 0x2C, 0x60, 0x00, 0x49, 0x26, 0x65, 0x30, 0x56, 0x30, 0x66, 0x5C, 0x50, 0xFF, 0x0F, + 0x77, 0x68, 0x5C, 0x60, 0xFF, 0x0F, 0x3F, 0x66, 0x05, 0x00, 0x36, 0x64, 0x28, 0x41, 0x2C, 0x00, + 0x38, 0x51, 0x40, 0x00, 0x36, 0x64, 0x28, 0x48, 0x14, 0x00, 0x24, 0x56, 0x36, 0x64, 0x23, 0x66, + 0x57, 0x51, 0x0C, 0x40, 0x14, 0x00, 0xA9, 0x68, 0x14, 0x03, 0xA9, 0x68, 0x16, 0x03, 0x06, 0x2E, + 0x0C, 0x20, 0x58, 0x0C, 0x04, 0x30, 0x26, 0x41, 0x26, 0x58, 0x06, 0x6D, 0x8B, 0x3D, 0x03, 0x00, + 0x38, 0x51, 0x44, 0x00, 0x06, 0x6D, 0x2C, 0x50, 0x1E, 0x00, 0x57, 0x51, 0x06, 0x2E, 0x0C, 0x20, + 0x58, 0x0C, 0x04, 0x31, 0x06, 0x41, 0x26, 0x58, 0x8B, 0x3D, 0x03, 0x00, 0x18, 0x68, 0x25, 0x03, + 0x04, 0xC1, 0xA9, 0x68, 0x78, 0x01, 0xA9, 0x68, 0x12, 0x00, 0x04, 0x61, 0x99, 0x68, 0x1D, 0x03, + 0x99, 0x68, 0x1E, 0x03, 0x99, 0x68, 0x1F, 0x03, 0x99, 0x68, 0x1C, 0x03, 0xAB, 0x4E, 0x03, 0x00, + 0x06, 0x2C, 0x58, 0xC1, 0x74, 0x00, 0x58, 0x81, 0x64, 0x00, 0x2C, 0x10, 0x84, 0x00, 0xE1, 0xF0, + 0x3C, 0x10, 0x18, 0x00, 0xD9, 0xC1, 0x08, 0x00, 0xC1, 0xA1, 0x0C, 0xE0, 0xFC, 0x0A, 0x38, 0x2E, + 0x88, 0x06, 0x04, 0x70, 0xC6, 0x27, 0x82, 0x4F, 0x0C, 0xF0, 0x80, 0x00, 0xF1, 0xF0, 0x04, 0x61, + 0x06, 0x42, 0x06, 0x52, 0x26, 0x62, 0x57, 0x41, 0x57, 0x52, 0x99, 0x6E, 0xE6, 0x00, 0x2F, 0x65, + 0x04, 0x00, 0x36, 0x62, 0x26, 0x66, 0x26, 0x6E, 0x78, 0xDE, 0x70, 0x01, 0x78, 0x66, 0xA8, 0x04, + 0x99, 0x2E, 0xE5, 0x00, 0x06, 0x72, 0x36, 0xD6, 0xC4, 0xD0, 0x32, 0x02, 0x16, 0xDD, 0x2F, 0x35, + 0x04, 0x00, 0x36, 0x37, 0x26, 0x33, 0x26, 0x3E, 0x78, 0x2E, 0x72, 0x01, 0x78, 0x63, 0xAA, 0x04, + 0x36, 0x26, 0xC4, 0x20, 0x32, 0x02, 0x16, 0x22, 0x26, 0x54, 0x3F, 0x77, 0x05, 0x00, 0x26, 0x77, + 0x2F, 0xC7, 0x0E, 0x00, 0x06, 0x32, 0x4B, 0x14, 0x00, 0x00, 0x28, 0xBC, 0xB4, 0x04, 0x06, 0x3D, + 0x06, 0xA2, 0x06, 0x2D, 0x4B, 0x14, 0x00, 0x00, 0x2F, 0xD2, 0x0A, 0x00, 0x06, 0x3B, 0x06, 0x2B, + 0x4B, 0x14, 0x00, 0x00, 0xC6, 0xD2, 0xB2, 0x0D, 0x04, 0xD1, 0x0C, 0x20, 0x98, 0x04, 0x99, 0xDE, + 0xDF, 0x00, 0x26, 0x2C, 0x0C, 0x30, 0x58, 0x0C, 0xEB, 0x4A, 0x02, 0x00, 0x99, 0xDE, 0x8C, 0x06, + 0x18, 0x7E, 0xDF, 0x00, 0x58, 0xC1, 0x08, 0x00, 0x40, 0xA1, 0x06, 0x27, 0x2C, 0x10, 0x18, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0x0C, 0x70, 0xFC, 0x0A, 0x99, 0x07, 0xDF, 0x00, + 0x98, 0x77, 0xE0, 0x00, 0x82, 0x07, 0x8B, 0x87, 0x04, 0x00, 0xC4, 0x20, 0x82, 0x03, 0x0B, 0x9D, + 0x04, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x3C, 0x10, 0xD0, 0x00, 0x08, 0x30, 0x00, 0x80, 0xD9, 0xC1, 0xC0, 0x00, 0x0C, 0x40, 0xBE, 0x00, + 0x2C, 0x30, 0xEC, 0x9C, 0x06, 0xD2, 0x06, 0x21, 0xEB, 0xE4, 0x04, 0x00, 0x0C, 0x20, 0x40, 0x00, + 0x2B, 0x60, 0x00, 0x00, 0x04, 0x28, 0x04, 0x30, 0xEB, 0x6B, 0x00, 0x00, 0x04, 0x30, 0x04, 0x48, + 0x0C, 0x20, 0x1E, 0x00, 0x4B, 0xAD, 0x01, 0x00, 0xEB, 0xAD, 0x01, 0x00, 0x0C, 0x20, 0x60, 0xEA, + 0x0B, 0xAF, 0x01, 0x00, 0xCB, 0x31, 0x00, 0x00, 0x08, 0x70, 0x0A, 0x13, 0x08, 0xE0, 0x00, 0x40, + 0x2C, 0x70, 0x0A, 0x13, 0xB9, 0x7E, 0x0C, 0x70, 0x0C, 0x70, 0x0A, 0x13, 0xB9, 0x7E, 0x88, 0x70, + 0xB9, 0x7E, 0x30, 0x71, 0x08, 0x70, 0x12, 0x00, 0x2C, 0x70, 0x08, 0x08, 0xB9, 0x7E, 0x34, 0x70, + 0x0C, 0x70, 0x88, 0x08, 0xB9, 0x7E, 0x3C, 0x70, 0x04, 0x71, 0xB9, 0x7E, 0x64, 0x70, 0x0C, 0x70, + 0xFF, 0x3F, 0xB9, 0x7E, 0x58, 0x70, 0x04, 0x20, 0xEB, 0x5A, 0x00, 0x00, 0x08, 0x70, 0x1B, 0x1A, + 0x2C, 0x70, 0x1D, 0x1C, 0xB9, 0x7E, 0x80, 0x71, 0x08, 0x70, 0x17, 0x16, 0x2C, 0x70, 0x19, 0x18, + 0xB9, 0x7E, 0x84, 0x71, 0x0C, 0x70, 0x13, 0x12, 0xB9, 0x7E, 0x88, 0x71, 0xB9, 0x0E, 0x8C, 0x71, + 0xB9, 0x0E, 0x90, 0x71, 0xB9, 0x0E, 0x94, 0x71, 0xB9, 0x0E, 0x98, 0x71, 0xB9, 0x0E, 0x9C, 0x71, + 0x08, 0x70, 0x12, 0x11, 0xB9, 0x7E, 0xA8, 0x71, 0x08, 0x70, 0x0E, 0x00, 0x2C, 0x70, 0x10, 0x0F, + 0xB9, 0x7E, 0xAC, 0x71, 0x08, 0x70, 0x0D, 0x0C, 0xB9, 0x7E, 0xB0, 0x71, 0x08, 0x70, 0x09, 0x00, + 0x2C, 0x70, 0x0B, 0x0A, 0xB9, 0x7E, 0xB4, 0x71, 0x08, 0x70, 0x01, 0x02, 0xB9, 0x7E, 0xB8, 0x71, + 0x08, 0x70, 0x00, 0x03, 0xB9, 0x7E, 0xBC, 0x71, 0x08, 0x70, 0x06, 0x07, 0x2C, 0x70, 0x04, 0x05, + 0xB9, 0x7E, 0xC0, 0x71, 0x04, 0x78, 0xB9, 0x7E, 0xC4, 0x71, 0x08, 0x70, 0x8E, 0x9F, 0x2C, 0x70, + 0x7C, 0x7C, 0xB9, 0x7E, 0x78, 0x71, 0x0C, 0x60, 0x00, 0x40, 0x08, 0x70, 0x00, 0x30, 0x08, 0x30, + 0x0F, 0x00, 0x0C, 0x20, 0xF8, 0x42, 0x06, 0xE1, 0x26, 0x67, 0x2C, 0x30, 0xFF, 0xFF, 0x26, 0x27, + 0x10, 0x5E, 0x30, 0x46, 0x57, 0x5C, 0x56, 0x43, 0x66, 0x54, 0xB1, 0x56, 0x24, 0x64, 0xC6, 0x62, + 0x24, 0xE1, 0x92, 0xF7, 0x08, 0x60, 0xF0, 0x3F, 0x0C, 0x50, 0x00, 0x90, 0x26, 0x56, 0xB9, 0x57, + 0xC4, 0x52, 0x0C, 0x50, 0x21, 0xB0, 0x26, 0x56, 0xB9, 0x57, 0xC8, 0x52, 0x0C, 0x50, 0x42, 0xB0, + 0x26, 0x56, 0xB9, 0x57, 0xCC, 0x52, 0x0C, 0x50, 0x63, 0xB0, 0x26, 0x56, 0xB9, 0x57, 0xD0, 0x52, + 0x0C, 0x50, 0x84, 0xB0, 0x26, 0x56, 0xB9, 0x57, 0xD4, 0x52, 0x0C, 0x50, 0xA5, 0xB0, 0x26, 0x56, + 0xB9, 0x57, 0xD8, 0x52, 0x0C, 0x50, 0xC6, 0xB0, 0x26, 0x56, 0xB9, 0x57, 0xDC, 0x52, 0x0C, 0x50, + 0xE7, 0xB0, 0x26, 0x56, 0xB9, 0x57, 0xE0, 0x52, 0x0C, 0x50, 0x08, 0xB1, 0x26, 0x56, 0xB9, 0x57, + 0xE4, 0x52, 0x0C, 0x50, 0x29, 0xA1, 0x26, 0x56, 0xB9, 0x57, 0xE8, 0x52, 0x2C, 0x60, 0x00, 0x80, + 0xB9, 0x67, 0xEC, 0x52, 0xB9, 0x67, 0xF0, 0x52, 0xB9, 0x67, 0xF4, 0x52, 0xB9, 0x67, 0xF8, 0x52, + 0xB9, 0x67, 0xFC, 0x52, 0x08, 0x60, 0xF1, 0x3F, 0x2C, 0x60, 0x00, 0xC0, 0xB9, 0x67, 0x00, 0x53, + 0xB9, 0x67, 0x04, 0x53, 0xB9, 0x67, 0x08, 0x53, 0xB9, 0x67, 0x0C, 0x53, 0xB9, 0x67, 0x10, 0x53, + 0xB9, 0x67, 0x14, 0x53, 0xB9, 0x67, 0x18, 0x53, 0xB9, 0x67, 0x1C, 0x53, 0xB9, 0x67, 0x20, 0x53, + 0xB9, 0x67, 0x24, 0x53, 0xB9, 0x67, 0x28, 0x53, 0xB9, 0x67, 0x2C, 0x53, 0xB9, 0x67, 0x30, 0x53, + 0xB9, 0x67, 0x34, 0x53, 0xB9, 0x67, 0x38, 0x53, 0x08, 0x70, 0x00, 0x40, 0x0C, 0x60, 0x70, 0x01, + 0xB9, 0x67, 0x28, 0x71, 0x08, 0x60, 0x01, 0x00, 0x2C, 0x60, 0x40, 0x62, 0xB9, 0x67, 0xAC, 0x70, + 0x08, 0x60, 0x08, 0x00, 0xB9, 0x67, 0xB4, 0x70, 0x08, 0x60, 0x88, 0x00, 0x2C, 0x60, 0x00, 0x10, + 0xB9, 0x07, 0xB8, 0x70, 0xB9, 0x67, 0xC0, 0x70, 0x08, 0x60, 0x10, 0x1F, 0x2C, 0x60, 0x10, 0x1F, + 0xB9, 0x67, 0xC4, 0x70, 0x0C, 0x60, 0x80, 0x00, 0xB9, 0x67, 0xC8, 0x70, 0x08, 0x60, 0x02, 0x01, + 0xB9, 0x67, 0xCC, 0x70, 0x04, 0x61, 0xB9, 0x67, 0xD4, 0x70, 0x08, 0x60, 0x00, 0x80, 0x2C, 0x60, + 0x00, 0xA0, 0xB9, 0x67, 0x8C, 0x70, 0x0C, 0x60, 0x14, 0xA0, 0xB9, 0x67, 0x90, 0x70, 0xB9, 0x07, + 0x94, 0x70, 0xB9, 0x07, 0x98, 0x70, 0x0C, 0x50, 0x00, 0xA0, 0xB9, 0x57, 0x9C, 0x70, 0xB9, 0x67, + 0xA0, 0x70, 0xB9, 0x07, 0xA4, 0x70, 0x08, 0x60, 0x80, 0x0F, 0xB9, 0x07, 0xA8, 0x70, 0x2C, 0x60, + 0x80, 0x0F, 0xB9, 0x67, 0x6C, 0x70, 0xEB, 0x2F, 0x00, 0x00, 0xEB, 0xAF, 0x01, 0x00, 0x04, 0xEA, + 0x04, 0x21, 0x0C, 0x30, 0x00, 0x20, 0x4B, 0x3A, 0x00, 0x00, 0x8B, 0x37, 0x00, 0x00, 0x0C, 0x20, + 0xD0, 0x07, 0x6B, 0xEB, 0x00, 0x00, 0x34, 0xE1, 0xA3, 0xEE, 0x92, 0xF3, 0x0B, 0x94, 0x00, 0x00, + 0xEB, 0xAF, 0x01, 0x00, 0x0B, 0x31, 0x00, 0x00, 0x6B, 0x32, 0x00, 0x00, 0x38, 0x7D, 0x18, 0x00, + 0x06, 0x2D, 0x04, 0x32, 0xF1, 0x70, 0x06, 0x2E, 0x58, 0xC1, 0xC0, 0x00, 0x2C, 0x10, 0xD0, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x14, 0x00, 0xD9, 0xC1, 0x04, 0x00, 0x08, 0xE0, 0x70, 0x41, + 0xB1, 0xB1, 0x06, 0xD2, 0x08, 0xC0, 0x00, 0x30, 0x2C, 0xE0, 0x22, 0xCF, 0xCB, 0xB9, 0x00, 0x00, + 0xB9, 0xEC, 0x04, 0x01, 0xCB, 0xBA, 0x00, 0x00, 0x86, 0xB2, 0x82, 0x04, 0x2B, 0xBB, 0x00, 0x00, + 0xF2, 0xF6, 0x4B, 0xBA, 0x00, 0x00, 0xEB, 0x6A, 0x00, 0x00, 0x38, 0x7D, 0x18, 0x00, 0x06, 0x2D, + 0x04, 0x35, 0xF1, 0x70, 0x58, 0xC1, 0x04, 0x00, 0x06, 0x2B, 0x30, 0xB1, 0x2C, 0x10, 0x14, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xE2, 0x06, 0xD3, 0xCB, 0x31, + 0x00, 0x00, 0xC4, 0xD2, 0x82, 0x0C, 0xC4, 0xD3, 0x82, 0x15, 0xC4, 0xD1, 0x92, 0x22, 0x0C, 0x20, + 0x11, 0x00, 0x8B, 0x34, 0x00, 0x00, 0xAB, 0x3C, 0x00, 0x00, 0xF2, 0x1B, 0x0C, 0x20, 0x11, 0x00, + 0x8B, 0x34, 0x00, 0x00, 0xAB, 0x3C, 0x00, 0x00, 0x99, 0x0E, 0x24, 0x00, 0x99, 0x0E, 0x1C, 0x00, + 0xF2, 0x10, 0x0C, 0x20, 0x1D, 0x00, 0x8B, 0x34, 0x00, 0x00, 0x2B, 0x3D, 0x00, 0x00, 0x04, 0x71, + 0x99, 0x7E, 0x1C, 0x00, 0x99, 0x7E, 0x24, 0x00, 0x6B, 0xAF, 0x01, 0x00, 0xB9, 0x2E, 0x20, 0x00, + 0x6B, 0x32, 0x00, 0x00, 0x91, 0xDE, 0x50, 0xC1, 0x04, 0x20, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, + 0x34, 0x18, 0xC1, 0xE1, 0x18, 0x72, 0x25, 0x00, 0x04, 0x61, 0xC4, 0x79, 0x26, 0x67, 0x99, 0x62, + 0x25, 0x00, 0x06, 0xE2, 0xD2, 0x0B, 0x0C, 0x20, 0xF4, 0x01, 0xAB, 0xED, 0x00, 0x00, 0x38, 0x7E, + 0x18, 0x00, 0x06, 0x2E, 0x04, 0x32, 0xF1, 0x70, 0xF2, 0x09, 0x6B, 0xAE, 0x01, 0x00, 0x0C, 0x20, + 0x40, 0x00, 0x0B, 0x61, 0x00, 0x00, 0x99, 0x00, 0x9F, 0x1B, 0x40, 0xE1, 0x04, 0x20, 0x24, 0x18, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xE2, 0x4B, 0x3E, 0x00, 0x00, + 0x0C, 0x30, 0x13, 0x00, 0x06, 0xD2, 0xAB, 0x15, 0x00, 0x00, 0x99, 0x2E, 0x01, 0x00, 0x0C, 0x30, + 0x13, 0x00, 0x06, 0x2D, 0x4B, 0x18, 0x00, 0x00, 0x91, 0x2E, 0x50, 0xC1, 0x04, 0x21, 0x2C, 0x10, + 0x10, 0x00, 0xE1, 0xF0, 0x34, 0x18, 0xC1, 0xE1, 0x06, 0xE2, 0xCB, 0x31, 0x00, 0x00, 0xEB, 0x2F, + 0x00, 0x00, 0x04, 0x21, 0x0C, 0x30, 0x00, 0x20, 0x4B, 0x3A, 0x00, 0x00, 0x8B, 0x37, 0x00, 0x00, + 0x0B, 0x31, 0x00, 0x00, 0xCB, 0x3E, 0x00, 0x00, 0x38, 0x70, 0x08, 0x0B, 0x0C, 0x60, 0x46, 0x00, + 0xD4, 0x71, 0x82, 0x03, 0x0C, 0x60, 0x64, 0x00, 0xC6, 0x26, 0xB2, 0x06, 0x6B, 0x32, 0x00, 0x00, + 0x0C, 0x20, 0x40, 0x9C, 0xF2, 0x19, 0x04, 0x2C, 0x8B, 0x34, 0x00, 0x00, 0x0C, 0x30, 0x00, 0x40, + 0x04, 0x24, 0x4B, 0x3A, 0x00, 0x00, 0x8B, 0x37, 0x00, 0x00, 0x0C, 0x20, 0x1D, 0x00, 0x26, 0x2E, + 0xAB, 0xC3, 0x04, 0x00, 0x6B, 0x32, 0x00, 0x00, 0x38, 0x7E, 0x18, 0x00, 0x06, 0x2E, 0x04, 0x33, + 0xF1, 0x70, 0x0C, 0x20, 0x20, 0x4E, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x3C, 0x10, 0x24, 0x00, + 0xD9, 0xC1, 0x14, 0x00, 0x06, 0xE2, 0xD9, 0x81, 0x04, 0x00, 0xCB, 0x3D, 0x00, 0x00, 0x06, 0xB2, + 0x6B, 0xAF, 0x01, 0x00, 0x18, 0xDE, 0x1C, 0x00, 0x14, 0x73, 0x26, 0x7D, 0xC4, 0x71, 0x06, 0xC2, + 0xD2, 0x18, 0xCC, 0xB0, 0x50, 0x00, 0xC2, 0x06, 0x6B, 0xAF, 0x01, 0x00, 0xB9, 0x2E, 0x20, 0x00, + 0xF2, 0x0D, 0x38, 0x7E, 0x20, 0x00, 0x3F, 0xC2, 0x07, 0x00, 0xC4, 0xC0, 0x32, 0x02, 0x16, 0xCC, + 0xCC, 0xC0, 0xF4, 0x01, 0x04, 0x75, 0x1A, 0x8E, 0x00, 0x00, 0x06, 0x7D, 0xFA, 0x8B, 0x00, 0x00, + 0xCC, 0xB0, 0x50, 0x00, 0x04, 0x72, 0xC2, 0x7B, 0x06, 0x21, 0xAB, 0xC3, 0x04, 0x00, 0x18, 0x6E, + 0x1D, 0x00, 0x10, 0x71, 0x3F, 0x77, 0x06, 0x00, 0xC4, 0x70, 0x32, 0x02, 0x16, 0x77, 0xC4, 0x71, + 0x02, 0x03, 0x04, 0x73, 0xF2, 0x6C, 0x18, 0x6E, 0x1E, 0x00, 0x18, 0x71, 0x01, 0x00, 0x3F, 0x77, + 0x06, 0x00, 0xC4, 0x70, 0x32, 0x02, 0x16, 0x77, 0xC4, 0x71, 0x12, 0xF4, 0x04, 0x60, 0x08, 0xF0, + 0x00, 0x30, 0x06, 0xB6, 0x06, 0x56, 0x06, 0xD6, 0x04, 0x21, 0x2C, 0xF0, 0xFC, 0x9F, 0x06, 0xA2, + 0x53, 0xAD, 0x06, 0x76, 0x04, 0x40, 0x08, 0x30, 0x00, 0x30, 0x2C, 0x30, 0x00, 0xA0, 0x26, 0x37, + 0x30, 0x93, 0xCC, 0x90, 0x50, 0x00, 0xC2, 0x2F, 0xC4, 0x40, 0x82, 0x0A, 0x2F, 0x9F, 0x07, 0x00, + 0x30, 0x89, 0x30, 0x93, 0xC6, 0x89, 0xD2, 0x27, 0xCC, 0x40, 0x12, 0x00, 0x82, 0x0A, 0x08, 0x90, + 0x00, 0x30, 0x2C, 0x90, 0x04, 0xA0, 0x26, 0x97, 0x30, 0x89, 0x30, 0x93, 0xC6, 0x89, 0xB2, 0x1B, + 0xC4, 0xD0, 0x82, 0x0C, 0x08, 0x90, 0x00, 0x30, 0x2C, 0x90, 0xB4, 0x9F, 0x26, 0x97, 0x30, 0x89, + 0x30, 0x93, 0xC6, 0x89, 0xD2, 0x10, 0xC4, 0xD9, 0x82, 0x0A, 0x08, 0x90, 0x00, 0x30, 0x2C, 0x90, + 0x4C, 0xA0, 0x26, 0x97, 0x30, 0x99, 0x30, 0x33, 0xC6, 0x93, 0xB2, 0x05, 0x06, 0x32, 0x53, 0x34, + 0x66, 0x53, 0x66, 0xBA, 0x24, 0x41, 0xCC, 0x40, 0x13, 0x00, 0x24, 0x74, 0x92, 0xC5, 0x24, 0xD1, + 0xC4, 0xDA, 0x2C, 0x60, 0x4C, 0x00, 0x92, 0xBC, 0x04, 0x31, 0x06, 0x21, 0x26, 0x31, 0x0B, 0x7D, + 0x04, 0x00, 0xC4, 0x20, 0x82, 0x9F, 0x04, 0x31, 0x06, 0x21, 0x26, 0x31, 0x06, 0x4D, 0x06, 0x5B, + 0x0B, 0x7D, 0x04, 0x00, 0xC4, 0x20, 0x04, 0x73, 0x82, 0x02, 0x04, 0x71, 0x38, 0x6E, 0x20, 0x00, + 0x3F, 0xCC, 0x06, 0x00, 0xC4, 0xC0, 0x32, 0x02, 0x16, 0xCC, 0xCC, 0xC0, 0xE8, 0x03, 0x02, 0x02, + 0x04, 0x74, 0x18, 0x6E, 0x1C, 0x00, 0xC6, 0x67, 0x92, 0x02, 0x04, 0x70, 0x58, 0xC1, 0x14, 0x00, + 0x58, 0x81, 0x04, 0x00, 0x06, 0x27, 0x2C, 0x10, 0x24, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, + 0xD1, 0xC1, 0x06, 0xE2, 0xCB, 0x31, 0x00, 0x00, 0xEB, 0x2F, 0x00, 0x00, 0x0C, 0x30, 0x00, 0x40, + 0x04, 0x21, 0x4B, 0x3A, 0x00, 0x00, 0x8B, 0x37, 0x00, 0x00, 0x0B, 0x31, 0x00, 0x00, 0x06, 0x2E, + 0xEB, 0xC8, 0x04, 0x00, 0x06, 0xD2, 0x6B, 0x32, 0x00, 0x00, 0x06, 0x7D, 0x6B, 0xE6, 0x04, 0x00, + 0x01, 0x00, 0x05, 0x00, 0x4C, 0x00, 0x10, 0x00, 0x10, 0x00, 0x34, 0x00, 0x34, 0x00, 0x42, 0x00, + 0x6B, 0xAF, 0x01, 0x00, 0x18, 0x3E, 0x24, 0x00, 0xB9, 0x2E, 0x20, 0x00, 0x99, 0xDE, 0x1C, 0x00, + 0x24, 0x31, 0x13, 0x33, 0xC4, 0x34, 0x99, 0x3E, 0x24, 0x00, 0x92, 0x11, 0x38, 0x7E, 0x18, 0x00, + 0x06, 0x2E, 0xF2, 0x0C, 0x6B, 0xAF, 0x01, 0x00, 0xB9, 0x2E, 0x20, 0x00, 0x99, 0xDE, 0x1C, 0x00, + 0xF2, 0x06, 0x38, 0x7E, 0x18, 0x00, 0x06, 0x2E, 0x04, 0x32, 0xF1, 0x70, 0x50, 0xC1, 0x0C, 0x20, + 0x20, 0x4E, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, 0x10, 0x72, 0x6B, 0xE6, + 0x04, 0x00, 0x01, 0x00, 0x05, 0x00, 0x30, 0x00, 0x10, 0x00, 0x16, 0x00, 0x1C, 0x00, 0x22, 0x00, + 0x28, 0x00, 0x38, 0x72, 0x04, 0x00, 0xF2, 0x0C, 0x38, 0x72, 0x0C, 0x00, 0xF2, 0x09, 0x38, 0x72, + 0x10, 0x00, 0xF2, 0x06, 0x38, 0x72, 0x14, 0x00, 0xF2, 0x03, 0x38, 0x72, 0x08, 0x00, 0xF1, 0x70, + 0xF2, 0x02, 0x04, 0x20, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x0C, 0x70, 0xFC, 0x0A, + 0x04, 0x61, 0x99, 0x67, 0x04, 0x0C, 0x08, 0x60, 0x00, 0x80, 0x2C, 0x60, 0x90, 0x94, 0xB9, 0x67, + 0x08, 0x0C, 0x08, 0x60, 0x00, 0x80, 0x2C, 0x60, 0x30, 0x98, 0xB9, 0x67, 0x0C, 0x0C, 0x08, 0x60, + 0x00, 0x80, 0x2C, 0x60, 0xA4, 0x98, 0xB9, 0x67, 0x10, 0x0C, 0x08, 0x60, 0x00, 0x80, 0x2C, 0x60, + 0x9C, 0x9A, 0xB9, 0x67, 0x14, 0x0C, 0x08, 0x60, 0x00, 0x80, 0x2C, 0x60, 0x74, 0x97, 0xB9, 0x67, + 0x18, 0x0C, 0x08, 0x60, 0x00, 0x80, 0x2C, 0x60, 0xC4, 0x97, 0x99, 0x07, 0x20, 0x0C, 0x99, 0x07, + 0x28, 0x0C, 0x99, 0x07, 0x29, 0x0C, 0xB9, 0x67, 0x1C, 0x0C, 0xE1, 0xF0, 0x34, 0x18, 0xC1, 0xE1, + 0x2B, 0x8B, 0x01, 0x00, 0x0C, 0x20, 0x00, 0x17, 0x4B, 0xD9, 0x04, 0x00, 0x06, 0xE2, 0xAB, 0x8B, + 0x01, 0x00, 0xC6, 0xE2, 0xC2, 0x18, 0x36, 0xE2, 0x06, 0x2E, 0x06, 0x7E, 0xD7, 0x72, 0xD7, 0x21, + 0x26, 0x27, 0x36, 0x2E, 0xD7, 0x21, 0x0C, 0x30, 0x10, 0x27, 0xAB, 0x15, 0x00, 0x00, 0xC4, 0x2A, + 0xC2, 0x0A, 0x98, 0x70, 0xA4, 0x1B, 0x82, 0x04, 0xCB, 0x3A, 0x01, 0x00, 0xF2, 0x04, 0x06, 0x2E, + 0x8B, 0xEA, 0x00, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, 0x06, 0x65, 0x0C, 0x60, + 0x74, 0x1A, 0x28, 0x50, 0x74, 0x1A, 0x06, 0x72, 0xC6, 0x25, 0x82, 0x0C, 0x28, 0x56, 0x02, 0x00, + 0xC6, 0x25, 0x82, 0x0A, 0x28, 0x66, 0x04, 0x00, 0x04, 0x20, 0xC6, 0x76, 0x92, 0x07, 0x04, 0x22, + 0xF2, 0x04, 0x04, 0x20, 0xF2, 0x02, 0x04, 0x21, 0x24, 0x21, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, + 0x08, 0x50, 0x00, 0x30, 0x18, 0x30, 0xB6, 0x1B, 0x0C, 0x60, 0x00, 0x0B, 0x04, 0x70, 0x0C, 0x20, + 0x74, 0x1A, 0x0C, 0xF0, 0x28, 0x08, 0x2C, 0x50, 0x00, 0xA0, 0xC4, 0x30, 0x2F, 0x42, 0x07, 0x00, + 0x20, 0x44, 0x92, 0x07, 0x57, 0x41, 0x26, 0x45, 0x30, 0x44, 0x5C, 0x40, 0xFF, 0x7F, 0xF2, 0x04, + 0x26, 0x44, 0x26, 0x4F, 0x20, 0x44, 0x24, 0x72, 0xC4, 0x76, 0xA1, 0x46, 0x24, 0x62, 0x92, 0xEE, + 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x04, 0x70, 0xC6, 0x74, + 0x82, 0x09, 0x2F, 0x67, 0x03, 0x00, 0x60, 0x56, 0x2F, 0x67, 0x02, 0x00, 0x91, 0x56, 0x24, 0x71, + 0xF2, 0xF7, 0xE1, 0xF0, 0x04, 0x70, 0xC6, 0x74, 0x82, 0x06, 0x2F, 0x67, 0x02, 0x00, 0x91, 0x36, + 0x24, 0x71, 0xF2, 0xFA, 0xE1, 0xF0, 0x00, 0x00, 0x71, 0x00, 0xF2, 0xFF, 0x70, 0x6F, 0x36, 0x76, + 0x78, 0x6F, 0x02, 0x00, 0xC6, 0x76, 0xB2, 0x07, 0x26, 0x77, 0x26, 0x7F, 0x78, 0x77, 0x06, 0x00, + 0x26, 0x7F, 0xE1, 0x70, 0x78, 0x7F, 0x04, 0x00, 0x26, 0x7F, 0xE1, 0x70, 0x0B, 0x0C, 0x0D, 0x0C, + 0x0C, 0x0D, 0x0C, 0x0C, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0B, + 0x0D, 0x0E, 0x0C, 0x0C, 0x0D, 0x0D, 0x0C, 0x0B, 0x0A, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x0A, 0x0D, 0x0D, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0B, 0x0A, 0x0A, 0x0A, 0x09, 0x09, + 0x09, 0x09, 0x0A, 0x09, 0x09, 0x0A, 0x0C, 0x0D, 0x0B, 0x0B, 0x0C, 0x0C, 0x0B, 0x0A, 0x0A, 0x0B, + 0x0A, 0x09, 0x0A, 0x09, 0x09, 0x0A, 0x0A, 0x09, 0x0A, 0x0B, 0x0C, 0x0A, 0x0B, 0x0C, 0x0B, 0x0B, + 0x09, 0x0A, 0x0B, 0x0A, 0x09, 0x0A, 0x09, 0x09, 0x0A, 0x0A, 0x09, 0x09, 0x0B, 0x0C, 0x0A, 0x0A, + 0x0B, 0x0B, 0x0A, 0x09, 0x0B, 0x0B, 0x0A, 0x0A, 0x0B, 0x0A, 0x0A, 0x0B, 0x0B, 0x0A, 0x09, 0x0B, + 0x0B, 0x0A, 0x0A, 0x0B, 0x0B, 0x0A, 0x09, 0x0C, 0x0C, 0x0B, 0x0B, 0x0B, 0x0B, 0x0A, 0x0B, 0x0B, + 0x0A, 0x09, 0x0A, 0x0B, 0x0A, 0x0A, 0x0B, 0x0A, 0x0A, 0x08, 0x0C, 0x0C, 0x0B, 0x0B, 0x0B, 0x0B, + 0x0B, 0x0C, 0x0C, 0x0A, 0x09, 0x0B, 0x0B, 0x09, 0x0A, 0x0B, 0x0A, 0x09, 0x08, 0x0C, 0x0D, 0x0C, + 0x0C, 0x0C, 0x0B, 0x0B, 0x0D, 0x0C, 0x0B, 0x09, 0x09, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x0C, 0x0C, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0B, 0x00, 0x00, 0x00, 0x07, 0x0E, 0x09, + 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, 0x70, 0x77, 0x7E, 0x79, + 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, 0xE0, 0xE7, 0xEE, 0xE9, + 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, 0x90, 0x97, 0x9E, 0x99, + 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, 0xC7, 0xC0, 0xC9, 0xCE, + 0xDB, 0xDC, 0xD5, 0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, 0xB7, 0xB0, 0xB9, 0xBE, + 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, 0x27, 0x20, 0x29, 0x2E, + 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, 0x57, 0x50, 0x59, 0x5E, + 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, 0x89, 0x8E, 0x87, 0x80, + 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, 0xF9, 0xFE, 0xF7, 0xF0, + 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, 0x69, 0x6E, 0x67, 0x60, + 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, 0x19, 0x1E, 0x17, 0x10, + 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, 0x4E, 0x49, 0x40, 0x47, + 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, 0x3E, 0x39, 0x30, 0x37, + 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, 0xAE, 0xA9, 0xA0, 0xA7, + 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, 0xDE, 0xD9, 0xD0, 0xD7, + 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3, 0x04, 0x70, 0x06, 0x62, + 0x73, 0x67, 0xD4, 0x61, 0x04, 0x51, 0x26, 0x57, 0x13, 0x55, 0x92, 0x03, 0x06, 0x75, 0xF2, 0xF8, + 0x06, 0x27, 0xE1, 0xF0, 0xC6, 0x23, 0x06, 0x72, 0x02, 0x02, 0x06, 0x73, 0x43, 0x27, 0xE1, 0xF0, + 0x34, 0x18, 0xC1, 0xE1, 0x06, 0xE4, 0xCB, 0x04, 0x00, 0x00, 0x06, 0x3E, 0xCB, 0x04, 0x00, 0x00, + 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x24, 0x00, 0xC6, 0x32, 0x06, 0x73, 0x32, 0x02, 0x06, 0x72, + 0x43, 0x27, 0xE1, 0xF0, 0x34, 0x18, 0xC1, 0xE1, 0x06, 0xE4, 0xEB, 0x05, 0x00, 0x00, 0x06, 0x3E, + 0xEB, 0x05, 0x00, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x24, 0x00, 0x3C, 0x10, 0x10, 0x00, + 0xD1, 0xC1, 0x06, 0xE5, 0x06, 0xD6, 0x4B, 0x06, 0x00, 0x00, 0x06, 0x3E, 0x06, 0x4D, 0x4B, 0x06, + 0x00, 0x00, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x24, 0x00, 0x14, 0x71, 0x26, 0x74, + 0x26, 0x27, 0x16, 0x64, 0x26, 0x37, 0x2F, 0x76, 0x03, 0x00, 0x26, 0x62, 0xC4, 0x40, 0x82, 0x09, + 0x2F, 0x54, 0x07, 0x00, 0x60, 0x35, 0x2F, 0x54, 0x06, 0x00, 0x91, 0x35, 0x34, 0x41, 0xF2, 0xF7, + 0xE1, 0xF0, 0x24, 0x00, 0x04, 0x70, 0xC6, 0x74, 0x82, 0x09, 0x2F, 0x67, 0x03, 0x00, 0x60, 0x56, + 0x2F, 0x67, 0x02, 0x00, 0x91, 0x56, 0x24, 0x71, 0xF2, 0xF7, 0xE1, 0xF0, 0x04, 0x70, 0xC6, 0x74, + 0x82, 0x0A, 0x2F, 0x67, 0x07, 0x00, 0x2F, 0x56, 0x03, 0x00, 0x20, 0x55, 0x26, 0x62, 0xA1, 0x56, + 0x24, 0x71, 0xF2, 0xF6, 0xE1, 0xF0, 0x24, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0x04, 0x70, 0x14, 0x61, + 0x34, 0x41, 0xC6, 0x46, 0x82, 0x09, 0x2F, 0x57, 0x03, 0x00, 0x30, 0xF5, 0x2F, 0x57, 0x02, 0x00, + 0xB1, 0xF5, 0x24, 0x74, 0xF2, 0xF6, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, + 0xD1, 0xC1, 0x04, 0x70, 0x14, 0xF1, 0x34, 0x51, 0xC6, 0x5F, 0x82, 0x0D, 0x2F, 0x67, 0x03, 0x00, + 0x30, 0xD6, 0x2F, 0xE7, 0x02, 0x00, 0xB1, 0xDE, 0x2F, 0xE7, 0x04, 0x00, 0x30, 0xEE, 0x24, 0x74, + 0xB1, 0xE6, 0xF2, 0xF2, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x04, 0x70, 0xC6, 0x74, + 0x82, 0x06, 0x2F, 0x67, 0x02, 0x00, 0x91, 0x36, 0x24, 0x71, 0xF2, 0xFA, 0xE1, 0xF0, 0x24, 0x00, + 0x04, 0x70, 0xC6, 0x74, 0x82, 0x07, 0x2F, 0x67, 0x07, 0x00, 0x26, 0x62, 0xA1, 0x36, 0x24, 0x71, + 0xF2, 0xF9, 0xE1, 0xF0, 0x14, 0x71, 0x34, 0x41, 0xC6, 0x47, 0x82, 0x04, 0xB1, 0x32, 0x24, 0x24, + 0xF2, 0xFB, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xC2, 0x06, 0xD3, 0x06, 0xE3, + 0x06, 0x2E, 0x06, 0x3E, 0x08, 0xF0, 0x00, 0x80, 0x2C, 0xF0, 0x88, 0x02, 0xF1, 0xF0, 0xC6, 0x2C, + 0xC2, 0x02, 0x76, 0xED, 0xF7, 0xD0, 0xC4, 0xD0, 0x82, 0x03, 0x66, 0xED, 0xF2, 0xF2, 0x06, 0x2E, + 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x38, 0x60, 0x68, 0x19, 0x08, 0x70, 0xFD, 0xFF, + 0x2C, 0x70, 0xFF, 0xFF, 0x56, 0x76, 0x08, 0x50, 0x31, 0x00, 0xC6, 0x75, 0x82, 0x05, 0x08, 0x70, + 0x32, 0x00, 0xC6, 0x67, 0x92, 0x03, 0xB1, 0x32, 0xE1, 0xF0, 0xF2, 0x00, 0x08, 0x20, 0x00, 0x40, + 0x34, 0x14, 0x2C, 0x20, 0x10, 0x60, 0x0C, 0x30, 0x00, 0xDE, 0xB1, 0xF1, 0x0B, 0x14, 0x00, 0x00, + 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x24, 0x00, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x07, 0x10, 0x60, + 0xE1, 0xF0, 0x24, 0x00, 0x34, 0x14, 0x0C, 0x70, 0x1E, 0x00, 0xB1, 0x71, 0x30, 0x71, 0x14, 0x61, + 0xC4, 0x70, 0x26, 0x67, 0xB1, 0x61, 0x92, 0xFB, 0x24, 0x14, 0xE1, 0xF0, 0xE1, 0xF0, 0x24, 0x00, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0x72, 0x08, 0xE0, 0x00, 0x40, 0x0C, 0x20, 0x00, 0x60, + 0x06, 0xD3, 0x26, 0x2E, 0x06, 0x37, 0xB9, 0x0E, 0x90, 0x60, 0x0B, 0x14, 0x00, 0x00, 0x0C, 0x20, + 0x08, 0x60, 0xB9, 0xDE, 0x04, 0x60, 0x26, 0x2E, 0x04, 0x30, 0x0B, 0x14, 0x00, 0x00, 0x38, 0x7E, + 0x90, 0x60, 0xD4, 0x71, 0x82, 0xFD, 0x0C, 0x70, 0x00, 0x81, 0xB9, 0x7E, 0x00, 0x60, 0x6B, 0x16, + 0x00, 0x00, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x24, 0x00, 0x3C, 0x10, 0x20, 0x00, + 0xD9, 0xC1, 0x10, 0x00, 0x06, 0x72, 0x08, 0xD0, 0x00, 0x40, 0x0C, 0x20, 0x00, 0x60, 0xD1, 0x81, + 0x06, 0xE3, 0x06, 0xB5, 0x26, 0x2D, 0x06, 0x37, 0x0C, 0xA0, 0x08, 0x60, 0x06, 0xC4, 0x26, 0xBE, + 0x0B, 0x14, 0x00, 0x00, 0x26, 0xAD, 0xC6, 0xEB, 0x82, 0x10, 0xB9, 0xED, 0x04, 0x60, 0x30, 0x3C, + 0x04, 0x91, 0x06, 0x2A, 0x26, 0x9E, 0x0B, 0x14, 0x00, 0x00, 0x38, 0x7D, 0x90, 0x60, 0xD4, 0x72, + 0x82, 0xFD, 0x24, 0xC4, 0x06, 0xE9, 0xF2, 0xF0, 0x0C, 0x70, 0x00, 0x81, 0xB9, 0x7D, 0x00, 0x60, + 0x6B, 0x16, 0x00, 0x00, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, + 0x3C, 0x10, 0x14, 0x00, 0xD9, 0xC1, 0x04, 0x00, 0x86, 0xD6, 0x08, 0x70, 0x00, 0x40, 0x82, 0x05, + 0x0C, 0x60, 0x00, 0xDE, 0xB9, 0x67, 0x10, 0x60, 0xB9, 0x27, 0x00, 0x60, 0xB9, 0x37, 0x04, 0x60, + 0x04, 0x61, 0x04, 0x70, 0x08, 0x20, 0x00, 0x40, 0xC6, 0x75, 0x82, 0x0E, 0xB1, 0x61, 0x30, 0x31, + 0x14, 0xF1, 0xC4, 0x30, 0x26, 0xF3, 0xB1, 0xF1, 0x92, 0xFB, 0x38, 0x32, 0x0C, 0x60, 0x24, 0x71, + 0xB1, 0x34, 0x24, 0x44, 0xF2, 0xF2, 0x08, 0xE0, 0x00, 0x40, 0x0C, 0x70, 0x00, 0x81, 0xB9, 0x7E, + 0x00, 0x60, 0x6B, 0x16, 0x00, 0x00, 0xC4, 0xD0, 0x82, 0x03, 0xB9, 0x0E, 0x10, 0x60, 0x58, 0xC1, + 0x04, 0x00, 0x04, 0x21, 0x2C, 0x10, 0x14, 0x00, 0xE1, 0xF0, 0x24, 0x00, 0x34, 0x18, 0xC1, 0xE1, + 0x08, 0x70, 0x00, 0x40, 0x0C, 0x60, 0x00, 0xDE, 0xB9, 0x67, 0x10, 0x60, 0x77, 0x41, 0xB9, 0x27, + 0x00, 0x60, 0x77, 0x31, 0x34, 0x41, 0x08, 0x60, 0x00, 0x13, 0xB9, 0x37, 0x04, 0x60, 0x66, 0x46, + 0xB9, 0x47, 0x14, 0x60, 0x08, 0x50, 0x00, 0x10, 0x38, 0x67, 0x14, 0x60, 0x0C, 0x40, 0x14, 0x60, + 0xD6, 0x65, 0x26, 0x47, 0x92, 0xFA, 0x38, 0xE7, 0x18, 0x60, 0xB1, 0x04, 0x0C, 0x60, 0x00, 0x81, + 0xB9, 0x67, 0x00, 0x60, 0xB9, 0x07, 0x10, 0x60, 0x6B, 0x16, 0x00, 0x00, 0x06, 0x2E, 0x40, 0xE1, + 0x24, 0x18, 0xE1, 0xF0, 0x29, 0x2A, 0x27, 0x26, 0x29, 0x26, 0x26, 0x2A, 0x29, 0x29, 0x27, 0x1F, + 0x21, 0x1D, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x28, 0x25, 0x23, + 0x26, 0x24, 0x24, 0x27, 0x26, 0x26, 0x23, 0x1F, 0x21, 0x1E, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x25, 0x27, 0x23, 0x23, 0x25, 0x22, 0x23, 0x26, 0x25, 0x26, 0x29, 0x1F, + 0x21, 0x1D, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x26, 0x23, 0x23, + 0x25, 0x23, 0x22, 0x25, 0x24, 0x23, 0x20, 0x20, 0x21, 0x1E, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x26, 0x23, 0x22, 0x25, 0x22, 0x21, 0x24, 0x23, 0x23, 0x1F, 0x20, + 0x22, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x26, 0x22, 0x21, + 0x24, 0x21, 0x20, 0x23, 0x22, 0x22, 0x1F, 0x20, 0x22, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x23, 0x24, 0x21, 0x20, 0x22, 0x20, 0x20, 0x23, 0x22, 0x23, 0x26, 0x20, + 0x22, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x24, 0x21, 0x20, + 0x22, 0x20, 0x1F, 0x22, 0x21, 0x21, 0x1D, 0x21, 0x24, 0x20, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x22, 0x24, 0x20, 0x1F, 0x22, 0x1F, 0x1E, 0x21, 0x21, 0x20, 0x1D, 0x22, + 0x24, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x24, 0x20, 0x1F, + 0x22, 0x1F, 0x1E, 0x21, 0x21, 0x20, 0x1C, 0x23, 0x25, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x22, 0x24, 0x20, 0x1E, 0x21, 0x1F, 0x1F, 0x22, 0x20, 0x20, 0x1C, 0x24, + 0x26, 0x23, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x23, 0x1F, 0x1E, + 0x21, 0x1E, 0x1E, 0x21, 0x20, 0x20, 0x23, 0x24, 0x26, 0x23, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x22, 0x23, 0x20, 0x1F, 0x21, 0x1F, 0x1E, 0x21, 0x20, 0x1F, 0x1C, 0x26, + 0x28, 0x25, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x23, 0x20, 0x1E, + 0x21, 0x1E, 0x1E, 0x21, 0x1F, 0x1F, 0x1B, 0x2A, 0x2C, 0x28, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0xFF, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xFF, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x07, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x18, 0x0E, 0x17, 0x0E, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0x02, 0x06, 0x0B, 0xFF, 0x17, 0x17, 0x17, 0xFF, 0x00, + 0x80, 0x07, 0x38, 0x04, 0xFF, 0x1F, 0xFF, 0x11, 0x40, 0x06, 0x40, 0x06, 0x01, 0xFA, 0xFA, 0x00, + 0x00, 0x02, 0x01, 0x46, 0x00, 0x01, 0x00, 0x02, 0x0A, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x2A, 0x00, 0x00, 0x30, 0x2A, 0x00, 0x00, 0x30, 0x2A, 0x00, 0x00, + 0xA0, 0x86, 0x01, 0x00, 0xC0, 0xE1, 0xE4, 0x00, 0x00, 0x7D, 0x00, 0x00, 0xC8, 0x00, 0xC8, 0x00, + 0xC8, 0x00, 0xC8, 0x00, 0x6E, 0x50, 0x14, 0x28, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x5A, 0x00, + 0x01, 0x00, 0x0A, 0x00, 0xA0, 0x0F, 0x64, 0x64, 0x64, 0x01, 0x38, 0x32, 0x02, 0x04, 0x02, 0x09, + 0x04, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00, 0x3C, 0x00, + 0x05, 0x05, 0x08, 0x0E, 0x11, 0x17, 0x17, 0x17, 0x17, 0x02, 0x03, 0x04, 0x02, 0x01, 0x00, 0x04, + 0x00, 0x06, 0x01, 0x03, 0x08, 0x04, 0x10, 0x03, 0x03, 0x00, 0x90, 0x01, 0x00, 0x00, 0x32, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x3F, 0x01, 0x00, + 0xFF, 0x3F, 0x01, 0x00, 0x42, 0x22, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x88, 0x00, 0x10, 0x1F, 0x10, 0x1F, 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x01, 0x80, 0x40, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x90, 0x00, 0x32, 0x16, 0x22, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, + 0x32, 0x16, 0x22, 0x00, 0x32, 0x16, 0x22, 0x00, 0x32, 0x16, 0x22, 0x00, 0x51, 0x06, 0x03, 0x00, + 0x63, 0x87, 0x02, 0x00, 0x63, 0x87, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x40, 0x0F, 0xB0, 0x0F, 0x00, 0x0E, 0x00, 0x0E, 0x65, 0x32, 0x00, 0x03, 0x66, 0x7F, 0xF0, 0x07, + 0x66, 0x7F, 0xF0, 0x07, 0x42, 0x22, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x88, 0x00, 0x10, 0x1F, 0x10, 0x1F, 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x01, 0x80, 0x40, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x40, 0x28, 0x22, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, + 0x40, 0x28, 0x22, 0x00, 0x40, 0x28, 0x22, 0x00, 0x40, 0x28, 0x22, 0x00, 0x51, 0x06, 0x03, 0x00, + 0x63, 0x87, 0x02, 0x00, 0x63, 0x87, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x40, 0x0F, 0xB0, 0x0F, 0x00, 0x0E, 0x00, 0x0E, 0x65, 0x30, 0x00, 0x03, 0x66, 0x7F, 0xF0, 0x07, + 0x66, 0x7F, 0xF0, 0x07, 0x42, 0x22, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x88, 0x00, 0x10, 0x1F, 0x10, 0x1F, 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x01, 0x80, 0x40, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x90, 0x00, 0x32, 0x16, 0x22, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, + 0x32, 0x32, 0x22, 0x00, 0x32, 0x32, 0x22, 0x00, 0x32, 0x32, 0x22, 0x00, 0x51, 0x06, 0x03, 0x00, + 0x63, 0x87, 0x02, 0x00, 0x63, 0x87, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x40, 0x0F, 0xB0, 0x0F, 0x00, 0x0E, 0x00, 0x0E, 0x65, 0x32, 0x00, 0x03, 0x66, 0x7F, 0xF0, 0x07, + 0x66, 0x7F, 0xF0, 0x07, 0x42, 0x22, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x88, 0x00, 0x10, 0x1F, 0x10, 0x1F, 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x01, 0x80, 0x40, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x40, 0x28, 0x22, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, + 0x40, 0x28, 0x22, 0x00, 0x40, 0x28, 0x22, 0x00, 0x40, 0x28, 0x22, 0x00, 0x51, 0x06, 0x03, 0x00, + 0x63, 0x87, 0x02, 0x00, 0x63, 0x87, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x40, 0x0F, 0xB0, 0x0F, 0x00, 0x0E, 0x00, 0x0E, 0x65, 0x30, 0x00, 0x03, 0x66, 0x7F, 0xF0, 0x07, + 0x66, 0x7F, 0xF0, 0x07, 0x02, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, 0x55, 0x07, 0x05, 0x50, + 0xC8, 0x00, 0x90, 0x01, 0x32, 0x00, 0x32, 0x00, 0x19, 0x19, 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, + 0x00, 0x00, 0x64, 0x64, 0xC8, 0x00, 0x14, 0x00, 0x01, 0x00, 0x32, 0x00, 0x46, 0x00, 0x14, 0x00, + 0x64, 0x00, 0x78, 0x00, 0x96, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x14, 0x00, 0x64, 0x00, + 0x00, 0x00, 0x50, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x1E, 0x00, 0x64, 0x00, 0x20, 0x03, 0x64, 0x00, 0x64, 0x00, 0x14, 0x00, 0x96, 0x00, + 0x00, 0x05, 0x04, 0x0A, 0x05, 0x06, 0xC8, 0x00, 0x05, 0x32, 0x0A, 0x17, 0x19, 0x17, 0x19, 0x1B, + 0x19, 0x19, 0x16, 0x19, 0x1E, 0x1E, 0x1E, 0x19, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x3C, 0x0F, 0x64, + 0x05, 0x1E, 0x20, 0x03, 0xDC, 0x05, 0xC8, 0x00, 0x14, 0x00, 0x28, 0x00, 0x14, 0x00, 0x0A, 0x00, + 0x46, 0x02, 0x01, 0x01, 0x01, 0x00, 0x1E, 0x00, 0x32, 0x00, 0x64, 0x00, 0x14, 0x01, 0x02, 0x03, + 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x14, 0x00, 0x19, 0x00, + 0x32, 0x00, 0x4B, 0x00, 0x64, 0x00, 0x64, 0x00, 0x02, 0x00, 0x64, 0x00, 0x2D, 0x2D, 0x0A, 0x00, + 0x0A, 0x00, 0x28, 0x00, 0x64, 0x00, 0x0A, 0x0A, 0x1E, 0x00, 0x05, 0x0A, 0x01, 0x00, 0x3C, 0x00, + 0x50, 0x00, 0x05, 0x00, 0x1E, 0x00, 0xC8, 0x00, 0x05, 0x05, 0x14, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x55, 0x55, 0x05, 0x00, 0x55, 0x07, 0x05, 0x50, 0xC8, 0x00, 0x90, 0x01, + 0x32, 0x00, 0x32, 0x00, 0x19, 0x19, 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x64, 0x64, + 0xC8, 0x00, 0x14, 0x00, 0x01, 0x00, 0x32, 0x00, 0x46, 0x00, 0x14, 0x00, 0x64, 0x00, 0x78, 0x00, + 0x96, 0x00, 0x64, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x1E, 0x00, 0x64, 0x00, 0x00, 0x00, 0x50, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x1E, 0x00, + 0x1E, 0x00, 0x20, 0x03, 0x64, 0x00, 0x64, 0x00, 0x14, 0x00, 0x96, 0x00, 0x00, 0x05, 0x04, 0x0A, + 0x05, 0x06, 0xDC, 0x00, 0x05, 0x32, 0x0A, 0x17, 0x19, 0x17, 0x19, 0x1B, 0x19, 0x19, 0x16, 0x19, + 0x1E, 0x1E, 0x1E, 0x19, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x3C, 0x0F, 0x64, 0x02, 0x14, 0x20, 0x03, + 0xDC, 0x05, 0xC8, 0x00, 0x14, 0x00, 0x28, 0x00, 0x1E, 0x00, 0x0A, 0x00, 0x46, 0x02, 0x01, 0x01, + 0x01, 0x00, 0x1E, 0x00, 0x32, 0x00, 0x64, 0x00, 0x14, 0x01, 0x02, 0x03, 0x02, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x14, 0x00, 0x19, 0x00, 0x32, 0x00, 0x4B, 0x00, + 0x64, 0x00, 0x64, 0x00, 0x02, 0x00, 0x64, 0x00, 0x2D, 0x2D, 0x0A, 0x00, 0x0A, 0x00, 0x28, 0x00, + 0x64, 0x00, 0x0A, 0x0A, 0x3C, 0x00, 0x05, 0x0A, 0x01, 0x00, 0x3C, 0x00, 0x50, 0x00, 0x05, 0x00, + 0x3C, 0x00, 0xC8, 0x00, 0x05, 0x05, 0x1E, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x90, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0E, 0x18, 0x0E, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x90, 0x00, 0x32, 0x16, 0x22, 0x00, 0x54, 0xFF, 0x0F, 0x00, 0x10, 0x90, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF4, 0x01, 0xC8, 0x00, 0x16, 0x32, 0x10, 0x10, 0x01, 0x00, 0x08, 0x00, + 0x32, 0x00, 0x64, 0x10, 0x51, 0x06, 0x03, 0x00, 0xFF, 0x3F, 0x01, 0x00, 0x18, 0x08, 0x00, 0x00, + 0x64, 0xC0, 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0F, 0xB0, 0x0F, + 0x01, 0x01, 0x80, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x80, 0x00, 0x80, 0x0A, 0x00, 0x00, 0x00, + 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x0E, 0x18, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, + 0x40, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x30, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x22, 0x01, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x16, 0x88, 0x00, 0x10, 0x1F, 0x10, 0x1F, 0x64, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x08, 0x82, + 0x00, 0x00, 0xFF, 0x0F, 0x01, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0xC8, 0x00, 0xF0, 0x0F, + 0x3C, 0x00, 0x08, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x3F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xAC, 0x0D, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x65, 0x32, 0x00, 0x03, + 0xD5, 0xC6, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0E, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0xE9, 0x05, 0x00, + 0x1B, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x31, 0x04, 0x40, 0x00, 0x04, 0x22, 0xC8, 0x00, 0x00, 0xFF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x7F, 0xFC, 0x8F, 0xBF, 0x01, 0x20, 0x00, 0x00, + 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x13, 0x12, 0x11, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x00, + 0x00, 0x00, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x17, 0x00, 0x00, 0xFF, 0x00, 0x20, 0x86, 0x00, 0x00, 0x00, 0x4D, + 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x26, 0x18, 0x00, + 0x3E, 0x26, 0x19, 0x01, 0x3F, 0x27, 0x19, 0x01, 0x3F, 0x27, 0x1A, 0x02, 0x40, 0x28, 0x1A, 0x02, + 0x40, 0x28, 0x1B, 0x03, 0x41, 0x29, 0x1B, 0x03, 0x41, 0x29, 0x1C, 0x04, 0x42, 0x2A, 0x1C, 0x04, + 0x42, 0x2A, 0x1D, 0x05, 0x43, 0x2B, 0x1D, 0x05, 0x43, 0x2B, 0x1E, 0x06, 0x44, 0x2C, 0x1E, 0x06, + 0x44, 0x2C, 0x1F, 0x07, 0x45, 0x2D, 0x1F, 0x07, 0x36, 0x26, 0x10, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x07, 0x13, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4F, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x10, 0x23, 0x98, 0x07, 0x10, 0x23, 0x0C, 0x00, 0x20, 0x1E, 0xFC, 0x0F, 0x20, 0x1E, + 0xFC, 0x0F, 0x30, 0x1A, 0xFC, 0x0F, 0x30, 0x1A, 0x54, 0x06, 0x40, 0x17, 0x1C, 0x00, 0x40, 0x1B, + 0x34, 0x00, 0x50, 0x18, 0xC4, 0x05, 0x50, 0x19, 0x9C, 0x05, 0x50, 0x19, 0x08, 0x00, 0x70, 0x19, + 0x30, 0x00, 0x90, 0x1A, 0xC4, 0x07, 0x90, 0x17, 0x98, 0x03, 0x90, 0x17, 0xB0, 0x02, 0xA0, 0x17, + 0xEC, 0x00, 0xA0, 0x15, 0xFC, 0x0F, 0xA0, 0x16, 0x08, 0x00, 0xB0, 0x18, 0x08, 0x00, 0xB0, 0x18, + 0x34, 0x04, 0xB0, 0x18, 0x2C, 0x00, 0xC0, 0x18, 0x18, 0x00, 0xC0, 0x16, 0x1C, 0x00, 0xF0, 0xBF, + 0x00, 0x0E, 0x10, 0x1D, 0xF4, 0x0F, 0x00, 0x22, 0xFC, 0x0F, 0x10, 0x1D, 0x00, 0x00, 0x10, 0x1E, + 0x30, 0x01, 0x20, 0x20, 0xFC, 0x0F, 0x20, 0x1E, 0xE0, 0x00, 0x30, 0x1A, 0xFC, 0x0F, 0x30, 0x1E, + 0xFC, 0x0F, 0x40, 0x1A, 0x00, 0x00, 0x50, 0x18, 0xB8, 0x07, 0x60, 0x13, 0x10, 0x00, 0x70, 0x19, + 0xE0, 0x00, 0x80, 0x1C, 0xFC, 0x0F, 0x80, 0x19, 0xFC, 0x0F, 0x80, 0x18, 0x0C, 0x00, 0x90, 0x17, + 0x1C, 0x00, 0x90, 0x16, 0xB0, 0x01, 0x90, 0x17, 0x30, 0x01, 0xA0, 0x19, 0x1C, 0x01, 0xA0, 0x19, + 0xDC, 0x00, 0xA0, 0x19, 0x24, 0x07, 0xA0, 0x18, 0xB8, 0x01, 0xC0, 0x15, 0x98, 0x0B, 0xF0, 0xBF, + 0x24, 0x04, 0x10, 0x20, 0xE4, 0x00, 0x00, 0x22, 0xFC, 0x0F, 0x10, 0x1E, 0x24, 0x00, 0x10, 0x1E, + 0x3C, 0x00, 0x20, 0x21, 0x14, 0x00, 0x30, 0x1B, 0xD0, 0x01, 0x30, 0x1C, 0xF4, 0x0F, 0x30, 0x1E, + 0xFC, 0x0F, 0x40, 0x1C, 0x00, 0x00, 0x40, 0x1C, 0x1C, 0x00, 0x50, 0x1C, 0x08, 0x00, 0x70, 0x18, + 0x04, 0x03, 0x80, 0x1B, 0xF4, 0x0F, 0x80, 0x18, 0xFC, 0x0F, 0x80, 0x17, 0xB8, 0x0E, 0x90, 0x17, + 0x90, 0x00, 0x90, 0x15, 0x18, 0x04, 0x90, 0x17, 0x00, 0x00, 0x90, 0x19, 0x0C, 0x00, 0xA0, 0x18, + 0x08, 0x00, 0xA0, 0x19, 0xB8, 0x0E, 0xA0, 0x17, 0xF4, 0x0F, 0xB0, 0x15, 0xFC, 0x0F, 0xF0, 0x2E, + 0x04, 0x00, 0x10, 0x21, 0x0C, 0x04, 0x00, 0x23, 0x04, 0x00, 0x10, 0x1E, 0x38, 0x0E, 0x10, 0x1E, + 0x9C, 0x00, 0x20, 0x22, 0xDC, 0x01, 0x30, 0x1C, 0x80, 0x0D, 0x30, 0x1A, 0xFC, 0x0F, 0x30, 0x1E, + 0xFC, 0x0F, 0x40, 0x1C, 0xB8, 0x0E, 0x40, 0x1C, 0x1C, 0x00, 0x40, 0x19, 0x78, 0x06, 0x70, 0x18, + 0x00, 0x00, 0x70, 0x1C, 0x50, 0x01, 0x80, 0x18, 0xFC, 0x0F, 0x80, 0x17, 0x10, 0x00, 0x90, 0x17, + 0xE0, 0x00, 0x90, 0x16, 0xFC, 0x0F, 0x90, 0x15, 0x3C, 0x00, 0x90, 0x18, 0x24, 0x00, 0x90, 0x19, + 0xD8, 0x01, 0x90, 0x1A, 0x10, 0x00, 0x90, 0x19, 0x04, 0x02, 0xA0, 0x16, 0x1C, 0x00, 0xF0, 0xBF, + 0x00, 0x00, 0x10, 0x21, 0x1C, 0x00, 0x10, 0x23, 0x08, 0x00, 0x20, 0x1E, 0xD0, 0x01, 0x20, 0x1D, + 0xE4, 0x0F, 0x30, 0x1E, 0xFC, 0x0F, 0x30, 0x1A, 0x24, 0x0D, 0x30, 0x1A, 0x0C, 0x07, 0x40, 0x1D, + 0x0C, 0x00, 0x40, 0x1C, 0x08, 0x00, 0x40, 0x1C, 0x1C, 0x04, 0x40, 0x18, 0xF4, 0x0F, 0x70, 0x18, + 0x08, 0x04, 0x70, 0x1B, 0x04, 0x00, 0x80, 0x18, 0x24, 0x0D, 0x80, 0x17, 0xC4, 0x0B, 0x90, 0x17, + 0xF8, 0x0F, 0x90, 0x15, 0xFC, 0x0F, 0x90, 0x16, 0x04, 0x00, 0x90, 0x19, 0x38, 0x0C, 0x90, 0x19, + 0x0C, 0x01, 0x90, 0x19, 0x04, 0x0A, 0x90, 0x18, 0x2C, 0x0E, 0xA0, 0x16, 0xEC, 0x0F, 0xF0, 0xBF, + 0x00, 0x00, 0x10, 0x21, 0x38, 0x0D, 0x10, 0x22, 0x9C, 0x00, 0x20, 0x1E, 0xD4, 0x02, 0x20, 0x1D, + 0x9C, 0x0D, 0x30, 0x1E, 0xFC, 0x0F, 0x30, 0x1C, 0x04, 0x09, 0x40, 0x1A, 0xF8, 0x0F, 0x40, 0x1D, + 0xFC, 0x0F, 0x40, 0x1C, 0x00, 0x01, 0x40, 0x1C, 0xF8, 0x0F, 0x40, 0x19, 0xFC, 0x0F, 0x70, 0x18, + 0x68, 0x06, 0x70, 0x1A, 0x04, 0x00, 0x70, 0x17, 0x58, 0x01, 0x80, 0x16, 0x10, 0x00, 0x80, 0x17, + 0x50, 0x01, 0x80, 0x15, 0xEC, 0x0F, 0x80, 0x16, 0x20, 0x00, 0x90, 0x18, 0xE0, 0x00, 0x90, 0x18, + 0xFC, 0x0F, 0x90, 0x19, 0x14, 0x00, 0x80, 0x19, 0xD8, 0x01, 0x90, 0x16, 0xF4, 0x0F, 0xF0, 0xBF, + 0x84, 0x06, 0x10, 0x21, 0xFC, 0x0F, 0x10, 0x21, 0xFC, 0x0F, 0x20, 0x1C, 0x80, 0x05, 0x20, 0x1B, + 0x0C, 0x00, 0x30, 0x1C, 0x18, 0x0E, 0x30, 0x1A, 0xB8, 0x07, 0x40, 0x19, 0x18, 0x00, 0x40, 0x1C, + 0xB8, 0x07, 0x40, 0x1C, 0x00, 0x00, 0x40, 0x1C, 0xB8, 0x07, 0x40, 0x1E, 0x0C, 0x00, 0x70, 0x18, + 0x04, 0x01, 0x70, 0x1A, 0x1C, 0x00, 0x80, 0x15, 0x1C, 0x00, 0x80, 0x16, 0x00, 0x00, 0x80, 0x17, + 0xD4, 0x05, 0x80, 0x15, 0x9C, 0x0E, 0x80, 0x16, 0xB0, 0x01, 0x90, 0x18, 0x38, 0x01, 0x90, 0x17, + 0x1C, 0x01, 0x90, 0x18, 0xC4, 0x00, 0x80, 0x18, 0x2C, 0x03, 0x90, 0x17, 0xFC, 0x0F, 0xF0, 0x2D, + 0x90, 0x0B, 0x20, 0x20, 0xFC, 0x0F, 0x20, 0x20, 0xFC, 0x0F, 0x30, 0x1A, 0x24, 0x01, 0x30, 0x19, + 0xBC, 0x04, 0x40, 0x1B, 0x2C, 0x04, 0x40, 0x19, 0xF0, 0x02, 0x40, 0x19, 0xFC, 0x0F, 0x40, 0x1C, + 0xFC, 0x0F, 0x50, 0x1A, 0x0C, 0x00, 0x50, 0x1B, 0x1C, 0x01, 0x40, 0x1A, 0xF8, 0x0F, 0x60, 0x17, + 0x00, 0x00, 0x70, 0x18, 0x78, 0x06, 0x80, 0x15, 0x04, 0x00, 0x70, 0x17, 0xC4, 0x00, 0x80, 0x17, + 0xF4, 0x0F, 0x80, 0x15, 0xFC, 0x0F, 0x80, 0x17, 0x10, 0x00, 0x90, 0x18, 0x58, 0x01, 0x90, 0x18, + 0xF4, 0x0F, 0x90, 0x18, 0x04, 0x01, 0x80, 0x18, 0x2C, 0x00, 0x90, 0x16, 0x14, 0x00, 0xF0, 0xBF, + 0xE0, 0x00, 0x20, 0x1E, 0xFC, 0x0F, 0x20, 0x1F, 0xFC, 0x0F, 0x30, 0x1A, 0xC0, 0x01, 0x30, 0x19, + 0xF8, 0x0F, 0x40, 0x1C, 0xFC, 0x0F, 0x40, 0x1A, 0x0C, 0x00, 0x40, 0x19, 0x18, 0x0E, 0x40, 0x1C, + 0xFC, 0x0F, 0x50, 0x1A, 0x10, 0x00, 0x50, 0x1B, 0x7C, 0x01, 0x40, 0x19, 0xB8, 0x07, 0x60, 0x17, + 0x00, 0x00, 0x70, 0x17, 0x7C, 0x01, 0x70, 0x16, 0x3C, 0x01, 0x70, 0x17, 0x08, 0x00, 0x80, 0x16, + 0x18, 0x03, 0x80, 0x14, 0xBC, 0x07, 0x80, 0x16, 0x04, 0x00, 0x90, 0x17, 0x7C, 0x06, 0x90, 0x17, + 0xB8, 0x07, 0x90, 0x18, 0x14, 0x00, 0x80, 0x19, 0x18, 0x00, 0x90, 0x16, 0x14, 0x00, 0xF0, 0xBF, + 0x38, 0x07, 0x20, 0x1E, 0x1C, 0x00, 0x20, 0x1F, 0x1C, 0x00, 0x30, 0x1B, 0x14, 0x00, 0x30, 0x1A, + 0xDC, 0x05, 0x40, 0x1C, 0x3C, 0x07, 0x40, 0x1A, 0x90, 0x0A, 0x40, 0x1A, 0xFC, 0x0F, 0x40, 0x1C, + 0xFC, 0x0F, 0x50, 0x1A, 0xB0, 0x04, 0x50, 0x1B, 0x0C, 0x00, 0x40, 0x19, 0x18, 0x01, 0x70, 0x15, + 0xB8, 0x07, 0x70, 0x16, 0x18, 0x00, 0x70, 0x15, 0xB8, 0x07, 0x70, 0x16, 0x10, 0x00, 0x80, 0x15, + 0x78, 0x06, 0x80, 0x14, 0x04, 0x00, 0x80, 0x16, 0x04, 0x0E, 0x90, 0x16, 0x48, 0x01, 0x90, 0x16, + 0xFC, 0x0F, 0x90, 0x17, 0xE0, 0x00, 0x80, 0x18, 0xFC, 0x0F, 0x90, 0x16, 0xFC, 0x0F, 0xF0, 0xBF, + 0x68, 0x07, 0x30, 0x1E, 0xE4, 0x06, 0x20, 0x1F, 0x74, 0x07, 0x40, 0x1A, 0x04, 0x08, 0x40, 0x19, + 0xF8, 0x06, 0x40, 0x1C, 0x34, 0x07, 0x40, 0x1B, 0x64, 0x07, 0x40, 0x18, 0xDC, 0x06, 0x50, 0x1C, + 0xFC, 0x06, 0x50, 0x1A, 0x20, 0x07, 0x50, 0x1B, 0x2C, 0x08, 0x60, 0x18, 0x18, 0x08, 0x60, 0x15, + 0x54, 0x06, 0x60, 0x17, 0xF0, 0x07, 0x60, 0x17, 0x7C, 0x07, 0x70, 0x16, 0xD4, 0x06, 0x80, 0x15, + 0x00, 0x00, 0x80, 0x14, 0x00, 0x00, 0x80, 0x14, 0x54, 0x00, 0x80, 0x17, 0x0C, 0x0A, 0x80, 0x18, + 0xEC, 0x0F, 0x80, 0x19, 0x34, 0x00, 0x80, 0x18, 0xFC, 0x0F, 0x90, 0x16, 0xFC, 0x0F, 0xF0, 0xBF, + 0x94, 0x0D, 0x30, 0x1E, 0xD4, 0x00, 0x30, 0x1E, 0x70, 0x0D, 0x40, 0x1B, 0x24, 0x00, 0x40, 0x1A, + 0xFC, 0x0F, 0x40, 0x1C, 0xFC, 0x0F, 0x40, 0x19, 0xAC, 0x0C, 0x40, 0x19, 0xF8, 0x0F, 0x50, 0x1A, + 0xFC, 0x0F, 0x50, 0x1A, 0xD0, 0x00, 0x50, 0x1C, 0x1C, 0x08, 0x60, 0x1F, 0x74, 0x00, 0x60, 0x14, + 0x80, 0x07, 0x60, 0x16, 0xFC, 0x0F, 0x60, 0x16, 0xFC, 0x0F, 0x60, 0x17, 0xF0, 0x0F, 0x70, 0x16, + 0xFC, 0x0F, 0x80, 0x13, 0xFC, 0x0F, 0x80, 0x14, 0x00, 0x08, 0x80, 0x17, 0xEC, 0x0F, 0x80, 0x17, + 0xFC, 0x0F, 0x80, 0x18, 0xFC, 0x0F, 0x80, 0x18, 0x1C, 0x0C, 0x80, 0x18, 0xC4, 0x06, 0xF0, 0x2A, + 0x4C, 0x0C, 0x40, 0x20, 0x74, 0x03, 0x40, 0x1F, 0xF8, 0x0F, 0x40, 0x1B, 0x60, 0x0E, 0x40, 0x19, + 0xF8, 0x0F, 0x40, 0x1B, 0xFC, 0x0F, 0x40, 0x1A, 0x08, 0x0C, 0x40, 0x19, 0x5C, 0x00, 0x40, 0x1B, + 0x74, 0x04, 0x50, 0x1A, 0xFC, 0x0F, 0x50, 0x1B, 0xEC, 0x0F, 0x60, 0x18, 0xFC, 0x0F, 0x50, 0x17, + 0xC0, 0x04, 0x60, 0x15, 0xFC, 0x0F, 0x50, 0x17, 0xFC, 0x0F, 0x60, 0x17, 0x60, 0x00, 0x60, 0x18, + 0x14, 0x0C, 0x60, 0x17, 0x20, 0x00, 0x70, 0x17, 0xAC, 0x07, 0x70, 0x1A, 0xFC, 0x0F, 0x70, 0x1A, + 0xFC, 0x0F, 0x80, 0x19, 0x14, 0x00, 0x80, 0x17, 0x8C, 0x0F, 0x80, 0x15, 0xF4, 0x0F, 0xF0, 0x3F, + 0x60, 0x0F, 0x40, 0x1C, 0xFC, 0x0F, 0x40, 0x20, 0xFC, 0x0F, 0x40, 0x1B, 0xE0, 0x09, 0x40, 0x1A, + 0x14, 0x00, 0x40, 0x1B, 0xF4, 0x0F, 0x40, 0x19, 0x04, 0x00, 0x40, 0x19, 0xF8, 0x0F, 0x50, 0x1A, + 0xFC, 0x0F, 0x60, 0x19, 0x60, 0x07, 0x60, 0x18, 0x04, 0x04, 0x60, 0x18, 0x70, 0x00, 0x60, 0x15, + 0x00, 0x0C, 0x60, 0x16, 0x24, 0x00, 0x60, 0x16, 0xF4, 0x0F, 0x70, 0x15, 0xFC, 0x0F, 0x70, 0x17, + 0xFC, 0x0F, 0x70, 0x16, 0xFC, 0x0F, 0x80, 0x16, 0x00, 0x0C, 0x80, 0x19, 0xD4, 0x0F, 0x80, 0x1A, + 0xFC, 0x0F, 0x80, 0x1B, 0x90, 0x04, 0x80, 0x1B, 0xFC, 0x0F, 0x80, 0x1B, 0xFC, 0x0F, 0xF0, 0x3F, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x90, 0xF0, 0x3F, 0x21, 0xB0, 0xF0, 0x3F, 0x42, 0xB0, 0xF0, 0x7F, 0x63, 0xB0, 0xF0, 0x3F, + 0x84, 0xB0, 0xF0, 0x3F, 0xA5, 0xB0, 0xF0, 0x3F, 0xC6, 0xB0, 0xF0, 0x7F, 0xE7, 0xB0, 0xF0, 0x3F, + 0x08, 0xB1, 0xF0, 0x3F, 0x29, 0xB1, 0xF0, 0x3F, 0x4A, 0xB1, 0xF0, 0x3F, 0x6B, 0xB1, 0xF0, 0x7F, + 0x8C, 0xB1, 0xF0, 0x3F, 0xAD, 0xA1, 0xF0, 0x3F, 0x00, 0x80, 0xF0, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, + 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, + 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3B, + 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, + 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x40, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x7F, 0xFC, 0x8F, 0x1F, 0x7F, 0xFC, 0x8F, 0x3F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC3, 0x30, 0x0C, 0x0C, 0xC3, 0x30, 0x0C, + 0x0C, 0xC3, 0x30, 0x0C, 0x0C, 0xC3, 0x30, 0x0C, 0x0C, 0xC3, 0x30, 0x0C, 0x0C, 0xC3, 0x30, 0x0C, + 0x0C, 0xC3, 0x30, 0x0C, 0x0C, 0xC3, 0x30, 0x0C, 0x0C, 0xC3, 0x30, 0x0C, 0x0C, 0xC3, 0x30, 0x0C, + 0x0C, 0xC3, 0x30, 0x0C, 0x0C, 0xC3, 0x30, 0x0C, 0x0C, 0xC3, 0x30, 0x0C, 0x0C, 0xC3, 0x30, 0x0C, + 0x10, 0x04, 0x41, 0x10, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, + 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, + 0x30, 0x30, 0x30, 0x30, 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, + 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0A, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x40, 0x00, 0x40, 0x00, 0x30, 0x00, 0x49, 0x00, 0x30, 0x00, 0xA0, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x35, 0x45, 0x1D, 0x01, 0xC6, 0x9A, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x49, 0x53, 0x54, 0x56, 0x32, 0x54, 0x41, 0x47, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xDC, 0x00, 0x00, + 0x00, 0xDC, 0x00, 0x80, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x80, 0x00, 0x0E, 0x00, 0x00, + 0x00, 0xF0, 0x00, 0x80, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x80, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0xFC, 0x0A, 0x00, 0x00, + 0x00, 0x49, 0x00, 0x30, 0x00, 0xA0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x8C, 0xA9, 0xC4, 0xBB, 0xF5, 0x43, 0x36, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x0C, 0xE0, 0x07, 0x15, 0x09, 0x23, 0x00, 0x49, 0x53, 0x54, 0x56, 0x32, 0x54, 0x41, 0x47 +}; + +#endif \ No newline at end of file diff --git a/drivers/input/touchscreen/ist3038c/Makefile b/drivers/input/touchscreen/ist3038c/Makefile new file mode 100644 index 0000000000000..c8927f5ac3dd1 --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the Imagis touch driver +# + +# Each configuration option enables a list of files. + +obj-$(CONFIG_TOUCHSCREEN_IST3038C) += ist30xxc.o ist30xxc_misc.o ist30xxc_sys.o ist30xxc_update.o ist30xxc_tracking.o ist30xxc_cmcs.o diff --git a/drivers/input/touchscreen/ist3038c/ist30xxc.c b/drivers/input/touchscreen/ist3038c/ist30xxc.c new file mode 100644 index 0000000000000..b485ab5ea1bec --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/ist30xxc.c @@ -0,0 +1,2341 @@ +/* + * Copyright (C) 2010,Imagis Technology Co. Ltd. All Rights Reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_OF +#include +#include +#include +#endif + +#if defined(CONFIG_FB) +#include +#include +#endif + + + +#include "ist30xxc.h" +#include "ist30xxc_update.h" + +#ifdef IST30XX_TRACKING_MODE +#include "ist30xxc_tracking.h" +#endif + +#ifdef IST30XX_DEBUG +#include "ist30xxc_misc.h" +#endif + +#ifdef IST30XX_CMCS_TEST +#include "ist30xxc_cmcs.h" +#endif + +#ifdef IST30XX_USE_KEY +int ist30xx_key_code[] = IST30XX_KEY_CODES; +#ifdef IST30XX_USE_KEY_COORD +int ist30xx_key_x[] = KEY_COORD_X; +#endif +#endif + +struct ist30xx_data *ts_data; +extern int set_usb_charge_mode_par; +int ist30xx_log_level = IST30XX_LOG_LEVEL; + +void tsp_printk(int level, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + if (ist30xx_log_level < level) + return; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + printk("%s %pV", IST30XX_LOG_TAG, &vaf); + + va_end(args); +} + +long get_milli_second(struct ist30xx_data *data) +{ + ktime_get_ts(&data->t_current); + + return data->t_current.tv_sec * 1000 + data->t_current.tv_nsec / 1000000; +} + +void ist30xx_delay(unsigned int ms) +{ + if (ms < 20) + usleep_range(ms * 1000, ms * 1000); + else + msleep(ms); +} + +int ist30xx_intr_wait(struct ist30xx_data *data, long ms) +{ + long start_ms = get_milli_second(data); + long curr_ms = 0; + + while (1) { + if (!data->irq_working) + break; + + curr_ms = get_milli_second(data); + if ((curr_ms < 0) || (start_ms < 0) || (curr_ms - start_ms > ms)) { + tsp_info("%s() timeout(%dms)\n", __func__, ms); + return -EPERM; + } + + ist30xx_delay(2); + } + return 0; +} + +void ist30xx_disable_irq(struct ist30xx_data *data) +{ + if (likely(data->irq_enabled)) { +#ifdef IST30XX_TRACKING_MODE + ist30xx_tracking(TRACK_INTR_DISABLE); +#endif + disable_irq(data->client->irq); + data->irq_enabled = false; + data->status.event_mode = false; + } +} + +void ist30xx_enable_irq(struct ist30xx_data *data) +{ + if (likely(!data->irq_enabled)) { +#ifdef IST30XX_TRACKING_MODE + ist30xx_tracking(TRACK_INTR_ENABLE); +#endif + enable_irq(data->client->irq); + ist30xx_delay(10); + data->irq_enabled = true; + data->status.event_mode = true; + } +} + +void ist30xx_scheduled_reset(struct ist30xx_data *data) +{ + if (likely(data->initialized)) + schedule_delayed_work(&data->work_reset_check, 0); +} + +static void ist30xx_request_reset(struct ist30xx_data *data) +{ + data->irq_err_cnt++; + if (unlikely(data->irq_err_cnt >= data->max_irq_err_cnt)) { + tsp_info("%s()\n", __func__); + ist30xx_scheduled_reset(data); + data->irq_err_cnt = 0; + } +} + +#define NOISE_MODE_TA (0) +#define NOISE_MODE_CALL (1) +#define NOISE_MODE_COVER (2) +#define NOISE_MODE_EDGE (4) +#define NOISE_MODE_POWER (8) +void ist30xx_start(struct ist30xx_data *data) +{ + if (data->initialized) { + data->scan_count = 0; + data->scan_retry = 0; + mod_timer(&data->event_timer, + get_jiffies_64() + EVENT_TIMER_INTERVAL * 2); + } + + data->ignore_delay = true; + + /* TA mode */ + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + ((eHCOM_SET_MODE_SPECIAL << 16) | (data->noise_mode & 0xFFFF))); + + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + ((eHCOM_SET_LOCAL_MODEL << 16) | (TSP_LOCAL_CODE & 0xFFFF))); + + if (data->report_rate >= 0) { + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + ((eHCOM_SET_TIME_ACTIVE << 16) | (data->report_rate & 0xFFFF))); + tsp_info("%s: active rate : %dus\n", __func__, data->report_rate); + } + + if (data->idle_rate >= 0) { + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + ((eHCOM_SET_TIME_IDLE << 16) | (data->idle_rate & 0xFFFF))); + tsp_info("%s: idle rate : %dus\n", __func__, data->idle_rate); + } + + if (data->rec_mode) { + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SET_REC_MODE << 16) | (IST30XX_ENABLE & 0xFFFF)); + tsp_info("%s: rec mode start\n", __func__); + } + + if (data->debugging_mode) { + data->debugging_scancnt = 0; + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SET_DBG_MODE << 16) | (IST30XX_ENABLE & 0xFFFF)); + tsp_info("%s: debugging mode start\n", __func__); + } + + if (data->debug_mode || data->rec_mode || data->debugging_mode) { + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SLEEP_MODE_EN << 16) | (IST30XX_DISABLE & 0xFFFF)); + tsp_info("%s: nosleep mode start\n", __func__); + } + + ist30xx_cmd_start_scan(data); + + data->ignore_delay = false; + + if (data->rec_mode) { + ist30xx_delay(100); + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SET_REC_MODE << 16) | (IST30XX_START_SCAN & 0xFFFF)); + } + + tsp_info("%s, local : %d, mode : 0x%x\n", __func__, TSP_LOCAL_CODE & 0xFFFF, + data->noise_mode & 0xFFFF); +} + +int ist30xx_get_ver_info(struct ist30xx_data *data) +{ + int ret; + + data->fw.prev.main_ver = data->fw.cur.main_ver; + data->fw.prev.fw_ver = data->fw.cur.fw_ver; + data->fw.prev.core_ver = data->fw.cur.core_ver; + data->fw.prev.test_ver = data->fw.cur.test_ver; +#ifdef XIAOMI_PRODUCT + data->fw.prev.lockdown[0] = data->fw.cur.lockdown[0]; + data->fw.prev.lockdown[1] = data->fw.cur.lockdown[1]; + data->fw.prev.config[0] = data->fw.cur.config[0]; + data->fw.prev.config[1] = data->fw.cur.config[1]; +#endif + data->fw.cur.main_ver = 0; + data->fw.cur.fw_ver = 0; + data->fw.cur.core_ver = 0; + data->fw.cur.test_ver = 0; +#ifdef XIAOMI_PRODUCT + data->fw.cur.lockdown[0] = 0; + data->fw.cur.lockdown[1] = 0; + data->fw.cur.config[0] = 0; + data->fw.cur.config[1] = 0; +#endif + + ret = ist30xx_cmd_hold(data, IST30XX_ENABLE); + if (unlikely(ret)) + return ret; + + ret = ist30xx_read_reg(data->client, IST30XX_DA_ADDR(eHCOM_GET_VER_MAIN), + &data->fw.cur.main_ver); + if (unlikely(ret)) + goto err_get_ver; + + ret = ist30xx_read_reg(data->client, IST30XX_DA_ADDR(eHCOM_GET_VER_FW), + &data->fw.cur.fw_ver); + if (unlikely(ret)) + goto err_get_ver; + + ret = ist30xx_read_reg(data->client, IST30XX_DA_ADDR(eHCOM_GET_VER_CORE), + &data->fw.cur.core_ver); + if (unlikely(ret)) + goto err_get_ver; + + ret = ist30xx_read_reg(data->client, IST30XX_DA_ADDR(eHCOM_GET_VER_TEST), + &data->fw.cur.test_ver); + if (unlikely(ret)) + goto err_get_ver; + +#ifdef XIAOMI_PRODUCT + ret = ist30xx_read_reg(data->client, IST30XX_DA_ADDR(eHCOM_GET_LOCKDOWN_1), + &data->fw.cur.lockdown[0]); + if (unlikely(ret)) + goto err_get_ver; + + ret = ist30xx_read_reg(data->client, IST30XX_DA_ADDR(eHCOM_GET_LOCKDOWN_2), + &data->fw.cur.lockdown[1]); + if (unlikely(ret)) + goto err_get_ver; + + ret = ist30xx_read_reg(data->client, IST30XX_DA_ADDR(eHCOM_GET_CONFIG_1), + &data->fw.cur.config[0]); + if (unlikely(ret)) + goto err_get_ver; + + ret = ist30xx_read_reg(data->client, IST30XX_DA_ADDR(eHCOM_GET_CONFIG_2), + &data->fw.cur.config[1]); + if (unlikely(ret)) + goto err_get_ver; +#endif + + ret = ist30xx_cmd_hold(data, IST30XX_DISABLE); + if (unlikely(ret)) + goto err_get_ver; + + tsp_info("IC version main: %x, fw: %x, test: %x, core: %x\n", + data->fw.cur.main_ver, data->fw.cur.fw_ver, data->fw.cur.test_ver, + data->fw.cur.core_ver); +#ifdef XIAOMI_PRODUCT + if (data->lockdown_upper != 0) + data->fw.cur.lockdown[0] = data->lockdown_upper; + + tsp_info("lockdown: %08X%08X, config: %08X%08X\n", + data->fw.cur.lockdown[0], data->fw.cur.lockdown[1], + data->fw.cur.config[0], data->fw.cur.config[1]); +#endif + + return 0; + +err_get_ver: + ist30xx_reset(data, false); + + return ret; +} + +#if defined(IST30XX_GESTURE) +#define WAKEUP_OFF 4 +#define WAKEUP_ON 5 +bool ist30xx_gesture_func_on = true; +static int ist30xx_gesture_switch(struct input_dev *dev, unsigned int type, unsigned int code, int value) +{ + if (type == EV_SYN && code == SYN_CONFIG) { + if (value == WAKEUP_OFF) { + ist30xx_gesture_func_on = false; + } else if (value == WAKEUP_ON) { + ist30xx_gesture_func_on = true; + } + } + return 0; +} +#endif + +int ist30xx_set_input_device(struct ist30xx_data *data) +{ + int ret; + data->input_dev->name = "ist30xx_ts_input"; + data->input_dev->id.bustype = BUS_I2C; + data->input_dev->dev.parent = &data->client->dev; + + input_mt_init_slots(data->input_dev, IST30XX_MAX_FINGERS, 0); + + set_bit(EV_ABS, data->input_dev->evbit); + set_bit(INPUT_PROP_DIRECT, data->input_dev->propbit); + + input_set_abs_params(data->input_dev, ABS_MT_POSITION_X, 0, + data->tsp_info.width - 1, 0, 0); + input_set_abs_params(data->input_dev, ABS_MT_POSITION_Y, 0, + data->tsp_info.height - 1, 0, 0); +#ifdef IST30XX_USE_3D_TOUCH + input_set_abs_params(data->input_dev, ABS_MT_PRESSURE, 0, + IST30XX_MAX_3D_VALUE, 0, 0); +#else + input_set_abs_params(data->input_dev, ABS_MT_TOUCH_MAJOR, 0, + IST30XX_MAX_W, 0, 0); +#endif + +#if (defined(IST30XX_USE_KEY) || defined(IST30XX_GESTURE) || \ + defined(IST30XX_SURFACE_TOUCH) || defined(IST30XX_BLADE_TOUCH)) + set_bit(EV_KEY, data->input_dev->evbit); + set_bit(EV_SYN, data->input_dev->evbit); +#endif +#ifdef IST30XX_USE_KEY + { + int i; + for (i = 0; i < ARRAY_SIZE(ist30xx_key_code); i++) + set_bit(ist30xx_key_code[i], data->input_dev->keybit); + } +#endif +#ifdef IST30XX_GESTURE + input_set_capability(data->input_dev, EV_KEY, KEY_WAKEUP); + tsp_info("regist gesture key!\n"); + data->input_dev->event = ist30xx_gesture_switch; +#endif +#ifdef IST30XX_SURFACE_TOUCH + input_set_capability(data->input_dev, EV_KEY, KEY_MUTE); +#endif +#ifdef IST30XX_BLADE_TOUCH + input_set_capability(data->input_dev, EV_KEY, KEY_SYSRQ); +#endif + + input_set_drvdata(data->input_dev, data); + ret = input_register_device(data->input_dev); + + tsp_info("%s: input register device:%d\n", __func__, ret); + + return ret; +} + +#define CALIB_MSG_MASK (0xF0000FFF) +#define CALIB_MSG_VALID (0x80000CAB) +#define CAL_REF_MSG_MASK (0xFF0000FF) +#define CAL_REF_MSG_VALID (0xAA000055) +#define TRACKING_INTR_VALID (0x127EA597) +#define TRACKING_INTR_DEBUG1_VALID (0x127A6E81) +#define TRACKING_INTR_DEBUG2_VALID (0x127A6E82) +#define TRACKING_INTR_DEBUG3_VALID (0x127A6E83) +int ist30xx_get_info(struct ist30xx_data *data) +{ + int ret; + u32 calib_msg; +#ifdef IST30XX_TRACKING_MODE + u32 tracking_value; + u32 ms; +#endif + + mutex_lock(&data->lock); + ist30xx_disable_irq(data); + +#ifdef IST30XX_INTERNAL_BIN + ist30xx_get_tsp_info(data); +#else + ret = ist30xx_get_ver_info(data); + if (unlikely(ret)) + goto err_get_info; + + ret = ist30xx_get_tsp_info(data); + if (unlikely(ret)) + goto err_get_info; +#endif /* IST30XX_INTERNAL_BIN */ + + ret = ist30xx_set_input_device(data); + if (unlikely(ret)) + goto err_get_info; + + ist30xx_print_info(data); + +#ifndef IST30XX_UPDATE_NO_CAL + if (data->fw_mode == IST30XX_CAL_MODE) { + ret = ist30xx_read_cmd(data, eHCOM_GET_CAL_RESULT, &calib_msg); + if (likely(ret == 0)) { + tsp_info("calib status: 0x%08x\n", calib_msg); +#ifdef IST30XX_TRACKING_MODE + ms = get_milli_second(data); + tracking_value = TRACKING_INTR_VALID; + ist30xx_put_track_ms(ms); + ist30xx_put_track(&tracking_value, 1); + ist30xx_put_track(&calib_msg, 1); +#endif + if ((calib_msg & CALIB_MSG_MASK) != CALIB_MSG_VALID || + CALIB_TO_STATUS(calib_msg) > 0) { + ist30xx_calibrate(data, IST30XX_MAX_RETRY_CNT); + } + } + } +#endif + +#ifdef IST30XX_CHECK_CALIB + if (data->fw_mode == IST30XX_CAL_MODE) { + if ((!data->status.update) && (!data->status.calib != 1)) { + ret = ist30xx_cmd_check_calib(data); + if (likely(!ret)) { + data->status.calib = 2; + data->status.calib_msg = 0; + data->event_ms = (u32)get_milli_second(data); + data->status.event_mode = true; + } + } + } +#endif + + ist30xx_enable_irq(data); + mutex_unlock(&data->lock); + + return 0; + +err_get_info: + mutex_unlock(&data->lock); + + return ret; +} + +#if (defined(IST30XX_GESTURE) || defined(IST30XX_SURFACE_TOUCH) || \ + defined(IST30XX_BLADE_TOUCH)) +#define SPECIAL_MAGIC_STRING (0x4170CF00) +#define SPECIAL_MAGIC_MASK (0xFFFFFF00) +#define SPECIAL_MESSAGE_MASK (~SPECIAL_MAGIC_MASK) +#define PARSE_SPECIAL_MESSAGE(n) \ + ((n & SPECIAL_MAGIC_MASK) == SPECIAL_MAGIC_STRING ? \ + (n & SPECIAL_MESSAGE_MASK) : -EINVAL) +#define SPECIAL_START_MASK (0x80) +#define SPECIAL_SUCCESS_MASK (0x0F) +#define MAX_LK_KEYCODE_NUM (256) +static unsigned short lk_keycode[MAX_LK_KEYCODE_NUM] = { + [0x01] = KEY_WAKEUP, + [0x02] = KEY_PLAYPAUSE, + [0x03] = KEY_NEXTSONG, + [0x04] = KEY_PREVIOUSSONG, + [0x05] = KEY_VOLUMEUP, + [0x06] = KEY_VOLUMEDOWN, + [0x07] = KEY_MUTE, + [0x21] = KEY_MUTE, + [0x11] = KEY_SYSRQ, + [0x12] = KEY_SYSRQ, + [0x13] = KEY_SYSRQ, + [0x14] = KEY_SYSRQ, + [0x41] = KEY_A, + [0x42] = KEY_B, + [0x43] = KEY_C, + [0x44] = KEY_D, + [0x45] = KEY_E, + [0x46] = KEY_F, + [0x47] = KEY_G, + [0x48] = KEY_H, + [0x49] = KEY_I, + [0x4A] = KEY_J, + [0x4B] = KEY_K, + [0x4C] = KEY_L, + [0x4D] = KEY_M, + [0x4E] = KEY_N, + [0x4F] = KEY_O, + [0x50] = KEY_P, + [0x51] = KEY_Q, + [0x52] = KEY_R, + [0x53] = KEY_S, + [0x54] = KEY_T, + [0x55] = KEY_U, + [0x56] = KEY_V, + [0x57] = KEY_W, + [0x58] = KEY_X, + [0x59] = KEY_Y, + [0x5A] = KEY_Z, + [0x91] = KEY_KP1, + [0x92] = KEY_VOLUMEDOWN, + [0x93] = KEY_KP3, + [0x94] = KEY_PREVIOUSSONG, + [0x95] = KEY_KP5, + [0x96] = KEY_NEXTSONG, + [0x97] = KEY_KP7, + [0x98] = KEY_VOLUMEUP, + [0x99] = KEY_KP9, +}; + +void ist30xx_special_cmd(struct ist30xx_data *data, int cmd) +{ +#ifdef IST30XX_GESTURE + if (cmd == 0x22) { + tsp_info("Double Tap Gesture\n"); + input_report_key(data->input_dev, KEY_WAKEUP, 1); + input_sync(data->input_dev); + input_report_key(data->input_dev, KEY_WAKEUP, 0); + input_sync(data->input_dev); + + return; + } + if (((cmd > 0x40) && (cmd < 0x5B)) || ((cmd > 0x90) && (cmd < 0x9A))) { + tsp_info("Gesture touch: 0x%02X\n", cmd); + + if ((cmd != 0x92) && (cmd != 0x94) && (cmd != 0x96) && (cmd != 0x98)) { + input_report_key(data->input_dev, KEY_WAKEUP, 1); + input_sync(data->input_dev); + input_report_key(data->input_dev, KEY_WAKEUP, 0); + input_sync(data->input_dev); + + ist30xx_delay(500); + } + + input_report_key(data->input_dev, lk_keycode[cmd], 1); + input_sync(data->input_dev); + input_report_key(data->input_dev, lk_keycode[cmd], 0); + input_sync(data->input_dev); + + return; + } +#endif +#ifdef IST30XX_SURFACE_TOUCH + if (((cmd & (~SPECIAL_START_MASK)) >= 0x20) && + ((cmd & (~SPECIAL_START_MASK)) <= 0x21)) { + if (cmd & SPECIAL_START_MASK) { + tsp_info("Surface touch start: 0x%02X\n", cmd); + } else { + if ((cmd & SPECIAL_SUCCESS_MASK) > 0) { + tsp_info("Surface touch stop: 0x%02X\n", cmd); + input_report_key(data->input_dev, lk_keycode[cmd], 1); + input_sync(data->input_dev); + input_report_key(data->input_dev, lk_keycode[cmd], 0); + input_sync(data->input_dev); + } else { + tsp_info("Surface touch cancel: 0x%02X\n", cmd); + } + } + + return; + } +#endif +#ifdef IST30XX_BLADE_TOUCH + if (((cmd & (~SPECIAL_START_MASK)) >= 0x10) && + ((cmd & (~SPECIAL_START_MASK)) <= 0x14)) { + if (cmd & SPECIAL_START_MASK) { + tsp_info("Blade touch start: 0x%02X\n", cmd); + } else { + if ((cmd & SPECIAL_SUCCESS_MASK) > 0) { + tsp_info("Blade touch stop: 0x%02X\n", cmd); + input_report_key(data->input_dev, lk_keycode[cmd], 1); + input_sync(data->input_dev); + input_report_key(data->input_dev, lk_keycode[cmd], 0); + input_sync(data->input_dev); + } else { + tsp_info("Blade touch cancel: 0x%02X\n", cmd); + } + } + + return; + } +#endif + + tsp_warn("Not support gesture cmd: 0x%02X\n", cmd); +} +#endif + +#define PRESS_MSG_MASK (0x01) +#define MULTI_MSG_MASK (0x02) +#define TOUCH_DOWN_MESSAGE ("p") +#define TOUCH_UP_MESSAGE ("r") +#define TOUCH_MOVE_MESSAGE (" ") +void print_tsp_event(struct ist30xx_data *data, int id, finger_info *finger) +{ + bool press; + + press = PRESSED_FINGER(data->t_status, id); + + if (press) { + if (data->tsp_touched[id] == false) { + /* touch down */ +#ifdef IST30XX_USE_3D_TOUCH + tsp_noti("%s%d (%d, %d)(f:%d)\n", TOUCH_DOWN_MESSAGE, id + 1, + finger->bit_field.x, finger->bit_field.y, + finger->bit_field.f); +#else + tsp_noti("%s%d (%d, %d)\n", TOUCH_DOWN_MESSAGE, id + 1, + finger->bit_field.x, finger->bit_field.y); +#endif + data->tsp_touched[id] = true; + } else { + /* touch move */ +#ifdef IST30XX_USE_3D_TOUCH + tsp_debug("%s%d (%d, %d)(f:%d)\n", TOUCH_MOVE_MESSAGE, id + 1, + finger->bit_field.x, finger->bit_field.y, + finger->bit_field.f); +#else + tsp_debug("%s%d (%d, %d)\n", TOUCH_MOVE_MESSAGE, id + 1, + finger->bit_field.x, finger->bit_field.y); +#endif + } + } else { + if (data->tsp_touched[id] == true) { + /* touch up */ + tsp_noti("%s%d\n", TOUCH_UP_MESSAGE, id + 1); + data->tsp_touched[id] = false; + } + } +} +#ifdef IST30XX_USE_KEY +#define PRESS_MSG_KEY (0x06) +void print_tkey_event(struct ist30xx_data *data, int id) +{ + bool press = PRESSED_KEY(data->t_status, id); + + if (press) { + if (data->tkey_pressed[id] == false) { + /* tkey down */ + tsp_noti("k %s%d\n", TOUCH_DOWN_MESSAGE, id + 1); + data->tkey_pressed[id] = true; + } + } else { + if (data->tkey_pressed[id] == true) { + /* tkey up */ + tsp_noti("k %s%d\n", TOUCH_UP_MESSAGE, id + 1); + data->tkey_pressed[id] = false; + } + } +} +#endif +static void release_finger(struct ist30xx_data *data, int id) +{ + input_mt_slot(data->input_dev, id); + input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, false); + +#ifdef IST30XX_TRACKING_MODE + ist30xx_tracking(TRACK_POS_FINGER + id + 1); +#endif + tsp_info("forced touch release: %d\n", id + 1); + + data->tsp_touched[id] = false; + if (data->debugging_mode && (id < 2)) + data->t_frame[id] = 0; + + input_sync(data->input_dev); +} + +#ifdef IST30XX_USE_KEY +static void release_key(struct ist30xx_data *data, int id) +{ + input_report_key(data->input_dev, ist30xx_key_code[id], false); + +#ifdef IST30XX_TRACKING_MODE + ist30xx_tracking(TRACK_POS_KEY + id + 1); +#endif + tsp_info("forced key release: %d\n", id + 1); + + data->tkey_pressed[id] = false; + + input_sync(data->input_dev); +} +#endif +static void clear_input_data(struct ist30xx_data *data) +{ + int id = 0; + u32 status; + + status = PARSE_FINGER_STATUS(data->t_status); + while (status) { + if (status & 1) + release_finger(data, id); + status >>= 1; + id++; + } +#ifdef IST30XX_USE_KEY + id = 0; + status = PARSE_KEY_STATUS(data->t_status); + while (status) { + if (status & 1) + release_key(data, id); + status >>= 1; + id++; + } +#endif + + data->t_status = 0; +} + +static int check_valid_coord(u32 *msg, int cnt) +{ + u8 *buf = (u8 *)msg; + u8 chksum1 = msg[0] >> 24; + u8 chksum2 = 0; + u32 tmp = msg[0]; + + msg[0] &= 0x00FFFFFF; + + cnt *= IST30XX_DATA_LEN; + + while (cnt--) + chksum2 += *buf++; + + msg[0] = tmp; + + if (chksum1 != chksum2) { + tsp_err("intr chksum: %02x, %02x\n", chksum1, chksum2); + return -EPERM; + } + + return 0; +} + +static void report_input_data(struct ist30xx_data *data, int finger_counts, + int key_counts) +{ + int id; + bool press = false; + finger_info *fingers = (finger_info *)data->fingers; + + int idx = 0; + u32 status; + + memset(data->t_frame, 0, sizeof(data->t_frame)); + + status = PARSE_FINGER_STATUS(data->t_status); + for (id = 0; id < IST30XX_MAX_FINGERS; id++) { + press = (status & (1 << id)) ? true : false; + + input_mt_slot(data->input_dev, id); + input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, press); + + print_tsp_event(data, id, &fingers[idx]); + + if (press == false) + continue; + + if (data->debugging_mode && (id < 2)) + data->t_frame[id] = fingers[idx].full_field; + + input_report_abs(data->input_dev, ABS_MT_POSITION_X, + fingers[idx].bit_field.x); + input_report_abs(data->input_dev, ABS_MT_POSITION_Y, + fingers[idx].bit_field.y); +#ifdef IST30XX_USE_3D_TOUCH + input_report_abs(data->input_dev, ABS_MT_PRESSURE, + fingers[idx].bit_field.f); +#else + input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, + fingers[idx].bit_field.w); +#endif + idx++; + } + +#ifdef IST30XX_USE_KEY + status = PARSE_KEY_STATUS(data->t_status); + for (id = 0; id < ARRAY_SIZE(ist30xx_key_code); id++) { + press = (status & (1 << id)) ? true : false; + + input_report_key(data->input_dev, ist30xx_key_code[id], press); + + print_tkey_event(data, id); + } +#endif + + data->irq_err_cnt = 0; + data->scan_retry = 0; + + input_sync(data->input_dev); +} + +void recording_data(struct ist30xx_data *data, bool idle) +{ + int ret; + int i; + int count = 0; + mm_segment_t old_fs = { 0 }; + struct file *fp = NULL; + u32 addr = 0; + u32 len; + u32 *buf32; + const int msg_len = 128; + char msg[msg_len]; + char *buf; + TSP_INFO *tsp = &data->tsp_info; + + if (idle && (data->rec_mode > 1)) + goto state_idle; + + ist30xx_delay(data->rec_delay); + + buf32 = kzalloc(IST30XX_MAX_NODE_NUM * sizeof(u32), GFP_KERNEL); + buf = kzalloc(IST30XX_MAX_NODE_NUM * 20, GFP_KERNEL); + + for (i = data->rec_start_ch.tx; i <= data->rec_stop_ch.tx; i++) { + addr = ((i * tsp->ch_num.rx + data->rec_start_ch.rx) * IST30XX_DATA_LEN) + + IST30XX_DA_ADDR(data->raw_addr); + len = data->rec_stop_ch.rx - data->rec_start_ch.rx + 1; + ret = ist30xx_burst_read(data->client, addr, + buf32 + (i * tsp->ch_num.rx + data->rec_start_ch.rx), len, + true); + if (ret) + goto err_rec_fail; + } + + for (i = 0; i < IST30XX_MAX_NODE_NUM; i++) { + count += snprintf(msg, msg_len, "%08x ", buf32[i]); + strncat(buf, msg, msg_len); + } + + for (i = 0; i < IST30XX_MAX_NODE_NUM; i++) { + count += snprintf(msg, msg_len, "%08x ", 0); + strncat(buf, msg, msg_len); + } + + count += snprintf(msg, msg_len, "\n"); + strncat(buf, msg, msg_len); + + old_fs = get_fs(); + set_fs(get_ds()); + + fp = filp_open(data->rec_file_name, O_CREAT|O_WRONLY|O_APPEND, 0); + if (IS_ERR(fp)) { + tsp_err("file %s open error:%d\n", data->rec_file_name, PTR_ERR(fp)); + goto err_file_open; + } + + fp->f_op->write(fp, buf, count, &fp->f_pos); + fput(fp); + + filp_close(fp, NULL); + +err_file_open: + set_fs(old_fs); + +err_rec_fail: + kfree(buf32); + kfree(buf); + +state_idle: + data->ignore_delay = true; + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SET_REC_MODE << 16) | (IST30XX_START_SCAN & 0xFFFF)); + data->ignore_delay = false; +} + +static void cal_ref_work_func(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct ist30xx_data *data = container_of(delayed_work, struct ist30xx_data, + work_cal_reference); + + mutex_lock(&data->lock); + ist30xx_reset(data, false); + ist30xx_cal_reference(data); + mutex_unlock(&data->lock); + + data->cal_ref_count++; +} + +void ist30xx_scheduled_cal_ref(struct ist30xx_data *data) +{ + if (data->initialized) + schedule_delayed_work(&data->work_cal_reference, 0); +} + +/* + * CMD : CMD_GET_COORD + * + * 1st [31:24] [23:21] [20:16] [15:12] [11:10] [9:0] + * Checksum KeyCnt KeyStatus FingerCnt Rsvd. FingerStatus + * 2nd [31:28] [27:24] [23:12] [11:0] + * ID Area X Y + */ +static irqreturn_t ist30xx_irq_thread(int irq, void *ptr) +{ + int i, ret; + int key_cnt, finger_cnt, read_cnt; + struct ist30xx_data *data = (struct ist30xx_data *)ptr; + int offset = 1; + u32 t_status; + u32 msg[IST30XX_MAX_FINGERS * 2 + offset]; + u32 *buf32; + u32 debugBuf32[IST30XX_MAX_DEBUGINFO / IST30XX_DATA_LEN]; +#ifdef IST30XX_TRACKING_MODE + u32 tracking_value; +#endif + u32 ms; + u32 touch[2]; + u32 result; + bool idle = false; + + data->irq_working = true; + + if (unlikely(!data->irq_enabled)) + goto irq_ignore; + + ms = get_milli_second(data); + + if (data->debugging_mode) { + ist30xx_burst_read(data->client, + IST30XX_DA_ADDR(data->debugging_addr), debugBuf32, + data->debugging_size / IST30XX_DATA_LEN, true); + } + +#ifdef IST30XX_DEBUG + if (data->intr_debug1_size > 0) { + buf32 = kzalloc(data->intr_debug1_size * sizeof(u32), GFP_KERNEL); + tsp_debug("Intr_debug1 (addr: 0x%08x)\n", data->intr_debug1_addr); + ist30xx_burst_read(data->client, + IST30XX_DA_ADDR(data->intr_debug1_addr), buf32, + data->intr_debug1_size, true); + + for (i = 0; i < data->intr_debug1_size; i++) + tsp_debug("\t%08x\n", buf32[i]); +#ifdef IST30XX_TRACKING_MODE + tracking_value = TRACKING_INTR_DEBUG1_VALID; + ist30xx_put_track_ms(ms); + ist30xx_put_track(&tracking_value, 1); + ist30xx_put_track(buf32, data->intr_debug1_size); +#endif + kfree(buf32); + } + + if (data->intr_debug2_size > 0) { + buf32 = kzalloc(data->intr_debug2_size * sizeof(u32), GFP_KERNEL); + tsp_debug("Intr_debug2 (addr: 0x%08x)\n", data->intr_debug2_addr); + ist30xx_burst_read(data->client, + IST30XX_DA_ADDR(data->intr_debug2_addr), buf32, + data->intr_debug2_size, true); + + for (i = 0; i < data->intr_debug2_size; i++) + tsp_debug("\t%08x\n", buf32[i]); +#ifdef IST30XX_TRACKING_MODE + tracking_value = TRACKING_INTR_DEBUG2_VALID; + ist30xx_put_track_ms(ms); + ist30xx_put_track(&tracking_value, 1); + ist30xx_put_track(buf32, data->intr_debug2_size); +#endif + kfree(buf32); + } +#endif + memset(msg, 0, sizeof(msg)); + + ret = ist30xx_read_reg(data->client, IST30XX_HIB_INTR_MSG, msg); + if (unlikely(ret)) + goto irq_err; + + tsp_verb("intr msg: 0x%08x\n", *msg); + + /* TSP End Initial */ + if (unlikely(*msg == IST30XX_INITIAL_VALUE)) { + tsp_debug("End Initial\n"); + goto irq_event; + } + + /* TSP Recording */ + if (unlikely(*msg == IST30XX_REC_VALUE)) { + idle = true; + goto irq_end; + } + + /* TSP Debugging */ + if (unlikely(*msg == IST30XX_DEBUGGING_VALUE)) + goto irq_end; + + /* TSP IC Exception */ + if (unlikely((*msg & IST30XX_EXCEPT_MASK) == IST30XX_EXCEPT_VALUE)) { + tsp_err("Occured IC exception(0x%02X)\n", *msg & 0xFF); + ret = ist30xx_burst_read(data->client, IST30XX_HIB_COORD, + &msg[offset], IST30XX_MAX_EXCEPT_SIZE, true); + if (unlikely(ret)) + tsp_err(" exception value read error(%d)\n", ret); + else + tsp_err(" exception value : 0x%08X, 0x%08X\n", msg[1], msg[2]); + + goto irq_ic_err; + } + + if (unlikely(*msg == 0 || *msg == 0xFFFFFFFF)) /* Unknown CMD */ + goto irq_err; + +#ifdef IST30XX_TRACKING_MODE + tracking_value = TRACKING_INTR_VALID; + ist30xx_put_track_ms(ms); + ist30xx_put_track(&tracking_value, 1); + ist30xx_put_track(msg, 1); +#endif + + if (unlikely((*msg & CALIB_MSG_MASK) == CALIB_MSG_VALID)) { + data->status.calib_msg = *msg; + tsp_info("calib status: 0x%08X\n", data->status.calib_msg); + + goto irq_event; + } + + if (unlikely((*msg & CAL_REF_MSG_MASK) == CAL_REF_MSG_VALID)) { + data->status.cal_ref_msg = *msg; + tsp_info("cal ref status: 0x%08X\n", data->status.cal_ref_msg); + if ((data->status.update != 1) && (data->status.calib == 0)) { + if (data->cal_ref_count < IST30XX_MAX_CAL_REF_CNT) { + result = CAL_REF_TO_STATUS(data->status.cal_ref_msg); + if ((result & CAL_REF_NONE) || + (result & CAL_REF_FAIL_UNKNOWN) || + (result & CAL_REF_FAIL_CRC) || + (result & CAL_REF_FAIL_VERIFY)) + ist30xx_scheduled_cal_ref(data); + } + } + + goto irq_event; + } + +#ifdef IST30XX_CMCS_TEST + if (((*msg & CMCS_MSG_MASK) == CM_MSG_VALID) || + ((*msg & CMCS_MSG_MASK) == CM2_MSG_VALID) || + ((*msg & CMCS_MSG_MASK) == CS_MSG_VALID) || + ((*msg & CMCS_MSG_MASK) == CMJIT_MSG_VALID) || + ((*msg & CMCS_MSG_MASK) == INT_MSG_VALID)) { + data->status.cmcs = *msg; + tsp_info("CMCS notify: 0x%08X\n", *msg); + + goto irq_event; + } +#endif + +#if (defined(IST30XX_GESTURE) || defined(IST30XX_SURFACE_TOUCH) || \ + defined(IST30XX_BLADE_TOUCH)) + if (ist30xx_gesture_func_on) { + ret = PARSE_SPECIAL_MESSAGE(*msg); + if (unlikely(ret > 0)) { + tsp_verb("special cmd: %d (0x%08X)\n", ret, *msg); + ist30xx_special_cmd(data, ret); + + goto irq_event; + } + } +#endif + + memset(data->fingers, 0, sizeof(data->fingers)); + + /* Unknown interrupt data for extend coordinate */ + if (unlikely(!CHECK_INTR_STATUS(*msg))) + goto irq_err; + + t_status = *msg; + key_cnt = PARSE_KEY_CNT(t_status); + finger_cnt = PARSE_FINGER_CNT(t_status); + + if (unlikely((finger_cnt > data->max_fingers) || + (key_cnt > data->max_keys))) { + tsp_warn("Invalid touch count - finger: %d(%d), key: %d(%d)\n", + finger_cnt, data->max_fingers, key_cnt, data->max_keys); + goto irq_err; + } + + if (finger_cnt > 0) { + ret = ist30xx_burst_read(data->client, IST30XX_HIB_COORD, &msg[offset], + finger_cnt, true); + if (unlikely(ret)) + goto irq_err; + + for (i = 0; i < finger_cnt; i++) + data->fingers[i].full_field = msg[i + offset]; + +#ifdef IST30XX_TRACKING_MODE + ist30xx_put_track(msg + offset, finger_cnt); +#endif + for (i = 0; i < finger_cnt; i++) { + tsp_verb("intr msg(%d): 0x%08x, %d\n", + i + offset, msg[i + offset], data->z_values[i]); + } + } + + read_cnt = finger_cnt + 1; + + ret = check_valid_coord(&msg[0], read_cnt); + if (unlikely(ret)) + goto irq_err; + + data->t_status = t_status; + report_input_data(data, finger_cnt, key_cnt); + +#ifdef IST30XX_DEBUG + if (data->intr_debug3_size > 0) { + buf32 = kzalloc(data->intr_debug3_size * sizeof(u32), GFP_KERNEL); + tsp_debug("Intr_debug3 (addr: 0x%08x)\n", data->intr_debug3_addr); + ist30xx_burst_read(data->client, + IST30XX_DA_ADDR(data->intr_debug3_addr), buf32, + data->intr_debug3_size, true); + + for (i = 0; i < data->intr_debug3_size; i++) + tsp_debug("\t%08x\n", buf32[i]); +#ifdef IST30XX_TRACKING_MODE + tracking_value = TRACKING_INTR_DEBUG3_VALID; + ist30xx_put_track_ms(ms); + ist30xx_put_track(&tracking_value, 1); + ist30xx_put_track(buf32, data->intr_debug3_size); +#endif + kfree(buf32); + } +#endif + + goto irq_end; + +irq_err: + tsp_err("intr msg: 0x%08x, ret: %d\n", msg[0], ret); +#ifdef IST30XX_GESTURE + if (!data->suspend) +#endif + ist30xx_request_reset(data); + goto irq_event; +irq_end: + if (data->rec_mode) + recording_data(data, idle); + if (data->debugging_mode) { + if ((data->debugging_scancnt == debugBuf32[0]) && data->debugging_noise) + goto irq_event; + + memset(touch, 0, sizeof(touch)); + touch[0] = data->t_frame[0]; + touch[1] = data->t_frame[1]; + +#ifdef IST30XX_DEBUG + ist30xx_put_frame(data, ms, touch, debugBuf32, + data->debugging_size / IST30XX_DATA_LEN); + data->debugging_scancnt = debugBuf32[0]; +#endif + } +irq_event: +irq_ignore: + data->irq_working = false; + data->event_ms = (u32)get_milli_second(data); + if (data->initialized) + mod_timer(&data->event_timer, get_jiffies_64() + EVENT_TIMER_INTERVAL); + return IRQ_HANDLED; + +irq_ic_err: + ist30xx_scheduled_reset(data); + data->irq_working = false; + data->event_ms = (u32)get_milli_second(data); + if (data->initialized) + mod_timer(&data->event_timer, get_jiffies_64() + EVENT_TIMER_INTERVAL); + return IRQ_HANDLED; +} + +static int ist30xx_power_init(struct ist30xx_data *data) +{ + int ret; + + data->vdd = regulator_get(&data->client->dev, "vdd"); + if (IS_ERR(data->vdd)) { + ret = PTR_ERR(data->vdd); + tsp_err("Regulator get failed vdd ret=%d\n", ret); + return ret; + } + + ret = regulator_set_voltage(data->vdd, 2850000, 2850000); + if (ret) { + tsp_err("Regulator set_vtg failed vdd ret=%d\n", ret); + return ret; + } + + data->vddio = regulator_get(&data->client->dev, "vcc_i2c"); + if (IS_ERR(data->vddio)) { + ret = PTR_ERR(data->vddio); + tsp_err("Regulator get failed vcc_i2c ret=%d\n", ret); + return ret; + } + + ret = regulator_set_voltage(data->vddio, 1800000, 1800000); + if (ret) { + tsp_err("Regulator set_vtg failed vcc_i2c ret=%d\n", ret); + return ret; + } + + ret = regulator_enable(data->vdd); + if (ret) { + tsp_err("Regulator vdd enable failed rc=%d\n", ret); + return ret; + } + + ret = regulator_enable(data->vddio); + if (ret) { + tsp_err("Regulator vddio enable failed rc=%d\n", ret); + return ret; + } + + return 0; +} + +static int ist30xx_pinctrl_init(struct ist30xx_data *data) +{ + int ret; + + /* Get pinctrl if target uses pinctrl */ + data->pinctrl = devm_pinctrl_get(&(data->client->dev)); + if (IS_ERR_OR_NULL(data->pinctrl)) { + ret = PTR_ERR(data->pinctrl); + tsp_err("target does not use pinctrl %d\n", ret); + goto err_pinctrl_get; + } + + data->pinctrl_state_active = pinctrl_lookup_state(data->pinctrl, + "pmx_ts_active"); + if (IS_ERR_OR_NULL(data->pinctrl_state_active)) { + ret = PTR_ERR(data->pinctrl_state_active); + tsp_err("can't lookup %s pinstate %d\n", "pmx_ts_active", ret); + goto err_pinctrl_lookup; + } + + data->pinctrl_state_suspend = pinctrl_lookup_state(data->pinctrl, + "pmx_ts_suspend"); + if (IS_ERR_OR_NULL(data->pinctrl_state_suspend)) { + ret = PTR_ERR(data->pinctrl_state_suspend); + tsp_err("can't lookup %s pinstate %d\n", "pmx_ts_suspend", ret); + goto err_pinctrl_lookup; + } + + data->pinctrl_state_release = pinctrl_lookup_state(data->pinctrl, + "pmx_ts_release"); + if (IS_ERR_OR_NULL(data->pinctrl_state_release)) { + ret = PTR_ERR(data->pinctrl_state_release); + tsp_err("can't lookup %s pinstate %d\n", "pmx_ts_release", ret); + goto err_pinctrl_lookup; + } + + return 0; + +err_pinctrl_lookup: + devm_pinctrl_put(data->pinctrl); +err_pinctrl_get: + data->pinctrl = NULL; + + return ret; +} + +static int ist30xx_suspend(struct device *dev) +{ + int ret; + struct i2c_client *client = to_i2c_client(dev); + struct ist30xx_data *data = i2c_get_clientdata(client); + + if (data->debugging_mode) + return 0; + + del_timer(&data->event_timer); + cancel_delayed_work_sync(&data->work_reset_check); +#ifdef IST30XX_NOISE_MODE + cancel_delayed_work_sync(&data->work_noise_protect); +#else +#ifdef IST30XX_FORCE_RELEASE + cancel_delayed_work_sync(&data->work_force_release); +#endif +#endif +#ifdef IST30XX_ALGORITHM_MODE + cancel_delayed_work_sync(&data->work_debug_algorithm); +#endif + cancel_delayed_work_sync(&data->work_cal_reference); + mutex_lock(&data->lock); + ist30xx_disable_irq(data); + ist30xx_internal_suspend(data); + clear_input_data(data); +#ifdef IST30XX_GESTURE + if (ist30xx_gesture_func_on) { + if (data->gesture) { + ist30xx_enable_irq(data); + ist30xx_start(data); + data->status.noise_mode = false; + if (device_may_wakeup(&data->client->dev)) + enable_irq_wake(data->client->irq); + } + } else { +#endif + + if (data->pinctrl) { + ret = pinctrl_select_state(data->pinctrl, data->pinctrl_state_suspend); + if (ret < 0) + tsp_err("cannot get suspend pinctrl state\n"); + } +#ifdef IST30XX_GESTURE + } +#endif + mutex_unlock(&data->lock); + + return 0; +} + +static int ist30xx_resume(struct device *dev) +{ + int ret; + struct i2c_client *client = to_i2c_client(dev); + struct ist30xx_data *data = i2c_get_clientdata(client); + + data->noise_mode |= (1 << NOISE_MODE_POWER); + + if (data->debugging_mode && data->status.power) + return 0; + + mutex_lock(&data->lock); +#ifdef IST30XX_GESTURE + if (ist30xx_gesture_func_on) { + if (data->gesture) { + ist30xx_disable_irq(data); + } + } +#endif + ist30xx_internal_resume(data); + ist30xx_enable_irq(data); + ist30xx_start(data); + +#ifdef IST30XX_GESTURE + + if (ist30xx_gesture_func_on) { + if (data->gesture) { + if (device_may_wakeup(&data->client->dev)) + disable_irq_wake(data->client->irq); + + } + } else { +#endif + + if (data->pinctrl) { + ret = pinctrl_select_state(data->pinctrl, data->pinctrl_state_active); + if (ret < 0) + tsp_err("cannot get active pinctrl state\n"); + } +#ifdef IST30XX_GESTURE + } +#endif + + mutex_unlock(&data->lock); + + return 0; +} + +#ifdef USE_OPEN_CLOSE +static void ist30xx_ts_close(struct input_dev *dev) +{ + struct ist30xx_data *data = input_get_drvdata(dev); + + ist30xx_suspend(&data->client->dev); +} + +static int ist30xx_ts_open(struct input_dev *dev) +{ + struct ist30xx_data *data = input_get_drvdata(dev); + + return ist30xx_resume(&data->client->dev); +} +#elif defined(CONFIG_HAS_EARLYSUSPEND) +static void ist30xx_early_suspend(struct early_suspend *h) +{ + struct ist30xx_data *data = container_of(h, struct ist30xx_data, + early_suspend); + + ist30xx_suspend(&data->client->dev); +} + +static void ist30xx_late_resume(struct early_suspend *h) +{ + struct ist30xx_data *data = container_of(h, struct ist30xx_data, + early_suspend); + + ist30xx_resume(&data->client->dev); +} +#endif + +void ist30xx_set_ta_mode(bool mode) +{ + struct ist30xx_data *data = ts_data; + + if (unlikely(mode == ((data->noise_mode >> NOISE_MODE_TA) & 1))) + return; + + pr_err("%s(), mode = %d\n", __func__, mode); + + if (mode) + data->noise_mode |= (1 << NOISE_MODE_TA); + else + data->noise_mode &= ~(1 << NOISE_MODE_TA); + +#ifdef IST30XX_TA_RESET + if (data->initialized) + ist30xx_scheduled_reset(data); +#else + if (data->initialized && data->status.power) + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + ((eHCOM_SET_MODE_SPECIAL << 16) | (data->noise_mode & 0xFFFF))); +#endif +#ifdef IST30XX_TRACKING_MODE + ist30xx_tracking(mode ? TRACK_CMD_TACON : TRACK_CMD_TADISCON); +#endif +} +EXPORT_SYMBOL(ist30xx_set_ta_mode); + +void ist30xx_set_edge_mode(int mode) +{ + struct ist30xx_data *data = ts_data; + + tsp_info("%s(), mode = %d\n", __func__, mode); + + if (mode) + data->noise_mode |= (1 << NOISE_MODE_EDGE); + else + data->noise_mode &= ~(1 << NOISE_MODE_EDGE); + + if (data->status.power) + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + ((eHCOM_SET_MODE_SPECIAL << 16) | (data->noise_mode & 0xFFFF))); +} +EXPORT_SYMBOL(ist30xx_set_edge_mode); + +void ist30xx_set_call_mode(int mode) +{ + struct ist30xx_data *data = ts_data; + + if (unlikely(mode == ((data->noise_mode >> NOISE_MODE_CALL) & 1))) + return; + + tsp_info("%s(), mode = %d\n", __func__, mode); + + if (mode) + data->noise_mode |= (1 << NOISE_MODE_CALL); + else + data->noise_mode &= ~(1 << NOISE_MODE_CALL); + +#ifdef IST30XX_TA_RESET + if (data->initialized) + ist30xx_scheduled_reset(data); +#else + if (data->initialized && data->status.power) + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + ((eHCOM_SET_MODE_SPECIAL << 16) | (data->noise_mode & 0xFFFF))); +#endif +#ifdef IST30XX_TRACKING_MODE + ist30xx_tracking(mode ? TRACK_CMD_CALL : TRACK_CMD_NOTCALL); +#endif +} +EXPORT_SYMBOL(ist30xx_set_call_mode); + +void ist30xx_set_cover_mode(int mode) +{ + struct ist30xx_data *data = ts_data; + + if (unlikely(mode == ((data->noise_mode >> NOISE_MODE_COVER) & 1))) + return; + + tsp_info("%s(), mode = %d\n", __func__, mode); + + if (mode) + data->noise_mode |= (1 << NOISE_MODE_COVER); + else + data->noise_mode &= ~(1 << NOISE_MODE_COVER); + +#ifdef IST30XX_TA_RESET + if (data->initialized) + ist30xx_scheduled_reset(data); +#else + if (data->initialized && data->status.power) + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + ((eHCOM_SET_MODE_SPECIAL << 16) | (data->noise_mode & 0xFFFF))); +#endif +#ifdef IST30XX_TRACKING_MODE + ist30xx_tracking(mode ? TRACK_CMD_COVER : TRACK_CMD_NOTCOVER); +#endif +} +EXPORT_SYMBOL(ist30xx_set_cover_mode); + +#ifdef USE_TSP_TA_CALLBACKS +void charger_enable(struct tsp_callbacks *cb, int enable) +{ + bool charging = enable ? true : false; + + ist30xx_set_ta_mode(charging); +} + +static void ist30xx_register_callback(struct tsp_callbacks *cb) +{ + charger_callbacks = cb; + pr_info("%s\n", __func__); +} +#endif + +static void reset_work_func(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct ist30xx_data *data = container_of(delayed_work, struct ist30xx_data, + work_reset_check); + + if (unlikely((data == NULL) || (data->client == NULL))) + return; + + tsp_info("Request reset function\n"); + + if (likely((data->initialized == 1) && (data->status.power == 1) && + (data->status.update != 1) && (data->status.calib != 1 && + (data->status.calib != 2)))) { + mutex_lock(&data->lock); + ist30xx_disable_irq(data); +#ifdef IST30XX_GESTURE + if (data->suspend) + ist30xx_internal_suspend(data); + else +#endif + ist30xx_reset(data, false); + clear_input_data(data); + ist30xx_enable_irq(data); + ist30xx_start(data); +#ifdef IST30XX_GESTURE + if (data->gesture && data->suspend) + data->status.noise_mode = false; +#endif + mutex_unlock(&data->lock); + } +} + +#ifdef IST30XX_INTERNAL_BIN +#ifdef IST30XX_UPDATE_BY_WORKQUEUE +static void fw_update_func(struct work_struct *work) +{ + int ret; + struct delayed_work *delayed_work = to_delayed_work(work); + struct ist30xx_data *data = container_of(delayed_work, + struct ist30xx_data, work_fw_update); + + if (unlikely((data == NULL) || (data->client == NULL))) + return; + + tsp_info("FW update function\n"); + + if (likely(ist30xx_auto_bin_update(data))) { + ist30xx_disable_irq(data); + } else { + ret = ist30xx_get_info(data); + tsp_info("Get info: %s\n", (ret == 0 ? "success" : "fail")); + + ist30xx_start(data); + data->initialized = true; + } +} +#endif +#endif + +#if (defined(IST30XX_NOISE_MODE) || defined(IST30XX_FORCE_RELEASE)) +#define TOUCH_STATUS_MAGIC (0x00000075) +#define TOUCH_STATUS_MASK (0x000000FF) +#define FINGER_ENABLE_MASK (0x00100000) +#define SCAN_CNT_MASK (0xFFE00000) +#define GET_FINGER_ENABLE(n) ((n & FINGER_ENABLE_MASK) >> 20) +#define GET_SCAN_CNT(n) ((n & SCAN_CNT_MASK) >> 21) +#endif +#ifdef IST30XX_NOISE_MODE +static void noise_work_func(struct work_struct *work) +{ + int ret; + u32 touch_status = 0; + u32 scan_count = 0; + struct delayed_work *delayed_work = to_delayed_work(work); + struct ist30xx_data *data = container_of(delayed_work, struct ist30xx_data, + work_noise_protect); + + ret = ist30xx_read_reg(data->client, IST30XX_HIB_TOUCH_STATUS, + &touch_status); + if (unlikely(ret)) { + tsp_warn("Touch status read fail!\n"); + goto retry_timer; + } + +#ifdef IST30XX_TRACKING_MODE + ist30xx_put_track_ms(data->timer_ms); + ist30xx_put_track(&touch_status, 1); +#endif + tsp_verb("Touch Info: 0x%08x\n", touch_status); + + /* Check valid scan count */ + if (unlikely((touch_status & TOUCH_STATUS_MASK) != TOUCH_STATUS_MAGIC)) { + tsp_warn("Touch status is not corrected! (0x%08x)\n", touch_status); + goto retry_timer; + } + + /* Status of IC is idle */ + if (GET_FINGER_ENABLE(touch_status) == 0) { + if ((PARSE_FINGER_CNT(data->t_status) > 0) || + (PARSE_KEY_CNT(data->t_status) > 0)) + clear_input_data(data); + } + + scan_count = GET_SCAN_CNT(touch_status); + + /* Status of IC is lock-up */ + if (unlikely(scan_count == data->scan_count)) { + tsp_warn("TSP IC is not responded! (0x%08x)\n", scan_count); + goto retry_timer; + } + + data->scan_retry = 0; + data->scan_count = scan_count; + return; + +retry_timer: + data->scan_retry++; + tsp_warn("Retry touch status!(%d)\n", data->scan_retry); + + if (unlikely(data->scan_retry == data->max_scan_retry)) { + ist30xx_scheduled_reset(data); + data->scan_retry = 0; + } +} +#else +#ifdef IST30XX_FORCE_RELEASE +static void release_work_func(struct work_struct *work) +{ + int ret; + u32 touch_status = 0; + struct delayed_work *delayed_work = to_delayed_work(work); + struct ist30xx_data *data = container_of(delayed_work, struct ist30xx_data, + work_force_release); + + if ((PARSE_FINGER_CNT(data->t_status) == 0) && + (PARSE_KEY_CNT(data->t_status) == 0)) + return; + + ret = ist30xx_read_reg(data->client, IST30XX_HIB_TOUCH_STATUS, + &touch_status); + if (unlikely(ret)) { + tsp_warn("Touch status read fail!\n"); + return; + } + +#ifdef IST30XX_TRACKING_MODE + ist30xx_put_track_ms(data->timer_ms); + ist30xx_put_track(&touch_status, 1); +#endif + tsp_verb("Touch Info: 0x%08x\n", touch_status); + + /* Check valid scan count */ + if (unlikely((touch_status & TOUCH_STATUS_MASK) != TOUCH_STATUS_MAGIC)) { + tsp_warn("Touch status is not corrected! (0x%08x)\n", touch_status); + return; + } + + /* Status of IC is idle */ + if (GET_FINGER_ENABLE(touch_status) == 0) + clear_input_data(data); +} +#endif +#endif + +#ifdef IST30XX_ALGORITHM_MODE +static void debug_work_func(struct work_struct *work) +{ + int ret = -EPERM; + int i; + u32 *buf32; + + struct delayed_work *delayed_work = to_delayed_work(work); + struct ist30xx_data *data = container_of(delayed_work, + struct ist30xx_data, work_debug_algorithm); + + buf32 = kzalloc(data->algr_size * sizeof(u32), GFP_KERNEL); + ret = ist30xx_burst_read(data->client, IST30XX_DA_ADDR(data->algr_addr), + buf32, data->algr_size, true); + if (ret) { + tsp_warn("Algorithm mem addr read fail!\n"); + return; + } + +#ifdef IST30XX_TRACKING_MODE + ist30xx_put_track(buf32, data->algr_size); +#endif + tsp_info("algorithm struct\n"); + for (i = 0; i < data->algr_size; i++) + tsp_info(" 0x%08x\n", buf32[i]); + + kfree(buf32); +} +#endif + +void timer_handler(unsigned long timer_data) +{ + struct ist30xx_data *data = (struct ist30xx_data *)timer_data; + struct ist30xx_status *status = &data->status; + + if (data->irq_working || !data->initialized || data->rec_mode) + goto restart_timer; + + if (status->event_mode) { + if (likely((status->power == 1) && (status->update != 1) && + (status->calib != 1))) { + data->timer_ms = (u32)get_milli_second(data); + if (unlikely(status->calib == 2)) { + /* Check calibration */ + if ((status->calib_msg & CALIB_MSG_MASK) == CALIB_MSG_VALID) { + tsp_info("Calibration check OK!!\n"); + schedule_delayed_work(&data->work_reset_check, 0); + status->calib = 0; + } else if (data->timer_ms - data->event_ms >= 3000) { + /* over 3 second */ + tsp_info("calibration timeout over 3sec\n"); + schedule_delayed_work(&data->work_reset_check, 0); + status->calib = 0; + } +#ifdef IST30XX_NOISE_MODE + } else if (likely(status->noise_mode)) { + /* 100ms after last interrupt */ + if (data->timer_ms - data->event_ms > 100) + schedule_delayed_work(&data->work_noise_protect, 0); +#else +#ifdef IST30XX_FORCE_RELEASE + } else if (likely(status->noise_mode)) { + /* 100ms after last interrupt */ + if (data->timer_ms - data->event_ms > 100) + schedule_delayed_work(&data->work_force_release, 0); +#endif +#endif + } +#ifdef IST30XX_ALGORITHM_MODE + if (data->algr_size > 0) { + /* 100ms after last interrupt */ + if (data->timer_ms - data->event_ms > 100) + schedule_delayed_work(&data->work_debug_algorithm, 0); + } +#endif + } + } + +restart_timer: + mod_timer(&data->event_timer, get_jiffies_64() + EVENT_TIMER_INTERVAL); +} + +#ifdef CONFIG_OF +static int ist30xx_request_gpio(struct ist30xx_data *data) +{ + int ret; + + tsp_info("%s\n", __func__); + + if (gpio_is_valid(data->dt_data->reset_gpio)) { + ret = gpio_request(data->dt_data->reset_gpio, "imagis,reset_gpio"); + if (ret) { + tsp_err("unable to request reset gpio: %d\n", + data->dt_data->reset_gpio); + return ret; + } + + ret = gpio_direction_output(data->dt_data->reset_gpio, 0); + if (ret) + tsp_err("unable to set direction for reset gpio: %d\n", + data->dt_data->reset_gpio); + + gpio_set_value_cansleep(data->dt_data->reset_gpio, 0); + } + + if (gpio_is_valid(data->dt_data->irq_gpio)) { + ret = gpio_request(data->dt_data->irq_gpio, "imagis,irq_gpio"); + if (ret) { + tsp_err("unable to request irq gpio: %d\n", + data->dt_data->irq_gpio); + return ret; + } + + ret = gpio_direction_input(data->dt_data->irq_gpio); + if (ret) + tsp_err("unable to set direction for irq gpio: %d\n", + data->dt_data->irq_gpio); + + gpio_set_value_cansleep(data->dt_data->reset_gpio, 0); + + data->client->irq = gpio_to_irq(data->dt_data->irq_gpio); + } + return 0; +} + +static void ist30xx_free_gpio(struct ist30xx_data *data) +{ + tsp_info("%s\n", __func__); + + if (gpio_is_valid(data->dt_data->reset_gpio)) + gpio_free(data->dt_data->reset_gpio); + + if (gpio_is_valid(data->dt_data->irq_gpio)) + gpio_free(data->dt_data->irq_gpio); +} + +static int ist30xx_parse_dt(struct device *dev, struct ist30xx_data *data) +{ + struct device_node *np = dev->of_node; + + data->dt_data->irq_gpio = of_get_named_gpio(np, "imagis,irq-gpio", 0); + data->dt_data->reset_gpio = of_get_named_gpio(np, "imagis,reset-gpio", 0); + + tsp_info("##### Device tree #####\n"); + tsp_info(" reset gpio: %d\n", data->dt_data->reset_gpio); + tsp_info(" irq gpio: %d\n", data->dt_data->irq_gpio); + + return 0; +} +#endif +#ifdef XIAOMI_PRODUCT +#define CTP_PROC_LOCKDOWN_FILE "tp_lockdown_info" +static struct proc_dir_entry *ctp_lockdown_status_proc; +static char tp_lockdown_info[128]; + +static int ctp_lockdown_proc_show(struct seq_file *file, void *data) +{ + char temp[40] = {0}; + + sprintf(temp, "%s\n", tp_lockdown_info); + seq_printf(file, "%s\n", temp); + return 0; +} + +static int ctp_lockdown_proc_open (struct inode *inode, struct file *file) +{ + return single_open(file, ctp_lockdown_proc_show, inode->i_private); +} + +static const struct file_operations ctp_lockdown_proc_fops = { + .open = ctp_lockdown_proc_open, + .read = seq_read, +}; +#endif +#if defined(CONFIG_FB) +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct ist30xx_data *ist_data = + container_of(self, struct ist30xx_data, fb_notif); + + if (evdata && evdata->data && event == FB_EVENT_BLANK && + ist_data && ist_data->client) { + blank = evdata->data; + if (*blank == FB_BLANK_UNBLANK) + ist30xx_resume(&ist_data->client->dev); + else if (*blank == FB_BLANK_POWERDOWN) + ist30xx_suspend(&ist_data->client->dev); + } + return 0; +} +#endif + +static char tp_info_summary[80] = ""; + +static int ist30xx_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + int i; + int retry = 3; + struct ist30xx_data *data; + struct input_dev *input_dev; + char tp_temp_info[80]; +#ifdef XIAOMI_PRODUCT + u32 info_data[2]; +#endif + + tsp_info("### IMAGIS probe(ver:%s, addr:0x%02X) ###\n", + IMAGIS_TSP_DD_VERSION, client->addr); + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + printk(KERN_INFO "i2c_check_functionality error\n"); + return -EIO; + } + + data = kzalloc(sizeof(struct ist30xx_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + data->client = client; +#ifdef CONFIG_OF + data->dt_data = NULL; + if (client->dev.of_node) { + data->dt_data = kzalloc(sizeof(struct ist30xx_dt_data), GFP_KERNEL); + if (unlikely(!data->dt_data)) { + tsp_err("failed to allocate dt data\n"); + goto err_alloc_dev; + } + + ret = ist30xx_parse_dt(&client->dev, data); + if (unlikely(ret)) + goto err_alloc_dev; + } else { + data->dt_data = NULL; + tsp_err("don't exist of_node\n"); + goto err_alloc_dev; + } + + if (data->dt_data) + ret = ist30xx_request_gpio(data); + if (ret) { + goto err_alloc_dev; + } +#endif + + ret = ist30xx_pinctrl_init(data); + if (!ret && data->pinctrl) { + /* + * Pinctrl handle is optional. If pinctrl handle is found + * let pins to be configured in active state. If not + * found continue further without error. + */ + ret = pinctrl_select_state(data->pinctrl, data->pinctrl_state_active); + if (ret < 0) + tsp_err("failed to select %s pinatate %d\n", "pmx_ts_active", ret); + } + + input_dev = input_allocate_device(); + if (unlikely(!input_dev)) { + tsp_err("input_allocate_device failed\n"); + goto err_alloc_dt; + } + + tsp_info("client->irq : %d\n", client->irq); + + data->input_dev = input_dev; + i2c_set_clientdata(client, data); + +#ifdef USE_OPEN_CLOSE + data->input_dev->open = ist30xx_ts_open; + data->input_dev->close = ist30xx_ts_close; +#else +#ifdef CONFIG_HAS_EARLYSUSPEND + data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + data->early_suspend.suspend = ist30xx_early_suspend; + data->early_suspend.resume = ist30xx_late_resume; + register_early_suspend(&data->early_suspend); +#endif +#endif + + data->max_fingers = IST30XX_MAX_FINGERS; + data->max_keys = IST30XX_MAX_KEYS; + data->irq_enabled = false; + data->status.event_mode = false; + mutex_init(&data->lock); + ts_data = data; + + /* initialize data variable */ + data->ignore_delay = false; + data->irq_working = false; + data->cal_ref_count = 0; + data->max_scan_retry = 2; + data->max_irq_err_cnt = IST30XX_MAX_ERR_CNT; + data->report_rate = -1; + data->idle_rate = -1; + data->timer_period_ms = 500; +#ifdef IST30XX_GESTURE + data->suspend = false; + data->gesture = true; +#endif + data->fw_mode = IST30XX_CAL_MODE; + data->rec_mode = 0; + data->rec_file_name = kzalloc(IST30XX_REC_FILENAME_SIZE, GFP_KERNEL); + data->debug_mode = 0; + data->debugging_mode = 0; + data->debugging_noise = 1; + for (i = 0; i < IST30XX_MAX_FINGERS; i++) + data->tsp_touched[i] = false; +#ifdef IST30XX_USE_KEY + for (i = 0; i < IST30XX_MAX_KEYS; i++) + data->tkey_pressed[i] = false; +#endif + + ret = ist30xx_power_init(data); + if (ret) + goto err_init_drv; + + /* system power init */ + ret = ist30xx_init_system(data); + if (unlikely(ret)) { + tsp_err("chip initialization failed\n"); + goto err_init_drv; + } + +#ifdef XIAOMI_PRODUCT + retry = 1; + while (retry-- > 0) { + ret = ist30xxc_isp_info_read(data, XIAOMI_INFO_ADDR, info_data, + XIAOMI_INFO_SIZE); + if (ret == 0) { + if ((info_data[XIAOMI_PID_INDEX] & XIAOMI_INFO_MASK) + == XIAOMI_INFO_VALUE) { + data->pid = XIAOMI_GET_PID(info_data[XIAOMI_PID_INDEX]); + data->lockdown_upper = info_data[XIAOMI_LOCKDOWN_INDEX]; + break; + } + } + + if (retry == 0) { + data->pid = 0; + tsp_err("read isp info failed\n"); + } + } + +#endif + + retry = IST30XX_MAX_RETRY_CNT; + while (retry-- > 0) { + ret = ist30xx_read_reg(data->client, IST30XX_REG_CHIPID, + &data->chip_id); + data->chip_id &= 0xFFFF; + if (unlikely(ret == 0)) { + set_usb_charge_mode_par = 1; + if ((data->chip_id == IST30XX_CHIP_ID) || + (data->chip_id == IST30XXC_DEFAULT_CHIP_ID) || + (data->chip_id == IST3048C_DEFAULT_CHIP_ID)) { + break; + } + } else if (unlikely(retry == 0)) { + goto err_init_drv; + } + + ist30xx_reset(data, false); + } + tsp_info("TSP IC: %x\n", data->chip_id); + + /* init irq thread */ + ret = request_threaded_irq(client->irq, NULL, ist30xx_irq_thread, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_DISABLED , "ist30xx_ts", + data); + if (unlikely(ret)) + goto err_init_drv; + +#ifdef IST30XX_INTERNAL_BIN +#ifdef XIAOMI_PRODUCT + if (data->pid != 0) { +#endif +#ifdef IST30XX_UPDATE_BY_WORKQUEUE + INIT_DELAYED_WORK(&data->work_fw_update, fw_update_func); + schedule_delayed_work(&data->work_fw_update, IST30XX_UPDATE_DELAY); +#else + + ret = ist30xx_auto_bin_update(data); + if (unlikely(ret != 0)) + goto err_irq; +#endif +#ifdef XIAOMI_PRODUCT + } +#endif +#endif + + ret = ist30xx_init_update_sysfs(data); + if (unlikely(ret)) + goto err_sysfs; + +#ifdef IST30XX_DEBUG + ret = ist30xx_init_misc_sysfs(data); + if (unlikely(ret)) + goto err_sysfs; +#endif + +#ifdef IST30XX_CMCS_TEST + ret = ist30xx_init_cmcs_sysfs(data); + if (unlikely(ret)) + goto err_sysfs; +#endif + +#ifdef IST30XX_TRACKING_MODE + ret = ist30xx_init_tracking_sysfs(data); + if (unlikely(ret)) + goto err_sysfs; +#endif + + tsp_info("Create sysfs!!\n"); + +#if defined(CONFIG_FB) + data->fb_notif.notifier_call = fb_notifier_callback; + + ret = fb_register_client(&data->fb_notif); + + if (ret) { + goto err_sysfs; + tsp_err("Unable to register fb_notifier\n"); + } +#endif +#ifndef IST30XX_UPDATE_BY_WORKQUEUE + ret = ist30xx_get_info(data); + tsp_info("Get info: %s\n", (ret == 0 ? "success" : "fail")); + if (unlikely(ret)) + goto err_read_info; +#endif + + +#ifdef XIAOMI_PRODUCT + memset(tp_lockdown_info, 0, sizeof(tp_lockdown_info)); + sprintf(tp_lockdown_info, "%08X%08X", data->fw.cur.lockdown[0], data->fw.cur.lockdown[1]); + tsp_info("[%s]lockdowninfo:%s\n", __FUNCTION__, tp_lockdown_info); + ctp_lockdown_status_proc = proc_create(CTP_PROC_LOCKDOWN_FILE, 0644, NULL, &ctp_lockdown_proc_fops); + if (ctp_lockdown_status_proc == NULL) + tsp_err("tpd, create_proc_entry ctp_lockdown_status_proc failed\n"); +#endif + + INIT_DELAYED_WORK(&data->work_reset_check, reset_work_func); +#ifdef IST30XX_NOISE_MODE + INIT_DELAYED_WORK(&data->work_noise_protect, noise_work_func); +#else +#ifdef IST30XX_FORCE_RELEASE + INIT_DELAYED_WORK(&data->work_force_release, release_work_func); +#endif +#endif +#ifdef IST30XX_ALGORITHM_MODE + INIT_DELAYED_WORK(&data->work_debug_algorithm, debug_work_func); +#endif + INIT_DELAYED_WORK(&data->work_cal_reference, cal_ref_work_func); + + init_timer(&data->event_timer); + data->event_timer.data = (unsigned long)data; + data->event_timer.function = timer_handler; + data->event_timer.expires = jiffies_64 + EVENT_TIMER_INTERVAL; + mod_timer(&data->event_timer, get_jiffies_64() + EVENT_TIMER_INTERVAL * 2); + +#ifdef USE_TSP_TA_CALLBACKS + data->callbacks.inform_charger = charger_enable; + ist30xx_register_callback(&data->callbacks); +#endif + +#ifndef IST30XX_UPDATE_BY_WORKQUEUE + ist30xx_start(data); + data->initialized = true; +#endif + strcpy(tp_info_summary, "[Vendor]Dongshan, [IC]IST3038C, [FW]Ver"); + sprintf(tp_temp_info, "%x", data->fw.bin.fw_ver); + strcat(tp_info_summary, tp_temp_info); + strcat(tp_info_summary, "\0"); + tsp_info("### IMAGIS probe success ###\n"); + + return 0; + +#ifndef IST30XX_UPDATE_BY_WORKQUEUE +err_read_info: +#endif +err_sysfs: + class_destroy(ist30xx_class); +#ifndef IST30XX_UPDATE_BY_WORKQUEUE +err_irq: +#endif + ist30xx_disable_irq(data); + free_irq(client->irq, data); +err_init_drv: + input_free_device(input_dev); + data->status.event_mode = false; + ist30xx_power_off(data); +#if (defined(CONFIG_HAS_EARLYSUSPEND) && !defined(USE_OPEN_CLOSE)) + unregister_early_suspend(&data->early_suspend); +#endif +err_alloc_dt: + if (data->pinctrl) { + if (IS_ERR_OR_NULL(data->pinctrl_state_release)) { + devm_pinctrl_put(data->pinctrl); + data->pinctrl = NULL; + } else { + ret = pinctrl_select_state(data->pinctrl, + data->pinctrl_state_release); + if (ret < 0) + tsp_err("cannot get release pinctrl state\n"); + } + } + if (data->dt_data) { + tsp_err("Error, ist30xx mem free\n"); + ist30xx_free_gpio(data); + kfree(data->dt_data); + } +#ifdef CONFIG_OF +err_alloc_dev: +#endif + kfree(data); + tsp_err("Error, ist30xx init driver\n"); + return -ENODEV; +} + + +static int ist30xx_remove(struct i2c_client *client) +{ + int ret; + struct ist30xx_data *data = i2c_get_clientdata(client); + +#if (defined(CONFIG_HAS_EARLYSUSPEND) && !defined(USE_OPEN_CLOSE)) + unregister_early_suspend(&data->early_suspend); +#endif + + ist30xx_disable_irq(data); + free_irq(client->irq, data); + ist30xx_power_off(data); + if (data->dt_data) { + ist30xx_free_gpio(data); + kfree(data->dt_data); + } + +#if defined(CONFIG_FB) + fb_unregister_client(&data->fb_notif); +#endif + if (data->pinctrl) { + if (IS_ERR_OR_NULL(data->pinctrl_state_release)) { + devm_pinctrl_put(data->pinctrl); + data->pinctrl = NULL; + } else { + ret = pinctrl_select_state(data->pinctrl, + data->pinctrl_state_release); + if (ret < 0) + tsp_err("cannot get release pinctrl state\n"); + } + } + input_unregister_device(data->input_dev); + input_free_device(data->input_dev); + kfree(data); + + return 0; +} + +static void ist30xx_shutdown(struct i2c_client *client) +{ + struct ist30xx_data *data = i2c_get_clientdata(client); + + del_timer(&data->event_timer); + cancel_delayed_work_sync(&data->work_reset_check); +#ifdef IST30XX_NOISE_MODE + cancel_delayed_work_sync(&data->work_noise_protect); +#else +#ifdef IST30XX_FORCE_RELEASE + cancel_delayed_work_sync(&data->work_force_release); +#endif +#endif +#ifdef IST30XX_ALGORITHM_MODE + cancel_delayed_work_sync(&data->work_debug_algorithm); +#endif + cancel_delayed_work_sync(&data->work_cal_reference); + mutex_lock(&data->lock); + ist30xx_disable_irq(data); + ist30xx_internal_suspend(data); + clear_input_data(data); + mutex_unlock(&data->lock); +} + +static struct i2c_device_id ist30xx_idtable[] = { + { IST30XX_DEV_NAME, 0 }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, ist30xx_idtable); + +#ifdef CONFIG_OF +static struct of_device_id ist30xx_match_table[] = { + { .compatible = "imagis,ist30xx-ts", }, + { }, +}; +#else +#define ist30xx_match_table NULL +#endif + +static struct i2c_driver ist30xx_i2c_driver = { + .id_table = ist30xx_idtable, + .probe = ist30xx_probe, + .remove = ist30xx_remove, + .shutdown = ist30xx_shutdown, + .driver = { + .owner = THIS_MODULE, + .name = IST30XX_DEV_NAME, + .of_match_table = ist30xx_match_table, + }, +}; + +static int __init ist30xx_init(void) +{ + tsp_info("%s()\n", __func__); + return i2c_add_driver(&ist30xx_i2c_driver); +} + + +static void __exit ist30xx_exit(void) +{ + tsp_info("%s()\n", __func__); + i2c_del_driver(&ist30xx_i2c_driver); +} + +module_init(ist30xx_init); +module_exit(ist30xx_exit); + +MODULE_DESCRIPTION("Imagis IST30XX touch driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/input/touchscreen/ist3038c/ist30xxc.h b/drivers/input/touchscreen/ist3038c/ist30xxc.h new file mode 100644 index 0000000000000..62d746ed53cfe --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/ist30xxc.h @@ -0,0 +1,606 @@ +/* + * Copyright (C) 2010, Imagis Technology Co. Ltd. All Rights Reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __IST30XXC_H__ +#define __IST30XXC_H__ + +/* + * Support F/W ver : ~ IST30xxC v3.0.0.0 + * Support CmCs ver : v5.2 + * Support IC : IST3026C, IST3032C, IST3038C, IST3038C1, IST3044C, IST3048C + * Release : 2015.09.18 by Drake + */ + +#define IMAGIS_TSP_DD_VERSION ("3.0.0.0") + +#define IMAGIS_IST3026C (1) /* 3026C */ +#define IMAGIS_IST3032C (2) /* 3032C */ +#define IMAGIS_IST3038C (3) /* 3038C/3038C1 */ +#define IMAGIS_IST3044C (4) /* 3044C */ +#define IMAGIS_IST3048C (5) /* 3048C */ + +#define IMAGIS_TSP_IC IMAGIS_IST3038C +#define TSP_CHIP_VENDOR ("IMAGIS") + +/* IST30XX FUNCTION ENABLE & DISABLE */ +#define XIAOMI_PRODUCT + + + +#define IST30XX_INTERNAL_BIN +#ifdef IST30XX_INTERNAL_BIN + +#ifdef IST30XX_UPDATE_BY_WORKQUEUE +#define IST30XX_UPDATE_DELAY (3 * HZ) +#endif +#endif +#define IST30XX_TRACKING_MODE +#define IST30XX_NOISE_MODE + +#define IST30XX_ALGORITHM_MODE +#define IST30XX_USE_KEY +#ifdef IST30XX_USE_KEY +#define IST30XX_KEY_CODES { KEY_MENU, KEY_HOMEPAGE, KEY_BACK } +#endif +#define IST30XX_DEBUG +#define IST30XX_CMCS_TEST + + +#define IST30XX_GESTURE + + + + +/* IST30XX FUNCTION ENABLE & DISABLE */ +#ifdef XIAOMI_PRODUCT +#define XIAOMI_INFO_ADDR (0xFE) +#define XIAOMI_INFO_SIZE (2) +#define XIAOMI_LOCKDOWN_INDEX (0) +#define XIAOMI_PID_INDEX (1) +#define XIAOMI_INFO_MASK (0xFF0000FF) +#define XIAOMI_INFO_VALUE (0x9A00001D) +#define C6_PID (0xC601) +#define XIAOMI_GET_PID(n) ((n & ~(XIAOMI_INFO_MASK)) >> 8) +#endif + +#define IST30XXC_DEFAULT_CHIP_ID (0x300C) +#define IST3048C_DEFAULT_CHIP_ID (0x3048) +#if (IMAGIS_TSP_IC == IMAGIS_IST3026C) +#define TSP_CHIP_NAME ("IST3026C") +#define IST30XX_CHIP_ID (0x026C) +#define IST30XX_MAX_NODE_NUM (16 * 16) +#elif (IMAGIS_TSP_IC == IMAGIS_IST3032C) +#define TSP_CHIP_NAME ("IST3032C") +#define IST30XX_CHIP_ID (0x032C) +#define IST30XX_MAX_NODE_NUM (16 * 16) +#elif (IMAGIS_TSP_IC == IMAGIS_IST3038C) +#define TSP_CHIP_NAME ("IST3038C") +#define IST30XX_CHIP_ID (0x038C) +#define IST30XX_MAX_NODE_NUM (24 * 24) +#elif (IMAGIS_TSP_IC == IMAGIS_IST3044C) +#define TSP_CHIP_NAME ("IST3044C") +#define IST30XX_CHIP_ID (0x044C) +#define IST30XX_MAX_NODE_NUM (24 * 24) +#elif (IMAGIS_TSP_IC == IMAGIS_IST3048C) +#define TSP_CHIP_NAME ("IST3048C") +#define IST30XX_CHIP_ID (0x048C) +#define IST30XX_MAX_NODE_NUM (24 * 24) +#else +#define TSP_CHIP_NAME ("IST30XXC") +#define IST30XX_CHIP_ID (0x300C) +#define IST30XX_MAX_NODE_NUM (24 * 24) +#endif + +#define IST30XX_MAX_FINGERS (10) +#define IST30XX_MAX_KEYS (5) +#define IST30XX_MAX_W (15) +#define IST30XX_MAX_3D_VALUE (255) + +#define IST30XX_INITIAL_VALUE (0x8EAD8EAD) +#define IST30XX_REC_VALUE (0x8CA0D00E) +#define IST30XX_REC_FILENAME_SIZE (128) +#define IST30XX_DEBUGGING_VALUE (0xDBDB0000) +#define IST30XX_MAX_DEBUGINFO (512) +#define IST30XX_EXCEPT_MASK (0xFFFFFF00) +#define IST30XX_EXCEPT_VALUE (0xE11CE900) +#define IST30XX_MAX_EXCEPT_SIZE (2) + +#define IST30XX_JIG_TOUCH (0xC0) +#define IST30XX_START_SCAN (2) +#define IST30XX_ENABLE (1) +#define IST30XX_DISABLE (0) + +#define IST30XX_CAL_MODE (1) +#define IST30XX_NON_CAL_MODE (2) + +/* retry count */ +#define IST30XX_MAX_RETRY_CNT (3) +#define IST30XX_MAX_CAL_REF_CNT (3) + +/* Local */ +#define TSP_LOCAL_EU (0) +#define TSP_LOCAL_EEU (1) +#define TSP_LOCAL_TD (11) +#define TSP_LOCAL_CMCC (12) +#define TSP_LOCAL_CU (13) +#define TSP_LOCAL_SPRD (14) +#define TSP_LOCAL_CTC (15) +#define TSP_LOCAL_INDIA (21) +#define TSP_LOCAL_SWASIA (22) +#define TSP_LOCAL_NA (31) +#define TSP_LOCAL_LA (32) +#define TSP_LOCAL_CODE TSP_LOCAL_EU + +/* Log message */ +#define DEV_ERR (1) +#define DEV_WARN (2) +#define DEV_INFO (3) +#define DEV_NOTI (4) +#define DEV_DEBUG (5) +#define DEV_VERB (6) + +#define IST30XX_LOG_TAG "[ TSP ]" +#define IST30XX_LOG_LEVEL DEV_NOTI + +#define tsp_err(fmt, ...) tsp_printk(DEV_ERR, fmt, ## __VA_ARGS__) +#define tsp_warn(fmt, ...) tsp_printk(DEV_WARN, fmt, ## __VA_ARGS__) +#define tsp_info(fmt, ...) tsp_printk(DEV_INFO, fmt, ## __VA_ARGS__) +#define tsp_noti(fmt, ...) tsp_printk(DEV_NOTI, fmt, ## __VA_ARGS__) +#define tsp_debug(fmt, ...) tsp_printk(DEV_DEBUG, fmt, ## __VA_ARGS__) +#define tsp_verb(fmt, ...) tsp_printk(DEV_VERB, fmt, ## __VA_ARGS__) + +/* timer & err cnt */ +#define IST30XX_MAX_ERR_CNT (100) +#define EVENT_TIMER_INTERVAL (HZ * data->timer_period_ms / 1000) + +/* i2c setting */ +/* I2C Device info */ +#define IST30XX_DEV_NAME "IST30XX" +#define IST30XX_DEV_ID (0xA0 >> 1) + +/* I2C transfer msg number */ +#define WRITE_CMD_MSG_LEN (1) +#define READ_CMD_MSG_LEN (2) + +/* I2C address/Data length */ +#define IST30XX_ADDR_LEN (4) /* bytes */ +#define IST30XX_DATA_LEN (4) /* bytes */ + +/* I2C transaction size */ +#define I2C_MAX_WRITE_SIZE (256) /* bytes */ +#define I2C_MAX_READ_SIZE (128) /* bytes */ + +/* I2C access mode */ +#define IST30XX_DIRECT_ACCESS (1 << 31) +#define IST30XX_BURST_ACCESS (1 << 27) +#define IST30XX_HIB_ACCESS (0x800B << 16) +#define IST30XX_DA_ADDR(n) (n | IST30XX_DIRECT_ACCESS) +#define IST30XX_BA_ADDR(n) (n | IST30XX_BURST_ACCESS) +#define IST30XX_HA_ADDR(n) (n | IST30XX_HIB_ACCESS) + +/* register */ +/* Info register */ +#define IST30XX_REG_CHIPID IST30XX_DA_ADDR(0x40001000) +#define IST30XX_REG_TSPTYPE IST30XX_DA_ADDR(0x40002010) + +/* HIB register */ +#define IST30XX_HIB_BASE (0x30000100) +#define IST30XX_HIB_TOUCH_STATUS IST30XX_HA_ADDR(IST30XX_HIB_BASE | 0x00) +#define IST30XX_HIB_INTR_MSG IST30XX_HA_ADDR(IST30XX_HIB_BASE | 0x04) +#define IST30XX_HIB_COORD IST30XX_HA_ADDR(IST30XX_HIB_BASE | 0x08) +#define IST30XX_HIB_CMD IST30XX_HA_ADDR(IST30XX_HIB_BASE | 0x3C) +#define IST30XX_HIB_RW_STATUS IST30XX_HA_ADDR(IST30XX_HIB_BASE | 0x40) + +/* interrupt macro */ +#define IST30XX_INTR_STATUS (0x00000C00) +#define CHECK_INTR_STATUS(n) (((n & IST30XX_INTR_STATUS) \ + == IST30XX_INTR_STATUS) ? 1 : 0) +#define PARSE_FINGER_CNT(n) ((n >> 12) & 0xF) +#define PARSE_KEY_CNT(n) ((n >> 21) & 0x7) +/* Finger status: [9:0] */ +#define PARSE_FINGER_STATUS(n) (n & 0x3FF) +/* Key status: [20:16] */ +#define PARSE_KEY_STATUS(n) ((n >> 16) & 0x1F) +#define PRESSED_FINGER(s, id) ((s & (1 << id)) ? true : false) +#define PRESSED_KEY(s, id) ((s & (1 << (16 + id))) ? true : false) + +#define IST30XX_MAX_CMD_SIZE (0x20) +#define IST30XX_CMD_ADDR(n) (n * 4) +#define IST30XX_CMD_VALUE(n) (n / 4) +enum ist30xx_read_commands { + eHCOM_GET_CHIP_ID = IST30XX_CMD_ADDR(0x00), + eHCOM_GET_VER_MAIN = IST30XX_CMD_ADDR(0x01), + eHCOM_GET_VER_FW = IST30XX_CMD_ADDR(0x02), + eHCOM_GET_VER_CORE = IST30XX_CMD_ADDR(0x03), + eHCOM_GET_VER_TEST = IST30XX_CMD_ADDR(0x04), + eHCOM_GET_CRC32 = IST30XX_CMD_ADDR(0x05), + eHCOM_GET_FW_MODE = IST30XX_CMD_ADDR(0x06), + eHCOM_GET_CAL_RESULT = IST30XX_CMD_ADDR(0x07), + eHCOM_GET_TSP_VENDOR = IST30XX_CMD_ADDR(0x08), +#ifdef XIAOMI_PRODUCT + eHCOM_GET_LOCKDOWN_1 = IST30XX_CMD_ADDR(0x09), + eHCOM_GET_LOCKDOWN_2 = IST30XX_CMD_ADDR(0x0A), + eHCOM_GET_CONFIG_1 = IST30XX_CMD_ADDR(0x0B), + eHCOM_GET_CONFIG_2 = IST30XX_CMD_ADDR(0x0C), +#endif + eHCOM_GET_DBG_INFO_BASE = IST30XX_CMD_ADDR(0x0E), + + eHCOM_GET_LCD_INFO = IST30XX_CMD_ADDR(0x10), + eHCOM_GET_TSP_INFO = IST30XX_CMD_ADDR(0x11), + eHCOM_GET_KEY_INFO_0 = IST30XX_CMD_ADDR(0x12), + eHCOM_GET_KEY_INFO_1 = IST30XX_CMD_ADDR(0x13), + eHCOM_GET_KEY_INFO_2 = IST30XX_CMD_ADDR(0x14), + eHCOM_GET_SCR_INFO = IST30XX_CMD_ADDR(0x15), + eHCOM_GET_GTX_INFO = IST30XX_CMD_ADDR(0x16), + eHCOM_GET_SWAP_INFO = IST30XX_CMD_ADDR(0x17), + eHCOM_GET_FINGER_INFO = IST30XX_CMD_ADDR(0x18), + eHCOM_GET_BASELINE = IST30XX_CMD_ADDR(0x19), + eHCOM_GET_TOUCH_TH = IST30XX_CMD_ADDR(0x1A), + + eHCOM_GET_FILTER_BASE = IST30XX_CMD_ADDR(0x1B), + eHCOM_GET_ZVALUE_BASE = IST30XX_CMD_ADDR(0x1C), + eHCOM_GET_RAW_BASE = IST30XX_CMD_ADDR(0x1D), + eHCOM_GET_ALGO_BASE = IST30XX_CMD_ADDR(0x1E), + eHCOM_GET_COM_CHECKSUM = IST30XX_CMD_ADDR(0x1F), +}; + +enum ist30xx_write_commands { + eHCOM_FW_START = 0x01, + eHCOM_FW_HOLD = 0x02, + + eHCOM_CP_CORRECT_EN = 0x10, + eHCOM_WDT_EN = 0x11, + eHCOM_GESTURE_EN = 0x12, + eHCOM_SCALE_EN = 0x13, + eHCOM_NEW_POSITION_DIS = 0x14, + eHCOM_SLEEP_MODE_EN = 0x15, + + eHCOM_SET_TIME_ACTIVE = 0x20, + eHCOM_SET_TIME_IDLE = 0x21, + eHCOM_SET_MODE_SPECIAL = 0x22, + eHCOM_SET_LOCAL_MODEL = 0x23, + + eHCOM_RUN_RAMCODE = 0x30, + eHCOM_RUN_CAL_AUTO = 0x31, + eHCOM_RUN_CAL_PARAM = 0x32, + eHCOM_RUN_CAL_REF = 0x33, + + eHCOM_SET_JIG_MODE = 0x80, + eHCOM_SET_JIG_SENSITI = 0x81, + + eHCOM_SET_REC_MODE = 0xE0, + eHCOM_SET_DBG_MODE = 0xE1, + + eHCOM_DEFAULT = 0xFF, +}; + +#define IST30XX_RINGBUF_NO_ERR (0) +#define IST30XX_RINGBUF_NOT_ENOUGH (1) +#define IST30XX_RINGBUF_EMPTY (2) +#define IST30XX_RINGBUF_FULL (3) +#define IST30XX_RINGBUF_TIMEOUT (4) +#define IST30XX_MAX_RINGBUF_SIZE (4 * 100 * 1024) +typedef struct _IST30XX_RINGBUF { + u32 RingBufCtr; + u32 RingBufInIdx; + u32 RingBufOutIdx; + u8 LogBuf[IST30XX_MAX_RINGBUF_SIZE]; +} IST30XX_RING_BUF; + +typedef union { + struct { + u32 y:12; + u32 x:12; +#ifdef IST30XX_USE_3D_TOUCH + u32 f:8; +#else + u32 w:4; + u32 id:4; +#endif + } bit_field; + u32 full_field; +} finger_info; + +struct ist30xx_status { + int power; + int update; + int update_result; + int calib; + int calib_msg; + u32 cal_ref_msg; + u32 cmcs; + bool event_mode; + bool noise_mode; +}; + +struct ist30xx_version { + u32 main_ver; + u32 fw_ver; + u32 core_ver; + u32 test_ver; +#ifdef XIAOMI_PRODUCT + u32 lockdown[2]; + u32 config[2]; +#endif +}; + +struct ist30xx_fw { + struct ist30xx_version prev; + struct ist30xx_version cur; + struct ist30xx_version bin; + u32 index; + u32 size; + u32 chksum; + u32 buf_size; + u8 *buf; +}; + +#define IST30XX_TAG_MAGIC "ISTV2TAG" +struct ist30xx_tags { + char magic1[8]; + u32 rom_base; + u32 ram_base; + u32 reserved0; + u32 reserved1; + + u32 fw_addr; + u32 fw_size; + u32 cfg_addr; + u32 cfg_size; + u32 sensor_addr; + u32 sensor_size; + u32 cp_addr; + u32 cp_size; + u32 flag_addr; + u32 flag_size; + u32 reserved2; + u32 reserved3; + + u32 zvalue_base; + u32 algr_base; + u32 raw_base; + u32 filter_base; + u32 reserved4; + u32 reserved5; + + u32 chksum; + u32 chksum_all; + u32 reserved6; + u32 reserved7; + + u8 day; + u8 month; + u16 year; + u8 hour; + u8 min; + u8 sec; + u8 reserved8; + char magic2[8]; +}; + +struct CH_NUM { + u8 tx; + u8 rx; +}; + +struct GTX_INFO { + u8 num; + u8 ch_num[4]; +}; + +struct TSP_NODE_BUF { + u16 raw[IST30XX_MAX_NODE_NUM]; + u16 base[IST30XX_MAX_NODE_NUM]; + u16 filter[IST30XX_MAX_NODE_NUM]; + u16 cp_lower[IST30XX_MAX_NODE_NUM]; + u16 cp_upper[IST30XX_MAX_NODE_NUM]; + u16 len; +}; + +struct TSP_DIRECTION { + bool swap_xy; + bool flip_x; + bool flip_y; +}; + +typedef struct _TSP_INFO { + struct CH_NUM ch_num; + struct CH_NUM screen; + struct GTX_INFO gtx; + struct TSP_DIRECTION dir; + struct TSP_NODE_BUF node; + int height; + int width; + int finger_num; + u16 baseline; +} TSP_INFO; + +typedef struct _TKEY_INFO { + int key_num; + bool enable; + struct CH_NUM ch_num[IST30XX_MAX_KEYS]; + u16 baseline; +} TKEY_INFO; + +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif +#ifdef IST30XX_TA_CALLBACK +#include +#endif +struct ist30xx_dt_data { + u32 reset_gpio; + u32 irq_gpio; + const char *vdd_name; + const char *vddio_name; +}; + +struct ist30xx_data { + struct mutex lock; + struct i2c_client *client; + struct input_dev *input_dev; + struct ist30xx_dt_data *dt_data; + TSP_INFO tsp_info; + TKEY_INFO tkey_info; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif + struct ist30xx_status status; + struct ist30xx_fw fw; + struct ist30xx_tags tags; + u32 chip_id; + u32 fw_mode; + u32 max_fingers; + u32 max_keys; + u32 t_status; + finger_info fingers[IST30XX_MAX_FINGERS]; + bool tsp_touched[IST30XX_MAX_FINGERS]; +#ifdef IST30XX_USE_KEY + bool tkey_pressed[IST30XX_MAX_KEYS]; +#endif +#if defined(CONFIG_FB) + struct notifier_block fb_notif; +#endif + + u32 raw_addr; + u32 filter_addr; + u32 zvalue_addr; + u32 algorithm_addr; + volatile bool irq_working; + bool irq_enabled; + bool initialized; + bool ignore_delay; + u32 noise_mode; + u32 debug_mode; + u32 jig_mode; + u32 z_values[IST30XX_MAX_FINGERS]; + int report_rate; + int idle_rate; +#ifdef IST30XX_GESTURE + bool suspend; + bool gesture; +#endif + int scan_count; + int scan_retry; + int max_scan_retry; + int timer_period_ms; + struct timer_list event_timer; + struct timespec t_current; /* nano seconds */ + u32 event_ms; + u32 timer_ms; + int cal_ref_count; + int irq_err_cnt; + int max_irq_err_cnt; + u32 intr_debug1_addr; + u32 intr_debug1_size; + u32 intr_debug2_addr; + u32 intr_debug2_size; + u32 intr_debug3_addr; + u32 intr_debug3_size; + u32 rec_mode; + struct CH_NUM rec_start_ch; + struct CH_NUM rec_stop_ch; + int rec_delay; + char *rec_file_name; + u32 debugging_mode; + u32 debugging_addr; + u8 debugging_size; + u32 debugging_scancnt; + u32 debugging_noise; + u32 t_frame[2]; + struct delayed_work work_reset_check; +#ifdef IST30XX_NOISE_MODE + struct delayed_work work_noise_protect; +#else +#ifdef IST30XX_FORCE_RELEASE + struct delayed_work work_force_release; +#endif +#endif +#ifdef IST30XX_ALGORITHM_MODE + struct delayed_work work_debug_algorithm; + u32 algr_addr; + u32 algr_size; +#endif + struct delayed_work work_cal_reference; +#ifdef IST30XX_INTERNAL_BIN +#ifdef IST30XX_UPDATE_BY_WORKQUEUE + struct delayed_work work_fw_update; +#endif +#endif +#ifdef USE_TSP_TA_CALLBACKS + struct tsp_callbacks callbacks; +#endif + +#ifdef S_IRWXUGO +#undef S_IRWXUGO +#define S_IRWXUGO 0664 +#endif + +#ifdef XIAOMI_PRODUCT + u32 pid; + u32 lockdown_upper; +#endif + struct pinctrl *pinctrl; + struct pinctrl_state *pinctrl_state_active; + struct pinctrl_state *pinctrl_state_suspend; + struct pinctrl_state *pinctrl_state_release; + struct regulator *vdd; + struct regulator *vddio; +}; + +extern int ist30xx_log_level; +extern struct class *ist30xx_class; +extern bool ist30xx_gesture_func_on; + +void tsp_printk(int level, const char *fmt, ...); +void ist30xx_delay(unsigned int ms); +int ist30xx_intr_wait(struct ist30xx_data *data, long ms); + +void ist30xx_enable_irq(struct ist30xx_data *data); +void ist30xx_disable_irq(struct ist30xx_data *data); +void ist30xx_set_ta_mode(bool charging); +void ist30xx_set_edge_mode(int mode); +void ist30xx_set_cover_mode(int mode); +void ist30xx_start(struct ist30xx_data *data); +int ist30xx_get_ver_info(struct ist30xx_data *data); + +int ist30xx_read_reg(struct i2c_client *client, u32 reg, u32 *buf); +int ist30xx_read_cmd(struct ist30xx_data *data, u32 cmd, u32 *buf); +int ist30xx_write_cmd(struct ist30xx_data *data, u32 cmd, u32 val); +int ist30xx_read_buf(struct i2c_client *client, u32 cmd, u32 *buf, u16 len); +int ist30xx_write_buf(struct i2c_client *client, u32 cmd, u32 *buf, u16 len); +int ist30xx_burst_read(struct i2c_client *client, u32 addr, + u32 *buf32, u16 len, bool bit_en); +int ist30xx_burst_write(struct i2c_client *client, u32 addr, + u32 *buf32, u16 len); + +int ist30xx_cmd_start_scan(struct ist30xx_data *data); +int ist30xx_cmd_calibrate(struct ist30xx_data *data); +int ist30xx_cmd_cal_reference(struct ist30xx_data *data); +int ist30xx_cmd_check_calib(struct ist30xx_data *data); +int ist30xx_cmd_update(struct ist30xx_data *data, int cmd); +int ist30xx_cmd_hold(struct ist30xx_data *data, int enable); + +int ist30xx_power_on(struct ist30xx_data *data, bool download); +int ist30xx_power_off(struct ist30xx_data *data); +int ist30xx_reset(struct ist30xx_data *data, bool download); + +int ist30xx_internal_suspend(struct ist30xx_data *data); +int ist30xx_internal_resume(struct ist30xx_data *data); + +int ist30xx_init_system(struct ist30xx_data *data); + +#endif /* __IST30XXC_H__ */ diff --git a/drivers/input/touchscreen/ist3038c/ist30xxc_cmcs.c b/drivers/input/touchscreen/ist3038c/ist30xxc_cmcs.c new file mode 100644 index 0000000000000..35133248a27d3 --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/ist30xxc_cmcs.c @@ -0,0 +1,2106 @@ +/* + * Copyright (C) 2010,Imagis Technology Co. Ltd. All Rights Reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ist30xxc.h" +#include "ist30xxc_cmcs.h" + +#ifdef IST30XX_CMCS_TEST + +#ifdef INTERNAL_CMCS_BIN +#include "ist30xxc_cmcs_bin.h" +#endif + +#define TSP_CH_UNUSED (0) +#define TSP_CH_SCREEN (1) +#define TSP_CH_GTX (2) +#define TSP_CH_KEY (3) +#define TSP_CH_UNKNOWN (-1) + +#define CMCS_FLAG_CM (1 << 0) +#define CMCS_FLAG_CM_SPEC (1 << 1) +#define CMCS_FLAG_CM_SLOPE0 (1 << 2) +#define CMCS_FLAG_CM_SLOPE1 (1 << 3) +#define CMCS_FLAG_CMJIT (1 << 4) +#define CMCS_FLAG_CM2 (1 << 5) +#define CMCS_FLAG_CS (1 << 6) +#define CMCS_FLAG_INT (1 << 7) + +#define CMCS_ENABLE_CM (1 << 0) +#define CMCS_ENABLE_CM2 (1 << 1) +#define CMCS_ENABLE_CS (1 << 8) +#define CMCS_ENABLE_INT (1 << 16) +#define CMCS_ENABLE_CMJIT (1 << 24) + +#define CMCS_READY (0) +#define CMCS_NOT_READY (-1) + +#define CMCS_TIMEOUT (10000) + +#define CMCS_CMJIT ("CMJIT") +#define CMCS_CM ("CM") +#define CMCS_CM2 ("CM2") +#define CMCS_CS ("CS") + +#define CMCS_PARSING_DEBUG (0) +#define CMCS_TAGS_PARSE_OK (0) + +int cmcs_ready = CMCS_READY; +u8 *ts_cmcs_bin = NULL; +u32 ts_cmcs_bin_size = 0; +CMCS_BIN_INFO ist30xx_cmcs_bin; +CMCS_BIN_INFO *ts_cmcs = (CMCS_BIN_INFO *)&ist30xx_cmcs_bin; +CMCS_BUF ist30xx_cmcs_buf; +CMCS_BUF *ts_cmcs_buf = (CMCS_BUF *)&ist30xx_cmcs_buf; + +int ist30xx_parse_cmcs_bin(const u8 *buf, const u32 size) +{ + int ret = -EPERM; + int i; + int node_spec_cnt; + + memcpy(ts_cmcs->magic1, buf, sizeof(ts_cmcs->magic1)); + memcpy(ts_cmcs->magic2, &buf[size - sizeof(ts_cmcs->magic2)], + sizeof(ts_cmcs->magic2)); + + if (!strncmp(ts_cmcs->magic1, IST30XX_CMCS_MAGIC, sizeof(ts_cmcs->magic1)) + && !strncmp(ts_cmcs->magic2, IST30XX_CMCS_MAGIC, + sizeof(ts_cmcs->magic2))) { + int idx; + + idx = sizeof(ts_cmcs->magic1); + + memcpy(&ts_cmcs->items.cnt, &buf[idx], sizeof(ts_cmcs->items.cnt)); + idx += sizeof(ts_cmcs->items.cnt); + ts_cmcs->items.item = kmalloc( + sizeof(struct CMCS_ITEM_INFO) * ts_cmcs->items.cnt, GFP_KERNEL); + for (i = 0; i < ts_cmcs->items.cnt; i++) { + memcpy(&ts_cmcs->items.item[i], &buf[idx], + sizeof(struct CMCS_ITEM_INFO)); + idx += sizeof(struct CMCS_ITEM_INFO); + } + + memcpy(&ts_cmcs->cmds.cnt, &buf[idx], sizeof(ts_cmcs->cmds.cnt)); + idx += sizeof(ts_cmcs->cmds.cnt); + ts_cmcs->cmds.cmd = kmalloc( + sizeof(struct CMCS_CMD_INFO) * ts_cmcs->cmds.cnt, GFP_KERNEL); + for (i = 0; i < ts_cmcs->cmds.cnt; i++) { + memcpy(&ts_cmcs->cmds.cmd[i], &buf[idx], + sizeof(struct CMCS_CMD_INFO)); + idx += sizeof(struct CMCS_CMD_INFO); + } + + memcpy(&ts_cmcs->spec_slope, &buf[idx], sizeof(ts_cmcs->spec_slope)); + idx += sizeof(ts_cmcs->spec_slope); + + memcpy(&ts_cmcs->spec_cr, &buf[idx], sizeof(ts_cmcs->spec_cr)); + idx += sizeof(ts_cmcs->spec_cr); + + memcpy(&ts_cmcs->param, &buf[idx], sizeof(ts_cmcs->param)); + idx += sizeof(ts_cmcs->param); + + ts_cmcs->spec_item = kmalloc( + sizeof(struct CMCS_SPEC_TOTAL) * ts_cmcs->items.cnt, GFP_KERNEL); + for (i = 0; i < ts_cmcs->items.cnt; i++) { + if (!strcmp(ts_cmcs->items.item[i].spec_type, "N")) { + memcpy(&node_spec_cnt, &buf[idx], sizeof(node_spec_cnt)); + ts_cmcs->spec_item[i].spec_node.node_cnt = node_spec_cnt; + idx += sizeof(node_spec_cnt); + ts_cmcs->spec_item[i].spec_node.buf_min = (u16 *)&buf[idx]; + idx += node_spec_cnt * sizeof(s16); + ts_cmcs->spec_item[i].spec_node.buf_max = (u16 *)&buf[idx]; + idx += node_spec_cnt * sizeof(s16); + } else if (!strcmp(ts_cmcs->items.item[i].spec_type, "T")) { + memcpy(&ts_cmcs->spec_item[i].spec_total, &buf[idx], + sizeof(struct CMCS_SPEC_TOTAL)); + idx += sizeof(struct CMCS_SPEC_TOTAL); + } + } + + ts_cmcs->buf_cmcs = (u8 *)&buf[idx]; + idx += ts_cmcs->param.cmcs_size; + + ts_cmcs->buf_cm_sensor = (u32 *)&buf[idx]; + idx += ts_cmcs->param.cm_sensor1_size + ts_cmcs->param.cm_sensor2_size + + ts_cmcs->param.cm_sensor3_size; + + ts_cmcs->buf_cs_sensor = (u32 *)&buf[idx]; + idx += ts_cmcs->param.cs_sensor1_size + ts_cmcs->param.cs_sensor2_size + + ts_cmcs->param.cs_sensor3_size; + + ts_cmcs->buf_jit_sensor = (u32 *)&buf[idx]; + idx += ts_cmcs->param.jit_sensor1_size + ts_cmcs->param.jit_sensor2_size + + ts_cmcs->param.jit_sensor3_size; + + ts_cmcs->version = *((u32 *)&buf[idx]); + + ret = 0; + } + + tsp_verb("Magic1: %s, Magic2: %s\n", ts_cmcs->magic1, ts_cmcs->magic2); + tsp_verb("CmCs ver: %08X\n", ts_cmcs->version); + tsp_verb(" item(%d)\n", ts_cmcs->items.cnt); + for (i = 0; i < ts_cmcs->items.cnt; i++) { + tsp_verb(" (%d): %s, 0x%08x, %d, %s, %s\n", + i, ts_cmcs->items.item[i].name, ts_cmcs->items.item[i].addr, + ts_cmcs->items.item[i].size, ts_cmcs->items.item[i].data_type, + ts_cmcs->items.item[i].spec_type); + } + tsp_verb(" cmd(%d)\n", ts_cmcs->cmds.cnt); + for (i = 0; i < ts_cmcs->cmds.cnt; i++) + tsp_verb(" (%d): 0x%08x, 0x%08x\n", + i, ts_cmcs->cmds.cmd[i].addr, ts_cmcs->cmds.cmd[i].value); + tsp_verb(" param\n"); + tsp_verb(" fw: 0x%08x, %d\n", ts_cmcs->param.cmcs_size_addr, + ts_cmcs->param.cmcs_size); + tsp_verb(" enable: 0x%08x\n", ts_cmcs->param.enable_addr); + tsp_verb(" checksum: 0x%08x\n", ts_cmcs->param.checksum_addr); + tsp_verb(" endnotify: 0x%08x\n", ts_cmcs->param.end_notify_addr); + tsp_verb(" cm sensor1: 0x%08x, %d\n", ts_cmcs->param.sensor1_addr, + ts_cmcs->param.cm_sensor1_size); + tsp_verb(" cm sensor2: 0x%08x, %d\n", ts_cmcs->param.sensor2_addr, + ts_cmcs->param.cm_sensor2_size); + tsp_verb(" cm sensor3: 0x%08x, %d\n", ts_cmcs->param.sensor3_addr, + ts_cmcs->param.cm_sensor3_size); + tsp_verb(" cs sensor1: 0x%08x, %d\n", ts_cmcs->param.sensor1_addr, + ts_cmcs->param.cs_sensor1_size); + tsp_verb(" cs sensor2: 0x%08x, %d\n", ts_cmcs->param.sensor2_addr, + ts_cmcs->param.cs_sensor2_size); + tsp_verb(" cs sensor3: 0x%08x, %d\n", ts_cmcs->param.sensor3_addr, + ts_cmcs->param.cs_sensor3_size); + tsp_verb(" jit sensor1: 0x%08x, %d\n", ts_cmcs->param.sensor1_addr, + ts_cmcs->param.jit_sensor1_size); + tsp_verb(" jit sensor2: 0x%08x, %d\n", ts_cmcs->param.sensor2_addr, + ts_cmcs->param.jit_sensor2_size); + tsp_verb(" jit sensor3: 0x%08x, %d\n", ts_cmcs->param.sensor3_addr, + ts_cmcs->param.jit_sensor3_size); + tsp_verb(" chksum: 0x%08x\n, 0x%08x\n, 0x%08x, 0x%08x\n", + ts_cmcs->param.cmcs_chksum, ts_cmcs->param.cm_sensor_chksum, + ts_cmcs->param.cs_sensor_chksum, ts_cmcs->param.jit_sensor_chksum); + tsp_verb(" cs result addr(tx, rx): 0x%08x, 0x%08x\n", + ts_cmcs->param.cs_tx_result_addr, ts_cmcs->param.cs_rx_result_addr); + tsp_verb(" slope(%s)\n", ts_cmcs->spec_slope.name); + tsp_verb(" x(%d,%d),y(%d,%d),gtx_x(%d,%d),gtx_y(%d,%d),key(%d,%d)\n", + ts_cmcs->spec_slope.x_min, ts_cmcs->spec_slope.x_max, + ts_cmcs->spec_slope.y_min, ts_cmcs->spec_slope.y_max, + ts_cmcs->spec_slope.gtx_x_min, ts_cmcs->spec_slope.gtx_x_max, + ts_cmcs->spec_slope.gtx_y_min, ts_cmcs->spec_slope.gtx_y_max, + ts_cmcs->spec_slope.key_min, ts_cmcs->spec_slope.key_max); + tsp_verb(" cr: screen(%4d, %4d), gtx(%4d, %4d), key(%4d, %4d)\n", + ts_cmcs->spec_cr.screen_min, ts_cmcs->spec_cr.screen_max, + ts_cmcs->spec_cr.gtx_min, ts_cmcs->spec_cr.gtx_max, + ts_cmcs->spec_cr.key_min, ts_cmcs->spec_cr.key_max); + for (i = 0; i < ts_cmcs->items.cnt; i++) { + if (!strcmp(ts_cmcs->items.item[i].spec_type, "N")) { + tsp_verb(" %s\n", ts_cmcs->items.item[i].name); + tsp_verb(" min: %x, %x, %x, %x\n", + ts_cmcs->spec_item[i].spec_node.buf_min[0], + ts_cmcs->spec_item[i].spec_node.buf_min[1], + ts_cmcs->spec_item[i].spec_node.buf_min[2], + ts_cmcs->spec_item[i].spec_node.buf_min[3]); + tsp_verb(" max: %x, %x, %x, %x\n", + ts_cmcs->spec_item[i].spec_node.buf_max[0], + ts_cmcs->spec_item[i].spec_node.buf_max[1], + ts_cmcs->spec_item[i].spec_node.buf_max[2], + ts_cmcs->spec_item[i].spec_node.buf_max[3]); + } else if (!strcmp(ts_cmcs->items.item[i].spec_type, "T")) { + tsp_verb(" %s: screen(%4d, %4d), gtx(%4d, %4d), key(%4d, %4d)\n", + ts_cmcs->items.item[i].name, + ts_cmcs->spec_item[i].spec_total.screen_min, + ts_cmcs->spec_item[i].spec_total.screen_max, + ts_cmcs->spec_item[i].spec_total.gtx_min, + ts_cmcs->spec_item[i].spec_total.gtx_max, + ts_cmcs->spec_item[i].spec_total.key_min, + ts_cmcs->spec_item[i].spec_total.key_max); + } + } + tsp_verb(" cmcs: %x, %x, %x, %x\n", ts_cmcs->buf_cmcs[0], + ts_cmcs->buf_cmcs[1], ts_cmcs->buf_cmcs[2], ts_cmcs->buf_cmcs[3]); + tsp_verb(" cm sensor: %x, %x, %x, %x\n", + ts_cmcs->buf_cm_sensor[0], ts_cmcs->buf_cm_sensor[1], + ts_cmcs->buf_cm_sensor[2], ts_cmcs->buf_cm_sensor[3]); + tsp_verb(" cs sensor: %x, %x, %x, %x\n", + ts_cmcs->buf_cs_sensor[0], ts_cmcs->buf_cs_sensor[1], + ts_cmcs->buf_cs_sensor[2], ts_cmcs->buf_cs_sensor[3]); + tsp_verb(" jit sensor: %x, %x, %x, %x\n", + ts_cmcs->buf_jit_sensor[0], ts_cmcs->buf_jit_sensor[1], + ts_cmcs->buf_jit_sensor[2], ts_cmcs->buf_jit_sensor[3]); + + return ret; +} + +int ist30xx_get_cmcs_info(const u8 *buf, const u32 size) +{ + int ret; + + cmcs_ready = CMCS_NOT_READY; + + ret = ist30xx_parse_cmcs_bin(buf, size); + if (unlikely(ret != CMCS_TAGS_PARSE_OK)) + tsp_warn("Cannot find tags of CMCS, make a bin by 'cmcs2bin.exe'\n"); + + return ret; +} + +int ist30xx_set_cmcs_fw(struct ist30xx_data *data, CMCS_PARAM param, u32 *buf32) +{ + int ret; + int len; + u32 waddr; + u32 val; + + len = param.cmcs_size / IST30XX_DATA_LEN; + waddr = IST30XX_DA_ADDR(data->tags.ram_base); + tsp_verb("%08x %08x %08x %08x\n", buf32[0], buf32[1], buf32[2], buf32[3]); + tsp_verb("%08x(%d)\n", waddr, len); + ret = ist30xx_burst_write(data->client, waddr, buf32, len); + if (ret) + return ret; + + waddr = IST30XX_DA_ADDR(param.cmcs_size_addr); + val = param.cmcs_size; + tsp_verb("size(0x%08x): 0x%08x\n", waddr, val); + ret = ist30xx_write_cmd(data, waddr, val); + if (ret) + return ret; + + tsp_info("cmcs code loaded!\n"); + + return 0; +} + +int ist30xx_set_cmcs_sensor(struct ist30xx_data *data, CMCS_PARAM param, + u32 *buf32, int mode) +{ + int ret; + int len = 0; + u32 waddr; + + if ((mode == CMCS_FLAG_CM) || (mode == CMCS_FLAG_CM2)) { + waddr = IST30XX_DA_ADDR(param.sensor1_addr); + len = (param.cm_sensor1_size / IST30XX_DATA_LEN) - 2; + buf32 += 2; + tsp_verb("%08x %08x %08x %08x\n", + buf32[0], buf32[1], buf32[2], buf32[3]); + tsp_verb("%08x(%d)\n", waddr, len); + + if (len > 0) { + ret = ist30xx_burst_write(data->client, waddr, buf32, len); + if (ret) + return ret; + + tsp_info("cm sensor reg1 loaded!\n"); + } + + buf32 += len; + waddr = IST30XX_DA_ADDR(param.sensor2_addr); + len = param.cm_sensor2_size / IST30XX_DATA_LEN; + tsp_verb("%08x %08x %08x %08x\n", + buf32[0], buf32[1], buf32[2], buf32[3]); + tsp_verb("%08x(%d)\n", waddr, len); + + if (len > 0) { + ret = ist30xx_burst_write(data->client, waddr, buf32, len); + if (ret) + return ret; + + tsp_info("cm sensor reg2 loaded!\n"); + } + + buf32 += len; + waddr = IST30XX_DA_ADDR(param.sensor3_addr); + len = param.cm_sensor3_size / IST30XX_DATA_LEN; + tsp_verb("%08x %08x %08x %08x\n", + buf32[0], buf32[1], buf32[2], buf32[3]); + tsp_verb("%08x(%d)\n", waddr, len); + + if (len > 0) { + ret = ist30xx_burst_write(data->client, waddr, buf32, len); + if (ret) + return ret; + + tsp_info("cm sensor reg3 loaded!\n"); + } + } else if (mode == CMCS_FLAG_CS) { + waddr = IST30XX_DA_ADDR(param.sensor1_addr); + len = (param.cs_sensor1_size / IST30XX_DATA_LEN) - 2; + buf32 += 2; + tsp_verb("%08x %08x %08x %08x\n", + buf32[0], buf32[1], buf32[2], buf32[3]); + tsp_verb("%08x(%d)\n", waddr, len); + + if (len > 0) { + ret = ist30xx_burst_write(data->client, waddr, buf32, len); + if (ret) + return ret; + + tsp_info("cs sensor reg1 loaded!\n"); + } + + buf32 += len; + waddr = IST30XX_DA_ADDR(param.sensor2_addr); + len = param.cs_sensor2_size / IST30XX_DATA_LEN; + tsp_verb("%08x %08x %08x %08x\n", + buf32[0], buf32[1], buf32[2], buf32[3]); + tsp_verb("%08x(%d)\n", waddr, len); + + if (len > 0) { + ret = ist30xx_burst_write(data->client, waddr, buf32, len); + if (ret) + return ret; + + tsp_info("cs sensor reg2 loaded!\n"); + } + + buf32 += len; + waddr = IST30XX_DA_ADDR(param.sensor3_addr); + len = param.cs_sensor3_size / IST30XX_DATA_LEN; + tsp_verb("%08x %08x %08x %08x\n", + buf32[0], buf32[1], buf32[2], buf32[3]); + tsp_verb("%08x(%d)\n", waddr, len); + + if (len > 0) { + ret = ist30xx_burst_write(data->client, waddr, buf32, len); + if (ret) + return ret; + + tsp_info("cs sensor reg3 loaded!\n"); + } + } else if (mode == CMCS_FLAG_CMJIT) { + waddr = IST30XX_DA_ADDR(param.sensor1_addr); + len = (param.jit_sensor1_size / IST30XX_DATA_LEN) - 2; + buf32 += 2; + tsp_verb("%08x %08x %08x %08x\n", + buf32[0], buf32[1], buf32[2], buf32[3]); + tsp_verb("%08x(%d)\n", waddr, len); + + if (len > 0) { + ret = ist30xx_burst_write(data->client, waddr, buf32, len); + if (ret) + return ret; + + tsp_info("jit sensor reg1 loaded!\n"); + } + + buf32 += len; + waddr = IST30XX_DA_ADDR(param.sensor2_addr); + len = param.jit_sensor2_size / IST30XX_DATA_LEN; + tsp_verb("%08x %08x %08x %08x\n", + buf32[0], buf32[1], buf32[2], buf32[3]); + tsp_verb("%08x(%d)\n", waddr, len); + + if (len > 0) { + ret = ist30xx_burst_write(data->client, waddr, buf32, len); + if (ret) + return ret; + + tsp_info("jit sensor reg2 loaded!\n"); + } + + buf32 += len; + waddr = IST30XX_DA_ADDR(param.sensor3_addr); + len = param.jit_sensor3_size / IST30XX_DATA_LEN; + tsp_verb("%08x %08x %08x %08x\n", + buf32[0], buf32[1], buf32[2], buf32[3]); + tsp_verb("%08x(%d)\n", waddr, len); + + if (len > 0) { + ret = ist30xx_burst_write(data->client, waddr, buf32, len); + if (ret) + return ret; + + tsp_info("jit sensor reg3 loaded!\n"); + } + } + + return 0; +} + +int ist30xx_set_cmcs_cmd(struct ist30xx_data *data, CMCS_CMD cmds) +{ + int ret; + int i; + u32 val; + u32 waddr; + + for (i = 0; i < cmds.cnt; i++) { + waddr = IST30XX_DA_ADDR(cmds.cmd[i].addr); + val = cmds.cmd[i].value; + ret = ist30xx_write_cmd(data, waddr, val); + if (ret) + return ret; + tsp_verb("cmd%d(0x%08x): 0x%08x\n", i, waddr, val); + } + + tsp_info("cmcs command loaded!\n"); + + return 0; +} + +int ist30xx_parse_cmcs_buf(struct ist30xx_data *data, s16 *buf) +{ + int i, j; + TSP_INFO *tsp = &data->tsp_info; + + tsp_info(" %d * %d\n", tsp->ch_num.tx, tsp->ch_num.rx); + for (i = 0; i < tsp->ch_num.tx; i++) { + tsp_info(" "); + for (j = 0; j < tsp->ch_num.rx; j++) + printk("%5d ", buf[i * tsp->ch_num.rx + j]); + printk("\n"); + } + + return 0; +} + +int ist30xx_apply_cmcs_slope(struct ist30xx_data *data, CMCS_BUF *cmcs_buf) +{ + int i, j, k; + int idx1, idx2, gtx_idx, key_idx; + int type; + int success = false; + TSP_INFO *tsp = &data->tsp_info; + int width = tsp->screen.rx; + int height = tsp->screen.tx; + s16 *presult; +#ifdef IST30XX_SDC_SLOPE + s16 slope_x = 0; + s16 slope_y = 0; +#else + s16 *pspec_min = (s16 *)cmcs_buf->spec_min; + s16 *pspec_max = (s16 *)cmcs_buf->spec_max; +#endif + s16 *pslope0 = (s16 *)cmcs_buf->slope0; + s16 *pslope1 = (s16 *)cmcs_buf->slope1; + + memset(cmcs_buf->slope0, 0, sizeof(cmcs_buf->slope0)); + memset(cmcs_buf->slope1, 0, sizeof(cmcs_buf->slope1)); + + if (!strcmp(ts_cmcs->spec_slope.name, CMCS_CS)) + presult = (s16 *)&cmcs_buf->cs; + else + presult = (s16 *)&cmcs_buf->cm; + + for (i = 0; i < ts_cmcs->items.cnt; i++) { + if (!strcmp(ts_cmcs->spec_slope.name, ts_cmcs->items.item[i].name)) { + idx1 = idx2 = gtx_idx = key_idx = 0; + gtx_idx = tsp->screen.tx * tsp->screen.rx; + key_idx = gtx_idx + (tsp->gtx.num * tsp->screen.rx); + for (j = 0; j < tsp->ch_num.tx; j++) { + for (k = 0; k < tsp->ch_num.rx; k++) { + type = check_tsp_type(data, j, k); + idx1 = (j * tsp->ch_num.rx) + k; + if (type == TSP_CH_UNKNOWN) { + continue; + } else if (type == TSP_CH_UNUSED) { + cmcs_buf->spec_min[idx1] = 0; + cmcs_buf->spec_max[idx1] = 0; + } else if (type == TSP_CH_GTX) { + cmcs_buf->spec_min[idx1] = + ts_cmcs->spec_item[i].spec_node.buf_min[gtx_idx]; + cmcs_buf->spec_max[idx1] = + ts_cmcs->spec_item[i].spec_node.buf_max[gtx_idx]; + gtx_idx++; + } else if (type == TSP_CH_KEY) { + cmcs_buf->spec_min[idx1] = + ts_cmcs->spec_item[i].spec_node.buf_min[key_idx]; + cmcs_buf->spec_max[idx1] = + ts_cmcs->spec_item[i].spec_node.buf_max[key_idx]; + key_idx++; + } else { + cmcs_buf->spec_min[idx1] = + ts_cmcs->spec_item[i].spec_node.buf_min[idx2]; + cmcs_buf->spec_max[idx1] = + ts_cmcs->spec_item[i].spec_node.buf_max[idx2]; + idx2++; + } + } + } + success = true; + } + } + + if (success == false) + return -EPERM; + +#if CMCS_PARSING_DEBUG + idx1 = 0; + tsp_info("# Node min specific\n"); + for (i = 0; i < tsp->ch_num.tx; i++) { + tsp_info(" "); + for (j = 0; j < tsp->ch_num.rx; j++) + printk("%5d ", cmcs_buf->spec_min[idx1++]); + printk("\n"); + } + + idx1 = 0; + tsp_info("# Node max specific\n"); + for (i = 0; i < tsp->ch_num.tx; i++) { + tsp_info(" "); + for (j = 0; j < tsp->ch_num.rx; j++) + printk("%5d ", cmcs_buf->spec_max[idx1++]); + printk("\n"); + } +#endif + +#ifdef IST30XX_SDC_SLOPE + tsp_verb("# Apply slope\n"); + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + idx1 = (i * tsp->ch_num.rx) + j; + + idx2 = idx1 + 1; + if (j == (width - 1)) { + slope_x = 0; + } else { + slope_x = 100 - ((presult[idx1] * 100) / presult[idx2]); + if (slope_x < 0) + slope_x *= -1; + } + + idx2 = idx1 + tsp->ch_num.rx; + if (i == (height - 1)) { + slope_y = 0; + } else { + slope_y = 100 - ((presult[idx1] * 100) / presult[idx2]); + if (slope_y < 0) + slope_y *= -1; + } + + if (slope_x > slope_y) { + pslope0[idx1] = (s16)slope_x; + pslope1[idx1] = (s16)slope_x; + } else { + pslope0[idx1] = (s16)slope_y; + pslope1[idx1] = (s16)slope_y; + } + } + } + + tsp_verb("# Apply slope_gtx\n"); + for (i = 0; i < tsp->gtx.num; i++) { + if (tsp->gtx.ch_num[i] > height) { + for (j = 0; j < width; j++) { + idx1 = (tsp->gtx.ch_num[i] * tsp->ch_num.rx) + j; + + idx2 = idx1 + 1; + if (j == (width - 1)) { + slope_x = 0; + } else { + slope_x = 100 - ((presult[idx1] * 100) / presult[idx2]); + if (slope_x < 0) + slope_x *= -1; + } + + idx2 = idx1 + tsp->ch_num.rx; + if (i == (tsp->gtx.num - 1)) { + slope_y = 0; + } else { + slope_y = 100 - ((presult[idx1] * 100) / presult[idx2]); + if (slope_y < 0) + slope_y *= -1; + } + + if (slope_x > slope_y) { + pslope0[idx1] = (s16)slope_x; + pslope1[idx1] = (s16)slope_x; + } else { + pslope0[idx1] = (s16)slope_y; + pslope1[idx1] = (s16)slope_y; + } + } + } + } +#else + tsp_verb("# Apply slope0\n"); + for (i = 0; i < height; i++) { + for (j = 0; j < width - 1; j++) { + idx1 = (i * tsp->ch_num.rx) + j; + idx2 = idx1 + 1; + + pslope0[idx1] = (presult[idx2] - presult[idx1]); + pslope0[idx1] += + (((pspec_min[idx1] + pspec_max[idx1]) / 2) - + ((pspec_min[idx2] + pspec_max[idx2]) / 2)); + } + } + + tsp_verb("# Apply slope1\n"); + for (i = 0; i < height - 1; i++) { + for (j = 0; j < width; j++) { + idx1 = (i * tsp->ch_num.rx) + j; + idx2 = idx1 + tsp->ch_num.rx; + + pslope1[idx1] = (presult[idx2] - presult[idx1]); + pslope1[idx1] += + (((pspec_min[idx1] + pspec_max[idx1]) / 2) - + ((pspec_min[idx2] + pspec_max[idx2]) / 2)); + } + } + + tsp_verb("# Apply slope0 gtx\n"); + for (i = 0; i < tsp->gtx.num; i++) { + if (tsp->gtx.ch_num[i] > height) { + for (j = 0; j < width - 1; j++) { + idx1 = (tsp->gtx.ch_num[i] * tsp->ch_num.rx) + j; + idx2 = idx1 + 1; + + pslope0[idx1] = (presult[idx2] - presult[idx1]); + pslope0[idx1] += + (((pspec_min[idx1] + pspec_max[idx1]) / 2) - + ((pspec_min[idx2] + pspec_max[idx2]) / 2)); + } + } + } + + tsp_verb("# Apply slope1 gtx\n"); + for (i = 0; i < (tsp->gtx.num - 1); i++) { + if (tsp->gtx.ch_num[i] > height) { + for (j = 0; j < width; j++) { + idx1 = (tsp->gtx.ch_num[i] * tsp->ch_num.rx) + j; + idx2 = idx1 + tsp->ch_num.rx; + + pslope1[idx1] = (presult[idx2] - presult[idx1]); + pslope1[idx1] += + (((pspec_min[idx1] + pspec_max[idx1]) / 2) - + ((pspec_min[idx2] + pspec_max[idx2]) / 2)); + } + } + } +#endif + +#if CMCS_PARSING_DEBUG + tsp_info("# slope0_x\n"); + for (i = 0; i < height; i++) { + tsp_info(" "); + for (j = 0; j < width; j++) { + idx1 = (i * tsp->ch_num.rx) + j; + printk("%5d ", pslope0[idx1]); + } + printk("\n"); + } + + tsp_info("# slope1_y\n"); + for (i = 0; i < height; i++) { + tsp_info(" "); + for (j = 0; j < width; j++) { + idx1 = (i * tsp->ch_num.rx) + j; + printk("%5d ", pslope1[idx1]); + } + printk("\n"); + } + + tsp_info("# slope0_gtx_x\n"); + for (i = 0; i < tsp->gtx.num; i++) { + tsp_info(" "); + for (j = 0; j < width; j++) { + idx1 = (tsp->gtx.ch_num[i] * tsp->ch_num.rx) + j; + printk("%5d ", pslope0[idx1]); + } + printk("\n"); + } + + tsp_info("# slope1_gtx_y\n"); + for (i = 0; i < tsp->gtx.num; i++) { + tsp_info(" "); + for (j = 0; j < width; j++) { + idx1 = (tsp->gtx.ch_num[i] * tsp->ch_num.rx) + j; + printk("%5d ", pslope1[idx1]); + } + printk("\n"); + } +#endif + + return 0; +} + +int ist30xx_get_cmcs_buf(struct ist30xx_data *data, const char *mode, + CMCS_ITEM items, s16 *buf) +{ + int ret = 0; + int i; + bool success = false; + u32 waddr; + u16 len; + + for (i = 0; i < items.cnt; i++) { + if (!strcmp(items.item[i].name, mode)) { + waddr = IST30XX_DA_ADDR(items.item[i].addr); + len = items.item[i].size / IST30XX_DATA_LEN; + ret = ist30xx_burst_read(data->client, + waddr, (u32 *)buf, len, true); + if (unlikely(ret)) + return ret; + tsp_verb("%s, 0x%08x, %d\n", __func__, waddr, len); + success = true; + } + } + + if (success == false) { + tsp_info("item(%s) dosen't exist!\n", mode); + return ret; + } + +#if CMCS_PARSING_DEBUG + ret = ist30xx_parse_cmcs_buf(data, buf); +#endif + + return ret; +} + +int ist30xx_cmcs_wait(struct ist30xx_data *data, int mode) +{ + u32 waddr; + u32 val; + int ret; + int cnt = CMCS_TIMEOUT / 100; + + data->status.cmcs = 0; + + waddr = IST30XX_DA_ADDR(ts_cmcs->param.enable_addr); + if (mode == CMCS_FLAG_CM) + val = CMCS_ENABLE_CM; + else if (mode == CMCS_FLAG_CM2) + val = CMCS_ENABLE_CM2; + else if (mode == CMCS_FLAG_CS) + val = CMCS_ENABLE_CS; + else if (mode == CMCS_FLAG_CMJIT) + val = CMCS_ENABLE_CMJIT; + else if (mode == CMCS_FLAG_INT) + val = CMCS_ENABLE_INT; + else + return -EPERM; + + ret = ist30xx_write_cmd(data, waddr, val); + if (ret) + return -EPERM; + + while (cnt-- > 0) { + ist30xx_delay(100); + + if (data->status.cmcs) { + if (mode == CMCS_FLAG_CM) + goto cm_end; + else if (mode == CMCS_FLAG_CM2) + goto cm2_end; + else if (mode == CMCS_FLAG_CS) + goto cs_end; + else if (mode == CMCS_FLAG_CMJIT) + goto cmjit_end; + else if (mode == CMCS_FLAG_INT) + goto int_end; + else + return -EPERM; + } + } + tsp_warn("cmcs time out\n"); + + return -EPERM; + +cm_end: + if ((data->status.cmcs & CMCS_MSG_MASK) == CM_MSG_VALID) + if (!(data->status.cmcs & 0x1)) + return 0; + + tsp_warn("CM test fail\n"); + + return -EPERM; + +cm2_end: + if ((data->status.cmcs & CMCS_MSG_MASK) == CM2_MSG_VALID) + if (!(data->status.cmcs & 0x1)) + return 0; + + tsp_warn("CM2 test fail\n"); + + return -EPERM; + +cs_end: + if ((data->status.cmcs & CMCS_MSG_MASK) == CS_MSG_VALID) + if (!(data->status.cmcs & 0x1)) + return 0; + + tsp_warn("CS test fail\n"); + + return -EPERM; + +cmjit_end: + if ((data->status.cmcs & CMCS_MSG_MASK) == CMJIT_MSG_VALID) + if (!(data->status.cmcs & 0x1)) + return 0; + + tsp_warn("CMJIT test fail\n"); + + return -EPERM; + +int_end: + if ((data->status.cmcs & CMCS_MSG_MASK) == INT_MSG_VALID) + if (!(data->status.cmcs & 0x1)) + return 0; + + tsp_warn("INT test fail\n"); + + return -EPERM; +} + +int ist30xx_item_test(struct ist30xx_data *data, CMCS_ITEM items, + CMCS_PARAM param, const char *mode, u32 flag, u32 *buf32, s16 *buf) +{ + int i; + int ret; + + for (i = 0; i < items.cnt; i++) { + if (!strcmp(items.item[i].name, mode)) { + ret = ist30xx_set_cmcs_sensor(data, param, buf32, flag); + if (ret) { + tsp_info("%s test not ready!!\n", mode); + return ret; + } + tsp_info("%s test!!\n", mode); + + /* 6-2. write Start CM enable & wait CM complete interrupt */ + ist30xx_enable_irq(data); + if (ist30xx_cmcs_wait(data, flag)) { + tsp_info("%s test fail!\n", mode); + ret = -ENOEXEC; + return ret; + } + ist30xx_disable_irq(data); + + /* 6-3. read CM data */ + ret = ist30xx_get_cmcs_buf(data, mode, items, buf); + if (ret) { + tsp_info("fail to read %s data\n", mode); + return ret; + } + + tsp_info("read %s data\n", mode); + } + } + + return 0; +} + +#define cmcs_next_step(ret) { if (unlikely(ret)) goto end; ist30xx_delay(20); } +int ist30xx_cmcs_test(struct ist30xx_data *data, const u8 *buf, int size) +{ + int ret; + u32 waddr; + u32 chksum = 0; + u32 *buf32; + + tsp_info("*** CM/CS test ***\n"); + + ist30xx_disable_irq(data); + ist30xx_reset(data, false); + + /* 1. set CmCsFW write mode */ + ret = ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_RUN_RAMCODE << 16) | 0); + cmcs_next_step(ret); + + /* 2. write CmCsFW */ + buf32 = (u32 *)ts_cmcs->buf_cmcs; + ret = ist30xx_set_cmcs_fw(data, ts_cmcs->param, buf32); + cmcs_next_step(ret); + + /* 3. write cmds */ + ret = ist30xx_set_cmcs_cmd(data, ts_cmcs->cmds); + cmcs_next_step(ret); + + /* 4. start CmCsFW */ + ret = ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_RUN_RAMCODE << 16) | 1); + cmcs_next_step(ret); + + /* 5. read & compare checksum */ + waddr = IST30XX_DA_ADDR(ts_cmcs->param.checksum_addr); + ret = ist30xx_read_reg(data->client, waddr, &chksum); + cmcs_next_step(ret); + if (chksum != ts_cmcs->param.cmcs_chksum) + goto end; + + /* 6. CM Test */ + buf32 = ts_cmcs->buf_cm_sensor; + memset(ts_cmcs_buf->cm, 0, sizeof(ts_cmcs_buf->cm)); + ret = ist30xx_item_test(data, ts_cmcs->items, ts_cmcs->param, CMCS_CM, + CMCS_FLAG_CM, buf32, ts_cmcs_buf->cm); + cmcs_next_step(ret); + + /* 7. CM2 Test */ + buf32 = ts_cmcs->buf_cm_sensor; + memset(ts_cmcs_buf->cm2, 0, sizeof(ts_cmcs_buf->cm2)); + ret = ist30xx_item_test(data, ts_cmcs->items, ts_cmcs->param, CMCS_CM2, + CMCS_FLAG_CM2, buf32, ts_cmcs_buf->cm2); + cmcs_next_step(ret); + + /* 8. CMJIT Test */ + buf32 = ts_cmcs->buf_jit_sensor; + memset(ts_cmcs_buf->cm_jit, 0, sizeof(ts_cmcs_buf->cm_jit)); + ret = ist30xx_item_test(data, ts_cmcs->items, ts_cmcs->param, CMCS_CMJIT, + CMCS_FLAG_CMJIT, buf32, ts_cmcs_buf->cm_jit); + cmcs_next_step(ret); + + /* 9. CS Test */ + buf32 = ts_cmcs->buf_cs_sensor; + memset(ts_cmcs_buf->cs, 0, sizeof(ts_cmcs_buf->cs)); + ret = ist30xx_item_test(data, ts_cmcs->items, ts_cmcs->param, CMCS_CS, + CMCS_FLAG_CS, buf32, ts_cmcs_buf->cs); + cmcs_next_step(ret); + + /* 10. calculate slope value */ + ret = ist30xx_apply_cmcs_slope(data, ts_cmcs_buf); + cmcs_next_step(ret); + + cmcs_ready = CMCS_READY; +end: + if (unlikely(ret)) { + tsp_warn("CmCs test Fail!, ret=%d\n", ret); + } else if (unlikely(chksum != ts_cmcs->param.cmcs_chksum)) { + tsp_warn("Error CheckSum: %x(%x)\n", + chksum, ts_cmcs->param.cmcs_chksum); + ret = -ENOEXEC; + } + + ist30xx_reset(data, false); + ist30xx_enable_irq(data); + ist30xx_start(data); + + return ret; +} + + +int check_tsp_type(struct ist30xx_data *data, int tx, int rx) +{ + int i; + TSP_INFO *tsp = &data->tsp_info; + TKEY_INFO *tkey = &data->tkey_info; + + if ((tx >= tsp->ch_num.tx) || (tx < 0) || + (rx >= tsp->ch_num.rx) || (rx < 0)) { + tsp_warn("TSP channel is not correct!! (%d * %d)\n", tx, rx); + return TSP_CH_UNKNOWN; + } + + if ((tx >= tsp->screen.tx) || (rx >= tsp->screen.rx)) { + for (i = 0; i < tsp->gtx.num; i++) + if ((tx == tsp->gtx.ch_num[i]) && (rx < tsp->screen.rx)) + return TSP_CH_GTX; + + for (i = 0; i < tkey->key_num; i++) { + if ((tx == tkey->ch_num[i].tx) && + (rx == tkey->ch_num[i].rx)) + return TSP_CH_KEY; + } + } else { + return TSP_CH_SCREEN; + } + + return TSP_CH_UNUSED; +} + +int print_cmcs(struct ist30xx_data *data, s16 *buf16, char *buf) +{ + int i, j; + int idx; + int type; + int count = 0; + char msg[128]; + + TSP_INFO *tsp = &data->tsp_info; + + int tx_num = tsp->ch_num.tx; + int rx_num = tsp->ch_num.rx; + + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + type = check_tsp_type(data, i, j); + idx = (i * rx_num) + j; + if ((type == TSP_CH_UNKNOWN) || (type == TSP_CH_UNUSED)) + count += sprintf(msg, "%5d ", 0); + else + count += sprintf(msg, "%5d ", buf16[idx]); + strcat(buf, msg); + } + + count += sprintf(msg, "\n"); + strcat(buf, msg); + } + + return count; +} + +int print_line_cmcs(struct ist30xx_data *data, int mode, s16 *buf16, char *buf) +{ + int i, j; + int idx; + int type; + int count = 0; + int key_index[5] = { 0, }; + int key_cnt = 0; + char msg[128]; + + TSP_INFO *tsp = &data->tsp_info; + + int tx_num = tsp->ch_num.tx; + int rx_num = tsp->ch_num.rx; + + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + type = check_tsp_type(data, i, j); + if ((type == TSP_CH_UNKNOWN) || (type == TSP_CH_UNUSED)) + continue; + + if ((mode == CMCS_FLAG_CM_SLOPE0) && + (j == (tsp->screen.rx - 1))) + continue; + else if ((mode == CMCS_FLAG_CM_SLOPE1) && + (i == (tsp->screen.tx - 1))) + continue; + + if ((mode == CMCS_FLAG_CM_SLOPE0) && (type == TSP_CH_GTX) && + (j == (tsp->screen.rx - 1))) + continue; + else if ((mode == CMCS_FLAG_CM_SLOPE1) && + (type == TSP_CH_GTX) && + (i == tsp->gtx.ch_num[tsp->gtx.num - 1])) + continue; + + idx = (i * rx_num) + j; + + if (type == TSP_CH_KEY) { + key_index[key_cnt++] = idx; + continue; + } + + count += sprintf(msg, "%5d ", buf16[idx]); + strcat(buf, msg); + } + } + + if ((mode != CMCS_FLAG_CM_SLOPE0) && (mode != CMCS_FLAG_CM_SLOPE1)) { + tsp_debug("key cnt: %d\n", key_cnt); + for (i = 0; i < key_cnt; i++) { + count += sprintf(msg, "%5d ", buf16[key_index[i]]); + strcat(buf, msg); + } + } + + count += sprintf(msg, "\n"); + strcat(buf, msg); + + return count; +} + +/* sysfs: /sys/class/touch/cmcs/info */ +ssize_t ist30xx_cmcs_info_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i; + int count; + char msg[128]; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + TKEY_INFO *tkey = &data->tkey_info; + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + /* Channel */ + count = sprintf(msg, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d ", + tsp->ch_num.tx, tsp->ch_num.rx, tsp->screen.tx, tsp->screen.rx, + tsp->gtx.num, tsp->gtx.ch_num[0], tsp->gtx.ch_num[1], + tsp->gtx.ch_num[2], tsp->gtx.ch_num[3], tkey->key_num, + tkey->ch_num[0].tx, tkey->ch_num[0].rx, tkey->ch_num[1].tx, + tkey->ch_num[1].rx, tkey->ch_num[2].tx, tkey->ch_num[2].rx, + tkey->ch_num[3].tx, tkey->ch_num[3].rx, tkey->ch_num[4].tx, + tkey->ch_num[4].rx); + strcat(buf, msg); + + /* Slope */ + count += sprintf(msg, "%d %d %d %d %d %d %d %d %d %d ", + ts_cmcs->spec_slope.x_min, ts_cmcs->spec_slope.x_max, + ts_cmcs->spec_slope.y_min, ts_cmcs->spec_slope.y_max, + ts_cmcs->spec_slope.gtx_x_min, ts_cmcs->spec_slope.gtx_x_max, + ts_cmcs->spec_slope.gtx_y_min, ts_cmcs->spec_slope.gtx_y_max, + ts_cmcs->spec_slope.key_min, ts_cmcs->spec_slope.key_max); + strcat(buf, msg); + + /* CS */ + for (i = 0; i < ts_cmcs->items.cnt; i++) { + if (!strcmp(ts_cmcs->items.item[i].name, CMCS_CS)) { + if (!strcmp(ts_cmcs->items.item[i].spec_type, "T")) { + count += sprintf(msg, "%d %d %d %d %d %d ", + ts_cmcs->spec_item[i].spec_total.screen_min, + ts_cmcs->spec_item[i].spec_total.screen_max, + ts_cmcs->spec_item[i].spec_total.gtx_min, + ts_cmcs->spec_item[i].spec_total.gtx_max, + ts_cmcs->spec_item[i].spec_total.key_min, + ts_cmcs->spec_item[i].spec_total.key_max); + strcat(buf, msg); + } + } + } + + /* CR */ + count += sprintf(msg, "%d %d %d %d %d %d ", + ts_cmcs->spec_cr.screen_min, ts_cmcs->spec_cr.screen_max, + ts_cmcs->spec_cr.gtx_min, ts_cmcs->spec_cr.gtx_max, + ts_cmcs->spec_cr.key_min, ts_cmcs->spec_cr.key_max); + strcat(buf, msg); + + /* CMJIT */ + for (i = 0; i < ts_cmcs->items.cnt; i++) { + if (!strcmp(ts_cmcs->items.item[i].name, CMCS_CMJIT)) { + if (!strcmp(ts_cmcs->items.item[i].spec_type, "T")) { + count += sprintf(msg, "%d %d %d %d %d %d ", + ts_cmcs->spec_item[i].spec_total.screen_min, + ts_cmcs->spec_item[i].spec_total.screen_max, + ts_cmcs->spec_item[i].spec_total.gtx_min, + ts_cmcs->spec_item[i].spec_total.gtx_max, + ts_cmcs->spec_item[i].spec_total.key_min, + ts_cmcs->spec_item[i].spec_total.key_max); + strcat(buf, msg); + } + } + } + + tsp_verb("%s\n", buf); + + return count; +} + +/* sysfs: /sys/class/touch/cmcs/cmcs_binary */ +ssize_t ist30xx_cmcs_binary_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + struct ist30xx_data *data = dev_get_drvdata(dev); + + if ((ts_cmcs_bin == NULL) || (ts_cmcs_bin_size == 0)) + return sprintf(buf, "Binary is not correct(%d)\n", ts_cmcs_bin_size); + + ret = ist30xx_get_cmcs_info(ts_cmcs_bin, ts_cmcs_bin_size); + if (ret) + goto binary_end; + + mutex_lock(&data->lock); + ret = ist30xx_cmcs_test(data, ts_cmcs_bin, ts_cmcs_bin_size); + mutex_unlock(&data->lock); + +binary_end: + return sprintf(buf, (ret == 0 ? "OK\n" : "Fail\n")); +} + +/* sysfs: /sys/class/touch/cmcs/cmcs_custom */ +ssize_t ist30xx_cmcs_custom_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + int bin_size = 0; + u8 *bin = NULL; + const struct firmware *req_bin = NULL; + struct ist30xx_data *data = dev_get_drvdata(dev); + + ret = request_firmware(&req_bin, IST30XX_CMCS_NAME, &data->client->dev); + if (ret) + return sprintf(buf, "File not found, %s\n", IST30XX_CMCS_NAME); + + bin = (u8 *)req_bin->data; + bin_size = (u32)req_bin->size; + + ret = ist30xx_get_cmcs_info(bin, bin_size); + if (ret) + goto custom_end; + + mutex_lock(&data->lock); + ret = ist30xx_cmcs_test(data, bin, bin_size); + mutex_unlock(&data->lock); + +custom_end: + release_firmware(req_bin); + + return sprintf(buf, (ret == 0 ? "OK\n" : "Fail\n")); +} + +#define MAX_FILE_PATH 255 +/* sysfs: /sys/class/touch/cmcs/cmcs_sdcard */ +ssize_t ist30xx_cmcs_sdcard_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret = 0; + int bin_size = 0; + u8 *bin = NULL; + const u8 *buff = 0; + mm_segment_t old_fs = { 0 }; + struct file *fp = NULL; + long fsize = 0, nread = 0; + char fw_path[MAX_FILE_PATH]; + struct ist30xx_data *data = dev_get_drvdata(dev); + + old_fs = get_fs(); + set_fs(get_ds()); + + snprintf(fw_path, MAX_FILE_PATH, "/sdcard/%s", + IST30XX_CMCS_NAME); + fp = filp_open(fw_path, O_RDONLY, 0); + if (IS_ERR(fp)) { + tsp_info("file %s open error:%d\n", fw_path, PTR_ERR(fp)); + ret = -ENOENT; + goto err_file_open; + } + + fsize = fp->f_path.dentry->d_inode->i_size; + + buff = kzalloc((size_t)fsize, GFP_KERNEL); + if (!buff) { + tsp_info("fail to alloc buffer\n"); + ret = -ENOMEM; + goto err_alloc; + } + + nread = vfs_read(fp, (char __user *)buff, fsize, &fp->f_pos); + if (nread != fsize) { + tsp_info("mismatch fw size\n"); + + goto err_fw_size; + } + + bin = (u8 *)buff; + bin_size = (u32)fsize; + + filp_close(fp, current->files); + set_fs(old_fs); + tsp_info("firmware is loaded!!\n"); + + ret = ist30xx_get_cmcs_info(bin, bin_size); + if (ret) + goto sdcard_end; + + mutex_lock(&data->lock); + ret = ist30xx_cmcs_test(data, bin, bin_size); + mutex_unlock(&data->lock); + +err_fw_size: + if (buff) + kfree(buff); +err_alloc: + if (fp) + filp_close(fp, NULL); +err_file_open: + set_fs(old_fs); + +sdcard_end: + tsp_info("size: %d\n", sprintf(buf, (ret == 0 ? "OK\n" : "Fail\n"))); + + return sprintf(buf, (ret == 0 ? "OK\n" : "Fail\n")); +} + +/* sysfs: /sys/class/touch/cmcs/cm_jit */ +ssize_t ist30xx_cm_jit_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + tsp_verb("CMJIT (%d * %d)\n", tsp->ch_num.tx, tsp->ch_num.rx); + + return print_cmcs(data, ts_cmcs_buf->cm_jit, buf); +} + +/* sysfs: /sys/class/touch/cmcs/cm */ +ssize_t ist30xx_cm_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + tsp_verb("CM (%d * %d)\n", tsp->ch_num.tx, tsp->ch_num.rx); + + return print_cmcs(data, ts_cmcs_buf->cm, buf); +} + +/* sysfs: /sys/class/touch/cmcs/cm_spec_min */ +ssize_t ist30xx_cm_spec_min_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + tsp_verb("CM Spec Min (%d * %d)\n", tsp->ch_num.tx, tsp->ch_num.rx); + + return print_cmcs(data, ts_cmcs_buf->spec_min, buf); +} + +/* sysfs: /sys/class/touch/cmcs/cm_spec_max */ +ssize_t ist30xx_cm_spec_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + tsp_verb("CM Spec Max (%d * %d)\n", tsp->ch_num.tx, tsp->ch_num.rx); + + return print_cmcs(data, ts_cmcs_buf->spec_max, buf); +} + +/* sysfs: /sys/class/touch/cmcs/cm_slope0 */ +ssize_t ist30xx_cm_slope0_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + tsp_verb("CM Slope0_X (%d * %d)\n", tsp->ch_num.tx, tsp->ch_num.rx); + + return print_cmcs(data, ts_cmcs_buf->slope0, buf); +} + +/* sysfs: /sys/class/touch/cmcs/cm_slope1 */ +ssize_t ist30xx_cm_slope1_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + tsp_verb("CM Slope1_Y (%d * %d)\n", tsp->ch_num.tx, tsp->ch_num.rx); + + return print_cmcs(data, ts_cmcs_buf->slope1, buf); +} + +/* sysfs: /sys/class/touch/cmcs/cm2 */ +ssize_t ist30xx_cm2_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + tsp_verb("CM2 (%d * %d)\n", tsp->ch_num.tx, tsp->ch_num.rx); + + return print_cmcs(data, ts_cmcs_buf->cm2, buf); +} + +/* sysfs: /sys/class/touch/cmcs/cs */ +ssize_t ist30xx_cs_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + tsp_verb("CS (%d * %d)\n", tsp->ch_num.tx, tsp->ch_num.rx); + + return print_cmcs(data, ts_cmcs_buf->cs, buf); +} + +/* sysfs: /sys/class/touch/cmcs/cs_tx */ +ssize_t ist30xx_cs_tx_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int i; + int count = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + char msg[8]; + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + for (i = 0; i < tsp->ch_num.tx; i++) { + count += sprintf(msg, "%5d ", (ts_cmcs_buf->cs_tx_result >> i) & 1); + strcat(buf, msg); + } + + count += sprintf(msg, "\n"); + strcat(buf, msg); + + return count; +} + +/* sysfs: /sys/class/touch/cmcs/cs_rx */ +ssize_t ist30xx_cs_rx_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int i; + int count = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + char msg[8]; + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + for (i = 0; i < tsp->ch_num.rx; i++) { + count += sprintf(msg, "%5d ", (ts_cmcs_buf->cs_rx_result >> i) & 1); + strcat(buf, msg); + } + + count += sprintf(msg, "\n"); + strcat(buf, msg); + + return count; +} + +int print_cm_slope_result(struct ist30xx_data *data, u8 flag, s16 *buf16, + char *buf, bool fail_list) +{ + int i, j; + int type, idx; + int count = 0, err_cnt = 0; + int min_spec, max_spec, gtx_min_spec, gtx_max_spec; + + char msg[128]; + + TSP_INFO *tsp = &data->tsp_info; + struct CMCS_SPEC_SLOPE *spec = + (struct CMCS_SPEC_SLOPE *)&ts_cmcs->spec_slope; + + if (flag == CMCS_FLAG_CM_SLOPE0) { + min_spec = spec->x_min; + max_spec = spec->x_max; + gtx_min_spec = spec->gtx_x_min; + gtx_max_spec = spec->gtx_x_max; + } else if (flag == CMCS_FLAG_CM_SLOPE1) { + min_spec = spec->y_min; + max_spec = spec->y_max; + gtx_min_spec = spec->gtx_y_min; + gtx_max_spec = spec->gtx_y_max; + } else { + count = sprintf(msg, "Unknown flag: %d\n", flag); + strcat(buf, msg); + return count; + } + + if (fail_list) { + count = sprintf(msg, "Spec: screen(%d~%d), GTx(%d~%d)\n", + min_spec, max_spec, gtx_min_spec, gtx_max_spec); + strcat(buf, msg); + } + + for (i = 0; i < tsp->ch_num.tx; i++) { + for (j = 0; j < tsp->ch_num.rx; j++) { + idx = (i * tsp->ch_num.rx) + j; + + type = check_tsp_type(data, i, j); + if ((type == TSP_CH_UNKNOWN) || (type == TSP_CH_UNUSED) || + (type == TSP_CH_KEY)) + continue; + + if (type == TSP_CH_SCREEN) { + if ((buf16[idx] >= min_spec) && (buf16[idx] <= max_spec)) + continue; + } else if (type == TSP_CH_GTX) { + if ((buf16[idx] >= gtx_min_spec) && + (buf16[idx] <= gtx_max_spec)) + continue; + } + + if (fail_list) { + count += sprintf(msg, "%2d,%2d:%4d\n", i, j, buf16[idx]); + strcat(buf, msg); + } + + err_cnt++; + } + } + + /* Check error count */ + if (err_cnt == 0) + count += sprintf(msg, "OK\n"); + else + count += sprintf(msg, "Fail, node count: %d\n", err_cnt); + strcat(buf, msg); + + return count; +} + +int print_cm_key_slope_result(struct ist30xx_data *data, s16 *buf16, char *buf, + bool print) +{ + int i, j; + int type, idx; + int count = 0; + int min_spec, max_spec; + int key_num = 0; + s16 key_cm[5] = { 0, }; + s16 slope_result; + + char msg[128]; + + TSP_INFO *tsp = &data->tsp_info; + struct CMCS_SPEC_SLOPE *spec = + (struct CMCS_SPEC_SLOPE *)&ts_cmcs->spec_slope; + + min_spec = spec->key_min; + max_spec = spec->key_max; + + if (print) { + count = sprintf(msg, "Spec: %d ~ %d\n", min_spec, max_spec); + strcat(buf, msg); + } + + for (i = 0; i < tsp->ch_num.tx; i++) { + for (j = 0; j < tsp->ch_num.rx; j++) { + idx = (i * tsp->ch_num.rx) + j; + + type = check_tsp_type(data, i, j); + if (type == TSP_CH_KEY) + key_cm[key_num++] = buf16[idx]; + } + } + + /* Check key slope */ + slope_result = key_cm[0] - key_cm[1]; + + if (print) { + if ((slope_result >= min_spec) && (slope_result <= max_spec)) + count += sprintf(msg, "OK (%d)\n", slope_result); + else + count += sprintf(msg, "Fail (%d)\n", slope_result); + } else { + count += sprintf(msg, "%d\n", + (slope_result >= 0 ? slope_result : -slope_result)); + } + + strcat(buf, msg); + + return count; +} + +int print_cm_result(struct ist30xx_data *data, char *buf, bool fail_list) +{ + int i, j; + int type, idx, err_cnt = 0; + int min_spec, max_spec; + int count = 0; + short cm; + char msg[128]; + TSP_INFO *tsp = &data->tsp_info; + + for (i = 0; i < tsp->ch_num.tx; i++) { + for (j = 0; j < tsp->ch_num.rx; j++) { + idx = (i * tsp->ch_num.rx) + j; + + type = check_tsp_type(data, i, j); + if ((type == TSP_CH_UNKNOWN) || (type == TSP_CH_UNUSED)) + continue; + + min_spec = ts_cmcs_buf->spec_min[idx]; + max_spec = ts_cmcs_buf->spec_max[idx]; + + cm = ts_cmcs_buf->cm[idx]; + if ((cm >= min_spec) && (cm <= max_spec)) + continue; + + if (fail_list) { + count += sprintf(msg, "%2d,%2d:%4d (%4d~%4d)\n", + i, j, cm, min_spec, max_spec); + strcat(buf, msg); + } + + err_cnt++; + } + } + + /* Check error count */ + if (err_cnt == 0) + count += sprintf(msg, "OK\n"); + else + count += sprintf(msg, "Fail, node count: %d\n", err_cnt); + strcat(buf, msg); + + return count; +} + +int print_total_result(struct ist30xx_data *data, s16 *buf16, char *buf, + const char *mode, bool fail_list) +{ + int i, j; + bool success = false; + int type, idx; + int count = 0, err_cnt = 0; + int min_spec, max_spec; + char msg[128]; + + TSP_INFO *tsp = &data->tsp_info; + struct CMCS_SPEC_TOTAL *spec; + + for (i = 0; i < ts_cmcs->items.cnt; i++) { + if (!strcmp(ts_cmcs->items.item[i].name, mode)) { + if (!strcmp(ts_cmcs->items.item[i].spec_type, "T")) { + spec = + (struct CMCS_SPEC_TOTAL *)&ts_cmcs->spec_item[i].spec_total; + success = true; + break; + } + } + } + + if (success == false) + return 0; + + if (fail_list) { + count = sprintf(msg, "Spec: screen(%d~%d), gtx(%d~%d), key(%d~%d)\n", + spec->screen_min, spec->screen_max, spec->gtx_min, + spec->gtx_max, spec->key_min, spec->key_max); + strcat(buf, msg); + } + + for (i = 0; i < tsp->ch_num.tx; i++) { + for (j = 0; j < tsp->ch_num.rx; j++) { + idx = (i * tsp->ch_num.rx) + j; + + type = check_tsp_type(data, i, j); + if ((type == TSP_CH_UNKNOWN) || (type == TSP_CH_UNUSED)) + continue; + + if (type == TSP_CH_SCREEN) { + min_spec = spec->screen_min; + max_spec = spec->screen_max; + } else if (type == TSP_CH_GTX) { + min_spec = spec->gtx_min; + max_spec = spec->gtx_max; + } else { + min_spec = spec->key_min; + max_spec = spec->key_max; + } + + if ((buf16[idx] >= min_spec) && (buf16[idx] <= max_spec)) + continue; + + if (fail_list) { + count += sprintf(msg, "%2d,%2d:%4d\n", i, j, buf16[idx]); + strcat(buf, msg); + } + + err_cnt++; + } + } + + /* Check error count */ + if (err_cnt == 0) + count += sprintf(msg, "OK\n"); + else + count += sprintf(msg, "Fail, node count: %d\n", err_cnt); + strcat(buf, msg); + + return count; +} + +/* sysfs: /sys/class/touch/cmcs/cm_jit_result */ +ssize_t ist30xx_cm_jit_result_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + return print_total_result(data, ts_cmcs_buf->cm_jit, buf, CMCS_CMJIT, true); +} + +/* sysfs: /sys/class/touch/cmcs/cm_result */ +ssize_t ist30xx_cm_result_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + return print_cm_result(data, buf, true); +} + +/* sysfs: /sys/class/touch/cmcs/cm_slope0_result */ +ssize_t ist30xx_cm_slope0_result_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + return print_cm_slope_result(data, CMCS_FLAG_CM_SLOPE0, + ts_cmcs_buf->slope0, buf, true); +} + +/* sysfs: /sys/class/touch/cmcs/cm_slope1_result */ +ssize_t ist30xx_cm_slope1_result_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + return print_cm_slope_result(data, CMCS_FLAG_CM_SLOPE1, + ts_cmcs_buf->slope1, buf, true); +} + +/* sysfs: /sys/class/touch/cmcs/cm_key_slope_result */ +ssize_t ist30xx_cm_key_slope_result_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + return print_cm_key_slope_result(data, ts_cmcs_buf->cm, buf, true); +} + +/* sysfs: /sys/class/touch/cmcs/cs_result */ +ssize_t ist30xx_cs_result_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + return print_total_result(data, ts_cmcs_buf->cs, buf, CMCS_CS, true); +} + +/* sysfs: /sys/class/touch/cmcs/line_cm_jit */ +ssize_t ist30xx_line_cm_jit_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + return print_line_cmcs(data, CMCS_FLAG_CMJIT, ts_cmcs_buf->cm_jit, buf); +} + +/* sysfs: /sys/class/touch/cmcs/line_cm */ +ssize_t ist30xx_line_cm_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + return print_line_cmcs(data, CMCS_FLAG_CM, ts_cmcs_buf->cm, buf); +} + +/* sysfs: /sys/class/touch/cmcs/line_cm_slope0 */ +ssize_t ist30xx_line_cm_slope0_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + return print_line_cmcs(data, CMCS_FLAG_CM_SLOPE0, ts_cmcs_buf->slope0, buf); +} + +/* sysfs: /sys/class/touch/cmcs/line_cm_slope1 */ +ssize_t ist30xx_line_cm_slope1_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + return print_line_cmcs(data, CMCS_FLAG_CM_SLOPE1, ts_cmcs_buf->slope1, buf); +} + +/* sysfs: /sys/class/touch/cmcs/line_cm2 */ +ssize_t ist30xx_line_cm2_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + return print_line_cmcs(data, CMCS_FLAG_CM2, ts_cmcs_buf->cm2, buf); +} + +/* sysfs: /sys/class/touch/cmcs/line_cs */ +ssize_t ist30xx_line_cs_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (cmcs_ready == CMCS_NOT_READY) + return sprintf(buf, "CMCS test is not work!!\n"); + + return print_line_cmcs(data, CMCS_FLAG_CS, ts_cmcs_buf->cs, buf); +} + +/* sysfs: /sys/class/touch/cmcs/cm_key_slope_value */ +ssize_t ist30xx_cm_key_slope_value_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + struct ist30xx_data *data = dev_get_drvdata(dev); + + if ((ts_cmcs_bin == NULL) || (ts_cmcs_bin_size == 0)) + goto err_key_slope; + + ret = ist30xx_get_cmcs_info(ts_cmcs_bin, ts_cmcs_bin_size); + if (ret) + goto err_key_slope; + + mutex_lock(&data->lock); + ret = ist30xx_cmcs_test(data, ts_cmcs_bin, ts_cmcs_bin_size); + mutex_unlock(&data->lock); + + if (ret) + goto err_key_slope; + + if (cmcs_ready == CMCS_NOT_READY) + goto err_key_slope; + + return print_cm_key_slope_result(data, ts_cmcs_buf->cm, buf, false); + +err_key_slope: + return sprintf(buf, "%s", "FFFF"); +} + +int cmcs_test_result(struct ist30xx_data *data) +{ + int ret; + int result = 0; + char *msg = NULL; + + msg = kzalloc(sizeof(char) * 4096, GFP_KERNEL); + if (!msg) { + tsp_err("Memory allocation failed\n"); + return 0; + } + + /* CMCS binary */ + if ((ts_cmcs_bin == NULL) || (ts_cmcs_bin_size == 0)) { + tsp_err("Binary is not correct(%d)\n", ts_cmcs_bin_size); + goto out; + } + + ret = ist30xx_get_cmcs_info(ts_cmcs_bin, ts_cmcs_bin_size); + if (ret) { + kfree(msg); + tsp_err("Getting CMCS Binary info failed!\n"); + goto out; + } + + mutex_lock(&data->lock); + ret = ist30xx_cmcs_test(data, ts_cmcs_bin, ts_cmcs_bin_size); + mutex_unlock(&data->lock); + + if (ret) { + kfree(msg); + tsp_err("CMCS Binary test failed!\n"); + goto out; + } + + /* CM result */ + memset(msg, 0, 4096); + print_cm_result(data, msg, false); + if (strncmp(msg, "OK\n", strlen("OK\n")) == 0) { + tsp_info("CM result: pass\n"); + } else { + result = -1; + tsp_err("CM result: fail\n"); + } + + /* CM slope0 result */ + memset(msg, 0, 4096); + print_cm_slope_result(data, CMCS_FLAG_CM_SLOPE0, ts_cmcs_buf->slope0, msg, + false); + if (strncmp(msg, "OK\n", strlen("OK\n")) == 0) { + tsp_info("Slope0 result: pass\n"); + } else { + result = -1; + tsp_err("Slope0 result: fail\n"); + } + + /* CM slope0 result */ + memset(msg, 0, 4096); + print_cm_slope_result(data, CMCS_FLAG_CM_SLOPE1, ts_cmcs_buf->slope1, msg, + false); + if (strncmp(msg, "OK\n", strlen("OK\n")) == 0) { + tsp_info("Slope1 result: pass\n"); + } else { + result = -1; + tsp_err("Slope1 result: fail\n"); + } + + /* CS Result */ + memset(msg, 0, 4096); + print_total_result(data, ts_cmcs_buf->cs, msg, CMCS_CS, false); + if (strncmp(msg, "OK\n", strlen("OK\n")) == 0) { + tsp_info("CS result: pass\n"); + } else { + result = -1; + tsp_debug("CS result: fail\n"); + } + + if (result) + goto out; + + kfree(msg); + return 1; + +out: + kfree(msg); + return 0; +} + +/* sysfs: /sys/class/touch/cmcs/cmcs_test_all */ +ssize_t ist30xx_cmcs_test_all_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int result = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + + result = cmcs_test_result(data); + + return sprintf(buf, "%d\n", result); +} + +/* sysfs : cmcs */ +static DEVICE_ATTR(info, S_IRUGO, ist30xx_cmcs_info_show, NULL); +static DEVICE_ATTR(cmcs_binary, S_IRUGO, ist30xx_cmcs_binary_show, NULL); +static DEVICE_ATTR(cmcs_custom, S_IRUGO, ist30xx_cmcs_custom_show, NULL); +static DEVICE_ATTR(cmcs_sdcard, S_IRUGO, ist30xx_cmcs_sdcard_show, NULL); +static DEVICE_ATTR(cm_jit, S_IRUGO, ist30xx_cm_jit_show, NULL); +static DEVICE_ATTR(cm, S_IRUGO, ist30xx_cm_show, NULL); +static DEVICE_ATTR(cm_spec_min, S_IRUGO, ist30xx_cm_spec_min_show, NULL); +static DEVICE_ATTR(cm_spec_max, S_IRUGO, ist30xx_cm_spec_max_show, NULL); +static DEVICE_ATTR(cm_slope0, S_IRUGO, ist30xx_cm_slope0_show, NULL); +static DEVICE_ATTR(cm_slope1, S_IRUGO, ist30xx_cm_slope1_show, NULL); +static DEVICE_ATTR(cm2, S_IRUGO, ist30xx_cm2_show, NULL); +static DEVICE_ATTR(cs, S_IRUGO, ist30xx_cs_show, NULL); +static DEVICE_ATTR(cs_tx, S_IRUGO, ist30xx_cs_tx_show, NULL); +static DEVICE_ATTR(cs_rx, S_IRUGO, ist30xx_cs_rx_show, NULL); +static DEVICE_ATTR(cm_jit_result, S_IRUGO, ist30xx_cm_jit_result_show, NULL); +static DEVICE_ATTR(cm_result, S_IRUGO, ist30xx_cm_result_show, NULL); +static DEVICE_ATTR(cm_slope0_result, S_IRUGO, ist30xx_cm_slope0_result_show, + NULL); +static DEVICE_ATTR(cm_slope1_result, S_IRUGO, ist30xx_cm_slope1_result_show, + NULL); +static DEVICE_ATTR(cm_key_slope_result, S_IRUGO, + ist30xx_cm_key_slope_result_show, NULL); +static DEVICE_ATTR(cs_result, S_IRUGO, ist30xx_cs_result_show, NULL); +static DEVICE_ATTR(line_cm_jit, S_IRUGO, ist30xx_line_cm_jit_show, NULL); +static DEVICE_ATTR(line_cm, S_IRUGO, ist30xx_line_cm_show, NULL); +static DEVICE_ATTR(line_cm_slope0, S_IRUGO, ist30xx_line_cm_slope0_show, NULL); +static DEVICE_ATTR(line_cm_slope1, S_IRUGO, ist30xx_line_cm_slope1_show, NULL); +static DEVICE_ATTR(line_cm2, S_IRUGO, ist30xx_line_cm2_show, NULL); +static DEVICE_ATTR(line_cs, S_IRUGO, ist30xx_line_cs_show, NULL); +static DEVICE_ATTR(cm_key_slope_value, S_IRUGO, ist30xx_cm_key_slope_value_show, + NULL); +static DEVICE_ATTR(cmcs_test_all, S_IRUGO, ist30xx_cmcs_test_all_show, NULL); + +static struct attribute *cmcs_attributes[] = { + &dev_attr_info.attr, + &dev_attr_cmcs_binary.attr, + &dev_attr_cmcs_custom.attr, + &dev_attr_cmcs_sdcard.attr, + &dev_attr_cm_jit.attr, + &dev_attr_cm.attr, + &dev_attr_cm_spec_min.attr, + &dev_attr_cm_spec_max.attr, + &dev_attr_cm_slope0.attr, + &dev_attr_cm_slope1.attr, + &dev_attr_cm2.attr, + &dev_attr_cs.attr, + &dev_attr_cs_tx.attr, + &dev_attr_cs_rx.attr, + &dev_attr_cm_jit_result.attr, + &dev_attr_cm_result.attr, + &dev_attr_cm_slope0_result.attr, + &dev_attr_cm_slope1_result.attr, + &dev_attr_cm_key_slope_result.attr, + &dev_attr_cs_result.attr, + &dev_attr_line_cm_jit.attr, + &dev_attr_line_cm.attr, + &dev_attr_line_cm_slope0.attr, + &dev_attr_line_cm_slope1.attr, + &dev_attr_line_cm2.attr, + &dev_attr_line_cs.attr, + &dev_attr_cm_key_slope_value.attr, + &dev_attr_cmcs_test_all.attr, + NULL, +}; + +static struct attribute_group cmcs_attr_group = { + .attrs = cmcs_attributes, +}; + +extern struct class *ist30xx_class; +struct device *ist30xx_cmcs_dev; + +int ist30xx_init_cmcs_sysfs(struct ist30xx_data *data) +{ + int ret = 0; + + /* /sys/class/touch/cmcs */ + ist30xx_cmcs_dev = device_create(ist30xx_class, NULL, 0, data, "cmcs"); + + /* /sys/class/touch/cmcs/... */ + if (unlikely(sysfs_create_group(&ist30xx_cmcs_dev->kobj, + &cmcs_attr_group))) + tsp_err("Failed to create sysfs group(%s)!\n", "cmcs"); + +#ifdef INTERNAL_CMCS_BIN + ts_cmcs_bin = (u8 *)ist30xx_cmcs; + ts_cmcs_bin_size = sizeof(ist30xx_cmcs); + + ret = ist30xx_get_cmcs_info(ts_cmcs_bin, ts_cmcs_bin_size); +#endif + + return ret; +} +#endif diff --git a/drivers/input/touchscreen/ist3038c/ist30xxc_cmcs.h b/drivers/input/touchscreen/ist3038c/ist30xxc_cmcs.h new file mode 100644 index 0000000000000..13f7254cd89ef --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/ist30xxc_cmcs.h @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2010, Imagis Technology Co. Ltd. All Rights Reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __IST30XXC_CMCS_H__ +#define __IST30XXC_CMCS_H__ + +#define INTERNAL_CMCS_BIN + +#define CMCS_MSG_MASK (0xFFFFFFF0) +#define CM_MSG_VALID (0x0E7DC770) +#define CM2_MSG_VALID (0x0E7DC770) +#define CS_MSG_VALID (0x0E7DC500) +#define CMJIT_MSG_VALID (0x0E7D2170) +#define INT_MSG_VALID (0x14709970) + +#define IST30XX_CMCS_NAME "ist30xxc.cms" +#define IST30XX_CMCS_MAGIC "CMCS2TAG" + +struct CMCS_SPEC_NODE { + u32 node_cnt; + u16 *buf_min; + u16 *buf_max; +}; + +struct CMCS_SPEC_TOTAL { + s16 screen_min; + s16 screen_max; + s16 gtx_min; + s16 gtx_max; + s16 key_min; + s16 key_max; +}; + +struct CMCS_ITEM_INFO { + char name[8]; + u32 addr; + u32 size; + char data_type[2]; + char spec_type[2]; +}; + +typedef struct _CMCS_ITEM { + u32 cnt; + struct CMCS_ITEM_INFO *item; +} CMCS_ITEM; + +struct CMCS_CMD_INFO { + u32 addr; + u32 value; +}; + +typedef struct _CMCS_CMD { + u32 cnt; + struct CMCS_CMD_INFO *cmd; +} CMCS_CMD; + +union CMCS_SPEC_ITEM { + struct CMCS_SPEC_NODE spec_node; + struct CMCS_SPEC_TOTAL spec_total; +}; + +struct CMCS_SPEC_SLOPE { + char name[8]; + s16 x_min; + s16 x_max; + s16 gtx_x_min; + s16 gtx_x_max; + s16 y_min; + s16 y_max; + s16 gtx_y_min; + s16 gtx_y_max; + s16 key_min; + s16 key_max; +}; + +struct CMCS_REG_INFO { + char name[8]; + u32 addr; + u32 size; +}; + +typedef struct _CMCS_PARAM { + u32 cmcs_size_addr; + u32 cmcs_size; + u32 enable_addr; + u32 checksum_addr; + u32 end_notify_addr; + u32 sensor1_addr; + u32 sensor2_addr; + u32 sensor3_addr; + u32 cm_sensor1_size; + u32 cm_sensor2_size; + u32 cm_sensor3_size; + u32 cs_sensor1_size; + u32 cs_sensor2_size; + u32 cs_sensor3_size; + u32 jit_sensor1_size; + u32 jit_sensor2_size; + u32 jit_sensor3_size; + u32 cmcs_chksum; + u32 cm_sensor_chksum; + u32 cs_sensor_chksum; + u32 jit_sensor_chksum; + u32 cs_tx_result_addr; + u32 cs_rx_result_addr; +} CMCS_PARAM; + +typedef struct _CMCS_BIN_INFO { + char magic1[8]; + CMCS_ITEM items; + CMCS_CMD cmds; + struct CMCS_SPEC_SLOPE spec_slope; + struct CMCS_SPEC_TOTAL spec_cr; + CMCS_PARAM param; + union CMCS_SPEC_ITEM *spec_item; + u8 *buf_cmcs; + u32 *buf_cm_sensor; + u32 *buf_cs_sensor; + u32 *buf_jit_sensor; + u32 version; + char magic2[8]; +} CMCS_BIN_INFO; + +typedef struct _CMCS_BUF { + s16 cm[IST30XX_MAX_NODE_NUM]; + s16 cm2[IST30XX_MAX_NODE_NUM]; + s16 cm_jit[IST30XX_MAX_NODE_NUM]; + s16 spec_min[IST30XX_MAX_NODE_NUM]; + s16 spec_max[IST30XX_MAX_NODE_NUM]; + s16 slope0[IST30XX_MAX_NODE_NUM]; + s16 slope1[IST30XX_MAX_NODE_NUM]; + s16 cs[IST30XX_MAX_NODE_NUM]; + u32 cs_tx_result; + u32 cs_rx_result; +} CMCS_BUF; + +int check_tsp_type(struct ist30xx_data *data, int tx, int rx); +int ist30xx_get_cmcs_info(const u8 *buf, const u32 size); +int ist30xx_cmcs_test(struct ist30xx_data *data, const u8 *buf, int size); +int ist30xx_init_cmcs_sysfs(struct ist30xx_data *data); +#endif diff --git a/drivers/input/touchscreen/ist3038c/ist30xxc_cmcs_bin.h b/drivers/input/touchscreen/ist3038c/ist30xxc_cmcs_bin.h new file mode 100644 index 0000000000000..f3848b1787afd --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/ist30xxc_cmcs_bin.h @@ -0,0 +1,756 @@ +#ifndef __IST30XXC_CMCS_BIN_H__ +#define __IST30XXC_CMCS_BIN_H__ + +/* ################################# */ +/* ### CmCs Version : 05020000 ### */ +/* ### Cheksum : 1D436CA3 ### */ +/* ################################# */ + +/* ist30xx cmcs binary: model( ) */ +static unsigned char ist30xx_cmcs[] = { + 0x43, 0x4D, 0x43, 0x53, 0x32, 0x54, 0x41, 0x47, 0x02, 0x00, 0x00, 0x00, 0x43, 0x4D, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x4E, 0x00, 0x4E, 0x00, + 0x43, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, + 0x4E, 0x00, 0x54, 0x00, 0x08, 0x00, 0x00, 0x00, 0xC4, 0x19, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xC8, 0x19, 0x00, 0x00, 0x18, 0x0E, 0x17, 0x0E, 0xCC, 0x19, 0x00, 0x00, 0x17, 0x02, 0x17, 0x06, + 0xD0, 0x19, 0x00, 0x00, 0x17, 0x0B, 0xFF, 0xFF, 0xD4, 0x19, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xD8, 0x19, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xDC, 0x19, 0x00, 0x00, 0xAC, 0x0D, 0xAC, 0x0D, + 0xE0, 0x19, 0x00, 0x00, 0x80, 0x0C, 0xD8, 0x0E, 0x43, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6A, 0xFF, 0x96, 0x00, 0x6A, 0xFF, 0x96, 0x00, 0x6A, 0xFF, 0x96, 0x00, 0x6A, 0xFF, 0x96, 0x00, + 0x6A, 0xFF, 0x96, 0x00, 0x01, 0x00, 0xFF, 0x0F, 0xEC, 0x04, 0x24, 0x09, 0x01, 0x00, 0xFF, 0x0F, + 0xC0, 0x19, 0x00, 0x00, 0xA4, 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x30, 0x08, 0x01, 0x00, 0x30, + 0x04, 0x01, 0x00, 0x30, 0x08, 0x70, 0x00, 0x40, 0x00, 0x40, 0x00, 0x30, 0xC4, 0x52, 0x00, 0x30, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xA3, 0x6C, 0x43, 0x1D, 0xFC, 0x86, 0xBB, 0xB0, 0x08, 0xFD, 0x99, 0x72, + 0x00, 0x00, 0x00, 0x00, 0xF8, 0x22, 0x00, 0x00, 0xFC, 0x22, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, + 0x6A, 0x03, 0x4D, 0x03, 0x50, 0x03, 0x54, 0x03, 0x3A, 0x03, 0x35, 0x03, 0x28, 0x03, 0x18, 0x03, + 0xFE, 0x02, 0xFD, 0x02, 0xE5, 0x02, 0x26, 0x02, 0x14, 0x02, 0x12, 0x02, 0x07, 0x02, 0xF5, 0x01, + 0xF4, 0x01, 0xE6, 0x01, 0xDD, 0x01, 0xD6, 0x01, 0xD1, 0x01, 0xBA, 0x01, 0xC2, 0x01, 0x2F, 0x03, + 0x19, 0x03, 0x1A, 0x03, 0x1B, 0x03, 0x00, 0x03, 0xFB, 0x02, 0xEC, 0x02, 0xDD, 0x02, 0xC3, 0x02, + 0xC1, 0x02, 0xA6, 0x02, 0x33, 0x02, 0x21, 0x02, 0x21, 0x02, 0x16, 0x02, 0x06, 0x02, 0x04, 0x02, + 0xF7, 0x01, 0xEE, 0x01, 0xE7, 0x01, 0xE2, 0x01, 0xCB, 0x01, 0xD5, 0x01, 0x1C, 0x03, 0x04, 0x03, + 0xFF, 0x02, 0xFF, 0x02, 0xE2, 0x02, 0xDA, 0x02, 0xCA, 0x02, 0xBA, 0x02, 0x9E, 0x02, 0x9C, 0x02, + 0x87, 0x02, 0x2C, 0x02, 0x1A, 0x02, 0x19, 0x02, 0x0C, 0x02, 0xFE, 0x01, 0xFB, 0x01, 0xEB, 0x01, + 0xE4, 0x01, 0xDB, 0x01, 0xD5, 0x01, 0xBE, 0x01, 0xC7, 0x01, 0x11, 0x03, 0xF7, 0x02, 0xF2, 0x02, + 0xF2, 0x02, 0xD7, 0x02, 0xCE, 0x02, 0xBD, 0x02, 0xAD, 0x02, 0x92, 0x02, 0x8F, 0x02, 0x72, 0x02, + 0x44, 0x02, 0x33, 0x02, 0x34, 0x02, 0x28, 0x02, 0x1B, 0x02, 0x19, 0x02, 0x0A, 0x02, 0x04, 0x02, + 0xFC, 0x01, 0xF7, 0x01, 0xE1, 0x01, 0xEB, 0x01, 0x02, 0x03, 0xE7, 0x02, 0xE1, 0x02, 0xDF, 0x02, + 0xC3, 0x02, 0xB9, 0x02, 0xA9, 0x02, 0x97, 0x02, 0x7C, 0x02, 0x79, 0x02, 0x5A, 0x02, 0x4F, 0x02, + 0x3F, 0x02, 0x41, 0x02, 0x34, 0x02, 0x26, 0x02, 0x27, 0x02, 0x17, 0x02, 0x10, 0x02, 0x0B, 0x02, + 0x04, 0x02, 0xEE, 0x01, 0xFA, 0x01, 0xF8, 0x02, 0xDA, 0x02, 0xD4, 0x02, 0xD1, 0x02, 0xB4, 0x02, + 0xA8, 0x02, 0x96, 0x02, 0x84, 0x02, 0x69, 0x02, 0x65, 0x02, 0x46, 0x02, 0x5E, 0x02, 0x4D, 0x02, + 0x4F, 0x02, 0x43, 0x02, 0x35, 0x02, 0x36, 0x02, 0x25, 0x02, 0x1F, 0x02, 0x1A, 0x02, 0x13, 0x02, + 0xFC, 0x01, 0x0A, 0x02, 0xE6, 0x02, 0xC9, 0x02, 0xC2, 0x02, 0xBC, 0x02, 0x9C, 0x02, 0x8F, 0x02, + 0x7B, 0x02, 0x67, 0x02, 0x4B, 0x02, 0x45, 0x02, 0x2C, 0x02, 0x5F, 0x02, 0x4D, 0x02, 0x4E, 0x02, + 0x41, 0x02, 0x32, 0x02, 0x32, 0x02, 0x22, 0x02, 0x19, 0x02, 0x12, 0x02, 0x0C, 0x02, 0xF5, 0x01, + 0x03, 0x02, 0xDC, 0x02, 0xC1, 0x02, 0xBA, 0x02, 0xB5, 0x02, 0x95, 0x02, 0x88, 0x02, 0x75, 0x02, + 0x61, 0x02, 0x45, 0x02, 0x3E, 0x02, 0x1F, 0x02, 0x82, 0x02, 0x72, 0x02, 0x75, 0x02, 0x69, 0x02, + 0x5B, 0x02, 0x5D, 0x02, 0x4D, 0x02, 0x46, 0x02, 0x3F, 0x02, 0x3A, 0x02, 0x24, 0x02, 0x35, 0x02, + 0xD1, 0x02, 0xB5, 0x02, 0xAD, 0x02, 0xA8, 0x02, 0x87, 0x02, 0x79, 0x02, 0x67, 0x02, 0x52, 0x02, + 0x34, 0x02, 0x2E, 0x02, 0x0E, 0x02, 0x95, 0x02, 0x85, 0x02, 0x8B, 0x02, 0x7D, 0x02, 0x6F, 0x02, + 0x73, 0x02, 0x61, 0x02, 0x5A, 0x02, 0x54, 0x02, 0x50, 0x02, 0x3A, 0x02, 0x4D, 0x02, 0xC8, 0x02, + 0xAC, 0x02, 0xA4, 0x02, 0x9D, 0x02, 0x7C, 0x02, 0x6D, 0x02, 0x59, 0x02, 0x45, 0x02, 0x28, 0x02, + 0x20, 0x02, 0x01, 0x02, 0xAD, 0x02, 0x9D, 0x02, 0xA2, 0x02, 0x94, 0x02, 0x87, 0x02, 0x8C, 0x02, + 0x7A, 0x02, 0x73, 0x02, 0x6D, 0x02, 0x69, 0x02, 0x54, 0x02, 0x68, 0x02, 0xC1, 0x02, 0xA4, 0x02, + 0x9B, 0x02, 0x93, 0x02, 0x71, 0x02, 0x62, 0x02, 0x4D, 0x02, 0x39, 0x02, 0x1D, 0x02, 0x13, 0x02, + 0xF3, 0x01, 0xC8, 0x02, 0xB6, 0x02, 0xBB, 0x02, 0xB0, 0x02, 0xA1, 0x02, 0xA6, 0x02, 0x95, 0x02, + 0x8E, 0x02, 0x89, 0x02, 0x86, 0x02, 0x6F, 0x02, 0x84, 0x02, 0xB5, 0x02, 0x98, 0x02, 0x8E, 0x02, + 0x83, 0x02, 0x62, 0x02, 0x51, 0x02, 0x3A, 0x02, 0x25, 0x02, 0x08, 0x02, 0xFF, 0x01, 0xE4, 0x01, + 0xD2, 0x02, 0xBE, 0x02, 0xC4, 0x02, 0xB7, 0x02, 0xA9, 0x02, 0xAD, 0x02, 0x9B, 0x02, 0x95, 0x02, + 0x8E, 0x02, 0x8B, 0x02, 0x73, 0x02, 0x89, 0x02, 0xB2, 0x02, 0x95, 0x02, 0x8C, 0x02, 0x82, 0x02, + 0x60, 0x02, 0x50, 0x02, 0x39, 0x02, 0x25, 0x02, 0x08, 0x02, 0xFF, 0x01, 0xDD, 0x01, 0x00, 0x03, + 0xEC, 0x02, 0xF3, 0x02, 0xE8, 0x02, 0xDB, 0x02, 0xE1, 0x02, 0xD0, 0x02, 0xCA, 0x02, 0xC5, 0x02, + 0xC2, 0x02, 0xAB, 0x02, 0xC4, 0x02, 0xAC, 0x02, 0x8F, 0x02, 0x84, 0x02, 0x78, 0x02, 0x54, 0x02, + 0x43, 0x02, 0x2B, 0x02, 0x16, 0x02, 0xF9, 0x01, 0xED, 0x01, 0xCB, 0x01, 0x5B, 0x03, 0x36, 0x03, + 0x3A, 0x03, 0x2E, 0x03, 0x20, 0x03, 0x26, 0x03, 0x11, 0x03, 0x0C, 0x03, 0x06, 0x03, 0x03, 0x03, + 0xEB, 0x02, 0x13, 0x03, 0x8C, 0x02, 0x9C, 0x02, 0x7F, 0x02, 0xB0, 0x05, 0x81, 0x05, 0x86, 0x05, + 0x8C, 0x05, 0x60, 0x05, 0x59, 0x05, 0x42, 0x05, 0x29, 0x05, 0xFD, 0x04, 0xFC, 0x04, 0xD4, 0x04, + 0x94, 0x03, 0x76, 0x03, 0x74, 0x03, 0x61, 0x03, 0x44, 0x03, 0x41, 0x03, 0x29, 0x03, 0x1B, 0x03, + 0x0F, 0x03, 0x06, 0x03, 0xE0, 0x02, 0xED, 0x02, 0x4F, 0x05, 0x2A, 0x05, 0x2B, 0x05, 0x2D, 0x05, + 0x00, 0x05, 0xF8, 0x04, 0xDF, 0x04, 0xC5, 0x04, 0x9A, 0x04, 0x98, 0x04, 0x6A, 0x04, 0xAA, 0x03, + 0x8D, 0x03, 0x8C, 0x03, 0x7A, 0x03, 0x5F, 0x03, 0x5D, 0x03, 0x46, 0x03, 0x38, 0x03, 0x2C, 0x03, + 0x23, 0x03, 0xFD, 0x02, 0x0D, 0x03, 0x2E, 0x05, 0x06, 0x05, 0xFE, 0x04, 0xFF, 0x04, 0xCE, 0x04, + 0xC0, 0x04, 0xA6, 0x04, 0x8B, 0x04, 0x5D, 0x04, 0x59, 0x04, 0x36, 0x04, 0x9F, 0x03, 0x80, 0x03, + 0x80, 0x03, 0x6A, 0x03, 0x52, 0x03, 0x4D, 0x03, 0x32, 0x03, 0x26, 0x03, 0x18, 0x03, 0x0D, 0x03, + 0xE7, 0x02, 0xF6, 0x02, 0x1C, 0x05, 0xF1, 0x04, 0xE8, 0x04, 0xE9, 0x04, 0xBB, 0x04, 0xAD, 0x04, + 0x91, 0x04, 0x76, 0x04, 0x49, 0x04, 0x43, 0x04, 0x14, 0x04, 0xC6, 0x03, 0xAB, 0x03, 0xAD, 0x03, + 0x98, 0x03, 0x82, 0x03, 0x80, 0x03, 0x65, 0x03, 0x5C, 0x03, 0x4F, 0x03, 0x46, 0x03, 0x21, 0x03, + 0x33, 0x03, 0x04, 0x05, 0xD7, 0x04, 0xCC, 0x04, 0xCA, 0x04, 0x9B, 0x04, 0x8A, 0x04, 0x6E, 0x04, + 0x50, 0x04, 0x24, 0x04, 0x1F, 0x04, 0xEB, 0x03, 0xDA, 0x03, 0xBE, 0x03, 0xC1, 0x03, 0xAC, 0x03, + 0x94, 0x03, 0x96, 0x03, 0x7B, 0x03, 0x71, 0x03, 0x67, 0x03, 0x5D, 0x03, 0x37, 0x03, 0x4B, 0x03, + 0xF2, 0x04, 0xC0, 0x04, 0xB7, 0x04, 0xB1, 0x04, 0x81, 0x04, 0x6E, 0x04, 0x4F, 0x04, 0x32, 0x04, + 0x04, 0x04, 0xFE, 0x03, 0xC9, 0x03, 0xF2, 0x03, 0xD5, 0x03, 0xD9, 0x03, 0xC4, 0x03, 0xAE, 0x03, + 0xAF, 0x03, 0x94, 0x03, 0x88, 0x03, 0x80, 0x03, 0x75, 0x03, 0x4F, 0x03, 0x66, 0x03, 0xD4, 0x04, + 0xA4, 0x04, 0x98, 0x04, 0x8F, 0x04, 0x59, 0x04, 0x44, 0x04, 0x22, 0x04, 0x02, 0x04, 0xD2, 0x03, + 0xC8, 0x03, 0x9E, 0x03, 0xF3, 0x03, 0xD6, 0x03, 0xD8, 0x03, 0xC2, 0x03, 0xA9, 0x03, 0xA9, 0x03, + 0x8E, 0x03, 0x80, 0x03, 0x74, 0x03, 0x69, 0x03, 0x44, 0x03, 0x5A, 0x03, 0xC5, 0x04, 0x96, 0x04, + 0x8B, 0x04, 0x83, 0x04, 0x4D, 0x04, 0x37, 0x04, 0x18, 0x04, 0xF7, 0x03, 0xC8, 0x03, 0xBD, 0x03, + 0x89, 0x03, 0x2F, 0x04, 0x13, 0x04, 0x18, 0x04, 0x04, 0x04, 0xEC, 0x03, 0xF0, 0x03, 0xD6, 0x03, + 0xC9, 0x03, 0xBF, 0x03, 0xB6, 0x03, 0x92, 0x03, 0xAE, 0x03, 0xB2, 0x04, 0x82, 0x04, 0x75, 0x04, + 0x6E, 0x04, 0x37, 0x04, 0x1F, 0x04, 0x00, 0x04, 0xDE, 0x03, 0xAC, 0x03, 0xA1, 0x03, 0x6D, 0x03, + 0x4E, 0x04, 0x33, 0x04, 0x3C, 0x04, 0x26, 0x04, 0x0F, 0x04, 0x15, 0x04, 0xF8, 0x03, 0xEB, 0x03, + 0xE2, 0x03, 0xDA, 0x03, 0xB7, 0x03, 0xD6, 0x03, 0xA3, 0x04, 0x74, 0x04, 0x66, 0x04, 0x5C, 0x04, + 0x24, 0x04, 0x0B, 0x04, 0xEA, 0x03, 0xC8, 0x03, 0x98, 0x03, 0x8A, 0x03, 0x57, 0x03, 0x76, 0x04, + 0x5A, 0x04, 0x63, 0x04, 0x4D, 0x04, 0x36, 0x04, 0x3E, 0x04, 0x20, 0x04, 0x15, 0x04, 0x0C, 0x04, + 0x05, 0x04, 0xE1, 0x03, 0x03, 0x04, 0x97, 0x04, 0x66, 0x04, 0x58, 0x04, 0x4A, 0x04, 0x12, 0x04, + 0xF9, 0x03, 0xD5, 0x03, 0xB5, 0x03, 0x85, 0x03, 0x76, 0x03, 0x40, 0x03, 0xA3, 0x04, 0x85, 0x04, + 0x8E, 0x04, 0x7A, 0x04, 0x62, 0x04, 0x6B, 0x04, 0x4D, 0x04, 0x43, 0x04, 0x39, 0x04, 0x34, 0x04, + 0x0F, 0x04, 0x31, 0x04, 0x83, 0x04, 0x52, 0x04, 0x42, 0x04, 0x30, 0x04, 0xF8, 0x03, 0xDC, 0x03, + 0xB6, 0x03, 0x94, 0x03, 0x63, 0x03, 0x53, 0x03, 0x27, 0x03, 0xB3, 0x04, 0x93, 0x04, 0x9C, 0x04, + 0x87, 0x04, 0x6F, 0x04, 0x76, 0x04, 0x58, 0x04, 0x4D, 0x04, 0x43, 0x04, 0x3D, 0x04, 0x15, 0x04, + 0x39, 0x04, 0x7F, 0x04, 0x4E, 0x04, 0x3F, 0x04, 0x2E, 0x04, 0xF6, 0x03, 0xDB, 0x03, 0xB5, 0x03, + 0x94, 0x03, 0x63, 0x03, 0x53, 0x03, 0x1B, 0x03, 0x00, 0x05, 0xDF, 0x04, 0xEB, 0x04, 0xD8, 0x04, + 0xC2, 0x04, 0xCD, 0x04, 0xAF, 0x04, 0xA6, 0x04, 0x9E, 0x04, 0x98, 0x04, 0x72, 0x04, 0x9B, 0x04, + 0x74, 0x04, 0x43, 0x04, 0x32, 0x04, 0x1E, 0x04, 0xE2, 0x03, 0xC5, 0x03, 0x9C, 0x03, 0x79, 0x03, + 0x49, 0x03, 0x35, 0x03, 0xFD, 0x02, 0x97, 0x05, 0x59, 0x05, 0x61, 0x05, 0x4D, 0x05, 0x35, 0x05, + 0x3F, 0x05, 0x1C, 0x05, 0x14, 0x05, 0x0B, 0x05, 0x05, 0x05, 0xDD, 0x04, 0x1F, 0x05, 0x3F, 0x04, + 0x5A, 0x04, 0x29, 0x04, 0x80, 0x0C, 0xD8, 0x0E, 0x80, 0x0C, 0xD8, 0x0E, 0x80, 0x0C, 0xD8, 0x0E, + 0x04, 0x00, 0x00, 0x00, 0x0C, 0x10, 0xBC, 0x19, 0x0C, 0x80, 0x9C, 0x0D, 0x0B, 0x17, 0x00, 0x00, + 0xF2, 0xFE, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0x38, 0x67, 0x08, 0x70, 0xB9, 0x67, 0x08, 0x70, + 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x08, 0x70, 0xD6, 0x72, 0x82, 0xFD, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xE2, 0x08, 0xD0, 0x00, 0x40, + 0x04, 0xC1, 0xC4, 0xE0, 0x82, 0x0A, 0xAB, 0x00, 0x00, 0x00, 0x04, 0x21, 0xB9, 0xCD, 0x00, 0x70, + 0x2B, 0x01, 0x00, 0x00, 0x34, 0xE1, 0xF2, 0xF6, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, + 0x04, 0x70, 0xC6, 0x27, 0x82, 0x05, 0x08, 0x70, 0x0F, 0xC0, 0x2C, 0x70, 0xFF, 0xFF, 0x08, 0x60, + 0x00, 0x40, 0xB9, 0x76, 0x3C, 0x71, 0xE1, 0xF0, 0x77, 0x41, 0x14, 0x71, 0x34, 0x41, 0xC6, 0x47, + 0x82, 0x04, 0xB1, 0x32, 0x24, 0x24, 0xF2, 0xFB, 0xE1, 0xF0, 0x00, 0x00, 0xF7, 0x40, 0x04, 0x70, + 0xC6, 0x74, 0x82, 0x07, 0x2F, 0x67, 0x07, 0x00, 0x26, 0x62, 0xA1, 0x36, 0x24, 0x71, 0xF2, 0xF9, + 0xE1, 0xF0, 0x00, 0x00, 0x04, 0x70, 0xC6, 0x74, 0x82, 0x06, 0x2F, 0x67, 0x02, 0x00, 0x91, 0x36, + 0x24, 0x71, 0xF2, 0xFA, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0x77, 0x41, 0x04, 0x70, + 0x14, 0x61, 0x34, 0x41, 0xC6, 0x46, 0x82, 0x09, 0x2F, 0x57, 0x03, 0x00, 0x30, 0xF5, 0x2F, 0x57, + 0x02, 0x00, 0xB1, 0xF5, 0x24, 0x74, 0xF2, 0xF6, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, + 0x04, 0x70, 0xC6, 0x74, 0x82, 0x09, 0x2F, 0x67, 0x03, 0x00, 0x10, 0x56, 0x2F, 0x67, 0x02, 0x00, + 0x91, 0x56, 0x24, 0x71, 0xF2, 0xF7, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x30, 0x38, 0x76, 0x28, 0x00, + 0xD4, 0x74, 0x92, 0xFD, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xE2, + 0x06, 0xD3, 0xCB, 0x07, 0x00, 0x00, 0x38, 0x70, 0xA8, 0x0D, 0x57, 0xE1, 0x26, 0xE7, 0xB1, 0xDE, + 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x77, 0x31, 0x04, 0x70, 0x14, 0x61, 0x34, 0x31, + 0xC6, 0x36, 0x82, 0x05, 0x30, 0x52, 0x24, 0x24, 0x26, 0x75, 0xF2, 0xFA, 0x06, 0x27, 0xE1, 0xF0, + 0x3C, 0x10, 0x10, 0x00, 0x08, 0x60, 0xFF, 0xCF, 0xD1, 0xC1, 0x08, 0x50, 0x00, 0x30, 0x0C, 0x70, + 0x6C, 0x53, 0x0C, 0xE0, 0x94, 0xAC, 0x0C, 0x20, 0xA4, 0xAC, 0x0C, 0x40, 0x7C, 0x53, 0x26, 0xE6, + 0x26, 0x26, 0x26, 0x75, 0x0C, 0xD0, 0xB0, 0x0D, 0x14, 0x61, 0x26, 0x45, 0x30, 0xF7, 0x2F, 0x5D, + 0x07, 0x00, 0x2F, 0x3E, 0x05, 0x00, 0xB1, 0xF3, 0x38, 0x37, 0x10, 0x00, 0x26, 0x52, 0xB1, 0x35, + 0xB1, 0x67, 0xB9, 0x67, 0x10, 0x00, 0x24, 0x74, 0xC6, 0x74, 0x92, 0xF1, 0x50, 0xC1, 0x2C, 0x10, + 0x10, 0x00, 0xE1, 0xF0, 0x34, 0x18, 0x08, 0x60, 0x00, 0x30, 0x08, 0x50, 0xFF, 0xCF, 0xC1, 0xE1, + 0x0C, 0x70, 0x6C, 0x53, 0x0C, 0xF0, 0x94, 0xAC, 0x26, 0x76, 0x26, 0xF5, 0x0C, 0x30, 0xB0, 0x0D, + 0x34, 0x21, 0x2C, 0x50, 0xA4, 0xAC, 0x2C, 0x60, 0x7C, 0x53, 0x2F, 0x43, 0x07, 0x00, 0x2F, 0xEF, + 0x04, 0x00, 0x30, 0xEE, 0xC4, 0x21, 0xB1, 0xE7, 0xD2, 0x05, 0x26, 0x45, 0x30, 0x44, 0xB9, 0x47, + 0x10, 0x00, 0x24, 0x74, 0xC6, 0x76, 0x92, 0xF2, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, + 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0xD1, 0x81, 0x08, 0xC0, 0x00, 0x30, 0x06, 0xA2, + 0x04, 0xD0, 0x0C, 0xB0, 0xAC, 0x0D, 0x2C, 0xC0, 0x00, 0x49, 0x30, 0x7B, 0x06, 0x9B, 0x18, 0x77, + 0x09, 0x00, 0xC6, 0xD7, 0x32, 0x19, 0x04, 0xE0, 0x30, 0x79, 0x18, 0x37, 0x08, 0x00, 0xC6, 0xE3, + 0x32, 0x11, 0x06, 0x2D, 0xBB, 0x6B, 0x00, 0x00, 0x26, 0x2E, 0x06, 0x72, 0x57, 0x71, 0x26, 0x7C, + 0x30, 0x77, 0x2F, 0x62, 0x02, 0x00, 0x26, 0x6A, 0x5C, 0x70, 0xFF, 0x0F, 0xA1, 0x76, 0x24, 0xE1, + 0xF2, 0xEC, 0x24, 0xD1, 0xF2, 0xE3, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0x38, 0xC0, 0xAC, 0x0D, + 0xD1, 0x81, 0x04, 0x9C, 0x26, 0x9C, 0x04, 0xE0, 0x0C, 0xA0, 0xB0, 0x0D, 0x2F, 0xDE, 0x09, 0x00, + 0x18, 0x2D, 0x01, 0x00, 0x18, 0x3C, 0x08, 0x00, 0x2F, 0xBA, 0x0E, 0x00, 0xBB, 0x6B, 0x00, 0x00, + 0x10, 0x7D, 0x24, 0xE2, 0xC4, 0xEA, 0x26, 0x27, 0xA9, 0x2B, 0x20, 0x00, 0x92, 0xF0, 0x58, 0xC1, + 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, + 0x38, 0x57, 0x98, 0x60, 0x08, 0x60, 0x48, 0x30, 0x2C, 0x60, 0xE0, 0x00, 0xC6, 0x56, 0x92, 0x0E, + 0xCC, 0x20, 0x70, 0x00, 0xC2, 0x03, 0x0C, 0x20, 0x70, 0x00, 0x0C, 0x60, 0x00, 0xDE, 0xB9, 0x67, + 0x10, 0x60, 0xB9, 0x27, 0x40, 0x60, 0xB9, 0x07, 0x10, 0x60, 0xE1, 0xF0, 0x34, 0x14, 0x66, 0x32, + 0x04, 0x21, 0xB1, 0xF1, 0x4B, 0x08, 0x00, 0x00, 0x04, 0x61, 0x08, 0x70, 0x00, 0x40, 0x04, 0x20, + 0xB9, 0x67, 0x70, 0x10, 0x06, 0x32, 0x4B, 0x08, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, + 0x3C, 0x10, 0x20, 0x00, 0x08, 0x70, 0x00, 0x30, 0xD9, 0xC1, 0x10, 0x00, 0x2C, 0x70, 0x00, 0x01, + 0xB9, 0x70, 0xA8, 0x0D, 0xD1, 0x81, 0x0C, 0x70, 0xC0, 0x19, 0x0C, 0x60, 0x9C, 0x01, 0xB9, 0x70, + 0xAC, 0x0D, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x67, 0x74, 0x10, 0xCB, 0x07, 0x00, 0x00, 0x38, 0x70, + 0xAC, 0x0D, 0x38, 0xE0, 0xA8, 0x0D, 0x20, 0x37, 0x04, 0x20, 0x4B, 0x09, 0x00, 0x00, 0xB9, 0x2E, + 0x08, 0x00, 0x38, 0x6E, 0x08, 0x00, 0xB9, 0x60, 0x00, 0x23, 0x08, 0x70, 0x02, 0x05, 0xB9, 0x7E, + 0x0C, 0x00, 0x08, 0xB0, 0x70, 0x14, 0x2B, 0x12, 0x00, 0x00, 0x2C, 0xB0, 0x70, 0x99, 0x04, 0xE0, + 0x0C, 0xD0, 0xA8, 0x0D, 0x08, 0x90, 0x01, 0x00, 0x08, 0xA0, 0x7D, 0x0E, 0x30, 0x7D, 0x30, 0x77, + 0xD6, 0x79, 0x82, 0x05, 0x06, 0x2B, 0x04, 0x30, 0xEB, 0x15, 0x00, 0x00, 0x30, 0x7D, 0x08, 0x60, + 0x00, 0x01, 0x30, 0x77, 0xD6, 0x76, 0x82, 0x1D, 0x08, 0x70, 0x00, 0x40, 0x38, 0xC7, 0x40, 0x60, + 0x0C, 0x20, 0x1D, 0x00, 0x5C, 0xC0, 0x7F, 0x00, 0x26, 0x2C, 0x6B, 0x14, 0x00, 0x00, 0x38, 0x70, + 0xAC, 0x0D, 0xA8, 0x77, 0x18, 0x00, 0x82, 0x04, 0xAB, 0x63, 0x00, 0x00, 0x06, 0xE2, 0x0C, 0x20, + 0x70, 0x21, 0x26, 0x2A, 0x06, 0x3E, 0xEB, 0x15, 0x00, 0x00, 0x06, 0x2C, 0x6B, 0x14, 0x00, 0x00, + 0x30, 0x6D, 0x30, 0x76, 0xD4, 0x71, 0x92, 0x04, 0x30, 0x76, 0xD4, 0x72, 0x82, 0x1B, 0x08, 0x70, + 0x00, 0x40, 0x38, 0xC7, 0x40, 0x60, 0x0C, 0x20, 0x1D, 0x00, 0x5C, 0xC0, 0x7F, 0x00, 0x26, 0x2C, + 0x6B, 0x14, 0x00, 0x00, 0x30, 0x7D, 0x30, 0x27, 0x54, 0x23, 0x0B, 0x38, 0x00, 0x00, 0x06, 0xE2, + 0x0C, 0x20, 0x70, 0xC7, 0x26, 0x2A, 0x06, 0x3E, 0xEB, 0x15, 0x00, 0x00, 0x06, 0x2C, 0x6B, 0x14, + 0x00, 0x00, 0x30, 0x7D, 0x30, 0x77, 0xDC, 0x70, 0x00, 0x01, 0x82, 0xB1, 0xEB, 0x61, 0x00, 0x00, + 0x06, 0xE2, 0x06, 0x3E, 0x08, 0x20, 0x7D, 0x0E, 0x2C, 0x20, 0x00, 0xC5, 0xEB, 0x15, 0x00, 0x00, + 0xF2, 0xA6, 0x00, 0x00, 0x3C, 0x10, 0x14, 0x00, 0xD9, 0xC1, 0x04, 0x00, 0xB1, 0xB1, 0x08, 0x50, + 0x00, 0x40, 0x38, 0x65, 0x0C, 0x70, 0xC4, 0x21, 0xB9, 0x63, 0x18, 0x01, 0x06, 0xC2, 0x06, 0xE3, + 0x92, 0x0D, 0x08, 0x70, 0xFF, 0xE0, 0x2C, 0x70, 0xFF, 0xE0, 0x56, 0x76, 0x08, 0x60, 0x00, 0x01, + 0x2C, 0x60, 0x00, 0x01, 0x66, 0x76, 0xB9, 0x75, 0x0C, 0x70, 0x08, 0xD0, 0x00, 0x40, 0x0C, 0x30, + 0xA8, 0x71, 0x06, 0x2E, 0x26, 0x3D, 0x0C, 0x40, 0x20, 0x00, 0x0B, 0x07, 0x00, 0x00, 0x0C, 0x20, + 0x20, 0x00, 0x08, 0xB0, 0x00, 0x30, 0x0C, 0x30, 0x00, 0x40, 0x26, 0x2E, 0x26, 0x3B, 0x0C, 0x40, + 0xF0, 0x00, 0xCB, 0x05, 0x00, 0x00, 0x38, 0x7D, 0x78, 0x71, 0xC4, 0xC1, 0xB9, 0x7E, 0x10, 0x01, + 0x92, 0x0A, 0x38, 0x7B, 0x8C, 0x53, 0xB9, 0x7E, 0x14, 0x01, 0x0C, 0x70, 0xFF, 0x03, 0xB9, 0x7B, + 0x8C, 0x53, 0xF2, 0x0F, 0xC4, 0xC2, 0x92, 0x0D, 0x38, 0x7D, 0x2C, 0x72, 0xB9, 0x7E, 0x1C, 0x01, + 0x38, 0x7D, 0x30, 0x72, 0xB9, 0x7E, 0x20, 0x01, 0xB9, 0x0D, 0x2C, 0x72, 0xB9, 0x0D, 0x30, 0x72, + 0x58, 0xC1, 0x04, 0x00, 0x30, 0xB1, 0x2C, 0x10, 0x14, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x14, 0x00, + 0xD9, 0xC1, 0x04, 0x00, 0x06, 0xE3, 0x06, 0xC2, 0x04, 0x21, 0xB1, 0xB1, 0xAB, 0x0C, 0x00, 0x00, + 0x38, 0x7E, 0x18, 0x01, 0x08, 0xD0, 0x00, 0x40, 0x0C, 0x20, 0xA8, 0x71, 0xB9, 0x7D, 0x0C, 0x70, + 0x26, 0x2D, 0x06, 0x3E, 0x0C, 0x40, 0x20, 0x00, 0xCB, 0x05, 0x00, 0x00, 0x08, 0xB0, 0x00, 0x30, + 0x0C, 0x20, 0x00, 0x40, 0x0C, 0x30, 0x20, 0x00, 0x26, 0x2B, 0x26, 0x3E, 0x0C, 0x40, 0xF0, 0x00, + 0xCB, 0x05, 0x00, 0x00, 0x38, 0x7E, 0x10, 0x01, 0xC4, 0xC1, 0xB9, 0x7D, 0x78, 0x71, 0x92, 0x06, + 0x38, 0x7E, 0x14, 0x01, 0xB9, 0x7B, 0x8C, 0x53, 0xF2, 0x0B, 0xC4, 0xC2, 0x92, 0x09, 0x38, 0x7E, + 0x1C, 0x01, 0xB9, 0x7D, 0x2C, 0x72, 0x38, 0x7E, 0x20, 0x01, 0xB9, 0x7D, 0x30, 0x72, 0x58, 0xC1, + 0x04, 0x00, 0x30, 0xB1, 0x2C, 0x10, 0x14, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x28, 0x00, + 0xD9, 0x81, 0x08, 0x00, 0x06, 0xB2, 0x08, 0x20, 0x00, 0x40, 0x2C, 0x20, 0xA8, 0x71, 0x04, 0x30, + 0x0C, 0x40, 0x20, 0x00, 0xD9, 0xC1, 0x18, 0x00, 0x0C, 0xA0, 0xAC, 0x0D, 0x2B, 0x05, 0x00, 0x00, + 0x14, 0xE1, 0x24, 0xE1, 0xCC, 0xE0, 0x1F, 0x00, 0x8A, 0x90, 0x00, 0x00, 0x04, 0x21, 0x38, 0x7B, + 0x10, 0x01, 0x06, 0x62, 0x53, 0x6E, 0xD6, 0x76, 0x82, 0xF5, 0x08, 0x70, 0x00, 0x80, 0x66, 0x76, + 0x08, 0x60, 0x00, 0x40, 0xB9, 0x76, 0x78, 0x71, 0x2F, 0x7E, 0x0B, 0x00, 0x10, 0xD7, 0xAB, 0x0C, + 0x00, 0x00, 0x04, 0x78, 0x26, 0x7D, 0x57, 0x71, 0x26, 0x7B, 0x30, 0x77, 0x08, 0x60, 0x00, 0x30, + 0xB9, 0x76, 0x00, 0x40, 0x30, 0x7A, 0x0C, 0x90, 0x08, 0x40, 0x18, 0x77, 0x08, 0x00, 0x26, 0x96, + 0x26, 0x7D, 0x24, 0x78, 0x57, 0x71, 0x26, 0x7B, 0x30, 0x77, 0x04, 0xC2, 0xB9, 0x76, 0x04, 0x40, + 0x06, 0x8A, 0x2C, 0x60, 0x00, 0x40, 0x30, 0x78, 0x18, 0x57, 0x09, 0x00, 0xC6, 0xC5, 0x32, 0x10, + 0x18, 0x37, 0x08, 0x00, 0xB1, 0x61, 0x06, 0x2C, 0xBB, 0x6B, 0x00, 0x00, 0x30, 0x61, 0x26, 0x2D, + 0x57, 0x21, 0x26, 0x26, 0x30, 0x72, 0x24, 0xC1, 0xB1, 0x79, 0x24, 0x94, 0xF2, 0xED, 0x04, 0x25, + 0xAB, 0x01, 0x00, 0x00, 0x30, 0x8A, 0x08, 0xC0, 0x00, 0x30, 0x2C, 0xC0, 0x00, 0x49, 0x04, 0x90, + 0x0C, 0x60, 0x00, 0x23, 0x18, 0x78, 0x09, 0x00, 0xC6, 0x97, 0x32, 0x12, 0x18, 0x38, 0x08, 0x00, + 0xB1, 0x61, 0x06, 0x29, 0xBB, 0x6B, 0x00, 0x00, 0x30, 0x7C, 0x30, 0x61, 0x26, 0x2D, 0x26, 0x22, + 0x26, 0x26, 0x5C, 0x70, 0xFF, 0x0F, 0xA1, 0x72, 0x24, 0x91, 0x24, 0xC4, 0xF2, 0xEC, 0x0B, 0x0A, + 0x00, 0x00, 0x04, 0x25, 0xAB, 0x01, 0x00, 0x00, 0x30, 0x7A, 0x08, 0xC0, 0x00, 0x30, 0x2C, 0xC0, + 0x00, 0x49, 0x04, 0x90, 0x0C, 0x50, 0x00, 0x23, 0x18, 0x67, 0x09, 0x00, 0xC6, 0x96, 0x32, 0x8A, + 0x18, 0x37, 0x08, 0x00, 0x30, 0x8C, 0xB9, 0x51, 0x04, 0x00, 0x06, 0x29, 0xB1, 0x71, 0xBB, 0x6B, + 0x00, 0x00, 0x38, 0x51, 0x04, 0x00, 0x30, 0x71, 0x26, 0x2D, 0x26, 0x22, 0x26, 0x25, 0x20, 0x62, + 0x5C, 0x80, 0xFF, 0x0F, 0xC6, 0x86, 0xC2, 0x03, 0xA1, 0x02, 0xF2, 0x04, 0x3F, 0x88, 0x06, 0x00, + 0xA1, 0x82, 0x24, 0x91, 0x24, 0xC4, 0xF2, 0xE1, 0x58, 0xC1, 0x18, 0x00, 0x58, 0x81, 0x08, 0x00, + 0x2C, 0x10, 0x28, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x20, 0x00, 0xD1, 0x81, 0x06, 0xB2, + 0x04, 0x25, 0xD9, 0xC1, 0x10, 0x00, 0xAB, 0x01, 0x00, 0x00, 0x38, 0xA0, 0xAC, 0x0D, 0x08, 0xC0, + 0x00, 0x30, 0x04, 0xD0, 0x2C, 0xC0, 0x00, 0x49, 0x0C, 0x90, 0x00, 0x23, 0x18, 0x7A, 0x09, 0x00, + 0xC6, 0xD7, 0xB2, 0x20, 0x04, 0xE0, 0x18, 0x3A, 0x08, 0x00, 0xC6, 0xE3, 0xB2, 0x19, 0x06, 0x2D, + 0xBB, 0x6B, 0x00, 0x00, 0x26, 0x2E, 0x06, 0x72, 0x57, 0x71, 0x2F, 0x62, 0x02, 0x00, 0x26, 0x7C, + 0x2F, 0x56, 0x0B, 0x00, 0x30, 0x77, 0x20, 0x55, 0x5C, 0x70, 0xFF, 0x0F, 0xC6, 0x75, 0x26, 0x69, + 0xB2, 0x03, 0xA1, 0x06, 0xF2, 0x03, 0x36, 0x75, 0xA1, 0x76, 0x24, 0xE1, 0xF2, 0xE5, 0x24, 0xD1, + 0xF2, 0xDE, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x3C, 0x10, 0x34, 0x01, 0xD9, 0xC1, 0x24, 0x01, 0x06, 0xE2, 0x0B, 0x0A, 0x00, 0x00, 0x04, 0x25, + 0xAB, 0x01, 0x00, 0x00, 0xC4, 0xE2, 0x92, 0x06, 0x06, 0x2D, 0x0C, 0x20, 0x00, 0x1A, 0x0B, 0x0F, + 0x00, 0x00, 0x06, 0x2E, 0xAB, 0x0C, 0x00, 0x00, 0x06, 0x2E, 0x06, 0x31, 0x2B, 0x20, 0x00, 0x00, + 0xC4, 0xE2, 0x92, 0x07, 0x06, 0x2D, 0x0C, 0x20, 0x00, 0x1A, 0x4B, 0x34, 0x00, 0x00, 0xF2, 0x07, + 0x06, 0x21, 0x06, 0x3D, 0x0C, 0x30, 0x00, 0x1A, 0x6B, 0x29, 0x00, 0x00, 0x06, 0x2E, 0x06, 0x31, + 0x6B, 0x25, 0x00, 0x00, 0x58, 0xC1, 0x24, 0x01, 0x04, 0x20, 0x2C, 0x10, 0x34, 0x01, 0xE1, 0xF0, + 0x3C, 0x10, 0x14, 0x00, 0xD9, 0xC1, 0x04, 0x00, 0x38, 0xE0, 0xAC, 0x0D, 0xB1, 0xB1, 0x06, 0xC3, + 0x18, 0x3E, 0x08, 0x00, 0x06, 0xB4, 0x06, 0xD2, 0xBB, 0x6B, 0x00, 0x00, 0x26, 0x2C, 0xB1, 0x2B, + 0x18, 0x7E, 0x0A, 0x00, 0xC6, 0xC7, 0xB2, 0x11, 0x18, 0x7E, 0x0B, 0x00, 0xC6, 0xD7, 0xA2, 0x0A, + 0x18, 0x7E, 0x16, 0x00, 0xC6, 0xD7, 0x82, 0x06, 0x18, 0x7E, 0x17, 0x00, 0x04, 0x20, 0xC6, 0xD7, + 0x92, 0x1E, 0x28, 0x2E, 0x1C, 0x00, 0xF2, 0x1B, 0x18, 0x6E, 0x04, 0x00, 0x2F, 0x76, 0x06, 0x00, + 0x0C, 0x30, 0xB0, 0x0D, 0x26, 0x37, 0x34, 0x61, 0x04, 0x70, 0x14, 0x51, 0x2F, 0x47, 0x06, 0x00, + 0xC6, 0x45, 0x82, 0x0C, 0x2F, 0x47, 0x07, 0x00, 0x26, 0x43, 0x28, 0x44, 0x1E, 0x00, 0x34, 0x71, + 0xC6, 0x24, 0x92, 0xF5, 0x28, 0x2E, 0x1E, 0x00, 0xF2, 0x02, 0x04, 0x20, 0x58, 0xC1, 0x04, 0x00, + 0x30, 0xB1, 0x2C, 0x10, 0x14, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xC2, + 0x06, 0xE4, 0x04, 0x21, 0x06, 0xD3, 0x0B, 0x03, 0x00, 0x00, 0x08, 0x70, 0x00, 0x30, 0x2C, 0x70, + 0x00, 0x40, 0x57, 0xC1, 0x2F, 0x27, 0x0C, 0x00, 0x30, 0x72, 0xC4, 0xE0, 0x0C, 0x60, 0xFF, 0x03, + 0x56, 0x67, 0x77, 0x75, 0x5C, 0x70, 0xFF, 0x03, 0x82, 0x09, 0xC4, 0xD0, 0x82, 0x04, 0x26, 0x6E, + 0x26, 0x7E, 0xF2, 0x11, 0x36, 0x7E, 0x36, 0x6E, 0xF2, 0x0E, 0xC4, 0xD0, 0x82, 0x07, 0xC6, 0x76, + 0x02, 0x03, 0x24, 0x61, 0xF2, 0x0D, 0x24, 0x71, 0xF2, 0x06, 0xC6, 0x76, 0x02, 0x03, 0x34, 0x71, + 0xF2, 0x02, 0x34, 0x61, 0xC4, 0x60, 0x02, 0x06, 0xCC, 0x60, 0xFF, 0x03, 0x12, 0x06, 0x04, 0xE0, + 0xF2, 0x07, 0x14, 0xE1, 0x04, 0x61, 0xF2, 0x04, 0x14, 0xE1, 0x0C, 0x60, 0xFF, 0x03, 0xC4, 0x70, + 0x02, 0x08, 0xCC, 0x70, 0xFF, 0x03, 0x02, 0x07, 0x14, 0xE1, 0x0C, 0x70, 0xFF, 0x03, 0xF2, 0x03, + 0x14, 0xE1, 0x04, 0x71, 0x57, 0x75, 0x66, 0x76, 0xB1, 0x72, 0x04, 0x20, 0x0B, 0x03, 0x00, 0x00, + 0x06, 0x2E, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x28, 0x00, + 0xD9, 0xC1, 0x18, 0x00, 0x38, 0xE0, 0xAC, 0x0D, 0xD9, 0x81, 0x08, 0x00, 0x06, 0xD2, 0x18, 0x7E, + 0x05, 0x00, 0x18, 0x2E, 0x0B, 0x00, 0x18, 0x3E, 0x0A, 0x00, 0x26, 0x27, 0xBB, 0x6B, 0x00, 0x00, + 0x18, 0xAE, 0x04, 0x00, 0x18, 0x3E, 0x08, 0x00, 0x26, 0x2A, 0xB9, 0x21, 0x04, 0x00, 0x18, 0x2E, + 0x09, 0x00, 0x23, 0xDD, 0xBB, 0x6B, 0x00, 0x00, 0x2F, 0x42, 0x02, 0x00, 0x06, 0x3D, 0x0C, 0x20, + 0x00, 0x1A, 0x6B, 0x04, 0x00, 0x00, 0x18, 0x3E, 0x08, 0x00, 0x18, 0x2E, 0x09, 0x00, 0xBB, 0x6B, + 0x00, 0x00, 0x06, 0x42, 0x04, 0x30, 0x06, 0x2D, 0x0C, 0x20, 0x80, 0x1E, 0x2B, 0x05, 0x00, 0x00, + 0x18, 0x3E, 0x08, 0x00, 0x18, 0x2E, 0x09, 0x00, 0xBB, 0x6B, 0x00, 0x00, 0x06, 0x42, 0x04, 0x31, + 0x06, 0x29, 0x0C, 0x20, 0xC0, 0x20, 0x08, 0xB0, 0x00, 0x30, 0x2B, 0x05, 0x00, 0x00, 0x0C, 0xC0, + 0x82, 0x00, 0x2C, 0xB0, 0x00, 0x49, 0x04, 0x21, 0x04, 0x80, 0xAB, 0x01, 0x00, 0x00, 0x06, 0xD8, + 0x18, 0x7E, 0x09, 0x00, 0xC6, 0x87, 0x32, 0x46, 0x04, 0xA0, 0x18, 0x6E, 0x08, 0x00, 0xC6, 0xA6, + 0x32, 0x3F, 0x06, 0x41, 0x06, 0x28, 0x06, 0x3A, 0x0B, 0x3B, 0x00, 0x00, 0x86, 0x42, 0x82, 0x36, + 0x30, 0x21, 0x06, 0x62, 0x57, 0x61, 0x26, 0x6B, 0x30, 0x66, 0x0C, 0x50, 0x80, 0x1E, 0x5C, 0x60, + 0xFF, 0x0F, 0x26, 0x52, 0x3F, 0x44, 0x06, 0x00, 0x90, 0x65, 0x82, 0x04, 0xCC, 0x40, 0x46, 0x00, + 0x02, 0x24, 0x06, 0x69, 0x0C, 0x60, 0xC0, 0x20, 0x26, 0x62, 0x10, 0x36, 0xC4, 0x31, 0x0C, 0xF0, + 0x00, 0x1A, 0x2F, 0x32, 0x02, 0x00, 0x92, 0x05, 0xC4, 0x40, 0x22, 0x0E, 0x91, 0x06, 0xF2, 0x0C, + 0xC4, 0x40, 0x12, 0x0A, 0x04, 0x41, 0x91, 0x46, 0x2F, 0x43, 0x0F, 0x00, 0xA0, 0x44, 0x92, 0x04, + 0x10, 0x45, 0x24, 0x41, 0x91, 0x45, 0x26, 0x3F, 0x20, 0x43, 0xF7, 0x40, 0xA1, 0x43, 0x10, 0x36, + 0x4B, 0x3F, 0x00, 0x00, 0xC4, 0x20, 0x32, 0x02, 0x24, 0xD1, 0x24, 0xA1, 0xF2, 0xBF, 0x24, 0x81, + 0xF2, 0xB8, 0x38, 0x71, 0x04, 0x00, 0xC6, 0xD7, 0xB2, 0x03, 0xB4, 0xC1, 0x92, 0xAD, 0x58, 0xC1, + 0x18, 0x00, 0x58, 0x81, 0x08, 0x00, 0x2C, 0x10, 0x28, 0x00, 0xE1, 0xF0, 0x34, 0x14, 0x04, 0x21, + 0xB1, 0xF1, 0x0B, 0x03, 0x00, 0x00, 0x08, 0x20, 0x00, 0x30, 0x08, 0x30, 0x06, 0x00, 0x2C, 0x30, + 0x80, 0x01, 0x0C, 0x40, 0x00, 0x09, 0x2C, 0x20, 0x00, 0x40, 0xCB, 0x03, 0x00, 0x00, 0x04, 0x20, + 0x0B, 0x03, 0x00, 0x00, 0x0C, 0x20, 0x00, 0x02, 0x6B, 0x44, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x24, 0x00, 0xD9, 0x81, 0x04, 0x00, 0x38, 0xB0, 0xAC, 0x0D, + 0xD9, 0xC1, 0x14, 0x00, 0x04, 0xE0, 0x06, 0xA2, 0x06, 0x93, 0x06, 0xCE, 0x04, 0x51, 0x18, 0x7B, + 0x09, 0x00, 0xC6, 0xC7, 0x32, 0x22, 0x04, 0xD0, 0x18, 0x3B, 0x08, 0x00, 0xC6, 0xD3, 0x32, 0x1B, + 0x06, 0x2C, 0xB1, 0x51, 0xBB, 0x6B, 0x00, 0x00, 0x26, 0x2D, 0x38, 0x40, 0xAC, 0x0D, 0x30, 0x51, + 0x2F, 0x72, 0x02, 0x00, 0x2F, 0x67, 0x0A, 0x00, 0x20, 0x66, 0x28, 0x34, 0x22, 0x00, 0xC6, 0x36, + 0xA2, 0x05, 0x28, 0x44, 0x20, 0x00, 0xC6, 0x46, 0xC2, 0x04, 0x26, 0x79, 0xA1, 0x57, 0x24, 0xE1, + 0x24, 0xD1, 0xF2, 0xE3, 0x24, 0xC1, 0xF2, 0xDC, 0x06, 0x2E, 0x58, 0xC1, 0x14, 0x00, 0x58, 0x81, + 0x04, 0x00, 0x2C, 0x10, 0x24, 0x00, 0xE1, 0xF0, 0x38, 0x70, 0xAC, 0x0D, 0x04, 0x60, 0x18, 0x37, + 0x09, 0x00, 0x18, 0x77, 0x08, 0x00, 0x14, 0x41, 0x26, 0x37, 0x06, 0x76, 0xC6, 0x73, 0x32, 0x0D, + 0x2F, 0x57, 0x07, 0x00, 0x26, 0x52, 0x20, 0x55, 0xC6, 0x56, 0xD2, 0x03, 0x06, 0x56, 0xF2, 0x02, + 0x06, 0x47, 0x24, 0x71, 0x06, 0x65, 0xF2, 0xF3, 0x06, 0x24, 0xE1, 0xF0, 0x3C, 0x10, 0x14, 0x00, + 0xD9, 0xC1, 0x04, 0x00, 0x38, 0xD0, 0xAC, 0x0D, 0xB1, 0xB1, 0x06, 0xC2, 0x18, 0x7D, 0x09, 0x00, + 0xC6, 0x37, 0x32, 0x0F, 0x18, 0xED, 0x08, 0x00, 0x06, 0x23, 0x06, 0x3E, 0xBB, 0x6B, 0x00, 0x00, + 0x26, 0x22, 0x26, 0x2C, 0x04, 0x30, 0x2F, 0x4E, 0x0E, 0x00, 0x6B, 0x04, 0x00, 0x00, 0xF2, 0x13, + 0x3F, 0xB7, 0x03, 0x00, 0x04, 0xE0, 0x18, 0x7D, 0x09, 0x00, 0xC6, 0xE7, 0x32, 0x0C, 0x18, 0x3D, + 0x08, 0x00, 0x06, 0x2E, 0xBB, 0x6B, 0x00, 0x00, 0x26, 0x2B, 0x26, 0x22, 0x26, 0x2C, 0xA1, 0x02, + 0x24, 0xE1, 0xF2, 0xF2, 0x58, 0xC1, 0x04, 0x00, 0x30, 0xB1, 0x2C, 0x10, 0x14, 0x00, 0xE1, 0xF0, + 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0x38, 0xE0, 0xAC, 0x0D, 0xD1, 0x81, 0x06, 0xA3, + 0x18, 0x4E, 0x09, 0x00, 0x18, 0x7E, 0x08, 0x00, 0x06, 0x92, 0x26, 0x47, 0x06, 0x23, 0x26, 0x44, + 0x04, 0x30, 0x6B, 0x04, 0x00, 0x00, 0x06, 0xBA, 0x04, 0xC0, 0x18, 0x7E, 0x09, 0x00, 0xC6, 0xC7, + 0x32, 0x1F, 0x04, 0xD0, 0x18, 0x3E, 0x08, 0x00, 0xC6, 0xD3, 0x32, 0x17, 0x06, 0x2C, 0xBB, 0x6B, + 0x00, 0x00, 0x26, 0x2D, 0x26, 0x22, 0x26, 0x29, 0x20, 0x72, 0xC4, 0x71, 0x92, 0x0C, 0x20, 0x7B, + 0x24, 0x71, 0xA1, 0x7B, 0x18, 0x7E, 0x09, 0x00, 0x26, 0x7D, 0x26, 0x77, 0x26, 0x7A, 0x20, 0x67, + 0x24, 0x61, 0xA1, 0x67, 0x24, 0xD1, 0xF2, 0xE7, 0x24, 0xC1, 0x24, 0xB2, 0xF2, 0xDF, 0x58, 0xC1, + 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x20, 0x00, + 0xD9, 0xC1, 0x10, 0x00, 0x06, 0xC2, 0x04, 0x30, 0x06, 0x2E, 0x0C, 0x20, 0x00, 0x1A, 0x0C, 0x40, + 0x80, 0x04, 0x38, 0xD0, 0xAC, 0x0D, 0xD1, 0x81, 0x6B, 0x04, 0x00, 0x00, 0x06, 0x2B, 0x0C, 0x20, + 0x80, 0x1E, 0x04, 0x30, 0x0C, 0x40, 0x80, 0x04, 0x6B, 0x04, 0x00, 0x00, 0x06, 0x2C, 0x06, 0x3E, + 0x0C, 0x30, 0x00, 0x1A, 0x2B, 0x50, 0x00, 0x00, 0x04, 0x70, 0xC6, 0x27, 0x06, 0xCE, 0x02, 0x31, + 0x06, 0x9E, 0x0C, 0x90, 0x00, 0x1A, 0x18, 0x5D, 0x08, 0x00, 0x18, 0x6D, 0x09, 0x00, 0x04, 0xA1, + 0x26, 0x65, 0xC6, 0x76, 0x26, 0xA7, 0x32, 0x25, 0x06, 0x2C, 0x0C, 0x20, 0x00, 0x1A, 0x06, 0x3B, + 0x0C, 0x30, 0x80, 0x1E, 0x8B, 0x58, 0x00, 0x00, 0x06, 0x2B, 0x0C, 0x20, 0x80, 0x1E, 0xCB, 0x53, + 0x00, 0x00, 0x86, 0xE2, 0x22, 0x16, 0x06, 0x29, 0x06, 0x3E, 0x6B, 0x55, 0x00, 0x00, 0x18, 0x7D, + 0x09, 0x00, 0xC6, 0xE7, 0x32, 0x04, 0x38, 0x50, 0xA0, 0x0D, 0xF2, 0x04, 0x38, 0x50, 0x9C, 0x0D, + 0x36, 0xE7, 0x30, 0x75, 0x04, 0x61, 0x53, 0x6E, 0x66, 0x76, 0xB1, 0x75, 0x06, 0x7A, 0xF2, 0xD4, + 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x34, 0x18, 0xC1, 0xE1, + 0x0B, 0x0A, 0x00, 0x00, 0x6B, 0x4E, 0x00, 0x00, 0x0C, 0x20, 0x00, 0x01, 0xAB, 0x0C, 0x00, 0x00, + 0x04, 0x2A, 0xAB, 0x01, 0x00, 0x00, 0x06, 0x2E, 0x0C, 0x20, 0x00, 0x23, 0x0B, 0x0F, 0x00, 0x00, + 0x06, 0x2E, 0x0C, 0x20, 0x00, 0x23, 0x6B, 0x5C, 0x00, 0x00, 0x40, 0xE1, 0x04, 0x20, 0x24, 0x18, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x28, 0x00, 0xD9, 0x81, 0x08, 0x00, 0x06, 0x2B, 0x0C, 0x20, + 0x00, 0x1A, 0x0C, 0x30, 0xFF, 0x0F, 0x0C, 0x40, 0x80, 0x04, 0xD9, 0xC1, 0x18, 0x00, 0x6B, 0x04, + 0x00, 0x00, 0x06, 0x2A, 0x0C, 0x20, 0x80, 0x1E, 0x04, 0x30, 0x0C, 0x40, 0x80, 0x04, 0x6B, 0x04, + 0x00, 0x00, 0x04, 0x2A, 0x08, 0x80, 0x00, 0x30, 0xAB, 0x01, 0x00, 0x00, 0x04, 0x90, 0x2C, 0x80, + 0x00, 0x49, 0x38, 0xE0, 0xAC, 0x0D, 0x28, 0x7E, 0x18, 0x00, 0xC6, 0x97, 0x22, 0x07, 0x04, 0xC0, + 0x0C, 0xA0, 0x80, 0x1E, 0x0C, 0xB0, 0x00, 0x1A, 0xF2, 0x37, 0x04, 0xD0, 0x06, 0x5A, 0x0C, 0x50, + 0x80, 0x1E, 0x06, 0x6B, 0x0C, 0x60, 0x00, 0x1A, 0x18, 0x7E, 0x09, 0x00, 0xC6, 0xD7, 0x32, 0x26, + 0x04, 0xC0, 0x18, 0x3E, 0x08, 0x00, 0xC6, 0xC3, 0x32, 0x1F, 0x06, 0x2D, 0xB1, 0x51, 0xB9, 0x61, + 0x04, 0x00, 0xBB, 0x6B, 0x00, 0x00, 0x26, 0x2C, 0x06, 0x72, 0x30, 0x51, 0x38, 0x61, 0x04, 0x00, + 0x57, 0x71, 0x26, 0x78, 0x26, 0x22, 0x30, 0x77, 0x2F, 0x45, 0x02, 0x00, 0x20, 0x34, 0x5C, 0x70, + 0xFF, 0x0F, 0xC6, 0x37, 0xB2, 0x02, 0xA1, 0x74, 0x26, 0x26, 0x20, 0x42, 0xC6, 0x47, 0xC2, 0x02, + 0xA1, 0x72, 0x24, 0xC1, 0xF2, 0xDF, 0x24, 0xD1, 0xF2, 0xD8, 0x04, 0x21, 0xAB, 0x01, 0x00, 0x00, + 0x24, 0x91, 0xF2, 0xC0, 0x24, 0xC1, 0x18, 0x7E, 0x09, 0x00, 0xC6, 0xC7, 0x32, 0x15, 0x04, 0xD0, + 0x18, 0x3E, 0x08, 0x00, 0xC6, 0xD3, 0x32, 0xF7, 0x06, 0x2C, 0xBB, 0x6B, 0x00, 0x00, 0x26, 0x2D, + 0x26, 0x22, 0x2F, 0x7A, 0x02, 0x00, 0x26, 0x2B, 0x20, 0x57, 0x20, 0x62, 0x24, 0xD1, 0x3F, 0x66, + 0x05, 0x00, 0xA1, 0x67, 0xF2, 0xEE, 0x58, 0xC1, 0x18, 0x00, 0x58, 0x81, 0x08, 0x00, 0x04, 0x20, + 0x2C, 0x10, 0x28, 0x00, 0xE1, 0xF0, 0xC4, 0x30, 0x04, 0x40, 0x04, 0x50, 0x0C, 0x60, 0x20, 0x00, + 0x52, 0x03, 0xA6, 0x42, 0x25, 0x50, 0xB4, 0x61, 0x02, 0x06, 0xA6, 0x44, 0x25, 0x55, 0xA6, 0x33, + 0x42, 0xF9, 0xF2, 0xFA, 0x06, 0x24, 0x06, 0x35, 0xE1, 0xF0, 0x00, 0x00, 0xFC, 0x22, 0x00, 0x00, + 0xF8, 0x22, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x0E, 0x18, 0x0E, 0x18, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x10, 0x08, 0x12, 0x00, 0x54, 0xFF, 0x0F, 0x00, + 0x10, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x32, 0x00, 0x16, 0x32, 0x10, 0x10, + 0x01, 0x00, 0x08, 0x00, 0x32, 0x00, 0x64, 0x10, 0x61, 0xC7, 0x00, 0x00, 0xFF, 0x3F, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x64, 0xC0, 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x0F, 0x40, 0x0F, 0x01, 0x01, 0x80, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x80, 0x00, 0x80, + 0x0A, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x0E, 0x18, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x80, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x42, 0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x88, 0x00, 0x10, 0x1F, 0x10, 0x1F, 0x64, 0x3C, 0x10, 0x00, + 0x00, 0x00, 0x08, 0x82, 0x00, 0x00, 0xFF, 0x0F, 0x01, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, + 0xC8, 0x00, 0x00, 0x02, 0x05, 0x00, 0x08, 0x1F, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0x0D, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x10, 0xB0, 0x00, 0xD5, 0xC6, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x01, 0x03, 0x00, 0x1B, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFB, 0x07, 0x40, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x7F, 0xFC, 0x8F, 0xBF, + 0x01, 0x20, 0x00, 0x00, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x13, 0x12, + 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x16, 0x15, 0x14, 0x13, + 0x12, 0x11, 0x10, 0x00, 0x00, 0x00, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x00, 0x01, 0x02, 0x03, 0x04, + 0x00, 0x00, 0x00, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x17, 0x00, 0x00, 0xFF, 0x00, 0x20, 0x86, + 0x00, 0x00, 0x00, 0x4C, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3A, 0x26, 0x14, 0x00, 0x38, 0x26, 0x10, 0x01, 0x45, 0x26, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x2D, 0x28, 0x08, 0x03, 0x2E, 0x28, 0x0B, 0x02, 0x28, 0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x07, 0x13, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x4E, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x50, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x50, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x50, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x50, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x50, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x50, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x50, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x50, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x50, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x50, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x50, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x50, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x50, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, + 0x00, 0x02, 0x50, 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0xD0, 0xF1, 0x7F, 0x21, 0xF0, 0xF1, 0x7F, 0x42, 0xF0, 0xF1, 0x7F, + 0x63, 0xF0, 0xF1, 0x7F, 0x84, 0xF0, 0xF1, 0x7F, 0xA5, 0xF0, 0xF1, 0x7F, 0xC6, 0xF0, 0xF1, 0x7F, + 0xE7, 0xF0, 0xF1, 0x7F, 0x08, 0xF1, 0xF1, 0x7F, 0x29, 0xF1, 0xF1, 0x7F, 0x4A, 0xF1, 0xF1, 0x7F, + 0x6B, 0xF1, 0xF1, 0x7F, 0x8C, 0xF1, 0xF1, 0x7F, 0xAD, 0xE1, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, + 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, + 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, + 0x00, 0xC0, 0xF1, 0x7B, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, + 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x40, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x7F, 0xFC, 0x8F, 0x1F, + 0x7F, 0xFC, 0x8F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x41, 0x10, 0x04, + 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, + 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, + 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, + 0x04, 0x41, 0x10, 0x04, 0x41, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, + 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, + 0x40, 0x40, 0x40, 0x00, 0x30, 0x30, 0x30, 0x30, 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, + 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, + 0x04, 0x41, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x05, 0x58, 0x00, 0x00, + 0x0E, 0x18, 0x0E, 0x18, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x10, 0x08, 0x12, 0x00, 0x54, 0xFF, 0x0F, 0x00, + 0x10, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x32, 0x00, 0x16, 0x32, 0x10, 0x10, + 0x01, 0x00, 0x08, 0x00, 0x32, 0x00, 0x64, 0x10, 0x61, 0xC7, 0x00, 0x00, 0xFF, 0x3F, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x64, 0xC0, 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x0F, 0x40, 0x0F, 0x01, 0x01, 0x80, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x80, 0x00, 0x80, + 0x0A, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x0E, 0x18, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x80, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x42, 0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x88, 0x00, 0x10, 0x1F, 0x10, 0x1F, 0x64, 0x3C, 0x10, 0x00, + 0x00, 0x00, 0x08, 0x82, 0x00, 0x00, 0xFF, 0x0F, 0x01, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, + 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0x0D, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x28, 0x00, 0x02, 0xD5, 0xC6, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2A, 0x3A, 0x02, 0x00, 0x80, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFB, 0xF7, 0x43, 0x00, 0x05, 0xA3, 0xA8, 0x00, 0x00, 0xFF, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x7F, 0xFC, 0x8F, 0xBF, + 0x01, 0x20, 0x00, 0x00, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x13, 0x12, + 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x16, 0x15, 0x14, 0x13, + 0x12, 0x11, 0x10, 0x00, 0x00, 0x00, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x00, 0x01, 0x02, 0x03, 0x04, + 0x00, 0x00, 0x00, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x17, 0x00, 0x00, 0xFF, 0x00, 0x20, 0x86, + 0x00, 0x00, 0x00, 0x4C, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x26, 0x12, 0x01, 0x38, 0x26, 0x10, 0x01, 0x45, 0x26, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x2D, 0x28, 0x08, 0x03, 0x2E, 0x28, 0x09, 0x03, 0x28, 0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x07, 0x13, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x4E, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x43, 0x12, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x3E, 0xFA, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, + 0x3F, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3F, 0xFE, 0x08, 0x30, + 0x45, 0x16, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x00, 0x02, 0x58, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x43, 0x12, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x3E, 0xFA, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x3F, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3F, 0xFE, 0x08, 0x30, + 0x45, 0x1A, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x00, 0x02, 0x58, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x43, 0x12, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x3E, 0xFE, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, + 0x3F, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x45, 0x1A, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x43, 0x0E, 0x59, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0xFE, 0x08, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x43, 0x12, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x3E, 0xFA, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, + 0x3F, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x45, 0x1A, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x00, 0x02, 0x58, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x43, 0x12, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x3E, 0xFE, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x3F, 0x02, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x45, 0x1A, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x00, 0x02, 0x58, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x43, 0x12, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x3E, 0xFA, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, + 0x3F, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x45, 0x1A, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x00, 0x02, 0x58, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x43, 0x12, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x3E, 0xFE, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x3F, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3F, 0xFE, 0x08, 0x30, + 0x45, 0x1A, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x43, 0x0E, 0x59, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x43, 0x12, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x3E, 0xFE, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x3F, 0x02, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x45, 0x1A, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x00, 0x02, 0x58, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x43, 0x12, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x3E, 0xFE, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x3F, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x45, 0x1A, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x00, 0x02, 0x58, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x43, 0x12, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x3E, 0xFE, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, + 0x3F, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x45, 0x1A, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x00, 0x02, 0x58, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x43, 0x12, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x43, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x3F, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x45, 0x1A, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x00, 0x02, 0x58, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x43, 0x12, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x3E, 0xFE, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, + 0x3F, 0x02, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x45, 0x1A, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x43, 0x0E, 0x59, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x43, 0x12, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x3E, 0xFA, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, + 0x3F, 0x02, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x45, 0x1A, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x00, 0x02, 0x58, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x43, 0x12, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x3E, 0xFE, 0x08, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x45, 0x1A, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFA, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, + 0x3F, 0x02, 0x09, 0x30, 0x43, 0x12, 0x09, 0x30, 0x43, 0x0E, 0x09, 0x30, 0x3F, 0x02, 0x09, 0x30, + 0x45, 0x1A, 0x09, 0x30, 0x42, 0x0E, 0x09, 0x30, 0x3E, 0xFE, 0x08, 0x30, 0x43, 0x12, 0x09, 0x30, + 0x00, 0x02, 0x58, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xF1, 0x7F, 0x21, 0xF0, 0xF1, 0x7F, 0x42, 0xF0, 0xF1, 0x7F, + 0x63, 0xF0, 0xF1, 0x7F, 0x84, 0xF0, 0xF1, 0x7F, 0xA5, 0xF0, 0xF1, 0x7F, 0xC6, 0xF0, 0xF1, 0x7F, + 0xE7, 0xF0, 0xF1, 0x7F, 0x08, 0xF1, 0xF1, 0x7F, 0x29, 0xF1, 0xF1, 0x7F, 0x4A, 0xF1, 0xF1, 0x7F, + 0x6B, 0xF1, 0xF1, 0x7F, 0x8C, 0xF1, 0xF1, 0x7F, 0xAD, 0xE1, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, + 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, + 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, + 0x00, 0xC0, 0xF1, 0x7B, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, + 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0xC0, 0xF1, 0x7F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x40, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x26, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x8F, 0x1F, + 0x7F, 0xFC, 0x8F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x82, 0x20, 0x08, + 0x08, 0x82, 0x20, 0x08, 0x08, 0x82, 0x20, 0x08, 0x08, 0x82, 0x20, 0x08, 0x08, 0x82, 0x20, 0x08, + 0x08, 0x82, 0x20, 0x08, 0x08, 0x82, 0x20, 0x08, 0x08, 0x82, 0x20, 0x08, 0x08, 0x82, 0x20, 0x08, + 0x08, 0x82, 0x20, 0x08, 0x08, 0x82, 0x20, 0x08, 0x08, 0x82, 0x20, 0x08, 0x08, 0x82, 0x20, 0x08, + 0x08, 0x82, 0x20, 0x08, 0x41, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, + 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, + 0x40, 0x40, 0x40, 0x00, 0x30, 0x30, 0x30, 0x30, 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, + 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, + 0x04, 0x41, 0x10, 0x00, 0x00, 0x00, 0x02, 0x05, 0x43, 0x4D, 0x43, 0x53, 0x32, 0x54, 0x41, 0x47 +}; + +#endif diff --git a/drivers/input/touchscreen/ist3038c/ist30xxc_fw_v02_t1.h b/drivers/input/touchscreen/ist3038c/ist30xxc_fw_v02_t1.h new file mode 100644 index 0000000000000..776712a2ff031 --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/ist30xxc_fw_v02_t1.h @@ -0,0 +1,4054 @@ + +#ifndef __IST30XXC_FW_H__ +#define __IST30XXC_FW_H__ + + + + + + + +static unsigned char ist30xxc_fw[] = { + 0x80, 0x00, 0x00, 0x80, 0x0C, 0x01, 0x00, 0x80, 0x74, 0x0C, 0x00, 0x80, 0xFC, 0x00, 0x00, 0x80, + 0x04, 0x01, 0x00, 0x80, 0xF8, 0x0C, 0x00, 0x80, 0xA8, 0x0C, 0x00, 0x80, 0xD0, 0x0C, 0x00, 0x80, + 0x0C, 0x01, 0x00, 0x80, 0x0C, 0x01, 0x00, 0x80, 0x0C, 0x01, 0x00, 0x80, 0x40, 0x0D, 0x00, 0x80, + 0x64, 0x0D, 0x00, 0x80, 0x0C, 0x01, 0x00, 0x80, 0x0C, 0x01, 0x00, 0x80, 0x0C, 0x01, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x10, 0x00, 0x27, 0x08, 0x80, 0x00, 0x80, 0x2C, 0x80, 0xB8, 0x6E, 0xAB, 0x0B, 0x00, 0x00, + 0x08, 0x70, 0x00, 0x40, 0x04, 0x61, 0x99, 0x67, 0x10, 0x00, 0x91, 0x67, 0x08, 0x70, 0x0F, 0x00, + 0x11, 0x17, 0x0C, 0x70, 0xB0, 0x15, 0x0C, 0x60, 0xB0, 0x15, 0xC6, 0x76, 0xB2, 0x04, 0xB1, 0x07, + 0x24, 0x74, 0xF2, 0xFC, 0x08, 0x30, 0x00, 0x80, 0x04, 0x70, 0x0C, 0x40, 0xB0, 0x15, 0x0C, 0x50, + 0xB0, 0x15, 0x2C, 0x30, 0x30, 0x73, 0x2F, 0x64, 0x07, 0x00, 0xC6, 0x65, 0xB2, 0x07, 0x2F, 0x23, + 0x07, 0x00, 0x30, 0x22, 0x24, 0x74, 0xB1, 0x26, 0xF2, 0xF7, 0x0C, 0x70, 0xB0, 0x15, 0x0C, 0x60, + 0xF0, 0x16, 0xC6, 0x76, 0xB2, 0x04, 0xB1, 0x07, 0x24, 0x74, 0xF2, 0xFC, 0xEB, 0x0F, 0x00, 0x00, + 0xAB, 0x74, 0x03, 0x00, 0xB9, 0x20, 0x88, 0x27, 0x04, 0x22, 0xF2, 0x0D, 0xB9, 0x20, 0x88, 0x27, + 0x04, 0x23, 0xF2, 0x09, 0xB9, 0x20, 0x88, 0x27, 0x04, 0x24, 0xF2, 0x05, 0xB9, 0x20, 0x88, 0x27, + 0x04, 0x21, 0xF2, 0x01, 0xB9, 0x10, 0x84, 0x27, 0xB9, 0x30, 0x8C, 0x27, 0x08, 0x30, 0x00, 0x50, + 0xB9, 0x03, 0x00, 0x10, 0xD9, 0x40, 0x90, 0x27, 0xD9, 0x80, 0xA0, 0x27, 0xD9, 0xC0, 0xB0, 0x27, + 0x01, 0x40, 0x01, 0x51, 0xC9, 0x40, 0xC0, 0x27, 0x99, 0x20, 0x80, 0x27, 0x08, 0x20, 0x01, 0x00, + 0xB1, 0x23, 0x98, 0x40, 0x80, 0x27, 0x92, 0xFE, 0x09, 0x00, 0x01, 0x00, 0x04, 0x23, 0xB9, 0x23, + 0x00, 0x10, 0xF2, 0x01, 0x48, 0x40, 0xC0, 0x27, 0x11, 0x15, 0x11, 0x04, 0x58, 0xC0, 0xB0, 0x27, + 0x58, 0x80, 0xA0, 0x27, 0x58, 0x40, 0x90, 0x27, 0x48, 0x20, 0x88, 0x27, 0x38, 0x10, 0x84, 0x27, + 0x61, 0x00, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0x2B, 0xC2, 0x00, 0x00, + 0x0B, 0xC9, 0x00, 0x00, 0x2B, 0xCA, 0x00, 0x00, 0xCB, 0xA0, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0xAB, 0xCF, 0x00, 0x00, 0xAB, 0xDD, 0x00, 0x00, + 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0xCB, 0xE0, 0x00, 0x00, + 0x4B, 0xD2, 0x00, 0x00, 0x6B, 0xD1, 0x00, 0x00, 0x2B, 0xD0, 0x00, 0x00, 0x8B, 0xD3, 0x00, 0x00, + 0x4B, 0xD4, 0x00, 0x00, 0xAB, 0xD6, 0x00, 0x00, 0x4B, 0xE8, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0xEB, 0xE3, 0x00, 0x00, 0xAB, 0xC4, 0x00, 0x00, + 0x0B, 0x36, 0x03, 0x00, 0xAB, 0xDD, 0x00, 0x00, 0x2B, 0x8B, 0x00, 0x00, 0x4B, 0x79, 0x00, 0x00, + 0x04, 0x20, 0x4B, 0xF3, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, + 0xD1, 0xC1, 0xAB, 0xBC, 0x00, 0x00, 0xAB, 0xC1, 0x00, 0x00, 0xEB, 0x12, 0x00, 0x00, 0xCB, 0x0B, + 0x00, 0x00, 0xAB, 0x0C, 0x00, 0x00, 0x4B, 0x0D, 0x00, 0x00, 0x4B, 0xB7, 0x00, 0x00, 0xCB, 0x1B, + 0x01, 0x00, 0xAB, 0x0E, 0x00, 0x00, 0xCB, 0x1A, 0x01, 0x00, 0x98, 0x70, 0xDE, 0x16, 0x92, 0xFC, + 0x18, 0x70, 0xD5, 0x16, 0xC4, 0x71, 0x82, 0xF8, 0x6B, 0x19, 0x01, 0x00, 0xCB, 0x2F, 0x00, 0x00, + 0xCB, 0x05, 0x01, 0x00, 0x6B, 0x30, 0x00, 0x00, 0x8B, 0x17, 0x01, 0x00, 0xAB, 0x18, 0x01, 0x00, + 0xEB, 0x19, 0x01, 0x00, 0x6B, 0xF9, 0x00, 0x00, 0xF2, 0xE7, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, + 0x04, 0x61, 0xB9, 0x67, 0x00, 0x80, 0xB9, 0x07, 0x0C, 0x80, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x80, + 0xC6, 0x27, 0x34, 0x14, 0xB1, 0xF1, 0x82, 0x03, 0xC6, 0x37, 0x92, 0x04, 0x8B, 0x1A, 0x00, 0x00, + 0xF2, 0x09, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x27, 0x04, 0x80, 0xB9, 0x37, 0x08, 0x80, 0x38, 0x27, + 0x10, 0x80, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x27, 0x18, 0x80, + 0xB9, 0x37, 0x1C, 0x80, 0x06, 0x67, 0x38, 0x76, 0x28, 0x80, 0xD4, 0x71, 0x82, 0xFD, 0x38, 0x26, + 0x20, 0x80, 0xE1, 0xF0, 0x04, 0x50, 0xC6, 0x25, 0x32, 0x03, 0x16, 0x22, 0x04, 0x51, 0x04, 0x60, + 0xC6, 0x36, 0x32, 0x03, 0x16, 0x33, 0x04, 0x61, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x27, 0x18, 0x80, + 0xB9, 0x37, 0x1C, 0x80, 0x06, 0x47, 0x38, 0x74, 0x28, 0x80, 0xD4, 0x71, 0x82, 0xFD, 0xC6, 0x56, + 0x38, 0x24, 0x20, 0x80, 0x82, 0x02, 0x16, 0x22, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, + 0xB9, 0x27, 0x18, 0x80, 0xB9, 0x37, 0x1C, 0x80, 0x06, 0x67, 0x38, 0x76, 0x28, 0x80, 0xD4, 0x71, + 0x82, 0xFD, 0x38, 0x26, 0x24, 0x80, 0xE1, 0xF0, 0x04, 0x50, 0xC6, 0x25, 0x34, 0x18, 0xC1, 0xE1, + 0x06, 0xE2, 0x32, 0x03, 0x16, 0xE2, 0x04, 0x51, 0x04, 0x60, 0xC6, 0x36, 0x32, 0x03, 0x16, 0x33, + 0x04, 0x61, 0x08, 0x70, 0x00, 0x40, 0xB9, 0xE7, 0x18, 0x80, 0xB9, 0x37, 0x1C, 0x80, 0x06, 0x47, + 0x38, 0x74, 0x28, 0x80, 0xD4, 0x71, 0x82, 0xFD, 0xC6, 0x56, 0x38, 0x24, 0x20, 0x80, 0x82, 0x02, + 0x16, 0x22, 0x6B, 0x13, 0x00, 0x00, 0x3F, 0x22, 0x0E, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, + 0xC4, 0x30, 0x04, 0x40, 0x04, 0x50, 0x0C, 0x60, 0x20, 0x00, 0x52, 0x03, 0xA6, 0x42, 0x25, 0x50, + 0xB4, 0x61, 0x02, 0x06, 0xA6, 0x44, 0x25, 0x55, 0xA6, 0x33, 0x42, 0xF9, 0xF2, 0xFA, 0x06, 0x24, + 0x06, 0x35, 0xE1, 0xF0, 0x04, 0x40, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x9E, 0x00, 0x00, + 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x9D, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, + 0xBA, 0x9C, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x9B, 0x00, 0x00, 0xA6, 0x22, + 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x9A, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x99, + 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x98, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, + 0xC6, 0x43, 0xBA, 0x97, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x96, 0x00, 0x00, + 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x95, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, + 0xBA, 0x94, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x93, 0x00, 0x00, 0xA6, 0x22, + 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x92, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x91, + 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x90, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, + 0xC6, 0x43, 0xBA, 0x8F, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x8E, 0x00, 0x00, + 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x8D, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, + 0xBA, 0x8C, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x8B, 0x00, 0x00, 0xA6, 0x22, + 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x8A, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x89, + 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x88, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, + 0xC6, 0x43, 0xBA, 0x87, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x86, 0x00, 0x00, + 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x85, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, + 0xBA, 0x84, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x83, 0x00, 0x00, 0xA6, 0x22, + 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x82, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x81, + 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, 0xC6, 0x43, 0xBA, 0x80, 0x00, 0x00, 0xA6, 0x22, 0x25, 0x44, + 0xC6, 0x43, 0xBA, 0x7F, 0x00, 0x00, 0xE1, 0xF0, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x62, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x63, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x64, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x65, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x66, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x67, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x68, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x69, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x6A, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x6B, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x6C, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x6D, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x6E, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x6F, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x70, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x71, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x72, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x73, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x74, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x75, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x76, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x77, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x78, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x79, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x7A, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x7B, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x7C, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x7D, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x7E, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xFA, 0x7F, 0xFF, 0xFF, 0x36, 0x43, 0x24, 0x21, 0xFA, 0x80, 0xFF, 0xFF, + 0x36, 0x43, 0x24, 0x21, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x04, 0x70, + 0x6C, 0x70, 0x40, 0x00, 0x66, 0x72, 0xB9, 0x76, 0x04, 0x70, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x40, + 0x38, 0x76, 0x60, 0x71, 0x08, 0x50, 0x40, 0x00, 0x66, 0x75, 0xB9, 0x76, 0x60, 0x71, 0xE1, 0xF0, + 0x08, 0x50, 0x00, 0x40, 0x38, 0x75, 0x60, 0x71, 0x08, 0x60, 0xBF, 0xFF, 0x2C, 0x60, 0xFF, 0xFF, + 0x56, 0x76, 0xB9, 0x75, 0x60, 0x71, 0xE1, 0xF0, 0x34, 0x14, 0x0C, 0x20, 0x00, 0x60, 0xB1, 0xF1, + 0x2B, 0x57, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x98, 0x70, 0xD5, 0x16, + 0x34, 0x14, 0xB1, 0xF1, 0x92, 0x05, 0x0C, 0x20, 0x00, 0x60, 0x0B, 0x58, 0x00, 0x00, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0x0C, 0x20, 0x00, 0x60, 0xB1, 0xF1, 0x2B, 0x57, 0x00, 0x00, + 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x60, 0x71, 0x08, 0x50, 0x40, 0x00, 0x66, 0x75, 0xB9, 0x76, + 0x60, 0x71, 0x0C, 0x20, 0x64, 0x00, 0x2B, 0xC0, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, + 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x04, 0x70, 0x1C, 0x50, 0x1D, 0x00, 0x56, 0x75, 0x66, 0x72, + 0xB9, 0x76, 0x04, 0x70, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x04, 0x35, + 0x06, 0xE2, 0x04, 0x21, 0xCB, 0x6F, 0x00, 0x00, 0x04, 0x24, 0x04, 0x30, 0xCB, 0x55, 0x00, 0x00, + 0x08, 0xD0, 0x00, 0x40, 0x38, 0x7D, 0x08, 0x70, 0xD6, 0x7E, 0x92, 0x0A, 0x04, 0x21, 0x4B, 0x6E, + 0x00, 0x00, 0xCB, 0x51, 0x00, 0x00, 0x04, 0x21, 0x0B, 0x6F, 0x00, 0x00, 0xF2, 0xF4, 0x04, 0x24, + 0x04, 0x31, 0xCB, 0x55, 0x00, 0x00, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x18, 0x70, 0xD2, 0x16, 0x34, 0x14, 0x93, 0x07, 0xB1, 0xF1, 0x92, 0x02, 0x51, 0x00, 0x08, 0x60, + 0x00, 0x40, 0x38, 0x76, 0x04, 0x70, 0x1C, 0x50, 0x41, 0x70, 0x56, 0x75, 0xB9, 0x76, 0x04, 0x70, + 0x04, 0x24, 0x04, 0x31, 0xCB, 0x55, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, + 0x08, 0x70, 0x00, 0x40, 0x38, 0x67, 0x08, 0x70, 0xB9, 0x67, 0x08, 0x70, 0xE1, 0xF0, 0x00, 0x00, + 0x34, 0x18, 0xC1, 0xE1, 0x06, 0xE2, 0x0B, 0x37, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0xB9, 0xE7, + 0x00, 0x70, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xE2, + 0x06, 0xD3, 0x0B, 0x37, 0x00, 0x00, 0x04, 0x24, 0x04, 0x30, 0xCB, 0x55, 0x00, 0x00, 0x06, 0x2D, + 0xCB, 0x2D, 0x00, 0x00, 0x99, 0x00, 0xD2, 0x16, 0x08, 0x70, 0x00, 0x40, 0xB9, 0xE7, 0x00, 0x70, + 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x80, 0x18, 0x67, 0x6B, 0xDC, + 0x08, 0x70, 0x00, 0x40, 0xB9, 0x67, 0x7C, 0x70, 0x38, 0x67, 0x70, 0x70, 0x64, 0x62, 0xB9, 0x67, + 0x70, 0x70, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x70, 0x70, 0x64, 0x71, 0xB9, 0x76, + 0x70, 0x70, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x70, 0x70, 0x14, 0x52, 0x56, 0x75, + 0xB9, 0x76, 0x70, 0x70, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0x38, 0x27, 0xE0, 0x70, + 0x5C, 0x20, 0xFF, 0x7F, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0x38, 0x27, 0xE4, 0x70, + 0x5C, 0x20, 0xFF, 0x01, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0x38, 0x27, 0x5C, 0x70, + 0x5C, 0x20, 0x7F, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0xC4, 0x20, 0x08, 0x60, 0x00, 0x40, 0x82, 0x08, + 0x08, 0x70, 0x0F, 0xC0, 0x2C, 0x70, 0xFF, 0xFF, 0xB9, 0x76, 0x3C, 0x71, 0xF2, 0x03, 0xB9, 0x06, + 0x3C, 0x71, 0xE1, 0xF0, 0x08, 0x20, 0x00, 0x40, 0x08, 0x30, 0x00, 0x80, 0x34, 0x18, 0x2C, 0x20, + 0x08, 0x70, 0x2C, 0x30, 0x08, 0xE2, 0x0C, 0x40, 0xBE, 0x00, 0xC1, 0xE1, 0x0C, 0xF0, 0x5C, 0x01, + 0xF1, 0xF0, 0x0C, 0x20, 0x00, 0x40, 0x08, 0xE0, 0x00, 0x30, 0x08, 0x30, 0x00, 0x80, 0x26, 0x2E, + 0x2C, 0x30, 0x00, 0xE5, 0x0C, 0x40, 0x40, 0x02, 0x0C, 0xF0, 0x5C, 0x01, 0xF1, 0xF0, 0x0C, 0x20, + 0xC4, 0x52, 0x08, 0x30, 0x00, 0x80, 0x26, 0x2E, 0x2C, 0x30, 0x00, 0xEE, 0x0C, 0x40, 0x54, 0x00, + 0x0C, 0xF0, 0x5C, 0x01, 0xF1, 0xF0, 0x08, 0x70, 0x00, 0x80, 0x28, 0x77, 0x28, 0xDC, 0x0C, 0x20, + 0x00, 0x49, 0x06, 0x37, 0x57, 0x38, 0x26, 0x2E, 0x66, 0x37, 0x0C, 0x40, 0x69, 0x01, 0x0C, 0xF0, + 0xD8, 0x01, 0xF1, 0xF0, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, 0x04, 0x7F, 0x56, 0x72, + 0xC4, 0x71, 0x34, 0x14, 0xB1, 0xF1, 0x92, 0x04, 0x38, 0x70, 0xA8, 0x16, 0xF2, 0x03, 0x38, 0x70, + 0xAC, 0x16, 0xC4, 0x28, 0x38, 0x67, 0x50, 0x00, 0x38, 0x57, 0x74, 0x00, 0x38, 0x37, 0x68, 0x00, + 0x38, 0xF7, 0x8C, 0x00, 0x38, 0x47, 0x94, 0x00, 0x82, 0x49, 0xC4, 0x28, 0xD2, 0x07, 0xC4, 0x22, + 0x82, 0x16, 0xC4, 0x23, 0x82, 0x38, 0xC4, 0x21, 0xF2, 0x09, 0xCC, 0x20, 0x82, 0x00, 0x82, 0x13, + 0xCC, 0x20, 0x82, 0x00, 0xD2, 0x05, 0xCC, 0x20, 0x81, 0x00, 0x92, 0x53, 0xF2, 0x3F, 0xCC, 0x20, + 0x83, 0x00, 0x82, 0x29, 0xCC, 0x20, 0x88, 0x00, 0x82, 0x31, 0xF2, 0x4B, 0x98, 0x20, 0xE4, 0x16, + 0x82, 0x35, 0xF2, 0x1C, 0x98, 0x20, 0xE4, 0x16, 0x82, 0x31, 0x08, 0x50, 0x00, 0x80, 0x2C, 0x50, + 0x0C, 0xDC, 0x28, 0x60, 0x0E, 0x0B, 0x18, 0x25, 0x77, 0x00, 0xC6, 0x26, 0xD2, 0x06, 0x38, 0x67, + 0x60, 0x00, 0x38, 0x57, 0x84, 0x00, 0xF2, 0x22, 0x18, 0x55, 0x78, 0x00, 0xC6, 0x56, 0xD2, 0x06, + 0x38, 0x67, 0x64, 0x00, 0x38, 0x57, 0x88, 0x00, 0xF2, 0x19, 0x38, 0x67, 0x5C, 0x00, 0x38, 0x57, + 0x80, 0x00, 0xF2, 0x14, 0x38, 0x67, 0x54, 0x00, 0x38, 0x57, 0x78, 0x00, 0x38, 0x37, 0x6C, 0x00, + 0x38, 0xF7, 0x90, 0x00, 0x38, 0x47, 0x98, 0x00, 0xF2, 0x09, 0x38, 0x67, 0x58, 0x00, 0x38, 0x57, + 0x7C, 0x00, 0x38, 0x37, 0x70, 0x00, 0x38, 0x47, 0x9C, 0x00, 0x98, 0x70, 0xD6, 0x16, 0x82, 0x05, + 0x08, 0x60, 0x22, 0x00, 0x2C, 0x60, 0x20, 0x20, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x67, 0x34, 0x70, + 0xB9, 0x57, 0x64, 0x70, 0xB9, 0x37, 0x54, 0x70, 0xB9, 0xF7, 0x6C, 0x70, 0xB9, 0x47, 0x1C, 0x71, + 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x54, 0x2F, 0xC4, 0x21, 0x92, 0x04, 0x38, 0x70, + 0xA8, 0x16, 0xF2, 0x03, 0x38, 0x70, 0xAC, 0x16, 0x38, 0x57, 0x4C, 0x00, 0x98, 0x70, 0xE4, 0x16, + 0x08, 0x70, 0x00, 0x80, 0x82, 0x06, 0x2C, 0x70, 0xC0, 0xDC, 0x38, 0x67, 0x04, 0x00, 0xF2, 0x03, + 0x38, 0x67, 0xC0, 0xDC, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x57, 0x30, 0x70, 0xB9, 0x67, 0x58, 0x70, + 0xE1, 0xF0, 0x00, 0x00, 0x54, 0x2F, 0xC4, 0x21, 0x92, 0x04, 0x38, 0x60, 0xA8, 0x16, 0xF2, 0x03, + 0x38, 0x60, 0xAC, 0x16, 0x38, 0x56, 0x08, 0x00, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x57, 0xB4, 0x70, + 0x38, 0x56, 0x0C, 0x00, 0x08, 0x40, 0xDF, 0xFF, 0xB9, 0x57, 0xB8, 0x70, 0x38, 0x56, 0x10, 0x00, + 0x2C, 0x40, 0xFF, 0xFF, 0x56, 0x54, 0xB9, 0x57, 0xC0, 0x70, 0x38, 0x56, 0x14, 0x00, 0xB9, 0x57, + 0xC4, 0x70, 0x98, 0x50, 0xD7, 0x16, 0x82, 0x0C, 0x08, 0x60, 0x01, 0x00, 0x2C, 0x60, 0x81, 0x11, + 0xB9, 0x67, 0xAC, 0x70, 0x08, 0x60, 0x10, 0x00, 0x2C, 0x60, 0x10, 0x00, 0xF2, 0x06, 0x30, 0x56, + 0xB9, 0x57, 0xAC, 0x70, 0x38, 0x66, 0x04, 0x00, 0xB9, 0x67, 0xB0, 0x70, 0xE1, 0xF0, 0x00, 0x00, + 0x54, 0x2F, 0xC4, 0x21, 0x92, 0x04, 0x38, 0x70, 0xA8, 0x16, 0xF2, 0x03, 0x38, 0x70, 0xAC, 0x16, + 0x38, 0x57, 0x2C, 0x00, 0x08, 0x60, 0x00, 0x40, 0xB9, 0x56, 0x8C, 0x70, 0x38, 0x57, 0x30, 0x00, + 0xB9, 0x56, 0x90, 0x70, 0x38, 0x57, 0x34, 0x00, 0xB9, 0x56, 0x94, 0x70, 0x38, 0x57, 0x38, 0x00, + 0xB9, 0x56, 0x98, 0x70, 0x38, 0x57, 0x3C, 0x00, 0xB9, 0x56, 0x9C, 0x70, 0x38, 0x57, 0x40, 0x00, + 0xB9, 0x56, 0xA0, 0x70, 0x38, 0x57, 0x44, 0x00, 0xB9, 0x56, 0xA4, 0x70, 0x38, 0x77, 0x48, 0x00, + 0xB9, 0x76, 0xA8, 0x70, 0xE1, 0xF0, 0x00, 0x00, 0x51, 0x00, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x40, + 0xC4, 0x20, 0x38, 0x67, 0x34, 0x10, 0x82, 0x03, 0x64, 0x63, 0xF2, 0x03, 0x14, 0x54, 0x56, 0x65, + 0xB9, 0x67, 0x34, 0x10, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0xAD, 0xDE, 0x2C, 0x70, 0x8C, 0x03, + 0x08, 0x60, 0x00, 0x40, 0xB9, 0x76, 0x00, 0x10, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0xAD, 0xDE, + 0x08, 0x60, 0x00, 0x40, 0x2C, 0x70, 0x8C, 0x03, 0xB9, 0x76, 0x00, 0x10, 0xB9, 0x26, 0x6C, 0x10, + 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x60, 0xAD, 0xDE, 0x08, 0x70, 0x00, 0x40, 0x2C, 0x60, 0x8C, 0x03, + 0xB9, 0x67, 0x00, 0x10, 0x0C, 0x50, 0x10, 0x00, 0xB9, 0x57, 0x20, 0x10, 0x08, 0x50, 0x38, 0x03, + 0xB9, 0x67, 0x00, 0x10, 0x2C, 0x50, 0x80, 0x88, 0xB9, 0x57, 0x24, 0x10, 0xB9, 0x67, 0x00, 0x10, + 0xB9, 0x07, 0x28, 0x10, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x60, 0xAD, 0xDE, 0x08, 0x70, 0x00, 0x40, + 0x2C, 0x60, 0x8C, 0x03, 0xB9, 0x67, 0x00, 0x10, 0xC4, 0x30, 0x38, 0x67, 0x50, 0x10, 0x82, 0x05, + 0x66, 0x62, 0xB9, 0x67, 0x50, 0x10, 0xF2, 0x05, 0x15, 0x22, 0x56, 0x26, 0xB9, 0x27, 0x50, 0x10, + 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x60, 0xAD, 0xDE, 0x08, 0x70, 0x00, 0x40, 0x2C, 0x60, 0x8C, 0x03, + 0xB9, 0x67, 0x00, 0x10, 0x38, 0x67, 0x54, 0x10, 0x66, 0x62, 0xB9, 0x67, 0x54, 0x10, 0xE1, 0xF0, + 0x08, 0x60, 0xAD, 0xDE, 0x08, 0x70, 0x00, 0x40, 0x2C, 0x60, 0x8C, 0x03, 0xB9, 0x67, 0x00, 0x10, + 0x38, 0x67, 0x54, 0x10, 0x15, 0x22, 0x56, 0x26, 0xB9, 0x27, 0x54, 0x10, 0xE1, 0xF0, 0x00, 0x00, + 0x08, 0x60, 0xAD, 0xDE, 0x08, 0x70, 0x00, 0x40, 0x2C, 0x60, 0x8C, 0x03, 0xB9, 0x67, 0x00, 0x10, + 0x38, 0x57, 0x58, 0x10, 0xCC, 0x20, 0xFF, 0x00, 0x1C, 0x40, 0x00, 0x01, 0x56, 0x54, 0x92, 0x0A, + 0xB9, 0x57, 0x58, 0x10, 0xB9, 0x67, 0x00, 0x10, 0x38, 0x67, 0x4C, 0x10, 0x14, 0x52, 0x56, 0x65, + 0xF2, 0x09, 0x66, 0x52, 0xB9, 0x57, 0x58, 0x10, 0xB9, 0x67, 0x00, 0x10, 0x38, 0x67, 0x4C, 0x10, + 0x64, 0x61, 0xB9, 0x67, 0x4C, 0x10, 0xE1, 0xF0, 0x08, 0x60, 0xAD, 0xDE, 0x08, 0x70, 0x00, 0x40, + 0x2C, 0x60, 0x8C, 0x03, 0xB9, 0x67, 0x00, 0x10, 0xC4, 0x30, 0x38, 0x67, 0x4C, 0x10, 0x82, 0x05, + 0x66, 0x62, 0xB9, 0x67, 0x4C, 0x10, 0xF2, 0x05, 0x15, 0x22, 0x56, 0x26, 0xB9, 0x27, 0x4C, 0x10, + 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0xAD, 0xDE, 0x08, 0x60, 0x00, 0x40, 0x2C, 0x70, 0x8C, 0x03, + 0xB9, 0x76, 0x00, 0x10, 0x04, 0x73, 0xB9, 0x76, 0x44, 0x10, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x40, + 0x38, 0x76, 0x08, 0x10, 0x66, 0x72, 0xB9, 0x76, 0x08, 0x10, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x40, + 0x38, 0x76, 0x64, 0x10, 0x66, 0x72, 0xB9, 0x76, 0x64, 0x10, 0xE1, 0xF0, 0x04, 0x62, 0x08, 0x70, + 0x00, 0x40, 0xB9, 0x67, 0x14, 0x10, 0xE1, 0xF0, 0x23, 0x22, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x27, + 0x10, 0x10, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x14, 0x10, 0x1C, 0x50, 0x11, 0x00, + 0x56, 0x75, 0x64, 0x71, 0xB9, 0x76, 0x14, 0x10, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, + 0x08, 0x60, 0x00, 0x40, 0x38, 0x76, 0x14, 0x10, 0x14, 0x52, 0x56, 0x75, 0x6C, 0x70, 0x10, 0x00, + 0xB9, 0x76, 0x14, 0x10, 0x0C, 0x20, 0x28, 0x00, 0x8B, 0xBD, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0xC4, 0x20, 0x04, 0x7F, 0x82, 0x03, 0x0C, 0x70, 0x9C, 0x00, 0x6C, 0x70, + 0x00, 0x01, 0x08, 0x60, 0x00, 0x40, 0xB9, 0x76, 0x74, 0x10, 0xE1, 0xF0, 0x04, 0x61, 0x08, 0x70, + 0x00, 0x40, 0xB9, 0x67, 0x70, 0x10, 0xE1, 0xF0, 0xC4, 0x20, 0x08, 0x70, 0x00, 0x40, 0x82, 0x04, + 0x04, 0x61, 0xB1, 0x67, 0xF2, 0x02, 0xB1, 0x07, 0xE1, 0xF0, 0x00, 0x00, 0xC4, 0x30, 0x57, 0x21, + 0x08, 0x70, 0x00, 0x40, 0x26, 0x72, 0x82, 0x04, 0x04, 0x61, 0xB1, 0x67, 0xF2, 0x02, 0xB1, 0x07, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x8B, 0x8E, 0x00, 0x00, 0x08, 0x70, + 0x1C, 0xE1, 0x08, 0x60, 0x00, 0x30, 0x2C, 0x70, 0x04, 0xE9, 0xB9, 0x76, 0x04, 0x01, 0x08, 0xE0, + 0x00, 0x40, 0xB9, 0x76, 0x08, 0x01, 0x2C, 0xE0, 0x70, 0x10, 0x04, 0xD1, 0xB1, 0xDE, 0x04, 0x2A, + 0xAB, 0xC0, 0x00, 0x00, 0xF2, 0xFC, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xC1, 0x61, 0x01, 0x61, + 0x01, 0x70, 0xC9, 0x61, 0x08, 0x00, 0x04, 0x61, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x67, 0x14, 0x40, + 0x48, 0x61, 0x08, 0x00, 0x11, 0x16, 0x11, 0x07, 0x40, 0x61, 0x2C, 0x10, 0x10, 0x00, 0x61, 0x00, + 0x3C, 0x10, 0x10, 0x00, 0xC1, 0x61, 0x01, 0x61, 0x01, 0x70, 0xC9, 0x61, 0x08, 0x00, 0x04, 0x61, + 0x08, 0x70, 0x00, 0x40, 0xB9, 0x67, 0x14, 0x50, 0x48, 0x61, 0x08, 0x00, 0x11, 0x16, 0x11, 0x07, + 0x40, 0x61, 0x2C, 0x10, 0x10, 0x00, 0x61, 0x00, 0x3C, 0x10, 0x24, 0x00, 0xD9, 0x41, 0x08, 0x00, + 0x01, 0x61, 0x01, 0x70, 0xC9, 0x61, 0x1C, 0x00, 0xC1, 0x21, 0x04, 0x61, 0x0C, 0x20, 0x28, 0x00, + 0xB9, 0xF1, 0x18, 0x00, 0x99, 0x60, 0xD3, 0x16, 0x8B, 0xBD, 0x00, 0x00, 0x04, 0x61, 0x08, 0x70, + 0x00, 0x40, 0xB9, 0x67, 0x78, 0x10, 0x48, 0x61, 0x1C, 0x00, 0x38, 0xF1, 0x18, 0x00, 0x40, 0x21, + 0x11, 0x16, 0x11, 0x07, 0x58, 0x41, 0x08, 0x00, 0x2C, 0x10, 0x24, 0x00, 0x61, 0x00, 0x00, 0x00, + 0x3C, 0x10, 0x10, 0x00, 0xC1, 0x61, 0x01, 0x61, 0x01, 0x70, 0xC9, 0x61, 0x08, 0x00, 0x04, 0x61, + 0x99, 0x60, 0xD2, 0x16, 0x48, 0x61, 0x08, 0x00, 0x11, 0x16, 0x11, 0x07, 0x40, 0x61, 0x2C, 0x10, + 0x10, 0x00, 0x61, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xC1, 0x61, 0x01, 0x61, 0x01, 0x70, 0xC9, 0x61, + 0x08, 0x00, 0x08, 0x70, 0x00, 0x40, 0x38, 0x67, 0x08, 0x70, 0xB9, 0x67, 0x08, 0x70, 0x48, 0x61, + 0x08, 0x00, 0x11, 0x16, 0x11, 0x07, 0x40, 0x61, 0x2C, 0x10, 0x10, 0x00, 0x61, 0x00, 0x00, 0x00, + 0x08, 0x70, 0x04, 0x00, 0x24, 0x74, 0x26, 0x27, 0x08, 0x70, 0xFF, 0xBF, 0x57, 0x26, 0x2C, 0x70, + 0x00, 0xC0, 0xB1, 0x42, 0x26, 0x27, 0x0C, 0x40, 0x04, 0x40, 0x08, 0x70, 0x00, 0x40, 0x26, 0x47, + 0x26, 0x42, 0xB1, 0x34, 0x0C, 0x40, 0x10, 0x40, 0x26, 0x47, 0x26, 0x42, 0x2C, 0x70, 0x08, 0x40, + 0xB1, 0x54, 0x26, 0x27, 0xB1, 0x62, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x40, 0x2C, 0x70, 0x08, 0x40, + 0x57, 0x26, 0x26, 0x27, 0x30, 0x72, 0x6C, 0x70, 0x00, 0x01, 0xB1, 0x72, 0xE1, 0xF0, 0x00, 0x00, + 0x08, 0x70, 0x00, 0x40, 0x2C, 0x70, 0x08, 0x40, 0x57, 0x26, 0x26, 0x27, 0x30, 0x72, 0x1C, 0x60, + 0x01, 0x01, 0x56, 0x76, 0xB1, 0x72, 0xE1, 0xF0, 0x08, 0x70, 0x04, 0x00, 0x24, 0x74, 0x26, 0x27, + 0x57, 0x26, 0xB1, 0x32, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0x57, 0x26, 0x2C, 0x70, + 0x0C, 0x40, 0x26, 0x72, 0x30, 0x27, 0xE1, 0xF0, 0x08, 0x70, 0x0F, 0x00, 0xD6, 0x72, 0x3C, 0x10, + 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xE2, 0x06, 0xC3, 0x82, 0x04, 0x1C, 0x70, 0x01, 0x10, 0x56, 0xE7, + 0x08, 0xD0, 0x00, 0x30, 0x8B, 0x8E, 0x00, 0x00, 0xB9, 0xED, 0x04, 0x01, 0xEB, 0x61, 0x00, 0x00, + 0x0C, 0x20, 0xE8, 0x03, 0xAB, 0xC0, 0x00, 0x00, 0xC4, 0xC0, 0x92, 0xF5, 0x50, 0xC1, 0x2C, 0x10, + 0x10, 0x00, 0xE1, 0xF0, 0x34, 0x18, 0x08, 0x50, 0x00, 0x80, 0xB9, 0xF1, 0x04, 0x00, 0xB1, 0x01, + 0x04, 0x70, 0x2C, 0x50, 0xB8, 0x6E, 0xC6, 0x73, 0x82, 0x0F, 0x04, 0x63, 0x56, 0x67, 0x26, 0x61, + 0x2F, 0x47, 0x02, 0x00, 0x10, 0xF6, 0x10, 0x44, 0x24, 0x71, 0x76, 0x4F, 0x13, 0x44, 0x26, 0x45, + 0x10, 0x44, 0x91, 0x46, 0xF2, 0xF1, 0x38, 0xF1, 0x04, 0x00, 0x30, 0x21, 0x24, 0x18, 0xE1, 0xF0, + 0x34, 0x18, 0x08, 0x70, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0xC1, 0xE1, 0x2C, 0x40, 0x5C, 0x04, + 0x06, 0xE2, 0x06, 0x27, 0x2C, 0x20, 0x80, 0x02, 0x36, 0x42, 0x08, 0x30, 0x00, 0x80, 0x2C, 0x30, + 0x54, 0x71, 0x77, 0x41, 0x0C, 0xF0, 0x5C, 0x01, 0xF1, 0xF0, 0x0C, 0x20, 0x98, 0x01, 0x04, 0x30, + 0x0C, 0x40, 0x80, 0x04, 0x0C, 0x50, 0x00, 0x01, 0x04, 0x61, 0x0C, 0xF0, 0x98, 0x03, 0xF1, 0xF0, + 0xC4, 0x20, 0x82, 0x26, 0x04, 0x21, 0x4B, 0x3D, 0x00, 0x00, 0x0C, 0x50, 0x80, 0x04, 0x0C, 0x70, + 0x88, 0x04, 0x06, 0x2E, 0x2C, 0x50, 0xC8, 0x01, 0x30, 0x67, 0x5C, 0x60, 0xFF, 0x03, 0x57, 0x61, + 0xB1, 0x62, 0x30, 0x67, 0x77, 0x64, 0x5C, 0x60, 0xFC, 0x0F, 0xB9, 0x62, 0x04, 0x00, 0x30, 0x67, + 0x24, 0x74, 0x77, 0x69, 0xC6, 0x75, 0x5C, 0x60, 0xFC, 0x0F, 0xB9, 0x62, 0x08, 0x00, 0x24, 0x2C, + 0x92, 0xEC, 0x04, 0x20, 0x4B, 0x3D, 0x00, 0x00, 0x38, 0x20, 0x84, 0x04, 0xF2, 0x03, 0x08, 0x20, + 0x01, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x08, 0x20, 0x00, 0x30, 0x34, 0x18, 0x2C, 0x20, + 0x00, 0x40, 0xC1, 0xE1, 0x8B, 0x74, 0x00, 0x00, 0x08, 0x70, 0x00, 0xFF, 0x2C, 0x70, 0xFF, 0x00, + 0x08, 0x60, 0x00, 0xAA, 0x0C, 0x50, 0x55, 0x00, 0x56, 0x72, 0x26, 0x56, 0xC6, 0x75, 0x06, 0xE2, + 0x92, 0x19, 0x0C, 0x70, 0x00, 0x10, 0xD6, 0x72, 0x82, 0x18, 0x0C, 0x20, 0x98, 0x01, 0x04, 0x34, + 0x0C, 0x40, 0xC4, 0x01, 0x0C, 0xF0, 0x04, 0x04, 0xF1, 0xF0, 0x38, 0x70, 0x80, 0x04, 0xC6, 0x27, + 0x82, 0x05, 0x08, 0x70, 0x02, 0x00, 0x66, 0xE7, 0xF2, 0x08, 0x04, 0x61, 0x99, 0x60, 0xD4, 0x16, + 0xF2, 0x08, 0x06, 0xE6, 0x2C, 0xE0, 0x55, 0x01, 0x06, 0x2E, 0x04, 0x30, 0xCB, 0x70, 0x00, 0x00, + 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x08, 0x40, + 0x00, 0x00, 0x06, 0xC2, 0x08, 0x20, 0x00, 0x00, 0x2C, 0x20, 0x80, 0x02, 0x2C, 0x40, 0x5C, 0x04, + 0x06, 0xE3, 0x36, 0x42, 0x08, 0x30, 0x00, 0x80, 0x2C, 0x30, 0x54, 0x71, 0x77, 0x41, 0x0C, 0xF0, + 0x5C, 0x01, 0xF1, 0xF0, 0x0C, 0xF0, 0xA4, 0x02, 0xF1, 0xF0, 0x04, 0x30, 0x0C, 0x20, 0x98, 0x01, + 0x0C, 0x40, 0x80, 0x04, 0x0C, 0x50, 0x00, 0x01, 0x06, 0x63, 0x0C, 0xF0, 0x98, 0x03, 0xF1, 0xF0, + 0xC4, 0x20, 0x82, 0x4B, 0x0C, 0xD0, 0x00, 0x10, 0x66, 0xDE, 0x0C, 0xF0, 0x80, 0x04, 0xB9, 0xD0, + 0x84, 0x04, 0x06, 0x6C, 0x0C, 0x40, 0x88, 0x04, 0x2C, 0xF0, 0xC8, 0x01, 0x78, 0x76, 0x02, 0x00, + 0x78, 0x56, 0x04, 0x00, 0x77, 0x71, 0x77, 0x51, 0x57, 0x5A, 0x57, 0x75, 0x66, 0x75, 0x70, 0x56, + 0x24, 0x66, 0x77, 0x51, 0x66, 0x75, 0xB1, 0x74, 0x24, 0x44, 0xC6, 0x4F, 0x92, 0xF0, 0x0C, 0x30, + 0xC0, 0x01, 0x0C, 0x20, 0x84, 0x04, 0xAB, 0x72, 0x00, 0x00, 0xB9, 0x20, 0x80, 0x04, 0x04, 0x30, + 0x0C, 0x20, 0x38, 0x00, 0x0C, 0xF0, 0xE8, 0x02, 0xF1, 0xF0, 0x0C, 0x20, 0x58, 0x01, 0x04, 0x30, + 0x0C, 0x40, 0x80, 0x04, 0x0C, 0x50, 0x00, 0x01, 0x0C, 0xF0, 0x34, 0x03, 0xF1, 0xF0, 0x0C, 0xF0, + 0xC0, 0x02, 0xF1, 0xF0, 0x0C, 0x20, 0x98, 0x01, 0x04, 0x34, 0x0C, 0x40, 0xC4, 0x01, 0x0C, 0xF0, + 0x04, 0x04, 0xF1, 0xF0, 0x38, 0x70, 0x80, 0x04, 0xC6, 0x27, 0x82, 0x0A, 0x08, 0x20, 0x02, 0x00, + 0x2C, 0x20, 0x00, 0x10, 0x66, 0x2E, 0xF2, 0x05, 0x08, 0x20, 0x01, 0x00, 0xF2, 0x02, 0x06, 0x2D, + 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x18, 0x70, + 0xE6, 0x16, 0x1C, 0x60, 0x10, 0x00, 0x56, 0x76, 0x06, 0x43, 0x64, 0x78, 0xF7, 0x40, 0x04, 0x30, + 0x99, 0x70, 0xE6, 0x16, 0x06, 0xD2, 0x0C, 0xF0, 0xC4, 0x01, 0xF1, 0xF0, 0x18, 0x20, 0xE6, 0x16, + 0xEB, 0x41, 0x00, 0x00, 0x18, 0x20, 0xE6, 0x16, 0xCB, 0x49, 0x00, 0x00, 0xAB, 0xDD, 0x00, 0x00, + 0x2B, 0x31, 0x00, 0x00, 0x0C, 0xE0, 0x15, 0x00, 0xB4, 0xE1, 0x82, 0x09, 0x04, 0x21, 0x0C, 0x30, + 0x00, 0x20, 0x4B, 0x38, 0x00, 0x00, 0x8B, 0x35, 0x00, 0x00, 0xF2, 0xF7, 0x08, 0x60, 0x00, 0x30, + 0x0C, 0x70, 0x00, 0x49, 0x0C, 0x50, 0x40, 0x4E, 0x06, 0x2D, 0x26, 0x76, 0x26, 0x56, 0x30, 0x67, + 0x24, 0x74, 0xC6, 0x75, 0x5C, 0x60, 0xFF, 0x0F, 0xA1, 0x62, 0x24, 0x22, 0x92, 0xF9, 0x50, 0xC1, + 0x08, 0x20, 0x00, 0xAA, 0x2C, 0x20, 0x55, 0x00, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0x2D, 0x0C, 0x20, 0x80, 0x02, 0x0C, 0x30, 0xD2, 0x02, + 0x4B, 0x84, 0x00, 0x00, 0x08, 0x70, 0x00, 0xAA, 0x2C, 0x70, 0x55, 0x00, 0xD6, 0x72, 0x06, 0xE2, + 0x06, 0x2D, 0x82, 0x03, 0x6C, 0xE0, 0x00, 0x20, 0x0C, 0x70, 0x00, 0x20, 0xD6, 0x7E, 0x82, 0x07, + 0x06, 0x3E, 0x0C, 0x20, 0x80, 0x02, 0xCB, 0x7C, 0x00, 0x00, 0x66, 0xE2, 0x06, 0x2E, 0x04, 0x31, + 0xB9, 0x00, 0xB4, 0x15, 0xCB, 0x70, 0x00, 0x00, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x14, 0x00, 0xD9, 0xC1, 0x04, 0x00, 0x08, 0xE0, 0x00, 0x80, + 0x2C, 0xE0, 0x0C, 0xDC, 0x28, 0x7E, 0x1C, 0x00, 0x28, 0x6E, 0x56, 0x00, 0x28, 0xDE, 0x1E, 0x00, + 0x28, 0x3E, 0x5A, 0x00, 0xB1, 0xB1, 0x28, 0xBE, 0x54, 0x00, 0x3F, 0x26, 0x07, 0x00, 0x3F, 0x33, + 0x0D, 0x00, 0x43, 0x33, 0x43, 0x22, 0x26, 0xB7, 0x0C, 0xF0, 0xBC, 0x00, 0xF1, 0xF0, 0x28, 0x7E, + 0x58, 0x00, 0x23, 0xBB, 0x2F, 0x37, 0x0D, 0x00, 0x06, 0xC2, 0x43, 0x33, 0x43, 0x2B, 0x0C, 0xF0, + 0x98, 0x00, 0xF1, 0xF0, 0x23, 0xCC, 0x57, 0x28, 0x66, 0x2C, 0x08, 0x60, 0x00, 0x40, 0xB9, 0x26, + 0x84, 0x70, 0x58, 0xC1, 0x04, 0x00, 0x30, 0xB1, 0x2C, 0x10, 0x14, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x08, 0x60, 0x00, 0x30, 0x38, 0x76, 0x28, 0x00, 0xD4, 0x74, 0x92, 0xFD, 0xE1, 0xF0, 0x00, 0x00, + 0x08, 0x60, 0x00, 0x30, 0x38, 0x76, 0x40, 0x01, 0x23, 0x77, 0xB9, 0x76, 0x40, 0x01, 0xE1, 0xF0, + 0x08, 0x70, 0x00, 0x30, 0x38, 0x27, 0x40, 0x01, 0xF7, 0x2F, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, + 0x8B, 0x8F, 0x00, 0x00, 0x04, 0x70, 0xC6, 0x27, 0x82, 0x0D, 0x8B, 0x8E, 0x00, 0x00, 0x08, 0x70, + 0x00, 0x30, 0x08, 0x60, 0x00, 0x80, 0xB9, 0x67, 0x40, 0x01, 0x38, 0x77, 0x3C, 0x01, 0xB9, 0x70, + 0xB4, 0x15, 0x30, 0xF1, 0x06, 0x27, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x06, 0x72, 0x77, 0x78, + 0xCC, 0x70, 0x15, 0x00, 0x3C, 0x10, 0x14, 0x00, 0xD9, 0xC1, 0x04, 0x00, 0xB1, 0xB1, 0x0C, 0xE0, + 0xFF, 0xFF, 0x56, 0xE2, 0x82, 0x4E, 0xCC, 0x70, 0x15, 0x00, 0xD2, 0x1B, 0xCC, 0x70, 0x10, 0x00, + 0x82, 0x3B, 0xCC, 0x70, 0x10, 0x00, 0xD2, 0x08, 0xC4, 0x71, 0x82, 0x32, 0xC4, 0x72, 0x92, 0x50, + 0x99, 0xE0, 0xDE, 0x16, 0xF2, 0x66, 0xCC, 0x70, 0x13, 0x00, 0x82, 0x32, 0xCC, 0x70, 0x13, 0x00, + 0xD2, 0x32, 0xCC, 0x70, 0x12, 0x00, 0x92, 0x44, 0x99, 0xE0, 0xDC, 0x16, 0xFA, 0xA6, 0x00, 0x00, + 0xCC, 0x70, 0x23, 0x00, 0x82, 0x34, 0xCC, 0x70, 0x23, 0x00, 0xD2, 0x0E, 0xCC, 0x70, 0x21, 0x00, + 0x82, 0x25, 0xCC, 0x70, 0x21, 0x00, 0xD2, 0x28, 0xCC, 0x70, 0x20, 0x00, 0x92, 0x31, 0xA9, 0xE0, + 0xCC, 0x16, 0xFA, 0x93, 0x00, 0x00, 0xCC, 0x70, 0x81, 0x00, 0x82, 0x24, 0xCC, 0x70, 0xE0, 0x00, + 0x82, 0x24, 0xCC, 0x70, 0x80, 0x00, 0x92, 0x24, 0x99, 0xE0, 0xD6, 0x16, 0xF2, 0x7A, 0x99, 0x70, + 0xDF, 0x16, 0xFA, 0x83, 0x00, 0x00, 0x99, 0xE0, 0xDD, 0x16, 0xFA, 0x7F, 0x00, 0x00, 0x99, 0xE0, + 0xDB, 0x16, 0xF2, 0x7B, 0x99, 0xE0, 0xDA, 0x16, 0xF2, 0x78, 0xA9, 0xE0, 0xCE, 0x16, 0xF2, 0x75, + 0x99, 0xE0, 0xD9, 0x16, 0xF2, 0x72, 0xA9, 0xE0, 0xCA, 0x16, 0xF2, 0x69, 0xA9, 0xE0, 0xC8, 0x16, + 0xF2, 0x6C, 0x99, 0xE0, 0xD7, 0x16, 0xF2, 0x69, 0x99, 0xE0, 0xD5, 0x16, 0xF2, 0x66, 0xCC, 0x70, + 0x33, 0x00, 0x82, 0x37, 0xCC, 0x70, 0x33, 0x00, 0xD2, 0x0A, 0xCC, 0x70, 0x22, 0x00, 0x82, 0x57, + 0xCC, 0x70, 0x30, 0x00, 0x82, 0x31, 0xC4, 0x72, 0x92, 0x58, 0xF2, 0x0B, 0xCC, 0x70, 0x90, 0x00, + 0x82, 0x4B, 0xCC, 0x70, 0xE1, 0x00, 0x82, 0x4E, 0xCC, 0x70, 0x80, 0x00, 0x92, 0x4E, 0xF2, 0x41, + 0xCB, 0x52, 0x00, 0x00, 0xC4, 0xE0, 0x82, 0x0E, 0x08, 0x50, 0x00, 0x40, 0x38, 0x75, 0x54, 0x10, + 0x08, 0x40, 0x00, 0x80, 0x66, 0x74, 0xB9, 0x70, 0xB0, 0x15, 0x14, 0x71, 0xB9, 0x75, 0x54, 0x10, + 0xF2, 0x3C, 0xB8, 0x50, 0xB0, 0x15, 0x32, 0x0A, 0x08, 0x70, 0xFF, 0x7F, 0x2C, 0x70, 0xFF, 0xFF, + 0x56, 0x75, 0x08, 0x50, 0x00, 0x40, 0xB9, 0x75, 0x54, 0x10, 0xB9, 0x00, 0xB0, 0x15, 0xF2, 0x2D, + 0x8B, 0x88, 0x00, 0x00, 0xF2, 0x2A, 0x04, 0x20, 0x4B, 0x62, 0x00, 0x00, 0x0C, 0xB0, 0x40, 0x01, + 0x08, 0xE0, 0x00, 0x30, 0x08, 0xD0, 0x30, 0x00, 0x06, 0xCE, 0x26, 0xBE, 0x24, 0xD1, 0x08, 0x60, + 0x00, 0x80, 0xB8, 0x7E, 0x40, 0x01, 0x32, 0xFE, 0x38, 0x7E, 0x28, 0x00, 0xD4, 0x74, 0x92, 0xFD, + 0xB1, 0x6B, 0x38, 0x7C, 0x3C, 0x01, 0xC6, 0x7D, 0x92, 0xF5, 0x04, 0x74, 0xF1, 0x70, 0xF2, 0xF0, + 0x2B, 0xE5, 0x00, 0x00, 0xF2, 0x0A, 0xEB, 0x61, 0x00, 0x00, 0xF2, 0x07, 0xEB, 0xE3, 0x00, 0x00, + 0xF2, 0x04, 0x13, 0x2E, 0xEB, 0x1E, 0x01, 0x00, 0x58, 0xC1, 0x04, 0x00, 0x30, 0xB1, 0x2C, 0x10, + 0x14, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x08, 0xE0, 0x00, 0x30, 0x0C, 0xD0, + 0x00, 0x01, 0x26, 0xDE, 0x8B, 0x8E, 0x00, 0x00, 0x06, 0x2D, 0x04, 0x30, 0x0C, 0x40, 0x10, 0x00, + 0x0C, 0xF0, 0xD8, 0x01, 0xF1, 0xF0, 0x38, 0x7E, 0x28, 0x00, 0xD4, 0x72, 0x82, 0x05, 0x04, 0x72, + 0xB9, 0x7E, 0x28, 0x00, 0xF2, 0xF0, 0x38, 0x7E, 0x40, 0x01, 0xB9, 0x7E, 0x40, 0x01, 0x50, 0xC1, + 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x18, 0x0C, 0x20, 0x00, 0x00, 0x04, 0x30, + 0x0C, 0x40, 0x20, 0x00, 0xC1, 0xE1, 0x0C, 0xF0, 0xD8, 0x01, 0xF1, 0xF0, 0x06, 0x2E, 0x0C, 0x20, + 0x00, 0x27, 0x04, 0x30, 0x0C, 0x40, 0x20, 0x00, 0x0C, 0xF0, 0xD8, 0x01, 0xF1, 0xF0, 0x08, 0x70, + 0x00, 0x80, 0x2C, 0x70, 0x00, 0xFA, 0x38, 0x67, 0xF8, 0x01, 0xB9, 0x60, 0x00, 0x00, 0x38, 0x67, + 0xFC, 0x01, 0xB9, 0x60, 0x04, 0x00, 0x08, 0x60, 0x00, 0x80, 0x38, 0x66, 0x04, 0xDC, 0xB9, 0x60, + 0x08, 0x00, 0x38, 0x67, 0xF0, 0x01, 0xB9, 0x60, 0x0C, 0x00, 0x38, 0x67, 0xF4, 0x01, 0x38, 0x77, + 0xCC, 0x01, 0xC4, 0x60, 0xB9, 0x70, 0x1C, 0x00, 0x08, 0x70, 0x35, 0x45, 0x2C, 0x70, 0x01, 0x32, + 0xB9, 0x70, 0x24, 0x00, 0x08, 0x70, 0x01, 0xC6, 0x2C, 0x70, 0x01, 0x45, 0xB9, 0x60, 0x10, 0x00, + 0xB9, 0x70, 0x28, 0x00, 0x82, 0x04, 0x08, 0x70, 0x02, 0x65, 0xF2, 0x03, 0x08, 0x70, 0x02, 0x02, + 0xB9, 0x70, 0x2C, 0x00, 0x04, 0x71, 0xB9, 0x70, 0x34, 0x00, 0x08, 0x70, 0x80, 0x07, 0x2C, 0x70, + 0x38, 0x04, 0xB9, 0x70, 0x40, 0x00, 0x08, 0x70, 0x18, 0x00, 0x24, 0x7E, 0xB9, 0x70, 0x44, 0x00, + 0x08, 0x70, 0x03, 0x01, 0x2C, 0x70, 0x02, 0x17, 0xB9, 0x70, 0x48, 0x00, 0x08, 0x70, 0x06, 0x17, + 0x2C, 0x70, 0x0B, 0x17, 0xB9, 0x70, 0x4C, 0x00, 0x08, 0x70, 0xFF, 0xFF, 0xB9, 0x70, 0x50, 0x00, + 0x08, 0x70, 0x17, 0x00, 0x24, 0x7E, 0xB9, 0x70, 0x54, 0x00, 0x08, 0x60, 0x00, 0x80, 0x08, 0x70, + 0xFF, 0x00, 0x2C, 0x60, 0x0C, 0xDC, 0x2C, 0x70, 0x00, 0xFF, 0xB9, 0x70, 0x58, 0x00, 0x18, 0x76, + 0x2D, 0x00, 0xB9, 0x00, 0x30, 0x00, 0x0C, 0xE0, 0x00, 0x27, 0xB9, 0x70, 0x5C, 0x00, 0x18, 0x76, + 0x2C, 0x00, 0xB9, 0xE0, 0x70, 0x00, 0xB9, 0x70, 0x60, 0x00, 0x28, 0x76, 0x1E, 0x00, 0x28, 0x66, + 0x1C, 0x00, 0x57, 0x78, 0x66, 0x76, 0x08, 0x60, 0x00, 0x80, 0x2C, 0x60, 0x48, 0xDF, 0xB9, 0x70, + 0x64, 0x00, 0x28, 0x76, 0x32, 0x00, 0x28, 0x66, 0x2C, 0x00, 0x57, 0x78, 0x66, 0x76, 0xB9, 0x70, + 0x68, 0x00, 0x0C, 0x60, 0x00, 0x49, 0x08, 0x70, 0x00, 0x30, 0x26, 0x67, 0x2C, 0x70, 0x00, 0xA0, + 0xB9, 0x70, 0x6C, 0x00, 0x0C, 0x70, 0xFC, 0x0A, 0xB9, 0x70, 0x78, 0x00, 0xB9, 0x60, 0x74, 0x00, + 0x0C, 0x70, 0x28, 0x16, 0x08, 0x60, 0x00, 0x80, 0x66, 0x76, 0xB9, 0x70, 0x38, 0x00, 0x04, 0x72, + 0xB9, 0x70, 0x18, 0x00, 0xAB, 0x9E, 0x00, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x0C, 0xE0, 0xFC, 0x0A, 0x18, 0x7E, 0x70, 0x0A, 0x06, 0x43, + 0x04, 0x30, 0xC6, 0x73, 0x06, 0xD2, 0x82, 0x1B, 0x0C, 0xF0, 0xD8, 0x01, 0xF1, 0xF0, 0x38, 0x7E, + 0x38, 0x0A, 0x0C, 0x50, 0x70, 0x0A, 0xB1, 0x7D, 0x0C, 0x70, 0x38, 0x15, 0x26, 0x5E, 0x04, 0x61, + 0xB0, 0x37, 0x82, 0x06, 0x06, 0x46, 0x57, 0x41, 0x26, 0x4D, 0xB1, 0x34, 0x24, 0x61, 0x24, 0x74, + 0xC6, 0x75, 0x92, 0xF7, 0x18, 0x3E, 0x70, 0x0A, 0x99, 0x0E, 0x70, 0x0A, 0x50, 0xC1, 0x06, 0x23, + 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x04, 0x70, 0x06, 0x67, 0x3F, 0x57, 0x03, 0x00, + 0xC4, 0x50, 0x02, 0x08, 0x2F, 0x57, 0x02, 0x00, 0x10, 0x55, 0x24, 0x71, 0x26, 0x65, 0x13, 0x66, + 0xF2, 0xF6, 0x06, 0x26, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x30, 0xE2, + 0x08, 0x70, 0xFF, 0x00, 0x2C, 0x70, 0xFF, 0xFF, 0x56, 0xE7, 0x6C, 0xE0, 0x00, 0x0C, 0xB1, 0xE2, + 0x57, 0x31, 0x06, 0xD2, 0xCB, 0xAE, 0x00, 0x00, 0x57, 0x2C, 0x66, 0x2E, 0xB1, 0x2D, 0x50, 0xC1, + 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x50, 0x00, 0xD9, 0xC1, 0x40, 0x00, + 0x4B, 0xB8, 0x00, 0x00, 0x06, 0x21, 0x0C, 0x30, 0x10, 0x00, 0x0B, 0xAC, 0x00, 0x00, 0x86, 0xE2, + 0x82, 0x25, 0x06, 0x21, 0x06, 0x3E, 0xCB, 0xAF, 0x00, 0x00, 0x98, 0x70, 0xD8, 0x16, 0x82, 0x07, + 0x6B, 0xB8, 0x00, 0x00, 0x06, 0x7E, 0x57, 0x71, 0x26, 0x71, 0xB1, 0x27, 0x08, 0xD0, 0x00, 0x30, + 0x0C, 0xC0, 0x04, 0x01, 0x26, 0xCD, 0x8B, 0x8E, 0x00, 0x00, 0x06, 0x2C, 0x06, 0x31, 0x04, 0x4B, + 0x0C, 0xF0, 0x5C, 0x01, 0xF1, 0xF0, 0x38, 0x7D, 0x28, 0x00, 0xD4, 0x72, 0x82, 0x05, 0x04, 0x72, + 0xB9, 0x7D, 0x28, 0x00, 0xF2, 0xF1, 0x0B, 0x8F, 0x00, 0x00, 0x18, 0x70, 0xED, 0x16, 0xC4, 0x71, + 0x92, 0x11, 0x6B, 0x36, 0x01, 0x00, 0x98, 0x70, 0xEA, 0x16, 0x82, 0x05, 0xC4, 0x71, 0x92, 0x0A, + 0xC4, 0xE0, 0x92, 0x08, 0x08, 0x60, 0xDB, 0xDB, 0x08, 0x70, 0x00, 0x30, 0xB9, 0x67, 0x04, 0x01, + 0x04, 0xE1, 0x18, 0x60, 0xD5, 0x16, 0xC4, 0x62, 0x92, 0x12, 0x04, 0x61, 0x99, 0x60, 0xD5, 0x16, + 0x18, 0x70, 0xEA, 0x16, 0x04, 0x21, 0xC4, 0x70, 0x92, 0x0B, 0x08, 0x70, 0xA0, 0x8C, 0x2C, 0x70, + 0x0E, 0xD0, 0x08, 0x60, 0x00, 0x30, 0xB9, 0x76, 0x04, 0x01, 0xF2, 0x02, 0x06, 0x2E, 0x58, 0xC1, + 0x40, 0x00, 0x2C, 0x10, 0x50, 0x00, 0xE1, 0xF0, 0x0C, 0x50, 0x00, 0x00, 0x0C, 0x70, 0x78, 0x00, + 0x34, 0x54, 0x04, 0x60, 0x30, 0x47, 0x34, 0x74, 0xC6, 0x75, 0x26, 0x64, 0x92, 0xFC, 0xB9, 0x60, + 0x7C, 0x00, 0xE1, 0xF0, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, + 0x0C, 0x70, 0xFC, 0x0A, 0x38, 0x27, 0x38, 0x0A, 0x08, 0x60, 0xE0, 0x00, 0xD6, 0x26, 0x92, 0x17, + 0xA8, 0x77, 0x14, 0x03, 0x82, 0x34, 0xCC, 0x70, 0xFF, 0x0F, 0x82, 0x31, 0x26, 0x77, 0x06, 0x27, + 0x57, 0x22, 0x36, 0x27, 0x0C, 0x30, 0x64, 0x00, 0xCB, 0x14, 0x00, 0x00, 0x2C, 0x20, 0x90, 0x01, + 0xCC, 0x20, 0x58, 0x02, 0xC2, 0x24, 0x0C, 0x20, 0x58, 0x02, 0xF2, 0x21, 0x28, 0x27, 0x18, 0x03, + 0x1C, 0x70, 0xA5, 0x01, 0x26, 0x72, 0xCC, 0x70, 0xE8, 0x03, 0xD2, 0x0F, 0x3C, 0x20, 0x8D, 0x05, + 0x06, 0x32, 0x6B, 0x13, 0x00, 0x00, 0x0C, 0x30, 0xE9, 0x03, 0xCB, 0x14, 0x00, 0x00, 0x0C, 0x70, + 0x8D, 0x05, 0x3F, 0x22, 0x07, 0x00, 0xF2, 0x0B, 0xCC, 0x20, 0x8D, 0x05, 0xC2, 0x08, 0x3C, 0x20, + 0x8D, 0x05, 0x04, 0x33, 0xCB, 0x14, 0x00, 0x00, 0x2C, 0x20, 0x8D, 0x05, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x01, 0x00, 0x34, 0x14, 0x2C, 0x70, 0xF8, 0x24, 0xB1, 0x71, + 0x30, 0x71, 0x14, 0x61, 0xC4, 0x70, 0x26, 0x67, 0xB1, 0x61, 0x92, 0xFB, 0x24, 0x14, 0xE1, 0xF0, + 0x06, 0x72, 0x57, 0x71, 0x26, 0x27, 0x34, 0x14, 0xF7, 0x20, 0xB1, 0x21, 0x30, 0x71, 0x14, 0x61, + 0xC4, 0x70, 0x26, 0x67, 0xB1, 0x61, 0x92, 0xFB, 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0x04, 0x3A, + 0xB1, 0xF1, 0xCB, 0x14, 0x00, 0x00, 0x23, 0x32, 0x04, 0x21, 0xCB, 0x6F, 0x00, 0x00, 0x04, 0x21, + 0x4B, 0x6E, 0x00, 0x00, 0x04, 0x24, 0x04, 0x30, 0xCB, 0x55, 0x00, 0x00, 0xCB, 0x51, 0x00, 0x00, + 0x04, 0x24, 0x04, 0x31, 0xCB, 0x55, 0x00, 0x00, 0x04, 0x21, 0x0B, 0x6F, 0x00, 0x00, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, 0x6B, 0xBE, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x06, 0x72, 0x06, 0x62, 0xD7, 0x63, 0x57, 0x71, 0x3F, 0x77, 0x06, 0x00, + 0x26, 0x27, 0x34, 0x14, 0xD7, 0x21, 0xB1, 0xF1, 0x6B, 0xBE, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x04, 0x20, 0xB1, 0xF1, 0x6B, 0x53, 0x00, 0x00, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x08, 0x60, 0x00, 0x00, 0x08, 0x70, 0x00, 0x00, 0x2C, 0x60, 0x80, 0x00, + 0x2C, 0x70, 0x1C, 0x02, 0x36, 0x76, 0xC4, 0x70, 0x34, 0x14, 0xB1, 0xF1, 0x32, 0x02, 0x24, 0x73, + 0x06, 0x47, 0x08, 0x50, 0x00, 0x80, 0x67, 0x41, 0x04, 0x70, 0x2C, 0x50, 0xB8, 0x6F, 0x14, 0x21, + 0xC6, 0x74, 0x04, 0x34, 0x26, 0x36, 0x32, 0x05, 0x30, 0xF5, 0x24, 0x54, 0xB1, 0xF6, 0xF2, 0x02, + 0xB1, 0x26, 0x24, 0x71, 0xCC, 0x70, 0x80, 0x00, 0x82, 0x03, 0x06, 0x63, 0xF2, 0xF2, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x28, 0x60, 0xCC, 0x16, 0xCC, 0x60, 0xFF, 0xFF, 0x92, 0x10, 0x38, 0x60, + 0x08, 0x0B, 0xD4, 0x61, 0x08, 0x60, 0x00, 0x80, 0x2C, 0x60, 0x0C, 0xDC, 0x82, 0x04, 0x38, 0x66, + 0x44, 0x00, 0xF2, 0x03, 0x38, 0x66, 0x40, 0x00, 0xA9, 0x60, 0xCC, 0x16, 0x28, 0x60, 0xCE, 0x16, + 0xCC, 0x60, 0xFF, 0xFF, 0x92, 0x07, 0x08, 0x60, 0x00, 0x80, 0x38, 0x66, 0x48, 0xDC, 0xA9, 0x60, + 0xCE, 0x16, 0xE1, 0xF0, 0x08, 0x40, 0x00, 0x80, 0x34, 0x14, 0x08, 0x70, 0x00, 0x80, 0x2C, 0x40, + 0x0C, 0xDC, 0xB1, 0xF1, 0x2C, 0x70, 0x1A, 0xDC, 0x0C, 0x60, 0xBA, 0x16, 0x24, 0x4A, 0x14, 0x21, + 0x10, 0x57, 0xCC, 0x50, 0xFF, 0x00, 0x82, 0x0D, 0x18, 0x37, 0x04, 0x00, 0xCC, 0x30, 0xFF, 0x00, + 0x82, 0x08, 0x2F, 0xF5, 0x05, 0x00, 0x26, 0x5F, 0xD7, 0x51, 0x26, 0x53, 0xA1, 0x56, 0xF2, 0x02, + 0xA1, 0x26, 0x34, 0x71, 0xC6, 0x74, 0x34, 0x62, 0x92, 0xEC, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, + 0x34, 0x14, 0x0C, 0x20, 0xFC, 0x0A, 0x04, 0x30, 0x0C, 0x40, 0xB4, 0x0A, 0xB1, 0xF1, 0x0C, 0xF0, + 0xB0, 0x01, 0xF1, 0xF0, 0xAB, 0xC6, 0x00, 0x00, 0x2B, 0x43, 0x01, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x0C, 0x60, 0xF4, 0x01, 0xB9, 0x60, 0xCC, 0x15, 0x99, 0x00, 0xEA, 0x16, + 0x14, 0x61, 0x99, 0x60, 0xE9, 0x16, 0xA9, 0x00, 0xD0, 0x16, 0xB9, 0x00, 0xC8, 0x15, 0xB9, 0x00, + 0xC4, 0x15, 0x99, 0x00, 0xE8, 0x16, 0xB9, 0x00, 0xC0, 0x15, 0xB9, 0x00, 0xBC, 0x15, 0x99, 0x00, + 0xE7, 0x16, 0x04, 0x63, 0x99, 0x60, 0xE6, 0x16, 0x99, 0x00, 0xDF, 0x16, 0x99, 0x00, 0xDE, 0x16, + 0x04, 0x71, 0x99, 0x70, 0xDD, 0x16, 0x99, 0x00, 0xDC, 0x16, 0x99, 0x70, 0xDB, 0x16, 0x99, 0x00, + 0xDA, 0x16, 0x14, 0x61, 0xA9, 0x60, 0xCE, 0x16, 0xA9, 0x60, 0xCC, 0x16, 0x08, 0x60, 0x00, 0x80, + 0x2C, 0x60, 0x00, 0xDC, 0x18, 0x46, 0x09, 0x00, 0x99, 0x40, 0xD9, 0x16, 0x18, 0x56, 0x08, 0x00, + 0xA9, 0x50, 0xCA, 0x16, 0xA9, 0x00, 0xC8, 0x16, 0x99, 0x00, 0xD8, 0x16, 0x99, 0x00, 0xD7, 0x16, + 0x99, 0x00, 0xD6, 0x16, 0x0C, 0x50, 0xFC, 0x0A, 0xB9, 0x00, 0xB8, 0x15, 0x99, 0x70, 0xE4, 0x16, + 0x38, 0x65, 0x0C, 0x00, 0x64, 0x64, 0xB9, 0x65, 0x0C, 0x00, 0x99, 0x00, 0xE3, 0x16, 0x08, 0x60, + 0x00, 0x80, 0x18, 0x56, 0x7D, 0xDC, 0x99, 0x50, 0xE2, 0x16, 0x99, 0x00, 0xE1, 0x16, 0x99, 0x70, + 0xEC, 0x16, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, 0x2B, 0x3E, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0x2B, 0x54, 0x00, 0x00, 0x04, 0x20, 0x2B, 0x61, + 0x00, 0x00, 0xEB, 0x3A, 0x01, 0x00, 0x08, 0x70, 0x00, 0x40, 0x38, 0x77, 0x10, 0x20, 0x30, 0xF1, + 0xF7, 0x70, 0xB9, 0x70, 0x20, 0x00, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x0C, 0x20, + 0x11, 0x00, 0xB1, 0xF1, 0x8B, 0x32, 0x00, 0x00, 0x04, 0x2B, 0x04, 0x31, 0xEB, 0x62, 0x00, 0x00, + 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x04, 0x21, 0xB1, 0xF1, 0xEB, 0x5D, + 0x00, 0x00, 0x04, 0x24, 0xEB, 0x5D, 0x00, 0x00, 0x0C, 0x20, 0x40, 0x00, 0xEB, 0x5D, 0x00, 0x00, + 0x0C, 0x20, 0x10, 0x00, 0x6B, 0x5D, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, + 0x34, 0x14, 0xB1, 0xF1, 0x6B, 0x5E, 0x00, 0x00, 0x04, 0x25, 0x04, 0x31, 0xEB, 0x62, 0x00, 0x00, + 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x0C, 0x20, 0x00, 0x01, 0xB1, 0xF1, + 0x2B, 0x57, 0x00, 0x00, 0x0C, 0x20, 0x80, 0x00, 0x2B, 0x57, 0x00, 0x00, 0x04, 0x20, 0x06, 0x52, + 0x0C, 0x30, 0x27, 0x00, 0x0C, 0x40, 0xFF, 0xFF, 0x0C, 0x60, 0x01, 0x02, 0x8B, 0x6C, 0x00, 0x00, + 0x04, 0x21, 0x0C, 0x30, 0x8F, 0x01, 0x0C, 0x40, 0xFF, 0xFF, 0x04, 0x50, 0x0C, 0x60, 0x01, 0x02, + 0x8B, 0x6C, 0x00, 0x00, 0x04, 0x27, 0x04, 0x31, 0xEB, 0x62, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x04, 0x21, 0xB1, 0xF1, 0x4B, 0x62, 0x00, 0x00, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x08, 0x60, 0x00, 0x40, 0x38, 0xE6, + 0x70, 0x60, 0x06, 0x72, 0x23, 0xEE, 0xCC, 0xE0, 0x00, 0xC9, 0x06, 0xC3, 0xC2, 0x05, 0x08, 0x60, + 0x04, 0x00, 0x66, 0xE6, 0xF7, 0xE1, 0x06, 0x37, 0x06, 0x2E, 0x6B, 0x13, 0x00, 0x00, 0x0C, 0x30, + 0xA0, 0x0F, 0xCB, 0x14, 0x00, 0x00, 0x24, 0x25, 0x04, 0x3A, 0xCB, 0x14, 0x00, 0x00, 0x08, 0x70, + 0x00, 0x40, 0x38, 0x77, 0xCC, 0x71, 0x06, 0xD2, 0x77, 0x7C, 0x24, 0x72, 0xC6, 0x27, 0xB2, 0x02, + 0x06, 0xD7, 0xC4, 0xC0, 0x82, 0x18, 0x06, 0x7E, 0xD7, 0x71, 0x2F, 0x2E, 0x0E, 0x00, 0x26, 0x27, + 0x06, 0x3D, 0xCB, 0x14, 0x00, 0x00, 0x3C, 0xE0, 0xB0, 0x9A, 0xCC, 0xE0, 0x20, 0x03, 0x04, 0x71, + 0xD2, 0x02, 0x04, 0x70, 0xD7, 0x7F, 0x66, 0x72, 0x0C, 0x60, 0x00, 0x00, 0xB9, 0x76, 0x3C, 0x00, + 0x4B, 0xB7, 0x00, 0x00, 0x06, 0x2D, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x38, 0x70, 0xB0, 0x16, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x38, 0xE7, 0x04, 0x00, 0x18, 0x27, + 0x05, 0x00, 0x04, 0x30, 0x0C, 0xC0, 0xFF, 0x00, 0x2B, 0xD7, 0x00, 0x00, 0x56, 0xCE, 0x06, 0xD2, + 0x04, 0x30, 0x06, 0x2C, 0x2B, 0xD7, 0x00, 0x00, 0x08, 0x70, 0xFF, 0xFF, 0x56, 0x7E, 0x57, 0xD4, + 0x66, 0x72, 0x66, 0x7D, 0x08, 0x60, 0x00, 0x40, 0xB9, 0x76, 0x6C, 0x72, 0x50, 0xC1, 0x2C, 0x10, + 0x10, 0x00, 0xE1, 0xF0, 0x38, 0x70, 0xB0, 0x16, 0x34, 0x14, 0xB1, 0xF1, 0x18, 0x27, 0x08, 0x00, + 0x04, 0x31, 0x2B, 0xD7, 0x00, 0x00, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x27, 0x18, 0x70, 0x8B, 0xDB, + 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x40, 0x38, 0x57, 0x64, 0x71, + 0x38, 0x77, 0x9C, 0x60, 0x06, 0x65, 0xC4, 0x71, 0x77, 0x6A, 0x54, 0x6F, 0x02, 0x14, 0x34, 0x78, + 0x26, 0x76, 0xC4, 0x7F, 0x02, 0x02, 0x04, 0x7F, 0x86, 0x67, 0x32, 0x02, 0x04, 0x60, 0x08, 0x70, + 0x0F, 0xFF, 0x2C, 0x70, 0xFF, 0xFF, 0x56, 0x75, 0x57, 0x6A, 0x66, 0x67, 0x08, 0x70, 0x00, 0x40, + 0xB9, 0x67, 0x64, 0x71, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0xAB, 0x5C, 0x00, 0x00, + 0x04, 0x31, 0x0C, 0x20, 0x20, 0x00, 0x4B, 0x5B, 0x00, 0x00, 0x0C, 0x20, 0xFF, 0x00, 0x0B, 0x59, + 0x00, 0x00, 0x04, 0x31, 0x04, 0x24, 0xCB, 0x55, 0x00, 0x00, 0x04, 0x21, 0xEB, 0x51, 0x00, 0x00, + 0xCB, 0xDE, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0xC4, 0x20, 0x34, 0x18, + 0xC1, 0xE1, 0x82, 0x0A, 0x04, 0x21, 0x6B, 0xBB, 0x02, 0x00, 0x18, 0x60, 0xE6, 0x16, 0x1C, 0x70, + 0x80, 0x00, 0x66, 0x76, 0xF2, 0x07, 0x6B, 0xBB, 0x02, 0x00, 0x18, 0x70, 0xE6, 0x16, 0x5C, 0x70, + 0x7F, 0x00, 0x99, 0x70, 0xE6, 0x16, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x80, + 0x98, 0x77, 0x6C, 0xDC, 0x34, 0x14, 0xB1, 0xF1, 0x82, 0x04, 0x28, 0x20, 0xCA, 0x16, 0xF2, 0x05, + 0x08, 0x70, 0x00, 0x80, 0x18, 0x27, 0x08, 0xDC, 0x54, 0x21, 0x6B, 0xE2, 0x00, 0x00, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0x04, 0x21, 0xB1, 0xF1, 0x2B, 0x61, 0x00, 0x00, 0x98, 0x70, + 0xD6, 0x16, 0x82, 0x27, 0x5C, 0x70, 0xF0, 0x00, 0xCC, 0x70, 0x80, 0x00, 0x82, 0x08, 0xCC, 0x70, + 0xC0, 0x00, 0x92, 0x1F, 0x04, 0x61, 0x99, 0x60, 0xD8, 0x16, 0xF2, 0x1B, 0x04, 0x71, 0x99, 0x70, + 0xD8, 0x16, 0x99, 0x70, 0xDA, 0x16, 0x99, 0x00, 0xDB, 0x16, 0x08, 0x60, 0x00, 0x80, 0x98, 0x66, + 0xAD, 0xDC, 0x92, 0x04, 0x99, 0x00, 0xD7, 0x16, 0xF2, 0x03, 0x99, 0x70, 0xD7, 0x16, 0x04, 0x20, + 0x6B, 0xBB, 0x02, 0x00, 0x18, 0x60, 0xE6, 0x16, 0x5C, 0x60, 0x7F, 0x00, 0x99, 0x60, 0xE6, 0x16, + 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, + 0x2C, 0x20, 0x80, 0x02, 0x2C, 0x40, 0x5C, 0x04, 0x36, 0x42, 0x08, 0x30, 0x00, 0x80, 0x3C, 0x10, + 0x10, 0x00, 0x2C, 0x30, 0x54, 0x71, 0x77, 0x41, 0xD1, 0xC1, 0x0C, 0xF0, 0x5C, 0x01, 0xF1, 0xF0, + 0x08, 0x40, 0x00, 0x80, 0x0C, 0x20, 0x90, 0x01, 0x04, 0x30, 0x2C, 0x40, 0x00, 0xF0, 0x0C, 0xF0, + 0x04, 0x04, 0xF1, 0xF0, 0xB9, 0x20, 0x14, 0x00, 0x08, 0x70, 0x00, 0x80, 0x38, 0xD7, 0xD0, 0xFB, + 0x06, 0xE2, 0xCC, 0xD0, 0xFF, 0x00, 0x82, 0x17, 0xC6, 0xD2, 0x82, 0x15, 0x8B, 0x8E, 0x00, 0x00, + 0x08, 0x60, 0x1C, 0xE1, 0x08, 0x70, 0x00, 0x30, 0x2C, 0x60, 0x01, 0xE9, 0xB9, 0x67, 0x04, 0x01, + 0xB9, 0xD7, 0x08, 0x01, 0xB9, 0xE7, 0x0C, 0x01, 0xEB, 0x61, 0x00, 0x00, 0x04, 0x2A, 0xAB, 0xC0, + 0x00, 0x00, 0xF2, 0xFB, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x98, 0x60, 0xE2, 0x16, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x82, 0x09, 0x34, 0x61, 0x93, 0x66, 0x99, 0x60, 0xE2, 0x16, + 0x92, 0x54, 0x99, 0x00, 0xE4, 0x16, 0xF2, 0x49, 0xDC, 0x20, 0x80, 0x00, 0x08, 0xE0, 0x00, 0x80, + 0x2C, 0xE0, 0x0C, 0xDC, 0x82, 0x04, 0x18, 0xDE, 0x73, 0x00, 0xF2, 0x03, 0x18, 0xDE, 0x72, 0x00, + 0xCB, 0x3C, 0x00, 0x00, 0xC6, 0x2D, 0xA2, 0x0A, 0x38, 0x50, 0xC4, 0x15, 0x18, 0x60, 0xE3, 0x16, + 0x34, 0x53, 0xC6, 0x65, 0xB2, 0x1A, 0x24, 0x61, 0xF2, 0x16, 0x98, 0x60, 0xE3, 0x16, 0x82, 0x15, + 0x98, 0x50, 0xEA, 0x16, 0x82, 0x04, 0xB8, 0x50, 0xC8, 0x15, 0x92, 0x0F, 0x18, 0x5E, 0x74, 0x00, + 0x36, 0xD5, 0xC6, 0x2D, 0xD2, 0x0A, 0x18, 0x40, 0xE1, 0x16, 0x28, 0x5E, 0x7A, 0x00, 0xC6, 0x45, + 0xD2, 0x04, 0x34, 0x61, 0x99, 0x60, 0xE3, 0x16, 0x98, 0x50, 0xE4, 0x16, 0x18, 0x50, 0xE3, 0x16, + 0x92, 0x0E, 0x18, 0x7E, 0x75, 0x00, 0xC6, 0x57, 0xA2, 0x18, 0x04, 0x71, 0x99, 0x70, 0xE4, 0x16, + 0x0C, 0x60, 0xFC, 0x0A, 0x38, 0x76, 0x0C, 0x00, 0x64, 0x74, 0xF2, 0x0D, 0x18, 0x7E, 0x76, 0x00, + 0xC6, 0x57, 0xD2, 0x0B, 0x99, 0x00, 0xE4, 0x16, 0x0C, 0x60, 0xFC, 0x0A, 0x38, 0x76, 0x0C, 0x00, + 0x14, 0x55, 0x56, 0x75, 0xB9, 0x76, 0x0C, 0x00, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, + 0x34, 0x18, 0xC1, 0xE1, 0x06, 0xE2, 0x0B, 0x4F, 0x00, 0x00, 0x06, 0x2E, 0xAB, 0x4B, 0x00, 0x00, + 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xD2, + 0xCB, 0x2F, 0x00, 0x00, 0x18, 0x20, 0xE6, 0x16, 0x5C, 0x20, 0xF0, 0x00, 0x64, 0x23, 0x99, 0x20, + 0xE6, 0x16, 0xEB, 0x41, 0x00, 0x00, 0x18, 0x20, 0xE6, 0x16, 0xCB, 0x49, 0x00, 0x00, 0x6B, 0x2E, + 0x00, 0x00, 0x04, 0x20, 0x6B, 0xCA, 0x02, 0x00, 0xAB, 0x3A, 0x00, 0x00, 0xC4, 0xD0, 0x92, 0x08, + 0x04, 0x21, 0x0C, 0x30, 0x00, 0x20, 0x4B, 0x38, 0x00, 0x00, 0x8B, 0x35, 0x00, 0x00, 0xCB, 0x39, + 0x00, 0x00, 0x08, 0x70, 0x00, 0x80, 0x18, 0xC7, 0x6A, 0xDC, 0x04, 0xE0, 0xC6, 0xCE, 0x82, 0x0E, + 0x04, 0x21, 0x0C, 0x30, 0x00, 0x20, 0x4B, 0x38, 0x00, 0x00, 0x8B, 0x35, 0x00, 0x00, 0xC4, 0xD0, + 0x82, 0x12, 0x8B, 0x8F, 0x00, 0x00, 0xC4, 0x20, 0x82, 0x0E, 0x0B, 0x2F, 0x00, 0x00, 0x2B, 0x3B, + 0x00, 0x00, 0x04, 0x61, 0x99, 0x60, 0xE7, 0x16, 0x6B, 0x30, 0x00, 0x00, 0x50, 0xC1, 0x2C, 0x10, + 0x10, 0x00, 0xE1, 0xF0, 0x24, 0xE1, 0xF2, 0xE3, 0x34, 0x18, 0xC1, 0xE1, 0x08, 0x70, 0x00, 0x40, + 0x38, 0x77, 0x14, 0x10, 0xDC, 0x70, 0x00, 0x01, 0x92, 0x0F, 0x99, 0x00, 0xD3, 0x16, 0xCB, 0x5E, + 0x00, 0x00, 0x2B, 0x5F, 0x00, 0x00, 0x18, 0x70, 0xD3, 0x16, 0x93, 0x07, 0x92, 0x03, 0xCB, 0x51, + 0x00, 0x00, 0xEB, 0x5F, 0x00, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x98, 0x70, 0xD8, 0x16, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xE2, 0x92, 0x0A, 0x0C, 0x70, 0xFC, 0x0A, 0xA8, 0x67, + 0x10, 0x00, 0x82, 0x05, 0x34, 0x61, 0xA9, 0x67, 0x10, 0x00, 0xF2, 0x4C, 0x18, 0x70, 0xEA, 0x16, + 0xC4, 0x71, 0x92, 0x07, 0x98, 0x60, 0xE9, 0x16, 0x92, 0x04, 0xA9, 0x70, 0x0C, 0x0B, 0xF2, 0x42, + 0x38, 0x50, 0xB8, 0x15, 0xCC, 0x50, 0xE8, 0x03, 0xC2, 0x04, 0x0C, 0x50, 0xE9, 0x03, 0xF2, 0x02, + 0x24, 0x51, 0xC4, 0x70, 0xB9, 0x50, 0xB8, 0x15, 0x82, 0x04, 0x28, 0x70, 0xCC, 0x16, 0xF2, 0x18, + 0x08, 0xD0, 0x00, 0x80, 0x38, 0xC0, 0xBC, 0x15, 0x2C, 0xD0, 0x0C, 0xDC, 0x38, 0x2D, 0x4C, 0x00, + 0x38, 0x3D, 0x3C, 0x00, 0x04, 0x61, 0x26, 0x6C, 0xB9, 0x60, 0xBC, 0x15, 0xCB, 0x14, 0x00, 0x00, + 0xC6, 0xC2, 0xA2, 0x04, 0x38, 0x7D, 0x50, 0x00, 0xF2, 0x03, 0x28, 0x70, 0xCE, 0x16, 0xC6, 0x7E, + 0xC2, 0x19, 0x3F, 0xEE, 0x07, 0x00, 0x06, 0x2E, 0x06, 0x7E, 0xD7, 0x72, 0xD7, 0x21, 0x26, 0x27, + 0x36, 0x2E, 0xD7, 0x21, 0x0C, 0x30, 0x10, 0x27, 0xCB, 0x14, 0x00, 0x00, 0xC4, 0x2A, 0xC2, 0x0A, + 0x98, 0x70, 0xD9, 0x16, 0x82, 0x04, 0xCB, 0xF7, 0x00, 0x00, 0xF2, 0x04, 0x06, 0x2E, 0x8B, 0xBD, + 0x00, 0x00, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x98, 0x70, 0xD7, 0x16, + 0x82, 0x06, 0x08, 0x70, 0x00, 0x80, 0x28, 0x67, 0xB2, 0xDC, 0xF2, 0x05, 0x38, 0x70, 0xB0, 0x16, + 0x28, 0x67, 0x28, 0x00, 0x0C, 0x70, 0xFC, 0x0A, 0x28, 0x57, 0x12, 0x03, 0x26, 0x65, 0x28, 0x57, + 0x18, 0x03, 0xC6, 0x65, 0x02, 0x1A, 0x98, 0x67, 0x99, 0x04, 0x92, 0x17, 0x98, 0x67, 0xAA, 0x04, + 0x92, 0x14, 0x38, 0x77, 0x0C, 0x00, 0xDC, 0x70, 0x00, 0xF0, 0x92, 0x0F, 0x38, 0x60, 0xC0, 0x15, + 0x04, 0x21, 0x24, 0x61, 0xB9, 0x60, 0xC0, 0x15, 0x38, 0x50, 0xB0, 0x16, 0x18, 0x55, 0x2A, 0x00, + 0xC6, 0x65, 0xD2, 0x06, 0x06, 0x27, 0xF2, 0x04, 0xB9, 0x00, 0xC0, 0x15, 0x04, 0x20, 0xE1, 0xF0, + 0x34, 0x14, 0xB1, 0xF1, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x07, 0xF0, 0x70, 0xB9, 0x07, 0xF4, 0x70, + 0xC4, 0x21, 0xB9, 0x07, 0xF8, 0x70, 0xB9, 0x07, 0x34, 0x71, 0x08, 0x60, 0x01, 0x00, 0x92, 0x05, + 0x66, 0x63, 0xB9, 0x67, 0xF0, 0x70, 0xF2, 0x15, 0xC4, 0x22, 0x92, 0x05, 0x66, 0x63, 0xB9, 0x67, + 0xF4, 0x70, 0xF2, 0x0F, 0xC4, 0x23, 0x92, 0x05, 0x66, 0x63, 0xB9, 0x67, 0xF8, 0x70, 0xF2, 0x09, + 0x0C, 0x50, 0x80, 0x02, 0x66, 0x56, 0xB9, 0x57, 0xF0, 0x70, 0x66, 0x63, 0xB9, 0x67, 0x34, 0x71, + 0x0C, 0x20, 0x10, 0x00, 0x0C, 0x30, 0x00, 0x50, 0x4B, 0x38, 0x00, 0x00, 0x8B, 0x35, 0x00, 0x00, + 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x18, 0xD0, + 0xEA, 0x16, 0x18, 0x60, 0xE9, 0x16, 0xC6, 0x6D, 0x82, 0x37, 0x99, 0xD0, 0xE9, 0x16, 0xC4, 0xD0, + 0x18, 0x70, 0xE6, 0x16, 0x1C, 0x60, 0x10, 0x00, 0x56, 0x76, 0x82, 0x05, 0x64, 0x72, 0x99, 0x70, + 0xE6, 0x16, 0xF2, 0x1E, 0x64, 0x71, 0x99, 0x70, 0xE6, 0x16, 0xCB, 0x48, 0x01, 0x00, 0x8B, 0x47, + 0x01, 0x00, 0xA9, 0x00, 0xD0, 0x16, 0xB9, 0x00, 0xC8, 0x15, 0xB9, 0x00, 0xC0, 0x15, 0x38, 0x70, + 0xB0, 0x16, 0x06, 0x5D, 0x18, 0x27, 0x47, 0x00, 0x18, 0x37, 0x90, 0x00, 0x18, 0x47, 0x8F, 0x00, + 0x18, 0x67, 0x2A, 0x00, 0x0C, 0xF0, 0xE0, 0x00, 0xF1, 0xF0, 0xB9, 0x20, 0xC4, 0x15, 0x98, 0x70, + 0xEA, 0x16, 0x82, 0x06, 0x04, 0x20, 0x0C, 0x30, 0x54, 0x05, 0x8B, 0x02, 0x01, 0x00, 0x18, 0x20, + 0xE6, 0x16, 0x8B, 0xF2, 0x00, 0x00, 0x18, 0x20, 0xE6, 0x16, 0xEB, 0x41, 0x00, 0x00, 0x18, 0x20, + 0xE6, 0x16, 0x6B, 0xEC, 0x00, 0x00, 0x18, 0x20, 0xE6, 0x16, 0xCB, 0x49, 0x00, 0x00, 0x8B, 0x3B, + 0x01, 0x00, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x04, 0x24, + 0xB1, 0xF1, 0x8B, 0x32, 0x00, 0x00, 0x04, 0x24, 0x0C, 0x30, 0x00, 0x30, 0x4B, 0x38, 0x00, 0x00, + 0x8B, 0x35, 0x00, 0x00, 0x0C, 0x20, 0x11, 0x00, 0x8B, 0x32, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x04, 0x28, 0x0C, 0x30, 0x00, 0x40, 0xB1, 0xF1, 0x4B, 0x38, + 0x00, 0x00, 0x8B, 0x35, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0x04, 0x62, + 0xB1, 0xF1, 0x99, 0x60, 0xE7, 0x16, 0xCB, 0x2F, 0x00, 0x00, 0xAB, 0x3A, 0x00, 0x00, 0x6B, 0x2E, + 0x00, 0x00, 0x0C, 0x30, 0x00, 0x20, 0x04, 0x21, 0x4B, 0x38, 0x00, 0x00, 0x6B, 0x52, 0x01, 0x00, + 0x8B, 0x35, 0x00, 0x00, 0x2B, 0x36, 0x03, 0x00, 0xEB, 0x0A, 0x01, 0x00, 0x2B, 0x0C, 0x01, 0x00, + 0x0B, 0x21, 0x01, 0x00, 0xEB, 0x8C, 0x02, 0x00, 0x93, 0x22, 0x92, 0x0C, 0x18, 0x70, 0xD6, 0x16, + 0x5C, 0x70, 0xF0, 0x00, 0xCC, 0x70, 0x40, 0x00, 0x82, 0x0D, 0x04, 0x61, 0x99, 0x60, 0xEA, 0x16, + 0xF2, 0x09, 0x8B, 0xCA, 0x02, 0x00, 0x04, 0x20, 0x06, 0x32, 0x0B, 0x8B, 0x00, 0x00, 0x4B, 0x20, + 0x01, 0x00, 0x0B, 0x2F, 0x00, 0x00, 0x6B, 0x30, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, + 0x34, 0x18, 0x04, 0x63, 0xC1, 0xE1, 0x99, 0x60, 0xE7, 0x16, 0xCB, 0x2F, 0x00, 0x00, 0x6B, 0xFF, + 0x00, 0x00, 0xC4, 0x20, 0x82, 0x09, 0xAB, 0x3A, 0x00, 0x00, 0x04, 0x20, 0x0C, 0x30, 0x54, 0x05, + 0x8B, 0x02, 0x01, 0x00, 0xF2, 0x03, 0x2B, 0x3B, 0x00, 0x00, 0x6B, 0x2E, 0x00, 0x00, 0x04, 0x21, + 0x0C, 0x30, 0x80, 0x02, 0x8B, 0x02, 0x01, 0x00, 0x0C, 0x30, 0x28, 0x08, 0x04, 0x23, 0x8B, 0x02, + 0x01, 0x00, 0x04, 0x21, 0x8B, 0x37, 0x00, 0x00, 0xEB, 0x52, 0x01, 0x00, 0x06, 0xE2, 0x04, 0x21, + 0x4B, 0x33, 0x00, 0x00, 0x2B, 0x36, 0x03, 0x00, 0x0B, 0x2F, 0x00, 0x00, 0xEB, 0x0A, 0x01, 0x00, + 0x4B, 0xBB, 0x02, 0x00, 0x2B, 0x0C, 0x01, 0x00, 0x06, 0x2E, 0x4B, 0x56, 0x01, 0x00, 0x0B, 0x21, + 0x01, 0x00, 0x2B, 0x28, 0x01, 0x00, 0xEB, 0x32, 0x01, 0x00, 0x6B, 0x30, 0x00, 0x00, 0x98, 0x70, + 0x19, 0x0E, 0x82, 0x0E, 0xB9, 0x00, 0xBC, 0x15, 0x28, 0x60, 0xD0, 0x16, 0xB9, 0x00, 0xC8, 0x15, + 0xCC, 0x60, 0xEF, 0x00, 0xD2, 0x0A, 0x24, 0x61, 0xA9, 0x60, 0xD0, 0x16, 0xF2, 0x06, 0x38, 0x60, + 0xC8, 0x15, 0x24, 0x61, 0xB9, 0x60, 0xC8, 0x15, 0x38, 0x60, 0xC4, 0x15, 0x38, 0x70, 0xC8, 0x15, + 0x24, 0x63, 0xC6, 0x76, 0xA2, 0x05, 0x99, 0x00, 0xEA, 0x16, 0x99, 0x00, 0xE1, 0x16, 0x98, 0x60, + 0xE8, 0x16, 0x82, 0x0B, 0x04, 0x20, 0x99, 0x00, 0xEA, 0x16, 0x99, 0x00, 0xE8, 0x16, 0x0B, 0x6F, + 0x00, 0x00, 0x04, 0x21, 0x4B, 0xF3, 0x00, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, + 0x98, 0x70, 0xEA, 0x16, 0x34, 0x14, 0xB1, 0xF1, 0x92, 0x04, 0x98, 0x70, 0xE5, 0x16, 0x82, 0x04, + 0x8B, 0x10, 0x01, 0x00, 0xF2, 0x03, 0xEB, 0x0C, 0x01, 0x00, 0x0B, 0x40, 0x01, 0x00, 0x30, 0xF1, + 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, 0x4B, 0xB1, 0x00, 0x00, 0xC4, 0x20, 0x82, 0x03, + 0xEB, 0x61, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x04, 0x20, + 0xB1, 0xF1, 0x4B, 0x6E, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x18, 0x04, 0x20, + 0xC1, 0xE1, 0x4B, 0x70, 0x00, 0x00, 0x06, 0xE2, 0x04, 0x20, 0x0B, 0x6F, 0x00, 0x00, 0x06, 0x2E, + 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x18, 0xC1, 0xE1, 0xEB, 0x8F, 0x00, 0x00, + 0xC4, 0x20, 0x82, 0x07, 0x38, 0x20, 0xB4, 0x15, 0x6B, 0x91, 0x00, 0x00, 0xB9, 0x00, 0xB4, 0x15, + 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x18, 0x04, 0x21, 0xC1, 0xE1, 0x4B, 0x6E, + 0x00, 0x00, 0xEB, 0x8F, 0x00, 0x00, 0xC4, 0x20, 0x92, 0x03, 0x2B, 0xB8, 0x00, 0x00, 0x08, 0xE0, + 0x07, 0x00, 0x2C, 0xE0, 0x20, 0xA1, 0xCB, 0x1A, 0x01, 0x00, 0x98, 0x70, 0xDF, 0x16, 0x92, 0x14, + 0x04, 0x21, 0x4B, 0x70, 0x00, 0x00, 0x26, 0x22, 0x06, 0x72, 0x57, 0x71, 0x26, 0x27, 0xC6, 0x2E, + 0xC2, 0xF3, 0x98, 0x70, 0xDE, 0x16, 0x82, 0x08, 0x04, 0x21, 0x0B, 0x6F, 0x00, 0x00, 0x04, 0x21, + 0x4B, 0x6E, 0x00, 0x00, 0xF2, 0xE9, 0x04, 0x21, 0x0B, 0x6F, 0x00, 0x00, 0x04, 0x61, 0x08, 0x70, + 0x00, 0x40, 0xB9, 0x67, 0x14, 0x50, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0xC4, 0x20, 0x34, 0x14, + 0xB1, 0xF1, 0x82, 0x05, 0x04, 0x61, 0x99, 0x60, 0xED, 0x16, 0xF2, 0x03, 0x99, 0x00, 0xED, 0x16, + 0x0C, 0x20, 0x28, 0x16, 0x04, 0x30, 0x0C, 0x40, 0x80, 0x00, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, + 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x98, 0x70, 0xED, 0x16, 0x82, 0x08, 0x98, 0x70, + 0xEC, 0x16, 0x82, 0x05, 0xB9, 0x00, 0x20, 0x16, 0xB9, 0x00, 0x1C, 0x16, 0xE1, 0xF0, 0x00, 0x00, + 0x98, 0x70, 0xED, 0x16, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x82, 0x68, 0xB9, 0x00, 0x24, 0x16, + 0xCB, 0x3C, 0x00, 0x00, 0x38, 0x70, 0x24, 0x16, 0x1C, 0x60, 0x80, 0x00, 0x56, 0x76, 0x18, 0x60, + 0xE4, 0x16, 0x5C, 0x20, 0x7F, 0x00, 0x08, 0x50, 0xFD, 0xFF, 0x2C, 0x50, 0xFF, 0xFF, 0x66, 0x72, + 0x54, 0x61, 0xD7, 0x68, 0x56, 0x75, 0x66, 0x76, 0x18, 0x60, 0xEA, 0x16, 0x08, 0x50, 0xFB, 0xFF, + 0x2C, 0x50, 0xFF, 0xFF, 0x54, 0x61, 0x57, 0x69, 0x56, 0x75, 0x66, 0x76, 0xB9, 0x70, 0x24, 0x16, + 0x04, 0xD0, 0x08, 0x70, 0x00, 0x30, 0x08, 0x50, 0x07, 0x00, 0x2C, 0x70, 0x00, 0x49, 0x06, 0x6D, + 0x2C, 0x50, 0xFF, 0xFF, 0x30, 0x47, 0x0C, 0x30, 0xFF, 0x0F, 0x56, 0x34, 0x77, 0x48, 0x5C, 0x40, + 0xFF, 0x0F, 0x36, 0x34, 0x38, 0x40, 0x24, 0x16, 0x23, 0x23, 0x06, 0xF4, 0xF7, 0xF9, 0xC6, 0x3F, + 0x02, 0x08, 0x06, 0x32, 0xD7, 0x39, 0x56, 0x45, 0x66, 0x43, 0xB9, 0x40, 0x24, 0x16, 0x43, 0xD6, + 0x24, 0x61, 0xCC, 0x60, 0x50, 0x01, 0x24, 0x74, 0x92, 0xE6, 0xC4, 0xD0, 0x82, 0x1F, 0x0C, 0x30, + 0x18, 0x00, 0x06, 0x2D, 0x4B, 0x18, 0x00, 0x00, 0x38, 0xE0, 0x24, 0x16, 0x1C, 0x70, 0x81, 0x0F, + 0x5C, 0x20, 0x1F, 0x00, 0x56, 0xE7, 0xD7, 0x23, 0x66, 0xE2, 0x0C, 0x30, 0x18, 0x00, 0x06, 0x2D, + 0xAB, 0x15, 0x00, 0x00, 0x08, 0x70, 0xFE, 0xFF, 0x5C, 0x20, 0x1F, 0x00, 0x2C, 0x70, 0xFF, 0x0F, + 0x57, 0x26, 0x56, 0x7E, 0x66, 0x72, 0xB9, 0x70, 0x24, 0x16, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x08, 0x70, 0x00, 0x80, 0x28, 0x67, 0x28, 0xDC, 0x98, 0x70, 0xED, 0x16, + 0x3C, 0x10, 0x38, 0x00, 0xD9, 0xC1, 0x28, 0x00, 0xD9, 0x81, 0x18, 0x00, 0x8A, 0x99, 0x00, 0x00, + 0xF7, 0x60, 0x08, 0xC0, 0x00, 0x30, 0x08, 0xB0, 0xC0, 0xFF, 0xB1, 0x61, 0x99, 0x00, 0xEB, 0x16, + 0x0C, 0xE0, 0x24, 0x0E, 0x04, 0x80, 0x2C, 0xC0, 0x00, 0x49, 0x2C, 0xB0, 0xFF, 0x07, 0x0C, 0x60, + 0xFC, 0x0A, 0x18, 0x76, 0x98, 0x04, 0xC6, 0x78, 0xCA, 0x83, 0x00, 0x00, 0x98, 0x7E, 0x16, 0x00, + 0x82, 0x04, 0x04, 0x71, 0x26, 0x78, 0x13, 0x87, 0x06, 0x2E, 0xAB, 0x3B, 0x01, 0x00, 0xC4, 0x20, + 0x92, 0x08, 0x2C, 0xE0, 0x1C, 0x00, 0x0C, 0x70, 0x90, 0x0F, 0xC6, 0xE7, 0x92, 0xE9, 0xF2, 0x70, + 0x18, 0x7E, 0x16, 0x00, 0xC4, 0x71, 0x92, 0x09, 0x18, 0x60, 0xEB, 0x16, 0x64, 0x61, 0x99, 0x60, + 0xEB, 0x16, 0x0C, 0x70, 0xF8, 0x15, 0xF2, 0x0A, 0xC4, 0x72, 0x92, 0xEC, 0x18, 0x60, 0xEB, 0x16, + 0x64, 0x62, 0x99, 0x60, 0xEB, 0x16, 0x0C, 0x70, 0xD4, 0x15, 0x18, 0x6E, 0x0D, 0x00, 0x08, 0x90, + 0x3F, 0x00, 0x34, 0x61, 0x2F, 0x56, 0x06, 0x00, 0x26, 0x56, 0x2C, 0x90, 0xFF, 0xFF, 0xD7, 0x51, + 0x04, 0x40, 0xB9, 0x61, 0x0C, 0x00, 0xB9, 0x91, 0x10, 0x00, 0x38, 0x61, 0x0C, 0x00, 0x26, 0x64, + 0xC4, 0x6D, 0xD2, 0x40, 0x18, 0x6E, 0x0C, 0x00, 0x04, 0x30, 0x2F, 0x26, 0x05, 0x00, 0x57, 0x21, + 0x34, 0x24, 0x34, 0x61, 0x26, 0x2C, 0xB9, 0x61, 0x08, 0x00, 0x38, 0x61, 0x08, 0x00, 0x26, 0x63, + 0xCC, 0x60, 0x16, 0x00, 0xD2, 0x2B, 0x30, 0xA1, 0x30, 0xD2, 0x1C, 0x90, 0x00, 0x08, 0x36, 0xDA, + 0x5C, 0xD0, 0xFF, 0x07, 0x23, 0xFD, 0xB9, 0xF1, 0x14, 0x00, 0x30, 0x67, 0x56, 0x69, 0x66, 0x6F, + 0xB1, 0x67, 0x28, 0xF2, 0x02, 0x00, 0x56, 0x6B, 0x36, 0xFA, 0x5C, 0xF0, 0xFF, 0x07, 0x23, 0xAF, + 0x06, 0x9A, 0xD7, 0x95, 0x66, 0x69, 0xB1, 0x67, 0x38, 0x91, 0x14, 0x00, 0x04, 0x60, 0xC6, 0x9A, + 0x02, 0x05, 0x3F, 0x6F, 0x0D, 0x00, 0x5C, 0x60, 0xFF, 0x03, 0x30, 0xF7, 0x38, 0xA1, 0x10, 0x00, + 0x57, 0x6B, 0x56, 0xFA, 0x66, 0xF6, 0xB1, 0xF7, 0x24, 0x74, 0x24, 0x31, 0xC4, 0x33, 0x24, 0x24, + 0x92, 0xCD, 0x24, 0x41, 0xC4, 0x43, 0x2C, 0x50, 0x18, 0x00, 0x92, 0xB8, 0xF2, 0x8B, 0x58, 0xC1, + 0x28, 0x00, 0x58, 0x81, 0x18, 0x00, 0x2C, 0x10, 0x38, 0x00, 0xE1, 0xF0, 0x98, 0x70, 0xED, 0x16, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x82, 0x2F, 0x06, 0xED, 0x0C, 0xE0, 0xD0, 0x15, 0xB9, 0x00, + 0xD0, 0x15, 0x4B, 0x3C, 0x00, 0x00, 0x18, 0x70, 0xEA, 0x16, 0xC4, 0x71, 0x92, 0x24, 0x98, 0x70, + 0x19, 0x0E, 0x82, 0x21, 0x23, 0xC2, 0xCB, 0x3B, 0x00, 0x00, 0xA9, 0x2E, 0x02, 0x00, 0x0C, 0x30, + 0x18, 0x00, 0x06, 0x2C, 0x6B, 0x17, 0x00, 0x00, 0x38, 0xE0, 0xD0, 0x15, 0x1C, 0x70, 0x20, 0x00, + 0x56, 0xE7, 0x5C, 0x20, 0x1F, 0x00, 0x66, 0xE2, 0x0C, 0x30, 0x18, 0x00, 0x06, 0x2C, 0xCB, 0x14, + 0x00, 0x00, 0x5C, 0x20, 0x1F, 0x00, 0x1C, 0x70, 0xE1, 0x03, 0xD7, 0x22, 0x56, 0xE7, 0x66, 0xE2, + 0xB9, 0xE0, 0xD0, 0x15, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x38, 0x60, 0x24, 0x16, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0x7E, 0x0C, 0x70, 0x28, 0x16, 0xB9, 0x67, 0x08, 0x00, + 0x38, 0x60, 0x20, 0x16, 0xB9, 0x67, 0x0C, 0x00, 0x38, 0x60, 0x1C, 0x16, 0x06, 0xD7, 0xB9, 0x67, + 0x10, 0x00, 0x38, 0x60, 0xD0, 0x15, 0x0C, 0x20, 0x40, 0x16, 0xB9, 0x67, 0x14, 0x00, 0x18, 0x30, + 0xEB, 0x16, 0x06, 0xC6, 0xD4, 0x31, 0x82, 0x08, 0x0C, 0x30, 0xF8, 0x15, 0x04, 0x49, 0x0C, 0xF0, + 0x5C, 0x01, 0xF1, 0xF0, 0xF2, 0x05, 0x04, 0x49, 0x0C, 0xF0, 0xD8, 0x01, 0xF1, 0xF0, 0x18, 0x30, + 0xEB, 0x16, 0x54, 0x32, 0x93, 0x33, 0x0C, 0x20, 0x64, 0x16, 0x82, 0x08, 0x0C, 0x30, 0xD4, 0x15, + 0x04, 0x49, 0x0C, 0xF0, 0x5C, 0x01, 0xF1, 0xF0, 0xF2, 0x05, 0x04, 0x49, 0x0C, 0xF0, 0xD8, 0x01, + 0xF1, 0xF0, 0x38, 0x70, 0x08, 0x0B, 0xB9, 0x7D, 0x04, 0x00, 0x38, 0x70, 0x28, 0x16, 0x24, 0x71, + 0xB9, 0x70, 0x28, 0x16, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x08, 0x70, 0x00, 0x40, + 0x0C, 0x60, 0xFE, 0x00, 0xB9, 0x67, 0x0C, 0x20, 0xB9, 0x07, 0x18, 0x20, 0xE1, 0xF0, 0x00, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x98, 0x40, 0xED, 0x0B, 0x38, 0x70, 0xB0, 0x16, 0x06, 0x62, 0x18, 0x57, + 0x8E, 0x00, 0x18, 0x77, 0x8D, 0x00, 0x92, 0x05, 0x18, 0x40, 0xEE, 0x0B, 0x26, 0x74, 0x13, 0x77, + 0x98, 0x40, 0xE4, 0x16, 0x82, 0x0D, 0x08, 0x40, 0x00, 0x80, 0x2C, 0x40, 0x0C, 0xDC, 0x18, 0x34, + 0x7E, 0x00, 0x18, 0x44, 0x7F, 0x00, 0x26, 0x73, 0x26, 0x54, 0x13, 0x77, 0x13, 0x55, 0x18, 0x46, + 0x1A, 0x00, 0xD4, 0x41, 0x82, 0x02, 0x06, 0x57, 0x18, 0x76, 0x18, 0x00, 0xC6, 0x75, 0xB2, 0x06, + 0x18, 0x76, 0x1B, 0x00, 0x04, 0x20, 0xC4, 0x71, 0x92, 0x05, 0x04, 0x71, 0x99, 0x76, 0x1B, 0x00, + 0x04, 0x21, 0xE1, 0xF0, 0x98, 0x60, 0xE4, 0x16, 0x38, 0x70, 0xB0, 0x16, 0x18, 0x77, 0x8E, 0x00, + 0x82, 0x07, 0x08, 0x60, 0x00, 0x80, 0x18, 0x66, 0x8B, 0xDC, 0x26, 0x76, 0x13, 0x77, 0x18, 0x52, + 0x01, 0x00, 0x04, 0x61, 0xC6, 0x57, 0xB2, 0x02, 0x04, 0x60, 0x04, 0x21, 0x56, 0x26, 0xE1, 0xF0, + 0x0C, 0x50, 0xFC, 0x0A, 0x18, 0x60, 0x1A, 0x0E, 0x30, 0x75, 0x16, 0x66, 0x24, 0x71, 0xB1, 0x75, + 0xF7, 0x6F, 0xD7, 0x7A, 0x57, 0x6A, 0x6C, 0x70, 0x75, 0x00, 0x66, 0x76, 0x08, 0x60, 0x00, 0x30, + 0xB9, 0x76, 0x00, 0x01, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x0C, 0x20, 0x80, 0x02, 0x04, 0x30, + 0x0C, 0x40, 0xD2, 0x02, 0xB1, 0xF1, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x0C, 0x20, 0x54, 0x05, + 0x04, 0x30, 0x0C, 0x40, 0xD2, 0x02, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x0C, 0x20, 0x28, 0x08, + 0x04, 0x30, 0x0C, 0x40, 0xD2, 0x02, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x1C, 0xC9, 0xE1, 0x04, 0x00, 0x08, 0xE0, 0x00, 0x80, 0x2C, 0xE0, + 0x0C, 0xDC, 0x28, 0x7E, 0x62, 0x00, 0xA9, 0x70, 0x0C, 0x0B, 0x4B, 0x41, 0x01, 0x00, 0x08, 0x70, + 0x00, 0x80, 0x18, 0x27, 0x08, 0xDC, 0x6B, 0xBB, 0x02, 0x00, 0x4B, 0xBB, 0x01, 0x00, 0x78, 0x2E, + 0x38, 0x00, 0x78, 0x3E, 0x3A, 0x00, 0x0C, 0x70, 0x64, 0x00, 0xB1, 0x71, 0x0C, 0x60, 0x69, 0x00, + 0x0C, 0x40, 0x41, 0x00, 0x0C, 0x50, 0x3C, 0x00, 0x8B, 0xCD, 0x02, 0x00, 0x8B, 0xC1, 0x01, 0x00, + 0x2B, 0x39, 0x03, 0x00, 0xEB, 0xB7, 0x01, 0x00, 0x0B, 0xB8, 0x01, 0x00, 0x38, 0x70, 0xB0, 0x16, + 0x04, 0x61, 0x30, 0x77, 0xD6, 0x67, 0x82, 0x04, 0x0C, 0x50, 0x28, 0x08, 0xF2, 0x03, 0x0C, 0x50, + 0x80, 0x02, 0xD4, 0x72, 0xB9, 0x50, 0xC0, 0x16, 0x82, 0x04, 0x0C, 0x60, 0x28, 0x08, 0xF2, 0x03, + 0x0C, 0x60, 0x80, 0x02, 0x48, 0xE1, 0x04, 0x00, 0xB9, 0x60, 0xBC, 0x16, 0x24, 0x1C, 0xE1, 0xF0, + 0x34, 0x14, 0xB1, 0xF1, 0xAB, 0x0F, 0x03, 0x00, 0x6B, 0x99, 0x02, 0x00, 0xCB, 0x57, 0x01, 0x00, + 0x8B, 0xBE, 0x02, 0x00, 0x4B, 0x59, 0x01, 0x00, 0x30, 0xF1, 0x99, 0x00, 0xD8, 0x0B, 0xA9, 0x00, + 0xAC, 0x15, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0x8B, 0xF4, 0x02, 0x00, + 0x30, 0xF1, 0x99, 0x00, 0xDA, 0x0B, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, + 0x6B, 0x37, 0x02, 0x00, 0x2B, 0xB8, 0x01, 0x00, 0x6B, 0xF2, 0x01, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x98, 0x50, 0x19, 0x0E, 0x34, 0x14, 0xB1, 0xF1, 0x92, 0x08, 0x98, 0x70, + 0x94, 0x0F, 0x92, 0x05, 0xB8, 0x70, 0xC8, 0x15, 0x82, 0x0D, 0xF2, 0x14, 0x18, 0x70, 0x96, 0x0F, + 0xCC, 0x70, 0xC7, 0x00, 0xD2, 0x04, 0x24, 0x71, 0x99, 0x70, 0x96, 0x0F, 0xC4, 0x50, 0x92, 0x10, + 0xF2, 0xF2, 0x98, 0x70, 0x94, 0x0F, 0x92, 0x03, 0x0B, 0x59, 0x01, 0x00, 0xCB, 0xCC, 0x02, 0x00, + 0xF2, 0x07, 0xC4, 0x74, 0x92, 0x05, 0x4B, 0x59, 0x01, 0x00, 0x8B, 0xBE, 0x02, 0x00, 0x18, 0x70, + 0xDA, 0x0B, 0xCC, 0x70, 0xF9, 0x00, 0xD2, 0x04, 0x24, 0x71, 0x99, 0x70, 0xDA, 0x0B, 0x38, 0x50, + 0x34, 0x15, 0x06, 0x75, 0x18, 0x40, 0x97, 0x0F, 0x77, 0x76, 0x54, 0x7F, 0xC6, 0x47, 0x32, 0x04, + 0x99, 0x70, 0x97, 0x0F, 0xF2, 0x0A, 0x06, 0x75, 0xDC, 0x70, 0x00, 0xF0, 0x92, 0x06, 0x98, 0x70, + 0x94, 0x0F, 0x92, 0x03, 0x99, 0x00, 0x97, 0x0F, 0x98, 0x70, 0xA8, 0x15, 0x82, 0x0A, 0x18, 0x70, + 0xD8, 0x0B, 0xCC, 0x70, 0xFF, 0x00, 0x82, 0x07, 0x24, 0x71, 0x99, 0x70, 0xD8, 0x0B, 0xF2, 0x03, + 0x99, 0x00, 0xD8, 0x0B, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x18, 0x70, 0xE8, 0x16, + 0x34, 0x14, 0xC4, 0x70, 0xB1, 0xF1, 0x04, 0x21, 0x82, 0x15, 0x38, 0x70, 0x08, 0x0B, 0x1C, 0x60, + 0x01, 0xF0, 0x56, 0x76, 0xB9, 0x70, 0x08, 0x0B, 0xCB, 0x57, 0x01, 0x00, 0x6B, 0x49, 0x01, 0x00, + 0xEB, 0xF5, 0x02, 0x00, 0x6B, 0xF8, 0x02, 0x00, 0x99, 0x00, 0x52, 0x0C, 0x99, 0x00, 0x1A, 0x0E, + 0x04, 0x20, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, 0x6B, 0x0A, 0x03, 0x00, + 0xC4, 0x21, 0x92, 0x09, 0x6B, 0xF8, 0x02, 0x00, 0x6B, 0xDB, 0x01, 0x00, 0x6B, 0x3D, 0x03, 0x00, + 0x8B, 0x0F, 0x03, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0xB1, 0xF1, + 0x6B, 0x8A, 0x02, 0x00, 0x30, 0xF1, 0x04, 0x20, 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, + 0x6B, 0x49, 0x01, 0x00, 0x0B, 0xBF, 0x02, 0x00, 0x4B, 0x46, 0x02, 0x00, 0x6B, 0xB5, 0x02, 0x00, + 0xEB, 0x14, 0x03, 0x00, 0xC4, 0x20, 0x92, 0x03, 0x6B, 0x10, 0x03, 0x00, 0x6B, 0x4F, 0x01, 0x00, + 0xC4, 0x21, 0x92, 0x1F, 0x98, 0x70, 0xDB, 0x0B, 0x82, 0x04, 0x98, 0x70, 0xDC, 0x0B, 0x92, 0x10, + 0x8B, 0xB7, 0x02, 0x00, 0x18, 0x70, 0xE5, 0x16, 0xC4, 0x71, 0x92, 0x04, 0x2B, 0x46, 0x02, 0x00, + 0xF2, 0x05, 0x4B, 0x84, 0x02, 0x00, 0xAB, 0xF2, 0x01, 0x00, 0x4B, 0xB8, 0x01, 0x00, 0xEB, 0xB6, + 0x01, 0x00, 0xC4, 0x21, 0x92, 0x06, 0x98, 0x70, 0xDC, 0x0B, 0x92, 0x03, 0x4B, 0x51, 0x01, 0x00, + 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0xC4, 0x20, 0x34, 0x14, 0xB1, 0xF1, 0x82, 0x10, + 0xEB, 0x34, 0x03, 0x00, 0x18, 0x70, 0xDC, 0x0B, 0xC4, 0x71, 0x92, 0x0A, 0x38, 0x70, 0x08, 0x0B, + 0x1C, 0x60, 0x01, 0x03, 0x56, 0x76, 0xB9, 0x70, 0x08, 0x0B, 0x4B, 0x51, 0x01, 0x00, 0x2B, 0x4A, + 0x01, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x34, 0x14, 0x0C, 0x20, 0x24, 0x0E, 0x04, 0x30, + 0x0C, 0x40, 0x74, 0x01, 0xB1, 0xF1, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x0C, 0x20, 0x98, 0x0F, + 0x04, 0x30, 0x04, 0x4F, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, + 0x99, 0x00, 0x96, 0x0F, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x0C, 0x20, 0xE4, 0x0B, 0x04, 0x30, + 0x04, 0x4C, 0xB1, 0xF1, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, + 0x04, 0x70, 0x2F, 0x67, 0x02, 0x00, 0x91, 0x06, 0x2F, 0x67, 0x03, 0x00, 0x24, 0x7C, 0xCC, 0x70, + 0x9C, 0x00, 0x91, 0x06, 0x92, 0xF7, 0xE1, 0xF0, 0x34, 0x18, 0xC1, 0xE1, 0x04, 0x71, 0x99, 0x32, + 0x01, 0x00, 0x91, 0x72, 0x20, 0x75, 0x06, 0xE2, 0xA9, 0x72, 0x02, 0x00, 0x28, 0x75, 0x02, 0x00, + 0x06, 0x34, 0xA9, 0x72, 0x04, 0x00, 0x06, 0x24, 0x6B, 0x13, 0x00, 0x00, 0xB9, 0x2E, 0x08, 0x00, + 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, 0xB9, 0x20, 0xC4, 0x16, 0x99, 0x30, 0xEF, 0x16, + 0x99, 0x40, 0xEE, 0x16, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x34, 0x00, 0xD9, 0x81, 0x14, 0x00, + 0xD9, 0xC1, 0x24, 0x00, 0x06, 0xB2, 0xB1, 0x31, 0xB9, 0x41, 0x04, 0x00, 0x04, 0x70, 0x2F, 0x67, + 0x0B, 0x00, 0x24, 0x78, 0xCC, 0x70, 0x48, 0x05, 0xB1, 0x06, 0x92, 0xFA, 0x30, 0xE1, 0x04, 0xD0, + 0x06, 0x9D, 0x06, 0xAD, 0x90, 0x7E, 0x92, 0x07, 0x04, 0xE0, 0x06, 0xCE, 0x06, 0x9E, 0x06, 0x8E, + 0xFA, 0x98, 0x00, 0x00, 0x30, 0x61, 0xB8, 0x76, 0x08, 0x00, 0x82, 0x05, 0x38, 0x7E, 0x08, 0x00, + 0xB9, 0x70, 0xC4, 0x16, 0x38, 0xC1, 0x04, 0x00, 0x04, 0x80, 0x90, 0x7C, 0x82, 0x63, 0x98, 0x70, + 0xEF, 0x16, 0x92, 0x03, 0xC6, 0x98, 0x82, 0x59, 0x78, 0x7C, 0x02, 0x00, 0x78, 0x2E, 0x02, 0x00, + 0x78, 0x6E, 0x04, 0x00, 0x36, 0x27, 0x78, 0x7C, 0x04, 0x00, 0xB9, 0x51, 0x10, 0x00, 0x06, 0x32, + 0x3F, 0x77, 0x06, 0x00, 0xB9, 0x71, 0x08, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x38, 0x71, 0x08, 0x00, + 0x06, 0x62, 0x06, 0x37, 0x06, 0x27, 0xB9, 0x61, 0x0C, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x38, 0x51, + 0x10, 0x00, 0x38, 0x61, 0x0C, 0x00, 0x38, 0x70, 0xC4, 0x16, 0x26, 0x62, 0xC6, 0x76, 0xA2, 0x35, + 0x06, 0x7B, 0x04, 0x40, 0xC6, 0x4D, 0x04, 0x21, 0x26, 0x24, 0x82, 0x07, 0x24, 0x78, 0x14, 0x38, + 0x26, 0x37, 0x30, 0x33, 0xC6, 0x36, 0xC2, 0x27, 0xD7, 0x21, 0x14, 0x78, 0x26, 0x72, 0x26, 0x7B, + 0x3F, 0x44, 0x0D, 0x00, 0x06, 0x37, 0x26, 0x2B, 0xD7, 0x41, 0xB9, 0x51, 0x10, 0x00, 0xB9, 0x61, + 0x0C, 0x00, 0xB9, 0x71, 0x08, 0x00, 0x0C, 0xF0, 0x00, 0x01, 0xF1, 0xF0, 0x38, 0x61, 0x0C, 0x00, + 0x38, 0x71, 0x08, 0x00, 0x24, 0xD1, 0xB1, 0x67, 0x18, 0x6E, 0x01, 0x00, 0x24, 0xA1, 0x99, 0x67, + 0x04, 0x00, 0x18, 0x6C, 0x01, 0x00, 0x13, 0xDD, 0x99, 0x67, 0x05, 0x00, 0x13, 0xAA, 0x38, 0x51, + 0x10, 0x00, 0xF2, 0x03, 0x13, 0x42, 0xF2, 0xCF, 0x24, 0x81, 0x13, 0x88, 0xC4, 0x8D, 0x24, 0xCC, + 0x92, 0x9D, 0x24, 0x91, 0x13, 0x99, 0xC4, 0x9D, 0x24, 0xEC, 0x92, 0x85, 0xF2, 0x86, 0x06, 0x39, + 0xD7, 0x31, 0x2F, 0x23, 0x0B, 0x00, 0x18, 0x42, 0x04, 0x00, 0x04, 0x71, 0x06, 0xF7, 0x53, 0xF4, + 0x06, 0x4F, 0x06, 0xFC, 0xD6, 0xF4, 0x82, 0x18, 0x34, 0xA1, 0x3F, 0x49, 0x0A, 0x00, 0x24, 0x38, + 0x26, 0x3B, 0xD7, 0x41, 0xB9, 0x51, 0x10, 0x00, 0xB9, 0x61, 0x0C, 0x00, 0x0C, 0xF0, 0x28, 0x01, + 0xF1, 0xF0, 0x38, 0x51, 0x10, 0x00, 0x38, 0x61, 0x0C, 0x00, 0x13, 0xAA, 0x24, 0x81, 0x13, 0x88, + 0xC6, 0x8D, 0x92, 0xDE, 0xF2, 0x14, 0x18, 0xF2, 0x05, 0x00, 0x53, 0x7F, 0x06, 0xFE, 0xD6, 0xF7, + 0x92, 0xE4, 0x98, 0x30, 0xEE, 0x16, 0x92, 0x02, 0x66, 0xC4, 0x98, 0x30, 0xEF, 0x16, 0x66, 0xE7, + 0x92, 0x03, 0x66, 0x74, 0x66, 0xC7, 0x24, 0x91, 0x13, 0x99, 0xF2, 0xE9, 0x58, 0xC1, 0x24, 0x00, + 0x06, 0x2A, 0x58, 0x81, 0x14, 0x00, 0x2C, 0x10, 0x34, 0x00, 0xE1, 0xF0, 0x0C, 0x70, 0xFC, 0x0A, + 0x18, 0x47, 0x98, 0x04, 0x3C, 0x10, 0x10, 0x00, 0xC4, 0x49, 0xD1, 0xC1, 0x04, 0x60, 0xD2, 0x63, + 0x0C, 0x50, 0x3A, 0x0E, 0x90, 0x35, 0x82, 0x07, 0x24, 0x61, 0x13, 0x66, 0xC4, 0x6D, 0x2C, 0x50, + 0x1C, 0x00, 0x92, 0xF9, 0x06, 0x56, 0x06, 0xF6, 0x24, 0x41, 0x57, 0x51, 0xD7, 0xF2, 0xD7, 0x22, + 0x2F, 0xD2, 0x07, 0x00, 0x99, 0x47, 0x98, 0x04, 0x04, 0x31, 0x3F, 0x45, 0x0F, 0x00, 0x26, 0x47, + 0x38, 0xCD, 0x70, 0x01, 0x28, 0xDD, 0x78, 0x01, 0x26, 0x36, 0x0C, 0xE0, 0x14, 0x00, 0x26, 0xE4, + 0x13, 0x33, 0x99, 0x3E, 0x2A, 0x03, 0xB9, 0xC4, 0x28, 0x03, 0xB9, 0xC4, 0x30, 0x03, 0x99, 0xDE, + 0x2B, 0x03, 0x98, 0xE7, 0x99, 0x04, 0x2C, 0x40, 0x18, 0x00, 0x92, 0x0C, 0x04, 0xE2, 0x99, 0xE4, + 0x2A, 0x03, 0x38, 0x47, 0x0C, 0x00, 0x08, 0xE0, 0x00, 0x01, 0x66, 0x4E, 0xB9, 0x47, 0x0C, 0x00, + 0xF2, 0x04, 0x04, 0xE1, 0x99, 0xE4, 0x2A, 0x03, 0x3F, 0x55, 0x0F, 0x00, 0x26, 0x57, 0x0C, 0x40, + 0x18, 0x00, 0x26, 0x27, 0x26, 0x45, 0x28, 0x22, 0x5E, 0x01, 0x99, 0x04, 0x2B, 0x03, 0x04, 0xF1, + 0x99, 0xF4, 0x28, 0x03, 0x99, 0x04, 0x29, 0x03, 0x04, 0x4C, 0x26, 0x45, 0xA9, 0x24, 0x28, 0x03, + 0x0C, 0x20, 0x2C, 0x01, 0xA9, 0x25, 0x3C, 0x03, 0xA9, 0x04, 0x2A, 0x03, 0xA9, 0x05, 0x38, 0x03, + 0xA9, 0x05, 0x3A, 0x03, 0x04, 0x51, 0x53, 0x56, 0x38, 0x67, 0x94, 0x04, 0x66, 0x56, 0xB9, 0x57, + 0x94, 0x04, 0x06, 0x63, 0x50, 0xC1, 0x06, 0x26, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x04, 0x60, 0x06, 0x52, 0x63, 0x56, 0xD4, 0x51, 0x13, 0x76, 0x92, 0x05, 0x24, 0x61, 0xC4, 0x64, + 0x92, 0xF9, 0x06, 0x76, 0x0C, 0x60, 0xFC, 0x0A, 0x18, 0x56, 0xA9, 0x04, 0x04, 0x41, 0x24, 0x51, + 0x99, 0x56, 0xA9, 0x04, 0x2F, 0x57, 0x07, 0x00, 0x26, 0x57, 0x26, 0x56, 0x26, 0x47, 0x99, 0x45, + 0x9C, 0x04, 0x04, 0x41, 0x99, 0x45, 0x9D, 0x04, 0x99, 0x05, 0x9E, 0x04, 0x04, 0x51, 0x53, 0x57, + 0x18, 0x76, 0xA8, 0x04, 0x66, 0x57, 0x99, 0x56, 0xA8, 0x04, 0xE1, 0xF0, 0x38, 0x70, 0xB0, 0x16, + 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0xD1, 0x81, 0x18, 0xF7, 0x8F, 0x00, 0x0C, 0x70, + 0xFC, 0x0A, 0x18, 0xA7, 0x24, 0x03, 0x18, 0x37, 0xAA, 0x04, 0xC4, 0xA0, 0x06, 0xE7, 0x92, 0x12, + 0xC4, 0x30, 0x92, 0x10, 0x18, 0x67, 0x99, 0x04, 0x06, 0x23, 0xC4, 0x60, 0x9A, 0x94, 0x00, 0x00, + 0xF8, 0x67, 0xB0, 0x0A, 0x0A, 0x90, 0x00, 0x00, 0x34, 0x61, 0xA9, 0x67, 0xB0, 0x0A, 0xFA, 0x8B, + 0x00, 0x00, 0xC4, 0x30, 0x99, 0x0E, 0xA9, 0x04, 0x06, 0x2E, 0x82, 0x0B, 0x04, 0xC0, 0x04, 0xDC, + 0x26, 0xDE, 0x06, 0x7E, 0x06, 0x5C, 0x06, 0x4C, 0x04, 0xB1, 0x1C, 0x90, 0x10, 0x00, 0xF2, 0x12, + 0x0C, 0x20, 0x98, 0x0F, 0x04, 0x4C, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x18, 0x2E, 0x23, 0x03, + 0x0B, 0x71, 0x01, 0x00, 0xF2, 0x68, 0x98, 0x87, 0x9C, 0x04, 0x92, 0x07, 0x24, 0x73, 0xC6, 0x7D, + 0x82, 0x21, 0xC6, 0x43, 0xA2, 0xF9, 0xF2, 0x1E, 0x18, 0x6E, 0x23, 0x03, 0x34, 0x81, 0x63, 0x68, + 0xD4, 0x61, 0x82, 0x15, 0x98, 0x67, 0x9E, 0x04, 0x82, 0x06, 0x99, 0x07, 0x9E, 0x04, 0x99, 0x97, + 0x9D, 0x04, 0xF2, 0x09, 0x18, 0x67, 0x9D, 0x04, 0xCC, 0x60, 0xEF, 0x00, 0xD2, 0x04, 0x24, 0x61, + 0x99, 0x67, 0x9D, 0x04, 0x06, 0x6B, 0x53, 0x68, 0x66, 0x56, 0x66, 0xC6, 0x24, 0x41, 0x13, 0x44, + 0xF2, 0xDE, 0x04, 0x60, 0x99, 0x3E, 0xA9, 0x04, 0x06, 0x72, 0x06, 0x46, 0x04, 0xD1, 0xC6, 0x63, + 0xB2, 0x22, 0x98, 0x27, 0x9C, 0x04, 0x82, 0x1B, 0x06, 0x2D, 0x53, 0x24, 0xD6, 0x25, 0x92, 0x15, + 0x18, 0x27, 0x9E, 0x04, 0xC6, 0x2F, 0xB2, 0x05, 0x24, 0x21, 0x99, 0x27, 0x9E, 0x04, 0xF2, 0x0D, + 0x98, 0x2E, 0xA9, 0x04, 0x82, 0x04, 0x34, 0x21, 0x99, 0x2E, 0xA9, 0x04, 0x99, 0x07, 0x9C, 0x04, + 0x99, 0x07, 0x9D, 0x04, 0x99, 0x07, 0x9E, 0x04, 0x24, 0x61, 0x13, 0x66, 0x24, 0x41, 0xC4, 0x44, + 0x24, 0x73, 0x92, 0xDE, 0x04, 0xB0, 0x06, 0xDB, 0x04, 0x91, 0xC6, 0xBA, 0xB2, 0x14, 0x18, 0x7E, + 0x23, 0x03, 0x63, 0x7D, 0xD4, 0x71, 0x82, 0x0C, 0x06, 0x7C, 0x73, 0x7D, 0xD4, 0x71, 0x92, 0x06, + 0x06, 0x29, 0x53, 0x2D, 0x13, 0x22, 0x0B, 0x71, 0x01, 0x00, 0x24, 0xB1, 0x13, 0xBB, 0x24, 0xD1, + 0xC4, 0xD4, 0x92, 0xEC, 0x78, 0x7E, 0xB0, 0x0A, 0x04, 0x21, 0xC4, 0x70, 0x02, 0x04, 0x26, 0x72, + 0xA9, 0x7E, 0xB0, 0x0A, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, + 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0xD1, 0x81, 0x06, 0xE2, 0x78, 0x7E, 0x04, 0x00, + 0x70, 0x22, 0x36, 0x27, 0xC4, 0x20, 0x32, 0x02, 0x16, 0x22, 0x78, 0xDE, 0x02, 0x00, 0x78, 0x7E, + 0x06, 0x00, 0x36, 0xD7, 0xC4, 0xD0, 0x32, 0x02, 0x16, 0xDD, 0x06, 0x32, 0x6B, 0x13, 0x00, 0x00, + 0x06, 0x3D, 0x06, 0xC2, 0x06, 0x2D, 0x6B, 0x13, 0x00, 0x00, 0x26, 0x2C, 0x0C, 0x30, 0x00, 0x01, + 0x0C, 0xF0, 0xE8, 0x01, 0xF1, 0xF0, 0x86, 0xD2, 0x8A, 0xB9, 0x00, 0x00, 0x38, 0x60, 0x08, 0x0B, + 0x08, 0x70, 0x02, 0x00, 0x2C, 0x70, 0x00, 0x03, 0xD6, 0x67, 0x82, 0x05, 0x0C, 0x70, 0x2C, 0x01, + 0xFA, 0xAB, 0x00, 0x00, 0x98, 0x3E, 0x19, 0x00, 0x82, 0x0D, 0x28, 0x7E, 0x12, 0x00, 0xC4, 0x7A, + 0xCA, 0xA5, 0x00, 0x00, 0x28, 0x2E, 0x14, 0x00, 0x24, 0x31, 0x6B, 0x13, 0x00, 0x00, 0xFA, 0x99, + 0x00, 0x00, 0x78, 0x2E, 0x10, 0x00, 0x04, 0x31, 0x0C, 0xF0, 0xBC, 0x00, 0xF1, 0xF0, 0xA8, 0x9E, + 0x0E, 0x00, 0x06, 0xC2, 0x2F, 0xBD, 0x0D, 0x00, 0x92, 0x04, 0xA9, 0xDE, 0x0E, 0x00, 0xF2, 0x14, + 0x2F, 0x7D, 0x0B, 0x00, 0x06, 0x67, 0x57, 0x62, 0x3F, 0x27, 0x06, 0x00, 0x0C, 0x30, 0x64, 0x00, + 0x26, 0x22, 0xCB, 0x14, 0x00, 0x00, 0x06, 0xA2, 0x04, 0x3A, 0x06, 0x29, 0xAB, 0x15, 0x00, 0x00, + 0x26, 0x2A, 0xA9, 0x2E, 0x0E, 0x00, 0xA8, 0x7E, 0x0E, 0x00, 0x92, 0x04, 0x04, 0x71, 0xA9, 0x7E, + 0x0E, 0x00, 0x06, 0x2D, 0xD7, 0x21, 0x0C, 0x30, 0x64, 0x00, 0x26, 0x2B, 0xCB, 0x14, 0x00, 0x00, + 0x28, 0x7E, 0x12, 0x00, 0x06, 0xA2, 0x2F, 0x67, 0x07, 0x00, 0x26, 0x76, 0x06, 0x67, 0x57, 0x62, + 0x3F, 0x27, 0x06, 0x00, 0x26, 0x22, 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x26, 0x2A, + 0xA3, 0x22, 0x82, 0x04, 0xA9, 0x2E, 0x12, 0x00, 0xF2, 0x04, 0x04, 0x71, 0xA9, 0x7E, 0x12, 0x00, + 0x26, 0xBD, 0xD7, 0xB1, 0x2F, 0x2D, 0x0B, 0x00, 0x26, 0x22, 0x0C, 0x30, 0x64, 0x00, 0xCB, 0x14, + 0x00, 0x00, 0x28, 0x7E, 0x10, 0x00, 0xE7, 0x70, 0x26, 0x27, 0xA3, 0x72, 0x92, 0x02, 0x04, 0x71, + 0xA9, 0x7E, 0x10, 0x00, 0x28, 0xDE, 0x10, 0x00, 0xC6, 0xDC, 0xA2, 0x0B, 0x2F, 0x7D, 0x0D, 0x00, + 0x26, 0x7D, 0x06, 0x67, 0xD7, 0x62, 0x2F, 0x26, 0x07, 0x00, 0x26, 0x2D, 0x06, 0x3C, 0xF2, 0x0A, + 0x2F, 0x7C, 0x0C, 0x00, 0x26, 0x7C, 0x06, 0x67, 0xD7, 0x62, 0x2F, 0x26, 0x07, 0x00, 0x26, 0x2C, + 0x06, 0x3D, 0xCB, 0x14, 0x00, 0x00, 0x06, 0x3D, 0x6B, 0x13, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, + 0xCB, 0x14, 0x00, 0x00, 0x28, 0xCE, 0x12, 0x00, 0x28, 0x7E, 0x0E, 0x00, 0x26, 0xCD, 0x26, 0xC7, + 0x26, 0xC2, 0x06, 0x3D, 0x06, 0x2D, 0x6B, 0x13, 0x00, 0x00, 0x06, 0x3C, 0x6B, 0x13, 0x00, 0x00, + 0x08, 0x30, 0x01, 0x00, 0x2C, 0x30, 0x90, 0x5F, 0xCB, 0x14, 0x00, 0x00, 0x2F, 0xBC, 0x0D, 0x00, + 0x3F, 0x22, 0x0B, 0x00, 0x23, 0x22, 0xCC, 0x20, 0x3B, 0x00, 0x0C, 0x70, 0x3C, 0x00, 0xC2, 0x04, + 0xA9, 0x2E, 0x14, 0x00, 0xF2, 0x03, 0xA9, 0x7E, 0x14, 0x00, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, + 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xE2, + 0x04, 0x24, 0x06, 0xD3, 0x04, 0x44, 0x06, 0x3E, 0x26, 0x2E, 0x0C, 0xC0, 0x14, 0x00, 0xEB, 0x73, + 0x03, 0x00, 0x26, 0xCD, 0x06, 0x3C, 0x04, 0x44, 0x06, 0x2E, 0xEB, 0x73, 0x03, 0x00, 0x04, 0x28, + 0x26, 0x2E, 0x06, 0x3C, 0x04, 0x44, 0xEB, 0x73, 0x03, 0x00, 0x28, 0x7D, 0x02, 0x00, 0xA9, 0x7E, + 0x0C, 0x00, 0x28, 0x7D, 0x1C, 0x00, 0x99, 0x7E, 0x17, 0x00, 0x98, 0x7E, 0x19, 0x00, 0x82, 0x09, + 0x18, 0x7E, 0x18, 0x00, 0x99, 0x0E, 0x19, 0x00, 0x24, 0x71, 0x99, 0x7E, 0x18, 0x00, 0xF2, 0x22, + 0x18, 0x6E, 0x18, 0x00, 0xCC, 0x60, 0xEF, 0x00, 0xD2, 0x1D, 0x18, 0x50, 0x95, 0x0F, 0xC4, 0x52, + 0x38, 0x70, 0xB0, 0x16, 0xC2, 0x04, 0x28, 0x77, 0x30, 0x00, 0xF2, 0x08, 0xC4, 0x52, 0x92, 0x04, + 0x28, 0x77, 0x2E, 0x00, 0xF2, 0x03, 0x28, 0x77, 0x2C, 0x00, 0x20, 0x5D, 0x26, 0x55, 0x0C, 0x40, + 0x28, 0x08, 0x26, 0x54, 0x70, 0x55, 0xF7, 0x70, 0xC6, 0x57, 0x02, 0x04, 0x24, 0x61, 0x99, 0x6E, + 0x18, 0x00, 0x06, 0x2E, 0x8B, 0x7E, 0x01, 0x00, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, + 0x3C, 0x10, 0xB8, 0x06, 0xD9, 0xC1, 0xA8, 0x06, 0x38, 0x70, 0xB0, 0x16, 0xD9, 0x81, 0x98, 0x06, + 0x0C, 0xE0, 0xFC, 0x0A, 0x0C, 0x50, 0x8F, 0x00, 0x18, 0xCE, 0x99, 0x04, 0x26, 0x57, 0x10, 0x55, + 0xC4, 0xC2, 0xB9, 0x51, 0x80, 0x06, 0x92, 0x2C, 0x78, 0x5E, 0xE8, 0x00, 0x78, 0x6E, 0xEC, 0x00, + 0x3F, 0x66, 0x05, 0x00, 0xC4, 0x60, 0x32, 0x02, 0x16, 0x66, 0x99, 0x0E, 0xF2, 0x00, 0x28, 0x47, + 0x92, 0x00, 0x78, 0x5E, 0xEE, 0x00, 0x43, 0x36, 0xC6, 0x34, 0x78, 0x6E, 0xEA, 0x00, 0x32, 0x18, + 0x36, 0x65, 0xC4, 0x60, 0x32, 0x02, 0x16, 0x66, 0x28, 0x57, 0x94, 0x00, 0x43, 0x66, 0xC6, 0x65, + 0x32, 0x04, 0x18, 0x67, 0x99, 0x00, 0xF2, 0x0A, 0x28, 0x57, 0x96, 0x00, 0xC6, 0x65, 0x32, 0x04, + 0x18, 0x67, 0x9A, 0x00, 0xF2, 0x03, 0x18, 0x67, 0x9B, 0x00, 0x99, 0x6E, 0xF2, 0x00, 0x18, 0x6E, + 0x9A, 0x04, 0x18, 0x77, 0x98, 0x00, 0xC6, 0x67, 0xB2, 0x07, 0x98, 0x7E, 0xF0, 0x00, 0x82, 0x04, + 0x04, 0x71, 0x99, 0x7E, 0xF1, 0x00, 0x98, 0x70, 0xE4, 0x16, 0x82, 0x0B, 0x08, 0x70, 0x00, 0x80, + 0x38, 0x61, 0x80, 0x06, 0x18, 0x77, 0x8C, 0xDC, 0x26, 0x76, 0x13, 0x77, 0xB9, 0x71, 0x80, 0x06, + 0x38, 0x7E, 0x0C, 0x00, 0xDC, 0x70, 0x00, 0xF0, 0x82, 0x06, 0xCB, 0x57, 0x01, 0x00, 0x04, 0xC0, + 0xFA, 0xE5, 0x01, 0x00, 0x98, 0xAE, 0x1F, 0x03, 0x92, 0x0C, 0xC4, 0xC0, 0x92, 0x0A, 0xF8, 0x7E, + 0xB0, 0x0A, 0x0A, 0xDC, 0x01, 0x00, 0x34, 0x71, 0xA9, 0x7E, 0xB0, 0x0A, 0xFA, 0xD7, 0x01, 0x00, + 0xC4, 0xC0, 0x99, 0x0E, 0x98, 0x04, 0x92, 0x10, 0x0C, 0x20, 0x24, 0x0E, 0x06, 0x3C, 0x0C, 0x40, + 0x6C, 0x01, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0xC6, 0xCA, 0x32, 0x4D, 0x13, 0x2C, 0xEB, 0x69, + 0x01, 0x00, 0x24, 0xC1, 0xF2, 0xFA, 0x04, 0xD0, 0x06, 0xBD, 0x06, 0x9D, 0x04, 0x82, 0xC6, 0xA9, + 0xC2, 0x17, 0xC4, 0xA1, 0x34, 0x81, 0x13, 0x88, 0x9A, 0x9F, 0x00, 0x00, 0xC4, 0xC1, 0x9A, 0x9C, + 0x00, 0x00, 0x18, 0x7E, 0xDF, 0x00, 0xC4, 0x71, 0x92, 0x48, 0x18, 0x7E, 0xE0, 0x00, 0xC4, 0x71, + 0x92, 0x44, 0x38, 0xBE, 0x94, 0x04, 0x06, 0xDA, 0x06, 0x9A, 0xC4, 0x80, 0x92, 0xE9, 0x04, 0x90, + 0x99, 0xCE, 0x98, 0x04, 0x06, 0x89, 0x04, 0x61, 0xC6, 0x8A, 0x32, 0x10, 0x06, 0x7D, 0x73, 0x78, + 0xD4, 0x71, 0x9A, 0x53, 0x01, 0x00, 0x13, 0x28, 0xB9, 0x61, 0x94, 0x06, 0xEB, 0x69, 0x01, 0x00, + 0x86, 0x22, 0x38, 0x61, 0x94, 0x06, 0x9A, 0x43, 0x01, 0x00, 0x04, 0x80, 0x08, 0x70, 0xFF, 0xFE, + 0x0C, 0xD0, 0x24, 0x0E, 0x06, 0xA8, 0x2C, 0x70, 0xFF, 0xFF, 0x2F, 0x69, 0x0C, 0x00, 0xC6, 0x86, + 0x32, 0x0A, 0x98, 0x6D, 0x16, 0x00, 0x9A, 0x3C, 0x01, 0x00, 0x24, 0xA1, 0xC4, 0xAD, 0x2C, 0xD0, + 0x1C, 0x00, 0x92, 0xF4, 0x98, 0x7E, 0x98, 0x04, 0x92, 0x08, 0x0C, 0x70, 0x14, 0x00, 0xA9, 0x7E, + 0xB0, 0x0A, 0x04, 0xC1, 0xFA, 0x73, 0x01, 0x00, 0x04, 0xC1, 0xC6, 0x7C, 0xCA, 0x6F, 0x01, 0x00, + 0x6B, 0x10, 0x03, 0x00, 0xFA, 0x6B, 0x01, 0x00, 0x38, 0x2E, 0x94, 0x04, 0x0C, 0xF0, 0x80, 0x00, + 0xF1, 0xF0, 0x06, 0x72, 0x57, 0x71, 0xD7, 0x22, 0x36, 0x27, 0x26, 0x2E, 0x78, 0x52, 0x30, 0x03, + 0x78, 0x7E, 0x70, 0x01, 0x0C, 0x60, 0x28, 0x03, 0x3F, 0x77, 0x05, 0x00, 0xC4, 0x70, 0x26, 0x62, + 0x32, 0x02, 0x16, 0x77, 0x78, 0x22, 0x32, 0x03, 0x78, 0x5E, 0x72, 0x01, 0x36, 0x25, 0xC4, 0x20, + 0x32, 0x02, 0x16, 0x22, 0x28, 0x56, 0x14, 0x00, 0xB9, 0x61, 0x94, 0x06, 0x06, 0x32, 0xB9, 0x51, + 0x8C, 0x06, 0xB9, 0x71, 0x90, 0x06, 0x6B, 0x13, 0x00, 0x00, 0x38, 0x71, 0x90, 0x06, 0x06, 0x42, + 0x06, 0x37, 0x06, 0x27, 0xB9, 0x41, 0x88, 0x06, 0x6B, 0x13, 0x00, 0x00, 0x38, 0x51, 0x8C, 0x06, + 0x38, 0x41, 0x88, 0x06, 0x06, 0x35, 0x26, 0x42, 0x06, 0x25, 0xB9, 0x41, 0x88, 0x06, 0x6B, 0x13, + 0x00, 0x00, 0x38, 0x41, 0x88, 0x06, 0x38, 0x61, 0x94, 0x06, 0xC6, 0x42, 0xBA, 0x7F, 0xFF, 0xFF, + 0x06, 0x26, 0x0C, 0x30, 0x58, 0x0C, 0x04, 0xD1, 0xCB, 0x8C, 0x01, 0x00, 0x06, 0x9D, 0x38, 0xBE, + 0x94, 0x04, 0xFA, 0x74, 0xFF, 0xFF, 0x0C, 0x20, 0xE4, 0x05, 0x0C, 0x30, 0x48, 0x05, 0x26, 0x21, + 0x26, 0x31, 0x0B, 0x5A, 0x01, 0x00, 0x04, 0x70, 0x0C, 0x90, 0x24, 0x0E, 0x0C, 0x40, 0x2C, 0x0E, + 0x06, 0x57, 0x06, 0x67, 0xC6, 0x7C, 0xB2, 0x56, 0x98, 0x39, 0x16, 0x00, 0x82, 0x4C, 0x04, 0x31, + 0x53, 0x36, 0xD6, 0x3B, 0x92, 0x46, 0x06, 0x29, 0xB9, 0x41, 0x88, 0x06, 0xB9, 0x51, 0x8C, 0x06, + 0xB9, 0x61, 0x94, 0x06, 0xB9, 0x71, 0x90, 0x06, 0xAB, 0x3B, 0x01, 0x00, 0xC6, 0x28, 0x38, 0x41, + 0x88, 0x06, 0x38, 0x51, 0x8C, 0x06, 0x38, 0x61, 0x94, 0x06, 0x38, 0x71, 0x90, 0x06, 0x92, 0x31, + 0x2F, 0x35, 0x05, 0x00, 0x04, 0x21, 0x26, 0x25, 0x26, 0x53, 0x0C, 0x30, 0xE4, 0x05, 0x26, 0x31, + 0x57, 0x51, 0x26, 0x53, 0x04, 0x31, 0x91, 0x35, 0x20, 0x34, 0xB9, 0x21, 0x84, 0x06, 0x28, 0x29, + 0x14, 0x00, 0xA9, 0x35, 0x02, 0x00, 0x28, 0x34, 0x02, 0x00, 0x99, 0x65, 0x01, 0x00, 0xA9, 0x35, + 0x04, 0x00, 0x06, 0x32, 0xB9, 0x41, 0x88, 0x06, 0xB9, 0x51, 0x8C, 0x06, 0xB9, 0x61, 0x94, 0x06, + 0xB9, 0x71, 0x90, 0x06, 0x6B, 0x13, 0x00, 0x00, 0x38, 0x51, 0x8C, 0x06, 0x38, 0x71, 0x90, 0x06, + 0x38, 0x61, 0x94, 0x06, 0xB9, 0x25, 0x08, 0x00, 0x38, 0x41, 0x88, 0x06, 0x38, 0x51, 0x84, 0x06, + 0x24, 0x71, 0x13, 0x77, 0x24, 0x61, 0xC4, 0x6D, 0x2C, 0x90, 0x1C, 0x00, 0x2C, 0x40, 0x1C, 0x00, + 0x92, 0xAA, 0x04, 0x70, 0x06, 0x4E, 0x06, 0x67, 0x04, 0x31, 0xC6, 0x6A, 0x32, 0x1F, 0x06, 0x53, + 0x53, 0x56, 0xD6, 0x5D, 0x92, 0x17, 0x2F, 0x57, 0x07, 0x00, 0x26, 0x57, 0x0C, 0x20, 0x48, 0x05, + 0x26, 0x21, 0x57, 0x51, 0x26, 0x52, 0x28, 0x24, 0x70, 0x01, 0x91, 0x35, 0x99, 0x65, 0x01, 0x00, + 0xA9, 0x25, 0x02, 0x00, 0x28, 0x24, 0x72, 0x01, 0xB9, 0x05, 0x08, 0x00, 0x24, 0x71, 0xA9, 0x25, + 0x04, 0x00, 0x24, 0x61, 0x2C, 0x40, 0x20, 0x00, 0xF2, 0xE1, 0x04, 0x61, 0xB9, 0x00, 0xC4, 0x16, + 0x0C, 0x30, 0xE4, 0x05, 0x0C, 0x40, 0x48, 0x05, 0x99, 0x60, 0xEF, 0x16, 0x06, 0x21, 0x26, 0x31, + 0x26, 0x41, 0x99, 0x00, 0xEE, 0x16, 0xCB, 0x5C, 0x01, 0x00, 0x04, 0x74, 0x06, 0x92, 0x26, 0x71, + 0x04, 0x60, 0x04, 0x51, 0xC6, 0x69, 0x3A, 0xD2, 0xFE, 0xFF, 0x10, 0x47, 0x06, 0x34, 0x57, 0x31, + 0xD7, 0x42, 0x3F, 0x23, 0x04, 0x00, 0x18, 0x37, 0x01, 0x00, 0xB9, 0x51, 0x8C, 0x06, 0x26, 0x2E, + 0xD7, 0x32, 0x26, 0x3E, 0x2C, 0x20, 0x28, 0x03, 0x2C, 0x30, 0x5C, 0x01, 0xB9, 0x61, 0x94, 0x06, + 0xB9, 0x71, 0x90, 0x06, 0xCB, 0x8C, 0x01, 0x00, 0x38, 0x71, 0x90, 0x06, 0x38, 0x51, 0x8C, 0x06, + 0x38, 0x61, 0x94, 0x06, 0x10, 0x47, 0x06, 0x35, 0x53, 0x34, 0x18, 0x47, 0x01, 0x00, 0x06, 0x25, + 0x53, 0x24, 0x66, 0xB3, 0x66, 0xD2, 0x24, 0x61, 0x24, 0x78, 0xF2, 0xD5, 0x34, 0x21, 0x06, 0x76, + 0x53, 0x72, 0x24, 0x91, 0x66, 0xB7, 0x13, 0x99, 0x24, 0x81, 0xFA, 0xA7, 0xFE, 0xFF, 0x06, 0x6B, + 0x73, 0x6A, 0xD4, 0x61, 0x92, 0x3F, 0x18, 0x6D, 0x19, 0x00, 0x38, 0x51, 0x80, 0x06, 0xC6, 0x65, + 0xB2, 0x17, 0x06, 0x2D, 0xB9, 0x71, 0x90, 0x06, 0xAB, 0x3B, 0x01, 0x00, 0xC4, 0x21, 0x38, 0x71, + 0x90, 0x06, 0x92, 0x0E, 0x18, 0x6D, 0x19, 0x00, 0x06, 0x2D, 0x24, 0x61, 0x99, 0x6D, 0x19, 0x00, + 0xB9, 0x71, 0x90, 0x06, 0x8B, 0x7E, 0x01, 0x00, 0x38, 0x71, 0x90, 0x06, 0xF2, 0x23, 0x98, 0x6E, + 0x98, 0x04, 0x82, 0x04, 0x34, 0x61, 0x99, 0x6E, 0x98, 0x04, 0x04, 0x51, 0x38, 0x4E, 0x94, 0x04, + 0x06, 0x65, 0x53, 0x6A, 0x15, 0x66, 0x56, 0x64, 0xB9, 0x6E, 0x94, 0x04, 0x99, 0x0D, 0x16, 0x00, + 0x99, 0x0D, 0x18, 0x00, 0x99, 0x0D, 0x19, 0x00, 0x99, 0x0D, 0x1B, 0x00, 0x99, 0x5E, 0xF0, 0x00, + 0x18, 0x6D, 0x1A, 0x00, 0xC4, 0x62, 0x92, 0x06, 0x38, 0x6E, 0x0C, 0x00, 0x56, 0x67, 0xB9, 0x6E, + 0x0C, 0x00, 0x24, 0x81, 0x13, 0x88, 0xFA, 0x82, 0xFE, 0xFF, 0x06, 0x2C, 0x58, 0xC1, 0xA8, 0x06, + 0x58, 0x81, 0x98, 0x06, 0x2C, 0x10, 0xB8, 0x06, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x18, 0xC1, 0xE1, + 0x0B, 0x92, 0x01, 0x00, 0xC4, 0x21, 0x06, 0xE2, 0x92, 0x03, 0x8B, 0x2C, 0x02, 0x00, 0x6B, 0x73, + 0x01, 0x00, 0x66, 0x2E, 0x40, 0xE1, 0x13, 0x22, 0x24, 0x18, 0xE1, 0xF0, 0xE1, 0xF0, 0x00, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x14, 0x0C, 0x70, 0xFC, 0x0A, 0xB1, 0xF1, + 0x98, 0x47, 0x1F, 0x03, 0x06, 0x67, 0x82, 0x07, 0x38, 0x30, 0xB0, 0x16, 0x0C, 0x50, 0x74, 0x0C, + 0x04, 0x70, 0xF2, 0x0A, 0x38, 0x67, 0x0C, 0x00, 0x1C, 0x50, 0x01, 0x80, 0x56, 0x65, 0xB9, 0x67, + 0x0C, 0x00, 0xF2, 0x18, 0x24, 0x71, 0xC6, 0x74, 0x32, 0x15, 0x20, 0x25, 0x18, 0xF3, 0x7B, 0x00, + 0x2C, 0x50, 0x20, 0x00, 0xC6, 0xF2, 0xB2, 0xF7, 0x38, 0x76, 0x0C, 0x00, 0x99, 0x06, 0x1C, 0x03, + 0x1C, 0x50, 0x01, 0x03, 0x56, 0x75, 0x6C, 0x70, 0x00, 0x80, 0x99, 0x06, 0x1F, 0x03, 0xB9, 0x76, + 0x0C, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x08, 0xD0, + 0x06, 0x00, 0x0C, 0xC0, 0x14, 0x0B, 0x04, 0xE0, 0x2C, 0xD0, 0x00, 0xBD, 0x06, 0x2E, 0x0C, 0x30, + 0x17, 0x00, 0xCB, 0x14, 0x00, 0x00, 0x2C, 0xE0, 0x00, 0x4B, 0xC6, 0xED, 0x2C, 0x20, 0xA1, 0x01, + 0xB1, 0x2C, 0x24, 0xC4, 0x92, 0xF4, 0x08, 0xD0, 0x02, 0x00, 0x0C, 0xC0, 0x74, 0x0B, 0x04, 0xE0, + 0x2C, 0xD0, 0xA0, 0x4E, 0x06, 0x2E, 0x04, 0x3E, 0xCB, 0x14, 0x00, 0x00, 0x2C, 0xE0, 0x30, 0x2A, + 0xC6, 0xED, 0x2C, 0x20, 0x81, 0x01, 0xB1, 0x2C, 0x24, 0xC4, 0x92, 0xF5, 0x50, 0xC1, 0x0C, 0x60, + 0x2B, 0x00, 0xB9, 0x60, 0xD4, 0x0B, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x2F, 0x72, 0x02, 0x00, + 0x34, 0x18, 0x26, 0x72, 0xC1, 0xE1, 0x06, 0xE7, 0x57, 0xE2, 0x26, 0x7E, 0x26, 0x27, 0x2C, 0x20, + 0xAC, 0x04, 0x0C, 0xE0, 0xFC, 0x0A, 0x26, 0xE2, 0x14, 0x71, 0x04, 0x26, 0xA1, 0x7E, 0xA9, 0x7E, + 0x02, 0x00, 0x26, 0x2E, 0x04, 0x30, 0x0C, 0x40, 0x24, 0x00, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, + 0x04, 0x71, 0x99, 0x7E, 0x04, 0x00, 0x38, 0x70, 0xB0, 0x16, 0xA9, 0x0E, 0x2A, 0x00, 0x0C, 0x20, + 0x2E, 0x00, 0x18, 0x77, 0x9D, 0x00, 0x26, 0x2E, 0x99, 0x7E, 0x2C, 0x00, 0x04, 0x30, 0x04, 0x46, + 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x99, 0x0E, 0x2D, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, + 0x34, 0x18, 0xC1, 0xE1, 0x04, 0xE0, 0x06, 0x2E, 0x6B, 0xBE, 0x01, 0x00, 0x24, 0xE1, 0xC4, 0xED, + 0x92, 0xFB, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, + 0xD1, 0x81, 0x06, 0xE2, 0x06, 0x93, 0x06, 0x25, 0x06, 0x36, 0x06, 0xC4, 0x06, 0xA5, 0x18, 0x81, + 0x20, 0x00, 0x28, 0xD1, 0x24, 0x00, 0x28, 0xB1, 0x28, 0x00, 0x0C, 0xF0, 0x98, 0x00, 0xF1, 0xF0, + 0x06, 0x32, 0x06, 0x2E, 0xAB, 0x15, 0x00, 0x00, 0x06, 0xE2, 0x06, 0x38, 0x06, 0x2A, 0x0C, 0xF0, + 0x98, 0x00, 0xF1, 0xF0, 0xC6, 0xCD, 0x06, 0x32, 0x32, 0x03, 0x43, 0x2E, 0xF2, 0x14, 0x06, 0x29, + 0xAB, 0x15, 0x00, 0x00, 0xC6, 0xCB, 0x06, 0x32, 0x32, 0x0D, 0x36, 0x3E, 0x3F, 0x2D, 0x0C, 0x00, + 0x6B, 0x13, 0x00, 0x00, 0x3F, 0x3D, 0x0B, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x26, 0x2E, 0x43, 0x22, + 0xF2, 0x02, 0x43, 0x22, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x28, 0xD4, 0x0E, 0x00, 0x38, 0xF1, 0x10, 0x00, 0x78, 0xE1, + 0x14, 0x00, 0xC6, 0x5D, 0x04, 0x75, 0x12, 0x11, 0x28, 0xD4, 0x0A, 0x00, 0x04, 0x74, 0xC6, 0x5D, + 0x12, 0x0C, 0x28, 0xD4, 0x06, 0x00, 0x04, 0x73, 0xC6, 0x5D, 0x12, 0x07, 0x28, 0x44, 0x02, 0x00, + 0x04, 0x71, 0xC6, 0x54, 0x02, 0x02, 0x04, 0x72, 0x10, 0x56, 0x36, 0x75, 0xB3, 0x57, 0x70, 0x7F, + 0x02, 0x05, 0xC6, 0x7E, 0x92, 0x0F, 0xA1, 0x0F, 0xF2, 0x0F, 0xC4, 0x50, 0x82, 0x05, 0x16, 0x5E, + 0xC6, 0x75, 0x92, 0x04, 0xF2, 0xF9, 0xC4, 0x70, 0x02, 0x03, 0x34, 0x71, 0xF2, 0x04, 0xC4, 0x70, + 0x82, 0x03, 0x24, 0x71, 0xA1, 0x7F, 0x70, 0x5F, 0x10, 0x76, 0xC6, 0x5E, 0x92, 0x05, 0xC4, 0x74, + 0xD2, 0x0A, 0x24, 0x71, 0xF2, 0x07, 0x16, 0xEE, 0xC6, 0x5E, 0x92, 0x05, 0xC4, 0x71, 0xC2, 0x03, + 0x34, 0x71, 0x91, 0x76, 0x10, 0x76, 0xCB, 0x74, 0x03, 0x00, 0x01, 0x00, 0x05, 0x00, 0x30, 0x00, + 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0x28, 0x00, 0x30, 0x00, 0x04, 0x79, 0x91, 0x72, 0x04, 0x77, + 0xF2, 0x10, 0x04, 0x77, 0x91, 0x72, 0x04, 0x75, 0xF2, 0x0C, 0x04, 0x75, 0x91, 0x72, 0x04, 0x73, + 0xF2, 0x08, 0x04, 0x73, 0x91, 0x72, 0x04, 0x72, 0xF2, 0x04, 0x04, 0x72, 0x91, 0x72, 0x04, 0x71, + 0x50, 0xC1, 0x91, 0x73, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x2F, 0x72, 0x02, 0x00, + 0x26, 0x72, 0x06, 0x67, 0x3C, 0x10, 0x40, 0x00, 0x57, 0x62, 0xD9, 0xC1, 0x30, 0x00, 0x26, 0x76, + 0x04, 0xC1, 0x26, 0xC2, 0x26, 0x27, 0x0C, 0xE0, 0xFC, 0x0A, 0x57, 0xC1, 0x2C, 0x20, 0xAC, 0x04, + 0xD9, 0x81, 0x20, 0x00, 0x26, 0xCE, 0x26, 0xE2, 0x18, 0x7E, 0x04, 0x00, 0x99, 0x01, 0x0D, 0x00, + 0x99, 0x01, 0x0C, 0x00, 0xC4, 0x71, 0x06, 0xB3, 0x0C, 0xD0, 0x64, 0x00, 0xC2, 0x17, 0x78, 0x2E, + 0x06, 0x00, 0x78, 0x7E, 0x0A, 0x00, 0x36, 0x27, 0xC4, 0x20, 0x32, 0x02, 0x16, 0x22, 0x78, 0x3E, + 0x08, 0x00, 0x78, 0x7E, 0x0C, 0x00, 0x43, 0x22, 0x36, 0x37, 0xC4, 0x30, 0x32, 0x02, 0x16, 0x33, + 0x43, 0x33, 0x0C, 0xF0, 0xBC, 0x00, 0xF1, 0xF0, 0x06, 0xD2, 0x78, 0x7E, 0x2E, 0x00, 0x78, 0x2E, + 0x30, 0x00, 0x18, 0x3E, 0x2D, 0x00, 0xA9, 0x7E, 0x30, 0x00, 0xA9, 0x2E, 0x32, 0x00, 0x26, 0x27, + 0x24, 0x31, 0x26, 0x2D, 0xAB, 0x15, 0x00, 0x00, 0x99, 0xD0, 0xE1, 0x16, 0x0C, 0x70, 0x2A, 0x00, + 0xA9, 0xDE, 0x2E, 0x00, 0x26, 0x7E, 0xB1, 0x71, 0x38, 0x70, 0xB0, 0x16, 0x06, 0x52, 0x18, 0x77, + 0x9C, 0x00, 0x04, 0x2D, 0x04, 0x3C, 0x0C, 0x60, 0x2C, 0x00, 0xB9, 0x71, 0x04, 0x00, 0x26, 0x21, + 0x26, 0x31, 0x06, 0x4B, 0x26, 0x6E, 0x0B, 0xC6, 0x01, 0x00, 0x18, 0x7E, 0x2C, 0x00, 0x68, 0x61, + 0x0D, 0x00, 0x04, 0x5C, 0x26, 0x51, 0x60, 0x55, 0x34, 0x71, 0x26, 0x77, 0x33, 0x77, 0x14, 0x41, + 0x26, 0x46, 0xB9, 0x71, 0x10, 0x00, 0xB9, 0x51, 0x14, 0x00, 0x04, 0x70, 0x34, 0x51, 0xB9, 0x41, + 0x18, 0x00, 0xB9, 0x51, 0x1C, 0x00, 0x06, 0xA7, 0x06, 0x5E, 0x06, 0x37, 0x06, 0x97, 0x06, 0x27, + 0x06, 0xF7, 0x06, 0x47, 0x78, 0x85, 0x06, 0x00, 0x26, 0x48, 0x78, 0x85, 0x08, 0x00, 0x26, 0xF8, + 0x38, 0x81, 0x18, 0x00, 0xC6, 0x78, 0x82, 0x08, 0x38, 0x81, 0x1C, 0x00, 0xC6, 0x78, 0x92, 0x06, + 0x06, 0xAF, 0x06, 0x34, 0xF2, 0x03, 0x06, 0x9F, 0x06, 0x24, 0x24, 0x71, 0xC4, 0x79, 0x24, 0x54, + 0x92, 0xEA, 0x38, 0x71, 0x10, 0x00, 0x38, 0x41, 0x14, 0x00, 0x18, 0x5E, 0x04, 0x00, 0x26, 0x77, + 0x2F, 0x87, 0x0B, 0x00, 0x24, 0x72, 0x26, 0xB7, 0x13, 0x74, 0xB1, 0x71, 0x20, 0x78, 0x06, 0x4D, + 0xB9, 0x71, 0x04, 0x00, 0x20, 0x7B, 0x13, 0x66, 0xB9, 0x71, 0x08, 0x00, 0x4B, 0xC2, 0x01, 0x00, + 0x38, 0x7C, 0x38, 0x0A, 0x08, 0x60, 0x00, 0xFF, 0x2C, 0x60, 0xFF, 0x0F, 0x5C, 0x20, 0xFF, 0x0F, + 0x57, 0x26, 0x56, 0x76, 0x66, 0x72, 0xB9, 0x7C, 0x38, 0x0A, 0x18, 0x71, 0x0C, 0x00, 0x18, 0x5E, + 0x04, 0x00, 0x18, 0x61, 0x0D, 0x00, 0xB1, 0x71, 0x20, 0x78, 0x06, 0x29, 0xB9, 0x71, 0x04, 0x00, + 0x20, 0x7B, 0x06, 0x3A, 0xB9, 0x71, 0x08, 0x00, 0x06, 0x4D, 0x4B, 0xC2, 0x01, 0x00, 0x38, 0x7C, + 0x38, 0x0A, 0x1C, 0x50, 0x00, 0x10, 0x5C, 0x20, 0xFF, 0x0F, 0x56, 0x75, 0x66, 0x72, 0xB9, 0x7C, + 0x38, 0x0A, 0x58, 0xC1, 0x30, 0x00, 0x58, 0x81, 0x20, 0x00, 0x2C, 0x10, 0x40, 0x00, 0xE1, 0xF0, + 0x38, 0x70, 0xB0, 0x16, 0x28, 0x67, 0xB4, 0x00, 0x3F, 0x74, 0x03, 0x00, 0xC4, 0x70, 0x32, 0x02, + 0x16, 0x77, 0x23, 0x77, 0xC6, 0x76, 0xC2, 0x09, 0xC6, 0x34, 0xC2, 0x04, 0x3F, 0x46, 0x03, 0x00, + 0xF2, 0x03, 0x2F, 0x46, 0x03, 0x00, 0x23, 0x44, 0x06, 0x24, 0xE1, 0xF0, 0x38, 0x30, 0xB0, 0x16, + 0x3C, 0x10, 0x48, 0x00, 0xD9, 0xC1, 0x38, 0x00, 0xD9, 0x81, 0x28, 0x00, 0x18, 0x83, 0xB2, 0x00, + 0x06, 0x21, 0x2C, 0x30, 0x9E, 0x00, 0x04, 0x4A, 0x0C, 0xF0, 0x40, 0x01, 0xF1, 0xF0, 0x0C, 0xD0, + 0xFC, 0x0A, 0x98, 0x7D, 0x98, 0x04, 0x92, 0x05, 0x8B, 0xC1, 0x01, 0x00, 0xFA, 0x50, 0x01, 0x00, + 0x18, 0xBD, 0xE5, 0x00, 0x08, 0x90, 0x00, 0xFF, 0x2F, 0xEB, 0x0B, 0x00, 0x26, 0xEB, 0x06, 0x7E, + 0x57, 0x72, 0x26, 0xE7, 0x26, 0xEB, 0x2C, 0xE0, 0xAC, 0x04, 0x26, 0xED, 0x06, 0xAD, 0x2C, 0x90, + 0xFF, 0x0F, 0x18, 0x7D, 0xE6, 0x00, 0xC6, 0xB7, 0x3A, 0xFF, 0x00, 0x00, 0x06, 0xCB, 0x57, 0xC1, + 0x0C, 0x50, 0x38, 0x15, 0x26, 0xC5, 0x30, 0x7C, 0x08, 0x60, 0x00, 0xF0, 0xD6, 0x76, 0x92, 0x06, + 0x06, 0x2B, 0x6B, 0xBE, 0x01, 0x00, 0xFA, 0xEB, 0x00, 0x00, 0x06, 0x7E, 0x04, 0x68, 0x0C, 0x20, + 0x26, 0x00, 0x0C, 0x30, 0x22, 0x00, 0x26, 0x27, 0x26, 0x37, 0x04, 0x44, 0xB9, 0x61, 0x20, 0x00, + 0xB9, 0x71, 0x24, 0x00, 0xEB, 0x73, 0x03, 0x00, 0x38, 0x61, 0x20, 0x00, 0x38, 0x71, 0x24, 0x00, + 0x34, 0x61, 0xC4, 0x60, 0x34, 0x74, 0x92, 0xEC, 0x30, 0x7C, 0x13, 0x2B, 0x77, 0x76, 0x5C, 0x70, + 0xFF, 0x0F, 0xA9, 0x7E, 0x06, 0x00, 0x30, 0x7C, 0x06, 0x31, 0x5C, 0x70, 0xFF, 0x0F, 0xA9, 0x7E, + 0x08, 0x00, 0x6B, 0xCC, 0x01, 0x00, 0xF0, 0x2E, 0x30, 0x7C, 0x22, 0x5A, 0xF8, 0x6E, 0x02, 0x00, + 0x22, 0x57, 0x0C, 0x60, 0x64, 0x00, 0x3F, 0x58, 0x06, 0x00, 0x06, 0x35, 0xB9, 0x51, 0x1C, 0x00, + 0xB9, 0x61, 0x20, 0x00, 0xB9, 0x71, 0x24, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x38, 0x71, 0x24, 0x00, + 0x06, 0x42, 0x06, 0x27, 0x77, 0x26, 0x06, 0x38, 0x5C, 0x20, 0xFF, 0x0F, 0xB9, 0x41, 0x18, 0x00, + 0x6B, 0x13, 0x00, 0x00, 0x38, 0x41, 0x18, 0x00, 0x38, 0x61, 0x20, 0x00, 0x26, 0x24, 0x06, 0x36, + 0xAB, 0x15, 0x00, 0x00, 0x38, 0x71, 0x24, 0x00, 0x5C, 0x20, 0xFF, 0x0F, 0x57, 0x26, 0x56, 0x79, + 0x66, 0x72, 0xB1, 0x7C, 0x38, 0x51, 0x1C, 0x00, 0x78, 0x2E, 0x02, 0x00, 0xB9, 0x71, 0x24, 0x00, + 0x06, 0x35, 0x6B, 0x13, 0x00, 0x00, 0x38, 0x71, 0x24, 0x00, 0x06, 0x52, 0x0C, 0x20, 0xFF, 0x0F, + 0x56, 0x27, 0x06, 0x38, 0xB9, 0x51, 0x1C, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x38, 0x51, 0x1C, 0x00, + 0x38, 0x61, 0x20, 0x00, 0x26, 0x25, 0x06, 0x36, 0xAB, 0x15, 0x00, 0x00, 0x38, 0x71, 0x24, 0x00, + 0x1C, 0x50, 0x00, 0x10, 0x5C, 0x20, 0xFF, 0x0F, 0x56, 0x75, 0x66, 0x72, 0x0C, 0x20, 0x14, 0x00, + 0xB1, 0x7C, 0x26, 0x21, 0x06, 0x3E, 0x04, 0x44, 0xEB, 0x73, 0x03, 0x00, 0xF2, 0x0B, 0x06, 0x67, + 0x77, 0x66, 0x5C, 0x60, 0xFF, 0x0F, 0x5C, 0x70, 0xFF, 0x0F, 0xA9, 0x61, 0x14, 0x00, 0xA9, 0x71, + 0x16, 0x00, 0x18, 0x7E, 0x04, 0x00, 0xC4, 0x78, 0xD2, 0x04, 0x24, 0x71, 0x99, 0x7E, 0x04, 0x00, + 0x18, 0x7E, 0x2D, 0x00, 0xC4, 0x71, 0xD2, 0x04, 0x24, 0x71, 0x99, 0x7E, 0x2D, 0x00, 0x30, 0x3C, + 0x18, 0x2E, 0x2C, 0x00, 0x28, 0x41, 0x14, 0x00, 0x77, 0x36, 0x5C, 0x30, 0xFF, 0x0F, 0xA1, 0x3E, + 0x30, 0x7C, 0x5C, 0x70, 0xFF, 0x0F, 0xA9, 0x7E, 0x02, 0x00, 0x0B, 0xDA, 0x01, 0x00, 0x30, 0x7C, + 0x0C, 0x60, 0xFF, 0x0F, 0x56, 0x62, 0x06, 0x56, 0x57, 0x56, 0x56, 0x79, 0x66, 0x75, 0xB1, 0x7C, + 0x28, 0x3E, 0x02, 0x00, 0x18, 0x2E, 0x2C, 0x00, 0x28, 0x41, 0x16, 0x00, 0xB9, 0x61, 0x20, 0x00, + 0xB9, 0x71, 0x24, 0x00, 0x0B, 0xDA, 0x01, 0x00, 0x38, 0x71, 0x24, 0x00, 0x1C, 0x30, 0x00, 0x10, + 0x5C, 0x20, 0xFF, 0x0F, 0x56, 0x37, 0x66, 0x32, 0xB1, 0x3C, 0x18, 0x50, 0xDB, 0x16, 0x38, 0x61, + 0x20, 0x00, 0xC4, 0x51, 0x92, 0x1C, 0xA9, 0x21, 0x16, 0x00, 0x0C, 0x20, 0x14, 0x00, 0x26, 0x21, + 0x77, 0x3E, 0xA9, 0x61, 0x14, 0x00, 0xEB, 0xDC, 0x02, 0x00, 0x28, 0x61, 0x14, 0x00, 0x30, 0x7C, + 0x5C, 0x60, 0xFF, 0x0F, 0x57, 0x66, 0x56, 0x79, 0x66, 0x76, 0x28, 0x61, 0x16, 0x00, 0x1C, 0x50, + 0x00, 0x10, 0x5C, 0x60, 0xFF, 0x0F, 0x56, 0x75, 0x66, 0x76, 0xB1, 0x7C, 0x24, 0xB1, 0x2C, 0xE0, + 0x34, 0x00, 0xFA, 0x00, 0xFF, 0xFF, 0x18, 0x2A, 0x98, 0x04, 0xC4, 0x22, 0xD2, 0x38, 0x78, 0x3A, + 0xE8, 0x00, 0x78, 0x4A, 0xEA, 0x00, 0x78, 0x6A, 0xEC, 0x00, 0x78, 0x7A, 0xEE, 0x00, 0x04, 0x50, + 0x06, 0xF5, 0xC6, 0x52, 0xB2, 0x24, 0x24, 0xF1, 0x06, 0xEF, 0x57, 0xE1, 0x26, 0xED, 0x38, 0xEE, + 0x38, 0x0A, 0x77, 0xEE, 0xC4, 0xE0, 0x82, 0x17, 0xC4, 0x21, 0x92, 0x08, 0x78, 0x7A, 0xAE, 0x04, + 0x78, 0x6A, 0xAC, 0x04, 0x06, 0x47, 0x06, 0x36, 0xF2, 0x0C, 0xC4, 0x50, 0x92, 0x06, 0x78, 0x4A, + 0xAE, 0x04, 0x78, 0x3A, 0xAC, 0x04, 0xF2, 0x05, 0x78, 0x7A, 0xAE, 0x04, 0x78, 0x6A, 0xAC, 0x04, + 0x24, 0x51, 0x13, 0x55, 0xC4, 0xFD, 0x2C, 0xA0, 0x34, 0x00, 0x92, 0xDC, 0xA9, 0x3D, 0xE8, 0x00, + 0xA9, 0x4D, 0xEA, 0x00, 0xA9, 0x6D, 0xEC, 0x00, 0xA9, 0x7D, 0xEE, 0x00, 0x58, 0xC1, 0x38, 0x00, + 0x58, 0x81, 0x28, 0x00, 0x2C, 0x10, 0x48, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0xA9, 0x00, 0x0E, 0x0B, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x2C, 0x02, 0xD9, 0xC1, 0x1C, 0x02, 0x0C, 0xD0, 0xFC, 0x0A, + 0x98, 0x4D, 0x1F, 0x03, 0x38, 0x70, 0xB0, 0x16, 0xD9, 0x81, 0x0C, 0x02, 0x18, 0xE7, 0x79, 0x00, + 0x18, 0x87, 0x7A, 0x00, 0x18, 0x57, 0x7C, 0x00, 0x92, 0x0A, 0x38, 0x7D, 0x0C, 0x00, 0x1C, 0x20, + 0x01, 0x02, 0x56, 0x72, 0xB9, 0x7D, 0x0C, 0x00, 0xFA, 0x62, 0x02, 0x00, 0x38, 0x6D, 0x0C, 0x00, + 0xDC, 0x60, 0x00, 0x02, 0x82, 0x07, 0xC6, 0x85, 0xC2, 0x04, 0x36, 0x85, 0x13, 0x88, 0xF2, 0x02, + 0x04, 0x81, 0xC4, 0x41, 0x92, 0x05, 0x18, 0x5D, 0x25, 0x03, 0xC6, 0x58, 0xA2, 0xE7, 0xC4, 0x60, + 0x82, 0x07, 0x18, 0x77, 0x7D, 0x00, 0x36, 0xE7, 0xC4, 0xE0, 0x12, 0x02, 0x04, 0xE1, 0x38, 0x30, + 0xC0, 0x16, 0x0C, 0xB0, 0x20, 0x01, 0x26, 0xB1, 0xB9, 0x31, 0xF4, 0x01, 0x06, 0x2B, 0x04, 0x30, + 0x0C, 0x40, 0xB5, 0x00, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x0C, 0x40, 0x20, 0x01, 0x06, 0x21, + 0x04, 0x30, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x28, 0x2D, 0x14, 0x03, 0x06, 0x3E, 0x6B, 0x13, + 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xCB, 0x14, 0x00, 0x00, 0x28, 0x7D, 0x14, 0x00, 0x04, 0x50, + 0x26, 0x27, 0x23, 0x22, 0x0C, 0x70, 0x74, 0x0B, 0xB9, 0x21, 0xF8, 0x01, 0xB9, 0x71, 0xF0, 0x01, + 0xB9, 0x51, 0xDC, 0x01, 0xB9, 0x51, 0xE0, 0x01, 0x04, 0x91, 0x04, 0xC0, 0x38, 0x61, 0xDC, 0x01, + 0x38, 0x51, 0xF4, 0x01, 0x26, 0x6C, 0x23, 0x66, 0x2F, 0x76, 0x06, 0x00, 0x26, 0x75, 0x70, 0x77, + 0x38, 0x51, 0xF8, 0x01, 0xB9, 0x61, 0xE4, 0x01, 0xC6, 0x75, 0x2A, 0x14, 0x01, 0x00, 0x04, 0x70, + 0x06, 0x56, 0x06, 0xE9, 0xB9, 0x71, 0xE8, 0x01, 0xB9, 0x71, 0xEC, 0x01, 0x06, 0xA7, 0xB9, 0x71, + 0xD8, 0x01, 0x38, 0xF1, 0xF4, 0x01, 0x38, 0x21, 0xF8, 0x01, 0x2F, 0x45, 0x05, 0x00, 0x26, 0x4F, + 0x70, 0x44, 0xC6, 0x42, 0x2A, 0xA5, 0x00, 0x00, 0x04, 0x36, 0x26, 0x3C, 0x57, 0x31, 0x26, 0x3D, + 0x30, 0x33, 0xB9, 0x51, 0x08, 0x02, 0x23, 0x44, 0x06, 0x24, 0xB9, 0x61, 0x04, 0x02, 0xB9, 0x41, + 0xFC, 0x01, 0xB9, 0x71, 0x00, 0x02, 0x6B, 0x13, 0x00, 0x00, 0x38, 0xF1, 0xF0, 0x01, 0x38, 0x41, + 0xFC, 0x01, 0x38, 0x71, 0x00, 0x02, 0x30, 0x3F, 0x26, 0x72, 0x06, 0x24, 0xB9, 0x71, 0x00, 0x02, + 0x6B, 0x13, 0x00, 0x00, 0x38, 0x41, 0xFC, 0x01, 0x38, 0xF1, 0xEC, 0x01, 0x38, 0x31, 0xE8, 0x01, + 0x38, 0x51, 0x08, 0x02, 0x38, 0x61, 0x04, 0x02, 0x38, 0x71, 0x00, 0x02, 0x26, 0xF4, 0x38, 0x41, + 0xD8, 0x01, 0xB9, 0xF1, 0xEC, 0x01, 0x26, 0x32, 0xB8, 0x21, 0xE0, 0x01, 0xB9, 0x31, 0xE8, 0x01, + 0x24, 0x41, 0x23, 0x44, 0xB9, 0x41, 0xD8, 0x01, 0x82, 0x63, 0xC4, 0xA0, 0x1C, 0x40, 0x18, 0x00, + 0x26, 0x45, 0x23, 0x44, 0x92, 0x24, 0x06, 0x34, 0xF7, 0x30, 0x26, 0x3B, 0x10, 0x33, 0x04, 0x21, + 0x56, 0x24, 0x57, 0x21, 0x63, 0x32, 0xD4, 0x3F, 0x92, 0x18, 0xC4, 0xC0, 0x82, 0x0C, 0x14, 0x21, + 0x26, 0x24, 0x06, 0x32, 0xE7, 0x30, 0x26, 0x3B, 0x10, 0x33, 0x54, 0x21, 0x57, 0x21, 0x63, 0x32, + 0xD4, 0x3F, 0x92, 0x0B, 0x24, 0x41, 0x06, 0x34, 0xE7, 0x30, 0x26, 0x3B, 0x10, 0x33, 0x54, 0x41, + 0x57, 0x41, 0x63, 0x34, 0xD4, 0x3F, 0x82, 0x3C, 0x13, 0xE3, 0xF2, 0x39, 0x04, 0x21, 0x26, 0x24, + 0x06, 0x32, 0xE7, 0x30, 0x26, 0x3B, 0x10, 0x33, 0x54, 0x21, 0x57, 0x21, 0x63, 0x32, 0xD4, 0x3F, + 0x82, 0x03, 0xC6, 0x3E, 0x92, 0x1C, 0x06, 0x34, 0xF7, 0x30, 0x26, 0x3B, 0x10, 0x33, 0x04, 0x21, + 0x56, 0x24, 0x57, 0x21, 0x63, 0x32, 0xD4, 0x3F, 0x82, 0x03, 0xC6, 0x3E, 0x92, 0x10, 0xC4, 0xC0, + 0x82, 0x1E, 0x34, 0x41, 0x06, 0x34, 0xE7, 0x30, 0x26, 0x3B, 0x10, 0x33, 0x54, 0x41, 0x57, 0x41, + 0x63, 0x34, 0xD4, 0x3F, 0x04, 0xA1, 0x82, 0x14, 0xC6, 0x3E, 0x82, 0x12, 0x13, 0x33, 0xC6, 0x3E, + 0x06, 0x43, 0xC2, 0x02, 0x06, 0x4E, 0x34, 0x31, 0x57, 0x32, 0x26, 0x31, 0x99, 0x43, 0x0E, 0x00, + 0x14, 0x31, 0x26, 0x3E, 0x57, 0x32, 0x26, 0x31, 0x99, 0x43, 0x0E, 0x00, 0x04, 0xA1, 0x24, 0xC1, + 0x23, 0xCC, 0xCC, 0xC0, 0x16, 0x00, 0x24, 0x51, 0x23, 0x55, 0xCA, 0x54, 0xFF, 0xFF, 0xC4, 0xA0, + 0x92, 0x03, 0x24, 0x91, 0x13, 0x99, 0x04, 0x51, 0xD6, 0x56, 0x82, 0x11, 0x06, 0x46, 0xF7, 0x40, + 0x26, 0x4B, 0x10, 0x34, 0x38, 0xA1, 0xD8, 0x01, 0x06, 0x5E, 0x57, 0x52, 0x66, 0x53, 0x24, 0x61, + 0x34, 0xA1, 0x91, 0x54, 0xB9, 0x61, 0xE4, 0x01, 0x23, 0xAA, 0xF2, 0x03, 0x38, 0xA1, 0xD8, 0x01, + 0x38, 0x21, 0xE4, 0x01, 0xB9, 0x71, 0x00, 0x02, 0x06, 0x3E, 0x57, 0x32, 0x06, 0x4A, 0x66, 0x3E, + 0xF7, 0x20, 0xF7, 0x40, 0x26, 0x2B, 0x33, 0x33, 0x23, 0x44, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, + 0x04, 0x61, 0xD6, 0x6A, 0x38, 0x71, 0x00, 0x02, 0x82, 0x0F, 0x38, 0x61, 0xE4, 0x01, 0x34, 0x61, + 0x26, 0xA6, 0x06, 0x5A, 0xF7, 0x50, 0x26, 0x5B, 0x10, 0x45, 0x54, 0xA1, 0x57, 0xA1, 0x06, 0x6E, + 0x53, 0x6A, 0x66, 0x64, 0x91, 0x65, 0x34, 0xE1, 0x57, 0xE2, 0x26, 0xE1, 0x30, 0x6E, 0x38, 0x51, + 0xE8, 0x01, 0x26, 0x76, 0xB1, 0x7E, 0x38, 0x7E, 0x04, 0x00, 0x38, 0x61, 0xEC, 0x01, 0x26, 0x75, + 0xB9, 0x7E, 0x04, 0x00, 0x38, 0x7E, 0x08, 0x00, 0x38, 0x51, 0xD8, 0x01, 0x26, 0x76, 0xB9, 0x7E, + 0x08, 0x00, 0x28, 0x7E, 0x0C, 0x00, 0xCC, 0x90, 0x10, 0x00, 0x26, 0x75, 0xA9, 0x7E, 0x0C, 0x00, + 0xD2, 0x1F, 0x24, 0xC1, 0x23, 0xCC, 0xCC, 0xC0, 0x16, 0x00, 0xCA, 0xD9, 0xFE, 0xFF, 0x38, 0x71, + 0xE0, 0x01, 0x38, 0x61, 0xF0, 0x01, 0x24, 0x71, 0x23, 0x77, 0xB9, 0x71, 0xE0, 0x01, 0x38, 0x71, + 0xDC, 0x01, 0x24, 0x64, 0x2C, 0x70, 0x18, 0x00, 0x23, 0x77, 0xB9, 0x71, 0xDC, 0x01, 0x38, 0x71, + 0xE0, 0x01, 0xB9, 0x61, 0xF0, 0x01, 0xC4, 0x7E, 0x9A, 0xC1, 0xFE, 0xFF, 0xF2, 0x03, 0x0C, 0x90, + 0x11, 0x00, 0x06, 0xE1, 0x04, 0x60, 0x13, 0x76, 0xC6, 0x79, 0xB2, 0x34, 0x18, 0x3E, 0x0E, 0x00, + 0x14, 0x71, 0x26, 0x73, 0xC6, 0x67, 0x0C, 0x40, 0x10, 0x00, 0x06, 0x56, 0x26, 0x4E, 0x92, 0x27, + 0x06, 0x74, 0x24, 0x51, 0xC6, 0x59, 0x32, 0x23, 0x68, 0x27, 0x0E, 0x00, 0xC6, 0x32, 0x92, 0x1C, + 0x28, 0xF7, 0x0C, 0x00, 0x28, 0x2E, 0x0C, 0x00, 0x26, 0x2F, 0xA9, 0x2E, 0x0C, 0x00, 0x30, 0xFE, + 0x30, 0x27, 0x26, 0x2F, 0xB1, 0x2E, 0x38, 0xFE, 0x04, 0x00, 0x38, 0x27, 0x04, 0x00, 0x26, 0x2F, + 0xB9, 0x2E, 0x04, 0x00, 0x38, 0xFE, 0x08, 0x00, 0x38, 0x27, 0x08, 0x00, 0x26, 0x2F, 0xB9, 0x2E, + 0x08, 0x00, 0xA9, 0x07, 0x0C, 0x00, 0x2C, 0x70, 0x10, 0x00, 0xF2, 0xDC, 0x24, 0x61, 0x06, 0xE4, + 0xF2, 0xCB, 0x04, 0x90, 0x06, 0xB9, 0x06, 0xCD, 0x04, 0x51, 0x0C, 0x60, 0x28, 0x08, 0x18, 0x7D, + 0x1F, 0x03, 0xC6, 0x7B, 0xC2, 0x7C, 0x06, 0x3B, 0xD7, 0x32, 0x26, 0x3C, 0x28, 0x73, 0x5C, 0x01, + 0x0C, 0xF0, 0x20, 0x01, 0x06, 0x47, 0xF7, 0x40, 0x26, 0xF1, 0x26, 0x4F, 0x10, 0xE4, 0x04, 0x41, + 0x56, 0x47, 0x57, 0x41, 0x63, 0xE4, 0xD4, 0xEF, 0x0C, 0xA0, 0x5C, 0x01, 0x26, 0xA3, 0x82, 0x5C, + 0x34, 0xE1, 0x57, 0xE2, 0x26, 0xE1, 0xE8, 0x4E, 0x0E, 0x00, 0x82, 0x05, 0x14, 0xE1, 0x26, 0xE4, + 0x57, 0xE2, 0x26, 0xE1, 0xA8, 0x4E, 0x0C, 0x00, 0x92, 0x1A, 0x18, 0x4E, 0x0F, 0x00, 0x2F, 0xF7, + 0x07, 0x00, 0xD7, 0x42, 0x26, 0x4D, 0x28, 0x24, 0x5C, 0x01, 0x26, 0xF6, 0x26, 0x22, 0x26, 0x26, + 0x70, 0xFF, 0x70, 0x22, 0xC6, 0xF2, 0x02, 0x07, 0x28, 0x33, 0x5E, 0x01, 0xA9, 0x74, 0x5C, 0x01, + 0xA9, 0x34, 0x5E, 0x01, 0xA9, 0x0A, 0x1C, 0x00, 0x24, 0x91, 0xF2, 0x36, 0xC6, 0x48, 0xA9, 0x4A, + 0x1C, 0x00, 0xA2, 0x32, 0xB8, 0x7E, 0x08, 0x00, 0x92, 0x03, 0xB9, 0x5E, 0x08, 0x00, 0x38, 0x7E, + 0x08, 0x00, 0x38, 0x2E, 0x04, 0x00, 0xB9, 0x51, 0x08, 0x02, 0x06, 0x37, 0xB9, 0x61, 0x04, 0x02, + 0xB9, 0x71, 0x00, 0x02, 0xCB, 0x14, 0x00, 0x00, 0x38, 0x71, 0x00, 0x02, 0x43, 0x42, 0x30, 0x2E, + 0xB9, 0x41, 0xFC, 0x01, 0x06, 0x37, 0xCB, 0x14, 0x00, 0x00, 0x04, 0x3A, 0x43, 0x22, 0xAB, 0x15, + 0x00, 0x00, 0x38, 0x41, 0xFC, 0x01, 0xA9, 0x2A, 0x14, 0x00, 0x04, 0x3A, 0x06, 0x24, 0xAB, 0x15, + 0x00, 0x00, 0x99, 0xBE, 0x0F, 0x00, 0x38, 0x61, 0x04, 0x02, 0x38, 0x51, 0x08, 0x02, 0xA9, 0x2A, + 0x16, 0x00, 0xA9, 0x0E, 0x0C, 0x00, 0x28, 0x7A, 0x1C, 0x00, 0x28, 0x4D, 0x12, 0x00, 0xC6, 0x47, + 0xB2, 0x03, 0xA9, 0x7C, 0x12, 0x00, 0x24, 0xB1, 0x13, 0xBB, 0xF2, 0x82, 0x38, 0x7C, 0x0C, 0x00, + 0x08, 0x60, 0x02, 0x00, 0xD6, 0x67, 0x82, 0x07, 0x1C, 0x20, 0x01, 0x02, 0x56, 0x72, 0xB9, 0x7C, + 0x0C, 0x00, 0xF2, 0x0D, 0xC4, 0x90, 0x82, 0x04, 0x6C, 0x70, 0x00, 0x02, 0xF2, 0x04, 0x1C, 0x30, + 0x01, 0x02, 0x56, 0x73, 0xB9, 0x7C, 0x0C, 0x00, 0x2B, 0x86, 0x02, 0x00, 0x58, 0xC1, 0x1C, 0x02, + 0x58, 0x81, 0x0C, 0x02, 0x2C, 0x10, 0x2C, 0x02, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0xC0, 0x06, + 0xD9, 0xC1, 0xB0, 0x06, 0x0C, 0x60, 0xFC, 0x0A, 0xD9, 0x81, 0xA0, 0x06, 0x38, 0x76, 0x0C, 0x00, + 0x08, 0x50, 0x02, 0x00, 0xD6, 0x57, 0x06, 0xD6, 0x82, 0x05, 0x1C, 0x30, 0x01, 0x01, 0x56, 0x73, + 0xF2, 0x08, 0x18, 0x56, 0x1F, 0x03, 0xC4, 0x51, 0xD2, 0x08, 0x1C, 0x40, 0x01, 0x01, 0x56, 0x74, + 0xB9, 0x76, 0x0C, 0x00, 0xFA, 0xF6, 0x00, 0x00, 0xDC, 0x70, 0x00, 0x01, 0x08, 0x70, 0x00, 0x80, + 0x2C, 0x70, 0x0C, 0xDC, 0x82, 0x0A, 0x28, 0x67, 0x86, 0x00, 0x28, 0x27, 0x82, 0x00, 0x28, 0xE7, + 0x84, 0x00, 0x26, 0x26, 0x26, 0xE6, 0xF2, 0x05, 0x28, 0x27, 0x82, 0x00, 0x28, 0xE7, 0x84, 0x00, + 0x06, 0x32, 0x6B, 0x13, 0x00, 0x00, 0x06, 0x3E, 0x06, 0x92, 0x06, 0x2E, 0x6B, 0x13, 0x00, 0x00, + 0x26, 0x92, 0x0C, 0x30, 0x48, 0x05, 0x0C, 0x20, 0xE4, 0x05, 0x26, 0x21, 0x26, 0x31, 0x0B, 0x5A, + 0x01, 0x00, 0x06, 0xAD, 0x04, 0xE0, 0x18, 0x7D, 0x1F, 0x03, 0xC6, 0x7E, 0xC2, 0x1F, 0x06, 0xCE, + 0x2F, 0xBE, 0x0E, 0x00, 0xD7, 0xC2, 0x26, 0xBE, 0x26, 0xCA, 0x0C, 0x20, 0xE4, 0x05, 0x2C, 0xC0, + 0x70, 0x01, 0x57, 0xB1, 0x26, 0x21, 0x06, 0x3E, 0x26, 0x2B, 0x04, 0x40, 0x06, 0x5C, 0xCB, 0x5A, + 0x01, 0x00, 0x0C, 0x20, 0x48, 0x05, 0x26, 0x21, 0x06, 0x3E, 0x26, 0x2B, 0x04, 0x40, 0x06, 0x5C, + 0xCB, 0x5A, 0x01, 0x00, 0x24, 0xE1, 0x13, 0xEE, 0xF2, 0xDF, 0x06, 0x29, 0x04, 0x30, 0x04, 0x41, + 0x4B, 0x5C, 0x01, 0x00, 0x0C, 0x30, 0xE4, 0x05, 0x0C, 0x40, 0x48, 0x05, 0x06, 0x21, 0x26, 0x31, + 0x26, 0x41, 0xCB, 0x5C, 0x01, 0x00, 0x86, 0x22, 0xB9, 0x21, 0x88, 0x06, 0x82, 0x07, 0x04, 0xA4, + 0x04, 0x60, 0x26, 0xA1, 0xB9, 0x61, 0x80, 0x06, 0xF2, 0x0A, 0x38, 0x7A, 0x0C, 0x00, 0x1C, 0xF0, + 0x01, 0x01, 0x56, 0x7F, 0xB9, 0x7A, 0x0C, 0x00, 0xFA, 0x8C, 0x00, 0x00, 0x10, 0x5A, 0x0C, 0xC0, + 0x5C, 0x01, 0x06, 0x75, 0xD7, 0x72, 0x26, 0x7D, 0x26, 0xC7, 0xB9, 0x51, 0x84, 0x06, 0x38, 0x67, + 0x60, 0x01, 0x38, 0x97, 0x64, 0x01, 0x38, 0x57, 0x68, 0x01, 0x38, 0x8C, 0x10, 0x00, 0x06, 0xE1, + 0x04, 0xB0, 0x18, 0x7E, 0x04, 0x00, 0x38, 0xF1, 0x84, 0x06, 0xC6, 0x7F, 0x92, 0x45, 0xB0, 0x7E, + 0x82, 0x43, 0x18, 0x7E, 0x05, 0x00, 0x0C, 0x20, 0x5C, 0x01, 0xD7, 0x72, 0x26, 0x7D, 0x38, 0x47, + 0x60, 0x01, 0x26, 0x27, 0x26, 0x64, 0x38, 0x47, 0x64, 0x01, 0x26, 0x94, 0x38, 0x47, 0x68, 0x01, + 0x0C, 0x30, 0x28, 0x08, 0x26, 0x54, 0x38, 0x42, 0x10, 0x00, 0x26, 0x84, 0x20, 0x42, 0x06, 0xF4, + 0x26, 0xF4, 0x26, 0x3F, 0xB9, 0x31, 0x94, 0x06, 0x20, 0x3C, 0xB9, 0x41, 0x9C, 0x06, 0x26, 0x33, + 0x0C, 0x40, 0x28, 0x08, 0x26, 0x43, 0xB9, 0x41, 0x98, 0x06, 0x38, 0xF1, 0x98, 0x06, 0x38, 0x41, + 0x94, 0x06, 0x70, 0x3F, 0x70, 0x44, 0xC6, 0x43, 0x02, 0x08, 0x28, 0x77, 0x5E, 0x01, 0x38, 0x31, + 0x9C, 0x06, 0xA9, 0x7C, 0x02, 0x00, 0xA1, 0x3C, 0x04, 0x30, 0x0C, 0x40, 0x20, 0x00, 0xB9, 0x51, + 0x8C, 0x06, 0xB9, 0x61, 0x90, 0x06, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0xB1, 0x0E, 0x38, 0x61, + 0x90, 0x06, 0x38, 0x51, 0x8C, 0x06, 0x38, 0x71, 0x88, 0x06, 0x24, 0xB1, 0x13, 0xBB, 0xC6, 0xB7, + 0x24, 0xE8, 0x92, 0xB0, 0x06, 0x36, 0x06, 0x25, 0xAB, 0x15, 0x00, 0x00, 0x04, 0x3A, 0x43, 0x22, + 0xAB, 0x15, 0x00, 0x00, 0xA9, 0x2C, 0x14, 0x00, 0x06, 0x39, 0x06, 0x28, 0xAB, 0x15, 0x00, 0x00, + 0x43, 0x22, 0x04, 0x3A, 0xAB, 0x15, 0x00, 0x00, 0x38, 0x71, 0x80, 0x06, 0xA9, 0x2C, 0x16, 0x00, + 0x24, 0xA8, 0x24, 0x71, 0x13, 0x77, 0xC6, 0x7B, 0xB9, 0x71, 0x80, 0x06, 0x9A, 0x80, 0xFF, 0xFF, + 0x38, 0x7D, 0x0C, 0x00, 0x6C, 0x70, 0x00, 0x01, 0xB9, 0x7D, 0x0C, 0x00, 0x2B, 0x86, 0x02, 0x00, + 0x58, 0xC1, 0xB0, 0x06, 0x58, 0x81, 0xA0, 0x06, 0x2C, 0x10, 0xC0, 0x06, 0xE1, 0xF0, 0x00, 0x00, + 0x3C, 0x10, 0x18, 0x00, 0xD9, 0xC1, 0x08, 0x00, 0x0C, 0xD0, 0xFC, 0x0A, 0xC1, 0xA1, 0x18, 0x7D, + 0x98, 0x04, 0x06, 0xED, 0xC4, 0x72, 0x92, 0x05, 0x18, 0x7D, 0x9B, 0x04, 0xC4, 0x72, 0x82, 0x3D, + 0x14, 0x71, 0xB9, 0x7E, 0x30, 0x0A, 0x08, 0x70, 0x00, 0x80, 0x2C, 0x70, 0x0C, 0xDC, 0x28, 0x67, + 0x86, 0x00, 0x28, 0xC7, 0x82, 0x00, 0x28, 0xD7, 0x84, 0x00, 0xA9, 0x0E, 0x34, 0x0A, 0x26, 0xC6, + 0x0C, 0x20, 0x14, 0x00, 0x26, 0x2C, 0x26, 0xD6, 0x06, 0x32, 0x0C, 0xA0, 0x14, 0x00, 0x6B, 0x13, + 0x00, 0x00, 0x26, 0xAD, 0x06, 0xB2, 0x06, 0x3A, 0x06, 0x2A, 0x6B, 0x13, 0x00, 0x00, 0x26, 0x2B, + 0xB9, 0x2E, 0x28, 0x0A, 0x0C, 0x20, 0x78, 0x00, 0x26, 0x2C, 0x06, 0x32, 0x6B, 0x13, 0x00, 0x00, + 0x2C, 0xD0, 0x78, 0x00, 0x06, 0xC2, 0x06, 0x3D, 0x06, 0x2D, 0x6B, 0x13, 0x00, 0x00, 0x38, 0x7E, + 0x0C, 0x00, 0x08, 0x60, 0xFD, 0xFF, 0x2C, 0x60, 0xFF, 0xFF, 0x26, 0x2C, 0x56, 0x76, 0xB9, 0x2E, + 0x2C, 0x0A, 0xB9, 0x7E, 0x0C, 0x00, 0xF2, 0x4E, 0x38, 0xCD, 0x0C, 0x00, 0x08, 0x70, 0x02, 0x00, + 0xD6, 0x7C, 0x92, 0x48, 0x98, 0x7D, 0x3E, 0x03, 0x82, 0x45, 0x98, 0x7D, 0x5A, 0x03, 0x82, 0x42, + 0x78, 0x7D, 0x44, 0x03, 0x78, 0x2D, 0x28, 0x03, 0x78, 0xAD, 0x2A, 0x03, 0x36, 0x27, 0x78, 0x7D, + 0x46, 0x03, 0x06, 0x32, 0x36, 0xA7, 0x6B, 0x13, 0x00, 0x00, 0x06, 0xB2, 0x06, 0x3A, 0x06, 0x2A, + 0x6B, 0x13, 0x00, 0x00, 0xF8, 0x7D, 0x34, 0x0A, 0x26, 0x2B, 0x02, 0x22, 0x38, 0x6D, 0x30, 0x0A, + 0xC6, 0x62, 0xC2, 0x13, 0xCC, 0x70, 0x13, 0x00, 0x12, 0x04, 0x24, 0x71, 0xA9, 0x7D, 0x34, 0x0A, + 0x38, 0x7E, 0x28, 0x0A, 0xC6, 0x72, 0xC2, 0x06, 0x08, 0x70, 0x02, 0x00, 0x66, 0x7C, 0xB9, 0x7E, + 0x0C, 0x00, 0xB9, 0x2E, 0x30, 0x0A, 0xF2, 0x16, 0x34, 0x71, 0xC3, 0x77, 0xA9, 0x7D, 0x34, 0x0A, + 0x92, 0x11, 0x14, 0x71, 0xB9, 0x7D, 0x30, 0x0A, 0xA9, 0x0D, 0x34, 0x0A, 0xF2, 0x0B, 0x38, 0x7D, + 0x2C, 0x0A, 0xC6, 0x72, 0xB2, 0x07, 0x04, 0x73, 0xA9, 0x7D, 0x34, 0x0A, 0x14, 0x71, 0xB9, 0x7D, + 0x30, 0x0A, 0x58, 0xC1, 0x08, 0x00, 0x40, 0xA1, 0x2C, 0x10, 0x18, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x0C, 0x70, 0xFC, 0x0A, 0x14, 0x61, 0x99, 0x07, 0x1C, 0x03, 0x99, 0x07, 0x1F, 0x03, 0x99, 0x07, + 0x24, 0x03, 0x99, 0x67, 0x22, 0x03, 0x99, 0x07, 0x23, 0x03, 0xE1, 0xF0, 0x34, 0x18, 0xC1, 0xE1, + 0x0C, 0xE0, 0xFC, 0x0A, 0x18, 0x7E, 0xDF, 0x00, 0x04, 0x4D, 0x06, 0x27, 0xD7, 0x22, 0x36, 0x47, + 0x26, 0x2E, 0x2C, 0x20, 0x5C, 0x01, 0x04, 0x30, 0xD7, 0x42, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, + 0x98, 0x7E, 0xDF, 0x00, 0x92, 0x03, 0x8B, 0x36, 0x02, 0x00, 0xB9, 0x0E, 0xFC, 0x02, 0xB9, 0x0E, + 0x00, 0x03, 0x99, 0x0E, 0x25, 0x03, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x2F, 0x75, 0x05, 0x00, + 0xC4, 0x50, 0x3C, 0x10, 0x18, 0x00, 0x26, 0x75, 0xD7, 0x71, 0xD9, 0xC1, 0x08, 0x00, 0xC1, 0xA1, + 0x2F, 0x64, 0x07, 0x00, 0x82, 0x06, 0xC4, 0x5D, 0x14, 0x71, 0x04, 0xC0, 0x82, 0x04, 0xF2, 0x02, + 0x06, 0x75, 0x04, 0xC1, 0xC4, 0x40, 0x82, 0x07, 0xCC, 0x40, 0x16, 0x00, 0x14, 0xD1, 0x04, 0xB0, + 0x82, 0x04, 0xF2, 0x02, 0x06, 0xD4, 0x04, 0xB1, 0x26, 0x66, 0x26, 0x63, 0x70, 0xF6, 0x2F, 0x67, + 0x05, 0x00, 0x2F, 0xE6, 0x06, 0x00, 0x26, 0xE6, 0xD7, 0xE1, 0x06, 0x6D, 0x2F, 0xA6, 0x04, 0x00, + 0x26, 0xAE, 0x26, 0xAA, 0x26, 0xA3, 0x70, 0xAA, 0xC6, 0xAF, 0x12, 0x11, 0x24, 0x61, 0x43, 0x66, + 0xC6, 0x6B, 0x02, 0xF5, 0x24, 0x71, 0x43, 0x77, 0xC6, 0x7C, 0x02, 0xEA, 0x28, 0x60, 0x16, 0x0E, + 0x04, 0x70, 0xC6, 0xF6, 0x22, 0x05, 0xA1, 0xF2, 0x04, 0x71, 0xF2, 0x02, 0x04, 0x70, 0x58, 0xC1, + 0x08, 0x00, 0x40, 0xA1, 0x06, 0x27, 0x2C, 0x10, 0x18, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x28, 0x00, + 0xD9, 0x81, 0x08, 0x00, 0x86, 0xB6, 0xD9, 0xC1, 0x18, 0x00, 0x06, 0xA3, 0x06, 0xD2, 0x06, 0xE4, + 0x06, 0xC5, 0x92, 0x13, 0x30, 0x74, 0x38, 0xB4, 0x04, 0x00, 0x26, 0xB7, 0x38, 0x74, 0x08, 0x00, + 0x26, 0xB7, 0x38, 0x74, 0x0C, 0x00, 0x26, 0xB7, 0x38, 0x74, 0x10, 0x00, 0xA6, 0xB7, 0x92, 0x05, + 0x38, 0xE5, 0x08, 0x00, 0x04, 0xB1, 0xF2, 0x35, 0x30, 0x3C, 0x30, 0x2E, 0x6B, 0x13, 0x00, 0x00, + 0xB1, 0x2E, 0x06, 0x72, 0x38, 0x3C, 0x04, 0x00, 0x38, 0x2E, 0x04, 0x00, 0xB9, 0x71, 0x04, 0x00, + 0x6B, 0x13, 0x00, 0x00, 0xB9, 0x2E, 0x04, 0x00, 0x06, 0x62, 0x38, 0x3C, 0x08, 0x00, 0x38, 0x2E, + 0x08, 0x00, 0xB1, 0x61, 0x6B, 0x13, 0x00, 0x00, 0xB9, 0x2E, 0x08, 0x00, 0x38, 0x3C, 0x0C, 0x00, + 0x06, 0x82, 0x38, 0x2E, 0x0C, 0x00, 0x6B, 0x13, 0x00, 0x00, 0xB9, 0x2E, 0x0C, 0x00, 0x06, 0x92, + 0x38, 0x3C, 0x10, 0x00, 0x38, 0x2E, 0x10, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x30, 0x61, 0x38, 0x71, + 0x04, 0x00, 0xB9, 0x2E, 0x10, 0x00, 0x2F, 0xE7, 0x06, 0x00, 0x26, 0xE8, 0x26, 0xE9, 0x26, 0xE2, + 0x06, 0x3B, 0x06, 0x2E, 0xCB, 0x14, 0x00, 0x00, 0x04, 0x3A, 0xCB, 0x14, 0x00, 0x00, 0xC4, 0xA0, + 0x92, 0x08, 0xB9, 0xBD, 0x04, 0x00, 0xB9, 0xED, 0x0C, 0x00, 0xA9, 0x2D, 0x14, 0x00, 0xF2, 0x11, + 0xC4, 0xA1, 0x92, 0x08, 0xB9, 0xBD, 0x08, 0x00, 0xB9, 0xED, 0x10, 0x00, 0xA9, 0x2D, 0x16, 0x00, + 0xF2, 0x08, 0xC4, 0xA2, 0x92, 0x04, 0xA9, 0x2D, 0x18, 0x00, 0xF2, 0x03, 0xA9, 0x2D, 0x1A, 0x00, + 0x58, 0xC1, 0x18, 0x00, 0x58, 0x81, 0x08, 0x00, 0x2C, 0x10, 0x28, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x34, 0x14, 0xB1, 0xF1, 0x8B, 0x99, 0x02, 0x00, 0x30, 0xF1, 0x16, 0x22, 0xF7, 0x2F, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x98, 0x70, 0xD7, 0x16, 0x3C, 0x10, 0x10, 0x00, + 0xD1, 0xC1, 0x0C, 0xE0, 0xFC, 0x0A, 0x82, 0x06, 0x08, 0x70, 0x00, 0x80, 0x28, 0x77, 0xB4, 0xDC, + 0xF2, 0x05, 0x38, 0x70, 0xB0, 0x16, 0x28, 0x77, 0x2C, 0x00, 0xA9, 0x7E, 0x04, 0x03, 0x28, 0x7E, + 0x04, 0x03, 0x28, 0x6E, 0x12, 0x03, 0x26, 0x67, 0x38, 0x70, 0xB0, 0x16, 0x23, 0x66, 0xA9, 0x6E, + 0x06, 0x03, 0x28, 0x77, 0x32, 0x00, 0xA9, 0x7E, 0x20, 0x03, 0x98, 0x70, 0xE4, 0x16, 0x82, 0x0C, + 0x38, 0x7E, 0x0C, 0x00, 0xD4, 0x71, 0x82, 0x08, 0x08, 0x70, 0x00, 0x80, 0x28, 0x77, 0x88, 0xDC, + 0x26, 0x67, 0xA9, 0x6E, 0x06, 0x03, 0x4B, 0x3C, 0x00, 0x00, 0x23, 0x22, 0x0C, 0x30, 0x18, 0x00, + 0x6B, 0x17, 0x00, 0x00, 0xA3, 0x22, 0x82, 0x04, 0xCC, 0x20, 0x16, 0x00, 0x92, 0x0A, 0x38, 0x70, + 0xB0, 0x16, 0x28, 0x67, 0x34, 0x00, 0x28, 0x7E, 0x06, 0x03, 0x26, 0x76, 0xA9, 0x7E, 0x06, 0x03, + 0x28, 0x7E, 0x06, 0x03, 0xA9, 0x7E, 0x08, 0x03, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x50, 0x01, 0x0C, 0x20, 0x68, 0x00, 0x0C, 0x40, 0x2E, 0x00, + 0x26, 0x21, 0x04, 0x30, 0xD9, 0xC1, 0x40, 0x01, 0xD9, 0x81, 0x30, 0x01, 0x0C, 0xF0, 0xB0, 0x01, + 0xF1, 0xF0, 0x0C, 0x70, 0xFC, 0x0A, 0x0C, 0x60, 0xFF, 0x0F, 0xA9, 0x67, 0x14, 0x03, 0x38, 0x40, + 0xC0, 0x16, 0xA9, 0x07, 0x16, 0x03, 0x38, 0x50, 0xBC, 0x16, 0xA9, 0x07, 0x18, 0x03, 0x18, 0xD7, + 0xE2, 0x00, 0xB9, 0x41, 0x10, 0x01, 0x06, 0x87, 0x0C, 0x70, 0x66, 0x00, 0x26, 0x71, 0xB9, 0x51, + 0x14, 0x01, 0xB9, 0x71, 0xFC, 0x00, 0x18, 0x78, 0xE4, 0x00, 0xC6, 0x7D, 0xCA, 0x9C, 0x01, 0x00, + 0x38, 0x78, 0x00, 0x03, 0x73, 0x7D, 0xD4, 0x71, 0x8A, 0x39, 0x02, 0x00, 0x2F, 0x7D, 0x0D, 0x00, + 0x0C, 0x90, 0x1C, 0x00, 0x26, 0x7D, 0x26, 0x9D, 0xD7, 0x71, 0x57, 0x91, 0x18, 0xC8, 0xE1, 0x00, + 0xB9, 0x71, 0x04, 0x01, 0xB9, 0x91, 0x0C, 0x01, 0xF2, 0x08, 0x18, 0x68, 0x99, 0x04, 0xC4, 0x62, + 0x8A, 0x8C, 0x01, 0x00, 0x24, 0xC1, 0x13, 0xCC, 0x18, 0x78, 0xE3, 0x00, 0xC6, 0x7C, 0xCA, 0x1E, + 0x02, 0x00, 0x38, 0x78, 0xFC, 0x02, 0x73, 0x7C, 0xD4, 0x71, 0x82, 0xF5, 0x38, 0xE1, 0x04, 0x01, + 0x26, 0xEC, 0xB9, 0xE1, 0x08, 0x01, 0x43, 0xEE, 0x2F, 0xBE, 0x0E, 0x00, 0x0C, 0x70, 0x28, 0x08, + 0x26, 0x7B, 0x70, 0x67, 0x78, 0x78, 0x06, 0x03, 0xC6, 0x67, 0x22, 0xE5, 0x06, 0x9E, 0x0C, 0x70, + 0x68, 0x00, 0xF7, 0x91, 0x26, 0x71, 0x38, 0xA1, 0x08, 0x01, 0x26, 0x79, 0x10, 0x77, 0x54, 0xA7, + 0x63, 0x7A, 0xD4, 0x71, 0x92, 0xD8, 0x43, 0x7C, 0x43, 0x6D, 0x0C, 0x20, 0xFA, 0x00, 0x06, 0x47, + 0x26, 0x21, 0x0C, 0x30, 0x28, 0x08, 0x06, 0x56, 0xB9, 0x71, 0x28, 0x01, 0xA9, 0x01, 0xFA, 0x00, + 0xB9, 0x61, 0x00, 0x01, 0x6B, 0x39, 0x02, 0x00, 0xC4, 0x20, 0x38, 0x71, 0x28, 0x01, 0x82, 0xBE, + 0x06, 0x2C, 0x06, 0x3D, 0x8B, 0x45, 0x02, 0x00, 0xC4, 0x20, 0x92, 0xBD, 0x78, 0x71, 0xFA, 0x00, + 0x28, 0x68, 0x18, 0x03, 0xC6, 0x76, 0x22, 0x03, 0xA9, 0x78, 0x18, 0x03, 0x0C, 0x70, 0x68, 0x00, + 0x26, 0x71, 0x26, 0x97, 0x10, 0x59, 0x04, 0x71, 0x06, 0x67, 0x53, 0x6A, 0xCC, 0xC0, 0x17, 0x00, + 0x66, 0x65, 0x91, 0x69, 0x82, 0x0E, 0x06, 0x57, 0x26, 0x5E, 0x06, 0x65, 0x0C, 0x90, 0x68, 0x00, + 0xE7, 0x61, 0x26, 0x91, 0x26, 0x69, 0x54, 0x57, 0x53, 0x75, 0x10, 0x56, 0x66, 0x75, 0x91, 0x76, + 0xC4, 0xDD, 0x9A, 0x32, 0x01, 0x00, 0x38, 0xE1, 0x14, 0x01, 0x38, 0x70, 0xB0, 0x16, 0x26, 0xBE, + 0x28, 0x37, 0x3E, 0x00, 0x70, 0x2B, 0x14, 0xB1, 0x6B, 0x13, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, + 0xAB, 0x15, 0x00, 0x00, 0x0C, 0x40, 0x14, 0x00, 0x26, 0x48, 0x20, 0x44, 0x13, 0x22, 0xB9, 0x41, + 0x00, 0x01, 0x04, 0x40, 0x06, 0x74, 0x14, 0x62, 0xB9, 0x21, 0x1C, 0x01, 0x2F, 0xA6, 0x0D, 0x00, + 0x13, 0xAA, 0x33, 0x5A, 0x2F, 0xF5, 0x05, 0x00, 0x26, 0x5F, 0x0C, 0x20, 0x34, 0x00, 0xD7, 0x51, + 0x23, 0x55, 0x26, 0x21, 0xB9, 0x51, 0x18, 0x01, 0x2F, 0x34, 0x01, 0x00, 0x26, 0x24, 0x14, 0x52, + 0xC4, 0xAD, 0xCA, 0x38, 0x01, 0x00, 0xA1, 0x02, 0xA1, 0x03, 0x24, 0x51, 0x43, 0x55, 0xC4, 0x53, + 0x24, 0x22, 0x24, 0x32, 0x92, 0xF6, 0x24, 0x4A, 0xCC, 0x40, 0x32, 0x00, 0x24, 0x61, 0x43, 0x66, + 0x92, 0xDE, 0x78, 0x61, 0x4C, 0x00, 0x28, 0x58, 0x14, 0x03, 0xA9, 0x61, 0xFA, 0x00, 0xC6, 0x56, + 0x02, 0x03, 0xA9, 0x68, 0x14, 0x03, 0x28, 0x58, 0x16, 0x03, 0xC6, 0x56, 0x32, 0x03, 0xA9, 0x68, + 0x16, 0x03, 0x0C, 0x50, 0x34, 0x00, 0x04, 0x42, 0x04, 0x34, 0x04, 0x28, 0x56, 0x47, 0x56, 0x37, + 0x56, 0x27, 0x26, 0x51, 0x5C, 0x70, 0x10, 0x00, 0x06, 0x65, 0x13, 0x44, 0x13, 0x33, 0x13, 0x22, + 0x13, 0x77, 0xC4, 0x40, 0x92, 0x02, 0xA1, 0x05, 0xC4, 0x30, 0x92, 0x03, 0xA9, 0x05, 0x28, 0x00, + 0xC4, 0x20, 0x92, 0x02, 0xA1, 0x06, 0xC4, 0x70, 0x92, 0x03, 0xA9, 0x06, 0x08, 0x00, 0x38, 0xE1, + 0xFC, 0x00, 0x24, 0x6A, 0xC6, 0x6E, 0x24, 0x52, 0x92, 0xED, 0x0C, 0x60, 0x34, 0x00, 0x26, 0x61, + 0x06, 0xE1, 0x06, 0x41, 0x06, 0x56, 0x04, 0x70, 0x78, 0x25, 0x0A, 0x00, 0x70, 0xF5, 0x0C, 0x30, + 0xD4, 0x00, 0x26, 0xF2, 0x78, 0x25, 0x14, 0x00, 0x26, 0x31, 0x26, 0xF2, 0x78, 0x25, 0x1E, 0x00, + 0x26, 0x37, 0x26, 0xF2, 0x78, 0x25, 0x28, 0x00, 0x24, 0x42, 0x26, 0x2F, 0xB1, 0x23, 0x70, 0xF6, + 0x78, 0x26, 0x02, 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x26, 0xF2, 0x78, 0x26, 0x04, 0x00, 0x26, 0x31, + 0x26, 0xF2, 0x78, 0x26, 0x06, 0x00, 0x26, 0x37, 0x26, 0xF2, 0x78, 0x26, 0x08, 0x00, 0x24, 0x52, + 0x26, 0x2F, 0xB1, 0x23, 0x78, 0xF4, 0x08, 0x00, 0x78, 0x24, 0x12, 0x00, 0x0C, 0x30, 0xAC, 0x00, + 0x26, 0xF2, 0x78, 0x24, 0x1C, 0x00, 0x26, 0x31, 0x26, 0x37, 0x26, 0x2F, 0xB1, 0x23, 0x78, 0xFE, + 0x02, 0x00, 0x78, 0x2E, 0x04, 0x00, 0x0C, 0x30, 0x98, 0x00, 0x26, 0xF2, 0x26, 0x31, 0x78, 0x2E, + 0x06, 0x00, 0x26, 0x37, 0x24, 0x74, 0xCC, 0x70, 0x14, 0x00, 0x26, 0x2F, 0xB1, 0x23, 0x24, 0x6A, + 0x24, 0xEA, 0x92, 0xBB, 0x18, 0x28, 0x1F, 0x03, 0x38, 0xE1, 0x0C, 0x01, 0xD7, 0x22, 0x26, 0xE8, + 0x26, 0x28, 0x0C, 0x40, 0xC0, 0x00, 0x06, 0x5E, 0x2C, 0x20, 0x5C, 0x01, 0x04, 0x31, 0x26, 0x41, + 0x04, 0x60, 0xEB, 0x3D, 0x02, 0x00, 0x18, 0x28, 0x1F, 0x03, 0x0C, 0x40, 0x98, 0x00, 0xD7, 0x22, + 0x26, 0x28, 0x06, 0x5E, 0x2C, 0x20, 0x5C, 0x01, 0x04, 0x33, 0x26, 0x41, 0x04, 0x60, 0xEB, 0x3D, + 0x02, 0x00, 0x18, 0x28, 0x1F, 0x03, 0x04, 0xE4, 0x26, 0xEC, 0x57, 0xE1, 0xD7, 0x22, 0x26, 0xE8, + 0x04, 0x30, 0x26, 0x28, 0x0C, 0x40, 0xD4, 0x00, 0x06, 0x63, 0x2C, 0x20, 0x5C, 0x01, 0x26, 0x41, + 0x06, 0x5E, 0xEB, 0x3D, 0x02, 0x00, 0x18, 0x28, 0x1F, 0x03, 0x0C, 0x40, 0xAC, 0x00, 0xD7, 0x22, + 0x26, 0x28, 0x06, 0x5E, 0x04, 0x60, 0x2C, 0x20, 0x5C, 0x01, 0x04, 0x32, 0x26, 0x41, 0xEB, 0x3D, + 0x02, 0x00, 0x18, 0x68, 0x1F, 0x03, 0x38, 0xF1, 0x08, 0x01, 0x18, 0x58, 0x25, 0x03, 0x06, 0x76, + 0xD7, 0x72, 0x26, 0x78, 0x99, 0xC7, 0x5E, 0x01, 0x99, 0xD7, 0x5F, 0x01, 0xA9, 0xF7, 0x5C, 0x01, + 0xA9, 0x57, 0x78, 0x01, 0x04, 0x71, 0x26, 0x76, 0x13, 0x77, 0xC4, 0x7D, 0x99, 0x78, 0x1F, 0x03, + 0x9A, 0x82, 0xFE, 0xFF, 0x18, 0x68, 0x1F, 0x03, 0x98, 0x78, 0xDD, 0x00, 0x99, 0x68, 0x1D, 0x03, + 0x9A, 0xA1, 0x00, 0x00, 0xFA, 0xA4, 0x00, 0x00, 0x38, 0x31, 0x10, 0x01, 0x38, 0x51, 0x00, 0x01, + 0x0C, 0x20, 0xFA, 0x00, 0x26, 0x21, 0x06, 0x47, 0x6B, 0x39, 0x02, 0x00, 0xC4, 0x20, 0x8A, 0x6B, + 0xFE, 0xFF, 0xFA, 0xA7, 0xFE, 0xFF, 0x0C, 0x70, 0x18, 0x00, 0x26, 0x7E, 0x0C, 0x50, 0x68, 0x00, + 0xE7, 0x71, 0x26, 0x51, 0x26, 0x57, 0x04, 0x67, 0x04, 0x71, 0x56, 0x6E, 0x10, 0x45, 0x06, 0xF7, + 0x53, 0xF6, 0x06, 0x6F, 0xC4, 0xC0, 0x66, 0x64, 0x91, 0x65, 0x92, 0x11, 0x2C, 0xE0, 0x19, 0x00, + 0x06, 0x6E, 0x0C, 0x40, 0x68, 0x00, 0xE7, 0x61, 0x26, 0x41, 0x26, 0x64, 0x10, 0x56, 0x54, 0xE7, + 0x04, 0x71, 0x53, 0x7E, 0x66, 0x75, 0x91, 0x76, 0xFA, 0xAF, 0xFE, 0xFF, 0x0C, 0x50, 0x17, 0x00, + 0x26, 0x5E, 0x06, 0x65, 0x0C, 0x90, 0x68, 0x00, 0xE7, 0x61, 0x26, 0x91, 0x26, 0x69, 0x54, 0x57, + 0x53, 0x75, 0x10, 0x56, 0xCC, 0xC0, 0x17, 0x00, 0x66, 0x75, 0x91, 0x76, 0x8A, 0x9D, 0xFE, 0xFF, + 0xF2, 0xDE, 0x2F, 0xF5, 0x0C, 0x00, 0x13, 0xFF, 0xCC, 0xF0, 0x16, 0x00, 0xDA, 0xC5, 0xFE, 0xFF, + 0x38, 0x91, 0x18, 0x01, 0x38, 0xE1, 0x10, 0x01, 0x33, 0xFF, 0x26, 0xF9, 0x43, 0xFF, 0x26, 0xFF, + 0x26, 0xEF, 0x20, 0x9E, 0x06, 0xE9, 0x38, 0x91, 0x00, 0x01, 0x36, 0xE9, 0xB9, 0xE1, 0x2C, 0x01, + 0x06, 0x9E, 0xC3, 0xEE, 0x32, 0x02, 0x04, 0x90, 0x0C, 0xE0, 0x28, 0x08, 0x26, 0xEF, 0xA1, 0x92, + 0x20, 0x9E, 0x06, 0xE9, 0x38, 0x91, 0x00, 0x01, 0x36, 0xE9, 0xB9, 0xE1, 0x2C, 0x01, 0x06, 0x9E, + 0xC3, 0xEE, 0x32, 0x02, 0x04, 0x90, 0xA1, 0x93, 0x14, 0x92, 0xC6, 0x69, 0x8A, 0x9F, 0xFE, 0xFF, + 0xC4, 0x62, 0x8A, 0x9C, 0xFE, 0xFF, 0xC6, 0x59, 0x8A, 0x99, 0xFE, 0xFF, 0xC4, 0x52, 0x8A, 0x96, + 0xFE, 0xFF, 0x38, 0xE1, 0x14, 0x01, 0x38, 0x91, 0x1C, 0x01, 0x26, 0xFE, 0x70, 0xFF, 0xC6, 0xF9, + 0x0A, 0x8D, 0xFE, 0xFF, 0xC6, 0x6B, 0x92, 0x03, 0x64, 0x72, 0xF2, 0x04, 0xC4, 0x61, 0x92, 0x02, + 0x64, 0x74, 0xC6, 0x5B, 0x92, 0x04, 0x64, 0x78, 0xFA, 0x81, 0xFE, 0xFF, 0xC4, 0x51, 0x9A, 0x7E, + 0xFE, 0xFF, 0x6C, 0x70, 0x10, 0x00, 0xFA, 0x7A, 0xFE, 0xFF, 0x24, 0xD1, 0x13, 0xDD, 0xFA, 0xBC, + 0xFD, 0xFF, 0xCC, 0x70, 0xF9, 0x00, 0xD2, 0x08, 0x24, 0x71, 0xF2, 0x04, 0xC4, 0x60, 0x82, 0x04, + 0x04, 0x71, 0x99, 0x78, 0xDD, 0x00, 0x0C, 0x20, 0xE8, 0x00, 0x0C, 0x40, 0x12, 0x00, 0x26, 0x21, + 0x04, 0x30, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x18, 0x98, 0x1F, 0x03, 0x14, 0x41, 0x26, 0x49, + 0x08, 0xB0, 0xE4, 0xFF, 0x08, 0xA0, 0xA9, 0x00, 0xB9, 0x41, 0x04, 0x01, 0x04, 0xE0, 0x2C, 0xB0, + 0xDC, 0x30, 0x2C, 0xA0, 0xDC, 0xF1, 0x04, 0x71, 0x38, 0x41, 0x04, 0x01, 0x06, 0x6E, 0xC6, 0xE4, + 0x32, 0x44, 0x06, 0xCE, 0xD7, 0xC2, 0x24, 0xE1, 0x0C, 0xF0, 0xE8, 0x00, 0x26, 0xC8, 0x43, 0xEE, + 0x26, 0xF1, 0x2C, 0xC0, 0x5C, 0x01, 0x06, 0xDE, 0x26, 0x6F, 0xC6, 0xD9, 0x32, 0xEE, 0x06, 0x5D, + 0xD7, 0x52, 0x26, 0x58, 0x78, 0x45, 0x70, 0x01, 0x78, 0x2C, 0x14, 0x00, 0x2C, 0x50, 0x5C, 0x01, + 0x78, 0x55, 0x16, 0x00, 0x36, 0x24, 0x78, 0x4C, 0x16, 0x00, 0xB9, 0x61, 0x24, 0x01, 0x06, 0x32, + 0x36, 0x45, 0xB9, 0x71, 0x28, 0x01, 0xB9, 0x41, 0x20, 0x01, 0x6B, 0x13, 0x00, 0x00, 0x38, 0x41, + 0x20, 0x01, 0x06, 0x52, 0x06, 0x34, 0x06, 0x24, 0xB9, 0x51, 0x20, 0x01, 0x6B, 0x13, 0x00, 0x00, + 0x38, 0x51, 0x20, 0x01, 0x38, 0x61, 0x24, 0x01, 0x38, 0x71, 0x28, 0x01, 0x26, 0x25, 0x2F, 0x5B, + 0x02, 0x00, 0xC6, 0x5A, 0xD2, 0x07, 0x0C, 0x50, 0xE8, 0x00, 0x26, 0x51, 0x91, 0x76, 0x26, 0x5D, + 0x91, 0x75, 0x24, 0xD1, 0x43, 0xDD, 0xF2, 0xCA, 0x04, 0x60, 0x06, 0x58, 0x18, 0x78, 0x1F, 0x03, + 0xC6, 0x67, 0x32, 0x16, 0x0C, 0x70, 0xE8, 0x00, 0x26, 0x71, 0x26, 0x76, 0x10, 0x77, 0xC4, 0x71, + 0x92, 0x0C, 0x06, 0x76, 0xD7, 0x72, 0x26, 0x75, 0x28, 0x47, 0x74, 0x01, 0xA9, 0x47, 0x70, 0x01, + 0x28, 0x47, 0x76, 0x01, 0xA9, 0x47, 0x72, 0x01, 0x24, 0x61, 0x43, 0x66, 0xF2, 0xE8, 0x58, 0xC1, + 0x40, 0x01, 0x58, 0x81, 0x30, 0x01, 0x2C, 0x10, 0x50, 0x01, 0xE1, 0xF0, 0x0C, 0x70, 0xFC, 0x0A, + 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0x28, 0xE7, 0x20, 0x03, 0x68, 0x27, 0x1F, 0x03, + 0xD1, 0x81, 0x04, 0x60, 0x14, 0x41, 0x99, 0x07, 0x24, 0x03, 0x43, 0x9E, 0x06, 0x36, 0x06, 0x54, + 0x0C, 0xB0, 0xB4, 0x16, 0x0C, 0xA0, 0x80, 0x02, 0x2F, 0xF6, 0x06, 0x00, 0x26, 0xFB, 0x70, 0xFF, + 0x06, 0xDB, 0x26, 0xFF, 0x26, 0xFA, 0x70, 0xFF, 0x06, 0xCA, 0xC6, 0xF9, 0x22, 0x09, 0xC6, 0x3F, + 0x32, 0x07, 0x04, 0x81, 0x26, 0x82, 0x06, 0x52, 0x33, 0x46, 0x23, 0x3F, 0x33, 0x28, 0x24, 0x61, + 0xC4, 0x63, 0x92, 0xEB, 0xA9, 0x37, 0x1A, 0x03, 0x04, 0x60, 0x43, 0x33, 0x2F, 0x26, 0x06, 0x00, + 0x26, 0x2D, 0x20, 0x22, 0x26, 0x22, 0x26, 0x2C, 0xF0, 0x22, 0x02, 0x06, 0x43, 0xF6, 0xC6, 0x4F, + 0x82, 0x03, 0x36, 0x32, 0x43, 0x33, 0x24, 0x61, 0xC4, 0x63, 0x92, 0xF1, 0xC6, 0x3E, 0x32, 0x04, + 0xA9, 0x07, 0x1A, 0x03, 0xF2, 0x1D, 0x14, 0x61, 0xC6, 0x56, 0x82, 0x1A, 0x98, 0x67, 0xAA, 0x04, + 0x82, 0x0B, 0x18, 0x67, 0xA8, 0x04, 0x99, 0x57, 0x22, 0x03, 0x99, 0x67, 0x23, 0x03, 0x04, 0x61, + 0x99, 0x67, 0x24, 0x03, 0xF2, 0x0D, 0x04, 0x31, 0x06, 0x63, 0x53, 0x64, 0x18, 0x47, 0x23, 0x03, + 0x99, 0x57, 0x22, 0x03, 0x99, 0x37, 0x24, 0x03, 0x66, 0x64, 0x99, 0x67, 0x23, 0x03, 0x58, 0xC1, + 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x18, 0xC1, 0xE1, + 0x0C, 0xE0, 0xFC, 0x0A, 0x98, 0x6E, 0x1F, 0x03, 0x06, 0x7E, 0x82, 0x24, 0x98, 0x5E, 0x24, 0x03, + 0x82, 0x21, 0x28, 0x4E, 0x18, 0x03, 0x28, 0x5E, 0x1A, 0x03, 0xC6, 0x45, 0xD2, 0x03, 0xC4, 0x61, + 0xC2, 0x0B, 0x14, 0x51, 0x99, 0x57, 0x22, 0x03, 0x99, 0x07, 0x23, 0x03, 0x99, 0x67, 0x1C, 0x03, + 0x99, 0x07, 0x24, 0x03, 0xF2, 0x0F, 0x0C, 0x20, 0x58, 0x0C, 0x04, 0x30, 0x0C, 0x40, 0x20, 0x00, + 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x18, 0x7E, 0x24, 0x03, 0x99, 0x0E, 0x1F, 0x03, 0x99, 0x7E, + 0x1C, 0x03, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x34, 0x18, 0xC1, 0xE1, 0xEB, 0x7A, 0x02, 0x00, + 0x2B, 0x4B, 0x02, 0x00, 0x0C, 0xE0, 0xFC, 0x0A, 0x18, 0x6E, 0x1F, 0x03, 0x18, 0x7E, 0x24, 0x03, + 0x26, 0x76, 0x13, 0x77, 0x99, 0x7E, 0x1C, 0x03, 0x99, 0x7E, 0x1D, 0x03, 0x6B, 0x81, 0x02, 0x00, + 0xEB, 0x1A, 0x02, 0x00, 0x18, 0x7E, 0x1C, 0x03, 0x99, 0x7E, 0x1E, 0x03, 0x40, 0xE1, 0x24, 0x18, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x18, 0x00, 0xC1, 0xA1, 0x0C, 0xB0, 0xFC, 0x0A, 0x18, 0xAB, + 0x1F, 0x03, 0xD9, 0xC1, 0x08, 0x00, 0x04, 0xE0, 0x06, 0xCE, 0x06, 0xDB, 0x18, 0x4B, 0x1F, 0x03, + 0xC6, 0xC4, 0xB2, 0x1A, 0x06, 0x3C, 0xD7, 0x32, 0x26, 0x3D, 0x2C, 0x30, 0x5C, 0x01, 0xA8, 0x73, + 0x1C, 0x00, 0x82, 0x0F, 0xC6, 0xCE, 0x82, 0x0B, 0x06, 0x2E, 0xD7, 0x22, 0x26, 0x2D, 0x2C, 0x20, + 0x5C, 0x01, 0x0C, 0x40, 0x20, 0x00, 0x0C, 0xF0, 0x28, 0x01, 0xF1, 0xF0, 0x24, 0xE1, 0x13, 0xEE, + 0x24, 0xC1, 0x13, 0xCC, 0xF2, 0xE4, 0x06, 0x2E, 0xD7, 0x22, 0x26, 0x2D, 0x36, 0x4E, 0x2C, 0x20, + 0x5C, 0x01, 0x04, 0x30, 0xD7, 0x42, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x18, 0x7D, 0x1C, 0x03, + 0x99, 0xED, 0x1F, 0x03, 0x3F, 0xAA, 0x07, 0x00, 0x26, 0xEA, 0x99, 0xED, 0x1C, 0x03, 0x58, 0xC1, + 0x08, 0x00, 0x40, 0xA1, 0x2C, 0x10, 0x18, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x38, 0x70, 0xB0, 0x16, 0x34, 0x14, 0xB1, 0xF1, 0x28, 0x47, 0x32, 0x00, 0x04, 0x70, 0x08, 0x60, + 0x00, 0x30, 0x06, 0x27, 0x0C, 0x30, 0xB4, 0x16, 0x2C, 0x60, 0x00, 0x49, 0x2F, 0x53, 0x07, 0x00, + 0x20, 0x55, 0x0C, 0xF0, 0xFF, 0x0F, 0x57, 0x51, 0x26, 0x56, 0x30, 0x55, 0x56, 0xF5, 0x77, 0x58, + 0x5C, 0x50, 0xFF, 0x0F, 0x3F, 0x55, 0x0F, 0x00, 0xC6, 0x54, 0x22, 0x02, 0x04, 0x21, 0x24, 0x72, + 0xC4, 0x76, 0x92, 0xED, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x98, 0x70, 0xD7, 0x16, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x82, 0x06, 0x08, 0x70, 0x00, 0x80, 0x28, 0xD7, 0xB2, 0xDC, + 0xF2, 0x05, 0x38, 0x70, 0xB0, 0x16, 0x28, 0xD7, 0x28, 0x00, 0xCB, 0x3B, 0x00, 0x00, 0xA9, 0x20, + 0x14, 0x0E, 0x23, 0x22, 0xC6, 0x2D, 0x04, 0xE0, 0xB2, 0x06, 0x8B, 0x8A, 0x02, 0x00, 0x14, 0xE1, + 0x26, 0xE2, 0xF7, 0xEF, 0x6B, 0x71, 0x03, 0x00, 0x06, 0x2E, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x24, 0x00, 0xD9, 0xC1, 0x14, 0x00, 0x38, 0xE0, 0xB0, 0x16, + 0xD9, 0x81, 0x04, 0x00, 0x06, 0xD2, 0x04, 0x30, 0x06, 0x2C, 0x0C, 0x20, 0xF0, 0x0B, 0x0C, 0x40, + 0x62, 0x00, 0x0C, 0x90, 0xFC, 0x0A, 0x0C, 0x80, 0x22, 0x01, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, + 0x0C, 0xC0, 0xF0, 0x0B, 0x26, 0x89, 0x06, 0xBD, 0x06, 0xAD, 0x30, 0x3A, 0x18, 0x2E, 0x12, 0x00, + 0x6B, 0x13, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xCB, 0x14, 0x00, 0x00, 0x06, 0x72, 0x38, 0x3A, + 0xC4, 0x00, 0x18, 0x2E, 0x13, 0x00, 0xB1, 0x71, 0x6B, 0x13, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, + 0xCB, 0x14, 0x00, 0x00, 0x98, 0x3B, 0x88, 0x01, 0x30, 0x71, 0x06, 0x52, 0x82, 0x07, 0x06, 0x27, + 0xB1, 0x51, 0xAB, 0x15, 0x00, 0x00, 0x30, 0x51, 0x06, 0x72, 0x28, 0x6E, 0x1A, 0x00, 0xC6, 0x76, + 0x02, 0x02, 0x06, 0x76, 0x06, 0x25, 0x04, 0x3E, 0xB1, 0x71, 0xAB, 0x15, 0x00, 0x00, 0x28, 0x6E, + 0x1C, 0x00, 0x30, 0x71, 0xC6, 0x26, 0x02, 0x02, 0x06, 0x26, 0x18, 0x3E, 0x15, 0x00, 0x3F, 0x22, + 0x07, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, 0xA1, 0x2C, + 0x24, 0xC2, 0xC6, 0xC8, 0x24, 0xA4, 0x24, 0xB1, 0x92, 0xC1, 0x06, 0xA9, 0x0C, 0xC0, 0x20, 0x0C, + 0x2C, 0xA0, 0x40, 0x01, 0x06, 0xBD, 0x38, 0x3B, 0x60, 0x00, 0x18, 0x2E, 0x10, 0x00, 0x6B, 0x13, + 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xCB, 0x14, 0x00, 0x00, 0x38, 0x3B, 0x24, 0x01, 0x06, 0x92, + 0x18, 0x2E, 0x11, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xCB, 0x14, 0x00, 0x00, + 0x98, 0x3D, 0xA0, 0x01, 0x06, 0x82, 0x82, 0x05, 0x06, 0x29, 0xAB, 0x15, 0x00, 0x00, 0x06, 0x92, + 0x28, 0x7E, 0x16, 0x00, 0xC6, 0x97, 0x02, 0x02, 0x06, 0x97, 0x06, 0x28, 0x0C, 0x30, 0x17, 0x00, + 0xAB, 0x15, 0x00, 0x00, 0x28, 0x7E, 0x18, 0x00, 0xC6, 0x27, 0x02, 0x02, 0x06, 0x27, 0x18, 0x3E, + 0x14, 0x00, 0x3F, 0x22, 0x09, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, + 0x00, 0x00, 0xA1, 0x2C, 0x24, 0xC2, 0xC6, 0xCA, 0x24, 0xB4, 0x24, 0xD1, 0x92, 0xC5, 0x58, 0xC1, + 0x14, 0x00, 0x58, 0x81, 0x04, 0x00, 0x2C, 0x10, 0x24, 0x00, 0xE1, 0xF0, 0xE1, 0xF0, 0x00, 0x00, + 0x04, 0x20, 0xE1, 0xF0, 0x3C, 0x10, 0x5C, 0x00, 0xD9, 0x81, 0x3C, 0x00, 0x38, 0x40, 0xB0, 0x16, + 0xD9, 0xC1, 0x4C, 0x00, 0x0C, 0x60, 0xC0, 0x00, 0x26, 0x64, 0x20, 0x66, 0x18, 0xA4, 0x79, 0x00, + 0xB9, 0x03, 0x0C, 0x00, 0x0C, 0xC0, 0xFC, 0x0A, 0x06, 0xD2, 0x28, 0x2C, 0x06, 0x03, 0xB9, 0x03, + 0x08, 0x00, 0x06, 0x76, 0x26, 0x76, 0xB9, 0x03, 0x04, 0x00, 0xB1, 0x03, 0x23, 0x77, 0x06, 0xE3, + 0x26, 0x22, 0x04, 0x33, 0xB9, 0x61, 0x04, 0x00, 0xB9, 0x71, 0x18, 0x00, 0xB9, 0x41, 0x10, 0x00, + 0x99, 0x0C, 0x5B, 0x01, 0xAB, 0x15, 0x00, 0x00, 0xB9, 0x21, 0x1C, 0x00, 0x28, 0x2C, 0x14, 0x03, + 0x06, 0x3A, 0x6B, 0x13, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xCB, 0x14, 0x00, 0x00, 0x0C, 0x70, + 0x28, 0x08, 0x38, 0xB0, 0xB0, 0x16, 0xB9, 0xD1, 0x08, 0x00, 0x04, 0x30, 0x3C, 0x70, 0x30, 0x00, + 0x23, 0x22, 0x06, 0xFD, 0x06, 0x63, 0x06, 0x53, 0x06, 0xA3, 0xB9, 0x71, 0x14, 0x00, 0xB9, 0x21, + 0x30, 0x00, 0x38, 0x81, 0x14, 0x00, 0xB9, 0xD1, 0x0C, 0x00, 0x26, 0x83, 0x04, 0x71, 0xB1, 0x81, + 0x0C, 0x20, 0x80, 0x02, 0x0C, 0x40, 0x54, 0x05, 0x14, 0x8C, 0x53, 0x7A, 0x26, 0x23, 0x26, 0x43, + 0x26, 0x8A, 0xB9, 0x71, 0x20, 0x00, 0x06, 0x9D, 0x04, 0x70, 0xB9, 0x21, 0x24, 0x00, 0xB9, 0x41, + 0x28, 0x00, 0xB9, 0x81, 0x2C, 0x00, 0x38, 0x21, 0x24, 0x00, 0x38, 0x81, 0x28, 0x00, 0x2F, 0x47, + 0x07, 0x00, 0x26, 0x24, 0x26, 0x48, 0x20, 0x44, 0x20, 0x22, 0xC4, 0xA1, 0x36, 0x24, 0x23, 0x22, + 0x43, 0x42, 0xB9, 0x41, 0x38, 0x00, 0x16, 0x22, 0x43, 0x22, 0x12, 0x1A, 0xC4, 0x71, 0x12, 0x07, + 0x28, 0x8B, 0xCA, 0x00, 0xC6, 0x48, 0x22, 0x45, 0x64, 0x51, 0xF2, 0x43, 0xCC, 0x70, 0x14, 0x00, + 0x02, 0x09, 0x28, 0x8B, 0xCA, 0x00, 0x38, 0x41, 0x38, 0x00, 0xC6, 0x48, 0x22, 0x3A, 0x64, 0x52, + 0xF2, 0x38, 0x28, 0x8B, 0xCC, 0x00, 0xC6, 0x28, 0x22, 0x34, 0x64, 0x61, 0xF2, 0x32, 0x38, 0x81, + 0x2C, 0x00, 0xC4, 0x81, 0xD2, 0x1E, 0xC4, 0x71, 0x12, 0x09, 0x28, 0x8B, 0xCA, 0x00, 0x38, 0x41, + 0x38, 0x00, 0xC6, 0x48, 0x22, 0x26, 0x64, 0x54, 0xF2, 0x24, 0x1C, 0x80, 0x15, 0x00, 0x26, 0x87, + 0xC4, 0x81, 0xD2, 0x09, 0x28, 0x8B, 0xCA, 0x00, 0x38, 0x41, 0x38, 0x00, 0xC6, 0x48, 0x22, 0x19, + 0x64, 0x58, 0xF2, 0x17, 0x28, 0x8B, 0xCC, 0x00, 0xC6, 0x28, 0x22, 0x13, 0x64, 0x62, 0xF2, 0x11, + 0xC4, 0x71, 0x12, 0x07, 0x28, 0x8B, 0xCC, 0x00, 0xC6, 0x28, 0x22, 0x0B, 0x64, 0x64, 0xF2, 0x09, + 0xCC, 0x70, 0x14, 0x00, 0x02, 0x06, 0x28, 0x8B, 0xCC, 0x00, 0xC6, 0x28, 0x22, 0x02, 0x64, 0x68, + 0xB8, 0x81, 0x38, 0x00, 0x02, 0x76, 0x30, 0x41, 0x38, 0x81, 0x1C, 0x00, 0x78, 0x24, 0x30, 0x00, + 0xC6, 0x28, 0x02, 0x37, 0x38, 0x8D, 0xC0, 0x00, 0x38, 0x41, 0x38, 0x00, 0x26, 0x84, 0xB9, 0x8D, + 0xC0, 0x00, 0x28, 0x8C, 0x06, 0x03, 0xC6, 0x28, 0x02, 0x44, 0xC4, 0x70, 0x82, 0x07, 0x30, 0x41, + 0x2C, 0x40, 0x2E, 0x00, 0x70, 0x44, 0xC6, 0x42, 0x12, 0x3C, 0x30, 0x41, 0x2C, 0x40, 0x32, 0x00, + 0x70, 0x44, 0xC6, 0x42, 0x32, 0x36, 0xC4, 0xA0, 0x82, 0x07, 0x30, 0x41, 0x70, 0x44, 0xC6, 0x42, + 0x12, 0x30, 0xC4, 0xAD, 0x82, 0x07, 0x30, 0x41, 0x2C, 0x40, 0x60, 0x00, 0x70, 0x44, 0xC6, 0x42, + 0x32, 0x28, 0x38, 0x8C, 0xFC, 0x02, 0x04, 0x21, 0x53, 0x27, 0x66, 0x28, 0xB9, 0x2C, 0xFC, 0x02, + 0x38, 0x81, 0x20, 0x00, 0x38, 0x2C, 0x00, 0x03, 0x66, 0x28, 0xB9, 0x2C, 0x00, 0x03, 0xF2, 0x19, + 0x38, 0x41, 0x0C, 0x00, 0x38, 0x81, 0x08, 0x00, 0x18, 0x24, 0x88, 0x01, 0x24, 0x21, 0x99, 0x24, + 0x88, 0x01, 0x18, 0x28, 0xA0, 0x01, 0x38, 0x41, 0x38, 0x00, 0x24, 0x21, 0x99, 0x28, 0xA0, 0x01, + 0x30, 0x29, 0x26, 0x24, 0xB1, 0x29, 0x38, 0x2F, 0x60, 0x00, 0x26, 0x24, 0xB9, 0x2F, 0x60, 0x00, + 0x38, 0x81, 0x38, 0x00, 0x38, 0x21, 0x30, 0x00, 0xC6, 0x82, 0x02, 0x06, 0x18, 0x2C, 0x25, 0x03, + 0x24, 0x21, 0x99, 0x2C, 0x25, 0x03, 0x38, 0x41, 0x38, 0x00, 0x38, 0x81, 0x04, 0x00, 0xC6, 0x48, + 0x02, 0x2A, 0x38, 0x81, 0x18, 0x00, 0x38, 0x2E, 0x08, 0x00, 0xC6, 0x48, 0x24, 0x21, 0xB9, 0x2E, + 0x08, 0x00, 0x02, 0x21, 0x38, 0x4E, 0x0C, 0x00, 0x24, 0x41, 0xB9, 0x4E, 0x0C, 0x00, 0xF2, 0x1B, + 0x38, 0x49, 0xC4, 0x00, 0x26, 0x42, 0xB9, 0x49, 0xC4, 0x00, 0x38, 0x4F, 0x24, 0x01, 0x26, 0x42, + 0xB9, 0x4F, 0x24, 0x01, 0x38, 0x41, 0x04, 0x00, 0xC6, 0x24, 0x02, 0x0D, 0x38, 0x81, 0x18, 0x00, + 0x30, 0x4E, 0xC6, 0x28, 0x24, 0x41, 0xB1, 0x4E, 0x02, 0x06, 0x38, 0x4E, 0x04, 0x00, 0x24, 0x41, + 0xB9, 0x4E, 0x04, 0x00, 0x38, 0x21, 0x0C, 0x00, 0x30, 0x41, 0x24, 0x71, 0xCC, 0x70, 0x17, 0x00, + 0x24, 0x21, 0x24, 0x42, 0xB9, 0x21, 0x0C, 0x00, 0xB1, 0x41, 0x24, 0x94, 0x9A, 0x05, 0xFF, 0xFF, + 0x38, 0x7F, 0x60, 0x00, 0x38, 0x4D, 0xC0, 0x00, 0x24, 0xA1, 0x26, 0x74, 0xB9, 0x7D, 0xC0, 0x00, + 0x38, 0x7F, 0x24, 0x01, 0x38, 0x4D, 0x84, 0x01, 0xC4, 0xAE, 0x26, 0x74, 0xB9, 0x7D, 0x84, 0x01, + 0x38, 0x71, 0x08, 0x00, 0x24, 0xF4, 0x24, 0x71, 0xB9, 0x71, 0x08, 0x00, 0x2C, 0x30, 0x30, 0x00, + 0x9A, 0xD1, 0xFE, 0xFF, 0x04, 0x71, 0xD6, 0x75, 0x82, 0x08, 0x54, 0x65, 0xC4, 0x60, 0x82, 0x13, + 0x04, 0x71, 0x99, 0x7C, 0x5B, 0x01, 0xF2, 0x0F, 0x04, 0x72, 0xD6, 0x75, 0x82, 0x03, 0x54, 0x69, + 0xF2, 0xF6, 0x04, 0x74, 0xD6, 0x75, 0x82, 0x03, 0x54, 0x66, 0xF2, 0xF1, 0xD4, 0x58, 0x82, 0x03, + 0x54, 0x6A, 0xF2, 0xED, 0xCB, 0x73, 0x03, 0x00, 0x38, 0x81, 0x10, 0x00, 0x28, 0x78, 0x38, 0x00, + 0x58, 0x81, 0x3C, 0x00, 0xA9, 0x7C, 0x14, 0x00, 0x58, 0xC1, 0x4C, 0x00, 0x2C, 0x10, 0x5C, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x0C, 0xE0, 0x17, 0x00, 0x0C, 0xD0, + 0x80, 0x02, 0x06, 0x2E, 0xEB, 0x6F, 0x03, 0x00, 0xC4, 0x20, 0x92, 0x05, 0x2F, 0x7E, 0x0E, 0x00, + 0x26, 0x7D, 0xA1, 0x07, 0x2C, 0xE0, 0x18, 0x00, 0xCC, 0xE0, 0x67, 0x01, 0x92, 0xF3, 0x6B, 0x71, + 0x03, 0x00, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0xCC, 0x01, + 0x0C, 0x40, 0xB8, 0x01, 0x06, 0x21, 0x04, 0x30, 0xB9, 0xF1, 0xC8, 0x01, 0x0C, 0xF0, 0xB0, 0x01, + 0xF1, 0xF0, 0x0C, 0x30, 0xB8, 0x01, 0x26, 0x31, 0x06, 0x21, 0xAB, 0x99, 0x02, 0x00, 0xAB, 0xB3, + 0x02, 0x00, 0x06, 0x21, 0x2B, 0x8F, 0x02, 0x00, 0x38, 0x21, 0x84, 0x01, 0x0C, 0x30, 0xB8, 0x01, + 0x26, 0x31, 0xCB, 0xC2, 0x02, 0x00, 0x38, 0xF1, 0xC8, 0x01, 0x2C, 0x10, 0xCC, 0x01, 0xE1, 0xF0, + 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0xD1, 0x81, 0x0C, 0x30, 0x20, 0x0C, 0x04, 0x60, + 0x0C, 0xC0, 0x80, 0x02, 0x0C, 0xE0, 0x54, 0x05, 0x0C, 0xA0, 0xFC, 0x0A, 0x70, 0xB3, 0x04, 0x70, + 0x06, 0x57, 0x2F, 0xDC, 0x06, 0x00, 0x2F, 0xFE, 0x06, 0x00, 0x2F, 0x27, 0x0D, 0x00, 0x2F, 0x47, + 0x0F, 0x00, 0x70, 0x92, 0x70, 0x44, 0xCC, 0x50, 0x17, 0x00, 0x3F, 0x44, 0x09, 0x00, 0x36, 0x4B, + 0x82, 0x06, 0x2F, 0x9A, 0x07, 0x00, 0x78, 0x99, 0xF4, 0x00, 0x36, 0x49, 0x86, 0x44, 0x32, 0x02, + 0x04, 0x40, 0x24, 0x51, 0xCC, 0x50, 0x18, 0x00, 0xA1, 0x42, 0x24, 0x72, 0x92, 0xE7, 0x2C, 0x60, + 0x30, 0x00, 0xCC, 0x60, 0xA0, 0x02, 0x24, 0x32, 0x92, 0xDA, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, + 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0xC4, 0x20, 0x0C, 0x70, + 0xFC, 0x0A, 0x38, 0x67, 0x0C, 0x00, 0x82, 0x15, 0x64, 0x61, 0xB9, 0x67, 0x0C, 0x00, 0x08, 0x70, + 0x00, 0x80, 0x2C, 0x70, 0x24, 0xE0, 0xB9, 0x70, 0xB0, 0x16, 0x08, 0x70, 0x00, 0x80, 0x2C, 0x70, + 0x08, 0xDE, 0xB9, 0x70, 0xAC, 0x16, 0x08, 0x70, 0x00, 0x80, 0x2C, 0x70, 0xC8, 0xDC, 0xF2, 0x15, + 0x14, 0x22, 0x56, 0x62, 0xB9, 0x67, 0x0C, 0x00, 0x08, 0x70, 0x00, 0x80, 0x2C, 0x70, 0x48, 0xDF, + 0xB9, 0x70, 0xB0, 0x16, 0x08, 0x70, 0x00, 0x80, 0x2C, 0x70, 0xA8, 0xDE, 0xB9, 0x70, 0xAC, 0x16, + 0x08, 0x70, 0x00, 0x80, 0x2C, 0x70, 0x68, 0xDD, 0xB9, 0x70, 0xA8, 0x16, 0xE1, 0xF0, 0x00, 0x00, + 0x0C, 0x70, 0xFC, 0x0A, 0x99, 0x07, 0x59, 0x01, 0x99, 0x07, 0x58, 0x01, 0xE1, 0xF0, 0x00, 0x00, + 0x38, 0x60, 0xB0, 0x16, 0x0C, 0x70, 0xFC, 0x0A, 0x18, 0x56, 0xCE, 0x00, 0x18, 0x37, 0xDD, 0x00, + 0x18, 0x46, 0xC2, 0x00, 0xC6, 0x35, 0x04, 0x60, 0xD2, 0x0E, 0x98, 0x57, 0x5B, 0x01, 0x82, 0x0B, + 0x98, 0x50, 0xD6, 0x16, 0x92, 0x08, 0x38, 0x67, 0x0C, 0x00, 0x6C, 0x60, 0x00, 0x08, 0xB9, 0x67, + 0x0C, 0x00, 0x04, 0x61, 0x18, 0x57, 0x56, 0x01, 0xC6, 0x54, 0xB2, 0x03, 0xC4, 0x60, 0x82, 0x15, + 0x38, 0x60, 0xB8, 0x15, 0xCC, 0x60, 0x1F, 0x03, 0xD2, 0x17, 0x98, 0x50, 0xE0, 0x16, 0x92, 0x14, + 0x38, 0x57, 0x0C, 0x00, 0x6C, 0x50, 0x00, 0x04, 0xB9, 0x57, 0x0C, 0x00, 0x04, 0x71, 0x99, 0x70, + 0xE8, 0x16, 0x99, 0x70, 0xE0, 0x16, 0xF2, 0x08, 0x38, 0x67, 0x0C, 0x00, 0x1C, 0x50, 0x01, 0x04, + 0x56, 0x65, 0xB9, 0x67, 0x0C, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x28, 0x00, 0xD9, 0xC1, 0x18, 0x00, + 0xD9, 0x81, 0x08, 0x00, 0x0C, 0xE0, 0xFC, 0x0A, 0x38, 0xDE, 0x0C, 0x00, 0xD4, 0xD1, 0x06, 0xC3, + 0x38, 0x90, 0xB0, 0x16, 0x82, 0x0A, 0x04, 0x62, 0x04, 0x80, 0x0C, 0xA0, 0x14, 0x00, 0x0C, 0xB0, + 0x23, 0x00, 0x0C, 0x50, 0xFA, 0x00, 0xF2, 0x08, 0x04, 0x8A, 0x04, 0x61, 0x06, 0xA8, 0x0C, 0xB0, + 0x14, 0x00, 0x0C, 0x50, 0x96, 0x00, 0x0C, 0x30, 0x42, 0x01, 0xB1, 0x51, 0xB9, 0x61, 0x04, 0x00, + 0xCB, 0x14, 0x00, 0x00, 0x30, 0x51, 0x38, 0x61, 0x04, 0x00, 0xC6, 0x25, 0x04, 0x71, 0xD2, 0x19, + 0x38, 0x5C, 0x04, 0x00, 0xC6, 0x5B, 0x02, 0x05, 0x38, 0x5C, 0x0C, 0x00, 0xC6, 0x5B, 0x22, 0x11, + 0x38, 0x3C, 0x08, 0x00, 0x30, 0xBC, 0x06, 0x26, 0x6B, 0x13, 0x00, 0x00, 0xC6, 0xB2, 0x02, 0x04, + 0xC6, 0xB8, 0x04, 0x71, 0x12, 0x06, 0xC6, 0xBA, 0x04, 0x71, 0x12, 0x02, 0x04, 0x70, 0x23, 0x77, + 0x98, 0x60, 0xE4, 0x16, 0x82, 0x04, 0xC4, 0xD0, 0x92, 0x02, 0x06, 0x7D, 0x38, 0x60, 0xB8, 0x15, + 0xCC, 0x60, 0x1F, 0x03, 0xD2, 0x24, 0xC4, 0x70, 0x82, 0x10, 0x18, 0x7E, 0x56, 0x01, 0xCC, 0x70, + 0xFF, 0x00, 0x82, 0x04, 0x24, 0x71, 0x99, 0x7E, 0x56, 0x01, 0x98, 0x7E, 0x57, 0x01, 0x82, 0x17, + 0x34, 0x71, 0x99, 0x7E, 0x57, 0x01, 0xF2, 0x13, 0x18, 0x7E, 0x57, 0x01, 0x24, 0x71, 0x13, 0x77, + 0x99, 0x7E, 0x57, 0x01, 0x18, 0x69, 0xC3, 0x00, 0xC6, 0x67, 0x92, 0x09, 0x98, 0x7E, 0x56, 0x01, + 0x99, 0x0E, 0x57, 0x01, 0x82, 0x04, 0x34, 0x71, 0x99, 0x7E, 0x56, 0x01, 0x58, 0xC1, 0x18, 0x00, + 0x58, 0x81, 0x08, 0x00, 0x2C, 0x10, 0x28, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x18, 0x60, 0xDB, 0x16, 0x04, 0x70, 0xC4, 0x61, 0x92, 0x05, 0x08, 0x70, + 0x00, 0x80, 0x18, 0x77, 0x3B, 0xDC, 0x70, 0x52, 0xC6, 0x57, 0x32, 0x03, 0xA1, 0x72, 0xF2, 0x07, + 0x0C, 0x60, 0x7F, 0x07, 0x36, 0x67, 0xC6, 0x56, 0x02, 0x02, 0xA1, 0x62, 0x78, 0x62, 0x02, 0x00, + 0xC6, 0x67, 0x22, 0x07, 0x0C, 0x50, 0x37, 0x04, 0x3F, 0x77, 0x05, 0x00, 0xC6, 0x67, 0x02, 0x03, + 0xA9, 0x72, 0x02, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x0C, 0x70, 0xFC, 0x0A, 0x0C, 0x60, 0xD4, 0x01, + 0x26, 0x67, 0x99, 0x07, 0x6C, 0x07, 0x2C, 0x70, 0x24, 0x00, 0xC6, 0x76, 0x92, 0xFB, 0xE1, 0xF0, + 0x3C, 0x10, 0x20, 0x00, 0xD1, 0x81, 0x06, 0x74, 0x06, 0x92, 0x06, 0x24, 0xD7, 0x72, 0xD7, 0x21, + 0xD9, 0xC1, 0x10, 0x00, 0x26, 0x27, 0x0C, 0xE0, 0xFC, 0x0A, 0x26, 0x24, 0x06, 0xA3, 0x0C, 0x30, + 0x64, 0x00, 0x06, 0x86, 0x06, 0xB5, 0x06, 0xD4, 0xAB, 0x15, 0x00, 0x00, 0xB9, 0x2E, 0x54, 0x07, + 0x06, 0x7B, 0x06, 0x2B, 0x57, 0x72, 0x57, 0x21, 0x26, 0x27, 0x36, 0x2B, 0x0C, 0x30, 0x64, 0x00, + 0x26, 0x22, 0xAB, 0x15, 0x00, 0x00, 0xB9, 0x2E, 0x58, 0x07, 0x06, 0x78, 0x06, 0x28, 0xD7, 0x72, + 0xD7, 0x21, 0x78, 0xC1, 0x20, 0x00, 0x26, 0x27, 0x0C, 0x30, 0x64, 0x00, 0x26, 0x28, 0xAB, 0x15, + 0x00, 0x00, 0xB9, 0x2E, 0x5C, 0x07, 0x06, 0x7C, 0x06, 0x2C, 0x57, 0x72, 0x57, 0x21, 0x26, 0x27, + 0x36, 0x2C, 0x26, 0x22, 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, 0xB9, 0x2E, 0x60, 0x07, + 0x3F, 0x2D, 0x08, 0x00, 0xC4, 0x20, 0x06, 0xDE, 0x32, 0x02, 0x16, 0x22, 0x04, 0x33, 0xAB, 0x15, + 0x00, 0x00, 0x99, 0x2E, 0x50, 0x07, 0x3F, 0x2B, 0x0C, 0x00, 0xC4, 0x20, 0x06, 0xED, 0x32, 0x02, + 0x16, 0x22, 0x04, 0x33, 0xAB, 0x15, 0x00, 0x00, 0xC4, 0x90, 0x99, 0x2E, 0x51, 0x07, 0x92, 0x06, + 0x0C, 0x70, 0xA6, 0x00, 0xB9, 0x7D, 0x64, 0x07, 0xF2, 0x03, 0xB9, 0x9D, 0x64, 0x07, 0xC4, 0xA0, + 0x92, 0x06, 0x0C, 0x70, 0x9A, 0x00, 0xB9, 0x7D, 0x68, 0x07, 0xF2, 0x03, 0xB9, 0xAD, 0x68, 0x07, + 0xCB, 0xCC, 0x02, 0x00, 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0x72, 0x70, 0x63, 0x38, 0x22, 0x0C, 0x00, 0x06, 0xE4, + 0x36, 0x26, 0xC4, 0x20, 0x32, 0x02, 0x16, 0x22, 0x38, 0x57, 0x04, 0x00, 0x43, 0x22, 0xC6, 0x65, + 0x0C, 0x60, 0xFC, 0x0A, 0x32, 0x06, 0x28, 0xD7, 0x14, 0x00, 0x28, 0x37, 0x1C, 0x00, 0xF2, 0x05, + 0x28, 0xD7, 0x16, 0x00, 0x28, 0x37, 0x1E, 0x00, 0x36, 0x3D, 0xC4, 0x30, 0x32, 0x02, 0x16, 0x33, + 0x18, 0xC6, 0x50, 0x07, 0x43, 0x33, 0xC6, 0x2C, 0x32, 0x07, 0x6B, 0x13, 0x00, 0x00, 0x06, 0x3C, + 0xAB, 0x15, 0x00, 0x00, 0x43, 0x32, 0x26, 0x3D, 0xA1, 0x3E, 0x50, 0xC1, 0x04, 0x21, 0x2C, 0x10, + 0x10, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0x72, 0x78, 0x63, 0x02, 0x00, + 0x38, 0x22, 0x10, 0x00, 0x06, 0xE4, 0x36, 0x26, 0xC4, 0x20, 0x32, 0x02, 0x16, 0x22, 0x38, 0x57, + 0x08, 0x00, 0x43, 0x22, 0xC6, 0x65, 0x0C, 0x60, 0xFC, 0x0A, 0x32, 0x06, 0x28, 0xD7, 0x18, 0x00, + 0x28, 0x37, 0x20, 0x00, 0xF2, 0x05, 0x28, 0xD7, 0x1A, 0x00, 0x28, 0x37, 0x22, 0x00, 0x36, 0x3D, + 0xC4, 0x30, 0x32, 0x02, 0x16, 0x33, 0x18, 0xC6, 0x51, 0x07, 0x43, 0x33, 0xC6, 0x2C, 0x32, 0x07, + 0x6B, 0x13, 0x00, 0x00, 0x06, 0x3C, 0xAB, 0x15, 0x00, 0x00, 0x43, 0x32, 0x26, 0x3D, 0xA1, 0x3E, + 0x50, 0xC1, 0x04, 0x21, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, + 0xD1, 0xC1, 0x70, 0xD2, 0x06, 0xC2, 0xC6, 0xD3, 0x06, 0xE3, 0x22, 0x04, 0x3F, 0x23, 0x0D, 0x00, + 0xF2, 0x03, 0x3F, 0x2D, 0x03, 0x00, 0x06, 0x34, 0x43, 0x22, 0x6B, 0x13, 0x00, 0x00, 0x0C, 0x30, + 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, 0xC6, 0xDE, 0x22, 0x03, 0x26, 0xE2, 0xF2, 0x02, 0x36, 0xE2, + 0xA1, 0xEC, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x50, 0x00, + 0xD9, 0xC1, 0x40, 0x00, 0x06, 0xD3, 0x57, 0xD1, 0xD7, 0x32, 0x98, 0x60, 0xD7, 0x16, 0xD9, 0x81, + 0x30, 0x00, 0x26, 0xD3, 0x0C, 0x70, 0xFC, 0x0A, 0x2C, 0xD0, 0x1C, 0x00, 0x26, 0xD7, 0x0C, 0xC0, + 0x50, 0x07, 0x08, 0x60, 0x00, 0x80, 0x06, 0xE2, 0x26, 0xCD, 0x06, 0x97, 0x2C, 0x60, 0x0C, 0xDC, + 0x82, 0x1E, 0x0C, 0x50, 0xAA, 0x00, 0x26, 0x56, 0x20, 0x55, 0x0C, 0x70, 0xAC, 0x00, 0x26, 0x76, + 0x70, 0x77, 0xB9, 0x51, 0x0C, 0x00, 0x0C, 0x50, 0xAE, 0x00, 0x26, 0x56, 0x70, 0x55, 0xB9, 0x71, + 0x04, 0x00, 0x0C, 0x70, 0xB0, 0x00, 0x26, 0x76, 0x70, 0x77, 0xB9, 0x51, 0x08, 0x00, 0x0C, 0x50, + 0xB2, 0x00, 0x26, 0x56, 0xB9, 0x71, 0x10, 0x00, 0x70, 0x65, 0xF2, 0x1D, 0x0C, 0x70, 0x2E, 0x00, + 0x26, 0x76, 0x10, 0x77, 0x0C, 0x50, 0x30, 0x00, 0x26, 0x56, 0xB9, 0x71, 0x0C, 0x00, 0x0C, 0x70, + 0x32, 0x00, 0x70, 0x55, 0x26, 0x76, 0x70, 0x77, 0xB9, 0x51, 0x04, 0x00, 0x0C, 0x50, 0x34, 0x00, + 0x26, 0x56, 0xB9, 0x71, 0x08, 0x00, 0x0C, 0x70, 0x36, 0x00, 0x70, 0x55, 0x26, 0x76, 0x70, 0x67, + 0xB9, 0x51, 0x10, 0x00, 0x38, 0x51, 0x04, 0x00, 0xB9, 0x61, 0x14, 0x00, 0x20, 0x6E, 0x38, 0x71, + 0x08, 0x00, 0x23, 0xA5, 0x26, 0x6A, 0xA1, 0x6E, 0x28, 0x6E, 0x02, 0x00, 0x23, 0xB7, 0x26, 0x6B, + 0xA9, 0x6E, 0x02, 0x00, 0x06, 0x2E, 0xAB, 0xCA, 0x02, 0x00, 0x98, 0x6D, 0x50, 0x07, 0x9A, 0xAF, + 0x00, 0x00, 0x04, 0x61, 0x99, 0x6D, 0x50, 0x07, 0x38, 0x69, 0x64, 0x07, 0x70, 0x5E, 0x26, 0x6A, + 0x43, 0x66, 0xC6, 0x56, 0x22, 0x07, 0x0C, 0x40, 0x80, 0x07, 0x3F, 0x66, 0x04, 0x00, 0xC6, 0x56, + 0x02, 0x04, 0xB9, 0x6D, 0x54, 0x07, 0xF2, 0x03, 0xB9, 0x5D, 0x54, 0x07, 0x38, 0x49, 0x68, 0x07, + 0x78, 0x6E, 0x02, 0x00, 0x26, 0x4B, 0x43, 0x44, 0xC6, 0x64, 0x22, 0x07, 0x0C, 0x30, 0x38, 0x04, + 0x3F, 0x44, 0x03, 0x00, 0xC6, 0x64, 0x02, 0x04, 0xB9, 0x4D, 0x58, 0x07, 0xF2, 0x03, 0xB9, 0x6D, + 0x58, 0x07, 0x38, 0xAD, 0x54, 0x07, 0xB9, 0x5D, 0x5C, 0x07, 0xB9, 0x6C, 0x10, 0x00, 0x2F, 0x6A, + 0x0A, 0x00, 0x26, 0x6A, 0x06, 0x56, 0x38, 0xB9, 0x54, 0x07, 0xD7, 0x52, 0x26, 0x65, 0x26, 0x6A, + 0x3F, 0x3B, 0x0A, 0x00, 0x06, 0x26, 0xB9, 0x61, 0x18, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x0C, 0x60, + 0x80, 0x07, 0x36, 0x6A, 0x2F, 0x56, 0x06, 0x00, 0x26, 0x56, 0x06, 0x45, 0xD7, 0x42, 0x26, 0x54, + 0x2F, 0x76, 0x05, 0x00, 0x3F, 0x3B, 0x06, 0x00, 0xA9, 0x2C, 0x14, 0x00, 0x06, 0x27, 0xB9, 0x61, + 0x24, 0x00, 0xB9, 0x71, 0x28, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x38, 0xBD, 0x58, 0x07, 0xA9, 0x2C, + 0x16, 0x00, 0x0C, 0x80, 0x38, 0x04, 0x2F, 0x5B, 0x0B, 0x00, 0x26, 0x5B, 0x06, 0x45, 0xD7, 0x42, + 0x26, 0x54, 0x38, 0x49, 0x58, 0x07, 0x26, 0x5B, 0x3F, 0x34, 0x0B, 0x00, 0x06, 0x25, 0x36, 0x8B, + 0xB9, 0x51, 0x1C, 0x00, 0xB9, 0x41, 0x20, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x2F, 0x58, 0x08, 0x00, + 0x26, 0x58, 0x06, 0x35, 0x38, 0x41, 0x20, 0x00, 0xA9, 0x2C, 0x18, 0x00, 0xD7, 0x32, 0x26, 0x53, + 0x26, 0x58, 0x06, 0x25, 0x3F, 0x34, 0x08, 0x00, 0xB9, 0x51, 0x2C, 0x00, 0xAB, 0x15, 0x00, 0x00, + 0x38, 0x49, 0x5C, 0x07, 0xA9, 0x2C, 0x1A, 0x00, 0x38, 0x21, 0x18, 0x00, 0xB9, 0x41, 0x20, 0x00, + 0x3F, 0x34, 0x0A, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x38, 0x71, 0x28, 0x00, 0x38, 0x41, 0x20, 0x00, + 0x38, 0x61, 0x24, 0x00, 0xA9, 0x2C, 0x1C, 0x00, 0x06, 0x27, 0x3F, 0x34, 0x06, 0x00, 0xAB, 0x15, + 0x00, 0x00, 0x38, 0xA9, 0x60, 0x07, 0xA9, 0x2C, 0x1E, 0x00, 0x38, 0x21, 0x1C, 0x00, 0x3F, 0x3A, + 0x0B, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x38, 0x51, 0x2C, 0x00, 0xA9, 0x2C, 0x20, 0x00, 0x3F, 0x3A, + 0x08, 0x00, 0x06, 0x25, 0xAB, 0x15, 0x00, 0x00, 0xA9, 0x2C, 0x22, 0x00, 0x38, 0x71, 0x0C, 0x00, + 0xD4, 0x71, 0x82, 0x28, 0x04, 0x42, 0x06, 0x3E, 0x26, 0x41, 0x06, 0x2C, 0x8B, 0xD4, 0x02, 0x00, + 0x78, 0x3D, 0x54, 0x07, 0x28, 0x41, 0x02, 0x00, 0x06, 0x2E, 0xEB, 0xDA, 0x02, 0x00, 0xB8, 0x61, + 0x04, 0x00, 0x32, 0x02, 0x16, 0x66, 0x38, 0x51, 0x10, 0x00, 0x70, 0x4E, 0x26, 0x65, 0xB8, 0x51, + 0x04, 0x00, 0x23, 0x66, 0x43, 0x76, 0x22, 0x05, 0xC6, 0x47, 0x32, 0x0C, 0xA1, 0x7E, 0xF2, 0x0A, + 0x0C, 0x50, 0x80, 0x07, 0x3F, 0x77, 0x05, 0x00, 0xC6, 0x47, 0x02, 0x04, 0x3F, 0x66, 0x05, 0x00, + 0xA1, 0x6E, 0x38, 0x71, 0x0C, 0x00, 0xD4, 0x72, 0x82, 0x2A, 0x06, 0x3E, 0x06, 0x41, 0x06, 0x2C, + 0xAB, 0xD7, 0x02, 0x00, 0x78, 0x3D, 0x58, 0x07, 0x20, 0x41, 0x04, 0x22, 0x26, 0x2E, 0xEB, 0xDA, + 0x02, 0x00, 0xB8, 0x61, 0x08, 0x00, 0x32, 0x02, 0x16, 0x66, 0x38, 0x71, 0x14, 0x00, 0xB8, 0x51, + 0x08, 0x00, 0x78, 0x4E, 0x02, 0x00, 0x26, 0x67, 0x23, 0x66, 0x43, 0x76, 0x22, 0x06, 0xC6, 0x47, + 0x32, 0x0E, 0xA9, 0x7E, 0x02, 0x00, 0xF2, 0x0B, 0x0C, 0x50, 0x38, 0x04, 0x3F, 0x77, 0x05, 0x00, + 0xC6, 0x47, 0x02, 0x05, 0x3F, 0x66, 0x05, 0x00, 0xA9, 0x6E, 0x02, 0x00, 0x06, 0x2E, 0xAB, 0xCA, + 0x02, 0x00, 0x58, 0xC1, 0x40, 0x00, 0x58, 0x81, 0x30, 0x00, 0x2C, 0x10, 0x50, 0x00, 0xE1, 0xF0, + 0x34, 0x14, 0x0C, 0x20, 0x34, 0x15, 0x04, 0x30, 0x0C, 0x40, 0x3C, 0x00, 0xB1, 0xF1, 0x0C, 0xF0, + 0xB0, 0x01, 0xF1, 0xF0, 0x0C, 0x20, 0x70, 0x15, 0x04, 0x30, 0x0C, 0x40, 0x3C, 0x00, 0x0C, 0xF0, + 0xB0, 0x01, 0xF1, 0xF0, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x18, 0xC1, 0xE1, + 0x0C, 0xE0, 0xFC, 0x0A, 0x98, 0x7E, 0xAC, 0x0A, 0x82, 0x1A, 0x0C, 0x20, 0x74, 0x15, 0x04, 0x30, + 0x0C, 0x40, 0x34, 0x00, 0x99, 0x0E, 0xAC, 0x0A, 0xB9, 0x0E, 0x74, 0x0A, 0x0C, 0xF0, 0xB0, 0x01, + 0xF1, 0xF0, 0x04, 0x71, 0x99, 0x7E, 0x70, 0x0A, 0xB9, 0x0E, 0x38, 0x0A, 0x0C, 0x20, 0x38, 0x15, + 0x04, 0x30, 0x0C, 0x40, 0x34, 0x00, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x8B, 0xC1, 0x01, 0x00, + 0x2B, 0x39, 0x03, 0x00, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x00, 0x00, 0x0C, 0x70, 0xFC, 0x0A, + 0x18, 0x67, 0x98, 0x04, 0x99, 0x67, 0x99, 0x04, 0x18, 0x67, 0xA9, 0x04, 0x99, 0x67, 0xAA, 0x04, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x28, 0x00, 0xD9, 0xC1, 0x18, 0x00, 0x0C, 0xD0, 0xFC, 0x0A, + 0xD9, 0x81, 0x08, 0x00, 0x18, 0xBD, 0xE5, 0x00, 0x04, 0xC0, 0x06, 0x7B, 0x06, 0xEB, 0x57, 0x71, + 0xD7, 0xE2, 0x36, 0xE7, 0x2C, 0xE0, 0x28, 0x03, 0x08, 0x90, 0x00, 0xFF, 0x08, 0x80, 0xFF, 0xF0, + 0x26, 0xED, 0x06, 0xAC, 0x2C, 0x90, 0xFF, 0x0F, 0x2C, 0x80, 0xFF, 0xFF, 0x08, 0x50, 0xFF, 0x0F, + 0x18, 0x7D, 0xE6, 0x00, 0x2F, 0x6B, 0x0C, 0x00, 0xC6, 0x67, 0x32, 0x5E, 0x18, 0x7D, 0x98, 0x04, + 0xC6, 0x7A, 0xC2, 0x5A, 0x98, 0x7E, 0x16, 0x00, 0x82, 0x53, 0x06, 0x2E, 0xB9, 0x51, 0x04, 0x00, + 0xB1, 0x61, 0xAB, 0x3B, 0x01, 0x00, 0xC4, 0x20, 0x24, 0xA1, 0x13, 0xAA, 0x38, 0x51, 0x04, 0x00, + 0x30, 0x61, 0x82, 0x46, 0x98, 0x7E, 0x19, 0x00, 0x92, 0x43, 0x24, 0x61, 0x57, 0x61, 0x26, 0x6D, + 0x20, 0x4E, 0x38, 0x76, 0x38, 0x0A, 0x5C, 0x40, 0xFF, 0x0F, 0x57, 0x46, 0x56, 0x79, 0x66, 0x74, + 0xB9, 0x76, 0x38, 0x0A, 0x28, 0x4E, 0x02, 0x00, 0x1C, 0x30, 0x00, 0x10, 0x5C, 0x40, 0xFF, 0x0F, + 0x56, 0x73, 0x66, 0x74, 0xB9, 0x76, 0x38, 0x0A, 0x18, 0x4E, 0x17, 0x00, 0x56, 0x78, 0x54, 0x4F, + 0x57, 0x4C, 0x66, 0x74, 0xB9, 0x76, 0x38, 0x0A, 0x18, 0x3E, 0x16, 0x00, 0x0C, 0x40, 0xFF, 0xFF, + 0x26, 0x45, 0x57, 0x3E, 0x56, 0x47, 0x66, 0x43, 0xB9, 0x46, 0x38, 0x0A, 0x18, 0x6E, 0x16, 0x00, + 0x04, 0x71, 0x34, 0x61, 0x53, 0x76, 0x38, 0x6D, 0x38, 0x0A, 0x1C, 0x40, 0x00, 0x04, 0x66, 0x76, + 0x5C, 0x70, 0xFF, 0x03, 0x56, 0x64, 0x66, 0x67, 0x06, 0x76, 0x77, 0x76, 0x24, 0x71, 0x54, 0x7F, + 0x1C, 0x30, 0x01, 0xF0, 0x57, 0x76, 0x56, 0x63, 0x66, 0x67, 0xB9, 0x6D, 0x38, 0x0A, 0x24, 0xC1, + 0x2C, 0xE0, 0x1C, 0x00, 0xF2, 0x9E, 0x58, 0xC1, 0x18, 0x00, 0x58, 0x81, 0x08, 0x00, 0x2C, 0x10, + 0x28, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0x0C, 0xD0, 0xFC, 0x0A, + 0x38, 0x7D, 0x38, 0x0A, 0xD1, 0x81, 0xDC, 0x70, 0x00, 0xF0, 0x92, 0x3A, 0xF8, 0x6D, 0xB0, 0x0A, + 0x12, 0x37, 0x0C, 0xE0, 0x98, 0x0F, 0x04, 0x9C, 0x08, 0xB0, 0xE0, 0xFF, 0x08, 0xA0, 0x1F, 0xFF, + 0x26, 0x9E, 0x06, 0xC7, 0x04, 0x81, 0x2C, 0xB0, 0xFF, 0xFF, 0x2C, 0xA0, 0xFF, 0xFF, 0x18, 0x7D, + 0xA9, 0x04, 0xC6, 0x7C, 0xC2, 0x25, 0x90, 0x7E, 0x82, 0x03, 0x24, 0xC1, 0x13, 0xCC, 0x06, 0x2E, + 0xAB, 0x3E, 0x01, 0x00, 0xC4, 0x20, 0x82, 0x19, 0x10, 0x7E, 0x06, 0x68, 0x34, 0x71, 0x53, 0x67, + 0x06, 0x76, 0x38, 0x6D, 0x38, 0x0A, 0x06, 0x56, 0x77, 0x58, 0x66, 0x75, 0x5C, 0x70, 0x1F, 0x00, + 0x57, 0x78, 0x56, 0x6B, 0x66, 0x67, 0x06, 0x76, 0xF7, 0x7A, 0x24, 0x71, 0x54, 0x77, 0xD7, 0x7A, + 0x56, 0x6A, 0x66, 0x67, 0xB9, 0x6D, 0x38, 0x0A, 0x24, 0xE3, 0xC6, 0xE9, 0x92, 0xD9, 0x58, 0xC1, + 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, + 0xD1, 0xC1, 0x0C, 0x50, 0xFC, 0x0A, 0x38, 0x45, 0x38, 0x0A, 0x06, 0x64, 0x77, 0x66, 0x54, 0x6F, + 0xC4, 0x6A, 0x02, 0x30, 0x38, 0xF5, 0x74, 0x0A, 0x14, 0x3A, 0x26, 0x36, 0x13, 0x33, 0x5C, 0xF0, + 0xFF, 0x03, 0x5C, 0x40, 0xFF, 0x03, 0x0C, 0x20, 0x68, 0x15, 0x04, 0x7C, 0x04, 0xD1, 0x14, 0xC1, + 0xC4, 0x30, 0x82, 0x16, 0x06, 0xEF, 0x63, 0xE7, 0xD4, 0xE1, 0x92, 0x0E, 0x06, 0xE4, 0x63, 0xE7, + 0xD4, 0xE1, 0x82, 0x0A, 0x06, 0xED, 0x53, 0xE7, 0x15, 0xEE, 0x24, 0x6F, 0x34, 0x31, 0xB1, 0x02, + 0x13, 0x33, 0x54, 0x6F, 0x56, 0x4E, 0x34, 0x71, 0xC6, 0x7C, 0x34, 0x24, 0x92, 0xEA, 0x38, 0x75, + 0x38, 0x0A, 0x1C, 0x30, 0x00, 0xF4, 0x56, 0x73, 0x57, 0x66, 0x66, 0x74, 0x66, 0x76, 0xB9, 0x75, + 0x38, 0x0A, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x10, 0x00, + 0xD1, 0xC1, 0x0C, 0xE0, 0xFC, 0x0A, 0x18, 0xCE, 0xAC, 0x0A, 0x0C, 0x20, 0x70, 0x15, 0x06, 0x3D, + 0x0C, 0x30, 0x34, 0x15, 0x0C, 0x40, 0x3C, 0x00, 0x0C, 0xF0, 0x28, 0x01, 0xF1, 0xF0, 0x06, 0x2D, + 0x0C, 0x20, 0x34, 0x15, 0x04, 0x30, 0x0C, 0x40, 0x3C, 0x00, 0x99, 0xCE, 0xAC, 0x0A, 0x0C, 0xF0, + 0xB0, 0x01, 0xF1, 0xF0, 0x2B, 0xF9, 0x02, 0x00, 0xAB, 0x01, 0x03, 0x00, 0x6B, 0x06, 0x03, 0x00, + 0x38, 0x6E, 0x38, 0x0A, 0x0C, 0x70, 0x00, 0xF0, 0xD6, 0x76, 0x06, 0x7E, 0x82, 0x05, 0x77, 0x66, + 0x54, 0x6F, 0x24, 0x61, 0xF2, 0x06, 0x08, 0x50, 0xE0, 0x00, 0xD6, 0x56, 0x82, 0x05, 0x04, 0x61, + 0x99, 0x67, 0x70, 0x0A, 0xF2, 0x03, 0x99, 0x0E, 0x70, 0x0A, 0x98, 0x67, 0x70, 0x0A, 0x82, 0x05, + 0x99, 0x67, 0xAC, 0x0A, 0x04, 0x21, 0xF2, 0x10, 0x18, 0x67, 0xAC, 0x0A, 0x04, 0x21, 0xC4, 0x60, + 0x82, 0x0B, 0x98, 0xE7, 0x98, 0x04, 0x92, 0x08, 0x99, 0x27, 0xAC, 0x0A, 0xCB, 0x57, 0x01, 0x00, + 0xEB, 0xF5, 0x02, 0x00, 0x06, 0x2E, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, + 0x04, 0x21, 0xE1, 0xF0, 0x34, 0x14, 0x0C, 0x20, 0xDB, 0x0B, 0x04, 0x30, 0x04, 0x48, 0xB1, 0xF1, + 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x0C, 0x70, 0xFC, 0x0A, + 0x0C, 0x60, 0x18, 0x00, 0x99, 0x67, 0xE3, 0x00, 0x04, 0x6E, 0x34, 0x14, 0x99, 0x67, 0xE4, 0x00, + 0x04, 0x6D, 0xB1, 0xF1, 0x99, 0x07, 0xE0, 0x00, 0x99, 0x07, 0xE1, 0x00, 0x99, 0x07, 0xE2, 0x00, + 0x99, 0x07, 0xE5, 0x00, 0x99, 0x67, 0xE6, 0x00, 0x8B, 0x36, 0x02, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x00, 0x00, 0x04, 0x70, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xC7, 0x06, 0xF7, + 0x06, 0xD7, 0x13, 0xE7, 0xC6, 0xE4, 0xB2, 0x1B, 0x06, 0x65, 0x73, 0x67, 0x54, 0x61, 0x26, 0xD6, + 0x13, 0xDD, 0xC4, 0xD2, 0xD2, 0x16, 0xC4, 0xF0, 0x92, 0x05, 0xC4, 0x61, 0x92, 0x0E, 0x91, 0xE2, + 0xF2, 0x0B, 0xC4, 0xC0, 0x92, 0x07, 0xC4, 0x60, 0x04, 0xF1, 0x92, 0x07, 0x91, 0xE3, 0x06, 0xCF, + 0xF2, 0x04, 0xC4, 0x61, 0x82, 0x06, 0x04, 0xF1, 0x24, 0x71, 0xF2, 0xE4, 0x04, 0x21, 0xF2, 0x02, + 0x04, 0x20, 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x34, 0x18, 0xC1, 0xE1, + 0x0C, 0xE0, 0xFC, 0x0A, 0x98, 0x7E, 0xDF, 0x00, 0x92, 0x03, 0x6B, 0x10, 0x03, 0x00, 0x18, 0x7E, + 0x99, 0x04, 0xC4, 0x71, 0xC2, 0x03, 0x04, 0x20, 0xF2, 0x23, 0xB8, 0x5E, 0xFC, 0x02, 0x82, 0xFC, + 0xB8, 0x7E, 0x00, 0x03, 0x82, 0xF9, 0x38, 0x7E, 0x0C, 0x00, 0xD4, 0x76, 0x92, 0xF5, 0x04, 0x71, + 0x99, 0x7E, 0xE0, 0x00, 0x0C, 0x20, 0xDD, 0x0B, 0x0C, 0x30, 0xDF, 0x0B, 0x0C, 0x40, 0x18, 0x00, + 0x2B, 0x12, 0x03, 0x00, 0xC4, 0x20, 0x82, 0xE8, 0x38, 0x5E, 0x00, 0x03, 0x0C, 0x20, 0xDE, 0x0B, + 0x0C, 0x30, 0xE0, 0x0B, 0x04, 0x4E, 0x2B, 0x12, 0x03, 0x00, 0x16, 0x22, 0xF7, 0x2F, 0x40, 0xE1, + 0x24, 0x18, 0xE1, 0xF0, 0x3C, 0x10, 0x14, 0x00, 0xD9, 0xC1, 0x04, 0x00, 0x06, 0xD2, 0x28, 0x20, + 0x02, 0x0E, 0xB1, 0xB1, 0x06, 0xE3, 0x26, 0x22, 0x04, 0x33, 0x06, 0xC4, 0x06, 0xB5, 0xAB, 0x15, + 0x00, 0x00, 0x2F, 0x7E, 0x0E, 0x00, 0x26, 0xE7, 0x08, 0x60, 0x00, 0x30, 0x04, 0x70, 0x06, 0x52, + 0xD7, 0xE1, 0x0C, 0x40, 0x00, 0xA0, 0x0C, 0x20, 0x00, 0x49, 0x26, 0xED, 0x06, 0x37, 0x06, 0xF7, + 0x26, 0x46, 0x26, 0x26, 0xC6, 0xFB, 0xB2, 0x1C, 0x06, 0x6E, 0x57, 0x61, 0x2F, 0xD4, 0x06, 0x00, + 0x30, 0xDD, 0xC6, 0xD5, 0xB2, 0x10, 0x26, 0x62, 0x30, 0xD6, 0x30, 0x66, 0x5C, 0xD0, 0xFF, 0x0F, + 0x77, 0x68, 0x5C, 0x60, 0xFF, 0x0F, 0x3F, 0x66, 0x0D, 0x00, 0xC4, 0x60, 0x02, 0x02, 0x26, 0x76, + 0x24, 0x31, 0x23, 0x33, 0x24, 0xF1, 0x26, 0xEC, 0x23, 0xFF, 0x23, 0xEE, 0xF2, 0xE4, 0x06, 0x27, + 0xCB, 0x14, 0x00, 0x00, 0x58, 0xC1, 0x04, 0x00, 0x30, 0xB1, 0x23, 0x22, 0x2C, 0x10, 0x14, 0x00, + 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x84, 0x00, 0xD9, 0xC1, 0x74, 0x00, 0xD9, 0x81, 0x64, 0x00, + 0x0C, 0xE0, 0xFC, 0x0A, 0x28, 0xCE, 0x06, 0x03, 0xA9, 0x0E, 0x18, 0x03, 0xCB, 0x3B, 0x00, 0x00, + 0x23, 0xD2, 0xC6, 0xDC, 0x04, 0xA0, 0xCA, 0x0F, 0x01, 0x00, 0x0C, 0x20, 0x14, 0x00, 0x26, 0x21, + 0x06, 0x3A, 0x04, 0x45, 0x0C, 0xF0, 0xD8, 0x01, 0xF1, 0xF0, 0x04, 0x45, 0x06, 0x3A, 0x06, 0x21, + 0x0C, 0xF0, 0xD8, 0x01, 0xF1, 0xF0, 0xA9, 0xDE, 0x18, 0x03, 0x4B, 0x3C, 0x00, 0x00, 0x23, 0xC2, + 0x0C, 0x30, 0x18, 0x00, 0xA9, 0xCE, 0x5C, 0x01, 0x06, 0x2C, 0xCB, 0x14, 0x00, 0x00, 0x13, 0xD2, + 0x99, 0xDE, 0x5F, 0x01, 0x06, 0x2C, 0x0C, 0x30, 0x18, 0x00, 0x6B, 0x17, 0x00, 0x00, 0x13, 0x22, + 0x14, 0x72, 0x26, 0x72, 0x33, 0x77, 0xB9, 0x71, 0x40, 0x00, 0x14, 0x72, 0x26, 0x7D, 0x24, 0xD2, + 0x33, 0x77, 0x33, 0xDD, 0x99, 0x2E, 0x5E, 0x01, 0xB9, 0x71, 0x44, 0x00, 0x24, 0x22, 0xB9, 0xD1, + 0x54, 0x00, 0x06, 0xD7, 0x08, 0x70, 0x00, 0x30, 0x33, 0x22, 0x2C, 0x70, 0x00, 0x49, 0xB9, 0x21, + 0x50, 0x00, 0x06, 0xBA, 0xB9, 0x71, 0x4C, 0x00, 0x38, 0x71, 0x54, 0x00, 0xC6, 0xD7, 0x1A, 0x7F, + 0x00, 0x00, 0x13, 0x7D, 0xC4, 0x7D, 0xB9, 0x71, 0x48, 0x00, 0xD2, 0x73, 0x38, 0x71, 0x44, 0x00, + 0x38, 0x31, 0x48, 0x00, 0x06, 0x9D, 0x36, 0x97, 0x04, 0x20, 0x04, 0x41, 0x0C, 0x50, 0x17, 0x00, + 0x2B, 0x18, 0x03, 0x00, 0x23, 0x99, 0x2F, 0x69, 0x09, 0x00, 0x26, 0x61, 0xA9, 0x26, 0x28, 0x00, + 0x2F, 0x6D, 0x0D, 0x00, 0x26, 0xD6, 0xD7, 0xD1, 0x23, 0xDD, 0xB9, 0xD1, 0x58, 0x00, 0x06, 0x69, + 0x38, 0xD1, 0x40, 0x00, 0x57, 0x61, 0x06, 0x72, 0x26, 0x61, 0x38, 0x51, 0x50, 0x00, 0xC6, 0xD5, + 0x12, 0x4B, 0x13, 0x8D, 0xCC, 0x80, 0x16, 0x00, 0xD2, 0x43, 0x38, 0x51, 0x40, 0x00, 0xC4, 0xA0, + 0x06, 0xCD, 0x36, 0xC5, 0x23, 0xCC, 0x92, 0x15, 0x04, 0x5E, 0x06, 0x28, 0x06, 0x3A, 0x0C, 0x40, + 0x18, 0x00, 0xB9, 0x61, 0x60, 0x00, 0xB9, 0x71, 0x5C, 0x00, 0x2B, 0x18, 0x03, 0x00, 0x2F, 0x5C, + 0x0C, 0x00, 0x38, 0x71, 0x5C, 0x00, 0x38, 0x61, 0x60, 0x00, 0x26, 0x51, 0xA9, 0x25, 0x34, 0x00, + 0x38, 0x51, 0x58, 0x00, 0x26, 0xD5, 0x38, 0x51, 0x4C, 0x00, 0x23, 0xDD, 0x57, 0xD1, 0x26, 0xD5, + 0x30, 0x4D, 0x30, 0x5D, 0x5C, 0x40, 0xFF, 0x0F, 0x77, 0x58, 0x5C, 0x50, 0xFF, 0x0F, 0x3F, 0x55, + 0x04, 0x00, 0x2F, 0x4C, 0x0C, 0x00, 0x26, 0x41, 0x28, 0x34, 0x34, 0x00, 0x36, 0x53, 0x28, 0x3E, + 0x14, 0x00, 0x36, 0x57, 0x36, 0x53, 0xC4, 0x50, 0x22, 0x0B, 0x57, 0xC1, 0x26, 0xC1, 0x38, 0x4C, + 0x14, 0x00, 0x26, 0x45, 0xB9, 0x4C, 0x14, 0x00, 0x30, 0x46, 0x26, 0x54, 0xB1, 0x56, 0x04, 0xD1, + 0x26, 0xD8, 0x33, 0xDD, 0xF2, 0xB3, 0x57, 0x91, 0x26, 0x91, 0x30, 0x79, 0x04, 0xA1, 0x26, 0xB7, + 0x38, 0xD1, 0x48, 0x00, 0x24, 0xD1, 0x33, 0xDD, 0xFA, 0x80, 0xFF, 0xFF, 0x28, 0x6E, 0x5C, 0x01, + 0x28, 0x51, 0x38, 0x00, 0x08, 0x70, 0x00, 0x30, 0x57, 0x61, 0x2C, 0x70, 0x00, 0x49, 0x26, 0x76, + 0x30, 0x67, 0x30, 0x77, 0x5C, 0x60, 0xFF, 0x0F, 0x77, 0x78, 0x5C, 0x70, 0xFF, 0x0F, 0x3F, 0x77, + 0x06, 0x00, 0x36, 0x75, 0x28, 0x51, 0x2C, 0x00, 0x36, 0x75, 0x28, 0x5E, 0x14, 0x00, 0x0C, 0x40, + 0x14, 0x00, 0x36, 0x75, 0x38, 0x51, 0x40, 0x00, 0x23, 0x77, 0x24, 0x56, 0x57, 0x51, 0x06, 0x2D, + 0x0C, 0x20, 0x58, 0x0C, 0x04, 0x30, 0x26, 0x41, 0x26, 0x5E, 0x06, 0x6B, 0xA9, 0x7E, 0x14, 0x03, + 0xA9, 0x7E, 0x16, 0x03, 0xEB, 0x3D, 0x02, 0x00, 0x38, 0x51, 0x44, 0x00, 0x06, 0x2D, 0x0C, 0x20, + 0x58, 0x0C, 0x2C, 0x50, 0x1E, 0x00, 0x57, 0x51, 0x04, 0x31, 0x06, 0x41, 0x26, 0x5E, 0x06, 0x6B, + 0xEB, 0x3D, 0x02, 0x00, 0x18, 0x7E, 0x25, 0x03, 0x04, 0xA1, 0xA9, 0x7E, 0x78, 0x01, 0xA9, 0x7E, + 0x12, 0x00, 0x04, 0x71, 0x99, 0x7E, 0x1D, 0x03, 0x99, 0x7E, 0x1E, 0x03, 0x99, 0x7E, 0x1F, 0x03, + 0x99, 0x7E, 0x1C, 0x03, 0x0B, 0x4B, 0x02, 0x00, 0x58, 0xC1, 0x74, 0x00, 0x06, 0x2A, 0x58, 0x81, + 0x64, 0x00, 0x2C, 0x10, 0x84, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x18, 0x00, 0xD9, 0xC1, 0x08, 0x00, + 0xC1, 0xA1, 0x0C, 0xE0, 0xFC, 0x0A, 0x38, 0x2E, 0x94, 0x04, 0x04, 0x70, 0xC6, 0x27, 0x82, 0x48, + 0x0C, 0xF0, 0x80, 0x00, 0xF1, 0xF0, 0x06, 0x62, 0x04, 0x71, 0x26, 0x72, 0x99, 0x2E, 0xE5, 0x00, + 0x57, 0x61, 0xD7, 0x22, 0x99, 0x7E, 0xE6, 0x00, 0x3F, 0x76, 0x02, 0x00, 0x26, 0x7E, 0x78, 0xDE, + 0x70, 0x01, 0x78, 0x77, 0x30, 0x03, 0x36, 0xD7, 0xC4, 0xD0, 0x32, 0x02, 0x16, 0xDD, 0x3F, 0x76, + 0x02, 0x00, 0x26, 0x7E, 0x78, 0x5E, 0x72, 0x01, 0x78, 0x77, 0x32, 0x03, 0x3F, 0x77, 0x05, 0x00, + 0xC4, 0x70, 0x32, 0x02, 0x16, 0x77, 0x36, 0x26, 0x06, 0x37, 0x2F, 0xC2, 0x0E, 0x00, 0x06, 0x27, + 0x6B, 0x13, 0x00, 0x00, 0x28, 0xBC, 0x3C, 0x03, 0x06, 0x3D, 0x06, 0xA2, 0x06, 0x2D, 0x6B, 0x13, + 0x00, 0x00, 0x2F, 0xD2, 0x0A, 0x00, 0x06, 0x3B, 0x06, 0x2B, 0x6B, 0x13, 0x00, 0x00, 0xC6, 0xD2, + 0xB2, 0x0D, 0x04, 0xD1, 0x0C, 0x20, 0x28, 0x03, 0x99, 0xDE, 0xDF, 0x00, 0x26, 0x2C, 0x0C, 0x30, + 0x58, 0x0C, 0xCB, 0x8C, 0x01, 0x00, 0x99, 0xDE, 0x98, 0x04, 0x18, 0x7E, 0xDF, 0x00, 0x58, 0xC1, + 0x08, 0x00, 0x40, 0xA1, 0x06, 0x27, 0x2C, 0x10, 0x18, 0x00, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, + 0x0C, 0x70, 0xFC, 0x0A, 0x99, 0x07, 0xDF, 0x00, 0x98, 0x77, 0xE0, 0x00, 0x82, 0x07, 0xAB, 0x1C, + 0x03, 0x00, 0xC4, 0x20, 0x82, 0x03, 0x4B, 0x2F, 0x03, 0x00, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, + 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x2F, 0x72, 0x02, 0x00, 0x26, 0x27, 0x57, 0x21, + 0x0C, 0x60, 0xFC, 0x0A, 0x34, 0x18, 0x2C, 0x20, 0x64, 0x09, 0xC1, 0xE1, 0x26, 0x26, 0x14, 0x71, + 0xA1, 0x72, 0xA9, 0x72, 0x02, 0x00, 0xA9, 0x72, 0x04, 0x00, 0xA9, 0x72, 0x06, 0x00, 0xA9, 0x02, + 0x08, 0x00, 0xA9, 0x02, 0x0A, 0x00, 0x38, 0xE6, 0x38, 0x0A, 0xDC, 0xE0, 0xFF, 0x03, 0x92, 0x10, + 0x0C, 0x20, 0x02, 0x15, 0x06, 0x3E, 0x04, 0x48, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x0C, 0x20, + 0x0A, 0x15, 0x06, 0x3E, 0x0C, 0x40, 0x1A, 0x00, 0x0C, 0xF0, 0xB0, 0x01, 0xF1, 0xF0, 0x40, 0xE1, + 0x24, 0x18, 0xE1, 0xF0, 0x34, 0x18, 0xC1, 0xE1, 0x04, 0xE0, 0x06, 0x2E, 0x4B, 0x36, 0x03, 0x00, + 0x24, 0xE1, 0xC4, 0xED, 0x92, 0xFB, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x3C, 0x10, 0x20, 0x00, + 0xB1, 0x21, 0x28, 0x71, 0x02, 0x00, 0xD9, 0xC1, 0x10, 0x00, 0xC9, 0xA1, 0x08, 0x00, 0xC6, 0x47, + 0x13, 0xD2, 0x06, 0xC4, 0x18, 0x21, 0x01, 0x00, 0x23, 0x33, 0x22, 0x03, 0x43, 0x23, 0xF2, 0x1F, + 0xC6, 0x4D, 0x43, 0xA2, 0x43, 0xDD, 0x32, 0x0C, 0x04, 0xE0, 0xC6, 0x2E, 0x06, 0xBD, 0x82, 0x05, + 0x04, 0x3A, 0xCB, 0x14, 0x00, 0x00, 0x13, 0xE2, 0x06, 0x3A, 0x04, 0xD0, 0xF2, 0x04, 0x43, 0xB7, + 0x06, 0xEA, 0x43, 0x33, 0x36, 0x3E, 0x3F, 0x2D, 0x0C, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x43, 0x22, + 0x3F, 0x3D, 0x0B, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x26, 0x2E, 0x43, 0x22, 0x58, 0xC1, 0x10, 0x00, + 0x48, 0xA1, 0x08, 0x00, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x3C, 0x10, 0x74, 0x00, + 0xD9, 0xC1, 0x64, 0x00, 0x0C, 0x70, 0xFC, 0x0A, 0xD9, 0x81, 0x54, 0x00, 0x98, 0x67, 0x70, 0x0A, + 0x06, 0xE7, 0x92, 0x0F, 0x98, 0x67, 0xAC, 0x0A, 0x9A, 0x13, 0x03, 0x00, 0x38, 0x77, 0x38, 0x0A, + 0xDC, 0x70, 0xFF, 0x03, 0x9A, 0x0D, 0x03, 0x00, 0x2B, 0x39, 0x03, 0x00, 0xFA, 0x09, 0x03, 0x00, + 0x98, 0x70, 0xE4, 0x16, 0x38, 0x7E, 0x0C, 0x00, 0x92, 0x73, 0x0C, 0x60, 0x00, 0x03, 0xD6, 0x67, + 0x82, 0x09, 0x0C, 0x70, 0x1E, 0x00, 0x99, 0x7E, 0x00, 0x0A, 0x0C, 0x70, 0x64, 0x00, 0xFA, 0x91, + 0x00, 0x00, 0xD4, 0x71, 0x08, 0x60, 0x00, 0x80, 0x2C, 0x60, 0x0C, 0xDC, 0x28, 0x7E, 0x12, 0x00, + 0x18, 0x56, 0x78, 0x00, 0x82, 0x3D, 0xC6, 0x57, 0xC2, 0x05, 0x04, 0x7A, 0x99, 0x7E, 0x00, 0x0A, + 0xF2, 0x09, 0x18, 0x66, 0x77, 0x00, 0xC6, 0x67, 0x0C, 0x70, 0x14, 0x00, 0x99, 0x7E, 0x00, 0x0A, + 0xC2, 0x25, 0x0C, 0x70, 0x64, 0x00, 0xA9, 0x7E, 0x02, 0x0A, 0x0C, 0x70, 0x50, 0x00, 0x99, 0x7E, + 0x01, 0x0A, 0x0C, 0x70, 0x82, 0x00, 0xA9, 0x7E, 0x04, 0x0A, 0x08, 0x50, 0x00, 0xFF, 0x04, 0xC0, + 0x0C, 0x70, 0x0B, 0x15, 0x2C, 0x50, 0xFF, 0x0F, 0xB9, 0x71, 0x04, 0x00, 0x0C, 0xD0, 0x60, 0x14, + 0xB9, 0xC1, 0x18, 0x00, 0xB9, 0xC1, 0x14, 0x00, 0xB9, 0xC1, 0x30, 0x00, 0xB9, 0xC1, 0x2C, 0x00, + 0xB9, 0xC1, 0x28, 0x00, 0xB9, 0x51, 0x24, 0x00, 0xF2, 0x6F, 0x0C, 0x70, 0x46, 0x00, 0xA9, 0x7E, + 0x02, 0x0A, 0x04, 0x7A, 0x99, 0x7E, 0x01, 0x0A, 0x0C, 0x70, 0x64, 0x00, 0xF2, 0xDD, 0xC6, 0x57, + 0xD2, 0xC5, 0x18, 0x66, 0x77, 0x00, 0xC6, 0x67, 0x0C, 0x70, 0x14, 0x00, 0x99, 0x7E, 0x00, 0x0A, + 0xC2, 0x14, 0x0C, 0x60, 0x50, 0x00, 0x99, 0x6E, 0x01, 0x0A, 0x0C, 0x60, 0x82, 0x00, 0xA9, 0x6E, + 0x04, 0x0A, 0x18, 0x6E, 0x1D, 0x03, 0x0C, 0x70, 0x64, 0x00, 0xC4, 0x61, 0xA9, 0x7E, 0x02, 0x0A, + 0xC2, 0xC5, 0x99, 0x0E, 0x01, 0x0A, 0xF2, 0xC0, 0x0C, 0x70, 0x78, 0x00, 0xF2, 0x2A, 0x08, 0x60, + 0x00, 0x80, 0x2C, 0x60, 0x0C, 0xDC, 0x28, 0x7E, 0x12, 0x00, 0x18, 0x56, 0x78, 0x00, 0xC6, 0x57, + 0xC2, 0x0C, 0x04, 0x7F, 0x99, 0x7E, 0x00, 0x0A, 0x04, 0x65, 0x0C, 0x70, 0x64, 0x00, 0xA9, 0x7E, + 0x02, 0x0A, 0x99, 0x6E, 0x01, 0x0A, 0xF2, 0xA8, 0x18, 0x66, 0x77, 0x00, 0xC6, 0x67, 0x0C, 0x70, + 0x14, 0x00, 0x99, 0x7E, 0x00, 0x0A, 0xC2, 0x0B, 0x0C, 0x70, 0x64, 0x00, 0xA9, 0x7E, 0x02, 0x0A, + 0x04, 0x75, 0x99, 0x7E, 0x01, 0x0A, 0x0C, 0x70, 0x5A, 0x00, 0xF2, 0x96, 0x0C, 0x70, 0x96, 0x00, + 0xA9, 0x7E, 0x02, 0x0A, 0x99, 0x0E, 0x01, 0x0A, 0x0C, 0x70, 0x50, 0x00, 0xF2, 0x8D, 0x38, 0x7E, + 0x38, 0x0A, 0x5C, 0x70, 0xFF, 0x03, 0x63, 0x7C, 0xD4, 0x71, 0x92, 0x16, 0x06, 0x2C, 0x4B, 0x36, + 0x03, 0x00, 0x38, 0x61, 0x04, 0x00, 0x24, 0xC1, 0xC4, 0xCD, 0x24, 0x62, 0xB9, 0x61, 0x04, 0x00, + 0x24, 0xDC, 0x8A, 0x3E, 0x02, 0x00, 0x18, 0x7E, 0x70, 0x0A, 0x38, 0x51, 0x28, 0x00, 0xC6, 0x75, + 0xD2, 0xE7, 0xFA, 0x36, 0x02, 0x00, 0x04, 0x71, 0x26, 0x7C, 0x57, 0x71, 0x26, 0x7E, 0x38, 0x77, + 0x38, 0x0A, 0x06, 0xA7, 0x5C, 0x70, 0xFF, 0x0F, 0xB9, 0x71, 0x0C, 0x00, 0xF0, 0x7D, 0x77, 0xA6, + 0x5C, 0xA0, 0xFF, 0x0F, 0x32, 0x0E, 0x38, 0x61, 0x0C, 0x00, 0x38, 0x51, 0x04, 0x00, 0xA1, 0xAD, + 0xA9, 0x6D, 0x02, 0x00, 0x38, 0x61, 0x04, 0x00, 0x04, 0x71, 0x34, 0x61, 0x91, 0x76, 0x91, 0x75, + 0x70, 0x7D, 0x38, 0x51, 0x0C, 0x00, 0x06, 0x6A, 0x36, 0x67, 0x78, 0x7D, 0x02, 0x00, 0xB9, 0x61, + 0x08, 0x00, 0xB9, 0x61, 0x1C, 0x00, 0x36, 0x57, 0x86, 0x76, 0xB9, 0x51, 0x10, 0x00, 0x32, 0x04, + 0x16, 0x57, 0xB9, 0x51, 0x1C, 0x00, 0x38, 0x61, 0x10, 0x00, 0x86, 0x76, 0xB9, 0x61, 0x20, 0x00, + 0x32, 0x04, 0x16, 0x57, 0xB9, 0x51, 0x20, 0x00, 0x38, 0x61, 0x1C, 0x00, 0x38, 0x71, 0x20, 0x00, + 0x43, 0x66, 0x43, 0x77, 0x06, 0x37, 0x06, 0x26, 0xB9, 0x71, 0x38, 0x00, 0xB9, 0x61, 0x34, 0x00, + 0x0C, 0xF0, 0xBC, 0x00, 0xF1, 0xF0, 0x98, 0x70, 0xE4, 0x16, 0x06, 0xB2, 0xB9, 0x71, 0x40, 0x00, + 0x92, 0x1B, 0x38, 0x7E, 0x0C, 0x00, 0xDC, 0x70, 0x00, 0x03, 0x82, 0x0C, 0x86, 0xB2, 0x32, 0x02, + 0x24, 0xB3, 0x06, 0x4B, 0x67, 0x41, 0x38, 0x2E, 0x00, 0x0A, 0x38, 0x3E, 0x04, 0x0A, 0x43, 0x44, + 0xF2, 0x06, 0x38, 0x2E, 0x00, 0x0A, 0x38, 0x3E, 0x04, 0x0A, 0x06, 0x4B, 0xEB, 0x39, 0x03, 0x00, + 0x06, 0xB2, 0x06, 0x92, 0xF2, 0x35, 0x08, 0x40, 0x00, 0x80, 0x2C, 0x40, 0x0C, 0xDC, 0x28, 0x7E, + 0x12, 0x00, 0x18, 0x64, 0x78, 0x00, 0xC6, 0x67, 0xC2, 0x04, 0x26, 0x22, 0x04, 0x33, 0xF2, 0x0C, + 0x08, 0x50, 0x00, 0x80, 0x2C, 0x50, 0x0C, 0xDC, 0x18, 0x65, 0x77, 0x00, 0xC6, 0x67, 0xC2, 0x0C, + 0x26, 0x22, 0x26, 0x2B, 0x04, 0x35, 0xAB, 0x15, 0x00, 0x00, 0x43, 0x42, 0x38, 0x3E, 0x04, 0x0A, + 0x38, 0x2E, 0x00, 0x0A, 0xF2, 0x0A, 0x06, 0x42, 0xF7, 0x4F, 0x26, 0x42, 0x38, 0x3E, 0x04, 0x0A, + 0x38, 0x2E, 0x00, 0x0A, 0xE7, 0x40, 0x43, 0x44, 0xEB, 0x39, 0x03, 0x00, 0x06, 0x92, 0x38, 0x3E, + 0x04, 0x0A, 0x38, 0x2E, 0x00, 0x0A, 0x06, 0x4B, 0xEB, 0x39, 0x03, 0x00, 0x06, 0xB2, 0x18, 0x7E, + 0x9A, 0x04, 0xC4, 0x72, 0xD2, 0x0F, 0x38, 0x60, 0xB0, 0x16, 0x78, 0x56, 0xBC, 0x00, 0xA9, 0x5E, + 0x08, 0x0A, 0xA9, 0x5E, 0x06, 0x0A, 0x78, 0x66, 0xBE, 0x00, 0xA9, 0x6E, 0x0C, 0x0A, 0xA9, 0x6E, + 0x0A, 0x0A, 0x38, 0x70, 0xB0, 0x16, 0x28, 0x3E, 0x0A, 0x0A, 0x18, 0x57, 0xB9, 0x00, 0x18, 0x67, + 0xB8, 0x00, 0x18, 0x77, 0xBA, 0x00, 0xB9, 0x51, 0x50, 0x00, 0x2F, 0x85, 0x06, 0x00, 0x06, 0x25, + 0x26, 0x87, 0xB9, 0x71, 0x4C, 0x00, 0xB9, 0x61, 0x48, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x38, 0x61, + 0x48, 0x00, 0x28, 0x3E, 0x06, 0x0A, 0x06, 0x42, 0x06, 0x26, 0xB9, 0x41, 0x44, 0x00, 0x6B, 0x13, + 0x00, 0x00, 0x38, 0x71, 0x4C, 0x00, 0x38, 0x41, 0x44, 0x00, 0x06, 0x39, 0x26, 0x42, 0x06, 0x27, + 0xB9, 0x41, 0x44, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x38, 0x41, 0x44, 0x00, 0x06, 0x38, 0x26, 0x24, + 0x43, 0x22, 0xAB, 0x15, 0x00, 0x00, 0x38, 0x51, 0x50, 0x00, 0x28, 0x3E, 0x0C, 0x0A, 0x43, 0x42, + 0x06, 0x92, 0x06, 0x25, 0xB9, 0x41, 0x3C, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x38, 0x61, 0x48, 0x00, + 0x28, 0x3E, 0x08, 0x0A, 0x06, 0x52, 0x06, 0x26, 0xB9, 0x51, 0x50, 0x00, 0x6B, 0x13, 0x00, 0x00, + 0x38, 0x71, 0x4C, 0x00, 0x38, 0x51, 0x50, 0x00, 0x06, 0x3B, 0x26, 0x52, 0x06, 0x27, 0xB9, 0x51, + 0x50, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x38, 0x51, 0x50, 0x00, 0x06, 0x38, 0x26, 0x25, 0x43, 0x22, + 0xAB, 0x15, 0x00, 0x00, 0x06, 0x82, 0x43, 0xB2, 0x38, 0x21, 0x1C, 0x00, 0x06, 0x39, 0x6B, 0x13, + 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x06, 0x92, 0x38, 0x21, 0x20, 0x00, + 0x06, 0x38, 0x6B, 0x13, 0x00, 0x00, 0x0C, 0x30, 0x64, 0x00, 0xAB, 0x15, 0x00, 0x00, 0xB8, 0x51, + 0x40, 0x00, 0x06, 0x82, 0x92, 0x47, 0xC4, 0x90, 0x70, 0x2D, 0x78, 0x3D, 0x04, 0x00, 0x78, 0x5D, + 0x02, 0x00, 0x78, 0x6D, 0x06, 0x00, 0x92, 0x21, 0xB8, 0x71, 0x1C, 0x00, 0x82, 0x1E, 0x38, 0x4E, + 0x64, 0x07, 0xC6, 0xA4, 0x22, 0x07, 0x0C, 0xF0, 0x80, 0x07, 0x3F, 0x44, 0x0F, 0x00, 0xC6, 0xA4, + 0x02, 0x14, 0x36, 0x23, 0xC4, 0x20, 0x32, 0x02, 0x16, 0x22, 0x38, 0x31, 0x34, 0x00, 0xB9, 0x51, + 0x50, 0x00, 0x43, 0x22, 0xB9, 0x61, 0x48, 0x00, 0x0C, 0xF0, 0x98, 0x00, 0xF1, 0xF0, 0x38, 0x61, + 0x48, 0x00, 0x38, 0x51, 0x50, 0x00, 0x06, 0x92, 0xC4, 0x80, 0x92, 0x1C, 0xB8, 0x71, 0x20, 0x00, + 0x82, 0x19, 0x38, 0x4E, 0x68, 0x07, 0x38, 0x71, 0x0C, 0x00, 0xC6, 0x74, 0x22, 0x07, 0x0C, 0x30, + 0x38, 0x04, 0x3F, 0x44, 0x03, 0x00, 0xC6, 0x74, 0x02, 0x0D, 0x3F, 0x26, 0x05, 0x00, 0xC4, 0x20, + 0x32, 0x02, 0x16, 0x22, 0x38, 0x31, 0x38, 0x00, 0x43, 0x22, 0x0C, 0xF0, 0x98, 0x00, 0xF1, 0xF0, + 0x06, 0x82, 0x38, 0x41, 0x3C, 0x00, 0x38, 0x51, 0x18, 0x00, 0x06, 0x64, 0xC6, 0x45, 0x32, 0x02, + 0x06, 0x65, 0x38, 0x71, 0x14, 0x00, 0x43, 0x66, 0xC6, 0xB7, 0xB9, 0x61, 0x18, 0x00, 0x06, 0x6B, + 0x32, 0x02, 0x06, 0x67, 0x38, 0x51, 0x08, 0x00, 0x43, 0x66, 0x15, 0xB5, 0x38, 0x51, 0x04, 0x00, + 0xB9, 0x61, 0x14, 0x00, 0xF7, 0xBF, 0x34, 0x51, 0x60, 0x35, 0x38, 0x61, 0x10, 0x00, 0x33, 0x4B, + 0xC6, 0x34, 0x15, 0xA6, 0xF7, 0xAF, 0x33, 0x6A, 0x92, 0x04, 0x04, 0x71, 0xB9, 0x71, 0x2C, 0x00, + 0x38, 0x71, 0x04, 0x00, 0x60, 0x37, 0xC6, 0x36, 0x92, 0x04, 0x04, 0x71, 0xB9, 0x71, 0x30, 0x00, + 0x91, 0x45, 0x38, 0x51, 0x04, 0x00, 0x06, 0x3D, 0x91, 0x65, 0x04, 0x44, 0x06, 0x21, 0xEB, 0x73, + 0x03, 0x00, 0xCB, 0x3B, 0x00, 0x00, 0x18, 0x6E, 0x9B, 0x04, 0xC4, 0x61, 0xD2, 0x16, 0x28, 0x6E, + 0x06, 0x03, 0x23, 0x22, 0xC6, 0x62, 0xC2, 0x11, 0x78, 0x6D, 0x08, 0x00, 0xC6, 0x69, 0x02, 0x05, + 0xB8, 0x71, 0x2C, 0x00, 0x82, 0x02, 0x06, 0x96, 0x78, 0x6D, 0x0A, 0x00, 0xC6, 0x68, 0x02, 0x05, + 0xB8, 0x51, 0x30, 0x00, 0x82, 0x02, 0x06, 0x86, 0xC4, 0xB0, 0x20, 0x61, 0x82, 0x03, 0x23, 0x79, + 0xF2, 0x03, 0x16, 0x79, 0x23, 0x77, 0xC4, 0xA0, 0x26, 0x76, 0xA1, 0x71, 0x28, 0x71, 0x02, 0x00, + 0x92, 0x02, 0x16, 0x88, 0x23, 0x88, 0x26, 0x87, 0x06, 0x21, 0xA9, 0x81, 0x02, 0x00, 0xAB, 0xCA, + 0x02, 0x00, 0x70, 0x7D, 0x70, 0xA1, 0x3F, 0x77, 0x0A, 0x00, 0xC4, 0x70, 0x32, 0x02, 0x16, 0x77, + 0xA9, 0x7D, 0x08, 0x00, 0x78, 0xB1, 0x02, 0x00, 0x78, 0x7D, 0x02, 0x00, 0x3F, 0x77, 0x0B, 0x00, + 0xC4, 0x70, 0x32, 0x02, 0x16, 0x77, 0x04, 0x24, 0x06, 0x3D, 0x04, 0x44, 0x26, 0x2D, 0xA9, 0x7D, + 0x0A, 0x00, 0xEB, 0x73, 0x03, 0x00, 0x06, 0x2D, 0x06, 0x31, 0x04, 0x44, 0xEB, 0x73, 0x03, 0x00, + 0x08, 0x60, 0x00, 0x80, 0x2C, 0x60, 0x0C, 0xDC, 0x18, 0x76, 0x2D, 0x00, 0x04, 0x62, 0xD6, 0x67, + 0x82, 0x06, 0x0C, 0x60, 0x7F, 0x07, 0x3F, 0xAA, 0x06, 0x00, 0x43, 0xAA, 0x04, 0x64, 0xD6, 0x67, + 0x82, 0x06, 0x0C, 0x60, 0x37, 0x04, 0x3F, 0xBB, 0x06, 0x00, 0x43, 0xBB, 0x04, 0x61, 0xD4, 0x71, + 0x26, 0x6C, 0x57, 0x61, 0x23, 0xAA, 0x23, 0xBB, 0x26, 0x6E, 0x82, 0x11, 0x38, 0x76, 0x38, 0x0A, + 0x38, 0x51, 0x24, 0x00, 0x1C, 0x40, 0x00, 0x10, 0x5C, 0xA0, 0xFF, 0x0F, 0x56, 0x74, 0x66, 0x7A, + 0x5C, 0xB0, 0xFF, 0x0F, 0x57, 0xB6, 0x56, 0x75, 0x66, 0x7B, 0xF2, 0x10, 0x38, 0x76, 0x38, 0x0A, + 0x38, 0x51, 0x24, 0x00, 0x1C, 0x40, 0x00, 0x10, 0x5C, 0xB0, 0xFF, 0x0F, 0x56, 0x74, 0x66, 0x7B, + 0x5C, 0xA0, 0xFF, 0x0F, 0x57, 0xA6, 0x56, 0x75, 0x66, 0x7A, 0xB9, 0x76, 0x38, 0x0A, 0x38, 0x71, + 0x28, 0x00, 0x24, 0x71, 0x13, 0x77, 0xB9, 0x71, 0x28, 0x00, 0xFA, 0xBC, 0xFD, 0xFF, 0x0C, 0x20, + 0x0A, 0x0A, 0x26, 0x2E, 0x14, 0x34, 0x26, 0x32, 0x04, 0x44, 0xEB, 0x73, 0x03, 0x00, 0x38, 0x61, + 0x18, 0x00, 0x38, 0x71, 0x14, 0x00, 0xA9, 0x6E, 0x06, 0x0A, 0xA9, 0x7E, 0x08, 0x0A, 0x58, 0xC1, + 0x64, 0x00, 0x58, 0x81, 0x54, 0x00, 0x2C, 0x10, 0x74, 0x00, 0xE1, 0xF0, 0x06, 0x65, 0x0C, 0x60, + 0xB4, 0x16, 0x28, 0x50, 0xB4, 0x16, 0x06, 0x72, 0xC6, 0x25, 0x82, 0x0C, 0x28, 0x56, 0x02, 0x00, + 0xC6, 0x25, 0x82, 0x0A, 0x28, 0x66, 0x04, 0x00, 0x04, 0x20, 0xC6, 0x76, 0x92, 0x07, 0x04, 0x22, + 0xF2, 0x04, 0x04, 0x20, 0xF2, 0x02, 0x04, 0x21, 0x24, 0x21, 0xE1, 0xF0, 0x34, 0x14, 0xB1, 0xF1, + 0x08, 0x50, 0x00, 0x30, 0x18, 0x30, 0xEA, 0x16, 0x0C, 0x60, 0x00, 0x0B, 0x04, 0x70, 0x0C, 0x20, + 0xB4, 0x16, 0x0C, 0xF0, 0x28, 0x08, 0x2C, 0x50, 0x00, 0xA0, 0xC4, 0x30, 0x2F, 0x42, 0x07, 0x00, + 0x20, 0x44, 0x92, 0x07, 0x57, 0x41, 0x26, 0x45, 0x30, 0x44, 0x5C, 0x40, 0xFF, 0x7F, 0xF2, 0x04, + 0x26, 0x44, 0x26, 0x4F, 0x20, 0x44, 0x24, 0x72, 0xC4, 0x76, 0xA1, 0x46, 0x24, 0x62, 0x92, 0xEE, + 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x00, 0x00, 0xE1, 0xF0, 0x00, 0x00, 0x04, 0x70, 0xC6, 0x74, + 0x82, 0x09, 0x2F, 0x67, 0x03, 0x00, 0x60, 0x56, 0x2F, 0x67, 0x02, 0x00, 0x91, 0x56, 0x24, 0x71, + 0xF2, 0xF7, 0xE1, 0xF0, 0x71, 0x00, 0xF2, 0xFF, 0x70, 0x6F, 0x36, 0x76, 0x78, 0x6F, 0x02, 0x00, + 0xC6, 0x76, 0xB2, 0x07, 0x26, 0x77, 0x26, 0x7F, 0x78, 0x77, 0x06, 0x00, 0x26, 0x7F, 0xE1, 0x70, + 0x78, 0x7F, 0x04, 0x00, 0x26, 0x7F, 0xE1, 0x70, 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, + 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, + 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, + 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, + 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, + 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, + 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, + 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, + 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, + 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, + 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, + 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, + 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, + 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, + 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, + 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, + 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3, 0x04, 0x70, 0x06, 0x62, 0x73, 0x67, 0xD4, 0x61, + 0x04, 0x51, 0x26, 0x57, 0x13, 0x55, 0x92, 0x03, 0x06, 0x75, 0xF2, 0xF8, 0x06, 0x27, 0xE1, 0xF0, + 0xC6, 0x23, 0x06, 0x72, 0x02, 0x02, 0x06, 0x73, 0x43, 0x27, 0xE1, 0xF0, 0x34, 0x18, 0xC1, 0xE1, + 0x06, 0xE4, 0xCB, 0x04, 0x00, 0x00, 0x06, 0x3E, 0xCB, 0x04, 0x00, 0x00, 0x40, 0xE1, 0x24, 0x18, + 0xE1, 0xF0, 0x24, 0x00, 0xC6, 0x32, 0x06, 0x73, 0x32, 0x02, 0x06, 0x72, 0x43, 0x27, 0xE1, 0xF0, + 0x34, 0x18, 0xC1, 0xE1, 0x06, 0xE4, 0xEB, 0x05, 0x00, 0x00, 0x06, 0x3E, 0xEB, 0x05, 0x00, 0x00, + 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, 0x24, 0x00, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xE5, + 0x06, 0xD6, 0x4B, 0x06, 0x00, 0x00, 0x06, 0x3E, 0x06, 0x4D, 0x4B, 0x06, 0x00, 0x00, 0x50, 0xC1, + 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x24, 0x00, 0x14, 0x71, 0x26, 0x74, 0x26, 0x27, 0x16, 0x64, + 0x26, 0x37, 0x2F, 0x76, 0x03, 0x00, 0x26, 0x62, 0xC4, 0x40, 0x82, 0x09, 0x2F, 0x54, 0x07, 0x00, + 0x60, 0x35, 0x2F, 0x54, 0x06, 0x00, 0x91, 0x35, 0x34, 0x41, 0xF2, 0xF7, 0xE1, 0xF0, 0x24, 0x00, + 0x04, 0x70, 0xC6, 0x74, 0x82, 0x09, 0x2F, 0x67, 0x03, 0x00, 0x60, 0x56, 0x2F, 0x67, 0x02, 0x00, + 0x91, 0x56, 0x24, 0x71, 0xF2, 0xF7, 0xE1, 0xF0, 0x04, 0x70, 0xC6, 0x74, 0x82, 0x0A, 0x2F, 0x67, + 0x07, 0x00, 0x2F, 0x56, 0x03, 0x00, 0x20, 0x55, 0x26, 0x62, 0xA1, 0x56, 0x24, 0x71, 0xF2, 0xF6, + 0xE1, 0xF0, 0x24, 0x00, 0x34, 0x14, 0xB1, 0xF1, 0x04, 0x70, 0x14, 0x61, 0x34, 0x41, 0xC6, 0x46, + 0x82, 0x09, 0x2F, 0x57, 0x03, 0x00, 0x30, 0xF5, 0x2F, 0x57, 0x02, 0x00, 0xB1, 0xF5, 0x24, 0x74, + 0xF2, 0xF6, 0x30, 0xF1, 0x24, 0x14, 0xE1, 0xF0, 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x04, 0x70, + 0x14, 0xF1, 0x34, 0x51, 0xC6, 0x5F, 0x82, 0x0D, 0x2F, 0x67, 0x03, 0x00, 0x30, 0xD6, 0x2F, 0xE7, + 0x02, 0x00, 0xB1, 0xDE, 0x2F, 0xE7, 0x04, 0x00, 0x30, 0xEE, 0x24, 0x74, 0xB1, 0xE6, 0xF2, 0xF2, + 0x50, 0xC1, 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x04, 0x70, 0xC6, 0x74, 0x82, 0x06, 0x2F, 0x67, + 0x02, 0x00, 0x91, 0x36, 0x24, 0x71, 0xF2, 0xFA, 0xE1, 0xF0, 0x24, 0x00, 0x04, 0x70, 0xC6, 0x74, + 0x82, 0x07, 0x2F, 0x67, 0x07, 0x00, 0x26, 0x62, 0xA1, 0x36, 0x24, 0x71, 0xF2, 0xF9, 0xE1, 0xF0, + 0x14, 0x71, 0x34, 0x41, 0xC6, 0x47, 0x82, 0x04, 0xB1, 0x32, 0x24, 0x24, 0xF2, 0xFB, 0xE1, 0xF0, + 0x3C, 0x10, 0x10, 0x00, 0xD1, 0xC1, 0x06, 0xC2, 0x06, 0xD3, 0x06, 0xE3, 0x06, 0x2E, 0x06, 0x3E, + 0x08, 0xF0, 0x00, 0x80, 0x2C, 0xF0, 0x6C, 0x02, 0xF1, 0xF0, 0xC6, 0x2C, 0xC2, 0x02, 0x76, 0xED, + 0xF7, 0xD0, 0xC4, 0xD0, 0x82, 0x03, 0x66, 0xED, 0xF2, 0xF2, 0x06, 0x2E, 0x50, 0xC1, 0x2C, 0x10, + 0x10, 0x00, 0xE1, 0xF0, 0x38, 0x60, 0xB4, 0x15, 0x08, 0x70, 0xFD, 0xFF, 0x2C, 0x70, 0xFF, 0xFF, + 0x56, 0x76, 0x08, 0x50, 0x31, 0x00, 0xC6, 0x75, 0x82, 0x05, 0x08, 0x70, 0x32, 0x00, 0xC6, 0x67, + 0x92, 0x03, 0xB1, 0x32, 0xE1, 0xF0, 0xF2, 0x00, 0x08, 0x20, 0x00, 0x40, 0x34, 0x14, 0x2C, 0x20, + 0x10, 0x60, 0x0C, 0x30, 0x00, 0xDE, 0xB1, 0xF1, 0x0B, 0x14, 0x00, 0x00, 0x30, 0xF1, 0x24, 0x14, + 0xE1, 0xF0, 0x24, 0x00, 0x08, 0x70, 0x00, 0x40, 0xB9, 0x07, 0x10, 0x60, 0xE1, 0xF0, 0x24, 0x00, + 0x34, 0x14, 0x0C, 0x70, 0x1E, 0x00, 0xB1, 0x71, 0x30, 0x71, 0x14, 0x61, 0xC4, 0x70, 0x26, 0x67, + 0xB1, 0x61, 0x92, 0xFB, 0x24, 0x14, 0xE1, 0xF0, 0xE1, 0xF0, 0x24, 0x00, 0x3C, 0x10, 0x10, 0x00, + 0xD1, 0xC1, 0x06, 0x72, 0x08, 0xE0, 0x00, 0x40, 0x0C, 0x20, 0x00, 0x60, 0x06, 0xD3, 0x26, 0x2E, + 0x06, 0x37, 0xB9, 0x0E, 0x90, 0x60, 0x0B, 0x14, 0x00, 0x00, 0x0C, 0x20, 0x08, 0x60, 0xB9, 0xDE, + 0x04, 0x60, 0x26, 0x2E, 0x04, 0x30, 0x0B, 0x14, 0x00, 0x00, 0x38, 0x7E, 0x90, 0x60, 0xD4, 0x71, + 0x82, 0xFD, 0x0C, 0x70, 0x00, 0x81, 0xB9, 0x7E, 0x00, 0x60, 0x6B, 0x16, 0x00, 0x00, 0x50, 0xC1, + 0x2C, 0x10, 0x10, 0x00, 0xE1, 0xF0, 0x24, 0x00, 0x3C, 0x10, 0x20, 0x00, 0xD9, 0xC1, 0x10, 0x00, + 0x06, 0x72, 0x08, 0xD0, 0x00, 0x40, 0x0C, 0x20, 0x00, 0x60, 0xD1, 0x81, 0x06, 0xE3, 0x06, 0xB5, + 0x26, 0x2D, 0x06, 0x37, 0x0C, 0xA0, 0x08, 0x60, 0x06, 0xC4, 0x26, 0xBE, 0x0B, 0x14, 0x00, 0x00, + 0x26, 0xAD, 0xC6, 0xEB, 0x82, 0x10, 0xB9, 0xED, 0x04, 0x60, 0x30, 0x3C, 0x04, 0x91, 0x06, 0x2A, + 0x26, 0x9E, 0x0B, 0x14, 0x00, 0x00, 0x38, 0x7D, 0x90, 0x60, 0xD4, 0x72, 0x82, 0xFD, 0x24, 0xC4, + 0x06, 0xE9, 0xF2, 0xF0, 0x0C, 0x70, 0x00, 0x81, 0xB9, 0x7D, 0x00, 0x60, 0x6B, 0x16, 0x00, 0x00, + 0x58, 0xC1, 0x10, 0x00, 0x50, 0x81, 0x2C, 0x10, 0x20, 0x00, 0xE1, 0xF0, 0x3C, 0x10, 0x14, 0x00, + 0xD9, 0xC1, 0x04, 0x00, 0x86, 0xD6, 0x08, 0x70, 0x00, 0x40, 0x82, 0x05, 0x0C, 0x60, 0x00, 0xDE, + 0xB9, 0x67, 0x10, 0x60, 0xB9, 0x27, 0x00, 0x60, 0xB9, 0x37, 0x04, 0x60, 0x04, 0x61, 0x04, 0x70, + 0x08, 0x20, 0x00, 0x40, 0xC6, 0x75, 0x82, 0x0E, 0xB1, 0x61, 0x30, 0x31, 0x14, 0xF1, 0xC4, 0x30, + 0x26, 0xF3, 0xB1, 0xF1, 0x92, 0xFB, 0x38, 0x32, 0x0C, 0x60, 0x24, 0x71, 0xB1, 0x34, 0x24, 0x44, + 0xF2, 0xF2, 0x08, 0xE0, 0x00, 0x40, 0x0C, 0x70, 0x00, 0x81, 0xB9, 0x7E, 0x00, 0x60, 0x6B, 0x16, + 0x00, 0x00, 0xC4, 0xD0, 0x82, 0x03, 0xB9, 0x0E, 0x10, 0x60, 0x58, 0xC1, 0x04, 0x00, 0x04, 0x21, + 0x2C, 0x10, 0x14, 0x00, 0xE1, 0xF0, 0x24, 0x00, 0x34, 0x18, 0xC1, 0xE1, 0x08, 0x70, 0x00, 0x40, + 0x0C, 0x60, 0x00, 0xDE, 0xB9, 0x67, 0x10, 0x60, 0x77, 0x41, 0xB9, 0x27, 0x00, 0x60, 0x77, 0x31, + 0x34, 0x41, 0x08, 0x60, 0x00, 0x13, 0xB9, 0x37, 0x04, 0x60, 0x66, 0x46, 0xB9, 0x47, 0x14, 0x60, + 0x08, 0x50, 0x00, 0x10, 0x38, 0x67, 0x14, 0x60, 0x0C, 0x40, 0x14, 0x60, 0xD6, 0x65, 0x26, 0x47, + 0x92, 0xFA, 0x38, 0xE7, 0x18, 0x60, 0xB1, 0x04, 0x0C, 0x60, 0x00, 0x81, 0xB9, 0x67, 0x00, 0x60, + 0xB9, 0x07, 0x10, 0x60, 0x6B, 0x16, 0x00, 0x00, 0x06, 0x2E, 0x40, 0xE1, 0x24, 0x18, 0xE1, 0xF0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x18, 0x0E, 0x17, 0x0E, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0x02, 0x06, 0x0B, 0xFF, 0x17, 0x17, 0x17, 0xFF, 0x00, + 0x80, 0x07, 0x38, 0x04, 0xFF, 0x1F, 0xFF, 0x11, 0xD0, 0x07, 0xD0, 0x07, 0x01, 0xFA, 0xFA, 0x00, + 0x00, 0x02, 0x01, 0x46, 0x00, 0x01, 0x00, 0x02, 0x0A, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x4E, 0x00, 0x00, 0xE0, 0x2E, 0x00, 0x00, + 0xE0, 0x2E, 0x00, 0x00, 0xA0, 0x86, 0x01, 0x00, 0x00, 0x24, 0xF4, 0x00, 0x50, 0xC3, 0x00, 0x00, + 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0x6E, 0x50, 0x0A, 0x14, 0x01, 0x00, 0x14, 0x00, + 0x00, 0x00, 0x5A, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xA0, 0x0F, 0x64, 0x64, 0x64, 0x01, 0x0E, 0x20, + 0x02, 0x04, 0x02, 0x07, 0x03, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x50, 0x00, + 0x00, 0x00, 0x14, 0x00, 0x05, 0x05, 0x08, 0x0E, 0x11, 0x17, 0x17, 0x17, 0x17, 0x02, 0x03, 0x04, + 0x02, 0x01, 0x00, 0x04, 0x00, 0x06, 0x01, 0x03, 0x08, 0x04, 0x10, 0x03, 0x03, 0x00, 0x90, 0x01, + 0x00, 0x00, 0x32, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0x3F, 0x00, 0x00, 0x42, 0x22, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x88, 0x00, 0x10, 0x1F, 0x10, 0x1F, + 0x64, 0x3C, 0x10, 0x00, 0x64, 0x3C, 0x10, 0x00, 0x64, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x08, 0x82, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x28, 0x18, 0x14, 0x00, 0x10, 0x10, 0x00, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x28, 0x18, 0x14, 0x00, 0x28, 0x18, 0x14, 0x00, 0x28, 0x18, 0x14, 0x00, + 0x51, 0x06, 0x02, 0x00, 0x63, 0x07, 0x02, 0x00, 0x63, 0x07, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x40, 0x0F, 0x40, 0x0F, 0x00, 0x0E, 0x00, 0x0E, 0x54, 0x28, 0x00, 0x02, + 0x66, 0x7F, 0xF0, 0x07, 0x66, 0x7F, 0xF0, 0x07, 0x42, 0x22, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x88, 0x00, 0x10, 0x1F, 0x10, 0x1F, + 0x64, 0x3C, 0x10, 0x00, 0x64, 0x3C, 0x10, 0x00, 0x64, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x08, 0x82, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x12, 0x0A, 0x12, 0x00, 0x10, 0x10, 0x00, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x12, 0x0A, 0x12, 0x00, 0x12, 0x0A, 0x12, 0x00, 0x12, 0x0A, 0x12, 0x00, + 0x51, 0xE6, 0x00, 0x00, 0x63, 0x07, 0x02, 0x00, 0x63, 0x07, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x40, 0x0F, 0x40, 0x0F, 0x00, 0x0E, 0x00, 0x0E, 0x54, 0x10, 0xB0, 0x00, + 0x66, 0x7F, 0xF0, 0x07, 0x66, 0x7F, 0xF0, 0x07, 0x42, 0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x88, 0x00, 0x10, 0x1F, 0x10, 0x1F, + 0x64, 0x3C, 0x10, 0x00, 0x64, 0x3C, 0x10, 0x00, 0x64, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x08, 0x82, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x24, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x28, 0x18, 0x14, 0x00, 0x10, 0x10, 0x00, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x28, 0x18, 0x14, 0x00, 0x28, 0x18, 0x14, 0x00, 0x28, 0x18, 0x14, 0x00, + 0x61, 0x07, 0x02, 0x00, 0x63, 0x07, 0x02, 0x00, 0x63, 0x07, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x40, 0x0F, 0x40, 0x0F, 0x00, 0x0E, 0x00, 0x0E, 0x54, 0x28, 0x00, 0x02, + 0x66, 0x7F, 0xF0, 0x07, 0x66, 0x7F, 0xF0, 0x07, 0x42, 0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x88, 0x00, 0x10, 0x1F, 0x10, 0x1F, + 0x64, 0x3C, 0x10, 0x00, 0x64, 0x3C, 0x10, 0x00, 0x64, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x08, 0x82, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x12, 0x0A, 0x12, 0x00, 0x10, 0x10, 0x00, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x12, 0x0A, 0x12, 0x00, 0x12, 0x0A, 0x12, 0x00, 0x12, 0x0A, 0x12, 0x00, + 0x61, 0xE7, 0x00, 0x00, 0x63, 0x07, 0x02, 0x00, 0x63, 0x07, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x40, 0x0F, 0x40, 0x0F, 0x00, 0x0E, 0x00, 0x0E, 0x54, 0x10, 0xB0, 0x00, + 0x66, 0x7F, 0xF0, 0x07, 0x66, 0x7F, 0xF0, 0x07, 0x02, 0x00, 0x00, 0x00, 0x80, 0x40, 0x05, 0x00, + 0x50, 0x07, 0x05, 0x50, 0xC8, 0x00, 0x90, 0x01, 0x32, 0x00, 0x32, 0x00, 0x19, 0x19, 0x32, 0x00, + 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x64, 0x64, 0xC8, 0x00, 0x14, 0x00, 0x01, 0x00, 0x32, 0x00, + 0x3C, 0x00, 0x14, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x64, 0x00, 0x00, 0x00, 0x3C, 0x00, + 0x14, 0x00, 0x64, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x1E, 0x00, 0x64, 0x00, 0x20, 0x03, 0x64, 0x00, 0x64, 0x00, + 0x14, 0x00, 0x96, 0x00, 0x00, 0x05, 0x04, 0x0A, 0x05, 0x06, 0xC8, 0x00, 0x05, 0x32, 0x0A, 0x17, + 0x19, 0x17, 0x19, 0x1B, 0x19, 0x19, 0x16, 0x19, 0x1E, 0x1E, 0x1E, 0x19, 0x1E, 0x1E, 0x1E, 0x1E, + 0x1E, 0x3C, 0x06, 0x64, 0x02, 0x28, 0x20, 0x03, 0xDC, 0x05, 0xC8, 0x00, 0x14, 0x00, 0x28, 0x00, + 0x14, 0x00, 0x0A, 0x00, 0x46, 0x02, 0x02, 0x01, 0x01, 0x00, 0x1E, 0x00, 0x32, 0x00, 0x64, 0x00, + 0x14, 0x01, 0x02, 0x03, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x19, 0x00, 0x32, 0x00, 0x5A, 0x00, 0x02, 0x00, 0x64, 0x00, + 0x32, 0x32, 0x14, 0x00, 0x00, 0x00, 0x32, 0x00, 0x3C, 0x00, 0x0A, 0x0A, 0x1E, 0x00, 0x05, 0x0A, + 0x01, 0x00, 0x3C, 0x00, 0x50, 0x00, 0x05, 0x00, 0x82, 0x00, 0xC8, 0x00, 0x05, 0x05, 0x14, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x40, 0x05, 0x00, 0x50, 0x07, 0x05, 0x50, + 0xC8, 0x00, 0x90, 0x01, 0x32, 0x00, 0x32, 0x00, 0x19, 0x19, 0x64, 0x00, 0x00, 0x00, 0x32, 0x00, + 0x00, 0x00, 0x64, 0x64, 0xC8, 0x00, 0x14, 0x00, 0x01, 0x00, 0x32, 0x00, 0x3C, 0x00, 0x14, 0x00, + 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x64, 0x00, 0x00, 0x00, 0xC4, 0xFF, 0x14, 0x00, 0x64, 0x00, + 0x00, 0x00, 0x3C, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x1E, 0x00, 0x1E, 0x00, 0x20, 0x03, 0x64, 0x00, 0x64, 0x00, 0x14, 0x00, 0x96, 0x00, + 0x00, 0x05, 0x04, 0x0A, 0x05, 0x06, 0xDC, 0x00, 0x05, 0x32, 0x0A, 0x17, 0x19, 0x17, 0x19, 0x1B, + 0x19, 0x19, 0x16, 0x19, 0x1E, 0x1E, 0x1E, 0x19, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x3C, 0x0A, 0x64, + 0x03, 0x0A, 0x20, 0x03, 0xDC, 0x05, 0xC8, 0x00, 0x14, 0x00, 0x28, 0x00, 0x1E, 0x00, 0x0A, 0x00, + 0x46, 0x02, 0x02, 0x01, 0x01, 0x00, 0x1E, 0x00, 0x32, 0x00, 0x64, 0x00, 0x14, 0x01, 0x02, 0x03, + 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x0F, 0x00, 0x19, 0x00, 0x32, 0x00, 0x5A, 0x00, 0x02, 0x00, 0x64, 0x00, 0x32, 0x32, 0x14, 0x00, + 0x00, 0x00, 0x32, 0x00, 0x64, 0x00, 0x0A, 0x0A, 0x3C, 0x00, 0x05, 0x0A, 0x01, 0x00, 0x3C, 0x00, + 0x50, 0x00, 0x05, 0x00, 0x82, 0x00, 0xC8, 0x00, 0x05, 0x05, 0x1E, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x90, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0E, 0x18, 0x0E, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x64, 0x00, 0x10, 0x08, 0x12, 0x00, 0x54, 0xFF, 0x0F, 0x00, 0x10, 0x90, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x64, 0x00, 0x16, 0x32, 0x10, 0x10, 0x01, 0x00, 0x08, 0x00, + 0x32, 0x00, 0x64, 0x10, 0x51, 0xC6, 0x00, 0x00, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x64, 0xC0, 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0F, 0x40, 0x0F, + 0x01, 0x01, 0x80, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x80, 0x00, 0x80, 0x0A, 0x00, 0x00, 0x00, + 0xE0, 0x0F, 0x00, 0x00, 0x08, 0x07, 0x98, 0x08, 0x0E, 0x18, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, + 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x22, 0x01, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x88, 0x00, 0x10, 0x1F, 0x10, 0x1F, 0x64, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x08, 0x82, + 0x00, 0x00, 0xFF, 0x0F, 0x01, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xAC, 0x0D, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x10, 0xB0, 0x00, + 0xD5, 0xC6, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0E, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x21, 0x50, 0x06, 0x00, 0x2F, 0x01, 0x03, 0x00, + 0x1B, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x31, 0x04, 0x40, 0x00, 0x04, 0x22, 0x88, 0x00, 0x00, 0xFF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x7F, 0xFC, 0x8F, 0xBF, 0x01, 0x20, 0x00, 0x00, + 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x13, 0x12, 0x11, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x00, + 0x00, 0x00, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x17, 0x00, 0x00, 0xFF, 0x00, 0x20, 0x86, 0x00, 0x00, 0x00, 0x4C, + 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x26, 0x18, 0x00, + 0x38, 0x26, 0x10, 0x01, 0x45, 0x26, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x28, 0x08, 0x03, + 0x30, 0x26, 0x0A, 0x00, 0x28, 0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x07, 0x13, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4E, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x25, 0xDC, 0x05, 0x00, 0x27, 0x0C, 0x00, 0x00, 0x25, 0xFC, 0x0F, 0x00, 0x25, + 0xFC, 0x0F, 0x00, 0x27, 0xFC, 0x0F, 0x00, 0x25, 0x54, 0x06, 0x00, 0x25, 0x1C, 0x00, 0x00, 0x27, + 0x34, 0x00, 0x00, 0x25, 0xC4, 0x05, 0x00, 0x25, 0x9C, 0x05, 0x00, 0x23, 0x08, 0x00, 0x00, 0x1B, + 0x30, 0x00, 0x00, 0x1C, 0xC4, 0x07, 0x00, 0x1A, 0x98, 0x03, 0x00, 0x1A, 0xB0, 0x02, 0x00, 0x1B, + 0xEC, 0x00, 0x00, 0x18, 0xFC, 0x0F, 0x00, 0x19, 0x08, 0x00, 0x00, 0x1B, 0x08, 0x00, 0x00, 0x1B, + 0x34, 0x04, 0x00, 0x1B, 0x2C, 0x00, 0x00, 0x1B, 0x18, 0x00, 0x00, 0x17, 0x1C, 0x00, 0x50, 0xBF, + 0x00, 0x0E, 0x00, 0x23, 0xF4, 0x0F, 0x00, 0x25, 0xFC, 0x0F, 0x00, 0x23, 0x00, 0x00, 0x00, 0x23, + 0x30, 0x01, 0x00, 0x25, 0xFC, 0x0F, 0x00, 0x23, 0xE0, 0x00, 0x00, 0x23, 0xFC, 0x0F, 0x00, 0x25, + 0xFC, 0x0F, 0x00, 0x23, 0x00, 0x00, 0x00, 0x23, 0xB8, 0x07, 0x00, 0x21, 0x10, 0x00, 0x00, 0x1C, + 0xE0, 0x00, 0x00, 0x1D, 0xFC, 0x0F, 0x00, 0x1B, 0xFC, 0x0F, 0x00, 0x1B, 0x0C, 0x00, 0x00, 0x1C, + 0x1C, 0x00, 0x00, 0x19, 0xB0, 0x01, 0x00, 0x1A, 0x30, 0x01, 0x00, 0x1C, 0x1C, 0x01, 0x00, 0x1C, + 0xDC, 0x00, 0x00, 0x1C, 0x24, 0x07, 0x00, 0x1C, 0xB8, 0x01, 0x00, 0x18, 0x98, 0x0B, 0x50, 0xBF, + 0x24, 0x04, 0x00, 0x22, 0xE4, 0x00, 0x00, 0x24, 0xFC, 0x0F, 0x00, 0x22, 0x24, 0x00, 0x00, 0x22, + 0x3C, 0x00, 0x00, 0x24, 0x14, 0x00, 0x00, 0x22, 0xD0, 0x01, 0x00, 0x22, 0xF4, 0x0F, 0x00, 0x24, + 0xFC, 0x0F, 0x00, 0x22, 0x00, 0x00, 0x00, 0x22, 0x1C, 0x00, 0x00, 0x23, 0x08, 0x00, 0x00, 0x1D, + 0x04, 0x03, 0x00, 0x1E, 0xF4, 0x0F, 0x00, 0x1C, 0xFC, 0x0F, 0x00, 0x1C, 0xB8, 0x0E, 0x00, 0x1D, + 0x90, 0x00, 0x00, 0x1A, 0x18, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1D, 0x0C, 0x00, 0x00, 0x1D, + 0x08, 0x00, 0x00, 0x1D, 0xB8, 0x0E, 0x00, 0x1D, 0xF4, 0x0F, 0x00, 0x19, 0xFC, 0x0F, 0x50, 0x20, + 0x04, 0x00, 0x00, 0x22, 0x0C, 0x04, 0x00, 0x24, 0x04, 0x00, 0x00, 0x22, 0x38, 0x0E, 0x00, 0x22, + 0x9C, 0x00, 0x00, 0x24, 0xDC, 0x01, 0x00, 0x22, 0x80, 0x0D, 0x00, 0x22, 0xFC, 0x0F, 0x00, 0x24, + 0xFC, 0x0F, 0x00, 0x22, 0xB8, 0x0E, 0x00, 0x22, 0x1C, 0x00, 0x00, 0x20, 0x78, 0x06, 0x00, 0x1E, + 0x00, 0x00, 0x00, 0x1F, 0x50, 0x01, 0x00, 0x1D, 0xFC, 0x0F, 0x00, 0x1D, 0x10, 0x00, 0x00, 0x1E, + 0xE0, 0x00, 0x00, 0x1B, 0xFC, 0x0F, 0x00, 0x1C, 0x3C, 0x00, 0x00, 0x1E, 0x24, 0x00, 0x00, 0x1E, + 0xD8, 0x01, 0x00, 0x1E, 0x10, 0x00, 0x00, 0x1E, 0x04, 0x02, 0x00, 0x1A, 0x1C, 0x00, 0x50, 0xBF, + 0x00, 0x00, 0x00, 0x21, 0x1C, 0x00, 0x00, 0x23, 0x08, 0x00, 0x00, 0x21, 0xD0, 0x01, 0x00, 0x21, + 0xE4, 0x0F, 0x00, 0x23, 0xFC, 0x0F, 0x00, 0x21, 0x24, 0x0D, 0x00, 0x21, 0x0C, 0x07, 0x00, 0x23, + 0x0C, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x21, 0x1C, 0x04, 0x00, 0x1F, 0xF4, 0x0F, 0x00, 0x1F, + 0x08, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x1E, 0x24, 0x0D, 0x00, 0x1E, 0xC4, 0x0B, 0x00, 0x1F, + 0xF8, 0x0F, 0x00, 0x1C, 0xFC, 0x0F, 0x00, 0x1D, 0x04, 0x00, 0x00, 0x1F, 0x38, 0x0C, 0x00, 0x1F, + 0x0C, 0x01, 0x00, 0x1F, 0x04, 0x0A, 0x00, 0x1F, 0x2C, 0x0E, 0x00, 0x1B, 0xEC, 0x0F, 0x50, 0xBF, + 0x00, 0x00, 0x00, 0x21, 0x38, 0x0D, 0x00, 0x23, 0x9C, 0x00, 0x00, 0x21, 0xD4, 0x02, 0x00, 0x21, + 0x9C, 0x0D, 0x00, 0x23, 0xFC, 0x0F, 0x00, 0x21, 0x04, 0x09, 0x00, 0x21, 0xF8, 0x0F, 0x00, 0x23, + 0xFC, 0x0F, 0x00, 0x21, 0x00, 0x01, 0x00, 0x21, 0xF8, 0x0F, 0x00, 0x1F, 0xFC, 0x0F, 0x00, 0x1F, + 0x68, 0x06, 0x00, 0x20, 0x04, 0x00, 0x00, 0x1E, 0x58, 0x01, 0x00, 0x1E, 0x10, 0x00, 0x00, 0x1F, + 0x50, 0x01, 0x00, 0x1C, 0xEC, 0x0F, 0x00, 0x1D, 0x20, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, + 0xFC, 0x0F, 0x00, 0x1F, 0x14, 0x00, 0x00, 0x1F, 0xD8, 0x01, 0x00, 0x1B, 0xF4, 0x0F, 0x50, 0xBF, + 0x84, 0x06, 0x00, 0x20, 0xFC, 0x0F, 0x00, 0x22, 0xFC, 0x0F, 0x00, 0x20, 0x80, 0x05, 0x00, 0x20, + 0x0C, 0x00, 0x00, 0x22, 0x18, 0x0E, 0x00, 0x20, 0xB8, 0x07, 0x00, 0x20, 0x18, 0x00, 0x00, 0x22, + 0xB8, 0x07, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0xB8, 0x07, 0x00, 0x21, 0x0C, 0x00, 0x00, 0x20, + 0x04, 0x01, 0x00, 0x21, 0x1C, 0x00, 0x00, 0x1F, 0x1C, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x20, + 0xD4, 0x05, 0x00, 0x1D, 0x9C, 0x0E, 0x00, 0x1E, 0xB0, 0x01, 0x00, 0x20, 0x38, 0x01, 0x00, 0x20, + 0x1C, 0x01, 0x00, 0x20, 0xC4, 0x00, 0x00, 0x20, 0x2C, 0x03, 0x00, 0x1C, 0xFC, 0x0F, 0x50, 0x20, + 0x90, 0x0B, 0x00, 0x1F, 0xFC, 0x0F, 0x00, 0x21, 0xFC, 0x0F, 0x00, 0x1F, 0x24, 0x01, 0x00, 0x1F, + 0xBC, 0x04, 0x00, 0x21, 0x2C, 0x04, 0x00, 0x1F, 0xF0, 0x02, 0x00, 0x1F, 0xFC, 0x0F, 0x00, 0x21, + 0xFC, 0x0F, 0x00, 0x1F, 0x0C, 0x00, 0x00, 0x1F, 0x1C, 0x01, 0x00, 0x1D, 0xF8, 0x0F, 0x00, 0x21, + 0x00, 0x00, 0x00, 0x22, 0x78, 0x06, 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0xC4, 0x00, 0x00, 0x21, + 0xF4, 0x0F, 0x00, 0x1E, 0xFC, 0x0F, 0x00, 0x1F, 0x10, 0x00, 0x00, 0x21, 0x58, 0x01, 0x00, 0x21, + 0xF4, 0x0F, 0x00, 0x21, 0x04, 0x01, 0x00, 0x21, 0x2C, 0x00, 0x00, 0x1D, 0x14, 0x00, 0x50, 0xBF, + 0xE0, 0x00, 0x00, 0x1F, 0xFC, 0x0F, 0x00, 0x21, 0xFC, 0x0F, 0x00, 0x1F, 0xC0, 0x01, 0x00, 0x1F, + 0xF8, 0x0F, 0x00, 0x21, 0xFC, 0x0F, 0x00, 0x1F, 0x0C, 0x00, 0x00, 0x1F, 0x18, 0x0E, 0x00, 0x21, + 0xFC, 0x0F, 0x00, 0x1F, 0x10, 0x00, 0x00, 0x1F, 0x7C, 0x01, 0x00, 0x1D, 0xB8, 0x07, 0x00, 0x22, + 0x00, 0x00, 0x00, 0x23, 0x7C, 0x01, 0x00, 0x21, 0x3C, 0x01, 0x00, 0x21, 0x08, 0x00, 0x00, 0x22, + 0x18, 0x03, 0x00, 0x1F, 0xBC, 0x07, 0x00, 0x20, 0x04, 0x00, 0x00, 0x22, 0x7C, 0x06, 0x00, 0x22, + 0xB8, 0x07, 0x00, 0x22, 0x14, 0x00, 0x00, 0x22, 0x18, 0x00, 0x00, 0x1E, 0x14, 0x00, 0x50, 0xBF, + 0x38, 0x07, 0x00, 0x1E, 0x1C, 0x00, 0x00, 0x20, 0x1C, 0x00, 0x00, 0x1E, 0x14, 0x00, 0x00, 0x1E, + 0xDC, 0x05, 0x00, 0x20, 0x3C, 0x07, 0x00, 0x1E, 0x90, 0x0A, 0x00, 0x1E, 0xFC, 0x0F, 0x00, 0x20, + 0xFC, 0x0F, 0x00, 0x1E, 0xB0, 0x04, 0x00, 0x1E, 0x0C, 0x00, 0x00, 0x1C, 0x18, 0x01, 0x00, 0x23, + 0xB8, 0x07, 0x00, 0x24, 0x18, 0x00, 0x00, 0x22, 0xB8, 0x07, 0x00, 0x22, 0x10, 0x00, 0x00, 0x23, + 0x78, 0x06, 0x00, 0x20, 0x04, 0x00, 0x00, 0x21, 0x04, 0x0E, 0x00, 0x23, 0x48, 0x01, 0x00, 0x23, + 0xFC, 0x0F, 0x00, 0x23, 0xE0, 0x00, 0x00, 0x23, 0xFC, 0x0F, 0x00, 0x1F, 0xFC, 0x0F, 0x50, 0xBF, + 0x90, 0x05, 0x00, 0x1E, 0x48, 0x05, 0x00, 0x20, 0xE0, 0x05, 0x00, 0x1E, 0x30, 0x07, 0x00, 0x1E, + 0x38, 0x06, 0x00, 0x20, 0x40, 0x06, 0x00, 0x1E, 0x50, 0x06, 0x00, 0x1E, 0xBC, 0x06, 0x00, 0x20, + 0x6C, 0x07, 0x00, 0x1E, 0x10, 0x08, 0x00, 0x1E, 0x4C, 0x08, 0x00, 0x1C, 0xCC, 0x06, 0x00, 0x24, + 0x14, 0x06, 0x00, 0x25, 0xE0, 0x06, 0x00, 0x23, 0x08, 0x07, 0x00, 0x23, 0x0C, 0x07, 0x00, 0x24, + 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x54, 0x00, 0x00, 0x24, 0x0C, 0x0A, 0x00, 0x24, + 0xEC, 0x0F, 0x00, 0x24, 0x34, 0x00, 0x00, 0x24, 0xFC, 0x0F, 0x00, 0x20, 0xFC, 0x0F, 0x50, 0xBF, + 0x94, 0x0D, 0x00, 0x1D, 0xD4, 0x00, 0x00, 0x1F, 0x70, 0x0D, 0x00, 0x1D, 0x24, 0x00, 0x00, 0x1D, + 0xFC, 0x0F, 0x00, 0x1F, 0xFC, 0x0F, 0x00, 0x1D, 0xAC, 0x0C, 0x00, 0x1D, 0xF8, 0x0F, 0x00, 0x1F, + 0xFC, 0x0F, 0x00, 0x1D, 0xD0, 0x00, 0x00, 0x1D, 0x1C, 0x08, 0x00, 0x1E, 0x74, 0x00, 0x00, 0x25, + 0x80, 0x07, 0x00, 0x26, 0xFC, 0x0F, 0x00, 0x24, 0xFC, 0x0F, 0x00, 0x24, 0xF0, 0x0F, 0x00, 0x25, + 0xFC, 0x0F, 0x00, 0x22, 0xFC, 0x0F, 0x00, 0x23, 0x00, 0x08, 0x00, 0x25, 0xEC, 0x0F, 0x00, 0x25, + 0xFC, 0x0F, 0x00, 0x25, 0xFC, 0x0F, 0x00, 0x25, 0x1C, 0x0C, 0x00, 0x21, 0xC4, 0x06, 0x50, 0x1D, + 0x4C, 0x0C, 0x00, 0x1D, 0x74, 0x03, 0x00, 0x1F, 0xF8, 0x0F, 0x00, 0x1D, 0x60, 0x0E, 0x00, 0x1D, + 0xF8, 0x0F, 0x00, 0x1F, 0xFC, 0x0F, 0x00, 0x1D, 0x08, 0x0C, 0x00, 0x1D, 0x5C, 0x00, 0x00, 0x1F, + 0x74, 0x04, 0x00, 0x1D, 0xFC, 0x0F, 0x00, 0x1D, 0xEC, 0x0F, 0x00, 0x1B, 0xFC, 0x0F, 0x00, 0x27, + 0xC0, 0x04, 0x00, 0x28, 0xFC, 0x0F, 0x00, 0x26, 0xFC, 0x0F, 0x00, 0x26, 0x60, 0x00, 0x00, 0x27, + 0x14, 0x0C, 0x00, 0x24, 0x20, 0x00, 0x00, 0x25, 0xAC, 0x07, 0x00, 0x27, 0xFC, 0x0F, 0x00, 0x27, + 0xFC, 0x0F, 0x00, 0x27, 0x14, 0x00, 0x00, 0x27, 0x8C, 0x0F, 0x00, 0x23, 0xF4, 0x0F, 0x50, 0x3F, + 0x60, 0x0F, 0x00, 0x1D, 0xFC, 0x0F, 0x00, 0x1F, 0xFC, 0x0F, 0x00, 0x1D, 0xE0, 0x09, 0x00, 0x1D, + 0x14, 0x00, 0x00, 0x1F, 0xF4, 0x0F, 0x00, 0x1D, 0x04, 0x00, 0x00, 0x1D, 0xF8, 0x0F, 0x00, 0x1F, + 0xFC, 0x0F, 0x00, 0x1D, 0x60, 0x07, 0x00, 0x1D, 0x04, 0x04, 0x00, 0x1B, 0x70, 0x00, 0x00, 0x29, + 0x00, 0x0C, 0x00, 0x2A, 0x24, 0x00, 0x00, 0x28, 0xF4, 0x0F, 0x00, 0x28, 0xFC, 0x0F, 0x00, 0x29, + 0xFC, 0x0F, 0x00, 0x26, 0xFC, 0x0F, 0x00, 0x27, 0x00, 0x0C, 0x00, 0x29, 0xD4, 0x0F, 0x00, 0x29, + 0xFC, 0x0F, 0x00, 0x29, 0x90, 0x04, 0x00, 0x29, 0xFC, 0x0F, 0x00, 0x25, 0xFC, 0x0F, 0x50, 0x3F, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x90, 0xF0, 0x3F, 0x21, 0xB0, 0xF0, 0x3F, 0x42, 0xB0, 0xF0, 0x7F, 0x63, 0xB0, 0xF0, 0x3F, + 0x84, 0xB0, 0xF0, 0x3F, 0xA5, 0xB0, 0xF0, 0x3F, 0xC6, 0xB0, 0xF0, 0x7F, 0xE7, 0xB0, 0xF0, 0x3F, + 0x08, 0xB1, 0xF0, 0x3F, 0x29, 0xB1, 0xF0, 0x3F, 0x4A, 0xB1, 0xF0, 0x3F, 0x6B, 0xB1, 0xF0, 0x7F, + 0x8C, 0xB1, 0xF0, 0x3F, 0xAD, 0xA1, 0xF0, 0x3F, 0x00, 0x80, 0xF0, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, + 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, + 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3B, + 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, + 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0xC0, 0xF1, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x40, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x7F, 0xFC, 0x8F, 0x1F, 0x7F, 0xFC, 0x8F, 0x3F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, + 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, + 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, + 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, + 0x41, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, + 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, + 0x30, 0x30, 0x30, 0x30, 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, + 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, 0x04, 0x41, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0A, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x40, 0x00, 0x40, 0x00, 0x30, 0x00, 0x49, 0x00, 0x30, 0x00, 0xA0, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x35, 0x45, 0x1D, 0x01, 0xC6, 0x9A, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x8C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x49, 0x53, 0x54, 0x56, 0x32, 0x54, 0x41, 0x47, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xDC, 0x00, 0x00, + 0x00, 0xDC, 0x00, 0x80, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x80, 0x00, 0x0E, 0x00, 0x00, + 0x00, 0xF0, 0x00, 0x80, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x80, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0xFC, 0x0A, 0x00, 0x00, + 0x00, 0x49, 0x00, 0x30, 0x00, 0xA0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBE, 0xE7, 0x10, 0x5B, 0x69, 0x8C, 0x96, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0x07, 0xE0, 0x07, 0x0C, 0x19, 0x03, 0x00, 0x49, 0x53, 0x54, 0x56, 0x32, 0x54, 0x41, 0x47 +}; + +#endif diff --git a/drivers/input/touchscreen/ist3038c/ist30xxc_misc.c b/drivers/input/touchscreen/ist3038c/ist30xxc_misc.c new file mode 100644 index 0000000000000..d29b50d318b3b --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/ist30xxc_misc.c @@ -0,0 +1,2325 @@ +/* + * Copyright (C) 2010,Imagis Technology Co. Ltd. All Rights Reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ist30xxc.h" +#include "ist30xxc_update.h" +#include "ist30xxc_misc.h" + +#define TSP_CH_UNUSED (0) +#define TSP_CH_SCREEN (1) +#define TSP_CH_GTX (2) +#define TSP_CH_KEY (3) +#define TSP_CH_UNKNOWN (-1) + +#define TOUCH_NODE_PARSING_DEBUG (1) + +static u32 ist30xx_frame_buf[IST30XX_MAX_NODE_NUM]; +static u32 ist30xx_frame_rawbuf[IST30XX_MAX_NODE_NUM]; +static u32 ist30xx_frame_fltbuf[IST30XX_MAX_NODE_NUM]; +static u32 ist30xx_frame_cpbuf[IST30XX_MAX_NODE_NUM]; +int ist30xx_check_valid_ch(struct ist30xx_data *data, int ch_tx, int ch_rx) +{ + int i; + TKEY_INFO *tkey = &data->tkey_info; + TSP_INFO *tsp = &data->tsp_info; + + if (unlikely((ch_tx >= tsp->ch_num.tx) || (ch_rx >= tsp->ch_num.rx))) + return TSP_CH_UNKNOWN; + + if ((ch_tx >= tsp->screen.tx) || (ch_rx >= tsp->screen.rx)) { + if (tsp->gtx.num) { + for (i = 0; i < tsp->gtx.num; i++) { + if ((ch_tx == tsp->gtx.ch_num[i]) && (ch_rx < tsp->screen.rx)) + return TSP_CH_GTX; + } + } + + if (tkey->enable) { + for (i = 0; i < tkey->key_num; i++) { + if ((ch_tx == tkey->ch_num[i].tx) && + (ch_rx == tkey->ch_num[i].rx)) + return TSP_CH_KEY; + } + } + } else { + return TSP_CH_SCREEN; + } + + return TSP_CH_UNUSED; +} + +int ist30xx_parse_touch_node(struct ist30xx_data *data, u8 flag, + struct TSP_NODE_BUF *node) +{ +#if TOUCH_NODE_PARSING_DEBUG + int j; + TSP_INFO *tsp = &data->tsp_info; +#endif + int i; + u16 *raw = (u16 *)&node->raw; + u16 *base = (u16 *)&node->base; + u16 *filter = (u16 *)&node->filter; + u32 *tmp_rawbuf = ist30xx_frame_rawbuf; + u32 *tmp_fltbuf = ist30xx_frame_fltbuf; + + for (i = 0; i < node->len; i++) { + if (flag & (NODE_FLAG_RAW | NODE_FLAG_BASE)) { + *raw++ = *tmp_rawbuf & 0xFFF; + *base++ = (*tmp_rawbuf >> 16) & 0xFFF; + + tmp_rawbuf++; + } + + if (flag & NODE_FLAG_FILTER) + *filter++ = *tmp_fltbuf++ & 0xFFF; + } + +#if TOUCH_NODE_PARSING_DEBUG + tsp_info("RAW - %d * %d\n", tsp->ch_num.tx, tsp->ch_num.rx); + for (i = 0; i < tsp->ch_num.tx; i++) { + printk("\n[ TSP ] "); + for (j = 0; j < tsp->ch_num.rx; j++) + printk("%4d ", node->raw[(i * tsp->ch_num.rx) + j]); + } + printk("\n"); + tsp_info("BASE - %d * %d\n", tsp->ch_num.tx, tsp->ch_num.rx); + for (i = 0; i < tsp->ch_num.tx; i++) { + printk("\n[ TSP ] "); + for (j = 0; j < tsp->ch_num.rx; j++) + printk("%4d ", node->base[(i * tsp->ch_num.rx) + j]); + } + printk("\n"); + tsp_info("FILTER - %d * %d\n", tsp->ch_num.tx, tsp->ch_num.rx); + for (i = 0; i < tsp->ch_num.tx; i++) { + printk("\n[ TSP ] "); + for (j = 0; j < tsp->ch_num.rx; j++) + printk("%4d ", node->filter[(i * tsp->ch_num.rx) + j]); + } + printk("\n"); +#endif + + return 0; +} + +int print_touch_node(struct ist30xx_data *data, u8 flag, + struct TSP_NODE_BUF *node, char *buf) +{ + int i, j; + int count = 0; + int val = 0; + const int msg_len = 128; + char msg[msg_len]; + TSP_INFO *tsp = &data->tsp_info; + + if (tsp->dir.swap_xy) { + for (i = 0; i < tsp->ch_num.rx; i++) { + for (j = 0; j < tsp->ch_num.tx; j++) { + if (flag == NODE_FLAG_RAW) { + val = (int)node->raw[(j * tsp->ch_num.rx) + i]; + if (val < 0) + val = 0; + } else if (flag == NODE_FLAG_BASE) { + val = (int)node->base[(j * tsp->ch_num.rx) + i]; + if (val < 0) + val = 0; + } else if (flag == NODE_FLAG_FILTER) { + val = (int)node->filter[(j * tsp->ch_num.rx) + i]; + if (val < 0) + val = 0; + } else if (flag == NODE_FLAG_DIFF) { + val = (int)(node->raw[(j * tsp->ch_num.rx) + i] + - node->base[(j * tsp->ch_num.rx) + i]); + } else { + return 0; + } + + if (ist30xx_check_valid_ch(data, j, i) == TSP_CH_UNUSED) + count += snprintf(msg, msg_len, "%4d ", 0); + else + count += snprintf(msg, msg_len, "%4d ", val); + + strncat(buf, msg, msg_len); + } + + count += snprintf(msg, msg_len, "\n"); + strncat(buf, msg, msg_len); + } + } else { + for (i = 0; i < tsp->ch_num.tx; i++) { + for (j = 0; j < tsp->ch_num.rx; j++) { + if (flag == NODE_FLAG_RAW) { + val = (int)node->raw[(i * tsp->ch_num.rx) + j]; + if (val < 0) + val = 0; + } else if (flag == NODE_FLAG_BASE) { + val = (int)node->base[(i * tsp->ch_num.rx) + j]; + if (val < 0) + val = 0; + } else if (flag == NODE_FLAG_FILTER) { + val = (int)node->filter[(i * tsp->ch_num.rx) + j]; + if (val < 0) + val = 0; + } else if (flag == NODE_FLAG_DIFF) { + val = (int)(node->raw[(i * tsp->ch_num.rx) + j] + - node->base[(i * tsp->ch_num.rx) + j]); + } else { + return 0; + } + + if (ist30xx_check_valid_ch(data, i, j) == TSP_CH_UNUSED) + count += snprintf(msg, msg_len, "%4d ", 0); + else + count += snprintf(msg, msg_len, "%4d ", val); + + strncat(buf, msg, msg_len); + } + + count += snprintf(msg, msg_len, "\n"); + strncat(buf, msg, msg_len); + } + } + + return count; +} + +int parse_tsp_node(struct ist30xx_data *data, u8 flag, + struct TSP_NODE_BUF *node, s16 *buf16, int mode) +{ + int i, j; + s16 val = 0; + TSP_INFO *tsp = &data->tsp_info; + + if (unlikely((flag != NODE_FLAG_RAW) && (flag != NODE_FLAG_BASE) && + (flag != NODE_FLAG_FILTER) && (flag != NODE_FLAG_DIFF))) + return -EPERM; + + for (i = 0; i < tsp->ch_num.tx; i++) { + for (j = 0; j < tsp->ch_num.rx; j++) { + if (mode & TSP_RAW_SCREEN) { + if (ist30xx_check_valid_ch(data, i, j) != TSP_CH_SCREEN) + continue; + } else if (mode & TSP_RAW_KEY) { + if (ist30xx_check_valid_ch(data, i, j) != TSP_CH_KEY) + continue; + } + switch (flag) { + case NODE_FLAG_RAW: + val = (s16)node->raw[(i * tsp->ch_num.rx) + j]; + if (val < 0) + val = 0; + break; + case NODE_FLAG_BASE: + val = (s16)node->base[(i * tsp->ch_num.rx) + j]; + if (val < 0) + val = 0; + break; + case NODE_FLAG_FILTER: + val = (s16)node->filter[(i * tsp->ch_num.rx) + j]; + if (val < 0) + val = 0; + break; + case NODE_FLAG_DIFF: + val = (s16)(node->raw[(i * tsp->ch_num.rx) + j] + - node->base[(i * tsp->ch_num.rx) + j]); + break; + default: + val = 0; + break; + } + + if (ist30xx_check_valid_ch(data, i, j) == TSP_CH_UNUSED) + val = 0; + + *buf16++ = val; + } + } + + return 0; +} + +int ist30xx_read_touch_node(struct ist30xx_data *data, u8 flag, + struct TSP_NODE_BUF *node) +{ + int ret; + u32 addr; + u32 *tmp_rawbuf = ist30xx_frame_rawbuf; + u32 *tmp_fltbuf = ist30xx_frame_fltbuf; + + ist30xx_disable_irq(data); + + if (flag & NODE_FLAG_NO_CCP) { + ist30xx_reset(data, false); + + ret = ist30xx_write_cmd(data, IST30XX_HIB_CMD, + ((eHCOM_CP_CORRECT_EN << 16) | (IST30XX_DISABLE & 0xFFFF))); + if (unlikely(ret)) + goto read_tsp_node_end; + + ist30xx_delay(1000); + } + + ret = ist30xx_cmd_hold(data, IST30XX_ENABLE); + if (unlikely(ret)) + goto read_tsp_node_end; + + addr = IST30XX_DA_ADDR(data->raw_addr); + if (flag & (NODE_FLAG_RAW | NODE_FLAG_BASE)) { + tsp_info("Reg addr: %x, size: %d\n", addr, node->len); + ret = ist30xx_burst_read(data->client, addr, tmp_rawbuf, node->len, + true); + if (unlikely(ret)) + goto reg_access_end; + } + + addr = IST30XX_DA_ADDR(data->filter_addr); + if (flag & NODE_FLAG_FILTER) { + tsp_info("Reg addr: %x, size: %d\n", addr, node->len); + ret = ist30xx_burst_read(data->client, addr, tmp_fltbuf, node->len, + true); + if (unlikely(ret)) + goto reg_access_end; + } + +reg_access_end: + if (flag & NODE_FLAG_NO_CCP) { + ist30xx_reset(data, false); + ist30xx_start(data); + } else { + ret = ist30xx_cmd_hold(data, IST30XX_DISABLE); + if (ret) { + ist30xx_reset(data, false); + ist30xx_start(data); + } + } + +read_tsp_node_end: + ist30xx_enable_irq(data); + + return ret; +} + +int ist30xx_parse_cp_node(struct ist30xx_data *data, struct TSP_NODE_BUF *node) +{ + int i; + int len; + u16 *cp_lower = (u16 *)&node->cp_lower; + u16 *cp_upper = (u16 *)&node->cp_upper; + u32 *tmp_cpbuf = ist30xx_frame_cpbuf; + +#if (IMAGIS_TSP_IC < IMAGIS_IST3038C) + len = node->len / 2; + if (node->len % 2) + len += 1; +#else + len = node->len; +#endif + + for (i = 0; i < len; i++) { +#if (IMAGIS_TSP_IC < IMAGIS_IST3038C) + *cp_lower++ = *tmp_cpbuf & 0xFF; + *cp_upper++ = (*tmp_cpbuf >> 8) & 0xFF; + *cp_lower++ = (*tmp_cpbuf >> 16) & 0xFF; + *cp_upper++ = (*tmp_cpbuf >> 24) & 0xFF; +#else + *cp_lower++ = *tmp_cpbuf & 0x3FF; + *cp_upper++ = (*tmp_cpbuf >> 10) & 0x3FF; +#endif + tmp_cpbuf++; + } + + return 0; +} + +int parse_cp_node(struct ist30xx_data *data, u8 flag, + struct TSP_NODE_BUF *node, s16 *buf16, int mode) +{ + int i, j; + s16 val = 0; + TSP_INFO *tsp = &data->tsp_info; + + if (unlikely((flag != NODE_FLAG_CP_LOWER) && (flag != NODE_FLAG_CP_UPPER))) + return -EPERM; + + for (i = 0; i < tsp->ch_num.tx; i++) { + for (j = 0; j < tsp->ch_num.rx; j++) { + if (mode & TSP_RAW_SCREEN) { + if (ist30xx_check_valid_ch(data, i, j) != TSP_CH_SCREEN) + continue; + } else if (mode & TSP_RAW_KEY) { + if (ist30xx_check_valid_ch(data, i, j) != TSP_CH_KEY) + continue; + } + switch (flag) { + case NODE_FLAG_CP_LOWER: + val = (s16)node->cp_lower[(i * tsp->ch_num.rx) + j]; + break; + case NODE_FLAG_CP_UPPER: + val = (s16)node->cp_upper[(i * tsp->ch_num.rx) + j]; + break; + } + + if (val < 0) + val = 0; + + if (ist30xx_check_valid_ch(data, i, j) == TSP_CH_UNUSED) + val = 0; + + *buf16++ = val; + } + } + + return 0; +} + +int print_cp_node(struct ist30xx_data *data, u8 flag, struct TSP_NODE_BUF *node, + char *buf) +{ + int i, j; + int count = 0; + u32 val = 0; + const int msg_len = 128; + char msg[msg_len]; + TSP_INFO *tsp = &data->tsp_info; + + if (tsp->dir.swap_xy) { + if (flag & NODE_FLAG_CP_LOWER) { + for (i = 0; i < tsp->ch_num.rx; i++) { + for (j = 0; j < tsp->ch_num.tx; j++) { + val = node->cp_lower[(j * tsp->ch_num.rx) + i]; + if (val < 0) + val = 0; + + if (ist30xx_check_valid_ch(data, j, i) == TSP_CH_UNUSED) + count += snprintf(msg, msg_len, "%4d ", 0); + else + count += snprintf(msg, msg_len, "%4d ", val); + + strncat(buf, msg, msg_len); + } + + count += snprintf(msg, msg_len, "\n"); + strncat(buf, msg, msg_len); + } + } else if (flag & NODE_FLAG_CP_UPPER) { + for (i = 0; i < tsp->ch_num.rx; i++) { + for (j = 0; j < tsp->ch_num.tx; j++) { + val = node->cp_upper[(j * tsp->ch_num.rx) + i]; + if (val < 0) + val = 0; + + if (ist30xx_check_valid_ch(data, j, i) == TSP_CH_UNUSED) + count += snprintf(msg, msg_len, "%4d ", 0); + else + count += snprintf(msg, msg_len, "%4d ", val); + + strncat(buf, msg, msg_len); + } + + count += snprintf(msg, msg_len, "\n"); + strncat(buf, msg, msg_len); + } + } + } else { + if (flag & NODE_FLAG_CP_LOWER) { + for (i = 0; i < tsp->ch_num.tx; i++) { + for (j = 0; j < tsp->ch_num.rx; j++) { + val = node->cp_lower[(i * tsp->ch_num.rx) + j]; + if (val < 0) + val = 0; + + if (ist30xx_check_valid_ch(data, i, j) == TSP_CH_UNUSED) + count += snprintf(msg, msg_len, "%4d ", 0); + else + count += snprintf(msg, msg_len, "%4d ", val); + + strncat(buf, msg, msg_len); + } + + count += snprintf(msg, msg_len, "\n"); + strncat(buf, msg, msg_len); + } + } else if (flag & NODE_FLAG_CP_UPPER) { + for (i = 0; i < tsp->ch_num.tx; i++) { + for (j = 0; j < tsp->ch_num.rx; j++) { + val = node->cp_upper[(i * tsp->ch_num.rx) + j]; + if (val < 0) + val = 0; + + if (ist30xx_check_valid_ch(data, i, j) == TSP_CH_UNUSED) + count += snprintf(msg, msg_len, "%4d ", 0); + else + count += snprintf(msg, msg_len, "%4d ", val); + + strncat(buf, msg, msg_len); + } + + count += snprintf(msg, msg_len, "\n"); + strncat(buf, msg, msg_len); + } + } + } + + return count; +} + +#define IST30XX_CP_ADDRESS 0x30004000 +int ist30xx_read_cp_node(struct ist30xx_data *data, struct TSP_NODE_BUF *node) +{ + int ret = 0; + u32 addr; + u32 len; + u32 *tmp_cpbuf = ist30xx_frame_cpbuf; + + ist30xx_disable_irq(data); + + ret = ist30xx_cmd_hold(data, IST30XX_ENABLE); + if (unlikely(ret)) + goto read_cp_node_end; + + addr = IST30XX_DA_ADDR(IST30XX_CP_ADDRESS); +#if (IMAGIS_TSP_IC < IMAGIS_IST3038C) + len = node->len / 2; + if (node->len % 2) + len += 1; +#else + len = node->len; +#endif + ret = ist30xx_burst_read(data->client, addr, tmp_cpbuf, node->len, true); + if (unlikely(ret)) + goto reg_access_end; + +reg_access_end: + ret = ist30xx_cmd_hold(data, IST30XX_DISABLE); + if (ret) { + ist30xx_reset(data, false); + ist30xx_start(data); + } + +read_cp_node_end: + ist30xx_enable_irq(data); + + return ret; + +} + +/* sysfs: /sys/class/touch/node/cp */ +ssize_t ist30xx_cp_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int ret = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + tsp_info("Read CP\n"); + mutex_lock(&data->lock); + ret = ist30xx_read_cp_node(data, &tsp->node); + if (unlikely(ret)) { + mutex_unlock(&data->lock); + tsp_err("cmd 1frame cp update fail\n"); + return sprintf(buf, "FAIL\n"); + } + mutex_unlock(&data->lock); + + ist30xx_parse_cp_node(data, &tsp->node); + + return sprintf(buf, "OK\n"); +} + +/* sysfs: /sys/class/touch/node/cp_lower */ +ssize_t ist30xx_cp_lower_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int count = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + buf[0] = '\0'; + count = sprintf(buf, "dump ist30xx cp lower(%d)\n", tsp->node.len); + + count += print_cp_node(data, NODE_FLAG_CP_LOWER, &tsp->node, buf); + + return count; +} + +/* sysfs: /sys/class/touch/node/cp_upper */ +ssize_t ist30xx_cp_upper_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int count = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + buf[0] = '\0'; + count = sprintf(buf, "dump ist30xx cp upper(%d)\n", tsp->node.len); + + count += print_cp_node(data, NODE_FLAG_CP_UPPER, &tsp->node, buf); + + return count; +} + +/* sysfs: /sys/class/touch/node/rawbase */ +ssize_t ist30xx_frame_rawbase(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int i; + int ret = 0; + int count = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + u8 flag = NODE_FLAG_RAW | NODE_FLAG_BASE; + u32 *tmp_rawbuf = ist30xx_frame_rawbuf; + const int msg_len = 128; + char msg[msg_len]; + char header[128]; + char *buf8; + mm_segment_t old_fs = { 0 }; + struct file *fp = NULL; + TKEY_INFO *tkey = &data->tkey_info; + TSP_INFO *tsp = &data->tsp_info; + + old_fs = get_fs(); + set_fs(get_ds()); + + if (!strcmp(data->rec_file_name, "")) + snprintf(data->rec_file_name, 128, "/sdcard/%s", IST30XX_REC_FILENAME); + + fp = filp_open(data->rec_file_name, O_WRONLY, 0); + if (IS_ERR(fp)) + ret = PTR_ERR(fp); + + fp = filp_open(data->rec_file_name, O_CREAT|O_WRONLY|O_APPEND, 0); + if (IS_ERR(fp)) { + tsp_err("file %s open error:%d\n", data->rec_file_name, PTR_ERR(fp)); + goto err_file_open; + } + + if (ret) { + count = snprintf(header, 128, "%d %d %d %d %d %d %d %d %d %d %d %d %d " + "%d %d %d %d %d\n", 2, tsp->ch_num.rx, tsp->ch_num.tx, + tsp->ch_num.rx, tsp->ch_num.tx, tsp->screen.rx, tsp->screen.tx, + tkey->key_num, tkey->ch_num[0].rx, tkey->ch_num[0].tx, + tkey->ch_num[1].tx, tkey->ch_num[1].rx, tkey->ch_num[2].tx, + tkey->ch_num[2].rx, tkey->ch_num[3].tx, tkey->ch_num[3].rx, + tkey->ch_num[4].tx, tkey->ch_num[4].rx); + + fp->f_op->write(fp, header, count, &fp->f_pos); + fput(fp); + } + + mutex_lock(&data->lock); + ret = ist30xx_read_touch_node(data, flag, &tsp->node); + if (unlikely(ret)) { + mutex_unlock(&data->lock); + tsp_err("fail to read frame\n"); + goto err_read_node; + } + mutex_unlock(&data->lock); + + buf8 = kzalloc(IST30XX_MAX_NODE_NUM * 20, GFP_KERNEL); + count = 0; + for (i = 0; i < IST30XX_MAX_NODE_NUM; i++) { + count += snprintf(msg, msg_len, "%08x ", *tmp_rawbuf); + strncat(buf8, msg, msg_len); + tmp_rawbuf++; + } + + for (i = 0; i < IST30XX_MAX_NODE_NUM; i++) { + count += snprintf(msg, msg_len, "%08x ", 0); + strncat(buf8, msg, msg_len); + } + + count += snprintf(msg, msg_len, "\n"); + strncat(buf8, msg, msg_len); + + fp->f_op->write(fp, buf8, count, &fp->f_pos); + fput(fp); + + kfree(buf8); + +err_read_node: + filp_close(fp, NULL); +err_file_open: + set_fs(old_fs); + + return 0; +} + +/* sysfs: /sys/class/touch/node/refresh */ +ssize_t ist30xx_frame_refresh(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int ret = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + u8 flag = NODE_FLAG_RAW | NODE_FLAG_BASE | NODE_FLAG_FILTER; + + tsp_info("refresh\n"); + mutex_lock(&data->lock); + ret = ist30xx_read_touch_node(data, flag, &tsp->node); + if (unlikely(ret)) { + mutex_unlock(&data->lock); + tsp_err("cmd 1frame raw update fail\n"); + return sprintf(buf, "FAIL\n"); + } + mutex_unlock(&data->lock); + + ist30xx_parse_touch_node(data, flag, &tsp->node); + + return sprintf(buf, "OK\n"); +} + + +/* sysfs: /sys/class/touch/node/read_nocp */ +ssize_t ist30xx_frame_nocp(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int ret = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + u8 flag = NODE_FLAG_RAW | NODE_FLAG_BASE | NODE_FLAG_FILTER | + NODE_FLAG_NO_CCP; + + mutex_lock(&data->lock); + ret = ist30xx_read_touch_node(data, flag, &tsp->node); + if (unlikely(ret)) { + mutex_unlock(&data->lock); + tsp_err("cmd 1frame raw update fail\n"); + return sprintf(buf, "FAIL\n"); + } + mutex_unlock(&data->lock); + + ist30xx_parse_touch_node(data, flag, &tsp->node); + + return sprintf(buf, "OK\n"); +} + + +/* sysfs: /sys/class/touch/node/base */ +ssize_t ist30xx_base_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int count = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + buf[0] = '\0'; + count = sprintf(buf, "dump ist30xx baseline(%d)\n", tsp->node.len); + + count += print_touch_node(data, NODE_FLAG_BASE, &tsp->node, buf); + + return count; +} + + +/* sysfs: /sys/class/touch/node/raw */ +ssize_t ist30xx_raw_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int count = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + buf[0] = '\0'; + count = sprintf(buf, "dump ist30xx raw(%d)\n", tsp->node.len); + + count += print_touch_node(data, NODE_FLAG_RAW, &tsp->node, buf); + + return count; +} + + +/* sysfs: /sys/class/touch/node/diff */ +ssize_t ist30xx_diff_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int count = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + buf[0] = '\0'; + count = sprintf(buf, "dump ist30xx difference (%d)\n", tsp->node.len); + + count += print_touch_node(data, NODE_FLAG_DIFF, &tsp->node, buf); + + return count; +} + + +/* sysfs: /sys/class/touch/node/filter */ +ssize_t ist30xx_filter_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int count = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + + buf[0] = '\0'; + count = sprintf(buf, "dump ist30xx filter (%d)\n", tsp->node.len); + + count += print_touch_node(data, NODE_FLAG_FILTER, &tsp->node, buf); + + return count; +} + +/* sysfs: /sys/class/touch/sys/debug_mode */ +ssize_t ist30xx_debug_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + int enable; + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%d", &enable); + + if (unlikely((enable != 0) && (enable != 1))) { + tsp_err("input data error(%d)\n", enable); + return size; + } + + data->debug_mode = enable; + + if (data->status.power) { + ret = ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SLEEP_MODE_EN << 16) | (data->debug_mode & 0xFFFF)); + } + + tsp_info("debug mode %s\n", enable ? "start" : "stop"); + + return size; +} + +/* sysfs: /sys/class/touch/sys/jig_mode */ +ssize_t ist30xx_jig_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + int enable; + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%d", &enable); + + if (unlikely((enable != 0) && (enable != 1))) { + tsp_err("input data error(%d)\n", enable); + return size; + } + + data->jig_mode = enable; + tsp_info("set jig mode: %s\n", enable ? "start" : "stop"); + + mutex_lock(&data->lock); + ist30xx_reset(data, false); + ist30xx_start(data); + mutex_unlock(&data->lock); + + return size; +} + +extern int calib_ms_delay; +/* sysfs: /sys/class/touch/sys/clb_time */ +ssize_t ist30xx_calib_time_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + int ms_delay; + + sscanf(buf, "%d", &ms_delay); + + if (ms_delay > 10 && ms_delay < 1000) + calib_ms_delay = ms_delay; + + tsp_info("Calibration wait time %dsec\n", calib_ms_delay / 10); + + return size; +} + +/* sysfs: /sys/class/touch/sys/clb */ +ssize_t ist30xx_calib_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + mutex_lock(&data->lock); + ist30xx_disable_irq(data); + + ist30xx_reset(data, false); + ist30xx_calibrate(data, 1); + + mutex_unlock(&data->lock); + ist30xx_start(data); + + return 0; +} + +/* sysfs: /sys/class/touch/sys/clb_result */ +ssize_t ist30xx_calib_result_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + int count = 0; + u32 value; + struct ist30xx_data *data = dev_get_drvdata(dev); + + ret = ist30xx_read_cmd(data, eHCOM_GET_CAL_RESULT, &value); + if (unlikely(ret)) { + mutex_lock(&data->lock); + ist30xx_reset(data, false); + ist30xx_start(data); + mutex_unlock(&data->lock); + tsp_warn("Error Read Calibration Result\n"); + count = sprintf(buf, "Error Read Calibration Result\n"); + goto calib_show_end; + } + + count = sprintf(buf, + "Calibration Status : %d, Max raw gap : %d - (raw: %08x)\n", + CALIB_TO_STATUS(value), CALIB_TO_GAP(value), value); + +calib_show_end: + + return count; +} + +/* sysfs: /sys/class/touch/sys/cal_ref */ +ssize_t ist30xx_cal_ref_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + mutex_lock(&data->lock); + ist30xx_disable_irq(data); + + ist30xx_reset(data, false); + ist30xx_cal_reference(data); + + mutex_unlock(&data->lock); + ist30xx_start(data); + + data->cal_ref_count = 0; + + return 0; +} + +/* sysfs: /sys/class/touch/sys/power_on */ +ssize_t ist30xx_power_on_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + tsp_info("Power enable: %d\n", true); + + mutex_lock(&data->lock); + ist30xx_internal_resume(data); + ist30xx_enable_irq(data); + mutex_unlock(&data->lock); + + ist30xx_start(data); + + return 0; +} + +/* sysfs: /sys/class/touch/sys/power_off */ +ssize_t ist30xx_power_off_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + tsp_info("Power enable: %d\n", false); + + mutex_lock(&data->lock); + ist30xx_disable_irq(data); + ist30xx_internal_suspend(data); + mutex_unlock(&data->lock); + + return 0; +} + +/* sysfs: /sys/class/touch/sys/errcnt */ +ssize_t ist30xx_errcnt_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int err_cnt; + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%d", &err_cnt); + + if (unlikely(err_cnt < 0)) + return size; + + tsp_info("Request reset error count: %d\n", err_cnt); + + data->max_irq_err_cnt = err_cnt; + + return size; +} + +/* sysfs: /sys/class/touch/sys/scancnt */ +ssize_t ist30xx_scancnt_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int retry; + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%d", &retry); + + if (unlikely(retry < 0)) + return size; + + tsp_info("Timer scan count retry: %d\n", retry); + + data->max_scan_retry = retry; + + return size; +} + +/* sysfs: /sys/class/touch/sys/timerms */ +ssize_t ist30xx_timerms_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ms; + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%d", &ms); + + if (unlikely((ms < 0) || (ms > 10000))) + return size; + + tsp_info("Timer period ms: %dms\n", ms); + + data->timer_period_ms = ms; + + return size; +} + +extern int ist30xx_log_level; +/* sysfs: /sys/class/touch/sys/printk */ +ssize_t ist30xx_printk_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int level; + + sscanf(buf, "%d", &level); + + if (unlikely((level < DEV_ERR) || (level > DEV_VERB))) + return size; + + tsp_info("prink log level: %d\n", level); + + ist30xx_log_level = level; + + return size; +} + +ssize_t ist30xx_printk_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "prink log level: %d\n", ist30xx_log_level); +} + +/* sysfs: /sys/class/touch/sys/printk5 */ +ssize_t ist30xx_printk5_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + tsp_info("prink log level:%d\n", DEV_DEBUG); + + ist30xx_log_level = DEV_DEBUG; + + return 0; +} + +/* sysfs: /sys/class/touch/sys/printk6 */ +ssize_t ist30xx_printk6_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + tsp_info("prink log level:%d\n", DEV_VERB); + + ist30xx_log_level = DEV_VERB; + + return 0; +} + +#ifdef IST30XX_GESTURE +/* sysfs: /sys/class/touch/sys/gesture */ +ssize_t ist30xx_gesture_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int gesture; + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%d", &gesture); + + tsp_info("gesture enable : %s\n", (gesture == 0) ? "disable" : "enable"); + + data->gesture = (gesture == 0) ? false : true; + if (data->gesture) + device_init_wakeup(&data->client->dev, 1); + else + device_init_wakeup(&data->client->dev, 0); + + return size; +} +#endif + +/* sysfs: /sys/class/touch/sys/report_rate */ +ssize_t ist30xx_report_rate_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + int rate; + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%d", &rate); + + if (unlikely(rate > 0xFFFF)) + return size; + + data->report_rate = rate; + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + ((eHCOM_SET_TIME_ACTIVE << 16) | (data->report_rate & 0xFFFF))); + tsp_info(" active rate : %dus\n", data->report_rate); + + return size; +} + +/* sysfs: /sys/class/touch/sys/idle_rate */ +ssize_t ist30xx_idle_scan_rate_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + int rate; + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%d", &rate); + + if (unlikely(rate > 0xFFFF)) + return size; + + data->idle_rate = rate; + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + ((eHCOM_SET_TIME_IDLE << 16) | (data->idle_rate & 0xFFFF))); + tsp_info(" idle rate : %dus\n", data->idle_rate); + + return size; +} + +extern void ist30xx_set_ta_mode(bool charging); +/* sysfs: /sys/class/touch/sys/mode_ta */ +ssize_t ist30xx_ta_mode_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int mode; + + sscanf(buf, "%d", &mode); + + if (unlikely((mode != 0) && (mode != 1))) + return size; + + ist30xx_set_ta_mode(mode); + + return size; +} + +extern void ist30xx_set_call_mode(int mode); +/* sysfs: /sys/class/touch/sys/mode_call */ +ssize_t ist30xx_call_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + int mode; + + sscanf(buf, "%d", &mode); + + if (unlikely((mode != 0) && (mode != 1))) + return size; + + ist30xx_set_call_mode(mode); + + return size; +} + +extern void ist30xx_set_cover_mode(int mode); +/* sysfs: /sys/class/touch/sys/mode_cover */ +ssize_t ist30xx_cover_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + int mode; + + sscanf(buf, "%d", &mode); + + if (unlikely((mode != 0) && (mode != 1))) + return size; + + ist30xx_set_cover_mode(mode); + + return size; +} + +/* sysfs: /sys/class/touch/sys/ic_inform */ +ssize_t ist30xx_read_ic_inform(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + ist30xx_print_info(data); + + return 0; +} + +#define TUNES_CMD_WRITE (1) +#define TUNES_CMD_READ (2) +#define TUNES_CMD_REG_ENTER (3) +#define TUNES_CMD_REG_EXIT (4) +#define TUNES_CMD_UPDATE_PARAM (5) +#define TUNES_CMD_UPDATE_FW (6) + +#define DIRECT_ADDR(n) (IST30XX_DA_ADDR(n)) +#define DIRECT_CMD_WRITE ('w') +#define DIRECT_CMD_READ ('r') +#define DIRECT_BUF_COUNT (4) + +#pragma pack(1) +typedef struct { + u8 cmd; + u32 addr; + u16 len; +} TUNES_INFO; +#pragma pack() +#pragma pack(1) +typedef struct { + char cmd; + u32 addr; + u32 val; + u32 size; +} DIRECT_INFO; +#pragma pack() + +static TUNES_INFO ist30xx_tunes; +static DIRECT_INFO ist30xx_direct; +static bool tunes_cmd_done; +static bool ist30xx_reg_mode; + +/* sysfs: /sys/class/touch/sys/direct */ +ssize_t ist30xx_direct_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = -EPERM; + struct ist30xx_data *data = dev_get_drvdata(dev); + DIRECT_INFO *direct = (DIRECT_INFO *)&ist30xx_direct; + + sscanf(buf, "%c %x %x %d", &direct->cmd, &direct->addr, &direct->val, + &direct->size); + + if (direct->size == 0) + direct->size = DIRECT_BUF_COUNT; + + tsp_debug("Direct cmd: %c, addr: %x, val: %x\n", + direct->cmd, direct->addr, direct->val); + + if (unlikely((direct->cmd != DIRECT_CMD_WRITE) && + (direct->cmd != DIRECT_CMD_READ))) { + tsp_warn("Direct cmd is not correct!\n"); + return size; + } + + if (ist30xx_intr_wait(data, 30) < 0) + return size; + + data->status.event_mode = false; + if (direct->cmd == DIRECT_CMD_WRITE) { + ist30xx_cmd_hold(data, IST30XX_ENABLE); + ist30xx_write_cmd(data, DIRECT_ADDR(direct->addr), direct->val); + ist30xx_read_reg(data->client, DIRECT_ADDR(direct->addr), &direct->val); + ret = ist30xx_cmd_hold(data, IST30XX_DISABLE); + if (ret) + tsp_debug("Direct write fail\n"); + else + tsp_debug("Direct write addr: %x, val: %x\n", direct->addr, + direct->val); + + } + data->status.event_mode = true; + + return size; +} + +ssize_t ist30xx_direct_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int i, count = 0; + int ret = 0; + int len; + u32 addr; + u32 *buf32; + const int msg_len = 256; + char msg[msg_len]; + struct ist30xx_data *data = dev_get_drvdata(dev); + DIRECT_INFO *direct = (DIRECT_INFO *)&ist30xx_direct; + int max_len = direct->size; + + if (unlikely(direct->cmd != DIRECT_CMD_READ)) + return sprintf(buf, "ex) echo r addr len size(display) > direct\n"); + + len = direct->val; + addr = DIRECT_ADDR(direct->addr); + + if (ist30xx_intr_wait(data, 30) < 0) + return 0; + + if (!data->status.power) + return 0; + + data->status.event_mode = false; + ist30xx_cmd_hold(data, IST30XX_ENABLE); + + buf32 = kzalloc(max_len * sizeof(u32), GFP_KERNEL); + while (len > 0) { + if (len < max_len) + max_len = len; + + memset(buf32, 0, sizeof(*buf32)); + ret = ist30xx_burst_read(data->client, addr, buf32, max_len, true); + if (unlikely(ret)) { + count = sprintf(buf, "I2C Burst read fail\n"); + break; + } + addr += (max_len * IST30XX_DATA_LEN); + + for (i = 0; i < max_len; i++) { + count += snprintf(msg, msg_len, "0x%08x ", buf32[i]); + strncat(buf, msg, msg_len); + } + count += snprintf(msg, msg_len, "\n"); + strncat(buf, msg, msg_len); + + len -= max_len; + } + kfree(buf32); + + ret = ist30xx_cmd_hold(data, IST30XX_DISABLE); + if (ret) + tsp_err("Hold disable fail\n"); + data->status.event_mode = true; + + return count; +} + +/* sysfs: /sys/class/touch/tunes/node_info */ +ssize_t tunes_node_info_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int size; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + TKEY_INFO *tkey = &data->tkey_info; + + size = sprintf(buf, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d " + "%d %d %d %d %d %d %d %d %d", + data->chip_id, tsp->dir.swap_xy, tsp->ch_num.tx, + tsp->ch_num.rx, tsp->screen.tx, tsp->screen.rx, + tsp->gtx.num, tsp->gtx.ch_num[0], tsp->gtx.ch_num[1], + tsp->gtx.ch_num[2], tsp->gtx.ch_num[3], tsp->baseline, + tkey->enable, tkey->baseline, tkey->key_num, tkey->ch_num[0].tx, + tkey->ch_num[0].rx, tkey->ch_num[1].tx, tkey->ch_num[1].rx, + tkey->ch_num[2].tx, tkey->ch_num[2].rx, tkey->ch_num[3].tx, + tkey->ch_num[3].rx, 255, 255, data->raw_addr, data->filter_addr); + + return size; +} + +/* sysfs: /sys/class/touch/tunes/regcmd */ +ssize_t tunes_regcmd_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = -1; + u32 *buf32; + struct ist30xx_data *data = dev_get_drvdata(dev); + + memcpy(&ist30xx_tunes, buf, sizeof(ist30xx_tunes)); + buf += sizeof(ist30xx_tunes); + buf32 = (u32 *)buf; + + tunes_cmd_done = false; + + switch (ist30xx_tunes.cmd) { + case TUNES_CMD_WRITE: + break; + case TUNES_CMD_READ: + break; + case TUNES_CMD_REG_ENTER: + ist30xx_disable_irq(data); + /* enter reg access mode */ + ret = ist30xx_cmd_hold(data, IST30XX_ENABLE); + if (unlikely(ret)) + goto regcmd_fail; + + ist30xx_reg_mode = true; + break; + case TUNES_CMD_REG_EXIT: + /* exit reg access mode */ + ret = ist30xx_cmd_hold(data, IST30XX_DISABLE); + if (unlikely(ret)) { + ist30xx_reset(data, false); + ist30xx_start(data); + goto regcmd_fail; + } + + ist30xx_reg_mode = false; + ist30xx_enable_irq(data); + break; + default: + ist30xx_enable_irq(data); + return size; + } + tunes_cmd_done = true; + + return size; + +regcmd_fail: + tsp_err("Tunes regcmd i2c_fail, ret=%d\n", ret); + return size; +} + +ssize_t tunes_regcmd_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int size; + + size = sprintf(buf, "cmd: 0x%02x, addr: 0x%08x, len: 0x%04x\n", + ist30xx_tunes.cmd, ist30xx_tunes.addr, ist30xx_tunes.len); + + return size; +} + +#define MAX_WRITE_LEN (1) +/* sysfs: /sys/class/touch/tunes/reg */ +ssize_t tunes_reg_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + u32 *buf32 = (u32 *)buf; + int waddr, wcnt = 0, len = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (unlikely(ist30xx_tunes.cmd != TUNES_CMD_WRITE)) { + tsp_err("error, IST30XX_REG_CMD is not correct!\n"); + return size; + } + + if (unlikely(!ist30xx_reg_mode)) { + tsp_err("error, IST30XX_REG_CMD is not ready!\n"); + return size; + } + + if (unlikely(!tunes_cmd_done)) { + tsp_err("error, IST30XX_REG_CMD is not ready!\n"); + return size; + } + + waddr = ist30xx_tunes.addr; + if (ist30xx_tunes.len >= MAX_WRITE_LEN) + len = MAX_WRITE_LEN; + else + len = ist30xx_tunes.len; + + while (wcnt < ist30xx_tunes.len) { + ret = ist30xx_write_buf(data->client, waddr, buf32, len); + if (unlikely(ret)) { + tsp_err("Tunes regstore i2c_fail, ret=%d\n", ret); + return size; + } + + wcnt += len; + + if ((ist30xx_tunes.len - wcnt) < MAX_WRITE_LEN) + len = ist30xx_tunes.len - wcnt; + + buf32 += MAX_WRITE_LEN; + waddr += MAX_WRITE_LEN * IST30XX_DATA_LEN; + } + + tunes_cmd_done = false; + + return size; +} + +ssize_t tunes_reg_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int ret; + int size = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (unlikely(ist30xx_tunes.cmd != TUNES_CMD_READ)) { + tsp_err("error, IST30XX_REG_CMD is not correct!\n"); + return 0; + } + + if (unlikely(!tunes_cmd_done)) { + tsp_err("error, IST30XX_REG_CMD is not ready!\n"); + return 0; + } + + ret = ist30xx_burst_read(data->client, ist30xx_tunes.addr, (u32 *)buf, + ist30xx_tunes.len, false); + if (unlikely(ret)) { + tsp_err("Tunes regshow i2c_fail, ret=%d\n", ret); + return size; + } + + size = ist30xx_tunes.len * IST30XX_DATA_LEN; + + tunes_cmd_done = false; + + return size; +} + +/* sysfs: /sys/class/touch/tunes/adb */ +ssize_t tunes_adb_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + char *tmp, *ptr; + char token[9]; + u32 cmd, addr, len, val; + int write_len; + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%x %x %x", &cmd, &addr, &len); + + switch (cmd) { + case TUNES_CMD_WRITE: /* write cmd */ + write_len = 0; + ptr = (char *)(buf + 15); + + while (write_len < len) { + memcpy(token, ptr, 8); + token[8] = 0; + val = simple_strtoul(token, &tmp, 16); + ret = ist30xx_write_buf(data->client, addr, &val, 1); + if (unlikely(ret)) { + tsp_err("Tunes regstore i2c_fail, ret=%d\n", ret); + return size; + } + + ptr += 8; + write_len++; + addr += 4; + } + break; + + case TUNES_CMD_READ: /* read cmd */ + ist30xx_tunes.cmd = cmd; + ist30xx_tunes.addr = addr; + ist30xx_tunes.len = len; + break; + + case TUNES_CMD_REG_ENTER: /* enter */ + ist30xx_disable_irq(data); + + ret = ist30xx_cmd_hold(data, IST30XX_ENABLE); + if (unlikely(ret < 0)) + goto cmd_fail; + + ist30xx_reg_mode = true; + break; + + case TUNES_CMD_REG_EXIT: /* exit */ + if (ist30xx_reg_mode == true) { + ret = ist30xx_cmd_hold(data, IST30XX_DISABLE); + if (unlikely(ret < 0)) { + ist30xx_reset(data, false); + ist30xx_start(data); + goto cmd_fail; + } + + ist30xx_reg_mode = false; + ist30xx_enable_irq(data); + } + break; + + default: + break; + } + + return size; + +cmd_fail: + tsp_err("Tunes adb i2c_fail\n"); + return size; +} + +ssize_t tunes_adb_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int ret; + int i, len, size = 0; + char reg_val[10]; + struct ist30xx_data *data = dev_get_drvdata(dev); + + tsp_info("tunes_adb_show,%08x,%d\n", ist30xx_tunes.addr, ist30xx_tunes.len); + + ret = ist30xx_burst_read(data->client, ist30xx_tunes.addr, + ist30xx_frame_buf, ist30xx_tunes.len, false); + if (unlikely(ret)) { + tsp_err("Tunes adbshow i2c_fail, ret=%d\n", ret); + return size; + } + + size = 0; + buf[0] = 0; + len = sprintf(reg_val, "%08x", ist30xx_tunes.addr); + strcat(buf, reg_val); + size += len; + for (i = 0; i < ist30xx_tunes.len; i++) { + len = sprintf(reg_val, "%08x", ist30xx_frame_buf[i]); + strcat(buf, reg_val); + size += len; + } + + return size; +} + +/* sysfs: /sys/class/touch/sys/rec_mode */ +ssize_t ist30xx_rec_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + int count; + int mode; + int start_ch_rx; + int stop_ch_rx; + int start_ch_tx; + int stop_ch_tx; + int delay; + char header[128]; + mm_segment_t old_fs = { 0 }; + struct file *fp = NULL; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + TKEY_INFO *tkey = &data->tkey_info; + + start_ch_rx = 0; + stop_ch_rx = tsp->ch_num.rx - 1; + start_ch_tx = 0; + stop_ch_tx = tsp->ch_num.tx - 1; + delay = 0; + data->rec_file_name = "/data/ist30xxc.res"; + + sscanf(buf, "%d %d %d %d %d %d", &mode, &delay, &start_ch_rx, &stop_ch_rx, + &start_ch_tx, &stop_ch_tx); + + if ((start_ch_rx > stop_ch_rx) || (start_ch_tx > stop_ch_tx) || + (stop_ch_rx >= tsp->ch_num.rx) || (stop_ch_tx >= tsp->ch_num.tx)) { + tsp_err("input data error(%d, %d, %d, %d)\n", start_ch_rx, stop_ch_rx, + start_ch_tx, stop_ch_tx); + return size; + } + + old_fs = get_fs(); + set_fs(get_ds()); + + if (mode) { + if (!strcmp(data->rec_file_name, "")) + snprintf(data->rec_file_name, 128, "/data/%s", + IST30XX_REC_FILENAME); + + fp = filp_open(data->rec_file_name, O_CREAT|O_WRONLY|O_TRUNC, 0); + if (IS_ERR(fp)) { + tsp_err("file %s open error:%d\n", data->rec_file_name, + PTR_ERR(fp)); + goto err_file_open; + } + + count = snprintf(header, 128, "%d %d %d %d %d %d %d %d %d %d %d %d %d " + "%d %d %d %d %d\n", 2, tsp->ch_num.rx, tsp->ch_num.tx, + tsp->ch_num.rx, tsp->ch_num.tx, tsp->screen.rx, tsp->screen.tx, + tkey->key_num, tkey->ch_num[0].rx, tkey->ch_num[0].tx, + tkey->ch_num[1].tx, tkey->ch_num[1].rx, tkey->ch_num[2].tx, + tkey->ch_num[2].rx, tkey->ch_num[3].tx, tkey->ch_num[3].rx, + 255, 255); + + fp->f_op->write(fp, header, count, &fp->f_pos); + fput(fp); + + filp_close(fp, NULL); + } + + data->rec_mode = mode; + tsp_info("rec mode: %s\n", mode ? "start" : "stop"); + if (mode) { + data->rec_start_ch.rx = start_ch_rx; + data->rec_stop_ch.rx = stop_ch_rx; + data->rec_start_ch.tx = start_ch_tx; + data->rec_stop_ch.tx = stop_ch_tx; + tsp_info("rec channel: %d, %d, %d, %d\n", data->rec_start_ch.rx, + data->rec_stop_ch.rx, data->rec_start_ch.tx, + data->rec_stop_ch.tx); + data->rec_delay = delay; + tsp_info("rec delay: %dms\n", data->rec_delay); + } + + if (data->status.power) { + if (data->debug_mode || data->jig_mode || data->rec_mode || + data->debugging_mode) { + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SLEEP_MODE_EN << 16) | (IST30XX_DISABLE & 0xFFFF)); + } else { + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SLEEP_MODE_EN << 16) | (IST30XX_ENABLE & 0xFFFF)); + } + + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SET_REC_MODE << 16) | (data->rec_mode & 0xFFFF)); + + if (data->rec_mode) { + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SET_REC_MODE << 16) | (IST30XX_START_SCAN & 0xFFFF)); + } + } + +err_file_open: + set_fs(old_fs); + + return size; +} + +ssize_t ist30xx_rec_mode_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int count; + int start_ch_rx; + int stop_ch_rx; + int start_ch_tx; + int stop_ch_tx; + int delay; + char header[128]; + mm_segment_t old_fs = { 0 }; + struct file *fp = NULL; + struct ist30xx_data *data = dev_get_drvdata(dev); + TSP_INFO *tsp = &data->tsp_info; + TKEY_INFO *tkey = &data->tkey_info; + + start_ch_rx = 0; + stop_ch_rx = tsp->ch_num.rx - 1; + start_ch_tx = 0; + stop_ch_tx = tsp->ch_num.tx - 1; + delay = 20; + + if (data->rec_mode) { + data->rec_mode = 0; + } else { + old_fs = get_fs(); + set_fs(get_ds()); + + if (!strcmp(data->rec_file_name, "")) + snprintf(data->rec_file_name, 128, "/data/%s", + IST30XX_REC_FILENAME); + + fp = filp_open(data->rec_file_name, O_CREAT|O_WRONLY|O_TRUNC, 0); + if (IS_ERR(fp)) { + tsp_err("file %s open error:%d\n", data->rec_file_name, + PTR_ERR(fp)); + goto err_file_open; + } + + count = snprintf(header, 128, "%d %d %d %d %d %d %d %d %d %d %d %d %d " + "%d %d %d %d %d\n", 2, tsp->ch_num.rx, tsp->ch_num.tx, + tsp->ch_num.rx, tsp->ch_num.tx, tsp->screen.rx, tsp->screen.tx, + tkey->key_num, tkey->ch_num[0].rx, tkey->ch_num[0].tx, + tkey->ch_num[1].tx, tkey->ch_num[1].rx, tkey->ch_num[2].tx, + tkey->ch_num[2].rx, tkey->ch_num[3].tx, tkey->ch_num[3].rx, + 255, 255); + + fp->f_op->write(fp, header, count, &fp->f_pos); + fput(fp); + + filp_close(fp, NULL); + + data->rec_mode = 2; + } + + tsp_info("rec mode: %s\n", data->rec_mode ? "start" : "stop"); + if (data->rec_mode) { + data->rec_start_ch.rx = start_ch_rx; + data->rec_stop_ch.rx = stop_ch_rx; + data->rec_start_ch.tx = start_ch_tx; + data->rec_stop_ch.tx = stop_ch_tx; + tsp_info("rec channel: %d, %d, %d, %d\n", data->rec_start_ch.rx, + data->rec_stop_ch.rx, data->rec_start_ch.tx, + data->rec_stop_ch.tx); + data->rec_delay = delay; + tsp_info("rec delay: %dms\n", data->rec_delay); + } + + if (data->status.power) { + if (data->debug_mode || data->jig_mode || data->rec_mode || + data->debugging_mode) { + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SLEEP_MODE_EN << 16) | (IST30XX_DISABLE & 0xFFFF)); + } else { + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SLEEP_MODE_EN << 16) | (IST30XX_ENABLE & 0xFFFF)); + } + + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SET_REC_MODE << 16) | (data->rec_mode & 0xFFFF)); + + if (data->rec_mode) { + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SET_REC_MODE << 16) | (IST30XX_START_SCAN & 0xFFFF)); + } + } + +err_file_open: + set_fs(old_fs); + + return 0; +} + +#ifdef IST30XX_ALGORITHM_MODE +/* sysfs: /sys/class/touch/tunes/algorithm */ +ssize_t ist30xx_algr_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%x %d", &data->algr_addr, &data->algr_size); + tsp_info("algorithm addr: 0x%x, count: %d\n", data->algr_addr, + data->algr_size); + + return size; +} + +ssize_t ist30xx_algr_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int ret; + u32 algr_addr; + int count = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + + ret = ist30xx_read_cmd(data, eHCOM_GET_ALGO_BASE, &algr_addr); + if (unlikely(ret)) { + mutex_lock(&data->lock); + ist30xx_reset(data, false); + ist30xx_start(data); + mutex_unlock(&data->lock); + tsp_warn("algorithm mem addr read fail!\n"); + return 0; + } + + tsp_info("algr_addr(0x%x): 0x%x\n", eHCOM_GET_ALGO_BASE, algr_addr); + count = sprintf(buf, "algorithm addr : 0x%x\n", algr_addr); + + return count; +} +#endif + +/* sysfs: /sys/class/touch/tunes/intr_debug */ +ssize_t intr_debug_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%x %d", &data->intr_debug1_addr, &data->intr_debug1_size); + tsp_info("intr debug1 addr: 0x%x, count: %d\n", data->intr_debug1_addr, + data->intr_debug1_size); + + return size; +} + +ssize_t intr_debug_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int count = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + + tsp_info("intr debug1 addr: 0x%x, count: %d\n", data->intr_debug1_addr, + data->intr_debug1_size); + + count = sprintf(buf, "intr debug1 addr: 0x%x, count: %d\n", + data->intr_debug1_addr, data->intr_debug1_size); + + return count; +} + +/* sysfs: /sys/class/touch/tunes/intr_debug2 */ +ssize_t intr_debug2_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%x %d", &data->intr_debug2_addr, &data->intr_debug2_size); + tsp_info("intr debug2 addr: 0x%x, count: %d\n", data->intr_debug2_addr, + data->intr_debug2_size); + + return size; +} + +ssize_t intr_debug2_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int count = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + + tsp_info("intr debug2 addr: 0x%x, count: %d\n", data->intr_debug2_addr, + data->intr_debug2_size); + + count = sprintf(buf, "intr debug2 addr: 0x%x, count: %d\n", + data->intr_debug2_addr, data->intr_debug2_size); + + return count; +} + +/* sysfs: /sys/class/touch/tunes/intr_debug3 */ +ssize_t intr_debug3_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%x %d", &data->intr_debug3_addr, &data->intr_debug3_size); + tsp_info("intr debug3 addr: 0x%x, count: %d\n", data->intr_debug3_addr, + data->intr_debug3_size); + + return size; +} + +ssize_t intr_debug3_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int count = 0; + struct ist30xx_data *data = dev_get_drvdata(dev); + + tsp_info("intr debug3 addr: 0x%x, count: %d\n", data->intr_debug3_addr, + data->intr_debug2_size); + + count = sprintf(buf, "intr debug3 addr: 0x%x, count: %d\n", + data->intr_debug3_addr, data->intr_debug3_size); + + return count; +} + +#define IST30XX_DEBUGGING_MAGIC 0xDEBC0000 +#define MAX_FRAME_COUNT 1024 +IST30XX_RING_BUF DebugBuf; +IST30XX_RING_BUF *pDebugBuf; +bool debugging_initialize = false; +void ist30xx_debugging_init(struct ist30xx_data *data) +{ + if (!debugging_initialize) + pDebugBuf = &DebugBuf; + + pDebugBuf->RingBufCtr = 0; + pDebugBuf->RingBufInIdx = 0; + pDebugBuf->RingBufOutIdx = 0; + + data->debugging_scancnt = 0; + + debugging_initialize = true; +} + +u32 ist30xx_get_debugging_cnt(void) +{ + return pDebugBuf->RingBufCtr; +} + +int ist30xx_get_frame(struct ist30xx_data *data, u32 *frame, u32 cnt) +{ + int i; + u8 *buf = (u8 *)frame; + + cnt *= IST30XX_DATA_LEN; + + if (pDebugBuf->RingBufCtr < cnt) + return IST30XX_RINGBUF_NOT_ENOUGH; + + for (i = 0; i < cnt; i++) { + if (pDebugBuf->RingBufOutIdx == IST30XX_MAX_RINGBUF_SIZE) + pDebugBuf->RingBufOutIdx = 0; + + *buf++ = (u8)pDebugBuf->LogBuf[pDebugBuf->RingBufOutIdx++]; + pDebugBuf->RingBufCtr--; + } + + return IST30XX_RINGBUF_NO_ERR; +} + +int ist30xx_put_frame(struct ist30xx_data *data, u32 ms, u32 *touch, u32 *frame, + int frame_cnt) +{ + int i; + int size = 0; + u32 *buf32; + u8 *buf; + + buf32 = kzalloc((frame_cnt + 3) * sizeof(u32), GFP_KERNEL); + + /* Header & Time */ + ms &= 0x0000FFFF; + ms |= IST30XX_DEBUGGING_MAGIC; + buf32[size++] = ms; + + buf32[size++] = *touch; + buf32[size++] = *(touch + 1); + + for (i = 0; i < frame_cnt; i++) { + buf32[i + 3] = frame[i]; + size++; + } + + buf = (u8 *)buf32; + size *= IST30XX_DATA_LEN; + + pDebugBuf->RingBufCtr += size; + if (pDebugBuf->RingBufCtr > IST30XX_MAX_RINGBUF_SIZE) { + pDebugBuf->RingBufOutIdx += + (pDebugBuf->RingBufCtr - IST30XX_MAX_RINGBUF_SIZE); + if (pDebugBuf->RingBufOutIdx >= IST30XX_MAX_RINGBUF_SIZE) + pDebugBuf->RingBufOutIdx -= IST30XX_MAX_RINGBUF_SIZE; + + pDebugBuf->RingBufCtr = IST30XX_MAX_RINGBUF_SIZE; + } + + for (i = 0; i < size; i++) { + if (pDebugBuf->RingBufInIdx == IST30XX_MAX_RINGBUF_SIZE) + pDebugBuf->RingBufInIdx = 0; + pDebugBuf->LogBuf[pDebugBuf->RingBufInIdx++] = *buf++; + } + + kfree(buf32); + + return IST30XX_RINGBUF_NO_ERR; +} + +/* sysfs: /sys/class/touch/tunes/debugging_mode */ +ssize_t debugging_mode_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int enable; + int noise = 1; + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%d %d", &enable, &noise); + + if (enable == data->debugging_mode) + return size; + + if (data->debugging_addr == 0x0) { + tsp_err("check feature in firmware\n"); + return size; + } + + if (unlikely((enable != 0) && (enable != 1))) { + tsp_err("input data error(%d)\n", enable); + return size; + } + + ist30xx_debugging_init(data); + data->debugging_noise = noise; + data->debugging_mode = enable; + tsp_info("set debugging mode: %s\n", enable ? "start" : "stop"); + + if (data->status.power) { + if (data->debug_mode || data->jig_mode || data->rec_mode || + data->debugging_mode) { + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SLEEP_MODE_EN << 16) | (IST30XX_DISABLE & 0xFFFF)); + } else { + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SLEEP_MODE_EN << 16) | (IST30XX_ENABLE & 0xFFFF)); + } + + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SET_DBG_MODE << 16) | (data->debugging_mode & 0xFFFF)); + } + + return size; +} + +ssize_t debugging_mode_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + if (data->debugging_addr == 0x0) { + tsp_err("check feature in firmware\n"); + return sprintf(buf, "%s", "FAIL"); + } + + ist30xx_debugging_init(data); + data->debugging_noise = 1; + data->debugging_mode = (data->debugging_mode ? 0 : 1); + tsp_info("set debugging mode: %s\n", + data->debugging_mode ? "start" : "stop"); + + if (data->status.power) { + if (data->debug_mode || data->jig_mode || data->rec_mode || + data->debugging_mode) { + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SLEEP_MODE_EN << 16) | (IST30XX_DISABLE & 0xFFFF)); + } else { + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SLEEP_MODE_EN << 16) | (IST30XX_ENABLE & 0xFFFF)); + } + + ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_SET_DBG_MODE << 16) | (data->debugging_mode & 0xFFFF)); + } + + return sprintf(buf, "%s", data->debugging_mode ? "ENABLE" : "DISABLE"); +} + +/* sysfs: /sys/class/touch/tunes/debugging_status */ +ssize_t debugging_status_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%s", data->debugging_mode ? "ENABLE" : "DISABLE"); +} + +/* sysfs: /sys/class/touch/tunes/debugging_cnt */ +ssize_t debugging_cnt_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + u32 cnt = (u32)ist30xx_get_debugging_cnt(); + + tsp_verb("debugging cnt: %d\n", cnt); + + return sprintf(buf, "%08x", cnt); +} + +/* sysfs: /sys/class/touch/tunes/debugging_frame */ +ssize_t debugging_frame_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int i; + int count = 0; + u32 *frame_data = NULL; + char msg[10]; + struct ist30xx_data *data = dev_get_drvdata(dev); + u32 frame_cnt = MAX_FRAME_COUNT; + + frame_data = kzalloc(MAX_FRAME_COUNT, GFP_KERNEL); + + buf[0] = '\0'; + + if (frame_cnt > ist30xx_get_debugging_cnt()) + frame_cnt = ist30xx_get_debugging_cnt(); + + tsp_verb("num: %d of %d\n", frame_cnt, ist30xx_get_debugging_cnt()); + + frame_cnt /= IST30XX_DATA_LEN; + + if (ist30xx_get_frame(data, frame_data, frame_cnt)) + return count; + + for (i = 0; i < frame_cnt; i++) { + tsp_verb("%08X\n", frame_data[i]); + + count += sprintf(msg, "%08x", frame_data[i]); + strcat(buf, msg); + } + + return count; +} + +/* sysfs: /sys/class/touch/tunes/tbase */ +ssize_t target_baseline_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%08x", data->tsp_info.baseline); +} + +/* sysfs : node */ +static DEVICE_ATTR(cp, S_IRWXUGO, ist30xx_cp_show, NULL); +static DEVICE_ATTR(cp_lower, S_IRWXUGO, ist30xx_cp_lower_show, NULL); +static DEVICE_ATTR(cp_upper, S_IRWXUGO, ist30xx_cp_upper_show, NULL); +static DEVICE_ATTR(rawbase, S_IRWXUGO, ist30xx_frame_rawbase, NULL); +static DEVICE_ATTR(refresh, S_IRWXUGO, ist30xx_frame_refresh, NULL); +static DEVICE_ATTR(nocp, S_IRWXUGO, ist30xx_frame_nocp, NULL); +static DEVICE_ATTR(filter, S_IRWXUGO, ist30xx_filter_show, NULL); +static DEVICE_ATTR(raw, S_IRWXUGO, ist30xx_raw_show, NULL); +static DEVICE_ATTR(base, S_IRWXUGO, ist30xx_base_show, NULL); +static DEVICE_ATTR(diff, S_IRWXUGO, ist30xx_diff_show, NULL); + +/* sysfs : sys */ +static DEVICE_ATTR(debug_mode, S_IRWXUGO, NULL, ist30xx_debug_mode_store); +static DEVICE_ATTR(rec_mode, S_IRWXUGO, ist30xx_rec_mode_show, + ist30xx_rec_mode_store); +static DEVICE_ATTR(jig_mode, S_IRWXUGO, NULL, ist30xx_jig_mode_store); +static DEVICE_ATTR(printk, S_IRWXUGO, ist30xx_printk_show, + ist30xx_printk_store); +static DEVICE_ATTR(printk5, S_IRWXUGO, ist30xx_printk5_show, NULL); +static DEVICE_ATTR(printk6, S_IRWXUGO, ist30xx_printk6_show, NULL); +#ifdef IST30XX_GESTURE +static DEVICE_ATTR(gesture, S_IRWXUGO, NULL, ist30xx_gesture_store); +#endif +static DEVICE_ATTR(direct, S_IRWXUGO, ist30xx_direct_show, + ist30xx_direct_store); +static DEVICE_ATTR(clb_time, S_IRWXUGO, NULL, ist30xx_calib_time_store); +static DEVICE_ATTR(clb, S_IRWXUGO, ist30xx_calib_show, NULL); +static DEVICE_ATTR(clb_result, S_IRWXUGO, ist30xx_calib_result_show, NULL); +static DEVICE_ATTR(cal_ref, S_IRWXUGO, ist30xx_cal_ref_show, NULL); +static DEVICE_ATTR(tsp_power_on, S_IRWXUGO, ist30xx_power_on_show, NULL); +static DEVICE_ATTR(tsp_power_off, S_IRWXUGO, ist30xx_power_off_show, NULL); +static DEVICE_ATTR(errcnt, S_IRWXUGO, NULL, ist30xx_errcnt_store); +static DEVICE_ATTR(scancnt, S_IRWXUGO, NULL, ist30xx_scancnt_store); +static DEVICE_ATTR(timerms, S_IRWXUGO, NULL, ist30xx_timerms_store); +static DEVICE_ATTR(report_rate, S_IRWXUGO, NULL, ist30xx_report_rate_store); +static DEVICE_ATTR(idle_rate, S_IRWXUGO, NULL, ist30xx_idle_scan_rate_store); +static DEVICE_ATTR(mode_ta, S_IRWXUGO, NULL, ist30xx_ta_mode_store); +static DEVICE_ATTR(mode_call, S_IRWXUGO, NULL, ist30xx_call_mode_store); +static DEVICE_ATTR(mode_cover, S_IRWXUGO, NULL, ist30xx_cover_mode_store); +static DEVICE_ATTR(ic_inform, S_IRUGO, ist30xx_read_ic_inform, NULL); +#ifdef IST30XX_TAU +static DEVICE_ATTR(tau, S_IRUGO, ist30xx_tau_show, NULL); +#endif + +/* sysfs : tunes */ +static DEVICE_ATTR(node_info, S_IRWXUGO, tunes_node_info_show, NULL); +static DEVICE_ATTR(regcmd, S_IRWXUGO, tunes_regcmd_show, tunes_regcmd_store); +static DEVICE_ATTR(reg, S_IRWXUGO, tunes_reg_show, tunes_reg_store); +static DEVICE_ATTR(adb, S_IRWXUGO, tunes_adb_show, tunes_adb_store); +#ifdef IST30XX_ALGORITHM_MODE +static DEVICE_ATTR(algorithm, S_IRWXUGO, ist30xx_algr_show, ist30xx_algr_store); +#endif +static DEVICE_ATTR(intr_debug, S_IRWXUGO, intr_debug_show, intr_debug_store); +static DEVICE_ATTR(intr_debug2, S_IRWXUGO, intr_debug2_show, intr_debug2_store); +static DEVICE_ATTR(intr_debug3, S_IRWXUGO, intr_debug3_show, intr_debug3_store); +static DEVICE_ATTR(debugging_mode, S_IRWXUGO, debugging_mode_show, + debugging_mode_store); +static DEVICE_ATTR(debugging_status, S_IRWXUGO, debugging_status_show, NULL); +static DEVICE_ATTR(debugging_cnt, S_IRWXUGO, debugging_cnt_show, NULL); +static DEVICE_ATTR(debugging_frame, S_IRWXUGO, debugging_frame_show, NULL); +static DEVICE_ATTR(tbase, S_IRWXUGO, target_baseline_show, NULL); + +static struct attribute *node_attributes[] = { + &dev_attr_cp.attr, + &dev_attr_cp_lower.attr, + &dev_attr_cp_upper.attr, + &dev_attr_rawbase.attr, + &dev_attr_refresh.attr, + &dev_attr_nocp.attr, + &dev_attr_filter.attr, + &dev_attr_raw.attr, + &dev_attr_base.attr, + &dev_attr_diff.attr, + NULL, +}; + +static struct attribute *sys_attributes[] = { + &dev_attr_debug_mode.attr, + &dev_attr_rec_mode.attr, + &dev_attr_jig_mode.attr, + &dev_attr_printk.attr, + &dev_attr_printk5.attr, + &dev_attr_printk6.attr, +#ifdef IST30XX_GESTURE + &dev_attr_gesture.attr, +#endif + &dev_attr_direct.attr, + &dev_attr_clb_time.attr, + &dev_attr_clb.attr, + &dev_attr_clb_result.attr, + &dev_attr_cal_ref.attr, + &dev_attr_tsp_power_on.attr, + &dev_attr_tsp_power_off.attr, + &dev_attr_errcnt.attr, + &dev_attr_scancnt.attr, + &dev_attr_timerms.attr, + &dev_attr_report_rate.attr, + &dev_attr_idle_rate.attr, + &dev_attr_mode_ta.attr, + &dev_attr_mode_call.attr, + &dev_attr_mode_cover.attr, + &dev_attr_ic_inform.attr, + NULL, +}; + +static struct attribute *tunes_attributes[] = { + &dev_attr_node_info.attr, + &dev_attr_regcmd.attr, + &dev_attr_reg.attr, + &dev_attr_adb.attr, +#ifdef IST30XX_ALGORITHM_MODE + &dev_attr_algorithm.attr, +#endif + &dev_attr_intr_debug.attr, + &dev_attr_intr_debug2.attr, + &dev_attr_intr_debug3.attr, + &dev_attr_debugging_mode.attr, + &dev_attr_debugging_cnt.attr, + &dev_attr_debugging_frame.attr, + &dev_attr_debugging_status.attr, + &dev_attr_tbase.attr, + NULL, +}; + +static struct attribute_group node_attr_group = { + .attrs = node_attributes, +}; + +static struct attribute_group sys_attr_group = { + .attrs = sys_attributes, +}; + +static struct attribute_group tunes_attr_group = { + .attrs = tunes_attributes, +}; + +extern struct class *ist30xx_class; +struct device *ist30xx_sys_dev; +struct device *ist30xx_tunes_dev; +struct device *ist30xx_node_dev; + +int ist30xx_init_misc_sysfs(struct ist30xx_data *data) +{ + /* /sys/class/touch/sys */ + ist30xx_sys_dev = device_create(ist30xx_class, NULL, 0, data, "sys"); + + /* /sys/class/touch/sys/... */ + if (unlikely(sysfs_create_group(&ist30xx_sys_dev->kobj, + &sys_attr_group))) + tsp_err("Failed to create sysfs group(%s)!\n", "sys"); + + /* /sys/class/touch/tunes */ + ist30xx_tunes_dev = device_create(ist30xx_class, NULL, 0, data, "tunes"); + + /* /sys/class/touch/tunes/... */ + if (unlikely(sysfs_create_group(&ist30xx_tunes_dev->kobj, + &tunes_attr_group))) + tsp_err("Failed to create sysfs group(%s)!\n", "tunes"); + + /* /sys/class/touch/node */ + ist30xx_node_dev = device_create(ist30xx_class, NULL, 0, data, "node"); + + /* /sys/class/touch/node/... */ + if (unlikely(sysfs_create_group(&ist30xx_node_dev->kobj, + &node_attr_group))) + tsp_err("Failed to create sysfs group(%s)!\n", "node"); + + ist30xx_debugging_init(data); + + return 0; +} diff --git a/drivers/input/touchscreen/ist3038c/ist30xxc_misc.h b/drivers/input/touchscreen/ist3038c/ist30xxc_misc.h new file mode 100644 index 0000000000000..70a5320cdc789 --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/ist30xxc_misc.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010, Imagis Technology Co. Ltd. All Rights Reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __IST30XXC_MISC_H__ +#define __IST30XXC_MISC_H__ + +#define NODE_FLAG_RAW (1 << 0) +#define NODE_FLAG_BASE (1 << 1) +#define NODE_FLAG_FILTER (1 << 2) +#define NODE_FLAG_DIFF (1 << 3) +#define NODE_FLAG_ALL (0xF) +#define NODE_FLAG_NO_CCP (1 << 7) + +#define NODE_FLAG_CP_LOWER (1 << 0) +#define NODE_FLAG_CP_UPPER (1 << 1) + +#define TSP_RAW_ALL (0) +#define TSP_RAW_SCREEN (1 << 0) +#define TSP_RAW_KEY (1 << 1) + +#define IST30XX_REC_FILENAME "ist30xxc.res" + +int ist30xx_check_valid_ch(struct ist30xx_data *data, int ch_tx, int ch_rx); +int ist30xx_parse_cp_node(struct ist30xx_data *data, struct TSP_NODE_BUF *node); +int parse_cp_node(struct ist30xx_data *data, u8 flag, + struct TSP_NODE_BUF *node, s16 *buf16, int mode); +int ist30xx_read_cp_node(struct ist30xx_data *data, struct TSP_NODE_BUF *node); +int ist30xx_parse_touch_node(struct ist30xx_data *data, u8 flag, + struct TSP_NODE_BUF *node); +int parse_tsp_node(struct ist30xx_data *data, u8 flag, + struct TSP_NODE_BUF *node, s16 *buf16, int mode); +int ist30xx_read_touch_node(struct ist30xx_data *data, u8 flag, + struct TSP_NODE_BUF *node); + +int ist30xx_put_frame(struct ist30xx_data *data, u32 ms, u32 *touch, u32 *frame, + int frame_cnt); + +int ist30xx_init_misc_sysfs(struct ist30xx_data *data); + +#endif diff --git a/drivers/input/touchscreen/ist3038c/ist30xxc_sys.c b/drivers/input/touchscreen/ist3038c/ist30xxc_sys.c new file mode 100644 index 0000000000000..52303ff9de13a --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/ist30xxc_sys.c @@ -0,0 +1,493 @@ +/* + * Copyright (C) 2010,Imagis Technology Co. Ltd. All Rights Reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ist30xxc.h" +#include "ist30xxc_update.h" +#ifdef IST30XX_TRACKING_MODE +#include "ist30xxc_tracking.h" +#endif + +/****************************************************************************** + * Return value of Error + * EPERM : 1 (Operation not permitted) + * ENOENT : 2 (No such file or directory) + * EIO : 5 (I/O error) + * ENXIO : 6 (No such device or address) + * EINVAL : 22 (Invalid argument) + *****************************************************************************/ +int ist30xx_cmd_gesture(struct ist30xx_data *data, int value) +{ + int ret = -EIO; + + if (value > 3) + return ret; + + ret = ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_GESTURE_EN << 16) | (value & 0xFFFF)); + + return ret; +} + +int ist30xx_cmd_start_scan(struct ist30xx_data *data) +{ + int ret = ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_FW_START << 16) | (IST30XX_ENABLE & 0xFFFF)); + +#ifdef IST30XX_TRACKING_MODE + ist30xx_tracking(TRACK_CMD_SCAN); +#endif + data->status.noise_mode = true; + + return ret; +} + +int ist30xx_cmd_calibrate(struct ist30xx_data *data) +{ + int ret = ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_RUN_CAL_AUTO << 16)); + +#ifdef IST30XX_TRACKING_MODE + ist30xx_tracking(TRACK_CMD_CALIB); +#endif + tsp_info("%s\n", __func__); + + return ret; +} + +int ist30xx_cmd_cal_reference(struct ist30xx_data *data) +{ + int ret = ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_RUN_CAL_REF << 16)); + +#ifdef IST30XX_TRACKING_MODE + ist30xx_tracking(TRACK_CMD_CALIB); +#endif + tsp_info("%s\n", __func__); + + return ret; +} + +int ist30xx_cmd_check_calib(struct ist30xx_data *data) +{ + int ret = ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_RUN_CAL_PARAM << 16) | (IST30XX_ENABLE & 0xFFFF)); + +#ifdef IST30XX_TRACKING_MODE + ist30xx_tracking(TRACK_CMD_CHECK_CALIB); +#endif + tsp_info("*** Check Calibration cmd ***\n"); + + return ret; +} + +int ist30xx_cmd_hold(struct ist30xx_data *data, int enable) +{ + int ret; + + if (!data->initialized && (data->status.update != 1)) + return 0; + + ret = ist30xx_write_cmd(data, IST30XX_HIB_CMD, + (eHCOM_FW_HOLD << 16) | (enable & 0xFFFF)); + tsp_info("%s: FW HOLDE %s\n", __func__, enable ? "Enable" : "Disable"); + +#ifdef IST30XX_TRACKING_MODE + if (enable) + ist30xx_tracking(TRACK_CMD_ENTER_REG); + else + ist30xx_tracking(TRACK_CMD_EXIT_REG); +#endif + + return ret; +} + +int ist30xx_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int msg_num, u8 *cmd_buf) +{ + int ret = 0; + int idx = msg_num - 1; + int size = msgs[idx].len; + u8 *msg_buf = NULL; + u8 *pbuf = NULL; + int trans_size, max_size = 0; + + if (msg_num == WRITE_CMD_MSG_LEN) + max_size = I2C_MAX_WRITE_SIZE; + else if (msg_num == READ_CMD_MSG_LEN) + max_size = I2C_MAX_READ_SIZE; + + if (unlikely(max_size == 0)) { + tsp_err("%s() : transaction size(%d)\n", __func__, max_size); + return -EINVAL; + } + + if (msg_num == WRITE_CMD_MSG_LEN) { + msg_buf = kmalloc(max_size + IST30XX_ADDR_LEN, GFP_KERNEL); + if (!msg_buf) + return -ENOMEM; + memcpy(msg_buf, cmd_buf, IST30XX_ADDR_LEN); + pbuf = msgs[idx].buf; + } + + while (size > 0) { + trans_size = (size >= max_size ? max_size : size); + + msgs[idx].len = trans_size; + if (msg_num == WRITE_CMD_MSG_LEN) { + memcpy(&msg_buf[IST30XX_ADDR_LEN], pbuf, trans_size); + msgs[idx].buf = msg_buf; + msgs[idx].len += IST30XX_ADDR_LEN; + } + ret = i2c_transfer(adap, msgs, msg_num); + if (unlikely(ret != msg_num)) { + tsp_err("%s() : i2c_transfer failed(%d), num=%d\n", + __func__, ret, msg_num); + break; + } + + if (msg_num == WRITE_CMD_MSG_LEN) + pbuf += trans_size; + else + msgs[idx].buf += trans_size; + + size -= trans_size; + } + + if (msg_num == WRITE_CMD_MSG_LEN) + kfree(msg_buf); + + return ret; +} + +int ist30xx_read_buf(struct i2c_client *client, u32 cmd, u32 *buf, u16 len) +{ + int ret, i; + u32 le_reg = cpu_to_be32(cmd); + + struct i2c_msg msg[READ_CMD_MSG_LEN] = { + { + .addr = client->addr, + .flags = 0, + .len = IST30XX_ADDR_LEN, + .buf = (u8 *)&le_reg, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = len * IST30XX_DATA_LEN, + .buf = (u8 *)buf, + }, + }; + + ret = ist30xx_i2c_transfer(client->adapter, msg, READ_CMD_MSG_LEN, NULL); + if (unlikely(ret != READ_CMD_MSG_LEN)) + return -EIO; + + for (i = 0; i < len; i++) + buf[i] = cpu_to_be32(buf[i]); + + return 0; +} + +int ist30xx_write_buf(struct i2c_client *client, u32 cmd, u32 *buf, u16 len) +{ + int i; + int ret; + struct i2c_msg msg; + u8 cmd_buf[IST30XX_ADDR_LEN]; + u8 msg_buf[IST30XX_DATA_LEN * (len + 1)]; + + put_unaligned_be32(cmd, cmd_buf); + + if (likely(len > 0)) { + for (i = 0; i < len; i++) + put_unaligned_be32(buf[i], msg_buf + (i * IST30XX_DATA_LEN)); + } else { + /* then add dummy data(4byte) */ + put_unaligned_be32(0, msg_buf); + len = 1; + } + + msg.addr = client->addr; + msg.flags = 0; + msg.len = len * IST30XX_DATA_LEN; + msg.buf = msg_buf; + + ret = ist30xx_i2c_transfer(client->adapter, &msg, WRITE_CMD_MSG_LEN, + cmd_buf); + if (unlikely(ret != WRITE_CMD_MSG_LEN)) + return -EIO; + + return 0; +} + +int ist30xx_read_reg(struct i2c_client *client, u32 reg, u32 *buf) +{ + int ret; + u32 le_reg = cpu_to_be32(reg); + + struct i2c_msg msg[READ_CMD_MSG_LEN] = { + { + .addr = client->addr, + .flags = 0, + .len = IST30XX_ADDR_LEN, + .buf = (u8 *)&le_reg, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = IST30XX_DATA_LEN, + .buf = (u8 *)buf, + }, + }; + + ret = i2c_transfer(client->adapter, msg, READ_CMD_MSG_LEN); + if (ret != READ_CMD_MSG_LEN) { + tsp_err("%s: i2c failed (%d), cmd: %x\n", __func__, ret, reg); + return -EIO; + } + *buf = cpu_to_be32(*buf); + + return 0; +} + +int ist30xx_read_cmd(struct ist30xx_data *data, u32 cmd, u32 *buf) +{ + int ret; + + ret = ist30xx_cmd_hold(data, IST30XX_ENABLE); + if (unlikely(ret)) + return ret; + + ist30xx_read_reg(data->client, IST30XX_DA_ADDR(cmd), buf); + + ret = ist30xx_cmd_hold(data, IST30XX_DISABLE); + if (unlikely(ret)) { + ist30xx_reset(data, false); + return ret; + } + + return ret; +} + +int ist30xx_write_cmd(struct ist30xx_data *data, u32 cmd, u32 val) +{ + int ret; + u8 msg_buf[IST30XX_ADDR_LEN + IST30XX_DATA_LEN]; + struct i2c_msg msg; + + put_unaligned_be32(cmd, msg_buf); + put_unaligned_be32(val, msg_buf + IST30XX_ADDR_LEN); + + msg.addr = data->client->addr; + msg.flags = 0; + msg.len = IST30XX_ADDR_LEN + IST30XX_DATA_LEN; + msg.buf = msg_buf; + + ret = i2c_transfer(data->client->adapter, &msg, WRITE_CMD_MSG_LEN); + if (ret != WRITE_CMD_MSG_LEN) { + tsp_err("%s: i2c failed (%d), cmd: %x(%x)\n", __func__, ret, cmd, val); + return -EIO; + } + + if (data->initialized && !data->ignore_delay) + ist30xx_delay(40); + + return 0; +} + +int ist30xx_burst_read(struct i2c_client *client, u32 addr, + u32 *buf32, u16 len, bool bit_en) +{ + int ret = 0; + int i; + u16 max_len = I2C_MAX_READ_SIZE / IST30XX_DATA_LEN; + u16 remain_len = len; + + if (bit_en) + addr = IST30XX_BA_ADDR(addr); + + for (i = 0; i < len; i += max_len) { + if (remain_len < max_len) + max_len = remain_len; + + ret = ist30xx_read_buf(client, addr, buf32, max_len); + if (unlikely(ret)) { + tsp_err("Burst fail, addr: %x\n", __func__, addr); + return ret; + } + + addr += max_len * IST30XX_DATA_LEN; + buf32 += max_len; + remain_len -= max_len; + } + + return 0; +} + +int ist30xx_burst_write(struct i2c_client *client, u32 addr, + u32 *buf32, u16 len) +{ + int ret = 0; + int i; + u16 max_len = I2C_MAX_WRITE_SIZE / IST30XX_DATA_LEN; + u16 remain_len = len; + + addr = IST30XX_BA_ADDR(addr); + + for (i = 0; i < len; i += max_len) { + if (remain_len < max_len) + max_len = remain_len; + + ret = ist30xx_write_buf(client, addr, buf32, max_len); + if (unlikely(ret)) { + tsp_err("Burst fail, addr: %x\n", __func__, addr); + return ret; + } + + addr += max_len * IST30XX_DATA_LEN; + buf32 += max_len; + remain_len -= max_len; + } + + return 0; +} + +static void ts_power_enable(struct ist30xx_data *data, int en) +{ + + if (en) { + + gpio_direction_output(data->dt_data->reset_gpio, 1); + + } else { + + gpio_direction_output(data->dt_data->reset_gpio, 0); + } +} + +int ist30xx_power_on(struct ist30xx_data *data, bool download) +{ + if (data->status.power != 1) { + tsp_info("%s()\n", __func__); +#ifdef IST30XX_TRACKING_MODE + ist30xx_tracking(TRACK_PWR_ON); +#endif + /* VDD enable */ + /* VDDIO enable */ + ts_power_enable(data, 1); + if (download) + ist30xx_delay(30); + else + ist30xx_delay(60); + + data->status.power = 1; + } + + return 0; +} + +int ist30xx_power_off(struct ist30xx_data *data) +{ + if (data->status.power != 0) { + tsp_info("%s()\n", __func__); +#ifdef IST30XX_TRACKING_MODE + ist30xx_tracking(TRACK_PWR_OFF); +#endif + data->ignore_delay = true; + ist30xxc_isp_enable(data, true); + data->ignore_delay = false; + /* VDDIO disable */ + /* VDD disable */ + ts_power_enable(data, 0); + data->status.power = 0; + data->status.noise_mode = false; + } + + return 0; +} + +int ist30xx_reset(struct ist30xx_data *data, bool download) +{ + tsp_info("%s()\n", __func__); + ist30xx_power_off(data); + ist30xx_delay(30); + ist30xx_power_on(data, download); + + return 0; +} + +int ist30xx_internal_suspend(struct ist30xx_data *data) +{ +#ifdef IST30XX_GESTURE + data->suspend = true; + if (ist30xx_gesture_func_on) { + if (data->gesture) { + ist30xx_reset(data, false); + ist30xx_cmd_gesture(data, 3); + } + } else { + ist30xx_power_off(data); + } +#else + ist30xx_power_off(data); +#endif + + return 0; +} + +int ist30xx_internal_resume(struct ist30xx_data *data) +{ +#ifdef IST30XX_GESTURE + data->suspend = false; + if (ist30xx_gesture_func_on) { + if (data->gesture) + ist30xx_reset(data, false); + } else + ist30xx_power_on(data, false); +#else + ist30xx_power_on(data, false); +#endif + + return 0; +} + +int ist30xx_init_system(struct ist30xx_data *data) +{ + int ret; + + + ret = ist30xx_power_on(data, false); + if (ret) { + tsp_err("%s: ist30xx_init_system failed (%d)\n", __func__, ret); + return -EIO; + } + + return 0; +} + diff --git a/drivers/input/touchscreen/ist3038c/ist30xxc_tracking.c b/drivers/input/touchscreen/ist3038c/ist30xxc_tracking.c new file mode 100644 index 0000000000000..9eaab6e812118 --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/ist30xxc_tracking.c @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2010,Imagis Technology Co. Ltd. All Rights Reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include + +#include "ist30xxc.h" +#ifdef IST30XX_TRACKING_MODE +#include "ist30xxc_tracking.h" +#endif + +#ifdef IST30XX_TRACKING_MODE +IST30XX_RING_BUF TrackBuf; +IST30XX_RING_BUF *pTrackBuf; + +bool tracking_initialize = false; + +void ist30xx_tracking_init(void) +{ + if (tracking_initialize) + return; + + pTrackBuf = &TrackBuf; + + pTrackBuf->RingBufCtr = 0; + pTrackBuf->RingBufInIdx = 0; + pTrackBuf->RingBufOutIdx = 0; + + tracking_initialize = true; +} + +void ist30xx_tracking_deinit(void) +{ +} + +static spinlock_t mr_lock = __SPIN_LOCK_UNLOCKED(); +int ist30xx_get_track(u32 *track, int cnt) +{ + int i; + u8 *buf = (u8 *)track; + unsigned long flags; + + cnt *= sizeof(track[0]); + + spin_lock_irqsave(&mr_lock, flags); + + if (pTrackBuf->RingBufCtr < (u16)cnt) { + spin_unlock_irqrestore(&mr_lock, flags); + return IST30XX_RINGBUF_NOT_ENOUGH; + } + + for (i = 0; i < cnt; i++) { + if (pTrackBuf->RingBufOutIdx == IST30XX_MAX_RINGBUF_SIZE) + pTrackBuf->RingBufOutIdx = 0; + + *buf++ = (u8)pTrackBuf->LogBuf[pTrackBuf->RingBufOutIdx++]; + pTrackBuf->RingBufCtr--; + } + + spin_unlock_irqrestore(&mr_lock, flags); + + return IST30XX_RINGBUF_NO_ERR; +} + +u32 ist30xx_get_track_cnt(void) +{ + return pTrackBuf->RingBufCtr; +} + +int ist30xx_put_track(u32 *track, int cnt) +{ + int i; + u8 *buf = (u8 *)track; + unsigned long flags; + + spin_lock_irqsave(&mr_lock, flags); + + cnt *= sizeof(track[0]); + + pTrackBuf->RingBufCtr += cnt; + if (pTrackBuf->RingBufCtr > IST30XX_MAX_RINGBUF_SIZE) { + pTrackBuf->RingBufOutIdx += + (pTrackBuf->RingBufCtr - IST30XX_MAX_RINGBUF_SIZE); + if (pTrackBuf->RingBufOutIdx >= IST30XX_MAX_RINGBUF_SIZE) + pTrackBuf->RingBufOutIdx -= IST30XX_MAX_RINGBUF_SIZE; + + pTrackBuf->RingBufCtr = IST30XX_MAX_RINGBUF_SIZE; + } + + for (i = 0; i < cnt; i++) { + if (pTrackBuf->RingBufInIdx == IST30XX_MAX_RINGBUF_SIZE) + pTrackBuf->RingBufInIdx = 0; + pTrackBuf->LogBuf[pTrackBuf->RingBufInIdx++] = *buf++; + } + + spin_unlock_irqrestore(&mr_lock, flags); + + return IST30XX_RINGBUF_NO_ERR; +} + +int ist30xx_put_track_ms(u32 ms) +{ + ms &= 0x0000FFFF; + ms |= IST30XX_TRACKING_MAGIC; + + return ist30xx_put_track(&ms, 1); +} + +static struct timespec t_track; +int ist30xx_tracking(u32 status) +{ + u32 ms; + + if (!tracking_initialize) + ist30xx_tracking_init(); + + ktime_get_ts(&t_track); + ms = t_track.tv_sec * 1000 + t_track.tv_nsec / 1000000; + + ist30xx_put_track_ms(ms); + ist30xx_put_track(&status, 1); + + return 0; +} + +#define MAX_TRACKING_COUNT (1024) +/* sysfs: /sys/class/touch/tracking/track_frame */ +ssize_t ist30xx_track_frame_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i, buf_cnt = 0; + u32 track_cnt = MAX_TRACKING_COUNT; + u32 track; + char msg[10]; + struct ist30xx_data *data = dev_get_drvdata(dev); + + mutex_lock(&data->lock); + + buf[0] = '\0'; + + if (track_cnt > ist30xx_get_track_cnt()) + track_cnt = ist30xx_get_track_cnt(); + + track_cnt /= sizeof(track); + + tsp_verb("num: %d of %d\n", track_cnt, ist30xx_get_track_cnt()); + + for (i = 0; i < track_cnt; i++) { + ist30xx_get_track(&track, 1); + + tsp_verb("%08X\n", track); + + buf_cnt += sprintf(msg, "%08x", track); + strcat(buf, msg); + } + + mutex_unlock(&data->lock); + + return buf_cnt; +} + +/* sysfs: /sys/class/touch/tracking/track_cnt */ +ssize_t ist30xx_track_cnt_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 val = (u32)ist30xx_get_track_cnt(); + + tsp_verb("tracking cnt: %d\n", val); + + return sprintf(buf, "%08x", val); +} + + +/* sysfs */ +static DEVICE_ATTR(track_frame, 0664, ist30xx_track_frame_show, NULL); +static DEVICE_ATTR(track_cnt, 0664, ist30xx_track_cnt_show, NULL); + +static struct attribute *tracking_attributes[] = { + &dev_attr_track_frame.attr, + &dev_attr_track_cnt.attr, + NULL, +}; + +static struct attribute_group tracking_attr_group = { + .attrs = tracking_attributes, +}; + +extern struct class *ist30xx_class; +struct device *ist30xx_tracking_dev; + +int ist30xx_init_tracking_sysfs(struct ist30xx_data *data) +{ + /* /sys/class/touch/tracking */ + ist30xx_tracking_dev = device_create(ist30xx_class, NULL, 0, data, + "tracking"); + + dev_set_drvdata(ist30xx_tracking_dev, data); + /* /sys/class/touch/tracking/... */ + if (sysfs_create_group(&ist30xx_tracking_dev->kobj, &tracking_attr_group)) + tsp_err("[ TSP ] Failed to create sysfs group(%s)!\n", "tracking"); + + ist30xx_tracking_init(); + + return 0; +} +#endif diff --git a/drivers/input/touchscreen/ist3038c/ist30xxc_tracking.h b/drivers/input/touchscreen/ist3038c/ist30xxc_tracking.h new file mode 100644 index 0000000000000..f8447ccd17a40 --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/ist30xxc_tracking.h @@ -0,0 +1,44 @@ +#ifndef __IST30XXC_TRACKING_H__ +#define __IST30XXC_TRACKING_H__ + +#define TRACK_PWR_ON (0x1) +#define TRACK_PWR_OFF (0x2) +#define TRACK_PWR_RESET (0x3) +#define TRACK_INTR_ENABLE (0x4) +#define TRACK_INTR_DISABLE (0x5) +#define TRACK_CMD_RUN_DEVICE (0x10) +#define TRACK_CMD_SCAN (0x11) +#define TRACK_CMD_TACON (0x12) +#define TRACK_CMD_TADISCON (0x13) +#define TRACK_CMD_FWUPDATE (0x14) +#define TRACK_CMD_PRUPDATE (0x15) +#define TRACK_CMD_CALIB (0x16) +#define TRACK_CMD_CHECK_CALIB (0x17) +#define TRACK_CMD_CHKSUM (0x18) +#define TRACK_CMD_CHKSUM_ALL (0x19) +#define TRACK_CMD_ENTER_REG (0x1A) +#define TRACK_CMD_EXIT_REG (0x1B) +#define TRACK_CMD_CALL (0x1C) +#define TRACK_CMD_NOTCALL (0x1D) +#define TRACK_CMD_COVER (0x1E) +#define TRACK_CMD_NOTCOVER (0x1F) +#define TRACK_POS_FINGER (0x20) +#define TRACK_POS_KEY (0x30) +#define TRACK_POS_UNKNOWN (0x3F) + +#define IST30XX_TRACKING_MAGIC (0x7750 << 16) + +void ist30xx_tracking_init(void); +void ist30xx_tracking_deinit(void); + +int ist30xx_get_track(u32 *track, int cnt); +int ist30xx_put_track(u32 *track, int cnt); +int ist30xx_put_track_ms(u32 ms); + +u32 ist30xx_get_track_cnt(void); + +int ist30xx_tracking(u32 status); + +int ist30xx_init_tracking_sysfs(struct ist30xx_data *data); + +#endif diff --git a/drivers/input/touchscreen/ist3038c/ist30xxc_update.c b/drivers/input/touchscreen/ist3038c/ist30xxc_update.c new file mode 100644 index 0000000000000..534bf0a4259bd --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/ist30xxc_update.c @@ -0,0 +1,1623 @@ +/* + * Copyright (C) 2010,Imagis Technology Co. Ltd. All Rights Reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ist30xxc.h" +#include "ist30xxc_update.h" +#include "ist30xxc_tracking.h" + +#ifdef IST30XX_INTERNAL_BIN + + +#include "IST3038C1_00000C6GFF_VER000007.h" +#endif + +#define TAGS_PARSE_OK (0) + + + +int ist30xx_isp_read_burst(struct i2c_client *client, u32 addr, u32 *buf32, + u16 len) +{ + int ret = 0; + int i; + u16 max_len = I2C_MAX_READ_SIZE / IST30XX_DATA_LEN; + u16 remain_len = len; + + for (i = 0; i < len; i += max_len) { + if (remain_len < max_len) + max_len = remain_len; + ret = ist30xx_read_buf(client, addr, buf32, max_len); + if (unlikely(ret)) { + tsp_err("Burst fail, addr: %x\n", __func__, addr); + return ret; + } + + buf32 += max_len; + remain_len -= max_len; + } + + return 0; +} + +int ist30xx_isp_write_burst(struct i2c_client *client, u32 addr, u32 *buf32, + u16 len) +{ + int ret = 0; + int i; + u16 max_len = I2C_MAX_WRITE_SIZE / IST30XX_DATA_LEN; + u16 remain_len = len; + + for (i = 0; i < len; i += max_len) { + if (remain_len < max_len) + max_len = remain_len; + ret = ist30xx_write_buf(client, addr, buf32, max_len); + if (unlikely(ret)) { + tsp_err("Burst fail, addr: %x\n", addr); + return ret; + } + + buf32 += max_len; + remain_len -= max_len; + } + + return 0; +} + +#define IST30XX_ISP_READ_TOTAL_S (0x01) +#define IST30XX_ISP_READ_TOTAL_B (0x11) +#define IST30XX_ISP_READ_MAIN_S (0x02) +#define IST30XX_ISP_READ_MAIN_B (0x12) +#define IST30XX_ISP_READ_INFO_S (0x03) +#define IST30XX_ISP_READ_INFO_B (0x13) +#define IST30XX_ISP_PROG_TOTAL_S (0x04) +#define IST30XX_ISP_PROG_TOTAL_B (0x14) +#define IST30XX_ISP_PROG_MAIN_S (0x05) +#define IST30XX_ISP_PROG_MAIN_B (0x15) +#define IST30XX_ISP_PROG_INFO_S (0x06) +#define IST30XX_ISP_PROG_INFO_B (0x16) +#define IST30XX_ISP_ERASE_BLOCK (0x07) +#define IST30XX_ISP_ERASE_SECTOR (0x08) +#define IST30XX_ISP_ERASE_PAGE (0x09) +#define IST30XX_ISP_ERASE_INFO (0x0A) +#define IST30XX_ISP_READ_TOTAL_CRC (0x1B) +#define IST30XX_ISP_READ_MAIN_CRC (0x1C) +#define IST30XX_ISP_READ_INFO_CRC (0x1D) +int ist30xxc_isp_enable(struct ist30xx_data *data, bool enable) +{ + int ret = 0; + + if (enable) { + ret = ist30xx_write_cmd(data, IST30XX_FLASH_ISPEN, 0xDE01); + if (unlikely(ret)) + return ret; + +#if (IMAGIS_TSP_IC < IMAGIS_IST3038C) + ret = ist30xx_write_cmd(data, IST30XX_FLASH_MODE, 0x4100); + if (unlikely(ret)) + return ret; + + ret = ist30xx_write_cmd(data, IST30XX_FLASH_TEST_MODE1, 0x38); + if (unlikely(ret)) + return ret; +#endif + } else { + ret = ist30xx_write_cmd(data, IST30XX_FLASH_ISPEN, 0x2); + if (unlikely(ret)) + return ret; + } + + ist30xx_delay(1); + + return ret; +} + +int ist30xxc_isp_mode(struct ist30xx_data *data, int mode) +{ + int ret = 0; + u32 val = 0; + + switch (mode) { + case IST30XX_ISP_READ_TOTAL_S: + val = 0x8090; + break; + case IST30XX_ISP_READ_TOTAL_B: + case IST30XX_ISP_READ_TOTAL_CRC: + val = 0x8190; + break; + case IST30XX_ISP_READ_MAIN_S: + val = 0x0090; + break; + case IST30XX_ISP_READ_MAIN_B: + case IST30XX_ISP_READ_MAIN_CRC: + val = 0x0190; + break; + case IST30XX_ISP_READ_INFO_S: + val = 0x0098; + break; + case IST30XX_ISP_READ_INFO_B: + case IST30XX_ISP_READ_INFO_CRC: + val = 0x0198; + break; + case IST30XX_ISP_PROG_TOTAL_S: + val = 0x8050; + break; + case IST30XX_ISP_PROG_TOTAL_B: + val = 0x8150; + break; + case IST30XX_ISP_PROG_MAIN_S: + val = 0x0050; + break; + case IST30XX_ISP_PROG_MAIN_B: + val = 0x0150; + break; + case IST30XX_ISP_PROG_INFO_S: + val = 0x0058; + break; + case IST30XX_ISP_PROG_INFO_B: + val = 0x0158; + break; + case IST30XX_ISP_ERASE_BLOCK: + val = 0x0031; + break; + case IST30XX_ISP_ERASE_SECTOR: + val = 0x0032; + break; + case IST30XX_ISP_ERASE_PAGE: + val = 0x0030; + break; + case IST30XX_ISP_ERASE_INFO: + val = 0x0038; + break; + default: + tsp_err("ISP fail, unknown mode\n"); + return -EINVAL; + } + +#if (IMAGIS_TSP_IC > IMAGIS_IST3032C) + val &= ~(0x8000); +#endif + + ret = ist30xx_write_cmd(data, IST30XX_FLASH_MODE, val); + if (unlikely(ret)) { + tsp_err("ISP fail, IST30XX_FLASH_MODE\n"); + return ret; + } + + return 0; +} + +int ist30xxc_isp_erase(struct ist30xx_data *data, int mode, u32 index) +{ + int ret = 0; + + tsp_info("%s\n", __func__); + + ret = ist30xxc_isp_mode(data, mode); + if (unlikely(ret)) + return ret; + + ret = ist30xx_write_cmd(data, IST30XX_FLASH_DIN, index); + if (unlikely(ret)) { + tsp_err("ISP fail, IST30XX_FLASH_DIN\n"); + return ret; + } + + ist30xx_delay(40); + + return ret; +} +#ifdef FLASH_USE_PAGE_CONTROL +int ist30xxc_isp_page_erase(struct ist30xx_data *data, u32 addr, u32 index) +{ + int ret = 0; + + tsp_info("%s\n", __func__); + + ret = ist30xxc_isp_mode(data, IST30XX_ISP_ERASE_PAGE); + if (unlikely(ret)) + return ret; + + ret = ist30xx_write_cmd(data, IST30XX_FLASH_ADDR, addr / 4); + if (unlikely(ret)) { + tsp_err("ISP fail, IST30XX_FLASH_ADDR\n"); + return ret; + } + + ret = ist30xx_write_cmd(data, IST30XX_FLASH_DIN, index); + if (unlikely(ret)) { + tsp_err("ISP fail, IST30XX_FLASH_DIN\n"); + return ret; + } + + tsp_info("%s delay 0\n", __func__); + ist30xx_delay(40); + tsp_info("%s delay 1\n", __func__); + + return ret; +} +#endif +int ist30xxc_isp_program(struct ist30xx_data *data, u32 addr, int mode, + const u32 *buf32, int len) +{ + int ret = 0; + + tsp_info("%s\n", __func__); + + ret = ist30xxc_isp_mode(data, mode); + if (unlikely(ret)) + return ret; + + ret = ist30xx_write_cmd(data, IST30XX_FLASH_ADDR, addr); + if (unlikely(ret)) { + tsp_err("ISP fail, IST30XX_FLASH_ADDR\n"); + return ret; + } + + if (mode & 0x10) + ret = ist30xx_isp_write_burst(data->client, IST30XX_FLASH_DIN, + (u32 *)buf32, len); + else + ret = ist30xx_write_buf(data->client, IST30XX_FLASH_DIN, (u32 *)buf32, + len); + + if (unlikely(ret)) { + tsp_err("ISP fail, IST30XX_FLASH_DIN\n"); + return ret; + } + + return ret; +} + +int ist30xxc_isp_read(struct ist30xx_data *data, u32 addr, int mode, u32 *buf32, + int len) +{ + int ret = 0; + + tsp_info("%s\n", __func__); + + ret = ist30xxc_isp_mode(data, mode); + if (unlikely(ret)) + return ret; + + ret = ist30xx_write_cmd(data, IST30XX_FLASH_ADDR, addr); + if (unlikely(ret)) { + tsp_err("ISP fail, IST30XX_FLASH_ADDR\n"); + return ret; + } + + if (mode & 0x10) + ret = ist30xx_isp_read_burst(data->client, IST30XX_FLASH_DOUT, buf32, + len); + else + ret = ist30xx_read_buf(data->client, IST30XX_FLASH_DOUT, buf32, len); + + if (unlikely(ret)) { + tsp_err("ISP fail, IST30XX_FLASH_DOUT\n"); + return ret; + } + + return 0; +} + +int ist30xxc_cmd_read_chksum(struct ist30xx_data *data, int mode, + u32 start_addr, u32 end_addr, u32 *chksum) +{ + int ret = 0; + u32 val = (1 << 28) | (1 << 25) | (1 << 24) | (1 << 20) | (1 << 16); + + val |= (end_addr / IST30XX_ADDR_LEN) - 1; + + ret = ist30xxc_isp_mode(data, mode); + if (unlikely(ret)) + return ret; + + ret = ist30xx_write_cmd(data, IST30XX_FLASH_ADDR, start_addr); + if (unlikely(ret)) { + tsp_err("ISP fail, IST30XX_FLASH_ADDR (%x)\n", val); + return ret; + } + + ret = ist30xx_write_cmd(data, IST30XX_FLASH_AUTO_READ, val); + if (unlikely(ret)) { + tsp_err("ISP fail, IST30XX_FLASH_AUTO_READ (%x)\n", val); + return ret; + } + + ist30xx_delay(100); + + ret = ist30xx_read_reg(data->client, IST30XX_FLASH_CRC, chksum); + if (unlikely(ret)) { + tsp_err("ISP fail, IST30XX_FLASH_CRC (%x)\n", chksum); + return ret; + } + + return 0; +} + +int ist30xxc_read_chksum(struct ist30xx_data *data, u32 *chksum) +{ + int ret = 0; + u32 start_addr, end_addr; + + start_addr = data->tags.fw_addr; + end_addr = data->tags.sensor_addr + data->tags.sensor_size; + ret = ist30xxc_cmd_read_chksum(data, IST30XX_ISP_READ_TOTAL_CRC, start_addr, + end_addr, chksum); + if (unlikely(ret)) + return ret; + + tsp_info("chksum: %x(%x~%x)\n", *chksum, start_addr, end_addr); + + return 0; +} + +int ist30xxc_read_chksum_all(struct ist30xx_data *data, u32 *chksum) +{ + int ret = 0; + u32 start_addr, end_addr; + + start_addr = IST30XX_FLASH_BASE_ADDR; + end_addr = IST30XX_FLASH_BASE_ADDR + IST30XX_FLASH_TOTAL_SIZE; + ret = ist30xxc_cmd_read_chksum(data, IST30XX_ISP_READ_TOTAL_CRC, start_addr, + end_addr, chksum); + if (unlikely(ret)) + return ret; + + tsp_info("chksum: %x(%x~%x)\n", *chksum, start_addr, end_addr); + + return 0; +} + +int ist30xxc_isp_info_read(struct ist30xx_data *data, u32 addr, u32 *buf32, + u32 len) +{ + int ret = 0; + int retry = IST30XX_MAX_RETRY_CNT; + +isp_info_read_retry: + if (retry-- == 0) + goto isp_info_read_end; + + ist30xx_reset(data, true); + + ret = ist30xxc_isp_enable(data, true); + if (unlikely(ret)) + goto isp_info_read_retry; + + ret = ist30xxc_isp_read(data, addr, IST30XX_ISP_READ_INFO_B, buf32, len); + if (unlikely(ret)) + goto isp_info_read_retry; + +isp_info_read_end: + ist30xxc_isp_enable(data, false); + ist30xx_reset(data, false); + + return ret; +} + +int ist30xxc_isp_fw_read(struct ist30xx_data *data, u32 *buf32) +{ + int ret = 0; + int i; + int len; + u32 addr = IST30XX_FLASH_BASE_ADDR; + + ist30xx_reset(data, true); + data->ignore_delay = true; + + ret = ist30xxc_isp_enable(data, true); + if (unlikely(ret)) + return ret; + + for (i = 0; i < IST30XX_FLASH_TOTAL_SIZE; i += I2C_MAX_READ_SIZE) { + len = I2C_MAX_READ_SIZE / IST30XX_DATA_LEN; + if ((IST30XX_FLASH_TOTAL_SIZE - i) < I2C_MAX_READ_SIZE) + len = (IST30XX_FLASH_TOTAL_SIZE - i) / IST30XX_DATA_LEN; + + ret = ist30xxc_isp_read(data, addr, IST30XX_ISP_READ_TOTAL_B, + buf32, len); + if (unlikely(ret)) + goto isp_fw_read_end; + + addr += len; + buf32 += len; + } + +isp_fw_read_end: + data->ignore_delay = false; + ist30xxc_isp_enable(data, false); + ist30xx_reset(data, false); + return ret; +} + +int ist30xxc_isp_fw_update(struct ist30xx_data *data, const u8 *buf) +{ +#ifdef FLASH_USE_PAGE_CONTROL + int i; +#endif + int ret = 0; + int size = 0; +#ifdef FLASH_USE_PAGE_CONTROL + int page_cnt = IST30XX_FLASH_TOTAL_SIZE / IST30XX_FLASH_PAGE_SIZE; +#endif + u32 addr = IST30XX_FLASH_BASE_ADDR; + + tsp_info("%s\n", __func__); + + ist30xx_reset(data, true); + data->ignore_delay = true; + + ret = ist30xxc_isp_enable(data, true); + if (unlikely(ret)) + goto isp_fw_update_end; +#ifdef FLASH_USE_PAGE_CONTROL + for (i = 0; i < (page_cnt - 2); i++) { + ret = ist30xxc_isp_page_erase(data, addr, 0); + if (unlikely(ret)) + goto isp_fw_update_end; + + addr += IST30XX_FLASH_PAGE_SIZE; + } +#else + ret = ist30xxc_isp_erase(data, IST30XX_ISP_ERASE_BLOCK, 0); + if (unlikely(ret)) + goto isp_fw_update_end; +#endif + +#if (IMAGIS_TSP_IC < IMAGIS_IST3038C) + ret = ist30xxc_isp_erase(data, IST30XX_ISP_ERASE_INFO, 0); + if (unlikely(ret)) + goto isp_fw_update_end; +#endif + + ist30xx_reset(data, true); + + ret = ist30xxc_isp_enable(data, true); + if (unlikely(ret)) + goto isp_fw_update_end; + +#ifdef FLASH_USE_PAGE_CONTROL + addr = IST30XX_FLASH_BASE_ADDR; + size = IST30XX_FLASH_TOTAL_SIZE - (IST30XX_FLASH_PAGE_SIZE * 2); +#else + size = IST30XX_FLASH_TOTAL_SIZE; +#endif + ret = ist30xxc_isp_program(data, addr, IST30XX_ISP_PROG_TOTAL_B, (u32 *)buf, + size / IST30XX_DATA_LEN); + if (unlikely(ret)) + goto isp_fw_update_end; + +isp_fw_update_end: + data->ignore_delay = false; + ist30xxc_isp_enable(data, false); + ist30xx_reset(data, false); + msleep(100); + return ret; +} + +u32 ist30xx_parse_ver(struct ist30xx_data *data, int flag, const u8 *buf) +{ + u32 ver = 0; + u32 *buf32 = (u32 *)buf; + + if (flag == FLAG_MAIN) + ver = (u32)buf32[(data->tags.flag_addr + 0x1FC) >> 2]; + else if (flag == FLAG_TEST) + ver = (u32)buf32[(data->tags.flag_addr + 0x1F4) >> 2]; + else if (flag == FLAG_FW) + ver = (u32)(buf32[(data->tags.cfg_addr + 0x4) >> 2] & 0xFFFF); + else if (flag == FLAG_CORE) + ver = (u32)buf32[(data->tags.flag_addr + 0x1F0) >> 2]; + else + tsp_warn("Parsing ver's flag is not corrent!\n"); + + return ver; +} + +int calib_ms_delay = CALIB_WAIT_TIME; +int ist30xx_calib_wait(struct ist30xx_data *data) +{ + int cnt = calib_ms_delay; + + data->status.calib_msg = 0; + while (cnt-- > 0) { + ist30xx_delay(100); + + if (data->status.calib_msg) { + tsp_info("Calibration status : %d, Max raw gap : %d - (%08x)\n", + CALIB_TO_STATUS(data->status.calib_msg), + CALIB_TO_GAP(data->status.calib_msg), + data->status.calib_msg); + if (CALIB_TO_STATUS(data->status.calib_msg) == 0) + return 0; + else + return -EAGAIN; + } + } + tsp_warn("Calibration time out\n"); + + return -EPERM; +} + +int ist30xx_calibrate(struct ist30xx_data *data, int wait_cnt) +{ + int ret = -ENOEXEC; + + tsp_info("*** Calibrate %ds ***\n", calib_ms_delay / 10); + + data->status.calib = 1; + ist30xx_disable_irq(data); + while (1) { + ret = ist30xx_cmd_calibrate(data); + if (unlikely(ret)) + continue; + + ist30xx_enable_irq(data); + ret = ist30xx_calib_wait(data); + if (likely(!ret)) + break; + + ist30xx_disable_irq(data); + + if (--wait_cnt == 0) + break; + + ist30xx_reset(data, false); + } + + ist30xx_disable_irq(data); + ist30xx_reset(data, false); + msleep(100); + data->status.calib = 0; + ist30xx_enable_irq(data); + + return ret; +} + +int ist30xx_cal_ref_wait(struct ist30xx_data *data) +{ + int cnt = calib_ms_delay; + u32 result; + + data->status.cal_ref_msg = 0; + while (cnt-- > 0) { + ist30xx_delay(100); + + if (data->status.cal_ref_msg) { + result = CAL_REF_TO_STATUS(data->status.cal_ref_msg); + tsp_info("Cal reference status : %04X - (%08x)\n", result, + data->status.cal_ref_msg); + if (result & CAL_REF_NONE) { + tsp_warn("Cal reference time out\n"); + return 1; + } else if (result & CAL_REF_OK) { + tsp_warn("Cal reference success\n"); + return 0; + } else { + tsp_warn("Cal reference error\n"); + return -EAGAIN; + } + } + } + tsp_warn("Cal reference time out\n"); + + return -EPERM; +} + +int ist30xx_cal_reference(struct ist30xx_data *data) +{ + int ret = -ENOEXEC; + + tsp_info("*** Cal Reference %ds ***\n", calib_ms_delay / 10); + + data->status.calib = 1; + ist30xx_disable_irq(data); + ret = ist30xx_cmd_cal_reference(data); + if (ret) + goto err_cal_ref; + + ist30xx_enable_irq(data); + ret = ist30xx_cal_ref_wait(data); + +err_cal_ref: + ist30xx_reset(data, false); + msleep(100); + data->status.calib = 0; + ist30xx_enable_irq(data); + + return ret; +} + +int ist30xx_parse_tags(struct ist30xx_data *data, const u8 *buf, const u32 size) +{ + int ret = -EPERM; + struct ist30xx_tags *tags; + + tags = (struct ist30xx_tags *)(&buf[size - sizeof(struct ist30xx_tags)]); + + if (!strncmp(tags->magic1, IST30XX_TAG_MAGIC, sizeof(tags->magic1)) + && !strncmp(tags->magic2, IST30XX_TAG_MAGIC, sizeof(tags->magic2))) { + data->tags = *tags; + + data->tags.fw_addr -= data->tags.rom_base; + data->tags.cfg_addr -= data->tags.rom_base; + data->tags.sensor_addr -= data->tags.rom_base; + data->tags.cp_addr -= data->tags.rom_base; + data->tags.flag_addr -= data->tags.rom_base; + + data->fw.index = data->tags.fw_addr; + data->fw.size = tags->flag_addr - tags->fw_addr + + tags->flag_size; + data->fw.chksum = tags->chksum; + + data->zvalue_addr = data->tags.zvalue_base; + data->raw_addr = data->tags.raw_base; + data->filter_addr = data->tags.filter_base; + data->algorithm_addr = data->tags.algr_base; + + tsp_verb("Tagts magic1: %s, magic2: %s\n", + data->tags.magic1, data->tags.magic2); + tsp_verb(" rom: %x\n", data->tags.rom_base); + tsp_verb(" ram: %x\n", data->tags.ram_base); + tsp_verb(" fw: %x(%x)\n", data->tags.fw_addr, data->tags.fw_size); + tsp_verb(" cfg: %x(%x)\n", data->tags.cfg_addr, data->tags.cfg_size); + tsp_verb(" sensor: %x(%x)\n", + data->tags.sensor_addr, data->tags.sensor_size); + tsp_verb(" cp: %x(%x)\n", data->tags.cp_addr, data->tags.cp_size); + tsp_verb(" flag: %x(%x)\n", data->tags.flag_addr, data->tags.flag_size); + tsp_verb(" zvalue: %x\n", data->tags.zvalue_base); + tsp_verb(" algo: %x\n", data->tags.algr_base); + tsp_verb(" raw: %x\n", data->tags.raw_base); + tsp_verb(" filter: %x\n", data->tags.filter_base); + tsp_verb(" chksum: %x\n", data->tags.chksum); + tsp_verb(" chksum_all: %x\n", data->tags.chksum_all); + tsp_verb(" build time: %04d/%02d/%02d (%02d:%02d:%02d)\n", + data->tags.year, data->tags.month, data->tags.day, + data->tags.hour, data->tags.min, data->tags.sec); + + ret = 0; + } + + return ret; +} + +int ist30xx_get_update_info(struct ist30xx_data *data, const u8 *buf, + const u32 size) +{ + int ret; + + ret = ist30xx_parse_tags(data, buf, size); + if (unlikely(ret != TAGS_PARSE_OK)) + tsp_warn("Cannot find tags of F/W\n"); + + return ret; +} + +#define TSP_INFO_SWAP_XY (1 << 0) +#define TSP_INFO_FLIP_X (1 << 1) +#define TSP_INFO_FLIP_Y (1 << 2) +u32 ist30xx_info_cal_crc(u32 *buf) +{ + int i; + u32 chksum32 = 0; + + for (i = 0; i < IST30XX_MAX_CMD_SIZE - 1; i++) + chksum32 += *buf++; + + return chksum32; +} + +int ist30xx_tsp_update_info(struct ist30xx_data *data) +{ + int ret = 0; + u32 chksum; + u32 info[IST30XX_MAX_CMD_SIZE]; + u32 fw_mode; + u32 tsp_lcd, tsp_swap, tsp_scr, tsp_gtx, tsp_ch; + u32 tkey_info0, tkey_info1, tkey_info2; + u32 finger_info, baseline, threshold; + u32 debugging_info; + TSP_INFO *tsp = &data->tsp_info; +#ifdef IST30XX_USE_KEY + TKEY_INFO *tkey = &data->tkey_info; +#endif + + ret = ist30xx_cmd_hold(data, IST30XX_ENABLE); + if (unlikely(ret)) + return ret; + + ret = ist30xx_burst_read(data->client, IST30XX_DA_ADDR(eHCOM_GET_CHIP_ID), + &info[0], IST30XX_MAX_CMD_SIZE, true); + if (unlikely(ret)) + return ret; + + ret = ist30xx_cmd_hold(data, IST30XX_DISABLE); + if (unlikely(ret)) { + ist30xx_reset(data, false); + return ret; + } + + ret = ist30xx_read_cmd(data, IST30XX_REG_CHIPID, &data->chip_id); + if (unlikely(ret)) + return ret; + + if ((info[IST30XX_CMD_VALUE(eHCOM_GET_CHIP_ID)] != data->chip_id) || + (info[IST30XX_CMD_VALUE(eHCOM_GET_CHIP_ID)] == 0) || + (info[IST30XX_CMD_VALUE(eHCOM_GET_CHIP_ID)] == 0xFFFF)) + return -EINVAL; + + chksum = ist30xx_info_cal_crc((u32 *)info); + if (chksum != info[IST30XX_MAX_CMD_SIZE - 1]) { + tsp_err("info checksum : %08X, %08X\n", chksum, + info[IST30XX_MAX_CMD_SIZE - 1]); + return -EINVAL; + } + tsp_info("info read success\n"); + + fw_mode = info[IST30XX_CMD_VALUE(eHCOM_GET_FW_MODE)]; + tsp_lcd = info[IST30XX_CMD_VALUE(eHCOM_GET_LCD_INFO)]; + tsp_ch = info[IST30XX_CMD_VALUE(eHCOM_GET_TSP_INFO)]; + tkey_info0 = info[IST30XX_CMD_VALUE(eHCOM_GET_KEY_INFO_0)]; + tkey_info1 = info[IST30XX_CMD_VALUE(eHCOM_GET_KEY_INFO_1)]; + tkey_info2 = info[IST30XX_CMD_VALUE(eHCOM_GET_KEY_INFO_2)]; + tsp_scr = info[IST30XX_CMD_VALUE(eHCOM_GET_SCR_INFO)]; + tsp_gtx = info[IST30XX_CMD_VALUE(eHCOM_GET_GTX_INFO)]; + tsp_swap = info[IST30XX_CMD_VALUE(eHCOM_GET_SWAP_INFO)]; + finger_info = info[IST30XX_CMD_VALUE(eHCOM_GET_FINGER_INFO)]; + baseline = info[IST30XX_CMD_VALUE(eHCOM_GET_BASELINE)]; + threshold = info[IST30XX_CMD_VALUE(eHCOM_GET_TOUCH_TH)]; + debugging_info = info[IST30XX_CMD_VALUE(eHCOM_GET_DBG_INFO_BASE)]; + data->raw_addr = info[IST30XX_CMD_VALUE(eHCOM_GET_RAW_BASE)]; + data->filter_addr = info[IST30XX_CMD_VALUE(eHCOM_GET_FILTER_BASE)]; + data->zvalue_addr = info[IST30XX_CMD_VALUE(eHCOM_GET_ZVALUE_BASE)]; + data->algorithm_addr = info[IST30XX_CMD_VALUE(eHCOM_GET_ALGO_BASE)]; + + if (fw_mode == IST30XX_NON_CAL_MODE) + data->fw_mode = IST30XX_NON_CAL_MODE; + else + data->fw_mode = IST30XX_CAL_MODE; + + data->debugging_addr = debugging_info & 0x00FFFFFF; + data->debugging_size = (debugging_info >> 24) & 0xFF; + + tsp->ch_num.rx = (tsp_ch >> 16) & 0xFFFF; + tsp->ch_num.tx = tsp_ch & 0xFFFF; + + tsp->node.len = tsp->ch_num.tx * tsp->ch_num.rx; + + tsp->gtx.num = (tsp_gtx >> 24) & 0xFF; + tsp->gtx.ch_num[0] = (tsp_gtx >> 16) & 0xFF; + tsp->gtx.ch_num[1] = (tsp_gtx >> 8) & 0xFF; + tsp->gtx.ch_num[2] = 0xFF; + tsp->gtx.ch_num[3] = 0xFF; + + tsp->finger_num = finger_info; + tsp->dir.swap_xy = (tsp_swap & TSP_INFO_SWAP_XY ? true : false); + tsp->dir.flip_x = (tsp_swap & TSP_INFO_FLIP_X ? true : false); + tsp->dir.flip_y = (tsp_swap & TSP_INFO_FLIP_Y ? true : false); + + tsp->baseline = baseline & 0xFFFF; + + tsp->screen.rx = (tsp_scr >> 16) & 0xFFFF; + tsp->screen.tx = tsp_scr & 0xFFFF; + + if (tsp->dir.swap_xy) { + tsp->width = tsp_lcd & 0xFFFF; + tsp->height = (tsp_lcd >> 16) & 0xFFFF; + } else { + tsp->width = (tsp_lcd >> 16) & 0xFFFF; + tsp->height = tsp_lcd & 0xFFFF; + } + +#ifdef IST30XX_USE_KEY + tkey->enable = (((tkey_info0 >> 24) & 0xFF) ? true : false); + tkey->key_num = (tkey_info0 >> 16) & 0xFF; + tkey->ch_num[0].tx = tkey_info0 & 0xFF; + tkey->ch_num[0].rx = (tkey_info0 >> 8) & 0xFF; + tkey->ch_num[1].tx = (tkey_info1 >> 16) & 0xFF; + tkey->ch_num[1].rx = (tkey_info1 >> 24) & 0xFF; + tkey->ch_num[2].tx = tkey_info1 & 0xFF; + tkey->ch_num[2].rx = (tkey_info1 >> 8) & 0xFF; + tkey->ch_num[3].tx = (tkey_info2 >> 16) & 0xFF; + tkey->ch_num[3].rx = (tkey_info2 >> 24) & 0xFF; + tkey->baseline = (baseline >> 16) & 0xFFFF; +#endif + + return ret; +} + +int ist30xx_get_tsp_info(struct ist30xx_data *data) +{ + int ret = 0; + int retry = 3; +#ifdef IST30XX_INTERNAL_BIN + TSP_INFO *tsp = &data->tsp_info; +#ifdef IST30XX_USE_KEY + TKEY_INFO *tkey = &data->tkey_info; +#endif + u8 *cfg_buf; +#endif + + while (retry--) { + ret = ist30xx_tsp_update_info(data); + if (ret == 0) { + tsp_info("tsp update info success!\n"); + return ret; + } + } + +#ifdef IST30XX_INTERNAL_BIN + cfg_buf = (u8 *)&data->fw.buf[data->tags.cfg_addr]; + + tsp->ch_num.rx = (u8)cfg_buf[0x0C]; + tsp->ch_num.tx = (u8)cfg_buf[0x0D]; + tsp->screen.rx = (u8)cfg_buf[0x0E]; + tsp->screen.tx = (u8)cfg_buf[0x0F]; + tsp->node.len = tsp->ch_num.tx * tsp->ch_num.rx; + + tsp->gtx.num = (u8)cfg_buf[0x10]; + tsp->gtx.ch_num[0] = (u8)cfg_buf[0x11]; + tsp->gtx.ch_num[1] = (u8)cfg_buf[0x12]; + tsp->gtx.ch_num[2] = (u8)cfg_buf[0x13]; + tsp->gtx.ch_num[3] = (u8)cfg_buf[0x14]; + + tsp->finger_num = (u8)cfg_buf[0x38]; + tsp->dir.swap_xy = (bool)(cfg_buf[0x39] & TSP_INFO_SWAP_XY ? true : false); + tsp->dir.flip_x = (bool)(cfg_buf[0x39] & TSP_INFO_FLIP_X ? true : false); + tsp->dir.flip_y = (bool)(cfg_buf[0x39] & TSP_INFO_FLIP_Y ? true : false); + + tsp->baseline = (u16)((cfg_buf[0x29] << 8) | cfg_buf[0x28]); + + if (tsp->dir.swap_xy) { + tsp->width = (u16)((cfg_buf[0x23] << 8) | cfg_buf[0x22]); + tsp->height = (u16)((cfg_buf[0x21] << 8) | cfg_buf[0x20]); + } else { + tsp->width = (u16)((cfg_buf[0x21] << 8) | cfg_buf[0x20]); + tsp->height = (u16)((cfg_buf[0x23] << 8) | cfg_buf[0x22]); + } + +#ifdef IST30XX_USE_KEY + tkey->enable = (bool)(cfg_buf[0x15] & 1); + tkey->key_num = (u8)cfg_buf[0x16]; + tkey->ch_num[0].tx = (u8)cfg_buf[0x17]; + tkey->ch_num[0].rx = (u8)cfg_buf[0x1B]; + tkey->ch_num[1].tx = (u8)cfg_buf[0x18]; + tkey->ch_num[1].rx = (u8)cfg_buf[0x1C]; + tkey->ch_num[2].tx = (u8)cfg_buf[0x19]; + tkey->ch_num[2].rx = (u8)cfg_buf[0x1D]; + tkey->ch_num[3].tx = (u8)cfg_buf[0x1A]; + tkey->ch_num[3].rx = (u8)cfg_buf[0x1E]; + + tkey->baseline = (u16)((cfg_buf[0x2B] << 8) | cfg_buf[0x2A]); +#endif +#endif + + return ret; +} + +void ist30xx_print_info(struct ist30xx_data *data) +{ + TSP_INFO *tsp = &data->tsp_info; + TKEY_INFO *tkey = &data->tkey_info; + + tsp_info("*** TSP/TKEY info ***\n"); + if (data->fw_mode == IST30XX_CAL_MODE) + tsp_info("FW Mode : Cal Mode\n"); + else + tsp_info("FW Mode : Non Cal Mode\n"); + tsp_info("TSP info: \n"); + tsp_info(" finger num: %d\n", tsp->finger_num); + tsp_info(" dir swap: %d, flip x: %d, y: %d\n", + tsp->dir.swap_xy, tsp->dir.flip_x, tsp->dir.flip_y); + tsp_info(" baseline: %d\n", tsp->baseline); + tsp_info(" ch_num tx: %d, rx: %d\n", tsp->ch_num.tx, tsp->ch_num.rx); + tsp_info(" screen tx: %d, rx: %d\n", tsp->screen.tx, tsp->screen.rx); + tsp_info(" width: %d, height: %d\n", tsp->width, tsp->height); + tsp_info(" gtx num: %d\n", tsp->gtx.num); + tsp_info(" [1]: %d, [2]: %d, [3]: %d, [4]: %d\n", tsp->gtx.ch_num[0], + tsp->gtx.ch_num[1], tsp->gtx.ch_num[2], tsp->gtx.ch_num[3]); + tsp_info(" node len: %d\n", tsp->node.len); + tsp_info("TKEY info: \n"); + tsp_info(" enable: %d, key num: %d\n", tkey->enable, tkey->key_num); + tsp_info(" [1]: %d,%d [2]: %d,%d [3]: %d,%d [4]: %d,%d\n", + tkey->ch_num[0].tx, tkey->ch_num[0].rx, tkey->ch_num[1].tx, + tkey->ch_num[1].rx, tkey->ch_num[2].tx, tkey->ch_num[2].rx, + tkey->ch_num[3].tx, tkey->ch_num[3].rx); + tsp_info(" baseline : %d\n", tkey->baseline); +} + +#define update_next_step(ret) { if (unlikely(ret)) goto end; } +int ist30xx_fw_update(struct ist30xx_data *data, const u8 *buf, int size) +{ + int ret = 0; + u32 chksum = 0; + struct ist30xx_fw *fw = &data->fw; + + tsp_info("*** Firmware update ***\n"); + tsp_info(" main: %x, fw: %x, test: %x, core: %x(addr: 0x%x ~ 0x%x)\n", + fw->bin.main_ver, fw->bin.fw_ver, fw->bin.test_ver, fw->bin.core_ver, + fw->index, (fw->index + fw->size)); + + data->status.update = 1; + data->status.update_result = 0; + + ist30xx_disable_irq(data); + + ret = ist30xxc_isp_fw_update(data, buf); + update_next_step(ret); + + ret = ist30xx_read_cmd(data, eHCOM_GET_CRC32, &chksum); + if (unlikely((ret) || (chksum != fw->chksum))) { + if (unlikely(ret)) + ist30xx_reset(data, false); + + goto end; + } + + ret = ist30xx_get_ver_info(data); + update_next_step(ret); + +end: + if (unlikely(ret)) { + data->status.update_result = 1; + tsp_warn("Firmware update Fail!, ret=%d\n", ret); + } else if (unlikely(chksum != fw->chksum)) { + data->status.update_result = 1; + tsp_warn("Error CheckSum: %x(%x)\n", chksum, fw->chksum); + ret = -ENOEXEC; + } + + ist30xx_enable_irq(data); + + data->status.update = 2; + + return ret; +} + +int ist30xx_fw_recovery(struct ist30xx_data *data) +{ + int ret = -EPERM; + u8 *fw = data->fw.buf; + int fw_size = data->fw.buf_size; + + ret = ist30xx_get_update_info(data, fw, fw_size); + if (ret) { + data->status.update_result = 1; + return ret; + } + + data->fw.bin.main_ver = ist30xx_parse_ver(data, FLAG_MAIN, fw); + data->fw.bin.fw_ver = ist30xx_parse_ver(data, FLAG_FW, fw); + data->fw.bin.test_ver = ist30xx_parse_ver(data, FLAG_TEST, fw); + data->fw.bin.core_ver = ist30xx_parse_ver(data, FLAG_CORE, fw); + + mutex_lock(&data->lock); + ret = ist30xx_fw_update(data, fw, fw_size); + if (ret == 0) { + ist30xx_get_tsp_info(data); + ist30xx_print_info(data); +#ifndef IST30XX_UPDATE_NO_CAL + if (data->fw_mode == IST30XX_CAL_MODE) + ist30xx_calibrate(data, 1); +#endif + } + mutex_unlock(&data->lock); + + ist30xx_start(data); + + return ret; +} + +#ifdef IST30XX_INTERNAL_BIN +int ist30xx_check_fw(struct ist30xx_data *data) +{ + int ret; + u32 chksum; + + ret = ist30xx_read_cmd(data, eHCOM_GET_CRC32, &chksum); + if (unlikely(ret)) { + ist30xx_reset(data, false); + return ret; + } + + if (unlikely(chksum != data->fw.chksum)) { + tsp_warn("Checksum compare error, (IC: %08x, Bin: %08x)\n", + chksum, data->fw.chksum); + return -EPERM; + } + + return 0; +} + +#define MAIN_VER_MASK 0xFF000000 +int ist30xx_check_auto_update(struct ist30xx_data *data) +{ + int ret = 0; + int retry = IST30XX_MAX_RETRY_CNT; + u32 chip_id = 0; + bool tsp_check = false; + u32 chksum; + struct ist30xx_fw *fw = &data->fw; + + while (retry--) { + ret = ist30xx_read_cmd(data, eHCOM_GET_CHIP_ID, &chip_id); + if (likely(ret == 0)) { + if (likely(chip_id == IST30XX_CHIP_ID)) + tsp_check = true; + + break; + } + + ist30xx_reset(data, false); + } + + if (unlikely(!tsp_check)) + goto fw_check_end; + + ist30xx_get_ver_info(data); + + if (likely((fw->cur.fw_ver > 0) && (fw->cur.fw_ver <= 0xFFFF))) { + if (unlikely(((fw->cur.main_ver & MAIN_VER_MASK) == MAIN_VER_MASK) || + ((fw->cur.main_ver & MAIN_VER_MASK) == 0))) + goto fw_check_end; + + tsp_info("Version compare IC: %x(%x), BIN: %x(%x)\n", fw->cur.fw_ver, + fw->cur.main_ver, fw->bin.fw_ver, fw->bin.main_ver); + + /* If FW version is same, check FW checksum */ + if (likely((fw->cur.main_ver == fw->bin.main_ver) && + (fw->cur.fw_ver == fw->bin.fw_ver) && + (fw->cur.test_ver == 0))) { + ret = ist30xx_read_cmd(data, eHCOM_GET_CRC32, &chksum); + if (unlikely((ret) || (chksum != fw->chksum))) { + tsp_warn("Checksum error, IC: %x, Bin: %x (ret: %d)\n", + chksum, fw->chksum, ret); + goto fw_check_end; + } + } + + /* + * fw->cur.main_ver : Main version in TSP IC + * fw->cur.fw_ver : FW version if TSP IC + * fw->bin.main_ver : Main version in FW Binary + * fw->bin.fw_ver : FW version in FW Binary + */ + /* If the ver of binary is higher than ver of IC, FW update operate. */ + + if (likely((fw->cur.main_ver >= fw->bin.main_ver) && + (fw->cur.fw_ver >= fw->bin.fw_ver))) + return 0; + } + +fw_check_end: + return -EAGAIN; +} + +int ist30xx_auto_bin_update(struct ist30xx_data *data) +{ + int ret = 0; + int retry = IST30XX_MAX_RETRY_CNT; + u32 fw_mode = 0; + struct ist30xx_fw *fw = &data->fw; + +#ifdef XIAOMI_PRODUCT + if (data->pid == C6_PID) { + fw->buf = (u8 *)ist30xxc_fw; + fw->buf_size = sizeof(ist30xxc_fw); + } else { + fw->buf = (u8 *)ist30xxc_fw; + fw->buf_size = sizeof(ist30xxc_fw); + } +#else + fw->buf = (u8 *)ist30xxc_fw; + fw->buf_size = sizeof(ist30xxc_fw); +#endif + + ret = ist30xx_get_update_info(data, fw->buf, fw->buf_size); + if (unlikely(ret)) + return 1; + + fw->bin.main_ver = ist30xx_parse_ver(data, FLAG_MAIN, fw->buf); + fw->bin.fw_ver = ist30xx_parse_ver(data, FLAG_FW, fw->buf); + fw->bin.test_ver = ist30xx_parse_ver(data, FLAG_TEST, fw->buf); + fw->bin.core_ver = ist30xx_parse_ver(data, FLAG_CORE, fw->buf); + + tsp_info("IC: %x, Binary ver main: %x, fw: %x, test: %x, core: %x\n", + data->chip_id, fw->bin.main_ver, fw->bin.fw_ver, fw->bin.test_ver, + fw->bin.core_ver); + + mutex_lock(&data->lock); + ret = ist30xx_check_auto_update(data); + mutex_unlock(&data->lock); + + if (likely(ret >= 0)) + return ret; + +update_bin: + tsp_info("Update version. fw(main, test, core): %x(%x, %x, %x) -> " + "%x(%x, %x, %x)\n", fw->cur.fw_ver, fw->cur.main_ver, + fw->cur.test_ver, fw->cur.core_ver, fw->bin.fw_ver, + fw->bin.main_ver, fw->bin.test_ver, fw->bin.core_ver); + + mutex_lock(&data->lock); + while (retry--) { + ret = ist30xx_fw_update(data, fw->buf, fw->buf_size); + if (unlikely(!ret)) + break; + } + mutex_unlock(&data->lock); + + if (unlikely(ret)) + goto end_update; + + if (unlikely(retry > 0 && ist30xx_check_fw(data))) + goto update_bin; + + ret = ist30xx_read_cmd(data, eHCOM_GET_FW_MODE, &fw_mode); + if (unlikely(ret)) { + data->fw_mode = IST30XX_CAL_MODE; + } else { + if (fw_mode == IST30XX_NON_CAL_MODE) + data->fw_mode = IST30XX_NON_CAL_MODE; + else + data->fw_mode = IST30XX_CAL_MODE; + } + +#ifndef IST30XX_UPDATE_NO_CAL + if (data->fw_mode == IST30XX_CAL_MODE) { + mutex_lock(&data->lock); + ist30xx_calibrate(data, IST30XX_MAX_RETRY_CNT); + mutex_unlock(&data->lock); + } +#endif + +end_update: + return ret; +} +#endif + +#define MAX_FILE_PATH 255 +const u8 fwbuf[IST30XX_FLASH_TOTAL_SIZE + sizeof(struct ist30xx_tags)]; +/* sysfs: /sys/class/touch/firmware/firmware */ +ssize_t ist30xx_fw_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + int fw_size = 0; + u8 *fw = NULL; + mm_segment_t old_fs = { 0 }; + struct file *fp = NULL; + long fsize = 0, nread = 0; + char fw_path[MAX_FILE_PATH]; + const struct firmware *request_fw = NULL; + int mode = 0; + int calib = 1; + struct ist30xx_data *data = dev_get_drvdata(dev); + + sscanf(buf, "%d %d", &mode, &calib); + + switch (mode) { + case MASK_UPDATE_INTERNAL: +#ifdef IST30XX_INTERNAL_BIN + fw = data->fw.buf; + fw_size = data->fw.buf_size; +#else + data->status.update_result = 1; + tsp_warn("Not support internal bin!!\n"); + return size; +#endif + break; + + case MASK_UPDATE_FW: + ret = request_firmware(&request_fw, IST30XX_FW_NAME, + &data->client->dev); + if (ret) { + data->status.update_result = 1; + tsp_warn("File not found, %s\n", IST30XX_FW_NAME); + return size; + } + + fw = (u8 *)request_fw->data; + fw_size = (u32)request_fw->size; + tsp_info("firmware is loaded!!\n"); + break; + + case MASK_UPDATE_SDCARD: + old_fs = get_fs(); + set_fs(get_ds()); + + snprintf(fw_path, MAX_FILE_PATH, "/sdcard/%s", IST30XX_FW_NAME); + fp = filp_open(fw_path, O_RDONLY, 0); + if (IS_ERR(fp)) { + data->status.update_result = 1; + tsp_info("file %s open error:%d\n", fw_path, PTR_ERR(fp)); + goto err_file_open; + } + + fsize = fp->f_path.dentry->d_inode->i_size; + + if (sizeof(fwbuf) != fsize) { + data->status.update_result = 1; + tsp_info("mismatch fw size\n"); + goto err_fw_size; + } + + nread = vfs_read(fp, (char __user *)fwbuf, fsize, &fp->f_pos); + if (nread != fsize) { + data->status.update_result = 1; + tsp_info("mismatch fw size\n"); + goto err_fw_size; + } + + fw = (u8 *)fwbuf; + fw_size = (u32)fsize; + + filp_close(fp, current->files); + tsp_info("firmware is loaded!!\n"); + break; + + case MASK_UPDATE_ERASE: + tsp_info("EEPROM all erase!!\n"); + + mutex_lock(&data->lock); + ist30xx_disable_irq(data); + ist30xx_reset(data, true); + data->ignore_delay = true; + ist30xxc_isp_enable(data, true); + ist30xxc_isp_erase(data, IST30XX_ISP_ERASE_BLOCK, 0); +#if (IMAGIS_TSP_IC < IMAGIS_IST3038C) + ist30xxc_isp_erase(data, IST30XX_ISP_ERASE_INFO, 0); +#endif + ist30xxc_isp_enable(data, false); + data->ignore_delay = false; + ist30xx_reset(data, false); + ist30xx_start(data); + ist30xx_enable_irq(data); + mutex_unlock(&data->lock); + + default: + return size; + } + + ret = ist30xx_get_update_info(data, fw, fw_size); + if (ret) { + data->status.update_result = 1; + goto err_get_info; + } + + data->fw.bin.main_ver = ist30xx_parse_ver(data, FLAG_MAIN, fw); + data->fw.bin.fw_ver = ist30xx_parse_ver(data, FLAG_FW, fw); + data->fw.bin.test_ver = ist30xx_parse_ver(data, FLAG_TEST, fw); + data->fw.bin.core_ver = ist30xx_parse_ver(data, FLAG_CORE, fw); + + mutex_lock(&data->lock); + ret = ist30xx_fw_update(data, fw, fw_size); + if (ret == 0) { + ist30xx_get_tsp_info(data); + ist30xx_print_info(data); + if (calib) { + if (data->fw_mode == IST30XX_CAL_MODE) + ist30xx_calibrate(data, 1); + else if (data->fw_mode == IST30XX_NON_CAL_MODE) + ist30xx_cal_reference(data); + } + } + mutex_unlock(&data->lock); + + ist30xx_start(data); + +err_get_info: + if (request_fw != NULL) + release_firmware(request_fw); + + if (fp) { +err_fw_size: + filp_close(fp, NULL); +err_file_open: + set_fs(old_fs); + } + + return size; +} + +/* sysfs: /sys/class/touch/firmware/fw_sdcard */ +ssize_t ist30xx_fw_sdcard_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret = 0; + mm_segment_t old_fs = { 0 }; + struct file *fp = NULL; + long fsize = 0, nread = 0; + char fw_path[MAX_FILE_PATH]; + struct ist30xx_data *data = dev_get_drvdata(dev); + + old_fs = get_fs(); + set_fs(get_ds()); + + snprintf(fw_path, MAX_FILE_PATH, "/sdcard/%s", + IST30XX_FW_NAME); + fp = filp_open(fw_path, O_RDONLY, 0); + if (IS_ERR(fp)) { + data->status.update_result = 1; + tsp_info("file %s open error:%d\n", fw_path, PTR_ERR(fp)); + goto err_file_open; + } + + fsize = fp->f_path.dentry->d_inode->i_size; + + if (sizeof(fwbuf) != fsize) { + data->status.update_result = 1; + tsp_info("mismatch fw size\n"); + goto err_fw_size; + } + + nread = vfs_read(fp, (char __user *)fwbuf, fsize, &fp->f_pos); + if (nread != fsize) { + data->status.update_result = 1; + tsp_info("mismatch fw size\n"); + goto err_fw_size; + } + + filp_close(fp, current->files); + tsp_info("firmware is loaded!!\n"); + + ret = ist30xx_get_update_info(data, fwbuf, fsize); + if (ret) { + data->status.update_result = 1; + goto err_get_info; + } + + data->fw.bin.main_ver = ist30xx_parse_ver(data, FLAG_MAIN, fwbuf); + data->fw.bin.fw_ver = ist30xx_parse_ver(data, FLAG_FW, fwbuf); + data->fw.bin.test_ver = ist30xx_parse_ver(data, FLAG_TEST, fwbuf); + data->fw.bin.core_ver = ist30xx_parse_ver(data, FLAG_CORE, fwbuf); + + mutex_lock(&data->lock); + ret = ist30xx_fw_update(data, fwbuf, fsize); + if (ret == 0) { + ist30xx_get_tsp_info(data); + ist30xx_print_info(data); + } + mutex_unlock(&data->lock); + + ist30xx_start(data); + +err_get_info: +err_fw_size: + filp_close(fp, NULL); +err_file_open: + set_fs(old_fs); + + return 0; +} + +/* sysfs: /sys/class/touch/firmware/firmware */ +ssize_t ist30xx_fw_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int count; + struct ist30xx_data *data = dev_get_drvdata(dev); + + switch (data->status.update) { + case 1: + count = sprintf(buf, "Downloading\n"); + break; + case 2: + if (data->status.update_result) { + count = sprintf(buf, "Update fail\n"); + } else { + count = sprintf(buf, "Update success, " + "ver %x(%x, %x, %x)-> %x(%x, %x, %x), " + "status : %d, gap : %d\n", + data->fw.prev.fw_ver, data->fw.prev.main_ver, + data->fw.prev.test_ver, data->fw.prev.core_ver, + data->fw.cur.fw_ver, data->fw.cur.main_ver, + data->fw.cur.test_ver, data->fw.cur.core_ver, + CALIB_TO_STATUS(data->status.calib_msg), + CALIB_TO_GAP(data->status.calib_msg)); + } + break; + default: + if (data->status.update_result) + count = sprintf(buf, "Update fail\n"); + else + count = sprintf(buf, "Pass\n"); + } + + return count; +} + +/* sysfs: /sys/class/touch/firmware/fw_read */ +u32 buf32_flash[IST30XX_FLASH_TOTAL_SIZE / IST30XX_DATA_LEN]; +ssize_t ist30xx_fw_read_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int i; + int ret; + int count; + mm_segment_t old_fs = { 0 }; + struct file *fp = NULL; + char fw_path[MAX_FILE_PATH]; + u8 *buf8 = (u8 *)buf32_flash; + struct ist30xx_data *data = dev_get_drvdata(dev); + + mutex_lock(&data->lock); + ist30xx_disable_irq(data); + + ret = ist30xxc_isp_fw_read(data, buf32_flash); + if (ret) { + count = sprintf(buf, "Fail\n"); + tsp_err("isp fw read fail\n"); + goto err_file_open; + } + + for (i = 0; i < IST30XX_FLASH_TOTAL_SIZE; i += 16) { + tsp_debug("%07x: %02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x\n", i, + buf8[i], buf8[i + 1], buf8[i + 2], buf8[i + 3], + buf8[i + 4], buf8[i + 5], buf8[i + 6], buf8[i + 7], + buf8[i + 8], buf8[i + 9], buf8[i + 10], buf8[i + 11], + buf8[i + 12], buf8[i + 13], buf8[i + 14], buf8[i + 15]); + } + + old_fs = get_fs(); + set_fs(get_ds()); + + snprintf(fw_path, MAX_FILE_PATH, "/sdcard/%s", IST30XX_BIN_NAME); + fp = filp_open(fw_path, O_CREAT|O_WRONLY|O_TRUNC, 0); + if (IS_ERR(fp)) { + count = sprintf(buf, "Fail\n"); + tsp_err("file %s open error:%d\n", fw_path, PTR_ERR(fp)); + goto err_file_open; + } + + fp->f_op->write(fp, buf8, IST30XX_FLASH_TOTAL_SIZE, &fp->f_pos); + fput(fp); + + filp_close(fp, NULL); + set_fs(old_fs); + + count = sprintf(buf, "OK\n"); + +err_file_open: + ist30xx_enable_irq(data); + mutex_unlock(&data->lock); + + ist30xx_start(data); + + return count; +} + +/* sysfs: /sys/class/touch/firmware/version */ +ssize_t ist30xx_fw_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int count; + struct ist30xx_data *data = dev_get_drvdata(dev); + + count = sprintf(buf, "ID: %x, main: %x, fw: %x, test: %x, core: %x\n", + data->chip_id, data->fw.cur.main_ver, data->fw.cur.fw_ver, + data->fw.cur.test_ver, data->fw.cur.core_ver); + +#ifdef IST30XX_INTERNAL_BIN + { + char msg[128]; + int ret = 0; + + ret = ist30xx_get_update_info(data, data->fw.buf, data->fw.buf_size); + if (ret == 0) { + count += sprintf(msg, + " Header - main: %x, fw: %x, test: %x, core: %x\n", + ist30xx_parse_ver(data, FLAG_MAIN, data->fw.buf), + ist30xx_parse_ver(data, FLAG_FW, data->fw.buf), + ist30xx_parse_ver(data, FLAG_TEST, data->fw.buf), + ist30xx_parse_ver(data, FLAG_CORE, data->fw.buf)); + strcat(buf, msg); + } + } +#endif + + return count; +} + +#ifdef XIAOMI_PRODUCT +/* sysfs: /sys/class/touch/firmware/lockdown */ +ssize_t ist30xx_lockdown_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + tsp_info("lockdown : %08X%08X\n", data->fw.cur.lockdown[0], + data->fw.cur.lockdown[1]); + + return sprintf(buf, "%08X%08X\n", data->fw.cur.lockdown[0], + data->fw.cur.lockdown[1]); +} + +/* sysfs: /sys/class/touch/firmware/config */ +ssize_t ist30xx_config_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ist30xx_data *data = dev_get_drvdata(dev); + + tsp_info("config : %08X%08X\n", data->fw.cur.config[0], + data->fw.cur.config[1]); + + return sprintf(buf, "%08X%08X", data->fw.cur.config[0], + data->fw.cur.config[1]); +} +#endif + +/* sysfs */ +static DEVICE_ATTR(fw_read, S_IRWXUGO, ist30xx_fw_read_show, NULL); +static DEVICE_ATTR(firmware, S_IRWXUGO, ist30xx_fw_status_show, + ist30xx_fw_store); +static DEVICE_ATTR(fw_sdcard, S_IRWXUGO, ist30xx_fw_sdcard_show, NULL); +static DEVICE_ATTR(version, S_IRWXUGO, ist30xx_fw_version_show, NULL); +#ifdef XIAOMI_PRODUCT +static DEVICE_ATTR(lockdown, S_IRWXUGO, ist30xx_lockdown_show, NULL); +static DEVICE_ATTR(config, S_IRWXUGO, ist30xx_config_show, NULL); +#endif + +struct class *ist30xx_class; +struct device *ist30xx_fw_dev; + +static struct attribute *fw_attributes[] = { + &dev_attr_fw_read.attr, + &dev_attr_firmware.attr, + &dev_attr_fw_sdcard.attr, + &dev_attr_version.attr, +#ifdef XIAOMI_PRODUCT + &dev_attr_lockdown.attr, + &dev_attr_config.attr, +#endif + NULL, +}; + +static struct attribute_group fw_attr_group = { + .attrs = fw_attributes, +}; + +int ist30xx_init_update_sysfs(struct ist30xx_data *data) +{ + /* /sys/class/touch */ + ist30xx_class = class_create(THIS_MODULE, "touch"); + + /* /sys/class/touch/firmware */ + ist30xx_fw_dev = device_create(ist30xx_class, NULL, 0, data, "firmware"); + + /* /sys/class/touch/firmware/... */ + if (unlikely(sysfs_create_group(&ist30xx_fw_dev->kobj, &fw_attr_group))) + tsp_err("Failed to create sysfs group(%s)!\n", "firmware"); + + data->status.update = 0; + data->status.calib = 0; + data->status.update_result = 0; + + return 0; +} diff --git a/drivers/input/touchscreen/ist3038c/ist30xxc_update.h b/drivers/input/touchscreen/ist3038c/ist30xxc_update.h new file mode 100644 index 0000000000000..004082b74ef69 --- /dev/null +++ b/drivers/input/touchscreen/ist3038c/ist30xxc_update.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2010, Imagis Technology Co. Ltd. All Rights Reserved. + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __IST30XXC_UPDATE_H__ +#define __IST30XXC_UPDATE_H__ + + +#define IST30XX_FLASH_BASE_ADDR (0x0) +#if (IMAGIS_TSP_IC < IMAGIS_IST3038C) +#define IST30XX_FLASH_TOTAL_SIZE (0x8400) +#else +#define IST30XX_FLASH_TOTAL_SIZE (0xFC00) +#define IST30XX_FLASH_PAGE_SIZE (0x0400) +#endif + + +#define IST30XX_FLASH_BASE (0x40006000) +#define IST30XX_FLASH_MODE IST30XX_DA_ADDR(IST30XX_FLASH_BASE | 0x00) +#define IST30XX_FLASH_ADDR IST30XX_DA_ADDR(IST30XX_FLASH_BASE | 0x04) +#define IST30XX_FLASH_DIN IST30XX_DA_ADDR(IST30XX_FLASH_BASE | 0x08) +#define IST30XX_FLASH_DOUT IST30XX_DA_ADDR(IST30XX_FLASH_BASE | 0x0C) +#define IST30XX_FLASH_ISPEN IST30XX_DA_ADDR(IST30XX_FLASH_BASE | 0x10) +#define IST30XX_FLASH_AUTO_READ IST30XX_DA_ADDR(IST30XX_FLASH_BASE | 0x14) +#define IST30XX_FLASH_CRC IST30XX_DA_ADDR(IST30XX_FLASH_BASE | 0x18) +#define IST30XX_FLASH_TEST_MODE1 IST30XX_DA_ADDR(IST30XX_FLASH_BASE | 0x30) +#define IST30XX_FLASH_STATUS IST30XX_DA_ADDR(IST30XX_FLASH_BASE | 0x90) + + +#define IST30XX_FW_NAME "ist30xxc.fw" +#define IST30XX_BIN_NAME "ist30xxc.bin" + + +#define CALIB_WAIT_TIME (50) /* unit : 100msec */ +#define CALIB_TO_GAP(n) ((n >> 16) & 0xFFF) +#define CALIB_TO_STATUS(n) ((n >> 12) & 0xF) +#define CALIB_TO_OS_VALUE(n) ((n >> 12) & 0xFFFF) + + +#define CAL_REF_TO_STATUS(n) ((n >> 8) & 0xFFFF) +#define CAL_REF_NONE (1 << 0) +#define CAL_REF_OK (1 << 4) +#define CAL_REF_OK_VERIFY (1 << 5) +#define CAL_REF_FAIL_UNKNOWN (1 << 8) +#define CAL_REF_FAIL_CRC (1 << 9) +#define CAL_REF_FAIL_VERIFY (1 << 10) + + +#define MASK_UPDATE_INTERNAL (1) +#define MASK_UPDATE_FW (2) +#define MASK_UPDATE_SDCARD (3) +#define MASK_UPDATE_ERASE (4) + + +#define FLAG_MAIN (1) +#define FLAG_FW (2) +#define FLAG_CORE (3) +#define FLAG_TEST (4) + +int ist30xxc_read_chksum(struct ist30xx_data *data, u32 *chksum); +int ist30xxc_read_chksum_all(struct ist30xx_data *data, u32 *chksum); + +int ist30xxc_isp_enable(struct ist30xx_data *data, bool enable); +int ist30xxc_isp_info_read(struct ist30xx_data *data, u32 addr, u32 *buf32, + u32 len); + +int ist30xx_get_update_info(struct ist30xx_data *data, const u8 *buf, + const u32 size); +int ist30xx_get_tsp_info(struct ist30xx_data *data); +void ist30xx_print_info(struct ist30xx_data *data); +u32 ist30xx_parse_ver(struct ist30xx_data *data, int flag, const u8 *buf); + +int ist30xx_fw_update(struct ist30xx_data *data, const u8 *buf, int size); +int ist30xx_fw_recovery(struct ist30xx_data *data); + +int ist30xx_auto_bin_update(struct ist30xx_data *data); + +int ist30xx_calibrate(struct ist30xx_data *data, int wait_cnt); +int ist30xx_cal_reference(struct ist30xx_data *data); + +int ist30xx_init_update_sysfs(struct ist30xx_data *data); + +#endif diff --git a/drivers/power/qpnp-smbcharger.c b/drivers/power/qpnp-smbcharger.c index 473c314683796..1281e5cd76815 100644 --- a/drivers/power/qpnp-smbcharger.c +++ b/drivers/power/qpnp-smbcharger.c @@ -4902,11 +4902,28 @@ static int smbchg_restricted_charging(struct smbchg_chip *chip, bool enable) return rc; } +#ifdef CONFIG_MACH_XIAOMI_MIDO +extern void ist30xx_set_ta_mode(bool mode); +extern void tpd_usb_plugin(bool mode); +extern void gtp_usb_plugin(bool mode); +int set_usb_charge_mode_par = 0; +#endif + static void handle_usb_removal(struct smbchg_chip *chip) { struct power_supply *parallel_psy = get_parallel_psy(chip); int rc; +#ifdef CONFIG_MACH_XIAOMI_MIDO + if (set_usb_charge_mode_par == 1) { + ist30xx_set_ta_mode(0); + } else if (set_usb_charge_mode_par == 2) { + tpd_usb_plugin(0); + } else if (set_usb_charge_mode_par == 3) { + gtp_usb_plugin(0); + } +#endif + pr_smb(PR_STATUS, "triggered\n"); smbchg_aicl_deglitch_wa_check(chip); /* Clear the OV detected status set before */ @@ -4983,6 +5000,16 @@ static void handle_usb_insertion(struct smbchg_chip *chip) int rc; char *usb_type_name = "null"; +#ifdef CONFIG_MACH_XIAOMI_MIDO + if (set_usb_charge_mode_par == 1) { + ist30xx_set_ta_mode(1); + } else if (set_usb_charge_mode_par == 2) { + tpd_usb_plugin(1); + } else if (set_usb_charge_mode_par == 3) { + gtp_usb_plugin(1); + } +#endif + pr_smb(PR_STATUS, "triggered\n"); /* usb inserted */ read_usb_type(chip, &usb_type_name, &usb_supply_type); From 6b955084afb9a8a5300600aff49ec3383b187108 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Mon, 19 Mar 2018 20:04:15 +0530 Subject: [PATCH 204/508] drivers: input: touchscreen: Add ft8716 and tdp4310 tissot drivers * Disable ft5435 auto upgrade for tissot * Remove ft8716 test code --- drivers/input/touchscreen/Kconfig | 39 + drivers/input/touchscreen/Makefile | 2 + drivers/input/touchscreen/ft5435/ft5435_ts.h | 4 + .../touchscreen/ft8716/Conf_MultipleTest.ini | 275 + drivers/input/touchscreen/ft8716/Kconfig | 16 + drivers/input/touchscreen/ft8716/Makefile | 16 + .../touchscreen/ft8716/focaltech_common.h | 201 + .../touchscreen/ft8716/focaltech_config.h | 231 + .../input/touchscreen/ft8716/focaltech_core.c | 1527 ++++ .../input/touchscreen/ft8716/focaltech_core.h | 197 + .../touchscreen/ft8716/focaltech_esdcheck.c | 449 ++ .../touchscreen/ft8716/focaltech_ex_fun.c | 1182 +++ .../touchscreen/ft8716/focaltech_ex_mode.c | 352 + .../touchscreen/ft8716/focaltech_flash.c | 759 ++ .../touchscreen/ft8716/focaltech_flash.h | 154 + .../ft8716/focaltech_flash/Makefile | 10 + .../focaltech_upgrade_common.h | 57 + .../focaltech_upgrade_ft8716.c | 541 ++ .../focaltech_flash/focaltech_upgrade_idc.c | 593 ++ .../focaltech_flash/focaltech_upgrade_test.c | 162 + .../touchscreen/ft8716/focaltech_gesture.c | 651 ++ .../input/touchscreen/ft8716/focaltech_i2c.c | 204 + .../ft8716/focaltech_point_report_check.c | 157 + .../touchscreen/ft8716/focaltech_sensor.c | 313 + .../include/firmware/FT8716_app_sample.i | 0 ...IAPU_BIEL0X3b_Black_V09_D01_20170809_app.i | 3555 +++++++++ .../pramboot/FT8716_Pramboot_V0.5_20160723.i | 246 + .../synaptics_dsx_2.6/synaptics_dsx_i2c.c | 2 +- .../touchscreen/synaptics_dsx_fw_update.c | 5990 +++++++++++++++ drivers/input/touchscreen/td4310/Kconfig | 128 + drivers/input/touchscreen/td4310/Makefile | 18 + .../td4310/synaptics_dsx_active_pen.c | 624 ++ .../touchscreen/td4310/synaptics_dsx_core.c | 4885 ++++++++++++ .../touchscreen/td4310/synaptics_dsx_core.h | 537 ++ .../td4310/synaptics_dsx_fw_update.c | 5990 +++++++++++++++ .../td4310/synaptics_dsx_gesture.c | 2308 ++++++ .../touchscreen/td4310/synaptics_dsx_i2c.c | 649 ++ .../td4310/synaptics_dsx_proximity.c | 692 ++ .../td4310/synaptics_dsx_rmi_dev.c | 1064 +++ .../td4310/synaptics_dsx_rmi_hid_i2c.c | 1006 +++ .../touchscreen/td4310/synaptics_dsx_spi.c | 712 ++ .../td4310/synaptics_dsx_test_reporting.c | 5409 ++++++++++++++ .../touchscreen/td4310/synaptics_dsx_video.c | 416 ++ firmware/Makefile | 1 + firmware/synaptics/startup_fw_update.img.ihex | 6531 +++++++++++++++++ include/linux/input/synaptics_dsx.h | 133 +- 46 files changed, 48935 insertions(+), 53 deletions(-) create mode 100644 drivers/input/touchscreen/ft8716/Conf_MultipleTest.ini create mode 100644 drivers/input/touchscreen/ft8716/Kconfig create mode 100644 drivers/input/touchscreen/ft8716/Makefile create mode 100644 drivers/input/touchscreen/ft8716/focaltech_common.h create mode 100644 drivers/input/touchscreen/ft8716/focaltech_config.h create mode 100644 drivers/input/touchscreen/ft8716/focaltech_core.c create mode 100644 drivers/input/touchscreen/ft8716/focaltech_core.h create mode 100644 drivers/input/touchscreen/ft8716/focaltech_esdcheck.c create mode 100644 drivers/input/touchscreen/ft8716/focaltech_ex_fun.c create mode 100644 drivers/input/touchscreen/ft8716/focaltech_ex_mode.c create mode 100644 drivers/input/touchscreen/ft8716/focaltech_flash.c create mode 100644 drivers/input/touchscreen/ft8716/focaltech_flash.h create mode 100644 drivers/input/touchscreen/ft8716/focaltech_flash/Makefile create mode 100644 drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_common.h create mode 100644 drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_ft8716.c create mode 100644 drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_idc.c create mode 100644 drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_test.c create mode 100644 drivers/input/touchscreen/ft8716/focaltech_gesture.c create mode 100644 drivers/input/touchscreen/ft8716/focaltech_i2c.c create mode 100644 drivers/input/touchscreen/ft8716/focaltech_point_report_check.c create mode 100644 drivers/input/touchscreen/ft8716/focaltech_sensor.c create mode 100644 drivers/input/touchscreen/ft8716/include/firmware/FT8716_app_sample.i create mode 100644 drivers/input/touchscreen/ft8716/include/firmware/HQ_D2_XIAOMI_FT8716_XIAPU_BIEL0X3b_Black_V09_D01_20170809_app.i create mode 100644 drivers/input/touchscreen/ft8716/include/pramboot/FT8716_Pramboot_V0.5_20160723.i create mode 100644 drivers/input/touchscreen/synaptics_dsx_fw_update.c create mode 100644 drivers/input/touchscreen/td4310/Kconfig create mode 100644 drivers/input/touchscreen/td4310/Makefile create mode 100644 drivers/input/touchscreen/td4310/synaptics_dsx_active_pen.c create mode 100644 drivers/input/touchscreen/td4310/synaptics_dsx_core.c create mode 100644 drivers/input/touchscreen/td4310/synaptics_dsx_core.h create mode 100644 drivers/input/touchscreen/td4310/synaptics_dsx_fw_update.c create mode 100644 drivers/input/touchscreen/td4310/synaptics_dsx_gesture.c create mode 100644 drivers/input/touchscreen/td4310/synaptics_dsx_i2c.c create mode 100644 drivers/input/touchscreen/td4310/synaptics_dsx_proximity.c create mode 100644 drivers/input/touchscreen/td4310/synaptics_dsx_rmi_dev.c create mode 100644 drivers/input/touchscreen/td4310/synaptics_dsx_rmi_hid_i2c.c create mode 100644 drivers/input/touchscreen/td4310/synaptics_dsx_spi.c create mode 100644 drivers/input/touchscreen/td4310/synaptics_dsx_test_reporting.c create mode 100644 drivers/input/touchscreen/td4310/synaptics_dsx_video.c create mode 100644 firmware/synaptics/startup_fw_update.img.ihex diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index b3f8454ec7963..0faa6432803d4 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1171,6 +1171,45 @@ config TOUCHSCREEN_MAXIM_STI To compile this driver as a module, choose M here: the module will be called maxim_sti. +config TOUCHSCREEN_FT5435 + tristate "FocalTech touchscreens" + depends on I2C + help + Say Y here if you have a ft5435 touchscreen. + Ft5435 controllers are multi touch controllers which can + report 5 touches at a time. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called ft5435_ts. + +config TOUCHSCREEN_FTS + tristate "FocalTech touchscreens" + depends on I2C + help + Say Y here if you have a ft8716 touchscreen. + Ft8716 controllers are multi touch controllers which can + report 5 touches at a time. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called ft8716_ts. + +config TOUCHSCREEN_TD4310 + tristate "synaptics touchscreens" + depends on I2C + help + Say Y here if you have a synaptics TD4310 touchscreen. + TD4310 controllers are multi touch controllers which can + report 5 touches at a time. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called td4310_ts. + source "drivers/input/touchscreen/gt9xx/Kconfig" endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 4792092e6c3d5..d0e90eedb241c 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -93,3 +93,5 @@ obj-$(CONFIG_TOUCHSCREEN_FT5435) += ft5435/ obj-$(CONFIG_TOUCHSCREEN_IST3038C) += ist3038c/ obj-$(CONFIG_TOUCHSCREEN_GT9XX) += gt9xx/ obj-$(CONFIG_TOUCHSCREEN_GT9XX_MIDO) += gt9xx_mido/ +obj-$(CONFIG_TOUCHSCREEN_FTS) += ft8716/ +obj-$(CONFIG_TOUCHSCREEN_TD4310) += td4310/ diff --git a/drivers/input/touchscreen/ft5435/ft5435_ts.h b/drivers/input/touchscreen/ft5435/ft5435_ts.h index 986359e0a254b..f7cd6f8106939 100644 --- a/drivers/input/touchscreen/ft5435/ft5435_ts.h +++ b/drivers/input/touchscreen/ft5435/ft5435_ts.h @@ -27,7 +27,11 @@ /* [PLATFORM]-Mod-BEGIN by TCTNB.YQJ, FR797197, 2014/11/28 add for tp gesture */ #define SET_COVER_MODE +#ifdef CONFIG_MACH_XIAOMI_TISSOT +#define FOCALTECH_AUTO_UPGRADE 0 +#else #define FOCALTECH_AUTO_UPGRADE 1 +#endif #define FOCALTECH_LOCK_DOWN_INFO 1 #define FOCALTECH_TP_GESTURE #define FOCALTECH_FAE_MOD diff --git a/drivers/input/touchscreen/ft8716/Conf_MultipleTest.ini b/drivers/input/touchscreen/ft8716/Conf_MultipleTest.ini new file mode 100644 index 0000000000000..2158f5e653cd3 --- /dev/null +++ b/drivers/input/touchscreen/ft8716/Conf_MultipleTest.ini @@ -0,0 +1,275 @@ +[Valid_File] +OnlyMultipleTest=1 +[Interface] +IC_Type=FT8716 +Normalize_Type=0 +Interface_Type=0 +Slave_Addr=0x80 +Freq_Index=2 +Phase_Pola=-1 +Max_Points=10 +iRotationDegree=0 +isReversed=0 +ixMaxPixel=1080 +iyMaxPixel=1920 +[Config] +Output_LevelSignal=0 +Output_NgSignal=0 +Input_LevelSignal=0 +Reverse_Time=0 +Switch_Protocol=0 +CLB_Other_Return=0 +Count_Result=0 +Count_Result_Type=0 +Full_Screen=0 +Impulsing=0 +Use_LockDown=0 +SetCheckFwFileName=0 +SetFwChecksum=0 +Run_Mode=1 +Read_Bytes=256 +Write_Bytes=128 +Test_Way=0 +Handle_SN=0 +SN_Length=18 +SN_AutoTest=1 +SKey_Index=0 +SKeyValue=13 +TP_AutoTest=0 +TP_AutoTest_Time=0 +TP_ReplaceTP=0 +TP_ReplaceTP_Time=0 +TP_Always_Replace=0 +TP_Always_Replace_Time=0 +Store_Result=1 +Result_Type=0 +Result_Format=0 +Result_Path_Enable=0 +Result_OP_Num=0 +Result_Use_IcId=0 +Result_ReplaceOldLog=0 +Result_SaveTestMsg=1 +Result_SimpleDirectory=0 +Auto_Switch=0 +Continue_Test_After_Fail=0 +CB_Test_Mode=1 +Tip_After_TestNG=0 +Show_Res=1 +Check_Mode=0 +Light_Up=0 +Non_Common_GND=0 +TP_Stop=0 +[Android_Terminal] +I2C_Interface=1 +I2C_Index=0 +RW_Byte=0 +CustomConfPath=0 +AutoSave=1 +ResultPath= +[OnLine_Setting] +IPAddress=127.0.0.1 +TCPPort=5555 +[COM_Setting] +COM_ID=0 +BaudRate=115200 +[TestItem] +FW_VERSION_TEST=0 +FACTORY_ID_TEST=0 +IC_VERSION_TEST=0 +PROJECT_CODE_TEST=0 +RAWDATA_TEST=1 +CB_TEST=1 +SHORT_CIRCUIT_TEST=0 +CHANNEL_NUM_TEST=0 +INT_PIN_TEST=0 +RESET_PIN_TEST=0 +NOISE_TEST=0 +OPEN_TEST=0 +CB_UNIFORMITY_TEST=0 +DIFFER_UNIFORMITY_TEST=0 +DIFFER2_UNIFORMITY_TEST=0 +LCD_NOISE_TEST=0 +GPIO_TEST=0 +ICTYPE_TEST=0 +RESETDETECTION_TEST=0 +ERASE_TEST=0 +RAWDATA_UNIFORMITY_TEST=0 +VIRTUAL_DIFFER_TEST=0 +WRITE_2D_CODE_TEST=0 +RED_PICTURE_NOISE_TEST=0 +VIRTUAL_BUTTON_TEST=1 +ONELINE_TEST=0 +DIAGONAL_TEST=0 +FREEPAINT_TEST=0 +SPECIAL_BUTTON_TEST=0 +HOME_KEY_TEST=0 +LINEARITY_TEST=0 +CIRCLE_TEST=0 +SQUARE_TEST=0 +KEY_TEST=0 +PRESS_CHANNEL_TEST=0 +[Basic_Threshold] +FW_VER_VALUE=1 +Factory_ID_Number=233 +IC_Version=0 +Project_Code=38333201d2005001 +Ori_ProjectCode=1 +RawDataTest_VA_Check=1 +RawDataTest_Min=3000 +RawDataTest_Max=13000 +RawDataTest_VKey_Check=1 +RawDataTest_Min_VKey=3000 +RawDataTest_Max_VKey=13000 +CBTest_VA_Check=1 +CBTest_Min=1 +CBTest_Max=110 +CBTest_VKey_Check=1 +CBTest_Min_Vkey=1 +CBTest_Max_Vkey=110 +CBTest_VKey_Double_Check=0 +CBTest_Min_DCheck_Vkey=140 +CBTest_Max_DCheck_Vkey=180 +Lcd_Busy_Adjust=0 +ShortCircuit_VA_Check=1 +ShortCircuit_VKey_Check=1 +ShortCircuit_VA_ResMin=200 +ShortCircuit_Key_ResMin=200 +ChannelNumTest_ChannelX=18 +ChannelNumTest_ChannelY=30 +ChannelNumTest_KeyNum=3 +IntPinTest_RegAddr=8 +ResetPinTest_RegAddr=136 +NoiseTest_Coefficient=50 +NoiseTest_Frames=32 +NoiseTest_Time=1 +NoiseTest_SampeMode=0 +NoiseTest_NoiseMode=0 +NoiseTest_ShowTip=0 +OpenTest_Check_NMOS=0 +OpenTest_CBMin=60 +OpenTest_Check_K1=0 +OpenTest_K1Threshold=30 +OpenTest_Check_K2=0 +OpenTest_K2Threshold=5 +Distance_Diagonal=50 +Type_Diagonal=2 +MaxNG_Diagonal=0 +LimitTime_Diagonal=0 +LinearityCheck_Diagonal=1 +LimitTime_HomeKey=10 +HomeKey_LeftChannel=0 +HomeKey_RightChannel=0 +HomeKey_TopChannel=0 +HomeKey_BottonChannel=0 +HomeKey_Hole=0 +SET_TOUCH_THRESHOLD_INCELL=1 +Key_Div_Number_Incell=1 +Preserved_key_threshold_Incell=12 +SET_TOUCH_THRESHOLD_INCELL2=0 +Key_Div_Number_Incell2=1 +Preserved_key_threshold_Incell2=4 +Preserved_key_threshold_Dynamic=1 +CIRCLE_TEST_MAX_NG=0 +CIRCLE_TEST_LIMITE_TIME=0 +CIRCLE_TEST_BOARDER=360 +CIRCLE_TEST_EDGE=20 +CIRCLE_TEST_TRACK=10 +CIRCLE_TEST_CENTER1=270 +CIRCLE_TEST_CENTER2=120 +CIRCLE_TEST_LINEARITY=35 +CIRCLE_TEST_SPLITS=10 +SET_TOUCH_THRESHOLD=0 +Key_Div_Number=1 +Preserved_key_threshold=800 +1_key_threshold=800 +2_key_threshold=800 +3_key_threshold=800 +4_key_threshold=800 +Key_Threshold=800 +KEY_TEST_MAX_NG=0 +KEY_TEST_LIMITE_TIME=0 +KEY_TEST_KEY_NUM=21 +PressChannelTest_Min=5000 +Press_Test_LimitedTime=0 +CBUniformityTest_CHX_Hole=70 +CBUniformityTest_CHY_Hole=70 +CBUniformityTest_MinMax_Hole=20 +CBUniformityTest_Check_CHX=1 +CBUniformityTest_Check_CHY=1 +CBUniformityTest_Check_MinMax=1 +LCDNoiseTest_FrameNum=200 +LCDNoiseTest_Coefficient=60 +LCDNoiseTest_Coefficient_Key=60 +LCDNoiseTest_NoiseMode=0 +LCDNoiseTest_Level1=100 +LCDNoiseTest_Level2=160 +LCDNoiseTest_Level3=400 +LCDNoiseTest_Level4=150 +LCDNoiseTest_Frame1=2 +LCDNoiseTest_Frame2=2 +LCDNoiseTest_Frame3=2 +LCDNoiseTest_Frame4=2 +Set_Key_Num=3 +LimitTime_Key=0 +MAX_NG_Key=0 +Use_Key_Value=0 +Key1_Left=180 +Key1_Top=2034 +Key1_Right=180 +Key1_Bottom=2034 +Key2_Left=540 +Key2_Top=2034 +Key2_Right=540 +Key2_Bottom=2034 +Key3_Left=900 +Key3_Top=2034 +Key3_Right=900 +Key3_Bottom=2034 +Key4_Left= +Key4_Top= +Key4_Right= +Key4_Bottom= +Key5_Left= +Key5_Top= +Key5_Right= +Key5_Bottom= +Key6_Left= +Key6_Top= +Key6_Right= +Key6_Bottom= +Key7_Left= +Key7_Top= +Key7_Right= +Key7_Bottom= +Key8_Left= +Key8_Top= +Key8_Right= +Key8_Bottom= +[SiuParam] +Check_Siu_Version=0 +Siu_MainVersion=0 +Siu_SubVersion=0 +Check_Set_IICVol=0 +IIC_Vol_Type=0 +IIC_Vdd_Type=0 +Check_Iovcc=0 +Iovcc_Vol_Type=0 +Iovcc_Current_Type=0 +Iovcc_Min_Hole=0 +Iovcc_Max_Hole=50 +Check_Vdd=0 +Vdd_Vol_Type=0 +Check_Normal=0 +Check_Sleep=0 +Vdd_Normal_Min=0 +Vdd_Normal_Max=500 +Vdd_Sleep_Min=0 +Vdd_Sleep_Max=150 +Check_Standby=0 +Standby_Vol_Type=0 +Vdd_Standby_Min=0 +Vdd_Standby_Max=150 +[INVALID_NODE] +InvalidNode[19][4]=0 +InvalidNode[19][5]=0 +InvalidNode[19][6]=0 diff --git a/drivers/input/touchscreen/ft8716/Kconfig b/drivers/input/touchscreen/ft8716/Kconfig new file mode 100644 index 0000000000000..f7663ba30610e --- /dev/null +++ b/drivers/input/touchscreen/ft8716/Kconfig @@ -0,0 +1,16 @@ +# +# Focaltech Touchscreen driver configuration +# + +config TOUCHSCREEN_FTS + bool "Focaltech Touchscreen" + depends on I2C + default n + help + Say Y here if you have Focaltech touch panel. + If unsure, say N. + +config TOUCHSCREEN_FTS_DIRECTORY + string "Focaltech ts directory name" + default "focaltech_touch" + depends on TOUCHSCREEN_FTS diff --git a/drivers/input/touchscreen/ft8716/Makefile b/drivers/input/touchscreen/ft8716/Makefile new file mode 100644 index 0000000000000..d4b6dc53c3811 --- /dev/null +++ b/drivers/input/touchscreen/ft8716/Makefile @@ -0,0 +1,16 @@ +# +# Makefile for the focaltech touchscreen drivers. +# + +# Each configuration option enables a list of files. + +obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_core.o +obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_ex_fun.o +obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_ex_mode.o +obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_flash.o +obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_gesture.o +obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_esdcheck.o +obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_i2c.o +obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_sensor.o +obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_point_report_check.o +obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_flash/ diff --git a/drivers/input/touchscreen/ft8716/focaltech_common.h b/drivers/input/touchscreen/ft8716/focaltech_common.h new file mode 100644 index 0000000000000..633c677a438f0 --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_common.h @@ -0,0 +1,201 @@ +/* + * + * FocalTech fts TouchScreen driver. + * + * Copyright (c) 2010-2016, Focaltech Ltd. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +/***************************************************************************** +* +* File Name: focaltech_common.h +* +* Author: Focaltech Driver Team +* +* Created: 2016-08-16 +* +* Abstract: +* +* Reference: +* +*****************************************************************************/ + +#ifndef __LINUX_FOCALTECH_COMMON_H__ +#define __LINUX_FOCALTECH_COMMON_H__ + +#include "focaltech_config.h" + +/***************************************************************************** +* Macro definitions using #define +*****************************************************************************/ +#define FTS_DRIVER_VERSION "Focaltech V1.2 20161229" + +#define FLAGBIT(x) (0x00000001 << (x)) +#define FLAGBITS(x, y) ((0xFFFFFFFF >> (32 - (y) - 1)) << (x)) + +#define FLAG_ICSERIALS_LEN 5 +#define FLAG_IDC_BIT 11 + +#define IC_SERIALS (FTS_CHIP_TYPE & FLAGBITS(0, FLAG_ICSERIALS_LEN-1)) +#define FTS_CHIP_IDC ((FTS_CHIP_TYPE & FLAGBIT(FLAG_IDC_BIT)) == FLAGBIT(FLAG_IDC_BIT)) + +#define FTS_CHIP_TYPE_MAPPING {{0x05, 0x87, 0x16, 0x87, 0x16, 0x87, 0xA6, 0x00, 0x00} } + +#define I2C_BUFFER_LENGTH_MAXINUM 256 +#define FILE_NAME_LENGTH 128 +#define ENABLE 1 +#define DISABLE 0 +/*register address*/ +#define FTS_REG_INT_CNT 0x8F +#define FTS_REG_FLOW_WORK_CNT 0x91 +#define FTS_REG_WORKMODE 0x00 +#define FTS_REG_WORKMODE_FACTORY_VALUE 0x40 +#define FTS_REG_WORKMODE_WORK_VALUE 0x00 +#define FTS_REG_CHIP_ID 0xA3 +#define FTS_REG_CHIP_ID2 0x9F +#define FTS_REG_POWER_MODE 0xA5 +#define FTS_REG_POWER_MODE_SLEEP_VALUE 0x03 +#define FTS_REG_FW_VER 0xA6 +#define FTS_REG_VENDOR_ID 0xA8 +#define FTS_REG_LCD_BUSY_NUM 0xAB +#define FTS_REG_FACE_DEC_MODE_EN 0xB0 +#define FTS_REG_GLOVE_MODE_EN 0xC0 +#define FTS_REG_COVER_MODE_EN 0xC1 +#define FTS_REG_CHARGER_MODE_EN 0x8B +#define FTS_REG_GESTURE_EN 0xD0 +#define FTS_REG_GESTURE_OUTPUT_ADDRESS 0xD3 +#define FTS_REG_ESD_SATURATE 0xED + + + +/***************************************************************************** +* Alternative mode (When something goes wrong, the modules may be able to solve the problem.) +*****************************************************************************/ +/* + * point report check + * default: disable + */ +#define FTS_POINT_REPORT_CHECK_EN 1 + + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ +struct ft_chip_t { + unsigned long type; + unsigned char chip_idh; + unsigned char chip_idl; + unsigned char rom_idh; + unsigned char rom_idl; + unsigned char pramboot_idh; + unsigned char pramboot_idl; + unsigned char bootloader_idh; + unsigned char bootloader_idl; +}; + +/* i2c communication*/ +int fts_i2c_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue); +int fts_i2c_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue); +int fts_i2c_read(struct i2c_client *client, char *writebuf, int writelen, char *readbuf, int readlen); +int fts_i2c_write(struct i2c_client *client, char *writebuf, int writelen); +int fts_i2c_init(void); +int fts_i2c_exit(void); + +/* Gesture functions */ +#if FTS_GESTURE_EN +int fts_gesture_init(struct input_dev *input_dev, struct i2c_client *client); +int fts_gesture_exit(struct i2c_client *client); +void fts_gesture_recovery(struct i2c_client *client); +int fts_gesture_readdata(struct i2c_client *client); +int fts_gesture_suspend(struct i2c_client *i2c_client); +int fts_gesture_resume(struct i2c_client *client); +#endif + +/* Apk and functions */ +#if FTS_APK_NODE_EN +int fts_create_apk_debug_channel(struct i2c_client *client); +void fts_release_apk_debug_channel(void); +#endif + +/* ADB functions */ +#if FTS_SYSFS_NODE_EN +int fts_create_sysfs(struct i2c_client *client); +int fts_remove_sysfs(struct i2c_client *client); +#endif + +/* ESD */ +#if FTS_ESDCHECK_EN +int fts_esdcheck_init(void); +int fts_esdcheck_exit(void); +int fts_esdcheck_switch(bool enable); +int fts_esdcheck_proc_busy(bool proc_debug); +int fts_esdcheck_set_intr(bool intr); +int fts_esdcheck_suspend(void); +int fts_esdcheck_resume(void); +int fts_esdcheck_get_status(void); +#endif + +/* Production test */ +#if FTS_TEST_EN +int fts_test_init(struct i2c_client *client); +int fts_test_exit(struct i2c_client *client); +#endif + +/* Point Report Check*/ +#if FTS_POINT_REPORT_CHECK_EN +int fts_point_report_check_init(void); +int fts_point_report_check_exit(void); +void fts_point_report_check_queue_work(void); +#endif + +/* Other */ +extern int g_show_log; +int fts_reset_proc(int hdelayms); +int fts_wait_tp_to_valid_sharp(struct i2c_client *client); +void fts_tp_state_recovery(struct i2c_client *client); +int fts_ex_mode_init(struct i2c_client *client); +int fts_ex_mode_exit(struct i2c_client *client); +int fts_ex_mode_recovery(struct i2c_client *client); + +void fts_irq_disable(void); +void fts_irq_enable(void); + +/***************************************************************************** +* DEBUG function define here +*****************************************************************************/ +#if FTS_DEBUG_EN +#define FTS_DEBUG_LEVEL 1 + +#if (FTS_DEBUG_LEVEL == 2) +#define FTS_DEBUG(fmt, args...) printk(KERN_ERR "[FTS][%s]"fmt"\n", __func__, ##args) +#else +#define FTS_DEBUG(fmt, args...) printk(KERN_ERR "[FTS]"fmt"\n", ##args) +#endif + +#define FTS_FUNC_ENTER() printk(KERN_ERR "[FTS]%s: Enter\n", __func__) +#define FTS_FUNC_EXIT() printk(KERN_ERR "[FTS]%s: Exit(%d)\n", __func__, __LINE__) +#else +#define FTS_DEBUG(fmt, args...) +#define FTS_FUNC_ENTER() +#define FTS_FUNC_EXIT() +#endif + +#define FTS_INFO(fmt, args...) do { \ + if (g_show_log) {printk(KERN_ERR "[FTS][Info]"fmt"\n", ##args); } \ + } while (0) + +#define FTS_ERROR(fmt, args...) do { \ + if (g_show_log) {printk(KERN_ERR "[FTS][Error]"fmt"\n", ##args); } \ + } while (0) + + +#endif /* __LINUX_FOCALTECH_COMMON_H__ */ + diff --git a/drivers/input/touchscreen/ft8716/focaltech_config.h b/drivers/input/touchscreen/ft8716/focaltech_config.h new file mode 100644 index 0000000000000..443408c91aa3d --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_config.h @@ -0,0 +1,231 @@ +/* + * + * FocalTech TouchScreen driver. + * + * Copyright (c) 2010-2016, FocalTech Systems, Ltd., all rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +/************************************************************************ +* +* File Name: focaltech_config.h +* +* Author: Focaltech Driver Team +* +* Created: 2016-08-08 +* +* Abstract: global configurations +* +* Version: v1.0 +* +************************************************************************/ +#ifndef _LINUX_FOCLATECH_CONFIG_H_ +#define _LINUX_FOCLATECH_CONFIG_H_ + +/**************************************************/ +/****** G: A, I: B, S: C, U: D ******************/ +/****** chip type defines, do not modify *********/ +#define _FT8716 0x87160805 +#define _FT8736 0x87360806 +#define _FT8006 0x80060807 +#define _FT8606 0x86060808 +#define _FT8607 0x86070809 +#define _FTE716 0xE716080a + +#define _FT5416 0x54160002 +#define _FT5426 0x54260002 +#define _FT5435 0x54350002 +#define _FT5436 0x54360002 +#define _FT5526 0x55260002 +#define _FT5526I 0x5526B002 +#define _FT5446 0x54460002 +#define _FT5346 0x53460002 +#define _FT5446I 0x5446B002 +#define _FT5346I 0x5346B002 +#define _FT7661 0x76610002 +#define _FT7511 0x75110002 +#define _FT7421 0x74210002 +#define _FT7681 0x76810002 +#define _FT3C47U 0x3C47D002 +#define _FT3417 0x34170002 +#define _FT3517 0x35170002 +#define _FT3327 0x33270002 +#define _FT3427 0x34270002 + +#define _FT5626 0x56260001 +#define _FT5726 0x57260001 +#define _FT5826B 0x5826B001 +#define _FT5826S 0x5826C001 +#define _FT7811 0x78110001 +#define _FT3D47 0x3D470001 +#define _FT3617 0x36170001 +#define _FT3717 0x37170001 +#define _FT3817B 0x3817B001 + +#define _FT6236U 0x6236D003 +#define _FT6336G 0x6336A003 +#define _FT6336U 0x6336D003 +#define _FT6436U 0x6436D003 + +#define _FT3267 0x32670004 +#define _FT3367 0x33670004 + + + +/*************************************************/ + +/* + * choose your ic chip type of focaltech + */ +#define FTS_CHIP_TYPE _FT8716 + +/******************* Enables *********************/ +/*********** 1 to enable, 0 to disable ***********/ + +/* + * show debug log info + * enable it for debug, disable it for release + */ +#define FTS_DEBUG_EN 1 + +/* + * Linux MultiTouch Protocol + * 1: Protocol B(default), 0: Protocol A + */ +#define FTS_MT_PROTOCOL_B_EN 1 + + +/* + * Report Pressure in multitouch + * 1:enable(default),0:disable +*/ +#define FTS_REPORT_PRESSURE_EN 0 + +/* + * Force touch support + * different pressure for multitouch + * 1: true pressure for force touch + * 0: constant pressure(default) + */ +#define FTS_FORCE_TOUCH_EN 0 + +/* + * Gesture function enable + * default: disable + */ +#define FTS_GESTURE_EN 1 + +/* + * ESD check & protection + * default: disable + */ +#define FTS_ESDCHECK_EN 1 + +/* + * Production test enable + * 1: enable, 0:disable(default) + */ +#define FTS_TEST_EN 0 + +/* + * Glove mode enable + * 1: enable, 0:disable(default) + */ +#define FTS_GLOVE_EN 0 +/* + * cover enable + * 1: enable, 0:disable(default) + */ +#define FTS_COVER_EN 1 +/* + * Charger enable + * 1: enable, 0:disable(default) + */ +#define FTS_CHARGER_EN 0 + +/* + * Proximity sensor + * default: disable + */ +#define FTS_PSENSOR_EN 0 + +/* + * Nodes for tools, please keep enable + */ +#define FTS_SYSFS_NODE_EN 1 +#define FTS_APK_NODE_EN 1 + +/* + * Customer power enable + * enable it when customer need control TP power + * default: disable + */ +#define FTS_POWER_SOURCE_CUST_EN 0 + +/****************************************************/ + +/********************** Upgrade ****************************/ +/* + * auto upgrade, please keep enable + */ +#define FTS_AUTO_UPGRADE_EN 1 + +/* + * auto upgrade for lcd cfg + * default: 0 + */ +#define FTS_AUTO_UPGRADE_FOR_LCD_CFG_EN 0 + +/* auto cb check + * default: disable + */ +#define FTS_AUTO_CLB_EN 0 + +/* + * FW_APP.i file for upgrade + * define your own fw_app, the sample one is invalid + */ +#define FTS_UPGRADE_FW_APP "include/firmware/HQ_D2_XIAOMI_FT8716_XIAPU_BIEL0X3b_Black_V09_D01_20170809_app.i" + +/* + * lcd_cfg.i file for lcd cfg upgrade + * define your own lcd_cfg.i, the sample one is invalid + */ + + + +/* get vedor id from flash + * default: enable + */ +#define FTS_GET_VENDOR_ID 0 + +/* + * vendor_id(s) for the ic + * you need confirm vendor_id for upgrade + * if only one vendor, ignore vendor_2_id, otherwise + * you need define both of them + */ +#define FTS_VENDOR_1_ID 0x8d +#define FTS_VENDOR_2_ID 0x8d + +/* + * upgrade stress test for debug + * enable it for upgrade debug if needed + * default: disable + */ +#define FTS_UPGRADE_STRESS_TEST 0 +/* stress test times, default: 1000 */ +#define FTS_UPGRADE_TEST_NUMBER 1000 + +/*********************************************************/ + +#endif /* _LINUX_FOCLATECH_CONFIG_H_ */ + diff --git a/drivers/input/touchscreen/ft8716/focaltech_core.c b/drivers/input/touchscreen/ft8716/focaltech_core.c new file mode 100644 index 0000000000000..d4017ecb7400d --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_core.c @@ -0,0 +1,1527 @@ +/* + * + * FocalTech TouchScreen driver. + * + * Copyright (c) 2010-2016, FocalTech Systems, Ltd., all rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +/***************************************************************************** +* +* File Name: focaltech_core.c +* +* Author: Focaltech Driver Team +* +* Created: 2016-08-08 +* +* Abstract: +* +* Reference: +* +*****************************************************************************/ + +/***************************************************************************** +* Included header files +*****************************************************************************/ +#include "focaltech_core.h" + + + +#if defined(CONFIG_FB) +#include +#include +#elif defined(CONFIG_HAS_EARLYSUSPEND) +#include +#define FTS_SUSPEND_LEVEL 1 /* Early-suspend level */ +#endif + +/***************************************************************************** +* Private constant and macro definitions using #define +*****************************************************************************/ +#define FTS_DRIVER_NAME "fts_ts" +#define INTERVAL_READ_REG 20 +#define TIMEOUT_READ_REG 300 +#if FTS_POWER_SOURCE_CUST_EN +#define FTS_VTG_MIN_UV 2600000 +#define FTS_VTG_MAX_UV 3300000 +#define FTS_I2C_VTG_MIN_UV 1800000 +#define FTS_I2C_VTG_MAX_UV 1800000 +#endif +#define FTS_READ_TOUCH_BUFFER_DIVIDED 0 + + + +char TP_vendor; +u8 fw_ver; + + +extern int fts_i2c_read(struct i2c_client *client, char *writebuf, int writelen, char *readbuf, int readlen); + +#if FTS_LOCK_DOWN_INFO +char ftp_lockdown_info[128]; + +#define FTS_PROC_LOCKDOWN_FILE "tp_lockdown_info" +static struct proc_dir_entry *fts_lockdown_status_proc; + +static int fts_lockdown_proc_show(struct seq_file *file, void *data) +{ + char temp[40] = {0}; + + sprintf(temp, "%s\n", ftp_lockdown_info); + seq_printf(file, "%s\n", temp); + + return 0; +} + +static int fts_lockdown_proc_open (struct inode *inode, struct file *file) +{ + return single_open(file, fts_lockdown_proc_show, inode->i_private); +} + +static const struct file_operations fts_lockdown_proc_fops = { + .open = fts_lockdown_proc_open, + .read = seq_read, +}; + +#endif + + + + + +/***************************************************************************** +* Global variable or extern global variabls/functions +******************************************************************************/ +struct i2c_client *fts_i2c_client; +struct fts_ts_data *fts_wq_data; +struct input_dev *fts_input_dev; + + +#if FTS_DEBUG_EN +int g_show_log = 1; +#else +int g_show_log = 0; +#endif + +#if (FTS_DEBUG_EN && (FTS_DEBUG_LEVEL == 2)) +char g_sz_debug[1024] = {0}; +#endif + +/***************************************************************************** +* Static function prototypes +*****************************************************************************/ +static void fts_release_all_finger(void); +static int fts_ts_suspend(struct device *dev); +static int fts_ts_resume(struct device *dev); + + +/***************************************************************************** +* Name: fts_wait_tp_to_valid_sharp +* Brief: Read chip id until TP FW become valid, need call when reset/power on/resume... +* 1. Read Chip ID per INTERVAL_READ_REG(20ms) +* 2. Timeout: TIMEOUT_READ_REG(300ms) +* Input: +* Output: +* Return: 0 - Get correct Device ID +*****************************************************************************/ +int fts_wait_tp_to_valid_sharp(struct i2c_client *client) +{ + int ret = 0; + int cnt = 0; + u8 reg_value = 0; + u8 id_cmd[4] = {0}; + u8 boot_id[2] = {0}; + + do { + ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID, ®_value); + if ((ret < 0) || (reg_value != chip_types.chip_idh)) { + FTS_INFO("TP Not Ready, ReadData = 0x%x", reg_value); + } else if (reg_value == chip_types.chip_idh) { + FTS_INFO("TP Ready, Device ID = 0x%x", reg_value); + return 0; + } + cnt++; + msleep(INTERVAL_READ_REG); + } while ((cnt * INTERVAL_READ_REG) < TIMEOUT_READ_REG); + + if ((cnt * INTERVAL_READ_REG) >= TIMEOUT_READ_REG) { + FTS_INFO("fw is invalid, need read boot id"); + + id_cmd[0] = 0x55; + id_cmd[1] = 0xAA; + ret = fts_i2c_write(client, id_cmd, 2); + if (ret < 0) { + FTS_ERROR("55 AA cmd write fail"); + return ret; + } + + id_cmd[0] = 0x90; + id_cmd[1] = id_cmd[2] = id_cmd[3] = 0x00; + ret = fts_i2c_read(client, id_cmd, 4, boot_id, 2); + if (ret < 0) { + FTS_ERROR("read boot id cmd fail"); + return ret; + } + FTS_INFO("read boot id:%02x%02x", boot_id[0], boot_id[1]); + if ((boot_id[0] == chip_types.rom_idh) && (boot_id[1] == chip_types.rom_idl)) { + return 0; + } + } + + /* error: not get correct reg data */ + return -EPERM; +} + +/***************************************************************************** +* Name: fts_recover_state +* Brief: Need execute this function when reset +* Input: +* Output: +* Return: +*****************************************************************************/ +void fts_tp_state_recovery(struct i2c_client *client) +{ + /* wait tp stable */ + fts_wait_tp_to_valid_sharp(client); + /* recover TP charger state 0x8B */ + /* recover TP glove state 0xC0 */ + /* recover TP cover state 0xC1 */ + fts_ex_mode_recovery(client); + /* recover TP gesture state 0xD0 */ +#if FTS_GESTURE_EN + fts_gesture_recovery(client); +#endif + + fts_release_all_finger(); +} + + +/***************************************************************************** +* Name: fts_reset_proc +* Brief: Execute reset operation +* Input: hdelayms - delay time unit:ms +* Output: +* Return: +*****************************************************************************/ +int fts_reset_proc(int hdelayms) +{ + gpio_direction_output(fts_wq_data->pdata->reset_gpio, 0); + msleep(20); + gpio_direction_output(fts_wq_data->pdata->reset_gpio, 1); + msleep(hdelayms); + + return 0; +} + +/***************************************************************************** +* Name: fts_irq_disable +* Brief: disable irq +* Input: +* sync: +* Output: +* Return: +*****************************************************************************/ +void fts_irq_disable(void) +{ + unsigned long irqflags; + spin_lock_irqsave(&fts_wq_data->irq_lock, irqflags); + + if (!fts_wq_data->irq_disable) { + + disable_irq_nosync(fts_wq_data->client->irq); + fts_wq_data->irq_disable = 1; + } + + spin_unlock_irqrestore(&fts_wq_data->irq_lock, irqflags); +} + +/***************************************************************************** +* Name: fts_irq_enable +* Brief: enable irq +* Input: +* Output: +* Return: +*****************************************************************************/ +void fts_irq_enable(void) +{ + unsigned long irqflags = 0; + spin_lock_irqsave(&fts_wq_data->irq_lock, irqflags); + + if (fts_wq_data->irq_disable) { + enable_irq(fts_wq_data->client->irq); + fts_wq_data->irq_disable = 0; + } + + spin_unlock_irqrestore(&fts_wq_data->irq_lock, irqflags); +} + +/***************************************************************************** +* Name: fts_input_dev_init +* Brief: input dev init +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_input_dev_init(struct i2c_client *client, struct fts_ts_data *data, struct input_dev *input_dev, struct fts_ts_platform_data *pdata) +{ + int err, len; + + FTS_FUNC_ENTER(); + + /* Init and register Input device */ + input_dev->name = FTS_DRIVER_NAME; + input_dev->id.bustype = BUS_I2C; + input_dev->dev.parent = &client->dev; + + input_set_drvdata(input_dev, data); + i2c_set_clientdata(client, data); + + __set_bit(EV_KEY, input_dev->evbit); + if (data->pdata->have_key) { + FTS_DEBUG("set key capabilities"); + for (len = 0; len < data->pdata->key_number; len++) { + input_set_capability(input_dev, EV_KEY, data->pdata->keys[len]); + } + } + __set_bit(EV_ABS, input_dev->evbit); + __set_bit(BTN_TOUCH, input_dev->keybit); + __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); + +#if FTS_MT_PROTOCOL_B_EN + input_mt_init_slots(input_dev, pdata->max_touch_number, INPUT_MT_DIRECT); +#else + input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, 0x0f, 0, 0); +#endif + input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min, pdata->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min, pdata->y_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 0xFF, 0, 0); +#if FTS_REPORT_PRESSURE_EN + input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 0xFF, 0, 0); +#endif + + err = input_register_device(input_dev); + if (err) { + FTS_ERROR("Input device registration failed"); + goto free_inputdev; + } + + FTS_FUNC_EXIT(); + + return 0; + +free_inputdev: + input_free_device(input_dev); + FTS_FUNC_EXIT(); + return err; + +} + +/***************************************************************************** +* Power Control +*****************************************************************************/ +#if FTS_POWER_SOURCE_CUST_EN +static int fts_power_source_init(struct fts_ts_data *data) +{ + int rc; + + FTS_FUNC_ENTER(); + + data->vdd = regulator_get(&data->client->dev, "vdd"); + if (IS_ERR(data->vdd)) { + rc = PTR_ERR(data->vdd); + FTS_ERROR("Regulator get failed vdd rc=%d", rc); + } + + if (regulator_count_voltages(data->vdd) > 0) { + rc = regulator_set_voltage(data->vdd, FTS_VTG_MIN_UV, FTS_VTG_MAX_UV); + if (rc) { + FTS_ERROR("Regulator set_vtg failed vdd rc=%d", rc); + goto reg_vdd_put; + } + } + + data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c"); + if (IS_ERR(data->vcc_i2c)) { + rc = PTR_ERR(data->vcc_i2c); + FTS_ERROR("Regulator get failed vcc_i2c rc=%d", rc); + goto reg_vdd_set_vtg; + } + + if (regulator_count_voltages(data->vcc_i2c) > 0) { + rc = regulator_set_voltage(data->vcc_i2c, FTS_I2C_VTG_MIN_UV, FTS_I2C_VTG_MAX_UV); + if (rc) { + FTS_ERROR("Regulator set_vtg failed vcc_i2c rc=%d", rc); + goto reg_vcc_i2c_put; + } + } + + FTS_FUNC_EXIT(); + return 0; + +reg_vcc_i2c_put: + regulator_put(data->vcc_i2c); +reg_vdd_set_vtg: + if (regulator_count_voltages(data->vdd) > 0) + regulator_set_voltage(data->vdd, 0, FTS_VTG_MAX_UV); +reg_vdd_put: + regulator_put(data->vdd); + FTS_FUNC_EXIT(); + return rc; +} + +static int fts_power_source_ctrl(struct fts_ts_data *data, int enable) +{ + int rc; + + FTS_FUNC_ENTER(); + if (enable) { + rc = regulator_enable(data->vdd); + if (rc) { + FTS_ERROR("Regulator vdd enable failed rc=%d", rc); + } + + rc = regulator_enable(data->vcc_i2c); + if (rc) { + FTS_ERROR("Regulator vcc_i2c enable failed rc=%d", rc); + } + } else { + rc = regulator_disable(data->vdd); + if (rc) { + FTS_ERROR("Regulator vdd disable failed rc=%d", rc); + } + rc = regulator_disable(data->vcc_i2c); + if (rc) { + FTS_ERROR("Regulator vcc_i2c disable failed rc=%d", rc); + } + } + FTS_FUNC_EXIT(); + return 0; +} + +#endif + + +/***************************************************************************** +* Reprot related +*****************************************************************************/ +/***************************************************************************** +* Name: fts_release_all_finger +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static void fts_release_all_finger(void) +{ +#if FTS_MT_PROTOCOL_B_EN + unsigned int finger_count = 0; + + for (finger_count = 0; finger_count < fts_wq_data->pdata->max_touch_number; finger_count++) { + input_mt_slot(fts_input_dev, finger_count); + input_mt_report_slot_state(fts_input_dev, MT_TOOL_FINGER, false); + } +#else + input_mt_sync(fts_input_dev); +#endif + input_report_key(fts_input_dev, BTN_TOUCH, 0); + input_sync(fts_input_dev); +} + + +#if (FTS_DEBUG_EN && (FTS_DEBUG_LEVEL == 2)) +static void fts_show_touch_buffer(u8 *buf, int point_num) +{ + int len = point_num * FTS_ONE_TCH_LEN; + int count = 0; + int i; + + memset(g_sz_debug, 0, 1024); + if (len > (POINT_READ_BUF-3)) { + len = POINT_READ_BUF-3; + } else if (len == 0) { + len += FTS_ONE_TCH_LEN; + } + count += sprintf(g_sz_debug, "%02X,%02X,%02X", buf[0], buf[1], buf[2]); + for (i = 0; i < len; i++) { + count += sprintf(g_sz_debug+count, ",%02X", buf[i+3]); + } + FTS_DEBUG("buffer: %s", g_sz_debug); +} +#endif + +static int fts_input_dev_report_key_event(struct ts_event *event, struct fts_ts_data *data) +{ + int i; + + if (data->pdata->have_key) { + if ((1 == event->touch_point || 1 == event->point_num) && + (event->au16_y[0] == data->pdata->key_y_coord)) { + + if (event->point_num == 0) { + FTS_DEBUG("Keys All Up!"); + for (i = 0; i < data->pdata->key_number; i++) { + input_report_key(data->input_dev, data->pdata->keys[i], 0); + } + } else { + for (i = 0; i < data->pdata->key_number; i++) { + if (event->au16_x[0] > (data->pdata->key_x_coords[i] - FTS_KEY_WIDTH) && + event->au16_x[0] < (data->pdata->key_x_coords[i] + FTS_KEY_WIDTH)) { + + if (event->au8_touch_event[i] == 0 || + event->au8_touch_event[i] == 2) { + input_report_key(data->input_dev, data->pdata->keys[i], 1); + FTS_DEBUG("Key%d(%d, %d) DOWN!", i, event->au16_x[0], event->au16_y[0]); + } else { + input_report_key(data->input_dev, data->pdata->keys[i], 0); + FTS_DEBUG("Key%d(%d, %d) Up!", i, event->au16_x[0], event->au16_y[0]); + } + break; + } + } + } + input_sync(data->input_dev); + return 0; + } + } + + return -EPERM; +} + +#if FTS_MT_PROTOCOL_B_EN +static int fts_input_dev_report_b(struct ts_event *event, struct fts_ts_data *data) +{ + int i = 0; + int uppoint = 0; + int touchs = 0; + for (i = 0; i < event->touch_point; i++) { + input_mt_slot(data->input_dev, event->au8_finger_id[i]); + + if (event->au8_touch_event[i] == FTS_TOUCH_DOWN || event->au8_touch_event[i] == FTS_TOUCH_CONTACT) { + input_report_key(data->input_dev, BTN_TOUCH, 1); + + input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->au8_finger_id[i]); + +#if FTS_REPORT_PRESSURE_EN +#if FTS_FORCE_TOUCH_EN + if (event->pressure[i] <= 0) { + FTS_ERROR("[B]Illegal pressure: %d", event->pressure[i]); + event->pressure[i] = 1; + } +#else + +#endif + +#endif + + if (event->area[i] <= 0) { + FTS_ERROR("[B]Illegal touch-major: %d", event->area[i]); + event->area[i] = 1; + } + input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->area[i]); + input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->au16_x[i]); + input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->au16_y[i]); + printk("event->au16_x[i] : %d, event->au16_y[i]: %d\n", event->au16_x[i], event->au16_y[i]); + touchs |= BIT(event->au8_finger_id[i]); + data->touchs |= BIT(event->au8_finger_id[i]); + } else { + uppoint++; + input_report_key(data->input_dev, BTN_TOUCH, 0); + + input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, -1); +#if FTS_REPORT_PRESSURE_EN + +#endif + data->touchs &= ~BIT(event->au8_finger_id[i]); + FTS_DEBUG("[B]P%d UP!", event->au8_finger_id[i]); + } + } + + if (unlikely(data->touchs ^ touchs)) { + for (i = 0; i < data->pdata->max_touch_number; i++) { + if (BIT(i) & (data->touchs ^ touchs)) { + FTS_DEBUG("[B]P%d UP!", i); + input_mt_slot(data->input_dev, i); + input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, -1); +#if FTS_REPORT_PRESSURE_EN + +#endif + } + } + } + + data->touchs = touchs; + + + if (event->point_num == 0) { + for (i = 0; i < data->pdata->max_touch_number; i++) { + if (BIT(i) & (data->touchs ^ touchs)) { + input_mt_slot(data->input_dev, i); + input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, -1); + } + } + } + + if (event->touch_point == uppoint) { + input_report_key(data->input_dev, BTN_TOUCH, 0); + } else { + input_report_key(data->input_dev, BTN_TOUCH, event->touch_point > 0); + } + + input_sync(data->input_dev); + + return 0; + +} + +#else +static int fts_input_dev_report_a(struct ts_event *event, struct fts_ts_data *data) +{ + int i = 0; + int uppoint = 0; + int touchs = 0; + + for (i = 0; i < event->touch_point; i++) { + + if (event->au8_touch_event[i] == FTS_TOUCH_DOWN || event->au8_touch_event[i] == FTS_TOUCH_CONTACT) { + input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->au8_finger_id[i]); +#if FTS_REPORT_PRESSURE_EN +#if FTS_FORCE_TOUCH_EN + if (event->pressure[i] <= 0) { + FTS_ERROR("[B]Illegal pressure: %d", event->pressure[i]); + event->pressure[i] = 1; + } +#else + event->pressure[i] = 0x3f; +#endif + input_report_abs(data->input_dev, ABS_MT_PRESSURE, event->pressure[i]); +#endif + + if (event->area[i] <= 0) { + FTS_ERROR("[B]Illegal touch-major: %d", event->area[i]); + event->area[i] = 1; + } + input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->area[i]); + + input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->au16_x[i]); + input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->au16_y[i]); + + input_mt_sync(data->input_dev); + +#if FTS_REPORT_PRESSURE_EN + event->au16_y[i], event->pressure[i], event->area[i]); +#endif + } else { + uppoint++; + } + } + + data->touchs = touchs; + if (event->touch_point == uppoint) { + FTS_DEBUG("Points All Up!"); + input_report_key(data->input_dev, BTN_TOUCH, 0); + input_mt_sync(data->input_dev); + } else { + input_report_key(data->input_dev, BTN_TOUCH, event->touch_point > 0); + } + + input_sync(data->input_dev); + + return 0; +} +#endif + +/***************************************************************************** +* Name: fts_read_touchdata +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_read_touchdata(struct fts_ts_data *data) +{ + u8 buf[POINT_READ_BUF] = { 0 }; + u8 pointid = FTS_MAX_ID; + int ret = -1; + int i; + struct ts_event *event = &(data->event); + +#if FTS_GESTURE_EN + { + u8 state; + if (data->suspended) { + fts_i2c_read_reg(data->client, FTS_REG_GESTURE_EN, &state); + printk("state :%d\n", state); + if (state == 1) { + fts_gesture_readdata(data->client); + return 1; + } + } + } +#endif + +#if FTS_PSENSOR_EN + if ((fts_sensor_read_data(data) != 0) && (data->suspended == 1)) { + return 1; + } +#endif + + +#if FTS_READ_TOUCH_BUFFER_DIVIDED + memset(buf, 0xFF, POINT_READ_BUF); + memset(event, 0, sizeof(struct ts_event)); + + buf[0] = 0x00; + ret = fts_i2c_read(data->client, buf, 1, buf, (3 + FTS_ONE_TCH_LEN)); + if (ret < 0) { + FTS_ERROR("%s read touchdata failed.", __func__); + return ret; + } + event->touch_point = 0; + event->point_num = buf[FTS_TOUCH_POINT_NUM] & 0x0F; + if (event->point_num > data->pdata->max_touch_number) + event->point_num = data->pdata->max_touch_number; + + if (event->point_num > 1) { + buf[9] = 0x09; + fts_i2c_read(data->client, buf+9, 1, buf+9, (event->point_num - 1) * FTS_ONE_TCH_LEN); + } +#else + ret = fts_i2c_read(data->client, buf, 1, buf, POINT_READ_BUF); + if (ret < 0) { + FTS_ERROR("[B]Read touchdata failed, ret: %d", ret); + return ret; + } + +#if FTS_POINT_REPORT_CHECK_EN + fts_point_report_check_queue_work(); +#endif + + memset(event, 0, sizeof(struct ts_event)); + event->point_num = buf[FTS_TOUCH_POINT_NUM] & 0x0F; + if (event->point_num > data->pdata->max_touch_number) + event->point_num = data->pdata->max_touch_number; + event->touch_point = 0; +#endif + +#if (FTS_DEBUG_EN && (FTS_DEBUG_LEVEL == 2)) + fts_show_touch_buffer(buf, event->point_num); +#endif + + for (i = 0; i < data->pdata->max_touch_number; i++) { + pointid = (buf[FTS_TOUCH_ID_POS + FTS_ONE_TCH_LEN * i]) >> 4; + if (pointid >= FTS_MAX_ID) + break; + else + event->touch_point++; + + event->au16_x[i] = + (s16) (buf[FTS_TOUCH_X_H_POS + FTS_ONE_TCH_LEN * i] & 0x0F) << + 8 | (s16) buf[FTS_TOUCH_X_L_POS + FTS_ONE_TCH_LEN * i]; + event->au16_y[i] = + (s16) (buf[FTS_TOUCH_Y_H_POS + FTS_ONE_TCH_LEN * i] & 0x0F) << + 8 | (s16) buf[FTS_TOUCH_Y_L_POS + FTS_ONE_TCH_LEN * i]; + event->au8_touch_event[i] = + buf[FTS_TOUCH_EVENT_POS + FTS_ONE_TCH_LEN * i] >> 6; + event->au8_finger_id[i] = + (buf[FTS_TOUCH_ID_POS + FTS_ONE_TCH_LEN * i]) >> 4; + event->area[i] = + (buf[FTS_TOUCH_AREA_POS + FTS_ONE_TCH_LEN * i]) >> 4; + event->pressure[i] = + (s16) buf[FTS_TOUCH_PRE_POS + FTS_ONE_TCH_LEN * i]; + + if (0 == event->area[i]) + event->area[i] = 0x09; + + if (0 == event->pressure[i]) + event->pressure[i] = 0x3f; + + if ((event->au8_touch_event[i] == 0 || event->au8_touch_event[i] == 2) && (event->point_num == 0)) + break; + } + return 0; +} + +/***************************************************************************** +* Name: fts_report_value +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static void fts_report_value(struct fts_ts_data *data) +{ + struct ts_event *event = &data->event; + + + if (0 == fts_input_dev_report_key_event(event, data)) { + return; + } + +#if FTS_MT_PROTOCOL_B_EN + fts_input_dev_report_b(event, data); +#else + fts_input_dev_report_a(event, data); +#endif + + return; + +} + +/***************************************************************************** +* Name: fts_ts_interrupt +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static irqreturn_t fts_ts_interrupt(int irq, void *dev_id) +{ + struct fts_ts_data *fts_ts = dev_id; + int ret = -1; + + if (!fts_ts) { + FTS_ERROR("[INTR]: Invalid fts_ts"); + return IRQ_HANDLED; + } + +#if FTS_ESDCHECK_EN + fts_esdcheck_set_intr(1); +#endif + + ret = fts_read_touchdata(fts_wq_data); + + if (ret == 0) { + fts_report_value(fts_wq_data); + } + +#if FTS_ESDCHECK_EN + fts_esdcheck_set_intr(0); +#endif + + return IRQ_HANDLED; +} + +/***************************************************************************** +* Name: fts_gpio_configure +* Brief: Configure IRQ&RESET GPIO +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_gpio_configure(struct fts_ts_data *data) +{ + int err = 0; + + FTS_FUNC_ENTER(); + /* request irq gpio */ + if (gpio_is_valid(data->pdata->irq_gpio)) { + err = gpio_request(data->pdata->irq_gpio, "fts_irq_gpio"); + if (err) { + FTS_ERROR("[GPIO]irq gpio request failed"); + goto err_irq_gpio_req; + } + + err = gpio_direction_input(data->pdata->irq_gpio); + if (err) { + FTS_ERROR("[GPIO]set_direction for irq gpio failed"); + goto err_irq_gpio_dir; + } + } + /* request reset gpio */ + if (gpio_is_valid(data->pdata->reset_gpio)) { + err = gpio_request(data->pdata->reset_gpio, "fts_reset_gpio"); + if (err) { + FTS_ERROR("[GPIO]reset gpio request failed"); + goto err_irq_gpio_dir; + } + + err = gpio_direction_output(data->pdata->reset_gpio, 1); + if (err) { + FTS_ERROR("[GPIO]set_direction for reset gpio failed"); + goto err_reset_gpio_dir; + } + } + + FTS_FUNC_EXIT(); + return 0; + +err_reset_gpio_dir: + if (gpio_is_valid(data->pdata->reset_gpio)) + gpio_free(data->pdata->reset_gpio); +err_irq_gpio_dir: + if (gpio_is_valid(data->pdata->irq_gpio)) + gpio_free(data->pdata->irq_gpio); +err_irq_gpio_req: + FTS_FUNC_EXIT(); + return err; +} + + +/***************************************************************************** +* Name: fts_get_dt_coords +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_get_dt_coords(struct device *dev, char *name, + struct fts_ts_platform_data *pdata) { + u32 coords[FTS_COORDS_ARR_SIZE]; + struct property *prop; + struct device_node *np = dev->of_node; + int coords_size, rc; + + prop = of_find_property(np, name, NULL); + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + + + coords_size = prop->length / sizeof(u32); + if (coords_size != FTS_COORDS_ARR_SIZE) { + FTS_ERROR("invalid %s", name); + return -EINVAL; + } + + rc = of_property_read_u32_array(np, name, coords, coords_size); + if (rc && (rc != -EINVAL)) { + FTS_ERROR("Unable to read %s", name); + return rc; + } + + if (!strcmp(name, "focaltech,display-coords")) { + pdata->x_min = coords[0]; + pdata->y_min = coords[1]; + pdata->x_max = coords[2]; + pdata->y_max = coords[3]; + } else { + FTS_ERROR("unsupported property %s", name); + return -EINVAL; + } + + return 0; +} + +/***************************************************************************** +* Name: fts_parse_dt +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_parse_dt(struct device *dev, struct fts_ts_platform_data *pdata) +{ + int rc; + struct device_node *np = dev->of_node; + u32 temp_val; + + FTS_FUNC_ENTER(); + + rc = fts_get_dt_coords(dev, "focaltech,display-coords", pdata); + if (rc) + FTS_ERROR("Unable to get display-coords"); + + /* key */ + pdata->have_key = of_property_read_bool(np, "focaltech,have-key"); + if (pdata->have_key) { + rc = of_property_read_u32(np, "focaltech,key-number", &pdata->key_number); + if (rc) { + FTS_ERROR("Key number undefined!"); + } + rc = of_property_read_u32_array(np, "focaltech,keys", + pdata->keys, pdata->key_number); + if (rc) { + FTS_ERROR("Keys undefined!"); + } + rc = of_property_read_u32(np, "focaltech,key-y-coord", &pdata->key_y_coord); + if (rc) { + FTS_ERROR("Key Y Coord undefined!"); + } + rc = of_property_read_u32_array(np, "focaltech,key-x-coords", + pdata->key_x_coords, pdata->key_number); + if (rc) { + FTS_ERROR("Key X Coords undefined!"); + } + FTS_DEBUG("%d: (%d, %d, %d), [%d, %d, %d][%d]", + pdata->key_number, pdata->keys[0], pdata->keys[1], pdata->keys[2], + pdata->key_x_coords[0], pdata->key_x_coords[1], pdata->key_x_coords[2], + pdata->key_y_coord); + } + + /* reset, irq gpio info */ + pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio", 0, &pdata->reset_gpio_flags); + if (pdata->reset_gpio < 0) { + FTS_ERROR("Unable to get reset_gpio"); + } + + pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio", 0, &pdata->irq_gpio_flags); + if (pdata->irq_gpio < 0) { + FTS_ERROR("Unable to get irq_gpio"); + } + + rc = of_property_read_u32(np, "focaltech,max-touch-number", &temp_val); + if (!rc) { + pdata->max_touch_number = temp_val; + FTS_DEBUG("max_touch_number=%d", pdata->max_touch_number); + } else { + FTS_ERROR("Unable to get max-touch-number"); + pdata->max_touch_number = FTS_MAX_POINTS; + } + + + + FTS_FUNC_EXIT(); + return 0; +} + +#if defined(CONFIG_FB) +/***************************************************************************** +* Name: fb_notifier_callback +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct fts_ts_data *fts_data = + container_of(self, struct fts_ts_data, fb_notif); + + if (evdata && evdata->data && event == FB_EVENT_BLANK && + fts_data && fts_data->client) { + blank = evdata->data; + if (*blank == FB_BLANK_UNBLANK) + fts_ts_resume(&fts_data->client->dev); + else if (*blank == FB_BLANK_POWERDOWN) + fts_ts_suspend(&fts_data->client->dev); + } + + return 0; +} +#elif defined(CONFIG_HAS_EARLYSUSPEND) +/***************************************************************************** +* Name: fts_ts_early_suspend +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static void fts_ts_early_suspend(struct early_suspend *handler) +{ + struct fts_ts_data *data = container_of(handler, + struct fts_ts_data, + early_suspend); + + fts_ts_suspend(&data->client->dev); +} + +/***************************************************************************** +* Name: fts_ts_late_resume +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static void fts_ts_late_resume(struct early_suspend *handler) +{ + struct fts_ts_data *data = container_of(handler, + struct fts_ts_data, + early_suspend); + + fts_ts_resume(&data->client->dev); +} +#endif + +/***************************************************************************** +* Name: fts_ts_probe +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +int ft8716_suspend = 0; +static int fts_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct fts_ts_platform_data *pdata; + struct fts_ts_data *data; + struct input_dev *input_dev; + int err; + unsigned char auc_i2c_write_buf[10]; + u8 r_buf[10] = {0}; + + + FTS_FUNC_ENTER(); + + /* 1. Get Platform data */ + if (client->dev.of_node) { + pdata = devm_kzalloc(&client->dev, + sizeof(struct fts_ts_platform_data), + GFP_KERNEL); + if (!pdata) { + FTS_ERROR("[MEMORY]Failed to allocate memory"); + FTS_FUNC_EXIT(); + ft8716_suspend = 1; + return -ENOMEM; + } + err = fts_parse_dt(&client->dev, pdata); + if (err) { + FTS_ERROR("[DTS]DT parsing failed"); + } + } else { + pdata = client->dev.platform_data; + } + + if (!pdata) { + FTS_ERROR("Invalid pdata"); + FTS_FUNC_EXIT(); + ft8716_suspend = 1; + return -EINVAL; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + FTS_ERROR("I2C not supported"); + FTS_FUNC_EXIT(); + ft8716_suspend = 1; + return -ENODEV; + } + + data = devm_kzalloc(&client->dev, sizeof(struct fts_ts_data), GFP_KERNEL); + if (!data) { + FTS_ERROR("[MEMORY]Failed to allocate memory"); + FTS_FUNC_EXIT(); + ft8716_suspend = 1; + return -ENOMEM; + } + + input_dev = input_allocate_device(); + if (!input_dev) { + FTS_ERROR("[INPUT]Failed to allocate input device"); + FTS_FUNC_EXIT(); + ft8716_suspend = 1; + return -ENOMEM; + } + + + + data->input_dev = input_dev; + data->client = client; + data->pdata = pdata; + + fts_wq_data = data; + fts_i2c_client = client; + fts_input_dev = input_dev; + + spin_lock_init(&fts_wq_data->irq_lock); + + fts_input_dev_init(client, data, input_dev, pdata); + + + fts_ctpm_get_upgrade_array(); + +#if FTS_POWER_SOURCE_CUST_EN + fts_power_source_init(data); + fts_power_source_ctrl(data, 1); +#endif + + err = fts_gpio_configure(data); + if (err < 0) { + FTS_ERROR("[GPIO]Failed to configure the gpios"); + goto free_gpio; + } + + fts_reset_proc(200); + +#if FTS_POINT_REPORT_CHECK_EN + fts_point_report_check_init(); +#endif + + err = request_threaded_irq(client->irq, NULL, fts_ts_interrupt, + pdata->irq_gpio_flags | IRQF_ONESHOT | IRQF_TRIGGER_FALLING, + client->dev.driver->name, data); + + if (err) { + FTS_ERROR("Request irq failed!"); + goto free_gpio; + } + + err = fts_wait_tp_to_valid_sharp(client); + if (err) { + FTS_ERROR("fts_wait_tp_to_valid_sharp failed!"); + + goto free_irq; + } + + + fts_irq_disable(); + + + +#ifdef FTS_LOCK_DOWN_INFO + + err = fts_i2c_write_reg(client, 0x90, 0x20); + if (err < 0) + printk("[FTS] i2c write 0x90 err\n"); + + msleep(5); + auc_i2c_write_buf[0] = 0x99; + err = fts_i2c_read(client, auc_i2c_write_buf, 1, r_buf, 8); + if (err < 0) + printk("[FTS] i2c read 0x99 err\n"); + + sprintf(ftp_lockdown_info, "%02x%02x%02x%02x%02x%02x%02x%02x", \ + r_buf[0], r_buf[1], r_buf[2], r_buf[3], r_buf[4], r_buf[5], r_buf[6], r_buf[7]); + + printk("tpd_probe, ft8716_ctpm_LockDownInfo_get_from_boot, tp_lockdown_info=%s\n", ftp_lockdown_info); + + fts_lockdown_status_proc = proc_create(FTS_PROC_LOCKDOWN_FILE, 0644, NULL, &fts_lockdown_proc_fops); + if (fts_lockdown_status_proc == NULL) { + printk("fts, create_proc_entry ctp_lockdown_status_proc failed\n"); + } +#endif + +#if FTS_PSENSOR_EN + if (fts_sensor_init(data) != 0) { + FTS_ERROR("fts_sensor_init failed!"); + FTS_FUNC_EXIT(); + return 0; + } +#endif + +#if FTS_APK_NODE_EN + fts_create_apk_debug_channel(client); +#endif + +#if FTS_SYSFS_NODE_EN + fts_create_sysfs(client); +#endif + + fts_ex_mode_init(client); + +#if FTS_GESTURE_EN + fts_gesture_init(input_dev, client); +#endif + +#if FTS_ESDCHECK_EN + fts_esdcheck_init(); +#endif + + fts_irq_enable(); + +#if FTS_AUTO_UPGRADE_EN + fts_ctpm_upgrade_init(); +#endif + + +#if FTS_TEST_EN + fts_test_init(client); +#endif + +#if defined(CONFIG_FB) + data->fb_notif.notifier_call = fb_notifier_callback; + err = fb_register_client(&data->fb_notif); + if (err) + FTS_ERROR("[FB]Unable to register fb_notifier: %d", err); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + FTS_SUSPEND_LEVEL; + data->early_suspend.suspend = fts_ts_early_suspend; + data->early_suspend.resume = fts_ts_late_resume; + register_early_suspend(&data->early_suspend); +#endif + + FTS_FUNC_EXIT(); + return 0; + +free_irq: + free_irq(client->irq, data); + printk("%s:free irq\n", __func__); +free_gpio: + if (gpio_is_valid(pdata->reset_gpio)) + gpio_free(pdata->reset_gpio); + if (gpio_is_valid(pdata->irq_gpio)) + gpio_free(pdata->irq_gpio); + ft8716_suspend = 1; + + printk("%s:free gpio\n", __func__); + return err; + +} + +/***************************************************************************** +* Name: fts_ts_remove +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_ts_remove(struct i2c_client *client) +{ + struct fts_ts_data *data = i2c_get_clientdata(client); + + FTS_FUNC_ENTER(); + cancel_work_sync(&data->touch_event_work); + +#if FTS_PSENSOR_EN + fts_sensor_remove(data); +#endif + +#if FTS_POINT_REPORT_CHECK_EN + fts_point_report_check_exit(); +#endif + +#if FTS_APK_NODE_EN + fts_release_apk_debug_channel(); +#endif + +#if FTS_SYSFS_NODE_EN + fts_remove_sysfs(client); +#endif + + fts_ex_mode_exit(client); + +#if FTS_AUTO_UPGRADE_EN + cancel_work_sync(&fw_update_work); +#endif + +#if defined(CONFIG_FB) + if (fb_unregister_client(&data->fb_notif)) + FTS_ERROR("Error occurred while unregistering fb_notifier."); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + unregister_early_suspend(&data->early_suspend); +#endif + free_irq(client->irq, data); + + if (gpio_is_valid(data->pdata->reset_gpio)) + gpio_free(data->pdata->reset_gpio); + + if (gpio_is_valid(data->pdata->irq_gpio)) + gpio_free(data->pdata->irq_gpio); + + input_unregister_device(data->input_dev); + +#if FTS_TEST_EN + fts_test_exit(client); +#endif + +#if FTS_ESDCHECK_EN + fts_esdcheck_exit(); +#endif + + FTS_FUNC_EXIT(); + return 0; +} + +/***************************************************************************** +* Name: fts_ts_suspend +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +extern struct mdss_panel_data *panel_data; +extern int panel_suspend_reset_flag; + +extern int mdss_dsi_panel_power_off(struct mdss_panel_data *pdata); +#if FTS_GESTURE_EN + extern int ft8716_gesture_func_on; +#endif + + +static int fts_ts_suspend(struct device *dev) +{ + struct fts_ts_data *data = dev_get_drvdata(dev); + int retval = 0; + + FTS_FUNC_ENTER(); + if (data->suspended) { + FTS_INFO("Already in suspend state"); + FTS_FUNC_EXIT(); + return -EPERM; + } + + +#if FTS_ESDCHECK_EN + fts_esdcheck_suspend(); +#endif + + +#if FTS_GESTURE_EN + retval = fts_gesture_suspend(data->client); + if (retval == 0) { + /* Enter into gesture mode(suspend) */ + retval = enable_irq_wake(fts_wq_data->client->irq); + if (retval) + FTS_ERROR("%s: set_irq_wake failed", __func__); + data->suspended = true; + FTS_FUNC_EXIT(); + return 0; + } +#endif + +#if FTS_PSENSOR_EN + if (fts_sensor_suspend(data) != 0) { + enable_irq_wake(data->client->irq); + data->suspended = true; + return 0; + } +#endif + + fts_irq_disable(); + + ft8716_suspend = 1; + + /* TP enter sleep mode */ + retval = fts_i2c_write_reg(data->client, FTS_REG_POWER_MODE, FTS_REG_POWER_MODE_SLEEP_VALUE); + if (retval < 0) { + FTS_ERROR("Set TP to sleep mode fail, ret=%d!", retval); + } + data->suspended = true; + + mdelay(10); + + if (!ft8716_gesture_func_on) { + printk("set rst in TP_suspend\n"); + retval = mdss_dsi_panel_power_off(panel_data); + if (retval < 0) + printk("Enter %s mdss_dsi_panel_power_off fail\n", __func__); + } + ft8716_suspend = 0; + FTS_FUNC_EXIT(); + + return 0; +} + +/***************************************************************************** +* Name: fts_ts_resume +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_ts_resume(struct device *dev) +{ + struct fts_ts_data *data = dev_get_drvdata(dev); + + FTS_FUNC_ENTER(); + + if (!data->suspended) { + FTS_DEBUG("Already in awake state"); + FTS_FUNC_EXIT(); + return -EPERM; + } + +#if (!FTS_CHIP_IDC) + fts_reset_proc(200); +#endif + + fts_tp_state_recovery(data->client); + +#if FTS_GESTURE_EN + if (fts_gesture_resume(data->client) == 0) { + int err; + err = disable_irq_wake(data->client->irq); + if (err) + FTS_ERROR("%s: disable_irq_wake failed", __func__); + data->suspended = false; + + #if FTS_ESDCHECK_EN + fts_esdcheck_resume(); + #endif + + FTS_FUNC_EXIT(); + return 0; + } +#endif + +#if FTS_PSENSOR_EN + if (fts_sensor_resume(data) != 0) { + disable_irq_wake(data->client->irq); + data->suspended = false; + FTS_FUNC_EXIT(); + return 0; + } +#endif + + data->suspended = false; + + fts_irq_enable(); + + + FTS_FUNC_EXIT(); + return 0; +} + +/***************************************************************************** +* I2C Driver +*****************************************************************************/ +static const struct i2c_device_id fts_ts_id[] = { + {FTS_DRIVER_NAME, 0}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, fts_ts_id); + +static struct of_device_id fts_match_table[] = { + { .compatible = "focaltech,fts", }, + { }, +}; + +static struct i2c_driver fts_ts_driver = { + .probe = fts_ts_probe, + .remove = fts_ts_remove, + .driver = { + .name = FTS_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = fts_match_table, + }, + .id_table = fts_ts_id, +}; + +/***************************************************************************** +* Name: fts_ts_init +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int __init fts_ts_init(void) +{ + int ret = 0; + + FTS_FUNC_ENTER(); + ret = i2c_add_driver(&fts_ts_driver); + if (ret != 0) { + FTS_ERROR("Focaltech touch screen driver init failed!"); + } + FTS_FUNC_EXIT(); + return ret; +} + +/***************************************************************************** +* Name: fts_ts_exit +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static void __exit fts_ts_exit(void) +{ + i2c_del_driver(&fts_ts_driver); +} + +module_init(fts_ts_init); +module_exit(fts_ts_exit); + +MODULE_AUTHOR("FocalTech Driver Team"); +MODULE_DESCRIPTION("FocalTech Touchscreen Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/ft8716/focaltech_core.h b/drivers/input/touchscreen/ft8716/focaltech_core.h new file mode 100644 index 0000000000000..e6cae02ef73e7 --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_core.h @@ -0,0 +1,197 @@ +/* + * + * FocalTech TouchScreen driver. + * + * Copyright (c) 2010-2016, Focaltech Ltd. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +/***************************************************************************** +* +* File Name: focaltech_core.h + +* Author: Focaltech Driver Team +* +* Created: 2016-08-08 +* +* Abstract: +* +* Reference: +* +*****************************************************************************/ + +#ifndef __LINUX_FOCALTECH_CORE_H__ +#define __LINUX_FOCALTECH_CORE_H__ +/***************************************************************************** +* Included header files +*****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "focaltech_common.h" +#include "focaltech_flash.h" + +/***************************************************************************** +* Private constant and macro definitions using #define +*****************************************************************************/ +#define LEN_FLASH_ECC_MAX 0xFFFE + +#define FTS_LOCK_DOWN_INFO 1 + +#define FTS_WORKQUEUE_NAME "fts_wq" + +#define FTS_MAX_POINTS 10 +#define FTS_KEY_WIDTH 50 +#define FTS_ONE_TCH_LEN 6 +#define POINT_READ_BUF (3 + FTS_ONE_TCH_LEN * FTS_MAX_POINTS) + +#define FTS_MAX_ID 0x0F +#define FTS_TOUCH_X_H_POS 3 +#define FTS_TOUCH_X_L_POS 4 +#define FTS_TOUCH_Y_H_POS 5 +#define FTS_TOUCH_Y_L_POS 6 +#define FTS_TOUCH_PRE_POS 7 +#define FTS_TOUCH_AREA_POS 8 +#define FTS_TOUCH_POINT_NUM 2 +#define FTS_TOUCH_EVENT_POS 3 +#define FTS_TOUCH_ID_POS 5 +#define FTS_COORDS_ARR_SIZE 4 + +#define FTS_TOUCH_DOWN 0 +#define FTS_TOUCH_UP 1 +#define FTS_TOUCH_CONTACT 2 + + +#define FTS_SYSFS_ECHO_ON(buf) ((strnicmp(buf, "1", 1) == 0) || \ + (strnicmp(buf, "on", 2) == 0)) +#define FTS_SYSFS_ECHO_OFF(buf) ((strnicmp(buf, "0", 1) == 0) || \ + (strnicmp(buf, "off", 3) == 0)) + +/***************************************************************************** +* Private enumerations, structures and unions using typedef +*****************************************************************************/ + + +struct fts_ts_platform_data { + u32 irq_gpio; + u32 irq_gpio_flags; + u32 reset_gpio; + u32 reset_gpio_flags; + bool have_key; + u32 key_number; + u32 keys[4]; + u32 key_y_coord; + u32 key_x_coords[4]; + u32 x_max; + u32 y_max; + u32 x_min; + u32 y_min; + u32 max_touch_number; +}; + +struct ts_event { + u16 au16_x[FTS_MAX_POINTS]; /*x coordinate */ + u16 au16_y[FTS_MAX_POINTS]; /*y coordinate */ + u16 pressure[FTS_MAX_POINTS]; + u8 au8_touch_event[FTS_MAX_POINTS]; /* touch event: 0 -- down; 1-- up; 2 -- contact */ + u8 au8_finger_id[FTS_MAX_POINTS]; /*touch ID */ + u8 area[FTS_MAX_POINTS]; + u8 touch_point; + u8 point_num; +}; + +struct fts_ts_data { + struct i2c_client *client; + struct input_dev *input_dev; + struct ts_event event; + const struct fts_ts_platform_data *pdata; +#if FTS_PSENSOR_EN + struct fts_psensor_platform_data *psensor_pdata; +#endif + struct work_struct touch_event_work; + struct workqueue_struct *ts_workqueue; + struct regulator *vdd; + struct regulator *vcc_i2c; + spinlock_t irq_lock; + u16 addr; + bool suspended; + u8 fw_ver[3]; + u8 fw_vendor_id; + int touchs; + int irq_disable; + +#if defined(CONFIG_FB) + struct notifier_block fb_notif; +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif +}; + + +#if FTS_PSENSOR_EN +struct fts_psensor_platform_data { + struct input_dev *input_psensor_dev; + struct sensors_classdev ps_cdev; + int tp_psensor_opened; + char tp_psensor_data; /* 0 near, 1 far */ + struct fts_ts_data *data; +}; + +int fts_sensor_init(struct fts_ts_data *data); +int fts_sensor_read_data(struct fts_ts_data *data); +int fts_sensor_suspend(struct fts_ts_data *data); +int fts_sensor_resume(struct fts_ts_data *data); +int fts_sensor_remove(struct fts_ts_data *data); +#endif + +/***************************************************************************** +* Static variables +*****************************************************************************/ +extern struct i2c_client *fts_i2c_client; +extern struct fts_ts_data *fts_wq_data; +extern struct input_dev *fts_input_dev; + + +/*global function */ +unsigned char ft8716_fw_LockDownInfo_get_from_boot(struct i2c_client *client, char *pProjectCode); + + +#endif /* __LINUX_FOCALTECH_CORE_H__ */ diff --git a/drivers/input/touchscreen/ft8716/focaltech_esdcheck.c b/drivers/input/touchscreen/ft8716/focaltech_esdcheck.c new file mode 100644 index 0000000000000..9281cc6b47f3e --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_esdcheck.c @@ -0,0 +1,449 @@ +/* + * + * FocalTech TouchScreen driver. + * + * Copyright (c) 2010-2016, FocalTech Systems, Ltd., all rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/***************************************************************************** +* +* File Name: focaltech_esdcheck.c +* +* Author: luoguojin +* +* Created: 2016-08-03 +* +* Abstract: ESD check function +* +* Version: v1.0 +* +* Revision History: +* v1.0: +* First release. By luougojin 2016-08-03 +*****************************************************************************/ + +/***************************************************************************** +* Included header files +*****************************************************************************/ +#include "focaltech_core.h" + +#if FTS_ESDCHECK_EN +/***************************************************************************** +* Private constant and macro definitions using #define +*****************************************************************************/ +#define ESDCHECK_WAIT_TIME 1000 + +/***************************************************************************** +* Private enumerations, structures and unions using typedef +*****************************************************************************/ +struct fts_esdcheck_st { + u8 active : 1; /* 1- esd check active, need check esd 0- no esd check */ + u8 suspend : 1; + u8 proc_debug : 1; /* apk or adb is accessing I2C */ + u8 intr : 1; /* 1- Interrupt trigger */ + u8 unused : 4; + u8 flow_work_hold_cnt; /* Flow Work Cnt(reg0x91) keep a same value for x times. >=5 times is ESD, need reset */ + u8 flow_work_cnt_last; /* Save Flow Work Cnt(reg0x91) value */ + u32 hardware_reset_cnt; + u32 i2c_nack_cnt; + u32 i2c_dataerror_cnt; +}; + +/***************************************************************************** +* Static variables +*****************************************************************************/ +static struct delayed_work fts_esdcheck_work; +static struct workqueue_struct *fts_esdcheck_workqueue; +static struct fts_esdcheck_st fts_esdcheck_data; + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ + +/***************************************************************************** +* Static function prototypes +*****************************************************************************/ + +/***************************************************************************** +* functions body +*****************************************************************************/ +/***************************************************************************** +* Name: lcd_esdcheck +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +int lcd_need_reset; +static int tp_need_recovery; /* LCD reset cause Tp reset */ +int idc_esdcheck_lcderror(void) +{ + u8 val; + int ret; + + FTS_DEBUG("[ESD]Check LCD ESD"); + if ((tp_need_recovery == 1) && (lcd_need_reset == 0)) { + tp_need_recovery = 0; + /* LCD reset, need recover TP state */ + fts_tp_state_recovery(fts_i2c_client); + } + + ret = fts_i2c_read_reg(fts_i2c_client, FTS_REG_ESD_SATURATE, &val); + if (ret < 0) { + FTS_ERROR("[ESD]: Read ESD_SATURATE(0xED) failed ret=%d!", ret); + return -EIO; + } + + if (val == 0xAA) { + /* + * 1. Set flag lcd_need_reset = 1; + * 2. LCD driver need reset(recovery) LCD and set lcd_need_reset to 0 + * 3. recover TP state + */ + FTS_INFO("LCD ESD, Execute LCD reset!"); + lcd_need_reset = 1; + tp_need_recovery = 1; + } + + return 0; +} + +/***************************************************************************** +* Name: fts_esdcheck_tp_reset +* Brief: esd check algorithm +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_esdcheck_tp_reset(void) +{ + FTS_FUNC_ENTER(); + + fts_esdcheck_data.flow_work_hold_cnt = 0; + fts_esdcheck_data.hardware_reset_cnt++; + + fts_reset_proc(200); + fts_tp_state_recovery(fts_i2c_client); + + FTS_FUNC_EXIT(); + return 0; +} + +/***************************************************************************** +* Name: get_chip_id +* Brief: Read Chip Id 3 times +* Input: +* Output: +* Return: 1 - Read Chip Id 3 times failed +* 0 - Read Chip Id pass +*****************************************************************************/ +static bool get_chip_id(void) +{ + int err = 0; + int i = 0; + u8 reg_value = 0; + u8 reg_addr = 0; + + for (i = 0; i < 3; i++) { + reg_addr = FTS_REG_CHIP_ID; + err = fts_i2c_read(fts_i2c_client, ®_addr, 1, ®_value, 1); + + if (err < 0) { + FTS_ERROR("[ESD]: Read Reg 0xA3 failed ret = %d!!", err); + fts_esdcheck_data.i2c_nack_cnt++; + } else { + if ((reg_value == chip_types.chip_idh) || (reg_value == 0xEF)) /* Upgrade sometimes can't detect */ { + break; + } else { + fts_esdcheck_data.i2c_dataerror_cnt++; + } + } + } + + /* if can't get correct data in 3 times, then need hardware reset */ + if (i >= 3) { + FTS_ERROR("[ESD]: Read Chip id 3 times failed, need execute TP reset!!"); + return 1; + } + + return 0; +} + +/***************************************************************************** +* Name: get_flow_cnt +* Brief: Read flow cnt(0x91) +* Input: +* Output: +* Return: 1 - Reg 0x91(flow cnt) abnormal: hold a value for 5 times +* 0 - Reg 0x91(flow cnt) normal +*****************************************************************************/ +static bool get_flow_cnt(void) +{ + int err = 0; + u8 reg_value = 0; + u8 reg_addr = 0; + + reg_addr = FTS_REG_FLOW_WORK_CNT; + err = fts_i2c_read(fts_i2c_client, ®_addr, 1, ®_value, 1); + if (err < 0) { + FTS_ERROR("[ESD]: Read Reg 0x91 failed ret = %d!!", err); + fts_esdcheck_data.i2c_nack_cnt++; + } else { + if (reg_value == fts_esdcheck_data.flow_work_cnt_last) { + fts_esdcheck_data.flow_work_hold_cnt++; + } else { + fts_esdcheck_data.flow_work_hold_cnt = 0; + } + + fts_esdcheck_data.flow_work_cnt_last = reg_value; + } + + /* if read flow work cnt 5 times and the value are all the same, then need hardware_reset */ + if (fts_esdcheck_data.flow_work_hold_cnt >= 5) { + FTS_DEBUG("[ESD]: Flow Work Cnt(reg0x91) keep a value for 5 times, need execute TP reset!!"); + return 1; + } + + return 0; +} + +/***************************************************************************** +* Name: esdcheck_algorithm +* Brief: esd check algorithm +* Input: +* Output: +* Return: +*****************************************************************************/ +static int esdcheck_algorithm(void) +{ + int err = 0; + u8 reg_value = 0; + u8 reg_addr = 0; + bool hardware_reset = 0; + + /* 1. esdcheck is interrupt, then return */ + if (fts_esdcheck_data.intr == 1) { + FTS_INFO("[ESD]: In interrupt state, not check esd, return immediately!!"); + return 0; + } + + /* 2. check power state, if suspend, no need check esd */ + if (fts_esdcheck_data.suspend == 1) { + FTS_INFO("[ESD]: In suspend, not check esd, return immediately!!"); + /* because in suspend state, adb can be used, when upgrade FW, will active ESD check(active = 1) + * But in suspend, then will don't queue_delayed_work, when resume, don't check ESD again + */ + fts_esdcheck_data.active = 0; + return 0; + } + + /* 3. check fts_esdcheck_data.proc_debug state, if 1-proc busy, no need check esd*/ + if (fts_esdcheck_data.proc_debug == 1) { + FTS_INFO("[ESD]: In apk or adb command mode, not check esd, return immediately!!"); + return 0; + } + + /* 4. In factory mode, can't check esd */ + reg_addr = FTS_REG_WORKMODE; + err = fts_i2c_read(fts_i2c_client, ®_addr, 1, ®_value, 1); + if (err < 0) { + fts_esdcheck_data.i2c_nack_cnt++; + } else if ((reg_value & 0x70) == FTS_REG_WORKMODE_FACTORY_VALUE) { + FTS_INFO("[ESD]: In factory mode, not check esd, return immediately!!"); + return 0; + } + + /* 5. Get Chip ID */ + hardware_reset = get_chip_id(); + + /* 6. get Flow work cnt: 0x91 If no change for 5 times, then ESD and reset */ + if (!hardware_reset) { + hardware_reset = get_flow_cnt(); + } + + /* 7. If need hardware reset, then handle it here */ + if (hardware_reset == 1) { + fts_esdcheck_tp_reset(); + } + + FTS_INFO("[ESD]: NoACK=%d, Error Data=%d, Hardware Reset=%d\n", fts_esdcheck_data.i2c_nack_cnt, fts_esdcheck_data.i2c_dataerror_cnt, fts_esdcheck_data.hardware_reset_cnt); + return 0; +} + +/***************************************************************************** +* Name: fts_esdcheck_func +* Brief: fts_esdcheck_func +* Input: +* Output: +* Return: +*****************************************************************************/ +static void esdcheck_func(struct work_struct *work) +{ + FTS_FUNC_ENTER(); + + idc_esdcheck_lcderror(); + + esdcheck_algorithm(); + + if (fts_esdcheck_data.suspend == 0) { + queue_delayed_work(fts_esdcheck_workqueue, &fts_esdcheck_work, msecs_to_jiffies(ESDCHECK_WAIT_TIME)); + } + + FTS_FUNC_EXIT(); +} + +/***************************************************************************** +* Name: fts_esdcheck_set_intr +* Brief: interrupt flag (main used in interrupt tp report) +* Input: +* Output: +* Return: +*****************************************************************************/ +int fts_esdcheck_set_intr(bool intr) +{ + /* interrupt don't add debug message */ + fts_esdcheck_data.intr = intr; + return 0; +} + +/***************************************************************************** +* Name: fts_esdcheck_get_status(void) +* Brief: get current status +* Input: +* Output: +* Return: +*****************************************************************************/ +int fts_esdcheck_get_status(void) +{ + /* interrupt don't add debug message */ + return fts_esdcheck_data.active; +} + +/***************************************************************************** +* Name: fts_esdcheck_proc_busy +* Brief: When APK or ADB command access TP via driver, then need set proc_debug, +* then will not check ESD. +* Input: +* Output: +* Return: +*****************************************************************************/ +int fts_esdcheck_proc_busy(bool proc_debug) +{ + fts_esdcheck_data.proc_debug = proc_debug; + return 0; +} + +/***************************************************************************** +* Name: fts_esdcheck_switch +* Brief: FTS esd check function switch. +* Input: enable: 1 - Enable esd check +* 0 - Disable esd check +* Output: +* Return: +*****************************************************************************/ +int fts_esdcheck_switch(bool enable) +{ + FTS_FUNC_ENTER(); + if (enable == 1) { + if (fts_esdcheck_data.active == 0) { + FTS_INFO("[ESD]: ESD check start!!"); + fts_esdcheck_data.active = 1; + queue_delayed_work(fts_esdcheck_workqueue, &fts_esdcheck_work, msecs_to_jiffies(ESDCHECK_WAIT_TIME)); + } + } else { + if (fts_esdcheck_data.active == 1) { + FTS_INFO("[ESD]: ESD check stop!!"); + fts_esdcheck_data.active = 0; + cancel_delayed_work_sync(&fts_esdcheck_work); + } + } + + FTS_FUNC_EXIT(); + return 0; +} + +/***************************************************************************** +* Name: fts_esdcheck_suspend +* Brief: Run when tp enter into suspend +* Input: +* Output: +* Return: +*****************************************************************************/ +int fts_esdcheck_suspend(void) +{ + FTS_FUNC_ENTER(); + fts_esdcheck_switch(DISABLE); + fts_esdcheck_data.suspend = 1; + FTS_FUNC_EXIT(); + return 0; +} + +/***************************************************************************** +* Name: fts_esdcheck_resume +* Brief: Run when tp resume +* Input: +* Output: +* Return: +*****************************************************************************/ +int fts_esdcheck_resume(void) +{ + FTS_FUNC_ENTER(); + fts_esdcheck_switch(ENABLE); + fts_esdcheck_data.suspend = 0; + FTS_FUNC_EXIT(); + return 0; +} + + +/***************************************************************************** +* Name: fts_esdcheck_init +* Brief: Init and create a queue work to check esd +* Input: +* Output: +* Return: < 0: Fail to create esd check queue +*****************************************************************************/ +int fts_esdcheck_init(void) +{ + FTS_FUNC_ENTER(); + + INIT_DELAYED_WORK(&fts_esdcheck_work, esdcheck_func); + fts_esdcheck_workqueue = create_workqueue("fts_esdcheck_wq"); + if (fts_esdcheck_workqueue == NULL) { + FTS_INFO("[ESD]: Failed to create esd work queue!!"); + } + + memset((u8 *)&fts_esdcheck_data, 0, sizeof(struct fts_esdcheck_st)); + + fts_esdcheck_switch(ENABLE); + FTS_FUNC_EXIT(); + return 0; +} + +/***************************************************************************** +* Name: fts_esdcheck_exit +* Brief: When FTS TP driver is removed, then call this function to destory work queue +* Input: +* Output: +* Return: +*****************************************************************************/ +int fts_esdcheck_exit(void) +{ + FTS_FUNC_ENTER(); + + destroy_workqueue(fts_esdcheck_workqueue); + + FTS_FUNC_EXIT(); + return 0; +} +#endif /* FTS_ESDCHECK_EN */ + diff --git a/drivers/input/touchscreen/ft8716/focaltech_ex_fun.c b/drivers/input/touchscreen/ft8716/focaltech_ex_fun.c new file mode 100644 index 0000000000000..10093f7e9a23c --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_ex_fun.c @@ -0,0 +1,1182 @@ +/* + * + * FocalTech TouchScreen driver. + * + * Copyright (c) 2010-2016, Focaltech Ltd. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/***************************************************************************** +* +* File Name: Focaltech_ex_fun.c +* +* Author: Focaltech Driver Team +* +* Created: 2016-08-08 +* +* Abstract: +* +* Reference: +* +*****************************************************************************/ + +/***************************************************************************** +* 1.Included header files +*****************************************************************************/ +#include "focaltech_core.h" + +/***************************************************************************** +* Private constant and macro definitions using #define +*****************************************************************************/ +/*create apk debug channel*/ +#define PROC_UPGRADE 0 +#define PROC_READ_REGISTER 1 +#define PROC_WRITE_REGISTER 2 +#define PROC_AUTOCLB 4 +#define PROC_UPGRADE_INFO 5 +#define PROC_WRITE_DATA 6 +#define PROC_READ_DATA 7 +#define PROC_SET_TEST_FLAG 8 +#define PROC_SET_SLAVE_ADDR 10 +#define PROC_HW_RESET 11 +#define PROC_NAME "ftxxxx-debug" +#define WRITE_BUF_SIZE 512 +#define READ_BUF_SIZE 512 + +/***************************************************************************** +* Private enumerations, structures and unions using typedef +*****************************************************************************/ + +/***************************************************************************** +* Static variables +*****************************************************************************/ +static unsigned char proc_operate_mode = PROC_UPGRADE; +static struct proc_dir_entry *fts_proc_entry; +static struct +{ + int op; + int reg; + int value; + int result; +} g_rwreg_result; + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ + +/***************************************************************************** +* Static function prototypes +*****************************************************************************/ +#if FTS_ESDCHECK_EN +static void esd_process(u8 *writebuf, int buflen, bool flag) +{ + if (flag) { + if ((writebuf[1] == 0xFC) && (writebuf[2] == 0x55) && (buflen == 0x03)) { + /* Upgrade command */ + FTS_DEBUG("[ESD]: Upgrade command(%x %x %x)!!", writebuf[0], writebuf[1], writebuf[2]); + fts_esdcheck_switch(DISABLE); + } else if ((writebuf[1] == 0x00) && (writebuf[2] == 0x40) && (buflen == 0x03)) { + /* factory mode bit 4 5 6 */ + FTS_DEBUG("[ESD]: Entry factory mode(%x %x %x)!!", writebuf[0], writebuf[1], writebuf[2]); + fts_esdcheck_switch(DISABLE); + } else if ((writebuf[1] == 0x00) && (writebuf[2] == 0x00) && (buflen == 0x03)) { + /* normal mode bit 4 5 6 */ + FTS_DEBUG("[ESD]: Exit factory mode(%x %x %x)!!", writebuf[0], writebuf[1], writebuf[2]); + fts_esdcheck_switch(ENABLE); + } else { + fts_esdcheck_proc_busy(1); + } + } else { + if ((writebuf[1] == 0x07) && (buflen == 0x02)) { + FTS_DEBUG("[ESD]: Upgrade finish-trigger reset(07)(%x %x)!!", writebuf[0], writebuf[1]); + fts_esdcheck_switch(ENABLE); + } else { + fts_esdcheck_proc_busy(0); + } + } +} +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) +/*interface of write proc*/ +/************************************************************************ +* Name: fts_debug_write +* Brief:interface of write proc +* Input: file point, data buf, data len, no use +* Output: no +* Return: data len +***********************************************************************/ +static ssize_t fts_debug_write(struct file *filp, const char __user *buff, size_t count, loff_t *ppos) +{ + unsigned char writebuf[WRITE_BUF_SIZE]; + int buflen = count; + int writelen = 0; + int ret = 0; + char tmp[25]; + + if (copy_from_user(&writebuf, buff, buflen)) { + FTS_DEBUG("[APK]: copy from user error!!"); + return -EFAULT; + } +#if FTS_ESDCHECK_EN + esd_process(writebuf, buflen, 1); +#endif + proc_operate_mode = writebuf[0]; + switch (proc_operate_mode) { + case PROC_UPGRADE: + { + char upgrade_file_path[FILE_NAME_LENGTH]; + memset(upgrade_file_path, 0, sizeof(upgrade_file_path)); + sprintf(upgrade_file_path, "%s", writebuf + 1); + upgrade_file_path[buflen-1] = '\0'; + FTS_DEBUG("%s\n", upgrade_file_path); + fts_irq_disable(); +#if FTS_ESDCHECK_EN + fts_esdcheck_switch(DISABLE); +#endif + if (fts_updatefun_curr.upgrade_with_app_bin_file) + ret = fts_updatefun_curr.upgrade_with_app_bin_file(fts_i2c_client, upgrade_file_path); +#if FTS_ESDCHECK_EN + fts_esdcheck_switch(ENABLE); +#endif + fts_irq_enable(); + if (ret < 0) { + FTS_ERROR("[APK]: upgrade failed!!"); + } + } + break; + + case PROC_SET_TEST_FLAG: + FTS_DEBUG("[APK]: PROC_SET_TEST_FLAG = %x!!", writebuf[1]); +#if FTS_ESDCHECK_EN + if (writebuf[1] == 0) { + fts_esdcheck_switch(DISABLE); + } else { + fts_esdcheck_switch(ENABLE); + } +#endif + break; + case PROC_READ_REGISTER: + writelen = 1; + ret = fts_i2c_write(fts_i2c_client, writebuf + 1, writelen); + if (ret < 0) { + FTS_ERROR("[APK]: write iic error!!"); + } + break; + case PROC_WRITE_REGISTER: + writelen = 2; + ret = fts_i2c_write(fts_i2c_client, writebuf + 1, writelen); + if (ret < 0) { + FTS_ERROR("[APK]: write iic error!!"); + } + break; + case PROC_SET_SLAVE_ADDR: + ret = fts_i2c_client->addr; + FTS_DEBUG("Original i2c addr 0x%x ", ret<<1); + if (writebuf[1] != fts_i2c_client->addr) { + fts_i2c_client->addr = writebuf[1]; + FTS_DEBUG("Change i2c addr 0x%x to 0x%x", ret<<1, writebuf[1]<<1); + } + break; + case PROC_HW_RESET: + sprintf(tmp, "%s", writebuf + 1); + tmp[buflen - 1] = '\0'; + if (strncmp(tmp, "focal_driver", 12) == 0) { + FTS_DEBUG("Begin HW Reset"); + fts_reset_proc(1); + } + break; + case PROC_AUTOCLB: + FTS_DEBUG("[APK]: autoclb!!"); + fts_ctpm_auto_clb_sharp(fts_i2c_client); + break; + case PROC_READ_DATA: + case PROC_WRITE_DATA: + writelen = count - 1; + if (writelen > 0) { + ret = fts_i2c_write(fts_i2c_client, writebuf + 1, writelen); + if (ret < 0) { + FTS_ERROR("[APK]: write iic error!!"); + } + } + break; + default: + break; + } + +#if FTS_ESDCHECK_EN + esd_process(writebuf, buflen, 0); +#endif + + if (ret < 0) { + return ret; + } else { + return count; + } +} + +/* interface of read proc */ +/************************************************************************ +* Name: fts_debug_read +* Brief:interface of read proc +* Input: point to the data, no use, no use, read len, no use, no use +* Output: page point to data +* Return: read char number +***********************************************************************/ +static ssize_t fts_debug_read(struct file *filp, char __user *buff, size_t count, loff_t *ppos) +{ + int ret = 0; + int num_read_chars = 0; + int readlen = 0; + u8 regvalue = 0x00, regaddr = 0x00; + unsigned char buf[READ_BUF_SIZE]; + +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(1); +#endif + switch (proc_operate_mode) { + case PROC_UPGRADE: + + regaddr = FTS_REG_FW_VER; + ret = fts_i2c_read_reg(fts_i2c_client, regaddr, ®value); + if (ret < 0) + num_read_chars = sprintf(buf, "%s", "get fw version failed.\n"); + else + num_read_chars = sprintf(buf, "current fw version:0x%02x\n", regvalue); + break; + case PROC_READ_REGISTER: + readlen = 1; + ret = fts_i2c_read(fts_i2c_client, NULL, 0, buf, readlen); + if (ret < 0) { +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(0); +#endif + FTS_ERROR("[APK]: read iic error!!"); + return ret; + } + num_read_chars = 1; + break; + case PROC_READ_DATA: + readlen = count; + ret = fts_i2c_read(fts_i2c_client, NULL, 0, buf, readlen); + if (ret < 0) { +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(0); +#endif + FTS_ERROR("[APK]: read iic error!!"); + return ret; + } + + num_read_chars = readlen; + break; + case PROC_WRITE_DATA: + break; + default: + break; + } + +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(0); +#endif + + if (copy_to_user(buff, buf, num_read_chars)) { + FTS_ERROR("[APK]: copy to user error!!"); + return -EFAULT; + } + + return num_read_chars; +} +static const struct file_operations fts_proc_fops = { + .owner = THIS_MODULE, + .read = fts_debug_read, + .write = fts_debug_write, +}; +#else +/* interface of write proc */ +/************************************************************************ +* Name: fts_debug_write +* Brief:interface of write proc +* Input: file point, data buf, data len, no use +* Output: no +* Return: data len +***********************************************************************/ +static int fts_debug_write(struct file *filp, + const char __user *buff, unsigned long len, void *data) +{ + unsigned char writebuf[WRITE_BUF_SIZE]; + int buflen = len; + int writelen = 0; + int ret = 0; + char tmp[25]; + + if (copy_from_user(&writebuf, buff, buflen)) { + FTS_ERROR("[APK]: copy from user error!!"); + return -EFAULT; + } +#if FTS_ESDCHECK_EN + esd_process(writebuf, buflen, 1); +#endif + proc_operate_mode = writebuf[0]; + switch (proc_operate_mode) { + + case PROC_UPGRADE: + { + char upgrade_file_path[FILE_NAME_LENGTH]; + memset(upgrade_file_path, 0, sizeof(upgrade_file_path)); + sprintf(upgrade_file_path, "%s", writebuf + 1); + upgrade_file_path[buflen-1] = '\0'; + FTS_DEBUG("%s\n", upgrade_file_path); + fts_irq_disable(); +#if FTS_ESDCHECK_EN + fts_esdcheck_switch(DISABLE); +#endif + if (fts_updatefun_curr.upgrade_with_app_bin_file) + ret = fts_updatefun_curr.upgrade_with_app_bin_file(fts_i2c_client, upgrade_file_path); +#if FTS_ESDCHECK_EN + fts_esdcheck_switch(ENABLE); +#endif + fts_irq_enable(); + if (ret < 0) { + FTS_ERROR("[APK]: upgrade failed!!"); + } + } + break; + case PROC_SET_TEST_FLAG: + FTS_DEBUG("[APK]: PROC_SET_TEST_FLAG = %x!!", writebuf[1]); +#if FTS_ESDCHECK_EN + if (writebuf[1] == 0) { + fts_esdcheck_switch(DISABLE); + } else { + fts_esdcheck_switch(ENABLE); + } +#endif + break; + case PROC_READ_REGISTER: + writelen = 1; + ret = fts_i2c_write(fts_i2c_client, writebuf + 1, writelen); + if (ret < 0) { + FTS_ERROR("[APK]: write iic error!!n"); + } + break; + case PROC_WRITE_REGISTER: + writelen = 2; + ret = fts_i2c_write(fts_i2c_client, writebuf + 1, writelen); + if (ret < 0) { + FTS_ERROR("[APK]: write iic error!!"); + } + break; + case PROC_SET_SLAVE_ADDR: + + ret = fts_i2c_client->addr; + FTS_DEBUG("Original i2c addr 0x%x ", ret<<1); + if (writebuf[1] != fts_i2c_client->addr) { + fts_i2c_client->addr = writebuf[1]; + FTS_DEBUG("Change i2c addr 0x%x to 0x%x", ret<<1, writebuf[1]<<1); + + } + break; + + case PROC_HW_RESET: + + sprintf(tmp, "%s", writebuf + 1); + tmp[buflen - 1] = '\0'; + if (strncmp(tmp, "focal_driver", 12) == 0) { + FTS_DEBUG("Begin HW Reset"); + fts_reset_proc(1); + } + + break; + + case PROC_AUTOCLB: + FTS_DEBUG("[APK]: autoclb!!"); + fts_ctpm_auto_clb_sharp(fts_i2c_client); + break; + case PROC_READ_DATA: + case PROC_WRITE_DATA: + writelen = len - 1; + if (writelen > 0) { + ret = fts_i2c_write(fts_i2c_client, writebuf + 1, writelen); + if (ret < 0) { + FTS_ERROR("[APK]: write iic error!!"); + } + } + break; + default: + break; + } + +#if FTS_ESDCHECK_EN + esd_process(writebuf, buflen, 0); +#endif + + if (ret < 0) { + return ret; + } else { + return len; + } +} + +/* interface of read proc */ +/************************************************************************ +* Name: fts_debug_read +* Brief:interface of read proc +* Input: point to the data, no use, no use, read len, no use, no use +* Output: page point to data +* Return: read char number +***********************************************************************/ +static int fts_debug_read(char *page, char **start, + off_t off, int count, int *eof, void *data) +{ + int ret = 0; + unsigned char buf[READ_BUF_SIZE]; + int num_read_chars = 0; + int readlen = 0; + u8 regvalue = 0x00, regaddr = 0x00; + +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(1); +#endif + switch (proc_operate_mode) { + case PROC_UPGRADE: + + regaddr = FTS_REG_FW_VER; + ret = fts_i2c_read_reg(fts_i2c_client, regaddr, ®value); + if (ret < 0) + num_read_chars = sprintf(buf, "%s", "get fw version failed.\n"); + else + num_read_chars = sprintf(buf, "current fw version:0x%02x\n", regvalue); + break; + case PROC_READ_REGISTER: + readlen = 1; + ret = fts_i2c_read(fts_i2c_client, NULL, 0, buf, readlen); + if (ret < 0) { +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(0); +#endif + FTS_ERROR("[APK]: read iic error!!"); + return ret; + } + num_read_chars = 1; + break; + case PROC_READ_DATA: + readlen = count; + ret = fts_i2c_read(fts_i2c_client, NULL, 0, buf, readlen); + if (ret < 0) { +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(0); +#endif + FTS_ERROR("[APK]: read iic error!!"); + return ret; + } + + num_read_chars = readlen; + break; + case PROC_WRITE_DATA: + break; + default: + break; + } + +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(0); +#endif + + memcpy(page, buf, num_read_chars); + return num_read_chars; +} +#endif +/************************************************************************ +* Name: fts_create_apk_debug_channel +* Brief: create apk debug channel +* Input: i2c info +* Output: no +* Return: success =0 +***********************************************************************/ +int fts_create_apk_debug_channel(struct i2c_client *client) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) + fts_proc_entry = proc_create(PROC_NAME, 0777, NULL, &fts_proc_fops); +#else + fts_proc_entry = create_proc_entry(PROC_NAME, 0777, NULL); +#endif + if (NULL == fts_proc_entry) { + FTS_ERROR("Couldn't create proc entry!"); + return -ENOMEM; + } else { + FTS_INFO("Create proc entry success!"); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)) + fts_proc_entry->write_proc = fts_debug_write; + fts_proc_entry->read_proc = fts_debug_read; +#endif + } + return 0; +} +/************************************************************************ +* Name: fts_release_apk_debug_channel +* Brief: release apk debug channel +* Input: no +* Output: no +* Return: no +***********************************************************************/ +void fts_release_apk_debug_channel(void) +{ + + if (fts_proc_entry) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) + proc_remove(fts_proc_entry); +#else + remove_proc_entry(PROC_NAME, NULL); +#endif +} + +/************************************************************************ +* Name: fts_tpfwver_show +* Brief: show tp fw vwersion +* Input: device, device attribute, char buf +* Output: no +* Return: char number +***********************************************************************/ +static ssize_t fts_tpfwver_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t num_read_chars = 0; + u8 fwver = 0; + + mutex_lock(&fts_input_dev->mutex); + +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(1); +#endif + if (fts_i2c_read_reg(fts_i2c_client, FTS_REG_FW_VER, &fwver) < 0) { + num_read_chars = snprintf(buf, PAGE_SIZE, "I2c transfer error!\n"); + } +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(0); +#endif + if (fwver == 255) + num_read_chars = snprintf(buf, PAGE_SIZE, "get tp fw version fail!\n"); + else { + num_read_chars = snprintf(buf, PAGE_SIZE, "%02X\n", fwver); + } + + mutex_unlock(&fts_input_dev->mutex); + + return num_read_chars; +} +/************************************************************************ +* Name: fts_tpfwver_store +* Brief: no +* Input: device, device attribute, char buf, char count +* Output: no +* Return: EPERM +***********************************************************************/ +static ssize_t fts_tpfwver_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + /* place holder for future use */ + return -EPERM; +} + +static int fts_is_hex_char(const char ch) +{ + int result = 0; + if (ch >= '0' && ch <= '9') { + result = 1; + } else if (ch >= 'a' && ch <= 'f') { + result = 1; + } else if (ch >= 'A' && ch <= 'F') { + result = 1; + } else { + result = 0; + } + + return result; +} + +static int fts_hex_char_to_int(const char ch) +{ + int result = 0; + if (ch >= '0' && ch <= '9') { + result = (int)(ch - '0'); + } else if (ch >= 'a' && ch <= 'f') { + result = (int)(ch - 'a') + 10; + } else if (ch >= 'A' && ch <= 'F') { + result = (int)(ch - 'A') + 10; + } else { + result = -1; + } + + return result; +} + +static int fts_hex_to_str(char *hex, int iHexLen, char *ch, int *iChLen) +{ + int high = 0; + int low = 0; + int tmp = 0; + int i = 0; + int iCharLen = 0; + if (hex == NULL || ch == NULL) { + return -EPERM; + } + + FTS_DEBUG("iHexLen: %d in function:%s!!\n\n", iHexLen, __func__); + + if (iHexLen % 2 == 1) { + return -ENOENT; + } + + for (i = 0; i < iHexLen; i += 2) { + high = fts_hex_char_to_int(hex[i]); + if (high < 0) { + ch[iCharLen] = '\0'; + return -3; + } + + low = fts_hex_char_to_int(hex[i+1]); + if (low < 0) { + ch[iCharLen] = '\0'; + return -3; + } + tmp = (high << 4) + low; + ch[iCharLen++] = (char)tmp; + } + ch[iCharLen] = '\0'; + *iChLen = iCharLen; + FTS_DEBUG("iCharLen: %d, iChLen: %d in function:%s!!\n\n", iCharLen, *iChLen, __func__); + return 0; +} + +static void fts_str_to_bytes(char *bufStr, int iLen, char *uBytes, int *iBytesLen) +{ + int i = 0; + int iNumChLen = 0; + + *iBytesLen = 0; + + for (i = 0; i < iLen; i++) { + if (fts_is_hex_char(bufStr[i])) { + bufStr[iNumChLen++] = bufStr[i]; + } + } + + bufStr[iNumChLen] = '\0'; + + fts_hex_to_str(bufStr, iNumChLen, uBytes, iBytesLen); +} +/************************************************************************ +* Name: fts_tprwreg_show +* Brief: no +* Input: device, device attribute, char buf +* Output: no +* Return: EPERM +***********************************************************************/ +static ssize_t fts_tprwreg_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int count; + + mutex_lock(&fts_input_dev->mutex); + + if (!g_rwreg_result.op) { + if (g_rwreg_result.result == 0) { + count = sprintf(buf, "Read %02X: %02X\n", g_rwreg_result.reg, g_rwreg_result.value); + } else { + count = sprintf(buf, "Read %02X failed, ret: %d\n", g_rwreg_result.reg, g_rwreg_result.result); + } + } else { + if (g_rwreg_result.result == 0) { + count = sprintf(buf, "Write %02X, %02X success\n", g_rwreg_result.reg, g_rwreg_result.value); + } else { + count = sprintf(buf, "Write %02X failed, ret: %d\n", g_rwreg_result.reg, g_rwreg_result.result); + } + } + mutex_unlock(&fts_input_dev->mutex); + + return count; +} +/************************************************************************ +* Name: fts_tprwreg_store +* Brief: read/write register +* Input: device, device attribute, char buf, char count +* Output: print register value +* Return: char count +***********************************************************************/ +static ssize_t fts_tprwreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + ssize_t num_read_chars = 0; + int retval; + long unsigned int wmreg = 0; + u8 regaddr = 0xff, regvalue = 0xff; + u8 valbuf[5] = {0}; + + memset(valbuf, 0, sizeof(valbuf)); + mutex_lock(&fts_input_dev->mutex); + num_read_chars = count - 1; + if (num_read_chars != 2) { + if (num_read_chars != 4) { + FTS_ERROR("please input 2 or 4 character"); + goto error_return; + } + } + memcpy(valbuf, buf, num_read_chars); + retval = kstrtoul(valbuf, 16, &wmreg); + fts_str_to_bytes((char *)buf, num_read_chars, valbuf, &retval); + + if (1 == retval) { + regaddr = valbuf[0]; + retval = 0; + } else if (2 == retval) { + regaddr = valbuf[0]; + regvalue = valbuf[1]; + retval = 0; + } else + retval = -1; + + if (0 != retval) { + FTS_ERROR("%s() - ERROR: Could not convert the given input to a number. The given input was: \"%s\"", __FUNCTION__, buf); + goto error_return; + } +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(1); +#endif + if (2 == num_read_chars) { + g_rwreg_result.op = 0; + g_rwreg_result.reg = regaddr; + /*read register*/ + regaddr = wmreg; + g_rwreg_result.result = fts_i2c_read_reg(client, regaddr, ®value); + if (g_rwreg_result.result < 0) { + FTS_ERROR("Could not read the register(0x%02x)", regaddr); + } else { + FTS_INFO("the register(0x%02x) is 0x%02x", regaddr, regvalue); + g_rwreg_result.value = regvalue; + g_rwreg_result.result = 0; + } + } else { + regaddr = wmreg>>8; + regvalue = wmreg; + + g_rwreg_result.op = 1; + g_rwreg_result.reg = regaddr; + g_rwreg_result.value = regvalue; + g_rwreg_result.result = fts_i2c_write_reg(client, regaddr, regvalue); + if (g_rwreg_result.result < 0) { + FTS_ERROR("Could not write the register(0x%02x)", regaddr); + + } else { + FTS_INFO("Write 0x%02x into register(0x%02x) successful", regvalue, regaddr); + g_rwreg_result.result = 0; + } + } +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(0); +#endif +error_return: + mutex_unlock(&fts_input_dev->mutex); + + return count; +} +/************************************************************************ +* Name: fts_fwupdate_show +* Brief: no +* Input: device, device attribute, char buf +* Output: no +* Return: EPERM +***********************************************************************/ +static ssize_t fts_fwupdate_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + /* place holder for future use */ + return -EPERM; +} + +/************************************************************************ +* Name: fts_fwupdate_store +* Brief: upgrade from *.i +* Input: device, device attribute, char buf, char count +* Output: no +* Return: char count +***********************************************************************/ +static ssize_t fts_fwupdate_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + mutex_lock(&fts_input_dev->mutex); + fts_irq_disable(); +#if FTS_ESDCHECK_EN + fts_esdcheck_switch(DISABLE); +#endif + if (fts_updatefun_curr.upgrade_with_app_i_file) + fts_updatefun_curr.upgrade_with_app_i_file(client); +#if FTS_ESDCHECK_EN + fts_esdcheck_switch(ENABLE); +#endif + fts_irq_enable(); + mutex_unlock(&fts_input_dev->mutex); + + return count; +} +/************************************************************************ +* Name: fts_fwupgradeapp_show +* Brief: no +* Input: device, device attribute, char buf +* Output: no +* Return: EPERM +***********************************************************************/ +static ssize_t fts_fwupgradeapp_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + /* place holder for future use */ + return -EPERM; +} + +/************************************************************************ +* Name: fts_fwupgradeapp_store +* Brief: upgrade from app.bin +* Input: device, device attribute, char buf, char count +* Output: no +* Return: char count +***********************************************************************/ +static ssize_t fts_fwupgradeapp_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + char fwname[FILE_NAME_LENGTH]; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + memset(fwname, 0, sizeof(fwname)); + sprintf(fwname, "%s", buf); + fwname[count-1] = '\0'; + + mutex_lock(&fts_input_dev->mutex); + fts_irq_disable(); +#if FTS_ESDCHECK_EN + fts_esdcheck_switch(DISABLE); +#endif + if (fts_updatefun_curr.upgrade_with_app_bin_file) + fts_updatefun_curr.upgrade_with_app_bin_file(client, fwname); +#if FTS_ESDCHECK_EN + fts_esdcheck_switch(ENABLE); +#endif + fts_irq_enable(); + mutex_unlock(&fts_input_dev->mutex); + + return count; +} +/************************************************************************ +* Name: fts_driverversion_show +* Brief: no +* Input: device, device attribute, char buf +* Output: no +* Return: EPERM +***********************************************************************/ +static ssize_t fts_driverversion_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int count; + + mutex_lock(&fts_input_dev->mutex); + + count = sprintf(buf, FTS_DRIVER_VERSION "\n"); + + mutex_unlock(&fts_input_dev->mutex); + + return count; +} +/************************************************************************ +* Name: fts_driverversion_store +* Brief: no +* Input: device, device attribute, char buf, char count +* Output: no +* Return: EPERM +***********************************************************************/ +static ssize_t fts_driverversion_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + /* place holder for future use */ + return -EPERM; +} + +#if FTS_ESDCHECK_EN +/************************************************************************ +* Name: fts_esdcheck_store +* Brief: no +* Input: device, device attribute, char buf, char count +* Output: no +* Return: EPERM +***********************************************************************/ +static ssize_t fts_esdcheck_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + mutex_lock(&fts_input_dev->mutex); + if (FTS_SYSFS_ECHO_ON(buf)) { + FTS_DEBUG("enable esdcheck"); + fts_esdcheck_switch(ENABLE); + } else if (FTS_SYSFS_ECHO_OFF(buf)) { + FTS_DEBUG("disable esdcheck"); + fts_esdcheck_switch(DISABLE); + } + mutex_unlock(&fts_input_dev->mutex); + + return -EPERM; +} + +/************************************************************************ +* Name: fts_esdcheck_show +* Brief: no +* Input: device, device attribute, char buf +* Output: no +* Return: EPERM +***********************************************************************/ +static ssize_t fts_esdcheck_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int count; + + mutex_lock(&fts_input_dev->mutex); + + count = sprintf(buf, "Esd check: %s\n", fts_esdcheck_get_status() ? "On" : "Off"); + + mutex_unlock(&fts_input_dev->mutex); + + return count; +} +#endif +/************************************************************************ +* Name: fts_module_config_show +* Brief: no +* Input: device, device attribute, char buf +* Output: no +* Return: EPERM +***********************************************************************/ +static ssize_t fts_module_config_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int count = 0; + + mutex_lock(&fts_input_dev->mutex); + + count += sprintf(buf, "FTS_CHIP_TYPE: \t\t\t%04X\n", FTS_CHIP_TYPE); + count += sprintf(buf+count, "FTS_DEBUG_EN: \t\t\t%s\n", FTS_DEBUG_EN ? "ON" : "OFF"); +#if defined(FTS_MT_PROTOCOL_B_EN) + count += sprintf(buf+count, "TS_MT_PROTOCOL_B_EN: \t\t%s\n", FTS_MT_PROTOCOL_B_EN ? "ON" : "OFF"); +#endif + count += sprintf(buf+count, "FTS_GESTURE_EN: \t\t%s\n", FTS_GESTURE_EN ? "ON" : "OFF"); + count += sprintf(buf+count, "FTS_ESDCHECK_EN: \t\t%s\n", FTS_ESDCHECK_EN ? "ON" : "OFF"); +#if defined(FTS_PSENSOR_EN) + count += sprintf(buf+count, "FTS_PSENSOR_EN: \t\t%s\n", FTS_PSENSOR_EN ? "ON" : "OFF"); +#endif + count += sprintf(buf+count, "FTS_GLOVE_EN: \t\t\t%s\n", FTS_GLOVE_EN ? "ON" : "OFF"); + count += sprintf(buf+count, "FTS_COVER_EN: \t\t%s\n", FTS_COVER_EN ? "ON" : "OFF"); + count += sprintf(buf+count, "FTS_CHARGER_EN: \t\t\t%s\n", FTS_CHARGER_EN ? "ON" : "OFF"); + + count += sprintf(buf+count, "FTS_REPORT_PRESSURE_EN: \t\t%s\n", FTS_REPORT_PRESSURE_EN ? "ON" : "OFF"); + count += sprintf(buf+count, "FTS_FORCE_TOUCH_EN: \t\t%s\n", FTS_FORCE_TOUCH_EN ? "ON" : "OFF"); + + count += sprintf(buf+count, "FTS_TEST_EN: \t\t\t%s\n", FTS_TEST_EN ? "ON" : "OFF"); + count += sprintf(buf+count, "FTS_APK_NODE_EN: \t\t%s\n", FTS_APK_NODE_EN ? "ON" : "OFF"); + count += sprintf(buf+count, "FTS_POWER_SOURCE_CUST_EN: \t%s\n", FTS_POWER_SOURCE_CUST_EN ? "ON" : "OFF"); + count += sprintf(buf+count, "FTS_AUTO_UPGRADE_EN: \t\t%s\n", FTS_AUTO_UPGRADE_EN ? "ON" : "OFF"); + + mutex_unlock(&fts_input_dev->mutex); + + return count; +} +/************************************************************************ +* Name: fts_module_config_store +* Brief: no +* Input: device, device attribute, char buf, char count +* Output: no +* Return: EPERM +***********************************************************************/ +static ssize_t fts_module_config_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + /* place holder for future use */ + return -EPERM; +} + +/************************************************************************ +* Name: fts_show_log_show +* Brief: no +* Input: device, device attribute, char buf +* Output: no +* Return: EPERM +***********************************************************************/ +static ssize_t fts_show_log_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int count; + + mutex_lock(&fts_input_dev->mutex); + + count = sprintf(buf, "Log: %s\n", g_show_log ? "On" : "Off"); + + mutex_unlock(&fts_input_dev->mutex); + + return count; +} +/************************************************************************ +* Name: fts_show_log_store +* Brief: no +* Input: device, device attribute, char buf, char count +* Output: no +* Return: EPERM +***********************************************************************/ +static ssize_t fts_show_log_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + /* place holder for future use */ + + mutex_lock(&fts_input_dev->mutex); + if (FTS_SYSFS_ECHO_ON(buf)) { + FTS_DEBUG("enable show log info/error"); + g_show_log = 1; + } else if (FTS_SYSFS_ECHO_OFF(buf)) { + FTS_DEBUG("disable show log info/error"); + g_show_log = 0; + } + mutex_unlock(&fts_input_dev->mutex); + return count; +} +/************************************************************************ +* Name: fts_dumpreg_store +* Brief: no +* Input: device, device attribute, char buf, char count +* Output: no +* Return: EPERM +***********************************************************************/ +static ssize_t fts_dumpreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + /* place holder for future use */ + return -EPERM; +} + +/************************************************************************ +* Name: fts_dumpreg_show +* Brief: no +* Input: device, device attribute, char buf +* Output: no +* Return: EPERM +***********************************************************************/ +static ssize_t fts_dumpreg_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + char tmp[256]; + int count = 0; + u8 regvalue = 0; + struct i2c_client *client; + + mutex_lock(&fts_input_dev->mutex); +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(1); +#endif + client = container_of(dev, struct i2c_client, dev); + fts_i2c_read_reg(client, FTS_REG_POWER_MODE, ®value); + count += sprintf(tmp + count, "Power Mode:0x%02x\n", regvalue); + + fts_i2c_read_reg(client, FTS_REG_FW_VER, ®value); + count += sprintf(tmp + count, "FW Ver:0x%02x\n", regvalue); + + fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, ®value); + count += sprintf(tmp + count, "Vendor ID:0x%02x\n", regvalue); + + fts_i2c_read_reg(client, FTS_REG_LCD_BUSY_NUM, ®value); + count += sprintf(tmp + count, "LCD Busy Number:0x%02x\n", regvalue); + + fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, ®value); + count += sprintf(tmp + count, "Gesture Mode:0x%02x\n", regvalue); + + fts_i2c_read_reg(client, FTS_REG_CHARGER_MODE_EN, ®value); + count += sprintf(tmp + count, "charge stat:0x%02x\n", regvalue); + + fts_i2c_read_reg(client, FTS_REG_INT_CNT, ®value); + count += sprintf(tmp + count, "INT count:0x%02x\n", regvalue); + + fts_i2c_read_reg(client, FTS_REG_FLOW_WORK_CNT, ®value); + count += sprintf(tmp + count, "ESD count:0x%02x\n", regvalue); +#if FTS_ESDCHECK_EN + fts_esdcheck_proc_busy(0); +#endif + memcpy(buf, tmp, count); + mutex_unlock(&fts_input_dev->mutex); + return count; +} + +/****************************************/ +/* sysfs */ +/* get the fw version +* example:cat fw_version +*/ +static DEVICE_ATTR(fts_fw_version, S_IRUGO|S_IWUSR, fts_tpfwver_show, fts_tpfwver_store); + +/* upgrade from *.i +* example: echo 1 > fw_update +*/ +static DEVICE_ATTR(fts_fw_update, S_IRUGO|S_IWUSR, fts_fwupdate_show, fts_fwupdate_store); +/* read and write register +* read example: echo 88 > rw_reg ---read register 0x88 +* write example:echo 8807 > rw_reg ---write 0x07 into register 0x88 +* +* note:the number of input must be 2 or 4.if it not enough,please fill in the 0. +*/ +static DEVICE_ATTR(fts_rw_reg, S_IRUGO|S_IWUSR, fts_tprwreg_show, fts_tprwreg_store); +/* upgrade from app.bin +* example:echo "*_app.bin" > upgrade_app +*/ +static DEVICE_ATTR(fts_upgrade_app, S_IRUGO|S_IWUSR, fts_fwupgradeapp_show, fts_fwupgradeapp_store); +static DEVICE_ATTR(fts_driver_version, S_IRUGO|S_IWUSR, fts_driverversion_show, fts_driverversion_store); +static DEVICE_ATTR(fts_dump_reg, S_IRUGO|S_IWUSR, fts_dumpreg_show, fts_dumpreg_store); +static DEVICE_ATTR(fts_show_log, S_IRUGO|S_IWUSR, fts_show_log_show, fts_show_log_store); +static DEVICE_ATTR(fts_module_config, S_IRUGO|S_IWUSR, fts_module_config_show, fts_module_config_store); +#if FTS_ESDCHECK_EN +static DEVICE_ATTR(fts_esd_check, S_IRUGO|S_IWUSR, fts_esdcheck_show, fts_esdcheck_store); +#endif + +/* add your attr in here*/ +static struct attribute *fts_attributes[] = { + &dev_attr_fts_fw_version.attr, + &dev_attr_fts_fw_update.attr, + &dev_attr_fts_rw_reg.attr, + &dev_attr_fts_dump_reg.attr, + &dev_attr_fts_upgrade_app.attr, + &dev_attr_fts_driver_version.attr, + &dev_attr_fts_show_log.attr, + &dev_attr_fts_module_config.attr, +#if FTS_ESDCHECK_EN + &dev_attr_fts_esd_check.attr, +#endif + NULL +}; + +static struct attribute_group fts_attribute_group = { + .attrs = fts_attributes +}; + +/************************************************************************ +* Name: fts_create_sysfs +* Brief: create sysfs for debug +* Input: i2c info +* Output: no +* Return: success =0 +***********************************************************************/ +int fts_create_sysfs(struct i2c_client *client) +{ + int err; + err = sysfs_create_group(&client->dev.kobj, &fts_attribute_group); + if (0 != err) { + FTS_ERROR("[EX]: sysfs_create_group() failed!!"); + sysfs_remove_group(&client->dev.kobj, &fts_attribute_group); + return -EIO; + } else { + FTS_INFO("[EX]: sysfs_create_group() succeeded!!"); + } + return err; +} +/************************************************************************ +* Name: fts_remove_sysfs +* Brief: remove sys +* Input: i2c info +* Output: no +* Return: no +***********************************************************************/ +int fts_remove_sysfs(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &fts_attribute_group); + return 0; +} diff --git a/drivers/input/touchscreen/ft8716/focaltech_ex_mode.c b/drivers/input/touchscreen/ft8716/focaltech_ex_mode.c new file mode 100644 index 0000000000000..699f529e5fec4 --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_ex_mode.c @@ -0,0 +1,352 @@ +/* + * + * FocalTech ftxxxx TouchScreen driver. + * + * Copyright (c) 2010-2016, Focaltech Ltd. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/***************************************************************************** +* +* File Name: focaltech_ex_mode.c +* +* Author: Liu WeiGuang +* +* Created: 2016-08-31 +* +* Abstract: +* +* Reference: +* +*****************************************************************************/ + +/***************************************************************************** +* 1.Included header files +*****************************************************************************/ +#include "focaltech_core.h" + +/***************************************************************************** +* 2.Private constant and macro definitions using #define +*****************************************************************************/ + +/***************************************************************************** +* 3.Private enumerations, structures and unions using typedef +*****************************************************************************/ +struct fts_mode_flag { + int fts_glove_mode_flag; + int fts_cover_mode_flag; + int fts_charger_mode_flag; +}; + +struct fts_mode_flag g_fts_mode_flag; + +/***************************************************************************** +* 4.Static variables +*****************************************************************************/ + +/***************************************************************************** +* 5.Global variable or extern global variabls/functions +*****************************************************************************/ +int fts_enter_glove_mode(struct i2c_client *client, int mode); +int fts_glove_init(struct i2c_client *client); +int fts_glove_exit(struct i2c_client *client); + +int fts_enter_cover_mode(struct i2c_client *client, int mode); +int fts_cover_init(struct i2c_client *client); +int fts_cover_exit(struct i2c_client *client); + +int fts_enter_charger_mode(struct i2c_client *client, int mode); +int fts_charger_init(struct i2c_client *client); +int fts_charger_exit(struct i2c_client *client); + +/***************************************************************************** +* 6.Static function prototypes +*******************************************************************************/ + +#if FTS_GLOVE_EN +static ssize_t fts_touch_glove_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "Glove: %s\n", g_fts_mode_flag.fts_glove_mode_flag ? "On" : "Off"); +} + +static ssize_t fts_touch_glove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + int ret; + + if (FTS_SYSFS_ECHO_ON(buf)) { + if (!g_fts_mode_flag.fts_glove_mode_flag) { + FTS_INFO("[Mode]enter glove mode"); + ret = fts_enter_glove_mode(fts_i2c_client, true); + if (ret >= 0) { + g_fts_mode_flag.fts_glove_mode_flag = true; + } + } + } else if (FTS_SYSFS_ECHO_OFF(buf)) { + if (g_fts_mode_flag.fts_glove_mode_flag) { + FTS_INFO("[Mode]exit glove mode"); + ret = fts_enter_glove_mode(fts_i2c_client, false); + if (ret >= 0) { + g_fts_mode_flag.fts_glove_mode_flag = false; + } + } + } + FTS_INFO("[Mode]glove mode status: %d", g_fts_mode_flag.fts_glove_mode_flag); + return count; +} + +/************************************************************************ +* Name: fts_enter_glove_mode +* Brief: change glove mode +* Input: glove mode +* Output: no +* Return: success >=0, otherwise failed +***********************************************************************/ +int fts_enter_glove_mode(struct i2c_client *client, int mode) +{ + int ret = 0; + static u8 buf_addr[2] = { 0 }; + static u8 buf_value[2] = { 0 }; + buf_addr[0] = FTS_REG_GLOVE_MODE_EN; + + if (mode) + buf_value[0] = 0x01; + else + buf_value[0] = 0x00; + + ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]); + if (ret < 0) { + FTS_ERROR("[Mode]fts_enter_glove_mode write value fail"); + } + + return ret ; + +} + +/* read and write glove mode +* read example: cat fts_touch_glove_mode---read glove mode +* write example:echo 01 > fts_touch_glove_mode ---write glove mode to 01 +* +*/ +static DEVICE_ATTR (fts_glove_mode, S_IRUGO|S_IWUSR, fts_touch_glove_show, fts_touch_glove_store); + +#endif + +#if FTS_COVER_EN +static ssize_t fts_touch_cover_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "Cover: %s\n", g_fts_mode_flag.fts_cover_mode_flag ? "On" : "Off"); +} + +static ssize_t fts_touch_cover_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + int ret; + + if (FTS_SYSFS_ECHO_ON(buf)) { + if (!g_fts_mode_flag.fts_cover_mode_flag) { + FTS_INFO("[Mode]enter cover mode"); + ret = fts_enter_cover_mode(fts_i2c_client, true); + if (ret >= 0) { + g_fts_mode_flag.fts_cover_mode_flag = true; + } + } + } else if (FTS_SYSFS_ECHO_OFF(buf)) { + if (g_fts_mode_flag.fts_cover_mode_flag) { + FTS_INFO("[Mode]exit cover mode"); + ret = fts_enter_cover_mode(fts_i2c_client, false); + if (ret >= 0) { + g_fts_mode_flag.fts_cover_mode_flag = false; + } + } + } + FTS_INFO("[Mode]cover mode status: %d", g_fts_mode_flag.fts_cover_mode_flag); + return count; +} + +/************************************************************************ +* Name: fts_enter_cover_mode +* Brief: change cover mode +* Input: cover mode +* Output: no +* Return: success >=0, otherwise failed +***********************************************************************/ +int fts_enter_cover_mode(struct i2c_client *client, int mode) +{ + int ret = 0; + static u8 buf_addr[2] = { 0 }; + static u8 buf_value[2] = { 0 }; + buf_addr[0] = FTS_REG_COVER_MODE_EN; + + if (mode) + buf_value[0] = 0x01; + else + buf_value[0] = 0x00; + + ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]); + if (mode) { + fts_i2c_write_reg(client, 0xc4, 0x00); + fts_i2c_write_reg(client, 0xc5, 0xff); + fts_i2c_write_reg(client, 0xc6, 0x00); + fts_i2c_write_reg(client, 0xc7, 0x78); + } + if (ret < 0) { + FTS_ERROR("[Mode] fts_enter_cover_mode write value fail \n"); + } + + return ret ; + +} + +/* read and write cover mode +* read example: cat fts_touch_cover_mode---read cover mode +* write example:echo 01 > fts_touch_cover_mode ---write cover mode to 01 +* +*/ +static DEVICE_ATTR (fts_cover_mode, S_IRUGO|S_IWUSR, fts_touch_cover_show, fts_touch_cover_store); + +#endif + +#if FTS_CHARGER_EN +static ssize_t fts_touch_charger_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "Charger: %s\n", g_fts_mode_flag.fts_charger_mode_flag ? "On" : "Off"); +} + +static ssize_t fts_touch_charger_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + int ret; + + if (FTS_SYSFS_ECHO_ON(buf)) { + if (!g_fts_mode_flag.fts_charger_mode_flag) { + FTS_INFO("[Mode]enter charger mode"); + ret = fts_enter_charger_mode(fts_i2c_client, true); + if (ret >= 0) { + g_fts_mode_flag.fts_charger_mode_flag = true; + } + } + } else if (FTS_SYSFS_ECHO_OFF(buf)) { + if (g_fts_mode_flag.fts_charger_mode_flag) { + FTS_INFO("[Mode]exit charger mode"); + ret = fts_enter_charger_mode(fts_i2c_client, false); + if (ret >= 0) { + g_fts_mode_flag.fts_charger_mode_flag = false; + } + } + } + FTS_INFO("[Mode]charger mode status: %d", g_fts_mode_flag.fts_charger_mode_flag); + return count; +} + +/************************************************************************ +* Name: fts_enter_charger_mode +* Brief: change charger mode +* Input: charger mode +* Output: no +* Return: success >=0, otherwise failed +***********************************************************************/ +int fts_enter_charger_mode(struct i2c_client *client, int mode) +{ + int ret = 0; + static u8 buf_addr[2] = { 0 }; + static u8 buf_value[2] = { 0 }; + buf_addr[0] = FTS_REG_CHARGER_MODE_EN; + + if (mode) + buf_value[0] = 0x01; + else + buf_value[0] = 0x00; + + ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]); + if (ret < 0) { + FTS_DEBUG("[Mode]fts_enter_charger_mode write value fail"); + } + + return ret ; + +} + +/* read and write charger mode +* read example: cat fts_touch_charger_mode---read charger mode +* write example:echo 01 > fts_touch_charger_mode ---write charger mode to 01 +* +*/ +static DEVICE_ATTR (fts_charger_mode, S_IRUGO|S_IWUSR, fts_touch_charger_show, fts_touch_charger_store); + +#endif + +static struct attribute *fts_touch_mode_attrs[] = { +#if FTS_GLOVE_EN + &dev_attr_fts_glove_mode.attr, +#endif + +#if FTS_COVER_EN + &dev_attr_fts_cover_mode.attr, +#endif + +#if FTS_CHARGER_EN + &dev_attr_fts_charger_mode.attr, +#endif + + NULL, +}; + +static struct attribute_group fts_touch_mode_group = { + .attrs = fts_touch_mode_attrs, +}; + +int fts_ex_mode_init(struct i2c_client *client) +{ + int err = 0; + + g_fts_mode_flag.fts_glove_mode_flag = false; + g_fts_mode_flag.fts_cover_mode_flag = false; + g_fts_mode_flag.fts_charger_mode_flag = false; + + err = sysfs_create_group(&client->dev.kobj, &fts_touch_mode_group); + if (0 != err) { + FTS_ERROR("[Mode]create sysfs failed."); + sysfs_remove_group(&client->dev.kobj, &fts_touch_mode_group); + return -EIO; + } else { + FTS_DEBUG("[Mode]create sysfs succeeded"); + } + + return err; + +} + +int fts_ex_mode_exit(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &fts_touch_mode_group); + return 0; +} + +int fts_ex_mode_recovery(struct i2c_client *client) +{ + int ret = 0; +#if FTS_GLOVE_EN + if (g_fts_mode_flag.fts_glove_mode_flag) + ret = fts_enter_glove_mode(client, true); +#endif + +#if FTS_COVER_EN + if (g_fts_mode_flag.fts_cover_mode_flag) + ret = fts_enter_cover_mode(client, true); +#endif + +#if FTS_CHARGER_EN + if (g_fts_mode_flag.fts_charger_mode_flag) + ret = fts_enter_charger_mode(client, true); +#endif + + return ret; +} + diff --git a/drivers/input/touchscreen/ft8716/focaltech_flash.c b/drivers/input/touchscreen/ft8716/focaltech_flash.c new file mode 100644 index 0000000000000..112a19e6e70ae --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_flash.c @@ -0,0 +1,759 @@ +/* + * + * FocalTech fts TouchScreen driver. + * + * Copyright (c) 2010-2016, Focaltech Ltd. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/***************************************************************************** +* +* File Name: focaltech_flash.c +* +* Author: fupeipei +* +* Created: 2016-08-08 +* +* Abstract: +* +* Reference: +* +*****************************************************************************/ + +/***************************************************************************** +* 1.Included header files +*****************************************************************************/ +#include "focaltech_core.h" +#include "focaltech_flash.h" + +/***************************************************************************** +* Static variables +*****************************************************************************/ +struct ft_chip_t chip_types; + + + +unsigned char CTPM_FW[] = { +#include FTS_UPGRADE_FW_APP +}; + +unsigned char aucFW_PRAM_BOOT[] = { +#ifdef FTS_UPGRADE_PRAMBOOT +#include FTS_UPGRADE_PRAMBOOT +#endif +}; + +unsigned char CTPM_LCD_CFG[] = { +#ifdef FTS_UPGRADE_LCD_CFG +#include FTS_UPGRADE_LCD_CFG +#endif +}; + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ +struct fts_upgrade_fun fts_updatefun_curr; + +struct workqueue_struct *touch_wq; +struct work_struct fw_update_work; + +/***************************************************************************** +* Static function prototypes +*****************************************************************************/ + +/************************************************************************ +* Name: fts_ctpm_upgrade_delay +* Brief: 0 +* Input: 0 +* Output: 0 +* Return: 0 +***********************************************************************/ +void fts_ctpm_upgrade_delay(u32 i) +{ + do { + i--; + } while (i > 0); +} + +/************************************************************************ +* Name: fts_ctpm_i2c_hid2std +* Brief: HID to I2C +* Input: i2c info +* Output: no +* Return: fail =0 +***********************************************************************/ +int fts_ctpm_i2c_hid2std(struct i2c_client *client) +{ +#if (FTS_CHIP_IDC) + return 0; +#else + u8 buf[5] = {0}; + int bRet = 0; + + buf[0] = 0xeb; + buf[1] = 0xaa; + buf[2] = 0x09; + bRet = fts_i2c_write(client, buf, 3); + msleep(10); + buf[0] = buf[1] = buf[2] = 0; + fts_i2c_read(client, buf, 0, buf, 3); + + if ((0xeb == buf[0]) && (0xaa == buf[1]) && (0x08 == buf[2])) { + FTS_DEBUG("hidi2c change to stdi2c successful!!"); + bRet = 1; + } else { + FTS_ERROR("hidi2c change to stdi2c error!!"); + bRet = 0; + } + + return bRet; +#endif +} + +/************************************************************************ +* Name: fts_get_chip_types +* Brief: get correct chip information +* Input: +* Output: +* Return: +***********************************************************************/ +void fts_get_chip_types(void) +{ + struct ft_chip_t ctype[] = FTS_CHIP_TYPE_MAPPING; + int ic_type = 0; + + if (sizeof(ctype) != sizeof(struct ft_chip_t)) /* only one array */ + ic_type = IC_SERIALS - 1; + + chip_types = ctype[ic_type]; + + FTS_INFO("CHIP TYPE ID = 0x%02x%02x", chip_types.chip_idh, chip_types.chip_idl); +} + +/************************************************************************ +* Name: fts_ctpm_get_upgrade_array +* Brief: decide which ic +* Input: no +* Output: get ic info in fts_updateinfo_curr +* Return: no +***********************************************************************/ +void fts_ctpm_get_upgrade_array(void) +{ + + FTS_FUNC_ENTER(); + + fts_get_chip_types(); + + fts_ctpm_i2c_hid2std(fts_i2c_client); + + /* Get functin pointer */ + memcpy(&fts_updatefun_curr, &fts_updatefun, sizeof(struct fts_upgrade_fun)); + + FTS_FUNC_EXIT(); +} + +/************************************************************************ +* Name: fts_ctpm_rom_or_pram_reset +* Brief: RST CMD(07), reset to romboot(maybe->bootloader) +* Input: +* Output: +* Return: +***********************************************************************/ +void fts_ctpm_rom_or_pram_reset(struct i2c_client *client) +{ + u8 rst_cmd = FTS_REG_RESET_FW; + + FTS_INFO("[UPGRADE]******Reset to romboot/bootloader******"); + fts_i2c_write(client, &rst_cmd, 1); + /* The delay can't be changed */ + msleep(300); +} + +/************************************************************************ +* Name: fts_ctpm_auto_clb_sharp +* Brief: auto calibration +* Input: i2c info +* Output: no +* Return: 0 +***********************************************************************/ +int fts_ctpm_auto_clb_sharp(struct i2c_client *client) +{ +#if FTS_AUTO_CLB_EN + unsigned char uc_temp = 0x00; + unsigned char i = 0; + + /*start auto CLB */ + msleep(200); + + fts_i2c_write_reg(client, 0, FTS_REG_WORKMODE_FACTORY_VALUE); + /*make sure already enter factory mode */ + msleep(100); + /*write command to start calibration */ + fts_i2c_write_reg(client, 2, 0x4); + msleep(300); + if ((chip_types.chip_idh == 0x11) || (chip_types.chip_idh == 0x12) || (chip_types.chip_idh == 0x13) || (chip_types.chip_idh == 0x14)) { + for (i = 0; i < 100; i++) { + fts_i2c_read_reg(client, 0x02, &uc_temp); + if (0x02 == uc_temp || + 0xFF == uc_temp) { + break; + } + msleep(20); + } + } else { + for (i = 0; i < 100; i++) { + fts_i2c_read_reg(client, 0, &uc_temp); + if (0x0 == ((uc_temp&0x70)>>4)) { + break; + } + msleep(20); + } + } + fts_i2c_write_reg(client, 0, 0x40); + msleep(200); + fts_i2c_write_reg(client, 2, 0x5); + msleep(300); + fts_i2c_write_reg(client, 0, FTS_REG_WORKMODE_WORK_VALUE); + msleep(300); +#endif + + return 0; +} + +/************************************************************************ +* Name: fts_GetFirmwareSize +* Brief: get file size +* Input: file name +* Output: no +* Return: file size +***********************************************************************/ +int fts_GetFirmwareSize(char *firmware_name) +{ + struct file *pfile = NULL; + struct inode *inode; + unsigned long magic; + off_t fsize = 0; + char filepath[FILE_NAME_LENGTH]; + + memset(filepath, 0, sizeof(filepath)); + sprintf(filepath, "%s%s", FTXXXX_INI_FILEPATH_CONFIG, firmware_name); + if (NULL == pfile) { + pfile = filp_open(filepath, O_RDONLY, 0); + } + if (IS_ERR(pfile)) { + FTS_ERROR("error occured while opening file %s", filepath); + return -EIO; + } + inode = pfile->f_dentry->d_inode; + magic = inode->i_sb->s_magic; + fsize = inode->i_size; + filp_close(pfile, NULL); + return fsize; +} + +/************************************************************************ +* Name: fts_ReadFirmware +* Brief: read firmware buf for .bin file. +* Input: file name, data buf +* Output: data buf +* Return: 0 +***********************************************************************/ +int fts_ReadFirmware(char *firmware_name, unsigned char *firmware_buf) +{ + struct file *pfile = NULL; + struct inode *inode; + unsigned long magic; + off_t fsize; + char filepath[FILE_NAME_LENGTH]; + loff_t pos; + mm_segment_t old_fs; + + memset(filepath, 0, sizeof(filepath)); + sprintf(filepath, "%s%s", FTXXXX_INI_FILEPATH_CONFIG, firmware_name); + if (NULL == pfile) { + pfile = filp_open(filepath, O_RDONLY, 0); + } + if (IS_ERR(pfile)) { + FTS_ERROR("[UPGRADE] Error occured while opening file %s.\n", filepath); + return -EIO; + } + inode = pfile->f_dentry->d_inode; + magic = inode->i_sb->s_magic; + fsize = inode->i_size; + old_fs = get_fs(); + set_fs(KERNEL_DS); + pos = 0; + vfs_read(pfile, firmware_buf, fsize, &pos); + filp_close(pfile, NULL); + set_fs(old_fs); + return 0; +} + +/************************************************************************ +* Name: fts_getsize +* Brief: 0 +* Input: 0 +* Output: 0 +* Return: 0 +***********************************************************************/ +u32 fts_getsize(u8 fw_type) +{ + int fw_len = 0; + + if (fw_type == FW_SIZE) + fw_len = sizeof(CTPM_FW); +#if FTS_CHIP_IDC + else if (fw_type == PRAMBOOT_SIZE) + fw_len = sizeof(aucFW_PRAM_BOOT); +#endif +#if (FTS_CHIP_TYPE == _FT8006) + else if (fw_type == LCD_CFG_SIZE) + fw_len = sizeof(CTPM_LCD_CFG); +#endif + + return fw_len; +} + +/************************************************************************ +* Name: fts_ctpm_get_pram_or_rom_id +* Brief: 0 +* Input: 0 +* Output: 0 +* Return: 0 +***********************************************************************/ +enum FW_STATUS fts_ctpm_get_pram_or_rom_id(struct i2c_client *client) +{ + u8 buf[4]; + u8 reg_val[2] = {0}; + enum FW_STATUS inRomBoot = FTS_RUN_IN_ERROR; + + fts_ctpm_i2c_hid2std(client); + + /*Enter upgrade mode*/ + /*send 0x55 in time windows*/ + buf[0] = FTS_UPGRADE_55; + buf[1] = FTS_UPGRADE_AA; + fts_i2c_write(client, buf, 2); + + msleep(20); + + buf[0] = 0x90; + buf[1] = buf[2] = buf[3] = 0x00; + fts_i2c_read(client, buf, 4, reg_val, 2); + + FTS_DEBUG("[UPGRADE] ROM/PRAM/Bootloader id:0x%02x%02x", reg_val[0], reg_val[1]); + if ((reg_val[0] == 0x00) || (reg_val[0] == 0xFF)) { + inRomBoot = FTS_RUN_IN_ERROR; + } else if (reg_val[0] == chip_types.pramboot_idh && reg_val[1] == chip_types.pramboot_idl) { + inRomBoot = FTS_RUN_IN_PRAM; + } else if (reg_val[0] == chip_types.rom_idh && reg_val[1] == chip_types.rom_idl) { + inRomBoot = FTS_RUN_IN_ROM; + } else if (reg_val[0] == chip_types.bootloader_idh && reg_val[1] == chip_types.bootloader_idl) { + inRomBoot = FTS_RUN_IN_BOOTLOADER; + } + + return inRomBoot; +} + +/************************************************************************ +* Name: fts_ctpm_get_app_ver +* Brief: get app file version +* Input: +* Output: +* Return: fw version +***********************************************************************/ +int fts_ctpm_get_app_ver(void) +{ + int i_ret = 0; + + if (fts_updatefun_curr.get_app_i_file_ver) + i_ret = fts_updatefun_curr.get_app_i_file_ver(); + + if (i_ret < 0) + i_ret = 0; + + return i_ret; +} + +/************************************************************************ +* Name: fts_ctpm_fw_upgrade +* Brief: fw upgrade entry funciotn +* Input: +* Output: +* Return: 0 - upgrade successfully +* <0 - upgrade failed +***********************************************************************/ +int fts_ctpm_fw_upgrade(struct i2c_client *client) +{ + int i_ret = 0; + + if (fts_updatefun_curr.upgrade_with_app_i_file) + i_ret = fts_updatefun_curr.upgrade_with_app_i_file(client); + + return i_ret; +} + +/************************************************************************ +* Name: fts_ctpm_fw_upgrade +* Brief: fw upgrade entry funciotn +* Input: +* Output: +* Return: 0 - upgrade successfully +* <0 - upgrade failed +***********************************************************************/ +int fts_ctpm_lcd_cfg_upgrade(struct i2c_client *client) +{ + int i_ret = 0; + + if (fts_updatefun_curr.upgrade_with_lcd_cfg_i_file) + i_ret = fts_updatefun_curr.upgrade_with_lcd_cfg_i_file(client); + + return i_ret; +} + +#if (!(FTS_UPGRADE_STRESS_TEST)) +/************************************************************************ +* Name: fts_ctpm_check_fw_status +* Brief: Check App is valid or not +* Input: +* Output: +* Return: -EIO - I2C communication error +* FTS_RUN_IN_APP - APP valid +* 0 - APP invalid +***********************************************************************/ +static int fts_ctpm_check_fw_status(struct i2c_client *client) +{ + u8 chip_id1 = 0; + u8 chip_id2 = 0; + int fw_status = FTS_RUN_IN_ERROR; + int i = 0; + int ret = 0; + int i2c_noack_retry = 0; + + for (i = 0; i < 5; i++) { + ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID, &chip_id1); + if (ret < 0) { + i2c_noack_retry++; + continue; + } + ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID2, &chip_id2); + if (ret < 0) { + i2c_noack_retry++; + continue; + } + + if ((chip_id1 == chip_types.chip_idh) +#if FTS_CHIP_IDC + && (chip_id2 == chip_types.chip_idl) +#endif + ) { + fw_status = FTS_RUN_IN_APP; + break; + } + } + + FTS_DEBUG("[UPGRADE]: chip_id = %02x%02x, chip_types.chip_idh = %02x%02x", + chip_id1, chip_id2, chip_types.chip_idh, chip_types.chip_idl); + + /* I2C No ACK 5 times, then return -EIO */ + if (i2c_noack_retry >= 5) + return -EIO; + + /* I2C communication ok, but not get correct ID, need check pram/rom/bootloader */ + if (i >= 5) + fw_status = fts_ctpm_get_pram_or_rom_id(client); + + return fw_status; +} + +/************************************************************************ +* Name: fts_ctpm_check_vendorid_fw +* Brief: Check vendor id is valid or not +* Input: +* Output: +* Return: 1 - vendor id valid +* 0 - vendor id invalid +***********************************************************************/ +static int fts_ctpm_check_vendorid_fw(struct i2c_client *client) +{ +#if FTS_GET_VENDOR_ID + u8 vendor_id; + fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id); + + FTS_DEBUG("[UPGRADE] tp_vendor_id=%x, FTS_VENDOR_1_ID=%x, FTS_VENDOR_2_ID=%x", vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID); + if ((vendor_id == FTS_VENDOR_1_ID) || (vendor_id == FTS_VENDOR_2_ID)) + return 1; + else + return 0; +#else + return 1; +#endif +} + +/************************************************************************ +* Name: fts_ctpm_check_fw_ver +* Brief: Check vendor id is valid or not +* Input: +* Output: +* Return: 1 - vendor id valid +* 0 - vendor id invalid +***********************************************************************/ + extern u8 fw_ver; + +#if FTS_AUTO_UPGRADE_EN + +extern char TP_vendor; +static char tp_info_summary[80] = ""; +#endif + static int fts_ctpm_check_fw_ver(struct i2c_client *client) +{ + + u8 uc_tp_fm_ver; + u8 uc_host_fm_ver = 0; + + + fts_i2c_read_reg(client, FTS_REG_FW_VER, &uc_tp_fm_ver); + uc_host_fm_ver = fts_ctpm_get_app_ver(); + + FTS_DEBUG("[UPGRADE]: uc_tp_fm_ver = 0x%x, uc_host_fm_ver = 0x%x!!", uc_tp_fm_ver, uc_host_fm_ver); + + printk("fw_ver= %d\n", uc_tp_fm_ver); + + + if (uc_tp_fm_ver < uc_host_fm_ver) + return 1; + else + return 0; +} + +/************************************************************************ +* Name: fts_ctpm_check_need_upgrade +* Brief: +* Input: +* Output: +* Return: 1 - Need upgrade +* 0 - No upgrade +***********************************************************************/ +static int fts_ctpm_check_need_upgrade(struct i2c_client *client) +{ + int fw_status = 0; + int bUpgradeFlag = false; + + FTS_FUNC_ENTER(); + + /* 1. veriry FW APP is valid or not */ + fw_status = fts_ctpm_check_fw_status(client); + FTS_DEBUG("[UPGRADE]: fw_status = %d!!", fw_status); + if (fw_status < 0) { + /* I2C no ACK, return immediately */ + FTS_ERROR("[UPGRADE]******I2C NO ACK,exit upgrade******"); + return -EIO; + } else if (fw_status == FTS_RUN_IN_ERROR) { + FTS_ERROR("[UPGRADE]******IC Type Fail******"); + } else if (fw_status == FTS_RUN_IN_APP) { + FTS_INFO("[UPGRADE]**********FW APP valid**********"); + + /* 2. check vendor id is valid or not */ + if (fts_ctpm_check_vendorid_fw(client) == 0) { + FTS_DEBUG("[UPGRADE]******Vendor ID in FW is invalid******"); + return false; + } + + if (fts_ctpm_check_fw_ver(client) == 1) { + FTS_DEBUG("[UPGRADE]**********need upgrade fw**********"); + bUpgradeFlag = true; + } else { + FTS_DEBUG("[UPGRADE]**********Don't need upgrade fw**********"); + bUpgradeFlag = false; + } + } else { + /* if app is invalid, reset to run ROM */ + FTS_INFO("[UPGRADE]**********FW APP invalid**********"); + fts_ctpm_rom_or_pram_reset(client); + + bUpgradeFlag = true; + } + + fts_ctpm_check_fw_ver(client); + + FTS_FUNC_EXIT(); + + return bUpgradeFlag; +} + +/************************************************************************ +* Name: fts_ctpm_auto_upgrade +* Brief: auto upgrade +* Input: +* Output: +* Return: 0 - no upgrade +***********************************************************************/ +int fts_ctpm_auto_upgrade(struct i2c_client *client) +{ + u8 uc_tp_fm_ver; + int i_ret = 0; + int bUpgradeFlag = false; + u8 uc_upgrade_times = 0; + + FTS_DEBUG("[UPGRADE]********************check upgrade need or not********************"); + bUpgradeFlag = fts_ctpm_check_need_upgrade(client); + FTS_DEBUG("[UPGRADE]**********bUpgradeFlag = 0x%x**********", bUpgradeFlag); + + if (bUpgradeFlag <= 0) { + FTS_DEBUG("[UPGRADE]**********No Upgrade, exit**********"); + return 0; + } else { + /* FW Upgrade */ + do { + uc_upgrade_times++; + FTS_DEBUG("[UPGRADE]********************star upgrade(%d)********************", uc_upgrade_times); + + i_ret = fts_ctpm_fw_upgrade(client); + if (i_ret == 0) { + /* upgrade success */ + fts_i2c_read_reg(client, FTS_REG_FW_VER, &uc_tp_fm_ver); + FTS_DEBUG("[UPGRADE]********************Success upgrade to new fw version 0x%x********************", uc_tp_fm_ver); + + fts_ctpm_auto_clb_sharp(client); + break; + } else { + /* upgrade fail, reset to run ROM BOOT.. + * if app in flash is ok, TP will work success + */ + FTS_ERROR("[UPGRADE]********************upgrade fail, reset now********************"); + fts_ctpm_rom_or_pram_reset(client); + } + } while (uc_upgrade_times < 2); /* if upgrade fail, upgrade again. then return */ + } + + return i_ret; +} +#endif + +#if FTS_AUTO_UPGRADE_EN + +#if FTS_LOCK_DOWN_INFO +extern char ftp_lockdown_info[128]; +#endif +static void fts_ctpm_update_work_func(struct work_struct *work) +{ + int i_ret = 0; + char tp_temp_info[80]; + +#if FTS_LOCK_DOWN_INFO + unsigned char auc_i2c_write_buf[10]; + u8 r_buf[10] = {0}; + char err = -1; +#endif + + FTS_DEBUG("[UPGRADE]******************************FTS enter upgrade******************************"); + fts_irq_disable(); + + /* esd check */ +#if FTS_ESDCHECK_EN + fts_esdcheck_switch(DISABLE); +#endif + + i_ret = fts_ctpm_auto_upgrade(fts_i2c_client); + if (i_ret < 0) + FTS_ERROR("[UPGRADE]**********TP FW upgrade failed**********"); + +#if FTS_AUTO_UPGRADE_FOR_LCD_CFG_EN + msleep(2000); + + /* lcd_cfg upgrade */ + i_ret = fts_ctpm_lcd_cfg_upgrade(fts_i2c_client); + if (i_ret < 0) + FTS_ERROR("[UPGRADE]**********LCD cfg upgrade failed*********"); +#endif + fts_i2c_read_reg(fts_i2c_client, FTS_REG_FW_VER, &fw_ver); + + printk("fw_ver: %d", fw_ver); + + if (TP_vendor == 1) { + strcpy(tp_info_summary, "[Vendor]Sharp, [IC]FT8716, [FW]Ver"); + } else if (TP_vendor == 2) { + strcpy(tp_info_summary, "[Vendor]Eggb, [IC]FT8716, [FW]Ver"); + } else{ + strcpy(tp_info_summary, "[Vendor]Unknown, [IC]FT8716, [FW]Ver"); + } + sprintf(tp_temp_info, "%d", fw_ver); + strcat(tp_info_summary, tp_temp_info); + strcat(tp_info_summary, "\0"); + +#ifdef FTS_LOCK_DOWN_INFO + + if (strncmp("3833", ftp_lockdown_info, 4)) { + err = fts_i2c_write_reg(fts_i2c_client, 0x90, 0x20); + if (err < 0) + printk("[FTS] i2c write 0x90 err\n"); + + msleep(5); + auc_i2c_write_buf[0] = 0x99; + err = fts_i2c_read(fts_i2c_client, auc_i2c_write_buf, 1, r_buf, 8); + if (err < 0) + printk("[FTS] i2c read 0x99 err\n"); + + sprintf(ftp_lockdown_info, "%02x%02x%02x%02x%02x%02x%02x%02x", \ + r_buf[0], r_buf[1], r_buf[2], r_buf[3], r_buf[4], r_buf[5], r_buf[6], r_buf[7]); + + printk(" ft8716 get lockdown info after upgrade, tp_lockdown_info=%s\n", ftp_lockdown_info); + } else{ + printk("FT8716 lockdown info is OK\n"); + } +#endif + +#if FTS_ESDCHECK_EN + fts_esdcheck_switch(ENABLE); +#endif + fts_irq_enable(); + + FTS_DEBUG("[UPGRADE]******************************FTS exit upgrade******************************"); +} + +/***************************************************************************** +* Name: fts_ctpm_upgrade_init +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +void fts_ctpm_upgrade_init(void) +{ + FTS_FUNC_ENTER(); + + touch_wq = create_singlethread_workqueue("touch_wq"); + if (touch_wq) { + INIT_WORK(&fw_update_work, fts_ctpm_update_work_func); + queue_work(touch_wq, &fw_update_work); + } else { + FTS_ERROR("[UPGRADE]create_singlethread_workqueue failed\n"); + } + + FTS_FUNC_EXIT(); +} + +/***************************************************************************** +* Name: fts_ctpm_upgrade_exit +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +void fts_ctpm_upgrade_exit(void) +{ + FTS_FUNC_ENTER(); + destroy_workqueue(touch_wq); + FTS_FUNC_EXIT(); +} + +#endif /* #if FTS_AUTO_UPGRADE_EN */ diff --git a/drivers/input/touchscreen/ft8716/focaltech_flash.h b/drivers/input/touchscreen/ft8716/focaltech_flash.h new file mode 100644 index 0000000000000..90d82fcc9de31 --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_flash.h @@ -0,0 +1,154 @@ +/************************************************************************ +* Copyright (C) 2012-2016, Focaltech Systems (R)£¬All Rights Reserved. +* +* File Name: focaltech_flash.h +* +* Author: fupeipei +* +* Created: 2016-08-07 +* +* Abstract: +* +************************************************************************/ +#ifndef __LINUX_FOCALTECH_FLASH_H__ +#define __LINUX_FOCALTECH_FLASH_H__ + +/***************************************************************************** +* 1.Included header files +*****************************************************************************/ +#include "focaltech_flash/focaltech_upgrade_common.h" + +/***************************************************************************** +* Private constant and macro definitions using #define +*****************************************************************************/ +#define FTS_MAX_TRIES 5 +#define FTS_RETRY_DLY 20 +#define FTS_MAX_WR_BUF 10 +#define FTS_MAX_RD_BUF 2 +#define FTS_FW_PKT_META_LEN 6 +#define FTS_FW_PKT_DLY_MS 20 +#define FTS_FW_LAST_PKT 0x6ffa +#define FTS_EARSE_DLY_MS 100 +#define FTS_55_AA_DLY_NS 5000 +#define FTS_CAL_START 0x04 +#define FTS_CAL_FIN 0x00 +#define FTS_CAL_STORE 0x05 +#define FTS_CAL_RETRY 100 +#define FTS_REG_CAL 0x00 +#define FTS_CAL_MASK 0x70 +#define FTS_BLOADER_SIZE_OFF 12 +#define FTS_BLOADER_NEW_SIZE 30 +#define FTS_DATA_LEN_OFF_OLD_FW 8 +#define FTS_DATA_LEN_OFF_NEW_FW 14 +#define FTS_FINISHING_PKT_LEN_OLD_FW 6 +#define FTS_FINISHING_PKT_LEN_NEW_FW 12 +#define FTS_MAGIC_BLOADER_Z7 0x7bfa +#define FTS_MAGIC_BLOADER_LZ4 0x6ffa +#define FTS_MAGIC_BLOADER_GZF_30 0x7ff4 +#define FTS_MAGIC_BLOADER_GZF 0x7bf4 +#define FTS_REG_ECC 0xCC +#define FTS_RST_CMD_REG2 0xBC +#define FTS_READ_ID_REG 0x90 +#define FTS_ERASE_APP_REG 0x61 +#define FTS_ERASE_PARAMS_CMD 0x63 +#define FTS_FW_WRITE_CMD 0xBF +#define FTS_REG_RESET_FW 0x07 +#define FTS_RST_CMD_REG1 0xFC +#define LEN_FLASH_ECC_MAX 0xFFFE + +#define BL_VERSION_LZ4 0 +#define BL_VERSION_Z7 1 +#define BL_VERSION_GZF 2 + +#define FTS_PACKET_LENGTH 128 +#define FTS_SETTING_BUF_LEN 128 + +#define FTS_UPGRADE_LOOP 30 +#define FTS_MAX_POINTS_2 2 +#define FTS_MAX_POINTS_5 5 +#define FTS_MAX_POINTS_10 10 +#define AUTO_CLB_NEED 1 +#define AUTO_CLB_NONEED 0 +#define FTS_UPGRADE_AA 0xAA +#define FTS_UPGRADE_55 0x55 +#define FTXXXX_INI_FILEPATH_CONFIG "/sdcard/" + +enum FW_STATUS { + FTS_RUN_IN_ERROR, + FTS_RUN_IN_APP, + FTS_RUN_IN_ROM, + FTS_RUN_IN_PRAM, + FTS_RUN_IN_BOOTLOADER +}; + +enum FILE_SIZE_TYPE { + FW_SIZE, + PRAMBOOT_SIZE, + LCD_CFG_SIZE +}; + +/* pramboot for 8716 */ +#define FTS_PRAMBOOT_8716 "include/pramboot/FT8716_Pramboot_V0.5_20160723.i" +#define FTS_UPGRADE_PRAMBOOT FTS_PRAMBOOT_8716 + + +#define FTS_PRAMBOOT_E716 "include/pramboot/FT8716_Pramboot_V0.5_20160723.i" +#define FTS_UPGRADE_PRAMBOOT FTS_PRAMBOOT_8716 + + + + +/***************************************************************************** +* Private enumerations, structures and unions using typedef +*****************************************************************************/ +/* IC info */ + +struct fts_upgrade_fun { + int (*get_app_bin_file_ver)(char *); + int (*get_app_i_file_ver)(void); + int (*upgrade_with_app_i_file)(struct i2c_client *); + int (*upgrade_with_app_bin_file)(struct i2c_client *, char *); + int (*upgrade_with_lcd_cfg_i_file)(struct i2c_client *); + int (*upgrade_with_lcd_cfg_bin_file)(struct i2c_client *, char *); +}; +extern struct fts_upgrade_fun fts_updatefun; + +/***************************************************************************** +* Static variables +*****************************************************************************/ + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ +extern unsigned char CTPM_FW[]; +extern unsigned char aucFW_PRAM_BOOT[]; +extern unsigned char CTPM_LCD_CFG[]; + +extern struct fts_upgrade_fun fts_updatefun_curr; +extern struct ft_chip_t chip_types; + +#if FTS_AUTO_UPGRADE_EN +extern struct workqueue_struct *touch_wq; +extern struct work_struct fw_update_work; +#endif + +void fts_ctpm_upgrade_init(void); +void fts_ctpm_upgrade_exit(void); +void fts_ctpm_upgrade_delay(u32 i); +void fts_ctpm_get_upgrade_array(void); +int fts_ctpm_auto_upgrade(struct i2c_client *client); +int fts_fw_upgrade(struct device *dev, bool force); +int fts_ctpm_auto_clb_sharp(struct i2c_client *client); + +/***************************************************************************** +* Static function prototypes +*****************************************************************************/ +u32 fts_getsize(u8 fw_type); +int fts_GetFirmwareSize(char *firmware_name); +int fts_ctpm_i2c_hid2std(struct i2c_client *client); +int fts_ReadFirmware(char *firmware_name, unsigned char *firmware_buf); +void fts_ctpm_rom_or_pram_reset(struct i2c_client *client); +enum FW_STATUS fts_ctpm_get_pram_or_rom_id(struct i2c_client *client); +#endif + + diff --git a/drivers/input/touchscreen/ft8716/focaltech_flash/Makefile b/drivers/input/touchscreen/ft8716/focaltech_flash/Makefile new file mode 100644 index 0000000000000..af1e9ce00953f --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_flash/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the focaltech touchscreen drivers. +# + +# Each configuration option enables a list of files. + + +obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_idc.o +obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft8716.o +obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_test.o diff --git a/drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_common.h b/drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_common.h new file mode 100644 index 0000000000000..544c1095d43f4 --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_common.h @@ -0,0 +1,57 @@ +/************************************************************************ +* Copyright (C) 2012-2016, Focaltech Systems (R)£¬All Rights Reserved. +* +* File Name: focaltech_upgrade_common.h +* +* Author: fupeipei +* +* Created: 2016-08-16 +* +* Abstract: +* +************************************************************************/ +#ifndef __LINUX_FOCALTECH_UPGRADE_COMMON_H__ +#define __LINUX_FOCALTECH_UPGRADE_COMMON_H__ + +/***************************************************************************** +* 1.Included header files +*****************************************************************************/ +#include "../focaltech_flash.h" + +/***************************************************************************** +* Private constant and macro definitions using #define +*****************************************************************************/ + +/***************************************************************************** +* Private enumerations, structures and unions using typedef +*****************************************************************************/ + +/***************************************************************************** +* Static variables +*****************************************************************************/ + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ + +/***************************************************************************** +* Static function prototypes +*****************************************************************************/ +int fts_ctpm_erase_flash(struct i2c_client *client); +int fts_ctpm_pramboot_ecc(struct i2c_client *client); +bool fts_ctpm_check_run_state(struct i2c_client *client, int state); +void fts_ctpm_start_pramboot(struct i2c_client *client); +int fts_ctpm_start_fw_upgrade(struct i2c_client *client); +bool fts_ctpm_check_in_pramboot(struct i2c_client *client); +int fts_ctpm_upgrade_idc_init(struct i2c_client *client, u32 dw_lenth); +int fts_ctpm_write_app_for_idc(struct i2c_client *client, u32 length, u8 *readbuf); +int fts_ctpm_upgrade_ecc(struct i2c_client *client, u32 startaddr, u32 length); +int fts_ctpm_write_pramboot_for_idc(struct i2c_client *client, u32 length, u8 *readbuf); +int fts_writeflash(struct i2c_client *client, u32 writeaddr, u32 length, u8 *readbuf, u32 cnt); +bool fts_check_app_bin_valid_idc(u8 *pbt_buf); + +int fts_ctpm_get_app_ver(void); +int fts_ctpm_fw_upgrade(struct i2c_client *client); +int fts_ctpm_lcd_cfg_upgrade(struct i2c_client *client); + +#endif diff --git a/drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_ft8716.c b/drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_ft8716.c new file mode 100644 index 0000000000000..2bf0511e3efc2 --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_ft8716.c @@ -0,0 +1,541 @@ +/* + * + * FocalTech fts TouchScreen driver. + * + * Copyright (c) 2010-2016, Focaltech Ltd. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/***************************************************************************** +* +* File Name: focaltech_upgrade_ft8716.c +* +* Author: fupeipei +* +* Created: 2016-08-15 +* +* Abstract: +* +* Reference: +* +*****************************************************************************/ + +/***************************************************************************** +* 1.Included header files +*****************************************************************************/ +#include "../focaltech_core.h" + +#if ((FTS_CHIP_TYPE == _FT8716) || (FTS_CHIP_TYPE == _FTE716)) +#include "../focaltech_flash.h" +#include "focaltech_upgrade_common.h" + +/***************************************************************************** +* Static variables +*****************************************************************************/ +#define APP_FILE_MAX_SIZE (64 * 1024) +#define APP_FILE_MIN_SIZE (8) +#define APP_FILE_VER_MAPPING (0x10E) +#define APP_FILE_VENDORID_MAPPING (0x10C) +#define APP_FILE_CHIPID_MAPPING (0x11E) +#define CONFIG_START_ADDR (0x0000) +#define CONFIG_VENDOR_ID_OFFSET (0x04) +#define CONFIG_PROJECT_ID_OFFSET (0x20) +#define CONFIG_VENDOR_ID_ADDR (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET) +#define CONFIG_PROJECT_ID_ADDR (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET) + + +extern char TP_vendor ; + + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ +static int fts_ctpm_get_app_i_file_ver(void); +static int fts_ctpm_get_app_bin_file_ver(char *firmware_name); +static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client); +static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client, char *firmware_name); + +struct fts_upgrade_fun fts_updatefun = { + .get_app_bin_file_ver = fts_ctpm_get_app_bin_file_ver, + .get_app_i_file_ver = fts_ctpm_get_app_i_file_ver, + .upgrade_with_app_i_file = fts_ctpm_fw_upgrade_with_app_i_file, + .upgrade_with_app_bin_file = fts_ctpm_fw_upgrade_with_app_bin_file, + .upgrade_with_lcd_cfg_i_file = NULL, + .upgrade_with_lcd_cfg_bin_file = NULL, +}; + +/***************************************************************************** +* Static function prototypes +*****************************************************************************/ + +/************************************************************************ +* Name: fts_ctpm_get_app_bin_file_ver +* Brief: get .i file version +* Input: no +* Output: no +* Return: fw version +***********************************************************************/ +static int fts_ctpm_get_app_bin_file_ver(char *firmware_name) +{ + u8 *pbt_buf = NULL; + int fwsize = fts_GetFirmwareSize(firmware_name); + int fw_ver = 0; + + FTS_FUNC_ENTER(); + + if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) { + FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize); + return -EIO; + } + + pbt_buf = (unsigned char *)kmalloc(fwsize + 1, GFP_KERNEL); + if (fts_ReadFirmware(firmware_name, pbt_buf)) { + FTS_ERROR("[UPGRADE]: request_firmware failed!!"); + kfree(pbt_buf); + return -EIO; + } + + fw_ver = pbt_buf[APP_FILE_VER_MAPPING]; + + kfree(pbt_buf); + FTS_FUNC_EXIT(); + + return fw_ver; +} + +/************************************************************************ +* Name: fts_ctpm_get_app_i_file_ver +* Brief: get .i file version +* Input: no +* Output: no +* Return: fw version +***********************************************************************/ +static int fts_ctpm_get_app_i_file_ver(void) +{ + int fwsize = fts_getsize(FW_SIZE); + + if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) { + FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize); + return -EIO; + } + + return CTPM_FW[APP_FILE_VER_MAPPING]; +} + +/************************************************************************ +* Name: fts_ctpm_get_vendor_id_flash +* Brief: +* Input: +* Output: +* Return: +***********************************************************************/ +static int fts_ctpm_get_vendor_id_flash(struct i2c_client *client) +{ +#if FTS_GET_VENDOR_ID + int i_ret = 0; + u8 vendorid[4] = {0}; + u8 auc_i2c_write_buf[10]; + u8 i = 0; + + for (i = 0; i < FTS_UPGRADE_LOOP; i++) { + auc_i2c_write_buf[0] = 0x03; + auc_i2c_write_buf[1] = 0x00; + + auc_i2c_write_buf[2] = (u8)((CONFIG_VENDOR_ID_ADDR-1)>>8); + auc_i2c_write_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR-1); + i_ret = fts_i2c_read(client, auc_i2c_write_buf, 4, vendorid, 2); + if (i_ret < 0) { + FTS_DEBUG("[UPGRADE]: read flash : i_ret = %d!!", i_ret); + continue; + } else if ((vendorid[1] == FTS_VENDOR_1_ID) || (vendorid[1] == FTS_VENDOR_2_ID)) + break; + } + + FTS_DEBUG("[UPGRADE]: vendor id from flash rom: 0x%x!!", vendorid[1]); + if (i >= FTS_UPGRADE_LOOP) { + FTS_ERROR("[UPGRADE]: read vendor id from flash more than 30 times!!"); + return -EIO; + } + + return 0; +#else + return 0; +#endif +} + +/************************************************************************ +* Name: fts_ctpm_write_pram +* Brief: fw upgrade +* Input: i2c info, file buf, file len +* Output: no +* Return: fail <0 +***********************************************************************/ +static int fts_ctpm_write_pram(struct i2c_client *client, u8 *pbt_buf, u32 dw_lenth) +{ + int i_ret; + bool inrom = false; + + FTS_FUNC_ENTER(); + + /*check the length of the pramboot*/ + if (dw_lenth > APP_FILE_MAX_SIZE || dw_lenth < APP_FILE_MIN_SIZE) { + FTS_ERROR("[UPGRADE] pramboot length(%d) fail", dw_lenth); + return -EIO; + } + + /*send comond to FW, reset and start write pramboot*/ + i_ret = fts_ctpm_start_fw_upgrade(client); + if (i_ret < 0) { + FTS_ERROR("[UPGRADE]: send upgrade cmd to FW error!!"); + return i_ret; + } + + /*check run in rom or not! if run in rom, will write pramboot*/ + inrom = fts_ctpm_check_run_state(client, FTS_RUN_IN_ROM); + if (!inrom) { + FTS_ERROR("[UPGRADE]: not run in rom, write pramboot fail!!"); + return -EIO; + } + + /*write pramboot to pram*/ + i_ret = fts_ctpm_write_pramboot_for_idc(client, dw_lenth, aucFW_PRAM_BOOT); + if (i_ret < 0) { + return i_ret; + FTS_ERROR("[UPGRADE]: write pramboot fail!!"); + } + + /*read out checksum*/ + i_ret = fts_ctpm_pramboot_ecc(client); + if (i_ret < 0) { + return i_ret; + FTS_ERROR("[UPGRADE]: write pramboot ecc error!!"); + } + + /*start pram*/ + fts_ctpm_start_pramboot(client); + + FTS_FUNC_EXIT(); + + return 0; + + +} + /********************************************************* + * Name: ft8716_fw_LockDownInfo_get_from_boot + * Brief: Lockdowninfo + * Input: + * Output: + * Return: + + *********************************************************/ + +unsigned char ft8716_fw_LockDownInfo_get_from_boot(struct i2c_client *client, char *pProjectCode) +{ + unsigned char auc_i2c_write_buf[10]; + u8 r_buf[10] = {0}; + unsigned char i = 0, j = 0; + int i_ret = 0; + int fw_len; + bool inpram = false; + u32 dw_lenth; + + + FTS_FUNC_ENTER(); + /*write pramboot*/ + fw_len = fts_getsize(PRAMBOOT_SIZE); + FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len); + + i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len); + if (i_ret != 0) { + FTS_ERROR("[UPGRADE]: write pram failed!!"); + return -EIO; + } + + /*upgrade init*/ + dw_lenth = fts_getsize(FW_SIZE); + i_ret = fts_ctpm_upgrade_idc_init(client, dw_lenth); + if (i_ret < 0) { + FTS_ERROR("[UPGRADE]: upgrade init error, upgrade fail!!"); + return i_ret; + } + + /***Read lockdowninfo***/ + + inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM); + if (!inpram) { + FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!"); + return -EIO; + } + + + msleep(10); + auc_i2c_write_buf[0] = 0x03; + auc_i2c_write_buf[1] = 0x00; + for (i = 0; i < FTS_UPGRADE_LOOP; i++) { + auc_i2c_write_buf[2] = 0x00; + auc_i2c_write_buf[3] = 0x20; + i_ret = fts_i2c_write(client, auc_i2c_write_buf, 4); + if (i_ret < 0) { + printk("[FTS] read lockdowninfo error when i2c write, i_ret = %d\n", i_ret); + continue; + } + msleep(10); + i_ret = fts_i2c_read(client, auc_i2c_write_buf, 0, r_buf, 8); + if (i_ret < 0) { + printk("[FTS] Step 4: read lockdowninfo error when i2c read, i_ret = %d\n", i_ret); + continue; + } + + for (j = 0; j < 8; j++) { + printk("%s: REG VAL = 0x%02x, j=%d\n", __func__, r_buf[j], j); + } + sprintf(pProjectCode, "%02x%02x%02x%02x%02x%02x%02x%02x", \ + r_buf[0], r_buf[1], r_buf[2], r_buf[3], r_buf[4], r_buf[5], r_buf[6], r_buf[7]); + + if (r_buf[0] == 0x38) { + TP_vendor = 1; + printk("vendor is sharp"); + } else if (r_buf[0] == 0x41) { + TP_vendor = 2; + printk("vendor is ebbg"); + } else { + TP_vendor = 3; + printk("vendor is unknow"); + } + break; + } + + printk("%s: reset the tp\n", __func__); + auc_i2c_write_buf[0] = 0x07; + fts_i2c_write(client, auc_i2c_write_buf, 1); + msleep(300); + return 0; +} + + + + + + +/************************************************************************ +* Name: fts_ctpm_write_app +* Brief: fw upgrade +* Input: i2c info, file buf, file len +* Output: no +* Return: fail <0 +***********************************************************************/ +static int fts_ctpm_write_app(struct i2c_client *client, u8 *pbt_buf, u32 dw_lenth) +{ + u32 temp; + int i_ret; + bool inpram = false; + + + + FTS_FUNC_ENTER(); + + /*check run in pramboot or not! if not rum in pramboot, can not upgrade*/ + inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM); + if (!inpram) { + FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!"); + return -EIO; + } + + /*upgrade init*/ + i_ret = fts_ctpm_upgrade_idc_init(client, dw_lenth); + if (i_ret < 0) { + FTS_ERROR("[UPGRADE]: upgrade init error, upgrade fail!!"); + return i_ret; + } + + /*read vendor id from flash, if vendor id error, can not upgrade*/ + i_ret = fts_ctpm_get_vendor_id_flash(client); + if (i_ret < 0) { + FTS_ERROR("[UPGRADE]: read vendor id in flash fail!!"); + return i_ret; + } + + + /*erase the app erea in flash*/ + i_ret = fts_ctpm_erase_flash(client); + if (i_ret < 0) { + FTS_ERROR("[UPGRADE]: erase flash error!!"); + return i_ret; + } + + /*start to write app*/ + i_ret = fts_ctpm_write_app_for_idc(client, dw_lenth, pbt_buf); + if (i_ret < 0) { + FTS_ERROR("[UPGRADE]: write app error!!"); + return i_ret; + } + + /*read check sum*/ + temp = 0x1000; + i_ret = fts_ctpm_upgrade_ecc(client, temp, dw_lenth); + if (i_ret < 0) { + FTS_ERROR("[UPGRADE]: ecc error!!"); + return i_ret; + } + + /*upgrade success, reset the FW*/ + fts_ctpm_rom_or_pram_reset(client); + + FTS_FUNC_EXIT(); + + return 0; +} + + + + +/************************************************************************ +* Name: fts_ctpm_fw_upgrade_use_buf +* Brief: fw upgrade +* Input: i2c info, file buf, file len +* Output: no +* Return: fail <0 +* success =0 +***********************************************************************/ +static int fts_ctpm_fw_upgrade_use_buf(struct i2c_client *client, u8 *pbt_buf, u32 fwsize) +{ + int i_ret = 0; + int fw_len; + + FTS_FUNC_ENTER(); + + /*write pramboot*/ + fw_len = fts_getsize(PRAMBOOT_SIZE); + FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len); + i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len); + if (i_ret != 0) { + FTS_ERROR("[UPGRADE]: write pram failed!!"); + return -EIO; + } + + /*write app*/ + i_ret = fts_ctpm_write_app(client, pbt_buf, fwsize); + + FTS_FUNC_EXIT(); + + return i_ret; +} + +/************************************************************************ +* Name: fts_ctpm_fw_upgrade_with_app_i_file +* Brief: upgrade with *.i file +* Input: i2c info +* Output: +* Return: fail < 0 +***********************************************************************/ +static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client) +{ + int i_ret = 0; + u32 fw_len; + + FTS_INFO("[UPGRADE]**********start upgrade with app.i**********"); + + fw_len = fts_getsize(FW_SIZE); + if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) { + FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len); + return -EIO; + } + + i_ret = fts_ctpm_fw_upgrade_use_buf(client, CTPM_FW, fw_len); + if (i_ret != 0) { + FTS_ERROR("[UPGRADE] upgrade app.i failed"); + } else { + FTS_INFO("[UPGRADE]: upgrade app.i succeed"); + } + + return i_ret; +} + +/************************************************************************ +* Name: fts_ctpm_fw_upgrade_with_app_bin_file +* Brief: upgrade with *.bin file +* Input: i2c info, file name +* Output: no +* Return: success =0 +***********************************************************************/ +static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client, char *firmware_name) +{ + u8 *pbt_buf = NULL; + int i_ret = 0; + bool ecc_ok = false; + int fwsize = fts_GetFirmwareSize(firmware_name); + + FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********"); + + if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) { + FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail", fwsize); + return -EIO; + } + + pbt_buf = (unsigned char *)kmalloc(fwsize + 1, GFP_KERNEL); + if (NULL == pbt_buf) { + FTS_ERROR(" malloc pbt_buf failed "); + goto ERROR_BIN; + } + + if (fts_ReadFirmware(firmware_name, pbt_buf)) { + FTS_ERROR("[UPGRADE]: request_firmware failed!!"); + goto ERROR_BIN; + } +#if FTS_GET_VENDOR_ID + if ((pbt_buf[APP_FILE_VENDORID_MAPPING] != FTS_VENDOR_1_ID) && (pbt_buf[APP_FILE_VENDORID_MAPPING] != FTS_VENDOR_2_ID)) { + FTS_ERROR("[UPGRADE]: vendor id(%02X)[%02X,%02X] is error, app.bin upgrade failed!!", + pbt_buf[fwsize-1], (u8)FTS_VENDOR_1_ID, (u8)FTS_VENDOR_2_ID); + goto ERROR_BIN; + } +#endif + +#if (FTS_CHIP_TYPE == _FT8716) + if ((pbt_buf[APP_FILE_CHIPID_MAPPING] != chip_types.pramboot_idh) + || (pbt_buf[APP_FILE_CHIPID_MAPPING+1] != chip_types.pramboot_idl)) { + FTS_ERROR("[UPGRADE]: chip id(%02X%02X)[%02X%02X] is error, app.bin upgrade failed!!", + pbt_buf[APP_FILE_CHIPID_MAPPING], pbt_buf[APP_FILE_CHIPID_MAPPING+1], chip_types.pramboot_idh, + chip_types.pramboot_idl); + goto ERROR_BIN; + } +#endif + + /*check the app.bin invalid or not*/ + ecc_ok = fts_check_app_bin_valid_idc(pbt_buf); + + if (ecc_ok) { + FTS_INFO("[UPGRADE] app.bin ecc ok"); + i_ret = fts_ctpm_fw_upgrade_use_buf(client, pbt_buf, fwsize); + if (i_ret != 0) { + FTS_ERROR("[UPGRADE]: upgrade app.bin failed"); + goto ERROR_BIN; + } else { + FTS_INFO("[UPGRADE]: upgrade app.bin succeed"); + } + } else { + FTS_ERROR("[UPGRADE] app.bin ecc failed"); + goto ERROR_BIN; + } + + kfree(pbt_buf); + return i_ret; +ERROR_BIN: + kfree(pbt_buf); + return -EIO; +} + + + + + + +#endif /* #if (FTS_CHIP_TYPE == _FT8716) */ diff --git a/drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_idc.c b/drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_idc.c new file mode 100644 index 0000000000000..072eb069646b7 --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_idc.c @@ -0,0 +1,593 @@ +/* + * + * FocalTech fts TouchScreen driver. + * + * Copyright (c) 2010-2016, Focaltech Ltd. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/***************************************************************************** +* +* File Name: focaltech_upgrade_idc.c +* +* Author: fupeipei +* +* Created: 2016-08-22 +* +* Abstract: +* +* Reference: +* +*****************************************************************************/ + +/***************************************************************************** +* 1.Included header files +*****************************************************************************/ +#include "../focaltech_core.h" + +#if (FTS_CHIP_IDC == 1) +#include "../focaltech_flash.h" + +/***************************************************************************** +* Static variables +*****************************************************************************/ + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ +u8 upgrade_ecc; + +/***************************************************************************** +* Static function prototypes +*****************************************************************************/ + +/************************************************************************ +* Name: fts_ctpm_upgrade_idc_init +* Brief: +* Input: +* Output: +* Return: +***********************************************************************/ +int fts_ctpm_upgrade_idc_init(struct i2c_client *client, u32 dw_lenth) +{ + int i_ret = 0; + u8 reg_val_id[4] = {0}; + u8 auc_i2c_write_buf[10]; + + FTS_INFO("[UPGRADE]**********Upgrade setting Init**********"); + + /*read flash ID*/ + auc_i2c_write_buf[0] = 0x05; + reg_val_id[0] = 0x00; + i_ret = fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val_id, 1); + if (i_ret < 0) { + return -EIO; + } + + if (dw_lenth == 0) { + return -EIO; + } + + /*check the fw length by falsh type*/ + if (0x81 == (int)reg_val_id[0]) { + if (dw_lenth > 1024*60) { + return -EIO; + } + } else if (0x80 == (int)reg_val_id[0]) { + if (dw_lenth > 1024*64) { + return -EIO; + } + } + + /*set flash clk*/ + { + auc_i2c_write_buf[0] = 0x05; + auc_i2c_write_buf[1] = reg_val_id[0]; + auc_i2c_write_buf[2] = 0x00; + fts_i2c_write(client, auc_i2c_write_buf, 3); + } + + /*send upgrade type to reg 0x09: 0x0B: upgrade; 0x0A: download*/ + { + auc_i2c_write_buf[0] = 0x09; + auc_i2c_write_buf[1] = 0x0B; + fts_i2c_write(client, auc_i2c_write_buf, 2); + } + + return 0; +} + +/************************************************************************ +* Name: fts_ctpm_start_pramboot +* Brief: +* Input: +* Output: +* Return: +***********************************************************************/ +void fts_ctpm_start_pramboot(struct i2c_client *client) +{ + u8 auc_i2c_write_buf[10]; + + FTS_INFO("[UPGRADE]**********start pramboot**********"); + auc_i2c_write_buf[0] = 0x08; + fts_i2c_write(client, auc_i2c_write_buf, 1); + msleep(20); +} + +/************************************************************************ +* Name: fts_ctpm_start_fw_upgrade +* Brief: +* Input: +* Output: +* Return: +***********************************************************************/ +int fts_ctpm_start_fw_upgrade(struct i2c_client *client) +{ + int i_ret = 0; + + /*send the soft upgrade commond to FW, and start upgrade*/ + FTS_INFO("[UPGRADE]**********send 0xAA and 0x55 to FW, start upgrade**********"); + + i_ret = fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_AA); + msleep(10); + i_ret = fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_55); + msleep(200); + + return i_ret; +} + +/************************************************************************ +* Name: fts_ctpm_check_run_state +* Brief: +* Input: +* Output: +* Return: +***********************************************************************/ +bool fts_ctpm_check_run_state(struct i2c_client *client, int rstate) +{ + int i = 0; + enum FW_STATUS cstate = FTS_RUN_IN_ERROR; + + for (i = 0; i < FTS_UPGRADE_LOOP; i++) { + cstate = fts_ctpm_get_pram_or_rom_id(client); + FTS_DEBUG("[UPGRADE]: run state = %d", cstate); + + if (cstate == rstate) + return true; + msleep(20); + } + + return false; +} + +/************************************************************************ +* Name: fts_ctpm_pramboot_ecc +* Brief: +* Input: +* Output: +* Return: +***********************************************************************/ +int fts_ctpm_pramboot_ecc(struct i2c_client *client) +{ + u8 auc_i2c_write_buf[10]; + u8 reg_val[4] = {0}; + + FTS_FUNC_ENTER(); + + /*read out checksum, if pramboot checksum != host checksum, upgrade fail*/ + FTS_INFO("[UPGRADE]******read out pramboot checksum******"); + auc_i2c_write_buf[0] = 0xcc; + msleep(2); + fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1); + if (reg_val[0] != upgrade_ecc) /*pramboot checksum != host checksum, upgrade fail*/ { + FTS_ERROR("[UPGRADE]: checksum fail : pramboot_ecc = %X, host_ecc = %X!!", reg_val[0], upgrade_ecc); + return -EIO; + } + FTS_DEBUG("[UPGRADE]: checksum success : pramboot_ecc = %X, host_ecc = %X!!", reg_val[0], upgrade_ecc); + msleep(100); + + FTS_FUNC_EXIT(); + + return 0; +} + +/************************************************************************ +* Name: fts_ctpm_upgrade_ecc +* Brief: +* Input: +* Output: +* Return: +***********************************************************************/ +int fts_ctpm_upgrade_ecc(struct i2c_client *client, u32 startaddr, u32 length) +{ + u32 i = 0; + u8 auc_i2c_write_buf[10]; + u32 temp; + u8 reg_val[4] = {0}; + int i_ret = 0; + + FTS_INFO("[UPGRADE]**********read out checksum**********"); + + /*check sum init*/ + auc_i2c_write_buf[0] = 0x64; + fts_i2c_write(client, auc_i2c_write_buf, 1); + msleep(300); + + /*send commond to pramboot to start checksum*/ + auc_i2c_write_buf[0] = 0x65; + auc_i2c_write_buf[1] = (u8)(startaddr >> 16); + auc_i2c_write_buf[2] = (u8)(startaddr >> 8); + auc_i2c_write_buf[3] = (u8)(startaddr); + + if (length > LEN_FLASH_ECC_MAX) { + temp = LEN_FLASH_ECC_MAX; + } else { + temp = length; + } + + auc_i2c_write_buf[4] = (u8)(temp >> 8); + auc_i2c_write_buf[5] = (u8)(temp); + i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6); + msleep(length/256); + + /*read status : if check sum is finished?*/ + for (i = 0; i < 100; i++) { + auc_i2c_write_buf[0] = 0x6a; + reg_val[0] = reg_val[1] = 0x00; + fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2); + + if (0xF0 == reg_val[0] && 0x55 == reg_val[1]) { + break; + } + msleep(1); + + } + + if (length > LEN_FLASH_ECC_MAX) { + temp = LEN_FLASH_ECC_MAX; + auc_i2c_write_buf[0] = 0x65; + auc_i2c_write_buf[1] = (u8)(temp >> 16); + auc_i2c_write_buf[2] = (u8)(temp >> 8); + auc_i2c_write_buf[3] = (u8)(temp); + temp = length-LEN_FLASH_ECC_MAX; + auc_i2c_write_buf[4] = (u8)(temp >> 8); + auc_i2c_write_buf[5] = (u8)(temp); + i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6); + + msleep(length/256); + + for (i = 0; i < 100; i++) { + auc_i2c_write_buf[0] = 0x6a; + reg_val[0] = reg_val[1] = 0x00; + fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2); + + if (0xF0 == reg_val[0] && 0x55 == reg_val[1]) { + break; + } + msleep(1); + } + } + + /*read out check sum*/ + auc_i2c_write_buf[0] = 0x66; + i_ret = fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1); + if (reg_val[0] != upgrade_ecc) /*if check sum fail, upgrade fail*/ { + FTS_ERROR("[UPGRADE]: ecc error! FW=%02x upgrade_ecc=%02x!!", reg_val[0], upgrade_ecc); + return -EIO; + } + + FTS_DEBUG("[UPGRADE]: ecc success : FW=%02x upgrade_ecc=%02x!!", reg_val[0], upgrade_ecc); + + upgrade_ecc = 0; + + return i_ret; +} + +/************************************************************************ +* Name: fts_ctpm_erase_flash +* Brief: +* Input: +* Output: +* Return: +***********************************************************************/ +int fts_ctpm_erase_flash(struct i2c_client *client) +{ + u32 i = 0; + u8 auc_i2c_write_buf[10]; + u8 reg_val[4] = {0}; + + FTS_INFO("[UPGRADE]**********erase app now**********"); + + /*send to erase flash*/ + auc_i2c_write_buf[0] = 0x61; + fts_i2c_write(client, auc_i2c_write_buf, 1); + msleep(1350); + + for (i = 0; i < 15; i++) { + /*get the erase app status, if get 0xF0AA£¬erase flash success*/ + auc_i2c_write_buf[0] = 0x6a; + reg_val[0] = reg_val[1] = 0x00; + fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2); + + if (0xF0 == reg_val[0] && 0xAA == reg_val[1]) /*erase flash success*/ { + break; + } + msleep(50); + } + + if ((0xF0 != reg_val[0] || 0xAA != reg_val[1]) && (i >= 15)) /*erase flash fail*/ { + FTS_ERROR("[UPGRADE]: erase app error.reset tp and reload FW!!"); + return -EIO; + } + FTS_DEBUG("[UPGRADE]: erase app ok!!"); + + return 0; +} + +/************************************************************************ +* Name: fts_ctpm_write_pramboot_for_idc +* Brief: +* Input: +* Output: +* Return: +***********************************************************************/ +int fts_ctpm_write_pramboot_for_idc(struct i2c_client *client, u32 length, u8 *readbuf) +{ + u32 i = 0; + u32 j; + u32 temp; + u32 packet_number; + u8 packet_buf[FTS_PACKET_LENGTH + 6]; + + upgrade_ecc = 0; + FTS_INFO("[UPGRADE]**********write pramboot to pram**********"); + + temp = 0; + packet_number = (length) / FTS_PACKET_LENGTH; + if ((length) % FTS_PACKET_LENGTH > 0) { + packet_number++; + } + packet_buf[0] = 0xae; + packet_buf[1] = 0x00; + + for (j = 0; j < packet_number; j++) { + temp = j * FTS_PACKET_LENGTH; + packet_buf[2] = (u8) (temp >> 8); + packet_buf[3] = (u8) temp; + if (j < (packet_number-1)) { + temp = FTS_PACKET_LENGTH; + } else { + temp = (length) % FTS_PACKET_LENGTH; + } + packet_buf[4] = (u8) (temp >> 8); + packet_buf[5] = (u8) temp; + + for (i = 0; i < temp; i++) { + packet_buf[6 + i] = readbuf[j * FTS_PACKET_LENGTH + i]; + upgrade_ecc ^= packet_buf[6 + i]; + } + fts_i2c_write(client, packet_buf, temp + 6); + } + + return 0; +} + +/************************************************************************ +* Name: fts_ctpm_write_app_for_idc +* Brief: +* Input: +* Output: +* Return: +***********************************************************************/ +int fts_ctpm_write_app_for_idc(struct i2c_client *client, u32 length, u8 *readbuf) +{ + u32 j; + u32 i = 0; + u32 packet_number; + u32 temp; + u32 writelenght; + u8 packet_buf[FTS_PACKET_LENGTH + 6]; + u8 auc_i2c_write_buf[10]; + u8 reg_val[4] = {0}; + + FTS_INFO("[UPGRADE]**********write app to flash**********"); + + upgrade_ecc = 0; + + packet_number = (length) / FTS_PACKET_LENGTH; + if (((length) % FTS_PACKET_LENGTH) > 0) { + packet_number++; + } + + packet_buf[0] = 0xbf; + + for (j = 0; j < packet_number; j++) { + temp = 0x1000+j * FTS_PACKET_LENGTH; + + if (j < (packet_number-1)) { + writelenght = FTS_PACKET_LENGTH; + } else { + writelenght = ((length) % FTS_PACKET_LENGTH); + } + packet_buf[1] = (u8) (temp >> 16); + packet_buf[2] = (u8) (temp >> 8); + packet_buf[3] = (u8) temp; + packet_buf[4] = (u8) (writelenght >> 8); + packet_buf[5] = (u8) writelenght; + + for (i = 0; i < writelenght; i++) { + packet_buf[6 + i] = readbuf[(temp - 0x1000+i)]; + upgrade_ecc ^= packet_buf[6 + i]; + } + + fts_i2c_write(client, packet_buf, (writelenght + 6)); + + for (i = 0; i < 30; i++) { + /*read status and check if the app writting is finished*/ + auc_i2c_write_buf[0] = 0x6a; + reg_val[0] = reg_val[1] = 0x00; + fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2); + + if ((j + 0x20+0x1000) == (((reg_val[0]) << 8) | reg_val[1])) { + break; + } + + fts_ctpm_upgrade_delay(1000); + } + } + msleep(50); + + return 0; +} + + +typedef enum { + APP_LEN = 0x00, + APP_LEN_NE = 0x02, + APP_P1_ECC = 0x04, + APP_P1_ECC_NE = 0x06, + APP_P2_ECC = 0x08, + APP_P2_ECC_NE = 0x0A, + APP_LEN_H = 0x12, + APP_LEN_H_NE = 0x14, + APP_BLR_ID = 0x1C, + APP_BLR_ID_NE = 0x1D, + PBOOT_ID_H = 0x1E, + PBOOT_ID_L = 0x1F +} ENUM_APP_INFO; + +#define AL2_FCS_COEF ((1 << 15) + (1 << 10) + (1 << 3)) + +#if ((FTS_CHIP_TYPE == _FT8006) || (FTS_CHIP_TYPE == _FT8736)) +#define FW_CFG_TOTAL_SIZE 0x80 +#else +#define FW_CFG_TOTAL_SIZE 0x00 +#endif +#define APP1_START 0x00 +#define APP1_LEN 0x100 +#define APP_VERIF_ADDR (APP1_START + APP1_LEN) +#define APP_VERIF_LEN 0x20 +#define APP1_ECC_ADDR (APP_VERIF_ADDR + APP_P1_ECC) +#define APP2_START (APP_VERIF_ADDR + APP_VERIF_LEN + FW_CFG_TOTAL_SIZE) +#define APP2_ECC_ADDR (APP_VERIF_ADDR + APP_P2_ECC) +/***************************************************************************** +* Name: DrvReadPram16 +* Brief: Get Word +* Input: +* Output: +* Return: +*****************************************************************************/ +static u16 data_word(u8 *pbt_buf, u32 addr) +{ + return (((u16)pbt_buf[addr]<<8) + pbt_buf[addr+1]); +} + +/****************************************************************************** +* Name: GetCrc16 +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +u16 crc_calc(u8 *pbt_buf, u32 addr, u16 length) +{ + u16 cFcs = 0; + u16 i, j; + + FTS_DEBUG("[UPGRADE][ECC] : %04x data:%04x, len:%04x!!", (addr), data_word(pbt_buf, (addr)), length); + for (i = 0; i < length; i++) { + cFcs ^= data_word(pbt_buf, (addr+i*2)); + for (j = 0; j < 16; j++) { + if (cFcs & 1) { + cFcs = (u16)((cFcs >> 1) ^ AL2_FCS_COEF); + } else { + cFcs >>= 1; + } + } + } + return cFcs; +} + +/***************************************************************************** +* Name: task_check_mem +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +bool ecc_check(u8 *pbt_buf, u32 star_addr, u32 len, u16 ecc_addr) +{ + u16 ecc1; + u16 ecc2; + u16 cal_ecc; + + ecc1 = data_word(pbt_buf, ecc_addr); + ecc2 = data_word(pbt_buf, ecc_addr+2); + + if ((ecc1 + ecc2) != 0xFFFF) { + return false; + } + + cal_ecc = crc_calc(pbt_buf, star_addr, (len/2)); + + FTS_DEBUG("[UPGRADE][ECC] : ecc1 = %x, cal_ecc = %x", ecc1, cal_ecc); + if (ecc1 != cal_ecc) { + FTS_DEBUG("[UPGRADE][ECC] : ecc error!!"); + return false; + } + return true; +} + +/***************************************************************************** +* Name: fts_check_app_bin_valid_idc +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +bool fts_check_app_bin_valid_idc(u8 *pbt_buf) +{ + u32 len; +#if (FTS_CHIP_TYPE != _FT8006) + /* 1. First Byte */ + if (pbt_buf[0] != 0x02) { + FTS_DEBUG("[UPGRADE]APP.BIN Verify- the first byte(%x) error", pbt_buf[0]); + return false; + } +#endif + /* 2 PART1 ECC */ + if (!ecc_check(pbt_buf, APP1_START, APP1_LEN, APP1_ECC_ADDR)) { + FTS_DEBUG("[UPGRADE]APP.BIN Verify- ecc1 error"); + return false; + } + + /* 3. PART2 ECC */ + if ((data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN) + data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_NE)) != 0xFFFF) { + FTS_DEBUG("[UPGRADE]APP.BIN Verify- Length XOR error"); + return false; + } + len = data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN); +#if (FTS_CHIP_TYPE == _FT8006) + if ((data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_H) + data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_H_NE)) != 0xFFFF) { + FTS_DEBUG("[UPGRADE]APP.BIN Verify- Length2 XOR error"); + return false; + } + len += ((u32)data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_H) << 16); +#endif + FTS_DEBUG("%x %x %x %x", APP2_START, len, ((u32)data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_H) << 16), data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN)); + len -= APP2_START; + + return ecc_check(pbt_buf, APP2_START, len, APP2_ECC_ADDR); +} + + +#endif /* IDC */ diff --git a/drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_test.c b/drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_test.c new file mode 100644 index 0000000000000..952eb68c5a5c3 --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_flash/focaltech_upgrade_test.c @@ -0,0 +1,162 @@ +/* + * + * FocalTech fts TouchScreen driver. + * + * Copyright (c) 2010-2016, Focaltech Ltd. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/***************************************************************************** +* +* File Name: focaltech_upgrade_test.c +* +* Author: fupeipei +* +* Created: 2016-08-22 +* +* Abstract: +* +* Reference: +* +*****************************************************************************/ + +/***************************************************************************** +* 1.Included header files +*****************************************************************************/ +#include "../focaltech_core.h" +#include "../focaltech_flash.h" +#include +#include + +/***************************************************************************** +* Static variables +*****************************************************************************/ +#define FTS_GET_UPGRADE_TIME 0 + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ +struct wake_lock ps_lock; + +#define FTS_DEBUG_UPGRADE(fmt, args...) do {\ + printk(KERN_ERR "[FTS][UPGRADE]:##############################################################################\n");\ + printk(KERN_ERR "[FTS][UPGRADE]: "fmt"\n", ##args);\ + printk(KERN_ERR "[FTS][UPGRADE]:##############################################################################\n");\ + } while (0)\ + +/***************************************************************************** +* Static function prototypes +*****************************************************************************/ +#if (FTS_UPGRADE_STRESS_TEST) +/************************************************************************ +* Name: fts_ctpm_auto_upgrade_pingpong +* Brief: 0 +* Input: 0 +* Output: 0 +* Return: 0 +***********************************************************************/ + +static int fts_ctpm_auto_upgrade_pingpong(struct i2c_client *client) +{ + u8 uc_tp_fm_ver; + int i_ret = 0; + u8 uc_upgrade_times = 0; + + FTS_FUNC_ENTER(); + + /* pingpong test mode, need upgrade */ + FTS_INFO("[UPGRADE]: pingpong test mode, need upgrade!!"); + do { + uc_upgrade_times++; + + /* fw upgrade */ + i_ret = fts_ctpm_fw_upgrade(client); + + if (i_ret == 0) /* upgrade success */ { + fts_i2c_read_reg(client, FTS_REG_FW_VER, &uc_tp_fm_ver); + FTS_DEBUG("[UPGRADE]: upgrade to new version 0x%x", uc_tp_fm_ver); + } else /* upgrade fail */ { + /* if upgrade fail, reset to run ROM. if app in flash is ok. TP will work success */ + FTS_INFO("[UPGRADE]: upgrade fail, reset now!!"); + fts_ctpm_rom_or_pram_reset(client); + } + } while ((i_ret != 0) && (uc_upgrade_times < 2)); /* if upgrade fail, upgrade again. then return */ + + FTS_FUNC_EXIT(); + return i_ret; +} + +/************************************************************************ +* Name: fts_ctpm_auto_upgrade +* Brief: 0 +* Input: 0 +* Output: 0 +* Return: 0 +***********************************************************************/ +void fts_ctpm_display_upgrade_time(bool start_time) +{ +#if FTS_GET_UPGRADE_TIME + static struct timeval tpend; + static struct timeval tpstart; + static int timeuse; + + if (start_time) { + do_gettimeofday(&tpstart); + } else { + do_gettimeofday(&tpend); + timeuse = 1000000*(tpend.tv_sec-tpstart.tv_sec) + tpend.tv_usec-tpstart.tv_usec; + timeuse /= 1000000; + FTS_DEBUG("[UPGRADE]: upgrade success : Use time: %d Seconds!!", timeuse); + } +#endif +} + +/************************************************************************ +* Name: fts_ctpm_auto_upgrade +* Brief: 0 +* Input: 0 +* Output: 0 +* Return: 0 +***********************************************************************/ +int fts_ctpm_auto_upgrade(struct i2c_client *client) +{ + int i_ret = 0; + static int uc_ErrorTimes0; + static int uc_UpgradeTimes; + + wake_lock_init(&ps_lock, WAKE_LOCK_SUSPEND, "tp_wakelock"); + + wake_lock(&ps_lock); + + do { + uc_UpgradeTimes++; + + FTS_DEBUG_UPGRADE("start to upgrade %d times !!", uc_UpgradeTimes); + + fts_ctpm_display_upgrade_time(true); + + i_ret = fts_ctpm_auto_upgrade_pingpong(client); + if (i_ret == 0) { + fts_ctpm_display_upgrade_time(false); + } else { + uc_ErrorTimes++; + } + + FTS_DEBUG_UPGRADE("upgrade %d times, error %d times!!", uc_UpgradeTimes, uc_ErrorTimes); + } while (uc_UpgradeTimes < (FTS_UPGRADE_TEST_NUMBER)); + + wake_unlock(&ps_lock); + + return 0; +} +#endif + diff --git a/drivers/input/touchscreen/ft8716/focaltech_gesture.c b/drivers/input/touchscreen/ft8716/focaltech_gesture.c new file mode 100644 index 0000000000000..500a8cb797d2e --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_gesture.c @@ -0,0 +1,651 @@ +/* + * + * FocalTech TouchScreen driver. + * + * Copyright (c) 2010-2016, Focaltech Ltd. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/***************************************************************************** +* +* File Name: focaltech_gestrue.c +* +* Author: Focaltech Driver Team +* +* Created: 2016-08-08 +* +* Abstract: +* +* Reference: +* +*****************************************************************************/ + +/***************************************************************************** +* 1.Included header files +*****************************************************************************/ +#include "focaltech_core.h" +#if FTS_GESTURE_EN +/****************************************************************************** +* Private constant and macro definitions using #define +*****************************************************************************/ +#define KEY_GESTURE_U KEY_U +#define KEY_GESTURE_UP KEY_UP +#define KEY_GESTURE_DOWN KEY_DOWN +#define KEY_GESTURE_LEFT KEY_LEFT +#define KEY_GESTURE_RIGHT KEY_RIGHT +#define KEY_GESTURE_O KEY_O +#define KEY_GESTURE_E KEY_E +#define KEY_GESTURE_M KEY_M +#define KEY_GESTURE_L KEY_L +#define KEY_GESTURE_W KEY_W +#define KEY_GESTURE_S KEY_S +#define KEY_GESTURE_V KEY_V +#define KEY_GESTURE_C KEY_C +#define KEY_GESTURE_Z KEY_Z + +#define GESTURE_LEFT 0x20 +#define GESTURE_RIGHT 0x21 +#define GESTURE_UP 0x22 +#define GESTURE_DOWN 0x23 +#define GESTURE_DOUBLECLICK 0x24 +#define GESTURE_O 0x30 +#define GESTURE_W 0x31 +#define GESTURE_M 0x32 +#define GESTURE_E 0x33 +#define GESTURE_L 0x44 +#define GESTURE_S 0x46 +#define GESTURE_V 0x54 +#define GESTURE_Z 0x41 +#define GESTURE_C 0x34 +#define FTS_GESTRUE_POINTS 255 +#define FTS_GESTRUE_POINTS_HEADER 8 +#define FTS_GESTURE_OUTPUT_ADRESS 0xD3 +/***************************************************************************** +* Private enumerations, structures and unions using typedef +*****************************************************************************/ +struct fts_gesture_st { + u8 header[FTS_GESTRUE_POINTS_HEADER]; + u16 coordinate_x[FTS_GESTRUE_POINTS]; + u16 coordinate_y[FTS_GESTRUE_POINTS]; + u8 mode; + u8 active; /* 1-enter into gesture(suspend) 0-gesture disable or LCD on */ +}; + +/***************************************************************************** +* Static variables +*****************************************************************************/ +static struct fts_gesture_st fts_gesture_data; +extern struct fts_ts_data *fts_wq_data; + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ + +/***************************************************************************** +* Static function prototypes +*****************************************************************************/ +static ssize_t fts_gesture_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t fts_gesture_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); +static ssize_t fts_gesture_buf_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t fts_gesture_buf_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); + +/* sysfs gesture node + * read example: cat fts_gesture_mode ---read gesture mode + * write example:echo 01 > fts_gesture_mode ---write gesture mode to 01 + * + */ +static DEVICE_ATTR (fts_gesture_mode, S_IRUGO|S_IWUSR, fts_gesture_show, fts_gesture_store); +/* + * read example: cat fts_gesture_buf ---read gesture buf + */ +static DEVICE_ATTR (fts_gesture_buf, S_IRUGO|S_IWUSR, fts_gesture_buf_show, fts_gesture_buf_store); +static struct attribute *fts_gesture_mode_attrs[] = { + + &dev_attr_fts_gesture_mode.attr, + &dev_attr_fts_gesture_buf.attr, + NULL, +}; + +static struct attribute_group fts_gesture_group = { + .attrs = fts_gesture_mode_attrs, +}; + + +/************************************************************************ +* Name: fts_gesture_show +* Brief: no +* Input: device, device attribute, char buf +* Output: no +* Return: +***********************************************************************/ +#if FTS_GESTURE_EN + int ft8716_gesture_func_on = 0; +#endif + +static ssize_t fts_gesture_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int count; + u8 val; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + mutex_lock(&fts_input_dev->mutex); + fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &val); + count = sprintf(buf, "Gesture Mode: %s\n", fts_gesture_data.mode ? "On" : "Off"); + count += sprintf(buf + count, "Reg(0xD0) = %d\n", val); + count += sprintf(buf + count, "ft8716_gesture_func_on : %d\n", ft8716_gesture_func_on); + mutex_unlock(&fts_input_dev->mutex); + + return count; +} + +/************************************************************************ +* Name: fts_gesture_store +* Brief: no +* Input: device, device attribute, char buf, char count +* Output: no +* Return: +***********************************************************************/ +static ssize_t fts_gesture_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + mutex_lock(&fts_input_dev->mutex); + + if (FTS_SYSFS_ECHO_ON(buf)) { + FTS_INFO("[GESTURE]enable gesture"); + fts_gesture_data.mode = ENABLE; + ft8716_gesture_func_on = 1; + } else if (FTS_SYSFS_ECHO_OFF(buf)) { + FTS_INFO("[GESTURE]disable gesture"); + fts_gesture_data.mode = DISABLE; + ft8716_gesture_func_on = 0; + } + if (ft8716_gesture_func_on == 1) + printk("ft8716_gesture_func_on is on"); + else + printk("ft8716_gesture_func_on is off"); + mutex_unlock(&fts_input_dev->mutex); + + + return count; +} + +/************************************************************************ +* Name: fts_gesture_buf_show +* Brief: no +* Input: device, device attribute, char buf +* Output: no +* Return: +***********************************************************************/ +static ssize_t fts_gesture_buf_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int count; + int i = 0; + + mutex_lock(&fts_input_dev->mutex); + count = snprintf(buf, PAGE_SIZE, "Gesture ID: 0x%x\n", fts_gesture_data.header[0]); + count += snprintf(buf + count, PAGE_SIZE, "Gesture PointNum: %d\n", fts_gesture_data.header[1]); + count += snprintf(buf + count, PAGE_SIZE, "Gesture Point Buf:\n"); + for (i = 0; i < fts_gesture_data.header[1]; i++) { + count += snprintf(buf + count, PAGE_SIZE, "%3d(%4d,%4d) ", i, fts_gesture_data.coordinate_x[i], fts_gesture_data.coordinate_y[i]); + if ((i + 1)%4 == 0) + count += snprintf(buf + count, PAGE_SIZE, "\n"); + } + count += snprintf(buf + count, PAGE_SIZE, "\n"); + mutex_unlock(&fts_input_dev->mutex); + + return count; +} + +/************************************************************************ +* Name: fts_gesture_buf_store +* Brief: no +* Input: device, device attribute, char buf, char count +* Output: no +* Return: +***********************************************************************/ +static ssize_t fts_gesture_buf_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + /* place holder for future use */ + return -EPERM; +} + +/***************************************************************************** +* Name: fts_create_gesture_sysfs +* Brief: +* Input: +* Output: None +* Return: 0-success or error +*****************************************************************************/ +int fts_create_gesture_sysfs(struct i2c_client *client) +{ + int ret = 0; + + ret = sysfs_create_group(&client->dev.kobj, &fts_gesture_group); + if (ret != 0) { + FTS_ERROR("[GESTURE]fts_gesture_mode_group(sysfs) create failed!"); + sysfs_remove_group(&client->dev.kobj, &fts_gesture_group); + return ret; + } + return 0; +} + +/***************************************************************************** +* Name: fts_gesture_recovery +* Brief: recovery gesture state when reset +* Input: +* Output: None +* Return: +*****************************************************************************/ +void fts_gesture_recovery(struct i2c_client *client) +{ + if (fts_gesture_data.mode && fts_gesture_data.active) { + fts_i2c_write_reg(client, 0xD1, 0xff); + fts_i2c_write_reg(client, 0xD2, 0xff); + fts_i2c_write_reg(client, 0xD5, 0xff); + fts_i2c_write_reg(client, 0xD6, 0xff); + fts_i2c_write_reg(client, 0xD7, 0xff); + fts_i2c_write_reg(client, 0xD8, 0xff); + fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, ENABLE); + } +} + +#if FTS_GESTURE_EN + +#define WAKEUP_OFF 4 +#define WAKEUP_ON 5 + +int ft8716_gesture_switch(struct input_dev *dev, unsigned int type, unsigned int code, int value) +{ + + mutex_lock(&fts_input_dev->mutex); + + if (type == EV_SYN && code == SYN_CONFIG) { + if (value == WAKEUP_OFF) { + ft8716_gesture_func_on = 0; + FTS_INFO("[GESTURE]disable gesture"); + fts_gesture_data.mode = DISABLE; + } else if (value == WAKEUP_ON) { + ft8716_gesture_func_on = 1; + FTS_INFO("[GESTURE]enable gesture"); + fts_gesture_data.mode = ENABLE; + } + } + mutex_unlock(&fts_input_dev->mutex); + return 0; +} +#endif + +/***************************************************************************** +* Name: fts_gesture_init +* Brief: +* Input: +* Output: None +* Return: None +*****************************************************************************/ +int fts_gesture_init(struct input_dev *input_dev, struct i2c_client *client) +{ + FTS_FUNC_ENTER(); + input_set_capability(input_dev, EV_KEY, KEY_POWER); + input_set_capability(input_dev, EV_KEY, KEY_GESTURE_U); + input_set_capability(input_dev, EV_KEY, KEY_GESTURE_UP); + input_set_capability(input_dev, EV_KEY, KEY_GESTURE_DOWN); + input_set_capability(input_dev, EV_KEY, KEY_GESTURE_LEFT); + input_set_capability(input_dev, EV_KEY, KEY_GESTURE_RIGHT); + input_set_capability(input_dev, EV_KEY, KEY_GESTURE_O); + input_set_capability(input_dev, EV_KEY, KEY_GESTURE_E); + input_set_capability(input_dev, EV_KEY, KEY_GESTURE_M); + input_set_capability(input_dev, EV_KEY, KEY_GESTURE_L); + input_set_capability(input_dev, EV_KEY, KEY_GESTURE_W); + input_set_capability(input_dev, EV_KEY, KEY_GESTURE_S); + input_set_capability(input_dev, EV_KEY, KEY_GESTURE_V); + input_set_capability(input_dev, EV_KEY, KEY_GESTURE_Z); + input_set_capability(input_dev, EV_KEY, KEY_GESTURE_C); + + __set_bit(KEY_GESTURE_RIGHT, input_dev->keybit); + __set_bit(KEY_GESTURE_LEFT, input_dev->keybit); + __set_bit(KEY_GESTURE_UP, input_dev->keybit); + __set_bit(KEY_GESTURE_DOWN, input_dev->keybit); + __set_bit(KEY_GESTURE_U, input_dev->keybit); + __set_bit(KEY_GESTURE_O, input_dev->keybit); + __set_bit(KEY_GESTURE_E, input_dev->keybit); + __set_bit(KEY_GESTURE_M, input_dev->keybit); + __set_bit(KEY_GESTURE_W, input_dev->keybit); + __set_bit(KEY_GESTURE_L, input_dev->keybit); + __set_bit(KEY_GESTURE_S, input_dev->keybit); + __set_bit(KEY_GESTURE_V, input_dev->keybit); + __set_bit(KEY_GESTURE_C, input_dev->keybit); + __set_bit(KEY_GESTURE_Z, input_dev->keybit); + + fts_create_gesture_sysfs(client); + fts_gesture_data.mode = 0; + fts_gesture_data.active = 0; + + input_set_capability(input_dev, EV_KEY, KEY_WAKEUP); + + input_dev->event = ft8716_gesture_switch; + + FTS_FUNC_EXIT(); + return 0; +} + +/************************************************************************ +* Name: fts_gesture_exit +* Brief: remove sys +* Input: i2c info +* Output: no +* Return: no +***********************************************************************/ +int fts_gesture_exit(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &fts_gesture_group); + return 0; +} + +/***************************************************************************** +* Name: fts_check_gesture +* Brief: +* Input: +* Output: None +* Return: None +*****************************************************************************/ +static void fts_check_gesture(struct input_dev *input_dev, int gesture_id) +{ + char *envp[2]; + int gesture; + + FTS_FUNC_ENTER(); + switch (gesture_id) { + case GESTURE_LEFT: + envp[0] = "GESTURE = LEFT"; + gesture = KEY_GESTURE_LEFT; + break; + case GESTURE_RIGHT: + envp[0] = "GESTURE = RIGHT"; + gesture = KEY_GESTURE_RIGHT; + break; + case GESTURE_UP: + envp[0] = "GESTURE = UP"; + gesture = KEY_GESTURE_UP; + break; + case GESTURE_DOWN: + envp[0] = "GESTURE = DOWN"; + gesture = KEY_GESTURE_DOWN; + break; + case GESTURE_DOUBLECLICK: + envp[0] = "GESTURE = DOUBLE_CLICK"; + gesture = KEY_WAKEUP; + break; + case GESTURE_O: + envp[0] = "GESTURE = O"; + gesture = KEY_GESTURE_O; + break; + case GESTURE_W: + envp[0] = "GESTURE = W"; + gesture = KEY_GESTURE_W; + break; + case GESTURE_M: + envp[0] = "GESTURE = M"; + gesture = KEY_GESTURE_M; + break; + case GESTURE_E: + envp[0] = "GESTURE = E"; + gesture = KEY_GESTURE_E; + break; + case GESTURE_L: + envp[0] = "GESTURE = L"; + gesture = KEY_GESTURE_L; + break; + case GESTURE_S: + envp[0] = "GESTURE = S"; + gesture = KEY_GESTURE_S; + break; + case GESTURE_V: + envp[0] = "GESTURE = V"; + gesture = KEY_GESTURE_V; + break; + case GESTURE_Z: + envp[0] = "GESTURE = Z"; + gesture = KEY_GESTURE_Z; + break; + case GESTURE_C: + envp[0] = "GESTURE = C"; + gesture = KEY_GESTURE_C; + break; + default: + envp[0] = "GESTURE = NONE"; + gesture = -1; + break; + } + FTS_DEBUG("envp[0]: %s", envp[0]); + /* report event key */ + if (gesture != -1) { + input_report_key(input_dev, gesture, 1); + input_sync(input_dev); + input_report_key(input_dev, gesture, 0); + input_sync(input_dev); + printk("[FTS]gesture KEY_WAKEUP\n"); + } else { + printk("[FTS]gesture = -1\n"); + } + + envp[1] = NULL; + kobject_uevent_env(&fts_wq_data->client->dev.kobj, KOBJ_CHANGE, envp); + sysfs_notify(&fts_wq_data->client->dev.kobj, NULL, "GESTURE_ID"); + + FTS_FUNC_EXIT(); +} + +/************************************************************************ +* Name: fts_gesture_readdata +* Brief: read data from TP register +* Input: no +* Output: no +* Return: fail <0 +***********************************************************************/ +static int fts_gesture_read_buffer(struct i2c_client *client, u8 *buf, int read_bytes) +{ + int remain_bytes; + int ret; + int i; + + if (read_bytes <= I2C_BUFFER_LENGTH_MAXINUM) { + ret = fts_i2c_read(client, buf, 1, buf, read_bytes); + } else { + ret = fts_i2c_read(client, buf, 1, buf, I2C_BUFFER_LENGTH_MAXINUM); + remain_bytes = read_bytes - I2C_BUFFER_LENGTH_MAXINUM; + for (i = 1; remain_bytes > 0; i++) { + if (remain_bytes <= I2C_BUFFER_LENGTH_MAXINUM) + ret = fts_i2c_read(client, buf, 0, buf + I2C_BUFFER_LENGTH_MAXINUM * i, remain_bytes); + else + ret = fts_i2c_read(client, buf, 0, buf + I2C_BUFFER_LENGTH_MAXINUM * i, I2C_BUFFER_LENGTH_MAXINUM); + remain_bytes -= I2C_BUFFER_LENGTH_MAXINUM; + } + } + + return ret; +} + +/************************************************************************ +* Name: fts_gesture_readdata +* Brief: read data from TP register +* Input: no +* Output: no +* Return: fail <0 +***********************************************************************/ +int fts_gesture_readdata(struct i2c_client *client) +{ + u8 buf[FTS_GESTRUE_POINTS * 4] = { 0 }; + int ret = -1; + int i = 0; + int gestrue_id = 0; + int read_bytes = 0; + u8 pointnum; + + FTS_FUNC_ENTER(); + /* init variable before read gesture point */ + memset(fts_gesture_data.header, 0, FTS_GESTRUE_POINTS_HEADER); + memset(fts_gesture_data.coordinate_x, 0, FTS_GESTRUE_POINTS * sizeof(u16)); + memset(fts_gesture_data.coordinate_y, 0, FTS_GESTRUE_POINTS * sizeof(u16)); + + buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS; + ret = fts_i2c_read(client, buf, 1, buf, FTS_GESTRUE_POINTS_HEADER); + if (ret < 0) { + FTS_ERROR("[GESTURE]Read gesture header data failed!!"); + FTS_FUNC_EXIT(); + return ret; + } + + /* FW recognize gesture */ + if (chip_types.chip_idh == 0x54 || chip_types.chip_idh == 0x58 || chip_types.chip_idh == 0x86 || chip_types.chip_idh == 0x87 || chip_types.chip_idh == 0x64) { + memcpy(fts_gesture_data.header, buf, FTS_GESTRUE_POINTS_HEADER); + gestrue_id = buf[0]; + pointnum = buf[1]; + read_bytes = ((int)pointnum) * 4 + 2; + buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS; + FTS_DEBUG("[GESTURE]PointNum=%d", pointnum); + ret = fts_gesture_read_buffer(client, buf, read_bytes); + if (ret < 0) { + FTS_ERROR("[GESTURE]Read gesture touch data failed!!"); + FTS_FUNC_EXIT(); + return ret; + } + + fts_check_gesture(fts_input_dev, gestrue_id); + for (i = 0; i < pointnum; i++) { + fts_gesture_data.coordinate_x[i] = (((s16) buf[0 + (4 * i + 2)]) & 0x0F) << 8 + | (((s16) buf[1 + (4 * i + 2)]) & 0xFF); + fts_gesture_data.coordinate_y[i] = (((s16) buf[2 + (4 * i + 2)]) & 0x0F) << 8 + | (((s16) buf[3 + (4 * i + 2)]) & 0xFF); + } + FTS_FUNC_EXIT(); + return 0; + } + /* other IC's gestrue in driver */ + if (0x24 == buf[0]) { + gestrue_id = 0x24; + fts_check_gesture(fts_input_dev, gestrue_id); + FTS_DEBUG("[GESTURE]%d check_gesture gestrue_id", gestrue_id); + FTS_FUNC_EXIT(); + return -EPERM; + } + + /* Host Driver recognize gesture */ + pointnum = buf[1]; + read_bytes = ((int)pointnum) * 4 + 2; + buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS; + ret = fts_gesture_read_buffer(client, buf, read_bytes); + if (ret < 0) { + FTS_ERROR("[GESTURE]Driver recognize gesture - Read gesture touch data failed!!"); + FTS_FUNC_EXIT(); + return ret; + } + + gestrue_id = 0x24; + fts_check_gesture(fts_input_dev, gestrue_id); + FTS_DEBUG("[GESTURE]%d read gestrue_id", gestrue_id); + + for (i = 0; i < pointnum; i++) { + fts_gesture_data.coordinate_x[i] = (((s16) buf[0 + (4 * i+8)]) & 0x0F) << 8 + | (((s16) buf[1 + (4 * i+8)]) & 0xFF); + fts_gesture_data.coordinate_y[i] = (((s16) buf[2 + (4 * i+8)]) & 0x0F) << 8 + | (((s16) buf[3 + (4 * i+8)]) & 0xFF); + } + FTS_FUNC_EXIT(); + return -EPERM; +} + +/***************************************************************************** +* Name: fts_gesture_suspend +* Brief: +* Input: +* Output: None +* Return: None +*****************************************************************************/ +int fts_gesture_suspend(struct i2c_client *i2c_client) +{ + int i; + u8 state; + + FTS_FUNC_ENTER(); + + /* gesture not enable, return immediately */ + if (fts_gesture_data.mode == 0) { + FTS_DEBUG("gesture is disabled"); + FTS_FUNC_EXIT(); + return -EPERM; + } + + for (i = 0; i < 5; i++) { + fts_i2c_write_reg(i2c_client, 0xd1, 0xff); + fts_i2c_write_reg(i2c_client, 0xd2, 0xff); + fts_i2c_write_reg(i2c_client, 0xd5, 0xff); + fts_i2c_write_reg(i2c_client, 0xd6, 0xff); + fts_i2c_write_reg(i2c_client, 0xd7, 0xff); + fts_i2c_write_reg(i2c_client, 0xd8, 0xff); + + fts_i2c_write_reg(i2c_client, FTS_REG_GESTURE_EN, 0x01); + msleep(1); + fts_i2c_read_reg(i2c_client, FTS_REG_GESTURE_EN, &state); + printk("FTS_REG_GESTURE_EN is : %d", state); + if (state == 1) { + printk("FTS_REG_GESTURE_EN write success\n"); + break; } + } + + if (i >= 5) { + FTS_ERROR("[GESTURE]Enter into gesture(suspend) failed!\n"); + FTS_FUNC_EXIT(); + return -EPERM; + } + + fts_gesture_data.active = 1; + FTS_DEBUG("[GESTURE]Enter into gesture(suspend) successfully!"); + FTS_FUNC_EXIT(); + return 0; +} + +/***************************************************************************** +* Name: fts_gesture_resume +* Brief: +* Input: +* Output: None +* Return: None +*****************************************************************************/ +int fts_gesture_resume(struct i2c_client *client) +{ + int i; + u8 state; + FTS_FUNC_ENTER(); + + /* gesture not enable, return immediately */ + if (fts_gesture_data.mode == 0) { + FTS_DEBUG("gesture is disabled"); + FTS_FUNC_EXIT(); + return -EPERM; + } + + fts_gesture_data.active = 0; + for (i = 0; i < 5; i++) { + fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, 0x00); + msleep(1); + fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &state); + if (state == 0) + break; + } + + if (i >= 5) { + FTS_ERROR("[GESTURE]Clear gesture(resume) failed!\n"); + } + + FTS_FUNC_EXIT(); + return 0; +} +#endif diff --git a/drivers/input/touchscreen/ft8716/focaltech_i2c.c b/drivers/input/touchscreen/ft8716/focaltech_i2c.c new file mode 100644 index 0000000000000..3379e36aa3e60 --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_i2c.c @@ -0,0 +1,204 @@ +/* + * + * FocalTech TouchScreen driver. + * + * Copyright (c) 2010-2016, FocalTech Systems, Ltd., all rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/************************************************************************ +* +* File Name: focaltech_i2c.c +* +* Author: fupeipei +* +* Created: 2016-08-04 +* +* Abstract: i2c communication with TP +* +* Version: v1.0 +* +* Revision History: +* v1.0: +* First release. By fupeipei 2016-08-04 +************************************************************************/ + +/***************************************************************************** +* Included header files +*****************************************************************************/ +#include "focaltech_core.h" + +/***************************************************************************** +* Private constant and macro definitions using #define +*****************************************************************************/ + +/***************************************************************************** +* Private enumerations, structures and unions using typedef +*****************************************************************************/ + +/***************************************************************************** +* Static variables +*****************************************************************************/ +static DEFINE_MUTEX(i2c_rw_access); + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ + +/***************************************************************************** +* Static function prototypes +*****************************************************************************/ + +/***************************************************************************** +* functions body +*****************************************************************************/ + +/************************************************************************ +* Name: fts_i2c_read +* Brief: i2c read +* Input: i2c info, write buf, write len, read buf, read len +* Output: get data in the 3rd buf +* Return: fail <0 +***********************************************************************/ +int fts_i2c_read(struct i2c_client *client, char *writebuf, int writelen, char *readbuf, int readlen) +{ + int ret; + + mutex_lock(&i2c_rw_access); + + if (readlen > 0) { + if (writelen > 0) { + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = writelen, + .buf = writebuf, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = readlen, + .buf = readbuf, + }, + }; + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret < 0) { + FTS_ERROR("[IIC]: i2c_transfer(write) error, ret=%d!!", ret); + } + } else { + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = readlen, + .buf = readbuf, + }, + }; + ret = i2c_transfer(client->adapter, msgs, 1); + if (ret < 0) { + FTS_ERROR("[IIC]: i2c_transfer(read) error, ret=%d!!", ret); + } + } + } + + mutex_unlock(&i2c_rw_access); + return ret; +} + +/************************************************************************ +* Name: fts_i2c_write +* Brief: i2c write +* Input: i2c info, write buf, write len +* Output: no +* Return: fail <0 +***********************************************************************/ +int fts_i2c_write(struct i2c_client *client, char *writebuf, int writelen) +{ + int ret = 0; + + mutex_lock(&i2c_rw_access); + if (writelen > 0) { + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = writelen, + .buf = writebuf, + }, + }; + ret = i2c_transfer(client->adapter, msgs, 1); + if (ret < 0) { + FTS_ERROR("%s: i2c_transfer(write) error, ret=%d", __func__, ret); + } + } + mutex_unlock(&i2c_rw_access); + + return ret; +} + +/************************************************************************ +* Name: fts_i2c_write_reg +* Brief: write register +* Input: i2c info, reg address, reg value +* Output: no +* Return: fail <0 +***********************************************************************/ +int fts_i2c_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue) +{ + u8 buf[2] = {0}; + + buf[0] = regaddr; + buf[1] = regvalue; + return fts_i2c_write(client, buf, sizeof(buf)); +} +/************************************************************************ +* Name: fts_i2c_read_reg +* Brief: read register +* Input: i2c info, reg address, reg value +* Output: get reg value +* Return: fail <0 +***********************************************************************/ +int fts_i2c_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue) +{ + return fts_i2c_read(client, ®addr, 1, regvalue, 1); +} + +/************************************************************************ +* Name: fts_i2c_init +* Brief: fts i2c init +* Input: +* Output: +* Return: +***********************************************************************/ +int fts_i2c_init(void) +{ + FTS_FUNC_ENTER(); + + FTS_FUNC_EXIT(); + return 0; +} +/************************************************************************ +* Name: fts_i2c_exit +* Brief: fts i2c exit +* Input: +* Output: +* Return: +***********************************************************************/ +int fts_i2c_exit(void) +{ + FTS_FUNC_ENTER(); + + FTS_FUNC_EXIT(); + return 0; +} + diff --git a/drivers/input/touchscreen/ft8716/focaltech_point_report_check.c b/drivers/input/touchscreen/ft8716/focaltech_point_report_check.c new file mode 100644 index 0000000000000..9fa56ce5ae07f --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_point_report_check.c @@ -0,0 +1,157 @@ +/* + * + * FocalTech TouchScreen driver. + * + * Copyright (c) 2010-2016, FocalTech Systems, Ltd., all rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/***************************************************************************** +* +* File Name: focaltech_point_report_check.c +* +* Author: WangTao +* +* Created: 2016-11-16 +* +* Abstract: point report check function +* +* Version: v1.0 +* +* Revision History: +* v1.0: +* First release. By WangTao 2016-11-16 +*****************************************************************************/ + +/***************************************************************************** +* Included header files +*****************************************************************************/ +#include "focaltech_core.h" + +#if FTS_POINT_REPORT_CHECK_EN +/***************************************************************************** +* Private constant and macro definitions using #define +*****************************************************************************/ +#define POINT_REPORT_CHECK_WAIT_TIME 200 + +/***************************************************************************** +* Private enumerations, structures and unions using typedef +*****************************************************************************/ + +/***************************************************************************** +* Static variables +*****************************************************************************/ +static struct delayed_work fts_point_report_check_work; +static struct workqueue_struct *fts_point_report_check_workqueue; + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ + +/***************************************************************************** +* Static function prototypes +*****************************************************************************/ + +/***************************************************************************** +* functions body +*****************************************************************************/ + + +/***************************************************************************** +* Name: fts_point_report_check_func +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static void fts_point_report_check_func(struct work_struct *work) +{ +int i; +#if FTS_MT_PROTOCOL_B_EN + unsigned int finger_count = 0; + + FTS_FUNC_ENTER(); + + for (finger_count = 0; finger_count < FTS_MAX_POINTS; finger_count++) { + input_mt_slot(fts_input_dev, finger_count); + input_mt_report_slot_state(fts_input_dev, MT_TOOL_FINGER, false); + } +#else + input_mt_sync(fts_input_dev); +#endif + if (fts_wq_data->pdata->have_key) { + printk("point_num 1 = %d\n", (fts_wq_data->event).point_num); + + FTS_DEBUG("Keys All Up!"); + for (i = 0; i < fts_wq_data->pdata->key_number; i++) { + input_report_key(fts_wq_data->input_dev, fts_wq_data->pdata->keys[i], 0); + } + + } + input_report_key(fts_input_dev, BTN_TOUCH, 0); + input_sync(fts_input_dev); + + + + FTS_FUNC_EXIT(); +} + +void fts_point_report_check_queue_work(void) +{ + + cancel_delayed_work(&fts_point_report_check_work); + queue_delayed_work(fts_point_report_check_workqueue, &fts_point_report_check_work, msecs_to_jiffies(POINT_REPORT_CHECK_WAIT_TIME)); + +} + +/***************************************************************************** +* Name: fts_point_report_check_init +* Brief: +* Input: +* Output: +* Return: < 0: Fail to create esd check queue +*****************************************************************************/ +int fts_point_report_check_init(void) +{ + FTS_FUNC_ENTER(); + + INIT_DELAYED_WORK(&fts_point_report_check_work, fts_point_report_check_func); + fts_point_report_check_workqueue = create_workqueue("fts_point_report_check_func_wq"); + if (fts_point_report_check_workqueue == NULL) { + FTS_ERROR("[POINT_REPORT]: Failed to create fts_point_report_check_workqueue!!"); + } else { + FTS_DEBUG("[POINT_REPORT]: Success to create fts_point_report_check_workqueue!!"); + } + + FTS_FUNC_EXIT(); + + return 0; +} + +/***************************************************************************** +* Name: fts_point_report_check_exit +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +int fts_point_report_check_exit(void) +{ + FTS_FUNC_ENTER(); + + destroy_workqueue(fts_point_report_check_workqueue); + + FTS_FUNC_EXIT(); + return 0; +} +#endif /* FTS_POINT_REPORT_CHECK_EN */ + diff --git a/drivers/input/touchscreen/ft8716/focaltech_sensor.c b/drivers/input/touchscreen/ft8716/focaltech_sensor.c new file mode 100644 index 0000000000000..a6e0e1f95622d --- /dev/null +++ b/drivers/input/touchscreen/ft8716/focaltech_sensor.c @@ -0,0 +1,313 @@ +/* + * + * FocalTech TouchScreen driver. + * + * Copyright (c) 2010-2016, FocalTech Systems, Ltd., all rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/***************************************************************************** +* +* File Name: focaltech_esdcheck.c +* +* Author: Focaltech Driver Team +* +* Created: 2016-08-03 +* +* Abstract: Sensor +* +* Version: v1.0 +* +* Revision History: +* v1.0: +* First release. By luougojin 2016-08-03 +*****************************************************************************/ + +/***************************************************************************** +* Included header files +*****************************************************************************/ +#include "focaltech_core.h" + +#if FTS_PSENSOR_EN +/***************************************************************************** +* Private constant and macro definitions using #define +*****************************************************************************/ +/* psensor register address*/ +#define FTS_REG_PSENSOR_ENABLE 0xB0 +#define FTS_REG_PSENSOR_STATUS 0x01 + +/* psensor register bits*/ +#define FTS_PSENSOR_ENABLE_MASK 0x01 +#define FTS_PSENSOR_STATUS_NEAR 0xC0 +#define FTS_PSENSOR_STATUS_FAR 0xE0 +#define FTS_PSENSOR_FAR_TO_NEAR 0 +#define FTS_PSENSOR_NEAR_TO_FAR 1 +#define FTS_PSENSOR_ORIGINAL_STATE_FAR 1 +#define FTS_PSENSOR_WAKEUP_TIMEOUT 500 + +/***************************************************************************** +* Static variables +*****************************************************************************/ +static struct sensors_classdev __maybe_unused sensors_proximity_cdev = { + .name = "fts-proximity", + .vendor = "FocalTech", + .version = 1, + .handle = SENSORS_PROXIMITY_HANDLE, + .type = SENSOR_TYPE_PROXIMITY, + .max_range = "5.0", + .resolution = "5.0", + .sensor_power = "0.1", + .min_delay = 0, + .fifo_reserved_event_count = 0, + .fifo_max_event_count = 0, + .enabled = 0, + .delay_msec = 200, + .sensors_enable = NULL, + .sensors_poll_delay = NULL, +}; + +/***************************************************************************** +* functions body +*****************************************************************************/ +/***************************************************************************** +* Name: fts_psensor_support_enabled +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static inline bool fts_psensor_support_enabled(void) +{ + /*return config_enabled(CONFIG_TOUCHSCREEN_FTS_PSENSOR);*/ + return FTS_PSENSOR_EN; +} + +/***************************************************************************** +* Name: fts_psensor_enable +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static void fts_psensor_enable(struct fts_ts_data *data, int enable) +{ + u8 state; + int ret = -1; + + if (data->client == NULL) + return; + + fts_i2c_read_reg(data->client, FTS_REG_PSENSOR_ENABLE, &state); + if (enable) + state |= FTS_PSENSOR_ENABLE_MASK; + else + state &= ~FTS_PSENSOR_ENABLE_MASK; + + ret = fts_i2c_write_reg(data->client, FTS_REG_PSENSOR_ENABLE, state); + if (ret < 0) + FTS_ERROR("write psensor switch command failed"); + return; +} + +/***************************************************************************** +* Name: fts_psensor_enable_set +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_psensor_enable_set(struct sensors_classdev *sensors_cdev, + unsigned int enable) +{ + struct fts_psensor_platform_data *psensor_pdata = + container_of(sensors_cdev, + struct fts_psensor_platform_data, ps_cdev); + struct fts_ts_data *data = psensor_pdata->data; + struct input_dev *input_dev = data->psensor_pdata->input_psensor_dev; + + mutex_lock(&input_dev->mutex); + fts_psensor_enable(data, enable); + psensor_pdata->tp_psensor_data = FTS_PSENSOR_ORIGINAL_STATE_FAR; + if (enable) + psensor_pdata->tp_psensor_opened = 1; + else + psensor_pdata->tp_psensor_opened = 0; + mutex_unlock(&input_dev->mutex); + return enable; +} + +/***************************************************************************** +* Name: fts_read_tp_psensor_data +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_read_tp_psensor_data(struct fts_ts_data *data) +{ + u8 psensor_status; + char tmp; + int ret = 1; + + fts_i2c_read_reg(data->client, + FTS_REG_PSENSOR_STATUS, &psensor_status); + + tmp = data->psensor_pdata->tp_psensor_data; + if (psensor_status == FTS_PSENSOR_STATUS_NEAR) + data->psensor_pdata->tp_psensor_data = + FTS_PSENSOR_FAR_TO_NEAR; + else if (psensor_status == FTS_PSENSOR_STATUS_FAR) + data->psensor_pdata->tp_psensor_data = + FTS_PSENSOR_NEAR_TO_FAR; + + if (tmp != data->psensor_pdata->tp_psensor_data) { + FTS_ERROR("%s sensor data changed", __func__); + ret = 0; + } + return ret; +} + + +int fts_sensor_read_data(struct fts_ts_data *data) +{ + int ret = 0; + if (fts_psensor_support_enabled() && data->psensor_pdata->tp_psensor_opened) { + ret = fts_read_tp_psensor_data(data); + if (!ret) { + if (data->suspended) { + pm_wakeup_event(&data->client->dev, FTS_PSENSOR_WAKEUP_TIMEOUT); + } + input_report_abs(data->psensor_pdata->input_psensor_dev, + ABS_DISTANCE, + data->psensor_pdata->tp_psensor_data); + input_sync(data->psensor_pdata->input_psensor_dev); + } + return 1; + } + return 0; +} + +int fts_sensor_suspend(struct fts_ts_data *data) +{ + int ret = 0; + + if (fts_psensor_support_enabled() && + device_may_wakeup(&data->client->dev) && + data->psensor_pdata->tp_psensor_opened) { + ret = enable_irq_wake(data->client->irq); + if (ret != 0) { + FTS_ERROR("%s: set_irq_wake failed", __func__); + } + data->suspended = true; + return 1; + } + + return 0; +} + + +int fts_sensor_resume(struct fts_ts_data *data) +{ + int ret = 0; + + if (fts_psensor_support_enabled() && + device_may_wakeup(&data->client->dev) && data->psensor_pdata->tp_psensor_opened) { + ret = disable_irq_wake(data->client->irq); + if (ret) { + FTS_ERROR("%s: disable_irq_wake failed", __func__); + } + data->suspended = false; + return 1; + } + + return 0; +} + + +int fts_sensor_init(struct fts_ts_data *data) +{ + struct fts_psensor_platform_data *psensor_pdata; + struct input_dev *psensor_input_dev; + int err; + + if (fts_psensor_support_enabled()) { + device_init_wakeup(&data->client->dev, 1); + psensor_pdata = devm_kzalloc(&data->client->dev, + sizeof(struct fts_psensor_platform_data), + GFP_KERNEL); + if (!psensor_pdata) { + FTS_ERROR("Failed to allocate memory"); + goto irq_free; + } + data->psensor_pdata = psensor_pdata; + + psensor_input_dev = input_allocate_device(); + if (!psensor_input_dev) { + FTS_ERROR("Failed to allocate device"); + goto free_psensor_pdata; + } + + __set_bit(EV_ABS, psensor_input_dev->evbit); + input_set_abs_params(psensor_input_dev, ABS_DISTANCE, 0, 1, 0, 0); + psensor_input_dev->name = "proximity"; + psensor_input_dev->id.bustype = BUS_I2C; + psensor_input_dev->dev.parent = &data->client->dev; + data->psensor_pdata->input_psensor_dev = psensor_input_dev; + + err = input_register_device(psensor_input_dev); + if (err) { + FTS_ERROR("Unable to register device, err=%d", err); + goto free_psensor_input_dev; + } + + psensor_pdata->ps_cdev = sensors_proximity_cdev; + psensor_pdata->ps_cdev.sensors_enable = fts_psensor_enable_set; + psensor_pdata->data = data; + + err = sensors_classdev_register(&data->client->dev, &psensor_pdata->ps_cdev); + if (err) { + goto unregister_psensor_input_device; + } + } + + return 0; +unregister_psensor_input_device: + if (fts_psensor_support_enabled()) + input_unregister_device(data->psensor_pdata->input_psensor_dev); +free_psensor_input_dev: + if (fts_psensor_support_enabled()) + input_free_device(data->psensor_pdata->input_psensor_dev); +free_psensor_pdata: + if (fts_psensor_support_enabled()) { + devm_kfree(&data->client->dev, psensor_pdata); + data->psensor_pdata = NULL; + } +irq_free: + if (fts_psensor_support_enabled()) + device_init_wakeup(&data->client->dev, 0); + free_irq(data->client->irq, data); + + return 1; +} + +int fts_sensor_remove(struct fts_ts_data *data) +{ + if (fts_psensor_support_enabled()) { + device_init_wakeup(&data->client->dev, 0); + sensors_classdev_unregister(&data->psensor_pdata->ps_cdev); + input_unregister_device(data->psensor_pdata->input_psensor_dev); + devm_kfree(&data->client->dev, data->psensor_pdata); + data->psensor_pdata = NULL; + } + return 0; +} +#endif /* FTS_PSENSOR_EN */ diff --git a/drivers/input/touchscreen/ft8716/include/firmware/FT8716_app_sample.i b/drivers/input/touchscreen/ft8716/include/firmware/FT8716_app_sample.i new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/drivers/input/touchscreen/ft8716/include/firmware/HQ_D2_XIAOMI_FT8716_XIAPU_BIEL0X3b_Black_V09_D01_20170809_app.i b/drivers/input/touchscreen/ft8716/include/firmware/HQ_D2_XIAOMI_FT8716_XIAPU_BIEL0X3b_Black_V09_D01_20170809_app.i new file mode 100644 index 0000000000000..694bd14e57d37 --- /dev/null +++ b/drivers/input/touchscreen/ft8716/include/firmware/HQ_D2_XIAOMI_FT8716_XIAPU_BIEL0X3b_Black_V09_D01_20170809_app.i @@ -0,0 +1,3555 @@ +0x2, 0x23,0x8a,0x2, 0xcb,0x98,0x1b,0xa, 0x30,0x22,0x22,0x2, 0x0, 0x19,0x0, 0x1, +0x1, 0x0, 0x22,0x2, 0xcb,0xe0,0xeb,0xaa,0x8, 0x32,0xff,0x2, 0x73,0x89,0x2, 0x41, +0xd4,0xff,0xff,0x2, 0x28,0x8d,0xb2,0x87,0x22,0xff,0xff,0x2, 0x77,0xfa,0xca,0x3b, +0x7d,0x72,0x7d,0x63,0x7d,0x27,0x12,0x6, 0x48,0x7d,0x36,0x7d,0x27,0x12,0x6, 0xc5, +0xda,0x3b,0x22,0x2, 0x78,0x26,0x7f,0x71,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x4, 0x7e, +0x6f,0x73,0x4d,0x79,0x36,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x6f,0x73,0x4d,0x79, +0x36,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x6f,0x73,0x4d,0x79,0x36,0x0, 0x8, 0x7e, +0x7b,0xa0,0x7c,0x6a,0x6c,0x77,0x7e,0x6f,0x73,0x4d,0x79,0x36,0x0, 0xe, 0x7c,0x4b, +0x6c,0x55,0xe5,0x26,0xa, 0x3b,0x4d,0x32,0x7e,0x2f,0x73,0x4d,0x79,0x32,0x0, 0x10, +0x29,0x77,0x0, 0x2, 0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x29,0x57, +0x0, 0x4, 0x7c,0x46,0x4c,0x57,0x7e,0x2f,0x73,0x4d,0x2e,0x54,0x0, 0xe, 0xb, 0x2a, +0x30,0x4d,0x32,0x1b,0x2a,0x30,0x29,0x77,0x0, 0x1, 0x7c,0x47,0x6c,0x55,0x29,0x77, +0x0, 0x3, 0x7c,0x64,0x7e,0x2f,0x73,0x4d,0x79,0x32,0x0, 0xa, 0x7e,0xb, 0x70,0x7c, +0x47,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e,0xf, 0x73,0x4d,0x79,0x30,0x0, +0xc, 0x6d,0x11,0x7e,0x1f,0x73,0x4d,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x30,0x12,0xa, +0x5e,0xa9,0xc6,0xcb,0x22,0x1, 0x2, 0x4, 0x8, 0x10,0x20,0x40,0x80,0x2, 0x5f,0xa5, +0xde,0x28,0x21,0xd7,0xd, 0x68,0xf2,0x97,0xf6,0x2a,0x9, 0xd5,0xe9,0x16,0x9, 0xf6, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x87,0xa6, +0xca,0x3b,0x7f,0x30,0x7e,0x3b,0xb0,0xf5,0x2c,0x29,0xb3,0x0, 0x1, 0xbe,0xb1,0x2c, +0x28,0x2, 0xf5,0x2c,0x69,0x13,0x0, 0x6, 0x6d,0x0, 0x7e,0x34,0x0, 0xf2,0x74,0xff, +0x12,0x24,0x39,0x7f,0x3, 0x12,0xa, 0x6, 0xa9,0xd6,0xcb,0x75,0x2a,0x0, 0x80,0x33, +0x75,0x2b,0x0, 0x80,0x23,0x7e,0x11,0x2a,0x74,0xb, 0xac,0x1b,0xe5,0x2b,0xa, 0x1b, +0x2d,0x1, 0x3e,0x4, 0x69,0x13,0x0, 0x6, 0x2d,0x10,0x6d,0x0, 0xb, 0xa, 0x30,0x6e, +0x34,0xff,0xff,0x1b,0xa, 0x30,0x5, 0x2b,0x29,0x73,0x0, 0x1, 0xbe,0x71,0x2b,0x38, +0xd4,0x5, 0x2a,0x7e,0x3b,0x70,0xbe,0x71,0x2a,0x38,0xc5,0x69,0x33,0x0, 0x6, 0x7e, +0xf, 0x73,0x4d,0x79,0x30,0x0, 0x4, 0xe5,0x2c,0xa, 0x2b,0x7d,0x32,0x7c,0x67,0x6c, +0x77,0x2d,0x32,0x7e,0xf, 0x73,0x4d,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x73, +0x4d,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xd0,0x12,0xa, 0x5e,0x75,0x2a,0x0, 0xe5,0x2a, +0xbe,0xb0,0x4, 0x50,0x17,0x7e,0xa1,0x2a,0x74,0x4, 0xa4,0x7e,0x1f,0x73,0x4d,0x69, +0x11,0x0, 0x26,0x60,0x44,0x1e,0x14,0x14,0x78,0xfb,0x80,0x3d,0xe5,0x2a,0xbe,0xb0, +0x8, 0x50,0x1b,0xe5,0x2a,0xa, 0x5b,0x1b,0x56,0x3e,0x54,0x3e,0x54,0x7e,0x1f,0x73, +0x4d,0x69,0x11,0x0, 0x28,0x60,0x22,0x1e,0x14,0x14,0x78,0xfb,0x80,0x1b,0xe5,0x2a, +0xa, 0x5b,0x9e,0x54,0x0, 0x8, 0x3e,0x54,0x3e,0x54,0x7e,0x1f,0x73,0x4d,0x69,0x11, +0x0, 0x2a,0x60,0x5, 0x1e,0x14,0x14,0x78,0xfb,0x5e,0x14,0x0, 0xf, 0x7e,0xa1,0x2a, +0x74,0x2, 0xa4,0x69,0x33,0x0, 0x6, 0x2d,0x35,0x6d,0x22,0x1b,0x1a,0x10,0x5, 0x2a, +0xe5,0x2a,0xbe,0xb0,0xb, 0x40,0x87,0xa9,0xc6,0xcb,0xda,0x3b,0x22,0x6d,0x33,0x7e, +0xf, 0x73,0x51,0x79,0x30,0x0, 0x12,0x7e,0xf, 0x73,0x51,0x2e,0x14,0x0, 0x14,0xb, +0xa, 0x30,0x5e,0x60,0x7f,0x1b,0xa, 0x30,0xe5,0x3b,0x54,0x1f,0xa, 0x2b,0x7e,0xf, +0x73,0x51,0x2e,0x14,0x0, 0x12,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0xe5,0x3c, +0x54,0x1, 0xa, 0x2b,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x7e,0xf, +0x73,0x51,0x2e,0x14,0x0, 0x12,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0xe5,0x3d, +0x54,0x3, 0xa, 0x2b,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24, +0x7e,0xf, 0x73,0x51,0x2e,0x14,0x0, 0x12,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30, +0x7e,0x35,0x39,0xbe,0x34,0x0, 0x2, 0x78,0x63,0x7e,0xf, 0x73,0x51,0x2e,0x14,0x0, +0x14,0xb, 0xa, 0x30,0x4e,0x60,0x80,0x1b,0xa, 0x30,0xe5,0x3e,0x54,0x1f,0x7c,0x4b, +0x6c,0x55,0x7e,0xf, 0x73,0x51,0x2e,0x14,0x0, 0x12,0xb, 0xa, 0x30,0x4d,0x32,0x1b, +0xa, 0x30,0xe5,0x3f,0x54,0x1, 0xa, 0x5b,0xc4,0x23,0x54,0xe0,0x7c,0xab,0xe4,0x7e, +0xf, 0x73,0x51,0x2e,0x14,0x0, 0x12,0xb, 0xa, 0x30,0x4d,0x35,0x1b,0xa, 0x30,0xe5, +0x40,0x54,0x3, 0xa, 0x5b,0x3, 0x3, 0x54,0xc0,0x7c,0xab,0xe4,0x7e,0xf, 0x73,0x51, +0x2e,0x14,0x0, 0x12,0xb, 0xa, 0x30,0x4d,0x35,0x1b,0xa, 0x30,0x22,0x7f,0x21,0xa9, +0xd6,0xcb,0x69,0x30,0x0, 0x4, 0x7e,0x7f,0x73,0x4d,0x79,0x37,0x0, 0x4, 0x69,0x30, +0x0, 0x8, 0x7e,0x7f,0x73,0x4d,0x79,0x37,0x0, 0x6, 0x69,0x30,0x0, 0x6, 0x7e,0x7f, +0x73,0x4d,0x79,0x37,0x0, 0x8, 0x29,0x70,0x0, 0x1, 0x7c,0x47,0x6c,0x55,0x7e,0xb, +0x70,0xa, 0x37,0x2d,0x32,0x7e,0x7f,0x73,0x4d,0x79,0x37,0x0, 0xc, 0x29,0x70,0x0, +0x2, 0xa, 0x37,0x1b,0x34,0x7e,0x7f,0x73,0x4d,0x79,0x37,0x0, 0xa, 0x69,0x30,0x0, +0xa, 0x7e,0x7f,0x73,0x4d,0x79,0x37,0x0, 0xe, 0x69,0x30,0x0, 0xc, 0x7e,0x7f,0x73, +0x4d,0x79,0x37,0x0, 0x10,0x69,0x30,0x0, 0xe, 0x7e,0x7f,0x73,0x4d,0x79,0x37,0x0, +0x12,0x69,0x30,0x0, 0x10,0x7e,0x7f,0x73,0x4d,0x79,0x37,0x0, 0x30,0x29,0x70,0x0, +0x3, 0x7c,0x27,0x6c,0x33,0x7e,0x1f,0x73,0x4d,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xa0, +0x12,0xa, 0x5e,0x7e,0x1f,0x73,0x4d,0x69,0x11,0x0, 0x1a,0x7a,0x2b,0x30,0x69,0x11, +0x0, 0x1c,0x39,0x32,0x0, 0x1, 0x69,0x11,0x0, 0x16,0x79,0x12,0x0, 0x2, 0x69,0x11, +0x0, 0x18,0x79,0x12,0x0, 0x4, 0x69,0x11,0x0, 0x22,0x79,0x12,0x0, 0x6, 0x69,0x11, +0x0, 0x24,0x79,0x12,0x0, 0x8, 0x69,0x11,0x0, 0x1e,0x79,0x12,0x0, 0xa, 0x69,0x31, +0x0, 0x20,0x79,0x32,0x0, 0xc, 0xa9,0xc6,0xcb,0x22,0xca,0x3b,0x7a,0x25,0x4d,0x7f, +0x30,0x7a,0x35,0x4b,0xa2,0xac,0x92,0x8, 0xc2,0xac,0x7e,0x1f,0x73,0x51,0x69,0x31, +0x0, 0x4, 0x5e,0x34,0x10,0x0, 0x7a,0x37,0x66,0x49,0xc2,0x9, 0x12,0xc, 0x17,0xa2, +0x8, 0x92,0xac,0xa9,0xd3,0xcb,0xa9,0xd5,0xcb,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x73, +0x20,0x79,0x30,0x0, 0x6, 0x7e,0xf, 0x73,0x20,0x69,0x30,0x0, 0x6, 0x4d,0x33,0x78, +0xf4,0x7e,0x35,0x4b,0x2e,0x34,0x80,0x0, 0x1b,0xa, 0x30,0x7e,0x1f,0x73,0x20,0x69, +0x31,0x0, 0x8, 0x4d,0x33,0x68,0xf4,0x6d,0x33,0x80,0x20,0x7d,0x23,0x3e,0x24,0x7f, +0x3, 0x2d,0x12,0xb, 0xa, 0x20,0x7e,0xf, 0x73,0x20,0x1b,0xa, 0x20,0x7e,0xf, 0x73, +0x20,0x69,0x20,0x0, 0x8, 0x4d,0x22,0x68,0xf4,0xb, 0x34,0xbe,0x35,0x4d,0x40,0xdb, +0xa9,0xc5,0xcb,0xa9,0xc3,0xcb,0x7e,0x37,0x66,0x49,0x2e,0x34,0xff,0xff,0x92,0x9, +0x12,0xc, 0x17,0xda,0x3b,0x22,0xca,0x3b,0x7a,0x25,0x4d,0x7f,0x30,0x7a,0x35,0x4b, +0xa2,0xac,0x92,0x8, 0xc2,0xac,0x7e,0x1f,0x73,0x51,0x69,0x31,0x0, 0x4, 0x5e,0x34, +0x10,0x0, 0x7a,0x37,0x66,0x49,0xc2,0x9, 0x12,0xc, 0x17,0xa2,0x8, 0x92,0xac,0xd2, +0xcd,0xa9,0xd5,0xcb,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x73,0x24,0x79,0x30,0x0, 0x6, +0x7e,0xf, 0x73,0x24,0x69,0x30,0x0, 0x6, 0x4d,0x33,0x78,0xf4,0x7e,0x35,0x4b,0x2e, +0x34,0x80,0x0, 0x1b,0xa, 0x30,0x7e,0x1f,0x73,0x24,0x69,0x31,0x0, 0x8, 0x4d,0x33, +0x68,0xf4,0x6d,0x33,0x80,0x20,0x7d,0x23,0x3e,0x24,0x7f,0x3, 0x2d,0x12,0xb, 0xa, +0x20,0x7e,0xf, 0x73,0x24,0x1b,0xa, 0x20,0x7e,0xf, 0x73,0x24,0x69,0x20,0x0, 0x8, +0x4d,0x22,0x68,0xf4,0xb, 0x34,0xbe,0x35,0x4d,0x40,0xdb,0xa9,0xc5,0xcb,0xc2,0xcd, +0x7e,0x37,0x66,0x49,0x2e,0x34,0xff,0xff,0x92,0x9, 0x12,0xc, 0x17,0xda,0x3b,0x22, +0xca,0x79,0x7c,0xab,0x6d,0x77,0x7e,0xf, 0x73,0x51,0x69,0x30,0x0, 0x6, 0x5e,0x34, +0x0, 0x2, 0x68,0x18,0x2e,0x14,0x0, 0xe, 0xb, 0xa, 0x30,0x5e,0x70,0xfb,0x1b,0xa, +0x30,0x74,0x3, 0x7a,0xb3,0x73,0x8, 0x75,0x1b,0x3, 0x80,0x3, 0xe4,0x80,0x5a,0x4c, +0xaa,0x68,0x54,0x80,0x44,0x7e,0x1f,0x73,0x51,0x69,0x31,0x0, 0x6, 0x5e,0x34,0x0, +0x1, 0x78,0xa, 0xe4,0x7a,0xb3,0x73,0x8, 0x75,0x1b,0x0, 0x80,0x3c,0x7e,0x34,0x0, +0x1, 0x12,0x71,0x76,0xb, 0x74,0xbe,0x74,0x3, 0xe8,0x28,0x1d,0x7e,0xf, 0x73,0x51, +0x2e,0x14,0x0, 0xe, 0xb, 0xa, 0x30,0x4e,0x70,0x4, 0x1b,0xa, 0x30,0x74,0x2, 0x7a, +0xb3,0x73,0x8, 0x75,0x1b,0x2, 0xe4,0x80,0x10,0x7e,0x1f,0x73,0x51,0x69,0x31,0x0, +0xe, 0x5e,0x34,0x0, 0x3, 0x78,0xae,0x74,0x1, 0xda,0x79,0x22,0xca,0x79,0x7c,0xab, +0x6d,0x77,0x7e,0xf, 0x73,0x51,0x69,0x30,0x0, 0x6, 0x5e,0x34,0x0, 0x2, 0x68,0x18, +0x2e,0x14,0x0, 0xe, 0xb, 0xa, 0x30,0x4e,0x70,0x4, 0x1b,0xa, 0x30,0x74,0x2, 0x7a, +0xb3,0x73,0x8, 0x75,0x1b,0x2, 0x80,0x3, 0xe4,0x80,0x5a,0x4c,0xaa,0x68,0x54,0x80, +0x44,0x7e,0x1f,0x73,0x51,0x69,0x31,0x0, 0x6, 0x5e,0x34,0x0, 0x1, 0x78,0xa, 0xe4, +0x7a,0xb3,0x73,0x8, 0x75,0x1b,0x0, 0x80,0x3c,0x7e,0x34,0x0, 0x1, 0x12,0x71,0x76, +0xb, 0x74,0xbe,0x74,0x3, 0xe8,0x28,0x1d,0x7e,0xf, 0x73,0x51,0x2e,0x14,0x0, 0xe, +0xb, 0xa, 0x30,0x5e,0x70,0xfb,0x1b,0xa, 0x30,0x74,0x3, 0x7a,0xb3,0x73,0x8, 0x75, +0x1b,0x3, 0xe4,0x80,0x10,0x7e,0x1f,0x73,0x51,0x69,0x31,0x0, 0xe, 0x5e,0x34,0x0, +0x8, 0x68,0xae,0x74,0x1, 0xda,0x79,0x22,0xca,0x3b,0x7d,0x72,0x7d,0x63,0xa2,0xac, +0x92,0x3, 0xc2,0xac,0x7e,0x1f,0x73,0x51,0x69,0x31,0x0, 0x4, 0x5e,0x34,0x10,0x0, +0x7a,0x37,0x61,0xcf,0xc2,0x9, 0x12,0xc, 0x17,0xa2,0x3, 0x92,0xac,0xa9,0xd3,0xcb, +0xa9,0xd5,0xcb,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x73,0x20,0x79,0x30,0x0, 0x6, 0x7e, +0xf, 0x73,0x20,0x69,0x30,0x0, 0x6, 0x4d,0x33,0x78,0xf4,0x7d,0x36,0x2e,0x34,0x80, +0x0, 0x1b,0xa, 0x30,0x7e,0x1f,0x73,0x20,0x69,0x11,0x0, 0x8, 0x4d,0x11,0x68,0xf4, +0x1b,0x1a,0x70,0x7e,0x1f,0x73,0x20,0x69,0x31,0x0, 0x8, 0x4d,0x33,0x68,0xf4,0xa9, +0xc5,0xcb,0xa9,0xc3,0xcb,0x7e,0x37,0x61,0xcf,0x2e,0x34,0xff,0xff,0x92,0x9, 0x12, +0xc, 0x17,0xda,0x3b,0x22,0xca,0x3b,0x7d,0x72,0x7d,0x63,0xa2,0xac,0x92,0x3, 0xc2, +0xac,0x7e,0x1f,0x73,0x51,0x69,0x31,0x0, 0x4, 0x5e,0x34,0x10,0x0, 0x7a,0x37,0x61, +0xcf,0xc2,0x9, 0x12,0xc, 0x17,0xa2,0x3, 0x92,0xac,0xd2,0xcd,0xa9,0xd5,0xcb,0x7e, +0x34,0x0, 0x1, 0x7e,0xf, 0x73,0x24,0x79,0x30,0x0, 0x6, 0x7e,0xf, 0x73,0x24,0x69, +0x30,0x0, 0x6, 0x4d,0x33,0x78,0xf4,0x7d,0x36,0x2e,0x34,0x80,0x0, 0x1b,0xa, 0x30, +0x7e,0x1f,0x73,0x24,0x69,0x11,0x0, 0x8, 0x4d,0x11,0x68,0xf4,0x1b,0x1a,0x70,0x7e, +0x1f,0x73,0x24,0x69,0x31,0x0, 0x8, 0x4d,0x33,0x68,0xf4,0xa9,0xc5,0xcb,0xc2,0xcd, +0x7e,0x37,0x61,0xcf,0x2e,0x34,0xff,0xff,0x92,0x9, 0x12,0xc, 0x17,0xda,0x3b,0x22, +0xca,0x3b,0x7d,0x73,0xa2,0xac,0x92,0x0, 0xc2,0xac,0x7e,0x1f,0x73,0x51,0x69,0x61, +0x0, 0x4, 0x5e,0x64,0x10,0x0, 0xc2,0x9, 0x12,0xc, 0x17,0xa2,0x0, 0x92,0xac,0xa9, +0xd3,0xcb,0xa9,0xd5,0xcb,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x73,0x20,0x79,0x30,0x0, +0x6, 0x7e,0x1f,0x73,0x20,0x69,0x11,0x0, 0x6, 0x4d,0x11,0x78,0xf4,0x1b,0x1a,0x70, +0x7e,0xf, 0x73,0x20,0x69,0x30,0x0, 0x8, 0x4d,0x33,0x68,0xf4,0x6d,0x33,0x1b,0xa, +0x30,0x7e,0x1f,0x73,0x20,0x69,0x11,0x0, 0x8, 0x4d,0x11,0x68,0xf4,0x69,0x71,0x0, +0x2, 0xa9,0xc5,0xcb,0xa9,0xc3,0xcb,0x2e,0x64,0xff,0xff,0x92,0x9, 0x12,0xc, 0x17, +0x7d,0x37,0xda,0x3b,0x22,0x7e,0x8, 0x1, 0x5f,0x7e,0x34,0x0, 0x18,0xe4,0x12,0x24, +0x39,0xa9,0xd1,0xcb,0xd2,0xcc,0x7e,0x34,0x0, 0x4, 0x7e,0x8, 0x1, 0x5f,0x74,0xc, +0x12,0xa, 0xb5,0xa9,0xd1,0xcb,0xc2,0xcc,0x6c,0xaa,0x7e,0x70,0x2, 0xac,0x7a,0x7e, +0x8, 0x1, 0x5f,0x2d,0x13,0xb, 0xa, 0x20,0x7c,0x45,0x6c,0x55,0xb, 0xa, 0x30,0xa, +0x36,0x4d,0x32,0x1b,0xa, 0x30,0xb, 0xa0,0xbe,0xa0,0xc, 0x40,0xdd,0x22,0xff,0xff, +0xca,0x3b,0x7d,0x73,0xa2,0xac,0x92,0x0, 0xc2,0xac,0x7e,0x1f,0x73,0x51,0x69,0x61, +0x0, 0x4, 0x5e,0x64,0x10,0x0, 0xc2,0x9, 0x12,0xc, 0x17,0xa2,0x0, 0x92,0xac,0xd2, +0xcd,0xa9,0xd5,0xcb,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x73,0x24,0x79,0x30,0x0, 0x6, +0x7e,0x1f,0x73,0x24,0x69,0x11,0x0, 0x6, 0x4d,0x11,0x78,0xf4,0x1b,0x1a,0x70,0x7e, +0xf, 0x73,0x24,0x69,0x30,0x0, 0x8, 0x4d,0x33,0x68,0xf4,0x6d,0x33,0x1b,0xa, 0x30, +0x7e,0x1f,0x73,0x24,0x69,0x11,0x0, 0x8, 0x4d,0x11,0x68,0xf4,0x69,0x71,0x0, 0x2, +0xa9,0xc5,0xcb,0xc2,0xcd,0x2e,0x64,0xff,0xff,0x92,0x9, 0x12,0xc, 0x17,0x7d,0x37, +0xda,0x3b,0x22,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x6, 0x7e,0x2f,0x73,0x4d,0x79,0x32, +0x0, 0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x73,0x4d,0x79,0x32,0x0, 0x8, 0x29,0x70, +0x0, 0x2, 0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x3, 0xa, 0x37,0x2d,0x32,0x7e,0x2f, +0x73,0x4d,0x79,0x32,0x0, 0xc, 0x7e,0xb, 0x70,0x7c,0x47,0x29,0x70,0x0, 0x1, 0xa, +0x37,0x2d,0x32,0x7e,0x2f,0x73,0x4d,0x79,0x32,0x0, 0xa, 0x29,0x70,0x0, 0x4, 0xa, +0x37,0x7e,0x2f,0x73,0x4d,0x79,0x32,0x0, 0xe, 0x29,0xb0,0x0, 0x5, 0x54,0x1, 0x7c, +0x2b,0x6c,0x33,0x7e,0x1f,0x73,0x4d,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xc0,0x12,0xa, +0x5e,0xa9,0xc6,0xcb,0x22,0xa9,0xd6,0xcb,0xc2,0x2b,0x69,0x30,0x0, 0x4, 0x7e,0x2f, +0x73,0x4d,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f,0x73,0x4d,0x79,0x32, +0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x73,0x4d,0x79,0x32,0x0, 0x8, 0x7e,0xb, +0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x73, +0x4d,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e,0x2f,0x73,0x4d,0x79, +0x32,0x0, 0xe, 0x29,0xb0,0x0, 0x3, 0x54,0x1, 0xa, 0x5b,0x7c,0xab,0xe4,0x7e,0x1f, +0x73,0x4d,0x1b,0x1a,0x50,0x69,0x30,0x0, 0xa, 0x12,0xa, 0x5e,0xa9,0xc6,0xcb,0x22, +0xa9,0xd6,0xcb,0x69,0x20,0x0, 0x4, 0x7e,0x2f,0x73,0x4d,0x79,0x22,0x0, 0x4, 0x69, +0x20,0x0, 0x8, 0x7e,0x2f,0x73,0x4d,0x79,0x22,0x0, 0x8, 0x7e,0xb, 0x50,0xa, 0x55, +0x7c,0xab,0xe4,0x29,0x50,0x0, 0x1, 0xa, 0x25,0x2d,0x25,0x7e,0x2f,0x73,0x4d,0x79, +0x22,0x0, 0xc, 0x29,0x50,0x0, 0x2, 0xa, 0x25,0x7e,0xf, 0x73,0x4d,0x79,0x20,0x0, +0xe, 0x7e,0xf, 0x73,0x4d,0x79,0x30,0x0, 0xa, 0x6d,0x11,0x7e,0x1f,0x73,0x4d,0x1b, +0x1a,0x10,0x7e,0x34,0x0, 0x40,0x12,0xa, 0x5e,0xa9,0xc6,0xcb,0x22,0xca,0x3b,0x6c, +0xaa,0x7e,0x90,0x2, 0xac,0x9a,0x7f,0x70,0x2d,0xf4,0xb, 0x7a,0x40,0x5e,0x80,0x3, +0x1b,0x7a,0x40,0x7e,0x90,0x6, 0xac,0x9a,0x7c,0xb9,0x7f,0x71,0x60,0xd, 0x1e,0xf4, +0x1e,0xe4,0x50,0x4, 0x4e,0xf4,0x80,0x0, 0x14,0x78,0xf3,0x7d,0x4f,0x5e,0x44,0x0, +0x3f,0x7d,0x74,0x7c,0xef,0x6c,0xff,0x3e,0x74,0x3e,0x74,0x7e,0xd0,0x2, 0xac,0xda, +0x7f,0x60,0x2d,0xd6,0xb, 0x6a,0xf0,0x4d,0xf7,0x1b,0x6a,0xf0,0xb, 0xa0,0xbe,0xa0, +0x4, 0x40,0xae,0xda,0x3b,0x22,0x7f,0x10,0xa9,0xd6,0xcb,0x69,0x11,0x0, 0x2, 0x7e, +0x2f,0x73,0x4d,0x79,0x12,0x0, 0x4, 0x69,0x11,0x0, 0x4, 0x7e,0x2f,0x73,0x4d,0x79, +0x12,0x0, 0x6, 0x69,0x11,0x0, 0x6, 0x7e,0x2f,0x73,0x4d,0x79,0x12,0x0, 0x8, 0x7e, +0x1b,0x30,0xa, 0x3, 0x7e,0x14,0x1, 0x0, 0xad,0x10,0x29,0x71,0x0, 0x1, 0xa, 0x37, +0x2d,0x31,0x7e,0xf, 0x73,0x4d,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x73,0x4d, +0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x60,0x12,0xa, 0x5e,0xa9,0xc6,0xcb,0x22,0xa9,0xd7, +0xcb,0x7d,0x23,0x4e,0x50,0x1, 0x7e,0xf, 0x73,0x4d,0xb, 0xa, 0x30,0x4d,0x32,0x1b, +0xa, 0x30,0x80,0x1e,0x7e,0xf, 0x73,0x4d,0xb, 0xa, 0x30,0x7d,0x23,0x5e,0x24,0x0, +0x8, 0xbe,0x24,0x0, 0x8, 0x78,0xb, 0xa9,0xd7,0xcb,0x4e,0x70,0x4, 0x1b,0xa, 0x30, +0xd2,0x2b,0x7e,0xf, 0x73,0x4d,0xb, 0xa, 0x30,0x7d,0x23,0x5e,0x24,0x80,0x0, 0xbe, +0x24,0x80,0x0, 0x78,0xcf,0x4e,0x60,0x40,0x1b,0xa, 0x30,0x6d,0x11,0x7e,0x1f,0x73, +0x4d,0x1b,0x1a,0x10,0x22,0x7e,0x24,0x0, 0x1, 0x7e,0x7f,0x73,0x28,0x79,0x27,0x0, +0x6, 0x7e,0x7f,0x73,0x28,0x69,0x27,0x0, 0x6, 0x4d,0x22,0x78,0xf4,0x5e,0x60,0x7f, +0x1b,0x7a,0x30,0x7e,0x1f,0x73,0x28,0x69,0x31,0x0, 0x8, 0x4d,0x33,0x68,0xf4,0x6c, +0xaa,0x80,0x20,0x6d,0x44,0x7e,0x1f,0x73,0x28,0x1b,0x1a,0x40,0x7e,0x1f,0x73,0x28, +0x69,0x41,0x0, 0x8, 0x4d,0x44,0x68,0xf4,0x69,0x41,0x0, 0x2, 0x1b,0xa, 0x40,0xb, +0x15,0xb, 0xa0,0xbc,0xba,0x38,0xdc,0x22,0xca,0x79,0x7c,0xab,0x6c,0x99,0x80,0x2d, +0x7e,0xf0,0x2, 0xac,0xf9,0x7f,0x60,0x2d,0xd7,0xb, 0x6a,0xf0,0x5e,0xf4,0xfc,0x0, +0x1b,0x6a,0xf0,0x7f,0x71,0x2d,0xf7,0xb, 0x7a,0xe0,0x7e,0xf0,0x2, 0xac,0xf9,0x7f, +0x60,0x2d,0xd7,0xb, 0x6a,0xf0,0x4d,0xfe,0x1b,0x6a,0xf0,0xb, 0x90,0xbc,0xa9,0x38, +0xcf,0xda,0x79,0x22,0xb, 0x38,0x20,0x5e,0x50,0xc0,0x1b,0x38,0x20,0xb, 0xa, 0x20, +0x5e,0x40,0x7, 0x1b,0xa, 0x20,0xe5,0x2d,0xa, 0x5b,0xb, 0x38,0x20,0x4d,0x25,0x1b, +0x38,0x20,0xe5,0x2c,0xa, 0x3b,0x7d,0x23,0x7c,0x45,0x6c,0x55,0x3e,0x24,0x3e,0x24, +0x3e,0x24,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x22,0xa9,0xd6,0xcb,0x54,0x3f, +0x5e,0x70,0x1f,0x7e,0x14,0x0, 0x1, 0x7e,0x7f,0x73,0x4d,0x79,0x17,0x0, 0x2, 0x7c, +0x2b,0x6c,0x33,0xa, 0x37,0x2d,0x31,0x7e,0xf, 0x73,0x4d,0x79,0x30,0x0, 0x32,0x7e, +0xf, 0x73,0x4d,0x79,0x20,0x0, 0x14,0xa9,0xc6,0xcb,0x12,0x7, 0xb5,0x2, 0xd, 0x59, +0x30,0x22,0x31,0xa9,0xd2,0xea,0xa9,0xc2,0xea,0x6d,0x33,0x7e,0xf, 0x73,0x51,0x79, +0x30,0x0, 0x16,0x7e,0x34,0x1, 0x2c,0x7e,0xf, 0x73,0x51,0x79,0x30,0x0, 0x18,0xc2, +0x22,0x7e,0xf, 0x73,0x51,0x2e,0x14,0x0, 0x14,0xb, 0xa, 0x30,0x5e,0x70,0xfb,0x1b, +0xa, 0x30,0xc2,0x21,0x22,0xa2,0xac,0x92,0x8, 0x7e,0xf, 0x73,0x51,0xb, 0xa, 0x30, +0x5e,0x34,0x10,0x0, 0x68,0xb, 0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x60,0x10,0x1b,0xa, +0x30,0xc2,0xac,0x7e,0xf, 0x73,0x51,0xb, 0x16,0xb, 0xa, 0x30,0x4e,0x60,0x10,0x1b, +0xa, 0x30,0xa2,0x8, 0x92,0xac,0x22,0xa2,0xac,0x92,0xa, 0xc2,0xac,0x7e,0xf, 0x73, +0x51,0x30,0x9, 0xa, 0xb, 0x16,0xb, 0xa, 0x30,0x4e,0x60,0x10,0x80,0x8, 0xb, 0x16, +0xb, 0xa, 0x30,0x5e,0x60,0xef,0x1b,0xa, 0x30,0xa2,0xa, 0x92,0xac,0x22,0xb, 0xa, +0x30,0x5e,0x34,0xfc,0x7f,0x1b,0xa, 0x30,0xa, 0x2b,0x5e,0x24,0x0, 0x7, 0x3e,0x24, +0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0xb, 0xa, 0x30,0x4d, +0x32,0x1b,0xa, 0x30,0x22,0xa9,0xd7,0xca,0x7e,0x24,0x0, 0x1, 0x7e,0xf, 0x73,0x55, +0x1b,0xa, 0x20,0x7e,0x24,0x9, 0x60,0x7e,0xf, 0x73,0x55,0x79,0x20,0x0, 0x2, 0x7e, +0xf, 0x73,0x55,0x79,0x30,0x0, 0x4, 0x22,0xb, 0xa, 0x20,0x5e,0x24,0x80,0x1f,0x1b, +0xa, 0x20,0x7d,0x23,0x5e,0x40,0x3, 0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e, +0x24,0xb, 0xa, 0x30,0x2d,0x32,0x1b,0xa, 0x30,0x22,0xb, 0xa, 0x30,0x5e,0x60,0xc7, +0x1b,0xa, 0x30,0x54,0x7, 0xa, 0x3b,0x7d,0x23,0x7c,0x45,0x6c,0x55,0x3e,0x24,0x3e, +0x24,0x3e,0x24,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x22,0xca,0x3b,0x7d,0x72, +0x7a,0xd, 0x2c,0x7d,0x63,0x7e,0xd, 0x2c,0x7d,0x27,0x12,0x3, 0xfa,0x7d,0x36,0x7e, +0xd, 0x2c,0x7d,0x27,0x12,0x4, 0x96,0xda,0x3b,0x22,0xb, 0xa, 0x30,0x5e,0x60,0x9f, +0x1b,0xa, 0x30,0x54,0x3, 0xa, 0x5b,0xc4,0x23,0x54,0xe0,0x7c,0xab,0xe4,0xb, 0xa, +0x30,0x4d,0x35,0x1b,0xa, 0x30,0x22,0xb, 0xa, 0x30,0x5e,0x70,0xe7,0x1b,0xa, 0x30, +0x54,0x3, 0xa, 0x2b,0x3e,0x24,0x3e,0x24,0x3e,0x24,0xb, 0xa, 0x30,0x4d,0x32,0x1b, +0xa, 0x30,0x22,0x7c,0xa7,0xb, 0xa, 0x30,0x5e,0x60,0x40,0x60,0x3, 0x4e,0x60,0x80, +0x7c,0xba,0x54,0x3f,0x7c,0x4b,0x6c,0x55,0x4d,0x32,0x1b,0xa, 0x30,0x22,0xb, 0xa, +0x50,0x54,0xe0,0x1b,0xa, 0x50,0x7d,0x52,0x5e,0x54,0x0, 0x1f,0xb, 0xa, 0x20,0x4d, +0x25,0x1b,0xa, 0x20,0x79,0x30,0x0, 0x2, 0x22,0x7e,0xb3,0x1, 0x6f,0xb4,0xe7,0x12, +0x7e,0xb3,0x1, 0x70,0xb4,0x16,0xb, 0x7e,0xb3,0x1, 0x6c,0x54,0x1, 0xb4,0x1, 0x2, +0x80,0xfe,0x22,0xb, 0xa, 0x30,0x5e,0x60,0xf, 0x1b,0xa, 0x30,0xa, 0x5b,0xc4,0x54, +0xf0,0x7c,0xab,0xe4,0xb, 0xa, 0x30,0x4d,0x35,0x1b,0xa, 0x30,0x22,0xb, 0xa, 0x30, +0x5e,0x60,0xfc,0x1b,0xa, 0x30,0x54,0x3, 0x7c,0x4b,0x6c,0x55,0xb, 0xa, 0x30,0x4d, +0x32,0x1b,0xa, 0x30,0x22,0xb, 0xa, 0x20,0x5e,0x50,0xfc,0x1b,0xa, 0x20,0x7d,0x23, +0x5e,0x24,0x0, 0x3, 0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x22,0xd2,0x22,0xd2, +0x21,0x7e,0xf, 0x73,0x51,0x2e,0x14,0x0, 0x14,0xb, 0xa, 0x30,0x4e,0x70,0x2, 0x1b, +0xa, 0x30,0x22,0x7d,0x23,0xb, 0xa, 0x30,0x5e,0x34,0xf8,0x0, 0x1b,0xa, 0x30,0x4d, +0x32,0x1b,0xa, 0x30,0x22,0x7d,0x23,0xb, 0xa, 0x30,0x5e,0x34,0xf8,0x0, 0x1b,0xa, +0x30,0x4d,0x32,0x1b,0xa, 0x30,0x22,0xb, 0xa, 0x30,0x5e,0x70,0x3, 0x70,0x3, 0x4e, +0x70,0xc, 0x1b,0xa, 0x30,0x22,0x2, 0xd, 0x14,0x1b,0x21,0x25,0x2b,0x31,0x37,0x36, +0x33,0x2d,0x28,0x20,0x19,0x14,0xd, 0x8, 0x1, 0x2, 0x5, 0xb, 0x10,0x18,0x1e,0x23, +0x2a,0x30,0x35,0x3a,0x3e,0x3f,0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4, +0x9, 0xf, 0x15,0x1d,0x24,0x2a,0x30,0x35,0x3b,0x3e,0x3f,0x40,0x3f,0x3e,0x3d,0x3d, +0x3c,0x3c,0x3b,0x3b,0x39,0x37,0x1a,0x2d,0x65,0x55,0x1b,0x29,0x27,0x1e,0x14,0x11, +0x1a,0x26,0x2e,0x37,0x3d,0x3f,0x3d,0x37,0x2e,0x21,0x16,0xc, 0x5, 0x1, 0x0, 0x0, +0x1, 0x3, 0xa, 0x13,0x1d,0x26,0x2e,0x33,0x38,0x3a,0x16,0x21,0x2b,0x32,0x30,0x2a, +0x27,0x2a,0x2f,0x2d,0x24,0x1a,0x10,0x7, 0x1, 0x0, 0x2, 0x7, 0x10,0x19,0x23,0x2d, +0x36,0x41,0x49,0x4c,0x4a,0x45,0x3c,0x34,0x2a,0x27,0x51,0x71,0x50,0x55,0x28,0x12, +0x11,0x18,0x23,0x29,0x2b,0x2a,0x2e,0x35,0x3c,0x3e,0x3f,0x39,0x31,0x28,0x1e,0x15, +0xe, 0x6, 0x3, 0x1, 0x0, 0x0, 0x3, 0xc, 0x16,0x20,0x2b,0x32,0x37,0x39,0x20,0x29, +0x32,0x37,0x31,0x28,0x21,0x2a,0x31,0x2d,0x23,0x1b,0x13,0x8, 0x1, 0x0, 0x1, 0x5, +0xc, 0x18,0x20,0x29,0x34,0x3e,0x47,0x4f,0x50,0x4d,0x45,0x3c,0x34,0x31,0x26,0xcb, +0x50,0x55,0x1d,0x2f,0x2c,0x25,0x1a,0x1b,0x20,0x29,0x31,0x31,0x2e,0x2d,0x35,0x3d, +0x3f,0x3d,0x38,0x2c,0x22,0x15,0xd, 0x6, 0x1, 0x0, 0x1, 0x6, 0x10,0x1b,0x24,0x2f, +0x38,0x3d,0xd, 0x1b,0x27,0x31,0x32,0x28,0x1e,0x14,0x15,0x1d,0x28,0x31,0x34,0x2a, +0x1f,0x14,0x9, 0x1, 0x0, 0x4, 0xd, 0x17,0x21,0x2c,0x35,0x40,0x47,0x47,0x44,0x3c, +0x34,0x30,0x1b,0x82,0x50,0x55,0x19,0x2e,0x2a,0x1f,0x18,0x1b,0x22,0x2d,0x30,0x2e, +0x2e,0x35,0x3d,0x3f,0x3d,0x3a,0x2f,0x24,0x18,0xf, 0x7, 0x1, 0x0, 0x0, 0x3, 0xb, +0x16,0x1e,0x29,0x32,0x3a,0x3d,0x11,0x1f,0x28,0x32,0x30,0x26,0x1b,0x14,0x1c,0x25, +0x2e,0x35,0x2e,0x23,0x19,0x11,0x4, 0x0, 0x1, 0x8, 0x10,0x1c,0x25,0x30,0x38,0x40, +0x42,0x3f,0x39,0x32,0x2c,0x27,0xc0,0xd1,0x50,0x55,0x18,0x2c,0x29,0x1e,0x14,0x13, +0x16,0x1e,0x29,0x30,0x2e,0x2c,0x2b,0x37,0x3d,0x3f,0x3e,0x39,0x30,0x25,0x1b,0x10, +0x8, 0x1, 0x0, 0x2, 0x9, 0x13,0x1f,0x2d,0x38,0x3c,0x11,0x1a,0x23,0x2f,0x33,0x29, +0x20,0x16,0xe, 0x13,0x1d,0x28,0x32,0x31,0x28,0x1e,0x16,0xb, 0x2, 0x0, 0x1, 0x8, +0x12,0x1e,0x29,0x33,0x3b,0x3f,0x3c,0x32,0x29,0x26,0x30,0x6e,0x50,0x55,0x16,0x2b, +0x24,0x17,0xd, 0xa, 0xe, 0x15,0x24,0x28,0x25,0x23,0x2b,0x36,0x3b,0x3d,0x3b,0x37, +0x2b,0x20,0x15,0xb, 0x4, 0x0, 0x0, 0x3, 0xe, 0x19,0x27,0x33,0x3d,0x3f,0x13,0x21, +0x2e,0x37,0x3a,0x31,0x27,0x1c,0x13,0x1c,0x28,0x34,0x3e,0x37,0x2d,0x22,0x18,0xc, +0x1, 0x0, 0x3, 0xd, 0x18,0x25,0x31,0x3c,0x47,0x48,0x42,0x38,0x2e,0x2a,0x31,0x62, +0x50,0x55,0x35,0x2e,0x27,0x22,0x1f,0x1b,0x16,0x10,0xc, 0x8, 0x6, 0x4, 0x2, 0x0, +0x0, 0x0, 0x1, 0x3, 0x6, 0xb, 0xe, 0x12,0x17,0x1d,0x22,0x26,0x2a,0x30,0x35,0x39, +0x3d,0x3f,0x0, 0x0, 0x1, 0x4, 0x6, 0x8, 0xb, 0x10,0x16,0x1b,0x1f,0x23,0x28,0x2d, +0x32,0x36,0x3b,0x40,0x44,0x48,0x4a,0x4b,0x4c,0x4b,0x4a,0x48,0x46,0x43,0x40,0x3e, +0x3c,0x3a,0x3c,0x9c,0x34,0x55,0x2d,0x28,0x24,0x22,0x1f,0x1c,0x19,0x16,0x13,0x10, +0xc, 0x8, 0x5, 0x2, 0x0, 0x3, 0x7, 0xa, 0xe, 0x11,0x16,0x19,0x1e,0x22,0x27,0x2c, +0x30,0x33,0x36,0x39,0x3d,0x40,0x0, 0x2, 0x6, 0x9, 0xb, 0xe, 0x11,0x14,0x16,0x18, +0x1b,0x1f,0x22,0x25,0x28,0x29,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x32,0x33,0x35,0x36, +0x38,0x39,0x3b,0x3c,0x3e,0x40,0xac,0x6a,0x34,0x55,0x25,0x1e,0x1a,0x17,0x15,0x11, +0xe, 0xb, 0x9, 0x7, 0x4, 0x2, 0x1, 0x2, 0x5, 0x9, 0xd, 0x10,0x13,0x17,0x1b,0x1e, +0x21,0x25,0x29,0x2d,0x30,0x33,0x37,0x3b,0x3e,0x40,0x0, 0x6, 0xc, 0x10,0x13,0x19, +0x1f,0x23,0x27,0x2b,0x2f,0x33,0x36,0x38,0x3a,0x3a,0x3a,0x3b,0x3b,0x3b,0x3c,0x3c, +0x3c,0x3c,0x3c,0x3d,0x3d,0x3d,0x3e,0x3e,0x3f,0x40,0xca,0xd8,0x34,0x55,0x9, 0x17, +0x1d,0x26,0x2e,0x37,0x3c,0x3f,0x3b,0x33,0x2b,0x22,0x1a,0x11,0xb, 0x5, 0x3, 0x1, +0x1, 0x0, 0x0, 0x0, 0x1, 0x6, 0xa, 0x11,0x19,0x22,0x2a,0x32,0x39,0x3d,0x30,0x30, +0x2f,0x2c,0x26,0x1e,0x17,0xd, 0x5, 0x0, 0x0, 0x1, 0x6, 0xe, 0x15,0x1e,0x26,0x2c, +0x32,0x3a,0x41,0x48,0x50,0x5b,0x61,0x64,0x64,0x60,0x5b,0x56,0x51,0x4f,0xd8,0x2c, +0x33,0x55,0x6, 0x11,0x18,0x1e,0x22,0x27,0x2a,0x2c,0x29,0x25,0x1f,0x18,0x11,0xb, +0x5, 0x1, 0x0, 0x0, 0x1, 0x3, 0x6, 0xa, 0x11,0x18,0x20,0x26,0x2c,0x32,0x36,0x3b, +0x3d,0x3f,0x48,0x37,0x2e,0x24,0x1a,0x11,0xa, 0x4, 0x0, 0x0, 0x1, 0x5, 0xb, 0x12, +0x1b,0x21,0x28,0x30,0x37,0x41,0x47,0x4e,0x54,0x53,0x4e,0x48,0x41,0x3b,0x33,0x2c, +0x28,0x25,0xb, 0x67,0x33,0x55,0x6, 0xc, 0x15,0x19,0x22,0x2b,0x2f,0x36,0x3c,0x3e, +0x3f,0x39,0x34,0x29,0x25,0x1d,0x14,0xf, 0x7, 0x2, 0x0, 0x0, 0x0, 0x2, 0xc, 0x10, +0x10,0x10,0x10,0x10,0x10,0x10,0x36,0x35,0x32,0x31,0x2d,0x28,0x25,0x1f,0x18,0x13, +0xa, 0x2, 0x0, 0x0, 0x0, 0x3, 0x8, 0xc, 0x17,0x21,0x26,0x31,0x3b,0x3f,0x45,0x46, +0x46,0x46,0x46,0x46,0x46,0x46,0xf0,0x59,0x33,0x55,0x0, 0x6, 0xf, 0x19,0x21,0x2a, +0x2e,0x32,0x2a,0x21,0x18,0x14,0xc, 0x6, 0x2, 0x0, 0x1, 0xb, 0x13,0x1d,0x25,0x2a, +0x32,0x3a,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x23,0x1f,0x1b,0x17,0x13,0xc, +0x9, 0x1, 0x1, 0x6, 0xe, 0x12,0x1b,0x24,0x2d,0x37,0x3b,0x3f,0x3f,0x3d,0x39,0x36, +0x2e,0x25,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xf4,0x7b,0x33,0x55,0x5, 0xd, +0x19,0x23,0x2d,0x31,0x34,0x2c,0x22,0x1e,0x15,0xd, 0x8, 0x4, 0x2, 0x0, 0x2, 0xc, +0x10,0x19,0x21,0x2a,0x2e,0x37,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x1b, +0x18,0x16,0x10,0xd, 0x4, 0x0, 0x3, 0x5, 0xc, 0x16,0x1e,0x26,0x2a,0x35,0x3d,0x3f, +0x3e,0x3c,0x3b,0x3a,0x39,0x38,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x8d,0x3a, +0x33,0x55,0x5, 0xd, 0x13,0x19,0x20,0x26,0x2e,0x35,0x3c,0x3d,0x37,0x2f,0x20,0x19, +0x11,0xb, 0x5, 0x2, 0x0, 0x0, 0x1, 0x6, 0xc, 0x17,0x1d,0x23,0x29,0x30,0x36,0x3b, +0x3e,0x3e,0x28,0x25,0x22,0x20,0x1d,0x18,0x14,0xf, 0x8, 0x2, 0x0, 0x0, 0x4, 0x7, +0xc, 0x11,0x18,0x1e,0x24,0x2c,0x33,0x3a,0x3e,0x3f,0x3e,0x3c,0x38,0x31,0x2a,0x21, +0x1a,0x1a,0x6, 0x33,0x33,0x55,0x26,0x1c,0x19,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x17,0x17,0x15,0xf, 0x9, 0x4, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4, 0xb, 0x12,0x18, +0x1f,0x28,0x31,0x37,0x3c,0x40,0x1, 0x7, 0xe, 0x14,0x1c,0x23,0x2c,0x34,0x3e,0x44, +0x4c,0x54,0x5b,0x60,0x5d,0x55,0x4f,0x49,0x43,0x3d,0x38,0x32,0x2b,0x26,0x22,0x1f, +0x1e,0x1c,0x1c,0x1c,0x1c,0x1d,0x66,0x54,0x74,0x55,0x3e,0x2c,0x21,0x1d,0x1d,0x1d, +0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1e,0x1e,0x1d,0x1a,0x11,0xc, 0x7, 0x2, +0x0, 0x0, 0x3, 0xa, 0x12,0x1c,0x23,0x2c,0x38,0x40,0xc, 0x0, 0x6, 0xf, 0x17,0x22, +0x29,0x32,0x3b,0x41,0x47,0x4f,0x55,0x5c,0x66,0x71,0x79,0x3e,0x76,0x6d,0x64,0x5a, +0x52,0x4b,0x42,0x39,0x35,0x33,0x32,0x32,0x31,0x31,0xf3,0xdb,0x74,0x55,0x9, 0x7, +0x6, 0x6, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, 0x3, 0x2, 0x2, 0x2, 0x1, 0x0, 0x0, 0x0, +0x0, 0x0, 0x3, 0xa, 0x10,0x14,0x1b,0x22,0x28,0x2e,0x34,0x39,0x3d,0x40,0x0, 0xb, +0x11,0x16,0x1b,0x22,0x28,0x2c,0x33,0x39,0x40,0x46,0x4d,0x52,0x56,0x5c,0x61,0x68, +0x6d,0x73,0x73,0x71,0x71,0x71,0x70,0x70,0x6f,0x6f,0x6f,0x6f,0x6d,0x6e,0x79,0x80, +0x44,0x55,0x17,0x13,0x12,0x12,0x11,0x10,0xf, 0xd, 0xc, 0xb, 0x9, 0x8, 0x7, 0x4, +0x3, 0x2, 0x1, 0x0, 0x0, 0x0, 0x1, 0x4, 0xb, 0x10,0x16,0x1d,0x24,0x29,0x31,0x39, +0x3d,0x40,0x0, 0xe, 0x16,0x1a,0x1f,0x24,0x29,0x2e,0x33,0x38,0x3e,0x43,0x47,0x50, +0x55,0x59,0x62,0x69,0x6e,0x75,0x7c,0xff,0x7d,0x7c,0x79,0x73,0x6d,0x68,0x60,0x5a, +0x57,0x56,0x5d,0x8, 0x44,0x55,0x0, 0x7, 0xb, 0xd, 0x10,0x12,0x16,0x17,0x17,0x18, +0x18,0x19,0x19,0x19,0x1c,0x1e,0x20,0x22,0x23,0x25,0x27,0x29,0x2b,0x30,0x32,0x33, +0x35,0x38,0x39,0x3b,0x3d,0x3f,0x3e,0x29,0x1f,0x18,0xf, 0x7, 0x6, 0xc, 0x12,0x1d, +0x25,0x2d,0x36,0x3e,0x3b,0x35,0x2c,0x26,0x20,0x19,0x11,0xa, 0x3, 0x3, 0x9, 0x10, +0x18,0x24,0x2c,0x33,0x3a,0x3e,0x60,0x9b,0x32,0x55,0x0, 0x5, 0x5, 0x5, 0x4, 0x3, +0x2, 0x3, 0x5, 0x7, 0xa, 0xe, 0x11,0x19,0x1b,0x1c,0x1d,0x1c,0x1c,0x1d,0x1f,0x22, +0x25,0x2a,0x31,0x33,0x35,0x37,0x38,0x39,0x3c,0x40,0x0, 0x12,0x1c,0x24,0x2b,0x34, +0x3c,0x39,0x2f,0x29,0x21,0x16,0xf, 0xd, 0x14,0x1e,0x2a,0x33,0x31,0x27,0x20,0x18, +0x10,0x7, 0xa, 0x10,0x1a,0x26,0x2f,0x37,0x3d,0x3f,0xfb,0x8f,0x32,0x55,0x0, 0x0, +0x1, 0x3, 0x8, 0xb, 0x12,0x18,0x1b,0x20,0x22,0x22,0x23,0x24,0x26,0x27,0x29,0x2b, +0x30,0x31,0x31,0x32,0x32,0x34,0x35,0x37,0x3b,0x3e,0x3f,0x3f,0x3f,0x3f,0x7b,0x6d, +0x5f,0x53,0x40,0x36,0x23,0x14,0xb, 0x3, 0xe, 0x1e,0x29,0x35,0x29,0x20,0x11,0x7, +0x6, 0x16,0x1f,0x2d,0x35,0x43,0x4c,0x59,0x68,0x72,0x74,0x74,0x74,0x74,0x90,0x27, +0x32,0x55,0x2c,0x23,0x1f,0x19,0x13,0xc, 0x7, 0x3, 0x0, 0x0, 0x0, 0x1, 0x5, 0xa, +0xf, 0x16,0x1d,0x23,0x2a,0x30,0x36,0x3b,0x3e,0x40,0x3f,0x3e,0x3b,0x38,0x33,0x2f, +0x2b,0x28,0x9, 0x1, 0x0, 0x1, 0x3, 0x9, 0xe, 0x14,0x1b,0x21,0x27,0x2e,0x36,0x3b, +0x3e,0x41,0x41,0x40,0x3d,0x3a,0x36,0x2f,0x2b,0x26,0x20,0x1c,0x16,0x10,0xc, 0xa, +0x9, 0xb, 0x36,0xdc,0x30,0x55,0x1a,0x9, 0x5, 0x1, 0x0, 0x0, 0x0, 0x2, 0x5, 0x9, +0xf, 0x16,0x1c,0x22,0x2a,0x31,0x36,0x39,0x3c,0x3e,0x3f,0x3f,0x3d,0x38,0x30,0x27, +0x1f,0x18,0x12,0xb, 0x6, 0x5, 0x7, 0x12,0x19,0x22,0x2c,0x36,0x3f,0x49,0x53,0x5c, +0x63,0x66,0x64,0x5f,0x58,0x4c,0x43,0x3d,0x34,0x2b,0x22,0x1b,0x15,0xb, 0x4, 0x0, +0x0, 0x1, 0x4, 0xb, 0x13,0x18,0xf1,0xc, 0x30,0x55,0x18,0x2c,0x34,0x39,0x3c,0x3d, +0x3f,0x3f,0x3f,0x3d,0x3b,0x36,0x30,0x2a,0x24,0x1c,0x16,0xd, 0x6, 0x1, 0x0, 0x0, +0x0, 0x1, 0x1, 0x3, 0x5, 0x9, 0xf, 0x17,0x1e,0x24,0x1, 0x2, 0x8, 0xe, 0x14,0x1a, +0x21,0x28,0x30,0x37,0x40,0x49,0x50,0x55,0x59,0x5c,0x5c,0x58,0x51,0x48,0x3f,0x38, +0x31,0x2b,0x25,0x1d,0x17,0x11,0xa, 0x4, 0x1, 0x1, 0x9d,0xbf,0x30,0x55,0x16,0x7, +0x2, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4, 0x8, 0xe, 0x16,0x1f,0x28,0x30,0x38,0x3c,0x3e, +0x3f,0x40,0x3f,0x3f,0x3d,0x3b,0x37,0x32,0x2c,0x25,0x1d,0x16,0xf, 0xc, 0x53,0x46, +0x3e,0x35,0x2e,0x27,0x20,0x1a,0x14,0xd, 0x6, 0x1, 0x0, 0x0, 0x3, 0xa, 0x13,0x1a, +0x20,0x27,0x2d,0x33,0x3a,0x40,0x48,0x4f,0x54,0x58,0x5a,0x5a,0x58,0x57,0xc6,0x55, +0x30,0x55,0x7, 0x1, 0x4, 0xa, 0x10,0x18,0x20,0x2a,0x32,0x38,0x3c,0x3e,0x3f,0x3e, +0x3d,0x3b,0x39,0x35,0x30,0x27,0x21,0x19,0x12,0xb, 0x6, 0x3, 0x1, 0x0, 0x0, 0x0, +0x0, 0x0, 0x32,0x1d,0x12,0x9, 0x5, 0x1, 0x0, 0x0, 0x1, 0x5, 0xd, 0x17,0x20,0x2a, +0x32,0x3b,0x45,0x4e,0x58,0x63,0x69,0x6b,0x6a,0x64,0x5d,0x57,0x4f,0x47,0x40,0x38, +0x32,0x2f,0x1a,0xb5,0x30,0x55,0x21,0x13,0xc, 0x8, 0x5, 0x2, 0x1, 0x0, 0x0, 0x1, +0x3, 0x8, 0xf, 0x17,0x1e,0x24,0x2b,0x32,0x39,0x3d,0x3e,0x3f,0x3f,0x3d,0x3a,0x36, +0x30,0x29,0x21,0x1a,0x16,0x13,0x5, 0x9, 0xe, 0x14,0x1a,0x22,0x29,0x30,0x38,0x3f, +0x47,0x4d,0x51,0x51,0x4f,0x4d,0x49,0x42,0x39,0x31,0x2b,0x25,0x1e,0x17,0x10,0x8, +0x3, 0x0, 0x0, 0x1, 0x3, 0x5, 0xaf,0x13,0x30,0x55,0x38,0x3f,0x3d,0x3a,0x36,0x2e, +0x26,0x1f,0x14,0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, 0x9, 0xe, 0x14,0x1c, +0x23,0x2a,0x34,0x38,0x3a,0x3b,0x3d,0x3d,0x3d,0x3d,0x29,0x1a,0x10,0x9, 0x4, 0x0, +0x0, 0x1, 0x4, 0xc, 0x14,0x1c,0x22,0x28,0x2f,0x37,0x3f,0x47,0x4f,0x56,0x5a,0x5b, +0x59,0x56,0x4e,0x47,0x40,0x37,0x30,0x28,0x22,0x1f,0x2a,0xa9,0x30,0x55,0x3e,0x3b, +0x38,0x33,0x2b,0x24,0x1d,0x16,0x10,0x7, 0x3, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, +0x6, 0xc, 0x15,0x1c,0x23,0x29,0x2f,0x35,0x38,0x3b,0x3c,0x3e,0x3f,0x3f,0x1f,0x10, +0xa, 0x6, 0x0, 0x0, 0x0, 0x2, 0x4, 0xc, 0x12,0x18,0x1e,0x25,0x2c,0x35,0x3c,0x42, +0x4a,0x51,0x56,0x56,0x53,0x4e,0x49,0x40,0x3a,0x33,0x2c,0x25,0x1f,0x1c,0xf9,0xa2, +0x30,0x55,0x1f,0x2b,0x31,0x35,0x38,0x3b,0x3e,0x3f,0x3f,0x3d,0x3a,0x34,0x2d,0x27, +0x23,0x1d,0x17,0x10,0x9, 0x4, 0x1, 0x0, 0x0, 0x1, 0x3, 0x6, 0xa, 0xf, 0x15,0x1b, +0x20,0x23,0x45,0x42,0x3e,0x38,0x34,0x2d,0x24,0x1c,0x15,0x11,0xb, 0x6, 0x2, 0x0, +0x0, 0x0, 0x1, 0x3, 0x7, 0xd, 0x12,0x18,0x20,0x28,0x30,0x36,0x3c,0x42,0x47,0x48, +0x49,0x4a,0x65,0x9d,0x30,0x55,0x1c,0x2a,0x33,0x39,0x3c,0x3e,0x3f,0x3f,0x3e,0x3d, +0x3a,0x35,0x2e,0x28,0x23,0x1c,0x15,0xf, 0x9, 0x4, 0x1, 0x0, 0x0, 0x1, 0x1, 0x4, +0x8, 0xd, 0x13,0x19,0x1e,0x22,0x40,0x3e,0x3a,0x33,0x2f,0x29,0x22,0x1b,0x15,0x10, +0xa, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x5, 0xa, 0x11,0x17,0x1c,0x24,0x2a,0x30,0x35, +0x3b,0x40,0x43,0x44,0x45,0x45,0xcb,0xc6,0x30,0x55,0x5, 0x3, 0x4, 0x7, 0xa, 0x10, +0x17,0x21,0x28,0x2e,0x33,0x38,0x3c,0x3e,0x3f,0x3f,0x3e,0x3b,0x38,0x31,0x29,0x21, +0x18,0xf, 0x9, 0x4, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26,0x35,0x3d,0x45,0x4b,0x51, +0x53,0x52,0x4f,0x4c,0x46,0x41,0x3b,0x34,0x2e,0x25,0x1e,0x17,0x11,0x9, 0x3, 0x0, +0x0, 0x2, 0x6, 0xc, 0x12,0x18,0x1e,0x24,0x2c,0x31,0xf4,0xb6,0x30,0x55,0xa, 0x5, +0x5, 0x5, 0x8, 0xf, 0x16,0x20,0x29,0x31,0x36,0x3a,0x3c,0x3e,0x3f,0x3f,0x3e,0x3c, +0x3a,0x33,0x2d,0x24,0x1c,0x14,0xf, 0x8, 0x4, 0x0, 0x0, 0x0, 0x1, 0x2, 0x35,0x46, +0x4e,0x56,0x5d,0x65,0x68,0x66,0x60,0x57,0x4f,0x47,0x3f,0x37,0x2e,0x25,0x1e,0x16, +0x10,0x6, 0x2, 0x0, 0x1, 0x5, 0xb, 0x15,0x1d,0x28,0x2f,0x39,0x41,0x45,0xf0,0xbc, +0x30,0x55,0x7, 0x3, 0x3, 0x3, 0x4, 0x7, 0xf, 0x17,0x20,0x28,0x30,0x36,0x3b,0x3d, +0x3f,0x3f,0x3d,0x39,0x36,0x2d,0x25,0x1d,0x16,0xd, 0x8, 0x2, 0x0, 0x0, 0x1, 0x2, +0x3, 0x5, 0x2e,0x3f,0x48,0x50,0x59,0x5f,0x67,0x68,0x63,0x5d,0x52,0x4a,0x3e,0x35, +0x2b,0x20,0x18,0x10,0xa, 0x3, 0x0, 0x0, 0x1, 0x7, 0xe, 0x19,0x22,0x2b,0x31,0x3a, +0x42,0x47,0xef,0xc9,0x30,0x55,0x3b,0x3c,0x3c,0x3b,0x39,0x36,0x2f,0x27,0x21,0x19, +0x11,0xb, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x4, 0x6, 0xa, 0x10,0x16,0x1f,0x26,0x2d, +0x33,0x39,0x3c,0x3e,0x3f,0x3f,0x22,0x31,0x3b,0x41,0x47,0x4d,0x56,0x59,0x5a,0x58, +0x55,0x51,0x4b,0x43,0x3d,0x35,0x29,0x20,0x18,0x11,0x9, 0x3, 0x0, 0x0, 0x1, 0x3, +0x7, 0xf, 0x15,0x1b,0x21,0x26,0x2b,0xa0,0x30,0x55,0x37,0x38,0x37,0x34,0x2d,0x26, +0x1c,0x16,0xe, 0x9, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, 0xa, 0x10,0x17,0x20, +0x26,0x2e,0x35,0x3a,0x3c,0x3e,0x3f,0x3f,0x3e,0x3e,0x30,0x40,0x49,0x50,0x59,0x5e, +0x60,0x5d,0x56,0x50,0x47,0x41,0x39,0x33,0x2a,0x20,0x1a,0x10,0xa, 0x5, 0x1, 0x0, +0x0, 0x3, 0x8, 0x10,0x17,0x1f,0x25,0x2f,0x38,0x3c,0x37,0xc3,0x30,0x55,0x3b,0x3d, +0x3d,0x3b,0x38,0x32,0x27,0x1c,0x13,0xe, 0x8, 0x3, 0x0, 0x0, 0x0, 0x1, 0x3, 0x7, +0xb, 0x12,0x18,0x20,0x28,0x31,0x39,0x3d,0x3f,0x40,0x3f,0x3f,0x3e,0x3e,0x33,0x45, +0x4e,0x57,0x5d,0x65,0x6c,0x6a,0x66,0x63,0x5c,0x53,0x4a,0x40,0x38,0x2e,0x25,0x1a, +0x11,0x8, 0x4, 0x0, 0x0, 0x2, 0x9, 0x10,0x19,0x21,0x2a,0x32,0x39,0x3e,0x7, 0x90, +0x30,0x55,0x8, 0x2, 0x0, 0x0, 0x0, 0x2, 0x5, 0x7, 0xc, 0x12,0x19,0x1f,0x2b,0x32, +0x37,0x3b,0x3d,0x3f,0x3f,0x3e,0x3d,0x3a,0x37,0x2f,0x29,0x23,0x1d,0x16,0xf, 0x9, +0x6, 0x6, 0x47,0x3d,0x36,0x2f,0x27,0x1e,0x16,0x10,0x9, 0x3, 0x0, 0x0, 0x1, 0x4, +0x7, 0xd, 0x14,0x1d,0x26,0x2d,0x33,0x3a,0x42,0x4e,0x53,0x55,0x56,0x54,0x4f,0x48, +0x42,0x42,0x43,0x9e,0x30,0x55,0x2, 0x0, 0x0, 0x1, 0x3, 0x7, 0xc, 0x13,0x1c,0x24, +0x2d,0x37,0x3f,0x3d,0x3b,0x39,0x36,0x34,0x31,0x2e,0x2b,0x27,0x20,0x16,0xe, 0x8, +0x3, 0x3, 0x3, 0x4, 0x4, 0x4, 0x5d,0x50,0x46,0x3e,0x36,0x2c,0x20,0x16,0xd, 0x6, +0x2, 0x0, 0xb, 0x16,0x22,0x2a,0x33,0x3c,0x44,0x4c,0x55,0x5d,0x69,0x79,0x7d,0x76, +0x6d,0x63,0x59,0x50,0x48,0x47,0x12,0x3e,0x30,0x55,0x3, 0x1, 0x2, 0x6, 0xa, 0x16, +0x20,0x25,0x30,0x39,0x3e,0x3f,0x3f,0x3c,0x3a,0x32,0x28,0x22,0x19,0xe, 0x5, 0x2, +0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x29,0x23,0x18,0xf, 0xb, 0x3, +0x0, 0x0, 0x1, 0x8, 0x11,0x17,0x21,0x2a,0x2f,0x3a,0x42,0x43,0x42,0x3e,0x38,0x34, +0x2c,0x24,0x1f,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x7f,0xd2,0x30,0x55,0x39,0x2b, +0x24,0x1c,0x15,0xe, 0x9, 0x6, 0x5, 0x6, 0x9, 0x10,0x19,0x22,0x27,0x2e,0x35,0x3b, +0x3e,0x3f,0x3d,0x38,0x32,0x2c,0x26,0x1f,0x19,0x13,0xb, 0x5, 0x1, 0x0, 0x6, 0x0, +0x1, 0x2, 0x6, 0xb, 0x11,0x17,0x1d,0x24,0x2a,0x2f,0x32,0x34,0x35,0x36,0x37,0x3b, +0x41,0x47,0x4e,0x56,0x5d,0x61,0x64,0x65,0x65,0x63,0x60,0x5c,0x57,0x54,0xd1,0x4a, +0x46,0x55,0x3c,0x37,0x33,0x2f,0x25,0x20,0x1b,0x10,0xc, 0x8, 0x2, 0x0, 0x0, 0x3, +0x7, 0xc, 0x16,0x1b,0x1f,0x2a,0x2f,0x33,0x3d,0x3d,0x39,0x2f,0x2b,0x28,0x28,0x28, +0x28,0x28,0x2, 0x0, 0x0, 0x0, 0x2, 0x4, 0x7, 0xc, 0xf, 0x13,0x1c,0x20,0x24,0x2d, +0x30,0x32,0x35,0x36,0x36,0x36,0x36,0x36,0x39,0x3d,0x42,0x48,0x4a,0x4b,0x4b,0x4b, +0x4b,0x4b,0x10,0xa2,0x46,0x55,0x32,0x2c,0x27,0x1c,0x16,0xc, 0x7, 0x3, 0x0, 0x0, +0x0, 0x2, 0x4, 0xd, 0x11,0x1a,0x1f,0x25,0x2f,0x33,0x3c,0x3d,0x34,0x2f,0x2a,0x21, +0x1d,0x1c,0x1c,0x1c,0x1c,0x1c,0x1, 0x0, 0x0, 0x0, 0x2, 0x6, 0xa, 0xe, 0x16,0x1a, +0x22,0x26,0x2b,0x31,0x32,0x35,0x36,0x38,0x3a,0x3b,0x3e,0x41,0x4a,0x4c,0x4d,0x4e, +0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x43,0x33,0x46,0x55,0x1a,0x13,0x10,0xd, 0xb, 0xa, +0xc, 0x11,0x16,0x20,0x25,0x29,0x2e,0x32,0x37,0x3c,0x3f,0x3c,0x38,0x33,0x2e,0x29, +0x24,0x1e,0x19,0xf, 0xb, 0x7, 0x2, 0x0, 0x0, 0x0, 0x0, 0x6, 0xb, 0x10,0x15,0x19, +0x1d,0x1e,0x1f,0x1e,0x1f,0x1f,0x20,0x21,0x24,0x29,0x2f,0x39,0x3e,0x41,0x44,0x47, +0x49,0x4b,0x4c,0x4e,0x4e,0x4f,0x4e,0x4d,0x4d,0x4d,0xa, 0x24,0x46,0x55,0x0, 0x1, +0x3, 0x5, 0x7, 0x8, 0xa, 0xb, 0xc, 0xe, 0xf, 0x11,0x12,0x14,0x16,0x1a,0x1e,0x22, +0x24,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x3f,0x1, 0xe, +0x14,0x1b,0x23,0x28,0x2e,0x35,0x3a,0x40,0x48,0x4f,0x56,0x5d,0x62,0x61,0x5a,0x53, +0x4e,0x47,0x40,0x3b,0x35,0x2d,0x29,0x22,0x1b,0x17,0x10,0x9, 0x5, 0x1, 0x6d,0x7d, +0x54,0x55,0x40,0x39,0x38,0x36,0x35,0x33,0x31,0x2e,0x2c,0x2b,0x29,0x27,0x25,0x24, +0x22,0x1f,0x1d,0x1a,0x18,0x15,0x14,0x12,0xf, 0xc, 0x9, 0x7, 0x4, 0x2, 0x1, 0x0, +0x0, 0x0, 0x0, 0xd, 0x15,0x1d,0x23,0x2a,0x32,0x3b,0x43,0x48,0x50,0x57,0x5d,0x63, +0x68,0x65,0x5e,0x58,0x51,0x4a,0x45,0x3f,0x38,0x32,0x2b,0x26,0x1f,0x16,0x10,0x8, +0x4, 0x1, 0x6a,0xec,0x54,0x55,0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x1, 0x2, 0x4, 0x5, 0x7, 0x9, 0xd, 0x10,0x13,0x18,0x1f,0x24,0x27,0x2b,0x2e,0x31, +0x34,0x36,0x39,0x3c,0x3e,0x40,0x0, 0x7, 0xf, 0x13,0x16,0x1a,0x1e,0x22,0x25,0x28, +0x2f,0x36,0x3b,0x3f,0x43,0x47,0x4b,0x4c,0x4c,0x4c,0x49,0x46,0x43,0x3f,0x3a,0x35, +0x32,0x2d,0x27,0x21,0x1d,0x1a,0xb5,0xd0,0x54,0x55,0x0, 0x1, 0x1, 0x1, 0x2, 0x3, +0x3, 0x4, 0x5, 0x9, 0xf, 0x16,0x1d,0x22,0x28,0x2d,0x30,0x32,0x34,0x37,0x39,0x3a, +0x3c,0x3d,0x3e,0x3e,0x3f,0x3f,0x3e,0x3e,0x3c,0x3a,0x22,0x2e,0x36,0x3f,0x46,0x4c, +0x51,0x56,0x5b,0x5e,0x60,0x5e,0x5c,0x58,0x53,0x4d,0x49,0x45,0x41,0x3a,0x35,0x31, +0x2d,0x27,0x23,0x1f,0x19,0x11,0xd, 0x8, 0x3, 0x0, 0x3b,0x38,0x54,0x55,0x0, 0x2, +0x3, 0x5, 0x6, 0x8, 0xb, 0x10,0x13,0x16,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x22,0x22, +0x22,0x22,0x23,0x25,0x28,0x2e,0x31,0x34,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x6, 0x17, +0x20,0x27,0x30,0x38,0x3e,0x39,0x32,0x2b,0x25,0x1e,0x18,0x10,0x9, 0x9, 0x10,0x18, +0x1f,0x26,0x2f,0x36,0x3c,0x38,0x2f,0x27,0x1f,0x18,0xf, 0x8, 0x1, 0x2, 0xc7,0x75, +0x31,0x55,0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x8, 0xd, 0x12,0x15,0x17,0x18,0x1a, +0x1b,0x1c,0x1d,0x1d,0x1e,0x1f,0x22,0x27,0x2e,0x35,0x38,0x3b,0x3d,0x3e,0x3f,0x40, +0x3f,0x3e,0x6, 0x15,0x1b,0x23,0x29,0x2f,0x37,0x3c,0x37,0x2e,0x27,0x20,0x1a,0x13, +0xe, 0x14,0x1a,0x21,0x27,0x2f,0x38,0x3f,0x3d,0x35,0x2e,0x26,0x20,0x18,0x11,0xb, +0x3, 0x0, 0x67,0x3f,0x31,0x55,0xd, 0xd0,0x80,0x7f,0x0, 0xff,0xe9,0x16,0x4, 0xa7, +0x24,0x87,0x2, 0xa9,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38,0x33,0x32,0x1, 0xd2,0x0, 0x50,0x1, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8, 0x30,0x30,0x31,0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, +0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, +0x1, 0x0, 0x1, 0x9, 0x9, 0x12,0x1e,0x12,0x1e,0x1, 0x5, 0x1, 0xe, 0x1, 0xe, 0x0, +0x3, 0x0, 0x3, 0x1, 0xe, 0x1, 0xe, 0x1, 0x0, 0x3, 0x0, 0x4, 0x0, 0x5, 0x0, 0x6, +0x0, 0x7, 0x0, 0x8, 0x0, 0x9, 0x0, 0xa, 0x0, 0xb, 0x0, 0xc, 0x0, 0xd, 0x0, 0xe, +0x0, 0xf, 0x0, 0x10,0x0, 0x11,0x0, 0x12,0x0, 0x13,0x0, 0x14,0x0, 0x15,0x0, 0x16, +0x0, 0x17,0x0, 0x18,0x0, 0x19,0x0, 0x1a,0x0, 0x1b,0x0, 0x1c,0x0, 0x1d,0x0, 0x1e, +0x0, 0x1f,0x0, 0x20,0x0, 0x21,0x0, 0x22,0x0, 0x23,0x0, 0x24,0x0, 0x25,0x0, 0x26, +0x0, 0x27,0x0, 0x28,0x0, 0x29,0x0, 0x2a,0x0, 0x2b,0x0, 0x2c,0x0, 0x2d,0x0, 0x2e, +0x0, 0x2f,0x0, 0x30,0x0, 0x31,0x0, 0x32,0x0, 0x33,0x0, 0x34,0x0, 0x35,0x0, 0x36, +0x0, 0x37,0x0, 0x38,0x0, 0x39,0x0, 0x3a,0x0, 0x3b,0x0, 0x3c,0x0, 0x3d,0x0, 0x3e, +0x0, 0x3f,0x0, 0x40,0x0, 0x41,0x0, 0x42,0x0, 0x43,0x0, 0x44,0x0, 0x45,0x0, 0x46, +0x0, 0x47,0x0, 0x48,0x0, 0x49,0x0, 0x4a,0x0, 0x4b,0x0, 0x4c,0x0, 0x4d,0x0, 0x4e, +0x0, 0x4f,0x0, 0x50,0x0, 0x51,0x0, 0x52,0x0, 0x53,0x0, 0x54,0x0, 0x55,0x0, 0x56, +0x0, 0x57,0x0, 0x58,0x0, 0x59,0x0, 0x5a,0x0, 0x5b,0x0, 0x5c,0x0, 0x5d,0x0, 0x5e, +0x0, 0x5f,0x0, 0x60,0x0, 0x61,0x0, 0x62,0x0, 0x63,0x0, 0x64,0x0, 0x65,0x0, 0x66, +0x0, 0x67,0x0, 0x68,0x0, 0x69,0x0, 0x6a,0x0, 0x6b,0x0, 0x6c,0x0, 0x6d,0x0, 0x6e, +0x0, 0x6f,0x0, 0x70,0x0, 0x71,0x0, 0x72,0x0, 0x73,0x0, 0x74,0x0, 0x75,0x0, 0x76, +0x0, 0x77,0x0, 0x78,0x0, 0x79,0x0, 0x7a,0x0, 0x7b,0x0, 0x7c,0x0, 0x7d,0x0, 0x7e, +0x0, 0x7f,0x0, 0x80,0x0, 0x81,0x0, 0x82,0x0, 0x83,0x0, 0x84,0x0, 0x85,0x0, 0x86, +0x0, 0x87,0x0, 0x88,0x0, 0x89,0x0, 0x8a,0x0, 0x8b,0x0, 0x8c,0x0, 0x8d,0x0, 0x8e, +0x0, 0x8f,0x0, 0x90,0x0, 0x91,0x0, 0x92,0x0, 0x93,0x0, 0x94,0x0, 0x95,0x0, 0x96, +0x0, 0x97,0x0, 0x98,0x0, 0x99,0x0, 0x9a,0x0, 0x9b,0x0, 0x9c,0x0, 0x9d,0x0, 0x9e, +0x0, 0x9f,0x0, 0xa0,0x0, 0xa1,0x0, 0xa2,0x0, 0xa3,0x0, 0xa4,0x0, 0xa5,0x0, 0xa6, +0x0, 0xa7,0x0, 0xa8,0x0, 0xa9,0x0, 0xaa,0x0, 0xab,0x0, 0xac,0x0, 0xad,0x0, 0xae, +0x0, 0xaf,0x0, 0xb0,0x0, 0xb1,0x0, 0xb2,0x0, 0xb3,0x0, 0xb4,0x0, 0xb5,0x0, 0xb6, +0x0, 0xb7,0x0, 0xb8,0x0, 0xb9,0x0, 0xba,0x0, 0xbb,0x0, 0xbc,0x0, 0xbd,0x0, 0xbe, +0x0, 0xbf,0x0, 0xc0,0x0, 0xc1,0x0, 0xc2,0x0, 0xc3,0x0, 0xc4,0x0, 0xc5,0x0, 0xc6, +0x0, 0xc7,0x0, 0xc8,0x0, 0xc9,0x0, 0xca,0x0, 0xcb,0x0, 0xcc,0x0, 0xcd,0x0, 0xce, +0x0, 0xcf,0x0, 0xd0,0x0, 0xd1,0x0, 0xd2,0x0, 0xd3,0x0, 0xd4,0x0, 0xd5,0x0, 0xd6, +0x0, 0xd7,0x0, 0xd8,0x0, 0xd9,0x0, 0xda,0x0, 0xdb,0x0, 0xdc,0x0, 0xdd,0x0, 0xde, +0x0, 0xdf,0x0, 0xe0,0x0, 0xe1,0x0, 0xe2,0x0, 0xe3,0x0, 0xe4,0x0, 0xe5,0x0, 0xe6, +0x0, 0xe7,0x0, 0xe8,0x0, 0xe9,0x0, 0xea,0x0, 0xeb,0x0, 0xec,0x0, 0xed,0x0, 0xee, +0x0, 0xef,0x0, 0xf0,0x0, 0xf1,0x0, 0xf2,0x0, 0xf3,0x0, 0xf4,0x0, 0xf5,0x0, 0xf6, +0x0, 0xf7,0x0, 0xf8,0x0, 0xf9,0x0, 0xfa,0x0, 0xfb,0x0, 0xfc,0x0, 0xfd,0x0, 0xfe, +0x0, 0xff,0x1, 0x0, 0x1, 0x1, 0x1, 0x2, 0x1, 0x3, 0x1, 0x4, 0x1, 0x5, 0x1, 0x6, +0x1, 0x7, 0x1, 0x8, 0x1, 0x9, 0x1, 0xa, 0x1, 0xb, 0x1, 0xc, 0x1, 0xd, 0x1, 0xe, +0x1, 0xf, 0x1, 0x10,0x1, 0x10,0x1, 0xf, 0x1, 0xe, 0x1, 0xd, 0x1, 0xc, 0x1, 0xb, +0x1, 0xa, 0x1, 0x9, 0x1, 0x8, 0x1, 0x7, 0x1, 0x6, 0x1, 0x5, 0x1, 0x4, 0x1, 0x3, +0x1, 0x2, 0x1, 0x1, 0x1, 0x0, 0x0, 0xff,0x0, 0xfe,0x0, 0xfd,0x0, 0xfc,0x0, 0xfb, +0x0, 0xfa,0x0, 0xf9,0x0, 0xf8,0x0, 0xf7,0x0, 0xf6,0x0, 0xf5,0x0, 0xf4,0x0, 0xf3, +0x0, 0xf2,0x0, 0xf1,0x0, 0xf0,0x0, 0xef,0x0, 0xee,0x0, 0xed,0x0, 0xec,0x0, 0xeb, +0x0, 0xea,0x0, 0xe9,0x0, 0xe8,0x0, 0xe7,0x0, 0xe6,0x0, 0xe5,0x0, 0xe4,0x0, 0xe3, +0x0, 0xe2,0x0, 0xe1,0x0, 0xe0,0x0, 0xdf,0x0, 0xde,0x0, 0xdd,0x0, 0xdc,0x0, 0xdb, +0x0, 0xda,0x0, 0xd9,0x0, 0xd8,0x0, 0xd7,0x0, 0xd6,0x0, 0xd5,0x0, 0xd4,0x0, 0xd3, +0x0, 0xd2,0x0, 0xd1,0x0, 0xd0,0x0, 0xcf,0x0, 0xce,0x0, 0xcd,0x0, 0xcc,0x0, 0xcb, +0x0, 0xca,0x0, 0xc9,0x0, 0xc8,0x0, 0xc7,0x0, 0xc6,0x0, 0xc5,0x0, 0xc4,0x0, 0xc3, +0x0, 0xc2,0x0, 0xc1,0x0, 0xc0,0x0, 0xbf,0x0, 0xbe,0x0, 0xbd,0x0, 0xbc,0x0, 0xbb, +0x0, 0xba,0x0, 0xb9,0x0, 0xb8,0x0, 0xb7,0x0, 0xb6,0x0, 0xb5,0x0, 0xb4,0x0, 0xb3, +0x0, 0xb2,0x0, 0xb1,0x0, 0xb0,0x0, 0xaf,0x0, 0xae,0x0, 0xad,0x0, 0xac,0x0, 0xab, +0x0, 0xaa,0x0, 0xa9,0x0, 0xa8,0x0, 0xa7,0x0, 0xa6,0x0, 0xa5,0x0, 0xa4,0x0, 0xa3, +0x0, 0xa2,0x0, 0xa1,0x0, 0xa0,0x0, 0x9f,0x0, 0x9e,0x0, 0x9d,0x0, 0x9c,0x0, 0x9b, +0x0, 0x9a,0x0, 0x99,0x0, 0x98,0x0, 0x97,0x0, 0x96,0x0, 0x95,0x0, 0x94,0x0, 0x93, +0x0, 0x92,0x0, 0x91,0x0, 0x90,0x0, 0x8f,0x0, 0x8e,0x0, 0x8d,0x0, 0x8c,0x0, 0x8b, +0x0, 0x8a,0x0, 0x89,0x0, 0x88,0x0, 0x87,0x0, 0x86,0x0, 0x85,0x0, 0x84,0x0, 0x83, +0x0, 0x82,0x0, 0x81,0x0, 0x80,0x0, 0x7f,0x0, 0x7e,0x0, 0x7d,0x0, 0x7c,0x0, 0x7b, +0x0, 0x7a,0x0, 0x79,0x0, 0x78,0x0, 0x77,0x0, 0x76,0x0, 0x75,0x0, 0x74,0x0, 0x73, +0x0, 0x72,0x0, 0x71,0x0, 0x70,0x0, 0x6f,0x0, 0x6e,0x0, 0x6d,0x0, 0x6c,0x0, 0x6b, +0x0, 0x6a,0x0, 0x69,0x0, 0x68,0x0, 0x67,0x0, 0x66,0x0, 0x65,0x0, 0x64,0x0, 0x63, +0x0, 0x62,0x0, 0x61,0x0, 0x60,0x0, 0x5f,0x0, 0x5e,0x0, 0x5d,0x0, 0x5c,0x0, 0x5b, +0x0, 0x5a,0x0, 0x59,0x0, 0x58,0x0, 0x57,0x0, 0x56,0x0, 0x55,0x0, 0x54,0x0, 0x53, +0x0, 0x52,0x0, 0x51,0x0, 0x50,0x0, 0x4f,0x0, 0x4e,0x0, 0x4d,0x0, 0x4c,0x0, 0x4b, +0x0, 0x4a,0x0, 0x49,0x0, 0x48,0x0, 0x47,0x0, 0x46,0x0, 0x45,0x0, 0x44,0x0, 0x43, +0x0, 0x42,0x0, 0x41,0x0, 0x40,0x0, 0x3f,0x0, 0x3e,0x0, 0x3d,0x0, 0x3c,0x0, 0x3b, +0x0, 0x3a,0x0, 0x39,0x0, 0x38,0x0, 0x37,0x0, 0x36,0x0, 0x35,0x0, 0x34,0x0, 0x33, +0x0, 0x32,0x0, 0x31,0x0, 0x30,0x0, 0x2f,0x0, 0x2e,0x0, 0x2d,0x0, 0x2c,0x0, 0x2b, +0x0, 0x2a,0x0, 0x29,0x0, 0x28,0x0, 0x27,0x0, 0x26,0x0, 0x25,0x0, 0x24,0x0, 0x23, +0x0, 0x22,0x0, 0x21,0x0, 0x20,0x0, 0x1f,0x0, 0x1e,0x0, 0x1d,0x0, 0x1c,0x0, 0x1b, +0x0, 0x1a,0x0, 0x19,0x0, 0x18,0x0, 0x17,0x0, 0x16,0x0, 0x15,0x0, 0x14,0x0, 0x13, +0x0, 0x12,0x0, 0x11,0x0, 0x10,0x0, 0xf, 0x0, 0xe, 0x0, 0xd, 0x0, 0xc, 0x0, 0xb, +0x0, 0xa, 0x0, 0x9, 0x0, 0x8, 0x0, 0x7, 0x0, 0x6, 0x0, 0x5, 0x0, 0x4, 0x0, 0x3, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x1e,0x10,0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x6, 0x0, +0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, +0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x0, 0x6, 0x1e,0x10,0x3, 0x5, 0x0, +0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, +0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, +0x0, 0x5, 0x1e,0x10,0x3, 0x5, 0x1, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, +0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, +0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x1e,0x10,0x3, 0x5, 0x2, 0x0, 0x0, +0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, +0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x5, +0x1, 0xa, 0x1e,0x40,0x8, 0x0, 0x64,0xd, 0xac,0x0, 0xc8,0x1, 0x9a,0x1, 0x36,0x1, +0x36,0x2, 0xbc,0x2, 0x58,0x2, 0x58,0x1, 0x90,0x1, 0x90,0xa, 0x0, 0x2, 0x0, 0x1, +0xa, 0x6, 0x21,0x3c,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16,0x1, 0x0, 0x1, 0x87,0x1, 0x0, 0x9, +0x1, 0xe9,0x0, 0x1, 0x0, 0x15,0x1, 0x1, 0x4, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d,0x0, 0x0, 0x0, 0x0, 0x0, 0xff,0x0, +0x64,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x40,0x3, 0xc0,0x4, 0x38, +0x2, 0x1c,0x3c,0x3c,0x1, 0xe0,0x1, 0xe0,0x0, 0xf0,0x0, 0xf0,0x7, 0x80,0x3, 0xc0, +0x40,0x40,0x2, 0x0, 0x2, 0x0, 0x1, 0x0, 0x1, 0x0, 0x12,0x0, 0xb4,0x2, 0x1c,0x3, +0x84,0x0, 0x0, 0x7, 0xf2,0x1, 0x2c,0x0, 0x43,0x0, 0x4, 0x1, 0x5, 0x2, 0x2, 0x4, +0x4, 0x6, 0x80,0x0, 0xc8,0x13,0x88,0x10,0x3, 0x6, 0x1, 0x2c,0x2, 0x58,0x3, 0x20, +0x1f,0x40,0x28,0x1, 0x5e,0x2, 0xbc,0x0, 0x14,0x10,0x5, 0xf, 0x3, 0x34,0x1, 0x9a, +0x6, 0x68,0x0, 0x64,0x4, 0x14,0x8, 0x0, 0x0, 0x4, 0x38,0x0, 0x0, 0x7, 0x80,0x0, +0x14,0x1, 0xf4,0x1, 0xf4,0x3, 0x20,0x0, 0xc8,0x0, 0x6c,0x0, 0x1e,0x0, 0x80,0x2, +0x1c,0x1, 0xe0,0x0, 0x64,0x7, 0xd0,0x1, 0xe0,0x2, 0x1c,0x0, 0x64,0x7, 0xd0,0x0, +0x0, 0x4, 0x38,0x0, 0x0, 0x7, 0x80,0x0, 0x64,0x0, 0xa0,0x0, 0xa0,0x9, 0xc4,0x1, +0x2c,0xc2,0xd5,0x7c,0xb4,0x30,0xe7,0x8, 0xb2,0xd5,0x6e,0x24,0xff,0xff,0xb, 0x24, +0x7c,0xb6,0x30,0xe7,0x12,0xb2,0xd5,0x6e,0x34,0xff,0xff,0xb, 0x34,0x8d,0x32,0x6e, +0x24,0xff,0xff,0xb, 0x24,0x80,0x2, 0x8d,0x32,0x30,0xd5,0x6, 0x6e,0x34,0xff,0xff, +0xb, 0x34,0x22,0x7d,0x51,0xad,0x3, 0x7d,0x2, 0x7d,0x21,0xad,0x5, 0x2d,0x12,0xad, +0x35,0x2d,0x21,0x22,0x7d,0x2, 0xad,0x31,0xad,0x10,0x2d,0x21,0x22,0x6d,0x0, 0x74, +0x10,0x4d,0x0, 0x78,0xb, 0x4d,0x22,0x78,0x27,0x8d,0x31,0x7d,0x12,0x6d,0x22,0x22, +0x7d,0x43,0x7d,0x32,0x6d,0x22,0x2f,0x11,0x2d,0x44,0x50,0x2, 0xa5,0xf, 0xbf,0x10, +0x40,0x4, 0x9f,0x10,0xb, 0x90,0x14,0x78,0xed,0x7f,0x1, 0x6d,0x22,0x7d,0x34,0x22, +0x7d,0x41,0x7d,0x13,0x8d,0x24,0x7d,0x2, 0x2f,0x0, 0x40,0x4, 0xbd,0x4, 0x40,0x4, +0x9d,0x4, 0xb, 0x14,0x14,0x78,0xf1,0x7d,0x23,0x7d,0x31,0x7d,0x10,0x6d,0x0, 0x22, +0xc2,0xd5,0x7c,0xb0,0x30,0xe7,0x8, 0xb2,0xd5,0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x7c, +0xb4,0x30,0xe7,0x13,0xb2,0xd5,0x9f,0x22,0x9f,0x21,0x7f,0x12,0x12,0x22,0xbf,0x9f, +0x22,0x9f,0x20,0x7f,0x2, 0x80,0x3, 0x12,0x22,0xbf,0x30,0xd5,0x6, 0x9f,0x22,0x9f, +0x21,0x7f,0x12,0x22,0x6c,0xaa,0x4d,0x11,0x68,0x1a,0x1e,0x54,0x68,0xe, 0xb, 0x38, +0x20,0x1b,0x18,0x20,0xb, 0x35,0xb, 0x15,0x1b,0x54,0x78,0xf2,0x50,0x6, 0x7e,0x39, +0x40,0x7a,0x19,0x40,0x22,0x6c,0xaa,0x4d,0x11,0x68,0x1e,0x1e,0x54,0x50,0xc, 0x7e, +0x1b,0x0, 0x7a,0x19,0x0, 0x68,0x12,0xb, 0x1c,0xb, 0x14,0xb, 0x1a,0x0, 0x1b,0x18, +0x0, 0xb, 0x1d,0xb, 0x15,0x1b,0x54,0x78,0xf2,0x22,0x75,0x84,0x1, 0x7e,0x44,0x7f, +0xff,0xe4,0x7a,0x49,0xb0,0x1b,0x44,0x78,0xf9,0x7e,0xf8,0x73,0x60,0xc2,0x23,0xc2, +0x1b,0xc2,0x1c,0xc2,0x25,0xc2,0x1d,0xd2,0x1e,0xc2,0x1f,0xc2,0x20,0x75,0x16,0x0, +0x75,0x17,0x0, 0xc2,0x26,0xc2,0x12,0xc2,0x13,0xc2,0x14,0xd2,0x15,0xd2,0x16,0xc2, +0x17,0xc2,0x18,0xc2,0x19,0xc2,0x1a,0x75,0x12,0x64,0xc2,0x27,0xc2,0xb, 0xc2,0xc, +0xc2,0xd, 0xc2,0xe, 0xc2,0xf, 0xc2,0x10,0xc2,0x11,0xc2,0x28,0xc2,0x29,0xd2,0x21, +0xc2,0x22,0x75,0x1b,0x0, 0x75,0x1c,0x1, 0x7e,0x4, 0x0, 0xff,0x7e,0x14,0x26,0xa5, +0xb, 0xa, 0x40,0x5d,0x44,0x68,0x1a,0x69,0x20,0x0, 0x2, 0xb, 0xe, 0xb, 0x44,0x80, +0xa, 0x7e,0xb, 0xb0,0x7a,0x29,0xb0,0xb, 0x24,0xb, 0xc, 0x1b,0x44,0x78,0xf2,0x80, +0xdf,0x2, 0x30,0x5, 0xca,0xf8,0x7f,0x20,0x80,0xa, 0x7e,0x1b,0xf0,0x7a,0x2b,0xf0, +0xb, 0x34,0xb, 0x54,0x69,0xff,0xff,0xfc,0x7d,0xef,0x1b,0xe4,0x79,0xef,0xff,0xfc, +0x4d,0xff,0x78,0xe6,0x7f,0x10,0xda,0xf8,0x22,0x7d,0x43,0x7f,0x10,0x80,0x7, 0x1b, +0x44,0x7a,0xb, 0xb0,0xb, 0x14,0x4d,0x44,0x78,0xf5,0x22,0xff,0x0, 0x1, 0x2, 0x0, +0xff,0x1, 0x2, 0x0, 0x1, 0xff,0x2, 0x0, 0x1, 0x2, 0xff,0x7d,0x23,0xbe,0x24,0x0, +0x0, 0x48,0x3, 0x7d,0x32,0x22,0x6d,0x33,0x9d,0x32,0x22,0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4d,0x40,0x1, 0x0, 0x1, 0x4d,0x46,0x1, 0x0, +0x1, 0x4d,0x48,0x3, 0x0, 0x3, 0x51,0xd4,0x0, 0x0, 0x0, 0x0, 0x6, 0x51,0xd7,0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x51,0xdd,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x1, 0x3, 0xff,0x1, 0x0, 0x2, 0x71,0xb6,0x0, 0x0, 0x0, 0x1, 0x70,0xe4,0xff,0x0, +0x8, 0x6f,0xad,0x5, 0x0, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0xc, 0x6f,0xdd,0x3, +0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x1, 0x73,0x5d,0x0, +0x0, 0x1, 0x72,0x5, 0x0, 0x0, 0x1, 0x72,0x49,0xff,0x0, 0x1, 0x72,0x4a,0xff,0x0, +0x2, 0x73,0x5b,0x0, 0x0, 0x0, 0x1, 0x72,0xce,0x0, 0x0, 0x1, 0x28,0x9f,0xff,0x0, +0x1, 0x28,0xb7,0x0, 0x0, 0x2, 0x28,0xb8,0x0, 0x0, 0x0, 0x4, 0x28,0xba,0x0, 0x0, +0x0, 0x0, 0x0, 0x1, 0x29,0xfd,0x1, 0x0, 0x1, 0x29,0xfe,0x0, 0x0, 0x2, 0x70,0xe2, +0x0, 0x0, 0x0, 0x6, 0x73,0x46,0x3f,0x1f,0x50,0x11,0x20,0x10,0x0, 0x1, 0x73,0x4c, +0x34,0x0, 0x2, 0x71,0xbc,0x0, 0x5, 0x0, 0x1, 0x72,0x1, 0xff,0x0, 0x1, 0x72,0x2, +0xff,0x0, 0x1, 0x73,0x5f,0x0, 0x0, 0x1, 0x72,0xfe,0x0, 0x0, 0x1, 0x73,0x0, 0x0, +0x0, 0x1, 0x73,0x3, 0x3, 0x0, 0x1, 0x73,0x7, 0x4, 0x0, 0x1, 0x73,0x8, 0x1, 0x0, +0x1, 0x73,0xa, 0x0, 0x0, 0x1, 0x3, 0xfe,0x1, 0x0, 0x1, 0x73,0x60,0x1, 0x0, 0x1, +0x73,0x2c,0x0, 0x0, 0x2, 0x24,0x2b,0x24,0x31,0x0, 0x1, 0x27,0xf1,0x2, 0x0, 0x1, +0x72,0x4b,0xff,0x0, 0x1, 0x72,0x4e,0x40,0x0, 0x1, 0x72,0x4f,0x40,0x0, 0x4, 0x73, +0x4d,0x0, 0x0, 0x90,0x0, 0x0, 0x4, 0x73,0x20,0x0, 0x0, 0x94,0x0, 0x0, 0x4, 0x73, +0x24,0x0, 0x0, 0x98,0x0, 0x0, 0x4, 0x73,0x28,0x0, 0x0, 0x9c,0x0, 0x0, 0x4, 0x1, +0x5b,0x0, 0x0, 0x80,0x0, 0x0, 0x4, 0x73,0x51,0x0, 0x0, 0x91,0x0, 0x0, 0x4, 0x73, +0x55,0x0, 0x0, 0x92,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x3, 0xe8,0x0, 0x51,0x0, 0x3, 0x3, 0x20,0x0, 0x50,0x0, 0x3, 0x2, +0x58,0x0, 0x4e,0x0, 0x4, 0x1, 0xc2,0x0, 0x4b,0x0, 0x4, 0x1, 0x40,0x0, 0x47,0x0, +0x4, 0x0, 0xc8,0x0, 0x44,0x0, 0x4, 0x0, 0x78,0x0, 0x3e,0x0, 0x5, 0x0, 0x64,0x0, +0x3c,0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12,0x72, +0x26,0x7a,0xb3,0x73,0x1f,0xe4,0x7a,0xb3,0x71,0x58,0x2, 0x28,0x82,0xd2,0x1, 0x12, +0x51,0x13,0x74,0x1f,0x7a,0xb3,0x6d,0xfc,0x7a,0xb3,0x6d,0xfd,0x22,0xca,0x7b,0xca, +0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0, +0x82,0x12,0x2a,0x1a,0x5e,0x34,0x80,0x0, 0x68,0x24,0xb, 0xa, 0x30,0x5e,0x34,0x80, +0x0, 0x68,0x1b,0x12,0x60,0x62,0x6e,0x70,0x40,0x1b,0xa, 0x30,0x7e,0xf, 0x73,0x51, +0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x60,0x80,0x12,0x2a,0x23,0x12,0x5b,0x0, 0x12,0x2a, +0x1a,0x5e,0x34,0x0, 0x2, 0x68,0x17,0xb, 0xa, 0x30,0x5e,0x34,0x0, 0x2, 0x68,0xe, +0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x2, 0x12,0x2a,0x23,0x12,0x5b,0x0, 0x12,0x2a, +0x1a,0x5e,0x34,0x0, 0x1, 0x68,0x20,0xb, 0xa, 0x30,0x5e,0x34,0x0, 0x1, 0x68,0x17, +0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x12,0x4b,0x36,0x12,0x2a, +0x29,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x12,0x2a,0x1a,0x5e,0x34,0x0, 0x8, 0x68,0x17, +0xb, 0xa, 0x30,0x5e,0x34,0x0, 0x8, 0x68,0xe, 0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70, +0x8, 0x1b,0xa, 0x30,0x12,0x4b,0x14,0x12,0x2a,0x1a,0x5e,0x34,0x0, 0x4, 0x68,0x17, +0xb, 0xa, 0x30,0x5e,0x34,0x0, 0x4, 0x68,0xe, 0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70, +0x4, 0x1b,0xa, 0x30,0x12,0x4a,0xf9,0x12,0x2a,0x1a,0x5e,0x34,0x40,0x0, 0x68,0x31, +0xb, 0xa, 0x30,0x5e,0x34,0x40,0x0, 0x68,0x28,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x60, +0x40,0x1b,0xa, 0x30,0xd2,0xc, 0x7e,0xb3,0x72,0xfc,0xbe,0xb0,0xc8,0x50,0x5, 0x4, +0x7a,0xb3,0x72,0xfc,0x7e,0xb3,0x72,0xfc,0xb4,0x1, 0x6, 0x12,0x28,0x82,0x12,0x2a, +0x46,0x12,0x2a,0x1a,0x5e,0x34,0x20,0x0, 0x68,0x19,0xb, 0xa, 0x30,0x5e,0x34,0x20, +0x0, 0x68,0x10,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x60,0x20,0x1b,0xa, 0x30,0xd2,0xc, +0x12,0x2a,0x46,0x12,0x2a,0x1a,0x5e,0x34,0x10,0x0, 0x68,0x26,0xb, 0xa, 0x30,0x7d, +0x23,0x5e,0x24,0x10,0x0, 0x68,0x1b,0x5e,0x34,0x8, 0x0, 0x2e,0x34,0xff,0xff,0x92, +0xf, 0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x60,0x8, 0x1b,0xa, 0x30,0x12,0xd0,0x7d,0x12, +0xd2,0xf8,0x12,0x2a,0x1a,0x5e,0x34,0x0, 0x40,0x68,0x1a,0xb, 0xa, 0x30,0x5e,0x34, +0x0, 0x40,0x68,0x11,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x40,0x1b,0xa, 0x30,0x74, +0xd, 0x7a,0xb3,0x72,0xff,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda, +0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7e,0xf, 0x73,0x51,0x69,0x30, +0x0, 0x4, 0x22,0x1b,0xa, 0x30,0x12,0x2a,0x35,0x7e,0xf, 0x73,0x51,0x2e,0x14,0x0, +0x14,0xb, 0xa, 0x30,0x22,0xd2,0xb, 0xd2,0xe, 0x12,0x4a,0xf0,0x5e,0x34,0x0, 0x1, +0x78,0x3, 0x2, 0x4b,0xa, 0x22,0x30,0x22,0x16,0xa9,0xd2,0xea,0xa9,0xc2,0xea,0x12, +0xdd,0x2c,0xc2,0x22,0x12,0x2a,0x29,0x12,0x2f,0xfe,0xc2,0x21,0x2, 0x4b,0x25,0x22, +0xe4,0x7a,0xb3,0x3, 0xce,0x12,0xcf,0xb8,0x12,0xcf,0xc4,0x12,0x2a,0x29,0x12,0x2f, +0xfe,0xc2,0x2, 0x12,0x2a,0x86,0x12,0xd1,0x8e,0xbe,0xb0,0x1, 0x68,0x3, 0x12,0xd0, +0xc1,0xd2,0x2, 0x2, 0x2a,0x86,0xa2,0xac,0x92,0x3, 0xc2,0xac,0x7e,0xf, 0x73,0x51, +0x30,0x2, 0xa, 0xb, 0x16,0xb, 0xa, 0x30,0x4e,0x70,0x3, 0x80,0x8, 0xb, 0x16,0xb, +0xa, 0x30,0x5e,0x70,0xfc,0x1b,0xa, 0x30,0xa2,0x3, 0x92,0xac,0x22,0xca,0x3b,0x6d, +0x33,0x7a,0x37,0x51,0xc0,0x7e,0x8, 0x4d,0x51,0x12,0x56,0xed,0x12,0x42,0x7a,0x7e, +0x34,0x1, 0x0, 0x12,0x7, 0x40,0x7a,0x37,0x5d,0x59,0x7e,0x34,0x1, 0x1, 0x12,0x7, +0x40,0x7a,0x37,0x5d,0x5d,0x7e,0x34,0x1, 0x2, 0x12,0x7, 0x40,0x7a,0x37,0x5d,0x5f, +0x7e,0x34,0x1, 0x6, 0x12,0x7, 0x40,0x7a,0x37,0x5d,0x5b,0x7e,0x34,0x1, 0x0, 0x6d, +0x22,0x12,0xde,0x1f,0x6d,0x22,0x12,0xde,0x17,0x7e,0x24,0x7, 0x8, 0x12,0xde,0xf, +0x7e,0x24,0x7, 0x8, 0x12,0xde,0x7, 0x7e,0x24,0x7, 0xe, 0x12,0xdd,0xff,0x7e,0x24, +0x7, 0xe, 0x12,0x6, 0xc5,0x12,0xdd,0x46,0x5e,0x24,0xfc,0x0, 0x12,0xdd,0x43,0x5e, +0x24,0xfc,0x0, 0x12,0x6, 0xc5,0x6d,0x33,0x12,0x7, 0x40,0x7a,0x37,0x5d,0x4f,0x7e, +0x34,0x0, 0x1, 0x12,0x7, 0x40,0x7a,0x37,0x5d,0x51,0x7e,0x34,0x0, 0x2, 0x12,0x7, +0x40,0x7a,0x37,0x5d,0x53,0x7e,0x34,0x0, 0x8, 0x12,0x7, 0x40,0x7a,0x37,0x5d,0x55, +0x7e,0x34,0x0, 0x17,0x12,0x7, 0x40,0x7a,0x37,0x5d,0x57,0x12,0x2f,0xf7,0x5e,0x50, +0xe0,0x4e,0x50,0xa, 0x12,0x2f,0xf4,0x5e,0x50,0xe0,0x4e,0x50,0xa, 0x12,0x6, 0xc5, +0x12,0xdd,0x76,0x5e,0x24,0x80,0x0, 0x12,0xdd,0x73,0x5e,0x24,0x80,0x0, 0x12,0x6, +0xc5,0x12,0xdd,0x6a,0x5e,0x40,0x9c,0x4e,0x40,0x21,0x12,0xdd,0x67,0x5e,0x40,0x9c, +0x4e,0x40,0x21,0x12,0x6, 0xc5,0x12,0xdd,0x5e,0x4e,0x40,0x40,0x12,0xdd,0x5b,0x4e, +0x40,0x40,0x12,0x6, 0xc5,0x12,0xdd,0x52,0x5e,0x24,0xe0,0x3f,0x12,0xdd,0x4f,0x5e, +0x24,0xe0,0x3f,0x12,0x6, 0xc5,0x12,0xdc,0xed,0x6d,0x66,0x80,0x34,0x12,0x2f,0xeb, +0x7e,0xb3,0x69,0x9e,0x70,0x14,0x7d,0x57,0x12,0x2f,0x11,0x60,0x5, 0x3e,0x14,0x14, +0x78,0xfb,0x12,0x2f,0x1a,0x12,0x2f,0xd6,0x80,0x12,0x7d,0x57,0x12,0x2f,0x11,0x60, +0x5, 0x3e,0x14,0x14,0x78,0xfb,0x12,0x2f,0x1a,0x12,0x2f,0xdd,0x12,0x35,0x7d,0xb, +0x64,0x12,0x2f,0xe4,0xbd,0x36,0x38,0xc5,0x7e,0xb3,0x69,0x90,0x54,0x1, 0xb4,0x1, +0xb, 0x7e,0x37,0x5d,0x7, 0x4e,0x70,0x1, 0x7a,0x37,0x5d,0x7, 0x12,0x2f,0x25,0xca, +0x39,0x7e,0x18,0xc, 0xd0,0x7e,0x8, 0x4d,0x51,0x12,0x24,0x14,0x1b,0xfd,0x7e,0x34, +0x0, 0x1, 0x81,0xd3,0x12,0xdc,0xed,0x7e,0x73,0x69,0x8d,0xa, 0x27,0x7e,0x35,0x26, +0xad,0x32,0x7d,0x63,0x80,0x61,0x12,0x2f,0xeb,0x7e,0x73,0x69,0x8a,0xa, 0x37,0xbe, +0x35,0x26,0x28,0x22,0x7e,0xb3,0x69,0x9e,0x70,0xe, 0x7d,0x57,0x12,0x2f,0x11,0x60, +0x3b,0x3e,0x14,0x14,0x78,0xfb,0x80,0x34,0x7d,0x57,0x12,0x2f,0x11,0x60,0x19,0x3e, +0x14,0x14,0x78,0xfb,0x80,0x12,0x7e,0xb3,0x69,0x9e,0x70,0x14,0x7d,0x57,0x12,0x2f, +0x11,0x60,0x5, 0x3e,0x14,0x14,0x78,0xfb,0x12,0x2f,0x1a,0x12,0x2f,0xdd,0x80,0x12, +0x7d,0x57,0x12,0x2f,0x11,0x60,0x5, 0x3e,0x14,0x14,0x78,0xfb,0x12,0x2f,0x1a,0x12, +0x2f,0xd6,0x12,0x35,0x7d,0xb, 0x64,0x7e,0x25,0x26,0xb, 0x24,0x12,0x2f,0xe4,0xad, +0x32,0xbd,0x36,0x38,0x91,0x7e,0xb3,0x69,0x90,0x54,0x4, 0xb4,0x4, 0xb, 0x7e,0x37, +0x5d,0x7, 0x4e,0x70,0x4, 0x7a,0x37,0x5d,0x7, 0x12,0x2f,0x25,0xca,0x39,0x7e,0x18, +0xc, 0xd0,0x7e,0x8, 0x5d,0x61,0x12,0x24,0x14,0x1b,0xfd,0x12,0x5f,0xfe,0x7e,0x35, +0x26,0xb, 0x34,0x7a,0x35,0x26,0x7e,0x73,0x69,0x8c,0xa, 0x37,0xbe,0x35,0x26,0x28, +0x2, 0x81,0x24,0x6d,0x33,0xa1,0x8b,0x12,0xdc,0xed,0x7e,0x65,0x26,0x80,0x61,0x12, +0x2f,0xeb,0x7e,0x37,0x69,0x92,0xbd,0x36,0x28,0x22,0x7e,0xb3,0x69,0x9e,0x70,0xe, +0x7d,0x57,0x12,0x2f,0x11,0x60,0x3b,0x3e,0x14,0x14,0x78,0xfb,0x80,0x34,0x7d,0x57, +0x12,0x2f,0x11,0x60,0x19,0x3e,0x14,0x14,0x78,0xfb,0x80,0x12,0x7e,0xb3,0x69,0x9e, +0x70,0x14,0x7d,0x57,0x12,0x2f,0x11,0x60,0x5, 0x3e,0x14,0x14,0x78,0xfb,0x12,0x2f, +0x1a,0x12,0x2f,0xdd,0x80,0x12,0x7d,0x57,0x12,0x2f,0x11,0x60,0x5, 0x3e,0x14,0x14, +0x78,0xfb,0x12,0x2f,0x1a,0x12,0x2f,0xd6,0x12,0x35,0x7d,0x12,0x2f,0xe4,0x2d,0x63, +0x7e,0xa3,0x69,0x8d,0x7e,0xb3,0x69,0x8c,0xa4,0xbd,0x56,0x38,0x92,0x7e,0xb3,0x69, +0x91,0x54,0x1, 0xb4,0x1, 0xb, 0x7e,0x37,0x5d,0x2b,0x4e,0x70,0x1, 0x7a,0x37,0x5d, +0x2b,0x12,0x2f,0x25,0xca,0x39,0x7e,0x18,0xc, 0xd0,0x7e,0x8, 0x5d,0x61,0x12,0x24, +0x14,0x1b,0xfd,0x12,0x5f,0xfe,0x7e,0x35,0x26,0xb, 0x34,0x7a,0x35,0x26,0x12,0x2f, +0xe4,0xbe,0x35,0x26,0x28,0x2, 0x81,0xe7,0x12,0xdc,0xed,0x7e,0xb3,0x69,0x91,0x54, +0x4, 0xb4,0x4, 0xb, 0x7e,0x37,0x5d,0x2b,0x4e,0x70,0x4, 0x7a,0x37,0x5d,0x2b,0x12, +0x2f,0x25,0xca,0x39,0x7e,0x18,0xc, 0xd0,0x7e,0x8, 0x5d,0x61,0x12,0x24,0x14,0x1b, +0xfd,0x12,0x5f,0xfe,0x6d,0x66,0x7d,0x26,0x3e,0x24,0x49,0x32,0x4d,0x51,0xbe,0x34, +0x2, 0x0, 0x28,0xf, 0x7d,0x12,0x2e,0x14,0x4d,0x51,0x9e,0x34,0x2, 0x0, 0x1b,0x18, +0x30,0x80,0x6, 0x6d,0x33,0x59,0x32,0x4d,0x51,0xb, 0x64,0xbe,0x64,0x2, 0x34,0x78, +0xd5,0x7e,0x34,0x4d,0x51,0x7a,0x37,0x51,0xbe,0xe4,0x7a,0xb3,0x71,0x68,0x7a,0xb3, +0x71,0x67,0x12,0x2f,0xf7,0x12,0x2f,0xf4,0x12,0x6, 0xc5,0x12,0xdd,0x76,0x12,0xdd, +0x73,0x12,0x6, 0xc5,0x12,0xdd,0x6a,0x12,0xdd,0x67,0x12,0x6, 0xc5,0x12,0xdd,0x5e, +0x12,0xdd,0x5b,0x12,0x6, 0xc5,0x12,0xdd,0x52,0x12,0xdd,0x4f,0x12,0x6, 0xc5,0x7e, +0x34,0x1, 0x0, 0x7e,0x27,0x5d,0x59,0x12,0xde,0x1f,0x7e,0x27,0x5d,0x59,0x12,0xde, +0x17,0x7e,0x27,0x5d,0x5d,0x12,0xde,0xf, 0x7e,0x27,0x5d,0x5d,0x12,0xde,0x7, 0x7e, +0x27,0x5d,0x5f,0x12,0xdd,0xff,0x7e,0x27,0x5d,0x5f,0x12,0x6, 0xc5,0x12,0xdd,0x46, +0x12,0xdd,0x43,0x12,0x6, 0xc5,0x6d,0x66,0x80,0x5e,0x12,0x2f,0xeb,0x7e,0x37,0x69, +0x92,0xbd,0x36,0x28,0x22,0x7e,0xb3,0x69,0x9e,0x70,0xe, 0x7d,0x57,0x12,0x2f,0x11, +0x60,0x3b,0x3e,0x14,0x14,0x78,0xfb,0x80,0x34,0x7d,0x57,0x12,0x2f,0x11,0x60,0x19, +0x3e,0x14,0x14,0x78,0xfb,0x80,0x12,0x7e,0xb3,0x69,0x9e,0x70,0x14,0x7d,0x57,0x12, +0x2f,0x11,0x60,0x5, 0x3e,0x14,0x14,0x78,0xfb,0x12,0x2f,0x1a,0x12,0x2f,0xdd,0x80, +0x12,0x7d,0x57,0x12,0x2f,0x11,0x60,0x5, 0x3e,0x14,0x14,0x78,0xfb,0x12,0x2f,0x1a, +0x12,0x2f,0xd6,0x12,0x35,0x7d,0xb, 0x64,0x7e,0x37,0x69,0x94,0x2e,0x37,0x69,0x92, +0xbd,0x36,0x38,0x96,0x7e,0x34,0x1, 0x16,0x7e,0x8, 0x5d,0x7, 0x12,0xdd,0xe1,0x7e, +0x34,0x1, 0x16,0x7e,0x8, 0x5d,0x2b,0x12,0xdd,0xe8,0x12,0x51,0xda,0x12,0x52,0x38, +0x12,0x4f,0xf3,0xda,0x3b,0x22,0x7e,0x35,0x39,0x3e,0x34,0x49,0x23,0x69,0x9f,0x7a, +0x27,0x5f,0x73,0x7f,0x3, 0x2e,0x15,0x39,0x7e,0xb, 0x70,0x19,0x72,0x1, 0x77,0x7d, +0x52,0x5e,0x54,0x0, 0xf, 0x7e,0x14,0x0, 0x1, 0x22,0x7d,0x27,0x1e,0x24,0x1e,0x24, +0x1e,0x24,0x1e,0x24,0x22,0x7e,0x34,0x1, 0x16,0x7e,0x8, 0x5d,0x7, 0x7e,0x24,0x0, +0x12,0x12,0x3, 0xfa,0x7e,0x34,0x1, 0x16,0x7e,0x8, 0x5d,0x2b,0x7e,0x24,0x0, 0x12, +0x12,0x4, 0x96,0x12,0x2a,0x60,0xd2,0x2, 0x12,0x2f,0x50,0x7e,0x34,0x4, 0x68,0x22, +0x7e,0xb3,0x3, 0xce,0xbe,0xb0,0x1, 0x68,0xf7,0x30,0x2, 0x3, 0x2, 0xb, 0xe5,0x22, +0xca,0x3b,0xc2,0x2, 0x12,0x2a,0x86,0xc2,0xc, 0x30,0xb, 0x11,0xc2,0xb, 0x12,0x40, +0xe6,0x12,0x3e,0xdc,0x12,0x3f,0xa3,0x12,0x47,0x8d,0x12,0x28,0x7d,0xd2,0x2, 0x12, +0x2a,0x86,0xc2,0x1, 0x12,0xcc,0xef,0x30,0xd, 0x44,0xc2,0xd, 0x7e,0x3f,0x73,0x51, +0x69,0x33,0x0, 0x6, 0x7d,0x23,0x5e,0x24,0x0, 0x1, 0x68,0x32,0x5e,0x34,0x0, 0x2, +0x68,0x8, 0x12,0x3f,0x84,0x12,0x5, 0xbc,0x80,0x11,0x75,0x1b,0x1, 0x74,0x1, 0x7a, +0xb3,0x73,0x8, 0x7f,0x3, 0x12,0x60,0x62,0x12,0x2f,0xfe,0x12,0x3f,0xa3,0xc2,0x1, +0x12,0x51,0x13,0xe5,0x1b,0x12,0x3f,0x3a,0x74,0x1f,0x7a,0xb3,0x6d,0xfd,0xd2,0x1, +0x12,0xcc,0xef,0xda,0x3b,0x22,0x3e,0x24,0x2e,0x24,0x5d,0x7, 0x22,0x3e,0x24,0x2e, +0x24,0x5d,0x2b,0x22,0x7e,0x73,0x69,0x8d,0xa, 0x37,0x22,0x7d,0x36,0x3e,0x34,0x49, +0x73,0x69,0x9f,0x22,0x12,0x6, 0x48,0x6d,0x33,0x7e,0x27,0x5d,0x4f,0x22,0x5e,0x70, +0xfb,0x1b,0xa, 0x30,0x22,0x12,0x60,0xdf,0x12,0x30,0x2a,0x12,0x5b,0x7, 0x12,0x40, +0xda,0x12,0x28,0x6e,0x7e,0xb3,0x71,0xd, 0x24,0xfd,0x68,0x9, 0xb, 0xb1,0x78,0xf4, +0x12,0x31,0xe1,0x80,0xef,0x12,0x52,0xb9,0x80,0xea,0x7e,0x34,0x21,0x5b,0x12,0x30, +0xa4,0x12,0x31,0xd6,0x7a,0x73,0x70,0xe6,0x7e,0x34,0x21,0x5d,0x12,0x30,0xa4,0x12, +0x35,0x8e,0x7a,0x73,0x70,0xe7,0x7e,0x34,0x21,0x61,0x12,0x30,0xa4,0x12,0x31,0xd6, +0x7a,0x73,0x70,0xe8,0x7e,0x34,0x21,0x63,0x12,0x30,0xa4,0x12,0x35,0x8e,0x7a,0x73, +0x70,0xe9,0x7e,0x34,0x21,0x6b,0x12,0x30,0xa4,0x12,0x31,0xd6,0x7a,0x73,0x70,0xeb, +0x7e,0x34,0x0, 0x6a,0xca,0x39,0x7e,0x34,0x21,0x6f,0x7e,0x24,0x0, 0xff,0x7e,0x8, +0x70,0xec,0x12,0x24,0x14,0x1b,0xfd,0x22,0x7a,0x37,0x69,0x6f,0xe4,0x7a,0xb3,0x73, +0x5e,0x7e,0x34,0x21,0x67,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30,0x7a,0x37,0x69,0x79, +0x7e,0x34,0x21,0x69,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30,0x22,0x90,0x21,0x51,0xe4, +0x93,0x7a,0xb3,0x69,0x6b,0x12,0x35,0xb6,0x7e,0x34,0x21,0x5b,0x12,0x30,0xa4,0x7a, +0x37,0x69,0x6d,0x7e,0x34,0x21,0x5d,0x12,0x30,0xa4,0x7a,0x37,0x69,0x6f,0x7e,0x34, +0x21,0x5f,0x12,0x30,0xa4,0x12,0x31,0x9e,0x7a,0x37,0x69,0x71,0x7e,0x34,0x21,0x61, +0x12,0x30,0xa4,0x7a,0x37,0x69,0x73,0x7e,0x34,0x21,0x63,0x12,0x30,0xa4,0x7a,0x37, +0x69,0x75,0x7e,0x34,0x21,0x65,0x12,0x30,0xa4,0x12,0x31,0x9e,0x7a,0x37,0x69,0x77, +0x12,0x30,0x91,0x12,0x31,0x9e,0x7a,0x37,0x69,0x7b,0x90,0x21,0x9b,0xe4,0x93,0x7a, +0xb3,0x69,0x7f,0x90,0x21,0x54,0xe4,0x93,0x7a,0xb3,0x69,0x80,0x7e,0x34,0x21,0x55, +0x12,0x30,0xa4,0x7a,0x37,0x69,0x81,0x7e,0x34,0x21,0x6b,0x12,0x30,0xa4,0x7a,0x37, +0x69,0x7d,0xe4,0x7a,0xb3,0x69,0x83,0x7a,0xb3,0x69,0x84,0x22,0x7e,0xb3,0x71,0x36, +0xb4,0x1, 0x5, 0x12,0x31,0xa5,0x80,0xf, 0x7e,0xb3,0x69,0x89,0xb4,0x1, 0x5, 0x12, +0x35,0x99,0x80,0x3, 0x12,0x76,0x4f,0x7e,0xb3,0x73,0x5e,0x70,0x17,0x7e,0xb3,0x69, +0x5f,0x70,0x11,0x7e,0xb3,0x69,0x89,0x70,0xb, 0x7e,0x34,0x21,0x6d,0x12,0x30,0xa4, +0x7a,0x37,0x69,0x6d,0x12,0xc3,0x8a,0x68,0x16,0x7e,0x34,0x21,0x61,0x12,0x30,0xa4, +0x7a,0x37,0x69,0x73,0x7e,0x34,0x21,0x63,0x12,0x30,0xa4,0x7a,0x37,0x69,0x75,0x7e, +0x34,0x21,0x5f,0x12,0x30,0xa4,0x12,0x31,0x9e,0x7a,0x37,0x69,0x71,0x22,0x6e,0x34, +0xff,0xff,0xb, 0x34,0x22,0x7e,0x34,0x21,0x5b,0x12,0x30,0xa4,0x7a,0x37,0x69,0x6d, +0x12,0x35,0xb6,0x7e,0x34,0x21,0x5d,0x12,0x30,0xa4,0x12,0x30,0x88,0x12,0x31,0xc8, +0x12,0x35,0x86,0x7a,0x73,0x70,0xe7,0x22,0x6e,0x34,0xff,0xff,0xb, 0x34,0x7a,0x37, +0x69,0x7b,0x7e,0x37,0x69,0x6d,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34, +0x22,0x30,0x25,0xa, 0xc2,0x25,0x74,0x1, 0x7a,0xb3,0x6d,0xfb,0x80,0x3, 0x12,0x53, +0x95,0x7e,0xb3,0x73,0x1f,0xb4,0x1, 0x2, 0x80,0x2, 0x41,0x8b,0x12,0x73,0x52,0x12, +0xd1,0xc8,0x12,0x32,0xc4,0x12,0x53,0xbc,0x7e,0x34,0x21,0x59,0x12,0x30,0xa4,0x12, +0x47,0xd6,0x12,0x7e,0x8c,0x7e,0xb3,0x24,0x26,0x70,0x2, 0x80,0x24,0x12,0xb3,0x8b, +0x7e,0xb3,0x71,0xa, 0xb4,0x1, 0x2, 0xd2,0x87,0x12,0x94,0x76,0x7e,0xb3,0x69,0x84, +0x70,0x6, 0x12,0x31,0x3c,0x12,0xd9,0xe3,0x12,0x7f,0xa1,0x7e,0xb3,0x24,0x26,0x70, +0x10,0x12,0xb1,0x6b,0x7e,0x73,0x71,0xd, 0x7a,0x73,0x73,0x1f,0x12,0xd5,0xc5,0x80, +0xa0,0x74,0x1, 0x12,0x32,0xa0,0x12,0x35,0xc0,0x12,0x99,0xc2,0x12,0x8b,0x27,0x12, +0x97,0x5b,0x74,0x2, 0x12,0x32,0xa0,0x12,0xa2,0x1b,0x74,0x3, 0x12,0x32,0xa0,0x12, +0xae,0xcc,0x74,0x4, 0x12,0x32,0xa0,0x12,0xb5,0x26,0x12,0x67,0x22,0x12,0x5b,0xbb, +0x12,0x72,0xfa,0x12,0x63,0x4d,0x12,0x73,0x20,0x21,0xf1,0xd2,0x2, 0x12,0x2f,0x50, +0x2, 0x32,0x93,0x12,0xd5,0x2b,0x7e,0xb3,0x71,0xa, 0xb4,0x1, 0x2, 0xd2,0x87,0x22, +0x1b,0xb1,0x68,0x10,0x14,0x68,0x13,0x14,0x68,0x16,0x24,0x3, 0x78,0x15,0xe4,0x7a, +0xb3,0x69,0x69,0x22,0x12,0x0, 0xa, 0x2, 0xaf,0x62,0x12,0xaa,0xce,0x2, 0xa9,0xd2, +0x2, 0xaf,0x8f,0x22,0x7e,0x34,0x70,0xe6,0x20,0x1b,0x2, 0x61,0x53,0xc2,0x1b,0x7e, +0x39,0x50,0xa, 0x25,0x12,0x33,0x6e,0x3e,0x24,0x7a,0x27,0x69,0x6d,0x9, 0x53,0x0, +0x1, 0xa, 0x25,0x12,0x33,0x6e,0x3e,0x24,0x7a,0x27,0x69,0x6f,0x9, 0x53,0x0, 0x2, +0xa, 0x25,0x12,0x33,0x6e,0x3e,0x24,0x7a,0x27,0x69,0x73,0x9, 0x53,0x0, 0x3, 0xa, +0x25,0x12,0x33,0x6e,0x3e,0x24,0x7a,0x27,0x69,0x75,0x9, 0x53,0x0, 0x5, 0xa, 0x25, +0x12,0x33,0x6e,0x3e,0x24,0x7a,0x27,0x69,0x7d,0x9, 0x53,0x0, 0x40,0x7a,0x53,0x69, +0x83,0x9, 0xb3,0x0, 0x41,0xbe,0xb3,0x69,0x89,0x68,0x20,0x7a,0xb3,0x69,0x89,0xd2, +0x27,0xb4,0x1, 0xf, 0x7e,0x73,0x69,0x83,0x7a,0x73,0x70,0xe5,0xe4,0x7a,0xb3,0x69, +0x83,0x80,0x8, 0x7e,0x73,0x70,0xe5,0x7a,0x73,0x69,0x83,0x7e,0x73,0x69,0x83,0x7a, +0x73,0x71,0x26,0x7e,0x37,0x69,0x6d,0x7a,0x37,0x71,0x56,0x4d,0x33,0x78,0xb, 0x7e, +0x34,0x21,0x5b,0x12,0x30,0xa4,0x7a,0x37,0x71,0x56,0x22,0xb, 0x18,0x20,0x3e,0x24, +0x3e,0x24,0x3e,0x24,0x3e,0x24,0x22,0xca,0x3b,0x7f,0x30,0x7c,0xab,0xbe,0xa0,0x4, +0x40,0x2, 0xa1,0x74,0x74,0x27,0xa4,0x9, 0xb5,0x6f,0x15,0xf5,0x3d,0xe4,0x12,0x42, +0x7a,0x7e,0xe7,0x69,0x92,0x7e,0xf7,0x69,0x94,0x2d,0xfe,0x7f,0x13,0x2d,0x3f,0x7a, +0x35,0x3b,0x7e,0x8, 0x5f,0x75,0x12,0xdc,0xf1,0x7e,0xb3,0x69,0x9e,0x60,0x64,0x6d, +0x33,0x80,0x34,0x7e,0x35,0x39,0x3e,0x34,0x49,0x23,0x69,0x9f,0x7a,0x27,0x5f,0x73, +0x7f,0x3, 0x2e,0x15,0x39,0x7e,0xb, 0x70,0x19,0x72,0x2, 0x91,0x12,0x2f,0xf, 0x60, +0x5, 0x3e,0x14,0x14,0x78,0xfb,0x12,0x2f,0x1c,0x3e,0x24,0x2e,0x24,0x5f,0x99,0x12, +0x35,0x7d,0x7e,0x35,0x39,0xb, 0x34,0x7a,0x35,0x39,0xbe,0xe5,0x39,0x38,0xc4,0x7a, +0xe5,0x39,0x80,0x18,0x12,0x2e,0xf6,0x60,0x5, 0x3e,0x14,0x14,0x78,0xfb,0x12,0x2f, +0x1c,0x12,0x35,0x77,0x7e,0x35,0x39,0xb, 0x34,0x7a,0x35,0x39,0xbe,0xf5,0x39,0x38, +0xe3,0x80,0x6b,0x6d,0x33,0x80,0x15,0x12,0x2e,0xf6,0x60,0x5, 0x3e,0x14,0x14,0x78, +0xfb,0x12,0x2f,0x1c,0x12,0x35,0x77,0x7e,0x35,0x39,0xb, 0x34,0x7a,0x35,0x39,0xbe, +0xe5,0x39,0x38,0xe3,0x80,0x40,0x7e,0xe5,0x39,0x3e,0xe4,0x49,0x3e,0x69,0x9f,0x7a, +0x37,0x5f,0x73,0x7f,0x3, 0x2e,0x15,0x39,0x7e,0xb, 0x50,0x19,0x53,0x2, 0x91,0x7d, +0x53,0x5e,0x54,0x0, 0xf, 0x7e,0x24,0x0, 0x1, 0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb, +0x12,0x31,0xd8,0x3e,0x34,0x2e,0x34,0x5f,0x99,0xb, 0x38,0xe0,0x4d,0xe2,0x1b,0x38, +0xe0,0x7e,0xe5,0x39,0xb, 0xe4,0x7a,0xe5,0x39,0xbe,0xf5,0x39,0x38,0xb8,0x7e,0x55, +0x3b,0xb, 0x58,0x20,0x7d,0x32,0x7a,0x73,0x1, 0x77,0x7d,0x15,0x2e,0x14,0x0, 0x0, +0x49,0x31,0x0, 0x2, 0x7d,0x43,0x5e,0x44,0x0, 0xf, 0x3e,0x44,0x3e,0x44,0xa, 0x24, +0x5e,0x24,0x0, 0x3, 0x4d,0x24,0x7a,0x53,0x1, 0x78,0x5e,0x34,0x3, 0xf0,0x12,0x31, +0xd8,0x7a,0x73,0x1, 0x79,0x49,0x25,0x0, 0x4, 0x7d,0x32,0x7a,0x73,0x2, 0x91,0x7d, +0x5, 0xb, 0x6, 0x49,0x30,0x0, 0x2, 0x7d,0x13,0x5e,0x14,0x0, 0xf, 0x3e,0x14,0x3e, +0x14,0xa, 0x24,0x5e,0x24,0x0, 0x3, 0x4d,0x21,0x7a,0x53,0x2, 0x92,0x5e,0x34,0x3, +0xf0,0x12,0x31,0xd8,0x7a,0x73,0x2, 0x93,0x7e,0xb3,0x69,0x90,0x54,0x5, 0xa, 0x3b, +0x4e,0x37,0x5f,0x75,0x7a,0x37,0x5f,0x75,0x7e,0xb3,0x69,0x91,0x54,0x5, 0xa, 0x3b, +0x4e,0x37,0x5f,0x99,0x7a,0x37,0x5f,0x99,0x12,0xdd,0xc7,0x2e,0x74,0x0, 0x16,0x7d, +0x37,0x7e,0x8, 0x5f,0x75,0x12,0xdd,0xe1,0x7d,0x37,0x7e,0x8, 0x5f,0x99,0x12,0xdd, +0xe8,0x12,0xdd,0xc7,0x2e,0x74,0x0, 0x28,0x6d,0x33,0x7a,0x35,0x39,0x7e,0x35,0x39, +0x9, 0x53,0x1, 0x78,0x7c,0x25,0x6c,0x33,0x9, 0x53,0x1, 0x77,0x12,0xdd,0x14,0x40, +0xec,0x7d,0x37,0x7e,0x8, 0x5f,0xbd,0x7e,0x24,0x0, 0x8d,0x12,0x3, 0xfa,0x6d,0x33, +0x7a,0x35,0x39,0x7e,0x35,0x39,0x9, 0x53,0x2, 0x92,0x7c,0x25,0x6c,0x33,0x9, 0x53, +0x2, 0x91,0x12,0xdd,0x14,0x40,0xec,0x7d,0x37,0x7e,0x8, 0x5f,0xbd,0x7e,0x24,0x0, +0x8d,0x12,0x4, 0x96,0xda,0x3b,0x22,0x3e,0x24,0x2e,0x24,0x5f,0x75,0xb, 0x28,0x30, +0x4d,0x31,0x1b,0x28,0x30,0x22,0x7a,0x73,0x70,0xe6,0x7e,0x37,0x69,0x6f,0xe, 0x34, +0xe, 0x34,0xe, 0x34,0xe, 0x34,0xe, 0x34,0x22,0x7e,0x34,0x0, 0xaa,0x7a,0x37,0x69, +0x6d,0x12,0x35,0xb6,0x7e,0x34,0x0, 0x64,0x12,0x30,0x88,0x12,0x31,0xc8,0x12,0x35, +0x86,0x7a,0x73,0x70,0xe7,0x22,0x90,0x21,0x53,0xe4,0x93,0x7a,0xb3,0x69,0x6c,0x22, +0xc2,0x1d,0x7e,0xb3,0x69,0x83,0x70,0x3, 0x12,0x95,0xab,0x12,0x89,0xf5,0x12,0x8a, +0x39,0x12,0x80,0x6d,0x12,0x89,0xf5,0x12,0x8a,0x79,0x12,0x89,0xf5,0x12,0x9c,0xf9, +0x12,0x89,0xf5,0x12,0x81,0xa6,0x12,0x89,0xf5,0x2, 0x35,0xec,0xca,0x3b,0xc2,0x0, +0x7e,0xd3,0x67,0xd5,0xa, 0x3d,0x3e,0x34,0xca,0x39,0x7e,0x18,0x66,0x4b,0x7e,0x8, +0x5d,0x7, 0x12,0x24,0x14,0x1b,0xfd,0x6c,0x11,0x75,0x26,0x0, 0x6c,0xcc,0xc1,0xd0, +0x7e,0x44,0x3, 0xff,0x7e,0xe0,0xff,0x6c,0xff,0x80,0x64,0x7c,0xbf,0x12,0x77,0xb6, +0x60,0x5b,0x74,0x2, 0xac,0xbf,0x9, 0x5, 0x5d,0x7, 0xbe,0x0, 0xff,0x68,0x4e,0x9, +0x5, 0x5d,0x8, 0xa, 0x10,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0x3, 0x72,0xd, 0xa, 0x30, +0x12,0x93,0x24,0x8, 0x4, 0x9d,0x31,0x80,0x4, 0x6d,0x33,0x9d,0x32,0x74,0x2, 0xac, +0xbf,0x9, 0x5, 0x5d,0x7, 0xa, 0xf0,0x74,0x2, 0xac,0xbc,0x9, 0x5, 0x72,0xc, 0xa, +0x10,0x7d,0x21,0x9d,0x2f,0xbe,0x24,0x0, 0x0, 0x8, 0x4, 0x9d,0x1f,0x80,0x4, 0x6d, +0x11,0x9d,0x12,0x2d,0x13,0xbd,0x41,0x28,0x4, 0x7d,0x41,0x7c,0xef,0xb, 0xf0,0xbc, +0xdf,0x38,0x98,0xbe,0xe0,0xff,0x68,0x46,0x7e,0x70,0x2, 0xac,0x7e,0x9, 0xb3,0x5d, +0x7, 0x9, 0x73,0x5d,0x8, 0x12,0x81,0x9d,0x7d,0x13,0x74,0x2, 0xac,0xbe,0x9, 0xb5, +0x5d,0x7, 0x12,0x97,0x88,0xbd,0x13,0x48,0x25,0x7e,0x70,0x2, 0xac,0x7e,0x9, 0x3, +0x5d,0x7, 0x7e,0xa1,0x26,0x74,0x2, 0xa4,0x19,0x5, 0x5d,0x43,0x9, 0x3, 0x5d,0x8, +0x19,0x5, 0x5d,0x44,0x74,0xff,0x19,0xb3,0x5d,0x7, 0xb, 0x10,0x5, 0x26,0xb, 0xc0, +0x7e,0x3, 0x72,0x48,0xbc,0xc, 0x28,0x2, 0xc1,0x10,0x7c,0xc1,0xe1,0x6e,0x6d,0x0, +0x7e,0xe0,0xff,0x6c,0xff,0x80,0x5a,0x7c,0xbf,0x12,0x77,0xb6,0x60,0x51,0x7e,0x30, +0x2, 0xac,0x3f,0x9, 0xb1,0x5d,0x7, 0xbe,0xb0,0xff,0x68,0x43,0x9, 0x71,0x5d,0x8, +0x12,0x81,0x9d,0x7d,0x43,0xc2,0x0, 0xbd,0x4, 0x58,0x2, 0xd2,0x0, 0x30,0x0, 0x2f, +0x7e,0xb3,0x69,0x84,0x60,0x14,0x7e,0x73,0x69,0x60,0xbe,0x70,0x2, 0x40,0xb, 0x7e, +0x37,0x67,0xdb,0x12,0x9e,0xe3,0xbd,0x34,0x18,0x15,0x7e,0x70,0x2, 0xac,0x7f,0x9, +0xb3,0x5d,0x7, 0xf5,0x27,0x9, 0xb3,0x5d,0x8, 0xf5,0x28,0x7d,0x4, 0x7c,0xef,0xb, +0xf0,0xbc,0xdf,0x38,0xa2,0xbe,0xe0,0xff,0x68,0x22,0x7e,0xa1,0x27,0x7e,0x31,0x26, +0x74,0x2, 0xac,0x3b,0x19,0xa1,0x5d,0x43,0xe5,0x28,0x19,0xb1,0x5d,0x44,0x7e,0xa0, +0xff,0x7e,0x30,0x2, 0xac,0x3e,0x19,0xa1,0x5d,0x7, 0x5, 0x26,0xb, 0xc0,0x90,0x21, +0x51,0xe4,0x93,0xbc,0xbc,0x28,0x2, 0xc1,0xde,0x90,0x21,0x52,0xe4,0x93,0x7c,0xab, +0x74,0x2, 0xa4,0xca,0x59,0x7e,0x18,0x5d,0x43,0x7e,0x8, 0x5d,0x7, 0x12,0x24,0x14, +0x1b,0xfd,0x7e,0xd1,0x26,0x12,0x5b,0xb3,0x74,0x2, 0xac,0x7b,0x7e,0x8, 0x72,0xc, +0x74,0xff,0x12,0x24,0x39,0xbe,0xd0,0x0, 0x28,0x37,0xa, 0x3d,0x3e,0x34,0xca,0x39, +0x7e,0x18,0x5d,0x7, 0x7e,0x8, 0x66,0x4b,0x12,0x24,0x14,0x1b,0xfd,0xa, 0x3d,0x3e, +0x34,0xca,0x39,0x7e,0x18,0x5d,0x7, 0x7e,0x8, 0x72,0xc, 0x12,0x24,0x14,0x1b,0xfd, +0x6c,0xcc,0x80,0x9, 0xd2,0x6, 0x7c,0xbc,0x12,0x89,0xc7,0xb, 0xc0,0xbc,0xdc,0x38, +0xf3,0x7a,0xd3,0x72,0x48,0x7a,0xd3,0x67,0xd5,0x90,0x21,0x51,0xe4,0x93,0xbe,0xb3, +0x67,0xd5,0x50,0x4, 0x7a,0xb3,0x67,0xd5,0xda,0x3b,0x22,0xca,0x3b,0x7e,0xf3,0x73, +0x8, 0x7e,0x30,0x27,0xac,0x3f,0x9, 0xb1,0x6f,0x11,0xf5,0x2a,0x9, 0xb1,0x6f,0x12, +0xf5,0x2b,0x7e,0x4, 0x0, 0x27,0xca,0x9, 0x2e,0x14,0x6f,0x11,0x6d,0x0, 0x7e,0x18, +0x71,0x89,0x12,0x24,0x14,0x1b,0xfd,0x74,0x27,0xac,0xbf,0x9, 0xe5,0x6f,0x15,0x7e, +0xd0,0xb5,0xac,0xde,0x2e,0x64,0x1, 0x0, 0xe4,0x12,0x42,0x7a,0x12,0x3a,0x30,0x5e, +0x24,0x1, 0x0, 0x68,0xc, 0x5e,0x60,0xfe,0x7a,0x37,0x4d,0x4d,0x7c,0xbf,0x12,0x48, +0x16,0x12,0x3a,0x30,0x5e,0x24,0x0, 0x1, 0x68,0x2e,0x5e,0x70,0xfe,0x7a,0x37,0x4d, +0x4d,0x7e,0xb3,0x71,0x89,0x12,0x47,0xfe,0x50,0xc, 0x7e,0xb3,0x71,0x89,0x12,0x7b, +0x22,0x12,0x3a,0xa9,0x80,0x12,0x7e,0xa1,0x2a,0x7e,0x70,0x27,0xac,0x7f,0x19,0xa3, +0x6f,0x11,0xe5,0x2a,0x7a,0xb3,0x71,0x89,0x12,0x3a,0x30,0x5e,0x24,0x0, 0x2, 0x68, +0x37,0x5e,0x70,0xfd,0x7a,0x37,0x4d,0x4d,0x7e,0xb3,0x71,0x8a,0x12,0xbf,0xd0,0x50, +0x15,0x7e,0xb3,0x71,0x8a,0x12,0x48,0x73,0x50,0xc, 0x7e,0xb3,0x71,0x8a,0x12,0x3c, +0xcf,0x12,0x3a,0xa9,0x80,0x12,0x7e,0xa1,0x2b,0x7e,0x70,0x27,0xac,0x7f,0x19,0xa3, +0x6f,0x12,0xe5,0x2b,0x7a,0xb3,0x71,0x8a,0x12,0x3a,0x30,0x5e,0x24,0x0, 0x4, 0x68, +0x2a,0x5e,0x70,0xfb,0x12,0x3a,0x63,0x7e,0x30,0x2c,0xac,0x3e,0x12,0x3b,0xd8,0x74, +0x1, 0x7e,0x70,0x27,0xac,0x7f,0x12,0xdd,0xda,0x12,0x3b,0xdf,0x12,0x3a,0x37,0x12, +0x3c,0x8b,0x12,0x3c,0xb8,0x12,0x7b,0x11,0x12,0x43,0x3b,0x12,0x3a,0x30,0x5e,0x24, +0x0, 0x8, 0x68,0xe, 0x5e,0x70,0xf7,0x7a,0x37,0x4d,0x4d,0x7e,0xb3,0x71,0x8c,0x12, +0x7a,0xca,0x12,0x3a,0x30,0x5e,0x24,0x0, 0x10,0x68,0xc, 0x5e,0x70,0xef,0x12,0x3a, +0x6a,0x12,0x3a,0x37,0x12,0x3c,0x8b,0x12,0x3a,0x30,0x5e,0x24,0x0, 0x20,0x68,0x37, +0x5e,0x70,0xdf,0x7a,0x37,0x4d,0x4d,0x4e,0x60,0x2, 0x12,0x3a,0x63,0x12,0x3b,0xdf, +0x12,0x3a,0x57,0x74,0xa, 0xac,0xbf,0x12,0xdd,0xb1,0x12,0x3a,0x57,0x7e,0x70,0x27, +0xac,0x7f,0x12,0xdd,0xbc,0x7c,0xbf,0x12,0xd5,0xd4,0x12,0x3c,0xb8,0x12,0x3a,0x51, +0x7e,0x24,0x0, 0x10,0x12,0xc, 0xcc,0x12,0x3a,0x30,0x5e,0x24,0x0, 0x40,0x68,0x2a, +0x5e,0x70,0xbf,0x7a,0x37,0x4d,0x4d,0xbe,0xf0,0x3, 0x7c,0xbf,0x12,0xc1,0x90,0x78, +0xc, 0xac,0x67,0x49,0x13,0x29,0x83,0x49,0x3, 0x29,0x81,0x80,0xa, 0xac,0x67,0x49, +0x13,0x29,0x7f,0x49,0x3, 0x29,0x7d,0x12,0x33,0x77,0x12,0x3a,0x30,0x5e,0x24,0x0, +0x80,0x68,0xa, 0x5e,0x70,0x7f,0x7a,0x37,0x4d,0x4d,0x12,0x41,0xd4,0x12,0x3a,0x30, +0x5e,0x24,0x2, 0x0, 0x68,0x3b,0x5e,0x60,0xfd,0x7a,0x37,0x4d,0x4d,0x74,0x27,0xac, +0xbf,0x49,0xe5,0x6f,0x18,0xb, 0xe4,0x7e,0xf7,0x71,0xb2,0xad,0xef,0xbe,0x78,0x7f, +0xff,0x28,0x4, 0x7e,0x78,0x7f,0xff,0x7e,0x8, 0x0, 0x65,0x12,0x3c,0x92,0x7e,0x8, +0x0, 0xa1,0x12,0x3c,0x92,0x7e,0x8, 0x0, 0x65,0x7d,0x3f,0x12,0xdc,0xf9,0x12,0xc, +0xcc,0x12,0x3a,0x30,0x5e,0x24,0x4, 0x0, 0x68,0xe, 0x5e,0x60,0xfb,0x7a,0x37,0x4d, +0x4d,0x7e,0xb3,0x71,0x62,0x12,0xbe,0x51,0x12,0x3a,0x30,0x5e,0x24,0x10,0x0, 0x68, +0x7, 0x5e,0x60,0xef,0x7a,0x37,0x4d,0x4d,0x12,0x3a,0x30,0x5e,0x24,0x20,0x0, 0x68, +0xc, 0x5e,0x60,0xdf,0x7a,0x37,0x4d,0x4d,0x7c,0xbf,0x12,0x59,0xbe,0xda,0x3b,0x22, +0x7e,0x37,0x4d,0x4d,0x7d,0x23,0x22,0x7e,0x30,0x2c,0xac,0x3e,0x2e,0x14,0x0, 0xe3, +0x6d,0x0, 0x74,0xa, 0xac,0xbf,0x49,0x35,0x6f,0xbd,0x49,0x25,0x6f,0xbb,0x12,0x9, +0xad,0x7d,0x36,0x2e,0x34,0x0, 0x6, 0x7e,0x30,0x2c,0xac,0x3e,0x2e,0x14,0x0, 0xe3, +0x6d,0x0, 0x22,0x7a,0x37,0x4d,0x4d,0x4e,0x60,0x10,0x7a,0x37,0x4d,0x4d,0x7c,0xbf, +0xca,0xf8,0x7c,0xfb,0x12,0x3a,0xa9,0x7e,0xa3,0x71,0x8b,0x7e,0x70,0x27,0xac,0x7f, +0x19,0xa3,0x6f,0x13,0x6c,0xaa,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x42,0x71,0x90,0x7e, +0x70,0x27,0xac,0x7f,0x2d,0x32,0x59,0x43,0x6f,0x18,0xb, 0xa0,0xbe,0xa0,0x10,0x40, +0xe5,0x7c,0xbf,0x12,0x43,0x9c,0xda,0xf8,0x22,0x12,0xdd,0xef,0x68,0x42,0xe5,0x1b, +0x60,0x3e,0x7e,0xb3,0x71,0x89,0x7e,0x73,0x71,0x8a,0x12,0xcd,0x16,0x7d,0x23,0x7e, +0x34,0x0, 0x3, 0xad,0x32,0x7e,0x24,0x0, 0xa, 0x8d,0x32,0x6c,0xaa,0x7e,0x50,0x2, +0xac,0x5a,0x49,0x12,0x71,0x90,0xbd,0x13,0x28,0xf, 0x59,0x32,0x71,0x90,0x7e,0x27, +0x4d,0x4d,0x4e,0x50,0x20,0x7a,0x27,0x4d,0x4d,0xb, 0xa0,0xbe,0xa0,0x10,0x78,0xdd, +0x22,0xca,0x79,0x7c,0xeb,0xbe,0xe0,0x4, 0x40,0x2, 0x61,0xc0,0x74,0x27,0xac,0xbe, +0x9, 0xf5,0x6f,0x15,0xbe,0xf0,0x3, 0x40,0x2, 0x61,0xc0,0x74,0x2, 0xac,0xbe,0x9, +0xb5,0x6f,0xae,0x54,0x3f,0xa, 0x3b,0x74,0x2c,0xac,0xbf,0x59,0x35,0x0, 0xd7,0x74, +0x2, 0xac,0xbe,0x9, 0xb5,0x6f,0xad,0x54,0x1f,0x7c,0x6b,0x6c,0x77,0x12,0x3b,0xcc, +0x74,0x2c,0xac,0xbf,0x59,0x35,0x0, 0xd9,0x12,0x3b,0xd3,0x74,0x1, 0x7e,0x70,0x27, +0xac,0x7e,0x12,0xdd,0xda,0x7e,0x30,0x2c,0xac,0x3f,0x12,0x3a,0x5c,0x7e,0x70,0x27, +0xac,0x7e,0x12,0xdd,0xbc,0x7e,0x30,0x2c,0xac,0x3f,0x2e,0x14,0x0, 0xd9,0x12,0x3b, +0xc3,0x9, 0x75,0x6f,0x11,0x12,0x3b,0xca,0x12,0xd, 0xd3,0x12,0x3c,0xa1,0x12,0x3b, +0xc3,0x9, 0x75,0x6f,0x12,0x12,0x3b,0xca,0x12,0xd, 0xe5,0x12,0x3c,0xa1,0x6d,0x0, +0x74,0xa, 0xac,0xbe,0x12,0x3b,0xee,0x7e,0x30,0x2c,0xac,0x3f,0x12,0x3a,0x5c,0x74, +0xa, 0xac,0xbe,0x12,0xdd,0xb1,0x7e,0x30,0x2c,0xac,0x3f,0x2e,0x14,0x0, 0xeb,0x12, +0x3b,0xc3,0x9, 0xb5,0x6f,0x14,0x12,0xc, 0xaa,0xe4,0x12,0x42,0x7a,0x7e,0x70,0xb5, +0xac,0x7f,0x2e,0x34,0x1, 0x0, 0x12,0x3b,0xd3,0x7e,0x24,0x0, 0x16,0x12,0xc, 0xcc, +0xda,0x79,0x22,0x6d,0x0, 0x74,0x27,0xac,0xbe,0x22,0xa, 0x37,0x3e,0x34,0x3e,0x34, +0x3e,0x34,0x22,0x7e,0x30,0x2c,0xac,0x3f,0x2e,0x14,0x0, 0xd7,0x6d,0x0, 0x22,0x7e, +0x30,0x2c,0xac,0x3e,0x2e,0x14,0x0, 0xdb,0x6d,0x0, 0x74,0xa, 0xac,0xbf,0x9, 0xb5, +0x6f,0xb5,0x2, 0xd, 0x73,0x7e,0x1f,0x73,0x51,0x69,0x11,0x0, 0x6, 0x7d,0x1, 0x5e, +0x4, 0x0, 0x1, 0x78,0xa, 0xe4,0x7a,0xb3,0x73,0x8, 0x75,0x1b,0x0, 0x80,0x31,0x5e, +0x14,0x0, 0x2, 0x78,0x7, 0x74,0x1, 0x12,0x3c,0x99,0x80,0x24,0x7e,0xb3,0x73,0x8, +0xbe,0xb0,0x1, 0x68,0x2, 0x70,0x19,0x12,0x3c,0x82,0x68,0xb, 0x74,0x2, 0x7a,0xb3, +0x73,0x8, 0x75,0x1b,0x2, 0x80,0x9, 0x74,0x3, 0x7a,0xb3,0x73,0x8, 0x75,0x1b,0x3, +0x74,0x1, 0x12,0x3a,0xf1,0x7e,0xb3,0x73,0x8, 0x24,0x0, 0x68,0x25,0x24,0xfd,0x68, +0x12,0x4, 0x78,0x22,0x12,0x3c,0xab,0x68,0x28,0x12,0x3c,0x82,0x78,0x23,0x74,0x1, +0x2, 0x5, 0xbc,0x12,0x3c,0xab,0x68,0x19,0x12,0x3c,0x82,0x68,0x14,0x74,0x1, 0x2, +0x5, 0x30,0xe4,0x2, 0x3a,0xf1,0x12,0x60,0x5e,0x12,0x2f,0xfe,0x74,0x1, 0x12,0x3c, +0x99,0x22,0x69,0x31,0x0, 0xe, 0x5e,0x34,0x0, 0x8, 0x22,0x7e,0x24,0x0, 0x4, 0x2, +0xc, 0xcc,0x7e,0x37,0x71,0xb0,0x2, 0xc, 0x88,0x7a,0xb3,0x73,0x8, 0x75,0x1b,0x1, +0x22,0x7e,0x30,0x2c,0xac,0x3f,0x2e,0x14,0x0, 0xdb,0x22,0x7e,0x1f,0x73,0x51,0x69, +0x11,0x0, 0x6, 0x5e,0x14,0x0, 0x2, 0x22,0x7d,0x36,0xb, 0x35,0x74,0x2c,0xac,0xbe, +0x49,0x25,0x0, 0xdb,0x2, 0x0, 0x2e,0x74,0x26,0xac,0xbf,0x9, 0xb5,0x29,0x6f,0xca, +0x3b,0x7c,0xfb,0x6c,0xee,0x74,0x27,0xac,0xbe,0x19,0xf5,0x6f,0x12,0xb, 0xe0,0xbe, +0xe0,0x4, 0x78,0xf1,0x7e,0x64,0x1, 0x0, 0x6c,0xee,0x7e,0x30,0x2c,0xac,0x3e,0x2e, +0x14,0x0, 0xdb,0x6d,0x0, 0xa, 0x3f,0x12,0x3b,0xcc,0x12,0xd, 0xe5,0x12,0x3c,0xb8, +0x12,0x7b,0x18,0x40,0xe5,0xda,0x3b,0x22,0xca,0x3b,0x7e,0x73,0x73,0x8, 0xa, 0x27, +0x12,0xd7,0xdc,0x7a,0x1d,0x26,0x7e,0x38,0x5d,0xd, 0x7e,0x73,0x69,0x90,0x7a,0x73, +0x5d,0x8, 0x7e,0x73,0x69,0x91,0x7a,0x73,0x5d,0x9, 0x7e,0x73,0x71,0x8a,0x7a,0x73, +0x5d,0xa, 0x7e,0x73,0x71,0x81,0x7a,0x73,0x5d,0xb, 0x7e,0x73,0x71,0x82,0x7a,0x73, +0x5d,0xc, 0x7e,0x8, 0x5d,0xd, 0x7e,0x34,0x0, 0x8, 0xe4,0x12,0x24,0x39,0x7e,0x34, +0x0, 0x20,0xca,0x39,0x7e,0x18,0x71,0x90,0x7e,0x8, 0x5d,0x15,0x12,0x24,0x14,0x1b, +0xfd,0x74,0x5, 0x7a,0xb3,0x71,0x8a,0xe4,0x7a,0xb3,0x71,0x81,0x74,0x2, 0x7a,0xb3, +0x71,0x82,0xe4,0x7a,0xb3,0x5d,0x7, 0x7e,0x34,0x0, 0x2, 0x12,0x3e,0x8d,0x59,0x35, +0x71,0x90,0x12,0x3e,0x95,0xb4,0x10,0xef,0x12,0x3e,0x9f,0x7a,0xb3,0x5d,0x7, 0x7e, +0xa3,0x5d,0x7, 0x4c,0xaa,0x78,0xd, 0x7e,0xb3,0x6e,0x2, 0x54,0x1, 0xb4,0x1, 0x4, +0x74,0x1, 0x80,0x12,0xbe,0xa0,0x1, 0x78,0x14,0x7e,0xb3,0x6e,0x2, 0x54,0x2, 0x1e, +0xb0,0xb4,0x1, 0x9, 0x74,0x4, 0x7a,0xb3,0x69,0x90,0xe4,0x80,0x34,0xbe,0xa0,0x2, +0x78,0x16,0x7e,0xb3,0x6e,0x2, 0x54,0x4, 0x1e,0xb0,0x1e,0xb0,0xb4,0x1, 0x9, 0xe4, +0x7a,0xb3,0x69,0x90,0x74,0x1, 0x80,0x19,0xbe,0xa0,0x3, 0x78,0x3a,0x7e,0xb3,0x6e, +0x2, 0x54,0x8, 0xc4,0x23,0x54,0x1f,0xb4,0x1, 0x2d,0xe4,0x7a,0xb3,0x69,0x90,0x74, +0x4, 0x7a,0xb3,0x69,0x91,0x7e,0x34,0x21,0x57,0x12,0x30,0xa4,0x12,0x47,0xd6,0x12, +0xd6,0xf6,0x12,0x53,0xbc,0x12,0x3e,0x8d,0x7e,0x1d,0x26,0x2d,0x35,0xb, 0x1a,0x10, +0x7f,0x13,0x2d,0x35,0x1b,0x1a,0x10,0x12,0x3e,0x95,0xb4,0x4, 0x2, 0x80,0x2, 0xa1, +0x8f,0xe4,0x7a,0xb3,0x5d,0x7, 0x12,0x3e,0x8d,0x7f,0x13,0x2d,0x35,0xb, 0x1a,0x10, +0x7e,0x1d,0x26,0x2d,0x35,0x1b,0x1a,0x10,0x12,0x3e,0x95,0x7e,0x73,0x5d,0x7, 0xbe, +0x70,0x4, 0x40,0xe2,0x7e,0x73,0x5d,0x8, 0x7a,0x73,0x69,0x90,0x7e,0x73,0x5d,0x9, +0x7a,0x73,0x69,0x91,0x7e,0x73,0x5d,0xa, 0x7a,0x73,0x71,0x8a,0x7e,0x73,0x5d,0xb, +0x7a,0x73,0x71,0x81,0x7e,0x73,0x5d,0xc, 0x7a,0x73,0x71,0x82,0x7e,0x34,0x0, 0x20, +0xca,0x39,0x7e,0x18,0x5d,0x15,0x7e,0x8, 0x71,0x90,0x12,0x24,0x14,0x1b,0xfd,0x12, +0x3e,0x9f,0x7a,0xb3,0x71,0x87,0x7a,0xb3,0x71,0x86,0xda,0x3b,0x22,0x7e,0xa3,0x5d, +0x7, 0x74,0x2, 0xa4,0x22,0x7e,0xb3,0x5d,0x7, 0x4, 0x7a,0xb3,0x5d,0x7, 0x22,0x7e, +0xb3,0x71,0x8a,0x12,0x3c,0xcf,0x7e,0x37,0x4d,0x4d,0x4e,0x60,0x1, 0x7a,0x37,0x4d, +0x4d,0x4e,0x70,0x20,0x7a,0x37,0x4d,0x4d,0x12,0x37,0xfb,0xe4,0x22,0xca,0xf8,0x12, +0xcf,0x79,0x7e,0xf0,0x1, 0x7c,0xbf,0x12,0x3a,0xf1,0xb, 0xf0,0xbe,0xf0,0x4, 0x78, +0xf4,0xe5,0x1b,0x70,0x4, 0xe4,0x12,0x3a,0xf1,0xda,0xf8,0x22,0x7e,0xf, 0x73,0x51, +0x69,0x30,0x0, 0x6, 0x5e,0x34,0x0, 0x1, 0x68,0x1b,0x12,0x4a,0xda,0x5e,0x34,0x0, +0x2, 0x68,0x6, 0x12,0x3f,0x84,0x12,0x5, 0xbc,0x74,0x3, 0x12,0xd6,0x3a,0x74,0x1, +0x12,0x3a,0xf1,0x80,0x30,0x12,0xd5,0x2b,0x75,0x1b,0x0, 0xe4,0x12,0x3f,0x89,0x12, +0xd6,0x3a,0xe4,0x12,0x3a,0xf1,0x7e,0xf, 0x73,0x51,0x2e,0x14,0x0, 0xa, 0xb, 0xa, +0x30,0x4e,0x60,0x10,0x1b,0xa, 0x30,0xe4,0x7a,0xb3,0x72,0xff,0x12,0x2a,0x29,0x12, +0x5b,0x0, 0x12,0x5a,0x8d,0xe5,0x1b,0x2, 0x3f,0x3a,0x7c,0xab,0x12,0xcf,0xa4,0x1b, +0xa0,0x68,0x12,0x1b,0xa0,0x68,0x13,0x1b,0xa0,0x68,0x14,0x2e,0xa0,0x3, 0x78,0x12, +0x12,0xcf,0xf8,0x80,0xd, 0x12,0xd0,0x35,0x80,0x8, 0x12,0xcf,0xdc,0x80,0x3, 0x12, +0xd0,0x48,0x2, 0x3f,0x65,0xe4,0x7a,0xb3,0x3, 0xd6,0x6c,0xaa,0x80,0xd, 0x12,0xd0, +0xc8,0x2e,0xb3,0x3, 0xd6,0x7a,0xb3,0x3, 0xd6,0xb, 0xa0,0x7e,0xb3,0x3, 0xcb,0xbc, +0xba,0x38,0xeb,0x22,0x75,0x1b,0x2, 0x74,0x2, 0x7a,0xb3,0x73,0x8, 0x74,0x1, 0x22, +0x12,0xdd,0xd3,0xd2,0x2, 0x12,0x2f,0x50,0x12,0x3b,0xf5,0xe5,0x1b,0x12,0x3f,0x3a, +0x2, 0x3f,0xa3,0x7e,0x1f,0x22,0xe0,0x7a,0x37,0x51,0xbb,0x7e,0x63,0x73,0x8, 0xa, +0x6, 0x12,0x47,0xbc,0x2e,0x24,0x51,0xe5,0x7a,0x27,0x4d,0x4f,0x6d,0x22,0x7a,0x27, +0x4d,0x41,0x7e,0x24,0x69,0x9f,0x7a,0x27,0x4d,0x4b,0x7e,0x24,0x0, 0x27,0xca,0x29, +0x12,0xdd,0x94,0x12,0x24,0x14,0x1b,0xfd,0x7e,0x34,0x0, 0x2, 0xca,0x39,0x7e,0x63, +0x73,0x8, 0xac,0x67,0x2e,0x34,0x6f,0xad,0x6d,0x22,0x7e,0x8, 0x71,0x81,0x12,0x24, +0x14,0x1b,0xfd,0x7e,0xa3,0x73,0x8, 0x74,0xa, 0xa4,0x49,0x35,0x6f,0xb9,0x7a,0x37, +0x71,0x8e,0x7e,0xb3,0x73,0x8, 0x12,0x42,0x1b,0x7e,0xb3,0x73,0x8, 0x12,0xd5,0xd4, +0x7e,0xb3,0x73,0x8, 0x12,0x42,0x36,0x12,0x40,0x51,0xa4,0x9, 0x75,0x6f,0xdd,0x7a, +0x73,0x71,0x78,0x12,0x40,0x51,0xa4,0x9, 0x75,0x6f,0xde,0x7a,0x73,0x71,0x79,0x12, +0x40,0x51,0xa4,0x9, 0x75,0x6f,0xdf,0x7a,0x73,0x71,0x7a,0x7e,0x73,0x73,0x8, 0x7a, +0x73,0x71,0x88,0x2, 0x40,0x46,0xe5,0x1b,0x7a,0xb3,0x71,0x64,0x22,0x7e,0x8, 0x0, +0x53,0x7e,0xa3,0x73,0x8, 0x74,0x3, 0x22,0x12,0x2a,0x29,0x12,0x2f,0xfe,0x12,0xce, +0xc6,0x7e,0xb3,0x69,0x9e,0x7e,0x37,0x69,0x9a,0x60,0xe, 0x7a,0x37,0x0, 0x9d,0x7e, +0x37,0x69,0x9c,0x7a,0x37,0x0, 0x61,0x80,0xc, 0x7a,0x37,0x0, 0x61,0x7e,0x37,0x69, +0x9c,0x7a,0x37,0x0, 0x9d,0x7e,0x37,0x0, 0x5f,0x4e,0x70,0x2, 0x7a,0x37,0x0, 0x5f, +0x7e,0x37,0x0, 0x9b,0x4e,0x70,0x2, 0x7a,0x37,0x0, 0x9b,0x12,0x40,0x4d,0xa4,0x9, +0xb5,0x6f,0xdd,0x12,0xc, 0xea,0x12,0x40,0x4d,0xa4,0x9, 0xb5,0x6f,0xde,0x12,0xd, +0x8d,0x12,0x40,0x4d,0xa4,0x12,0x42,0x73,0x7e,0x37,0x0, 0x53,0x7a,0x37,0x0, 0x8f, +0x6d,0x33,0x7e,0x8, 0x0, 0x4f,0x7e,0x24,0x0, 0x1e,0x12,0x3, 0xfa,0x6d,0x33,0x7e, +0x8, 0x0, 0x8b,0x7e,0x24,0x0, 0x1e,0x2, 0x4, 0x96,0x12,0x40,0x58,0x12,0x40,0xe6, +0x12,0x0, 0x1e,0x2, 0x3e,0xbd,0xca,0x3b,0x7e,0x38,0x1, 0x5f,0x12,0x7, 0xb5,0x7e, +0x63,0x1, 0x6f,0xbe,0x60,0xff,0x68,0x2a,0x7e,0x73,0x1, 0x70,0xbe,0x70,0xff,0x68, +0x21,0x7e,0xa3,0x1, 0x71,0xbe,0xa0,0xff,0x68,0x18,0x4c,0x66,0x68,0x14,0x4c,0x77, +0x68,0x10,0x4c,0xaa,0x68,0xc, 0x7a,0x63,0x71,0x9, 0x7a,0x73,0x71,0x5, 0x7a,0xa3, +0x71,0x6, 0xe4,0x7a,0xb3,0x73,0x0, 0x7e,0x73,0x1, 0x71,0xbe,0x70,0x3, 0x28,0x13, +0x74,0x3, 0x7a,0xb3,0x73,0x3, 0x7a,0xb3,0x4d,0x48,0x75,0xc3,0x83,0x74,0x1, 0x7a, +0xb3,0x73,0x0, 0x7e,0x8, 0x0, 0x83,0x69,0x33,0x0, 0x4, 0x12,0x41,0xc7,0x7e,0x8, +0x0, 0x85,0x29,0xb3,0x0, 0x6, 0x12,0x41,0xbc,0x7e,0x8, 0x0, 0xbf,0x69,0x33,0x0, +0x1, 0x12,0x41,0xc7,0x7e,0x8, 0x0, 0xc1,0x29,0xb3,0x0, 0x3, 0x12,0x41,0xbc,0x7e, +0x8, 0x0, 0x87,0x69,0x33,0x0, 0xa, 0x12,0x41,0xc7,0x7e,0x8, 0x0, 0x89,0x29,0xb3, +0x0, 0xc, 0x12,0x41,0xbc,0x7e,0x8, 0x0, 0xc3,0x69,0x33,0x0, 0x7, 0x12,0x41,0xc7, +0x7e,0x8, 0x0, 0xc5,0x29,0xb3,0x0, 0x9, 0x12,0x41,0xbc,0x7e,0x34,0x0, 0x1a,0x7e, +0x8, 0x0, 0x83,0x7e,0x24,0x0, 0x4, 0x12,0x3, 0xfa,0x7e,0x34,0x0, 0x1a,0x7e,0x8, +0x0, 0xbf,0x7e,0x24,0x0, 0x4, 0x12,0x4, 0x96,0xda,0x3b,0x22,0x54,0xc0,0x23,0x23, +0x54,0x3, 0xa, 0x3b,0x2, 0xd, 0xa5,0x7d,0x23,0x7c,0x45,0x6c,0x55,0xa, 0x36,0x4d, +0x32,0x2, 0x0, 0x6, 0xca,0x3b,0x7e,0x67,0x69,0x92,0x7e,0x77,0x69,0x94,0x74,0x1, +0x12,0x42,0x7a,0x7e,0xb3,0x69,0x9e,0x7e,0x34,0x1, 0x0, 0x7e,0x8, 0x69,0x9f,0x7d, +0x26,0x60,0xb, 0x12,0x4, 0x96,0x12,0x42,0xa, 0x12,0x3, 0xfa,0x80,0x9, 0x12,0x3, +0xfa,0x12,0x42,0xa, 0x12,0x4, 0x96,0xda,0x3b,0x22,0x7e,0x34,0x1, 0x0, 0x7d,0x16, +0x3e,0x14,0x2e,0x14,0x69,0x9f,0x6d,0x0, 0x7d,0x27,0x22,0x7c,0xab,0x74,0x27,0xa4, +0x49,0x25,0x6f,0x18,0xb, 0x24,0x7e,0x37,0x71,0xb2,0xad,0x32,0x7e,0x8, 0x0, 0x65, +0x12,0xdc,0xf9,0x2, 0xc, 0xcc,0x7c,0x9b,0x12,0x42,0x6a,0x12,0x42,0x54,0x12,0x42, +0x73,0x4c,0x99,0x78,0x9, 0x7e,0x8, 0x0, 0x53,0x74,0x1, 0x12,0xc, 0xea,0x12,0x5a, +0xe, 0x2, 0x4, 0x96,0x9, 0xb5,0x6f,0xdd,0x12,0xc, 0xea,0x7e,0x8, 0x0, 0x53,0x74, +0x3, 0xac,0xb9,0x9, 0xb5,0x6f,0xde,0x12,0xd, 0x8d,0x7e,0x8, 0x0, 0x53,0x74,0x3, +0xac,0xb9,0x22,0x9, 0xb5,0x6f,0xdf,0x2, 0xd, 0x7, 0x7c,0xab,0x7e,0x8, 0x0, 0x5f, +0x7c,0xba,0x12,0xd, 0xf7,0x7e,0x8, 0x0, 0x9b,0x12,0xd, 0xf7,0x7e,0x34,0x0, 0x8, +0x7e,0x8, 0x0, 0x5f,0x12,0xd6,0x73,0x7e,0x34,0x0, 0x8, 0x7e,0x8, 0x0, 0x9b,0x7e, +0x24,0x0, 0x1, 0x2, 0x4, 0x96,0xca,0x3b,0x7c,0xeb,0x74,0x27,0xac,0xbe,0x9, 0xf5, +0x6f,0x15,0x12,0x47,0xb0,0xe5,0x1b,0x12,0x3f,0x3a,0x12,0x42,0xf3,0xda,0x3b,0x22, +0xca,0x3b,0x7c,0xeb,0xc2,0x2, 0x7e,0x70,0x27,0xac,0x7e,0x9, 0xf3,0x6f,0x15,0x12, +0x47,0xb0,0x4c,0xee,0x68,0x18,0xd2,0x2, 0xe4,0x19,0xb3,0x6f,0x13,0x7c,0xbe,0x12, +0x43,0x9c,0x12,0xcf,0xa4,0x12,0xd0,0x64,0x12,0x3f,0x65,0x12,0x42,0xf3,0xa2,0x2, +0xda,0x3b,0x22,0xe4,0x12,0x42,0x7a,0x7e,0x30,0x2c,0xac,0x3f,0x2e,0x14,0x0, 0xd7, +0x6d,0x0, 0x74,0x1, 0x7e,0x70,0x27,0xac,0x7e,0x9, 0x73,0x6f,0x13,0x12,0xd, 0x23, +0x7e,0x30,0x2c,0xac,0x3f,0x2e,0x14,0x0, 0xdb,0x6d,0x0, 0x74,0xa, 0xac,0xbe,0x9, +0xb5,0x6f,0xb5,0x12,0xd, 0x73,0x7d,0x36,0xb, 0x35,0x74,0x2c,0xac,0xbf,0x49,0x25, +0x0, 0xdb,0x12,0x0, 0x2e,0x7d,0x36,0x74,0x2c,0xac,0xbf,0x49,0x25,0x0, 0xd7,0x2, +0x0, 0x2e,0xca,0x79,0x7c,0xfb,0xd2,0x0, 0xc2,0x1, 0x6d,0x33,0x7a,0x37,0x72,0xf7, +0x74,0x27,0xac,0xbf,0x9, 0xe5,0x6f,0x13,0x7c,0xbf,0x12,0x42,0xc0,0x92,0x1, 0x7c, +0xbf,0x12,0xc0,0xf2,0x92,0x0, 0x30,0x0, 0x7, 0x7c,0xbf,0x7c,0x7f,0x12,0x43,0xfe, +0x7e,0xb3,0x71,0x86,0x70,0xc, 0x7c,0xbf,0x12,0xd7,0x6c,0x92,0x2a,0x20,0x2a,0x2, +0xc2,0x0, 0x30,0x1, 0x12,0x74,0x27,0xac,0xbf,0x19,0xe5,0x6f,0x13,0x7c,0xbf,0x12, +0x43,0x9c,0x7c,0xbf,0x12,0x42,0xa6,0xa2,0x0, 0xda,0x79,0x22,0x7c,0x9b,0x12,0xd6, +0x3, 0x7e,0x50,0xa, 0xac,0x59,0x59,0x32,0x6f,0xb7,0x74,0x27,0xac,0xb9,0x49,0x5, +0x6f,0x16,0x59,0x2, 0x6f,0xb9,0x49,0x15,0x6f,0x18,0xb, 0x14,0xad,0x10,0x6d,0x0, +0x59,0x12,0x6f,0xbd,0x59,0x2, 0x6f,0xbb,0x12,0x43,0xef,0x7c,0xab,0x7e,0x70,0xa, +0xac,0x79,0x19,0xa3,0x6f,0xb5,0x74,0x27,0xac,0xb9,0x49,0x35,0x6f,0x18,0xb, 0x34, +0x12,0x43,0xef,0x7c,0xab,0x7e,0x70,0xa, 0xac,0x79,0x19,0xa3,0x6f,0xb6,0x22,0xe4, +0x80,0x5, 0xb, 0x34,0x1e,0x34,0x4, 0xbe,0x34,0x0, 0x10,0x38,0xf5,0x22,0xca,0x3b, +0x7c,0xf7,0x7c,0xeb,0x75,0x2b,0x9, 0x7e,0x34,0x2, 0x0, 0x7a,0x35,0x2e,0x75,0x38, +0x0, 0x7e,0x34,0x24,0x6b,0x7e,0x24,0x0, 0xff,0x7e,0x14,0x5d,0x35,0x7e,0x54,0x2, +0x3a,0x12,0x23,0x67,0x6d,0x66,0x80,0xe, 0x7e,0x34,0x7f,0xff,0x7d,0x26,0x3e,0x24, +0x59,0x32,0x11,0x38,0xb, 0x64,0x7e,0x37,0x6d,0xfe,0x7d,0x23,0xb, 0x26,0xbd,0x26, +0x38,0xe6,0x2e,0x34,0x0, 0x8, 0x12,0x46,0xc2,0xe4,0x12,0x24,0x39,0xa, 0x2f,0x12, +0xd7,0xdc,0x7a,0x1d,0x30,0x7e,0x37,0x6d,0xfe,0x2e,0x34,0x5d,0x35,0x7a,0x1d,0x34, +0x7e,0xb3,0x3, 0xfa,0xb4,0x1, 0xa, 0x7e,0x37,0x3, 0xfb,0x12,0x31,0xd8,0x7a,0x35, +0x2e,0x74,0xa, 0xac,0xbe,0x49,0x25,0x6f,0xb7,0x7e,0x35,0x2e,0xad,0x32,0x9, 0xb5, +0x6f,0xb5,0x60,0xc, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4, +0x7a,0x35,0x2e,0xe5,0x2b,0xa, 0x5b,0x1b,0x54,0xf5,0x2a,0xc1,0xf, 0xe5,0x2a,0x7e, +0x34,0x0, 0x1, 0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7a,0x35,0x2c,0x7e,0x34,0x9, +0xc4,0x12,0x47,0xd6,0xe5,0x2a,0xbe,0xb0,0x7, 0x58,0x1b,0x6d,0x66,0x80,0x12,0x7e, +0x35,0x2c,0x7c,0x67,0x12,0x47,0xba,0x12,0x47,0xa6,0x4c,0x76,0x7a,0x29,0x70,0xb, +0x64,0x12,0x46,0xb9,0x38,0xe9,0x6d,0x66,0x12,0x47,0xc5,0x4e,0x35,0x2c,0x1b,0xa, +0x30,0x12,0x46,0xa2,0x78,0xf2,0x12,0x46,0xc0,0x12,0x33,0x77,0x5, 0x38,0xe5,0x38, +0x54,0x1, 0xb4,0x1, 0x8, 0x74,0x1, 0x7a,0xb3,0x3, 0xfe,0x80,0xe, 0x7e,0x73,0x72, +0xff,0xa, 0x37,0x1e,0x34,0xb, 0x34,0x7a,0x73,0x3, 0xfe,0x12,0x2a,0x60,0xd2,0x2, +0x12,0x2f,0x50,0xe5,0x2a,0xbe,0xb0,0x7, 0x58,0x73,0x6d,0x66,0x80,0x6a,0x7d,0x26, +0x12,0x46,0xa9,0x8, 0x7, 0x7d,0x13,0x9e,0x15,0x2e,0x80,0x4, 0x6d,0x11,0x9d,0x10, +0x7a,0x17,0x5f,0x6f,0x49,0x12,0x11,0x38,0x7d,0x1, 0x12,0x46,0xb1,0x8, 0x5, 0x9e, +0x15,0x2e,0x80,0x4, 0x6d,0x11,0x9d,0x10,0x7a,0x17,0x5f,0x71,0xbe,0x17,0x5f,0x6f, +0x40,0x16,0x59,0x32,0x11,0x38,0xa, 0x2f,0x7e,0x34,0x2, 0x3a,0xad,0x32,0x2d,0x36, +0x9, 0x73,0x51,0xe5,0x19,0x76,0x5d,0x35,0x7d,0x36,0x12,0x47,0x9c,0x50,0x17,0x7e, +0x55,0x2c,0x64,0xff,0xa, 0x2f,0x7e,0x34,0x2, 0x3a,0xad,0x32,0x7d,0x23,0x12,0x47, +0xa6,0x5c,0x7b,0x7a,0x29,0x70,0xb, 0x64,0x12,0x46,0xb9,0x38,0x91,0x6d,0x66,0x7e, +0x27,0x6d,0xfe,0x2d,0x26,0x12,0x46,0xa9,0x8, 0x7, 0x7d,0x13,0x9e,0x15,0x2e,0x80, +0x4, 0x6d,0x11,0x9d,0x10,0x7a,0x17,0x5f,0x6f,0x49,0x12,0x11,0x38,0x7d,0x1, 0x12, +0x46,0xb1,0x8, 0x5, 0x9e,0x15,0x2e,0x80,0x4, 0x6d,0x11,0x9d,0x10,0x7a,0x17,0x5f, +0x71,0xbe,0x17,0x5f,0x6f,0x40,0x18,0x59,0x32,0x11,0x38,0x7d,0x6, 0x3e,0x4, 0x7e, +0x1d,0x30,0x2d,0x30,0xb, 0x1a,0x10,0x7e,0x1d,0x34,0x2d,0x30,0x1b,0x1a,0x10,0x7e, +0x37,0x6d,0xfe,0x2d,0x36,0x12,0x47,0x9c,0x50,0xf, 0x7e,0x25,0x2c,0x6e,0x24,0xff, +0xff,0x12,0x47,0xc5,0x5d,0x32,0x1b,0xa, 0x30,0x12,0x46,0xa2,0x78,0x91,0x30,0xb, +0x2, 0xc1,0x9f,0x30,0xc, 0x2, 0xc1,0x9f,0x30,0xd, 0x2, 0xc1,0x9f,0x15,0x2a,0xe5, +0x2a,0xbe,0xb0,0x1, 0x48,0x2, 0x81,0x9d,0x7e,0xb3,0x71,0x78,0xbe,0xb0,0x2, 0x68, +0x6f,0x12,0xdd,0xef,0x68,0x6a,0x7e,0x8, 0x11,0x38,0x74,0xa, 0xac,0xbe,0x12,0x56, +0xf8,0x6d,0x66,0x80,0x23,0x7d,0x26,0x3e,0x24,0x49,0x32,0x11,0x38,0xbe,0x34,0x3, +0xe8,0x28,0x13,0xbe,0x34,0x3e,0x80,0x50,0xd, 0x9, 0x76,0x5d,0x35,0x12,0x47,0xba, +0x2d,0x26,0x19,0x72,0x51,0xe5,0xb, 0x64,0x12,0x46,0xb9,0x38,0xd8,0x6d,0x66,0x7e, +0x27,0x6d,0xfe,0x2d,0x26,0x3e,0x24,0x49,0x32,0x11,0x38,0xbe,0x34,0x3, 0xe8,0x28, +0x1a,0xbe,0x34,0x3e,0x80,0x50,0x14,0x7d,0x6, 0x3e,0x4, 0x7e,0x1d,0x34,0x2d,0x30, +0xb, 0x1a,0x10,0x7e,0x1d,0x30,0x2d,0x30,0x1b,0x1a,0x10,0x12,0x46,0xa2,0x78,0xcf, +0x74,0x1, 0x7a,0xb3,0x3, 0xfe,0x12,0x46,0xc0,0x12,0x33,0x77,0x12,0x47,0x8d,0xda, +0x3b,0x22,0xb, 0x64,0xbe,0x64,0x0, 0x4, 0x22,0x3e,0x24,0x49,0x32,0xc, 0xd0,0x7d, +0x3, 0x9e,0x5, 0x2e,0xbe,0x4, 0x0, 0x0, 0x22,0x7e,0x37,0x6d,0xfe,0xbd,0x36,0x22, +0x7c,0xbe,0xa, 0xf, 0x7e,0x14,0x2, 0x3a,0xad,0x10,0x2e,0x14,0x51,0xe5,0x6d,0x0, +0x22,0x7e,0xb3,0x29,0x6b,0x7c,0xab,0x6c,0x77,0xbc,0xa7,0x78,0x2e,0x7e,0x63,0x73, +0x8, 0xa, 0x6, 0x12,0x46,0xc4,0x12,0x47,0x6b,0x59,0x2, 0x29,0x81,0x7e,0x8, 0x15, +0xa0,0x59,0x12,0x29,0x8b,0x59,0x2, 0x29,0x89,0x7e,0x8, 0x1a,0x8, 0x59,0x12,0x29, +0x8f,0x59,0x2, 0x29,0x8d,0x7e,0x8, 0x1e,0x70,0x80,0x4e,0x7e,0x50,0x4, 0xac,0x5a, +0xa, 0x17,0x2d,0x21,0x2e,0x24,0x24,0x4b,0x12,0x5f,0xf5,0x7c,0x6b,0x7e,0xb3,0x73, +0x8, 0xa, 0xb, 0x12,0x46,0xc4,0x12,0x47,0x6b,0x59,0x2, 0x29,0x81,0xa, 0x6, 0x7e, +0x14,0xd, 0x38,0xad,0x10,0x7d,0xf1,0x2e,0xf4,0x2a,0x0, 0x6d,0xee,0x59,0xf2,0x29, +0x8b,0x59,0xe2,0x29,0x89,0x7d,0xf1,0x2e,0xf4,0x2e,0x68,0x59,0xf2,0x29,0x8f,0x59, +0xe2,0x29,0x8d,0x2e,0x14,0x32,0xd0,0x6d,0x0, 0x59,0x12,0x29,0x93,0x59,0x2, 0x29, +0x91,0xb, 0x70,0xbe,0x70,0x3, 0x50,0x2, 0xc1,0xd9,0x22,0x7e,0x50,0x26,0xac,0x57, +0x59,0x12,0x29,0x7f,0x59,0x2, 0x29,0x7d,0x7e,0x8, 0x5a,0xcd,0x59,0x12,0x29,0x87, +0x59,0x2, 0x29,0x85,0x7e,0x8, 0x58,0x93,0x59,0x12,0x29,0x83,0x22,0xe4,0x7a,0xb3, +0x73,0xb, 0x2, 0x47,0x95,0x6d,0x33,0x7a,0x37,0x73,0x3c,0x22,0x3e,0x34,0x49,0x33, +0xc, 0xd0,0xbe,0x35,0x2e,0x22,0x2d,0x26,0x2e,0x24,0x51,0xe5,0x7e,0x29,0x70,0x22, +0x7e,0xd0,0xb5,0xac,0xdf,0x2e,0x64,0x1, 0x0, 0x22,0xa, 0xf, 0x7e,0x14,0x2, 0x3a, +0xad,0x10,0x7d,0x21,0x22,0x7d,0x36,0x3e,0x34,0x7e,0xd, 0x30,0x2d,0x13,0xb, 0xa, +0x30,0x22,0x7e,0x34,0xd, 0xac,0x6d,0x22,0x7a,0x27,0x73,0xe, 0x7a,0x37,0x73,0x10, +0x22,0x7e,0x34,0x21,0x57,0x12,0x30,0xa4,0x12,0x47,0xd6,0x12,0x60,0xdf,0x12,0x5b, +0x7, 0x12,0x72,0x26,0x7a,0xb3,0x73,0x1f,0x12,0x47,0xd2,0x2, 0x28,0x82,0x7c,0x7b, +0x74,0x8, 0xac,0x7b,0xbe,0x34,0x1, 0x18,0x38,0x2, 0xc3,0x22,0xbe,0x34,0x0, 0xdc, +0x50,0x2, 0xc3,0x22,0xd3,0x22,0x7c,0x7b,0x74,0x27,0xac,0xb7,0x9, 0x95,0x6f,0x15, +0x7e,0x63,0x71,0x81,0x74,0x2, 0xac,0xb7,0x19,0x65,0x6f,0xad,0x7e,0x63,0x71,0x82, +0x74,0x2, 0xac,0xb7,0x19,0x65,0x6f,0xae,0x74,0x2, 0xac,0x7b,0x2e,0x34,0x6f,0xad, +0x7e,0x14,0x0, 0x2c,0x12,0x23,0x44,0x7e,0x30,0x2c,0xac,0x39,0x7d,0x31,0x2e,0x34, +0x0, 0xd7,0x2e,0x14,0x0, 0xd9,0x6d,0x0, 0x12,0xb, 0x44,0x7e,0x70,0xb5,0xac,0x79, +0x2e,0x34,0x1, 0x0, 0x7e,0x30,0x2c,0xac,0x39,0x12,0x3b,0xd8,0x7e,0x24,0x0, 0x2, +0x2, 0xc, 0xcc,0x7c,0x7b,0x74,0x8, 0xac,0x7b,0xbe,0x34,0x0, 0x12,0x50,0x2, 0xc3, +0x22,0xd3,0x22,0xca,0x79,0x7c,0xeb,0xbe,0xe0,0xfa,0x78,0x6, 0x7e,0xb3,0x4d,0x46, +0x41,0x28,0xbe,0xe0,0xfc,0x78,0x4, 0x74,0x1, 0x41,0x28,0xbe,0xe0,0x5b,0x38,0x8, +0xa, 0x3e,0x9, 0xb3,0x71,0x58,0x41,0x28,0xbe,0xe0,0x6a,0x68,0x5, 0xbe,0xe0,0x6b, +0x78,0x22,0x12,0x50,0x6e,0x7e,0x37,0x4d,0x43,0x7d,0x23,0xb, 0x24,0x7a,0x27,0x4d, +0x43,0x2e,0x37,0x51,0xbb,0x7e,0x39,0xf0,0xbe,0xe0,0x6b,0x78,0x3, 0x75,0xf, 0x6a, +0x7c,0xbf,0x41,0x28,0xbe,0xe0,0x6e,0x68,0x5, 0xbe,0xe0,0x6f,0x78,0x22,0x12,0x57, +0xf6,0x7e,0x37,0x4d,0x41,0x7d,0x23,0xb, 0x24,0x7a,0x27,0x4d,0x41,0x2e,0x37,0x4d, +0x4f,0x7e,0x39,0xf0,0xbe,0xe0,0x6f,0x78,0x3, 0x75,0xf, 0x6e,0x7c,0xbf,0x41,0x28, +0xbe,0xe0,0x6c,0x68,0x5, 0xbe,0xe0,0x6d,0x78,0x1f,0x7e,0x37,0x51,0xb9,0x7d,0x23, +0xb, 0x24,0x7a,0x27,0x51,0xb9,0x2e,0x37,0x4d,0x4b,0x7e,0x39,0xf0,0xbe,0xe0,0x6d, +0x78,0x3, 0x75,0xf, 0x6c,0x7c,0xbf,0x41,0x28,0xbe,0xe0,0x89,0x68,0x5, 0xbe,0xe0, +0x8a,0x78,0x1f,0x7e,0x37,0x51,0xc0,0x7d,0x23,0xb, 0x24,0x7a,0x27,0x51,0xc0,0x2e, +0x37,0x51,0xbe,0x7e,0x39,0xf0,0xbe,0xe0,0x8a,0x78,0x3, 0x75,0xf, 0x89,0x7c,0xbf, +0x41,0x28,0xbe,0xe0,0x70,0x40,0xc, 0xbe,0xe0,0x7f,0x38,0x7, 0x7c,0xbe,0x12,0x4a, +0x2b,0x41,0x28,0xbe,0xe0,0x81,0x68,0x5, 0xbe,0xe0,0x82,0x78,0x26,0x7e,0x24,0x1b, +0xd8,0x7e,0xb3,0x71,0x6f,0xa, 0x3b,0x2d,0x32,0x6d,0x22,0x2e,0x24,0x0, 0xff,0x7e, +0x1b,0xf0,0x4, 0x7a,0xb3,0x71,0x6f,0xbe,0xe0,0x82,0x78,0x3, 0x75,0xf, 0x81,0x7c, +0xbf,0x41,0x28,0xbe,0xe0,0x86,0x78,0x6, 0x7e,0xb3,0x4d,0x48,0x41,0x28,0xbe,0xe0, +0x87,0x78,0x6, 0x7e,0xb3,0x4d,0x40,0x80,0x7f,0xbe,0xe0,0x88,0x78,0x1a,0x7e,0x1f, +0x73,0x51,0x69,0x31,0x0, 0x10,0x5e,0x34,0x38,0x0, 0xa, 0x56,0x1e,0x54,0x1e,0x54, +0x1e,0x54,0x5e,0x54,0x0, 0x7, 0x80,0x60,0xbe,0xe0,0x90,0x40,0xc, 0xbe,0xe0,0x94, +0x38,0x7, 0x7c,0xbe,0x12,0x70,0x1, 0x80,0x4f,0xbe,0xe0,0x99,0x68,0x5, 0xbe,0xe0, +0x9a,0x78,0x1d,0x7e,0xa3,0x4d,0x45,0x7c,0xba,0x4, 0x7a,0xb3,0x4d,0x45,0xa, 0x3a, +0x9, 0xf3,0x51,0xc2,0xbe,0xe0,0x9a,0x78,0x3, 0x75,0xf, 0x99,0x7c,0xbf,0x80,0x28, +0xbe,0xe0,0x9b,0x78,0x6, 0x7e,0xb3,0x4d,0x47,0x80,0x1d,0xbe,0xe0,0xf6,0x78,0x6, +0x7e,0xb3,0x3, 0xfa,0x80,0x12,0xbe,0xe0,0xf7,0x78,0xc, 0x7e,0x57,0x3, 0xfb,0x7e, +0x44,0x0, 0x64,0x8d,0x54,0x80,0x1, 0xe4,0xda,0x79,0x22,0x7c,0x6b,0x7e,0x70,0xff, +0x7c,0xb6,0x24,0x8c,0xbe,0xb0,0xa, 0x40,0x2, 0x41,0xd7,0x7e,0xa0,0x3, 0xa4,0x90, +0x4a,0x43,0x73,0x2, 0x4a,0x81,0x2, 0x4a,0xd7,0x2, 0x4a,0x61,0x2, 0x4a,0x6f,0x2, +0x4a,0x78,0x2, 0x4a,0x8a,0x2, 0x4a,0xa6,0x2, 0x4a,0x95,0x2, 0x4a,0xab,0x2, 0x4a, +0xab,0x7e,0x1f,0x73,0x51,0x69,0x31,0x0, 0xe, 0x5e,0x34,0x0, 0x4, 0x80,0x68,0x7e, +0x1f,0x73,0x51,0x12,0x3c,0x82,0x80,0x5f,0x12,0x4a,0xf0,0x5e,0x34,0x0, 0x2, 0x80, +0x56,0x12,0x4a,0xf0,0x5e,0x34,0x0, 0x1, 0x80,0x4d,0x12,0x4a,0xf0,0x5e,0x34,0x4, +0x0, 0xa, 0x36,0x80,0xb, 0x12,0x4a,0xf0,0x5e,0x34,0x8, 0x0, 0xa, 0x36,0x1e,0x34, +0x1e,0x34,0x1e,0x34,0x80,0x31,0x7e,0x71,0xef,0x80,0x2c,0x7e,0x73,0x72,0xfd,0x7c, +0xb7,0x4, 0x7a,0xb3,0x72,0xfd,0xa, 0x27,0x9, 0x72,0x1, 0x5f,0x7e,0xb3,0x71,0x7c, +0x4, 0x7a,0xb3,0x71,0x7c,0x70,0x9, 0x7e,0xb3,0x71,0x7b,0x4, 0x7a,0xb3,0x71,0x7b, +0xa5,0xbe,0x7d,0x3, 0x75,0xf, 0x7c,0x7c,0xb7,0x22,0x2e,0x14,0x0, 0x14,0xb, 0xa, +0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x75,0x1b,0x1, 0x74,0x1, 0x7a,0xb3,0x73,0x8, +0x7e,0x1f,0x73,0x51,0x69,0x31,0x0, 0x6, 0x22,0xd2,0xd, 0xd2,0xe, 0x12,0x4a,0xf0, +0x5e,0x34,0x0, 0x2, 0x68,0x3, 0x2, 0x4b,0xa, 0x22,0x12,0xb, 0xb0,0x20,0x21,0x3, +0x2, 0x4b,0x25,0x22,0xd2,0xd, 0xd2,0xe, 0x12,0x4a,0xf0,0x5e,0x34,0x0, 0x2, 0x78, +0x3, 0x2, 0x4b,0xa, 0x22,0x12,0xb, 0xe5,0x12,0xd0,0xc1,0x74,0x2, 0x7a,0xb3,0x3, +0xcf,0x7a,0xb3,0x3, 0xd0,0x22,0xd2,0xb, 0xd2,0xe, 0x12,0x4a,0xf0,0x5e,0x34,0x0, +0x1, 0x68,0x8, 0xe4,0x7a,0xb3,0x72,0xfc,0x2, 0x4b,0xa, 0x22,0x7c,0x7b,0x6c,0xaa, +0x12,0x4f,0xdf,0x78,0x9, 0x7c,0xb7,0x12,0x74,0x4, 0x7c,0xab,0x80,0xa, 0xb4,0x4, +0x7, 0x7c,0xb7,0x12,0x48,0x83,0x7c,0xab,0x7c,0xba,0x22,0x30,0x90,0x19,0xc2,0x90, +0xe5,0x8, 0x70,0x9, 0x75,0x8, 0x1, 0xe5,0x91,0xf5,0xf, 0x80,0x11,0x7e,0x71,0x91, +0xe5,0xf, 0x12,0x4b,0x96,0x5, 0xf, 0x30,0x91,0xb, 0xc2,0x91,0x5, 0xf, 0xe5,0xf, +0x12,0x4b,0x4c,0xf5,0x91,0x22,0x7c,0x6b,0x12,0x4f,0xdf,0x78,0x5, 0x7c,0xb6,0x2, +0x71,0xba,0xb4,0x4, 0x5, 0x7c,0xb6,0x2, 0x4b,0xab,0x22,0xca,0x79,0x7c,0xf7,0x7c, +0xeb,0xbe,0xe0,0xfa,0x78,0x4, 0x7a,0xf3,0x4d,0x46,0x4c,0xee,0x78,0x7, 0x7c,0xbf, +0x12,0x71,0xfe,0xe1,0xb4,0xbe,0xe0,0xf, 0x78,0xe, 0x74,0x1, 0x7a,0xb3,0x71,0x67, +0x7a,0xb3,0x71,0x68,0xd2,0x23,0xe1,0xd3,0xbe,0xe0,0x2e,0x78,0xe, 0x74,0x1, 0x7a, +0xb3,0x71,0x86,0x7a,0xb3,0x71,0x87,0xd2,0x23,0xe1,0xd3,0xbe,0xe0,0x12,0x78,0x6, +0x7a,0xf3,0x71,0x6a,0xe1,0xd3,0xbe,0xe0,0x11,0x78,0x34,0xbe,0xf0,0x1, 0x78,0x1f, +0x7e,0xb3,0x71,0x69,0x60,0x2, 0xe1,0xd3,0x74,0x1, 0x7a,0xb3,0x71,0x69,0xe4,0x7a, +0xb3,0x71,0x6b,0x7e,0xb3,0x71,0x58,0x44,0x80,0x7a,0xb3,0x71,0x58,0xe1,0xd3,0x4c, +0xff,0x68,0x2, 0xe1,0xd3,0x7e,0x1f,0x22,0xe0,0x7a,0x37,0x51,0xbb,0xe1,0xd3,0xbe, +0xe0,0x99,0x68,0x5, 0xbe,0xe0,0x9a,0x78,0x1d,0x7e,0xa3,0x4d,0x47,0x7c,0xba,0x4, +0x7a,0xb3,0x4d,0x47,0xa, 0x3a,0x19,0xf3,0x51,0xc2,0xbe,0xe0,0x9a,0x68,0x2, 0xe1, +0xd3,0x75,0xf, 0x99,0xe1,0xd3,0xbe,0xe0,0x9b,0x78,0xa, 0x7a,0xf3,0x4d,0x47,0x7a, +0xf3,0x4d,0x45,0xe1,0xd3,0xbe,0xe0,0x1, 0x78,0xe, 0x12,0xdd,0xd3,0x7a,0xf3,0x71, +0x59,0x7c,0xbf,0x12,0x63,0x20,0xe1,0xb4,0xbe,0xe0,0x5b,0x28,0x2, 0xc1,0xb4,0xbe, +0xe0,0x30,0x78,0x11,0x7e,0x73,0x71,0x88,0xbc,0x7f,0x78,0x2, 0xe1,0xd3,0xbe,0xf0, +0x4, 0x40,0x2, 0xe1,0xd3,0xbe,0xe0,0x20,0x40,0xc, 0xbe,0xe0,0x22,0x38,0x7, 0xbe, +0xf0,0x3, 0x28,0x2, 0xe1,0xd3,0x7c,0xbe,0x24,0xf9,0xbe,0xb0,0x29,0x40,0x2, 0xa1, +0x34,0x7e,0xa0,0x3, 0xa4,0x90,0x4c,0xb9,0x73,0x2, 0x4f,0xd3,0x2, 0x4d,0x34,0x2, +0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4f,0xd3,0x2, 0x4f,0xd3,0x2, 0x4f,0xd3,0x2, 0x4f, +0xd3,0x2, 0x4d,0x34,0x2, 0x4f,0xd3,0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4d,0x34, +0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, +0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4d, +0x34,0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4d,0x34, +0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4d,0x34,0x2, +0x4d,0x34,0x2, 0x4d,0x34,0x2, 0x4f,0xd3,0x2, 0x4f,0xd3,0x2, 0x4f,0xd3,0x2, 0x4d, +0x34,0x2, 0x4f,0xd3,0xa, 0x3e,0x19,0xf3,0x71,0x58,0x7c,0xbe,0x1b,0xb2,0xbe,0xb0, +0x34,0x40,0x2, 0xc1,0x6f,0x7e,0xa0,0x3, 0xa4,0x90,0x4d,0x4d,0x73,0x2, 0x4d,0xe9, +0x2, 0x4e,0x6f,0x2, 0x4d,0xe9,0x2, 0x4e,0x6f,0x2, 0x4d,0xed,0x2, 0x4d,0xe9,0x2, +0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e, +0x6f,0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e,0x6f, +0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e,0x35,0x2, +0x4e,0x6f,0x2, 0x4e,0x42,0x2, 0x4e,0x6f,0x2, 0x4e,0x55,0x2, 0x4d,0xe9,0x2, 0x4d, +0xe9,0x2, 0x4d,0xf2,0x2, 0x4d,0xf2,0x2, 0x4d,0xf2,0x2, 0x4e,0x6f,0x2, 0x4e,0x64, +0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4d,0xfb,0x2, 0x4d,0xfb,0x2, +0x4d,0xfb,0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e, +0x6f,0x2, 0x4d,0xe9,0x2, 0x4e,0x4, 0x2, 0x4e,0xd, 0x2, 0x4e,0x16,0x2, 0x4e,0x1f, +0x2, 0x4e,0x6f,0x2, 0x4e,0x6f,0x2, 0x4e,0x28,0xd2,0x23,0xc1,0x6f,0x12,0x0, 0x26, +0x80,0x7d,0x7e,0x37,0x4d,0x4d,0x4e,0x60,0x20,0x80,0x34,0x7e,0x37,0x4d,0x4d,0x4e, +0x60,0x1, 0x80,0x2b,0x7e,0x37,0x4d,0x4d,0x4e,0x70,0x1, 0x80,0x22,0x7e,0x37,0x4d, +0x4d,0x4e,0x70,0x2, 0x80,0x19,0x7e,0x37,0x4d,0x4d,0x4e,0x70,0x4, 0x80,0x10,0x7e, +0x37,0x4d,0x4d,0x4e,0x70,0x8, 0x80,0x7, 0x7e,0x37,0x4d,0x4d,0x4e,0x70,0x10,0x7a, +0x37,0x4d,0x4d,0x80,0x3a,0x7e,0x73,0x71,0x70,0x12,0x4f,0xd6,0x7a,0x37,0x4d,0x41, +0x80,0x2d,0x7e,0x73,0x71,0x72,0x12,0x4f,0xd6,0x3e,0x34,0x7a,0x37,0x51,0xb9,0x7a, +0x37,0x4d,0x49,0x80,0x1a,0x7e,0x73,0x71,0x74,0x12,0x4f,0xd6,0x3e,0x34,0x7a,0x37, +0x4d,0x43,0x80,0xb, 0x7e,0x73,0x71,0x7b,0x12,0x4f,0xd6,0x7a,0x73,0x72,0xfd,0xbe, +0xe0,0x38,0x40,0x1c,0xbe,0xe0,0x56,0x38,0x17,0xa, 0x3e,0x5e,0x34,0x0, 0x1, 0xbe, +0x34,0x0, 0x1, 0x78,0xb, 0x7e,0x37,0x4d,0x4d,0x4e,0x70,0x20,0x7a,0x37,0x4d,0x4d, +0xbe,0xe0,0x58,0x40,0xb, 0x7e,0x37,0x4d,0x4d,0x4e,0x60,0x2, 0x7a,0x37,0x4d,0x4d, +0xbe,0xe0,0xa, 0x68,0x2, 0xe1,0xb4,0x7e,0x37,0x4d,0x4d,0x4e,0x60,0x4, 0x7a,0x37, +0x4d,0x4d,0xe1,0xb4,0xbe,0xe0,0x6c,0x68,0x5, 0xbe,0xe0,0x6d,0x78,0x2a,0x7e,0x37, +0x4d,0x4d,0x4e,0x70,0x80,0x7a,0x37,0x4d,0x4d,0x7e,0x37,0x4d,0x49,0x7d,0x23,0xb, +0x24,0x7a,0x27,0x4d,0x49,0x2e,0x37,0x4d,0x4b,0x7a,0x39,0xf0,0xbe,0xe0,0x6d,0x68, +0x2, 0xe1,0xb4,0x75,0xf, 0x6c,0xe1,0xb4,0xbe,0xe0,0x6e,0x68,0x5, 0xbe,0xe0,0x6f, +0x78,0x49,0x7e,0x37,0x4d,0x4d,0x4e,0x70,0x40,0x7a,0x37,0x4d,0x4d,0x7e,0x63,0x71, +0x70,0x6c,0x77,0x7e,0xb3,0x71,0x71,0xa, 0x2b,0x2d,0x23,0x4, 0x7a,0xb3,0x71,0x71, +0x70,0x9, 0x7e,0xb3,0x71,0x70,0x4, 0x7a,0xb3,0x71,0x70,0x7a,0x27,0x4d,0x41,0x12, +0x57,0xf6,0x7e,0x27,0x4d,0x41,0x7e,0x37,0x4d,0x4f,0x2d,0x32,0x7a,0x39,0xf0,0xbe, +0xe0,0x6f,0x68,0x2, 0xe1,0xb4,0x75,0xf, 0x6e,0x80,0x79,0xbe,0xe0,0x70,0x40,0xe, +0xbe,0xe0,0x7f,0x38,0x9, 0x7c,0xbe,0x7c,0x7f,0x12,0x60,0x40,0x80,0x66,0xbe,0xe0, +0x86,0x78,0xf, 0x7c,0xbf,0x54,0x7, 0x7a,0xb3,0x4d,0x48,0x53,0xc3,0xf8,0x42,0xc3, +0x80,0x52,0xbe,0xe0,0x87,0x78,0xf, 0x7c,0xbf,0x54,0x3, 0x7a,0xb3,0x4d,0x40,0x53, +0xc2,0xfc,0x42,0xc2,0x80,0x3e,0xbe,0xe0,0x88,0x78,0x21,0x5e,0xf0,0x7, 0x12,0x4f, +0xe7,0x5e,0x60,0xc7,0x1b,0xa, 0x30,0xa, 0x3f,0x7d,0x23,0x7c,0x45,0x6c,0x55,0x12, +0x33,0x70,0x12,0x4f,0xe7,0x4d,0x32,0x1b,0xa, 0x30,0x80,0x18,0xbe,0xe0,0xf6,0x78, +0x6, 0x7a,0xf3,0x3, 0xfa,0x80,0xd, 0xbe,0xe0,0xf7,0x78,0x8, 0x74,0x64,0xac,0xbf, +0x7a,0x57,0x3, 0xfb,0x30,0x23,0xa, 0x7e,0xb3,0x71,0x66,0x44,0x1, 0x7a,0xb3,0x71, +0x66,0x7e,0x37,0x4d,0x4d,0x4d,0x33,0x68,0xa, 0x7e,0xb3,0x71,0x66,0x44,0x2, 0x7a, +0xb3,0x71,0x66,0xda,0x79,0x22,0x7c,0x47,0x6c,0x55,0xa, 0x3f,0x2d,0x32,0x22,0x7e, +0xb3,0x71,0x58,0xc4,0x54,0x7, 0x22,0x7e,0xf, 0x73,0x51,0x2e,0x14,0x0, 0x10,0xb, +0xa, 0x30,0x22,0xca,0xf8,0x7e,0x34,0x28,0x62,0x7e,0x24,0x0, 0xff,0x7e,0x14,0x61, +0xc9,0x74,0xc, 0x12,0x23,0x65,0x7e,0x57,0x51,0xc0,0x4d,0x55,0x78,0x4b,0x12,0x50, +0xcf,0x7c,0xba,0x30,0xe0,0x20,0x7d,0x14,0xb, 0x44,0x2e,0x17,0x51,0xbe,0x12,0x50, +0x64,0x19,0x41,0x61,0xc9,0x7d,0x14,0xb, 0x44,0x2e,0x17,0x51,0xbe,0x12,0x50,0x64, +0x19,0x41,0x61,0xc9,0x80,0x2, 0xb, 0x45,0x12,0x50,0xc7,0x78,0xd4,0x7d,0x43,0x6c, +0xff,0xa, 0x5f,0x9, 0x75,0x61,0xc9,0x7d,0x54,0xb, 0x44,0x2e,0x57,0x51,0xbe,0x7a, +0x59,0x70,0xb, 0xf0,0xbe,0xf0,0xc, 0x78,0xe8,0xda,0xf8,0x22,0x7d,0x14,0xb, 0x44, +0x2e,0x17,0x51,0xbb,0x7e,0x19,0x40,0x7c,0x35,0xb, 0x50,0xa, 0x13,0x22,0xca,0xf8, +0x7e,0x34,0x28,0x56,0x7e,0x24,0x0, 0xff,0x7e,0x14,0x66,0x3d,0x74,0xc, 0x12,0x23, +0x65,0x7e,0x57,0x4d,0x43,0x4d,0x55,0x78,0x3b,0x12,0x50,0xcf,0x7c,0xba,0x30,0xe0, +0x10,0x12,0x50,0x5c,0x19,0x41,0x66,0x3d,0x12,0x50,0x5c,0x19,0x41,0x66,0x3d,0x80, +0x2, 0xb, 0x45,0x12,0x50,0xc7,0x78,0xe4,0x7d,0x43,0x6c,0xff,0xa, 0x5f,0x9, 0x75, +0x66,0x3d,0x7d,0x54,0xb, 0x44,0x2e,0x57,0x51,0xbb,0x7a,0x59,0x70,0xb, 0xf0,0xbe, +0xf0,0xc, 0x78,0xe8,0xda,0xf8,0x22,0x1e,0xa0,0xb, 0xf0,0xbe,0xf0,0x4, 0x22,0x7e, +0xa3,0x6e,0x2, 0x7e,0x37,0x6d,0xfe,0x3e,0x34,0x6c,0x55,0x7d,0x43,0x6c,0xff,0x22, +0x7e,0xa3,0x71,0x5c,0xbe,0xa0,0x5, 0x78,0x8, 0x74,0x1, 0x7a,0xb3,0x71,0x5c,0x80, +0x1b,0xbe,0xa0,0x4, 0x78,0x1c,0x74,0x1, 0x7a,0xb3,0x71,0x5c,0x7e,0x34,0x21,0x57, +0x12,0x30,0xa4,0x12,0x47,0xd6,0x12,0x28,0x7d,0x12,0x53,0xbc,0x74,0x2, 0x7a,0xb3, +0x71,0x5c,0x22,0xe4,0x7a,0xb3,0x29,0x6c,0x7a,0xb3,0x29,0x6d,0x6c,0xaa,0x12,0xbd, +0xd0,0x78,0xfb,0xe4,0x7a,0xb3,0x29,0xe1,0x7a,0xb3,0x29,0x6e,0x30,0x1, 0x3, 0x12, +0x28,0x82,0x22,0x30,0x23,0x7b,0xc2,0x23,0x12,0x50,0xe0,0xd2,0x2, 0x12,0x2f,0x50, +0x7e,0x73,0x71,0x88,0xbe,0x73,0x73,0x8, 0x68,0xc, 0x7a,0x73,0x73,0x8, 0x12,0x3f, +0x90,0xd2,0x1, 0x12,0x51,0x13,0x7e,0xb3,0x71,0x76,0xbe,0xb3,0x69,0x90,0x68,0x14, +0x54,0x5, 0x7a,0xb3,0x71,0x76,0x7e,0x73,0x71,0x76,0x7a,0x73,0x69,0x90,0x12,0x51, +0xcf,0x12,0x52,0x38,0x7e,0xb3,0x71,0x77,0xbe,0xb3,0x69,0x91,0x68,0x14,0x54,0x5, +0x7a,0xb3,0x71,0x77,0x7e,0x73,0x71,0x77,0x7a,0x73,0x69,0x91,0x12,0x51,0xcf,0x12, +0x52,0x38,0x7e,0xb3,0x71,0x66,0x54,0xfe,0x7a,0xb3,0x71,0x66,0x7e,0xb3,0x71,0x67, +0x60,0x3, 0x12,0x2a,0xad,0x7e,0xb3,0x71,0x86,0x60,0x3, 0x12,0x3d,0x8, 0x12,0x2a, +0x60,0x7e,0x37,0x4d,0x4d,0x4d,0x33,0x68,0x15,0xd2,0x2, 0x12,0x2f,0x50,0x12,0x37, +0xfb,0x7e,0xb3,0x71,0x66,0x54,0xfd,0x7a,0xb3,0x71,0x66,0x2, 0x2a,0x60,0x22,0x7e, +0xb3,0x69,0x90,0x7e,0x73,0x69,0x91,0x12,0x51,0xe3,0x7e,0xb3,0x69,0x90,0x7e,0x73, +0x69,0x91,0x22,0x7c,0x6b,0x7c,0x56,0x5e,0x50,0x4, 0x1e,0x50,0xa, 0x45,0x7c,0xb6, +0x54,0x1, 0xa, 0x5b,0x2d,0x54,0x7c,0xab,0x7c,0x67,0x5e,0x60,0x4, 0x1e,0x60,0xa, +0x26,0x7c,0xb7,0x54,0x1, 0xa, 0x3b,0x2d,0x32,0x7c,0xb7,0xa, 0x4b,0x3e,0x44,0x3e, +0x44,0xa, 0x5a,0x2d,0x54,0x7c,0xab,0x7a,0xa3,0x6e,0x2, 0xe4,0x7a,0xb3,0x6e,0x3, +0x7e,0x70,0x4, 0x7c,0xba,0x30,0xe0,0x9, 0x7e,0xb3,0x6e,0x3, 0x4, 0x7a,0xb3,0x6e, +0x3, 0x1e,0xa0,0x1b,0x70,0x78,0xec,0x22,0xca,0xd8,0xca,0x79,0x7c,0xf7,0x7c,0xeb, +0xe4,0x12,0x42,0x7a,0x6c,0xdd,0x7e,0x70,0xb5,0xac,0x7d,0x2e,0x34,0x1, 0x0, 0x2e, +0x34,0x0, 0x16,0x7a,0x37,0x61,0xc9,0x12,0x7, 0x40,0x7a,0x37,0x61,0xcb,0x7e,0x37, +0x61,0xc9,0x12,0x8, 0x0, 0x7a,0x37,0x61,0xcd,0x7e,0x27,0x61,0xcb,0x5e,0x50,0xf8, +0x7a,0x27,0x61,0xcb,0x5e,0x70,0xf8,0x7a,0x37,0x61,0xcd,0x7c,0xbe,0x54,0x5, 0xa, +0x3b,0x4e,0x37,0x61,0xcb,0x7a,0x37,0x61,0xcb,0x7c,0xbf,0x54,0x5, 0xa, 0x3b,0x4e, +0x37,0x61,0xcd,0x7a,0x37,0x61,0xcd,0x7e,0x37,0x61,0xc9,0x7e,0x27,0x61,0xcb,0x12, +0x6, 0x48,0x7e,0x37,0x61,0xc9,0x7e,0x27,0x61,0xcd,0x12,0x6, 0xc5,0xb, 0xd0,0xbe, +0xd0,0x3, 0x40,0x92,0xda,0x79,0xda,0xd8,0x22,0x12,0x53,0x52,0x7e,0xb3,0x73,0x1f, +0xb4,0x3, 0x79,0x12,0x51,0x33,0x12,0x53,0xbc,0x7e,0x34,0x9, 0xc4,0x12,0x47,0xd6, +0x7e,0xb3,0x71,0x58,0x30,0xe7,0x60,0x7e,0xb3,0x71,0x69,0x70,0x5, 0xc2,0x2, 0x12, +0x2f,0x50,0x12,0x2f,0x60,0x30,0xe, 0xd, 0xc2,0xe, 0x12,0x3f,0x90,0xd2,0x1, 0x12, +0x51,0x13,0x12,0x2a,0x60,0x7e,0xb3,0x71,0x69,0x70,0x5, 0x12,0x7f,0xfa,0x80,0x6, +0x12,0x7e,0x8c,0x12,0x57,0xb5,0x7e,0xb3,0x6d,0xfb,0xb4,0x1, 0x17,0x12,0xb3,0x8b, +0x74,0x2, 0x12,0xc3,0x6, 0x12,0xd9,0xe3,0x12,0x58,0x4d,0x12,0x57,0xaa,0x12,0x7f, +0xa1,0x12,0x35,0xc0,0x12,0x70,0x2e,0x7e,0xb3,0x71,0x69,0x70,0xa, 0x7e,0xb3,0x71, +0x58,0x54,0x7f,0x7a,0xb3,0x71,0x58,0x12,0x6f,0x96,0x80,0x80,0xd2,0x25,0xd2,0x2, +0x12,0x2f,0x50,0x2, 0x53,0x46,0xe4,0x7a,0xb3,0x3, 0xfa,0x6d,0x33,0x7a,0x37,0x3, +0xfb,0x22,0xe4,0x7a,0xb3,0x71,0xb, 0x6d,0x33,0x7a,0x37,0x51,0xb9,0x7e,0x73,0x71, +0x5e,0x7a,0x73,0x6d,0xfb,0x12,0x54,0x2c,0x12,0x3f,0x90,0xc2,0x1, 0x12,0x51,0x13, +0x7e,0x34,0x4, 0x68,0xca,0x39,0x7e,0x1f,0x22,0xdc,0x7e,0xf, 0x22,0xe0,0x12,0x24, +0x14,0x1b,0xfd,0x12,0x2a,0x60,0x2, 0x53,0x89,0x7e,0x8, 0x29,0xe9,0x7e,0x34,0x0, +0xa, 0xe4,0x2, 0x24,0x39,0xe4,0x7a,0xb3,0x71,0xb, 0x74,0x1, 0x7a,0xb3,0x73,0x8, +0x7a,0xb3,0x6d,0xfb,0x12,0x57,0xee,0x12,0x54,0x2c,0x12,0x3e,0xdc,0x12,0x3f,0xa3, +0x12,0x47,0xd2,0x12,0xaf,0x49,0x12,0x53,0x89,0x2, 0x28,0x7d,0x74,0x5, 0x7a,0xb3, +0x3, 0xfd,0x12,0x2f,0x60,0x7e,0xb3,0x6d,0xfc,0x60,0x11,0x80,0xa, 0x7e,0x34,0x9, +0xc4,0x12,0x47,0xd6,0x12,0x2f,0x60,0x12,0xd2,0x8c,0x50,0xf1,0x7e,0xb3,0x6d,0xfd, +0x60,0x11,0x80,0xa, 0x7e,0x34,0x9, 0xc4,0x12,0x47,0xd6,0x12,0x2f,0x60,0x12,0x54, +0xdd,0x50,0xf1,0x2, 0x53,0xf6,0x7e,0x63,0x73,0x8, 0x7e,0x73,0x29,0x6b,0x74,0x26, +0xa5,0xbe,0x3, 0x8, 0xac,0xb7,0x49,0x15,0x29,0x83,0x80,0x6, 0xac,0xb7,0x49,0x15, +0x29,0x7f,0x7d,0x21,0x7a,0x27,0x4d,0x4f,0x30,0x12,0x10,0x7e,0x24,0x0, 0x27,0xca, +0x29,0x12,0xdd,0x94,0x12,0x24,0x14,0x1b,0xfd,0xc2,0x12,0x22,0x7e,0x8, 0x3, 0xab, +0x7e,0x34,0x0, 0x20,0xe4,0x12,0x24,0x39,0x7e,0x34,0x0, 0x1, 0x7a,0x37,0x3, 0xab, +0x7a,0xb3,0x3, 0xad,0x74,0x1, 0x7a,0xb3,0x3, 0xae,0xe4,0x7a,0xb3,0x3, 0xaf,0xe5, +0x1a,0xb4,0x1, 0x3f,0x7e,0x34,0x0, 0x2, 0x12,0x54,0xba,0x7a,0xb3,0x3, 0xb7,0x7e, +0x73,0x72,0xff,0x1e,0x34,0xb, 0x34,0x7a,0x73,0x3, 0xb8,0x74,0x1, 0x7a,0xb3,0x3, +0xb9,0xe4,0x7a,0xb3,0x3, 0xba,0x7e,0x34,0x0, 0x2, 0x12,0x54,0xca,0x7e,0x73,0x72, +0xff,0x1e,0x34,0xb, 0x34,0x7a,0x73,0x3, 0xc0,0x7a,0xb3,0x3, 0xc1,0x7a,0xb3,0x3, +0xc2,0x80,0xe, 0x7e,0x34,0x0, 0x1, 0x12,0x54,0xba,0x7a,0xb3,0x3, 0xb7,0x12,0x54, +0xca,0x7e,0x34,0x0, 0x1, 0x7a,0x37,0x3, 0xc3,0x74,0x1, 0x7a,0xb3,0x3, 0xc5,0x7a, +0xb3,0x3, 0xc6,0x74,0x2, 0x7a,0xb3,0x3, 0xc7,0x22,0x7a,0x37,0x3, 0xb3,0x74,0x1, +0x7a,0xb3,0x3, 0xb5,0x7a,0xb3,0x3, 0xb6,0xe4,0x22,0x7a,0x37,0x3, 0xbb,0x74,0x1, +0x7a,0xb3,0x3, 0xbd,0x7a,0xb3,0x3, 0xbe,0x7a,0xb3,0x3, 0xbf,0x22,0xca,0x79,0x6c, +0xee,0x7e,0xf3,0x73,0x8, 0x20,0xb, 0x6, 0x20,0xc, 0x3, 0x30,0xd, 0x3, 0xc3,0xa1, +0x7e,0x7e,0x24,0x0, 0x1, 0x7c,0xbf,0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0x7e,0x73, +0x6d,0xfd,0x6c,0x66,0x5c,0x75,0x4d,0x33,0x68,0x73,0x7c,0xbf,0x12,0x7b,0x6b,0x50, +0x3, 0x7e,0xe0,0x1, 0x12,0x57,0xa2,0x7c,0x7e,0x12,0x55,0xb8,0x40,0x3, 0xc3,0x80, +0x5d,0x7c,0xbf,0x7e,0x73,0x29,0xf3,0x12,0x55,0x87,0xe4,0x7c,0x7f,0x12,0x57,0xbd, +0x7a,0xe1,0x2f,0x7e,0xf, 0x22,0xdc,0x7e,0x18,0x1a,0x8, 0x7c,0xbf,0x12,0x56,0x33, +0x12,0x55,0x81,0x20,0xb, 0x6, 0x20,0xc, 0x3, 0x30,0xd, 0x3, 0xc3,0x80,0x2f,0x12, +0x2a,0x60,0x12,0xbf,0xf4,0xc2,0x1, 0x12,0x51,0x13,0x12,0x57,0x9b,0x60,0x5, 0x3e, +0x34,0x14,0x78,0xfb,0x6e,0x70,0xff,0x5e,0x73,0x6d,0xfd,0x7a,0x73,0x6d,0xfd,0x12, +0x47,0x8d,0x12,0xd1,0xc8,0x7c,0xbf,0x12,0xd6,0x7a,0xd3,0x80,0x1, 0xd3,0xda,0x79, +0x22,0x7c,0xbf,0x7e,0x73,0x29,0x6b,0xca,0x79,0x7c,0xf7,0x7c,0xeb,0xd2,0x14,0x12, +0x3c,0xc7,0xbe,0xe0,0x3, 0x7c,0xbe,0x7e,0x70,0x26,0x78,0xc, 0xac,0x7f,0x49,0x13, +0x29,0x83,0x49,0x3, 0x29,0x81,0x80,0xa, 0xac,0x7f,0x49,0x13,0x29,0x7f,0x49,0x3, +0x29,0x7d,0x12,0x33,0x77,0xda,0x79,0x22,0xca,0xd8,0xca,0x79,0x7c,0xe7,0x7c,0xfb, +0xc2,0x0, 0x7c,0xbf,0x12,0xbd,0x76,0xe5,0x1b,0x60,0x5c,0x6c,0xdd,0x74,0x26,0xac, +0xbd,0x9, 0xb5,0x29,0x7c,0x60,0x37,0x12,0x57,0xa2,0x7c,0x7d,0x12,0x55,0x87,0xd2, +0x0, 0xbe,0xf0,0x3, 0x7a,0xe1,0x2f,0x74,0x26,0x78,0xc, 0xac,0xbd,0x49,0x15,0x29, +0x93,0x49,0x5, 0x29,0x91,0x80,0xa, 0xac,0xbd,0x49,0x15,0x29,0x8b,0x49,0x5, 0x29, +0x89,0x49,0x35,0x29,0x8f,0x49,0x25,0x29,0x8d,0x7c,0xbf,0x12,0x56,0x33,0x20,0xb, +0x6, 0x20,0xc, 0x3, 0x30,0xd, 0x9, 0x30,0x0, 0x3, 0x12,0x55,0x81,0xc3,0x80,0xe, +0xb, 0xd0,0xbe,0xd0,0x3, 0x40,0xa6,0x30,0x0, 0x3, 0x12,0x55,0x81,0xd3,0xda,0x79, +0xda,0xd8,0x22,0xca,0x3b,0xf5,0x2e,0x7f,0x31,0x7a,0xd, 0x2a,0x7e,0x18,0xc, 0xd0, +0x7a,0x1f,0x5d,0x37,0x12,0x2a,0x60,0x7e,0xd, 0x2a,0x12,0x56,0xed,0xe5,0x2f,0x60, +0xd, 0x7e,0x18,0x11,0x38,0x7a,0x1f,0x5d,0x3b,0x7f,0x3, 0x12,0x56,0xed,0xe4,0x68, +0x3, 0x12,0x2a,0x60,0xd2,0x2, 0x12,0x2f,0x50,0xe5,0x2f,0x60,0x2e,0x6d,0x33,0x80, +0x1a,0x7e,0x37,0x5d,0x35,0x7d,0x23,0x3e,0x24,0x7e,0xf, 0x5d,0x3b,0x2d,0x12,0xb, +0xa, 0x50,0x7d,0x23,0x3e,0x24,0x12,0x7d,0x40,0xb, 0x34,0x7a,0x37,0x5d,0x35,0x7e, +0x37,0x6d,0xfe,0xb, 0x36,0xbe,0x37,0x5d,0x35,0x38,0xd6,0x6d,0x33,0x80,0x26,0x7e, +0x37,0x5d,0x35,0x7d,0x23,0x3e,0x24,0x7e,0xf, 0x5d,0x37,0x2d,0x12,0xb, 0xa, 0x20, +0x3e,0x34,0x7e,0xd, 0x2a,0x2d,0x13,0xb, 0xa, 0x30,0x2d,0x32,0x1b,0xa, 0x30,0x7e, +0x37,0x5d,0x35,0xb, 0x34,0x7a,0x37,0x5d,0x35,0x7e,0x37,0x6d,0xfe,0xb, 0x36,0xbe, +0x37,0x5d,0x35,0x38,0xca,0x7e,0xd, 0x2a,0x7e,0xa1,0x2e,0x12,0x56,0xf5,0xe5,0x2f, +0x60,0x8, 0x7f,0x3, 0x7e,0xa1,0x2e,0x12,0x56,0xf5,0xda,0x3b,0x22,0x7e,0x34,0x4, +0x68,0xe4,0x2, 0x24,0x39,0x74,0xa, 0xa4,0x49,0x35,0x6f,0xb7,0x7d,0xb3,0x7f,0x70, +0x7d,0x3b,0x12,0x43,0xef,0x7c,0x7b,0xa, 0x57,0x2e,0x54,0x0, 0xb, 0x7e,0x18,0x0, +0x1, 0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0x74,0x4, 0x2f,0x11,0x14,0x78,0xfb,0x7d, +0x1b,0x12,0x22,0xbd,0x7f,0x61,0xbe,0xb4,0x0, 0x10,0x68,0x6e,0x7e,0x73,0x69,0x8c, +0x7a,0x73,0x5f,0x73,0x7e,0x73,0x69,0x8d,0x7a,0x73,0x5f,0x74,0x74,0xb, 0x7a,0xb3, +0x5f,0x75,0x7d,0xaf,0x7a,0xa7,0x5f,0x77,0x7a,0xa7,0x5f,0x7b,0xbe,0xb4,0x0, 0x2, +0x38,0xd, 0xe4,0x7a,0xb3,0x5f,0x75,0x7e,0xd4,0x0, 0x10,0x8d,0xdb,0x6d,0xcc,0x7e, +0x8, 0x5f,0x73,0x7d,0x3d,0x12,0x9, 0x50,0x7e,0x47,0x6d,0xfe,0x7e,0xa0,0x4, 0x7d, +0x34,0x3e,0x34,0x7f,0x57,0x2d,0xb3,0xb, 0x5a,0x10,0x7f,0x16,0x12,0x22,0xb4,0x7e, +0xb3,0x5f,0x75,0x60,0xc, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78, +0xf4,0x1b,0x5a,0x30,0xb, 0x44,0x1b,0xa0,0x78,0xd5,0x22,0x7e,0x34,0x0, 0x1, 0x7c, +0xbf,0x22,0xd2,0x2, 0x12,0x2f,0x50,0x7c,0xbf,0x22,0x7e,0xb3,0x73,0x1f,0xb4,0x3, +0x3, 0x2, 0xc3,0x92,0x22,0x7e,0xb3,0x71,0x84,0x7e,0x73,0x73,0xa, 0x14,0x68,0x1d, +0x4, 0x78,0x1a,0x7e,0x8, 0xc, 0xd0,0x7a,0xf, 0x22,0xd8,0x7e,0x8, 0x15,0xa0,0x7a, +0xf, 0x22,0xdc,0xa5,0xbf,0x3, 0x16,0x7e,0x18,0x1e,0x70,0x80,0xc, 0x7e,0x18,0x11, +0x38,0x7a,0x1f,0x22,0xd8,0x7e,0x18,0x1a,0x8, 0x7a,0x1f,0x22,0xdc,0x22,0x90,0x21, +0x50,0xe4,0x93,0xf5,0x1a,0x22,0x7e,0x37,0x6d,0xfe,0xbe,0x37,0x4d,0x41,0x38,0x4c, +0x7d,0x23,0x2e,0x24,0x0, 0xc, 0xbe,0x27,0x4d,0x41,0x38,0x9, 0x2e,0x34,0x0, 0xb, +0x7a,0x37,0x4d,0x41,0x22,0x7e,0xa3,0x6e,0x2, 0x7e,0x24,0x0, 0x2, 0x7d,0x42,0x7e, +0x37,0x4d,0x41,0x9e,0x37,0x6d,0xfe,0x8d,0x32,0x7c,0xb7,0x60,0x1a,0x1e,0xa0,0x14, +0x78,0xfb,0x80,0x13,0x7c,0xba,0x20,0xe0,0x13,0x7d,0x24,0x2e,0x27,0x4d,0x41,0x7a, +0x27,0x4d,0x41,0x1e,0xa0,0xb, 0x70,0xbe,0x70,0x4, 0x40,0xe8,0x22,0xca,0x79,0x7e, +0x14,0x28,0x53,0x7e,0x4, 0x0, 0xff,0x69,0x30,0x0, 0x1, 0x7e,0xb, 0x50,0x7a,0x37, +0x5d,0x8, 0x7a,0x53,0x5d,0x7, 0x6c,0xff,0x6d,0xcc,0x7e,0xb4,0xff,0xff,0x7e,0xb3, +0x51,0xbd,0xb4,0x1, 0x2, 0x80,0x2, 0x21,0x9a,0x7e,0xd4,0x4, 0x68,0xca,0xd9,0x7e, +0x1f,0x22,0xe0,0x7e,0x8, 0x48,0xd8,0x12,0x24,0x14,0x1b,0xfd,0x6d,0xaa,0x7d,0xda, +0x80,0x26,0x7d,0x2d,0x3e,0x24,0x49,0x12,0x48,0xd8,0xbe,0x14,0x0, 0x0, 0x8, 0x6, +0x49,0x32,0x48,0xd8,0x80,0x4, 0x6d,0x33,0x9d,0x31,0x59,0x32,0x48,0xd8,0xbd,0x3c, +0x28,0x4, 0x7d,0xc3,0x7d,0xbd,0xb, 0xd4,0x7e,0x37,0x6d,0xfe,0xbd,0x3d,0x38,0xd2, +0x7e,0x37,0x51,0xd2,0xbd,0x3c,0x50,0x4, 0x7a,0xc7,0x51,0xd2,0x7e,0x37,0x51,0xc8, +0xbd,0x3c,0x50,0x10,0xbe,0xb4,0xff,0xff,0x68,0xa, 0x7e,0x37,0x51,0xd0,0xb, 0x34, +0x7a,0x37,0x51,0xd0,0x7e,0x73,0x69,0x8d,0xa, 0x27,0x7d,0x3b,0x8d,0x32,0x7c,0xe5, +0xbe,0xe0,0x0, 0x40,0x8, 0xbe,0xe0,0x1d,0x38,0x3, 0x7e,0xf0,0x1, 0x7d,0xda,0x7d, +0x3d,0x3e,0x34,0x49,0x23,0x51,0xc2,0xbd,0x2c,0x50,0x55,0xbe,0xb4,0xff,0xff,0x68, +0x4f,0x9, 0xbd,0x51,0xd4,0xb4,0x1, 0x27,0x49,0x23,0x51,0xdd,0xbd,0x2b,0x78,0x10, +0x7d,0xa3,0x2e,0xa4,0x51,0xd7,0xb, 0xa8,0x20,0xb, 0x24,0x1b,0xa8,0x20,0x80,0x36, +0x4d,0xdd,0x78,0x18,0xbe,0xf0,0x1, 0x78,0x27,0x80,0x11,0x80,0x23,0x80,0xd, 0x4d, +0xdd,0x78,0x9, 0xbe,0xf0,0x1, 0x78,0x18,0x80,0x2, 0x80,0x14,0x59,0xb3,0x51,0xdd, +0x7e,0x24,0x0, 0x1, 0x59,0x23,0x51,0xd7,0x74,0x1, 0x19,0xbd,0x51,0xd4,0x80,0x6, +0x74,0x1, 0x19,0xbd,0x5d,0x7, 0x49,0xa3,0x51,0xca,0x49,0x23,0x51,0xd7,0xbd,0x2a, +0x28,0x4, 0x59,0x23,0x51,0xca,0x9, 0xbd,0x5d,0x7, 0xb4,0x1, 0x11,0x6d,0x22,0x59, +0x23,0x51,0xdd,0x6d,0xaa,0x59,0xa3,0x51,0xd7,0xe4,0x19,0xbd,0x51,0xd4,0xb, 0xd4, +0xbe,0xd4,0x0, 0x3, 0x68,0x2, 0x1, 0xff,0x80,0x1a,0x7e,0x8, 0x51,0xd4,0x7e,0x34, +0x0, 0x3, 0xe4,0x12,0x24,0x39,0x7e,0x8, 0x51,0xd7,0x12,0x59,0xb7,0x7e,0x8, 0x51, +0xdd,0x12,0x59,0xb7,0xda,0x79,0x22,0x7e,0x34,0x0, 0x6, 0x2, 0x24,0x39,0x7c,0x9b, +0x74,0x3, 0xac,0xb9,0x9, 0x85,0x6f,0xdd,0xbe,0x83,0x71,0x78,0x68,0x8, 0x7e,0x83, +0x71,0x78,0x19,0x85,0x6f,0xdd,0x9, 0x85,0x6f,0xde,0xbe,0x83,0x71,0x79,0x68,0x8, +0x7e,0x83,0x71,0x79,0x19,0x85,0x6f,0xde,0x9, 0x85,0x6f,0xdf,0xbe,0x83,0x71,0x7a, +0x68,0x8, 0x7e,0x83,0x71,0x7a,0x19,0x85,0x6f,0xdf,0x7e,0x8, 0x0, 0x53,0x12,0x42, +0x54,0x9, 0xb5,0x6f,0xdf,0x12,0x5a,0xb, 0x2, 0x4, 0x96,0x12,0xd, 0x7, 0x7e,0x37, +0x0, 0x53,0x7a,0x37,0x0, 0x8f,0x7e,0x34,0x0, 0x2, 0x7e,0x8, 0x0, 0x53,0x7e,0x24, +0x0, 0x1, 0x12,0x3, 0xfa,0x7e,0x34,0x0, 0x2, 0x7e,0x8, 0x0, 0x8f,0x7e,0x24,0x0, +0x1, 0x22,0x70,0x9, 0x12,0x5a,0xb5,0x12,0x5a,0xb, 0x2, 0x4, 0x96,0x22,0x70,0xc, +0x12,0x5a,0xb5,0x12,0xc, 0xea,0x12,0x5a,0xe, 0x2, 0x4, 0x96,0x22,0x12,0x4f,0xe7, +0x4e,0x70,0x10,0x1b,0xa, 0x30,0x12,0x5a,0xbf,0x12,0x5a,0x3e,0x74,0x14,0x12,0x72, +0x2d,0x7e,0xb3,0x73,0x8, 0x7e,0x73,0x6f,0xdd,0x12,0x5a,0x3e,0x7e,0xb3,0x73,0x8, +0x7e,0x73,0x6f,0xde,0x12,0x5a,0xad,0x7e,0x73,0x6f,0xdf,0x2, 0x5a,0x32,0x70,0xc, +0x12,0x5a,0xb5,0x12,0xd, 0x8d,0x12,0x5a,0xe, 0x2, 0x4, 0x96,0x22,0x7e,0xb3,0x73, +0x8, 0x7e,0x70,0x1, 0x12,0x5a,0xad,0x7e,0x70,0x1, 0x12,0x5a,0x32,0x12,0x5a,0xbf, +0x12,0x5a,0x3e,0x12,0x4f,0xe7,0x5e,0x70,0xef,0x1b,0xa, 0x30,0x22,0x12,0x5a,0x7e, +0x7e,0xb3,0x73,0x8, 0x22,0x5e,0x70,0x3, 0x7e,0x8, 0x0, 0x53,0x7c,0xb7,0x22,0x7e, +0xb3,0x73,0x8, 0x7e,0x70,0x2, 0x22,0xca,0x3b,0x7e,0x3f,0x73,0x51,0x69,0x33,0x0, +0x6, 0x5e,0x34,0x0, 0x1, 0x68,0x13,0x7f,0x3, 0x12,0x4a,0xda,0x5e,0x34,0x0, 0x2, +0x68,0x1b,0x12,0x3f,0x84,0x12,0x5, 0xbc,0x80,0x13,0x75,0x1b,0x0, 0xe4,0x7a,0xb3, +0x73,0x8, 0x7f,0x3, 0x12,0x2a,0x2d,0x12,0x5b,0x0, 0x12,0x5a,0x8d,0xda,0x3b,0x22, +0x5e,0x70,0xfe,0x1b,0xa, 0x30,0x22,0x12,0x79,0x3b,0x12,0x79,0xeb,0x12,0x79,0xc4, +0x12,0x7a,0x5d,0x12,0x5e,0xe9,0x12,0x30,0xac,0x12,0x7a,0x3e,0x12,0x5b,0x75,0x12, +0xb6,0x3f,0x12,0x5a,0xc7,0x2, 0x5b,0x28,0xd2,0x1, 0x12,0x51,0x13,0x6c,0xaa,0x7e, +0x63,0x73,0x8, 0x7e,0x70,0x27,0xac,0x67,0x9, 0x63,0x6f,0x12,0xa, 0x2a,0x12,0x5f, +0xf1,0x7c,0x7b,0xbc,0x67,0x78,0x4, 0x7a,0xa3,0x29,0x6b,0x7e,0x50,0x26,0xac,0x5a, +0x19,0x72,0x29,0x6f,0xb, 0xa0,0xbe,0xa0,0x3, 0x78,0xd4,0x7e,0x73,0x29,0x6b,0xbe, +0x70,0x3, 0x40,0x5, 0xe4,0x7a,0xb3,0x29,0x6b,0x12,0x46,0xd1,0x7e,0x73,0x29,0x6b, +0x7a,0x73,0x29,0xf3,0x22,0x12,0x5b,0xb3,0x74,0x9, 0xac,0x7b,0x7e,0x8, 0x68,0xb, +0x12,0x5b,0xae,0x74,0x9, 0xac,0x7b,0x7e,0x8, 0x68,0xbf,0x12,0x5b,0xae,0x74,0x9, +0xac,0x7b,0x7e,0x8, 0x68,0x65,0x74,0xff,0x12,0x24,0x39,0x7e,0x8, 0x69,0x19,0x12, +0x5f,0x20,0x7e,0x8, 0x69,0x5f,0x7e,0x34,0x0, 0xc, 0xe4,0x2, 0x24,0x39,0x74,0xff, +0x12,0x24,0x39,0x90,0x21,0x51,0xe4,0x93,0x7c,0x7b,0x22,0xca,0x3b,0x75,0x28,0x0, +0x75,0x29,0x0, 0x75,0x2a,0x0, 0x75,0x2b,0x0, 0x75,0x2d,0x0, 0x75,0x2e,0x3, 0xc2, +0x0, 0xc2,0x1, 0x7e,0x18,0x6e,0x72,0x7a,0x1f,0x5d,0x9, 0x7e,0x38,0x69,0x19,0xe4, +0x7e,0x34,0x6e,0x73,0x7e,0x24,0x0, 0x0, 0x7a,0x1b,0xb0,0x12,0xc5,0x99,0x7e,0xb3, +0x69,0x68,0x70,0xe, 0x7e,0xb3,0x69,0x64,0x70,0x8, 0x7e,0xb3,0x69,0x65,0x70,0x2, +0xc1,0x9a,0x30,0x24,0x6, 0x7e,0x18,0x6e,0xb0,0x80,0x4, 0x7e,0x18,0x6e,0x72,0x7a, +0x1f,0x5d,0x9, 0x7e,0xf, 0x5d,0x9, 0x12,0x5f,0x6a,0x75,0x26,0x0, 0xc1,0x36,0x7e, +0x71,0x26,0x74,0x9, 0xac,0x7b,0x49,0xc3,0x68,0x65,0x49,0x23,0x68,0x67,0x7a,0x27, +0x5d,0x7, 0x9, 0xb3,0x68,0x69,0xf5,0x2c,0x90,0x21,0x51,0xe4,0x93,0xbe,0xb1,0x2c, +0x38,0x2, 0xc1,0x34,0x7e,0xa1,0x2c,0x5e,0xa0,0xf, 0x74,0x7, 0xa4,0x7f,0x3, 0x2d, +0x15,0x7e,0xb, 0xb0,0xf5,0x2e,0x60,0x5, 0xe5,0x2e,0xb4,0x2, 0x11,0x7e,0xa0,0x2, +0x7e,0x51,0x2c,0x74,0x7, 0xac,0x5b,0x7f,0x3, 0x2d,0x12,0x7a,0xb, 0xa0,0x9, 0xb3, +0x68,0x6c,0x9, 0x73,0x68,0x6d,0x7e,0x61,0x2c,0x12,0x84,0xd, 0x92,0x1, 0x30,0x1, +0x3c,0x12,0x5e,0xc8,0x7f,0x3, 0x2d,0x13,0x29,0xb0,0x0, 0x6, 0x70,0x6, 0x74,0x1, +0x39,0xb0,0x0, 0x6, 0x7f,0x3, 0x2d,0x13,0x29,0x50,0x0, 0x6, 0xbe,0x50,0x1, 0x28, +0x2, 0xa1,0x43,0xe5,0x2e,0x70,0x5, 0x75,0x2e,0x3, 0x80,0x8, 0xe5,0x2e,0xb4,0x2, +0x3, 0x75,0x2e,0x1, 0xd2,0x0, 0x74,0x3, 0x7a,0xb, 0xb0,0x80,0x32,0xe5,0x2e,0x70, +0x3a,0x12,0x5e,0xd0,0x7e,0xa3,0x71,0x34,0x74,0x5, 0xa4,0xbd,0x35,0x28,0x10,0x7e, +0xa3,0x71,0x35,0x74,0x5, 0xa4,0x12,0x5f,0xe5,0x9d,0xd5,0xbd,0x3d,0x40,0x64,0x75, +0x2e,0x3, 0x7e,0xa0,0x3, 0x12,0x5e,0xc8,0x7f,0x3, 0x2d,0x13,0x7a,0xb, 0xa0,0x74, +0x3, 0x2d,0x37,0x7d,0x26,0x39,0xb1,0x0, 0x1, 0x80,0x48,0x7e,0xa3,0x71,0x34,0x74, +0x2, 0xa4,0x7e,0x4, 0x0, 0x5, 0x7d,0xf5,0xad,0xf0,0x12,0x5e,0xd0,0xbd,0x3f,0x28, +0x32,0x7e,0x23,0x71,0x35,0x7e,0x30,0x2, 0xac,0x23,0xad,0x10,0x7e,0x54,0x21,0xde, +0x7e,0x44,0x0, 0xff,0xb, 0x2a,0xd0,0x9d,0xd1,0xbd,0x3d,0x50,0x16,0x7e,0xa1,0x2c, +0x74,0x7, 0xa4,0x7f,0x13,0x2d,0x35,0x29,0xb1,0x0, 0x6, 0x70,0x6, 0x74,0x2, 0x39, +0xb1,0x0, 0x6, 0xe5,0x2e,0xbe,0xb0,0x3, 0x78,0x2, 0xc1,0x34,0xe5,0x2e,0xb4,0x1, +0x49,0x6c,0xaa,0x7e,0x71,0x2c,0x74,0x3, 0xac,0x7b,0x19,0xa3,0x6e,0xef,0x12,0x5e, +0xc8,0x2d,0x37,0x7d,0x26,0x39,0xa1,0x0, 0x6, 0x75,0x27,0x0, 0x80,0x22,0x7e,0x71, +0x27,0x74,0x9, 0xac,0x7b,0x9, 0xb3,0x6e,0x8, 0x54,0xf, 0xbe,0xb1,0x2c,0x78,0xe, +0x49,0xc3,0x6e,0x4, 0x49,0xd3,0x6e,0x6, 0x7a,0xd7,0x5d,0x7, 0x80,0xc, 0x5, 0x27, +0x90,0x21,0x51,0xe4,0x93,0xbe,0xb1,0x27,0x38,0xd4,0x85,0x28,0x2f,0x7e,0x8, 0x0, +0x2a,0x7e,0x18,0x0, 0x2b,0xe5,0x26,0x12,0x78,0x31,0x5e,0xc4,0xf, 0xff,0x7e,0xd7, +0x5d,0x7, 0x5e,0xd4,0xf, 0xff,0x7a,0xd7,0x5d,0x7, 0x7e,0x91,0x26,0x74,0x9, 0xac, +0x9b,0x9, 0x74,0x68,0x69,0xa, 0x57,0xc4,0x54,0xf0,0x7c,0xab,0xe4,0x7d,0xd5,0x2e, +0xd7,0x5d,0x7, 0x7a,0xd7,0x5d,0x7, 0xbe,0x70,0xff,0x68,0x1a,0xe5,0x2e,0xbe,0xb0, +0x1, 0x68,0x2, 0x5, 0x28,0x5, 0x2d,0xe5,0x2e,0xa, 0x5b,0x3, 0x3, 0x54,0xc0,0x7c, +0xab,0xe4,0x2d,0xc5,0x80,0x4, 0x2e,0xc4,0xc0,0x0, 0x12,0x5e,0xdc,0x79,0xc1,0x0, +0x2, 0x7e,0xd7,0x5d,0x7, 0x12,0x5e,0xdc,0x79,0xd1,0x0, 0x4, 0x7e,0xa1,0x2a,0x7e, +0x31,0x29,0x74,0x6, 0xac,0x3b,0x7e,0x1f,0x5d,0x9, 0x2d,0x31,0x39,0xa1,0x0, 0x6, +0x7e,0xa1,0x2b,0x7e,0x31,0x29,0xac,0x3b,0x7e,0x1f,0x5d,0x9, 0x2d,0x31,0x39,0xa1, +0x0, 0x7, 0x5, 0x29,0x5, 0x26,0x7e,0x73,0x69,0x6b,0xbe,0x71,0x26,0x28,0x2, 0x81, +0x1f,0xe5,0x28,0x7e,0x1f,0x5d,0x9, 0x39,0xb1,0x0, 0x1, 0x7e,0x33,0x69,0x61,0x7e, +0x1f,0x5d,0x9, 0x7a,0x1b,0x30,0x7e,0xb3,0x71,0x36,0xb4,0x1, 0xf, 0x7e,0xb3,0x69, +0x65,0xb4,0x1, 0x1c,0x74,0x5, 0x7a,0xb3,0x73,0x4, 0x80,0xf, 0xe5,0x2d,0xbe,0xb0, +0x0, 0x38,0x6, 0x7e,0xb3,0x69,0x65,0x60,0x7, 0xb2,0x24,0xc2,0x87,0x12,0x79,0x29, +0x7e,0xb3,0x69,0x64,0x60,0x5, 0x7f,0x3, 0x12,0x5f,0x20,0xe4,0x7a,0xb3,0x69,0x68, +0x7a,0xb3,0x69,0x64,0x7a,0xb3,0x69,0x65,0x80,0x2, 0xd2,0x87,0x12,0x5f,0xda,0xca, +0x59,0x7e,0x18,0x68,0x65,0x7e,0x8, 0x6e,0x4, 0x12,0x24,0x14,0x1b,0xfd,0xe5,0x2d, +0x70,0x10,0x12,0x5b,0xb3,0x74,0x9, 0xac,0x7b,0x7e,0x8, 0x6e,0x4, 0x74,0xff,0x12, +0x24,0x39,0x12,0xc5,0x77,0xda,0x3b,0x22,0x7e,0x71,0x2c,0x74,0x7, 0xac,0x7b,0x22, +0x7e,0x51,0x26,0x74,0x9, 0xac,0x5b,0x49,0x32,0x68,0x65,0x22,0x7e,0xa1,0x29,0x74, +0x6, 0xa4,0x7e,0x1f,0x5d,0x9, 0x2d,0x35,0x22,0x7e,0x34,0x22,0x5, 0x12,0x30,0xa4, +0x7a,0x37,0x67,0xee,0x7e,0x34,0x22,0x7, 0x12,0x30,0xa4,0x7a,0x37,0x67,0xf0,0x7e, +0x34,0x22,0x9, 0x12,0x30,0xa4,0x12,0x5f,0xc5,0x7a,0xb3,0x67,0xf4,0x90,0x22,0xc, +0xe4,0x93,0x7a,0xb3,0x67,0xf5,0xe4,0x7a,0xb3,0x67,0xfe,0x7a,0xb3,0x67,0xff,0x22, +0xca,0xf8,0x6c,0xaa,0x80,0x38,0x7e,0xf0,0x3, 0x7e,0x90,0x7, 0xac,0x9a,0x7f,0x10, +0x2d,0x34,0x7a,0x1b,0xf0,0x74,0x3, 0x7f,0x10,0x2d,0x34,0x39,0xb1,0x0, 0x1, 0x7e, +0x34,0x7f,0xff,0x7f,0x70,0x2d,0xf4,0x79,0x37,0x0, 0x2, 0x7f,0x70,0x2d,0xf4,0x79, +0x37,0x0, 0x4, 0xe4,0x7f,0x10,0x2d,0x34,0x39,0xb1,0x0, 0x6, 0xb, 0xa0,0x90,0x21, +0x51,0xe4,0x93,0xbc,0xba,0x38,0xbf,0xda,0xf8,0x22,0x7e,0x34,0x0, 0x3e,0x74,0xff, +0x2, 0x24,0x39,0xe4,0x7a,0xb3,0x71,0x58,0x7e,0x8, 0x6e,0x72,0x12,0x5f,0x6a,0x7e, +0x8, 0x6e,0xb0,0x7e,0x34,0x0, 0x3e,0x12,0x24,0x39,0x7e,0x18,0x6e,0x72,0x7a,0x1f, +0x6f,0xc, 0x12,0x0, 0xfd,0x2, 0x5f,0x98,0x75,0x8, 0x0, 0x75,0xf, 0x0, 0x7e,0xb3, +0x71,0x58,0xf5,0x91,0x22,0xc2,0x92,0x12,0x5f,0xbd,0x90,0x1b,0xd8,0xe4,0x93,0x54, +0xfe,0xf5,0x92,0xd2,0xe8,0xc2,0xc0,0xa9,0xd4,0x95,0xd2,0xad,0x22,0x75,0x91,0x0, +0xc2,0x90,0xc2,0x91,0x22,0x7a,0x37,0x67,0xf2,0x90,0x22,0xb, 0xe4,0x93,0x22,0xc2, +0x8d,0xc2,0x8f,0x12,0x5f,0xbd,0xa9,0xc0,0x93,0x22,0x90,0x21,0x51,0xe4,0x93,0x7c, +0xab,0x74,0x9, 0xa4,0x22,0x7e,0x14,0x21,0xde,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0xd0, +0x22,0x2e,0x24,0x22,0x29,0x7a,0x51,0x82,0x7a,0x41,0x83,0xe4,0x93,0x22,0x7e,0x34, +0x2, 0x34,0x7a,0x35,0x28,0x7e,0x8, 0x4d,0x51,0x7e,0x18,0x5d,0x61,0x6d,0x55,0x80, +0x29,0x7d,0xf5,0x3e,0xf4,0x7f,0x61,0x2d,0xdf,0xb, 0x6a,0x40,0xbe,0x44,0x0, 0x64, +0x28,0x16,0x2d,0xf1,0x7d,0xe0,0xb, 0x7a,0xd0,0xbe,0xd4,0x0, 0x64,0x50,0x2, 0x80, +0x4, 0xbd,0xd4,0x28,0x3, 0x1b,0x7a,0x40,0xb, 0x54,0xbe,0x55,0x28,0x40,0xd2,0x22, +0x24,0x8a,0x78,0x19,0x7e,0xf, 0x73,0x51,0xa5,0xbf,0x0, 0x8, 0x12,0x60,0x62,0x5e, +0x70,0xfb,0x80,0x6, 0x12,0x60,0x62,0x4e,0x70,0x4, 0x1b,0xa, 0x30,0x22,0x7e,0xf, +0x73,0x51,0x2e,0x14,0x0, 0xe, 0xb, 0xa, 0x30,0x22,0xa9,0xd2,0xea,0xa9,0xc2,0xea, +0x6d,0x33,0x7e,0xf, 0x73,0x51,0x79,0x30,0x0, 0x10,0x12,0x4f,0xe7,0x4e,0x34,0xdc, +0xe, 0x1b,0xa, 0x30,0x7e,0x34,0x1, 0xc2,0x7e,0xf, 0x73,0x51,0x79,0x30,0x0, 0x1e, +0x12,0x60,0x5e,0x4e,0x70,0x10,0x1b,0xa, 0x30,0x12,0xdd,0x2c,0x12,0xb, 0xe5,0x7e, +0x34,0xff,0xff,0x7e,0xf, 0x73,0x51,0x79,0x30,0x0, 0x2, 0x6d,0x33,0x7e,0xf, 0x73, +0x51,0x79,0x30,0x0, 0x14,0x7e,0xf, 0x73,0x51,0x79,0x30,0x0, 0x4, 0x7e,0x34,0xf0, +0x4f,0x7e,0xf, 0x73,0x51,0x79,0x30,0x0, 0x4, 0xd2,0x2, 0x12,0x2a,0x86,0x53,0xc3, +0xf8,0x75,0xc3,0x83,0x53,0xc2,0xfc,0x43,0xc2,0x81,0xd2,0xac,0x2, 0x57,0xee,0xe4, +0x12,0xcc,0x7f,0x12,0xcf,0x6c,0x12,0x66,0xcb,0x12,0x5f,0xcf,0x12,0xcf,0x99,0x7e, +0x34,0x0, 0x1c,0x12,0xc, 0x65,0x7e,0x34,0x9, 0xc4,0x12,0x47,0xd6,0x12,0xcc,0xe8, +0x12,0xcc,0x7a,0x12,0xcf,0x93,0x12,0xcb,0x92,0x12,0xcc,0x9c,0x12,0xcc,0xa8,0x12, +0x5f,0x73,0x12,0xcc,0xb8,0x12,0x61,0x37,0x12,0x60,0x6a,0xd2,0xaf,0x12,0x66,0xe1, +0x90,0x1c,0x45,0xe4,0x93,0xca,0xb8,0x90,0x1c,0x46,0xe4,0x93,0x7c,0x7b,0x7e,0x24, +0x1, 0x33,0xda,0xb8,0x2, 0xb, 0x7b,0x2, 0x61,0x3a,0xd2,0x0, 0x12,0x61,0x5c,0xa9, +0xd0,0xcb,0xa9,0xc6,0xca,0x12,0xcc,0x6d,0xa9,0xd3,0x9e,0xa9,0xc3,0xb9,0xc2,0x8a, +0xd2,0xaa,0x2, 0x61,0x55,0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0x22,0xa9,0xd0,0xce,0x30, +0x0, 0x4, 0xa9,0xd5,0xc9,0x22,0xa9,0xc5,0xc9,0x22,0x12,0x62,0xbc,0x12,0x66,0xb1, +0x12,0x61,0xf6,0x12,0x61,0x5c,0xa9,0xd7,0xeb,0x74,0x1, 0x7e,0x70,0x82,0x12,0x62, +0x12,0xa9,0xc7,0xeb,0xd2,0x0, 0x12,0x61,0x5c,0xd2,0x0, 0x2, 0x61,0x8e,0x30,0x0, +0x5, 0x43,0xc3,0x80,0x80,0x3, 0x53,0xc3,0x7f,0x30,0x0, 0x5, 0x43,0xc2,0x80,0x80, +0x3, 0x53,0xc2,0x7f,0x7e,0xf, 0x73,0x51,0x30,0x0, 0x8, 0x12,0x4f,0xeb,0x4e,0x60, +0xc4,0x80,0x6, 0x12,0x4f,0xeb,0x5e,0x60,0x3b,0x1b,0xa, 0x30,0x22,0x12,0x62,0xf2, +0x40,0x6, 0x12,0x62,0xe7,0x12,0x0, 0x12,0x12,0x61,0xf6,0x12,0x61,0xfe,0x80,0xb, +0x7e,0xb3,0x71,0x36,0x60,0x2, 0x80,0x0, 0x12,0x62,0x93,0x30,0x11,0xf2,0x7e,0xb3, +0x73,0x4, 0xbe,0xb0,0x0, 0x28,0x5, 0x14,0x7a,0xb3,0x73,0x4, 0xd2,0x0, 0x12,0x61, +0xfe,0xd2,0x0, 0x2, 0x61,0x8e,0xc2,0x0, 0x12,0x61,0x8e,0xc2,0x0, 0x22,0xa2,0x0, +0xa9,0x92,0xcb,0xa2,0x0, 0xa9,0x92,0xca,0xa2,0x0, 0xa9,0x91,0xcb,0x22,0xe4,0x7e, +0x70,0xff,0x7c,0x6b,0x7e,0xb3,0x72,0xfe,0xb4,0x81,0x72,0xa5,0xbe,0x0, 0x2, 0x80, +0x66,0xa5,0xbe,0x1, 0x22,0xc2,0xaf,0xa, 0x27,0x5e,0x24,0x0, 0x2, 0x68,0x2, 0xd2, +0x95,0x7a,0x71,0xcd,0xa9,0xd0,0xce,0xa9,0xc6,0xc9,0xa9,0xd0,0xce,0xa9,0xc7,0xc9, +0xa9,0xd1,0x87,0xd2,0xaf,0x80,0x40,0xa5,0xbe,0x2, 0x1d,0xc2,0xaf,0x7a,0x71,0xcd, +0x12,0x62,0xb7,0x70,0xf, 0xa9,0xd0,0xce,0xa9,0xc7,0xc9,0xa9,0xd0,0xce,0xa9,0xd6, +0xc9,0xa9,0xd1,0x87,0xd2,0xaf,0x80,0x1f,0xa5,0xbe,0x3, 0x21,0xc2,0xaf,0x7a,0x71, +0xcd,0x12,0x62,0xb7,0x70,0xf, 0xa9,0xd0,0xce,0xa9,0xd7,0xc9,0xa9,0xd0,0xce,0xa9, +0xc6,0xc9,0xa9,0xd1,0x87,0xd2,0xaf,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe4,0x7a,0xb3, +0x72,0xfe,0x22,0x80,0xe, 0x12,0x62,0xbc,0x12,0x62,0xf2,0x40,0x19,0x20,0x11,0x16, +0x12,0x62,0xe, 0x12,0x62,0xb7,0x70,0xed,0x12,0x62,0xbc,0x12,0x64,0xc6,0x74,0x2, +0x7e,0x70,0x7, 0x2, 0x62,0x12,0x22,0xa2,0x93,0xe4,0x33,0x22,0x74,0x81,0x7a,0xb3, +0x72,0xfe,0x22,0x80,0xe, 0x12,0x62,0xbc,0x12,0x62,0xf2,0x40,0x19,0x20,0x11,0x16, +0x12,0x62,0xe, 0x12,0x62,0xb7,0x70,0xed,0x12,0x62,0xbc,0x12,0x64,0xc6,0x74,0x2, +0x7e,0x70,0x7, 0x2, 0x62,0x12,0x22,0x80,0x3, 0x12,0x62,0xc3,0x12,0x62,0xf2,0x50, +0xf8,0x22,0x7e,0xb3,0x3, 0xcf,0x70,0x6, 0x7e,0xb3,0x3, 0xd0,0x60,0x2, 0xd3,0x22, +0xc3,0x22,0x20,0x11,0x6, 0x12,0x66,0xa8,0x12,0x0, 0x12,0x7e,0xb3,0x73,0x3a,0x60, +0x3, 0x12,0x2a,0x60,0x12,0x62,0xf2,0x40,0x6, 0x12,0x62,0xe7,0x2, 0x0, 0x12,0x22, +0x24,0x52,0x68,0x6, 0x4, 0x78,0x25,0x2, 0xdd,0xd3,0x7e,0x63,0x69,0x8c,0x7e,0x73, +0x69,0x8d,0xac,0x76,0x3e,0x34,0x7a,0x37,0x4d,0x43,0x1e,0x34,0xa, 0x36,0x7a,0x73, +0x71,0x74,0x7e,0x37,0x4d,0x43,0x1e,0x34,0x7a,0x73,0x71,0x75,0x22,0x12,0x63,0xae, +0xe5,0x1b,0x70,0x5, 0x12,0x61,0xbd,0x80,0x3, 0x12,0x63,0x2, 0x2, 0x63,0x5f,0x6c, +0x77,0x7e,0x30,0x3b,0x7e,0xa0,0x3c,0x7e,0xb3,0x71,0xb, 0xb4,0x1, 0xf, 0xe5,0x1b, +0x60,0xb, 0x7e,0x23,0x73,0x3e,0xbc,0x27,0x78,0x3, 0x12,0xd5,0xb0,0x7e,0xb3,0x71, +0xb, 0xb4,0x1, 0x29,0xe5,0x1b,0x60,0x25,0x7e,0xb3,0x73,0x3e,0xbc,0xb3,0x78,0x3, +0x12,0x64,0x78,0x7e,0xb3,0x73,0x3e,0x7a,0xb3,0x73,0x39,0x4, 0x7a,0xb3,0x73,0x3e, +0x7e,0x73,0x73,0x3e,0xbc,0x7a,0x28,0x5, 0xe4,0x7a,0xb3,0x73,0x3e,0x22,0x30,0x1c, +0x28,0xc2,0x1c,0x7e,0x73,0x70,0xe4,0x7a,0x73,0x71,0xb, 0x74,0xff,0x7a,0xb3,0x70, +0xe4,0x7e,0xa3,0x71,0xb, 0x4c,0xaa,0x78,0x5, 0x12,0x64,0x6b,0x80,0xb, 0xbe,0xa0, +0x1, 0x78,0x6, 0x74,0x1, 0x7a,0xb3,0x73,0x38,0x7e,0xb3,0x73,0x38,0x60,0x3, 0x12, +0x64,0x8d,0x7e,0xb3,0x71,0xb, 0x14,0x68,0x5b,0x1b,0xb1,0x68,0x5f,0x24,0x3, 0x78, +0x6e,0x12,0x64,0x63,0x38,0x7, 0x7e,0xb3,0x73,0x3f,0xb4,0x1, 0x16,0x12,0x47,0x95, +0x7e,0xb3,0x70,0xec,0x30,0xe0,0x5b,0x7e,0xb3,0x71,0x36,0xb4,0x1, 0x54,0x30,0x10, +0x51,0x80,0x2e,0x7e,0xb3,0x70,0xec,0x30,0xe0,0x48,0x7e,0x37,0x73,0x3c,0x7e,0x44, +0x3, 0xe8,0x7d,0x53,0x8d,0x54,0x7e,0x53,0x70,0xed,0xa, 0x15,0xbd,0x51,0x50,0x11, +0x7e,0xb3,0x71,0x36,0xb4,0x1, 0x2b,0x7e,0x24,0x0, 0xc8,0x8d,0x32,0xbd,0x31,0x40, +0x21,0x2, 0x64,0x8d,0x12,0x64,0x63,0x28,0x19,0x2, 0x66,0xbc,0x7e,0x34,0x21,0x59, +0x12,0x30,0xa4,0x12,0x47,0xd6,0x12,0x61,0x6a,0x12,0x47,0xe1,0x2, 0x64,0x6b,0x12, +0x64,0xcd,0x22,0x7e,0x73,0x69,0x5f,0xbe,0x70,0x0, 0x22,0xe4,0x7a,0xb3,0x71,0xb, +0xd2,0x11,0x12,0x47,0x95,0x2, 0x64,0x78,0x12,0x4a,0xf0,0x5e,0x34,0x0, 0x1, 0x68, +0xb, 0x74,0x1, 0x7a,0xb3,0x73,0x3b,0xe4,0x7a,0xb3,0x73,0x37,0x22,0xe5,0x1b,0xb4, +0x1, 0xc, 0x7e,0xb3,0x24,0x27,0x60,0x6, 0xe4,0x7a,0xb3,0x71,0xb, 0x22,0xe4,0x7a, +0xb3,0x73,0x38,0x12,0x64,0xcd,0x12,0x47,0x95,0xe4,0x7a,0xb3,0x73,0x3e,0x7a,0xb3, +0x73,0x39,0x12,0x4a,0xf0,0x5e,0x34,0x0, 0x2, 0x68,0xa, 0x7e,0xb3,0x6d,0xfd,0x44, +0x8, 0x7a,0xb3,0x6d,0xfd,0x22,0xa9,0xd5,0xea,0xa9,0xc5,0xea,0x22,0x74,0x1, 0x7a, +0xb3,0x71,0xb, 0x22,0xca,0xf8,0x7e,0xa3,0x69,0x5f,0x7e,0xb3,0x69,0x60,0xc2,0x10, +0xbe,0xa0,0x1, 0x38,0x21,0xbe,0xb0,0x1, 0x38,0x1c,0x7e,0x47,0x67,0xd7,0xbe,0x44, +0x0, 0x1e,0x28,0x2, 0x80,0x10,0x7e,0xf3,0x27,0xf2,0x4c,0xff,0x68,0xf, 0x7e,0x47, +0x24,0x29,0x4d,0x44,0x78,0x7, 0xd2,0x10,0x12,0x64,0xcd,0x80,0x35,0x4c,0xaa,0x78, +0x36,0xb4,0x1, 0x33,0x7e,0x37,0x24,0x29,0x7a,0x37,0x27,0xf4,0x7e,0xb3,0x27,0xf2, +0xb4,0x3, 0x1f,0x7e,0x37,0x24,0x29,0xbe,0x34,0x0, 0x0, 0x28,0x15,0x74,0x4, 0x7a, +0xb3,0x27,0xf2,0x7e,0x37,0x28,0xa, 0x7e,0x27,0x28,0xc, 0x12,0x65,0xdb,0xa1,0xd4, +0x80,0x0, 0x12,0xdc,0xe1,0xa1,0xd4,0x7e,0xc7,0x68,0x65,0x7e,0xd7,0x68,0x67,0x4c, +0xff,0x78,0x19,0x70,0x53,0xbe,0xa0,0x1, 0x78,0x4e,0x7d,0x3c,0x7d,0x2d,0x12,0xdc, +0x7c,0x12,0x65,0xd7,0x74,0x1, 0x7a,0xb3,0x27,0xf2,0x80,0x3c,0xbe,0xf0,0x1, 0x78, +0x2a,0x7e,0x27,0x27,0xfa,0x9e,0x27,0x28,0x2, 0x7e,0x14,0x22,0x69,0x12,0x66,0x86, +0x38,0x11,0x7e,0x27,0x28,0x8, 0x9e,0x27,0x28,0x0, 0x7e,0x14,0x22,0x6b,0x12,0x66, +0x86,0x28,0x15,0x74,0x3, 0x7a,0xb3,0x27,0xf2,0x80,0x5, 0xbe,0xf0,0x3, 0x78,0x8, +0x7a,0xc7,0x28,0xa, 0x7a,0xd7,0x28,0xc, 0x7e,0xb3,0x27,0xf2,0x60,0x26,0x7d,0x3c, +0x7d,0x2d,0x7e,0x17,0x24,0x2d,0x7e,0x7, 0x24,0x2f,0x12,0x66,0x90,0xa, 0x2b,0x7e, +0x73,0x27,0xf1,0xa, 0x37,0xbd,0x32,0x58,0xb, 0x12,0x65,0xd7,0x7a,0xc7,0x24,0x2d, +0x7a,0xd7,0x24,0x2f,0xda,0xf8,0x22,0x7d,0x3c,0x7d,0x2d,0x7d,0x42,0x7d,0x13,0x7d, +0x24,0x12,0xdc,0x57,0x7d,0x31,0x12,0xdb,0xcc,0x2, 0x65,0xec,0x7e,0x3, 0x28,0x1a, +0xbe,0x0, 0xf0,0x50,0x2, 0xc1,0x85,0xc1,0x7a,0x6c,0x99,0x7e,0xb3,0x27,0xf1,0xbe, +0xb0,0x20,0x50,0x5, 0x4, 0x7a,0xb3,0x27,0xf1,0x7e,0x1f,0x24,0x31,0x7a,0x1f,0x5d, +0x7, 0x7e,0x80,0x1, 0x80,0x49,0x74,0x4, 0xac,0xb8,0x49,0x35,0x24,0x31,0x49,0x25, +0x24,0x33,0x7e,0x17,0x5d,0x7, 0x7e,0x7, 0x5d,0x9, 0x12,0x66,0x90,0x7c,0x1b,0x7e, +0x3, 0x27,0xf1,0xbc,0x1, 0x38,0x26,0xb, 0x90,0x7e,0x70,0x4, 0xac,0x78,0x2e,0x34, +0x24,0x31,0x7e,0x14,0x5d,0x7, 0x74,0x4, 0x12,0x23,0x44,0x7e,0x34,0x5d,0x7, 0x7e, +0x30,0x4, 0xac,0x39,0x2e,0x14,0x24,0x31,0x74,0x4, 0x12,0x23,0x44,0xb, 0x80,0x7e, +0x3, 0x28,0x1a,0xbc,0x8, 0x38,0xaf,0xa, 0x59,0xb, 0x54,0x7c,0xb, 0x7a,0x3, 0x28, +0x1a,0x7e,0x3, 0x27,0xf1,0xbe,0x0, 0x20,0x50,0xb, 0x7e,0x3, 0x28,0x1a,0xbe,0x0, +0xec,0x40,0x2, 0xa1,0xf9,0x22,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0xbd,0x23,0x22, +0x7d,0x51,0x7d,0x12,0x9d,0x35,0x12,0x24,0x5b,0x7c,0xa7,0x12,0x8f,0xf3,0x7c,0xb7, +0xbc,0xba,0x50,0x3, 0x7c,0xba,0x22,0x22,0x80,0x3, 0x12,0x62,0xc3,0x30,0x11,0xfa, +0x22,0xd2,0x2, 0x12,0x2f,0x50,0x12,0x62,0xb7,0x70,0xfb,0x22,0x7e,0xb3,0x71,0x36, +0x60,0x5, 0x20,0x10,0x5, 0x80,0x0, 0x2, 0x64,0x6b,0x22,0x75,0xec,0xff,0x75,0xee, +0xff,0x75,0xeb,0x23,0x75,0xac,0xc0,0x12,0xcb,0x82,0xa9,0xd5,0xad,0xa9,0xc5,0xed, +0x22,0x6c,0x77,0xa9,0xc7,0xb3,0xa9,0xc6,0xb3,0xd2,0xc8,0x43,0xed,0xf, 0xc2,0xea, +0xb, 0x70,0xbe,0x70,0x3, 0x28,0x3, 0x7e,0x70,0x3, 0xa, 0x57,0x3e,0x54,0x3e,0x54, +0x3e,0x54,0x3e,0x54,0x2e,0x54,0x0, 0x3, 0xf5,0xb3,0xa9,0xd1,0xb4,0xa9,0xc0,0xb4, +0x12,0xcb,0x78,0x2, 0x67,0x16,0xa9,0xc5,0xca,0xa9,0xc7,0x94,0xe4,0x7a,0xb3,0x73, +0x5f,0x22,0x7e,0xb3,0x71,0x36,0x70,0x6, 0x12,0x67,0x5b,0x2, 0xdb,0x49,0x12,0x64, +0xd4,0x12,0xdc,0x4c,0x50,0xa, 0x12,0x67,0x61,0x7c,0x3b,0x12,0x67,0x5b,0x80,0x5, +0x12,0xcd,0x59,0x7c,0x3b,0x4c,0x33,0x68,0x11,0x7c,0xb3,0x12,0xdb,0x4f,0x60,0xa, +0x7a,0x33,0x71,0x39,0x74,0x1, 0x7a,0xb3,0x69,0x65,0x22,0xe4,0x7a,0xb3,0x27,0xf2, +0x22,0x7e,0x37,0x27,0xfa,0x9e,0x37,0x28,0x2, 0x7a,0x37,0x28,0xe, 0x7e,0x37,0x28, +0x8, 0x9e,0x37,0x28,0x0, 0x7a,0x37,0x28,0x10,0x12,0x8c,0xef,0x60,0x1, 0x22,0x7e, +0x73,0x28,0x1a,0xa, 0x37,0x7a,0x35,0x26,0x7e,0x8, 0x24,0x31,0x7e,0x18,0x27,0xf2, +0x2, 0x67,0x93,0xca,0xf8,0x7e,0x55,0x26,0x7a,0xb3,0x72,0x4c,0x74,0xff,0x7a,0xb3, +0x72,0x4b,0x6d,0x55,0x80,0x1f,0x7d,0x45,0x3e,0x44,0x3e,0x44,0x7f,0x60,0x2d,0xd4, +0xb, 0x6a,0x40,0x7d,0xf5,0x3e,0xf4,0x59,0x4f,0x5d,0x7, 0x69,0x46,0x0, 0x2, 0x59, +0x4f,0x5e,0xe7,0xb, 0x54,0xbe,0x55,0x26,0x40,0xdc,0x7e,0x33,0x72,0x4c,0xbe,0x30, +0x4, 0x38,0x3, 0x2, 0x68,0x6a,0x69,0xf1,0x0, 0x1c,0x69,0x11,0x0, 0x1e,0xbd,0x1f, +0x18,0x19,0x4d,0x11,0x78,0x4, 0x7e,0x14,0x0, 0x1, 0x7d,0x3f,0x7d,0x21,0x12,0x22, +0x71,0x7c,0xf7,0x74,0x40,0x7a,0xb3,0x72,0x4f,0x80,0x43,0x4d,0xff,0x78,0x4, 0x7e, +0xf4,0x0, 0x1, 0x7d,0x31,0x7d,0x2f,0x12,0x22,0x71,0x7c,0xf7,0x74,0x80,0x7a,0xb3, +0x72,0x4f,0x7d,0xf, 0x2d,0xf, 0xbd,0x1, 0x8, 0x24,0x1a,0x2, 0x1a,0x0, 0x7e,0x73, +0x72,0x4f,0xa, 0x37,0x6d,0x22,0x12,0x22,0xa3,0x7d,0x5f,0x1a,0x4a,0x1a,0x48,0x7d, +0x1f,0x1a,0x2, 0x1a,0x0, 0x2f,0x2, 0x12,0x22,0xbf,0x7a,0x73,0x72,0x4f,0xbe,0xf0, +0x5, 0x58,0x23,0x7e,0x8, 0x5d,0x7, 0x7e,0x18,0x5e,0xe7,0x12,0x6a,0x5, 0x7e,0x8, +0x5d,0x7, 0x7e,0x18,0x5e,0xe7,0x12,0x68,0x89,0x7e,0x8, 0x5d,0x7, 0x7e,0x18,0x5e, +0xe7,0x12,0x6a,0xb0,0x80,0xa, 0x74,0x7d,0x80,0x2, 0x74,0x7f,0x7a,0xb3,0x72,0x4b, +0xe4,0x7a,0xb3,0x72,0x4c,0x7e,0x73,0x73,0x4c,0xbe,0x73,0x72,0x4b,0x48,0x6, 0x7e, +0xb3,0x72,0x4d,0x80,0x1, 0xe4,0xda,0xf8,0x22,0xca,0x3b,0x7f,0x71,0x7e,0x60,0x1, +0xb, 0xa, 0x20,0xb, 0x7a,0x50,0x7c,0x4b,0x7a,0x53,0x60,0xc7,0x7a,0x43,0x61,0xb7, +0x7e,0x70,0x1, 0x7e,0xa0,0x1, 0x21,0xb0,0x7e,0x90,0x2, 0xac,0x9a,0x7f,0x60,0x2d, +0xd4,0xb, 0x6a,0xd0,0x7d,0x7d,0x7c,0xbf,0xf5,0x28,0x7f,0x67,0x2d,0xd4,0xb, 0x6a, +0x40,0xa, 0xd5,0xa, 0xbb,0x7d,0xab,0x9d,0xad,0x7d,0x7a,0x7c,0x8f,0xbe,0x80,0x0, +0x58,0x5, 0x6e,0x80,0xff,0xb, 0x80,0xa, 0xa4,0xa, 0x79,0x9d,0x7a,0xbe,0xf0,0x0, +0x58,0x5, 0x6e,0xf0,0xff,0xb, 0xf0,0xbe,0x80,0x2, 0x58,0x7, 0xbe,0xf0,0x2, 0x58, +0x2, 0x21,0xae,0xbe,0x60,0x0, 0x18,0x2, 0x21,0x96,0xbe,0x70,0xec,0x28,0x2, 0x21, +0xba,0xbe,0x80,0x8, 0x58,0x5, 0xbe,0xf0,0x8, 0x48,0x67,0xa, 0xa7,0xb, 0xa4,0x7d, +0x6a,0x7c,0x7d,0xa, 0xa5,0x2d,0xab,0x12,0x69,0xfe,0xa, 0xa7,0x19,0xba,0x60,0xc7, +0xa, 0xd9,0xa, 0xa4,0x2d,0xad,0x12,0x69,0xfe,0xa, 0xa7,0x19,0xba,0x61,0xb7,0x9, +0xba,0x60,0xc7,0xa, 0xdb,0xa, 0xc5,0x2d,0xcd,0xe, 0xc4,0x7d,0x6c,0x7c,0xbd,0xa, +0xc7,0x19,0xbc,0x60,0xc6,0x9, 0xbc,0x61,0xb7,0xa, 0xcb,0xa, 0xa4,0x2d,0xac,0x12, +0x69,0xfe,0xa, 0xa7,0x19,0xba,0x61,0xb6,0x2d,0xdb,0x12,0x69,0xf5,0x19,0xbd,0x60, +0xc8,0xa, 0xd9,0x12,0x69,0xf3,0x19,0xbd,0x61,0xb8,0xb, 0xd5,0x7d,0x6d,0x7c,0x7d, +0x80,0x24,0xbe,0x80,0x4, 0x58,0x5, 0xbe,0xf0,0x4, 0x48,0x1a,0xe5,0x28,0xa, 0xcb, +0xa, 0xd5,0x12,0x69,0xf3,0x19,0xbd,0x60,0xc7,0xa, 0xc9,0xa, 0xd4,0x12,0x69,0xf3, +0x19,0xbd,0x61,0xb7,0xb, 0x70,0xbe,0x70,0xf0,0x50,0x1f,0x7e,0x51,0x28,0x7c,0x49, +0xe5,0x28,0xa, 0xd7,0x19,0xbd,0x60,0xc7,0x19,0x9d,0x61,0xb7,0xb, 0x70,0xb, 0xa0, +0x7e,0xb3,0x72,0x4c,0xbc,0xba,0x28,0x2, 0x1, 0xa8,0x7a,0x73,0x72,0x4c,0x7e,0xa0, +0x1, 0x80,0x25,0xa, 0x3a,0x9, 0xb3,0x60,0xc7,0xa, 0x2b,0x7e,0x70,0x2, 0xac,0x7a, +0x7f,0x60,0x2d,0xd3,0x1b,0x6a,0x20,0xa, 0x2a,0x9, 0xb2,0x61,0xb7,0xa, 0x4b,0x2d, +0x3f,0x7d,0x2e,0x1b,0x1a,0x40,0xb, 0xa0,0x7e,0xb3,0x72,0x4c,0xbc,0xba,0x38,0xd3, +0xda,0x3b,0x22,0x2d,0xdc,0xe, 0xd4,0x7d,0x6d,0x7c,0xbd,0xa, 0xd7,0x22,0xe, 0xa4, +0x7d,0x6a,0x7c,0xbd,0x22,0xca,0xf8,0x7f,0x51,0x7f,0x40,0x7e,0x37,0x28,0x2, 0x7a, +0x35,0x2c,0x7e,0x37,0x28,0x0, 0x7a,0x35,0x2e,0x7e,0x37,0x28,0xe, 0x7a,0x35,0x28, +0x7e,0x37,0x28,0x10,0x7a,0x35,0x2a,0x6c,0xff,0x80,0x1e,0x7e,0x34,0x0, 0x28,0x7e, +0x14,0x0, 0x31,0x74,0x9, 0x12,0x23,0x44,0x74,0x2, 0xac,0xbf,0x7f,0x4, 0x2d,0x15, +0x7f,0x15,0x2d,0x35,0x12,0x6a,0x54,0xb, 0xf0,0x7e,0x73,0x72,0x4c,0xbc,0x7f,0x38, +0xda,0xda,0xf8,0x22,0x7f,0x71,0x7f,0x60,0x7e,0x35,0x31,0xbe,0x34,0x0, 0x0, 0x38, +0x7, 0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x31,0x7e,0x35,0x33,0xbe,0x34,0x0, 0x0, 0x38, +0x7, 0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x33,0xb, 0x6a,0x30,0x9e,0x35,0x35,0x6d,0x22, +0x7e,0x33,0x72,0x4e,0x12,0x6a,0xa9,0x7e,0x15,0x31,0x12,0x22,0xbd,0x1b,0x6a,0x30, +0xb, 0x7a,0x30,0x9e,0x35,0x37,0x6d,0x22,0x7e,0x33,0x72,0x4f,0x12,0x6a,0xa9,0x7e, +0x15,0x33,0x12,0x22,0xbd,0x1b,0x7a,0x30,0x22,0xa, 0x13,0x6d,0x0, 0x2, 0x22,0xa3, +0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x73,0x72,0x4c,0xbe,0x70,0x20,0x40,0x52,0x7e, +0xf0,0x2, 0x80,0x3c,0xa, 0x3f,0x6d,0x22,0x74,0x5, 0x2f,0x11,0x14,0x78,0xfb,0x7e, +0x33,0x72,0x4c,0xa, 0x13,0x6d,0x0, 0x12,0x22,0xbf,0x7c,0xe7,0xbe,0xe0,0x2, 0x50, +0x3, 0x7e,0xe0,0x2, 0xa, 0x6f,0x1b,0x64,0xa, 0x3e,0x1b,0x34,0x7c,0xc7,0x7f,0x5, +0x7c,0xbd,0x12,0x6b,0x1a,0x7f,0x6, 0x7c,0xbd,0x7c,0x7c,0x12,0x6b,0x1a,0xb, 0xf0, +0x7e,0x73,0x72,0x4c,0xbc,0x7f,0x50,0xbc,0x7f,0x5, 0x7f,0x16,0x12,0x6b,0x68,0x80, +0x6, 0x74,0x7e,0x7a,0xb3,0x72,0x4b,0xda,0x3b,0x22,0x7c,0x97,0x7c,0xab,0x7f,0x10, +0x7e,0x30,0x2, 0xac,0x3a,0x12,0x6f,0x8e,0x7e,0x10,0x2, 0xac,0x19,0x7f,0x71,0x2d, +0xf0,0xb, 0x7a,0x0, 0x7c,0x21,0xa5,0xba,0x0, 0x14,0xa, 0x3, 0x1b,0x7a,0x0, 0xbc, +0x9a,0x68,0x24,0x6d,0x44,0x74,0x2, 0xa4,0x2d,0x35,0x1b,0x1a,0x40,0x22,0xbc,0x9a, +0x68,0x15,0xa, 0x2, 0xa, 0x13,0x2d,0x10,0xe, 0x14,0x1b,0x7a,0x10,0x6d,0x11,0x74, +0x2, 0xa4,0x2d,0x35,0x1b,0x1a,0x10,0x22,0xca,0x79,0x6c,0xaa,0x7e,0x90,0x2, 0xac, +0x9a,0x7f,0x70,0x2d,0xf4,0xb, 0x7a,0xf0,0x7d,0x7f,0x7c,0xbf,0xa, 0xfa,0x19,0xbf, +0x72,0x50,0x7f,0x71,0x2d,0xf4,0xb, 0x7a,0x40,0x7c,0xb9,0xa, 0x4a,0x19,0xb4,0x72, +0x70,0xb, 0xa0,0xbe,0xa0,0x20,0x40,0xd4,0x7e,0x8, 0x72,0x50,0x7e,0x18,0x72,0x70, +0x74,0x20,0x12,0x6b,0xa8,0xda,0x79,0x22,0xca,0x3b,0xf5,0x2c,0x7f,0x31,0x7a,0xd, +0x28,0xe4,0x7a,0xb3,0x60,0xca,0x7a,0xb3,0x60,0xcb,0x7a,0xb3,0x60,0xcc,0x7e,0x34, +0x3, 0xe8,0x7a,0x37,0x60,0xd7,0x74,0x3c,0x7a,0xb3,0x60,0xc8,0x74,0x46,0x7a,0xb3, +0x60,0xc9,0x75,0x2d,0x0, 0xa1,0xbd,0x12,0x6d,0xfd,0x28,0x1e,0x7e,0x34,0x0, 0x44, +0xca,0x39,0x7e,0x71,0x2d,0x74,0x44,0xac,0x7b,0x2e,0x34,0xe, 0x6, 0x7e,0x24,0x0, +0xff,0x7e,0x8, 0x60,0xdb,0x12,0x24,0x14,0x1b,0xfd,0x6d,0x33,0x7a,0x37,0x60,0xcd, +0x7a,0x37,0x60,0xcf,0x7a,0x37,0x60,0xd1,0x7a,0x37,0x60,0xd3,0x7a,0x37,0x60,0xd5, +0x7e,0x34,0x60,0xdb,0x7a,0x35,0x31,0x7e,0x34,0x60,0xfb,0x7a,0x35,0x33,0x75,0x2e, +0x0, 0x80,0x65,0xe5,0x2e,0xa, 0x3b,0x7e,0xd, 0x28,0x12,0x6e,0xd, 0x2e,0x35,0x31, +0x12,0x6e,0x5, 0x12,0x24,0x5b,0x7d,0xd3,0x7e,0xc7,0x60,0xd1,0xbd,0xcd,0x58,0x4, +0x7a,0xd7,0x60,0xd1,0xe5,0x2e,0xa, 0x3b,0x7f,0x3, 0x12,0x6e,0xd, 0x2e,0x35,0x33, +0x12,0x6e,0x5, 0x12,0x24,0x5b,0x7d,0xc3,0x7e,0x37,0x60,0xd3,0xbd,0x3c,0x58,0x4, +0x7a,0xc7,0x60,0xd3,0x7e,0x37,0x60,0xcd,0x2d,0x3d,0x7a,0x37,0x60,0xcd,0x7e,0x37, +0x60,0xcf,0x2d,0x3c,0x7a,0x37,0x60,0xcf,0x2d,0xcd,0x7e,0x37,0x60,0xd5,0xbd,0x3c, +0x58,0x4, 0x7a,0xc7,0x60,0xd5,0x5, 0x2e,0xe5,0x2c,0xbe,0xb1,0x2e,0x38,0x94,0xe5, +0x2c,0xb4,0xa, 0x2c,0x7e,0x37,0x60,0xd1,0xbe,0x34,0x0, 0x40,0x48,0xc, 0x7e,0x27, +0x60,0xd3,0xbe,0x24,0x0, 0x40,0x48,0x2, 0xa1,0xbb,0xbe,0x34,0x0, 0x60,0x8, 0x2, +0xa1,0xbb,0x7e,0x37,0x60,0xd3,0xbe,0x34,0x0, 0x60,0x8, 0x2, 0xa1,0xbb,0x80,0x2a, +0x7e,0x37,0x60,0xd1,0xbe,0x34,0x0, 0x20,0x8, 0xc, 0x7e,0x27,0x60,0xd3,0xbe,0x24, +0x0, 0x20,0x8, 0x2, 0xa1,0xbb,0xbe,0x34,0x0, 0x30,0x8, 0x2, 0xa1,0xbb,0x7e,0x37, +0x60,0xd3,0xbe,0x34,0x0, 0x30,0x8, 0x2, 0xa1,0xbb,0x7e,0xa3,0x72,0x4e,0x74,0xc, +0xa4,0xbe,0x57,0x60,0xcd,0x58,0x2, 0xa1,0xbb,0x7e,0xa3,0x72,0x4f,0x74,0xc, 0xa4, +0xbe,0x57,0x60,0xcf,0x58,0x2, 0xa1,0xbb,0x7e,0x15,0x31,0x6d,0x0, 0x7e,0x1d,0x28, +0xe5,0x2c,0x12,0x6e,0x15,0x7a,0xb3,0x60,0xc7,0x7e,0x15,0x33,0x6d,0x0, 0x7f,0x13, +0xe5,0x2c,0x12,0x6e,0x15,0xf5,0x2f,0x7e,0x73,0x60,0xc8,0xbe,0x73,0x60,0xc7,0x28, +0x2, 0xa1,0xbb,0xbe,0x71,0x2f,0x28,0x2, 0xa1,0xbb,0xe5,0x2f,0x7e,0x31,0x2f,0xac, +0x3b,0x1a,0x2, 0x1a,0x0, 0x7e,0x73,0x60,0xc7,0xac,0x77,0x1a,0x26,0x1a,0x24,0x2f, +0x10,0xe5,0x2f,0xa, 0x5b,0x6d,0x44,0x7e,0x33,0x60,0xc7,0xa, 0x13,0x6d,0x0, 0x2f, +0x2, 0x12,0x22,0xbf,0x7c,0xb7,0xf5,0x30,0x7e,0x73,0x60,0xc9,0xbe,0x71,0x30,0x38, +0x4a,0x7e,0x37,0x60,0xd3,0x2e,0x37,0x60,0xd1,0x2e,0x37,0x60,0xd5,0x7a,0x37,0x60, +0xd9,0xe5,0x30,0xa, 0x2b,0x7e,0x34,0x0, 0x64,0x9d,0x32,0x3e,0x34,0x2e,0x37,0x60, +0xd9,0x7a,0x37,0x60,0xd9,0x7e,0x37,0x60,0xd7,0xbe,0x37,0x60,0xd9,0x8, 0x1c,0x7e, +0x37,0x60,0xd9,0x7a,0x37,0x60,0xd7,0xe5,0x30,0x7a,0xb3,0x60,0xcb,0x7e,0x73,0x61, +0x1d,0x7a,0x73,0x60,0xcc,0xe5,0x2d,0x7a,0xb3,0x60,0xca,0x5, 0x2d,0x12,0x6d,0xfd, +0x28,0x2, 0x61,0xd7,0x7e,0x73,0x60,0xc9,0xbe,0x73,0x60,0xcb,0x38,0x22,0x7e,0x73, +0x60,0xcc,0xbe,0x70,0x0, 0x28,0x19,0xbe,0x70,0xff,0x50,0x14,0x7e,0x63,0x60,0xca, +0xa, 0x26,0xb, 0x24,0x7c,0x65,0x7a,0x63,0x72,0x4b,0x7a,0x73,0x72,0x4d,0x80,0x6, +0x74,0x7c,0x7a,0xb3,0x72,0x4b,0x7e,0xb3,0x60,0xcb,0xda,0x3b,0x22,0x7e,0x73,0x73, +0x4c,0xbe,0x71,0x2d,0x22,0x7e,0x39,0x70,0xa, 0x37,0x9d,0x32,0x22,0x2d,0x13,0x7e, +0xb, 0x50,0xa, 0x25,0x22,0xca,0x3b,0x7c,0xfb,0x7f,0x61,0x7f,0x40,0x9f,0x11,0x7f, +0x51,0x7f,0x71,0x7a,0x1f,0x61,0x1f,0x7a,0x1f,0x61,0x23,0x7a,0x1f,0x61,0x27,0xbe, +0xf0,0xa, 0x78,0x6, 0x7e,0x54,0x1, 0x3c,0x80,0x4, 0x7e,0x54,0x2, 0x35,0x7a,0x57, +0x61,0x2f,0x6c,0xee,0x80,0x6d,0xa, 0x5e,0x7f,0x14,0x12,0x6f,0x86,0x7a,0x57,0x61, +0x2d,0xa, 0x5e,0x7f,0x16,0x12,0x6f,0x86,0x7a,0x57,0x61,0x2b,0x7e,0x37,0x61,0x2b, +0x12,0x6f,0x7f,0x2f,0x50,0x7e,0x67,0x61,0x2d,0x7d,0x16,0x1a,0x2, 0x1a,0x0, 0x2f, +0x70,0x12,0x6f,0x7f,0x12,0x6f,0x75,0x7e,0x1f,0x61,0x1f,0x2f,0x10,0x7a,0x1f,0x61, +0x1f,0x7d,0x16,0x1a,0x2, 0x1a,0x0, 0x7e,0x37,0x61,0x2d,0x12,0x6f,0x75,0x7e,0x1f, +0x61,0x23,0x2f,0x10,0x7a,0x1f,0x61,0x23,0x7e,0x17,0x61,0x2d,0x1a,0x2, 0x1a,0x0, +0x7e,0x37,0x61,0x2b,0x12,0x6f,0x75,0x7e,0x1f,0x61,0x27,0x2f,0x10,0x7a,0x1f,0x61, +0x27,0xb, 0xe0,0xbc,0xfe,0x38,0x8f,0xa, 0xdf,0x6d,0xcc,0x7f,0x15,0x7f,0x6, 0x12, +0x23,0x10,0x7f,0x51,0x7f,0x17,0x7f,0x6, 0x12,0x23,0x10,0x7f,0x71,0x7e,0x94,0x0, +0x64,0x7e,0x1f,0x61,0x1f,0x7d,0x19,0x12,0x22,0xb4,0x7e,0x87,0x61,0x2f,0x7d,0x18, +0x7d,0xd8,0x1a,0x12,0x1a,0xc2,0x7f,0x6, 0x12,0x23,0x10,0x7a,0x1f,0x61,0x1f,0x7e, +0x1f,0x61,0x23,0x7d,0x19,0x12,0x22,0xb4,0x7f,0x6, 0x12,0x23,0x10,0x7a,0x1f,0x61, +0x23,0x7e,0x1f,0x61,0x27,0x7d,0x19,0x12,0x22,0xb4,0x7d,0x18,0x1a,0x2, 0x1a,0x0, +0x12,0x23,0x10,0x7a,0x1f,0x61,0x27,0x7f,0x15,0x7f,0x7, 0x12,0x22,0xa3,0x7e,0x6f, +0x61,0x27,0x9f,0x61,0x7f,0x15,0x7f,0x5, 0x12,0x22,0xa3,0x7e,0x5f,0x61,0x1f,0x9f, +0x51,0x7f,0x17,0x7f,0x7, 0x12,0x22,0xa3,0x7e,0x7f,0x61,0x23,0x9f,0x71,0xbe,0x58, +0x0, 0x0, 0x68,0x6, 0xbe,0x78,0x0, 0x0, 0x78,0x6, 0x7e,0x44,0x0, 0x64,0x80,0x18, +0x7f,0x16,0x7d,0x19,0x12,0x22,0xb4,0x7f,0x5, 0x12,0x23,0x10,0x7f,0x6, 0x12,0x22, +0xa3,0x7f,0x7, 0x12,0x23,0x10,0x7d,0x43,0xbe,0x44,0x0, 0x0, 0x18,0x2, 0x6d,0x44, +0x7c,0xb9,0xda,0x3b,0x22,0x1a,0x26,0x1a,0x24,0x12,0x22,0xa3,0x7f,0x1, 0x22,0x7d, +0x13,0x1a,0x2, 0x1a,0x0, 0x22,0x2d,0x35,0x7e,0x1b,0x70,0xa, 0x57,0x22,0x2d,0x13, +0x7d,0x2, 0xb, 0xa, 0x10,0x22,0x12,0x40,0x46,0x7e,0x73,0x72,0xff,0x7a,0x73,0x71, +0x5f,0x7e,0x73,0x71,0x5e,0x7a,0x73,0x6d,0xfb,0xe4,0x7a,0xb3,0x69,0x60,0x7a,0xb3, +0x69,0x5f,0x7e,0x73,0x71,0xd, 0x7a,0x73,0x73,0x1f,0x22,0x7e,0x34,0x4, 0x68,0xca, +0x39,0x7e,0x1f,0x22,0xe0,0x7e,0x8, 0x48,0xd8,0x12,0x24,0x14,0x1b,0xfd,0x6d,0x33, +0x7d,0x13,0x3e,0x14,0x49,0x1, 0x48,0xd8,0xbe,0x4, 0x0, 0x0, 0x8, 0x6, 0x49,0x21, +0x48,0xd8,0x80,0x4, 0x6d,0x22,0x9d,0x20,0x59,0x21,0x48,0xd8,0x49,0x1, 0x44,0x70, +0xbd,0x20,0x28,0x4, 0x59,0x21,0x44,0x70,0xb, 0x34,0xbe,0x34,0x2, 0x34,0x40,0xd0, +0x22,0x24,0x6f,0x68,0x12,0x14,0x68,0x14,0x14,0x68,0x16,0x14,0x68,0x18,0xb, 0xb2, +0x78,0x19,0x7e,0xb3,0x1, 0x72,0x22,0x7e,0xb3,0x1, 0x73,0x22,0x7e,0xb3,0x1, 0x74, +0x22,0x7e,0xb3,0x1, 0x75,0x22,0x7e,0xb3,0x1, 0x76,0x22,0x74,0xfe,0x22,0x7e,0x37, +0x51,0xe3,0x7a,0x73,0x71,0x6c,0x7e,0xb3,0x71,0x69,0xb4,0x1, 0x2, 0x80,0x2, 0x21, +0x16,0x7e,0xb3,0x71,0x58,0x44,0x80,0x7a,0xb3,0x71,0x58,0x7e,0xa7,0x51,0xe3,0xbe, +0xa4,0x0, 0x5, 0x38,0x30,0x6d,0xdd,0x7a,0xd7,0x51,0xd2,0x7a,0xd7,0x51,0xd0,0x7e, +0x8, 0x51,0xca,0x7e,0x34,0x0, 0x6, 0xe4,0x12,0x24,0x39,0x7e,0x34,0x4, 0x68,0x7d, +0x1d,0xad,0x13,0x2e,0x14,0x44,0x70,0x6d,0x0, 0xe4,0x12,0x24,0x39,0xb, 0xd4,0xbe, +0xd4,0x0, 0x2, 0x78,0xe6,0x7e,0xa7,0x51,0xe3,0xb, 0xa4,0x7a,0xa7,0x51,0xe3,0xbe, +0xa4,0x0, 0x5, 0x28,0x9, 0x74,0x1, 0x7a,0xb3,0x51,0xbd,0x12,0x6f,0xbb,0x7e,0x73, +0x71,0x6a,0xa, 0xa7,0x3e,0xa4,0x3e,0xa4,0x2e,0xa4,0x0, 0x5, 0xbe,0xa7,0x51,0xe3, +0x78,0x79,0x6d,0xdd,0x4d,0xdd,0x78,0x4, 0x6d,0xbb,0x80,0xa, 0x7d,0x3d,0x1b,0x34, +0x3e,0x34,0x49,0xb3,0x44,0x70,0xbe,0xd4,0x2, 0x34,0x78,0x4, 0x6d,0xcc,0x80,0x8, +0x7d,0xcd,0x3e,0xc4,0x49,0xcc,0x44,0x72,0x7d,0x3b,0x2d,0x3c,0x7e,0x24,0x0, 0xa, +0x8d,0x32,0x7d,0x3d,0x3e,0x34,0x2e,0x34,0x44,0x70,0xb, 0x38,0xa0,0x2d,0xa2,0x1b, +0x38,0xa0,0xb, 0xd4,0xbe,0xd4,0x2, 0x34,0x78,0xba,0xe4,0x7a,0xb3,0x51,0xbd,0x7a, +0xb3,0x71,0x69,0x6d,0xaa,0x7a,0xa7,0x4d,0x43,0x7e,0x34,0x44,0x70,0x7a,0x37,0x51, +0xbb,0x7a,0xa7,0x51,0xe3,0x22,0xe4,0x7a,0xb3,0x51,0xbd,0x7e,0xa7,0x51,0xe3,0x4d, +0xaa,0x68,0x8, 0x6d,0xaa,0x7a,0xa7,0x51,0xe3,0xd2,0xe, 0x22,0x24,0xab,0x68,0x10, +0x24,0xef,0x68,0x1c,0x24,0xde,0x68,0x26,0x24,0xde,0x78,0x2f,0x74,0x5, 0x80,0x2d, +0x7e,0xb3,0x3, 0xff,0xb4,0x5, 0x2a,0x12,0x71,0x72,0x12,0x72,0xb2,0x2, 0x71,0x9c, +0x7e,0xb3,0x3, 0xff,0xb4,0x5, 0x1a,0x12,0x71,0x72,0x75,0xe9,0xff,0x22,0x7e,0xb3, +0x3, 0xff,0xb4,0x5, 0xc, 0x12,0x71,0x72,0x2, 0x71,0x95,0x74,0x1, 0x7a,0xb3,0x3, +0xff,0x22,0x7e,0x34,0x0, 0x1, 0x7d,0x23,0x80,0x12,0x7e,0x30,0x4, 0x80,0x5, 0x74, +0xfa,0x12,0x72,0x2d,0x7c,0x23,0x1b,0x30,0xa5,0xba,0x0, 0xf3,0x7d,0x32,0x1b,0x24, +0x4d,0x33,0x78,0xe6,0x22,0x12,0x71,0xa3,0x75,0xe9,0xff,0x22,0x12,0x71,0xa3,0x75, +0xe9,0xff,0x22,0x75,0xe7,0x6b,0xe4,0x7e,0x34,0x1, 0x4, 0x7e,0x24,0x0, 0xff,0x7a, +0x1b,0xb0,0x7e,0x34,0x1, 0x5, 0x7a,0x1b,0xb0,0x22,0x7c,0xa7,0x7c,0x3b,0xa5,0xbb, +0x0, 0x7, 0x7c,0xba,0x12,0x71,0xfe,0x80,0x25,0xbe,0x30,0xeb,0x68,0x4, 0xa5,0xbb, +0xec,0x9, 0x7c,0xb3,0x7c,0x7a,0x12,0x72,0x76,0x80,0x13,0xbe,0x30,0x80,0x40,0xe, +0xbe,0x30,0xef,0x38,0x9, 0x7c,0xb3,0x24,0x80,0x7c,0x7a,0x12,0x72,0x49,0xa5,0xbb, +0xfc,0x5, 0x7c,0xba,0x2, 0x71,0x2c,0x74,0x1, 0x7a,0xb3,0x3, 0xff,0x22,0x7a,0xb3, +0x71,0x58,0xc4,0x54,0x7, 0xbe,0xb0,0x4, 0x68,0x3, 0xb4,0x2, 0x4, 0x74,0x3, 0x80, +0x7, 0x60,0x3, 0xb4,0x1, 0x7, 0x74,0x1, 0x7a,0xb3,0x71,0xd, 0x22,0x12,0x72,0x26, +0xe4,0x7a,0xb3,0x71,0x58,0x22,0x74,0x1, 0x7a,0xb3,0x71,0xd, 0x22,0x7c,0xab,0x80, +0xf, 0x7e,0x70,0x2, 0x80,0x1, 0x0, 0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, 0xf7,0x0, +0x7c,0x6a,0x1b,0xa0,0xa5,0xbe,0x0, 0xe9,0x22,0x7c,0x6b,0x2e,0x60,0xdd,0x68,0x25, +0x2e,0x60,0xfd,0x68,0x20,0x1b,0x61,0x68,0x1c,0x2e,0x60,0xfa,0x68,0x17,0x1b,0x60, +0x68,0x13,0x80,0x0, 0xa, 0x2b,0x19,0x72,0x70,0xe6,0xd2,0x1b,0xb4,0x25,0x6, 0xd2, +0x1c,0x7a,0x73,0x70,0xe4,0x22,0xbe,0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x33,0x7e,0x27, +0x71,0xb6,0x4d,0x22,0x78,0xe, 0xa5,0xbf,0xaa,0xa, 0x7e,0x24,0x0, 0x1, 0x7a,0x27, +0x71,0xb6,0x15,0xf, 0x7e,0x27,0x71,0xb6,0xbe,0x24,0x0, 0x1, 0x78,0x10,0xa5,0xbf, +0x9, 0x6, 0x7e,0x34,0x0, 0x2, 0x80,0x2, 0x6d,0x33,0x7a,0x37,0x71,0xb6,0x75,0xf, +0xea,0x22,0x7e,0x14,0xf7,0xf0,0x7e,0x4, 0x0, 0xff,0x7e,0x34,0x47,0x52,0x7e,0x24, +0x55,0x50,0x79,0x30,0x0, 0x2, 0x1b,0xa, 0x20,0x7e,0x34,0x45,0x20,0x7e,0x24,0x41, +0x44,0x79,0x30,0x0, 0x6, 0x79,0x20,0x0, 0x4, 0x7e,0x34,0x99,0x33,0x7e,0x24,0x66, +0xcc,0x79,0x30,0x0, 0xa, 0x79,0x20,0x0, 0x8, 0x7e,0x34,0x41,0x47,0x7e,0x24,0x46, +0x4c,0x79,0x30,0x0, 0xe, 0x79,0x20,0x0, 0xc, 0x22,0x7e,0x73,0x67,0xea,0x7a,0x73, +0x67,0xeb,0x7e,0x73,0x69,0x5f,0x7a,0x73,0x69,0x60,0xe4,0x7a,0xb3,0x69,0x63,0x7e, +0x73,0x72,0xff,0x7a,0x73,0x71,0x11,0x7e,0x73,0x69,0x84,0x7a,0x73,0x28,0x9f,0x22, +0x12,0x73,0x4b,0x12,0x73,0x2f,0x7e,0x73,0x71,0xd, 0x7a,0x73,0x73,0x1f,0x22,0x7e, +0x8, 0x73,0x35,0x2, 0x73,0x36,0xb, 0xa, 0x30,0xbe,0x37,0x72,0xf7,0x28,0x6, 0x9e, +0x37,0x72,0xf7,0x80,0x2, 0x6d,0x33,0x1b,0xa, 0x30,0x22,0x7e,0x8, 0x24,0x29,0x2, +0x73,0x36,0x7e,0xb3,0x29,0xff,0x4, 0x7a,0xb3,0x29,0xff,0x7e,0x73,0x29,0xff,0x7a, +0x73,0x70,0xf7,0x22,0x7e,0x37,0x73,0xe, 0xb, 0x34,0x7a,0x37,0x73,0xe, 0x7e,0x37, +0x73,0x10,0xbe,0x37,0x73,0xe, 0x28,0x3, 0x2, 0x73,0x7f,0x22,0x2, 0x73,0x64,0xe5, +0x9a,0x60,0x5, 0xd2,0x9c,0xa9,0xd6,0xdf,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca, +0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xc2,0x8f,0x12, +0x73,0x7c,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b, +0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7e,0xa3,0x28,0x1a,0x7e,0x70,0x4, 0xac,0x7a, +0xb, 0x34,0xbe,0x37,0x71,0xb4,0x40,0x39,0x7e,0x37,0x71,0xb4,0xb, 0x34,0x7a,0x37, +0x71,0xb4,0xbe,0x34,0x0, 0x1, 0x78,0x5, 0x7e,0xb3,0x71,0x39,0x22,0xbe,0x34,0x0, +0x2, 0x78,0x3, 0x7c,0xba,0x22,0xbe,0x34,0x0, 0x2, 0x50,0x9, 0x7d,0x23,0x1b,0x25, +0x9, 0xb2,0x73,0x46,0x22,0x9e,0x34,0x0, 0x3, 0x2e,0x37,0x24,0x2b,0x7e,0x39,0xb0, +0x22,0x74,0xff,0x22,0x7c,0xab,0xbe,0xa0,0xfa,0x78,0x5, 0x7e,0xb3,0x4d,0x46,0x22, +0x4c,0xaa,0x78,0x5, 0x7e,0xb3,0x71,0x58,0x22,0xbe,0xa0,0x3, 0x38,0x13,0x30,0x24, +0x6, 0x7e,0x18,0x6e,0x72,0x80,0x4, 0x7e,0x18,0x6e,0xb0,0x7a,0x1f,0x6f,0xc, 0x80, +0x5, 0xbe,0xa0,0x6e,0x38,0xe, 0xa, 0x1a,0x7e,0x1f,0x6f,0xc, 0x2d,0x31,0x1b,0x34, +0x7e,0x1b,0xb0,0x22,0xbe,0xa0,0xd3,0x68,0x5, 0xbe,0xa0,0xd4,0x78,0x12,0xbe,0xa0, +0xd3,0x78,0x8, 0x6d,0x33,0x7a,0x37,0x71,0xb4,0x80,0x2, 0x15,0xf, 0x2, 0x73,0xb7, +0xbe,0xa0,0xf6,0x78,0x7, 0x7e,0x34,0x1b,0xd6,0x2, 0x77,0x99,0xbe,0xa0,0xf7,0x78, +0xa, 0x7e,0x34,0x1b,0xd6,0x12,0x30,0xa4,0xa, 0x56,0x22,0xbe,0xa0,0xf8,0x68,0x5, +0xbe,0xa0,0xf9,0x78,0x1e,0xbe,0xa0,0xf8,0x78,0x8, 0x6d,0x33,0x7a,0x37,0x71,0xb4, +0x80,0x2, 0x15,0xf, 0x7e,0x37,0x71,0xb4,0x7d,0x23,0xb, 0x24,0x7a,0x27,0x71,0xb4, +0x2, 0x75,0x10,0xbe,0xa0,0xeb,0x68,0x5, 0xbe,0xa0,0xec,0x78,0x5, 0x7c,0xba,0x2, +0x77,0xc8,0xbe,0xa0,0x99,0x68,0x5, 0xbe,0xa0,0x9a,0x78,0x25,0x7e,0x24,0x1b,0xd8, +0x7e,0xb3,0x70,0xf6,0xa, 0x3b,0x2d,0x32,0x6d,0x22,0x2e,0x24,0x0, 0xff,0x7e,0x1b, +0x70,0x4, 0x7a,0xb3,0x70,0xf6,0xbe,0xa0,0x9a,0x78,0x3, 0x75,0xf, 0x99,0x7c,0xb7, +0x22,0xbe,0xa0,0x80,0x40,0xc, 0xbe,0xa0,0xef,0x38,0x7, 0xa, 0x3a,0x9, 0xb3,0x70, +0x66,0x22,0xbe,0xa0,0xfc,0x78,0x5, 0x7e,0xb3,0x71,0xd, 0x22,0xbe,0xa0,0xfe,0x78, +0xc, 0x7e,0xa3,0x73,0x8, 0x74,0x27,0xa4,0x9, 0xb5,0x6f,0x12,0x22,0x74,0xff,0x22, +0x7e,0x24,0xe, 0x6, 0x2d,0x32,0x2, 0x75,0x23,0x7c,0xb7,0x54,0x7, 0xa, 0x3b,0x2e, +0x34,0x0, 0xf5,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x74,0x1, 0x7a,0xb3, +0x73,0x5e,0x7e,0xb3,0x71,0x36,0xb4,0x1, 0x6, 0xe4,0x7a,0xb3,0x73,0x5e,0x22,0x7e, +0xb4,0x21,0x53,0x7d,0x3b,0x12,0x75,0x23,0x7c,0x7b,0x1e,0x70,0x7a,0x73,0x69,0x6c, +0x7e,0xa4,0x0, 0x96,0x7a,0xa7,0x69,0x6d,0x7e,0x34,0x0, 0x8c,0x7a,0x37,0x69,0x6f, +0x12,0xd9,0xff,0x7e,0xa3,0x67,0xd5,0xbe,0xa0,0x0, 0x38,0x2, 0xa1,0xff,0xbe,0xa0, +0x8, 0x28,0x1f,0x7e,0x37,0x67,0xdb,0xbe,0x34,0x1, 0x90,0x58,0x15,0x7d,0x3b,0x12, +0x75,0x23,0x1e,0xb0,0xa, 0x3b,0x7d,0x2a,0x7e,0x14,0x0, 0x8c,0x7e,0x4, 0x0, 0x82, +0x80,0x66,0xbe,0xa0,0x6, 0x28,0x1b,0x7e,0x37,0x67,0xdb,0xbe,0x34,0x1, 0xf4,0x58, +0x11,0x7d,0x3b,0x12,0x75,0x23,0xa, 0x3b,0x7e,0x24,0x0, 0xa0,0x7d,0x1a,0x7d,0xa, +0x80,0x46,0xbe,0xa0,0x4, 0x28,0x1f,0x7e,0xa7,0x67,0xdb,0xbe,0xa4,0x2, 0x58,0x58, +0x15,0x7d,0x3b,0x12,0x75,0x23,0xa, 0x3b,0x7e,0x24,0x0, 0xb4,0x7e,0x14,0x0, 0xaa, +0x7e,0x4, 0x0, 0xc8,0x80,0x22,0xbe,0xa0,0x2, 0x28,0x24,0x7e,0xa7,0x67,0xdb,0xbe, +0xa4,0x3, 0x20,0x58,0x1a,0x7d,0x3b,0x12,0x75,0x23,0xa, 0x3b,0x7e,0x24,0x0, 0xdc, +0x7e,0x14,0x0, 0xd2,0x7e,0x4, 0x0, 0xe6,0x12,0x76,0x30,0x80,0x7, 0x80,0x0, 0xe4, +0x7a,0xb3,0x73,0x5e,0x7e,0xb3,0x73,0x5e,0x70,0x23,0x90,0x21,0x53,0xe4,0x93,0xa, +0x3b,0x7e,0x14,0x21,0x5b,0x12,0x77,0x91,0x7e,0x14,0x21,0x5d,0x12,0x76,0x55,0x7e, +0x54,0x21,0x67,0x7e,0x44,0x0, 0xff,0xb, 0x2a,0x0, 0x2, 0x76,0x30,0xd2,0x1b,0x22, +0x7a,0x73,0x69,0x6c,0x7a,0x27,0x69,0x6d,0x7a,0x17,0x69,0x6f,0x7a,0x7, 0x69,0x79, +0x6d,0x33,0x9d,0x30,0x12,0x31,0xce,0x12,0x35,0x86,0x7a,0x73,0x70,0xe7,0x22,0x12, +0x77,0xa9,0x2, 0x75,0x2c,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x10,0x22,0x7d,0x13,0x9f, +0x11,0x7e,0xf4,0x21,0xdc,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x0, 0x7e,0xf4,0x21,0xec, +0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0xf0,0x7e,0xd4,0x21,0xee,0x7e,0xc4,0x0, 0xff,0xb, +0x6a,0xe0,0x90,0x1c,0x2c,0xe4,0x93,0x70,0x3, 0x7d,0x31,0x22,0x90,0x21,0xd9,0xe4, +0x93,0xb4,0x1, 0x6, 0x7e,0x83,0x69,0x8e,0x80,0x4, 0x7e,0x83,0x69,0x8f,0x12,0x77, +0xa1,0xbe,0x14,0x0, 0x3f,0x38,0x1a,0x7e,0x24,0x0, 0x3f,0x9d,0x21,0x7e,0x14,0x21, +0xf2,0x12,0x77,0x73,0x12,0x77,0x85,0x48,0x2, 0x7f,0x10,0x9f,0x1, 0x7f,0x10,0xe1, +0x6a,0x7d,0x54,0x9e,0x54,0x0, 0x3f,0xbd,0x51,0x38,0x43,0x7d,0x54,0x9e,0x54,0x0, +0x1f,0xbd,0x51,0x40,0x1d,0x7d,0x34,0x9e,0x34,0x0, 0x40,0x12,0x77,0x6b,0x90,0x21, +0xf1,0x12,0x77,0x88,0x48,0x4, 0x7f,0x10,0x1b,0x1c,0xa, 0xb, 0x7d,0x1f,0x9d,0x10, +0x80,0x16,0xbd,0x41,0x50,0x74,0x7e,0xb3,0x6e,0x3, 0xbe,0xb0,0x0, 0x28,0x6b,0x7d, +0x34,0xb, 0x34,0x12,0x77,0x6b,0x7d,0x1f,0x6d,0x0, 0x2f,0x10,0x80,0x5c,0x7d,0x50, +0x1b,0x54,0xbd,0x51,0x40,0x1f,0x7d,0x30,0x9d,0x31,0x6d,0x22,0x7e,0x14,0x21,0xf6, +0x12,0x76,0x55,0x12,0x22,0xb4,0x12,0x77,0x7e,0x7d,0x1e,0x1b,0x14,0x6d,0x0, 0x9f, +0x1, 0x7f,0x10,0x80,0x19,0x7d,0x31,0x9d,0x30,0x6d,0x22,0x7e,0x14,0x21,0xf8,0x12, +0x76,0x55,0x12,0x22,0xb4,0x12,0x77,0x7e,0x7d,0x1e,0x6d,0x0, 0x2f,0x10,0x12,0x77, +0x85,0x58,0x4, 0x7f,0x10,0x80,0x13,0x90,0x21,0xf1,0xe4,0x93,0xa, 0xb, 0x7d,0x1f, +0x9d,0x10,0x6d,0x0, 0xbf,0x10,0x8, 0x2, 0x7f,0x10,0x22,0x7d,0x21,0x9d,0x23,0x7e, +0x14,0x21,0xf4,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0xad,0x32,0x6d,0x22,0x7c,0x76, +0x7c,0x65,0x1a,0x24,0x22,0x90,0x21,0xf0,0xe4,0x93,0xa, 0x1b,0x6d,0x0, 0xbf,0x10, +0x22,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x50, +0x22,0x7e,0x90,0x40,0xac,0x89,0x1b,0x44,0x22,0x7e,0x8, 0x73,0x5e,0x7e,0x34,0x0, +0x1, 0x74,0xff,0x2, 0x24,0x39,0x7c,0x7b,0xc4,0x23,0x54,0x1f,0xa, 0x2b,0x9, 0xa2, +0x66,0xc3,0x12,0x75,0x19,0x5c,0xba,0x22,0xb4,0xeb,0x5, 0xe4,0x7a,0xb3,0x71,0xb8, +0x7e,0x73,0x71,0xb8,0xa, 0x27,0x2e,0x24,0x0, 0x16,0x12,0x5f,0xf5,0x7c,0xab,0x7c, +0xb7,0x4, 0x7a,0xb3,0x71,0xb8,0xb4,0x3, 0xb, 0xe4,0x7a,0xb3,0x71,0xb8,0x6d,0x33, +0x7a,0x37,0x71,0xb6,0x75,0xf, 0xeb,0x7c,0xba,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b, +0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0x12,0x4b, +0x6b,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda, +0x5b,0xda,0x6b,0xda,0x7b,0x32,0x12,0x78,0x2d,0x75,0x8, 0x0, 0x32,0xa9,0xc0,0x93, +0x22,0xca,0x79,0x7c,0xfb,0x7f,0x51,0x7f,0x40,0x74,0x9, 0xac,0xbf,0x9, 0xb5,0x68, +0x6a,0xf5,0x30,0x74,0x9, 0xac,0xbf,0x9, 0xb5,0x68,0x6b,0xc4,0x54,0xf0,0xf5,0x31, +0x74,0x9, 0xac,0xbf,0x9, 0xe5,0x68,0x69,0x7e,0x73,0x69,0x6b,0xbc,0x7e,0x28,0x58, +0x7e,0xb3,0x69,0x66,0x70,0x28,0x75,0x32,0xf, 0x7e,0x8, 0x0, 0x30,0xa, 0x3e,0x2e, +0x34,0x6e,0x5e,0x6d,0x22,0x74,0x1, 0x12,0x78,0xe2,0x75,0x32,0x20,0x7e,0x8, 0x0, +0x31,0xa, 0x3e,0x2e,0x34,0x6e,0x68,0x74,0x10,0x12,0x78,0xe2,0x80,0xe, 0xa, 0x3e, +0x9, 0xb3,0x6e,0x5e,0xf5,0x30,0x9, 0xb3,0x6e,0x68,0xf5,0x31,0x74,0x7, 0xac,0xbe, +0x9, 0xb5,0x69,0x19,0xb4,0x1, 0x11,0xe4,0xa, 0x3e,0x19,0xb3,0x6e,0x5e,0x19,0xb3, +0x6e,0x68,0x75,0x30,0x0, 0x75,0x31,0x0, 0x7e,0xb3,0x69,0x7f,0xb4,0xff,0x16,0x85, +0x2f,0x30,0x75,0x30,0x0, 0x74,0x9, 0xac,0xbf,0x9, 0xb5,0x68,0x69,0xbe,0xb0,0xff, +0x68,0x3, 0x75,0x30,0x1, 0xe5,0x30,0x7a,0x4b,0xb0,0xe5,0x31,0x7a,0x5b,0xb0,0xda, +0x79,0x22,0x7c,0x9b,0x7e,0x1b,0xa0,0x4c,0xaa,0x78,0x7, 0x7e,0xb, 0xb0,0x7a,0x1b, +0xb0,0x22,0xa, 0xda,0x7e,0xb, 0x80,0xa, 0xe8,0x7d,0xfe,0x9d,0xfd,0xbe,0xf4,0x0, +0x0, 0x8, 0x4, 0x9d,0xed,0x80,0x4, 0x6d,0xee,0x9d,0xef,0xe5,0x32,0xa, 0xfb,0xbd, +0xef,0x8, 0xf, 0xbc,0x8a,0x7c,0xba,0x28,0x4, 0x2c,0xb9,0x80,0x2, 0x9c,0xb9,0x7a, +0x1b,0xb0,0x7e,0x1b,0x70,0x7a,0xb, 0x70,0x22,0x7e,0xb3,0x6f,0x10,0x4, 0x7a,0xb3, +0x6f,0x10,0x7e,0x73,0x6f,0x10,0x7a,0x73,0x70,0xf5,0x22,0xe4,0x7a,0xb3,0x71,0x58, +0x90,0x1c,0x45,0x93,0x7a,0xb3,0x71,0x5a,0x90,0x1c,0x46,0xe4,0x93,0x7a,0xb3,0x71, +0x5b,0x90,0x21,0x51,0xe4,0x93,0x7a,0xb3,0x71,0x5d,0xe4,0x7a,0xb3,0x71,0x5e,0x74, +0x1, 0x7a,0xb3,0x71,0x63,0x12,0x40,0x46,0xe4,0x7a,0xb3,0x71,0x66,0x7e,0x73,0x6f, +0xe0,0x7a,0x73,0x71,0x78,0x7e,0x73,0x6f,0xe1,0x7a,0x73,0x71,0x79,0x7e,0x73,0x6f, +0xe2,0x7a,0x73,0x71,0x7a,0x7e,0x73,0x6f,0xaf,0x7a,0x73,0x71,0x81,0x7e,0x73,0x6f, +0xb0,0x7a,0x73,0x71,0x82,0x90,0x1c,0x49,0x93,0x7a,0xb3,0x71,0x76,0x90,0x1c,0x4a, +0xe4,0x93,0x7a,0xb3,0x71,0x77,0x74,0x1, 0x7a,0xb3,0x71,0x88,0x7e,0x34,0x22,0x32, +0x12,0x30,0xa4,0x7a,0x37,0x71,0xb2,0x74,0x2, 0x7a,0xb3,0x71,0x61,0x74,0x17,0x7a, +0xb3,0x71,0x85,0x22,0x7e,0x18,0x15,0xa0,0x7a,0x1f,0x22,0xdc,0x7e,0x18,0x4, 0x0, +0x7a,0x1f,0x22,0xe0,0x7e,0xf, 0x22,0xdc,0x12,0x56,0xed,0x7e,0xf, 0x22,0xe0,0x7e, +0x34,0x4, 0x68,0x12,0x24,0x39,0x7a,0xb3,0x24,0x26,0x22,0x7e,0x34,0x4, 0x71,0xca, +0x39,0x7e,0x34,0x1c,0x43,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x69,0x8a,0x12,0x24,0x14, +0x1b,0xfd,0x7e,0x37,0x69,0x94,0x2e,0x37,0x69,0x92,0x7a,0x37,0x6d,0xfe,0x90,0x1c, +0x49,0xe4,0x93,0xca,0xb8,0x90,0x1c,0x4a,0xe4,0x93,0x7c,0x7b,0xda,0xb8,0x12,0x51, +0xe3,0x90,0x21,0xd9,0xe4,0x93,0x70,0x6, 0x7e,0x63,0x69,0x8d,0x80,0x4, 0x7e,0x63, +0x69,0x8c,0x7e,0x70,0x40,0xac,0x67,0x1b,0x34,0x7a,0x37,0x6e,0x0, 0x22,0x7e,0x8, +0x66,0x4b,0x7e,0x34,0x1, 0xa1,0xe4,0x12,0x24,0x39,0x90,0x21,0x52,0x93,0x7c,0x7b, +0x74,0x9, 0xac,0x7b,0x7e,0x8, 0x66,0xc7,0x74,0xff,0x2, 0x24,0x39,0x7e,0x34,0x0, +0x27,0xca,0x39,0x7e,0x34,0x20,0xb4,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x6f,0x11,0x12, +0x24,0x14,0x1b,0xfd,0x7e,0x34,0x0, 0x27,0xca,0x39,0x7e,0x34,0x20,0xdb,0x7e,0x24, +0x0, 0xff,0x7e,0x8, 0x6f,0x38,0x12,0x24,0x14,0x1b,0xfd,0x7e,0x34,0x0, 0x27,0xca, +0x39,0x7e,0x34,0x21,0x2, 0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x6f,0x5f,0x12,0x24,0x14, +0x1b,0xfd,0x7e,0x34,0x0, 0x27,0xca,0x39,0x7e,0x34,0x21,0x29,0x7e,0x24,0x0, 0xff, +0x7e,0x8, 0x6f,0x86,0x12,0x24,0x14,0x1b,0xfd,0x6c,0x88,0x7c,0xb8,0x12,0x43,0x9c, +0xb, 0x80,0xbe,0x80,0x4, 0x40,0xf4,0x2, 0x54,0x2c,0xca,0x3b,0x7c,0xfb,0x6c,0xee, +0x74,0x27,0xac,0xbe,0x19,0xf5,0x6f,0x14,0xb, 0xe0,0xbe,0xe0,0x4, 0x78,0xf1,0x7e, +0x64,0x1, 0xa, 0x6c,0xee,0x7e,0x30,0x2c,0xac,0x3e,0x2e,0x14,0x0, 0xeb,0x6d,0x0, +0x7c,0xbf,0x12,0xc, 0xaa,0x12,0x7b,0x11,0x49,0x25,0x0, 0xeb,0x12,0x6, 0x48,0x12, +0x7b,0x11,0x49,0x25,0x0, 0xeb,0x12,0x6, 0xc5,0x12,0x7b,0x18,0x40,0xd7,0xda,0x3b, +0x22,0x7d,0x36,0x74,0x2c,0xac,0xbe,0x22,0x2e,0x64,0x0, 0xb5,0xb, 0xe0,0xbe,0xe0, +0x3, 0x22,0xca,0x3b,0x7c,0xfb,0x6c,0xee,0x74,0x27,0xac,0xbe,0x19,0xf5,0x6f,0x11, +0xb, 0xe0,0xbe,0xe0,0x4, 0x78,0xf1,0x7e,0x64,0x1, 0x0, 0x6c,0xee,0x7e,0x30,0x2c, +0xac,0x3e,0x2e,0x14,0x0, 0xd9,0x6d,0x0, 0xa, 0x3f,0x12,0x3b,0xcc,0x12,0xd, 0xd3, +0x7d,0x36,0xb, 0x34,0x74,0x2c,0xac,0xbe,0x49,0x25,0x0, 0xd9,0x12,0x0, 0x2e,0x12, +0x7b,0x18,0x40,0xd9,0xda,0x3b,0x22,0x7e,0xb3,0x73,0x8, 0x7c,0xab,0xd2,0x2, 0xe5, +0x1a,0x70,0x4, 0xc2,0x2, 0x80,0xb, 0x4c,0xaa,0x68,0x5, 0xbe,0xa0,0x3, 0x78,0x2, +0xc2,0x2, 0xa2,0x2, 0x22,0xca,0x3b,0x7c,0x67,0x7c,0x7b,0x6d,0x22,0x7a,0x27,0x5d, +0x7, 0x7e,0x27,0x6d,0xfe,0xb, 0x26,0x7a,0x25,0x28,0x7c,0xb6,0x12,0x7b,0x6b,0xe4, +0x33,0xf5,0x2a,0x68,0x6, 0x4c,0x77,0x78,0x2, 0xa1,0x1a,0x12,0x7d,0x87,0x7a,0xa1, +0x2f,0x74,0x26,0xa4,0x49,0xb5,0x29,0x8b,0x49,0xa5,0x29,0x89,0x49,0x95,0x29,0x8f, +0x49,0x85,0x29,0x8d,0x7e,0x34,0x5d,0xb, 0x1e,0x34,0x3e,0x34,0x7d,0x73,0x6d,0x66, +0x7e,0x34,0x61,0x75,0x1e,0x34,0x3e,0x34,0x6d,0x22,0x7a,0x1d,0x2b,0x7e,0x18,0xc, +0xd0,0x7a,0x1d,0x30,0x7f,0x3, 0x7e,0x18,0x11,0x38,0x74,0x1, 0x12,0x7d,0x4d,0x12, +0x7d,0x1d,0x7e,0x37,0x65,0xdd,0x7d,0x13,0x3e,0x14,0x49,0x1, 0xc, 0xd0,0x49,0x21, +0x11,0x38,0x9d,0x20,0x2d,0x17,0x7d,0x6, 0x1b,0xa, 0x20,0x12,0x7d,0x2b,0x78,0xe2, +0xe5,0x2a,0x60,0x7b,0x7e,0x73,0x29,0xf3,0xbe,0x71,0x2f,0x68,0x37,0x6d,0x33,0x80, +0x26,0x7e,0x35,0x26,0x7d,0x23,0x3e,0x24,0x7f,0x4, 0x2d,0x12,0xb, 0xa, 0x50,0x49, +0x42,0x1a,0x8, 0x2d,0x45,0x7f,0x5, 0x2d,0x12,0xb, 0xa, 0x10,0x49,0x52,0x15,0xa0, +0x2d,0x51,0x12,0x7d,0x3e,0xb, 0x34,0x7a,0x35,0x26,0x7e,0x35,0x28,0xbe,0x35,0x26, +0x38,0xcf,0x80,0x3b,0x7e,0x18,0x1a,0x8, 0x7a,0x1d,0x30,0x7e,0xd, 0x2b,0x7e,0x18, +0x15,0xa0,0x74,0x1, 0x12,0x7d,0x4d,0x7e,0x1d,0x2b,0x7a,0x1d,0x30,0x7f,0x3, 0x7f, +0x13,0x12,0x7d,0x91,0x12,0x7d,0x1d,0x7e,0x37,0x65,0xdd,0x7d,0x23,0x3e,0x24,0x49, +0x42,0x1a,0x8, 0x49,0x52,0x15,0xa0,0x12,0x7d,0x3e,0x12,0x7d,0x2b,0x78,0xe8,0x7f, +0x3, 0x12,0xc1,0x98,0x7a,0x37,0x5d,0x7, 0x12,0x7d,0x1d,0x7e,0x37,0x65,0xdd,0x7d, +0x23,0x3e,0x24,0x7f,0x23,0x2d,0x52,0xb, 0x2a,0x10,0xbe,0x14,0x0, 0x0, 0x8, 0x5, +0xb, 0x2a,0x20,0x80,0x4, 0x6d,0x22,0x9d,0x21,0xbe,0x27,0x5d,0x7, 0x28,0x13,0xbe, +0x14,0x0, 0x0, 0x8, 0x5, 0xb, 0x2a,0x20,0x80,0x4, 0x6d,0x22,0x9d,0x21,0x7a,0x27, +0x5d,0x7, 0x12,0x7d,0x2b,0x78,0xc4,0x7e,0x37,0x5d,0x7, 0xbe,0x34,0x7f,0xff,0x28, +0x8, 0x7e,0x34,0x7f,0xff,0x7a,0x37,0x5d,0x7, 0x7e,0x37,0x5d,0x7, 0x7a,0x37,0x29, +0xe9,0xe5,0x2a,0x70,0x25,0x7e,0x8, 0x11,0x38,0x7e,0x18,0xc, 0xd0,0x12,0x7d,0xb8, +0x12,0x7d,0x1d,0x7e,0x27,0x65,0xdd,0x3e,0x24,0x49,0x32,0xc, 0xd0,0x59,0x32,0x11, +0x38,0x7e,0x37,0x65,0xdd,0x12,0x7d,0x2b,0x78,0xe9,0xda,0x3b,0x22,0x7e,0x37,0x6d, +0xfe,0x7a,0x37,0x65,0xdd,0x6d,0x33,0x7a,0x35,0x26,0x22,0xb, 0x34,0x7a,0x37,0x65, +0xdd,0x7e,0x35,0x26,0xb, 0x34,0x7a,0x35,0x26,0xbe,0x34,0x0, 0x4, 0x22,0x9d,0x54, +0x7f,0x3, 0x2d,0x12,0xb, 0xa, 0x20,0x2d,0x25,0x1b,0xa, 0x20,0x22,0x7c,0xab,0x7f, +0x61,0x7f,0x70,0x7e,0x8, 0x65,0xdf,0x7e,0x34,0x0, 0xc, 0xe4,0x12,0x24,0x39,0x7e, +0xb3,0x69,0x8d,0x7a,0xb3,0x65,0xe0,0x7e,0xb3,0x69,0x8c,0x7a,0xb3,0x65,0xdf,0xe4, +0x12,0x7d,0xf1,0x12,0x7d,0xa6,0x7a,0xa3,0x65,0xe2,0x6d,0x33,0x7a,0x37,0x65,0xe9, +0x7e,0x8, 0x65,0xdf,0x2, 0x8, 0xe5,0x7e,0xb3,0x29,0xe8,0x12,0x7f,0x84,0x7c,0xab, +0x22,0x12,0x7d,0xd1,0x12,0x7d,0xa6,0x7e,0x34,0x0, 0x10,0x7a,0x37,0x65,0xe9,0x7e, +0x8, 0x65,0xdf,0x2, 0x8, 0xe5,0x7a,0x37,0x65,0xe3,0x7e,0x1d,0x30,0x7a,0x37,0x65, +0xe5,0x7d,0x3f,0x7a,0x37,0x65,0xe7,0x22,0x12,0x7d,0xd1,0x7a,0x37,0x65,0xe3,0x12, +0x7d,0xb1,0x7e,0x34,0x0, 0x20,0x7a,0x37,0x65,0xe9,0x7e,0x8, 0x65,0xdf,0x2, 0x8, +0xe5,0x7f,0x61,0x7f,0x70,0x7e,0x8, 0x65,0xdf,0x7e,0x34,0x0, 0xc, 0xe4,0x12,0x24, +0x39,0x7e,0x73,0x69,0x8d,0x7a,0x73,0x65,0xe0,0x7e,0x73,0x69,0x8c,0x7a,0x73,0x65, +0xdf,0x7a,0xb3,0x65,0xe1,0x7d,0x3d,0x22,0xca,0xf8,0x7e,0xb3,0x6d,0xfb,0x70,0xd, +0x7e,0xf, 0x22,0xe0,0x7e,0x1f,0x22,0xd8,0x12,0x7d,0xb8,0x80,0x14,0x7e,0x1f,0x22, +0xdc,0x7a,0x1d,0x30,0x7e,0xf, 0x22,0xe0,0x7e,0x1f,0x22,0xd8,0x74,0x1, 0x12,0x7d, +0x4d,0x7e,0x37,0x6d,0xfe,0x90,0x1c,0x2b,0xe4,0x93,0x70,0x13,0x6c,0xff,0x6d,0x22, +0x7d,0x53,0x12,0x7e,0x79,0x1b,0xa, 0x20,0x12,0x7e,0x71,0x78,0xf1,0x80,0x2f,0x6c, +0xff,0x7e,0xb3,0x6d,0xfb,0xb4,0x1, 0x14,0x7d,0x53,0x3e,0x54,0x7e,0xf, 0x22,0xdc, +0x2d,0x15,0xb, 0xa, 0x40,0x12,0x7e,0x82,0x9d,0x24,0x80,0x7, 0x7d,0x53,0x3e,0x54, +0x12,0x7e,0x82,0x12,0x7e,0x7b,0x1b,0xa, 0x20,0x12,0x7e,0x71,0x78,0xd3,0xda,0xf8, +0x22,0xb, 0x34,0xb, 0xf0,0xbe,0xf0,0x4, 0x22,0x3e,0x54,0x7e,0xf, 0x22,0xe0,0x2d, +0x15,0x22,0x7e,0xf, 0x22,0xd8,0x2d,0x15,0xb, 0xa, 0x20,0x22,0xca,0xd8,0xca,0x79, +0xd2,0x0, 0x12,0x62,0xf2,0x50,0xfb,0x7e,0xe3,0x3, 0xd5,0x7a,0xe3,0x24,0x27,0x7e, +0xd3,0x3, 0xd6,0xa, 0x3e,0x9, 0xb3,0x3, 0xcf,0x60,0x38,0xa, 0x3b,0x1b,0x34,0x7c, +0xa7,0x7a,0xa3,0x71,0x83,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x7a,0xb3,0x24, +0x26,0xe4,0xa, 0x3e,0x19,0xb3,0x3, 0xcf,0x9, 0xf3,0x3, 0xd1,0x7c,0xbe,0x7c,0x7f, +0x12,0x57,0xbd,0x7c,0xbe,0x7c,0x7f,0x12,0xbf,0x5e,0x7e,0xb3,0x3, 0xd5,0x4, 0x7a, +0xb3,0x3, 0xd5,0x7e,0x73,0x3, 0xd6,0xbe,0x73,0x3, 0xd5,0x38,0x9, 0x12,0x2f,0x60, +0x12,0xbc,0x93,0x12,0xd5,0x31,0x7e,0xb3,0x24,0x26,0xbe,0xb0,0x1, 0x68,0x7, 0x7e, +0xb3,0x73,0x1f,0xb4,0x3, 0x44,0x74,0xa, 0xac,0xbf,0x49,0x35,0x6f,0xb7,0x7e,0xf, +0x22,0xd8,0x12,0x56,0xfc,0x7c,0xbe,0x7c,0x7f,0x12,0x80,0x11,0x92,0x0, 0xe5,0x1a, +0x70,0xc, 0xbe,0xe0,0x1, 0x40,0x7, 0xe4,0x7a,0xb3,0x24,0x26,0xc2,0x0, 0x7c,0xbe, +0x7c,0x7f,0x12,0x7b,0x85,0x30,0x0, 0x12,0x12,0x7d,0xf8,0x7c,0xbe,0x7c,0x7f,0x12, +0xbe,0xb7,0x7a,0xe3,0x71,0x84,0x7a,0xf3,0x73,0xa, 0x7e,0xb3,0x73,0x1f,0xb4,0x1, +0x3, 0x12,0x8f,0xfa,0x7c,0xbd,0x14,0xbc,0xbe,0x78,0x3, 0x12,0xb, 0xe5,0x12,0xcc, +0x8d,0x12,0x7f,0x72,0x50,0x7, 0x7c,0xbf,0x7c,0x7e,0x12,0xba,0x9a,0xda,0x79,0xda, +0xd8,0x22,0xe5,0x1b,0x70,0xc, 0x7e,0x73,0x73,0x7, 0xbe,0x73,0x73,0xb, 0x40,0x2, +0xc3,0x22,0xd3,0x22,0x7c,0x7b,0x6c,0xaa,0x6c,0x66,0xa, 0x26,0x12,0x5f,0xf1,0xbc, +0xb7,0x78,0x4, 0x7c,0xa6,0x80,0x7, 0xb, 0x60,0xbe,0x60,0x3, 0x40,0xec,0x7c,0xba, +0x22,0x12,0x8f,0x49,0x12,0x9f,0xb4,0x12,0x7f,0x72,0x40,0x5, 0xe4,0x7a,0xb3,0x68, +0x4, 0x7e,0xb3,0x68,0x4, 0x60,0xb, 0xe4,0x7a,0xb3,0x29,0xf6,0x74,0x1f,0x7a,0xb3, +0x6d,0xfd,0x12,0x7f,0x72,0x40,0x6, 0x12,0xd9,0xd3,0x12,0xdb,0x3f,0x7e,0xb3,0x68, +0x7, 0x60,0xb, 0xe4,0x7a,0xb3,0x29,0xf7,0x74,0x2, 0x7a,0xb3,0x29,0xfe,0x7e,0xb3, +0x29,0xfe,0xbe,0xb0,0x0, 0x28,0x8, 0x14,0x7a,0xb3,0x29,0xfe,0x12,0xd6,0xfd,0x7e, +0xb3,0x68,0xa, 0x60,0x4, 0xe4,0x2, 0xd8,0xd9,0x22,0xca,0xf8,0x6c,0xff,0x12,0x7e, +0x8c,0xb, 0xf0,0x7e,0x73,0x3, 0xd6,0xbc,0x7f,0x38,0xf3,0x12,0x57,0xb5,0xda,0xf8, +0x22,0x7c,0x67,0x7c,0x7b,0xd2,0x1, 0x7e,0xb3,0x73,0x1f,0xb4,0x3, 0x4c,0x7c,0xb6, +0x12,0x7b,0x6b,0x50,0x45,0x7e,0xa3,0x71,0x61,0xbe,0xa0,0x2, 0x40,0x32,0x7e,0xb3, +0x71,0x69,0x70,0x28,0x7e,0x63,0x73,0x5d,0xa, 0x26,0x2e,0x24,0x0, 0xe, 0x12,0x5f, +0xf5,0x24,0xff,0x92,0x1, 0x7c,0xb6,0x4, 0x7a,0xb3,0x73,0x5d,0x7e,0x63,0x73,0x5d, +0xbe,0x60,0x4, 0x40,0x15,0xe4,0x7a,0xb3,0x73,0x5d,0x80,0xe, 0xd2,0x1, 0x80,0xa, +0xbc,0xa7,0x78,0x4, 0xd2,0x1, 0x80,0x2, 0xc2,0x1, 0xa2,0x1, 0x22,0xca,0xd8,0xca, +0x79,0xc2,0x0, 0xc2,0x1, 0xc2,0x4, 0xd2,0x2, 0xd2,0x3, 0x6c,0xdd,0x80,0x42,0x12, +0x83,0xe5,0x50,0x4, 0xd2,0x1, 0x80,0x37,0xd2,0x0, 0xd2,0x4, 0x7e,0x73,0x69,0x8f, +0xa, 0x27,0x1b,0x24,0xa, 0x3e,0xbd,0x32,0x58,0x2, 0xc2,0x2, 0x4c,0xff,0x78,0xa, +0x7c,0xbf,0x4, 0x12,0x81,0x8e,0xbd,0x3f,0x18,0x15,0x7e,0xb3,0x69,0x8e,0x14,0xbc, +0xbf,0x78,0xa, 0x7c,0xbf,0x14,0x12,0x81,0x8e,0xbd,0x3f,0x18,0x2, 0xc2,0x3, 0xb, +0xd0,0x7e,0xb3,0x67,0xd5,0xbc,0xbd,0x38,0xb6,0xa2,0x4, 0x82,0x3, 0x92,0x3, 0xa2, +0x4, 0x82,0x2, 0x92,0x2, 0xc2,0x3, 0x70,0xe, 0x7e,0xb3,0x72,0x8, 0xbe,0xb0,0x0, +0x28,0x5, 0x14,0x7a,0xb3,0x72,0x8, 0xa2,0x1e,0x92,0x6, 0x12,0x97,0xb8,0x92,0x5, +0x30,0x1, 0x6, 0xa2,0x5, 0x92,0x1, 0x92,0x1e,0x7e,0x73,0x72,0x8, 0xbe,0x70,0x0, +0x28,0x5, 0x20,0x3, 0x2, 0xc2,0x1, 0xa2,0x3, 0x82,0x0, 0x82,0x1, 0x50,0x2, 0xc2, +0x0, 0xa2,0x0, 0x82,0x1, 0x50,0x29,0x7e,0xb3,0x72,0x7, 0xb4,0x1, 0x4, 0xc2,0x1, +0x80,0x1e,0xb4,0x2, 0x7, 0x20,0x2, 0x4, 0xc2,0x1, 0x80,0x14,0x70,0x12,0x7e,0x27, +0x67,0xdb,0x7e,0x34,0x0, 0x5, 0xad,0x32,0xbe,0x37,0x67,0xe3,0x8, 0x2, 0xc2,0x1, +0x30,0x1, 0x2, 0xc2,0x0, 0x30,0x1, 0x4, 0x74,0x2, 0x80,0x12,0x30,0x0, 0xe, 0x74, +0x1, 0x7a,0xb3,0x72,0x7, 0x74,0x8, 0x7a,0xb3,0x72,0x8, 0x80,0x5, 0xe4,0x7a,0xb3, +0x72,0x7, 0x6c,0xdd,0x80,0x1b,0x12,0x83,0xe5,0x50,0x5, 0x20,0x1, 0x2, 0x80,0x8, +0x12,0x83,0xf1,0x40,0xa, 0x20,0x0, 0x7, 0xc2,0x6, 0x7c,0xbd,0x12,0x89,0xc7,0xb, +0xd0,0x7e,0x73,0x67,0xd5,0xbc,0x7d,0x38,0xdd,0xda,0x79,0xda,0xd8,0x22,0x7c,0x7e, +0x12,0x81,0x9d,0x7e,0xf4,0x0, 0x3, 0xad,0xf3,0x7c,0xbf,0x7c,0x7e,0x12,0x87,0xc2, +0x2d,0x31,0xb, 0x1a,0x30,0x22,0xca,0x79,0x7e,0xb3,0x69,0x84,0x60,0x2, 0x61,0xd8, +0x12,0xdd,0xf7,0x78,0x2, 0x61,0xd8,0x7e,0xa3,0x67,0xd5,0xbe,0xa0,0x1, 0x78,0x1b, +0x7e,0xb3,0x67,0xeb,0x70,0x15,0x7e,0xb3,0x66,0x4b,0x7a,0xb3,0x72,0x9, 0x7e,0xb3, +0x66,0x4c,0x7a,0xb3,0x72,0xa, 0xe4,0x7a,0xb3,0x72,0xb, 0xbe,0xa0,0x0, 0x28,0x3e, +0xc2,0x0, 0x6c,0x11,0x80,0x21,0x12,0xdd,0xa4,0x7e,0x73,0x72,0x9, 0xa, 0x27,0x1a, +0x39,0x12,0x87,0xb8,0x58,0xf, 0x7e,0x73,0x72,0xa, 0xa, 0x27,0x1a,0x30,0x12,0x87, +0xb8,0x58,0x2, 0xd2,0x0, 0xb, 0x10,0x12,0x86,0xdd,0x38,0xda,0x30,0x0, 0xc, 0x7e, +0xb3,0x72,0xb, 0xbe,0xb0,0xc8,0x50,0xb, 0x4, 0x80,0x4, 0xe4,0x80,0x1, 0xe4,0x7a, +0xb3,0x72,0xb, 0x7e,0x73,0x67,0xd5,0xbe,0x70,0x2, 0x50,0x2, 0x61,0xd8,0x7e,0xb3, +0x69,0x60,0xb4,0x1, 0x2, 0x80,0x2, 0x61,0xd8,0x6d,0xee,0x6c,0x11,0x80,0x18,0x12, +0xdd,0xa4,0x12,0x83,0xdb,0xbd,0xde,0x8, 0xc, 0x7d,0xed,0x7a,0x93,0x67,0xdd,0x7a, +0x3, 0x67,0xde,0x7c,0x81,0xb, 0x10,0x12,0x86,0xdd,0x38,0xe3,0x6c,0x11,0x61,0xd1, +0xbc,0x81,0x78,0x2, 0x61,0xcf,0x74,0x2, 0xac,0xb1,0x9, 0xf5,0x66,0x4b,0x9, 0xe5, +0x66,0x4c,0x7e,0x73,0x67,0xdd,0x7a,0x73,0x5d,0xb, 0x7e,0x63,0x67,0xde,0x7a,0x63, +0x5d,0xc, 0xbc,0x7f,0x28,0x4, 0x7c,0x7f,0x80,0x4, 0x7e,0x73,0x5d,0xb, 0x7a,0x73, +0x5d,0x7, 0x12,0x86,0xd6,0x50,0x4, 0x7c,0x7f,0x80,0x4, 0x7e,0x73,0x5d,0xb, 0x7a, +0x73,0x5d,0x9, 0x7e,0x73,0x5d,0xc, 0xbc,0x7e,0x28,0x4, 0x7c,0x6e,0x80,0x4, 0x7e, +0x63,0x5d,0xc, 0x7a,0x63,0x5d,0x8, 0xbc,0x7e,0x50,0x4, 0x7c,0x7e,0x80,0x4, 0x7e, +0x73,0x5d,0xc, 0x7a,0x73,0x5d,0xa, 0x7e,0x63,0x5d,0x7, 0x1a,0x56,0x7e,0x63,0x5d, +0x9, 0x1a,0x16,0x9d,0x15,0xb, 0x14,0x7c,0x63,0x7a,0x63,0x5d,0xd, 0x7e,0x63,0x5d, +0x8, 0x1a,0x26,0x1a,0x37,0x9d,0x32,0xb, 0x34,0x7a,0x73,0x5d,0xe, 0x12,0x81,0x99, +0x7d,0xf3,0x7e,0x73,0x5d,0xe, 0xbe,0x73,0x5d,0xd, 0x50,0x5c,0x7e,0xb3,0x5d,0x8, +0xbe,0xb0,0x0, 0x8, 0x5, 0x14,0x7a,0xb3,0x5d,0x8, 0x7e,0x73,0x69,0x8f,0xa, 0xc7, +0x1b,0xc4,0x7e,0xb3,0x5d,0xa, 0x1a,0x1b,0xbd,0x1c,0x58,0x5, 0x4, 0x7a,0xb3,0x5d, +0xa, 0x7e,0x93,0x5d,0x9, 0x12,0x81,0x99,0x7d,0xe3,0x80,0x22,0x1b,0x90,0x6d,0xdd, +0x7e,0x3, 0x5d,0xa, 0x80,0xa, 0x12,0x87,0x1e,0x8, 0x3, 0x12,0x83,0xdb,0x1b,0x0, +0x7e,0x73,0x5d,0x8, 0xbc,0x70,0x8, 0xee,0xbd,0xde,0x58,0x2, 0x7d,0xed,0x7e,0x73, +0x5d,0x7, 0xbc,0x79,0x48,0xd6,0x80,0x5a,0x7e,0xb3,0x5d,0x7, 0xbe,0xb0,0x0, 0x8, +0x5, 0x14,0x7a,0xb3,0x5d,0x7, 0x7e,0x73,0x69,0x8e,0xa, 0xc7,0x1b,0xc4,0x7e,0xb3, +0x5d,0x9, 0x1a,0x1b,0xbd,0x1c,0x58,0x5, 0x4, 0x7a,0xb3,0x5d,0x9, 0x7e,0x3, 0x5d, +0xa, 0x12,0x81,0x99,0x7d,0xe3,0x80,0x22,0x1b,0x0, 0x6d,0xdd,0x7e,0x93,0x5d,0x9, +0x80,0xa, 0x12,0x87,0x1e,0x8, 0x3, 0x12,0x83,0xdb,0x1b,0x90,0x7e,0x73,0x5d,0x7, +0xbc,0x79,0x8, 0xee,0xbd,0xde,0x58,0x2, 0x7d,0xed,0x7e,0x73,0x5d,0x8, 0xbc,0x70, +0x48,0xd6,0x7d,0x3f,0x3e,0x34,0x3e,0x34,0x7e,0x24,0x0, 0xa, 0x12,0x22,0x71,0xbd, +0x3e,0x58,0xc, 0x7e,0x73,0x72,0xb, 0xbe,0x70,0x28,0x50,0x3, 0x12,0x87,0xf5,0xb, +0x10,0x12,0x86,0xdd,0x28,0x2, 0x41,0x60,0xda,0x79,0x22,0x7c,0xb9,0x7c,0x70,0x12, +0x81,0x9d,0x7d,0xd3,0x22,0x74,0x2, 0xac,0xbd,0x9, 0xf5,0x66,0x4b,0x9, 0xe5,0x66, +0x4c,0x7c,0xbf,0x7c,0x7e,0x7c,0xa7,0x7c,0x7b,0x90,0x21,0xfa,0xe4,0x93,0xbc,0xb7, +0x78,0x9, 0x7c,0xba,0x12,0xb6,0x2b,0x50,0x2, 0xd3,0x22,0xc3,0x22,0xca,0x79,0x7c, +0x6, 0x7c,0x9b,0x7e,0xf0,0xff,0xc2,0x2, 0xc2,0x3, 0xc2,0x4, 0x7e,0x14,0x2, 0x58, +0x7e,0xb3,0x67,0xfe,0xbe,0xb0,0x1, 0x68,0xd, 0x7e,0xb3,0x69,0x83,0xb4,0x1, 0xc, +0x7e,0xb3,0x69,0x84,0x60,0x6, 0x12,0xc5,0x99,0xc3,0xa1,0x1e,0xbe,0x0, 0xa, 0x28, +0x3, 0xc3,0xa1,0x1e,0x7e,0x60,0x4, 0x74,0x3, 0xac,0xb0,0x19,0x65,0x6e,0xf0,0x7d, +0xf1,0x7c,0x17,0xc2,0x2, 0xc2,0x3, 0x7c,0x89,0x7a,0x91,0x2f,0x80,0x8, 0x12,0x86, +0xe4,0x8, 0xd, 0x7a,0x81,0x2f,0x7c,0xb8,0x14,0x7c,0x8b,0xbe,0xb0,0x0, 0x58,0xee, +0x7c,0x89,0x80,0x7, 0x12,0x86,0xe4,0x8, 0x13,0x7c,0x98,0x7c,0xb8,0x4, 0x7c,0x8b, +0x1a,0x5b,0x7e,0x73,0x69,0x8e,0x1a,0x17,0xbd,0x51,0x48,0xe8,0x75,0x30,0x0, 0x7e, +0xa3,0x69,0x8e,0x7c,0xba,0x14,0xbc,0xb9,0x78,0x8, 0xd2,0x3, 0xa, 0x7a,0x1b,0x74, +0x80,0x8, 0xe5,0x2f,0x70,0x4, 0xd2,0x2, 0x6c,0xff,0x7c,0xe1,0x7c,0x81,0x20,0x3, +0xe, 0x30,0x2, 0x3d,0x80,0x9, 0x12,0x81,0x99,0xbd,0x3f,0x8, 0xc, 0x7c,0x8e,0x7c, +0xbe,0x14,0x7c,0xeb,0xbe,0xb0,0x0, 0x58,0xed,0x7c,0xe1,0x7c,0x91,0x80,0x9, 0x12, +0x81,0x99,0xbd,0x3f,0x8, 0x13,0x7c,0x9e,0x7c,0xbe,0x4, 0x7c,0xeb,0x1a,0x5b,0x7e, +0x73,0x69,0x8d,0x1a,0x17,0xbd,0x51,0x48,0xe6,0xa, 0x18,0xa, 0x59,0x9d,0x51,0xf5, +0x30,0x7e,0x70,0x3, 0xac,0x70,0x9, 0x53,0x6e,0xf0,0xbe,0x51,0x30,0x50,0x2, 0x80, +0xc, 0x9, 0xb3,0x6e,0xef,0x60,0x10,0x20,0x3, 0x3, 0x30,0x2, 0xa, 0x74,0x1, 0x19, +0xb3,0x6e,0xef,0xd2,0x4, 0x80,0x5, 0xe4,0x19,0xb3,0x6e,0xef,0xa2,0x4, 0xda,0x79, +0x22,0xca,0x3b,0x7e,0xe3,0x69,0x8c,0x7e,0xd3,0x69,0x8d,0xc2,0x2, 0x7e,0x34,0x22, +0x23,0x12,0xb5,0xab,0x7e,0x17,0x67,0xdb,0xbd,0x1d,0x58,0x4, 0x7d,0xd1,0xe, 0xd4, +0x6c,0xcc,0xc1,0xc7,0x7e,0x30,0x2, 0xac,0x3c,0x9, 0xb1,0x66,0x4b,0x7a,0xb3,0x5d, +0x7, 0x9, 0x71,0x66,0x4c,0x12,0x87,0xb1,0x7d,0xc3,0xbd,0xdc,0x8, 0x2, 0xc1,0xc5, +0xbe,0xe3,0x5d,0x7, 0x38,0x2, 0xc1,0xc5,0xbe,0xd3,0x5d,0x8, 0x38,0x2, 0xc1,0xc5, +0x7d,0x1c,0xe, 0x14,0x7d,0xec,0xe, 0xe4,0xe, 0xe4,0x2d,0xe1,0x6d,0xff,0x12,0xdd, +0x7f,0x7e,0x73,0x5d,0x8, 0x7a,0x73,0x5d,0xc, 0x80,0x32,0x6c,0x99,0x7e,0xf3,0x5d, +0x7, 0x80,0x1e,0x7c,0xbf,0x12,0x86,0xf8,0xbd,0xe0,0x18,0xe, 0xbd,0xc0,0x48,0xa, +0xb, 0xf4,0xb, 0x90,0x7a,0xf3,0x5d,0xb, 0x80,0x5, 0x12,0x86,0xd6,0x58,0x7, 0x1b, +0xf0,0xbe,0xf0,0x0, 0x58,0xdd,0x4c,0x99,0x68,0x8, 0x12,0x87,0x14,0x12,0x87,0x2, +0x58,0xc9,0x12,0x87,0xe8,0x58,0x40,0x7e,0x73,0x5d,0x8, 0x7a,0x73,0x5d,0xc, 0x80, +0x31,0x12,0x87,0xdb,0x80,0x21,0x7c,0xb8,0x12,0x86,0xf8,0xbd,0xe0,0x18,0xe, 0xbd, +0xc0,0x48,0xa, 0xb, 0xf4,0xb, 0x90,0x7a,0x83,0x5d,0xa, 0x80,0x8, 0x7e,0x73,0x5d, +0xa, 0xbc,0x78,0x28,0x6, 0xb, 0x80,0xbc,0xe8,0x38,0xdb,0x4c,0x99,0x68,0x8, 0x12, +0x87,0x14,0x12,0x87,0x2, 0x58,0xca,0x12,0xdd,0x7f,0xa, 0x5d,0x1b,0x54,0x7e,0x73, +0x5d,0x8, 0xa, 0x17,0xbd,0x15,0x48,0x2, 0xc1,0xa6,0xa, 0x37,0xb, 0x34,0x7a,0x73, +0x5d,0x9, 0x80,0x32,0x6c,0x99,0x7e,0xf3,0x5d,0x7, 0x80,0x1e,0x7c,0xbf,0x12,0x86, +0xee,0xbd,0xe0,0x18,0xe, 0xbd,0xc0,0x48,0xa, 0xb, 0xf4,0xb, 0x90,0x7a,0xf3,0x5d, +0xb, 0x80,0x5, 0x12,0x86,0xd6,0x58,0x7, 0x1b,0xf0,0xbe,0xf0,0x0, 0x58,0xdd,0x4c, +0x99,0x68,0x9, 0x12,0x87,0xa, 0xbe,0xd3,0x5d,0x9, 0x38,0xc8,0x12,0x87,0xe8,0x58, +0x45,0x7e,0x73,0x5d,0x8, 0xa, 0x37,0xb, 0x34,0x7a,0x73,0x5d,0x9, 0x80,0x31,0x12, +0x87,0xdb,0x80,0x21,0x7c,0xb8,0x12,0x86,0xee,0xbd,0xe0,0x18,0xe, 0xbd,0xc0,0x48, +0xa, 0xb, 0xf4,0xb, 0x90,0x7a,0x83,0x5d,0xa, 0x80,0x8, 0x7e,0x73,0x5d,0xa, 0xbc, +0x78,0x28,0x6, 0xb, 0x80,0xbc,0xe8,0x38,0xdb,0x4c,0x99,0x68,0x9, 0x12,0x87,0xa, +0xbe,0xd3,0x5d,0x9, 0x38,0xc9,0x90,0x22,0x22,0xe4,0x93,0xa, 0x1b,0xbd,0x1f,0x38, +0x14,0xd2,0x2, 0x7e,0x73,0x5d,0x7, 0x7a,0x73,0x73,0x42,0x7e,0x73,0x5d,0x8, 0x7a, +0x73,0x73,0x43,0x80,0xc, 0xb, 0xc0,0x7e,0x73,0x67,0xd5,0xbc,0x7c,0x28,0x2, 0xa1, +0x44,0xa2,0x2, 0xda,0x3b,0x22,0x7e,0x73,0x5d,0xb, 0xbc,0x7f,0x22,0x7e,0x73,0x67, +0xd5,0xbc,0x71,0x22,0x7c,0xb8,0x7c,0x71,0x12,0x81,0x9d,0xbd,0x3f,0x22,0x7e,0x73, +0x5d,0x9, 0x12,0x81,0x9d,0x7d,0x3, 0x22,0x7e,0x73,0x5d,0xc, 0x12,0x81,0x9d,0x7d, +0x3, 0x22,0x7e,0x73,0x5d,0xc, 0xbe,0x70,0x0, 0x22,0x7e,0xb3,0x5d,0x9, 0x4, 0x7a, +0xb3,0x5d,0x9, 0x22,0x7e,0xb3,0x5d,0xc, 0x14,0x7a,0xb3,0x5d,0xc, 0x22,0x7c,0xb9, +0x7c,0x70,0x12,0x81,0x9d,0xbd,0x3d,0x22,0xd2,0x0, 0x6c,0x99,0x80,0x31,0x74,0x2, +0xac,0xb9,0x9, 0x5, 0x70,0xa6,0x9, 0x15,0x70,0xa7,0x12,0x87,0xa5,0x49,0x25,0x70, +0x69,0x7d,0xf3,0x9d,0xf2,0xbe,0xf4,0x0, 0x0, 0x8, 0x4, 0x7d,0x1f,0x80,0x4, 0x6d, +0x11,0x9d,0x1f,0xbe,0x17,0x67,0xee,0x28,0x4, 0xc2,0x0, 0x80,0xa, 0xb, 0x90,0x7e, +0x83,0x70,0xa5,0xbc,0x89,0x38,0xc7,0x20,0x0, 0x2d,0x6c,0x99,0x80,0x1d,0x74,0x2, +0xac,0xb9,0x9, 0x5, 0x66,0x4b,0x9, 0x15,0x66,0x4c,0x12,0x87,0xa5,0x59,0x35,0x70, +0x69,0x19,0x5, 0x70,0xa6,0x19,0x15,0x70,0xa7,0xb, 0x90,0x7e,0x73,0x67,0xd5,0xbc, +0x79,0x38,0xdb,0x7a,0x73,0x70,0xa5,0x7e,0xb3,0x67,0xd5,0x70,0x5, 0xe4,0x7a,0xb3, +0x70,0xa5,0xa2,0x0, 0x22,0x7c,0xb0,0x7c,0x71,0x12,0x81,0x9d,0x74,0x2, 0xac,0xb9, +0x22,0x7a,0x73,0x5d,0x8, 0x2, 0x81,0x9d,0x9d,0x32,0x12,0x24,0x5b,0xbe,0x34,0x0, +0x2, 0x22,0x12,0x87,0xce,0x7d,0x13,0x3e,0x14,0x7e,0x1f,0x22,0xe0,0x22,0x7c,0xa7, +0x7e,0x73,0x69,0x8d,0xac,0x7b,0xa, 0x2a,0x2d,0x32,0x22,0x6c,0x99,0x7e,0x83,0x5d, +0x7, 0xa, 0x18,0xb, 0x14,0x7c,0x83,0x22,0xa, 0x5e,0x1b,0x54,0x7e,0x73,0x5d,0x7, +0xa, 0x17,0xbd,0x15,0x22,0xc2,0x6, 0x7c,0xb1,0x2, 0x89,0xc7,0xca,0x79,0x7c,0xeb, +0x6c,0xaa,0x6c,0x11,0x12,0x89,0xac,0x7a,0x37,0x67,0xe3,0x12,0x89,0xac,0x7a,0x37, +0x67,0xe5,0xe4,0x7a,0xb3,0x67,0xe7,0x7a,0xb3,0x67,0xe8,0x7e,0xf4,0x0, 0x1, 0x7e, +0xf0,0xff,0xbe,0xe0,0x1, 0x78,0xa, 0x7e,0xb3,0x72,0x49,0x7a,0xb3,0x5d,0xf, 0x80, +0x8, 0x7e,0x33,0x72,0x4a,0x7a,0x33,0x5d,0xf, 0x6c,0x33,0x90,0x1c,0x49,0xe4,0x93, +0x20,0xe0,0x6, 0x4c,0x33,0x78,0x2, 0x1, 0xe9,0x1e,0xb0,0x1e,0xb0,0x20,0xe0,0x7, +0xbe,0x30,0x1, 0x78,0x2, 0x1, 0xe9,0x90,0x1c,0x4a,0xe4,0x93,0x20,0xe0,0x7, 0xbe, +0x30,0x2, 0x78,0x2, 0x1, 0xe9,0x1e,0xb0,0x1e,0xb0,0x20,0xe0,0x5, 0xbe,0x30,0x3, +0x68,0x77,0x7e,0xb3,0x5d,0xf, 0xb4,0xff,0x6, 0x7e,0x47,0x69,0x75,0x80,0x1d,0xbc, +0xb3,0x7e,0x27,0x69,0x75,0x78,0x6, 0x7e,0x34,0x0, 0x3, 0x80,0x4, 0x7e,0x34,0x0, +0x5, 0xad,0x32,0x7e,0x24,0x0, 0x4, 0x12,0x22,0x71,0x7d,0x43,0xa, 0xe3,0x2e,0xe7, +0x6d,0xfe,0x3e,0xe4,0x7e,0x1f,0x22,0xe0,0x2d,0x3e,0xb, 0x1a,0xe0,0xbd,0x4e,0x18, +0x8, 0xbd,0xef,0x8, 0x4, 0x7c,0xf3,0x7d,0xfe,0x7e,0x37,0x69,0x77,0xbd,0x3e,0x48, +0x8, 0xa, 0x31,0x19,0x33,0x5d,0xb, 0xb, 0x10,0x7e,0x37,0x67,0xe3,0xbd,0x3e,0x58, +0x8, 0x7a,0xe7,0x67,0xe3,0x7a,0x33,0x67,0xe7,0x7e,0x37,0x67,0xe5,0xbd,0x3e,0x8, +0x8, 0x7a,0xe7,0x67,0xe5,0x7a,0x33,0x67,0xe8,0xb, 0x30,0xa5,0xbb,0x4, 0x2, 0x80, +0x2, 0x1, 0x3b,0xbe,0xf0,0x4, 0x50,0x7, 0x7e,0xa0,0x1, 0x7a,0xf3,0x5d,0x7, 0xbe, +0xe0,0x1, 0x78,0x6, 0x7a,0xf3,0x72,0x49,0x80,0x4, 0x7a,0xf3,0x72,0x4a,0xa, 0x2a, +0x7e,0xa3,0x67,0xd5,0xa, 0x3a,0x2d,0x32,0x7c,0x7, 0x90,0x21,0x52,0xe4,0x93,0xbc, +0xb0,0x50,0x2, 0x7c,0xb, 0x7c,0x3a,0x80,0x28,0x12,0x89,0xbc,0x12,0x89,0xa4,0x7e, +0x70,0x2, 0xac,0x73,0x19,0xa3,0x66,0x4b,0x7e,0x73,0x67,0xd5,0xa, 0x37,0xa, 0x53, +0x9d,0x53,0x9, 0xa5,0x5d,0x7, 0x7e,0x70,0x2, 0xac,0x73,0x19,0xa3,0x66,0x4c,0xb, +0x30,0xbc,0x3, 0x38,0xd4,0x7a,0x3, 0x67,0xd5,0xa, 0x21,0x7e,0xa3,0x67,0xd6,0xa, +0x3a,0x2d,0x32,0x7c,0x27,0x90,0x21,0x52,0xe4,0x93,0xbc,0xb2,0x50,0x2, 0x7c,0x2b, +0x7c,0x3a,0x80,0x25,0x12,0x89,0xa4,0x7e,0x10,0x2, 0xac,0x13,0x19,0xa0,0x66,0x87, +0x7e,0x73,0x67,0xd6,0xa, 0x57,0xa, 0x3, 0x9d,0x5, 0x9, 0xa0,0x5d,0xb, 0x7e,0x10, +0x2, 0xac,0x13,0x19,0xa0,0x66,0x88,0xb, 0x30,0xbc,0x23,0x38,0xd7,0x7a,0x23,0x67, +0xd6,0xda,0x79,0x22,0x90,0x21,0xfa,0xe4,0x93,0x7c,0xab,0x22,0x7e,0xf7,0x6d,0xfe, +0x3e,0xf4,0x7e,0x1f,0x22,0xe0,0x2d,0x3f,0xb, 0x1a,0x30,0x22,0xd2,0x6, 0x7c,0xb3, +0x2, 0x89,0xc7,0xc2,0x6, 0x7c,0xbf,0x7c,0x7b,0xc4,0x23,0x54,0x1f,0x7c,0xab,0x12, +0x75,0x19,0x30,0x6, 0xf, 0xa, 0x3a,0x2e,0x34,0x66,0xc3,0x7e,0x39,0xa0,0x4c,0xba, +0x7a,0x39,0xb0,0x22,0x64,0xff,0xa, 0x2a,0x2e,0x24,0x66,0xc3,0x7e,0x29,0x70,0x5c, +0x7b,0x7a,0x29,0x70,0x22,0xca,0x79,0x6c,0xff,0x6c,0xee,0x80,0x30,0x7c,0xbe,0x12, +0x77,0xb6,0x60,0x27,0x7e,0x34,0x0, 0x2, 0xca,0x39,0xac,0x7e,0x2e,0x34,0x66,0x4b, +0x6d,0x22,0x7e,0x30,0x2, 0xac,0x3f,0x2e,0x14,0x66,0x4b,0x6d,0x0, 0x12,0x24,0x14, +0x1b,0xfd,0xd2,0x6, 0x7c,0xbf,0x12,0x89,0xc7,0xb, 0xf0,0xb, 0xe0,0x12,0x8f,0xec, +0x38,0xcb,0x7a,0xf3,0x67,0xd5,0xda,0x79,0x22,0x12,0x8e,0xf6,0x28,0x35,0x7e,0xb3, +0x69,0x60,0x70,0x2f,0x7e,0x37,0x67,0xd7,0xbe,0x34,0x0, 0x26,0x28,0x28,0xe5,0x17, +0xbe,0xb0,0x2, 0x50,0x21,0x5, 0x17,0x6c,0x33,0x80,0x9, 0xc2,0x6, 0x7c,0xb3,0x12, +0x89,0xc7,0xb, 0x30,0x7e,0x23,0x67,0xd5,0xbc,0x23,0x38,0xef,0xe4,0x7a,0xb3,0x67, +0xd5,0x80,0x3, 0x75,0x17,0x0, 0x2, 0x89,0xf5,0xca,0xf8,0xc2,0x0, 0xc2,0x1, 0x12, +0xdd,0xf7,0x68,0x7a,0x7e,0xb3,0x71,0x36,0x70,0x74,0x7e,0xb3,0x67,0xd5,0x70,0x5, +0x12,0x8b,0x8, 0x80,0x69,0x12,0x85,0x21,0x92,0x1, 0x12,0xb6,0x5b,0x92,0x0, 0x30, +0x0, 0x13,0x7e,0x34,0x22,0x27,0x12,0x30,0xa4,0x7a,0x37,0x73,0x44,0x74,0x1, 0x7a, +0xb3,0x73,0x40,0x80,0x14,0x30,0x1, 0x19,0x7e,0x34,0x22,0x27,0x12,0x30,0xa4,0x7a, +0x37,0x73,0x44,0x74,0x1, 0x7a,0xb3,0x73,0x41,0x74,0x1, 0x7a,0xb3,0x73,0x3f,0x80, +0x3, 0x12,0x8b,0x8, 0x7e,0xb3,0x73,0x40,0x60,0x10,0x6c,0xff,0x80,0x5, 0x12,0x89, +0xc3,0xb, 0xf0,0x12,0x8b,0x1, 0x38,0xf6,0x80,0x14,0x7e,0xb3,0x73,0x41,0x60,0xe, +0x6c,0xff,0x80,0x5, 0x12,0x89,0xc3,0xb, 0xf0,0x12,0x8b,0x1, 0x38,0xf6,0xda,0xf8, +0x22,0x7e,0x73,0x67,0xd5,0xbc,0x7f,0x22,0x7e,0x37,0x73,0x44,0xbe,0x34,0x0, 0x0, +0x28,0x7, 0x1b,0x34,0x7a,0x37,0x73,0x44,0x22,0xe4,0x7a,0xb3,0x73,0x40,0x7a,0xb3, +0x73,0x41,0x7a,0xb3,0x73,0x3f,0x22,0xca,0x3b,0x7e,0x73,0x71,0x2a,0xa, 0x37,0x6d, +0x22,0x7a,0x1d,0x2a,0x7e,0x33,0x71,0x2c,0xa, 0xb3,0x6d,0xaa,0x7e,0x33,0x71,0x2b, +0xa, 0x93,0x6d,0x88,0x7e,0x33,0x71,0x2d,0xa, 0x73,0x6d,0x66,0x7e,0x14,0x21,0xde, +0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x40,0x7d,0x14,0x12,0x22,0xb4,0x12,0x8b,0xff,0x7a, +0x1d,0x2a,0x7e,0x34,0x21,0xec,0x12,0x77,0x99,0x7f,0x15,0x7d,0x15,0x12,0x22,0xb4, +0x12,0x8b,0xff,0x7f,0x51,0x7f,0x14,0x7d,0x14,0x12,0x22,0xb4,0x12,0x8b,0xff,0x7f, +0x41,0x7f,0x13,0x7d,0x15,0x12,0x22,0xb4,0x7c,0xf6,0x7c,0xe5,0xa, 0x64,0x12,0xb9, +0x3, 0x50,0x5b,0x7e,0xb3,0x24,0x26,0xb4,0x1, 0x54,0x75,0x2e,0x0, 0x80,0x46,0x7e, +0xa1,0x2e,0x74,0x9, 0xa4,0x49,0x35,0x66,0xc7,0x12,0x8c,0x6, 0x7a,0x35,0x26,0x7e, +0xa1,0x2e,0x74,0x9, 0xa4,0x49,0x35,0x66,0xc9,0x12,0x76,0x5d,0x7a,0x35,0x28,0x7e, +0x15,0x26,0x6d,0x0, 0x7e,0x1d,0x2a,0xbf,0x1, 0x40,0x11,0x7e,0x35,0x28,0x6d,0x22, +0xbf,0x15,0x40,0x8, 0xbf,0x4, 0x38,0x4, 0xbf,0x13,0x28,0x7, 0xc2,0x6, 0xe5,0x2e, +0x12,0x89,0xc7,0x5, 0x2e,0x7e,0x73,0x67,0xd5,0xbe,0x71,0x2e,0x38,0xb1,0xda,0x3b, +0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x10,0x7f,0x17,0x12,0x22,0xb4,0x7f,0x71,0x7c, +0x76,0x7c,0x65,0xa, 0x24,0x22,0x7e,0x14,0x21,0xda,0x12,0x77,0x91,0x12,0x5f,0xe5, +0x7e,0x14,0x21,0xe0,0x12,0xce,0xbe,0x90,0x1c,0x2c,0xe4,0x93,0x70,0x1, 0x22,0x90, +0x21,0xd9,0xe4,0x93,0xb4,0x1, 0x6, 0x7e,0x83,0x69,0x8f,0x80,0x4, 0x7e,0x83,0x69, +0x8e,0x12,0x77,0xa1,0xbe,0x34,0x0, 0x3f,0x38,0x1f,0x7e,0xe4,0x0, 0x3f,0x9d,0xe3, +0x7e,0x34,0x21,0xe4,0x12,0x8c,0xe7,0x12,0x8e,0xaa,0x12,0x8e,0x96,0xbf,0x71,0x40, +0x2, 0x7f,0x71,0x9f,0x17,0x7f,0x71,0x81,0xe4,0x7d,0x54,0x9e,0x54,0x0, 0x3f,0xbd, +0x53,0x38,0x29,0x7d,0xe3,0x9d,0xe5,0x7e,0x34,0x21,0xe6,0x12,0x8c,0xe7,0x12,0x8e, +0xaa,0x90,0x21,0xe3,0xe4,0x93,0xa, 0x3b,0xbf,0x71,0x40,0x4, 0x7f,0x71,0x1b,0x7c, +0xa, 0x2b,0x7d,0x3d,0x9d,0x32,0x6d,0x22,0x2f,0x71,0x80,0x58,0x7d,0x52,0x1b,0x54, +0xbd,0x53,0x40,0x1b,0x7d,0xf5,0x9d,0xf3,0x6d,0xee,0x7e,0x34,0x21,0xe8,0x12,0x8b, +0xf1,0x7f,0x71,0x7d,0x3c,0x1b,0x34,0x6d,0x22,0x9f,0x17,0x7f,0x71,0x80,0x15,0x7d, +0xf3,0x9d,0xf2,0x6d,0xee,0x7e,0x34,0x21,0xea,0x12,0x8b,0xf1,0x7f,0x71,0x7d,0x3c, +0x6d,0x22,0x2f,0x71,0x12,0x8e,0x96,0x6d,0x22,0xbf,0x71,0x50,0x4, 0x7f,0x71,0x80, +0x13,0x90,0x21,0xe3,0xe4,0x93,0xa, 0x2b,0x7d,0x3d,0x9d,0x32,0x6d,0x22,0xbf,0x71, +0x28,0x2, 0x7f,0x71,0x7d,0x3f,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0x22,0xca, +0xf8,0x6c,0xff,0x7e,0xb7,0x28,0xe, 0x7e,0xc7,0x28,0x10,0x7e,0x97,0x27,0xf6,0x7e, +0xd7,0x27,0xf8,0x7e,0xa7,0x28,0xa, 0x7e,0xe7,0x28,0xc, 0xe4,0x7e,0x73,0x28,0x1a, +0x1b,0x70,0x7d,0x2b,0x7d,0x1c,0x12,0x8e,0x42,0x40,0x2, 0xc1,0x3d,0x7e,0x73,0x28, +0x1a,0xbe,0x70,0xa, 0x28,0x13,0xe4,0x7e,0x70,0x9, 0x7e,0x27,0x28,0x12,0x7e,0x17, +0x28,0x14,0x12,0x8e,0x42,0x40,0x2, 0xc1,0x3d,0x7e,0x73,0x28,0x1a,0xbe,0x70,0xf, +0x28,0x13,0xe4,0x7e,0x70,0xe, 0x7e,0x27,0x28,0x16,0x7e,0x17,0x28,0x18,0x12,0x8e, +0x42,0x40,0x2, 0xc1,0x3d,0x7e,0x34,0x22,0x51,0x12,0x8c,0xe7,0xbd,0xfc,0x28,0x50, +0x7e,0x34,0x22,0x4f,0x12,0x8c,0xe7,0xbd,0xfb,0x50,0x45,0x7e,0x34,0x22,0x55,0x12, +0x30,0xa4,0x12,0x8e,0x9e,0x7d,0x8f,0x9d,0x83,0xbe,0x87,0x27,0xf4,0x50,0x31,0x7e, +0x34,0x22,0x53,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x80,0x9d,0xf8,0xbe,0xf7,0x27,0xf4, +0x28,0x1e,0x7e,0x34,0x0, 0x3, 0xad,0x3c,0x7d,0xfb,0x3e,0xf4,0xbd,0xf3,0x38,0x2, +0xc1,0x3d,0xbd,0xa9,0x50,0x5, 0x7e,0xf0,0x20,0xc1,0x3d,0x7e,0xf0,0x21,0xc1,0x3d, +0x7e,0x34,0x22,0x59,0x12,0x8c,0xe7,0xbd,0xfb,0x38,0x2, 0xc1,0x3d,0x7e,0x34,0x22, +0x57,0x12,0x8c,0xe7,0xbd,0xfc,0x50,0x75,0x7e,0xb3,0x27,0xf3,0x70,0x6f,0x7e,0x34, +0x22,0x5d,0x12,0x30,0xa4,0x12,0x8e,0x9e,0x7d,0xaf,0x9d,0xa3,0xbe,0xa7,0x27,0xf4, +0x50,0x5b,0x7e,0x34,0x22,0x5b,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xa0,0x9d,0xfa,0xbe, +0xf7,0x27,0xf4,0x28,0x48,0x7d,0xfb,0x3e,0xf4,0x7e,0x34,0x0, 0x3, 0xad,0x3c,0xbd, +0x3f,0x28,0x3a,0xbd,0xed,0x50,0x5, 0x7e,0xf0,0x22,0x80,0x31,0x7e,0xa3,0x28,0x1a, +0x7e,0x10,0x4, 0xac,0x1a,0x49,0x30,0x24,0x2d,0x49,0x10,0x24,0x2f,0x49,0x20,0x24, +0x1d,0x49,0x0, 0x24,0x1f,0x9d,0x10,0xbe,0x14,0x0, 0x20,0x18,0xd, 0x9d,0x32,0xbe, +0x34,0x0, 0x10,0x48,0x5, 0xbe,0xa0,0x6, 0x50,0x3, 0x7e,0xf0,0x23,0x7c,0xbf,0xda, +0xf8,0x22,0x7d,0x41,0x7d,0x2, 0x7c,0x37,0x7c,0x2b,0x74,0x4, 0xac,0xb2,0x49,0x35, +0x24,0x31,0x49,0xf5,0x24,0x33,0x74,0x4, 0xac,0xb3,0x49,0x25,0x24,0x31,0x49,0x55, +0x24,0x33,0x9d,0x32,0x12,0x24,0x5b,0x7d,0x13,0x7d,0x3f,0x9d,0x35,0x12,0x24,0x5b, +0x9d,0x34,0x12,0x24,0x5b,0x7e,0x54,0x22,0x49,0x7e,0x44,0x0, 0xff,0xb, 0x2a,0x20, +0xbd,0x32,0x50,0x10,0x12,0x8f,0xf3,0x7e,0x14,0x22,0x49,0x12,0x77,0x91,0xbd,0x32, +0x50,0x2, 0xd3,0x22,0xc3,0x22,0x90,0x21,0xe2,0xe4,0x93,0xa, 0x3b,0x22,0x7e,0x14, +0x22,0x6d,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0xf0,0x22,0xad,0xfe,0x6d,0xee,0x7d,0x3f, +0x7d,0x2e,0x7c,0x76,0x7c,0x65,0x7f,0x71,0x22,0xca,0xd8,0xca,0x79,0x7d,0x43,0x7f, +0x70,0x12,0x8e,0xf6,0x28,0x2a,0x6c,0xff,0x80,0x21,0x12,0xc5,0x6a,0x7c,0xbe,0x7c, +0x7d,0x12,0x81,0x9d,0x7d,0xd3,0x7f,0x7, 0x7c,0x7d,0x12,0xb9,0x61,0x50,0x7, 0xbd, +0xd4,0x8, 0x6, 0xd3,0x80,0xb, 0xd3,0x80,0x8, 0xb, 0xf0,0x12,0x8b,0x1, 0x38,0xda, +0xc3,0xda,0x79,0xda,0xd8,0x22,0x7e,0x73,0x67,0xd5,0xbe,0x70,0x0, 0x22,0xe4,0x7a, +0xb3,0x67,0xf6,0x7a,0xb3,0x5d,0x7, 0x7a,0xb3,0x5d,0x8, 0x7e,0x73,0x69,0x8c,0x7a, +0x73,0x5d,0x9, 0x7e,0x73,0x69,0x8d,0x7a,0x73,0x5d,0xa, 0x7e,0x8, 0x5d,0x7, 0x7e, +0x37,0x69,0x6f,0x12,0x8e,0xb9,0xe4,0x33,0x7a,0xb3,0x67,0xf6,0xe4,0x7a,0xb3,0x67, +0xff,0x12,0xb7,0xf5,0x33,0x7a,0xb3,0x67,0xff,0x74,0x1, 0x7a,0xb3,0x68,0x0, 0x12, +0x87,0x28,0xe4,0x33,0x7a,0xb3,0x68,0x0, 0x22,0x12,0x8e,0xfe,0x12,0xb6,0x8f,0x12, +0xb8,0x7, 0x2, 0x8f,0x55,0x7e,0x37,0x6d,0xfe,0x1e,0x34,0x1e,0x34,0xe4,0x7a,0xb3, +0x68,0x1, 0xbe,0x37,0x67,0xd7,0x40,0x6, 0xbe,0x37,0x67,0xd9,0x50,0x6, 0x74,0x1, +0x7a,0xb3,0x68,0x1, 0x22,0x74,0x1, 0x7a,0xb3,0x68,0xa, 0x7e,0xb3,0x67,0xf6,0xb4, +0x1, 0x5, 0xe4,0x7a,0xb3,0x68,0xa, 0x12,0x97,0x65,0x28,0x5, 0xe4,0x7a,0xb3,0x68, +0xa, 0x7e,0xb3,0x24,0x26,0x70,0x5, 0xe4,0x7a,0xb3,0x68,0xa, 0x7e,0xb3,0x73,0x3f, +0xb4,0x1, 0x5, 0xe4,0x7a,0xb3,0x68,0xa, 0x7e,0x34,0x22,0x32,0x12,0x30,0xa4,0xbe, +0x37,0x29,0xef,0x50,0x5, 0xe4,0x7a,0xb3,0x68,0xa, 0x12,0xb8,0x39,0x7e,0xb3,0x71, +0x36,0x70,0xa, 0x12,0x8e,0xf6,0x28,0x5, 0xe4,0x7a,0xb3,0x68,0xa, 0x7e,0xb3,0x71, +0xb, 0xb4,0x1, 0x17,0x7e,0x73,0x73,0x39,0xbe,0x70,0x3c,0x50,0xe, 0xbe,0x70,0x0, +0x28,0x9, 0xe5,0x1b,0x60,0x5, 0xe4,0x7a,0xb3,0x68,0xa, 0x22,0x7e,0x73,0x67,0xd5, +0xbc,0x7e,0x22,0x7d,0x31,0x9d,0x30,0x2, 0x24,0x5b,0x6d,0x22,0x7d,0x32,0x7d,0x52, +0x3e,0x54,0x7e,0xf, 0x22,0xd8,0x12,0x90,0x5b,0x28,0x2, 0xb, 0x34,0xb, 0x24,0xbe, +0x24,0x0, 0x14,0x78,0xe9,0xbe,0x34,0x0, 0x5, 0x38,0x6, 0xe4,0x7a,0xb3,0x72,0x5, +0x22,0x7e,0x24,0x0, 0x14,0x80,0xd, 0x7d,0x52,0x3e,0x54,0x12,0x90,0x5b,0x28,0x2, +0xb, 0x34,0xb, 0x24,0x7e,0x57,0x6d,0xfe,0xbd,0x52,0x38,0xeb,0xbe,0x34,0x0, 0xb4, +0x28,0x7, 0x7e,0xb3,0x72,0x5, 0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x72,0x5, 0x7e,0x73, +0x72,0x5, 0xbe,0x70,0x4, 0x40,0x3, 0x75,0xe9,0xff,0x22,0x2d,0x51,0x7d,0x40,0xb, +0x2a,0x50,0xbe,0x54,0x3e,0x80,0x22,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7a,0x9, 0xb3, +0x66,0x4b,0x9, 0x73,0x66,0x4c,0x2, 0x81,0x9d,0xca,0x3b,0x7c,0xf5,0x7c,0xe6,0x7c, +0xd7,0x7c,0xcb,0x75,0x34,0x0, 0x75,0x35,0x0, 0x75,0x36,0x0, 0x75,0x37,0x0, 0x75, +0x38,0x0, 0x75,0x39,0x0, 0xe4,0x7a,0xb3,0x5d,0x13,0x7e,0x37,0x69,0x81,0x7a,0x37, +0x5d,0x14,0x6c,0xaa,0x12,0x93,0x18,0x19,0xb3,0x66,0xcd,0x7e,0x13,0x69,0x8c,0x7e, +0xb3,0x69,0x8d,0xf5,0x33,0x12,0x94,0x4b,0xf5,0x32,0x12,0x94,0x35,0x7a,0x37,0x5d, +0x14,0x7e,0x37,0x69,0x81,0xbe,0x37,0x5d,0x14,0x8, 0x4, 0x7a,0x37,0x5d,0x14,0xe5, +0x31,0x7c,0x71,0x7c,0x6c,0x7e,0x8, 0x0, 0x36,0x12,0x93,0x2d,0xf5,0x34,0xe5,0x32, +0x7e,0x71,0x33,0x7c,0x6d,0x7e,0x8, 0x0, 0x37,0x12,0x93,0x2d,0xf5,0x35,0xe5,0x36, +0x7e,0x71,0x37,0x12,0x87,0xc2,0x2d,0x31,0x7a,0x37,0x5d,0xf, 0x7e,0x34,0x23,0x34, +0x7a,0x37,0x5d,0x11,0xe5,0x36,0x7a,0xb3,0x5d,0x9, 0xe5,0x37,0x7a,0xb3,0x5d,0xa, +0xe5,0x34,0x7a,0xb3,0x5d,0xb, 0xe5,0x35,0x7a,0xb3,0x5d,0xc, 0x7e,0x73,0x69,0x6c, +0x7a,0x73,0x5d,0xd, 0xe4,0x7a,0xb3,0x5d,0xe, 0x7e,0x8, 0x5d,0x9, 0x12,0x8, 0x73, +0x7e,0x37,0x23,0x34,0x7d,0x23,0x6d,0x33,0x7e,0xb7,0x23,0x36,0x6d,0xaa,0x2f,0x51, +0x7e,0x37,0x23,0x38,0x6d,0x22,0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x23,0x3a,0x2f,0x10, +0x7a,0x1d,0x2b,0x7e,0x37,0x23,0x3c,0x7d,0x23,0x6d,0x33,0x7e,0x97,0x23,0x3e,0x6d, +0x88,0x2f,0x41,0x7f,0x65,0xe5,0x34,0xa, 0x4b,0xe5,0x36,0xa, 0x5b,0x2d,0x54,0xf5, +0x38,0xe5,0x35,0xa, 0x4b,0xe5,0x37,0xa, 0x5b,0x2d,0x54,0xf5,0x39,0x85,0x36,0x2f, +0x41,0x59,0x85,0x37,0x30,0x41,0x4e,0xe5,0x2f,0x7e,0x71,0x30,0x12,0x94,0x41,0x9d, +0x32,0x7a,0x37,0x5d,0x7, 0xbe,0x34,0x0, 0x0, 0x18,0x2, 0x41,0x4c,0x7e,0x37,0x5d, +0x14,0xbe,0x37,0x5d,0x7, 0x18,0x9, 0x7e,0xb3,0x5d,0x13,0x4, 0x7a,0xb3,0x5d,0x13, +0xe5,0x31,0xa, 0x1b,0xe5,0x2f,0x12,0x93,0x22,0x8, 0x4, 0x9d,0x31,0x80,0x4, 0x6d, +0x33,0x9d,0x32,0xbe,0x34,0x0, 0x1, 0x18,0x19,0xe5,0x32,0xa, 0x1b,0xe5,0x30,0x12, +0x93,0x22,0x8, 0x4, 0x9d,0x31,0x80,0x4, 0x6d,0x33,0x9d,0x32,0xbe,0x34,0x0, 0x1, +0x8, 0x6a,0xbe,0xc0,0x3, 0x40,0x9, 0xbe,0xd0,0x3, 0x40,0x4, 0xd2,0x0, 0x80,0x2, +0xc2,0x0, 0xe5,0x2f,0x7e,0x71,0x30,0x7c,0x6e,0x12,0xd7,0xed,0x7c,0x9b,0xbe,0x90, +0x2, 0x68,0x5, 0xbe,0x90,0x3, 0x78,0xa, 0x7e,0x37,0x5d,0x7, 0xe, 0x34,0x7a,0x37, +0x5d,0x7, 0xbe,0x90,0x2, 0x68,0xa, 0xbe,0x90,0x1, 0x68,0x5, 0xbe,0x90,0x3, 0x78, +0x2b,0x7e,0xf7,0x5d,0x7, 0x12,0x92,0xf8,0xe5,0x2f,0x12,0x92,0xff,0x7f,0x1, 0x7e, +0x1d,0x2b,0x9f,0x10,0x7a,0x1d,0x2b,0x12,0x92,0xf8,0xe5,0x30,0x12,0x92,0xff,0x9f, +0x41,0x12,0x92,0xf8,0x9f,0x51,0x1a,0x26,0x1a,0x24,0x9f,0x61,0x5, 0x30,0xe5,0x39, +0xbe,0xb1,0x30,0x28,0x2, 0x21,0x87,0x5, 0x2f,0xe5,0x38,0xbe,0xb1,0x2f,0x28,0x2, +0x21,0x82,0xbe,0x58,0x0, 0x0, 0x78,0x2, 0xb, 0x5c,0xbe,0x68,0x0, 0x0, 0x78,0x2, +0xb, 0x6c,0x74,0x6, 0x7e,0x1d,0x2b,0x2f,0x11,0x14,0x78,0xfb,0x7a,0x1d,0x2b,0x7f, +0x5, 0x12,0x93,0x6, 0x7e,0xd0,0x9, 0xac,0xdf,0x59,0x36,0x66,0xc7,0x74,0x6, 0x2f, +0x44,0x14,0x78,0xfb,0x7f,0x14,0x7f,0x6, 0x12,0x93,0x6, 0x59,0x36,0x66,0xc9,0x7e, +0xb3,0x69,0x80,0x60,0xd, 0x1e,0xd4,0x1e,0xc4,0x50,0x4, 0x4e,0xd4,0x80,0x0, 0x14, +0x78,0xf3,0xbe,0x68,0x0, 0x7f,0x28,0x4, 0x7e,0x68,0x0, 0x7f,0x7d,0x3d,0x7c,0xa7, +0x12,0x93,0x18,0x7e,0xa3,0x5d,0x13,0x12,0x93,0xe, 0x74,0x9, 0xac,0xbf,0x9, 0x75, +0x66,0xcd,0xbe,0x70,0x2d,0x28,0x6, 0x7e,0xa0,0x2d,0x12,0x93,0xe, 0x7e,0xa1,0x31, +0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x66,0xce,0x7e,0xa1,0x32,0x7e,0x70,0x9, 0xac, +0x7f,0x19,0xa3,0x66,0xcf,0xda,0x3b,0x22,0x7d,0x3f,0x1a,0x26,0x1a,0x24,0x22,0xa, +0x1b,0x6d,0x0, 0x2, 0x22,0xa3,0x12,0x22,0xbf,0x2e,0x18,0x0, 0x20,0x22,0x7e,0x70, +0x9, 0xac,0x7f,0x19,0xa3,0x66,0xcd,0x22,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x66, +0xcc,0x22,0xa, 0x3b,0x7d,0x23,0x9d,0x21,0xbe,0x24,0x0, 0x0, 0x22,0xca,0xf8,0x7c, +0xf6,0x7c,0x87,0x7c,0x9b,0xa, 0x2f,0x7d,0x32,0x3e,0x34,0xb, 0x34,0x7c,0xb7,0xbc, +0xf9,0x38,0x14,0xa, 0xf8,0x1b,0xf4,0xa, 0x3f,0x9d,0xf3,0xa, 0x39,0xbd,0x3f,0x18, +0x6, 0x7c,0xab,0xa, 0x39,0x80,0x1d,0xbc,0xf9,0x28,0xd, 0xa, 0x39,0xa, 0x5f,0x2d, +0x53,0xb, 0x54,0x7c,0xab,0xe4,0x80,0x10,0xa, 0x3f,0xa, 0x58,0x2d,0x53,0xa, 0x39, +0x9d,0x53,0x7c,0xab,0x9d,0x32,0x7c,0xb7,0x7a,0xb, 0xb0,0x7c,0xba,0xda,0xf8,0x22, +0xca,0x3b,0x6c,0xff,0x6c,0xee,0x81,0x29,0x12,0x94,0x4b,0xf5,0x32,0x75,0x2a,0x3, +0x75,0x2b,0x3, 0x12,0x94,0x35,0x7d,0xe3,0x7e,0xf7,0x69,0x81,0xbd,0xfe,0x8, 0x2, +0x7d,0xef,0x7e,0x73,0x69,0x8c,0x7a,0x71,0x26,0x7e,0xb3,0x69,0x8d,0xf5,0x27,0xe5, +0x31,0x7e,0x61,0x2a,0x7e,0x8, 0x0, 0x2c,0x12,0x93,0x2d,0xf5,0x28,0xe5,0x32,0x7e, +0x71,0x27,0x7e,0x61,0x2b,0x7e,0x8, 0x0, 0x2d,0x12,0x93,0x2d,0x7c,0xab,0x7a,0xa1, +0x29,0xe5,0x28,0xa, 0x4b,0xe5,0x2c,0xa, 0xfb,0x2d,0xf4,0x7d,0x3f,0x7c,0xb7,0xf5, +0x2e,0xa, 0x4a,0xe5,0x2d,0xa, 0x5b,0x2d,0x54,0xf5,0x2f,0x75,0x30,0x0, 0x7e,0xd1, +0x2c,0x80,0x26,0x7e,0xc1,0x2d,0x80,0x19,0x7c,0xbd,0x7c,0x7c,0x12,0x94,0x41,0x7d, +0xd3,0x9d,0xd2,0xbe,0xd4,0x0, 0x0, 0x8, 0x6, 0xbd,0xed,0x18,0x2, 0x5, 0x30,0xb, +0xc0,0xe5,0x2f,0xbc,0xbc,0x38,0xe1,0xb, 0xd0,0xe5,0x2e,0xbc,0xbd,0x38,0xd4,0xbe, +0xf1,0x30,0x50,0x3, 0x7e,0xf1,0x30,0xb, 0xe0,0x12,0x8f,0xec,0x28,0x2, 0x61,0x88, +0x7c,0xbf,0xda,0x3b,0x22,0x7c,0xbe,0x12,0x90,0x67,0x7e,0x24,0x0, 0x3, 0x2, 0x22, +0x71,0x12,0x81,0x9d,0x7e,0x53,0x69,0x6c,0xa, 0x25,0x22,0x7e,0x70,0x2, 0xac,0x7e, +0x9, 0xb3,0x66,0x4b,0xf5,0x31,0x9, 0xb3,0x66,0x4c,0x22,0x7e,0x37,0x67,0xdb,0xbe, +0x34,0x1, 0x5e,0x58,0xa, 0x12,0x97,0x6d,0x50,0x5, 0x12,0x93,0x80,0x80,0x2, 0x74, +0xff,0x7a,0xb3,0x73,0x59,0x22,0x7e,0xb3,0x69,0x83,0x70,0x6, 0xe4,0x7a,0xb3,0x69, +0x84,0x22,0x7e,0xb3,0x69,0x84,0x70,0x1b,0x12,0x97,0x65,0x28,0x6, 0x7e,0x34,0x0, +0xf, 0x80,0xc, 0x7e,0x37,0x71,0xbc,0xbe,0x34,0x0, 0x5, 0x28,0x6, 0x1b,0x34,0x7a, +0x37,0x71,0xbc,0xe4,0x7a,0xb3,0x67,0xea,0x74,0x1, 0x12,0xc3,0x6, 0x12,0xd9,0xff, +0x74,0x1, 0x12,0x87,0xfc,0x12,0x95,0xab,0x12,0x89,0xf5,0x12,0x94,0x5b,0xc2,0x0, +0x12,0x94,0xd3,0x7e,0xb3,0x24,0x26,0xb4,0x1, 0x8, 0x7e,0x73,0x67,0xd5,0x7a,0x73, +0x67,0xe9,0x22,0xca,0xf8,0xc2,0x4, 0xc2,0x5, 0xc2,0x6, 0x7e,0xb3,0x67,0xd5,0x70, +0x3, 0x12,0x97,0x99,0x7e,0x34,0x2, 0xbc,0x12,0xb9,0xb, 0x7a,0xb3,0x71,0xb9,0x7e, +0x37,0x71,0xbc,0x12,0xb8,0x92,0x92,0x1, 0x7e,0xb3,0x69,0x84,0x70,0x62,0x7e,0xa3, +0x71,0xb9,0xbe,0xa0,0x0, 0x38,0x2, 0xa1,0xa1,0xbe,0xa0,0x4, 0x28,0x2, 0xa1,0xa1, +0xd2,0x2, 0x20,0x2, 0x2, 0xa1,0xa1,0xbe,0xa0,0x4, 0x78,0x5, 0x7e,0xf0,0x2, 0x80, +0x17,0xbe,0xa0,0x3, 0x78,0x5, 0x7e,0xf0,0x3, 0x80,0xd, 0xbe,0xa0,0x2, 0x78,0x5, +0x7e,0xf0,0x5, 0x80,0x3, 0x7e,0xf0,0x8, 0x7c,0xbf,0x12,0xc2,0x52,0x92,0x3, 0x12, +0x95,0xb6,0x92,0x4, 0xd2,0x5, 0x30,0x3, 0x9, 0x30,0x4, 0x6, 0x30,0x5, 0x3, 0x12, +0x95,0xa4,0x30,0x1, 0x4c,0x30,0x4, 0x49,0x30,0x5, 0x46,0x12,0x95,0xa4,0x80,0x41, +0x7e,0x73,0x71,0xb9,0xbe,0x70,0x0, 0x28,0x7, 0x12,0x95,0xa4,0x6d,0x33,0x80,0x11, +0x7e,0xb3,0x67,0xd5,0x70,0x10,0x74,0x1, 0x7a,0xb3,0x69,0x84,0x7e,0x35,0x10,0xb, +0x34,0x7a,0x35,0x10,0x80,0x2, 0xd2,0x6, 0x20,0x6, 0xc, 0x7e,0x35,0x10,0xbe,0x34, +0xe, 0x10,0x50,0x3, 0x30,0x0, 0xa, 0xe4,0x7a,0xb3,0x69,0x84,0x6d,0x33,0x7a,0x35, +0x10,0xda,0xf8,0x22,0x74,0x2, 0x7a,0xb3,0x69,0x84,0x22,0x7e,0xb3,0x73,0x1f,0xb4, +0x1, 0x3, 0x2, 0xc3,0x92,0x22,0xca,0xf8,0xd2,0x7, 0x6c,0xff,0x80,0x13,0x7c,0xbf, +0x7e,0x70,0x1, 0x12,0x95,0xde,0xbe,0x18,0x2, 0xee,0x58,0x3, 0xc3,0x80,0xc, 0xb, +0xf0,0x7e,0x33,0x67,0xd5,0xbc,0x3f,0x38,0xe5,0xa2,0x7, 0xda,0xf8,0x22,0x7c,0x67, +0x7c,0x7b,0x7e,0x50,0x2, 0xac,0x57,0x9, 0xa2,0x66,0x4b,0x9, 0x72,0x66,0x4c,0x12, +0x97,0x75,0x78,0x3, 0x9f,0x11,0x22,0x7c,0xba,0x2, 0x95,0xfc,0x7c,0x16,0x7c,0x7, +0x7c,0x9b,0x7e,0x83,0x69,0x8e,0x7a,0x83,0x5d,0x7, 0x7e,0x83,0x69,0x8f,0x7a,0x83, +0x5d,0x8, 0x9f,0x77,0xa, 0x31,0xa, 0x19,0x9d,0x13,0x7c,0x83,0x80,0x7e,0x7a,0x81, +0x27,0xbe,0x80,0x0, 0x58,0xc, 0x1a,0x58,0x1a,0x19,0x9d,0x15,0xa, 0x59,0x2d,0x51, +0xf5,0x27,0x7e,0x73,0x5d,0x7, 0xbc,0x78,0x18,0xc, 0x1a,0x59,0x1a,0x18,0x9d,0x15, +0xa, 0x59,0x9d,0x51,0xf5,0x27,0xa, 0x11,0xa, 0x50,0x9d,0x51,0xf5,0x26,0x80,0x3c, +0x85,0x26,0x28,0xe5,0x26,0xbe,0xb0,0x0, 0x58,0xe, 0xe5,0x26,0x1a,0x5b,0x1a,0x10, +0x9d,0x15,0xa, 0x50,0x2d,0x51,0xf5,0x28,0x7e,0x73,0x5d,0x8, 0xbe,0x71,0x26,0x18, +0xe, 0x1a,0x30,0xe5,0x26,0x1a,0x1b,0x9d,0x13,0xa, 0x50,0x9d,0x51,0xf5,0x28,0xe5, +0x27,0x7e,0x71,0x28,0x12,0x81,0x9d,0x12,0x97,0x5e,0x5, 0x26,0xa, 0x21,0xa, 0x30, +0x2d,0x32,0xe5,0x26,0x1a,0x1b,0xbd,0x13,0x8, 0xb6,0xb, 0x80,0xa, 0x11,0xa, 0x59, +0x2d,0x51,0x1a,0x18,0xbd,0x15,0x18,0x2, 0xc1,0x1e,0x7f,0x17,0x22,0xca,0x79,0x6c, +0xff,0xc2,0x0, 0x7e,0xb3,0x69,0x84,0x60,0x6, 0x7e,0xd4,0x1, 0xc2,0x80,0x4, 0x7e, +0xd4,0x3, 0xe8,0x7e,0xb3,0x69,0x89,0xb4,0x1, 0x4, 0x7e,0xd4,0x0, 0xf0,0x7e,0xc7, +0x67,0xdb,0x6c,0xee,0x80,0x71,0xc2,0x0, 0x7c,0xbe,0x12,0x90,0x67,0x7d,0xb3,0x74, +0x2, 0xac,0xbe,0x9, 0xb5,0x66,0x4b,0x12,0x97,0x88,0xbd,0x3b,0x58,0x4, 0xd2,0x0, +0x80,0x26,0x7e,0x73,0x69,0x60,0xbe,0x73,0x67,0xd5,0x78,0x1c,0x7e,0xa7,0x73,0x5b, +0xe, 0xa4,0xbd,0xac,0x58,0x12,0x7c,0xbe,0x7e,0x70,0x1, 0x12,0x95,0xde,0x7d,0x1d, +0x6d,0x0, 0xbf,0x10,0x8, 0x2, 0xd2,0x0, 0x30,0x0, 0x2a,0x7c,0xbe,0x12,0x77,0xb6, +0x60,0x23,0x7e,0xa4,0x0, 0x9, 0xca,0xa9,0x7e,0x70,0x9, 0xac,0x7e,0x2e,0x34,0x66, +0xc7,0x6d,0x22,0x7e,0x30,0x9, 0xac,0x3f,0x2e,0x14,0x68,0xb, 0x6d,0x0, 0x12,0x24, +0x14,0x1b,0xfd,0xb, 0xf0,0xb, 0xe0,0x12,0x8f,0xec,0x38,0x8a,0x7a,0x73,0x67,0xea, +0x7a,0xf3,0x69,0x5f,0x7a,0xc7,0x73,0x5b,0xda,0x79,0x22,0x2, 0x96,0xad,0x1a,0x26, +0x1a,0x24,0x2f,0x71,0x22,0x7e,0x73,0x69,0x60,0xbe,0x70,0x0, 0x22,0x7e,0x73,0x67, +0xd5,0xbe,0x70,0x3, 0x22,0x90,0x21,0xfa,0xe4,0x93,0xbc,0xba,0x22,0x7c,0xab,0x12, +0x97,0x75,0x78,0x2, 0xd3,0x22,0xc3,0x22,0x7e,0x37,0x69,0x6d,0x7e,0x53,0x69,0x8e, +0xbc,0x5b,0x38,0x4, 0x7e,0x37,0x69,0x73,0x22,0xe4,0x7a,0xb3,0x71,0xbe,0x7a,0xb3, +0x71,0xbb,0x7e,0x8, 0x71,0xe2,0x7e,0x34,0x0, 0x1f,0x12,0x24,0x39,0x7e,0x8, 0x71, +0xbf,0x7e,0x34,0x0, 0x23,0x2, 0x24,0x39,0xca,0x79,0x6d,0x0, 0x6c,0x44,0x7e,0x14, +0x7f,0xff,0x7e,0xf0,0x2, 0xac,0xf4,0x59,0x17,0x5d,0x7, 0x90,0x1c,0x49,0xe4,0x93, +0x20,0xe0,0x4, 0x4c,0x44,0x68,0x3a,0x1e,0xb0,0x1e,0xb0,0x20,0xe0,0x5, 0xbe,0x40, +0x1, 0x68,0x2e,0x90,0x1c,0x4a,0xe4,0x93,0x20,0xe0,0x5, 0xbe,0x40,0x2, 0x68,0x21, +0x1e,0xb0,0x1e,0xb0,0x20,0xe0,0x5, 0xbe,0x40,0x3, 0x68,0x15,0xa, 0x44,0x2e,0x47, +0x6d,0xfe,0x3e,0x44,0x7e,0x7f,0x22,0xe0,0x2d,0xf4,0xb, 0x7a,0x40,0x59,0x47,0x5d, +0x7, 0xb, 0x40,0xa5,0xbc,0x4, 0xa7,0x7d,0x31,0x6c,0x44,0x7e,0x90,0x2, 0xac,0x94, +0x49,0x14,0x5d,0x7, 0xbe,0x14,0x7f,0xff,0x68,0x8, 0xbd,0x13,0x58,0x2, 0x7d,0x31, +0x2d,0x1, 0xb, 0x40,0xa5,0xbc,0x4, 0xe3,0xbe,0x34,0x0, 0x0, 0x58,0x4, 0x7e,0x34, +0x0, 0x1, 0xbe,0x4, 0x0, 0x0, 0x58,0x4, 0x7e,0x4, 0x0, 0x1, 0x20,0x6, 0x8, 0x7e, +0x50,0x4, 0x7e,0xa0,0x3, 0x80,0x6, 0x7e,0x50,0x3, 0x7e,0xa0,0x2, 0xa, 0xf5,0xad, +0xf3,0xbe,0xf7,0x67,0xe3,0x8, 0xf, 0x7e,0x17,0x67,0xe3,0xbe,0x14,0x3, 0xe8,0x8, +0x5, 0xd2,0x1d,0xc3,0x80,0x12,0x9e,0x7, 0x67,0xe3,0xa, 0x1a,0xad,0x10,0xbe,0x17, +0x67,0xe3,0x8, 0x3, 0xc3,0x80,0x1, 0xd3,0xda,0x79,0x22,0x7f,0x20,0xb, 0x2a,0x10, +0xb, 0x1a,0x0, 0x1b,0x2a,0x0, 0x1b,0x1a,0x10,0x22,0xca,0x3b,0x6c,0xff,0x6c,0xee, +0x7e,0xb3,0x69,0x8e,0xf5,0x2a,0x7e,0xd3,0x69,0x8f,0xe4,0x7a,0xb3,0x73,0x5a,0x7e, +0xb3,0x24,0x26,0xb4,0x1, 0x2, 0x80,0x2, 0x21,0xbf,0x6c,0xcc,0x21,0xad,0x7e,0x70, +0x2, 0xac,0x7c,0x12,0x99,0xc5,0x75,0x26,0x3, 0x75,0x27,0x3, 0xe5,0x28,0x12,0x97, +0x7d,0x50,0xf, 0x75,0x26,0x0, 0x75,0x27,0x0, 0x7c,0xbc,0x7c,0x7e,0x12,0xd8,0x92, +0x21,0xa9,0xe5,0x28,0x7e,0x71,0x29,0x12,0x81,0x9d,0xbe,0x37,0x69,0x6f,0x58,0x2, +0x21,0xab,0x7e,0x73,0x67,0xd5,0xbe,0x70,0x5, 0x28,0x6, 0x75,0x26,0x2, 0x75,0x27, +0x2, 0xe5,0x28,0xbe,0xb0,0x1, 0x68,0x9, 0xe5,0x2a,0x24,0xfe,0xbe,0xb1,0x28,0x78, +0x3, 0x75,0x26,0x2, 0xe5,0x29,0xbe,0xb0,0x1, 0x68,0x9, 0x7c,0xbd,0x24,0xfe,0xbe, +0xb1,0x29,0x78,0x3, 0x75,0x27,0x2, 0xe5,0x28,0x60,0x8, 0xe5,0x2a,0x14,0xbe,0xb1, +0x28,0x78,0x3, 0x75,0x26,0x2, 0xe5,0x29,0x60,0x8, 0x7c,0xbd,0x14,0xbe,0xb1,0x29, +0x78,0x3, 0x75,0x27,0x2, 0xc2,0x0, 0xe5,0x28,0x7e,0x71,0x29,0x7c,0x6c,0x12,0xd7, +0xed,0xbe,0xb0,0xff,0x68,0x6, 0x75,0x26,0x2, 0x75,0x27,0x2, 0x7c,0xbc,0x7e,0x8, +0x0, 0x26,0x7e,0x18,0x0, 0x27,0x12,0xa1,0xc4,0x7e,0xb3,0x69,0x84,0x60,0x6, 0x75, +0x26,0x4, 0x75,0x27,0x4, 0xe5,0x26,0x7e,0x71,0x27,0x7c,0x6c,0x7c,0x5e,0x12,0x90, +0x79,0x7e,0x70,0x9, 0xac,0x7e,0x9, 0x53,0x66,0xcd,0xbc,0x5f,0x28,0x2, 0x7c,0xf5, +0x90,0x21,0xd9,0xe4,0x93,0xb4,0x1, 0x11,0x7d,0x13,0x2e,0x14,0x66,0xc7,0x6d,0x0, +0x2e,0x34,0x66,0xc9,0x6d,0x22,0x12,0x98,0x8b,0xb, 0xe0,0xb, 0xc0,0x7e,0x73,0x67, +0xd5,0xbc,0x7c,0x28,0x2, 0x1, 0xbe,0x7a,0xe3,0x67,0xd5,0x7a,0xf3,0x73,0x5a,0xda, +0x3b,0x22,0x2, 0x98,0x9a,0x9, 0xb3,0x66,0x4b,0xf5,0x28,0x9, 0xb3,0x66,0x4c,0xf5, +0x29,0x22,0xca,0x3b,0x7c,0xfb,0xc2,0x2, 0xc2,0x3, 0xc2,0x4, 0x7e,0x94,0x0, 0x51, +0x7e,0xe3,0x67,0xd5,0xe4,0x7a,0xb3,0x70,0x29,0x7a,0xb3,0x70,0x2a,0x7a,0xb3,0x6f, +0xeb,0x7e,0x8, 0x70,0x2b,0x12,0x9c,0xe6,0xe4,0x12,0x24,0x39,0x12,0x9c,0xe6,0x3e, +0x34,0x7e,0x8, 0x6f,0xec,0xe4,0x12,0x24,0x39,0xbe,0xe0,0x2, 0x50,0x2, 0x81,0xcf, +0x6c,0xdd,0x81,0xc9,0x74,0x2, 0x7c,0x7d,0xac,0x7b,0x12,0x99,0xc5,0x90,0x21,0xfa, +0xe4,0x93,0xbe,0xb1,0x28,0x78,0x2, 0x81,0xc7,0x4c,0xdd,0x68,0x8, 0xa, 0x8d,0x9, +0xb8,0x70,0x2b,0x70,0xa, 0xa, 0x3d,0xb, 0x34,0xa, 0x8d,0x19,0x78,0x70,0x2b,0xa, +0x5d,0xb, 0x54,0xf5,0x26,0x81,0xc0,0x7e,0xa1,0x26,0x74,0x2, 0x7c,0x7a,0xac,0x7b, +0x9, 0xb3,0x66,0x4b,0xf5,0x2a,0x9, 0xb3,0x66,0x4c,0xf5,0x2b,0x90,0x21,0xfa,0xe4, +0x93,0xbe,0xb1,0x2a,0x78,0x2, 0x81,0xbe,0xe5,0x2a,0xa, 0x2b,0xe5,0x28,0xa, 0xb, +0x7d,0x30,0x9d,0x32,0xbe,0x34,0x0, 0x0, 0x8, 0x6, 0x7d,0x50,0x9d,0x52,0x80,0x4, +0x6d,0x55,0x9d,0x53,0xf5,0x2c,0xe5,0x2b,0xa, 0x2b,0xe5,0x29,0xa, 0xb, 0x7d,0x30, +0x9d,0x32,0xbe,0x34,0x0, 0x0, 0x8, 0x6, 0x7d,0x80,0x9d,0x82,0x80,0x4, 0x6d,0x88, +0x9d,0x83,0x7d,0x38,0x7c,0xc7,0xe5,0x2c,0xbe,0xb0,0x6, 0x40,0x2, 0x81,0xbe,0xbe, +0xc0,0x6, 0x40,0x2, 0x81,0xbe,0xe5,0x28,0x7e,0x71,0x29,0x12,0x81,0x9d,0x7a,0x37, +0x5d,0x7, 0xe5,0x2a,0x7e,0x71,0x2b,0x12,0x81,0x9d,0x7d,0x83,0x7e,0x27,0x5d,0x7, +0xbd,0x28,0x8, 0x4, 0x7d,0x38,0x80,0x4, 0x7e,0x37,0x5d,0x7, 0x7a,0x37,0x5d,0x9, +0xbd,0x28,0x58,0x4, 0x7d,0x38,0x80,0x4, 0x7e,0x37,0x5d,0x7, 0x7a,0x37,0x5d,0xb, +0x75,0x2d,0x0, 0xe5,0x2c,0xbe,0xb0,0x1, 0x38,0x21,0xbe,0xc0,0x1, 0x38,0x1c,0x7c, +0xbf,0x30,0xe0,0x17,0x7e,0xb3,0x6f,0xeb,0x4, 0x7a,0xb3,0x6f,0xeb,0x75,0x2d,0x1, +0x7e,0xb3,0x70,0x29,0x4, 0x7a,0xb3,0x70,0x29,0x81,0x62,0xe5,0x2c,0xbe,0xb0,0x1, +0x38,0x7, 0xbe,0xc0,0x1, 0x38,0x2, 0x81,0x62,0xe5,0x2c,0xbe,0xb0,0x6, 0x40,0x2, +0x81,0x62,0xbe,0xc0,0x6, 0x40,0x2, 0x81,0x62,0x7c,0xbf,0x20,0xe1,0x2, 0x81,0x62, +0xc2,0x3, 0xe5,0x2c,0xbe,0xb0,0x2, 0x28,0x5, 0xbe,0xc0,0x2, 0x38,0x2, 0xd2,0x3, +0x12,0x9c,0xed,0x12,0xc7,0x90,0x12,0x6f,0x7f,0x7a,0xd, 0x30,0x7d,0x38,0x2e,0x37, +0x5d,0x7, 0x12,0x9e,0xe3,0x7a,0x35,0x2e,0xc2,0x2, 0xbe,0x8, 0x7f,0xff,0x78,0x5, +0x9f,0x11,0x7a,0x1d,0x30,0x7e,0x35,0x2e,0x7a,0x35,0x39,0x12,0x9c,0xed,0x7e,0xd, +0x30,0x12,0x9d,0xc8,0x92,0x4, 0x12,0xca,0xfa,0x92,0x1, 0x7e,0x37,0x5d,0xb, 0x12, +0x9c,0xd6,0x20,0x1, 0x1a,0xe5,0x2c,0xbe,0xb0,0x4, 0x38,0x13,0xbe,0xc0,0x4, 0x38, +0xe, 0xa, 0x2c,0xe5,0x2c,0xa, 0x3b,0x12,0x9c,0xdf,0x18,0x3, 0x12,0x9c,0xd2,0x85, +0x29,0x39,0x85,0x2a,0x3a,0x85,0x2b,0x3b,0x7e,0x8, 0x0, 0x34,0x7e,0x18,0x0, 0x36, +0xe5,0x28,0x12,0xc6,0x92,0xe5,0x2c,0xa, 0x4b,0xbe,0x45,0x36,0x8, 0x7, 0xa, 0x3c, +0xbe,0x35,0x36,0x18,0xc, 0xa, 0x2c,0x7d,0x34,0x12,0x9c,0xdf,0x18,0x3, 0x7e,0x95, +0x34,0x7e,0x5, 0x36,0xbe,0x4, 0x0, 0x3, 0x78,0x6, 0x7e,0x37,0x5d,0xb, 0x80,0x15, +0xbe,0x4, 0x0, 0x4, 0x78,0x5, 0x7e,0x35,0x2e,0x80,0xa, 0xbe,0x4, 0x0, 0x5, 0x78, +0x7, 0x7e,0x37,0x5d,0x9, 0x12,0x9c,0xd6,0x7e,0xb3,0x71,0x36,0xb4,0x1, 0x4, 0x7e, +0x94,0x0, 0x3c,0x7e,0xb3,0x69,0x84,0x60,0x1c,0x12,0x9c,0xd2,0xe5,0x2c,0xbe,0xb0, +0x2, 0x38,0x12,0xbe,0xc0,0x2, 0x38,0xd, 0xa, 0x2c,0x7d,0x34,0x12,0x9c,0xdf,0x18, +0x4, 0x7e,0x94,0x0, 0x32,0x7d,0x19,0x1a,0x2, 0x1a,0x0, 0x7e,0x1f,0x5d,0xd, 0x12, +0x22,0xa3,0x7e,0x8, 0x0, 0x64,0x12,0x23,0x10,0x7f,0x1, 0x7e,0x1d,0x30,0xbf,0x10, +0x8, 0x2, 0xd2,0x2, 0x30,0x4, 0x5, 0x20,0x3, 0x2, 0xc2,0x2, 0x30,0x2, 0x3, 0x75, +0x2d,0x2, 0xe5,0x2d,0xbe,0xb0,0x0, 0x28,0x55,0xe5,0x26,0xa, 0x4b,0x9, 0x14,0x70, +0x2b,0xa5,0xb9,0x0, 0xc, 0xa, 0x3d,0x9, 0xa3,0x70,0x2b,0x19,0xa4,0x70,0x2b,0x80, +0x3d,0xa, 0x3d,0x9, 0x53,0x70,0x2b,0x7a,0x51,0x38,0xbc,0x51,0x28,0x3, 0x7a,0x11, +0x38,0x75,0x27,0x0, 0x80,0x23,0x9, 0x64,0x70,0x2b,0xe5,0x27,0xa, 0xb, 0x9, 0x30, +0x70,0x2b,0xbc,0x36,0x68,0xa, 0xa, 0x3d,0x9, 0x63,0x70,0x2b,0xbc,0x36,0x78,0x7, +0x7e,0xa1,0x38,0x19,0xa0,0x70,0x2b,0x5, 0x27,0xbe,0xe1,0x27,0x38,0xd8,0x5, 0x26, +0xbe,0xe1,0x26,0x28,0x2, 0x41,0x47,0xb, 0xd0,0xbc,0xed,0x28,0x2, 0x41,0x14,0xda, +0x3b,0x22,0x7e,0x37,0x5d,0x9, 0x1a,0x26,0x1a,0x24,0x7a,0x1f,0x5d,0xd, 0x22,0x2d, +0x32,0xbe,0x34,0x0, 0x6, 0x22,0x90,0x21,0x52,0x93,0xa, 0x3b,0x22,0xe5,0x28,0x7e, +0x71,0x29,0x7e,0x61,0x2a,0x7e,0x51,0x2b,0x22,0xca,0xd8,0xca,0x79,0xc2,0x0, 0x7e, +0xe0,0x3, 0xe4,0x7a,0xb3,0x70,0x28,0x7e,0xd3,0x69,0x60,0x12,0xc9,0xbe,0x7e,0xf3, +0x67,0xd5,0xbe,0xf0,0x1, 0x38,0x2, 0xa1,0xbd,0x7c,0xbe,0x12,0x99,0xd2,0x4c,0xdd, +0x78,0x4, 0xc2,0x0, 0x80,0x5d,0xbe,0xd0,0x1, 0x28,0xb, 0xe5,0x12,0xbe,0xb0,0x6, +0x28,0x4, 0xc2,0x0, 0x80,0x4d,0xc2,0x0, 0x7e,0x53,0x67,0xd5,0xbc,0x5d,0x78,0x11, +0x12,0xc6,0xe7,0x50,0x5, 0x7e,0xe0,0x3, 0x80,0x3, 0x7e,0xe0,0x1, 0xd2,0x0, 0x80, +0x32,0x7e,0x43,0x70,0x29,0xa, 0x34,0xa, 0x25,0x7d,0x12,0x9d,0x13,0xb, 0x14,0xa, +0x3d,0xbd,0x31,0x78,0x7, 0x7e,0xe0,0x1, 0xd2,0x0, 0x80,0x17,0x7e,0x73,0x6f,0xeb, +0xa, 0x37,0x9d,0x23,0xb, 0x24,0xe5,0x13,0xa, 0x3b,0xbd,0x32,0x78,0x5, 0x7e,0xe0, +0x41,0xd2,0x0, 0x30,0x0, 0x5, 0x7c,0xbe,0x12,0x99,0xd2,0x7e,0x8, 0x70,0x2b,0x12, +0xc5,0xc6,0x7a,0xb3,0x70,0x28,0x7e,0xa3,0x70,0x28,0x7a,0xa3,0x67,0xd5,0x74,0x2, +0xa4,0xca,0x59,0x7e,0x18,0x6f,0xec,0x7e,0x8, 0x66,0x4b,0x12,0x24,0x14,0x1b,0xfd, +0x7e,0xb3,0x67,0xd5,0xf5,0x13,0x12,0xc7,0x7, 0xf5,0x12,0x80,0x6, 0x75,0x12,0x64, +0x7a,0xf1,0x13,0xda,0x79,0xda,0xd8,0x22,0xca,0x79,0x7f,0x60,0x7c,0xf5,0x7c,0xe6, +0x12,0x9e,0x2f,0x7d,0xb3,0x7c,0xbe,0x7c,0x7f,0x12,0x9e,0x2f,0x2d,0x3b,0x12,0x9e, +0xe3,0x7d,0xa3,0x7e,0x25,0x39,0x7d,0x12,0x9d,0x1a,0xbe,0x14,0x0, 0x0, 0x8, 0x6, +0x7d,0x32,0x9d,0x3a,0x80,0x4, 0x6d,0x33,0x9d,0x31,0x7d,0x12,0x1a,0x2, 0x1a,0x0, +0x9f,0x6, 0xbe,0x14,0x0, 0x0, 0x8, 0x6, 0x7d,0xd, 0x9d,0x20,0x80,0x4, 0x6d,0x22, +0x9d,0x21,0x7e,0x14,0x0, 0x3, 0xad,0x13,0xbd,0x12,0x58,0xf, 0xbe,0x24,0x0, 0x64, +0x8, 0x9, 0xbe,0x34,0x0, 0x46,0x8, 0x3, 0xd3,0x80,0x1, 0xc3,0xda,0x79,0x22,0xca, +0x79,0x7e,0x63,0x69,0x8e,0x7a,0x63,0x5d,0x11,0x7e,0x93,0x69,0x8f,0x7e,0x4, 0x80, +0x1, 0x7c,0x8b,0x7c,0xf7,0x1a,0x18,0x1b,0x14,0x7c,0xe3,0xc1,0xd2,0x7a,0xe1,0x3c, +0xbe,0xe0,0x0, 0x58,0xc, 0x1a,0x5e,0x1a,0x18,0x9d,0x15,0x1a,0x58,0x2d,0x51,0xf5, +0x3c,0x7e,0x73,0x5d,0x11,0xbc,0x7e,0x18,0xc, 0x1a,0x58,0x1a,0x1e,0x9d,0x15,0x1a, +0x58,0x9d,0x51,0xf5,0x3c,0x1a,0x5f,0x1b,0x54,0xf5,0x3b,0x80,0x47,0x85,0x3b,0x3d, +0xe5,0x3b,0xbe,0xb0,0x0, 0x58,0xe, 0xe5,0x3b,0x1a,0x5b,0x1a,0x1f,0x9d,0x15,0x1a, +0x5f,0x2d,0x51,0xf5,0x3d,0xbe,0x91,0x3b,0x18,0xe, 0x1a,0x3f,0xe5,0x3b,0x1a,0x1b, +0x9d,0x13,0x1a,0x5f,0x9d,0x51,0xf5,0x3d,0xbe,0x81,0x3c,0x78,0x5, 0xbe,0xf1,0x3d, +0x68,0x10,0xe5,0x3c,0x7e,0x71,0x3d,0x12,0x81,0x9d,0x7d,0xf3,0xbd,0xf0,0x8, 0x2, +0x7d,0xf, 0x5, 0x3b,0x1a,0xef,0xb, 0xe4,0xe5,0x3b,0x1a,0x1b,0xbd,0x1e,0x8, 0xad, +0xb, 0xe0,0x1a,0x58,0xb, 0x54,0x1a,0x1e,0xbd,0x15,0x18,0x2, 0xc1,0x4d,0x7d,0x30, +0xda,0x79,0x22,0x7e,0x24,0x0, 0x2, 0x2, 0x22,0x71,0x7e,0x47,0x67,0xdf,0x7e,0x7, +0x69,0x71,0x7e,0x34,0x0, 0x6, 0xad,0x30,0x7e,0x14,0x0, 0x4, 0x12,0x9f,0xac,0x8, +0x5, 0x7e,0xa0,0x4, 0x80,0x21,0x7d,0x30,0x3e,0x34,0x3e,0x34,0x12,0x9f,0xac,0x8, +0x5, 0x7e,0xa0,0x3, 0x80,0x11,0x7d,0x30,0x3e,0x34,0x12,0x9f,0xac,0x8, 0x5, 0x7e, +0xa0,0x2, 0x80,0x3, 0x7e,0xa0,0x1, 0x7e,0xb3,0x68,0x1, 0x60,0x3, 0x7e,0xa0,0x4, +0x12,0xbf,0xcb,0x60,0x3, 0x7e,0xa0,0x1, 0xa, 0x2a,0x7e,0x14,0x22,0x9, 0x7e,0x4, +0x0, 0xff,0xb, 0xa, 0x30,0xad,0x32,0x12,0x5f,0xc5,0x7a,0xb3,0x67,0xf4,0x7e,0xb3, +0x67,0xd5,0xbe,0xb0,0x0, 0x28,0x28,0x7e,0xb3,0x67,0xf6,0x70,0x22,0x7e,0x37,0x67, +0xf2,0xbe,0x34,0x0, 0x2, 0x48,0x9, 0x12,0x9e,0xe3,0x7a,0x37,0x67,0xf2,0x80,0xf, +0x7e,0x63,0x67,0xf4,0x7e,0x70,0x2, 0xac,0x67,0x7c,0xb7,0x7a,0xb3,0x67,0xf4,0x7e, +0xb3,0x71,0xb, 0xb4,0x1, 0xe, 0x7e,0x27,0x67,0xf2,0x7e,0x34,0x0, 0x5, 0xad,0x32, +0x7a,0x37,0x67,0xf2,0x7e,0xb3,0x71,0xb9,0xbe,0xb0,0x0, 0x28,0xe, 0x7e,0x34,0x0, +0x1, 0x7a,0x37,0x67,0xf2,0x74,0x1, 0x7a,0xb3,0x67,0xf4,0x22,0x7d,0x21,0x12,0x22, +0x71,0xbd,0x34,0x22,0x12,0x8f,0x75,0x12,0xa0,0xe9,0x12,0x9e,0xea,0x2, 0x9f,0xc0, +0x7e,0xb3,0x68,0x4, 0xb4,0x1, 0x18,0x12,0xa1,0xba,0xbe,0x73,0x29,0xf6,0x28,0xc, +0xe4,0x7a,0xb3,0x68,0x4, 0x7e,0xb3,0x29,0xf6,0x4, 0x80,0x4, 0xe4,0x80,0x1, 0xe4, +0x7a,0xb3,0x29,0xf6,0x7e,0xb3,0x68,0x4, 0x70,0x53,0x12,0xa0,0xe2,0x78,0x15,0x7e, +0xb3,0x68,0x5, 0xb4,0x1, 0x7, 0x7e,0xb3,0x29,0xf8,0x4, 0x80,0x1, 0xe4,0x7a,0xb3, +0x29,0xf8,0x80,0x18,0xbe,0xa0,0x1, 0x78,0x13,0x7e,0xb3,0x68,0x6, 0xb4,0x1, 0x7, +0x7e,0xb3,0x29,0xf9,0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x29,0xf9,0x7e,0x73,0x29,0xf8, +0xbe,0x70,0x3, 0x50,0x9, 0x7e,0x73,0x29,0xf9,0xbe,0x70,0x3, 0x40,0xf, 0x74,0x1, +0x7a,0xb3,0x68,0x4, 0xe4,0x7a,0xb3,0x29,0xf8,0x7a,0xb3,0x29,0xf9,0x7e,0xb3,0x68, +0x7, 0xb4,0x1, 0x18,0x12,0xa1,0xba,0xbe,0x73,0x29,0xf7,0x28,0xc, 0xe4,0x7a,0xb3, +0x68,0x7, 0x7e,0xb3,0x29,0xf7,0x4, 0x80,0x4, 0xe4,0x80,0x1, 0xe4,0x7a,0xb3,0x29, +0xf7,0x7e,0xb3,0x68,0x7, 0x70,0x53,0x12,0xa0,0xe2,0x78,0x15,0x7e,0xb3,0x68,0x8, +0xb4,0x1, 0x7, 0x7e,0xb3,0x29,0xfa,0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x29,0xfa,0x80, +0x18,0xbe,0xa0,0x1, 0x78,0x13,0x7e,0xb3,0x68,0x9, 0xb4,0x1, 0x7, 0x7e,0xb3,0x29, +0xfc,0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x29,0xfc,0x7e,0x73,0x29,0xfa,0xbe,0x70,0x3, +0x50,0x9, 0x7e,0x73,0x29,0xfc,0xbe,0x70,0x3, 0x40,0xf, 0x74,0x1, 0x7a,0xb3,0x68, +0x7, 0xe4,0x7a,0xb3,0x29,0xfa,0x7a,0xb3,0x29,0xfc,0x7e,0xb3,0x68,0xa, 0xb4,0x1, +0x1a,0x7e,0x73,0x67,0xf4,0xbe,0x73,0x29,0xfd,0x28,0xc, 0xe4,0x7a,0xb3,0x68,0xa, +0x7e,0xb3,0x29,0xfd,0x4, 0x80,0x6, 0x74,0x1, 0x80,0x2, 0x74,0x1, 0x7a,0xb3,0x29, +0xfd,0x22,0x7e,0xa3,0x24,0x27,0x4c,0xaa,0x22,0xd2,0x0, 0xe4,0x7a,0xb3,0x68,0x4, +0x7a,0xb3,0x68,0x7, 0x7e,0xb3,0x67,0xf7,0xb4,0x1, 0x6, 0x74,0x1, 0x7a,0xb3,0x68, +0x4, 0x12,0xa0,0xe2,0x78,0x14,0xe4,0x7a,0xb3,0x68,0x5, 0x7e,0xb3,0x67,0xf8,0xb4, +0x1, 0x1f,0x74,0x1, 0x7a,0xb3,0x68,0x5, 0x80,0x17,0xbe,0xa0,0x1, 0x78,0x12,0xe4, +0x7a,0xb3,0x68,0x6, 0x7e,0xb3,0x67,0xf9,0xb4,0x1, 0x6, 0x74,0x1, 0x7a,0xb3,0x68, +0x6, 0x7e,0xb3,0x67,0xfa,0xb4,0x1, 0x6, 0x74,0x1, 0x7a,0xb3,0x68,0x7, 0x4c,0xaa, +0x78,0x14,0xe4,0x7a,0xb3,0x68,0x8, 0x7e,0xb3,0x67,0xfb,0xb4,0x1, 0x1f,0x74,0x1, +0x7a,0xb3,0x68,0x8, 0x80,0x17,0xbe,0xa0,0x1, 0x78,0x12,0xe4,0x7a,0xb3,0x68,0x9, +0x7e,0xb3,0x67,0xfc,0xb4,0x1, 0x6, 0x74,0x1, 0x7a,0xb3,0x68,0x9, 0x7e,0xb3,0x68, +0x0, 0x70,0x3, 0x12,0xa1,0xae,0x7e,0xb3,0x24,0x26,0x70,0x3, 0x12,0xa1,0xae,0x7e, +0xb3,0x68,0x2, 0xb4,0x1, 0x3, 0x12,0xa1,0xae,0x7e,0x34,0x22,0x32,0x12,0x30,0xa4, +0xbe,0x37,0x29,0xef,0x50,0x3, 0x12,0xa1,0xae,0x20,0x0, 0x11,0xe4,0x7a,0xb3,0x68, +0x5, 0x7a,0xb3,0x68,0x6, 0x7a,0xb3,0x68,0x8, 0x7a,0xb3,0x68,0x9, 0x22,0xe4,0x7a, +0xb3,0x68,0x4, 0x7a,0xb3,0x68,0x7, 0xc2,0x0, 0x22,0xe4,0x7a,0xb3,0x68,0xa, 0x7e, +0x73,0x67,0xf5,0x22,0x7c,0xab,0x7e,0xb3,0x67,0xeb,0x7e,0x93,0x67,0xd5,0x60,0x4a, +0xb4,0x1, 0x5, 0xbe,0x90,0x2, 0x68,0x42,0x74,0x9, 0xa4,0x9, 0xa5,0x66,0xcd,0xbe, +0x90,0x1, 0x78,0x24,0xbe,0xa0,0x19,0x28,0x7, 0x74,0x6, 0x7a,0xb, 0xb0,0x80,0x27, +0xbe,0xa0,0x14,0x28,0x7, 0x74,0x5, 0x7a,0xb, 0xb0,0x80,0x1b,0xbe,0xa0,0xa, 0x28, +0x19,0x74,0x4, 0x7a,0xb, 0xb0,0x80,0xf, 0xbe,0x90,0x2, 0x78,0xd, 0xbe,0xa0,0x14, +0x28,0x8, 0x74,0x4, 0x7a,0xb, 0xb0,0x7a,0x1b,0xb0,0x22,0xca,0x3b,0x7e,0x8, 0x5d, +0x2d,0x7e,0x34,0x0, 0xa, 0xe4,0x12,0x24,0x39,0x7e,0x18,0x69,0x19,0x7a,0x1d,0x26, +0x6c,0xdd,0x80,0x1f,0x7e,0x70,0xff,0x7e,0x50,0x9, 0xac,0x5d,0x19,0x72,0x68,0xf, +0x74,0xff,0xa, 0x4d,0x19,0xb4,0x5d,0x1b,0xe4,0x19,0xb4,0x5d,0x7, 0x19,0xb4,0x5d, +0x11,0xb, 0xd0,0x12,0xa5,0xaf,0x38,0xdc,0x7e,0x73,0x69,0x5f,0xa5,0xbf,0x0, 0x35, +0x7e,0xb3,0x72,0xce,0x70,0x2, 0xa1,0x5e,0x6c,0xdd,0x80,0x22,0x7e,0x44,0x7f,0xff, +0x7e,0x50,0x7, 0xac,0x5d,0x7e,0xd, 0x26,0x2d,0x12,0x79,0x40,0x0, 0x2, 0x7e,0x50, +0x7, 0xac,0x5d,0x7e,0xd, 0x26,0x2d,0x12,0x79,0x40,0x0, 0x4, 0xb, 0xd0,0x12,0xa5, +0xaf,0x38,0xd9,0xa1,0x5e,0x7e,0xb3,0x72,0xce,0x70,0x45,0xbe,0x70,0x0, 0x28,0x40, +0x6c,0xdd,0x80,0x32,0x7e,0x70,0x9, 0xac,0x7d,0x49,0x43,0x68,0xb, 0x7e,0x30,0x7, +0xac,0x3d,0x7e,0x1d,0x26,0x2d,0x31,0x79,0x41,0x0, 0x2, 0x12,0xa5,0xe7,0xac,0x3d, +0x12,0xa5,0xd1,0x74,0x1, 0xa, 0x4d,0x19,0xb4,0x5d,0x7, 0x7e,0x70,0x9, 0xac,0x7d, +0x19,0xd3,0x68,0xf, 0xb, 0xd0,0x7e,0xb3,0x69,0x5f,0xbc,0xbd,0x38,0xc6,0xa1,0x5e, +0x6c,0xdd,0x80,0x1d,0x7e,0x44,0x7f,0xff,0x7e,0x70,0x2, 0xac,0x7d,0x3e,0x34,0x59, +0x43,0x22,0xe4,0x59,0x43,0x22,0xe6,0x59,0x43,0x23,0xc, 0x59,0x43,0x23,0xe, 0xb, +0xd0,0x12,0xa5,0xaf,0x38,0xde,0x7e,0xb3,0x72,0xce,0xbe,0xb3,0x69,0x5f,0x28,0xa, +0xbe,0xb0,0x2, 0x40,0x5, 0x7e,0xa0,0x1, 0x80,0x2, 0x6c,0xaa,0x6c,0xdd,0x61,0xe0, +0x6c,0xff,0x61,0xd7,0x7e,0x70,0x7, 0xac,0x7f,0x7e,0x7d,0x26,0x2d,0xf3,0x69,0x17, +0x0, 0x2, 0xbe,0x14,0x7f,0xff,0x78,0x2, 0x61,0xd5,0xa, 0x2f,0x9, 0xb2,0x5d,0x11, +0x60,0x2, 0x61,0xd5,0xbe,0xa0,0x1, 0x78,0x6f,0x7e,0x70,0x2, 0xac,0x7f,0x49,0x3, +0x72,0xe3,0xbe,0x4, 0x7f,0xff,0x68,0x60,0x49,0x3, 0x72,0xe3,0x69,0x37,0x0, 0x2, +0x7d,0x43,0x9d,0x40,0x2d,0x43,0x7e,0x70,0x2, 0xac,0x7f,0x49,0xd3,0x72,0xcf,0x69, +0x7, 0x0, 0x4, 0x7d,0x30,0x9d,0x3d,0x2d,0x30,0xbe,0x44,0x0, 0x0, 0x58,0x2, 0x6d, +0x44,0xbe,0x34,0x0, 0x0, 0x58,0x2, 0x6d,0x33,0x7e,0x3, 0x69,0x8e,0x12,0xa5,0xdb, +0xbd,0xd4,0x18,0x6, 0x7d,0x40,0x9e,0x44,0x0, 0x21,0x7e,0x3, 0x69,0x8f,0x12,0xa5, +0xdb,0xbd,0xd3,0x18,0x6, 0x7d,0x30,0x9e,0x34,0x0, 0x21,0x12,0xa5,0xbf,0x59,0x40, +0x22,0xe4,0x59,0x30,0x22,0xe6,0x80,0xf, 0x12,0xa5,0xbf,0x59,0x10,0x22,0xe4,0x69, +0x17,0x0, 0x4, 0x59,0x10,0x22,0xe6,0xa, 0x1d,0x19,0xf1,0x5d,0x1b,0x74,0x1, 0x19, +0xb2,0x5d,0x11,0x80,0x9, 0xb, 0xf0,0x12,0xa5,0xb7,0x28,0x2, 0x61,0x24,0xb, 0xd0, +0x7e,0xb3,0x72,0xce,0xbc,0xbd,0x28,0x2, 0x61,0x20,0x6c,0xdd,0x80,0x1f,0x74,0x7, +0xac,0xbd,0x7e,0x1d,0x26,0x2d,0x35,0x69,0x41,0x0, 0x2, 0x74,0x2, 0xac,0xbd,0x59, +0x45,0x72,0xe3,0x69,0x31,0x0, 0x4, 0x59,0x35,0x72,0xcf,0xb, 0xd0,0x90,0x21,0x51, +0xe4,0x93,0x7c,0xab,0xbc,0xad,0x38,0xd6,0x6c,0xdd,0x80,0x2b,0xa, 0x3d,0x9, 0xb3, +0x5d,0x1b,0xb4,0xff,0x20,0x6c,0xff,0x80,0x18,0xa, 0x4f,0x9, 0xb4,0x5d,0x11,0x70, +0xe, 0xa, 0x3d,0x19,0xf3,0x5d,0x1b,0x74,0x1, 0x19,0xb4,0x5d,0x11,0x80,0x6, 0xb, +0xf0,0xbc,0xaf,0x38,0xe4,0xb, 0xd0,0xbc,0xad,0x38,0xd1,0x6c,0xdd,0x80,0x1e,0x7e, +0x70,0x9, 0xac,0x7d,0x49,0x13,0x68,0xb, 0x7e,0x50,0x2, 0xac,0x5d,0x3e,0x24,0x59, +0x12,0x23,0xc, 0x49,0x33,0x68,0xd, 0x59,0x32,0x23,0xe, 0xb, 0xd0,0x7e,0x73,0x69, +0x5f,0xbc,0x7d,0x38,0xda,0x7e,0x34,0x22,0xe4,0x7a,0x37,0x5d,0x27,0x7e,0x34,0x23, +0xc, 0x7a,0x37,0x5d,0x29,0x7e,0x34,0x23,0x34,0x7a,0x37,0x5d,0x2b,0x7e,0x73,0x72, +0xce,0x7a,0x73,0x5d,0x25,0x7e,0x73,0x69,0x5f,0x7a,0x73,0x5d,0x26,0x7e,0x8, 0x5d, +0x25,0x12,0x1, 0x20,0x6c,0xdd,0xa1,0x2c,0x7e,0xa0,0xff,0x6c,0xff,0x80,0x19,0x7e, +0x70,0x2, 0xac,0x7f,0x49,0x23,0x23,0x34,0xa, 0x3d,0xbd,0x32,0x78,0x8, 0xa, 0x3f, +0x9, 0xa3,0x5d,0x1b,0x80,0x7, 0xb, 0xf0,0x12,0xa5,0xb7,0x38,0xe2,0xbe,0xa0,0xff, +0x68,0x58,0x7e,0x70,0x9, 0xac,0x7d,0x19,0xa3,0x68,0xf, 0x74,0x1, 0xa, 0x4a,0x19, +0xb4,0x5d,0x7, 0x7e,0x70,0x7, 0xac,0x7a,0x7e,0xd, 0x26,0x2d,0x13,0x69,0x30,0x0, +0x4, 0xbe,0x37,0x6e,0x0, 0x38,0x1e,0x7e,0x70,0x9, 0xac,0x7d,0x49,0x33,0x68,0xd, +0xbe,0x37,0x6e,0x0, 0x28,0xf, 0xe4,0xa, 0x4a,0x19,0xb4,0x5d,0x7, 0x74,0x1, 0xa, +0x4d,0x19,0xb4,0x5d,0x2d,0x7e,0x70,0x9, 0xac,0x7d,0x49,0x33,0x68,0xb, 0x79,0x30, +0x0, 0x2, 0x12,0xa5,0xe7,0xac,0x3a,0x12,0xa5,0xd1,0xb, 0xd0,0x7e,0xb3,0x69,0x5f, +0xbc,0xbd,0x28,0x2, 0x81,0xa8,0x6c,0xdd,0x80,0x1f,0xa, 0x3d,0x9, 0xb3,0x5d,0x7, +0xbe,0xb0,0x1, 0x68,0x12,0x7e,0x34,0x7f,0xff,0x12,0xa5,0xc7,0x79,0x30,0x0, 0x2, +0x12,0xa5,0xc7,0x79,0x30,0x0, 0x4, 0xb, 0xd0,0x12,0xa5,0xaf,0x38,0xdc,0x6c,0xee, +0x7e,0xc3,0x69,0x5f,0x6c,0xdd,0x80,0x2a,0xa, 0x3d,0x9, 0xb3,0x5d,0x2d,0x70,0x20, +0x7e,0x34,0x0, 0x9, 0xca,0x39,0xac,0x7d,0x2e,0x34,0x68,0xb, 0x6d,0x22,0x7e,0x30, +0x9, 0xac,0x3e,0x2e,0x14,0x68,0xb, 0x6d,0x0, 0x12,0x24,0x14,0x1b,0xfd,0xb, 0xe0, +0xb, 0xd0,0xbc,0xcd,0x38,0xd2,0x7a,0xe3,0x69,0x5f,0x7e,0x73,0x69,0x5f,0x7a,0x73, +0x72,0xce,0x7e,0xd, 0x26,0x7e,0x18,0x5d,0x7, 0x12,0xa7,0xea,0xda,0x3b,0x22,0x90, +0x21,0x51,0xe4,0x93,0xbc,0xbd,0x22,0x90,0x21,0x51,0xe4,0x93,0xbc,0xbf,0x22,0x7e, +0x10,0x2, 0xac,0x1d,0x3e,0x4, 0x22,0x74,0x7, 0xac,0xbd,0x7e,0xd, 0x26,0x2d,0x15, +0x22,0x7e,0x1d,0x26,0x2d,0x31,0x79,0x41,0x0, 0x4, 0x22,0x7e,0x10,0x40,0xac,0x1, +0x7d,0xd0,0x9e,0xd4,0x0, 0x20,0x22,0x7e,0x70,0x9, 0xac,0x7d,0x49,0x43,0x68,0xd, +0x7e,0x30,0x7, 0x22,0xca,0x3b,0x7c,0xfb,0x6c,0xee,0xc1,0x8e,0x6c,0xdd,0x80,0x16, +0x74,0x9, 0xac,0xbd,0x9, 0x65,0x68,0xc3,0x74,0x9, 0xac,0xbe,0x9, 0x75,0x68,0xf, +0xbc,0x67,0x68,0x7, 0xb, 0xd0,0x12,0xa5,0xaf,0x38,0xe5,0x12,0xa5,0xaf,0x28,0x74, +0x7e,0x50,0x9, 0xac,0x5d,0x9, 0xc2,0x68,0xc3,0x49,0x42,0x68,0xc1,0x74,0x9, 0xac, +0xbe,0x49,0xa5,0x68,0xd, 0x7d,0x3a,0x9d,0x34,0xbe,0x34,0x0, 0x0, 0x8, 0x4, 0x9d, +0xa4,0x80,0x4, 0x6d,0xaa,0x9d,0xa3,0x49,0x42,0x68,0xbf,0x49,0xb5,0x68,0xb, 0x7d, +0x3b,0x9d,0x34,0xbe,0x34,0x0, 0x0, 0x8, 0x4, 0x9d,0xb4,0x80,0x4, 0x6d,0xbb,0x9d, +0xb3,0x2d,0xba,0x74,0x7, 0xac,0xbc,0x9, 0xb5,0x69,0x19,0xb4,0x1, 0xe, 0x6d,0xaa, +0x74,0x2, 0xac,0xbc,0x59,0xa5,0x28,0x89,0x59,0xa5,0x28,0xa1,0x7d,0x3b,0x7c,0xbd, +0x7c,0x5e,0x7c,0x4c,0x12,0xb1,0x7a,0x7c,0xbd,0x12,0xa6,0x97,0xb, 0xe0,0xbc,0xfe, +0x28,0x2, 0xa1,0xfc,0xda,0x3b,0x22,0x2, 0xa6,0x9a,0xca,0x3b,0x7c,0xd4,0x7c,0xe5, +0x7c,0xfb,0x7d,0xf3,0x7e,0x17,0x69,0x7d,0xbd,0x13,0x38,0x6, 0x7e,0xd4,0x1, 0x0, +0x80,0x17,0x6d,0x22,0x7c,0x56,0x7c,0x67,0x6c,0x77,0x12,0x22,0xbd,0x7d,0xd3,0xbe, +0xd4,0x0, 0x10,0x50,0x4, 0x7e,0xd4,0x0, 0x10,0x74,0x2, 0xac,0xbd,0x49,0x45,0x28, +0xa1,0xbd,0x4f,0x28,0x6, 0x49,0xd5,0x28,0x89,0x80,0x4, 0x59,0xd5,0x28,0x89,0x59, +0xf5,0x28,0xa1,0xbe,0xd4,0x1, 0x0, 0x28,0x4, 0x7e,0xd4,0x1, 0x0, 0x7e,0xb3,0x69, +0x84,0x60,0xb, 0x7e,0x73,0x69,0x5f,0xbe,0x70,0x2, 0x40,0x2, 0x1e,0xd4,0x7e,0x73, +0x69,0x5f,0xbe,0x70,0x5, 0x28,0x2, 0x1e,0xd4,0xbe,0xd4,0x0, 0x20,0x50,0x11,0x7e, +0x70,0x9, 0xac,0x7d,0x9, 0xb3,0x28,0x2d,0xb4,0x1, 0x5, 0xe4,0x19,0xb3,0x28,0x2d, +0xbe,0xd4,0x0, 0x40,0x28,0xc, 0x7e,0xa0,0x1, 0x7e,0x70,0x9, 0xac,0x7d,0x19,0xa3, +0x28,0x2d,0x7c,0xbe,0x7c,0x7d,0x12,0xb2,0x8a,0x7d,0x13,0x7e,0xb3,0x69,0x84,0x60, +0x2, 0x1e,0xd4,0x7e,0x70,0x9, 0xac,0x7f,0x49,0x3, 0x68,0xbf,0x7e,0xd0,0x9, 0xac, +0xde,0x49,0x26,0x68,0xb, 0x7d,0xe2,0x9d,0xe0,0xbe,0xe4,0x0, 0x0, 0x8, 0x6, 0x7d, +0xf2,0x9d,0xf0,0x80,0x4, 0x6d,0xff,0x9d,0xfe,0x12,0xa7,0xdb,0xbd,0x20,0x28,0xf, +0x7d,0xe3,0x2e,0xe4,0x68,0xbf,0x7d,0xc0,0x2d,0xcf,0x1b,0xe8,0xc0,0x80,0xf, 0x74, +0x9, 0xac,0xbf,0x7d,0xe5,0x2e,0xe4,0x68,0xbf,0x9d,0xf, 0x1b,0xe8,0x0, 0x7e,0x50, +0x9, 0xac,0x5f,0x49,0x32,0x68,0xc1,0x7e,0xd0,0x9, 0xac,0xde,0x49,0xe6,0x68,0xd, +0x7d,0xe, 0x9d,0x3, 0xbe,0x4, 0x0, 0x0, 0x8, 0x6, 0x7d,0xfe,0x9d,0xf3,0x80,0x4, +0x6d,0xff,0x9d,0xf0,0x12,0xa7,0xdb,0xbd,0xe3,0x28,0xf, 0x7d,0xe2,0x2e,0xe4,0x68, +0xc1,0x7d,0x23,0x2d,0x2f,0x1b,0xe8,0x20,0x80,0xe, 0x7e,0x50,0x9, 0xac,0x5f,0x2e, +0x24,0x68,0xc1,0x9d,0x3f,0x1b,0x28,0x30,0xda,0x3b,0x22,0x7d,0x5d,0xad,0x5f,0x7c, +0xba,0x7c,0xa9,0xa, 0x48,0x7d,0xf5,0x5d,0xf1,0x22,0xca,0x79,0x7e,0xa3,0x69,0x5f, +0x6c,0x99,0x80,0x66,0xa, 0xf9,0x2d,0xf3,0x7d,0xe2,0x7e,0x7b,0xb0,0xb4,0x1, 0x27, +0x12,0xa8,0x62,0x29,0xb7,0x0, 0x1, 0xb4,0x1, 0x6, 0x74,0x3, 0x39,0xb7,0x0, 0x1, +0x12,0xa8,0x62,0x29,0x87,0x0, 0x1, 0xbe,0x80,0x3, 0x78,0x3, 0xe4,0x80,0x2c,0x4c, +0x88,0x78,0x2b,0x74,0x2, 0x80,0x24,0x12,0xa8,0x62,0x29,0xb7,0x0, 0x1, 0xbe,0xb0, +0x2, 0x68,0x2, 0x70,0x14,0x74,0x1, 0x7a,0x7b,0xb0,0x7c,0x8a,0xb, 0xa0,0x7e,0xf0, +0x9, 0xac,0xf8,0x19,0x97,0x68,0xf, 0x80,0x5, 0x74,0x3, 0x7a,0x7b,0xb0,0x12,0xa8, +0x62,0x7e,0x7b,0xb0,0x39,0xb7,0x0, 0x1, 0xb, 0x90,0x12,0xa8,0x6c,0x38,0x95,0xda, +0x79,0x22,0x7e,0xf0,0x7, 0xac,0xf9,0x7f,0x70,0x2d,0xf7,0x22,0x90,0x21,0x51,0xe4, +0x93,0xbc,0xb9,0x22,0x7e,0x8, 0x5d,0x7, 0xca,0x69,0xca,0xf8,0x7f,0x70,0x7c,0x86, +0x7c,0xf7,0x7c,0xab,0x6c,0x99,0x21,0x38,0x7c,0x3f,0x21,0x30,0x7e,0x10,0x9, 0xac, +0x19,0x9, 0x20,0x68,0xc3,0x7e,0x10,0x9, 0xac,0x13,0x9, 0xb0,0x68,0xf, 0xbc,0xb2, +0x68,0x2, 0x21,0x2e,0xbe,0x20,0xff,0x78,0x2, 0x21,0x2e,0x7e,0xd0,0x7, 0xac,0xd2, +0x9, 0xb6,0x69,0x19,0x70,0xa, 0x7d,0x30,0x2e,0x34,0x68,0xb, 0x6d,0x22,0x80,0xb, +0x7e,0x70,0x9, 0xac,0x79,0x2e,0x34,0x68,0xbf,0x6d,0x22,0x29,0x11,0x0, 0x4, 0x12, +0xa9,0x46,0x39,0x16,0x0, 0x4, 0xb, 0x1a,0x0, 0x12,0xa9,0x46,0x1b,0x6a,0x0, 0x69, +0x1, 0x0, 0x2, 0x12,0xa9,0x46,0x79,0x6, 0x0, 0x2, 0x7e,0x10,0x9, 0xac,0x13,0x9, +0x10,0x68,0x10,0x12,0xa9,0x46,0x39,0x16,0x0, 0x5, 0x7e,0x10,0x9, 0xac,0x13,0x9, +0x10,0x68,0x11,0x12,0xa9,0x46,0x39,0x16,0x0, 0x6, 0x7e,0x10,0x9, 0xac,0x13,0x9, +0x10,0x68,0x12,0x12,0xa9,0x46,0x39,0x16,0x0, 0x7, 0x7e,0x10,0x9, 0xac,0x13,0x9, +0x10,0x68,0x13,0x12,0xa9,0x46,0x39,0x16,0x0, 0x8, 0xb, 0xa0,0x80,0x8, 0xb, 0x30, +0xbc,0x83,0x28,0x2, 0x1, 0x8c,0xb, 0x90,0x12,0xa8,0x6c,0x28,0x2, 0x1, 0x88,0x7c, +0xba,0xda,0xf8,0xda,0x69,0x22,0x7e,0xd0,0x9, 0xac,0xda,0x7f,0x67,0x2d,0xd6,0x22, +0xca,0x79,0x7c,0xeb,0x90,0x21,0x51,0xe4,0x93,0x7c,0xfb,0x7e,0x70,0x9, 0xac,0x7f, +0x7e,0x8, 0x5d,0x7, 0x74,0xff,0x12,0x24,0x39,0xe4,0x6c,0x77,0x7c,0x6e,0x12,0xa8, +0x74,0x7c,0x7e,0x7c,0x6f,0x12,0xa8,0x74,0x7c,0x1b,0x6c,0x0, 0x80,0x3a,0x6c,0x99, +0x80,0x17,0x74,0x9, 0xac,0xb9,0x9, 0xa5,0x5d,0xb, 0x7e,0x30,0x9, 0xac,0x30,0x9, +0x81,0x68,0xf, 0xbc,0x8a,0x68,0x6, 0xb, 0x90,0xbc,0x19,0x38,0xe5,0xbc,0x19,0x78, +0x15,0x7e,0x70,0x9, 0xac,0x70,0x12,0xaa,0xc6,0xac,0x31,0x2e,0x14,0x5d,0x7, 0x74, +0x9, 0x12,0x23,0x44,0xb, 0x10,0xb, 0x0, 0xbc,0xf0,0x38,0xc2,0x74,0x9, 0xac,0xbf, +0xca,0x59,0x7e,0x18,0x5d,0x7, 0x7e,0x8, 0x68,0xbf,0x12,0x24,0x14,0x1b,0xfd,0xda, +0x79,0x22,0xca,0x79,0x7e,0xf3,0x69,0x5f,0x7e,0xe3,0x69,0x60,0x7c,0xbf,0x7c,0x7e, +0x12,0xaa,0x69,0x7c,0xbf,0x12,0xa9,0x50,0x4c,0xee,0x78,0x17,0x12,0x5f,0xda,0xca, +0x59,0x7e,0x18,0x68,0xb, 0x7e,0x8, 0x68,0xbf,0x12,0x24,0x14,0x1b,0xfd,0x12,0xaa, +0x19,0x80,0xe, 0x7e,0xb3,0x69,0x66,0x70,0x8, 0x12,0xaa,0x19,0x7c,0xbf,0x12,0xa5, +0xf4,0x7c,0xbf,0x12,0xad,0xbf,0xda,0x79,0x22,0x7e,0xa3,0x69,0x5f,0x6c,0x77,0x80, +0x43,0x7e,0x90,0x9, 0xac,0x97,0x9, 0x64,0x68,0xc3,0x7e,0x50,0x7, 0xac,0x56,0x9, +0xb2,0x69,0x19,0x70,0x2d,0x7e,0x30,0x1, 0x7e,0x50,0x9, 0xac,0x56,0x19,0x32,0x28, +0x28,0x49,0x14,0x68,0xb, 0x59,0x12,0x28,0x29,0x49,0x14,0x68,0xd, 0x59,0x12,0x28, +0x2b,0xe4,0x19,0xb2,0x28,0x2d,0x19,0xb2,0x28,0x25,0x19,0xb2,0x28,0x26,0x19,0xb2, +0x28,0x27,0xb, 0x70,0xbc,0xa7,0x38,0xb9,0x22,0x7c,0x67,0x7c,0x7b,0xa5,0xbf,0x0, +0xd, 0xbe,0x60,0x0, 0x28,0x5, 0xe4,0x7a,0xb3,0x69,0x66,0x2, 0xad,0x62,0xa5,0xbe, +0x0, 0x1b,0x6c,0xaa,0x80,0xe, 0x7e,0x60,0xff,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x62, +0x68,0xc3,0xb, 0xa0,0x90,0x21,0x51,0xe4,0x93,0xbc,0xba,0x38,0xe9,0x6c,0xaa,0x80, +0x20,0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x68,0xb, 0x12,0x33,0x6b,0x1b,0x18,0x20, +0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x68,0xd, 0x12,0x33,0x6b,0x1b,0x18,0x20,0xb, +0xa0,0xbc,0x7a,0x38,0xdc,0x22,0x2e,0x34,0x68,0xb, 0x7e,0x30,0x9, 0x22,0xca,0xd8, +0xca,0x79,0x6d,0x33,0x7d,0xc3,0x7e,0x53,0x69,0x5f,0x7c,0xd5,0x7e,0xa3,0x71,0xb, +0x4c,0xaa,0x78,0x19,0xe5,0x16,0xb4,0x1, 0x14,0x4c,0x55,0x68,0x10,0x7e,0xb3,0x69, +0x60,0x70,0x2, 0xa1,0x44,0xbe,0xb3,0x69,0x5f,0x78,0x2, 0xa1,0x44,0x7a,0xa1,0x16, +0xc2,0x20,0x7e,0xd4,0x68,0xb, 0x4c,0xdd,0x68,0x6, 0x7e,0xb3,0x69,0x60,0x70,0x27, +0x6c,0xff,0x80,0x1e,0x74,0x2, 0xac,0xbf,0x59,0x35,0x29,0x18,0x7e,0xa0,0xff,0x7e, +0x50,0x9, 0xac,0x5f,0x19,0xa2,0x28,0xc2,0x74,0x1, 0xa, 0x2f,0x19,0xb2,0x29,0x2c, +0xb, 0xf0,0x12,0xa5,0xb7,0x38,0xdd,0xc2,0x1f,0x7e,0xb3,0x28,0x9f,0x60,0x6, 0x7e, +0xb3,0x69,0x84,0x60,0x7, 0x12,0xae,0x30,0x50,0x2, 0xd2,0x1f,0x12,0xad,0x83,0x6c, +0xff,0x81,0xe1,0x74,0x9, 0xac,0xbf,0x9, 0xe5,0x68,0xf, 0x5e,0xe0,0xf, 0x12,0xad, +0x49,0x38,0x2, 0x81,0xdf,0x74,0x7, 0xac,0xbe,0x9, 0xb5,0x69,0x19,0xbe,0xb0,0x1, +0x78,0x2, 0x81,0xc2,0x6c,0x11,0x81,0xb5,0x74,0x9, 0xac,0xb1,0x9, 0x5, 0x28,0xc2, +0xbc,0xe, 0x68,0x2, 0x81,0xb3,0x49,0xf5,0x28,0xc0,0x7e,0x30,0x9, 0xac,0x3f,0x2d, +0x1d,0x49,0x31,0x0, 0x2, 0x7d,0x23,0x9d,0x2f,0xbe,0x24,0x0, 0x0, 0x8, 0x4, 0x9d, +0x3f,0x80,0x4, 0x6d,0x33,0x9d,0x32,0x74,0x9, 0xac,0xb1,0x49,0xf5,0x28,0xbe,0xb, +0x18,0x20,0x7d,0x52,0x9d,0x5f,0xbe,0x54,0x0, 0x0, 0x8, 0x6, 0x9d,0x2f,0x7d,0x42, +0x80,0x4, 0x6d,0x44,0x9d,0x45,0x2d,0x43,0x74,0x2, 0xac,0xb0,0x49,0xc5,0x29,0x18, +0x59,0x45,0x29,0x18,0xa, 0x50,0x9, 0xb5,0x29,0x2c,0xbe,0xb0,0x0, 0x28,0x12,0xa, +0x30,0x2e,0x34,0x29,0x2c,0x14,0x7a,0x39,0xb0,0xbe,0x44,0x1, 0x40,0x50,0x2, 0x81, +0xdf,0xbe,0xc4,0x0, 0x32,0x28,0x8, 0xbe,0x44,0x0, 0x32,0x28,0x2, 0xd2,0x20,0xbe, +0xc4,0x0, 0x1e,0x28,0xa, 0x7d,0x5c,0x2e,0x54,0x1, 0x40,0xbd,0x54,0x40,0x3a,0xbe, +0xc4,0x0, 0x1e,0x28,0x15,0xbe,0x44,0x0, 0x1e,0x28,0xf, 0x12,0xad,0x51,0x50,0x2, +0x81,0xdf,0xbe,0xc4,0x0, 0x3c,0x28,0x2, 0x81,0xdf,0x7d,0x5c,0x2e,0x54,0x0, 0x1e, +0xbd,0x54,0x50,0x15,0xbe,0xc4,0x0, 0x1e,0x28,0xf, 0x12,0xad,0x51,0x50,0x2, 0x81, +0xdf,0xbe,0xc4,0x0, 0x3c,0x28,0x2, 0x81,0xdf,0x30,0x1f,0x2, 0x81,0xdf,0xbe,0x44, +0x0, 0xb4,0x28,0x55,0x7e,0x30,0x7, 0xac,0x3e,0x9, 0xb1,0x69,0x19,0x70,0x4, 0x74, +0x3, 0x80,0x2, 0x74,0x1, 0x19,0xb1,0x69,0x19,0x7e,0xa0,0x3, 0x7e,0x30,0x7, 0xac, +0x30,0x19,0xa1,0x69,0x1a,0xbe,0xd0,0x0, 0x28,0x2f,0x1b,0xd0,0x7e,0x70,0x9, 0xac, +0x7f,0x2e,0x34,0x68,0xb, 0x7e,0x14,0x5d,0x7, 0x74,0x9, 0x12,0x23,0x44,0x7e,0x70, +0x9, 0xac,0x7d,0x12,0xaa,0xc6,0xac,0x3f,0x12,0xad,0x59,0x7e,0x34,0x5d,0x7, 0x7e, +0x30,0x9, 0xac,0x3d,0x12,0xad,0x59,0x1b,0xf0,0x74,0x2, 0xac,0xb0,0x59,0x45,0x29, +0x18,0x80,0x2c,0xb, 0x10,0x90,0x21,0x51,0xe4,0x93,0xbc,0xb1,0x28,0x2, 0x61,0x78, +0x80,0x1d,0x6d,0x33,0x74,0x2, 0xac,0xbe,0x59,0x35,0x29,0x18,0x7e,0x0, 0xff,0x74, +0x9, 0xac,0xbe,0x19,0x5, 0x28,0xc2,0x74,0x1, 0xa, 0x3e,0x19,0xb3,0x29,0x2c,0xb, +0xf0,0xbc,0xdf,0x28,0x2, 0x61,0x53,0x12,0x5f,0xda,0xca,0x59,0x7e,0x18,0x68,0xb, +0x7e,0x8, 0x28,0xbe,0x12,0x24,0x14,0x1b,0xfd,0x6c,0xff,0x80,0x39,0x7e,0x70,0x9, +0xac,0x7f,0x9, 0xe3,0x28,0xc2,0x12,0xad,0x49,0x28,0x29,0x7e,0x50,0x7, 0xac,0x5e, +0x9, 0xb2,0x69,0x19,0xbe,0xb0,0x1, 0x68,0x3, 0xb4,0x3, 0x18,0x6d,0x22,0x74,0x2, +0xac,0xbe,0x59,0x25,0x29,0x18,0x74,0xff,0x19,0xb3,0x28,0xc2,0x74,0x1, 0xa, 0xce, +0x19,0xbc,0x29,0x2c,0xb, 0xf0,0x12,0xa5,0xb7,0x38,0xc2,0x7a,0xd3,0x69,0x5f,0xe4, +0x7a,0xb3,0x28,0xa0,0xda,0x79,0xda,0xd8,0x22,0x90,0x21,0x51,0xe4,0x93,0xbc,0xbe, +0x22,0x9, 0x71,0x0, 0x6, 0xbe,0x70,0x14,0x22,0x2e,0x14,0x68,0xb, 0x74,0x9, 0x2, +0x23,0x44,0x12,0x5b,0xb3,0x74,0x2, 0xac,0x7b,0x7e,0x8, 0x28,0xa1,0xe4,0x12,0x24, +0x39,0x90,0x21,0x51,0x93,0x7c,0x7b,0x74,0x2, 0xac,0x7b,0x7e,0x8, 0x28,0x89,0xe4, +0x2, 0x24,0x39,0x7e,0x73,0x69,0x60,0xbe,0x73,0x69,0x5f,0x78,0x17,0x7e,0x73,0x69, +0x5f,0xbe,0x70,0x1, 0x40,0xe, 0x7e,0x37,0x28,0x9d,0xbe,0x34,0x0, 0x14,0x38,0xe, +0xb, 0x34,0x80,0x6, 0x7e,0x37,0x28,0x9d,0x1e,0x34,0x7a,0x37,0x28,0x9d,0x7e,0xb3, +0x69,0x5f,0x70,0x6, 0x6d,0x33,0x7a,0x37,0x28,0x9d,0x7e,0x37,0x28,0x9d,0x22,0x6c, +0xaa,0x80,0x63,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x68,0xbf,0x12,0x31,0xd8,0x59, +0x32,0x68,0xb, 0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x68,0xc1,0x12,0x31,0xd8,0x59, +0x32,0x68,0xd, 0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x68,0xc3,0x19,0xb4,0x68,0xf, +0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x68,0xc4,0x19,0xb4,0x68,0x10,0x7e,0x90,0x9, +0xac,0x9a,0x9, 0xb4,0x68,0xc5,0x19,0xb4,0x68,0x11,0x7e,0x90,0x9, 0xac,0x9a,0x9, +0xb4,0x68,0xc6,0x19,0xb4,0x68,0x12,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x68,0xc7, +0x19,0xb4,0x68,0x13,0xb, 0xa0,0x90,0x21,0x51,0xe4,0x93,0xbc,0xba,0x38,0x94,0x22, +0x7e,0x73,0x69,0x60,0xbe,0x73,0x69,0x5f,0x78,0x7d,0x7e,0xb3,0x69,0x5f,0xb4,0x1, +0x76,0x7e,0xb3,0x28,0xb7,0xbe,0xb0,0x2, 0x38,0x13,0x4, 0x7a,0xb3,0x28,0xb7,0x7e, +0x37,0x68,0xb, 0x7a,0x37,0x28,0xba,0x7e,0x37,0x68,0xd, 0x80,0x69,0x7e,0x37,0x28, +0xb8,0xbe,0x34,0x6, 0xa4,0x50,0x4e,0x7e,0x27,0x68,0xb, 0x7d,0x12,0x9e,0x17,0x28, +0xba,0xbe,0x14,0x0, 0x0, 0x8, 0x8, 0x7d,0x32,0x9e,0x37,0x28,0xba,0x80,0x4, 0x6d, +0x33,0x9d,0x31,0x2e,0x37,0x28,0xb8,0x7a,0x37,0x28,0xb8,0x7e,0x37,0x68,0xd, 0x7d, +0x3, 0x9e,0x7, 0x28,0xbc,0xbe,0x4, 0x0, 0x0, 0x8, 0x8, 0x7d,0x13,0x9e,0x17,0x28, +0xbc,0x80,0x4, 0x6d,0x11,0x9d,0x10,0x2e,0x17,0x28,0xb8,0x7a,0x17,0x28,0xb8,0x7a, +0x27,0x28,0xba,0x80,0x11,0xd3,0x22,0xe4,0x7a,0xb3,0x28,0xb7,0x6d,0x33,0x7a,0x37, +0x28,0xb8,0x7a,0x37,0x28,0xba,0x7a,0x37,0x28,0xbc,0xc3,0x22,0xca,0xf8,0x7e,0xb3, +0x69,0x5f,0x70,0x17,0xe4,0x7a,0xb3,0x69,0x68,0x12,0x97,0x65,0x28,0x1f,0x74,0x1, +0x7a,0xb3,0x69,0x64,0xe4,0x7a,0xb3,0x69,0x67,0x80,0x12,0x74,0x1, 0x7a,0xb3,0x69, +0x68,0x7e,0xb3,0x69,0x60,0x70,0x6, 0x74,0x1, 0x7a,0xb3,0x69,0x63,0x12,0x5f,0xda, +0xca,0x59,0x7e,0x18,0x68,0xb, 0x7e,0x8, 0x68,0x65,0x12,0x24,0x14,0x1b,0xfd,0x90, +0x1c,0x2c,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x2d,0x6c,0xff,0x80,0x24,0x74,0x9, 0xac, +0xbf,0x49,0x35,0x68,0xb, 0x12,0x8c,0x6, 0x74,0x9, 0xac,0xbf,0x59,0x35,0x68,0x65, +0x49,0x35,0x68,0xd, 0x12,0x76,0x5d,0x74,0x9, 0xac,0xbf,0x59,0x35,0x68,0x67,0xb, +0xf0,0x12,0xa5,0xb7,0x38,0xd7,0xda,0xf8,0x22,0x7e,0x8, 0x28,0x1b,0x7e,0x34,0x0, +0xa, 0x74,0x8, 0x12,0x24,0x39,0x7e,0x8, 0x28,0x7f,0x7e,0x34,0x0, 0xa, 0xe4,0x2, +0x24,0x39,0x7e,0xa3,0x69,0x60,0xbe,0xa0,0x0, 0x38,0x23,0xbe,0xa3,0x69,0x5f,0x50, +0x18,0x7e,0xb3,0x69,0x69,0xbe,0xb3,0x28,0xb6,0x28,0x13,0x7e,0xb3,0x28,0xb6,0x4, +0x7a,0xb3,0x28,0xb6,0x7a,0xa3,0x69,0x5f,0x22,0xe4,0x7a,0xb3,0x28,0xb6,0x22,0xca, +0x3b,0x7e,0xb3,0x69,0x5f,0x7e,0x18,0x69,0x19,0x70,0x12,0x12,0xaf,0x49,0x7e,0x8, +0x29,0x5e,0x7e,0x34,0x0, 0xa, 0xe4,0x12,0x24,0x39,0x2, 0xb1,0x68,0x6c,0xaa,0x2, +0xb1,0x5c,0x7e,0xf0,0x9, 0xac,0xfa,0x9, 0x37,0x68,0x69,0x6c,0x22,0x6c,0x11,0x49, +0xb7,0x68,0x65,0x4d,0xbb,0x68,0x11,0x7e,0xf4,0x21,0xde,0x7e,0xe4,0x0, 0xff,0xb, +0x7a,0xa0,0x1b,0xa4,0xbd,0xba,0x78,0x3, 0x7e,0x20,0x1, 0x49,0xe7,0x68,0x67,0x4d, +0xee,0x68,0x11,0x7e,0xd4,0x21,0xec,0x7e,0xc4,0x0, 0xff,0xb, 0x6a,0xf0,0x1b,0xf4, +0xbd,0xef,0x78,0x3, 0x7e,0x10,0x1, 0xbe,0x30,0xff,0x78,0x3, 0x2, 0xb1,0x5a,0x7e, +0x90,0x7, 0xac,0x93,0x7f,0x61,0x2d,0xd4,0x7e,0x6b,0xb0,0xb4,0x2, 0x2, 0x80,0x2, +0x21,0x1e,0x7e,0x90,0x4, 0xac,0x93,0x49,0xa4,0x29,0x36,0x7d,0xfb,0x9d,0xfa,0xbe, +0xf4,0x0, 0x0, 0x8, 0x6, 0x7d,0x4b,0x9d,0x4a,0x80,0x4, 0x6d,0x44,0x9d,0x4f,0x7e, +0xf0,0x4, 0xac,0xf3,0x49,0x87,0x29,0x38,0x7d,0x9e,0x9d,0x98,0xbe,0x94,0x0, 0x0, +0x8, 0x6, 0x7d,0xfe,0x9d,0xf8,0x80,0x4, 0x6d,0xff,0x9d,0xf9,0x7e,0x3, 0x69,0x5f, +0xbe,0x0, 0x8, 0x40,0x8, 0x74,0xf, 0xa, 0x9a,0x19,0xb9,0x28,0x1b,0xa, 0x9a,0x9, +0xb9,0x29,0x5e,0x70,0xe, 0x7d,0x9f,0x2d,0x94,0xbe,0x94,0x0, 0x4, 0x50,0x4, 0x6d, +0xff,0x7d,0x4f,0xa, 0x9a,0x9, 0x9, 0x28,0x1b,0xa, 0x90,0xbd,0x94,0x28,0x5c,0xbd, +0x9f,0x28,0x58,0xbe,0x20,0x1, 0x68,0x9, 0x7e,0xf0,0x9, 0xac,0xfa,0x59,0xa7,0x68, +0x65,0xbe,0x10,0x1, 0x68,0x12,0x7e,0xf0,0x4, 0xac,0xf3,0x49,0xa7,0x29,0x38,0x7e, +0xf0,0x9, 0xac,0xfa,0x59,0xa7,0x68,0x67,0xa, 0xaa,0x2e,0xa4,0x28,0x7f,0x7e,0xa9, +0xb0,0x4, 0x7a,0xa9,0xb0,0xa, 0xaa,0x9, 0xba,0x28,0x7f,0xbe,0xb0,0x32,0x50,0x2, +0x21,0x5a,0xa, 0xaa,0x9, 0xba,0x28,0x1b,0xbe,0xb0,0x8, 0x40,0x2, 0x21,0x5a,0xa, +0xaa,0x2e,0xa4,0x28,0x1b,0x4, 0x7a,0xa9,0xb0,0x80,0x7f,0x74,0x1, 0xa, 0xaa,0x19, +0xba,0x29,0x5e,0x7e,0xf0,0x4, 0xac,0xf3,0x59,0xb7,0x29,0x36,0x7e,0xf0,0x4, 0xac, +0xf3,0x59,0xe7,0x29,0x38,0xbe,0x0, 0x8, 0x40,0xa, 0x74,0x3, 0xa, 0xea,0x19,0xbe, +0x28,0x1b,0x80,0x11,0xbe,0x0, 0x1, 0x28,0xc, 0xa, 0xea,0x2e,0xe4,0x28,0x1b,0x7c, +0xb0,0x14,0x7a,0xe9,0xb0,0xe4,0xa, 0xea,0x19,0xbe,0x28,0x7f,0x80,0x3c,0x7e,0x6b, +0xb0,0x70,0x21,0x7e,0xf0,0x9, 0xac,0xfa,0x49,0xe7,0x68,0x65,0x7e,0xf0,0x4, 0xac, +0xf3,0x59,0xe7,0x29,0x36,0x7e,0xd0,0x9, 0xac,0xda,0x49,0xe6,0x68,0x67,0x59,0xe7, +0x29,0x38,0x80,0x16,0x7e,0xf0,0x7, 0xac,0xf3,0x7f,0x61,0x2d,0xd7,0x7e,0x6b,0xb0, +0xb4,0x1, 0x7, 0xe4,0xa, 0xea,0x19,0xbe,0x29,0x5e,0xb, 0xa0,0x90,0x21,0x51,0xe4, +0x93,0xbc,0xba,0x28,0x3, 0x2, 0xaf,0xb2,0xda,0x3b,0x22,0x7e,0xb3,0x28,0xa0,0xbe, +0xb0,0xfa,0x50,0x5, 0x4, 0x7a,0xb3,0x28,0xa0,0x22,0xca,0x3b,0x7c,0xab,0x7d,0x3, +0x7e,0x20,0x10,0x7d,0x30,0x7e,0x90,0x9, 0xac,0x95,0x9, 0x34,0x68,0x11,0xbe,0x30, +0x10,0x28,0x2, 0x7c,0x23,0xbe,0x20,0x20,0x28,0x3, 0x7e,0x20,0x20,0x49,0xe4,0x68, +0xb, 0xbe,0xe4,0x6, 0x50,0x40,0x20,0x7e,0x33,0x69,0x8e,0x12,0xb2,0x76,0xbd,0xef, +0x38,0x15,0x49,0xe4,0x68,0xd, 0xbe,0xe4,0x6, 0x50,0x40,0xb, 0x7e,0x33,0x69,0x8f, +0x12,0xb2,0x76,0xbd,0xef,0x28,0x3, 0x7e,0x20,0x8, 0x7e,0xf0,0x10,0xac,0xf2,0xbd, +0x70,0x40,0x5d,0x7e,0xf0,0x9, 0xac,0xf4,0x9, 0xb7,0x28,0x2d,0x70,0x52,0x7e,0xd0, +0x8, 0xac,0xd2,0xbd,0x60,0x50,0x3c,0x9, 0xb7,0x28,0x26,0x70,0x1f,0x9, 0xb7,0x28, +0x27,0xbe,0xb0,0x0, 0x28,0xc, 0x7d,0x37,0x2e,0x34,0x28,0x27,0x14,0x7a,0x39,0xb0, +0x80,0x6, 0x74,0x1, 0x19,0xb7,0x28,0x26,0x6d,0x33,0x80,0x34,0x9, 0xb7,0x28,0x27, +0xbe,0xb0,0x14,0x50,0x2b,0x7d,0x37,0x2e,0x34,0x28,0x27,0x4, 0x7a,0x39,0xb0,0x6d, +0x33,0x80,0x1d,0xe4,0x19,0xb7,0x28,0x27,0x19,0xb7,0x28,0x26,0x6d,0x33,0x80,0x10, +0x6c,0x33,0x7e,0xf0,0x9, 0xac,0xf4,0x19,0x37,0x28,0x27,0xe4,0x19,0xb7,0x28,0x26, +0x7e,0x30,0x8, 0xac,0x23,0xbd,0x10,0x40,0x2a,0x7e,0x70,0x9, 0xac,0x7a,0x49,0x33, +0x68,0xbf,0x59,0x34,0x68,0xb, 0x74,0x9, 0xa4,0x49,0x35,0x68,0xc1,0x74,0x9, 0xac, +0xb5,0x59,0x35,0x68,0xd, 0x7e,0xa0,0x1, 0x7e,0x70,0x9, 0xac,0x74,0x19,0xa3,0x28, +0x25,0x6d,0x33,0xda,0x3b,0x22,0x7e,0xf0,0x40,0xac,0xf3,0x7d,0xf7,0x9e,0xf4,0x0, +0x65,0x3e,0xf4,0x3e,0xf4,0x3e,0xf4,0x3e,0xf4,0x22,0x7c,0x17,0x7c,0xab,0x7e,0x14, +0xff,0xfc,0x7e,0x3, 0x69,0x5f,0x7e,0x90,0x9, 0xac,0x91,0x9, 0xb4,0x28,0x28,0xb4, +0x1, 0x49,0xa5,0xb8,0x1, 0xc, 0xbe,0x14,0xff,0x0, 0x28,0x10,0x7e,0x14,0xff,0x0, +0x80,0xa, 0xbe,0x14,0xff,0xe0,0x28,0x4, 0x7e,0x14,0xff,0xe0,0x49,0x34,0x28,0x29, +0x7e,0x50,0x9, 0xac,0x5a,0x49,0x22,0x68,0xb, 0x12,0xb3,0x75,0x8, 0x3, 0x12,0xb3, +0x7f,0x7e,0x70,0x9, 0xac,0x71,0x49,0x33,0x28,0x2b,0x7e,0x50,0x9, 0xac,0x5a,0x49, +0x22,0x68,0xd, 0x12,0xb3,0x75,0x8, 0x3, 0x12,0xb3,0x7f,0x7e,0x70,0x9, 0xac,0x71, +0x49,0x23,0x28,0x29,0x7e,0x70,0x9, 0xac,0x7a,0x49,0x33,0x68,0xb, 0x12,0xb3,0x6b, +0x18,0x16,0x74,0x9, 0xac,0x1b,0x49,0x20,0x28,0x2b,0x7e,0x70,0x9, 0xac,0x7a,0x49, +0x33,0x68,0xd, 0x12,0xb3,0x6b,0x8, 0x4, 0x7e,0x14,0xff,0xfc,0x7e,0x50,0x9, 0xac, +0x5a,0x49,0x2, 0x68,0xb, 0xbe,0x4, 0x6, 0x50,0x40,0x39,0x7e,0x63,0x69,0x8e,0x7e, +0x70,0x40,0xac,0x67,0x9e,0x34,0x0, 0x65,0x12,0x3b,0xcc,0x3e,0x34,0xbd,0x3, 0x38, +0x23,0x49,0x32,0x68,0xd, 0xbe,0x34,0x6, 0x50,0x40,0x19,0x7e,0x3, 0x69,0x8f,0x7e, +0x10,0x40,0xac,0x1, 0x9e,0x4, 0x0, 0x65,0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, +0xbd,0x30,0x28,0x4, 0x7e,0x14,0xff,0xff,0x7d,0x31,0x22,0x9d,0x32,0x12,0x24,0x5b, +0xbe,0x34,0x4, 0x0, 0x22,0x9d,0x32,0x12,0x24,0x5b,0xbe,0x34,0x1, 0x0, 0x22,0x6c, +0x0, 0x7e,0x70,0x9, 0xac,0x71,0x19,0x3, 0x28,0x28,0x22,0x12,0xb4,0xf2,0x12,0xb4, +0xfc,0x12,0xb3,0x9e,0x2, 0xb3,0x97,0x74,0x1, 0x7a,0xb3,0x73,0x60,0x22,0xca,0x3b, +0x7e,0xf3,0x69,0x8d,0x7e,0xe3,0x69,0x8e,0x7e,0xd3,0x69,0x8f,0x6c,0xcc,0x80,0x13, +0x7c,0x3c,0xac,0x3f,0x3e,0x14,0x2e,0x14,0x4, 0x0, 0x6d,0x0, 0x7c,0xbd,0x12,0xb3, +0xca,0xb, 0xc0,0xbc,0xec,0x38,0xe9,0xda,0x3b,0x22,0xca,0xd8,0xca,0x79,0x7c,0xfb, +0x7f,0x70,0xc2,0x0, 0x6c,0xdd,0x9f,0x55,0x6d,0x11,0x7d,0xc1,0x7d,0x91,0x7d,0xd1, +0x7e,0x4, 0x7f,0xff,0x6c,0xee,0x80,0x26,0x74,0x2, 0xac,0xbe,0x7f,0x17,0x2d,0x35, +0xb, 0x1a,0x30,0x12,0x24,0x5b,0x7d,0x93,0xbd,0xc9,0x58,0x2, 0x7d,0xc9,0xbd,0x9, +0x8, 0x2, 0x7d,0x9, 0x7d,0x39,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xe0,0xbc,0xfe, +0x38,0xd6,0xbe,0xc4,0x0, 0x1e,0x58,0xa, 0x7e,0xb3,0x67,0xeb,0x70,0x4, 0x6d,0x33, +0x81,0xd7,0xbe,0xc4,0x4, 0xb0,0x8, 0x2, 0xd2,0x0, 0xbe,0xc4,0x4, 0xb0,0x8, 0x11, +0x7e,0xc4,0x0, 0xa0,0x7e,0xb3,0x71,0x36,0xb4,0x1, 0x38,0x7e,0xc4,0x2, 0x58,0x80, +0x32,0xbe,0xc4,0x3, 0x20,0x8, 0x11,0x7e,0xc4,0x0, 0x96,0x7e,0xb3,0x71,0x36,0xb4, +0x1, 0x21,0x7e,0xc4,0x2, 0x26,0x80,0x1b,0xbe,0xc4,0x0, 0x0, 0x8, 0x11,0x7e,0xc4, +0x0, 0x8c,0x7e,0xb3,0x71,0x36,0xb4,0x1, 0xa, 0x7e,0xc4,0x1, 0xc2,0x80,0x4, 0x6d, +0x33,0x80,0x64,0xbd,0xc, 0x8, 0x5, 0x30,0x0, 0x2, 0x7d,0xc0,0xa, 0x1f,0x12,0xb4, +0xdc,0x9f,0x55,0x6c,0xee,0x80,0x1a,0x12,0xb4,0xe6,0x7d,0x3d,0x12,0x24,0x5b,0x7d, +0x93,0xbd,0x19,0x8, 0xa, 0x7d,0x3d,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xd0,0xb, +0xe0,0xbc,0xfe,0x38,0xe2,0x6d,0x11,0xbe,0xd0,0x0, 0x28,0x5, 0xa, 0x1d,0x12,0xb4, +0xdc,0xbd,0x1c,0x8, 0x4, 0x7d,0x1c,0x80,0xa, 0x6d,0x0, 0x9d,0xc, 0xbd,0x1, 0x8, +0x2, 0x7d,0x10,0x6c,0xee,0x80,0xa, 0x12,0xb4,0xe6,0x9d,0xd1,0x1b,0x1a,0xd0,0xb, +0xe0,0xbc,0xfe,0x38,0xf2,0x7d,0x31,0xda,0x79,0xda,0xd8,0x22,0x6d,0x0, 0x7f,0x15, +0x12,0x23,0x10,0x7d,0x13,0x22,0x74,0x2, 0xac,0xbe,0x7f,0x17,0x2d,0x35,0xb, 0x1a, +0xd0,0x22,0xe4,0x7a,0xb3,0x68,0x2, 0x7a,0xb3,0x68,0x3, 0x22,0x7e,0x8, 0x8, 0x68, +0x7e,0x1f,0x22,0xe0,0x12,0x7d,0xb8,0x7e,0x37,0x6d,0xfe,0x7e,0x50,0x4, 0x7d,0x3, +0x3e,0x4, 0x7e,0x2f,0x22,0xe0,0x2d,0x50,0xb, 0x2a,0x10,0x59,0x10,0x8, 0x68,0xb, +0x34,0x1b,0x50,0x78,0xe9,0x22,0xca,0xd8,0xca,0x79,0x7e,0x34,0x21,0xec,0x12,0xb5, +0xab,0x90,0x1c,0x2c,0xe4,0x93,0x60,0x6e,0x7e,0xb3,0x6e,0x3, 0x60,0x68,0x6c,0xff, +0x80,0x5f,0x7e,0x70,0x9, 0xac,0x7f,0x9, 0xe3,0x68,0x69,0x5e,0xe0,0xf, 0x49,0x23, +0x68,0x67,0xbd,0x2d,0x40,0x49,0x49,0xc3,0x68,0xb, 0x7d,0x3c,0x12,0xb5,0xb3,0x7c, +0xdb,0x7e,0x73,0x6e,0x3, 0xbc,0x7d,0x28,0x25,0x7e,0x70,0x2, 0xac,0x7d,0x2e,0x34, +0x21,0xfb,0x12,0x30,0xa4,0x74,0x9, 0xac,0xbf,0x59,0x35,0x68,0x65,0x7e,0x34,0x22, +0x3, 0x12,0x30,0xa4,0x74,0x9, 0xac,0xbf,0x59,0x35,0x68,0x67,0x80,0x11,0x7d,0x3d, +0x1b,0x34,0x74,0x9, 0xac,0xbf,0x59,0x35,0x68,0x67,0x7c,0xbe,0x12,0xb5,0xec,0xb, +0xf0,0x12,0xa5,0xb7,0x38,0x9c,0xda,0x79,0xda,0xd8,0x22,0x7e,0x24,0x0, 0xff,0xb, +0x1a,0xd0,0x22,0x7d,0x43,0x6c,0xaa,0x6c,0x77,0x7e,0x63,0x6e,0x2, 0x7c,0xb7,0x60, +0x5, 0x1e,0x60,0x14,0x78,0xfb,0x7c,0xb6,0x30,0xe0,0xf, 0x7e,0x50,0x40,0xac,0x57, +0x2e,0x24,0x0, 0x20,0xbd,0x24,0x68,0x9, 0xb, 0xa0,0xb, 0x70,0xbe,0x70,0x4, 0x40, +0xd8,0xa5,0xbf,0x4, 0x4, 0x7e,0xa3,0x6e,0x3, 0x7c,0xba,0x22,0x7c,0xab,0x7e,0x8, +0x69,0x19,0x90,0x21,0x51,0xe4,0x93,0xbc,0xba,0x28,0x2f,0x7e,0x70,0x7, 0xac,0x7a, +0x7f,0x70,0x2d,0xf3,0x7e,0x7b,0xb0,0xbe,0xb0,0x2, 0x68,0x3, 0xb4,0x1, 0xe, 0x74, +0x1, 0x7a,0x7b,0xb0,0x74,0x3, 0x2d,0x13,0x39,0xb0,0x0, 0x1, 0x22,0x74,0x3, 0x7a, +0x7b,0xb0,0x2d,0x31,0x7d,0x20,0x39,0xb1,0x0, 0x1, 0x22,0x7e,0xa3,0x6e,0x2, 0x60, +0x5, 0x1e,0xa0,0x14,0x78,0xfb,0x7c,0xba,0x30,0xe0,0x2, 0xd3,0x22,0xc3,0x22,0x6d, +0x33,0x7a,0x37,0x73,0x44,0xe4,0x7a,0xb3,0x73,0x42,0x7a,0xb3,0x73,0x43,0x7a,0xb3, +0x73,0x3f,0x7a,0xb3,0x73,0x40,0x7a,0xb3,0x73,0x41,0x22,0x7e,0x63,0x69,0x8d,0x7e, +0x73,0x69,0x8c,0xac,0x76,0x7d,0x13,0x1e,0x14,0x7e,0x27,0x67,0xd9,0x2e,0x27,0x67, +0xd7,0xbd,0x21,0x38,0x16,0x1e,0x34,0x1e,0x34,0x7d,0x23,0x2e,0x24,0x0, 0x14,0xbe, +0x27,0x67,0xd7,0x40,0x6, 0xbe,0x37,0x67,0xd9,0x50,0x2, 0xd3,0x22,0xc3,0x22,0xe4, +0x7a,0xb3,0x67,0xf7,0x7a,0xb3,0x67,0xfa,0x7a,0xb3,0x67,0xf8,0x7a,0xb3,0x67,0xf9, +0x7a,0xb3,0x67,0xfb,0x7a,0xb3,0x67,0xfc,0x7e,0x73,0x67,0xd6,0xbe,0x70,0x0, 0x28, +0x2e,0x12,0xb7,0xbc,0x8, 0x6, 0x74,0x1, 0x7a,0xb3,0x67,0xf7,0x7e,0x7, 0x69,0x77, +0x7d,0x30,0x12,0xb7,0xb0,0x8, 0x3, 0x12,0xb7,0xa9,0x7d,0x30,0x3e,0x34,0x3e,0x34, +0x7d,0x21,0x12,0xb7,0xb4,0x8, 0x8, 0xd2,0x26,0x6d,0x33,0x7a,0x37,0x70,0xe2,0x7e, +0x37,0x67,0xe5,0xbe,0x34,0x1, 0xf4,0x8, 0x2d,0x30,0x1d,0x2a,0x30,0x26,0x1b,0x12, +0xb7,0xa9,0x7e,0x37,0x70,0xe2,0xb, 0x34,0x7a,0x37,0x70,0xe2,0xbe,0x34,0x0, 0x5, +0x28,0x8, 0xc2,0x26,0x6d,0x33,0x7a,0x37,0x70,0xe2,0x12,0xb7,0xd4,0xbe,0x34,0x0, +0x64,0x28,0x3, 0x12,0xb7,0xa9,0x7e,0xa3,0x67,0xd6,0xbe,0xa0,0x0, 0x28,0x42,0x12, +0xb7,0xbc,0x8, 0x1a,0x7e,0x73,0x24,0x27,0xa5,0xbf,0x0, 0x8, 0x74,0x1, 0x7a,0xb3, +0x67,0xf8,0x80,0xa, 0xa5,0xbf,0x1, 0x6, 0x74,0x1, 0x7a,0xb3,0x67,0xf9,0x7e,0x37, +0x69,0x77,0x12,0xb7,0xb0,0x8, 0x1a,0x7e,0x73,0x24,0x27,0xa5,0xbf,0x0, 0x8, 0x74, +0x1, 0x7a,0xb3,0x67,0xfb,0x80,0xa, 0xa5,0xbf,0x1, 0x6, 0x74,0x1, 0x7a,0xb3,0x67, +0xfc,0x7e,0xb3,0x67,0xf7,0xbe,0xb0,0x1, 0x68,0x10,0x7e,0xb3,0x67,0xf8,0xbe,0xb0, +0x1, 0x68,0x7, 0x7e,0xb3,0x67,0xf9,0xb4,0x1, 0x29,0xbe,0xa0,0x0, 0x28,0x24,0xbe, +0xa0,0x3, 0x50,0x1f,0x7e,0xb3,0x67,0xd5,0xb4,0x1, 0x18,0x90,0x21,0xfa,0xe4,0x93, +0xbe,0xb3,0x66,0x4b,0x68,0xd, 0xe4,0x7a,0xb3,0x67,0xf7,0x7a,0xb3,0x67,0xf8,0x7a, +0xb3,0x67,0xf9,0xe4,0x7a,0xb3,0x67,0xfd,0x22,0x74,0x1, 0x7a,0xb3,0x67,0xfa,0x22, +0xad,0x31,0x7d,0x24,0x12,0x22,0x71,0xbe,0x37,0x67,0xe5,0x22,0x7e,0x37,0x69,0x71, +0x7e,0x14,0x0, 0x6, 0xad,0x31,0x7e,0x44,0x0, 0x4, 0x7d,0x24,0x12,0x22,0x71,0xbe, +0x37,0x67,0xdf,0x22,0x6d,0x22,0x7d,0x32,0x80,0x12,0x7d,0x52,0x12,0x7e,0x79,0xb, +0xa, 0x10,0xbe,0x14,0xff,0xb0,0x58,0x2, 0xb, 0x34,0xb, 0x24,0x7e,0x17,0x6d,0xfe, +0xbd,0x12,0x38,0xe6,0x22,0x7e,0x37,0x67,0xd9,0x2e,0x37,0x67,0xd7,0xbe,0x37,0x67, +0xf0,0x28,0x2, 0xd3,0x22,0xc3,0x22,0xe4,0x7a,0xb3,0x67,0xfe,0x7a,0xb3,0x67,0xfe, +0x22,0x7e,0xb3,0x67,0xdd,0x7e,0x73,0x67,0xde,0x7c,0xab,0x4c,0x77,0x68,0x18,0x7e, +0xb3,0x69,0x8f,0x14,0xbc,0xb7,0x68,0xf, 0x4c,0xaa,0x68,0xb, 0x7e,0xb3,0x69,0x8e, +0x14,0xbc,0xba,0x68,0x2, 0xd3,0x22,0xc3,0x22,0xc2,0x0, 0x12,0xb9,0x3, 0x50,0x30, +0x6c,0x66,0x80,0x1b,0x74,0x2, 0xac,0xb6,0x9, 0x55,0x66,0x4b,0x9, 0x45,0x66,0x4c, +0x7c,0xb5,0x7c,0x74,0x12,0xb8,0x19,0x50,0x4, 0xd2,0x0, 0x80,0xa, 0xb, 0x60,0x7e, +0x73,0x67,0xd5,0xbc,0x76,0x38,0xdd,0x20,0x0, 0x6, 0x74,0x1, 0x7a,0xb3,0x68,0xa, +0x30,0x27,0x1b,0x5, 0x19,0xe5,0x19,0xbe,0xb0,0x50,0x50,0xe, 0x7e,0x34,0x22,0x9, +0x12,0x30,0xa4,0x3e,0x34,0x7a,0x37,0x67,0xf2,0x22,0xc2,0x27,0x80,0x0, 0x75,0x19, +0x0, 0x22,0x7c,0x3b,0x7d,0x43,0xc2,0x7, 0x7e,0x23,0x72,0x1, 0xa, 0x22,0x7e,0x23, +0x67,0xdd,0x12,0xb8,0xf7,0x18,0x37,0x7e,0x23,0x72,0x2, 0xa, 0x22,0x7e,0x23,0x67, +0xde,0x12,0xb8,0xf7,0x18,0x28,0x12,0xb8,0x11,0x50,0x23,0xbe,0x30,0x0, 0x28,0x1e, +0x7e,0x57,0x72,0x3, 0xb, 0x54,0x7a,0x57,0x72,0x3, 0x7e,0x37,0x72,0x3, 0xbd,0x34, +0x40,0x12,0x6d,0x33,0x7a,0x37,0x72,0x3, 0xd2,0x7, 0x80,0x8, 0x80,0x0, 0x6d,0x33, +0x7a,0x37,0x72,0x3, 0x7e,0x73,0x67,0xdd,0x7a,0x73,0x72,0x1, 0x7e,0x73,0x67,0xde, +0x7a,0x73,0x72,0x2, 0xa2,0x7, 0x22,0xa, 0x32,0x9d,0x32,0x12,0x24,0x5b,0xbe,0x34, +0x0, 0x1, 0x22,0x7e,0x73,0x69,0x89,0x2e,0x70,0xff,0x22,0x7d,0x23,0x12,0x8e,0xf6, +0x28,0x4b,0x7e,0x37,0x67,0xdb,0xbd,0x32,0x8, 0x4, 0xd2,0x1a,0xe4,0x22,0x30,0x1a, +0x2, 0xe4,0x22,0x12,0xb8,0x11,0x50,0x32,0x7e,0x27,0x69,0x6f,0x7d,0x32,0x3e,0x34, +0xbe,0x37,0x67,0xdb,0x48,0x3, 0x74,0x1, 0x22,0x7d,0x32,0x3e,0x34,0x3e,0x34,0xbe, +0x37,0x67,0xdb,0x48,0x3, 0x74,0x2, 0x22,0x7e,0x34,0x0, 0x6, 0xad,0x32,0xbe,0x37, +0x67,0xdb,0x48,0x3, 0x74,0x3, 0x22,0x74,0x4, 0x22,0x74,0xff,0x22,0xc2,0x1a,0xe4, +0x22,0x7c,0x67,0x7e,0xb, 0x70,0xbc,0x7b,0x38,0x1a,0x29,0x70,0x0, 0x2, 0xbc,0x7b, +0x28,0x12,0x29,0x70,0x0, 0x1, 0xbc,0x76,0x38,0xa, 0x29,0x70,0x0, 0x3, 0xbc,0x76, +0x28,0x2, 0xd3,0x22,0xc3,0x22,0x6c,0x44,0xc2,0x1, 0x7e,0x47,0x29,0xed,0x7e,0x7, +0x29,0xef,0x12,0x7b,0x6b,0x40,0x4, 0xd2,0x1, 0x80,0x6, 0xa5,0xbf,0x1, 0x2, 0xd2, +0x1, 0x7e,0xb3,0x29,0x6e,0x60,0x2, 0x41,0x35,0x7e,0xb3,0x29,0xf5,0x4, 0x7a,0xb3, +0x29,0xf5,0x7d,0x34,0x12,0xba,0x79,0xbe,0xb0,0x1, 0x40,0x8, 0x4e,0x40,0x4, 0xe4, +0x7a,0xb3,0x29,0xf5,0xbe,0x44,0x0, 0x0, 0x28,0x10,0x7e,0x17,0x29,0x69,0xbd,0x10, +0x50,0x8, 0x4e,0x40,0x2, 0xe4,0x7a,0xb3,0x29,0xf5,0x7e,0x17,0x29,0x69,0xbd,0x10, +0x50,0x17,0x7e,0xb3,0x29,0xf4,0x4, 0x7a,0xb3,0x29,0xf4,0xbe,0x4, 0xb, 0xb8,0x28, +0x16,0x7e,0xb3,0x29,0xf4,0xb, 0xb2,0x80,0xa, 0x7e,0xb3,0x29,0xf4,0xbe,0xb0,0x0, +0x28,0x5, 0x14,0x7a,0xb3,0x29,0xf4,0x7e,0x53,0x29,0xf4,0xbe,0x50,0xa, 0x40,0x11, +0xe4,0x7a,0xb3,0x29,0xf4,0x7a,0x43,0x29,0xe1,0x74,0x1, 0x7a,0xb3,0x29,0x6e,0x80, +0x14,0x7e,0x73,0x29,0xf5,0xbe,0x70,0x20,0x40,0xb, 0x74,0x20,0x7a,0xb3,0x29,0xf5, +0xe4,0x7a,0xb3,0x29,0xe1,0x7d,0x34,0x7d,0x20,0x2, 0xba,0x3c,0x7d,0x2, 0x12,0xba, +0x79,0x7c,0x7b,0xbe,0x70,0x1, 0x40,0x1a,0x7e,0x34,0x22,0x32,0x7e,0x24,0x0, 0xff, +0xb, 0x1a,0x20,0x7e,0x34,0x0, 0xa, 0xad,0x32,0x1e,0x34,0xbd,0x30,0x38,0x3, 0x75, +0x18,0x1, 0xe5,0x18,0xbe,0xb0,0x0, 0x28,0x7, 0x15,0x18,0xe4,0x7a,0xb3,0x24,0x26, +0x30,0x14,0x3, 0xd2,0x16,0x22,0xc2,0x16,0x22,0x6c,0xaa,0x6c,0x55,0x7e,0x14,0x0, +0x1, 0x7c,0xb5,0x60,0x5, 0x3e,0x14,0x14,0x78,0xfb,0x5d,0x13,0x68,0x2, 0xb, 0xa0, +0xb, 0x50,0xbe,0x50,0x10,0x40,0xe6,0x7c,0xba,0x22,0xca,0x79,0x7c,0xf7,0x7c,0xeb, +0x7e,0xb3,0x71,0x36,0xbe,0xb0,0x1, 0x78,0x2, 0x61,0x95,0xe5,0x1b,0x70,0x2, 0x61, +0x95,0x7e,0xb3,0x6d,0xfb,0x70,0x2, 0x61,0x95,0x12,0xbb,0x98,0x7c,0xbe,0x7c,0x7f, +0x12,0xb9,0x86,0x12,0xbe,0x1e,0x7e,0xb3,0x29,0x6e,0x1b,0xb1,0x68,0x1d,0x4, 0x68, +0x2, 0x61,0x95,0x7e,0x73,0x29,0x6b,0x7a,0x73,0x29,0x6c,0xe4,0x7a,0xb3,0x29,0x6d, +0x6c,0xaa,0x12,0xbd,0xd0,0x78,0xfb,0x74,0x2, 0x61,0x91,0x7e,0x43,0x29,0x6c,0x7e, +0x50,0x26,0xac,0x45,0x7d,0x32,0x2e,0x34,0x29,0x70,0x7e,0x39,0xb0,0x4, 0x7a,0x39, +0xb0,0x9, 0x72,0x29,0x70,0xbe,0x70,0x2, 0x50,0x2, 0x61,0x95,0xe4,0x19,0xb2,0x29, +0x70,0x49,0x12,0x29,0x71,0x2e,0x17,0x29,0xe9,0xbe,0x14,0x7f,0xff,0x50,0xb, 0x7d, +0x32,0x2e,0x34,0x29,0x71,0x1b,0x38,0x10,0x80,0x8, 0x7e,0x34,0x7f,0xff,0x59,0x32, +0x29,0x71,0x49,0x32,0x29,0x73,0xbe,0x37,0x29,0xe9,0x50,0x8, 0x7e,0x37,0x29,0xe9, +0x59,0x32,0x29,0x73,0x7e,0x37,0x29,0xed,0x12,0xba,0x79,0xa, 0x4b,0x7e,0xa3,0x29, +0x6c,0x7e,0x50,0x26,0xac,0x5a,0x2e,0x24,0x29,0x75,0xb, 0x28,0x30,0x2d,0x34,0x1b, +0x28,0x30,0xbe,0xa0,0x2, 0x50,0x5, 0x7c,0xba,0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x29, +0x6c,0x12,0xbc,0x89,0x38,0x1f,0x12,0xbb,0xe2,0xbe,0xb0,0xff,0x68,0x12,0x30,0x15, +0xf, 0x7e,0x73,0x29,0x6b,0x12,0xbd,0xf6,0x12,0x2a,0x60,0xe4,0x7a,0xb3,0x29,0xe1, +0xe4,0x7a,0xb3,0x29,0x6e,0xda,0x79,0x22,0xca,0x79,0x7e,0xb3,0x69,0x83,0x70,0xe, +0x7e,0x34,0x5, 0xdc,0x7a,0x37,0x29,0xe5,0x7e,0x34,0x22,0x32,0x80,0x2a,0x7e,0x34, +0x0, 0x32,0x7a,0x37,0x29,0xe5,0x7e,0x74,0x22,0x32,0x7d,0x37,0x12,0x30,0xa4,0x7e, +0x24,0x0, 0x3, 0x8d,0x32,0x7a,0x37,0x29,0x69,0x12,0xbd,0xc2,0x50,0x11,0x7e,0x34, +0x5, 0xdc,0x7a,0x37,0x29,0xe5,0x7d,0x37,0x12,0x30,0xa4,0x7a,0x37,0x29,0x69,0xda, +0x79,0x22,0x6c,0x77,0x7e,0xa0,0xff,0x7e,0x78,0xff,0xff,0x6d,0x44,0x6c,0x66,0x7e, +0x14,0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0x14,0x14,0x78,0xfb,0x7e,0xb3,0x29,0x68, +0xa, 0x2b,0x5d,0x21,0xbe,0x24,0x0, 0x0, 0x8, 0xd, 0x7e,0x24,0xff,0xff,0x7e,0x30, +0x26,0xac,0x36,0x59,0x21,0x29,0x71,0x12,0xbc,0x7f,0x6d,0x0, 0xbf,0x7, 0x50,0x8, +0x7f,0x70,0x49,0x42,0x29,0x73,0x7c,0x76,0xb, 0x60,0xa5,0xbe,0x3, 0xc1,0x7e,0x63, +0x29,0x6b,0xbc,0x67,0x68,0x46,0x12,0xbc,0x7f,0x7d,0xc1,0x1e,0xc4,0x1e,0xc4,0x7e, +0xd4,0x0, 0x3, 0xad,0xdc,0x6d,0xcc,0xbf,0x76,0x50,0xf, 0x7e,0xd4,0x22,0x2c,0x7e, +0xc4,0x0, 0xff,0xb, 0x6a,0x0, 0xbd,0x4, 0x38,0x20,0x1e,0x14,0x6d,0x0, 0xbf,0x70, +0x50,0x1a,0x7e,0x50,0x26,0xac,0x56,0x49,0x12,0x29,0x73,0x7e,0xf4,0x22,0x2c,0x7e, +0xe4,0x0, 0xff,0xb, 0x7a,0x20,0xbd,0x12,0x28,0x2, 0x7c,0xa7,0x7c,0xba,0x22,0x7e, +0x50,0x26,0xac,0x56,0x49,0x12,0x29,0x71,0x22,0x90,0x22,0x34,0xe4,0x93,0xbe,0xb3, +0x29,0x6d,0x22,0x12,0xbd,0x6, 0xc2,0x14,0x7e,0xb3,0x29,0x6e,0x60,0x67,0x12,0x7b, +0x67,0x40,0x10,0x7e,0xa3,0x29,0x6c,0x74,0x26,0xa4,0x9, 0x75,0x29,0x70,0xbe,0x70, +0x1, 0x40,0x52,0x7e,0x73,0x29,0x6c,0xb, 0x70,0xbe,0x70,0x3, 0x40,0x2, 0x6c,0x77, +0x7e,0x14,0x0, 0x1, 0x7c,0xb7,0x60,0x5, 0x3e,0x14,0x14,0x78,0xfb,0x7e,0x63,0x29, +0x68,0xa, 0x26,0x5d,0x21,0xbe,0x24,0x0, 0x0, 0x8, 0x9, 0xb, 0x70,0xbe,0x70,0x3, +0x40,0x2, 0x6c,0x77,0x7e,0x63,0x29,0x6b,0xbc,0x67,0x78,0x9, 0x7e,0xb3,0x29,0x6d, +0x4, 0x7a,0xb3,0x29,0x6d,0x12,0xbc,0x89,0x7e,0xb3,0x73,0x8, 0x38,0x4, 0x7c,0x76, +0x80,0x0, 0x2, 0x55,0x87,0x22,0x7e,0x27,0x29,0xef,0x7e,0x37,0x29,0x69,0xbd,0x32, +0x50,0x20,0x7e,0xa3,0x29,0x6c,0x12,0xbd,0x6f,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb, +0x7c,0xb9,0x4e,0xb3,0x29,0x68,0x7a,0xb3,0x29,0x68,0x74,0x5, 0xa, 0x3a,0x19,0xb3, +0x29,0xe2,0x6c,0xaa,0xa, 0x3a,0x9, 0xb3,0x29,0xe2,0xbe,0xb0,0x0, 0x28,0xa, 0xa, +0x4a,0x2e,0x44,0x29,0xe2,0x14,0x7a,0x49,0xb0,0xa, 0x3a,0x9, 0xb3,0x29,0xe2,0x70, +0x16,0x12,0xbd,0x6f,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7c,0xb9,0x64,0xff,0x5e, +0xb3,0x29,0x68,0x7a,0xb3,0x29,0x68,0xb, 0xa0,0xbe,0xa0,0x3, 0x40,0xc6,0x22,0x7e, +0x44,0x0, 0x1, 0x7c,0xba,0x22,0x7c,0xab,0x6c,0x77,0x7e,0x63,0x29,0xf3,0xbc,0x67, +0x78,0x4, 0x6c,0x66,0x80,0x27,0x12,0xbd,0x6f,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb, +0x7e,0x63,0x6d,0xfc,0xa, 0x26,0x5d,0x24,0x68,0x6, 0x7e,0x60,0x1, 0x12,0xbd,0xb8, +0x7e,0x63,0x6d,0xfd,0xa, 0x26,0x5d,0x24,0x68,0x6, 0x7e,0x60,0x1, 0x12,0xbd,0xb8, +0xb, 0x70,0xbe,0x70,0x3, 0x40,0xc3,0x22,0x7e,0x50,0x26,0xac,0x57,0x19,0x62,0x29, +0x7c,0x22,0x7e,0x37,0x67,0xdb,0xbe,0x34,0x3, 0xe8,0x8, 0x2, 0xd3,0x22,0xc3,0x22, +0x6d,0x33,0x7e,0x90,0x26,0xac,0x9a,0x59,0x34,0x29,0x71,0x59,0x34,0x29,0x73,0x59, +0x34,0x29,0x75,0x59,0x34,0x29,0x77,0x59,0x34,0x29,0x79,0xe4,0x19,0xb4,0x29,0x70, +0xb, 0xa0,0xbe,0xa0,0x3, 0x22,0xca,0xf8,0x7c,0xfb,0xbe,0xf0,0x3, 0x50,0x1c,0xbe, +0x70,0x3, 0x50,0x17,0xd2,0x2, 0x12,0x2f,0x50,0x12,0x3c,0xc7,0x7e,0xb3,0x73,0x8, +0x7c,0x7f,0x12,0x55,0x87,0x7a,0xf3,0x29,0x6b,0xd2,0x12,0xda,0xf8,0x22,0xc2,0x13, +0xd2,0x15,0x7e,0x37,0x29,0xe5,0xbe,0x37,0x29,0xef,0x50,0x2, 0xd2,0x13,0x30,0x20, +0x4, 0x74,0x64,0x80,0x7, 0x7e,0xb3,0x29,0xe7,0x60,0x5, 0x14,0x7a,0xb3,0x29,0xe7, +0x30,0x13,0x5, 0xe4,0x7a,0xb3,0x29,0xe7,0x7e,0xb3,0x29,0xe7,0x60,0x2, 0xc2,0x15, +0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0xbe,0xd0,0x80,0x78,0x1e,0x7e,0xe0,0xff,0x6c, +0xff,0x74,0x26,0xac,0xbf,0x9, 0x75,0x29,0x6f,0xbc,0x7e,0x38,0x4, 0x7c,0xe7,0x7c, +0xdf,0xb, 0xf0,0xbe,0xf0,0x3, 0x78,0xe9,0x80,0x20,0xbe,0xd0,0x81,0x78,0x1b,0x6c, +0xee,0x6c,0xff,0x74,0x26,0xac,0xbf,0x9, 0x75,0x29,0x6f,0xbc,0x7e,0x40,0x4, 0x7c, +0xe7,0x7c,0xdf,0xb, 0xf0,0xbe,0xf0,0x3, 0x78,0xe9,0xbe,0xd0,0x3, 0x40,0x2, 0x6c, +0xdd,0x7e,0x73,0x29,0x6b,0xbc,0x7d,0x68,0x5, 0x7c,0xbd,0x12,0xbd,0xf6,0x7a,0xd3, +0x71,0x62,0xda,0x79,0xda,0xd8,0x22,0x7c,0x37,0x7c,0x2b,0x7e,0xb3,0x6d,0xfb,0x70, +0x2, 0xe1,0x5d,0x12,0x7d,0x87,0x7e,0xb3,0x29,0xf3,0xbc,0xba,0x78,0x2, 0xe1,0x5d, +0xa5,0xba,0x0, 0x1b,0x7e,0x90,0x26,0xac,0x9a,0x49,0xf4,0x29,0x8b,0x49,0xe4,0x29, +0x89,0xa5,0xbb,0x3, 0x15,0x49,0xf4,0x29,0x93,0x49,0xe4,0x29,0x91,0x80,0xb, 0x74, +0x26,0xa4,0x49,0xf5,0x29,0x8f,0x49,0xe5,0x29,0x8d,0x7e,0x73,0x69,0x8d,0x7a,0x73, +0x5d,0x8, 0x7e,0x73,0x69,0x8c,0x7a,0x73,0x5d,0x7, 0xe4,0x7a,0xb3,0x5d,0x9, 0x7a, +0xb3,0x5d,0xa, 0x6d,0x33,0x7a,0x37,0x5d,0x11,0x7e,0x1f,0x22,0xe0,0x7a,0x37,0x5d, +0xb, 0x7d,0x3f,0x7a,0x37,0x5d,0xd, 0x7e,0x1f,0x22,0xe0,0x7a,0x37,0x5d,0xf, 0x7e, +0x8, 0x5d,0x7, 0x12,0x8, 0xe5,0x7e,0x37,0x6d,0xfe,0x6c,0x55,0xa, 0x15,0x2d,0x13, +0x3e,0x14,0x7f,0x27,0x2d,0x51,0xb, 0x2a,0x0, 0x7e,0x2f,0x22,0xe0,0x2d,0x51,0xb, +0x2a,0x10,0x9d,0x10,0x1b,0x2a,0x10,0xb, 0x50,0xa5,0xbd,0x4, 0xdf,0x22,0x7c,0xab, +0x7e,0x50,0xa, 0xac,0x57,0x9, 0x62,0x6f,0xb6,0x7e,0x50,0x27,0xac,0x57,0x49,0x2, +0x6f,0x18,0xb, 0x4, 0x7e,0x50,0x8, 0xac,0x5a,0x49,0x22,0x0, 0xc9,0x7a,0x27,0x29, +0xed,0x7e,0x50,0x8, 0xac,0x5a,0x49,0x22,0x0, 0xc7,0x7a,0x27,0x29,0xeb,0x7e,0x50, +0x8, 0xac,0x5a,0x9, 0xb2,0x0, 0xcd,0x7a,0xb3,0x29,0xf1,0x7e,0x50,0x8, 0xac,0x5a, +0x9, 0xb2,0x0, 0xce,0x7a,0xb3,0x29,0xf2,0x74,0x8, 0xa4,0x49,0x15,0x0, 0xcb,0x7c, +0xb6,0x60,0x5, 0x1e,0x4, 0x14,0x78,0xfb,0x8d,0x10,0x7a,0x17,0x29,0xef,0x74,0x27, +0xac,0xb7,0x9, 0x75,0x6f,0x12,0x7a,0x73,0x29,0xe8,0x22,0x7e,0xb3,0x29,0xe1,0x22, +0x7c,0xab,0x6c,0x77,0x7e,0x50,0x26,0xac,0x57,0x9, 0x62,0x29,0x6f,0xbc,0x6a,0x68, +0x7, 0xb, 0x70,0xbe,0x70,0x3, 0x40,0xec,0xa5,0xbf,0x3, 0x6, 0x7a,0xa3,0x29,0x6f, +0xd3,0x22,0xc3,0x22,0xca,0x79,0x7e,0x68,0x15,0xa0,0x7e,0xb3,0x73,0x8, 0xb4,0x3, +0x4, 0x7e,0x68,0x1e,0x70,0x7e,0x73,0x69,0x8d,0x7a,0x73,0x5d,0x36,0x7e,0x73,0x69, +0x8c,0x7a,0x73,0x5d,0x35,0xe4,0x7a,0xb3,0x5d,0x37,0x7a,0xb3,0x5d,0x38,0x6d,0x33, +0x7a,0x37,0x5d,0x3f,0x6c,0xff,0x7e,0x70,0x26,0xac,0x7f,0x9, 0xb3,0x29,0x7c,0x70, +0x2, 0x1, 0xcf,0x7e,0xb3,0x73,0x8, 0xb4,0x3, 0xa, 0x49,0xf3,0x29,0x93,0x49,0xe3, +0x29,0x91,0x80,0x8, 0x49,0xf3,0x29,0x8b,0x49,0xe3,0x29,0x89,0x7d,0x3f,0x7a,0x37, +0x5d,0x39,0x7d,0x3d,0x7a,0x37,0x5d,0x3b,0x7d,0x3f,0x7a,0x37,0x5d,0x3d,0x12,0xc0, +0xdb,0x7e,0xb7,0x6d,0xfe,0x6c,0xee,0xa, 0xe, 0x2d,0xb, 0x3e,0x4, 0x7f,0x16,0x2d, +0x30,0xb, 0x1a,0x10,0x7f,0x17,0x12,0xc0,0xe2,0x78,0xec,0x12,0x7b,0x67,0x50,0x44, +0x74,0x26,0xac,0xbf,0x49,0x35,0x29,0x8f,0x7d,0xa3,0x7a,0xa7,0x5d,0x39,0x7e,0xa4, +0x1a,0x8, 0x7a,0xa7,0x5d,0x3b,0x74,0x26,0xac,0xbf,0x49,0x35,0x29,0x8f,0x7d,0xa3, +0x7a,0xa7,0x5d,0x3d,0x12,0xc0,0xdb,0x6c,0xee,0xa, 0xe, 0x2d,0xb, 0x3e,0x4, 0x49, +0x10,0x1a,0x8, 0x74,0x26,0xac,0xbf,0x49,0x35,0x29,0x8f,0x49,0x25,0x29,0x8d,0x12, +0xc0,0xe2,0x78,0xe5,0x6c,0xaa,0x7e,0x70,0x26,0xac,0x7f,0x19,0xa3,0x29,0x7c,0xb, +0xf0,0xbe,0xf0,0x3, 0x50,0x2, 0x1, 0x26,0xda,0x79,0x22,0x7e,0x8, 0x5d,0x35,0x2, +0x8, 0xe5,0x2d,0x30,0xb, 0x1a,0xa0,0x9d,0xa1,0x1b,0x1a,0xa0,0xb, 0xe0,0xbe,0xe0, +0x4, 0x22,0xca,0xf8,0x7c,0xab,0xc2,0x2, 0x12,0xc1,0x90,0xac,0x67,0x9, 0xf3,0x29, +0x6f,0x7c,0xba,0x12,0xc1,0x25,0x6c,0xaa,0x6c,0x77,0x7e,0x50,0x26,0xac,0x57,0x19, +0xa2,0x29,0x7b,0xb, 0x70,0xa5,0xbf,0x3, 0xf1,0x30,0x2, 0x5, 0x7c,0xbf,0x12,0x3c, +0xcf,0xd3,0xda,0xf8,0x22,0x7c,0x9b,0x7e,0x24,0x0, 0x1, 0x7c,0xb9,0x60,0x5, 0x3e, +0x24,0x14,0x78,0xfb,0x7e,0x83,0x6d,0xfc,0xa, 0x38,0x5d,0x32,0x68,0xb, 0x12,0x46, +0xd1,0x7e,0x83,0x29,0x6b,0x7a,0x83,0x29,0xf3,0x6c,0xaa,0x7e,0xb3,0x29,0xf3,0xbc, +0xba,0x78,0x8, 0x6c,0x88,0x12,0xc1,0x86,0xe4,0x80,0x1f,0x7e,0x24,0x0, 0x1, 0x7c, +0xb9,0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0x7e,0xb3,0x6d,0xfc,0xa, 0x3b,0x5d,0x32, +0x68,0xc, 0x7e,0x80,0x1, 0x12,0xc1,0x86,0x74,0x1, 0x19,0xb3,0x29,0x7c,0xb, 0xa0, +0xbe,0xa0,0x3, 0x40,0xc6,0x22,0x7e,0x70,0x26,0xac,0x7a,0x19,0x83,0x29,0x7b,0x22, +0x7e,0x63,0x29,0x6b,0x7e,0x70,0x26,0x22,0x7e,0x34,0x65,0xe1,0x1e,0x34,0x3e,0x34, +0x7a,0x17,0x66,0x21,0x7a,0x37,0x66,0x25,0x7e,0x34,0x23,0x34,0x7a,0x37,0x66,0x23, +0x7e,0x73,0x69,0x8c,0x7a,0x73,0x66,0x1e,0x7e,0x73,0x69,0x8d,0x7a,0x73,0x66,0x1d, +0x7e,0x37,0x69,0x6f,0x7a,0x37,0x66,0x27,0x7e,0x37,0x69,0x71,0x7a,0x37,0x66,0x29, +0x7e,0x37,0x69,0x79,0x7a,0x37,0x66,0x2b,0x7e,0x37,0x69,0x7b,0x7a,0x37,0x66,0x2d, +0x74,0x1, 0x7a,0xb3,0x66,0x1f,0x7a,0xb3,0x66,0x20,0x7e,0x8, 0x66,0x1d,0x7e,0x18, +0x66,0x2f,0x12,0x3, 0x1d,0x7e,0x37,0x66,0x3b,0x7a,0x37,0x69,0x87,0x7e,0x27,0x66, +0x35,0xbe,0x24,0x0, 0x0, 0x8, 0x6, 0x7e,0x7, 0x66,0x35,0x80,0x6, 0x6d,0x0, 0x9e, +0x7, 0x66,0x35,0x7e,0x37,0x66,0x39,0xbe,0x34,0x0, 0x0, 0x8, 0x6, 0x7e,0x17,0x66, +0x39,0x80,0x6, 0x6d,0x11,0x9e,0x17,0x66,0x39,0xbd,0x10,0x8, 0x12,0xbe,0x34,0x0, +0x0, 0x8, 0x5, 0x7e,0x37,0x66,0x39,0x22,0x6d,0x33,0x9e,0x37,0x66,0x39,0x22,0xbe, +0x24,0x0, 0x0, 0x8, 0x6, 0x7e,0x37,0x66,0x35,0x80,0x6, 0x6d,0x33,0x9e,0x37,0x66, +0x35,0x22,0x7c,0x5b,0x7e,0x73,0x71,0xbe,0xa5,0xbf,0x0, 0xe, 0x7e,0x63,0x67,0xdd, +0xa, 0x17,0x19,0x61,0x71,0xe2,0x74,0x1, 0x80,0x20,0x7e,0xb3,0x67,0xdd,0x7e,0x8, +0x71,0xe2,0x12,0xc2,0xef,0x40,0x17,0x7e,0x43,0x67,0xdd,0x7e,0x73,0x71,0xbe,0xa, +0x37,0x19,0x43,0x71,0xe2,0x7e,0xb3,0x71,0xbe,0x4, 0x7a,0xb3,0x71,0xbe,0x7e,0x73, +0x71,0xbb,0xa5,0xbf,0x0, 0xe, 0x7e,0x63,0x67,0xde,0xa, 0x17,0x19,0x61,0x71,0xbf, +0x74,0x1, 0x80,0x20,0x7e,0xb3,0x67,0xde,0x7e,0x8, 0x71,0xbf,0x12,0xc2,0xef,0x40, +0x17,0x7e,0x43,0x67,0xde,0x7e,0x73,0x71,0xbb,0xa, 0x37,0x19,0x43,0x71,0xbf,0x7e, +0xb3,0x71,0xbb,0x4, 0x7a,0xb3,0x71,0xbb,0x7e,0xa3,0x71,0xbe,0xbc,0xa5,0x50,0x18, +0x7e,0x73,0x71,0xbb,0xbc,0x75,0x50,0x10,0x74,0x3, 0xac,0x5b,0xe, 0x24,0xa, 0x17, +0xa, 0x3a,0x2d,0x31,0xbd,0x32,0x48,0x5, 0x12,0x97,0x99,0xd3,0x22,0xc3,0x22,0x6c, +0x66,0x80,0xd, 0x7e,0xb, 0xa0,0xbc,0xab,0x78,0x2, 0xd3,0x22,0xb, 0x14,0xb, 0x60, +0xbc,0x76,0x38,0xef,0xc3,0x22,0x7c,0xab,0xbe,0xa0,0x1, 0x78,0x41,0x12,0x35,0xb6, +0x7e,0x34,0x0, 0x96,0x7a,0x37,0x69,0x6d,0x7e,0x34,0x0, 0x8c,0x7a,0x37,0x69,0x6f, +0x7e,0x34,0xff,0x38,0x7a,0x37,0x69,0x71,0x7e,0x34,0x1, 0x2c,0x7a,0x37,0x69,0x79, +0x7e,0x34,0xfe,0xd4,0x7a,0x37,0x69,0x7b,0x12,0xc3,0x8a,0x68,0x4c,0x7e,0x34,0x2, +0x58,0x7a,0x37,0x69,0x73,0x7e,0x34,0x2, 0x26,0x7a,0x37,0x69,0x75,0x22,0xbe,0xa0, +0x2, 0x78,0x36,0x7e,0xb3,0x73,0x1f,0xb4,0x3, 0x18,0x74,0x5c,0x7a,0xb3,0x69,0x6c, +0x7e,0x34,0x0, 0x5c,0x7a,0x37,0x69,0x6d,0x7a,0x37,0x69,0x6f,0x7e,0x34,0xff,0xa4, +0x80,0x13,0x12,0x35,0xb6,0x7e,0x34,0x1, 0x2c,0x7a,0x37,0x69,0x6d,0x7a,0x37,0x69, +0x6f,0x7e,0x34,0xfe,0xd4,0x7a,0x37,0x69,0x71,0x22,0x7e,0xb3,0x70,0xea,0xbe,0xb0, +0xaa,0x22,0xca,0x3b,0x7e,0xb3,0x73,0x0, 0xbe,0xb0,0x1, 0x78,0x2, 0xa1,0xc, 0x7e, +0xb3,0x67,0xd5,0xf5,0x26,0x6c,0xff,0x81,0x63,0x12,0xc5,0x6a,0x7e,0x73,0x69,0x8c, +0xbc,0x7e,0x78,0x2, 0x81,0x61,0x12,0xc5,0x1f,0xb, 0x7a,0x30,0x7d,0xc3,0x12,0xc5, +0x3c,0x4c,0xee,0x78,0x2, 0x6d,0xee,0x12,0xc5,0x17,0x78,0x2, 0x6d,0xff,0x4c,0xdd, +0x78,0x2, 0x6d,0x0, 0x12,0xc5,0xf, 0x78,0x2, 0x6d,0x11,0xbe,0xe4,0x0, 0x46,0x8, +0x2, 0xb, 0xc0,0xbe,0xf4,0x0, 0x46,0x8, 0x2, 0xb, 0xc0,0xbe,0x4, 0x0, 0x46,0x8, +0x2, 0xb, 0xc0,0xbe,0x14,0x0, 0x46,0x8, 0x2, 0xb, 0xc0,0xbe,0xc0,0x2, 0x40,0x4, +0xd2,0x0, 0x80,0x2e,0x4c,0xee,0x68,0x16,0x7e,0xb3,0x69,0x8e,0x14,0xbc,0xbe,0x68, +0xd, 0x4c,0xdd,0x68,0x9, 0x7e,0xb3,0x69,0x8f,0x14,0xbc,0xbd,0x78,0x14,0xbe,0xc4, +0x1, 0x90,0x8, 0xe, 0xbe,0xc0,0x0, 0x28,0x9, 0x7e,0xb3,0x73,0x1f,0xb4,0x1, 0x2, +0xd2,0x0, 0x20,0x0, 0x2c,0x7d,0xd3,0x7e,0xb3,0x73,0x1f,0xb4,0x3, 0x4, 0x7d,0x5d, +0x80,0xb, 0x7e,0xb3,0x73,0x1f,0xb4,0x1, 0x15,0x7d,0x5d,0xe, 0x54,0xe, 0x54,0xe, +0x54,0x7d,0xb4,0x3e,0xb4,0x7e,0x1f,0x22,0xe0,0x2d,0x3b,0x1b,0x1a,0x50,0x12,0x89, +0xc3,0xb, 0xf0,0xe5,0x26,0xbc,0xbf,0x28,0x2, 0x61,0xa9,0x7e,0xb3,0x73,0x1f,0xb4, +0x3, 0x2, 0x80,0x2, 0xa1,0xc, 0x7e,0xb3,0x67,0xd6,0xf5,0x26,0x6c,0xff,0xa1,0x4, +0x74,0x2, 0xac,0xbf,0x9, 0xe5,0x66,0x87,0x9, 0xd5,0x66,0x88,0x7e,0x73,0x69,0x8c, +0xbc,0x7e,0x68,0x6e,0x12,0xc5,0x1f,0xb, 0x7a,0x30,0x12,0xc5,0x3c,0x4c,0xee,0x78, +0x2, 0x6d,0xee,0x12,0xc5,0x17,0x78,0x2, 0x6d,0xff,0x4c,0xdd,0x78,0x2, 0x6d,0x0, +0x12,0xc5,0xf, 0x78,0x2, 0x6d,0x11,0xbe,0xe4,0xff,0xba,0x58,0x2, 0xb, 0xc0,0xbe, +0xf4,0xff,0xba,0x58,0x2, 0xb, 0xc0,0xbe,0x4, 0xff,0xba,0x58,0x2, 0xb, 0xc0,0xbe, +0x14,0xff,0xba,0x58,0x2, 0xb, 0xc0,0xbe,0xc0,0x2, 0x40,0x2, 0xd2,0x0, 0x20,0x0, +0x21,0x12,0x24,0x5b,0x7d,0xd3,0x7d,0x5d,0xe, 0x54,0xe, 0x54,0x6e,0x54,0xff,0xff, +0xb, 0x54,0x7d,0xb4,0x3e,0xb4,0x7e,0x1f,0x22,0xe0,0x2d,0x3b,0x1b,0x1a,0x50,0x12, +0x89,0xc3,0xb, 0xf0,0xe5,0x26,0xbc,0xbf,0x28,0x2, 0x81,0x80,0xda,0x3b,0x22,0x7e, +0xb3,0x69,0x8d,0x14,0xbc,0xbd,0x22,0x7e,0xb3,0x69,0x8c,0x14,0xbc,0xbe,0x22,0x6c, +0xcc,0xc2,0x0, 0x7e,0x33,0x69,0x8d,0x7c,0x9e,0xac,0x93,0xa, 0x5d,0x2d,0x45,0x7d, +0x24,0x3e,0x24,0x7e,0x5f,0x22,0xe0,0x7f,0x75,0x2d,0xf2,0x22,0xa, 0x53,0x7d,0x14, +0x9d,0x15,0x3e,0x14,0x2d,0x1b,0x7d,0xa, 0xb, 0xa, 0xe0,0x2d,0x54,0x3e,0x54,0x7f, +0x5, 0x2d,0x15,0xb, 0xa, 0xf0,0x7d,0x54,0x1b,0x54,0x3e,0x54,0x7f,0x5, 0x2d,0x15, +0xb, 0xa, 0x0, 0x2d,0xb2,0x69,0x15,0x0, 0x2, 0x22,0x74,0x2, 0xac,0xbf,0x9, 0xe5, +0x66,0x4b,0x9, 0xd5,0x66,0x4c,0x22,0x6c,0xaa,0x7e,0x70,0x3, 0xac,0x7a,0x9, 0xb3, +0x6e,0xef,0x60,0x8, 0x74,0x1, 0x7a,0xb3,0x69,0x6a,0x80,0x7, 0xb, 0xa0,0xbe,0xa0, +0xa, 0x40,0xe6,0xe4,0x7a,0xb3,0x69,0x6a,0x22,0x7e,0xb3,0x67,0xd5,0x70,0x26,0x7e, +0xb3,0x69,0x5f,0x70,0x20,0x6c,0xaa,0x7e,0x70,0xff,0x7e,0x90,0x3, 0xac,0x9a,0x19, +0x74,0x6e,0xee,0xe4,0x19,0xb4,0x6e,0xef,0x74,0x4, 0x19,0xb4,0x6e,0xf0,0xb, 0xa0, +0xbe,0xa0,0xa, 0x78,0xe2,0x22,0xca,0x79,0x7f,0x70,0x7e,0x3, 0x69,0x8d,0x7e,0x93, +0x67,0xd5,0x7e,0x6f,0x22,0xe0,0x6c,0x11,0x6c,0x88,0x6c,0xff,0x80,0xd, 0xa, 0x1f, +0x12,0xc6,0x8a,0xbc,0x78,0x40,0x2, 0x7c,0x87,0xb, 0xf0,0xbc,0x9f,0x38,0xef,0x7e, +0xf0,0x1, 0xc1,0x77,0x75,0x28,0x0, 0x6d,0xbb,0x6d,0x99,0x7d,0xa9,0x6c,0xee,0x80, +0x3a,0x7e,0x30,0x2, 0xac,0x3e,0x9, 0xb1,0x66,0x4b,0xf5,0x26,0x9, 0xb1,0x66,0x4c, +0xf5,0x27,0xa, 0x1e,0x12,0xc6,0x8a,0xbc,0x7f,0x78,0x1e,0x5, 0x28,0xe5,0x26,0xa, +0x1b,0x2d,0xa1,0xe5,0x27,0xa, 0x1b,0x2d,0x91,0xe5,0x26,0x7e,0x71,0x27,0x12,0x81, +0x9d,0x7d,0x83,0xbd,0xb8,0x58,0x2, 0x7d,0xb8,0xb, 0xe0,0xbc,0x9e,0x38,0xc2,0xe5, +0x28,0xbe,0xb0,0x0, 0x28,0x2f,0xe5,0x28,0xa, 0x8b,0x7d,0x3a,0x8d,0x38,0x7d,0xa3, +0x8d,0x98,0x12,0xc6,0x82,0x19,0xa1,0x6f,0xec,0x7d,0x39,0x12,0xc6,0x82,0x19,0xa1, +0x6f,0xed,0xa, 0x30,0xad,0x3a,0x7d,0x13,0x2d,0x19,0x3e,0x14,0x7f,0x16,0x2d,0x31, +0x1b,0x1a,0xb0,0xb, 0x10,0xb, 0xf0,0xbc,0x8f,0x40,0x2, 0xa1,0xf4,0x7c,0xb1,0xda, +0x79,0x22,0x7c,0xa7,0x7e,0x30,0x2, 0xac,0x31,0x22,0x7f,0x17,0x2d,0x31,0x7e,0x1b, +0x70,0x22,0x7c,0x9b,0x7f,0x71,0x7f,0x60,0x7e,0x34,0x28,0x23,0x7e,0x24,0x0, 0xff, +0x7e,0x14,0x5d,0x11,0x74,0x30,0x12,0x23,0x65,0x7e,0x58,0x5d,0x11,0x7c,0xb9,0x7e, +0x71,0x39,0x12,0x81,0x9d,0x7d,0x3, 0xe5,0x3a,0x7e,0x71,0x3b,0x12,0x81,0x9d,0x2d, +0x30,0xe, 0x34,0x7f,0x5, 0x7e,0x50,0x8, 0xb, 0xa, 0x50,0xbd,0x53,0x58,0xf, 0x69, +0x30,0x0, 0x2, 0x1b,0x6a,0x30,0x69,0x30,0x0, 0x4, 0x1b,0x7a,0x30,0x22,0x2e,0x14, +0x0, 0x6, 0x1b,0x50,0x78,0xe2,0x22,0x6c,0xaa,0x80,0x12,0x7e,0x70,0x9, 0xac,0x7a, +0x9, 0xb3,0x66,0xcd,0xbe,0xb0,0x10,0x28,0x2, 0xd3,0x22,0xb, 0xa0,0x7e,0xb3,0x67, +0xeb,0xbc,0xba,0x38,0xe6,0xc3,0x22,0xca,0x3b,0x7e,0xa0,0x64,0x6c,0x77,0x80,0x6c, +0xa, 0x27,0xb, 0x24,0x7c,0x65,0x80,0x5a,0x7e,0xf0,0x2, 0xac,0xf6,0x9, 0xb7,0x66, +0x4b,0xa, 0xb, 0x7e,0xd0,0x2, 0xac,0xd7,0x9, 0xb6,0x66,0x4b,0xa, 0x2b,0x7d,0x12, +0x9d,0x10,0xbe,0x14,0x0, 0x0, 0x8, 0x4, 0x9d,0x20,0x80,0x4, 0x6d,0x22,0x9d,0x21, +0x9, 0x47,0x66,0x4c,0xa, 0x44,0x9, 0x46,0x66,0x4c,0xa, 0x14,0x7d,0x1, 0x9d,0x4, +0xbe,0x4, 0x0, 0x0, 0x8, 0x4, 0x9d,0x14,0x80,0x4, 0x6d,0x11,0x9d,0x10,0x7c,0x43, +0xbc,0x45,0x50,0x4, 0x7c,0x35,0x80,0x2, 0x7c,0x34,0xbc,0xa3,0x28,0x2, 0x7c,0xa3, +0xb, 0x60,0x7e,0x23,0x67,0xd5,0xbc,0x26,0x38,0x9e,0xb, 0x70,0x7e,0xb3,0x67,0xd5, +0xbc,0xb7,0x38,0x8c,0xbe,0xa0,0x64,0x78,0x2, 0x6c,0xaa,0x7c,0xba,0xda,0x3b,0x22, +0xca,0x3b,0x7c,0x45,0x7c,0x57,0x7c,0x7b,0xe4,0x12,0xc9,0xb6,0x75,0x3e,0x0, 0x7e, +0xf4,0x7f,0xff,0xbc,0x67,0x28,0x4, 0x7c,0xd7,0x80,0x2, 0x7c,0xd6,0xbc,0x67,0x50, +0x4, 0x7c,0xa7,0x80,0x2, 0x7c,0xa6,0xbc,0x45,0x28,0x4, 0x7c,0xc5,0x80,0x2, 0x7c, +0xc4,0xbc,0x45,0x50,0x4, 0x7c,0xb5,0x80,0x2, 0x7c,0xb4,0xf5,0x39,0x7a,0xd1,0x3a, +0x7a,0xc1,0x3b,0x7a,0xa1,0x3c,0x85,0x39,0x3d,0x75,0x3e,0x1, 0xbe,0x51,0x3b,0x78, +0x8, 0xe5,0x3a,0xbc,0xb7,0x50,0xb, 0x80,0x6, 0xe5,0x3a,0xbc,0xb6,0x50,0x3, 0x75, +0x3e,0x0, 0xe5,0x3e,0x60,0x3, 0x2, 0xc9,0x3b,0x7c,0xda,0x2, 0xc9,0x3b,0x7e,0x8, +0x0, 0x3f,0x7e,0x34,0x0, 0xc, 0x74,0xff,0x12,0x24,0x39,0xe5,0x3e,0x70,0x2, 0x1, +0x9c,0xa, 0x2c,0xb, 0x24,0xe5,0x3d,0xa, 0x3b,0xbd,0x23,0x18,0x3, 0x12,0xc9,0x81, +0xa, 0xd, 0xb, 0x4, 0xe5,0x3c,0xa, 0x1b,0xbd,0x1, 0x18,0x9, 0xa, 0x5d,0xb, 0x54, +0xf5,0x43,0x7a,0xc1,0x44,0xbd,0x1, 0x18,0x10,0xbd,0x23,0x18,0xc, 0xa, 0x5d,0xb, +0x54,0xf5,0x47,0xa, 0x5c,0xb, 0x54,0xf5,0x48,0x7e,0xe4,0x80,0x1, 0x6c,0xff,0x12, +0xc9,0x6b,0x7c,0x6b,0xbe,0x60,0xff,0x68,0x13,0x12,0xc9,0x79,0xbe,0x70,0xff,0x68, +0xb, 0x12,0xc9,0x9e,0xbd,0x3e,0x8, 0x4, 0x7d,0xe3,0x7c,0xef,0xb, 0xf0,0xbe,0xf0, +0x3, 0x78,0xdc,0x12,0xc9,0x8b,0x78,0xa, 0x12,0xc9,0x71,0xbe,0xb1,0x3c,0x78,0x2, +0x21,0x4a,0xe5,0x3d,0xbe,0xb1,0x3b,0x78,0xa, 0x12,0xc9,0x71,0xbe,0xb1,0x3c,0x78, +0x2, 0x21,0x4a,0xbe,0xe0,0xff,0x78,0x2, 0x21,0x3b,0x21,0x1f,0xa, 0x2c,0xb, 0x24, +0xe5,0x3d,0xa, 0x3b,0xbd,0x23,0x18,0x3, 0x12,0xc9,0x81,0xa, 0xd, 0x1b,0x4, 0xe5, +0x3a,0xa, 0x1b,0xbd,0x1, 0x48,0x9, 0xa, 0x5d,0x1b,0x54,0xf5,0x43,0x7a,0xc1,0x44, +0xbd,0x1, 0x48,0x10,0xbd,0x23,0x18,0xc, 0xa, 0x5d,0x1b,0x54,0xf5,0x47,0xa, 0x5c, +0xb, 0x54,0xf5,0x48,0x7e,0xe4,0x80,0x1, 0x6c,0xff,0x12,0xc9,0x6b,0x7c,0x6b,0xbe, +0x60,0xff,0x68,0x13,0x12,0xc9,0x79,0xbe,0x70,0xff,0x68,0xb, 0x12,0xc9,0x9e,0xbd, +0x3e,0x8, 0x4, 0x7d,0xe3,0x7c,0xef,0xb, 0xf0,0xbe,0xf0,0x3, 0x78,0xdc,0x12,0xc9, +0x8b,0x78,0x8, 0x12,0xc9,0x71,0xbe,0xb1,0x3a,0x68,0x3f,0xe5,0x3d,0xbe,0xb1,0x3b, +0x78,0x8, 0x12,0xc9,0x71,0xbe,0xb1,0x3a,0x68,0x30,0xbe,0xe0,0xff,0x68,0x1c,0x7e, +0xa3,0x5d,0x11,0x7e,0x50,0x2, 0xac,0x5a,0x59,0xe2,0x70,0x49,0x2e,0x10,0x3f,0xa5, +0xe7,0x7c,0xdb,0x7c,0xc7,0x7c,0xba,0x4, 0x12,0xc9,0xb6,0xe5,0x39,0xa, 0x2b,0xb, +0x24,0xa, 0x3c,0xbd,0x32,0x68,0x3, 0x2, 0xc7,0xfe,0x6c,0xff,0x80,0x10,0x74,0x2, +0xac,0xbf,0x49,0xe5,0x70,0x49,0xbd,0xef,0x58,0x2, 0x7d,0xfe,0xb, 0xf0,0x7e,0x73, +0x5d,0x11,0xbc,0x7f,0x38,0xe8,0x7d,0x3f,0xda,0x3b,0x22,0x7c,0x1f,0x3e,0x10,0x3e, +0x10,0x7c,0x1, 0x2e,0x0, 0x3f,0xa5,0xe6,0x22,0x2e,0x10,0x40,0xa5,0xe7,0x7c,0x7b, +0x22,0x7a,0xd1,0x3f,0xa, 0x5c,0xb, 0x54,0xf5,0x40,0x22,0x7c,0x1e,0x3e,0x10,0x3e, +0x10,0x7c,0x1, 0x2e,0x0, 0x40,0xa5,0xe6,0x7c,0x7b,0xbe,0x71,0x3d,0x22,0x7c,0xb6, +0x12,0x81,0x9d,0x7d,0x23,0x7c,0xbf,0x3e,0xb0,0x3e,0xb0,0x24,0x41,0xa, 0x3b,0x1b, +0x38,0x20,0xb, 0x38,0x30,0x22,0x7a,0xb3,0x5d,0x11,0x7e,0xe0,0xff,0x22,0xca,0x3b, +0x74,0xff,0x7a,0xb3,0x5d,0x9, 0x6c,0xff,0x7e,0xc0,0xff,0x6c,0xee,0x6c,0x99,0x6c, +0x88,0x7e,0xf4,0x7f,0xff,0x6c,0xdd,0x80,0x68,0x7e,0x70,0x2, 0xac,0x7d,0x9, 0xb3, +0x66,0x4b,0x7a,0xb3,0x5d,0x7, 0x9, 0x73,0x66,0x4c,0x12,0x87,0xb1,0x7d,0x3, 0xbd, +0xf, 0x58,0x2, 0x7d,0xf0,0x7e,0x73,0x5d,0x7, 0xbe,0x73,0x5d,0x9, 0x50,0x4, 0x7a, +0x73,0x5d,0x9, 0xbc,0x7f,0x28,0x2, 0x7c,0xf7,0x7e,0x73,0x5d,0x8, 0xbc,0x7c,0x50, +0x2, 0x7c,0xc7,0xbc,0x7e,0x28,0x2, 0x7c,0xe7,0x7e,0x73,0x5d,0x9, 0xa, 0x57,0xa, +0x1f,0x9d,0x15,0xbe,0x14,0x0, 0x7, 0x18,0xc, 0xa, 0x5c,0xa, 0x1e,0x9d,0x15,0xbe, +0x14,0x0, 0x7, 0x8, 0xa, 0x7e,0x14,0x1, 0xf4,0x7a,0x17,0x70,0x67,0x41,0xf7,0xb, +0xd0,0x7e,0x73,0x67,0xd5,0xbc,0x7d,0x38,0x90,0x7d,0x3f,0x3e,0x34,0x12,0x94,0x3a, +0x7d,0x3, 0x7c,0xdc,0x80,0x1d,0x7e,0xc3,0x5d,0x9, 0x80,0x11,0x7c,0xbc,0x7c,0x7d, +0x12,0x81,0x9d,0xbd,0x30,0x8, 0x2, 0xb, 0x90,0xb, 0x80,0xb, 0xc0,0xbc,0xfc,0x50, +0xeb,0xb, 0xd0,0xbc,0xed,0x50,0xdf,0x7e,0x73,0x69,0x60,0xbe,0x70,0x3, 0x40,0x12, +0x7e,0x17,0x70,0x67,0xbe,0x14,0x3, 0xe8,0x50,0x2d,0xb, 0x14,0x7a,0x17,0x70,0x67, +0x80,0x25,0xbe,0x70,0x1, 0x38,0x20,0x7e,0x17,0x70,0x67,0xbe,0x14,0x0, 0x2, 0x28, +0x6, 0x1b,0x15,0x7a,0x17,0x70,0x67,0x7e,0x17,0x6f,0xe9,0xbe,0x14,0x1, 0xf4,0x50, +0x6, 0xb, 0x14,0x7a,0x17,0x6f,0xe9,0x7e,0x73,0x67,0xd5,0xbe,0x70,0x1, 0x40,0x37, +0x7e,0x30,0x2, 0xac,0x38,0x74,0x3, 0xac,0xb9,0xbd,0x51,0x8, 0x14,0x6d,0x11,0x7a, +0x17,0x70,0x67,0x7e,0x17,0x6f,0xe9,0xbe,0x14,0x1, 0xf4,0x50,0x1a,0xb, 0x14,0x80, +0x12,0x7e,0x17,0x70,0x67,0xbe,0x14,0x3, 0xe8,0x50,0x6, 0xb, 0x15,0x7a,0x17,0x70, +0x67,0x6d,0x11,0x7a,0x17,0x6f,0xe9,0xda,0x3b,0x22,0xd2,0x5, 0x7e,0x34,0x27,0xe7, +0x7e,0x24,0x0, 0xff,0x7e,0x14,0x5d,0x11,0x74,0x3c,0x12,0x23,0x65,0x12,0x97,0x6d, +0x50,0x2, 0xc3,0x22,0x6c,0xaa,0x80,0x17,0x7e,0x90,0x2, 0xac,0x9a,0x9, 0xb4,0x66, +0x4b,0x19,0xb4,0x5d,0x11,0x9, 0xb4,0x66,0x4c,0x19,0xb4,0x5d,0x12,0xb, 0xa0,0x7e, +0x73,0x67,0xd5,0xbc,0x7a,0x38,0xe1,0x6c,0xaa,0x80,0x36,0xa, 0x2a,0xb, 0x24,0x7c, +0x65,0x80,0x28,0x7e,0x50,0x2, 0xac,0x56,0x9, 0x12,0x5d,0x11,0x7e,0x30,0x2, 0xac, +0x3a,0x9, 0xb1,0x5d,0x11,0xbc,0xb1,0x78,0x2, 0xc2,0x5, 0x9, 0x52,0x5d,0x12,0x9, +0xb1,0x5d,0x12,0xbc,0xb5,0x78,0x2, 0xc2,0x5, 0xb, 0x60,0xbc,0x76,0x38,0xd4,0xb, +0xa0,0xbc,0x7a,0x38,0xc6,0xa2,0x5, 0x22,0xa9,0xd7,0x94,0x74,0xa5,0x7a,0xb3,0x73, +0x5f,0x22,0xa9,0xc5,0xca,0x75,0xed,0x8f,0x75,0xad,0xb0,0xa9,0xc7,0x94,0xa9,0xd4, +0x94,0x22,0xa9,0xd5,0xcd,0xd2,0x99,0x22,0xa9,0x31,0xcd,0xc, 0xa9,0x31,0xe5,0x8, +0x12,0x64,0xc6,0xc2,0x95,0xa9,0xc1,0xcd,0xa9,0x30,0xcd,0x7, 0xa9,0x30,0xe5,0x3, +0xa9,0xc0,0xcd,0xa9,0x32,0xcd,0x7, 0xa9,0x32,0xe5,0x3, 0xa9,0xc2,0xcd,0xa9,0x35, +0xcd,0x7, 0xa9,0x35,0xe5,0x3, 0xa9,0xc5,0xcd,0xa9,0x36,0xcd,0x7, 0xa9,0x36,0xe5, +0x3, 0xa9,0xc6,0xcd,0xa9,0x37,0xcd,0x7, 0xa9,0x37,0xe5,0x3, 0xa9,0xc7,0xcd,0x32, +0xca,0xb8,0xca,0x39,0x12,0xcc,0x6d,0x12,0x61,0x55,0x7e,0x37,0x72,0xf7,0xb, 0x34, +0x7a,0x37,0x72,0xf7,0x7e,0xb3,0x71,0xd, 0xb4,0x1, 0x40,0x7e,0xb3,0x73,0x9, 0x4, +0x7a,0xb3,0x73,0x9, 0x7e,0x73,0x73,0x9, 0xbe,0x70,0xa, 0x28,0x2e,0xe4,0x7a,0xb3, +0x73,0x9, 0x7e,0x73,0x73,0x2, 0xbe,0x73,0x29,0xff,0x78,0x8, 0x7e,0x37,0x72,0xf9, +0xb, 0x34,0x80,0xa, 0x7e,0x73,0x29,0xff,0x7a,0x73,0x73,0x2, 0x6d,0x33,0x7a,0x37, +0x72,0xf9,0xbe,0x34,0x0, 0xfa,0x28,0x3, 0x75,0xe9,0xff,0x7e,0xb3,0x72,0xfb,0x60, +0x5, 0x14,0x7a,0xb3,0x72,0xfb,0x7e,0xb3,0x72,0xfb,0x70,0x2, 0xd2,0x11,0x7e,0x37, +0x73,0x3c,0xb, 0x34,0x7a,0x37,0x73,0x3c,0x7e,0x37,0x73,0x5, 0xbe,0x34,0x0, 0x0, +0x28,0x6, 0x1b,0x34,0x7a,0x37,0x73,0x5, 0xda,0x39,0xda,0xb8,0x32,0xa9,0xd0,0x9e, +0xa9,0xd4,0x9e,0x75,0x9d,0x0, 0x75,0x9c,0x20,0x22,0xc2,0x88,0xd2,0xa8,0x22,0xa9, +0xc5,0xca,0xbe,0xb0,0x8, 0x50,0x2, 0xf5,0xcc,0x75,0xe6,0x0, 0x22,0x7e,0xb3,0x73, +0xb, 0xbe,0xb0,0xc8,0x50,0x5, 0x4, 0x7a,0xb3,0x73,0xb, 0x22,0x75,0x9a,0x2f,0xa9, +0xd1,0x99,0xd2,0x9c,0xa9,0xd6,0xdf,0x22,0xc2,0x8e,0x43,0x89,0x20,0x75,0x8d,0x1, +0x75,0x8b,0x0, 0xd2,0x8e,0xd2,0xab,0x22,0x75,0xb7,0x0, 0x75,0xb8,0x0, 0x75,0xf7, +0x0, 0x75,0xf8,0x0, 0xa9,0xd0,0xb7,0xd2,0xb8,0xa9,0xd5,0xb7,0xd2,0xbd,0xa9,0xd0, +0xf7,0xd2,0xf8,0xa9,0xd4,0xb7,0xc2,0xbc,0xa9,0xc2,0xb7,0xc2,0xba,0xa9,0xc1,0xb7, +0xc2,0xb9,0xa9,0xc3,0xb7,0xc2,0xbb,0x22,0xa9,0xd0,0x99,0xa9,0xc6,0xdf,0x22,0xa2, +0xac,0x92,0x2, 0xc2,0xac,0x7e,0xf, 0x73,0x51,0x30,0x1, 0xa, 0xb, 0x16,0xb, 0xa, +0x30,0x4e,0x70,0xc, 0x80,0x8, 0xb, 0x16,0xb, 0xa, 0x30,0x5e,0x70,0xf3,0x1b,0xa, +0x30,0xa2,0x2, 0x92,0xac,0x22,0xa, 0x7, 0xa, 0x1b,0x2d,0x10,0x12,0xcd,0x2a,0x3e, +0x14,0x6d,0x0, 0x7e,0x18,0xbb,0x80,0x2, 0x23,0x10,0x3e,0x14,0x3e,0x14,0x3e,0x14, +0x22,0x7d,0x13,0x12,0xcd,0x2a,0x7e,0x37,0x73,0x31,0x9e,0x37,0x73,0x2d,0x12,0x24, +0x5b,0xbd,0x31,0x38,0x12,0x7e,0x37,0x73,0x33,0x9e,0x37,0x73,0x2f,0x12,0x24,0x5b, +0xbd,0x31,0x38,0x3, 0x74,0x1, 0x22,0xe4,0x22,0xca,0xd8,0xca,0x79,0x6c,0xff,0x6d, +0xdd,0x7d,0xed,0x7d,0xfd,0x7e,0xd3,0x69,0x5f,0x7e,0xe3,0x69,0x60,0x7e,0xb3,0x73, +0x2c,0x60,0x11,0x7e,0xc7,0x73,0x35,0x4d,0xcc,0x78,0x2, 0xc1,0x5d,0xbe,0xd0,0x1, +0x28,0x2, 0xc1,0x5d,0xbe,0xd0,0x1, 0x78,0x1d,0xbe,0xb0,0x4, 0x78,0x2, 0xc1,0x5d, +0x7e,0xe7,0x68,0x65,0x7e,0xf7,0x68,0x67,0x7d,0x3e,0x7d,0x2f,0x12,0xce,0x7f,0xbe, +0xb0,0x1, 0x78,0x2, 0xc1,0x5d,0x7e,0xa3,0x73,0x2c,0x7c,0xba,0x14,0x68,0x2e,0x14, +0x68,0x5e,0x14,0x68,0x28,0x14,0x78,0x2, 0xc1,0x5a,0xb, 0xb2,0x68,0x2, 0xc1,0x5d, +0xbe,0xd0,0x1, 0x68,0x2, 0xc1,0x6c,0x4c,0xee,0x68,0x2, 0xc1,0x6c,0x74,0x1, 0x7a, +0xb3,0x73,0x2c,0x7a,0xe7,0x73,0x2d,0x7a,0xf7,0x73,0x2f,0x80,0x70,0x4c,0xdd,0x78, +0x1d,0xbe,0xa0,0x1, 0x78,0xc, 0x74,0x2, 0x7a,0xb3,0x73,0x2c,0x7e,0x34,0x22,0x43, +0x80,0x5f,0x74,0x4, 0x7a,0xb3,0x73,0x2c,0x7e,0x34,0x22,0x47,0x80,0x53,0x7a,0xe7, +0x73,0x31,0x7a,0xf7,0x73,0x33,0x90,0x22,0x36,0x12,0xce,0x73,0x68,0x4f,0x80,0x5c, +0xbe,0xd0,0x1, 0x78,0x57,0x4c,0xee,0x78,0x53,0x7a,0xe7,0x73,0x31,0x7a,0xf7,0x73, +0x33,0x7e,0x34,0x22,0x3f,0x12,0x30,0xa4,0x7e,0x14,0x22,0x43,0x12,0xce,0xbe,0x9d, +0xc3,0xbe,0xc7,0x73,0x35,0x40,0x26,0x90,0x22,0x35,0x12,0xce,0x73,0x68,0x1e,0x7a, +0xe7,0x73,0x2d,0x7a,0xf7,0x73,0x2f,0x74,0x3, 0x7a,0xb3,0x73,0x2c,0x7e,0x34,0x22, +0x43,0x12,0x30,0xa4,0x7a,0x37,0x73,0x35,0x80,0x12,0x7e,0xf0,0x24,0xe4,0x7a,0xb3, +0x73,0x2c,0x6d,0x33,0x7a,0x37,0x73,0x35,0x7c,0xbf,0x80,0x2, 0x7c,0xbf,0xda,0x79, +0xda,0xd8,0x22,0xe4,0x93,0xa, 0x3b,0x12,0xcd,0x31,0xa, 0xdb,0x4d,0xdd,0x22,0x7d, +0x13,0x7e,0x54,0x22,0x37,0x12,0xce,0xb4,0x50,0x1d,0x7e,0x54,0x22,0x39,0x12,0xce, +0xb4,0x28,0x14,0x7e,0x14,0x22,0x3b,0x12,0xce,0xaa,0x50,0xb, 0x7e,0x14,0x22,0x3d, +0x12,0xce,0xaa,0x28,0x2, 0xe4,0x22,0x74,0x1, 0x22,0x7e,0x4, 0x0, 0xff,0xb, 0xa, +0x30,0xbd,0x32,0x22,0x7e,0x44,0x0, 0xff,0xb, 0x2a,0x30,0xbd,0x31,0x22,0x7e,0x4, +0x0, 0xff,0xb, 0xa, 0xc0,0x22,0x7e,0x8, 0x0, 0x4f,0x7e,0x34,0x0, 0x3c,0xe4,0x12, +0x24,0x39,0x7e,0x34,0x1, 0x5, 0x7a,0x37,0x0, 0x4f,0x7e,0x34,0x20,0x0, 0x7a,0x37, +0x0, 0x51,0x6d,0x33,0x7a,0x37,0x0, 0x53,0x7e,0x34,0x1, 0xe0,0x7a,0x37,0x0, 0x55, +0x7e,0x34,0x28,0x30,0x7a,0x37,0x0, 0x57,0x7e,0x34,0x18,0xdc,0x7a,0x37,0x0, 0x59, +0x7e,0x34,0x66,0x6, 0x7a,0x37,0x0, 0x5b,0x7e,0x34,0x73,0x0, 0x7a,0x37,0x0, 0x5d, +0x7e,0x34,0x14,0x2, 0x7a,0x37,0x0, 0x5f,0x6d,0x33,0x7a,0x37,0x0, 0x63,0x7a,0x37, +0x0, 0x65,0x7a,0x37,0x0, 0x67,0x7a,0x37,0x0, 0x69,0x7a,0x37,0x0, 0x7b,0x7e,0x34, +0x38,0x1, 0x7a,0x37,0x0, 0x7d,0x7e,0x34,0x4, 0x1, 0x7a,0x37,0x0, 0x7f,0x7e,0x34, +0x6, 0x3, 0x7a,0x37,0x0, 0x81,0x6d,0x33,0x7a,0x37,0x0, 0x83,0x7a,0x37,0x0, 0x85, +0x7a,0x37,0x0, 0x87,0x7a,0x37,0x0, 0x89,0x7e,0x34,0x0, 0x3c,0xca,0x39,0x7e,0x18, +0x0, 0x4f,0x7e,0x8, 0x0, 0x8b,0x12,0x24,0x14,0x1b,0xfd,0x22,0xa9,0xc5,0xcb,0xa9, +0xd1,0xcb,0xa9,0xd2,0xca,0xa9,0xd2,0xcb,0x22,0x6c,0xaa,0x7e,0x30,0x2c,0xac,0x3a, +0x12,0x3b,0xd8,0x7e,0x34,0x0, 0x2c,0xe4,0x12,0x24,0x39,0xb, 0xa0,0xbe,0xa0,0x3, +0x40,0xe9,0x22,0xa9,0xd6,0xcd,0xd2,0x98,0x22,0xa9,0xc3,0xcb,0xc2,0xcd,0xc2,0xcc, +0xa9,0xd6,0xea,0x22,0xe4,0x7a,0xb3,0x3, 0xcb,0x12,0xcf,0xb8,0x7a,0xb3,0x3, 0xce, +0x12,0xcf,0xc4,0x7a,0xb3,0x3, 0xd6,0x22,0x7a,0xb3,0x3, 0xcc,0x74,0xff,0x7a,0xb3, +0x3, 0xcd,0xe4,0x22,0x7a,0xb3,0x3, 0xcf,0x7a,0xb3,0x3, 0xd0,0x7a,0xb3,0x3, 0xd3, +0x74,0xff,0x7a,0xb3,0x3, 0xd4,0xe4,0x7a,0xb3,0x3, 0xd5,0x22,0x7e,0x34,0x0, 0x2, +0x12,0xd0,0x5b,0x7e,0x57,0x3, 0xbb,0x12,0xd0,0x8, 0x74,0x2, 0x2, 0xcf,0xef,0x7a, +0xb3,0x3, 0xd1,0x7a,0xb3,0x3, 0xd2,0x22,0x6d,0x33,0x12,0xd0,0x5b,0x7e,0x57,0x3, +0xab,0x12,0xd0,0x8, 0xe4,0x2, 0xcf,0xef,0x7c,0x1b,0x7d,0x43,0x7e,0xa3,0x3, 0xcb, +0xbe,0xa0,0x5, 0x50,0x1e,0x7e,0x70,0x7, 0xac,0x7a,0x59,0x43,0x3, 0xd7,0x59,0x23, +0x3, 0xd9,0x59,0x13,0x3, 0xdb,0x19,0x13,0x3, 0xdd,0x7c,0xba,0x4, 0x7a,0xb3,0x3, +0xcb,0xc3,0x22,0xd3,0x22,0x7e,0x34,0x0, 0x1, 0x12,0xd0,0x5b,0x7e,0x57,0x3, 0xb3, +0x12,0xd0,0x8, 0x74,0x1, 0x2, 0xcf,0xef,0x7e,0x34,0x0, 0x3, 0x12,0xd0,0x5b,0x7e, +0x57,0x3, 0xc3,0x12,0xd0,0x8, 0x74,0x3, 0x2, 0xcf,0xef,0x7e,0x24,0xc, 0xd0,0x7e, +0x14,0x11,0x38,0x22,0x7e,0x34,0x0, 0x4, 0x12,0xd0,0x5b,0x74,0x1, 0x12,0xd0,0x8, +0x7e,0x73,0x73,0x8, 0x7a,0x73,0x3, 0xd1,0x7a,0x73,0x3, 0xd2,0x22,0x7e,0xb3,0x3, +0xce,0xb4,0x1, 0x3c,0x7e,0xa3,0x3, 0xcc,0x7a,0xa3,0x3, 0xcd,0x7e,0xb3,0x3, 0xd4, +0x4, 0x7a,0xb3,0x3, 0xd4,0x7e,0xb3,0x3, 0xd3,0x4, 0x7a,0xb3,0x3, 0xd3,0x12,0xd0, +0xc8,0xbe,0xb3,0x3, 0xd3,0x38,0x19,0xe4,0x7a,0xb3,0x3, 0xd3,0x7c,0xba,0x4, 0x7a, +0xb3,0x3, 0xcc,0x7e,0x73,0x3, 0xcb,0xbe,0x73,0x3, 0xcc,0x28,0x3, 0x12,0xd0,0xc1, +0x22,0x74,0x3, 0x7a,0xb3,0x3, 0xce,0x22,0x7e,0x70,0x7, 0xac,0x7a,0x9, 0xb3,0x3, +0xdd,0x22,0xe5,0x1b,0x70,0x21,0x7e,0x37,0x73,0x5, 0x4d,0x33,0x78,0xf8,0x12,0xd1, +0xc8,0x7e,0x34,0x0, 0x5, 0x7a,0x37,0x73,0x5, 0xbe,0x34,0x0, 0x21,0x28,0x8, 0x7e, +0x34,0x0, 0x21,0x7a,0x37,0x73,0x5, 0x22,0x7c,0x3b,0xd2,0x2, 0x12,0xd0,0xd2,0x12, +0xd1,0xab,0x1b,0x30,0x68,0x1d,0x1b,0x30,0x68,0x23,0x1b,0x30,0x68,0x29,0x1b,0x30, +0x68,0x2f,0xb, 0x32,0x78,0x73,0x12,0x5a,0x4d,0x7e,0x1f,0x3, 0xaf,0x7e,0xf, 0x3, +0xab,0x80,0x52,0x7e,0x1f,0x3, 0xb7,0x7e,0xf, 0x3, 0xb3,0x80,0x48,0x7e,0x1f,0x3, +0xbf,0x7e,0xf, 0x3, 0xbb,0x80,0x3e,0x7e,0x1f,0x3, 0xc7,0x7e,0xf, 0x3, 0xc3,0x80, +0x34,0x7e,0x34,0x0, 0x8, 0xca,0x39,0x7e,0x71,0x1b,0x74,0x8, 0xac,0x7b,0x2e,0x34, +0x3, 0xab,0x6d,0x22,0x7e,0x8, 0x61,0xc9,0x12,0x24,0x14,0x1b,0xfd,0x7e,0x34,0x0, +0x1, 0x7a,0x37,0x61,0xc9,0x7e,0x73,0x3, 0xfe,0x7a,0x73,0x61,0xcb,0x7e,0x1f,0x61, +0xcd,0x7e,0xf, 0x61,0xc9,0x7a,0x1d,0x3d,0x7a,0xd, 0x39,0x12,0x2, 0x3d,0x74,0x1, +0x7a,0xb3,0x3, 0xce,0x12,0xd, 0xbd,0x80,0x2, 0xc2,0x2, 0xa2,0x2, 0x22,0x7e,0x73, +0x3, 0xcb,0xbe,0x73,0x3, 0xcc,0x38,0x2, 0xe4,0x22,0x7e,0xa3,0x3, 0xcc,0x74,0x7, +0xa4,0x49,0x55,0x3, 0xd7,0x12,0xd0,0xf8,0xe4,0x33,0x22,0x6c,0xaa,0x7e,0xb3,0x72, +0xff,0xa, 0x3b,0x1e,0x34,0xb, 0x34,0x7e,0x50,0x8, 0xac,0x5a,0x19,0x72,0x3, 0xb0, +0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xe6,0x22,0x7e,0x73,0x70,0xf0,0x7e,0xb3,0x71,0xb, +0x70,0x3b,0xe5,0x1b,0x70,0x1d,0x7e,0x63,0x70,0xee,0xbe,0x60,0x14,0x28,0x5, 0x7e, +0x60,0x14,0x80,0x7, 0xa5,0xbe,0x0, 0x3, 0x7e,0x60,0x1, 0xa, 0x26,0x7e,0x34,0x0, +0x64,0x80,0x7a,0xe5,0x1b,0xb4,0x3, 0x2, 0x80,0x46,0xe5,0x1a,0xa, 0x27,0xb4,0x1, +0x6, 0x7e,0x34,0x1, 0xf4,0x80,0x66,0x7e,0x34,0x3, 0xe8,0x80,0x60,0xe5,0x1b,0x70, +0xe, 0x7e,0x63,0x70,0xef,0xbe,0x60,0x7f,0x28,0x58,0x7e,0x60,0x7f,0x80,0x53,0x7e, +0x63,0x73,0x39,0xbe,0x60,0x3b,0x40,0x13,0xe5,0x1a,0xa, 0x27,0xb4,0x1, 0x6, 0x7e, +0x34,0x1, 0xf4,0x80,0x2a,0x7e,0x34,0x3, 0xe8,0x80,0x24,0xe5,0x1b,0xb4,0x3, 0x8, +0x7e,0x73,0x71,0x25,0xa, 0x37,0x80,0x19,0x7e,0xb3,0x73,0x37,0x60,0x19,0xe5,0x1a, +0xa, 0x27,0xb4,0x1, 0x6, 0x7e,0x34,0x1, 0xf4,0x80,0x4, 0x7e,0x34,0x3, 0xe8,0x8d, +0x32,0x1b,0x34,0x7c,0x67,0x80,0xb, 0xa, 0x27,0x7e,0x34,0x3, 0xe8,0x12,0x22,0x71, +0x7c,0x67,0x7e,0x73,0x71,0x12,0xac,0x67,0x7e,0x24,0x0, 0x18,0x12,0x22,0x71,0x7a, +0x73,0x72,0xfb,0xc2,0x11,0x6d,0x33,0x7a,0x37,0x72,0xf7,0x22,0xca,0xf8,0x7e,0xf3, +0x73,0x8, 0x20,0xb, 0x6, 0x20,0xc, 0x3, 0x30,0xd, 0x3, 0xc3,0x80,0x57,0x12,0x57, +0x9b,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7e,0x53,0x6d,0xfc,0x6c,0x44,0x5c,0x57, +0x4d,0x22,0x68,0x40,0x7e,0xb3,0x71,0x86,0x70,0x8, 0x4e,0x73,0x6d,0xfd,0x7a,0x73, +0x6d,0xfd,0x12,0x57,0xa2,0x12,0x43,0x42,0x40,0x3, 0xc3,0x80,0x28,0x20,0xb, 0x6, +0x20,0xc, 0x3, 0x30,0xd, 0x3, 0xc3,0x80,0x1c,0x12,0x57,0x9b,0x60,0x5, 0x3e,0x34, +0x14,0x78,0xfb,0x6e,0x70,0xff,0x5e,0x73,0x6d,0xfc,0x7a,0x73,0x6d,0xfc,0x12,0xd1, +0xc8,0xd3,0x80,0x1, 0xd3,0xda,0xf8,0x22,0x7e,0xb3,0x3, 0xce,0xb4,0x1, 0x2, 0x80, +0x2, 0x61,0xa0,0x7e,0x73,0x3, 0xcb,0xbe,0x73,0x3, 0xcd,0x28,0x74,0x7e,0x63,0x3, +0xcd,0x7e,0x70,0x7, 0xac,0x67,0x49,0x53,0x3, 0xd7,0x7c,0xab,0x7e,0x43,0x3, 0xd4, +0x7e,0x50,0x2, 0xac,0x45,0x2d,0x32,0x49,0x33,0x3, 0xd9,0x7a,0x35,0x14,0x4d,0x33, +0x68,0x4f,0xd2,0x29,0x1b,0xa0,0x68,0x10,0x1b,0xa0,0x68,0xc, 0x1b,0xa0,0x68,0x8, +0x1b,0xa0,0x68,0x4, 0xb, 0xa2,0x78,0x39,0x12,0xd3,0xa1,0x30,0xf, 0x4, 0x74,0x2, +0x80,0x2, 0x74,0x1, 0x7e,0xa3,0x3, 0xd4,0xa, 0x3a,0x19,0xb3,0x3, 0xcf,0x7e,0xb3, +0x3, 0xd4,0x70,0xe, 0x7e,0x73,0x3, 0xd6,0xbe,0x70,0x1, 0x28,0x5, 0x12,0xb, 0xe5, +0x80,0xf, 0x7e,0xf, 0x73,0x51,0xb, 0x16,0xb, 0xa, 0x30,0x5e,0x60,0xef,0x1b,0xa, +0x30,0x7e,0x73,0x3, 0xcb,0xbe,0x73,0x3, 0xcc,0x38,0x15,0x74,0x2, 0x7a,0xb3,0x3, +0xce,0xc2,0x22,0x12,0x2a,0x29,0x12,0x2f,0xfe,0xe5,0x1b,0x70,0x3, 0x2, 0x5a,0x8d, +0x22,0xca,0x69,0xca,0xf8,0x7e,0xe5,0x14,0x7e,0xf3,0x3, 0xd4,0x7e,0xb3,0x69,0x9e, +0x60,0xa, 0x7e,0x47,0x69,0x92,0x7e,0xf7,0x69,0x94,0x80,0x8, 0x7e,0xf7,0x69,0x92, +0x7e,0x47,0x69,0x94,0x20,0x29,0x2, 0x81,0xff,0x7e,0x17,0x6d,0xfe,0x7e,0x24,0x0, +0xa, 0xa9,0xd7,0xea,0x7e,0x6f,0x1, 0x5b,0x69,0x56,0x2, 0x64,0x69,0xb6,0x0, 0xc, +0x4d,0xb5,0x7e,0xd0,0x8, 0xac,0xdf,0x59,0xb6,0x0, 0xc7,0x69,0xb6,0x2, 0x5c,0x69, +0x56,0x0, 0x4, 0x4d,0x5b,0x59,0x56,0x0, 0xc9,0x69,0xb6,0x2, 0x5a,0x69,0x56,0x0, +0x2, 0xbd,0x5b,0x28,0x8, 0x69,0x56,0x0, 0x2, 0x7d,0x35,0x80,0x4, 0x69,0x36,0x2, +0x5a,0x74,0x8, 0xac,0xbf,0x59,0x35,0x0, 0xcb,0xb, 0x6a,0x50,0x12,0xd5,0x1f,0x19, +0xa3,0x0, 0xcd,0x69,0x56,0x2, 0x58,0x12,0xd5,0x1f,0x19,0xa3,0x0, 0xce,0x6d,0xdd, +0x7d,0x3d,0xbe,0x34,0x0, 0x1, 0x78,0x4, 0xb, 0x24,0x80,0x23,0x7c,0xb7,0x7e,0xc4, +0x0, 0x1, 0x60,0x5, 0x3e,0xc4,0x14,0x78,0xfb,0x7e,0xb3,0x69,0x90,0xa, 0x5b,0x5d, +0x5c,0x68,0x5, 0x12,0xd5,0x4, 0x80,0x7, 0x6d,0xcc,0x12,0xd5,0x13,0xb, 0x24,0xb, +0x34,0xbe,0x34,0x0, 0x3, 0x78,0xcb,0x7e,0xb3,0x69,0x9e,0x60,0x4, 0x7d,0x4, 0x80, +0x2, 0x7d,0xd, 0x7d,0x3d,0x80,0x18,0x7d,0x52,0x2d,0x53,0x3e,0x54,0x7e,0x5f,0x1, +0x5b,0x2d,0xb5,0xb, 0x5a,0xc0,0x7d,0x50,0xb, 0x4, 0x12,0xd5,0x17,0xb, 0x34,0xbd, +0xf3,0x38,0xe4,0x7e,0x24,0x1, 0x36,0x7d,0x3d,0xbe,0x34,0x0, 0x1, 0x78,0x4, 0xb, +0x24,0x80,0x23,0x7c,0xb7,0x7e,0xc4,0x0, 0x1, 0x60,0x5, 0x3e,0xc4,0x14,0x78,0xfb, +0x7e,0xb3,0x69,0x91,0xa, 0x5b,0x5d,0x5c,0x68,0x5, 0x12,0xd5,0x4, 0x80,0x7, 0x6d, +0xcc,0x12,0xd5,0x13,0xb, 0x24,0xb, 0x34,0xbe,0x34,0x0, 0x3, 0x78,0xcb,0x7e,0xb3, +0x69,0x9e,0x60,0x2, 0x7d,0xd, 0x7d,0x3d,0x80,0x1c,0x7d,0x52,0xb, 0x24,0x3e,0x54, +0x7e,0x6f,0x1, 0x5b,0x2d,0xd5,0xb, 0x6a,0xd0,0x7d,0x50,0xb, 0x4, 0x3e,0x54,0x2d, +0x5e,0x1b,0x58,0xd0,0xb, 0x34,0xbd,0x43,0x38,0xe0,0xa9,0xc7,0xea,0xc2,0x29,0xda, +0xf8,0xda,0x69,0x22,0x7d,0x52,0xb, 0x24,0x3e,0x54,0x7e,0x5f,0x1, 0x5b,0x2d,0xb5, +0xb, 0x5a,0xc0,0x7d,0x51,0xb, 0x14,0x3e,0x54,0x2d,0x5e,0x1b,0x58,0xc0,0x22,0x5e, +0x54,0x0, 0x7f,0x7c,0xab,0x7e,0x70,0x8, 0xac,0x7f,0x22,0xe4,0x7a,0xb3,0x73,0x3a, +0x22,0x7e,0xb3,0x73,0x37,0x60,0x2f,0xe4,0x7a,0xb3,0x73,0x37,0x74,0x1, 0x7a,0xb3, +0x73,0x3a,0x12,0x4a,0xf0,0x5e,0x34,0x0, 0x2, 0x68,0x5, 0x12,0x5, 0x30,0x80,0x3, +0x12,0x3c,0x99,0x7e,0x34,0x0, 0x1, 0x7e,0xa1,0x1b,0x74,0x8, 0xa4,0x59,0x35,0x3, +0xab,0xe5,0x1b,0x2, 0x3f,0x3a,0x7e,0xb3,0x73,0x3b,0x60,0x36,0xe4,0x7a,0xb3,0x73, +0x3b,0x7a,0xb3,0x73,0x3a,0x12,0x4a,0xf0,0x5e,0x34,0x0, 0x2, 0x74,0x1, 0x68,0x5, +0x12,0x5, 0xbc,0x80,0x3, 0x12,0x3c,0x99,0xe5,0x1a,0xb4,0x1, 0xe, 0x7e,0x34,0x0, +0x2, 0x7e,0xa1,0x1b,0x74,0x8, 0xa4,0x59,0x35,0x3, 0xab,0xe5,0x1b,0x12,0x3f,0x3a, +0x80,0xa, 0x7e,0xb3,0x73,0x3a,0x60,0x4, 0xe5,0x1b,0x70,0x3, 0x2, 0x2a,0x60,0x22, +0x12,0x4a,0xf0,0x5e,0x34,0x0, 0x1, 0x68,0xb, 0x74,0x1, 0x7a,0xb3,0x73,0x37,0xe4, +0x7a,0xb3,0x73,0x3b,0x22,0x7e,0xb3,0x73,0x3a,0x60,0x8, 0xe5,0x1b,0xb4,0x1, 0x3, +0x2, 0x2a,0x60,0x22,0x7c,0xab,0x7e,0x8, 0x0, 0x69,0x7e,0x70,0xa, 0xac,0x7a,0x9, +0xb3,0x6f,0xb6,0x12,0xc, 0x3e,0x7e,0x8, 0x0, 0xa5,0x74,0xa, 0xa4,0x9, 0xb5,0x6f, +0xb6,0x12,0xc, 0x3e,0x7e,0x34,0x0, 0xd, 0x7e,0x8, 0x0, 0x69,0x7e,0x24,0x0, 0x1, +0x2, 0xc, 0xcc,0x7c,0xab,0x6d,0x33,0xbe,0xa0,0x4, 0x50,0x27,0x6c,0x55,0x80,0x16, +0x7e,0x10,0x2, 0xac,0x15,0x7e,0x30,0x27,0xac,0x3a,0x2d,0x10,0x49,0x11,0x6f,0x18, +0xb, 0x14,0x2d,0x31,0xb, 0x50,0x7e,0x30,0x27,0xac,0x3a,0x9, 0x41,0x6f,0x13,0xbc, +0x45,0x50,0xdd,0x4d,0x33,0x78,0x2, 0xb, 0x34,0x22,0xbe,0xb0,0x4, 0x50,0x33,0x7e, +0x37,0x0, 0x81,0x5e,0x70,0xf0,0x7a,0x37,0x0, 0x81,0xa, 0x3b,0x4e,0x37,0x0, 0x81, +0x7a,0x37,0x0, 0x81,0x7a,0x37,0x0, 0xbd,0x7e,0x34,0x0, 0x19,0x7e,0x8, 0x0, 0x81, +0x12,0xd6,0x73,0x7e,0x34,0x0, 0x19,0x7e,0x8, 0x0, 0xbd,0x7e,0x24,0x0, 0x1, 0x2, +0x4, 0x96,0x22,0x7e,0x24,0x0, 0x1, 0x2, 0x3, 0xfa,0x6c,0x77,0x12,0x7b,0x6b,0x50, +0x3, 0x7e,0x70,0x1, 0x7e,0x27,0x6d,0xfe,0x6c,0x66,0x90,0x1c,0x49,0xe4,0x93,0x20, +0xe0,0x4, 0x4c,0x66,0x68,0x58,0x1e,0xb0,0x1e,0xb0,0x20,0xe0,0x5, 0xbe,0x60,0x1, +0x68,0x4c,0x90,0x1c,0x4a,0xe4,0x93,0x20,0xe0,0x5, 0xbe,0x60,0x2, 0x68,0x3f,0x1e, +0xb0,0x1e,0xb0,0x20,0xe0,0x5, 0xbe,0x60,0x3, 0x68,0x33,0x4c,0x77,0x68,0x1c,0xa, +0x16,0x2d,0x12,0x3e,0x14,0x49,0x1, 0x15,0xa0,0xbe,0x4, 0xb, 0xb8,0x40,0x1c,0x49, +0x11,0x1a,0x8, 0xbe,0x14,0xb, 0xb8,0x50,0x15,0x80,0x10,0xa, 0x16,0x2d,0x12,0x3e, +0x14,0x49,0x11,0x15,0xa0,0xbe,0x14,0xb, 0xb8,0x50,0x3, 0x2, 0xd6,0xf6,0xb, 0x60, +0xbe,0x60,0x4, 0x40,0x95,0x22,0x74,0x1f,0x7a,0xb3,0x6d,0xfc,0x22,0x7e,0x37,0x6d, +0xfe,0x6c,0xaa,0x90,0x1c,0x49,0xe4,0x93,0x20,0xe0,0x4, 0x4c,0xaa,0x68,0x25,0x1e, +0xb0,0x1e,0xb0,0x20,0xe0,0x5, 0xbe,0xa0,0x1, 0x68,0x19,0x90,0x1c,0x4a,0xe4,0x93, +0x20,0xe0,0x5, 0xbe,0xa0,0x2, 0x68,0xc, 0x1e,0xb0,0x1e,0xb0,0x20,0xe0,0x9, 0xbe, +0xa0,0x3, 0x78,0x4, 0xb, 0x34,0x80,0x22,0x7d,0x23,0x3e,0x24,0x49,0x42,0x8, 0x68, +0x12,0xd7,0x62,0x2d,0x24,0x1b,0xa, 0x20,0x7d,0x23,0x3e,0x24,0x12,0xd7,0x62,0xbe, +0x24,0xf, 0xa0,0x50,0x3, 0x12,0xd6,0xf6,0xb, 0x34,0xb, 0xa0,0xbe,0xa0,0x4, 0x40, +0xa2,0x22,0x7e,0xf, 0x22,0xdc,0x2d,0x12,0xb, 0xa, 0x20,0x22,0x7c,0x1b,0x7e,0xa3, +0x6e,0x2, 0xc2,0x2, 0xa, 0xf1,0x7e,0xd4,0x2, 0x3a,0xad,0xdf,0x7d,0x3d,0x12,0xd7, +0xe2,0x6d,0x11,0x7d,0x41,0x80,0x10,0x7d,0xed,0x2d,0xe4,0x9, 0xbe,0x51,0xe5,0x70, +0x4, 0xd2,0x2, 0x80,0xa, 0xb, 0x44,0x7e,0xe7,0x6d,0xfe,0xbd,0xe4,0x38,0xe8,0x7d, +0x41,0x7c,0xba,0x54,0x1, 0xb4,0x1, 0xf, 0x7d,0x14,0x3e,0x14,0x12,0x6f,0x8e,0x4d, +0x11,0x78,0x4, 0xd2,0x2, 0x80,0xa, 0x1e,0xa0,0xb, 0x44,0xbe,0x44,0x0, 0x4, 0x40, +0xe0,0x30,0x2, 0x10,0x7e,0xb3,0x3, 0xfd,0xbe,0xb0,0x0, 0x28,0xd, 0x14,0x7a,0xb3, +0x3, 0xfd,0xc3,0x22,0x74,0x5, 0x7a,0xb3,0x3, 0xfd,0xd3,0x22,0x7e,0x34,0x2, 0x3a, +0xad,0x32,0x2e,0x37,0x6d,0xfe,0x2e,0x34,0x51,0xe5,0x6d,0x22,0x22,0xca,0x79,0x7c, +0x5b,0x7e,0x40,0xff,0x7e,0xa0,0xff,0x6c,0x33,0x2, 0xd8,0x82,0xbc,0x63,0x78,0x2, +0x1, 0x80,0x7e,0x90,0x2, 0xac,0x93,0x9, 0x24,0x66,0x4b,0xa, 0xf2,0xa, 0x5, 0x9d, +0xf, 0xbe,0x4, 0x0, 0x0, 0x8, 0xc, 0xa, 0xe2,0xa, 0xf5,0x9d,0xfe,0x7d,0x7f,0x7c, +0x2f,0x80,0x8, 0x6e,0x4, 0xff,0xff,0xb, 0x4, 0x7c,0x21,0x7e,0x10,0x2, 0xac,0x13, +0x9, 0xb0,0x66,0x4c,0xa, 0xb, 0xa, 0x47,0x9d,0x40,0xbe,0x44,0x0, 0x0, 0x8, 0x8, +0xa, 0xfb,0xa, 0x7, 0x9d,0xf, 0x80,0x4, 0x6d,0x0, 0x9d,0x4, 0xbe,0x20,0x1, 0x38, +0xa, 0xbe,0x10,0x1, 0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x32,0xbe,0x20,0x2, 0x38,0xa, +0xbe,0x10,0x2, 0x38,0x5, 0x7e,0x40,0x2, 0x80,0x10,0x30,0x0, 0xd, 0xbe,0x20,0x3, +0x38,0x8, 0xbe,0x10,0x3, 0x38,0x3, 0x7e,0x40,0x3, 0xbc,0x4a,0x50,0x2, 0x7c,0xa4, +0xb, 0x30,0x7e,0x3, 0x67,0xd5,0xbc,0x3, 0x28,0x3, 0x2, 0xd7,0xfc,0x7c,0xba,0xda, +0x79,0x22,0x7c,0x57,0x7c,0x7b,0x74,0x2, 0xac,0x7b,0x9, 0x63,0x66,0x4c,0x90,0x21, +0xd9,0xe4,0x93,0x70,0x6, 0x7e,0xa3,0x69,0x8d,0x80,0x4, 0x7e,0xa3,0x69,0x8c,0x7e, +0x70,0x40,0xac,0x67,0x2e,0x34,0x0, 0x20,0x7e,0x90,0x9, 0xac,0x95,0x59,0x34,0x66, +0xc7,0x7e,0x70,0x40,0xac,0x7a,0x2e,0x34,0x0, 0x20,0x59,0x34,0x66,0xc9,0x74,0xff, +0x19,0xb4,0x66,0xcd,0x19,0xb4,0x66,0xcc,0x22,0xca,0x3b,0x7c,0xcb,0x7e,0x8, 0x5d, +0x7, 0x7e,0x34,0x0, 0xc, 0xe4,0x12,0x24,0x39,0x7e,0x8, 0x5d,0x13,0x7e,0x34,0x0, +0x5, 0x12,0x24,0x39,0x7e,0xe3,0x69,0x8c,0x7e,0xd3,0x69,0x8d,0x7e,0xb7,0x6d,0xfe, +0x7e,0x97,0x67,0xf2,0x7d,0xa9,0x3e,0xa4,0x3e,0xa4,0x4c,0xcc,0x78,0x6c,0x7a,0xd3, +0x5d,0x8, 0x7a,0xe3,0x5d,0x7, 0x7e,0x84,0x8, 0x68,0x7a,0x87,0x5d,0xb, 0x7e,0x1f, +0x22,0xdc,0x7d,0x83,0x7a,0x87,0x5d,0xd, 0x7e,0x1f,0x22,0xdc,0x7d,0x83,0x7a,0x87, +0x5d,0xf, 0x7d,0x39,0x7c,0xb7,0xf5,0x26,0x7e,0x8, 0x5d,0x7, 0x7e,0x18,0x5d,0x13, +0x7d,0x59,0x12,0x0, 0x46,0x6c,0xff,0x7d,0x3b,0x3e,0x34,0x49,0x83,0x8, 0x68,0xbd, +0xa8,0x58,0x10,0x7e,0xf, 0x22,0xdc,0x2d,0x13,0xb, 0xa, 0x20,0x2d,0x2a,0x1b,0xa, +0x20,0x80,0x10,0x6d,0x22,0x9d,0x2a,0xbd,0x28,0x8, 0x8, 0x12,0xd9,0xc9,0x9d,0x3a, +0x1b,0xa, 0x30,0x12,0xd9,0xc1,0x78,0xcf,0x80,0x44,0xbe,0xc0,0x1, 0x78,0x3f,0x6c, +0xff,0x80,0x24,0x6c,0x77,0x80,0x1a,0x7c,0xbf,0xac,0xbd,0xa, 0x87,0x2d,0x85,0x3e, +0x84,0x7e,0xf, 0x22,0xdc,0x2d,0x18,0xb, 0xa, 0x80,0x2d,0x89,0x1b,0xa, 0x80,0xb, +0x70,0xbc,0xd7,0x38,0xe2,0xb, 0xf0,0xbc,0xef,0x38,0xd8,0x6c,0xff,0x7d,0x3b,0x3e, +0x34,0x12,0xd9,0xc9,0x2d,0x3a,0x1b,0xa, 0x30,0x12,0xd9,0xc1,0x78,0xef,0xda,0x3b, +0x22,0xb, 0xb4,0xb, 0xf0,0xbe,0xf0,0x4, 0x22,0x7e,0xf, 0x22,0xdc,0x2d,0x13,0xb, +0xa, 0x30,0x22,0x7e,0x18,0x8, 0x68,0x7a,0x1d,0x30,0x7e,0x1f,0x22,0xdc,0x7f,0x1, +0x2, 0x7d,0x91,0xe4,0x7a,0xb3,0x67,0xea,0x12,0xd9,0xff,0xe4,0x12,0x87,0xfc,0x7e, +0xb3,0x24,0x26,0xb4,0x1, 0x8, 0x7e,0x73,0x67,0xd5,0x7a,0x73,0x67,0xe9,0x22,0x6c, +0x33,0x80,0x9, 0xe4,0xa, 0x33,0x19,0xb3,0x66,0xc3,0xb, 0x30,0x90,0x21,0x52,0xe4, +0x93,0xc4,0x23,0x54,0x1f,0xa, 0x2b,0xb, 0x24,0xa, 0x33,0xbd,0x32,0x48,0xe4,0x12, +0xdb,0x3f,0x6d,0x33,0x7a,0x37,0x67,0xd7,0x7a,0x37,0x67,0xd9,0x7a,0x37,0x67,0xdb, +0x7a,0x37,0x67,0xdf,0x7e,0xd4,0x5d,0x9, 0x1e,0xd4,0x3e,0xd4,0x6d,0xcc,0x7e,0x1f, +0x22,0xe0,0x7a,0x37,0x5d,0x49,0x7d,0x3d,0x7a,0x37,0x5d,0x4d,0x7e,0x34,0x23,0x34, +0x7a,0x37,0x5d,0x4b,0x7e,0x73,0x69,0x8c,0x7a,0x73,0x5d,0x46,0x7e,0x73,0x69,0x8d, +0x7a,0x73,0x5d,0x45,0x7e,0x37,0x69,0x6f,0x7a,0x37,0x5d,0x4f,0x7e,0x37,0x69,0x71, +0x7a,0x37,0x5d,0x51,0x7e,0x37,0x69,0x79,0x7a,0x37,0x5d,0x53,0x7e,0x37,0x69,0x7b, +0x7a,0x37,0x5d,0x55,0x12,0x9c,0xe6,0x1b,0x34,0x7a,0x73,0x5d,0x47,0x7e,0x73,0x73, +0x60,0x7a,0x73,0x5d,0x48,0x7e,0x8, 0x5d,0x45,0x7e,0x18,0x5d,0x57,0x12,0x3, 0x1d, +0x7e,0x73,0x5d,0x57,0x7a,0x73,0x67,0xd5,0x7e,0x73,0x5d,0x58,0x7a,0x73,0x67,0xd6, +0x7e,0x37,0x5d,0x59,0x7a,0x37,0x67,0xd7,0x7e,0x37,0x5d,0x5b,0x7a,0x37,0x67,0xd9, +0x7e,0x37,0x5d,0x61,0x7a,0x37,0x67,0xdb,0x7e,0x37,0x5d,0x63,0x7d,0x23,0x7a,0x53, +0x67,0xdd,0xa, 0x36,0x7a,0x73,0x67,0xde,0x7e,0x37,0x5d,0x5d,0x7a,0x37,0x67,0xdf, +0x7e,0x37,0x5d,0x5f,0x7d,0x23,0x7a,0x53,0x67,0xe1,0xa, 0x36,0x7a,0x73,0x67,0xe2, +0x6c,0x33,0x80,0x1b,0x12,0x89,0xbc,0x74,0x2, 0xac,0xb3,0x49,0x45,0x23,0x34,0xa, +0x38,0x7c,0x27,0x19,0x25,0x66,0x4b,0x7c,0x29,0x19,0x25,0x66,0x4c,0xb, 0x30,0x7e, +0x23,0x67,0xd5,0xbc,0x23,0x38,0xdd,0x6c,0x33,0x80,0x1b,0x74,0x2, 0xac,0xb3,0x7f, +0x16,0x2d,0x35,0xb, 0x1a,0x40,0xa, 0x38,0x7c,0x27,0x19,0x25,0x66,0x87,0x7c,0x29, +0x19,0x25,0x66,0x88,0xb, 0x30,0x7e,0x23,0x67,0xd6,0xbc,0x23,0x38,0xdd,0x22,0xe4, +0x7a,0xb3,0x67,0xd5,0x7a,0xb3,0x67,0xd6,0x22,0xe4,0x7a,0xb3,0x73,0x2c,0x22,0x7c, +0x7b,0xa, 0x57,0x9e,0x54,0x0, 0x20,0xe, 0x54,0xe, 0x54,0xe, 0x54,0xe, 0x54,0x7c, +0xab,0x7c,0x67,0x5e,0x60,0xf0,0xa5,0xbe,0x20,0x1d,0x7c,0xb7,0x54,0xf, 0x7e,0x24, +0x0, 0x1, 0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0x7e,0x73,0x73,0x46,0xa, 0x47,0x5d, +0x42,0x7e,0x73,0x71,0x37,0x80,0x40,0xa5,0xbe,0x30,0x1d,0x7c,0xb7,0x54,0xf, 0x7e, +0x34,0x0, 0x1, 0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7e,0x53,0x73,0x47,0xa, 0x45, +0x5d,0x43,0x7e,0x73,0x71,0x38,0x80,0x1f,0x7c,0xb7,0x54,0xf, 0x7e,0x34,0x0, 0x1, +0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0xa, 0x2a,0x9, 0xb2,0x73,0x46,0xa, 0x4b,0x5d, +0x43,0xa, 0x5a,0x9, 0x75,0x71,0x39,0xa, 0x57,0x5d,0x54,0x22,0x7e,0x17,0x28,0x2, +0xbd,0x13,0x28,0xa, 0x7a,0x37,0x28,0x2, 0x7a,0x27,0x28,0x4, 0x80,0x10,0x7e,0x17, +0x27,0xfa,0xbd,0x13,0x50,0x8, 0x7a,0x37,0x27,0xfa,0x7a,0x27,0x27,0xfc,0x7e,0x17, +0x28,0x0, 0xbd,0x12,0x28,0xa, 0x7a,0x27,0x28,0x0, 0x7a,0x37,0x27,0xfe,0x80,0x10, +0x7e,0x17,0x28,0x8, 0xbd,0x12,0x50,0x8, 0x7a,0x27,0x28,0x8, 0x7a,0x37,0x28,0x6, +0x7e,0xb3,0x28,0x1a,0xb4,0xa, 0x19,0x7e,0x37,0x27,0xfa,0x9e,0x37,0x28,0x2, 0x7a, +0x37,0x28,0x12,0x7e,0x37,0x28,0x8, 0x9e,0x37,0x28,0x0, 0x7a,0x37,0x28,0x14,0x22, +0xb4,0xf, 0x18,0x7e,0x37,0x27,0xfa,0x9e,0x37,0x28,0x2, 0x7a,0x37,0x28,0x16,0x7e, +0x37,0x28,0x8, 0x9e,0x37,0x28,0x0, 0x7a,0x37,0x28,0x18,0x22,0x7e,0xb3,0x27,0xf2, +0xb4,0x4, 0x2, 0xd3,0x22,0xc3,0x22,0x7e,0xa3,0x28,0x1a,0xbe,0xa0,0xf0,0x50,0x1b, +0x74,0x4, 0xa4,0x59,0x35,0x24,0x31,0x7e,0xa3,0x28,0x1a,0x74,0x4, 0xa4,0x59,0x25, +0x24,0x33,0x7e,0xb3,0x28,0x1a,0x4, 0x7a,0xb3,0x28,0x1a,0x22,0x7d,0xf2,0x7d,0xe3, +0x7e,0x8, 0x27,0xf2,0x7e,0x34,0x0, 0x28,0xe4,0x12,0x24,0x39,0x7e,0x8, 0x24,0x31, +0x7e,0x34,0x3, 0xc0,0x12,0x24,0x39,0x7a,0xb3,0x71,0x39,0x7e,0x34,0x22,0x6d,0x12, +0x30,0xa4,0x7a,0x37,0x24,0x29,0x7a,0xe7,0x27,0xf6,0x7a,0xf7,0x27,0xf8,0x7a,0xe7, +0x27,0xfa,0x7a,0xe7,0x27,0xfe,0x7a,0xe7,0x28,0x2, 0x7a,0xe7,0x28,0x6, 0x7a,0xf7, +0x27,0xfc,0x7a,0xf7,0x28,0x0, 0x7a,0xf7,0x28,0x4, 0x7a,0xf7,0x28,0x8, 0x7a,0xe7, +0x24,0x2d,0x7a,0xf7,0x24,0x2f,0x7a,0xb3,0x28,0x1a,0x74,0x2, 0x7a,0xb3,0x27,0xf1, +0x22,0x74,0xfe,0x7a,0xb3,0x71,0x39,0xe4,0x7a,0xb3,0x27,0xf2,0x22,0x7e,0x8, 0x5d, +0x7, 0x7e,0x34,0x0, 0x48,0xe4,0x2, 0x24,0x39,0x6d,0x22,0x12,0xd, 0x3e,0x7e,0x8, +0x0, 0xa1,0x6d,0x22,0x12,0xd, 0x3e,0x7e,0x34,0x0, 0xb, 0x7e,0x8, 0x0, 0x65,0x7e, +0x24,0x0, 0x2, 0x22,0xa, 0x25,0x2d,0x21,0x7d,0x13,0x1e,0x14,0x3e,0x14,0x59,0x21, +0x5f,0xbd,0xb, 0x35,0x7a,0x35,0x39,0xbe,0x34,0x1, 0x1a,0x22,0x6d,0x33,0x7e,0xf, +0x73,0x51,0x79,0x30,0x0, 0x16,0x7e,0x34,0x1, 0x2c,0x7e,0xf, 0x73,0x51,0x79,0x30, +0x0, 0x18,0x22,0x12,0x6, 0x48,0x7e,0x34,0x1, 0x6, 0x7e,0x27,0x5d,0x5b,0x22,0x12, +0x6, 0x48,0x7e,0x34,0x0, 0x17,0x7e,0x27,0x5d,0x57,0x22,0x12,0x6, 0x48,0x7e,0x34, +0x0, 0x8, 0x7e,0x27,0x5d,0x55,0x22,0x12,0x6, 0x48,0x7e,0x34,0x0, 0x2, 0x7e,0x27, +0x5d,0x53,0x22,0x12,0x6, 0x48,0x7e,0x34,0x0, 0x1, 0x7e,0x27,0x5d,0x51,0x22,0x7e, +0x73,0x5d,0x7, 0xa, 0x37,0xb, 0x34,0x7a,0x73,0x5d,0xa, 0x7e,0x73,0x5d,0x7, 0x7a, +0x73,0x5d,0xb, 0x22,0x7e,0x70,0x27,0xac,0x67,0x2e,0x34,0x6f,0x11,0x6d,0x22,0x7e, +0x8, 0x71,0x89,0x22,0x74,0x2, 0xac,0xb1,0x9, 0x95,0x66,0x4b,0x9, 0x5, 0x66,0x4c, +0x22,0x49,0x35,0x6f,0xbd,0x49,0x25,0x6f,0xbb,0x2, 0x9, 0xad,0x2e,0x34,0x6f,0x18, +0x6d,0x22,0x74,0x10,0x2, 0xb, 0x8, 0x7e,0xf1,0x3d,0x74,0xb5,0xac,0xfb,0x2e,0x74, +0x1, 0x0, 0x22,0x6d,0x33,0x7a,0x37,0x4d,0x43,0x22,0x9, 0x73,0x6f,0x13,0x2, 0xd, +0x23,0x7e,0x24,0x0, 0x12,0x2, 0x3, 0xfa,0x7e,0x24,0x0, 0x12,0x2, 0x4, 0x96,0x7e, +0xb3,0x71,0x86,0xbe,0xb0,0x1, 0x22,0x7e,0xb3,0x69,0x89,0xbe,0xb0,0x1, 0x22,0x12, +0x6, 0x48,0x7e,0x34,0x1, 0x2, 0x22,0x12,0x6, 0xc5,0x7e,0x34,0x1, 0x2, 0x22,0x12, +0x6, 0x48,0x7e,0x34,0x1, 0x1, 0x22,0x12,0x6, 0xc5,0x7e,0x34,0x1, 0x1, 0x22,0x12, +0x6, 0x48,0x7e,0x34,0x1, 0x0, 0x22,0xff, \ No newline at end of file diff --git a/drivers/input/touchscreen/ft8716/include/pramboot/FT8716_Pramboot_V0.5_20160723.i b/drivers/input/touchscreen/ft8716/include/pramboot/FT8716_Pramboot_V0.5_20160723.i new file mode 100644 index 0000000000000..8c27370a9170b --- /dev/null +++ b/drivers/input/touchscreen/ft8716/include/pramboot/FT8716_Pramboot_V0.5_20160723.i @@ -0,0 +1,246 @@ +0x2, 0x3, 0x83,0xca,0x39,0x12,0xf, 0x3c,0xda,0x39,0x32,0x2, 0x0, 0x3, 0x6d,0x22, +0x80,0x13,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xe5,0xb5,0x7a,0xb, +0xb0,0xb, 0x14,0xb, 0x24,0xbd,0x32,0x38,0xe9,0x22,0xff,0x2, 0xd, 0xf, 0xe5,0x33, +0xb4,0xc, 0xf, 0xc2,0x86,0xc2,0x87,0x7e,0x34,0x0, 0x64,0x12,0xe, 0x86,0xd2,0x86, +0xd2,0x87,0x22,0x2, 0x0, 0xf9,0xca,0x3b,0x7a,0xd, 0x10,0x7f,0x31,0xe5,0x24,0xb4, +0x80,0x2, 0x80,0x3, 0x2, 0x0, 0xdc,0x7f,0x13,0x5e,0x34,0x0, 0x7f,0x7d,0x23,0x7e, +0x34,0x0, 0x80,0x9d,0x32,0x7a,0x35,0x16,0x7e,0x35,0x14,0xbe,0x35,0x16,0x38,0x2, +0x80,0x5d,0x7e,0x35,0x16,0x7a,0x35,0x18,0x7f,0x13,0x7e,0xd, 0x10,0x12,0xa, 0xe6, +0x7e,0x35,0x14,0x9e,0x35,0x16,0x7a,0x35,0x14,0x7e,0x35,0x16,0x6d,0x22,0x2f,0x31, +0x7e,0x1d,0x10,0x2e,0x35,0x16,0x7a,0x1d,0x10,0x80,0x27,0x7e,0x34,0x0, 0x80,0x7a, +0x35,0x18,0x7f,0x13,0x7e,0xd, 0x10,0x12,0xa, 0xe6,0x7e,0x35,0x14,0x9e,0x34,0x0, +0x80,0x7a,0x35,0x14,0x7e,0x1d,0x10,0x2e,0x34,0x0, 0x80,0x7a,0x1d,0x10,0x2e,0x38, +0x0, 0x80,0x7e,0x35,0x14,0xbe,0x34,0x0, 0x80,0x50,0xd0,0x4d,0x33,0x68,0x26,0x7a, +0x35,0x18,0x7f,0x13,0x7e,0xd, 0x10,0x12,0xa, 0xe6,0x80,0x19,0x74,0x2, 0x12,0xa, +0x89,0x5e,0x70,0xf4,0x12,0xc, 0x86,0x7e,0x35,0x14,0x7a,0x35,0x18,0x7f,0x13,0x7e, +0xd, 0x10,0x12,0x8, 0xe, 0xd3,0xda,0x3b,0x22,0xa9,0xc0,0x93,0x75,0x39,0x0, 0x32, +0xf, 0x60,0xf0,0x9f,0x4c,0xf1,0xb3,0xe, 0xce,0xb9,0x31,0x46,0xff,0x0, 0xff,0x0, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0x7c,0x6b,0xc2,0x2, 0xe5,0x22,0x14,0x78,0x3, 0x2, 0x2, 0xda,0x1b,0xb1,0x78,0x3, +0x2, 0x2, 0x3d,0x1b,0xb1,0x78,0x3, 0x2, 0x2, 0x89,0x1b,0xb1,0x78,0x3, 0x2, 0x2, +0x9a,0x1b,0xb1,0x78,0x3, 0x2, 0x2, 0xc1,0x24,0xf9,0x78,0x3, 0x2, 0x2, 0xd6,0x24, +0xaf,0x78,0x3, 0x2, 0x3, 0x3b,0x24,0xfd,0x68,0x3a,0x14,0x78,0x3, 0x2, 0x2, 0xdd, +0x14,0x78,0x3, 0x2, 0x2, 0xda,0x1b,0xb2,0x78,0x3, 0x2, 0x2, 0xda,0x24,0xda,0x68, +0x26,0x24,0xe6,0x68,0x1f,0x24,0xeb,0x68,0x3b,0x24,0xf3,0x78,0x3, 0x2, 0x2, 0xda, +0x24,0xe4,0x78,0x3, 0x2, 0x3, 0x46,0x14,0x78,0x3, 0x2, 0x2, 0xda,0x24,0x94,0x68, +0x3, 0x2, 0x3, 0x82,0x2, 0x3, 0x42,0xbe,0x60,0x4, 0x50,0xc, 0x75,0x3f,0x0, 0x7c, +0x16,0x2e,0x10,0x25,0x7c,0xb7,0xa5,0xf7,0xa5,0xbe,0x0, 0x2, 0x80,0x3, 0x2, 0x3, +0x82,0xd2,0x2, 0x22,0x7c,0xb6,0x24,0x0, 0x78,0x3, 0x2, 0x3, 0x82,0x1b,0xb1,0x68, +0x1e,0x14,0x68,0x1e,0x14,0x68,0x1e,0x14,0x68,0x1e,0xb, 0xb2,0x78,0x33,0x30,0x1, +0x7, 0x7e,0x8, 0x0, 0x44,0x2, 0x2, 0x5a,0x7e,0x8, 0x1, 0x50,0x2, 0x2, 0x5a,0x2, +0x2, 0xfb,0x2, 0x3, 0x2, 0x2, 0x3, 0x1a,0xa, 0x27,0x7e,0xd, 0x3a,0xb, 0x16,0xb, +0xa, 0x30,0x2d,0x32,0x1b,0xa, 0x30,0x6d,0x33,0x7e,0xd, 0x3a,0x79,0x30,0x0, 0x6, +0x22,0x7c,0xb7,0x62,0x3f,0x7e,0x2d,0x3a,0x2e,0x54,0x0, 0x6, 0xb, 0x2a,0x20,0x7d, +0x12,0xb, 0x14,0x1b,0x2a,0x10,0x7e,0xd, 0x3a,0x2d,0x12,0x39,0x70,0x0, 0x8, 0x7e, +0xd, 0x3a,0x69,0x50,0x0, 0x4, 0x69,0x20,0x0, 0x6, 0xbd,0x25,0x50,0x3, 0x2, 0x3, +0x82,0xb2,0x1, 0x7a,0xd, 0x34,0x7e,0x34,0x0, 0x2, 0x2, 0x3, 0x7f,0x7c,0xb6,0x1b, +0xb1,0x68,0x1d,0x14,0x68,0x1d,0xb, 0xb1,0x68,0x3, 0x2, 0x3, 0x82,0x30,0x1, 0x6, +0x7e,0x8, 0x0, 0x44,0x80,0x4, 0x7e,0x8, 0x1, 0x50,0x7a,0xd, 0x3a,0x2, 0x2, 0xf3, +0x2, 0x2, 0xfb,0xa, 0x57,0x6d,0x44,0x7e,0xd, 0x3a,0x69,0x30,0x0, 0x2, 0xb, 0xa, +0x20,0x2f,0x12,0x79,0x30,0x0, 0x2, 0x1b,0xa, 0x20,0x7e,0x1d,0x3a,0x7a,0x1d,0x34, +0xd2,0x2, 0x7e,0x34,0x0, 0x1, 0x2, 0x3, 0x7f,0xbe,0x60,0x1, 0x68,0x9, 0xa5,0xbe, +0x2, 0x5, 0x7a,0x71,0x3e,0xd2,0x3, 0xd2,0x2, 0x22,0x75,0xe6,0x0, 0xe4,0x7e,0x34, +0x1, 0x4, 0x7e,0x24,0x0, 0xff,0x7a,0x1b,0xb0,0x7e,0x34,0x1, 0x5, 0x7a,0x1b,0xb0, +0x7e,0x34,0x1, 0x8, 0x7a,0x1b,0xb0,0x7e,0x34,0x1, 0x9, 0x7a,0x1b,0xb0,0xd2,0x4, +0x22,0xa5,0xbe,0x1, 0x4, 0x7a,0x71,0x38,0x22,0xa5,0xbe,0x2, 0x2, 0x80,0x3, 0x2, +0x3, 0x82,0x7a,0x71,0x23,0x22,0x7a,0x71,0x33,0x22,0xd2,0x2, 0x22,0x7c,0xb6,0x1b, +0xb1,0x68,0x18,0x14,0x68,0x1c,0x14,0x68,0x31,0x14,0x68,0x3a,0xb, 0xb2,0x68,0x3, +0x2, 0x3, 0x82,0xa, 0x37,0x7d,0x3, 0x6d,0x11,0x80,0x59,0xa, 0x57,0x7c,0xab,0xe4, +0x80,0x2, 0xa, 0x57,0x6d,0x44,0x7e,0xd, 0x3a,0x69,0x30,0x0, 0x2, 0xb, 0xa, 0x20, +0x2f,0x12,0x79,0x30,0x0, 0x2, 0x1b,0xa, 0x20,0x22,0x7c,0x67,0x6c,0x77,0x7e,0xd, +0x3a,0x79,0x30,0x0, 0x4, 0x22,0xa, 0x27,0x7e,0xd, 0x3a,0xb, 0x16,0xb, 0xa, 0x30, +0x2d,0x32,0x1b,0xa, 0x30,0x7e,0x34,0x0, 0x3, 0x80,0x44,0x7e,0x34,0x0, 0x4, 0x7a, +0x35,0x2f,0x75,0x3f,0x0, 0x22,0x1b,0x61,0x68,0x15,0xb, 0x60,0x78,0x34,0x7c,0x27, +0x6c,0x33,0x6d,0x0, 0x7e,0x1d,0x3a,0x79,0x11,0x0, 0x2, 0x1b,0x1a,0x0, 0x22,0xa, +0x57,0x6d,0x44,0x7e,0xd, 0x3a,0x69,0x30,0x0, 0x2, 0xb, 0xa, 0x20,0x2f,0x12,0x79, +0x30,0x0, 0x2, 0x1b,0xa, 0x20,0xe4,0x7a,0xb3,0x2, 0xe4,0x7e,0x34,0x0, 0x5, 0x7a, +0x35,0x2f,0x22,0x75,0x84,0x1, 0x7e,0x44,0x1f,0xff,0xe4,0x7a,0x49,0xb0,0x1b,0x44, +0x78,0xf9,0x7e,0xf8,0x2, 0xe8,0xd2,0x7, 0xc2,0x8, 0x75,0x3f,0x0, 0x75,0x40,0x87, +0x75,0x41,0xa6,0x75,0x42,0x0, 0x75,0x43,0x0, 0xd2,0x0, 0xc2,0x2, 0xc2,0x3, 0xc2, +0x4, 0x75,0x22,0x0, 0x75,0x23,0x0, 0x75,0x24,0x80,0x75,0x2f,0x0, 0x75,0x30,0x0, +0x75,0x31,0x0, 0x75,0x32,0x0, 0x75,0x33,0x0, 0x75,0x38,0xb, 0x75,0x39,0x0, 0x75, +0x3e,0x1, 0x7e,0x4, 0x0, 0xff,0x7e,0x14,0xf, 0x50,0xb, 0xa, 0x40,0x5d,0x44,0x68, +0x1a,0x69,0x20,0x0, 0x2, 0xb, 0xe, 0xb, 0x44,0x80,0xa, 0x7e,0xb, 0xb0,0x7a,0x29, +0xb0,0xb, 0x24,0xb, 0xc, 0x1b,0x44,0x78,0xf2,0x80,0xdf,0x2, 0x4, 0x20,0xff,0xff, +0x56,0x30,0x2e,0x35,0x4a,0x75,0x6c,0x20,0x32,0x33,0x20,0x32,0x30,0x31,0x36,0x0, +0x46,0x54,0x53,0x38,0x37,0x31,0x36,0x5f,0x70,0x72,0x61,0x6d,0x62,0x6f,0x6f,0x74, +0x12,0xe, 0x63,0x2, 0x5, 0xbc,0x7e,0x35,0x2f,0x1b,0x34,0x68,0x60,0x1b,0x35,0x78, +0x3, 0x2, 0x4, 0xbc,0x1b,0x34,0x78,0x3, 0x2, 0x4, 0xe6,0x1b,0x34,0x78,0x3, 0x2, +0x5, 0x96,0x2e,0x34,0x0, 0x3, 0x68,0x3, 0x2, 0x5, 0xa8,0x6d,0x33,0x7a,0x35,0x2f, +0x7a,0x35,0x31,0x30,0x7, 0x5, 0x12,0x0, 0x2e,0xc2,0x7, 0x7e,0xd, 0x34,0x69,0x30, +0x0, 0x4, 0x7a,0x35,0x14,0x69,0x30,0x0, 0x2, 0xb, 0xa, 0x20,0x2e,0x14,0x0, 0x8, +0x12,0x0, 0x46,0xd2,0x7, 0x7e,0x2d,0x34,0x69,0x12,0x0, 0x4, 0x69,0x32,0x0, 0x2, +0xb, 0x2a,0x20,0x12,0xb, 0xe2,0x2e,0x34,0x10,0x0, 0x2, 0x5, 0x91,0x6d,0x33,0x7a, +0x35,0x2f,0x7e,0x34,0x1, 0x0, 0x7a,0x35,0x15,0x7e,0xd, 0x34,0x69,0x30,0x0, 0x2, +0xb, 0xa, 0x20,0x2e,0x14,0x0, 0x8, 0x12,0xe, 0xf2,0x20,0x0, 0x3, 0x2, 0x5, 0xa8, +0x7e,0x1d,0x34,0x29,0xb1,0x0, 0x8, 0xf5,0x91,0x2, 0x5, 0xa8,0x6d,0x33,0x7a,0x35, +0x2f,0x7a,0x35,0x31,0x7e,0x18,0x0, 0x3f,0x7a,0x1d,0xe, 0x7e,0xd, 0x34,0x69,0x30, +0x0, 0x2, 0xb, 0xa, 0x20,0x69,0x10,0x0, 0x4, 0x12,0x7, 0x62,0x12,0x0, 0x2e,0x7e, +0x34,0xf0,0x55,0x2, 0x5, 0x91,0x7e,0x18,0x10,0x0, 0x7a,0x1d,0x8, 0xd2,0x5, 0x6d, +0x33,0x7a,0x35,0x2f,0x7a,0x35,0x31,0xe5,0x38,0xb4,0xa, 0x17,0xe5,0x24,0xb4,0x80, +0xc, 0xe4,0x12,0xc, 0xd1,0x74,0x1, 0x12,0xc, 0xd1,0x2, 0x5, 0x7f,0x12,0x8, 0xa4, +0x2, 0x5, 0x7f,0xe5,0x38,0xb4,0xb, 0x27,0xe5,0x24,0xb4,0x80,0x11,0x7e,0xf0,0x1, +0x7c,0xbf,0x12,0x5, 0xc3,0xb, 0xf0,0xbe,0xf0,0x11,0x78,0xf4,0x80,0x51,0x7e,0xf0, +0x4, 0x7c,0xbf,0x12,0x5, 0xc3,0xb, 0xf0,0xbe,0xf0,0x40,0x78,0xf4,0x80,0x40,0xe5, +0x38,0xa, 0x3b,0x9e,0x34,0x0, 0x80,0x7c,0xe7,0xe5,0x24,0xb4,0x80,0x10,0xa, 0x3e, +0x6d,0x22,0x74,0xc, 0x2f,0x11,0x14,0x78,0xfb,0x7a,0x1d,0x8, 0x80,0xe, 0xa, 0x3e, +0x6d,0x22,0x74,0xa, 0x2f,0x11,0x14,0x78,0xfb,0x7a,0x1d,0x8, 0x6c,0xdd,0x80,0x9, +0x7c,0xbe,0x12,0x5, 0xc3,0xb, 0xe0,0xb, 0xd0,0xe5,0x23,0xbc,0xbd,0x38,0xf1,0x7e, +0x1d,0x8, 0x12,0xe, 0xd, 0x92,0x5, 0x12,0x0, 0x2e,0x30,0x5, 0x1b,0x7e,0x34,0xf0, +0xaa,0x7a,0x35,0x31,0x80,0x12,0x6d,0x33,0x7a,0x35,0x2f,0x7a,0x35,0x31,0x7e,0xd, +0x34,0x69,0x30,0x0, 0x2, 0x12,0x6, 0x98,0x30,0x4, 0x11,0x7e,0x34,0x13,0x88,0x12, +0xe, 0x86,0x7e,0x34,0x13,0x88,0x12,0xe, 0x86,0x75,0xe9,0xff,0x30,0x8, 0x3, 0x2, +0x4, 0x26,0x22,0xca,0xf8,0x7c,0xfb,0xe5,0x24,0xb4,0x80,0x4a,0xd2,0x6, 0x12,0xe, +0xdf,0x74,0x20,0xca,0xb8,0xa, 0x3f,0x6d,0x22,0x74,0xc, 0x2f,0x11,0x14,0x78,0xfb, +0xda,0xb8,0x12,0xd, 0xb3,0xa9,0xd2,0xb4,0x12,0xf, 0x32,0x12,0xe, 0xca,0x50,0x9, +0x7e,0x35,0x42,0xbe,0x34,0x1, 0xf4,0x28,0xf2,0x7e,0x35,0x42,0xbe,0x34,0x1, 0xf4, +0x38,0x6, 0x12,0xf, 0x4d,0x2, 0x6, 0x95,0xc2,0x86,0x7e,0x34,0x13,0x88,0x12,0xe, +0x86,0xd2,0x86,0x2, 0x6, 0x95,0x74,0x1, 0x12,0xa, 0x21,0x74,0x1, 0x6d,0x33,0x12, +0xc, 0x86,0xe4,0x12,0xa, 0x89,0x5e,0x34,0x80,0x0, 0x7c,0x4f,0x6c,0x55,0x3e,0x24, +0x4d,0x32,0x12,0xc, 0x86,0x74,0x4, 0x6d,0x33,0x12,0xc, 0x86,0x7e,0x34,0x0, 0x50, +0x12,0xc, 0x86,0x7e,0x34,0x0, 0x19,0x12,0xe, 0x86,0x74,0x4, 0x7e,0x34,0x0, 0x51, +0x12,0xc, 0x86,0x7e,0x34,0xa2,0x1c,0x12,0xe, 0x86,0x74,0x4, 0x7e,0x34,0x0, 0x11, +0x12,0xc, 0x86,0x7e,0x34,0x0, 0x19,0x12,0xe, 0x86,0x74,0x4, 0x7e,0x34,0x0, 0x10, +0x12,0xc, 0x86,0x7e,0x34,0x0, 0x19,0x12,0xe, 0x86,0x74,0x4, 0x6d,0x33,0x12,0xc, +0x86,0x7e,0x34,0x0, 0x5, 0x12,0xe, 0x86,0xe4,0x12,0xa, 0x21,0x74,0x4, 0x7e,0x34, +0xff,0xf7,0x12,0xc, 0x86,0xda,0xf8,0x22,0xca,0xf8,0xe4,0x7a,0xb3,0x2, 0xe4,0xe5, +0x24,0xbe,0xb0,0x80,0x68,0x9, 0x74,0x1, 0x7a,0xb3,0x2, 0xe4,0x2, 0x7, 0x5f,0xbe, +0x34,0xff,0xff,0x68,0x6, 0xbe,0x34,0x0, 0x12,0x50,0x4, 0x7e,0x34,0x0, 0x12,0x7d, +0x13,0x6d,0x0, 0x74,0xc, 0x2f,0x0, 0x14,0x78,0xfb,0x7a,0xd, 0xc, 0x7c,0xb7,0x12, +0x5, 0xc3,0x7e,0x1d,0xc, 0x12,0xe, 0xd, 0xe4,0x33,0x7c,0xfb,0xbe,0xf0,0x1, 0x78, +0xa, 0x7e,0xb3,0x2, 0xe4,0x44,0x2, 0x7a,0xb3,0x2, 0xe4,0x6c,0xaa,0xa, 0x3a,0x19, +0xa3,0x2, 0xdc,0xb, 0xa0,0xbe,0xa0,0x8, 0x78,0xf3,0x7e,0x34,0x0, 0x8, 0x7a,0x35, +0x14,0x7e,0x1d,0xc, 0x7e,0x8, 0x2, 0xdc,0x12,0x0, 0x46,0x6c,0xaa,0xe4,0xa, 0x4a, +0x19,0xb4,0x2, 0xdc,0xb, 0xa0,0xbe,0xa0,0x8, 0x78,0xf3,0x7e,0x34,0x0, 0x8, 0x7a, +0x35,0x15,0x7e,0x1d,0xc, 0x7e,0x8, 0x2, 0xdc,0x12,0xe, 0xf2,0x7e,0xf0,0x1, 0x6c, +0xaa,0xa, 0x3a,0x9, 0xb3,0x2, 0xdc,0xbc,0xba,0x68,0x4, 0x6c,0xff,0x80,0x7, 0xb, +0xa0,0xbe,0xa0,0x8, 0x40,0xeb,0xbe,0xf0,0x1, 0x78,0xa, 0x7e,0xb3,0x2, 0xe4,0x44, +0x4, 0x7a,0xb3,0x2, 0xe4,0x7e,0xb3,0x2, 0xe4,0x44,0x1, 0x7a,0xb3,0x2, 0xe4,0xda, +0xf8,0x22,0xca,0x3b,0x7a,0x15,0xc, 0x7f,0x31,0x75,0x12,0x0, 0x7e,0x35,0xc, 0xbe, +0x34,0x0, 0x0, 0x38,0x4f,0x7e,0x34,0xff,0xff,0x7a,0x35,0xc, 0x75,0x12,0x1, 0x80, +0x43,0x7e,0x34,0x0, 0x80,0x7a,0x35,0x15,0x7f,0x13,0x7e,0x8, 0x2, 0x5c,0x12,0xe, +0xf2,0x7e,0x35,0xc, 0x9e,0x34,0x0, 0x80,0x7a,0x35,0xc, 0x2e,0x38,0x0, 0x80,0x6d, +0x33,0x7a,0x35,0x13,0x7e,0x35,0x13,0x9, 0x63,0x2, 0x5c,0x7e,0xd, 0xe, 0x7e,0xb, +0x70,0x6c,0x76,0x7a,0xb, 0x70,0x7e,0x35,0x13,0xb, 0x34,0x7a,0x35,0x13,0xbe,0x34, +0x0, 0x80,0x78,0xe0,0x7e,0x35,0xc, 0xbe,0x34,0x0, 0x80,0x38,0xb4,0xe5,0x12,0x60, +0x5, 0xb, 0x34,0x7a,0x35,0xc, 0x7e,0x35,0xc, 0x7a,0x35,0x15,0x7f,0x13,0x7e,0x8, +0x2, 0x5c,0x12,0xe, 0xf2,0x6d,0x33,0x80,0x17,0x7e,0x35,0x13,0x9, 0x63,0x2, 0x5c, +0x7e,0xd, 0xe, 0x7e,0xb, 0x70,0x6c,0x76,0x7a,0xb, 0x70,0x7e,0x35,0x13,0xb, 0x34, +0x7a,0x35,0x13,0x7e,0x35,0xc, 0xbe,0x35,0x13,0x38,0xde,0xda,0x3b,0x22,0xca,0x3b, +0x7f,0x30,0x7c,0xb6,0xf5,0x1a,0x7c,0xb7,0xf5,0x1b,0x74,0x1, 0x7e,0x35,0x18,0x1e, +0x34,0x1b,0x34,0x4e,0x60,0x80,0x12,0xc, 0x86,0x12,0xa, 0x21,0xa9,0xc2,0xb4,0xa9, +0xc6,0xb3,0x75,0xb5,0x2, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9, +0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x85,0x1a,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3, +0x85,0x1b,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x6d,0x33,0x80,0x2a,0x7f,0x13, +0x2e,0x35,0x1c,0x7e,0x1b,0xb0,0xf5,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7e, +0x35,0x1c,0x5e,0x34,0x0, 0x1, 0xbe,0x34,0x0, 0x1, 0x78,0x7, 0x7e,0x34,0x0, 0x78, +0x12,0xe, 0x86,0x7e,0x35,0x1c,0xb, 0x34,0x7a,0x35,0x1c,0x7e,0x35,0x18,0xbe,0x35, +0x1c,0x38,0xcb,0xa9,0xd2,0xb4,0x7e,0x34,0x0, 0x5, 0x12,0xe, 0x86,0xe4,0x12,0xa, +0x21,0xda,0x3b,0x22,0xe5,0x24,0xb4,0x80,0x16,0xd2,0x6, 0x12,0xe, 0xdf,0xa9,0xc2, +0xb4,0x74,0x60,0x12,0xf, 0x27,0xa9,0xd2,0xb4,0x12,0xe, 0xca,0x40,0xfb,0x22,0x74, +0x1, 0x12,0xa, 0x21,0xe4,0x6d,0x33,0x12,0xc, 0x86,0x74,0x1, 0x6d,0x33,0x12,0xc, +0x86,0x74,0x4, 0x6d,0x33,0x12,0xc, 0x86,0x7e,0x34,0x0, 0x54,0x12,0xc, 0x86,0x7e, +0x34,0x0, 0x19,0x12,0xe, 0x86,0x74,0x4, 0x7e,0x34,0x0, 0x55,0x12,0xc, 0x86,0x7e, +0x34,0xa2,0x1c,0x12,0xe, 0x86,0x74,0x4, 0x7e,0x34,0x0, 0x15,0x12,0xc, 0x86,0x7e, +0x34,0x0, 0xa0,0x12,0xe, 0x86,0x74,0x4, 0x7e,0x34,0x0, 0x14,0x12,0xc, 0x86,0x7e, +0x34,0x0, 0x19,0x12,0xe, 0x86,0x74,0x4, 0x7e,0x34,0x0, 0x4, 0x12,0xc, 0x86,0x7e, +0x34,0x0, 0x5, 0x12,0xe, 0x86,0xe4,0x12,0xa, 0x21,0x74,0x4, 0x7e,0x34,0xff,0xf7, +0x2, 0xc, 0x86,0x7c,0x7b,0x7e,0xa0,0xef,0xe5,0x22,0x24,0xfd,0x68,0x3c,0x1b,0xb1, +0x68,0x26,0x24,0x9f,0x68,0x41,0x1b,0xb2,0x68,0x42,0x24,0x9e,0x68,0x39,0x24,0xe3, +0x68,0x52,0x24,0x59,0x78,0x52,0xa5,0xbf,0x0, 0x5, 0x7e,0xa1,0x40,0x80,0x49,0xa5, +0xbf,0x1, 0x45,0x7e,0xa1,0x41,0x80,0x40,0xa5,0xbf,0x0, 0x5, 0x7e,0xa1,0x24,0x80, +0x37,0xa5,0xbf,0x1, 0x33,0x7e,0xa1,0x3e,0x80,0x2e,0xa, 0x17,0x7e,0x1d,0x3a,0x2d, +0x31,0x29,0xa1,0x0, 0x8, 0x80,0x21,0x7e,0xa1,0x3f,0x80,0x1c,0xa5,0xbf,0x0, 0x9, +0x7e,0x35,0x31,0xa, 0x56,0x7c,0xab,0x80,0xf, 0xa5,0xbf,0x1, 0xb, 0x7e,0x55,0x31, +0x7c,0xab,0x80,0x4, 0x7e,0xa3,0x2, 0xe4,0x7c,0xba,0x22,0xca,0x79,0x6c,0xee,0x7e, +0xf0,0x70,0x75,0x91,0x0, 0xc2,0x90,0xc2,0x91,0x30,0x8, 0x31,0x7e,0x34,0x0, 0x2, +0x7a,0x35,0x15,0x9f,0x11,0x7e,0x8, 0x0, 0xc, 0x12,0xe, 0xf2,0xe5,0xc, 0xbe,0xb0, +0xff,0x68,0x1a,0xe5,0xc, 0x60,0x16,0xe5,0xd, 0xa, 0x2b,0xe5,0xc, 0xa, 0x3b,0x2d, +0x32,0xbe,0x34,0x0, 0xff,0x78,0x6, 0x7e,0xf1,0xc, 0x7e,0xe0,0x1, 0x4c,0xee,0x78, +0x1c,0xa9,0xd1,0xcb,0xd2,0xcc,0x12,0xc, 0x35,0x7c,0xfb,0xc2,0xcc,0xa9,0xc1,0xcb, +0xbe,0xf0,0x2, 0x40,0x5, 0xbe,0xf0,0xfd,0x28,0x3, 0x7e,0xf0,0x70,0x7c,0xbf,0x54, +0xfe,0xf5,0x92,0xd2,0xe8,0xc2,0xc0,0xa9,0xd5,0xb7,0xd2,0xbd,0xd2,0xad,0xda,0x79, +0x22,0xca,0x79,0xbe,0xb0,0x0, 0x28,0x2e,0x74,0x6, 0x12,0xa, 0x89,0x7d,0x73,0x6c, +0xff,0x7e,0xf0,0xa5,0x7d,0x37,0x12,0xc, 0x86,0x6c,0xff,0x7e,0xf0,0xf, 0x7d,0x37, +0x12,0xc, 0x86,0x6c,0xff,0x7e,0xf0,0x6a,0x7d,0x37,0x12,0xc, 0x86,0x7e,0x34,0x0, +0x5, 0x12,0xe, 0x86,0x80,0x30,0x74,0x1, 0x7e,0x34,0xdf,0xff,0x12,0xc, 0x86,0x74, +0x6, 0x12,0xa, 0x89,0x7d,0x73,0x6c,0xff,0x7d,0x37,0x12,0xc, 0x86,0x7d,0x37,0x12, +0xc, 0x86,0x7d,0x37,0x12,0xc, 0x86,0x74,0x2, 0x12,0xa, 0x89,0x7d,0x73,0x4e,0xf0, +0x1, 0x7d,0x37,0x12,0xc, 0x86,0xda,0x79,0x22,0xa9,0xc2,0xb4,0xa9,0xc6,0xb3,0x75, +0xb5,0x5, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc, +0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xf5,0xb5,0xa9, +0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3, +0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7e,0x71,0xb5,0x75,0xb5,0x0, +0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7e,0xa1,0xb5,0xa9,0xd2,0xb4,0x7c,0x47,0x6c, +0x55,0xa, 0x3a,0x4d,0x32,0x22,0x7f,0x70,0xd2,0x6, 0x12,0xe, 0xdf,0x74,0x2, 0x12, +0xd, 0xb3,0x6d,0x33,0x80,0x12,0x7f,0x7, 0x2d,0x13,0x7e,0xb, 0xb0,0xf5,0xb5,0xa9, +0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xb, 0x34,0x7e,0x25,0x18,0xbd,0x23,0x38,0xe7,0xa9, +0xd2,0xb4,0x12,0xf, 0x32,0x12,0xe, 0xca,0x50,0x9, 0x7e,0x35,0x42,0xbe,0x34,0x1, +0xf4,0x28,0xf2,0x7e,0x35,0x42,0xbe,0x34,0x1, 0xf4,0x38,0x3, 0x2, 0xf, 0x4d,0xc2, +0x86,0x7e,0x34,0x13,0x88,0x12,0xe, 0x86,0xd2,0x86,0x22,0xa9,0xd1,0xcb,0xd2,0xcc, +0x7e,0x34,0x0, 0x4, 0x7e,0x8, 0x2, 0x5c,0x74,0xc, 0x12,0xb, 0x8f,0xa9,0xd1,0xcb, +0xc2,0xcc,0x6c,0xaa,0x7e,0x70,0x2, 0xac,0x7a,0x7e,0x8, 0x2, 0x5c,0x2d,0x13,0xb, +0xa, 0x30,0x7d,0x23,0x7c,0x45,0x6c,0x55,0xa, 0x36,0x4d,0x32,0x1b,0xa, 0x30,0xb, +0xa0,0xbe,0xa0,0xc, 0x78,0xde,0x7e,0x37,0x2, 0x6c,0x7d,0x23,0xa, 0x54,0x7c,0xa7, +0xb4,0xe7,0xb, 0xbe,0xa0,0x16,0x78,0x6, 0x75,0x40,0xe7,0x75,0x41,0xa6,0x22,0x7e, +0x24,0x0, 0x1, 0x7e,0x7f,0x2, 0xe5,0x79,0x27,0x0, 0x6, 0x7e,0x7f,0x2, 0xe5,0x69, +0x27,0x0, 0x6, 0x4d,0x22,0x78,0xf4,0x5e,0x60,0x7f,0x1b,0x7a,0x30,0x7e,0x1f,0x2, +0xe5,0x69,0x31,0x0, 0x8, 0x4d,0x33,0x68,0xf4,0x6c,0xaa,0x80,0x20,0x6d,0x44,0x7e, +0x1f,0x2, 0xe5,0x1b,0x1a,0x40,0x7e,0x1f,0x2, 0xe5,0x69,0x41,0x0, 0x8, 0x4d,0x44, +0x68,0xf4,0x69,0x41,0x0, 0x2, 0x1b,0xa, 0x40,0xb, 0x15,0xb, 0xa0,0xbc,0xba,0x38, +0xdc,0x22,0x6d,0x0, 0x74,0x10,0x4d,0x0, 0x78,0xb, 0x4d,0x22,0x78,0x27,0x8d,0x31, +0x7d,0x12,0x6d,0x22,0x22,0x7d,0x43,0x7d,0x32,0x6d,0x22,0x2f,0x11,0x2d,0x44,0x50, +0x2, 0xa5,0xf, 0xbf,0x10,0x40,0x4, 0x9f,0x10,0xb, 0x90,0x14,0x78,0xed,0x7f,0x1, +0x6d,0x22,0x7d,0x34,0x22,0x7d,0x41,0x7d,0x13,0x8d,0x24,0x7d,0x2, 0x2f,0x0, 0x40, +0x4, 0xbd,0x4, 0x40,0x4, 0x9d,0x4, 0xb, 0x14,0x14,0x78,0xf1,0x7d,0x23,0x7d,0x31, +0x7d,0x10,0x6d,0x0, 0x22,0x7e,0x34,0x0, 0x2, 0x7e,0xf, 0x2, 0xe5,0x79,0x30,0x0, +0x4, 0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x2, 0xe5,0x79,0x30,0x0, 0x6, 0x7e,0xf, 0x2, +0xe5,0x69,0x30,0x0, 0x6, 0x4d,0x33,0x78,0xf4,0x7e,0x34,0x0, 0x4, 0x1b,0xa, 0x30, +0x7e,0xf, 0x2, 0xe5,0x69,0x30,0x0, 0x8, 0x4d,0x33,0x68,0xf4,0x6d,0x33,0x1b,0xa, +0x30,0x7e,0x1f,0x2, 0xe5,0x69,0x11,0x0, 0x8, 0x4d,0x11,0x68,0xf4,0x69,0x51,0x0, +0x2, 0x5e,0x54,0x0, 0xfe,0x22,0x7d,0x23,0xa, 0x36,0x7c,0xa5,0xa9,0xc2,0xb4,0xa9, +0xc6,0xb3,0x75,0xb5,0x1, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9, +0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3, +0xf5,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x71,0xb5,0xa9,0x36,0xb3,0xfc, +0xa9,0xc6,0xb3,0x7a,0xa1,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xa9,0xd2,0xb4, +0x22,0x7c,0xab,0xd2,0x6, 0x12,0xe, 0xdf,0x74,0xd8,0xa, 0x3a,0x7d,0x23,0x6d,0x33, +0x12,0xd, 0xb3,0xa9,0xd2,0xb4,0x12,0xf, 0x32,0x12,0xe, 0xca,0x50,0x9, 0x7e,0x35, +0x42,0xbe,0x34,0x5, 0xdc,0x28,0xf2,0x7e,0x35,0x42,0xbe,0x34,0x5, 0xdc,0x38,0x3, +0x2, 0xf, 0x4d,0xc2,0x86,0x7e,0x34,0x13,0x88,0x12,0xe, 0x86,0xd2,0x86,0x22,0xca, +0x2b,0xca,0x1b,0xca,0xb, 0xd2,0x0, 0x30,0x90,0x1c,0xc2,0x90,0x7e,0x71,0x91,0xe5, +0x39,0x70,0x3, 0x7a,0x71,0x22,0xe5,0x39,0x12,0x1, 0x20,0x5, 0x39,0x30,0x2, 0x6, +0xe4,0x12,0x9, 0x33,0xf5,0x91,0x30,0x91,0xb, 0xc2,0x91,0x5, 0x39,0xe5,0x39,0x12, +0x9, 0x33,0xf5,0x91,0xda,0xb, 0xda,0x1b,0xda,0x2b,0x32,0xd2,0x6, 0x12,0xe, 0xdf, +0xa9,0xc2,0xb4,0x74,0x9f,0x12,0xf, 0x27,0x12,0xf, 0xe, 0xa9,0xd2,0xb4,0x60,0x3, +0xb4,0xff,0x1a,0x75,0x24,0x81,0xa9,0xd5,0xca,0xa9,0xd0,0xca,0x75,0xed,0x9f,0x75, +0xad,0x20,0xa9,0xd1,0xea,0xa9,0xc1,0xea,0x74,0x1, 0x2, 0xd, 0xe0,0x2, 0xd, 0x80, +0xd2,0x6, 0x12,0xe, 0xdf,0xa9,0xc2,0xb4,0x74,0x5, 0x12,0xf, 0x27,0x12,0xf, 0xe, +0x7c,0xab,0xa9,0xd2,0xb4,0xd2,0x6, 0x12,0xe, 0xdf,0x5e,0xa0,0xe3,0xa9,0xc2,0xb4, +0x74,0x1, 0x12,0xf, 0x27,0x7c,0xba,0x12,0xf, 0x27,0xa9,0xd2,0xb4,0x12,0xe, 0xca, +0x40,0xfb,0x22,0x7c,0xab,0x7d,0x12,0x7c,0xb3,0xf5,0x1c,0x7c,0x36,0x7c,0x25,0xa, +0x4, 0x7c,0xb3,0xf5,0x1b,0x7c,0xb7,0xf5,0x1a,0xa9,0xc2,0xb4,0x7c,0xba,0x12,0xf, +0x27,0xe5,0x1c,0x12,0xf, 0x27,0xe5,0x1b,0x12,0xf, 0x27,0xe5,0x1a,0x2, 0xf, 0x27, +0xca,0xf8,0x7c,0xfb,0xe5,0x24,0xb4,0x81,0x21,0x74,0x2, 0x12,0xa, 0x89,0x4c,0xff, +0x78,0x8, 0xa9,0xc0,0xca,0x5e,0x70,0xdf,0x80,0x6, 0xa9,0xd0,0xca,0x4e,0x70,0x20, +0x74,0x2, 0x12,0xc, 0x86,0x74,0x2, 0x12,0xa, 0x89,0xda,0xf8,0x22,0xd2,0x6, 0x7e, +0x14,0x0, 0x8, 0x7a,0x15,0x15,0x7e,0x8, 0x2, 0xdc,0x12,0xe, 0xf2,0x6c,0xaa,0xa, +0x3a,0x9, 0xb3,0x2, 0xdc,0xbe,0xb0,0xff,0x68,0x4, 0xc2,0x6, 0x80,0x7, 0xb, 0xa0, +0xbe,0xa0,0x8, 0x40,0xea,0xa2,0x6, 0x22,0x7d,0x52,0xf5,0x19,0x7c,0xb6,0x7c,0xa5, +0xa, 0x44,0xf5,0x18,0x7f,0x21,0xf5,0x17,0xa9,0xc2,0xb4,0x74,0xb, 0x12,0xf, 0x27, +0xe5,0x19,0x12,0xf, 0x27,0xe5,0x18,0x12,0xf, 0x27,0xe5,0x17,0x12,0xf, 0x27,0xe4, +0x2, 0xf, 0x27,0x12,0xe, 0xa9,0x12,0xb, 0x3b,0xa9,0xa6,0x94,0xb3,0x92,0x8, 0x30, +0x8, 0x6, 0x12,0xf, 0x1b,0x12,0xd, 0x4b,0x12,0x9, 0xab,0x12,0xf, 0x0, 0xd2,0xaf, +0x30,0x3, 0xfd,0x2, 0xf, 0x45,0x80,0x18,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0xe5,0x3e,0x70,0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x7d,0x23,0x1b,0x34,0x4d,0x22,0x78,0xe0,0x22,0xd2,0xcf,0x85,0x3e,0xcc,0x75,0xec, +0xff,0x75,0xee,0xff,0x75,0xeb,0x3, 0x75,0xac,0xc0,0xa9,0xc5,0xca,0x75,0xed,0xf, +0x75,0xad,0xb0,0xa9,0xd7,0x94,0xa9,0xd4,0x94,0x22,0xa9,0xc2,0xb4,0x74,0x5, 0x12, +0xf, 0x27,0x12,0xf, 0xe, 0xa9,0xd2,0xb4,0x30,0xe0,0x2, 0xd3,0x22,0xc3,0x22,0xa9, +0xc2,0xb4,0x30,0x6, 0x4, 0x74,0x6, 0x80,0x2, 0x74,0x4, 0x12,0xf, 0x27,0xa9,0xd2, +0xb4,0x22,0x12,0xe, 0x38,0x7e,0x35,0x15,0x12,0x0, 0xe, 0xa9,0xd2,0xb4,0xd3,0x22, +0xc2,0x8c,0x43,0x89,0x2, 0x75,0x8c,0x1, 0x75,0x8a,0x0, 0xd2,0xa9,0x22,0x75,0xb5, +0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xe5,0xb5,0x22,0xd2,0xc8,0x75,0xb3,0x13, +0xa9,0xd1,0xb4,0xa9,0xc0,0xb4,0x22,0xf5,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3, +0xd3,0x22,0xc2,0x8c,0x6d,0x33,0x7a,0x35,0x42,0xd2,0x8c,0x22,0x7e,0x35,0x42,0xb, +0x34,0x7a,0x35,0x42,0x22,0x85,0x3e,0xcc,0xe5,0x3e,0x2, 0xd, 0xe0,0x2, 0xf, 0x3c, +0x0, 0x1, 0x2, 0xe4,0x0, 0x0, 0x4, 0x2, 0xe5,0x0, 0x0, 0x9c,0x0, 0x0, 0x0, 0xff, diff --git a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c index 563ce16885b32..72259b7c97d54 100644 --- a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c +++ b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c @@ -43,7 +43,7 @@ #include #include "synaptics_dsx_core.h" -#define SYN_I2C_RETRY_TIMES 10 +#define SYN_I2C_RETRY_TIMES 1 /* #define I2C_BURST_LIMIT 255 diff --git a/drivers/input/touchscreen/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx_fw_update.c new file mode 100644 index 0000000000000..656ae1599e4fb --- /dev/null +++ b/drivers/input/touchscreen/synaptics_dsx_fw_update.c @@ -0,0 +1,5990 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" +#include + + +#define FW_IHEX_NAME "synaptics/startup_fw_update.bin" +#define FW_IMAGE_NAME "synaptics/startup_fw_update.img" + +#define DO_STARTUP_FW_UPDATE + +#define SYNAPTICS_LOCK_DOWN_INFO + +#ifdef DO_STARTUP_FW_UPDATE +#ifdef CONFIG_FB +#define WAIT_FOR_FB_READY +#define FB_READY_WAIT_MS 100 +#define FB_READY_TIMEOUT_S 30 +#endif +#endif + + +#define MAX_WRITE_SIZE 4096 + + +#define ENABLE_SYS_REFLASH true +#define FORCE_UPDATE false +#define DO_LOCKDOWN false + +#define MAX_IMAGE_NAME_LEN 256 +#define MAX_FIRMWARE_ID_LEN 10 + +#define IMAGE_HEADER_VERSION_05 0x05 +#define IMAGE_HEADER_VERSION_06 0x06 +#define IMAGE_HEADER_VERSION_10 0x10 + +#define IMAGE_AREA_OFFSET 0x100 +#define LOCKDOWN_SIZE 0x50 + +#define MAX_UTILITY_PARAMS 20 + +#define V5V6_BOOTLOADER_ID_OFFSET 0 +#define V5V6_CONFIG_ID_SIZE 4 + +#define V5_PROPERTIES_OFFSET 2 +#define V5_BLOCK_SIZE_OFFSET 3 +#define V5_BLOCK_COUNT_OFFSET 5 +#define V5_BLOCK_NUMBER_OFFSET 0 +#define V5_BLOCK_DATA_OFFSET 2 + +#define V6_PROPERTIES_OFFSET 1 +#define V6_BLOCK_SIZE_OFFSET 2 +#define V6_BLOCK_COUNT_OFFSET 3 +#define V6_PROPERTIES_2_OFFSET 4 +#define V6_GUEST_CODE_BLOCK_COUNT_OFFSET 5 +#define V6_BLOCK_NUMBER_OFFSET 0 +#define V6_BLOCK_DATA_OFFSET 1 +#define V6_FLASH_COMMAND_OFFSET 2 +#define V6_FLASH_STATUS_OFFSET 3 + +#define V7_CONFIG_ID_SIZE 32 + +#define V7_FLASH_STATUS_OFFSET 0 +#define V7_PARTITION_ID_OFFSET 1 +#define V7_BLOCK_NUMBER_OFFSET 2 +#define V7_TRANSFER_LENGTH_OFFSET 3 +#define V7_COMMAND_OFFSET 4 +#define V7_PAYLOAD_OFFSET 5 + +#define V7_PARTITION_SUPPORT_BYTES 4 + +#define F35_ERROR_CODE_OFFSET 0 +#define F35_FLASH_STATUS_OFFSET 5 +#define F35_CHUNK_NUM_LSB_OFFSET 0 +#define F35_CHUNK_NUM_MSB_OFFSET 1 +#define F35_CHUNK_DATA_OFFSET 2 +#define F35_CHUNK_COMMAND_OFFSET 18 + +#define F35_CHUNK_SIZE 16 +#define F35_ERASE_ALL_WAIT_MS 5000 +#define F35_RESET_WAIT_MS 250 + +#define SLEEP_MODE_NORMAL (0x00) +#define SLEEP_MODE_SENSOR_SLEEP (0x01) +#define SLEEP_MODE_RESERVED0 (0x02) +#define SLEEP_MODE_RESERVED1 (0x03) + +#define ENABLE_WAIT_MS (1 * 1000) +#define WRITE_WAIT_MS (3 * 1000) +#define ERASE_WAIT_MS (5 * 1000) + +#define MIN_SLEEP_TIME_US 50 +#define MAX_SLEEP_TIME_US 100 + +#define INT_DISABLE_WAIT_MS 20 +#define ENTER_FLASH_PROG_WAIT_MS 20 +#define READ_CONFIG_WAIT_MS 20 + +static int fwu_do_reflash(void); + +static int fwu_recovery_check_status(void); + +static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t fwu_sysfs_store_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t fwu_sysfs_do_recovery_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_write_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_read_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_config_area_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_image_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_image_size_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_block_size_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_utility_parameter_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_guest_code_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_read_guest_serialization_show(struct device *dev, + struct device_attribute *attr, char *buf); + +#ifdef SYNA_TDDI +static ssize_t fwu_sysfs_write_lockdown_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_read_lockdown_code_show(struct device *dev, + struct device_attribute *attr, char *buf); + +#endif + +enum f34_version { + F34_V0 = 0, + F34_V1, + F34_V2, +}; + +enum bl_version { + BL_V5 = 5, + BL_V6 = 6, + BL_V7 = 7, + BL_V8 = 8, +}; + +enum flash_area { + NONE = 0, + UI_FIRMWARE, + UI_CONFIG, +}; + +enum update_mode { + NORMAL = 1, + FORCE = 2, + LOCKDOWN = 8, +}; + +enum config_area { + UI_CONFIG_AREA = 0, + PM_CONFIG_AREA, + BL_CONFIG_AREA, + DP_CONFIG_AREA, + FLASH_CONFIG_AREA, +#ifdef SYNA_TDDI + TDDI_FORCE_CONFIG_AREA, + TDDI_LCM_DATA_AREA, + TDDI_OEM_DATA_AREA, +#endif + UPP_AREA, +}; + +enum v7_status { + SUCCESS = 0x00, + DEVICE_NOT_IN_BOOTLOADER_MODE, + INVALID_PARTITION, + INVALID_COMMAND, + INVALID_BLOCK_OFFSET, + INVALID_TRANSFER, + NOT_ERASED, + FLASH_PROGRAMMING_KEY_INCORRECT, + BAD_PARTITION_TABLE, + CHECKSUM_FAILED, + FLASH_HARDWARE_FAILURE = 0x1f, +}; + +enum v7_partition_id { + BOOTLOADER_PARTITION = 0x01, + DEVICE_CONFIG_PARTITION, + FLASH_CONFIG_PARTITION, + MANUFACTURING_BLOCK_PARTITION, + GUEST_SERIALIZATION_PARTITION, + GLOBAL_PARAMETERS_PARTITION, + CORE_CODE_PARTITION, + CORE_CONFIG_PARTITION, + GUEST_CODE_PARTITION, + DISPLAY_CONFIG_PARTITION, + EXTERNAL_TOUCH_AFE_CONFIG_PARTITION, + UTILITY_PARAMETER_PARTITION, +}; + +enum v7_flash_command { + CMD_V7_IDLE = 0x00, + CMD_V7_ENTER_BL, + CMD_V7_READ, + CMD_V7_WRITE, + CMD_V7_ERASE, + CMD_V7_ERASE_AP, + CMD_V7_SENSOR_ID, +}; + +enum v5v6_flash_command { + CMD_V5V6_IDLE = 0x0, + CMD_V5V6_WRITE_FW = 0x2, + CMD_V5V6_ERASE_ALL = 0x3, + CMD_V5V6_WRITE_LOCKDOWN = 0x4, + CMD_V5V6_READ_CONFIG = 0x5, + CMD_V5V6_WRITE_CONFIG = 0x6, + CMD_V5V6_ERASE_UI_CONFIG = 0x7, + CMD_V5V6_ERASE_BL_CONFIG = 0x9, + CMD_V5V6_ERASE_DISP_CONFIG = 0xa, + CMD_V5V6_ERASE_GUEST_CODE = 0xb, + CMD_V5V6_WRITE_GUEST_CODE = 0xc, + CMD_V5V6_ERASE_CHIP = 0x0d, + CMD_V5V6_ENABLE_FLASH_PROG = 0xf, +#ifdef SYNA_TDDI + CMD_V5V6_ERASE_FORCE_CONFIG = 0x11, + CMD_V5V6_READ_FORCE_CONFIG = 0x12, + CMD_V5V6_WRITE_FORCE_CONFIG = 0x13, + CMD_V5V6_ERASE_LOCKDOWN_DATA = 0x1a, + CMD_V5V6_READ_LOCKDOWN_DATA = 0x1b, + CMD_V5V6_WRITE_LOCKDOWN_DATA = 0x1c, + CMD_V5V6_ERASE_LCM_DATA = 0x1d, + CMD_V5V6_ERASE_OEM_DATA = 0x1e, +#endif +}; + +enum flash_command { + CMD_IDLE = 0, + CMD_WRITE_FW, + CMD_WRITE_CONFIG, + CMD_WRITE_LOCKDOWN, + CMD_WRITE_GUEST_CODE, + CMD_WRITE_BOOTLOADER, + CMD_WRITE_UTILITY_PARAM, + CMD_READ_CONFIG, + CMD_ERASE_ALL, + CMD_ERASE_UI_FIRMWARE, + CMD_ERASE_UI_CONFIG, + CMD_ERASE_BL_CONFIG, + CMD_ERASE_DISP_CONFIG, + CMD_ERASE_FLASH_CONFIG, + CMD_ERASE_GUEST_CODE, + CMD_ERASE_BOOTLOADER, + CMD_ERASE_UTILITY_PARAMETER, + CMD_ENABLE_FLASH_PROG, +#ifdef SYNA_TDDI + CMD_ERASE_CHIP, + CMD_ERASE_FORCE_CONFIG, + CMD_READ_FORCE_CONFIG, + CMD_WRITE_FORCE_CONFIG, + CMD_ERASE_LOCKDOWN_DATA, + CMD_READ_LOCKDOWN_DATA, + CMD_WRITE_LOCKDOWN_DATA, + CMD_ERASE_LCM_DATA, + CMD_READ_LCM_DATA, + CMD_WRITE_LCM_DATA, + CMD_ERASE_OEM_DATA, + CMD_READ_OEM_DATA, + CMD_WRITE_OEM_DATA, +#endif +}; + +enum f35_flash_command { + CMD_F35_IDLE = 0x0, + CMD_F35_RESERVED = 0x1, + CMD_F35_WRITE_CHUNK = 0x2, + CMD_F35_ERASE_ALL = 0x3, + CMD_F35_RESET = 0x10, +}; + +enum container_id { + TOP_LEVEL_CONTAINER = 0, + UI_CONTAINER, + UI_CONFIG_CONTAINER, + BL_CONTAINER, + BL_IMAGE_CONTAINER, + BL_CONFIG_CONTAINER, + BL_LOCKDOWN_INFO_CONTAINER, + PERMANENT_CONFIG_CONTAINER, + GUEST_CODE_CONTAINER, + BL_PROTOCOL_DESCRIPTOR_CONTAINER, + UI_PROTOCOL_DESCRIPTOR_CONTAINER, + RMI_SELF_DISCOVERY_CONTAINER, + RMI_PAGE_CONTENT_CONTAINER, + GENERAL_INFORMATION_CONTAINER, + DEVICE_CONFIG_CONTAINER, + FLASH_CONFIG_CONTAINER, + GUEST_SERIALIZATION_CONTAINER, + GLOBAL_PARAMETERS_CONTAINER, + CORE_CODE_CONTAINER, + CORE_CONFIG_CONTAINER, + DISPLAY_CONFIG_CONTAINER, + EXTERNAL_TOUCH_AFE_CONFIG_CONTAINER, + UTILITY_CONTAINER, + UTILITY_PARAMETER_CONTAINER, +}; + +enum utility_parameter_id { + UNUSED = 0, + FORCE_PARAMETER, + ANTI_BENDING_PARAMETER, +}; + +struct pdt_properties { + union { + struct { + unsigned char reserved_1:6; + unsigned char has_bsr:1; + unsigned char reserved_2:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct partition_table { + unsigned char partition_id:5; + unsigned char byte_0_reserved:3; + unsigned char byte_1_reserved; + unsigned char partition_length_7_0; + unsigned char partition_length_15_8; + unsigned char start_physical_address_7_0; + unsigned char start_physical_address_15_8; + unsigned char partition_properties_7_0; + unsigned char partition_properties_15_8; +} __packed; + +struct f01_device_control { + union { + struct { + unsigned char sleep_mode:2; + unsigned char nosleep:1; + unsigned char reserved:2; + unsigned char charger_connected:1; + unsigned char report_rate:1; + unsigned char configured:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v7_query_0 { + union { + struct { + unsigned char subpacket_1_size:3; + unsigned char has_config_id:1; + unsigned char f34_query0_b4:1; + unsigned char has_thqa:1; + unsigned char f34_query0_b6__7:2; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v7_query_1_7 { + union { + struct { + /* query 1 */ + unsigned char bl_minor_revision; + unsigned char bl_major_revision; + + /* query 2 */ + unsigned char bl_fw_id_7_0; + unsigned char bl_fw_id_15_8; + unsigned char bl_fw_id_23_16; + unsigned char bl_fw_id_31_24; + + /* query 3 */ + unsigned char minimum_write_size; + unsigned char block_size_7_0; + unsigned char block_size_15_8; + unsigned char flash_page_size_7_0; + unsigned char flash_page_size_15_8; + + /* query 4 */ + unsigned char adjustable_partition_area_size_7_0; + unsigned char adjustable_partition_area_size_15_8; + + /* query 5 */ + unsigned char flash_config_length_7_0; + unsigned char flash_config_length_15_8; + + /* query 6 */ + unsigned char payload_length_7_0; + unsigned char payload_length_15_8; + + /* query 7 */ + unsigned char f34_query7_b0:1; + unsigned char has_bootloader:1; + unsigned char has_device_config:1; + unsigned char has_flash_config:1; + unsigned char has_manufacturing_block:1; + unsigned char has_guest_serialization:1; + unsigned char has_global_parameters:1; + unsigned char has_core_code:1; + unsigned char has_core_config:1; + unsigned char has_guest_code:1; + unsigned char has_display_config:1; + unsigned char f34_query7_b11__15:5; + unsigned char f34_query7_b16__23; + unsigned char f34_query7_b24__31; + } __packed; + unsigned char data[21]; + }; +}; + +struct f34_v7_data0 { + union { + struct { + unsigned char operation_status:5; + unsigned char device_cfg_status:2; + unsigned char bl_mode:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v7_data_1_5 { + union { + struct { + unsigned char partition_id:5; + unsigned char f34_data1_b5__7:3; + unsigned char block_offset_7_0; + unsigned char block_offset_15_8; + unsigned char transfer_length_7_0; + unsigned char transfer_length_15_8; + unsigned char command; + unsigned char payload_0; + unsigned char payload_1; + } __packed; + unsigned char data[8]; + }; +}; + +struct f34_v5v6_flash_properties { + union { + struct { + unsigned char reg_map:1; + unsigned char unlocked:1; + unsigned char has_config_id:1; + unsigned char has_pm_config:1; + unsigned char has_bl_config:1; + unsigned char has_disp_config:1; + unsigned char has_ctrl1:1; + unsigned char has_query4:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v5v6_flash_properties_2 { + union { + struct { + unsigned char has_guest_code:1; + unsigned char f34_query4_b1:1; + unsigned char has_gesture_config:1; + unsigned char has_force_config:1; + unsigned char has_lockdown_data:1; + unsigned char has_lcm_data:1; + unsigned char has_oem_data:1; + unsigned char f34_query4_b7:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct register_offset { + unsigned char properties; + unsigned char properties_2; + unsigned char block_size; + unsigned char block_count; + unsigned char gc_block_count; + unsigned char flash_status; + unsigned char partition_id; + unsigned char block_number; + unsigned char transfer_length; + unsigned char flash_cmd; + unsigned char payload; +}; + +struct block_count { + unsigned short ui_firmware; + unsigned short ui_config; + unsigned short dp_config; + unsigned short pm_config; + unsigned short fl_config; + unsigned short bl_image; + unsigned short bl_config; + unsigned short utility_param; + unsigned short lockdown; + unsigned short guest_code; +#ifdef SYNA_TDDI + unsigned short tddi_force_config; + unsigned short tddi_lockdown_data; + unsigned short tddi_lcm_data; + unsigned short tddi_oem_data; +#endif + unsigned short total_count; +}; + +struct physical_address { + unsigned short ui_firmware; + unsigned short ui_config; + unsigned short dp_config; + unsigned short pm_config; + unsigned short fl_config; + unsigned short bl_image; + unsigned short bl_config; + unsigned short utility_param; + unsigned short lockdown; + unsigned short guest_code; +}; + +struct container_descriptor { + unsigned char content_checksum[4]; + unsigned char container_id[2]; + unsigned char minor_version; + unsigned char major_version; + unsigned char reserved_08; + unsigned char reserved_09; + unsigned char reserved_0a; + unsigned char reserved_0b; + unsigned char container_option_flags[4]; + unsigned char content_options_length[4]; + unsigned char content_options_address[4]; + unsigned char content_length[4]; + unsigned char content_address[4]; +}; + +struct image_header_10 { + unsigned char checksum[4]; + unsigned char reserved_04; + unsigned char reserved_05; + unsigned char minor_header_version; + unsigned char major_header_version; + unsigned char reserved_08; + unsigned char reserved_09; + unsigned char reserved_0a; + unsigned char reserved_0b; + unsigned char top_level_container_start_addr[4]; +}; + +struct image_header_05_06 { + /* 0x00 - 0x0f */ + unsigned char checksum[4]; + unsigned char reserved_04; + unsigned char reserved_05; + unsigned char options_firmware_id:1; + unsigned char options_bootloader:1; + unsigned char options_guest_code:1; + unsigned char options_tddi:1; + unsigned char options_reserved:4; + unsigned char header_version; + unsigned char firmware_size[4]; + unsigned char config_size[4]; + /* 0x10 - 0x1f */ + unsigned char product_id[PRODUCT_ID_SIZE]; + unsigned char package_id[2]; + unsigned char package_id_revision[2]; + unsigned char product_info[PRODUCT_INFO_SIZE]; + /* 0x20 - 0x2f */ + unsigned char bootloader_addr[4]; + unsigned char bootloader_size[4]; + unsigned char ui_addr[4]; + unsigned char ui_size[4]; + /* 0x30 - 0x3f */ + unsigned char ds_id[16]; + /* 0x40 - 0x4f */ + union { + struct { + unsigned char cstmr_product_id[PRODUCT_ID_SIZE]; + unsigned char reserved_4a_4f[6]; + }; + struct { + unsigned char dsp_cfg_addr[4]; + unsigned char dsp_cfg_size[4]; + unsigned char reserved_48_4f[8]; + }; + }; + /* 0x50 - 0x53 */ + unsigned char firmware_id[4]; +}; + +struct block_data { + unsigned int size; + const unsigned char *data; +}; + +struct image_metadata { + bool contains_firmware_id; + bool contains_bootloader; + bool contains_guest_code; + bool contains_disp_config; + bool contains_perm_config; + bool contains_flash_config; + bool contains_utility_param; + unsigned int firmware_id; + unsigned int checksum; + unsigned int bootloader_size; + unsigned int disp_config_offset; + unsigned char bl_version; + unsigned char product_id[PRODUCT_ID_SIZE + 1]; + unsigned char cstmr_product_id[PRODUCT_ID_SIZE + 1]; + unsigned char utility_param_id[MAX_UTILITY_PARAMS]; + struct block_data bootloader; + struct block_data utility; + struct block_data ui_firmware; + struct block_data ui_config; + struct block_data dp_config; + struct block_data pm_config; + struct block_data fl_config; + struct block_data bl_image; + struct block_data bl_config; + struct block_data utility_param[MAX_UTILITY_PARAMS]; + struct block_data lockdown; + struct block_data guest_code; + struct block_count blkcount; + struct physical_address phyaddr; +}; + +struct synaptics_rmi4_fwu_handle { + enum bl_version bl_version; + bool initialized; + bool in_bl_mode; + bool in_ub_mode; + bool bl_mode_device; + bool force_update; + bool do_lockdown; + bool has_guest_code; +#ifdef SYNA_TDDI + bool has_force_config; + bool has_lockdown_data; + bool has_lcm_data; + bool has_oem_data; +#endif + bool has_utility_param; + bool new_partition_table; + bool incompatible_partition_tables; + bool write_bootloader; + unsigned int data_pos; + unsigned char *ext_data_source; + unsigned char *read_config_buf; + unsigned char intr_mask; + unsigned char command; + unsigned char bootloader_id[2]; + unsigned char config_id[32]; + unsigned char flash_status; + unsigned char partitions; +#ifdef F51_DISCRETE_FORCE + unsigned char *cal_data; + unsigned short cal_data_off; + unsigned short cal_data_size; + unsigned short cal_data_buf_size; + unsigned short cal_packet_data_size; +#endif + unsigned short block_size; + unsigned short config_size; + unsigned short config_area; + unsigned short config_block_count; + unsigned short flash_config_length; + unsigned short payload_length; + unsigned short partition_table_bytes; + unsigned short read_config_buf_size; + const unsigned char *config_data; + const unsigned char *image; + unsigned char *image_name; + unsigned int image_size; + struct image_metadata img; + struct register_offset off; + struct block_count blkcount; + struct physical_address phyaddr; + struct f34_v5v6_flash_properties flash_properties; + struct synaptics_rmi4_fn_desc f34_fd; + struct synaptics_rmi4_fn_desc f35_fd; + struct synaptics_rmi4_data *rmi4_data; + struct workqueue_struct *fwu_workqueue; + struct work_struct fwu_work; +}; + +static struct bin_attribute dev_attr_data = { + .attr = { + .name = "data", + .mode = (S_IRUGO | S_IWUSR | S_IWGRP), + }, + .size = 0, + .read = fwu_sysfs_show_image, + .write = fwu_sysfs_store_image, +}; + +static struct device_attribute attrs[] = { + __ATTR(dorecovery, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_do_recovery_store), + __ATTR(doreflash, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_do_reflash_store), + __ATTR(writeconfig, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_write_config_store), + __ATTR(readconfig, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_read_config_store), + __ATTR(configarea, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_config_area_store), + __ATTR(imagename, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_image_name_store), + __ATTR(imagesize, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_image_size_store), + __ATTR(blocksize, S_IRUGO, + fwu_sysfs_block_size_show, + synaptics_rmi4_store_error), + __ATTR(fwblockcount, S_IRUGO, + fwu_sysfs_firmware_block_count_show, + synaptics_rmi4_store_error), + __ATTR(configblockcount, S_IRUGO, + fwu_sysfs_configuration_block_count_show, + synaptics_rmi4_store_error), + __ATTR(dispconfigblockcount, S_IRUGO, + fwu_sysfs_disp_config_block_count_show, + synaptics_rmi4_store_error), + __ATTR(permconfigblockcount, S_IRUGO, + fwu_sysfs_perm_config_block_count_show, + synaptics_rmi4_store_error), + __ATTR(blconfigblockcount, S_IRUGO, + fwu_sysfs_bl_config_block_count_show, + synaptics_rmi4_store_error), + __ATTR(uppblockcount, S_IRUGO, + fwu_sysfs_utility_parameter_block_count_show, + synaptics_rmi4_store_error), + __ATTR(guestcodeblockcount, S_IRUGO, + fwu_sysfs_guest_code_block_count_show, + synaptics_rmi4_store_error), + __ATTR(writeguestcode, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_write_guest_code_store), + __ATTR(guestserialization, S_IRUGO, + fwu_sysfs_read_guest_serialization_show, + synaptics_rmi4_store_error), + +#ifdef SYNA_TDDI + __ATTR(lockdowncode, (S_IWUSR | S_IWGRP | S_IRUGO), + fwu_sysfs_read_lockdown_code_show, + fwu_sysfs_write_lockdown_code_store), +#endif +}; + +static struct synaptics_rmi4_fwu_handle *fwu; + +#if defined(SYNAPTICS_LOCK_DOWN_INFO) +#define CTP_PROC_LOCKDOWN_FILE "tp_lockdown_info" +DEFINE_MUTEX(fwu_sysfs_mutex); +static struct proc_dir_entry *ctp_lockdown_status_proc; +static char tp_lockdown_info[128]; + +static int fwu_do_read_customer_serialization_data(void); + +static int ctp_lockdown_proc_show(struct seq_file *file, void *data) +{ + char temp[40] = {0}; + fwu_do_read_customer_serialization_data(); + + sprintf(temp, "%s\n", tp_lockdown_info); + seq_printf(file, "%s\n", temp); + + return 0; + + +} + +static int ctp_lockdown_proc_open (struct inode *inode, struct file *file) +{ + return single_open(file, ctp_lockdown_proc_show, inode->i_private); +} + +static const struct file_operations ctp_lockdown_proc_fops = { + .open = ctp_lockdown_proc_open, + .read = seq_read, +}; +#endif +DECLARE_COMPLETION(fwu_remove_complete); + + + +static void calculate_checksum(unsigned short *data, unsigned long len, + unsigned long *result) +{ + unsigned long temp; + unsigned long sum1 = 0xffff; + unsigned long sum2 = 0xffff; + + *result = 0xffffffff; + + while (len--) { + temp = *data; + sum1 += temp; + sum2 += sum1; + sum1 = (sum1 & 0xffff) + (sum1 >> 16); + sum2 = (sum2 & 0xffff) + (sum2 >> 16); + data++; + } + + *result = sum2 << 16 | sum1; + + return; +} + +static void convert_to_little_endian(unsigned char *dest, unsigned long src) +{ + dest[0] = (unsigned char)(src & 0xff); + dest[1] = (unsigned char)((src >> 8) & 0xff); + dest[2] = (unsigned char)((src >> 16) & 0xff); + dest[3] = (unsigned char)((src >> 24) & 0xff); + + return; +} + +static unsigned int le_to_uint(const unsigned char *ptr) +{ + return (unsigned int)ptr[0] + + (unsigned int)ptr[1] * 0x100 + + (unsigned int)ptr[2] * 0x10000 + + (unsigned int)ptr[3] * 0x1000000; +} + +#ifdef F51_DISCRETE_FORCE +static int fwu_f51_force_data_init(void) +{ + int retval; + unsigned char query_count; + unsigned char packet_info; + unsigned char offset[2]; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f51_query_base_addr + 7, + offset, + sizeof(offset)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read force data offset\n", + __func__); + return retval; + } + + fwu->cal_data_off = offset[0] | offset[1] << 8; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f51_query_base_addr, + &query_count, + sizeof(query_count)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read number of F51 query registers\n", + __func__); + return retval; + } + + if (query_count >= 10) { + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f51_query_base_addr + 9, + &packet_info, + sizeof(packet_info)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F51 packet register info\n", + __func__); + return retval; + } + + if (packet_info & MASK_1BIT) { + fwu->cal_packet_data_size = packet_info >> 1; + fwu->cal_packet_data_size *= 2; + } else { + fwu->cal_packet_data_size = 0; + } + } else { + fwu->cal_packet_data_size = 0; + } + + fwu->cal_data_size = CAL_DATA_SIZE + fwu->cal_packet_data_size; + if (fwu->cal_data_size > fwu->cal_data_buf_size) { + kfree(fwu->cal_data); + fwu->cal_data_buf_size = fwu->cal_data_size; + fwu->cal_data = kmalloc(fwu->cal_data_buf_size, GFP_KERNEL); + if (!fwu->cal_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu->cal_data\n", + __func__); + fwu->cal_data_buf_size = 0; + return -ENOMEM; + } + } + + return 0; +} +#endif + +static int fwu_allocate_read_config_buf(unsigned int count) +{ + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (count > fwu->read_config_buf_size) { + kfree(fwu->read_config_buf); + fwu->read_config_buf = kzalloc(count, GFP_KERNEL); + if (!fwu->read_config_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu->read_config_buf\n", + __func__); + fwu->read_config_buf_size = 0; + return -ENOMEM; + } + fwu->read_config_buf_size = count; + } + + return 0; +} + +static void fwu_compare_partition_tables(void) +{ + fwu->incompatible_partition_tables = false; + + if (fwu->phyaddr.bl_image != fwu->img.phyaddr.bl_image) + fwu->incompatible_partition_tables = true; + else if (fwu->phyaddr.lockdown != fwu->img.phyaddr.lockdown) + fwu->incompatible_partition_tables = true; + else if (fwu->phyaddr.bl_config != fwu->img.phyaddr.bl_config) + fwu->incompatible_partition_tables = true; + else if (fwu->phyaddr.utility_param != fwu->img.phyaddr.utility_param) + fwu->incompatible_partition_tables = true; + + if (fwu->bl_version == BL_V7) { + if (fwu->phyaddr.fl_config != fwu->img.phyaddr.fl_config) + fwu->incompatible_partition_tables = true; + } + + fwu->new_partition_table = false; + + if (fwu->phyaddr.ui_firmware != fwu->img.phyaddr.ui_firmware) + fwu->new_partition_table = true; + else if (fwu->phyaddr.ui_config != fwu->img.phyaddr.ui_config) + fwu->new_partition_table = true; + + if (fwu->flash_properties.has_disp_config) { + if (fwu->phyaddr.dp_config != fwu->img.phyaddr.dp_config) + fwu->new_partition_table = true; + } + + if (fwu->has_guest_code) { + if (fwu->phyaddr.guest_code != fwu->img.phyaddr.guest_code) + fwu->new_partition_table = true; + } + + return; +} + +static void fwu_parse_partition_table(const unsigned char *partition_table, + struct block_count *blkcount, struct physical_address *phyaddr) +{ + unsigned char ii; + unsigned char index; + unsigned char offset; + unsigned short partition_length; + unsigned short physical_address; + struct partition_table *ptable; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + for (ii = 0; ii < fwu->partitions; ii++) { + index = ii * 8 + 2; + ptable = (struct partition_table *)&partition_table[index]; + partition_length = ptable->partition_length_15_8 << 8 | + ptable->partition_length_7_0; + physical_address = ptable->start_physical_address_15_8 << 8 | + ptable->start_physical_address_7_0; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Partition entry %d:\n", + __func__, ii); + for (offset = 0; offset < 8; offset++) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: 0x%02x\n", + __func__, + partition_table[index + offset]); + } + switch (ptable->partition_id) { + case CORE_CODE_PARTITION: + blkcount->ui_firmware = partition_length; + phyaddr->ui_firmware = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Core code block count: %d\n", + __func__, blkcount->ui_firmware); + blkcount->total_count += partition_length; + break; + case CORE_CONFIG_PARTITION: + blkcount->ui_config = partition_length; + phyaddr->ui_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Core config block count: %d\n", + __func__, blkcount->ui_config); + blkcount->total_count += partition_length; + break; + case BOOTLOADER_PARTITION: + blkcount->bl_image = partition_length; + phyaddr->bl_image = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Bootloader block count: %d\n", + __func__, blkcount->bl_image); + blkcount->total_count += partition_length; + break; + case UTILITY_PARAMETER_PARTITION: + blkcount->utility_param = partition_length; + phyaddr->utility_param = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Utility parameter block count: %d\n", + __func__, blkcount->utility_param); + blkcount->total_count += partition_length; + break; + case DISPLAY_CONFIG_PARTITION: + blkcount->dp_config = partition_length; + phyaddr->dp_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Display config block count: %d\n", + __func__, blkcount->dp_config); + blkcount->total_count += partition_length; + break; + case FLASH_CONFIG_PARTITION: + blkcount->fl_config = partition_length; + phyaddr->fl_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Flash config block count: %d\n", + __func__, blkcount->fl_config); + blkcount->total_count += partition_length; + break; + case GUEST_CODE_PARTITION: + blkcount->guest_code = partition_length; + phyaddr->guest_code = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Guest code block count: %d\n", + __func__, blkcount->guest_code); + blkcount->total_count += partition_length; + break; + case GUEST_SERIALIZATION_PARTITION: + blkcount->pm_config = partition_length; + phyaddr->pm_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Guest serialization block count: %d\n", + __func__, blkcount->pm_config); + blkcount->total_count += partition_length; + break; + case GLOBAL_PARAMETERS_PARTITION: + blkcount->bl_config = partition_length; + phyaddr->bl_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Global parameters block count: %d\n", + __func__, blkcount->bl_config); + blkcount->total_count += partition_length; + break; + case DEVICE_CONFIG_PARTITION: + blkcount->lockdown = partition_length; + phyaddr->lockdown = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Device config block count: %d\n", + __func__, blkcount->lockdown); + blkcount->total_count += partition_length; + break; + }; + } + + return; +} + +static void fwu_parse_image_header_10_utility(const unsigned char *image) +{ + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int container_id; + unsigned int length; + const unsigned char *content; + struct container_descriptor *descriptor; + + num_of_containers = fwu->img.utility.size / 4; + + for (ii = 0; ii < num_of_containers; ii++) { + if (ii >= MAX_UTILITY_PARAMS) + continue; + addr = le_to_uint(fwu->img.utility.data + (ii * 4)); + descriptor = (struct container_descriptor *)(image + addr); + container_id = descriptor->container_id[0] | + descriptor->container_id[1] << 8; + content = image + le_to_uint(descriptor->content_address); + length = le_to_uint(descriptor->content_length); + switch (container_id) { + case UTILITY_PARAMETER_CONTAINER: + fwu->img.utility_param[ii].data = content; + fwu->img.utility_param[ii].size = length; + fwu->img.utility_param_id[ii] = content[0]; + break; + default: + break; + }; + } + + return; +} + +static void fwu_parse_image_header_10_bootloader(const unsigned char *image) +{ + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int container_id; + unsigned int length; + const unsigned char *content; + struct container_descriptor *descriptor; + + num_of_containers = (fwu->img.bootloader.size - 4) / 4; + + for (ii = 1; ii <= num_of_containers; ii++) { + addr = le_to_uint(fwu->img.bootloader.data + (ii * 4)); + descriptor = (struct container_descriptor *)(image + addr); + container_id = descriptor->container_id[0] | + descriptor->container_id[1] << 8; + content = image + le_to_uint(descriptor->content_address); + length = le_to_uint(descriptor->content_length); + switch (container_id) { + case BL_IMAGE_CONTAINER: + fwu->img.bl_image.data = content; + fwu->img.bl_image.size = length; + break; + case BL_CONFIG_CONTAINER: + case GLOBAL_PARAMETERS_CONTAINER: + fwu->img.bl_config.data = content; + fwu->img.bl_config.size = length; + break; + case BL_LOCKDOWN_INFO_CONTAINER: + case DEVICE_CONFIG_CONTAINER: + fwu->img.lockdown.data = content; + fwu->img.lockdown.size = length; + break; + default: + break; + }; + } + + return; +} + +static void fwu_parse_image_header_10(void) +{ + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int offset; + unsigned int container_id; + unsigned int length; + const unsigned char *image; + const unsigned char *content; + struct container_descriptor *descriptor; + struct image_header_10 *header; + + image = fwu->image; + header = (struct image_header_10 *)image; + + fwu->img.checksum = le_to_uint(header->checksum); + + /* address of top level container */ + offset = le_to_uint(header->top_level_container_start_addr); + descriptor = (struct container_descriptor *)(image + offset); + + /* address of top level container content */ + offset = le_to_uint(descriptor->content_address); + num_of_containers = le_to_uint(descriptor->content_length) / 4; + + for (ii = 0; ii < num_of_containers; ii++) { + addr = le_to_uint(image + offset); + offset += 4; + descriptor = (struct container_descriptor *)(image + addr); + container_id = descriptor->container_id[0] | + descriptor->container_id[1] << 8; + content = image + le_to_uint(descriptor->content_address); + length = le_to_uint(descriptor->content_length); + switch (container_id) { + case UI_CONTAINER: + case CORE_CODE_CONTAINER: + fwu->img.ui_firmware.data = content; + fwu->img.ui_firmware.size = length; + break; + case UI_CONFIG_CONTAINER: + case CORE_CONFIG_CONTAINER: + fwu->img.ui_config.data = content; + fwu->img.ui_config.size = length; + break; + case BL_CONTAINER: + fwu->img.bl_version = *content; + fwu->img.bootloader.data = content; + fwu->img.bootloader.size = length; + fwu_parse_image_header_10_bootloader(image); + break; + case UTILITY_CONTAINER: + fwu->img.utility.data = content; + fwu->img.utility.size = length; + fwu_parse_image_header_10_utility(image); + break; + case GUEST_CODE_CONTAINER: + fwu->img.contains_guest_code = true; + fwu->img.guest_code.data = content; + fwu->img.guest_code.size = length; + break; + case DISPLAY_CONFIG_CONTAINER: + fwu->img.contains_disp_config = true; + fwu->img.dp_config.data = content; + fwu->img.dp_config.size = length; + break; + case PERMANENT_CONFIG_CONTAINER: + case GUEST_SERIALIZATION_CONTAINER: + fwu->img.contains_perm_config = true; + fwu->img.pm_config.data = content; + fwu->img.pm_config.size = length; + break; + case FLASH_CONFIG_CONTAINER: + fwu->img.contains_flash_config = true; + fwu->img.fl_config.data = content; + fwu->img.fl_config.size = length; + break; + case GENERAL_INFORMATION_CONTAINER: + fwu->img.contains_firmware_id = true; + fwu->img.firmware_id = le_to_uint(content + 4); + break; + default: + break; + } + } + + return; +} + +static void fwu_parse_image_header_05_06(void) +{ + int retval; + const unsigned char *image; + struct image_header_05_06 *header; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + image = fwu->image; + header = (struct image_header_05_06 *)image; + + fwu->img.checksum = le_to_uint(header->checksum); + + fwu->img.bl_version = header->header_version; + + fwu->img.contains_bootloader = header->options_bootloader; + if (fwu->img.contains_bootloader) + fwu->img.bootloader_size = le_to_uint(header->bootloader_size); + + fwu->img.ui_firmware.size = le_to_uint(header->firmware_size); + if (fwu->img.ui_firmware.size) { + fwu->img.ui_firmware.data = image + IMAGE_AREA_OFFSET; + if (fwu->img.contains_bootloader) + fwu->img.ui_firmware.data += fwu->img.bootloader_size; + } + + if ((fwu->img.bl_version == BL_V6) && header->options_tddi) + fwu->img.ui_firmware.data = image + IMAGE_AREA_OFFSET; + + fwu->img.ui_config.size = le_to_uint(header->config_size); + if (fwu->img.ui_config.size) { + fwu->img.ui_config.data = fwu->img.ui_firmware.data + + fwu->img.ui_firmware.size; + } + + if (fwu->img.contains_bootloader || header->options_tddi) + fwu->img.contains_disp_config = true; + else + fwu->img.contains_disp_config = false; + + if (fwu->img.contains_disp_config) { + fwu->img.disp_config_offset = le_to_uint(header->dsp_cfg_addr); + fwu->img.dp_config.size = le_to_uint(header->dsp_cfg_size); + fwu->img.dp_config.data = image + fwu->img.disp_config_offset; + } else { + retval = secure_memcpy(fwu->img.cstmr_product_id, + sizeof(fwu->img.cstmr_product_id), + header->cstmr_product_id, + sizeof(header->cstmr_product_id), + PRODUCT_ID_SIZE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy custom product ID string\n", + __func__); + } + fwu->img.cstmr_product_id[PRODUCT_ID_SIZE] = 0; + } + + fwu->img.contains_firmware_id = header->options_firmware_id; + if (fwu->img.contains_firmware_id) + fwu->img.firmware_id = le_to_uint(header->firmware_id); + + retval = secure_memcpy(fwu->img.product_id, + sizeof(fwu->img.product_id), + header->product_id, + sizeof(header->product_id), + PRODUCT_ID_SIZE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy product ID string\n", + __func__); + } + fwu->img.product_id[PRODUCT_ID_SIZE] = 0; + + fwu->img.lockdown.size = LOCKDOWN_SIZE; + fwu->img.lockdown.data = image + IMAGE_AREA_OFFSET - LOCKDOWN_SIZE; + + return; +} + +static int fwu_parse_image_info(void) +{ + struct image_header_10 *header; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + header = (struct image_header_10 *)fwu->image; + + memset(&fwu->img, 0x00, sizeof(fwu->img)); + + switch (header->major_header_version) { + case IMAGE_HEADER_VERSION_10: + fwu_parse_image_header_10(); + break; + case IMAGE_HEADER_VERSION_05: + case IMAGE_HEADER_VERSION_06: + fwu_parse_image_header_05_06(); + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Unsupported image file format (0x%02x)\n", + __func__, header->major_header_version); + return -EINVAL; + } + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) { + if (!fwu->img.contains_flash_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No flash config found in firmware image\n", + __func__); + return -EINVAL; + } + + fwu_parse_partition_table(fwu->img.fl_config.data, + &fwu->img.blkcount, &fwu->img.phyaddr); + + if (fwu->img.blkcount.utility_param) + fwu->img.contains_utility_param = true; + + fwu_compare_partition_tables(); + } else { + fwu->new_partition_table = false; + fwu->incompatible_partition_tables = false; + } + + return 0; +} + +static int fwu_read_flash_status(void) +{ + int retval; + unsigned char status; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.data_base_addr + fwu->off.flash_status, + &status, + sizeof(status)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash status\n", + __func__); + return retval; + } + + fwu->in_bl_mode = status >> 7; + + if (fwu->bl_version == BL_V5) + fwu->flash_status = (status >> 4) & MASK_3BIT; + else if (fwu->bl_version == BL_V6) + fwu->flash_status = status & MASK_3BIT; + else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + fwu->flash_status = status & MASK_5BIT; + + if (fwu->write_bootloader) + fwu->flash_status = 0x00; + + if (fwu->flash_status != 0x00) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash status = %d, command = 0x%02x\n", + __func__, fwu->flash_status, fwu->command); + } + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) { + if (fwu->flash_status == 0x08) + fwu->flash_status = 0x00; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.data_base_addr + fwu->off.flash_cmd, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash command\n", + __func__); + return retval; + } + + if (fwu->bl_version == BL_V5) + fwu->command = command & MASK_4BIT; + else if (fwu->bl_version == BL_V6) + fwu->command = command & MASK_6BIT; + else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + fwu->command = command; + + if (fwu->write_bootloader) + fwu->command = 0x00; + + return 0; +} + +static int fwu_wait_for_idle(int timeout_ms, bool poll) +{ + int count = 0; + int timeout_count = ((timeout_ms * 1000) / MAX_SLEEP_TIME_US) + 1; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + do { + usleep_range(MIN_SLEEP_TIME_US, MAX_SLEEP_TIME_US); + + count++; + if (poll || (count == timeout_count)) + fwu_read_flash_status(); + + if ((fwu->command == CMD_IDLE) && (fwu->flash_status == 0x00)) + return 0; + } while (count < timeout_count); + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for idle status\n", + __func__); + + return -ETIMEDOUT; +} + +static int fwu_write_f34_v7_command_single_transaction(unsigned char cmd) +{ + int retval; + unsigned char data_base; + struct f34_v7_data_1_5 data_1_5; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + memset(data_1_5.data, 0x00, sizeof(data_1_5.data)); + + switch (cmd) { + case CMD_ERASE_ALL: + data_1_5.partition_id = CORE_CODE_PARTITION; + data_1_5.command = CMD_V7_ERASE_AP; + break; + case CMD_ERASE_UI_FIRMWARE: + data_1_5.partition_id = CORE_CODE_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_BL_CONFIG: + data_1_5.partition_id = GLOBAL_PARAMETERS_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_UI_CONFIG: + data_1_5.partition_id = CORE_CONFIG_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_DISP_CONFIG: + data_1_5.partition_id = DISPLAY_CONFIG_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_FLASH_CONFIG: + data_1_5.partition_id = FLASH_CONFIG_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_GUEST_CODE: + data_1_5.partition_id = GUEST_CODE_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_BOOTLOADER: + data_1_5.partition_id = BOOTLOADER_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_UTILITY_PARAMETER: + data_1_5.partition_id = UTILITY_PARAMETER_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ENABLE_FLASH_PROG: + data_1_5.partition_id = BOOTLOADER_PARTITION; + data_1_5.command = CMD_V7_ENTER_BL; + break; + }; + + data_1_5.payload_0 = fwu->bootloader_id[0]; + data_1_5.payload_1 = fwu->bootloader_id[1]; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.partition_id, + data_1_5.data, + sizeof(data_1_5.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write single transaction command\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_write_f34_v7_command(unsigned char cmd) +{ + int retval; + unsigned char data_base; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + switch (cmd) { + case CMD_WRITE_FW: + case CMD_WRITE_CONFIG: + case CMD_WRITE_LOCKDOWN: + case CMD_WRITE_GUEST_CODE: + case CMD_WRITE_BOOTLOADER: + case CMD_WRITE_UTILITY_PARAM: + command = CMD_V7_WRITE; + break; + case CMD_READ_CONFIG: + command = CMD_V7_READ; + break; + case CMD_ERASE_ALL: + command = CMD_V7_ERASE_AP; + break; + case CMD_ERASE_UI_FIRMWARE: + case CMD_ERASE_BL_CONFIG: + case CMD_ERASE_UI_CONFIG: + case CMD_ERASE_DISP_CONFIG: + case CMD_ERASE_FLASH_CONFIG: + case CMD_ERASE_GUEST_CODE: + case CMD_ERASE_BOOTLOADER: + case CMD_ERASE_UTILITY_PARAMETER: + command = CMD_V7_ERASE; + break; + case CMD_ENABLE_FLASH_PROG: + command = CMD_V7_ENTER_BL; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid command 0x%02x\n", + __func__, cmd); + return -EINVAL; + }; + + fwu->command = command; + + switch (cmd) { + case CMD_ERASE_ALL: + case CMD_ERASE_UI_FIRMWARE: + case CMD_ERASE_BL_CONFIG: + case CMD_ERASE_UI_CONFIG: + case CMD_ERASE_DISP_CONFIG: + case CMD_ERASE_FLASH_CONFIG: + case CMD_ERASE_GUEST_CODE: + case CMD_ERASE_BOOTLOADER: + case CMD_ERASE_UTILITY_PARAMETER: + case CMD_ENABLE_FLASH_PROG: + retval = fwu_write_f34_v7_command_single_transaction(cmd); + if (retval < 0) + return retval; + else + return 0; + default: + break; + }; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.flash_cmd, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write flash command\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_write_f34_v5v6_command(unsigned char cmd) +{ + int retval; + unsigned char data_base; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + switch (cmd) { + case CMD_IDLE: + command = CMD_V5V6_IDLE; + break; + case CMD_WRITE_FW: + command = CMD_V5V6_WRITE_FW; + break; + case CMD_WRITE_CONFIG: + command = CMD_V5V6_WRITE_CONFIG; + break; + case CMD_WRITE_LOCKDOWN: + command = CMD_V5V6_WRITE_LOCKDOWN; + break; + case CMD_WRITE_GUEST_CODE: + command = CMD_V5V6_WRITE_GUEST_CODE; + break; + case CMD_READ_CONFIG: + command = CMD_V5V6_READ_CONFIG; + break; + case CMD_ERASE_ALL: + command = CMD_V5V6_ERASE_ALL; + break; + case CMD_ERASE_UI_CONFIG: + command = CMD_V5V6_ERASE_UI_CONFIG; + break; + case CMD_ERASE_DISP_CONFIG: + command = CMD_V5V6_ERASE_DISP_CONFIG; + break; + case CMD_ERASE_GUEST_CODE: + command = CMD_V5V6_ERASE_GUEST_CODE; + break; + case CMD_ENABLE_FLASH_PROG: + command = CMD_V5V6_ENABLE_FLASH_PROG; + break; +#ifdef SYNA_TDDI + case CMD_ERASE_CHIP: + command = CMD_V5V6_ERASE_CHIP; + break; + case CMD_ERASE_FORCE_CONFIG: + command = CMD_V5V6_ERASE_FORCE_CONFIG; + break; + case CMD_READ_FORCE_CONFIG: + command = CMD_V5V6_READ_FORCE_CONFIG; + break; + case CMD_WRITE_FORCE_CONFIG: + command = CMD_V5V6_WRITE_CONFIG; + break; + case CMD_ERASE_LOCKDOWN_DATA: + command = CMD_V5V6_ERASE_LOCKDOWN_DATA; + break; + case CMD_READ_LOCKDOWN_DATA: + command = CMD_V5V6_READ_LOCKDOWN_DATA; + break; + case CMD_WRITE_LOCKDOWN_DATA: + command = CMD_V5V6_WRITE_LOCKDOWN_DATA; + break; + case CMD_ERASE_LCM_DATA: + command = CMD_V5V6_ERASE_LCM_DATA; + break; + case CMD_ERASE_OEM_DATA: + command = CMD_V5V6_ERASE_OEM_DATA; + break; +#endif + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid command 0x%02x\n", + __func__, cmd); + return -EINVAL; + } + + switch (cmd) { + case CMD_ERASE_ALL: + case CMD_ERASE_UI_CONFIG: + case CMD_ERASE_DISP_CONFIG: + case CMD_ERASE_GUEST_CODE: +#ifdef SYNA_TDDI + case CMD_ERASE_CHIP: + case CMD_ERASE_FORCE_CONFIG: + case CMD_ERASE_LOCKDOWN_DATA: + case CMD_ERASE_LCM_DATA: + case CMD_ERASE_OEM_DATA: +#endif + case CMD_ENABLE_FLASH_PROG: + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.payload, + fwu->bootloader_id, + sizeof(fwu->bootloader_id)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write bootloader ID\n", + __func__); + return retval; + } + break; + default: + break; + }; + + fwu->command = command; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.flash_cmd, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command 0x%02x\n", + __func__, command); + return retval; + } + + return 0; +} + +static int fwu_write_f34_command(unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_write_f34_v7_command(cmd); + else + retval = fwu_write_f34_v5v6_command(cmd); + + return retval; +} + +static int fwu_write_f34_v7_partition_id(unsigned char cmd) +{ + int retval; + unsigned char data_base; + unsigned char partition; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + switch (cmd) { + case CMD_WRITE_FW: + partition = CORE_CODE_PARTITION; + break; + case CMD_WRITE_CONFIG: + case CMD_READ_CONFIG: + if (fwu->config_area == UI_CONFIG_AREA) + partition = CORE_CONFIG_PARTITION; + else if (fwu->config_area == DP_CONFIG_AREA) + partition = DISPLAY_CONFIG_PARTITION; + else if (fwu->config_area == PM_CONFIG_AREA) + partition = GUEST_SERIALIZATION_PARTITION; + else if (fwu->config_area == BL_CONFIG_AREA) + partition = GLOBAL_PARAMETERS_PARTITION; + else if (fwu->config_area == FLASH_CONFIG_AREA) + partition = FLASH_CONFIG_PARTITION; + else if (fwu->config_area == UPP_AREA) + partition = UTILITY_PARAMETER_PARTITION; + break; + case CMD_WRITE_LOCKDOWN: + partition = DEVICE_CONFIG_PARTITION; + break; + case CMD_WRITE_GUEST_CODE: + partition = GUEST_CODE_PARTITION; + break; + case CMD_WRITE_BOOTLOADER: + partition = BOOTLOADER_PARTITION; + break; + case CMD_WRITE_UTILITY_PARAM: + partition = UTILITY_PARAMETER_PARTITION; + break; + case CMD_ERASE_ALL: + partition = CORE_CODE_PARTITION; + break; + case CMD_ERASE_BL_CONFIG: + partition = GLOBAL_PARAMETERS_PARTITION; + break; + case CMD_ERASE_UI_CONFIG: + partition = CORE_CONFIG_PARTITION; + break; + case CMD_ERASE_DISP_CONFIG: + partition = DISPLAY_CONFIG_PARTITION; + break; + case CMD_ERASE_FLASH_CONFIG: + partition = FLASH_CONFIG_PARTITION; + break; + case CMD_ERASE_GUEST_CODE: + partition = GUEST_CODE_PARTITION; + break; + case CMD_ERASE_BOOTLOADER: + partition = BOOTLOADER_PARTITION; + break; + case CMD_ENABLE_FLASH_PROG: + partition = BOOTLOADER_PARTITION; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid command 0x%02x\n", + __func__, cmd); + return -EINVAL; + }; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.partition_id, + &partition, + sizeof(partition)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write partition ID\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_write_f34_partition_id(unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_write_f34_v7_partition_id(cmd); + else + retval = 0; + + return retval; +} + +static int fwu_read_f34_v7_partition_table(unsigned char *partition_table) +{ + int retval; + unsigned char data_base; + unsigned char length[2]; + unsigned short block_number = 0; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + fwu->config_area = FLASH_CONFIG_AREA; + + retval = fwu_write_f34_partition_id(CMD_READ_CONFIG); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + (unsigned char *)&block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + length[0] = (unsigned char)(fwu->flash_config_length & MASK_8BIT); + length[1] = (unsigned char)(fwu->flash_config_length >> 8); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.transfer_length, + length, + sizeof(length)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write transfer length\n", + __func__); + return retval; + } + + retval = fwu_write_f34_command(CMD_READ_CONFIG); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command\n", + __func__); + return retval; + } + + msleep(READ_CONFIG_WAIT_MS); + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, true); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status\n", + __func__); + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + fwu->off.payload, + partition_table, + fwu->partition_table_bytes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block data\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_read_f34_v7_queries(void) +{ + int retval; + unsigned char ii; + unsigned char query_base; + unsigned char index; + unsigned char offset; + unsigned char *ptable; + struct f34_v7_query_0 query_0; + struct f34_v7_query_1_7 query_1_7; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + query_base = fwu->f34_fd.query_base_addr; + + retval = synaptics_rmi4_reg_read(rmi4_data, + query_base, + query_0.data, + sizeof(query_0.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read query 0\n", + __func__); + return retval; + } + + offset = query_0.subpacket_1_size + 1; + + retval = synaptics_rmi4_reg_read(rmi4_data, + query_base + offset, + query_1_7.data, + sizeof(query_1_7.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read queries 1 to 7\n", + __func__); + return retval; + } + + fwu->bootloader_id[0] = query_1_7.bl_minor_revision; + fwu->bootloader_id[1] = query_1_7.bl_major_revision; + + if (fwu->bootloader_id[1] == BL_V8) + fwu->bl_version = BL_V8; + + fwu->block_size = query_1_7.block_size_15_8 << 8 | + query_1_7.block_size_7_0; + + fwu->flash_config_length = query_1_7.flash_config_length_15_8 << 8 | + query_1_7.flash_config_length_7_0; + + fwu->payload_length = query_1_7.payload_length_15_8 << 8 | + query_1_7.payload_length_7_0; + + fwu->off.flash_status = V7_FLASH_STATUS_OFFSET; + fwu->off.partition_id = V7_PARTITION_ID_OFFSET; + fwu->off.block_number = V7_BLOCK_NUMBER_OFFSET; + fwu->off.transfer_length = V7_TRANSFER_LENGTH_OFFSET; + fwu->off.flash_cmd = V7_COMMAND_OFFSET; + fwu->off.payload = V7_PAYLOAD_OFFSET; + + index = sizeof(query_1_7.data) - V7_PARTITION_SUPPORT_BYTES; + + fwu->partitions = 0; + for (offset = 0; offset < V7_PARTITION_SUPPORT_BYTES; offset++) { + for (ii = 0; ii < 8; ii++) { + if (query_1_7.data[index + offset] & (1 << ii)) + fwu->partitions++; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Supported partitions: 0x%02x\n", + __func__, query_1_7.data[index + offset]); + } + + fwu->partition_table_bytes = fwu->partitions * 8 + 2; + + ptable = kzalloc(fwu->partition_table_bytes, GFP_KERNEL); + if (!ptable) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for partition table\n", + __func__); + return -ENOMEM; + } + + retval = fwu_read_f34_v7_partition_table(ptable); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read partition table\n", + __func__); + kfree(ptable); + return retval; + } + + fwu_parse_partition_table(ptable, &fwu->blkcount, &fwu->phyaddr); + + if (fwu->blkcount.dp_config) + fwu->flash_properties.has_disp_config = 1; + else + fwu->flash_properties.has_disp_config = 0; + + if (fwu->blkcount.pm_config) + fwu->flash_properties.has_pm_config = 1; + else + fwu->flash_properties.has_pm_config = 0; + + if (fwu->blkcount.bl_config) + fwu->flash_properties.has_bl_config = 1; + else + fwu->flash_properties.has_bl_config = 0; + + if (fwu->blkcount.guest_code) + fwu->has_guest_code = 1; + else + fwu->has_guest_code = 0; + + if (fwu->blkcount.utility_param) + fwu->has_utility_param = 1; + else + fwu->has_utility_param = 0; + + kfree(ptable); + + return 0; +} + +static int fwu_read_f34_v5v6_queries(void) +{ + int retval; + unsigned char count; + unsigned char base; + unsigned char offset; + unsigned char buf[10]; + struct f34_v5v6_flash_properties_2 properties_2; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + base = fwu->f34_fd.query_base_addr; + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + V5V6_BOOTLOADER_ID_OFFSET, + fwu->bootloader_id, + sizeof(fwu->bootloader_id)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read bootloader ID\n", + __func__); + return retval; + } + + if (fwu->bl_version == BL_V5) { + fwu->off.properties = V5_PROPERTIES_OFFSET; + fwu->off.block_size = V5_BLOCK_SIZE_OFFSET; + fwu->off.block_count = V5_BLOCK_COUNT_OFFSET; + fwu->off.block_number = V5_BLOCK_NUMBER_OFFSET; + fwu->off.payload = V5_BLOCK_DATA_OFFSET; + } else if (fwu->bl_version == BL_V6) { + fwu->off.properties = V6_PROPERTIES_OFFSET; + fwu->off.properties_2 = V6_PROPERTIES_2_OFFSET; + fwu->off.block_size = V6_BLOCK_SIZE_OFFSET; + fwu->off.block_count = V6_BLOCK_COUNT_OFFSET; + fwu->off.gc_block_count = V6_GUEST_CODE_BLOCK_COUNT_OFFSET; + fwu->off.block_number = V6_BLOCK_NUMBER_OFFSET; + fwu->off.payload = V6_BLOCK_DATA_OFFSET; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.block_size, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block size info\n", + __func__); + return retval; + } + + batohs(&fwu->block_size, &(buf[0])); + + if (fwu->bl_version == BL_V5) { + fwu->off.flash_cmd = fwu->off.payload + fwu->block_size; + fwu->off.flash_status = fwu->off.flash_cmd; + } else if (fwu->bl_version == BL_V6) { + fwu->off.flash_cmd = V6_FLASH_COMMAND_OFFSET; + fwu->off.flash_status = V6_FLASH_STATUS_OFFSET; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.properties, + fwu->flash_properties.data, + sizeof(fwu->flash_properties.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash properties\n", + __func__); + return retval; + } + + count = 4; + + if (fwu->flash_properties.has_pm_config) + count += 2; + + if (fwu->flash_properties.has_bl_config) + count += 2; + + if (fwu->flash_properties.has_disp_config) + count += 2; + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.block_count, + buf, + count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block count info\n", + __func__); + return retval; + } + + batohs(&fwu->blkcount.ui_firmware, &(buf[0])); + batohs(&fwu->blkcount.ui_config, &(buf[2])); + + count = 4; + + if (fwu->flash_properties.has_pm_config) { + batohs(&fwu->blkcount.pm_config, &(buf[count])); + count += 2; + } + + if (fwu->flash_properties.has_bl_config) { + batohs(&fwu->blkcount.bl_config, &(buf[count])); + count += 2; + } + + if (fwu->flash_properties.has_disp_config) + batohs(&fwu->blkcount.dp_config, &(buf[count])); + + fwu->has_guest_code = false; +#ifdef SYNA_TDDI + fwu->has_force_config = false; + fwu->has_lockdown_data = false; + fwu->has_lcm_data = false; + fwu->has_oem_data = false; +#endif + + if (fwu->flash_properties.has_query4) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.properties_2, + properties_2.data, + sizeof(properties_2.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash properties 2\n", + __func__); + return retval; + } + offset = fwu->off.properties_2 + 1; + count = 0; + if (properties_2.has_guest_code) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read guest code block count\n", + __func__); + return retval; + } + + batohs(&fwu->blkcount.guest_code, &(buf[0])); + count++; + fwu->has_guest_code = true; + } +#ifdef SYNA_TDDI + if (properties_2.has_force_config) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi force block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_force_config, &(buf[0])); + count++; + fwu->has_force_config = true; + } + if (properties_2.has_lockdown_data) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi lockdown block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_lockdown_data, &(buf[0])); + count++; + fwu->has_lockdown_data = true; + } + if (properties_2.has_lcm_data) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi lcm block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_lcm_data, &(buf[0])); + count++; + fwu->has_lcm_data = true; + } + if (properties_2.has_oem_data) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi oem block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_oem_data, &(buf[0])); + fwu->has_oem_data = true; + } +#endif + } + + fwu->has_utility_param = false; + + return 0; +} + +static int fwu_read_f34_queries(void) +{ + int retval; + + memset(&fwu->blkcount, 0x00, sizeof(fwu->blkcount)); + memset(&fwu->phyaddr, 0x00, sizeof(fwu->phyaddr)); + + if (fwu->bl_version == BL_V7) + retval = fwu_read_f34_v7_queries(); + else + retval = fwu_read_f34_v5v6_queries(); + + return retval; +} + +static int fwu_write_f34_v7_blocks(unsigned char *block_ptr, + unsigned short block_cnt, unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char length[2]; + unsigned short transfer; + unsigned short remaining = block_cnt; + unsigned short block_number = 0; + unsigned short left_bytes; + unsigned short write_size; + unsigned short max_write_size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + retval = fwu_write_f34_partition_id(command); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + (unsigned char *)&block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + do { + if (remaining / fwu->payload_length) + transfer = fwu->payload_length; + else + transfer = remaining; + + length[0] = (unsigned char)(transfer & MASK_8BIT); + length[1] = (unsigned char)(transfer >> 8); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.transfer_length, + length, + sizeof(length)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write transfer length (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command (remaining = %d)\n", + __func__, remaining); + return retval; + } + +#ifdef MAX_WRITE_SIZE + max_write_size = MAX_WRITE_SIZE; + if (max_write_size >= transfer * fwu->block_size) + max_write_size = transfer * fwu->block_size; + else if (max_write_size > fwu->block_size) + max_write_size -= max_write_size % fwu->block_size; + else + max_write_size = fwu->block_size; +#else + max_write_size = transfer * fwu->block_size; +#endif + left_bytes = transfer * fwu->block_size; + + do { + if (left_bytes / max_write_size) + write_size = max_write_size; + else + write_size = left_bytes; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.payload, + block_ptr, + write_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block data (remaining = %d)\n", + __func__, remaining); + return retval; + } + + block_ptr += write_size; + left_bytes -= write_size; + } while (left_bytes); + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status (remaining = %d)\n", + __func__, remaining); + return retval; + } + + remaining -= transfer; + } while (remaining); + + return 0; +} + +static int fwu_write_f34_v5v6_blocks(unsigned char *block_ptr, + unsigned short block_cnt, unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char block_number[] = {0, 0}; + unsigned short blk; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + block_number[1] |= (fwu->config_area << 5); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + for (blk = 0; blk < block_cnt; blk++) { + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.payload, + block_ptr, + fwu->block_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block data (block %d)\n", + __func__, blk); + return retval; + } + + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command for block %d\n", + __func__, blk); + return retval; + } + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status (block %d)\n", + __func__, blk); + return retval; + } + + block_ptr += fwu->block_size; + } + + return 0; +} + +static int fwu_write_f34_blocks(unsigned char *block_ptr, + unsigned short block_cnt, unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_write_f34_v7_blocks(block_ptr, block_cnt, cmd); + else + retval = fwu_write_f34_v5v6_blocks(block_ptr, block_cnt, cmd); + + return retval; +} + +static int fwu_read_f34_v7_blocks(unsigned short block_cnt, + unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char length[2]; + unsigned short transfer; + unsigned short remaining = block_cnt; + unsigned short block_number = 0; + unsigned short index = 0; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + retval = fwu_write_f34_partition_id(command); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + (unsigned char *)&block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + do { + if (remaining / fwu->payload_length) + transfer = fwu->payload_length; + else + transfer = remaining; + + length[0] = (unsigned char)(transfer & MASK_8BIT); + length[1] = (unsigned char)(transfer >> 8); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.transfer_length, + length, + sizeof(length)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write transfer length (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + fwu->off.payload, + &fwu->read_config_buf[index], + transfer * fwu->block_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block data (remaining = %d)\n", + __func__, remaining); + return retval; + } + + index += (transfer * fwu->block_size); + remaining -= transfer; + } while (remaining); + + return 0; +} + +static int fwu_read_f34_v5v6_blocks(unsigned short block_cnt, + unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char block_number[] = {0, 0}; + unsigned short blk; + unsigned short index = 0; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + block_number[1] |= (fwu->config_area << 5); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + for (blk = 0; blk < block_cnt; blk++) { + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write read config command\n", + __func__); + return retval; + } + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status\n", + __func__); + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + fwu->off.payload, + &fwu->read_config_buf[index], + fwu->block_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block data (block %d)\n", + __func__, blk); + return retval; + } + + index += fwu->block_size; + } + + return 0; +} + +static int fwu_read_f34_blocks(unsigned short block_cnt, unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_read_f34_v7_blocks(block_cnt, cmd); + else + retval = fwu_read_f34_v5v6_blocks(block_cnt, cmd); + + return retval; +} + +static int fwu_get_image_firmware_id(unsigned int *fw_id) +{ + int retval; + unsigned char index = 0; + char *strptr; + char *firmware_id; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->img.contains_firmware_id) { + *fw_id = fwu->img.firmware_id; + } else { + strptr = strnstr(fwu->image_name, "PR", MAX_IMAGE_NAME_LEN); + if (!strptr) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No valid PR number (PRxxxxxxx) found in image file name (%s)\n", + __func__, fwu->image_name); + return -EINVAL; + } + + strptr += 2; + firmware_id = kzalloc(MAX_FIRMWARE_ID_LEN, GFP_KERNEL); + if (!firmware_id) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for firmware_id\n", + __func__); + return -ENOMEM; + } + while (strptr[index] >= '0' && strptr[index] <= '9') { + firmware_id[index] = strptr[index]; + index++; + if (index == MAX_FIRMWARE_ID_LEN - 1) + break; + } + + retval = sstrtoul(firmware_id, 10, (unsigned long *)fw_id); + kfree(firmware_id); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to obtain image firmware ID\n", + __func__); + return -EINVAL; + } + } + + return 0; +} + +static int fwu_get_device_config_id(void) +{ + int retval; + unsigned char config_id_size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + config_id_size = V7_CONFIG_ID_SIZE; + else + config_id_size = V5V6_CONFIG_ID_SIZE; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.ctrl_base_addr, + fwu->config_id, + config_id_size); + if (retval < 0) + return retval; + + return 0; +} + +static enum flash_area fwu_go_nogo(void) +{ + int retval; + enum flash_area flash_area = NONE; + unsigned char ii; + unsigned char config_id_size; + unsigned int device_fw_id; + unsigned int image_fw_id; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->force_update) { + flash_area = UI_FIRMWARE; + goto exit; + } + + /* Update both UI and config if device is in bootloader mode */ + if (fwu->bl_mode_device) { + flash_area = UI_FIRMWARE; + goto exit; + } + + /* Get device firmware ID */ + device_fw_id = rmi4_data->firmware_id; + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device firmware ID = %d\n", + __func__, device_fw_id); + + /* Get image firmware ID */ + retval = fwu_get_image_firmware_id(&image_fw_id); + if (retval < 0) { + flash_area = NONE; + goto exit; + } + dev_info(rmi4_data->pdev->dev.parent, + "%s: Image firmware ID = %d\n", + __func__, image_fw_id); + + if (image_fw_id > device_fw_id) { + flash_area = UI_FIRMWARE; + goto exit; + } else if (image_fw_id < device_fw_id) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Image firmware ID older than device firmware ID\n", + __func__); + flash_area = NONE; + goto exit; + } + + /* Get device config ID */ + retval = fwu_get_device_config_id(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device config ID\n", + __func__); + flash_area = NONE; + goto exit; + } + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + config_id_size = V7_CONFIG_ID_SIZE; + else + config_id_size = V5V6_CONFIG_ID_SIZE; + + for (ii = 0; ii < config_id_size; ii++) { + if (fwu->img.ui_config.data[ii] > fwu->config_id[ii]) { + flash_area = UI_CONFIG; + goto exit; + } else if (fwu->img.ui_config.data[ii] < fwu->config_id[ii]) { + flash_area = NONE; + goto exit; + } + } + + flash_area = NONE; + +exit: + if (flash_area == NONE) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: No need to do reflash\n", + __func__); + } else { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Updating %s\n", + __func__, + flash_area == UI_FIRMWARE ? + "UI firmware and config" : + "UI config only"); + } + + return flash_area; +} + +static int fwu_scan_pdt(void) +{ + int retval; + unsigned char ii; + unsigned char intr_count = 0; + unsigned char intr_off; + unsigned char intr_src; + unsigned short addr; + bool f01found = false; + bool f34found = false; + bool f35found = false; + struct synaptics_rmi4_fn_desc rmi_fd; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + fwu->in_ub_mode = false; + + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&rmi_fd, + sizeof(rmi_fd)); + if (retval < 0) + return retval; + + if (rmi_fd.fn_number) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Found F%02x\n", + __func__, rmi_fd.fn_number); + switch (rmi_fd.fn_number) { + case SYNAPTICS_RMI4_F01: + f01found = true; + + rmi4_data->f01_query_base_addr = + rmi_fd.query_base_addr; + rmi4_data->f01_ctrl_base_addr = + rmi_fd.ctrl_base_addr; + rmi4_data->f01_data_base_addr = + rmi_fd.data_base_addr; + rmi4_data->f01_cmd_base_addr = + rmi_fd.cmd_base_addr; + break; + case SYNAPTICS_RMI4_F34: + f34found = true; + fwu->f34_fd.query_base_addr = + rmi_fd.query_base_addr; + fwu->f34_fd.ctrl_base_addr = + rmi_fd.ctrl_base_addr; + fwu->f34_fd.data_base_addr = + rmi_fd.data_base_addr; + + switch (rmi_fd.fn_version) { + case F34_V0: + fwu->bl_version = BL_V5; + break; + case F34_V1: + fwu->bl_version = BL_V6; + break; + case F34_V2: + fwu->bl_version = BL_V7; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Unrecognized F34 version\n", + __func__); + return -EINVAL; + } + + fwu->intr_mask = 0; + intr_src = rmi_fd.intr_src_count; + intr_off = intr_count % 8; + for (ii = intr_off; + ii < (intr_src + intr_off); + ii++) { + fwu->intr_mask |= 1 << ii; + } + break; + case SYNAPTICS_RMI4_F35: + f35found = true; + fwu->f35_fd.query_base_addr = + rmi_fd.query_base_addr; + fwu->f35_fd.ctrl_base_addr = + rmi_fd.ctrl_base_addr; + fwu->f35_fd.data_base_addr = + rmi_fd.data_base_addr; + fwu->f35_fd.cmd_base_addr = + rmi_fd.cmd_base_addr; + break; + } + } else { + break; + } + + intr_count += rmi_fd.intr_src_count; + } + + if (!f01found || !f34found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find both F01 and F34\n", + __func__); + if (!f35found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F35\n", + __func__); + return -EINVAL; + } else { + fwu->in_ub_mode = true; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + fwu_recovery_check_status(); + return 0; + } + } + + rmi4_data->intr_mask[0] |= fwu->intr_mask; + + addr = rmi4_data->f01_ctrl_base_addr + 1; + + retval = synaptics_rmi4_reg_write(rmi4_data, + addr, + &(rmi4_data->intr_mask[0]), + sizeof(rmi4_data->intr_mask[0])); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set interrupt enable bit\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_enter_flash_prog(void) +{ + int retval; + struct f01_device_control f01_device_control; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_read_flash_status(); + if (retval < 0) + return retval; + + if (fwu->in_bl_mode) + return 0; + + retval = rmi4_data->irq_enable(rmi4_data, false, true); + if (retval < 0) + return retval; + + msleep(INT_DISABLE_WAIT_MS); + + retval = fwu_write_f34_command(CMD_ENABLE_FLASH_PROG); + if (retval < 0) + return retval; + + retval = fwu_wait_for_idle(ENABLE_WAIT_MS, false); + if (retval < 0) + return retval; + + if (!fwu->in_bl_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: BL mode not entered\n", + __func__); + return -EINVAL; + } + + if (rmi4_data->hw_if->bl_hw_init) { + retval = rmi4_data->hw_if->bl_hw_init(rmi4_data); + if (retval < 0) + return retval; + } + + retval = fwu_scan_pdt(); + if (retval < 0) + return retval; + + retval = fwu_read_f34_queries(); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + f01_device_control.data, + sizeof(f01_device_control.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F01 device control\n", + __func__); + return retval; + } + + f01_device_control.nosleep = true; + f01_device_control.sleep_mode = SLEEP_MODE_NORMAL; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + f01_device_control.data, + sizeof(f01_device_control.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write F01 device control\n", + __func__); + return retval; + } + + msleep(ENTER_FLASH_PROG_WAIT_MS); + + return retval; +} + +static int fwu_check_ui_firmware_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.ui_firmware.size / fwu->block_size; + + if (block_count != fwu->blkcount.ui_firmware) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: UI firmware size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_ui_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.ui_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.ui_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: UI configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_dp_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.dp_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.dp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Display configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_pm_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.pm_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_bl_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.bl_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.bl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Bootloader configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_guest_code_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.guest_code.size / fwu->block_size; + if (block_count != fwu->blkcount.guest_code) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Guest code size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_erase_configuration(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_UI_CONFIG); + if (retval < 0) + return retval; + break; + case DP_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_DISP_CONFIG); + if (retval < 0) + return retval; + break; + case BL_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_BL_CONFIG); + if (retval < 0) + return retval; + break; + case FLASH_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_FLASH_CONFIG); + if (retval < 0) + return retval; + break; + case UPP_AREA: + retval = fwu_write_f34_command(CMD_ERASE_UTILITY_PARAMETER); + if (retval < 0) + return retval; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid config area\n", + __func__); + return -EINVAL; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return retval; +} + +static int fwu_erase_bootloader(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_command(CMD_ERASE_BOOTLOADER); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return 0; +} + +#ifdef SYNA_TDDI +static int fwu_erase_lockdown_data(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_command(CMD_ERASE_LOCKDOWN_DATA); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + msleep(100); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return 0; +} + +#endif + +static int fwu_erase_guest_code(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_command(CMD_ERASE_GUEST_CODE); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return 0; +} + +static int fwu_erase_all(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->bl_version == BL_V7) { + retval = fwu_write_f34_command(CMD_ERASE_UI_FIRMWARE); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + fwu->config_area = UI_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + } else { + retval = fwu_write_f34_command(CMD_ERASE_ALL); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase all command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (!(fwu->bl_version == BL_V8 && + fwu->flash_status == BAD_PARTITION_TABLE)) { + if (retval < 0) + return retval; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + if (fwu->bl_version == BL_V8) + return 0; + } + + if (fwu->flash_properties.has_disp_config) { + fwu->config_area = DP_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + } + + if (fwu->has_guest_code) { + retval = fwu_erase_guest_code(); + if (retval < 0) + return retval; + } + + return 0; +} + +static int fwu_write_firmware(void) +{ + unsigned short firmware_block_count; + + firmware_block_count = fwu->img.ui_firmware.size / fwu->block_size; + + return fwu_write_f34_blocks((unsigned char *)fwu->img.ui_firmware.data, + firmware_block_count, CMD_WRITE_FW); +} + +static int fwu_write_bootloader(void) +{ + int retval; + unsigned short bootloader_block_count; + + bootloader_block_count = fwu->img.bl_image.size / fwu->block_size; + + fwu->write_bootloader = true; + retval = fwu_write_f34_blocks((unsigned char *)fwu->img.bl_image.data, + bootloader_block_count, CMD_WRITE_BOOTLOADER); + fwu->write_bootloader = false; + + return retval; +} + +static int fwu_write_utility_parameter(void) +{ + int retval; + unsigned char ii; + unsigned char checksum_array[4]; + unsigned char *pbuf; + unsigned short remaining_size; + unsigned short utility_param_size; + unsigned long checksum; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + utility_param_size = fwu->blkcount.utility_param * fwu->block_size; + retval = fwu_allocate_read_config_buf(utility_param_size); + if (retval < 0) + return retval; + memset(fwu->read_config_buf, 0x00, utility_param_size); + + pbuf = fwu->read_config_buf; + remaining_size = utility_param_size - 4; + + for (ii = 0; ii < MAX_UTILITY_PARAMS; ii++) { + if (fwu->img.utility_param_id[ii] == UNUSED) + continue; + +#ifdef F51_DISCRETE_FORCE + if (fwu->img.utility_param_id[ii] == FORCE_PARAMETER) { + if (fwu->bl_mode_device) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device in bootloader mode, skipping calibration data restoration\n", + __func__); + goto image_param; + } + retval = secure_memcpy(&(pbuf[4]), + remaining_size - 4, + fwu->cal_data, + fwu->cal_data_buf_size, + fwu->cal_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy force calibration data\n", + __func__); + return retval; + } + pbuf[0] = FORCE_PARAMETER; + pbuf[1] = 0x00; + pbuf[2] = (4 + fwu->cal_data_size) / 2; + pbuf += (fwu->cal_data_size + 4); + remaining_size -= (fwu->cal_data_size + 4); + continue; + } +image_param: +#endif + + retval = secure_memcpy(pbuf, + remaining_size, + fwu->img.utility_param[ii].data, + fwu->img.utility_param[ii].size, + fwu->img.utility_param[ii].size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy utility parameter data\n", + __func__); + return retval; + } + pbuf += fwu->img.utility_param[ii].size; + remaining_size -= fwu->img.utility_param[ii].size; + } + + calculate_checksum((unsigned short *)fwu->read_config_buf, + ((utility_param_size - 4) / 2), + &checksum); + + convert_to_little_endian(checksum_array, checksum); + + fwu->read_config_buf[utility_param_size - 4] = checksum_array[0]; + fwu->read_config_buf[utility_param_size - 3] = checksum_array[1]; + fwu->read_config_buf[utility_param_size - 2] = checksum_array[2]; + fwu->read_config_buf[utility_param_size - 1] = checksum_array[3]; + + retval = fwu_write_f34_blocks((unsigned char *)fwu->read_config_buf, + fwu->blkcount.utility_param, CMD_WRITE_UTILITY_PARAM); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_write_configuration(void) +{ + return fwu_write_f34_blocks((unsigned char *)fwu->config_data, + fwu->config_block_count, CMD_WRITE_CONFIG); +} + +static int fwu_write_ui_configuration(void) +{ + fwu->config_area = UI_CONFIG_AREA; + fwu->config_data = fwu->img.ui_config.data; + fwu->config_size = fwu->img.ui_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + return fwu_write_configuration(); +} + +static int fwu_write_dp_configuration(void) +{ + fwu->config_area = DP_CONFIG_AREA; + fwu->config_data = fwu->img.dp_config.data; + fwu->config_size = fwu->img.dp_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + return fwu_write_configuration(); +} + +static int fwu_write_pm_configuration(void) +{ + fwu->config_area = PM_CONFIG_AREA; + fwu->config_data = fwu->img.pm_config.data; + fwu->config_size = fwu->img.pm_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + return fwu_write_configuration(); +} + +#ifdef SYNA_TDDI +static int fwu_write_tddi_lockdown_data(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_blocks(fwu->read_config_buf, + fwu->blkcount.tddi_lockdown_data, + CMD_WRITE_LOCKDOWN_DATA); + if (retval < 0) + return retval; + rmi4_data->reset_device(rmi4_data, false); + return 0; +} +#endif + +static int fwu_write_flash_configuration(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + fwu->config_area = FLASH_CONFIG_AREA; + fwu->config_data = fwu->img.fl_config.data; + fwu->config_size = fwu->img.fl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + if (fwu->config_block_count != fwu->blkcount.fl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash configuration size mismatch\n", + __func__); + return -EINVAL; + } + + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + rmi4_data->reset_device(rmi4_data, false); + + return 0; +} + +static int fwu_write_guest_code(void) +{ + int retval; + unsigned short guest_code_block_count; + + guest_code_block_count = fwu->img.guest_code.size / fwu->block_size; + + retval = fwu_write_f34_blocks((unsigned char *)fwu->img.guest_code.data, + guest_code_block_count, CMD_WRITE_GUEST_CODE); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_write_lockdown(void) +{ + unsigned short lockdown_block_count; + + lockdown_block_count = fwu->img.lockdown.size / fwu->block_size; + + return fwu_write_f34_blocks((unsigned char *)fwu->img.lockdown.data, + lockdown_block_count, CMD_WRITE_LOCKDOWN); +} + +static int fwu_write_partition_table_v8(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + fwu->config_area = FLASH_CONFIG_AREA; + fwu->config_data = fwu->img.fl_config.data; + fwu->config_size = fwu->img.fl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + if (fwu->config_block_count != fwu->blkcount.fl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash configuration size mismatch\n", + __func__); + return -EINVAL; + } + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + rmi4_data->reset_device(rmi4_data, false); + + return 0; +} + +static int fwu_write_partition_table_v7(void) +{ + int retval; + unsigned short block_count; + + block_count = fwu->blkcount.bl_config; + fwu->config_area = BL_CONFIG_AREA; + fwu->config_size = fwu->block_size * block_count; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + return retval; + + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG); + if (retval < 0) + return retval; + + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_write_flash_configuration(); + if (retval < 0) + return retval; + + fwu->config_area = BL_CONFIG_AREA; + fwu->config_data = fwu->read_config_buf; + fwu->config_size = fwu->img.bl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_write_bl_area_v7(void) +{ + int retval; + bool has_utility_param; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + has_utility_param = fwu->has_utility_param; + + if (fwu->has_utility_param) { + fwu->config_area = UPP_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + } + + fwu->config_area = BL_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + fwu->config_area = FLASH_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_erase_bootloader(); + if (retval < 0) + return retval; + + retval = fwu_write_bootloader(); + if (retval < 0) + return retval; + + msleep(rmi4_data->hw_if->board_data->reset_delay_ms); + rmi4_data->reset_device(rmi4_data, false); + + fwu->config_area = FLASH_CONFIG_AREA; + fwu->config_data = fwu->img.fl_config.data; + fwu->config_size = fwu->img.fl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + rmi4_data->reset_device(rmi4_data, false); + + fwu->config_area = BL_CONFIG_AREA; + fwu->config_data = fwu->img.bl_config.data; + fwu->config_size = fwu->img.bl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + if (fwu->img.contains_utility_param) { + retval = fwu_write_utility_parameter(); + if (retval < 0) + return retval; + } + + return 0; +} + +static int fwu_do_reflash(void) +{ + int retval; + bool do_bl_update = false; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!fwu->new_partition_table) { + retval = fwu_check_ui_firmware_size(); + if (retval < 0) + return retval; + + retval = fwu_check_ui_configuration_size(); + if (retval < 0) + return retval; + + if (fwu->flash_properties.has_disp_config && + fwu->img.contains_disp_config) { + retval = fwu_check_dp_configuration_size(); + if (retval < 0) + return retval; + } + + if (fwu->has_guest_code && fwu->img.contains_guest_code) { + retval = fwu_check_guest_code_size(); + if (retval < 0) + return retval; + } + } else if (fwu->bl_version == BL_V7) { + retval = fwu_check_bl_configuration_size(); + if (retval < 0) + return retval; + } + + if (!fwu->has_utility_param && fwu->img.contains_utility_param) { + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + do_bl_update = true; + } + + if (fwu->has_utility_param && !fwu->img.contains_utility_param) { + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + do_bl_update = true; + } + + if (!do_bl_update && fwu->incompatible_partition_tables) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Incompatible partition tables\n", + __func__); + return -EINVAL; + } else if (!do_bl_update && fwu->new_partition_table) { + if (!fwu->force_update) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Partition table mismatch\n", + __func__); + return -EINVAL; + } + } + + retval = fwu_erase_all(); + if (retval < 0) + return retval; + + if (do_bl_update) { + retval = fwu_write_bl_area_v7(); + if (retval < 0) + return retval; + pr_notice("%s: Bootloader area programmed\n", __func__); + } else if (fwu->bl_version == BL_V7 && fwu->new_partition_table) { + retval = fwu_write_partition_table_v7(); + if (retval < 0) + return retval; + pr_notice("%s: Partition table programmed\n", __func__); + } else if (fwu->bl_version == BL_V8) { + retval = fwu_write_partition_table_v8(); + if (retval < 0) + return retval; + pr_notice("%s: Partition table programmed\n", __func__); + } + + fwu->config_area = UI_CONFIG_AREA; + if (fwu->flash_properties.has_disp_config && + fwu->img.contains_disp_config) { + retval = fwu_write_dp_configuration(); + if (retval < 0) + return retval; + pr_notice("%s: Display configuration programmed\n", __func__); + } + + retval = fwu_write_ui_configuration(); + if (retval < 0) + return retval; + pr_notice("%s: Configuration programmed\n", __func__); + + if (fwu->has_guest_code && fwu->img.contains_guest_code) { + retval = fwu_write_guest_code(); + if (retval < 0) + return retval; + pr_notice("%s: Guest code programmed\n", __func__); + } + + retval = fwu_write_firmware(); + if (retval < 0) + return retval; + pr_notice("%s: Firmware programmed\n", __func__); + + return retval; +} + +static int fwu_do_read_config(void) +{ + int retval; + unsigned short block_count; + unsigned short config_area; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + block_count = fwu->blkcount.ui_config; + break; + case DP_CONFIG_AREA: + if (!fwu->flash_properties.has_disp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Display configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.dp_config; + break; + case PM_CONFIG_AREA: + if (!fwu->flash_properties.has_pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.pm_config; + break; + case BL_CONFIG_AREA: + if (!fwu->flash_properties.has_bl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Bootloader configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.bl_config; + break; + case UPP_AREA: + if (!fwu->has_utility_param) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Utility parameter not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.utility_param; + break; +#ifdef SYNA_TDDI + case TDDI_FORCE_CONFIG_AREA: + if (!fwu->has_force_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: force configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.tddi_force_config; + break; + case TDDI_OEM_DATA_AREA: + if (!fwu->has_oem_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: oem data not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.tddi_oem_data; + break; + case TDDI_LCM_DATA_AREA: + if (!fwu->has_lcm_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: lcm data not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.tddi_lcm_data; + break; +#endif + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid config area\n", + __func__); + return -EINVAL; + } + + if (block_count == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid block count\n", + __func__); + return -EINVAL; + } + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + if (fwu->bl_version == BL_V5 || fwu->bl_version == BL_V6) { + config_area = fwu->config_area; + retval = fwu_enter_flash_prog(); + fwu->config_area = config_area; + if (retval < 0) + goto exit; + } + + fwu->config_size = fwu->block_size * block_count; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + goto exit; + + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG); + +exit: + if (fwu->bl_version == BL_V5 || fwu->bl_version == BL_V6) + rmi4_data->reset_device(rmi4_data, false); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + return retval; +} + +static int fwu_do_read_customer_serialization_data(void) +{ + int ii; + int retval = 0; + int block_count = 0; + char temp[40] = {0}; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + if (!fwu->flash_properties.has_pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration not supported\n", + __func__); + return -EINVAL; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of customer serialization aquirement process\n", __func__); + + retval = fwu_read_flash_status(); + if (retval < 0) + goto exit; + fwu->config_area = PM_CONFIG_AREA; + block_count = fwu->blkcount.pm_config; + if (block_count == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid block count\n", + __func__); + goto exit; + } + fwu->config_size = fwu->block_size * block_count; + pr_notice("%s: Block size = %d\n", __func__, fwu->block_size); + pr_notice("%s: Permanent config block count = %d\n", __func__, block_count); + pr_notice("%s: Permanent config size = %d\n", __func__, fwu->config_size); + dev_info(rmi4_data->pdev->dev.parent, + "%s: permanent config size = %d\n", + __func__, fwu->config_size); + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) { + + goto exit; + } + + retval = fwu_read_f34_blocks(block_count, + CMD_READ_CONFIG); + if (retval < 0) { + + goto exit; + } + + for (ii = 0; ii < 10; ii++) + pr_notice("%s: Permanent config data[%d] = 0x%02x\n", __func__, ii, fwu->read_config_buf[ii]); + + sprintf(temp, "%02x%02x%02x%02x%02x%02x%02x%02x", fwu->read_config_buf[0], fwu->read_config_buf[1], fwu->read_config_buf[2], fwu->read_config_buf[3], fwu->read_config_buf[4], fwu->read_config_buf[5], fwu->read_config_buf[6], fwu->read_config_buf[7]); + printk("tp_lockdown info : %s\n", temp); + strcpy(tp_lockdown_info, temp); + + + +exit: + + pr_notice("%s: End of customer serialization acquirement process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} + + + +#ifdef SYNA_TDDI +static int fwu_do_read_tddi_lockdown_data(void) +{ + int retval = -EINVAL; + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->blkcount.tddi_lockdown_data; + fwu->config_size = fwu->block_size * block_count; + + if (fwu->bl_version != BL_V6) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data in bl v.%d\n", + __func__, + fwu->bl_version); + goto exit; + } else if (!fwu->has_lockdown_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data\n", __func__); + goto exit; + } + + kfree(fwu->read_config_buf); + + fwu->read_config_buf = kzalloc(fwu->config_size, GFP_KERNEL); + + if (!fwu->read_config_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu->read_config_buf\n", + __func__); + fwu->read_config_buf_size = 0; + retval = -ENOMEM; + goto exit; + } + fwu->read_config_buf_size = fwu->config_size; + retval = fwu_read_f34_blocks(block_count, CMD_READ_LOCKDOWN_DATA); +exit: + return retval; +} + +int get_tddi_lockdown_data(unsigned char *lockdown_data, unsigned short leng) +{ + int retval; + + retval = fwu_do_read_tddi_lockdown_data(); + if (retval < 0) + return retval; + memcpy(lockdown_data, fwu->read_config_buf, leng); + return retval; +} + +int set_tddi_lockdown_data(unsigned char *lockdown_data, unsigned short leng) +{ + int retval = -EINVAL; + unsigned long checksum; + unsigned char checksum_array[4]; + unsigned short blk_cnt; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->bl_version != BL_V6) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data in bl v.%d\n", + __func__, + fwu->bl_version); + goto exit; + } else if (!fwu->has_lockdown_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data\n", __func__); + goto exit; + } + + retval = fwu_enter_flash_prog(); + if (retval < 0) + goto exit; + + retval = fwu_erase_lockdown_data(); + if (retval < 0) + goto exit; + + fwu->config_size = fwu->blkcount.tddi_lockdown_data * fwu->block_size; + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + goto exit; + memset(fwu->read_config_buf, 0x00, fwu->config_size); + retval = secure_memcpy(fwu->read_config_buf, fwu->config_size, + lockdown_data, leng, leng); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy tddi lockdwon data\n", + __func__); + goto exit; + } + + calculate_checksum((unsigned short *)fwu->read_config_buf, + ((fwu->config_size - 4) / 2), + &checksum); + + convert_to_little_endian(checksum_array, checksum); + + fwu->read_config_buf[blk_cnt * fwu->block_size - 4] = checksum_array[0]; + fwu->read_config_buf[blk_cnt * fwu->block_size - 3] = checksum_array[1]; + fwu->read_config_buf[blk_cnt * fwu->block_size - 2] = checksum_array[2]; + fwu->read_config_buf[blk_cnt * fwu->block_size - 1] = checksum_array[3]; + retval = fwu_write_tddi_lockdown_data(); +exit: + return retval; +} +#endif + +static int fwu_do_lockdown_v7(void) +{ + int retval; + struct f34_v7_data0 status; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_enter_flash_prog(); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.data_base_addr + fwu->off.flash_status, + status.data, + sizeof(status.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash status\n", + __func__); + return retval; + } + + if (status.device_cfg_status == 2) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device already locked down\n", + __func__); + return 0; + } + + retval = fwu_write_lockdown(); + if (retval < 0) + return retval; + + pr_notice("%s: Lockdown programmed\n", __func__); + + return retval; +} + +static int fwu_do_lockdown_v5v6(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; +#ifdef SYNA_TDDI + unsigned char *img_ld; + + img_ld = (unsigned char *)fwu->img.lockdown.data; + if (fwu->has_lockdown_data) { + retval = set_tddi_lockdown_data(img_ld, + LOCKDOWN_SIZE); + if (retval < 0) + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write lockdown data\n", + __func__); + return retval; + } +#endif + + retval = fwu_enter_flash_prog(); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.query_base_addr + fwu->off.properties, + fwu->flash_properties.data, + sizeof(fwu->flash_properties.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash properties\n", + __func__); + return retval; + } + + if (fwu->flash_properties.unlocked == 0) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device already locked down\n", + __func__); + return 0; + } + + retval = fwu_write_lockdown(); + if (retval < 0) + return retval; + + pr_notice("%s: Lockdown programmed\n", __func__); + + return retval; +} + +#ifdef F51_DISCRETE_FORCE +static int fwu_do_restore_f51_cal_data(void) +{ + int retval; + unsigned char checksum_array[4]; + unsigned short block_count; + unsigned long checksum; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->blkcount.ui_config; + fwu->config_size = fwu->block_size * block_count; + fwu->config_area = UI_CONFIG_AREA; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + return retval; + + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG); + if (retval < 0) + return retval; + + retval = secure_memcpy(&fwu->read_config_buf[fwu->cal_data_off], + fwu->cal_data_size, fwu->cal_data, + fwu->cal_data_buf_size, fwu->cal_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore calibration data\n", + __func__); + return retval; + } + + calculate_checksum((unsigned short *)fwu->read_config_buf, + ((fwu->config_size - 4) / 2), + &checksum); + + convert_to_little_endian(checksum_array, checksum); + + fwu->read_config_buf[fwu->config_size - 4] = checksum_array[0]; + fwu->read_config_buf[fwu->config_size - 3] = checksum_array[1]; + fwu->read_config_buf[fwu->config_size - 2] = checksum_array[2]; + fwu->read_config_buf[fwu->config_size - 1] = checksum_array[3]; + + retval = fwu_enter_flash_prog(); + if (retval < 0) + return retval; + + fwu->config_area = UI_CONFIG_AREA; + fwu->config_data = fwu->read_config_buf; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + return 0; +} +#endif + +static int fwu_start_write_guest_code(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_parse_image_info(); + if (retval < 0) + return -EINVAL; + + if (!fwu->has_guest_code) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Guest code not supported\n", + __func__); + return -EINVAL; + } + + if (!fwu->img.contains_guest_code) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No guest code in firmware image\n", + __func__); + return -EINVAL; + } + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of write guest code process\n", __func__); + + retval = fwu_enter_flash_prog(); + if (retval < 0) + goto exit; + + retval = fwu_check_guest_code_size(); + if (retval < 0) + goto exit; + + retval = fwu_erase_guest_code(); + if (retval < 0) + goto exit; + + retval = fwu_write_guest_code(); + if (retval < 0) + goto exit; + + pr_notice("%s: Guest code programmed\n", __func__); + +exit: + rmi4_data->reset_device(rmi4_data, false); + + pr_notice("%s: End of write guest code process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} + +static int fwu_start_write_config(void) +{ + int retval; + unsigned short config_area; + unsigned int device_fw_id; + unsigned int image_fw_id; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_parse_image_info(); + if (retval < 0) + return -EINVAL; + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + device_fw_id = rmi4_data->firmware_id; + retval = fwu_get_image_firmware_id(&image_fw_id); + if (retval < 0) + return retval; + if (device_fw_id != image_fw_id) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Device and image firmware IDs don't match\n", + __func__); + return -EINVAL; + } + retval = fwu_check_ui_configuration_size(); + if (retval < 0) + return retval; + break; + case DP_CONFIG_AREA: + if (!fwu->flash_properties.has_disp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Display configuration not supported\n", + __func__); + return -EINVAL; + } + if (!fwu->img.contains_disp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No display configuration in firmware image\n", + __func__); + return -EINVAL; + } + retval = fwu_check_dp_configuration_size(); + if (retval < 0) + return retval; + break; + case PM_CONFIG_AREA: + if (!fwu->flash_properties.has_pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration not supported\n", + __func__); + return -EINVAL; + } + if (!fwu->img.contains_perm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No permanent configuration in firmware image\n", + __func__); + return -EINVAL; + } + retval = fwu_check_pm_configuration_size(); + if (retval < 0) + return retval; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Configuration not supported\n", + __func__); + return -EINVAL; + } + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of write config process\n", __func__); + + config_area = fwu->config_area; + + retval = fwu_enter_flash_prog(); + if (retval < 0) + goto exit; + + fwu->config_area = config_area; + + if (fwu->config_area != PM_CONFIG_AREA) { + retval = fwu_erase_configuration(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to erase config\n", + __func__); + goto exit; + } + } + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + retval = fwu_write_ui_configuration(); + if (retval < 0) + goto exit; + break; + case DP_CONFIG_AREA: + retval = fwu_write_dp_configuration(); + if (retval < 0) + goto exit; + break; + case PM_CONFIG_AREA: + retval = fwu_write_pm_configuration(); + if (retval < 0) + goto exit; + break; + } + + pr_notice("%s: Config written\n", __func__); + +exit: + switch (fwu->config_area) { + case UI_CONFIG_AREA: + rmi4_data->reset_device(rmi4_data, true); + break; + case DP_CONFIG_AREA: + case PM_CONFIG_AREA: + rmi4_data->reset_device(rmi4_data, false); + break; + } + + pr_notice("%s: End of write config process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} +static char tp_info_summary[80] = ""; + +static int fwu_start_reflash(void) +{ + int retval = 0; + enum flash_area flash_area; + bool do_rebuild = false; + const struct firmware *fw_entry = NULL; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + unsigned char config_ver[20] = {0}; + + char tp_temp_info[80]; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of reflash process\n", __func__); + + if (fwu->image == NULL) { + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN, + FW_IMAGE_NAME, sizeof(FW_IMAGE_NAME), + sizeof(FW_IMAGE_NAME)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy image file name\n", + __func__); + goto exit; + } + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Requesting firmware image %s\n", + __func__, fwu->image_name); + + retval = request_firmware(&fw_entry, fwu->image_name, + rmi4_data->pdev->dev.parent); + if (retval != 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Firmware image %s not available\n", + __func__, fwu->image_name); + retval = -EINVAL; + goto exit; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Firmware image size = %d\n", + __func__, (unsigned int)fw_entry->size); + + fwu->image = fw_entry->data; + } + + retval = fwu_parse_image_info(); + if (retval < 0) + goto exit; + + if (fwu->blkcount.total_count != fwu->img.blkcount.total_count) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash size mismatch\n", + __func__); + retval = -EINVAL; + goto exit; + } + + if (fwu->bl_version != fwu->img.bl_version) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Bootloader version mismatch\n", + __func__); + retval = -EINVAL; + goto exit; + } + + retval = fwu_read_flash_status(); + if (retval < 0) + goto exit; + + if (fwu->in_bl_mode) { + fwu->bl_mode_device = true; + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device in bootloader mode\n", + __func__); + } else { + fwu->bl_mode_device = false; + } + + flash_area = fwu_go_nogo(); + + if (flash_area != NONE) { + retval = fwu_enter_flash_prog(); + if (retval < 0) { + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + } + +#ifdef F51_DISCRETE_FORCE + if (flash_area != NONE && !fwu->bl_mode_device) { + fwu->config_size = fwu->block_size * fwu->blkcount.ui_config; + fwu->config_area = UI_CONFIG_AREA; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) { + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + + retval = fwu_read_f34_blocks(fwu->blkcount.ui_config, + CMD_READ_CONFIG); + if (retval < 0) { + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + + retval = secure_memcpy(fwu->cal_data, fwu->cal_data_buf_size, + &fwu->read_config_buf[fwu->cal_data_off], + fwu->cal_data_size, fwu->cal_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to save calibration data\n", + __func__); + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + } +#endif + + switch (flash_area) { + case UI_FIRMWARE: + do_rebuild = true; + retval = fwu_do_reflash(); +#ifdef F51_DISCRETE_FORCE + if (retval < 0) + break; + + if (fwu->has_utility_param || fwu->img.contains_utility_param) + break; + + rmi4_data->reset_device(rmi4_data, false); + + if (fwu->bl_mode_device || fwu->in_bl_mode) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device in bootloader mode, skipping calibration data restoration\n", + __func__); + break; + } + + retval = fwu_do_restore_f51_cal_data(); +#endif + break; + case UI_CONFIG: + do_rebuild = true; + retval = fwu_check_ui_configuration_size(); + if (retval < 0) + break; + fwu->config_area = UI_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + break; + retval = fwu_write_ui_configuration(); +#ifdef F51_DISCRETE_FORCE + if (retval < 0) + break; + + if (fwu->has_utility_param) + break; + + retval = fwu_do_restore_f51_cal_data(); +#endif + break; + case NONE: + default: + break; + } + + if (retval < 0) { + do_rebuild = false; + rmi4_data->reset_device(rmi4_data, false); + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do reflash\n", + __func__); + goto exit; + } + + if (fwu->do_lockdown && (fwu->img.lockdown.data != NULL)) { + switch (fwu->bl_version) { + case BL_V5: + case BL_V6: + retval = fwu_do_lockdown_v5v6(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do lockdown\n", + __func__); + } + rmi4_data->reset_device(rmi4_data, false); + break; + case BL_V7: + case BL_V8: + retval = fwu_do_lockdown_v7(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do lockdown\n", + __func__); + } + rmi4_data->reset_device(rmi4_data, false); + break; + default: + break; + } + } + +exit: + if (fw_entry) + release_firmware(fw_entry); + + if (do_rebuild) + rmi4_data->reset_device(rmi4_data, true); + + pr_notice("%s: End of reflash process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + synaptics_rmi4_reg_read(rmi4_data, + 0x000c, + config_ver, + 1); + printk("config_ver info =%02x\n", config_ver[0]); + + strcpy(tp_info_summary, "[Vendor]O-film, [IC]S3603(synaptics), [FW]Ver"); + sprintf(tp_temp_info, "%02x", config_ver[0]); + strcat(tp_info_summary, tp_temp_info); + strcat(tp_info_summary, "\0"); + + rmi4_data->stay_awake = false; + + return retval; +} + +static int fwu_recovery_check_status(void) +{ + int retval; + unsigned char data_base; + unsigned char status; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f35_fd.data_base_addr; + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + F35_ERROR_CODE_OFFSET, + &status, + 1); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read status\n", + __func__); + return retval; + } + + status = status & MASK_5BIT; + + if (status != 0x00) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Recovery mode status = %d\n", + __func__, status); + return -EINVAL; + } + + return 0; +} + +static int fwu_recovery_erase_completion(void) +{ + int retval; + unsigned char data_base; + unsigned char command; + unsigned char status; + unsigned int timeout = F35_ERASE_ALL_WAIT_MS / 20; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f35_fd.data_base_addr; + + do { + command = 0x01; + retval = synaptics_rmi4_reg_write(rmi4_data, + fwu->f35_fd.cmd_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue command\n", + __func__); + return retval; + } + + do { + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f35_fd.cmd_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read command status\n", + __func__); + return retval; + } + + if ((command & 0x01) == 0x00) + break; + + msleep(20); + timeout--; + } while (timeout > 0); + + if (timeout == 0) + goto exit; + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + F35_FLASH_STATUS_OFFSET, + &status, + sizeof(status)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash status\n", + __func__); + return retval; + } + + if ((status & 0x01) == 0x00) + break; + + msleep(20); + timeout--; + } while (timeout > 0); + +exit: + if (timeout == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for flash erase completion\n", + __func__); + return -ETIMEDOUT; + } + + return 0; +} + +static int fwu_recovery_erase_all(void) +{ + int retval; + unsigned char ctrl_base; + unsigned char command = CMD_F35_ERASE_ALL; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + ctrl_base = fwu->f35_fd.ctrl_base_addr; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_COMMAND_OFFSET, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue erase all command\n", + __func__); + return retval; + } + + if (fwu->f35_fd.cmd_base_addr) { + retval = fwu_recovery_erase_completion(); + if (retval < 0) + return retval; + } else { + msleep(F35_ERASE_ALL_WAIT_MS); + } + + retval = fwu_recovery_check_status(); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_recovery_write_chunk(void) +{ + int retval; + unsigned char ctrl_base; + unsigned char chunk_number[] = {0, 0}; + unsigned char chunk_spare; + unsigned char chunk_size; + unsigned char buf[F35_CHUNK_SIZE + 1]; + unsigned short chunk; + unsigned short chunk_total; + unsigned short bytes_written = 0; + unsigned char *chunk_ptr = (unsigned char *)fwu->image; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + ctrl_base = fwu->f35_fd.ctrl_base_addr; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_NUM_LSB_OFFSET, + chunk_number, + sizeof(chunk_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk number\n", + __func__); + return retval; + } + + buf[sizeof(buf) - 1] = CMD_F35_WRITE_CHUNK; + + chunk_total = fwu->image_size / F35_CHUNK_SIZE; + chunk_spare = fwu->image_size % F35_CHUNK_SIZE; + if (chunk_spare) + chunk_total++; + + for (chunk = 0; chunk < chunk_total; chunk++) { + if (chunk_spare && chunk == chunk_total - 1) + chunk_size = chunk_spare; + else + chunk_size = F35_CHUNK_SIZE; + + memset(buf, 0x00, F35_CHUNK_SIZE); + secure_memcpy(buf, sizeof(buf), chunk_ptr, + fwu->image_size - bytes_written, + chunk_size); + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_DATA_OFFSET, + buf, + sizeof(buf)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk data (chunk %d)\n", + __func__, chunk); + return retval; + } + chunk_ptr += chunk_size; + bytes_written += chunk_size; + } + + retval = fwu_recovery_check_status(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk data\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_recovery_reset(void) +{ + int retval; + unsigned char ctrl_base; + unsigned char command = CMD_F35_RESET; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + ctrl_base = fwu->f35_fd.ctrl_base_addr; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_COMMAND_OFFSET, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + return retval; + } + + msleep(F35_RESET_WAIT_MS); + + return 0; +} + +static int fwu_start_recovery(void) +{ + int retval; + const struct firmware *fw_entry = NULL; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of recovery process\n", __func__); + + if (fwu->image == NULL) { + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN, + FW_IHEX_NAME, sizeof(FW_IHEX_NAME), + sizeof(FW_IHEX_NAME)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy ihex file name\n", + __func__); + goto exit; + } + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Requesting firmware ihex %s\n", + __func__, fwu->image_name); + + retval = request_firmware(&fw_entry, fwu->image_name, + rmi4_data->pdev->dev.parent); + if (retval != 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Firmware ihex %s not available\n", + __func__, fwu->image_name); + retval = -EINVAL; + goto exit; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Firmware image size = %d\n", + __func__, (unsigned int)fw_entry->size); + + fwu->image = fw_entry->data; + fwu->image_size = fw_entry->size; + } + + retval = rmi4_data->irq_enable(rmi4_data, false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to disable interrupt\n", + __func__); + goto exit; + } + + retval = fwu_recovery_erase_all(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do erase all in recovery mode\n", + __func__); + goto exit; + } + + pr_notice("%s: External flash erased\n", __func__); + + retval = fwu_recovery_write_chunk(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk data in recovery mode\n", + __func__); + goto exit; + } + + pr_notice("%s: Chunk data programmed\n", __func__); + + retval = fwu_recovery_reset(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to reset device in recovery mode\n", + __func__); + goto exit; + } + + pr_notice("%s: Recovery mode reset issued\n", __func__); + + rmi4_data->reset_device(rmi4_data, true); + + retval = 0; + +exit: + if (fw_entry) + release_firmware(fw_entry); + + pr_notice("%s: End of recovery process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} + +int synaptics_fw_updater(const unsigned char *fw_data) +{ + int retval; + + if (!fwu) + return -ENODEV; + + if (!fwu->initialized) + return -ENODEV; + + if (fwu->in_ub_mode) { + fwu->image = NULL; + retval = fwu_start_recovery(); + if (retval < 0) + return retval; + } + + fwu->image = fw_data; + + retval = fwu_start_reflash(); + + fwu->image = NULL; + + return retval; +} +EXPORT_SYMBOL(synaptics_fw_updater); + +#ifdef DO_STARTUP_FW_UPDATE +static void fwu_startup_fw_update_work(struct work_struct *work) +{ + static unsigned char do_once = 1; +#ifdef WAIT_FOR_FB_READY + unsigned int timeout; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; +#endif + + + if (!do_once) + return; + do_once = 0; + +#ifdef WAIT_FOR_FB_READY + timeout = FB_READY_TIMEOUT_S * 1000 / FB_READY_WAIT_MS + 1; + + while (!rmi4_data->fb_ready) { + msleep(FB_READY_WAIT_MS); + timeout--; + if (timeout == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for FB ready\n", + __func__); + return; + } + } +#endif + + synaptics_fw_updater(NULL); + + + + return; +} +#endif + +static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (count < fwu->config_size) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not enough space (%d bytes) in buffer\n", + __func__, (unsigned int)count); + retval = -EINVAL; + goto exit; + } + + retval = secure_memcpy(buf, count, fwu->read_config_buf, + fwu->read_config_buf_size, fwu->config_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy config data\n", + __func__); + goto exit; + } else { + retval = fwu->config_size; + } + +exit: + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_store_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = secure_memcpy(&fwu->ext_data_source[fwu->data_pos], + fwu->image_size - fwu->data_pos, buf, count, count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy image data\n", + __func__); + goto exit; + } else { + retval = count; + } + + fwu->data_pos += count; + +exit: + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_do_recovery_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + + } + + if (!fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not in microbootloader mode\n", + __func__); + retval = -EINVAL; + + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + + } else { + fwu->image = fwu->ext_data_source; + } + + retval = fwu_start_recovery(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do recovery\n", + __func__); + + } + + retval = count; + + + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + + } + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + + } else { + fwu->image = fwu->ext_data_source; + } + + if (input & LOCKDOWN) { + fwu->do_lockdown = true; + input &= ~LOCKDOWN; + } + + if ((input != NORMAL) && (input != FORCE)) { + retval = -EINVAL; + + } + + if (input == FORCE) + fwu->force_update = true; + + retval = synaptics_fw_updater(fwu->image); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do reflash\n", + __func__); + + } + + retval = count; + + + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = DO_LOCKDOWN; + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_write_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + goto exit; + } + + if (input != 1) { + retval = -EINVAL; + goto exit; + } + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + goto exit; + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + goto exit; + } else { + fwu->image = fwu->ext_data_source; + } + + retval = fwu_start_write_config(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write config\n", + __func__); + goto exit; + } + + retval = count; + +exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_read_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + goto exit; + } + + retval = fwu_do_read_config(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read config\n", + __func__); + goto exit; + } + + retval = count; + +exit: + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_config_area_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long config_area; + + retval = sstrtoul(buf, 10, &config_area); + if (retval) + return retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + fwu->config_area = config_area; + + mutex_unlock(&fwu_sysfs_mutex); + + return count; +} + +static ssize_t fwu_sysfs_image_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN, + buf, count, count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy image file name\n", + __func__); + } else { + retval = count; + } + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_image_size_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = sstrtoul(buf, 10, &size); + if (retval) + return retval; + +/* if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; +*/ + fwu->image_size = size; + fwu->data_pos = 0; + + kfree(fwu->ext_data_source); + fwu->ext_data_source = kzalloc(fwu->image_size, GFP_KERNEL); + if (!fwu->ext_data_source) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for image data\n", + __func__); + retval = -ENOMEM; + } else { + retval = count; + } + + + + return retval; +} + +static ssize_t fwu_sysfs_block_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->block_size); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.ui_firmware); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.ui_config); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.dp_config); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.pm_config); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.bl_config); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_utility_parameter_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.utility_param); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_guest_code_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.guest_code); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + + +static ssize_t fwu_sysfs_read_guest_serialization_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + fwu_do_read_customer_serialization_data(); + + retval = snprintf(buf, PAGE_SIZE, "%s\n", fwu->read_config_buf); + + return retval; +} + + +static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + goto exit; + } + + if (input != 1) { + retval = -EINVAL; + goto exit; + } + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + goto exit; + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + goto exit; + } else { + fwu->image = fwu->ext_data_source; + } + + retval = fwu_start_write_guest_code(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write guest code\n", + __func__); + goto exit; + } + + retval = count; + +exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +#ifdef SYNA_TDDI +static ssize_t fwu_sysfs_read_lockdown_code_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned short lockdown_data_size; + unsigned char *lockdown_data; + char ld_val[2]; + int retval = 0; + int i = 0; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + lockdown_data_size = fwu->blkcount.tddi_lockdown_data * fwu->block_size; + lockdown_data = kzalloc(lockdown_data_size, GFP_KERNEL); + if (!lockdown_data) { + mutex_unlock(&fwu_sysfs_mutex); + return -ENOMEM; + } + + if (get_tddi_lockdown_data(lockdown_data, lockdown_data_size) < 0) { + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex); + return -EINVAL; + } + + for (i = 0; i < lockdown_data_size; i++) { + retval += snprintf(ld_val, PAGE_SIZE, "%02x", + *(lockdown_data + i)); + strlcat(buf, ld_val, lockdown_data_size); + } + *(buf + retval) = '\n'; + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex); + return retval + 1; +} + +static ssize_t fwu_sysfs_write_lockdown_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned short lockdown_data_size = (count - 1) / 2; + unsigned char *lockdown_data; + unsigned char temp[2]; + int ld_val; + int i = 0; + + for (i = 0; i < (count - 1); i++) { + if (((*buf >= '0') && (*buf <= '9')) || + (('a' < *buf) && (*buf > 'f')) || + (('A' < *buf) && (*buf > 'F'))) + continue; + else + return -EINVAL; + } + + if (count % 2 != 1) + return -EINVAL; + + lockdown_data = kzalloc(lockdown_data_size, GFP_KERNEL); + if (!lockdown_data) + return -ENOMEM; + + for (i = 0; i < lockdown_data_size; i++) { + memcpy(temp, (buf + 2 * i), sizeof(temp)); + if (sscanf(temp, "%02x", &ld_val) == 1) + *(lockdown_data + i) = ld_val & 0xff; + } + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (set_tddi_lockdown_data(lockdown_data, lockdown_data_size) < 0) { + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex); + return -EINVAL; + } + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex); + return count; +} +#endif +static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!fwu) + return; + + if (fwu->intr_mask & intr_mask) + fwu_read_flash_status(); + + return; +} + +static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char attr_count; + struct pdt_properties pdt_props; + +#if defined(SYNAPTICS_LOCK_DOWN_INFO) + unsigned char lockdown[20] = {0}; +#endif + if (fwu) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + fwu = kzalloc(sizeof(*fwu), GFP_KERNEL); + if (!fwu) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + fwu->image_name = kzalloc(MAX_IMAGE_NAME_LEN, GFP_KERNEL); + if (!fwu->image_name) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for image name\n", + __func__); + retval = -ENOMEM; + goto exit_free_fwu; + } + + fwu->rmi4_data = rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + PDT_PROPS, + pdt_props.data, + sizeof(pdt_props.data)); + if (retval < 0) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Failed to read PDT properties, assuming 0x00\n", + __func__); + } else if (pdt_props.has_bsr) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Reflash for LTS not currently supported\n", + __func__); + retval = -ENODEV; + goto exit_free_mem; + } + + retval = fwu_scan_pdt(); + if (retval < 0) + goto exit_free_mem; + + if (!fwu->in_ub_mode) { + retval = fwu_read_f34_queries(); + if (retval < 0) + goto exit_free_mem; + + retval = fwu_get_device_config_id(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device config ID\n", + __func__); + goto exit_free_mem; + } + } + + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = DO_LOCKDOWN; + fwu->initialized = true; + +#ifdef DO_STARTUP_FW_UPDATE + +#ifdef SYNAPTICS_ESD_CHECK + cancel_delayed_work_sync(&(rmi4_data->esd_work)); +#endif + + fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue"); + INIT_WORK(&fwu->fwu_work, fwu_startup_fw_update_work); + queue_work(fwu->fwu_workqueue, + &fwu->fwu_work); + + #ifdef SYNAPTICS_ESD_CHECK + printk("SYNAPTICS_ESD_CHECK is on\n"); + queue_delayed_work(rmi4_data->esd_workqueue, &(rmi4_data->esd_work), SYNAPTICS_ESD_CHECK_CIRCLE); +#endif +#endif + +printk("before get_tddi_lockdown_data"); + + if (get_tddi_lockdown_data(lockdown, 20) < 0) { + printk("read lockdown fail\n"); + } + printk("lockdown info =%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x\n", lockdown[4], lockdown[5], lockdown[6], lockdown[7], lockdown[8], lockdown[9], lockdown[10], lockdown[11]); + + sprintf(tp_lockdown_info, "%02x%02x%02x%02x%02x%02x%02x%02x\n", lockdown[4], lockdown[5], lockdown[6], lockdown[7], lockdown[8], lockdown[9], lockdown[10], lockdown[11]); + + ctp_lockdown_status_proc = proc_create(CTP_PROC_LOCKDOWN_FILE, 0644, NULL, &ctp_lockdown_proc_fops); + if (ctp_lockdown_status_proc == NULL) { + printk("tpd, create_proc_entry ctp_lockdown_status_proc failed\n"); + } + + +#ifdef F51_DISCRETE_FORCE + fwu_read_flash_status(); + if (!fwu->in_bl_mode) { + retval = fwu_f51_force_data_init(); + if (retval < 0) + goto exit_free_mem; + } +#endif + + if (ENABLE_SYS_REFLASH == false) + return 0; + + retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj, + &dev_attr_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs bin file\n", + __func__); + goto exit_free_mem; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + retval = -ENODEV; + goto exit_remove_attrs; + } + } + + return 0; + +exit_remove_attrs: + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); + +exit_free_mem: + kfree(fwu->image_name); + +exit_free_fwu: + kfree(fwu); + fwu = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char attr_count; + + if (!fwu) + goto exit; + +#ifdef DO_STARTUP_FW_UPDATE + cancel_work_sync(&fwu->fwu_work); + flush_workqueue(fwu->fwu_workqueue); + destroy_workqueue(fwu->fwu_workqueue); +#endif + +#ifdef F51_DISCRETE_FORCE + kfree(fwu->cal_data); +#endif + kfree(fwu->read_config_buf); + kfree(fwu->image_name); + kfree(fwu); + fwu = NULL; + + if (ENABLE_SYS_REFLASH == false) + goto exit; + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); + +exit: + complete(&fwu_remove_complete); + + return; +} + +static void synaptics_rmi4_fwu_reset(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + + if (!fwu) { + synaptics_rmi4_fwu_init(rmi4_data); + return; + } + + retval = fwu_scan_pdt(); + if (retval < 0) + return; + + if (!fwu->in_ub_mode) + fwu_read_f34_queries(); + +#ifdef F51_DISCRETE_FORCE + fwu_read_flash_status(); + if (!fwu->in_bl_mode) + fwu_f51_force_data_init(); +#endif + + return; +} + +static struct synaptics_rmi4_exp_fn fwu_module = { + .fn_type = RMI_FW_UPDATER, + .init = synaptics_rmi4_fwu_init, + .remove = synaptics_rmi4_fwu_remove, + .reset = synaptics_rmi4_fwu_reset, + .reinit = NULL, + .early_suspend = NULL, + .suspend = NULL, + .resume = NULL, + .late_resume = NULL, + .attn = synaptics_rmi4_fwu_attn, +}; + +static int __init rmi4_fw_update_module_init(void) +{ + synaptics_rmi4_new_function(&fwu_module, true); + + return 0; +} + +static void __exit rmi4_fw_update_module_exit(void) +{ + synaptics_rmi4_new_function(&fwu_module, false); + + wait_for_completion(&fwu_remove_complete); + + return; +} + +module_init(rmi4_fw_update_module_init); +module_exit(rmi4_fw_update_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX FW Update Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310/Kconfig b/drivers/input/touchscreen/td4310/Kconfig new file mode 100644 index 0000000000000..b2fa11501269d --- /dev/null +++ b/drivers/input/touchscreen/td4310/Kconfig @@ -0,0 +1,128 @@ +# +# Synaptics DSX touchscreen driver configuration +# +menuconfig TOUCHSCREEN_SYNAPTICS_DSX + bool "Synaptics DSX touchscreen" + default y + help + Say Y here if you have a Synaptics DSX touchscreen connected + to your system. + + If unsure, say N. + +if TOUCHSCREEN_SYNAPTICS_DSX + +choice + default TOUCHSCREEN_SYNAPTICS_DSX_I2C + prompt "Synaptics DSX bus interface" +config TOUCHSCREEN_SYNAPTICS_DSX_I2C + bool "RMI over I2C" + depends on I2C +config TOUCHSCREEN_SYNAPTICS_DSX_SPI + bool "RMI over SPI" + depends on SPI_MASTER +config TOUCHSCREEN_SYNAPTICS_DSX_RMI_HID_I2C + bool "HID over I2C" + depends on I2C +endchoice + +config TOUCHSCREEN_SYNAPTICS_DSX_CORE + tristate "Synaptics DSX core driver module" + depends on I2C || SPI_MASTER + help + Say Y here to enable basic touch reporting functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_core. + +config TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV + tristate "Synaptics DSX RMI device module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for direct RMI register access. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_rmi_dev. + +config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE + tristate "Synaptics DSX firmware update module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for doing firmware update. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_fw_update. + +config TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING + tristate "Synaptics DSX test reporting module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for retrieving production test reports. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_test_reporting. + +config TOUCHSCREEN_SYNAPTICS_DSX_PROXIMITY + tristate "Synaptics DSX proximity module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for proximity functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_proximity. + +config TOUCHSCREEN_SYNAPTICS_DSX_ACTIVE_PEN + tristate "Synaptics DSX active pen module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for active pen functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_active_pen. + +config TOUCHSCREEN_SYNAPTICS_DSX_GESTURE + tristate "Synaptics DSX user defined gesture module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for user defined gesture functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_gesture. + +config TOUCHSCREEN_SYNAPTICS_DSX_VIDEO + tristate "Synaptics DSX video module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for video communication functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_video. + +config TOUCHSCREEN_SYNAPTICS_DSX_DEBUG + tristate "Synaptics DSX debug module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for firmware debug functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_debug. + +endif diff --git a/drivers/input/touchscreen/td4310/Makefile b/drivers/input/touchscreen/td4310/Makefile new file mode 100644 index 0000000000000..8dd29916f673c --- /dev/null +++ b/drivers/input/touchscreen/td4310/Makefile @@ -0,0 +1,18 @@ +# +# Makefile for the Synaptics DSX touchscreen driver. +# + +# Each configuration option enables a list of files. + +obj-$(CONFIG_TOUCHSCREEN_TD4310) += synaptics_dsx_i2c.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_SPI) += synaptics_dsx_spi.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_HID_I2C) += synaptics_dsx_rmi_hid_i2c.o +obj-$(CONFIG_TOUCHSCREEN_TD4310) += synaptics_dsx_core.o +obj-$(CONFIG_TOUCHSCREEN_TD4310) += synaptics_dsx_rmi_dev.o +obj-$(CONFIG_TOUCHSCREEN_TD4310) += synaptics_dsx_fw_update.o +obj-$(CONFIG_TOUCHSCREEN_TD4310) += synaptics_dsx_test_reporting.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_PROXIMITY) += synaptics_dsx_proximity.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_ACTIVE_PEN) += synaptics_dsx_active_pen.o +#obj-$(CONFIG_TOUCHSCREEN_TD4310) += synaptics_dsx_gesture.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_VIDEO) += synaptics_dsx_video.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_DEBUG) += synaptics_dsx_debug.o diff --git a/drivers/input/touchscreen/td4310/synaptics_dsx_active_pen.c b/drivers/input/touchscreen/td4310/synaptics_dsx_active_pen.c new file mode 100644 index 0000000000000..fc0d8d6bc556c --- /dev/null +++ b/drivers/input/touchscreen/td4310/synaptics_dsx_active_pen.c @@ -0,0 +1,624 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define APEN_PHYS_NAME "synaptics_dsx/active_pen" + +#define ACTIVE_PEN_MAX_PRESSURE_16BIT 65535 +#define ACTIVE_PEN_MAX_PRESSURE_8BIT 255 + +struct synaptics_rmi4_f12_query_8 { + union { + struct { + unsigned char size_of_query9; + struct { + unsigned char data0_is_present:1; + unsigned char data1_is_present:1; + unsigned char data2_is_present:1; + unsigned char data3_is_present:1; + unsigned char data4_is_present:1; + unsigned char data5_is_present:1; + unsigned char data6_is_present:1; + unsigned char data7_is_present:1; + } __packed; + }; + unsigned char data[2]; + }; +}; + +struct apen_data_8b_pressure { + union { + struct { + unsigned char status_pen:1; + unsigned char status_invert:1; + unsigned char status_barrel:1; + unsigned char status_reserved:5; + unsigned char x_lsb; + unsigned char x_msb; + unsigned char y_lsb; + unsigned char y_msb; + unsigned char pressure_msb; + unsigned char battery_state; + unsigned char pen_id_0_7; + unsigned char pen_id_8_15; + unsigned char pen_id_16_23; + unsigned char pen_id_24_31; + } __packed; + unsigned char data[11]; + }; +}; + +struct apen_data { + union { + struct { + unsigned char status_pen:1; + unsigned char status_invert:1; + unsigned char status_barrel:1; + unsigned char status_reserved:5; + unsigned char x_lsb; + unsigned char x_msb; + unsigned char y_lsb; + unsigned char y_msb; + unsigned char pressure_lsb; + unsigned char pressure_msb; + unsigned char battery_state; + unsigned char pen_id_0_7; + unsigned char pen_id_8_15; + unsigned char pen_id_16_23; + unsigned char pen_id_24_31; + } __packed; + unsigned char data[12]; + }; +}; + +struct synaptics_rmi4_apen_handle { + bool apen_present; + unsigned char intr_mask; + unsigned char battery_state; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; + unsigned short apen_data_addr; + unsigned short max_pressure; + unsigned int pen_id; + struct input_dev *apen_dev; + struct apen_data *apen_data; + struct synaptics_rmi4_data *rmi4_data; +}; + +static struct synaptics_rmi4_apen_handle *apen; + +DECLARE_COMPLETION(apen_remove_complete); + +static void apen_lift(void) +{ + input_report_key(apen->apen_dev, BTN_TOUCH, 0); + input_report_key(apen->apen_dev, BTN_TOOL_PEN, 0); + input_report_key(apen->apen_dev, BTN_TOOL_RUBBER, 0); + input_sync(apen->apen_dev); + apen->apen_present = false; + + return; +} + +static void apen_report(void) +{ + int retval; + int x; + int y; + int pressure; + static int invert = -1; + struct apen_data_8b_pressure *apen_data_8b; + struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + apen->apen_data_addr, + apen->apen_data->data, + sizeof(apen->apen_data->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read active pen data\n", + __func__); + return; + } + + if (apen->apen_data->status_pen == 0) { + if (apen->apen_present) + apen_lift(); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: No active pen data\n", + __func__); + + return; + } + + x = (apen->apen_data->x_msb << 8) | (apen->apen_data->x_lsb); + y = (apen->apen_data->y_msb << 8) | (apen->apen_data->y_lsb); + + if ((x == -1) && (y == -1)) { + if (apen->apen_present) + apen_lift(); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Active pen in range but no valid x & y\n", + __func__); + + return; + } + + if (!apen->apen_present) + invert = -1; + + if (invert != -1 && invert != apen->apen_data->status_invert) + apen_lift(); + + invert = apen->apen_data->status_invert; + + if (apen->max_pressure == ACTIVE_PEN_MAX_PRESSURE_16BIT) { + pressure = (apen->apen_data->pressure_msb << 8) | + apen->apen_data->pressure_lsb; + apen->battery_state = apen->apen_data->battery_state; + apen->pen_id = (apen->apen_data->pen_id_24_31 << 24) | + (apen->apen_data->pen_id_16_23 << 16) | + (apen->apen_data->pen_id_8_15 << 8) | + apen->apen_data->pen_id_0_7; + } else { + apen_data_8b = (struct apen_data_8b_pressure *)apen->apen_data; + pressure = apen_data_8b->pressure_msb; + apen->battery_state = apen_data_8b->battery_state; + apen->pen_id = (apen_data_8b->pen_id_24_31 << 24) | + (apen_data_8b->pen_id_16_23 << 16) | + (apen_data_8b->pen_id_8_15 << 8) | + apen_data_8b->pen_id_0_7; + } + + input_report_key(apen->apen_dev, BTN_TOUCH, pressure > 0 ? 1 : 0); + input_report_key(apen->apen_dev, + apen->apen_data->status_invert > 0 ? + BTN_TOOL_RUBBER : BTN_TOOL_PEN, 1); + input_report_key(apen->apen_dev, + BTN_STYLUS, apen->apen_data->status_barrel > 0 ? + 1 : 0); + input_report_abs(apen->apen_dev, ABS_X, x); + input_report_abs(apen->apen_dev, ABS_Y, y); + input_report_abs(apen->apen_dev, ABS_PRESSURE, pressure); + + input_sync(apen->apen_dev); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Active pen: status = %d, invert = %d, barrel = %d, x = %d, y = %d, pressure = %d\n", + __func__, + apen->apen_data->status_pen, + apen->apen_data->status_invert, + apen->apen_data->status_barrel, + x, y, pressure); + + apen->apen_present = true; + + return; +} + +static void apen_set_params(void) +{ + input_set_abs_params(apen->apen_dev, ABS_X, 0, + apen->rmi4_data->sensor_max_x, 0, 0); + input_set_abs_params(apen->apen_dev, ABS_Y, 0, + apen->rmi4_data->sensor_max_y, 0, 0); + input_set_abs_params(apen->apen_dev, ABS_PRESSURE, 0, + apen->max_pressure, 0, 0); + + return; +} + +static int apen_pressure(struct synaptics_rmi4_f12_query_8 *query_8) +{ + int retval; + unsigned char ii; + unsigned char data_reg_presence; + unsigned char size_of_query_9; + unsigned char *query_9; + unsigned char *data_desc; + struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data; + + data_reg_presence = query_8->data[1]; + + size_of_query_9 = query_8->size_of_query9; + query_9 = kmalloc(size_of_query_9, GFP_KERNEL); + + retval = synaptics_rmi4_reg_read(rmi4_data, + apen->query_base_addr + 9, + query_9, + size_of_query_9); + if (retval < 0) + goto exit; + + data_desc = query_9; + + for (ii = 0; ii < 6; ii++) { + if (!(data_reg_presence & (1 << ii))) + continue; /* The data register is not present */ + data_desc++; /* Jump over the size entry */ + while (*data_desc & (1 << 7)) + data_desc++; + data_desc++; /* Go to the next descriptor */ + } + + data_desc++; /* Jump over the size entry */ + /* Check for the presence of subpackets 1 and 2 */ + if ((*data_desc & (3 << 1)) == (3 << 1)) + apen->max_pressure = ACTIVE_PEN_MAX_PRESSURE_16BIT; + else + apen->max_pressure = ACTIVE_PEN_MAX_PRESSURE_8BIT; + +exit: + kfree(query_9); + + return retval; +} + +static int apen_reg_init(void) +{ + int retval; + unsigned char data_offset; + unsigned char size_of_query8; + struct synaptics_rmi4_f12_query_8 query_8; + struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + apen->query_base_addr + 7, + &size_of_query8, + sizeof(size_of_query8)); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_read(rmi4_data, + apen->query_base_addr + 8, + query_8.data, + sizeof(query_8.data)); + if (retval < 0) + return retval; + + if ((size_of_query8 >= 2) && (query_8.data6_is_present)) { + data_offset = query_8.data0_is_present + + query_8.data1_is_present + + query_8.data2_is_present + + query_8.data3_is_present + + query_8.data4_is_present + + query_8.data5_is_present; + apen->apen_data_addr = apen->data_base_addr + data_offset; + retval = apen_pressure(&query_8); + if (retval < 0) + return retval; + } else { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Active pen support unavailable\n", + __func__); + retval = -ENODEV; + } + + return retval; +} + +static int apen_scan_pdt(void) +{ + int retval; + unsigned char ii; + unsigned char page; + unsigned char intr_count = 0; + unsigned char intr_off; + unsigned char intr_src; + unsigned short addr; + struct synaptics_rmi4_fn_desc fd; + struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data; + + for (page = 0; page < PAGES_TO_SERVICE; page++) { + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + addr |= (page << 8); + + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&fd, + sizeof(fd)); + if (retval < 0) + return retval; + + addr &= ~(MASK_8BIT << 8); + + if (fd.fn_number) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Found F%02x\n", + __func__, fd.fn_number); + switch (fd.fn_number) { + case SYNAPTICS_RMI4_F12: + goto f12_found; + break; + } + } else { + break; + } + + intr_count += fd.intr_src_count; + } + } + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F12\n", + __func__); + return -EINVAL; + +f12_found: + apen->query_base_addr = fd.query_base_addr | (page << 8); + apen->control_base_addr = fd.ctrl_base_addr | (page << 8); + apen->data_base_addr = fd.data_base_addr | (page << 8); + apen->command_base_addr = fd.cmd_base_addr | (page << 8); + + retval = apen_reg_init(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to initialize active pen registers\n", + __func__); + return retval; + } + + apen->intr_mask = 0; + intr_src = fd.intr_src_count; + intr_off = intr_count % 8; + for (ii = intr_off; + ii < (intr_src + intr_off); + ii++) { + apen->intr_mask |= 1 << ii; + } + + rmi4_data->intr_mask[0] |= apen->intr_mask; + + addr = rmi4_data->f01_ctrl_base_addr + 1; + + retval = synaptics_rmi4_reg_write(rmi4_data, + addr, + &(rmi4_data->intr_mask[0]), + sizeof(rmi4_data->intr_mask[0])); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set interrupt enable bit\n", + __func__); + return retval; + } + + return 0; +} + +static void synaptics_rmi4_apen_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!apen) + return; + + if (apen->intr_mask & intr_mask) + apen_report(); + + return; +} + +static int synaptics_rmi4_apen_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + + if (apen) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + apen = kzalloc(sizeof(*apen), GFP_KERNEL); + if (!apen) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for apen\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + apen->apen_data = kzalloc(sizeof(*(apen->apen_data)), GFP_KERNEL); + if (!apen->apen_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for apen_data\n", + __func__); + retval = -ENOMEM; + goto exit_free_apen; + } + + apen->rmi4_data = rmi4_data; + + retval = apen_scan_pdt(); + if (retval < 0) + goto exit_free_apen_data; + + apen->apen_dev = input_allocate_device(); + if (apen->apen_dev == NULL) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate active pen device\n", + __func__); + retval = -ENOMEM; + goto exit_free_apen_data; + } + + apen->apen_dev->name = ACTIVE_PEN_DRIVER_NAME; + apen->apen_dev->phys = APEN_PHYS_NAME; + apen->apen_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT; + apen->apen_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION; + apen->apen_dev->dev.parent = rmi4_data->pdev->dev.parent; + input_set_drvdata(apen->apen_dev, rmi4_data); + + set_bit(EV_KEY, apen->apen_dev->evbit); + set_bit(EV_ABS, apen->apen_dev->evbit); + set_bit(BTN_TOUCH, apen->apen_dev->keybit); + set_bit(BTN_TOOL_PEN, apen->apen_dev->keybit); + set_bit(BTN_TOOL_RUBBER, apen->apen_dev->keybit); + set_bit(BTN_STYLUS, apen->apen_dev->keybit); +#ifdef INPUT_PROP_DIRECT + set_bit(INPUT_PROP_DIRECT, apen->apen_dev->propbit); +#endif + + apen_set_params(); + + retval = input_register_device(apen->apen_dev); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to register active pen device\n", + __func__); + goto exit_free_input_device; + } + + return 0; + +exit_free_input_device: + input_free_device(apen->apen_dev); + +exit_free_apen_data: + kfree(apen->apen_data); + +exit_free_apen: + kfree(apen); + apen = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_apen_remove(struct synaptics_rmi4_data *rmi4_data) +{ + if (!apen) + goto exit; + + input_unregister_device(apen->apen_dev); + kfree(apen->apen_data); + kfree(apen); + apen = NULL; + +exit: + complete(&apen_remove_complete); + + return; +} + +static void synaptics_rmi4_apen_reset(struct synaptics_rmi4_data *rmi4_data) +{ + if (!apen) { + synaptics_rmi4_apen_init(rmi4_data); + return; + } + + apen_lift(); + + apen_scan_pdt(); + + return; +} + +static void synaptics_rmi4_apen_reinit(struct synaptics_rmi4_data *rmi4_data) +{ + if (!apen) + return; + + apen_lift(); + + return; +} + +static void synaptics_rmi4_apen_e_suspend(struct synaptics_rmi4_data *rmi4_data) +{ + if (!apen) + return; + + apen_lift(); + + return; +} + +static void synaptics_rmi4_apen_suspend(struct synaptics_rmi4_data *rmi4_data) +{ + if (!apen) + return; + + apen_lift(); + + return; +} + +static struct synaptics_rmi4_exp_fn active_pen_module = { + .fn_type = RMI_ACTIVE_PEN, + .init = synaptics_rmi4_apen_init, + .remove = synaptics_rmi4_apen_remove, + .reset = synaptics_rmi4_apen_reset, + .reinit = synaptics_rmi4_apen_reinit, + .early_suspend = synaptics_rmi4_apen_e_suspend, + .suspend = synaptics_rmi4_apen_suspend, + .resume = NULL, + .late_resume = NULL, + .attn = synaptics_rmi4_apen_attn, +}; + +static int __init rmi4_active_pen_module_init(void) +{ + synaptics_rmi4_new_function(&active_pen_module, true); + + return 0; +} + +static void __exit rmi4_active_pen_module_exit(void) +{ + synaptics_rmi4_new_function(&active_pen_module, false); + + wait_for_completion(&apen_remove_complete); + + return; +} + +module_init(rmi4_active_pen_module_init); +module_exit(rmi4_active_pen_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX Active Pen Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310/synaptics_dsx_core.c b/drivers/input/touchscreen/td4310/synaptics_dsx_core.c new file mode 100644 index 0000000000000..81aba2c7d237a --- /dev/null +++ b/drivers/input/touchscreen/td4310/synaptics_dsx_core.c @@ -0,0 +1,4885 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" +#include +#include + +#ifdef KERNEL_ABOVE_2_6_38 +#include +#endif + +#define INPUT_PHYS_NAME "synaptics_dsx/touch_input" +#define STYLUS_PHYS_NAME "synaptics_dsx/stylus" + +#define VIRTUAL_KEY_MAP_FILE_NAME "virtualkeys." PLATFORM_DRIVER_NAME + +#ifdef KERNEL_ABOVE_2_6_38 +#define TYPE_B_PROTOCOL +#endif + +/* +#define USE_DATA_SERVER +*/ + +#define WAKEUP_GESTURE true + +#define NO_0D_WHILE_2D +#define REPORT_2D_Z +#define REPORT_2D_W +/* +#define REPORT_2D_PRESSURE +*/ + +#define F12_DATA_15_WORKAROUND + +#define IGNORE_FN_INIT_FAILURE +/* +#define FB_READY_RESET +#define FB_READY_WAIT_MS 100 +#define FB_READY_TIMEOUT_S 30 +*/ +#ifdef SYNA_TDDI +#define TDDI_LPWG_WAIT_US 10 +#endif +#define RPT_TYPE (1 << 0) +#define RPT_X_LSB (1 << 1) +#define RPT_X_MSB (1 << 2) +#define RPT_Y_LSB (1 << 3) +#define RPT_Y_MSB (1 << 4) +#define RPT_Z (1 << 5) +#define RPT_WX (1 << 6) +#define RPT_WY (1 << 7) +#define RPT_DEFAULT (RPT_TYPE | RPT_X_LSB | RPT_X_MSB | RPT_Y_LSB | RPT_Y_MSB) + +#define REBUILD_WORK_DELAY_MS 500 /* ms */ + +#define EXP_FN_WORK_DELAY_MS 500 /* ms */ +#define MAX_F11_TOUCH_WIDTH 15 +#define MAX_F12_TOUCH_WIDTH 255 + +#define CHECK_STATUS_TIMEOUT_MS 100 + +#define F01_STD_QUERY_LEN 21 +#define F01_BUID_ID_OFFSET 18 + +#define STATUS_NO_ERROR 0x00 +#define STATUS_RESET_OCCURRED 0x01 +#define STATUS_INVALID_CONFIG 0x02 +#define STATUS_DEVICE_FAILURE 0x03 +#define STATUS_CONFIG_CRC_FAILURE 0x04 +#define STATUS_FIRMWARE_CRC_FAILURE 0x05 +#define STATUS_CRC_IN_PROGRESS 0x06 + +#define NORMAL_OPERATION (0 << 0) +#define SENSOR_SLEEP (1 << 0) +#define NO_SLEEP_OFF (0 << 2) +#define NO_SLEEP_ON (1 << 2) +#define CONFIGURED (1 << 7) + +#define F11_CONTINUOUS_MODE 0x00 +#define F11_WAKEUP_GESTURE_MODE 0x04 +#define F12_CONTINUOUS_MODE 0x00 +#define F12_WAKEUP_GESTURE_MODE 0x02 +#define F12_UDG_DETECT 0x0f + +struct synaptics_rmi4_data *rmi4_data; + +#if 1 +bool synaptics_gesture_func_on = true; +#define WAKEUP_OFF 4 +#define WAKEUP_ON 5 + +int synaptics_gesture_switch(struct input_dev *dev, unsigned int type, unsigned int code, int value) +{ + + unsigned int input ; + if (type == EV_SYN && code == SYN_CONFIG) { + if (value == WAKEUP_OFF) { + synaptics_gesture_func_on = false; + input = 0; + } else if (value == WAKEUP_ON) { + synaptics_gesture_func_on = true; + input = 1; + } + } + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture) + rmi4_data->enable_wakeup_gesture = input; + + return 0; +} +#endif + + +extern int get_tddi_lockdown_data(unsigned char *lockdown_data, unsigned short leng); + +static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data, + bool *was_in_bl_mode); +static int synaptics_rmi4_free_fingers(struct synaptics_rmi4_data *rmi4_data); +static int synaptics_rmi4_reinit_device(struct synaptics_rmi4_data *rmi4_data); +static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data, + bool rebuild); + +#ifdef SYNAPTICS_ESD_CHECK +#define SYNAPTICS_ESD_CHECK_CIRCLE 2*HZ +void synaptics_rmi4_esd_work(struct work_struct *work); +#if 1 +#define SYNAPTICS_ESD_CHECK_RETRY_TIME 5 +int touch_event_flag; +int fw_update_flag; + + + + +#endif +#endif + + +#ifdef CONFIG_FB +static int synaptics_rmi4_fb_notifier_cb(struct notifier_block *self, + unsigned long event, void *data); +#endif + +#ifdef CONFIG_HAS_EARLYSUSPEND +#ifndef CONFIG_FB +#define USE_EARLYSUSPEND +#endif +#endif + +#ifdef USE_EARLYSUSPEND +static void synaptics_rmi4_early_suspend(struct early_suspend *h); + +static void synaptics_rmi4_late_resume(struct early_suspend *h); +#endif + +static int synaptics_rmi4_suspend(struct device *dev); + +static int synaptics_rmi4_resume(struct device *dev); + +static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t synaptics_rmi4_suspend_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t synaptics_rmi4_wake_gesture_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_wake_gesture_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +#ifdef USE_DATA_SERVER +static ssize_t synaptics_rmi4_synad_pid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); +#endif + +static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf); + +struct synaptics_rmi4_f01_device_status { + union { + struct { + unsigned char status_code:4; + unsigned char reserved:2; + unsigned char flash_prog:1; + unsigned char unconfigured:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f11_query_0_5 { + union { + struct { + /* query 0 */ + unsigned char f11_query0_b0__2:3; + unsigned char has_query_9:1; + unsigned char has_query_11:1; + unsigned char has_query_12:1; + unsigned char has_query_27:1; + unsigned char has_query_28:1; + + /* query 1 */ + unsigned char num_of_fingers:3; + unsigned char has_rel:1; + unsigned char has_abs:1; + unsigned char has_gestures:1; + unsigned char has_sensitibity_adjust:1; + unsigned char f11_query1_b7:1; + + /* query 2 */ + unsigned char num_of_x_electrodes; + + /* query 3 */ + unsigned char num_of_y_electrodes; + + /* query 4 */ + unsigned char max_electrodes:7; + unsigned char f11_query4_b7:1; + + /* query 5 */ + unsigned char abs_data_size:2; + unsigned char has_anchored_finger:1; + unsigned char has_adj_hyst:1; + unsigned char has_dribble:1; + unsigned char has_bending_correction:1; + unsigned char has_large_object_suppression:1; + unsigned char has_jitter_filter:1; + } __packed; + unsigned char data[6]; + }; +}; + +struct synaptics_rmi4_f11_query_7_8 { + union { + struct { + /* query 7 */ + unsigned char has_single_tap:1; + unsigned char has_tap_and_hold:1; + unsigned char has_double_tap:1; + unsigned char has_early_tap:1; + unsigned char has_flick:1; + unsigned char has_press:1; + unsigned char has_pinch:1; + unsigned char has_chiral_scroll:1; + + /* query 8 */ + unsigned char has_palm_detect:1; + unsigned char has_rotate:1; + unsigned char has_touch_shapes:1; + unsigned char has_scroll_zones:1; + unsigned char individual_scroll_zones:1; + unsigned char has_multi_finger_scroll:1; + unsigned char has_multi_finger_scroll_edge_motion:1; + unsigned char has_multi_finger_scroll_inertia:1; + } __packed; + unsigned char data[2]; + }; +}; + +struct synaptics_rmi4_f11_query_9 { + union { + struct { + unsigned char has_pen:1; + unsigned char has_proximity:1; + unsigned char has_large_object_sensitivity:1; + unsigned char has_suppress_on_large_object_detect:1; + unsigned char has_two_pen_thresholds:1; + unsigned char has_contact_geometry:1; + unsigned char has_pen_hover_discrimination:1; + unsigned char has_pen_hover_and_edge_filters:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f11_query_12 { + union { + struct { + unsigned char has_small_object_detection:1; + unsigned char has_small_object_detection_tuning:1; + unsigned char has_8bit_w:1; + unsigned char has_2d_adjustable_mapping:1; + unsigned char has_general_information_2:1; + unsigned char has_physical_properties:1; + unsigned char has_finger_limit:1; + unsigned char has_linear_cofficient_2:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f11_query_27 { + union { + struct { + unsigned char f11_query27_b0:1; + unsigned char has_pen_position_correction:1; + unsigned char has_pen_jitter_filter_coefficient:1; + unsigned char has_group_decomposition:1; + unsigned char has_wakeup_gesture:1; + unsigned char has_small_finger_correction:1; + unsigned char has_data_37:1; + unsigned char f11_query27_b7:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f11_ctrl_6_9 { + union { + struct { + unsigned char sensor_max_x_pos_7_0; + unsigned char sensor_max_x_pos_11_8:4; + unsigned char f11_ctrl7_b4__7:4; + unsigned char sensor_max_y_pos_7_0; + unsigned char sensor_max_y_pos_11_8:4; + unsigned char f11_ctrl9_b4__7:4; + } __packed; + unsigned char data[4]; + }; +}; + +struct synaptics_rmi4_f11_data_1_5 { + union { + struct { + unsigned char x_position_11_4; + unsigned char y_position_11_4; + unsigned char x_position_3_0:4; + unsigned char y_position_3_0:4; + unsigned char wx:4; + unsigned char wy:4; + unsigned char z; + } __packed; + unsigned char data[5]; + }; +}; + +struct synaptics_rmi4_f12_query_5 { + union { + struct { + unsigned char size_of_query6; + struct { + unsigned char ctrl0_is_present:1; + unsigned char ctrl1_is_present:1; + unsigned char ctrl2_is_present:1; + unsigned char ctrl3_is_present:1; + unsigned char ctrl4_is_present:1; + unsigned char ctrl5_is_present:1; + unsigned char ctrl6_is_present:1; + unsigned char ctrl7_is_present:1; + } __packed; + struct { + unsigned char ctrl8_is_present:1; + unsigned char ctrl9_is_present:1; + unsigned char ctrl10_is_present:1; + unsigned char ctrl11_is_present:1; + unsigned char ctrl12_is_present:1; + unsigned char ctrl13_is_present:1; + unsigned char ctrl14_is_present:1; + unsigned char ctrl15_is_present:1; + } __packed; + struct { + unsigned char ctrl16_is_present:1; + unsigned char ctrl17_is_present:1; + unsigned char ctrl18_is_present:1; + unsigned char ctrl19_is_present:1; + unsigned char ctrl20_is_present:1; + unsigned char ctrl21_is_present:1; + unsigned char ctrl22_is_present:1; + unsigned char ctrl23_is_present:1; + } __packed; + struct { + unsigned char ctrl24_is_present:1; + unsigned char ctrl25_is_present:1; + unsigned char ctrl26_is_present:1; + unsigned char ctrl27_is_present:1; + unsigned char ctrl28_is_present:1; + unsigned char ctrl29_is_present:1; + unsigned char ctrl30_is_present:1; + unsigned char ctrl31_is_present:1; + } __packed; + struct { + unsigned char ctrl32_is_present:1; + unsigned char ctrl33_is_present:1; + unsigned char ctrl34_is_present:1; + unsigned char ctrl35_is_present:1; + unsigned char ctrl36_is_present:1; + unsigned char ctrl37_is_present:1; + unsigned char ctrl38_is_present:1; + unsigned char ctrl39_is_present:1; + } __packed; + struct { + unsigned char ctrl40_is_present:1; + unsigned char ctrl41_is_present:1; + unsigned char ctrl42_is_present:1; + unsigned char ctrl43_is_present:1; + unsigned char ctrl44_is_present:1; + unsigned char ctrl45_is_present:1; + unsigned char ctrl46_is_present:1; + unsigned char ctrl47_is_present:1; + } __packed; + struct { + unsigned char ctrl48_is_present:1; + unsigned char ctrl49_is_present:1; + unsigned char ctrl50_is_present:1; + unsigned char ctrl51_is_present:1; + unsigned char ctrl52_is_present:1; + unsigned char ctrl53_is_present:1; + unsigned char ctrl54_is_present:1; + unsigned char ctrl55_is_present:1; + } __packed; + struct { + unsigned char ctrl56_is_present:1; + unsigned char ctrl57_is_present:1; + unsigned char ctrl58_is_present:1; + unsigned char ctrl59_is_present:1; + unsigned char ctrl60_is_present:1; + unsigned char ctrl61_is_present:1; + unsigned char ctrl62_is_present:1; + unsigned char ctrl63_is_present:1; + } __packed; + }; + unsigned char data[9]; + }; +}; + +struct synaptics_rmi4_f12_query_8 { + union { + struct { + unsigned char size_of_query9; + struct { + unsigned char data0_is_present:1; + unsigned char data1_is_present:1; + unsigned char data2_is_present:1; + unsigned char data3_is_present:1; + unsigned char data4_is_present:1; + unsigned char data5_is_present:1; + unsigned char data6_is_present:1; + unsigned char data7_is_present:1; + } __packed; + struct { + unsigned char data8_is_present:1; + unsigned char data9_is_present:1; + unsigned char data10_is_present:1; + unsigned char data11_is_present:1; + unsigned char data12_is_present:1; + unsigned char data13_is_present:1; + unsigned char data14_is_present:1; + unsigned char data15_is_present:1; + } __packed; + struct { + unsigned char data16_is_present:1; + unsigned char data17_is_present:1; + unsigned char data18_is_present:1; + unsigned char data19_is_present:1; + unsigned char data20_is_present:1; + unsigned char data21_is_present:1; + unsigned char data22_is_present:1; + unsigned char data23_is_present:1; + } __packed; + struct { + unsigned char data24_is_present:1; + unsigned char data25_is_present:1; + unsigned char data26_is_present:1; + unsigned char data27_is_present:1; + unsigned char data28_is_present:1; + unsigned char data29_is_present:1; + unsigned char data30_is_present:1; + unsigned char data31_is_present:1; + } __packed; + }; + unsigned char data[5]; + }; +}; + +struct synaptics_rmi4_f12_ctrl_8 { + union { + struct { + unsigned char max_x_coord_lsb; + unsigned char max_x_coord_msb; + unsigned char max_y_coord_lsb; + unsigned char max_y_coord_msb; + unsigned char rx_pitch_lsb; + unsigned char rx_pitch_msb; + unsigned char tx_pitch_lsb; + unsigned char tx_pitch_msb; + unsigned char low_rx_clip; + unsigned char high_rx_clip; + unsigned char low_tx_clip; + unsigned char high_tx_clip; + unsigned char num_of_rx; + unsigned char num_of_tx; + }; + unsigned char data[14]; + }; +}; + +struct synaptics_rmi4_f12_ctrl_23 { + union { + struct { + unsigned char finger_enable:1; + unsigned char active_stylus_enable:1; + unsigned char palm_enable:1; + unsigned char unclassified_object_enable:1; + unsigned char hovering_finger_enable:1; + unsigned char gloved_finger_enable:1; + unsigned char f12_ctr23_00_b6__7:2; + unsigned char max_reported_objects; + unsigned char f12_ctr23_02_b0:1; + unsigned char report_active_stylus_as_finger:1; + unsigned char report_palm_as_finger:1; + unsigned char report_unclassified_object_as_finger:1; + unsigned char report_hovering_finger_as_finger:1; + unsigned char report_gloved_finger_as_finger:1; + unsigned char report_narrow_object_swipe_as_finger:1; + unsigned char report_handedge_as_finger:1; + unsigned char cover_enable:1; + unsigned char stylus_enable:1; + unsigned char eraser_enable:1; + unsigned char small_object_enable:1; + unsigned char f12_ctr23_03_b4__7:4; + unsigned char report_cover_as_finger:1; + unsigned char report_stylus_as_finger:1; + unsigned char report_eraser_as_finger:1; + unsigned char report_small_object_as_finger:1; + unsigned char f12_ctr23_04_b4__7:4; + }; + unsigned char data[5]; + }; +}; + +struct synaptics_rmi4_f12_ctrl_31 { + union { + struct { + unsigned char max_x_coord_lsb; + unsigned char max_x_coord_msb; + unsigned char max_y_coord_lsb; + unsigned char max_y_coord_msb; + unsigned char rx_pitch_lsb; + unsigned char rx_pitch_msb; + unsigned char rx_clip_low; + unsigned char rx_clip_high; + unsigned char wedge_clip_low; + unsigned char wedge_clip_high; + unsigned char num_of_p; + unsigned char num_of_q; + }; + unsigned char data[12]; + }; +}; + +struct synaptics_rmi4_f12_ctrl_58 { + union { + struct { + unsigned char reporting_format; + unsigned char f12_ctr58_00_reserved; + unsigned char min_force_lsb; + unsigned char min_force_msb; + unsigned char max_force_lsb; + unsigned char max_force_msb; + unsigned char light_press_threshold_lsb; + unsigned char light_press_threshold_msb; + unsigned char light_press_hysteresis_lsb; + unsigned char light_press_hysteresis_msb; + unsigned char hard_press_threshold_lsb; + unsigned char hard_press_threshold_msb; + unsigned char hard_press_hysteresis_lsb; + unsigned char hard_press_hysteresis_msb; + }; + unsigned char data[14]; + }; +}; + +struct synaptics_rmi4_f12_finger_data { + unsigned char object_type_and_status; + unsigned char x_lsb; + unsigned char x_msb; + unsigned char y_lsb; + unsigned char y_msb; +#ifdef REPORT_2D_Z + unsigned char z; +#endif +#ifdef REPORT_2D_W + unsigned char wx; + unsigned char wy; +#endif +}; + +struct synaptics_rmi4_f1a_query { + union { + struct { + unsigned char max_button_count:3; + unsigned char f1a_query0_b3__4:2; + unsigned char has_query4:1; + unsigned char has_query3:1; + unsigned char has_query2:1; + unsigned char has_general_control:1; + unsigned char has_interrupt_enable:1; + unsigned char has_multibutton_select:1; + unsigned char has_tx_rx_map:1; + unsigned char has_perbutton_threshold:1; + unsigned char has_release_threshold:1; + unsigned char has_strongestbtn_hysteresis:1; + unsigned char has_filter_strength:1; + } __packed; + unsigned char data[2]; + }; +}; + +struct synaptics_rmi4_f1a_query_4 { + union { + struct { + unsigned char has_ctrl19:1; + unsigned char f1a_query4_b1__4:4; + unsigned char has_ctrl24:1; + unsigned char f1a_query4_b6__7:2; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f1a_control_0 { + union { + struct { + unsigned char multibutton_report:2; + unsigned char filter_mode:2; + unsigned char reserved:4; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f1a_control { + struct synaptics_rmi4_f1a_control_0 general_control; + unsigned char button_int_enable; + unsigned char multi_button; + unsigned char *txrx_map; + unsigned char *button_threshold; + unsigned char button_release_threshold; + unsigned char strongest_button_hysteresis; + unsigned char filter_strength; +}; + +struct synaptics_rmi4_f1a_handle { + int button_bitmask_size; + unsigned char max_count; + unsigned char valid_button_count; + unsigned char *button_data_buffer; + unsigned char *button_map; + struct synaptics_rmi4_f1a_query button_query; + struct synaptics_rmi4_f1a_control button_control; +}; + +struct synaptics_rmi4_exp_fhandler { + struct synaptics_rmi4_exp_fn *exp_fn; + bool insert; + bool remove; + struct list_head link; +}; + +struct synaptics_rmi4_exp_fn_data { + bool initialized; + bool queue_work; + struct mutex mutex; + struct list_head list; + struct delayed_work work; + struct workqueue_struct *workqueue; + struct synaptics_rmi4_data *rmi4_data; +}; + +static struct synaptics_rmi4_exp_fn_data exp_data; + +static struct synaptics_dsx_button_map *vir_button_map; + +#ifdef USE_DATA_SERVER +static pid_t synad_pid; +static struct task_struct *synad_task; +static struct siginfo interrupt_signal; +#endif + +static struct device_attribute attrs[] = { + __ATTR(reset, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + synaptics_rmi4_f01_reset_store), + __ATTR(productinfo, S_IRUGO, + synaptics_rmi4_f01_productinfo_show, + synaptics_rmi4_store_error), + __ATTR(buildid, S_IRUGO, + synaptics_rmi4_f01_buildid_show, + synaptics_rmi4_store_error), + __ATTR(flashprog, S_IRUGO, + synaptics_rmi4_f01_flashprog_show, + synaptics_rmi4_store_error), + __ATTR(0dbutton, (S_IRUGO | S_IWUSR | S_IWGRP), + synaptics_rmi4_0dbutton_show, + synaptics_rmi4_0dbutton_store), + __ATTR(suspend, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + synaptics_rmi4_suspend_store), + __ATTR(wake_gesture, (S_IRUGO | S_IWUSR | S_IWGRP), + synaptics_rmi4_wake_gesture_show, + synaptics_rmi4_wake_gesture_store), +#ifdef USE_DATA_SERVER + __ATTR(synad_pid, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + synaptics_rmi4_synad_pid_store), +#endif +}; + +static struct kobj_attribute virtual_key_map_attr = { + .attr = { + .name = VIRTUAL_KEY_MAP_FILE_NAME, + .mode = S_IRUGO, + }, + .show = synaptics_rmi4_virtual_key_map_show, +}; + +static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int reset; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + if (sscanf(buf, "%u", &reset) != 1) + return -EINVAL; + + if (reset != 1) + return -EINVAL; + + retval = synaptics_rmi4_reset_device(rmi4_data, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command, error = %d\n", + __func__, retval); + return retval; + } + + return count; +} + +static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "0x%02x 0x%02x\n", + (rmi4_data->rmi4_mod_info.product_info[0]), + (rmi4_data->rmi4_mod_info.product_info[1])); +} + +static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", + rmi4_data->firmware_id); +} + +static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + struct synaptics_rmi4_f01_device_status device_status; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + device_status.data, + sizeof(device_status.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device status, error = %d\n", + __func__, retval); + return retval; + } + + return snprintf(buf, PAGE_SIZE, "%u\n", + device_status.flash_prog); +} + +static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", + rmi4_data->button_0d_enabled); +} + +static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + unsigned char ii; + unsigned char intr_enable; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + input = input > 0 ? 1 : 0; + + if (rmi4_data->button_0d_enabled == input) + return count; + + if (list_empty(&rmi->support_fn_list)) + return -ENODEV; + + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) { + ii = fhandler->intr_reg_num; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr + 1 + ii, + &intr_enable, + sizeof(intr_enable)); + if (retval < 0) + return retval; + + if (input == 1) + intr_enable |= fhandler->intr_mask; + else + intr_enable &= ~fhandler->intr_mask; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr + 1 + ii, + &intr_enable, + sizeof(intr_enable)); + if (retval < 0) + return retval; + } + } + + rmi4_data->button_0d_enabled = input; + + return count; +} + +static ssize_t synaptics_rmi4_suspend_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input == 1) + synaptics_rmi4_suspend(dev); + else if (input == 0) + synaptics_rmi4_resume(dev); + else + return -EINVAL; + + return count; +} + +static ssize_t synaptics_rmi4_wake_gesture_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", + rmi4_data->enable_wakeup_gesture); +} + + +static ssize_t synaptics_rmi4_wake_gesture_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + unsigned int input ; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (synaptics_gesture_func_on) + input = input > 0 ? 1 : 0; + else + input = 0; + + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture) + rmi4_data->enable_wakeup_gesture = input; + + return count; +} + +#ifdef USE_DATA_SERVER +static ssize_t synaptics_rmi4_synad_pid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + synad_pid = input; + + if (synad_pid) { + synad_task = pid_task(find_vpid(synad_pid), PIDTYPE_PID); + if (!synad_task) + return -EINVAL; + } + + return count; +} +#endif + +static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int ii; + int cnt; + int count = 0; + + for (ii = 0; ii < vir_button_map->nbuttons; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, "0x01:%d:%d:%d:%d:%d\n", + vir_button_map->map[ii * 5 + 0], + vir_button_map->map[ii * 5 + 1], + vir_button_map->map[ii * 5 + 2], + vir_button_map->map[ii * 5 + 3], + vir_button_map->map[ii * 5 + 4]); + buf += cnt; + count += cnt; + } + + return count; +} + +static void synaptics_rmi4_f11_wg(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval; + unsigned char reporting_control; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F11) + break; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base, + &reporting_control, + sizeof(reporting_control)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to change reporting mode\n", + __func__); + return; + } + + reporting_control = (reporting_control & ~MASK_3BIT); + if (enable) + reporting_control |= F11_WAKEUP_GESTURE_MODE; + else + reporting_control |= F11_CONTINUOUS_MODE; + + retval = synaptics_rmi4_reg_write(rmi4_data, + fhandler->full_addr.ctrl_base, + &reporting_control, + sizeof(reporting_control)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to change reporting mode\n", + __func__); + return; + } + + return; +} + +static void synaptics_rmi4_f12_wg(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval; + unsigned char offset; + unsigned char reporting_control[3]; + struct synaptics_rmi4_f12_extra_data *extra_data; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F12) + break; + } + + extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra; + offset = extra_data->ctrl20_offset; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + offset, + reporting_control, + sizeof(reporting_control)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to change reporting mode\n", + __func__); + return; + } + + if (enable) + reporting_control[2] = F12_WAKEUP_GESTURE_MODE; + else + reporting_control[2] = F12_CONTINUOUS_MODE; + + retval = synaptics_rmi4_reg_write(rmi4_data, + fhandler->full_addr.ctrl_base + offset, + reporting_control, + sizeof(reporting_control)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to change reporting mode\n", + __func__); + return; + } + + return; +} + +static void synaptics_rmi4_wakeup_gesture(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + if (rmi4_data->f11_wakeup_gesture) + synaptics_rmi4_f11_wg(rmi4_data, enable); + else if (rmi4_data->f12_wakeup_gesture) + synaptics_rmi4_f12_wg(rmi4_data, enable); + + return; +} + +static int synaptics_rmi4_f11_abs_report(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + unsigned char touch_count = 0; /* number of touch points */ + unsigned char reg_index; + unsigned char finger; + unsigned char fingers_supported; + unsigned char num_of_finger_status_regs; + unsigned char finger_shift; + unsigned char finger_status; + unsigned char finger_status_reg[3]; + unsigned char detected_gestures; + unsigned short data_addr; + unsigned short data_offset; + int x; + int y; + int wx; + int wy; + int temp; + struct synaptics_rmi4_f11_data_1_5 data; + struct synaptics_rmi4_f11_extra_data *extra_data; + + /* + * The number of finger status registers is determined by the + * maximum number of fingers supported - 2 bits per finger. So + * the number of finger status registers to read is: + * register_count = ceil(max_num_of_fingers / 4) + */ + fingers_supported = fhandler->num_of_data_points; + num_of_finger_status_regs = (fingers_supported + 3) / 4; + data_addr = fhandler->full_addr.data_base; + + extra_data = (struct synaptics_rmi4_f11_extra_data *)fhandler->extra; + + if (rmi4_data->suspend && rmi4_data->enable_wakeup_gesture) { + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data38_offset, + &detected_gestures, + sizeof(detected_gestures)); + if (retval < 0) + return 0; + + if (detected_gestures) { + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 1); + input_sync(rmi4_data->input_dev); + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 0); + input_sync(rmi4_data->input_dev); + rmi4_data->suspend = false; + } + synaptics_rmi4_wakeup_gesture(rmi4_data, false); + return 0; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr, + finger_status_reg, + num_of_finger_status_regs); + if (retval < 0) + return 0; + + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + + for (finger = 0; finger < fingers_supported; finger++) { + reg_index = finger / 4; + finger_shift = (finger % 4) * 2; + finger_status = (finger_status_reg[reg_index] >> finger_shift) + & MASK_2BIT; + + /* + * Each 2-bit finger status field represents the following: + * 00 = finger not present + * 01 = finger present and data accurate + * 10 = finger present but data may be inaccurate + * 11 = reserved + */ +#ifdef TYPE_B_PROTOCOL + input_mt_slot(rmi4_data->input_dev, finger); + input_mt_report_slot_state(rmi4_data->input_dev, + MT_TOOL_FINGER, finger_status); +#endif + + if (finger_status) { + data_offset = data_addr + + num_of_finger_status_regs + + (finger * sizeof(data.data)); + retval = synaptics_rmi4_reg_read(rmi4_data, + data_offset, + data.data, + sizeof(data.data)); + if (retval < 0) { + touch_count = 0; + goto exit; + } + + x = (data.x_position_11_4 << 4) | data.x_position_3_0; + y = (data.y_position_11_4 << 4) | data.y_position_3_0; + wx = data.wx; + wy = data.wy; + + if (rmi4_data->hw_if->board_data->swap_axes) { + temp = x; + x = y; + y = temp; + temp = wx; + wx = wy; + wy = temp; + } + + if (rmi4_data->hw_if->board_data->x_flip) + x = rmi4_data->sensor_max_x - x; + if (rmi4_data->hw_if->board_data->y_flip) + y = rmi4_data->sensor_max_y - y; + + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 1); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 1); + input_report_abs(rmi4_data->input_dev, + ABS_MT_POSITION_X, x); + input_report_abs(rmi4_data->input_dev, + ABS_MT_POSITION_Y, y); +#ifdef REPORT_2D_W + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MAJOR, max(wx, wy)); + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MINOR, min(wx, wy)); +#endif +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Finger %d: status = 0x%02x, x = %d, y = %d, wx = %d, wy = %d\n", + __func__, finger, + finger_status, + x, y, wx, wy); + + touch_count++; + } + } + + if (touch_count == 0) { + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 0); +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + } + + input_sync(rmi4_data->input_dev); + +exit: + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + + return touch_count; +} + +static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + unsigned char touch_count = 0; /* number of touch points */ + unsigned char index; + unsigned char finger; + unsigned char fingers_to_process; + unsigned char finger_status; + unsigned char size_of_2d_data; + unsigned char gesture_type; + unsigned short data_addr; + int x; + int y; + int wx; + int wy; + int temp; +#if defined(REPORT_2D_PRESSURE) || defined(F51_DISCRETE_FORCE) + int pressure; +#endif +#ifdef REPORT_2D_PRESSURE + unsigned char f_fingers; + unsigned char f_lsb; + unsigned char f_msb; + unsigned char *f_data; +#endif +#ifdef F51_DISCRETE_FORCE + unsigned char force_level; +#endif + struct synaptics_rmi4_f12_extra_data *extra_data; + struct synaptics_rmi4_f12_finger_data *data; + struct synaptics_rmi4_f12_finger_data *finger_data; + static unsigned char finger_presence; + static unsigned char stylus_presence; +#ifdef F12_DATA_15_WORKAROUND + static unsigned char objects_already_present; +#endif + + fingers_to_process = fhandler->num_of_data_points; + data_addr = fhandler->full_addr.data_base; + extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra; + size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data); + + if (rmi4_data->suspend && rmi4_data->enable_wakeup_gesture) { + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data4_offset, + rmi4_data->gesture_detection, + sizeof(rmi4_data->gesture_detection)); + if (retval < 0) + return 0; + + gesture_type = rmi4_data->gesture_detection[0]; + + if (gesture_type && gesture_type != F12_UDG_DETECT) { + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 1); + input_sync(rmi4_data->input_dev); + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 0); + input_sync(rmi4_data->input_dev); + + rmi4_data->suspend = false; + } + + return 0; + } + + /* Determine the total number of fingers to process */ + if (extra_data->data15_size) { + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data15_offset, + extra_data->data15_data, + extra_data->data15_size); + if (retval < 0) + return 0; + + /* Start checking from the highest bit */ + index = extra_data->data15_size - 1; /* Highest byte */ + finger = (fingers_to_process - 1) % 8; /* Highest bit */ + do { + if (extra_data->data15_data[index] & (1 << finger)) + break; + + if (finger) { + finger--; + } else if (index > 0) { + index--; /* Move to the next lower byte */ + finger = 7; + } + + fingers_to_process--; + } while (fingers_to_process); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Number of fingers to process = %d\n", + __func__, fingers_to_process); + } + +#ifdef F12_DATA_15_WORKAROUND + fingers_to_process = max(fingers_to_process, objects_already_present); +#endif + + if (!fingers_to_process) { + synaptics_rmi4_free_fingers(rmi4_data); + finger_presence = 0; + stylus_presence = 0; + return 0; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data1_offset, + (unsigned char *)fhandler->data, + fingers_to_process * size_of_2d_data); + if (retval < 0) + return 0; + + data = (struct synaptics_rmi4_f12_finger_data *)fhandler->data; + +#ifdef REPORT_2D_PRESSURE + if (rmi4_data->report_pressure) { + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data29_offset, + extra_data->data29_data, + extra_data->data29_size); + if (retval < 0) + return 0; + } +#endif + + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + + for (finger = 0; finger < fingers_to_process; finger++) { + finger_data = data + finger; + finger_status = finger_data->object_type_and_status; + +#ifdef F12_DATA_15_WORKAROUND + objects_already_present = finger + 1; +#endif + + x = (finger_data->x_msb << 8) | (finger_data->x_lsb); + y = (finger_data->y_msb << 8) | (finger_data->y_lsb); +#ifdef REPORT_2D_W + wx = finger_data->wx; + wy = finger_data->wy; +#endif + + if (rmi4_data->hw_if->board_data->swap_axes) { + temp = x; + x = y; + y = temp; + temp = wx; + wx = wy; + wy = temp; + } + + if (rmi4_data->hw_if->board_data->x_flip) + x = rmi4_data->sensor_max_x - x; + if (rmi4_data->hw_if->board_data->y_flip) + y = rmi4_data->sensor_max_y - y; + + switch (finger_status) { + case F12_FINGER_STATUS: + case F12_GLOVED_FINGER_STATUS: + /* Stylus has priority over fingers */ + if (stylus_presence) + break; +#ifdef TYPE_B_PROTOCOL + input_mt_slot(rmi4_data->input_dev, finger); + input_mt_report_slot_state(rmi4_data->input_dev, + MT_TOOL_FINGER, 1); +#endif + + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 1); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 1); + input_report_abs(rmi4_data->input_dev, + ABS_MT_POSITION_X, x); + input_report_abs(rmi4_data->input_dev, + ABS_MT_POSITION_Y, y); +#ifdef REPORT_2D_W + if (rmi4_data->wedge_sensor) { + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MAJOR, wx); + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MINOR, wx); + } else { + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MAJOR, + max(wx, wy)); + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MINOR, + min(wx, wy)); + } +#endif +#ifdef REPORT_2D_PRESSURE + if (rmi4_data->report_pressure) { + f_fingers = extra_data->data29_size / 2; + f_data = extra_data->data29_data; + if (finger + 1 > f_fingers) { + pressure = 1; + } else { + f_lsb = finger * 2; + f_msb = finger * 2 + 1; + pressure = (int)f_data[f_lsb] << 0 | + (int)f_data[f_msb] << 8; + } + pressure = pressure > 0 ? pressure : 1; + if (pressure > rmi4_data->force_max) + pressure = rmi4_data->force_max; + input_report_abs(rmi4_data->input_dev, + ABS_MT_PRESSURE, pressure); + } +#elif defined(F51_DISCRETE_FORCE) + if (finger == 0) { + retval = synaptics_rmi4_reg_read(rmi4_data, + FORCE_LEVEL_ADDR, + &force_level, + sizeof(force_level)); + if (retval < 0) + return 0; + pressure = force_level > 0 ? force_level : 1; + } else { + pressure = 1; + } + input_report_abs(rmi4_data->input_dev, + ABS_MT_PRESSURE, pressure); +#endif +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Finger %d: status = 0x%02x, x = %d, y = %d, wx = %d, wy = %d\n", + __func__, finger, + finger_status, + x, y, wx, wy); + + finger_presence = 1; + touch_count++; + break; + case F12_PALM_STATUS: + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Finger %d: x = %d, y = %d, wx = %d, wy = %d\n", + __func__, finger, + x, y, wx, wy); + break; + case F12_STYLUS_STATUS: + case F12_ERASER_STATUS: + if (!rmi4_data->stylus_enable) + break; + /* Stylus has priority over fingers */ + if (finger_presence) { + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + synaptics_rmi4_free_fingers(rmi4_data); + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + finger_presence = 0; + } + if (stylus_presence) {/* Allow one stylus at a timee */ + if (finger + 1 != stylus_presence) + break; + } + input_report_key(rmi4_data->stylus_dev, + BTN_TOUCH, 1); + if (finger_status == F12_STYLUS_STATUS) { + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_PEN, 1); + } else { + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_RUBBER, 1); + } + input_report_abs(rmi4_data->stylus_dev, + ABS_X, x); + input_report_abs(rmi4_data->stylus_dev, + ABS_Y, y); + input_sync(rmi4_data->stylus_dev); + + stylus_presence = finger + 1; + touch_count++; + break; + default: +#ifdef TYPE_B_PROTOCOL + input_mt_slot(rmi4_data->input_dev, finger); + input_mt_report_slot_state(rmi4_data->input_dev, + MT_TOOL_FINGER, 0); +#endif + break; + } + } + + if (touch_count == 0) { + finger_presence = 0; +#ifdef F12_DATA_15_WORKAROUND + objects_already_present = 0; +#endif + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 0); +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + + if (rmi4_data->stylus_enable) { + stylus_presence = 0; + input_report_key(rmi4_data->stylus_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_PEN, 0); + if (rmi4_data->eraser_enable) { + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_RUBBER, 0); + } + input_sync(rmi4_data->stylus_dev); + } + } + + input_sync(rmi4_data->input_dev); + + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + + return touch_count; +} + +static void synaptics_rmi4_f1a_report(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + unsigned char touch_count = 0; + unsigned char button; + unsigned char index; + unsigned char shift; + unsigned char status; + unsigned char *data; + unsigned short data_addr = fhandler->full_addr.data_base; + struct synaptics_rmi4_f1a_handle *f1a = fhandler->data; + static unsigned char do_once = 1; + static bool current_status[MAX_NUMBER_OF_BUTTONS]; +#ifdef NO_0D_WHILE_2D + static bool before_2d_status[MAX_NUMBER_OF_BUTTONS]; + static bool while_2d_status[MAX_NUMBER_OF_BUTTONS]; +#endif + + if (do_once) { + memset(current_status, 0, sizeof(current_status)); +#ifdef NO_0D_WHILE_2D + memset(before_2d_status, 0, sizeof(before_2d_status)); + memset(while_2d_status, 0, sizeof(while_2d_status)); +#endif + do_once = 0; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr, + f1a->button_data_buffer, + f1a->button_bitmask_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read button data registers\n", + __func__); + return; + } + + data = f1a->button_data_buffer; + + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + + for (button = 0; button < f1a->valid_button_count; button++) { + index = button / 8; + shift = button % 8; + status = ((data[index] >> shift) & MASK_1BIT); + + if (current_status[button] == status) + continue; + else + current_status[button] = status; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Button %d (code %d) ->%d\n", + __func__, button, + f1a->button_map[button], + status); +#ifdef NO_0D_WHILE_2D + if (rmi4_data->fingers_on_2d == false) { + if (status == 1) { + before_2d_status[button] = 1; + } else { + if (while_2d_status[button] == 1) { + while_2d_status[button] = 0; + continue; + } else { + before_2d_status[button] = 0; + } + } + touch_count++; + input_report_key(rmi4_data->input_dev, + f1a->button_map[button], + status); + } else { + if (before_2d_status[button] == 1) { + before_2d_status[button] = 0; + touch_count++; + input_report_key(rmi4_data->input_dev, + f1a->button_map[button], + status); + } else { + if (status == 1) + while_2d_status[button] = 1; + else + while_2d_status[button] = 0; + } + } +#else + touch_count++; + input_report_key(rmi4_data->input_dev, + f1a->button_map[button], + status); +#endif + } + + if (touch_count) + input_sync(rmi4_data->input_dev); + + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + + return; +} + +static void synaptics_rmi4_report_touch(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + unsigned char touch_count_2d; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Function %02x reporting\n", + __func__, fhandler->fn_number); + + switch (fhandler->fn_number) { + case SYNAPTICS_RMI4_F11: + touch_count_2d = synaptics_rmi4_f11_abs_report(rmi4_data, + fhandler); + + if (touch_count_2d) + rmi4_data->fingers_on_2d = true; + else + rmi4_data->fingers_on_2d = false; + break; + case SYNAPTICS_RMI4_F12: + touch_count_2d = synaptics_rmi4_f12_abs_report(rmi4_data, + fhandler); + + if (touch_count_2d) + rmi4_data->fingers_on_2d = true; + else + rmi4_data->fingers_on_2d = false; + break; + case SYNAPTICS_RMI4_F1A: + synaptics_rmi4_f1a_report(rmi4_data, fhandler); + break; +#ifdef USE_DATA_SERVER + case SYNAPTICS_RMI4_F21: + if (synad_pid) + send_sig_info(SIGIO, &interrupt_signal, synad_task); + break; +#endif + default: + break; + } + + return; +} + +static void synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data, + bool report) +{ + int retval; + unsigned char data[MAX_INTR_REGISTERS + 1]; + unsigned char *intr = &data[1]; + bool was_in_bl_mode; + struct synaptics_rmi4_f01_device_status status; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + /* + * Get interrupt status information from F01 Data1 register to + * determine the source(s) that are flagging the interrupt. + */ + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + data, + rmi4_data->num_of_intr_regs + 1); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read interrupt status\n", + __func__); + return; + } + + status.data[0] = data[0]; + if (status.status_code == STATUS_CRC_IN_PROGRESS) { + retval = synaptics_rmi4_check_status(rmi4_data, + &was_in_bl_mode); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to check status\n", + __func__); + return; + } + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + status.data, + sizeof(status.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device status\n", + __func__); + return; + } + } + if (status.unconfigured && !status.flash_prog) { + pr_notice("%s: spontaneous reset detected\n", __func__); + retval = synaptics_rmi4_reinit_device(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to reinit device\n", + __func__); + } + } + + if (!report) + return; + + /* + * Traverse the function handler list and service the source(s) + * of the interrupt accordingly. + */ + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->num_of_data_sources) { + if (fhandler->intr_mask & + intr[fhandler->intr_reg_num]) { + + synaptics_rmi4_report_touch(rmi4_data, + fhandler); + + } + } + } + } + + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) { + if (!exp_fhandler->insert && + !exp_fhandler->remove && + (exp_fhandler->exp_fn->attn != NULL)) + exp_fhandler->exp_fn->attn(rmi4_data, intr[0]); + } + } + mutex_unlock(&exp_data.mutex); + + return; +} + +static irqreturn_t synaptics_rmi4_irq(int irq, void *data) +{ + struct synaptics_rmi4_data *rmi4_data = data; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (gpio_get_value(bdata->irq_gpio) != bdata->irq_on_state) + goto exit; + + synaptics_rmi4_sensor_report(rmi4_data, true); + +exit: + return IRQ_HANDLED; +} + +static int synaptics_rmi4_int_enable(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval = 0; + unsigned char ii; + unsigned char zero = 0x00; + unsigned char *intr_mask; + unsigned short intr_addr; + + intr_mask = rmi4_data->intr_mask; + + for (ii = 0; ii < rmi4_data->num_of_intr_regs; ii++) { + if (intr_mask[ii] != 0x00) { + intr_addr = rmi4_data->f01_ctrl_base_addr + 1 + ii; + if (enable) { + retval = synaptics_rmi4_reg_write(rmi4_data, + intr_addr, + &(intr_mask[ii]), + sizeof(intr_mask[ii])); + if (retval < 0) + return retval; + } else { + retval = synaptics_rmi4_reg_write(rmi4_data, + intr_addr, + &zero, + sizeof(zero)); + if (retval < 0) + return retval; + } + } + } + + return retval; +} + +static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data, + bool enable, bool attn_only) +{ + int retval = 0; + unsigned char data[MAX_INTR_REGISTERS]; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + mutex_lock(&(rmi4_data->rmi4_irq_enable_mutex)); + + if (attn_only) { + retval = synaptics_rmi4_int_enable(rmi4_data, enable); + goto exit; + } + + if (enable) { + if (rmi4_data->irq_enabled) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Interrupt already enabled\n", + __func__); + goto exit; + } + + retval = synaptics_rmi4_int_enable(rmi4_data, false); + if (retval < 0) + goto exit; + + /* Clear interrupts */ + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr + 1, + data, + rmi4_data->num_of_intr_regs); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read interrupt status\n", + __func__); + goto exit; + } + + retval = request_threaded_irq(rmi4_data->irq, NULL, + synaptics_rmi4_irq, bdata->irq_flags, + PLATFORM_DRIVER_NAME, rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create irq thread\n", + __func__); + goto exit; + } + + retval = synaptics_rmi4_int_enable(rmi4_data, true); + if (retval < 0) + goto exit; + + rmi4_data->irq_enabled = true; + } else { + if (rmi4_data->irq_enabled) { + disable_irq(rmi4_data->irq); + free_irq(rmi4_data->irq, rmi4_data); + rmi4_data->irq_enabled = false; + } + } + +exit: + mutex_unlock(&(rmi4_data->rmi4_irq_enable_mutex)); + + return retval; +} + +static void synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + unsigned char ii; + unsigned char intr_offset; + + fhandler->intr_reg_num = (intr_count + 7) / 8; + if (fhandler->intr_reg_num != 0) + fhandler->intr_reg_num -= 1; + + /* Set an enable bit for each data source */ + intr_offset = intr_count % 8; + fhandler->intr_mask = 0; + for (ii = intr_offset; + ii < (fd->intr_src_count + intr_offset); + ii++) + fhandler->intr_mask |= 1 << ii; + + return; +} + +static int synaptics_rmi4_f01_init(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + fhandler->data = NULL; + fhandler->extra = NULL; + + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + + rmi4_data->f01_query_base_addr = fd->query_base_addr; + rmi4_data->f01_ctrl_base_addr = fd->ctrl_base_addr; + rmi4_data->f01_data_base_addr = fd->data_base_addr; + rmi4_data->f01_cmd_base_addr = fd->cmd_base_addr; + + return 0; +} + +static int synaptics_rmi4_f11_init(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + int retval; + int temp; + unsigned char offset; + unsigned char fingers_supported; + struct synaptics_rmi4_f11_extra_data *extra_data; + struct synaptics_rmi4_f11_query_0_5 query_0_5; + struct synaptics_rmi4_f11_query_7_8 query_7_8; + struct synaptics_rmi4_f11_query_9 query_9; + struct synaptics_rmi4_f11_query_12 query_12; + struct synaptics_rmi4_f11_query_27 query_27; + struct synaptics_rmi4_f11_ctrl_6_9 control_6_9; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + fhandler->extra = kmalloc(sizeof(*extra_data), GFP_KERNEL); + if (!fhandler->extra) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fhandler->extra\n", + __func__); + return -ENOMEM; + } + extra_data = (struct synaptics_rmi4_f11_extra_data *)fhandler->extra; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base, + query_0_5.data, + sizeof(query_0_5.data)); + if (retval < 0) + return retval; + + /* Maximum number of fingers supported */ + if (query_0_5.num_of_fingers <= 4) + fhandler->num_of_data_points = query_0_5.num_of_fingers + 1; + else if (query_0_5.num_of_fingers == 5) + fhandler->num_of_data_points = 10; + + rmi4_data->num_of_fingers = fhandler->num_of_data_points; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + 6, + control_6_9.data, + sizeof(control_6_9.data)); + if (retval < 0) + return retval; + + /* Maximum x and y */ + rmi4_data->sensor_max_x = control_6_9.sensor_max_x_pos_7_0 | + (control_6_9.sensor_max_x_pos_11_8 << 8); + rmi4_data->sensor_max_y = control_6_9.sensor_max_y_pos_7_0 | + (control_6_9.sensor_max_y_pos_11_8 << 8); + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Function %02x max x = %d max y = %d\n", + __func__, fhandler->fn_number, + rmi4_data->sensor_max_x, + rmi4_data->sensor_max_y); + + rmi4_data->max_touch_width = MAX_F11_TOUCH_WIDTH; + + if (bdata->swap_axes) { + temp = rmi4_data->sensor_max_x; + rmi4_data->sensor_max_x = rmi4_data->sensor_max_y; + rmi4_data->sensor_max_y = temp; + } + + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + + fhandler->data = NULL; + + offset = sizeof(query_0_5.data); + + /* query 6 */ + if (query_0_5.has_rel) + offset += 1; + + /* queries 7 8 */ + if (query_0_5.has_gestures) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_7_8.data, + sizeof(query_7_8.data)); + if (retval < 0) + return retval; + + offset += sizeof(query_7_8.data); + } + + /* query 9 */ + if (query_0_5.has_query_9) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_9.data, + sizeof(query_9.data)); + if (retval < 0) + return retval; + + offset += sizeof(query_9.data); + } + + /* query 10 */ + if (query_0_5.has_gestures && query_7_8.has_touch_shapes) + offset += 1; + + /* query 11 */ + if (query_0_5.has_query_11) + offset += 1; + + /* query 12 */ + if (query_0_5.has_query_12) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_12.data, + sizeof(query_12.data)); + if (retval < 0) + return retval; + + offset += sizeof(query_12.data); + } + + /* query 13 */ + if (query_0_5.has_jitter_filter) + offset += 1; + + /* query 14 */ + if (query_0_5.has_query_12 && query_12.has_general_information_2) + offset += 1; + + /* queries 15 16 17 18 19 20 21 22 23 24 25 26*/ + if (query_0_5.has_query_12 && query_12.has_physical_properties) + offset += 12; + + /* query 27 */ + if (query_0_5.has_query_27) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_27.data, + sizeof(query_27.data)); + if (retval < 0) + return retval; + + rmi4_data->f11_wakeup_gesture = query_27.has_wakeup_gesture; + } + + if (!rmi4_data->f11_wakeup_gesture) + return retval; + + /* data 0 */ + fingers_supported = fhandler->num_of_data_points; + offset = (fingers_supported + 3) / 4; + + /* data 1 2 3 4 5 */ + offset += 5 * fingers_supported; + + /* data 6 7 */ + if (query_0_5.has_rel) + offset += 2 * fingers_supported; + + /* data 8 */ + if (query_0_5.has_gestures && query_7_8.data[0]) + offset += 1; + + /* data 9 */ + if (query_0_5.has_gestures && (query_7_8.data[0] || query_7_8.data[1])) + offset += 1; + + /* data 10 */ + if (query_0_5.has_gestures && + (query_7_8.has_pinch || query_7_8.has_flick)) + offset += 1; + + /* data 11 12 */ + if (query_0_5.has_gestures && + (query_7_8.has_flick || query_7_8.has_rotate)) + offset += 2; + + /* data 13 */ + if (query_0_5.has_gestures && query_7_8.has_touch_shapes) + offset += (fingers_supported + 3) / 4; + + /* data 14 15 */ + if (query_0_5.has_gestures && + (query_7_8.has_scroll_zones || + query_7_8.has_multi_finger_scroll || + query_7_8.has_chiral_scroll)) + offset += 2; + + /* data 16 17 */ + if (query_0_5.has_gestures && + (query_7_8.has_scroll_zones && + query_7_8.individual_scroll_zones)) + offset += 2; + + /* data 18 19 20 21 22 23 24 25 26 27 */ + if (query_0_5.has_query_9 && query_9.has_contact_geometry) + offset += 10 * fingers_supported; + + /* data 28 */ + if (query_0_5.has_bending_correction || + query_0_5.has_large_object_suppression) + offset += 1; + + /* data 29 30 31 */ + if (query_0_5.has_query_9 && query_9.has_pen_hover_discrimination) + offset += 3; + + /* data 32 */ + if (query_0_5.has_query_12 && + query_12.has_small_object_detection_tuning) + offset += 1; + + /* data 33 34 */ + if (query_0_5.has_query_27 && query_27.f11_query27_b0) + offset += 2; + + /* data 35 */ + if (query_0_5.has_query_12 && query_12.has_8bit_w) + offset += fingers_supported; + + /* data 36 */ + if (query_0_5.has_bending_correction) + offset += 1; + + /* data 37 */ + if (query_0_5.has_query_27 && query_27.has_data_37) + offset += 1; + + /* data 38 */ + if (query_0_5.has_query_27 && query_27.has_wakeup_gesture) + extra_data->data38_offset = offset; + + return retval; +} + +static int synaptics_rmi4_f12_set_enables(struct synaptics_rmi4_data *rmi4_data, + unsigned short ctrl28) +{ + int retval; + static unsigned short ctrl_28_address; + + if (ctrl28) + ctrl_28_address = ctrl28; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_28_address, + &rmi4_data->report_enable, + sizeof(rmi4_data->report_enable)); + if (retval < 0) + return retval; + + return retval; +} + +static int synaptics_rmi4_f12_find_sub(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + unsigned char *presence, unsigned char presence_size, + unsigned char structure_offset, unsigned char reg, + unsigned char sub) +{ + int retval; + unsigned char cnt; + unsigned char regnum; + unsigned char bitnum; + unsigned char p_index; + unsigned char s_index; + unsigned char offset; + unsigned char max_reg; + unsigned char *structure; + + max_reg = (presence_size - 1) * 8 - 1; + + if (reg > max_reg) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Register number (%d) over limit\n", + __func__, reg); + return -EINVAL; + } + + p_index = reg / 8 + 1; + bitnum = reg % 8; + if ((presence[p_index] & (1 << bitnum)) == 0x00) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Register %d is not present\n", + __func__, reg); + return -EINVAL; + } + + structure = kmalloc(presence[0], GFP_KERNEL); + if (!structure) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for structure register\n", + __func__); + return -ENOMEM; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + structure_offset, + structure, + presence[0]); + if (retval < 0) + goto exit; + + s_index = 0; + + for (regnum = 0; regnum < reg; regnum++) { + p_index = regnum / 8 + 1; + bitnum = regnum % 8; + if ((presence[p_index] & (1 << bitnum)) == 0x00) + continue; + + if (structure[s_index] == 0x00) + s_index += 3; + else + s_index++; + + while (structure[s_index] & ~MASK_7BIT) + s_index++; + + s_index++; + } + + cnt = 0; + s_index++; + offset = sub / 7; + bitnum = sub % 7; + + do { + if (cnt == offset) { + if (structure[s_index + cnt] & (1 << bitnum)) + retval = 1; + else + retval = 0; + goto exit; + } + cnt++; + } while (structure[s_index + cnt - 1] & ~MASK_7BIT); + + retval = 0; + +exit: + kfree(structure); + + return retval; +} + +static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + int retval = 0; + int temp; + unsigned char subpacket; + unsigned char ctrl_23_size; + unsigned char size_of_2d_data; + unsigned char size_of_query5; + unsigned char size_of_query8; + unsigned char ctrl_8_offset; + unsigned char ctrl_20_offset; + unsigned char ctrl_23_offset; + unsigned char ctrl_28_offset; + unsigned char ctrl_31_offset; + unsigned char ctrl_58_offset; + unsigned char num_of_fingers; + struct synaptics_rmi4_f12_extra_data *extra_data; + struct synaptics_rmi4_f12_query_5 *query_5 = NULL; + struct synaptics_rmi4_f12_query_8 *query_8 = NULL; + struct synaptics_rmi4_f12_ctrl_8 *ctrl_8 = NULL; + struct synaptics_rmi4_f12_ctrl_23 *ctrl_23 = NULL; + struct synaptics_rmi4_f12_ctrl_31 *ctrl_31 = NULL; + struct synaptics_rmi4_f12_ctrl_58 *ctrl_58 = NULL; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + fhandler->extra = kmalloc(sizeof(*extra_data), GFP_KERNEL); + if (!fhandler->extra) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fhandler->extra\n", + __func__); + return -ENOMEM; + } + extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra; + size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data); + + query_5 = kzalloc(sizeof(*query_5), GFP_KERNEL); + if (!query_5) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_5\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + query_8 = kzalloc(sizeof(*query_8), GFP_KERNEL); + if (!query_8) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_8\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + ctrl_8 = kzalloc(sizeof(*ctrl_8), GFP_KERNEL); + if (!ctrl_8) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for ctrl_8\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + ctrl_23 = kzalloc(sizeof(*ctrl_23), GFP_KERNEL); + if (!ctrl_23) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for ctrl_23\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + ctrl_31 = kzalloc(sizeof(*ctrl_31), GFP_KERNEL); + if (!ctrl_31) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for ctrl_31\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + ctrl_58 = kzalloc(sizeof(*ctrl_58), GFP_KERNEL); + if (!ctrl_58) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for ctrl_58\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + 4, + &size_of_query5, + sizeof(size_of_query5)); + if (retval < 0) + goto exit; + + if (size_of_query5 > sizeof(query_5->data)) + size_of_query5 = sizeof(query_5->data); + memset(query_5->data, 0x00, sizeof(query_5->data)); + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + 5, + query_5->data, + size_of_query5); + if (retval < 0) + goto exit; + + ctrl_8_offset = query_5->ctrl0_is_present + + query_5->ctrl1_is_present + + query_5->ctrl2_is_present + + query_5->ctrl3_is_present + + query_5->ctrl4_is_present + + query_5->ctrl5_is_present + + query_5->ctrl6_is_present + + query_5->ctrl7_is_present; + + ctrl_20_offset = ctrl_8_offset + + query_5->ctrl8_is_present + + query_5->ctrl9_is_present + + query_5->ctrl10_is_present + + query_5->ctrl11_is_present + + query_5->ctrl12_is_present + + query_5->ctrl13_is_present + + query_5->ctrl14_is_present + + query_5->ctrl15_is_present + + query_5->ctrl16_is_present + + query_5->ctrl17_is_present + + query_5->ctrl18_is_present + + query_5->ctrl19_is_present; + + ctrl_23_offset = ctrl_20_offset + + query_5->ctrl20_is_present + + query_5->ctrl21_is_present + + query_5->ctrl22_is_present; + + ctrl_28_offset = ctrl_23_offset + + query_5->ctrl23_is_present + + query_5->ctrl24_is_present + + query_5->ctrl25_is_present + + query_5->ctrl26_is_present + + query_5->ctrl27_is_present; + + ctrl_31_offset = ctrl_28_offset + + query_5->ctrl28_is_present + + query_5->ctrl29_is_present + + query_5->ctrl30_is_present; + + ctrl_58_offset = ctrl_31_offset + + query_5->ctrl31_is_present + + query_5->ctrl32_is_present + + query_5->ctrl33_is_present + + query_5->ctrl34_is_present + + query_5->ctrl35_is_present + + query_5->ctrl36_is_present + + query_5->ctrl37_is_present + + query_5->ctrl38_is_present + + query_5->ctrl39_is_present + + query_5->ctrl40_is_present + + query_5->ctrl41_is_present + + query_5->ctrl42_is_present + + query_5->ctrl43_is_present + + query_5->ctrl44_is_present + + query_5->ctrl45_is_present + + query_5->ctrl46_is_present + + query_5->ctrl47_is_present + + query_5->ctrl48_is_present + + query_5->ctrl49_is_present + + query_5->ctrl50_is_present + + query_5->ctrl51_is_present + + query_5->ctrl52_is_present + + query_5->ctrl53_is_present + + query_5->ctrl54_is_present + + query_5->ctrl55_is_present + + query_5->ctrl56_is_present + + query_5->ctrl57_is_present; + + ctrl_23_size = 2; + for (subpacket = 2; subpacket <= 4; subpacket++) { + retval = synaptics_rmi4_f12_find_sub(rmi4_data, + fhandler, query_5->data, sizeof(query_5->data), + 6, 23, subpacket); + if (retval == 1) + ctrl_23_size++; + else if (retval < 0) + goto exit; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_23_offset, + ctrl_23->data, + ctrl_23_size); + if (retval < 0) + goto exit; + + /* Maximum number of fingers supported */ + fhandler->num_of_data_points = min_t(unsigned char, + ctrl_23->max_reported_objects, + (unsigned char)F12_FINGERS_TO_SUPPORT); + + num_of_fingers = fhandler->num_of_data_points; + rmi4_data->num_of_fingers = num_of_fingers; + + rmi4_data->stylus_enable = ctrl_23->stylus_enable; + rmi4_data->eraser_enable = ctrl_23->eraser_enable; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + 7, + &size_of_query8, + sizeof(size_of_query8)); + if (retval < 0) + goto exit; + + if (size_of_query8 > sizeof(query_8->data)) + size_of_query8 = sizeof(query_8->data); + memset(query_8->data, 0x00, sizeof(query_8->data)); + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + 8, + query_8->data, + size_of_query8); + if (retval < 0) + goto exit; + + /* Determine the presence of the Data0 register */ + extra_data->data1_offset = query_8->data0_is_present; + + if ((size_of_query8 >= 3) && (query_8->data15_is_present)) { + extra_data->data15_offset = query_8->data0_is_present + + query_8->data1_is_present + + query_8->data2_is_present + + query_8->data3_is_present + + query_8->data4_is_present + + query_8->data5_is_present + + query_8->data6_is_present + + query_8->data7_is_present + + query_8->data8_is_present + + query_8->data9_is_present + + query_8->data10_is_present + + query_8->data11_is_present + + query_8->data12_is_present + + query_8->data13_is_present + + query_8->data14_is_present; + extra_data->data15_size = (num_of_fingers + 7) / 8; + } else { + extra_data->data15_size = 0; + } + +#ifdef REPORT_2D_PRESSURE + if ((size_of_query8 >= 5) && (query_8->data29_is_present)) { + extra_data->data29_offset = query_8->data0_is_present + + query_8->data1_is_present + + query_8->data2_is_present + + query_8->data3_is_present + + query_8->data4_is_present + + query_8->data5_is_present + + query_8->data6_is_present + + query_8->data7_is_present + + query_8->data8_is_present + + query_8->data9_is_present + + query_8->data10_is_present + + query_8->data11_is_present + + query_8->data12_is_present + + query_8->data13_is_present + + query_8->data14_is_present + + query_8->data15_is_present + + query_8->data16_is_present + + query_8->data17_is_present + + query_8->data18_is_present + + query_8->data19_is_present + + query_8->data20_is_present + + query_8->data21_is_present + + query_8->data22_is_present + + query_8->data23_is_present + + query_8->data24_is_present + + query_8->data25_is_present + + query_8->data26_is_present + + query_8->data27_is_present + + query_8->data28_is_present; + extra_data->data29_size = 0; + for (subpacket = 0; subpacket <= num_of_fingers; subpacket++) { + retval = synaptics_rmi4_f12_find_sub(rmi4_data, + fhandler, query_8->data, + sizeof(query_8->data), + 9, 29, subpacket); + if (retval == 1) + extra_data->data29_size += 2; + else if (retval < 0) + goto exit; + } + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_58_offset, + ctrl_58->data, + sizeof(ctrl_58->data)); + if (retval < 0) + goto exit; + rmi4_data->force_min = + (int)(ctrl_58->min_force_lsb << 0) | + (int)(ctrl_58->min_force_msb << 8); + rmi4_data->force_max = + (int)(ctrl_58->max_force_lsb << 0) | + (int)(ctrl_58->max_force_msb << 8); + rmi4_data->report_pressure = true; + } else { + extra_data->data29_size = 0; + rmi4_data->report_pressure = false; + } +#endif + + rmi4_data->report_enable = RPT_DEFAULT; +#ifdef REPORT_2D_Z + rmi4_data->report_enable |= RPT_Z; +#endif +#ifdef REPORT_2D_W + rmi4_data->report_enable |= (RPT_WX | RPT_WY); +#endif + + retval = synaptics_rmi4_f12_set_enables(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_28_offset); + if (retval < 0) + goto exit; + + if (query_5->ctrl8_is_present) { + rmi4_data->wedge_sensor = false; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_8_offset, + ctrl_8->data, + sizeof(ctrl_8->data)); + if (retval < 0) + goto exit; + + /* Maximum x and y */ + rmi4_data->sensor_max_x = + ((unsigned int)ctrl_8->max_x_coord_lsb << 0) | + ((unsigned int)ctrl_8->max_x_coord_msb << 8); + rmi4_data->sensor_max_y = + ((unsigned int)ctrl_8->max_y_coord_lsb << 0) | + ((unsigned int)ctrl_8->max_y_coord_msb << 8); + + rmi4_data->max_touch_width = MAX_F12_TOUCH_WIDTH; + } else { + rmi4_data->wedge_sensor = true; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_31_offset, + ctrl_31->data, + sizeof(ctrl_31->data)); + if (retval < 0) + goto exit; + + /* Maximum x and y */ + rmi4_data->sensor_max_x = + ((unsigned int)ctrl_31->max_x_coord_lsb << 0) | + ((unsigned int)ctrl_31->max_x_coord_msb << 8); + rmi4_data->sensor_max_y = + ((unsigned int)ctrl_31->max_y_coord_lsb << 0) | + ((unsigned int)ctrl_31->max_y_coord_msb << 8); + + rmi4_data->max_touch_width = MAX_F12_TOUCH_WIDTH; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Function %02x max x = %d max y = %d\n", + __func__, fhandler->fn_number, + rmi4_data->sensor_max_x, + rmi4_data->sensor_max_y); + + if (bdata->swap_axes) { + temp = rmi4_data->sensor_max_x; + rmi4_data->sensor_max_x = rmi4_data->sensor_max_y; + rmi4_data->sensor_max_y = temp; + } + + rmi4_data->f12_wakeup_gesture = query_5->ctrl27_is_present; + if (rmi4_data->f12_wakeup_gesture) { + extra_data->ctrl20_offset = ctrl_20_offset; + extra_data->data4_offset = query_8->data0_is_present + + query_8->data1_is_present + + query_8->data2_is_present + + query_8->data3_is_present; + } + + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + + /* Allocate memory for finger data storage space */ + fhandler->data_size = num_of_fingers * size_of_2d_data; + fhandler->data = kmalloc(fhandler->data_size, GFP_KERNEL); + if (!fhandler->data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fhandler->data\n", + __func__); + retval = -ENOMEM; + goto exit; + } + +exit: + kfree(query_5); + kfree(query_8); + kfree(ctrl_8); + kfree(ctrl_23); + kfree(ctrl_31); + kfree(ctrl_58); + + return retval; +} + +static int synaptics_rmi4_f1a_alloc_mem(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + struct synaptics_rmi4_f1a_handle *f1a; + + f1a = kzalloc(sizeof(*f1a), GFP_KERNEL); + if (!f1a) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for function handle\n", + __func__); + return -ENOMEM; + } + + fhandler->data = (void *)f1a; + fhandler->extra = NULL; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base, + f1a->button_query.data, + sizeof(f1a->button_query.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read query registers\n", + __func__); + return retval; + } + + f1a->max_count = f1a->button_query.max_button_count + 1; + + f1a->button_control.txrx_map = kzalloc(f1a->max_count * 2, GFP_KERNEL); + if (!f1a->button_control.txrx_map) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for tx rx mapping\n", + __func__); + return -ENOMEM; + } + + f1a->button_bitmask_size = (f1a->max_count + 7) / 8; + + f1a->button_data_buffer = kcalloc(f1a->button_bitmask_size, + sizeof(*(f1a->button_data_buffer)), GFP_KERNEL); + if (!f1a->button_data_buffer) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for data buffer\n", + __func__); + return -ENOMEM; + } + + f1a->button_map = kcalloc(f1a->max_count, + sizeof(*(f1a->button_map)), GFP_KERNEL); + if (!f1a->button_map) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for button map\n", + __func__); + return -ENOMEM; + } + + return 0; +} + +static int synaptics_rmi4_f1a_button_map(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + unsigned char ii; + unsigned char offset = 0; + struct synaptics_rmi4_f1a_query_4 query_4; + struct synaptics_rmi4_f1a_handle *f1a = fhandler->data; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + rmi4_data->valid_button_count = f1a->valid_button_count; + + offset = f1a->button_query.has_general_control + + f1a->button_query.has_interrupt_enable + + f1a->button_query.has_multibutton_select; + + if (f1a->button_query.has_tx_rx_map) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + offset, + f1a->button_control.txrx_map, + f1a->max_count * 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tx rx mapping\n", + __func__); + return retval; + } + + rmi4_data->button_txrx_mapping = f1a->button_control.txrx_map; + } + + if (f1a->button_query.has_query4) { + offset = 2 + f1a->button_query.has_query2 + + f1a->button_query.has_query3; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_4.data, + sizeof(query_4.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read button features 4\n", + __func__); + return retval; + } + + if (query_4.has_ctrl24) + rmi4_data->external_afe_buttons = true; + else + rmi4_data->external_afe_buttons = false; + } + + if (!bdata->cap_button_map) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: cap_button_map is NULL in board file\n", + __func__); + return -ENODEV; + } else if (!bdata->cap_button_map->map) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Button map is missing in board file\n", + __func__); + return -ENODEV; + } else { + if (bdata->cap_button_map->nbuttons != f1a->max_count) { + f1a->valid_button_count = min(f1a->max_count, + bdata->cap_button_map->nbuttons); + } else { + f1a->valid_button_count = f1a->max_count; + } + + for (ii = 0; ii < f1a->valid_button_count; ii++) + f1a->button_map[ii] = bdata->cap_button_map->map[ii]; + + rmi4_data->valid_button_count = f1a->valid_button_count; + } + + return 0; +} + +static void synaptics_rmi4_f1a_kfree(struct synaptics_rmi4_fn *fhandler) +{ + struct synaptics_rmi4_f1a_handle *f1a = fhandler->data; + + if (f1a) { + kfree(f1a->button_control.txrx_map); + kfree(f1a->button_data_buffer); + kfree(f1a->button_map); + kfree(f1a); + fhandler->data = NULL; + } + + return; +} + +static int synaptics_rmi4_f1a_init(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + int retval; + + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + + retval = synaptics_rmi4_f1a_alloc_mem(rmi4_data, fhandler); + if (retval < 0) + goto error_exit; + + retval = synaptics_rmi4_f1a_button_map(rmi4_data, fhandler); + if (retval < 0) + goto error_exit; + + rmi4_data->button_0d_enabled = 1; + + return 0; + +error_exit: + synaptics_rmi4_f1a_kfree(fhandler); + + return retval; +} + +static void synaptics_rmi4_empty_fn_list(struct synaptics_rmi4_data *rmi4_data) +{ + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_fn *fhandler_temp; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry_safe(fhandler, + fhandler_temp, + &rmi->support_fn_list, + link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) { + synaptics_rmi4_f1a_kfree(fhandler); + } else { + kfree(fhandler->extra); + kfree(fhandler->data); + } + list_del(&fhandler->link); + kfree(fhandler); + } + } + INIT_LIST_HEAD(&rmi->support_fn_list); + + return; +} + +static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data, + bool *was_in_bl_mode) +{ + int retval; + int timeout = CHECK_STATUS_TIMEOUT_MS; + struct synaptics_rmi4_f01_device_status status; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + status.data, + sizeof(status.data)); + if (retval < 0) + return retval; + + while (status.status_code == STATUS_CRC_IN_PROGRESS) { + if (timeout > 0) + msleep(20); + else + return -EINVAL; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + status.data, + sizeof(status.data)); + if (retval < 0) + return retval; + + timeout -= 20; + } + + if (timeout != CHECK_STATUS_TIMEOUT_MS) + *was_in_bl_mode = true; + + if (status.flash_prog == 1) { + rmi4_data->flash_prog_mode = true; + pr_notice("%s: In flash prog mode, status = 0x%02x\n", + __func__, + status.status_code); + } else { + rmi4_data->flash_prog_mode = false; + } + + return 0; +} + +static void synaptics_rmi4_set_configured(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char device_ctrl; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set configured\n", + __func__); + return; + } + + rmi4_data->no_sleep_setting = device_ctrl & NO_SLEEP_ON; + device_ctrl |= CONFIGURED; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set configured\n", + __func__); + } + + return; +} + +static int synaptics_rmi4_alloc_fh(struct synaptics_rmi4_fn **fhandler, + struct synaptics_rmi4_fn_desc *rmi_fd, int page_number) +{ + *fhandler = kzalloc(sizeof(**fhandler), GFP_KERNEL); + if (!(*fhandler)) + return -ENOMEM; + + (*fhandler)->full_addr.data_base = + (rmi_fd->data_base_addr | + (page_number << 8)); + (*fhandler)->full_addr.ctrl_base = + (rmi_fd->ctrl_base_addr | + (page_number << 8)); + (*fhandler)->full_addr.cmd_base = + (rmi_fd->cmd_base_addr | + (page_number << 8)); + (*fhandler)->full_addr.query_base = + (rmi_fd->query_base_addr | + (page_number << 8)); + + return 0; +} + +static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char page_number; + unsigned char intr_count; + unsigned char *f01_query; + unsigned short pdt_entry_addr; + bool f01found; + bool f35found; + bool was_in_bl_mode; + struct synaptics_rmi4_fn_desc rmi_fd; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + +rescan_pdt: + f01found = false; + f35found = false; + was_in_bl_mode = false; + intr_count = 0; + INIT_LIST_HEAD(&rmi->support_fn_list); + + /* Scan the page description tables of the pages to service */ + for (page_number = 0; page_number < PAGES_TO_SERVICE; page_number++) { + for (pdt_entry_addr = PDT_START; pdt_entry_addr > PDT_END; + pdt_entry_addr -= PDT_ENTRY_SIZE) { + pdt_entry_addr |= (page_number << 8); + + retval = synaptics_rmi4_reg_read(rmi4_data, + pdt_entry_addr, + (unsigned char *)&rmi_fd, + sizeof(rmi_fd)); + if (retval < 0) + return retval; + + pdt_entry_addr &= ~(MASK_8BIT << 8); + + fhandler = NULL; + + if (rmi_fd.fn_number == 0) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Reached end of PDT\n", + __func__); + break; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: F%02x found (page %d)\n", + __func__, rmi_fd.fn_number, + page_number); + + switch (rmi_fd.fn_number) { + case SYNAPTICS_RMI4_F01: + if (rmi_fd.intr_src_count == 0) + break; + + f01found = true; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + retval = synaptics_rmi4_f01_init(rmi4_data, + fhandler, &rmi_fd, intr_count); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_check_status(rmi4_data, + &was_in_bl_mode); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to check status\n", + __func__); + return retval; + } + + if (was_in_bl_mode) { + kfree(fhandler); + fhandler = NULL; + goto rescan_pdt; + } + + if (rmi4_data->flash_prog_mode) + goto flash_prog_mode; + + break; + case SYNAPTICS_RMI4_F11: + if (rmi_fd.intr_src_count == 0) + break; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + retval = synaptics_rmi4_f11_init(rmi4_data, + fhandler, &rmi_fd, intr_count); + if (retval < 0) + return retval; + break; + case SYNAPTICS_RMI4_F12: + if (rmi_fd.intr_src_count == 0) + break; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + retval = synaptics_rmi4_f12_init(rmi4_data, + fhandler, &rmi_fd, intr_count); + if (retval < 0) + return retval; + break; + case SYNAPTICS_RMI4_F1A: + if (rmi_fd.intr_src_count == 0) + break; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + retval = synaptics_rmi4_f1a_init(rmi4_data, + fhandler, &rmi_fd, intr_count); + if (retval < 0) { +#ifdef IGNORE_FN_INIT_FAILURE + kfree(fhandler); + fhandler = NULL; +#else + return retval; +#endif + } + break; +#ifdef USE_DATA_SERVER + case SYNAPTICS_RMI4_F21: + if (rmi_fd.intr_src_count == 0) + break; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + fhandler->fn_number = rmi_fd.fn_number; + fhandler->num_of_data_sources = + rmi_fd.intr_src_count; + + synaptics_rmi4_set_intr_mask(fhandler, &rmi_fd, + intr_count); + break; +#endif + case SYNAPTICS_RMI4_F35: + f35found = true; + break; +#ifdef F51_DISCRETE_FORCE + case SYNAPTICS_RMI4_F51: + rmi4_data->f51_query_base_addr = + rmi_fd.query_base_addr | + (page_number << 8); + break; +#endif + } + + /* Accumulate the interrupt count */ + intr_count += rmi_fd.intr_src_count; + + if (fhandler && rmi_fd.intr_src_count) { + list_add_tail(&fhandler->link, + &rmi->support_fn_list); + } + } + } + + if (!f01found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F01\n", + __func__); + if (!f35found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F35\n", + __func__); + return -EINVAL; + } else { + pr_notice("%s: In microbootloader mode\n", + __func__); + return 0; + } + } + +flash_prog_mode: + rmi4_data->num_of_intr_regs = (intr_count + 7) / 8; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Number of interrupt registers = %d\n", + __func__, rmi4_data->num_of_intr_regs); + + f01_query = kmalloc(F01_STD_QUERY_LEN, GFP_KERNEL); + if (!f01_query) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for f01_query\n", + __func__); + return -ENOMEM; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_query_base_addr, + f01_query, + F01_STD_QUERY_LEN); + if (retval < 0) { + kfree(f01_query); + return retval; + } + + /* RMI Version 4.0 currently supported */ + rmi->version_major = 4; + rmi->version_minor = 0; + + rmi->manufacturer_id = f01_query[0]; + rmi->product_props = f01_query[1]; + rmi->product_info[0] = f01_query[2]; + rmi->product_info[1] = f01_query[3]; + retval = secure_memcpy(rmi->product_id_string, + sizeof(rmi->product_id_string), + &f01_query[11], + F01_STD_QUERY_LEN - 11, + PRODUCT_ID_SIZE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy product ID string\n", + __func__); + } + + kfree(f01_query); + + if (rmi->manufacturer_id != 1) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Non-Synaptics device found, manufacturer ID = %d\n", + __func__, rmi->manufacturer_id); + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_query_base_addr + F01_BUID_ID_OFFSET, + rmi->build_id, + sizeof(rmi->build_id)); + if (retval < 0) + return retval; + + rmi4_data->firmware_id = (unsigned int)rmi->build_id[0] + + (unsigned int)rmi->build_id[1] * 0x100 + + (unsigned int)rmi->build_id[2] * 0x10000; + + memset(rmi4_data->intr_mask, 0x00, sizeof(rmi4_data->intr_mask)); + + /* + * Map out the interrupt bit masks for the interrupt sources + * from the registered function handlers. + */ + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->num_of_data_sources) { + rmi4_data->intr_mask[fhandler->intr_reg_num] |= + fhandler->intr_mask; + } + } + } + + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture) + rmi4_data->enable_wakeup_gesture = WAKEUP_GESTURE; + else + rmi4_data->enable_wakeup_gesture = false; + + synaptics_rmi4_set_configured(rmi4_data); + + return 0; +} + +static int synaptics_rmi4_gpio_setup(int gpio, bool config, int dir, int state) +{ + int retval = 0; + unsigned char buf[16]; + + if (config) { + snprintf(buf, PAGE_SIZE, "dsx_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; +} + +static void synaptics_rmi4_set_params(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char ii; + struct synaptics_rmi4_f1a_handle *f1a; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_POSITION_X, 0, + rmi4_data->sensor_max_x, 0, 0); + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_POSITION_Y, 0, + rmi4_data->sensor_max_y, 0, 0); +#ifdef REPORT_2D_W + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_TOUCH_MAJOR, 0, + rmi4_data->max_touch_width, 0, 0); + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_TOUCH_MINOR, 0, + rmi4_data->max_touch_width, 0, 0); +#endif + + rmi4_data->input_settings.sensor_max_x = rmi4_data->sensor_max_x; + rmi4_data->input_settings.sensor_max_y = rmi4_data->sensor_max_y; + rmi4_data->input_settings.max_touch_width = rmi4_data->max_touch_width; + +#ifdef REPORT_2D_PRESSURE + if (rmi4_data->report_pressure) { + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_PRESSURE, rmi4_data->force_min, + rmi4_data->force_max, 0, 0); + + rmi4_data->input_settings.force_min = rmi4_data->force_min; + rmi4_data->input_settings.force_max = rmi4_data->force_max; + } +#elif defined(F51_DISCRETE_FORCE) + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_PRESSURE, 0, + FORCE_LEVEL_MAX, 0, 0); +#endif + +#ifdef TYPE_B_PROTOCOL +#ifdef KERNEL_ABOVE_3_6 + input_mt_init_slots(rmi4_data->input_dev, + rmi4_data->num_of_fingers, INPUT_MT_DIRECT); +#else + input_mt_init_slots(rmi4_data->input_dev, + rmi4_data->num_of_fingers); +#endif +#endif + + rmi4_data->input_settings.num_of_fingers = rmi4_data->num_of_fingers; + + f1a = NULL; + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) + f1a = fhandler->data; + } + } + + if (f1a) { + for (ii = 0; ii < f1a->valid_button_count; ii++) { + set_bit(f1a->button_map[ii], + rmi4_data->input_dev->keybit); + input_set_capability(rmi4_data->input_dev, + EV_KEY, f1a->button_map[ii]); + } + + rmi4_data->input_settings.valid_button_count = + f1a->valid_button_count; + } + + if (vir_button_map->nbuttons) { + for (ii = 0; ii < vir_button_map->nbuttons; ii++) { + set_bit(vir_button_map->map[ii * 5], + rmi4_data->input_dev->keybit); + input_set_capability(rmi4_data->input_dev, + EV_KEY, vir_button_map->map[ii * 5]); + } + } + + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture) { + set_bit(KEY_WAKEUP, rmi4_data->input_dev->keybit); + input_set_capability(rmi4_data->input_dev, EV_KEY, KEY_WAKEUP); + } + + return; +} + +static int synaptics_rmi4_set_input_dev(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + rmi4_data->input_dev = input_allocate_device(); + if (rmi4_data->input_dev == NULL) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate input device\n", + __func__); + retval = -ENOMEM; + goto err_input_device; + } + + retval = synaptics_rmi4_query_device(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to query device\n", + __func__); + goto err_query_device; + } + + rmi4_data->input_dev->name = PLATFORM_DRIVER_NAME; + rmi4_data->input_dev->phys = INPUT_PHYS_NAME; + rmi4_data->input_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT; + rmi4_data->input_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION; + rmi4_data->input_dev->dev.parent = rmi4_data->pdev->dev.parent; + input_set_drvdata(rmi4_data->input_dev, rmi4_data); + + set_bit(EV_SYN, rmi4_data->input_dev->evbit); + set_bit(EV_KEY, rmi4_data->input_dev->evbit); + set_bit(EV_ABS, rmi4_data->input_dev->evbit); + set_bit(BTN_TOUCH, rmi4_data->input_dev->keybit); + set_bit(BTN_TOOL_FINGER, rmi4_data->input_dev->keybit); +#ifdef INPUT_PROP_DIRECT + set_bit(INPUT_PROP_DIRECT, rmi4_data->input_dev->propbit); +#endif + + if (bdata->max_y_for_2d >= 0) + rmi4_data->sensor_max_y = bdata->max_y_for_2d; + + synaptics_rmi4_set_params(rmi4_data); + + retval = input_register_device(rmi4_data->input_dev); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to register input device\n", + __func__); + goto err_register_input; + } + + rmi4_data->input_settings.stylus_enable = rmi4_data->stylus_enable; + rmi4_data->input_settings.eraser_enable = rmi4_data->eraser_enable; + + if (!rmi4_data->stylus_enable) + return 0; + + rmi4_data->stylus_dev = input_allocate_device(); + if (rmi4_data->stylus_dev == NULL) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate stylus device\n", + __func__); + retval = -ENOMEM; + goto err_stylus_device; + } + + rmi4_data->stylus_dev->name = STYLUS_DRIVER_NAME; + rmi4_data->stylus_dev->phys = STYLUS_PHYS_NAME; + rmi4_data->stylus_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT; + rmi4_data->stylus_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION; + rmi4_data->stylus_dev->dev.parent = rmi4_data->pdev->dev.parent; + input_set_drvdata(rmi4_data->stylus_dev, rmi4_data); + + set_bit(EV_KEY, rmi4_data->stylus_dev->evbit); + set_bit(EV_ABS, rmi4_data->stylus_dev->evbit); + set_bit(BTN_TOUCH, rmi4_data->stylus_dev->keybit); + set_bit(BTN_TOOL_PEN, rmi4_data->stylus_dev->keybit); + if (rmi4_data->eraser_enable) + set_bit(BTN_TOOL_RUBBER, rmi4_data->stylus_dev->keybit); +#ifdef INPUT_PROP_DIRECT + set_bit(INPUT_PROP_DIRECT, rmi4_data->stylus_dev->propbit); +#endif + + input_set_abs_params(rmi4_data->stylus_dev, ABS_X, 0, + rmi4_data->sensor_max_x, 0, 0); + input_set_abs_params(rmi4_data->stylus_dev, ABS_Y, 0, + rmi4_data->sensor_max_y, 0, 0); + + retval = input_register_device(rmi4_data->stylus_dev); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to register stylus device\n", + __func__); + goto err_register_stylus; + } + + return 0; + +err_register_stylus: + rmi4_data->stylus_dev = NULL; + +err_stylus_device: + input_unregister_device(rmi4_data->input_dev); + rmi4_data->input_dev = NULL; + +err_register_input: +err_query_device: + synaptics_rmi4_empty_fn_list(rmi4_data); + input_free_device(rmi4_data->input_dev); + +err_input_device: + return retval; +} + +static int synaptics_rmi4_set_gpio(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + retval = synaptics_rmi4_gpio_setup( + bdata->irq_gpio, + true, 0, 0); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to configure attention GPIO\n", + __func__); + goto err_gpio_irq; + } + + if (bdata->power_gpio >= 0) { + retval = synaptics_rmi4_gpio_setup( + bdata->power_gpio, + true, 1, !bdata->power_on_state); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to configure power GPIO\n", + __func__); + goto err_gpio_power; + } + } + + if (bdata->reset_gpio >= 0) { + retval = synaptics_rmi4_gpio_setup( + bdata->reset_gpio, + true, 1, !bdata->reset_on_state); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to configure reset GPIO\n", + __func__); + goto err_gpio_reset; + } + } + + if (bdata->power_gpio >= 0) { + gpio_set_value(bdata->power_gpio, bdata->power_on_state); + msleep(bdata->power_delay_ms); + } + + if (bdata->reset_gpio >= 0) { + gpio_set_value(bdata->reset_gpio, bdata->reset_on_state); + msleep(bdata->reset_active_ms); + gpio_set_value(bdata->reset_gpio, !bdata->reset_on_state); + msleep(bdata->reset_delay_ms); + } + + return 0; + +err_gpio_reset: + if (bdata->power_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->power_gpio, false, 0, 0); + +err_gpio_power: + synaptics_rmi4_gpio_setup(bdata->irq_gpio, false, 0, 0); + +err_gpio_irq: + return retval; +} + +static int synaptics_rmi4_get_reg(struct synaptics_rmi4_data *rmi4_data, + bool get) +{ + int retval; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (!get) { + retval = 0; + goto regulator_put; + } + + if ((bdata->pwr_reg_name != NULL) && (*bdata->pwr_reg_name != 0)) { + rmi4_data->pwr_reg = regulator_get(rmi4_data->pdev->dev.parent, + bdata->pwr_reg_name); + if (IS_ERR(rmi4_data->pwr_reg)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to get power regulator\n", + __func__); + retval = PTR_ERR(rmi4_data->pwr_reg); + goto regulator_put; + } + } + + if ((bdata->bus_reg_name != NULL) && (*bdata->bus_reg_name != 0)) { + rmi4_data->bus_reg = regulator_get(rmi4_data->pdev->dev.parent, + bdata->bus_reg_name); + if (IS_ERR(rmi4_data->bus_reg)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to get bus pullup regulator\n", + __func__); + retval = PTR_ERR(rmi4_data->bus_reg); + goto regulator_put; + } + } + + return 0; + +regulator_put: + if (rmi4_data->pwr_reg) { + regulator_put(rmi4_data->pwr_reg); + rmi4_data->pwr_reg = NULL; + } + + if (rmi4_data->bus_reg) { + regulator_put(rmi4_data->bus_reg); + rmi4_data->bus_reg = NULL; + } + + return retval; +} + +static int synaptics_rmi4_enable_reg(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (!enable) { + retval = 0; + goto disable_pwr_reg; + } + + if (rmi4_data->bus_reg) { + retval = regulator_enable(rmi4_data->bus_reg); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to enable bus pullup regulator\n", + __func__); + goto exit; + } + } + + if (rmi4_data->pwr_reg) { + retval = regulator_enable(rmi4_data->pwr_reg); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to enable power regulator\n", + __func__); + goto disable_bus_reg; + } + msleep(bdata->power_delay_ms); + } + + return 0; + +disable_pwr_reg: + if (rmi4_data->pwr_reg) + regulator_disable(rmi4_data->pwr_reg); + +disable_bus_reg: + if (rmi4_data->bus_reg) + regulator_disable(rmi4_data->bus_reg); + +exit: + return retval; +} + +static int synaptics_rmi4_free_fingers(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char ii; + + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + +#ifdef TYPE_B_PROTOCOL + for (ii = 0; ii < rmi4_data->num_of_fingers; ii++) { + input_mt_slot(rmi4_data->input_dev, ii); + input_mt_report_slot_state(rmi4_data->input_dev, + MT_TOOL_FINGER, 0); + } +#endif + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 0); +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + input_sync(rmi4_data->input_dev); + + if (rmi4_data->stylus_enable) { + input_report_key(rmi4_data->stylus_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_PEN, 0); + if (rmi4_data->eraser_enable) { + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_RUBBER, 0); + } + input_sync(rmi4_data->stylus_dev); + } + + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + + rmi4_data->fingers_on_2d = false; + + return 0; +} + +static int synaptics_rmi4_sw_reset(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char command = 0x01; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_cmd_base_addr, + &command, + sizeof(command)); + if (retval < 0) + return retval; + + msleep(rmi4_data->hw_if->board_data->reset_delay_ms); + + if (rmi4_data->hw_if->ui_hw_init) { + retval = rmi4_data->hw_if->ui_hw_init(rmi4_data); + if (retval < 0) + return retval; + } + + return 0; +} + +static int synaptics_rmi4_do_rebuild(struct synaptics_rmi4_data *rmi4_data) +{ + struct synaptics_rmi4_input_settings *settings; + + settings = &(rmi4_data->input_settings); + + if (settings->num_of_fingers != rmi4_data->num_of_fingers) + return 1; + + if (settings->valid_button_count != rmi4_data->valid_button_count) + return 1; + + if (settings->max_touch_width != rmi4_data->max_touch_width) + return 1; + + if (settings->sensor_max_x != rmi4_data->sensor_max_x) + return 1; + + if (settings->sensor_max_y != rmi4_data->sensor_max_y) + return 1; + + if (settings->force_min != rmi4_data->force_min) + return 1; + + if (settings->force_max != rmi4_data->force_max) + return 1; + + if (settings->stylus_enable != rmi4_data->stylus_enable) + return 1; + + if (settings->eraser_enable != rmi4_data->eraser_enable) + return 1; + + return 0; +} + +static void synaptics_rmi4_rebuild_work(struct work_struct *work) +{ + int retval; + unsigned char attr_count; + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct delayed_work *delayed_work = + container_of(work, struct delayed_work, work); + struct synaptics_rmi4_data *rmi4_data = + container_of(delayed_work, struct synaptics_rmi4_data, + rb_work); + + mutex_lock(&(rmi4_data->rmi4_reset_mutex)); + + mutex_lock(&exp_data.mutex); + + synaptics_rmi4_irq_enable(rmi4_data, false, false); + + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->remove != NULL) + exp_fhandler->exp_fn->remove(rmi4_data); + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + synaptics_rmi4_free_fingers(rmi4_data); + synaptics_rmi4_empty_fn_list(rmi4_data); + input_unregister_device(rmi4_data->input_dev); + rmi4_data->input_dev = NULL; + if (rmi4_data->stylus_enable) { + input_unregister_device(rmi4_data->stylus_dev); + rmi4_data->stylus_dev = NULL; + } + + retval = synaptics_rmi4_set_input_dev(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set up input device\n", + __func__); + goto exit; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + goto exit; + } + } + + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->init != NULL) + exp_fhandler->exp_fn->init(rmi4_data); + } + + retval = 0; + +exit: + synaptics_rmi4_irq_enable(rmi4_data, true, false); + + mutex_unlock(&exp_data.mutex); + + mutex_unlock(&(rmi4_data->rmi4_reset_mutex)); + + return; +} + +static int synaptics_rmi4_reinit_device(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + mutex_lock(&(rmi4_data->rmi4_reset_mutex)); + + synaptics_rmi4_free_fingers(rmi4_data); + + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F12) { + synaptics_rmi4_f12_set_enables(rmi4_data, 0); + break; + } + } + } + + retval = synaptics_rmi4_int_enable(rmi4_data, true); + if (retval < 0) + goto exit; + + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->reinit != NULL) + exp_fhandler->exp_fn->reinit(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + synaptics_rmi4_set_configured(rmi4_data); + + retval = 0; + +exit: + mutex_unlock(&(rmi4_data->rmi4_reset_mutex)); + return retval; +} + +static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data, + bool rebuild) +{ + int retval; + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + + mutex_lock(&(rmi4_data->rmi4_reset_mutex)); + + synaptics_rmi4_irq_enable(rmi4_data, false, false); + + retval = synaptics_rmi4_sw_reset(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + goto exit; + } + + synaptics_rmi4_free_fingers(rmi4_data); + + synaptics_rmi4_empty_fn_list(rmi4_data); + + retval = synaptics_rmi4_query_device(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to query device\n", + __func__); + goto exit; + } + + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->reset != NULL) + exp_fhandler->exp_fn->reset(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + retval = 0; + +exit: + synaptics_rmi4_irq_enable(rmi4_data, true, false); + + mutex_unlock(&(rmi4_data->rmi4_reset_mutex)); + + if (rebuild && synaptics_rmi4_do_rebuild(rmi4_data)) { + queue_delayed_work(rmi4_data->rb_workqueue, + &rmi4_data->rb_work, + msecs_to_jiffies(REBUILD_WORK_DELAY_MS)); + } + + return retval; +} + +#ifdef FB_READY_RESET +static void synaptics_rmi4_reset_work(struct work_struct *work) +{ + int retval; + unsigned int timeout; + struct synaptics_rmi4_data *rmi4_data = + container_of(work, struct synaptics_rmi4_data, + reset_work); + + timeout = FB_READY_TIMEOUT_S * 1000 / FB_READY_WAIT_MS + 1; + + while (!rmi4_data->fb_ready) { + msleep(FB_READY_WAIT_MS); + timeout--; + if (timeout == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for FB ready\n", + __func__); + return; + } + } + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + retval = synaptics_rmi4_reset_device(rmi4_data, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + } + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + return; +} +#endif + +static void synaptics_rmi4_sleep_enable(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval; + unsigned char device_ctrl; + unsigned char no_sleep_setting = rmi4_data->no_sleep_setting; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device control\n", + __func__); + return; + } + + device_ctrl = device_ctrl & ~MASK_3BIT; + if (enable) + device_ctrl = device_ctrl | SENSOR_SLEEP; + else + device_ctrl = device_ctrl | no_sleep_setting | NORMAL_OPERATION; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write device control\n", + __func__); + return; + } + + rmi4_data->sensor_sleep = enable; + + return; +} + +static void synaptics_rmi4_exp_fn_work(struct work_struct *work) +{ + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_exp_fhandler *exp_fhandler_temp; + struct synaptics_rmi4_data *rmi4_data = exp_data.rmi4_data; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + mutex_lock(&rmi4_data->rmi4_reset_mutex); + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry_safe(exp_fhandler, + exp_fhandler_temp, + &exp_data.list, + link) { + if ((exp_fhandler->exp_fn->init != NULL) && + exp_fhandler->insert) { + exp_fhandler->exp_fn->init(rmi4_data); + exp_fhandler->insert = false; + } else if ((exp_fhandler->exp_fn->remove != NULL) && + exp_fhandler->remove) { + exp_fhandler->exp_fn->remove(rmi4_data); + list_del(&exp_fhandler->link); + kfree(exp_fhandler); + } + } + } + mutex_unlock(&exp_data.mutex); + mutex_unlock(&rmi4_data->rmi4_reset_mutex); + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + return; +} + +void synaptics_rmi4_new_function(struct synaptics_rmi4_exp_fn *exp_fn, + bool insert) +{ + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + + if (!exp_data.initialized) { + mutex_init(&exp_data.mutex); + INIT_LIST_HEAD(&exp_data.list); + exp_data.initialized = true; + } + + mutex_lock(&exp_data.mutex); + if (insert) { + exp_fhandler = kzalloc(sizeof(*exp_fhandler), GFP_KERNEL); + if (!exp_fhandler) { + pr_err("%s: Failed to alloc mem for expansion function\n", + __func__); + goto exit; + } + exp_fhandler->exp_fn = exp_fn; + exp_fhandler->insert = true; + exp_fhandler->remove = false; + list_add_tail(&exp_fhandler->link, &exp_data.list); + } else if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) { + if (exp_fhandler->exp_fn->fn_type == exp_fn->fn_type) { + exp_fhandler->insert = false; + exp_fhandler->remove = true; + goto exit; + } + } + } + +exit: + mutex_unlock(&exp_data.mutex); + + if (exp_data.queue_work) { + queue_delayed_work(exp_data.workqueue, + &exp_data.work, + msecs_to_jiffies(EXP_FN_WORK_DELAY_MS)); + } + + return; +} +EXPORT_SYMBOL(synaptics_rmi4_new_function); + +#ifdef SYNAPTICS_ESD_CHECK +void synaptics_rmi4_esd_work(struct work_struct *work) +{ + unsigned char product_info[F01_STD_QUERY_LEN]; + int retval = 0; + + +struct delayed_work *esd_work = + container_of(work, struct delayed_work, work); +struct synaptics_rmi4_data *rmi4_data = + container_of(esd_work, struct synaptics_rmi4_data, + esd_work); + + + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + printk("[synaptics]Enter %s\n", __func__); + + mutex_lock(&rmi4_data->rmi4_esd_mutex); + + pr_notice("%s: Start of esd check process\n", __func__); + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_query_base_addr, + product_info, + F01_STD_QUERY_LEN); + + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s Failed to read product info, need to do HW RESET\n", + __func__); + + gpio_set_value(bdata->reset_gpio, 1); + mdelay(20); + gpio_set_value(bdata->reset_gpio, 0); + mdelay(20); + gpio_set_value(bdata->reset_gpio, 1); + mdelay(200); + + } + + retval = synaptics_rmi4_query_device(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to query device\n", + __func__); + } + + pr_notice("%s: End of esd check process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_esd_mutex); + + queue_delayed_work(rmi4_data->esd_workqueue, &rmi4_data->esd_work, SYNAPTICS_ESD_CHECK_CIRCLE); + + return; + +} +#endif + +static int synaptics_rmi4_probe(struct platform_device *pdev) +{ + int retval; + unsigned char attr_count; + + const struct synaptics_dsx_hw_interface *hw_if; + const struct synaptics_dsx_board_data *bdata; + + hw_if = pdev->dev.platform_data; + if (!hw_if) { + dev_err(&pdev->dev, + "%s: No hardware interface found\n", + __func__); + return -EINVAL; + } + + bdata = hw_if->board_data; + if (!bdata) { + dev_err(&pdev->dev, + "%s: No board data found\n", + __func__); + return -EINVAL; + } + + rmi4_data = kzalloc(sizeof(*rmi4_data), GFP_KERNEL); + if (!rmi4_data) { + dev_err(&pdev->dev, + "%s: Failed to alloc mem for rmi4_data\n", + __func__); + return -ENOMEM; + } + + rmi4_data->pdev = pdev; + rmi4_data->current_page = MASK_8BIT; + rmi4_data->hw_if = hw_if; + rmi4_data->suspend = false; + rmi4_data->irq_enabled = false; + rmi4_data->fingers_on_2d = false; + + rmi4_data->reset_device = synaptics_rmi4_reset_device; + rmi4_data->irq_enable = synaptics_rmi4_irq_enable; + rmi4_data->sleep_enable = synaptics_rmi4_sleep_enable; + rmi4_data->report_touch = synaptics_rmi4_report_touch; + + mutex_init(&(rmi4_data->rmi4_reset_mutex)); + mutex_init(&(rmi4_data->rmi4_report_mutex)); + mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex)); + mutex_init(&(rmi4_data->rmi4_exp_init_mutex)); + mutex_init(&(rmi4_data->rmi4_irq_enable_mutex)); + mutex_init(&(rmi4_data->rmi4_esd_mutex)); + + + platform_set_drvdata(pdev, rmi4_data); + + vir_button_map = bdata->vir_button_map; + + retval = synaptics_rmi4_get_reg(rmi4_data, true); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to get regulators\n", + __func__); + goto err_get_reg; + } + + retval = synaptics_rmi4_enable_reg(rmi4_data, true); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to enable regulators\n", + __func__); + goto err_enable_reg; + } + + retval = synaptics_rmi4_set_gpio(rmi4_data); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to set up GPIO's\n", + __func__); + goto err_set_gpio; + } + + if (hw_if->ui_hw_init) { + retval = hw_if->ui_hw_init(rmi4_data); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to initialize hardware interface\n", + __func__); + goto err_ui_hw_init; + } + } + + retval = synaptics_rmi4_set_input_dev(rmi4_data); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to set up input device\n", + __func__); + goto err_set_input_dev; + } + +#ifdef CONFIG_FB + rmi4_data->fb_notifier.notifier_call = synaptics_rmi4_fb_notifier_cb; + retval = fb_register_client(&rmi4_data->fb_notifier); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to register fb notifier client\n", + __func__); + } +#endif + +#ifdef USE_EARLYSUSPEND + rmi4_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + rmi4_data->early_suspend.suspend = synaptics_rmi4_early_suspend; + rmi4_data->early_suspend.resume = synaptics_rmi4_late_resume; + register_early_suspend(&rmi4_data->early_suspend); +#endif + + if (!exp_data.initialized) { + mutex_init(&exp_data.mutex); + INIT_LIST_HEAD(&exp_data.list); + exp_data.initialized = true; + } + + rmi4_data->irq = gpio_to_irq(bdata->irq_gpio); + + retval = synaptics_rmi4_irq_enable(rmi4_data, true, false); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to enable attention interrupt\n", + __func__); + goto err_enable_irq; + } + + if (vir_button_map->nbuttons) { + rmi4_data->board_prop_dir = kobject_create_and_add( + "board_properties", NULL); + if (!rmi4_data->board_prop_dir) { + dev_err(&pdev->dev, + "%s: Failed to create board_properties directory\n", + __func__); + goto err_virtual_buttons; + } else { + retval = sysfs_create_file(rmi4_data->board_prop_dir, + &virtual_key_map_attr.attr); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to create virtual key map file\n", + __func__); + goto err_virtual_buttons; + } + } + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to create sysfs attributes\n", + __func__); + goto err_sysfs; + } + } + +#ifdef USE_DATA_SERVER + memset(&interrupt_signal, 0, sizeof(interrupt_signal)); + interrupt_signal.si_signo = SIGIO; + interrupt_signal.si_code = SI_USER; +#endif + + rmi4_data->rb_workqueue = + create_singlethread_workqueue("dsx_rebuild_workqueue"); + INIT_DELAYED_WORK(&rmi4_data->rb_work, synaptics_rmi4_rebuild_work); + + exp_data.workqueue = create_singlethread_workqueue("dsx_exp_workqueue"); + INIT_DELAYED_WORK(&exp_data.work, synaptics_rmi4_exp_fn_work); + exp_data.rmi4_data = rmi4_data; + exp_data.queue_work = true; + queue_delayed_work(exp_data.workqueue, + &exp_data.work, + 0); + +#ifdef FB_READY_RESET + rmi4_data->reset_workqueue = + create_singlethread_workqueue("dsx_reset_workqueue"); + INIT_WORK(&rmi4_data->reset_work, synaptics_rmi4_reset_work); + queue_work(rmi4_data->reset_workqueue, &rmi4_data->reset_work); +#endif + +#if 1 + input_set_capability(rmi4_data->input_dev, EV_KEY, KEY_WAKEUP); + + rmi4_data->input_dev->event = synaptics_gesture_switch; +#endif + + +#ifdef SYNAPTICS_ESD_CHECK + rmi4_data->esd_workqueue = create_singlethread_workqueue("dsx_esd_workqueue"); + INIT_DELAYED_WORK(&(rmi4_data->esd_work), synaptics_rmi4_esd_work); + queue_delayed_work(rmi4_data->esd_workqueue, &rmi4_data->esd_work, SYNAPTICS_ESD_CHECK_CIRCLE); +#endif + + return retval; + +err_sysfs: + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + +err_virtual_buttons: + if (rmi4_data->board_prop_dir) { + sysfs_remove_file(rmi4_data->board_prop_dir, + &virtual_key_map_attr.attr); + kobject_put(rmi4_data->board_prop_dir); + } + + synaptics_rmi4_irq_enable(rmi4_data, false, false); + +err_enable_irq: +#ifdef CONFIG_FB + fb_unregister_client(&rmi4_data->fb_notifier); +#endif + +#ifdef USE_EARLYSUSPEND + unregister_early_suspend(&rmi4_data->early_suspend); +#endif + + synaptics_rmi4_empty_fn_list(rmi4_data); + input_unregister_device(rmi4_data->input_dev); + rmi4_data->input_dev = NULL; + if (rmi4_data->stylus_enable) { + input_unregister_device(rmi4_data->stylus_dev); + rmi4_data->stylus_dev = NULL; + } + +err_set_input_dev: + synaptics_rmi4_gpio_setup(bdata->irq_gpio, false, 0, 0); + + if (bdata->reset_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->reset_gpio, false, 0, 0); + + if (bdata->power_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->power_gpio, false, 0, 0); + +err_ui_hw_init: +err_set_gpio: + synaptics_rmi4_enable_reg(rmi4_data, false); + +err_enable_reg: + synaptics_rmi4_get_reg(rmi4_data, false); + +err_get_reg: + kfree(rmi4_data); + + return retval; +} + +static int synaptics_rmi4_remove(struct platform_device *pdev) +{ + unsigned char attr_count; + struct synaptics_rmi4_data *rmi4_data = platform_get_drvdata(pdev); + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + +#ifdef FB_READY_RESET + cancel_work_sync(&rmi4_data->reset_work); + flush_workqueue(rmi4_data->reset_workqueue); + destroy_workqueue(rmi4_data->reset_workqueue); +#endif +printk("Enter %s\n", __func__); +#ifdef SYNAPTICS_ESD_CHECK + cancel_delayed_work_sync(&(rmi4_data->esd_work)); + flush_workqueue(rmi4_data->esd_workqueue); + destroy_workqueue(rmi4_data->esd_workqueue); +#endif + + cancel_delayed_work_sync(&exp_data.work); + flush_workqueue(exp_data.workqueue); + destroy_workqueue(exp_data.workqueue); + + cancel_delayed_work_sync(&rmi4_data->rb_work); + flush_workqueue(rmi4_data->rb_workqueue); + destroy_workqueue(rmi4_data->rb_workqueue); + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + if (rmi4_data->board_prop_dir) { + sysfs_remove_file(rmi4_data->board_prop_dir, + &virtual_key_map_attr.attr); + kobject_put(rmi4_data->board_prop_dir); + } + + synaptics_rmi4_irq_enable(rmi4_data, false, false); + +#ifdef CONFIG_FB + fb_unregister_client(&rmi4_data->fb_notifier); +#endif + +#ifdef USE_EARLYSUSPEND + unregister_early_suspend(&rmi4_data->early_suspend); +#endif + + synaptics_rmi4_empty_fn_list(rmi4_data); + input_unregister_device(rmi4_data->input_dev); + rmi4_data->input_dev = NULL; + if (rmi4_data->stylus_enable) { + input_unregister_device(rmi4_data->stylus_dev); + rmi4_data->stylus_dev = NULL; + } + + synaptics_rmi4_gpio_setup(bdata->irq_gpio, false, 0, 0); + + if (bdata->reset_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->reset_gpio, false, 0, 0); + + if (bdata->power_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->power_gpio, false, 0, 0); + + synaptics_rmi4_enable_reg(rmi4_data, false); + synaptics_rmi4_get_reg(rmi4_data, false); + + kfree(rmi4_data); + + return 0; +} + +#ifdef CONFIG_FB +static int synaptics_rmi4_fb_notifier_cb(struct notifier_block *self, + unsigned long event, void *data) +{ + int *transition; + struct fb_event *evdata = data; + struct synaptics_rmi4_data *rmi4_data = + container_of(self, struct synaptics_rmi4_data, + fb_notifier); + + if (evdata && evdata->data && rmi4_data) { + if (event == FB_EVENT_BLANK) { + transition = evdata->data; + if (*transition == FB_BLANK_POWERDOWN) { + synaptics_rmi4_suspend(&rmi4_data->pdev->dev); + rmi4_data->fb_ready = false; + } else if (*transition == FB_BLANK_UNBLANK) { + synaptics_rmi4_resume(&rmi4_data->pdev->dev); + rmi4_data->fb_ready = true; + } + } + } + + return 0; +} +#endif + +#ifdef USE_EARLYSUSPEND +static void synaptics_rmi4_early_suspend(struct early_suspend *h) +{ + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_data *rmi4_data = + container_of(h, struct synaptics_rmi4_data, + early_suspend); + unsigned char device_ctrl; + + if (rmi4_data->stay_awake) + return; + + + if (rmi4_data->enable_wakeup_gesture) { + if (rmi4_data->no_sleep_setting) { + synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + } + synaptics_rmi4_wakeup_gesture(rmi4_data, true); + enable_irq_wake(rmi4_data->irq); + goto exit; + } + +#ifdef SYNA_TDDI + if (rmi4_data->no_sleep_setting) { + synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + } + synaptics_rmi4_wakeup_gesture(rmi4_data, true); + udelay(TDDI_LPWG_WAIT_US); +#endif + synaptics_rmi4_irq_enable(rmi4_data, false, false); + synaptics_rmi4_sleep_enable(rmi4_data, true); + synaptics_rmi4_free_fingers(rmi4_data); + +exit: + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->early_suspend != NULL) + exp_fhandler->exp_fn->early_suspend(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + rmi4_data->suspend = true; + + return; +} + +static void synaptics_rmi4_late_resume(struct early_suspend *h) +{ +#ifdef FB_READY_RESET + int retval; +#endif + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_data *rmi4_data = + container_of(h, struct synaptics_rmi4_data, + early_suspend); + + if (rmi4_data->stay_awake) + return; + + if (rmi4_data->enable_wakeup_gesture) { + disable_irq_wake(rmi4_data->irq); + goto exit; + } + + rmi4_data->current_page = MASK_8BIT; + + if (rmi4_data->suspend) { + synaptics_rmi4_sleep_enable(rmi4_data, false); + synaptics_rmi4_irq_enable(rmi4_data, true, false); + } + +exit: +#ifdef FB_READY_RESET + if (rmi4_data->suspend) { + retval = synaptics_rmi4_reset_device(rmi4_data, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + } + } +#endif + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->late_resume != NULL) + exp_fhandler->exp_fn->late_resume(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + rmi4_data->suspend = false; + + return; +} +#endif + +static int synaptics_rmi4_suspend(struct device *dev) +{ + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + unsigned char device_ctrl; + + if (rmi4_data->stay_awake) + return 0; + printk("[synaptics]Enter %s\n", __func__); + +#ifdef SYNAPTICS_ESD_CHECK + cancel_delayed_work_sync(&(rmi4_data->esd_work)); +#endif + + + if (rmi4_data->enable_wakeup_gesture) { + printk("enable_wakeup_gesture is on\n"); + if (rmi4_data->no_sleep_setting) { + synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + } + synaptics_rmi4_wakeup_gesture(rmi4_data, true); + enable_irq_wake(rmi4_data->irq); + goto exit; + } + + if (!rmi4_data->suspend) { +#ifdef SYNA_TDDI + if (rmi4_data->no_sleep_setting) { + synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + } + synaptics_rmi4_wakeup_gesture(rmi4_data, false); + udelay(TDDI_LPWG_WAIT_US); +#endif + synaptics_rmi4_irq_enable(rmi4_data, false, false); + synaptics_rmi4_sleep_enable(rmi4_data, true); + synaptics_rmi4_free_fingers(rmi4_data); + } + +exit: + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->suspend != NULL) + exp_fhandler->exp_fn->suspend(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + rmi4_data->suspend = true; + + return 0; +} + +static int synaptics_rmi4_resume(struct device *dev) +{ +#ifdef FB_READY_RESET + int retval; +#endif + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + if (rmi4_data->stay_awake) + return 0; + + if (rmi4_data->enable_wakeup_gesture) { + disable_irq_wake(rmi4_data->irq); + synaptics_rmi4_wakeup_gesture(rmi4_data, false); + goto exit; + } + + rmi4_data->current_page = MASK_8BIT; + + synaptics_rmi4_sleep_enable(rmi4_data, false); + synaptics_rmi4_irq_enable(rmi4_data, true, false); + msleep(50); +#ifdef SYNAPTICS_ESD_CHECK + printk("SYNAPTICS_ESD_CHECK is on\n"); + queue_delayed_work(rmi4_data->esd_workqueue, &(rmi4_data->esd_work), SYNAPTICS_ESD_CHECK_CIRCLE); +#endif + msleep(50); + + +exit: +#ifdef FB_READY_RESET + retval = synaptics_rmi4_reset_device(rmi4_data, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + } +#endif + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->resume != NULL) + exp_fhandler->exp_fn->resume(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + rmi4_data->suspend = false; + + + return 0; +} + +#ifdef CONFIG_PM +static const struct dev_pm_ops synaptics_rmi4_dev_pm_ops = { +#ifndef CONFIG_FB + .suspend = synaptics_rmi4_suspend, + .resume = synaptics_rmi4_resume, +#endif +}; +#endif + +static struct platform_driver synaptics_rmi4_driver = { + .driver = { + .name = PLATFORM_DRIVER_NAME, + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &synaptics_rmi4_dev_pm_ops, +#endif + }, + .probe = synaptics_rmi4_probe, + .remove = synaptics_rmi4_remove, +}; + +static int __init synaptics_rmi4_init(void) +{ + int retval; + + retval = synaptics_rmi4_bus_init(); + if (retval) + return retval; + + return platform_driver_register(&synaptics_rmi4_driver); +} + +static void __exit synaptics_rmi4_exit(void) +{ + platform_driver_unregister(&synaptics_rmi4_driver); + + synaptics_rmi4_bus_exit(); + + return; +} + +module_init(synaptics_rmi4_init); +module_exit(synaptics_rmi4_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX Touch Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310/synaptics_dsx_core.h b/drivers/input/touchscreen/td4310/synaptics_dsx_core.h new file mode 100644 index 0000000000000..b120b7ff9810c --- /dev/null +++ b/drivers/input/touchscreen/td4310/synaptics_dsx_core.h @@ -0,0 +1,537 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#ifndef _SYNAPTICS_DSX_RMI4_H_ +#define _SYNAPTICS_DSX_RMI4_H_ + +#define SYNAPTICS_DS4 (1 << 0) +#define SYNAPTICS_DS5 (1 << 1) +#define SYNAPTICS_DSX_DRIVER_PRODUCT (SYNAPTICS_DS4 | SYNAPTICS_DS5) +#define SYNAPTICS_DSX_DRIVER_VERSION 0x2070 + +#include +#ifdef CONFIG_FB +#include +#include +#endif +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)) +#define KERNEL_ABOVE_2_6_38 +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) +#define KERNEL_ABOVE_3_6 +#endif + +#ifdef KERNEL_ABOVE_2_6_38 +#define sstrtoul(...) kstrtoul(__VA_ARGS__) +#else +#define sstrtoul(...) strict_strtoul(__VA_ARGS__) +#endif + + +#ifdef SYNAPTICS_ESD_CHECK +#define SYNAPTICS_ESD_CHECK_CIRCLE 2*HZ +#endif + + +/* +#define F51_DISCRETE_FORCE +#ifdef F51_DISCRETE_FORCE +#define FORCE_LEVEL_ADDR 0x0419 +#define FORCE_LEVEL_MAX 255 +#define CAL_DATA_SIZE 144 +#endif +#define SYNA_TDDI +*/ +#define SYNA_TDDI +#define PDT_PROPS (0X00EF) +#define PDT_START (0x00E9) +#define PDT_END (0x00D0) +#define PDT_ENTRY_SIZE (0x0006) +#define PAGES_TO_SERVICE (10) +#define PAGE_SELECT_LEN (2) +#define ADDRESS_LEN (2) + +#define SYNAPTICS_RMI4_F01 (0x01) +#define SYNAPTICS_RMI4_F11 (0x11) +#define SYNAPTICS_RMI4_F12 (0x12) +#define SYNAPTICS_RMI4_F1A (0x1A) +#define SYNAPTICS_RMI4_F21 (0x21) +#define SYNAPTICS_RMI4_F34 (0x34) +#define SYNAPTICS_RMI4_F35 (0x35) +#define SYNAPTICS_RMI4_F38 (0x38) +#define SYNAPTICS_RMI4_F51 (0x51) +#define SYNAPTICS_RMI4_F54 (0x54) +#define SYNAPTICS_RMI4_F55 (0x55) +#define SYNAPTICS_RMI4_FDB (0xDB) + +#define PRODUCT_INFO_SIZE 2 +#define PRODUCT_ID_SIZE 10 +#define BUILD_ID_SIZE 3 + +#define F12_FINGERS_TO_SUPPORT 10 +#define F12_NO_OBJECT_STATUS 0x00 +#define F12_FINGER_STATUS 0x01 +#define F12_ACTIVE_STYLUS_STATUS 0x02 +#define F12_PALM_STATUS 0x03 +#define F12_HOVERING_FINGER_STATUS 0x05 +#define F12_GLOVED_FINGER_STATUS 0x06 +#define F12_NARROW_OBJECT_STATUS 0x07 +#define F12_HAND_EDGE_STATUS 0x08 +#define F12_COVER_STATUS 0x0A +#define F12_STYLUS_STATUS 0x0B +#define F12_ERASER_STATUS 0x0C +#define F12_SMALL_OBJECT_STATUS 0x0D + +#define F12_GESTURE_DETECTION_LEN 5 + +#define MAX_NUMBER_OF_BUTTONS 4 +#define MAX_INTR_REGISTERS 4 + +#define MASK_16BIT 0xFFFF +#define MASK_8BIT 0xFF +#define MASK_7BIT 0x7F +#define MASK_6BIT 0x3F +#define MASK_5BIT 0x1F +#define MASK_4BIT 0x0F +#define MASK_3BIT 0x07 +#define MASK_2BIT 0x03 +#define MASK_1BIT 0x01 + +enum exp_fn { + RMI_DEV = 0, + RMI_FW_UPDATER, + RMI_TEST_REPORTING, + RMI_PROXIMITY, + RMI_ACTIVE_PEN, + RMI_GESTURE, + RMI_VIDEO, + RMI_DEBUG, + RMI_LAST, +}; + +/* + * struct synaptics_rmi4_fn_desc - function descriptor fields in PDT entry + * @query_base_addr: base address for query registers + * @cmd_base_addr: base address for command registers + * @ctrl_base_addr: base address for control registers + * @data_base_addr: base address for data registers + * @intr_src_count: number of interrupt sources + * @fn_version: version of function + * @fn_number: function number + */ +struct synaptics_rmi4_fn_desc { + union { + struct { + unsigned char query_base_addr; + unsigned char cmd_base_addr; + unsigned char ctrl_base_addr; + unsigned char data_base_addr; + unsigned char intr_src_count:3; + unsigned char reserved_1:2; + unsigned char fn_version:2; + unsigned char reserved_2:1; + unsigned char fn_number; + } __packed; + unsigned char data[6]; + }; +}; + +/* + * synaptics_rmi4_fn_full_addr - full 16-bit base addresses + * @query_base: 16-bit base address for query registers + * @cmd_base: 16-bit base address for command registers + * @ctrl_base: 16-bit base address for control registers + * @data_base: 16-bit base address for data registers + */ +struct synaptics_rmi4_fn_full_addr { + unsigned short query_base; + unsigned short cmd_base; + unsigned short ctrl_base; + unsigned short data_base; +}; + +/* + * struct synaptics_rmi4_f11_extra_data - extra data of F$11 + * @data38_offset: offset to F11_2D_DATA38 register + */ +struct synaptics_rmi4_f11_extra_data { + unsigned char data38_offset; +}; + +/* + * struct synaptics_rmi4_f12_extra_data - extra data of F$12 + * @data1_offset: offset to F12_2D_DATA01 register + * @data4_offset: offset to F12_2D_DATA04 register + * @data15_offset: offset to F12_2D_DATA15 register + * @data15_size: size of F12_2D_DATA15 register + * @data15_data: buffer for reading F12_2D_DATA15 register + * @data29_offset: offset to F12_2D_DATA29 register + * @data29_size: size of F12_2D_DATA29 register + * @data29_data: buffer for reading F12_2D_DATA29 register + * @ctrl20_offset: offset to F12_2D_CTRL20 register + */ +struct synaptics_rmi4_f12_extra_data { + unsigned char data1_offset; + unsigned char data4_offset; + unsigned char data15_offset; + unsigned char data15_size; + unsigned char data15_data[(F12_FINGERS_TO_SUPPORT + 7) / 8]; + unsigned char data29_offset; + unsigned char data29_size; + unsigned char data29_data[F12_FINGERS_TO_SUPPORT * 2]; + unsigned char ctrl20_offset; +}; + +/* + * struct synaptics_rmi4_fn - RMI function handler + * @fn_number: function number + * @num_of_data_sources: number of data sources + * @num_of_data_points: maximum number of fingers supported + * @intr_reg_num: index to associated interrupt register + * @intr_mask: interrupt mask + * @full_addr: full 16-bit base addresses of function registers + * @link: linked list for function handlers + * @data_size: size of private data + * @data: pointer to private data + * @extra: pointer to extra data + */ +struct synaptics_rmi4_fn { + unsigned char fn_number; + unsigned char num_of_data_sources; + unsigned char num_of_data_points; + unsigned char intr_reg_num; + unsigned char intr_mask; + struct synaptics_rmi4_fn_full_addr full_addr; + struct list_head link; + int data_size; + void *data; + void *extra; +}; + +/* + * struct synaptics_rmi4_input_settings - current input settings + * @num_of_fingers: maximum number of fingers for 2D touch + * @valid_button_count: number of valid 0D buttons + * @max_touch_width: maximum touch width + * @sensor_max_x: maximum x coordinate for 2D touch + * @sensor_max_y: maximum y coordinate for 2D touch + * @force_min: minimum force value + * @force_max: maximum force value + * @stylus_enable: flag to indicate reporting of stylus data + * @eraser_enable: flag to indicate reporting of eraser data + */ +struct synaptics_rmi4_input_settings { + unsigned char num_of_fingers; + unsigned char valid_button_count; + unsigned char max_touch_width; + int sensor_max_x; + int sensor_max_y; + int force_min; + int force_max; + bool stylus_enable; + bool eraser_enable; +}; + +/* + * struct synaptics_rmi4_device_info - device information + * @version_major: RMI protocol major version number + * @version_minor: RMI protocol minor version number + * @manufacturer_id: manufacturer ID + * @product_props: product properties + * @product_info: product information + * @product_id_string: product ID + * @build_id: firmware build ID + * @support_fn_list: linked list for function handlers + */ +struct synaptics_rmi4_device_info { + unsigned int version_major; + unsigned int version_minor; + unsigned char manufacturer_id; + unsigned char product_props; + unsigned char product_info[PRODUCT_INFO_SIZE]; + unsigned char product_id_string[PRODUCT_ID_SIZE + 1]; + unsigned char build_id[BUILD_ID_SIZE]; + struct list_head support_fn_list; +}; + +/* + * struct synaptics_rmi4_data - RMI4 device instance data + * @pdev: pointer to platform device + * @input_dev: pointer to associated input device + * @stylus_dev: pointer to associated stylus device + * @hw_if: pointer to hardware interface data + * @rmi4_mod_info: device information + * @board_prop_dir: /sys/board_properties directory for virtual key map file + * @pwr_reg: pointer to regulator for power control + * @bus_reg: pointer to regulator for bus pullup control + * @rmi4_reset_mutex: mutex for software reset + * @rmi4_report_mutex: mutex for input event reporting + * @rmi4_io_ctrl_mutex: mutex for communication interface I/O + * @rmi4_exp_init_mutex: mutex for expansion function module initialization + * @rmi4_irq_enable_mutex: mutex for enabling/disabling interrupt + * @rb_work: work for rebuilding input device + * @rb_workqueue: workqueue for rebuilding input device + * @fb_notifier: framebuffer notifier client + * @reset_work: work for issuing reset after display framebuffer ready + * @reset_workqueue: workqueue for issuing reset after display framebuffer ready + * @early_suspend: early suspend power management + * @current_page: current RMI page for register access + * @button_0d_enabled: switch for enabling 0d button support + * @num_of_tx: number of Tx channels for 2D touch + * @num_of_rx: number of Rx channels for 2D touch + * @num_of_fingers: maximum number of fingers for 2D touch + * @max_touch_width: maximum touch width + * @valid_button_count: number of valid 0D buttons + * @report_enable: input data to report for F$12 + * @no_sleep_setting: default setting of NoSleep in F01_RMI_CTRL00 register + * @gesture_detection: detected gesture type and properties + * @intr_mask: interrupt enable mask + * @button_txrx_mapping: Tx Rx mapping of 0D buttons + * @num_of_intr_regs: number of interrupt registers + * @f01_query_base_addr: query base address for f$01 + * @f01_cmd_base_addr: command base address for f$01 + * @f01_ctrl_base_addr: control base address for f$01 + * @f01_data_base_addr: data base address for f$01 + * @f51_query_base_addr: query base address for f$51 + * @firmware_id: firmware build ID + * @irq: attention interrupt + * @sensor_max_x: maximum x coordinate for 2D touch + * @sensor_max_y: maximum y coordinate for 2D touch + * @force_min: minimum force value + * @force_max: maximum force value + * @flash_prog_mode: flag to indicate flash programming mode status + * @irq_enabled: flag to indicate attention interrupt enable status + * @fingers_on_2d: flag to indicate presence of fingers in 2D area + * @suspend: flag to indicate whether in suspend state + * @sensor_sleep: flag to indicate sleep state of sensor + * @stay_awake: flag to indicate whether to stay awake during suspend + * @fb_ready: flag to indicate whether display framebuffer in ready state + * @f11_wakeup_gesture: flag to indicate support for wakeup gestures in F$11 + * @f12_wakeup_gesture: flag to indicate support for wakeup gestures in F$12 + * @enable_wakeup_gesture: flag to indicate usage of wakeup gestures + * @wedge_sensor: flag to indicate use of wedge sensor + * @report_pressure: flag to indicate reporting of pressure data + * @stylus_enable: flag to indicate reporting of stylus data + * @eraser_enable: flag to indicate reporting of eraser data + * @external_afe_buttons: flag to indicate presence of external AFE buttons + * @reset_device: pointer to device reset function + * @irq_enable: pointer to interrupt enable function + * @sleep_enable: pointer to sleep enable function + * @report_touch: pointer to touch reporting function + */ +struct synaptics_rmi4_data { + struct platform_device *pdev; + struct input_dev *input_dev; + struct input_dev *stylus_dev; + const struct synaptics_dsx_hw_interface *hw_if; + struct synaptics_rmi4_device_info rmi4_mod_info; + struct synaptics_rmi4_input_settings input_settings; + struct kobject *board_prop_dir; + struct regulator *pwr_reg; + struct regulator *bus_reg; + struct mutex rmi4_reset_mutex; + struct mutex rmi4_report_mutex; + struct mutex rmi4_io_ctrl_mutex; + struct mutex rmi4_exp_init_mutex; + struct mutex rmi4_irq_enable_mutex; + struct mutex rmi4_esd_mutex; + struct delayed_work rb_work; + struct workqueue_struct *rb_workqueue; +#ifdef CONFIG_FB + struct notifier_block fb_notifier; + struct work_struct reset_work; + struct workqueue_struct *reset_workqueue; +#endif +#ifdef SYNAPTICS_ESD_CHECK + struct delayed_work esd_work; + struct workqueue_struct *esd_workqueue; +#endif + +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif + unsigned char current_page; + unsigned char button_0d_enabled; + unsigned char num_of_tx; + unsigned char num_of_rx; + unsigned char num_of_fingers; + unsigned char max_touch_width; + unsigned char valid_button_count; + unsigned char report_enable; + unsigned char no_sleep_setting; + unsigned char gesture_detection[F12_GESTURE_DETECTION_LEN]; + unsigned char intr_mask[MAX_INTR_REGISTERS]; + unsigned char *button_txrx_mapping; + unsigned short num_of_intr_regs; + unsigned short f01_query_base_addr; + unsigned short f01_cmd_base_addr; + unsigned short f01_ctrl_base_addr; + unsigned short f01_data_base_addr; +#ifdef F51_DISCRETE_FORCE + unsigned short f51_query_base_addr; +#endif + unsigned int firmware_id; + int irq; + int sensor_max_x; + int sensor_max_y; + int force_min; + int force_max; + bool flash_prog_mode; + bool irq_enabled; + bool fingers_on_2d; + bool suspend; + bool sensor_sleep; + bool stay_awake; + bool fb_ready; + bool f11_wakeup_gesture; + bool f12_wakeup_gesture; + bool enable_wakeup_gesture; + bool wedge_sensor; + bool report_pressure; + bool stylus_enable; + bool eraser_enable; + bool external_afe_buttons; + int (*reset_device)(struct synaptics_rmi4_data *rmi4_data, + bool rebuild); + int (*irq_enable)(struct synaptics_rmi4_data *rmi4_data, bool enable, + bool attn_only); + void (*sleep_enable)(struct synaptics_rmi4_data *rmi4_data, + bool enable); + void (*report_touch)(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler); +}; + +struct synaptics_dsx_bus_access { + unsigned char type; + int (*read)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr, + unsigned char *data, unsigned int length); + int (*write)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr, + unsigned char *data, unsigned int length); +}; + +struct synaptics_dsx_hw_interface { + struct synaptics_dsx_board_data *board_data; + const struct synaptics_dsx_bus_access *bus_access; + int (*bl_hw_init)(struct synaptics_rmi4_data *rmi4_data); + int (*ui_hw_init)(struct synaptics_rmi4_data *rmi4_data); +}; + +struct synaptics_rmi4_exp_fn { + enum exp_fn fn_type; + int (*init)(struct synaptics_rmi4_data *rmi4_data); + void (*remove)(struct synaptics_rmi4_data *rmi4_data); + void (*reset)(struct synaptics_rmi4_data *rmi4_data); + void (*reinit)(struct synaptics_rmi4_data *rmi4_data); + void (*early_suspend)(struct synaptics_rmi4_data *rmi4_data); + void (*suspend)(struct synaptics_rmi4_data *rmi4_data); + void (*resume)(struct synaptics_rmi4_data *rmi4_data); + void (*late_resume)(struct synaptics_rmi4_data *rmi4_data); + void (*attn)(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask); +}; + +int synaptics_rmi4_bus_init(void); + +void synaptics_rmi4_bus_exit(void); + +void synaptics_rmi4_new_function(struct synaptics_rmi4_exp_fn *exp_fn_module, + bool insert); + +int synaptics_fw_updater(const unsigned char *fw_data); + +static inline int synaptics_rmi4_reg_read( + struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, + unsigned char *data, + unsigned int len) +{ + return rmi4_data->hw_if->bus_access->read(rmi4_data, addr, data, len); +} + +static inline int synaptics_rmi4_reg_write( + struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, + unsigned char *data, + unsigned int len) +{ + return rmi4_data->hw_if->bus_access->write(rmi4_data, addr, data, len); +} + +static inline ssize_t synaptics_rmi4_show_error(struct device *dev, + struct device_attribute *attr, char *buf) +{ + dev_warn(dev, "%s Attempted to read from write-only attribute %s\n", + __func__, attr->attr.name); + return -EPERM; +} + +static inline ssize_t synaptics_rmi4_store_error(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + dev_warn(dev, "%s Attempted to write to read-only attribute %s\n", + __func__, attr->attr.name); + return -EPERM; +} + +static inline int secure_memcpy(unsigned char *dest, unsigned int dest_size, + const unsigned char *src, unsigned int src_size, + unsigned int count) +{ + if (dest == NULL || src == NULL) + return -EINVAL; + + if (count > dest_size || count > src_size) + return -EINVAL; + + memcpy((void *)dest, (const void *)src, count); + + return 0; +} + +static inline void batohs(unsigned short *dest, unsigned char *src) +{ + *dest = src[1] * 0x100 + src[0]; +} + +static inline void hstoba(unsigned char *dest, unsigned short src) +{ + dest[0] = src % 0x100; + dest[1] = src / 0x100; +} + +#endif diff --git a/drivers/input/touchscreen/td4310/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/td4310/synaptics_dsx_fw_update.c new file mode 100644 index 0000000000000..34cd53fbcf5d0 --- /dev/null +++ b/drivers/input/touchscreen/td4310/synaptics_dsx_fw_update.c @@ -0,0 +1,5990 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" +#include + + +#define FW_IHEX_NAME "synaptics/startup_fw_update.bin" +#define FW_IMAGE_NAME "synaptics/startup_fw_update.img" + +#define DO_STARTUP_FW_UPDATE + +#define SYNAPTICS_LOCK_DOWN_INFO + +#ifdef DO_STARTUP_FW_UPDATE +#ifdef CONFIG_FB +#define WAIT_FOR_FB_READY +#define FB_READY_WAIT_MS 100 +#define FB_READY_TIMEOUT_S 30 +#endif +#endif + + +#define MAX_WRITE_SIZE 4096 + + +#define ENABLE_SYS_REFLASH true +#define FORCE_UPDATE false +#define DO_LOCKDOWN false + +#define MAX_IMAGE_NAME_LEN 256 +#define MAX_FIRMWARE_ID_LEN 10 + +#define IMAGE_HEADER_VERSION_05 0x05 +#define IMAGE_HEADER_VERSION_06 0x06 +#define IMAGE_HEADER_VERSION_10 0x10 + +#define IMAGE_AREA_OFFSET 0x100 +#define LOCKDOWN_SIZE 0x50 + +#define MAX_UTILITY_PARAMS 20 + +#define V5V6_BOOTLOADER_ID_OFFSET 0 +#define V5V6_CONFIG_ID_SIZE 4 + +#define V5_PROPERTIES_OFFSET 2 +#define V5_BLOCK_SIZE_OFFSET 3 +#define V5_BLOCK_COUNT_OFFSET 5 +#define V5_BLOCK_NUMBER_OFFSET 0 +#define V5_BLOCK_DATA_OFFSET 2 + +#define V6_PROPERTIES_OFFSET 1 +#define V6_BLOCK_SIZE_OFFSET 2 +#define V6_BLOCK_COUNT_OFFSET 3 +#define V6_PROPERTIES_2_OFFSET 4 +#define V6_GUEST_CODE_BLOCK_COUNT_OFFSET 5 +#define V6_BLOCK_NUMBER_OFFSET 0 +#define V6_BLOCK_DATA_OFFSET 1 +#define V6_FLASH_COMMAND_OFFSET 2 +#define V6_FLASH_STATUS_OFFSET 3 + +#define V7_CONFIG_ID_SIZE 32 + +#define V7_FLASH_STATUS_OFFSET 0 +#define V7_PARTITION_ID_OFFSET 1 +#define V7_BLOCK_NUMBER_OFFSET 2 +#define V7_TRANSFER_LENGTH_OFFSET 3 +#define V7_COMMAND_OFFSET 4 +#define V7_PAYLOAD_OFFSET 5 + +#define V7_PARTITION_SUPPORT_BYTES 4 + +#define F35_ERROR_CODE_OFFSET 0 +#define F35_FLASH_STATUS_OFFSET 5 +#define F35_CHUNK_NUM_LSB_OFFSET 0 +#define F35_CHUNK_NUM_MSB_OFFSET 1 +#define F35_CHUNK_DATA_OFFSET 2 +#define F35_CHUNK_COMMAND_OFFSET 18 + +#define F35_CHUNK_SIZE 16 +#define F35_ERASE_ALL_WAIT_MS 5000 +#define F35_RESET_WAIT_MS 250 + +#define SLEEP_MODE_NORMAL (0x00) +#define SLEEP_MODE_SENSOR_SLEEP (0x01) +#define SLEEP_MODE_RESERVED0 (0x02) +#define SLEEP_MODE_RESERVED1 (0x03) + +#define ENABLE_WAIT_MS (1 * 1000) +#define WRITE_WAIT_MS (3 * 1000) +#define ERASE_WAIT_MS (5 * 1000) + +#define MIN_SLEEP_TIME_US 50 +#define MAX_SLEEP_TIME_US 100 + +#define INT_DISABLE_WAIT_MS 20 +#define ENTER_FLASH_PROG_WAIT_MS 20 +#define READ_CONFIG_WAIT_MS 20 + +static int fwu_do_reflash(void); + +static int fwu_recovery_check_status(void); + +static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t fwu_sysfs_store_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t fwu_sysfs_do_recovery_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_write_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_read_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_config_area_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_image_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_image_size_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_block_size_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_utility_parameter_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_guest_code_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_read_guest_serialization_show(struct device *dev, + struct device_attribute *attr, char *buf); + +#ifdef SYNA_TDDI +static ssize_t fwu_sysfs_write_lockdown_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_read_lockdown_code_show(struct device *dev, + struct device_attribute *attr, char *buf); + +#endif + +enum f34_version { + F34_V0 = 0, + F34_V1, + F34_V2, +}; + +enum bl_version { + BL_V5 = 5, + BL_V6 = 6, + BL_V7 = 7, + BL_V8 = 8, +}; + +enum flash_area { + NONE = 0, + UI_FIRMWARE, + UI_CONFIG, +}; + +enum update_mode { + NORMAL = 1, + FORCE = 2, + LOCKDOWN = 8, +}; + +enum config_area { + UI_CONFIG_AREA = 0, + PM_CONFIG_AREA, + BL_CONFIG_AREA, + DP_CONFIG_AREA, + FLASH_CONFIG_AREA, +#ifdef SYNA_TDDI + TDDI_FORCE_CONFIG_AREA, + TDDI_LCM_DATA_AREA, + TDDI_OEM_DATA_AREA, +#endif + UPP_AREA, +}; + +enum v7_status { + SUCCESS = 0x00, + DEVICE_NOT_IN_BOOTLOADER_MODE, + INVALID_PARTITION, + INVALID_COMMAND, + INVALID_BLOCK_OFFSET, + INVALID_TRANSFER, + NOT_ERASED, + FLASH_PROGRAMMING_KEY_INCORRECT, + BAD_PARTITION_TABLE, + CHECKSUM_FAILED, + FLASH_HARDWARE_FAILURE = 0x1f, +}; + +enum v7_partition_id { + BOOTLOADER_PARTITION = 0x01, + DEVICE_CONFIG_PARTITION, + FLASH_CONFIG_PARTITION, + MANUFACTURING_BLOCK_PARTITION, + GUEST_SERIALIZATION_PARTITION, + GLOBAL_PARAMETERS_PARTITION, + CORE_CODE_PARTITION, + CORE_CONFIG_PARTITION, + GUEST_CODE_PARTITION, + DISPLAY_CONFIG_PARTITION, + EXTERNAL_TOUCH_AFE_CONFIG_PARTITION, + UTILITY_PARAMETER_PARTITION, +}; + +enum v7_flash_command { + CMD_V7_IDLE = 0x00, + CMD_V7_ENTER_BL, + CMD_V7_READ, + CMD_V7_WRITE, + CMD_V7_ERASE, + CMD_V7_ERASE_AP, + CMD_V7_SENSOR_ID, +}; + +enum v5v6_flash_command { + CMD_V5V6_IDLE = 0x0, + CMD_V5V6_WRITE_FW = 0x2, + CMD_V5V6_ERASE_ALL = 0x3, + CMD_V5V6_WRITE_LOCKDOWN = 0x4, + CMD_V5V6_READ_CONFIG = 0x5, + CMD_V5V6_WRITE_CONFIG = 0x6, + CMD_V5V6_ERASE_UI_CONFIG = 0x7, + CMD_V5V6_ERASE_BL_CONFIG = 0x9, + CMD_V5V6_ERASE_DISP_CONFIG = 0xa, + CMD_V5V6_ERASE_GUEST_CODE = 0xb, + CMD_V5V6_WRITE_GUEST_CODE = 0xc, + CMD_V5V6_ERASE_CHIP = 0x0d, + CMD_V5V6_ENABLE_FLASH_PROG = 0xf, +#ifdef SYNA_TDDI + CMD_V5V6_ERASE_FORCE_CONFIG = 0x11, + CMD_V5V6_READ_FORCE_CONFIG = 0x12, + CMD_V5V6_WRITE_FORCE_CONFIG = 0x13, + CMD_V5V6_ERASE_LOCKDOWN_DATA = 0x1a, + CMD_V5V6_READ_LOCKDOWN_DATA = 0x1b, + CMD_V5V6_WRITE_LOCKDOWN_DATA = 0x1c, + CMD_V5V6_ERASE_LCM_DATA = 0x1d, + CMD_V5V6_ERASE_OEM_DATA = 0x1e, +#endif +}; + +enum flash_command { + CMD_IDLE = 0, + CMD_WRITE_FW, + CMD_WRITE_CONFIG, + CMD_WRITE_LOCKDOWN, + CMD_WRITE_GUEST_CODE, + CMD_WRITE_BOOTLOADER, + CMD_WRITE_UTILITY_PARAM, + CMD_READ_CONFIG, + CMD_ERASE_ALL, + CMD_ERASE_UI_FIRMWARE, + CMD_ERASE_UI_CONFIG, + CMD_ERASE_BL_CONFIG, + CMD_ERASE_DISP_CONFIG, + CMD_ERASE_FLASH_CONFIG, + CMD_ERASE_GUEST_CODE, + CMD_ERASE_BOOTLOADER, + CMD_ERASE_UTILITY_PARAMETER, + CMD_ENABLE_FLASH_PROG, +#ifdef SYNA_TDDI + CMD_ERASE_CHIP, + CMD_ERASE_FORCE_CONFIG, + CMD_READ_FORCE_CONFIG, + CMD_WRITE_FORCE_CONFIG, + CMD_ERASE_LOCKDOWN_DATA, + CMD_READ_LOCKDOWN_DATA, + CMD_WRITE_LOCKDOWN_DATA, + CMD_ERASE_LCM_DATA, + CMD_READ_LCM_DATA, + CMD_WRITE_LCM_DATA, + CMD_ERASE_OEM_DATA, + CMD_READ_OEM_DATA, + CMD_WRITE_OEM_DATA, +#endif +}; + +enum f35_flash_command { + CMD_F35_IDLE = 0x0, + CMD_F35_RESERVED = 0x1, + CMD_F35_WRITE_CHUNK = 0x2, + CMD_F35_ERASE_ALL = 0x3, + CMD_F35_RESET = 0x10, +}; + +enum container_id { + TOP_LEVEL_CONTAINER = 0, + UI_CONTAINER, + UI_CONFIG_CONTAINER, + BL_CONTAINER, + BL_IMAGE_CONTAINER, + BL_CONFIG_CONTAINER, + BL_LOCKDOWN_INFO_CONTAINER, + PERMANENT_CONFIG_CONTAINER, + GUEST_CODE_CONTAINER, + BL_PROTOCOL_DESCRIPTOR_CONTAINER, + UI_PROTOCOL_DESCRIPTOR_CONTAINER, + RMI_SELF_DISCOVERY_CONTAINER, + RMI_PAGE_CONTENT_CONTAINER, + GENERAL_INFORMATION_CONTAINER, + DEVICE_CONFIG_CONTAINER, + FLASH_CONFIG_CONTAINER, + GUEST_SERIALIZATION_CONTAINER, + GLOBAL_PARAMETERS_CONTAINER, + CORE_CODE_CONTAINER, + CORE_CONFIG_CONTAINER, + DISPLAY_CONFIG_CONTAINER, + EXTERNAL_TOUCH_AFE_CONFIG_CONTAINER, + UTILITY_CONTAINER, + UTILITY_PARAMETER_CONTAINER, +}; + +enum utility_parameter_id { + UNUSED = 0, + FORCE_PARAMETER, + ANTI_BENDING_PARAMETER, +}; + +struct pdt_properties { + union { + struct { + unsigned char reserved_1:6; + unsigned char has_bsr:1; + unsigned char reserved_2:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct partition_table { + unsigned char partition_id:5; + unsigned char byte_0_reserved:3; + unsigned char byte_1_reserved; + unsigned char partition_length_7_0; + unsigned char partition_length_15_8; + unsigned char start_physical_address_7_0; + unsigned char start_physical_address_15_8; + unsigned char partition_properties_7_0; + unsigned char partition_properties_15_8; +} __packed; + +struct f01_device_control { + union { + struct { + unsigned char sleep_mode:2; + unsigned char nosleep:1; + unsigned char reserved:2; + unsigned char charger_connected:1; + unsigned char report_rate:1; + unsigned char configured:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v7_query_0 { + union { + struct { + unsigned char subpacket_1_size:3; + unsigned char has_config_id:1; + unsigned char f34_query0_b4:1; + unsigned char has_thqa:1; + unsigned char f34_query0_b6__7:2; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v7_query_1_7 { + union { + struct { + /* query 1 */ + unsigned char bl_minor_revision; + unsigned char bl_major_revision; + + /* query 2 */ + unsigned char bl_fw_id_7_0; + unsigned char bl_fw_id_15_8; + unsigned char bl_fw_id_23_16; + unsigned char bl_fw_id_31_24; + + /* query 3 */ + unsigned char minimum_write_size; + unsigned char block_size_7_0; + unsigned char block_size_15_8; + unsigned char flash_page_size_7_0; + unsigned char flash_page_size_15_8; + + /* query 4 */ + unsigned char adjustable_partition_area_size_7_0; + unsigned char adjustable_partition_area_size_15_8; + + /* query 5 */ + unsigned char flash_config_length_7_0; + unsigned char flash_config_length_15_8; + + /* query 6 */ + unsigned char payload_length_7_0; + unsigned char payload_length_15_8; + + /* query 7 */ + unsigned char f34_query7_b0:1; + unsigned char has_bootloader:1; + unsigned char has_device_config:1; + unsigned char has_flash_config:1; + unsigned char has_manufacturing_block:1; + unsigned char has_guest_serialization:1; + unsigned char has_global_parameters:1; + unsigned char has_core_code:1; + unsigned char has_core_config:1; + unsigned char has_guest_code:1; + unsigned char has_display_config:1; + unsigned char f34_query7_b11__15:5; + unsigned char f34_query7_b16__23; + unsigned char f34_query7_b24__31; + } __packed; + unsigned char data[21]; + }; +}; + +struct f34_v7_data0 { + union { + struct { + unsigned char operation_status:5; + unsigned char device_cfg_status:2; + unsigned char bl_mode:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v7_data_1_5 { + union { + struct { + unsigned char partition_id:5; + unsigned char f34_data1_b5__7:3; + unsigned char block_offset_7_0; + unsigned char block_offset_15_8; + unsigned char transfer_length_7_0; + unsigned char transfer_length_15_8; + unsigned char command; + unsigned char payload_0; + unsigned char payload_1; + } __packed; + unsigned char data[8]; + }; +}; + +struct f34_v5v6_flash_properties { + union { + struct { + unsigned char reg_map:1; + unsigned char unlocked:1; + unsigned char has_config_id:1; + unsigned char has_pm_config:1; + unsigned char has_bl_config:1; + unsigned char has_disp_config:1; + unsigned char has_ctrl1:1; + unsigned char has_query4:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v5v6_flash_properties_2 { + union { + struct { + unsigned char has_guest_code:1; + unsigned char f34_query4_b1:1; + unsigned char has_gesture_config:1; + unsigned char has_force_config:1; + unsigned char has_lockdown_data:1; + unsigned char has_lcm_data:1; + unsigned char has_oem_data:1; + unsigned char f34_query4_b7:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct register_offset { + unsigned char properties; + unsigned char properties_2; + unsigned char block_size; + unsigned char block_count; + unsigned char gc_block_count; + unsigned char flash_status; + unsigned char partition_id; + unsigned char block_number; + unsigned char transfer_length; + unsigned char flash_cmd; + unsigned char payload; +}; + +struct block_count { + unsigned short ui_firmware; + unsigned short ui_config; + unsigned short dp_config; + unsigned short pm_config; + unsigned short fl_config; + unsigned short bl_image; + unsigned short bl_config; + unsigned short utility_param; + unsigned short lockdown; + unsigned short guest_code; +#ifdef SYNA_TDDI + unsigned short tddi_force_config; + unsigned short tddi_lockdown_data; + unsigned short tddi_lcm_data; + unsigned short tddi_oem_data; +#endif + unsigned short total_count; +}; + +struct physical_address { + unsigned short ui_firmware; + unsigned short ui_config; + unsigned short dp_config; + unsigned short pm_config; + unsigned short fl_config; + unsigned short bl_image; + unsigned short bl_config; + unsigned short utility_param; + unsigned short lockdown; + unsigned short guest_code; +}; + +struct container_descriptor { + unsigned char content_checksum[4]; + unsigned char container_id[2]; + unsigned char minor_version; + unsigned char major_version; + unsigned char reserved_08; + unsigned char reserved_09; + unsigned char reserved_0a; + unsigned char reserved_0b; + unsigned char container_option_flags[4]; + unsigned char content_options_length[4]; + unsigned char content_options_address[4]; + unsigned char content_length[4]; + unsigned char content_address[4]; +}; + +struct image_header_10 { + unsigned char checksum[4]; + unsigned char reserved_04; + unsigned char reserved_05; + unsigned char minor_header_version; + unsigned char major_header_version; + unsigned char reserved_08; + unsigned char reserved_09; + unsigned char reserved_0a; + unsigned char reserved_0b; + unsigned char top_level_container_start_addr[4]; +}; + +struct image_header_05_06 { + /* 0x00 - 0x0f */ + unsigned char checksum[4]; + unsigned char reserved_04; + unsigned char reserved_05; + unsigned char options_firmware_id:1; + unsigned char options_bootloader:1; + unsigned char options_guest_code:1; + unsigned char options_tddi:1; + unsigned char options_reserved:4; + unsigned char header_version; + unsigned char firmware_size[4]; + unsigned char config_size[4]; + /* 0x10 - 0x1f */ + unsigned char product_id[PRODUCT_ID_SIZE]; + unsigned char package_id[2]; + unsigned char package_id_revision[2]; + unsigned char product_info[PRODUCT_INFO_SIZE]; + /* 0x20 - 0x2f */ + unsigned char bootloader_addr[4]; + unsigned char bootloader_size[4]; + unsigned char ui_addr[4]; + unsigned char ui_size[4]; + /* 0x30 - 0x3f */ + unsigned char ds_id[16]; + /* 0x40 - 0x4f */ + union { + struct { + unsigned char cstmr_product_id[PRODUCT_ID_SIZE]; + unsigned char reserved_4a_4f[6]; + }; + struct { + unsigned char dsp_cfg_addr[4]; + unsigned char dsp_cfg_size[4]; + unsigned char reserved_48_4f[8]; + }; + }; + /* 0x50 - 0x53 */ + unsigned char firmware_id[4]; +}; + +struct block_data { + unsigned int size; + const unsigned char *data; +}; + +struct image_metadata { + bool contains_firmware_id; + bool contains_bootloader; + bool contains_guest_code; + bool contains_disp_config; + bool contains_perm_config; + bool contains_flash_config; + bool contains_utility_param; + unsigned int firmware_id; + unsigned int checksum; + unsigned int bootloader_size; + unsigned int disp_config_offset; + unsigned char bl_version; + unsigned char product_id[PRODUCT_ID_SIZE + 1]; + unsigned char cstmr_product_id[PRODUCT_ID_SIZE + 1]; + unsigned char utility_param_id[MAX_UTILITY_PARAMS]; + struct block_data bootloader; + struct block_data utility; + struct block_data ui_firmware; + struct block_data ui_config; + struct block_data dp_config; + struct block_data pm_config; + struct block_data fl_config; + struct block_data bl_image; + struct block_data bl_config; + struct block_data utility_param[MAX_UTILITY_PARAMS]; + struct block_data lockdown; + struct block_data guest_code; + struct block_count blkcount; + struct physical_address phyaddr; +}; + +struct synaptics_rmi4_fwu_handle { + enum bl_version bl_version; + bool initialized; + bool in_bl_mode; + bool in_ub_mode; + bool bl_mode_device; + bool force_update; + bool do_lockdown; + bool has_guest_code; +#ifdef SYNA_TDDI + bool has_force_config; + bool has_lockdown_data; + bool has_lcm_data; + bool has_oem_data; +#endif + bool has_utility_param; + bool new_partition_table; + bool incompatible_partition_tables; + bool write_bootloader; + unsigned int data_pos; + unsigned char *ext_data_source; + unsigned char *read_config_buf; + unsigned char intr_mask; + unsigned char command; + unsigned char bootloader_id[2]; + unsigned char config_id[32]; + unsigned char flash_status; + unsigned char partitions; +#ifdef F51_DISCRETE_FORCE + unsigned char *cal_data; + unsigned short cal_data_off; + unsigned short cal_data_size; + unsigned short cal_data_buf_size; + unsigned short cal_packet_data_size; +#endif + unsigned short block_size; + unsigned short config_size; + unsigned short config_area; + unsigned short config_block_count; + unsigned short flash_config_length; + unsigned short payload_length; + unsigned short partition_table_bytes; + unsigned short read_config_buf_size; + const unsigned char *config_data; + const unsigned char *image; + unsigned char *image_name; + unsigned int image_size; + struct image_metadata img; + struct register_offset off; + struct block_count blkcount; + struct physical_address phyaddr; + struct f34_v5v6_flash_properties flash_properties; + struct synaptics_rmi4_fn_desc f34_fd; + struct synaptics_rmi4_fn_desc f35_fd; + struct synaptics_rmi4_data *rmi4_data; + struct workqueue_struct *fwu_workqueue; + struct work_struct fwu_work; +}; + +static struct bin_attribute dev_attr_data = { + .attr = { + .name = "data", + .mode = (S_IRUGO | S_IWUSR | S_IWGRP), + }, + .size = 0, + .read = fwu_sysfs_show_image, + .write = fwu_sysfs_store_image, +}; + +static struct device_attribute attrs[] = { + __ATTR(dorecovery, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_do_recovery_store), + __ATTR(doreflash, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_do_reflash_store), + __ATTR(writeconfig, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_write_config_store), + __ATTR(readconfig, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_read_config_store), + __ATTR(configarea, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_config_area_store), + __ATTR(imagename, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_image_name_store), + __ATTR(imagesize, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_image_size_store), + __ATTR(blocksize, S_IRUGO, + fwu_sysfs_block_size_show, + synaptics_rmi4_store_error), + __ATTR(fwblockcount, S_IRUGO, + fwu_sysfs_firmware_block_count_show, + synaptics_rmi4_store_error), + __ATTR(configblockcount, S_IRUGO, + fwu_sysfs_configuration_block_count_show, + synaptics_rmi4_store_error), + __ATTR(dispconfigblockcount, S_IRUGO, + fwu_sysfs_disp_config_block_count_show, + synaptics_rmi4_store_error), + __ATTR(permconfigblockcount, S_IRUGO, + fwu_sysfs_perm_config_block_count_show, + synaptics_rmi4_store_error), + __ATTR(blconfigblockcount, S_IRUGO, + fwu_sysfs_bl_config_block_count_show, + synaptics_rmi4_store_error), + __ATTR(uppblockcount, S_IRUGO, + fwu_sysfs_utility_parameter_block_count_show, + synaptics_rmi4_store_error), + __ATTR(guestcodeblockcount, S_IRUGO, + fwu_sysfs_guest_code_block_count_show, + synaptics_rmi4_store_error), + __ATTR(writeguestcode, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_write_guest_code_store), + __ATTR(guestserialization, S_IRUGO, + fwu_sysfs_read_guest_serialization_show, + synaptics_rmi4_store_error), + +#ifdef SYNA_TDDI + __ATTR(lockdowncode, (S_IWUSR | S_IWGRP | S_IRUGO), + fwu_sysfs_read_lockdown_code_show, + fwu_sysfs_write_lockdown_code_store), +#endif +}; + +static struct synaptics_rmi4_fwu_handle *fwu; + +#if defined(SYNAPTICS_LOCK_DOWN_INFO) +#define CTP_PROC_LOCKDOWN_FILE "tp_lockdown_info" +DEFINE_MUTEX(fwu_sysfs_mutex); +static struct proc_dir_entry *ctp_lockdown_status_proc; +static char tp_lockdown_info[128]; + +static int fwu_do_read_customer_serialization_data(void); + +static int ctp_lockdown_proc_show(struct seq_file *file, void *data) +{ + char temp[40] = {0}; + fwu_do_read_customer_serialization_data(); + + sprintf(temp, "%s\n", tp_lockdown_info); + seq_printf(file, "%s\n", temp); + + return 0; + + +} + +static int ctp_lockdown_proc_open (struct inode *inode, struct file *file) +{ + return single_open(file, ctp_lockdown_proc_show, inode->i_private); +} + +static const struct file_operations ctp_lockdown_proc_fops = { + .open = ctp_lockdown_proc_open, + .read = seq_read, +}; +#endif +DECLARE_COMPLETION(fwu_remove_complete); + + + +static void calculate_checksum(unsigned short *data, unsigned long len, + unsigned long *result) +{ + unsigned long temp; + unsigned long sum1 = 0xffff; + unsigned long sum2 = 0xffff; + + *result = 0xffffffff; + + while (len--) { + temp = *data; + sum1 += temp; + sum2 += sum1; + sum1 = (sum1 & 0xffff) + (sum1 >> 16); + sum2 = (sum2 & 0xffff) + (sum2 >> 16); + data++; + } + + *result = sum2 << 16 | sum1; + + return; +} + +static void convert_to_little_endian(unsigned char *dest, unsigned long src) +{ + dest[0] = (unsigned char)(src & 0xff); + dest[1] = (unsigned char)((src >> 8) & 0xff); + dest[2] = (unsigned char)((src >> 16) & 0xff); + dest[3] = (unsigned char)((src >> 24) & 0xff); + + return; +} + +static unsigned int le_to_uint(const unsigned char *ptr) +{ + return (unsigned int)ptr[0] + + (unsigned int)ptr[1] * 0x100 + + (unsigned int)ptr[2] * 0x10000 + + (unsigned int)ptr[3] * 0x1000000; +} + +#ifdef F51_DISCRETE_FORCE +static int fwu_f51_force_data_init(void) +{ + int retval; + unsigned char query_count; + unsigned char packet_info; + unsigned char offset[2]; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f51_query_base_addr + 7, + offset, + sizeof(offset)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read force data offset\n", + __func__); + return retval; + } + + fwu->cal_data_off = offset[0] | offset[1] << 8; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f51_query_base_addr, + &query_count, + sizeof(query_count)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read number of F51 query registers\n", + __func__); + return retval; + } + + if (query_count >= 10) { + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f51_query_base_addr + 9, + &packet_info, + sizeof(packet_info)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F51 packet register info\n", + __func__); + return retval; + } + + if (packet_info & MASK_1BIT) { + fwu->cal_packet_data_size = packet_info >> 1; + fwu->cal_packet_data_size *= 2; + } else { + fwu->cal_packet_data_size = 0; + } + } else { + fwu->cal_packet_data_size = 0; + } + + fwu->cal_data_size = CAL_DATA_SIZE + fwu->cal_packet_data_size; + if (fwu->cal_data_size > fwu->cal_data_buf_size) { + kfree(fwu->cal_data); + fwu->cal_data_buf_size = fwu->cal_data_size; + fwu->cal_data = kmalloc(fwu->cal_data_buf_size, GFP_KERNEL); + if (!fwu->cal_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu->cal_data\n", + __func__); + fwu->cal_data_buf_size = 0; + return -ENOMEM; + } + } + + return 0; +} +#endif + +static int fwu_allocate_read_config_buf(unsigned int count) +{ + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (count > fwu->read_config_buf_size) { + kfree(fwu->read_config_buf); + fwu->read_config_buf = kzalloc(count, GFP_KERNEL); + if (!fwu->read_config_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu->read_config_buf\n", + __func__); + fwu->read_config_buf_size = 0; + return -ENOMEM; + } + fwu->read_config_buf_size = count; + } + + return 0; +} + +static void fwu_compare_partition_tables(void) +{ + fwu->incompatible_partition_tables = false; + + if (fwu->phyaddr.bl_image != fwu->img.phyaddr.bl_image) + fwu->incompatible_partition_tables = true; + else if (fwu->phyaddr.lockdown != fwu->img.phyaddr.lockdown) + fwu->incompatible_partition_tables = true; + else if (fwu->phyaddr.bl_config != fwu->img.phyaddr.bl_config) + fwu->incompatible_partition_tables = true; + else if (fwu->phyaddr.utility_param != fwu->img.phyaddr.utility_param) + fwu->incompatible_partition_tables = true; + + if (fwu->bl_version == BL_V7) { + if (fwu->phyaddr.fl_config != fwu->img.phyaddr.fl_config) + fwu->incompatible_partition_tables = true; + } + + fwu->new_partition_table = false; + + if (fwu->phyaddr.ui_firmware != fwu->img.phyaddr.ui_firmware) + fwu->new_partition_table = true; + else if (fwu->phyaddr.ui_config != fwu->img.phyaddr.ui_config) + fwu->new_partition_table = true; + + if (fwu->flash_properties.has_disp_config) { + if (fwu->phyaddr.dp_config != fwu->img.phyaddr.dp_config) + fwu->new_partition_table = true; + } + + if (fwu->has_guest_code) { + if (fwu->phyaddr.guest_code != fwu->img.phyaddr.guest_code) + fwu->new_partition_table = true; + } + + return; +} + +static void fwu_parse_partition_table(const unsigned char *partition_table, + struct block_count *blkcount, struct physical_address *phyaddr) +{ + unsigned char ii; + unsigned char index; + unsigned char offset; + unsigned short partition_length; + unsigned short physical_address; + struct partition_table *ptable; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + for (ii = 0; ii < fwu->partitions; ii++) { + index = ii * 8 + 2; + ptable = (struct partition_table *)&partition_table[index]; + partition_length = ptable->partition_length_15_8 << 8 | + ptable->partition_length_7_0; + physical_address = ptable->start_physical_address_15_8 << 8 | + ptable->start_physical_address_7_0; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Partition entry %d:\n", + __func__, ii); + for (offset = 0; offset < 8; offset++) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: 0x%02x\n", + __func__, + partition_table[index + offset]); + } + switch (ptable->partition_id) { + case CORE_CODE_PARTITION: + blkcount->ui_firmware = partition_length; + phyaddr->ui_firmware = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Core code block count: %d\n", + __func__, blkcount->ui_firmware); + blkcount->total_count += partition_length; + break; + case CORE_CONFIG_PARTITION: + blkcount->ui_config = partition_length; + phyaddr->ui_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Core config block count: %d\n", + __func__, blkcount->ui_config); + blkcount->total_count += partition_length; + break; + case BOOTLOADER_PARTITION: + blkcount->bl_image = partition_length; + phyaddr->bl_image = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Bootloader block count: %d\n", + __func__, blkcount->bl_image); + blkcount->total_count += partition_length; + break; + case UTILITY_PARAMETER_PARTITION: + blkcount->utility_param = partition_length; + phyaddr->utility_param = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Utility parameter block count: %d\n", + __func__, blkcount->utility_param); + blkcount->total_count += partition_length; + break; + case DISPLAY_CONFIG_PARTITION: + blkcount->dp_config = partition_length; + phyaddr->dp_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Display config block count: %d\n", + __func__, blkcount->dp_config); + blkcount->total_count += partition_length; + break; + case FLASH_CONFIG_PARTITION: + blkcount->fl_config = partition_length; + phyaddr->fl_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Flash config block count: %d\n", + __func__, blkcount->fl_config); + blkcount->total_count += partition_length; + break; + case GUEST_CODE_PARTITION: + blkcount->guest_code = partition_length; + phyaddr->guest_code = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Guest code block count: %d\n", + __func__, blkcount->guest_code); + blkcount->total_count += partition_length; + break; + case GUEST_SERIALIZATION_PARTITION: + blkcount->pm_config = partition_length; + phyaddr->pm_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Guest serialization block count: %d\n", + __func__, blkcount->pm_config); + blkcount->total_count += partition_length; + break; + case GLOBAL_PARAMETERS_PARTITION: + blkcount->bl_config = partition_length; + phyaddr->bl_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Global parameters block count: %d\n", + __func__, blkcount->bl_config); + blkcount->total_count += partition_length; + break; + case DEVICE_CONFIG_PARTITION: + blkcount->lockdown = partition_length; + phyaddr->lockdown = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Device config block count: %d\n", + __func__, blkcount->lockdown); + blkcount->total_count += partition_length; + break; + }; + } + + return; +} + +static void fwu_parse_image_header_10_utility(const unsigned char *image) +{ + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int container_id; + unsigned int length; + const unsigned char *content; + struct container_descriptor *descriptor; + + num_of_containers = fwu->img.utility.size / 4; + + for (ii = 0; ii < num_of_containers; ii++) { + if (ii >= MAX_UTILITY_PARAMS) + continue; + addr = le_to_uint(fwu->img.utility.data + (ii * 4)); + descriptor = (struct container_descriptor *)(image + addr); + container_id = descriptor->container_id[0] | + descriptor->container_id[1] << 8; + content = image + le_to_uint(descriptor->content_address); + length = le_to_uint(descriptor->content_length); + switch (container_id) { + case UTILITY_PARAMETER_CONTAINER: + fwu->img.utility_param[ii].data = content; + fwu->img.utility_param[ii].size = length; + fwu->img.utility_param_id[ii] = content[0]; + break; + default: + break; + }; + } + + return; +} + +static void fwu_parse_image_header_10_bootloader(const unsigned char *image) +{ + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int container_id; + unsigned int length; + const unsigned char *content; + struct container_descriptor *descriptor; + + num_of_containers = (fwu->img.bootloader.size - 4) / 4; + + for (ii = 1; ii <= num_of_containers; ii++) { + addr = le_to_uint(fwu->img.bootloader.data + (ii * 4)); + descriptor = (struct container_descriptor *)(image + addr); + container_id = descriptor->container_id[0] | + descriptor->container_id[1] << 8; + content = image + le_to_uint(descriptor->content_address); + length = le_to_uint(descriptor->content_length); + switch (container_id) { + case BL_IMAGE_CONTAINER: + fwu->img.bl_image.data = content; + fwu->img.bl_image.size = length; + break; + case BL_CONFIG_CONTAINER: + case GLOBAL_PARAMETERS_CONTAINER: + fwu->img.bl_config.data = content; + fwu->img.bl_config.size = length; + break; + case BL_LOCKDOWN_INFO_CONTAINER: + case DEVICE_CONFIG_CONTAINER: + fwu->img.lockdown.data = content; + fwu->img.lockdown.size = length; + break; + default: + break; + }; + } + + return; +} + +static void fwu_parse_image_header_10(void) +{ + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int offset; + unsigned int container_id; + unsigned int length; + const unsigned char *image; + const unsigned char *content; + struct container_descriptor *descriptor; + struct image_header_10 *header; + + image = fwu->image; + header = (struct image_header_10 *)image; + + fwu->img.checksum = le_to_uint(header->checksum); + + /* address of top level container */ + offset = le_to_uint(header->top_level_container_start_addr); + descriptor = (struct container_descriptor *)(image + offset); + + /* address of top level container content */ + offset = le_to_uint(descriptor->content_address); + num_of_containers = le_to_uint(descriptor->content_length) / 4; + + for (ii = 0; ii < num_of_containers; ii++) { + addr = le_to_uint(image + offset); + offset += 4; + descriptor = (struct container_descriptor *)(image + addr); + container_id = descriptor->container_id[0] | + descriptor->container_id[1] << 8; + content = image + le_to_uint(descriptor->content_address); + length = le_to_uint(descriptor->content_length); + switch (container_id) { + case UI_CONTAINER: + case CORE_CODE_CONTAINER: + fwu->img.ui_firmware.data = content; + fwu->img.ui_firmware.size = length; + break; + case UI_CONFIG_CONTAINER: + case CORE_CONFIG_CONTAINER: + fwu->img.ui_config.data = content; + fwu->img.ui_config.size = length; + break; + case BL_CONTAINER: + fwu->img.bl_version = *content; + fwu->img.bootloader.data = content; + fwu->img.bootloader.size = length; + fwu_parse_image_header_10_bootloader(image); + break; + case UTILITY_CONTAINER: + fwu->img.utility.data = content; + fwu->img.utility.size = length; + fwu_parse_image_header_10_utility(image); + break; + case GUEST_CODE_CONTAINER: + fwu->img.contains_guest_code = true; + fwu->img.guest_code.data = content; + fwu->img.guest_code.size = length; + break; + case DISPLAY_CONFIG_CONTAINER: + fwu->img.contains_disp_config = true; + fwu->img.dp_config.data = content; + fwu->img.dp_config.size = length; + break; + case PERMANENT_CONFIG_CONTAINER: + case GUEST_SERIALIZATION_CONTAINER: + fwu->img.contains_perm_config = true; + fwu->img.pm_config.data = content; + fwu->img.pm_config.size = length; + break; + case FLASH_CONFIG_CONTAINER: + fwu->img.contains_flash_config = true; + fwu->img.fl_config.data = content; + fwu->img.fl_config.size = length; + break; + case GENERAL_INFORMATION_CONTAINER: + fwu->img.contains_firmware_id = true; + fwu->img.firmware_id = le_to_uint(content + 4); + break; + default: + break; + } + } + + return; +} + +static void fwu_parse_image_header_05_06(void) +{ + int retval; + const unsigned char *image; + struct image_header_05_06 *header; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + image = fwu->image; + header = (struct image_header_05_06 *)image; + + fwu->img.checksum = le_to_uint(header->checksum); + + fwu->img.bl_version = header->header_version; + + fwu->img.contains_bootloader = header->options_bootloader; + if (fwu->img.contains_bootloader) + fwu->img.bootloader_size = le_to_uint(header->bootloader_size); + + fwu->img.ui_firmware.size = le_to_uint(header->firmware_size); + if (fwu->img.ui_firmware.size) { + fwu->img.ui_firmware.data = image + IMAGE_AREA_OFFSET; + if (fwu->img.contains_bootloader) + fwu->img.ui_firmware.data += fwu->img.bootloader_size; + } + + if ((fwu->img.bl_version == BL_V6) && header->options_tddi) + fwu->img.ui_firmware.data = image + IMAGE_AREA_OFFSET; + + fwu->img.ui_config.size = le_to_uint(header->config_size); + if (fwu->img.ui_config.size) { + fwu->img.ui_config.data = fwu->img.ui_firmware.data + + fwu->img.ui_firmware.size; + } + + if (fwu->img.contains_bootloader || header->options_tddi) + fwu->img.contains_disp_config = true; + else + fwu->img.contains_disp_config = false; + + if (fwu->img.contains_disp_config) { + fwu->img.disp_config_offset = le_to_uint(header->dsp_cfg_addr); + fwu->img.dp_config.size = le_to_uint(header->dsp_cfg_size); + fwu->img.dp_config.data = image + fwu->img.disp_config_offset; + } else { + retval = secure_memcpy(fwu->img.cstmr_product_id, + sizeof(fwu->img.cstmr_product_id), + header->cstmr_product_id, + sizeof(header->cstmr_product_id), + PRODUCT_ID_SIZE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy custom product ID string\n", + __func__); + } + fwu->img.cstmr_product_id[PRODUCT_ID_SIZE] = 0; + } + + fwu->img.contains_firmware_id = header->options_firmware_id; + if (fwu->img.contains_firmware_id) + fwu->img.firmware_id = le_to_uint(header->firmware_id); + + retval = secure_memcpy(fwu->img.product_id, + sizeof(fwu->img.product_id), + header->product_id, + sizeof(header->product_id), + PRODUCT_ID_SIZE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy product ID string\n", + __func__); + } + fwu->img.product_id[PRODUCT_ID_SIZE] = 0; + + fwu->img.lockdown.size = LOCKDOWN_SIZE; + fwu->img.lockdown.data = image + IMAGE_AREA_OFFSET - LOCKDOWN_SIZE; + + return; +} + +static int fwu_parse_image_info(void) +{ + struct image_header_10 *header; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + header = (struct image_header_10 *)fwu->image; + + memset(&fwu->img, 0x00, sizeof(fwu->img)); + + switch (header->major_header_version) { + case IMAGE_HEADER_VERSION_10: + fwu_parse_image_header_10(); + break; + case IMAGE_HEADER_VERSION_05: + case IMAGE_HEADER_VERSION_06: + fwu_parse_image_header_05_06(); + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Unsupported image file format (0x%02x)\n", + __func__, header->major_header_version); + return -EINVAL; + } + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) { + if (!fwu->img.contains_flash_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No flash config found in firmware image\n", + __func__); + return -EINVAL; + } + + fwu_parse_partition_table(fwu->img.fl_config.data, + &fwu->img.blkcount, &fwu->img.phyaddr); + + if (fwu->img.blkcount.utility_param) + fwu->img.contains_utility_param = true; + + fwu_compare_partition_tables(); + } else { + fwu->new_partition_table = false; + fwu->incompatible_partition_tables = false; + } + + return 0; +} + +static int fwu_read_flash_status(void) +{ + int retval; + unsigned char status; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.data_base_addr + fwu->off.flash_status, + &status, + sizeof(status)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash status\n", + __func__); + return retval; + } + + fwu->in_bl_mode = status >> 7; + + if (fwu->bl_version == BL_V5) + fwu->flash_status = (status >> 4) & MASK_3BIT; + else if (fwu->bl_version == BL_V6) + fwu->flash_status = status & MASK_3BIT; + else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + fwu->flash_status = status & MASK_5BIT; + + if (fwu->write_bootloader) + fwu->flash_status = 0x00; + + if (fwu->flash_status != 0x00) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash status = %d, command = 0x%02x\n", + __func__, fwu->flash_status, fwu->command); + } + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) { + if (fwu->flash_status == 0x08) + fwu->flash_status = 0x00; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.data_base_addr + fwu->off.flash_cmd, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash command\n", + __func__); + return retval; + } + + if (fwu->bl_version == BL_V5) + fwu->command = command & MASK_4BIT; + else if (fwu->bl_version == BL_V6) + fwu->command = command & MASK_6BIT; + else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + fwu->command = command; + + if (fwu->write_bootloader) + fwu->command = 0x00; + + return 0; +} + +static int fwu_wait_for_idle(int timeout_ms, bool poll) +{ + int count = 0; + int timeout_count = ((timeout_ms * 1000) / MAX_SLEEP_TIME_US) + 1; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + do { + usleep_range(MIN_SLEEP_TIME_US, MAX_SLEEP_TIME_US); + + count++; + if (poll || (count == timeout_count)) + fwu_read_flash_status(); + + if ((fwu->command == CMD_IDLE) && (fwu->flash_status == 0x00)) + return 0; + } while (count < timeout_count); + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for idle status\n", + __func__); + + return -ETIMEDOUT; +} + +static int fwu_write_f34_v7_command_single_transaction(unsigned char cmd) +{ + int retval; + unsigned char data_base; + struct f34_v7_data_1_5 data_1_5; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + memset(data_1_5.data, 0x00, sizeof(data_1_5.data)); + + switch (cmd) { + case CMD_ERASE_ALL: + data_1_5.partition_id = CORE_CODE_PARTITION; + data_1_5.command = CMD_V7_ERASE_AP; + break; + case CMD_ERASE_UI_FIRMWARE: + data_1_5.partition_id = CORE_CODE_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_BL_CONFIG: + data_1_5.partition_id = GLOBAL_PARAMETERS_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_UI_CONFIG: + data_1_5.partition_id = CORE_CONFIG_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_DISP_CONFIG: + data_1_5.partition_id = DISPLAY_CONFIG_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_FLASH_CONFIG: + data_1_5.partition_id = FLASH_CONFIG_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_GUEST_CODE: + data_1_5.partition_id = GUEST_CODE_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_BOOTLOADER: + data_1_5.partition_id = BOOTLOADER_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_UTILITY_PARAMETER: + data_1_5.partition_id = UTILITY_PARAMETER_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ENABLE_FLASH_PROG: + data_1_5.partition_id = BOOTLOADER_PARTITION; + data_1_5.command = CMD_V7_ENTER_BL; + break; + }; + + data_1_5.payload_0 = fwu->bootloader_id[0]; + data_1_5.payload_1 = fwu->bootloader_id[1]; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.partition_id, + data_1_5.data, + sizeof(data_1_5.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write single transaction command\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_write_f34_v7_command(unsigned char cmd) +{ + int retval; + unsigned char data_base; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + switch (cmd) { + case CMD_WRITE_FW: + case CMD_WRITE_CONFIG: + case CMD_WRITE_LOCKDOWN: + case CMD_WRITE_GUEST_CODE: + case CMD_WRITE_BOOTLOADER: + case CMD_WRITE_UTILITY_PARAM: + command = CMD_V7_WRITE; + break; + case CMD_READ_CONFIG: + command = CMD_V7_READ; + break; + case CMD_ERASE_ALL: + command = CMD_V7_ERASE_AP; + break; + case CMD_ERASE_UI_FIRMWARE: + case CMD_ERASE_BL_CONFIG: + case CMD_ERASE_UI_CONFIG: + case CMD_ERASE_DISP_CONFIG: + case CMD_ERASE_FLASH_CONFIG: + case CMD_ERASE_GUEST_CODE: + case CMD_ERASE_BOOTLOADER: + case CMD_ERASE_UTILITY_PARAMETER: + command = CMD_V7_ERASE; + break; + case CMD_ENABLE_FLASH_PROG: + command = CMD_V7_ENTER_BL; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid command 0x%02x\n", + __func__, cmd); + return -EINVAL; + }; + + fwu->command = command; + + switch (cmd) { + case CMD_ERASE_ALL: + case CMD_ERASE_UI_FIRMWARE: + case CMD_ERASE_BL_CONFIG: + case CMD_ERASE_UI_CONFIG: + case CMD_ERASE_DISP_CONFIG: + case CMD_ERASE_FLASH_CONFIG: + case CMD_ERASE_GUEST_CODE: + case CMD_ERASE_BOOTLOADER: + case CMD_ERASE_UTILITY_PARAMETER: + case CMD_ENABLE_FLASH_PROG: + retval = fwu_write_f34_v7_command_single_transaction(cmd); + if (retval < 0) + return retval; + else + return 0; + default: + break; + }; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.flash_cmd, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write flash command\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_write_f34_v5v6_command(unsigned char cmd) +{ + int retval; + unsigned char data_base; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + switch (cmd) { + case CMD_IDLE: + command = CMD_V5V6_IDLE; + break; + case CMD_WRITE_FW: + command = CMD_V5V6_WRITE_FW; + break; + case CMD_WRITE_CONFIG: + command = CMD_V5V6_WRITE_CONFIG; + break; + case CMD_WRITE_LOCKDOWN: + command = CMD_V5V6_WRITE_LOCKDOWN; + break; + case CMD_WRITE_GUEST_CODE: + command = CMD_V5V6_WRITE_GUEST_CODE; + break; + case CMD_READ_CONFIG: + command = CMD_V5V6_READ_CONFIG; + break; + case CMD_ERASE_ALL: + command = CMD_V5V6_ERASE_ALL; + break; + case CMD_ERASE_UI_CONFIG: + command = CMD_V5V6_ERASE_UI_CONFIG; + break; + case CMD_ERASE_DISP_CONFIG: + command = CMD_V5V6_ERASE_DISP_CONFIG; + break; + case CMD_ERASE_GUEST_CODE: + command = CMD_V5V6_ERASE_GUEST_CODE; + break; + case CMD_ENABLE_FLASH_PROG: + command = CMD_V5V6_ENABLE_FLASH_PROG; + break; +#ifdef SYNA_TDDI + case CMD_ERASE_CHIP: + command = CMD_V5V6_ERASE_CHIP; + break; + case CMD_ERASE_FORCE_CONFIG: + command = CMD_V5V6_ERASE_FORCE_CONFIG; + break; + case CMD_READ_FORCE_CONFIG: + command = CMD_V5V6_READ_FORCE_CONFIG; + break; + case CMD_WRITE_FORCE_CONFIG: + command = CMD_V5V6_WRITE_CONFIG; + break; + case CMD_ERASE_LOCKDOWN_DATA: + command = CMD_V5V6_ERASE_LOCKDOWN_DATA; + break; + case CMD_READ_LOCKDOWN_DATA: + command = CMD_V5V6_READ_LOCKDOWN_DATA; + break; + case CMD_WRITE_LOCKDOWN_DATA: + command = CMD_V5V6_WRITE_LOCKDOWN_DATA; + break; + case CMD_ERASE_LCM_DATA: + command = CMD_V5V6_ERASE_LCM_DATA; + break; + case CMD_ERASE_OEM_DATA: + command = CMD_V5V6_ERASE_OEM_DATA; + break; +#endif + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid command 0x%02x\n", + __func__, cmd); + return -EINVAL; + } + + switch (cmd) { + case CMD_ERASE_ALL: + case CMD_ERASE_UI_CONFIG: + case CMD_ERASE_DISP_CONFIG: + case CMD_ERASE_GUEST_CODE: +#ifdef SYNA_TDDI + case CMD_ERASE_CHIP: + case CMD_ERASE_FORCE_CONFIG: + case CMD_ERASE_LOCKDOWN_DATA: + case CMD_ERASE_LCM_DATA: + case CMD_ERASE_OEM_DATA: +#endif + case CMD_ENABLE_FLASH_PROG: + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.payload, + fwu->bootloader_id, + sizeof(fwu->bootloader_id)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write bootloader ID\n", + __func__); + return retval; + } + break; + default: + break; + }; + + fwu->command = command; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.flash_cmd, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command 0x%02x\n", + __func__, command); + return retval; + } + + return 0; +} + +static int fwu_write_f34_command(unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_write_f34_v7_command(cmd); + else + retval = fwu_write_f34_v5v6_command(cmd); + + return retval; +} + +static int fwu_write_f34_v7_partition_id(unsigned char cmd) +{ + int retval; + unsigned char data_base; + unsigned char partition; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + switch (cmd) { + case CMD_WRITE_FW: + partition = CORE_CODE_PARTITION; + break; + case CMD_WRITE_CONFIG: + case CMD_READ_CONFIG: + if (fwu->config_area == UI_CONFIG_AREA) + partition = CORE_CONFIG_PARTITION; + else if (fwu->config_area == DP_CONFIG_AREA) + partition = DISPLAY_CONFIG_PARTITION; + else if (fwu->config_area == PM_CONFIG_AREA) + partition = GUEST_SERIALIZATION_PARTITION; + else if (fwu->config_area == BL_CONFIG_AREA) + partition = GLOBAL_PARAMETERS_PARTITION; + else if (fwu->config_area == FLASH_CONFIG_AREA) + partition = FLASH_CONFIG_PARTITION; + else if (fwu->config_area == UPP_AREA) + partition = UTILITY_PARAMETER_PARTITION; + break; + case CMD_WRITE_LOCKDOWN: + partition = DEVICE_CONFIG_PARTITION; + break; + case CMD_WRITE_GUEST_CODE: + partition = GUEST_CODE_PARTITION; + break; + case CMD_WRITE_BOOTLOADER: + partition = BOOTLOADER_PARTITION; + break; + case CMD_WRITE_UTILITY_PARAM: + partition = UTILITY_PARAMETER_PARTITION; + break; + case CMD_ERASE_ALL: + partition = CORE_CODE_PARTITION; + break; + case CMD_ERASE_BL_CONFIG: + partition = GLOBAL_PARAMETERS_PARTITION; + break; + case CMD_ERASE_UI_CONFIG: + partition = CORE_CONFIG_PARTITION; + break; + case CMD_ERASE_DISP_CONFIG: + partition = DISPLAY_CONFIG_PARTITION; + break; + case CMD_ERASE_FLASH_CONFIG: + partition = FLASH_CONFIG_PARTITION; + break; + case CMD_ERASE_GUEST_CODE: + partition = GUEST_CODE_PARTITION; + break; + case CMD_ERASE_BOOTLOADER: + partition = BOOTLOADER_PARTITION; + break; + case CMD_ENABLE_FLASH_PROG: + partition = BOOTLOADER_PARTITION; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid command 0x%02x\n", + __func__, cmd); + return -EINVAL; + }; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.partition_id, + &partition, + sizeof(partition)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write partition ID\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_write_f34_partition_id(unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_write_f34_v7_partition_id(cmd); + else + retval = 0; + + return retval; +} + +static int fwu_read_f34_v7_partition_table(unsigned char *partition_table) +{ + int retval; + unsigned char data_base; + unsigned char length[2]; + unsigned short block_number = 0; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + fwu->config_area = FLASH_CONFIG_AREA; + + retval = fwu_write_f34_partition_id(CMD_READ_CONFIG); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + (unsigned char *)&block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + length[0] = (unsigned char)(fwu->flash_config_length & MASK_8BIT); + length[1] = (unsigned char)(fwu->flash_config_length >> 8); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.transfer_length, + length, + sizeof(length)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write transfer length\n", + __func__); + return retval; + } + + retval = fwu_write_f34_command(CMD_READ_CONFIG); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command\n", + __func__); + return retval; + } + + msleep(READ_CONFIG_WAIT_MS); + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, true); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status\n", + __func__); + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + fwu->off.payload, + partition_table, + fwu->partition_table_bytes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block data\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_read_f34_v7_queries(void) +{ + int retval; + unsigned char ii; + unsigned char query_base; + unsigned char index; + unsigned char offset; + unsigned char *ptable; + struct f34_v7_query_0 query_0; + struct f34_v7_query_1_7 query_1_7; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + query_base = fwu->f34_fd.query_base_addr; + + retval = synaptics_rmi4_reg_read(rmi4_data, + query_base, + query_0.data, + sizeof(query_0.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read query 0\n", + __func__); + return retval; + } + + offset = query_0.subpacket_1_size + 1; + + retval = synaptics_rmi4_reg_read(rmi4_data, + query_base + offset, + query_1_7.data, + sizeof(query_1_7.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read queries 1 to 7\n", + __func__); + return retval; + } + + fwu->bootloader_id[0] = query_1_7.bl_minor_revision; + fwu->bootloader_id[1] = query_1_7.bl_major_revision; + + if (fwu->bootloader_id[1] == BL_V8) + fwu->bl_version = BL_V8; + + fwu->block_size = query_1_7.block_size_15_8 << 8 | + query_1_7.block_size_7_0; + + fwu->flash_config_length = query_1_7.flash_config_length_15_8 << 8 | + query_1_7.flash_config_length_7_0; + + fwu->payload_length = query_1_7.payload_length_15_8 << 8 | + query_1_7.payload_length_7_0; + + fwu->off.flash_status = V7_FLASH_STATUS_OFFSET; + fwu->off.partition_id = V7_PARTITION_ID_OFFSET; + fwu->off.block_number = V7_BLOCK_NUMBER_OFFSET; + fwu->off.transfer_length = V7_TRANSFER_LENGTH_OFFSET; + fwu->off.flash_cmd = V7_COMMAND_OFFSET; + fwu->off.payload = V7_PAYLOAD_OFFSET; + + index = sizeof(query_1_7.data) - V7_PARTITION_SUPPORT_BYTES; + + fwu->partitions = 0; + for (offset = 0; offset < V7_PARTITION_SUPPORT_BYTES; offset++) { + for (ii = 0; ii < 8; ii++) { + if (query_1_7.data[index + offset] & (1 << ii)) + fwu->partitions++; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Supported partitions: 0x%02x\n", + __func__, query_1_7.data[index + offset]); + } + + fwu->partition_table_bytes = fwu->partitions * 8 + 2; + + ptable = kzalloc(fwu->partition_table_bytes, GFP_KERNEL); + if (!ptable) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for partition table\n", + __func__); + return -ENOMEM; + } + + retval = fwu_read_f34_v7_partition_table(ptable); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read partition table\n", + __func__); + kfree(ptable); + return retval; + } + + fwu_parse_partition_table(ptable, &fwu->blkcount, &fwu->phyaddr); + + if (fwu->blkcount.dp_config) + fwu->flash_properties.has_disp_config = 1; + else + fwu->flash_properties.has_disp_config = 0; + + if (fwu->blkcount.pm_config) + fwu->flash_properties.has_pm_config = 1; + else + fwu->flash_properties.has_pm_config = 0; + + if (fwu->blkcount.bl_config) + fwu->flash_properties.has_bl_config = 1; + else + fwu->flash_properties.has_bl_config = 0; + + if (fwu->blkcount.guest_code) + fwu->has_guest_code = 1; + else + fwu->has_guest_code = 0; + + if (fwu->blkcount.utility_param) + fwu->has_utility_param = 1; + else + fwu->has_utility_param = 0; + + kfree(ptable); + + return 0; +} + +static int fwu_read_f34_v5v6_queries(void) +{ + int retval; + unsigned char count; + unsigned char base; + unsigned char offset; + unsigned char buf[10]; + struct f34_v5v6_flash_properties_2 properties_2; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + base = fwu->f34_fd.query_base_addr; + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + V5V6_BOOTLOADER_ID_OFFSET, + fwu->bootloader_id, + sizeof(fwu->bootloader_id)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read bootloader ID\n", + __func__); + return retval; + } + + if (fwu->bl_version == BL_V5) { + fwu->off.properties = V5_PROPERTIES_OFFSET; + fwu->off.block_size = V5_BLOCK_SIZE_OFFSET; + fwu->off.block_count = V5_BLOCK_COUNT_OFFSET; + fwu->off.block_number = V5_BLOCK_NUMBER_OFFSET; + fwu->off.payload = V5_BLOCK_DATA_OFFSET; + } else if (fwu->bl_version == BL_V6) { + fwu->off.properties = V6_PROPERTIES_OFFSET; + fwu->off.properties_2 = V6_PROPERTIES_2_OFFSET; + fwu->off.block_size = V6_BLOCK_SIZE_OFFSET; + fwu->off.block_count = V6_BLOCK_COUNT_OFFSET; + fwu->off.gc_block_count = V6_GUEST_CODE_BLOCK_COUNT_OFFSET; + fwu->off.block_number = V6_BLOCK_NUMBER_OFFSET; + fwu->off.payload = V6_BLOCK_DATA_OFFSET; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.block_size, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block size info\n", + __func__); + return retval; + } + + batohs(&fwu->block_size, &(buf[0])); + + if (fwu->bl_version == BL_V5) { + fwu->off.flash_cmd = fwu->off.payload + fwu->block_size; + fwu->off.flash_status = fwu->off.flash_cmd; + } else if (fwu->bl_version == BL_V6) { + fwu->off.flash_cmd = V6_FLASH_COMMAND_OFFSET; + fwu->off.flash_status = V6_FLASH_STATUS_OFFSET; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.properties, + fwu->flash_properties.data, + sizeof(fwu->flash_properties.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash properties\n", + __func__); + return retval; + } + + count = 4; + + if (fwu->flash_properties.has_pm_config) + count += 2; + + if (fwu->flash_properties.has_bl_config) + count += 2; + + if (fwu->flash_properties.has_disp_config) + count += 2; + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.block_count, + buf, + count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block count info\n", + __func__); + return retval; + } + + batohs(&fwu->blkcount.ui_firmware, &(buf[0])); + batohs(&fwu->blkcount.ui_config, &(buf[2])); + + count = 4; + + if (fwu->flash_properties.has_pm_config) { + batohs(&fwu->blkcount.pm_config, &(buf[count])); + count += 2; + } + + if (fwu->flash_properties.has_bl_config) { + batohs(&fwu->blkcount.bl_config, &(buf[count])); + count += 2; + } + + if (fwu->flash_properties.has_disp_config) + batohs(&fwu->blkcount.dp_config, &(buf[count])); + + fwu->has_guest_code = false; +#ifdef SYNA_TDDI + fwu->has_force_config = false; + fwu->has_lockdown_data = false; + fwu->has_lcm_data = false; + fwu->has_oem_data = false; +#endif + + if (fwu->flash_properties.has_query4) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.properties_2, + properties_2.data, + sizeof(properties_2.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash properties 2\n", + __func__); + return retval; + } + offset = fwu->off.properties_2 + 1; + count = 0; + if (properties_2.has_guest_code) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read guest code block count\n", + __func__); + return retval; + } + + batohs(&fwu->blkcount.guest_code, &(buf[0])); + count++; + fwu->has_guest_code = true; + } +#ifdef SYNA_TDDI + if (properties_2.has_force_config) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi force block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_force_config, &(buf[0])); + count++; + fwu->has_force_config = true; + } + if (properties_2.has_lockdown_data) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi lockdown block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_lockdown_data, &(buf[0])); + count++; + fwu->has_lockdown_data = true; + } + if (properties_2.has_lcm_data) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi lcm block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_lcm_data, &(buf[0])); + count++; + fwu->has_lcm_data = true; + } + if (properties_2.has_oem_data) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi oem block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_oem_data, &(buf[0])); + fwu->has_oem_data = true; + } +#endif + } + + fwu->has_utility_param = false; + + return 0; +} + +static int fwu_read_f34_queries(void) +{ + int retval; + + memset(&fwu->blkcount, 0x00, sizeof(fwu->blkcount)); + memset(&fwu->phyaddr, 0x00, sizeof(fwu->phyaddr)); + + if (fwu->bl_version == BL_V7) + retval = fwu_read_f34_v7_queries(); + else + retval = fwu_read_f34_v5v6_queries(); + + return retval; +} + +static int fwu_write_f34_v7_blocks(unsigned char *block_ptr, + unsigned short block_cnt, unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char length[2]; + unsigned short transfer; + unsigned short remaining = block_cnt; + unsigned short block_number = 0; + unsigned short left_bytes; + unsigned short write_size; + unsigned short max_write_size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + retval = fwu_write_f34_partition_id(command); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + (unsigned char *)&block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + do { + if (remaining / fwu->payload_length) + transfer = fwu->payload_length; + else + transfer = remaining; + + length[0] = (unsigned char)(transfer & MASK_8BIT); + length[1] = (unsigned char)(transfer >> 8); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.transfer_length, + length, + sizeof(length)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write transfer length (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command (remaining = %d)\n", + __func__, remaining); + return retval; + } + +#ifdef MAX_WRITE_SIZE + max_write_size = MAX_WRITE_SIZE; + if (max_write_size >= transfer * fwu->block_size) + max_write_size = transfer * fwu->block_size; + else if (max_write_size > fwu->block_size) + max_write_size -= max_write_size % fwu->block_size; + else + max_write_size = fwu->block_size; +#else + max_write_size = transfer * fwu->block_size; +#endif + left_bytes = transfer * fwu->block_size; + + do { + if (left_bytes / max_write_size) + write_size = max_write_size; + else + write_size = left_bytes; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.payload, + block_ptr, + write_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block data (remaining = %d)\n", + __func__, remaining); + return retval; + } + + block_ptr += write_size; + left_bytes -= write_size; + } while (left_bytes); + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status (remaining = %d)\n", + __func__, remaining); + return retval; + } + + remaining -= transfer; + } while (remaining); + + return 0; +} + +static int fwu_write_f34_v5v6_blocks(unsigned char *block_ptr, + unsigned short block_cnt, unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char block_number[] = {0, 0}; + unsigned short blk; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + block_number[1] |= (fwu->config_area << 5); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + for (blk = 0; blk < block_cnt; blk++) { + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.payload, + block_ptr, + fwu->block_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block data (block %d)\n", + __func__, blk); + return retval; + } + + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command for block %d\n", + __func__, blk); + return retval; + } + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status (block %d)\n", + __func__, blk); + return retval; + } + + block_ptr += fwu->block_size; + } + + return 0; +} + +static int fwu_write_f34_blocks(unsigned char *block_ptr, + unsigned short block_cnt, unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_write_f34_v7_blocks(block_ptr, block_cnt, cmd); + else + retval = fwu_write_f34_v5v6_blocks(block_ptr, block_cnt, cmd); + + return retval; +} + +static int fwu_read_f34_v7_blocks(unsigned short block_cnt, + unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char length[2]; + unsigned short transfer; + unsigned short remaining = block_cnt; + unsigned short block_number = 0; + unsigned short index = 0; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + retval = fwu_write_f34_partition_id(command); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + (unsigned char *)&block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + do { + if (remaining / fwu->payload_length) + transfer = fwu->payload_length; + else + transfer = remaining; + + length[0] = (unsigned char)(transfer & MASK_8BIT); + length[1] = (unsigned char)(transfer >> 8); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.transfer_length, + length, + sizeof(length)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write transfer length (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + fwu->off.payload, + &fwu->read_config_buf[index], + transfer * fwu->block_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block data (remaining = %d)\n", + __func__, remaining); + return retval; + } + + index += (transfer * fwu->block_size); + remaining -= transfer; + } while (remaining); + + return 0; +} + +static int fwu_read_f34_v5v6_blocks(unsigned short block_cnt, + unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char block_number[] = {0, 0}; + unsigned short blk; + unsigned short index = 0; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + block_number[1] |= (fwu->config_area << 5); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + for (blk = 0; blk < block_cnt; blk++) { + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write read config command\n", + __func__); + return retval; + } + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status\n", + __func__); + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + fwu->off.payload, + &fwu->read_config_buf[index], + fwu->block_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block data (block %d)\n", + __func__, blk); + return retval; + } + + index += fwu->block_size; + } + + return 0; +} + +static int fwu_read_f34_blocks(unsigned short block_cnt, unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_read_f34_v7_blocks(block_cnt, cmd); + else + retval = fwu_read_f34_v5v6_blocks(block_cnt, cmd); + + return retval; +} + +static int fwu_get_image_firmware_id(unsigned int *fw_id) +{ + int retval; + unsigned char index = 0; + char *strptr; + char *firmware_id; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->img.contains_firmware_id) { + *fw_id = fwu->img.firmware_id; + } else { + strptr = strnstr(fwu->image_name, "PR", MAX_IMAGE_NAME_LEN); + if (!strptr) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No valid PR number (PRxxxxxxx) found in image file name (%s)\n", + __func__, fwu->image_name); + return -EINVAL; + } + + strptr += 2; + firmware_id = kzalloc(MAX_FIRMWARE_ID_LEN, GFP_KERNEL); + if (!firmware_id) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for firmware_id\n", + __func__); + return -ENOMEM; + } + while (strptr[index] >= '0' && strptr[index] <= '9') { + firmware_id[index] = strptr[index]; + index++; + if (index == MAX_FIRMWARE_ID_LEN - 1) + break; + } + + retval = sstrtoul(firmware_id, 10, (unsigned long *)fw_id); + kfree(firmware_id); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to obtain image firmware ID\n", + __func__); + return -EINVAL; + } + } + + return 0; +} + +static int fwu_get_device_config_id(void) +{ + int retval; + unsigned char config_id_size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + config_id_size = V7_CONFIG_ID_SIZE; + else + config_id_size = V5V6_CONFIG_ID_SIZE; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.ctrl_base_addr, + fwu->config_id, + config_id_size); + if (retval < 0) + return retval; + + return 0; +} + +static enum flash_area fwu_go_nogo(void) +{ + int retval; + enum flash_area flash_area = NONE; + unsigned char ii; + unsigned char config_id_size; + unsigned int device_fw_id; + unsigned int image_fw_id; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->force_update) { + flash_area = UI_FIRMWARE; + goto exit; + } + + /* Update both UI and config if device is in bootloader mode */ + if (fwu->bl_mode_device) { + flash_area = UI_FIRMWARE; + goto exit; + } + + /* Get device firmware ID */ + device_fw_id = rmi4_data->firmware_id; + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device firmware ID = %d\n", + __func__, device_fw_id); + + /* Get image firmware ID */ + retval = fwu_get_image_firmware_id(&image_fw_id); + if (retval < 0) { + flash_area = NONE; + goto exit; + } + dev_info(rmi4_data->pdev->dev.parent, + "%s: Image firmware ID = %d\n", + __func__, image_fw_id); + + if (image_fw_id > device_fw_id) { + flash_area = UI_FIRMWARE; + goto exit; + } else if (image_fw_id < device_fw_id) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Image firmware ID older than device firmware ID\n", + __func__); + flash_area = NONE; + goto exit; + } + + /* Get device config ID */ + retval = fwu_get_device_config_id(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device config ID\n", + __func__); + flash_area = NONE; + goto exit; + } + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + config_id_size = V7_CONFIG_ID_SIZE; + else + config_id_size = V5V6_CONFIG_ID_SIZE; + + for (ii = 0; ii < config_id_size; ii++) { + if (fwu->img.ui_config.data[ii] > fwu->config_id[ii]) { + flash_area = UI_CONFIG; + goto exit; + } else if (fwu->img.ui_config.data[ii] < fwu->config_id[ii]) { + flash_area = NONE; + goto exit; + } + } + + flash_area = NONE; + +exit: + if (flash_area == NONE) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: No need to do reflash\n", + __func__); + } else { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Updating %s\n", + __func__, + flash_area == UI_FIRMWARE ? + "UI firmware and config" : + "UI config only"); + } + + return flash_area; +} + +static int fwu_scan_pdt(void) +{ + int retval; + unsigned char ii; + unsigned char intr_count = 0; + unsigned char intr_off; + unsigned char intr_src; + unsigned short addr; + bool f01found = false; + bool f34found = false; + bool f35found = false; + struct synaptics_rmi4_fn_desc rmi_fd; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + fwu->in_ub_mode = false; + + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&rmi_fd, + sizeof(rmi_fd)); + if (retval < 0) + return retval; + + if (rmi_fd.fn_number) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Found F%02x\n", + __func__, rmi_fd.fn_number); + switch (rmi_fd.fn_number) { + case SYNAPTICS_RMI4_F01: + f01found = true; + + rmi4_data->f01_query_base_addr = + rmi_fd.query_base_addr; + rmi4_data->f01_ctrl_base_addr = + rmi_fd.ctrl_base_addr; + rmi4_data->f01_data_base_addr = + rmi_fd.data_base_addr; + rmi4_data->f01_cmd_base_addr = + rmi_fd.cmd_base_addr; + break; + case SYNAPTICS_RMI4_F34: + f34found = true; + fwu->f34_fd.query_base_addr = + rmi_fd.query_base_addr; + fwu->f34_fd.ctrl_base_addr = + rmi_fd.ctrl_base_addr; + fwu->f34_fd.data_base_addr = + rmi_fd.data_base_addr; + + switch (rmi_fd.fn_version) { + case F34_V0: + fwu->bl_version = BL_V5; + break; + case F34_V1: + fwu->bl_version = BL_V6; + break; + case F34_V2: + fwu->bl_version = BL_V7; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Unrecognized F34 version\n", + __func__); + return -EINVAL; + } + + fwu->intr_mask = 0; + intr_src = rmi_fd.intr_src_count; + intr_off = intr_count % 8; + for (ii = intr_off; + ii < (intr_src + intr_off); + ii++) { + fwu->intr_mask |= 1 << ii; + } + break; + case SYNAPTICS_RMI4_F35: + f35found = true; + fwu->f35_fd.query_base_addr = + rmi_fd.query_base_addr; + fwu->f35_fd.ctrl_base_addr = + rmi_fd.ctrl_base_addr; + fwu->f35_fd.data_base_addr = + rmi_fd.data_base_addr; + fwu->f35_fd.cmd_base_addr = + rmi_fd.cmd_base_addr; + break; + } + } else { + break; + } + + intr_count += rmi_fd.intr_src_count; + } + + if (!f01found || !f34found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find both F01 and F34\n", + __func__); + if (!f35found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F35\n", + __func__); + return -EINVAL; + } else { + fwu->in_ub_mode = true; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + fwu_recovery_check_status(); + return 0; + } + } + + rmi4_data->intr_mask[0] |= fwu->intr_mask; + + addr = rmi4_data->f01_ctrl_base_addr + 1; + + retval = synaptics_rmi4_reg_write(rmi4_data, + addr, + &(rmi4_data->intr_mask[0]), + sizeof(rmi4_data->intr_mask[0])); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set interrupt enable bit\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_enter_flash_prog(void) +{ + int retval; + struct f01_device_control f01_device_control; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_read_flash_status(); + if (retval < 0) + return retval; + + if (fwu->in_bl_mode) + return 0; + + retval = rmi4_data->irq_enable(rmi4_data, false, true); + if (retval < 0) + return retval; + + msleep(INT_DISABLE_WAIT_MS); + + retval = fwu_write_f34_command(CMD_ENABLE_FLASH_PROG); + if (retval < 0) + return retval; + + retval = fwu_wait_for_idle(ENABLE_WAIT_MS, false); + if (retval < 0) + return retval; + + if (!fwu->in_bl_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: BL mode not entered\n", + __func__); + return -EINVAL; + } + + if (rmi4_data->hw_if->bl_hw_init) { + retval = rmi4_data->hw_if->bl_hw_init(rmi4_data); + if (retval < 0) + return retval; + } + + retval = fwu_scan_pdt(); + if (retval < 0) + return retval; + + retval = fwu_read_f34_queries(); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + f01_device_control.data, + sizeof(f01_device_control.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F01 device control\n", + __func__); + return retval; + } + + f01_device_control.nosleep = true; + f01_device_control.sleep_mode = SLEEP_MODE_NORMAL; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + f01_device_control.data, + sizeof(f01_device_control.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write F01 device control\n", + __func__); + return retval; + } + + msleep(ENTER_FLASH_PROG_WAIT_MS); + + return retval; +} + +static int fwu_check_ui_firmware_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.ui_firmware.size / fwu->block_size; + + if (block_count != fwu->blkcount.ui_firmware) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: UI firmware size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_ui_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.ui_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.ui_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: UI configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_dp_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.dp_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.dp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Display configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_pm_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.pm_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_bl_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.bl_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.bl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Bootloader configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_guest_code_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.guest_code.size / fwu->block_size; + if (block_count != fwu->blkcount.guest_code) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Guest code size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_erase_configuration(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_UI_CONFIG); + if (retval < 0) + return retval; + break; + case DP_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_DISP_CONFIG); + if (retval < 0) + return retval; + break; + case BL_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_BL_CONFIG); + if (retval < 0) + return retval; + break; + case FLASH_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_FLASH_CONFIG); + if (retval < 0) + return retval; + break; + case UPP_AREA: + retval = fwu_write_f34_command(CMD_ERASE_UTILITY_PARAMETER); + if (retval < 0) + return retval; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid config area\n", + __func__); + return -EINVAL; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return retval; +} + +static int fwu_erase_bootloader(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_command(CMD_ERASE_BOOTLOADER); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return 0; +} + +#ifdef SYNA_TDDI +static int fwu_erase_lockdown_data(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_command(CMD_ERASE_LOCKDOWN_DATA); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + msleep(100); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return 0; +} + +#endif + +static int fwu_erase_guest_code(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_command(CMD_ERASE_GUEST_CODE); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return 0; +} + +static int fwu_erase_all(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->bl_version == BL_V7) { + retval = fwu_write_f34_command(CMD_ERASE_UI_FIRMWARE); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + fwu->config_area = UI_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + } else { + retval = fwu_write_f34_command(CMD_ERASE_ALL); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase all command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (!(fwu->bl_version == BL_V8 && + fwu->flash_status == BAD_PARTITION_TABLE)) { + if (retval < 0) + return retval; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + if (fwu->bl_version == BL_V8) + return 0; + } + + if (fwu->flash_properties.has_disp_config) { + fwu->config_area = DP_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + } + + if (fwu->has_guest_code) { + retval = fwu_erase_guest_code(); + if (retval < 0) + return retval; + } + + return 0; +} + +static int fwu_write_firmware(void) +{ + unsigned short firmware_block_count; + + firmware_block_count = fwu->img.ui_firmware.size / fwu->block_size; + + return fwu_write_f34_blocks((unsigned char *)fwu->img.ui_firmware.data, + firmware_block_count, CMD_WRITE_FW); +} + +static int fwu_write_bootloader(void) +{ + int retval; + unsigned short bootloader_block_count; + + bootloader_block_count = fwu->img.bl_image.size / fwu->block_size; + + fwu->write_bootloader = true; + retval = fwu_write_f34_blocks((unsigned char *)fwu->img.bl_image.data, + bootloader_block_count, CMD_WRITE_BOOTLOADER); + fwu->write_bootloader = false; + + return retval; +} + +static int fwu_write_utility_parameter(void) +{ + int retval; + unsigned char ii; + unsigned char checksum_array[4]; + unsigned char *pbuf; + unsigned short remaining_size; + unsigned short utility_param_size; + unsigned long checksum; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + utility_param_size = fwu->blkcount.utility_param * fwu->block_size; + retval = fwu_allocate_read_config_buf(utility_param_size); + if (retval < 0) + return retval; + memset(fwu->read_config_buf, 0x00, utility_param_size); + + pbuf = fwu->read_config_buf; + remaining_size = utility_param_size - 4; + + for (ii = 0; ii < MAX_UTILITY_PARAMS; ii++) { + if (fwu->img.utility_param_id[ii] == UNUSED) + continue; + +#ifdef F51_DISCRETE_FORCE + if (fwu->img.utility_param_id[ii] == FORCE_PARAMETER) { + if (fwu->bl_mode_device) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device in bootloader mode, skipping calibration data restoration\n", + __func__); + goto image_param; + } + retval = secure_memcpy(&(pbuf[4]), + remaining_size - 4, + fwu->cal_data, + fwu->cal_data_buf_size, + fwu->cal_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy force calibration data\n", + __func__); + return retval; + } + pbuf[0] = FORCE_PARAMETER; + pbuf[1] = 0x00; + pbuf[2] = (4 + fwu->cal_data_size) / 2; + pbuf += (fwu->cal_data_size + 4); + remaining_size -= (fwu->cal_data_size + 4); + continue; + } +image_param: +#endif + + retval = secure_memcpy(pbuf, + remaining_size, + fwu->img.utility_param[ii].data, + fwu->img.utility_param[ii].size, + fwu->img.utility_param[ii].size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy utility parameter data\n", + __func__); + return retval; + } + pbuf += fwu->img.utility_param[ii].size; + remaining_size -= fwu->img.utility_param[ii].size; + } + + calculate_checksum((unsigned short *)fwu->read_config_buf, + ((utility_param_size - 4) / 2), + &checksum); + + convert_to_little_endian(checksum_array, checksum); + + fwu->read_config_buf[utility_param_size - 4] = checksum_array[0]; + fwu->read_config_buf[utility_param_size - 3] = checksum_array[1]; + fwu->read_config_buf[utility_param_size - 2] = checksum_array[2]; + fwu->read_config_buf[utility_param_size - 1] = checksum_array[3]; + + retval = fwu_write_f34_blocks((unsigned char *)fwu->read_config_buf, + fwu->blkcount.utility_param, CMD_WRITE_UTILITY_PARAM); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_write_configuration(void) +{ + return fwu_write_f34_blocks((unsigned char *)fwu->config_data, + fwu->config_block_count, CMD_WRITE_CONFIG); +} + +static int fwu_write_ui_configuration(void) +{ + fwu->config_area = UI_CONFIG_AREA; + fwu->config_data = fwu->img.ui_config.data; + fwu->config_size = fwu->img.ui_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + return fwu_write_configuration(); +} + +static int fwu_write_dp_configuration(void) +{ + fwu->config_area = DP_CONFIG_AREA; + fwu->config_data = fwu->img.dp_config.data; + fwu->config_size = fwu->img.dp_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + return fwu_write_configuration(); +} + +static int fwu_write_pm_configuration(void) +{ + fwu->config_area = PM_CONFIG_AREA; + fwu->config_data = fwu->img.pm_config.data; + fwu->config_size = fwu->img.pm_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + return fwu_write_configuration(); +} + +#ifdef SYNA_TDDI +static int fwu_write_tddi_lockdown_data(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_blocks(fwu->read_config_buf, + fwu->blkcount.tddi_lockdown_data, + CMD_WRITE_LOCKDOWN_DATA); + if (retval < 0) + return retval; + rmi4_data->reset_device(rmi4_data, false); + return 0; +} +#endif + +static int fwu_write_flash_configuration(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + fwu->config_area = FLASH_CONFIG_AREA; + fwu->config_data = fwu->img.fl_config.data; + fwu->config_size = fwu->img.fl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + if (fwu->config_block_count != fwu->blkcount.fl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash configuration size mismatch\n", + __func__); + return -EINVAL; + } + + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + rmi4_data->reset_device(rmi4_data, false); + + return 0; +} + +static int fwu_write_guest_code(void) +{ + int retval; + unsigned short guest_code_block_count; + + guest_code_block_count = fwu->img.guest_code.size / fwu->block_size; + + retval = fwu_write_f34_blocks((unsigned char *)fwu->img.guest_code.data, + guest_code_block_count, CMD_WRITE_GUEST_CODE); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_write_lockdown(void) +{ + unsigned short lockdown_block_count; + + lockdown_block_count = fwu->img.lockdown.size / fwu->block_size; + + return fwu_write_f34_blocks((unsigned char *)fwu->img.lockdown.data, + lockdown_block_count, CMD_WRITE_LOCKDOWN); +} + +static int fwu_write_partition_table_v8(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + fwu->config_area = FLASH_CONFIG_AREA; + fwu->config_data = fwu->img.fl_config.data; + fwu->config_size = fwu->img.fl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + if (fwu->config_block_count != fwu->blkcount.fl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash configuration size mismatch\n", + __func__); + return -EINVAL; + } + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + rmi4_data->reset_device(rmi4_data, false); + + return 0; +} + +static int fwu_write_partition_table_v7(void) +{ + int retval; + unsigned short block_count; + + block_count = fwu->blkcount.bl_config; + fwu->config_area = BL_CONFIG_AREA; + fwu->config_size = fwu->block_size * block_count; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + return retval; + + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG); + if (retval < 0) + return retval; + + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_write_flash_configuration(); + if (retval < 0) + return retval; + + fwu->config_area = BL_CONFIG_AREA; + fwu->config_data = fwu->read_config_buf; + fwu->config_size = fwu->img.bl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_write_bl_area_v7(void) +{ + int retval; + bool has_utility_param; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + has_utility_param = fwu->has_utility_param; + + if (fwu->has_utility_param) { + fwu->config_area = UPP_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + } + + fwu->config_area = BL_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + fwu->config_area = FLASH_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_erase_bootloader(); + if (retval < 0) + return retval; + + retval = fwu_write_bootloader(); + if (retval < 0) + return retval; + + msleep(rmi4_data->hw_if->board_data->reset_delay_ms); + rmi4_data->reset_device(rmi4_data, false); + + fwu->config_area = FLASH_CONFIG_AREA; + fwu->config_data = fwu->img.fl_config.data; + fwu->config_size = fwu->img.fl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + rmi4_data->reset_device(rmi4_data, false); + + fwu->config_area = BL_CONFIG_AREA; + fwu->config_data = fwu->img.bl_config.data; + fwu->config_size = fwu->img.bl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + if (fwu->img.contains_utility_param) { + retval = fwu_write_utility_parameter(); + if (retval < 0) + return retval; + } + + return 0; +} + +static int fwu_do_reflash(void) +{ + int retval; + bool do_bl_update = false; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!fwu->new_partition_table) { + retval = fwu_check_ui_firmware_size(); + if (retval < 0) + return retval; + + retval = fwu_check_ui_configuration_size(); + if (retval < 0) + return retval; + + if (fwu->flash_properties.has_disp_config && + fwu->img.contains_disp_config) { + retval = fwu_check_dp_configuration_size(); + if (retval < 0) + return retval; + } + + if (fwu->has_guest_code && fwu->img.contains_guest_code) { + retval = fwu_check_guest_code_size(); + if (retval < 0) + return retval; + } + } else if (fwu->bl_version == BL_V7) { + retval = fwu_check_bl_configuration_size(); + if (retval < 0) + return retval; + } + + if (!fwu->has_utility_param && fwu->img.contains_utility_param) { + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + do_bl_update = true; + } + + if (fwu->has_utility_param && !fwu->img.contains_utility_param) { + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + do_bl_update = true; + } + + if (!do_bl_update && fwu->incompatible_partition_tables) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Incompatible partition tables\n", + __func__); + return -EINVAL; + } else if (!do_bl_update && fwu->new_partition_table) { + if (!fwu->force_update) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Partition table mismatch\n", + __func__); + return -EINVAL; + } + } + + retval = fwu_erase_all(); + if (retval < 0) + return retval; + + if (do_bl_update) { + retval = fwu_write_bl_area_v7(); + if (retval < 0) + return retval; + pr_notice("%s: Bootloader area programmed\n", __func__); + } else if (fwu->bl_version == BL_V7 && fwu->new_partition_table) { + retval = fwu_write_partition_table_v7(); + if (retval < 0) + return retval; + pr_notice("%s: Partition table programmed\n", __func__); + } else if (fwu->bl_version == BL_V8) { + retval = fwu_write_partition_table_v8(); + if (retval < 0) + return retval; + pr_notice("%s: Partition table programmed\n", __func__); + } + + fwu->config_area = UI_CONFIG_AREA; + if (fwu->flash_properties.has_disp_config && + fwu->img.contains_disp_config) { + retval = fwu_write_dp_configuration(); + if (retval < 0) + return retval; + pr_notice("%s: Display configuration programmed\n", __func__); + } + + retval = fwu_write_ui_configuration(); + if (retval < 0) + return retval; + pr_notice("%s: Configuration programmed\n", __func__); + + if (fwu->has_guest_code && fwu->img.contains_guest_code) { + retval = fwu_write_guest_code(); + if (retval < 0) + return retval; + pr_notice("%s: Guest code programmed\n", __func__); + } + + retval = fwu_write_firmware(); + if (retval < 0) + return retval; + pr_notice("%s: Firmware programmed\n", __func__); + + return retval; +} + +static int fwu_do_read_config(void) +{ + int retval; + unsigned short block_count; + unsigned short config_area; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + block_count = fwu->blkcount.ui_config; + break; + case DP_CONFIG_AREA: + if (!fwu->flash_properties.has_disp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Display configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.dp_config; + break; + case PM_CONFIG_AREA: + if (!fwu->flash_properties.has_pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.pm_config; + break; + case BL_CONFIG_AREA: + if (!fwu->flash_properties.has_bl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Bootloader configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.bl_config; + break; + case UPP_AREA: + if (!fwu->has_utility_param) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Utility parameter not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.utility_param; + break; +#ifdef SYNA_TDDI + case TDDI_FORCE_CONFIG_AREA: + if (!fwu->has_force_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: force configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.tddi_force_config; + break; + case TDDI_OEM_DATA_AREA: + if (!fwu->has_oem_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: oem data not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.tddi_oem_data; + break; + case TDDI_LCM_DATA_AREA: + if (!fwu->has_lcm_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: lcm data not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.tddi_lcm_data; + break; +#endif + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid config area\n", + __func__); + return -EINVAL; + } + + if (block_count == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid block count\n", + __func__); + return -EINVAL; + } + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + if (fwu->bl_version == BL_V5 || fwu->bl_version == BL_V6) { + config_area = fwu->config_area; + retval = fwu_enter_flash_prog(); + fwu->config_area = config_area; + if (retval < 0) + goto exit; + } + + fwu->config_size = fwu->block_size * block_count; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + goto exit; + + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG); + +exit: + if (fwu->bl_version == BL_V5 || fwu->bl_version == BL_V6) + rmi4_data->reset_device(rmi4_data, false); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + return retval; +} + +static int fwu_do_read_customer_serialization_data(void) +{ + int ii; + int retval = 0; + int block_count = 0; + char temp[40] = {0}; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + if (!fwu->flash_properties.has_pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration not supported\n", + __func__); + return -EINVAL; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of customer serialization aquirement process\n", __func__); + + retval = fwu_read_flash_status(); + if (retval < 0) + goto exit; + fwu->config_area = PM_CONFIG_AREA; + block_count = fwu->blkcount.pm_config; + if (block_count == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid block count\n", + __func__); + goto exit; + } + fwu->config_size = fwu->block_size * block_count; + pr_notice("%s: Block size = %d\n", __func__, fwu->block_size); + pr_notice("%s: Permanent config block count = %d\n", __func__, block_count); + pr_notice("%s: Permanent config size = %d\n", __func__, fwu->config_size); + dev_info(rmi4_data->pdev->dev.parent, + "%s: permanent config size = %d\n", + __func__, fwu->config_size); + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) { + + goto exit; + } + + retval = fwu_read_f34_blocks(block_count, + CMD_READ_CONFIG); + if (retval < 0) { + + goto exit; + } + + for (ii = 0; ii < 10; ii++) + pr_notice("%s: Permanent config data[%d] = 0x%02x\n", __func__, ii, fwu->read_config_buf[ii]); + + sprintf(temp, "%02x%02x%02x%02x%02x%02x%02x%02x", fwu->read_config_buf[0], fwu->read_config_buf[1], fwu->read_config_buf[2], fwu->read_config_buf[3], fwu->read_config_buf[4], fwu->read_config_buf[5], fwu->read_config_buf[6], fwu->read_config_buf[7]); + printk("tp_lockdown info : %s\n", temp); + strcpy(tp_lockdown_info, temp); + + + +exit: + + pr_notice("%s: End of customer serialization acquirement process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} + + + +#ifdef SYNA_TDDI +static int fwu_do_read_tddi_lockdown_data(void) +{ + int retval = -EINVAL; + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->blkcount.tddi_lockdown_data; + fwu->config_size = fwu->block_size * block_count; + + if (fwu->bl_version != BL_V6) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data in bl v.%d\n", + __func__, + fwu->bl_version); + goto exit; + } else if (!fwu->has_lockdown_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data\n", __func__); + goto exit; + } + + kfree(fwu->read_config_buf); + + fwu->read_config_buf = kzalloc(fwu->config_size, GFP_KERNEL); + + if (!fwu->read_config_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu->read_config_buf\n", + __func__); + fwu->read_config_buf_size = 0; + retval = -ENOMEM; + goto exit; + } + fwu->read_config_buf_size = fwu->config_size; + retval = fwu_read_f34_blocks(block_count, CMD_READ_LOCKDOWN_DATA); +exit: + return retval; +} + +int get_tddi_lockdown_data(unsigned char *lockdown_data, unsigned short leng) +{ + int retval; + + retval = fwu_do_read_tddi_lockdown_data(); + if (retval < 0) + return retval; + memcpy(lockdown_data, fwu->read_config_buf, leng); + return retval; +} + +int set_tddi_lockdown_data(unsigned char *lockdown_data, unsigned short leng) +{ + int retval = -EINVAL; + unsigned long checksum; + unsigned char checksum_array[4]; + unsigned short blk_cnt; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->bl_version != BL_V6) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data in bl v.%d\n", + __func__, + fwu->bl_version); + goto exit; + } else if (!fwu->has_lockdown_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data\n", __func__); + goto exit; + } + + retval = fwu_enter_flash_prog(); + if (retval < 0) + goto exit; + + retval = fwu_erase_lockdown_data(); + if (retval < 0) + goto exit; + + fwu->config_size = fwu->blkcount.tddi_lockdown_data * fwu->block_size; + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + goto exit; + memset(fwu->read_config_buf, 0x00, fwu->config_size); + retval = secure_memcpy(fwu->read_config_buf, fwu->config_size, + lockdown_data, leng, leng); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy tddi lockdwon data\n", + __func__); + goto exit; + } + + calculate_checksum((unsigned short *)fwu->read_config_buf, + ((fwu->config_size - 4) / 2), + &checksum); + + convert_to_little_endian(checksum_array, checksum); + + fwu->read_config_buf[blk_cnt * fwu->block_size - 4] = checksum_array[0]; + fwu->read_config_buf[blk_cnt * fwu->block_size - 3] = checksum_array[1]; + fwu->read_config_buf[blk_cnt * fwu->block_size - 2] = checksum_array[2]; + fwu->read_config_buf[blk_cnt * fwu->block_size - 1] = checksum_array[3]; + retval = fwu_write_tddi_lockdown_data(); +exit: + return retval; +} +#endif + +static int fwu_do_lockdown_v7(void) +{ + int retval; + struct f34_v7_data0 status; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_enter_flash_prog(); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.data_base_addr + fwu->off.flash_status, + status.data, + sizeof(status.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash status\n", + __func__); + return retval; + } + + if (status.device_cfg_status == 2) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device already locked down\n", + __func__); + return 0; + } + + retval = fwu_write_lockdown(); + if (retval < 0) + return retval; + + pr_notice("%s: Lockdown programmed\n", __func__); + + return retval; +} + +static int fwu_do_lockdown_v5v6(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; +#ifdef SYNA_TDDI + unsigned char *img_ld; + + img_ld = (unsigned char *)fwu->img.lockdown.data; + if (fwu->has_lockdown_data) { + retval = set_tddi_lockdown_data(img_ld, + LOCKDOWN_SIZE); + if (retval < 0) + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write lockdown data\n", + __func__); + return retval; + } +#endif + + retval = fwu_enter_flash_prog(); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.query_base_addr + fwu->off.properties, + fwu->flash_properties.data, + sizeof(fwu->flash_properties.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash properties\n", + __func__); + return retval; + } + + if (fwu->flash_properties.unlocked == 0) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device already locked down\n", + __func__); + return 0; + } + + retval = fwu_write_lockdown(); + if (retval < 0) + return retval; + + pr_notice("%s: Lockdown programmed\n", __func__); + + return retval; +} + +#ifdef F51_DISCRETE_FORCE +static int fwu_do_restore_f51_cal_data(void) +{ + int retval; + unsigned char checksum_array[4]; + unsigned short block_count; + unsigned long checksum; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->blkcount.ui_config; + fwu->config_size = fwu->block_size * block_count; + fwu->config_area = UI_CONFIG_AREA; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + return retval; + + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG); + if (retval < 0) + return retval; + + retval = secure_memcpy(&fwu->read_config_buf[fwu->cal_data_off], + fwu->cal_data_size, fwu->cal_data, + fwu->cal_data_buf_size, fwu->cal_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore calibration data\n", + __func__); + return retval; + } + + calculate_checksum((unsigned short *)fwu->read_config_buf, + ((fwu->config_size - 4) / 2), + &checksum); + + convert_to_little_endian(checksum_array, checksum); + + fwu->read_config_buf[fwu->config_size - 4] = checksum_array[0]; + fwu->read_config_buf[fwu->config_size - 3] = checksum_array[1]; + fwu->read_config_buf[fwu->config_size - 2] = checksum_array[2]; + fwu->read_config_buf[fwu->config_size - 1] = checksum_array[3]; + + retval = fwu_enter_flash_prog(); + if (retval < 0) + return retval; + + fwu->config_area = UI_CONFIG_AREA; + fwu->config_data = fwu->read_config_buf; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + return 0; +} +#endif + +static int fwu_start_write_guest_code(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_parse_image_info(); + if (retval < 0) + return -EINVAL; + + if (!fwu->has_guest_code) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Guest code not supported\n", + __func__); + return -EINVAL; + } + + if (!fwu->img.contains_guest_code) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No guest code in firmware image\n", + __func__); + return -EINVAL; + } + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of write guest code process\n", __func__); + + retval = fwu_enter_flash_prog(); + if (retval < 0) + goto exit; + + retval = fwu_check_guest_code_size(); + if (retval < 0) + goto exit; + + retval = fwu_erase_guest_code(); + if (retval < 0) + goto exit; + + retval = fwu_write_guest_code(); + if (retval < 0) + goto exit; + + pr_notice("%s: Guest code programmed\n", __func__); + +exit: + rmi4_data->reset_device(rmi4_data, false); + + pr_notice("%s: End of write guest code process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} + +static int fwu_start_write_config(void) +{ + int retval; + unsigned short config_area; + unsigned int device_fw_id; + unsigned int image_fw_id; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_parse_image_info(); + if (retval < 0) + return -EINVAL; + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + device_fw_id = rmi4_data->firmware_id; + retval = fwu_get_image_firmware_id(&image_fw_id); + if (retval < 0) + return retval; + if (device_fw_id != image_fw_id) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Device and image firmware IDs don't match\n", + __func__); + return -EINVAL; + } + retval = fwu_check_ui_configuration_size(); + if (retval < 0) + return retval; + break; + case DP_CONFIG_AREA: + if (!fwu->flash_properties.has_disp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Display configuration not supported\n", + __func__); + return -EINVAL; + } + if (!fwu->img.contains_disp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No display configuration in firmware image\n", + __func__); + return -EINVAL; + } + retval = fwu_check_dp_configuration_size(); + if (retval < 0) + return retval; + break; + case PM_CONFIG_AREA: + if (!fwu->flash_properties.has_pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration not supported\n", + __func__); + return -EINVAL; + } + if (!fwu->img.contains_perm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No permanent configuration in firmware image\n", + __func__); + return -EINVAL; + } + retval = fwu_check_pm_configuration_size(); + if (retval < 0) + return retval; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Configuration not supported\n", + __func__); + return -EINVAL; + } + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of write config process\n", __func__); + + config_area = fwu->config_area; + + retval = fwu_enter_flash_prog(); + if (retval < 0) + goto exit; + + fwu->config_area = config_area; + + if (fwu->config_area != PM_CONFIG_AREA) { + retval = fwu_erase_configuration(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to erase config\n", + __func__); + goto exit; + } + } + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + retval = fwu_write_ui_configuration(); + if (retval < 0) + goto exit; + break; + case DP_CONFIG_AREA: + retval = fwu_write_dp_configuration(); + if (retval < 0) + goto exit; + break; + case PM_CONFIG_AREA: + retval = fwu_write_pm_configuration(); + if (retval < 0) + goto exit; + break; + } + + pr_notice("%s: Config written\n", __func__); + +exit: + switch (fwu->config_area) { + case UI_CONFIG_AREA: + rmi4_data->reset_device(rmi4_data, true); + break; + case DP_CONFIG_AREA: + case PM_CONFIG_AREA: + rmi4_data->reset_device(rmi4_data, false); + break; + } + + pr_notice("%s: End of write config process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} +static char tp_info_summary[80] = ""; + +static int fwu_start_reflash(void) +{ + int retval = 0; + enum flash_area flash_area; + bool do_rebuild = false; + const struct firmware *fw_entry = NULL; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + unsigned char config_ver[20] = {0}; + + char tp_temp_info[80]; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of reflash process\n", __func__); + + if (fwu->image == NULL) { + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN, + FW_IMAGE_NAME, sizeof(FW_IMAGE_NAME), + sizeof(FW_IMAGE_NAME)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy image file name\n", + __func__); + goto exit; + } + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Requesting firmware image %s\n", + __func__, fwu->image_name); + + retval = request_firmware(&fw_entry, fwu->image_name, + rmi4_data->pdev->dev.parent); + if (retval != 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Firmware image %s not available\n", + __func__, fwu->image_name); + retval = -EINVAL; + goto exit; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Firmware image size = %d\n", + __func__, (unsigned int)fw_entry->size); + + fwu->image = fw_entry->data; + } + + retval = fwu_parse_image_info(); + if (retval < 0) + goto exit; + + if (fwu->blkcount.total_count != fwu->img.blkcount.total_count) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash size mismatch\n", + __func__); + retval = -EINVAL; + goto exit; + } + + if (fwu->bl_version != fwu->img.bl_version) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Bootloader version mismatch\n", + __func__); + retval = -EINVAL; + goto exit; + } + + retval = fwu_read_flash_status(); + if (retval < 0) + goto exit; + + if (fwu->in_bl_mode) { + fwu->bl_mode_device = true; + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device in bootloader mode\n", + __func__); + } else { + fwu->bl_mode_device = false; + } + + flash_area = fwu_go_nogo(); + + if (flash_area != NONE) { + retval = fwu_enter_flash_prog(); + if (retval < 0) { + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + } + +#ifdef F51_DISCRETE_FORCE + if (flash_area != NONE && !fwu->bl_mode_device) { + fwu->config_size = fwu->block_size * fwu->blkcount.ui_config; + fwu->config_area = UI_CONFIG_AREA; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) { + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + + retval = fwu_read_f34_blocks(fwu->blkcount.ui_config, + CMD_READ_CONFIG); + if (retval < 0) { + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + + retval = secure_memcpy(fwu->cal_data, fwu->cal_data_buf_size, + &fwu->read_config_buf[fwu->cal_data_off], + fwu->cal_data_size, fwu->cal_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to save calibration data\n", + __func__); + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + } +#endif + + switch (flash_area) { + case UI_FIRMWARE: + do_rebuild = true; + retval = fwu_do_reflash(); +#ifdef F51_DISCRETE_FORCE + if (retval < 0) + break; + + if (fwu->has_utility_param || fwu->img.contains_utility_param) + break; + + rmi4_data->reset_device(rmi4_data, false); + + if (fwu->bl_mode_device || fwu->in_bl_mode) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device in bootloader mode, skipping calibration data restoration\n", + __func__); + break; + } + + retval = fwu_do_restore_f51_cal_data(); +#endif + break; + case UI_CONFIG: + do_rebuild = true; + retval = fwu_check_ui_configuration_size(); + if (retval < 0) + break; + fwu->config_area = UI_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + break; + retval = fwu_write_ui_configuration(); +#ifdef F51_DISCRETE_FORCE + if (retval < 0) + break; + + if (fwu->has_utility_param) + break; + + retval = fwu_do_restore_f51_cal_data(); +#endif + break; + case NONE: + default: + break; + } + + if (retval < 0) { + do_rebuild = false; + rmi4_data->reset_device(rmi4_data, false); + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do reflash\n", + __func__); + goto exit; + } + + if (fwu->do_lockdown && (fwu->img.lockdown.data != NULL)) { + switch (fwu->bl_version) { + case BL_V5: + case BL_V6: + retval = fwu_do_lockdown_v5v6(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do lockdown\n", + __func__); + } + rmi4_data->reset_device(rmi4_data, false); + break; + case BL_V7: + case BL_V8: + retval = fwu_do_lockdown_v7(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do lockdown\n", + __func__); + } + rmi4_data->reset_device(rmi4_data, false); + break; + default: + break; + } + } + +exit: + if (fw_entry) + release_firmware(fw_entry); + + if (do_rebuild) + rmi4_data->reset_device(rmi4_data, true); + + pr_notice("%s: End of reflash process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + synaptics_rmi4_reg_read(rmi4_data, + 0x000c, + config_ver, + 1); + printk("config_ver info =%02x\n", config_ver[0]); + + strcpy(tp_info_summary, "[Vendor]O-film, [IC]S3603(synaptics), [FW]Ver"); + sprintf(tp_temp_info, "%02x", config_ver[0]); + strcat(tp_info_summary, tp_temp_info); + strcat(tp_info_summary, "\0"); + + rmi4_data->stay_awake = false; + + return retval; +} + +static int fwu_recovery_check_status(void) +{ + int retval; + unsigned char data_base; + unsigned char status; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f35_fd.data_base_addr; + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + F35_ERROR_CODE_OFFSET, + &status, + 1); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read status\n", + __func__); + return retval; + } + + status = status & MASK_5BIT; + + if (status != 0x00) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Recovery mode status = %d\n", + __func__, status); + return -EINVAL; + } + + return 0; +} + +static int fwu_recovery_erase_completion(void) +{ + int retval; + unsigned char data_base; + unsigned char command; + unsigned char status; + unsigned int timeout = F35_ERASE_ALL_WAIT_MS / 20; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f35_fd.data_base_addr; + + do { + command = 0x01; + retval = synaptics_rmi4_reg_write(rmi4_data, + fwu->f35_fd.cmd_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue command\n", + __func__); + return retval; + } + + do { + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f35_fd.cmd_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read command status\n", + __func__); + return retval; + } + + if ((command & 0x01) == 0x00) + break; + + msleep(20); + timeout--; + } while (timeout > 0); + + if (timeout == 0) + goto exit; + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + F35_FLASH_STATUS_OFFSET, + &status, + sizeof(status)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash status\n", + __func__); + return retval; + } + + if ((status & 0x01) == 0x00) + break; + + msleep(20); + timeout--; + } while (timeout > 0); + +exit: + if (timeout == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for flash erase completion\n", + __func__); + return -ETIMEDOUT; + } + + return 0; +} + +static int fwu_recovery_erase_all(void) +{ + int retval; + unsigned char ctrl_base; + unsigned char command = CMD_F35_ERASE_ALL; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + ctrl_base = fwu->f35_fd.ctrl_base_addr; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_COMMAND_OFFSET, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue erase all command\n", + __func__); + return retval; + } + + if (fwu->f35_fd.cmd_base_addr) { + retval = fwu_recovery_erase_completion(); + if (retval < 0) + return retval; + } else { + msleep(F35_ERASE_ALL_WAIT_MS); + } + + retval = fwu_recovery_check_status(); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_recovery_write_chunk(void) +{ + int retval; + unsigned char ctrl_base; + unsigned char chunk_number[] = {0, 0}; + unsigned char chunk_spare; + unsigned char chunk_size; + unsigned char buf[F35_CHUNK_SIZE + 1]; + unsigned short chunk; + unsigned short chunk_total; + unsigned short bytes_written = 0; + unsigned char *chunk_ptr = (unsigned char *)fwu->image; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + ctrl_base = fwu->f35_fd.ctrl_base_addr; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_NUM_LSB_OFFSET, + chunk_number, + sizeof(chunk_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk number\n", + __func__); + return retval; + } + + buf[sizeof(buf) - 1] = CMD_F35_WRITE_CHUNK; + + chunk_total = fwu->image_size / F35_CHUNK_SIZE; + chunk_spare = fwu->image_size % F35_CHUNK_SIZE; + if (chunk_spare) + chunk_total++; + + for (chunk = 0; chunk < chunk_total; chunk++) { + if (chunk_spare && chunk == chunk_total - 1) + chunk_size = chunk_spare; + else + chunk_size = F35_CHUNK_SIZE; + + memset(buf, 0x00, F35_CHUNK_SIZE); + secure_memcpy(buf, sizeof(buf), chunk_ptr, + fwu->image_size - bytes_written, + chunk_size); + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_DATA_OFFSET, + buf, + sizeof(buf)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk data (chunk %d)\n", + __func__, chunk); + return retval; + } + chunk_ptr += chunk_size; + bytes_written += chunk_size; + } + + retval = fwu_recovery_check_status(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk data\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_recovery_reset(void) +{ + int retval; + unsigned char ctrl_base; + unsigned char command = CMD_F35_RESET; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + ctrl_base = fwu->f35_fd.ctrl_base_addr; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_COMMAND_OFFSET, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + return retval; + } + + msleep(F35_RESET_WAIT_MS); + + return 0; +} + +static int fwu_start_recovery(void) +{ + int retval; + const struct firmware *fw_entry = NULL; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of recovery process\n", __func__); + + if (fwu->image == NULL) { + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN, + FW_IHEX_NAME, sizeof(FW_IHEX_NAME), + sizeof(FW_IHEX_NAME)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy ihex file name\n", + __func__); + goto exit; + } + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Requesting firmware ihex %s\n", + __func__, fwu->image_name); + + retval = request_firmware(&fw_entry, fwu->image_name, + rmi4_data->pdev->dev.parent); + if (retval != 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Firmware ihex %s not available\n", + __func__, fwu->image_name); + retval = -EINVAL; + goto exit; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Firmware image size = %d\n", + __func__, (unsigned int)fw_entry->size); + + fwu->image = fw_entry->data; + fwu->image_size = fw_entry->size; + } + + retval = rmi4_data->irq_enable(rmi4_data, false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to disable interrupt\n", + __func__); + goto exit; + } + + retval = fwu_recovery_erase_all(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do erase all in recovery mode\n", + __func__); + goto exit; + } + + pr_notice("%s: External flash erased\n", __func__); + + retval = fwu_recovery_write_chunk(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk data in recovery mode\n", + __func__); + goto exit; + } + + pr_notice("%s: Chunk data programmed\n", __func__); + + retval = fwu_recovery_reset(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to reset device in recovery mode\n", + __func__); + goto exit; + } + + pr_notice("%s: Recovery mode reset issued\n", __func__); + + rmi4_data->reset_device(rmi4_data, true); + + retval = 0; + +exit: + if (fw_entry) + release_firmware(fw_entry); + + pr_notice("%s: End of recovery process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} + +int synaptics_fw_updater(const unsigned char *fw_data) +{ + int retval; + + if (!fwu) + return -ENODEV; + + if (!fwu->initialized) + return -ENODEV; + + if (fwu->in_ub_mode) { + fwu->image = NULL; + retval = fwu_start_recovery(); + if (retval < 0) + return retval; + } + + fwu->image = fw_data; + + retval = fwu_start_reflash(); + + fwu->image = NULL; + + return retval; +} +EXPORT_SYMBOL(synaptics_fw_updater); + +#ifdef DO_STARTUP_FW_UPDATE +static void fwu_startup_fw_update_work(struct work_struct *work) +{ + static unsigned char do_once = 1; +#ifdef WAIT_FOR_FB_READY + unsigned int timeout; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; +#endif + + + if (!do_once) + return; + do_once = 0; + +#ifdef WAIT_FOR_FB_READY + timeout = FB_READY_TIMEOUT_S * 1000 / FB_READY_WAIT_MS + 1; + + while (!rmi4_data->fb_ready) { + msleep(FB_READY_WAIT_MS); + timeout--; + if (timeout == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for FB ready\n", + __func__); + return; + } + } +#endif + + synaptics_fw_updater(NULL); + + + + return; +} +#endif + +static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (count < fwu->config_size) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not enough space (%d bytes) in buffer\n", + __func__, (unsigned int)count); + retval = -EINVAL; + goto exit; + } + + retval = secure_memcpy(buf, count, fwu->read_config_buf, + fwu->read_config_buf_size, fwu->config_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy config data\n", + __func__); + goto exit; + } else { + retval = fwu->config_size; + } + +exit: + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_store_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = secure_memcpy(&fwu->ext_data_source[fwu->data_pos], + fwu->image_size - fwu->data_pos, buf, count, count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy image data\n", + __func__); + goto exit; + } else { + retval = count; + } + + fwu->data_pos += count; + +exit: + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_do_recovery_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + + } + + if (!fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not in microbootloader mode\n", + __func__); + retval = -EINVAL; + + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + + } else { + fwu->image = fwu->ext_data_source; + } + + retval = fwu_start_recovery(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do recovery\n", + __func__); + + } + + retval = count; + + + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + + } + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + + } else { + fwu->image = fwu->ext_data_source; + } + + if (input & LOCKDOWN) { + fwu->do_lockdown = true; + input &= ~LOCKDOWN; + } + + if ((input != NORMAL) && (input != FORCE)) { + retval = -EINVAL; + + } + + if (input == FORCE) + fwu->force_update = true; + + retval = synaptics_fw_updater(fwu->image); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do reflash\n", + __func__); + + } + + retval = count; + + + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = DO_LOCKDOWN; + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_write_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + goto exit; + } + + if (input != 1) { + retval = -EINVAL; + goto exit; + } + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + goto exit; + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + goto exit; + } else { + fwu->image = fwu->ext_data_source; + } + + retval = fwu_start_write_config(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write config\n", + __func__); + goto exit; + } + + retval = count; + +exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_read_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + goto exit; + } + + retval = fwu_do_read_config(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read config\n", + __func__); + goto exit; + } + + retval = count; + +exit: + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_config_area_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long config_area; + + retval = sstrtoul(buf, 10, &config_area); + if (retval) + return retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + fwu->config_area = config_area; + + mutex_unlock(&fwu_sysfs_mutex); + + return count; +} + +static ssize_t fwu_sysfs_image_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN, + buf, count, count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy image file name\n", + __func__); + } else { + retval = count; + } + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_image_size_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = sstrtoul(buf, 10, &size); + if (retval) + return retval; + +/* if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; +*/ + fwu->image_size = size; + fwu->data_pos = 0; + + kfree(fwu->ext_data_source); + fwu->ext_data_source = kzalloc(fwu->image_size, GFP_KERNEL); + if (!fwu->ext_data_source) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for image data\n", + __func__); + retval = -ENOMEM; + } else { + retval = count; + } + + + + return retval; +} + +static ssize_t fwu_sysfs_block_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->block_size); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.ui_firmware); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.ui_config); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.dp_config); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.pm_config); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.bl_config); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_utility_parameter_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.utility_param); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_guest_code_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.guest_code); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + + +static ssize_t fwu_sysfs_read_guest_serialization_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + fwu_do_read_customer_serialization_data(); + + retval = snprintf(buf, PAGE_SIZE, "%s\n", fwu->read_config_buf); + + return retval; +} + + +static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + goto exit; + } + + if (input != 1) { + retval = -EINVAL; + goto exit; + } + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + goto exit; + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + goto exit; + } else { + fwu->image = fwu->ext_data_source; + } + + retval = fwu_start_write_guest_code(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write guest code\n", + __func__); + goto exit; + } + + retval = count; + +exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +#ifdef SYNA_TDDI +static ssize_t fwu_sysfs_read_lockdown_code_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned short lockdown_data_size; + unsigned char *lockdown_data; + char ld_val[2]; + int retval = 0; + int i = 0; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + lockdown_data_size = fwu->blkcount.tddi_lockdown_data * fwu->block_size; + lockdown_data = kzalloc(lockdown_data_size, GFP_KERNEL); + if (!lockdown_data) { + mutex_unlock(&fwu_sysfs_mutex); + return -ENOMEM; + } + + if (get_tddi_lockdown_data(lockdown_data, lockdown_data_size) < 0) { + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex); + return -EINVAL; + } + + for (i = 0; i < lockdown_data_size; i++) { + retval += snprintf(ld_val, PAGE_SIZE, "%02x", + *(lockdown_data + i)); + strlcat(buf, ld_val, lockdown_data_size); + } + *(buf + retval) = '\n'; + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex); + return retval + 1; +} + +static ssize_t fwu_sysfs_write_lockdown_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned short lockdown_data_size = (count - 1) / 2; + unsigned char *lockdown_data; + unsigned char temp[2]; + int ld_val; + int i = 0; + + for (i = 0; i < (count - 1); i++) { + if (((*buf >= '0') && (*buf <= '9')) || + (('a' < *buf) && (*buf > 'f')) || + (('A' < *buf) && (*buf > 'F'))) + continue; + else + return -EINVAL; + } + + if (count % 2 != 1) + return -EINVAL; + + lockdown_data = kzalloc(lockdown_data_size, GFP_KERNEL); + if (!lockdown_data) + return -ENOMEM; + + for (i = 0; i < lockdown_data_size; i++) { + memcpy(temp, (buf + 2 * i), sizeof(temp)); + if (sscanf(temp, "%02x", &ld_val) == 1) + *(lockdown_data + i) = ld_val & 0xff; + } + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (set_tddi_lockdown_data(lockdown_data, lockdown_data_size) < 0) { + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex); + return -EINVAL; + } + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex); + return count; +} +#endif +static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!fwu) + return; + + if (fwu->intr_mask & intr_mask) + fwu_read_flash_status(); + + return; +} + +static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char attr_count; + struct pdt_properties pdt_props; + +#if defined(SYNAPTICS_LOCK_DOWN_INFO) + unsigned char lockdown[20] = {0}; +#endif + if (fwu) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + fwu = kzalloc(sizeof(*fwu), GFP_KERNEL); + if (!fwu) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + fwu->image_name = kzalloc(MAX_IMAGE_NAME_LEN, GFP_KERNEL); + if (!fwu->image_name) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for image name\n", + __func__); + retval = -ENOMEM; + goto exit_free_fwu; + } + + fwu->rmi4_data = rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + PDT_PROPS, + pdt_props.data, + sizeof(pdt_props.data)); + if (retval < 0) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Failed to read PDT properties, assuming 0x00\n", + __func__); + } else if (pdt_props.has_bsr) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Reflash for LTS not currently supported\n", + __func__); + retval = -ENODEV; + goto exit_free_mem; + } + + retval = fwu_scan_pdt(); + if (retval < 0) + goto exit_free_mem; + + if (!fwu->in_ub_mode) { + retval = fwu_read_f34_queries(); + if (retval < 0) + goto exit_free_mem; + + retval = fwu_get_device_config_id(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device config ID\n", + __func__); + goto exit_free_mem; + } + } + + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = DO_LOCKDOWN; + fwu->initialized = true; + +#ifdef DO_STARTUP_FW_UPDATE + +#ifdef SYNAPTICS_ESD_CHECK + cancel_delayed_work_sync(&(rmi4_data->esd_work)); +#endif + + fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue"); + INIT_WORK(&fwu->fwu_work, fwu_startup_fw_update_work); + queue_work(fwu->fwu_workqueue, + &fwu->fwu_work); + + #ifdef SYNAPTICS_ESD_CHECK + printk("SYNAPTICS_ESD_CHECK is on\n"); + queue_delayed_work(rmi4_data->esd_workqueue, &(rmi4_data->esd_work), SYNAPTICS_ESD_CHECK_CIRCLE); +#endif +#endif + +printk("before get_tddi_lockdown_data"); + + if (get_tddi_lockdown_data(lockdown, 20) < 0) { + printk("read lockdown fail\n"); + } + printk("lockdown info =%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x\n", lockdown[4], lockdown[5], lockdown[6], lockdown[7], lockdown[8], lockdown[9], lockdown[10], lockdown[11]); + + sprintf(tp_lockdown_info, "%02x%02x%02x%02x%02x%02x%02x%02x\n", lockdown[4], lockdown[5], lockdown[6], lockdown[7], lockdown[8], lockdown[9], lockdown[10], lockdown[11]); + + ctp_lockdown_status_proc = proc_create(CTP_PROC_LOCKDOWN_FILE, 0644, NULL, &ctp_lockdown_proc_fops); + if (ctp_lockdown_status_proc == NULL) { + printk("tpd, create_proc_entry ctp_lockdown_status_proc failed\n"); + } + + +#ifdef F51_DISCRETE_FORCE + fwu_read_flash_status(); + if (!fwu->in_bl_mode) { + retval = fwu_f51_force_data_init(); + if (retval < 0) + goto exit_free_mem; + } +#endif + + if (ENABLE_SYS_REFLASH == false) + return 0; + + retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj, + &dev_attr_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs bin file\n", + __func__); + goto exit_free_mem; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + retval = -ENODEV; + goto exit_remove_attrs; + } + } + + return 0; + +exit_remove_attrs: + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); + +exit_free_mem: + kfree(fwu->image_name); + +exit_free_fwu: + kfree(fwu); + fwu = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char attr_count; + + if (!fwu) + goto exit; + +#ifdef DO_STARTUP_FW_UPDATE + cancel_work_sync(&fwu->fwu_work); + flush_workqueue(fwu->fwu_workqueue); + destroy_workqueue(fwu->fwu_workqueue); +#endif + +#ifdef F51_DISCRETE_FORCE + kfree(fwu->cal_data); +#endif + kfree(fwu->read_config_buf); + kfree(fwu->image_name); + kfree(fwu); + fwu = NULL; + + if (ENABLE_SYS_REFLASH == false) + goto exit; + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); + +exit: + complete(&fwu_remove_complete); + + return; +} + +static void synaptics_rmi4_fwu_reset(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + + if (!fwu) { + synaptics_rmi4_fwu_init(rmi4_data); + return; + } + + retval = fwu_scan_pdt(); + if (retval < 0) + return; + + if (!fwu->in_ub_mode) + fwu_read_f34_queries(); + +#ifdef F51_DISCRETE_FORCE + fwu_read_flash_status(); + if (!fwu->in_bl_mode) + fwu_f51_force_data_init(); +#endif + + return; +} + +static struct synaptics_rmi4_exp_fn fwu_module = { + .fn_type = RMI_FW_UPDATER, + .init = synaptics_rmi4_fwu_init, + .remove = synaptics_rmi4_fwu_remove, + .reset = synaptics_rmi4_fwu_reset, + .reinit = NULL, + .early_suspend = NULL, + .suspend = NULL, + .resume = NULL, + .late_resume = NULL, + .attn = synaptics_rmi4_fwu_attn, +}; + +static int __init rmi4_fw_update_module_init(void) +{ + synaptics_rmi4_new_function(&fwu_module, true); + + return 0; +} + +static void __exit rmi4_fw_update_module_exit(void) +{ + synaptics_rmi4_new_function(&fwu_module, false); + + wait_for_completion(&fwu_remove_complete); + + return; +} + +module_init(rmi4_fw_update_module_init); +module_exit(rmi4_fw_update_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX FW Update Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310/synaptics_dsx_gesture.c b/drivers/input/touchscreen/td4310/synaptics_dsx_gesture.c new file mode 100644 index 0000000000000..c91eb26b88bb5 --- /dev/null +++ b/drivers/input/touchscreen/td4310/synaptics_dsx_gesture.c @@ -0,0 +1,2308 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define GESTURE_PHYS_NAME "synaptics_dsx/gesture" + +#define TUNING_SYSFS_DIR_NAME "tuning" + +#define STORE_GESTURES +#ifdef STORE_GESTURES +#define GESTURES_TO_STORE 10 +#endif + +#define CTRL23_FINGER_REPORT_ENABLE_BIT 0 +#define CTRL27_UDG_ENABLE_BIT 4 +#define WAKEUP_GESTURE_MODE 0x02 + +static ssize_t udg_sysfs_engine_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_detection_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_detection_score_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_detection_index_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_registration_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_registration_begin_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_registration_status_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_template_size_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_template_max_index_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_template_detection_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_template_index_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_template_valid_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_template_valid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_template_clear_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_trace_size_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_template_data_show(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t udg_sysfs_template_data_store(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t udg_sysfs_trace_data_show(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t udg_sysfs_template_displacement_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_template_displacement_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_rotation_invariance_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_rotation_invariance_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_scale_invariance_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_scale_invariance_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_threshold_factor_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_threshold_factor_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_match_metric_threshold_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_match_metric_threshold_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_max_inter_stroke_time_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_max_inter_stroke_time_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static int udg_read_tuning_params(void); + +static int udg_write_tuning_params(void); + +static int udg_detection_enable(bool enable); + +static int udg_engine_enable(bool enable); + +static int udg_set_index(unsigned char index); + +#ifdef STORE_GESTURES +static int udg_read_valid_data(void); +static int udg_write_valid_data(void); +static int udg_read_template_data(unsigned char index); +static int udg_write_template_data(void); +#endif + +enum gesture_type { + DETECTION = 0x0f, + REGISTRATION = 0x10, +}; + +struct udg_tuning { + union { + struct { + unsigned char maximum_number_of_templates; + unsigned char template_size; + unsigned char template_disp_lsb; + unsigned char template_disp_msb; + unsigned char rotation_inv_lsb; + unsigned char rotation_inv_msb; + unsigned char scale_inv_lsb; + unsigned char scale_inv_msb; + unsigned char thres_factor_lsb; + unsigned char thres_factor_msb; + unsigned char metric_thres_lsb; + unsigned char metric_thres_msb; + unsigned char inter_stroke_lsb; + unsigned char inter_stroke_msb; + } __packed; + unsigned char data[14]; + }; +}; + +struct udg_addr { + unsigned short data_4; + unsigned short ctrl_18; + unsigned short ctrl_20; + unsigned short ctrl_23; + unsigned short ctrl_27; + unsigned short ctrl_41; + unsigned short trace_x; + unsigned short trace_y; + unsigned short trace_segment; + unsigned short template_helper; + unsigned short template_data; + unsigned short template_flags; +}; + +struct synaptics_rmi4_f12_query_0 { + union { + struct { + struct { + unsigned char has_register_descriptors:1; + unsigned char has_closed_cover:1; + unsigned char has_fast_glove_detect:1; + unsigned char has_dribble:1; + unsigned char has_4p4_jitter_filter_strength:1; + unsigned char f12_query0_s0_b5__7:3; + } __packed; + struct { + unsigned char max_num_templates:4; + unsigned char f12_query0_s1_b4__7:4; + unsigned char template_size_lsb; + unsigned char template_size_msb; + } __packed; + }; + unsigned char data[4]; + }; +}; + +struct synaptics_rmi4_f12_query_5 { + union { + struct { + unsigned char size_of_query6; + struct { + unsigned char ctrl0_is_present:1; + unsigned char ctrl1_is_present:1; + unsigned char ctrl2_is_present:1; + unsigned char ctrl3_is_present:1; + unsigned char ctrl4_is_present:1; + unsigned char ctrl5_is_present:1; + unsigned char ctrl6_is_present:1; + unsigned char ctrl7_is_present:1; + } __packed; + struct { + unsigned char ctrl8_is_present:1; + unsigned char ctrl9_is_present:1; + unsigned char ctrl10_is_present:1; + unsigned char ctrl11_is_present:1; + unsigned char ctrl12_is_present:1; + unsigned char ctrl13_is_present:1; + unsigned char ctrl14_is_present:1; + unsigned char ctrl15_is_present:1; + } __packed; + struct { + unsigned char ctrl16_is_present:1; + unsigned char ctrl17_is_present:1; + unsigned char ctrl18_is_present:1; + unsigned char ctrl19_is_present:1; + unsigned char ctrl20_is_present:1; + unsigned char ctrl21_is_present:1; + unsigned char ctrl22_is_present:1; + unsigned char ctrl23_is_present:1; + } __packed; + struct { + unsigned char ctrl24_is_present:1; + unsigned char ctrl25_is_present:1; + unsigned char ctrl26_is_present:1; + unsigned char ctrl27_is_present:1; + unsigned char ctrl28_is_present:1; + unsigned char ctrl29_is_present:1; + unsigned char ctrl30_is_present:1; + unsigned char ctrl31_is_present:1; + } __packed; + struct { + unsigned char ctrl32_is_present:1; + unsigned char ctrl33_is_present:1; + unsigned char ctrl34_is_present:1; + unsigned char ctrl35_is_present:1; + unsigned char ctrl36_is_present:1; + unsigned char ctrl37_is_present:1; + unsigned char ctrl38_is_present:1; + unsigned char ctrl39_is_present:1; + } __packed; + struct { + unsigned char ctrl40_is_present:1; + unsigned char ctrl41_is_present:1; + unsigned char ctrl42_is_present:1; + unsigned char ctrl43_is_present:1; + unsigned char ctrl44_is_present:1; + unsigned char ctrl45_is_present:1; + unsigned char ctrl46_is_present:1; + unsigned char ctrl47_is_present:1; + } __packed; + }; + unsigned char data[7]; + }; +}; + +struct synaptics_rmi4_f12_query_8 { + union { + struct { + unsigned char size_of_query9; + struct { + unsigned char data0_is_present:1; + unsigned char data1_is_present:1; + unsigned char data2_is_present:1; + unsigned char data3_is_present:1; + unsigned char data4_is_present:1; + unsigned char data5_is_present:1; + unsigned char data6_is_present:1; + unsigned char data7_is_present:1; + } __packed; + struct { + unsigned char data8_is_present:1; + unsigned char data9_is_present:1; + unsigned char data10_is_present:1; + unsigned char data11_is_present:1; + unsigned char data12_is_present:1; + unsigned char data13_is_present:1; + unsigned char data14_is_present:1; + unsigned char data15_is_present:1; + } __packed; + struct { + unsigned char data16_is_present:1; + unsigned char data17_is_present:1; + unsigned char data18_is_present:1; + unsigned char data19_is_present:1; + unsigned char data20_is_present:1; + unsigned char data21_is_present:1; + unsigned char data22_is_present:1; + unsigned char data23_is_present:1; + } __packed; + }; + unsigned char data[4]; + }; +}; + +struct synaptics_rmi4_f12_control_41 { + union { + struct { + unsigned char enable_registration:1; + unsigned char template_index:4; + unsigned char begin:1; + unsigned char f12_ctrl41_b6__7:2; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_udg_handle { + atomic_t attn_event; + unsigned char intr_mask; + unsigned char report_flags; + unsigned char object_type_enable1; + unsigned char object_type_enable2; + unsigned char trace_size; + unsigned char template_index; + unsigned char max_num_templates; + unsigned char detection_score; + unsigned char detection_index; + unsigned char detection_status; + unsigned char registration_status; + unsigned char *ctrl_buf; + unsigned char *trace_data_buf; + unsigned char *template_data_buf; +#ifdef STORE_GESTURES + unsigned char gestures_to_store; + unsigned char *storage_buf; + unsigned char valid_buf[2]; +#endif + unsigned short trace_data_buf_size; + unsigned short template_size; + unsigned short template_data_size; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; + unsigned short ctrl_18_sub10_off; + unsigned short ctrl_20_sub1_off; + unsigned short ctrl_23_sub3_off; + unsigned short ctrl_27_sub5_off; + struct input_dev *udg_dev; + struct kobject *tuning_dir; + struct udg_addr addr; + struct udg_tuning tuning; + struct synaptics_rmi4_data *rmi4_data; +}; + +static struct device_attribute attrs[] = { + __ATTR(engine_enable, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + udg_sysfs_engine_enable_store), + __ATTR(detection_enable, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + udg_sysfs_detection_enable_store), + __ATTR(detection_score, S_IRUGO, + udg_sysfs_detection_score_show, + synaptics_rmi4_store_error), + __ATTR(detection_index, S_IRUGO, + udg_sysfs_detection_index_show, + synaptics_rmi4_store_error), + __ATTR(registration_enable, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + udg_sysfs_registration_enable_store), + __ATTR(registration_begin, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + udg_sysfs_registration_begin_store), + __ATTR(registration_status, S_IRUGO, + udg_sysfs_registration_status_show, + synaptics_rmi4_store_error), + __ATTR(template_size, S_IRUGO, + udg_sysfs_template_size_show, + synaptics_rmi4_store_error), + __ATTR(template_max_index, S_IRUGO, + udg_sysfs_template_max_index_show, + synaptics_rmi4_store_error), + __ATTR(template_detection, S_IRUGO, + udg_sysfs_template_detection_show, + synaptics_rmi4_store_error), + __ATTR(template_index, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + udg_sysfs_template_index_store), + __ATTR(template_valid, (S_IRUGO | S_IWUSR | S_IWGRP), + udg_sysfs_template_valid_show, + udg_sysfs_template_valid_store), + __ATTR(template_clear, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + udg_sysfs_template_clear_store), + __ATTR(trace_size, S_IRUGO, + udg_sysfs_trace_size_show, + synaptics_rmi4_store_error), +}; + +static struct bin_attribute template_data = { + .attr = { + .name = "template_data", + .mode = (S_IRUGO | S_IWUSR | S_IWGRP), + }, + .size = 0, + .read = udg_sysfs_template_data_show, + .write = udg_sysfs_template_data_store, +}; + +static struct bin_attribute trace_data = { + .attr = { + .name = "trace_data", + .mode = S_IRUGO, + }, + .size = 0, + .read = udg_sysfs_trace_data_show, + .write = NULL, +}; + +static struct device_attribute params[] = { + __ATTR(template_displacement, (S_IRUGO | S_IWUSR | S_IWGRP), + udg_sysfs_template_displacement_show, + udg_sysfs_template_displacement_store), + __ATTR(rotation_invariance, (S_IRUGO | S_IWUSR | S_IWGRP), + udg_sysfs_rotation_invariance_show, + udg_sysfs_rotation_invariance_store), + __ATTR(scale_invariance, (S_IRUGO | S_IWUSR | S_IWGRP), + udg_sysfs_scale_invariance_show, + udg_sysfs_scale_invariance_store), + __ATTR(threshold_factor, (S_IRUGO | S_IWUSR | S_IWGRP), + udg_sysfs_threshold_factor_show, + udg_sysfs_threshold_factor_store), + __ATTR(match_metric_threshold, (S_IRUGO | S_IWUSR | S_IWGRP), + udg_sysfs_match_metric_threshold_show, + udg_sysfs_match_metric_threshold_store), + __ATTR(max_inter_stroke_time, (S_IRUGO | S_IWUSR | S_IWGRP), + udg_sysfs_max_inter_stroke_time_show, + udg_sysfs_max_inter_stroke_time_store), +}; + +static struct synaptics_rmi4_udg_handle *udg; + +static unsigned char ctrl_18_sub_size[] = {10, 10, 10, 2, 3, 4, 3, 3, 1, 1}; +static unsigned char ctrl_20_sub_size[] = {2}; +static unsigned char ctrl_23_sub_size[] = {1, 1, 1}; +static unsigned char ctrl_27_sub_size[] = {1, 5, 2, 1, 7}; + +DECLARE_COMPLETION(udg_remove_complete); + +static ssize_t udg_sysfs_engine_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + bool enable; + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input == 1) + enable = true; + else if (input == 0) + enable = false; + else + return -EINVAL; + + retval = udg_engine_enable(enable); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_detection_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + bool enable; + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input == 1) + enable = true; + else if (input == 0) + enable = false; + else + return -EINVAL; + + udg->detection_status = 0; + + retval = udg_detection_enable(enable); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_detection_score_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", udg->detection_score); +} + +static ssize_t udg_sysfs_detection_index_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", udg->detection_index); +} + +static ssize_t udg_sysfs_registration_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + bool enable; + unsigned int input; + struct synaptics_rmi4_f12_control_41 control_41; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input == 1) + enable = true; + else if (input == 0) + enable = false; + else + return -EINVAL; + + if (enable) { + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_23, + udg->ctrl_buf, + udg->ctrl_23_sub3_off + 1); + if (retval < 0) + return retval; + + udg->ctrl_buf[0] = 0; + udg->ctrl_buf[0] |= (1 << CTRL23_FINGER_REPORT_ENABLE_BIT); + if (udg->ctrl_23_sub3_off) + udg->ctrl_buf[udg->ctrl_23_sub3_off] = 0; + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_23, + udg->ctrl_buf, + udg->ctrl_23_sub3_off + 1); + if (retval < 0) + return retval; + } else { + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_23, + udg->ctrl_buf, + udg->ctrl_23_sub3_off + 1); + if (retval < 0) + return retval; + + udg->ctrl_buf[0] = udg->object_type_enable1; + if (udg->ctrl_23_sub3_off) { + udg->ctrl_buf[udg->ctrl_23_sub3_off] = + udg->object_type_enable2; + } + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_23, + udg->ctrl_buf, + udg->ctrl_23_sub3_off + 1); + if (retval < 0) + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_41, + control_41.data, + sizeof(control_41.data)); + if (retval < 0) + return retval; + + control_41.enable_registration = enable ? 1 : 0; + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_41, + control_41.data, + sizeof(control_41.data)); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_registration_begin_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + bool begin; + unsigned int input; + struct synaptics_rmi4_f12_control_41 control_41; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input == 1) + begin = true; + else if (input == 0) + begin = false; + else + return -EINVAL; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_41, + control_41.data, + sizeof(control_41.data)); + if (retval < 0) + return retval; + + control_41.begin = begin ? 1 : 0; + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_41, + control_41.data, + sizeof(control_41.data)); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_registration_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0x%02x\n", udg->registration_status); +} + +static ssize_t udg_sysfs_template_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", udg->template_size); +} + +static ssize_t udg_sysfs_template_max_index_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", udg->max_num_templates - 1); +} + +static ssize_t udg_sysfs_template_detection_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + int attn_event; + unsigned char detection_status; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + attn_event = atomic_read(&udg->attn_event); + atomic_set(&udg->attn_event, 0); + + if (attn_event == 0) + return snprintf(buf, PAGE_SIZE, "0\n"); + + if (udg->detection_status == 0) { + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.data_4, + rmi4_data->gesture_detection, + sizeof(rmi4_data->gesture_detection)); + if (retval < 0) + return retval; + + udg->detection_status = rmi4_data->gesture_detection[0]; + } + + detection_status = udg->detection_status; + udg->detection_status = 0; + + switch (detection_status) { + case DETECTION: + udg->detection_score = rmi4_data->gesture_detection[1]; + udg->detection_index = rmi4_data->gesture_detection[4]; + udg->trace_size = rmi4_data->gesture_detection[3]; + break; + case REGISTRATION: + udg->registration_status = rmi4_data->gesture_detection[1]; + udg->trace_size = rmi4_data->gesture_detection[3]; + break; + default: + return snprintf(buf, PAGE_SIZE, "0\n"); + } + + return snprintf(buf, PAGE_SIZE, "0x%02x\n", detection_status); +} + +static ssize_t udg_sysfs_template_index_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long index; + + retval = sstrtoul(buf, 10, &index); + if (retval) + return retval; + + retval = udg_set_index((unsigned char)index); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_template_valid_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned char valid; + unsigned char offset; + unsigned char byte_num; + unsigned char template_flags[2]; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + byte_num = udg->template_index / 8; + offset = udg->template_index % 8; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.template_flags, + template_flags, + sizeof(template_flags)); + if (retval < 0) + return retval; + + valid = (template_flags[byte_num] & (1 << offset)) >> offset; + + return snprintf(buf, PAGE_SIZE, "%u\n", valid); +} + +static ssize_t udg_sysfs_template_valid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long valid; + unsigned char offset; + unsigned char byte_num; + unsigned char template_flags[2]; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + retval = sstrtoul(buf, 10, &valid); + if (retval) + return retval; + + if (valid > 0) + valid = 1; + + byte_num = udg->template_index / 8; + offset = udg->template_index % 8; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.template_flags, + template_flags, + sizeof(template_flags)); + if (retval < 0) + return retval; + + if (valid) + template_flags[byte_num] |= (1 << offset); + else + template_flags[byte_num] &= ~(1 << offset); + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.template_flags, + template_flags, + sizeof(template_flags)); + if (retval < 0) + return retval; + +#ifdef STORE_GESTURES + udg_read_valid_data(); +#endif + + return count; +} + +static ssize_t udg_sysfs_template_clear_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + const char cmd[] = {'0', 0}; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + memset(udg->template_data_buf, 0x00, udg->template_data_size); + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.template_data, + udg->template_data_buf, + udg->template_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to clear template data\n", + __func__); + return retval; + } + + retval = udg_sysfs_template_valid_store(dev, attr, cmd, 1); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to clear valid bit\n", + __func__); + return retval; + } + +#ifdef STORE_GESTURES + udg_read_template_data(udg->template_index); + udg_read_valid_data(); +#endif + + return count; +} + +static ssize_t udg_sysfs_trace_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", udg->trace_size); +} + +static ssize_t udg_sysfs_trace_data_show(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + unsigned short index = 0; + unsigned short trace_data_size; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + trace_data_size = udg->trace_size * 5; + + if (trace_data_size == 0) + return -EINVAL; + + if (count < trace_data_size) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not enough space (%d bytes) in buffer\n", + __func__, (unsigned int)count); + return -EINVAL; + } + + if (udg->trace_data_buf_size < trace_data_size) { + if (udg->trace_data_buf_size) + kfree(udg->trace_data_buf); + udg->trace_data_buf = kzalloc(trace_data_size, GFP_KERNEL); + if (!udg->trace_data_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for trace data buffer\n", + __func__); + udg->trace_data_buf_size = 0; + return -ENOMEM; + } + udg->trace_data_buf_size = trace_data_size; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.trace_x, + &udg->trace_data_buf[index], + udg->trace_size * 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read trace X data\n", + __func__); + return retval; + } else { + index += udg->trace_size * 2; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.trace_y, + &udg->trace_data_buf[index], + udg->trace_size * 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read trace Y data\n", + __func__); + return retval; + } else { + index += udg->trace_size * 2; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.trace_segment, + &udg->trace_data_buf[index], + udg->trace_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read trace segment data\n", + __func__); + return retval; + } + + retval = secure_memcpy(buf, count, udg->trace_data_buf, + udg->trace_data_buf_size, trace_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy trace data\n", + __func__); + return retval; + } + + return trace_data_size; +} + +static ssize_t udg_sysfs_template_data_show(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + if (count < udg->template_data_size) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not enough space (%d bytes) in buffer\n", + __func__, (unsigned int)count); + return -EINVAL; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.template_data, + udg->template_data_buf, + udg->template_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read template data\n", + __func__); + return retval; + } + + retval = secure_memcpy(buf, count, udg->template_data_buf, + udg->template_data_size, udg->template_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy template data\n", + __func__); + return retval; + } + +#ifdef STORE_GESTURES + udg_read_template_data(udg->template_index); + udg_read_valid_data(); +#endif + + return udg->template_data_size; +} + +static ssize_t udg_sysfs_template_data_store(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + retval = secure_memcpy(udg->template_data_buf, udg->template_data_size, + buf, count, count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy template data\n", + __func__); + return retval; + } + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.template_data, + udg->template_data_buf, + count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write template data\n", + __func__); + return retval; + } + +#ifdef STORE_GESTURES + udg_read_template_data(udg->template_index); + udg_read_valid_data(); +#endif + + return count; +} + +static ssize_t udg_sysfs_template_displacement_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned short template_displacement; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + template_displacement = + ((unsigned short)udg->tuning.template_disp_lsb << 0) | + ((unsigned short)udg->tuning.template_disp_msb << 8); + + return snprintf(buf, PAGE_SIZE, "%u\n", template_displacement); +} + +static ssize_t udg_sysfs_template_displacement_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long input; + + retval = sstrtoul(buf, 10, &input); + if (retval) + return retval; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + udg->tuning.template_disp_lsb = (unsigned char)(input >> 0); + udg->tuning.template_disp_msb = (unsigned char)(input >> 8); + + retval = udg_write_tuning_params(); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_rotation_invariance_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned short rotation_invariance; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + rotation_invariance = + ((unsigned short)udg->tuning.rotation_inv_lsb << 0) | + ((unsigned short)udg->tuning.rotation_inv_msb << 8); + + return snprintf(buf, PAGE_SIZE, "%u\n", rotation_invariance); +} + +static ssize_t udg_sysfs_rotation_invariance_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long input; + + retval = sstrtoul(buf, 10, &input); + if (retval) + return retval; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + udg->tuning.rotation_inv_lsb = (unsigned char)(input >> 0); + udg->tuning.rotation_inv_msb = (unsigned char)(input >> 8); + + retval = udg_write_tuning_params(); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_scale_invariance_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned short scale_invariance; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + scale_invariance = + ((unsigned short)udg->tuning.scale_inv_lsb << 0) | + ((unsigned short)udg->tuning.scale_inv_msb << 8); + + return snprintf(buf, PAGE_SIZE, "%u\n", scale_invariance); +} + +static ssize_t udg_sysfs_scale_invariance_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long input; + + retval = sstrtoul(buf, 10, &input); + if (retval) + return retval; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + udg->tuning.scale_inv_lsb = (unsigned char)(input >> 0); + udg->tuning.scale_inv_msb = (unsigned char)(input >> 8); + + retval = udg_write_tuning_params(); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_threshold_factor_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned short threshold_factor; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + threshold_factor = + ((unsigned short)udg->tuning.thres_factor_lsb << 0) | + ((unsigned short)udg->tuning.thres_factor_msb << 8); + + return snprintf(buf, PAGE_SIZE, "%u\n", threshold_factor); +} + +static ssize_t udg_sysfs_threshold_factor_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long input; + + retval = sstrtoul(buf, 10, &input); + if (retval) + return retval; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + udg->tuning.thres_factor_lsb = (unsigned char)(input >> 0); + udg->tuning.thres_factor_msb = (unsigned char)(input >> 8); + + retval = udg_write_tuning_params(); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_match_metric_threshold_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned short match_metric_threshold; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + match_metric_threshold = + ((unsigned short)udg->tuning.metric_thres_lsb << 0) | + ((unsigned short)udg->tuning.metric_thres_msb << 8); + + return snprintf(buf, PAGE_SIZE, "%u\n", match_metric_threshold); +} + +static ssize_t udg_sysfs_match_metric_threshold_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long input; + + retval = sstrtoul(buf, 10, &input); + if (retval) + return retval; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + udg->tuning.metric_thres_lsb = (unsigned char)(input >> 0); + udg->tuning.metric_thres_msb = (unsigned char)(input >> 8); + + retval = udg_write_tuning_params(); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_max_inter_stroke_time_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned short max_inter_stroke_time; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + max_inter_stroke_time = + ((unsigned short)udg->tuning.inter_stroke_lsb << 0) | + ((unsigned short)udg->tuning.inter_stroke_msb << 8); + + return snprintf(buf, PAGE_SIZE, "%u\n", max_inter_stroke_time); +} + +static ssize_t udg_sysfs_max_inter_stroke_time_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long input; + + retval = sstrtoul(buf, 10, &input); + if (retval) + return retval; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + udg->tuning.inter_stroke_lsb = (unsigned char)(input >> 0); + udg->tuning.inter_stroke_msb = (unsigned char)(input >> 8); + + retval = udg_write_tuning_params(); + if (retval < 0) + return retval; + + return count; +} + +static int udg_ctrl_subpacket(unsigned char ctrlreg, + unsigned char subpacket, + struct synaptics_rmi4_f12_query_5 *query_5) +{ + int retval; + unsigned char cnt; + unsigned char regnum; + unsigned char bitnum; + unsigned char q5_index; + unsigned char q6_index; + unsigned char offset; + unsigned char max_ctrlreg; + unsigned char *query_6; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + max_ctrlreg = (sizeof(query_5->data) - 1) * 8 - 1; + + if (ctrlreg > max_ctrlreg) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Control register number (%d) over limit\n", + __func__, ctrlreg); + return -EINVAL; + } + + q5_index = ctrlreg / 8 + 1; + bitnum = ctrlreg % 8; + if ((query_5->data[q5_index] & (1 << bitnum)) == 0x00) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Control %d is not present\n", + __func__, ctrlreg); + return -EINVAL; + } + + query_6 = kmalloc(query_5->size_of_query6, GFP_KERNEL); + if (!query_6) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query 6\n", + __func__); + return -ENOMEM; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->query_base_addr + 6, + query_6, + query_5->size_of_query6); + if (retval < 0) + goto exit; + + q6_index = 0; + + for (regnum = 0; regnum < ctrlreg; regnum++) { + q5_index = regnum / 8 + 1; + bitnum = regnum % 8; + if ((query_5->data[q5_index] & (1 << bitnum)) == 0x00) + continue; + + if (query_6[q6_index] == 0x00) + q6_index += 3; + else + q6_index++; + + while (query_6[q6_index] & ~MASK_7BIT) + q6_index++; + + q6_index++; + } + + cnt = 0; + q6_index++; + offset = subpacket / 7; + bitnum = subpacket % 7; + + do { + if (cnt == offset) { + if (query_6[q6_index + cnt] & (1 << bitnum)) + retval = 1; + else + retval = 0; + goto exit; + } + cnt++; + } while (query_6[q6_index + cnt - 1] & ~MASK_7BIT); + + retval = 0; + +exit: + kfree(query_6); + + return retval; +} + +static int udg_read_tuning_params(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_18, + udg->ctrl_buf, + udg->ctrl_18_sub10_off + sizeof(struct udg_tuning)); + if (retval < 0) + return retval; + + secure_memcpy(udg->tuning.data, + sizeof(udg->tuning.data), + (unsigned char *)&udg->ctrl_buf[udg->ctrl_18_sub10_off], + sizeof(struct udg_tuning), + sizeof(struct udg_tuning)); + + return 0; +} + +static int udg_write_tuning_params(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + secure_memcpy((unsigned char *)&udg->ctrl_buf[udg->ctrl_18_sub10_off], + sizeof(struct udg_tuning), + udg->tuning.data, + sizeof(udg->tuning.data), + sizeof(struct udg_tuning)); + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_18, + udg->ctrl_buf, + udg->ctrl_18_sub10_off + sizeof(struct udg_tuning)); + if (retval < 0) + return retval; + + return 0; +} + +static int udg_detection_enable(bool enable) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_20, + udg->ctrl_buf, + udg->ctrl_20_sub1_off + 1); + if (retval < 0) + return retval; + + if (enable) + udg->ctrl_buf[udg->ctrl_20_sub1_off] = WAKEUP_GESTURE_MODE; + else + udg->ctrl_buf[udg->ctrl_20_sub1_off] = udg->report_flags; + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_20, + udg->ctrl_buf, + udg->ctrl_20_sub1_off + 1); + if (retval < 0) + return retval; + + return 0; +} + +static int udg_engine_enable(bool enable) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + if (enable) { + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_27, + udg->ctrl_buf, + udg->ctrl_27_sub5_off + 1); + if (retval < 0) + return retval; + + udg->ctrl_buf[udg->ctrl_27_sub5_off] |= + (1 << CTRL27_UDG_ENABLE_BIT); + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_27, + udg->ctrl_buf, + udg->ctrl_27_sub5_off + 1); + if (retval < 0) + return retval; + } else { + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_27, + udg->ctrl_buf, + udg->ctrl_27_sub5_off + 1); + if (retval < 0) + return retval; + + udg->ctrl_buf[udg->ctrl_27_sub5_off] &= + ~(1 << CTRL27_UDG_ENABLE_BIT); + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_27, + udg->ctrl_buf, + udg->ctrl_27_sub5_off + 1); + if (retval < 0) + return retval; + } + + return 0; +} + +static void udg_report(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + atomic_set(&udg->attn_event, 1); + + if (rmi4_data->suspend) { + if (rmi4_data->gesture_detection[0] == 0) { + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.data_4, + rmi4_data->gesture_detection, + sizeof(rmi4_data->gesture_detection)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read gesture detection\n", + __func__); + return; + } + } + + udg->detection_status = rmi4_data->gesture_detection[0]; + rmi4_data->gesture_detection[0] = 0; + + if (udg->detection_status == DETECTION) { + input_report_key(udg->udg_dev, KEY_WAKEUP, 1); + input_sync(udg->udg_dev); + input_report_key(udg->udg_dev, KEY_WAKEUP, 0); + input_sync(udg->udg_dev); + rmi4_data->suspend = false; + } + } + + return; +} + +static int udg_set_index(unsigned char index) +{ + int retval; + struct synaptics_rmi4_f12_control_41 control_41; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + if (index >= udg->max_num_templates) + return -EINVAL; + + udg->template_index = index; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_41, + control_41.data, + sizeof(control_41.data)); + if (retval < 0) + return retval; + + control_41.template_index = udg->template_index; + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_41, + control_41.data, + sizeof(control_41.data)); + if (retval < 0) + return retval; + + return 0; +} + +#ifdef STORE_GESTURES +static int udg_read_valid_data(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.template_flags, + udg->valid_buf, + sizeof(udg->valid_buf)); + if (retval < 0) + return retval; + + return 0; +} + +static int udg_write_valid_data(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.template_flags, + udg->valid_buf, + sizeof(udg->valid_buf)); + if (retval < 0) + return retval; + + return 0; +} + +static int udg_read_template_data(unsigned char index) +{ + int retval; + unsigned char *storage; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + udg_set_index(index); + storage = &(udg->storage_buf[index * udg->template_data_size]); + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.template_data, + storage, + udg->template_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read template data\n", + __func__); + return retval; + } + + return 0; +} + +static int udg_write_template_data(void) +{ + int retval; + unsigned char ii; + unsigned char *storage; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + for (ii = 0; ii < udg->gestures_to_store; ii++) { + udg_set_index(ii); + storage = &(udg->storage_buf[ii * udg->template_data_size]); + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.template_data, + storage, + udg->template_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write template data\n", + __func__); + return retval; + } + } + + return 0; +} +#endif + +static int udg_reg_init(void) +{ + int retval; + unsigned char ii; + unsigned char data_offset; + unsigned char size_of_query; + unsigned char ctrl_18_offset; + unsigned char ctrl_20_offset; + unsigned char ctrl_23_offset; + unsigned char ctrl_27_offset; + unsigned char ctrl_41_offset; + struct synaptics_rmi4_f12_query_0 query_0; + struct synaptics_rmi4_f12_query_5 query_5; + struct synaptics_rmi4_f12_query_8 query_8; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->query_base_addr + 7, + &size_of_query, + sizeof(size_of_query)); + if (retval < 0) + return retval; + + if (size_of_query < 4) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: User defined gesture support unavailable (missing data registers)\n", + __func__); + retval = -ENODEV; + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->query_base_addr + 8, + query_8.data, + sizeof(query_8.data)); + if (retval < 0) + return retval; + + if ((query_8.data16_is_present) && + (query_8.data17_is_present) && + (query_8.data18_is_present) && + (query_8.data19_is_present) && + (query_8.data20_is_present) && + (query_8.data21_is_present)) { + data_offset = query_8.data0_is_present + + query_8.data1_is_present + + query_8.data2_is_present + + query_8.data3_is_present; + udg->addr.data_4 = udg->data_base_addr + data_offset; + data_offset = data_offset + + query_8.data4_is_present + + query_8.data5_is_present + + query_8.data6_is_present + + query_8.data7_is_present + + query_8.data8_is_present + + query_8.data9_is_present + + query_8.data10_is_present + + query_8.data11_is_present + + query_8.data12_is_present + + query_8.data13_is_present + + query_8.data14_is_present + + query_8.data15_is_present; + udg->addr.trace_x = udg->data_base_addr + data_offset; + udg->addr.trace_y = udg->addr.trace_x + 1; + udg->addr.trace_segment = udg->addr.trace_y + 1; + udg->addr.template_helper = udg->addr.trace_segment + 1; + udg->addr.template_data = udg->addr.template_helper + 1; + udg->addr.template_flags = udg->addr.template_data + 1; + } else { + dev_err(rmi4_data->pdev->dev.parent, + "%s: User defined gesture support unavailable (missing data registers)\n", + __func__); + retval = -ENODEV; + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->query_base_addr + 4, + &size_of_query, + sizeof(size_of_query)); + if (retval < 0) + return retval; + + if (size_of_query < 7) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: User defined gesture support unavailable (missing control registers)\n", + __func__); + retval = -ENODEV; + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->query_base_addr + 5, + query_5.data, + sizeof(query_5.data)); + if (retval < 0) + return retval; + + ctrl_18_offset = query_5.ctrl0_is_present + + query_5.ctrl1_is_present + + query_5.ctrl2_is_present + + query_5.ctrl3_is_present + + query_5.ctrl4_is_present + + query_5.ctrl5_is_present + + query_5.ctrl6_is_present + + query_5.ctrl7_is_present + + query_5.ctrl8_is_present + + query_5.ctrl9_is_present + + query_5.ctrl10_is_present + + query_5.ctrl11_is_present + + query_5.ctrl12_is_present + + query_5.ctrl13_is_present + + query_5.ctrl14_is_present + + query_5.ctrl15_is_present + + query_5.ctrl16_is_present + + query_5.ctrl17_is_present; + + ctrl_20_offset = ctrl_18_offset + + query_5.ctrl18_is_present + + query_5.ctrl19_is_present; + + ctrl_23_offset = ctrl_20_offset + + query_5.ctrl20_is_present + + query_5.ctrl21_is_present + + query_5.ctrl22_is_present; + + ctrl_27_offset = ctrl_23_offset+ + query_5.ctrl23_is_present + + query_5.ctrl24_is_present + + query_5.ctrl25_is_present + + query_5.ctrl26_is_present; + + ctrl_41_offset = ctrl_27_offset+ + query_5.ctrl27_is_present + + query_5.ctrl28_is_present + + query_5.ctrl29_is_present + + query_5.ctrl30_is_present + + query_5.ctrl31_is_present + + query_5.ctrl32_is_present + + query_5.ctrl33_is_present + + query_5.ctrl34_is_present + + query_5.ctrl35_is_present + + query_5.ctrl36_is_present + + query_5.ctrl37_is_present + + query_5.ctrl38_is_present + + query_5.ctrl39_is_present + + query_5.ctrl40_is_present; + + udg->addr.ctrl_18 = udg->control_base_addr + ctrl_18_offset; + udg->addr.ctrl_20 = udg->control_base_addr + ctrl_20_offset; + udg->addr.ctrl_23 = udg->control_base_addr + ctrl_23_offset; + udg->addr.ctrl_27 = udg->control_base_addr + ctrl_27_offset; + udg->addr.ctrl_41 = udg->control_base_addr + ctrl_41_offset; + + udg->ctrl_18_sub10_off = 0; + for (ii = 0; ii < 10; ii++) { + retval = udg_ctrl_subpacket(18, ii, &query_5); + if (retval == 1) + udg->ctrl_18_sub10_off += ctrl_18_sub_size[ii]; + else if (retval < 0) + return retval; + } + + udg->ctrl_20_sub1_off = 0; + for (ii = 0; ii < 1; ii++) { + retval = udg_ctrl_subpacket(20, ii, &query_5); + if (retval == 1) + udg->ctrl_20_sub1_off += ctrl_20_sub_size[ii]; + else if (retval < 0) + return retval; + } + + udg->ctrl_23_sub3_off = 0; + for (ii = 0; ii < 3; ii++) { + retval = udg_ctrl_subpacket(23, ii, &query_5); + if (retval == 1) + udg->ctrl_23_sub3_off += ctrl_23_sub_size[ii]; + else if (retval < 0) + return retval; + } + + retval = udg_ctrl_subpacket(23, 3, &query_5); + if (retval == 0) + udg->ctrl_23_sub3_off = 0; + else if (retval < 0) + return retval; + + udg->ctrl_27_sub5_off = 0; + for (ii = 0; ii < 5; ii++) { + retval = udg_ctrl_subpacket(27, ii, &query_5); + if (retval == 1) + udg->ctrl_27_sub5_off += ctrl_27_sub_size[ii]; + else if (retval < 0) + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->query_base_addr + 0, + query_0.data, + sizeof(query_0.data)); + if (retval < 0) + return retval; + + udg->max_num_templates = query_0.max_num_templates; + udg->template_size = + ((unsigned short)query_0.template_size_lsb << 0) | + ((unsigned short)query_0.template_size_msb << 8); + udg->template_data_size = udg->template_size * 4 * 2 + 4 + 1; + +#ifdef STORE_GESTURES + udg->gestures_to_store = udg->max_num_templates; + if (GESTURES_TO_STORE < udg->gestures_to_store) + udg->gestures_to_store = GESTURES_TO_STORE; +#endif + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_20, + udg->ctrl_buf, + udg->ctrl_20_sub1_off + 1); + if (retval < 0) + return retval; + + udg->report_flags = udg->ctrl_buf[udg->ctrl_20_sub1_off]; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_23, + udg->ctrl_buf, + udg->ctrl_23_sub3_off + 1); + if (retval < 0) + return retval; + + udg->object_type_enable1 = udg->ctrl_buf[0]; + if (udg->ctrl_23_sub3_off) + udg->object_type_enable2 = udg->ctrl_buf[udg->ctrl_23_sub3_off]; + + return retval; +} + +static int udg_scan_pdt(void) +{ + int retval; + unsigned char ii; + unsigned char page; + unsigned char intr_count = 0; + unsigned char intr_off; + unsigned char intr_src; + unsigned short addr; + struct synaptics_rmi4_fn_desc fd; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + for (page = 0; page < PAGES_TO_SERVICE; page++) { + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + addr |= (page << 8); + + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&fd, + sizeof(fd)); + if (retval < 0) + return retval; + + addr &= ~(MASK_8BIT << 8); + + if (fd.fn_number) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Found F%02x\n", + __func__, fd.fn_number); + switch (fd.fn_number) { + case SYNAPTICS_RMI4_F12: + goto f12_found; + break; + } + } else { + break; + } + + intr_count += fd.intr_src_count; + } + } + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F12\n", + __func__); + return -EINVAL; + +f12_found: + udg->query_base_addr = fd.query_base_addr | (page << 8); + udg->control_base_addr = fd.ctrl_base_addr | (page << 8); + udg->data_base_addr = fd.data_base_addr | (page << 8); + udg->command_base_addr = fd.cmd_base_addr | (page << 8); + + retval = udg_reg_init(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to initialize user defined gesture registers\n", + __func__); + return retval; + } + + udg->intr_mask = 0; + intr_src = fd.intr_src_count; + intr_off = intr_count % 8; + for (ii = intr_off; + ii < (intr_src + intr_off); + ii++) { + udg->intr_mask |= 1 << ii; + } + + rmi4_data->intr_mask[0] |= udg->intr_mask; + + addr = rmi4_data->f01_ctrl_base_addr + 1; + + retval = synaptics_rmi4_reg_write(rmi4_data, + addr, + &rmi4_data->intr_mask[0], + sizeof(rmi4_data->intr_mask[0])); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set interrupt enable bit\n", + __func__); + return retval; + } + + return 0; +} + +static void synaptics_rmi4_udg_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!udg) + return; + + if (udg->intr_mask & intr_mask) + udg_report(); + + return; +} + +static int synaptics_rmi4_udg_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char ii; + unsigned char size; + unsigned char attr_count; + unsigned char param_count; + + if (udg) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + udg = kzalloc(sizeof(*udg), GFP_KERNEL); + if (!udg) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for udg\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + size = 0; + for (ii = 0; ii < sizeof(ctrl_18_sub_size); ii++) + size += ctrl_18_sub_size[ii]; + size += sizeof(struct udg_tuning); + udg->ctrl_buf = kzalloc(size, GFP_KERNEL); + if (!udg->ctrl_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for ctrl_buf\n", + __func__); + retval = -ENOMEM; + goto exit_free_udg; + } + + udg->rmi4_data = rmi4_data; + + retval = udg_scan_pdt(); + if (retval < 0) + goto exit_free_ctrl_buf; + + udg->template_data_buf = kzalloc(udg->template_data_size, GFP_KERNEL); + if (!udg->template_data_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for template_data_buf\n", + __func__); + retval = -ENOMEM; + goto exit_free_ctrl_buf; + } + +#ifdef STORE_GESTURES + udg->storage_buf = kzalloc( + udg->template_data_size * udg->gestures_to_store, + GFP_KERNEL); + if (!udg->storage_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for storage_buf\n", + __func__); + kfree(udg->template_data_buf); + retval = -ENOMEM; + goto exit_free_ctrl_buf; + } +#endif + + udg->udg_dev = input_allocate_device(); + if (udg->udg_dev == NULL) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate gesture device\n", + __func__); + retval = -ENOMEM; + goto exit_free_template_data_buf; + } + + udg->udg_dev->name = GESTURE_DRIVER_NAME; + udg->udg_dev->phys = GESTURE_PHYS_NAME; + udg->udg_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT; + udg->udg_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION; + udg->udg_dev->dev.parent = rmi4_data->pdev->dev.parent; + input_set_drvdata(udg->udg_dev, rmi4_data); + + set_bit(EV_KEY, udg->udg_dev->evbit); + set_bit(KEY_WAKEUP, udg->udg_dev->keybit); + input_set_capability(udg->udg_dev, EV_KEY, KEY_WAKEUP); + + retval = input_register_device(udg->udg_dev); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to register gesture device\n", + __func__); + input_free_device(udg->udg_dev); + goto exit_free_template_data_buf; + } + + udg->tuning_dir = kobject_create_and_add(TUNING_SYSFS_DIR_NAME, + &udg->udg_dev->dev.kobj); + if (!udg->tuning_dir) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create tuning sysfs directory\n", + __func__); + goto exit_unregister_input_device; + } + + retval = sysfs_create_bin_file(&udg->udg_dev->dev.kobj, &template_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create template data bin file\n", + __func__); + goto exit_remove_sysfs_directory; + } + + retval = sysfs_create_bin_file(&udg->udg_dev->dev.kobj, &trace_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create trace data bin file\n", + __func__); + goto exit_remove_bin_file; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&udg->udg_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + retval = -ENODEV; + goto exit_remove_attrs; + } + } + + for (param_count = 0; param_count < ARRAY_SIZE(params); param_count++) { + retval = sysfs_create_file(udg->tuning_dir, + ¶ms[param_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create tuning parameters\n", + __func__); + retval = -ENODEV; + goto exit_remove_params; + } + } + + retval = udg_engine_enable(true); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to enable gesture engine\n", + __func__); + goto exit_remove_params; + } + + return 0; + +exit_remove_params: + for (param_count--; param_count >= 0; param_count--) { + sysfs_remove_file(udg->tuning_dir, + ¶ms[param_count].attr); + } + +exit_remove_attrs: + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&udg->udg_dev->dev.kobj, + &attrs[attr_count].attr); + } + + sysfs_remove_bin_file(&udg->udg_dev->dev.kobj, &trace_data); + +exit_remove_bin_file: + sysfs_remove_bin_file(&udg->udg_dev->dev.kobj, &template_data); + +exit_remove_sysfs_directory: + kobject_put(udg->tuning_dir); + +exit_unregister_input_device: + input_unregister_device(udg->udg_dev); + +exit_free_template_data_buf: +#ifdef STORE_GESTURES + kfree(udg->storage_buf); +#endif + kfree(udg->template_data_buf); + +exit_free_ctrl_buf: + kfree(udg->ctrl_buf); + +exit_free_udg: + kfree(udg); + udg = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_udg_remove(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char count; + + if (!udg) + goto exit; + + for (count = 0; count < ARRAY_SIZE(params); count++) { + sysfs_remove_file(udg->tuning_dir, + ¶ms[count].attr); + } + + for (count = 0; count < ARRAY_SIZE(attrs); count++) { + sysfs_remove_file(&udg->udg_dev->dev.kobj, + &attrs[count].attr); + } + + sysfs_remove_bin_file(&udg->udg_dev->dev.kobj, &trace_data); + sysfs_remove_bin_file(&udg->udg_dev->dev.kobj, &template_data); + kobject_put(udg->tuning_dir); + + input_unregister_device(udg->udg_dev); +#ifdef STORE_GESTURES + kfree(udg->storage_buf); +#endif + kfree(udg->template_data_buf); + kfree(udg->trace_data_buf); + kfree(udg->ctrl_buf); + kfree(udg); + udg = NULL; + +exit: + complete(&udg_remove_complete); + + return; +} + +static void synaptics_rmi4_udg_reset(struct synaptics_rmi4_data *rmi4_data) +{ + if (!udg) { + synaptics_rmi4_udg_init(rmi4_data); + return; + } + + udg_scan_pdt(); + udg_engine_enable(true); +#ifdef STORE_GESTURES + udg_write_template_data(); + udg_write_valid_data(); +#endif + + return; +} + +static void synaptics_rmi4_udg_reinit(struct synaptics_rmi4_data *rmi4_data) +{ + if (!udg) + return; + + udg_engine_enable(true); +#ifdef STORE_GESTURES + udg_write_template_data(); + udg_write_valid_data(); +#endif + + return; +} + +static void synaptics_rmi4_udg_e_suspend(struct synaptics_rmi4_data *rmi4_data) +{ + if (!udg) + return; + + rmi4_data->sleep_enable(rmi4_data, false); + rmi4_data->irq_enable(rmi4_data, true, false); + enable_irq_wake(rmi4_data->irq); + + udg_engine_enable(true); + udg_detection_enable(true); + + return; +} + +static void synaptics_rmi4_udg_suspend(struct synaptics_rmi4_data *rmi4_data) +{ + if (!udg) + return; + + rmi4_data->sleep_enable(rmi4_data, false); + rmi4_data->irq_enable(rmi4_data, true, false); + enable_irq_wake(rmi4_data->irq); + + udg_engine_enable(true); + udg_detection_enable(true); + + return; +} + +static void synaptics_rmi4_udg_resume(struct synaptics_rmi4_data *rmi4_data) +{ + if (!udg) + return; + + disable_irq_wake(rmi4_data->irq); + udg_detection_enable(false); + + return; +} + +static void synaptics_rmi4_udg_l_resume(struct synaptics_rmi4_data *rmi4_data) +{ + if (!udg) + return; + + disable_irq_wake(rmi4_data->irq); + udg_detection_enable(false); + + return; +} + +static struct synaptics_rmi4_exp_fn gesture_module = { + .fn_type = RMI_GESTURE, + .init = synaptics_rmi4_udg_init, + .remove = synaptics_rmi4_udg_remove, + .reset = synaptics_rmi4_udg_reset, + .reinit = synaptics_rmi4_udg_reinit, + .early_suspend = synaptics_rmi4_udg_e_suspend, + .suspend = synaptics_rmi4_udg_suspend, + .resume = synaptics_rmi4_udg_resume, + .late_resume = synaptics_rmi4_udg_l_resume, + .attn = synaptics_rmi4_udg_attn, +}; + +static int __init rmi4_gesture_module_init(void) +{ + synaptics_rmi4_new_function(&gesture_module, true); + + return 0; +} + +static void __exit rmi4_gesture_module_exit(void) +{ + synaptics_rmi4_new_function(&gesture_module, false); + + wait_for_completion(&udg_remove_complete); + + return; +} + +module_init(rmi4_gesture_module_init); +module_exit(rmi4_gesture_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX User Defined Gesture Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310/synaptics_dsx_i2c.c b/drivers/input/touchscreen/td4310/synaptics_dsx_i2c.c new file mode 100644 index 0000000000000..412ec8a974aeb --- /dev/null +++ b/drivers/input/touchscreen/td4310/synaptics_dsx_i2c.c @@ -0,0 +1,649 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define SYN_I2C_RETRY_TIMES 2 + +/* +#define I2C_BURST_LIMIT 255 +*/ +/* +#define XFER_MSGS_LIMIT 8 +*/ + +static unsigned char *wr_buf; + +static struct synaptics_dsx_hw_interface hw_if; + +static struct platform_device *synaptics_dsx_i2c_device; + +#ifdef CONFIG_OF +static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata) +{ + int retval; + u32 value; + const char *name; + struct property *prop; + struct device_node *np = dev->of_node; + + bdata->irq_gpio = of_get_named_gpio_flags(np, + "synaptics,irq-gpio", 0, + (enum of_gpio_flags *)&bdata->irq_flags); + bdata->reset_gpio = of_get_named_gpio_flags(np, + "synaptics,rst-gpio", 0, + NULL); +printk("reset gpio : %d\n", bdata->reset_gpio); + retval = of_property_read_u32(np, "synaptics,irq-on-state", + &value); + if (retval < 0) + bdata->irq_on_state = 0; + else + bdata->irq_on_state = value; + + retval = of_property_read_string(np, "synaptics,pwr-reg-name", &name); + if (retval < 0) + bdata->pwr_reg_name = NULL; + else + bdata->pwr_reg_name = name; + + retval = of_property_read_string(np, "synaptics,bus-reg-name", &name); + if (retval < 0) + bdata->bus_reg_name = NULL; + else + bdata->bus_reg_name = name; + + prop = of_find_property(np, "synaptics,power-gpio", NULL); + if (prop && prop->length) { + bdata->power_gpio = of_get_named_gpio_flags(np, + "synaptics,power-gpio", 0, NULL); + retval = of_property_read_u32(np, "synaptics,power-on-state", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,power-on-state property\n", + __func__); + return retval; + } else { + bdata->power_on_state = value; + } + } else { + bdata->power_gpio = -1; + } + + prop = of_find_property(np, "synaptics,power-delay-ms", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,power-delay-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,power-delay-ms property\n", + __func__); + return retval; + } else { + bdata->power_delay_ms = value; + } + } else { + bdata->power_delay_ms = 0; + } + + prop = of_find_property(np, "synaptics,reset-gpio", NULL); + if (prop && prop->length) { + bdata->reset_gpio = of_get_named_gpio_flags(np, + "synaptics,reset-gpio", 0, NULL); + retval = of_property_read_u32(np, "synaptics,reset-on-state", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-on-state property\n", + __func__); + return retval; + } else { + bdata->reset_on_state = value; + } + retval = of_property_read_u32(np, "synaptics,reset-active-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-active-ms property\n", + __func__); + return retval; + } else { + bdata->reset_active_ms = value; + } + } else { + bdata->reset_gpio = -1; + } + + prop = of_find_property(np, "synaptics,reset-delay-ms", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,reset-delay-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-delay-ms property\n", + __func__); + return retval; + } else { + bdata->reset_delay_ms = value; + } + } else { + bdata->reset_delay_ms = 0; + } + + prop = of_find_property(np, "synaptics,max-y-for-2d", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,max-y-for-2d", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,max-y-for-2d property\n", + __func__); + return retval; + } else { + bdata->max_y_for_2d = value; + } + } else { + bdata->max_y_for_2d = -1; + } + + prop = of_find_property(np, "synaptics,swap-axes", NULL); + bdata->swap_axes = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,x-flip", NULL); + bdata->x_flip = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,y-flip", NULL); + bdata->y_flip = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,ub-i2c-addr", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,ub-i2c-addr", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,ub-i2c-addr property\n", + __func__); + return retval; + } else { + bdata->ub_i2c_addr = (unsigned short)value; + } + } else { + bdata->ub_i2c_addr = -1; + } + + prop = of_find_property(np, "synaptics,cap-button-codes", NULL); + if (prop && prop->length) { + bdata->cap_button_map->map = devm_kzalloc(dev, + prop->length, + GFP_KERNEL); + if (!bdata->cap_button_map->map) + return -ENOMEM; + bdata->cap_button_map->nbuttons = prop->length / sizeof(u32); + retval = of_property_read_u32_array(np, + "synaptics,cap-button-codes", + bdata->cap_button_map->map, + bdata->cap_button_map->nbuttons); + if (retval < 0) { + bdata->cap_button_map->nbuttons = 0; + bdata->cap_button_map->map = NULL; + } + } else { + bdata->cap_button_map->nbuttons = 0; + bdata->cap_button_map->map = NULL; + } + + prop = of_find_property(np, "synaptics,vir-button-codes", NULL); + if (prop && prop->length) { + bdata->vir_button_map->map = devm_kzalloc(dev, + prop->length, + GFP_KERNEL); + if (!bdata->vir_button_map->map) + return -ENOMEM; + bdata->vir_button_map->nbuttons = prop->length / sizeof(u32); + bdata->vir_button_map->nbuttons /= 5; + retval = of_property_read_u32_array(np, + "synaptics,vir-button-codes", + bdata->vir_button_map->map, + bdata->vir_button_map->nbuttons * 5); + if (retval < 0) { + bdata->vir_button_map->nbuttons = 0; + bdata->vir_button_map->map = NULL; + } + } else { + bdata->vir_button_map->nbuttons = 0; + bdata->vir_button_map->map = NULL; + } + + return 0; +} +#endif + +static int synaptics_rmi4_i2c_alloc_buf(struct synaptics_rmi4_data *rmi4_data, + unsigned int count) +{ + static unsigned int buf_size; + + if (count > buf_size) { + if (buf_size) + kfree(wr_buf); + wr_buf = kzalloc(count, GFP_KERNEL); + if (!wr_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for buffer\n", + __func__); + buf_size = 0; + return -ENOMEM; + } + buf_size = count; + } + + return 0; +} + +static void synaptics_rmi4_i2c_check_addr(struct synaptics_rmi4_data *rmi4_data, + struct i2c_client *i2c) +{ + if (hw_if.board_data->ub_i2c_addr == -1) + return; + + if (hw_if.board_data->i2c_addr == i2c->addr) + hw_if.board_data->i2c_addr = hw_if.board_data->ub_i2c_addr; + else + hw_if.board_data->i2c_addr = i2c->addr; + + return; +} + +static int synaptics_rmi4_i2c_set_page(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr) +{ + int retval; + unsigned char retry; + unsigned char buf[PAGE_SELECT_LEN]; + unsigned char page; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + struct i2c_msg msg[1]; + + msg[0].addr = hw_if.board_data->i2c_addr; + msg[0].flags = 0; + msg[0].len = PAGE_SELECT_LEN; + msg[0].buf = buf; + + page = ((addr >> 8) & MASK_8BIT); + buf[0] = MASK_8BIT; + buf[1] = page; + + if (page != rmi4_data->current_page) { + for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) { + if (i2c_transfer(i2c->adapter, msg, 1) == 1) { + rmi4_data->current_page = page; + retval = PAGE_SELECT_LEN; + break; + } + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C retry %d\n", + __func__, retry + 1); + msleep(20); + + if (retry == SYN_I2C_RETRY_TIMES / 2) { + synaptics_rmi4_i2c_check_addr(rmi4_data, i2c); + msg[0].addr = hw_if.board_data->i2c_addr; + } + } + } else { + retval = PAGE_SELECT_LEN; + } + + return retval; +} + +static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, unsigned char *data, unsigned int length) +{ + int retval; + unsigned char retry; + unsigned char buf; +#ifdef I2C_BURST_LIMIT + unsigned int ii; + unsigned int rd_msgs = ((length - 1) / I2C_BURST_LIMIT) + 1; +#else + unsigned int rd_msgs = 1; +#endif + unsigned char index = 0; + unsigned char xfer_msgs; + unsigned char remaining_msgs; + unsigned short i2c_addr; + unsigned short data_offset = 0; + unsigned int remaining_length = length; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + struct i2c_adapter *adap = i2c->adapter; + struct i2c_msg msg[rd_msgs + 1]; + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + retval = synaptics_rmi4_i2c_set_page(rmi4_data, addr); + if (retval != PAGE_SELECT_LEN) { + retval = -EIO; + goto exit; + } + + msg[0].addr = hw_if.board_data->i2c_addr; + msg[0].flags = 0; + msg[0].len = 1; + msg[0].buf = &buf; + +#ifdef I2C_BURST_LIMIT + for (ii = 0; ii < (rd_msgs - 1); ii++) { + msg[ii + 1].addr = hw_if.board_data->i2c_addr; + msg[ii + 1].flags = I2C_M_RD; + msg[ii + 1].len = I2C_BURST_LIMIT; + msg[ii + 1].buf = &data[data_offset]; + data_offset += I2C_BURST_LIMIT; + remaining_length -= I2C_BURST_LIMIT; + } +#endif + + msg[rd_msgs].addr = hw_if.board_data->i2c_addr; + msg[rd_msgs].flags = I2C_M_RD; + msg[rd_msgs].len = (unsigned short)remaining_length; + msg[rd_msgs].buf = &data[data_offset]; + + buf = addr & MASK_8BIT; + + remaining_msgs = rd_msgs + 1; + + while (remaining_msgs) { +#ifdef XFER_MSGS_LIMIT + if (remaining_msgs > XFER_MSGS_LIMIT) + xfer_msgs = XFER_MSGS_LIMIT; + else + xfer_msgs = remaining_msgs; +#else + xfer_msgs = remaining_msgs; +#endif + for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) { + retval = i2c_transfer(adap, &msg[index], xfer_msgs); + if (retval == xfer_msgs) + break; + + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C retry %d\n", + __func__, retry + 1); + msleep(20); + + if (retry == SYN_I2C_RETRY_TIMES / 2) { + synaptics_rmi4_i2c_check_addr(rmi4_data, i2c); + i2c_addr = hw_if.board_data->i2c_addr; + msg[0].addr = i2c_addr; +#ifdef I2C_BURST_LIMIT + for (ii = 0; ii < (rd_msgs - 1); ii++) + msg[ii + 1].addr = i2c_addr; +#endif + msg[rd_msgs].addr = i2c_addr; + } + } + + if (retry == SYN_I2C_RETRY_TIMES) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C read over retry limit\n", + __func__); + retval = -EIO; + goto exit; + } + + remaining_msgs -= xfer_msgs; + index += xfer_msgs; + } + + retval = length; + +exit: + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, unsigned char *data, unsigned int length) +{ + int retval; + unsigned char retry; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + struct i2c_msg msg[1]; + + retval = synaptics_rmi4_i2c_alloc_buf(rmi4_data, length + 1); + if (retval < 0) + return retval; + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + retval = synaptics_rmi4_i2c_set_page(rmi4_data, addr); + if (retval != PAGE_SELECT_LEN) { + retval = -EIO; + goto exit; + } + + msg[0].addr = hw_if.board_data->i2c_addr; + msg[0].flags = 0; + msg[0].len = (unsigned short)(length + 1); + msg[0].buf = wr_buf; + + wr_buf[0] = addr & MASK_8BIT; + retval = secure_memcpy(&wr_buf[1], length, &data[0], length, length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy data\n", + __func__); + goto exit; + } + + for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) { + if (i2c_transfer(i2c->adapter, msg, 1) == 1) { + retval = length; + break; + } + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C retry %d\n", + __func__, retry + 1); + msleep(20); + + if (retry == SYN_I2C_RETRY_TIMES / 2) { + synaptics_rmi4_i2c_check_addr(rmi4_data, i2c); + msg[0].addr = hw_if.board_data->i2c_addr; + } + } + + if (retry == SYN_I2C_RETRY_TIMES) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C write over retry limit\n", + __func__); + retval = -EIO; + } + +exit: + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static struct synaptics_dsx_bus_access bus_access = { + .type = BUS_I2C, + .read = synaptics_rmi4_i2c_read, + .write = synaptics_rmi4_i2c_write, +}; + +static void synaptics_rmi4_i2c_dev_release(struct device *dev) +{ + kfree(synaptics_dsx_i2c_device); + + return; +} + +static int synaptics_rmi4_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int retval; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, + "%s: SMBus byte data commands not supported by host\n", + __func__); + return -EIO; + } + + synaptics_dsx_i2c_device = kzalloc( + sizeof(struct platform_device), + GFP_KERNEL); + if (!synaptics_dsx_i2c_device) { + dev_err(&client->dev, + "%s: Failed to allocate memory for synaptics_dsx_i2c_device\n", + __func__); + return -ENOMEM; + } + +#ifdef CONFIG_OF + if (client->dev.of_node) { + hw_if.board_data = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_board_data), + GFP_KERNEL); + if (!hw_if.board_data) { + dev_err(&client->dev, + "%s: Failed to allocate memory for board data\n", + __func__); + return -ENOMEM; + } + hw_if.board_data->cap_button_map = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_button_map), + GFP_KERNEL); + if (!hw_if.board_data->cap_button_map) { + dev_err(&client->dev, + "%s: Failed to allocate memory for 0D button map\n", + __func__); + return -ENOMEM; + } + hw_if.board_data->vir_button_map = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_button_map), + GFP_KERNEL); + if (!hw_if.board_data->vir_button_map) { + dev_err(&client->dev, + "%s: Failed to allocate memory for virtual button map\n", + __func__); + return -ENOMEM; + } + parse_dt(&client->dev, hw_if.board_data); + } +#else + hw_if.board_data = client->dev.platform_data; +#endif + + hw_if.bus_access = &bus_access; + hw_if.board_data->i2c_addr = client->addr; + + synaptics_dsx_i2c_device->name = PLATFORM_DRIVER_NAME; + synaptics_dsx_i2c_device->id = 0; + synaptics_dsx_i2c_device->num_resources = 0; + synaptics_dsx_i2c_device->dev.parent = &client->dev; + synaptics_dsx_i2c_device->dev.platform_data = &hw_if; + synaptics_dsx_i2c_device->dev.release = synaptics_rmi4_i2c_dev_release; + + retval = platform_device_register(synaptics_dsx_i2c_device); + if (retval) { + dev_err(&client->dev, + "%s: Failed to register platform device\n", + __func__); + return -ENODEV; + } + + return 0; +} + +static int synaptics_rmi4_i2c_remove(struct i2c_client *client) +{ + platform_device_unregister(synaptics_dsx_i2c_device); + + return 0; +} + +static const struct i2c_device_id synaptics_rmi4_id_table[] = { + {I2C_DRIVER_NAME, 0}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, synaptics_rmi4_id_table); + +#ifdef CONFIG_OF +static struct of_device_id synaptics_rmi4_of_match_table[] = { + { + .compatible = "synaptics,dsx-i2c", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, synaptics_rmi4_of_match_table); +#else +#define synaptics_rmi4_of_match_table NULL +#endif + +static struct i2c_driver synaptics_rmi4_i2c_driver = { + .driver = { + .name = I2C_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = synaptics_rmi4_of_match_table, + }, + .probe = synaptics_rmi4_i2c_probe, + .remove = synaptics_rmi4_i2c_remove, + .id_table = synaptics_rmi4_id_table, +}; + +int synaptics_rmi4_bus_init(void) +{ + return i2c_add_driver(&synaptics_rmi4_i2c_driver); +} +EXPORT_SYMBOL(synaptics_rmi4_bus_init); + +void synaptics_rmi4_bus_exit(void) +{ + kfree(wr_buf); + + i2c_del_driver(&synaptics_rmi4_i2c_driver); + + return; +} +EXPORT_SYMBOL(synaptics_rmi4_bus_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX I2C Bus Support Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310/synaptics_dsx_proximity.c b/drivers/input/touchscreen/td4310/synaptics_dsx_proximity.c new file mode 100644 index 0000000000000..67d9e0a094551 --- /dev/null +++ b/drivers/input/touchscreen/td4310/synaptics_dsx_proximity.c @@ -0,0 +1,692 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define PROX_PHYS_NAME "synaptics_dsx/proximity" + +#define HOVER_Z_MAX (255) + +#define HOVERING_FINGER_EN (1 << 4) + +static ssize_t synaptics_rmi4_hover_finger_en_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_hover_finger_en_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static struct device_attribute attrs[] = { + __ATTR(hover_finger_en, (S_IRUGO | S_IWUGO), + synaptics_rmi4_hover_finger_en_show, + synaptics_rmi4_hover_finger_en_store), +}; + +struct synaptics_rmi4_f12_query_5 { + union { + struct { + unsigned char size_of_query6; + struct { + unsigned char ctrl0_is_present:1; + unsigned char ctrl1_is_present:1; + unsigned char ctrl2_is_present:1; + unsigned char ctrl3_is_present:1; + unsigned char ctrl4_is_present:1; + unsigned char ctrl5_is_present:1; + unsigned char ctrl6_is_present:1; + unsigned char ctrl7_is_present:1; + } __packed; + struct { + unsigned char ctrl8_is_present:1; + unsigned char ctrl9_is_present:1; + unsigned char ctrl10_is_present:1; + unsigned char ctrl11_is_present:1; + unsigned char ctrl12_is_present:1; + unsigned char ctrl13_is_present:1; + unsigned char ctrl14_is_present:1; + unsigned char ctrl15_is_present:1; + } __packed; + struct { + unsigned char ctrl16_is_present:1; + unsigned char ctrl17_is_present:1; + unsigned char ctrl18_is_present:1; + unsigned char ctrl19_is_present:1; + unsigned char ctrl20_is_present:1; + unsigned char ctrl21_is_present:1; + unsigned char ctrl22_is_present:1; + unsigned char ctrl23_is_present:1; + } __packed; + }; + unsigned char data[4]; + }; +}; + +struct synaptics_rmi4_f12_query_8 { + union { + struct { + unsigned char size_of_query9; + struct { + unsigned char data0_is_present:1; + unsigned char data1_is_present:1; + unsigned char data2_is_present:1; + unsigned char data3_is_present:1; + unsigned char data4_is_present:1; + unsigned char data5_is_present:1; + unsigned char data6_is_present:1; + unsigned char data7_is_present:1; + } __packed; + }; + unsigned char data[2]; + }; +}; + +struct prox_finger_data { + union { + struct { + unsigned char object_type_and_status; + unsigned char x_lsb; + unsigned char x_msb; + unsigned char y_lsb; + unsigned char y_msb; + unsigned char z; + } __packed; + unsigned char proximity_data[6]; + }; +}; + +struct synaptics_rmi4_prox_handle { + bool hover_finger_present; + bool hover_finger_en; + unsigned char intr_mask; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; + unsigned short hover_finger_en_addr; + unsigned short hover_finger_data_addr; + struct input_dev *prox_dev; + struct prox_finger_data *finger_data; + struct synaptics_rmi4_data *rmi4_data; +}; + +static struct synaptics_rmi4_prox_handle *prox; + +DECLARE_COMPLETION(prox_remove_complete); + +static void prox_hover_finger_lift(void) +{ + input_report_key(prox->prox_dev, BTN_TOUCH, 0); + input_report_key(prox->prox_dev, BTN_TOOL_FINGER, 0); + input_sync(prox->prox_dev); + prox->hover_finger_present = false; + + return; +} + +static void prox_hover_finger_report(void) +{ + int retval; + int x; + int y; + int z; + struct prox_finger_data *data; + struct synaptics_rmi4_data *rmi4_data = prox->rmi4_data; + + data = prox->finger_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + prox->hover_finger_data_addr, + data->proximity_data, + sizeof(data->proximity_data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read hovering finger data\n", + __func__); + return; + } + + if (data->object_type_and_status != F12_HOVERING_FINGER_STATUS) { + if (prox->hover_finger_present) + prox_hover_finger_lift(); + + return; + } + + x = (data->x_msb << 8) | (data->x_lsb); + y = (data->y_msb << 8) | (data->y_lsb); + z = HOVER_Z_MAX - data->z; + + input_report_key(prox->prox_dev, BTN_TOUCH, 0); + input_report_key(prox->prox_dev, BTN_TOOL_FINGER, 1); + input_report_abs(prox->prox_dev, ABS_X, x); + input_report_abs(prox->prox_dev, ABS_Y, y); + input_report_abs(prox->prox_dev, ABS_DISTANCE, z); + + input_sync(prox->prox_dev); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: x = %d y = %d z = %d\n", + __func__, x, y, z); + + prox->hover_finger_present = true; + + return; +} + +static int prox_set_hover_finger_en(void) +{ + int retval; + unsigned char object_report_enable; + struct synaptics_rmi4_data *rmi4_data = prox->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + prox->hover_finger_en_addr, + &object_report_enable, + sizeof(object_report_enable)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read from object report enable register\n", + __func__); + return retval; + } + + if (prox->hover_finger_en) + object_report_enable |= HOVERING_FINGER_EN; + else + object_report_enable &= ~HOVERING_FINGER_EN; + + retval = synaptics_rmi4_reg_write(rmi4_data, + prox->hover_finger_en_addr, + &object_report_enable, + sizeof(object_report_enable)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write to object report enable register\n", + __func__); + return retval; + } + + return 0; +} + +static void prox_set_params(void) +{ + input_set_abs_params(prox->prox_dev, ABS_X, 0, + prox->rmi4_data->sensor_max_x, 0, 0); + input_set_abs_params(prox->prox_dev, ABS_Y, 0, + prox->rmi4_data->sensor_max_y, 0, 0); + input_set_abs_params(prox->prox_dev, ABS_DISTANCE, 0, + HOVER_Z_MAX, 0, 0); + + return; +} + +static int prox_reg_init(void) +{ + int retval; + unsigned char ctrl_23_offset; + unsigned char data_1_offset; + struct synaptics_rmi4_f12_query_5 query_5; + struct synaptics_rmi4_f12_query_8 query_8; + struct synaptics_rmi4_data *rmi4_data = prox->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + prox->query_base_addr + 5, + query_5.data, + sizeof(query_5.data)); + if (retval < 0) + return retval; + + ctrl_23_offset = query_5.ctrl0_is_present + + query_5.ctrl1_is_present + + query_5.ctrl2_is_present + + query_5.ctrl3_is_present + + query_5.ctrl4_is_present + + query_5.ctrl5_is_present + + query_5.ctrl6_is_present + + query_5.ctrl7_is_present + + query_5.ctrl8_is_present + + query_5.ctrl9_is_present + + query_5.ctrl10_is_present + + query_5.ctrl11_is_present + + query_5.ctrl12_is_present + + query_5.ctrl13_is_present + + query_5.ctrl14_is_present + + query_5.ctrl15_is_present + + query_5.ctrl16_is_present + + query_5.ctrl17_is_present + + query_5.ctrl18_is_present + + query_5.ctrl19_is_present + + query_5.ctrl20_is_present + + query_5.ctrl21_is_present + + query_5.ctrl22_is_present; + + prox->hover_finger_en_addr = prox->control_base_addr + ctrl_23_offset; + + retval = synaptics_rmi4_reg_read(rmi4_data, + prox->query_base_addr + 8, + query_8.data, + sizeof(query_8.data)); + if (retval < 0) + return retval; + + data_1_offset = query_8.data0_is_present; + prox->hover_finger_data_addr = prox->data_base_addr + data_1_offset; + + return retval; +} + +static int prox_scan_pdt(void) +{ + int retval; + unsigned char ii; + unsigned char page; + unsigned char intr_count = 0; + unsigned char intr_off; + unsigned char intr_src; + unsigned short addr; + struct synaptics_rmi4_fn_desc fd; + struct synaptics_rmi4_data *rmi4_data = prox->rmi4_data; + + for (page = 0; page < PAGES_TO_SERVICE; page++) { + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + addr |= (page << 8); + + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&fd, + sizeof(fd)); + if (retval < 0) + return retval; + + addr &= ~(MASK_8BIT << 8); + + if (fd.fn_number) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Found F%02x\n", + __func__, fd.fn_number); + switch (fd.fn_number) { + case SYNAPTICS_RMI4_F12: + goto f12_found; + break; + } + } else { + break; + } + + intr_count += fd.intr_src_count; + } + } + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F12\n", + __func__); + return -EINVAL; + +f12_found: + prox->query_base_addr = fd.query_base_addr | (page << 8); + prox->control_base_addr = fd.ctrl_base_addr | (page << 8); + prox->data_base_addr = fd.data_base_addr | (page << 8); + prox->command_base_addr = fd.cmd_base_addr | (page << 8); + + retval = prox_reg_init(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to initialize proximity registers\n", + __func__); + return retval; + } + + prox->intr_mask = 0; + intr_src = fd.intr_src_count; + intr_off = intr_count % 8; + for (ii = intr_off; + ii < (intr_src + intr_off); + ii++) { + prox->intr_mask |= 1 << ii; + } + + rmi4_data->intr_mask[0] |= prox->intr_mask; + + addr = rmi4_data->f01_ctrl_base_addr + 1; + + retval = synaptics_rmi4_reg_write(rmi4_data, + addr, + &(rmi4_data->intr_mask[0]), + sizeof(rmi4_data->intr_mask[0])); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set interrupt enable bit\n", + __func__); + return retval; + } + + return 0; +} + +static ssize_t synaptics_rmi4_hover_finger_en_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + if (!prox) + return -ENODEV; + + return snprintf(buf, PAGE_SIZE, "%u\n", + prox->hover_finger_en); +} + +static ssize_t synaptics_rmi4_hover_finger_en_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = prox->rmi4_data; + + if (!prox) + return -ENODEV; + + if (sscanf(buf, "%x", &input) != 1) + return -EINVAL; + + if (input == 1) + prox->hover_finger_en = true; + else if (input == 0) + prox->hover_finger_en = false; + else + return -EINVAL; + + retval = prox_set_hover_finger_en(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to change hovering finger enable setting\n", + __func__); + return retval; + } + + return count; +} + +int synaptics_rmi4_prox_hover_finger_en(bool enable) +{ + int retval; + + if (!prox) + return -ENODEV; + + prox->hover_finger_en = enable; + + retval = prox_set_hover_finger_en(); + if (retval < 0) + return retval; + + return 0; +} +EXPORT_SYMBOL(synaptics_rmi4_prox_hover_finger_en); + +static void synaptics_rmi4_prox_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!prox) + return; + + if (prox->intr_mask & intr_mask) + prox_hover_finger_report(); + + return; +} + +static int synaptics_rmi4_prox_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char attr_count; + + if (prox) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + prox = kzalloc(sizeof(*prox), GFP_KERNEL); + if (!prox) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for prox\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + prox->finger_data = kzalloc(sizeof(*(prox->finger_data)), GFP_KERNEL); + if (!prox->finger_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for finger_data\n", + __func__); + retval = -ENOMEM; + goto exit_free_prox; + } + + prox->rmi4_data = rmi4_data; + + retval = prox_scan_pdt(); + if (retval < 0) + goto exit_free_finger_data; + + prox->hover_finger_en = true; + + retval = prox_set_hover_finger_en(); + if (retval < 0) + return retval; + + prox->prox_dev = input_allocate_device(); + if (prox->prox_dev == NULL) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate proximity device\n", + __func__); + retval = -ENOMEM; + goto exit_free_finger_data; + } + + prox->prox_dev->name = PROXIMITY_DRIVER_NAME; + prox->prox_dev->phys = PROX_PHYS_NAME; + prox->prox_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT; + prox->prox_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION; + prox->prox_dev->dev.parent = rmi4_data->pdev->dev.parent; + input_set_drvdata(prox->prox_dev, rmi4_data); + + set_bit(EV_KEY, prox->prox_dev->evbit); + set_bit(EV_ABS, prox->prox_dev->evbit); + set_bit(BTN_TOUCH, prox->prox_dev->keybit); + set_bit(BTN_TOOL_FINGER, prox->prox_dev->keybit); +#ifdef INPUT_PROP_DIRECT + set_bit(INPUT_PROP_DIRECT, prox->prox_dev->propbit); +#endif + + prox_set_params(); + + retval = input_register_device(prox->prox_dev); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to register proximity device\n", + __func__); + goto exit_free_input_device; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + goto exit_free_sysfs; + } + } + + return 0; + +exit_free_sysfs: + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + input_unregister_device(prox->prox_dev); + prox->prox_dev = NULL; + +exit_free_input_device: + if (prox->prox_dev) + input_free_device(prox->prox_dev); + +exit_free_finger_data: + kfree(prox->finger_data); + +exit_free_prox: + kfree(prox); + prox = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_prox_remove(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char attr_count; + + if (!prox) + goto exit; + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + input_unregister_device(prox->prox_dev); + kfree(prox->finger_data); + kfree(prox); + prox = NULL; + +exit: + complete(&prox_remove_complete); + + return; +} + +static void synaptics_rmi4_prox_reset(struct synaptics_rmi4_data *rmi4_data) +{ + if (!prox) { + synaptics_rmi4_prox_init(rmi4_data); + return; + } + + prox_hover_finger_lift(); + + prox_scan_pdt(); + + prox_set_hover_finger_en(); + + return; +} + +static void synaptics_rmi4_prox_reinit(struct synaptics_rmi4_data *rmi4_data) +{ + if (!prox) + return; + + prox_hover_finger_lift(); + + prox_set_hover_finger_en(); + + return; +} + +static void synaptics_rmi4_prox_e_suspend(struct synaptics_rmi4_data *rmi4_data) +{ + if (!prox) + return; + + prox_hover_finger_lift(); + + return; +} + +static void synaptics_rmi4_prox_suspend(struct synaptics_rmi4_data *rmi4_data) +{ + if (!prox) + return; + + prox_hover_finger_lift(); + + return; +} + +static struct synaptics_rmi4_exp_fn proximity_module = { + .fn_type = RMI_PROXIMITY, + .init = synaptics_rmi4_prox_init, + .remove = synaptics_rmi4_prox_remove, + .reset = synaptics_rmi4_prox_reset, + .reinit = synaptics_rmi4_prox_reinit, + .early_suspend = synaptics_rmi4_prox_e_suspend, + .suspend = synaptics_rmi4_prox_suspend, + .resume = NULL, + .late_resume = NULL, + .attn = synaptics_rmi4_prox_attn, +}; + +static int __init rmi4_proximity_module_init(void) +{ + synaptics_rmi4_new_function(&proximity_module, true); + + return 0; +} + +static void __exit rmi4_proximity_module_exit(void) +{ + synaptics_rmi4_new_function(&proximity_module, false); + + wait_for_completion(&prox_remove_complete); + + return; +} + +module_init(rmi4_proximity_module_init); +module_exit(rmi4_proximity_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX Proximity Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310/synaptics_dsx_rmi_dev.c b/drivers/input/touchscreen/td4310/synaptics_dsx_rmi_dev.c new file mode 100644 index 0000000000000..b85ba1d94e52b --- /dev/null +++ b/drivers/input/touchscreen/td4310/synaptics_dsx_rmi_dev.c @@ -0,0 +1,1064 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define CHAR_DEVICE_NAME "rmi" +#define DEVICE_CLASS_NAME "rmidev" +#define SYSFS_FOLDER_NAME "rmidev" +#define DEV_NUMBER 1 +#define REG_ADDR_LIMIT 0xFFFF + +#define RMIDEV_MAJOR_NUM 0 + +static ssize_t rmidev_sysfs_data_show(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t rmidev_sysfs_data_store(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t rmidev_sysfs_open_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_release_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_attn_state_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t rmidev_sysfs_pid_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t rmidev_sysfs_pid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_term_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_intr_mask_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t rmidev_sysfs_intr_mask_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_concurrent_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t rmidev_sysfs_concurrent_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +struct rmidev_handle { + dev_t dev_no; + pid_t pid; + unsigned char intr_mask; + unsigned char *tmpbuf; + unsigned int tmpbuf_size; + struct device dev; + struct synaptics_rmi4_data *rmi4_data; + struct kobject *sysfs_dir; + struct siginfo interrupt_signal; + struct siginfo terminate_signal; + struct task_struct *task; + void *data; + bool concurrent; +}; + +struct rmidev_data { + int ref_count; + struct cdev main_dev; + struct class *device_class; + struct mutex file_mutex; + struct rmidev_handle *rmi_dev; +}; + +static struct bin_attribute attr_data = { + .attr = { + .name = "data", + .mode = (S_IRUGO | S_IWUSR | S_IWGRP), + }, + .size = 0, + .read = rmidev_sysfs_data_show, + .write = rmidev_sysfs_data_store, +}; + +static struct device_attribute attrs[] = { + __ATTR(open, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + rmidev_sysfs_open_store), + __ATTR(release, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + rmidev_sysfs_release_store), + __ATTR(attn_state, S_IRUGO, + rmidev_sysfs_attn_state_show, + synaptics_rmi4_store_error), + __ATTR(pid, (S_IRUGO | S_IWUSR | S_IWGRP), + rmidev_sysfs_pid_show, + rmidev_sysfs_pid_store), + __ATTR(term, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + rmidev_sysfs_term_store), + __ATTR(intr_mask, (S_IRUGO | S_IWUSR | S_IWGRP), + rmidev_sysfs_intr_mask_show, + rmidev_sysfs_intr_mask_store), + __ATTR(concurrent, (S_IRUGO | S_IWUSR | S_IWGRP), + rmidev_sysfs_concurrent_show, + rmidev_sysfs_concurrent_store), +}; + +static int rmidev_major_num = RMIDEV_MAJOR_NUM; + +static struct class *rmidev_device_class; + +static struct rmidev_handle *rmidev; + +DECLARE_COMPLETION(rmidev_remove_complete); + +static irqreturn_t rmidev_sysfs_irq(int irq, void *data) +{ + struct synaptics_rmi4_data *rmi4_data = data; + + sysfs_notify(&rmi4_data->input_dev->dev.kobj, + SYSFS_FOLDER_NAME, "attn_state"); + + return IRQ_HANDLED; +} + +static int rmidev_sysfs_irq_enable(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval = 0; + unsigned char intr_status[MAX_INTR_REGISTERS]; + unsigned long irq_flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | + IRQF_ONESHOT; + + mutex_lock(&(rmi4_data->rmi4_irq_enable_mutex)); + + if (enable) { + if (rmi4_data->irq_enabled) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Interrupt already enabled\n", + __func__); + goto exit; + } + + /* Clear interrupts first */ + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr + 1, + intr_status, + rmi4_data->num_of_intr_regs); + if (retval < 0) + goto exit; + + retval = request_threaded_irq(rmi4_data->irq, NULL, + rmidev_sysfs_irq, irq_flags, + PLATFORM_DRIVER_NAME, rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create irq thread\n", + __func__); + goto exit; + } + + rmi4_data->irq_enabled = true; + } else { + if (rmi4_data->irq_enabled) { + disable_irq(rmi4_data->irq); + free_irq(rmi4_data->irq, rmi4_data); + rmi4_data->irq_enabled = false; + } + } + +exit: + mutex_unlock(&(rmi4_data->rmi4_irq_enable_mutex)); + + return retval; +} + +static ssize_t rmidev_sysfs_data_show(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + unsigned char intr_status = 0; + unsigned int length = (unsigned int)count; + unsigned short address = (unsigned short)pos; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + rmi = &(rmi4_data->rmi4_mod_info); + + if (length > (REG_ADDR_LIMIT - address)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Out of register map limit\n", + __func__); + return -EINVAL; + } + + if (length) { + retval = synaptics_rmi4_reg_read(rmi4_data, + address, + (unsigned char *)buf, + length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read data\n", + __func__); + return retval; + } + } else { + return -EINVAL; + } + + if (!rmidev->concurrent) + goto exit; + + if (address != rmi4_data->f01_data_base_addr) + goto exit; + + if (length <= 1) + goto exit; + + intr_status = buf[1]; + + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->num_of_data_sources) { + if (fhandler->intr_mask & intr_status) { + rmi4_data->report_touch(rmi4_data, + fhandler); + } + } + } + } + +exit: + return length; +} + +static ssize_t rmidev_sysfs_data_store(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + unsigned int length = (unsigned int)count; + unsigned short address = (unsigned short)pos; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (length > (REG_ADDR_LIMIT - address)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Out of register map limit\n", + __func__); + return -EINVAL; + } + + if (length) { + retval = synaptics_rmi4_reg_write(rmi4_data, + address, + (unsigned char *)buf, + length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write data\n", + __func__); + return retval; + } + } else { + return -EINVAL; + } + + return length; +} + +static ssize_t rmidev_sysfs_open_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + rmi4_data->irq_enable(rmi4_data, false, false); + rmidev_sysfs_irq_enable(rmi4_data, true); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Attention interrupt disabled\n", + __func__); + + return count; +} + +static ssize_t rmidev_sysfs_release_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + rmidev_sysfs_irq_enable(rmi4_data, false); + + rmi4_data->reset_device(rmi4_data, false); + + rmi4_data->stay_awake = false; + + return count; +} + +static ssize_t rmidev_sysfs_attn_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int attn_state; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + attn_state = gpio_get_value(bdata->irq_gpio); + + return snprintf(buf, PAGE_SIZE, "%u\n", attn_state); +} + +static ssize_t rmidev_sysfs_pid_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", rmidev->pid); +} + +static ssize_t rmidev_sysfs_pid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + rmidev->pid = input; + + if (rmidev->pid) { + rmidev->task = pid_task(find_vpid(rmidev->pid), PIDTYPE_PID); + if (!rmidev->task) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to locate PID of data logging tool\n", + __func__); + return -EINVAL; + } + } + + return count; +} + +static ssize_t rmidev_sysfs_term_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + if (rmidev->pid) + send_sig_info(SIGTERM, &rmidev->terminate_signal, rmidev->task); + + return count; +} + +static ssize_t rmidev_sysfs_intr_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0x%02x\n", rmidev->intr_mask); +} + +static ssize_t rmidev_sysfs_intr_mask_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + rmidev->intr_mask = (unsigned char)input; + + return count; +} + +static ssize_t rmidev_sysfs_concurrent_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", rmidev->concurrent); +} + +static ssize_t rmidev_sysfs_concurrent_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + rmidev->concurrent = input > 0 ? true : false; + + return count; +} + +static int rmidev_allocate_buffer(int count) +{ + if (count + 1 > rmidev->tmpbuf_size) { + if (rmidev->tmpbuf_size) + kfree(rmidev->tmpbuf); + rmidev->tmpbuf = kzalloc(count + 1, GFP_KERNEL); + if (!rmidev->tmpbuf) { + dev_err(rmidev->rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for buffer\n", + __func__); + rmidev->tmpbuf_size = 0; + return -ENOMEM; + } + rmidev->tmpbuf_size = count + 1; + } + + return 0; +} + +/* + * rmidev_llseek - set register address to access for RMI device + * + * @filp: pointer to file structure + * @off: + * if whence == SEEK_SET, + * off: 16-bit RMI register address + * if whence == SEEK_CUR, + * off: offset from current position + * if whence == SEEK_END, + * off: offset from end position (0xFFFF) + * @whence: SEEK_SET, SEEK_CUR, or SEEK_END + */ +static loff_t rmidev_llseek(struct file *filp, loff_t off, int whence) +{ + loff_t newpos; + struct rmidev_data *dev_data = filp->private_data; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (IS_ERR(dev_data)) { + pr_err("%s: Pointer of char device data is invalid", __func__); + return -EBADF; + } + + mutex_lock(&(dev_data->file_mutex)); + + switch (whence) { + case SEEK_SET: + newpos = off; + break; + case SEEK_CUR: + newpos = filp->f_pos + off; + break; + case SEEK_END: + newpos = REG_ADDR_LIMIT + off; + break; + default: + newpos = -EINVAL; + goto clean_up; + } + + if (newpos < 0 || newpos > REG_ADDR_LIMIT) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: New position 0x%04x is invalid\n", + __func__, (unsigned int)newpos); + newpos = -EINVAL; + goto clean_up; + } + + filp->f_pos = newpos; + +clean_up: + mutex_unlock(&(dev_data->file_mutex)); + + return newpos; +} + +/* + * rmidev_read: read register data from RMI device + * + * @filp: pointer to file structure + * @buf: pointer to user space buffer + * @count: number of bytes to read + * @f_pos: starting RMI register address + */ +static ssize_t rmidev_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + ssize_t retval; + unsigned char intr_status = 0; + unsigned short address; + struct rmidev_data *dev_data = filp->private_data; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + rmi = &(rmi4_data->rmi4_mod_info); + + if (IS_ERR(dev_data)) { + pr_err("%s: Pointer of char device data is invalid", __func__); + return -EBADF; + } + + if (count == 0) + return 0; + + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; + + address = (unsigned short)(*f_pos); + + mutex_lock(&(dev_data->file_mutex)); + + rmidev_allocate_buffer(count); + + retval = synaptics_rmi4_reg_read(rmidev->rmi4_data, + *f_pos, + rmidev->tmpbuf, + count); + if (retval < 0) + goto clean_up; + + if (copy_to_user(buf, rmidev->tmpbuf, count)) + retval = -EFAULT; + else + *f_pos += retval; + + if (!rmidev->concurrent) + goto clean_up; + + if (address != rmi4_data->f01_data_base_addr) + goto clean_up; + + if (count <= 1) + goto clean_up; + + intr_status = rmidev->tmpbuf[1]; + + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->num_of_data_sources) { + if (fhandler->intr_mask & intr_status) { + rmi4_data->report_touch(rmi4_data, + fhandler); + } + } + } + } + +clean_up: + mutex_unlock(&(dev_data->file_mutex)); + + return retval; +} + +/* + * rmidev_write: write register data to RMI device + * + * @filp: pointer to file structure + * @buf: pointer to user space buffer + * @count: number of bytes to write + * @f_pos: starting RMI register address + */ +static ssize_t rmidev_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + ssize_t retval; + struct rmidev_data *dev_data = filp->private_data; + + if (IS_ERR(dev_data)) { + pr_err("%s: Pointer of char device data is invalid", __func__); + return -EBADF; + } + + if (count == 0) + return 0; + + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; + + mutex_lock(&(dev_data->file_mutex)); + + rmidev_allocate_buffer(count); + + if (copy_from_user(rmidev->tmpbuf, buf, count)) + return -EFAULT; + + retval = synaptics_rmi4_reg_write(rmidev->rmi4_data, + *f_pos, + rmidev->tmpbuf, + count); + if (retval >= 0) + *f_pos += retval; + + mutex_unlock(&(dev_data->file_mutex)); + + return retval; +} + +static int rmidev_open(struct inode *inp, struct file *filp) +{ + int retval = 0; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + struct rmidev_data *dev_data = + container_of(inp->i_cdev, struct rmidev_data, main_dev); + + if (!dev_data) + return -EACCES; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + filp->private_data = dev_data; + + mutex_lock(&(dev_data->file_mutex)); + + rmi4_data->irq_enable(rmi4_data, false, false); + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Attention interrupt disabled\n", + __func__); + + if (dev_data->ref_count < 1) + dev_data->ref_count++; + else + retval = -EACCES; + + mutex_unlock(&(dev_data->file_mutex)); + + return retval; +} + +static int rmidev_release(struct inode *inp, struct file *filp) +{ + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + struct rmidev_data *dev_data = + container_of(inp->i_cdev, struct rmidev_data, main_dev); + + if (!dev_data) + return -EACCES; + + mutex_lock(&(dev_data->file_mutex)); + + dev_data->ref_count--; + if (dev_data->ref_count < 0) + dev_data->ref_count = 0; + + rmi4_data->reset_device(rmi4_data, false); + + rmi4_data->stay_awake = false; + + mutex_unlock(&(dev_data->file_mutex)); + + return 0; +} + +static const struct file_operations rmidev_fops = { + .owner = THIS_MODULE, + .llseek = rmidev_llseek, + .read = rmidev_read, + .write = rmidev_write, + .open = rmidev_open, + .release = rmidev_release, +}; + +static void rmidev_device_cleanup(struct rmidev_data *dev_data) +{ + dev_t devno; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (dev_data) { + devno = dev_data->main_dev.dev; + + if (dev_data->device_class) + device_destroy(dev_data->device_class, devno); + + cdev_del(&dev_data->main_dev); + + unregister_chrdev_region(devno, 1); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: rmidev device removed\n", + __func__); + } + + return; +} + +static char *rmi_char_devnode(struct device *dev, umode_t *mode) +{ + if (!mode) + return NULL; + + *mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + + return kasprintf(GFP_KERNEL, "rmi/%s", dev_name(dev)); +} + +static int rmidev_create_device_class(void) +{ + if (rmidev_device_class != NULL) + return 0; + + rmidev_device_class = class_create(THIS_MODULE, DEVICE_CLASS_NAME); + + if (IS_ERR(rmidev_device_class)) { + pr_err("%s: Failed to create /dev/%s\n", + __func__, CHAR_DEVICE_NAME); + return -ENODEV; + } + + rmidev_device_class->devnode = rmi_char_devnode; + + return 0; +} + +static void rmidev_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!rmidev) + return; + + if (rmidev->pid && (rmidev->intr_mask & intr_mask)) + send_sig_info(SIGIO, &rmidev->interrupt_signal, rmidev->task); + + return; +} + +static int rmidev_init_device(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + dev_t dev_no; + unsigned char attr_count; + struct rmidev_data *dev_data; + struct device *device_ptr; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (rmidev) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + rmidev = kzalloc(sizeof(*rmidev), GFP_KERNEL); + if (!rmidev) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for rmidev\n", + __func__); + retval = -ENOMEM; + goto err_rmidev; + } + + rmidev->rmi4_data = rmi4_data; + + memset(&rmidev->interrupt_signal, 0, sizeof(rmidev->interrupt_signal)); + rmidev->interrupt_signal.si_signo = SIGIO; + rmidev->interrupt_signal.si_code = SI_USER; + + memset(&rmidev->terminate_signal, 0, sizeof(rmidev->terminate_signal)); + rmidev->terminate_signal.si_signo = SIGTERM; + rmidev->terminate_signal.si_code = SI_USER; + + retval = rmidev_create_device_class(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create device class\n", + __func__); + goto err_device_class; + } + + if (rmidev_major_num) { + dev_no = MKDEV(rmidev_major_num, DEV_NUMBER); + retval = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME); + } else { + retval = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate char device region\n", + __func__); + goto err_device_region; + } + + rmidev_major_num = MAJOR(dev_no); + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Major number of rmidev = %d\n", + __func__, rmidev_major_num); + } + + dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL); + if (!dev_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for dev_data\n", + __func__); + retval = -ENOMEM; + goto err_dev_data; + } + + mutex_init(&dev_data->file_mutex); + dev_data->rmi_dev = rmidev; + rmidev->data = dev_data; + + cdev_init(&dev_data->main_dev, &rmidev_fops); + + retval = cdev_add(&dev_data->main_dev, dev_no, 1); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to add rmi char device\n", + __func__); + goto err_char_device; + } + + dev_set_name(&rmidev->dev, "rmidev%d", MINOR(dev_no)); + dev_data->device_class = rmidev_device_class; + + device_ptr = device_create(dev_data->device_class, NULL, dev_no, + NULL, CHAR_DEVICE_NAME"%d", MINOR(dev_no)); + if (IS_ERR(device_ptr)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create rmi char device\n", + __func__); + retval = -ENODEV; + goto err_char_device; + } + + retval = gpio_export(bdata->irq_gpio, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to export attention gpio\n", + __func__); + } else { + retval = gpio_export_link(&(rmi4_data->input_dev->dev), + "attn", bdata->irq_gpio); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s Failed to create gpio symlink\n", + __func__); + } else { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Exported attention gpio %d\n", + __func__, bdata->irq_gpio); + } + } + + rmidev->sysfs_dir = kobject_create_and_add(SYSFS_FOLDER_NAME, + &rmi4_data->input_dev->dev.kobj); + if (!rmidev->sysfs_dir) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs directory\n", + __func__); + retval = -ENODEV; + goto err_sysfs_dir; + } + + retval = sysfs_create_bin_file(rmidev->sysfs_dir, + &attr_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs bin file\n", + __func__); + goto err_sysfs_bin; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(rmidev->sysfs_dir, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + retval = -ENODEV; + goto err_sysfs_attrs; + } + } + + return 0; + +err_sysfs_attrs: + for (attr_count--; attr_count >= 0; attr_count--) + sysfs_remove_file(rmidev->sysfs_dir, &attrs[attr_count].attr); + + sysfs_remove_bin_file(rmidev->sysfs_dir, &attr_data); + +err_sysfs_bin: + kobject_put(rmidev->sysfs_dir); + +err_sysfs_dir: + sysfs_remove_link(&(rmi4_data->input_dev->dev.kobj), "attn"); + gpio_unexport(bdata->irq_gpio); + +err_char_device: + rmidev_device_cleanup(dev_data); + kfree(dev_data); + +err_dev_data: + unregister_chrdev_region(dev_no, 1); + +err_device_region: + if (rmidev_device_class != NULL) { + class_destroy(rmidev_device_class); + rmidev_device_class = NULL; + } + +err_device_class: + kfree(rmidev); + rmidev = NULL; + +err_rmidev: + return retval; +} + +static void rmidev_remove_device(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char attr_count; + struct rmidev_data *dev_data; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (!rmidev) + goto exit; + + rmidev_major_num = RMIDEV_MAJOR_NUM; + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) + sysfs_remove_file(rmidev->sysfs_dir, &attrs[attr_count].attr); + + sysfs_remove_bin_file(rmidev->sysfs_dir, &attr_data); + + kobject_put(rmidev->sysfs_dir); + + sysfs_remove_link(&(rmi4_data->input_dev->dev.kobj), "attn"); + gpio_unexport(bdata->irq_gpio); + + dev_data = rmidev->data; + if (dev_data) { + rmidev_device_cleanup(dev_data); + kfree(dev_data); + } + + unregister_chrdev_region(rmidev->dev_no, 1); + + if (rmidev_device_class != NULL) { + class_destroy(rmidev_device_class); + rmidev_device_class = NULL; + } + + kfree(rmidev->tmpbuf); + + kfree(rmidev); + rmidev = NULL; + +exit: + complete(&rmidev_remove_complete); + + return; +} + +static struct synaptics_rmi4_exp_fn rmidev_module = { + .fn_type = RMI_DEV, + .init = rmidev_init_device, + .remove = rmidev_remove_device, + .reset = NULL, + .reinit = NULL, + .early_suspend = NULL, + .suspend = NULL, + .resume = NULL, + .late_resume = NULL, + .attn = rmidev_attn, +}; + +static int __init rmidev_module_init(void) +{ + synaptics_rmi4_new_function(&rmidev_module, true); + + return 0; +} + +static void __exit rmidev_module_exit(void) +{ + synaptics_rmi4_new_function(&rmidev_module, false); + + wait_for_completion(&rmidev_remove_complete); + + return; +} + +module_init(rmidev_module_init); +module_exit(rmidev_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX RMI Dev Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310/synaptics_dsx_rmi_hid_i2c.c b/drivers/input/touchscreen/td4310/synaptics_dsx_rmi_hid_i2c.c new file mode 100644 index 0000000000000..244e97e3aa508 --- /dev/null +++ b/drivers/input/touchscreen/td4310/synaptics_dsx_rmi_hid_i2c.c @@ -0,0 +1,1006 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define SYN_I2C_RETRY_TIMES 10 + +#define REPORT_ID_GET_BLOB 0x07 +#define REPORT_ID_WRITE 0x09 +#define REPORT_ID_READ_ADDRESS 0x0a +#define REPORT_ID_READ_DATA 0x0b +#define REPORT_ID_SET_RMI_MODE 0x0f + +#define PREFIX_USAGE_PAGE_1BYTE 0x05 +#define PREFIX_USAGE_PAGE_2BYTES 0x06 +#define PREFIX_USAGE 0x09 +#define PREFIX_REPORT_ID 0x85 +#define PREFIX_REPORT_COUNT_1BYTE 0x95 +#define PREFIX_REPORT_COUNT_2BYTES 0x96 + +#define USAGE_GET_BLOB 0xc5 +#define USAGE_WRITE 0x02 +#define USAGE_READ_ADDRESS 0x03 +#define USAGE_READ_DATA 0x04 +#define USAGE_SET_MODE 0x06 + +#define FEATURE_REPORT_TYPE 0x03 + +#define VENDOR_DEFINED_PAGE 0xff00 + +#define BLOB_REPORT_SIZE 256 + +#define RESET_COMMAND 0x01 +#define GET_REPORT_COMMAND 0x02 +#define SET_REPORT_COMMAND 0x03 +#define SET_POWER_COMMAND 0x08 + +#define FINGER_MODE 0x00 +#define RMI_MODE 0x02 + +struct hid_report_info { + unsigned char get_blob_id; + unsigned char write_id; + unsigned char read_addr_id; + unsigned char read_data_id; + unsigned char set_mode_id; + unsigned int blob_size; +}; + +static struct hid_report_info hid_report; + +struct hid_device_descriptor { + unsigned short device_descriptor_length; + unsigned short format_version; + unsigned short report_descriptor_length; + unsigned short report_descriptor_index; + unsigned short input_register_index; + unsigned short input_report_max_length; + unsigned short output_register_index; + unsigned short output_report_max_length; + unsigned short command_register_index; + unsigned short data_register_index; + unsigned short vendor_id; + unsigned short product_id; + unsigned short version_id; + unsigned int reserved; +}; + +static struct hid_device_descriptor hid_dd; + +struct i2c_rw_buffer { + unsigned char *read; + unsigned char *write; + unsigned int read_size; + unsigned int write_size; +}; + +static struct i2c_rw_buffer buffer; + +#ifdef CONFIG_OF +static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata) +{ + int retval; + u32 value; + const char *name; + struct property *prop; + struct device_node *np = dev->of_node; + + bdata->irq_gpio = of_get_named_gpio_flags(np, + "synaptics,irq-gpio", 0, + (enum of_gpio_flags *)&bdata->irq_flags); + + retval = of_property_read_u32(np, "synaptics,irq-on-state", + &value); + if (retval < 0) + bdata->irq_on_state = 0; + else + bdata->irq_on_state = value; + + retval = of_property_read_string(np, "synaptics,pwr-reg-name", &name); + if (retval < 0) + bdata->pwr_reg_name = NULL; + else + bdata->pwr_reg_name = name; + + retval = of_property_read_string(np, "synaptics,bus-reg-name", &name); + if (retval < 0) + bdata->bus_reg_name = NULL; + else + bdata->bus_reg_name = name; + + prop = of_find_property(np, "synaptics,power-gpio", NULL); + if (prop && prop->length) { + bdata->power_gpio = of_get_named_gpio_flags(np, + "synaptics,power-gpio", 0, NULL); + retval = of_property_read_u32(np, "synaptics,power-on-state", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,power-on-state property\n", + __func__); + return retval; + } else { + bdata->power_on_state = value; + } + } else { + bdata->power_gpio = -1; + } + + prop = of_find_property(np, "synaptics,power-delay-ms", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,power-delay-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,power-delay-ms property\n", + __func__); + return retval; + } else { + bdata->power_delay_ms = value; + } + } else { + bdata->power_delay_ms = 0; + } + + prop = of_find_property(np, "synaptics,reset-gpio", NULL); + if (prop && prop->length) { + bdata->reset_gpio = of_get_named_gpio_flags(np, + "synaptics,reset-gpio", 0, NULL); + retval = of_property_read_u32(np, "synaptics,reset-on-state", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-on-state property\n", + __func__); + return retval; + } else { + bdata->reset_on_state = value; + } + retval = of_property_read_u32(np, "synaptics,reset-active-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-active-ms property\n", + __func__); + return retval; + } else { + bdata->reset_active_ms = value; + } + } else { + bdata->reset_gpio = -1; + } + + prop = of_find_property(np, "synaptics,reset-delay-ms", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,reset-delay-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-delay-ms property\n", + __func__); + return retval; + } else { + bdata->reset_delay_ms = value; + } + } else { + bdata->reset_delay_ms = 0; + } + + prop = of_find_property(np, "synaptics,dev-dscrptr-addr", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,dev-dscrptr-addr", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,dev-dscrptr-addr property\n", + __func__); + return retval; + } else { + bdata->device_descriptor_addr = (unsigned short)value; + } + } else { + bdata->device_descriptor_addr = 0; + } + + prop = of_find_property(np, "synaptics,max-y-for-2d", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,max-y-for-2d", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,max-y-for-2d property\n", + __func__); + return retval; + } else { + bdata->max_y_for_2d = value; + } + } else { + bdata->max_y_for_2d = -1; + } + + prop = of_find_property(np, "synaptics,swap-axes", NULL); + bdata->swap_axes = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,x-flip", NULL); + bdata->x_flip = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,y-flip", NULL); + bdata->y_flip = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,ub-i2c-addr", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,ub-i2c-addr", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,ub-i2c-addr property\n", + __func__); + return retval; + } else { + bdata->ub_i2c_addr = (unsigned short)value; + } + } else { + bdata->ub_i2c_addr = -1; + } + + prop = of_find_property(np, "synaptics,cap-button-codes", NULL); + if (prop && prop->length) { + bdata->cap_button_map->map = devm_kzalloc(dev, + prop->length, + GFP_KERNEL); + if (!bdata->cap_button_map->map) + return -ENOMEM; + bdata->cap_button_map->nbuttons = prop->length / sizeof(u32); + retval = of_property_read_u32_array(np, + "synaptics,cap-button-codes", + bdata->cap_button_map->map, + bdata->cap_button_map->nbuttons); + if (retval < 0) { + bdata->cap_button_map->nbuttons = 0; + bdata->cap_button_map->map = NULL; + } + } else { + bdata->cap_button_map->nbuttons = 0; + bdata->cap_button_map->map = NULL; + } + + prop = of_find_property(np, "synaptics,vir-button-codes", NULL); + if (prop && prop->length) { + bdata->vir_button_map->map = devm_kzalloc(dev, + prop->length, + GFP_KERNEL); + if (!bdata->vir_button_map->map) + return -ENOMEM; + bdata->vir_button_map->nbuttons = prop->length / sizeof(u32); + bdata->vir_button_map->nbuttons /= 5; + retval = of_property_read_u32_array(np, + "synaptics,vir-button-codes", + bdata->vir_button_map->map, + bdata->vir_button_map->nbuttons * 5); + if (retval < 0) { + bdata->vir_button_map->nbuttons = 0; + bdata->vir_button_map->map = NULL; + } + } else { + bdata->vir_button_map->nbuttons = 0; + bdata->vir_button_map->map = NULL; + } + + return 0; +} +#endif + +static int do_i2c_transfer(struct i2c_client *client, struct i2c_msg *msg) +{ + unsigned char retry; + + for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) { + if (i2c_transfer(client->adapter, msg, 1) == 1) + break; + dev_err(&client->dev, + "%s: I2C retry %d\n", + __func__, retry + 1); + msleep(20); + } + + if (retry == SYN_I2C_RETRY_TIMES) { + dev_err(&client->dev, + "%s: I2C transfer over retry limit\n", + __func__); + return -EIO; + } + + return 0; +} + +static int check_buffer(unsigned char **buffer, unsigned int *buffer_size, + unsigned int length) +{ + if (*buffer_size < length) { + if (*buffer_size) + kfree(*buffer); + *buffer = kzalloc(length, GFP_KERNEL); + if (!(*buffer)) + return -ENOMEM; + *buffer_size = length; + } + + return 0; +} + +static int generic_read(struct i2c_client *client, unsigned short length) +{ + int retval; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = length, + } + }; + + check_buffer(&buffer.read, &buffer.read_size, length); + msg[0].buf = buffer.read; + + retval = do_i2c_transfer(client, msg); + + return retval; +} + +static int generic_write(struct i2c_client *client, unsigned short length) +{ + int retval; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = length, + .buf = buffer.write, + } + }; + + retval = do_i2c_transfer(client, msg); + + return retval; +} + +static void traverse_report_descriptor(unsigned int *index) +{ + unsigned char size; + unsigned char *buf = buffer.read; + + size = buf[*index] & MASK_2BIT; + switch (size) { + case 0: /* 0 bytes */ + *index += 1; + break; + case 1: /* 1 byte */ + *index += 2; + break; + case 2: /* 2 bytes */ + *index += 3; + break; + case 3: /* 4 bytes */ + *index += 5; + break; + default: + break; + } + + return; +} + +static void find_blob_size(unsigned int index) +{ + unsigned int ii = index; + unsigned char *buf = buffer.read; + + while (ii < hid_dd.report_descriptor_length) { + if (buf[ii] == PREFIX_REPORT_COUNT_1BYTE) { + hid_report.blob_size = buf[ii + 1]; + return; + } else if (buf[ii] == PREFIX_REPORT_COUNT_2BYTES) { + hid_report.blob_size = buf[ii + 1] | (buf[ii + 2] << 8); + return; + } + traverse_report_descriptor(&ii); + } + + return; +} + +static void find_reports(unsigned int index) +{ + unsigned int ii = index; + unsigned char *buf = buffer.read; + static unsigned int report_id_index; + static unsigned char report_id; + static unsigned short usage_page; + + if (buf[ii] == PREFIX_REPORT_ID) { + report_id = buf[ii + 1]; + report_id_index = ii; + return; + } + + if (buf[ii] == PREFIX_USAGE_PAGE_1BYTE) { + usage_page = buf[ii + 1]; + return; + } else if (buf[ii] == PREFIX_USAGE_PAGE_2BYTES) { + usage_page = buf[ii + 1] | (buf[ii + 2] << 8); + return; + } + + if ((usage_page == VENDOR_DEFINED_PAGE) && (buf[ii] == PREFIX_USAGE)) { + switch (buf[ii + 1]) { + case USAGE_GET_BLOB: + hid_report.get_blob_id = report_id; + find_blob_size(report_id_index); + break; + case USAGE_WRITE: + hid_report.write_id = report_id; + break; + case USAGE_READ_ADDRESS: + hid_report.read_addr_id = report_id; + break; + case USAGE_READ_DATA: + hid_report.read_data_id = report_id; + break; + case USAGE_SET_MODE: + hid_report.set_mode_id = report_id; + break; + default: + break; + } + } + + return; +} + +static int parse_report_descriptor(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned int ii = 0; + unsigned char *buf; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + + buffer.write[0] = hid_dd.report_descriptor_index & MASK_8BIT; + buffer.write[1] = hid_dd.report_descriptor_index >> 8; + retval = generic_write(i2c, 2); + if (retval < 0) + return retval; + retval = generic_read(i2c, hid_dd.report_descriptor_length); + if (retval < 0) + return retval; + + buf = buffer.read; + + hid_report.get_blob_id = REPORT_ID_GET_BLOB; + hid_report.write_id = REPORT_ID_WRITE; + hid_report.read_addr_id = REPORT_ID_READ_ADDRESS; + hid_report.read_data_id = REPORT_ID_READ_DATA; + hid_report.set_mode_id = REPORT_ID_SET_RMI_MODE; + hid_report.blob_size = BLOB_REPORT_SIZE; + + while (ii < hid_dd.report_descriptor_length) { + find_reports(ii); + traverse_report_descriptor(&ii); + } + + return 0; +} + +static int switch_to_rmi(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + check_buffer(&buffer.write, &buffer.write_size, 11); + + /* set rmi mode */ + buffer.write[0] = hid_dd.command_register_index & MASK_8BIT; + buffer.write[1] = hid_dd.command_register_index >> 8; + buffer.write[2] = (FEATURE_REPORT_TYPE << 4) | hid_report.set_mode_id; + buffer.write[3] = SET_REPORT_COMMAND; + buffer.write[4] = hid_report.set_mode_id; + buffer.write[5] = hid_dd.data_register_index & MASK_8BIT; + buffer.write[6] = hid_dd.data_register_index >> 8; + buffer.write[7] = 0x04; + buffer.write[8] = 0x00; + buffer.write[9] = hid_report.set_mode_id; + buffer.write[10] = RMI_MODE; + + retval = generic_write(i2c, 11); + + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static int check_report_mode(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned short report_size; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + check_buffer(&buffer.write, &buffer.write_size, 7); + + buffer.write[0] = hid_dd.command_register_index & MASK_8BIT; + buffer.write[1] = hid_dd.command_register_index >> 8; + buffer.write[2] = (FEATURE_REPORT_TYPE << 4) | hid_report.set_mode_id; + buffer.write[3] = GET_REPORT_COMMAND; + buffer.write[4] = hid_report.set_mode_id; + buffer.write[5] = hid_dd.data_register_index & MASK_8BIT; + buffer.write[6] = hid_dd.data_register_index >> 8; + + retval = generic_write(i2c, 7); + if (retval < 0) + goto exit; + + retval = generic_read(i2c, 2); + if (retval < 0) + goto exit; + + report_size = (buffer.read[1] << 8) | buffer.read[0]; + + retval = generic_write(i2c, 7); + if (retval < 0) + goto exit; + + retval = generic_read(i2c, report_size); + if (retval < 0) + goto exit; + + retval = buffer.read[3]; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Report mode = %d\n", + __func__, retval); + +exit: + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static int hid_i2c_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + check_buffer(&buffer.write, &buffer.write_size, 6); + + /* read device descriptor */ + buffer.write[0] = bdata->device_descriptor_addr & MASK_8BIT; + buffer.write[1] = bdata->device_descriptor_addr >> 8; + retval = generic_write(i2c, 2); + if (retval < 0) + goto exit; + retval = generic_read(i2c, sizeof(hid_dd)); + if (retval < 0) + goto exit; + retval = secure_memcpy((unsigned char *)&hid_dd, + sizeof(struct hid_device_descriptor), + buffer.read, + buffer.read_size, + sizeof(hid_dd)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy device descriptor data\n", + __func__); + goto exit; + } + + retval = parse_report_descriptor(rmi4_data); + if (retval < 0) + goto exit; + + /* set power */ + buffer.write[0] = hid_dd.command_register_index & MASK_8BIT; + buffer.write[1] = hid_dd.command_register_index >> 8; + buffer.write[2] = 0x00; + buffer.write[3] = SET_POWER_COMMAND; + retval = generic_write(i2c, 4); + if (retval < 0) + goto exit; + + /* reset */ + buffer.write[0] = hid_dd.command_register_index & MASK_8BIT; + buffer.write[1] = hid_dd.command_register_index >> 8; + buffer.write[2] = 0x00; + buffer.write[3] = RESET_COMMAND; + retval = generic_write(i2c, 4); + if (retval < 0) + goto exit; + + while (gpio_get_value(bdata->irq_gpio)) + msleep(20); + + retval = generic_read(i2c, hid_dd.input_report_max_length); + if (retval < 0) + goto exit; + + /* get blob */ + buffer.write[0] = hid_dd.command_register_index & MASK_8BIT; + buffer.write[1] = hid_dd.command_register_index >> 8; + buffer.write[2] = (FEATURE_REPORT_TYPE << 4) | hid_report.get_blob_id; + buffer.write[3] = 0x02; + buffer.write[4] = hid_dd.data_register_index & MASK_8BIT; + buffer.write[5] = hid_dd.data_register_index >> 8; + + retval = generic_write(i2c, 6); + if (retval < 0) + goto exit; + + msleep(20); + + retval = generic_read(i2c, hid_report.blob_size + 3); + if (retval < 0) + goto exit; + +exit: + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to initialize HID/I2C interface\n", + __func__); + return retval; + } + + retval = switch_to_rmi(rmi4_data); + + return retval; +} + +static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, unsigned char *data, unsigned int length) +{ + int retval; + unsigned char retry; + unsigned char recover = 1; + unsigned short report_length; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + struct i2c_msg msg[] = { + { + .addr = i2c->addr, + .flags = 0, + .len = hid_dd.output_report_max_length + 2, + }, + { + .addr = i2c->addr, + .flags = I2C_M_RD, + .len = (unsigned short)(length + 4), + }, + }; + +recover: + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + check_buffer(&buffer.write, &buffer.write_size, + hid_dd.output_report_max_length + 2); + msg[0].buf = buffer.write; + buffer.write[0] = hid_dd.output_register_index & MASK_8BIT; + buffer.write[1] = hid_dd.output_register_index >> 8; + buffer.write[2] = hid_dd.output_report_max_length & MASK_8BIT; + buffer.write[3] = hid_dd.output_report_max_length >> 8; + buffer.write[4] = hid_report.read_addr_id; + buffer.write[5] = 0x00; + buffer.write[6] = addr & MASK_8BIT; + buffer.write[7] = addr >> 8; + buffer.write[8] = (unsigned char)length; + buffer.write[9] = (unsigned char)(length >> 8); + + check_buffer(&buffer.read, &buffer.read_size, length + 4); + msg[1].buf = buffer.read; + + retval = do_i2c_transfer(i2c, &msg[0]); + if (retval != 0) + goto exit; + + retry = 0; + do { + retval = do_i2c_transfer(i2c, &msg[1]); + if (retval == 0) + retval = length; + else + goto exit; + + report_length = (buffer.read[1] << 8) | buffer.read[0]; + if (report_length == hid_dd.input_report_max_length) { + retval = secure_memcpy(&data[0], length, + &buffer.read[4], buffer.read_size - 4, + length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy data\n", + __func__); + } else { + retval = length; + } + goto exit; + } + + msleep(20); + retry++; + } while (retry < SYN_I2C_RETRY_TIMES); + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to receive read report\n", + __func__); + retval = -EIO; + +exit: + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + if ((retval != length) && (recover == 1)) { + recover = 0; + if (check_report_mode(rmi4_data) != RMI_MODE) { + retval = hid_i2c_init(rmi4_data); + if (retval == 0) + goto recover; + } + } + + return retval; +} + +static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, unsigned char *data, unsigned int length) +{ + int retval; + unsigned char recover = 1; + unsigned int msg_length; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + struct i2c_msg msg[] = { + { + .addr = i2c->addr, + .flags = 0, + } + }; + + if ((length + 10) < (hid_dd.output_report_max_length + 2)) + msg_length = hid_dd.output_report_max_length + 2; + else + msg_length = length + 10; + +recover: + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + check_buffer(&buffer.write, &buffer.write_size, msg_length); + msg[0].len = (unsigned short)msg_length; + msg[0].buf = buffer.write; + buffer.write[0] = hid_dd.output_register_index & MASK_8BIT; + buffer.write[1] = hid_dd.output_register_index >> 8; + buffer.write[2] = hid_dd.output_report_max_length & MASK_8BIT; + buffer.write[3] = hid_dd.output_report_max_length >> 8; + buffer.write[4] = hid_report.write_id; + buffer.write[5] = 0x00; + buffer.write[6] = addr & MASK_8BIT; + buffer.write[7] = addr >> 8; + buffer.write[8] = (unsigned char)length; + buffer.write[9] = (unsigned char)(length >> 8); + retval = secure_memcpy(&buffer.write[10], buffer.write_size - 10, + &data[0], length, length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy data\n", + __func__); + } else { + retval = do_i2c_transfer(i2c, msg); + if (retval == 0) + retval = length; + } + + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + if ((retval != length) && (recover == 1)) { + recover = 0; + if (check_report_mode(rmi4_data) != RMI_MODE) { + retval = hid_i2c_init(rmi4_data); + if (retval == 0) + goto recover; + } + } + + return retval; +} + +static struct synaptics_dsx_bus_access bus_access = { + .type = BUS_I2C, + .read = synaptics_rmi4_i2c_read, + .write = synaptics_rmi4_i2c_write, +}; + +static struct synaptics_dsx_hw_interface hw_if; + +static struct platform_device *synaptics_dsx_i2c_device; + +static void synaptics_rmi4_i2c_dev_release(struct device *dev) +{ + kfree(synaptics_dsx_i2c_device); + + return; +} + +static int synaptics_rmi4_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int retval; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, + "%s: SMBus byte data commands not supported by host\n", + __func__); + return -EIO; + } + + synaptics_dsx_i2c_device = kzalloc( + sizeof(struct platform_device), + GFP_KERNEL); + if (!synaptics_dsx_i2c_device) { + dev_err(&client->dev, + "%s: Failed to allocate memory for synaptics_dsx_i2c_device\n", + __func__); + return -ENOMEM; + } + +#ifdef CONFIG_OF + if (client->dev.of_node) { + hw_if.board_data = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_board_data), + GFP_KERNEL); + if (!hw_if.board_data) { + dev_err(&client->dev, + "%s: Failed to allocate memory for board data\n", + __func__); + return -ENOMEM; + } + hw_if.board_data->cap_button_map = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_button_map), + GFP_KERNEL); + if (!hw_if.board_data->cap_button_map) { + dev_err(&client->dev, + "%s: Failed to allocate memory for 0D button map\n", + __func__); + return -ENOMEM; + } + hw_if.board_data->vir_button_map = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_button_map), + GFP_KERNEL); + if (!hw_if.board_data->vir_button_map) { + dev_err(&client->dev, + "%s: Failed to allocate memory for virtual button map\n", + __func__); + return -ENOMEM; + } + parse_dt(&client->dev, hw_if.board_data); + } +#else + hw_if.board_data = client->dev.platform_data; +#endif + + hw_if.bus_access = &bus_access; + hw_if.bl_hw_init = switch_to_rmi; + hw_if.ui_hw_init = hid_i2c_init; + + synaptics_dsx_i2c_device->name = PLATFORM_DRIVER_NAME; + synaptics_dsx_i2c_device->id = 0; + synaptics_dsx_i2c_device->num_resources = 0; + synaptics_dsx_i2c_device->dev.parent = &client->dev; + synaptics_dsx_i2c_device->dev.platform_data = &hw_if; + synaptics_dsx_i2c_device->dev.release = synaptics_rmi4_i2c_dev_release; + + retval = platform_device_register(synaptics_dsx_i2c_device); + if (retval) { + dev_err(&client->dev, + "%s: Failed to register platform device\n", + __func__); + return -ENODEV; + } + + return 0; +} + +static int synaptics_rmi4_i2c_remove(struct i2c_client *client) +{ + if (buffer.read_size) + kfree(buffer.read); + + if (buffer.write_size) + kfree(buffer.write); + + platform_device_unregister(synaptics_dsx_i2c_device); + + return 0; +} + +static const struct i2c_device_id synaptics_rmi4_id_table[] = { + {I2C_DRIVER_NAME, 0}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, synaptics_rmi4_id_table); + +#ifdef CONFIG_OF +static struct of_device_id synaptics_rmi4_of_match_table[] = { + { + .compatible = "synaptics,dsx-rmi-hid-i2c", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, synaptics_rmi4_of_match_table); +#else +#define synaptics_rmi4_of_match_table NULL +#endif + +static struct i2c_driver synaptics_rmi4_i2c_driver = { + .driver = { + .name = I2C_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = synaptics_rmi4_of_match_table, + }, + .probe = synaptics_rmi4_i2c_probe, + .remove = synaptics_rmi4_i2c_remove, + .id_table = synaptics_rmi4_id_table, +}; + +int synaptics_rmi4_bus_init(void) +{ + return i2c_add_driver(&synaptics_rmi4_i2c_driver); +} +EXPORT_SYMBOL(synaptics_rmi4_bus_init); + +void synaptics_rmi4_bus_exit(void) +{ + i2c_del_driver(&synaptics_rmi4_i2c_driver); + + return; +} +EXPORT_SYMBOL(synaptics_rmi4_bus_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX I2C Bus Support Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310/synaptics_dsx_spi.c b/drivers/input/touchscreen/td4310/synaptics_dsx_spi.c new file mode 100644 index 0000000000000..e2dafbb5b45c6 --- /dev/null +++ b/drivers/input/touchscreen/td4310/synaptics_dsx_spi.c @@ -0,0 +1,712 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define SPI_READ 0x80 +#define SPI_WRITE 0x00 + +static unsigned char *buf; + +static struct spi_transfer *xfer; + +#ifdef CONFIG_OF +static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata) +{ + int retval; + u32 value; + const char *name; + struct property *prop; + struct device_node *np = dev->of_node; + + bdata->irq_gpio = of_get_named_gpio_flags(np, + "synaptics,irq-gpio", 0, + (enum of_gpio_flags *)&bdata->irq_flags); + + retval = of_property_read_u32(np, "synaptics,irq-on-state", + &value); + if (retval < 0) + bdata->irq_on_state = 0; + else + bdata->irq_on_state = value; + + retval = of_property_read_string(np, "synaptics,pwr-reg-name", &name); + if (retval < 0) + bdata->pwr_reg_name = NULL; + else + bdata->pwr_reg_name = name; + + retval = of_property_read_string(np, "synaptics,bus-reg-name", &name); + if (retval < 0) + bdata->bus_reg_name = NULL; + else + bdata->bus_reg_name = name; + + prop = of_find_property(np, "synaptics,power-gpio", NULL); + if (prop && prop->length) { + bdata->power_gpio = of_get_named_gpio_flags(np, + "synaptics,power-gpio", 0, NULL); + retval = of_property_read_u32(np, "synaptics,power-on-state", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,power-on-state property\n", + __func__); + return retval; + } else { + bdata->power_on_state = value; + } + } else { + bdata->power_gpio = -1; + } + + prop = of_find_property(np, "synaptics,power-delay-ms", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,power-delay-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,power-delay-ms property\n", + __func__); + return retval; + } else { + bdata->power_delay_ms = value; + } + } else { + bdata->power_delay_ms = 0; + } + + prop = of_find_property(np, "synaptics,reset-gpio", NULL); + if (prop && prop->length) { + bdata->reset_gpio = of_get_named_gpio_flags(np, + "synaptics,reset-gpio", 0, NULL); + retval = of_property_read_u32(np, "synaptics,reset-on-state", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-on-state property\n", + __func__); + return retval; + } else { + bdata->reset_on_state = value; + } + retval = of_property_read_u32(np, "synaptics,reset-active-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-active-ms property\n", + __func__); + return retval; + } else { + bdata->reset_active_ms = value; + } + } else { + bdata->reset_gpio = -1; + } + + prop = of_find_property(np, "synaptics,reset-delay-ms", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,reset-delay-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-delay-ms property\n", + __func__); + return retval; + } else { + bdata->reset_delay_ms = value; + } + } else { + bdata->reset_delay_ms = 0; + } + + prop = of_find_property(np, "synaptics,byte-delay-us", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,byte-delay-us", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,byte-delay-us property\n", + __func__); + return retval; + } else { + bdata->byte_delay_us = value; + } + } else { + bdata->byte_delay_us = 0; + } + + prop = of_find_property(np, "synaptics,block-delay-us", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,block-delay-us", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,block-delay-us property\n", + __func__); + return retval; + } else { + bdata->block_delay_us = value; + } + } else { + bdata->block_delay_us = 0; + } + + prop = of_find_property(np, "synaptics,address-delay-us", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,address-delay-us", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,address-delay-us property\n", + __func__); + return retval; + } else { + bdata->addr_delay_us = value; + } + } else { + bdata->addr_delay_us = 0; + } + + prop = of_find_property(np, "synaptics,max-y-for-2d", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,max-y-for-2d", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,max-y-for-2d property\n", + __func__); + return retval; + } else { + bdata->max_y_for_2d = value; + } + } else { + bdata->max_y_for_2d = -1; + } + + prop = of_find_property(np, "synaptics,swap-axes", NULL); + bdata->swap_axes = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,x-flip", NULL); + bdata->x_flip = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,y-flip", NULL); + bdata->y_flip = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,ub-i2c-addr", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,ub-i2c-addr", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,ub-i2c-addr property\n", + __func__); + return retval; + } else { + bdata->ub_i2c_addr = (unsigned short)value; + } + } else { + bdata->ub_i2c_addr = -1; + } + + prop = of_find_property(np, "synaptics,cap-button-codes", NULL); + if (prop && prop->length) { + bdata->cap_button_map->map = devm_kzalloc(dev, + prop->length, + GFP_KERNEL); + if (!bdata->cap_button_map->map) + return -ENOMEM; + bdata->cap_button_map->nbuttons = prop->length / sizeof(u32); + retval = of_property_read_u32_array(np, + "synaptics,cap-button-codes", + bdata->cap_button_map->map, + bdata->cap_button_map->nbuttons); + if (retval < 0) { + bdata->cap_button_map->nbuttons = 0; + bdata->cap_button_map->map = NULL; + } + } else { + bdata->cap_button_map->nbuttons = 0; + bdata->cap_button_map->map = NULL; + } + + prop = of_find_property(np, "synaptics,vir-button-codes", NULL); + if (prop && prop->length) { + bdata->vir_button_map->map = devm_kzalloc(dev, + prop->length, + GFP_KERNEL); + if (!bdata->vir_button_map->map) + return -ENOMEM; + bdata->vir_button_map->nbuttons = prop->length / sizeof(u32); + bdata->vir_button_map->nbuttons /= 5; + retval = of_property_read_u32_array(np, + "synaptics,vir-button-codes", + bdata->vir_button_map->map, + bdata->vir_button_map->nbuttons * 5); + if (retval < 0) { + bdata->vir_button_map->nbuttons = 0; + bdata->vir_button_map->map = NULL; + } + } else { + bdata->vir_button_map->nbuttons = 0; + bdata->vir_button_map->map = NULL; + } + + return 0; +} +#endif + +static int synaptics_rmi4_spi_alloc_buf(struct synaptics_rmi4_data *rmi4_data, + unsigned int size, unsigned int count) +{ + static unsigned int buf_size; + static unsigned int xfer_count; + + if (size > buf_size) { + if (buf_size) + kfree(buf); + buf = kmalloc(size, GFP_KERNEL); + if (!buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for buf\n", + __func__); + buf_size = 0; + return -ENOMEM; + } + buf_size = size; + } + + if (count > xfer_count) { + if (xfer_count) + kfree(xfer); + xfer = kcalloc(count, sizeof(struct spi_transfer), GFP_KERNEL); + if (!xfer) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for xfer\n", + __func__); + xfer_count = 0; + return -ENOMEM; + } + xfer_count = count; + } else { + memset(xfer, 0, count * sizeof(struct spi_transfer)); + } + + return 0; +} + +static int synaptics_rmi4_spi_set_page(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr) +{ + int retval; + unsigned int index; + unsigned int byte_count = PAGE_SELECT_LEN + 1; + unsigned char page; + struct spi_message msg; + struct spi_device *spi = to_spi_device(rmi4_data->pdev->dev.parent); + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + page = ((addr >> 8) & MASK_8BIT); + if ((page >> 7) == (rmi4_data->current_page >> 7)) + return PAGE_SELECT_LEN; + + spi_message_init(&msg); + + retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, byte_count, + byte_count); + if (retval < 0) + return retval; + + buf[0] = SPI_WRITE; + buf[1] = MASK_8BIT; + buf[2] = page; + + if (bdata->byte_delay_us == 0) { + xfer[0].len = byte_count; + xfer[0].tx_buf = &buf[0]; + if (bdata->block_delay_us) + xfer[0].delay_usecs = bdata->block_delay_us; + spi_message_add_tail(&xfer[0], &msg); + } else { + for (index = 0; index < byte_count; index++) { + xfer[index].len = 1; + xfer[index].tx_buf = &buf[index]; + if (index == 1) + xfer[index].delay_usecs = bdata->addr_delay_us; + else + xfer[index].delay_usecs = bdata->byte_delay_us; + spi_message_add_tail(&xfer[index], &msg); + } + if (bdata->block_delay_us) + xfer[index - 1].delay_usecs = bdata->block_delay_us; + } + + retval = spi_sync(spi, &msg); + if (retval == 0) { + rmi4_data->current_page = page; + retval = PAGE_SELECT_LEN; + } else { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to complete SPI transfer, error = %d\n", + __func__, retval); + } + + return retval; +} + +static int synaptics_rmi4_spi_read(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, unsigned char *data, unsigned int length) +{ + int retval; + unsigned int index; + unsigned int byte_count = length + ADDRESS_LEN; + unsigned char txbuf[ADDRESS_LEN]; + struct spi_message msg; + struct spi_device *spi = to_spi_device(rmi4_data->pdev->dev.parent); + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + spi_message_init(&msg); + + txbuf[0] = (addr >> 8) | SPI_READ; + txbuf[1] = addr & MASK_8BIT; + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + retval = synaptics_rmi4_spi_set_page(rmi4_data, addr); + if (retval != PAGE_SELECT_LEN) { + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + return -EIO; + } + + if (bdata->byte_delay_us == 0) { + retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, length, + 2); + } else { + retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, length, + byte_count); + } + if (retval < 0) { + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + return retval; + } + + if (bdata->byte_delay_us == 0) { + xfer[0].len = ADDRESS_LEN; + xfer[0].tx_buf = &txbuf[0]; + spi_message_add_tail(&xfer[0], &msg); + xfer[1].len = length; + xfer[1].rx_buf = &buf[0]; + if (bdata->block_delay_us) + xfer[1].delay_usecs = bdata->block_delay_us; + spi_message_add_tail(&xfer[1], &msg); + } else { + for (index = 0; index < byte_count; index++) { + xfer[index].len = 1; + if (index < ADDRESS_LEN) + xfer[index].tx_buf = &txbuf[index]; + else + xfer[index].rx_buf = &buf[index - ADDRESS_LEN]; + if (index == 1) + xfer[index].delay_usecs = bdata->addr_delay_us; + else + xfer[index].delay_usecs = bdata->byte_delay_us; + spi_message_add_tail(&xfer[index], &msg); + } + if (bdata->block_delay_us) + xfer[index - 1].delay_usecs = bdata->block_delay_us; + } + + retval = spi_sync(spi, &msg); + if (retval == 0) { + retval = secure_memcpy(data, length, buf, length, length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy data\n", + __func__); + } else { + retval = length; + } + } else { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to complete SPI transfer, error = %d\n", + __func__, retval); + } + + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static int synaptics_rmi4_spi_write(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, unsigned char *data, unsigned int length) +{ + int retval; + unsigned int index; + unsigned int byte_count = length + ADDRESS_LEN; + struct spi_message msg; + struct spi_device *spi = to_spi_device(rmi4_data->pdev->dev.parent); + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + spi_message_init(&msg); + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + retval = synaptics_rmi4_spi_set_page(rmi4_data, addr); + if (retval != PAGE_SELECT_LEN) { + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + return -EIO; + } + + if (bdata->byte_delay_us == 0) { + retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, byte_count, + 1); + } else { + retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, byte_count, + byte_count); + } + if (retval < 0) { + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + return retval; + } + + buf[0] = (addr >> 8) & ~SPI_READ; + buf[1] = addr & MASK_8BIT; + retval = secure_memcpy(&buf[ADDRESS_LEN], + byte_count - ADDRESS_LEN, data, length, length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy data\n", + __func__); + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + return retval; + } + + if (bdata->byte_delay_us == 0) { + xfer[0].len = byte_count; + xfer[0].tx_buf = &buf[0]; + if (bdata->block_delay_us) + xfer[0].delay_usecs = bdata->block_delay_us; + spi_message_add_tail(xfer, &msg); + } else { + for (index = 0; index < byte_count; index++) { + xfer[index].len = 1; + xfer[index].tx_buf = &buf[index]; + if (index == 1) + xfer[index].delay_usecs = bdata->addr_delay_us; + else + xfer[index].delay_usecs = bdata->byte_delay_us; + spi_message_add_tail(&xfer[index], &msg); + } + if (bdata->block_delay_us) + xfer[index - 1].delay_usecs = bdata->block_delay_us; + } + + retval = spi_sync(spi, &msg); + if (retval == 0) { + retval = length; + } else { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to complete SPI transfer, error = %d\n", + __func__, retval); + } + + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static struct synaptics_dsx_bus_access bus_access = { + .type = BUS_SPI, + .read = synaptics_rmi4_spi_read, + .write = synaptics_rmi4_spi_write, +}; + +static struct synaptics_dsx_hw_interface hw_if; + +static struct platform_device *synaptics_dsx_spi_device; + +static void synaptics_rmi4_spi_dev_release(struct device *dev) +{ + kfree(synaptics_dsx_spi_device); + + return; +} + +static int synaptics_rmi4_spi_probe(struct spi_device *spi) +{ + int retval; + + if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) { + dev_err(&spi->dev, + "%s: Full duplex not supported by host\n", + __func__); + return -EIO; + } + + synaptics_dsx_spi_device = kzalloc( + sizeof(struct platform_device), + GFP_KERNEL); + if (!synaptics_dsx_spi_device) { + dev_err(&spi->dev, + "%s: Failed to allocate memory for synaptics_dsx_spi_device\n", + __func__); + return -ENOMEM; + } + +#ifdef CONFIG_OF + if (spi->dev.of_node) { + hw_if.board_data = devm_kzalloc(&spi->dev, + sizeof(struct synaptics_dsx_board_data), + GFP_KERNEL); + if (!hw_if.board_data) { + dev_err(&spi->dev, + "%s: Failed to allocate memory for board data\n", + __func__); + return -ENOMEM; + } + hw_if.board_data->cap_button_map = devm_kzalloc(&spi->dev, + sizeof(struct synaptics_dsx_button_map), + GFP_KERNEL); + if (!hw_if.board_data->cap_button_map) { + dev_err(&spi->dev, + "%s: Failed to allocate memory for 0D button map\n", + __func__); + return -ENOMEM; + } + hw_if.board_data->vir_button_map = devm_kzalloc(&spi->dev, + sizeof(struct synaptics_dsx_button_map), + GFP_KERNEL); + if (!hw_if.board_data->vir_button_map) { + dev_err(&spi->dev, + "%s: Failed to allocate memory for virtual button map\n", + __func__); + return -ENOMEM; + } + parse_dt(&spi->dev, hw_if.board_data); + } +#else + hw_if.board_data = spi->dev.platform_data; +#endif + + hw_if.bus_access = &bus_access; + + spi->bits_per_word = 8; + spi->mode = SPI_MODE_3; + + retval = spi_setup(spi); + if (retval < 0) { + dev_err(&spi->dev, + "%s: Failed to perform SPI setup\n", + __func__); + return retval; + } + + synaptics_dsx_spi_device->name = PLATFORM_DRIVER_NAME; + synaptics_dsx_spi_device->id = 0; + synaptics_dsx_spi_device->num_resources = 0; + synaptics_dsx_spi_device->dev.parent = &spi->dev; + synaptics_dsx_spi_device->dev.platform_data = &hw_if; + synaptics_dsx_spi_device->dev.release = synaptics_rmi4_spi_dev_release; + + retval = platform_device_register(synaptics_dsx_spi_device); + if (retval) { + dev_err(&spi->dev, + "%s: Failed to register platform device\n", + __func__); + return -ENODEV; + } + + return 0; +} + +static int synaptics_rmi4_spi_remove(struct spi_device *spi) +{ + platform_device_unregister(synaptics_dsx_spi_device); + + return 0; +} + +static const struct spi_device_id synaptics_rmi4_id_table[] = { + {SPI_DRIVER_NAME, 0}, + {}, +}; +MODULE_DEVICE_TABLE(spi, synaptics_rmi4_id_table); + +#ifdef CONFIG_OF +static struct of_device_id synaptics_rmi4_of_match_table[] = { + { + .compatible = "synaptics,dsx-spi", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, synaptics_rmi4_of_match_table); +#else +#define synaptics_rmi4_of_match_table NULL +#endif + +static struct spi_driver synaptics_rmi4_spi_driver = { + .driver = { + .name = SPI_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = synaptics_rmi4_of_match_table, + }, + .probe = synaptics_rmi4_spi_probe, + .remove = synaptics_rmi4_spi_remove, + .id_table = synaptics_rmi4_id_table, +}; + + +int synaptics_rmi4_bus_init(void) +{ + return spi_register_driver(&synaptics_rmi4_spi_driver); +} +EXPORT_SYMBOL(synaptics_rmi4_bus_init); + +void synaptics_rmi4_bus_exit(void) +{ + kfree(buf); + + kfree(xfer); + + spi_unregister_driver(&synaptics_rmi4_spi_driver); + + return; +} +EXPORT_SYMBOL(synaptics_rmi4_bus_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX SPI Bus Support Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310/synaptics_dsx_test_reporting.c b/drivers/input/touchscreen/td4310/synaptics_dsx_test_reporting.c new file mode 100644 index 0000000000000..9fa1cde55b44c --- /dev/null +++ b/drivers/input/touchscreen/td4310/synaptics_dsx_test_reporting.c @@ -0,0 +1,5409 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define SYSFS_FOLDER_NAME "f54" + +#define GET_REPORT_TIMEOUT_S 1 +#define CALIBRATION_TIMEOUT_S 10 +#define COMMAND_TIMEOUT_100MS 20 + +#define NO_SLEEP_OFF (0 << 2) +#define NO_SLEEP_ON (1 << 2) + +#define STATUS_IDLE 0 +#define STATUS_BUSY 1 +#define STATUS_ERROR 2 + +#define REPORT_INDEX_OFFSET 1 +#define REPORT_DATA_OFFSET 3 + +#define SENSOR_RX_MAPPING_OFFSET 1 +#define SENSOR_TX_MAPPING_OFFSET 2 + +#define COMMAND_GET_REPORT 1 +#define COMMAND_FORCE_CAL 2 +#define COMMAND_FORCE_UPDATE 4 + +#define CONTROL_NO_AUTO_CAL 1 + +#define CONTROL_0_SIZE 1 +#define CONTROL_1_SIZE 1 +#define CONTROL_2_SIZE 2 +#define CONTROL_3_SIZE 1 +#define CONTROL_4_6_SIZE 3 +#define CONTROL_7_SIZE 1 +#define CONTROL_8_9_SIZE 3 +#define CONTROL_10_SIZE 1 +#define CONTROL_11_SIZE 2 +#define CONTROL_12_13_SIZE 2 +#define CONTROL_14_SIZE 1 +#define CONTROL_15_SIZE 1 +#define CONTROL_16_SIZE 1 +#define CONTROL_17_SIZE 1 +#define CONTROL_18_SIZE 1 +#define CONTROL_19_SIZE 1 +#define CONTROL_20_SIZE 1 +#define CONTROL_21_SIZE 2 +#define CONTROL_22_26_SIZE 7 +#define CONTROL_27_SIZE 1 +#define CONTROL_28_SIZE 2 +#define CONTROL_29_SIZE 1 +#define CONTROL_30_SIZE 1 +#define CONTROL_31_SIZE 1 +#define CONTROL_32_35_SIZE 8 +#define CONTROL_36_SIZE 1 +#define CONTROL_37_SIZE 1 +#define CONTROL_38_SIZE 1 +#define CONTROL_39_SIZE 1 +#define CONTROL_40_SIZE 1 +#define CONTROL_41_SIZE 1 +#define CONTROL_42_SIZE 2 +#define CONTROL_43_54_SIZE 13 +#define CONTROL_55_56_SIZE 2 +#define CONTROL_57_SIZE 1 +#define CONTROL_58_SIZE 1 +#define CONTROL_59_SIZE 2 +#define CONTROL_60_62_SIZE 3 +#define CONTROL_63_SIZE 1 +#define CONTROL_64_67_SIZE 4 +#define CONTROL_68_73_SIZE 8 +#define CONTROL_70_73_SIZE 6 +#define CONTROL_74_SIZE 2 +#define CONTROL_75_SIZE 1 +#define CONTROL_76_SIZE 1 +#define CONTROL_77_78_SIZE 2 +#define CONTROL_79_83_SIZE 5 +#define CONTROL_84_85_SIZE 2 +#define CONTROL_86_SIZE 1 +#define CONTROL_87_SIZE 1 +#define CONTROL_88_SIZE 1 +#define CONTROL_89_SIZE 1 +#define CONTROL_90_SIZE 1 +#define CONTROL_91_SIZE 1 +#define CONTROL_92_SIZE 1 +#define CONTROL_93_SIZE 1 +#define CONTROL_94_SIZE 1 +#define CONTROL_95_SIZE 1 +#define CONTROL_96_SIZE 1 +#define CONTROL_97_SIZE 1 +#define CONTROL_98_SIZE 1 +#define CONTROL_99_SIZE 1 +#define CONTROL_100_SIZE 1 +#define CONTROL_101_SIZE 1 +#define CONTROL_102_SIZE 1 +#define CONTROL_103_SIZE 1 +#define CONTROL_104_SIZE 1 +#define CONTROL_105_SIZE 1 +#define CONTROL_106_SIZE 1 +#define CONTROL_107_SIZE 1 +#define CONTROL_108_SIZE 1 +#define CONTROL_109_SIZE 1 +#define CONTROL_110_SIZE 1 +#define CONTROL_111_SIZE 1 +#define CONTROL_112_SIZE 1 +#define CONTROL_113_SIZE 1 +#define CONTROL_114_SIZE 1 +#define CONTROL_115_SIZE 1 +#define CONTROL_116_SIZE 1 +#define CONTROL_117_SIZE 1 +#define CONTROL_118_SIZE 1 +#define CONTROL_119_SIZE 1 +#define CONTROL_120_SIZE 1 +#define CONTROL_121_SIZE 1 +#define CONTROL_122_SIZE 1 +#define CONTROL_123_SIZE 1 +#define CONTROL_124_SIZE 1 +#define CONTROL_125_SIZE 1 +#define CONTROL_126_SIZE 1 +#define CONTROL_127_SIZE 1 +#define CONTROL_128_SIZE 1 +#define CONTROL_129_SIZE 1 +#define CONTROL_130_SIZE 1 +#define CONTROL_131_SIZE 1 +#define CONTROL_132_SIZE 1 +#define CONTROL_133_SIZE 1 +#define CONTROL_134_SIZE 1 +#define CONTROL_135_SIZE 1 +#define CONTROL_136_SIZE 1 +#define CONTROL_137_SIZE 1 +#define CONTROL_138_SIZE 1 +#define CONTROL_139_SIZE 1 +#define CONTROL_140_SIZE 1 +#define CONTROL_141_SIZE 1 +#define CONTROL_142_SIZE 1 +#define CONTROL_143_SIZE 1 +#define CONTROL_144_SIZE 1 +#define CONTROL_145_SIZE 1 +#define CONTROL_146_SIZE 1 +#define CONTROL_147_SIZE 1 +#define CONTROL_148_SIZE 1 +#define CONTROL_149_SIZE 1 +#define CONTROL_150_SIZE 1 +#define CONTROL_151_SIZE 1 +#define CONTROL_152_SIZE 1 +#define CONTROL_153_SIZE 1 +#define CONTROL_154_SIZE 1 +#define CONTROL_155_SIZE 1 +#define CONTROL_156_SIZE 1 +#define CONTROL_157_158_SIZE 2 +#define CONTROL_163_SIZE 1 +#define CONTROL_165_SIZE 1 +#define CONTROL_166_SIZE 1 +#define CONTROL_167_SIZE 1 +#define CONTROL_168_SIZE 1 +#define CONTROL_169_SIZE 1 +#define CONTROL_171_SIZE 1 +#define CONTROL_172_SIZE 1 +#define CONTROL_173_SIZE 1 +#define CONTROL_174_SIZE 1 +#define CONTROL_175_SIZE 1 +#define CONTROL_176_SIZE 1 +#define CONTROL_177_178_SIZE 2 +#define CONTROL_179_SIZE 1 +#define CONTROL_182_SIZE 1 +#define CONTROL_183_SIZE 1 +#define CONTROL_185_SIZE 1 +#define CONTROL_186_SIZE 1 +#define CONTROL_187_SIZE 1 +#define CONTROL_188_SIZE 1 + +#define HIGH_RESISTANCE_DATA_SIZE 6 +#define FULL_RAW_CAP_MIN_MAX_DATA_SIZE 4 +#define TRX_OPEN_SHORT_DATA_SIZE 7 + +#define concat(a, b) a##b + +#define attrify(propname) (&dev_attr_##propname.attr) + +#define show_prototype(propname)\ +static ssize_t concat(test_sysfs, _##propname##_show)(\ + struct device *dev, \ + struct device_attribute *attr,\ + char *buf);\ +\ +static struct device_attribute dev_attr_##propname = \ + __ATTR(propname, S_IRUGO,\ + concat(test_sysfs, _##propname##_show),\ + synaptics_rmi4_store_error); + +#define store_prototype(propname)\ +static ssize_t concat(test_sysfs, _##propname##_store)(\ + struct device *dev, \ + struct device_attribute *attr,\ + const char *buf, size_t count);\ +\ +static struct device_attribute dev_attr_##propname =\ + __ATTR(propname, (S_IWUSR | S_IWGRP),\ + synaptics_rmi4_show_error,\ + concat(test_sysfs, _##propname##_store)); + +#define show_store_prototype(propname)\ +static ssize_t concat(test_sysfs, _##propname##_show)(\ + struct device *dev, \ + struct device_attribute *attr,\ + char *buf);\ +\ +static ssize_t concat(test_sysfs, _##propname##_store)(\ + struct device *dev,\ + struct device_attribute *attr,\ + const char *buf, size_t count);\ +\ +static struct device_attribute dev_attr_##propname =\ + __ATTR(propname, (S_IRUGO | S_IWUSR | S_IWGRP),\ + concat(test_sysfs, _##propname##_show),\ + concat(test_sysfs, _##propname##_store)); + +#define disable_cbc(ctrl_num)\ +do {\ + retval = synaptics_rmi4_reg_read(rmi4_data, \ + f54->control.ctrl_num->address,\ + f54->control.ctrl_num->data,\ + sizeof(f54->control.ctrl_num->data));\ + if (retval < 0) {\ + dev_err(rmi4_data->pdev->dev.parent,\ + "%s: Failed to disable CBC (" #ctrl_num ")\n",\ + __func__);\ + return retval;\ + } \ + f54->control.ctrl_num->cbc_tx_carrier_selection = 0;\ + retval = synaptics_rmi4_reg_write(rmi4_data,\ + f54->control.ctrl_num->address,\ + f54->control.ctrl_num->data,\ + sizeof(f54->control.ctrl_num->data));\ + if (retval < 0) {\ + dev_err(rmi4_data->pdev->dev.parent,\ + "%s: Failed to disable CBC (" #ctrl_num ")\n",\ + __func__);\ + return retval;\ + } \ +} while (0) + +enum f54_report_types { + F54_8BIT_IMAGE = 1, + F54_16BIT_IMAGE = 2, + F54_RAW_16BIT_IMAGE = 3, + F54_HIGH_RESISTANCE = 4, + F54_TX_TO_TX_SHORTS = 5, + F54_RX_TO_RX_SHORTS_1 = 7, + F54_TRUE_BASELINE = 9, + F54_FULL_RAW_CAP_MIN_MAX = 13, + F54_RX_OPENS_1 = 14, + F54_TX_OPENS = 15, + F54_TX_TO_GND_SHORTS = 16, + F54_RX_TO_RX_SHORTS_2 = 17, + F54_RX_OPENS_2 = 18, + F54_FULL_RAW_CAP = 19, + F54_FULL_RAW_CAP_NO_RX_COUPLING = 20, + F54_SENSOR_SPEED = 22, + F54_ADC_RANGE = 23, + F54_TRX_OPENS = 24, + F54_TRX_TO_GND_SHORTS = 25, + F54_TRX_SHORTS = 26, + F54_ABS_RAW_CAP = 38, + F54_ABS_DELTA_CAP = 40, + F54_ABS_HYBRID_DELTA_CAP = 59, + F54_ABS_HYBRID_RAW_CAP = 63, + F54_AMP_FULL_RAW_CAP = 78, + F54_AMP_RAW_ADC = 83, + F54_FULL_RAW_CAP_TDDI = 92, + INVALID_REPORT_TYPE = -1, +}; + +enum f54_afe_cal { + F54_AFE_CAL, + F54_AFE_IS_CAL, +}; + +struct f54_query { + union { + struct { + /* query 0 */ + unsigned char num_of_rx_electrodes; + + /* query 1 */ + unsigned char num_of_tx_electrodes; + + /* query 2 */ + unsigned char f54_query2_b0__1:2; + unsigned char has_baseline:1; + unsigned char has_image8:1; + unsigned char f54_query2_b4__5:2; + unsigned char has_image16:1; + unsigned char f54_query2_b7:1; + + /* queries 3.0 and 3.1 */ + unsigned short clock_rate; + + /* query 4 */ + unsigned char touch_controller_family; + + /* query 5 */ + unsigned char has_pixel_touch_threshold_adjustment:1; + unsigned char f54_query5_b1__7:7; + + /* query 6 */ + unsigned char has_sensor_assignment:1; + unsigned char has_interference_metric:1; + unsigned char has_sense_frequency_control:1; + unsigned char has_firmware_noise_mitigation:1; + unsigned char has_ctrl11:1; + unsigned char has_two_byte_report_rate:1; + unsigned char has_one_byte_report_rate:1; + unsigned char has_relaxation_control:1; + + /* query 7 */ + unsigned char curve_compensation_mode:2; + unsigned char f54_query7_b2__7:6; + + /* query 8 */ + unsigned char f54_query8_b0:1; + unsigned char has_iir_filter:1; + unsigned char has_cmn_removal:1; + unsigned char has_cmn_maximum:1; + unsigned char has_touch_hysteresis:1; + unsigned char has_edge_compensation:1; + unsigned char has_per_frequency_noise_control:1; + unsigned char has_enhanced_stretch:1; + + /* query 9 */ + unsigned char has_force_fast_relaxation:1; + unsigned char has_multi_metric_state_machine:1; + unsigned char has_signal_clarity:1; + unsigned char has_variance_metric:1; + unsigned char has_0d_relaxation_control:1; + unsigned char has_0d_acquisition_control:1; + unsigned char has_status:1; + unsigned char has_slew_metric:1; + + /* query 10 */ + unsigned char has_h_blank:1; + unsigned char has_v_blank:1; + unsigned char has_long_h_blank:1; + unsigned char has_startup_fast_relaxation:1; + unsigned char has_esd_control:1; + unsigned char has_noise_mitigation2:1; + unsigned char has_noise_state:1; + unsigned char has_energy_ratio_relaxation:1; + + /* query 11 */ + unsigned char has_excessive_noise_reporting:1; + unsigned char has_slew_option:1; + unsigned char has_two_overhead_bursts:1; + unsigned char has_query13:1; + unsigned char has_one_overhead_burst:1; + unsigned char f54_query11_b5:1; + unsigned char has_ctrl88:1; + unsigned char has_query15:1; + + /* query 12 */ + unsigned char number_of_sensing_frequencies:4; + unsigned char f54_query12_b4__7:4; + } __packed; + unsigned char data[14]; + }; +}; + +struct f54_query_13 { + union { + struct { + unsigned char has_ctrl86:1; + unsigned char has_ctrl87:1; + unsigned char has_ctrl87_sub0:1; + unsigned char has_ctrl87_sub1:1; + unsigned char has_ctrl87_sub2:1; + unsigned char has_cidim:1; + unsigned char has_noise_mitigation_enhancement:1; + unsigned char has_rail_im:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_15 { + union { + struct { + unsigned char has_ctrl90:1; + unsigned char has_transmit_strength:1; + unsigned char has_ctrl87_sub3:1; + unsigned char has_query16:1; + unsigned char has_query20:1; + unsigned char has_query21:1; + unsigned char has_query22:1; + unsigned char has_query25:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_16 { + union { + struct { + unsigned char has_query17:1; + unsigned char has_data17:1; + unsigned char has_ctrl92:1; + unsigned char has_ctrl93:1; + unsigned char has_ctrl94_query18:1; + unsigned char has_ctrl95_query19:1; + unsigned char has_ctrl99:1; + unsigned char has_ctrl100:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_21 { + union { + struct { + unsigned char has_abs_rx:1; + unsigned char has_abs_tx:1; + unsigned char has_ctrl91:1; + unsigned char has_ctrl96:1; + unsigned char has_ctrl97:1; + unsigned char has_ctrl98:1; + unsigned char has_data19:1; + unsigned char has_query24_data18:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_22 { + union { + struct { + unsigned char has_packed_image:1; + unsigned char has_ctrl101:1; + unsigned char has_dynamic_sense_display_ratio:1; + unsigned char has_query23:1; + unsigned char has_ctrl103_query26:1; + unsigned char has_ctrl104:1; + unsigned char has_ctrl105:1; + unsigned char has_query28:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_23 { + union { + struct { + unsigned char has_ctrl102:1; + unsigned char has_ctrl102_sub1:1; + unsigned char has_ctrl102_sub2:1; + unsigned char has_ctrl102_sub4:1; + unsigned char has_ctrl102_sub5:1; + unsigned char has_ctrl102_sub9:1; + unsigned char has_ctrl102_sub10:1; + unsigned char has_ctrl102_sub11:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_25 { + union { + struct { + unsigned char has_ctrl106:1; + unsigned char has_ctrl102_sub12:1; + unsigned char has_ctrl107:1; + unsigned char has_ctrl108:1; + unsigned char has_ctrl109:1; + unsigned char has_data20:1; + unsigned char f54_query25_b6:1; + unsigned char has_query27:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_27 { + union { + struct { + unsigned char has_ctrl110:1; + unsigned char has_data21:1; + unsigned char has_ctrl111:1; + unsigned char has_ctrl112:1; + unsigned char has_ctrl113:1; + unsigned char has_data22:1; + unsigned char has_ctrl114:1; + unsigned char has_query29:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_29 { + union { + struct { + unsigned char has_ctrl115:1; + unsigned char has_ground_ring_options:1; + unsigned char has_lost_bursts_tuning:1; + unsigned char has_aux_exvcom2_select:1; + unsigned char has_ctrl116:1; + unsigned char has_data23:1; + unsigned char has_ctrl117:1; + unsigned char has_query30:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_30 { + union { + struct { + unsigned char has_ctrl118:1; + unsigned char has_ctrl119:1; + unsigned char has_ctrl120:1; + unsigned char has_ctrl121:1; + unsigned char has_ctrl122_query31:1; + unsigned char has_ctrl123:1; + unsigned char has_ctrl124:1; + unsigned char has_query32:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_32 { + union { + struct { + unsigned char has_ctrl125:1; + unsigned char has_ctrl126:1; + unsigned char has_ctrl127:1; + unsigned char has_abs_charge_pump_disable:1; + unsigned char has_query33:1; + unsigned char has_data24:1; + unsigned char has_query34:1; + unsigned char has_query35:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_33 { + union { + struct { + unsigned char has_ctrl128:1; + unsigned char has_ctrl129:1; + unsigned char has_ctrl130:1; + unsigned char has_ctrl131:1; + unsigned char has_ctrl132:1; + unsigned char has_ctrl133:1; + unsigned char has_ctrl134:1; + unsigned char has_query36:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_35 { + union { + struct { + unsigned char has_data25:1; + unsigned char has_ctrl135:1; + unsigned char has_ctrl136:1; + unsigned char has_ctrl137:1; + unsigned char has_ctrl138:1; + unsigned char has_ctrl139:1; + unsigned char has_data26:1; + unsigned char has_ctrl140:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_36 { + union { + struct { + unsigned char has_ctrl141:1; + unsigned char has_ctrl142:1; + unsigned char has_query37:1; + unsigned char has_ctrl143:1; + unsigned char has_ctrl144:1; + unsigned char has_ctrl145:1; + unsigned char has_ctrl146:1; + unsigned char has_query38:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_38 { + union { + struct { + unsigned char has_ctrl147:1; + unsigned char has_ctrl148:1; + unsigned char has_ctrl149:1; + unsigned char has_ctrl150:1; + unsigned char has_ctrl151:1; + unsigned char has_ctrl152:1; + unsigned char has_ctrl153:1; + unsigned char has_query39:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_39 { + union { + struct { + unsigned char has_ctrl154:1; + unsigned char has_ctrl155:1; + unsigned char has_ctrl156:1; + unsigned char has_ctrl160:1; + unsigned char has_ctrl157_ctrl158:1; + unsigned char f54_query39_b5__6:2; + unsigned char has_query40:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_40 { + union { + struct { + unsigned char has_ctrl169:1; + unsigned char has_ctrl163_query41:1; + unsigned char f54_query40_b2:1; + unsigned char has_ctrl165_query42:1; + unsigned char has_ctrl166:1; + unsigned char has_ctrl167:1; + unsigned char has_ctrl168:1; + unsigned char has_query43:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_43 { + union { + struct { + unsigned char f54_query43_b0__1:2; + unsigned char has_ctrl171:1; + unsigned char has_ctrl172_query44_query45:1; + unsigned char has_ctrl173:1; + unsigned char has_ctrl174:1; + unsigned char has_ctrl175:1; + unsigned char has_query46:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_46 { + union { + struct { + unsigned char has_ctrl176:1; + unsigned char has_ctrl177_ctrl178:1; + unsigned char has_ctrl179:1; + unsigned char f54_query46_b3:1; + unsigned char has_data27:1; + unsigned char has_data28:1; + unsigned char f54_query46_b6:1; + unsigned char has_query47:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_47 { + union { + struct { + unsigned char f54_query47_b0:1; + unsigned char has_ctrl182:1; + unsigned char has_ctrl183:1; + unsigned char f54_query47_b3:1; + unsigned char has_ctrl185:1; + unsigned char has_ctrl186:1; + unsigned char has_ctrl187:1; + unsigned char has_query49:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_49 { + union { + struct { + unsigned char f54_query49_b0__1:2; + unsigned char has_ctrl188:1; + unsigned char has_data31:1; + unsigned char f54_query49_b4__6:3; + unsigned char has_query50:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_50 { + union { + struct { + unsigned char f54_query50_b0__6:7; + unsigned char has_query51:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_51 { + union { + struct { + unsigned char f54_query51_b0__4:5; + unsigned char has_query53_query54_ctrl198:1; + unsigned char has_ctrl199:1; + unsigned char has_query55:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_55 { + union { + struct { + unsigned char has_query56:1; + unsigned char has_data33_data34:1; + unsigned char has_alt_report_rate:1; + unsigned char has_ctrl200:1; + unsigned char has_ctrl201_ctrl202:1; + unsigned char has_ctrl203:1; + unsigned char has_ctrl204:1; + unsigned char has_query57:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_57 { + union { + struct { + unsigned char has_ctrl205:1; + unsigned char has_ctrl206:1; + unsigned char has_usb_bulk_read:1; + unsigned char has_ctrl207:1; + unsigned char has_ctrl208:1; + unsigned char has_ctrl209:1; + unsigned char has_ctrl210:1; + unsigned char has_query58:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_58 { + union { + struct { + unsigned char has_query59:1; + unsigned char has_query60:1; + unsigned char has_ctrl211:1; + unsigned char has_ctrl212:1; + unsigned char has_hybrid_abs_tx_axis_filtering:1; + unsigned char has_hybrid_abs_tx_interpolation:1; + unsigned char has_ctrl213:1; + unsigned char has_query61:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_61 { + union { + struct { + unsigned char has_ctrl214:1; + unsigned char has_ctrl215_query62_query63:1; + unsigned char f54_query_61_b2:1; + unsigned char has_ctrl216:1; + unsigned char has_ctrl217:1; + unsigned char has_misc_host_ctrl:1; + unsigned char hybrid_abs_buttons:1; + unsigned char has_query64:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_64 { + union { + struct { + unsigned char has_ctrl101_sub1:1; + unsigned char has_ctrl220:1; + unsigned char has_ctrl221:1; + unsigned char has_ctrl222:1; + unsigned char has_ctrl219_sub1:1; + unsigned char has_ctrl103_sub3:1; + unsigned char has_ctrl224_ctrl226_ctrl227:1; + unsigned char has_query65:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_65 { + union { + struct { + unsigned char f54_query_65_b0__1:2; + unsigned char has_ctrl101_sub2:1; + unsigned char f54_query_65_b3__4:2; + unsigned char has_query66_ctrl231:1; + unsigned char has_ctrl232:1; + unsigned char has_query67:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_67 { + union { + struct { + unsigned char has_abs_doze_spatial_filter_en:1; + unsigned char has_abs_doze_avg_filter_enhancement_en:1; + unsigned char has_single_display_pulse:1; + unsigned char f54_query_67_b3__4:2; + unsigned char has_ctrl235_ctrl236:1; + unsigned char f54_query_67_b6:1; + unsigned char has_query68:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_68 { + union { + struct { + unsigned char f54_query_68_b0:1; + unsigned char has_ctrl238:1; + unsigned char has_ctrl238_sub1:1; + unsigned char has_ctrl238_sub2:1; + unsigned char has_ctrl239:1; + unsigned char has_freq_filter_bw_ext:1; + unsigned char is_tddi_hic:1; + unsigned char has_query69:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_69 { + union { + struct { + unsigned char has_ctrl240_sub0:1; + unsigned char has_ctrl240_sub1_sub2:1; + unsigned char has_ctrl240_sub3:1; + unsigned char has_ctrl240_sub4:1; + unsigned char f54_query_69_b4__7:4; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_data_31 { + union { + struct { + unsigned char is_calibration_crc:1; + unsigned char calibration_crc:1; + unsigned char short_test_row_number:5; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_7 { + union { + struct { + unsigned char cbc_cap:3; + unsigned char cbc_polarity:1; + unsigned char cbc_tx_carrier_selection:1; + unsigned char f54_ctrl7_b5__7:3; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_41 { + union { + struct { + unsigned char no_signal_clarity:1; + unsigned char f54_ctrl41_b1__7:7; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_57 { + union { + struct { + unsigned char cbc_cap:3; + unsigned char cbc_polarity:1; + unsigned char cbc_tx_carrier_selection:1; + unsigned char f54_ctrl57_b5__7:3; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_86 { + union { + struct { + unsigned char enable_high_noise_state:1; + unsigned char dynamic_sense_display_ratio:2; + unsigned char f54_ctrl86_b3__7:5; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_88 { + union { + struct { + unsigned char tx_low_reference_polarity:1; + unsigned char tx_high_reference_polarity:1; + unsigned char abs_low_reference_polarity:1; + unsigned char abs_polarity:1; + unsigned char cbc_polarity:1; + unsigned char cbc_tx_carrier_selection:1; + unsigned char charge_pump_enable:1; + unsigned char cbc_abs_auto_servo:1; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_110 { + union { + struct { + unsigned char active_stylus_rx_feedback_cap; + unsigned char active_stylus_rx_feedback_cap_reference; + unsigned char active_stylus_low_reference; + unsigned char active_stylus_high_reference; + unsigned char active_stylus_gain_control; + unsigned char active_stylus_gain_control_reference; + unsigned char active_stylus_timing_mode; + unsigned char active_stylus_discovery_bursts; + unsigned char active_stylus_detection_bursts; + unsigned char active_stylus_discovery_noise_multiplier; + unsigned char active_stylus_detection_envelope_min; + unsigned char active_stylus_detection_envelope_max; + unsigned char active_stylus_lose_count; + } __packed; + struct { + unsigned char data[13]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_149 { + union { + struct { + unsigned char trans_cbc_global_cap_enable:1; + unsigned char f54_ctrl149_b1__7:7; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_188 { + union { + struct { + unsigned char start_calibration:1; + unsigned char start_is_calibration:1; + unsigned char frequency:2; + unsigned char start_production_test:1; + unsigned char short_test_calibration:1; + unsigned char f54_ctrl188_b7:1; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control { + struct f54_control_7 *reg_7; + struct f54_control_41 *reg_41; + struct f54_control_57 *reg_57; + struct f54_control_86 *reg_86; + struct f54_control_88 *reg_88; + struct f54_control_110 *reg_110; + struct f54_control_149 *reg_149; + struct f54_control_188 *reg_188; +}; + +struct synaptics_rmi4_f54_handle { + bool no_auto_cal; + bool skip_preparation; + unsigned char status; + unsigned char intr_mask; + unsigned char intr_reg_num; + unsigned char tx_assigned; + unsigned char rx_assigned; + unsigned char *report_data; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; + unsigned short fifoindex; + unsigned int report_size; + unsigned int data_buffer_size; + unsigned int data_pos; + enum f54_report_types report_type; + struct f54_query query; + struct f54_query_13 query_13; + struct f54_query_15 query_15; + struct f54_query_16 query_16; + struct f54_query_21 query_21; + struct f54_query_22 query_22; + struct f54_query_23 query_23; + struct f54_query_25 query_25; + struct f54_query_27 query_27; + struct f54_query_29 query_29; + struct f54_query_30 query_30; + struct f54_query_32 query_32; + struct f54_query_33 query_33; + struct f54_query_35 query_35; + struct f54_query_36 query_36; + struct f54_query_38 query_38; + struct f54_query_39 query_39; + struct f54_query_40 query_40; + struct f54_query_43 query_43; + struct f54_query_46 query_46; + struct f54_query_47 query_47; + struct f54_query_49 query_49; + struct f54_query_50 query_50; + struct f54_query_51 query_51; + struct f54_query_55 query_55; + struct f54_query_57 query_57; + struct f54_query_58 query_58; + struct f54_query_61 query_61; + struct f54_query_64 query_64; + struct f54_query_65 query_65; + struct f54_query_67 query_67; + struct f54_query_68 query_68; + struct f54_query_69 query_69; + struct f54_data_31 data_31; + struct f54_control control; + struct mutex status_mutex; + struct kobject *sysfs_dir; + struct hrtimer watchdog; + struct work_struct timeout_work; + struct work_struct test_report_work; + struct workqueue_struct *test_report_workqueue; + struct synaptics_rmi4_data *rmi4_data; +}; + +struct f55_query { + union { + struct { + /* query 0 */ + unsigned char num_of_rx_electrodes; + + /* query 1 */ + unsigned char num_of_tx_electrodes; + + /* query 2 */ + unsigned char has_sensor_assignment:1; + unsigned char has_edge_compensation:1; + unsigned char curve_compensation_mode:2; + unsigned char has_ctrl6:1; + unsigned char has_alternate_transmitter_assignment:1; + unsigned char has_single_layer_multi_touch:1; + unsigned char has_query5:1; + } __packed; + unsigned char data[3]; + }; +}; + +struct f55_query_3 { + union { + struct { + unsigned char has_ctrl8:1; + unsigned char has_ctrl9:1; + unsigned char has_oncell_pattern_support:1; + unsigned char has_data0:1; + unsigned char has_single_wide_pattern_support:1; + unsigned char has_mirrored_tx_pattern_support:1; + unsigned char has_discrete_pattern_support:1; + unsigned char has_query9:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_5 { + union { + struct { + unsigned char has_corner_compensation:1; + unsigned char has_ctrl12:1; + unsigned char has_trx_configuration:1; + unsigned char has_ctrl13:1; + unsigned char f55_query5_b4:1; + unsigned char has_ctrl14:1; + unsigned char has_basis_function:1; + unsigned char has_query17:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_17 { + union { + struct { + unsigned char f55_query17_b0:1; + unsigned char has_ctrl16:1; + unsigned char has_ctrl18_ctrl19:1; + unsigned char has_ctrl17:1; + unsigned char has_ctrl20:1; + unsigned char has_ctrl21:1; + unsigned char has_ctrl22:1; + unsigned char has_query18:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_18 { + union { + struct { + unsigned char has_ctrl23:1; + unsigned char has_ctrl24:1; + unsigned char has_query19:1; + unsigned char has_ctrl25:1; + unsigned char has_ctrl26:1; + unsigned char has_ctrl27_query20:1; + unsigned char has_ctrl28_query21:1; + unsigned char has_query22:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_22 { + union { + struct { + unsigned char has_ctrl29:1; + unsigned char has_query23:1; + unsigned char has_guard_disable:1; + unsigned char has_ctrl30:1; + unsigned char has_ctrl31:1; + unsigned char has_ctrl32:1; + unsigned char has_query24_through_query27:1; + unsigned char has_query28:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_23 { + union { + struct { + unsigned char amp_sensor_enabled:1; + unsigned char image_transposed:1; + unsigned char first_column_at_left_side:1; + unsigned char size_of_column2mux:5; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_28 { + union { + struct { + unsigned char f55_query28_b0__4:5; + unsigned char has_ctrl37:1; + unsigned char has_query29:1; + unsigned char has_query30:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_30 { + union { + struct { + unsigned char has_ctrl38:1; + unsigned char has_query31_query32:1; + unsigned char has_ctrl39:1; + unsigned char has_ctrl40:1; + unsigned char has_ctrl41:1; + unsigned char has_ctrl42:1; + unsigned char has_ctrl43_ctrl44:1; + unsigned char has_query33:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_33 { + union { + struct { + unsigned char has_extended_amp_pad:1; + unsigned char has_extended_amp_btn:1; + unsigned char has_ctrl45_ctrl46:1; + unsigned char f55_query33_b3:1; + unsigned char has_ctrl47_sub0_sub1:1; + unsigned char f55_query33_b5__7:3; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_control_43 { + union { + struct { + unsigned char swap_sensor_side:1; + unsigned char f55_ctrl43_b1__7:7; + unsigned char afe_l_mux_size:4; + unsigned char afe_r_mux_size:4; + } __packed; + unsigned char data[2]; + }; +}; + +struct synaptics_rmi4_f55_handle { + bool amp_sensor; + bool extended_amp; + bool has_force; + unsigned char size_of_column2mux; + unsigned char afe_mux_offset; + unsigned char force_tx_offset; + unsigned char force_rx_offset; + unsigned char *tx_assignment; + unsigned char *rx_assignment; + unsigned char *force_tx_assignment; + unsigned char *force_rx_assignment; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; + struct f55_query query; + struct f55_query_3 query_3; + struct f55_query_5 query_5; + struct f55_query_17 query_17; + struct f55_query_18 query_18; + struct f55_query_22 query_22; + struct f55_query_23 query_23; + struct f55_query_28 query_28; + struct f55_query_30 query_30; + struct f55_query_33 query_33; +}; + +struct f21_query_2 { + union { + struct { + unsigned char size_of_query3; + struct { + unsigned char query0_is_present:1; + unsigned char query1_is_present:1; + unsigned char query2_is_present:1; + unsigned char query3_is_present:1; + unsigned char query4_is_present:1; + unsigned char query5_is_present:1; + unsigned char query6_is_present:1; + unsigned char query7_is_present:1; + } __packed; + struct { + unsigned char query8_is_present:1; + unsigned char query9_is_present:1; + unsigned char query10_is_present:1; + unsigned char query11_is_present:1; + unsigned char query12_is_present:1; + unsigned char query13_is_present:1; + unsigned char query14_is_present:1; + unsigned char query15_is_present:1; + } __packed; + }; + unsigned char data[3]; + }; +}; + +struct f21_query_5 { + union { + struct { + unsigned char size_of_query6; + struct { + unsigned char ctrl0_is_present:1; + unsigned char ctrl1_is_present:1; + unsigned char ctrl2_is_present:1; + unsigned char ctrl3_is_present:1; + unsigned char ctrl4_is_present:1; + unsigned char ctrl5_is_present:1; + unsigned char ctrl6_is_present:1; + unsigned char ctrl7_is_present:1; + } __packed; + struct { + unsigned char ctrl8_is_present:1; + unsigned char ctrl9_is_present:1; + unsigned char ctrl10_is_present:1; + unsigned char ctrl11_is_present:1; + unsigned char ctrl12_is_present:1; + unsigned char ctrl13_is_present:1; + unsigned char ctrl14_is_present:1; + unsigned char ctrl15_is_present:1; + } __packed; + struct { + unsigned char ctrl16_is_present:1; + unsigned char ctrl17_is_present:1; + unsigned char ctrl18_is_present:1; + unsigned char ctrl19_is_present:1; + unsigned char ctrl20_is_present:1; + unsigned char ctrl21_is_present:1; + unsigned char ctrl22_is_present:1; + unsigned char ctrl23_is_present:1; + } __packed; + }; + unsigned char data[4]; + }; +}; + +struct f21_query_11 { + union { + struct { + unsigned char has_high_resolution_force:1; + unsigned char has_force_sensing_txrx_mapping:1; + unsigned char f21_query11_00_b2__7:6; + unsigned char f21_query11_00_reserved; + unsigned char max_number_of_force_sensors; + unsigned char max_number_of_force_txs; + unsigned char max_number_of_force_rxs; + unsigned char f21_query11_01_reserved; + } __packed; + unsigned char data[6]; + }; +}; + +struct synaptics_rmi4_f21_handle { + bool has_force; + unsigned char tx_assigned; + unsigned char rx_assigned; + unsigned char max_num_of_tx; + unsigned char max_num_of_rx; + unsigned char max_num_of_txrx; + unsigned char *force_txrx_assignment; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; +}; + +show_prototype(num_of_mapped_tx) +show_prototype(num_of_mapped_rx) +show_prototype(tx_mapping) +show_prototype(rx_mapping) +show_prototype(num_of_mapped_force_tx) +show_prototype(num_of_mapped_force_rx) +show_prototype(force_tx_mapping) +show_prototype(force_rx_mapping) +show_prototype(report_size) +show_prototype(status) +show_prototype(ito_test_result) +store_prototype(do_preparation) +store_prototype(force_cal) +store_prototype(get_report) +store_prototype(resume_touch) +store_prototype(do_afe_calibration) +show_store_prototype(report_type) +show_store_prototype(fifoindex) +show_store_prototype(no_auto_cal) +show_store_prototype(read_report) + + +static struct attribute *attrs[] = { + attrify(num_of_mapped_tx), + attrify(num_of_mapped_rx), + attrify(tx_mapping), + attrify(rx_mapping), + attrify(num_of_mapped_force_tx), + attrify(num_of_mapped_force_rx), + attrify(force_tx_mapping), + attrify(force_rx_mapping), + attrify(report_size), + attrify(status), + attrify(ito_test_result), + attrify(do_preparation), + attrify(force_cal), + attrify(get_report), + attrify(resume_touch), + attrify(do_afe_calibration), + attrify(report_type), + attrify(fifoindex), + attrify(no_auto_cal), + attrify(read_report), + NULL, +}; + +static struct attribute_group attr_group = { + .attrs = attrs, +}; + +static ssize_t test_sysfs_data_read(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static struct bin_attribute test_report_data = { + .attr = { + .name = "report_data", + .mode = S_IRUGO, + }, + .size = 0, + .read = test_sysfs_data_read, +}; + +static struct synaptics_rmi4_f54_handle *f54; +static struct synaptics_rmi4_f55_handle *f55; +static struct synaptics_rmi4_f21_handle *f21; + +DECLARE_COMPLETION(test_remove_complete); + +static bool test_report_type_valid(enum f54_report_types report_type) +{ + switch (report_type) { + case F54_8BIT_IMAGE: + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_HIGH_RESISTANCE: + case F54_TX_TO_TX_SHORTS: + case F54_RX_TO_RX_SHORTS_1: + case F54_TRUE_BASELINE: + case F54_FULL_RAW_CAP_MIN_MAX: + case F54_RX_OPENS_1: + case F54_TX_OPENS: + case F54_TX_TO_GND_SHORTS: + case F54_RX_TO_RX_SHORTS_2: + case F54_RX_OPENS_2: + case F54_FULL_RAW_CAP: + case F54_FULL_RAW_CAP_NO_RX_COUPLING: + case F54_SENSOR_SPEED: + case F54_ADC_RANGE: + case F54_TRX_OPENS: + case F54_TRX_TO_GND_SHORTS: + case F54_TRX_SHORTS: + case F54_ABS_RAW_CAP: + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + case F54_ABS_HYBRID_RAW_CAP: + case F54_AMP_FULL_RAW_CAP: + case F54_AMP_RAW_ADC: + case F54_FULL_RAW_CAP_TDDI: + return true; + break; + default: + f54->report_type = INVALID_REPORT_TYPE; + f54->report_size = 0; + return false; + } +} + +static void test_set_report_size(void) +{ + int retval; + unsigned char tx = f54->tx_assigned; + unsigned char rx = f54->rx_assigned; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + switch (f54->report_type) { + case F54_8BIT_IMAGE: + f54->report_size = tx * rx; + break; + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_TRUE_BASELINE: + case F54_FULL_RAW_CAP: + case F54_FULL_RAW_CAP_NO_RX_COUPLING: + case F54_SENSOR_SPEED: + case F54_AMP_FULL_RAW_CAP: + case F54_AMP_RAW_ADC: + case F54_FULL_RAW_CAP_TDDI: + f54->report_size = 2 * tx * rx; + break; + case F54_HIGH_RESISTANCE: + f54->report_size = HIGH_RESISTANCE_DATA_SIZE; + break; + case F54_TX_TO_TX_SHORTS: + case F54_TX_OPENS: + case F54_TX_TO_GND_SHORTS: + f54->report_size = (tx + 7) / 8; + break; + case F54_RX_TO_RX_SHORTS_1: + case F54_RX_OPENS_1: + if (rx < tx) + f54->report_size = 2 * rx * rx; + else + f54->report_size = 2 * tx * rx; + break; + case F54_FULL_RAW_CAP_MIN_MAX: + f54->report_size = FULL_RAW_CAP_MIN_MAX_DATA_SIZE; + break; + case F54_RX_TO_RX_SHORTS_2: + case F54_RX_OPENS_2: + if (rx <= tx) + f54->report_size = 0; + else + f54->report_size = 2 * rx * (rx - tx); + break; + case F54_ADC_RANGE: + if (f54->query.has_signal_clarity) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_41->address, + f54->control.reg_41->data, + sizeof(f54->control.reg_41->data)); + if (retval < 0) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Failed to read control reg_41\n", + __func__); + f54->report_size = 0; + break; + } + if (!f54->control.reg_41->no_signal_clarity) { + if (tx % 4) + tx += 4 - (tx % 4); + } + } + f54->report_size = 2 * tx * rx; + break; + case F54_TRX_OPENS: + case F54_TRX_TO_GND_SHORTS: + case F54_TRX_SHORTS: + f54->report_size = TRX_OPEN_SHORT_DATA_SIZE; + break; + case F54_ABS_RAW_CAP: + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + case F54_ABS_HYBRID_RAW_CAP: + tx += f21->tx_assigned; + rx += f21->rx_assigned; + f54->report_size = 4 * (tx + rx); + break; + default: + f54->report_size = 0; + } + + return; +} + +static int test_set_interrupt(bool set) +{ + int retval; + unsigned char ii; + unsigned char zero = 0x00; + unsigned char *intr_mask; + unsigned short f01_ctrl_reg; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + intr_mask = rmi4_data->intr_mask; + f01_ctrl_reg = rmi4_data->f01_ctrl_base_addr + 1 + f54->intr_reg_num; + + if (!set) { + retval = synaptics_rmi4_reg_write(rmi4_data, + f01_ctrl_reg, + &zero, + sizeof(zero)); + if (retval < 0) + return retval; + } + + for (ii = 0; ii < rmi4_data->num_of_intr_regs; ii++) { + if (intr_mask[ii] != 0x00) { + f01_ctrl_reg = rmi4_data->f01_ctrl_base_addr + 1 + ii; + if (set) { + retval = synaptics_rmi4_reg_write(rmi4_data, + f01_ctrl_reg, + &zero, + sizeof(zero)); + if (retval < 0) + return retval; + } else { + retval = synaptics_rmi4_reg_write(rmi4_data, + f01_ctrl_reg, + &(intr_mask[ii]), + sizeof(intr_mask[ii])); + if (retval < 0) + return retval; + } + } + } + + f01_ctrl_reg = rmi4_data->f01_ctrl_base_addr + 1 + f54->intr_reg_num; + + if (set) { + retval = synaptics_rmi4_reg_write(rmi4_data, + f01_ctrl_reg, + &f54->intr_mask, + 1); + if (retval < 0) + return retval; + } + + return 0; +} + +static int test_wait_for_command_completion(void) +{ + int retval; + unsigned char value; + unsigned char timeout_count; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + timeout_count = 0; + do { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->command_base_addr, + &value, + sizeof(value)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read command register\n", + __func__); + return retval; + } + + if (value == 0x00) + break; + + msleep(100); + timeout_count++; + } while (timeout_count < COMMAND_TIMEOUT_100MS); + + if (timeout_count == COMMAND_TIMEOUT_100MS) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for command completion\n", + __func__); + return -ETIMEDOUT; + } + + return 0; +} + +static int test_do_command(unsigned char command) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->command_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command\n", + __func__); + return retval; + } + + retval = test_wait_for_command_completion(); + if (retval < 0) + return retval; + + return 0; +} + +static int test_do_preparation(void) +{ + int retval; + unsigned char value; + unsigned char zero = 0x00; + unsigned char device_ctrl; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set no sleep\n", + __func__); + return retval; + } + + device_ctrl |= NO_SLEEP_ON; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set no sleep\n", + __func__); + return retval; + } + + if (f54->skip_preparation) + return 0; + + switch (f54->report_type) { + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_SENSOR_SPEED: + case F54_ADC_RANGE: + case F54_ABS_RAW_CAP: + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + case F54_ABS_HYBRID_RAW_CAP: + case F54_FULL_RAW_CAP_TDDI: + break; + case F54_AMP_RAW_ADC: + if (f54->query_49.has_ctrl188) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set start production test\n", + __func__); + return retval; + } + f54->control.reg_188->start_production_test = 1; + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set start production test\n", + __func__); + return retval; + } + } + break; + default: + if (f54->query.touch_controller_family == 1) + disable_cbc(reg_7); + else if (f54->query.has_ctrl88) + disable_cbc(reg_88); + + if (f54->query.has_0d_acquisition_control) + disable_cbc(reg_57); + + if ((f54->query.has_query15) && + (f54->query_15.has_query25) && + (f54->query_25.has_query27) && + (f54->query_27.has_query29) && + (f54->query_29.has_query30) && + (f54->query_30.has_query32) && + (f54->query_32.has_query33) && + (f54->query_33.has_query36) && + (f54->query_36.has_query38) && + (f54->query_38.has_ctrl149)) { + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_149->address, + &zero, + sizeof(f54->control.reg_149->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to disable global CBC\n", + __func__); + return retval; + } + } + + if (f54->query.has_signal_clarity) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_41->address, + &value, + sizeof(f54->control.reg_41->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to disable signal clarity\n", + __func__); + return retval; + } + value |= 0x01; + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_41->address, + &value, + sizeof(f54->control.reg_41->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to disable signal clarity\n", + __func__); + return retval; + } + } + + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update\n", + __func__); + return retval; + } + + retval = test_do_command(COMMAND_FORCE_CAL); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force cal\n", + __func__); + return retval; + } + } + + return 0; +} + +static int test_do_afe_calibration(enum f54_afe_cal mode) +{ + int retval; + unsigned char timeout = CALIBRATION_TIMEOUT_S; + unsigned char timeout_count = 0; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to start calibration\n", + __func__); + return retval; + } + + if (mode == F54_AFE_CAL) + f54->control.reg_188->start_calibration = 1; + else if (mode == F54_AFE_IS_CAL) + f54->control.reg_188->start_is_calibration = 1; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to start calibration\n", + __func__); + return retval; + } + + do { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to complete calibration\n", + __func__); + return retval; + } + + if (mode == F54_AFE_CAL) { + if (!f54->control.reg_188->start_calibration) + break; + } else if (mode == F54_AFE_IS_CAL) { + if (!f54->control.reg_188->start_is_calibration) + break; + } + + if (timeout_count == timeout) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for calibration completion\n", + __func__); + return -EBUSY; + } + + timeout_count++; + msleep(1000); + } while (true); + + /* check CRC */ + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->data_31.address, + f54->data_31.data, + sizeof(f54->data_31.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read calibration CRC\n", + __func__); + return retval; + } + + if (mode == F54_AFE_CAL) { + if (f54->data_31.calibration_crc == 0) + return 0; + } else if (mode == F54_AFE_IS_CAL) { + if (f54->data_31.is_calibration_crc == 0) + return 0; + } + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read calibration CRC\n", + __func__); + + return -EINVAL; +} + +static int test_check_for_idle_status(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + switch (f54->status) { + case STATUS_IDLE: + retval = 0; + break; + case STATUS_BUSY: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Status busy\n", + __func__); + retval = -EINVAL; + break; + case STATUS_ERROR: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Status error\n", + __func__); + retval = -EINVAL; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid status (%d)\n", + __func__, f54->status); + retval = -EINVAL; + } + + return retval; +} + +static void test_timeout_work(struct work_struct *work) +{ + int retval; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + mutex_lock(&f54->status_mutex); + + if (f54->status == STATUS_BUSY) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->command_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read command register\n", + __func__); + } else if (command & COMMAND_GET_REPORT) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Report type not supported by FW\n", + __func__); + } else { + queue_work(f54->test_report_workqueue, + &f54->test_report_work); + goto exit; + } + f54->status = STATUS_ERROR; + f54->report_size = 0; + } + +exit: + mutex_unlock(&f54->status_mutex); + + return; +} + +static enum hrtimer_restart test_get_report_timeout(struct hrtimer *timer) +{ + schedule_work(&(f54->timeout_work)); + + return HRTIMER_NORESTART; +} + +static ssize_t test_sysfs_num_of_mapped_tx_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->tx_assigned); +} + +static ssize_t test_sysfs_num_of_mapped_rx_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->rx_assigned); +} + +static ssize_t test_sysfs_tx_mapping_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int cnt; + int count = 0; + unsigned char ii; + unsigned char tx_num; + unsigned char tx_electrodes; + + if (!f55) + return -EINVAL; + + tx_electrodes = f55->query.num_of_tx_electrodes; + + for (ii = 0; ii < tx_electrodes; ii++) { + tx_num = f55->tx_assignment[ii]; + if (tx_num == 0xff) + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + else + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", tx_num); + buf += cnt; + count += cnt; + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; + + return count; +} + +static ssize_t test_sysfs_rx_mapping_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int cnt; + int count = 0; + unsigned char ii; + unsigned char rx_num; + unsigned char rx_electrodes; + + if (!f55) + return -EINVAL; + + rx_electrodes = f55->query.num_of_rx_electrodes; + + for (ii = 0; ii < rx_electrodes; ii++) { + rx_num = f55->rx_assignment[ii]; + if (rx_num == 0xff) + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + else + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", rx_num); + buf += cnt; + count += cnt; + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; + + return count; +} + +static ssize_t test_sysfs_num_of_mapped_force_tx_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f21->tx_assigned); +} + +static ssize_t test_sysfs_num_of_mapped_force_rx_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f21->rx_assigned); +} + +static ssize_t test_sysfs_force_tx_mapping_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int cnt; + int count = 0; + unsigned char ii; + unsigned char tx_num; + unsigned char tx_electrodes; + + if ((!f55 || !f55->has_force) && (!f21 || !f21->has_force)) + return -EINVAL; + + if (f55->has_force) { + tx_electrodes = f55->query.num_of_tx_electrodes; + + for (ii = 0; ii < tx_electrodes; ii++) { + tx_num = f55->force_tx_assignment[ii]; + if (tx_num == 0xff) { + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + } else { + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", + tx_num); + } + buf += cnt; + count += cnt; + } + } else if (f21->has_force) { + tx_electrodes = f21->max_num_of_tx; + + for (ii = 0; ii < tx_electrodes; ii++) { + tx_num = f21->force_txrx_assignment[ii]; + if (tx_num == 0xff) { + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + } else { + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", + tx_num); + } + buf += cnt; + count += cnt; + } + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; + + return count; +} + +static ssize_t test_sysfs_force_rx_mapping_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int cnt; + int count = 0; + unsigned char ii; + unsigned char offset; + unsigned char rx_num; + unsigned char rx_electrodes; + + if ((!f55 || !f55->has_force) && (!f21 || !f21->has_force)) + return -EINVAL; + + if (f55->has_force) { + rx_electrodes = f55->query.num_of_rx_electrodes; + + for (ii = 0; ii < rx_electrodes; ii++) { + rx_num = f55->force_rx_assignment[ii]; + if (rx_num == 0xff) + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + else + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", + rx_num); + buf += cnt; + count += cnt; + } + } else if (f21->has_force) { + offset = f21->max_num_of_tx; + rx_electrodes = f21->max_num_of_rx; + + for (ii = offset; ii < (rx_electrodes + offset); ii++) { + rx_num = f21->force_txrx_assignment[ii]; + if (rx_num == 0xff) + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + else + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", + rx_num); + buf += cnt; + count += cnt; + } + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; + + return count; +} + +static ssize_t test_sysfs_report_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->report_size); +} + +static ssize_t test_sysfs_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + mutex_lock(&f54->status_mutex); + + retval = snprintf(buf, PAGE_SIZE, "%u\n", f54->status); + + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static ssize_t test_sysfs_do_preparation_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting != 1) + return -EINVAL; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + retval = test_do_preparation(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do preparation\n", + __func__); + goto exit; + } + + retval = count; + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static ssize_t test_sysfs_force_cal_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting != 1) + return -EINVAL; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + retval = test_do_command(COMMAND_FORCE_CAL); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force cal\n", + __func__); + goto exit; + } + + retval = count; + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static ssize_t test_sysfs_get_report_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char command; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting != 1) + return -EINVAL; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + if (!test_report_type_valid(f54->report_type)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid report type\n", + __func__); + retval = -EINVAL; + goto exit; + } + + test_set_interrupt(true); + + command = (unsigned char)COMMAND_GET_REPORT; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->command_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write get report command\n", + __func__); + goto exit; + } + + f54->status = STATUS_BUSY; + f54->report_size = 0; + f54->data_pos = 0; + + hrtimer_start(&f54->watchdog, + ktime_set(GET_REPORT_TIMEOUT_S, 0), + HRTIMER_MODE_REL); + + retval = count; + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static ssize_t test_sysfs_resume_touch_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char device_ctrl; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting != 1) + return -EINVAL; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore no sleep setting\n", + __func__); + return retval; + } + + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + device_ctrl |= rmi4_data->no_sleep_setting; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore no sleep setting\n", + __func__); + return retval; + } + + test_set_interrupt(false); + + if (f54->skip_preparation) + return count; + + switch (f54->report_type) { + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_SENSOR_SPEED: + case F54_ADC_RANGE: + case F54_ABS_RAW_CAP: + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + case F54_ABS_HYBRID_RAW_CAP: + case F54_FULL_RAW_CAP_TDDI: + break; + case F54_AMP_RAW_ADC: + if (f54->query_49.has_ctrl188) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set start production test\n", + __func__); + return retval; + } + f54->control.reg_188->start_production_test = 0; + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set start production test\n", + __func__); + return retval; + } + } + break; + default: + rmi4_data->reset_device(rmi4_data, false); + } + + return count; +} + +static ssize_t test_sysfs_do_afe_calibration_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (!f54->query_49.has_ctrl188) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: F54_ANALOG_Ctrl188 not found\n", + __func__); + return -EINVAL; + } + + if (setting == 0 || setting == 1) + retval = test_do_afe_calibration((enum f54_afe_cal)setting); + else + return -EINVAL; + + if (retval) + return retval; + else + return count; +} + +static ssize_t test_sysfs_report_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->report_type); +} + +static ssize_t test_sysfs_report_type_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char data; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + if (!test_report_type_valid((enum f54_report_types)setting)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Report type not supported by driver\n", + __func__); + retval = -EINVAL; + goto exit; + } + + f54->report_type = (enum f54_report_types)setting; + data = (unsigned char)setting; + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->data_base_addr, + &data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write report type\n", + __func__); + goto exit; + } + + retval = count; + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static ssize_t test_sysfs_fifoindex_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned char data[2]; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->data_base_addr + REPORT_INDEX_OFFSET, + data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report index\n", + __func__); + return retval; + } + + batohs(&f54->fifoindex, data); + + return snprintf(buf, PAGE_SIZE, "%u\n", f54->fifoindex); +} + +static ssize_t test_sysfs_fifoindex_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char data[2]; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + f54->fifoindex = setting; + + hstoba(data, (unsigned short)setting); + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->data_base_addr + REPORT_INDEX_OFFSET, + data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write report index\n", + __func__); + return retval; + } + + return count; +} + +static ssize_t test_sysfs_no_auto_cal_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->no_auto_cal); +} + +static ssize_t test_sysfs_no_auto_cal_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char data; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting > 1) + return -EINVAL; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control_base_addr, + &data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read no auto cal setting\n", + __func__); + return retval; + } + + if (setting) + data |= CONTROL_NO_AUTO_CAL; + else + data &= ~CONTROL_NO_AUTO_CAL; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control_base_addr, + &data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write no auto cal setting\n", + __func__); + return retval; + } + + f54->no_auto_cal = (setting == 1); + + return count; +} + +static int check_ito_test_flag = 2; +#ifdef SYNAPTICS_ESD_CHECK +extern void synaptics_rmi4_esd_work(struct work_struct *work); +#define SYNAPTICS_ESD_CHECK_CIRCLE 2*HZ +extern struct synaptics_rmi4_data *rmi4_data; + +#endif +static ssize_t test_sysfs_read_report_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned int ii; + unsigned int jj; + int cnt; + int count = 0; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + char *report_data_8; + short *report_data_16; + int *report_data_32; + unsigned short *report_data_u16; + unsigned int *report_data_u32; + +#ifdef SYNAPTICS_ESD_CHECK + printk("%s SYNAPTICS_ESD_CHECK is off\n", __func__); + cancel_delayed_work_sync(&(rmi4_data->esd_work)); +#endif + + switch (f54->report_type) { + case F54_8BIT_IMAGE: + printk("F54_8BIT_IMAGE\n"); + report_data_8 = (char *)f54->report_data; + for (ii = 0; ii < f54->report_size; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%03d: %d\n", + ii, *report_data_8); + report_data_8++; + buf += cnt; + count += cnt; + } + break; + case F54_AMP_RAW_ADC: + report_data_u16 = (unsigned short *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "tx = %d\nrx = %d\n", + tx_num, rx_num); + buf += cnt; + count += cnt; + + for (ii = 0; ii < tx_num; ii++) { + for (jj = 0; jj < (rx_num - 1); jj++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d ", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d\n", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + break; + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_TRUE_BASELINE: + case F54_FULL_RAW_CAP: + case F54_FULL_RAW_CAP_NO_RX_COUPLING: + case F54_SENSOR_SPEED: + case F54_AMP_FULL_RAW_CAP: + case F54_FULL_RAW_CAP_TDDI: + printk("start F54_FULL_RAW_CAP_TDDI\n"); + report_data_16 = (short *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "tx = %d\nrx = %d\n", + tx_num, rx_num); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + for (jj = 0; jj < (rx_num - 1); jj++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d ", + *report_data_16); + if (*report_data_16 <= 1700 || *report_data_16 >= 2300) { + if ((jj == 24) && (ii != 1) && (ii != 6) && (ii != 12)) { + check_ito_test_flag = 1; + } else{ + check_ito_test_flag = 0; + } + } else{ + check_ito_test_flag = 0; + } + report_data_16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d\n", + *report_data_16); + report_data_16++; + buf += cnt; + count += cnt; + } + if (1 == check_ito_test_flag) { + cnt = snprintf(buf, PAGE_SIZE - count, "fail\n"); + buf += cnt; + count += cnt; + printk("[synaptics]ITO test fail\n"); + } else { + cnt = snprintf(buf, PAGE_SIZE - count, "pass\n"); + buf += cnt; + count += cnt; + printk("[synaptics]ITO test pass\n"); + } + break; + case F54_HIGH_RESISTANCE: + case F54_FULL_RAW_CAP_MIN_MAX: + report_data_16 = (short *)f54->report_data; + for (ii = 0; ii < f54->report_size; ii += 2) { + cnt = snprintf(buf, PAGE_SIZE - count, "%03d: %d\n", + ii / 2, *report_data_16); + report_data_16++; + buf += cnt; + count += cnt; + } + break; + case F54_ABS_RAW_CAP: + case F54_ABS_HYBRID_RAW_CAP: + tx_num += f21->tx_assigned; + rx_num += f21->rx_assigned; + report_data_u32 = (unsigned int *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "rx "); + buf += cnt; + count += cnt; + for (ii = 0; ii < rx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %2d", ii); + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, " "); + buf += cnt; + count += cnt; + for (ii = 0; ii < rx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %5u", + *report_data_u32); + report_data_u32++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, "tx "); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %2d", ii); + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, " "); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %5u", + *report_data_u32); + report_data_u32++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + break; + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + tx_num += f21->tx_assigned; + rx_num += f21->rx_assigned; + report_data_32 = (int *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "rx "); + buf += cnt; + count += cnt; + for (ii = 0; ii < rx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %2d", ii); + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, " "); + buf += cnt; + count += cnt; + for (ii = 0; ii < rx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %5d", + *report_data_32); + report_data_32++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, "tx "); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %2d", ii); + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, " "); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %5d", + *report_data_32); + report_data_32++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + break; + default: + for (ii = 0; ii < f54->report_size; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%03d: 0x%02x\n", + ii, f54->report_data[ii]); + buf += cnt; + count += cnt; + } + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; +#ifdef SYNAPTICS_ESD_CHECK + printk("%s SYNAPTICS_ESD_CHECK is on\n", __func__); + queue_delayed_work(rmi4_data->esd_workqueue, &(rmi4_data->esd_work), SYNAPTICS_ESD_CHECK_CIRCLE); +#endif + + return count; +} + +static ssize_t test_sysfs_read_report_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char timeout = GET_REPORT_TIMEOUT_S * 10; + unsigned char timeout_count; + const char cmd[] = {'1', 0}; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = test_sysfs_report_type_store(dev, attr, buf, count); + if (retval < 0) + goto exit; + + retval = test_sysfs_do_preparation_store(dev, attr, cmd, 1); + if (retval < 0) + goto exit; + + retval = test_sysfs_get_report_store(dev, attr, cmd, 1); + if (retval < 0) + goto exit; + + timeout_count = 0; + do { + if (f54->status != STATUS_BUSY) + break; + msleep(100); + timeout_count++; + } while (timeout_count < timeout); + + if ((f54->status != STATUS_IDLE) || (f54->report_size == 0)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report\n", + __func__); + retval = -EINVAL; + goto exit; + } + + retval = test_sysfs_resume_touch_store(dev, attr, cmd, 1); + if (retval < 0) + goto exit; + + return count; + +exit: + rmi4_data->reset_device(rmi4_data, false); + + return retval; +} + +static ssize_t test_sysfs_ito_test_result_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + + if (1 == check_ito_test_flag) { + return snprintf(buf, PAGE_SIZE, "%s\n", "fail"); + } else if (0 == check_ito_test_flag) { + return snprintf(buf, PAGE_SIZE, "%s\n", "pass"); + } else { + return snprintf(buf, PAGE_SIZE, "%s\n", ""); + } +} + +static ssize_t test_sysfs_data_read(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + unsigned int read_size; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + if (!f54->report_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Report type %d data not available\n", + __func__, f54->report_type); + retval = -EINVAL; + goto exit; + } + + if ((f54->data_pos + count) > f54->report_size) + read_size = f54->report_size - f54->data_pos; + else + read_size = min_t(unsigned int, count, f54->report_size); + + retval = secure_memcpy(buf, count, f54->report_data + f54->data_pos, + f54->data_buffer_size - f54->data_pos, read_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy report data\n", + __func__); + goto exit; + } + f54->data_pos += read_size; + retval = read_size; + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static void test_report_work(struct work_struct *work) +{ + int retval; + unsigned char report_index[2]; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + mutex_lock(&f54->status_mutex); + + if (f54->status != STATUS_BUSY) { + retval = f54->status; + goto exit; + } + + retval = test_wait_for_command_completion(); + if (retval < 0) { + retval = STATUS_ERROR; + goto exit; + } + + test_set_report_size(); + if (f54->report_size == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Report data size = 0\n", + __func__); + retval = STATUS_ERROR; + goto exit; + } + + if (f54->data_buffer_size < f54->report_size) { + if (f54->data_buffer_size) + kfree(f54->report_data); + f54->report_data = kzalloc(f54->report_size, GFP_KERNEL); + if (!f54->report_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for data buffer\n", + __func__); + f54->data_buffer_size = 0; + retval = STATUS_ERROR; + goto exit; + } + f54->data_buffer_size = f54->report_size; + } + + report_index[0] = 0; + report_index[1] = 0; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->data_base_addr + REPORT_INDEX_OFFSET, + report_index, + sizeof(report_index)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write report data index\n", + __func__); + retval = STATUS_ERROR; + goto exit; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->data_base_addr + REPORT_DATA_OFFSET, + f54->report_data, + f54->report_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report data\n", + __func__); + retval = STATUS_ERROR; + goto exit; + } + + retval = STATUS_IDLE; + +exit: + mutex_unlock(&f54->status_mutex); + + if (retval == STATUS_ERROR) + f54->report_size = 0; + + f54->status = retval; + + return; +} + +static void test_remove_sysfs(void) +{ + sysfs_remove_group(f54->sysfs_dir, &attr_group); + sysfs_remove_bin_file(f54->sysfs_dir, &test_report_data); + kobject_put(f54->sysfs_dir); + + return; +} + +static int test_set_sysfs(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + f54->sysfs_dir = kobject_create_and_add(SYSFS_FOLDER_NAME, + &rmi4_data->input_dev->dev.kobj); + if (!f54->sysfs_dir) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs directory\n", + __func__); + goto exit_directory; + } + + retval = sysfs_create_bin_file(f54->sysfs_dir, &test_report_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs bin file\n", + __func__); + goto exit_bin_file; + } +printk("before creat attr_group "); + retval = sysfs_create_group(f54->sysfs_dir, &attr_group); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + goto exit_attributes; + } + + return 0; + +exit_attributes: + sysfs_remove_group(f54->sysfs_dir, &attr_group); + sysfs_remove_bin_file(f54->sysfs_dir, &test_report_data); + +exit_bin_file: + kobject_put(f54->sysfs_dir); + +exit_directory: + return -ENODEV; +} + +static void test_free_control_mem(void) +{ + struct f54_control control = f54->control; + + kfree(control.reg_7); + kfree(control.reg_41); + kfree(control.reg_57); + kfree(control.reg_86); + kfree(control.reg_88); + kfree(control.reg_110); + kfree(control.reg_149); + kfree(control.reg_188); + + return; +} + +static void test_set_data(void) +{ + unsigned short reg_addr; + + reg_addr = f54->data_base_addr + REPORT_DATA_OFFSET + 1; + + /* data 4 */ + if (f54->query.has_sense_frequency_control) + reg_addr++; + + /* data 5 reserved */ + + /* data 6 */ + if (f54->query.has_interference_metric) + reg_addr += 2; + + /* data 7 */ + if (f54->query.has_one_byte_report_rate | + f54->query.has_two_byte_report_rate) + reg_addr++; + if (f54->query.has_two_byte_report_rate) + reg_addr++; + + /* data 8 */ + if (f54->query.has_variance_metric) + reg_addr += 2; + + /* data 9 */ + if (f54->query.has_multi_metric_state_machine) + reg_addr += 2; + + /* data 10 */ + if (f54->query.has_multi_metric_state_machine | + f54->query.has_noise_state) + reg_addr++; + + /* data 11 */ + if (f54->query.has_status) + reg_addr++; + + /* data 12 */ + if (f54->query.has_slew_metric) + reg_addr += 2; + + /* data 13 */ + if (f54->query.has_multi_metric_state_machine) + reg_addr += 2; + + /* data 14 */ + if (f54->query_13.has_cidim) + reg_addr++; + + /* data 15 */ + if (f54->query_13.has_rail_im) + reg_addr++; + + /* data 16 */ + if (f54->query_13.has_noise_mitigation_enhancement) + reg_addr++; + + /* data 17 */ + if (f54->query_16.has_data17) + reg_addr++; + + /* data 18 */ + if (f54->query_21.has_query24_data18) + reg_addr++; + + /* data 19 */ + if (f54->query_21.has_data19) + reg_addr++; + + /* data_20 */ + if (f54->query_25.has_ctrl109) + reg_addr++; + + /* data 21 */ + if (f54->query_27.has_data21) + reg_addr++; + + /* data 22 */ + if (f54->query_27.has_data22) + reg_addr++; + + /* data 23 */ + if (f54->query_29.has_data23) + reg_addr++; + + /* data 24 */ + if (f54->query_32.has_data24) + reg_addr++; + + /* data 25 */ + if (f54->query_35.has_data25) + reg_addr++; + + /* data 26 */ + if (f54->query_35.has_data26) + reg_addr++; + + /* data 27 */ + if (f54->query_46.has_data27) + reg_addr++; + + /* data 28 */ + if (f54->query_46.has_data28) + reg_addr++; + + /* data 29 30 reserved */ + + /* data 31 */ + if (f54->query_49.has_data31) { + f54->data_31.address = reg_addr; + reg_addr++; + } + + return; +} + +static int test_set_controls(void) +{ + int retval; + unsigned char length; + unsigned char num_of_sensing_freqs; + unsigned short reg_addr = f54->control_base_addr; + struct f54_control *control = &f54->control; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + num_of_sensing_freqs = f54->query.number_of_sensing_frequencies; + + /* control 0 */ + reg_addr += CONTROL_0_SIZE; + + /* control 1 */ + if ((f54->query.touch_controller_family == 0) || + (f54->query.touch_controller_family == 1)) + reg_addr += CONTROL_1_SIZE; + + /* control 2 */ + reg_addr += CONTROL_2_SIZE; + + /* control 3 */ + if (f54->query.has_pixel_touch_threshold_adjustment) + reg_addr += CONTROL_3_SIZE; + + /* controls 4 5 6 */ + if ((f54->query.touch_controller_family == 0) || + (f54->query.touch_controller_family == 1)) + reg_addr += CONTROL_4_6_SIZE; + + /* control 7 */ + if (f54->query.touch_controller_family == 1) { + control->reg_7 = kzalloc(sizeof(*(control->reg_7)), + GFP_KERNEL); + if (!control->reg_7) + goto exit_no_mem; + control->reg_7->address = reg_addr; + reg_addr += CONTROL_7_SIZE; + } + + /* controls 8 9 */ + if ((f54->query.touch_controller_family == 0) || + (f54->query.touch_controller_family == 1)) + reg_addr += CONTROL_8_9_SIZE; + + /* control 10 */ + if (f54->query.has_interference_metric) + reg_addr += CONTROL_10_SIZE; + + /* control 11 */ + if (f54->query.has_ctrl11) + reg_addr += CONTROL_11_SIZE; + + /* controls 12 13 */ + if (f54->query.has_relaxation_control) + reg_addr += CONTROL_12_13_SIZE; + + /* controls 14 15 16 */ + if (f54->query.has_sensor_assignment) { + reg_addr += CONTROL_14_SIZE; + reg_addr += CONTROL_15_SIZE * f54->query.num_of_rx_electrodes; + reg_addr += CONTROL_16_SIZE * f54->query.num_of_tx_electrodes; + } + + /* controls 17 18 19 */ + if (f54->query.has_sense_frequency_control) { + reg_addr += CONTROL_17_SIZE * num_of_sensing_freqs; + reg_addr += CONTROL_18_SIZE * num_of_sensing_freqs; + reg_addr += CONTROL_19_SIZE * num_of_sensing_freqs; + } + + /* control 20 */ + reg_addr += CONTROL_20_SIZE; + + /* control 21 */ + if (f54->query.has_sense_frequency_control) + reg_addr += CONTROL_21_SIZE; + + /* controls 22 23 24 25 26 */ + if (f54->query.has_firmware_noise_mitigation) + reg_addr += CONTROL_22_26_SIZE; + + /* control 27 */ + if (f54->query.has_iir_filter) + reg_addr += CONTROL_27_SIZE; + + /* control 28 */ + if (f54->query.has_firmware_noise_mitigation) + reg_addr += CONTROL_28_SIZE; + + /* control 29 */ + if (f54->query.has_cmn_removal) + reg_addr += CONTROL_29_SIZE; + + /* control 30 */ + if (f54->query.has_cmn_maximum) + reg_addr += CONTROL_30_SIZE; + + /* control 31 */ + if (f54->query.has_touch_hysteresis) + reg_addr += CONTROL_31_SIZE; + + /* controls 32 33 34 35 */ + if (f54->query.has_edge_compensation) + reg_addr += CONTROL_32_35_SIZE; + + /* control 36 */ + if ((f54->query.curve_compensation_mode == 1) || + (f54->query.curve_compensation_mode == 2)) { + if (f54->query.curve_compensation_mode == 1) { + length = max(f54->query.num_of_rx_electrodes, + f54->query.num_of_tx_electrodes); + } else if (f54->query.curve_compensation_mode == 2) { + length = f54->query.num_of_rx_electrodes; + } + reg_addr += CONTROL_36_SIZE * length; + } + + /* control 37 */ + if (f54->query.curve_compensation_mode == 2) + reg_addr += CONTROL_37_SIZE * f54->query.num_of_tx_electrodes; + + /* controls 38 39 40 */ + if (f54->query.has_per_frequency_noise_control) { + reg_addr += CONTROL_38_SIZE * num_of_sensing_freqs; + reg_addr += CONTROL_39_SIZE * num_of_sensing_freqs; + reg_addr += CONTROL_40_SIZE * num_of_sensing_freqs; + } + + /* control 41 */ + if (f54->query.has_signal_clarity) { + control->reg_41 = kzalloc(sizeof(*(control->reg_41)), + GFP_KERNEL); + if (!control->reg_41) + goto exit_no_mem; + control->reg_41->address = reg_addr; + reg_addr += CONTROL_41_SIZE; + } + + /* control 42 */ + if (f54->query.has_variance_metric) + reg_addr += CONTROL_42_SIZE; + + /* controls 43 44 45 46 47 48 49 50 51 52 53 54 */ + if (f54->query.has_multi_metric_state_machine) + reg_addr += CONTROL_43_54_SIZE; + + /* controls 55 56 */ + if (f54->query.has_0d_relaxation_control) + reg_addr += CONTROL_55_56_SIZE; + + /* control 57 */ + if (f54->query.has_0d_acquisition_control) { + control->reg_57 = kzalloc(sizeof(*(control->reg_57)), + GFP_KERNEL); + if (!control->reg_57) + goto exit_no_mem; + control->reg_57->address = reg_addr; + reg_addr += CONTROL_57_SIZE; + } + + /* control 58 */ + if (f54->query.has_0d_acquisition_control) + reg_addr += CONTROL_58_SIZE; + + /* control 59 */ + if (f54->query.has_h_blank) + reg_addr += CONTROL_59_SIZE; + + /* controls 60 61 62 */ + if ((f54->query.has_h_blank) || + (f54->query.has_v_blank) || + (f54->query.has_long_h_blank)) + reg_addr += CONTROL_60_62_SIZE; + + /* control 63 */ + if ((f54->query.has_h_blank) || + (f54->query.has_v_blank) || + (f54->query.has_long_h_blank) || + (f54->query.has_slew_metric) || + (f54->query.has_slew_option) || + (f54->query.has_noise_mitigation2)) + reg_addr += CONTROL_63_SIZE; + + /* controls 64 65 66 67 */ + if (f54->query.has_h_blank) + reg_addr += CONTROL_64_67_SIZE * 7; + else if ((f54->query.has_v_blank) || + (f54->query.has_long_h_blank)) + reg_addr += CONTROL_64_67_SIZE; + + /* controls 68 69 70 71 72 73 */ + if ((f54->query.has_h_blank) || + (f54->query.has_v_blank) || + (f54->query.has_long_h_blank)) { + if (f54->query_68.is_tddi_hic) + reg_addr += CONTROL_70_73_SIZE; + else + reg_addr += CONTROL_68_73_SIZE; + } + + /* control 74 */ + if (f54->query.has_slew_metric) + reg_addr += CONTROL_74_SIZE; + + /* control 75 */ + if (f54->query.has_enhanced_stretch) + reg_addr += CONTROL_75_SIZE * num_of_sensing_freqs; + + /* control 76 */ + if (f54->query.has_startup_fast_relaxation) + reg_addr += CONTROL_76_SIZE; + + /* controls 77 78 */ + if (f54->query.has_esd_control) + reg_addr += CONTROL_77_78_SIZE; + + /* controls 79 80 81 82 83 */ + if (f54->query.has_noise_mitigation2) + reg_addr += CONTROL_79_83_SIZE; + + /* controls 84 85 */ + if (f54->query.has_energy_ratio_relaxation) + reg_addr += CONTROL_84_85_SIZE; + + /* control 86 */ + if (f54->query_13.has_ctrl86) { + control->reg_86 = kzalloc(sizeof(*(control->reg_86)), + GFP_KERNEL); + if (!control->reg_86) + goto exit_no_mem; + control->reg_86->address = reg_addr; + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_86->address, + f54->control.reg_86->data, + sizeof(f54->control.reg_86->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read sense display ratio\n", + __func__); + return retval; + } + reg_addr += CONTROL_86_SIZE; + } + + /* control 87 */ + if (f54->query_13.has_ctrl87) + reg_addr += CONTROL_87_SIZE; + + /* control 88 */ + if (f54->query.has_ctrl88) { + control->reg_88 = kzalloc(sizeof(*(control->reg_88)), + GFP_KERNEL); + if (!control->reg_88) + goto exit_no_mem; + control->reg_88->address = reg_addr; + reg_addr += CONTROL_88_SIZE; + } + + /* control 89 */ + if (f54->query_13.has_cidim || + f54->query_13.has_noise_mitigation_enhancement || + f54->query_13.has_rail_im) + reg_addr += CONTROL_89_SIZE; + + /* control 90 */ + if (f54->query_15.has_ctrl90) + reg_addr += CONTROL_90_SIZE; + + /* control 91 */ + if (f54->query_21.has_ctrl91) + reg_addr += CONTROL_91_SIZE; + + /* control 92 */ + if (f54->query_16.has_ctrl92) + reg_addr += CONTROL_92_SIZE; + + /* control 93 */ + if (f54->query_16.has_ctrl93) + reg_addr += CONTROL_93_SIZE; + + /* control 94 */ + if (f54->query_16.has_ctrl94_query18) + reg_addr += CONTROL_94_SIZE; + + /* control 95 */ + if (f54->query_16.has_ctrl95_query19) + reg_addr += CONTROL_95_SIZE; + + /* control 96 */ + if (f54->query_21.has_ctrl96) + reg_addr += CONTROL_96_SIZE; + + /* control 97 */ + if (f54->query_21.has_ctrl97) + reg_addr += CONTROL_97_SIZE; + + /* control 98 */ + if (f54->query_21.has_ctrl98) + reg_addr += CONTROL_98_SIZE; + + /* control 99 */ + if (f54->query.touch_controller_family == 2) + reg_addr += CONTROL_99_SIZE; + + /* control 100 */ + if (f54->query_16.has_ctrl100) + reg_addr += CONTROL_100_SIZE; + + /* control 101 */ + if (f54->query_22.has_ctrl101) + reg_addr += CONTROL_101_SIZE; + + /* control 102 */ + if (f54->query_23.has_ctrl102) + reg_addr += CONTROL_102_SIZE; + + /* control 103 */ + if (f54->query_22.has_ctrl103_query26) { + f54->skip_preparation = true; + reg_addr += CONTROL_103_SIZE; + } + + /* control 104 */ + if (f54->query_22.has_ctrl104) + reg_addr += CONTROL_104_SIZE; + + /* control 105 */ + if (f54->query_22.has_ctrl105) + reg_addr += CONTROL_105_SIZE; + + /* control 106 */ + if (f54->query_25.has_ctrl106) + reg_addr += CONTROL_106_SIZE; + + /* control 107 */ + if (f54->query_25.has_ctrl107) + reg_addr += CONTROL_107_SIZE; + + /* control 108 */ + if (f54->query_25.has_ctrl108) + reg_addr += CONTROL_108_SIZE; + + /* control 109 */ + if (f54->query_25.has_ctrl109) + reg_addr += CONTROL_109_SIZE; + + /* control 110 */ + if (f54->query_27.has_ctrl110) { + control->reg_110 = kzalloc(sizeof(*(control->reg_110)), + GFP_KERNEL); + if (!control->reg_110) + goto exit_no_mem; + control->reg_110->address = reg_addr; + reg_addr += CONTROL_110_SIZE; + } + + /* control 111 */ + if (f54->query_27.has_ctrl111) + reg_addr += CONTROL_111_SIZE; + + /* control 112 */ + if (f54->query_27.has_ctrl112) + reg_addr += CONTROL_112_SIZE; + + /* control 113 */ + if (f54->query_27.has_ctrl113) + reg_addr += CONTROL_113_SIZE; + + /* control 114 */ + if (f54->query_27.has_ctrl114) + reg_addr += CONTROL_114_SIZE; + + /* control 115 */ + if (f54->query_29.has_ctrl115) + reg_addr += CONTROL_115_SIZE; + + /* control 116 */ + if (f54->query_29.has_ctrl116) + reg_addr += CONTROL_116_SIZE; + + /* control 117 */ + if (f54->query_29.has_ctrl117) + reg_addr += CONTROL_117_SIZE; + + /* control 118 */ + if (f54->query_30.has_ctrl118) + reg_addr += CONTROL_118_SIZE; + + /* control 119 */ + if (f54->query_30.has_ctrl119) + reg_addr += CONTROL_119_SIZE; + + /* control 120 */ + if (f54->query_30.has_ctrl120) + reg_addr += CONTROL_120_SIZE; + + /* control 121 */ + if (f54->query_30.has_ctrl121) + reg_addr += CONTROL_121_SIZE; + + /* control 122 */ + if (f54->query_30.has_ctrl122_query31) + reg_addr += CONTROL_122_SIZE; + + /* control 123 */ + if (f54->query_30.has_ctrl123) + reg_addr += CONTROL_123_SIZE; + + /* control 124 */ + if (f54->query_30.has_ctrl124) + reg_addr += CONTROL_124_SIZE; + + /* control 125 */ + if (f54->query_32.has_ctrl125) + reg_addr += CONTROL_125_SIZE; + + /* control 126 */ + if (f54->query_32.has_ctrl126) + reg_addr += CONTROL_126_SIZE; + + /* control 127 */ + if (f54->query_32.has_ctrl127) + reg_addr += CONTROL_127_SIZE; + + /* control 128 */ + if (f54->query_33.has_ctrl128) + reg_addr += CONTROL_128_SIZE; + + /* control 129 */ + if (f54->query_33.has_ctrl129) + reg_addr += CONTROL_129_SIZE; + + /* control 130 */ + if (f54->query_33.has_ctrl130) + reg_addr += CONTROL_130_SIZE; + + /* control 131 */ + if (f54->query_33.has_ctrl131) + reg_addr += CONTROL_131_SIZE; + + /* control 132 */ + if (f54->query_33.has_ctrl132) + reg_addr += CONTROL_132_SIZE; + + /* control 133 */ + if (f54->query_33.has_ctrl133) + reg_addr += CONTROL_133_SIZE; + + /* control 134 */ + if (f54->query_33.has_ctrl134) + reg_addr += CONTROL_134_SIZE; + + /* control 135 */ + if (f54->query_35.has_ctrl135) + reg_addr += CONTROL_135_SIZE; + + /* control 136 */ + if (f54->query_35.has_ctrl136) + reg_addr += CONTROL_136_SIZE; + + /* control 137 */ + if (f54->query_35.has_ctrl137) + reg_addr += CONTROL_137_SIZE; + + /* control 138 */ + if (f54->query_35.has_ctrl138) + reg_addr += CONTROL_138_SIZE; + + /* control 139 */ + if (f54->query_35.has_ctrl139) + reg_addr += CONTROL_139_SIZE; + + /* control 140 */ + if (f54->query_35.has_ctrl140) + reg_addr += CONTROL_140_SIZE; + + /* control 141 */ + if (f54->query_36.has_ctrl141) + reg_addr += CONTROL_141_SIZE; + + /* control 142 */ + if (f54->query_36.has_ctrl142) + reg_addr += CONTROL_142_SIZE; + + /* control 143 */ + if (f54->query_36.has_ctrl143) + reg_addr += CONTROL_143_SIZE; + + /* control 144 */ + if (f54->query_36.has_ctrl144) + reg_addr += CONTROL_144_SIZE; + + /* control 145 */ + if (f54->query_36.has_ctrl145) + reg_addr += CONTROL_145_SIZE; + + /* control 146 */ + if (f54->query_36.has_ctrl146) + reg_addr += CONTROL_146_SIZE; + + /* control 147 */ + if (f54->query_38.has_ctrl147) + reg_addr += CONTROL_147_SIZE; + + /* control 148 */ + if (f54->query_38.has_ctrl148) + reg_addr += CONTROL_148_SIZE; + + /* control 149 */ + if (f54->query_38.has_ctrl149) { + control->reg_149 = kzalloc(sizeof(*(control->reg_149)), + GFP_KERNEL); + if (!control->reg_149) + goto exit_no_mem; + control->reg_149->address = reg_addr; + reg_addr += CONTROL_149_SIZE; + } + + /* control 150 */ + if (f54->query_38.has_ctrl150) + reg_addr += CONTROL_150_SIZE; + + /* control 151 */ + if (f54->query_38.has_ctrl151) + reg_addr += CONTROL_151_SIZE; + + /* control 152 */ + if (f54->query_38.has_ctrl152) + reg_addr += CONTROL_152_SIZE; + + /* control 153 */ + if (f54->query_38.has_ctrl153) + reg_addr += CONTROL_153_SIZE; + + /* control 154 */ + if (f54->query_39.has_ctrl154) + reg_addr += CONTROL_154_SIZE; + + /* control 155 */ + if (f54->query_39.has_ctrl155) + reg_addr += CONTROL_155_SIZE; + + /* control 156 */ + if (f54->query_39.has_ctrl156) + reg_addr += CONTROL_156_SIZE; + + /* controls 157 158 */ + if (f54->query_39.has_ctrl157_ctrl158) + reg_addr += CONTROL_157_158_SIZE; + + /* controls 159 to 162 reserved */ + + /* control 163 */ + if (f54->query_40.has_ctrl163_query41) + reg_addr += CONTROL_163_SIZE; + + /* control 164 reserved */ + + /* control 165 */ + if (f54->query_40.has_ctrl165_query42) + reg_addr += CONTROL_165_SIZE; + + /* control 166 */ + if (f54->query_40.has_ctrl166) + reg_addr += CONTROL_166_SIZE; + + /* control 167 */ + if (f54->query_40.has_ctrl167) + reg_addr += CONTROL_167_SIZE; + + /* control 168 */ + if (f54->query_40.has_ctrl168) + reg_addr += CONTROL_168_SIZE; + + /* control 169 */ + if (f54->query_40.has_ctrl169) + reg_addr += CONTROL_169_SIZE; + + /* control 170 reserved */ + + /* control 171 */ + if (f54->query_43.has_ctrl171) + reg_addr += CONTROL_171_SIZE; + + /* control 172 */ + if (f54->query_43.has_ctrl172_query44_query45) + reg_addr += CONTROL_172_SIZE; + + /* control 173 */ + if (f54->query_43.has_ctrl173) + reg_addr += CONTROL_173_SIZE; + + /* control 174 */ + if (f54->query_43.has_ctrl174) + reg_addr += CONTROL_174_SIZE; + + /* control 175 */ + if (f54->query_43.has_ctrl175) + reg_addr += CONTROL_175_SIZE; + + /* control 176 */ + if (f54->query_46.has_ctrl176) + reg_addr += CONTROL_176_SIZE; + + /* controls 177 178 */ + if (f54->query_46.has_ctrl177_ctrl178) + reg_addr += CONTROL_177_178_SIZE; + + /* control 179 */ + if (f54->query_46.has_ctrl179) + reg_addr += CONTROL_179_SIZE; + + /* controls 180 to 181 reserved */ + + /* control 182 */ + if (f54->query_47.has_ctrl182) + reg_addr += CONTROL_182_SIZE; + + /* control 183 */ + if (f54->query_47.has_ctrl183) + reg_addr += CONTROL_183_SIZE; + + /* control 184 reserved */ + + /* control 185 */ + if (f54->query_47.has_ctrl185) + reg_addr += CONTROL_185_SIZE; + + /* control 186 */ + if (f54->query_47.has_ctrl186) + reg_addr += CONTROL_186_SIZE; + + /* control 187 */ + if (f54->query_47.has_ctrl187) + reg_addr += CONTROL_187_SIZE; + + /* control 188 */ + if (f54->query_49.has_ctrl188) { + control->reg_188 = kzalloc(sizeof(*(control->reg_188)), + GFP_KERNEL); + if (!control->reg_188) + goto exit_no_mem; + control->reg_188->address = reg_addr; + reg_addr += CONTROL_188_SIZE; + } + + return 0; + +exit_no_mem: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for control registers\n", + __func__); + return -ENOMEM; +} + +static int test_set_queries(void) +{ + int retval; + unsigned char offset; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr, + f54->query.data, + sizeof(f54->query.data)); + if (retval < 0) + return retval; + + offset = sizeof(f54->query.data); + + /* query 12 */ + if (f54->query.has_sense_frequency_control == 0) + offset -= 1; + + /* query 13 */ + if (f54->query.has_query13) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_13.data, + sizeof(f54->query_13.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 14 */ + if (f54->query_13.has_ctrl87) + offset += 1; + + /* query 15 */ + if (f54->query.has_query15) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_15.data, + sizeof(f54->query_15.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 16 */ + if (f54->query_15.has_query16) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_16.data, + sizeof(f54->query_16.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 17 */ + if (f54->query_16.has_query17) + offset += 1; + + /* query 18 */ + if (f54->query_16.has_ctrl94_query18) + offset += 1; + + /* query 19 */ + if (f54->query_16.has_ctrl95_query19) + offset += 1; + + /* query 20 */ + if (f54->query_15.has_query20) + offset += 1; + + /* query 21 */ + if (f54->query_15.has_query21) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_21.data, + sizeof(f54->query_21.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 22 */ + if (f54->query_15.has_query22) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_22.data, + sizeof(f54->query_22.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 23 */ + if (f54->query_22.has_query23) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_23.data, + sizeof(f54->query_23.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 24 */ + if (f54->query_21.has_query24_data18) + offset += 1; + + /* query 25 */ + if (f54->query_15.has_query25) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_25.data, + sizeof(f54->query_25.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 26 */ + if (f54->query_22.has_ctrl103_query26) + offset += 1; + + /* query 27 */ + if (f54->query_25.has_query27) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_27.data, + sizeof(f54->query_27.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 28 */ + if (f54->query_22.has_query28) + offset += 1; + + /* query 29 */ + if (f54->query_27.has_query29) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_29.data, + sizeof(f54->query_29.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 30 */ + if (f54->query_29.has_query30) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_30.data, + sizeof(f54->query_30.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 31 */ + if (f54->query_30.has_ctrl122_query31) + offset += 1; + + /* query 32 */ + if (f54->query_30.has_query32) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_32.data, + sizeof(f54->query_32.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 33 */ + if (f54->query_32.has_query33) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_33.data, + sizeof(f54->query_33.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 34 */ + if (f54->query_32.has_query34) + offset += 1; + + /* query 35 */ + if (f54->query_32.has_query35) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_35.data, + sizeof(f54->query_35.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 36 */ + if (f54->query_33.has_query36) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_36.data, + sizeof(f54->query_36.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 37 */ + if (f54->query_36.has_query37) + offset += 1; + + /* query 38 */ + if (f54->query_36.has_query38) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_38.data, + sizeof(f54->query_38.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 39 */ + if (f54->query_38.has_query39) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_39.data, + sizeof(f54->query_39.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 40 */ + if (f54->query_39.has_query40) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_40.data, + sizeof(f54->query_40.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 41 */ + if (f54->query_40.has_ctrl163_query41) + offset += 1; + + /* query 42 */ + if (f54->query_40.has_ctrl165_query42) + offset += 1; + + /* query 43 */ + if (f54->query_40.has_query43) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_43.data, + sizeof(f54->query_43.data)); + if (retval < 0) + return retval; + offset += 1; + } + + if (f54->query_43.has_ctrl172_query44_query45) + offset += 2; + + /* query 46 */ + if (f54->query_43.has_query46) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_46.data, + sizeof(f54->query_46.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 47 */ + if (f54->query_46.has_query47) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_47.data, + sizeof(f54->query_47.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 48 reserved */ + + /* query 49 */ + if (f54->query_47.has_query49) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_49.data, + sizeof(f54->query_49.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 50 */ + if (f54->query_49.has_query50) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_50.data, + sizeof(f54->query_50.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 51 */ + if (f54->query_50.has_query51) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_51.data, + sizeof(f54->query_51.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 53 54 */ + if (f54->query_51.has_query53_query54_ctrl198) + offset += 2; + + /* query 55 */ + if (f54->query_51.has_query55) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_55.data, + sizeof(f54->query_55.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 56 */ + if (f54->query_55.has_query56) + offset += 1; + + /* query 57 */ + if (f54->query_55.has_query57) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_57.data, + sizeof(f54->query_57.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 58 */ + if (f54->query_57.has_query58) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_58.data, + sizeof(f54->query_58.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 59 */ + if (f54->query_58.has_query59) + offset += 1; + + /* query 60 */ + if (f54->query_58.has_query60) + offset += 1; + + /* query 61 */ + if (f54->query_58.has_query61) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_61.data, + sizeof(f54->query_61.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 62 63 */ + if (f54->query_61.has_ctrl215_query62_query63) + offset += 2; + + /* query 64 */ + if (f54->query_61.has_query64) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_64.data, + sizeof(f54->query_64.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 65 */ + if (f54->query_64.has_query65) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_65.data, + sizeof(f54->query_65.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 66 */ + if (f54->query_65.has_query66_ctrl231) + offset += 1; + + /* query 67 */ + if (f54->query_65.has_query67) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_67.data, + sizeof(f54->query_67.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 68 */ + if (f54->query_67.has_query68) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_68.data, + sizeof(f54->query_68.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 68 */ + if (f54->query_68.has_query69) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_69.data, + sizeof(f54->query_69.data)); + if (retval < 0) + return retval; + offset += 1; + } + + return 0; +} + +static void test_f54_set_regs(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count, + unsigned char page) +{ + unsigned char ii; + unsigned char intr_offset; + + f54->query_base_addr = fd->query_base_addr | (page << 8); + f54->control_base_addr = fd->ctrl_base_addr | (page << 8); + f54->data_base_addr = fd->data_base_addr | (page << 8); + f54->command_base_addr = fd->cmd_base_addr | (page << 8); + + f54->intr_reg_num = (intr_count + 7) / 8; + if (f54->intr_reg_num != 0) + f54->intr_reg_num -= 1; + + f54->intr_mask = 0; + intr_offset = intr_count % 8; + for (ii = intr_offset; + ii < (fd->intr_src_count + intr_offset); + ii++) { + f54->intr_mask |= 1 << ii; + } + + return; +} + +static int test_f55_set_controls(void) +{ + unsigned char offset = 0; + + /* controls 0 1 2 */ + if (f55->query.has_sensor_assignment) + offset += 3; + + /* control 3 */ + if (f55->query.has_edge_compensation) + offset++; + + /* control 4 */ + if (f55->query.curve_compensation_mode == 0x1 || + f55->query.curve_compensation_mode == 0x2) + offset++; + + /* control 5 */ + if (f55->query.curve_compensation_mode == 0x2) + offset++; + + /* control 6 */ + if (f55->query.has_ctrl6) + offset++; + + /* control 7 */ + if (f55->query.has_alternate_transmitter_assignment) + offset++; + + /* control 8 */ + if (f55->query_3.has_ctrl8) + offset++; + + /* control 9 */ + if (f55->query_3.has_ctrl9) + offset++; + + /* control 10 */ + if (f55->query_5.has_corner_compensation) + offset++; + + /* control 11 */ + if (f55->query.curve_compensation_mode == 0x3) + offset++; + + /* control 12 */ + if (f55->query_5.has_ctrl12) + offset++; + + /* control 13 */ + if (f55->query_5.has_ctrl13) + offset++; + + /* control 14 */ + if (f55->query_5.has_ctrl14) + offset++; + + /* control 15 */ + if (f55->query_5.has_basis_function) + offset++; + + /* control 16 */ + if (f55->query_17.has_ctrl16) + offset++; + + /* control 17 */ + if (f55->query_17.has_ctrl17) + offset++; + + /* controls 18 19 */ + if (f55->query_17.has_ctrl18_ctrl19) + offset += 2; + + /* control 20 */ + if (f55->query_17.has_ctrl20) + offset++; + + /* control 21 */ + if (f55->query_17.has_ctrl21) + offset++; + + /* control 22 */ + if (f55->query_17.has_ctrl22) + offset++; + + /* control 23 */ + if (f55->query_18.has_ctrl23) + offset++; + + /* control 24 */ + if (f55->query_18.has_ctrl24) + offset++; + + /* control 25 */ + if (f55->query_18.has_ctrl25) + offset++; + + /* control 26 */ + if (f55->query_18.has_ctrl26) + offset++; + + /* control 27 */ + if (f55->query_18.has_ctrl27_query20) + offset++; + + /* control 28 */ + if (f55->query_18.has_ctrl28_query21) + offset++; + + /* control 29 */ + if (f55->query_22.has_ctrl29) + offset++; + + /* control 30 */ + if (f55->query_22.has_ctrl30) + offset++; + + /* control 31 */ + if (f55->query_22.has_ctrl31) + offset++; + + /* control 32 */ + if (f55->query_22.has_ctrl32) + offset++; + + /* controls 33 34 35 36 reserved */ + + /* control 37 */ + if (f55->query_28.has_ctrl37) + offset++; + + /* control 38 */ + if (f55->query_30.has_ctrl38) + offset++; + + /* control 39 */ + if (f55->query_30.has_ctrl39) + offset++; + + /* control 40 */ + if (f55->query_30.has_ctrl40) + offset++; + + /* control 41 */ + if (f55->query_30.has_ctrl41) + offset++; + + /* control 42 */ + if (f55->query_30.has_ctrl42) + offset++; + + /* controls 43 44 */ + if (f55->query_30.has_ctrl43_ctrl44) { + f55->afe_mux_offset = offset; + offset += 2; + } + + /* controls 45 46 */ + if (f55->query_33.has_ctrl45_ctrl46) { + f55->has_force = true; + f55->force_tx_offset = offset; + f55->force_rx_offset = offset + 1; + offset += 2; + } + + return 0; +} + +static int test_f55_set_queries(void) +{ + int retval; + unsigned char offset; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr, + f55->query.data, + sizeof(f55->query.data)); + if (retval < 0) + return retval; + + offset = sizeof(f55->query.data); + + /* query 3 */ + if (f55->query.has_single_layer_multi_touch) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_3.data, + sizeof(f55->query_3.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 4 */ + if (f55->query_3.has_ctrl9) + offset += 1; + + /* query 5 */ + if (f55->query.has_query5) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_5.data, + sizeof(f55->query_5.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 6 7 */ + if (f55->query.curve_compensation_mode == 0x3) + offset += 2; + + /* query 8 */ + if (f55->query_3.has_ctrl8) + offset += 1; + + /* query 9 */ + if (f55->query_3.has_query9) + offset += 1; + + /* queries 10 11 12 13 14 15 16 */ + if (f55->query_5.has_basis_function) + offset += 7; + + /* query 17 */ + if (f55->query_5.has_query17) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_17.data, + sizeof(f55->query_17.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 18 */ + if (f55->query_17.has_query18) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_18.data, + sizeof(f55->query_18.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 19 */ + if (f55->query_18.has_query19) + offset += 1; + + /* query 20 */ + if (f55->query_18.has_ctrl27_query20) + offset += 1; + + /* query 21 */ + if (f55->query_18.has_ctrl28_query21) + offset += 1; + + /* query 22 */ + if (f55->query_18.has_query22) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_22.data, + sizeof(f55->query_22.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 23 */ + if (f55->query_22.has_query23) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_23.data, + sizeof(f55->query_23.data)); + if (retval < 0) + return retval; + offset += 1; + + f55->amp_sensor = f55->query_23.amp_sensor_enabled; + f55->size_of_column2mux = f55->query_23.size_of_column2mux; + } + + /* queries 24 25 26 27 reserved */ + + /* query 28 */ + if (f55->query_22.has_query28) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_28.data, + sizeof(f55->query_28.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 29 */ + if (f55->query_28.has_query29) + offset += 1; + + /* query 30 */ + if (f55->query_28.has_query30) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_30.data, + sizeof(f55->query_30.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 31 32 */ + if (f55->query_30.has_query31_query32) + offset += 2; + + /* query 33 */ + if (f55->query_30.has_query33) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_33.data, + sizeof(f55->query_33.data)); + if (retval < 0) + return retval; + offset += 1; + + f55->extended_amp = f55->query_33.has_extended_amp_pad; + } + + return 0; +} + +static void test_f55_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char ii; + unsigned char rx_electrodes; + unsigned char tx_electrodes; + struct f55_control_43 ctrl_43; + + retval = test_f55_set_queries(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 query registers\n", + __func__); + return; + } + + if (!f55->query.has_sensor_assignment) + return; + + retval = test_f55_set_controls(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set up F55 control registers\n", + __func__); + return; + } + + tx_electrodes = f55->query.num_of_tx_electrodes; + rx_electrodes = f55->query.num_of_rx_electrodes; + + f55->tx_assignment = kzalloc(tx_electrodes, GFP_KERNEL); + f55->rx_assignment = kzalloc(rx_electrodes, GFP_KERNEL); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + SENSOR_TX_MAPPING_OFFSET, + f55->tx_assignment, + tx_electrodes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 tx assignment\n", + __func__); + return; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + SENSOR_RX_MAPPING_OFFSET, + f55->rx_assignment, + rx_electrodes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 rx assignment\n", + __func__); + return; + } + + f54->tx_assigned = 0; + for (ii = 0; ii < tx_electrodes; ii++) { + if (f55->tx_assignment[ii] != 0xff) + f54->tx_assigned++; + } + + f54->rx_assigned = 0; + for (ii = 0; ii < rx_electrodes; ii++) { + if (f55->rx_assignment[ii] != 0xff) + f54->rx_assigned++; + } + + if (f55->amp_sensor) { + f54->tx_assigned = f55->size_of_column2mux; + f54->rx_assigned /= 2; + } + + if (f55->extended_amp) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + f55->afe_mux_offset, + ctrl_43.data, + sizeof(ctrl_43.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 AFE mux sizes\n", + __func__); + return; + } + + f54->tx_assigned = ctrl_43.afe_l_mux_size + + ctrl_43.afe_r_mux_size; + } + + /* force mapping */ + if (f55->has_force) { + f55->force_tx_assignment = kzalloc(tx_electrodes, GFP_KERNEL); + f55->force_rx_assignment = kzalloc(rx_electrodes, GFP_KERNEL); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + f55->force_tx_offset, + f55->force_tx_assignment, + tx_electrodes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 force tx assignment\n", + __func__); + return; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + f55->force_rx_offset, + f55->force_rx_assignment, + rx_electrodes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 force rx assignment\n", + __func__); + return; + } + + for (ii = 0; ii < tx_electrodes; ii++) { + if (f55->force_tx_assignment[ii] != 0xff) + f54->tx_assigned++; + } + + for (ii = 0; ii < rx_electrodes; ii++) { + if (f55->force_rx_assignment[ii] != 0xff) + f54->rx_assigned++; + } + } + + return; +} + +static void test_f55_set_regs(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn_desc *fd, + unsigned char page) +{ + f55 = kzalloc(sizeof(*f55), GFP_KERNEL); + if (!f55) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for F55\n", + __func__); + return; + } + + f55->query_base_addr = fd->query_base_addr | (page << 8); + f55->control_base_addr = fd->ctrl_base_addr | (page << 8); + f55->data_base_addr = fd->data_base_addr | (page << 8); + f55->command_base_addr = fd->cmd_base_addr | (page << 8); + + return; +} + +static void test_f21_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char ii; + unsigned char size_of_query2; + unsigned char size_of_query5; + unsigned char query_11_offset; + unsigned char ctrl_4_offset; + struct f21_query_2 *query_2 = NULL; + struct f21_query_5 *query_5 = NULL; + struct f21_query_11 *query_11 = NULL; + + query_2 = kzalloc(sizeof(*query_2), GFP_KERNEL); + if (!query_2) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_2\n", + __func__); + goto exit; + } + + query_5 = kzalloc(sizeof(*query_5), GFP_KERNEL); + if (!query_5) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_5\n", + __func__); + goto exit; + } + + query_11 = kzalloc(sizeof(*query_11), GFP_KERNEL); + if (!query_11) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_11\n", + __func__); + goto exit; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 1, + &size_of_query2, + sizeof(size_of_query2)); + if (retval < 0) + goto exit; + + if (size_of_query2 > sizeof(query_2->data)) + size_of_query2 = sizeof(query_2->data); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 2, + query_2->data, + size_of_query2); + if (retval < 0) + goto exit; + + if (!query_2->query11_is_present) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No F21 force capabilities\n", + __func__); + goto exit; + } + + query_11_offset = query_2->query0_is_present + + query_2->query1_is_present + + query_2->query2_is_present + + query_2->query3_is_present + + query_2->query4_is_present + + query_2->query5_is_present + + query_2->query6_is_present + + query_2->query7_is_present + + query_2->query8_is_present + + query_2->query9_is_present + + query_2->query10_is_present; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 11, + query_11->data, + sizeof(query_11->data)); + if (retval < 0) + goto exit; + + if (!query_11->has_force_sensing_txrx_mapping) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No F21 force mapping\n", + __func__); + goto exit; + } + + f21->max_num_of_tx = query_11->max_number_of_force_txs; + f21->max_num_of_rx = query_11->max_number_of_force_rxs; + f21->max_num_of_txrx = f21->max_num_of_tx + f21->max_num_of_rx; + + f21->force_txrx_assignment = kzalloc(f21->max_num_of_txrx, GFP_KERNEL); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 4, + &size_of_query5, + sizeof(size_of_query5)); + if (retval < 0) + goto exit; + + if (size_of_query5 > sizeof(query_5->data)) + size_of_query5 = sizeof(query_5->data); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 5, + query_5->data, + size_of_query5); + if (retval < 0) + goto exit; + + ctrl_4_offset = query_5->ctrl0_is_present + + query_5->ctrl1_is_present + + query_5->ctrl2_is_present + + query_5->ctrl3_is_present; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->control_base_addr + ctrl_4_offset, + f21->force_txrx_assignment, + f21->max_num_of_txrx); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F21 force txrx assignment\n", + __func__); + goto exit; + } + + f21->has_force = true; + + for (ii = 0; ii < f21->max_num_of_tx; ii++) { + if (f21->force_txrx_assignment[ii] != 0xff) + f21->tx_assigned++; + } + + for (ii = f21->max_num_of_tx; ii < f21->max_num_of_txrx; ii++) { + if (f21->force_txrx_assignment[ii] != 0xff) + f21->rx_assigned++; + } + +exit: + kfree(query_2); + kfree(query_5); + kfree(query_11); + + return; +} + +static void test_f21_set_regs(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn_desc *fd, + unsigned char page) +{ + f21 = kzalloc(sizeof(*f21), GFP_KERNEL); + if (!f21) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for F21\n", + __func__); + return; + } + + f21->query_base_addr = fd->query_base_addr | (page << 8); + f21->control_base_addr = fd->ctrl_base_addr | (page << 8); + f21->data_base_addr = fd->data_base_addr | (page << 8); + f21->command_base_addr = fd->cmd_base_addr | (page << 8); + + return; +} + +static int test_scan_pdt(void) +{ + int retval; + unsigned char intr_count = 0; + unsigned char page; + unsigned short addr; + bool f54found = false; + bool f55found = false; + struct synaptics_rmi4_fn_desc rmi_fd; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + for (page = 0; page < PAGES_TO_SERVICE; page++) { + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + addr |= (page << 8); + + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&rmi_fd, + sizeof(rmi_fd)); + if (retval < 0) + return retval; + + addr &= ~(MASK_8BIT << 8); + + if (!rmi_fd.fn_number) + break; + + switch (rmi_fd.fn_number) { + case SYNAPTICS_RMI4_F54: + test_f54_set_regs(rmi4_data, + &rmi_fd, intr_count, page); + f54found = true; + break; + case SYNAPTICS_RMI4_F55: + test_f55_set_regs(rmi4_data, + &rmi_fd, page); + f55found = true; + break; + case SYNAPTICS_RMI4_F21: + test_f21_set_regs(rmi4_data, + &rmi_fd, page); + break; + default: + break; + } + + if (f54found && f55found) + goto pdt_done; + + intr_count += rmi_fd.intr_src_count; + } + } + + if (!f54found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F54\n", + __func__); + return -EINVAL; + } + +pdt_done: + return 0; +} + +static void synaptics_rmi4_test_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!f54) + return; + + if (f54->intr_mask & intr_mask) + queue_work(f54->test_report_workqueue, &f54->test_report_work); + + return; +} + +static int synaptics_rmi4_test_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + + if (f54) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + f54 = kzalloc(sizeof(*f54), GFP_KERNEL); + if (!f54) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for F54\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + f54->rmi4_data = rmi4_data; + + f55 = NULL; + + f21 = NULL; + + retval = test_scan_pdt(); + if (retval < 0) + goto exit_free_mem; + + retval = test_set_queries(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F54 query registers\n", + __func__); + goto exit_free_mem; + } + + f54->tx_assigned = f54->query.num_of_tx_electrodes; + f54->rx_assigned = f54->query.num_of_rx_electrodes; + + retval = test_set_controls(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set up F54 control registers\n", + __func__); + goto exit_free_control; + } + + test_set_data(); + + if (f55) + test_f55_init(rmi4_data); + + if (f21) + test_f21_init(rmi4_data); + + if (rmi4_data->external_afe_buttons) + f54->tx_assigned++; + + retval = test_set_sysfs(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs entries\n", + __func__); + goto exit_sysfs; + } + + f54->test_report_workqueue = + create_singlethread_workqueue("test_report_workqueue"); + INIT_WORK(&f54->test_report_work, test_report_work); + + hrtimer_init(&f54->watchdog, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + f54->watchdog.function = test_get_report_timeout; + INIT_WORK(&f54->timeout_work, test_timeout_work); + + mutex_init(&f54->status_mutex); + f54->status = STATUS_IDLE; + + return 0; + +exit_sysfs: + if (f21) + kfree(f21->force_txrx_assignment); + + if (f55) { + kfree(f55->tx_assignment); + kfree(f55->rx_assignment); + kfree(f55->force_tx_assignment); + kfree(f55->force_rx_assignment); + } + +exit_free_control: + test_free_control_mem(); + +exit_free_mem: + kfree(f21); + f21 = NULL; + kfree(f55); + f55 = NULL; + kfree(f54); + f54 = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_test_remove(struct synaptics_rmi4_data *rmi4_data) +{ + if (!f54) + goto exit; + + hrtimer_cancel(&f54->watchdog); + + cancel_work_sync(&f54->test_report_work); + flush_workqueue(f54->test_report_workqueue); + destroy_workqueue(f54->test_report_workqueue); + + test_remove_sysfs(); + + if (f21) + kfree(f21->force_txrx_assignment); + + if (f55) { + kfree(f55->tx_assignment); + kfree(f55->rx_assignment); + kfree(f55->force_tx_assignment); + kfree(f55->force_rx_assignment); + } + + test_free_control_mem(); + + if (f54->data_buffer_size) + kfree(f54->report_data); + + kfree(f21); + f21 = NULL; + + kfree(f55); + f55 = NULL; + + kfree(f54); + f54 = NULL; + +exit: + complete(&test_remove_complete); + + return; +} + +static void synaptics_rmi4_test_reset(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + + if (!f54) { + synaptics_rmi4_test_init(rmi4_data); + return; + } + + if (f21) + kfree(f21->force_txrx_assignment); + + if (f55) { + kfree(f55->tx_assignment); + kfree(f55->rx_assignment); + kfree(f55->force_tx_assignment); + kfree(f55->force_rx_assignment); + } + + test_free_control_mem(); + + kfree(f55); + f55 = NULL; + + kfree(f21); + f21 = NULL; + + retval = test_scan_pdt(); + if (retval < 0) + goto exit_free_mem; + + retval = test_set_queries(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F54 query registers\n", + __func__); + goto exit_free_mem; + } + + f54->tx_assigned = f54->query.num_of_tx_electrodes; + f54->rx_assigned = f54->query.num_of_rx_electrodes; + + retval = test_set_controls(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set up F54 control registers\n", + __func__); + goto exit_free_control; + } + + test_set_data(); + + if (f55) + test_f55_init(rmi4_data); + + if (f21) + test_f21_init(rmi4_data); + + if (rmi4_data->external_afe_buttons) + f54->tx_assigned++; + + f54->status = STATUS_IDLE; + + return; + +exit_free_control: + test_free_control_mem(); + +exit_free_mem: + hrtimer_cancel(&f54->watchdog); + + cancel_work_sync(&f54->test_report_work); + flush_workqueue(f54->test_report_workqueue); + destroy_workqueue(f54->test_report_workqueue); + + test_remove_sysfs(); + + if (f54->data_buffer_size) + kfree(f54->report_data); + + kfree(f21); + f21 = NULL; + + kfree(f55); + f55 = NULL; + + kfree(f54); + f54 = NULL; + + return; +} + +static struct synaptics_rmi4_exp_fn test_module = { + .fn_type = RMI_TEST_REPORTING, + .init = synaptics_rmi4_test_init, + .remove = synaptics_rmi4_test_remove, + .reset = synaptics_rmi4_test_reset, + .reinit = NULL, + .early_suspend = NULL, + .suspend = NULL, + .resume = NULL, + .late_resume = NULL, + .attn = synaptics_rmi4_test_attn, +}; + +static int __init rmi4_test_module_init(void) +{ + synaptics_rmi4_new_function(&test_module, true); + + return 0; +} + +static void __exit rmi4_test_module_exit(void) +{ + synaptics_rmi4_new_function(&test_module, false); + + wait_for_completion(&test_remove_complete); + + return; +} + +module_init(rmi4_test_module_init); +module_exit(rmi4_test_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX Test Reporting Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310/synaptics_dsx_video.c b/drivers/input/touchscreen/td4310/synaptics_dsx_video.c new file mode 100644 index 0000000000000..59ef780d423cf --- /dev/null +++ b/drivers/input/touchscreen/td4310/synaptics_dsx_video.c @@ -0,0 +1,416 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define SYSFS_FOLDER_NAME "video" + +/* +#define RMI_DCS_SUSPEND_RESUME +*/ + +static ssize_t video_sysfs_dcs_write_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t video_sysfs_param_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static int video_send_dcs_command(unsigned char command_opcode); + +struct f38_command { + union { + struct { + unsigned char command_opcode; + unsigned char register_access:1; + unsigned char gamma_page:1; + unsigned char f38_control1_b2__7:6; + unsigned char parameter_field_1; + unsigned char parameter_field_2; + unsigned char parameter_field_3; + unsigned char parameter_field_4; + unsigned char send_to_dcs:1; + unsigned char f38_command6_b1__7:7; + } __packed; + unsigned char data[7]; + }; +}; + +struct synaptics_rmi4_video_handle { + unsigned char param; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; + struct synaptics_rmi4_data *rmi4_data; + struct kobject *sysfs_dir; +}; + +#ifdef RMI_DCS_SUSPEND_RESUME +struct dcs_command { + unsigned char command; + unsigned int wait_time; +}; + +static struct dcs_command suspend_sequence[] = { + { + .command = 0x28, + .wait_time = 200, + }, + { + .command = 0x10, + .wait_time = 200, + }, +}; + +static struct dcs_command resume_sequence[] = { + { + .command = 0x11, + .wait_time = 200, + }, + { + .command = 0x29, + .wait_time = 200, + }, +}; +#endif + +static struct device_attribute attrs[] = { + __ATTR(dcs_write, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + video_sysfs_dcs_write_store), + __ATTR(param, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + video_sysfs_param_store), +}; + +static struct synaptics_rmi4_video_handle *video; + +DECLARE_COMPLETION(video_remove_complete); + +static ssize_t video_sysfs_dcs_write_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + + if (sscanf(buf, "%x", &input) != 1) + return -EINVAL; + + retval = video_send_dcs_command((unsigned char)input); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t video_sysfs_param_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%x", &input) != 1) + return -EINVAL; + + video->param = (unsigned char)input; + + return count; +} + +static int video_send_dcs_command(unsigned char command_opcode) +{ + int retval; + struct f38_command command; + struct synaptics_rmi4_data *rmi4_data = video->rmi4_data; + + memset(&command, 0x00, sizeof(command)); + + command.command_opcode = command_opcode; + command.parameter_field_1 = video->param; + command.send_to_dcs = 1; + + video->param = 0; + + retval = synaptics_rmi4_reg_write(rmi4_data, + video->command_base_addr, + command.data, + sizeof(command.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to send DCS command\n", + __func__); + return retval; + } + + return 0; +} + +static int video_scan_pdt(void) +{ + int retval; + unsigned char page; + unsigned short addr; + bool f38_found = false; + struct synaptics_rmi4_fn_desc rmi_fd; + struct synaptics_rmi4_data *rmi4_data = video->rmi4_data; + + for (page = 0; page < PAGES_TO_SERVICE; page++) { + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + addr |= (page << 8); + + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&rmi_fd, + sizeof(rmi_fd)); + if (retval < 0) + return retval; + + addr &= ~(MASK_8BIT << 8); + + if (!rmi_fd.fn_number) + break; + + if (rmi_fd.fn_number == SYNAPTICS_RMI4_F38) { + f38_found = true; + goto f38_found; + } + } + } + + if (!f38_found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F38\n", + __func__); + return -EINVAL; + } + +f38_found: + video->query_base_addr = rmi_fd.query_base_addr | (page << 8); + video->control_base_addr = rmi_fd.ctrl_base_addr | (page << 8); + video->data_base_addr = rmi_fd.data_base_addr | (page << 8); + video->command_base_addr = rmi_fd.cmd_base_addr | (page << 8); + + return 0; +} + +static int synaptics_rmi4_video_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char attr_count; + + if (video) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + video = kzalloc(sizeof(*video), GFP_KERNEL); + if (!video) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for video\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + video->rmi4_data = rmi4_data; + + retval = video_scan_pdt(); + if (retval < 0) { + retval = 0; + goto exit_scan_pdt; + } + + video->sysfs_dir = kobject_create_and_add(SYSFS_FOLDER_NAME, + &rmi4_data->input_dev->dev.kobj); + if (!video->sysfs_dir) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs directory\n", + __func__); + retval = -ENODEV; + goto exit_sysfs_dir; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(video->sysfs_dir, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + retval = -ENODEV; + goto exit_sysfs_attrs; + } + } + + return 0; + +exit_sysfs_attrs: + for (attr_count--; attr_count >= 0; attr_count--) + sysfs_remove_file(video->sysfs_dir, &attrs[attr_count].attr); + + kobject_put(video->sysfs_dir); + +exit_sysfs_dir: +exit_scan_pdt: + kfree(video); + video = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_video_remove(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char attr_count; + + if (!video) + goto exit; + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) + sysfs_remove_file(video->sysfs_dir, &attrs[attr_count].attr); + + kobject_put(video->sysfs_dir); + + kfree(video); + video = NULL; + +exit: + complete(&video_remove_complete); + + return; +} + +static void synaptics_rmi4_video_reset(struct synaptics_rmi4_data *rmi4_data) +{ + if (!video) + synaptics_rmi4_video_init(rmi4_data); + + return; +} + +#ifdef RMI_DCS_SUSPEND_RESUME +static void synaptics_rmi4_video_suspend(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char ii; + unsigned char command; + unsigned char num_of_cmds; + + if (!video) + return; + + num_of_cmds = ARRAY_SIZE(suspend_sequence); + + for (ii = 0; ii < num_of_cmds; ii++) { + command = suspend_sequence[ii].command; + retval = video_send_dcs_command(command); + if (retval < 0) + return; + msleep(suspend_sequence[ii].wait_time); + } + + return; +} + +static void synaptics_rmi4_video_resume(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char ii; + unsigned char command; + unsigned char num_of_cmds; + + if (!video) + return; + + num_of_cmds = ARRAY_SIZE(resume_sequence); + + for (ii = 0; ii < num_of_cmds; ii++) { + command = resume_sequence[ii].command; + retval = video_send_dcs_command(command); + if (retval < 0) + return; + msleep(resume_sequence[ii].wait_time); + } + + return; +} +#endif + +static struct synaptics_rmi4_exp_fn video_module = { + .fn_type = RMI_VIDEO, + .init = synaptics_rmi4_video_init, + .remove = synaptics_rmi4_video_remove, + .reset = synaptics_rmi4_video_reset, + .reinit = NULL, + .early_suspend = NULL, +#ifdef RMI_DCS_SUSPEND_RESUME + .suspend = synaptics_rmi4_video_suspend, + .resume = synaptics_rmi4_video_resume, +#else + .suspend = NULL, + .resume = NULL, +#endif + .late_resume = NULL, + .attn = NULL, +}; + +static int __init rmi4_video_module_init(void) +{ + synaptics_rmi4_new_function(&video_module, true); + + return 0; +} + +static void __exit rmi4_video_module_exit(void) +{ + synaptics_rmi4_new_function(&video_module, false); + + wait_for_completion(&video_remove_complete); + + return; +} + +module_init(rmi4_video_module_init); +module_exit(rmi4_video_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX Video Module"); +MODULE_LICENSE("GPL v2"); diff --git a/firmware/Makefile b/firmware/Makefile index e297e1b52636d..5df50e11c8cd8 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -135,6 +135,7 @@ fw-shipped-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda/xircom_pgs.fw fw-shipped-$(CONFIG_USB_VICAM) += vicam/firmware.fw fw-shipped-$(CONFIG_VIDEO_CPIA2) += cpia2/stv0672_vp4.bin fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin +fw-shipped-$(CONFIG_TOUCHSCREEN_TD4310) += synaptics/startup_fw_update.img fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-) diff --git a/firmware/synaptics/startup_fw_update.img.ihex b/firmware/synaptics/startup_fw_update.img.ihex new file mode 100644 index 0000000000000..b349664b28720 --- /dev/null +++ b/firmware/synaptics/startup_fw_update.img.ihex @@ -0,0 +1,6531 @@ +:100000007420716500000010000000001000000066 +:1000100079345A5400000000000000000000000085 +:100020000000000000000000280000003000000078 +:1000300060000000B0000000300100005009000026 +:1000400090820100C0820100F08201002083010043 +:10005000B0850100D0970100000000000000000002 +:100060008F5C74D00D000000000000000000000054 +:1000700000000000000000002200000080000000DE +:10008000130E010034972700445335205231372E88 +:10009000302E300000000000533336303352000061 +:1000A0000000000000000000000000000000000050 +:1000B000E883D1070F0000000000000000000000EE +:1000C000000000000000000060000000D000000000 +:1000D0000000010000020000240502000100EF0101 +:1000E000070606001000F0010F00030006000002E2 +:1000F000670207007A150602641B0800800080175B +:10010000671A0500100000180F00040010001018F6 +:1001100003000000000000000000000000000000DC +:1001200000000000000000000000000048AB572D58 +:1001300069ACD3581300000000000000000000006C +:100140000000000000000000000800005001000056 +:10015000075205230000000000000000000000001E +:10016000000000000000000000000000000000008F +:100170000017031E0F550E37047F070A475C470020 +:10018000000000180E011E05506C6A272D9AFE9083 +:1001900001B9DA2ADA250D058C00E0B1E0B1400E94 +:1001A0001E20080A20011A5C0F0801CC4C46004CA6 +:1001B00000CC8C01012626808000000120010C0F5C +:1001C000401E280128804040008037225000000057 +:1001D0000037047F073CC80000000001002008C170 +:1001E0000A00000114030C0F0A00FF000100004B7D +:1001F000003C0000006400000010001000C8000077 +:100200000066668813000026050B0C0A0C080C0417 +:100210000C010C020C0105070C3A1E0014002228E8 +:1002200004005A321200D20080041B0000FF580262 +:10023000B80B60C8881300C08004400A100208464A +:1002400000002003900100FFFFFFFFE80301040509 +:100250004000130000000500022A043A00130006C3 +:10026000000300012804360012000A0007000225DE +:10027000843D001100060003000128843D001100A8 +:10028000080003000129843D0010000A0007000255 +:1002900025843D0010000C0007000226843D000F5D +:1002A000000F0007000227090908080809090909C1 +:1002B00009090909090909090909090909090903B4 +:1002C0000000002B0003005000323204100802002E +:1002D0000035A000A00000B40000000000000000F5 +:1002E000120080040414001A04003D2D00050500CE +:1002F0002A020000000800000000000001003C018C +:1003000000000150000A007B80807D7D7D7D7A7B2E +:1003100074716D807C77716A645A534A4140407AA7 +:1003200080808080808080808080808080808080CD +:10033000808080000000000001000F03030F030312 +:1003400014FA3F00000000000000E0FF020000007F +:10035000000000000000000000000000000C0C0E77 +:100360000005000000000000000000000001000087 +:100370000000000100000005080805000000000F53 +:10038000170303000007000E2813281A28FFFF7325 +:10039000737351CD0D0410101010FF2400060401DA +:1003A00003080509070C0A0D0B29272625242322FB +:1003B000211F201D1E28FFFFFF0F0E141211101306 +:1003C00015161718191A1BFFFF8080808080808007 +:1003D000808080808080808080808080808080801D +:1003E0008080808080979696949493939292919136 +:1003F0008F8E8D8A80000002FFFFFFFFFFFFFF004E +:1004000000000000000000000000000000000000EC +:1004100000000000000000000000000000000000DC +:1004200000000000000000000000000000000000CC +:1004300000000000000000000000000000000000BC +:1004400000000000000000000000000000000000AC +:10045000000000000000000000000000000000009C +:10046000000000000000000000000000000000008C +:10047000000000000000000000000000000000007C +:10048000000000000000000000000000000000006C +:10049000000000000000000000000000000000005C +:1004A000000000000000000000000000000000004C +:1004B000000000000000000000000000000000003C +:1004C000000000000000000000000000000000002C +:1004D000000000000000000000000000000000001C +:1004E000000000000000000000000000000000000C +:1004F00000000000000000000000000000000000FC +:1005000000000000000000000000000000000000EB +:1005100000000000000000000000000000000000DB +:1005200000000000000000000000000000000000CB +:1005300000000000000000000000000000000000BB +:1005400000000000000000000000000000000000AB +:10055000000000000000000000000000000000009B +:10056000000000000000000000000000000000008B +:10057000000000000000000000000000000000007B +:10058000000000000000000000000000000000006B +:10059000000000000000000000000000000000005B +:1005A000000000000000000000000000000000004B +:1005B000000000000000000000000000000000003B +:1005C000000000000000000000000000000000002B +:1005D000000000000000000000000000000000001B +:1005E000000000000000000000000000000000000B +:1005F00000000000000000000000000000000000FB +:1006000000000000000000000000000000000000EA +:1006100000000000000000000000000000000000DA +:1006200000000000000000000000000000000000CA +:1006300000000000000000000000000000000000BA +:1006400000000000000000000000000000000000AA +:10065000000000000000000000000000000000009A +:10066000000000000000000000000000000000008A +:10067000000000000000000000000000000000007A +:10068000000000000000000000000000000000006A +:10069000000000000000000000000000000000005A +:1006A000000000000000000000000000000000004A +:1006B000000000000000000000000000000000003A +:1006C000000000000000000000000000000000002A +:1006D000000000000000000000000000000000001A +:1006E000000000000000000000000000000000000A +:1006F00000000000000000000000000000000000FA +:1007000000000000000000000000000000000000E9 +:1007100000000000000000000000000000000000D9 +:1007200000000000000000000000000000000000C9 +:1007300000000000000000000000000000000000B9 +:1007400000000000000000000000000000000000A9 +:100750000000000000000000000000000000000099 +:100760000000000000000000000000000000000089 +:100770000000000000000000000000000000000079 +:100780000000000000000000000000000000000069 +:100790000000000000000000000000000000000059 +:1007A0000000000000000000000000000000000049 +:1007B0000000000000000000000000000000000039 +:1007C0000000000000000000000000000000000029 +:1007D0000000000000000000000000000000000019 +:1007E0000000000000000000000000000000000009 +:1007F00000000000000000000000000000000000F9 +:1008000000000000000000000000000000000000E8 +:1008100000000000000000000000000000000000D8 +:1008200000000000000000000000000000000000C8 +:1008300000000000000000000000000000000000B8 +:1008400000000000000000000000000000000000A8 +:100850000000000000000000000000000000000098 +:100860000000000000000000000000000000000088 +:100870000000000000000000000000000000000078 +:100880000000000000000000000000000000000068 +:100890000000000000000000000000000000000058 +:1008A0000000000000000000000000000000000048 +:1008B0000000000000000000000000000000000038 +:1008C0000000000000000000000000000000000028 +:1008D0000000000000000000000000000000000018 +:1008E0000000000000000000000000000000000008 +:1008F00000000000000000000000000000000000F8 +:1009000000000000000000000000000000000000E7 +:1009100000000000000000000000000000000000D7 +:1009200000000000000000000000000000000000C7 +:1009300000000000000000000000000000000000B7 +:100940000000000000000000000000001B0A3398B7 +:1009500096993082120000000000000000000000A4 +:100960000000000000000000A05701007009000016 +:1009700039B7338DCA8D8EBFF9D381CBD51DB22A3D +:100980004661A9FE4DA48235E082BB1883BEC558DE +:10099000FE8FBF3F7E94C6585284A1830EC2E58667 +:1009A000B6A2D05FBC45024BC076227C19B0BD1EFA +:1009B0008E5FB565326491F2249B3E7FBC502F5709 +:1009C000C944F1168FF01480558372115C49DEE63C +:1009D000110F2D2F2D78782D3C99FE3C95B436F5CE +:1009E000947E084B90AE74B0527ECC687B2BFC4456 +:1009F000EC3D1E8D74E3D69A0FEB7E3A9BC3C3FA8F +:100A000021374CB28C57414EA3F03FD8E19577B9CE +:100A10007CCC10EA0ABDBFEFAD4106999614ABDA63 +:100A2000CAA318E9EB084E9C97C1556995BEDC0333 +:100A30002B01EFA80DF1227851537514E54CF6E621 +:100A4000924CA0282F509435EE976A10D79E1A49E1 +:100A5000455C7B7FC8D4DE747D71E7F8A4C8FA3D9D +:100A6000071CB97AB1B17C3C81DECF2C075D34081C +:100A700087A26D03A5E94D57A4B84253FE72FB242B +:100A800085CA5A25A69CC8E06F402FCE0A7C50A28A +:100A90009E61A04BB252F02B668B6ADCCE7B2C3A67 +:100AA000C6A1937A1C22896E08898B9EF70348B5EC +:100AB000B88DF09CCEC0C9C057317F2C65BCA2A7B1 +:100AC0002CA1115E1E5832C578F9D32D41A3824B5B +:100AD0009E2D60B3F3D9BF37124439FB4A2ED86A32 +:100AE00088DC75C933F1D8B6DC0BCA4C12911EE90B +:100AF000ABB81409F10089FDC6E84F357D4C1A7C6E +:100B00008CF284EC91AD02DEDCA9A541AECE67F992 +:100B10004A48C12BF8D22513D09F4BEF3D3D5321BE +:100B2000D71454B8B9BAAD7A6D920CC468E247FADA +:100B3000505A757EE8ED12C3629382AF74B455A823 +:100B400053A795AFD26706817907ECA73644A5A0D5 +:100B50001BBAD41D55FD0D9D57CB898201A90E40AE +:100B60006C21619C1A1E47A1169A50E1B3B6BB15C1 +:100B7000DE572B640C0A7F54568480FE4DED390CF1 +:100B80000A44B16322D0A82CBED3545145AA208D6B +:100B90000C51F4C840F638CFB6ADA35C8C4970F761 +:100BA0008C511565D6594E0E4C9838B8FE446E429D +:100BB000ECB1F987BC7C14F41D776408E1732DB99E +:100BC0004FFF9D94FA7EC41EC7B080AC47872D8A24 +:100BD000448A3A04D9CCA778E8244FD3CF8A2D8D04 +:100BE0006D476F8BBB9AFA39F982BC5CB70C606FAA +:100BF000E75316BB9F1F7ED74670256C9C73D2307F +:100C0000DCF06478081A2CFBA40ED711FFB2CD15C6 +:100C1000A147FF5B528BEB0E029FC0681E76D9B8CE +:100C2000A6C2E0666FD3AE3BD1528A86AB8B34F35B +:100C30001328AB00B38BE25DCB52A20EE5CE5B2F47 +:100C40006A9CBA3FDEB826C66DCE1F507F2E50ADCF +:100C5000716B4780C547ADF160C5BCAB467D56A6FC +:100C600039D155D91DF683B13E05EA1BCBA550BA43 +:100C70003C1760C13727879C144BE71DF132E6F320 +:100C800025F17192DB24D4738378E2C9F272BCD56A +:100C9000DEE0DAE8DE04A5AC5158ED6C4ED55C59C7 +:100CA0003AE03774E3C82051511FC8FF5D636B60A1 +:100CB00098CDF0D5BB065E524D3AF64DB3975B0C1E +:100CC00036EBD673CCD3A5947637AACD49A3226C44 +:100CD0007FE7E3CEBFFA476399D6CD8E12A0496C69 +:100CE0008F416788849D0C30B03C265BBC70DFC8A8 +:100CF00074B9798F4E6B410BF6BEF500FFF23A8165 +:100D0000032E5D2A2EFD26EFF3A605A7C7FDDDFB0A +:100D100057C01A3E649E32D903F8B791E33279CFB7 +:100D200068A1178527F505F1CA989E840DEB2E1C46 +:100D3000E86F07133A87E1081308C875D171B07AD4 +:100D400012B2AD5B9399FCCA3C67C450BC703E2F95 +:100D500051FA8101CE31271446D11927A3B150C1D0 +:100D6000D41EA688666FEEF830D44F45AD11130C33 +:100D700011282866F2E5BD2EFDD4938FC176B5D13A +:100D8000B426719143D8F39BC1019A2A8DCCE0F926 +:100D9000F4B60ABBADDA77A92C2F45B2525DFD46F9 +:100DA0007D3CD794AAD597D00998EEB4742DD9D4A8 +:100DB0006B48A3AB9A99773CF855D2750E05940D04 +:100DC0002612356C8C5DC802B3F8E91A3C55E3FD78 +:100DD000C40704E4C7C78E5EAF3436EFF190009DC0 +:100DE00025DE55DFB6C6F2CA868A5EC4A97A250119 +:100DF0000C5C578F4BF0366E7EEEEAC24E0AFBEE6D +:100E0000FD4BB6BAA9EED07ECB376F4BBD4844A49C +:100E10003A60D22A60871610DE1491026C1E9D5132 +:100E2000D656B74141B9F34DCA6926E14BCA100FF6 +:100E30000B60F1EAF04247B402FE62667062D811BC +:100E4000EDDD12B7D34002CAD30435D6AC23143E2D +:100E5000D5D8E54491EC0663851BC54AA7FCC1AE15 +:100E6000BE9472ED2B982C1B00AB2A3BAE7640272C +:100E7000E9D03F451D26E3ACA7316AD570693E979E +:100E80008CDE8937D3DEE1A3257B337534A8163396 +:100E90003B552F896E328312CE74ADE204ED2F3EA6 +:100EA000A06E9EBB5360AEBC898025F04B77478F08 +:100EB0003E50818D85925FB2C7B1EBCAE37DC342DC +:100EC000E32A006F64D5A1B996630C41A3612F7D1D +:100ED00019CBBFE3E5A71AC2E9E50D43ACD3C0B017 +:100EE000282C8CF42D4D08B7B4DDC4BD389F78BDD7 +:100EF000160D51BA4DEECC51FBBC08639649BA9120 +:100F0000664E4514E8EDED975437E16A57DD75CA32 +:100F10005AA504248333C51782A10E284AA84EA9D6 +:100F2000055CE3E4EF521FAD96AA4BE624AC50B744 +:100F300058AAC08DB22DA0E112D9C22D110B948FE9 +:100F4000E2000CE9DC2BA3ADE01421CC1F3887EBC9 +:100F500088A025B70AC143F1450898E29FEC53C227 +:100F6000AF64CBA51EFCC50A748FEA7672ABD8B607 +:100F7000D7A6E15A356104E98C1578B99F0C94E342 +:100F8000F46D86058CEF5A8B225B5F8B354F89DDC4 +:100F9000A04EA27AB804414909A99C11162336E54E +:100FA000C31691133C99CB7B5FEDEB57E90B706156 +:100FB000A5A0A6643066F08FBF72BF86C59F3D01B5 +:100FC00012BB0491A30344089FE99B6F81F3583A35 +:100FD000BA9BE31E5E9A89307DDBED0E6691CF44AD +:100FE000842B500A462422388083A7697D5B892B95 +:100FF00066E307FD6B0C5DF08B26A182F47C2590E7 +:10100000435AECD5AF67E727B172BB1D50F4AD79F9 +:10101000FE7AD251154A9CB1CDF01336FDB92804A1 +:1010200087D8EB19926BE52626E0BD7D4043481733 +:1010300059A7AEB9F356D73D6CABB37DC7886D17D2 +:1010400015FCF87CEF14403265361CB8BBE1CFF4D8 +:1010500089369EC93F7BD9FC6796C75908D2267C42 +:10106000D94E58084F13B30E47A0E28B34D22FADA0 +:1010700082EAF9551B689BD8333221D757A9A61CA1 +:10108000C2F9E57D14FE791FD95A6882DF2896D906 +:101090006A2F99FAF8102AF6E4223913C2D1E384B0 +:1010A0007A648170EF39A0D6DF0D2C4B3468874B02 +:1010B0005E0D944F81C4046764933A1761FB71B865 +:1010C000FCD5964B36AFFABCF251B5755A4659FC71 +:1010D000995AE41AE751AABBEBB7F2381EA6A6EF5D +:1010E00038182EA0CEFFCBF9D0DCD589EEAD603616 +:1010F00077A7F265E10E1AAF743524B08B880D1B0B +:101100002D5D95735D23591EAEA7D117CBC73CE06B +:10111000CFF5578C765CD74CFF2FDA105F12C40BDB +:10112000F7B9DB2556831A4DFBA8975266F3AC310D +:1011300064C2DD8F1F9FD40D190A65FE44CAED1AE3 +:101140009DB2AC9090C204FFCE79A5582D398598F8 +:10115000C2F77A4B8DC7DF90D8F99DAAA5C8668AD9 +:1011600081E46B091E28C1CFA2B7113E55B9F548DD +:101170002ED750ADC6D774BC2DCE9F94288F1F514B +:1011800026E9BE5435373D7B818F2D0FFC8039E237 +:1011900042EB40A81F482C6B4677040F96D8489125 +:1011A000F6F0C3F21F7B5093480F1C134FC72A273A +:1011B000731D5AA334CA554541D4977CACEA96397D +:1011C00048CCDF2BA43CAB7F298DD334B98A4F9315 +:1011D00012BD32DAEA8FC9ED8156ADCC52BCD53A98 +:1011E00081EB4981656FEF8DC37E55FE1BFF5E333A +:1011F000B559CBE78A6DB1E802DB5DE2C300D1EA05 +:1012000038D7FA03142F76E6152E14A6FCD119133D +:10121000DFF81E97F875C699A7ACC6CAEB9628C822 +:10122000D8F9DEBC8A94EF8E84D8E642531AD6A150 +:10123000DE0C1E2900DF2769848BFF51B2ED2E7270 +:10124000F74F0EAFE1A9BE3EEBBF18C09AAA28C661 +:1012500053F8C594DD389BF25788DEBA61DED03989 +:10126000CC152C28F261991444C35C5B9C8BBFAAFB +:10127000918A71E4A9BC3976465F689A0DDE8E24A6 +:10128000BCCDB4E76B2C47FF925FAFC97A473B8474 +:1012900074381A017E87AD7E1162ABBD13CA5F8EB2 +:1012A0009FE263960A459F40DCEBC6E6C4C18B1CF7 +:1012B0007A208A931A954373F1D81CF05134987FA1 +:1012C0009704C435A05F0A97E4F10F8AE44CF42236 +:1012D0007E3A78DAA85ADD109686CB751275FD40F5 +:1012E00008C649E02E5F086C6626A1C887D337C7B9 +:1012F00018335462DA4F5EEEBE55745DCEEB6DEC82 +:10130000CCD7C59C5ED9B5EB5C2CC2146A5005A144 +:1013100076CF532B5EDC5305DB542F7BBBDFA41051 +:10132000C1A3D83C8A2DA1B109B479C1DDEFF7F989 +:10133000B09FED4DAB7AB31CC19AA9E2D52246FF0E +:10134000AA9356CE687BA0C106BF146642ABE913D0 +:1013500053D9E0F37E8DD9B62680A8C2672237DE46 +:101360009C9B135FB2DDF63AD47B65CB4D7AD0B44B +:101370008D9E413DC1CB8AA1AF8A693C35CCCC6200 +:10138000A146B18BA4593F0F6EB119630554FE6994 +:10139000A9050ADD3DD4937016E35ABFE0CA92B79F +:1013A000E3D3C935A84AC9D6CF6066F45E8E8B9E5A +:1013B0009AB998B05FADDEB4FF42C07E939882DCEC +:1013C00059BA1D239B5DE718C0D5A9486BFE54167A +:1013D000EA28B0BD2539321A2DD9C3BC20A6B99E42 +:1013E000EFDA9E48F5A7BF8CCD3F566820B0995FD5 +:1013F000F7C8667434153A04A867F0500AD3428CD3 +:10140000F5B7FB28314BCE319A40B118CE2F7991E8 +:1014100034EA4DB2997C09BA0810E1AFDB70CCF325 +:10142000A532ADDB8452A8199FFCB7830CDBD144F5 +:10143000812AFC5F578A71852A5431FE6152856C7E +:1014400053ACD424971F6443D2923CF37470C7F119 +:1014500086856CE44D39876466A713B4113344E57F +:101460009A6496F16D5148CBC7B7B80F8E15E9ACA9 +:101470003898429FF80023AEB25BC6FC3E808C5386 +:10148000E1453801D0BC1F302669A4DCCD6475412C +:10149000E2FA6E68B40339E9C010FD87746A629994 +:1014A000C3FEFDF4ECD5B301130B7E2A4813188E4E +:1014B0001438587D941F35DC96FAB19ADD0B721DF5 +:1014C000242A9D532D2C464715B74FE6084CF91E8C +:1014D000FD01455E3E048C80EBBD478A3350A3AAD4 +:1014E0009C9FE4AE5A2913175552B6705E98490175 +:1014F0005D00A6FE0E341A66217A9A42C8A3FB63E9 +:10150000DEF4B419E3B9B1F6846BF33BA9ECECB8A3 +:101510001BADE53410399DA59EDCE21B30EDE3F8F0 +:101520000CF18AF9FB715FBA9A811C2122DDD26924 +:101530003879CE02AA03367984E01000489BD8900F +:1015400068FDD6094D265812D8FFC6D65744B1D4E7 +:10155000DEFB014FE99D1F4A1E78DC281397B094EB +:101560005BFCD56F46F850948CC95181A64315D7C2 +:10157000D9C7F4C49243510E27FE4B46C8B96EA694 +:10158000FA0D09AF6111A139D9C913629B5893F9BA +:10159000E32FCDECA19EE66110C5EE0011E322F52C +:1015A0001BD297FB52BAB4244058F9FDF9C54856EE +:1015B000A9B579F1D11B366A6CA733D8C3C94CDC05 +:1015C0004590CE37624AC02BF0367CA2E97E1E5D84 +:1015D00007FB0027335E442E03C3FE7D32CE712409 +:1015E000198A38E14B8187BD1976A0DD79C63C8127 +:1015F0006C6A24C655D20CD5A4780E493091ECEB18 +:101600006CFC7E61A18220F343F74B1D75D57B34C2 +:1016100062A008459F599E000B54154E4A8ED06912 +:10162000C40AF6A1B5351D31A33BE08CD86845D17D +:10163000EEF86E524F7E860712522426BDE81D0D2D +:10164000B7501E0DD73E27D28A82E0494A7D1AE65E +:10165000BC49AAC0DF46063ACD144751636DBB08AA +:101660000914A6EE22CED35EAA17187B60354B82F2 +:10167000322673827E944EA7B8BDCDBCAAC714B4DF +:101680000B3F7707C3ED05D9D644D74C2F6E697A47 +:10169000EEF478B06D783060E67C1F3B983E63884E +:1016A0004278C4EA7EBE922B7049C0FBFAF9D37926 +:1016B0001D72C37D2ECF53A752A6E671E94E95B990 +:1016C000D04C4CAA8305D053053C4E03448762C1DD +:1016D000FC4DF884B788DB94A897A8E268DC2EA2BA +:1016E0005D6717E87157BC80BCCB6FF1F1BB530845 +:1016F0006F8C449D59FDD0D7670FB7C442943B010E +:10170000E97EA6B04BF9615F543BC89C381A451F6F +:10171000B8D90FC7F3F7B0B963C6D0806689C2BA2B +:10172000094A00D95CED22CCB913AD0D76F4AC7842 +:1017300055286D0A5A92380DD0A9AE445BEAE8DF0D +:10174000BF82A31A42482B2114C3C4B89627AAE328 +:10175000CA56B55FFE1B982C2E5E43E2A5A625D681 +:101760003027AB915411AACAA4E45C8C4A1E3C23D6 +:10177000B8CF016162359916610A21AADDC884805B +:101780006CBAE06F02A4D2C251C0D3B737FC34D1D7 +:101790002805DF7539247E1FC8CB78745BF66A098B +:1017A00074318835D3B0D23424FD738A54AED7D483 +:1017B000326B1E36D5F17DE015B9A9408641D31EA6 +:1017C000A88316165D97F339F45338441E7124F03C +:1017D0008FEA5680C1AF6BC0C81C99D7E6650A2F47 +:1017E000C08235BFD76A15AFA0D314EF511F70EF79 +:1017F00035938E89453653B9861C6BA182CE69E537 +:101800006799422902CE861C06E0F814633CC5970E +:101810006087EDE262ADCBFC3ACA29358A1BAF96F0 +:101820005262B524B2487CA1DE2A1720D4FC17E608 +:101830000CB968C54A4E0638C9B3C30FA828A2B16F +:1018400014B60B1B3952FDEC350FC694A712F9F0F4 +:101850007E8DE4E14A8EB73DD32EC71350A641F1E9 +:10186000B8617F7B756FBE9221075EB8E66BD4AA24 +:10187000E1E7F6BAFF0CB5AB7A8470BDF1DDBB844D +:1018800096969FE881102869C357B862FB395EC3FA +:10189000FB0A647E1353F0E8AEC2389EBE73AD02FD +:1018A000E0C0FAB39151601BF8359D7201C25DFF33 +:1018B000B6BBB26433D7749C650EEC8BCE739AC6FC +:1018C0000E4A6EB8C61952AA4EB151D11C9CC3A67D +:1018D000283039DF4729534295D1BEBC94E63DDA22 +:1018E000502CD812621BAE4C91FBC9C22FABF7E74C +:1018F0002FF33036C63C960215095FE6D2E9CEE4F6 +:10190000DFE8903562151B40DF213C24B8BED2E8E9 +:10191000ADEBA8956866EF3E106C15ED48B4E27526 +:1019200037B3925E7C9423DD6650190F72D0089C09 +:1019300087F7A4AC8A8D98EAC348AA32BA5477E0F4 +:101940002D68A8AF9E56F9F22FBF5744CA819D5A01 +:101950008A36D1DD8F00CC5BCAE587408BD0884FBB +:1019600004A7D86A2A414D3473B75A94418C225C3B +:10197000ACB05F1CEE4F6D32E201DD7A37E3758665 +:101980009BDF9374B92A368510A0AC39733AFC9367 +:10199000DC57313BB708DDFC5D80A2916D5EBF4333 +:1019A000B1577A758C1ACF1EC14152E2695746CBA6 +:1019B0006EF7E42F68C975E7645BE616B121030F83 +:1019C000D1C0A311D508D8B7A1DC044B12A54AD4C5 +:1019D0006B775B9DA08B7E25A2D0A6D6A5370096FF +:1019E0000A3A7E5085A4F913EE4E903CEF943B0AE0 +:1019F000BF2CC7DDAB0D413FA20927691115D9489E +:101A000032BD657CB53EE505D24C8A2EBB2AB08F2F +:101A1000AA9330AE7D11506C7F3AAA84F4D9CA2BB8 +:101A200007990E4AD6690460A13F177E6776B4BF56 +:101A3000546E214E59C53C7CF483ACB396D7969630 +:101A400066DC533BC798665EF42BD201FB919593FD +:101A5000FBBF0B8D30DC365C00D5669757290466DA +:101A6000BB0BB6A6DCBE46B1629C25F23A31995D4D +:101A70008425585F760729E8AD0F75EEB088CC4C09 +:101A8000BB900FE49DE67F4216159FE02ACD67E3E9 +:101A900039C837FBD8CBFADF1F35F81CD549CC78CD +:101AA0009DF08C35940520CE3C424260CE470853D1 +:101AB0007C5157875BB153289C88C3BF92713F7F8D +:101AC0001D5490A3BEF5749E0AB50C3C119662FF9E +:101AD0003B46BBB2F6D12B67764E8380A7EF0698C4 +:101AE0002940298DC7B7AA5CB2AA190624969B1172 +:101AF000BE468B32400E252B05C98D26BEADF7D4D0 +:101B0000773F9E842FA0711B98885A05299C4DC64B +:101B100067E8E04511EEF9DBA49645E133DD21BA33 +:101B2000F8789E73BCC00A7339504A22C286695A3B +:101B300088728964C273CBE2383D39CEF5CD51FD50 +:101B4000AD6DFCF8A99BB4A488914A8E2279D19BF3 +:101B5000FD2D1DF97588414FA5CB9F5C273FE00FF8 +:101B600079888B8479B75CAEF64918984A0CC42EF4 +:101B700057BDC824C8DC81DF42E4FDBEBEDB600F78 +:101B8000E7E6D0FB46EB8AB9428866C2A07B9C8D13 +:101B900084E7E3DE8BB267D6050603F3C1DC3B5B6B +:101BA0003C627471BE81A1946DD192B6800FFDDE4E +:101BB000987B66807E768791A53D3CF90F1EBABF63 +:101BC000BFAFC20C9A9547D0DA5D5E4895E698FDA6 +:101BD000CDF9E7113537A6F573EFBAB02296453641 +:101BE000FD293F5F149A0637C90946D643CCB01782 +:101BF0009AE01753667DE516AC878E84C505165BA3 +:101C0000CF11C924A6F4128D593F85A8CED0264302 +:101C1000ABB91976A63D7A777BF65F204A1075EB53 +:101C2000495C382C56C152887196DBB2D8928DD25D +:101C3000EDE5BF292004A15D00AE68B76BCC216B38 +:101C400070A1F8763D3D70DCA790D4FB7AB971485D +:101C5000E76D86A831D940D370943BC130AC68A8F9 +:101C600049CA3492C6DABB87C67FF597279DCDC196 +:101C7000E1335A8A644E050D5EB6C5628A0A682948 +:101C80008A68D69813AC1BD7222C1B3F2A93E342B9 +:101C9000281B111D0C16C8627E4770B25E53D5C753 +:101CA000321262D1AAA2805A1E16B548832F8E6BBB +:101CB000C3C6C932D065DA133A44C02B3E6A208DC0 +:101CC000F75B662ACED85A0375C860B6240CCB2AB7 +:101CD000C70FB277BB642D32AFFA515E6BE98381D7 +:101CE0004F211B5F5F32682ADCB472D09F5CFF9E7D +:101CF000687A69DB87395A42F034116D6BEAF383F5 +:101D0000147321B040E44B3E2C72B09E28EE8A92B0 +:101D10002996DFE47C042B6EBDC4285C39C883C7D8 +:101D20001565CDE4FC6837B462A9E55F9963A51633 +:101D30001FFEADEDC9C2213BBB176801706B3E248D +:101D4000F2A2101C65723F04161E4E73842EE1C56C +:101D5000E0C5AD1AF44B69DD80B6DE3D0FBC774EB1 +:101D6000DE05F8412BE7DFE2A4E80E16E9FA3C7E37 +:101D70003ED5BAC5FEDC7BBF6D75E3D598C44B601C +:101D8000EFC83C870DD17ADDA2DE53798C60B7D4E1 +:101D9000307CB0C8916503FD8E7B8303D2D6AECB79 +:101DA00099D8D757A6D9259B23A6C65EB027985A9F +:101DB0007CCA796AA0A124DA3B5B825568515EFD3A +:101DC0003A7C89B7B8800FA7A1B2432A99D542F2CD +:101DD0005931772ADE039F0615F17727D69EDA035D +:101DE000B5A597C3DEA4316C249E28CFEE00AFA327 +:101DF000655EF4FC4C262D780C8843CF97D7A1481C +:101E0000A36DC805C3611A3E6B7A74BE5E5570EB54 +:101E1000B71171A7B6904D775A058952B28A5C1FE7 +:101E200006E71F618E1ABC6860FD2B887C16EE3CAD +:101E300076E6B9AC86370C85B4829F43E79042BF03 +:101E400056B79323808E33EA01E33888C1FBB96C1F +:101E5000D3FDB755F5019421F75EBA9E5F936927CC +:101E60009C89B8466E815AA00B6696C264BBFEC2BE +:101E7000847F9875C96D06D60165049FF1B75E5ED3 +:101E8000C262DCE2C3BFB87019404F730759B8791A +:101E90002BF78D988AB265FAAE98B57077436C8A45 +:101EA000FB3A668EF539129D83D5E9906136D11AD9 +:101EB000741ADD4167DE8ADD2B7EB66C2185FF1644 +:101EC000546A91E0C4C8973162BCBCBD88B3306C21 +:101ED00071ADB19922522006A0FD70AA9FE410981E +:101EE000A0E91634E7A5C15BB0316F477806C9B6E3 +:101EF000ADCCF0BD23C4082F763E40BD5CF0FF1B87 +:101F0000B970367C1096C32C3A7D0722E45AA27A27 +:101F1000394054971FEDBE321CDB78B30F36F56F96 +:101F20003ECA195FE2FF1C9CD776CEA927395EAB6B +:101F300091A10862DBEA49FD5A94A58F845F0A04E7 +:101F4000A43C5454D60CFA17C71AAD3B8CD341327B +:101F5000A74393A5E3CD449089D9B15FA013EFCBFC +:101F600001FA133DE8FCC1F192A0BFB2601B0AB1B7 +:101F7000C5434D52D09F302682E03D2C3CF68FA5C4 +:101F800047AC45A3C05F09763B7B4AF0A39ACF30AC +:101F90001F469EDB57F3DCDE2026385C63F81EC844 +:101FA0005234FE169017925FEB2B15CD6A99AE0254 +:101FB00014C4215B5AC39476E9CAE830449ED966BA +:101FC000F1898244A90A46AD57EB7BE1ED24F1B3D8 +:101FD0001989299781F0471370BF9D03355189E115 +:101FE00078AC2E8E35A1E59A55DAFD92FAFC629016 +:101FF000151A8B27A7C2049AEAE01DDE3E734F37FD +:10200000163C97F637FDBDF0C016B1B09857FFD219 +:102010007F2B01FD7B5DC66D85D056F48760DF5058 +:102020009F26F057CC9408B4ED178D58EAFA8C9699 +:10203000E086FC2D09244B64A12CCC393192D0D6FA +:10204000BCA598C301133E6A595F9BF242BA6DAEBC +:10205000AA90C2EA5CD9C03DB92FB81D90F5FAFF2D +:102060006853C3B8BFA1D13929A7768B31EE0A7B5B +:10207000DEBB86F078354702A3851F0DF6A2B608B1 +:10208000726522C03AA16606F3E6A9FCCCE13117DD +:102090007C4101073044F86B871E0390F4AD4CACD3 +:1020A000771295F5715C7AEACAA8CF8E3153E5F4C0 +:1020B0006578606B246A3A5522D90165ED3938AEEE +:1020C000E57103C6ACFB3E87107B3B526706B470DC +:1020D0009EAC9909002B4E6FB6905F8042296DC669 +:1020E000574D8AFFBE657BAB4B61600144794D7CE7 +:1020F000CA9F50BED3AA03BFC03FAE9EA14120B02D +:102100002324AFE49F0811FBCAFDDB402F1C903550 +:10211000D4E9F50BED4328968F9765F26DE8083505 +:102120001F20A0CB7F18CC7209D5B09188EFB6BC28 +:102130007586C9E656B616585C6965743DCB68AEBF +:102140003C07E485050D1A94737F3D21DD300C3A80 +:10215000C6231340C9F3C06F0299845C3866976543 +:10216000C83FB6025C2E4B1228B1A52E59588301E8 +:102170005B208FC809D45EB9945C14124A1DA67105 +:10218000FDCE59ECB33E71EE0A9BB466C7F31F89CE +:10219000C9335BDD658D4207060944F95559CCF911 +:1021A000A82AF735585C55EEBB80E9393F7E7BE3C2 +:1021B0009059B2C6A95BD1E75D2D2C0845D0BCD69D +:1021C000F85C9993E54D94C9F4ABCF4F6E48115F1D +:1021D00088AE388FFEA08E2949322E84CCF0AAF129 +:1021E0002F79882DBB633EC48F797F068BD3C53F83 +:1021F000259538747B7E6A2A30D4D028956E850068 +:102200006DDA686BBB02F08E52771968F0B121A4C9 +:10221000F965675B46E40B30FF3114E7F45510A510 +:10222000073FE0AEE45E0D24004C512B5BECAFE7C2 +:102230004CBFE2C06FD64CAE8B767894D48D2546D9 +:102240000AF7B122C1E38657C659F42FD0CFE9432C +:10225000E4DAA837CBA7BC7FFCEB1290591AF64DF5 +:102260004FBC2A2BEDBB62A37D934E8DC1ADF93FD0 +:102270000B08D305B143DBCD6AD7336BBE0863349B +:102280004BD0D5ABADC36C08639C0BD59325F5EE55 +:10229000A3BA291EBCDEE55D0E96BCD8A713D6AC4A +:1022A0009465460B4CE0DE2FC6FBDB4193A9A949A0 +:1022B000C00D5949B3508DBED0F436346015D0608E +:1022C000AC7ED740B6D0A256149BC35F49B28C28CF +:1022D00061425DBCFAA614294637CC14CF9AACA251 +:1022E000D05EF4A48AC90E6685811BE306DD939255 +:1022F000315FD93FE68D02C7735FB29840E0CDDD14 +:1023000001A29B604CBFFC49465831C5BCFD0CC8BE +:10231000D38DC94166A13AEDFE9C3BF9F667D31D0A +:10232000DA9AA355061F799610E86340C4887E05A3 +:10233000D956288EBCD6BA5EB07B2E155933DD7ABD +:102340002386D6D5AA99664A24A2B86CD547E96BEC +:102350006A278D07FE30A9D6A85FE4388BBA9D1F87 +:1023600036EB1F9A81AA2248B2655DD1EF9F293DC5 +:10237000D09D00564247BCDAC26C027FD97B2D4902 +:1023800062ABFEFAF56E49B641705FFF196FCD6D15 +:10239000A818235345EBEC894354F71D2FC7B36BA3 +:1023A000B9A78D86070130DB712A029B948F4B28D9 +:1023B0007BF304547CA12B3E0104E011E70F6F86F0 +:1023C000E22DC33E2DD3284D07E9B2A6AB72DE63E2 +:1023D00064FE3FDF18DFDF7BB92DB845CD62A6CEA6 +:1023E000E2281862912992DE28BF81BCB29794C579 +:1023F000490ECE7CCEE9AE4FC594B916033F3801E5 +:102400002932EBAFF39E9E87A53BEAADDBF695E85C +:10241000A5EE79CF991DF6544D8593300F357FA7E2 +:102420004F941CE489A5C92C0EF08D90057ABC93BD +:102430007EB9408B3AF1E95399DBB22BF7E6C658E7 +:102440006C7275B6B482A4BA907CB03E6B99734737 +:1024500098F0C83E9C4A33E0FCA8CB8E28A9EBED4F +:1024600056CCD9057A3F50C37C404A00B49D8A4877 +:10247000872D1B9F83C676461A31856757610D6E7F +:1024800066779B2490DB09F22C3DF0970211C99BE3 +:10249000A85D09FF14813C98559A2396DB73ACC85C +:1024A0002FD59B4ED4F200567EA4C7CF1D2858CC02 +:1024B00072A6475A78477D661ECB13DF22C374A8E5 +:1024C00014ABB0B785BC09EF4C07AE83E14F5F2D6D +:1024D00025B56535A21DCDA9C9DBCD13CB31B62DF0 +:1024E000B39EA9B85912C0AB00CBD99DFB0A1F02FD +:1024F000CB1AE48EDCB59A51C6FE003E968A77CBA5 +:10250000464FF86F3C50C686865BFBE47FE5F905D5 +:10251000FAF339607ECC74191C9856220D655D273C +:10252000DB82D7095F078AB6F31D3B34F6BA04791C +:10253000DF297FD7106883A410FB377556495BB33A +:102540001EE749B73AB7FE07CE57DB8EA38B9381C0 +:102550003DEAA4EE8C3C8FE6A9624F6E97C5D34B43 +:10256000D60C00A12ADF2F857AE5A87593AD532FED +:10257000AE57D672FE029A7CD15A5B9E33BA5D4D3D +:102580005A1AD9EB43BF6D9F353685448031EEAD85 +:102590005E12BB7423AE942A99E8E5B57EB1187239 +:1025A00016DB6818FA443B2408CC086A6F0C9C9828 +:1025B00013C0B77FE0DBE59EFA3B287C5875214AC3 +:1025C00009F1D64B6639697AD16615F0221B6C6B1E +:1025D000D886AF72415FA222C55AD1828BC128AB87 +:1025E000CF5AF6BC0DFEAA8C345C48C52D08604756 +:1025F0008CE27CD593E72121DC16DBC74A1ADB2964 +:1026000091856E99EFBA30E31215C798803349E08F +:10261000179EAD02C2EA93F630B9E7FD802A815CCD +:10262000E8C4D581F955C179D27C73F1100DC5B2DA +:102630008859913F42E7395ED73665C194C6C9CC07 +:10264000CCF1CFB4D07D75B0607EB65D08C4E6979E +:10265000FBAA81901A613B64EDE1F083876A26C88A +:10266000FF40C0697871EFF2DE0FE1B97B67258C1E +:1026700093927C23A791D77B42201E8C3591FDA796 +:1026800077EA3F8FCA4437D38415437BE0D3AAB19E +:102690000D49D60433A6D350C3382760034B19C65F +:1026A00077FE3D173AB2C4F9EC847856EE777F3E58 +:1026B000DCEA589AB9E5D543A89F85FC49B0ED28D6 +:1026C000BAD6D1FFA0D89C0C4C94351F6BB98EB1F3 +:1026D00078EA685CF192C75E82DC6B77590AF8D7BA +:1026E00008864CC3A6C99CC03A368BBA34D8890632 +:1026F000AFF08940D32F62EE5CC8608BD56CEAC125 +:10270000FF35D221E2336B85CE4572137D0137E868 +:10271000052C4235FABA3AED9DFD50A925C1DEF2ED +:10272000B824B066E80A853F7B4D6153BBEA0B4095 +:10273000A951D1576C68D80A7630E480AD25216262 +:102740002B32B59435307B09E171F63A894AFFC1E5 +:10275000099538724CC7953BC74BB206D333F77314 +:10276000A2DAFF3F5B9F0D5795C08B5FA163A8085E +:10277000C6A91491D597A5B3FCCF674722C8E23408 +:1027800067D030E2054680591C7D56754EE840A062 +:102790009B85C141CCD463BDE5E6578D5F70455341 +:1027A000E431663E59330BAAAE7D56EA103787F501 +:1027B000B38B22EED4C3C6C8747B2140AABDD25BC2 +:1027C000C391BB73D27FE0CB7D996489FC0ABCF0D6 +:1027D000D9D61B97BBF525EE229E2F32871CF7C357 +:1027E000E397C43FFA6667EF7A0C2E97E74755BB2D +:1027F0009BBCEA1D6F97E854882591866786A3B82D +:10280000BEB497BB55007EC9499DD07DD0A4791A2E +:10281000256C178CCBA10DBB95BC00B5B96DF30B26 +:10282000CF819732C75493ACD2C2A2DC533D113B47 +:10283000D629506E9F2D788B311FAE3044C0F9E100 +:1028400012280F143978993942E1F89BBD5B710B5E +:1028500096B5B7EC148C59C16EB5BC4CE6D5CF5CBF +:10286000FA5B2DF0D567D470D86C89FFDC63569184 +:1028700052F3C0C94E0821757C3C901C5319CBBB48 +:10288000C60E11718ADED2BCD315318CAF90EF87A2 +:10289000F4FBBB999B4451CDD770D02889A1365504 +:1028A00082DD6B5749F82B9C8D9863E8AE9F4C2BCB +:1028B000CA3CC4F17C0E313B09D1B4B89BB166333C +:1028C00070683FBBB2045CF9C4670FE20DAF20C46F +:1028D000DCA5E81F03B5A617DE10F8145EFE3B2E3C +:1028E000699847CD03ED4E86E167F95B8F861AD86C +:1028F000A4BAE117C87C4FF97DC504FDFC804AC924 +:10290000221B7855D0139AE74AD40B7001086E3D0C +:1029100068AD8192E434F3F5783D7A2962D532D4FA +:1029200047F9E72677441D1614094BFED2E085A827 +:10293000D2E4D784ADD26F53538A06094870FD6B39 +:10294000E0B8E6043C544A62C5E80100100FC197A4 +:10295000EF74FB3AB3577450C3F8CF94202F2B1366 +:1029600078652250BFCCE95C29AA1AF75D5C8A45DC +:1029700054E0774116438F62738C165C248C3FFCC5 +:102980006A9EA3713643B912E5F1734DC7B6400C88 +:10299000E474C4ACA03E089A78FCCB444BFA3F7E6A +:1029A000EAF3B86EFF31AAB076103F7BE972A04718 +:1029B0002B7A609BFCE617F818A773C925BE853DE6 +:1029C0005D910AEF528FD743A206AF76436A95997D +:1029D00096A35A534B4CF19C25E6329635678F01EE +:1029E0001B6A335389CAA90D40634E299DAF1DF858 +:1029F000931EF697D369AC1354963C17329AFAC4D7 +:102A000046F65DDCDEF73B516557B908F751B22E4B +:102A1000EF567BA8AC6F64E95EF4ED4384549F9657 +:102A20004BCFCE7C0F0000D80C1A4E081C9EC33D25 +:102A30006276822A0F08CD1C61866F6D93F12FF8A4 +:102A40005042A601915AEA492DBCBA08880890D78D +:102A500006BED2F9BC3B65F0F9E9099710DE6F5C60 +:102A6000FF7D47D8672C9B468824369F9F72F87558 +:102A70002FEE51A125CFB03683265CC6B07CC0CFE7 +:102A80003C700521591D8A5D702E915A700D543885 +:102A90008D6FD83795F0886D163201B63691C9F42E +:102AA000C4DA454E9FD872EB055FE815BEC7EB4A06 +:102AB000B166A0444BFECDDDD4EF7E584DE2061C3E +:102AC00067F8873DCDC4B22A57BD65A69856C7D9C9 +:102AD000AE241DEFE6F706B8E1D654E53D99732321 +:102AE000F6D22DA65D2F33759C0B8A0854E1AEAA51 +:102AF00055F45236B62075E4B40DCF235061FAAACE +:102B000025E93604C70A5D7B5C81058F9910AE29E3 +:102B1000AED0A7DDE63BE7787EDDD102BA885E85E0 +:102B20001C27F3B35E4F6F49741FE83EA798A47B40 +:102B3000F5747236EBE92C9D544F281AB0EFAA9227 +:102B4000D8B148BFE43FD5CAB44CF952B57A0B8C22 +:102B5000F6EA6566A0F7DA6B551586C310263ABA11 +:102B6000F465EEFFD789CA74A309F7BA6339618C9B +:102B70009497798E20CC454E5B6F9F8225F3327FF0 +:102B8000F5DFFA1E102B88B8C7D60F198E97DFF71E +:102B90003D7A4840230B98F07B96BDA1D1611CF390 +:102BA0002DB9FF25BA8B975F9A6018C46D6CB75822 +:102BB000E11E8C7B07EF12225026F3B2711B3CAD55 +:102BC00062C54E5CE188DC510D1B414B1C0C405D25 +:102BD0008BFA5896E78623D87C30298AF3B50A5FAA +:102BE000C6611689D2E702D32A63F44982BE75040E +:102BF00000C71036832F874D4AEEFD55E2843A7C9C +:102C0000646F09A7144F7D4E2C91F662A2DE4C0A28 +:102C10001C07691F359D3FA4BEC5CF1B74A19E94A0 +:102C200051D43CFCD1FAE491F419D41CB242A2C5AF +:102C30005608152BD1821D41676C173AE0D2341F1C +:102C4000EB5B7687B2429118D5F4280636BC6CBE91 +:102C500071CD4F65FAEE9B3914E3DD229E3AE1E334 +:102C6000028236D8C7D1274EAEE27A696F3554A2B8 +:102C70003F210C7961FADFE0F31B8A6D4DD902B078 +:102C80006ED4E6A3AAEB8932220DA8C11A3DBE601C +:102C90005520D0FC95D0C63E74FEA469AC16FBC589 +:102CA0007D380E2D22A7C9342303D38C5C9041BDFF +:102CB000813C28FFE64CE9852B43A81C790D06973B +:102CC000E60FDDC5BBBA8C67863D9174FCDE6FE212 +:102CD000D2BD1653412C809E9CBCD04A51C97EFB6C +:102CE00069D869AAA1D8D98F8696EABEC0DAF1055B +:102CF00087130451544E8E3F0C5D4E5D730ECFEA28 +:102D000056A2DC81340CADA93A28741C0E634276BD +:102D1000E7567804F90CD2059BD0F52966EE60538E +:102D200020DF28BB0F56E2533BAD1CF9516568EB21 +:102D3000D88D490DBB1EF1DDDF28041D84CA7D44FA +:102D4000B75791F08D07870CEE28AAF3BAAFDA0BCC +:102D5000D108552E4AD0B55529E2D510A7A51E1683 +:102D6000D734FBFB9A3943BE972EF9CDE9D01EA18B +:102D7000FB76AAB8F17FD64DDE000EA79602276635 +:102D800013CE1895014BCF1700E59CEDAC7780BEB4 +:102D900058C322BBB16BE9759612330CD773359FBC +:102DA000D1D6B708C03F2736D9CAE302CDF2754B5A +:102DB000974978D3E8DB1D44C621AC998103C43020 +:102DC00082BCB80A84ABA36874E57E0AA9C070CE41 +:102DD0008265B539EF436C991AB770B459847F573F +:102DE000F420C26998B63295C5FE90872388A1C4A5 +:102DF0002E6BC36B142E40118C92455DF113A50709 +:102E000059F7364C1D41C47F79B31088CC0AA91BF1 +:102E100052DA83B67DEFC3A554C8EC4DC9EE32DF5C +:102E2000843F5FC63780E210D12C4321BB6694FFFC +:102E300047B1C007CFFB4CE3866DB98B2A6130D513 +:102E40004480E81E6A572F38F199A1A2140B1493FD +:102E500079C8945FAD659362A1C879A308B8C72605 +:102E60001DEC0BE80DAA49911F45EF5EE3A36F89A6 +:102E70001FEAD0B31ECFD1917D9697F0FC7CD30191 +:102E8000CE37C3564745751DAC2B02FB8AD490DD67 +:102E9000A8CF3385F888A2C72F42124E6AA7CBC9A4 +:102EA000E21720F303063E434DFE1DB210C14AD97E +:102EB000E58C1B37A46CCC4EF5F0566B024570ECDC +:102EC000CB367EF455779304F5D6E2F7F9248E736A +:102ED0003E6C819D720EE79257C42449975609B201 +:102EE0005B14D87725BF595CB7504299A18AB65870 +:102EF000B957B3DAB9464FD84B7F412CB4BB2390B6 +:102F0000396A9C25F895C0BEA56B8821857D1FDC9C +:102F1000DD63B96C4EC8A4732D432FA359B1CFAB59 +:102F20003493C6AB7C4B439CCC5C9322706507AC5E +:102F300072CA1875ED50AB12B63FE75BFD4976A437 +:102F4000C28584C4C4690E672DC8EB931C90997E1A +:102F5000FEC2B8D3F708359875F5422D672D749ADF +:102F60009DA6655D6C58E65284A40BD7AAFF364433 +:102F700027537918A0F698A4E0E419262F3A17E011 +:102F800040B8F691E4EA34CE5113CF9DDB12542BB6 +:102F900092024DC5C4F8979B546787DD2621E7BB95 +:102FA000A963E2ED9664B12AF3A9788E2CA863EAAE +:102FB000EE96A7BD46FEBCE34FCE9D71A0FBC94B6C +:102FC000B054C05514438645B5C655F94A3B184E12 +:102FD00029EEF1376CA3DBCEEAF9D0489B26BE611F +:102FE00061FE2584652C8EC21F9C4F86320509F137 +:102FF0009C0AF6998700A014671457C38AD8D9E1B0 +:103000001320EDE031BD844F0AB7F51CB406181447 +:103010001E733B4AF19F08D0E300188F3FE4980CE1 +:1030200025335DBCE45C43A311230DBCB06DEFF20E +:1030300066811735AB0CCA0D8F054C78E0B70A9343 +:103040000BC6008163468F9B8F6FF5B68E9902E8A1 +:1030500022BDE66E267D12ADC06559932765C1A3DA +:10306000D801FDA0EFC87FBA3DEBDD883B1CD1EE57 +:10307000FF89B861009D058EEEC5929CADDBF62AF6 +:1030800098627E736DCED9828A4B040CEB70C44B70 +:1030900090DE255BE7113F502989D3B9B70058EE80 +:1030A000440EEB93F4E561AA1F0F2BF9C4974E551C +:1030B000BB0C171CBCD540BEA82FA1476B56EF21F7 +:1030C00016869FC61B796AC696B9B5E16B15B034F2 +:1030D000D82FACEE9CBA252EF5BF2E9E0A291CBE19 +:1030E00046C8F35AF5038B6DCA75EB03CC20793FC4 +:1030F000B55BD28D1794A673600F900B93A9A5D5DD +:10310000111FD403A6F52059B20612E91C67F48AF0 +:10311000F1B150CC4ABAD02DC49EAE6265270723C8 +:1031200082150B82A3A937166760A3B5BB5A67DB6C +:10313000375B8EEB195E9418946CC2B2BEE9F9CE7F +:10314000ADE335C41487943E5EA2580E11C8252302 +:10315000C806EE7EB381A660C3F3A96FA59210CC1A +:103160009E7C43F16476186F59000C9D7D4505BD2A +:10317000AD4931F529C55E98BEC8E06FD3B147505F +:10318000D5F254F7595CC56AE17750B7D62C02D313 +:103190001983A582C96360F7BDF4959A6E2D233615 +:1031A000BB5231C7320BE2D5C120AE6A3B715D82A2 +:1031B000A9C3766C761E09A50816AF821DD6CF224C +:1031C000CF52E2E4C050C7EE945A5952E390DF8BDD +:1031D00039A6140B2EE3FF3F5B7FCEA082153BFE8A +:1031E000B8A6FCFF6180C1CAA225877B1D4D4CC6D5 +:1031F0006842B80718B415328EAF6A8EF727D97EA9 +:10320000395760A36825DDB93954116D8164CE99B1 +:10321000EB68DD5CF7B62897CC8D26E1BA7FE77ABC +:103220007718B8E8BAE7995380A5E7FC461E3542FF +:103230007320AE771C159A8F426E4719030B9C774B +:103240008E0F35150A77E3FCA6E99131074809642A +:10325000D1C07FAC4688CF2F068B0B6A4A25712CD4 +:10326000119D5966B3BA6AF62E565BAF171A5EE522 +:1032700039BE2864F76DF7060076944E4DC2FE08FD +:103280008ED74C2F797B5C96F9CEFEDC7ADAE6514C +:10329000E0A95F61D2DB765D1BB4828B3BE9B38D25 +:1032A000FF0E43BD35B87FDE6081E938696A702B57 +:1032B000D64DA7FCA11A3DCB7D7615BCEFD0FEDB29 +:1032C000B2F70EFB89724CF744B3E218179314B5AA +:1032D00004CD3B7D486CD9B1E275A81FFD587551EE +:1032E0007983E033E40B52A6EC48EE8D49694BAC90 +:1032F000ADED8AB0018475E36A0917B6EFD001B865 +:10330000E591B0CC7EB0F37219A6AEE6E5462AC4CC +:10331000A17582FDB4C05A2FF2C43F631CFC38B8BB +:10332000A0AC429705F463157026DCF6B5E3C40B38 +:10333000C0087FC88DB58E2BBFA3C614298310E7A4 +:10334000630BD1862816C71C678BD103DF207E9BB9 +:10335000B8A7C494C3CF15BA1DA5CCAFFCCD62CF1E +:10336000B714B26EC5415848831E4585383D8373F6 +:1033700079611ED2EC60F189EAE93262C1E66B88BC +:10338000C841ED97B43FE00290D08EB15987815F7C +:10339000835123DF7D02E0A5A51F35D2273B0CF822 +:1033A000D285F9415AE068E5F7A7755AC612C08977 +:1033B00062A74CA628A776499507045D7D6A45E774 +:1033C000D17A81616F0C9E9CBA3D61CBC64B507621 +:1033D000C0ABA8C0E09F8F41552800381361A3DA25 +:1033E000A83D0ACFE76ACB89BE3C4B6057695F8D29 +:1033F000635C1EF468F710F345DB2558AB1689B7FC +:103400006F03DE6844101AB3895265AFCB4FD922DF +:10341000219D7A4EDD8F2AD0FDE5CE07B398F10AC3 +:10342000D397D467D7A1B1C14D53508D84F6985B23 +:103430009CDAE67B79AB604C1247A9B0F1F208E662 +:103440005BF62FE18FD2CDEA5630B4DF2BA4F68F96 +:10345000E8BE055CA65BBC6273D0EF0F22E8D3FF29 +:103460008E9985AD787BA43782198E4A442B4920EA +:10347000D17071962F1BFE8A49088743815CC65D17 +:103480009BE938BE29C87B102C04F2F8D956C4BC7D +:10349000BCE58F521AC4A4251DE1ED87C64E898272 +:1034A000591065431E4C8F2146189FDFB9876CEF7A +:1034B00064293D9529A32089D1419101EB9A218569 +:1034C0005D905FDF53B28C48947F11E6A14288D6AD +:1034D0003FDB2D32D14E9B9667C5F026E79CAC7F33 +:1034E000ED0FF9C611E1DB381E4ED3D98FDAE92191 +:1034F000D33FA2309E8EDF1AC208CA264E9A2550AC +:10350000D2C5579AB442C7ADEF1B739491C6F15D13 +:10351000A92E13FC6C8C2813B4B9D99BC5A86ACD0D +:10352000188699D3A4F25775EE5B207964B0050B29 +:103530007CF1DC31FAA92EAC9C3BA2FCDB6B1103C5 +:10354000F280BF89E93993A24F7CBD063BD9ED10CB +:10355000F3657BC5F99B6092F1318D235FD768C518 +:103560006EA71688B2106A713BB40F37C965B0B444 +:103570001F71E6667EB8AE5F83A70084F42B58A85F +:103580007DEFA7E260803D41303A3890071C236808 +:10359000A225D747C0FD00724436E1C4D861C632C7 +:1035A0004BC4BD6BDC45DF1A8D81E45BC17990872C +:1035B000F019168B4DAA401F01A2B43109F76B62B6 +:1035C000F53D485B344657B2F1360DB25EFEF3F579 +:1035D000FB2BD8BF248C0C8A9DE642CC91661C8ABA +:1035E000D8377FD3B125FED3E8959D50AF3625E778 +:1035F00014C9FE8DDA8EF9255BDC461F4D1975590D +:103600003B3F709DF1D83445364C26914630341EF0 +:10361000CB1C3B71772A0E0A7986E1BE5395F8F2EE +:10362000D8C99E057268AFFC3E12FFF8A6689F5C81 +:10363000AD165FC8F78D900D1C46DABD9D892187B8 +:10364000DE396BFBB97DA2F2D3CD62AF8559D58748 +:10365000B5D5762D62276F173417285935EEB23855 +:103660000689D5CD49D3C95F20DBE21808CCA47800 +:1036700088C35BA6EAF9D53096D6B1B0D3B1D732BC +:10368000B08272C138C2F12CEC165CD595991B1F23 +:103690008A49A33127D76FF99C15159809CA76274F +:1036A0006709FFF84293F7E3FACDF86551F100BFDF +:1036B000C0EEB5CF47F9125DA35A4572D810F7B2E4 +:1036C000D3C53B9DB45F8A9A4E3ADE06195AC4B4FC +:1036D000BF2F0D26F416F7509D3C11F34B2C69AE0D +:1036E00051F7E8C38461002EBB93EA217360CE7B5F +:1036F00009F3CF35E2851298CF7F8103DD1EDF32DB +:1037000055916DC69F89EA3BFA790E7E846F478595 +:1037100013CF979BBB79F0A21C6D650506E298B2AA +:103720008B0C48AE9D24284322D1D01EC906D284DA +:10373000D4A42D9005C2DEFC742D5773A40AB635AF +:10374000D425E6E26A7C21D0EC2C0019F4AE38C313 +:10375000F486346047BFDD5AF6AABA6626B9D8CFD8 +:1037600062A141C6E104CC3AC42992011118150A9C +:10377000CEFA98432675E8E3FA8FF84988488B4AD1 +:10378000E393F1FE5A0F08DE3FBCFDE8418E5691EF +:1037900075F0D631C82A0236ADF1558B9BA8937BC4 +:1037A0007D4BFEA21F9C3B7B9C7756DEDB6A07228B +:1037B000057D79B12B52E970C071A41C6DB740B979 +:1037C00021B030A1A1026C219E931AA064F02005C3 +:1037D00041E568672B757AF8B7C832B764427794C9 +:1037E0006D57F0D5D525FB42019DC5598C4CF5E2AE +:1037F000B2C383CBA74FA4D8FD4B322B3B18EDC0EF +:103800009706DABF4D7B24717036A0E65842CDB4DE +:10381000412E9CDBABDE0FBB2BAE796C078C621F9D +:10382000BDF1BA84DAA73F295E2D7EFE8159F2C42C +:103830002A3BA0AD281DFA05B6D4CA418F6961C2E2 +:1038400040050F5F9B763C1F3237B050540350A4A5 +:103850000B70920034115946732001B432661E6E0B +:10386000F24D71427E681EB7AC8525C25EF5938825 +:103870003FE60CFFE3E2258932A758BCA617D628FD +:103880006087A4DAD04E73E72AD7F3E7A953FAE0AA +:10389000FD79321EC956ED888A14EEC996720BB8AE +:1038A000647CF43C46102F597B58FAA22C74F5D650 +:1038B00039C7FA0645E856AB6F5DA0B4D639D31ABE +:1038C000C7BE2854DD3A7C9464CFD676FC7617C404 +:1038D0006E68AC5E28FC72DBC987FDF8D233B7B1E5 +:1038E000CF973B755732EC684534EAAEF38C2275BE +:1038F000F2F3AAD35CFB194A98425AFB46132F4CA9 +:1039000018EAB13FE46928B8DE8172ACF2450C12C6 +:103910006367B7D07277C81AAB85F2951DE5C113FE +:103920003E462BEE2D9AB40752FD5804592442C846 +:10393000E2CC8ADD6D049169BCFF0825AE515E7949 +:10394000EC491639F9315D7B9882F92278FAF6E56F +:103950009C72897EC77B21AF1DECE0C136B270DD61 +:103960009E69C73FA82987FD680FD8C04C1A4C5ADA +:1039700052781EA03060191F98ACDC1991DBE1333E +:10398000D60CEDAA5CDD7A7435234F7BBC3F27044F +:103990002AA0C1D50BBF70009DDF5C10A9366798C7 +:1039A00029FF54088D0E2850A31E13E2A376F57A42 +:1039B000F280638326F825679169B83BF9ABBC1E9A +:1039C000A0B19E473BB6D3B5A161E3121F2EE71409 +:1039D0006501056B6A8A691D02A0F31AF43FDAD209 +:1039E000072EAEB1D14352DCCDFDDC3F538217260A +:1039F0002AE2A22249F14E0E1BC2C492214933EAA7 +:103A0000EF131C69EDF9580B166669C5725030DA70 +:103A10004D80D300083163EC2ACB900B93340929F5 +:103A200054D3175BCC61C6F1FF71CDBCB2E285AB5C +:103A3000C753F560A081732AC7789960614AD11293 +:103A40006B348C4AD2805936A04FD37944A1E5EC2F +:103A5000FF572BDA7D1A90772049ED0D3B1711E4C3 +:103A6000D2391B23EC97B761B9BABE8149969CF84D +:103A70006B7D7A970890FF63F9A0A6E35BB2ACFC7C +:103A8000CDBF8AAC7DC139D51856BE51D5CF95185A +:103A9000C706DD16A057556493D9177F425D6C3277 +:103AA00001E7F8F4DE9FC6F960E0A5A5A4CA02AC60 +:103AB000549D9F50F24A4000A0331AA3FAE05202EC +:103AC000879EAE4A645C54619626F21A84021C12E8 +:103AD0008D83AC301FFB471D074DEB82A9CBFD8EBC +:103AE000FCD6AABE4423C04D0C08BB063D5DA721F1 +:103AF000FB834A225462292551B47AB4E2ABC86CE4 +:103B000076A92F1E25437B1BE848650AD78666D910 +:103B1000168693059426077CE0D595320D5493FACA +:103B200092133B2626CEC3F3CA7AEAA1D098C3A348 +:103B3000C7D89E0AB4E4EBE380C4A5A45B17DB8975 +:103B40001C8B6CC993E2E849BDBE2FEA9B2B294E22 +:103B50002C300E7F5925CB546C240E6CD5584B1A43 +:103B60004555B26A71AD603572A1AF2530ECEE6F8C +:103B7000AC3D997F0AD579B34B466D52E917624542 +:103B8000F4B8914E9A26861CD1091351F538A9E252 +:103B9000A7F9D1196BD422080A8914895602E49333 +:103BA00010A87D6271BE79CDDE8F5D8D251BE80A80 +:103BB000FD64743674AF3D4A8FE8477FD4111FAB64 +:103BC00045B8A2E27DEB8C6C7AD2FCE0095D2C8BCF +:103BD0001CA3786200D1C61AFD1F61DBE699E63AA4 +:103BE000725C99D3FF31D9ABDF5EC13CAF996B9268 +:103BF0001C9BAFF1E92E016B75D546223D07C64EE1 +:103C000099DF39C96019E63D0DE80AA3789E6C4436 +:103C1000AC098CA305B0A1E34BC5C1571C316CB7EF +:103C20009A26552589245E98ABF7774590BBEB71B2 +:103C3000B98FC17781BBA465D119B9284B0603D6CA +:103C40008A825E299F8167266F1AB2EE88A96E0666 +:103C5000DA116A156EAB56C282F41847BA90023276 +:103C600008DDFED9B230454DC969B5A50387123DBF +:103C700097B18A5A22F02445757202671257789ECE +:103C80006A3A8C988F744DA4FF42FE8FCBE19B2C37 +:103C9000AD2DA692693F4F7EDB408C19566158C905 +:103CA000EDED2BA58B37597B1BD9DA7055A7E79C17 +:103CB0000B23F1C31F6F8E2DADAE1B7B2186C90078 +:103CC000AE6B182646C0F2B90B5035A6528F40F3A2 +:103CD000A1DF8D96887A5E59E0E420CE7268B952F1 +:103CE00092D03AB853BFC540E63E9BA67B662D7086 +:103CF00016A91CA3B366C6C4F33F1CC32B0D1D93AA +:103D00004A21641E67B8D66274A00E07ABCF1EBCF2 +:103D100021577E19032E0D152700262C19B6567231 +:103D20002E3F6450C417B9CC3B54B8272438E1D493 +:103D3000A686FD3009779F7182BF0372D53564BCBA +:103D40007163E8652987BAEB04423B144E85022C67 +:103D50005AAF77696ACD0C466B6FD05C4D20971CCB +:103D600063D1115D37B75C7E5BEC6D6D4FE6131769 +:103D700027A817726183E47947E4A30AAEB3330F2F +:103D80004BA53AE72C3C7EF5AE4562D0957E8C1A69 +:103D9000663C4D4BD63781073BFA14E27C37956C75 +:103DA000242C203D394BF97D23D99C151F805E07BB +:103DB000681C0587C979AD081FEECEA464EEA65F26 +:103DC00056DF21B299B3D4E3E0F2FD716B759976B9 +:103DD000EAB2D0AD2ED40556D642D791456B7B18AA +:103DE000E3AF237B507DBFE5B98615C929E244DDE9 +:103DF000E0E80C66E844771A855FECCA9C97E61FFA +:103E00005DBA48C744072FDA12D3592C9185B6DE24 +:103E1000FC9AA0F4FD009623915D3E361EC9C9D9D7 +:103E20008445E6CC823397C699E0CAFE89AF1FFC71 +:103E300062A988EBEF337438145642C502DA006386 +:103E4000F3DE73BD6FDE4B4D3E67FBFEC55D9259E1 +:103E5000FE549BC61D2E7385995D04034857F38657 +:103E6000633A692A93511AF86282734B2B640105F5 +:103E7000438EBD95FA96B1F4DF4AB97D6ED4E6A7BC +:103E8000DBE4878E2420A8AB5A28DC0FD60894E503 +:103E9000956DCF2933E7AC7EC67E03E78B6285A3A1 +:103EA000ACD39642127F809EE569DBB57953B99118 +:103EB000E9DA08AB6B48E5668A53C4680DCF53BC9A +:103EC0003B86745DCE04B9229145CDB05E6FD5A816 +:103ED000ED332A4A4DD18DC4FE64280CE38FB76FB1 +:103EE0009367BF09E9E19E1C277FA25E5D714CE1EB +:103EF0003BD98E17A699B854A2BA36FEAB4D4B1CCF +:103F0000F8D76AA9C7C3CEBD91B58DF1385A66AA54 +:103F1000DE75130835B6A430A14C3508CFDB8467B5 +:103F200061892566A1B256BCCD9B5D99DAC3CB4AA7 +:103F3000F7F6444CF7BBBCC4181BD696A18CBF94B3 +:103F4000A41E052DE62218BBEC0E8A89C6C4D8E44F +:103F5000078CA6013A686FB2C20AC71FB1CCE42A27 +:103F60002F9AD0AA226B8DB1559A9332DAD733CCDF +:103F7000A668EBF30EEFCD31F8479082E661A97B9E +:103F800089B6AC5AF6524138B29CC3197E0194E707 +:103F90001571E3A393C316C12EA8BDA54C14DAD0A6 +:103FA000DE045DCDC92260FFED083F24125A9190D6 +:103FB000A193A28C1E3A022783DFFC21460724DA54 +:103FC0002A5BE2B2E4922CF3AC07B6330C30CF0696 +:103FD000F1B2FA80EC2964A5331B7EF0ABBA4F5BDB +:103FE000E6DC5AD700766EAD163EC5D06A0775CDB1 +:103FF000DEE3E48AA96345CC613C206B84DC19AB29 +:1040000093A08F235A3C716757BAB1DEC660C3686C +:10401000254ECD3D413E09C53D55925D152C5B07B2 +:1040200016925BA7BA0FF4411AE313E78E6582DD9F +:104030008833B77804E980A70CAA5F9B54DE8FB55C +:1040400062460071675BFA09D8D417670316E54A20 +:104050005528EAF4341981B05DC326D642BBC88E18 +:10406000742EA14BD99159515EC61E266866A21DB9 +:104070006AD8CF0D7C896DAB8C41A290F20FF9BE4E +:10408000C75EC20253CCA4F442B71713E28798F775 +:10409000EC97C929794D6594A040CA393AD5316E5B +:1040A000FE3E84D3F8FAFB5FB6EACA2165A6316208 +:1040B000C91AAB1D43C8F18C307B8A2BB3A06C535B +:1040C00073947C9F9AACF5E9EBCAAE62ECFDF2DF2B +:1040D000F37B16491BE8D8C16D428627123F25F0B5 +:1040E00063CF0AD4F3D4F3CB3E20538EE5122B3F9B +:1040F0000407CD8C37B70F133FE5B2236E737521DC +:10410000A7E48110F16FCE773896B099BBD2AA3C64 +:10411000D38BBFA878B1A7A9C7D0A09F7164576CF3 +:104120004C0D0E0C30E8E1BB4BA42BF41FF06B6A76 +:10413000E01FDCF0508A931316253B68A88203AB7E +:10414000D36EFA345F0D007B9974C832E04D0D2DAB +:10415000FAE6A8FA5054FFD77B657EFFF2B43E4ED4 +:10416000BAACC2549BCEDCD72C8A3CFEC3AECEACDC +:104170002A7009944520ACD8846A048E4D1EB0E3A1 +:104180009F21AE7B8BB7FABF98E94D4A6BD3C34FE3 +:104190006BC070E4B4230A2D219FE4F1829463C5BF +:1041A000530E15915BA14D19568765602F6BEAE997 +:1041B00083E2ADEEAB8F6B7D214BB309469F107B45 +:1041C00039B7F7B6D63A344CF2655DE36D8FA1E9A5 +:1041D00097E9EC5910CE65CD30ABCA85B4B77A8774 +:1041E0002D5AD848CCCF10D5E144EEA92C5C38AC80 +:1041F000FE99F484C0EB7CACB2F9114A677F284683 +:104200006D21770BC7CFB0ABE73F454D6FB6480E7A +:10421000E9D2C84D9DEA07A7432451E6AE40DAAE85 +:10422000D8276162DD87E36D543E89919D11A247D5 +:104230004FA03783B4D993B18C31875A03041A85C0 +:10424000A4024B7C78681097976E2ECECF535DB446 +:1042500062590C4BF0E9C75A95400CA70992B13945 +:104260001D8AD6EEA12A014AD726A213ABDD06A7E6 +:10427000BD5458803CA3D35B45CA7D2BDD4EE9D8A5 +:10428000B2A81BAD4F0F7470187AD5696D3762E90B +:1042900046DD62040537D972B6378B2F1F23B597D9 +:1042A0005E8D49C6EE4F090EDB50AF8AC0702139D2 +:1042B000D8F2344E295A9DC1726F88B55CB0C439AA +:1042C0009B05D7814356F1A032B09DEE59DABCC3AD +:1042D000B8E8C8DF87F6BC725D13BD26ACFCC8FB2E +:1042E000623BA3B6F9DD2B1921617D54560277CFCD +:1042F000513DD9FDEF1EDE564D169D1CCF4394E176 +:10430000DA7B22F7EA364FBCDD6B84755ED90F91FC +:104310001FA8149B38D92F7BE54A8B8957D62EF7D7 +:10432000BB468121C83D9AC957020F6F9B3C23A50C +:10433000CED4A3F06CC3B7A79AFDF509648656FDE9 +:10434000795F626ED2027471A08DDDCBC383BC0E27 +:1043500037F85AFAFCC6071AF74F63DFD98963901A +:1043600009C9C2699E2AE4C6675F79CA20F992E743 +:10437000BD6F1A854DEC5FB944D235AC402F6085D6 +:1043800055AD16C99271EA5C93DAAA199DA17A5FBC +:10439000D4D9D3747C69E9B43AC3BBF818769C2F9E +:1043A000C8AAA5DC7F83AE92E2976559ABBC44FCFA +:1043B000BC79246B5FE741B58D87A621BE84BA998D +:1043C000058543AEE4A17E48F5D130F6D73CD10E49 +:1043D0000F6BFE4BD8DE294B88E84CB8868F6334D0 +:1043E000510F9D261E96F1D56B01F2D226A46F0ABD +:1043F000132C0EF6C61EAF922B6C86208867C64F14 +:10440000A1D5093B829702971793FFC057C5BC33CC +:104410006A5886B494DA95B24C257327FE89A6EBC8 +:10442000628A4C2079F47560430E8D0B9DE684A161 +:10443000473957497EB7FC310884098A3BBBC6B867 +:10444000293009A44A8346698D2888842E7DD41892 +:1044500076D0ECDB1943F8A98F48C1D0D1BD09183B +:104460007E0527B1AC70D48AE9246B4BFD93CA0753 +:1044700004EA39457C99FA9CFACD0E9760F94DFF14 +:10448000DF70DADDE6B4AC0410EC44E877E7B41D85 +:1044900033552C80E663B380D879A0899258B56FE4 +:1044A000239ACFCD0DB2F8A6255ECAED0FDEC80C5B +:1044B0005DEA07A2C39696CCAA465B26992F1068A0 +:1044C000FC8D2A65C9BD22053A11577A7F8280E3A7 +:1044D000C1FCFC71B37CA5961EF7D81679DA3B2493 +:1044E0009F6EF268B2B7FD486CA99EEF1A69D408B6 +:1044F00067B6C6F4222F4B3D124632E8F5427D489E +:10450000A57C7EAA4E901027CA00AB667CF83D526F +:104510004E22BA7A12AF19D06382DFF78483DEFCB1 +:10452000513C61C0B2A8E24D6A81744164E67AD51B +:10453000BB20CCB1B8E6CC7AB5EC081917B101C6EE +:10454000126AAC247CB65DD85A4ED6824641EAB790 +:10455000B310363B28E2B076D5738651EA34347B0B +:10456000FD0DD28A1CF1EB3319613BA313D6A7834F +:1045700072DBD1C468FD29F867019ABF6CC9EA9E55 +:10458000E9BD43B33DA410BA33239F4E57F904103D +:10459000139630E874908ECD75A077036F3E8A90A5 +:1045A000DBAC289DFD183F9B20CFF1E6E873C8E502 +:1045B0008BAD65D5C9F2B1FD5D3C33FECA9036EED8 +:1045C0009458D599E7CB680DA5FB0CABF9B1FC5617 +:1045D00022A99CD813AF993ECC8551773942B8B304 +:1045E0004B48D9A396AC82D5387F977215F53CEB32 +:1045F000D6E5B97444BB23A3689ABD221462CCD417 +:104600006ABA209C9B3D7EC3EAD7286BC198783F4D +:10461000694DA1699DC40032791BFD8BBF157DB822 +:1046200007AB22B284093C85C44EA897B0B2F344CC +:10463000C9142B3F826CCB7997848A9CF3EB13AF20 +:10464000B041C1632AE3D638B507D18E33207680D6 +:10465000A45375E4714D53F6E939FA6A95D9E80126 +:104660004B90A345F751F04330D20FD923C1385AAC +:10467000A6D3FC722E987BE9D6509F7E7D1AEE530E +:104680005AA66AF1465C714925BB23307120FE139E +:104690000F248A46E9092DC0CFFE310A374744BAB4 +:1046A000BA19F9AC2769ABFC531FE93712623B56C4 +:1046B000B22DB4CF5390F1F24A716EABE22BED9272 +:1046C0008F5C9D4528A8F9CAD201837AB80CD8E13D +:1046D000183A5EAF0E080D2480B6100C1A3A153C3D +:1046E000AE4E5C4DAD417E5DBA6AA3933D812C48D0 +:1046F00051A3AF15023B5C526E564151CD34D520CB +:104700002CD294F54D37CA3D65CB91E258687003C1 +:104710001A51DC57600EBC2BE261864E5417CB1544 +:1047200041BC98584A0273F5A541D951FCF090510B +:104730007523F3AE8123332F6FBD65BE8524271CFF +:10474000D454FE0CA4DB636A8251F394E30BCBFFD9 +:10475000546ABFD62CA19EEF17849A80182011BCF2 +:10476000C14AB5C20CA64B27E007B77C6D57BD40C8 +:10477000593D0E23724484CB0CAA508F8213C87803 +:104780006FEE13CE21083169CC14EFB4F40265D674 +:1047900031099CD5252D57894EC0ECAFF65F264DCB +:1047A0001D1FBBA965880B1FAB43A0A8DA4E58D3C9 +:1047B000B7C8D85B1A5A95FB2E57DB55B42779D268 +:1047C000603A3224A40CDEED223FEA8112B0C45DCF +:1047D0008444AAC4F492442C76B0B23ACC0EE2E1FE +:1047E0001E937C82C1D4978BC64482B904FA318B64 +:1047F000539F6EC731E2BB09343FC563B028DBCCA1 +:104800007A02E2AD5F1F8F470E438CA630278B33B1 +:104810009049E4843CB3CD991FAA276996E5B487F3 +:10482000F2AF841C843F326BE14C7F3083AAE6A157 +:10483000532EA8316346E200CA3DC83CED22E3E0B6 +:1048400090398FCC9493DFAD4D737C422447F108AF +:10485000D9DA560DDAEA7559B6E51D8C284C29804F +:10486000A34E40A4696148A264083C9BA426BDA550 +:10487000A48785BEEE86C8944756DD703A94D0284A +:104880004B475257735597482DC6C29BDA6C523925 +:104890008ED971240B199E09DE1C5F072B165EA0B2 +:1048A00095ADD9D9D8486ABE0B02095BDB16ADF6C7 +:1048B0005C26061FB2C1AA3DA9BCD703F51CA65FA2 +:1048C00083BEA5CC234E31E0F43AFACDED0E3B1B6E +:1048D000CD6FD57259A34EEBB3D4A9A72078DB17BF +:1048E000B3DEAAE1B6656F9F14D5858C1D99B2D150 +:1048F000A9791EA1CDCF3C7B2ED297314FE913B2BF +:10490000135D1950340B9AB965ACE7144D51FF2A69 +:104910004831B1D6E073F4E77E089E1C89310997CF +:1049200037202112C67E6E4C01A7CCBD6F3069982E +:10493000EB8D99BA582F78ED4A6C370A6908937352 +:104940007B1F23E8D74146A84F72FDE53560A5D20D +:104950006940F2889FD9F6185317CA8DC0072FE314 +:10496000D354F213461C4DC4265275471D4DFA26EA +:10497000069F73DE25B04C569E77CCCF79254EB579 +:10498000E9EE0A40516A37EB070736BF9897BDE852 +:104990003701126C7F4AA2D5BD549B3771B2FA041D +:1049A000164184A099D9E4B6A07EFCE2AF2B061391 +:1049B00005D6522128079C997312423CC1F2351B3F +:1049C0003E1D2B7DB7D54E4879AD3A567571654978 +:1049D000CC993432DBCC8F29157E8221CD5416152B +:1049E000BE06C26F6826DE07623032A158886FE1CA +:1049F00007D27CFF6E09EA28933033F4FFFA89036B +:104A00006405B5987ACB7A49C77CE6F0D091BA7143 +:104A1000D25FF15797724F31D302BB2E5FB8ABE52F +:104A20001143A1B1CC5ACE57DA47171AE589C8A568 +:104A3000A70B5E146947B8A309385BA679DE928B91 +:104A400053E43820480E89068AC611F74D39CCF850 +:104A500051BE0EB7900EAFB7C3F3EDCE49DA555342 +:104A6000B5A63403C83393A40DC8BD1732CD98D86A +:104A70001306CF56DD1C7243A095DF5995513C9229 +:104A800039A3BE4BC078E5B3C3900CC034214FBFEF +:104A90007F72EC9FED039E4519EB87FD86D34D5643 +:104AA00012AC24BF377D1705D49719F6C45E7CD4A9 +:104AB000201D69D25056424F199070C780DA379442 +:104AC0008EA34192E3645D53AC4E1C35F64C4C0012 +:104AD000ED069215608AE05B7D8C904A74E5613743 +:104AE0006B88C94D8617DC25DCDC374A60B79C3BF8 +:104AF0007521874BB488E07CAD4406D25AE8AAC140 +:104B00007755775F789B202B0572B2E6F6025F112E +:104B10002154E462C44F74E5E946DE8FF71B820F2F +:104B2000C8E180AFBA6BE8DE9120F6BA1EEA7119CF +:104B30007F8831BFED2F43D528A7A9E4FC640D4938 +:104B40009705C5CD7D92128B859090731AD276D938 +:104B5000ADDDA1C25D013E8F75895FFB8750D43CFE +:104B6000B57A887C5F67300D226A63798D6B4C4023 +:104B70006F0433604622056566BBE0A44229E9174D +:104B80007B4AC5EBC97F7ABC7A4A8C5B0334A27B33 +:104B90000927DFF0A03A8DA9E0CC0571BC5AA91E07 +:104BA000B8DC0E1E7A2FAAE84005094C875B334813 +:104BB0008388D4E0076AE500FE4EC0FD648E92E073 +:104BC000683563A1846D749DB33A4B7E8B4756D98B +:104BD00020306B8C8AC5D9B950C242522DDE0011EB +:104BE000EA98058E21D6D561CA423688C8952063D9 +:104BF00045B07F2CC579E87EC5D1C4EC69AE744759 +:104C0000BB781C38CA2A79651C0B386108220575E7 +:104C10009CEDF0E33DFF17E6009A8C303CAE719CB2 +:104C20009BDC65401CC446DE3E26FC7EC83D413F01 +:104C30001BAFBE5B5162363191A92CEFD320748338 +:104C400069C32A5639DC5450D0BC61ACE69562CFBA +:104C5000748613CB9693319180412DA3A518E1ADB5 +:104C600038E039E2176A45EE34394D7A60685EB44F +:104C7000B8EF559ACB1A8F1D347EE85DB8391445CC +:104C80000555F1604C723FB8B075783549DCA8C85D +:104C9000ED9DFF38DCFE0DEE1898DEC0FDDC2273C2 +:104CA0002735A390FAF0CAAE8CF9E791C8B0D8BE08 +:104CB000BECA56B0E171873666A1CB5A2322A81826 +:104CC00057168CDA85620F212A068907BA090B0C60 +:104CD000F55AB5D021069B2AB0CDF247E3E4604DEA +:104CE00035A8798E0CCF6DAB07D83972720AB438FB +:104CF0009336FE48BAE0CB09D52496ED3EDC581336 +:104D0000CE154D28ECFBD7919AB4ED50C6ADCACD67 +:104D1000C90DCCCC713CE24061A22F8D37CDC5B41A +:104D2000EC5BE748477F14D8D3353994F1F873FA30 +:104D3000D23D8EAA89A242E00DF6FE11B40C945722 +:104D40000D51C6E945DC0EEB7ADC2866D0150B194F +:104D500048B5EF9C8D654034194A4D690E015325C5 +:104D6000CB896044149ED94151C9AFF12954ED2932 +:104D7000DF2179AB6691BA89E9AEC96CD82953694C +:104D800012468B3CAE4FD9D305025DB1997EC0E689 +:104D90000D4703656A37114B2ED4D7C1534C061209 +:104DA000FBFF065AAA945BA3A903F050BCC1009D67 +:104DB000F53C276818FD26C4458362248CCF7B5BB5 +:104DC0001823B41513A82BF71B0FFCFFDB42F47656 +:104DD000E3C44052186A3537889CC870AF506D3DA7 +:104DE0004E336C55AA30562AA9C1C39DC70D08661B +:104DF0008B115FCAF01E46DD51E4C540951C44DFAF +:104E00002A39AC252F4760F45F27CCC4D27D8F654B +:104E1000CC3D9F3D97CFD721716F8D412B6D964330 +:104E200001543967CB6E1B4BDD90FC9C6D3F770ABC +:104E3000C750AF73433866CF76E681D7BFFDED6EBE +:104E4000AF7F61D9680BC92DB0B731C456BF4AC313 +:104E500097C2EDD677B793B3EC674566826E611360 +:104E6000292A364C3CED1D4396768C180E7BB8D51E +:104E7000BBED4389EE64A968669E5E791C8EF4FFE3 +:104E80009FA0CF018C560D7E3BA52A23DAF6C8776A +:104E90000543DC5C180FF006B5F4A7DC08B095F408 +:104EA00011D3F6D7DA9DFEEE9F248265CA3E228496 +:104EB0002FE4233F363344E28E3BAB0CB8CCBB2F00 +:104EC000B3FAE08022CACC9D889356D11D3C0D34A4 +:104ED00037847E8EF0C7D770A9D9878869BED8F08D +:104EE000896396A8CFCB3150F3258EE5DB35E656A6 +:104EF000CC2F3B2E9CE15ED03E3E6B4D5A9006235C +:104F0000C37E7CD7C3752D1E8267F41359E44644D3 +:104F100073C834E074BF5476D48D0BA2358B4734FC +:104F200094068E71F2AE2303A2BC6105DC5FDE46FF +:104F3000F98B8C263145F0198CFAFA9C2E068905DE +:104F40000448E653BAECE7E0AFEB51B8355C4BF1FF +:104F5000990A29A82B0DB4C319EA9A4F9857EF461E +:104F6000C6044553F5010657A1A1CC629139D7A7D4 +:104F7000D802F7AD2FA27DBF9137944285E0989576 +:104F8000A9260406BC5B2F1008CFF9E3D583C98D91 +:104F90003EF603CBD064C77839F070A0EFC04F184D +:104FA0000D39FA20B693F6699F320E4A55FE31D775 +:104FB000B9388007CB1E4AC1581536A32F0A72A1F3 +:104FC000DBF697402FA6533B25F15745E460F54E9D +:104FD000EE48E800E77093C5B562EB44EFF640E9B0 +:104FE000F928A4DD5700CAA32FFDDD5AD57F809193 +:104FF000AEBD3204EC31B03C1E3621126764F5912F +:1050000049052F29D7BD6CE3618856E497222467B0 +:10501000EA99809317A05CBF3C0E7E56FFC9FAF256 +:10502000A98E6FF10BE32752AC9130F2C931EA4BF4 +:10503000E5FF9B2BA3CB4381B3A663CB65594F47B9 +:1050400063B88FC781732EB655C480EA73EDA2DEB4 +:1050500066739A6F4BD6A2AFDF4B3E1D182EE2E46B +:1050600017D6A3BE532A255B59D0E63A0193904E3A +:105070005B82899A060D7F310169A4CB2FAF5C88D2 +:10508000CD99DBE49EEFE1A840B06C4A9529FFE79B +:10509000A72944922D86CA3FC8B6458D8D0BDE0FD9 +:1050A00007CCC55651394C8B6CCB3503AEA8023EAC +:1050B00094A092445C2E5945BBE74BBA21E8FAA074 +:1050C0004CD6EBC9267DB1376CD1323558EE7CFB1E +:1050D00040E584EDD424DF4B3E490C22B46683EADC +:1050E000CA568AF9030D748AFD009244B5BBD36B8E +:1050F0006C6AD3FDD59CDC684E89C2FF3503D69E11 +:10510000228A2C2C5C742074C2EABD7A80DA9B88D7 +:105110005EE4A346800E986E8B4FA3F598EE7DC794 +:105120000705B88087B4B9B16B6ECABC0F128B2F5C +:10513000FEB5EA162DD3A1BB1AD991297191F2714E +:10514000A74E9A534F1F8DF46EF9B823B3D9D57378 +:10515000DA722C4B1E19BB9A31F2190B1ABA385855 +:10516000B267CBCACDC993952F8200DFECF763EE0F +:105170003A034073F317107DDB8924D0E745F7A28B +:10518000F03E32B423EBDAF31331D189B463F3D0B8 +:10519000020EB73FE1B421FAD7E154DEB5E2338A1B +:1051A000983C26CCECBB32251BAE3788E052F2058A +:1051B0001AFE7E7C1E66E423034553995055A7F3DF +:1051C00075E1F554952D881AC304C62A6952EEFA82 +:1051D000C18BDF7510DA47BE233F40D012766F35A2 +:1051E0009771B4E5B3F53C37CE1290489829C8EED4 +:1051F000E0D3A951A498A353ADEC8D27F21AA809C6 +:10520000FF643A4F67DD4F4ADC11ECD77E0AFA168D +:10521000C24617D979C809729BFF08D9C16CC63A32 +:105220003EC8855789649D117DA4E5CF594586D236 +:1052300024D1344663D2525F041FEA2EFCD5F18597 +:105240007BF9E1DD862F227528AC20BACEE237FA51 +:105250000488E96BB08C6F03DBE62EE56A7529F7ED +:105260009E0B25D829B966EA8BAD7E2C60F9846740 +:10527000D69FFD088BB8B5808B6D01AD9402B9D275 +:1052800056C5F03D887BCE7B3D59A6C3573B772161 +:105290009D6331963E7C730791DF8A3208F8AE2B0E +:1052A000B2BBC7C63E01233F5B62847C4C6CB7A691 +:1052B0003EC882D4B48EDC26C29549A2D9CFE0A6DE +:1052C000AAE18C19697E8A1A34794D91436448F3B6 +:1052D0000345BFE406013C3B8939F51262341B5A91 +:1052E000675B0A9F06491A64A091CE03A70D29D6D1 +:1052F0008C7EE541BDCA13858C7B814BE57A8E306F +:105300001F1D59E065EE10C2A0C771C00134E7C38C +:1053100095AA843AA288A6AFDEFE4167AA793B87A8 +:10532000D65F203443C40185741095EFB770CFE287 +:105330005231EC272090FCC4D7EBCD20F6FF4DCDA9 +:10534000F3634B91247FA5B954BD68482E866665EA +:1053500004C83250DAC18FDF8B59F812F4680C7828 +:105360001D361FBF6A7EEA01B2A7EA545A15F3B090 +:10537000CED0A1AFF5E5F0D958DF9E95BBA8842625 +:1053800084BB5F619736FA99EC689566E9F96A5BC8 +:1053900022C7B31C01B9A126CC97DD360068748BF7 +:1053A00008029EB66144ABA400D2E0D4C8BDE7EACF +:1053B0002CD68AB3491B89F629454B04B35561277E +:1053C000E83BDADA123499FE8AD1FCD8A6C07432EE +:1053D000726DF410080542B7B0236E05B1AE1C5EC5 +:1053E0008CF21CDA4342FBB850399EBD0F2C8B98CF +:1053F000E62383734180D2EC9EF04EC97DEA0B26F2 +:10540000ACCF2587E11B6489FCFFC901AC38A97FBB +:105410009BE72FA7835FDF8815F5796BB64DF9D031 +:105420002A16771CE45028EFB75B6D30CBD3CC5EE7 +:10543000A10F2EEECC3F6EC7BFBF56694B032FEDB9 +:1054400051FAFAD98A1E8847B88D489E9B68AC9E4F +:1054500046D60F8198E970E7187E6E06E0B18D316F +:105460008EBB95EF6E03A5CA7DA6F0C026B7A33A02 +:10547000098F4AC8A439CBC5021290D45F77154A68 +:105480006AFF56244A3FE5B59F5E9A610D30B6F338 +:105490005B04610AF226E7ED6CF1F817F584F0FB86 +:1054A000D6497D5AC6A710A83626B21F812A4305C1 +:1054B000DAFF3B24AA93383D12AAFA0A72C796F57E +:1054C0005150A301C276F1A7EE28713207F707F613 +:1054D000E2030DF0187A4D17BAD31466420006F9AC +:1054E000AEB12832DD322979F55264056697CA2AB1 +:1054F000CD630AD1BBBCF14C7E7324F64616B82AA4 +:10550000A072DC1E8FF75B5E43516957C2701BDED1 +:10551000127ECE784D673CC1197FEF9CA7172FE60E +:105520004894A533C431EADEF090F8C11A3A958B5D +:10553000FDF6FB2C41969666029C578333BD4C8F3B +:10554000AC647CDE636D6FA82AFADC414585516F3F +:105550004A4E90B97F09C3137157C7A38D346FA901 +:105560008A25E496227E8DD2AA13FDF217FB6DFDEB +:1055700031842EFA2091113BF3E3C25D40A6CB1695 +:1055800045024004750C12F67F96A0067A92CD591A +:10559000A644B1FDB098FAEAAE7C6B65803D374316 +:1055A000B12951CEBFEC0CC4B0F09CC7CEACF6BC58 +:1055B00099C3C920D32BBC0484CD3D3ADE1B801B8C +:1055C000CC9A334B636B29F91F0BD99D0C12D6571C +:1055D0006309A7572FD349F1580532B5AD0D08FE21 +:1055E0009D29D63D6F9DB068310C2897B791223523 +:1055F00054A62E2313CA4D46AE8856CED4EDAF55D1 +:105600001C6DEEF25A3E9CEFE47E29BB89F61879B8 +:105610005F542E8874ADD812131CA367C0312F3C81 +:105620001563EA97996A1DDBFF814FD8753691445F +:105630004015B899E241A8E2B187097F9D30F85042 +:10564000A49C87357920FE8BF01FAABCCC4B160E8C +:10565000FE6D4D5D2C493E5493DF89E4AD6FD3E37D +:1056600096D28D950291CA4C663CFBD880A46D4BB6 +:105670002699F6D3D629C4CEBF066254E0E73CEFA4 +:105680003385C951BB330093A0D6802B846B1EDBBE +:105690009CD18B2EAF211A1A02D6C0A15E6AE16698 +:1056A000D82F454220C742773A52A83E0043A05225 +:1056B000E6C8D762E25D579503ACD418150B26A552 +:1056C000F68889182E665E37B43B3D864143FC322E +:1056D0009B8AA8929986CF1D4D21C641619F7888EB +:1056E0007CC1842786FD1AD274978C58E2B07A2246 +:1056F00069FC69C293DD646B815A682668F5B55E02 +:10570000984FB93D2426C53DEE1E8C328CB2A2F3D3 +:10571000D42BD328832944967E0BD16D7352143831 +:10572000047324B310DCBAC7F7A07D7501A70A592A +:10573000D09AAD4083DCDA87DBC4F385676CD82868 +:10574000544833ECAF0C970D66017F34C4844A5142 +:10575000224E1C236D61EB9FD62814B4765622721C +:1057600049D02918735A103AF2AD22971523FF0138 +:10577000CA661AF54214685D93DEF84BA9E46F8A95 +:10578000C3BF72AF9BBA31788B32B4D7AB47CC81F1 +:10579000493C9B5154744D54B6928EC14840325B83 +:1057A000EEA2981BD66713C80AD06FF31E9F0D0890 +:1057B0000483F3B01C69FB29171E8D1CBA5D83940A +:1057C0007FD1082A5D4AA83A2993C83E57B7952E3B +:1057D0008BD3064CE160785B96AB4EE8CC4D905C89 +:1057E0001F1050D25F6D18B877F50ED55F1925D20E +:1057F0006DE1227EB4477CB7C0FC12CA55B842E3C3 +:10580000D90D65454F70C2F332E24B9BD72AC67C57 +:10581000800EC493D8CA5EEC388E4AB2C22AF5B85C +:105820009C564CD5451E5DCC9D6789C80750D0A2BB +:105830000439CEEAD6793ED3437DDE93C1910D572C +:10584000B13D77BD8E031E0F75D7D90E743A0BBAD2 +:1058500063DB805C90B5E4D29F2542FAD8BEBEFDE2 +:105860002D80DE1658880C9A6A50CF623ECDD50E38 +:10587000F6DD19B124D8B62AE68F65B4777A5021BF +:105880005986235DB03214C0BED4104CE428070101 +:1058900013BB32A44EE2C524DEF37A47AACA1640EF +:1058A000C45491AD1EFE8869685E004C72529585A5 +:1058B000BE8309015398B376A8EB62323476B48480 +:1058C000D3FC086CDD1F75C43BBED5CAF78B26FB25 +:1058D0003D0EBC40420C434808396F8993D22F27B4 +:1058E000186EC4B41FE0187DE90274C8788058F2BD +:1058F00047EE8B97884D1E304A00AC1B769B0B29D8 +:105900008BA4BF8B0878107FA67F86B9466C12AE39 +:10591000F270845837FF27BF87294313318DFA9DD2 +:105920000451779F932B2C1C6CD1C98A5C45966AD5 +:1059300010DEAE879841AE0CEFD5BB27FFF9F2E938 +:105940001F8EE444AD468AC5CC35983B3008773C81 +:10595000432DDD6B316EFBCED8750CFD93C3103536 +:10596000A68E5D56692CC84EAC10BE7443F0171E4F +:10597000C1E15933A27EE9945104EE56E49D2DFD18 +:10598000E12703B390B09949ADF032BC81957169BC +:105990008BC777E7E917259C67FC877B43ADB37816 +:1059A000A496539E289D6B9707B2DED59D6A03B2DD +:1059B000E5AB37A077441C3C209D08AE05320E5E57 +:1059C00031E7803050ED121D78A2103EA33FF691D2 +:1059D0003E4D6731654D3FEA0BFAFC5F368D29C2BB +:1059E0005A040966B0A2E18A4E78E7C2F46E5051BB +:1059F00098767EFC4E0A5A87272906E9E4D6701964 +:105A0000EEAA4E620A8C338FCC9C29775C09C8B50C +:105A1000554C422AD488DB64378BBCBBD848E2ABF8 +:105A2000F59516D0CAAE4CBBC8788284F3F82D7CAD +:105A3000058EDBA773B9F1632583B5898AE68C727D +:105A4000B3BAD34A2E8ADB277F7401C269763F79C5 +:105A500039C358AFFE0DE3FECA0434B71F2B478984 +:105A60008223D58A028BC78E7A2986729B3CEBF300 +:105A70003F6FD941ABCDDEC97A3B75BE77838FD2FC +:105A8000423B8F32DDC1F14D08BCC5ECCB2A85D23B +:105A90008358595443E102B176E35C80436E6371ED +:105AA000A3B317B28B9F67EAAB9AD73C4751B03488 +:105AB0006EB317D235AC60818546981511CDE111D2 +:105AC00071A571AA77C5029AA5954E382592CDC4C5 +:105AD000397FAB8834D6AE498D51A88B8746394C77 +:105AE000B563574BFDED633C222393EA0B68FF95AA +:105AF00089B26599F705E88810CF111F5F821107F9 +:105B0000D67CCEE0E58732912E124FE02A53834AAD +:105B1000778126D05032FCCF27C54FF3FFCBEE66FE +:105B200095EF3F4777A0E6BF0DA52ABC21E45007BB +:105B30001C157719DC6A3F0ACA8C7711236BC337AF +:105B40003E58B6F18BACC1F838B827E4B526FAE276 +:105B5000226A5467EC18352AFC1E244377D8BAE32E +:105B6000B7F8826614AD700F8EF51F91FF19BB78E0 +:105B7000DD6BD3C6B6A2EAC213F419863FE9C69E0E +:105B8000168A6CF522E8D42980EE0E209E067CEA67 +:105B9000F1A7F27DA5135567366FC6F9FC0E00B26A +:105BA000C11A64D4F3C9DDD89FDC59EC73C810E383 +:105BB000300D83008167216308D85794C888CB5182 +:105BC000FF45227812BA0F24A7FCE4EFCC436D0EF8 +:105BD0009923730468B6994CA3C47243A1F47F86D9 +:105BE00014029EE68977C3D06AE10CE613D0A65171 +:105BF000EF955B3B46B08038774268871B10D170C9 +:105C00004BFBD7EFED0A110C7EDD1B982918225CA7 +:105C1000F904DEAF3B2CEBEF1007365B8A95982F2B +:105C2000BD207A2476D016AF39BA781C8D7AFAAFB7 +:105C30009F912BBDA88855B42BF174AF6298CC4BC3 +:105C40002C14F1DE84A2494E4948F5F0C931704662 +:105C500039A85C05FCB6A4160C35E52ABF3FE371F4 +:105C600061402F3C47B0957CB8DB5DFBF3109D6B2A +:105C70009BAE72AAFC0DD32CB760CAE0B1E5539F6E +:105C8000C24AB3F8096D0FB48BDA87F3E751FC55BC +:105C9000BA0C15E0B31F7DAE6E9948393571B1F17C +:105CA000875FD9CFC437FB6ED199C70D8FC9D3B4E5 +:105CB00013DDECE7FA8CC28B684FED9724289690A1 +:105CC000AB51E477DFD92F76473629C62CA9127C51 +:105CD00011FA3F5D751C266DC4E96044689FAD9B59 +:105CE00054F8A1B40493F1DFBD1FD6F7A33437D124 +:105CF000AF028C9346B2F17FE16EE33C79B80A0DB6 +:105D0000D02E67FA788A9AEA47802DF866775A6B20 +:105D10003B4E089C4660AD86FC4DFED628540A7C5E +:105D2000C2618A26121978B49B3974E7C86AAF4FEA +:105D3000EA5ACA4FA9BDFA67F3AAAB2B4A3B0699A8 +:105D40004AB6489D2A460516F68F6CB4E918EE351A +:105D500044B5063D1A618FE8F7A1DB52061183FCBA +:105D6000DDDDFC385B0A58F066D9398BCBE3937ED6 +:105D700079A5D7C8D483D5C6A5E16956515B7460AF +:105D8000910C33873F8FA5C8B501021F797E839F91 +:105D90008B9B3B26280F5DF0525324E9F6CB8E1DDA +:105DA000F2D3D515BA0C162ED4BBA4BD6E6693D90A +:105DB00019A6744EBDF1953CE70CC8DEF41AEF7FCE +:105DC000888BFBD2E6D05E4CD96C536F9705730C71 +:105DD000E78D95CF2300D3EAB9F2AE096CF0E3501A +:105DE0009B965E1FF27106D6D197277D5C164DBC3F +:105DF0008011074B59EC4EA1DDF7C86E4D973FBDA2 +:105E0000460D6AD9F7208AABF5638452E431CD6E32 +:105E1000BA2DCBDDF3F677CD27B896CD050627C88A +:105E20004F2CDD53BCA90A09483070BE1A9AEFAE58 +:105E3000B4FD53842ADD09C543EE2E0AE714A2718E +:105E4000ECA073C7FA3E298787F9D328603139540B +:105E5000B119ECD0A64B863B027CE69A56EE9569CA +:105E60000EFF7222B8A0A22DD7AE68C365FE6011E6 +:105E700018B593D8312C31DACCD63999B19AC61AE3 +:105E8000518E5C2BD1BC718A826CF6EF64FEA63C0D +:105E9000969E15A595E76E49D63BC96398248DDD7E +:105EA0007CE61C0EBE95681FFA80B3D3D8264B4300 +:105EB000851F52D3F967357AE94CBF7879949021E0 +:105EC0009BC964B9307DA62CA989A5093A982E2CC6 +:105ED0005FFAB60A0CEEB98734A1F76F788EFBE64D +:105EE0009A1EDCF9C4EE4A7E2222BCAD2862FACBAF +:105EF0000D8266EC77DFB960ED69901DDF0436F93D +:105F00005FAFB64915E665D7F6B4D407E9EADEB760 +:105F100022DA6FBF404D1F5E2025FF424F1A47090E +:105F2000453FBE0443FBA1CC7DECD0014A9113D088 +:105F3000C64CEF9C4B81E99FB971A1774B8EC08E07 +:105F400066FB8785B37AB3DAC53C0E468A3B1037C9 +:105F50008A906E4C9EE6810CE56E5DA2A7A3D843A5 +:105F60007DAE3936CDC8F09165DBACB52F8B942171 +:105F70002F2D130EA159FB1DC2ADEACAD78F5D604C +:105F80002A36C1B9D959B916FC2BB6B5D8FFBA5FB4 +:105F9000D0D4B7F1C4983A64655F7A52EAAADE7742 +:105FA00065844F565905EDA5D9859B8C3959ABE7CA +:105FB00032CB272FBAAC367670A679E4FCD7B28004 +:105FC000D2706349F58C54529BDD0D4E71F306A9D6 +:105FD0009A92892EE1B24DBA444C2BAEAD49980647 +:105FE0002F814F7E419EDC3055E4E4A8106C485967 +:105FF000ECC3B33B22B8B119C091128727CD1E9CC8 +:106000006D83F93EEC2590CB34E9DAAA52150DD117 +:106010007A9D4CDE9C161BC2DA5F58BA29DB6D2EC6 +:10602000672223FFAF7339A54C3433D6076BD6F6FE +:1060300046C70A3B2D4FA524F716FF3C842A9E290C +:106040002089FD1FC8F939655B4DCAAE4B4AE15442 +:106050004C282167D3E298FC0E942F8F42A3CBD417 +:1060600023EF7994BCB1716ADEE6DBAC279E8D7FAD +:10607000AE19B42ADC6580120B6C3EAECFFF12D095 +:1060800072CDADE1FC7CE0A13A5FFAB08618CA118E +:10609000E5BDD391BD2E4695B4B185E89818968B91 +:1060A000EAB1A1E00ADA09504CE16B245D1618341C +:1060B000F0B9A676A69699725AB027DD2840736388 +:1060C0001BA2E73F1FF125EEBD5CDEE988E3CF9818 +:1060D000FF9457A5C018137527EC0FE27F1CAE582C +:1060E000DE358A7CD80FDE8F95C432D84A335E59AC +:1060F00024E97505DC8FAC3B5754A7817BCB9B4AC9 +:10610000A4747DCD0DAC0E089D81C9356213E95391 +:106110005570976D9CB611590211DA2727F793191C +:10612000027258EBE50BBD2E3867D420978365507B +:10613000D2BCA2691CD150E58DDDABB2ACD6519674 +:106140002DA644DF80D46C3B7C019D33F8DF122008 +:10615000ADE9CF9D395CE33A217F8ACA53D1B0695A +:1061600045A68C5EEA08A90F9773A6C16C0EE706D8 +:106170002F513A23236C3478CC2D9B4422987645BA +:10618000BEA2E072637681BF39CE2582F6012D2949 +:1061900051C47CA3923C8FDDCBBFCD669963974CF5 +:1061A000CAFF9D9E2EE07CCAB6B44B840803ED83E3 +:1061B000D42171456CA2B697336DF28CEA2E181477 +:1061C000C0C196E31EAB3EF191940C4336847DF43E +:1061D00052C441ED86C36619A062F34518AE3D5A1C +:1061E00012862E7BFC59DE781DCDB101167D4E2D19 +:1061F0000411D21F39EED05856B9C3F6BBE8B3EA42 +:1062000004E2A7DD61ABB985B4AC46B141C2F1A5EA +:1062100016B80660294DAB2AA885324F99D6752647 +:106220000AC1B44348524C1707371E9E5959791D6D +:10623000F54D60D8DE5742266225CF69784EC43CC2 +:10624000F458A8165BEB3435FAB9C2B612B2C29C48 +:1062500005FE761F2746D2974D4C2DB55E17356744 +:106260001E3009D8A15DB4C19E831838DBA17FAB75 +:1062700095ABB4E6B5FE485502A4A14F366D4E1B52 +:1062800021B8231816535016D9F1B9AED181A942BD +:1062900030FFC354396E1F01CB3B68C90433E84C4F +:1062A000B07FC8DC2F53DA31F07BE4A50FC393CE67 +:1062B000B0D9E83D9884D89FD675A948BC528C0FB8 +:1062C000BA1D21E6CA49D62965443A1E0F9EEDB88B +:1062D0002AA28E2544C19F375A5E22083192E67960 +:1062E0001699872263A120DEC2C1794FC5B4647EAE +:1062F000346B8399E938E4F93E4B1BA3AC3BE916B8 +:106300000F67BD7D5F5671A07DBCAB5F050B3A1773 +:106310000332349D38987F1AC4AA756D2355FF0C3B +:10632000546CCFBF0117B71BD84A34063D625622C2 +:106330005872C424CBD098F4BB91DE5448E7C79F71 +:106340004B028E6DADEC36247FD6DE8F76D20EF703 +:10635000A01055BDBFA893E2726ACD6D9C444075F4 +:106360000D8901D3B0BF1D48916D64E95E6AADA887 +:10637000D29049674C8381EE31D8EA469F49E8497B +:106380009BD89967D0F5433D90242E3F4754909A6F +:106390007DF5B5B2BEB8F4F50C6ABE98E8E3EA3E06 +:1063A00078E5C8208FEDDF931F6E4935C06A00CCB9 +:1063B0005D692F665F97B46C77873BFC2AE9B76EFF +:1063C0006B6E1B236AE24AC8FFFD80029394AB22E6 +:1063D0009DBD6D8DFD96C48AB470A91F21B8DDC71F +:1063E00077275460E36666E481AC342AA739FCA6BB +:1063F00081A4E06CCED7761555A56236FE5C4A8B3B +:106400002079084BA69D5060DE3B3268E251BBE02C +:10641000A0B9CDF91A475335F1AC0A3BEEBE7C76F4 +:106420003C0583EE24617634CC2B78A3E768ED4CF1 +:10643000F80BDB16D86DBFB8A5647F99C9F2771D3C +:10644000429F743F4BA789948EDC0B87D1D6BF98AF +:106450001531B4C622A560FEC3FDCB2FB1471F1E68 +:10646000B592216E599484A65F70A2FE477D29AA39 +:106470000109B46AD4043D2426463CB532C83882AA +:106480005C120E5AF38B066EA9D721A8067C1382E4 +:1064900066F50A14FC53B91CC0A1D00A7E174F7AC6 +:1064A000C6FD9489448EB8E193798117B873A78C9F +:1064B000A4962DC5F224904BDFE806A9BCF9DD5166 +:1064C000759252D3682A2F17C2C63F1A988C1BAFF9 +:1064D0003FD4C8FDC5091F4A777F72906E2E5C06B7 +:1064E0006828F106C7C0A732510E211CBE5836D10C +:1064F0000E3C5606FB3901737311CC995C3C158C2C +:10650000272DD1E98F487CC64A289F754F5CD9DD7D +:1065100063886ECD32EEBEEA9AEB05D9ECFA8A3E7C +:10652000C4EE749033306D7E88619D96D405B7F9C2 +:106530005EAA3197E2738053DB55E979F960FE4A30 +:106540003BFD1C09EB35E3A0FC4C6AD5205930F328 +:106550003AF7C1F634FEE9BD07523594168BA3DF36 +:10656000D031173F146009F737F2906323AC899359 +:1065700058B50E5DF091CD256616AA6BB529A278A7 +:106580006A053EFE27A71BE45DFC01D6D21462C358 +:10659000D5AC75AD2D3AD3D545A7453E85C4B39F3F +:1065A000CC09A563F6987DFDA7670CEAACCA877392 +:1065B000724267C56E50A33E439AD529F9771C53A2 +:1065C000596937001B4121FD23DFBCC01B9C52D001 +:1065D0009DEEFA001694B6F727E220B200481AB3EF +:1065E0005E0AD0C74522086489C7362626A54AF721 +:1065F000ED8319AA0B23E876D54B9FE1EE9C22BED2 +:10660000947F69BBFB53AC99F22D354027618B55C4 +:10661000B4BA5139CE4AA67424093F7E66E3514E7E +:1066200046EBAF1BF839CCE60C22F8EB7F7275A174 +:106630009618378932D4AC996183C7CA5F2B3ED490 +:10664000FBDA88CFAF4947F03E44F4CB7D975DE855 +:10665000BB44473F4E6A068C7CAE0B9452BDC38F41 +:10666000D2DD848B605289AA1D63D91F8CBF465E20 +:106670001111A9DDFB3E9EC7C6CA428956B479E313 +:106680006E5A986F058C424E9B7A3E66F879831756 +:10669000043AD2018432692C279F689161A312C702 +:1066A000116F14850390D9E06B371A820AA9C54986 +:1066B0004A2C5632573607683521143FAFF993A25A +:1066C00032651C2E987F843928CD67CB018717F25D +:1066D000F42222906D50CFCBAAF84A75FD41CCC868 +:1066E000F4FF4E0709D2BF471050E4FFB32A4873A6 +:1066F000B27DB54AC6D0EA2B0C3A20DF2331C41C48 +:10670000D9D73E449DBA38FC9C1CD22B59A74FDEEA +:10671000B515EA4B6BE03207079937A4A115C52BD5 +:1067200063F0693AB09E060105E64024C55F722811 +:1067300023088EBC852E86AFC995FF212796BBCB3B +:106740005276E7701A1FC733C1179D658AB4BD68BA +:10675000AA9FD0899FEA9B817B6C26FDE2B7DE8FE2 +:10676000AC6C584E411402F93882B1D334880948D0 +:10677000DFCFAAFEE6DBA7C233E8B24B51D4AD426D +:10678000B0242E3CE6413179653D61ACEA115CEF05 +:106790000546A9E1D67FB34308C27DEE76D2F086E6 +:1067A0004721D5265A404580A4F938D41A39B689EC +:1067B0000083DDBD7B1E1156A03F2F52241BD46BDE +:1067C000E1EDEFAB56E5C75099A4233D19A2573B25 +:1067D00009EF85E102CDA7320E9959441E35A30F6A +:1067E000EF618A737919E3C99F482C8492170CA32F +:1067F0002D4C9368D464E2F80624CA6CC9C90A6BAC +:10680000B13B879605FCC95B7C054E71E9C525E463 +:10681000142E68DBE352F621F23AC8B7D95938E5AD +:10682000D487ACFCAA9A50BD2B8F49B3895A7A9869 +:10683000FBF0FA434D0F834934BB01190C464A4E15 +:10684000A90050A7904C89FCF6C9F6AAA157837EEF +:10685000F379F5A8D884FFDEB5285DEA65ED96BB2F +:10686000D465C44B3B09951E65BA011922C10D20A0 +:10687000849876669D9AE927BA6AA949645D300DC5 +:106880006B433DB1A798F5F671A87C599A817F1F9B +:106890009659D1BA039695AA3E09B9DA75CFEBE2BB +:1068A000EF765044576F73E99713B1F1FD848FFE73 +:1068B000E72F07E9E27708D87C4CB0D41F03DF1E2E +:1068C000F0D677A6C0A0AA76CFD39621491A17A9E9 +:1068D00003DB7142BD2AFB32BD270C619B7E6EE259 +:1068E00098EC0EB4A56AC24C224BF9E2B964EB53A2 +:1068F00062BA819F60DCF4DB5186F991D2BB58A764 +:10690000974E942D09236ABB1D237CDC04F354FEAF +:10691000A4F11D9919B4080027DE05877A7A431976 +:1069200044B9C17D38DE50DD0F933DAB4E81FEEFA3 +:1069300097F8E0ECBFEC356B981D1E930BCCE7ADE0 +:10694000A598C9AD3E9C0428C6A1BC2FF4BD4B6FD1 +:1069500091AE3D9FF1218D41D0C6A1F069D0E83FB5 +:10696000CB9EABA5EB4BC33AF7B19BF48610A36D5E +:106970005D5750B34E47CBE33C8A67E896F9147CE9 +:106980009FC06AF9D59A1EAAF17282BD1D5ED3AC72 +:10699000E845E0855B8D9D9C83A37488E6320D629B +:1069A000FBC26BB991DA65A597119AF1B8076A55E0 +:1069B000E95108A5D76CB9BCCA0B1D88DBB8586F64 +:1069C000D8792DA306B522B7A37152A0BE2B76ECC1 +:1069D000BE4506D4B7835FBC789BAF3BC4182E8AF4 +:1069E000EBD09C5790DD650591281E1622C64627E0 +:1069F0002FFF6D9D4E970A5AC817F01132BF0A1922 +:106A0000556D18E705C0462DA8F5D2A4A3013A7626 +:106A10007028CA01D33E0FC1023545AEFA0A98204C +:106A2000EA8E256AF157A0E591BFE27F52B5370F94 +:106A3000D1BBF665E034826E00EB64AEB092A44E3A +:106A4000605D7F792A3820555D0323933C6EAD4607 +:106A50003DAD1BB115831F245D573153103B9C7115 +:106A6000EA5AD0C409738A6A6FC5D3BEF10E044DC9 +:106A7000D26D20C7328603B6E131DFCE90D94F8781 +:106A8000F694DAE0F1A0E5D23ACF67ADBE8BE6FE30 +:106A9000798A653694D5BAFE1EC3E2BB7BC2691300 +:106AA0008E99D202BEEBC621EA3B018E0AAAAEBC89 +:106AB000EE6E0995BE906DD7EB06755447BA3AB5A0 +:106AC0006C40F735A9E9A7597282285169C51B376F +:106AD00088504DC5A95E1B03990B09374C3D075BD8 +:106AE0003F39EF3CD8B0F944FC2933A643D5D32B2A +:106AF000D1154C888AC923D8A09C442777E20E3B45 +:106B000004F6CE28CE00FF82518090E47E451BF92A +:106B1000262F9285F4C71395ECCC03595A828BCB60 +:106B20003EAF0CB2DF6A408F411435BBCF02C325A4 +:106B3000F1A1A7E894A34FE7AADFECE42267305F56 +:106B4000272E1A4B938ECE77A594E4A645FDEB2213 +:106B50008EC9865AF829DCE131FFAAA4A02B0C7E4D +:106B600070560014419EEF615A1049D86AEDC92D44 +:106B700085247AE50660FA879DDB9653D4A6EFB9A3 +:106B8000CFD0D3C424691630488EA2AE190B36A3D9 +:106B900093674219077CD58EAF2301DB71B54DD7C2 +:106BA0009DC22C9A20FD6589D47B3DD9D1DE94FE0F +:106BB0002F4BBF3A14EB93EFB4D2229F07755E0CB4 +:106BC0008994D734C3088992778CA97C882B620F6B +:106BD0005D9CB39F9026CE1F4B1C6512F0CF68A41E +:106BE00005A02273CF0BD01BB1C86D4C0977652D62 +:106BF00001036EBAD92878107926E41677F47499CF +:106C000013551E3B6CC724FAC372627747E469DCF4 +:106C1000FF1F808D86B40B852C3E3B0DEC4CA8FBF2 +:106C2000A876C175FB036B776C9B81DC39C9922E0A +:106C300081F5A3123A2E0FE51FE0C7D381DFF2538F +:106C4000C20DF95BC7AB751735A90C032B2C637804 +:106C50002C26A3A3C92888D13B0B369690EDC0788B +:106C6000A9129E3E198C32BC13B3899CCF61449209 +:106C70009CDDA7FC33BE318375CFB35CCF2FAB4512 +:106C8000BD09FDE10C58ACB9F9FBAB4CAC29A484AF +:106C9000557EC033BF4D8E9C39FAF56CA9502BC37D +:106CA0001B956FB0F039EF8CC180BEE43AED251F23 +:106CB000DAE4D84FB36A0A6E12EFCAD9863F05A646 +:106CC00072162F33B9DE99CB70037DCB26F6504F69 +:106CD0003B09822AE1873228DB5DD460CFFE54D1A4 +:106CE0001655A41AB39E3CCC5E7C5DFC4BDA00A426 +:106CF000C6AF6F46BCD785B17C73AA3FDE40EA625F +:106D0000811097D6734BC80D0A30EA5390EA44506D +:106D1000E7CCD727333BEFAF3B32ABA8A425F40237 +:106D200007B6CDC072E6550FC20C6F0D6135D6A700 +:106D3000F13881A77EF390E550796F091A27388ED4 +:106D4000579A58E91F2E7479E7651788F8B773C208 +:106D5000DB7609D61FAA4ABCFBDA2EEA1D73DE6970 +:106D6000D7C2EAF90C344E196050279AAEDA5A05A8 +:106D70002766B0D6C3B2160C6D89F6CF5D47A6E183 +:106D8000486CCCD35398536FEB2D11C80E4F3C1168 +:106D9000BBC1D9B1730606ABFF52243F45E47D0E5B +:106DA0001B26E460D05F05E1D8887CE5E82B03046E +:106DB000D57786491447B2BA97AF8ECF05D8F84138 +:106DC000B4A45F6BAA55842B146A7B77ED013BAAB0 +:106DD000C937060B52EF1460CD0661F5EFCDA41153 +:106DE000C19154BA2B7A0639694F5238438543CC46 +:106DF0004E556260135BBB16CAE261531A850F1BC6 +:106E00001EAE347C6EEAA4F755CCF1DD15659BF41B +:106E10005E7E903B762AE80156192B8148E737A21F +:106E20000B547C67E94CA8A37756444806DEEE2C49 +:106E30009B7D6DA665CCF886CAC62E5EA7786310CA +:106E40007F48E650C0D185F529B2885ED5726F596A +:106E5000C01447BF7D69CE9D8F42DCD3DF7979F8BE +:106E60000B9A3C4DCBEC320C6873B182771F04C493 +:106E7000F46C4DA08ADD4E4E50EF6D87FA94DF7DA5 +:106E8000C35B034E891916C4B83524A5A6FBCF7081 +:106E90006011F5CE04438608DB60B8A60D4D35922F +:106EA0003011E4BE851C0E8E7F2AE6F87D95FA131C +:106EB000CE6BAC4ACB7A691337C96C182B8FE5D3EC +:106EC000D979E8FEE3359A547445C6BFA5B395A5B4 +:106ED000BA016FD9E34C9866CEAAB6ACEF027D4FEB +:106EE0007FC2215DB74B042418028B3B6F21B34D49 +:106EF000083FADA4DA4EEB10A474C85B5E8F91FC22 +:106F0000D07C225E8BDB00D68D06A7E28E99FA56E6 +:106F1000CD9861EFD687E6D5414E03604398C6F41D +:106F2000F6F10441AF0A11B8F00A1793585E0272E5 +:106F3000E6339FC6B1889BE5F11E77A179134CEC2F +:106F4000F06CA794CCAC2D746A95616ACD8F2B3D03 +:106F500058B7215B1AD3675ECA79CBA15D0E595D24 +:106F6000EDED1B8DAEF377F32D93F6A09519ADFDE6 +:106F700038BD790771CB87B1A0C3B1928A6728D495 +:106F8000D2C942C64E0E41D464A01D9B4C9BBE2567 +:106F90006A90EAEF22F3396C3614190CEBD79A9603 +:106FA00088A0F325C5C572715341C391CF72EFEF2D +:106FB0003B9F36CCD9E26D247745B32452FAFD507D +:106FC000F185B9132ED5875F7AE955DB82A09C1A2B +:106FD00085539B1F26FA0094EA2A2E5AE3DF85FE8A +:106FE000D5284326F68C1431833619BB300BE31DAC +:106FF0002681D8DD00977F685363D8B18691259BA1 +:107000002E2F1F73FD55C6136EB279AF3A3E15EFA2 +:10701000B8CEBCAA14E9A2BB3EDCBB43AB777B462F +:10702000BADCEFBB15D1EFF22B5F4CC4B98C5CA678 +:1070300019604ECAB58CC137ED5E017047EFD2E2E0 +:107040009B2BFB7E41AFFB3801F902693FC2432C09 +:1070500026F5DEBCF7C0A348A4C7604EEC4D928174 +:107060002FB819165ED1826515D3CA5646D9535525 +:10707000CEEDD24EDB0157A821A98F638579FBA203 +:1070800057E34828095F91B4C26E1CB66F2BEA3FE4 +:107090008E3B491F4D2D2968412C0438E53C24685E +:1070A00098236ABFC2C586813EA723B7E25EDCD7BC +:1070B0009B8F41228740F0665CEC2E4EFC3351B929 +:1070C000690D2C14EF205560A17C945759581B5220 +:1070D000778542B143CA9B2FFA2780C09A37D13AAD +:1070E000F940388B32E9CCEF49C487F0C0B57ED087 +:1070F000BAC6B2BE67B3EAF87379B9176E9626DBE3 +:107100005436DC7A0AFACCE54396C15E9EEE85835E +:107110004CDAB88EA3416E8B21D3ADB1B5850E7B11 +:1071200029F31084822DDF90D5E81360BC32697595 +:1071300075A78EFE111B9347A24A226CCE8A18C8EF +:107140008BBD15351679FFFD08ABBF624D999D913A +:107150009CBCC0660F001A63C597730D787987AF22 +:107160000961565C36704BAAA9398D402406B76276 +:10717000B6D8D0166BDD7C539F769D5A1FF6CD8115 +:10718000B17FC69AB6E47C6BE59D023CFDA095906C +:10719000612E2F571FDF6B0E7CFB0AA29DC7BCCE52 +:1071A000E7CB663BB6ABFFE853F52B56AD3FE86641 +:1071B0005046CC489B7879A7377BA61F3FD0A5E1E6 +:1071C000BF7A88802BEC4FB54E77930DC7B6E72971 +:1071D00097F469D5C8CAF88EEEA86EA79E7995E196 +:1071E00025A59616E620D665511528519F5C3D0EC3 +:1071F000901BCABA6D13E6859FED7E44FA05446381 +:1072000081FA82683AD4205A2BCA7A7E9B99C89414 +:10721000F820F13078E7293778E604D4D84A04B664 +:10722000DCE4B01D861B5E7305820F5888B8A22C63 +:1072300016286F02B61AFCBB0948DA738C919AF1D2 +:107240003D65CE92D318F654B362904A60F675A9A4 +:10725000639CB62D0A2F0A2492B65E236C5E6A5F89 +:10726000D5F88E650BEFBA96F9D8DAD8F4AF6E5729 +:10727000EA2840F57310AE7465D3607B283AE04F7E +:10728000D5548134EB9C3EB497D0E0FA80C46FE4CF +:107290008DB8959E2FA71320FFFFDD77C39843215C +:1072A000EE071F64B4127E34DD0655494DB1291C2A +:1072B000FF803D28A484609FDBD6DE9724053BFD3C +:1072C000879C04A748A2123C5DD4833823360A1E4B +:1072D00052FD06B7411FD5ADE0888167FC0CAFD9E0 +:1072E00066DB63A86B566171D167E127AFBD424C85 +:1072F0008146320059A189D88F22BEE55289229158 +:10730000DF1FB64491307EED6EAE2D86AA235C8BD6 +:10731000500F4ED80177CE3E81F62A3849472208D1 +:10732000DCA8DE826A3CF6EA05217BA5D4B9F46EBE +:10733000ED36D309E2EC1CFCF69CD4E2FBC73F41DE +:10734000048F3E47FB1F362EE6A45D92B98EA9D866 +:107350007ADD3B486F8E6608232EDEC9DDDA6AB01F +:107360004D28693009A368602EA08A2726B02BDF3C +:1073700020AA1232E2F4F03895C9D01C7B5F90F05D +:10738000E0D18D7876A2E156CCEC74DA312AC1F2E4 +:10739000DB212731D4ED9DF8E02CCF4E2E48ADAC4B +:1073A000CB80FD0560727E4DAB0C9BF8F435494DEA +:1073B000E9452B3033F9AB35D08DAE0432AEC9C0C0 +:1073C000DF1FF5C8466558629356880E983AC85232 +:1073D0003439E64B2BF012DEC28EF93E454F0EBB20 +:1073E0001476D653542DEAE42D438F851141B0E332 +:1073F000E032DFF304CA91B7682D41CD16F3EB08F4 +:10740000AFF2206D65B115FE59399F3FF8966A2F8E +:10741000EE7CF05B1E4ACDF1E2C5BD700CFB249DF5 +:10742000B8C2FAB9210174A4B45B4BFFFD933F3895 +:10743000BF65D9723CDA0FE5B433695F301B527A0D +:1074400088D3834790B6ECE1061F909EEDC8D5C166 +:10745000020303D5DD78B043A9EE96038CDBDFD5BC +:107460001959D4756CC7E59E43D5A2F0933EA35D30 +:1074700030DAA145901A5296AF2B995BC17E7E8778 +:10748000429BEF88A25D676325DC228B8357F82A35 +:10749000AFADADF7AF3104F330A7F89B0121C0BB0E +:1074A000A444A75BB39CE3DC8CCFEE588BB80126D9 +:1074B000BAAF5AE93B7BC391277E0FB93CFCCEA300 +:1074C000C5073AE6FD0909BD234B202ABC1E1AE96F +:1074D000C4A78C62EF55F0AB76D6511F874AE2A85D +:1074E000566B0809A9E326C627E2CB1260D851DC07 +:1074F000ECDEF232AD59C897EED1D4A88DD560FB41 +:10750000A83626D5760D402E74EC1B0099A3318049 +:107510001A6A3B59009A16AD2A3AE7CDFAF8E2DB2F +:10752000FDEF2454A9C8174B70E7E4A63CC5FA3612 +:107530000B4FB1D92E290FF211EAD4113C12E71BDF +:1075400013470894089C1C0FF428F306929CC1FE74 +:10755000D7A6609ADE65119FBDE9711C818AD32B85 +:10756000222EDD0043305B0D98FB8EA9B208B25588 +:107570003BA4590C4E9F88636870910B4D074C0FCC +:10758000A686BC6ADE34072EB787021E3E5673DB22 +:10759000E70A145632D8791707F1C875DE12A86EBB +:1075A00056A4239F0B72CD6DAB9739F3ABE1218EBF +:1075B000EAA8C138A4AC45172BE4FBFF8E8D8201ED +:1075C0007FE4D42932F7B9EB6743DE28DEA98E09C0 +:1075D000C26A221676F774F3DE341D25AFCE569AB2 +:1075E000AA62AFBB7BAF01389571CACC7B5691972D +:1075F000C536850076BFB9A8C974916C5FC0FC140C +:10760000496F4B0F57578074B97B8854161CAFBB1A +:107610006BCAE4595407421C7F21FAE26D3117FD11 +:107620001E9F2F31EA365DD15CD2B9EA7FDB4C8EEA +:10763000EF691A9B1CB29F12226C9882D94BEFDB28 +:1076400023BCCCD4A4B67BC406C05867D6659B3E89 +:107650006C3D54E512A95BFE37F6D2DA571EBC6FBB +:10766000D3286F44A18F33F5181E86FFDD8DFD1AD8 +:1076700093C1FDF882551F45576D8A093C0A402089 +:10768000C3DAE0F56147811352E5EE57691C31D04A +:107690005A51F767D2FF060613DF9DC90896FEC848 +:1076A0003D8C3874E8E882A9D5290786463C9A5F64 +:1076B0002F7172AD62DF2740925697AEC1F2C85368 +:1076C000311BB7BFF901C8CA45351E4653327E8CFF +:1076D0004ED2E4169C0981C3FF53EBA0FDE36F611A +:1076E000E4D33172150A99814A5F617404C219C2E8 +:1076F000AB8CE64E8D6B73EB848F44E2907A470837 +:107700007CE7454236DACD32BCD5086BF9C243205E +:1077100057411FE4D77C1E4F13A2AEA1BB40C9F650 +:1077200083360B825DE2C6818331F67D798C89A830 +:10773000387FDBDE8BB91B009A744C46FBFD18DDED +:10774000DF05157613A00160CD4BE267F073E7EC1F +:10775000EC24EA1E258B9383882D4CE5D8C0379EF8 +:1077600066DDA586C6359955F54F4E79A1319E4DFA +:107770006681F5D684234ED39590B57FF688C96C83 +:1077800010C983AAC94DAF277776C06D544E0297B2 +:107790004C755B552BE83FFD2CF3D6200563B48C6C +:1077A000C0BCE04941C0890D621C8B7F1A5B0AFE98 +:1077B00079BCEEFB766BA25B4AE5D92977430A4593 +:1077C000826509B85DC33438CADFD0C81E810E4F48 +:1077D0006B7FF763D8881E5721F772C2DBE8DB5650 +:1077E0007F3E7685226362C1CBB711634F49D2F4E5 +:1077F0001B6C9950E2144BA98F5D94C82DB5900075 +:107800001E962E1D81A5B3ADE579AECBAB93B0210D +:107810001A218C7BC4F70F37F3372A375B39A8A5B9 +:107820001A1A3D64F8C8AA28A0D70EBAD68B538678 +:10783000DE6980EA2C0D68706B6B3B6D4ECA45D7D4 +:10784000702ADCE084CAAACE4922B6C9C2FAA99637 +:107850001BC8429858CE599810AED43B7DB3869839 +:107860001427B4DEAD4FC50ACEF1DD1451DB9F57AE +:10787000C0471255CDEE9BD9377CF8A5D322E91A23 +:10788000E7723F8DA8F020FD750F98F5279AAF930A +:107890000509DB1A6659F583CB82FC853B69CB8BE6 +:1078A000E6D5BC5DD78FEB33C7C061DD8B4F090ACE +:1078B00088EA9B075F3118925D2AB5F8350E54A708 +:1078C000D0D465DE65D51FF0A74F4077353BEB047C +:1078D0005391E5BDB67A9D8A7FE87061236A10C72F +:1078E0007A913AFCCE4CB76EF0AC354EB17AA5C960 +:1078F00043453081533625876C0FBB7568E54CBF17 +:10790000AD997297530769996F6E43532E4062FB8E +:1079100023CFEA292CDA037D079C39CA59567BE923 +:107920002EFD217274CE4188BD0B0B6D316FAC30D2 +:10793000391E7E71AB1203023DF10B9F856502D7A4 +:10794000938DA6E4A670327F411266BA744ECB5175 +:10795000AF733FFC73AC04D86C836167FFCA6A4D98 +:107960009800D484EB8F7675F2379947D91CA9A873 +:107970001AB2E4B171BC033258F6FDC9C323C63450 +:10798000EA80DB0D5110270AA5CCF7F0C4523180F4 +:1079900022A74519DFFD7929EC0BE352BF67039855 +:1079A000E2DD13B1045956598A92B5134367A79182 +:1079B000152622DA154674CF996C35DF09138E9996 +:1079C000370B167EC7077064B3AF35A650973235B4 +:1079D000B674E429BB75A63DEA4F5BE639306B5FB0 +:1079E000A631EED86FDBC62B18164A73E1F0DAEA3F +:1079F00096699AFB8ACFA5375212FC229496B6025A +:107A000044DA886DF03161B22CA45C00A641CEA6A8 +:107A100024672BA0D0C4B387E7433A772A92861F06 +:107A2000F9546F45A7919F84130472F98302475458 +:107A30000AE8AEDEEFB21C05AA6662BEA424DA3BF9 +:107A4000DF9D56BC9234BC9E55AAB0068BFBA17F2D +:107A5000455C50CA2F393420D460B1E5D687870EF3 +:107A600049B5FBAF9AF75619578C21D4F51AEE6732 +:107A70003D723D62E0E7094324BB87EF62E1B0CA93 +:107A80004E3A2EB20827F4F5BD1F8B5D71982ACBB4 +:107A90003AF44FF8B183F7C0FC66487AC50CD92890 +:107AA00017CE643C31D25DBEADE6F23C8F2D2D6524 +:107AB0006C0269B3AD2E0F0669799CB92DDC801577 +:107AC0004248241BEB1F5F750DAC4F5EEE23F99A05 +:107AD000796DD9455D00ED5840E1CC359A03D05D14 +:107AE000C17F335757F5FF766A84528BB5C8F84586 +:107AF0004FBADD1E2BE8518CF94BE4C2DD93237D98 +:107B00005B4C7E6C7FDEE2B3DDBCE003162AA08D09 +:107B10006C44DC8D67A15DE90C559E329D8E869983 +:107B200060DF4ACF5E002005FEA12FC41094B28F03 +:107B3000D8A2CBFD686B83A7880DF12F464464CD96 +:107B40002C65802792F4900984042556FCAA2230E3 +:107B5000B596FC9A9AD9AD15D66D58A235E5E33C99 +:107B6000BEA058D2A6A61B6F62ABB5D33B0E559DE7 +:107B7000E9FF67CB8F405DA662FD2B618C6EAAFB8F +:107B8000E159FF3D7D5A981F88575D075AA5C433B8 +:107B900032F370C8A8352DD54CD9652DE1E133FA03 +:107BA00035B0273C3CE2723EC2F44000D7EFD52D01 +:107BB000E095508AB312CC7E2478D0C6B3C21C0F95 +:107BC00012EC6F82D1C8EDAEE0AEEF8021C7891B09 +:107BD0006A7935DB9018BA3EC8C50FB97959207556 +:107BE000130255FD59EF24BD4126874120F4F54786 +:107BF000FD7703DBDD50B003E53554890CF546C84D +:107C00000E766E362AFBB5FCDFCA364D8350BF18A0 +:107C10005048C2C51D2C1375EC9B58F215FCD86E4C +:107C20005F2BDE973556232A5AF0E849826DC9A5A5 +:107C3000617E8F4B34EC170F8C345CF77D2253360A +:107C4000B6FC6F988E36C29ABA55AAEF149E4F9022 +:107C5000FF5DDB3D88D5167529C94A9001CAFFB082 +:107C60006FA52E27567D3764328F7FE105D023958F +:107C7000A4047A83BC0AA4911ADFFC4EB34D0F4EC4 +:107C8000958E4674142FF23899F298BD5D3654469D +:107C9000E5796F7A52FAEC76B044EA6B31ACFF9D2D +:107CA0007E18DF1B24CCA0BB05E03A638D15764C13 +:107CB000D9B2C990FF62A93154833387D6E41890B2 +:107CC0001CE8BD15C200EE1F4586574B4F5D3E0BAD +:107CD00009273DE75FFD4E602EC7C00306EF931BEB +:107CE0002898438EE97C4A392854CD52F10BC62F8F +:107CF000804BBE9DE3153ACBE194B105B287BA2C17 +:107D00005A93287582BB7AFB99EBDE7B9D06624A0B +:107D100079AC7CC1F06F6579EE2EDA573239BED07E +:107D2000C5F8EE357AA9EEA4065936DEFCF2021447 +:107D3000325A2493D46371A30719A6F4A2C8C5C606 +:107D40009BF7A61653B8C1C47728BBD1C0D4FDFE9B +:107D5000EF90957DFB43587CB512E7282D28959927 +:107D6000EBF1BBCCA9D5D301B5E5130D3FDEC56F53 +:107D70008140F80E192C789DF40E7F42897C99B9C8 +:107D80001E784020FD22906E86D3F2198BBF581AC0 +:107D9000E00C8A13385D272B2D74F5BDB85B46D8EF +:107DA000DA1FE6DDF9D842F9E4E7724A740C0B6990 +:107DB00047EF1A1CE13572D2F6799201CA80396F09 +:107DC00066928ABB39871CED8DA718045B5C7D57D2 +:107DD0003FB6654A29288D3E213A66CAE48827D5F0 +:107DE000630ED41AC408224BE8EDF3E87826685EE7 +:107DF0006178C0F3A0565CB3477E44BDF107CBB5B4 +:107E00003EF0DCA86AC14D208CA39259BCAD6D1C1C +:107E100079FA4091DD0D092DC0AE799A88ABA77F24 +:107E20001DD2106096EBD888E64B1EDE4C83D5E65B +:107E3000E075BD2F3D00319FBE66035D522CBB7FB8 +:107E40002CB710E200C8B31D27783A0A07614BAD82 +:107E5000A39ED5CDE71B1A45278CB0F77D6CF43770 +:107E6000FC4FAF229673828C8A965AEC5BA0045C1E +:107E700016DF199DAD69ECFA5FCA9CAC38807504B9 +:107E80009C8633D613A044874758A99FF19764A6D0 +:107E9000A2B0DCDFAAE9720B062CA5B7C9476CE0DB +:107EA000647AF9454AD3677FB530377F5650C1D2DF +:107EB000DCC5DE6E1D69025AB2173BC043C0071D08 +:107EC0003F4DD230305A5776161C40C772825871D7 +:107ED000A8FDF023539A6EBD78AB41FEF023FD84DC +:107EE0000F016C2EBB345C86AA1E801BB95A09AFE9 +:107EF000B1D545746E6A3E3F5B85E2BC8F45D98F34 +:107F000072B563E82702AA7BA770BA0B3E869A91E6 +:107F1000BEA662F3A44973867F2F30EE92CC844BC9 +:107F2000AFB6BC8CC84EB5C16471554607D436EAAD +:107F3000A6AA9B0317012D91A14D1641DAAFA1E925 +:107F4000CCE3476C88440E559C4BD191A3468B12D1 +:107F50006388B3981DE7C73AA47E2210008D813351 +:107F600037DE81ED407E756133AFAAE54D9C2DE093 +:107F70007C21D55592C29BE70177D8D538F27B0199 +:107F8000A7867D5067B8F00A458C9E26DB55B1D197 +:107F9000688952922D3ECE434F338203B008CE3EC5 +:107FA00013B7C5CC7699EB445597A9B14408776DC2 +:107FB0009F0E3C24E02BC592340DC6DD651D54395F +:107FC000F99335F9A448262BA7F1B2DDE9B14C4865 +:107FD000159296DBFF286A42186EFFA485FD26B431 +:107FE00010B9515144C631E0F5ED02207B4E808638 +:107FF000A4281F4832373C355DF1949712DD634C5D +:10800000D4F250716421115DD7E93049F329085841 +:10801000499C639FFDF1BDEA7856B114124090BCB3 +:108020005AAA5B59407F5377ECE1AC25F9E95594A6 +:10803000147BF76DE0CD439EF0780C37CD602D4773 +:10804000DB5CA12952FA32D0F4B47BF7E1F3FCE017 +:10805000DE04C789643309D9A6B22E64223B807638 +:108060009E113ACCDC29A00B9B9A082E9B004AC695 +:108070003B76A3B6CF74A0A27BA342C3FAAE6E3CFC +:1080800058ADC375855CA08CF09901950621630DF0 +:10809000D943EEDC5596C73EED7C6203455D8674A0 +:1080A0000018F41CB567E431C4085D0EEF472224C4 +:1080B000B7397648577B76D99ACFDF54D2715B4D6A +:1080C000F2331A1B2CF7EBCC70E7AA60ED122518DF +:1080D000923DD9226FF7E3702EDB9404A79D8AD0DE +:1080E00057504FA65FD70D1C51E847DFCC576D9D09 +:1080F0002358B1BD63DCCBF7DFF1427704CA728647 +:10810000C0FB7FBF968B5792C35271EEF46D60B681 +:10811000DD77315503B94E87556E705AED67C62F1E +:10812000B69997DC0C09715257407DB87A5E20B73A +:10813000B6AEADCC414CF08E14C523DE53FBB75820 +:10814000C9A733801B14AEF03722304A52B04A3CE4 +:10815000C2BED49C167F796F29D7191D32DAC0BEF2 +:1081600071AF2B5E831D722507FBB79F4F4012D75F +:108170002BA332BCCD80423EB1CFA56D75EB77D439 +:10818000306D00E15C7421482E1AB05BCEBB9225A5 +:1081900051324E48590ACA6E2BE62F19837853EB99 +:1081A00042FFFAB7B75CA4DECF9600C1CB802FFEAA +:1081B00092D77ADE559473BC05804A31AEC27D6A8F +:1081C000796A97A4058BE60FEFDB6442312427F12F +:1081D0002C4A34889D881BBC105DEF16A883DA50AA +:1081E0006453B1FD67E8236E6C7E5DA6378761BC82 +:1081F000F33092ED76F11C45D663699CA39048F864 +:108200001026AEA4EB16449FB8662ED1F67787FCF5 +:10821000C1790AB0B4BB6C879966270B84FBD1F097 +:10822000C914D08D4BFC00AF430F047F7C3F5547F2 +:10823000C8DC1F25DA4771E7C49F01C8C414A4D065 +:1082400029A04A0AF65BAD64A699C9F4F1D40A4B99 +:1082500048ACB8217B84627418F75AC12039A1D880 +:10826000F872A8CD2F36C0CDA457F0EEEAD886C25A +:108270003CCDC8E12AB3B8E855BEF87748ABD63252 +:108280000F403A6FE8FC41D89039DB5E02BD27CF42 +:108290005836E923F57F979A1E9A741075715D26FA +:1082A000A547571E3339F89AF858D7C0C722B58F5B +:1082B000D33E91D581B0C7E67B422CC5BB70E3F3BA +:1082C000574F7E53DEB590FAA674D347E3055B4E55 +:1082D0007C45F7AF4392FB2BA0D9C8EFF883EAF2B5 +:1082E00032848582735D525095A8468CC6CA9389A4 +:1082F0009CFC537A595152CCAD0773B9E7D64599D6 +:10830000E16F9E300E23D8B97D22A4329D3420F532 +:10831000399D606E4BF7B9FC48298587C7ACA85CCE +:10832000D9B6410DC6F33A6E5E582659E9867E1ECF +:108330000A24D847CE27DEEFBD62FA30C64874560D +:108340003A5E3CEEA23DA4B13CBA52C6431543CCC2 +:108350000842D5A10727153A226E32CC00159B148E +:10836000C2869E7EF1BD52689AAC9C7EC3118DDCA4 +:1083700060F31B7A70724C00D1E00879F8C00DEF01 +:10838000064FF10C63D44B2118E6AA611D761CE45C +:108390004E2F68D3C08087F71BFDA65038D675E2F4 +:1083A0007B6DCE0BBBFAAF1FBB8F2597568B5478D6 +:1083B000B5D9C1B84D76B0051BF6A41FA727B79154 +:1083C0007BD413092AFBBB3C86A230129BFF06D745 +:1083D0008C18EF6278543DE6B536CCAD6BDCF278A4 +:1083E0004072A71C113E12741829929377BBF7CFE5 +:1083F000BEE26C399429FD9763ADEA5576555BB3BF +:108400000649781D83FB33626CF9CF6371F32670E4 +:10841000F653D6353B507A965D69CCED05E505659A +:108420005C27BBE51393D9A78B09CEDF5099BCDC41 +:1084300020B0CD2E519E269E89BA3AB9AD90FC93BC +:108440004E1E7AF8938B3FD4211C18EB4F319E417E +:108450008A99E3367EA67E144761B7B2A26D2823BF +:1084600041D4BDE277BF4D99FE7F345777A86B7A30 +:108470002ACCE9DA3ED0DA097403C735CAC37DFDD8 +:10848000C1990B6E66307760BB83EDE0E73EC0B903 +:108490007B5C990663F388CE461C02D01F8AE0EC11 +:1084A000CF88B2BB9E7B12D5937E90A39298C16871 +:1084B000E89D152A2063201C4274F86346B759B81A +:1084C000FBA148D3136CBD187B41E64B534B637F34 +:1084D000F203FE45FF64A6BF85B9E0CCDDB79E6719 +:1084E000AF0A8C6A8B80A44710C217E89E4EE576CF +:1084F00016D3794920BEEBD65C4B52009E1C8D7C76 +:1085000081CE70D48D0A55783E3A52C9AC2E38359A +:10851000C253618AEA01B40B0B1D4694A025EE2DCF +:10852000F344D433B92A594C30D687D60EF2F3F03F +:10853000342066A1A348A0FEFECE7ED2DB4997D9A7 +:10854000600BD3FD71691D8AD8D8B9A5E65C58C502 +:108550004292B43E371B45179D7D3E5519AEDA5306 +:10856000E54CC99C92657C0BE0FECCA843F5EBBBC7 +:108570002D51B7FCE67C71D968407A9FFE5F037489 +:108580008CC28C232ACC5173B2C9D124430A3BF04C +:10859000FCE9D00E3CF23B5A83468D59513EB5E37F +:1085A000ED4FEBC0B91E67B7CA72DDEDFD633FBA90 +:1085B0006CBF6518B7453944998774757960BFF603 +:1085C0003FE4FE7DE3D486F315B077421407E988D3 +:1085D0002F2B7FCE74826F223DAA8964A65090EC27 +:1085E00056A035DC3F5F67401F7D3A1BAC4D465EB1 +:1085F00005942C92A3C597E5FAA9BEA0DD402104FD +:108600002D13DA42440A05160D277043D685CC99FE +:108610001920B7B6DB9AC0DF4F42AFAFAAF209E626 +:10862000D30FB66266AE5BDBE41CB74CA05F41DAE9 +:108630007E44883AFC138BCE55DEF567191F9D6882 +:10864000F40E79810B90A5BE73B03C98DA47EF7FAA +:1086500096FEBAEB4D93561B2954F37B960615A54F +:108660008B8CCAA38107923F2920F60857B71EF5C5 +:1086700049E0970A0B0BE03408B17A2168D25CAD6F +:108680007F4C72BD3D09CF9F535BCC092AC9316233 +:10869000BC9D847C0AFF410D0434A71A6899725866 +:1086A000504225CB29166394DEA8EE9C10ADC3A5DD +:1086B0006FBE33427DA4248FB74296F14493F9A351 +:1086C0000C353BF6849DF58C3A8B681BBA28AC6A56 +:1086D000FCE6AC8B4AEBC7FECAA0BD22CADD17CDB3 +:1086E000498F86B0E92874BA2394FB6215FDF46FB4 +:1086F000658E4CCC8094E2D45B263EDAA18B2100BF +:10870000B1A7D9AF66D021A1FF2201BD96BA3559D4 +:1087100087D0256ECE319EB0C213D9B861DC3580CA +:108720007EAC96CE206DF950E143D93873B976907E +:10873000565545BE9F9D5EC11A4125626AF241169B +:10874000478B6860ACF2F217935366E61EDC10E5C7 +:108750002E24A2A2C327D09CA36E8F7C53ED0EE6DD +:108760008B5DE6F0AC1769754A270F9DA63C2CA7D8 +:10877000850AA2949FADB0B38840B16F6838E553C5 +:108780004C76C257E16761FF938A1A96F7E9F3A81E +:108790001226D249C91E40DAB5021E8A89287E5C9B +:1087A000DCAEAB4753F9ED54192CA05D663B6DBFB1 +:1087B0008BD45A98C29DF188BDD14BD2BF664A0F67 +:1087C00094C587C1B0C5CE14AE9E9F5111F42DD271 +:1087D0001986A2BF56E3A2F9B3D0A4111DC2589ABC +:1087E000D38ECEDF3110A51CEE6D39E6DD718A1512 +:1087F0006E67EAE2F9CAD73A5D8761AA9C8A9A292C +:1088000040AA5C330424AA7F4223C93911A49125CC +:1088100070410299CC063B062BA8FE7BC5ADFA023F +:108820006EDEBAD65A63D38CE29AB34DC368351C58 +:1088300088F7585152229380AB9E77E7464734E041 +:108840004C2BB9B1D5DDC4338608217C8C6B8FC825 +:108850005775ADC7CBE2BC4106EE8A9AE86EC814E4 +:10886000D14918E93FAB9392EADEE159A602BC0078 +:108870004A15D604F420CFF6F5D975F69B805094AE +:10888000939CE51124444B01C65CD374D4CB9E0267 +:1088900056FB8F7EACD78C600F6A62E27EB56CF3BC +:1088A000A1DBF03EF5D260B75288849BBBAFD649BE +:1088B000F6AA2B02147D703F3E530C78F0505C7684 +:1088C0003B2F3962758E7F88D728601C9F0FD0ADF3 +:1088D000EECFDEC7CE89CAADCC2A865A3425A05148 +:1088E0000EB544D61513AD2C104127CBC9C7874E02 +:1088F000C2EBD3E3644A88773CE36AA6975F2C68AF +:1089000060555EF9F009C633782040CF50F7423207 +:1089100068E955B0EB0F15D1E5C08A94E00B707C87 +:108920007CA8B2EB03C72CA966CB1C71669A82584F +:108930007353D05196EAC015988643975DA19A84E7 +:1089400065750FD424F24804F630341AE6C2E956AD +:10895000257EA810B624D0F2E1F9DF717D979C3115 +:10896000271FCE8DE7C7249AA671BD79D7D67CE2A2 +:10897000E91866205853BE5A2BED560B21A36C2DD7 +:10898000BC4519956E29ECE3DE06755BBDEF3D90A5 +:108990001A1667A2FCFA6F25A3D7C31A1F739D5E30 +:1089A000C4A63ADF972CEAE3DF371F90A24A76BAD3 +:1089B000ED78A594042CC2DFD56618380D955FC8F4 +:1089C000125191B5E79822B0FF20880A2E606366A5 +:1089D000CE9A871F1CBD51BD87653E6C3AFEA79499 +:1089E0009B4FBA46B6165EB192687CFBBE25D98C09 +:1089F000D9FB612E75F8C2A433F203A3D35AF8F75A +:108A00004372BF72E2B1F54DD8BAD9F4308FDBDDD5 +:108A1000CCE73565B1603891296E341DCC0C5FF21E +:108A20007F486823E6F702E7FC32F61D4A410CEF67 +:108A3000E4FF36EB0B270A971C36BD3222D7C967F5 +:108A40007163DE23354005C8B5BE525A3137968270 +:108A500054C95D40F2C18D66FE4A631873681139CE +:108A60009B549A6B2E74F42BFFDFB41F22EE274B1E +:108A7000A7BAFB648A2E234BBAB5D9B93F22A77592 +:108A800093D44C074286A1BB722DF561BE976BAAA9 +:108A9000C0A4F7F0B19903CC0138512FF48DDDC893 +:108AA000C74EC5C8251FAE2EC338898C8E91A50E22 +:108AB000B4304106B5DF2992949269F34AD4729F8B +:108AC000AB74F099A7B42548B945633D061DE07A1B +:108AD000C23715A0022302E28AFEB9561F32E8A16E +:108AE000D3A573CE96C46B03A427ABEE45EA92BC24 +:108AF0004C93192DE38B128DD2B52CC5945E683B37 +:108B00004D9F3CC9EDB36920CDB4447C6875A20F7C +:108B100009B8608AC1D4A52C16480F01BA1ACD4EE7 +:108B20005DEF2F5FA4F95834C2BF60867764B21F2F +:108B3000C50CD7D29249A97DB75DB97A944338B8AC +:108B40004EBF5A4CFF7FC9EAF0371B04973BB2FF78 +:108B500007839768F9D9E9D93D1C31689924B74C46 +:108B6000194C2B3859C7D7A97CD1F6E0C2CD274282 +:108B70001735CA0B85512893C92F62CC8A506F4193 +:108B800084FC5FFFD62BE12E8E419E4B9E78D94D03 +:108B900080D4812C0AE11762109FEA0EF18F95B9FB +:108BA000FB4B5B01362735B21D00B0015373CBCBB5 +:108BB000F43079E85FA671178974B03C29394C38D4 +:108BC000224B3DB347514EECBCDF37D17DF4B7C9E2 +:108BD0000B7350AC633C62E94746D51E8C09D5A1A6 +:108BE000EFC826B99DF8BF9C0A8FD15205A4F2A701 +:108BF0009216D0EF2A4B74DF6070277721B77F9FE2 +:108C00009DF1D636DDAE4B4749389AE79CF9A08EE8 +:108C1000E1796779E3EF65BE71EE671981115FFF56 +:108C2000A4F5DD1DDE0D690E0470B8043A05804D13 +:108C300077E0BFA9A3DFC48A11C338B624128677B0 +:108C4000773B3D00CB62E55482CB0F50608E98CAD3 +:108C500017AB58297D469CBE21938F26BCAA9AB893 +:108C6000DFFB203B1BD1D27E548F34F24FD930EE44 +:108C700014764B091D1011A28FF48C4FABDD2EFE24 +:108C80001205C0ADA3B90796623F04AF2C5C316DED +:108C9000329C6BC8F0CB0E5AA053279A1AA3270D0B +:108CA000E104D26324BC3A4B4B792975EF89DB3060 +:108CB000D965210240774FEEE67CC20FFCE2C63F49 +:108CC000E570185755F5A496869210282F9BB6A8E4 +:108CD0008CADDAFBAFBD9AB1198621BA569938C569 +:108CE000FABC27E1ACA125445137142CC1D3752E11 +:108CF000C363BFCB9F5B6CC77E673D327117C58076 +:108D0000C61EF81110A453A45F1464CAEE54F53CB7 +:108D100006E1EDF176E3C6E945338D2E21CD1464ED +:108D20002536D2F0DEA7E2AAD55EAB553D3DD2FA9C +:108D30000780695990BB6B714A4F4C7255A53BC176 +:108D4000D5FD345215C7E2666B439C43B4E6F80286 +:108D500064DBB7596A12BAC58ECFA81128F74AA6A4 +:108D600069C13BBE48CCB2FFFBD5A2A21D43BA48A5 +:108D700070ACEF46066B5299D002314550EBBCB453 +:108D80003578FC223F83FF2F277D14331F14B086D4 +:108D9000BE29248CA7E1DF1C5141B4D806D9A4A672 +:108DA000EF7C0249C5281E29E0D5DEB7EB304F32F3 +:108DB0002822C588A03FACACDD64CBDA7C95A0DE70 +:108DC00071D774E64EDD3296C1D2A3A7D259820D77 +:108DD0005B29A5476965607B56B1FCD83436E888C5 +:108DE000F824A0CA9895397DF3055A1DCEEB4A1098 +:108DF0000FA1945C5CE527C6B0CC074102D28DD8A8 +:108E000065FDAAE0DC324CA54C60F49910B1320D3E +:108E100001E192541DC9010DD0C9E4129A215F9A53 +:108E20005C08D831C7887E8094616509082539AC13 +:108E30003ACBF19D5F6158DC5D904EC680009A424E +:108E4000E9BC775DDB94869A83494B4FB6FFEFDD33 +:108E5000EF2715ACFB36E0444009A5A48A310C97F6 +:108E60000CACFC2D1CFC7FC6977B57F815175B17C5 +:108E70001E905BA7ACADE996C8D05F614690F01339 +:108E8000428A1ED88A0C01752937AA1E9C9316CDDA +:108E9000FB71D62AB7EE71CA814765A14A8BAC2D0A +:108EA000A3D90277F372DD638B6F46BF3754C8F3E3 +:108EB00086A95425E98648159CD7166682437864AE +:108EC0007B380E868DC1355FE5944B4F046927D6FC +:108ED000C4F5E665B80D51964B6603A4671A86F390 +:108EE000C31804D431FD4D324F1A2C96A37FE908E4 +:108EF00007362F7CF9B2DA3CC657A212D189364127 +:108F00008DD72FC2B27010A0AF4231E943A65150A5 +:108F1000E8AB6A94ADCC969FE3513B31D31C70B75C +:108F200045C8B96FACFE0FB13801FE74ABAF9E936C +:108F300092D6AC4A4A3DEA459FA5C286514668A8EA +:108F40002D20FAF4000AE82BC226D5CC2A1BA5B4A2 +:108F500037E0525A6F91F3E5205C2825B6292E5E42 +:108F600033BF7A4DDE2D9A8718799F32EE444B0637 +:108F700079395358EB419EAE8F7782930DB6A16E2F +:108F8000A490CBE9B1FC98E45E995B16EAF52D3626 +:108F90007F4FC5B84A52AAE330CF88045FBF7A3BFF +:108FA00077CFC180608071F7EA96F9752F631BCA8D +:108FB00041DA01A0D3334E1438D8CB2F34A54489DD +:108FC000CA79DA97A6DDD89F1CB4C8CD3E25E7E361 +:108FD0000FA91413F400027343473DC20D562641F6 +:108FE000FB1FDF7BF9812AF162C43C07E0B7313611 +:108FF00014E6F3C5FE15DE96F59B5FD253548CBE86 +:10900000C94398BBEDA0B41E28113EADA0FA05EBF4 +:10901000B02B93F434A5B36B99267EBF161AA92200 +:10902000F7BC86CA167BF9BAF9ACF1EDBBB6007D88 +:10903000B4B84889897273A910742397B945E4F7C5 +:10904000445716B3A923937F93D9FE9BFEBF878A0B +:109050004B2113ABE17AFAA2FB7278B356827131DD +:109060003952FC7B76A88A8749D73A998B0789A21F +:10907000A83BDB355FC213961EDC83AC0307BFAE93 +:1090800015D7256349CD4ECEDDFA1B96260D8418E3 +:1090900088D25CD67878A04BE65370E9610C855A8B +:1090A00053E5813D0BEAC38FD7290A64BE5ED8BA67 +:1090B000C604FADDE5D5A5FECC74A52119AE2F585E +:1090C000A7ABAFD51EA40EBDB0CC3B617805872BF6 +:1090D000A7D0803EE002724A786A481548EF0FF246 +:1090E00065D90D31502863F1513E4C732AFFF64C7F +:1090F000E03445672888A980F8C43173A3EDC283A2 +:109100009B0F28D47A425A8ED105AE508C7E14B96A +:109110007420521AB05C252680702A877CD1468A3A +:10912000D36CC05F4B5CBFC8365380979925D2EA99 +:10913000C73159D317FA529B9220C1EF769F8C4DBD +:10914000C8B54684CF7487389808357E01DEB3B43D +:109150005A62B9D8643339B04CE593A063D4EC9427 +:109160006BAA0F56F9897A452F49A8E001F276AD2E +:10917000992A3B288387C362A648954A9FE799BBF3 +:10918000E1BE60581AA8AAF6EA721414C395F67ADA +:1091900068FC4D96AC5A53A6E51D076F188B60BD51 +:1091A0006B0F77DF97A332B1142553D072D85C6070 +:1091B00079436162CF170C10180AD3647BE45126FF +:1091C0008DEE1B981108278DDDAB303E9E52265A3E +:1091D0005E420BEC354A2E9FFFBB4BFBF05F7B6E74 +:1091E00086415BB91E589CCF1DEBAD0F30D0C6D861 +:1091F000441AD7651BD1983578249DE9AC903A7A0A +:10920000865040D7ECF41AC25727D0B3E6B168F3C2 +:1092100051B393551EE1B495B8FA9D1F6188AA39E0 +:109220009EDBECE8C41570DDFF675CE3D167EF6798 +:10923000FAAD0420F11F432DC16A27D1A8594CA3D0 +:1092400075C353DA143FAEEA58C58A9E2F7FFF39A3 +:109250003E94F8E2EA209E9A0879041533E6381025 +:10926000F5D19EFCB4705CBD385A3C3DFEDF975D85 +:109270004926E58CEC0B675A069058710BFEFDFBF6 +:10928000C394393E121097F1E0569E5BC35A355F86 +:109290001EF04C15DEB6A4A79769EF24EB1F63D32D +:1092A0003382F86D1C247EC0B7C60EAC4FBE3FBFE4 +:1092B00003ECE97B279AE9D1C9EAD55D18643C2C17 +:1092C000FCAB1105D4624F743DEDA93175260F57E3 +:1092D000DDD3ED360C2423F167032DD1622AEF9301 +:1092E000A7EA3FBF06AB0BBE4DC438004B2161BDA2 +:1092F000B0064580F8292133D39739A49617FDFD90 +:1093000043141B15C0CA377303111F32F6BD9A5898 +:1093100048EF5CEBB7ACE7A5B709D1CD0F8043159B +:109320002A2E662DA04A0E8C084140BEB0F2256A56 +:10933000E8FC4738397D0B6A3609A9E8089995A4F5 +:109340005B06BF851C1DFA5DBCC08E959AB0D9D94D +:109350000D9BB9D19690EC6E8445A5C959BF3729AC +:10936000D8734E4B4181061B63E46C22370FB293D6 +:109370001E1D91C7B858E4FDFD133513617FA3ADE1 +:109380009BA8E40E31CD0F179226B540A686FB159B +:10939000239B3509A5654C66FE8031044C545793D8 +:1093A000A69633D541F694EE876EA4F9385B0F9CF0 +:1093B0002C53015D78790CE729532356FCE2E8AE83 +:1093C000B6D8E4DDC6F25DCC591B6F6C4F3443B8A0 +:1093D00040CEBAFB16207070645FA117B0183283BC +:1093E0000816E0E9860FDDFA15BD6E40A9178B2639 +:1093F00027A5BD0D60F9430EE53750530513C1880D +:109400001D4EF5741ECF41C9370CC5A60090AF396B +:10941000F1EBAA03210577E4C68EFF6F956E5FB866 +:1094200056EE3440C5AC5A02BE06D899D2733AA75C +:109430009E93D8BA8ED18B0123DFBF0D50AE53352A +:1094400041ABAD8497B6BAEDF326D4FEC3FBC4643A +:10945000DEC1301442408A2492AE23AF0BEC120FCF +:109460000A2AB9F6CB231B6829735E139FEA712081 +:1094700032B7642BE35B47910676B0E9DFABDCEAF9 +:10948000E60F23F0C33CE2B5B6806BFE7D3B53B8DC +:10949000C4F6CA9245AE0B3BB99D842ACCDAECA542 +:1094A000406DBF887D7127C48BFDCA19B19EACFD8C +:1094B000817A360C7300B5785E0611E55469C67D75 +:1094C0007624520C21DAD8F6F5C8DD3C62BED621EE +:1094D000C703CAFEE0340493FF7399A5DAE6C69584 +:1094E00035156DAC089C7EB2B33CB68822AD67C121 +:1094F0005877EFB4210C4E717DE307149B91926E67 +:10950000BD59BB5B9291371D89BBAAF8233BBA04B6 +:10951000631C6CC8AB2197BDF54AC0D23DCD93907A +:10952000E0D1E3C1CA6909DF35BF2C1A15DF346BFE +:109530000A93CCE515A4D6088A1AD820285DF19E96 +:1095400014C98AB122CDA3AFBE2B804211089FE877 +:109550006AF1F177F773B6DF54B807B03D05974E5F +:109560001E023C7EED0128B789B5D9B178AEA88D31 +:10957000513715BE2243C00907C17B6F15F3B67E74 +:10958000A763B55F98EACC99D8990E27808A1A16F6 +:10959000851C66813CDB79D6E0EA30AFB5751454A2 +:1095A0003F85EB61AF42A4573A0AF3853BF9FDE9E9 +:1095B000F6C58AA575581AC747C465CFCA11A02930 +:1095C00041CA56390A3345F5A6D9F8A8D2D8FF5F63 +:1095D00015E88450255EFABB3DFEAAD1ED12A67BAC +:1095E000BC7BEC4BEFDA423894B6B8DC13877EB71D +:1095F00032FB5765C0F8F62F5D1EB477524200ABC0 +:10960000DF303E67D1208C508DE991649277ADECCC +:1096100024084553F48188E6DB72ECA02DDA7B9CAC +:10962000A7C265B94C58A9BBACCFB73C2B58FD8835 +:10963000B3F30AB3688BD12DCD9FB74B79F5EF22E9 +:109640006E81B19C65326FD5C391E8F980F25E0BF3 +:1096500098CEE34C3C641A615A825200F5A337CA93 +:1096600073E19F88A51CC52A95E2B5743E7A09244A +:1096700042D0819E84294744E39D8CDB71A8879E5C +:10968000C25076195283FEF4A5A7E2A6E0302789DE +:10969000A0577EC1364ACAC5836A252ABE9C624A43 +:1096A000A586FCC9B94E9592378E676F98501D4DAF +:1096B00036682F1DA85E90D8ED1C49BF6D5CBA912D +:1096C000759D929711AAECBC9907FF8F74932ECECB +:1096D000B6B558EDBE718B28A35A3BD0D897FB770F +:1096E000A4EFB889602A1E8CE1DF73852E9F11528A +:1096F0005CB600A1D66D431278BC8C2CBAAE1D9915 +:10970000F00A8475D22CB2AC57E743E026B0122E93 +:10971000D1D0592B52ED9C83639155A30B602C0241 +:109720009DB8ECE64401872FD9F110C5DD1F28ED67 +:10973000CDFD5586D6971E2A0D41206735531EB2A2 +:10974000B805BFB59E6152373EEEBA70B31149AE4F +:1097500063B41870ED73D07DAD48CC2273E0433212 +:10976000AF343608A1FD1321A6A0CAA3B909EB980E +:109770000322192301D5970B970C7B5234644D7D3E +:10978000DEF3DE009D53D4529564BEF4945C826196 +:109790007D0B8F8D56F72545777A799163B47335B4 +:1097A000379723865F30DF35720E1BDC40A1999717 +:1097B0002C445F5917BF7C55067C4C4FADE43503F4 +:1097C000827393E4CB88531477335F16ABDE71DE7C +:1097D000B864AA6D134FA0824A0CF6378964F5D598 +:1097E000F1B9067EF0CF61696479457686D8DFFBF2 +:1097F0005F373AFC3795E5450031A84D8334F8C40E +:1098000009ABB7C27224FF5E5CA734EBD905CEB0BA +:109810000A54EC4440DAB0DA4F0FA18D1CC879A786 +:10982000600DE09A92B72F5D9002B81D2759AAD11A +:10983000AA9A05B447EC4739696C524D911D0A74D8 +:109840000DEF75D32E5DDE56EC7C718FB4360E0EA7 +:10985000E05785BADB23C7B82724EE8129E330D14E +:1098600023F8A01E0982FD395210F92F584827B954 +:10987000BE0EFC002699F2EC2FE5A4AFBB6E318939 +:109880001912E8CFA516B017F3598F40CB3391A624 +:10989000B3130100FA5F3B8E94FDCE27DF7BF724E4 +:1098A0008156510DD3A7B2BE2C164F67E060D2D8B7 +:1098B000CF641A03C11C4D8D5C1159D62A03365250 +:1098C000C286730CC4E995CE2A1FB2D9A7C96730E6 +:1098D00036B7C77A5C0C0E24D940F2CBDF2F5F2459 +:1098E0008DC32EE25135A6B6B13D361E13B640DF0C +:1098F000F2BF3FA222AB9AA47636A763551F3A1B4C +:109900006B7242BE028F4A1C53C4E41D497BE1BB0B +:1099100049449A676E63BE29C536D2CB007483D0A2 +:10992000E2045209DC2420A4A3B69840E98B8738CE +:10993000A696E424878403A1F15B3246D351547E7A +:109940001557D47680CB5B8DFF46ACD8622866D1A4 +:1099500012EC287E063B7CF44988BBF27C019175B1 +:1099600055AE7E202F4BB1AD8DED958D95EE17F94F +:1099700095320C9383141F9CE0DB561023BCBBFE76 +:109980001AE28B9E4793892A61CA869459B45D284E +:10999000AB8E444F452CA6C9B1D7F618F1EFFEE6C1 +:1099A000FD73291FAB8D8BB8045DA3D044C690BA5C +:1099B000ECE3DE7CB7E69A4971A9D7BE87A66FAF04 +:1099C000B7840861645A97BBAA021B167D78FBEB2B +:1099D0007FBD9AC452DC64BB0715F4A797B5233A40 +:1099E0002B1A3E10FBCE1A5BDA3C112DED1FE52041 +:1099F000F94F27E54F32C87DAA6A7B8463755616F6 +:109A0000922DF4B4BEC0AE712C9B518707DF690163 +:109A1000C4D07EE81267AA9661C4868C41AF3C6DC3 +:109A200031D1CC08135E0C91A76DA796F30CE6FA22 +:109A3000CB51E37DD85028C5813D05E8BC79383E3F +:109A4000E22524F99057500C4AB94595F705BFC156 +:109A50006CABC1CB53E2F426C752C12B95DAEF149D +:109A60000731CFFABF443BA6A07011D5723BAFF1CE +:109A7000EFE9D252AF7D01DD048CCC60B1FCFD1F5B +:109A800028834B59E2BFEE32081E48DCF1CE5D1B45 +:109A90002B369CAEC45D1F79D0A59BADF9AF593C68 +:109AA0003F94E668B0BD5E002A8EBB5A23AA77DADF +:109AB000BA0E986E923178437737E16A1D51A674D9 +:109AC000A0D1A09D4F0EE81DFE4A7E5535F8058BAE +:109AD000E073430CDBAD485D7B0B4FB1391016ECE6 +:109AE000233ADE52DD6589592810D3AE41B6870886 +:109AF00037F3DB69C6A0FD21BA0055C9CFF117E0E5 +:109B00009F3DCFFD5048FF205D484F5DFBF339C7B7 +:109B10003F8D44E7434C806DAE9B7BAFC378437071 +:109B20001E56BAB30E136C183FE16A7ADD99F958E4 +:109B30005A114C43CB93B2FE21B2F31F3FF7619B06 +:109B400040FA28C20FA85027BE9E9744D2DFEB6789 +:109B50001C1B7EB5B6334A0998D07CAC72B5124650 +:109B6000D6FA8E5A6112B37EFAC36B5B144FEFFACA +:109B70003442F779B657FF82D83DFDBAD76FDCA7DC +:109B8000CD6ABA30A8A23647FC5AC2B8C1E9B96B4F +:109B900002AA3ACF38BC9F6FBEB2699B5B3D751974 +:109BA000127E13F34DF945490A99414A1BCCA71B74 +:109BB0003320B30239FB3081E1E5C31FFDAFE7C9B4 +:109BC000A31367FEE2A221257EC0174FA2A106C003 +:109BD00085636863EBD39FB185DFBC48D8AECCC941 +:109BE00020EBC068BB2DBB298E109E243374EA7312 +:109BF0008E2B623EE265D360B8E22A8F37E65F8A39 +:109C00008A685DEE5E2D169B5ECD39862D08C2F208 +:109C1000CC584F73C1081585153A27F1FAB6E221E1 +:109C20005F42001B14A8F070DDA53C543D64A636CD +:109C30007B29BA5E53084450D7CA34EBE21C2D9DF1 +:109C4000153B69B56B23605D308319650ACAF464FE +:109C5000E5DCE81296851E11FC172C7BFC5C5B7220 +:109C600067B525BB906F84085B2C0A56FEB0592C53 +:109C7000CBC1E17EADE9A767271D7A30E35C74EFC5 +:109C8000EEE43AD1944B4845264CA84F2936209B08 +:109C9000B2379BEEB21CDD31125752E19E7EE810C6 +:109CA0006B3E4AAD010BA8EF17A762821474738054 +:109CB0005F9AB6F62C74C8BB6C2C3F9669F1AF5A0C +:109CC000BA0941070AD35118B21874D4ADBB265F44 +:109CD00040D2687ED65B74005D66FF11546DFB2F29 +:109CE000D45C717C384318377E93A1F58C14D8E38B +:109CF00043DC5A3FF60A2C7DAAA88B3E40761B27F0 +:109D0000C463A5F8D23FF81ABF8E66CB3EA0DF0031 +:109D1000CF8E9727D4CEF424A1305322FBC3847F67 +:109D200077CDEA0ADC72D65975E845F75C4A6E8849 +:109D30004BFB8AD2841B35B045852332B17FD3607B +:109D400055186DCE3CAC72E6DFFAFBE874085DE9AD +:109D50009B892C2DCE0BF4BEA43F9314E79E2A2999 +:109D60003988BE222B5C66819598E5643DE02C55D0 +:109D70008B3029E9D1F4F1F822556FB3DF3669DA77 +:109D80007B9CCB0CA8E36A7B977AAD669988AFE39E +:109D90009B57FBE5EFB7F615E5246B796E272B4251 +:109DA000F2BF587F364C6DE783CA224F6B3940842F +:109DB0008BBC8F3F59F6B274AB74345A8C0BC59F71 +:109DC000D501A76C41FC79CD4A0109092B8F1C8D67 +:109DD000C081E225999DDBB980AD52F0391FEEBC00 +:109DE000CA28F0E56989763E4E6183E2E533C90D04 +:109DF00040C55B5EE5EDB9DAF5A549C58376EA05B0 +:109E0000A31DC0147D757F42585E77EB1CA240F005 +:109E1000176646768E0FC49BF55865496EF0EBA326 +:109E2000FDE17D1956B1DBA20F4412E2A404040245 +:109E3000B6E83A7641F8726A5E1BBA1F129C35E9A1 +:109E4000F689949FD130A36D1CB3325BA69B5B1245 +:109E50003CE749823990F28B8DDDAB7E5691C6FA94 +:109E600022A0C36EB7A49ADA94D280FA4F61A0AE52 +:109E7000F9810DE78E51F7E9BF96C8CF8E815B2C33 +:109E8000EFD1929DD3F939D2D4B48D861742DC9D9F +:109E900074A7941D59605D928A6B333F9C0B674693 +:109EA0009F4AE451C9FCDC8B9EEF84248EB6F4F308 +:109EB0001B5CC56A0A2678455C0A7092DF2CBA4F93 +:109EC000EBC8573E75ADB59E7FF438C7DE81108470 +:109ED000171774D5FBA127494C20C2E879FC920FD3 +:109EE00083011DDF090427FFD9A676D1472040FE54 +:109EF0004924E36E88C2958E0A3532EB33B1D3FF25 +:109F0000C31DD2DA6F2B229B8AE23BC808330AAB0F +:109F1000F072227F045644BE400A4E31DB3BCF4CE8 +:109F2000CB61E321C9F4C15E2F750B51E7AD06C8C3 +:109F3000E878346E44537D87E6D742457D3ED93E6E +:109F40004691EACE05BB95D8E5D77D9CCA4F52B95C +:109F50006FB88F6F76BC0C66C131E5576C0DAD5B89 +:109F6000968A59E824D7CF2474E1EC2668F7C238E2 +:109F7000D200A2609B0D148811B9143F3B57F3899E +:109F80006ABE82F4846273B524790EE55C19986226 +:109F90003B5339FEA6C511335198F5051503F3FE61 +:109FA000035EC479A28AD4D93CC2712A5E928C82A3 +:109FB0000D1E5CC59D2BBE3AD1EEBB97E8069C09F1 +:109FC000C359A1BBC1AF0DB52746A14DEFC684E56E +:109FD000C8335A81EC6EF3AEC2D99FD349265C27B1 +:109FE000E7E9F2AF9BD4983C8549E33EBBD3D5F576 +:109FF0005E12D2E95378C083CF04D19BA8AD38DE7E +:10A000002CA3D5A4FAC801B91AB82DCCDBFD1BC509 +:10A01000B634B68BA8FAEBB24DDFD98F5033F10FBF +:10A02000C859DDCF7FC0FE5C1A1EE9443726EE3AE0 +:10A0300038FF2E3859867036553D22E782B6B85F14 +:10A0400082E5D26EC8D87F74522EBB3FA6F467CD8E +:10A05000B7E9527B4F4F5924A9C5A2F594E2A89BBA +:10A0600063363C754F2CBE07D52A7D2CF7C6F163AD +:10A07000CD30311212C52E477E6406B6185BCC7700 +:10A080005765BEB524846853942CAB50158E358A21 +:10A090000FB49EE9F318255362657088924AE9244B +:10A0A000DF1C5C219834183907FC6715E451FB2745 +:10A0B000D44A8E327AFFF8BB2AEC9DD6C4E0C23B6C +:10A0C000F41495749FD6351B8863D0766FEF68CEF5 +:10A0D000AEC08ADA31BC17B0A8EAD5684B99A17333 +:10A0E0000B675CE379E9D2CA1F538A061C7632DD1E +:10A0F00099A8E82387744AD38CCD11A2DC1303DE20 +:10A100003C862E147A6992320145656D2940E2320F +:10A1100056A51417E0BAAE62B567CA40FA900A5065 +:10A12000E0DB7053D8C320A518989F35FE7249759F +:10A130007E90F4E1E74064F03E712D98BAE0223160 +:10A14000C18FCD347EE6772BEB043C731E930C4518 +:10A150005A9001FBA69BEC9A36398891383E17C27B +:10A16000931FFC9A66C4BE94B4E615DEE8189432D8 +:10A17000B3FCD0D75516B1D5D381298305473E1CF2 +:10A180000E330DECD15ECCCCE1F9D8407BD8E88F12 +:10A19000001B3E8AEF11DED0841F2054522F1ACFAD +:10A1A000A07DE51EF363D3A5A31BDF6811F88067CC +:10A1B000B0A1160425F5F6ED77A3690704A55CA503 +:10A1C000CC1AD7783F567CFC646928CC3616208997 +:10A1D00023CBAF65A4026329FA96200F6B07EE8F9D +:10A1E000C2DBCC9C8E048E5A1F82E44C402AAF3BCB +:10A1F0003D9B44CEE5B8C1989C7E59BF84F541AFE4 +:10A20000893EF90FF54D0694B43F35E173B571F30E +:10A21000D9658B65E45FB315DCB51E21E8D5292629 +:10A2200001718800DF595BA9E426DE2BF4F8240BCA +:10A2300078BC80A07860EC09E36184BA04A2364758 +:10A240001D96522DD049929640C0137103566978DD +:10A25000218507EF163818D80DD76B5DAB29C801DB +:10A260005F26835191404F69EE09EFFE4D24B76E92 +:10A270008BD7FC43F340D1C8655DAF23875C61F0A9 +:10A28000379661836820FCD805FD5D8EF365DE3866 +:10A29000084372636C78C8CF048D020E920DE10CF6 +:10A2A000EE9A08207E58F450EB6B20328AE5D952A2 +:10A2B0001E023F1F687C980C453B3CDACFEE794A82 +:10A2C000EFB9F5FD560E9DF7FD6E5A5D46AF97C48A +:10A2D000ECF83682A407CB594D8A39624B118D0BAD +:10A2E0001639F0B5C7D5801C4F36BCC973EC7AF768 +:10A2F00020C8EF3C466CFF26AB58E5F62B73C40D27 +:10A3000019D867B9CEA152144AD035B5395FFEE0ED +:10A3100090FB55503438747D0293B991D89E9E1AA3 +:10A32000D7B6F90D5E869EE39106FD2CF0157D559E +:10A33000EF55DADB398D3E248935158D6459E93EB8 +:10A34000A8A424D0F09FCEBEC182B0FC34E818F897 +:10A35000A87F071F1E02CC967EBD0C3D74D1EC93E6 +:10A360003929D18335C6B4DEBAF7F11073C830ECA1 +:10A37000F89D23BAC27DB683D5D1B8789009D4852B +:10A38000FF5E7969DB433E585AC9A4DE6134FBECB9 +:10A390006558ADC806E62A84542B87A5320FA7BF9F +:10A3A000CBEF782E45D5E58D47DF26B9EF3381DF3A +:10A3B000A971AE6955F9920964D0930FC0BB87DBD0 +:10A3C0005A5BA6408A432791B99E6639D249E8E193 +:10A3D00013C521BF8AE03FB6839D302A70BE1B762D +:10A3E0006F17BE398160EB2CDE100710A52FFC68BB +:10A3F000D2DBDC4A6189D6E79942447AB292E09D89 +:10A40000947413FCCD6D86C623DAD8EADF2BAF5DDA +:10A410004C211478E9265BC3DB777E29C76BA26BDE +:10A42000DAF2C842987C0AAA57D52E81239F74235A +:10A43000C90C0432B3621A80697A2ADECA0CB628C3 +:10A440007492E80D575F94CB61430C701325BB0BDE +:10A45000FC17986979FA955B30EC9B8276FF00C116 +:10A460003A769B248B696AC7C69C33616261A1B648 +:10A470001698D28F217A01B7E5DAF9A7EA39A2C591 +:10A48000E23DD2F15E13810F001A693E986B5A9932 +:10A49000653A17F4CD681BFB2C085D20C0A78562C8 +:10A4A000745C8D1CB07A46142691D1BE24A2CA6F6A +:10A4B00073864866824ACF130CFF16008A2F906875 +:10A4C000801B704C13768E33D0471A2723409C286C +:10A4D0000382E4C791CA47BB7155930A4E48337A49 +:10A4E00016957029E1C392BF51FE5F1F0F4263AE04 +:10A4F000B0C268CDB817D19AC5AD76C49ECF4B9D7A +:10A50000452190CD64C795600706D7DBCA694437FB +:10A51000FE609B50ACC9CCAE74915598C3C9A8A736 +:10A52000317BA36E2738FC5F962138336EE30795A5 +:10A5300066A4190EBE8F215AE9B2FEC7E1E975C2C1 +:10A54000DB0CB3BAE7C3FC33E58D71E2D9F2458386 +:10A55000AC6CE1891A1B19BBF0C0190978B4192732 +:10A56000EB936EE26493F18DC1A3FF4F6CC1C056B3 +:10A570001E075118FECED605E0BDB9DEF9077E27CD +:10A58000A09410215620C967EE6DCD2C1F55A5F45F +:10A590007FF6ACAE29D5FC0484713F68D2A9E03FB8 +:10A5A000BF8490DE2C1360044F9C09567850FA73D8 +:10A5B0005106983E07AC109354D1AB7B456276C3ED +:10A5C0007FC116E18315FB639F8A821DBC1898B476 +:10A5D000C8EE3EB5F384F61C6913C001515F19D76C +:10A5E000C6552DFFEB40A598597AAF6FEAC19C91F3 +:10A5F000D4F4D0747E81180EDFD52E127BA8E07DB6 +:10A60000110AB3E7DF4E6E68FA36166CE74F9A5FB1 +:10A61000B50BA6C01CB6183C9A4044D7EB725F8DB0 +:10A620003D4BB02115ABBF6A8213D880E0A649DD4F +:10A63000B3A563C78772AE5CBEB1AC0F593C80F066 +:10A64000C1FACD06EAC2BDC90CBB9FE0A932FE9C8F +:10A6500015F0246580C9C11BC7B80E35E4777F3873 +:10A66000EDAF36F48481A9A7F0E5BE1EC600303AEE +:10A6700067C0BCAAEA021912F3D576938E860991B7 +:10A68000A23FDD645D2E8F775343DD1BCDC358E7BA +:10A690009A8F68E144B4C375271E07861475D9AA3A +:10A6A00065988F73A481B78C87BA1F53339B7473DB +:10A6B00021BF8712F04352802705224C710E6BD6C2 +:10A6C00045036238FC0B85CD36C53812E987E21F99 +:10A6D000B5640A62FD1289E858EEB71859EA1806FF +:10A6E0001BBB422E6717B87366ECADAD4AC3338609 +:10A6F0002511BEF17700DE9EFDE4408A364A4B15F7 +:10A700003D553702CC6996EDC570F9A94E890F7099 +:10A71000F7752DF8F50CC1B4558B3B319698601F39 +:10A720007CE36A9E3B0E719FBB79859174A44D803A +:10A7300057862A46064A9B9160A3B79E1BD9ED2BEC +:10A740002A79DB6B90BCBE95499BC60D73F426D469 +:10A750002F4208DB6AAEDC1606E28DA49D4E266809 +:10A760007067D07B3CEEF0033311B9E6D5C267DCED +:10A77000514C971B2E5332B551BA4902AE41CDB55B +:10A78000775B66B737D2079149C2C96706F6575754 +:10A7900003146ED181BB010676EDFA4DDE26FF6013 +:10A7A00086429266ABDEFCAC166F90A06D14DEFBA9 +:10A7B000423E659D12A1715FB07C67E849C566683D +:10A7C000814A9FD2EDD8C7488BF02D6D094D97EE89 +:10A7D000BEE293808464C0689DD4D7C5FF0EFE8717 +:10A7E000C752E2867DA0CF0A331767739B449E55FC +:10A7F000FE22B9DBF4FF66EAC908E7D092399EDA97 +:10A80000D120EBBD736FDB149CAB7729E835C1F326 +:10A810005E40EA16BA2DB5C85B2C9269306F812371 +:10A8200079B5E6EAF55C59B2C144690011780F1EAA +:10A8300067DD78070494A68D4EEF4BC02421B5DB6D +:10A84000DF9C41D9803C442CE7F0DC9914D8764059 +:10A8500075D2CC96422D3FBF29869394F1F29E7219 +:10A860008C0E224AF6C932F7EDDD91F047BE429DCB +:10A87000770602A1BE57823576280614418BB58132 +:10A880006D622AFC72BFBB09038CC4DE5E63A9D073 +:10A8900049EA825A5CE8C4F9BB8718695CFAFBB3E1 +:10A8A000D340A37E65112411D68B2213E64314D91D +:10A8B000FB880C21210AD6241A51361389671959AD +:10A8C000E65158035075174F9AD0164003CB459F59 +:10A8D0002B0F824412171E77FB5C2F91852E6AE89E +:10A8E000CEA1461A75B18D77899AEA6B6CBEF33F9B +:10A8F0009349B10A20254CDE951ABF73D5471864D9 +:10A90000BA23D7F26361AF607D333054A5500FC1D5 +:10A9100031437994E6DD3DD29821AF956EA0C6A76C +:10A92000EB89D30FD2322742CB513E7A81D6FD3C00 +:10A93000DC03B74F569CF207A3A7DD306DA1413968 +:10A94000443B60889E43FC0B1405C40D189373852B +:10A9500020845B0856420C7ADA123C4A61A73E3FDB +:10A960009CBEFF7BB869DB420304D7389DA25E140E +:10A97000B60E14C01B5F6D9C2F53D94A31E04508B9 +:10A9800064C9D17E159A0C967C03B1753C8FA8954D +:10A990005739AFD288B5B41A4FEC5A75764258BAC7 +:10A9A000D53C16DBC052E4C32AF8FBE45FA5BB6CC0 +:10A9B000197026E50296960DD0AC7A18B6370725A1 +:10A9C00040230DA6ABFA46D248C4AFA7C33BE7FE6F +:10A9D000125898E993543DBF7B1623391218F2643C +:10A9E00047D55E5DEECF88F6F326F65E2BF2996DC5 +:10A9F000E26F2B0E64FB027DA7B8CDCA920D2EBD6F +:10AA0000F5F81434E31345C7F30699EF6C58DA18D8 +:10AA1000025A00FF9D611BDD78F30C4A5F840C6FC6 +:10AA2000871AB89B9D54E229CE116A744EC72C1E1A +:10AA30004665789EF824707FCD66D1CA1748C7173F +:10AA400078F1BCF2FA79C90247331A13DAE8E32243 +:10AA5000515349C62D409EC25D9B70D8CD081C86BF +:10AA6000C444A1CE6A8582AC6B14198EB92D4020E6 +:10AA7000C9FEB7C0F5D3CE298B17B0B713966F9721 +:10AA80008FB1B262F72053B8BD1ED709F932B5FEB7 +:10AA9000829B5D059E75F2F947C7E87FD1CC8CBAE1 +:10AAA00059C470F8F793A8847D20240BDF3933D282 +:10AAB0008FC6DC2379D789E3D973E90365D000A574 +:10AAC00077473CAA89252226C42341353CA93C2D41 +:10AAD000EBE028CA5CE2FE21C1B92CFA2B354735E0 +:10AAE000A5B15C3FE83FB930AAC8B57ADBA972BB13 +:10AAF000BF4370613E66066C5DDA58F2011939CDCC +:10AB0000088758A83BCBA081047C7EC006537A0DF1 +:10AB10006036B773B13FD3E17AB67C35F29D1D2E16 +:10AB2000124F67748D08DABBE8392FAB417D28A13D +:10AB30003C04B9E71095F370CD9A1DDB837A3F2E64 +:10AB400049DE2A641A117C88900C6A9054B111BFB6 +:10AB500087881E48C72ADCEFE4278250EFCE7F8E1D +:10AB6000CA29A0BF2F9179AB745ADFBAFF7F499EE3 +:10AB7000D1204BF4ECD8C26AEDCD55E8556537C706 +:10AB8000DB01629FD8F79B62187CBBD771CED2C61F +:10AB9000C885B7D23C7EEBB208991A14F476DC185B +:10ABA0002217ABCF246754969E99CC0B2EEBAD8227 +:10ABB00070ACF318747C6C49CFF48174D22A154DB3 +:10ABC000AD9B22431FEA9A3163C9E0D91FCC29BD4E +:10ABD000357ED7D461A427AC3373B2BF473D8E8D89 +:10ABE0003D54893950209BAE868DEBB0B2E47C7128 +:10ABF0001B015CD9CFDF8EB1CDD5EF7ECECEC74065 +:10AC0000082186C7C6ACC20A32A16744EB43B71B12 +:10AC1000ACF0FC23EB9F348DE16450E2273360C637 +:10AC2000648B9F0AEB63D4EA38401AC916E0F02718 +:10AC300082BDBC25A815B8CDC7BDF98601BCA4D876 +:10AC40009142ED6472F31E56C1BEFBC15C531C867B +:10AC50004AA0059A75DF944E4B0E60A71E7659AC3C +:10AC6000C925006D8DD549A794F17D197B213952F5 +:10AC700047D86C3DF37B6D6AA2355415BEEDAA88AA +:10AC800063ADB1CF6651E92CAA328EE01E8917E37D +:10AC90002F049C562FAEF8573129638A1C5CD8C903 +:10ACA000F59B4BD45CD415B5D053CE9232BF39CD81 +:10ACB00035C2F7C5D8B833E50ECD06BE7DAB1EB1A3 +:10ACC0003A840FBE2936C2851A7A5CB2DD9892D9D1 +:10ACD000DE856137E017329DE11E4EBF621E099787 +:10ACE000911E60DD00ED2C2F5C216554DF4708FCD0 +:10ACF0006BF0F411370B0E8B3261CB2F67A84CDB56 +:10AD0000B78A562CAC62AB278688642EA8ED39959D +:10AD10003998B4FA0F74540639A0D38196461DA40D +:10AD200003F79962C8F235423983D8F04309FD250B +:10AD3000623C2A44002EAB6BB876F27A2A191B2F9C +:10AD4000FFFA390473A73D9EED3479B4B912A746D2 +:10AD50003D3B195587CB8C1997C3851FB706FAD190 +:10AD6000556325FAB09F2AD851EF4A18738E9C0676 +:10AD70007C9366A366D959E6AE5BA56C97CC11FEB1 +:10AD8000E1FF1E5F072CAC1C8E7181441569A094F5 +:10AD9000C25374BBC1A93F9FF83E50A8BDDDEDC5AD +:10ADA00027F61E32AB64B0CA3AD3A59A4D4F919C98 +:10ADB0002BB3C2D0075A9144C2C8C5BBD5E36CCAF5 +:10ADC0002933398BD2B05C2A356B9EC5E8BF5F084A +:10ADD0000EF8ED1362E54A69DD8D5670B39C8CE781 +:10ADE000C4C447F701BCEECB1067C3D778F3828A9F +:10ADF0000446C29EE455C6DC93B8A86F1398ABB561 +:10AE0000ED38F3A64184EBB18A3F087AF8341BBDD4 +:10AE1000F6A8E341EAE6107883BEB3EBC92E7B02C5 +:10AE2000C603E2F22003F6CB0B7DA418F2F2C7E0D2 +:10AE30001883B83DA77D8D40CA92496D9E89CA3658 +:10AE40004002C88AA72F56E6E86F03E4A5A1ACA18B +:10AE5000C839745FB3EEB173622BA854D8A78C0EB7 +:10AE600076A0D0D966CB15E4EF5CEF75465676E058 +:10AE70009B16871AD5E46BDC9016BD800399ADDA7A +:10AE8000514C9C9F387BF68F12CB17DA3FD8381D78 +:10AE90005A9742731366A9810D1FFFDDB93C5653C3 +:10AEA0006EF33A91CC5A04A660528EF2CC797FB000 +:10AEB0007BBF1EE7E618298FCAA5DDE137A038560B +:10AEC0008870EED8D3CD3B91255EE7A849CC94C7D6 +:10AED0009EBF3FDF969C23D59A09D08665A66B5E00 +:10AEE000CE99081B1E483BB25359560B9D3BE810A8 +:10AEF000C9132AC1DFDD35B7FF6068DFA225042F43 +:10AF000058E110FB401938F826EB250BDFE10A4425 +:10AF10003704C7A85E2986BE2AD299AB2DB707B5DC +:10AF200082BF2C6D96924580DA85F799FD1F870ABE +:10AF3000D5022BCA7384AC21EDAA66F9B93182D649 +:10AF400063764B4332A5B10B04E1236A4CC1833EC7 +:10AF50009173308D085F4B78EF0D013737C48CCB80 +:10AF6000310FD044771B8413C15D7AED270464163A +:10AF7000E8EBE845226B0B0285BFBA4BA67A6E015F +:10AF800050BE743E1B558D22D75BFE3D49427FF972 +:10AF90003C40D7EBC9430122175DA1E2701C34BBD2 +:10AFA00033EEFAD534125069358289552B1654FC8C +:10AFB000A3CD0BEE53485D917EE14E3F439B76E57A +:10AFC00075A358F4DDB72D08C003951B4587E7E549 +:10AFD0006CC0BBFF509832068D8159196A4CCF075F +:10AFE00097DC4CA2DBA6CE2A8BE061765A86829C47 +:10AFF0009DFBF3C60277FF2ACCC4D6FE0B4076DA5F +:10B000004503D1596F08B68A3C5695CFB0A38B66DD +:10B010009EA9C142FFFB7E8AC8ED435341D1A67A67 +:10B020000E185085A002BEB8BF806323B2E17094B1 +:10B030001F308886A0BC53F4C92AB412FDEB4D54CE +:10B04000373B4EF53F15EAFCB24AFB9FBF9DF82304 +:10B050002A5E9224A9CD0A784A4270E7EA55D98C33 +:10B0600000D5F8C502AAF7A8D2B54FBADE4C963182 +:10B070004CC7299D20BAAFCBD54F1EBA615407F9F2 +:10B08000A0E3F79695D5530BA47909D21011DCEE05 +:10B09000821EC56BFAF4241E94492829E641E45E19 +:10B0A0004943B30ACAEF0BEF16398025ACBB184DE4 +:10B0B00012A4471C5702CC4E79A06BC9C504EC03FF +:10B0C000CAA22EB34B0AAB50AB52DF879D532F3F22 +:10B0D0007CAD6A5A07A04020A7BD74FE9DA2509C7B +:10B0E000FFB6A0BF112741AAA4E742282A7527B1BD +:10B0F0009D4A410CFB62B73C6C24B8FF9FF0B5EE53 +:10B10000D0243FCC6E5B1F9A8229BB81ECCF28E014 +:10B110007F5B12B26E47949704E687111311D354E4 +:10B1200008CBA068A09B9BA3965FC5D7DF9B952605 +:10B13000930DCE0957A131421B6A7C3D6D3799585A +:10B14000D03F94CDDBE051F96F1BBECD61D3AC078E +:10B15000CE16F71D7B6D9EF0BFF4B6F66D1D6F2207 +:10B160008A3ECF9F6825D37A5D83A997D5AAAE87FB +:10B17000AF02C5D25F2E809AC14D2CA31F0371442C +:10B180005EA04ECCA2A536421E426A02ED6BC72ECF +:10B1900067ABEA2704DC50A4BCBD48C7D8BD88F320 +:10B1A000EAFA8A0960E7E028DE80F48486470550E1 +:10B1B0008840853681D89BCAFB462A776A6838DD85 +:10B1C000774D25F31033380F26A4AB977209EA6741 +:10B1D000317656F2E59082487BA56402FAA648F3E0 +:10B1E0000A641B49851BF3E6EB6771B20A8BCA88B8 +:10B1F0008F2EB9F4A833E43872A648FEE320C03F8E +:10B20000723BADC248B9007AD46656B3938C1158DC +:10B2100097664122691DC19F14F72B53AAB2A8A2B9 +:10B22000664B7792D9A45C8B4D558D5B9E8D0EBE7F +:10B23000F64D2D8A4BDA6AF103D8477305563F4E17 +:10B240003B4495C2A429BF02E9AFE8B6F950F98B97 +:10B250005FA902F1DB2D758F71EA23FA2EEDED3631 +:10B260000D5A487058CE5442E40CCEE0B2732F4FC2 +:10B27000541E38FAEA9A17207B1E241A6FE2C8512E +:10B28000770E3752BABA8C3BFCD051273FF7F72ED6 +:10B290002CE31CD3258112E59E8B8ECAA70913B916 +:10B2A00068567F3F05A186BDB2AF3F31C0F01EF9A1 +:10B2B000C58DCB9EBE3943D79B34EDEE14CBA36F27 +:10B2C000493E7E488D2068B308F4908A6C07855EFD +:10B2D0007989846BC4AB318D3F6CA2A665B96BC90B +:10B2E0009EAC0C698A0E5434B595E7A84A57F3030F +:10B2F000D99556C6D0C59DB6938D3AB4729C7948FF +:10B30000392E5359A60979D0FE5D5D681025A3EA50 +:10B31000A012576AD035DA48DABA61CD47DD73AC8E +:10B32000D5251C94B395605DB3354D2461E5B639E0 +:10B33000393F6A6340A651D293407D95EE15FB9F3D +:10B34000F21BE7B08BFC84CEEBCD5DDD54EDDF610D +:10B350005048B436147DCEDBEF4746E11EF7A060BF +:10B36000F856DC6F20F79AE57AA91730981C0D750E +:10B370009A73B441CD6F216939D1A6CAAEB233C92F +:10B38000F33180D1EA5B95AB694DDBC6DEE27D9798 +:10B39000DA850961C110DE828D06852D3FB9ACCCFE +:10B3A000B99BAE19DCAF89B7AD52F1884953F5A10D +:10B3B000A0E0A38A6AF6EDFEB5BF556C9C597A7B76 +:10B3C000AA4764F3239AE0F73AEC5AFF6FE8E511D5 +:10B3D0007118940007F999A14AF87A6C18725C8E7A +:10B3E00040F2442C7AE982A118EE962C5D638A1A09 +:10B3F0006BFB42C0DEDC24527540405E25D31BAAA5 +:10B40000C17FF385912F97334C8CDA5C51973608C6 +:10B410000F225705CFF4F4823681C1C232B8F792B9 +:10B42000214BF77141ED1177D9738016DE63C42E7D +:10B430000EEB570AB448E7B07383C3DDB36679B344 +:10B44000D7DD7A323BD847B0AC267BEF78428F3BD2 +:10B4500021E294340735DCF99AF639D4F22BFC82D8 +:10B460006530557CA5A425763CF6755461A6740E0E +:10B4700004CBFF5C4B8EB0DCC1E9B736C0CFF36DB7 +:10B48000C2603EF93F12C9DEB544D030E2B542E5B4 +:10B490007AB0E34B6DEAB922F7A67C64D22BF7BFF2 +:10B4A000CF5BAADB90E44DF29F1E8A0136928E8814 +:10B4B000B3DC8CA9D0A7E1552571617014BEC4819D +:10B4C000CE2D5881F463FEF3C0B6120F5F56EE3FE7 +:10B4D0003BA375320C5D7FF95A42AEF5A630444C61 +:10B4E0009454B9EBEB29F08EB0CBB7532FAD5C2958 +:10B4F000FA554BE9FF4E102807BAAC10359EEB8089 +:10B500009DD150E4F67105E0036421CB21A47FB501 +:10B5100002E67BDEFD61BB6564E5F969E74E0ADBA7 +:10B5200005EA573F6D08346050A0614AC1467E4429 +:10B53000FF15B7172B0C2C5E31EA537D490A444B9B +:10B540003B3A5DF7704C01D0806E87387AAC048747 +:10B55000957A24DDD8D2B69590ACC59DB8EA19BECF +:10B560008890FD434965C399DF2077D0DFC3AA5B8C +:10B57000C4C411CD1B764BEF51A2CAFFFCA2AB9005 +:10B58000BE88846B63D28871FE737E3434B00B6ADC +:10B59000954295E46CD8728CFAE54345707D28128B +:10B5A0007AD4C412DFAB637516818607F6691DD2A3 +:10B5B000EF7D25D28AA17565A7CF2D34DFD9180C70 +:10B5C000C7C60AC44E2A5A94F4496803643D3CB481 +:10B5D000EAA70F22B7DE9E3FEE2F42083D2ED7E1AD +:10B5E000B5E909F78AA69090E49EEB06D52F5A316B +:10B5F0009FED82DC5C131ED13BFA823EC5CA5F6CB4 +:10B600006BD71FDD4AA0BF64E178A9C045271BAEF8 +:10B610004493C1F93335A0EF1318948F8AEBC4DC3F +:10B620007A20117722A93FFA6838F34BE44710B328 +:10B630001B8A4E7F0DE0B297DB962DB54F2C7920FB +:10B640009AF1B2DB6FFF56946975FD6DFC9AAE847A +:10B6500093C6A6B18F31687646590160B9A0775B71 +:10B66000C4B0DD78A8D66D46DF3F229B21886CE709 +:10B6700005A7C41BD3F9E24766487A331F78031144 +:10B68000F4F8F2F5293BDEB2F1243459BD39BBB0F0 +:10B69000E877B223C111051520F8DF718316B520B4 +:10B6A0008AF627C0E002FB93C2F555996C3588F302 +:10B6B000DFBAB4AB6D990E9C8F414C6121F6FD68E9 +:10B6C00040B0E4CCCC5BEDC918F9001D00DA7D0474 +:10B6D000BD3AF1FE734FB19FF73B039017CF9837F8 +:10B6E0003781145359C824E5B196308779412F3EEC +:10B6F000B9F7D94F2893C90B0905BC649DF39F89FD +:10B70000188DB830E14B9A14B2B66A44F3B64A05C4 +:10B7100092A4FC11B660FD89B4CD5A5CF9664EA3C3 +:10B7200028648D4679AA5E14737BFA4CE57717601E +:10B730006D368391F5D16C2F0D3ABA5F4994742D13 +:10B740000D0C95CD54803E2E9A53731A55BC3B5622 +:10B75000C3BAB15CD15FDC85CDA3B35F00D9339EA2 +:10B760000BC5711F9911E8387BFC731E1D88F67696 +:10B77000B5A93F4FCFD3A2381225D43BAAB3D27B71 +:10B78000553B13B156C82B53CB78D52BF7C8D3AE46 +:10B790007D42C65EF67B81537E1E6C388C7CA85E33 +:10B7A0009C1FAFE88958040814C37777EA40C61F86 +:10B7B0003E728E2D3507BE0642FC9EB6382B766053 +:10B7C000DC6B7516C37F958B4CA4366027C8F13DA2 +:10B7D0006B4172362A18103188F948ECD21E4AE0C3 +:10B7E0008A24FFAA215F68A681F179961B7086E3FF +:10B7F000EC8E58B6AD3D26EF088C98306DC9D8E672 +:10B8000086111A6E5BAB0AC9094AA528C8E4C3377A +:10B81000237153F763BC2ECA09724F62C5A607E8AD +:10B820008B514B276863821FF079287683C67E0987 +:10B830001CE7E70516C9BA9792C2992FE7C00D66B3 +:10B84000DC79C4180F6249B103D9BA16B8D6311DD4 +:10B85000890798F93A064EDEC952F45AF33E2E276C +:10B86000474AB1DD366B6B7F5FA4ED70C10CC3DF5F +:10B87000A5C9B2A338981F7DECB4EFA2647B948471 +:10B880000E6A65E7D361221170568069088C94B600 +:10B890002712DDBDD37CB2DFB715EE9A3BCEA1599E +:10B8A0003A8FD6A6A5F0B0AC21A9DDB0BFD2DC445A +:10B8B000394519BF7789180A34CC230BB67D938D8F +:10B8C000BC70FC7EEF3AD422858EE6D4FBFC519E00 +:10B8D000197D1B13720C726BA2F1F68AD60CE27AF8 +:10B8E000E9B696C786AA460CE30526D2668AFFBE4D +:10B8F00070A8C01A2D0F877D110DFF168C39A1631A +:10B90000DD61E24A11C01AE97151FFD0776A4CC873 +:10B910000B4DD49AD8C09BCEAF077F4D59E0C9F2EA +:10B92000DFF1D798D62C6E66E5B483D1E89A96916C +:10B930003B972C906CEE1E9836CAB41FA98C985178 +:10B9400024D6C74AA71E01E0A7F7418B1A5CF5A9C8 +:10B950001629F1734A29756844ABA2BEB7C4B4D0A6 +:10B96000F4D1BE0D67A761D8ECE7CC211B6E424A2B +:10B97000F67086800AAB20E65E1AF72E8B0C4A8E94 +:10B980003FD96DC9779A957129ADF352E13794A3E8 +:10B990006DA877061A31D2B33F7FC995A0DF49233E +:10B9A000C7453CA7EAAD0A321E5D16B348854E591D +:10B9B000B8EA428B839178298F478FA7B75B3929E3 +:10B9C000E019B38598C0F66A856E6FD6C57C9AB3C8 +:10B9D0005D050D4A7C2F84CAF56A8A2115811AFDFE +:10B9E00040B6811509E5527D33426CD69B7058BE36 +:10B9F000D8D564E64004289612E8F3707FCF31D79B +:10BA0000E5B460EB17845401FD11D9C38F1EEE51CC +:10BA1000DA10C6FE90E316D5113F56ECA9ED7A5E1A +:10BA20004A54FE008AA228E1FAAE57EB04A4D7CE0E +:10BA30007C068C3749A3CA61E1C265A08F104738E4 +:10BA4000047DAEAD5EFBF58445643B8729F3C4FB02 +:10BA50009DEBED9EADA575A26965F5F904322265F1 +:10BA6000A5BD2C3F8621384F3134473D01261415A2 +:10BA7000FE1564B3A713AD2107F4F089973F01C702 +:10BA80006FADD683D7FD55C238348E722E2300A9F0 +:10BA9000B06697B6509DCAE4D83415CA1A86D6A0A7 +:10BAA00059DBEAF53E13B1B5E1C90C031BF43813B9 +:10BAB0008C3A8CCBFE72BF3911B3F376532EBE593C +:10BAC00099F8727D2650D0C7A734E03EECCCC41B59 +:10BAD0000BB6CE05924EC028D6161C968B46E12694 +:10BAE000215A298BF39420385BB47F58C7BB6EE88A +:10BAF000D88B8F8111F1F36FF1E4C04DB92A2785FE +:10BB000009ACDD3CA7E81383125F3F20024737787A +:10BB1000ADB48B60681963C5396E69ADAF092C355A +:10BB20001900DB115071D11B2854049773E755E8B5 +:10BB300054D139762D51F11C0C4E7E5FDAA5FF6C85 +:10BB40005ECB8713D49E3374008580DB50027BF379 +:10BB500029B6CA85E2E555AA9F7F7481062AF5FEBB +:10BB60005FAA75D315FF6AF3D89C99ABAB3F6CFF06 +:10BB700026C005B93F3D4869E9E741382D35A52B79 +:10BB8000176A1C797C7DE89371884A56E9FCFCC2EF +:10BB9000D14399A40D28B6E2B14DBD1429A33B654C +:10BBA000454276DA15930415252306F930479CC9DA +:10BBB0000B9F79AC4B472A175B966D6F2BF53C18A2 +:10BBC000EDF38FCA3D91CC1BEBBD1B98CAB2AC0301 +:10BBD0003495D0341DEE123D16B7FDC1B3C99D4555 +:10BBE0000AE132BF2457D6F26F3ADB5E85627C3DB4 +:10BBF00044F1485BC73B73C1AB214132FDE95501BC +:10BC0000889C7E78E4EA9A4968B41D3778D10C6C38 +:10BC100084D966DC47926E5EC93AA7659F8407E4C3 +:10BC2000C8C42D69C328EAC61FD040952E4048DB02 +:10BC30002C9151ACD690D8A718CFB8383836047E9E +:10BC4000620EF2AE0C6FEB0EC34B5023A97F0E6A4F +:10BC5000721B55A53D8B2D2A2335DE31EB22FFA823 +:10BC6000324CC17AFFD2BC4F50F1E8493CBEE91CCE +:10BC7000D2B5FBAAD0BADB697A6970DC832D6DE995 +:10BC80005D81D169B29A6CCC638DA2668873CE3225 +:10BC9000C7DE5CF76408165110F335A7C9F8F01237 +:10BCA00025830CD7258B50F1D3A4FE14D6A95B4273 +:10BCB000BFB29ACC1816CBB9DB8B588A1A3EF66302 +:10BCC00031EFF85993CFA5E8E93DE51BF317328E24 +:10BCD000E9E1B7BA331F7854A162E6E677711B59E0 +:10BCE000A36AB9345930664C3618D7EB42716D1ED1 +:10BCF000266D8AE12F7BD92A3BAF4750D135678328 +:10BD00001D948C0975289CE32AC45CEF02E4832D02 +:10BD1000244CFAFAC881EC1B0AB806FA1B19786E93 +:10BD200006A0E8DB4105AC8441CB1167D02140B7C8 +:10BD30004C7D53D88D38CC676D42FBAD48C646B8B4 +:10BD40002004E341A1685A4AACC91B1EB6CCAFE639 +:10BD5000FAACEC3B08E88FAFC4AB4FD169FD6A6425 +:10BD6000BA830A2FE452D89D43BFD239BFB62254BA +:10BD7000A3459BE1C33D0BA77AFD187F42952A6638 +:10BD8000281E2DBB64BE1AD0B7DFF33C44AC07C4F9 +:10BD9000AD9FA63ED514233BC1A7AA4ECE2B860944 +:10BDA000A56C7BDF2A90BE570079679A80A4A39583 +:10BDB000D927C2FC976F7BFFB8EC298BF716123F8F +:10BDC00067BC0D5F120CAD603BA244F17C34ED31D9 +:10BDD00047E6514253038A0A0F3B85BC02ADFE8AF7 +:10BDE0000DA96EE32F7D00659613518A4651884454 +:10BDF000DF512FA74A5078B7ABACFB2C3C9D458A4E +:10BE000062D5A09B2AC266EB51359AA81D78E11A2B +:10BE1000028B338DD97A19041D8AB12DC0FC4C4C8C +:10BE200080EC749AEA57DB0CE703D57716FA0AAA76 +:10BE3000A1E257ECAB3FDB31CB9FAF0E050AB9F661 +:10BE40006F9369C0E81C427E8EC4913321322E7AF2 +:10BE5000321C27D6088802027B4684C9BBF22F41D8 +:10BE60000BC11CC072F9D642F495FD1A9AF7AFBC0B +:10BE7000B6E0A35BCB5EF27EF7B3C4E63939E76385 +:10BE80001BA0FD19B274FABAA24E34A68F5284E2F6 +:10BE900019AFD187181644657ABC84D53851916F93 +:10BEA0005DB1AD7834786323456C27A2DF2803A702 +:10BEB000304209293B1411FAB05D631CBAED4A0BFC +:10BEC00014544A1F869FB136A964C3CF2A9D6B962E +:10BED0003A9BE044EC9B886C9AE80DD104C7A6D647 +:10BEE0008069B6C143D9058947E707517262E42EDC +:10BEF000500780EC1826E9CCEB63B5EF40C2926D99 +:10BF00000954AD8597924AC8BD699255F8720118D7 +:10BF1000D7170DB93006AB287A09176CBF135CDB55 +:10BF200066156065F847D04C03285549BB096B94EA +:10BF3000CF5BCF453BEA4B664E81723CE11ED0732E +:10BF4000BC87FE528B62DAC6C560FEEAC85C1BC5C0 +:10BF50008B76EAB4525190C79E95E2ED8588CEA7C4 +:10BF6000D13B95AC6DABC2D9678B8F35B63530C43C +:10BF70005ADAF7EECEA1846DB78D07F4B900F64218 +:10BF8000E3CF5843FBE63FD12A9F183D094D24DB00 +:10BF90008267618F33958C5EDD7797ACCF9C808D07 +:10BFA0002E2271B6E0C44997557831D74C4DBD3239 +:10BFB000081D1C97B1C98C09E957C96E0A9FAD17B6 +:10BFC000635272FDDE0A4923D9BDB31B1170A1690A +:10BFD0007237B37369EE5D1DD21BB5EE4E1B5FA7C2 +:10BFE0002F94E822ECB30E7D0627B1D9C19FB20D84 +:10BFF000687FA9D5E087C412586D02410F7C953641 +:10C00000086F410DB2C9BC1BBE4FC5DD58D98F9317 +:10C01000266417A4601D126297D7C3E6E695BEF1A9 +:10C020004915F339E8406D320C3AC6285AE6948235 +:10C03000678ED2F0A22D35156AEE15AE88E7B142B3 +:10C04000A96D21EB590ACD1DD8B4E6C8427873908A +:10C05000C35B6890B5B96F1A5746A792E4BD725595 +:10C0600096D5A98BAC5BDED81CCA3F9CC9C568CEEF +:10C07000BEFEAA7F23E77CD6D39686EFC6000CEFE0 +:10C080005F0A05B3A68488767985021B8F1B15216C +:10C090008664FECA39AC1CF59ED201C105D7904C0E +:10C0A000E521E0EF761D014EC5A5A051C1ACF6918A +:10C0B000F3444AB653405EC5C4DC6AC793E21C0B26 +:10C0C000EEB4D6EB5E4C2FF71C199388017542C66F +:10C0D000309624CCB9BBC9FD8F6B459655A9035446 +:10C0E000CF56A688E2E59027C38FD38A6D6A85D0A4 +:10C0F000E893CC5D78DB042D0C4F9D5827362E0E2F +:10C100000C497C7C4FF4E70E1E54F0648CDDA0EDEE +:10C110002860666FB26F5479C1939F3651C2CFBF0A +:10C12000677BC5B055359F482F689D9C43F6D2A0CC +:10C13000880CEF65DEC47A1DE112EF90B99A848213 +:10C1400069188D63C09F5046F45BDFD9392FE8A68C +:10C15000885EF7916C9360C95EBFD503F36BDE7B9D +:10C160006209E010C51D2C454108BB1DDEF5E3B991 +:10C170003B8A2F06CC67ED720FFBAF196A486C0241 +:10C18000797C31BBCBAC39859EBBFBDF09145A5F90 +:10C19000F69E69CF074D9C07DF1531E1F8A813D94A +:10C1A0005450FDF02F1D84D8126C0EB67EBEBAC955 +:10C1B000DA388570795432404C2FD9C9DAB59FBC32 +:10C1C00094FE0FC40A9C55CC510546E4B313AF440A +:10C1D000CC25CFF19DBDC43618CB4605C306AB9B1D +:10C1E00012950CAC43DD5704A659D1A3CE10FE0620 +:10C1F0004291B390D325379D3C331EB8BF10D5E094 +:10C20000B13D79FB1BA28BB6C82820E7059A42DF17 +:10C21000067C772C275BB7F54FADC93C6C3F12E22B +:10C2200009E4D13BFC16DCD5912D050896CD2CAE4A +:10C23000DA610746228DA39B38A2E4C03B95469065 +:10C24000967CC2A333FBE590CE9EC8AEB84CE1937A +:10C25000DABEA9B1F34AE3A54D1816305FB1F8C4B0 +:10C26000DCB05750212D10DB15CFD1570B505300A8 +:10C27000BDD3B3B00658FCF937326B339610AC8897 +:10C28000DD8E41B425BC134B80E0CBB12D95D5108C +:10C29000D2D512B36276EDE32910A0B7CF7066CD88 +:10C2A0005CE01F0B9E225360D06FD55DA95E86E3D4 +:10C2B0004FA3FF8CC13607696C2E875683FD4C96C1 +:10C2C000B4A9AAA6801F0EF174AABC5028BC4017BE +:10C2D0002799659FBF53EF8CAE6E0138BFC4B75826 +:10C2E000E1DBA39AC35896D4FBCEBBC1FE25C55251 +:10C2F000C7A3BB75980DB3228A8A709E368442EB21 +:10C30000F738E3C1E3046D932B8A3FBB4EB9F0F8D5 +:10C3100038A77E212A3300D395635C7CAA3EF0BC0B +:10C32000D2A7DF851BB44DFC273D1AD13DB6FBDA01 +:10C3300074B25DA7133B90DA5E6C005445D688E377 +:10C340004C59338611B42EE45108DB638B4DE06CFD +:10C350008BCCC42CDDDEAAC730D7B127727851C888 +:10C3600083F07C8BEDDBCB512DCC38A556605E8401 +:10C370000BD8ACD15A76BAD8995D16676353675615 +:10C38000DDC9007E60CD37F8F0DDBCFEDEDC2BA918 +:10C39000CB82B9085AEB3280F9C0D11BF39A105BFB +:10C3A000D873380DE3662C54B3F37749103BF95139 +:10C3B000FDD16BADC5029E0FB041207CEF8EBED18A +:10C3C0000432F836912210E453B8DAE00D264D4FCE +:10C3D0001AD3854EC3213AAA074CD7DCD49946F12B +:10C3E00004909F25F4E8E355618FB9EB1F0E7B2580 +:10C3F000CBDB6289A3483459467AA873BC11849375 +:10C400006488756C16BB43BBAAB2A04599114678E7 +:10C410001BC91118ACD83868DE7A0FDA4F1C1EE140 +:10C42000830984B5F90B60BF8D1B1FDD7E7D2B73E7 +:10C43000174F4DA0C24F66FB6763D139AF544650CA +:10C440002DDCC3C4EA5F80D401CE21A4279ED1F1A4 +:10C4500017A6D45D88F5B0E994D95E7DCE9EFC70B8 +:10C4600024F10476454E266E90DB4F66199F4C3AB8 +:10C47000538530B86F70319EAC9EAF7DC172FF0A9C +:10C4800022AB7D34D2084E3884304ECA207B6FC335 +:10C490009EFF8E43F152AC6B33D1DD018CC1EF2294 +:10C4A000A1433D5EA937732CA657493096E9F9D6CA +:10C4B000C102551C1F358D3BDC0E696A9B3DAD04E6 +:10C4C00004ED0FD64AA3CA9E2573F26A5C7D266EE0 +:10C4D000C80E67AEE9D91599CC0D742DDF592A28FD +:10C4E000E872B74A821E8F0B369F08FC8790B514FE +:10C4F0001D0FED8D767B9C76E85E7D24DF327189A1 +:10C5000032CE9C92AD0A68078EB0E4600B14FB1A21 +:10C510007BD57097B2F092AA3FB9F982E2AD8EF165 +:10C5200070E104BC0A9DEE06B6D0B84FFF8973894E +:10C53000D52F0F6B3F496B7DB74D4EA8A2F537C085 +:10C54000F0DFBC6D7B36DDADA2A55A49A51B92CDAF +:10C55000D691A3F27DCDD458E832029D7B7F917CA9 +:10C56000BBE3B91177A4E1194A5DE82DEEC2F30FE0 +:10C5700040CA629B69606CF1BEDA38491BE3FF6117 +:10C58000AADB75A3A070C57310681A796C94E5F4E2 +:10C59000FC7BB74980C185DA5BEDD3AF86DB8F606A +:10C5A000733E4E30AB182A7F8F6FA46BE99AFAD096 +:10C5B00007E94F1FFE06941909E99A6BFF1F689B54 +:10C5C000AA803E0EEF94F0A71ABB5785E59F9663AD +:10C5D000D25F2C6040A8EAB13B7085BA611BD1F2F2 +:10C5E00089F31076FFF4821000206F13B8D8F85941 +:10C5F000D536862A1509E49D8788206BEEC2E7E0D0 +:10C6000095ADAAD429ECCE683C659E4E70EAB486FE +:10C610004EAA11CAC987DDF11AD78926C76A517196 +:10C62000C8D8B6E4C2073EFAE012D15DD9AF9B8FFD +:10C63000FC27BC2A8FB2FDF852C93FF8290ABE7CFC +:10C64000656C026AE67F8991F1BE28915F4CF42601 +:10C650001588EF0DCEFF80788DD00089A941B56295 +:10C66000E6A086BE0D4C483B274709F9829A2CC8A4 +:10C67000EC86C58323051B6FAF438D56443B0D8C61 +:10C68000E9DD3BE78D6944E384C5737DAED4F09565 +:10C69000AA2B6B8339FAE0561A10834630FDCF1867 +:10C6A000D9B03F9BA5A59C8B579FB250F99DD258FE +:10C6B000490C295FE224056D3FCEF75F6034A42664 +:10C6C0009DBEFD0DFC7C9286549221E946992DACCD +:10C6D00048D21BB099B9A611E419A8183C6EB90B41 +:10C6E000F0746513951EB6F3090182CD9E27EE798D +:10C6F0009D1243B47BA130D3D514D8639C9525C338 +:10C70000F5F456D0A21A71BB16495FF4A98601C28E +:10C71000E4E1060CA2CAF93E5BF8A94302B4F3BFF8 +:10C7200068DE5AE814A038B289521B9FB0DB144669 +:10C73000F03F8D8CF0CA20BA660CD82818F9C914BD +:10C74000E8C2AB7E81647DC7910C709878174DDC90 +:10C75000254E38F7E8952C4496BCB80763DCB1E366 +:10C760007C1511B8B0197B713F76FBA1052FA73757 +:10C770003802431DDD12322060CE07BC1FD28CB5BB +:10C78000D9B1532E9039B2ACF38F2936E37AAD711B +:10C790006A6AF8CB96EA0D25D4B56C9BAFCB42BA4A +:10C7A000FC318E5562B9BFC903D2F46F2AC542A9C4 +:10C7B000E16A34BB68ACC93E7D043430F19D3A4037 +:10C7C000412E1EDBF06D8F3B8DCACEF5E92D100793 +:10C7D000BE03FE36A16D373B90E869DD6D6336CC54 +:10C7E00059E91654D1EC1A4E997F13B2AA490F9702 +:10C7F00034C80BA12EACBD18E3679E4FC11573D78B +:10C8000072DBB1B6EFAFB16B94C24C6655F51FE465 +:10C81000F494A690F6F7165E5C7B824EB04E427F93 +:10C820003914D000A2A48A3E0026A042330B653BF7 +:10C83000430BB23CEACEC809573F8445C43E3B5443 +:10C840001CDB88B9A226EE9D18408F2A3BA248F136 +:10C85000CC9B19F79E511F492DBBDA54B6856DFF4D +:10C8600054E33BFF37F0DF89EC13C44B7A2D381EBD +:10C870001E15BFF6EF32B5879DA1BD3201E6AE4170 +:10C88000D35D0B9C7BC035B83A218C35C8078775C2 +:10C890002F233DA84E4AD395F28AD5F600C63EC056 +:10C8A000424D9DC7750BD4AD9A5E6D172BCE7F4D53 +:10C8B0003B587218E93469C915D177D8DE1F15C401 +:10C8C000EA2C5828B804E2BCC6EE4B623D295A0057 +:10C8D000A9EB681A5D3F74F774E27DE8BDC58ECDA3 +:10C8E000B5B41A929B37D609B814FF9FB6D8FCB2DC +:10C8F000475EF0B89B071D0B4EF392598FCF422134 +:10C9000090906D1538B505908E5EC594C693A97448 +:10C91000A8AC86095F2B3E80296E72210E4769BA4A +:10C92000E00FE5295FE7D36D00A0ADABE3B103C134 +:10C93000CE0E47FD37EEA7368F4BAAB5D2D8F852A8 +:10C94000F117E828C437F63652F0FFAA946E46492C +:10C95000304228C9374E6CCA3B0169E7A51D48EC37 +:10C960003497E7BB8E76E4F2B3EBE8A21ADE6C43B1 +:10C970009BD123EA9859969EDC558E223A6F25D892 +:10C98000505E5046B8D38FDA28826BAAC1C2E66ED9 +:10C99000E257FDC54F43985E7A1420E452B8D90699 +:10C9A000A569D54FBE277049A4D7766E8A7EE1DA95 +:10C9B000C4EAB6044474E4B607587BB74080D92D66 +:10C9C000912B6990C7E08FA8FFD745F6C542C15BA0 +:10C9D000000D43B9FB37B9AE65997205014DBD9B9A +:10C9E00099091C9CB54FF561284FAB60444A35212D +:10C9F000C38E4806F83DC4DAE2C3CFEFC56A593D9D +:10CA00007B229D53F4ECF0D5DFCD6C57C632D2516A +:10CA1000EA579E2C1403DF8A3E32626348DF746B50 +:10CA2000304DAD737508C4C1F4DCC20588DF3AA887 +:10CA3000CFA0607BD5F5914F76684B6AED81A862F7 +:10CA4000CD1138CC021CB5DABA56EBD154AB7F907D +:10CA5000B815D20BEA5B410A0581D27A4139F23E20 +:10CA6000C328B543BFB375C19A04377E1369C4D0D8 +:10CA7000B18028736FB90ADCAF516851895D1E0817 +:10CA8000B5FA46E8A458295F16C580ED44B49F6303 +:10CA90006C698EBD8B47C83ABDC1F78319CF470873 +:10CAA00062E6A7B775F4D0F8395938AEB5746AB0F4 +:10CAB000F9AD597E50BBFFEDF7FFF351DE0B5EB3CE +:10CAC00094D50FE62AB8A4221075D2530E1826D991 +:10CAD000FC8C37240995622142629DD36B06B49683 +:10CAE0008F02F5EDCE07F8CA3A25D8473CB3ED1AC8 +:10CAF0006DB3FEFA03F80334C5D8A9EB735D14EDEA +:10CB00008B4005C74F09967891A320FC00CFAC5904 +:10CB10007D1805C036B72D2CAD88B76B5D4FD21B85 +:10CB2000054CEAE382D6F8C4EBF684E9E9CF993FF5 +:10CB3000917D4C0172E72FB98EE23A4574B71CAF74 +:10CB400085F9FE8CD31A144881754FFA7258DCDBD4 +:10CB50009F6F19F9A28FB784A17DA5314DB68ED2F2 +:10CB60000D48A6BDEFCE8B88F68432ECF41425BCBC +:10CB70009F65A1653B953A71B2689146B2852C29B3 +:10CB8000A2ACBFBC8428BFE29C4E04966C3D3571BC +:10CB90007CF7B5C470254EA8F70CAC1E4101D29F9E +:10CBA0008367FE3DDE33F269C06955054C4A52F297 +:10CBB000502EE59B96EED9E82D90A4CDDD0D2400F6 +:10CBC000D8A5D3F2CA251FC2111A238C5A842EA5C8 +:10CBD0008F83A432BB44DEE0AC9C305CE8A7B47425 +:10CBE0003608E3F10C8D937EBFCBCBBADC4A8904C7 +:10CBF0005C7AB526C3BAACF5174FB51E883A14DC7B +:10CC000069AEE79A02D59FFB160D39F35C9E08309A +:10CC10007701C34975E152C12B3796842BF5FC1C73 +:10CC2000925715D8CA4089ACDBFEBADF511F3B8C46 +:10CC3000633FA49EBB9B0BFE76166CDB2555D45A36 +:10CC4000C62F04101B8282AAC2D03F4E4D11100184 +:10CC50009A65F2A913FFE3A4C6A697DC5C1F14270C +:10CC6000513516AD7FD12B2C1B545B23B53B767110 +:10CC70002FA31B17924303093F40208D893FB058D3 +:10CC800066FD9D4DA1602E9F31DFB31BAC55EB2E91 +:10CC9000281DB53CE9BDF61A51EDF62AB39F9FDD7C +:10CCA0006DBC8BC8B7177B4877EFD007330182B5CF +:10CCB00021A1157B15F12D116DD6A28F08CB336FF5 +:10CCC0006388887794CC7BCFBDF1EF291785A47456 +:10CCD0009F7B2E5B7EEEDEA297401084D5B31E4470 +:10CCE000AAEDC981D1BA98EE6D829C51CC7832F30D +:10CCF000EFD6E92319F6850DA519D13A362172939D +:10CD0000C777EA217E28399BA2E65C176EED2E7C60 +:10CD10007352B65C10FB6CCAC638F6D286D92F9F08 +:10CD2000FB605B2FC87EAB23BDD893B0843107C6B0 +:10CD3000561011340694F0CB7D4351977EC085D2B6 +:10CD4000FDC11DFEC41B2CECEB3615DB3FE7A28DAD +:10CD5000AD2628201D34CE0D351B3D8AF3DA9BCB42 +:10CD600004E49327DE3F0FCB26AA97A8D88B175051 +:10CD700024D464CDA6C1CFE3BF84F6200F215EDFAB +:10CD800028E5B24BA50B0F1CAC7468967C028ED2C2 +:10CD90007875A9FB42B4EF7C7D5904BCB324AFBACB +:10CDA000823C0AD12F9C8AF7FC31AD5C36ABF91D71 +:10CDB000681B312583EFA21B416494AC48BA802ED6 +:10CDC000A2BDF6B05E78FF786A4DB7D1D0AA0C014B +:10CDD000A81D6D4716521A9A7D4C5DCBBA97A933A0 +:10CDE000A6E32B43B1B74E05808361AF60795B4A00 +:10CDF00071B709317006F91F54D98D86B4CF6C868E +:10CE00009861FAAF78C2DD85B787DFE02B7C05B388 +:10CE10009715377CCE48A79DB300794C28E650EE95 +:10CE2000F26A93D0966B3EBC1D82159DD0564D2460 +:10CE3000527202B2FC69735BB163F8243414580E69 +:10CE4000F58A984722C471C25E0C5159BB68AB5534 +:10CE5000BE69B4A58B0B28DCB88504419AE36FDC6E +:10CE60001B81EC267881B8C7FD67E19F02B3AC80D7 +:10CE7000A9D7ADEA0CEE6C8E5C16E52119100E6E8A +:10CE8000F1033C7B1D5D0D277A7BDF8DB57C2E4A3F +:10CE9000C48CB360DED7EBB6881D89C437FB476B03 +:10CEA0005F20B5D9A7781984379C1A49BEDB8CEE70 +:10CEB00087802AFE1A991AFBE27DBFA2C62FE82BB3 +:10CEC0006166A698F25BF9CFBEF88009AD62EB65AA +:10CED0009EB1E2F6EBF1243B8C9C2CFCBADF2C3E9D +:10CEE00007D62D1C226329DDF5BC39A22571809E51 +:10CEF000A4AF6D07FAF620E78A810A85BB1A3A9E2D +:10CF00004AC55AD845821B3340A4D942291D080579 +:10CF1000ECC6B9EC84391A94E7DD110043D53236FA +:10CF2000799F3891FC1F5801F4C782C5B897F23138 +:10CF30008AEF707F32753235128B872C96A9B66ACC +:10CF40003CCD2E03D274D553DAA35B6F903A4DE3F8 +:10CF50009F86A570F16733D2DEE0D993F9FA67D2E4 +:10CF6000CC93B3D7B61AEE810F936F1F1A6E4C3F56 +:10CF700064DFB228451BCC56C18EDCFD5F033259FD +:10CF8000DA584D175BD0F132A837CE46F3DA149158 +:10CF90001F9ECA35FCEF62E15BA163A58A6724CFBF +:10CFA00006D1697516243E814A03F3FBE349413CEF +:10CFB000CE3FD9CC128705BFF2147CC37C3CB0981D +:10CFC00026B5A55ACF76739444A3B7BB1178EFCD9D +:10CFD0005558FBD93EC216041261448F40DD6BD612 +:10CFE0008CAAC0DA4887FE41482BDDDDB583349139 +:10CFF000960470A4A73ECAC56A46D83E9DEF1E9F00 +:10D0000075C975EC3ADEE7D7B6933ABCDB046764C2 +:10D01000DEE4E78352C160733D3AC7B0E8CAB9B8ED +:10D02000237450D4A1C86F3AFFAF4F99EA79A45D39 +:10D03000C3C3D1D867D1D3ABFE786D586D331EE82A +:10D04000C29C3CFEFC0EB71785E59906CCBFADFD32 +:10D05000E4DE483179ABF2AA4538951A1863504F8F +:10D06000F2A7A431D73C9A33AEF2A0ED64B85428AD +:10D07000CA5196F40E26F1FD50CDD59A505386B282 +:10D08000D5C1114E2A184843B5DD0C63E261456EE7 +:10D090009BE5DC7BD3BF9FA592690289C9132E98BB +:10D0A000C0D717EF6AADCFA8FEDD4E1089825D7D37 +:10D0B000C7283F80DBF465C8CD2F601D82DD590B8A +:10D0C000C637C477FD8FA8E3350151ED2C52A5E793 +:10D0D000B319F7F3B5247F5BE4654D186760C1426F +:10D0E000D742062B4697E70B46D9C5522F0AC38075 +:10D0F00013B5EF4AADEC95D03D9B5908BB3C7DB9CB +:10D100007954165966187FDA1162CE25C131D3F2EF +:10D1100045BEDF75F5B4FE1BCC944F62394E7935B0 +:10D12000394F707C7CE6E16DAB231082943DEEB00C +:10D13000F4B67A5292A85A1ED682C9AA0437E27768 +:10D14000DFB1672C7903FAE731C7C50126490833F7 +:10D150004A9DC84739945467B59217038012DEE898 +:10D160001B24E59A6EFBE3595598DA20CE295ED24E +:10D17000151C873C797CAB666F26E594724F73DF94 +:10D1800037A093EA8C9B4F2385D8674DBFE436AA1E +:10D190007B499DF0E01A8CEC69E4DDC6452DDB4946 +:10D1A0007BB15B55B862C28B1B0F72F34C20A95A3E +:10D1B0009B35577CD6A9D80914EF2C1B18DC02E943 +:10D1C000E5137E09CD4C8A762962AF128EBD34A15B +:10D1D000E6554FD4F45058AF189C53B9D54FE338A7 +:10D1E00032CD489E6D6D2703A34E276B147067D612 +:10D1F000F0DC201C51B0C7C97271F11378521F695D +:10D20000097930B3F6C355E45553B1B586D045BD61 +:10D210002BB8914A06D4233AD58033DEBDC48FCED5 +:10D22000AFD813929C6D3452D356E4E539669B0116 +:10D230002CFF06EE693D486124D0499899A1CAFAAD +:10D24000335CF52FFAB0F0076E65386D16497EBD78 +:10D25000EDAB604A7C0F2482DE1CD8078E18508507 +:10D26000376CD8BBC18AF810F774E08C72BE9F2C63 +:10D2700065E0C7296993FD59D60C9A44C36BBD7408 +:10D28000DB706DCC459EBEE9C3DFD95CE76B9C19B2 +:10D2900081E3D25365135BCA5EB8E1034B6FBB6891 +:10D2A000C4293D62C1CA60D870A88F8ECFCBC84C4C +:10D2B000162067BB42ADDBCFD2A659F9973E853227 +:10D2C000709FAD1F9383BB569908785CC4CA1A2916 +:10D2D0003ECA668DCF9B8FB568B2C4121E94A3A0C0 +:10D2E0005AB01055F3F8AEC9B9A385D4CAC2626169 +:10D2F000AD0B414EAB3C5B9FF9B7FA8FCD5D1B5236 +:10D3000005DF9ABA025F956B138F117BE3665D3D73 +:10D31000C641989E1698D51277A2352D384272F4E0 +:10D320004549DD39AD52BC9B445457C90913A31F6D +:10D33000DC8C387259E8D010A08FFA55F853051BD1 +:10D3400032D8BFE5E3276D9DF0DF8F04A89115FF6C +:10D3500055B26695EB6F0BB4E111FCDEC4EB58EAF5 +:10D360008AA49BB173E357E90EC398B9AB68880FE1 +:10D370001888FDF4C8FB5E1601A75291A956A0A11A +:10D38000A5336BB273B4343F2C50056A0FF19F98EC +:10D3900029D64C5261DD4FC1D3546E375BF68936C6 +:10D3A000F2D38A51552BF49BC9AEB8656EB853952C +:10D3B000290C148B61A705CE955B71EF5EFDCA4FFA +:10D3C000DD13A5EC4B147B94123B42D9DB3BEF9E63 +:10D3D000096BBB05ABC9EF2F045DBF1BD5B186112F +:10D3E0007DE0439E20157300F394CF011B18C961A3 +:10D3F0000F71D746F6A0423C2650E536612AC9286F +:10D400003B1BDAE3FD3E51AF9205E1E858F1B10A6A +:10D4100032B2E730F4AFA9413361ED6CF522DA8E18 +:10D420003FFAF507A025C39FA7861E3EA04AEDAE92 +:10D43000AA95964B97B40FB708678E06D7B993CFC6 +:10D440003090925CD3EA77D37E00DE2DEFFC77B389 +:10D450006A05A5FD0B71784773A0B6218FADB42581 +:10D4600002D6421F3F711F102AE9C6F0B92EDC997F +:10D470004DCDF01DFAD4C59906DAEC27FC5C346575 +:10D48000DB1DD4E12515FE45C3DDAE1A9EE16254D5 +:10D490004C78C7723B7DAFFD89EDC3F8EFC07B6C64 +:10D4A00062FFCDAFB8E6FBDC6E5D340FAAE6EBF9A8 +:10D4B0008B7D60E40B5E060C66A636D10170713C74 +:10D4C000C686F02B0B9BBA2D71201510FC10D011C5 +:10D4D000EA8DAEDB87F53447D8E6B76F249BA728E3 +:10D4E000E302A6DC35BB8A2BF557B633034ACBBA29 +:10D4F0003718C882C9145F3A05D907898FDC0BF148 +:10D50000FBA77393163A2451AE6DA2F5DCD5981A99 +:10D51000304C51435468E0DBCD4E782D9AD6050E41 +:10D52000C1A08E7EBCF82CED08C0AC57794EAA1F66 +:10D53000045AE31E5471476CA62BB3FD5E5B37792A +:10D54000F9A64C3327E087F6ED4D9D7E4D3BACF1BF +:10D55000083DBB5DC778547C935194E20C8AA1AF1F +:10D56000BDA0979B2CD4BB48984058EDE3B6552CF2 +:10D5700038281022A15648268F41E4827EEC79FE9D +:10D5800025C80242BC5BE51BA119515194C103F2AD +:10D5900031634E280D33AC174E5CDED8DE1B0442DF +:10D5A00098981AF97DC5B75981FCBE2ADFDA8EC278 +:10D5B000DC8EA8DABD578F0115C5F8B2D0F959B283 +:10D5C0003DF6C9D93136231B3AC33B46C2E1C717E2 +:10D5D000BB00D39101D6B4E52383C3225EE2DED241 +:10D5E0006AA4482A48664E6767198ECF22182BE432 +:10D5F000FA16EF6C304D5B3B6E4CBD5C78B626592D +:10D60000A5CE069DEA9D4CFE3EB275D1A72089A706 +:10D6100016DC6A8002DA01A0DFE3A6180BDCEA322E +:10D620001A026B3C5D217078BFA6F77D7D2F99C2F1 +:10D6300063168F1D465455B1710EDAC35C9F8E8000 +:10D640000CE4D9F51852EACD49058C07DABAB05284 +:10D65000AD0F69D0A9E0BF738B9DCA3D1DB8E17EB7 +:10D6600088BAF774EEE7D882BA186B4449A368EF1A +:10D6700067E5EEC923727DE313529283FD6E31BEDE +:10D68000D4F88B582C66902A2468D6FEDC077A31B1 +:10D69000ED12083320D6E045328D8AE283A813F0DC +:10D6A000DE58C1DE90FA3EFFFEAA79AB72DCFD4285 +:10D6B000FE30FBFF5C5547CA64CB8F5E5BB0806B6E +:10D6C000DA7424A2BCE2F867187CB34F73F3947445 +:10D6D0000A1070CF0A8424378B70B3A55E8CA09B90 +:10D6E0005656F1103F36AF1A9C98192E9B4586A5C9 +:10D6F000F42C2D45A5A5CEBEEDCAC7720EC2C63804 +:10D7000084430F3D07CACFDB0AC39F2D1759D009A9 +:10D71000EEEA767D77FE1C175BDEB355AFA844BDFD +:10D72000312E3427754CA5FC42D523D2F874162F20 +:10D73000A99D09043F128DB1FA16883F6BD8CEBD62 +:10D74000F179B5382C20B3F015C2A58DAB83325DCD +:10D75000491FC16188D264A01A0FB6242C6F81CFF3 +:10D760008B965B886A740D1213544BF15B92DE6CDE +:10D770002793C37648B4659D27A367846A9E8B3E32 +:10D7800046E8D4E22872AB1B7B9978D7C54FF35F8C +:10D79000ED6EFB60115DEC73B17B6224F72444C431 +:10D7A0005001CAC4D8312B5498E26C146923D2E1D9 +:10D7B0008BF5CEE8481D458F03777BD65997B77018 +:10D7C00052C85976D2DECED26D7186AEEBCF0B2029 +:10D7D000297BE88D5A7A9881641B2D299AF07EE680 +:10D7E000A5CDF4FDE52898DED966B6A4B0041EB92F +:10D7F0004BE4A062D30271AD70F2F956E3AB108234 +:10D8000025AED25726212C498256499F4C79592B57 +:10D810008384CF7AC9909AE25BD8B33CC1D1D1AAB4 +:10D8200099270EAA287E893BC22079B6F675B128C1 +:10D83000AA062C749E288AFC64ED9CA2AF47446122 +:10D840008A20C728628C52216E9190AB577FD6EE0A +:10D85000F70EB0F9C7C0B132ADE8B61B9051A5E9DB +:10D86000964D301F833BCB880886D97450C20F7702 +:10D87000857CFC34117633040ABBA52F812E1B7ED8 +:10D88000988A8ADBA026A022643967BC5818DAEE91 +:10D89000164E0B16AF2B574489309DAB1282993B25 +:10D8A00055CC44DC6AE19EF645BBF16F2F3C09C8BC +:10D8B0008BE07A43207D51536E189085414A4F2367 +:10D8C0001176F8A541639E26178983FF6BB5818D7C +:10D8D0004BFD6D89E36099A37077216DF437BD1C12 +:10D8E00084AF95178B647488573C682F2F09E31F0A +:10D8F000F53BC863CEC0085A3B72A4E06C2762991E +:10D9000090AE18FB4A4DEB4FE585EEDF38C3B87992 +:10D91000D84021A758D565C95C786181A4453E1CD3 +:10D920003BDD5AD622F1B9C131CDCA54CC0B0DC062 +:10D930008B382395A19DD4E31ADFB3A9EC290F06F8 +:10D94000B66EF53132F0000D884B2BCFE2B0AEFA57 +:10D950004F61E34F13590C2BDA59898DBEB2ACC01D +:10D9600086D2CC3212C8D9C38C518EAB6B8A46BFDB +:10D9700099E08C4AC451437D9D3E26CE763DDEDD46 +:10D980004A1957A811B76A4D7DC257E2222717D608 +:10D99000AEC616D0844745C8D777BFBEDCD037DEC9 +:10D9A000C2F7EFF3682472CE1A685FCC0731B00972 +:10D9B000FF83789BEF059986140EB4896DAF4CFBFD +:10D9C000EC1EF0B7D5883AE65BC6E1EEA3573F10F0 +:10D9D00070895C84BA3A3F86FF70573D49B1BC6C90 +:10D9E000440481EF49886952DF409113D3678D5D0C +:10D9F000301B5A27479153F3AC16B48D563369F850 +:10DA0000094DC642CC35120272011241F6B910BA64 +:10DA10004FF0E505821B89D1C6D3F3515E71032314 +:10DA2000781BB9CA599EEBAB6DF77D903863585C93 +:10DA30007CA64FFBB24D8CF6DCE1B2502A4D264D50 +:10DA400032DF078F65C8918C2FCD32ECA8D28AC9FE +:10DA500088E61E9C8165764E6656FE8142BF48135D +:10DA60001CBB5416E2750EE1C157EF144D18A32EDE +:10DA7000F8916E0D8E41B57432EE2FD868691FFB98 +:10DA80007DF800EC662D7248EDD5664FCD0F39223A +:10DA90001BD7EBA6BCC3CEF34665A4EE55C8F2AEC9 +:10DAA00039DE41817BB6ABCBE6312ABB77727E494A +:10DAB000DF5A965D1C5237EA8AE2F82CBD1FB95D29 +:10DAC000D6EF0DD83F3FE8ECD0457AB87D0455B28B +:10DAD0003B04FDC3378E16A7386151387057BCE53B +:10DAE000B776B6209EF550DEE3379C12DF76C39BF7 +:10DAF00050C2B7F581362AD469BA75AE813A00169C +:10DB00007BA560C6FA2305CC0FE161D735F2F63A62 +:10DB1000010D4B116BBEA9D4F7819FA72A7804EFA2 +:10DB2000B9E3C3AE5DA49FD268FC8CDDAC90B88134 +:10DB30007AE5DB4521BDB48C66EAB8D7030BC42B6C +:10DB40001CAB35CF0D44D6661391DFDBB281F7F6FF +:10DB5000F36F8270D278BE8EC57A903C7F1FD5E37A +:10DB6000D8D830B14E96DFC71A838EC844D4C77E4A +:10DB7000CE760A146488382B4E87DAC63FC80EE288 +:10DB80001D30A05DE78D63042BA196A474502ECFA9 +:10DB9000D016891F1676B20DDFCBF37C4253741476 +:10DBA000B661DFF259EAC4FA70AF5B9439D5210847 +:10DBB000A7E9808AE81F38859A9F14E52798FEE137 +:10DBC000D592E60059332BD6C2203270AD17A74646 +:10DBD000E748244F00B0B7E5860262A73B7A423F90 +:10DBE00027D5EAEDA0848BEC2EB06B091E8726B4F6 +:10DBF0004CF4303726FC148FBCD347063D84FD55CA +:10DC0000BD63DA29474D402D2CDE0DF13F60358094 +:10DC100063FCEB60B1DEEAC434260A2ECDAD9AFA7D +:10DC2000A816FACF86DD5C7A2BE6FCC7A330059EEA +:10DC3000263F67887B92A320C0E195287552CC7758 +:10DC4000686A8FF94958F15505D09511DF753E6D19 +:10DC5000D261EFC0DF6CB96CAADEA65CB630786B1F +:10DC60004D4992A4F40E65C3421F869BB9C12C9AFC +:10DC7000F48FC1F9B6D92DBD8F823785499F97059D +:10DC800034711EFC75BDDA0220AC4E99EDC9554FBA +:10DC9000971A7537952B2F77186816BD3DCEDDE5A1 +:10DCA0008465D65FB8DA36435D5B48247B183ECA8C +:10DCB00079A32466B3299A40DCEB1A888EB02398A6 +:10DCC00039798CE332E8928B378F1E877F66F49C1C +:10DCD000EF1DA8F0F679939DD2E685DD6294CEC45F +:10DCE000EB29CAA6417746C150E393E0BA1BABDDEE +:10DCF0006BE0CD1777BE3B09CA14D9CB6700AE44A1 +:10DD0000022E12593071EBA14C0608AF2EB4D72C5D +:10DD1000BC651B738E83333542C0AF8FA9634AA0A5 +:10DD20000651D73DA4D94B1AF12C8817893513D346 +:10DD30000199688F05EEB4EF1ABC90146CA2EC3810 +:10DD4000DF15CF0A756517A158B3A723EF9B91AFD5 +:10DD5000AD14DC3C6051C1BA43A50D180490364D9A +:10DD60007F17C133F46D892A55E83B9F93FD013A33 +:10DD700031436EC81012FED43267DD78EDEAA4A5F7 +:10DD8000295C3A87618DA071EFF9436AC13CC840B4 +:10DD90004CFD3A883E4C8F7B862DCAB6CF42E17B44 +:10DDA000731BA5BE5E56B7673FCF5FBEBACB8DE48F +:10DDB000F225C47510C5CFDD62AB6AD0A5F569A7A1 +:10DDC000DC840763F6276358786F24F61FBE37F2AA +:10DDD000D74A05745919DDD83D3D903638CDE658FF +:10DDE000C91739093C216D9366CE934BD9D9EAE125 +:10DDF00012AC83294C3F51744EDCDF7220286BA992 +:10DE000033A84E636C47528F513870359342B55EDC +:10DE1000535DF1F5B6A33F83A464A78A141CB94FE0 +:10DE2000033B67AAA2B9AEF65BEEB337E3EF02E7B6 +:10DE30000FE23C84636ECE00CC14AD437B4895BCAE +:10DE40000A118B525F9120C2153C8B4E2A0105F5B9 +:10DE5000B07FDDA3A2A1789C9F8219D6FF4732BC78 +:10DE6000EFED1F5F8EF480B0BA1E6A8E9CDF34C95E +:10DE7000715B1E72BB21DD1B6C951260205CF6EF9E +:10DE8000B7B13673CF9742870FCC8FEDD8DF38F21A +:10DE9000B3C63170295A3EEB07C209268B59657902 +:10DEA000C13514F70CB6E57507035B73C10D97B95F +:10DEB00074FA488D7DF0B33DED409C9B3A31E1BC56 +:10DEC0006ADD46A3FB52E241DAD2983CDFF5769E4A +:10DED00084D025FF7ED67270551347DCFCBB8E2E96 +:10DEE000F9BFED8BE31855A3049CDD47BA86BAB0A1 +:10DEF000F750F6FD551C18DFA00FAF0D95AC90D56F +:10DF00004EC8E52567FBB321CC5601E21B0D8DCC35 +:10DF100045F8E7A436A1BA2B794963D601B7E3BA2D +:10DF200098084A7276904F49E1B4250FABAC26EEC3 +:10DF3000FEE23AC1B3868E6A048DB69DA094788EB7 +:10DF4000716C69F5B1DDC0BD807FA38356A781FAEE +:10DF5000CD65E9345141EF0F97891ADB583AEB0749 +:10DF60007F79BF9DA7B0CDC5F5EB85586FE0FB9AD3 +:10DF7000E783378875EF267FF5D0FAED1CAA85AECA +:10DF8000F1C4C169BBEF48EA0E67FDC1540CC2E899 +:10DF900066BEB4FDBE77A7362E9DCF0EF2C6E22B2D +:10DFA00064F7CBBDAAAE91B0EDE5B042D0C8828394 +:10DFB00054F6CD0DA7549C6A54FCB7F472B1C04F0F +:10DFC0008F67685D3000A2C55C88827944DD14D516 +:10DFD000544B17AB2BB080FDAAFD4F24D3B936FDAF +:10DFE000AFFB3850C03A593D479CB87E66DD84751A +:10DFF000E02152ED74E378E4510D3CB3C8958F28CD +:10E000007B4EA6CC7264DC64CF3AC46732D3DA3676 +:10E010009D86A7B8175E046E6D5D634CE4F0587C76 +:10E02000A097490990EFA7823657BCEB36E7F23547 +:10E0300053BBD6E222E7ECAE96B41D97C991456278 +:10E04000B0993234AE6C6E08ACF68D9100CD1FAC39 +:10E050003BFF03A151BAB09C7764117B343D4FCB99 +:10E06000685BF6D25638C0D1EFEA82A7E330425D52 +:10E070003FABC256B83F180C81E74D1A0DB6F43BC2 +:10E08000F258AF97497979807FB475D7DC40FE317B +:10E09000E93DA129A44AEE71A1C4A796556C26ECCE +:10E0A000059DA74D0396EEFF352A0E0CB88FEB7831 +:10E0B00007E152F510F61E3F787C2D11980579F98D +:10E0C000E1E7060E87CB62DE6658912D491D3306C7 +:10E0D0009852895C74E142EF70234348E6D66AE4C3 +:10E0E000A6C4830F5D06C892A7A06F971A27818ADE +:10E0F000C55F61C101B86665CBC6CC13C43B4B0C90 +:10E100001B7096996DDBB94A7F26A456DAAF6EE490 +:10E11000D98084D8C920F4FD64B8C7A11576F90266 +:10E120000769CB28E3424380948BEE28B7B6E6B468 +:10E1300004C5E8E757238704D44E3B42B7768BB338 +:10E14000513C84C20C03E15CB53918685765C40FB3 +:10E15000D3FEBCD52D45755F2E173AEBCC28854BE9 +:10E16000ECB6D1FA17C82F5465E454D55AA17B14E4 +:10E17000EB2ADB145485CF0972A413C230BC7AE0B9 +:10E18000ECD1B66C4D1D78E4C8F1D7615D20F8E59F +:10E19000BE436430888F558B46FC0D8796AE9D0B31 +:10E1A00001B6C1F3E04A22E71702DB7F6FA75A539B +:10E1B000F356391EC14332232462A687D3900BAF96 +:10E1C000FD9A76B176A587EEF07D6E7A39E7554DEA +:10E1D00032CFA8E79DE35FD1EA7518D5F2AAC70749 +:10E1E000F07900361F3B018D719D40FF8CDB38EECE +:10E1F000D32F7C0964CAF71182FEC5E2B20427500E +:10E20000C37ECC645CB6650BD7CAEEDFC80FC71DF2 +:10E21000AF614FFEBB39ADADA65332853BA289D16C +:10E220004F6FDFB012CE6DEBDC7603E32F72556FCC +:10E23000D1AD2946832325DAA087080FEACDCDA0EA +:10E24000D22A0E4060EF46C824E5C883148F5AF6E0 +:10E2500051FF6A64E4F2CD455EA8755D67054635F9 +:10E26000CBEF5AE9BD31DEEB12F0F9D50ED0D21C5E +:10E270002C5F8BECF99F2ED4E843F40D2A9D4EE1E0 +:10E2800035B67D42B6950D2E0CB809B634F3C614DA +:10E290009FBE7B7AE10D9AA6A99A77FDE4ED8DCF1A +:10E2A00046A9E4D3221E17D1F784021882D552253D +:10E2B000E46B4866E498CC2917BF79467B6403E594 +:10E2C0002F53E3A015AE3A78BB7907CF83C3D1BFF4 +:10E2D0003608E9883FE0AC575C4FDE497838889AC9 +:10E2E000B259BE0425168755523B0DCF331B8DD531 +:10E2F000C205E23A52B59A501C5BADF9255662F45C +:10E300006AC789B9D22C1D276F4BE449EABB25DBCC +:10E31000EC36A21CF978262B6A24E5CD04F1746052 +:10E32000F5E65187CFE171631DDBA86BB828E33EAA +:10E3300009D3EB9E8C7214E544B67C0F44AEE760C3 +:10E34000B48B7F4A706B35C6BD33438F1BFF7BF5A3 +:10E35000AF018D1D04873398516CE453E6911B5433 +:10E36000900ACC78FBF037534E561E74674F15EB6E +:10E37000EF018ACA805C2A0FEB752DE6105859759B +:10E38000C7F9DE8F08F87D9F526E2CB0FA29C67E41 +:10E39000DE7B3BCDA370F92D6BDF78E7544DC5854F +:10E3A00061DF38A654E25B27C964B6593F36EC6496 +:10E3B0006D90AC3F546571ED0B14B24451D7FB85A1 +:10E3C000F85D4A22BFA9E494F7DEA8011165543133 +:10E3D000856D45413411C6650CF5218311F755D87B +:10E3E0009EE5D9EF5E3A7A63D454C8C98473CD41AF +:10E3F000CF54720186EE7E71A5B62431562BFCE512 +:10E40000BB79C08AA1FA1D34B88437CB7950EB743C +:10E410003B9AF51850F26510C71289E17CAD00EF08 +:10E42000683CDC71851095C22814CA200D45A7F5FB +:10E430009D3F7A840F0712092335D0801BAFCFC6CA +:10E4400044A09FE70EC4B2686D0356272B25D15C0C +:10E45000738901E07AB85FB1F86A9A65E9A185D558 +:10E4600047756E748540A756A48FF8B9091B3D0DFA +:10E4700085FDCD1BCC6B85B0F94F544DDC784EC477 +:10E480004DBB1BCC8B55E75778AACEFF3E30ABF681 +:10E49000B8B325F0C2712FC99481A71FCD51D859A7 +:10E4A0004870257CEA73DC604E314F76BE55FC2DFA +:10E4B000BB77116EEFFD9A93C85C64DBE0E97A8468 +:10E4C000B992C7712CEF6C1416FE4BE6F1D6892D6C +:10E4D000184695A6EF15D7672C8B80D01F503E4F5E +:10E4E0003F428A498F7EB70B991F7523EF214774EE +:10E4F000C12BB833EDD541C9D75096A97E2E14EE65 +:10E5000077FF3ACCF2245AB05C4175340BA7B19333 +:10E51000E77D93E0BB06A4F851B0084660EE2FE813 +:10E520004B97F8D77D168D933841DFA80E06254C02 +:10E5300018BAB79CC7FF892246ABC5966728EFDBA0 +:10E5400088476E1AA09689B060C557454133F54794 +:10E55000CFF360A46EBFE2544D7C805C904C82D7B8 +:10E56000C01F540B36067218BCED6DABD453F227A6 +:10E570009C2C25BC413CFB80CB17D389D549CF19B6 +:10E580007D4D610C389605D0CFE407C63ED7AC5E12 +:10E5900005734737E3E867F1B7D76D56A7D8A39C53 +:10E5A000BEA49F7C70408E9334FF054DB47EA2853F +:10E5B0009359B023B59F8D74174292CE96BA012716 +:10E5C000C13291F5A5A8C109965730ACFFC775B9FE +:10E5D00054485F64516F97A98FABACCCA67B04C540 +:10E5E0006F99096BC6C89CE8D4731AC02297587FEC +:10E5F000E46C7425DE85B6BC279B4D9936B74B2B52 +:10E60000FD7F2DD66E97BA18D9F0373F22DC02FD78 +:10E610005C2E6ABDE74AD918E07EF680D95FFE9885 +:10E620003D894DEA83CE4DED9B898E061CDFD6DEFB +:10E630006C8F74153430B8D5E7253553D952B52CC5 +:10E640004D2D67552E99DF2F77B8FC79322C6DFA56 +:10E6500071E173E41398A6809F35C1675817C28B88 +:10E6600048AA7A501C6CC864CC03B846B58A1D5BB6 +:10E67000E51326EDED5CD6FCF83457F61712DE44B0 +:10E680009E602334B66047F86CC7E7ED45E797B066 +:10E690002BC68AA95D2176839D92BC23BDB49224AA +:10E6A000AD8A69356E5BAAE20C52D703E70DFF7B9A +:10E6B000E06FFE143BF8BA47747B595168ECCCAF5D +:10E6C0000D263627C0842E35150280DDCB18900D1F +:10E6D0002C0ADAC78B2B2A6C8759DAF20BBCD37958 +:10E6E000FC2B2D3C7AC911A039316ED61ECFD9A989 +:10E6F00079565CFF3441A8AE229FD7920B76E4DABC +:10E70000E353B00E6DB7E6FAE648BE78EB82A6FE9C +:10E7100012F0A905D6D84F929E40166021C4E8B4E5 +:10E720005B7343B24B09A0F8623088D199ADFE32D9 +:10E730003BD96DDFCF10DE4BE41907E1507921D7CB +:10E740008352FC290F5EAF7FD0FD8C27BEF584C7B6 +:10E75000E26903A2B0B0D8F48FB294F1BB95C0D6F1 +:10E76000B81249BE2D0F2AC172240142E783609D71 +:10E770007A852188EEFB2361A13DAEE8A8516A119C +:10E7800000A4A3632C891F584458C00B8B9DFC7DAB +:10E79000BAD3260E335340198C2A8C75D889DFC81A +:10E7A000FEA47B5FA371CB8DE6BF6CE6416C7F114D +:10E7B000E1724F19073277B2484B3C11A40740363B +:10E7C00035B34D751C7EAA46DE0507EEA652A4F6AB +:10E7D0009D33285C026D874B6A53FFA3C6F02C194A +:10E7E0003600E7B20ABD67EFC085F9086A77925F25 +:10E7F00012659BF7938B9B535B502FFE3E45EE1E9D +:10E80000127AED4001762477B9AB64149A5B72BF3B +:10E81000AA4304894A0AB0CAA259502475BEFACE46 +:10E8200039A70ABC42A161999FC4E9D1F74F15509D +:10E83000C89A9ADAB8A95568E876308E59A74F7603 +:10E84000BB549D35322356961102080CE9EDE2E3E4 +:10E85000723A7CC5265DEC39DDD0F5F3BF8C8C03B4 +:10E86000A0A462CC2C0E9A507F193529FE67EEA227 +:10E8700096593E756FB0F7FABB8903B3FF5BBD5283 +:10E88000F5C8FAFB1EC8031D77344C5CCB9AD7360B +:10E89000FBBA4753672D670C61A497796B2D487CB1 +:10E8A0001ABE8EEE65A1793A06BFAF9D91AA1FC42C +:10E8B0005329DDA2FEE352D02592C9B61DE4BB70F8 +:10E8C0000ED38AEB3E82FF93E45093642F15590BCD +:10E8D000F4C4D2D1F1DCBCC04A272CAF1CB601FD78 +:10E8E0009C539261B93FA4EF9FF96E8BFEC222E365 +:10E8F000060656D110CAA266A0CD238BBDDB229B93 +:10E90000226329DA483B3E920CF1E5E9D1D50F2389 +:10E9100034DECC70163095C0D6BB3F85D1F5C62D00 +:10E920008D617543B0268B745A101B8720D24C170B +:10E93000C51A2764F06CE1362DD36B7EBB13CF561E +:10E94000908C0778460E25C6E3E4AB2310042AEE2C +:10E950002AA2798928F5992F3325B5554FF487F7E1 +:10E960006E7866353D73298A1A97AD1C3E111141A8 +:10E97000EF6B13662F847867B98303B8690AE9DA05 +:10E98000B31C0DE6453BA5B6489E1B5AF0CF7C4D07 +:10E99000178D1642BC3C1EECC9277A816333BFBF7A +:10E9A0007B9124774749385D5132142B5E5A3935B3 +:10E9B0007E322D7F70D2DCA3C54118699D085B486B +:10E9C000BB3EDE5C92AEBE8B2DD0811D2DD759385B +:10E9D0008383513C612EF0D8F0AE9C8AB83774F234 +:10E9E000B7D64326FAD8C3B8AF4D9BE6AB0F247A0F +:10E9F000EDBF9CE799A9192AFD81FF1639312ED662 +:10EA000011FE7595794377BD185640C1AF0BA3939E +:10EA10006D8D9E67D172B053A64A0DAB16729EE6FD +:10EA2000C88317195784F44E1C2CC835848036507F +:10EA3000A743A851D84FA9EC8542610B6924D04562 +:10EA4000355ED9E885D8D2FC86A5D1209938E478FE +:10EA50007E27463B38520701ED81238B2C36719C73 +:10EA600079096615A123B1D55C64303F122C9E0D47 +:10EA7000B07DAD20DAD6AF04631F341546DB51EA12 +:10EA80006ADF7653972E835A5CA3AC3D646EAE2644 +:10EA9000FAD14E55BB9E19B7B38CA13EB48FBFCAF5 +:10EAA000FEB573FB3EBCF8D5FDF24AD711AC5B3E18 +:10EAB000A4AECA57F0DF731BCDBE473B761479B0C6 +:10EAC00065AB4F98E615D491C11948347E065A516A +:10EAD0001928EBEA7BF92DC7F31EE8161E86D82C01 +:10EAE000EE6EB617FD4D447B71240633F41DBB68F2 +:10EAF000757EF990D3A4F9C538DB333CBFC75C9869 +:10EB00007BC8ACF92A3C8F6BC8291E5C499D40F339 +:10EB1000BA5759B069C0834372B384A6B663CCFDBB +:10EB2000CC299425D9ACC1DE097F0A81D8AEC8258D +:10EB30004CB44CFC6883C3EB88269E8F045AA4EC2B +:10EB4000BF6727467D9F9C44C5E4184393780F8890 +:10EB5000B69BFFD35CA435CDF44B406E263930868E +:10EB600025FEF60ABDC2B3313161C10650A5744E0F +:10EB7000D4B0C7DE3993A4D041021D3C2920A1693D +:10EB800063F06A46ABD0FC2A7EF8413BCAD0568C73 +:10EB90000FDED8E146823BD4BCA77DF09988DACC61 +:10EBA000450C8C2603E90B56A2EFD19E07052EA03B +:10EBB00095BE57BB3C2D5C0F3F8B8C34CA44120969 +:10EBC000958AB6D16201AE6469131B55BB692807EB +:10EBD000E60E3865DA8EE77DB6B91FB42CB95889D0 +:10EBE00028632F1D0FED13ABF5CE235D21787E63D7 +:10EBF00010F10C2B61ACD8DF271ABE1F9FB408E0C0 +:10EC0000AD11B732F5D7954994E64019F5097296DA +:10EC10005492EFB290B5A009DA4F2AC6576006F5B4 +:10EC2000E78F73050A7FF8232F9D21D184BC442BE5 +:10EC30003F145CA43217AFD813443EDF299377DA30 +:10EC40006827BF968D6D3A2BE79E1D0B7612DC93DD +:10EC500017FA86375BC7547D05D8E0AE1411D03A59 +:10EC60003A1FF0A429FB4E497EEB1B96711DCC592F +:10EC7000510645171BC1427C2CF75249186D8FF97C +:10EC8000013DD9B5FC3A32C1F4C3C786204497B5DB +:10EC90005E17BFFF47B212D674955C12FE46A839C4 +:10ECA000DC0D2F4FB593C62872063775926CC16E76 +:10ECB000DACCBF4B58814AA42C3E2993D801874116 +:10ECC0004EA749FA774F43EC045222AD83119CA61C +:10ECD000C3965D997688EBB7EF3D2EEFEC32E845B1 +:10ECE0009D489E5555CF85F7602F8C30A33B1EA0C5 +:10ECF000DB0574208E9B73B85A796795DAD58E112F +:10ED0000B1085A6E6A9D0A97AD4BE09B5D3B9291AC +:10ED10002F1B741CFA5A9952A1BEB4937C6B00F657 +:10ED20001B52F45F6E02BB7F5457706C4E37440821 +:10ED300052C92AE7A6757C6C7C56D3FBDD305A0697 +:10ED4000B4C95E0EF910CD36105BBBBACE40EFB041 +:10ED50003DDADDC0BEA7F70956F40697DA845C3ABF +:10ED60008C88E7FAA702078DC2C2CBDFCB853AD0E9 +:10ED7000EFBA53727867A489763FC2A7DF0C693B6C +:10ED80001A464D39D66610F8518D00DA4E49F1F227 +:10ED90007966E730E6A7CBAFCBAE9C33ED52841B50 +:10EDA0003035C19723C79889FBA964496B5A382F1E +:10EDB0006438A922542520F209DD7E5ACB9A5DB130 +:10EDC000366393194DAE2A4125D69D62A705B4D569 +:10EDD000884F3A0218B024BD5F1D5F126542A1BC86 +:10EDE0009123501254BDB8F500902C09247CF35B9C +:10EDF00009941D38078616D665B5FE84F538708EE1 +:10EE000017FB9DD721D1E74496AB2D7648557981E4 +:10EE1000DD8B207ACBA59DA7E4ACCCDFC6F1692AB7 +:10EE2000AF1A0EDA1A1D1238E507CFA4591D9EA29B +:10EE3000A234834DE14E8C1CC2632C273CF3AC669C +:10EE400063B218FFE7F513A136DF9AFDB6D219FFBA +:10EE500059D7F84F53D4B9098C461CA6CF433D600F +:10EE600092FBCC175AE2E729B05004EB9A57ED1603 +:10EE70006EF634C61BCA748F9C0635F3D79D6BFFA4 +:10EE80004347C658F2246AAE6739EC56C267FB3B6B +:10EE900045FC94288583BF711518144E03728A644B +:10EEA00055EA6B28882150E16BF4A28CC01E8C5867 +:10EEB000C1563398B640FB051E06499698A374B117 +:10EEC0008B29C1A6BCCE8F4432D98977080B18098B +:10EED0009C535AB05F1111ACA42B7099CF6A104F9C +:10EEE00007944B0D9B5CB38215FFE8FE092CBF9A7B +:10EEF00065F8845843DF8D9009928E129BA46C852F +:10EF00004EE260F63D57CEFF83BEFE0B907EE5AC31 +:10EF1000174C69BDBDA4C97850CC6BB7592F65F3A8 +:10EF20005E7BCC781F64F1592D5256B6FDB95084E2 +:10EF300015D81FB322C2B59F1A85F7A3E78B13DB41 +:10EF40007FB8865433520EC4BFA68121FA7E714524 +:10EF50005B558D2FF359F491F95A50964136B11FF4 +:10EF600063DF7A0FC52D751918912BAB128E889718 +:10EF700036F6F45D34893FB6CDB8BD7602A80E7979 +:10EF8000F6C5EA3D88BF4CDF58585B9E8311FCB341 +:10EF900019EF84A634A2FD89007670D2E31B0766C0 +:10EFA000B32D3B1CE5499EBE07ECA120A10D60746A +:10EFB000BAF4353D23601ECFED59360E096AABB663 +:10EFC000CFB45E2F4BB355A5DC2F0A1112F1EF3CE5 +:10EFD000247A36FB194B834925D50726082F1DAA0D +:10EFE000B5350E41930E24BF9B6747458FC346C876 +:10EFF00044882A5B072B4C80D80C135D341B478B4D +:10F00000AB45B41BAEE94A6F950B55B3D2C0C047B0 +:10F010008308F1AFB1AB78971E7CE931C2C4E81820 +:10F020007A1BAA7EAC7DEE6D5D9DEA56C428BBEBD3 +:10F030004CFC57EF7DB09C82CA580DEB458F71EFA9 +:10F04000D23E0212DE0F237DE00E31912DA6949365 +:10F05000E930F39CC7B1A802A270A03E830B3C85A7 +:10F060003DBC4CADB520B850914B81A008E3BAA08F +:10F07000A15B3588E4DEAEC8E5102C89965070930C +:10F080000DC5B748F807A0F76A6F94514462DC7366 +:10F090002642EE5B7DAF8ACFA481471EC97E1984CC +:10F0A00039504C4C6AF46D801C8ACF615BC4DE56CB +:10F0B000277275AEAB1E03EBCB0F29247B3066B3F2 +:10F0C0003CB8D03BC598E864BBE169DEED84CF77FE +:10F0D000B39D25FF5DE7FA4350F99A90B5D3B01B75 +:10F0E000B8400E7C0FD094E706D2BFA647CBB15EE6 +:10F0F0008640B490B9C055DA9DBA2FD7AB50A369FA +:10F100003CE39687C8BB1C6B6BD0DE8488185C1D03 +:10F1100077125864B4DFD2A135AB09B8C679A659C5 +:10F120008D8C4FF2C51399A066B413E88B263E551B +:10F13000B7FCB7A6DA71500550657A71FCB96E94C8 +:10F14000268DFBFC7C7EC534B540146101D5383A70 +:10F150007A8DBC586CB657B1EC68087B53BB326DE6 +:10F16000D020E6009B76273A5E1F5D9289132431FA +:10F17000E09D245854A306F37973DD9302F118B18E +:10F18000C7DDB79D5E571C51C4C496F0B937158AC8 +:10F19000C763BEF627FD824F0958E1BFD1C5B5A9A7 +:10F1A000A43971F98CFF22DF31A4120F5A5B275F5B +:10F1B000C5C6F558C57C83921B4FC4222797E955D5 +:10F1C000E34B55EFD0EF51B4FEBDF966BA2A628D1C +:10F1D0008A47799BF9AFD584F927EDA92D754C3570 +:10F1E00010D9766235454B56F9CD3AC20B75C90A2E +:10F1F00096C712C331D913300C28EC8144E942C0C0 +:10F2000021394D4041F0C7A35456175BF8D883C14C +:10F210005C65E221CC12E76A703B1E94EA35D9F5B1 +:10F2200073D84E036ACBDE8E08DE7197CC8F5D2BD0 +:10F23000931D5957BB37A542FD56091D4D66270E34 +:10F240008CC94426B242662D4DF7E1BFF984440DC6 +:10F25000F301E6998E33B4C86F0C9C81825408691F +:10F2600043A1EBD582A22901E5B0EFF3156880EC4C +:10F2700072B0A6509155ACA9B727BA0FF27126BD4E +:10F280005E18AF050D9D05A67D73E47F6905B45C2E +:10F29000AD845F68F3FE96176D9E6F253CD6277789 +:10F2A000298B27B39F36B744B0AE5E2C7088B3026B +:10F2B000E09D35D85C22AAA8EB774B1653BC651AA3 +:10F2C00019A94118B8D53FD9D875C1F9A947BEEFDA +:10F2D00019CE2CDE7107F10166EF81653EDD5378B2 +:10F2E000BAA891729D402ECA402138A12172A33440 +:10F2F0006EF95D58E2AF4325722AB66147CF150318 +:10F30000CD959E360941B3E7E20832BC26EC899FD1 +:10F310007E3B1443D7D30EA6DD1DA98559D00279B3 +:10F3200079B0A9431283C4731D2C05D96BAAE81ABE +:10F33000CF08F90FD17013C9EEBF1AC11C345BE9B5 +:10F3400042F7F5E4051C30474F4D3A82FFADD0DB64 +:10F3500066EB1F554150CF2ED345EC8DDE32F0A920 +:10F36000F94E468B4AF40AB966A8FA75F132138C45 +:10F37000204092F470E28D19E38D7282DA99EF47A2 +:10F380004775DCF63FC248E79A4FDE11495EBA5F27 +:10F39000F0A6C056A53C32D9863B245F5D3FD9DC40 +:10F3A00024F694786C5436C56FFA3259B423DFE6EC +:10F3B0008459CF8BB4B4F44AB3858A34E518D59018 +:10F3C000567D8FE00CAAF3A18A28B4A2C8C491F993 +:10F3D000578980376711EED50C7D53250DA2C3DD0B +:10F3E0006C6F943021896548A0BD14773D77DAC3EE +:10F3F0002154A7FA1952FA980AD18BB5C3A81DDB7C +:10F40000AC739960F7D65174EE6CBECAE03C3364BD +:10F41000CDB93ACFB71EED8CEB1694C907F750DA89 +:10F42000E455C81B769F9AFF8DB39C5A338F1C12EC +:10F43000F81C6875E4A7676C31BB06190E8C0612C0 +:10F44000A8C6F219584C2D1508E73BF6A39ACEB57D +:10F45000040984BEF67EE567F2C66A6EAF8EEDD013 +:10F4600021D36A9DE9799A39DEA35DC9E30F74C09F +:10F4700071779CC91860EA96A9DBEFC8EE7BF98B1F +:10F480002E7937E8DF4A14AB7353DE7AD4D89786E7 +:10F4900087504BED9A99EF21A677FAB0E59FD640B9 +:10F4A000277A02A61D164A998FC8E7D3B06512DDE8 +:10F4B0009A34A8A8F6A7D0860BF70BAA687ACEE4F0 +:10F4C0006A6229798048D6864AAE1AF1087F178485 +:10F4D00040473E096E6AF79D59C2A78ADA36FEB2E6 +:10F4E000D89C65ABDDFA2304187F38739601EC31A4 +:10F4F00005A5B0033500D63C8DA9277CDA994113C8 +:10F50000F2F7A38C248EA8379313AD15AAC97BD824 +:10F5100001FF022F1144033CC6DE23374038F5C8F3 +:10F520005C77F4BAC576C9A13388AA3315A7FE342F +:10F530005FD1D01BF40C542E6BB70F1C69701054A4 +:10F540004CEC246C81758FC1300F0F4B93A7133295 +:10F550004955BD4D74EFD838D88946F84A5F2B67B6 +:10F5600052D2E482781E367A89A33A08DEE1A1FD00 +:10F57000E2EC2769445263F1855C27028ECE7A5F04 +:10F58000BDD39E33B8798E7A3FD4D106810C2478CE +:10F5900065A4329CAF378DCD0435E833219CA0871C +:10F5A0005FD763D7A8A718A9129285AD63B21F08C9 +:10F5B000B3A120884DC3808C38127ACF4F1D39C239 +:10F5C000B00BBED3EEA47A28A0B27669731283255D +:10F5D0006B7B443D2E0EC879A52FD5AA4FD6A69396 +:10F5E000864AC524C3583C9FAE6C6E73AD67882CA9 +:10F5F0001FF3478D87C1297670EB5E79CFC10B630E +:10F60000B7C3E5526937027BC37F9444B1CDEE980E +:10F6100085666520B488D24D81F5BF6B262B59C312 +:10F6200087D3B42A67E4D9FC262AC823F34EDF63C4 +:10F630004E6A09970563296410B96890EE6B257DC1 +:10F64000BA8B03FD3C0638DA993B08446AB8348D1E +:10F65000862277997F4D27BDB9A67FD8AC21AC080B +:10F660003A5E2C8294B78FFB799A98ABF2F59D3E67 +:10F6700095E8D1BE80173C2F5EB7D78F0C7443C27C +:10F68000A229B46CFCA8BF8EF4E3A8699B22D551D3 +:10F690000A7A24AF6DFB3E1001727F73CF0016E62D +:10F6A0005DD080D31D93721EDCA823B85155958878 +:10F6B000FBA76B91A914272DEA18F49190DDA0CC3B +:10F6C000E76FB434EF715BE4A52AF0E5BD62CCBC12 +:10F6D000C7E3F0A3A18A9ACE55C14C11B92090413D +:10F6E000EEBB6B5D1B48B5ACE6E80DAF7DE8B7A19E +:10F6F000A332E7156E1E2E1BBF3C040D69FBE12BE8 +:10F70000D89520A9AA04E85CD50B35424BBFF0DCA4 +:10F7100042860BE4B0D39D3013D06A4F49B9053708 +:10F72000B9B19F9F15BDEA432157BFE7B3CFB29B45 +:10F73000B9C6334F2B4898CA592A0506373C5C791D +:10F7400029D73CEA34DFD4F278A0E0EFEA58F74A50 +:10F7500055635AAF6DB42F2A74251EED6E77ACC871 +:10F76000385E27FC282DA1234E84896AAAC80BEE97 +:10F77000D03E85DF6946FF0D41C6D5221CE8D8057D +:10F78000C0D120861754018B6CADD642D8B8063B49 +:10F79000BF1D671638CEBEDA7D4944E33DC84CC56F +:10F7A00007ED21499C73D3A3EEB6A98D1F6240BF1C +:10F7B000FA13EA63CDAC267338A9393FF232E5B3C8 +:10F7C000367A455296354911BFF961B4CCCC242F15 +:10F7D0000FDE713EA83C639F22789E2B237D40550F +:10F7E000B4D6148DE4597168ADB88C3D1ABF7D78DC +:10F7F000F0DDB720342F2674852C579C2D29A9477E +:10F80000038CEA2B704B5C5ADEDBA4E9CBA40C76AC +:10F810006920C007C4DE26E6CC52E1EAA8FB80CE10 +:10F8200064BCF73F9580F698777CB35DCDC24F09F5 +:10F83000288725C519B15511FA06BBE93880C26A77 +:10F840000BB7076A591FB460DBBA0F21D8DD516EC0 +:10F85000F153722968ABB1C57BF7A129C7B02F5608 +:10F86000462BBA2DEBFB1A0CABC4B4E5CA2635E81F +:10F87000676398E452EB041C5226E94CCE5B84E0AB +:10F88000B38265F5249B39AA9F3A90565858F113D4 +:10F89000E34A277D6E9F20E91502A47596C8F67A83 +:10F8A000AA662B8AF6FCA83FA78BA8C8917E6B9806 +:10F8B0007CE8354B90544C61AF3E19CC83A27091DB +:10F8C0007A23C1AEF76AE82A53CBE9FBCFABD45019 +:10F8D00073C125717FEBB1059B892BDDCB05B71B70 +:10F8E0001DE0E91F85A7A9CFDE3ACAC4442CEF1852 +:10F8F00032E1634023C657E80EEF9DB403B70F63B0 +:10F900001156A0ABB8E0DC1EEC7106889475188A1D +:10F910005E96DE5E598A74189733173E190DF18191 +:10F92000D0EFED5DBA13F464E8277BE485C4636A25 +:10F93000EF9494D6196D7BDD62DF9480F43C3EF445 +:10F940003993D432C6845292B1A0DD0ED0145767D9 +:10F95000A8D38222CE49035AC9123B55DC13800733 +:10F9600038FCDEAED597970B71DD0C874DDCEDBE14 +:10F970005B8730902E3292FAC2DEDD850E6CF0B6D7 +:10F9800018CACB41C0FF85EA627112DB8DC94E16E1 +:10F990004CBFE9DDC96B9C35C083A9C2D8AA470614 +:10F9A000E1BD4A954490BE7B88A2F878B69BC4DC42 +:10F9B000FE986B2F6D945297E81DBB5233BA6C05BD +:10F9C000F6F9E549F6C5E5BD8AC3FC5ECB65A2F54F +:10F9D000C01EB8457D0D9EC22F88788E21814005BE +:10F9E00080A3781ABDE296C9A8B43E56D3A7F9A75A +:10F9F000C1313AE2A988F1D0B0A624553E59C26D72 +:10FA000026C545EBD996AD450ADC5FACC04DDF3E5F +:10FA1000E79FA39E9C5D9F3F9210CA58E521E6F99F +:10FA2000B5055952A24110819C9968BB2FE3255D11 +:10FA30001D60A8BBE1A4819B38F8BDA582CFC91980 +:10FA4000C1658432A6FC62E61B565F46A274CB1ADF +:10FA50001280D73A25F3DF497CDCCEA01AD4BD1141 +:10FA6000EC88D7F2D25927C93F946144D41FAC81A6 +:10FA70002D44AA771F071BF33314A43CC5DBBDE854 +:10FA8000D13CBED2777ED0E9DBCAE1F37D4A7980F2 +:10FA90002D349289FAB1532937D6FBA161B3A4DB87 +:10FAA000E909154B911FA6F720720E2352E70FA408 +:10FAB000E3FAB0F5BB00591B4F87B8D3EE839A7FAA +:10FAC0003BC5D9826EE88836D1FFD172ABDB1120FD +:10FAD000BCABCE2D57517763D1BE7AFFECD9105E07 +:10FAE000E714E41FEE33F2949C20CC87D90DDA633F +:10FAF0008778735CB98C38D7FFF5ECF1BD3747C810 +:10FB00009D07635C1D238E8B945CB474681E76E83D +:10FB1000589F3101E146BC286FE706225415283D65 +:10FB2000C10DC3EFFCDCE418EFB5F4C00D66901115 +:10FB3000B1B2299B8BC8893F09F11151A06024BD46 +:10FB4000FA5B2B0C629FA7B038451EAA991E89F953 +:10FB50005AD2A7CD88ECD225B77296FFCD2190144A +:10FB60001ACA6454B34E7B748B922172A012F7BCF4 +:10FB7000EAB4CFFC42C37B610FFAB20FAA0A827DBE +:10FB80003C8A0CE6EC5919FF50D921FC7B788700A0 +:10FB90006EA638BEF98D4B8A504DCF931C0991A4A7 +:10FBA00046E2757D9318D155509DB690B780E80513 +:10FBB000767EA928F9B6A887CB46455E7E156B1FD1 +:10FBC000DBDB3587C11337CD0FC694FE9B1FED6875 +:10FBD0009412BDC8C503EC2A0CA153FD531D336913 +:10FBE0000C3128A3ADB183C550010DB5173F20845A +:10FBF000C50CD5F0DA0D9F82A4FA384E3662E27A4F +:10FC00003CE515324B2AAE67FB394E03D492FAFE1F +:10FC100025D935F9AB8B87850073B2EBE0BF0713AD +:10FC20001A7A51386F829E1D848405ABD32871BD2A +:10FC3000F34FACB6B401EEB1DB4001A6134CADF20C +:10FC4000686982C9A1BD8E32D1610058928831287D +:10FC5000F1E1A692B41FDE6AC204E00F160C9A55B9 +:10FC60009765CEB7283F836D0DC7C4DB775AE5A7EC +:10FC700050FC47A5EFEAD12F1970757463BFF2BF2E +:10FC80009FE86912195BB9C3D8F75129824BC79411 +:10FC900095364D97C3D7E625DE59492E4AEB1544D4 +:10FCA0007856B9D694C264714239AB565FCA52785D +:10FCB0005B7AC2BBA24EE2A43133245C26E76458CF +:10FCC0009D212EB73EBEC6E45CE395981E63E2AF6D +:10FCD0004186A3153BAB0215804D21381B69394A7B +:10FCE0001737B88DF312F490E7EB223B3D5F90FAA3 +:10FCF000F739E842482C415140F974C751ACEF53F1 +:10FD0000CA81883831B9413DBD03A325270B27C2DD +:10FD10003D3DB0A6C008441D008B993EF952D46BFE +:10FD20006A37E305DC7E51C4BA2EE7AAB9D176A1C1 +:10FD30000AE6EE47AA7E14D1F59FB515E20451A557 +:10FD40008A7437B57AE0D2E9123131C909689E2642 +:10FD5000763F765F13EFBE4A77CF8762B0FBABACDE +:10FD6000F2B1111B074931DCE1C2EFB7F34B2CDED6 +:10FD700077690A9AF75A6510E0521C8D1A1EA9DBA2 +:10FD8000CBF79C49A5C4EC99E4100CC09B90A6EC61 +:10FD9000D64738BFAC48E7D849E22CE511EB4175AE +:10FDA0004FDFB1CFD98F65183303CAADF8BC4F0B05 +:10FDB000E56D373228D811CD5FA469D9130193308E +:10FDC0007E7E79A211EFF6456F4063C87584C666E2 +:10FDD0003BF4A0A3AB7A51C01FC62D6220C4870795 +:10FDE000CCAFB3F376A1EB914B2AEF324CE7D6CFF1 +:10FDF000F72B1B760E7F0B05B3C2D1B9ADE07A515C +:10FE00006244B669B2F8738F535917D247D30BA522 +:10FE1000A98F59C1B4C55EB6DF7C8E4908089364CA +:10FE2000FC882AAE758001FEF59CAF3A1F27466814 +:10FE30005EF7AAD232ABBA83C910CFB5A51F34EA98 +:10FE4000784847CE71A7B5E398DAD469009E05F3E8 +:10FE50002EE8DE66B363E998E17D359462B1DB3567 +:10FE60007D63CF2C9922B48E7322FDCC8A331F6B15 +:10FE7000033014F965CD6035C6AB7209F23B45C25B +:10FE80004C6EE2E2CCD5670D4327F891E41543B6FA +:10FE9000A0B24F0F999B2C935177DC6653107E2EA6 +:10FEA00070C6B4BC2EE907F8BF27F8AD7480712D79 +:10FEB00069BDFFA0A023DDAFA437930DA604FF9872 +:10FEC000DE420FEE5515B941AD0BD8B448F2385E9D +:10FED00035E65E9D6BEFA0ADF6D1C6ABE16959B2D8 +:10FEE000EF49BF164C6A349C7A6739E3C49AB9ED7E +:10FEF000B3737ACBE933309D29005C167BB586D885 +:10FF0000FE89C1DE94496BFB500644A286AD0B1FEF +:10FF1000C4433263E337A5583A222DB174F8374B06 +:10FF20004BE364604A54D8058EB0160CF79E2797B1 +:10FF3000438C1CBF2E7B6DA07E308ADF2F781F3F45 +:10FF40007521D46D26A8EBE5044047F76A622E467A +:10FF5000CE3FBCADD1D45676A2434EAF534367DA01 +:10FF6000BFC531C5379EC5A302EAA384D87D1BB6A1 +:10FF700064B759323593D9FCBA59105CAF033DEAE6 +:10FF80004D4ECF43368BC879A3A54C4FA35AAA0B2D +:10FF9000CAFF8C1BE19E1FDC4EF905349FAC59361D +:10FFA000E7EFA8EEF4AADAC5CE2C68FD27017C663F +:10FFB000637EE0AEC62CDAF2A031082F1B9D5D9562 +:10FFC0000AAF552A8C2FE459A09169F70DD9043551 +:10FFD00016C43F3865802C4C16C698AC88633C7EAE +:10FFE00055FB5B06FC4F815932831BDC6B544A1274 +:10FFF000774DFA128B6A373BF1B5C17A01D9FD1AF8 +:020000021000EC +:10000000947EDBAA15FB74ADB5F4C33B77A3FA125B +:1000100099926C849A7743DC7B1DB2550C38AA9F69 +:100020004503D0C7EEDC16D2F58C568469BFDB6879 +:10003000464958E859C706FF8507C79B729E9CBB77 +:10004000B4A5959B41775D3BDFC1D7EAB5EABAFE1F +:100050007590907D21D2E1302405AF74208B8EF015 +:10006000BCAA2BFDFC442F367F8A2652C557CD975C +:10007000161DC3774E57A1ADB75E725E44CBD15407 +:10008000F4FD7B976573DD23A760F1CE94E47D5189 +:1000900087D28395608BA2EE928B319DE70967D55D +:1000A0004788A425906D1C3D575DF070B9E427DBAF +:1000B00040CFE0E079617F276702B0ED587024A758 +:1000C00021919ECC6F659332A65143CA8EE111B740 +:1000D00083F1092034131ADF81F03A42E75080EFB0 +:1000E00003CDD50563A3967A1DDD4557C79D5B58A3 +:1000F000923FE7535BD076489D679C72EEA2E5A7DE +:10010000DD38914288467464C37048B3BBE9519AA4 +:10011000984887B40A4F6DF6CD839F5839183F6EC3 +:100120009C48E29212F1A1A3BAF545B5670DAB4325 +:10013000AED3B846123FBD4C1E7FAD6E993EC6474A +:10014000683DA9C759A48E70E2303C4D359C94633C +:100150002202AE591C037346DA26EE25B2735F58AD +:100160000A27CE7C62699729381EB16E3BEA3E9A17 +:100170001E41B99952D516FEA6E3475E81EE3BB704 +:10018000DC7699712D1E00645FF104585D2CB5DB9F +:1001900037694C2B48A27477B5A208D1B38A484777 +:1001A00092635EC2B1B8B9173D445110985C24EC1B +:1001B0006A7A725101B85B250B1B1F472CA534DCF2 +:1001C000E57E74383EC34431376EDA014E7B087BDE +:1001D0003B7FB1A0B97DEA1662195EAF467417E2A3 +:1001E0008B636B56E94354AA394D9CD9019800039F +:1001F0004AAD820C9ABC0A44EEB3CE11B703F29812 +:1002000030EA6AC06B5E7A67FEF782705BC7EEB059 +:100210006CDADABC0BC9B121DBFB420D71A1FB1F0B +:10022000D3B44E751B93BA11785320A12D3C945929 +:100230000F5B7A3C3B90D5E4CE950012757B8355DD +:10024000A1CCA24A296B487E76BB415B586D5A68A7 +:1002500068147FBD4E712920CCEFD961D4A261E230 +:100260004458C2E19830A6658EB4C63B6EFACF42C0 +:10027000BA4522C96D2D4EF95BBB715A840CD78FDC +:100280006F6239F1A7F42FC8AF354FF75AC5361E44 +:100290002507A239CF2582B5A6A4D4BA6399D81967 +:1002A0002B79C8D7347521002357FF8D21B92A6DCA +:1002B0001CCD2C48938563BA3271996919C9ECC178 +:1002C00068D447A38A5C48663BFC5C85FFAC0E960D +:1002D000DB2DE9F676B015D08E3A7DB11F39A91F16 +:1002E0009DBAB68B5486DF7590FE060D8DBD8107D5 +:1002F0009F19A0205BADEC39FDEA3916DC05706E64 +:100300000598FA581B1EF454A090F694E5990952EA +:10031000FAC13FF3DA7809AA1A312422EBB0B1848A +:10032000D4F9B3B85583992B35B0D7206D1A1A3943 +:10033000A3E91CEFE4BED900F3C4421259FF76AE24 +:1003400015A1612CA519F6417786AF37AD1FB831DD +:10035000C39128F1FB55404A4CA2C738F72FBA93F6 +:100360009EBBCAF06C9923C610ABDC141612FCEBD2 +:1003700083A4E0400691B22AF4C2014D9DAE6E689E +:100380002EE0E77554BDA76AAD1F9DBA87275BF4C1 +:100390008C544DA18B4723194996F2B232667DF0F9 +:1003A000CE26A52EDC52D5C3A0C8EAC7662B199D60 +:1003B000E1046390EE9CB6E0F2F4C2CBC8C91E9093 +:1003C00026C99B03679C68999AA95BC9AF62C9FB60 +:1003D000AD63487559A342CE7AE85A556677885E70 +:1003E0002A487065B59E0D0DAD33493B80C1D105DE +:1003F0008E80E47B755598B7F8CFF4E08E72EBFEF3 +:100400002C8CB83B7DFE4C8DF6B4D06E2CFA893C1A +:100410007A8CBCB9B40E6B7C0B4BA7C64178B50A7D +:1004200097FCB7C9E87B8EC965B4D3715011535B93 +:100430005372EF0B1BCA1C634131DAA07B85377DF9 +:10044000EF69293C49BD15540EE6E159E10602EF7A +:100450009966135DEC3B63D483F10BE865D17120A1 +:10046000E688A17F6530DAB8E5199FA3F738D4EBA9 +:1004700049BEA6BFACB0EDD298E49B4062580CAE2A +:10048000D55E4B886F96249EFC5EE8D623158B22A2 +:100490002429C38D780B7C8F305EBF729A015A116C +:1004A00032D9D8E388C80C7575C744D582B564893C +:1004B0003497C19618ED04C990EC697BA901D1D19C +:1004C0002238C74A6A81650B20C40ED6611D063BDF +:1004D000BD75ACE395EBA96A039F400B3964518865 +:1004E0005C488924F652FBB7FB3F7F8444909A8B8B +:1004F00045C842F10357B47D48D80E32110E54A7B7 +:10050000820A0B590E6C1D04C310D15EBBD21E377C +:100510000349479F316370F6D956E22EF532794E82 +:1005200021645EB21B13A778F13B026A5CDC03AA6C +:10053000331426663F3400EE427C1E04FF62C33350 +:10054000D4AA3B611B715A83950CAEDD41242DE189 +:10055000089B29B885FD6DCAEE9BDBFC70DE8E61C1 +:10056000D5EB38209B3DBCE6CAA801F6C135D119B0 +:100570001847D9FB80774D925B2E25133287953231 +:10058000054E5DD637D5941672EA8216852E0F87F2 +:10059000CA1E6725BE604D66804379C1F6101703F9 +:1005A000ACA3CA64B2A08628BF253373D731B8C9BB +:1005B000EFE263B23587D506E724AC411B37E4AAE6 +:1005C0002319BC99B1562768AF62FB4E208424CA18 +:1005D0003BA036BC0696288062913491F0144BA55E +:1005E000D0E4E01E13D624CCF595F9FF0CC5E41732 +:1005F000A623B0B0A2B004239CED29393DC87AC02F +:10060000F32385439A9D3E16D4BC70A5FB247CE45D +:100610002636678DEDFD50B109BC39A547C23719A3 +:10062000DF1B543F151699F2F8C3FE2C86E82ED531 +:100630004FA34E612439055E7E5A0EAA94EBED2835 +:100640008470B9D75DB5736D12994016DA48C2A1AE +:10065000ADA8D74524F01FEC0B312CA79DA218CED6 +:10066000B550AB32276F3CD38CFF8EC49AFF85D038 +:10067000267E9AA1DA0EE9A111B5B822CAEA0B19B1 +:10068000D1961D56F65D8D67886FABAC75ED87D141 +:100690002C58A80A5D1117983700046BCF49B95A36 +:1006A00080A7A37F97325CF32058FCA200B3B8EA7E +:1006B000B1A9EC631B154D6D046D5258F925D86333 +:1006C000ACE1803E0512A9E2553B38B71C2DA34290 +:1006D0000A13E58E42F011DFE4E6207DEB2739B8FE +:1006E0005C76A11FA38F4C327B0FF8B544AB45D885 +:1006F000629F3979C9319B465F29ADF5C252C62543 +:100700009CDFAD4FFB1F5EF5F3A822D920EFF790D9 +:10071000FF48CD4BDB33CD1A7DAFD3C34D9E06DEF4 +:1007200029223F8592969FED447F2A5B6DA6C16C7E +:10073000EB79B176FEB08FCC7915E6D88DD802135F +:100740009037FFC1F2C11D399AA0C87ACABCE5230F +:100750009FEAC7D9116E3C19C5A479159AF3F9031C +:10076000B13F1AB8B08EF56654361726D9A8FAE408 +:10077000F2903D43621DCFF559E93093107B4D2136 +:10078000B0629A612F616885BE6A9C11BD8035F8A0 +:10079000D9AEA04E76076A8DA88B5871EB1AD3C4D8 +:1007A000ADB6B5097D3008FFD57ED0272716292D97 +:1007B000E2C5071F7CADEBF88D6776C0049BA715DB +:1007C000FB8D3B58197C5ACC84F32FA7CE0485159A +:1007D00043D52C76EC53186749DC0E29A7BD392583 +:1007E000C6259902AB3EF701B6F3884FEAD3AB4971 +:1007F000E0FD711798C168197C2761ACCE84B48381 +:10080000BC84600F7E5332461FF50408AFD044E02D +:10081000BDA200BCEB1EAC13CA199EACF225453933 +:1008200050FD783CAE7BE2F56123669E3A7371A77A +:10083000C4FEEA6086DE56F936DD5628DF897D790A +:1008400046BD045204769DF2F47C38876C3A3F2909 +:1008500017B51E5947089AE037C1340D923CCCA118 +:100860005D721A4B1147B152A67E6F11EA94693A34 +:10087000DC18129D8FAF385ED0658C71742215AA7A +:10088000108C438054321B26E3B1AD67EC14C16673 +:10089000AB9A46A8D614DB76DE374AC8E6D11D747B +:1008A000AEF8745166C2C66FF7C3DDB93AB4416998 +:1008B000FAD39C1BA6240863C489514AEC4907B5A6 +:1008C00092285D4CA5A758022EE785698C9E39A019 +:1008D000495C571D44457CD802A74A1595DE2C9DDE +:1008E000A5F20498A17787E5AB4CE7DD4F48156189 +:1008F000D30333D81A9306E949377A1A5D1D643752 +:100900007EE46924DFDB3109221493119D8912B939 +:10091000ED4F2FC02C884D46BD84187B45F769AB41 +:1009200038A4909246186EB10DA56C0764F206BB10 +:10093000BA0FDA83A034DB3561CE3CAB307EA693B0 +:1009400058D4FF02EDA0C051E48A036DA300A9278B +:10095000999AF9838F207B912294280A65467D0F0E +:100960009165BF6D105131189C59840B8D9648B319 +:10097000D97C224623613B280C133F4AAE90350EAA +:10098000E3938D174EB8B116579AF8622FF6651F8C +:10099000AAE263685CBDB6026BBAC76B88B48E38D6 +:1009A000C3D7BF49F83276E4907B15088695BE918F +:1009B000DB723ABB89147A5D4B937ABB7BA2C78802 +:1009C0001268905B3E78A542520721FA1E91DC9A8C +:1009D00070F4F777C08F7EF3649D09F8C5FC97ED3E +:1009E00060A8E57B91BB56FFB1A0D8A51F512EFF93 +:1009F00090862924AC6B181768B63E5FAA7F5071A9 +:100A0000538143CB9B1F0CB3944C84F1BCC0D71FC4 +:100A10000013EAD840D1305975E7B895762142BF26 +:100A20009C60148FD2430C852A95C4FC360AA5CA53 +:100A30005228A089924AFE8CF1E3B87B09FAC4DC03 +:100A40001F533815D65B7AA0722066643AF70A9A6B +:100A500019EE99A5BD6F3B0AB38193926D926CB26A +:100A6000F2397EEE7B00A00D6706D7DA6FD25B000D +:100A700010B6E907E5E40EB997DF9E960108816894 +:100A8000FA8571D943E838B71C788C54025B0C8323 +:100A9000F4297980987C109DF827EB24E65395FC87 +:100AA000F0F985E9B68966F61157832D4BE41E0EE1 +:100AB000D73D5435B2F449A67529F8F01789819EBF +:100AC000390CFAF08E98349F12E93EF262EAD7C9E7 +:100AD00046C3665FD62CF7843427E33A92F433A0FA +:100AE00031936B1EC873ABFC21E30DCE5CFEBEE4FC +:100AF0002A9D3A389FC7F2BD49CBC5F6A88F25E39A +:100B0000374664AEBA7FDF860396A0AE0E90D2ED74 +:100B1000453246D85744ED42D17DEEA9AD5310CEB3 +:100B2000C88E9F2FC8B9F51BB8FCE1FB470A577761 +:100B300028522DD8035D036207348E61F281337D24 +:100B40004F7878B58F3E6BE4502C7A694DA8C73248 +:100B5000600C08875BB39332866CA3C26D42BDE71D +:100B6000DCE98B5320A1A00FDF8EAF1E720E26F69C +:100B70003C3B62C6F4BD43C65D48685A5811E568FF +:100B80003CE3E0A326C818B1F19C1BDC3C8F222D6E +:100B90006DBACB38442FE67DA42EDC0955D5A8FDCF +:100BA000C029E98B80B367896632B9A76777616D21 +:100BB000D848B99D7E73D65A801B9778C9A76D22F5 +:100BC000E8BB2A9C34E700B69EA7BBDFA62FAA7E0F +:100BD000B9DA2F681A477B0ED6A135AE122ADD3658 +:100BE000C058A5EBB2F85C1A73A54C90D07399F17C +:100BF0003A18C2661C626102351018F7FF7751D9A6 +:100C0000E8E8BCA09E020F4D2D6CABACBBDCF086BF +:100C1000CBF046FD2A4E64139C5712D743246071D3 +:100C2000BDBB6C1DB164C2B21EBA24EB91624853C5 +:100C300019935F3A1136D118A5B4B1F603D61EFA4E +:100C40001EFE803259B233EA8CD6C43F4625E5B148 +:100C500056DF2D39D9E56DE39A6440FAA32F982128 +:100C6000B8E5F22F2E53E169892339679D88EFF8A3 +:100C7000D8CA34277801BEE48A30E825DAAEAECC93 +:100C800035D00E40148E9A4BC6261F7AB43DDE4FE7 +:100C90002E9F81E02739771F7D80B571EB9E6DF324 +:100CA0001FD8C18F5F5007227C0F853BF668CE3D71 +:100CB00041E1B14C8558482E856A3441D5678A4058 +:100CC00076407B6FFCE3EF1517B50A2B737606872A +:100CD00010B208129915D997E147AE55BDAC9C28C2 +:100CE000A63EBE182F470F9B97DA8FF51E948F995B +:100CF0004A0259CC3597E137663519E266E65C8CD5 +:100D0000AF9CB4BE675D6B0DF49DA98F9BC33A0287 +:100D1000DDDE7D2BD593F135DC80508C6230D75AE7 +:100D20008A96F7242F30D9611ECA3E787D777833B2 +:100D300019AB2C9773B3166DF3008265079D71BCD8 +:100D4000E5954B8D06A8E6473A178B109428B2E23A +:100D50008CB7FE57AD2927BAFD397E3CBF7EB31450 +:100D6000D450F67E19A4037FFBB6004F7D76BBB648 +:100D7000C4208E9FB0AE631F1BF76FD437F4D56BC2 +:100D8000016D4D596CE2197DB9FD6AF4B1F4F0E8DA +:100D900090372831C2E92C324D702697EF9A50FDDA +:100DA00005DF4FBEB893DA9D4E614FE9D71F7B76C2 +:100DB0003A392614229DC4265C09C27D30C3487C82 +:100DC000E0013EA032213510CF8F91F1ACD66561A4 +:100DD0005C6EF6F6F9C65201779E6A415333426261 +:100DE0002D6DB8B66BFBB1D5B4562AD71A55AF7571 +:100DF0008DF2C6F94E4D76060B0AF5E3549FE600D8 +:100E00000F00F795CF1EBCF86AB2DC1B139F45217B +:100E1000A29CFAFC61EE27AC3E8C200611C3A3A570 +:100E2000E45E71D49221C0882D2298803FA455920F +:100E300014EB0B5800D75F6B2F3CECBB218BDD17FD +:100E400016C339AB3EB0E410EFD0F20D0A3ED8EA3B +:100E5000006B97198CD3ED2C5B47626C939AC58D10 +:100E6000DDA94726D7E5F188E2F0A88D0BCCBAD3EF +:100E7000D2FFF002F3DD61B1CE178DD1EF27BD9621 +:100E80006F8AC730424111335A57F2E21A1A83A0CF +:100E90004E099FFBEFEE28DD24A09EE8C52BC5EB95 +:100EA000D373CA1736B0F30BB3AB6DC718DCE20AC5 +:100EB00098C31DFD8B698597BE7A01F9AD83E0C0AB +:100EC0007615A8CEDF80FB5A848C0E4DF5EAA4B7C8 +:100ED0003B8F94B167F373EE816112A08C22BBF556 +:100EE000E95A5E0CAB1283BAFCA3CF9B8991529E48 +:100EF000AFCB245F15B84ABC726FB5E22B88FAF00D +:100F0000086F1443EA35AFB08C497B8464070182D3 +:100F100083B76C3AB75C07CE7FE3B598277BA71CF5 +:100F2000CE3C56D40613F1A418A16BB0A774344B71 +:100F30007436B5AB869C0E7409AC003D1457DDEBDE +:100F4000D58CE5F089F41E3E712AFEF3168047AE7B +:100F5000DCB395C448EB0B60F0D3CDBF6F768EC881 +:100F60003CD88E4ED5D6634CE52CFA1BBF2681703B +:100F70007DA5E0ADCC493477D570CB036FD21B1A79 +:100F80002E03E3ED0F38BEF6316BA330E7BCC09AF9 +:100F90009E9F89C9158954F7E55E35C11E0819FC65 +:100FA00069F447762D2A9095C3EB6B913C4F8AE20A +:100FB0002E7AF17E49949E5404A3EAC1C43B3FC4F7 +:100FC000EC990A7729710536C04CA87274C411F5E2 +:100FD000C3A7594A6827B56BAE554B4AB97A174B28 +:100FE0009CAA994AD62E7CFA4DA235FC198B0DF994 +:100FF0007E732ECCD6FB4548F695AB0C53A1FDDA9B +:101000000FEEB5A4FBDA650D2D5ED13CD997D13139 +:10101000DACE68ECE1546E52DB02C931BE05CB0674 +:10102000F195152A580E27C7BB7848EC3718905E03 +:101030005374EC6692F7A6E4376B6C3B10C615A6AA +:10104000B7EAE80134503EC336200A03319826C57A +:1010500003B764E2B976C4A08B9E4AEFBC4F5262DC +:101060002A71289385DD215A9FFEE4289B3D2AA4FE +:10107000FEDC3DD2CD248BE5FD86251F20B5EB039C +:101080004EC1C8CAE1073F7CE92EE92092FF553ED8 +:10109000AC6DF5D403A2DCA6EA38240391A97C77D1 +:1010A0006F00DF7ED44EF9EE1586E7256F323E4E97 +:1010B000EFBA00DC769A4109A8F369916B73FB8360 +:1010C000655DA4C2DFACADD917A8D861D99EB0BC0C +:1010D000E3CBD6822A4C6EA8B8F42A6BA241857D58 +:1010E000D27DE81B8A7877C14E2377B1D141BF2DDD +:1010F0007BF999F585170A4A29A8F68266682AD1EC +:101100009EE9FF62EB70B86606A874550667DCF8C6 +:10111000A84C86D15646B66B6B8CCC3F795376B5CE +:101120003999E9D41B2C8969914503589103EA52F6 +:10113000A72D7454E7BF7DC32CB33548936E95D764 +:10114000550D6C203C22ADAD0C84F79C82874B3151 +:1011500036C36F08CAE6A345742D22584AA858DB47 +:10116000670936C84BC8D8740CC4987CCD2450ADE0 +:101170006BF21981866A17FB430828A5CFC152B2CA +:10118000BCB961DCF005A19B0D7B2299B8DF2D1B5A +:1011900084B48148FE4EE7360028CD02C72BF255B5 +:1011A000289FA5FFA6289C233208182711DCDB37CF +:1011B0003BC2C644355F110F1AA085551AAC9B7E01 +:1011C000E580CD9185B0E9A20E30CFDB30A28D9FB6 +:1011D00091353ABE359AF89FFD9894E5AE4DC3041B +:1011E0005DB172E66E0D57CDBDB90B2C07E66C5C98 +:1011F000263605210A7E15B5B377EF2E9D8106F8B8 +:101200005C8E9F104F4AF5B7F97C47AB2683E70702 +:10121000041456C86BA1710CDD6918DBD149B9AC57 +:10122000869EF212D667E8684E43C7E166101C84BA +:10123000E4A27B3EA04FE84045D7082455F5C68F71 +:10124000A73A8B59A9E6E0C3CE42E2152EAD8955E7 +:10125000193167909F75F5E180FEBC5FF8DE558619 +:10126000105BA1C03C9F86E26714C77FB5D40EEA2D +:10127000B66412FE1D4AA7823D08A8EDD109BEF34F +:101280002E22A48D402A31DA344908617670C88D47 +:101290007361FEAFB2A4A79FAA6AEEF5B7B906F6CE +:1012A0008680865BE9B1D089B7E59EB64656281E92 +:1012B000BC84A10E9CFAB0FEFC4A6E9320A5E01DF2 +:1012C000C61347B8C9BAF2D7E5AB28B9CDA90F3CC8 +:1012D000BD363B484C83915B50A144AC7F5820ED18 +:1012E00054561F93DE9B5944A583F802D7B395014A +:1012F000D50A83CCDD843DB4C6FF3F2B6F1D22DAB7 +:101300009F3104B3C1FAA2C4AC74C4FBAB1C2F560A +:10131000DA22991DC469835B253BB80C0A20BBB94E +:101320006636C4302601A9217720CD1CA6E9681BAA +:10133000F6F21405AFED17A4CC1220EC615F931EFA +:101340001DC366C24CD5078798DBCF7DC1FC944D89 +:101350008C3B0138E75A8514A6DC4406775B25EA06 +:101360009DC67AA490008D4DE012981FA04ACDD260 +:1013700016A59496B16F6A7CC92883C0A9BDEF9F5A +:101380000A150BCC83C2654BB129300DFB72396154 +:101390005A92B0CB896AF4FE4E9F07A22EAA2EB0B5 +:1013A0008AD2F47D6FFBA1349660510F7F7E9BA0A3 +:1013B0008113D7136371E8EE1539AD48E6593381CF +:1013C0009E3F6AA00702D6CB56EEA810E4529BEFD0 +:1013D000AA52794D6BEDC952EBA1CC4D89E98AB087 +:1013E000EBC320EF5DC6E6C69632468303A67ED0E9 +:1013F000AC89CF5C9B01F70293B6BE62DF47AF2B8F +:101400008812C106AEB0BB66DF13F4BF7CDBB3DC71 +:10141000A79C8309EFA30EF7A299603D22AC406E12 +:1014200062072F582CB2EE8911B99384C4A867358E +:1014300074A202CBEAEDF9BE8AB63AE63B4748729F +:10144000AD609DF578A2926EDC9EFD5E5A7C6CC507 +:101450007C578E5AF31E297169ADD0A0E1C550F1B9 +:10146000E87A9D419BBC50EAE35755003D2CCD786E +:10147000AAB191C2178A785A55BF7AB9A41849B54A +:1014800027D9FACC3B1EEC7616903C28A1734FA7C7 +:101490006E526D2788CCD7BD23A6DC1405445D149D +:1014A000319A44B3515FE9270772340F3121C1915A +:1014B00036EC8B436E9DE8833733B5DEDE8623E45E +:1014C000D1C6A2F3ADE99567F062FEF6DE9988F722 +:1014D0001D195C374A3D99C3AEFFE6EEB07AE65D72 +:1014E000AC88632D4E6A621688F943B7E0AD607D23 +:1014F0003A2EFC076F45B1D68D0743F343CFE1C8C1 +:101500005FAA5ED29C337C1703D5C8F05EF42FCC63 +:101510001409472BC7079A2D785BFB726C87C55857 +:1015200017B27FF87F3C54CFF083C6C0DC9EFA1F11 +:1015300017F89B43838B4A05CE9857DA14911F7294 +:10154000EB153469EF94B646677BA7B5412A74C69C +:1015500010C20D881E1977963112A7C1E1A4211976 +:101560000A6489C1614F7203F4DE014BCC944BC015 +:1015700084A635A74A5158EAAA950BDC0FF4646D8E +:1015800013E0B3272D654159A31A543161E83A603D +:10159000DF6053CA82C3A3EECF3FB79DD49E8DCDEB +:1015A0009CFCC14457CC163013C54947F1EC245676 +:1015B00065153B4DF31BF692928DE4D5D15FF4FC9B +:1015C00082A26C01F6AB723BF17B19C858FA6CA988 +:1015D000CD1DA1657AFCF3672DC0E79CE64F0DC1D8 +:1015E000D450E496DCD1F7D31735C49458F8148559 +:1015F0005DACE58B87AF281DD8AD159513D521259A +:101600008EE5C589C7CDDF5555A1DA76B7C705A6E2 +:101610006DBF0BB1198CA49FFDAF4E7B5CFB919D00 +:10162000FD094DF030C10EECD03274CA85C1E2D54F +:10163000F3105BBED4B497257A9130A633ADBE8A41 +:1016400082731348B01BD439DD6B7BC6BC617C64EC +:101650008AC646DB3CC694ECBFBE04FAB24B127796 +:1016600010A9E86F5763FA4215843D4A43011F767B +:10167000450260765C5CE8B448A70BB8CE8AEDEC16 +:1016800086909CA338B1595B646497256602B7784D +:1016900042EA7C5F67EF56BAE9EE326A97E50911D4 +:1016A0007C55E4E1BF578382A57855A5CF83B288E6 +:1016B0005FE7B3CFACE2C80F0194CF6819D518BC6F +:1016C000DE12AE8DC8DA88C891B3F7EF4961B8E38E +:1016D000E04594A9735EAD1F82DA00AD0CD23521CE +:1016E000063A5EFA0FCB3338066A18542838DE0300 +:1016F000D9265DF797681712F7890BB1C5DC28CE9C +:101700002A658E1B7C1FE4800A94A1D8E76D6FE8E0 +:10171000F79DB36946BB46066878F32EB66B96B95B +:10172000DC532B3C93529FF267317C6A392611FAC5 +:101730007BD754C94435CBD63CB8B3E0D995553E98 +:101740008ACEB677C0A9193255D2AF6F6874162306 +:10175000ED59F3F013E2C263794559E68BC3BCD669 +:10176000BA66450A6FC9379038EC5FDC459A87E561 +:101770004548867E0ED1D5F29ECB38954CE6C47195 +:10178000879260803005924445ED47C0EACC242919 +:10179000FC589AD02BF01A29DF97747DE3D945D3F2 +:1017A0004F69C66C30FBC63D5B10086B23BD21063C +:1017B00008BD746D6478FEA538D27B54471766C4A3 +:1017C0008EA9F7DA28F017863C9279CBC01C587F97 +:1017D0000F000C441E236997131C549FB17210FC18 +:1017E0007BD1534F249157A1CC3D66F6A7DF87C22A +:1017F000BED37C211239D923BCEE5E1E016DE57388 +:101800007F7951B1DAD89C68D5D56D5B3B75AAF765 +:10181000105C91D58B782ADDE4A356ABCC7F742B7A +:101820005715AFD0A760562F7B4CDC2931F1D1D2B0 +:1018300037419113BC19E71DFB998E0565D46ED510 +:10184000452B75B0D654D04E41E4CFE3CFADB40EA6 +:10185000021D7E334AC6429A92A1E587B6DE9715ED +:101860005F0791EE7AA15F85F8927BD98C999253AC +:10187000F13FE2373344880E6F3DCAD7D770735DAE +:101880004802BA6133647CB3E2297291369764AB43 +:101890006D568A1E4BA83714806F06065631C60E49 +:1018A000F4E951B3FC231FD58E079F2484AB149019 +:1018B000CE5739ABFDC54587DB5D4B9D3DAC2EE179 +:1018C0008C350376A4235062B0693FCCDBFCBCEAC4 +:1018D000811E1654B0173D10AAAA83D7F5DAAFFBC4 +:1018E000F2D9895F5CACE177E1F1A170B62F6A565D +:1018F000F373E722533532616FD957C2E8DEE458FB +:101900007B44AA6840A6D22E56B0D739B7CC7D24E6 +:10191000A1E6E29EA518978A1F2E4686EEEF960D49 +:101920004E81236F6605676980A16B5D5893A60E93 +:10193000390765EBD7F48660FB3A7A120770CBA2C1 +:10194000C1CD4FCA74EA38A9E448B038D7B949A51F +:1019500034286973759D07554327A3925CC7C86FE8 +:10196000EA1ADDE63D5BD53CD3506C5162331FE98A +:101970001D7AE409527FA65B886454942011424E7C +:10198000933A70E21DE7D372085DA5D99716861ABF +:10199000EAD336557672BC12F41ACC768667DA65CD +:1019A0002A59FC70E580EA38AADDD6E7CE0DA260A0 +:1019B0009AE73D9B8236A2E5EA2F2C13B6F43E9DB2 +:1019C000A84131C73E449DC5B9F07166DFF9748600 +:1019D0009042362C06F0903D68B39241FF45CC0012 +:1019E000DB1B37A854FF679838748952B51A35FF46 +:1019F0009DF28C7071FA6313371C4FDA26A9EF4AF7 +:101A0000CAAE585FFD17A159B2908325F344898C63 +:101A1000E6267A086C36D1FC4BFD9D5DBF76CE295B +:101A20004151BB39060BAD7FFAEAF5DB3F9C9D9334 +:101A30008A3A16E30CC6B0E335ACB5121E5C2B86B1 +:101A40000D7A20AE6E65266A2711865FC7B42D52C7 +:101A50001D411B3C6E38D8800CBBC3092EB8D1E8A1 +:101A600074240643C4A27C77143E6556881E04770E +:101A7000433A7C7EA7B9A5D7F03A74FDBB2E413519 +:101A8000FC9F938146752963D44097118F3AED3DB1 +:101A9000E1FA6B02002D8DE25FC1159C75B9C3E5BB +:101AA0008CA7AA768FDF45FD13CBBC1C51DFED76EA +:101AB00079226752F1CFF669D5B6AC927D6786D4AC +:101AC000C5FBECF384FDFE13A7AD8CF532CAF2EF33 +:101AD000D3629FF1A1BF257BCE06BDBB1F67E2C6C7 +:101AE000492DCAE2A72C128FD031B7E0DB536D82AB +:101AF00037AF09EC9F1DD64F5CFB278FF76888A98D +:101B000012E30EDB12C6950CD1F2E7AB5D8E28C254 +:101B100096135EC5D9A0F8D30C53690D09E8A53119 +:101B2000DF40BC13668F5EDE02D763AAD3BE1263AA +:101B30004FA4728F6CF3B42C731CFC20A0DE590BE5 +:101B40001B16D61410AADB89FB7946346A114C8621 +:101B5000DC7A627D193BC6F903670AFD8E21E80C29 +:101B6000E383080968FBCAE98D7EF5E3E7409AF74D +:101B70003D430522ED5F360BBFEEA8CE75EA4B273D +:101B8000C53FA2F9192B76CAFF816D190250836BEC +:101B9000EBB7178CC08E6A0408431F34EDAA468346 +:101BA0003D3601AFE316C150914D5CB4BBAFEF734E +:101BB00010500E1FCF5D53AB703535ACEC0ADD3ED7 +:101BC00073A527F901659754311C6E8074B89D4345 +:101BD000430D040FA40F0900F1EFD492445A42437D +:101BE000EAD1B55C24ABBA113031EBA9238D0FE7F4 +:101BF0001946549794A1A3FA3CA6F33FE08AF984CE +:101C000012C3973C9B5385CFD537E0EF5B0C087E22 +:101C1000E99F15F4F1AA0F84AC5A0246FF4798C415 +:101C2000F5EC3D7D1F92082533E3EFCF04549E5D14 +:101C300048A62C973C13DDA2DD596B2D204B102FAD +:101C4000ABF318A222EA2A0E5BBA234E7ADE316485 +:101C500081D2B51D31F55D911BE3972D87E7E22B0E +:101C60006422A72F5464BEB29B6B2D5163426B3E1E +:101C700059E5B0CF1027626C6B5F069A315E78A28F +:101C80009E899A99AAC1BE4BD6B1AA9C71947E181E +:101C9000B4AF4494C469076F341BF0B29A1E348603 +:101CA00023267797D2198F6E01282FF958F0D8E2A2 +:101CB0008F0CB393B9DC6D70D76A7BCF5475CFD3DB +:101CC0005426A7CD10CB52C14C822585B1ECA96B0F +:101CD000970F5CE1AB19DED9DFF204D6B827992C57 +:101CE000B075696387CB9B0B5CC506FB959F23DCB6 +:101CF000AD6A3DA5D051760953FBBBA39119EC55B4 +:101D0000B9AD02D342A4F6DEBC99F4AF0E7DB64D58 +:101D10009F61EFF1C42B8017028FB75AA47723A1DC +:101D2000322247C76E1F48E2E124A86927C54CBF8D +:101D30000903F920FBAF52D33966784EF71D5DAD2C +:101D4000E3BBEF843EE65642BE427307B7FD257DF6 +:101D500082DFBEC7CDCBF3173B2E590903D0692DC7 +:101D6000CED867DE996C9E014E12A91693562A238F +:101D7000FEAF86F198BFE318BBBA05F8568F58023C +:101D8000AE0C6F4A0BD297B63909EE913F443DEF46 +:101D9000FA28A8FF61207B90C7FA796978E91FA12A +:101DA000DE2AEC4BE18CC396A63CF1EB99CE8D7408 +:101DB000A5F2C9B009FFBB6C67E007037309F8E936 +:101DC000E68DDA35EAAC51688BA0E5C7F7EB793AD6 +:101DD0003548D0910337006C585B346BC2640EF603 +:101DE000329B1742F78747E10C50A0FA0AE43A61A8 +:101DF0007F94335D6E6AA1B877EA375A69AEC690B0 +:101E0000F310FB55B28E477446E2B0618398F6DF5B +:101E1000860F4CC7A2CB54919B002C06FDECDE4FE5 +:101E2000A160A88AB84223C673B16A434BB1653337 +:101E3000C8DDDE5B117C1C0CA9C92B7C1ED0E8D947 +:101E4000B23232B505CB20503F07782CC243B0FAEE +:101E5000DB0C74442CD173857270925D25837CC435 +:101E60001DE48742F71775AD190720256A8A0B2DE7 +:101E7000152BF6E6E94EFA60507F42F05F80433C56 +:101E8000B8E8F4F2A12345CD695308014E3CC811CE +:101E90008E15D80134606B804C83638828BDA6A45E +:101EA0002ED82BF32063A019088C79136D4CBF0D2D +:101EB000EC73BCF71D6B7C239A7946B83E15F98606 +:101EC0004FE344E857BD2F8FC048FFE7D4B378CC29 +:101ED0009CCEE72DC0806B91E44DF0D4EDEFFF9CDC +:101EE0003C3F4D79B4244A8529F050191A8799D579 +:101EF000267E86A25EAA4C3B8ECE17CAE8A0BD3ACB +:101F00001CACBF17FD566CE27749229142427C0D12 +:101F100004344AE3CC7FDCCF53CA10ECF4F48C05D4 +:101F20006253E6D58ED6362273FA93AA2C4FEFC8A9 +:101F3000CCB9F91F2D5954EE85D3AE962590199C36 +:101F40007F957EFAFA21F428B768EFB4C819E01536 +:101F5000159ED53C84D778A3B35078437927ACD06D +:101F6000E4D02553F35A500C825CE2745D915DDF3E +:101F7000AC3A59D19FCEB31B309CE3FF928DC14A3E +:101F8000E9CCC694ADAA01F84B915AFCBD8883A256 +:101F90000728886FB724177560B0A82155137E15E0 +:101FA00010A029CFB2DEEA448B5368CACCE9E5ED34 +:101FB000192E8854256681AD9A1AF99AEB4292013E +:101FC00049517139BC7342239168D4D91647346C96 +:101FD0007BAD5305672BB9B17C5B2B01FE937B8DE9 +:101FE000D6068D3BD2DD8E74537D219D8A9CE212F4 +:101FF00021E7E783A812E061AA95430391E1C4C9F0 +:1020000058B0A2CFD4FBEE70F44BBF0504735DB99A +:1020100086193533DA758B8B6E41883BC01FA80259 +:102020009E2CF68B60270C5DEACD5C7ABCAC240B51 +:1020300012CB922732782874EE7FF8ADAF8E26AEA1 +:102040003423C6DF695D3FC5DCBDE375710489BC1F +:10205000C9BCB80321285B10977E4AEB51D623D523 +:10206000D6161D309F68D027C676A1613C178D52C9 +:102070004E118C5182B8D883F1CF10DA34363D50EE +:10208000F6DA4852787BC7128A7D4838D6792CB95F +:10209000803C3EDEE9CBC37A05FD6FA12E69D4D327 +:1020A0003B4BF1B716EF16D05316A7B8068341ED98 +:1020B000682F32D71AD58693C6F2C99B0774B7CA60 +:1020C000A859D66D7EEC1C6468801407506995D9B8 +:1020D000B335A2D08393FFA17094F54B8ED0C6097F +:1020E00007F43173A7E5E6583FA1670148596C9A98 +:1020F000B435ECDA35DAD84013F503D89C74A22B4A +:102100003B9DBFF163C3DDBEEFFCBF40A19915103D +:102110006DE27AE5AC9B215BA17C0A7F4F3D39B033 +:10212000360708301F23F459E25F209E13293044FC +:102130008FA35BC0C37996D9347B07BC5795AC603D +:102140003EB04B15756D7DFAC593A698A8CBE4AC4F +:1021500036A5B80BCF5F0D4C92FA00BC2158164340 +:10216000905E02338233545ACAE67E373B35E847E5 +:102170008CAE9CDE3B886F852ED02F15E7496A898F +:10218000D3F3F5D1DAD5C486440F01825063D58DDF +:102190002298D8F40253E14682EF14A4ECDBF8C194 +:1021A00049A1376B618ED3464E09B8E5772E6FAFE4 +:1021B000AE36F575EAAEB7B3495D5E22F76A66479B +:1021C0007C81CCD154BF827AB5DCCFEA53AA1BDF25 +:1021D00043A730EFBEEBCA3183B50F721D73B64B08 +:1021E0009B7FD79B99A9475CBF8273D2AEE31E2623 +:1021F0007398CB8426BBA04D92E973EC5AAD512A5B +:10220000673D3C4E886D9F2F830B3E248DA2097144 +:102210003D9FE53768520F040F850AA19DD2764293 +:10222000728C2D1A9F3C0CB26BC4CEDAC6F68F1896 +:1022300077FB6C344C137281F191E6C9EEBC2C34FF +:1022400071A143ED6E0DEF7B96D700E17B250C1459 +:10225000EEF068EA598DFC5E8B30D1E1569B26E1A9 +:10226000A49E5CA55F1267D1CACC96EDCF6FD43126 +:10227000F5400A24252CA5BB664BCA6D3EA24750EB +:1022800005F01C934C638452CCE45F37AA41DB44D5 +:10229000DBF1D72DE907D833E02645376E9C624B3A +:1022A000B6A36A76AAEB03BD52C7E978F63C5D880F +:1022B000961962FC0FA7850F12721A74AE7A7D16FA +:1022C00080AC0ACAA2C4C50CEF4A650661814166AA +:1022D0009E99CF3D66718F5C3258091DDE6601AD57 +:1022E000772BD8C468C5575D7F9DB8E1F12583740D +:1022F000D70E819AD3CAB9063C3BB9D0A653D908A8 +:102300000F745976722FE093ED96451F24F7C34C56 +:1023100073DEAE2BD1882D691BF2B1B1BE6B0013F9 +:10232000E1B54E9D09B9B9C6B87FB8FC584214D67C +:102330006E14101276E779DC38D038EF8531140C42 +:1023400013E09133A8C18C65E1AA0DD4469F5DE2EC +:10235000F4F24C4F26049FA53061760A5C655F2B32 +:10236000543F13FC7F7A68D60F8EE7BA6AA45F6188 +:10237000ED8DF600F2BED11C1A2981E13760BF2A2B +:10238000FD71B8F9AA785CFC381DD8A5A722CEF259 +:102390009ACE0F58ED2CDD0FEC10ADE98251256D72 +:1023A0001CCE664A202A12EEB4AE7093DA5E8A68BA +:1023B000527A165814B25A95A593FA99C701DBCAF6 +:1023C0002342EE19387950D8550D8F2A1229AC15B1 +:1023D000BB7DED3AEF5EA4E6C28E7DB0AD57BCE0AA +:1023E0000DF054A7996AD1B300C6B4DE3C164FC6AF +:1023F000491AC77674F34C4026831E12ECA4DFFC06 +:10240000C1B5BC478D8E31BDA3E0FAC43FE4C279AB +:10241000C3E530E1096533129BA6AC157586BA7D1C +:1024200002495674F8A0082B43866F8DD4A82C0956 +:102430002B1C50DE81F9B7726DDFEC3B88061A5712 +:10244000C25802D03F1F4C0D899C4544B7AD0C8942 +:1024500099489509663B4BCBECF50AD3941A448F07 +:1024600002E964121670DDF287874DCD95601B7707 +:1024700053C54E5EFBE7F83177E63763EBACA9ADA9 +:10248000224020D683A342E5C9F6E05D3A1FBD1085 +:102490001F2552D381920ADE64D4D029DBBBFFA76B +:1024A00074358C3CF35C4C4D28A9748792402E13F4 +:1024B00086FDEBA316D7820D8909A058431A8B8598 +:1024C00061B33C81CB5AA055E44E66B54F0C96DC07 +:1024D000A63B4AD5E5348215BEB3F81B64412546B8 +:1024E000FEA69DB925719AF37E9B49CB625C50890B +:1024F000F0285976A7E3A7D05FDF6A65AF7577A2AA +:10250000BF1B2A674F99B23C4F97B2C9C424ACF69F +:10251000744FBC5530BCD54360030FC1D6A1E1C98F +:10252000B7ADD189758E6A2217EC33F9CC1B34789C +:10253000CCF073529007591272B63384CCB4385A27 +:1025400023604724CB810D0F2DE207C86466B7EAEC +:10255000784D28739038EB5133D16F694B011C686B +:102560006E6CFF167C957B52A8E7688E4FBD1543B5 +:102570008F8615970FC0DA21EDB7E894FCBC3E2199 +:102580001CC57377552F25A1D6EC69CDF406DA2149 +:10259000267584A695179F96ED69E941C5D20A79FB +:1025A000A6A3C7C56F592F50861B727B676C56B2A6 +:1025B000CEA9FDB96A6B96ED40EE63A70D09BC3E4E +:1025C000C57180A6C2711865E11167134413117DAE +:1025D0002997D470F04C2BC887BC2F296D6847E62B +:1025E0006E17B9529405CCABAC670168DC1F8CC880 +:1025F000131AF9F1BC282036FEA85998EA9639DD5D +:1026000093031AC919A649B0B7A084FC71EBAAD7E5 +:10261000E9D5E39A36F8CB192F43C092404909997E +:102620002C702A800CBE1FDEA6E2649B4BFE169C1B +:10263000CE853D90CC02719199A94F240FB395D0CE +:102640006CBD79E07AD140B479F664B6C664BEEE6A +:1026500027ED8A8F2E920130DA0F709D8516DEA845 +:102660006C5CD07A761CAC9140418909B967BFA8EF +:10267000EE827B6F536A06E570C14451FB2650120F +:1026800025F9A08E1590C5ED58948C9150A9EB5466 +:1026900049799A7FCE89360555DDF5DC996DD3CC25 +:1026A000F6803D089B90371C4A6907BBD03BA84D7C +:1026B00064C676B91E4AE95F77358CE3CEC46141C2 +:1026C0007A8B6AC9A1BAB111970CCE9F61A1DA4584 +:1026D0004E679EAD49B8AEE714DE3DDEABDC94122A +:1026E000F68DD0ADB9D64B20DCBA066CFA96B3DDC8 +:1026F000E8056D1D613DDABF61CAB056D07467252B +:10270000C1A4EC1D72F95B3E5362C44A0A08889F5B +:102710002F5BFD5DEADF7B637BEC5542C964E8A17A +:10272000E84B8BCAD7586020C19EDF7315A3BA53FC +:102730000A5C08E04DFD0468133EDA7E4BD58ED866 +:102740006AD6D564FE205C955A8CC0A5FB986E7144 +:10275000AD7FB1B31553033499CEF5EFAB491CBC33 +:10276000010C80A0B9126FC6534499CA02FA5CD614 +:1027700041AE6B1E4F8369B306E672DB9C9EB9E8DF +:1027800017B78533E2268F71EF5A5196A0A21F2208 +:10279000014FB2D3DF5C02656A97C35793406DDB8C +:1027A000E5A5DC221264B3A22F4FC5158AD4BB90D5 +:1027B000FDBA762D13860DD66935DE78577AF8C4C2 +:1027C000740CBB61FB681B022335DCD4C35902F4D3 +:1027D00005F54A6C9CABE2BF09BB3ED9EBE4D69F42 +:1027E000A4F1758072DF883C8CA27ADB1ACA9F84C0 +:1027F0009373C8F134DADB51CBD758ACEAC4FB3B56 +:10280000D3471A942919F9A76D6FB5D33F81FAC63A +:10281000BC5459CFC3C0A799A116982853F5A52831 +:10282000E9E06FCFCF0E06C8C9EA801DAA1CF95A8D +:102830005F2AA9320676E5D7060E9FB04860BD4BE9 +:1028400083A217024316B4818D227CF1B304AB62DC +:102850003EF5B83BA6A42DF791BA14A8BCC9D8CDB3 +:102860005F326528C4C623777949D6AFF00B0A00DA +:10287000AE12EC5C0C538DE99382144DC712C76FF6 +:1028800024F1E34FF35EE4A576B8AFB7A59F6F9F41 +:102890003314CCC8F2354C25235EF6E15F64A59174 +:1028A000C214B7062060D7A3E2448D9C5216328E24 +:1028B000C3193813B096F4B004C8E30F451427CAFF +:1028C0002089396A5990E5410D0281358F02A0595E +:1028D000E7828505792064A1AECC0C0CF1CEC0391D +:1028E000FEB73757CA55D6271A95416A9FA0791F58 +:1028F000714BBDFE58687D737B1E7188002B266965 +:10290000CFEED13CA4C4D56FB77434A0B575E37ACB +:10291000BABA8184A82F4C5AD0DAA00ACAC3BB190C +:1029200099D06C4F9E2F9847785715884990BE7361 +:10293000218F02751992E541B347A4D86A16432640 +:102940003E3C8F5A1D3200BD39F0B53E01F046A81D +:102950003AAA996050017EA1329D6FEF80BB424F31 +:102960009A9C83BBC7AA9D0246142C805CCEBC787F +:10297000174240ECFD40A48D8AF0E0A15336575039 +:10298000CCF202242F6BE209642AF301D1CAEF24AE +:10299000158519D4045DB48022AD4D0C5C4332BC66 +:1029A00000D4EB59CA3DF4551BE2B4EBE6DF9AD2F2 +:1029B0006578AD48F032599ED1CC118F4DBE34AF01 +:1029C000123F6D04E3EE2963ED042BC71009309725 +:1029D00019C2109134817B550C26BFE7EB7E25F997 +:1029E0004518D2CD6F826F4971D0ED027F5D03BE75 +:1029F000C1496DD41AB309F0CCA565731203FB1E4F +:102A0000CD35730DA15B8D0B1D115323E6561E882A +:102A1000FA892A93A898E64AB9BA303A456A49E64B +:102A20009E97537566E59E65ACD3273F1E11E82738 +:102A30003015EF8DC29D4808624A27367EDAD3E80A +:102A4000A6FF79CACE993A41DD6ADAC2F4864761B7 +:102A500000803CAA7CA94A19882EE3DD9DA347C1CA +:102A600033B4496CF574CDC59F7645F74162DF49B3 +:102A7000ADB73FA280F5132FFD8C8C55E8749C3BBD +:102A80002BA89875DD7ECAE6900F438A9F6074413B +:102A9000108D5AA65EF5C679FA5C1932320550F8E7 +:102AA000A912B29BB889100A5E2AC3BBAD0A81473E +:102AB00054AC4400B56DA60A6E39865760DC0895A3 +:102AC0008E332300B48F190F873E87570CA622FC44 +:102AD000ED3C54D8F306EDD6F8D0A7FE9613DF29C7 +:102AE000625B444B8084EECD4E18E087D3B6493507 +:102AF000631A63383E4FF756A55ED49BA58BB199F8 +:102B0000132DC55339EDD20BE44B4279DA0A0A9101 +:102B1000C2815E7077704053CA52E9909A40366F16 +:102B200069487483160BA09B0229CB3212DA62EA41 +:102B3000FB8D726238C07DDA2E805AB7EE2E6C9F04 +:102B400009DF1A91487702591FE02C6443D73A31C4 +:102B50004E020002B5F2ABAE0861B184A177868B5C +:102B600067EE81E4F2E08ACFDFC0064481CFAF197F +:102B70009C647A76C3DA1A9A5E8F981F4B7490E23F +:102B8000145C84E05B1B8693D5ADCA2679593FA4BB +:102B9000688F847B8DFFE25ABED9BAEE2F54407005 +:102BA000C1CA68CC58A82CC3D0269AAB53769B3D9B +:102BB000DD82E6BBCDF62B7ABC105346EE3A5ACAFC +:102BC0003EDB6CC5593C76316C80A8EB741A032946 +:102BD00035C76937D1C28C02E247C320A4222556EB +:102BE000D813F2B2DDF780E691F0268D48F03E2052 +:102BF000EB54B7CEC47083C09D7793523F6C8375FE +:102C00000C7C3585BAC09F3629B94F76D14C0F451B +:102C10009FCAF40D514BD661A88C0C68E4ECA0C59A +:102C20008EF83ABC173E28C31234707D1888F13AEA +:102C30005E5109DB4EB682B1AB6B5914D9FBA83596 +:102C4000B80A1B3480DD56BA8D5792D5B1FB5F09A7 +:102C5000F0FF57C43FD8E9345F4795334A553CF6F7 +:102C600043A3B29848A054727A0661D693B73E93B4 +:102C700043A8670B99E9186FF538AABA425AD95D8B +:102C80003A54D881AD51DB50272579A2EF053AD3CC +:102C9000A50259BAD567BD0A118055E3C376D4920F +:102CA0008FF475A5077499012467C9A19EE7DAB06E +:102CB000560050DB5EF21BCB616A9DD74DF5C31AFF +:102CC00096ADBB987983239EB690E9BE62072F72BA +:102CD0000F9A2D4DEB94EA1A1216BEADA0F2C2A8BF +:102CE000FBC6DDBEFE550FE6CC0943CDFECA43014F +:102CF0004CDC9079DF84433D4C668F5BA4F6A203E5 +:102D0000B06227E4220BDF721FFF42BEEC5ABD5BAC +:102D1000A7CF91626B145F2AAF9A91F6563FE730C6 +:102D20007496F8819D5A37DC39500DA1CB52B02FE3 +:102D30001FB4C1D97BAAA08A16C4559FF59FCF5B4B +:102D4000B7F7C27296024681F27EC07E0A908A7CF4 +:102D500057686A71956743327965BC799CAD9C89E7 +:102D6000FA86EE4FF34067D2EB3BD666DD793BCC7B +:102D7000BA06CCEFDF0EE24EFE77654B7EC46B9F4A +:102D800021212AD36280708DB49CF14149A8231778 +:102D90002A9AEF96A9EB4278662331A36F74A54671 +:102DA0008D5E02FBC15DB343967BEE3A4E2DDCACEB +:102DB00035DB33251BE3C8F1C7D2931EE1FC1207B4 +:102DC000390F4FA69094C8FA0264C2CA7EB5E26A6F +:102DD0006B03A9308165748385C2D27DC5EFC42899 +:102DE000294EEBD4FF05DF4216EE5DC3EF6CF79F73 +:102DF000B75ABA513521371C5A6951C72A256B2F4A +:102E0000C7D1C86F221F6E38E6D78B2863D17A49A5 +:102E10003130D1E1046949A189244C6DA1C3A81ABC +:102E200015E6DC0E8360C525C143C4572E726FF6CC +:102E3000075419FF82277EFFE98F6C072FE598332F +:102E4000728CC40C59FCE5344515476AE58E2E6C2E +:102E5000A5D0649ACB01071808379D1468A724826F +:102E600062D065EB20F6BD6A2B750611A21509CE5E +:102E7000199C257F9753B08C6D188FDA64E44380DA +:102E800057811C5858EEFB87C8095441196B399378 +:102E90002B50E674E9C88DF6538199992D2A3BB0E1 +:102EA0001A86A57F4E860AF2B36AD233950B238029 +:102EB000015B2215734327DDF1FAE2EB6D97DBAA84 +:102EC0008A63E0B175F9DAFC1C0190EAD25C436FC9 +:102ED0002E51F1E8EE7B81F92A4881622C279C82F1 +:102EE000431423C880782DAD23E031F3A5EEB2243E +:102EF0007D005B89D20C1A77B2C6CB376EF5114EC6 +:102F0000A88DC547EDE93D9F441E995A604C903C01 +:102F10008BE237CADED7D29AB2E7A90328D3F5935A +:102F20002A7EC3F4A7B30BD2535CF165EA5EB3B358 +:102F30009CAE82B7E00C959E4B3FB49DCBCC266CEB +:102F400076D979D5D6F3A04B356C0D3E161B970E6E +:102F5000931EA0A24456D28BF6781D8228E5BE08A7 +:102F60008EC27ED710ED05C796B33AD4F71719FB7A +:102F7000E4BD023E508F0BBF3048BC5414A1CC8E30 +:102F80000AEC3E5FE9245B3A2231F86280C58FB0DB +:102F9000F731CF509501D1A344A3416188A8596A64 +:102FA000DBD730CBC26DC7E14D8B6667E029166B6E +:102FB0005436B7C4DA558E5BBAF6B1437C00E5BB34 +:102FC000564437BA9077FCD3DE2FFDFA0FF4223D3A +:102FD00019F8311455B5318BCC2C27DF529F563060 +:102FE000F264F97172BE3C38E9E07606EAECE393EC +:102FF00087F60C12BB018408597D120DF733185A5D +:103000002259662982CD6FEC7520088BD496D57F26 +:103010000C915DAAEC50B17E6488402D5039209B04 +:1030200095F3731FC92FBF9EA20FF8D23EEFF3484E +:10303000CC30127870A5351A3054500135BBBCE63F +:10304000CE9181DBD7D3F700660F8A3C788C43FFA3 +:10305000ABA9D61602BE3F9F03ED1FE201646F4D80 +:103060006642EDD305225AA6CC660ECE899835006D +:103070007A55915D4CDB270F50B68A6E51F360E4B0 +:1030800070E433086968C6E4975A89B0C6160DD251 +:10309000F88126BA6300D94A323AF471D5CD48B4E2 +:1030A00018432E7C057E16EF76EA2D99B448550319 +:1030B0004800F8922F3E6A6A836A5AD52E71907939 +:1030C0003BBC5B48071E7A70A96D245F382D273002 +:1030D00075922E91A12B94056A18095D3646044617 +:1030E000FEE7703694EE7A3F9197E1D7DCFC99EEDB +:1030F000BA790B32AF84A31074F89E89265080C32E +:10310000B85E41BEE628523A13B0A68353D3A3BE9D +:10311000870EE1D5C5F06B68091003A79D76E845D9 +:1031200080C19C252A7A15E3E1B212C15678D7995D +:103130008781377A40EF8554FD51346D92121E7AA3 +:10314000001AA2D86DE332617EC79F35B9BF3392B2 +:103150007B851FB2E4090D9F74B34F5EF325454D87 +:10316000F89C5E4D753DCB761907FD7F5BFF109790 +:1031700048FAC8CFBEF9A559CE7086C21E2549604F +:1031800087DEA78BBD0D8559DEA8938E1686159018 +:1031900059F091B9C2C84E60BF84B222BDE4B48E6A +:1031A000F8E51C3F1EE0BCEF089AAD0C42C5782D37 +:1031B000C41C0A3ABE6A8A15E58A0EA15B1047E66E +:1031C00000FF748B0575AB2AB98D36C3729A22291C +:1031D0000827011761C1AC0A9D8DB4CD229C994985 +:1031E00070DCC2ED3157FA090049F16BD39EEE2F26 +:1031F00036D07FF558245E9F1D84B34CB3AAA1B28C +:10320000C9DA4B18285D9B25DE825D59715EB806D0 +:10321000F589B31EBF318AB1CDD65D299EA95689E5 +:10322000D21E8EA27AE23369968CC7B3117AAFFBB5 +:103230009CFC4BE87ED4FEBB4518C7A8C193235B1A +:1032400024BB49A818590711F98BDF08D47F138FC5 +:10325000D69C8344677418BD49D8E96BAAC4800F13 +:10326000536D59A75E7F090DA441846DE018191BA9 +:10327000ED104F9760278F38FC3D0DB8DC40574765 +:10328000AF3A70066C6115319C27CF218316E01888 +:10329000CB0BCBD2A1B7DFCA72CEC456849416B37F +:1032A000111B7533EC590B2B10C4206DD32BDD5C37 +:1032B000562A751E05371470E5995F21FAD0101B48 +:1032C00046DFDFC8957703C96E11AF935905E1B2A8 +:1032D00032A751DB5AA482413D5AF1524154F0E6E3 +:1032E000BEE94F8C350D6196C524C5DD277ED779A3 +:1032F000038237E95917E5B8BD989FF6B951A90E71 +:1033000006358BF2E7B0F9429D7DC3C357E7533FC3 +:1033100083DCBA2DC5DC1788E4972E059925F2A821 +:1033200017A177E14C64447A5899A3A1710CD45742 +:1033300081FF7EDD20E9A9F42E989B88AFC3BEDA19 +:103340003511A71B87A65EC2B9C1433BCA33718E34 +:103350006B26BBA3287DD5205F2A0DF868B5E280D7 +:10336000AC575F0B47A35F2D6D9918132E5858FF6C +:10337000511F1EF5551B94119E9FD55C22FF5E4B7D +:10338000AC01103BB369544DC18C67C44BE263522E +:1033900023F347487BD1C958096B65ABD3665634D4 +:1033A00074494D8CB6B5322DB5A5BCF91C799FD6A4 +:1033B0002639DCDEA7F36174071DF349F69E6EA182 +:1033C000C9245DEC482BE16E7C7BDA010402558A4E +:1033D000EF39244267350369D3DE302FF83EFEA370 +:1033E00015253601657B1A6C51ED81EA7622F21DB6 +:1033F000F974211ACFDEB8861905115A9EF61FC23C +:1034000047C240635F7DF5F9DEC35C3C0B06A4C395 +:103410001C7B7B91B784A806B1A6FBA14FE71401E2 +:1034200085F55D5709C0610CA201ADD336F3FE7A74 +:10343000F61E49DBC6BDA788559E64F321E9FE7BD5 +:103440002FBDB1F48C7CEEE1A69A3AB5B7F1BBF290 +:1034500061EE9E2AB17AA1091895D114189E10DA4E +:10346000CFFF2DE91D4F24B78F42886FD1EDBD707E +:10347000E0B6E74792CE55C4A6322D1B50B4013FAB +:1034800087782F9135FB2247D41088AC22AA47DBDE +:10349000046864DEA57BB3367FCA09099097C5C767 +:1034A00013B7B4A33157C6B8AD796942DBC16136F1 +:1034B0003C82CC84BAEBCCECBEE346FF7B5003C12C +:1034C000CE6DCBBB2183FEE49CB39DA3C75ACC63D6 +:1034D000E02BD52A6E123964FAE06B352BB1C9B6F0 +:1034E0009DD9D462717735754BE93B3ABDD4B2476B +:1034F000078EFC2EFE1DF845ECAE91C703CAC5FF32 +:103500005680FA60A0B36D1CAB941ED1C67DD9B4B1 +:1035100030E40F1C84343087A07B2ACF0C0429B2FE +:10352000DB08EFCE569FC17D93A49943D294C1A6E8 +:103530006482F05B674C843E5C0E7EB45F5A9757A2 +:103540002F5F58293B502F59AF7260781609DD2341 +:10355000BEF2C9FBE919E9AE6DA6030209DE0383D9 +:1035600071BA98A87485CB257CA928AA56A9793662 +:103570009C412AE286041E8C867BC29BF733233A49 +:1035800014973B945B868CD015BB975D5CDBF7F2A0 +:1035900005F4E95CEEFF78D072D3B76D536FB6A235 +:1035A0001FF56C063D229D1A83C7F9478CF1FEA2D8 +:1035B0000C4B60176A826B0B7229B40584DC6FA810 +:1035C000C7D7A4215B5619F532702BBD2FBBBE6344 +:1035D0009B93610F7C0587C5720463D615FD00C7F8 +:1035E0009998D279829DB15D7A2E25541243BC847C +:1035F000339DD017EDDA72159694A90A7D265CC02A +:10360000B29F773063EB5BDE408430015CEA3E0BB7 +:103610007C55781E417A9D5F3D46F39BCC1851F94D +:103620001DB6903C89E347665C736525DD525D04F9 +:10363000D33D37DB3FF7249A4C7437224287AFC221 +:10364000043A05AEB738CA455EB5B3FF9CEEF153F8 +:103650005E92C585EFAC4E3D008B32522765C46348 +:1036600014A8F206C1FFAB3A100DA5665844E86AEB +:10367000600D04E460DAA06E9A84E5DB63CC24F587 +:10368000E190457BF710C142616B6D54BB7D30A862 +:10369000DC4A5863718C46264E13BD756016F61CC5 +:1036A000667849343B4D9B9FBCFD117467B7A43DC0 +:1036B0002836A0A22AAF8D0517A129BF6B174E840B +:1036C0006B514DA9D3E75CAC43F728EA7FB5642A78 +:1036D00029D0C475BD830FFE67B1EA2C8C8653FCDC +:1036E000F8AC0C726A544B6ACAADEEDE9F10AEDACB +:1036F00008B5A19A6CB38A7060EA34AB5F33F9DB2A +:103700001652549C55A9B062ECB76351C5252CF8EC +:10371000822568385A5261983624E0495BA74F3CAD +:103720008CBBAC6FEC7EFE423606977250D3F83FEE +:1037300056020D4A21D8E80EFB1CE45F9B96A78633 +:103740004E9A366F63E19B51C137F404176FEF0D4A +:103750007F8EEA05E4F52BB99EFB4372B8FD7D3FF1 +:103760003892B4BCC6EA894E5BC10E8E7E6F03DA16 +:10377000D2027D9A65B22845A7A536894EB56B451C +:10378000F9C6CBFC2D4B9418031E3C4773F476B45A +:1037900025D86003B56F6CA81A13B375852E863EC5 +:1037A000175F6366B75CD93F22271B4801F5AF77E7 +:1037B0007A6E70CB6FB1355600F0672FCC7A53D04C +:1037C0004D5EE6159CB763F2138CB46FB2AFAEA03A +:1037D000E71A28FB65079DB7223B86D58F394EB582 +:1037E000969BB6E9931C1B9FEDAFBD58618CC497A7 +:1037F000B9FA4170186D3F321B045395E455559A40 +:1038000063CD1D530A24BB810DADDE9A4E669BC568 +:103810007E33AB353745F189748B7C301E7A9C043E +:10382000CC42F3C8B833F8262948281D2E60461329 +:10383000EDECE95FFAE934DF078153E6C2B1C16319 +:10384000F67B7D84060F6E03F2FC329DBC59E16766 +:103850006BC21E2E27816C6D00BA3AA88799392B4E +:10386000C87532DE1B0F79493D85312B6D813814C7 +:103870005DEF44F5BE4E898A29A255B5B817BAF254 +:1038800059C7AD0443C5C40DBF4DCB780030C482C9 +:10389000925CC13DCB279EEB27A721E52FDECB9E77 +:1038A0002C0010E94A0E143AD5627F95D354F3C820 +:1038B000C9EA75DBE465357457395D838124661187 +:1038C00042ADB3863F72D4A6E51A531F8E3B7054A7 +:1038D000115C5A4BB18B9FA981D4E34DEBC3354C9E +:1038E00023293944016A3427757037F55556C96F55 +:1038F000040F1989B5980CEE864D3AB82A9BD3452A +:10390000029E4718F872AB88A1FF2A3EFD4D09B60A +:103910008401169B4F3980D3DC23579C6B052B8287 +:103920007D0142D56D049DE996BA78572C32DE7E32 +:103930005A26B33A97FEE0F453D0D6A0E8B37D19E7 +:1039400053B7E3B8AF435A3333B585B7C50E1D1629 +:10395000F2A3B3774B2133B7C4041A94210B79C671 +:1039600073BE4A6407B31BC680F2E36852E3CB110F +:10397000F0A231379A7C1A52E23E04C8D71321379D +:1039800094E0CCC2FC45F025C4F28A945CC7C63AE8 +:1039900075D93E9B870F650DE6288AB709D303F6D4 +:1039A0004A594B4B7DC1062F9440D2CC383DEDD1C6 +:1039B000B1FF8FCFCAEFDB4959804619A6400C14DE +:1039C000954400E9F845A9287673FC06534493A56D +:1039D0008FC9A22F2491AD80A355BEAFA7D9963C25 +:1039E0003CAA0E8E5B7790F4EE9D8C594054F07D8E +:1039F0009FDFF37437C88DDCBCB2B78BBBD5FF66D5 +:103A0000B934947D836C72EA5EC7A1BEEAD2D75FF7 +:103A1000B396D4F76F9DAE095A897A0621DE1ADF74 +:103A20001ED5900017A5DCEB03D253C1D3179175B7 +:103A3000656EC52C95FD11D54A44A0831F6B694264 +:103A400009CF4B27D3AE93272946A508EF6BF82D56 +:103A50007567A8B26C419C75A4386EE5F23677772D +:103A6000F8286F3B59890E7ABE04E933981F6BF032 +:103A70003135DB2A262B0FDB0602B34A5840E0A380 +:103A8000FA85D8B3F837001319ACCF66B767BB30E7 +:103A9000929C898471F87656A0C82D68C5CC8F7029 +:103AA000B7F2E5CBD40DC7A8A1879B798F6D83159D +:103AB000A58978FA76998C4049A11C13FE679EBDB2 +:103AC0006DBEEAF72C6B05C501EFD910E453C32C8A +:103AD000516DC28A530E7BBA619D2762CCDA4C26A7 +:103AE000C9D9DF7426259D77F20ECA202A9557F191 +:103AF000365744A3B435CCCF5C08471D9D33AD1871 +:103B00002460E76E72F19FD1FC7157C967C1E36110 +:103B10009C556034D56E8059E41972DD5886E26791 +:103B2000B0BC6D2A5156012064C9BCA02D5E1CA4F6 +:103B3000D20A521D50DE86F470828C27F2B735CF40 +:103B400022C5BD9E3B787831F87F450E73351E2C1B +:103B50002291265669456CD5FD4896A60ABED80B1B +:103B6000B06259C132C66CCCF480E03050DADB1858 +:103B700030BBBF0A0F5BD0D82754D2A03130B387F7 +:103B80006F6419EAFD42FDFB2C75F9862789A6CEE4 +:103B9000DC7B22427FD9AC91CC122CE0898305F6E4 +:103BA000407D6BAD45BA4658927E70BD479615FC78 +:103BB00076B5BC0B5C7E43B07A9F03E12A28CA9895 +:103BC0002A1B91F8AAC005B5A08408C84A624EEF26 +:103BD000789A4F0DFBF3ED2AB862A39507853D0651 +:103BE0009C713008267A6EFAC5EBE0AEAF768F8A0C +:103BF00075E96DF62561F9D5CE6FFF5D28A6B63360 +:103C0000A6B22BE0F6D690C177F5D91440A41B30AC +:103C1000A162917FCC2DA8CE63C1A651BDC3035A2A +:103C2000469998398CE2E5DB75860F571334747D1D +:103C30000DBDD30B3BA417FC35B780740B0F35ECCF +:103C4000CB5625870808FF645E66C5CADC1999262D +:103C50006CC99E045ACC0E5EB58B26A3AC1A8EB5E9 +:103C60009D841822A893E05291B08E2449D41B1F42 +:103C7000A361EB23878247AD7E0802C176E780E12E +:103C800089C3E3363D87C10DFE76BB9AA0A5085FC8 +:103C9000B1DC2D26DF8A273147EAF1F2E30ED43E6C +:103CA00048607F2F5E0CB541A23233AE90843EC097 +:103CB0008930D3C031B6FE47C3DB82BE26EFA3F105 +:103CC000BA4569E866FE556A8DC1491FC633820E42 +:103CD000B1758762A16F42B221BDA893B7C98802AE +:103CE000B33369932216214D02D638F09D8D98B1D9 +:103CF0001BB9D65C93B9523430F6FEC18F3EDD2F2E +:103D000042FD343B888792A34B548357C5DE80FE27 +:103D1000DD49C832F13BF34C2CB4149D75295BCEC0 +:103D2000FDDF5B98AC4DB018C2564D0C654AC8F922 +:103D30007717EC38F4020690AB51B1376B2CEAB42C +:103D4000566CE3A8FE7445F488B442F6866FA8E882 +:103D50002065FA00F4DC074BEB1F8D12AA70D9AB7B +:103D60001AF28092A4BBDCD0EE6BD362A279D65259 +:103D7000421D4348B13EC0D24E8546951FAEF51C4C +:103D800064461CB221B34D6CB007422F681FE41487 +:103D9000BCD45CB9138133824A7C0923D0239FF6BB +:103DA0001C9EB3668295BBD9800471631BAFAE962F +:103DB0007CC6540D2D523F2273A26797EACB7BC17C +:103DC000FDCC63FF1E3DEAC5A419FCA34EEBFF4BDF +:103DD0007120D70738057438B725AB334C1651001E +:103DE000548AA86B016C4931BA1DCE380A43D0F50C +:103DF000681CD200CFBE54688D588297B1A9365343 +:103E00004BEC79AE52315F359E7CBB131B74335A39 +:103E1000E1F9C2C5C66F0C29AA31F9015067FF67E5 +:103E20004BB4C4DC382E0C2DD9DCC39EDC4AA84C24 +:103E30000B17E16B481F432B780650FB2FBF9723CE +:103E4000BAA8861BCE0FBC8E7D6526B69E23017454 +:103E500067CB2195E8D94E519C9E4759F3DFDB5142 +:103E60005406DDB99A1ED06477D2D778337E301CE1 +:103E700071CB1D76422CFE7D4C98BBD6249CA91696 +:103E8000641FEBB988D2ADBC73F65E13326039C9DA +:103E9000F278686C0DF1A3A83170797A08CB288488 +:103EA000A9FF1F9C55FFC537D1DEBF330C7A1171B6 +:103EB00082BF179AAE4388E39BD191B9C70D7614A0 +:103EC00034B84ED2BFB9341DCCD409D608BFBBC05C +:103ED000A97B4C31E119834382D5537933D1086BE7 +:103EE000F7F9574744946C8F15AE49EA8B098C411A +:103EF00079471BC1B89FB34168BB84E858DFA67FF0 +:103F0000BDA31B87C488DAAF8917E3C4B86CAB9D27 +:103F1000B0404F3B3268C0DD6DF352BD86981BCD7B +:103F20001290E5F8AB61C18193643201677E0B505A +:103F30000361AAE5CF292DC7049DB289490163D643 +:103F400053F005BAFF690A4564DF9E08343B3D6AB9 +:103F5000B42A360E76A345362F4BC55757AEA8BAAE +:103F6000B3135B32A31F64D812F42FD3F953A245C5 +:103F700090450C16D29DDC031A893583EE09C46B7B +:103F8000C1B2465F17D5506C98A7D65221E22709D7 +:103F9000C6746A7E0007A4BCA3C5D415C4E653B397 +:103FA000B53FE64E104A22572D6AE334ACD6B4A989 +:103FB00007104A0E9E684DEDF92383CD0EB928C136 +:103FC0005C713F4F0AF6F6C600B0459D662242FA84 +:103FD0003D0FF3528D5B193B979865287CC365991B +:103FE000FBB68DF3125370B196AD929A124D1D45EA +:103FF000E25408ECD26B7D1CF65ABFA1688EE3C177 +:10400000AA20CF124A0DB58663E5568E45E397CEBA +:1040100078810E5EF443E69C1CEDABF20EAF59BC0A +:10402000AF7C0AE6414900A71A631903EC1F9A41C5 +:1040300011FC9BEC05AA433F0FE426A776AB2F2883 +:104040000AE32DD24EB7D90906317A29F82B6E0929 +:10405000A6DAA7D89291FBEA089D2841971E406FE7 +:10406000435220FC2309889D5EECFB352A0C11E4A9 +:10407000209762805BC047F8B29220212F799BAFD6 +:10408000735E028BDB4688C9FFAAEA2EA14CC86783 +:10409000BB425BD491C26F6FF0BD2E1CA2E90E74BF +:1040A000E7FCE5DBD54D95D5050E00CA324549F54F +:1040B0003029656B129AB8E72205EBA4966B1C4277 +:1040C000167A9807360E183A0353428A9CFD4D859E +:1040D0004344C7896E924803749D33B546688199FD +:1040E000E83ECBD5A537A693E3947F6491C6C0F78D +:1040F000FFA932FE2677179272D6364D75EA1D213A +:10410000BB1751D3F38EFFBF26BE923C62889D2F12 +:104110000CDBE50C64E4CCFC021F7FBBEAE79032C9 +:10412000EC9EB98B6B438F570B99DB02DC5933D66E +:10413000AFD8A938C891D8D3F3DF45EC478A3F6D93 +:10414000186B95B0D636C44EBC6402B238B8D57A76 +:104150000C63915A38374A1D7328F6C7B377D1AF2D +:10416000ADC886817011DC252C631378B1DAB47C7C +:10417000536CEAA8154F279020016D2066782BD844 +:104180005B246BD6A620140E363101771F0C393113 +:10419000DB004924C1A926BA7E0A2A11DC8E42E13D +:1041A0009079EFBF34EF422C3EB23A4097894018E5 +:1041B000ADF11E9C6E538411DAA3608156F36378CF +:1041C0002983650849309DFD1F8660338C16D621F2 +:1041D0009C36C4B9E2D1098DAC092E576D515FC42C +:1041E00071A922A9B553FA4627A77CFBE502D60D93 +:1041F000EF6C40D587939C572340A00EE27A26C5EA +:10420000D0D9960627350E576730148AA0F6E853A2 +:10421000A40E6AD37D6EEF237426124AC27348E25D +:10422000C52111EFF591088AB7E1BC4711D8E5F136 +:10423000A1E470493E84EA607C57B9EEF635A63EAB +:104240002AB807A33642B7AEC152BA6ACFB95FFAED +:10425000B5BEA2A9E259D5305CD7646FC6A0860569 +:10426000E44CC7D58C5AFFCBB5DC12127276903075 +:10427000C2F2DA363C5F04AB1DBC1DD62FC1CD05A2 +:10428000412F7929546EC7271C5047C76084D35DDE +:104290005B05D3BCCF57F5B118CFEF8AC64C67CCBE +:1042A0008D78D763FD25CB72A2027E357F1F8ECB22 +:1042B0007CFC31AB806A44773573846AF6052792BB +:1042C000309BD3FCADBA884656D1689E8AECB706BF +:1042D000DC0595542FF0112C5E35776A586B35BF8D +:1042E00004C71A8E538F1EF09D9B47806D3822B9EC +:1042F0007EB98F9B86AE06B53924E42284EA809687 +:10430000EA7FADEC370E223D3FA4962F692609BE09 +:1043100051300A34E8D10D7C2619FB0AF527DAF66C +:104320008799ABE932D9035EDCF0367685840BCB16 +:10433000CA88EBB87D8E651AAA447C46CD755B02AF +:1043400013041946DCDA3F52AB8F4D4961A6FF0FCB +:10435000E772BA2E1065C0111B9E4DABBE8C969DA8 +:104360009DA91941D5DE6D3F535EACC8E003E5F76A +:10437000A72ECFD7101C3936EDB73B2D82166821FA +:10438000426A1314800C0999D031ECCBC5AE5B6C3A +:104390009D1A08EDD54ECBB9165162D320D7CBF379 +:1043A000BFD845A7FFAE48A5BA46ADEE7BD70B7286 +:1043B00090FA6C1D83108C39DFA72EDD348188C301 +:1043C000ADBDF843CC0B623A6C5F0DD521FEEC1805 +:1043D000ED260B162937F9FD368226BEF41ABC24C9 +:1043E0003DF39A84AA84971D3BD01AE8B7396876C2 +:1043F000239391B4D0820E5A6342195E30E7DA8E6D +:104400005CA5301C15AE4E64D80D2FEA07FF51FD98 +:104410002970EA5CFDF47CA070959C955BB5A2BF09 +:10442000B256ACCB27588CF2B21F28B7E0F0CFF1D0 +:10443000D8677D06D087CBE365D6AD2B670C836B41 +:1044400073DBC2ABEAE61D6B9EEC20DE7DBC2E0268 +:104450003A05EDF7B6A4146B44FA3D74DC770BE132 +:104460000D81772BCE7BAD4363162F504D22A5D8FF +:10447000B95A3D91A74C4687C05FD074C8861108D1 +:1044800087F7B3E9C0A90427EB68BE68E04912BC0E +:10449000D5A8DAB2A1A48678280A1F7A6BBCCC31E1 +:1044A0007D0B8759A0B36AC6BA2B30251C482C0750 +:1044B000E81086E40FF03B7675B7206BF3FB0DB286 +:1044C00009606FADAD31236F1A527E5E6C952BA8DB +:1044D0003E7656C0EC03838E71B31577ECB5FCC104 +:1044E0006467C3480416CC2F3A5843FC68F3F0487D +:1044F0005BB81B8E35E9CB9A21EEA1650939DB65E6 +:10450000CA2B230C0FDADFF3822AE921B628AEEB9F +:10451000F7FDD8454214710C215BA88041D5190BD9 +:104520002C6563C22256DFD992A983B4DC248C2A7D +:104530000D3125512954BE5729477FCF8F939A3C7F +:10454000C6F3147FADFBD435562BE4D6308AAC8746 +:10455000B340FC595A1E13D62C096260BC107F8DE3 +:10456000FD488C6658052644A660DE39B4EBD1CDF3 +:1045700005B823E19ECB48D542D7871E3B35C8A856 +:104580000C5AD0F04E183F37C72BBF81A326738338 +:104590006E95F235099B0E2E21410D25514D9C47FC +:1045A00041717C241B3EF4C1915DECF74F7D7A98FC +:1045B000C721D0E143DA10996B0D913B4E5E723FFB +:1045C00068B26759CF6D54C0921260C1907C48D4D4 +:1045D00084FCF64F7670A45BC9BD0E1821E87F5CA1 +:1045E000628E71DCF8F8660706F65F50EED0F0A632 +:1045F00018B254D76D49F1356680E218BA3C0313FE +:1046000030A40A389E76E5F2F520712F7B3A075BDD +:10461000C5AFC40C30ABBAA85ED28D17B54A2EFF19 +:1046200008D5A2D169276FE6428BA616CE7A23253C +:10463000B579D493D5565E743772D59E46A74D0D85 +:104640006519A61313C20D38341DCB66C2737149A8 +:10465000FC8DDAB2D983CDF6E5189510084FC13C30 +:10466000FDB547B639AA3686C5AB9CF6AA43AAB5AE +:104670000B826A17588B37749EA21A874FBFFF0FA1 +:10468000B56121296DBEAD274D8253743A2A3F5C36 +:104690009AB4380B467A6FEBC8E945434E7697E0FB +:1046A000F1933D0ABBBFB5DAE2E7C6ED26FFC3C40E +:1046B0009F2F1778719B9C689C193957D2F2EF6A2B +:1046C00044EF97D83538FC6ED6C401C695F8D79319 +:1046D000247495F8213BBA37820261BAC36F3DEB6F +:1046E000D83366EC94FF0EB7CBDC9D0962BD1AC7C8 +:1046F00004ECE0E0C5F4D51E5D152BA42F8EAF971A +:104700009E435C61EA9C3D2F8FEFE3AC39AE0B64B6 +:10471000F9447317A2EABAC68CE330FDF8E3526598 +:1047200026BE5C7BF597C17A9EEE03CFBCC7CFED6A +:10473000BE9DE85EAD137FBC5C62062A82DCC74D7D +:104740000068FD831A5997FA62BA938F6E438562A7 +:10475000ACC36B6A53CAF8469DAA7450B0CF5C3B99 +:10476000393DEA9E1766487BC9FA88A99DB1E6B033 +:10477000AE5260FBAD83EC351977056B04AC073A9C +:10478000D83F839719908DED6C215D9FD6153453DA +:1047900060E1EFBCB25A9CCBE6C981F2FFA2288D42 +:1047A0008803CF9A897EFBE886195CA54DFFA67D1C +:1047B00088D8356183BA3EF50A60C71869F2341D9E +:1047C0005768E90E54ACFBAE607B65B6CF1371E160 +:1047D00083B6F2D86D41F1CF746318C7E25C5177AC +:1047E0005A4C6D7BB61AEE8AFD0D0D099F6D88EC53 +:1047F000B55FDAB029DA92E23F67D657229338D212 +:104800000E5747596F862870FA58ECDC1B81923F8F +:1048100082665FC0A4E640CEB4097D317B04CC51F2 +:10482000DFEB2AFFFF47A495204059A1FC13C835B0 +:10483000B55C3BC5F630AB76861951A7F28652447B +:10484000C32868763A12D33682F1ACA91A8B035E7C +:10485000BA300B3E726E8D2755003FE6F7FAC93429 +:10486000BD289DE3F1DF37AB164B95A7BD58777098 +:10487000E2AA1321DA5451436338A56718A91597A2 +:10488000424DD5A14F856F8C6AE4AD2FA8F6D24179 +:104890008FC70C85BF7C5B0DBF94B6ACEABEEAE562 +:1048A0009BFBC083CA213FD1C4EF8D422DD7BE42AE +:1048B00028B03D00D0339EB63E2BAC2CB802DB1B9B +:1048C0001592512A361F3576ACC3FA084BD50163D1 +:1048D0008556A9C8A428A31693FB52E169410C444C +:1048E0000BD85D1B38F769C037688A0B425A44738E +:1048F0004B61D44A382364D2B590F4AA39AFBE369E +:10490000A6DC286CE0214FC11457D806EA8B1EADF7 +:1049100004F09E0EF1290E43A1E5644238E092D5E1 +:1049200066679B52F3CF9A724673A8341F60904417 +:10493000E21914CF66D92CB7CFC619CEA8420A8186 +:104940005F1022D3B2CBA1BA89CD588BC4A1B9B420 +:1049500047AAF00DB0B279FA9A28A292BDF043C4EA +:104960006447FED0740A2AE725513FDF14E527FC8F +:1049700090D3DCD83D89C9224A5BDF8F30F74A5D8E +:10498000BCC9E69A693E8F9777957A0CCFC4B596E5 +:1049900025D8F055C984385721010C614B273BEFCE +:1049A000FFB8E39B2DA5950D1BA577BD3DD7017ED7 +:1049B000332E65C40E44558D207AFFC08A2C50BF1B +:1049C0006DBA9AE56960C2C3ACBC75788ABA413FDA +:1049D0007BFFB64760675D2ABFE6A12D56FD87398C +:1049E000984180167D91B0E1F962507261CE34D267 +:1049F000AC4352CF0E6144D52DF7B0DFDF28D5E8A8 +:104A0000074D1FD7FB1B2CC335E408D3415506CFF8 +:104A1000E6EF320BD7448A706E2A458402F12228D1 +:104A20000784964AA8509F5CF51A1B6593A083548F +:104A3000CD335208C06ED9CD66372FF48FECBF95B9 +:104A40006416CA6BA1ECACC354A6D2A9FB4547724D +:104A50007F2A6F8E472B0186E5B6092AAFF2E07BED +:104A6000C2E99D2E073C81EC4FEDF068F46108A28D +:104A7000B2EC07BACB671A1847F973710964F3CD22 +:104A8000478D70FADF4D201D7EC7C9F99CBE37F7F0 +:104A9000F4742B5D1E98DEF73554EC8E6052972926 +:104AA0006C165C8A945853CB3435E76CCF3FBAB55B +:104AB000FF47A33AE0D6AAEAA06454078D1F0B274C +:104AC000AAA224ABF3C34ADE7B57F59EE209A0A756 +:104AD000DC19202F14A2DBBEEEFA6C22421E7ACD26 +:104AE00062D77B4C4E2D805A51F163CC971A9DCBE7 +:104AF00068C7B4B6D8B2916474936866BA3027EFC9 +:104B0000C3B58544828B77956E196E3F5B461689D7 +:104B100007DE672219E36F0E8DACCBF39A1906A559 +:104B2000B6C6F09640E761BAF471E2AAA3BAA83516 +:104B3000A2FD429386DC85861653440AB476BE7B7A +:104B4000A9FCA5759E73BCD88B1E6E343731445DAD +:104B50000FF9344FF438C5649A95007BAC3CDD0006 +:104B6000DB2AE27E869A7101BAE8065C9FE9E86F6B +:104B7000A5D923000E43E2835DD4AF651FD92BE393 +:104B8000651EDA81C72202C6C8428A6B139A8C5D01 +:104B900035A88B686A9F58CD142601B97F13D53587 +:104BA000288A25B76DE59672F1814FD96F3E5CE694 +:104BB000A10CD944B627FBC505A1B25B218F3115E5 +:104BC0008D7404EAF0A0F8D8BF2CD0A80329B7E46C +:104BD0005058C7E6650DEA2CDCB178D4C1EAD8B7E5 +:104BE000E97FC87D71D923C24ED9A859C95BFD4C54 +:104BF0002E12BD79CF4F75F123DCED5B545F01645C +:104C0000F186D3FA881BA5F531C2AABC98C7BD02AC +:104C1000F5164C6879EA976A13472A0D699D701852 +:104C20005D0F6C87CC501CC823B47C235CB45E50F1 +:104C3000A618F898A60F380F6AE37E4771BBEDA25D +:104C400048A3F592C8E18BF1AAAB3F1BE8C9EF5529 +:104C50001529B7FC68A186525FFB2944FE5E10FA55 +:104C60009579B5F99E62BCB5FBDA9CD7AD1D068E71 +:104C70008247279A87AC70FF339457FD673FB8E4AB +:104C8000BA5FDBC4442E02605C6445658BEAF12C9C +:104C9000E8CE26F2C01B4D007F4BACDB8E628F6FDF +:104CA000D853871D8E1E25226845FD52C3C4AD1FF3 +:104CB000B17406FB0BB2AC4EC9B87A095D4922F358 +:104CC00081B5183B44D601C634CD6FDA8184357680 +:104CD00017C231F143BB80417EF7F07381F89DD359 +:104CE0000DFEA8D770EBBA2D4B0F8668827A93B46D +:104CF000E5BAFDEAFC8B663A5351BA5742BD997743 +:104D0000CB240369BBE21FF2D7A7CD6782B543F37B +:104D10005B5B6429D84829427D91E04125BFEA8741 +:104D200030F48EFBEB3BCF7FD37A0A011C3EBECD25 +:104D3000EFC1464CEEBF7C80C9693A04ECA97F6F95 +:104D4000C92364A48BC5341C558026C7A789370D99 +:104D5000F178BDA1166CDE79DC9665709BC9DC57D5 +:104D6000B18584B797635F582D0D29CA51A054BFF0 +:104D7000DEF3A6B88F8A2B6064F9F6333B801230DD +:104D8000EB35A611FE6E73BF53BDD43AE846CE3361 +:104D9000BE3CF9F5F49EF65DB24B64500CB53D4A4D +:104DA0008A689E982A5191A407CC6FE37796C6A98A +:104DB00096E656739A130716FD2DC38327EC6EE112 +:104DC000444AB84DF1DA32EE968A68CB41B0485E7B +:104DD0001AEE635CD1D18A4BFAF326F5631E763A5C +:104DE00047206EE71C25C2130A237224C05282F7A3 +:104DF00014D0964A461D862438BDC470D9CE286882 +:104E0000728C9E6DEC1F7F23ED0AE5A83C07B081F4 +:104E10003745DBBDBC4B5B09BA691F8F4699FCC3A4 +:104E20002668509AF1ABAF357173AC483411AA3D86 +:104E3000C45002B3894E9080CA51B1A09493D41A41 +:104E400004117037E8428AD287208FC82B729F479F +:104E50009E98DEB35AD1CBEB5FF24D47A89786ED13 +:104E60007E159EAEAB4A4CCFB7407766A5D29A3F2F +:104E700080FE0FD9D89D6CCBFFA780E4ED7A9C997A +:104E8000EACE0B4CDBFA9FCEE066E9451276B438E9 +:104E900048265432748D990D69FC9DB8BA415B5512 +:104EA000ED4002D2BA23FDB6A112761DCFAD5A3520 +:104EB000E25D00A29214215A49ECBFF0ED3BE48D73 +:104EC000B7CC0F73DF32574A21F3D5A1F0C2893E28 +:104ED000B315EBA40FE4BE22BBFD748CB338022BD8 +:104EE00027384933245E1C2C9422B23B3CAB8757B5 +:104EF0005F5079B251940904B8945434D8BE6FBA53 +:104F0000483D3ADFE5B38EA1C0F146E3E179485B65 +:104F10003A9485E6A7023579682376B0E3107E0BD4 +:104F200077E842A4D52BAFD412D87F212C1133E0DF +:104F30001A98B5D27E8BF6B0D89CFCF89EF5D9EDC8 +:104F40002058066D7247355CAD644346368DD5B446 +:104F500069268A395F8EE9AC62792F4974B4A63A22 +:104F600014E83DC276679C938456381E15C69EB5DC +:104F70000C80ECD22A0CCFEA4CD2E9F39167894E2F +:104F8000FBD319197EA79F08D8B90B9EBC6F9ED87A +:104F9000A5A98098312159A009D41D93F4433B7AE7 +:104FA000681ED08C7B2CF8C5AF2716EEC970C48B59 +:104FB000B9ADA4C24B3604A4E3D52F341CFFD7E00F +:104FC00035725E6C1A111DF2DA734B0D9B92E4037D +:104FD000D5E783A73FD4D034E401AE55CCBFC3D1CD +:104FE000F3BC2EC597EAD226A545DD839EE3613644 +:104FF00099F9DF7CC4AF1230225FB94AFB3CC5BBD4 +:1050000046AE148569ECC2DBB2E5E5F49A7C50BF8C +:1050100065F87D3939620E7E67102F346B41A89C8C +:10502000DF3EC8FE40154BFFE2803FE9DCF6F23878 +:1050300079960CC26D63428CDBC73A1B05E78ED4B0 +:10504000D3755595AD4F55F3BCFB8F05AEE795F87D +:10505000F978026C4EEECDDEC402835C830C65F6FB +:105060004DEF2B535F8C72685F7234E74A9565C4CD +:105070000F6B3DFD112E480B62F4E4F8FCDBFAA740 +:105080008219EB79864AF101BD8E8F3D7136CAD106 +:105090005580E01E5E748A0D3A8D1AF3E4D99A9B0E +:1050A000AF06DA4E2D6F0017EEC956DBD561B99FFA +:1050B000C3F49A636C60044C72AEAA72B48FAD4CA8 +:1050C0009FF110B130563547CE8EE9A7386E9B7CE4 +:1050D000907A06192A7304C88B767D1514D6175258 +:1050E00005E6F911E89624A1870A7EADED25AB48C7 +:1050F000758182166FB105B2EE96C725466CFA939C +:10510000099E4781E35FE7E90D7515D906A7226679 +:1051100014D3F981585989CC446AE53ED38F676A24 +:10512000CAB21DF52673DBD5C61B474C89666E2DAA +:10513000AB42DEFC17C5589A9AC281A83E28C2D05D +:10514000A84A43E02423322C59C00EA0521DAC4C77 +:10515000F2C92BB890DEBD05D32ED3C5D14FBF6C9D +:105160006809605D9A2E6DCAFED6206A227D1CCE2B +:10517000D596044B223CBDF5B9E5D3278EB3F8C6CE +:1051800013FA8B3CA0F90EDCD3576C82FEA7475A6A +:10519000940FD3782846A3763E4A6F52FDDA2C87C7 +:1051A000451E0B0081850F48FF41E0067D4C3FCC3A +:1051B000E75BE057D7954748EE208FDFC6001362C4 +:1051C000FB5946B538A54E17E596D34FC67CDBA5EF +:1051D00074C8A9FE3162F312451CC6BAFC6CF7977D +:1051E000977BBC1187D24E431C0052E5E49C149679 +:1051F000E754D915C69D40194D67D46313842F68B1 +:10520000B459EA0D258703C3C9ACBF132BDE1906B9 +:10521000B07BF58CCAD27C61CD96345AD5F74F78E5 +:10522000F7EDFAC97BEF998EA953B1BEFA200CBCF9 +:105230008AD9D678F6A59116D7237D1A7FD2EE03A8 +:1052400021DD4DD88E00D7A61FD20C5326480C0E58 +:1052500017EEAE93B0D26310928A6C85E1EFF382C1 +:10526000CD9FA0711E03BC3B44D73E603064FB471A +:10527000110916AE769B09182FDDE51ECC3D4EE2D6 +:105280009C589B71FA27C062F6589768AC651FCD91 +:1052900034AE1F74BA1FA8720FF8D938FC25D7C1D5 +:1052A000271E3912C30F42FAEB9ED1949695511CDA +:1052B000B825689D373717D4CEC71E77A195C47E11 +:1052C000553761DC249C6B04B20278BEAC79B0C166 +:1052D0003F024D5922E81AB07FEC94B639592F7924 +:1052E000161EDB866111FB66F811405E7C0D49FEDF +:1052F0004A4B6BA380579FC16B7F8C5F81182B1A21 +:10530000548FD69B2A21FEE3223446234B7C42BD98 +:105310000D21BBD7D832ED815ACD004A69B01E2687 +:10532000F2A27A1F7E5516FA29680ACF88A05091FA +:10533000E46E1DD94E0DAAA2C087F9FE2EA8EE720A +:105340003E75F373A6D2D50BC103BB861DD8A5024B +:1053500065BA00268399BC4C3AFDF2E84552D80D57 +:10536000314DEE48EB7E5450C7CA4436196DD07BA0 +:105370006FA33D25A3E681283E616E540AF910AC67 +:1053800032843D68F562D7258D8275050052266608 +:10539000D961442B035BEDAB39BE572B0924A61E04 +:1053A00017F661A418AE3F5AA13A05ECD3C6E96FCF +:1053B000A0827331F82546ACA93F84B8D50D6AB6F2 +:1053C000F95FC1B644A83898C0002B92F78788626D +:1053D0001BA2DF0A7076F08DCA67EE5F038141275A +:1053E000DEB3072FC601DE4160BD1C4C1D9A4E780E +:1053F000590DD84458B7D9C4EE7B7412A2662476EE +:10540000D878070CE59E2E90AA8CEB81C516F51472 +:10541000EEB5CDFE2911BEC5A2E153E6018548FADD +:1054200093C6C1B7625DFB9345A5D30557098E7539 +:10543000DF29A4C1E4C3D6BF2C7399CCEC44D710A8 +:105440003B8721D879494862154C1C33626F2A4F3B +:10545000A07EEF48C0C486F5879EE87E9E86EB035B +:105460007DC68EAB393C7955095172F789548FDA74 +:105470003350C39F82330D86E33AE401057DAF9A32 +:1054800001B06313EBB251F133778F9FF666CE3ED6 +:105490001B6434A3BC351DA175F0BC46DDE40FF8D8 +:1054A000B5E69BAA7DB76316579EADF846AE76D398 +:1054B0003C054BDA2AD8200D5573919AD7C0CC6998 +:1054C0006EE91C3385B86F74405778A7961730EB98 +:1054D0004032936F35763B7BC3FB297895880B2D43 +:1054E00025A2E98416A3A13975A380B326A61210BC +:1054F0002109C84FD31138676E619DDCF3D11408C0 +:10550000C2C481AA337438AFF93709B2598E8B3BC4 +:10551000332B54C77A44D928EBB5906BF0A7F0C26F +:1055200020FFFC547E1DDD0EABA1A3153DEFDDC3B6 +:105530005027C53F04D85595BD10D4289A6A6351A9 +:10554000BA264695BF854F05B68FE935235168D3F6 +:105550000C456C8982F7C742A0CE97D4E178C48805 +:105560008C773714036D1C0ECF33062D6CF8C951A0 +:105570002E73FCE2FCB60EAFD43215C3B40312296D +:10558000D72DF627BA78A39EAD85B9F8A8246EC4A6 +:1055900040D24DBBC190B78CF54C426CF7F1C5DAE7 +:1055A000FE4FD5EB9443196278C0CFBAB5427795D8 +:1055B0006022E9E0D7D01C182DBFF55A4254FC3FB9 +:1055C0003787421B3F36DCDEB808C651B942760C3D +:1055D000038FE92DAF45AB03B7E08FC7BC3B1C7C05 +:1055E000FCC6BD4D4DE8BC4FBC6CF1EDA4CAF0D675 +:1055F00051014C0B2010D8EB1C05A034BB3D4EA133 +:10560000A1D9161EFC16C747D45D7AD111523FCFDF +:1056100078AC4C72823F10EC1ECF052884A970C074 +:1056200057D075E3EFD93629589BE8C7CFB022D1C0 +:10563000CAAF07D35E261C1CA7C70DF3CC42CC0310 +:1056400075F58DCDD72D6C2C45FB5AFE353AA8C289 +:10565000E70650B087BE046F1922F56D2C9CC52457 +:10566000CC586B401BF001982D16EA8CD0000248F4 +:105670000B8687FCF53DC6504E603E2CF0D3B577C7 +:10568000D94619587EF1FCBCB63B9FEACABA5A7893 +:10569000A838767C8DD984A184EC52EAD52C2F08C9 +:1056A0006DAA769E652C19FC36E0D0E232F3033009 +:1056B000A4455B80E93B68D98E3F0766330BF83C15 +:1056C0003D405B843C0C3C4D820C8EDFD6ADDFE967 +:1056D00059BB89409387D0222AE38A31B72A5A25B9 +:1056E000357B49FF9439340401A16EFA55D4D5F5C0 +:1056F000D8842F0C8963AC3263B9EE41CB7BDF32A7 +:105700007F1CD9C961C3212843FAEBDBC697150278 +:1057100087288DA51078B2D699D305391DFED836C5 +:105720002DF38BCADDA9FFD0638E6BC8916ACEB012 +:10573000835FCA08FAE86261F36BC94D0813641607 +:10574000D45EBC6834442594CA6A7DE685966BD0E5 +:10575000FFEC666923F21292F8ECFF2AF84A75030F +:1057600082B1F2E4A97D9269FA86EBFF4994FC6963 +:105770002569788946BD8FB87791DEE03ABFB1C917 +:1057800043D11A62F5F1C341649BE4837FB711D41E +:1057900036D86EA5D60FED01221AD8F9B67533B9F1 +:1057A000614A9A26B1BB4C28E54363698A9A499AB3 +:1057B0000BB1ADBA661048D0303B827E3B1BE4A3F0 +:1057C00008FDCFB8F82F52DB4C3345985CEF498E7B +:1057D0004AD9FABE4E00DDB19E8BD957CB38CB37B4 +:1057E000D07CB6825DCEEACC0EF5C5960CADBCFC85 +:1057F00004FD3D2459B1B288605060E96441827271 +:10580000260367C4C1940E800BFAEF91EB430A9212 +:10581000B66C08655F2B8D05D6759A25F49F9A4660 +:105820007D67C43E4CC180C736B8BE58CA9EAB33F4 +:1058300006CB900776FD72E6F1581F71E826E12944 +:10584000265B47147F2979FBBFA4C80BB5F76C21F1 +:10585000B6B9CA83D5666E7E95E3FC55A349D9EBEC +:10586000E93767E044E961F5938B5397A6B8792A45 +:105870007E9F7B5A3F1F8312C89481571E7E2BAC9C +:105880002C18389153632803A5D0D14EA895FFDA80 +:1058900042772E5D16893ED6803FA44BCEE8AF639B +:1058A000D38E511575746243905D737728194F6FCD +:1058B00024818BCB7138B38F7ACC074FF3244C3DC6 +:1058C000CBC1A5AF3A336D698AC7DC3307F58BA42A +:1058D0004783BB6D360DAD34AB17E66D405C7FA2E0 +:1058E0000F3FA8F71CD0BC51444F5D72C8BE117366 +:1058F000789812F647918C9D7039F068BD30880E0B +:10590000349ECDF94041AD45B0F1CA2AA9822EABF3 +:105910004F69BEFF741F0627578A2DC126D6E52979 +:105920006023BA68750C482873BF4E86877BCD7A92 +:10593000A953CEBCB3313501AFBC0FAF1AE95DE45A +:10594000FF8BA390A2A5C14A99C6608DD8E8E63F17 +:1059500099059C1690CA3E35BD0A2858DBF8A73D2C +:10596000B7D68B58846A4DA7348C41F50F59698797 +:105970001CCD9C7AB17D1DD747B6DEF1F9E6823D9C +:1059800056401BB5A1ED55FBA9553872D2C674A37C +:1059900089BB99F8ABFFC15D068A4D7F1499567F8C +:1059A00042C12931A785F38B8F779E6D20EEBAB661 +:1059B00006920AD6E8422033583534115BBE66564B +:1059C000135D0A93E4416F7372DB9AE399FA6C6298 +:1059D000F5B697E40EB7BB537841E2E1D27697096A +:1059E0004A6D0C92D6AA378D1528F147EABFA4A0BC +:1059F00039133F8BA997F1DF9162E14ACEF3BE5C88 +:105A00008D8F994417DF6A6ACF74163B4CB32256C8 +:105A1000DB74AD972399F986384E06BD4A8823D3A7 +:105A2000A0E13BEC06D8CA08D89E8142B0B6204A15 +:105A300046E404FE49A6FFE332539E54282A45D18A +:105A4000EFA14D551DDF2B916324ABCE1B0CE974E8 +:105A5000637F82D67543D56CE98EC7BBD2F81EF042 +:105A60007F4D6A32C46561892419B45A9BD99FFC61 +:105A700011AADF1F9FE014615D250F50AFAB8CA012 +:105A80003754BA72D17779745BC9374E105621AD4D +:105A900065C97462D18FBFB5F824A937FB10CC510A +:105AA000307444ABA913C368979380EB9B3C1DD81B +:105AB00019D1897CBCC5D007286250C339EA9ED869 +:105AC0004E6ABFB3C0600259E6C6641279338B4E8A +:105AD00038EC5D03B204725B1FA37E02190642AE6E +:105AE000DC5C5D2CA3A99660C88AD8745BE6117C47 +:105AF000ADDEDB9D56ECA60156DE6D88D5201CBEC2 +:105B000065A70D673167303406AE83AD48F12D3D92 +:105B100024C36E1C229BBC9686D1D5E82C144CB5B0 +:105B20000CE4D1771DF5AFEE0F2988A3243ABF7896 +:105B30009AA6BFC68A721D5A73E0A3E1ED17FF8EC5 +:105B400099E8851BF4D06F300B01F81BCBB76A8B3B +:105B500078166FA72965E09D35D5B73DE4D25CDBAB +:105B60000D06BBA8F2451BCA34DAAA6CE3888A1476 +:105B7000E494579631045785618DA2E76A02EA31B1 +:105B800010FCC034DD35D0489B7C7E79D9DBB21067 +:105B9000EFE990EE3924513DBF0BC0F9DB63F6CE3F +:105BA000E9E8311B82F8A9DF76F40E8CAFC5F34427 +:105BB0002ACD1CD80992AE016FA763FA03A5AE7374 +:105BC000104EBB163885513767566ACBB379D3CBA5 +:105BD0003804B1D6E23F86418FDFE23B00E7E3FACB +:105BE000AB4192755E52CB8798DC051256F3A8C77D +:105BF000CBEE7542298B85A0A2180142207FB67991 +:105C00006D1FF59D88EC9070C9001FEDE1F5B8B8E7 +:105C1000588DA0A4DB3C8A9953A1B42E817E1ED856 +:105C2000CE142A01B9B63E479F55423E871D546D9A +:105C300054D82A9D3EDE1F7BAD3390B0891A60B5E3 +:105C40000C25B36B3B02B8FE5FBE1EC46BCFCEA269 +:105C50004650DD5B2C46659C5701B65B16818AB9C0 +:105C600047856106EBCA5FF899CD6CEF1096DD3C75 +:105C70002A8E7600EA816D6276364D5D7294CC0E86 +:105C8000137A31003EC8589880BE22BACFEE0C0677 +:105C900054C5E202FDA7C09B840BC7C77F5C402CA4 +:105CA000B387303830E68D997FD2ACE52A86D7AFFE +:105CB0008797FBC6E1A6C7C881CAE6F0F984DAA9CE +:105CC000E02BB3B44EB4BB1F1E7B1179DDAD059341 +:105CD000B119324753033A9A93BA5018338CE94DAD +:105CE000ECFACDD5461737FD8AA262BDFCE5BC6053 +:105CF000FD293A6576DAF9365F085945CD066EF723 +:105D0000F5DA169400B65C65CABAAEDE04C007299F +:105D10007D5A5325E2CA2175A3C34C7C9A25E7928C +:105D2000AB6574C66F6B8D33D004B86F14E9C75977 +:105D3000BB9D8C06C4EF58EF11533073FA92B57FB8 +:105D4000EC21A2BDB394E9694D301EACD8D7D4C2C2 +:105D5000899AC9BE8A0F05AADE531DF52552C1A234 +:105D60006670BAFA618A9C3E59A8A5E760306A2439 +:105D7000779DD51718D3658E57CF729B8E8B0205F2 +:105D8000893D553D8E52BEF141DE2B3AC5F6920E4D +:105D90002884A0C93E4FE3CE1E49F6E5411E7B6034 +:105DA0002EC59C2C1C54DC7333793C757974FB1420 +:105DB00015B6E54869E7811C9A4CAC42D8DF2DE561 +:105DC0000D96566ED923D41D978C29AA5271947CB6 +:105DD000A8473E1B732ADE0D1C7B4DBB5FB3B97F0A +:105DE000FD9F6D91CBDA71428A7FA3430B8B01FA41 +:105DF000C03AB039A2122447F709E7465313F327F4 +:105E000023B7B259B9964B299D9F966E3678AFDD70 +:105E1000C39D25671EB2A5B22BA85544E472D94C88 +:105E20007641F4198812A1152F050CB2853613039B +:105E3000027D43FB8B7D1C52DC4D8C2FC97996D59E +:105E4000AA4E09B3BABA6D955DC4795D20B8C38016 +:105E5000F4336A1637A3D0CA073FDE425A08AF2A86 +:105E6000E9BEAD76F71E8DDA2F14130BDE4DD22668 +:105E7000BB7689AC072AC90B21A9580783F158C5FD +:105E800028B0D4BF889D67931C48D673855197BAB4 +:105E90007BBF90C4E4674D80D73E93548AEA7479FF +:105EA0002363A948C61FDA91B28A7919A277BBA1E8 +:105EB000DD5F8A8005D8AE09A1E26993B8C6B9CE84 +:105EC000A91A52F518E77ECFF3C95CD2689F16F67F +:105ED000EE1B5E36BE9A014E041C52111D763E82A8 +:105EE0008DBC27B4B376EF3CA3AB6C5AEA014F1DCF +:105EF0002F93326862522C5C73E4573208D12850D9 +:105F00007C2C85CFFD824EAC9812960475FD508591 +:105F1000683BCCD6211DE1647CCEC3121A28DB4D30 +:105F20000634532CD2A4C554F46F6CD7739765EA2A +:105F30003E322E3EEFC0E604C549604FD8B0DE29A0 +:105F4000B8BF0409C34B8FCA103FC79D9168C121D8 +:105F50009DD13362E6920273E137A749F185E6608D +:105F6000DBB5669FB1857DB8D107B4F0B86465989C +:105F70000C2A9249DD41BE728F9F17437088169597 +:105F80003C536388701ED2306D25A707097F4C43B0 +:105F900023A5FA67F7B5B3BE1914B3E6C4FCE84C01 +:105FA0006F48B328F5E1209665C447B9C55CF20B8C +:105FB00087062327EA47136488D5042AA3929BF314 +:105FC0007BEE70264B83C3D059EF81CA7AE4E52873 +:105FD00004DF84F8ACCB52D51D3799928ECC50AFEC +:105FE00082AFCE4149C66F3D68BDFE5897F5F3A11B +:105FF00034CB597155250293E16D2AC8A0F900F4FC +:10600000FF69F1374980FAA0CB205292E7514FC285 +:10601000281D0CF9DD37CCD599072AE564F6146400 +:10602000FAF059614A25AC421B2B69CC93A79DA974 +:10603000E1CAFEF53C984B7E62CE66B1C0D949EC10 +:10604000DE1F273254CF540835087D4EF8248A507D +:10605000F7B4958124C2FAB4A434499F4C346E80BD +:10606000D7E46C715356E9621FA4268914A979E517 +:10607000A106269A6F667C55BD61B85AA72EA1C1AC +:106080007BB641C632C8C35272C06009C43D7D7F31 +:10609000668826C3422B718B23C8345D2AEF72D8E1 +:1060A0006C7FEC98F85461659CBDD9994191FBA92E +:1060B000721D9FC295B87E2848D9924F536816CB5F +:1060C0003C1B5A1AC7B34B5BE8FB11CDB7073C2109 +:1060D00029AB5B4E64C6A733499906301B69FCCCDB +:1060E0008FFB30A0442C653152B6D0BCAEAC9D7B4A +:1060F000F9FD32F1FED9965E5D33BD93141D912DED +:106100003C65D15A0E28BA392E44CDCEF2F365A1A2 +:10611000DC2C292704000100000000000000000022 +:1061200000000000000000001020000030610100AD +:1061300013D970005C9D2718DB4A69DDC414006C1C +:10614000BF166B7880C57EED45AABD040822F18993 +:106150002297578DC254A33B12F3418007BD6411AF +:10616000C8A67754A8C3E255048E09C4D86FB432C8 +:1061700091BA4E5B24FA9497C3F55954201C3F9D65 +:10618000B5A61C9E91D51597997E48934F05A5B548 +:1061900049D9B5272F9C97D376ED14A7803E66FB8F +:1061A0007296ACD35605CF32AA47B388B5785E72E3 +:1061B000E2EA4D74736F173ADC8D371B4CE0C5442F +:1061C000DDFEAB7A7087FA3C2453DC8DCDFC5E712A +:1061D0008B3DE370371F79BEE54B3E9064CA0A36AB +:1061E00053894FA7B8F5771F9E3A990DBD33520BCF +:1061F000447A6FB46609DC333FE6FA6E3AB2B5E032 +:10620000C1D0410C54CE45C61DDAAF59A7161C5B50 +:10621000906A615EFD22F441E8B6806E422602DC9F +:10622000F4C32059B0A0BAC08256B33311D99AB979 +:1062300057AD26A7B048F14E6F8DCC7E740541C98D +:1062400023C6976068B13136F2D2CA5F3DD62B695A +:106250001066B4EA408A9B2F0A87E1D8256F0701B0 +:1062600016F60A3859711279B99E73E3A0AA4391C0 +:1062700048FC4C5A65B22130DFC4E76468E64CF351 +:106280001EFA728065D7CD493D2836146970C089E1 +:10629000B8AA0AABD495601719AB68F464BA0B1F9F +:1062A0008D3A02011D9C67F8FFC2340A0213E72CE5 +:1062B0006A36248E3625379CD32E99EF45B5F18A60 +:1062C0006E5FC48A0120F14888101DD9F942A1C02F +:1062D0009817222D78DA9C386F92D49908F8DBCF82 +:1062E00065260F3990059815B96A7FF1F6F3D1F755 +:1062F00020A85CA6D6E792E424616394F5F72E60AB +:106300009D7CC5CBF617077DD12423C540C97D668A +:10631000710BB34A2A2EAC05DD853C3887F3D12FAB +:106320007EFBC468B81342F61FECC55C9B213FC8D6 +:106330002B864FDB59196865639DB632B9F8FB8F20 +:1063400057EE9F604344ECFFC488C10B06F16F8297 +:1063500065CD76D9452B8E7EE93DA2CA602744984B +:10636000AE6028B16A899224367BFCD64F1A684801 +:1063700060F1C50E336F22EF36367AAA097B93B4EB +:1063800054C044DBA097454E9A15FA0EBBBA3F0B9A +:10639000212803C68DEEAA48A007AD85C6DB6FCEC7 +:1063A000C06B437681610739E2F35005F818FE6C43 +:1063B000507567B17DE4409F757C998E39B34E3E30 +:1063C0002F91DA76DEC5462D3B05DFF3C64F2B391C +:1063D00065E0FC8E880E40AF30A4369EE767FDBFB7 +:1063E00094D73CB7E98BD67D81E445812843B23808 +:1063F000983155204BA3C23172858C2260B1BC7993 +:106400002769D8908DF889D3937169D53CA812F883 +:1064100044579167144A2BDA342899CA20FAE7E0E6 +:10642000995271519714C8ABB2125F515EA6812E7A +:10643000184AE87AB9EE2CB0E2482F9DE504186EB0 +:10644000B84C1A4B4FD66B33B953D2ED2D626F5EF9 +:10645000AA13D65C22187F52300D8807CA7FD36BEF +:106460000465C51CA5DF41B3553A4BC170CDECE2C4 +:106470000FD306A7105141FC66A7C3A3C46D1BF13F +:10648000B484B804804D1D25A5F10091901589AB09 +:10649000654580FB144369DC9A6838DFD91912BF5F +:1064A000F44124C8D267A657AA3000B598B26CC090 +:1064B0008719F986C4C9FEDFE4D717DFD667531DF5 +:1064C000BAFF489A13510D7AA9F8999992DEFA15F4 +:1064D00047BD01E5199781A3A8048E5B5C86FEAFDA +:1064E0008C7221A2F07FFC3EA8B2C20A019A8BF7FF +:1064F0003BCEAB7B04DA13CE612CD3F404CAC48E3A +:106500009BC4178DC27361F12124480BB37E0077C1 +:10651000EBB977D08FE57BA574E357F8AD85F0FB39 +:1065200000C51FDA22E89DCE10F1BC9331327A5DAE +:106530007F6A9965A9D3D69D9162AC9A8E8A95336C +:106540009812706EC574F3E6971801FD3BE6AB7ABE +:106550001C018F38A1F9093F7078E4EE07E042BAD8 +:106560000C6D8D9967FC5A7E5C8467F913DBF5FC32 +:1065700069940E3ECC93B4902A9B085EFDC1AA5F3D +:10658000DEC7CA71B9BA87C0D78FB3C472F2F8FE3A +:10659000692C05A4E1380A1962C2A6F440B220A40D +:1065A000269DEB93FF93F59E3803D31EE6A1F38F50 +:1065B000DC96AC2C8933F53B322A62D86A557EE8EA +:1065C000EF4FD495E16D2659B9D61D9B46309421E5 +:1065D0001982438C926C68AD5EC0853F27F74A16DE +:1065E00084BB00881474DB0C90E5B60581C5640398 +:1065F000E4826AE5D58FE58614FC4DD916853E0305 +:10660000727720B0FECAA57C514F15DCB3453EB36E +:106610002C2186BC00BE001CF03CF92452A0F99944 +:1066200023919CB09C7B9B21F9C42BB604E4230EE0 +:10663000DC6B3632A032A6B08E92FC67CB7D04B8FC +:10664000E4507F1A3F32307B2298B8391CC6AF9293 +:10665000F0A640ED177A28816646F6274A70713712 +:10666000B047D015054234A415A787221503217918 +:10667000A03A3221575BC19158830F00C48B1EE7AB +:10668000699F37D975764C5C302C4CFC48C19B60B7 +:10669000B23257AB723947431259B323254F69467B +:1066A000CDE6CEB0B8B3BF910938DEC892F16F8E97 +:1066B000826F1F6622B203A01005CC2C48A431D3F0 +:1066C00025B07690460A9D00BA7738E68E963A67EE +:1066D0004F9CFF3BFA33E33934C942F625482E5527 +:1066E000C0BED7A7C8060345BB469C00BAE664787F +:1066F000FFC4F0A940836A569F3B6B61EF13042DE2 +:1067000039FE19CB2DB299E8F595A3B4AEC92FBACD +:10671000D803C7104B060BBA7361799AF2D654129C +:10672000634E3E7DB46DF0E6B65F5D27371ED869D7 +:10673000DCFA33034D90DB518C4E3047C9E2D85A16 +:10674000F2A2B2235BEDA2DC72D20BD18D3F7F01AE +:1067500071CBDFD8218AE3573F8522285EB3D75417 +:1067600027AD3007190B2FC55E66CDD9ABE241606E +:10677000D6468FD075983DF5042206B999A6865362 +:10678000CCD38F4C6F5930780D9AC154952C513E13 +:106790009F6C8C72F352E1343F858EA6EC6990B702 +:1067A000712842CD8CACA71F58C5F3C0DCE8B48E6D +:1067B00042E33A8483A656946D5F215BD388D1254A +:1067C00038D8B1C6E2F32570D974F74B5A69EA029A +:1067D000155E2EC961C65560D23BC691E22EF0E12E +:1067E000B3BF2174412740395AE1E4CF7E89F4E9EF +:1067F000B5EC28F0DD7FBD25BE9615D736B5B96856 +:1068000005E8AD43517C5A4E671241C1B289A0A937 +:10681000422CF96E3528DDACAC8098C94DFCC9EA34 +:10682000EE904C271626614B4B49ABAFCC18D919CB +:10683000F36D7F9F01F6349A202655CD46C19AA468 +:10684000FE2461EA8DEA5831D23B42798E4B31AC5D +:10685000598664C4DA4F649E9BD083E8E8C2420440 +:10686000619B72559E727446D8C8D4C3E6C3FEF0CD +:10687000C62B073ACE6083701CEF2D5EAB991616BF +:106880008931C89C2ADF76592BD7FCDC1FEC69279D +:10689000305F15C9F87BA6A597B946A2645792192F +:1068A000CF96E00AB8DA2E8C24C594A1EB41DDF234 +:1068B00089DE0D605EB20CB91AA914E946E036868D +:1068C0007493724B45501D9E3A9799DF145312559D +:1068D0008BCDEBD8BF6FE024B8876ABBADEF5524F2 +:1068E000A8D844EE61DC1010DF477354A604594465 +:1068F0008424F8E88539755BB9804957482C8C7138 +:1069000086BF3657B782B484659DC0033C85378502 +:1069100043BD94EBE3396943D84F0CBD677D0FC18C +:10692000DAFDA51A680DA713A80988CE04365B55B1 +:10693000B49C9CE154AA9AAAE493AB6379D19E7665 +:106940003D56A16E154A003B34D231E869DC283C43 +:10695000C2908CD60FE01CEA728DE09B33EAF747B9 +:106960009FB814F62918E202CFB0A2A3D8712C6602 +:10697000857A6D3DBAAA2FC9C335D6D8BFC4DFAB5F +:10698000E00958046539A2F1822D519D06AE3E16EC +:1069900031680D97EC972C8F96AA2D231CB53D06D8 +:1069A000CC04DEF9B9C8790222E6AB83F3E6DB97C3 +:1069B000EB31F29D4A26E88B86463172B262A1061F +:1069C0005E07706C5D3E27E4919AB00866E7BE52A0 +:1069D00096DE98762CCF75F45B186978684CEA6976 +:1069E000CC2F49443EFA09A56F1C9CD29432083141 +:1069F0006D7773CAECDA440E43B696736B5A27CCA4 +:106A0000B87401EA06B50EDEF3A4E596928429E691 +:106A1000C3B746B0870FB9BFBE93013CCBEA0CC3E6 +:106A200058E2B865FC5C787D230994D2896B2D5DB2 +:106A3000998C862BBBB4FF3A392B0F192845E5708A +:106A4000F78F56BECA5A7C41E23F9F1EDBB2912BA4 +:106A5000633A78F5934CE47002395CC1D883950FA2 +:106A60005B4D4D91F7122B0CAFE83196B01B85B101 +:106A7000AECF221C92F5F1720F9D61BAC4EE58E5BB +:106A8000696C230A88181986067567645AF441D31D +:106A9000382F545820A1FEB8983B9D516AFB31E72E +:106AA000AA1117E3488F2D126872510D582E008CD1 +:106AB0009DD97C7FD8113E4FBD8762A932576A822B +:106AC000CF3DDC253A61D07D2BCE68D5FCDCBBC642 +:106AD00076A459CC73F520FD82BC7E7C515ED6D65F +:106AE000E53FFFC436867B4CC2358C0ACC407A9990 +:106AF000E5F55726F66D5E4378CBDF5C5CFA8FB028 +:106B00005888C428999D108E5C8D2E7C7531AB19E8 +:106B100032116680C406748BDE53E0CA184C6B7A5F +:106B2000449AD34D15C7F015242C66FBBF20257F52 +:106B300098F812B8D3A7E0770DBAC6239987C8CEC4 +:106B4000BF5035698E333ACCAB999BEA8279726E2D +:106B500087F96CD8C90112A09CC6F58E8229C11C88 +:106B6000E737EDA89A59E38FF8519A218E3116A98B +:106B7000BBE7BC781EED6C01971D514D333885E3A2 +:106B8000C2AD7DA051BBE0D834FCBA14C124C8A169 +:106B9000B30D51EAF50786DF53A3F7EED83FF413A0 +:106BA000E32E9141BFFD14F6605F7B2238EB48F580 +:106BB0003CDBC098BA7E4D5741C6240AFD123D7099 +:106BC00062737927FF4C71DF5AB4F64E1A6EB9031F +:106BD000A9CC6C0CCE1069501FFEB737F78BE3724F +:106BE000AC8158E25CA94571305C59FCE502AC64AB +:106BF000D5166FFB429C025CF582289991F77E07BF +:106C00004F85D459CE0E783ECAC9394AA2FED70C58 +:106C1000AFCF3425AF52A0D7B7444C5E2520B0D1BA +:106C200036619F573BDE570A7C93469CBA82B37B02 +:106C3000EBF2F76C6DD2BCA4EA127DDEAB531A60A6 +:106C400094B52A569D0220AD5795C63D16433E3653 +:106C50002CF3827C7B001310AB98E8A94F26FD50E3 +:106C6000566495A559273F9F397361C6E42AB4C37A +:106C7000AB7394BCC4726D4180207EB91CCC0AA752 +:106C80007608E8325384E3C243ADB7DC12CA355606 +:106C90001CBB430826CB52566E6733582164051B34 +:106CA000AB2B1F35FAEBBA000ACB7B13EAA56B4975 +:106CB0001BF898347A7B15A6D4D3DB37BC02327527 +:106CC000E3B0E00786429F96A69057DA8543410AD3 +:106CD000B05C41DBE77CCA0F80ED47E6788B9A8990 +:106CE00019D856F03F5DD60D2634A4897B30C2E614 +:106CF00016F0371C342C39E892E25A6483E7CD7FD2 +:106D00004F86E4BE5D0D489374C6869BFA0763D335 +:106D100046E147E64AA695481FA806F40C0E5966B8 +:106D2000CF0341A6B6B628FFDA8B979054142EE60F +:106D3000AC8B0ECFBB6FC3FA7AAA46BF59A24AE802 +:106D400088AAEC2DE25B0DECCB01BF7A8616D61833 +:106D5000025776B34CE713D90D2FA1DE96737F94BB +:106D6000A9C110E0B8CC84CBDC0A646F2E3AEC28C1 +:106D7000E0C5FB4D610501D84A48EF0C754B411B3E +:106D80001FCA0D003B66F80FFE693B9CE1516D2F59 +:106D9000AEA384A9D379723815BE05B9B597968F7D +:106DA000AE9797E1535B97324224146D0F307CA06D +:106DB00004A98ABDB7FFFCDA192AD869CBBB0E7EBD +:106DC000606E2817384CCD23884D1A42105A844DD6 +:106DD000C921797D395AC6B4EA6312B4945E88AB8E +:106DE00075664B751EE6FD53733C4F8DD4907375DD +:106DF000D163975ADF34AC8FCB52AD918E4C89FB67 +:106E00009282979A2E82CA2F1F960B8D2EFCE4DE5B +:106E1000B658C7A735E8BB0CDBC1F60C2AB182DD3A +:106E2000C679988D433CA26F4D8BAC8ADB66184EB9 +:106E30003BEDADAB6CFE33E85CAF4238D345CD9053 +:106E40007F489403CA63CE3E8EB074C0774BD41E85 +:106E50006EEFAE1F7243BE42F99C74DA546264F066 +:106E6000B962083EA72BBB76EC42B66079CC52E003 +:106E7000BB332B8E94D6CDABCC974FDCF451E1B81D +:106E8000412895463460B18D80832A95D97D7B61F8 +:106E90002C2A2AF12EEABFD91F41C0A36B65F93312 +:106EA000D0AFE490008B6A0BCC427C080EFF9DA70C +:106EB0005EB58D59DF3F51199221994945A85792E6 +:106EC000A3FF259F11E7B9F512623E459B956D0919 +:106ED00059A20B24178D64C015FD12626FC89C382F +:106EE000F3EC39B1CE1BD3E330C5779D631E40D59B +:106EF000C291373E358DF3E9245DE9DF1262E9A3E3 +:106F0000DA2823D853F15587E42FE3FD32A636FD66 +:106F100071058AB548E13D78C232F4E45559F6AFBF +:106F2000BA2C3A13EC987CC6CB40CB6D45C788FA97 +:106F300076ADBABFDCE75E7CAA45971FAD2B815CBE +:106F4000CB684F51F99583EA08FEA7D1FBE8BB63F4 +:106F5000ADE1D49A23A0F1A2DC99453E197E075AEF +:106F6000699FED73CE8797219BA1990B65BB65C681 +:106F70004E2D0EC50ABF71F9DB451D41889F13E5F3 +:106F800026F53646210E2B3E7E22718326BE23CD6A +:106F9000324AB48976FB700900CBA54633131AB97F +:106FA000146A5DDDD0EAC9B37C67CDF987B41EB53C +:106FB000956BC475E0E62D84B037BA1FA7B7591F8B +:106FC0002D2B9A07628D26847205C032F597FDE657 +:106FD000B4A6E38BF0B3D2307B5E193432C54005E2 +:106FE000EBE76FC589182C16EF15C3D48C96CDD05E +:106FF0006F77649D27B065111E46B1FB54646562CE +:107000005FA8B7529F027F858B3B55EF51553B7D63 +:107010003F4DC5945F3267FACA816D1CA4B8CFD6C4 +:1070200072BB8F148D56700220730EB9218B3B4FAB +:10703000A4CCD9049B38D18A01DC83C647D5968578 +:10704000C7C50F18B8E78361C4E51B048D4BED7805 +:1070500099CD480A4BDF46655F48D992E5CB7D0460 +:10706000D78D31B661F93C94D55E3CE9F5D9136909 +:10707000B44ABD5C3E98F519A887B4E118DAB47536 +:107080005711ACDF331040EB74E69E4EA1AE8E0B71 +:107090000632486F89069D4A164CBD9FF9DA4FF2B9 +:1070A000EADF17CDFA8E37C23F17851A792FEFC561 +:1070B00013C61456E953B0533E9674CDF3A40ED0C4 +:1070C0008B6FFB1322675EB012AFFB7236C164EAAE +:1070D0009638AF5B6B3C9A27188E802BC57D550A7E +:1070E0007C6A36041B2AACA2A048E340E5EE6E3071 +:1070F0009111082C939CBE127C5A52B0877C6A4A2C +:10710000672B792933F2A87A720F280066D1696B50 +:10711000A7E14D2A9AD62E3CD826C7557D104B6044 +:107120007E2B88CDA9BADADFDBB2D100727AD78E96 +:10713000CF38510587C1759C4FB39FB9D8E6A6C615 +:10714000B7CDF59FFA5ACF81512061FDD3A444BB3E +:10715000DA86159A50871D417D5EC742C119CB8AD8 +:107160009F29363EADD425E6EC60180AA1C00F7009 +:1071700064ABE5486300358636A87A37B8A0F87E58 +:10718000A113007FCC25821BF763BB611041808275 +:1071900042EB9E8F35EF1467AB51E5FCB7804E3D57 +:1071A00092B2395C5C52498F00FE1EF041B635E563 +:1071B0002E62716801F0C023010BF0B339BFC8879C +:1071C0001E0535ABBF7475EFC7E18271E29F5BD0DE +:1071D000ACA3CBE673928811C4143A4D24B6E3E510 +:1071E0006968BCCB9E7CC6605AACFF6F57501C7759 +:1071F0002271107B8CF2510D5B5599D5D2F4E0B41D +:10720000D3FC9CE629348F8F9519B27DE83933047D +:1072100067E429688A908818B3A1F094DECA73F0F5 +:107220005A29257B5B0EB53F04E7986E49E00F7C39 +:10723000B5F5CDBD8CBAAFD269B251F478960BAE2C +:10724000573ABCDC199D3B1F511C6AF228FA65A70E +:1072500052A4E16C9682BE992233791CB34DF7AEED +:107260008AB23EA8647DCF3590E1C1A5646E8F3CA3 +:10727000025AF4A9B08DF04FB381DFDC9E66471847 +:10728000EF154986FCB5D54ABD65FAFA18EB8508B5 +:107290003A055F70AFF0F10371B81199B3E365BDC2 +:1072A0003C79104A7175791E44179C96D6D283C0DA +:1072B0003DBFC3D594682C097B8A83722196D9DAA5 +:1072C0008F101AFFCBDECCCA15EB56FDC67E895255 +:1072D0005E869687E6BAB1CD189095F2D88B947CED +:1072E000B746D0BE461849D11F7846882AEB0A1CFB +:1072F000A02F99EA0D81F743012847802E339FADD7 +:1073000041DB6552634488C2A80B4725D4D42017BB +:10731000B95B1F46539418AAFE3BCE9860F45DC239 +:10732000974FF53AEE6E5D3A9F9A894FDF0A78CE15 +:10733000160D838A222DEDCF96C1491221CAE41F72 +:10734000D917C015C484E14C66E972BB8B6920442F +:10735000A6E915FF02784B5B4A289A95C0E9A196E9 +:10736000536D4885F08BE4D1C124A1EAB7E90DCE75 +:10737000E4479B86D9892C930363DB5A931C969927 +:107380007B66C5BD649F351DECF2769764921267EB +:1073900030C7ADDEBC706DB3F0428428469B5535D6 +:1073A0009C7FA2BE6AD4E8AB6AB0157E76085EBD4B +:1073B0006B98E4419D3BC5704A548AF8CED3CECD3C +:1073C000EC02D4A0AF2756A15602D867DD4764600F +:1073D000DB5087574A6E2F4F019E7B2DC215ED4D16 +:1073E000BBF6B43E6EB2C9F38E57B8E55C4E9F4013 +:1073F0005EB4B43EBABA54321E6AD2E03389D99E22 +:107400005823EC4D2EF512B91EB8530184984957F4 +:107410000C76066743AA2D2063640B67482388A374 +:10742000489ACBE48023F5FEDA8CBA8D3979067E52 +:10743000A55270555D76CEA08D1DEDDE0C442DBBA2 +:10744000D8E50A220FDEB6447EE2A54D19E7F21513 +:107450007E2DB66576E693772497F8CE4E7C7595AB +:10746000F6E0AAC52400CD92B52617AAD678073231 +:10747000907417F115A2C8AEB6FBE9C50ACA9A18EE +:107480009CAD89DC3DD5CC1DFB5A1158E1941C36CE +:107490000861F0ACBF3A238893D8C0AF7202EB65A5 +:1074A000BD268C1881B92965316F63A1849D4F2D4C +:1074B000188E5F0BD43EC03AFBE08B2EA157C10162 +:1074C000E94ED8AD8CBE022FE5C3FF881DEF2078B2 +:1074D000DB301ED6009D235E10C02A8F255CBEA720 +:1074E000C479BC4A35376C3FB4991633E9B72C0AD6 +:1074F0005B07B288EFF54AF9073EBC2F020E500D2C +:10750000160DB8EBCB743F498E4732C4FC48330AA2 +:107510008C078C088238A411F7EA6CE20DE9CB697C +:107520002411D2B25C6B9334E6ADFB97657C966315 +:10753000BF587D48D27586DBC6588398F74429DF4B +:1075400042E26DF07C31687B978891EBEE788F2377 +:1075500032D8A43FFAAA5981401801577B6026DD32 +:10756000759035C88CC47F42847A3A8C81B6CBBC86 +:107570005BC319A4B55A7FA90B0D3C2DB3EDCA16F8 +:107580000D8D72542718DD0DC8E65BE3EAD1C6877E +:1075900021BE0CFC18FD33845917AD1D6F844DFDC1 +:1075A000E8C22BF4E1C69A4D129AF0A751559903FF +:1075B0005C01E6EF54C2557EFD3CBA3CC44A84C926 +:1075C000250A5FA5B9DD850A4D161D6EFC4C80E9C4 +:1075D000EDCAB45252E7F57A528B20346D1F3A7DD2 +:1075E00085EE651CEBF07D1E83086D3AC12E993F38 +:1075F000DAF8C52B0E2B33A2BA4460AA2D5D29FB05 +:107600004F0E5749616BBD6180B1C0CB0D81B21681 +:10761000D94AA07AC687B81E84555120DBF7892243 +:10762000CECD71350EE9B15CCEB5278A3F1BED8911 +:10763000C368A437BDBD5A4AE9730B773E8937AC9E +:107640001B9CABF2B2F77BED8CCCBDA24A27C5FDEB +:10765000AE1FC02DB1B5D1C9863F6F172D4DE7FCC8 +:107660005085D38EC2FF4B746B8015E9AF1665F859 +:10767000069AE2646A1A86B752073B9B171F0AB242 +:10768000A6EA71DBC4A36FBBC68D4F9865B06A00D4 +:107690004DE74DEF9DAF234F100F846234413EC93B +:1076A000E5F7A6C8B8C91B644D90E20BEA0CA33EEF +:1076B0004E58384867BB4710A4CA6B57C1B96D47CD +:1076C0006C6F42EFB15D7BB84E91F624ED9C8FD884 +:1076D00067F6CD4EE628BD0678688ED5749B149A61 +:1076E000FBE22FFE63BF76C511F55E0F8A37BE5CE5 +:1076F000C6B259F4C9FCE51978CE2C32AFBFEFB54C +:1077000089F12C90DAA5DB30726BAC179E7B494374 +:1077100048F5404F6A5D39E4E380B99EF07205CBCD +:1077200031A934D37A68A7DE584D1C49C256C55AD0 +:1077300089563A663958272B2EB722DC711D17342B +:10774000EA6C879722BE92612796CB7A47D7D35AA5 +:107750004F956B0E76B4783E037212671D244BA4CE +:107760007F357F23E7D9C22FCAD1267EACB1C7BCF3 +:10777000C8ED76B18E95491577F600F84E4004BDF8 +:1077800030647E1E7C7146DCCBE6287017BF956B9B +:10779000E6473C4A53D081C3809A09D858CF861512 +:1077A000193BA720085FEA6FCD3148462A6C7994CF +:1077B000004F811A90845FC8BF9391F9881F2B48AE +:1077C000AE5A9085EB61D6F70EA4A87B06FA6FB28D +:1077D000E6D3409470C30FF4037CF95CD5A5A73BB6 +:1077E0008E7ED9F8406780AD77CBF8D3C710D0280C +:1077F00088787AC5F36B8CD1183F719290E24F2153 +:107800009C04F56F581077EF6896C38E683FACCB39 +:10781000316071BC596A2F7FE4E42B738BA68CA472 +:107820009B525BD0112F7351B843027DFA8F16B172 +:107830001CB5BB3AF89BEF268FAA0CF0D8C35E1597 +:107840008177E51DD87D1CA717C45E2096EE708257 +:107850002861D49D8002FC8D7832C665BA7D667140 +:107860008C91DD8AD9E8C987018B7E73481A0B0594 +:10787000AD6C04D279C00620875AEDFA756915738C +:1078800066691A76BE89D3E0762349F4BE7E66CC5B +:107890001BA25EAB01D2D666D49299535D8C469002 +:1078A00001AF0BC3C8071F8A80A307A8187827F168 +:1078B00044C3B6B7488AFED4A049DED0AADAD6823D +:1078C0000FD2B6838EC6D23DB55EBBF702A2B8D545 +:1078D0009A9521D2CE412EA9FF885787643BB90AD9 +:1078E00082D7C11C63E1B2BFCC46D9E0B36CAE0F06 +:1078F000B9FAE01D6D8A631D74A692BAAAD2735FAD +:10790000E68598045DA37F3C9300DDD393119C39F9 +:107910005521A65419CAAA9CA0F872CE43E694B188 +:1079200052A766398148FBD1CDD2195CB1E7879562 +:107930004FED29F1CD6670667DAC705D4285275BA9 +:1079400063CF759A90C5E3AB243E841B037F658AA1 +:1079500015C9E76584FD9CD4496C58EF0786F81477 +:10796000B446C91F48DCC1CDE19D4DC321BFD5B888 +:107970006CE2E94815C33D40C5EB48AC846D5DB190 +:1079800083B4B890D4F3D75EBE0A7D70CE66062E5F +:107990007562A2D2E846FCA2AE83908607DBFE7435 +:1079A000F06FBFED1D7ECB437B3CA13EFC1313610A +:1079B000B4B9849828DFA24E1C4F50A03CA0D73603 +:1079C00092EDEA6E74A61099602C615E5FD13082F0 +:1079D000FA35FAC6E4EA5A1EF85AE51DED172532C3 +:1079E000BD36C920205F09CB0AE8721B02AB0073C9 +:1079F0007BDB807FDB62A95693EA94E36CCA913EFD +:107A00009D0DF0A180196562A5E03EEEE8AB4CB992 +:107A10004E1CE0297B93F789502ED2C0718365AE4E +:107A200005732E1AB53E3D141E70B71DF464E0BBFD +:107A30000BBE4FCEBBE8140255168F5652FDD490A4 +:107A40005B5CF220A270ABD3FC7647DA6368AAF7DE +:107A5000023CAABC7B4CE49C4BDF38053F1738FC4A +:107A6000043065935F37E66927B010E0661BD8C124 +:107A7000787972C8A8B0F30E58BF42E8ABFC17B6CD +:107A80008F56C3E195141434C775389E45C0616D97 +:107A90007B503145D34795DA358BDC9D0F6FD9E4A8 +:107AA0003EDE95F313303E5692BA2ACE7BF9489CBF +:107AB000B04ED3B53910054D8C1AC60343BF44638D +:107AC000244ABC31E532ABC6363DA0EA750A3CFA21 +:107AD00070949E3F162278CEB206B9F6ED3182EB55 +:107AE00029B119DA9337ACF709B7E952AAD0313086 +:107AF0009ADDE47E10526A55E9442DBA48A7B4B91C +:107B000013831DD2A479BD6EC815FFB557E1175771 +:107B1000841276A2F73DD46BEF2A533539B005377E +:107B2000F6C15FC912C1937B01F649E4123F1EAB57 +:107B3000A1348416B72F87F94125F7575F9DFA279F +:107B400098659BE6001FA56EC54A549026921C0DB1 +:107B500075F5D47B3719F41F1A643B0019DF2F8F9A +:107B6000AF1F493A3784196E539E08E3BEB3A90E7E +:107B7000F56CF9C46A615D86E4C16AEBD53F59EFE3 +:107B8000A41294A9FDBEC0F7AB88606FBD5713B1B6 +:107B9000F710357D1D28D8CE7911D6376F1B200FF1 +:107BA000E4E9F477A9C61F6FE15604D00593C3D06A +:107BB000CF7131D148107F300735B6B5696572E9AC +:107BC000AEEA57AC7C4AF69EE2EF9B32838242518A +:107BD0008062B72A6673EFFE2A046265CA6FEE6B95 +:107BE0004C59A4FAAFE612985E4A6C3C9D79BB3BB7 +:107BF000392693D4800BBA395C4CA175882F6EB7A7 +:107C0000A16189E3ABD4D8E602907BDCA1F943EB18 +:107C1000FE000E61A7B312C038832E79D8ACB4CC65 +:107C2000FFD0BB1F54728A68B85AA17B8A0F960690 +:107C30006142D5747BB866FA8EE1B3B5211779C27B +:107C40004A4FD9C097F8D1958D200EC2ADEC3DB802 +:107C500051628D97F1626652659EC082A8C53A75E1 +:107C6000F5ECF5B0B89C9CAAC4D5B0662ECB0596B1 +:107C70004931DF013F4F1E0771472E09060C3AD0EC +:107C80007A734BD8F03C426FDD6BDC0BF3E7559019 +:107C90005385122F16832CB59EF47CA16CCF1E7BCE +:107CA000752A89C0D1F864924237E79AF61F466771 +:107CB00088E87893799C47678729735AEEA6B35F63 +:107CC000CFF224253FEC68E9288DF5C4B3045CF9B4 +:107CD000DE425192002611838907E6F8E3F8A67B7D +:107CE000A7AB759326013142302EAC9B4BF511DBCF +:107CF000AA945F8ED74816DC2F08314DE4B1593273 +:107D0000DFAB328F775335B5E03A120B176E9B6AB3 +:107D1000E08C414738E83714B9BC24F8AA365E8AAB +:107D2000DE8886EB4BDDE1EA0ADCE17C0255F1E11D +:107D3000F35CEF474190FBD7C82D412D80309D8FDC +:107D400088493E581D92B53E28EFF0818D9D5D2EED +:107D500052FEC20AB78AAFEDDD506FED2280783E49 +:107D6000332E28F3F915F772A4B1407604A6D7F59F +:107D70009887649E4D6CEA010C6AAF890F2A35A67C +:107D8000D3C9CF776154EC782A5D95AAA3FBDAFAC0 +:107D90000CD738FB9C5102734F9281D469A864C7F9 +:107DA000834FECA68C28B5595668747B47E56DB0B7 +:107DB0007326BAB6010A86BB307EAC949C5AB67262 +:107DC0005302A74D31F7D7E7C7D0602D135CBBB482 +:107DD000E5392919F2CBBC58C0CF729EA99A440349 +:107DE00066153EF8C4E98F10B3D009B8B8DDF810B5 +:107DF00073279310EC1B443CE468A80FD1E1C24AFE +:107E000035A1DFFFFC9D40E3B2B0FCD0BAA299C21D +:107E1000E2E3EE5369BA3E91DEB1540D8FA059D61C +:107E2000B3015930FB42E18CE5D315B5E8FEDBF434 +:107E30009B4033C0120AFA51720B746706B905638E +:107E400088004AE96AF9D1E1DF040EB3DACD5D7B3F +:107E5000BCF4E5800AA1ED40CDA42EF5062A0B0462 +:107E600059B4E01F658344F1801B43D9194B63402B +:107E7000799E9E2C031CE979D4D454D5E062D2E3D8 +:107E8000A2E347839100D473C49548DEF2B61FCDB8 +:107E9000DC1FF2D64B47E5AA6E4C2196A0AFDF80DF +:107EA0001DC2AFF3C311FEE7016E20798F10EF6C96 +:107EB000A2334E68F2897A6AA38A9B3910D7E16DA2 +:107EC000EFEECF7C11062E51FD1D0C02BE05ECE03D +:107ED000A202DDE7A5EBDC26B71EB0116DE1A41B05 +:107EE0005EBFB261E6FC9D87F3F91B0D008981AB93 +:107EF0000C133FF84C3BA4C853867BC95C36027C0C +:107F0000A4F5967A11CC82C2A584ADF04805173449 +:107F100083313400A60D066A2B60717600B7FF37F7 +:107F20001D5457BD044B073C982CE4F0CD4BF23068 +:107F3000E625924099EB1FD9E6BC3D800EDC96AE5B +:107F4000439EC37DB22227F1F4D26238B4D13668A1 +:107F50002D82A5567C1C59FAE7A09A1BC8EDB2C128 +:107F60006CC50098B92C1A13376204C59D4A7BF77B +:107F7000E38FE3D1B4F4B13135AD6690C67676586F +:107F80007DC6559033DD0DDCE19DF2DC83743983D1 +:107F900093EDCD32FF418A63C014D5C32A2B7EE70F +:107FA0006EA4EA1F0AC427D748C18E61CAD444749C +:107FB000E2F98B0D0B2F59CD6BD567C76BFF52893B +:107FC000D47450B7DD43D76C76A4DEA57CF2D91DFE +:107FD000CE002A2984F4DE4BA0C3912A653CDC5BE9 +:107FE00071F85090865F4C15A411F38F31DA70E26E +:107FF000A93E984F02FA8042FE5BC9C98031C3C4D2 +:108000004E7CA21E0EFCCE321C19057BB157D6FB4E +:10801000CA6BB4E73D64AF0575A97A04F992FA6CAE +:10802000676376C32CF79101F03CB19F4AFDD93AC2 +:10803000BB86161DA341FC00FFD150DB84A8D89C51 +:10804000A2113E175D2D332F8491125DBA823BD56C +:108050000B6012CABCDF69CB1547F9D27EFF2D5EDB +:108060007CB2407C103A91BA5E6C30839E35129F90 +:10807000DE08F3C90F424CE4D302708A253CC09855 +:1080800027E87C7C103DB698885EB5577E82014912 +:1080900007E9B35740F1E2A7E8D5B5DBE5A407400F +:1080A000A7C7E44B71CD3EC5B4AA3C136F11F77856 +:1080B000C053BE7E43F6360550BB7E3065C8628332 +:1080C00084DF458E846E98BA14974E2672A14500BF +:1080D000EA4D603DC364AFA068FB36671DACD9288C +:1080E000DFCD8EF8072F6AB25EF7762FB8B80A2F69 +:1080F00011A6700E2B14BF397FF6AF9D2D10BD5504 +:1081000063AC83878D15FAEC116E44D4131B5D8725 +:10811000163FDB3F1AE3451F2E08CF8E8E0F6C0DE6 +:10812000D8A84844C308FE8062F16C63D5C5480AEC +:10813000C9218957B16DA48281AFC155316B177BBD +:10814000FFFFFFFF11000000000000000000000022 +:10815000000000000000000000010000608101003C +:10816000000000000000000000000000000000000F +:1081700000000000000000000000000000000000FF +:1081800000000000000000000000000000000000EF +:1081900000000000000000000000000000000000DF +:1081A00000000000000000000000000000000000CF +:1081B00000000000000000000000000000000000BF +:1081C00000000000000000000000000000000000AF +:1081D000000000000000000000000000000000009F +:1081E000000000000000000000000000000000008F +:1081F000000000000000000000000000000000007F +:10820000000000000000000000000000000000006E +:10821000000000000000000000000000000000005E +:10822000000000000000000000000000000000004E +:10823000000000000000000000000000000000003E +:10824000000000000000000000000000000000002E +:10825000000000000000000000000000000000001E +:108260002A0454080E000000000000000000000076 +:1082700000000000000000001000000080820100EB +:10828000400026002000000000002000A600DE02C2 +:10829000BC686E70030000000000000000000000D9 +:1082A000000000000000000010000000B08201008B +:1082B000080400001061010040810100608201009B +:1082C000B641A3D309000000000000000000000038 +:1082D000000000000000000010000000E08201002B +:1082E00049324300FF00FF000C0D20000000000099 +:1082F000B641A3D30A000000000000000000000007 +:1083000000000000000000001000000010830100C9 +:1083100049324300FF00FF000C0D20000000000068 +:108320006C3AAB2F100000000000000000000000BD +:108330000000000000000000000100004083010078 +:1083400034373201D2003401000000000000000088 +:10835000000000000000000000000000000000001D +:10836000000000000000000000000000000000000D +:1083700000000000000000000000000000000000FD +:1083800000000000000000000000000000000000ED +:1083900000000000000000000000000000000000DD +:1083A00000000000000000000000000000000000CD +:1083B00000000000000000000000000000000000BD +:1083C00000000000000000000000000000000000AD +:1083D000000000000000000000000000000000009D +:1083E000000000000000000000000000000000008D +:1083F000000000000000000000000000000000007D +:10840000000000000000000000000000000000006C +:10841000000000000000000000000000000000005C +:10842000000000000000000000000000000000004C +:10843000000000000000000000000000000000003C +:108440008109CCA919000000000000000000000014 +:1084500000000000000000004A01000060840100EC +:10846000A328F3F100304B1EB6235ADD1F913903C8 +:10847000323031372D30352D323330343A31363ACF +:10848000303553594E41000000000000000000004C +:1084900000000000000000000000000000000000DC +:1084A00000000000000000000000000000000000CC +:1084B00000000000000000000000000000000000BC +:1084C00000000000000000000000000000000000AC +:1084D000000000000000000000000000000000009C +:1084E000000000000000000000000000000000008C +:1084F000000000000000000000000000000000007C +:108500000000556E2D74756E656420626173652080 +:10851000696D616765000000000000000000000058 +:10852000000000000000000000000000000000004B +:10853000000000000000000000000000000000003B +:10854000000000000000000000000000000000002B +:10855000000000000000000000000000000000001B +:10856000000000000000000000000000000000000B +:1085700000000000000000000000000000000000FB +:108580000000696D616765636F6E76657274657210 +:108590000000312E352E362E300000000000000085 +:1085A000000000009B55004F00010000000000008B +:1085B0004184820818000000000000000000000054 +:1085C000000000000000000004000000D085010051 +:1085D00040840100000000000000000000000000D6 +:1085E000FAF67B0D0C000000000000000000000007 +:1085F00000000000000000001904000000860100D7 +:108600000001000100020002000100010001000160 +:1086100000500001000500020020000100010001DF +:108620000001000100010001000F001900140013F7 +:108630000007000B00030004000300010007000115 +:10864000001E0010000800040001000100020004E8 +:108650000005000200020002000400010001000108 +:108660000001000100010001000100010001000102 +:1086700000010001000100010001000100010001F2 +:1086800000010001000100010001000100010001E2 +:10869000001000100001001000010001000300267E +:1086A0000001000A0023000100050009000200008B +:1086B00000000000000000000000000000000000BA +:1086C00000000000000000000000000000000000AA +:1086D000000000000000000000000000000000009A +:1086E000000000000000000000000000000000008A +:1086F000000000000000000000000000000000007A +:108700000000000000000000000000000000000069 +:108710000000000000000000000000000000000059 +:108720000000000000000000000000000000000049 +:108730000000000000000000000000000000000039 +:108740000000000000000000000000000000000029 +:108750000000000000000000000000000000000019 +:108760000000000000000000000000000000000009 +:1087700000000000000000000000000000000000F9 +:1087800000000000000000000000000000000000E9 +:1087900000000000000000000000000000000000D9 +:1087A00000000000000000000000000000000000C9 +:1087B00000000000000000000000000100010001B6 +:1087C00000010001000100010001000100010001A1 +:1087D0000001000100010001000100010001000191 +:1087E0000000000000000000000000000000000089 +:1087F0000000000000000000000000000000000178 +:108800000000000000000000000000000000000068 +:108810000000000000000000000000000000000058 +:108820000000000000000000000000000000000048 +:108830000000000000000000000000000000000038 +:108840000000000000000000000000000000000028 +:108850000000000000000000000000000000000018 +:108860000000000000000000000000000000000008 +:1088700000000000000000000000000000000000F8 +:10888000000000047F031E05510EB409E805675679 +:108890006756000000001C10011E0500401E052840 +:1088A00030003000F0D2F0D2250D058C00E0B1E0B0 +:1088B000B140122D80080A20001A5C0F0801CC4C30 +:1088C00046004C00CC8C01012626808000000380ED +:1088D000030C0600200F0128008013008033315064 +:1088E000000000004C046C073C3200000000000057 +:1088F0000000FF0A00000114030C0F0A00FF000132 +:1089000000008C00000000002C012C011000100061 +:10891000C800C8006666881300002605FFFFFFFF39 +:10892000FFFFFFFFFFFFFFFFFFFFFFFF3A1E0014E7 +:10893000002228040150500A000804083497270038 +:108940000210002000FA1506008102FE010000015D +:10895000E00100FFFFFFFFFFFFFF533336303352CC +:1089600000000000A9030F04030000000000000045 +:1089700000000000000000000000000000000000F7 +:108980000000000000000000000008FFFFFFFFFFE4 +:10899000FFFFFFFFFFFFFFFFFFFFFF010326FF07B2 +:1089A00001010101030326FF8F0001010A03238057 +:1089B0009ED2E6E180808080C00101010503099616 +:1089C0008082800002030A23008FD41C060000006E +:1089D000600F1F19C713143F13490783020B81044B +:1089E0000303040503070101072301011E1F1001F2 +:1089F0000801040105091680000050FF0701010568 +:108A000003020120004C00140801122D240D060160 +:108A10000125000C004134000000000000000000AF +:108A20009EE52B8B0C000000000000000000000001 +:108A30000000000000000000AE030000408A0100BA +:108A4000010100010001000100010001000100011D +:108A50000001000200020002000100040001000108 +:108A600000010001000100010001000100010001FE +:108A700000010001000100010001000100010001EE +:108A80000001000100010001000100010001000DD2 +:108A9000000200020058001C000300010005000253 +:108AA000000A00080001000100010002000D0001A1 +:108AB0000001000B00340005000200060001003F29 +:108AC000000300010001000100010001000100019C +:108AD000000100010001000100010001000100018E +:108AE000000100010001000100010001000100017E +:108AF000000100010001000100010001000100016E +:108B0000000100010001000100010001000100015D +:108B1000000100010001000100010001000100014D +:108B20000001000100010001000000000000000041 +:108B30000000000000000000000000000000000035 +:108B40000000000000000000000000000000000025 +:108B50000000000000000000000000000000000015 +:108B60000000000000000000000000000000000005 +:108B700000000000000000000000000000000000F5 +:108B800000000000000000000000000000000000E5 +:108B900000000000000000000000000000000000D5 +:108BA00000000000000000000000000000000000C5 +:108BB00000000000000000000000000000000000B5 +:108BC00000000000000000000000000000000000A5 +:108BD0000000000000000000000000000000000095 +:108BE0000000000000000000000000000000000085 +:108BF0000000000000000000000000000000000075 +:108C00000000000000000000000000000000000064 +:108C1000000000010001000100010001000100014D +:108C20000000000000000000000000000000000044 +:108C30000000000000000000000000000000000133 +:108C40000000000000000000000000000000000024 +:108C50000000000000000B0180041B0000FF5E000C +:108C6000FFFFBF96FA0000C08004100A10000D0834 +:108C700000006E00010000FFFFFFFF6E0001040511 +:108C800040000F00000000000000053F000F000141 +:108C90000000000000053E000F0002000000000080 +:108CA000053D000F00030000000000053C000F0020 +:108CB000040000000000053A000F0006000000005C +:108CC000000539000F000800000000000537000F04 +:108CD000000A00000000000E0E0E0E0E0E0E0E0E0C +:108CE0000E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0EA4 +:108CF0000E0E0E24000300A60014640210000200F1 +:108D00000808A000A0005050000000000000000073 +:108D10001E0180040432003205003F0F00050000F0 +:108D2000000000000108000000000000001E2800F4 +:108D30000000010A000100808080808080808080A7 +:108D40008080808080808080808080808080808023 +:108D50008080808080808080808080808080808013 +:108D6000808080000000000001000F03030F030358 +:108D700014000000F03F00FF1F0000000000000092 +:108D8000000000000000000000000000000A0D0EBE +:108D9000000500000000C00200000000000000000C +:108DA00000000000000000050808050A0A00000095 +:108DB0000F030300001C1044502D04013A001C3422 +:108DC0004088E0E8FB080C5848028890C0809480F6 +:108DD00010E6048580808084808180C0808080C08F +:108DE000D4808080800543420E00015400000000C2 +:108DF00053F7B1380C000000000000000000000034 +:108E0000000000000000000025020000108E01009C +:108E10000201000100010001000100010001000148 +:108E2000000100010001000100010001000100013A +:108E3000000100010001000100010001000100012A +:108E4000000100010001000100000000000000001E +:108E50000000000000000000000000000000000012 +:108E60000000000000000000000000000000000002 +:108E700000000000000000000000000000000000F2 +:108E800000000000000000000000000000000000E2 +:108E900000000000000000000000000000000000D2 +:108EA00000000000000000000000000000000000C2 +:108EB00000000000000000000000000000000000B2 +:108EC00000000000000000000000000000000000A2 +:108ED0000000000000000000000000000000000092 +:108EE0000000000000000000000000000000000082 +:108EF0000000000000000000000000000000000072 +:108F00000000000000000000000000000000000061 +:108F10000000000000000000000000000000000051 +:108F20000000000000000000000000000000000041 +:108F30000000000000000000000000000000000031 +:108F40000000000000000000000000000000000021 +:108F50000000000000000000000000000000000011 +:108F60000000000000000000000000000000000001 +:108F700000000000000000000000000000000000F1 +:108F800000000000000000000000000000000000E1 +:108F900000000000000000000000000000000000D1 +:108FA00000000000000000000000000000000000C1 +:108FB00000000000000000000000000000000000B1 +:108FC00000000000000000000000000000000000A1 +:108FD0000000000000000000000000000000000091 +:108FE000000000010001000100010001000100017A +:108FF0000000000000000000000000000000000071 +:10900000000000000000000000000000000000015F +:109010000000000000FFFFFFFFFFFFFFFF51515165 +:1090200051CD0D0410101010612483FF821900012E +:1090300000011A0000000000000000000000000015 +:1090400018E5C9480C000000000000000000000006 +:1090500000000000000000007402000060900100A9 +:109060000301001C0010001C0010000A0001000198 +:1090700000010001000100010001000100000000EA +:1090800000000000000000000000000000000000E0 +:1090900000000000000000000000000000000000D0 +:1090A00000000000000000000000000000000000C0 +:1090B00000000000000000000000000000000000B0 +:1090C00000000000000000000000000000000000A0 +:1090D0000000000000000000000000000000000090 +:1090E0000000000000000000000000000000000080 +:1090F0000000000000000000000000000000000070 +:10910000000000000000000000000000000000005F +:10911000000000000000000000000000000000004F +:10912000000000000000000000000000000000003F +:10913000000000000000000000000000000000002F +:10914000000000000000000000000000000000001F +:10915000000000000000000000000000000000000F +:1091600000000000000000000000000000000000FF +:1091700000000000000000000000000000000000EF +:1091800000000000000000000000000000000000DF +:1091900000000000000000000000000000000000CF +:1091A00000000000000000000000000000000000BF +:1091B00000000000000000000000000000000000AF +:1091C000000000000000000000000000000000009F +:1091D000000000000000000000000000000000008F +:1091E000000000000000000000000000000000007F +:1091F000000000000000000000000000000000006F +:10920000000000000000000000000000000000005E +:10921000000000000000000000000000000000004E +:10922000000000000000000000000000000000003E +:109230000000000100010001000100010001000127 +:10924000000000000000000000000000000000001E +:10925000000000000000000000000000000000010D +:10926000000125242223211F201E1D1C00010204B1 +:109270000305070608090A0C0B0D262728290F0EDF +:10928000101112141315161817191A1B282980808B +:1092900080808080808080808080808080808080CE +:1092A00080808080808080808080808080808080BE +:1092B000808080808080808080800000FFFFFFFFB2 +:1092C000FFFFFFFF001C1089A0808004070600003C +:1092D0000155000000000000000000000000000038 +:1092E00025676ACE0C0000000000000000000000AE +:1092F00000000000000000001002000000930100C8 +:109300000401000100010001000100010001000052 +:10931000000000000000000000000000000000004D +:10932000000000000000000000000000000000003D +:10933000000000000000000000000000000000002D +:10934000000000000000000000000000000000001D +:10935000000000000000000000000000000000000D +:1093600000000000000000000000000000000000FD +:1093700000000000000000000000000000000000ED +:1093800000000000000000000000000000000000DD +:1093900000000000000000000000000000000000CD +:1093A00000000000000000000000000000000000BD +:1093B00000000000000000000000000000000000AD +:1093C000000000000000000000000000000000009D +:1093D000000000000000000000000000000000008D +:1093E000000000000000000000000000000000007D +:1093F000000000000000000000000000000000006D +:10940000000000000000000000000000000000005C +:10941000000000000000000000000000000000004C +:10942000000000000000000000000000000000003C +:10943000000000000000000000000000000000002C +:10944000000000000000000000000000000000001C +:10945000000000000000000000000000000000000C +:1094600000000000000000000000000000000000FC +:1094700000000000000000000000000000000000EC +:1094800000000000000000000000000000000000DC +:1094900000000000000000000000000000000000CC +:1094A00000000000000000000000000000000000BC +:1094B00000000000000000000000000000000000AC +:1094C000000000000000000000000000000000009C +:1094D0000000000100010001000100010001000185 +:1094E000000000000000000000000000000000007C +:1094F000000000000000000000000000000000016B +:1095000000070000000000000000000021510000E2 +:109510005C0303840C000000000000000000000059 +:1095200000000000000000009E02000030950100D5 +:1095300080010001000100010001000100010001A3 +:109540000001000100010001000100010001000113 +:109550000001000100010001000100010001000103 +:1095600000010001000100010001000100010001F3 +:1095700000010001000100010001000100010001E3 +:1095800000010001000100010001000100010001D3 +:1095900000010001000100010001000100010001C3 +:1095A00000010001000100010001000100010001B3 +:1095B00000010001000100010001000100010001A3 +:1095C0000001000100010001000100010001000193 +:1095D0000001000100010001000100010001000183 +:1095E0000001000100010001000100010001000173 +:1095F0000001000100010001000100010001000163 +:109600000001000100010001000100010001000152 +:109610000001000100010001000100010001000142 +:109620000001000100010001000100010001000132 +:109630000001000100010001000100010001000122 +:109640000001000100010001000100010001000112 +:109650000001000100010001000100010000000004 +:1096600000000000000000000000000000000000FA +:1096700000000000000000000000000000000000EA +:1096800000000000000000000000000000000000DA +:1096900000000000000000000000000000000000CA +:1096A00000000000000000000000000000000000BA +:1096B00000000000000000000000000000000000AA +:1096C000000000000000000000000000000000009A +:1096D000000000000000000000000000000000008A +:1096E000000000000000000000000000000000007A +:1096F000000000000000000000000000000000006A +:109700000000000100010001000100010001000152 +:109710000000000000000000000000000000000049 +:109720000000000000000000000000000000000039 +:109730000000000000000000000000000000000029 +:109740000000000000000000000000000000000019 +:109750000000000000000000000000000000000009 +:1097600000000000000000000000000000000000F9 +:1097700000000000000000000000000000000000E9 +:1097800000000000000000000000000000000000D9 +:1097900000000000000000000000000000000000C9 +:1097A00000000000000000000000000000000000B9 +:1097B00000000000349727A328F3F100304B1EB6B9 +:1097C000235ADD1F91390382000000008100000050 +:1097D00029569AF20B000000000000000000000073 +:1097E000000000000000000018000000F0970100D9 +:1097F000E0850100208A0100F08D01004090010009 +:10980000E09201001095010000000000000000003F +:00000001FF diff --git a/include/linux/input/synaptics_dsx.h b/include/linux/input/synaptics_dsx.h index 976b4bf48b653..fc16d8d94f5b5 100644 --- a/include/linux/input/synaptics_dsx.h +++ b/include/linux/input/synaptics_dsx.h @@ -1,11 +1,10 @@ /* - * Synaptics RMI4 touchscreen driver + * Synaptics DSX touchscreen driver * - * Copyright (C) 2012 Synaptics Incorporated + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. * * Copyright (C) 2012 Alexandra Chin * Copyright (C) 2012 Scott Lin - * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,73 +13,103 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. */ #ifndef _SYNAPTICS_DSX_H_ #define _SYNAPTICS_DSX_H_ +#define PLATFORM_DRIVER_NAME "synaptics_dsx_v21" +#define STYLUS_DRIVER_NAME "synaptics_dsx_stylus" +#define ACTIVE_PEN_DRIVER_NAME "synaptics_dsx_active_pen" +#define PROXIMITY_DRIVER_NAME "synaptics_dsx_proximity" +#define GESTURE_DRIVER_NAME "synaptics_dsx_gesture" +#define I2C_DRIVER_NAME "synaptics_dsx_i2c" +#define SPI_DRIVER_NAME "synaptics_dsx_spi" + /* - * struct synaptics_rmi4_capacitance_button_map - 0d button map + * struct synaptics_dsx_button_map - button map * @nbuttons: number of buttons - * @map: button map + * @map: pointer to array of button codes */ -struct synaptics_rmi4_capacitance_button_map { +struct synaptics_dsx_button_map { unsigned char nbuttons; - unsigned char *map; + unsigned int *map; }; /* - * struct synaptics_rmi4_platform_data - rmi4 platform data + * struct synaptics_dsx_board_data - DSX board data * @x_flip: x flip flag * @y_flip: y flip flag - * @i2c_pull_up: pull up i2c bus with regulator - * @power_down_enable: enable complete regulator shutdown in suspend - * @irq_gpio: attention interrupt gpio - * @irq_flags: flags used by the irq - * @reset_flags: flags used by reset line - * @reset_gpio: reset gpio - * @panel_x: panel maximum values on the x - * @panel_y: panel maximum values on the y - * @disp_maxx: display panel maximum values on the x - * @disp_maxy: display panel maximum values on the y - * @disp_minx: display panel minimum values on the x - * @disp_miny: display panel minimum values on the y - * @panel_maxx: touch panel maximum values on the x - * @panel_maxy: touch panel maximum values on the y - * @panel_minx: touch panel minimum values on the x - * @panel_miny: touch panel minimum values on the y - * @reset_delay: reset delay - * @gpio_config: pointer to gpio configuration function - * @capacitance_button_map: pointer to 0d button map + * @swap_axes: swap axes flag + * @irq_gpio: attention interrupt GPIO + * @irq_on_state: attention interrupt active state + * @power_gpio: power switch GPIO + * @power_on_state: power switch active state + * @reset_gpio: reset GPIO + * @reset_on_state: reset active state + * @max_y_for_2d: maximum y value for 2D area when virtual buttons are present + * @irq_flags: IRQ flags + * @i2c_addr: I2C slave address + * @ub_i2c_addr: microbootloader mode I2C slave address + * @device_descriptor_addr: HID device descriptor address + * @panel_x: x-axis resolution of display panel + * @panel_y: y-axis resolution of display panel + * @power_delay_ms: delay time to wait after powering up device + * @reset_delay_ms: delay time to wait after resetting device + * @reset_active_ms: reset active time + * @byte_delay_us: delay time between two bytes of SPI data + * @block_delay_us: delay time between two SPI transfers + * @addr_delay_us: delay time after sending address word + * @pwr_reg_name: pointer to name of regulator for power control + * @bus_reg_name: pointer to name of regulator for bus pullup control + * @cap_button_map: pointer to 0D button map + * @vir_button_map: pointer to virtual button map */ -struct synaptics_rmi4_platform_data { +struct synaptics_dsx_board_data { bool x_flip; bool y_flip; - bool i2c_pull_up; - bool power_down_enable; - bool disable_gpios; - bool do_lockdown; - bool detect_device; - bool modify_reso; - unsigned irq_gpio; - u32 irq_flags; - u32 reset_flags; - unsigned reset_gpio; - unsigned panel_minx; - unsigned panel_miny; - unsigned panel_maxx; - unsigned panel_maxy; - unsigned disp_minx; - unsigned disp_miny; - unsigned disp_maxx; - unsigned disp_maxy; - unsigned reset_delay; - const char *fw_image_name; - unsigned int package_id; - int (*gpio_config)(unsigned gpio, bool configure); - struct synaptics_rmi4_capacitance_button_map *capacitance_button_map; + bool swap_axes; + int irq; + int irq_gpio; + int irq_on_state; + int power_gpio; + int power_on_state; + int reset_gpio; + int reset_on_state; + int display_reset_gpio; + int max_y_for_2d; + unsigned long irq_flags; + unsigned short i2c_addr; + unsigned short ub_i2c_addr; + unsigned short device_descriptor_addr; + unsigned int panel_x; + unsigned int panel_y; + unsigned int power_delay_ms; + unsigned int reset_delay_ms; + unsigned int reset_active_ms; + unsigned int byte_delay_us; + unsigned int block_delay_us; + unsigned int addr_delay_us; + const char *pwr_reg_name; + const char *bus_reg_name; + struct synaptics_dsx_button_map *cap_button_map; + struct synaptics_dsx_button_map *vir_button_map; }; #endif From dff5d61fe65c253d8bba5395b674fcd97f305997 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Fri, 29 Dec 2017 19:55:26 +0530 Subject: [PATCH 205/508] drivers: media: rc : Import mido lirc drivers --- drivers/media/rc/Kconfig | 29 ++ drivers/media/rc/Makefile | 3 + drivers/media/rc/gpio-ir.c | 762 +++++++++++++++++++++++++++++ drivers/media/rc/ir-dump-decoder.c | 86 ++++ drivers/media/rc/ir-lirc-codec.c | 49 ++ drivers/media/rc/lirc_dev.c | 4 + drivers/media/rc/pwm-ir.c | 391 +++++++++++++++ drivers/media/rc/rc-ir-raw.c | 16 + drivers/media/rc/rc-main.c | 23 + include/media/gpio-ir.h | 34 ++ include/media/pwm-ir.h | 25 + include/media/rc-core.h | 5 + 12 files changed, 1427 insertions(+) create mode 100644 drivers/media/rc/gpio-ir.c create mode 100644 drivers/media/rc/ir-dump-decoder.c create mode 100644 drivers/media/rc/pwm-ir.c create mode 100644 include/media/gpio-ir.h create mode 100644 include/media/pwm-ir.h diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 8ce08107a69d5..bcb52980556dc 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -123,6 +123,16 @@ config IR_XMP_DECODER ---help--- Enable this option if you have IR with XMP protocol, and if the IR is decoded in software + +config IR_DUMP_DECODER + tristate "Enable IR dump decoder for debugging purpose" + depends on RC_CORE + default n + + ---help--- + Enable this option if you have an infrared remote control which + you want to dump the IR signal. + endif #RC_DECODERS menuconfig RC_DEVICES @@ -341,6 +351,25 @@ config IR_GPIO_CIR To compile this driver as a module, choose M here: the module will be called gpio-ir-recv. + +config IR_GPIO + tristate "GPIO IR remote control" + depends on RC_CORE + ---help--- + Say Y if you want to use GPIO based IR. + + To compile this driver as a module, choose M here: the module will + be called gpio-ir. + +config IR_PWM + tristate "PWM IR remote control" + depends on RC_CORE + ---help--- + Say Y if you want to use PWM based IR. + + To compile this driver as a module, choose M here: the module will + be called pwm-ir. + config RC_ST tristate "ST remote control receiver" depends on RC_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 0989f940e9cfa..5b6e32aa6dc6b 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -14,6 +14,9 @@ obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-decoder.o obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o obj-$(CONFIG_IR_XMP_DECODER) += ir-xmp-decoder.o +obj-$(CONFIG_IR_DUMP_DECODER) += ir-dump-decoder.o +obj-$(CONFIG_IR_GPIO) += gpio-ir.o +obj-$(CONFIG_IR_PWM) += pwm-ir.o # stand-alone IR receivers/transmitters obj-$(CONFIG_RC_ATI_REMOTE) += ati_remote.o diff --git a/drivers/media/rc/gpio-ir.c b/drivers/media/rc/gpio-ir.c new file mode 100644 index 0000000000000..82e591d229079 --- /dev/null +++ b/drivers/media/rc/gpio-ir.c @@ -0,0 +1,762 @@ +/* Copyright (C) 2012 by Xiang Xiao + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct gpio_ir_dev { + struct mutex lock; + struct platform_device *pdev; + struct rc_dev *rdev; + struct regulator *tx_reg; + u32 tx_carrier; + u32 tx_duty_cycle; + struct regulator *rx_reg; + struct hrtimer rx_timer; + ktime_t rx_carrier_last; + u32 rx_carrier_count; + bool rx_carrier_report; +}; + +struct gpio_ir_tx_packet { + struct completion done; + struct hrtimer timer; + unsigned int gpio_nr; + bool high_active; + u32 pulse; + u32 space; + bool abort; + unsigned int *buffer; + unsigned int length; + unsigned int next; + bool on; +}; + +#define GPIO_IR_TX_NAME (GPIO_IR_NAME "-tx") +#define GPIO_IR_RX_NAME (GPIO_IR_NAME "-rx") + +#define GPIO_IR_MIN_CARRIER_HZ 10000 +#define GPIO_IR_DEF_CARRIER_HZ 38000 + +#define GPIO_IR_DEF_CARRIER_NS (NSEC_PER_SEC / GPIO_IR_DEF_CARRIER_HZ) +#define GPIO_IR_MAX_CARRIER_NS (NSEC_PER_SEC / GPIO_IR_MIN_CARRIER_HZ) + +/* code for open and close */ +static int gpio_ir_rx_enable(struct gpio_ir_dev *gdev) +{ + struct gpio_ir_data *gdata = gdev->pdev->dev.platform_data; + int rc = 0; + + if (gdev->rx_reg) + rc = regulator_enable(gdev->rx_reg); + if (rc == 0 && gpio_is_valid(gdata->rx_gpio_nr)) + enable_irq(gpio_to_irq(gdata->rx_gpio_nr)); + + return rc; +} + +static void gpio_ir_rx_disable(struct gpio_ir_dev *gdev) +{ + struct gpio_ir_data *gdata = gdev->pdev->dev.platform_data; + + if (gpio_is_valid(gdata->rx_gpio_nr)) + disable_irq(gpio_to_irq(gdata->rx_gpio_nr)); + hrtimer_cancel(&gdev->rx_timer); + if (gdev->rx_reg) + regulator_disable(gdev->rx_reg); +} + +static int gpio_ir_open(struct rc_dev *rdev) +{ + struct gpio_ir_dev *gdev = rdev->priv; + int rc = 0; + + mutex_lock(&gdev->lock); + rc = gpio_ir_rx_enable(gdev); + mutex_unlock(&gdev->lock); + + return rc; +} + +static void gpio_ir_close(struct rc_dev *rdev) +{ + struct gpio_ir_dev *gdev = rdev->priv; + + mutex_lock(&gdev->lock); + gpio_ir_rx_disable(gdev); + mutex_unlock(&gdev->lock); +} + +/* code for ir transmit */ +static int gpio_ir_tx_carrier(struct rc_dev *rdev, u32 carrier) +{ + struct gpio_ir_dev *gdev = rdev->priv; + + mutex_lock(&gdev->lock); + gdev->tx_carrier = carrier; + mutex_unlock(&gdev->lock); + + return 0; +} + +static int gpio_ir_tx_duty_cycle(struct rc_dev *rdev, u32 duty_cycle) +{ + struct gpio_ir_dev *gdev = rdev->priv; + + mutex_lock(&gdev->lock); + gdev->tx_duty_cycle = duty_cycle; + mutex_unlock(&gdev->lock); + + return 0; +} + +static void gpio_ir_tx_set(struct gpio_ir_tx_packet *gpkt, bool on) +{ + if (gpkt->high_active) + gpio_set_value(gpkt->gpio_nr, on); + else + gpio_set_value(gpkt->gpio_nr, !on); +} + +static enum hrtimer_restart gpio_ir_tx_timer(struct hrtimer *timer) +{ + struct gpio_ir_tx_packet *gpkt = container_of(timer, struct gpio_ir_tx_packet, timer); + enum hrtimer_restart restart = HRTIMER_RESTART; + + if (!gpkt->abort && gpkt->next < gpkt->length) { + if (gpkt->next & 0x01) { /* space */ + gpio_ir_tx_set(gpkt, false); + + hrtimer_forward_now(&gpkt->timer, + ns_to_ktime(gpkt->buffer[gpkt->next++])); + } else if (!gpkt->pulse || !gpkt->space) { + gpio_ir_tx_set(gpkt, true); + + hrtimer_forward_now(&gpkt->timer, + ns_to_ktime(gpkt->buffer[gpkt->next++])); + } else { /* pulse with soft carrier */ + unsigned int nsecs; + + nsecs = gpkt->on ? gpkt->pulse : gpkt->space; + nsecs = min(nsecs, gpkt->buffer[gpkt->next]); + + gpio_ir_tx_set(gpkt, gpkt->on); + hrtimer_forward_now(&gpkt->timer, ns_to_ktime(nsecs)); + + gpkt->buffer[gpkt->next] -= nsecs; + gpkt->on = !gpkt->on; + + if (!gpkt->buffer[gpkt->next]) + gpkt->next++; + } + } else { + restart = HRTIMER_NORESTART; + gpio_ir_tx_set(gpkt, false); + complete(&gpkt->done); + } + + return restart; +} + +static int gpio_ir_tx_transmit_with_timer(struct gpio_ir_tx_packet *gpkt) +{ + int rc = 0; + + init_completion(&gpkt->done); + + hrtimer_init(&gpkt->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + gpkt->timer.function = gpio_ir_tx_timer; + + hrtimer_start(&gpkt->timer, ns_to_ktime(0), HRTIMER_MODE_REL); + + rc = wait_for_completion_interruptible(&gpkt->done); + if (rc != 0) { /* signal exit immediately */ + gpkt->abort = true; + wait_for_completion(&gpkt->done); + } + + return gpkt->next ? : -ERESTARTSYS; +} + +static void gpio_ir_tx_ndelay(unsigned long nsecs) +{ + unsigned long max_delay_ns = NSEC_PER_MSEC * MAX_UDELAY_MS; + + while (nsecs > max_delay_ns) { + ndelay(max_delay_ns); + nsecs -= max_delay_ns; + } + ndelay(nsecs); +} + +static int gpio_ir_tx_transmit_with_delay(struct gpio_ir_tx_packet *gpkt) +{ + unsigned long flags; + + /* disable irq for acurracy timing */ + local_irq_save(flags); + + for (; gpkt->next < gpkt->length; gpkt->next++) { + if (signal_pending(current)) + break; + if (gpkt->next & 0x01) { /* space */ + gpio_ir_tx_set(gpkt, false); + gpio_ir_tx_ndelay(gpkt->buffer[gpkt->next]); + } else if (!gpkt->pulse || !gpkt->space) { + gpio_ir_tx_set(gpkt, true); + gpio_ir_tx_ndelay(gpkt->buffer[gpkt->next]); + } else { /* pulse with soft carrier */ + while (gpkt->buffer[gpkt->next]) { + unsigned int nsecs; + + nsecs = gpkt->on ? gpkt->pulse : gpkt->space; + nsecs = min(nsecs, gpkt->buffer[gpkt->next]); + + gpio_ir_tx_set(gpkt, gpkt->on); + gpio_ir_tx_ndelay(nsecs); + + gpkt->buffer[gpkt->next] -= nsecs; + gpkt->on = !gpkt->on; + } + } + } + + gpio_ir_tx_set(gpkt, false); + local_irq_restore(flags); + + return gpkt->next ? : -ERESTARTSYS; +} + +static int gpio_ir_tx_transmit(struct rc_dev *rdev, unsigned *txbuf, unsigned n) +{ + struct gpio_ir_dev *gdev = rdev->priv; + struct gpio_ir_data *gdata = gdev->pdev->dev.platform_data; + struct gpio_ir_tx_packet gpkt = {}; + int i, rc = 0; + + for (i = 0; i < n; i++) + txbuf[i] *= NSEC_PER_USEC; + + mutex_lock(&gdev->lock); + + if (gdata->tx_disable_rx) + gpio_ir_rx_disable(gdev); + + if (gdev->tx_reg) { + rc = regulator_enable(gdev->tx_reg); + if (rc != 0) + goto err_regulator_enable; + } + + if (gdata->tx_soft_carrier) { + u32 carrier = gdev->tx_carrier ?: GPIO_IR_DEF_CARRIER_HZ; + u32 duty_cycle = gdev->tx_duty_cycle ?: 50; + u32 period = NSEC_PER_SEC / carrier; + + gpkt.pulse = period * duty_cycle / 100; + gpkt.space = period - gpkt.pulse; + } + + gpkt.gpio_nr = gdata->tx_gpio_nr; + gpkt.high_active = gdata->tx_high_active; + gpkt.buffer = txbuf; + gpkt.length = n; + + if (gdata->tx_with_timer) + rc = gpio_ir_tx_transmit_with_timer(&gpkt); + else + rc = gpio_ir_tx_transmit_with_delay(&gpkt); + + if (gdev->tx_reg) + regulator_disable(gdev->tx_reg); +err_regulator_enable: + if (gdata->tx_disable_rx) + gpio_ir_rx_enable(gdev); + mutex_unlock(&gdev->lock); + return rc; +} + +static int __devinit gpio_ir_tx_probe(struct gpio_ir_dev *gdev) +{ + struct gpio_ir_data *gdata = gdev->pdev->dev.platform_data; + int rc = 0; + + if (gdata->tx_reg_id) { + gdev->tx_reg = regulator_get(&gdev->pdev->dev, gdata->tx_reg_id); + if (IS_ERR(gdev->tx_reg)) { + dev_err(&gdev->pdev->dev, + "failed to regulator_get(%s)\n", + gdata->tx_reg_id); + return PTR_ERR(gdev->tx_reg); + } + } + + if (gpio_is_valid(gdata->tx_gpio_nr)) { + rc = gpio_request(gdata->tx_gpio_nr, GPIO_IR_TX_NAME); + if (rc < 0) { + dev_err(&gdev->pdev->dev, + "failed to gpio_request(%u)\n", + gdata->tx_gpio_nr); + goto err_gpio_request; + } + + rc = gpio_direction_output( + gdata->tx_gpio_nr, + !gdata->tx_high_active); + if (rc < 0) { + dev_err(&gdev->pdev->dev, + "failed to gpio_direction_output(%u)\n", + gdata->tx_gpio_nr); + goto err_gpio_direction_output; + } + + if (gdata->tx_soft_carrier) { + gdev->rdev->s_tx_carrier = gpio_ir_tx_carrier; + gdev->rdev->s_tx_duty_cycle = gpio_ir_tx_duty_cycle; + } + gdev->rdev->tx_ir = gpio_ir_tx_transmit; + } + + return rc; + +err_gpio_direction_output: + gpio_free(gdata->tx_gpio_nr); +err_gpio_request: + if (gdev->tx_reg) + regulator_put(gdev->tx_reg); + return rc; +} + +static void gpio_ir_tx_remove(struct gpio_ir_dev *gdev) +{ + struct gpio_ir_data *gdata = gdev->pdev->dev.platform_data; + + if (gpio_is_valid(gdata->tx_gpio_nr)) + gpio_free(gdata->tx_gpio_nr); + + if (gdev->tx_reg) + regulator_put(gdev->tx_reg); +} + +/* code for ir receive */ +static int gpio_ir_rx_carrier_report(struct rc_dev *rdev, int enable) +{ + struct gpio_ir_dev *gdev = rdev->priv; + + mutex_lock(&gdev->lock); + gdev->rx_carrier_report = enable; + mutex_unlock(&gdev->lock); + + return 0; +} + +static u32 gpio_ir_rx_carrier_period(struct gpio_ir_dev *gdev, s32 adjust) +{ + ktime_t now; + s64 delta; + u32 period; + + now = ktime_add_ns(ktime_get(), adjust); + delta = ktime_to_ns(ktime_sub(now, gdev->rx_carrier_last)); + period = (u32)(2 * delta) / gdev->rx_carrier_count; + + return period; +} + +static enum hrtimer_restart gpio_ir_rx_timer(struct hrtimer *timer) +{ + struct gpio_ir_dev *gdev = container_of(timer, struct gpio_ir_dev, rx_timer); + u32 period = gpio_ir_rx_carrier_period(gdev, -GPIO_IR_MAX_CARRIER_NS); + int rc = -ENOENT; + + if (gdev->rx_carrier_report) { + DEFINE_IR_RAW_EVENT(ev); + + ev.carrier = NSEC_PER_SEC / period; + ev.duty_cycle = 50; + ev.carrier_report = 1; + + rc = ir_raw_event_store(gdev->rdev, &ev); + if (rc != 0) { + dev_err(&gdev->pdev->dev, + "failed to ir_raw_event_store(%d)\n", rc); + } + } else { + rc = ir_raw_event_store_edge_with_adjust(gdev->rdev, + IR_SPACE, period - GPIO_IR_MAX_CARRIER_NS); + if (rc != 0) { + dev_err(&gdev->pdev->dev, "failed to " + "ir_raw_event_store_edge_with_adjust(%d)\n", rc); + } + } + + if (rc == 0) + ir_raw_event_handle(gdev->rdev); + + return HRTIMER_NORESTART; +} + +static bool gpio_ir_rx_get(struct gpio_ir_data *gdata) +{ + if (gdata->rx_high_active) + return gpio_get_value(gdata->rx_gpio_nr); + else + return !gpio_get_value(gdata->rx_gpio_nr); +} + +static irqreturn_t gpio_ir_rx_irq(int irq, void *dev) +{ + struct gpio_ir_dev *gdev = dev; + struct gpio_ir_data *gdata = gdev->pdev->dev.platform_data; + int rc = -ENOENT; + + if (gdata->rx_soft_carrier) { + if (!hrtimer_active(&gdev->rx_timer)) { + gdev->rx_carrier_last = ktime_get(); + gdev->rx_carrier_count = 0; + if (!gdev->rx_carrier_report) { + rc = ir_raw_event_store_edge(gdev->rdev, IR_PULSE); + if (rc != 0) { + dev_err(&gdev->pdev->dev, "failed to " + "ir_raw_event_store_edge(%d, %d)\n", + IR_PULSE, rc); + } + } + } + + gdev->rx_carrier_count++; + hrtimer_start(&gdev->rx_timer, + ns_to_ktime(GPIO_IR_MAX_CARRIER_NS), + HRTIMER_MODE_REL); + } else { + enum raw_event_type type; + + type = gpio_ir_rx_get(gdata) ? IR_PULSE : IR_SPACE; + rc = ir_raw_event_store_edge(gdev->rdev, type); + if (rc != 0) { + dev_err(&gdev->pdev->dev, "failed to " + "ir_raw_event_store_edge(%d, %d)\n", + type, rc); + } + } + + if (rc == 0) + ir_raw_event_handle(gdev->rdev); + + return IRQ_HANDLED; +} + +static int __devinit gpio_ir_rx_probe(struct gpio_ir_dev *gdev) +{ + struct gpio_ir_data *gdata = gdev->pdev->dev.platform_data; + unsigned long flags; + int rc = 0; + + hrtimer_init(&gdev->rx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + gdev->rx_timer.function = gpio_ir_rx_timer; + + if (gdata->rx_reg_id) { + gdev->rx_reg = regulator_get(&gdev->pdev->dev, gdata->rx_reg_id); + if (IS_ERR(gdev->rx_reg)) { + dev_err(&gdev->pdev->dev, + "failed to regulator_get(%s)\n", + gdata->rx_reg_id); + return PTR_ERR(gdev->rx_reg); + } + } + + if (gpio_is_valid(gdata->rx_gpio_nr)) { + rc = gpio_request(gdata->rx_gpio_nr, GPIO_IR_RX_NAME); + if (rc < 0) { + dev_err(&gdev->pdev->dev, + "failed to gpio_request(%u)\n", + gdata->rx_gpio_nr); + goto err_gpio_request; + } + + rc = gpio_direction_input(gdata->rx_gpio_nr); + if (rc < 0) { + dev_err(&gdev->pdev->dev, + "failed to gpio_direction_input(%u)\n", + gdata->rx_gpio_nr); + goto err_gpio_direction_input; + } + + flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_DISABLED; + rc = request_irq(gpio_to_irq(gdata->rx_gpio_nr), + gpio_ir_rx_irq, flags, GPIO_IR_RX_NAME, gdev); + if (rc < 0) { + dev_err(&gdev->pdev->dev, + "failed to request_irq(%d)\n", + gpio_to_irq(gdata->rx_gpio_nr)); + goto err_request_irq; + } + + rc = device_init_wakeup(&gdev->pdev->dev, gdata->rx_can_wakeup); + if (rc < 0) { + dev_err(&gdev->pdev->dev, + "failed to device_init_wakeup(%d)\n", + gdata->rx_can_wakeup); + goto err_device_init_wakeup; + } + + if (gdata->rx_soft_carrier) + gdev->rdev->s_carrier_report = gpio_ir_rx_carrier_report; + } + + return rc; + +err_device_init_wakeup: + free_irq(gpio_to_irq(gdata->rx_gpio_nr), gdev); +err_request_irq: +err_gpio_direction_input: + gpio_free(gdata->rx_gpio_nr); +err_gpio_request: + if (gdev->rx_reg) + regulator_put(gdev->rx_reg); + return rc; +} + +static void gpio_ir_rx_remove(struct gpio_ir_dev *gdev) +{ + struct gpio_ir_data *gdata = gdev->pdev->dev.platform_data; + + if (gpio_is_valid(gdata->rx_gpio_nr)) { + free_irq(gpio_to_irq(gdata->rx_gpio_nr), gdev); + gpio_free(gdata->rx_gpio_nr); + } + + hrtimer_cancel(&gdev->rx_timer); + if (gdev->rx_reg) + regulator_put(gdev->rx_reg); +} + +/* code for power management */ +#ifdef CONFIG_PM +static int gpio_ir_rx_wake(struct gpio_ir_dev *gdev, bool enable) +{ + struct gpio_ir_data *gdata = gdev->pdev->dev.platform_data; + int rc = 0; + + if (gpio_is_valid(gdata->rx_gpio_nr)) { + int irq = gpio_to_irq(gdata->rx_gpio_nr); + + if (enable) + rc = enable_irq_wake(irq); + else + rc = disable_irq_wake(irq); + } + + return rc; +} + +static int gpio_ir_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct gpio_ir_dev *gdev = platform_get_drvdata(pdev); + int rc = 0; + + mutex_lock(&gdev->lock); + if (gdev->rdev->open_count) { + if (device_may_wakeup(dev)) + rc = gpio_ir_rx_wake(gdev, true); + else + gpio_ir_rx_disable(gdev); + } + mutex_unlock(&gdev->lock); + + return rc; +} + +static int gpio_ir_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct gpio_ir_dev *gdev = platform_get_drvdata(pdev); + int rc = 0; + + mutex_lock(&gdev->lock); + if (gdev->rdev->open_count) { + if (device_may_wakeup(dev)) + rc = gpio_ir_rx_wake(gdev, false); + else + rc = gpio_ir_rx_enable(gdev); + } + mutex_unlock(&gdev->lock); + + return rc; +} + +static const struct dev_pm_ops gpio_ir_pm_ops = { + .suspend = gpio_ir_suspend, + .resume = gpio_ir_resume, +}; +#endif + +/* code for probe and remove */ +static int __devinit gpio_ir_probe(struct platform_device *pdev) +{ + struct gpio_ir_data *gdata; + struct gpio_ir_dev *gdev; + int rc = -ENOMEM; + + gdata = pdev->dev.platform_data; + if (!gdata) { + gdata = devm_kzalloc(&pdev->dev, sizeof(*gdata), GFP_KERNEL); + if (gdata) { + pdev->dev.platform_data = gdata; + if (pdev->dev.of_node) { + of_property_read_string(pdev->dev.of_node, "tx-reg-id", &gdata->tx_reg_id); + of_property_read_u32(pdev->dev.of_node, "tx-gpio-nr", (u32 *)&gdata->tx_gpio_nr); + gdata->tx_high_active = of_property_read_bool(pdev->dev.of_node, "tx-high-active"); + gdata->tx_soft_carrier = of_property_read_bool(pdev->dev.of_node, "tx-soft-carrier"); + gdata->tx_disable_rx = of_property_read_bool(pdev->dev.of_node, "tx-disable-rx"); + gdata->tx_with_timer = of_property_read_bool(pdev->dev.of_node, "tx-with-timer"); + + of_property_read_string(pdev->dev.of_node, "rx-reg-id", &gdata->rx_reg_id); + of_property_read_u32(pdev->dev.of_node, "rx-gpio-nr", (u32 *)&gdata->rx_gpio_nr); + gdata->rx_high_active = of_property_read_bool(pdev->dev.of_node, "rx-high-active"); + gdata->rx_soft_carrier = of_property_read_bool(pdev->dev.of_node, "rx-soft-carrier"); + of_property_read_u64(pdev->dev.of_node, "rx-init-protos", &gdata->rx_init_protos); + gdata->rx_can_wakeup = of_property_read_bool(pdev->dev.of_node, "rx-can-wakeup"); + of_property_read_string(pdev->dev.of_node, "rx-map-name", &gdata->rx_map_name); + + dev_info(&pdev->dev, + "tx-reg-id = %s, tx-gpio-nr = %d, tx-high-active = %d, " + "tx-soft-carrier = %d, tx-disable-rx = %d, tx-with-timer = %d\n", + gdata->tx_reg_id, gdata->tx_gpio_nr, gdata->tx_high_active, + gdata->tx_soft_carrier, gdata->tx_disable_rx, gdata->tx_with_timer); + + dev_info(&pdev->dev, + "rx-reg-id = %s, rx-gpio-nr = %d, rx-high-active = %d, rx-soft-carrier = %d, " + "rx-init-protos = %d, rx-can-wakeup = %d, rx-map-name = %d\n", + gdata->rx_reg_id, gdata->rx_gpio_nr, gdata->rx_high_active, gdata->rx_soft_carrier, + gdata->rx_init_protos, gdata->rx_can_wakeup, gdata->rx_map_name); + } + } else { + dev_err(&pdev->dev, "failed to alloc platform data\n"); + return -ENOMEM; + } + } + + gdev = kzalloc(sizeof(*gdev), GFP_KERNEL); + if (!gdev) { + dev_err(&pdev->dev, "failed to alloc gdev\n"); + return rc; + } + + mutex_init(&gdev->lock); + + gdev->pdev = pdev; + platform_set_drvdata(pdev, gdev); + + gdev->rdev = rc_allocate_device(); + if (!gdev->rdev) { + dev_err(&pdev->dev, "failed to alloc rdev\n"); + goto err_rc_allocate_device; + } + + gdev->rdev->dev.parent = &pdev->dev; + gdev->rdev->input_name = GPIO_IR_NAME; + gdev->rdev->input_phys = GPIO_IR_NAME; + gdev->rdev->input_id.bustype = BUS_HOST; + gdev->rdev->driver_name = GPIO_IR_NAME; + gdev->rdev->map_name = gdata->rx_map_name; + gdev->rdev->driver_type = RC_DRIVER_IR_RAW; + gdev->rdev->allowed_protos = gdata->rx_init_protos; + gdev->rdev->priv = gdev; + gdev->rdev->open = gpio_ir_open; + gdev->rdev->close = gpio_ir_close; + + rc = gpio_ir_tx_probe(gdev); + if (rc != 0) + goto err_gpio_ir_tx_probe; + + rc = gpio_ir_rx_probe(gdev); + if (rc != 0) + goto err_gpio_ir_rx_probe; + + rc = rc_register_device(gdev->rdev); + if (rc < 0) { + dev_err(&pdev->dev, "failed to register rdev\n"); + goto err_rc_register_device; + } + + return rc; + +err_rc_register_device: + gpio_ir_rx_remove(gdev); +err_gpio_ir_rx_probe: + gpio_ir_tx_remove(gdev); +err_gpio_ir_tx_probe: + rc_free_device(gdev->rdev); +err_rc_allocate_device: + kfree(gdev); + return rc; +} + +static int __devexit gpio_ir_remove(struct platform_device *pdev) +{ + struct gpio_ir_dev *gdev = platform_get_drvdata(pdev); + + rc_unregister_device(gdev->rdev); + gpio_ir_rx_remove(gdev); + gpio_ir_tx_remove(gdev); + kfree(gdev); + + return 0; +} + +/* code for init and exit */ +static const struct of_device_id of_gpio_ir_match[] = { + {.compatible = GPIO_IR_NAME,}, + {}, +}; + +static struct platform_driver gpio_ir_driver = { + .probe = gpio_ir_probe, + .remove = __devexit_p(gpio_ir_remove), + .driver = { + .name = GPIO_IR_NAME, + .owner = THIS_MODULE, + .of_match_table = of_gpio_ir_match, +#ifdef CONFIG_PM + .pm = &gpio_ir_pm_ops, +#endif + }, +}; + +static int __init gpio_ir_init(void) +{ + return platform_driver_register(&gpio_ir_driver); +} +module_init(gpio_ir_init); + +static void __exit gpio_ir_exit(void) +{ + platform_driver_unregister(&gpio_ir_driver); +} +module_exit(gpio_ir_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Xiang Xiao "); +MODULE_DESCRIPTION("GPIO IR driver"); diff --git a/drivers/media/rc/ir-dump-decoder.c b/drivers/media/rc/ir-dump-decoder.c new file mode 100644 index 0000000000000..986847e7a49f3 --- /dev/null +++ b/drivers/media/rc/ir-dump-decoder.c @@ -0,0 +1,86 @@ +/* ir-dump-decoder.c - dump IR pulse/space signal + * + * Copyright (C) 2012 by Xiang Xiao + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include "rc-core-priv.h" + +/** + * ir_dump_decode() - Dump one pulse or space signal + * @dev: the struct rc_dev descriptor of the device + * @duration: the struct ir_raw_event descriptor of the pulse/space + */ +static int ir_dump_decode(struct rc_dev *dev, struct ir_raw_event ev) +{ + const char *n = dev_name(&dev->dev) ?: "unknown"; + + if (ev.reset) + pr_info("%s: reset\n", n); + else if (ev.timeout) + pr_info("%s: timeout\t%uus\n", n, TO_US(ev.duration)); + else if (ev.carrier_report) + pr_info("%s: carrier\t%uHz(%u%%)\n", n, ev.carrier, ev.duty_cycle); + else + pr_info("%s: %s\t%uus\n", n, TO_STR(ev.pulse), TO_US(ev.duration)); + + return 0; +} + +static int ir_dump_register(struct rc_dev *dev) +{ + pr_info("%s: register(%s %s %s %s)\n", + dev_name(&dev->dev) ?: "unknown", + dev->driver_name ?: "unknown", + dev->map_name ?: "unknown", + dev->input_name ?: "unknown", + dev->input_phys ?: "unknown"); + return 0; +} + +static int ir_dump_unregister(struct rc_dev *dev) +{ + pr_info("%s: unregister(%s %s %s %s)\n", + dev_name(&dev->dev) ?: "unknown", + dev->driver_name ?: "unknown", + dev->map_name ?: "unknown", + dev->input_name ?: "unknown", + dev->input_phys ?: "unknown"); + return 0; +} + +static struct ir_raw_handler dump_handler = { + .protocols = RC_TYPE_OTHER, + .decode = ir_dump_decode, + .raw_register = ir_dump_register, + .raw_unregister = ir_dump_unregister, +}; + +static int __init ir_dump_decode_init(void) +{ + ir_raw_handler_register(&dump_handler); + pr_info("ir dump protocol handler initialized\n"); + return 0; +} + +static void __exit ir_dump_decode_exit(void) +{ + ir_raw_handler_unregister(&dump_handler); +} + +module_init(ir_dump_decode_init); +module_exit(ir_dump_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Xiang Xiao "); +MODULE_DESCRIPTION("ir dump protocol decoder"); diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index 98893a8332c7a..b5439736f07a6 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -20,7 +20,11 @@ #include #include "rc-core-priv.h" +#ifdef CONFIG_MACH_XIAOMI_MIDO +#define LIRCBUF_SIZE 1024 +#else #define LIRCBUF_SIZE 256 +#endif /** * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the @@ -113,12 +117,14 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, unsigned int *txbuf; /* buffer with values to transmit */ ssize_t ret = -EINVAL; size_t count; +#ifndef CONFIG_IR_PWM ktime_t start; s64 towait; unsigned int duration = 0; /* signal duration in us */ int i; start = ktime_get(); +#endif lirc = lirc_get_pdata(file); if (!lirc) @@ -146,6 +152,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, goto out; } +#ifndef CONFIG_IR_PWM for (i = 0; i < count; i++) { if (txbuf[i] > IR_MAX_DURATION / 1000 - duration || !txbuf[i]) { ret = -EINVAL; @@ -154,16 +161,20 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, duration += txbuf[i]; } +#endif ret = dev->tx_ir(dev, txbuf, count); if (ret < 0) goto out; +#ifndef CONFIG_IR_PWM for (duration = i = 0; i < ret; i++) duration += txbuf[i]; +#endif ret *= sizeof(unsigned int); +#ifndef CONFIG_IR_PWM /* * The lircd gap calculation expects the write function to * wait for the actual IR signal to be transmitted before @@ -174,6 +185,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(usecs_to_jiffies(towait)); } +#endif out: kfree(txbuf); @@ -314,12 +326,39 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, static int ir_lirc_open(void *data) { + +#ifdef CONFIG_MACH_XIAOMI_MIDO + struct lirc_codec *lirc = data; + struct rc_dev *dev = lirc->dev; + int ret = 0; + + mutex_lock(&dev->lock); + if (!dev->open_count++ && dev->open) + ret = dev->open(dev); + if (ret < 0) + dev->open_count--; + mutex_unlock(&dev->lock); + + return ret; +#else return 0; +#endif } static void ir_lirc_close(void *data) { + +#ifdef CONFIG_MACH_XIAOMI_MIDO + struct lirc_codec *lirc = data; + struct rc_dev *dev = lirc->dev; + + mutex_lock(&dev->lock); + if (!--dev->open_count && dev->close) + dev->close(dev); + mutex_unlock(&dev->lock); +#else return; +#endif } static const struct file_operations lirc_fops = { @@ -387,7 +426,11 @@ static int ir_lirc_register(struct rc_dev *dev) drv->rbuf = rbuf; drv->set_use_inc = &ir_lirc_open; drv->set_use_dec = &ir_lirc_close; +#ifdef CONFIG_MACH_XIAOMI_MIDO + drv->code_length = sizeof(int) * 8; +#else drv->code_length = sizeof(struct ir_raw_event) * 8; +#endif drv->fops = &lirc_fops; drv->dev = &dev->dev; drv->rdev = dev; @@ -404,6 +447,9 @@ static int ir_lirc_register(struct rc_dev *dev) return 0; lirc_register_failed: +#ifdef CONFIG_MACH_XIAOMI_MIDO + lirc_buffer_free(rbuf); +#endif rbuf_init_failed: kfree(rbuf); rbuf_alloc_failed: @@ -418,6 +464,9 @@ static int ir_lirc_unregister(struct rc_dev *dev) lirc_unregister_driver(lirc->drv->minor); lirc_buffer_free(lirc->drv->rbuf); +#ifdef CONFIG_MACH_XIAOMI_MIDO + kfree(lirc->drv->rbuf); +#endif kfree(lirc->drv); return 0; diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 249d2fbc8f374..ff6758a28e6db 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -314,8 +314,12 @@ int lirc_register_driver(struct lirc_driver *d) /* some safety check 8-) */ d->name[sizeof(d->name)-1] = '\0'; +#ifdef CONFIG_MACH_XIAOMI_MIDO + bytes_in_key = (d->code_length + 7)/8; +#else bytes_in_key = BITS_TO_LONGS(d->code_length) + (d->code_length % 8 ? 1 : 0); +#endif buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key; chunk_size = d->chunk_size ? d->chunk_size : bytes_in_key; diff --git a/drivers/media/rc/pwm-ir.c b/drivers/media/rc/pwm-ir.c new file mode 100644 index 0000000000000..0b006a35cbd4c --- /dev/null +++ b/drivers/media/rc/pwm-ir.c @@ -0,0 +1,391 @@ +/* Copyright (C) 2013 by Xiang Xiao + * Copyright (C) 2017 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +struct pwm_ir_dev { + struct mutex lock; + struct platform_device *pdev; + struct rc_dev *rdev; + struct regulator *reg; + struct pwm_device *pwm; + u32 carrier; + u32 duty_cycle; +}; + +struct pwm_ir_packet { + struct completion done; + struct hrtimer timer; + struct pwm_device *pwm; + bool abort; + unsigned int *buffer; + unsigned int length; + unsigned int next; +}; + +#define __devexit +#define __devinitdata +#define __devinit +#define __devexit_p + +/* code for ir transmit */ +static int pwm_ir_tx_config(struct pwm_ir_dev *dev, u32 carrier, u32 duty_cycle) +{ + int period_ns, duty_ns, rc; + + period_ns = NSEC_PER_SEC / carrier; + duty_ns = period_ns * duty_cycle / 100; + + rc = pwm_config(dev->pwm, duty_ns, period_ns); + if (rc == 0) { + dev->carrier = carrier; + dev->duty_cycle = duty_cycle; + } + + return rc; +} + +static int pwm_ir_tx_carrier(struct rc_dev *rdev, u32 carrier) +{ + struct pwm_ir_dev *dev = rdev->priv; + int rc; + + mutex_lock(&dev->lock); + rc = pwm_ir_tx_config(dev, carrier, dev->duty_cycle); + mutex_unlock(&dev->lock); + + return rc; +} + +static int pwm_ir_tx_duty_cycle(struct rc_dev *rdev, u32 duty_cycle) +{ + struct pwm_ir_dev *dev = rdev->priv; + int rc; + + mutex_lock(&dev->lock); + rc = pwm_ir_tx_config(dev, dev->carrier, duty_cycle); + mutex_unlock(&dev->lock); + + return rc; +} + +static enum hrtimer_restart pwm_ir_tx_timer(struct hrtimer *timer) +{ + struct pwm_ir_packet *pkt = container_of(timer, struct pwm_ir_packet, timer); + enum hrtimer_restart restart = HRTIMER_RESTART; + + if (!pkt->abort && pkt->next < pkt->length) { + u64 orun = hrtimer_forward_now(&pkt->timer, + ns_to_ktime(pkt->buffer[pkt->next++])); + if (orun > 1) + pr_warn("pwm-ir: lost %llu hrtimer callback\n", orun - 1); + + if (pkt->next & 0x01) + pwm_disable(pkt->pwm); + else /* pulse */ + pwm_enable(pkt->pwm); + } else { + restart = HRTIMER_NORESTART; + pwm_disable(pkt->pwm); + complete(&pkt->done); + } + + return restart; +} + +static int pwm_ir_tx_transmit_with_timer(struct pwm_ir_packet *pkt) +{ + int rc = 0; + + init_completion(&pkt->done); + + hrtimer_init(&pkt->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + pkt->timer.function = pwm_ir_tx_timer; + + hrtimer_start(&pkt->timer, ns_to_ktime(0), HRTIMER_MODE_REL); + + rc = wait_for_completion_interruptible(&pkt->done); + if (rc != 0) { /* signal exit immediately */ + pkt->abort = true; + wait_for_completion(&pkt->done); + } + + return pkt->next ? : -ERESTARTSYS; +} + + +static long pwm_ir_tx_work(void *arg) +{ + struct pwm_ir_packet *pkt = arg; + unsigned long flags; + + /* disable irq for acurracy timing */ + local_irq_save(flags); + + for (; pkt->next < pkt->length; pkt->next++) { + if (signal_pending(current)) + break; + if (pkt->next & 0x01) + pwm_disable(pkt->pwm); + else /* pulse */ + pwm_enable(pkt->pwm); + + ndelay(pkt->buffer[pkt->next]%1000); + udelay(pkt->buffer[pkt->next]/1000); + } + + pwm_disable(pkt->pwm); + local_irq_restore(flags); + + return pkt->next ? : -ERESTARTSYS; +} + +static int pwm_ir_tx_transmit_with_delay(struct pwm_ir_packet *pkt) +{ + int cpu, rc = -ENODEV; + + for_each_online_cpu(cpu) { + /* select one auxilliary cpu to run */ + if (cpu != 0) { + rc = work_on_cpu(cpu, pwm_ir_tx_work, pkt); + break; + } + } + + if (rc == -ENODEV) { + pr_warn("pwm-ir: can't run on the auxilliary cpu\n"); + rc = pwm_ir_tx_work(pkt); + } + + return rc; +} + +static int pwm_ir_tx_transmit(struct rc_dev *rdev, unsigned *txbuf, unsigned n) +{ + struct pwm_ir_dev *dev = rdev->priv; + struct pwm_ir_data *data = dev->pdev->dev.platform_data; + struct pwm_ir_packet pkt = {}; + int i, rc = 0; + + for (i = 0; i < n; i++) + txbuf[i] *= NSEC_PER_USEC; + + mutex_lock(&dev->lock); + + if (dev->reg) { + rc = regulator_enable(dev->reg); + if (rc != 0) + goto err_regulator_enable; + } + + pkt.pwm = dev->pwm; + pkt.buffer = txbuf; + pkt.length = n; + + if (data->use_timer) + rc = pwm_ir_tx_transmit_with_timer(&pkt); + else + rc = pwm_ir_tx_transmit_with_delay(&pkt); + + if (dev->reg) + regulator_disable(dev->reg); +err_regulator_enable: + mutex_unlock(&dev->lock); + return rc; +} + +static int __devinit pwm_ir_tx_probe(struct pwm_ir_dev *dev) +{ + struct pwm_ir_data *data = dev->pdev->dev.platform_data; + struct platform_device *pdev = dev->pdev; + int rc = 0; + + if (data->reg_id) { + dev->reg = regulator_get(&dev->pdev->dev, data->reg_id); + if (IS_ERR(dev->reg)) { + dev_err(&dev->pdev->dev, + "failed to regulator_get(%s)\n", + data->reg_id); + return PTR_ERR(dev->reg); + } + } + + + dev->pwm = of_pwm_get(pdev->dev.of_node, NULL); + if (IS_ERR(dev->pwm)) { + dev_err(&dev->pdev->dev, + "failed to of_pwm_get()\n"); + rc = PTR_ERR(dev->pwm); + dev_err(&dev->pdev->dev, "Cannot get PWM device rc:(%d)\n", rc); + dev->pwm = NULL; + goto err_regulator_put; + } + + if (data->low_active) { + rc = -ENOSYS; + if (rc != 0) { + dev_err(&dev->pdev->dev, "failed to change polarity\n"); + goto err_pwm_free; + } + } + rc = pwm_ir_tx_config(dev, 38000, 50); + if (rc != 0) { + dev_err(&dev->pdev->dev, "failed to change carrier and duty\n"); + goto err_pwm_free; + } + dev->rdev->tx_ir = pwm_ir_tx_transmit; + dev->rdev->s_tx_carrier = pwm_ir_tx_carrier; + dev->rdev->s_tx_duty_cycle = pwm_ir_tx_duty_cycle; + + return rc; + +err_pwm_free: + pwm_free(dev->pwm); +err_regulator_put: + if (dev->reg) + regulator_put(dev->reg); + return rc; +} + +static void pwm_ir_tx_remove(struct pwm_ir_dev *dev) +{ + if (dev->reg) + regulator_put(dev->reg); + pwm_free(dev->pwm); +} + +/* code for probe and remove */ +static int __devinit pwm_ir_probe(struct platform_device *pdev) +{ + struct pwm_ir_dev *dev; + int rc = -ENOMEM; + + if (!pdev->dev.platform_data) { + pdev->dev.platform_data = devm_kzalloc(&pdev->dev, sizeof(struct pwm_ir_data), GFP_KERNEL); + if (pdev->dev.platform_data) { + if (pdev->dev.of_node) { + struct pwm_ir_data *data = pdev->dev.platform_data; + + of_property_read_string(pdev->dev.of_node, "reg-id", &data->reg_id); + + data->low_active = of_property_read_bool(pdev->dev.of_node, "low-active"); + data->use_timer = of_property_read_bool(pdev->dev.of_node, "use-timer"); + + dev_info(&pdev->dev, + "reg-id = %s, low-active = %d, use-timer = %d\n", + data->reg_id, data->low_active, data->use_timer); + } + } else { + dev_err(&pdev->dev, "failed to alloc platform data\n"); + return -ENOMEM; + } + } + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + dev_err(&pdev->dev, "failed to alloc dev\n"); + return rc; + } + + mutex_init(&dev->lock); + + dev->pdev = pdev; + platform_set_drvdata(pdev, dev); + + dev->rdev = rc_allocate_device(); + if (!dev->rdev) { + dev_err(&pdev->dev, "failed to alloc rdev\n"); + goto err_rc_allocate_device; + } + + dev->rdev->dev.parent = &pdev->dev; + dev->rdev->input_name = PWM_IR_NAME; + dev->rdev->input_phys = PWM_IR_NAME; + dev->rdev->input_id.bustype = BUS_HOST; + dev->rdev->driver_name = PWM_IR_NAME; + dev->rdev->map_name = RC_MAP_LIRC; + dev->rdev->driver_type = RC_DRIVER_IR_RAW; + dev->rdev->priv = dev; + + rc = pwm_ir_tx_probe(dev); + if (rc != 0) + goto err_pwm_ir_tx_probe; + + rc = rc_register_device(dev->rdev); + if (rc < 0) { + dev_err(&pdev->dev, "failed to register rdev\n"); + goto err_rc_register_device; + } + + return rc; + +err_rc_register_device: + pwm_ir_tx_remove(dev); +err_pwm_ir_tx_probe: + rc_free_device(dev->rdev); +err_rc_allocate_device: + kfree(dev); + return rc; +} + +static int __devexit pwm_ir_remove(struct platform_device *pdev) +{ + struct pwm_ir_dev *dev = platform_get_drvdata(pdev); + + rc_unregister_device(dev->rdev); + pwm_ir_tx_remove(dev); + kfree(dev); + + return 0; +} + +/* code for init and exit */ +static const struct of_device_id of_pwm_ir_match[] = { + {.compatible = PWM_IR_NAME,}, + {}, +}; + +static struct platform_driver pwm_ir_driver = { + .probe = pwm_ir_probe, + .remove = __devexit_p(pwm_ir_remove), + .driver = { + .name = PWM_IR_NAME, + .owner = THIS_MODULE, + .of_match_table = of_pwm_ir_match, + }, +}; + +static int __init pwm_ir_init(void) +{ + return platform_driver_register(&pwm_ir_driver); +} +late_initcall(pwm_ir_init); + +static void __exit pwm_ir_exit(void) +{ + platform_driver_unregister(&pwm_ir_driver); +} +module_exit(pwm_ir_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Xiang Xiao "); +MODULE_DESCRIPTION("PWM IR driver"); diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c index b732ac6a26d80..350210160b22e 100644 --- a/drivers/media/rc/rc-ir-raw.c +++ b/drivers/media/rc/rc-ir-raw.c @@ -104,6 +104,14 @@ EXPORT_SYMBOL_GPL(ir_raw_event_store); * (or similar events) on state change. */ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type) +#ifdef CONFIG_MACH_XIAOMI_MIDO +{ + return ir_raw_event_store_edge_with_adjust(dev, type, 0); +} +EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); + +int ir_raw_event_store_edge_with_adjust(struct rc_dev *dev, enum raw_event_type type, s32 ns) +#endif { ktime_t now; s64 delta; /* ns */ @@ -114,7 +122,11 @@ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type) if (!dev->raw) return -EINVAL; +#ifdef CONFIG_MACH_XIAOMI_MIDO + now = ktime_add_ns(ktime_get(), ns); +#else now = ktime_get(); +#endif delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event)); delay = MS_TO_NS(dev->input_dev->rep[REP_DELAY]); @@ -142,7 +154,11 @@ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type) dev->raw->last_type = type; return rc; } +#ifdef CONFIG_MACH_XIAOMI_MIDO +EXPORT_SYMBOL_GPL(ir_raw_event_store_edge_with_adjust); +#else EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); +#endif /** * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index b4ceda856939f..ab1bbaa12e5b5 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -738,7 +738,20 @@ static int ir_open(struct input_dev *idev) { struct rc_dev *rdev = input_get_drvdata(idev); +#ifdef CONFIG_MACH_XIAOMI_MIDO + int rc = 0; + + mutex_lock(&rdev->lock); + if (!rdev->open_count++) + rc = rdev->open(rdev); + if (rc < 0) + rdev->open_count--; + mutex_unlock(&rdev->lock); + + return rc; +#else return rc_open(rdev); +#endif } void rc_close(struct rc_dev *rdev) @@ -757,7 +770,17 @@ EXPORT_SYMBOL_GPL(rc_close); static void ir_close(struct input_dev *idev) { struct rc_dev *rdev = input_get_drvdata(idev); + +#ifdef CONFIG_MACH_XIAOMI_MIDO + if (rdev) { + mutex_lock(&rdev->lock); + if (!--rdev->open_count) + rdev->close(rdev); + mutex_unlock(&rdev->lock); + } +#else rc_close(rdev); +#endif } /* class for /sys/class/rc */ diff --git a/include/media/gpio-ir.h b/include/media/gpio-ir.h new file mode 100644 index 0000000000000..c986439930bf8 --- /dev/null +++ b/include/media/gpio-ir.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2012 by Xiang Xiao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __GPIO_IR_H__ +#define __GPIO_IR_H__ + +#define GPIO_IR_NAME "gpio-ir" + +struct gpio_ir_data { + const char *tx_reg_id; + unsigned int tx_gpio_nr; + bool tx_high_active; + bool tx_soft_carrier; + bool tx_disable_rx; + bool tx_with_timer; + const char *rx_reg_id; + unsigned int rx_gpio_nr; + bool rx_high_active; + bool rx_soft_carrier; + u64 rx_init_protos; + bool rx_can_wakeup; + const char *rx_map_name; +}; + +#endif /* __GPIO_IR_H__ */ diff --git a/include/media/pwm-ir.h b/include/media/pwm-ir.h new file mode 100644 index 0000000000000..8df893d8319c8 --- /dev/null +++ b/include/media/pwm-ir.h @@ -0,0 +1,25 @@ +/* Copyright (C) 2013 by Xiang Xiao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __PWM_IR_H__ +#define __PWM_IR_H__ + +#define PWM_IR_NAME "pwm-ir" + +struct pwm_ir_data { + const char *reg_id; + int pwm_id; + bool low_active; + bool use_timer; +}; + +#endif /* __PWM_IR_H__ */ diff --git a/include/media/rc-core.h b/include/media/rc-core.h index 2c7fbca40b69f..0541a14f7bf16 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -156,6 +156,7 @@ struct rc_dev { u32 max_timeout; u32 rx_resolution; u32 tx_resolution; + u32 open_count; int (*change_protocol)(struct rc_dev *dev, u64 *rc_type); int (*change_wakeup_protocol)(struct rc_dev *dev, u64 *rc_type); int (*open)(struct rc_dev *dev); @@ -247,6 +248,10 @@ static inline void init_ir_raw_event(struct ir_raw_event *ev) void ir_raw_event_handle(struct rc_dev *dev); int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev); int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type); +#ifdef CONFIG_MACH_XIAOMI_MIDO +int ir_raw_event_store_edge_with_adjust(struct rc_dev *dev, + enum raw_event_type type, s32 ns); +#endif int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev); void ir_raw_event_set_idle(struct rc_dev *dev, bool idle); From 22d662cfb079dc82a1ae952e0f26e0230dba6fd1 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Mon, 19 Mar 2018 16:55:30 +0530 Subject: [PATCH 206/508] drivers: media: rc: Import tissot peelir driver --- drivers/media/rc/Kconfig | 7 + drivers/media/rc/Makefile | 3 + drivers/media/rc/peelir.c | 550 ++++++++++++++++++++++++++++++++++++++ drivers/media/rc/peelir.h | 81 ++++++ 4 files changed, 641 insertions(+) create mode 100644 drivers/media/rc/peelir.c create mode 100644 drivers/media/rc/peelir.h diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index bcb52980556dc..23ce743dc71e3 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -4,6 +4,13 @@ config RC_CORE depends on INPUT default y +config SPI_PEELIR + tristate "PEELIR" + default y + + ---help--- + Enable this option if you use peelir + source "drivers/media/rc/keymaps/Kconfig" menuconfig RC_DECODERS diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 5b6e32aa6dc6b..95c8f9c1e86f5 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -38,3 +38,6 @@ obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o obj-$(CONFIG_RC_ST) += st_rc.o obj-$(CONFIG_IR_SUNXI) += sunxi-cir.o obj-$(CONFIG_IR_IMG) += img-ir/ + +# peelir using spi +obj-$(CONFIG_SPI_PEELIR) += peelir.o diff --git a/drivers/media/rc/peelir.c b/drivers/media/rc/peelir.c new file mode 100644 index 0000000000000..cb1a26cbbcdd7 --- /dev/null +++ b/drivers/media/rc/peelir.c @@ -0,0 +1,550 @@ +/* +* Copyright (C) 2014 Peel Technologies Inc +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_OF +#include +#include +#include +#endif +#include +#include +#include +#include "peelir.h" + +#include +#include + +#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ + | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \ + | SPI_NO_CS | SPI_READY) + +#ifndef CONFIG_OF +#define LR_EN 73 +#endif + +#define TRACE printk("@@@@ %s, %d\n", __func__, __LINE__); + +/*uncoment below defintion to use map +for write*/ +#define USES_MMAP +struct peelir_data { + dev_t devt; + struct spi_device *spi; + struct mutex buf_lock; + spinlock_t spi_lock; + unsigned users; + u8 *buffer; +}; + +/*npages gets its value from the makefile +avoid changing it here*/ +/*static unsigned int npages = CONFIG_NPAGES; */ +static unsigned int npages = 150; +static unsigned bufsiz; /* Default buffer size */ +u32 is_gpio_used; +#ifndef CONFIG_OF +static int mode = 0, bpw = 32, spi_clk_freq = 960000; +#endif +static int lr_en, in_use , rcount; +static int prev_tx_status; /* Status of previous transaction */ +static u32 field; +static const char *reg_id; +static struct regulator *ir_reg; +u8 *p_buf; +struct peelir_data *peel_data_g; +#ifdef USES_MMAP +static void *kmalloc_ptr; +static int *kmalloc_area; +#endif +static struct spi_transfer t; + + +static int ir_regulator_set(bool enable) +{ + int rc = 0; +#ifdef CONFIG_OF + if (ir_reg) { + if (enable) { + rc = regulator_enable(ir_reg); + } else { + rc = regulator_disable(ir_reg); + } + + } +#endif + return rc; +} + + +static inline int +peelir_read(struct peelir_data *peelir, size_t len) +{ + struct spi_message m; + t.rx_buf = peelir->buffer; + t.len = len; + t.tx_buf = NULL; + memset(peelir->buffer, 0, len); TRACE + spi_message_init(&m); + spi_message_add_tail(&t, &m); + return spi_sync(peelir->spi, &m); +} + +static int peelir_read_message(struct peelir_data *peelir, + struct spi_ioc_transfer *u_xfers) +{ + u8 *buf; + + memset(peelir->buffer, 0, bufsiz); /*Receive Buffer*/ + + buf = peelir->buffer; TRACE + if (u_xfers->len > bufsiz) { + printk("%s: Requested too large data\n", __func__); + return -EMSGSIZE; + } + + /* Receiving IR input */ + + pr_info("\n Waiting for IR data.... \n"); + pr_info("\n Press the Key\n"); + + peelir_read(peelir, bufsiz); TRACE + + /* copy any rx data to user space */ + if (u_xfers->rx_buf) { + pr_info("\n%s:Copying data to user space\n", __func__); + if (__copy_to_user((u8 __user *) + (uintptr_t) u_xfers->rx_buf, buf, u_xfers->len)) { + pr_info("\n%s:Copy to user space failed !!!\n", __func__); + return -EFAULT; + } + } + + return 0; +} + +static inline int +peelir_write(struct peelir_data *peelir, size_t len) +{ + struct spi_message m; + + t.tx_buf = peelir->buffer; + t.len = len; + t.bits_per_word = peelir->spi->bits_per_word; + spi_message_init(&m); TRACE + spi_message_add_tail(&t, &m); + return spi_sync(peelir->spi, &m); +} + +static int peelir_write_message(struct peelir_data *peelir, + struct spi_ioc_transfer *u_xfers) +{ + u8 *buf; + int status = -EFAULT; + + buf = peelir->buffer; TRACE + + if (u_xfers->len > bufsiz) + status = -EMSGSIZE; + + if (u_xfers->tx_buf) + if (copy_from_user(buf, (const u8 __user *) + (uintptr_t) u_xfers->tx_buf, + u_xfers->len)) + + peelir->spi->bits_per_word = u_xfers->bits_per_word; + + status = peelir_write(peelir, u_xfers->len); TRACE + return status; +} + +static long +peelir_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int retval = 0; + struct peelir_data *peelir; + struct spi_ioc_transfer *ioc; + struct strIds *id; + int rc = 0; + + printk("%s:Invoked. cmd = %d\n", __func__, cmd); + peelir = filp->private_data; TRACE + + mutex_lock(&peelir->buf_lock); + + switch (cmd) { + /* read ioctls */ + + case SPI_IOC_WR_MSG: + /* copy into scratch area */ + ioc = kmalloc(sizeof(struct spi_ioc_transfer), GFP_KERNEL); + if (!ioc) { + retval = -ENOMEM; + break; + } + if (__copy_from_user(ioc, (void __user *)arg, sizeof(struct spi_ioc_transfer))) { + kfree(ioc); + retval = -EFAULT; + break; + } + + rc = ir_regulator_set(1); + if (!rc) { + retval = peelir_write_message(peelir, ioc); + } + if (retval > 0) + prev_tx_status = 1; + else + prev_tx_status = 0; + ir_regulator_set(0); + kfree(ioc); + + break; + + case SPI_IOC_RD_MSG: + printk("%s: READ Invoked\n", __func__); + if (is_gpio_used) + gpio_set_value(lr_en, 1); /* LR Enable high for Rx*/ + /* copy into scratch area */ + ioc = kmalloc(sizeof(struct spi_ioc_transfer), GFP_KERNEL); + if (!ioc) { + pr_err("%s: No memory for ioc. Exiting\n", __func__); + retval = -ENOMEM; + break; + } + if (__copy_from_user(ioc, (void __user *)arg, + sizeof(struct spi_ioc_transfer))) { + pr_err("%s: Error performing copy from user of ioc\n", + __func__); + kfree(ioc); + retval = -EFAULT; + break; + } + printk("%s: Starting hw read\n", __func__); + rc = ir_regulator_set(1); + if (!rc) { + retval = peelir_read_message(peelir, ioc); + } + ir_regulator_set(0); + if (is_gpio_used) + gpio_set_value(lr_en, 0); /* LR Enable default state*/ + break; + case SPI_IOC_RD_IDS: + id = kmalloc(sizeof(struct strIds), GFP_KERNEL); + if (!id) { + retval = -ENOMEM; + break; + } + id->u32ID1 = 0xad1a4100; + id->u32ID2 = 0x3c03d40; + id->u32ID3 = 0xb5300000; + + if (__copy_to_user((void __user *)arg , id, + sizeof(struct strIds))) { + kfree(id); + retval = -EFAULT; + break; + } + break; + } + + mutex_unlock(&peelir->buf_lock); + + return retval; +} + +static int peelir_open(struct inode *inode, struct file *filp) +{ + struct peelir_data *peelir; + int status = 0; + + peelir = peel_data_g; TRACE + if (in_use) { + dev_err(&peelir->spi->dev, "%s: Device in use. users = %d\n", + __func__, in_use); + return -EBUSY; + } + + peelir->buffer = p_buf; + if (!peelir->buffer) { + if (!peelir->buffer) { + dev_dbg(&peelir->spi->dev, "open/ENOMEM\n"); + status = -ENOMEM; + } + } + if (status == 0) { + peelir->users++; + filp->private_data = peel_data_g; + nonseekable_open(inode, filp); + } + rcount = 0; + + return status; +} + +static int peelir_release(struct inode *inode, struct file *filp) +{ + int status = 0; + in_use = 0; TRACE + peel_data_g->users = 0; + filp->private_data = NULL; + rcount = 0; + return status; +} + +#ifdef USES_MMAP +int peelir_mmap(struct file *filp, struct vm_area_struct *vma) +{ + int ret; + struct peelir_data *peelir; + long length = vma->vm_end - vma->vm_start; + + printk(KERN_INFO "mmap is invoked\n"); + peelir = (struct peelir_data *)filp->private_data; TRACE + /* check length - do not allow larger mappings than the number of + pages allocated */ + if (length > bufsiz) + return -EIO; + + ret = remap_pfn_range(vma, vma->vm_start, + virt_to_phys((void *)kmalloc_area) >> PAGE_SHIFT, + length, + vma->vm_page_prot); + if (ret < 0) + return ret; + return 0; +} +#endif +/* + * sysfs layer + */ + +static ssize_t ir_tx_status(struct device *dev, + struct device_attribute *attr, char *buf) +{TRACE + return snprintf(buf, strlen(buf) + 1, "%d\n", prev_tx_status); +} + +static ssize_t field_show(struct device *dev, + struct device_attribute *attr, char *buf) +{TRACE + return snprintf(buf, strlen(buf) + 1, "%x\n", field); +} + +static ssize_t field_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{TRACE + sscanf(buf, "%x", &field); + return count; +} + +static DEVICE_ATTR(txstat, S_IRUGO, ir_tx_status, NULL); +static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field_show, field_store); + +static struct attribute *peel_attributes[] = { + &dev_attr_txstat.attr, + &dev_attr_field.attr, + NULL, +}; + +static struct attribute_group attr_group = { + .attrs = peel_attributes, +}; + +/*-------------------------------------------------------------------------*/ +static const struct file_operations peel_dev_fops = { + .owner = THIS_MODULE, + .open = peelir_open, + .release = peelir_release, + .unlocked_ioctl = peelir_ioctl, + .compat_ioctl = peelir_ioctl, + #ifdef USES_MMAP + .mmap = peelir_mmap, + #endif +}; + +static struct miscdevice peel_dev_drv = { + .minor = MISC_DYNAMIC_MINOR, + .name = "peel_ir", + .fops = &peel_dev_fops, + .nodename = "peel_ir", + .mode = 0666 +}; + +static int peelir_probe(struct spi_device *spi) +{ + struct peelir_data *peelir; + int status; + + struct device_node *np = spi->dev.of_node; + #ifdef CONFIG_OF + u32 bpw, mode; TRACE + #endif + /* Allocate driver data */ + peelir = kzalloc(sizeof(*peelir), GFP_KERNEL); + if (!peelir) + return -ENOMEM; + + /* Initialize the driver data */ + peelir->spi = spi; + spin_lock_init(&peelir->spi_lock); + mutex_init(&peelir->buf_lock); + spi_set_drvdata(spi, peelir); + peel_data_g = peelir; + in_use = 0; + #ifdef CONFIG_OF + of_property_read_u32(np, "peel_ir,spi-bpw", &bpw); TRACE + of_property_read_u32(np, "peel_ir,spi-clk-speed", &spi->max_speed_hz); + of_property_read_u32(np, "peel_ir,spi-mode", &mode); + of_property_read_u32(np, "peel_ir,lr-gpio-valid", &is_gpio_used); + of_property_read_u32(np, "peel_ir,peel-field", &field); + of_property_read_u32(np, "peel_ir,lr-gpio", &lr_en); + of_property_read_string(np, "peel_ir,reg-id", ®_id); + if (reg_id) { + ir_reg = regulator_get(&(spi->dev), reg_id); + if (IS_ERR(ir_reg)) { + printk(KERN_ERR "ir regulator_get fail.\n"); + return PTR_ERR(ir_reg); + } + } + printk("%s: lr-gpio-valid = %d\n", __func__, is_gpio_used); + spi->bits_per_word = (u8)bpw; + spi->mode = (u8)mode; + #else + lr_en = LR_EN; TRACE + spi->bits_per_word = bpw; + spi->max_speed_hz = spi_clk_freq; + is_gpio_used = 1; + #endif + printk("%s:lr_en = %d\n", __func__, lr_en); + if (is_gpio_used) { + if (gpio_is_valid(lr_en)) { + /* configure LR enable gpio */ + status = gpio_request(lr_en, "lr_enable"); + if (status) { + printk("unable to request gpio [%d]: %d\n", + lr_en, status); + } + status = gpio_direction_output(lr_en, 0); + if (status) { + printk("unable to set direction for gpio [%d]: %d\n", + lr_en, status); + } + gpio_set_value(lr_en, 0); + } else + printk("gpio %d is not valid \n", lr_en); + } + misc_register(&peel_dev_drv); + /* sysfs entry */ + status = sysfs_create_group(&spi->dev.kobj, &attr_group); + if (status) + dev_dbg(&spi->dev, " Error creating sysfs entry "); + + return status; +} + +static int peelir_remove(struct spi_device *spi) +{ + struct peelir_data *peelir = spi_get_drvdata(spi); + + sysfs_remove_group(&spi->dev.kobj, &attr_group); TRACE + + /* make sure ops on existing fds can abort cleanly */ + spin_lock_irq(&peelir->spi_lock); + peelir->spi = NULL; + spi_set_drvdata(spi, NULL); + spin_unlock_irq(&peelir->spi_lock); + + /* prevent opening a new instance of the device + during the removal of the device + */ + if (peelir->users == 0) { + kfree(peelir); + kfree(p_buf); + } else { + return -EBUSY; + } + + return 0; +} +#ifdef CONFIG_OF +static const struct of_device_id peel_of_match[] = { + {.compatible = "peel_ir"}, +}; +MODULE_DEVICE_TABLE(of, peel_of_match); +#endif +static struct spi_driver peelir_spi_driver = { + .driver = { + .name = "peel_ir", + .owner = THIS_MODULE, + #ifdef CONFIG_OF + .of_match_table = peel_of_match, + #endif + }, + .probe = peelir_probe, + .remove = peelir_remove, + + /* NOTE: suspend/resume methods are not necessary here. + * We don't do anything except pass the requests to/from + * the underlying controller. The refrigerator handles + * most issues; the controller driver handles the rest. + */ +}; + +/*-------------------------------------------------------------------------*/ + +static int __init peelir_init(void) +{ + int status; + printk("%s:npages = %u\n", __func__, npages); + bufsiz = npages * PAGE_SIZE; + if (bufsiz % PAGE_SIZE) { + printk("%s:buffer size not aligned to page\n", __func__); + return -EINVAL; + } + p_buf = kzalloc(bufsiz, GFP_KERNEL|GFP_ATOMIC); + if (p_buf == NULL) + return -ENOMEM; + #ifdef USES_MMAP + kmalloc_ptr = p_buf; + kmalloc_area = (int *)((((unsigned long)kmalloc_ptr) + + PAGE_SIZE - 1) & PAGE_MASK); + #endif + status = spi_register_driver(&peelir_spi_driver); + if (status < 0 || p_buf == NULL) { + printk("%s: Error registerign peel driver\n", __func__); + return -ENODEV; + } + + return status; +} +module_init(peelir_init); + +static void __exit peelir_exit(void) +{ + spi_unregister_driver(&peelir_spi_driver); + misc_deregister(&peel_dev_drv); +} +module_exit(peelir_exit); + +MODULE_DESCRIPTION("Peel IR SPI driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("PEEL_IR"); +MODULE_AUTHOR("Preetam S Reddy "); + diff --git a/drivers/media/rc/peelir.h b/drivers/media/rc/peelir.h new file mode 100644 index 0000000000000..cf2459f09ee30 --- /dev/null +++ b/drivers/media/rc/peelir.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) Peel Technologies Inc + */ + +#ifndef PEELIR_H +#define PEELIR_H + +#include + +/* User space versions of kernel symbols for SPI clocking modes, + * matching + */ + +#define SPI_CPHA 0x01 +#define SPI_CPOL 0x02 + +#define SPI_CS_HIGH 0x04 +#define SPI_LSB_FIRST 0x08 +#define SPI_3WIRE 0x10 +#define SPI_LOOP 0x20 +#define SPI_NO_CS 0x40 +#define SPI_READY 0x80 + +/*---------------------------------------------------------------------------*/ + +/* IOCTL commands */ + +#define SPI_IOC_MAGIC 'k' + +/** + * struct spi_ioc_transfer - describes a single SPI transfer + * @tx_buf: Holds pointer to userspace buffer with transmit data, or null. + * If no data is provided, zeroes are shifted out. + * @rx_buf: Holds pointer to userspace buffer for receive data, or null. + * @len: Length of tx and rx buffers, in bytes. + * @speed_hz: Temporary override of the device's bitrate. + * @bits_per_word: Temporary override of the device's wordsize. + * @delay_usecs: If nonzero, how long to delay after the last bit transfer + * before optionally deselecting the device before the next transfer. + * @cs_change: True to deselect device before starting the next transfer. + * + * This structure is mapped directly to the kernel spi_transfer structure; + * the fields have the same meanings, except of course that the pointers + * are in a different address space (and may be of different sizes in some + * cases, such as 32-bit i386 userspace over a 64-bit x86_64 kernel). + */ +struct spi_ioc_transfer { + __u64 tx_buf; + __u64 rx_buf; + + __u32 len; + __u32 speed_hz; + + __u16 delay_usecs; + __u8 bits_per_word; + __u8 cs_change; + + /* If the contents of 'struct spi_ioc_transfer' ever change + * incompatibly, then the ioctl number (currently 0) must change; + * ioctls with constant size fields get a bit more in the way of + * error checking than ones (like this) where that field varies. + * + * NOTE: struct layout is the same in 64bit and 32bit userspace. + */ +}; + +struct strIds { + __u32 u32ID1; + __u32 u32ID2; + __u32 u32ID3; +}; + +/* Read/Write Message */ +#define SPI_IOC_RD_MODE _IOW(SPI_IOC_MAGIC, 1, __u8) +#define SPI_IOC_WR_MSG _IOW(SPI_IOC_MAGIC, 2, __u8) +#define SPI_IOC_RD_MSG _IOR(SPI_IOC_MAGIC, 3, __u8) +#define SPI_IOC_RD_IDS _IOR(SPI_IOC_MAGIC, 4, __u8) + + +#endif /* PEELIR_H */ + From 5cd2c77e639c5a6e7f620b551d4ebd44e070df85 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Fri, 29 Dec 2017 20:01:41 +0530 Subject: [PATCH 207/508] drivers: power: Import mido changes --- drivers/of/of_batterydata.c | 25 +++++++++++++++ drivers/power/qpnp-fg.c | 18 +++++++---- drivers/power/qpnp-smbcharger.c | 54 +++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 6 deletions(-) diff --git a/drivers/of/of_batterydata.c b/drivers/of/of_batterydata.c index 4fddbdefce5b5..19cf31407bd6d 100644 --- a/drivers/of/of_batterydata.c +++ b/drivers/of/of_batterydata.c @@ -316,12 +316,18 @@ struct device_node *of_batterydata_get_best_profile( { struct batt_ids batt_ids; struct device_node *node, *best_node = NULL; +#if (defined CONFIG_MACH_XIAOMI_MIDO) + struct device_node *default_node = NULL; +#endif struct power_supply *psy; const char *battery_type = NULL; union power_supply_propval ret = {0, }; int delta = 0, best_delta = 0, best_id_kohm = 0, id_range_pct, batt_id_kohm = 0, i = 0, rc = 0, limit = 0; bool in_range = false; +#if (defined CONFIG_MACH_XIAOMI_MIDO) + int checknum = 0, match = 0; +#endif psy = power_supply_get_by_name(psy_name); if (!psy) { @@ -372,11 +378,19 @@ struct device_node *of_batterydata_get_best_profile( delta = abs(batt_ids.kohm[i] - batt_id_kohm); limit = (batt_ids.kohm[i] * id_range_pct) / 100; in_range = (delta <= limit); +#if (defined CONFIG_MACH_XIAOMI_MIDO) + if (in_range != 0) + match = 1; +#endif /* * Check if the delta is the lowest one * and also if the limits are in range * before selecting the best node. */ +#ifdef CONFIG_MACH_XIAOMI_MIDO + if (batt_ids.kohm[i] == 82) + default_node = node; +#endif if ((delta < best_delta || !best_node) && in_range) { best_node = node; @@ -387,13 +401,24 @@ struct device_node *of_batterydata_get_best_profile( } } +#if (defined CONFIG_MACH_XIAOMI_MIDO) + checknum = abs(best_id_kohm - batt_id_kohm); + if (match == 0) { + best_node = default_node; + checknum = 0; + } +#endif if (best_node == NULL) { pr_err("No battery data found\n"); return best_node; } /* check that profile id is in range of the measured batt_id */ +#if (defined CONFIG_MACH_XIAOMI_MIDO) + if (checknum > +#else if (abs(best_id_kohm - batt_id_kohm) > +#endif ((best_id_kohm * id_range_pct) / 100)) { pr_err("out of range: profile id %d batt id %d pct %d", best_id_kohm, batt_id_kohm, id_range_pct); diff --git a/drivers/power/qpnp-fg.c b/drivers/power/qpnp-fg.c index 7b110598681d8..fce336600c33c 100644 --- a/drivers/power/qpnp-fg.c +++ b/drivers/power/qpnp-fg.c @@ -248,7 +248,11 @@ static struct fg_mem_setting settings[FG_MEM_SETTING_MAX] = { SETTING(CHG_TERM_CURRENT, 0x4F8, 2, 250), SETTING(IRQ_VOLT_EMPTY, 0x458, 3, 3100), SETTING(CUTOFF_VOLTAGE, 0x40C, 0, 3200), +#if (defined CONFIG_MACH_XIAOMI_MIDO) + SETTING(VBAT_EST_DIFF, 0x000, 0, 200), +#else SETTING(VBAT_EST_DIFF, 0x000, 0, 30), +#endif SETTING(DELTA_SOC, 0x450, 3, 1), SETTING(BATT_LOW, 0x458, 0, 4200), SETTING(THERM_DELAY, 0x4AC, 3, 0), @@ -330,7 +334,11 @@ module_param_named( battery_type, fg_batt_type, charp, S_IRUSR | S_IWUSR ); +#if (defined CONFIG_MACH_XIAOMI_MIDO) +static int fg_sram_update_period_ms = 3000; +#else static int fg_sram_update_period_ms = 30000; +#endif module_param_named( sram_update_period_ms, fg_sram_update_period_ms, int, S_IRUSR | S_IWUSR ); @@ -2025,12 +2033,6 @@ static void fg_handle_battery_insertion(struct fg_chip *chip) schedule_delayed_work(&chip->update_sram_data, msecs_to_jiffies(0)); } - -static int soc_to_setpoint(int soc) -{ - return DIV_ROUND_CLOSEST(soc * 255, 100); -} - static void batt_to_setpoint_adc(int vbatt_mv, u8 *data) { int val; @@ -8043,8 +8045,12 @@ static int fg_common_hw_init(struct fg_chip *chip) } } +#if (defined CONFIG_MACH_XIAOMI_MIDO) + rc = fg_mem_masked_write(chip, settings[FG_MEM_DELTA_SOC].address, 0xFF, 1, +#else rc = fg_mem_masked_write(chip, settings[FG_MEM_DELTA_SOC].address, 0xFF, soc_to_setpoint(settings[FG_MEM_DELTA_SOC].value), +#endif settings[FG_MEM_DELTA_SOC].offset); if (rc) { pr_err("failed to write delta soc rc=%d\n", rc); diff --git a/drivers/power/qpnp-smbcharger.c b/drivers/power/qpnp-smbcharger.c index 1281e5cd76815..3378de83a683c 100644 --- a/drivers/power/qpnp-smbcharger.c +++ b/drivers/power/qpnp-smbcharger.c @@ -4993,6 +4993,9 @@ static bool is_usbin_uv_high(struct smbchg_chip *chip) return reg &= USBIN_UV_BIT; } +#ifdef CONFIG_MACH_XIAOMI_MIDO +static int rerun_apsd(struct smbchg_chip *chip); +#endif #define HVDCP_NOTIFY_MS 2500 static void handle_usb_insertion(struct smbchg_chip *chip) { @@ -5013,6 +5016,12 @@ static void handle_usb_insertion(struct smbchg_chip *chip) pr_smb(PR_STATUS, "triggered\n"); /* usb inserted */ read_usb_type(chip, &usb_type_name, &usb_supply_type); +#ifdef CONFIG_MACH_XIAOMI_MIDO + if (usb_supply_type == POWER_SUPPLY_TYPE_USB_CDP || usb_supply_type == POWER_SUPPLY_TYPE_USB) { + rc = rerun_apsd(chip); + read_usb_type(chip, &usb_type_name, &usb_supply_type); + } +#endif pr_smb(PR_STATUS, "inserted type = %d (%s)", usb_supply_type, usb_type_name); @@ -6107,6 +6116,7 @@ static void smbchg_external_power_changed(struct power_supply *psy) read_usb_type(chip, &usb_type_name, &usb_supply_type); +#if (defined CONFIG_MACH_XIAOMI_MIDO) if (!rc && usb_supply_type == POWER_SUPPLY_TYPE_USB && prop.intval != POWER_SUPPLY_TYPE_USB && is_usb_present(chip)) { @@ -6146,6 +6156,7 @@ static void smbchg_external_power_changed(struct power_supply *psy) if (usb_supply_type != POWER_SUPPLY_TYPE_USB) goto skip_current_for_non_sdp; +#endif pr_smb(PR_MISC, "usb type = %s current_limit = %d\n", usb_type_name, current_limit); @@ -6348,7 +6359,11 @@ static int smbchg_battery_get_property(struct power_supply *psy, val->intval = get_prop_batt_health(chip); break; case POWER_SUPPLY_PROP_TECHNOLOGY: +#if (defined CONFIG_MACH_XIAOMI_MIDO) + val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO; +#else val->intval = POWER_SUPPLY_TECHNOLOGY_LION; +#endif break; case POWER_SUPPLY_PROP_FLASH_CURRENT_MAX: val->intval = smbchg_calc_max_flash_current(chip); @@ -6560,6 +6575,17 @@ static irqreturn_t batt_warm_handler(int irq, void *_chip) { struct smbchg_chip *chip = _chip; u8 reg = 0; +#if (defined CONFIG_MACH_XIAOMI_MIDO) + int rc; + /* set the warm float voltage compensation,set the warm float voltage to 4.1V */ + if (chip->float_voltage_comp != -EINVAL) { + rc = smbchg_float_voltage_comp_set(chip, chip->float_voltage_comp); + if (rc < 0) + dev_err(chip->dev, "Couldn't set float voltage comp rc = %d\n", rc); + pr_smb(PR_STATUS, "set float voltage comp to %d\n", chip->float_voltage_comp); + + } +#endif smbchg_read(chip, ®, chip->bat_if_base + RT_STS, 1); chip->batt_warm = !!(reg & HOT_BAT_SOFT_BIT); @@ -6577,6 +6603,14 @@ static irqreturn_t batt_cool_handler(int irq, void *_chip) struct smbchg_chip *chip = _chip; u8 reg = 0; +#if (defined CONFIG_MACH_XIAOMI_MIDO) + int rc; + /* set the cool float voltage compensation ,set the cool float voltage to 4.4V*/ + rc = smbchg_float_voltage_comp_set(chip, 0); + if (rc < 0) + dev_err(chip->dev, "Couldn't set float voltage comp rc = %d\n", rc); +#endif + smbchg_read(chip, ®, chip->bat_if_base + RT_STS, 1); chip->batt_cool = !!(reg & COLD_BAT_SOFT_BIT); pr_smb(PR_INTERRUPT, "triggered: 0x%02x\n", reg); @@ -7641,6 +7675,22 @@ static int smbchg_hw_init(struct smbchg_chip *chip) if (rc < 0) dev_err(chip->dev, "Couldn't set OTG OC config rc = %d\n", rc); + +#ifdef CONFIG_MACH_XIAOMI_MIDO + rc = smbchg_sec_masked_write(chip, chip->otg_base + OTG_CFG, 0x0c, 0x8); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set SMBCHGL_OTG_CFG rc=%d\n", + rc); + } + + rc = smbchg_read(chip, ®, chip->otg_base + OTG_CFG, 1); + printk("%s:read OTG_CFG=%2x\n", __func__, reg); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set SMBCHGL_OTG_CFG rc=%d\n", + rc); + } +#endif + } if (chip->otg_pinctrl) { @@ -8631,6 +8681,10 @@ static int smbchg_probe(struct spmi_device *spmi) goto votables_cleanup; } +#if (defined CONFIG_MACH_XIAOMI_MIDO) + chip->hvdcp_not_supported = true; +#endif + rc = smbchg_check_chg_version(chip); if (rc) { pr_err("Unable to check schg version rc=%d\n", rc); From 15da594e7c5093bf6881840268af8f4daa608fe7 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Fri, 23 Mar 2018 19:06:06 +0530 Subject: [PATCH 208/508] drivers: power: Import tissot changes --- drivers/of/of_batterydata.c | 14 +++++++----- drivers/power/qpnp-fg.c | 35 +++++++++++++++++++++++++----- drivers/power/qpnp-smbcharger.c | 10 ++++----- drivers/power/reset/msm-poweroff.c | 2 ++ 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/drivers/of/of_batterydata.c b/drivers/of/of_batterydata.c index 19cf31407bd6d..5e07b6ec524bc 100644 --- a/drivers/of/of_batterydata.c +++ b/drivers/of/of_batterydata.c @@ -316,7 +316,7 @@ struct device_node *of_batterydata_get_best_profile( { struct batt_ids batt_ids; struct device_node *node, *best_node = NULL; -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) struct device_node *default_node = NULL; #endif struct power_supply *psy; @@ -325,7 +325,7 @@ struct device_node *of_batterydata_get_best_profile( int delta = 0, best_delta = 0, best_id_kohm = 0, id_range_pct, batt_id_kohm = 0, i = 0, rc = 0, limit = 0; bool in_range = false; -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) int checknum = 0, match = 0; #endif @@ -378,7 +378,7 @@ struct device_node *of_batterydata_get_best_profile( delta = abs(batt_ids.kohm[i] - batt_id_kohm); limit = (batt_ids.kohm[i] * id_range_pct) / 100; in_range = (delta <= limit); -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) if (in_range != 0) match = 1; #endif @@ -389,6 +389,10 @@ struct device_node *of_batterydata_get_best_profile( */ #ifdef CONFIG_MACH_XIAOMI_MIDO if (batt_ids.kohm[i] == 82) + default_node = node; +#endif +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (batt_ids.kohm[i] == 50) default_node = node; #endif if ((delta < best_delta || !best_node) @@ -401,7 +405,7 @@ struct device_node *of_batterydata_get_best_profile( } } -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) checknum = abs(best_id_kohm - batt_id_kohm); if (match == 0) { best_node = default_node; @@ -414,7 +418,7 @@ struct device_node *of_batterydata_get_best_profile( } /* check that profile id is in range of the measured batt_id */ -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) if (checknum > #else if (abs(best_id_kohm - batt_id_kohm) > diff --git a/drivers/power/qpnp-fg.c b/drivers/power/qpnp-fg.c index fce336600c33c..cc2920d3e91a3 100644 --- a/drivers/power/qpnp-fg.c +++ b/drivers/power/qpnp-fg.c @@ -237,10 +237,17 @@ enum fg_mem_data_index { static struct fg_mem_setting settings[FG_MEM_SETTING_MAX] = { /* ID Address, Offset, Value*/ +#ifdef CONFIG_MACH_XIAOMI_TISSOT + SETTING(SOFT_COLD, 0x454, 0, 150), + SETTING(SOFT_HOT, 0x454, 1, 450), + SETTING(HARD_COLD, 0x454, 2, 0), + SETTING(HARD_HOT, 0x454, 3, 450), +#else SETTING(SOFT_COLD, 0x454, 0, 100), SETTING(SOFT_HOT, 0x454, 1, 400), SETTING(HARD_COLD, 0x454, 2, 50), SETTING(HARD_HOT, 0x454, 3, 450), +#endif SETTING(RESUME_SOC, 0x45C, 1, 0), SETTING(BCL_LM_THRESHOLD, 0x47C, 2, 50), SETTING(BCL_MH_THRESHOLD, 0x47C, 3, 752), @@ -248,7 +255,7 @@ static struct fg_mem_setting settings[FG_MEM_SETTING_MAX] = { SETTING(CHG_TERM_CURRENT, 0x4F8, 2, 250), SETTING(IRQ_VOLT_EMPTY, 0x458, 3, 3100), SETTING(CUTOFF_VOLTAGE, 0x40C, 0, 3200), -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) SETTING(VBAT_EST_DIFF, 0x000, 0, 200), #else SETTING(VBAT_EST_DIFF, 0x000, 0, 30), @@ -334,7 +341,7 @@ module_param_named( battery_type, fg_batt_type, charp, S_IRUSR | S_IWUSR ); -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) static int fg_sram_update_period_ms = 3000; #else static int fg_sram_update_period_ms = 30000; @@ -4494,6 +4501,11 @@ static bool fg_validate_battery_info(struct fg_chip *chip) batt_soc = DIV_ROUND_CLOSEST((batt_soc - 1) * (FULL_CAPACITY - 2), FULL_SOC_RAW - 2) + 1; +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (batt_soc == FULL_SOC_RAW) + chip->batt_info[BATT_INFO_SOC] = 100; +#endif + if (*chip->batt_range_ocv && chip->batt_max_voltage_uv > 1000) delta_pct = DIV_ROUND_CLOSEST(abs(batt_volt_mv - chip->batt_info[BATT_INFO_VOLTAGE]) * 100, @@ -4645,10 +4657,18 @@ static int fg_power_get_property(struct power_supply *psy, val->intval = 1; break; case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: +#ifdef CONFIG_MACH_XIAOMI_TISSOT + val->intval = 3080000; +#else val->intval = chip->nom_cap_uah; +#endif break; case POWER_SUPPLY_PROP_CHARGE_FULL: +#ifdef CONFIG_MACH_XIAOMI_TISSOT + val->intval = 3080000; +#else val->intval = chip->learning_data.learned_cc_uah; +#endif break; case POWER_SUPPLY_PROP_CHARGE_NOW: val->intval = chip->learning_data.cc_uah; @@ -6464,8 +6484,13 @@ static int fg_batt_profile_init(struct fg_chip *chip) goto no_profile; } - - vbat_in_range = get_vbat_est_diff(chip) +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (!chip->input_present) + vbat_in_range = get_vbat_est_diff(chip) + < 80 * 1000; + else +#endif + vbat_in_range = get_vbat_est_diff(chip) < settings[FG_MEM_VBAT_EST_DIFF].value * 1000; profiles_same = memcmp(chip->batt_profile, data, PROFILE_COMPARE_LEN) == 0; @@ -8045,7 +8070,7 @@ static int fg_common_hw_init(struct fg_chip *chip) } } -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) rc = fg_mem_masked_write(chip, settings[FG_MEM_DELTA_SOC].address, 0xFF, 1, #else rc = fg_mem_masked_write(chip, settings[FG_MEM_DELTA_SOC].address, 0xFF, diff --git a/drivers/power/qpnp-smbcharger.c b/drivers/power/qpnp-smbcharger.c index 3378de83a683c..a622fc1ea0e20 100644 --- a/drivers/power/qpnp-smbcharger.c +++ b/drivers/power/qpnp-smbcharger.c @@ -6116,7 +6116,7 @@ static void smbchg_external_power_changed(struct power_supply *psy) read_usb_type(chip, &usb_type_name, &usb_supply_type); -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) if (!rc && usb_supply_type == POWER_SUPPLY_TYPE_USB && prop.intval != POWER_SUPPLY_TYPE_USB && is_usb_present(chip)) { @@ -6359,7 +6359,7 @@ static int smbchg_battery_get_property(struct power_supply *psy, val->intval = get_prop_batt_health(chip); break; case POWER_SUPPLY_PROP_TECHNOLOGY: -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO; #else val->intval = POWER_SUPPLY_TECHNOLOGY_LION; @@ -6575,7 +6575,7 @@ static irqreturn_t batt_warm_handler(int irq, void *_chip) { struct smbchg_chip *chip = _chip; u8 reg = 0; -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) int rc; /* set the warm float voltage compensation,set the warm float voltage to 4.1V */ if (chip->float_voltage_comp != -EINVAL) { @@ -6603,7 +6603,7 @@ static irqreturn_t batt_cool_handler(int irq, void *_chip) struct smbchg_chip *chip = _chip; u8 reg = 0; -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) int rc; /* set the cool float voltage compensation ,set the cool float voltage to 4.4V*/ rc = smbchg_float_voltage_comp_set(chip, 0); @@ -8681,7 +8681,7 @@ static int smbchg_probe(struct spmi_device *spmi) goto votables_cleanup; } -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) chip->hvdcp_not_supported = true; #endif diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index 0123fbf309048..bdb709e212e3a 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -205,10 +205,12 @@ static void set_dload_mode(int on) return; } +#if 0 static void enable_emergency_dload_mode(void) { pr_err("dload mode is not enabled on target\n"); } +#endif static bool get_dload_mode(void) { From 3d0109a968fff7bf6c843f99aa8549c4527be06f Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Fri, 29 Dec 2017 20:15:00 +0530 Subject: [PATCH 209/508] sound: soc: Import mido changes --- sound/soc/codecs/msm8x16-wcd.c | 6 +++++ sound/soc/codecs/wcd-mbhc-v2.c | 34 +++++++++++++++++++++++++ sound/soc/msm/msm8952.c | 45 ++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) diff --git a/sound/soc/codecs/msm8x16-wcd.c b/sound/soc/codecs/msm8x16-wcd.c index 964372f0f328f..a4715fadd002d 100644 --- a/sound/soc/codecs/msm8x16-wcd.c +++ b/sound/soc/codecs/msm8x16-wcd.c @@ -4236,6 +4236,9 @@ static int msm8x16_wcd_lo_dac_event(struct snd_soc_dapm_widget *w, MSM8X16_WCD_A_ANALOG_RX_LO_DAC_CTL, 0x08, 0x08); snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_RX_LO_DAC_CTL, 0x40, 0x40); +#if (defined CONFIG_MACH_XIAOMI_MIDO) + msleep(5); +#endif break; case SND_SOC_DAPM_POST_PMU: snd_soc_update_bits(codec, @@ -4461,6 +4464,9 @@ static const struct snd_soc_dapm_route audio_map[] = { {"LINEOUT PA", NULL, "LINE_OUT"}, {"LINE_OUT", "Switch", "LINEOUT DAC"}, {"LINEOUT DAC", NULL, "RX3 CHAIN"}, +#if (defined CONFIG_MACH_XIAOMI_MIDO) + { "Ext Spk", NULL, "LINEOUT PA"}, +#endif /* lineout to WSA */ {"WSA_SPK OUT", NULL, "LINEOUT PA"}, diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index 42ea423662d68..05797fb1fd869 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -25,6 +25,9 @@ #include #include #include +#if (defined CONFIG_MACH_XIAOMI_MIDO) +#include +#endif #include #include #include "wcd-mbhc-v2.h" @@ -42,7 +45,11 @@ #define OCP_ATTEMPT 1 #define HS_DETECT_PLUG_TIME_MS (3 * 1000) #define SPECIAL_HS_DETECT_TIME_MS (2 * 1000) +#if (defined CONFIG_MACH_XIAOMI_MIDO) +#define MBHC_BUTTON_PRESS_THRESHOLD_MIN 750 +#else #define MBHC_BUTTON_PRESS_THRESHOLD_MIN 250 +#endif #define GND_MIC_SWAP_THRESHOLD 4 #define WCD_FAKE_REMOVAL_MIN_PERIOD_MS 100 #define HS_VREF_MIN_VAL 1400 @@ -67,9 +74,20 @@ enum wcd_mbhc_cs_mb_en_flag { WCD_MBHC_EN_NONE, }; +#if (defined CONFIG_MACH_XIAOMI_MIDO) +static struct switch_dev accdet_data; +#endif + static void wcd_mbhc_jack_report(struct wcd_mbhc *mbhc, struct snd_soc_jack *jack, int status, int mask) { +#if (defined CONFIG_MACH_XIAOMI_MIDO) + if (!status && (jack->jack->type&WCD_MBHC_JACK_MASK)) { + switch_set_state(&accdet_data, 0); + } else if (jack->jack->type&WCD_MBHC_JACK_MASK) { + switch_set_state(&accdet_data, status); + } +#endif snd_soc_jack_report(jack, status, mask); } @@ -2378,6 +2396,16 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec, pr_debug("%s: enter\n", __func__); +#ifdef CONFIG_MACH_XIAOMI_MIDO + accdet_data.name = "h2w"; + accdet_data.index = 0; + accdet_data.state = 0; + ret = switch_dev_register(&accdet_data); + if (ret) { + dev_err(card->dev, "[Accdet]switch_dev_register returned:%d!\n", ret); + return -EPERM; + } +#endif ret = of_property_read_u32(card->dev->of_node, hph_switch, &hph_swh); if (ret) { dev_err(card->dev, @@ -2574,6 +2602,9 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec, mbhc->mbhc_cb->register_notifier(codec, &mbhc->nblock, false); mutex_destroy(&mbhc->codec_resource_lock); err: +#if (defined CONFIG_MACH_XIAOMI_MIDO) + switch_dev_unregister(&accdet_data); +#endif pr_debug("%s: leave ret %d\n", __func__, ret); return ret; } @@ -2595,6 +2626,9 @@ void wcd_mbhc_deinit(struct wcd_mbhc *mbhc) if (mbhc->mbhc_cb && mbhc->mbhc_cb->register_notifier) mbhc->mbhc_cb->register_notifier(codec, &mbhc->nblock, false); mutex_destroy(&mbhc->codec_resource_lock); +#if (defined CONFIG_MACH_XIAOMI_MIDO) + switch_dev_unregister(&accdet_data); +#endif } EXPORT_SYMBOL(wcd_mbhc_deinit); diff --git a/sound/soc/msm/msm8952.c b/sound/soc/msm/msm8952.c index 880677fc39a92..c8d2dba28ce4f 100644 --- a/sound/soc/msm/msm8952.c +++ b/sound/soc/msm/msm8952.c @@ -53,6 +53,10 @@ #define MAX_WSA_CODEC_NAME_LENGTH 80 #define MSM_DT_MAX_PROP_SIZE 80 +#ifdef CONFIG_MACH_XIAOMI_MIDO +#define EXT_PA_MODE 5 +#endif + enum btsco_rates { RATE_8KHZ_ID, RATE_16KHZ_ID, @@ -94,9 +98,15 @@ static struct wcd_mbhc_config mbhc_cfg = { .swap_gnd_mic = NULL, .hs_ext_micbias = false, .key_code[0] = KEY_MEDIA, +#if (defined CONFIG_MACH_XIAOMI_MIDO) + .key_code[1] = BTN_1, + .key_code[2] = BTN_2, + .key_code[3] = 0, +#else .key_code[1] = KEY_VOICECOMMAND, .key_code[2] = KEY_VOLUMEUP, .key_code[3] = KEY_VOLUMEDOWN, +#endif .key_code[4] = 0, .key_code[5] = 0, .key_code[6] = 0, @@ -257,6 +267,9 @@ int is_ext_spk_gpio_support(struct platform_device *pdev, return -EINVAL; } } +#ifdef CONFIG_MACH_XIAOMI_MIDO + gpio_direction_output(pdata->spk_ext_pa_gpio, 0); +#endif return 0; } @@ -265,6 +278,9 @@ static int enable_spk_ext_pa(struct snd_soc_codec *codec, int enable) struct snd_soc_card *card = codec->component.card; struct msm8916_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); int ret; +#ifdef CONFIG_MACH_XIAOMI_MIDO + int pa_mode = EXT_PA_MODE; +#endif if (!gpio_is_valid(pdata->spk_ext_pa_gpio)) { pr_err("%s: Invalid gpio: %d\n", __func__, @@ -276,6 +292,15 @@ static int enable_spk_ext_pa(struct snd_soc_codec *codec, int enable) enable ? "Enable" : "Disable"); if (enable) { +#ifdef CONFIG_MACH_XIAOMI_MIDO + while (pa_mode > 0) { + gpio_set_value_cansleep(pdata->spk_ext_pa_gpio, 0); + udelay(2); + gpio_set_value_cansleep(pdata->spk_ext_pa_gpio, enable); + udelay(2); + pa_mode--; + } +#else ret = msm_gpioset_activate(CLIENT_WCD_INT, "ext_spk_gpio"); if (ret) { pr_err("%s: gpio set cannot be de-activated %s\n", @@ -283,14 +308,17 @@ static int enable_spk_ext_pa(struct snd_soc_codec *codec, int enable) return ret; } gpio_set_value_cansleep(pdata->spk_ext_pa_gpio, enable); +#endif } else { gpio_set_value_cansleep(pdata->spk_ext_pa_gpio, enable); +#ifndef CONFIG_MACH_XIAOMI_MIDO ret = msm_gpioset_suspend(CLIENT_WCD_INT, "ext_spk_gpio"); if (ret) { pr_err("%s: gpio set cannot be de-activated %s\n", __func__, "ext_spk_gpio"); return ret; } +#endif } return 0; } @@ -1545,7 +1573,11 @@ static void *def_msm8952_wcd_mbhc_cal(void) return NULL; #define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(msm8952_wcd_cal)->X) = (Y)) +#ifdef CONFIG_MACH_XIAOMI_MIDO + S(v_hs_max, 1600); +#else S(v_hs_max, 1500); +#endif #undef S #define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(msm8952_wcd_cal)->X) = (Y)) S(num_btn, WCD_MBHC_DEF_BUTTONS); @@ -1568,6 +1600,18 @@ static void *def_msm8952_wcd_mbhc_cal(void) * 210-290 == Button 2 * 360-680 == Button 3 */ +#ifdef CONFIG_MACH_XIAOMI_MIDO + btn_low[0] = 73; + btn_high[0] = 73; + btn_low[1] = 233; + btn_high[1] = 233; + btn_low[2] = 438; + btn_high[2] = 438; + btn_low[3] = 438; + btn_high[3] = 438; + btn_low[4] = 438; + btn_high[4] = 438; +#else btn_low[0] = 75; btn_high[0] = 75; btn_low[1] = 150; @@ -1578,6 +1622,7 @@ static void *def_msm8952_wcd_mbhc_cal(void) btn_high[3] = 450; btn_low[4] = 500; btn_high[4] = 500; +#endif return msm8952_wcd_cal; } From b97927786632a615174dba47ca457aab6672a701 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Mon, 19 Mar 2018 19:51:19 +0530 Subject: [PATCH 210/508] sound: soc: Import tissot changes --- include/sound/apr_audio-v2.h | 28 + sound/soc/codecs/Kconfig | 7 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/max98927.c | 1487 ++++++++++++++++++++ sound/soc/codecs/max98927.h | 1246 ++++++++++++++++ sound/soc/codecs/msm8x16-wcd.c | 8 +- sound/soc/codecs/wcd-mbhc-v2.c | 110 +- sound/soc/msm/msm-dai-fe.c | 34 + sound/soc/msm/msm8952.c | 98 +- sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c | 119 ++ sound/soc/msm/qdsp6v2/q6afe.c | 130 ++ 11 files changed, 3255 insertions(+), 14 deletions(-) create mode 100644 sound/soc/codecs/max98927.c create mode 100644 sound/soc/codecs/max98927.h diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index 6f88d5348f2f2..8638f5fe97f68 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -8194,6 +8194,34 @@ struct afe_spkr_prot_calib_get_resp { struct asm_calib_res_cfg res_cfg; } __packed; +#ifdef CONFIG_SND_SOC_MAX98927 +#define AFE_RX_TOPOLOGY_ID_DSM 0x10001060 +#define AFE_MODULE_DSM_TX 0x10001061 +#define AFE_MODULE_DSM_RX 0x10001062 +#define AFE_PARAM_ID_DSM_CFG 0x10001066 +#define AFE_PARAM_ID_DSM_ENABLE 0x10001068 + +#define AFE_DSM_RX_PORT AFE_PORT_ID_QUINARY_MI2S_RX +#define AFE_DSM_TX_PORT AFE_PORT_ID_QUINARY_MI2S_TX + +struct afe_dsm_set_command { + struct apr_hdr hdr; + struct afe_port_cmd_set_param_v2 param; + struct afe_port_param_data_v2 pdata; +} __packed; + +struct afe_dsm_get_command { + struct apr_hdr hdr; + struct afe_port_cmd_get_param_v2 param; + struct afe_port_param_data_v2 pdata; +} __packed; + +struct afe_dsm_get_resp { + uint32_t status; + struct afe_port_param_data_v2 pdata; + uint32_t payload[0]; +} __packed; +#endif /* SRS TRUMEDIA start */ /* topology */ diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index aae1b9a86eb6a..0e6f79f0fde72 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -164,6 +164,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM9705 if SND_SOC_AC97_BUS select SND_SOC_WM9712 if SND_SOC_AC97_BUS select SND_SOC_WM9713 if SND_SOC_AC97_BUS + select SND_SOC_MAX98927 if I2C help Normally ASoC codec drivers are only built if a machine driver which uses them is also built since they are only usable with a machine @@ -871,4 +872,10 @@ config SND_SOC_MSM_HDMI_CODEC_RX config SND_SOC_MSM_HDMI_DBA_CODEC_RX bool "HDMI DBA Audio Playback" depends on MSM_DBA + +config SND_SOC_MAX98927 + tristate "Audio SMART PA 98927 support" + help + Say Y here to enable Audio SMART PA support. This allows + monitoring switches by userspace via sysfs and uevent. endmenu diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 8c9db9b1a62a7..04eaf07b9e91e 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -189,6 +189,7 @@ obj-$(CONFIG_SND_SOC_MSM_HDMI_DBA_CODEC_RX) := msm_hdmi_dba_codec_rx.o snd-soc-max9877-objs := max9877.o snd-soc-tpa6130a2-objs := tpa6130a2.o snd-soc-tas2552-objs := tas2552.o +snd-soc-max98927-objs := max98927.o obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o @@ -376,3 +377,4 @@ obj-$(CONFIG_SND_SOC_MSM_STUB) += snd-soc-msm-stub.o # Amp obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o +obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c new file mode 100644 index 0000000000000..1f34f02b9751f --- /dev/null +++ b/sound/soc/codecs/max98927.c @@ -0,0 +1,1487 @@ +/* max98927.c -- ALSA SoC Stereo MAX98927 driver + * Copyright 2013-15 Maxim Integrated Products + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "max98927.h" +#include + +#define F0_DETECT 1 + +#define Q_DSM_ADAPTIVE_FC 9 +#define Q_DSM_ADAPTIVE_DC_RES 27 + +static int i2c_states = -1; + +int reg_common_map[][2] = { + {MAX98927_Brownout_level_infinite_hold, 0x00}, + {MAX98927_Brownout_level_hold, 0x00}, + {MAX98927_Brownout__level_1_current_limit, 0x14}, + {MAX98927_Brownout__level_1_amp_1_control_1, 0x00}, + {MAX98927_Brownout__level_1_amp_1_control_2, 0x0c}, + {MAX98927_Brownout__level_1_amp_1_control_3, 0x00}, + {MAX98927_Brownout__level_2_current_limit, 0x10}, + {MAX98927_Brownout__level_2_amp_1_control_1, 0x00}, + {MAX98927_Brownout__level_2_amp_1_control_2, 0x0c}, + {MAX98927_Brownout__level_2_amp_1_control_3, 0x00}, + {MAX98927_Brownout__level_3_current_limit, 0x0c}, + {MAX98927_Brownout__level_3_amp_1_control_1, 0x06}, + {MAX98927_Brownout__level_3_amp_1_control_2, 0x18}, + {MAX98927_Brownout__level_3_amp_1_control_3, 0x0c}, + {MAX98927_Brownout__level_4_current_limit, 0x08}, + {MAX98927_Brownout__level_4_amp_1_control_1, 0x0e}, + {MAX98927_Brownout__level_4_amp_1_control_2, 0x80}, + {MAX98927_Brownout__level_4_amp_1_control_3, 0x00}, + {MAX98927_Brownout_threshold_hysterysis, 0x00}, + {MAX98927_Brownout_AMP_limiter_attack_release, 0x00}, + {MAX98927_Brownout_AMP_gain_attack_release, 0x00}, + {MAX98927_Brownout_AMP1_clip_mode, 0x00}, + {MAX98927_Meas_ADC_Config, 0x07}, + {MAX98927_Meas_ADC_Thermal_Warning_Threshhold, 0x78}, + {MAX98927_Meas_ADC_Thermal_Shutdown_Threshhold, 0xFF}, + {MAX98927_Pin_Config, 0x55}, + {MAX98927_Measurement_DSP_Config, 0x07}, + {MAX98927_PCM_Tx_Enables_B, 0x00}, + {MAX98927_PCM_Rx_Enables_B, 0x00}, + {MAX98927_PCM_Tx_Channel_Sources_B, 0x00}, + {MAX98927_PCM_Tx_HiZ_Control_B, 0xFF}, + {MAX98927_Measurement_enables, 0x03}, + {MAX98927_PDM_Rx_Enable, 0x00}, + {MAX98927_AMP_volume_control, 0x38}, + {MAX98927_AMP_DSP_Config, 0x33}, + {MAX98927_DRE_Control, 0x01}, + {MAX98927_Speaker_Gain, 0x05}, + {MAX98927_SSM_Configuration, 0x85}, + {MAX98927_Boost_Control_0, 0x1c}, + {MAX98927_Boost_Control_1, 0x3f}, + {MAX98927_Meas_ADC_Base_Divide_MSByte, 0x00}, + {MAX98927_Meas_ADC_Base_Divide_LSByte, 0x00}, + {MAX98927_Meas_ADC_Thermal_Hysteresis, 0x00}, + {MAX98927_Env_Tracker_Vout_Headroom, 0x08}, + {MAX98927_Env_Tracker_Control, 0x01}, + {MAX98927_Brownout_enables, 0x00}, +}; + +int reg_mono_map[][2] = { + {MAX98927_Boost_Control_3, 0x01}, + {MAX98927_PCM_Tx_Channel_Sources_A, 0x01}, + {MAX98927_PCM_Rx_Enables_A, 0x03}, + {MAX98927_PCM_Tx_Enables_A, 0x03}, + {MAX98927_PCM_Tx_HiZ_Control_A, 0xFC}, + {MAX98927_PCM_to_speaker_monomix_A, 0x80}, + {MAX98927_PCM_to_speaker_monomix_B, 0x00}, +}; + +int reg_left_map[][2] = { + {MAX98927_Boost_Control_3, 0x01}, + {MAX98927_PCM_Tx_Channel_Sources_A, 0x00}, + {MAX98927_PCM_Rx_Enables_A, 0x01}, + {MAX98927_PCM_Tx_Enables_A, 0x01}, + {MAX98927_PCM_Tx_HiZ_Control_A, 0xFE}, + {MAX98927_PCM_to_speaker_monomix_A, 0x80}, + {MAX98927_PCM_to_speaker_monomix_B, 0x00}, +}; + +int reg_right_map[][2] = { + {MAX98927_Boost_Control_3, 0x09}, + {MAX98927_PCM_Tx_Channel_Sources_A, 0x11}, + {MAX98927_PCM_Rx_Enables_A, 0x02}, + {MAX98927_PCM_Tx_Enables_A, 0x02}, + {MAX98927_PCM_Tx_HiZ_Control_A, 0xFD}, + {MAX98927_PCM_to_speaker_monomix_A, 0x81}, + {MAX98927_PCM_to_speaker_monomix_B, 0x01}, +}; + +static bool max98927_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98927_Interrupt_Raw_1: + case MAX98927_Interrupt_Raw_2: + case MAX98927_Interrupt_Raw_3: + case MAX98927_Interrupt_State_1: + case MAX98927_Interrupt_State_2: + case MAX98927_Interrupt_State_3: + case MAX98927_Interrupt_Flag_1: + case MAX98927_Interrupt_Flag_2: + case MAX98927_Interrupt_Flag_3: + case MAX98927_Interrupt_Enable_1: + case MAX98927_Interrupt_Enable_2: + case MAX98927_Interrupt_Enable_3: + case MAX98927_IRQ_Control: + case MAX98927_Clock_monitor_enable: + case MAX98927_Watchdog_Control: + case MAX98927_Meas_ADC_Thermal_Warning_Threshhold: + case MAX98927_Meas_ADC_Thermal_Shutdown_Threshhold: + case MAX98927_Meas_ADC_Thermal_Hysteresis: + case MAX98927_Pin_Config: + case MAX98927_PCM_Rx_Enables_A: + case MAX98927_PCM_Rx_Enables_B: + case MAX98927_PCM_Tx_Enables_A: + case MAX98927_PCM_Tx_Enables_B: + case MAX98927_PCM_Tx_HiZ_Control_A: + case MAX98927_PCM_Tx_HiZ_Control_B: + case MAX98927_PCM_Tx_Channel_Sources_A: + case MAX98927_PCM_Tx_Channel_Sources_B: + case MAX98927_PCM_Mode_Config: + case MAX98927_PCM_Master_Mode: + case MAX98927_PCM_Clock_setup: + case MAX98927_PCM_Sample_rate_setup_1: + case MAX98927_PCM_Sample_rate_setup_2: + case MAX98927_PCM_to_speaker_monomix_A: + case MAX98927_PCM_to_speaker_monomix_B: + case MAX98927_ICC_RX_Enables_A: + case MAX98927_ICC_RX_Enables_B: + case MAX98927_ICC_TX_Enables_A: + case MAX98927_ICC_TX_Enables_B: + case MAX98927_ICC_Data_Order_Select: + case MAX98927_ICC_HiZ_Manual_Mode: + case MAX98927_ICC_TX_HiZ_Enables_A: + case MAX98927_ICC_TX_HiZ_Enables_B: + case MAX98927_ICC_Link_Enables: + case MAX98927_PDM_Tx_Enables: + case MAX98927_PDM_Tx_HiZ_Control: + case MAX98927_PDM_Tx_Control: + case MAX98927_PDM_Rx_Enable: + case MAX98927_AMP_volume_control: + case MAX98927_AMP_DSP_Config: + case MAX98927_Tone_Generator_and_DC_Config: + case MAX98927_DRE_Control: + case MAX98927_AMP_enables: + case MAX98927_Speaker_source_select: + case MAX98927_Speaker_Gain: + case MAX98927_SSM_Configuration: + case MAX98927_Measurement_enables: + case MAX98927_Measurement_DSP_Config: + case MAX98927_Boost_Control_0: + case MAX98927_Boost_Control_3: + case MAX98927_Boost_Control_1: + case MAX98927_Meas_ADC_Config: + case MAX98927_Meas_ADC_Base_Divide_MSByte: + case MAX98927_Meas_ADC_Base_Divide_LSByte: + case MAX98927_Meas_ADC_Chan_0_Divide: + case MAX98927_Meas_ADC_Chan_1_Divide: + case MAX98927_Meas_ADC_Chan_2_Divide: + case MAX98927_Meas_ADC_Chan_0_Filt_Config: + case MAX98927_Meas_ADC_Chan_1_Filt_Config: + case MAX98927_Meas_ADC_Chan_2_Filt_Config: + case MAX98927_Meas_ADC_Chan_0_Readback: + case MAX98927_Meas_ADC_Chan_1_Readback: + case MAX98927_Meas_ADC_Chan_2_Readback: + case MAX98927_Brownout_status: + case MAX98927_Brownout_enables: + case MAX98927_Brownout_level_infinite_hold: + case MAX98927_Brownout_level_hold: + case MAX98927_Brownout__level_1_threshold: + case MAX98927_Brownout__level_2_threshold: + case MAX98927_Brownout__level_3_threshold: + case MAX98927_Brownout__level_4_threshold: + case MAX98927_Brownout_threshold_hysterysis: + case MAX98927_Brownout_AMP_limiter_attack_release: + case MAX98927_Brownout_AMP_gain_attack_release: + case MAX98927_Brownout_AMP1_clip_mode: + case MAX98927_Brownout__level_1_current_limit: + case MAX98927_Brownout__level_1_amp_1_control_1: + case MAX98927_Brownout__level_1_amp_1_control_2: + case MAX98927_Brownout__level_1_amp_1_control_3: + case MAX98927_Brownout__level_2_current_limit: + case MAX98927_Brownout__level_2_amp_1_control_1: + case MAX98927_Brownout__level_2_amp_1_control_2: + case MAX98927_Brownout__level_2_amp_1_control_3: + case MAX98927_Brownout__level_3_current_limit: + case MAX98927_Brownout__level_3_amp_1_control_1: + case MAX98927_Brownout__level_3_amp_1_control_2: + case MAX98927_Brownout__level_3_amp_1_control_3: + case MAX98927_Brownout__level_4_current_limit: + case MAX98927_Brownout__level_4_amp_1_control_1: + case MAX98927_Brownout__level_4_amp_1_control_2: + case MAX98927_Brownout__level_4_amp_1_control_3: + case MAX98927_Env_Tracker_Vout_Headroom: + case MAX98927_Env_Tracker_Boost_Vout_Delay: + case MAX98927_Env_Tracker_Release_Rate: + case MAX98927_Env_Tracker_Hold_Rate: + case MAX98927_Env_Tracker_Control: + case MAX98927_Env_Tracker__Boost_Vout_ReadBack: + case MAX98927_Global_Enable: + case MAX98927_REV_ID: + return true; + default: + return false; + } +} + +static bool max98927_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98927_Interrupt_Raw_1: + case MAX98927_Interrupt_Raw_2: + case MAX98927_Interrupt_Raw_3: + case MAX98927_Interrupt_State_1: + case MAX98927_Interrupt_State_2: + case MAX98927_Interrupt_State_3: + case MAX98927_Interrupt_Flag_1: + case MAX98927_Interrupt_Flag_2: + case MAX98927_Interrupt_Flag_3: + case MAX98927_Meas_ADC_Chan_0_Readback: + case MAX98927_Meas_ADC_Chan_1_Readback: + case MAX98927_Meas_ADC_Chan_2_Readback: + case MAX98927_Brownout_status: + case MAX98927_Env_Tracker__Boost_Vout_ReadBack: + return true; + default: + return false; + } +} + +#define PKG_HEADER (48) +#define PAYLOAD_COUNT (256) + +typedef enum { + DSM_API_MONO_SPKER = 0x00000000, + DSM_API_STEREO_SPKER = 0x03000000, + + DSM_API_L_CHAN = 0x01000000, + DSM_API_R_CHAN = 0x02000000, + + DSM_API_CHANNEL_1 = 0x01000000, + DSM_API_CHANNEL_2 = 0x02000000, + DSM_API_CHANNEL_3 = 0x04000000, + DSM_API_CHANNEL_4 = 0x08000000, + DSM_API_CHANNEL_5 = 0x10000000, + DSM_API_CHANNEL_6 = 0x20000000, + DSM_API_CHANNEL_7 = 0x40000000, + DSM_API_CHANNEL_8 = 0x80000000, + + DSM_MAX_SUPPORTED_CHANNELS = 8 +} DSM_API_CHANNEL_ID; + +#define DSM_SET_MONO_PARAM(cmdId) ((cmdId&0x00FFFFFF)|DSM_API_MONO_SPKER) +#define DSM_SET_STEREO_PARAM(cmdId) ((cmdId&0x00FFFFFF)|DSM_API_STEREO_SPKER) +#define DSM_SET_LEFT_PARAM(cmdId) ((cmdId&0x00FFFFFF)|DSM_API_L_CHAN) +#define DSM_SET_RIGHT_PARAM(cmdId) ((cmdId&0x00FFFFFF)|DSM_API_R_CHAN) + +typedef struct dsm_params { + uint32_t mode; + uint32_t pcount; + uint32_t pdata[PAYLOAD_COUNT]; +} dsm_param_t; + + +static uint32_t gParam[PKG_HEADER+PAYLOAD_COUNT]; + +#ifdef F0_DETECT +static int f0_detect_open(struct inode *inode, struct file *filep) +{ + return 0; +} + +static ssize_t f0_detect_read(struct file *filep, char __user *buf, + size_t count, loff_t *ppos) +{ + int ret = 0; + char param[20]; + int fc_left = 0; + int fc_right = 0; + + if (*ppos > 1) { + return 0; + } + + snprintf(param, sizeof(param), "%d|%d", fc_left, fc_right); + + ret = copy_to_user(buf, param, strlen(param)); + if (ret != 0) { + pr_err("%s: copy_to_user failed - %d\n", __func__, ret); + return -EFAULT; + } + *ppos += strlen(param); + + pr_info("%s value:%s\n", __func__, param); + return strlen(param); +} + +static ssize_t f0_detect_write(struct file *filep, const char __user *buf, + size_t count, loff_t *ppos) +{ + int rc = 0; + char param[10]; + rc = copy_from_user(¶m, buf, count); + if (rc != 0) { + pr_err("%s: copy_from_user failed - %d\n", __func__, rc); + return rc; + } + pr_info("%s value:%s\n", __func__, param); + return count; +} + +static const struct file_operations f0_detect_ctrl_fops = { + .owner = THIS_MODULE, + .open = f0_detect_open, + .release = NULL, + .read = f0_detect_read, + .write = f0_detect_write, + .mmap = NULL, + .poll = NULL, + .fasync = NULL, + .llseek = NULL, +}; + +static struct miscdevice f0_detect_ctrl_miscdev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "smartpa_f0_detect", + .fops = &f0_detect_ctrl_fops +}; + +static int f0_detect_init(void) +{ + int result; + pr_info("%s\n", __func__); + result = misc_register(&f0_detect_ctrl_miscdev); + if (result != 0) { + pr_err("%s error:%d\n", __func__, result); + } + return result; +} + +static int f0_detect_deinit(void) +{ + int result; + pr_info("%s\n", __func__); + result = misc_deregister(&f0_detect_ctrl_miscdev); + return result; +} +#endif + +int max98927_wrapper_read(struct max98927_priv *max98927, bool speaker, + unsigned int reg, unsigned int *val) +{ + int ret = 0; + if (speaker == MAX98927L && max98927->left_i2c) + ret = regmap_read(max98927->regmap_l, reg, val); + if (speaker == MAX98927R && max98927->mono_stereo && max98927->right_i2c) + ret = regmap_read(max98927->regmap_r, reg, val); + return ret; +} + +void max98927_wrapper_write(struct max98927_priv *max98927, + unsigned int reg, unsigned int val) +{ + if (max98927->left_i2c) + regmap_write(max98927->regmap_l, reg, val); + if (max98927->mono_stereo && max98927->right_i2c) + regmap_write(max98927->regmap_r, reg, val); +} + +void max98927_wrap_update_bits(struct max98927_priv *max98927, + unsigned int reg, unsigned int mask, unsigned int val) +{ + if (max98927->left_i2c) + regmap_update_bits(max98927->regmap_l, reg, mask, val); + if (max98927->mono_stereo && max98927->right_i2c) + regmap_update_bits(max98927->regmap_r, reg, mask, val); +} + +static int max98927_reg_get_w(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int reg = mc->reg; + unsigned int shift = mc->shift; + int max = mc->max; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; + unsigned int val; + + max98927_wrapper_read(max98927, 0, reg, &val); + + val = (val >> shift) & mask; + + if (invert) + ucontrol->value.integer.value[0] = max - val; + else + ucontrol->value.integer.value[0] = val; + + return 0; +} + +static int max98927_reg_put_w(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int reg = mc->reg; + unsigned int shift = mc->shift; + int max = mc->max; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; + + unsigned int val = (ucontrol->value.integer.value[0] & mask); + if (invert) + val = max - val; + mask = mask << shift; + val = val << shift; + + max98927_wrap_update_bits(max98927, reg, mask, val); + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, reg, val); + return 0; +} +static int max98927_reg_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, unsigned int reg, + unsigned int mask, unsigned int shift) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int data; + + max98927_wrapper_read(max98927, 0, reg, &data); + ucontrol->value.integer.value[0] = + (data & mask) >> shift; + return 0; +} + +static int max98927_reg_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, unsigned int reg, + unsigned int mask, unsigned int shift) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + + unsigned int sel = ucontrol->value.integer.value[0]; + max98927_wrap_update_bits(max98927, reg, mask, sel << shift); + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, reg, sel); + return 0; +} + +static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + + pr_info("------%s------\n", __func__); + + pr_info("%s: fmt 0x%08X\n", __func__, fmt); + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + max98927_wrap_update_bits(max98927, MAX98927_PCM_Master_Mode, + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_Mask, + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_SLAVE); + break; + case SND_SOC_DAIFMT_CBM_CFM: + max98927->master = true; + max98927_wrap_update_bits(max98927, MAX98927_PCM_Master_Mode, + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_Mask, + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_MASTER); + break; + case SND_SOC_DAIFMT_CBS_CFM: + max98927_wrap_update_bits(max98927, MAX98927_PCM_Master_Mode, + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_Mask, + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_HYBRID); + default: + pr_info("DAI clock mode unsupported"); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + max98927_wrap_update_bits(max98927, MAX98927_PCM_Mode_Config, + MAX98927_PCM_Mode_Config_PCM_BCLKEDGE, + 0); + break; + case SND_SOC_DAIFMT_IB_NF: + max98927_wrap_update_bits(max98927, MAX98927_PCM_Mode_Config, + MAX98927_PCM_Mode_Config_PCM_BCLKEDGE, + MAX98927_PCM_Mode_Config_PCM_BCLKEDGE); + break; + default: + pr_info("DAI invert mode unsupported"); + return -EINVAL; + } + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + max98927->iface |= SND_SOC_DAIFMT_I2S; + max98927_wrap_update_bits(max98927, MAX98927_PCM_Mode_Config, + MAX98927_PCM_Mode_Config_PCM_FORMAT_Mask, + MAX98927_PCM_Mode_Config_PCM_FORMAT_I2S); + break; + case SND_SOC_DAIFMT_LEFT_J: + max98927->iface |= SND_SOC_DAIFMT_LEFT_J; + max98927_wrap_update_bits(max98927, MAX98927_PCM_Mode_Config, + MAX98927_PCM_Mode_Config_PCM_FORMAT_Mask, + MAX98927_PCM_Mode_Config_PCM_FORMAT_LEFT); + break; + default: + return -EINVAL; + } + return 0; +} + +/* codec MCLK rate in master mode */ +static const int rate_table[] = { + 5644800, 6000000, 6144000, 6500000, + 9600000, 11289600, 12000000, 12288000, + 13000000, 19200000, +}; + +static int max98927_set_clock(struct max98927_priv *max98927, + struct snd_pcm_hw_params *params) +{ + /* BCLK/LRCLK ratio calculation */ + int blr_clk_ratio = 2*max98927->ch_size; + int reg = MAX98927_PCM_Clock_setup; + int mask = MAX98927_PCM_Clock_setup_PCM_BSEL_Mask; + int value; + pr_info("------%s------\n", __func__); + + if (max98927->master) { + int i; + /* match rate to closest value */ + for (i = 0; i < ARRAY_SIZE(rate_table); i++) { + if (rate_table[i] >= max98927->sysclk) + break; + } + if (i == ARRAY_SIZE(rate_table)) { + pr_err("%s couldn't get the MCLK to match codec\n", __func__); + return -EINVAL; + } + max98927_wrap_update_bits(max98927, MAX98927_PCM_Master_Mode, + MAX98927_PCM_Master_Mode_PCM_MCLK_RATE_Mask, + i << MAX98927_PCM_Master_Mode_PCM_MCLK_RATE_SHIFT); + } + switch (blr_clk_ratio) { + case 32: + value = 2; + break; + case 48: + value = 3; + break; + case 64: + value = 4; + break; + default: + return -EINVAL; + } + max98927_wrap_update_bits(max98927, + reg, mask, value); + return 0; +} + +static int max98927_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int sampling_rate = 0; + pr_info("------%s------\n", __func__); + + switch (snd_pcm_format_width(params_format(params))) { + case 16: + max98927_wrap_update_bits(max98927, + MAX98927_PCM_Mode_Config, + MAX98927_PCM_Mode_Config_PCM_CHANSZ_16, + MAX98927_PCM_Mode_Config_PCM_CHANSZ_16); + max98927->ch_size = 16; + break; + case 24: + case 32: + max98927_wrap_update_bits(max98927, + MAX98927_PCM_Mode_Config, + MAX98927_PCM_Mode_Config_PCM_CHANSZ_32, + MAX98927_PCM_Mode_Config_PCM_CHANSZ_32); + max98927->ch_size = 32; + break; + default: + pr_err("%s: format unsupported %d", + __func__, params_format(params)); + goto err; + } + pr_info("%s: format supported %d", + __func__, params_format(params)); + + switch (params_rate(params)) { + case 8000: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_8000; + break; + case 11025: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_11025; + break; + case 12000: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_12000; + break; + case 16000: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_16000; + break; + case 22050: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_22050; + break; + case 24000: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_24000; + break; + case 32000: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_32000; + break; + case 44100: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_44100; + break; + case 48000: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_48000; + break; + default: + pr_err("%s rate %d not supported\n", __func__, params_rate(params)); + goto err; + } + /* set DAI_SR to correct LRCLK frequency */ + max98927_wrap_update_bits(max98927, MAX98927_PCM_Sample_rate_setup_1, + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_Mask, sampling_rate); + max98927_wrap_update_bits(max98927, MAX98927_PCM_Sample_rate_setup_2, + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_Mask, sampling_rate<<4); + max98927_wrap_update_bits(max98927, MAX98927_PCM_Sample_rate_setup_2, + MAX98927_PCM_Sample_rate_setup_2_IVADC_SR_Mask, sampling_rate); + return max98927_set_clock(max98927, params); +err: + return -EINVAL; +} + +#define MAX98927_RATES SNDRV_PCM_RATE_8000_48000 + +#define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static int max98927_dai_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = dai->codec; + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + pr_info("------%s------\n", __func__); + + pr_info("%s: clk_id %d, freq %d, dir %d\n", __func__, clk_id, freq, dir); + + max98927->sysclk = freq; + return 0; +} + +static int max98927_stream_mute(struct snd_soc_dai *codec_dai, int mute, int stream) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + struct dsm_params *params = (struct dsm_params *)&gParam[PKG_HEADER]; + + pr_info("%s--- stream %d, mute %d \n", __func__, stream, mute); + + if (!max98927) { + pr_err("%s ------ priv data null pointer\n", __func__); + return 0; + } + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (mute) { + params->pcount = 3; + params->pdata[0] = DSM_SET_LEFT_PARAM(99); + params->pdata[1] = 15; + params->pdata[2] = DSM_SET_LEFT_PARAM(100); + params->pdata[3] = 5000; + params->pdata[4] = DSM_SET_LEFT_PARAM(102); + params->pdata[5] = 1; + + usleep_range(20000, 20010); + pr_info("%s ------ disable max98927 \n", __func__); + max98927_wrap_update_bits(max98927, MAX98927_Global_Enable, 1, 0); + max98927_wrap_update_bits(max98927, MAX98927_AMP_enables, 1, 0); + } else { + max98927_wrap_update_bits(max98927, MAX98927_AMP_enables, 1, 1); + max98927_wrap_update_bits(max98927, MAX98927_Global_Enable, 1, 1); + } + } + + return 0; +} + + +static const struct snd_soc_dai_ops max98927_dai_ops = { + .set_sysclk = max98927_dai_set_sysclk, + .set_fmt = max98927_dai_set_fmt, + .hw_params = max98927_dai_hw_params, + .mute_stream = max98927_stream_mute, +}; + + +static int max98927_feedback_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + u32 ret = 0; + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + if (!max98927) { + pr_err("%s------priv data null pointer\n", __func__); + return ret; + } + pr_info("%s---feedback event %d\n", __func__, event); + switch (event) { + case SND_SOC_DAPM_POST_PMU: + max98927_wrapper_write(max98927, MAX98927_Measurement_enables, 0x3); + break; + case SND_SOC_DAPM_POST_PMD: + max98927_wrapper_write(max98927, MAX98927_Measurement_enables, 0x0); + break; + default: + break; + } + return ret; +} + + +static const struct snd_soc_dapm_widget max98927_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("iv_feedback", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT_E("iv_feedback_e", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0, + max98927_feedback_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_INPUT("BE_IN"), + SND_SOC_DAPM_OUTPUT("BE_OUT"), +}; + +static DECLARE_TLV_DB_SCALE(max98927_spk_tlv, 300, 300, 0); +static DECLARE_TLV_DB_SCALE(max98927_digital_tlv, -1600, 25, 0); + +static int max98927_spk_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = max98927->spk_gain; + pr_info("max98927_spk_gain_get: spk_gain setting returned %d\n", + (int) ucontrol->value.integer.value[0]); + + return 0; +} + +static int max98927_spk_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + pr_info("max98927_spk_gain_put: %d\n", sel); + + if (sel < ((1 << MAX98927_Speaker_Gain_Width) - 1)) { + max98927_wrap_update_bits(max98927, MAX98927_Speaker_Gain, + MAX98927_Speaker_Gain_SPK_PCM_GAIN_Mask, sel); + max98927->spk_gain = sel; + } + return 0; +} + +static int max98927_digital_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = max98927->digital_gain; + pr_info("%s: spk_gain setting returned %d\n", __func__, + (int) ucontrol->value.integer.value[0]); + return 0; +} + +static int max98927_digital_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + pr_info("max98927_digital_gain_put: %d\n", sel); + + if (sel <= ((1 << MAX98927_AMP_VOL_WIDTH) - 1)) { + max98927_wrap_update_bits(max98927, MAX98927_AMP_volume_control, + MAX98927_AMP_volume_control_AMP_VOL_Mask, sel); + max98927->digital_gain = sel; + } + return 0; +} + +static int max98927_boost_voltage_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_get(kcontrol, ucontrol, MAX98927_Boost_Control_0, + MAX98927_Boost_Control_0_BST_VOUT_Mask, 0); +} + +static int max98927_boost_voltage_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_put(kcontrol, ucontrol, MAX98927_Boost_Control_0, + MAX98927_Boost_Control_0_BST_VOUT_Mask, 0); +} + +static int max98927_boost_input_limit_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_get(kcontrol, ucontrol, MAX98927_Boost_Control_1, + MAX98927_Boost_Control_1_BST_ILIM_Mask, MAX98927_BST_ILIM_SHIFT); +} + +static int max98927_boost_input_limit_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_put(kcontrol, ucontrol, MAX98927_Boost_Control_1, + MAX98927_Boost_Control_1_BST_ILIM_Mask, MAX98927_BST_ILIM_SHIFT); +} + +static int max98927_spk_src_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_get(kcontrol, ucontrol, MAX98927_Speaker_source_select, + MAX98927_Speaker_source_select_SPK_SOURCE_Mask, 0); +} + +static int max98927_spk_src_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_put(kcontrol, ucontrol, MAX98927_Speaker_source_select, + MAX98927_Speaker_source_select_SPK_SOURCE_Mask, 0); +} + +static int max98927_mono_out_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_get(kcontrol, ucontrol, MAX98927_PCM_to_speaker_monomix_A, + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CH0_SOURCE_Mask, 0); +} + +static int max98927_mono_out_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_put(kcontrol, ucontrol, MAX98927_PCM_to_speaker_monomix_A, + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CH0_SOURCE_Mask, 0); +} + +static int max98927_mono_out_get_l(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int data = 0; + + if (max98927->left_i2c) { + regmap_read(max98927->regmap_l, MAX98927_PCM_to_speaker_monomix_A, &data); + ucontrol->value.integer.value[0] = + (data & MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CH0_SOURCE_Mask); + pr_info("%s: value:%d", __func__, data); + } + + return 0; +} + +static int max98927_mono_out_put_l(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + + if (max98927->left_i2c) { + regmap_update_bits(max98927->regmap_l, MAX98927_PCM_to_speaker_monomix_A, + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CH0_SOURCE_Mask, sel); + regmap_update_bits(max98927->regmap_l, MAX98927_PCM_Rx_Enables_A, + 0xf, sel+1); + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, MAX98927_PCM_to_speaker_monomix_A, sel); + } + + return 0; +} + +static int max98927_mono_out_get_r(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int data = 0; + + if (max98927->mono_stereo && max98927->right_i2c) { + regmap_read(max98927->regmap_r, MAX98927_PCM_to_speaker_monomix_A, &data); + ucontrol->value.integer.value[0] = + (data & MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CH0_SOURCE_Mask); + } + pr_info("%s: value:%d", __func__, data); + return 0; +} + +static int max98927_mono_out_put_r(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + if (max98927->mono_stereo && max98927->right_i2c) { + regmap_update_bits(max98927->regmap_r, MAX98927_PCM_to_speaker_monomix_A, + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CH0_SOURCE_Mask, sel); + regmap_update_bits(max98927->regmap_r, MAX98927_PCM_Rx_Enables_A, 0xf, sel+1); + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, MAX98927_PCM_to_speaker_monomix_A, sel); + } else { + pr_info("%s: mono mode not support!!\n", __func__); + } + return 0; +} + +static int max98927_feedback_en_get_l(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int data = 0; + + if (max98927->left_i2c) { + regmap_read(max98927->regmap_l, MAX98927_Measurement_enables, &data); + ucontrol->value.integer.value[0] = data; + pr_info("%s: value:%d", __func__, data); + } + + return 0; +} + +static int max98927_feedback_en_put_l(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + + if (max98927->left_i2c) { + regmap_write(max98927->regmap_l, MAX98927_Measurement_enables, sel); + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, MAX98927_Measurement_enables, sel); + } + return 0; +} + +static int max98927_feedback_en_get_r(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int data = 0; + + if (max98927->mono_stereo && max98927->right_i2c) { + regmap_read(max98927->regmap_r, MAX98927_Measurement_enables, &data); + ucontrol->value.integer.value[0] = data; + } + pr_info("%s: value:%d", __func__, data); + return 0; +} + +static int max98927_feedback_en_put_r(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + if (max98927->mono_stereo && max98927->right_i2c) { + regmap_write(max98927->regmap_r, MAX98927_Measurement_enables, sel); + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, MAX98927_Measurement_enables, sel); + } else { + pr_info("%s: mono mode not support!!\n", __func__); + } + return 0; +} + +static int max98927_left_channel_enable_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int data_global = 0; + int data_amp = 0; + + + if (max98927->left_i2c) { + regmap_read(max98927->regmap_l, MAX98927_Global_Enable, &data_global); + regmap_read(max98927->regmap_l, MAX98927_AMP_enables, &data_amp); + ucontrol->value.integer.value[0] = (data_global & MAX98927_Global_Enable_EN) + & (data_amp & MAX98927_AMP_enables_SPK_EN); + } + + pr_info("%s: value:%d", __func__, (int)ucontrol->value.integer.value[0]); + return 0; +} + +static int max98927_left_channel_enable_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + if (max98927->regmap_l && max98927->left_i2c) { + max98927->spk_mode &= ~0x1; + max98927->spk_mode |= sel; + + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, MAX98927_Global_Enable, sel); + } + return 0; +} + +static int max98927_right_channel_enable_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int data_global = 0; + int data_amp = 0; + + if (max98927->mono_stereo && max98927->right_i2c) { + regmap_read(max98927->regmap_r, MAX98927_Global_Enable, &data_global); + regmap_read(max98927->regmap_r, MAX98927_AMP_enables, &data_amp); + ucontrol->value.integer.value[0] = (data_global & MAX98927_Global_Enable_EN) + & (data_amp & MAX98927_AMP_enables_SPK_EN); + } + + pr_info("%s: value:%d", __func__, (int)ucontrol->value.integer.value[0]); + return 0; +} + +static int max98927_right_channel_enable_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + if (max98927->regmap_r && max98927->right_i2c) { + max98927->spk_mode &= ~0x2; + max98927->spk_mode |= sel<<0x1; + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, MAX98927_Global_Enable, sel); + } else { + pr_info("%s: mono mode not support!!\n", __func__); + } + return 0; +} + +static const char * const max98927_boost_voltage_text[] = { + "6.5V", "6.625V", "6.75V", "6.875V", "7V", "7.125V", "7.25V", "7.375V", + "7.5V", "7.625V", "7.75V", "7.875V", "8V", "8.125V", "8.25V", "8.375V", + "8.5V", "8.625V", "8.75V", "8.875V", "9V", "9.125V", "9.25V", "9.375V", + "9.5V", "9.625V", "9.75V", "9.875V", "10V" +}; + +static const char * const max98927_boost_current_limit_text[] = { + "1.0A", "1.1A", "1.2A", "1.3A", "1.4A", "1.5A", "1.6A", "1.7A", "1.8A", "1.9A", + "2.0A", "2.1A", "2.2A", "2.3A", "2.4A", "2.5A", "2.6A", "2.7A", "2.8A", "2.9A", + "3.0A", "3.1A", "3.2A", "3.3A", "3.4A", "3.5A", "3.6A", "3.7A", "3.8A", "3.9A", + "4.0A", "4.1A" +}; + +static const char * const max98927_speaker_source_text[] = { + "i2s", "reserved", "tone", "pdm" +}; + +static const char * const max98927_monomix_output_text[] = { + "ch_0", "ch_1", "ch_1_2_div" +}; +static const char * const max98927_feedback_switch_text[] = { + "OFF", "V_EN", "I_EN", "ON" +}; + +static const struct soc_enum max98927_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max98927_monomix_output_text), max98927_monomix_output_text), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max98927_speaker_source_text), max98927_speaker_source_text), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max98927_boost_voltage_text), max98927_boost_voltage_text), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max98927_feedback_switch_text), max98927_feedback_switch_text), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max98927_boost_current_limit_text), max98927_boost_current_limit_text), +}; + +static const struct snd_kcontrol_new max98927_snd_controls[] = { + SOC_SINGLE_EXT_TLV("Speaker Volume", MAX98927_Speaker_Gain, + 0, (1<dapm; + + pr_info("------%s------\n", __func__); + + max98927->codec = codec; + codec->control_data = max98927->regmap_l; + codec->cache_bypass = 1; + + if (max98927->left_i2c) { + if (max98927->mono_stereo) { + for (i = 0; i < sizeof(reg_left_map)/sizeof(reg_left_map[0]); i++) + regmap_write(max98927->regmap_l, reg_left_map[i][0], reg_left_map[i][1]); + } else{ + for (i = 0; i < sizeof(reg_mono_map)/sizeof(reg_mono_map[0]); i++) + regmap_write(max98927->regmap_l, reg_mono_map[i][0], reg_mono_map[i][1]); + } + } + if (max98927->mono_stereo && max98927->right_i2c) { + for (i = 0; i < sizeof(reg_right_map)/sizeof(reg_right_map[0]); i++) + regmap_write(max98927->regmap_r, reg_right_map[i][0], reg_right_map[i][1]); + } + for (i = 0; i < sizeof(reg_common_map)/sizeof(reg_common_map[0]); i++) + max98927_wrapper_write(max98927, reg_common_map[i][0], reg_common_map[i][1]); + + pr_info("%s: enter\n", __func__); + + max98927->codec = codec; + snd_soc_dapm_ignore_suspend(dapm, "BE_OUT"); + snd_soc_dapm_ignore_suspend(dapm, "BE_IN"); + snd_soc_dapm_ignore_suspend(dapm, "HiFi Playback"); + snd_soc_dapm_ignore_suspend(dapm, "HiFi Capture"); + + snd_soc_dapm_sync(dapm); + return 0; +} + +static const struct snd_soc_codec_driver soc_codec_dev_max98927 = { + .probe = max98927_probe, + .dapm_routes = max98927_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98927_audio_map), + .dapm_widgets = max98927_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98927_dapm_widgets), + .controls = max98927_snd_controls, + .num_controls = ARRAY_SIZE(max98927_snd_controls), +}; + +static const struct regmap_config max98927_regmap = { + .reg_bits = 16, + .val_bits = 8, + .max_register = MAX98927_REV_ID, + .readable_reg = max98927_readable_register, + .volatile_reg = max98927_volatile_register, + .cache_type = REGCACHE_RBTREE, +}; + +int max98927_get_i2c_states(void) +{ + return i2c_states; +} +EXPORT_SYMBOL(max98927_get_i2c_states); + +int probe_common(struct i2c_client *i2c, struct max98927_priv *max98927) +{ + int ret = -1, ret_l = -1, ret_r = -1, reg = 0; + + max98927->left_i2c = false; + max98927->right_i2c = false; + + ret_l = regmap_read(max98927->regmap_l, MAX98927_REV_ID, ®); + pr_info("max98927 L device version 0x%02X\n", reg); + if (ret_l == 0) { + max98927->left_i2c = true; + pr_info("max98927 L read ok.\n"); + } + reg = 0; + pr_info("max98927 R read enter.\n"); + if (max98927->mono_stereo) { + ret_r = regmap_read(max98927->regmap_r, MAX98927_REV_ID, ®); + pr_info("max98927 R device version 0x%02X\n", reg); + if (ret_r == 0) { + max98927->right_i2c = true; + pr_info("max98927 R read ok.\n"); + } + } + + if ((ret_l != 0) && (ret_r != 0)) { + pr_err("max98927 i2c connection error ret_l: %d ret_r:%d\n", ret_l, ret_r); + return ret_l; + } + dev_set_name(&i2c->dev, "%s", "max98927"); + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98927, + max98927_dai, ARRAY_SIZE(max98927_dai)); + if (ret < 0) { + pr_err("Failed to register codec: %d\n", ret); + if (max98927->regmap_l) + regmap_exit(max98927->regmap_l); + if (max98927->regmap_r) + regmap_exit(max98927->regmap_r); + kfree(max98927); + return ret; + } + i2c_states = 0; + + pr_info("max98927 driver probe end.\n"); + +#ifdef F0_DETECT + f0_detect_init(); +#endif + + return 0; +} + +static int max98927_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + static struct max98927_priv *max98927; + int ret = 0, value; + + + if (!max98927) { + max98927 = devm_kzalloc(&i2c->dev, + sizeof(*max98927), GFP_KERNEL); + if (!max98927) { + pr_info("------%s devm_kzalloc error!!\n", __func__); + return -ENOMEM; + } + } + max98927->dev = &i2c->dev; + pr_info("max98927 reset gpio requse name:%s------\n", i2c->name); + + max98927->reset_gpio_l = of_get_named_gpio(i2c->dev.of_node, "maxim,98927-reset-gpio", 0); + pr_info("reset_gpio_l:%d------\n", max98927->reset_gpio_l); + + if (max98927->reset_gpio_l > 0) { + ret = gpio_request(max98927->reset_gpio_l, "max_98927_reset"); + if (ret) { + pr_err("max98927_i2c_probe : failed to request rest gpio %d error:%d\n", + max98927->reset_gpio_l, ret); + gpio_free(max98927->reset_gpio_l); + return ret; + } + gpio_direction_output(max98927->reset_gpio_l, 0); + } + if (max98927->reset_gpio_l > 0) { + msleep(10); + gpio_direction_output(max98927->reset_gpio_l, 1); + msleep(5); + } + + i2c_set_clientdata(i2c, max98927); + + if (!of_property_read_u32(i2c->dev.of_node, "mono_stereo_mode", &value)) { + if (value > 1) { + pr_info("mono_stereo number is wrong:\n"); + } + max98927->mono_stereo = value; + } + + if (!of_property_read_u32(i2c->dev.of_node, "interleave_mode", &value)) { + if (value > 1) { + pr_info("interleave number is wrong:\n"); + } + max98927->interleave_mode = value; + } + /* by default we are assuming interleave mode */ + if (id->driver_data == MAX98927L) { + max98927->regmap_l = + devm_regmap_init_i2c(i2c, &max98927_regmap); + if (IS_ERR(max98927->regmap_l)) { + ret = PTR_ERR(max98927->regmap_l); + dev_err(&i2c->dev, + "Failed to allocate regmap_l: %d\n", ret); + } + + } else {/* check for second MAX98927 */ + if (id->driver_data == MAX98927R) { + max98927->regmap_r = + devm_regmap_init_i2c(i2c, &max98927_regmap); + if (IS_ERR(max98927->regmap_r)) { + ret = PTR_ERR(max98927->regmap_r); + dev_err(&i2c->dev, + "Failed to allocate regmap_r: %d\n", ret); + } + } + } + + if (max98927->mono_stereo) { + if (max98927->regmap_r && max98927->regmap_l) + ret = probe_common(i2c, max98927); + } else if (max98927->regmap_l && !max98927->mono_stereo) { + ret = probe_common(i2c, max98927); + } + + return ret; +} + +static int max98927_i2c_remove(struct i2c_client *client) +{ + struct max98927_priv *max98927 = i2c_get_clientdata(client); + if (max98927) { + if (max98927->dev == &client->dev) { + snd_soc_unregister_codec(&client->dev); + if (max98927->regmap_l) + regmap_exit(max98927->regmap_l); + if (max98927->regmap_r) + regmap_exit(max98927->regmap_r); + kfree(max98927); +#ifdef F0_DETECT + f0_detect_deinit(); +#endif + } + } + + return 0; +} + +static const struct i2c_device_id max98927_i2c_id[] = { + { "max98927L", MAX98927L }, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, max98927_i2c_id); + +static const struct of_device_id max98927_of_match[] = { + { .compatible = "maxim,max98927L", }, + { } +}; +MODULE_DEVICE_TABLE(of, max98927_of_match); + +static struct i2c_driver max98927_i2c_driver = { + .driver = { + .name = "max98927", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(max98927_of_match), + .pm = NULL, + }, + .probe = max98927_i2c_probe, + .remove = max98927_i2c_remove, + .id_table = max98927_i2c_id, +}; + +module_i2c_driver(max98927_i2c_driver) + +MODULE_DESCRIPTION("ALSA SoC MAX98927 driver"); +MODULE_AUTHOR("Anish kumar "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/max98927.h b/sound/soc/codecs/max98927.h new file mode 100644 index 0000000000000..ae8b6c8a6b55d --- /dev/null +++ b/sound/soc/codecs/max98927.h @@ -0,0 +1,1246 @@ +/* + * AnishBestPingPongerAliveButNotAsGoodAsMax.h + * + * Auto generated by Maxim Integrated, supporting revision + * Search for #BYHAND for flags on special cases to fix by hand + * #BYHAND width doesn't match: (this is usually when a bit has shorthand or formulaic descriptions) + * #BYHAND width >= 5: + */ +#ifndef __MAX98927_REGISTERDEFS_H +#define __MAX98927_REGISTERDEFS_H +#ifdef CONFIG_SND_SOC_MAXIM_DSM +#include +#endif /* CONFIG_SND_SOC_MAXIM_DSM */ + +#define MAX98927L 0 +#define MAX98927R 1 + +typedef enum { + + MAX98927_Interrupt_Raw_1 = 0x0001, + MAX98927_Interrupt_Raw_1_BDE_ACTIVE_END_RAW = (0x1 << 0), + MAX98927_Interrupt_Raw_1_BDE_ACTIVE_BGN_RAW = (0x1 << 1), + MAX98927_Interrupt_Raw_1_BDE_LEVEL_CHANGE_RAW = (0x1 << 2), + MAX98927_Interrupt_Raw_1_BDE_L8_RAW = (0x1 << 3), + MAX98927_Interrupt_Raw_1_THERMWARN_END_RAW = (0x1 << 4), + MAX98927_Interrupt_Raw_1_THERMWARN_START_RAW = (0x1 << 5), + MAX98927_Interrupt_Raw_1_THERMSHDN_END_RAW = (0x1 << 6), + MAX98927_Interrupt_Raw_1_THERMSHDN_START_RAW = (0x1 << 7), + + + MAX98927_Interrupt_Raw_2 = 0x0002, + MAX98927_Interrupt_Raw_2_WATCHDOGWARN_RAW = (0x1 << 0), + MAX98927_Interrupt_Raw_2_WATCHDOGFAIL_RAW = (0x1 << 1), + MAX98927_Interrupt_Raw_2_BOOSTCURRLIM_RAW = (0x1 << 2), + MAX98927_Interrupt_Raw_2_CLKSTOP_RAW = (0x1 << 3), + MAX98927_Interrupt_Raw_2_CLKSTART_RAW = (0x1 << 4), + MAX98927_Interrupt_Raw_2_MEASADC_END_RAW = (0x1 << 5), + MAX98927_Interrupt_Raw_2_PWRDN_DONE_RAW = (0x1 << 6), + MAX98927_Interrupt_Raw_2_PWRUP_DONE_RAW = (0x1 << 7), + + + MAX98927_Interrupt_Raw_3 = 0x0003, + MAX98927_Interrupt_Raw_3_PWRUP_FAIL_RAW = (0x1 << 0), + MAX98927_Interrupt_Raw_3_AUTH_DONE_RAW = (0x1 << 1), + MAX98927_Interrupt_Raw_3_SPK_OVC_RAW = (0x1 << 2), + MAX98927_Interrupt_Raw_3_BST_UVLO_RAW = (0x1 << 3), + + + MAX98927_Interrupt_State_1 = 0x0004, + MAX98927_Interrupt_State_1_BDE_ACTIVE_END_STATE = (0x1 << 0), + MAX98927_Interrupt_State_1_BDE_ACTIVE_BGN_STATE = (0x1 << 1), + MAX98927_Interrupt_State_1_BDE_LEVEL_CHANGE_STATE = (0x1 << 2), + MAX98927_Interrupt_State_1_BDE_L8_STATE = (0x1 << 3), + MAX98927_Interrupt_State_1_THERMWARN_END_STATE = (0x1 << 4), + MAX98927_Interrupt_State_1_THERMWARN_START_STATE = (0x1 << 5), + MAX98927_Interrupt_State_1_THERMSHDN_END_STATE = (0x1 << 6), + MAX98927_Interrupt_State_1_THERMSHDN_START_STATE = (0x1 << 7), + + + MAX98927_Interrupt_State_2 = 0x0005, + MAX98927_Interrupt_State_2_WATCHDOGWARN_STATE = (0x1 << 0), + MAX98927_Interrupt_State_2_WATCHDOGFAIL_STATE = (0x1 << 1), + MAX98927_Interrupt_State_2_BOOSTCURRLIM_STATE = (0x1 << 2), + MAX98927_Interrupt_State_2_CLKSTOP_STATE = (0x1 << 3), + MAX98927_Interrupt_State_2_CLKSTART_STATE = (0x1 << 4), + MAX98927_Interrupt_State_2_MEASADC_END_STATE = (0x1 << 5), + MAX98927_Interrupt_State_2_PWRDN_DONE_STATE = (0x1 << 6), + MAX98927_Interrupt_State_2_PWRUP_DONE_STATE = (0x1 << 7), + + + MAX98927_Interrupt_State_3 = 0x0006, + MAX98927_Interrupt_State_3_PWRUP_FAIL_STATE = (0x1 << 0), + MAX98927_Interrupt_State_3_AUTH_DONE_STATE = (0x1 << 1), + MAX98927_Interrupt_State_3_SPK_OVC_STATE = (0x1 << 2), + MAX98927_Interrupt_State_3_BST_UVLO_STATE = (0x1 << 3), + + + MAX98927_Interrupt_Flag_1 = 0x0007, + MAX98927_Interrupt_Flag_1_BDE_ACTIVE_END_FLAG = (0x1 << 0), + MAX98927_Interrupt_Flag_1_BDE_ACTIVE_BGN_FLAG = (0x1 << 1), + MAX98927_Interrupt_Flag_1_BDE_LEVEL_CHANGE_FLAG = (0x1 << 2), + MAX98927_Interrupt_Flag_1_BDE_L8_FLAG = (0x1 << 3), + MAX98927_Interrupt_Flag_1_THERMWARN_END_FLAG = (0x1 << 4), + MAX98927_Interrupt_Flag_1_THERMWARN_START_FLAG = (0x1 << 5), + MAX98927_Interrupt_Flag_1_THERMSHDN_END_FLAG = (0x1 << 6), + MAX98927_Interrupt_Flag_1_THERMSHDN_START_FLAG = (0x1 << 7), + + + MAX98927_Interrupt_Flag_2 = 0x0008, + MAX98927_Interrupt_Flag_2_WATCHDOGWARN_FLAG = (0x1 << 0), + MAX98927_Interrupt_Flag_2_WATCHDOGFAIL_FLAG = (0x1 << 1), + MAX98927_Interrupt_Flag_2_BOOSTCURRLIM_FLAG = (0x1 << 2), + MAX98927_Interrupt_Flag_2_CLKSTOP_FLAG = (0x1 << 3), + MAX98927_Interrupt_Flag_2_CLKSTART_FLAG = (0x1 << 4), + MAX98927_Interrupt_Flag_2_MEASADC_END_FLAG = (0x1 << 5), + MAX98927_Interrupt_Flag_2_PWRDN_DONE_FLAG = (0x1 << 6), + MAX98927_Interrupt_Flag_2_PWRUP_DONE_FLAG = (0x1 << 7), + + + MAX98927_Interrupt_Flag_3 = 0x0009, + MAX98927_Interrupt_Flag_3_PWRUP_FAIL_FLAG = (0x1 << 0), + MAX98927_Interrupt_Flag_3_AUTH_DONE_FLAG = (0x1 << 1), + MAX98927_Interrupt_Flag_3_SPK_OVC_FLAG = (0x1 << 2), + MAX98927_Interrupt_Flag_3_BST_UVLO_FLAG = (0x1 << 3), + + + MAX98927_Interrupt_Enable_1 = 0x000a, + MAX98927_Interrupt_Enable_1_BDE_ACTIVE_END_EN = (0x1 << 0), + MAX98927_Interrupt_Enable_1_BDE_ACTIVE_BGN_EN = (0x1 << 1), + MAX98927_Interrupt_Enable_1_BDE_LEVEL_CHANGE_EN = (0x1 << 2), + MAX98927_Interrupt_Enable_1_BDE_L8_EN = (0x1 << 3), + MAX98927_Interrupt_Enable_1_THERMWARN_END_EN = (0x1 << 4), + MAX98927_Interrupt_Enable_1_THERMWARN_START_EN = (0x1 << 5), + MAX98927_Interrupt_Enable_1_THERMSHDN_END_EN = (0x1 << 6), + MAX98927_Interrupt_Enable_1_THERMSHDN_START_EN = (0x1 << 7), + + + MAX98927_Interrupt_Enable_2 = 0x000b, + MAX98927_Interrupt_Enable_2_WATCHDOGWARN_EN = (0x1 << 0), + MAX98927_Interrupt_Enable_2_WATCHDOGFAIL_EN = (0x1 << 1), + MAX98927_Interrupt_Enable_2_BOOSTCURRLIM_EN = (0x1 << 2), + MAX98927_Interrupt_Enable_2_CLKSTOP_EN = (0x1 << 3), + MAX98927_Interrupt_Enable_2_CLKSTART_EN = (0x1 << 4), + MAX98927_Interrupt_Enable_2_MEASADC_END_EN = (0x1 << 5), + MAX98927_Interrupt_Enable_2_PWRDN_DONE_EN = (0x1 << 6), + MAX98927_Interrupt_Enable_2_PWRUP_DONE_EN = (0x1 << 7), + + + MAX98927_Interrupt_Enable_3 = 0x000c, + MAX98927_Interrupt_Enable_3_PWRUP_FAIL_EN = (0x1 << 0), + MAX98927_Interrupt_Enable_3_AUTH_DONE_EN = (0x1 << 1), + MAX98927_Interrupt_Enable_3_SPK_OVC_EN = (0x1 << 2), + MAX98927_Interrupt_Enable_3_BST_UVLO_EN = (0x1 << 3), + + + MAX98927_Interrupt_Flag_Clear_1 = 0x000d, + MAX98927_Interrupt_Flag_Clear_1_BDE_ACTIVE_END_CLR = (0x1 << 0), + MAX98927_Interrupt_Flag_Clear_1_BDE_ACTIVE_BGN_CLR = (0x1 << 1), + MAX98927_Interrupt_Flag_Clear_1_BDE_LEVEL_CHANGE_CLR = (0x1 << 2), + MAX98927_Interrupt_Flag_Clear_1_BDE_L8_CLR = (0x1 << 3), + MAX98927_Interrupt_Flag_Clear_1_THERMWARN_END_CLR = (0x1 << 4), + MAX98927_Interrupt_Flag_Clear_1_THERMWARN_START_CLR = (0x1 << 5), + MAX98927_Interrupt_Flag_Clear_1_THERMSHDN_END_CLR = (0x1 << 6), + MAX98927_Interrupt_Flag_Clear_1_THERMSHDN_START_CLR = (0x1 << 7), + + + MAX98927_Interrupt_Flag_Clear_2 = 0x000e, + MAX98927_Interrupt_Flag_Clear_2_WATCHDOGWARN_CLR = (0x1 << 0), + MAX98927_Interrupt_Flag_Clear_2_WATCHDOGFAIL_CLR = (0x1 << 1), + MAX98927_Interrupt_Flag_Clear_2_BOOSTCURRLIM_CLR = (0x1 << 2), + MAX98927_Interrupt_Flag_Clear_2_CLKSTOP_CLR = (0x1 << 3), + MAX98927_Interrupt_Flag_Clear_2_CLKSTART_CLR = (0x1 << 4), + MAX98927_Interrupt_Flag_Clear_2_MEASADC_END_CLR = (0x1 << 5), + MAX98927_Interrupt_Flag_Clear_2_PWRDN_DONE_CLR = (0x1 << 6), + MAX98927_Interrupt_Flag_Clear_2_PWRUP_DONE_CLR = (0x1 << 7), + + + MAX98927_Interrupt_Flag_Clear_3 = 0x000f, + MAX98927_Interrupt_Flag_Clear_3_PWRUP_FAIL_CLR = (0x1 << 0), + MAX98927_Interrupt_Flag_Clear_3_AUTH_DONE_CLR = (0x1 << 1), + MAX98927_Interrupt_Flag_Clear_3_SPK_OVC_CLR = (0x1 << 2), + MAX98927_Interrupt_Flag_Clear_3_BST_UVLO_CLR = (0x1 << 3), + + + MAX98927_IRQ_Control = 0x0010, + MAX98927_IRQ_Control_IRQ_EN = (0x1 << 0), + MAX98927_IRQ_Control_IRQ_POL = (0x1 << 1), + MAX98927_IRQ_Control_IRQ_MODE = (0x1 << 2), + + + MAX98927_Clock_monitor_enable = 0x0011, + MAX98927_Clock_monitor_enable_CMON_ENA = (0x1 << 0), + MAX98927_Clock_monitor_enable_CMON_AUTORESTART_ENA = (0x1 << 1), + + + MAX98927_Watchdog_Control = 0x0012, + MAX98927_Watchdog_Control_WDT_ENA = (0x1 << 0), + MAX98927_Watchdog_Control_WDT_MODE = (0x1 << 1), + MAX98927_Watchdog_Control_WDT_TO_SEL_Mask = (0x3 << 2), + + MAX98927_Watchdog_Control_WDT_TO_SEL_5 = (0x0 << 2), + MAX98927_Watchdog_Control_WDT_TO_SEL_10 = (0x1 << 2), + MAX98927_Watchdog_Control_WDT_TO_SEL_35 = (0x2 << 2), + MAX98927_Watchdog_Control_WDT_TO_SEL_50 = (0x3 << 2), + MAX98927_Watchdog_Control_WDT_HW_SOURCE = (0x1 << 4), + + + MAX98927_Watchdog_SW_Reset = 0x0013, + + MAX98927_Watchdog_SW_Reset_WDT_SW_RST_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Thermal_Warning_Threshhold = 0x0014, + + MAX98927_Meas_ADC_Thermal_Warning_Threshhold_MEAS_ADC_WARN_THRESH_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Thermal_Shutdown_Threshhold = 0x0015, + + MAX98927_Meas_ADC_Thermal_Shutdown_Threshhold_MEAS_ADC_SHDN_THRESH_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Thermal_Hysteresis = 0x0016, + + MAX98927_Meas_ADC_Thermal_Hysteresis_MEAS_ADC_THERM_HYST_Mask = (0x1f << 0), + + + MAX98927_Pin_Config = 0x0017, + MAX98927_Pin_Config_DOUT_DRV_Mask = (0x3 << 0), + + + MAX98927_Pin_Config_DOUT_DRV_01 = (0x0 << 0), + MAX98927_Pin_Config_DOUT_DRV_11 = (0x2 << 0), + MAX98927_Pin_Config_BCLK_DRV_Mask = (0x3 << 2), + + + MAX98927_Pin_Config_BCLK_DRV_01 = (0x0 << 2), + MAX98927_Pin_Config_BCLK_DRV_11 = (0x2 << 2), + MAX98927_Pin_Config_LRCLK_DRV_Mask = (0x3 << 4), + + + MAX98927_Pin_Config_LRCLK_DRV_01 = (0x0 << 4), + MAX98927_Pin_Config_LRCLK_DRV_11 = (0x2 << 4), + MAX98927_Pin_Config_ICC_DRV_Mask = (0x3 << 6), + + + MAX98927_Pin_Config_ICC_DRV_01 = (0x0 << 6), + MAX98927_Pin_Config_ICC_DRV_11 = (0x2 << 6), + + + MAX98927_PCM_Rx_Enables_A = 0x0018, + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH0_EN = (0x1 << 0), + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH1_EN = (0x1 << 1), + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH2_EN = (0x1 << 2), + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH3_EN = (0x1 << 3), + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH4_EN = (0x1 << 4), + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH5_EN = (0x1 << 5), + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH6_EN = (0x1 << 6), + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH7_EN = (0x1 << 7), + + + MAX98927_PCM_Rx_Enables_B = 0x0019, + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH8_EN = (0x1 << 0), + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH9_EN = (0x1 << 1), + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH10_EN = (0x1 << 2), + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH11_EN = (0x1 << 3), + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH12_EN = (0x1 << 4), + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH13_EN = (0x1 << 5), + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH14_EN = (0x1 << 6), + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH15_EN = (0x1 << 7), + + + MAX98927_PCM_Tx_Enables_A = 0x001a, + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH0_EN = (0x1 << 0), + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH1_EN = (0x1 << 1), + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH2_EN = (0x1 << 2), + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH3_EN = (0x1 << 3), + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH4_EN = (0x1 << 4), + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH5_EN = (0x1 << 5), + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH6_EN = (0x1 << 6), + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH7_EN = (0x1 << 7), + + + MAX98927_PCM_Tx_Enables_B = 0x001b, + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH8_EN = (0x1 << 0), + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH9_EN = (0x1 << 1), + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH10_EN = (0x1 << 2), + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH11_EN = (0x1 << 3), + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH12_EN = (0x1 << 4), + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH13_EN = (0x1 << 5), + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH14_EN = (0x1 << 6), + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH15_EN = (0x1 << 7), + + + MAX98927_PCM_Tx_HiZ_Control_A = 0x001c, + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH0_HIZ = (0x1 << 0), + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH1_HIZ = (0x1 << 1), + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH2_HIZ = (0x1 << 2), + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH3_HIZ = (0x1 << 3), + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH4_HIZ = (0x1 << 4), + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH5_HIZ = (0x1 << 5), + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH6_HIZ = (0x1 << 6), + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH7_HIZ = (0x1 << 7), + + + MAX98927_PCM_Tx_HiZ_Control_B = 0x001d, + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH8_HIZ = (0x1 << 0), + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH9_HIZ = (0x1 << 1), + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH10_HIZ = (0x1 << 2), + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH11_HIZ = (0x1 << 3), + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH12_HIZ = (0x1 << 4), + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH13_HIZ = (0x1 << 5), + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH14_HIZ = (0x1 << 6), + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH15_HIZ = (0x1 << 7), + + + MAX98927_PCM_Tx_Channel_Sources_A = 0x001e, + MAX98927_PCM_Tx_Channel_Sources_A_PCM_IVADC_V_DEST_Mask = (0xf << 0), + + + MAX98927_PCM_Tx_Channel_Sources_A_PCM_IVADC_I_DEST_Mask = (0xf << 4), + + + + + MAX98927_PCM_Tx_Channel_Sources_B = 0x001f, + MAX98927_PCM_Tx_Channel_Sources_B_PCM_AMP_DSP_DEST_Mask = (0xf << 0), + + + + + MAX98927_PCM_Mode_Config = 0x0020, + MAX98927_PCM_Mode_Config_PCM_TX_EXTRA_HIZ = (0x1 << 0), + MAX98927_PCM_Mode_Config_PCM_CHANSEL = (0x1 << 1), + MAX98927_PCM_Mode_Config_PCM_BCLKEDGE = (0x1 << 2), + MAX98927_PCM_Mode_Config_PCM_FORMAT_Mask = (0x7 << 3), + + + MAX98927_PCM_Mode_Config_PCM_FORMAT_I2S = (0x0 << 3), + MAX98927_PCM_Mode_Config_PCM_FORMAT_LEFT = (0x1 << 3), + MAX98927_PCM_Mode_Config_PCM_FORMAT_TDM_0 = (0x3 << 3), + MAX98927_PCM_Mode_Config_PCM_FORMAT_TDM_1 = (0x4 << 3), + MAX98927_PCM_Mode_Config_PCM_FORMAT_TDM_2 = (0x5 << 3), + MAX98927_PCM_Mode_Config_PCM_FORMAT_ = (0x6 << 3), + MAX98927_PCM_Mode_Config_PCM_CHANSZ_Mask = (0x3 << 6), + + + MAX98927_PCM_Mode_Config_PCM_CHANSZ_16 = (0x1 << 6), + MAX98927_PCM_Mode_Config_PCM_CHANSZ_24 = (0x2 << 6), + MAX98927_PCM_Mode_Config_PCM_CHANSZ_32 = (0x3 << 6), + + + MAX98927_PCM_Master_Mode = 0x0021, + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_Mask = (0x3 << 0), + + + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_SLAVE = (0x0 << 0), + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_MASTER = (0x3 << 0), + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_HYBRID = (0x1 << 0), + MAX98927_PCM_Master_Mode_PCM_MCLK_RATE_Mask = (0xf << 2), + + + MAX98927_PCM_Master_Mode_PCM_CLK_SOURCE = (0x1 << 6), + + + MAX98927_PCM_Clock_setup = 0x0022, + MAX98927_PCM_Clock_setup_PCM_BSEL_Mask = (0xf << 0), + + + MAX98927_PCM_Clock_setup_PCM_MSEL_Mask = (0xf << 4), + + + + + MAX98927_PCM_Sample_rate_setup_1 = 0x0023, + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_Mask = (0xf << 0), + + + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_8000 = (0x0 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_11025 = (0x1 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_12000 = (0x2 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_16000 = (0x3 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_22050 = (0x4 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_24000 = (0x5 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_32000 = (0x6 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_44100 = (0x7 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_48000 = (0x8 << 0), + + + MAX98927_PCM_Sample_rate_setup_2 = 0x0024, + MAX98927_PCM_Sample_rate_setup_2_IVADC_SR_Mask = (0xf << 0), + + + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_Mask = (0xf << 4), + + + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_0001 = (0x0 << 4), + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_0011 = (0x2 << 4), + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_0101 = (0x4 << 4), + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_0111 = (0x6 << 4), + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_1001 = (0x8 << 4), + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_1011 = (0xa << 4), + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_1101 = (0xc << 4), + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_ = (0xf << 4), + + + MAX98927_PCM_to_speaker_monomix_A = 0x0025, + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CH0_SOURCE_Mask = (0xf << 0), + + + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CFG_Mask = (0x3 << 6), + + + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CFG_1 = (0x0 << 6), + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CFG_3 = (0x0 << 6), + + + MAX98927_PCM_to_speaker_monomix_B = 0x0026, + MAX98927_PCM_to_speaker_monomix_B_DMONOMIX_CH1_SOURCE_Mask = (0xf << 0), + + + + + MAX98927_ICC_RX_Enables_A = 0x0027, + MAX98927_ICC_RX_Enables_A_ICC_RX_CH0_EN = (0x1 << 0), + MAX98927_ICC_RX_Enables_A_ICC_RX_CH1_EN = (0x1 << 1), + MAX98927_ICC_RX_Enables_A_ICC_RX_CH2_EN = (0x1 << 2), + MAX98927_ICC_RX_Enables_A_ICC_RX_CH3_EN = (0x1 << 3), + MAX98927_ICC_RX_Enables_A_ICC_RX_CH4_EN = (0x1 << 4), + MAX98927_ICC_RX_Enables_A_ICC_RX_CH5_EN = (0x1 << 5), + MAX98927_ICC_RX_Enables_A_ICC_RX_CH6_EN = (0x1 << 6), + MAX98927_ICC_RX_Enables_A_ICC_RX_CH7_EN = (0x1 << 7), + + + MAX98927_ICC_RX_Enables_B = 0x0028, + MAX98927_ICC_RX_Enables_B_ICC_RX_CH8_EN = (0x1 << 0), + MAX98927_ICC_RX_Enables_B_ICC_RX_CH9_EN = (0x1 << 1), + MAX98927_ICC_RX_Enables_B_ICC_RX_CH10_EN = (0x1 << 2), + MAX98927_ICC_RX_Enables_B_ICC_RX_CH11_EN = (0x1 << 3), + MAX98927_ICC_RX_Enables_B_ICC_RX_CH12_EN = (0x1 << 4), + MAX98927_ICC_RX_Enables_B_ICC_RX_CH13_EN = (0x1 << 5), + MAX98927_ICC_RX_Enables_B_ICC_RX_CH14_EN = (0x1 << 6), + MAX98927_ICC_RX_Enables_B_ICC_RX_CH15_EN = (0x1 << 7), + + + MAX98927_ICC_TX_Enables_A = 0x002b, + MAX98927_ICC_TX_Enables_A_ICC_TX_CH0_EN = (0x1 << 0), + MAX98927_ICC_TX_Enables_A_ICC_TX_CH1_EN = (0x1 << 1), + MAX98927_ICC_TX_Enables_A_ICC_TX_CH2_EN = (0x1 << 2), + MAX98927_ICC_TX_Enables_A_ICC_TX_CH3_EN = (0x1 << 3), + MAX98927_ICC_TX_Enables_A_ICC_TX_CH4_EN = (0x1 << 4), + MAX98927_ICC_TX_Enables_A_ICC_TX_CH5_EN = (0x1 << 5), + MAX98927_ICC_TX_Enables_A_ICC_TX_CH6_EN = (0x1 << 6), + MAX98927_ICC_TX_Enables_A_ICC_TX_CH7_EN = (0x1 << 7), + + + MAX98927_ICC_TX_Enables_B = 0x002c, + MAX98927_ICC_TX_Enables_B_ICC_TX_CH8_EN = (0x1 << 0), + MAX98927_ICC_TX_Enables_B_ICC_TX_CH9_EN = (0x1 << 1), + MAX98927_ICC_TX_Enables_B_ICC_TX_CH10_EN = (0x1 << 2), + MAX98927_ICC_TX_Enables_B_ICC_TX_CH11_EN = (0x1 << 3), + MAX98927_ICC_TX_Enables_B_ICC_TX_CH12_EN = (0x1 << 4), + MAX98927_ICC_TX_Enables_B_ICC_TX_CH13_EN = (0x1 << 5), + MAX98927_ICC_TX_Enables_B_ICC_TX_CH14_EN = (0x1 << 6), + MAX98927_ICC_TX_Enables_B_ICC_TX_CH15_EN = (0x1 << 7), + + + MAX98927_ICC_Data_Order_Select = 0x002d, + MAX98927_ICC_Data_Order_Select_ICC_DRIVE_MODE = (0x1 << 3), + + + MAX98927_ICC_HiZ_Manual_Mode = 0x002e, + MAX98927_ICC_HiZ_Manual_Mode_ICC_TX_HIZ_MANUAL = (0x1 << 0), + MAX98927_ICC_HiZ_Manual_Mode_ICC_TX_EXTRA_HIZ = (0x1 << 1), + + + MAX98927_ICC_TX_HiZ_Enables_A = 0x002f, + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH0_HIZ = (0x1 << 0), + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH1_HIZ = (0x1 << 1), + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH2_HIZ = (0x1 << 2), + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH3_HIZ = (0x1 << 3), + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH4_HIZ = (0x1 << 4), + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH5_HIZ = (0x1 << 5), + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH6_HIZ = (0x1 << 6), + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH7_HIZ = (0x1 << 7), + + + MAX98927_ICC_TX_HiZ_Enables_B = 0x0030, + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH8_HIZ = (0x1 << 0), + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH9_HIZ = (0x1 << 1), + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH10_HIZ = (0x1 << 2), + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH11_HIZ = (0x1 << 3), + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH12_HIZ = (0x1 << 4), + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH13_HIZ = (0x1 << 5), + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH14_HIZ = (0x1 << 6), + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH15_HIZ = (0x1 << 7), + + + MAX98927_ICC_Link_Enables = 0x0031, + MAX98927_ICC_Link_Enables_ICC_LINK_EN = (0x1 << 1), + + + MAX98927_PDM_Tx_Enables = 0x0032, + MAX98927_PDM_Tx_Enables_PDM_TX_EN = (0x1 << 0), + MAX98927_PDM_Tx_Enables_PDM_TX_CLK_DIV2 = (0x1 << 1), + + + MAX98927_PDM_Tx_HiZ_Control = 0x0033, + MAX98927_PDM_Tx_HiZ_Control_PDM_TX_HIZ = (0x1 << 0), + + + MAX98927_PDM_Tx_Control = 0x0034, + MAX98927_PDM_Tx_Control_PDM_TX_CH0_SOURCE = (0x1 << 0), + MAX98927_PDM_Tx_Control_PDM_TX_CH1_SOURCE = (0x1 << 1), + + + MAX98927_PDM_Rx_Enable = 0x0035, + MAX98927_PDM_Rx_Enable_PDM_RX_EN = (0x1 << 0), + MAX98927_PDM_Rx_Enable_PDM_DSP_EN = (0x1 << 1), + MAX98927_PDM_Rx_Enable_PDM_DITH_EN = (0x1 << 2), + MAX98927_PDM_Rx_Enable_PDM_RX_CH_SEL = (0x1 << 3), + MAX98927_PDM_Rx_Enable_PDM_FIFO_RDY_LVL_Mask = (0xf << 4), + + + + + MAX98927_AMP_volume_control = 0x0036, + + MAX98927_AMP_volume_control_AMP_VOL_Mask = (0x7f << 0), + MAX98927_AMP_volume_control_AMP_VOL_SEL = (0x1 << 7), + + + MAX98927_AMP_DSP_Config = 0x0037, + MAX98927_AMP_DSP_Config_AMP_DCBLK_EN = (0x1 << 0), + MAX98927_AMP_DSP_Config_AMP_DITH_EN = (0x1 << 1), + MAX98927_AMP_DSP_Config_DAC_HALF_REF_CURRENT = (0x1 << 2), + MAX98927_AMP_DSP_Config_DAC_DOUBLE_RFB = (0x1 << 3), + MAX98927_AMP_DSP_Config_AMP_VOL_RMP_BYPASS = (0x1 << 4), + MAX98927_AMP_DSP_Config_DAC_INVERT = (0x1 << 5), + + + MAX98927_Tone_Generator_and_DC_Config = 0x0038, + MAX98927_Tone_Generator_and_DC_Config_TONE_CONFIG_Mask = (0xf << 0), + + + + + MAX98927_DRE_Control = 0x0039, + MAX98927_DRE_Control_DRE_EN = (0x1 << 0), + + + MAX98927_AMP_enables = 0x003a, + MAX98927_AMP_enables_SPK_EN = (0x1 << 0), + + + MAX98927_Speaker_source_select = 0x003b, + MAX98927_Speaker_source_select_SPK_SOURCE_Mask = (0x3 << 0), + + + MAX98927_Speaker_source_select_SPK_SOURCE_01 = (0x0 << 0), + MAX98927_Speaker_source_select_SPK_SOURCE_11 = (0x2 << 0), + + + MAX98927_Speaker_Gain = 0x003c, + MAX98927_Speaker_Gain_SPK_PCM_GAIN_Mask = (0x7 << 0), + + + MAX98927_Speaker_Gain_SPK_PCM_GAIN_001 = (0x0 << 0), + MAX98927_Speaker_Gain_SPK_PCM_GAIN_011 = (0x2 << 0), + MAX98927_Speaker_Gain_SPK_PCM_GAIN_101 = (0x4 << 0), + MAX98927_Speaker_Gain_SPK_PCM_GAIN_111 = (0x6 << 0), + MAX98927_Speaker_Gain_SPK_PDM_GAIN_Mask = (0x7 << 4), + + + MAX98927_Speaker_Gain_SPK_PDM_GAIN_001 = (0x0 << 4), + MAX98927_Speaker_Gain_SPK_PDM_GAIN_011 = (0x2 << 4), + MAX98927_Speaker_Gain_SPK_PDM_GAIN_101 = (0x4 << 4), + MAX98927_Speaker_Gain_SPK_PDM_GAIN_111 = (0x6 << 4), + + + MAX98927_SSM_Configuration = 0x003d, + MAX98927_SSM_Configuration_SSM_MOD_INDEX_Mask = (0x7 << 0), + + + MAX98927_SSM_Configuration_SSM_MOD_INDEX_001 = (0x0 << 0), + MAX98927_SSM_Configuration_SSM_MOD_INDEX_011 = (0x2 << 0), + MAX98927_SSM_Configuration_SSM_MOD_INDEX_101 = (0x4 << 0), + MAX98927_SSM_Configuration_SSM_MOD_INDEX_ = (0x6 << 0), + MAX98927_SSM_Configuration_SPK_FSW_SEL = (0x1 << 3), + MAX98927_SSM_Configuration_SSM_ENA = (0x1 << 7), + + + MAX98927_Measurement_enables = 0x003e, + MAX98927_Measurement_enables_IVADC_V_EN = (0x1 << 0), + MAX98927_Measurement_enables_IVADC_I_EN = (0x1 << 1), + + + MAX98927_Measurement_DSP_Config = 0x003f, + MAX98927_Measurement_DSP_Config_MEAS_V_DCBLK_EN = (0x1 << 0), + MAX98927_Measurement_DSP_Config_MEAS_I_DCBLK_EN = (0x1 << 1), + MAX98927_Measurement_DSP_Config_MEAS_DITH_EN = (0x1 << 2), + MAX98927_Measurement_DSP_Config_MEAS_V_DCBLK_Mask = (0x3 << 4), + + + MAX98927_Measurement_DSP_Config_MEAS_V_DCBLK_01 = (0x0 << 4), + MAX98927_Measurement_DSP_Config_MEAS_V_DCBLK_11 = (0x2 << 4), + MAX98927_Measurement_DSP_Config_MEAS_I_DCBLK_Mask = (0x3 << 6), + + + MAX98927_Measurement_DSP_Config_MEAS_I_DCBLK_01 = (0x0 << 6), + MAX98927_Measurement_DSP_Config_MEAS_I_DCBLK_11 = (0x2 << 6), + + + MAX98927_Boost_Control_0 = 0x0040, + + MAX98927_Boost_Control_0_BST_VOUT_Mask = (0x1f << 0), + MAX98927_Boost_Control_0_EXT_PVDD_EN = (0x1 << 7), + + + MAX98927_Boost_Control_3 = 0x0041, + MAX98927_Boost_Control_3_BST_SKIPLOAD_Mask = (0x3 << 0), + + + MAX98927_Boost_Control_3_BST_SKIPLOAD_01 = (0x0 << 0), + MAX98927_Boost_Control_3_BST_SKIPLOAD_11 = (0x2 << 0), + MAX98927_Boost_Control_3_BST_PHASE_Mask = (0x7 << 2), + + + MAX98927_Boost_Control_3_BST_PHASE_001 = (0x0 << 2), + MAX98927_Boost_Control_3_BST_PHASE_011 = (0x2 << 2), + MAX98927_Boost_Control_3_BST_PHASE_ = (0x1 << 2), + MAX98927_Boost_Control_3_BST_SLOWSTART = (0x1 << 5), + + + MAX98927_Boost_Control_1 = 0x0042, + + MAX98927_Boost_Control_1_BST_ILIM_Mask = (0x1f << 1), + + + MAX98927_Meas_ADC_Config = 0x0043, + MAX98927_Meas_ADC_Config_MEAS_ADC_CH0_EN = (0x1 << 0), + MAX98927_Meas_ADC_Config_MEAS_ADC_CH1_EN = (0x1 << 1), + MAX98927_Meas_ADC_Config_MEAS_ADC_CH2_EN = (0x1 << 2), + + + MAX98927_Meas_ADC_Base_Divide_MSByte = 0x0044, + + MAX98927_Meas_ADC_Base_Divide_MSByte_MEAS_ADC_BASE_DIV_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Base_Divide_LSByte = 0x0045, + + MAX98927_Meas_ADC_Base_Divide_LSByte_MEAS_ADC_BASE_DIV_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Chan_0_Divide = 0x0046, + + MAX98927_Meas_ADC_Chan_0_Divide_MEAS_ADC_CH0_DIV_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Chan_1_Divide = 0x0047, + + MAX98927_Meas_ADC_Chan_1_Divide_MEAS_ADC_CH1_DIV_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Chan_2_Divide = 0x0048, + + MAX98927_Meas_ADC_Chan_2_Divide_MEAS_ADC_CH2_DIV_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Chan_0_Filt_Config = 0x0049, + MAX98927_Meas_ADC_Chan_0_Filt_Config_MEAS_ADC_CH0_FILT_AVG_Mask = (0x7 << 0), + + + MAX98927_Meas_ADC_Chan_0_Filt_Config_MEAS_ADC_CH0_FILT_AVG_001 = (0x0 << 0), + MAX98927_Meas_ADC_Chan_0_Filt_Config_MEAS_ADC_CH0_FILT_AVG_011 = (0x2 << 0), + MAX98927_Meas_ADC_Chan_0_Filt_Config_MEAS_ADC_CH0_FILT_AVG_101 = (0x4 << 0), + MAX98927_Meas_ADC_Chan_0_Filt_Config_MEAS_ADC_CH0_FILT_EN = (0x1 << 3), + + + MAX98927_Meas_ADC_Chan_1_Filt_Config = 0x004a, + MAX98927_Meas_ADC_Chan_1_Filt_Config_MEAS_ADC_CH1_FILT_AVG_Mask = (0x7 << 0), + + + MAX98927_Meas_ADC_Chan_1_Filt_Config_MEAS_ADC_CH1_FILT_AVG_001 = (0x0 << 0), + MAX98927_Meas_ADC_Chan_1_Filt_Config_MEAS_ADC_CH1_FILT_AVG_011 = (0x2 << 0), + MAX98927_Meas_ADC_Chan_1_Filt_Config_MEAS_ADC_CH1_FILT_AVG_101 = (0x4 << 0), + MAX98927_Meas_ADC_Chan_1_Filt_Config_MEAS_ADC_CH1_FILT_EN = (0x1 << 3), + + + MAX98927_Meas_ADC_Chan_2_Filt_Config = 0x004b, + MAX98927_Meas_ADC_Chan_2_Filt_Config_MEAS_ADC_CH2_FILT_AVG_Mask = (0x7 << 0), + + + MAX98927_Meas_ADC_Chan_2_Filt_Config_MEAS_ADC_CH2_FILT_AVG_001 = (0x0 << 0), + MAX98927_Meas_ADC_Chan_2_Filt_Config_MEAS_ADC_CH2_FILT_AVG_011 = (0x2 << 0), + MAX98927_Meas_ADC_Chan_2_Filt_Config_MEAS_ADC_CH2_FILT_AVG_101 = (0x4 << 0), + MAX98927_Meas_ADC_Chan_2_Filt_Config_MEAS_ADC_CH2_FILT_EN = (0x1 << 3), + + + MAX98927_Meas_ADC_Chan_0_Readback = 0x004c, + + MAX98927_Meas_ADC_Chan_0_Readback_MEAS_ADC_CH0_DATA_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Chan_1_Readback = 0x004d, + + MAX98927_Meas_ADC_Chan_1_Readback_MEAS_ADC_CH1_DATA_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Chan_2_Readback = 0x004e, + + MAX98927_Meas_ADC_Chan_2_Readback_MEAS_ADC_CH2_DATA_Mask = (0xff << 0), + + + MAX98927_Brownout_status = 0x0051, + MAX98927_Brownout_status_BDE_STATE_Mask = (0xf << 0), + + + + + MAX98927_Brownout_enables = 0x0052, + MAX98927_Brownout_enables_BDE_EN = (0x1 << 0), + MAX98927_Brownout_enables_BDE_AMP_EN = (0x1 << 1), + MAX98927_Brownout_enables_AMP_DSP_EN = (0x1 << 2), + + + MAX98927_Brownout_level_infinite_hold = 0x0053, + MAX98927_Brownout_level_infinite_hold_BDE_L8_INF_HLD = (0x1 << 1), + + + MAX98927_Brownout_level_infinite_hold_clear = 0x0054, + MAX98927_Brownout_level_infinite_hold_clear_BDE_L8_HLD_RLS = (0x1 << 1), + + + MAX98927_Brownout_level_hold = 0x0055, + + MAX98927_Brownout_level_hold_BDE_HLD_Mask = (0xff << 0), + + + MAX98927_Brownout__level_1_threshold = 0x005a, + + MAX98927_Brownout__level_1_threshold_BDE_L1_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout__level_2_threshold = 0x005b, + + MAX98927_Brownout__level_2_threshold_BDE_L2_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout__level_3_threshold = 0x005c, + + MAX98927_Brownout__level_3_threshold_BDE_L3_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout__level_4_threshold = 0x005d, + + MAX98927_Brownout__level_4_threshold_BDE_L4_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout__level_5_threshold = 0x005a, + + MAX98927_Brownout__level_5_threshold_BDE_L5_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout__level_6_threshold = 0x005b, + + MAX98927_Brownout__level_6_threshold_BDE_L6_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout__level_7_threshold = 0x005c, + + MAX98927_Brownout__level_7_threshold_BDE_L7_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout__level_8_threshold = 0x005d, + + MAX98927_Brownout__level_8_threshold_BDE_L8_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout_threshold_hysterysis = 0x005e, + + MAX98927_Brownout_threshold_hysterysis_BDE_VTHRESH_HYST_Mask = (0xff << 0), + + + MAX98927_Brownout_AMP_limiter_attack_release = 0x005f, + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_Mask = (0xf << 0), + + + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_0001 = (0x0 << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_0011 = (0x2 << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_0101 = (0x4 << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_0111 = (0x6 << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_1001 = (0x8 << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_1011 = (0xa << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_1101 = (0xc << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_1111 = (0xe << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_Mask = (0xf << 4), + + + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_0001 = (0x0 << 4), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_0011 = (0x2 << 4), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_0101 = (0x4 << 4), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_0111 = (0x6 << 4), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_1001 = (0x8 << 4), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_1011 = (0xa << 4), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_1101 = (0xc << 4), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_1111 = (0xe << 4), + + + MAX98927_Brownout_AMP_gain_attack_release = 0x0060, + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_Mask = (0xf << 0), + + + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_0001 = (0x0 << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_0011 = (0x2 << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_0101 = (0x4 << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_0111 = (0x6 << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_1001 = (0x8 << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_1011 = (0xa << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_1101 = (0xc << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_1111 = (0xe << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_Mask = (0xf << 4), + + + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_0001 = (0x0 << 4), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_0011 = (0x2 << 4), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_0101 = (0x4 << 4), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_0111 = (0x6 << 4), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_1001 = (0x8 << 4), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_1011 = (0xa << 4), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_1101 = (0xc << 4), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_1111 = (0xe << 4), + + + MAX98927_Brownout_AMP1_clip_mode = 0x0061, + MAX98927_Brownout_AMP1_clip_mode_AMP_CLIP_MODE = (0x1 << 0), + + + MAX98927_Brownout__level_1_current_limit = 0x0072, + + MAX98927_Brownout__level_1_current_limit_BDE_L1_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_1_amp_1_control_1 = 0x0073, + MAX98927_Brownout__level_1_amp_1_control_1_BDE_L1_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_1_amp_1_control_2 = 0x0074, + + MAX98927_Brownout__level_1_amp_1_control_2_BDE_L1_AMP1_CLIP_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_1_amp_1_control_3 = 0x0075, + + MAX98927_Brownout__level_1_amp_1_control_3_BDE_L1_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_2_current_limit = 0x0076, + + MAX98927_Brownout__level_2_current_limit_BDE_L2_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_2_amp_1_control_1 = 0x0077, + MAX98927_Brownout__level_2_amp_1_control_1_BDE_L2_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_2_amp_1_control_2 = 0x0078, + + MAX98927_Brownout__level_2_amp_1_control_2_BDE_L2_AMP1_CLIP_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_2_amp_1_control_3 = 0x0079, + + MAX98927_Brownout__level_2_amp_1_control_3_BDE_L2_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_3_current_limit = 0x007a, + + MAX98927_Brownout__level_3_current_limit_BDE_L3_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_3_amp_1_control_1 = 0x007b, + MAX98927_Brownout__level_3_amp_1_control_1_BDE_L3_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_3_amp_1_control_2 = 0x007c, + + MAX98927_Brownout__level_3_amp_1_control_2_BDE_L3_AMP1_CLIP_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_3_amp_1_control_3 = 0x007d, + + MAX98927_Brownout__level_3_amp_1_control_3_BDE_L3_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_4_current_limit = 0x007e, + + MAX98927_Brownout__level_4_current_limit_BDE_L4_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_4_amp_1_control_1 = 0x007f, + MAX98927_Brownout__level_4_amp_1_control_1_BDE_L4_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_4_amp_1_control_2 = 0x0080, + + MAX98927_Brownout__level_4_amp_1_control_2_BDE_L4_AMP1_CLIP_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_4_amp_1_control_3 = 0x0081, + + MAX98927_Brownout__level_4_amp_1_control_3_BDE_L4_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_5_current_limit = 0x0072, + + MAX98927_Brownout__level_5_current_limit_BDE_L5_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_5_amp_1_control_1 = 0x0073, + MAX98927_Brownout__level_5_amp_1_control_1_BDE_L5_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_5_amp_1_control_2 = 0x0074, + + MAX98927_Brownout__level_5_amp_1_control_2_BDE_L5_AMP1_CLIP_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_5_amp_1_control_3 = 0x0075, + + MAX98927_Brownout__level_5_amp_1_control_3_BDE_L5_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_6_current_limit = 0x0076, + + MAX98927_Brownout__level_6_current_limit_BDE_L6_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_6_amp_1_control_1 = 0x0077, + MAX98927_Brownout__level_6_amp_1_control_1_BDE_L6_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_6_amp_1_control_2 = 0x0078, + + MAX98927_Brownout__level_6_amp_1_control_2_BDE_L6_AMP1_CLIP_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_6_amp_1_control_3 = 0x0079, + + MAX98927_Brownout__level_6_amp_1_control_3_BDE_L6_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_7_current_limit = 0x007a, + + MAX98927_Brownout__level_7_current_limit_BDE_L7_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_7_amp_1_control_1 = 0x007b, + MAX98927_Brownout__level_7_amp_1_control_1_BDE_L7_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_7_amp_1_control_2 = 0x007c, + + MAX98927_Brownout__level_7_amp_1_control_2_BDE_L7_AMP1_CLIP_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_7_amp_1_control_3 = 0x007d, + + MAX98927_Brownout__level_7_amp_1_control_3_BDE_L7_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_8_current_limit = 0x007e, + + MAX98927_Brownout__level_8_current_limit_BDE_L8_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_8_amp_1_control_1 = 0x007f, + MAX98927_Brownout__level_8_amp_1_control_1_BDE_L8_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_8_amp_1_control_2 = 0x0080, + + MAX98927_Brownout__level_8_amp_1_control_2_BDE_L8_AMP1_CLIP_Mask = (0x3f << 0), + MAX98927_Brownout__level_8_amp_1_control_2_BDE_L8_AMP1_MUTE = (0x1 << 7), + + + MAX98927_Brownout__level_8_amp_1_control_3 = 0x0081, + + MAX98927_Brownout__level_8_amp_1_control_3_BDE_L8_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Env_Tracker_Vout_Headroom = 0x0082, + + MAX98927_Env_Tracker_Vout_Headroom_ENV_TRACKER_BST_VOUT_HEADROOM_Mask = (0x1f << 0), + + + MAX98927_Env_Tracker_Boost_Vout_Delay = 0x0083, + + MAX98927_Env_Tracker_Boost_Vout_Delay_ENV_TRACKER_BST_VOUT_DELAY_Mask = (0x1f << 0), + MAX98927_Env_Tracker_Boost_Vout_Delay_ENV_TRACKER_BDE_MODE = (0x1 << 7), + + + MAX98927_Env_Tracker_Release_Rate = 0x0084, + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_Mask = (0x7 << 0), + + + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_001 = (0x0 << 0), + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_011 = (0x2 << 0), + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_101 = (0x4 << 0), + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_111 = (0x6 << 0), + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_PEAK_DET_LPF_BYP_EN = (0x1 << 3), + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_SCALE_Mask = (0x3 << 4), + + + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_SCALE_01 = (0x0 << 4), + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_SCALE_11 = (0x2 << 4), + + + MAX98927_Env_Tracker_Hold_Rate = 0x0085, + MAX98927_Env_Tracker_Hold_Rate_ENV_TRACKER_HOLD_RATE_Mask = (0x7 << 0), + + + MAX98927_Env_Tracker_Hold_Rate_ENV_TRACKER_HOLD_RATE_001 = (0x0 << 0), + MAX98927_Env_Tracker_Hold_Rate_ENV_TRACKER_HOLD_RATE_011 = (0x2 << 0), + MAX98927_Env_Tracker_Hold_Rate_ENV_TRACKER_HOLD_RATE_101 = (0x4 << 0), + MAX98927_Env_Tracker_Hold_Rate_ENV_TRACKER_HOLD_RATE_111 = (0x6 << 0), + + + MAX98927_Env_Tracker_Control = 0x0086, + MAX98927_Env_Tracker_Control_ENV_TRACKER_EN = (0x1 << 0), + + + MAX98927_Env_Tracker__Boost_Vout_ReadBack = 0x0087, + + MAX98927_Env_Tracker__Boost_Vout_ReadBack_ENV_TRACKER_BST_VOUT_RD_Mask = (0x1f << 0), + + + MAX98927_Advanced_Settings = 0x0089, + MAX98927_Advanced_Settings_DAC_HALF_FIR = (0x1 << 0), + MAX98927_Advanced_Settings_PDM_MOD_SEL = (0x1 << 1), + MAX98927_Advanced_Settings_ISOCH_EN = (0x1 << 2), + + + MAX98927_DAC_Test_1 = 0x009f, + MAX98927_DAC_Test_1_DAC_PCM_TIMING = (0x1 << 0), + MAX98927_DAC_Test_1_DAC_HALFI_AMP = (0x1 << 1), + MAX98927_DAC_Test_1_DAC_LONG_HOLD = (0x1 << 3), + MAX98927_DAC_Test_1_DAC_DISABLE_CHOP = (0x1 << 4), + MAX98927_DAC_Test_1_DAC_TM = (0x1 << 5), + MAX98927_DAC_Test_1_DAC_INVERT_DACCLK = (0x1 << 6), + + + MAX98927_Authentication_key_0 = 0x00ea, + + MAX98927_Authentication_key_0_AUTH_KEY_Mask = (0xff << 0), + + + MAX98927_Authentication_key_1 = 0x00eb, + + MAX98927_Authentication_key_1_AUTH_KEY_Mask = (0xff << 0), + + + MAX98927_Authentication_key_2 = 0x00ec, + + MAX98927_Authentication_key_2_AUTH_KEY_Mask = (0xff << 0), + + + MAX98927_Authentication_key_3 = 0x00ed, + + MAX98927_Authentication_key_3_AUTH_KEY_Mask = (0xff << 0), + + + MAX98927_Authentication_enable = 0x00ee, + MAX98927_Authentication_enable_AUTH_EN = (0x1 << 0), + + + MAX98927_Authentication_result_0 = 0x00ef, + + MAX98927_Authentication_result_0_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_1 = 0x00f0, + + MAX98927_Authentication_result_1_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_2 = 0x00f1, + + MAX98927_Authentication_result_2_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_3 = 0x00f2, + + MAX98927_Authentication_result_3_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_4 = 0x00f3, + + MAX98927_Authentication_result_4_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_5 = 0x00f4, + + MAX98927_Authentication_result_5_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_6 = 0x00f5, + + MAX98927_Authentication_result_6_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_7 = 0x00f6, + + MAX98927_Authentication_result_7_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_8 = 0x00f7, + + MAX98927_Authentication_result_8_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_9 = 0x00f8, + + MAX98927_Authentication_result_9_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_10 = 0x00f9, + + MAX98927_Authentication_result_10_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_11 = 0x00fa, + + MAX98927_Authentication_result_11_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_12 = 0x00fb, + + MAX98927_Authentication_result_12_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_13 = 0x00fc, + + MAX98927_Authentication_result_13_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_14 = 0x00fd, + + MAX98927_Authentication_result_14_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_15 = 0x00fe, + + MAX98927_Authentication_result_15_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Global_Enable = 0x00ff, + MAX98927_Global_Enable_EN = (0x1 << 0), + + MAX98927_Software_Reset = 0x0100, + MAX98927_Software_Reset_RST = (0x1 << 0), + + + MAX98927_REV_ID = 0x01ff, + + MAX98927_REV_ID_REV_ID_Mask = (0xff << 0), + + +} MAX98927Registers; + +struct max98927_priv { + struct device *dev; + struct regmap *regmap_l; + struct regmap *regmap_r; + struct regmap *regmap; + struct snd_soc_codec *codec; + struct max98927_pdata *pdata; + + unsigned int spk_mode; + unsigned int spk_gain; + unsigned int sysclk; + unsigned int v_l_slot; + unsigned int i_l_slot; + unsigned int v_r_slot; + unsigned int i_r_slot; + bool mono_stereo; + bool left_i2c; + bool right_i2c; + bool interleave_mode; + unsigned int ch_size; + unsigned int rate; + unsigned int iface; + unsigned int master; + unsigned int thres_hyste; + unsigned int level5_hold; + unsigned int level6_hold; + unsigned int level7_hold; + unsigned int level8_hold; + unsigned int amp_limit; + unsigned int amp_limit_rel; + unsigned int amp1_level; + unsigned int amp2_level; + unsigned int amp3_level; + unsigned int amp1_level8; + unsigned int amp2_level8; + unsigned int amp3_level8; + unsigned int amp1_level7; + unsigned int amp2_level7; + unsigned int amp3_level7; + unsigned int amp1_level6; + unsigned int amp2_level6; + unsigned int amp3_level6; + unsigned int amp1_level5; + unsigned int amp2_level5; + unsigned int amp3_level5; + unsigned int digital_gain; + unsigned int pdm_gain; + unsigned int level_hold; + int reset_gpio_l; + int reset_gpio_r; +}; + +#define MAX98927_GLOBAL_SHIFT 0 +#define M98927_DAI_MSEL_SHIFT 4 +#define M98927_DAI_BSEL_SHIFT 0 +#define M98927_DAI_BSEL_32 (2 << M98927_DAI_BSEL_SHIFT) +#define M98927_DAI_BSEL_48 (3 << M98927_DAI_BSEL_SHIFT) +#define M98927_DAI_BSEL_64 (4 << M98927_DAI_BSEL_SHIFT) +#define M98927_DAI_MSEL_32 (2 << M98927_DAI_MSEL_SHIFT) +#define M98927_DAI_MSEL_48 (3 << M98927_DAI_MSEL_SHIFT) +#define M98927_DAI_MSEL_64 (4 << M98927_DAI_MSEL_SHIFT) +#define MAX98927_Speaker_Gain_Width 3 +#define MAX98927_SPK_RMP_EN_SHIFT 4 +#define MAX98927_PDM_GAIN_SHIFT 4 +#define MAX98927_pdm_Gain_Width 3 +#define MAX98927_AMP_VOL_WIDTH 7 +#define MAX98927_AMP_VOL_LOCATION_SHIFT 7 +#define MAX98927_PDM_Rx_Enable_PDM_CH_SHIFT 3 +#define MAX98927_PCM_to_speaker_monomix_A_SHIFT 6 +#define MAX98927_PCM_Sample_rate_setup_2_DIG_IF_SR_48000 (0x8 << 4) +#define MAX98927_PCM_FORMAT_DSP_A (0x3 << 3) +#define MAX98927_DRE_Control_DRE_SHIFT 0 +#define MAX98927_PCM_Master_Mode_PCM_MCLK_RATE_SHIFT (2) +#define MAX98927_Brownout_AMP_limiter_attack_release_shift 4 +#define MAX98927_BDE_DSP_SHIFT 2 +#define MAX98927_Speaker_Gain_SPK_PDM_GAIN_SHIFT (4) +#define MAX98927_BDE_AMP_SHIFT 1 +#define MAX98927_BST_ILIM_SHIFT 1 +#endif diff --git a/sound/soc/codecs/msm8x16-wcd.c b/sound/soc/codecs/msm8x16-wcd.c index a4715fadd002d..5cc320d5fec95 100644 --- a/sound/soc/codecs/msm8x16-wcd.c +++ b/sound/soc/codecs/msm8x16-wcd.c @@ -98,7 +98,11 @@ enum { #define SPK_PMD 2 #define SPK_PMU 3 +#ifdef CONFIG_MACH_XIAOMI_TISSOT +#define MICBIAS_DEFAULT_VAL 2200000 +#else #define MICBIAS_DEFAULT_VAL 1800000 +#endif #define MICBIAS_MIN_VAL 1600000 #define MICBIAS_STEP_SIZE 50000 @@ -4236,7 +4240,7 @@ static int msm8x16_wcd_lo_dac_event(struct snd_soc_dapm_widget *w, MSM8X16_WCD_A_ANALOG_RX_LO_DAC_CTL, 0x08, 0x08); snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_RX_LO_DAC_CTL, 0x40, 0x40); -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) msleep(5); #endif break; @@ -4464,7 +4468,7 @@ static const struct snd_soc_dapm_route audio_map[] = { {"LINEOUT PA", NULL, "LINE_OUT"}, {"LINE_OUT", "Switch", "LINEOUT DAC"}, {"LINEOUT DAC", NULL, "RX3 CHAIN"}, -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) { "Ext Spk", NULL, "LINEOUT PA"}, #endif diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index 05797fb1fd869..4274d62bdeca4 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -25,7 +25,7 @@ #include #include #include -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) #include #endif #include @@ -43,9 +43,13 @@ SND_JACK_BTN_4 | SND_JACK_BTN_5 | \ SND_JACK_BTN_6 | SND_JACK_BTN_7) #define OCP_ATTEMPT 1 +#ifdef CONFIG_MACH_XIAOMI_TISSOT +#define HS_DETECT_PLUG_TIME_MS (2500) +#else #define HS_DETECT_PLUG_TIME_MS (3 * 1000) +#endif #define SPECIAL_HS_DETECT_TIME_MS (2 * 1000) -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) #define MBHC_BUTTON_PRESS_THRESHOLD_MIN 750 #else #define MBHC_BUTTON_PRESS_THRESHOLD_MIN 250 @@ -58,7 +62,11 @@ #define FAKE_REM_RETRY_ATTEMPTS 3 #define MAX_IMPED 60000 +#ifdef CONFIG_MACH_XIAOMI_TISSOT +#define WCD_MBHC_BTN_PRESS_COMPL_TIMEOUT_MS 200 +#else #define WCD_MBHC_BTN_PRESS_COMPL_TIMEOUT_MS 50 +#endif #define ANC_DETECT_RETRY_CNT 7 #define WCD_MBHC_SPL_HS_CNT 2 @@ -67,6 +75,10 @@ module_param(det_extn_cable_en, int, S_IRUGO | S_IWUSR | S_IWGRP); MODULE_PARM_DESC(det_extn_cable_en, "enable/disable extn cable detect"); +#ifdef CONFIG_MACH_XIAOMI_TISSOT +bool is_jack_insert = false; +#endif + enum wcd_mbhc_cs_mb_en_flag { WCD_MBHC_EN_CS = 0, WCD_MBHC_EN_MB, @@ -74,18 +86,24 @@ enum wcd_mbhc_cs_mb_en_flag { WCD_MBHC_EN_NONE, }; -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) static struct switch_dev accdet_data; #endif static void wcd_mbhc_jack_report(struct wcd_mbhc *mbhc, struct snd_soc_jack *jack, int status, int mask) { -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) if (!status && (jack->jack->type&WCD_MBHC_JACK_MASK)) { switch_set_state(&accdet_data, 0); +#ifdef CONFIG_MACH_XIAOMI_TISSOT + is_jack_insert = false; +#endif } else if (jack->jack->type&WCD_MBHC_JACK_MASK) { switch_set_state(&accdet_data, status); +#ifdef CONFIG_MACH_XIAOMI_TISSOT + is_jack_insert = true; +#endif } #endif snd_soc_jack_report(jack, status, mask); @@ -180,11 +198,13 @@ static void wcd_enable_curr_micbias(const struct wcd_mbhc *mbhc, switch (cs_mb_en) { case WCD_MBHC_EN_CS: +#ifndef CONFIG_MACH_XIAOMI_TISSOT WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MICB_CTRL, 0); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 3); /* Program Button threshold registers as per CS */ wcd_program_btn_threshold(mbhc, false); break; +#endif case WCD_MBHC_EN_MB: WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1); @@ -351,13 +371,25 @@ static int wcd_event_notify(struct notifier_block *self, unsigned long val, &mbhc->event_state))) /* enable pullup and cs, disable mb */ wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_PULLUP); - else + else { /* enable current source and disable mb, pullup*/ +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (is_jack_insert) + wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB); + else + wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_NONE); +#else wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS); +#endif + } /* configure cap settings properly when micbias is disabled */ if (mbhc->mbhc_cb->set_cap_mode) - mbhc->mbhc_cb->set_cap_mode(codec, micbias1, false); +#ifdef CONFIG_MACH_XIAOMI_TISSOT + mbhc->mbhc_cb->set_cap_mode(codec, micbias1, is_jack_insert); +#else + mbhc->mbhc_cb->set_cap_mode(codec, micbias1, false); +#endif break; case WCD_EVENT_PRE_HPHL_PA_OFF: mutex_lock(&mbhc->hphl_pa_lock); @@ -368,12 +400,20 @@ static int wcd_event_notify(struct notifier_block *self, unsigned long val, hphlocp_off_report(mbhc, SND_JACK_OC_HPHL); clear_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state); /* check if micbias is enabled */ +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (is_jack_insert) +#else if (micbias2) +#endif /* Disable cs, pullup & enable micbias */ wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB); else /* Disable micbias, pullup & enable cs */ +#ifdef CONFIG_MACH_XIAOMI_TISSOT + wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_NONE); +#else wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS); +#endif mutex_unlock(&mbhc->hphl_pa_lock); break; case WCD_EVENT_PRE_HPHR_PA_OFF: @@ -385,12 +425,20 @@ static int wcd_event_notify(struct notifier_block *self, unsigned long val, hphrocp_off_report(mbhc, SND_JACK_OC_HPHR); clear_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state); /* check if micbias is enabled */ +#ifdef CONFIG_MACH_XIAOMI_TISSOT + if (is_jack_insert) +#else if (micbias2) +#endif /* Disable cs, pullup & enable micbias */ wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB); else /* Disable micbias, pullup & enable cs */ +#ifdef CONFIG_MACH_XIAOMI_TISSOT + wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_NONE); +#else wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS); +#endif mutex_unlock(&mbhc->hphr_pa_lock); break; case WCD_EVENT_PRE_HPHL_PA_ON: @@ -568,6 +616,11 @@ static void wcd_mbhc_hs_elec_irq(struct wcd_mbhc *mbhc, int irq_type, } } +#ifdef CONFIG_MACH_XIAOMI_TISSOT +extern int ext_pa_gpio; +extern int ext_pa_status; +#endif + static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion, enum snd_jack_types jack_type) { @@ -580,7 +633,14 @@ static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion, __func__, insertion, mbhc->hph_status); if (!insertion) { /* Report removal */ +#ifdef CONFIG_MACH_XIAOMI_TISSOT + mbhc->hph_status &= ~(SND_JACK_HEADSET | + SND_JACK_LINEOUT | + SND_JACK_ANC_HEADPHONE | + SND_JACK_UNSUPPORTED); +#else mbhc->hph_status &= ~jack_type; +#endif /* * cancel possibly scheduled btn work and * report release if we reported button press @@ -622,6 +682,11 @@ static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion, hphrocp_off_report(mbhc, SND_JACK_OC_HPHR); hphlocp_off_report(mbhc, SND_JACK_OC_HPHL); mbhc->current_plug = MBHC_PLUG_TYPE_NONE; + +#ifdef CONFIG_MACH_XIAOMI_TISSOT + gpio_set_value(ext_pa_gpio, 0); +#endif + } else { /* * Report removal of current jack type. @@ -734,6 +799,13 @@ static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion, (mbhc->hph_status | SND_JACK_MECHANICAL), WCD_MBHC_JACK_MASK); wcd_mbhc_clr_and_turnon_hph_padac(mbhc); + +#ifdef CONFIG_MACH_XIAOMI_TISSOT + msleep(500); + if (ext_pa_status) + gpio_set_value(ext_pa_gpio, 1); +#endif + } pr_debug("%s: leave hph_status %x\n", __func__, mbhc->hph_status); } @@ -852,7 +924,11 @@ static void wcd_mbhc_find_plug_and_report(struct wcd_mbhc *mbhc, SND_JACK_HEADPHONE); if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET) wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADSET); +#ifdef CONFIG_MACH_XIAOMI_TISSOT + wcd_mbhc_report_plug(mbhc, 1, SND_JACK_HEADSET); +#else wcd_mbhc_report_plug(mbhc, 1, SND_JACK_UNSUPPORTED); +#endif } else if (plug_type == MBHC_PLUG_TYPE_HEADSET) { if (mbhc->mbhc_cfg->enable_anc_mic_detect) anc_mic_found = wcd_mbhc_detect_anc_plug_type(mbhc); @@ -1112,6 +1188,10 @@ static void wcd_enable_mbhc_supply(struct wcd_mbhc *mbhc, WCD_MBHC_EN_CS); } else if (plug_type == MBHC_PLUG_TYPE_HEADPHONE) { wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS); +#ifdef CONFIG_MACH_XIAOMI_TISSOT + } else if (is_jack_insert) { + wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB); +#endif } else { wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_NONE); } @@ -2021,6 +2101,12 @@ static irqreturn_t wcd_mbhc_release_handler(int irq, void *data) */ if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) { wcd_mbhc_find_plug_and_report(mbhc, MBHC_PLUG_TYPE_HEADSET); +#ifdef CONFIG_MACH_XIAOMI_TISSOT + wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack, + 0, WCD_MBHC_JACK_MASK); + msleep(100); + wcd_mbhc_report_plug(mbhc, 1, SND_JACK_HEADSET); +#endif goto exit; } @@ -2396,7 +2482,8 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec, pr_debug("%s: enter\n", __func__); -#ifdef CONFIG_MACH_XIAOMI_MIDO + +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) accdet_data.name = "h2w"; accdet_data.index = 0; accdet_data.state = 0; @@ -2406,6 +2493,7 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec, return -EPERM; } #endif + ret = of_property_read_u32(card->dev->of_node, hph_switch, &hph_swh); if (ret) { dev_err(card->dev, @@ -2425,7 +2513,11 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec, mbhc->is_btn_press = false; mbhc->codec = codec; mbhc->intr_ids = mbhc_cdc_intr_ids; +#ifdef CONFIG_MACH_XIAOMI_TISSOT + mbhc->impedance_detect = false; +#else mbhc->impedance_detect = impedance_det_en; +#endif mbhc->hphl_swh = hph_swh; mbhc->gnd_swh = gnd_swh; mbhc->micbias_enable = false; @@ -2602,7 +2694,7 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec, mbhc->mbhc_cb->register_notifier(codec, &mbhc->nblock, false); mutex_destroy(&mbhc->codec_resource_lock); err: -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) switch_dev_unregister(&accdet_data); #endif pr_debug("%s: leave ret %d\n", __func__, ret); @@ -2626,7 +2718,7 @@ void wcd_mbhc_deinit(struct wcd_mbhc *mbhc) if (mbhc->mbhc_cb && mbhc->mbhc_cb->register_notifier) mbhc->mbhc_cb->register_notifier(codec, &mbhc->nblock, false); mutex_destroy(&mbhc->codec_resource_lock); -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) switch_dev_unregister(&accdet_data); #endif } diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c index 7857813ca3b04..a518ac21641dc 100644 --- a/sound/soc/msm/msm-dai-fe.c +++ b/sound/soc/msm/msm-dai-fe.c @@ -2666,6 +2666,40 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .name = "MultiMedia29", .probe = fe_dai_probe, }, +#ifdef CONFIG_SND_SOC_MAX98927 + { + .capture = { + .stream_name = "Quinary MI2S_TX Hostless Capture", + .aif_name = "QUIN_MI2S_UL_HL", + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &msm_fe_dai_ops, + .name = "QUIN_MI2S_TX_HOSTLESS", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "Quinary MI2S_RX Hostless Playback", + .aif_name = "QUIN_MI2S_DL_HL", + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_fe_dai_ops, + .name = "QUIN_MI2S_RX_HOSTLESS", + .probe = fe_dai_probe, + }, +#endif }; static int msm_fe_dai_dev_probe(struct platform_device *pdev) diff --git a/sound/soc/msm/msm8952.c b/sound/soc/msm/msm8952.c index c8d2dba28ce4f..75fd25ed9554f 100644 --- a/sound/soc/msm/msm8952.c +++ b/sound/soc/msm/msm8952.c @@ -49,6 +49,11 @@ #define DEFAULT_MCLK_RATE 9600000 +#ifdef CONFIG_MACH_XIAOMI_TISSOT +int ext_pa_gpio = 0; +int ext_pa_status = 0; +#endif + #define WCD_MBHC_DEF_RLOADS 5 #define MAX_WSA_CODEC_NAME_LENGTH 80 #define MSM_DT_MAX_PROP_SIZE 80 @@ -93,12 +98,16 @@ static int msm8952_wsa_switch_event(struct snd_soc_dapm_widget *w, static struct wcd_mbhc_config mbhc_cfg = { .read_fw_bin = false, .calibration = NULL, +#ifdef CONFIG_MACH_XIAOMI_TISSOT + .detect_extn_cable = false, +#else .detect_extn_cable = true, +#endif .mono_stero_detection = false, .swap_gnd_mic = NULL, .hs_ext_micbias = false, .key_code[0] = KEY_MEDIA, -#if (defined CONFIG_MACH_XIAOMI_MIDO) +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) .key_code[1] = BTN_1, .key_code[2] = BTN_2, .key_code[3] = 0, @@ -252,6 +261,9 @@ int is_ext_spk_gpio_support(struct platform_device *pdev, { const char *spk_ext_pa = "qcom,msm-spk-ext-pa"; +#ifdef CONFIG_MACH_XIAOMI_TISSOT + int ret; +#endif pr_debug("%s:Enter\n", __func__); pdata->spk_ext_pa_gpio = of_get_named_gpio(pdev->dev.of_node, @@ -266,6 +278,16 @@ int is_ext_spk_gpio_support(struct platform_device *pdev, __func__, pdata->spk_ext_pa_gpio); return -EINVAL; } +#ifdef CONFIG_MACH_XIAOMI_TISSOT + ext_pa_gpio = pdata->spk_ext_pa_gpio; + ret = msm_get_gpioset_index(CLIENT_WCD_INT, + "ext_pa_gpio"); + if (ret < 0) { + pr_err("%s: gpio set name does not exist: %s", + __func__, "ext_pa_gpio"); + return ret; + } +#endif } #ifdef CONFIG_MACH_XIAOMI_MIDO gpio_direction_output(pdata->spk_ext_pa_gpio, 0); @@ -277,7 +299,9 @@ static int enable_spk_ext_pa(struct snd_soc_codec *codec, int enable) { struct snd_soc_card *card = codec->component.card; struct msm8916_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); +#ifdef CONFIG_MACH_XIAOMI_TISSOT int ret; +#endif #ifdef CONFIG_MACH_XIAOMI_MIDO int pa_mode = EXT_PA_MODE; #endif @@ -288,6 +312,10 @@ static int enable_spk_ext_pa(struct snd_soc_codec *codec, int enable) return false; } +#ifdef CONFIG_MACH_XIAOMI_TISSOT + ext_pa_status = enable; +#endif + pr_debug("%s: %s external speaker PA\n", __func__, enable ? "Enable" : "Disable"); @@ -300,8 +328,12 @@ static int enable_spk_ext_pa(struct snd_soc_codec *codec, int enable) udelay(2); pa_mode--; } +#else +#ifdef CONFIG_MACH_XIAOMI_TISSOT + ret = msm_gpioset_activate(CLIENT_WCD_INT, "ext_pa_gpio"); #else ret = msm_gpioset_activate(CLIENT_WCD_INT, "ext_spk_gpio"); +#endif if (ret) { pr_err("%s: gpio set cannot be de-activated %s\n", __func__, "ext_spk_gpio"); @@ -312,7 +344,11 @@ static int enable_spk_ext_pa(struct snd_soc_codec *codec, int enable) } else { gpio_set_value_cansleep(pdata->spk_ext_pa_gpio, enable); #ifndef CONFIG_MACH_XIAOMI_MIDO +#ifdef CONFIG_MACH_XIAOMI_TISSOT + ret = msm_gpioset_suspend(CLIENT_WCD_INT, "ext_pa_gpio"); +#else ret = msm_gpioset_suspend(CLIENT_WCD_INT, "ext_spk_gpio"); +#endif if (ret) { pr_err("%s: gpio set cannot be de-activated %s\n", __func__, "ext_spk_gpio"); @@ -1573,7 +1609,7 @@ static void *def_msm8952_wcd_mbhc_cal(void) return NULL; #define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(msm8952_wcd_cal)->X) = (Y)) -#ifdef CONFIG_MACH_XIAOMI_MIDO +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) S(v_hs_max, 1600); #else S(v_hs_max, 1500); @@ -1611,6 +1647,18 @@ static void *def_msm8952_wcd_mbhc_cal(void) btn_high[3] = 438; btn_low[4] = 438; btn_high[4] = 438; +#else +#ifdef CONFIG_MACH_XIAOMI_TISSOT + btn_low[0] = 91; + btn_high[0] = 91; + btn_low[1] = 259; + btn_high[1] = 259; + btn_low[2] = 488; + btn_high[2] = 488; + btn_low[3] = 488; + btn_high[3] = 488; + btn_low[4] = 488; + btn_high[4] = 488; #else btn_low[0] = 75; btn_high[0] = 75; @@ -1623,7 +1671,7 @@ static void *def_msm8952_wcd_mbhc_cal(void) btn_low[4] = 500; btn_high[4] = 500; #endif - +#endif return msm8952_wcd_cal; } @@ -2407,7 +2455,41 @@ static struct snd_soc_dai_link msm8952_dai[] = { .ignore_suspend = 1, .ignore_pmdown_time = 1, .be_id = MSM_FRONTEND_DAI_MULTIMEDIA29, + }, +#ifdef CONFIG_SND_SOC_MAX98927 + {/* hw:x,41 */ + .name = "Quinary MI2S TX_Hostless", + .stream_name = "Quinary MI2S_TX Hostless Capture", + .cpu_dai_name = "QUIN_MI2S_TX_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", }, + { /* hw:x,42 */ + .name = "Quinary MI2S_RX Hostless", + .stream_name = "Quinary MI2S_RX Hostless", + .cpu_dai_name = "QUIN_MI2S_RX_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + /* this dailink has playback support */ + .ignore_pmdown_time = 1, + /* This dainlink has MI2S support */ + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, +#endif /* Backend I2S DAI Links */ { .name = LPASS_BE_PRI_MI2S_RX, @@ -2661,8 +2743,13 @@ static struct snd_soc_dai_link msm8952_dai[] = { .stream_name = "Quinary MI2S Capture", .cpu_dai_name = "msm-dai-q6-mi2s.5", .platform_name = "msm-pcm-routing", +#ifdef CONFIG_SND_SOC_MAX98927 + .codec_dai_name = "max98927-aif1", + .codec_name = "max98927", +#else .codec_dai_name = "snd-soc-dummy-dai", .codec_name = "snd-soc-dummy", +#endif .no_pcm = 1, .dpcm_capture = 1, .be_id = MSM_BACKEND_DAI_QUINARY_MI2S_TX, @@ -2695,8 +2782,13 @@ static struct snd_soc_dai_link msm8952_quin_dai_link[] = { .stream_name = "Quinary MI2S Playback", .cpu_dai_name = "msm-dai-q6-mi2s.5", .platform_name = "msm-pcm-routing", +#ifdef CONFIG_SND_SOC_MAX98927 + .codec_dai_name = "max98927-aif1", + .codec_name = "max98927", +#else .codec_dai_name = "snd-soc-dummy-dai", .codec_name = "snd-soc-dummy", +#endif .no_pcm = 1, .dpcm_playback = 1, .be_id = MSM_BACKEND_DAI_QUINARY_MI2S_RX, diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index cf5c8fa32b126..581db456554b8 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -57,6 +57,9 @@ static int pri_mi2s_switch_enable; static int sec_mi2s_switch_enable; static int tert_mi2s_switch_enable; static int quat_mi2s_switch_enable; +#ifdef CONFIG_SND_SOC_MAX98927 +static int quin_mi2s_switch_enable; +#endif static int fm_pcmrx_switch_enable; static int lsm_port_index; static int slim0_rx_aanc_fb_port; @@ -1970,6 +1973,39 @@ static int msm_routing_put_quat_mi2s_switch_mixer( return 1; } +#ifdef CONFIG_SND_SOC_MAX98927 +static int msm_routing_get_quin_mi2s_switch_mixer( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = quin_mi2s_switch_enable; + pr_debug("%s: QUIN MI2S Switch enable %ld\n", __func__, + ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_routing_put_quin_mi2s_switch_mixer( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget_list *wlist = + dapm_kcontrol_get_wlist(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct snd_soc_dapm_update *update = NULL; + + pr_debug("%s: QUIN MI2S Switch enable %ld\n", __func__, + ucontrol->value.integer.value[0]); + if (ucontrol->value.integer.value[0]) + snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, 1, + update); + else + snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, 0, + update); + quin_mi2s_switch_enable = ucontrol->value.integer.value[0]; + return 1; +} +#endif + static int msm_routing_get_fm_pcmrx_switch_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -7454,6 +7490,11 @@ static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX, MSM_BACKEND_DAI_TERTIARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), +#ifdef CONFIG_SND_SOC_MAX98927 + SOC_SINGLE_EXT("QUIN_MI2S_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_BACKEND_DAI_QUINARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), +#endif SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX, MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), @@ -7469,6 +7510,11 @@ static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_RX", MSM_BACKEND_DAI_SLIMBUS_0_RX, MSM_BACKEND_DAI_TERTIARY_MI2S_RX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), +#ifdef CONFIG_SND_SOC_MAX98927 + SOC_SINGLE_EXT("QUIN_MI2S_RX", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_BACKEND_DAI_QUINARY_MI2S_RX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), +#endif SOC_SINGLE_EXT("QUAT_MI2S_RX", MSM_BACKEND_DAI_SLIMBUS_0_RX, MSM_BACKEND_DAI_QUATERNARY_MI2S_RX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), @@ -7670,6 +7716,31 @@ static const struct snd_kcontrol_new quat_mi2s_rx_port_mixer_controls[] = { msm_routing_put_port_mixer), }; +#ifdef CONFIG_SND_SOC_MAX98927 +static const struct snd_kcontrol_new quin_mi2s_rx_port_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_BACKEND_DAI_TERTIARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUIN_MI2S_TX", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_BACKEND_DAI_QUINARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), +}; +#endif static const struct snd_kcontrol_new pri_tdm_rx_0_port_mixer_controls[] = { SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_TDM_RX_0, @@ -9027,6 +9098,13 @@ static const struct snd_kcontrol_new quat_mi2s_rx_switch_mixer_controls = 0, 1, 0, msm_routing_get_quat_mi2s_switch_mixer, msm_routing_put_quat_mi2s_switch_mixer); +#ifdef CONFIG_SND_SOC_MAX98927 +static const struct snd_kcontrol_new quin_mi2s_rx_switch_mixer_controls = + SOC_SINGLE_EXT("Switch", SND_SOC_NOPM, + 0, 1, 0, msm_routing_get_quin_mi2s_switch_mixer, + msm_routing_put_quin_mi2s_switch_mixer); +#endif + static const struct snd_kcontrol_new hfp_pri_aux_switch_mixer_controls = SOC_SINGLE_EXT("Switch", SND_SOC_NOPM, 0, 1, 0, msm_routing_get_hfp_switch_mixer, @@ -9999,6 +10077,11 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_AIF_IN("QUAT_MI2S_DL_HL", "Quaternary MI2S_RX Hostless Playback", 0, 0, 0, 0), +#ifdef CONFIG_SND_SOC_MAX98927 + SND_SOC_DAPM_AIF_IN("QUIN_MI2S_DL_HL", + "Quinary MI2S_RX Hostless Playback", + 0, 0, 0, 0), +#endif SND_SOC_DAPM_AIF_IN("AUXPCM_DL_HL", "AUXPCM_HOSTLESS Playback", 0, 0, 0, 0), @@ -10026,6 +10109,11 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_UL_HL", "Quaternary MI2S_TX Hostless Capture", 0, 0, 0, 0), +#ifdef CONFIG_SND_SOC_MAX98927 + SND_SOC_DAPM_AIF_OUT("QUIN_MI2S_UL_HL", + "Quinary MI2S_TX Hostless Capture", + 0, 0, 0, 0), +#endif SND_SOC_DAPM_AIF_IN("PRI_TDM_RX_0_DL_HL", "Primary TDM0 Hostless Playback", @@ -10484,6 +10572,10 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { &tert_mi2s_rx_switch_mixer_controls), SND_SOC_DAPM_SWITCH("QUAT_MI2S_RX_DL_HL", SND_SOC_NOPM, 0, 0, &quat_mi2s_rx_switch_mixer_controls), +#ifdef CONFIG_SND_SOC_MAX98927 + SND_SOC_DAPM_SWITCH("QUIN_MI2S_RX_DL_HL", SND_SOC_NOPM, 0, 0, + &quin_mi2s_rx_switch_mixer_controls), +#endif SND_SOC_DAPM_SWITCH("HFP_PRI_AUX_UL_HL", SND_SOC_NOPM, 0, 0, &hfp_pri_aux_switch_mixer_controls), SND_SOC_DAPM_SWITCH("HFP_AUX_UL_HL", SND_SOC_NOPM, 0, 0, @@ -10777,6 +10869,11 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MIXER("QUAT_MI2S_RX Port Mixer", SND_SOC_NOPM, 0, 0, quat_mi2s_rx_port_mixer_controls, ARRAY_SIZE(quat_mi2s_rx_port_mixer_controls)), +#ifdef CONFIG_SND_SOC_MAX98927 + SND_SOC_DAPM_MIXER("QUIN_MI2S_RX Port Mixer", SND_SOC_NOPM, 0, 0, + quin_mi2s_rx_port_mixer_controls, + ARRAY_SIZE(quin_mi2s_rx_port_mixer_controls)), +#endif SND_SOC_DAPM_MIXER("PRI_TDM_RX_0 Port Mixer", SND_SOC_NOPM, 0, 0, pri_tdm_rx_0_port_mixer_controls, ARRAY_SIZE(pri_tdm_rx_0_port_mixer_controls)), @@ -12400,6 +12497,12 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_MI2S_RX_DL_HL", "Switch", "QUAT_MI2S_DL_HL"}, {"QUAT_MI2S_RX", NULL, "QUAT_MI2S_RX_DL_HL"}, + +#ifdef CONFIG_SND_SOC_MAX98927 + {"QUIN_MI2S_RX_DL_HL", "Switch", "PRI_MI2S_DL_HL"}, + {"QUIN_MI2S_RX", NULL, "QUIN_MI2S_RX_DL_HL"}, +#endif + {"MI2S_UL_HL", NULL, "TERT_MI2S_TX"}, {"TERT_MI2S_UL_HL", NULL, "TERT_MI2S_TX"}, {"SEC_I2S_RX", NULL, "SEC_I2S_DL_HL"}, @@ -12409,6 +12512,9 @@ static const struct snd_soc_dapm_route intercon[] = { {"PRI_MI2S_RX", NULL, "PRI_MI2S_DL_HL"}, {"TERT_MI2S_RX", NULL, "TERT_MI2S_DL_HL"}, {"QUAT_MI2S_UL_HL", NULL, "QUAT_MI2S_TX"}, +#ifdef CONFIG_SND_SOC_MAX98927 + {"QUIN_MI2S_UL_HL", NULL, "QUIN_MI2S_TX"}, +#endif {"PRI_TDM_TX_0_UL_HL", NULL, "PRI_TDM_TX_0"}, {"PRI_TDM_TX_1_UL_HL", NULL, "PRI_TDM_TX_1"}, @@ -12884,7 +12990,20 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_MI2S_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"}, {"QUAT_MI2S_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, {"QUAT_MI2S_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, +#ifdef CONFIG_SND_SOC_MAX98927 + {"QUAT_MI2S_RX Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, +#endif {"QUAT_MI2S_RX", NULL, "QUAT_MI2S_RX Port Mixer"}, +#ifdef CONFIG_SND_SOC_MAX98927 + {"QUIN_MI2S_RX Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"QUIN_MI2S_RX Port Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"QUIN_MI2S_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, + {"QUIN_MI2S_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_UL_TX"}, + {"QUIN_MI2S_RX Port Mixer", "SLIM_0_TX", "SLIM_0_TX"}, + {"QUIN_MI2S_RX Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"QUIN_MI2S_RX Port Mixer", "QUIN_MI2S_TX", "QUIN_MI2S_TX"}, + {"QUIN_MI2S_RX", NULL, "QUIN_MI2S_RX Port Mixer"}, +#endif /* Backend Enablement */ diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c index 9c60419dfb420..ea85dc8892597 100644 --- a/sound/soc/msm/qdsp6v2/q6afe.c +++ b/sound/soc/msm/qdsp6v2/q6afe.c @@ -119,6 +119,9 @@ struct afe_ctl { struct aanc_data aanc_info; struct mutex afe_cmd_lock; int set_custom_topology; +#ifdef CONFIG_SND_SOC_MAX98927 + uint8_t *dsm_payload; +#endif }; #define MAD_SLIMBUS_PORT_COUNT ((SLIMBUS_PORT_LAST - SLIMBUS_0_RX) + 1) @@ -255,6 +258,29 @@ static int32_t sp_make_afe_callback(uint32_t *payload, uint32_t payload_size) atomic_set(&this_afe.state, -1); } } +#ifdef CONFIG_SND_SOC_MAX98927 + if (param_id == AFE_PARAM_ID_DSM_CFG) { + struct afe_dsm_get_resp *dsm_resp = + (struct afe_dsm_get_resp *) payload; + + if (payload_size < sizeof(*dsm_resp)) { + pr_err("%s: Error: received size %d, afe_dsm_get_resp size %zu\n", + __func__, payload_size, sizeof(*dsm_resp)); + return -EINVAL; + } + + if (this_afe.dsm_payload) + memcpy(this_afe.dsm_payload, dsm_resp->payload, + payload_size - sizeof(*dsm_resp)); + + if (!dsm_resp->status) { + atomic_set(&this_afe.state, 0); + } else { + pr_debug("%s: dsm resp status: %d", __func__, dsm_resp->status); + atomic_set(&this_afe.state, -1); + } + } +#endif return 0; } @@ -890,6 +916,110 @@ static int afe_spk_ramp_dn_cfg(int port) return ret; } +#ifdef CONFIG_SND_SOC_MAX98927 +int afe_dsm_setget_params(uint8_t *payload, int size, int dir) +{ + struct afe_dsm_set_command *set = NULL; + struct afe_dsm_get_command *get = NULL; + uint32_t *config = NULL; + int ret = -EINVAL, dst_port = AFE_PORT_ID_QUINARY_MI2S_RX; + int index = 0; + + if (!payload || size <= 0) { + pr_err("%s: Invalid params\n", __func__); + goto fail_cmd; + } + ret = q6audio_validate_port(dst_port); + if (ret < 0) { + pr_err("%s: Invalid src port 0x%x ret %d", + __func__, dst_port, ret); + ret = -EINVAL; + goto fail_cmd; + } + + index = q6audio_get_port_index(dst_port); + if (index < 0 || index > AFE_MAX_PORTS) { + pr_err("%s: AFE port index[%d] invalid!\n", + __func__, index); + ret = -EINVAL; + goto fail_cmd; + } + + if (dir) { + get = (struct afe_dsm_get_command *) (payload - sizeof(*get)); + + memset(get, 0 , sizeof(*get)); + + get->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + get->hdr.pkt_size = size + sizeof(*get); + get->hdr.token = index; + get->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2; + get->param.port_id = q6audio_get_port_id(dst_port); + get->param.payload_size = size + sizeof(struct afe_port_param_data_v2); + get->param.module_id = AFE_MODULE_DSM_RX; + get->param.param_id = AFE_PARAM_ID_DSM_CFG; + get->pdata.module_id = AFE_MODULE_DSM_RX; + get->pdata.param_id = AFE_PARAM_ID_DSM_CFG; + get->pdata.param_size = size; + + this_afe.dsm_payload = payload; + + config = (uint32_t *)get; + } else { + set = (struct afe_dsm_set_command *) (payload - sizeof(*set)); + + memset(set, 0 , sizeof(*set)); + + set->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + set->hdr.pkt_size = size + sizeof(*set); + set->hdr.token = index; + set->hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2; + set->param.port_id = q6audio_get_port_id(dst_port); + set->param.payload_size = size + sizeof(struct afe_port_param_data_v2); + set->pdata.module_id = AFE_MODULE_DSM_RX; + set->pdata.param_id = AFE_PARAM_ID_DSM_CFG; + set->pdata.param_size = size; + + config = (uint32_t *)set; + } + + atomic_set(&this_afe.state, 1); + atomic_set(&this_afe.status, 0); + ret = apr_send_pkt(this_afe.apr, config); + if (ret < 0) { + pr_err("%s: port = 0x%x failed %d\n", __func__, dst_port, ret); + goto fail_cmd; + } + ret = wait_event_timeout(this_afe.wait[index], + (atomic_read(&this_afe.state) == 0), + msecs_to_jiffies(TIMEOUT_MS)); + if (!ret) { + pr_err("%s: wait_event timeout\n", __func__); + ret = -EINVAL; + goto fail_cmd; + } + if (atomic_read(&this_afe.status) > 0) { + pr_err("%s: config cmd failed [%s]\n", + __func__, adsp_err_get_err_str( + atomic_read(&this_afe.status))); + ret = adsp_err_get_lnx_err_code( + atomic_read(&this_afe.status)); + goto fail_cmd; + } + + ret = 0; + +fail_cmd: + pr_debug("%s: status %d 0x%x\n", __func__, ret, dst_port); + + this_afe.dsm_payload = NULL; + + return ret; +} +#endif + static int afe_spk_prot_prepare(int src_port, int dst_port, int param_id, union afe_spkr_prot_config *prot_config) { From 97c9b8343050f3e93b63c8757fdf3fd026cdf8cd Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Mon, 19 Mar 2018 16:53:17 +0530 Subject: [PATCH 211/508] fs: pstore: Import xiaomi pstore changes --- fs/pstore/ram.c | 16 ++++++++++++++++ fs/pstore/ram_core.c | 14 ++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 273f06370dc1f..b49ba69e1c4c0 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -43,7 +43,11 @@ module_param(record_size, ulong, 0400); MODULE_PARM_DESC(record_size, "size of each dump done on oops/panic"); +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) +static ulong ramoops_console_size = 512*1024UL; +#else static ulong ramoops_console_size = MIN_MEM_SIZE; +#endif module_param_named(console_size, ramoops_console_size, ulong, 0400); MODULE_PARM_DESC(console_size, "size of kernel console log"); @@ -51,16 +55,28 @@ static ulong ramoops_ftrace_size = MIN_MEM_SIZE; module_param_named(ftrace_size, ramoops_ftrace_size, ulong, 0400); MODULE_PARM_DESC(ftrace_size, "size of ftrace log"); +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) +static ulong ramoops_pmsg_size = 32*1024UL; +#else static ulong ramoops_pmsg_size = MIN_MEM_SIZE; +#endif module_param_named(pmsg_size, ramoops_pmsg_size, ulong, 0400); MODULE_PARM_DESC(pmsg_size, "size of user space message log"); +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) +static ulong mem_address = 0x9ff00000; +#else static ulong mem_address; +#endif module_param(mem_address, ulong, 0400); MODULE_PARM_DESC(mem_address, "start of reserved RAM used to store oops/panic logs"); +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) +static ulong mem_size = 0x100000; +#else static ulong mem_size; +#endif module_param(mem_size, ulong, 0400); MODULE_PARM_DESC(mem_size, "size of reserved RAM used to store oops/panic logs"); diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index 982d333f56850..dce181d03f6a5 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -298,11 +298,25 @@ ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, return ret; } +static void *memcpy_pstore(void *dest, const void *src, size_t count) +{ + char *tmp = dest; + const char *s = src; + + while (count--) + *tmp++ = *s++; + return dest; +} + static void notrace persistent_ram_update(struct persistent_ram_zone *prz, const void *s, unsigned int start, unsigned int count) { struct persistent_ram_buffer *buffer = prz->buffer; +#if (defined CONFIG_MACH_XIAOMI_MIDO) || (defined CONFIG_MACH_XIAOMI_TISSOT) + memcpy_pstore(buffer->data + start, s, count); +#else memcpy(buffer->data + start, s, count); +#endif persistent_ram_update_ecc(prz, start, count); } From 424d901bce604fdf0cb6a32848ac2b678be01390 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Wed, 21 Feb 2018 23:36:51 +0530 Subject: [PATCH 212/508] driver: soc: qcom: Import xiaomi serialnum driver --- drivers/soc/qcom/Kconfig | 5 ++ drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/serial_num.c | 121 ++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 drivers/soc/qcom/serial_num.c diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index c0d99ba847d8b..c6a119a120fe4 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -901,6 +901,11 @@ config WCD_DSP_GLINK between MSM and WCD DSP over glink transport protocol. This driver provides read and write interface via char device. +config SERIAL_NUM + bool "Enable Serial Number Proc Interface" + help + Provide a interface for reading CPU serial number + source "drivers/soc/qcom/memshare/Kconfig" endif # ARCH_MSM diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index fb0ae9187ab74..9be6bdbe10cb0 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -108,3 +108,4 @@ obj-$(CONFIG_MSM_REMOTEQDSS) += remoteqdss.o obj-$(CONFIG_QCOM_SMCINVOKE) += smcinvoke.o obj-$(CONFIG_QCOM_EARLY_RANDOM) += early_random.o obj-$(CONFIG_MSM_HAB) += hab/ +obj-$(CONFIG_SERIAL_NUM) += serial_num.o diff --git a/drivers/soc/qcom/serial_num.c b/drivers/soc/qcom/serial_num.c new file mode 100644 index 0000000000000..01e90d1f45c82 --- /dev/null +++ b/drivers/soc/qcom/serial_num.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define sn_readl(drvdata, off) __raw_readl(drvdata->base + off) + +#define SERIAL_NUM (0x000) + +static uint32_t sn; + +struct sn_drvdata { + void __iomem *base; + struct device *dev; +}; + +static struct sn_drvdata *sndrvdata; + +static int sn_read(struct seq_file *m, void *v) +{ + struct sn_drvdata *drvdata = sndrvdata; + + if (!drvdata) + return false; + + if (sn == 0) + sn = sn_readl(drvdata, SERIAL_NUM); + + dev_dbg(drvdata->dev, "serial num: %x\n", sn); + + seq_printf(m, "0x%x\n", sn); + + return 0; + +} + +static int sn_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, sn_read, NULL); +} + +static const struct file_operations sn_fops = { + .open = sn_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void sn_create_proc(void) +{ + struct proc_dir_entry *entry; + entry = proc_create("serial_num", 0 /* default mode */, + NULL /* parent dir */, &sn_fops); +} + +static int sn_fuse_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct sn_drvdata *drvdata; + struct resource *res; + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + /* Store the driver data pointer for use in exported functions */ + sndrvdata = drvdata; + drvdata->dev = &pdev->dev; + platform_set_drvdata(pdev, drvdata); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sn-base"); + if (!res) + return -ENODEV; + + drvdata->base = devm_ioremap(dev, res->start, resource_size(res)); + if (!drvdata->base) + return -ENOMEM; + + sn_create_proc(); + dev_info(dev, "SN interface initialized\n"); + return 0; +} + +static int sn_fuse_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct of_device_id sn_fuse_match[] = { + {.compatible = "qcom,sn-fuse"}, + {} +}; + +static struct platform_driver sn_fuse_driver = { + .probe = sn_fuse_probe, + .remove = sn_fuse_remove, + .driver = { + .name = "msm-sn-fuse", + .owner = THIS_MODULE, + .of_match_table = sn_fuse_match, + }, +}; + +static int __init sn_fuse_init(void) +{ + return platform_driver_register(&sn_fuse_driver); +} +arch_initcall(sn_fuse_init); + +static void __exit sn_fuse_exit(void) +{ + platform_driver_unregister(&sn_fuse_driver); +} +module_exit(sn_fuse_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("JTag Fuse driver"); From c9e310426e69c03edf38cc2ec2396b5fa467ae2d Mon Sep 17 00:00:00 2001 From: Vitaliy Tomin Date: Thu, 25 Jan 2018 19:17:36 +0530 Subject: [PATCH 213/508] drivers: leds: leds-aw2013: fix compilation --- drivers/leds/leds-aw2013.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-aw2013.c b/drivers/leds/leds-aw2013.c index d0a39fab2821c..1fa2ac5ab38e6 100644 --- a/drivers/leds/leds-aw2013.c +++ b/drivers/leds/leds-aw2013.c @@ -385,7 +385,7 @@ static int aw_2013_check_chipid(struct aw2013_led *led) u8 val; aw2013_write(led, AW_REG_RESET, AW_LED_RESET_MASK); - usleep(AW_LED_RESET_DELAY); + udelay(AW_LED_RESET_DELAY); aw2013_read(led, AW_REG_RESET, &val); if (val == AW2013_CHIPID) return 0; From 1fc159abcd482fb4f10b31ca325f92178745edab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Triszka?= Date: Sat, 20 May 2017 19:06:14 +0000 Subject: [PATCH 214/508] drivers : usb: Increase charge current --- drivers/usb/dwc3/dwc3-msm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index de2a90887e74f..82eb5c266df3a 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -52,8 +52,8 @@ #include "debug.h" #include "xhci.h" -#define DWC3_IDEV_CHG_MAX 1500 -#define DWC3_HVDCP_CHG_MAX 1800 +#define DWC3_IDEV_CHG_MAX 2000 +#define DWC3_HVDCP_CHG_MAX 2000 #define DWC3_WAKEUP_SRC_TIMEOUT 5000 #define MICRO_5V 5000000 From f810429e6a75acb5206478c5ee585d6fb270b8ec Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Fri, 27 Feb 2015 18:31:48 -0800 Subject: [PATCH 215/508] power: reset: Allow device to preserve memory on restart * Always perform a soft reset as this preserves memory contents, including pstore and other persistent memory. Change-Id: Ideca44c9f38d2ebcd437ff289f8e036922eafcd2 --- drivers/power/reset/Kconfig | 9 +++++++++ drivers/power/reset/msm-poweroff.c | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index db933765d38d0..7008160eb0794 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -94,6 +94,15 @@ config MSM_DLOAD_MODE make the kernel reboot on a kernel panic - that must be enabled via another mechanism. +config MSM_PRESERVE_MEM + bool "Always preserve memory on restart" + depends on POWER_RESET_MSM + help + If crash to download mode is disabled and restart reason is null + the system will always perform a hard reset, which wipes out + persistent memory contents. Select this option to always perform + a soft reset that preserves memory contents. + config POWER_RESET_QNAP bool "QNAP power-off driver" depends on OF_GPIO && PLAT_ORION diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index bdb709e212e3a..6e045bca0e850 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -295,6 +295,10 @@ static void msm_restart_prepare(const char *cmd) strcmp(cmd, "userrequested"))); } +#ifdef CONFIG_MSM_PRESERVE_MEM + need_warm_reset = true; +#endif + /* Hard reset the PMIC unless memory contents must be maintained. */ if (need_warm_reset) { qpnp_pon_system_pwr_off(PON_POWER_OFF_WARM_RESET); From ed04ee804b0dadda786262df7c08f75f48093827 Mon Sep 17 00:00:00 2001 From: Vitaliy Tomin Date: Tue, 23 May 2017 00:28:29 +0800 Subject: [PATCH 216/508] drivers: input: touchscreen: ft5435_ts: Create shared procfs nodes * Creates sysfs nodes and procfs symlinks to it to easy handle disable_keys and dt2w functions from userspace --- drivers/input/touchscreen/ft5435/ft5435_ts.c | 116 ++++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/ft5435/ft5435_ts.c b/drivers/input/touchscreen/ft5435/ft5435_ts.c index 7ebb3a2876e03..1e08a2ab04ce4 100644 --- a/drivers/input/touchscreen/ft5435/ft5435_ts.c +++ b/drivers/input/touchscreen/ft5435/ft5435_ts.c @@ -324,6 +324,7 @@ struct work_struct work_vr; u8 vr_on; #endif }; +static bool disable_keys_function = false; bool is_ft5435 = false; struct wake_lock ft5436_wakelock; @@ -1176,7 +1177,7 @@ static irqreturn_t ft5435_ts_interrupt(int irq, void *dev_id) input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0); } } else{ - if (data->pdata->fw_vkey_support) { + if (data->pdata->fw_vkey_support && !disable_keys_function) { for (j = 0; j < data->pdata->num_virkey; j++) { if (x == data->pdata->vkeys[j].x) { if (status == FT_TOUCH_DOWN || status == FT_TOUCH_CONTACT) @@ -3645,6 +3646,112 @@ static void ft5x0x_release_apk_debug_channel(void) } #endif +static ssize_t ft5435_ts_disable_keys_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const char c = disable_keys_function ? '1' : '0'; + return sprintf(buf, "%c\n", c); +} + +static ssize_t ft5435_ts_disable_keys_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int i; + + if (sscanf(buf, "%u", &i) == 1 && i < 2) { + disable_keys_function = (i == 1); + return count; + } else { + dev_dbg(dev, "disable_keys write error\n"); + return -EINVAL; + } +} + + +static DEVICE_ATTR(disable_keys, S_IWUSR | S_IRUSR, ft5435_ts_disable_keys_show, + ft5435_ts_disable_keys_store); + + + +static ssize_t ft5435_ts_enable_dt2w_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const char c = gesture_func_on ? '1' : '0'; + return sprintf(buf, "%c\n", c); +} + +static ssize_t ft5435_ts_enable_dt2w_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int i; + + if (sscanf(buf, "%u", &i) == 1 && i < 2) { + gesture_func_on = (i == 1); + return count; + } else { + dev_dbg(dev, "enable_dt2w write error\n"); + return -EINVAL; + } +} + + +static DEVICE_ATTR(enable_dt2w, S_IWUSR | S_IRUSR, ft5435_ts_enable_dt2w_show, + ft5435_ts_enable_dt2w_store); + +static struct attribute *ft5435_ts_attrs[] = { + &dev_attr_disable_keys.attr, + &dev_attr_enable_dt2w.attr, + NULL +}; + + +static const struct attribute_group ft5435_ts_attr_group = { + .attrs = ft5435_ts_attrs, +}; + +static int ft5435_proc_init(struct kernfs_node *sysfs_node_parent) +{ + int ret = 0; + char *buf, *path = NULL; + char *key_disabler_sysfs_node, *double_tap_sysfs_node; + struct proc_dir_entry *proc_entry_tp = NULL; + struct proc_dir_entry *proc_symlink_tmp = NULL; + buf = kzalloc(PATH_MAX, GFP_KERNEL); + if (buf) + path = kernfs_path(sysfs_node_parent, buf, PATH_MAX); + + proc_entry_tp = proc_mkdir("touchpanel", NULL); + if (proc_entry_tp == NULL) { + pr_err("%s: Couldn't create touchpanel dir in procfs\n", __func__); + ret = -ENOMEM; + } + + key_disabler_sysfs_node = kzalloc(PATH_MAX, GFP_KERNEL); + if (key_disabler_sysfs_node) + sprintf(key_disabler_sysfs_node, "/sys%s/%s", path, "disable_keys"); + proc_symlink_tmp = proc_symlink("capacitive_keys_disable", + proc_entry_tp, key_disabler_sysfs_node); + if (proc_symlink_tmp == NULL) { + pr_err("%s: Couldn't create capacitive_keys_enable symlink\n", __func__); + ret = -ENOMEM; + } + + double_tap_sysfs_node = kzalloc(PATH_MAX, GFP_KERNEL); + if (double_tap_sysfs_node) + sprintf(double_tap_sysfs_node, "/sys%s/%s", path, "enable_dt2w"); + proc_symlink_tmp = proc_symlink("enable_dt2w", + proc_entry_tp, double_tap_sysfs_node); + if (proc_symlink_tmp == NULL) { + ret = -ENOMEM; + pr_err("%s: Couldn't create double_tap_enable symlink\n", __func__); + } + + kfree(buf); + kfree(key_disabler_sysfs_node); + kfree(double_tap_sysfs_node); + return ret; +} + static char tp_info_summary[80] = ""; static int ft5435_ts_probe(struct i2c_client *client, @@ -4096,6 +4203,13 @@ g_ft5435_ts_data = data; if (ft5x0x_create_apk_debug_channel(client) < 0) ft5x0x_release_apk_debug_channel(); #endif + err = sysfs_create_group(&client->dev.kobj, &ft5435_ts_attr_group); + if (err) { + dev_err(&client->dev, "Failure %d creating sysfs group\n", + err); + goto free_reset_gpio; + } + ft5435_proc_init(client->dev.kobj.sd); w_buf[0] = FT_REG_RESET_FW; ft5435_i2c_write(client, w_buf, 1); From d4c4626d222252473d76a0f936272770cc84baea Mon Sep 17 00:00:00 2001 From: Vitaliy Tomin Date: Tue, 23 May 2017 12:41:55 +0800 Subject: [PATCH 217/508] drivers: input: touchscreen: ist30xxc: Create shared procfs nodes * Creates sysfs nodes and procfs symlinks to it to easy handle disable_keys and dt2w functions from userspace --- drivers/input/touchscreen/ist3038c/ist30xxc.c | 131 +++++++++++++++++- 1 file changed, 126 insertions(+), 5 deletions(-) diff --git a/drivers/input/touchscreen/ist3038c/ist30xxc.c b/drivers/input/touchscreen/ist3038c/ist30xxc.c index b485ab5ea1bec..c752b1859da41 100644 --- a/drivers/input/touchscreen/ist3038c/ist30xxc.c +++ b/drivers/input/touchscreen/ist3038c/ist30xxc.c @@ -76,6 +76,8 @@ struct ist30xx_data *ts_data; extern int set_usb_charge_mode_par; int ist30xx_log_level = IST30XX_LOG_LEVEL; +static bool disable_keys_function = false; + void tsp_printk(int level, const char *fmt, ...) { struct va_format vaf; @@ -814,13 +816,15 @@ static void report_input_data(struct ist30xx_data *data, int finger_counts, } #ifdef IST30XX_USE_KEY - status = PARSE_KEY_STATUS(data->t_status); - for (id = 0; id < ARRAY_SIZE(ist30xx_key_code); id++) { - press = (status & (1 << id)) ? true : false; + if(!disable_keys_function) { + status = PARSE_KEY_STATUS(data->t_status); + for (id = 0; id < ARRAY_SIZE(ist30xx_key_code); id++) { + press = (status & (1 << id)) ? true : false; - input_report_key(data->input_dev, ist30xx_key_code[id], press); + input_report_key(data->input_dev, ist30xx_key_code[id], press); - print_tkey_event(data, id); + print_tkey_event(data, id); + } } #endif @@ -1903,6 +1907,115 @@ static int fb_notifier_callback(struct notifier_block *self, } #endif + +static ssize_t ist30xx_ts_disable_keys_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const char c = disable_keys_function ? '1' : '0'; + return sprintf(buf, "%c\n", c); +} + +static ssize_t ist30xx_ts_disable_keys_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int i; + + if (sscanf(buf, "%u", &i) == 1 && i < 2) { + disable_keys_function = (i == 1); + return count; + } else { + dev_dbg(dev, "disable_keys write error\n"); + return -EINVAL; + } +} + + +static DEVICE_ATTR(disable_keys, S_IWUSR | S_IRUSR, ist30xx_ts_disable_keys_show, + ist30xx_ts_disable_keys_store); + + + +static ssize_t ist30xx_ts_enable_dt2w_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const char c = ist30xx_gesture_func_on ? '1' : '0'; + return sprintf(buf, "%c\n", c); +} + +static ssize_t ist30xx_ts_enable_dt2w_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int i; + + if (sscanf(buf, "%u", &i) == 1 && i < 2) { + ist30xx_gesture_func_on = (i == 1); + return count; + } else { + dev_dbg(dev, "enable_dt2w write error\n"); + return -EINVAL; + } +} + + +static DEVICE_ATTR(enable_dt2w, S_IWUSR | S_IRUSR, ist30xx_ts_enable_dt2w_show, + ist30xx_ts_enable_dt2w_store); + +static struct attribute *ist30xx_ts_attrs[] = { + &dev_attr_disable_keys.attr, + &dev_attr_enable_dt2w.attr, + NULL +}; + + +static const struct attribute_group ist30xx_ts_attr_group = { + .attrs = ist30xx_ts_attrs, +}; + +static int ist30xx_proc_init(struct kernfs_node *sysfs_node_parent) +{ + int ret = 0; + char *buf, *path = NULL; + char *key_disabler_sysfs_node, *double_tap_sysfs_node; + struct proc_dir_entry *proc_entry_tp = NULL; + struct proc_dir_entry *proc_symlink_tmp = NULL; + buf = kzalloc(PATH_MAX, GFP_KERNEL); + if (buf) + path = kernfs_path(sysfs_node_parent, buf, PATH_MAX); + + proc_entry_tp = proc_mkdir("touchpanel", NULL); + if (proc_entry_tp == NULL) { + pr_err("%s: Couldn't create touchpanel dir in procfs\n", __func__); + ret = -ENOMEM; + } + + key_disabler_sysfs_node = kzalloc(PATH_MAX, GFP_KERNEL); + if (key_disabler_sysfs_node) + sprintf(key_disabler_sysfs_node, "/sys%s/%s", path, "disable_keys"); + proc_symlink_tmp = proc_symlink("capacitive_keys_disable", + proc_entry_tp, key_disabler_sysfs_node); + if (proc_symlink_tmp == NULL) { + pr_err("%s: Couldn't create capacitive_keys_enable symlink\n", __func__); + ret = -ENOMEM; + } + + double_tap_sysfs_node = kzalloc(PATH_MAX, GFP_KERNEL); + if (double_tap_sysfs_node) + sprintf(double_tap_sysfs_node, "/sys%s/%s", path, "enable_dt2w"); + proc_symlink_tmp = proc_symlink("enable_dt2w", + proc_entry_tp, double_tap_sysfs_node); + if (proc_symlink_tmp == NULL) { + ret = -ENOMEM; + pr_err("%s: Couldn't create double_tap_enable symlink\n", __func__); + } + + kfree(buf); + kfree(key_disabler_sysfs_node); + kfree(double_tap_sysfs_node); + return ret; +} + + + static char tp_info_summary[80] = ""; static int ist30xx_probe(struct i2c_client *client, @@ -2180,6 +2293,14 @@ static int ist30xx_probe(struct i2c_client *client, ist30xx_start(data); data->initialized = true; #endif + + ret = sysfs_create_group(&client->dev.kobj, &ist30xx_ts_attr_group); + if (ret) { + dev_err(&client->dev, "Failure %d creating sysfs group\n",ret); + goto err_alloc_dt; + } + ist30xx_proc_init(client->dev.kobj.sd); + strcpy(tp_info_summary, "[Vendor]Dongshan, [IC]IST3038C, [FW]Ver"); sprintf(tp_temp_info, "%x", data->fw.bin.fw_ver); strcat(tp_info_summary, tp_temp_info); From 24134bfd5806a4697a4b7b1ae6f6ed26d2f7c9fe Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Thu, 25 Jan 2018 21:21:14 +0530 Subject: [PATCH 218/508] drivers: input: touchscreen: gt9xx_mido: Create shared procfs nodes * Creates sysfs nodes and procfs symlinks to it to easy handle disable_keys and dt2w functions from userspaceCreate shared procfs nodes --- drivers/input/touchscreen/gt9xx_mido/gt9xx.c | 112 ++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/gt9xx_mido/gt9xx.c b/drivers/input/touchscreen/gt9xx_mido/gt9xx.c index d54ce7b8d8ce2..a132c4dfa549b 100644 --- a/drivers/input/touchscreen/gt9xx_mido/gt9xx.c +++ b/drivers/input/touchscreen/gt9xx_mido/gt9xx.c @@ -56,6 +56,7 @@ extern int set_usb_charge_mode_par; int gt9xx_id; int gt9xx_flag; +static bool disable_keys_function = false; @@ -876,7 +877,7 @@ static void goodix_ts_work_func(struct work_struct *work) #endif #if GTP_HAVE_TOUCH_KEY - if (!pre_touch) { + if (!pre_touch && !disable_keys_function) { for (i = 0; i < GTP_MAX_KEY_NUM; i++) { #if GTP_DEBUG_ON for (ret = 0; ret < 4; ++ret) { @@ -2558,6 +2559,107 @@ void gtp_usb_plugin(bool mode) GTP_ERROR("GTP send Charge cmd failed."); } +static ssize_t gt9xx_mido_disable_keys_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const char c = disable_keys_function ? '1' : '0'; + return sprintf(buf, "%c\n", c); +} + +static ssize_t gt9xx_mido_disable_keys_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int i; + + if (sscanf(buf, "%u", &i) == 1 && i < 2) { + disable_keys_function = (i == 1); + return count; + } else { + dev_dbg(dev, "disable_keys write error\n"); + return -EINVAL; + } +} + +static DEVICE_ATTR(disable_keys, S_IWUSR | S_IRUSR, gt9xx_mido_disable_keys_show, + gt9xx_mido_disable_keys_store); + +static ssize_t gt9xx_mido_enable_dt2w_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const char c = gtp_gesture_func_on ? '1' : '0'; + return sprintf(buf, "%c\n", c); +} + +static ssize_t gt9xx_mido_enable_dt2w_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int i; + + if (sscanf(buf, "%u", &i) == 1 && i < 2) { + gtp_gesture_func_on = (i == 1); + return count; + } else { + dev_dbg(dev, "enable_dt2w write error\n"); + return -EINVAL; + } +} + + +static DEVICE_ATTR(enable_dt2w, S_IWUSR | S_IRUSR, gt9xx_mido_enable_dt2w_show, + gt9xx_mido_enable_dt2w_store); + +static struct attribute *gt9xx_mido_attrs[] = { + &dev_attr_disable_keys.attr, + &dev_attr_enable_dt2w.attr, + NULL +}; + +static const struct attribute_group gt9xx_mido_attr_group = { + .attrs = gt9xx_mido_attrs, +}; + +static int gt9xx_mido_proc_init(struct kernfs_node *sysfs_node_parent) +{ + int ret = 0; + char *buf, *path = NULL; + char *key_disabler_sysfs_node, *double_tap_sysfs_node; + struct proc_dir_entry *proc_entry_tp = NULL; + struct proc_dir_entry *proc_symlink_tmp = NULL; + buf = kzalloc(PATH_MAX, GFP_KERNEL); + if (buf) + path = kernfs_path(sysfs_node_parent, buf, PATH_MAX); + + proc_entry_tp = proc_mkdir("touchpanel", NULL); + if (proc_entry_tp == NULL) { + pr_err("%s: Couldn't create touchpanel dir in procfs\n", __func__); + ret = -ENOMEM; + } + + key_disabler_sysfs_node = kzalloc(PATH_MAX, GFP_KERNEL); + if (key_disabler_sysfs_node) + sprintf(key_disabler_sysfs_node, "/sys%s/%s", path, "disable_keys"); + proc_symlink_tmp = proc_symlink("capacitive_keys_disable", + proc_entry_tp, key_disabler_sysfs_node); + if (proc_symlink_tmp == NULL) { + pr_err("%s: Couldn't create capacitive_keys_enable symlink\n", __func__); + ret = -ENOMEM; + } + + double_tap_sysfs_node = kzalloc(PATH_MAX, GFP_KERNEL); + if (double_tap_sysfs_node) + sprintf(double_tap_sysfs_node, "/sys%s/%s", path, "enable_dt2w"); + proc_symlink_tmp = proc_symlink("enable_dt2w", + proc_entry_tp, double_tap_sysfs_node); + if (proc_symlink_tmp == NULL) { + ret = -ENOMEM; + pr_err("%s: Couldn't create double_tap_enable symlink\n", __func__); + } + + kfree(buf); + kfree(key_disabler_sysfs_node); + kfree(double_tap_sysfs_node); + return ret; +} /******************************************************* Function: @@ -2714,6 +2816,14 @@ static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id GTP_INFO("create_glove_proc %s success", GT91XX_Glove_PROC_FILE); } + ret = sysfs_create_group(&client->dev.kobj, >9xx_mido_attr_group); + if (ret) { + dev_err(&client->dev, "Failure %d creating sysfs group\n", + ret); + sysfs_remove_group(&client->dev.kobj, >9xx_mido_attr_group); + } + gt9xx_mido_proc_init(client->dev.kobj.sd); + #if GTP_ESD_PROTECT gtp_esd_switch(client, SWITCH_ON); From 7d35a6b7c2d664f418349e6fc729957e60458579 Mon Sep 17 00:00:00 2001 From: Vitaliy Tomin Date: Tue, 23 May 2017 17:45:10 +0800 Subject: [PATCH 219/508] drivers: input: touchscreen: ft5435: enable glove mode sysfs node --- drivers/input/touchscreen/ft5435/ft5435_ts.c | 10 ++++------ drivers/input/touchscreen/ft5435/ft5435_ts.h | 1 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/input/touchscreen/ft5435/ft5435_ts.c b/drivers/input/touchscreen/ft5435/ft5435_ts.c index 1e08a2ab04ce4..fddbb201970fa 100644 --- a/drivers/input/touchscreen/ft5435/ft5435_ts.c +++ b/drivers/input/touchscreen/ft5435/ft5435_ts.c @@ -491,13 +491,10 @@ static ssize_t tp_glove_id_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ft5435_ts_data *data = NULL; - int ret; data = dev_get_drvdata(dev); - ret = snprintf(buf, 50, "glove_id show:%d\n", data->glove_id); - - return ret; + return sprintf(buf, "%d", data->glove_id); } static ssize_t tp_glove_id_store(struct device *dev, @@ -546,8 +543,9 @@ static DEVICE_ATTR(glove_enable, 0644, tp_glove_id_show, tp_glove_id_store); void tp_glove_register (struct ft5435_ts_data *data) { int rc = 0; - - tp_glove_dev = device_create(tp_device_class, NULL, 0, NULL, "tp_glove"); + struct class *tp_device_class = NULL; + tp_device_class = class_create(THIS_MODULE, "tp_glove"); + tp_glove_dev = device_create(tp_device_class, NULL, 0, NULL, "device"); if (IS_ERR(tp_glove_dev)) pr_err("Failed to create device(glove_ctrl)!\n"); diff --git a/drivers/input/touchscreen/ft5435/ft5435_ts.h b/drivers/input/touchscreen/ft5435/ft5435_ts.h index f7cd6f8106939..f309692b80c34 100644 --- a/drivers/input/touchscreen/ft5435/ft5435_ts.h +++ b/drivers/input/touchscreen/ft5435/ft5435_ts.h @@ -35,6 +35,7 @@ #define FOCALTECH_LOCK_DOWN_INFO 1 #define FOCALTECH_TP_GESTURE #define FOCALTECH_FAE_MOD +#define FOCALTECH_TP_GLOVE #define USB_CHARGE_DETECT #define FOCALTECH_ITO_TEST 1 From 38ba2ea547c079f45ce8ba6c6a66c828a034f1e5 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Thu, 25 Jan 2018 22:25:59 +0530 Subject: [PATCH 220/508] arch: arm: dts: mido: Increase max led brightness --- arch/arm/boot/dts/qcom/mido/msm8953-general-mido.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/qcom/mido/msm8953-general-mido.dtsi b/arch/arm/boot/dts/qcom/mido/msm8953-general-mido.dtsi index 390a28aabde03..cb00a4f9fdec1 100644 --- a/arch/arm/boot/dts/qcom/mido/msm8953-general-mido.dtsi +++ b/arch/arm/boot/dts/qcom/mido/msm8953-general-mido.dtsi @@ -433,7 +433,7 @@ aw2013,red { aw2013,name = "red"; aw2013,id = <0>; - aw2013,max-brightness = <150>; + aw2013,max-brightness = <255>; aw2013,max-current = <1>; aw2013,rise-time-ms = <3>; aw2013,hold-time-ms = <1>; @@ -444,7 +444,7 @@ aw2013,green { aw2013,name = "green"; aw2013,id = <1>; - aw2013,max-brightness = <150>; + aw2013,max-brightness = <255>; aw2013,max-current = <1>; aw2013,rise-time-ms = <3>; aw2013,hold-time-ms = <1>; @@ -455,7 +455,7 @@ aw2013,blue { aw2013,name = "blue"; aw2013,id = <2>; - aw2013,max-brightness = <150>; + aw2013,max-brightness = <255>; aw2013,max-current = <1>; aw2013,rise-time-ms = <3>; aw2013,hold-time-ms = <1>; From 8c2405892d6df8639c85daaaeae0d108544c87a3 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Thu, 25 May 2017 13:00:49 +0000 Subject: [PATCH 221/508] drivers: input: Stop ft5435 spam --- drivers/input/touchscreen/ft5435/ft5435_ts.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/input/touchscreen/ft5435/ft5435_ts.c b/drivers/input/touchscreen/ft5435/ft5435_ts.c index fddbb201970fa..848a5b05b8542 100644 --- a/drivers/input/touchscreen/ft5435/ft5435_ts.c +++ b/drivers/input/touchscreen/ft5435/ft5435_ts.c @@ -1161,11 +1161,6 @@ static irqreturn_t ft5435_ts_interrupt(int irq, void *dev_id) break; input_mt_slot(ip_dev, id); - if (status == FT_TOUCH_DOWN) - printk("[FTS]Down pid[%d]:[%d, %d]\n", id, x, y); - else if (status == 1) - printk("[FTS]Up pid[%d]:[%d, %d]\n", id, x, y); - if (x < data->pdata->panel_maxx && y < data->pdata->panel_maxy) { if (status == FT_TOUCH_DOWN || status == FT_TOUCH_CONTACT) { input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1); From a19c0531a282370935f0e7e2251930e5335fe7d9 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Thu, 25 May 2017 13:07:50 +0000 Subject: [PATCH 222/508] driver: input: fingerprint: undef goodix debug --- drivers/input/fingerprint/goodix_mido/gf_spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/fingerprint/goodix_mido/gf_spi.c b/drivers/input/fingerprint/goodix_mido/gf_spi.c index 49e5a2a0844cd..8c315a8ad546e 100644 --- a/drivers/input/fingerprint/goodix_mido/gf_spi.c +++ b/drivers/input/fingerprint/goodix_mido/gf_spi.c @@ -81,8 +81,8 @@ struct gf_key_map key_map[] = { }; /**************************debug******************************/ -#define GF_DEBUG -/*#undef GF_DEBUG*/ +/*#define GF_DEBUG*/ +#undef GF_DEBUG #ifdef GF_DEBUG #define gf_dbg(fmt, args...) do { \ From 624f7dba2aa8748bcd0b3453800d2538a823b337 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Thu, 25 May 2017 13:17:35 +0000 Subject: [PATCH 223/508] drivers: input: touchscreen: Set set_cover_mode permission to 0220 Fixes: [ 1.140622] Attribute set_cover_mode: read permission without 'show' --- drivers/input/touchscreen/ft5435/ft5435_ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/ft5435/ft5435_ts.c b/drivers/input/touchscreen/ft5435/ft5435_ts.c index 848a5b05b8542..0174bd21638d5 100644 --- a/drivers/input/touchscreen/ft5435/ft5435_ts.c +++ b/drivers/input/touchscreen/ft5435/ft5435_ts.c @@ -2738,7 +2738,7 @@ static ssize_t fts_set_cover_mode(struct device *dev, } return ret; } -static DEVICE_ATTR(set_cover_mode, 0664, NULL, +static DEVICE_ATTR(set_cover_mode, 0220, NULL, fts_set_cover_mode); #endif From c778302913f8d5968198839c9d09dee616a14643 Mon Sep 17 00:00:00 2001 From: Thierry Strudel Date: Mon, 11 Jul 2016 16:00:49 -0700 Subject: [PATCH 224/508] removing msm calls to trace_printk Bug: 27997214 Change-Id: If5cbd097a082ff05c174bc0531276c97c191087e Signed-off-by: Thierry Strudel --- .../media/platform/msm/vidc/msm_vidc_debug.h | 4 ---- .../msm/msm_bus/msm_bus_fabric_adhoc.c | 19 ------------------- drivers/video/msm/ba/msm_ba_debug.h | 5 ----- 3 files changed, 28 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h index ec9ec267a92e5..7c156e1026aa2 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_debug.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.h @@ -109,10 +109,6 @@ extern int msm_vidc_debug_timeout; pr_info(VIDC_DBG_TAG __fmt, \ VIDC_MSG_PRIO2STRING(__level), \ ## arg); \ - } else if (msm_vidc_debug_out == VIDC_OUT_FTRACE) { \ - trace_printk(KERN_DEBUG VIDC_DBG_TAG __fmt, \ - VIDC_MSG_PRIO2STRING(__level), \ - ## arg); \ } \ } \ } while (0) diff --git a/drivers/platform/msm/msm_bus/msm_bus_fabric_adhoc.c b/drivers/platform/msm/msm_bus/msm_bus_fabric_adhoc.c index 146d7c6d70a84..1c4dca20e90a2 100644 --- a/drivers/platform/msm/msm_bus/msm_bus_fabric_adhoc.c +++ b/drivers/platform/msm/msm_bus/msm_bus_fabric_adhoc.c @@ -52,13 +52,6 @@ ssize_t bw_show(struct device *dev, struct device_attribute *attr, bus_node->lnode_list[i].lnode_ab[ACTIVE_CTX], bus_node->lnode_list[i].lnode_ib[DUAL_CTX], bus_node->lnode_list[i].lnode_ab[DUAL_CTX]); - trace_printk( - "[%d]:%s:Act_IB %llu Act_AB %llu Slp_IB %llu Slp_AB %llu\n", - i, bus_node->lnode_list[i].cl_name, - bus_node->lnode_list[i].lnode_ib[ACTIVE_CTX], - bus_node->lnode_list[i].lnode_ab[ACTIVE_CTX], - bus_node->lnode_list[i].lnode_ib[DUAL_CTX], - bus_node->lnode_list[i].lnode_ab[DUAL_CTX]); } off += scnprintf((buf + off), PAGE_SIZE, "Max_Act_IB %llu Sum_Act_AB %llu Act_Util_fact %d Act_Vrail_comp %d\n", @@ -72,18 +65,6 @@ ssize_t bw_show(struct device *dev, struct device_attribute *attr, bus_node->node_bw[DUAL_CTX].sum_ab, bus_node->node_bw[DUAL_CTX].util_used, bus_node->node_bw[DUAL_CTX].vrail_used); - trace_printk( - "Max_Act_IB %llu Sum_Act_AB %llu Act_Util_fact %d Act_Vrail_comp %d\n", - bus_node->node_bw[ACTIVE_CTX].max_ib, - bus_node->node_bw[ACTIVE_CTX].sum_ab, - bus_node->node_bw[ACTIVE_CTX].util_used, - bus_node->node_bw[ACTIVE_CTX].vrail_used); - trace_printk( - "Max_Slp_IB %llu Sum_Slp_AB %lluSlp_Util_fact %d Slp_Vrail_comp %d\n", - bus_node->node_bw[DUAL_CTX].max_ib, - bus_node->node_bw[DUAL_CTX].sum_ab, - bus_node->node_bw[DUAL_CTX].util_used, - bus_node->node_bw[DUAL_CTX].vrail_used); return off; } diff --git a/drivers/video/msm/ba/msm_ba_debug.h b/drivers/video/msm/ba/msm_ba_debug.h index baabb712cc58f..65c2b024824e3 100644 --- a/drivers/video/msm/ba/msm_ba_debug.h +++ b/drivers/video/msm/ba/msm_ba_debug.h @@ -65,11 +65,6 @@ extern int msm_ba_debug_out; __LINE__, \ BA_MSG_PRIO2STRING(__level), \ ## arg); \ - } else if (msm_ba_debug_out == BA_OUT_FTRACE) { \ - trace_printk(KERN_DEBUG BA_DBG_TAG __fmt "\n", \ - __LINE__, \ - BA_MSG_PRIO2STRING(__level), \ - ## arg); \ } \ } \ } while (0) From fed337d37eab12238cdae303d5f28088bd638cfa Mon Sep 17 00:00:00 2001 From: Fatih Akca Date: Mon, 20 Feb 2017 20:50:32 +0300 Subject: [PATCH 225/508] mm: swap_ratio: Only call trace_printk() in debug * Use DEBUG preprocessor macro to get rid of the message seen below on dmesg. ********************************************************** ** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE ** ** ** ** trace_printk() being used. Allocating extra memory. ** ** ** ** This means that this is a DEBUG kernel and it is ** ** unsafe for produciton use. ** ** ** ** If you see this message and you are not debugging ** ** the kernel, report this immediately to your vendor! ** ** ** ** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE ** ********************************************************** The usage of trace_printk() causes remarkable CPU load and memory waste on production systems, as described here: https://lkml.org/lkml/2014/5/28/496 Change-Id: Idf89e2a1405edf2efa6526d18892eaa7e9a6221b --- mm/swap_ratio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/swap_ratio.c b/mm/swap_ratio.c index cf2a6e2ae1357..fa889105ced02 100644 --- a/mm/swap_ratio.c +++ b/mm/swap_ratio.c @@ -67,7 +67,9 @@ static int calculate_write_pending(struct swap_info_struct *si, si->write_pending = si->max_writes; n->write_pending = n->max_writes; +#if defined(CONFIG_TRACING) && defined(DEBUG) trace_printk("%u, %u\n", si->max_writes, n->max_writes); +#endif return 0; } From 1b92c3cf68616654ee5eb3a1201d812d7c92d782 Mon Sep 17 00:00:00 2001 From: Willi Ye Date: Sun, 13 Sep 2015 12:24:59 +0200 Subject: [PATCH 226/508] qpnp-haptic: Add sysfs interface to control intensity Change-Id: Ib8ad562c5e847a8511bf1e2dbda7c0f863ea25dd --- drivers/platform/msm/qpnp-haptic.c | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/platform/msm/qpnp-haptic.c b/drivers/platform/msm/qpnp-haptic.c index b31cd841e43be..1e4f484c9ad9c 100644 --- a/drivers/platform/msm/qpnp-haptic.c +++ b/drivers/platform/msm/qpnp-haptic.c @@ -1379,6 +1379,44 @@ static ssize_t qpnp_hap_ramp_test_data_show(struct device *dev, } +static ssize_t qpnp_hap_vmax_mv_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct timed_output_dev *timed_dev = dev_get_drvdata(dev); + struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap, + timed_dev); + + return snprintf(buf, PAGE_SIZE, "%d\n", hap->vmax_mv); +} + +static ssize_t qpnp_hap_vmax_mv_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct timed_output_dev *timed_dev = dev_get_drvdata(dev); + struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap, + timed_dev); + u32 data; + int rc; + + if (sscanf(buf, "%d", &data) != 1) + return -EINVAL; + + if (data < QPNP_HAP_VMAX_MIN_MV) { + pr_err("%s: mv %d not in range (%d - %d), using min.", __func__, data, QPNP_HAP_VMAX_MIN_MV, QPNP_HAP_VMAX_MAX_MV); + data = QPNP_HAP_VMAX_MIN_MV; + } else if (data > QPNP_HAP_VMAX_MAX_MV) { + pr_err("%s: mv %d not in range (%d - %d), using max.", __func__, data, QPNP_HAP_VMAX_MIN_MV, QPNP_HAP_VMAX_MAX_MV); + data = QPNP_HAP_VMAX_MAX_MV; + } + + hap->vmax_mv = data; + rc = qpnp_hap_vmax_config(hap); + if (rc) + pr_info("qpnp: error while writing vibration control register\n"); + + return strnlen(buf, count); +} + /* sysfs attributes */ static struct device_attribute qpnp_hap_attrs[] = { __ATTR(wf_s0, (S_IRUGO | S_IWUSR | S_IWGRP), @@ -1426,6 +1464,9 @@ static struct device_attribute qpnp_hap_attrs[] = { __ATTR(min_max_test, (S_IRUGO | S_IWUSR | S_IWGRP), qpnp_hap_min_max_test_data_show, qpnp_hap_min_max_test_data_store), + __ATTR(vmax_mv, (S_IRUGO | S_IWUSR | S_IWGRP), + qpnp_hap_vmax_mv_show, + qpnp_hap_vmax_mv_store), }; static int calculate_lra_code(struct qpnp_hap *hap) From bbc25f696a5d0ae21607b76f3d6f2bb301bf495d Mon Sep 17 00:00:00 2001 From: dianlujitao Date: Fri, 1 Jul 2016 22:17:42 +0800 Subject: [PATCH 227/508] msm: qpnp-haptic: set up sysfs interface for common cmhw implementation * Rename vmax_mv to vtg_level * Add min/max/default voltage sysfs entries Change-Id: Iefa3accdb75fcef9bcb2d4c730ca0a72763994f3 --- drivers/platform/msm/qpnp-haptic.c | 98 ++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 12 deletions(-) diff --git a/drivers/platform/msm/qpnp-haptic.c b/drivers/platform/msm/qpnp-haptic.c index 1e4f484c9ad9c..c7afbb65b3ac0 100644 --- a/drivers/platform/msm/qpnp-haptic.c +++ b/drivers/platform/msm/qpnp-haptic.c @@ -357,6 +357,9 @@ struct qpnp_hap { u32 timeout_ms; u32 time_required_to_generate_back_emf_us; u32 vmax_mv; + u32 vtg_min; + u32 vtg_max; + u32 vtg_default; u32 ilim_ma; u32 sc_deb_cycles; u32 int_pwm_freq_khz; @@ -785,16 +788,16 @@ static int qpnp_hap_vmax_config(struct qpnp_hap *hap) u8 reg = 0; int rc, temp; - if (hap->vmax_mv < QPNP_HAP_VMAX_MIN_MV) - hap->vmax_mv = QPNP_HAP_VMAX_MIN_MV; - else if (hap->vmax_mv > QPNP_HAP_VMAX_MAX_MV) - hap->vmax_mv = QPNP_HAP_VMAX_MAX_MV; + if (hap->vmax_mv < hap->vtg_min) + hap->vmax_mv = hap->vtg_min; + else if (hap->vmax_mv > hap->vtg_max) + hap->vmax_mv = hap->vtg_max; rc = qpnp_hap_read_reg(hap, ®, QPNP_HAP_VMAX_REG(hap->base)); if (rc < 0) return rc; reg &= QPNP_HAP_VMAX_MASK; - temp = hap->vmax_mv / QPNP_HAP_VMAX_MIN_MV; + temp = hap->vmax_mv / hap->vtg_min; reg |= (temp << QPNP_HAP_VMAX_SHIFT); rc = qpnp_hap_write_reg(hap, ®, QPNP_HAP_VMAX_REG(hap->base)); if (rc) @@ -1401,12 +1404,14 @@ static ssize_t qpnp_hap_vmax_mv_store(struct device *dev, if (sscanf(buf, "%d", &data) != 1) return -EINVAL; - if (data < QPNP_HAP_VMAX_MIN_MV) { - pr_err("%s: mv %d not in range (%d - %d), using min.", __func__, data, QPNP_HAP_VMAX_MIN_MV, QPNP_HAP_VMAX_MAX_MV); - data = QPNP_HAP_VMAX_MIN_MV; - } else if (data > QPNP_HAP_VMAX_MAX_MV) { - pr_err("%s: mv %d not in range (%d - %d), using max.", __func__, data, QPNP_HAP_VMAX_MIN_MV, QPNP_HAP_VMAX_MAX_MV); - data = QPNP_HAP_VMAX_MAX_MV; + if (data < hap->vtg_min) { + pr_err("%s: mv %d not in range (%d - %d), using min.", __func__, data, + hap->vtg_min, hap->vtg_max); + data = hap->vtg_min; + } else if (data > hap->vtg_max) { + pr_err("%s: mv %d not in range (%d - %d), using max.", __func__, data, + hap->vtg_min, hap->vtg_max); + data = hap->vtg_max; } hap->vmax_mv = data; @@ -1417,6 +1422,39 @@ static ssize_t qpnp_hap_vmax_mv_store(struct device *dev, return strnlen(buf, count); } +static ssize_t qpnp_hap_min_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct timed_output_dev *timed_dev = dev_get_drvdata(dev); + struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap, + timed_dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", hap->vtg_min); +} + +static ssize_t qpnp_hap_max_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct timed_output_dev *timed_dev = dev_get_drvdata(dev); + struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap, + timed_dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", hap->vtg_max); +} + +static ssize_t qpnp_hap_default_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct timed_output_dev *timed_dev = dev_get_drvdata(dev); + struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap, + timed_dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", hap->vtg_default); +} + /* sysfs attributes */ static struct device_attribute qpnp_hap_attrs[] = { __ATTR(wf_s0, (S_IRUGO | S_IWUSR | S_IWGRP), @@ -1464,9 +1502,18 @@ static struct device_attribute qpnp_hap_attrs[] = { __ATTR(min_max_test, (S_IRUGO | S_IWUSR | S_IWGRP), qpnp_hap_min_max_test_data_show, qpnp_hap_min_max_test_data_store), - __ATTR(vmax_mv, (S_IRUGO | S_IWUSR | S_IWGRP), + __ATTR(vtg_level, (S_IRUGO | S_IWUSR | S_IWGRP), qpnp_hap_vmax_mv_show, qpnp_hap_vmax_mv_store), + __ATTR(vtg_min, S_IRUGO, + qpnp_hap_min_show, + NULL), + __ATTR(vtg_max, S_IRUGO, + qpnp_hap_max_show, + NULL), + __ATTR(vtg_default, S_IRUGO, + qpnp_hap_default_show, + NULL), }; static int calculate_lra_code(struct qpnp_hap *hap) @@ -2431,6 +2478,33 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap) return rc; } + hap->vtg_min = QPNP_HAP_VMAX_MIN_MV; + rc = of_property_read_u32(spmi->dev.of_node, + "qcom,hap-vtg-min-mv", &temp); + if (!rc) { + hap->vtg_min = temp; + } else if (rc != -EINVAL) { + dev_err(&spmi->dev, "Unable to read vtg_min\n"); + return rc; + } + + hap->vtg_max = QPNP_HAP_VMAX_MAX_MV; + rc = of_property_read_u32(spmi->dev.of_node, + "qcom,hap-vtg-max-mv", &temp); + if (!rc) { + hap->vtg_max = temp; + } else if (rc != -EINVAL) { + dev_err(&spmi->dev, "Unable to read vtg_max\n"); + return rc; + } + + if (hap->vmax_mv < hap->vtg_min) + hap->vmax_mv = hap->vtg_min; + else if (hap->vmax_mv > hap->vtg_max) + hap->vmax_mv = hap->vtg_max; + + hap->vtg_default = hap->vmax_mv; + hap->ilim_ma = QPNP_HAP_ILIM_MIN_MV; rc = of_property_read_u32(spmi->dev.of_node, "qcom,ilim-ma", &temp); From 1864abff8d3174de5004173f3e937a8f094f3031 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Wed, 20 Jul 2016 12:48:01 -0700 Subject: [PATCH 228/508] qpnp-haptic: Dejank the haptics * Add mutexes and call hap_set without the workqueue for direct mode Change-Id: I98f5b8ddea572def2706ad2cfa18f9dd460757ed --- drivers/platform/msm/qpnp-haptic.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/platform/msm/qpnp-haptic.c b/drivers/platform/msm/qpnp-haptic.c index c7afbb65b3ac0..5ad3b66e9cdc9 100644 --- a/drivers/platform/msm/qpnp-haptic.c +++ b/drivers/platform/msm/qpnp-haptic.c @@ -343,6 +343,7 @@ struct qpnp_hap { struct qpnp_pwm_info pwm_info; struct mutex lock; struct mutex wf_lock; + struct mutex set_lock; struct completion completion; enum qpnp_hap_mode play_mode; enum qpnp_hap_high_z lra_high_z; @@ -1679,6 +1680,8 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) unsigned long timeout_ns = POLL_TIME_AUTO_RES_ERR_NS; u32 back_emf_delay_us = hap->time_required_to_generate_back_emf_us; + mutex_lock(&hap->set_lock); + if (hap->play_mode == QPNP_HAP_PWM) { if (on) rc = pwm_enable(hap->pwm_info.pwm_dev); @@ -1712,8 +1715,10 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) qpnp_hap_auto_res_enable(hap, 0); rc = qpnp_hap_mod_enable(hap, on); - if (rc < 0) + if (rc < 0) { + mutex_unlock(&hap->set_lock); return rc; + } rc = qpnp_hap_play(hap, on); @@ -1723,8 +1728,10 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) usleep_range(back_emf_delay_us, back_emf_delay_us + 1); rc = qpnp_hap_auto_res_enable(hap, 1); - if (rc < 0) + if (rc < 0) { + mutex_unlock(&hap->set_lock); return rc; + } } if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq && @@ -1741,8 +1748,10 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) } } else { rc = qpnp_hap_play(hap, on); - if (rc < 0) + if (rc < 0) { + mutex_unlock(&hap->set_lock); return rc; + } if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq && @@ -1759,6 +1768,7 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) } } + mutex_unlock(&hap->set_lock); return rc; } @@ -1767,6 +1777,7 @@ static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value) { struct qpnp_hap *hap = container_of(dev, struct qpnp_hap, timed_dev); + flush_work(&hap->work); mutex_lock(&hap->lock); @@ -1792,7 +1803,10 @@ static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value) HRTIMER_MODE_REL); } mutex_unlock(&hap->lock); - schedule_work(&hap->work); + if (hap->play_mode == QPNP_HAP_DIRECT) + qpnp_hap_set(hap, hap->state); + else + schedule_work(&hap->work); } /* play pwm bytes */ @@ -2675,6 +2689,8 @@ static int qpnp_haptic_probe(struct spmi_device *spmi) mutex_init(&hap->lock); mutex_init(&hap->wf_lock); + mutex_init(&hap->set_lock); + INIT_WORK(&hap->work, qpnp_hap_worker); INIT_DELAYED_WORK(&hap->sc_work, qpnp_handle_sc_irq); init_completion(&hap->completion); From 18fc2e5985301aac37aca38660a92f4e7c46fe54 Mon Sep 17 00:00:00 2001 From: Sultanxda Date: Tue, 2 Aug 2016 23:59:42 -0700 Subject: [PATCH 229/508] msm: qpnp-haptic: Process haptics asynchronously Blocking the timed_output sysfs node due to mutex contention causes severe device wake-up latency, as a process crucial to system resume writes to the timed_output vibrator node every time the device is resumed via the fingerprint reader (fingerprint reader triggers a haptic response on success). By processing haptics asynchronously via a worker, the timed_output sysfs won't get stalled for long periods of time (>30ms), and thus the device will consistently wake from sleep faster. Signed-off-by: Sultanxda msm: qpnp-haptic: Prevent redundant calls to disable vibrator A redundant call to disable the vibrator right before something wants to enable it results in lack of vibration. Avoid re-disabling haptics to fix this. Signed-off-by: Sultanxda msm: qpnp-haptic: Start shutoff timer after haptics actually start qpnp_hap_set() sometimes lags when enabling haptics, causing the shutoff timer to kill the haptics prematurely. Start the shutoff timer after haptics are enabled so that the requested duration is actually carried out. Change-Id: I91bad94d18415476b5b05c1e1a4a60ae180947df Signed-off-by: Sultanxda --- drivers/platform/msm/qpnp-haptic.c | 47 +++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/drivers/platform/msm/qpnp-haptic.c b/drivers/platform/msm/qpnp-haptic.c index 5ad3b66e9cdc9..5ddd841a609eb 100644 --- a/drivers/platform/msm/qpnp-haptic.c +++ b/drivers/platform/msm/qpnp-haptic.c @@ -344,6 +344,8 @@ struct qpnp_hap { struct mutex lock; struct mutex wf_lock; struct mutex set_lock; + spinlock_t td_lock; + struct work_struct td_work; struct completion completion; enum qpnp_hap_mode play_mode; enum qpnp_hap_high_z lra_high_z; @@ -397,6 +399,7 @@ struct qpnp_hap { bool correct_lra_drive_freq; bool misc_trim_error_rc19p2_clk_reg_present; bool perform_lra_auto_resonance_search; + int td_value; }; static struct qpnp_hap *ghap; @@ -1772,11 +1775,20 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) return rc; } -/* enable interface from timed output class */ -static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value) +static void qpnp_timed_enable_worker(struct work_struct *work) { - struct qpnp_hap *hap = container_of(dev, struct qpnp_hap, - timed_dev); + struct qpnp_hap *hap = container_of(work, struct qpnp_hap, + td_work); + int value; + + spin_lock(&hap->td_lock); + value = hap->td_value; + spin_unlock(&hap->td_lock); + + /* Vibrator already disabled */ + if (!value && !hap->state) + return; + flush_work(&hap->work); mutex_lock(&hap->lock); @@ -1798,15 +1810,30 @@ static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value) value = (value > hap->timeout_ms ? hap->timeout_ms : value); hap->state = 1; - hrtimer_start(&hap->hap_timer, - ktime_set(value / 1000, (value % 1000) * 1000000), - HRTIMER_MODE_REL); } mutex_unlock(&hap->lock); if (hap->play_mode == QPNP_HAP_DIRECT) qpnp_hap_set(hap, hap->state); else schedule_work(&hap->work); + + if (value) + hrtimer_start(&hap->hap_timer, + ktime_set(value / 1000, (value % 1000) * 1000000), + HRTIMER_MODE_REL); +} + +/* enable interface from timed output class */ +static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value) +{ + struct qpnp_hap *hap = container_of(dev, struct qpnp_hap, + timed_dev); + + spin_lock(&hap->td_lock); + hap->td_value = value; + spin_unlock(&hap->td_lock); + + schedule_work(&hap->td_work); } /* play pwm bytes */ @@ -1925,6 +1952,10 @@ static enum hrtimer_restart qpnp_hap_timer(struct hrtimer *timer) struct qpnp_hap *hap = container_of(timer, struct qpnp_hap, hap_timer); + /* Vibrator already disabled */ + if (!hap->state) + return HRTIMER_NORESTART; + hap->state = 0; schedule_work(&hap->work); @@ -2690,10 +2721,12 @@ static int qpnp_haptic_probe(struct spmi_device *spmi) mutex_init(&hap->lock); mutex_init(&hap->wf_lock); mutex_init(&hap->set_lock); + spin_lock_init(&hap->td_lock); INIT_WORK(&hap->work, qpnp_hap_worker); INIT_DELAYED_WORK(&hap->sc_work, qpnp_handle_sc_irq); init_completion(&hap->completion); + INIT_WORK(&hap->td_work, qpnp_timed_enable_worker); hrtimer_init(&hap->hap_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hap->hap_timer.function = qpnp_hap_timer; From 2cb2921264d0c45d70ebb7bfbc2e08a9e702f47c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Rivotti=20Casimiro?= Date: Mon, 15 May 2017 17:27:25 +0000 Subject: [PATCH 230/508] ASoC: wcd-mbhc: correct lineout detection Change-Id: I9b352b69872e9fb185404457f349c6abef923a4f --- sound/soc/codecs/wcd-mbhc-v2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index 4274d62bdeca4..a8936a4dac81e 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -1325,7 +1325,8 @@ static void wcd_correct_swch_plug(struct work_struct *work) if ((plug_type == MBHC_PLUG_TYPE_HEADSET || plug_type == MBHC_PLUG_TYPE_HEADPHONE) && - (!wcd_swch_level_remove(mbhc))) { + (!wcd_swch_level_remove(mbhc)) && + (!mbhc->btn_press_intr)) { WCD_MBHC_RSC_LOCK(mbhc); wcd_mbhc_find_plug_and_report(mbhc, plug_type); WCD_MBHC_RSC_UNLOCK(mbhc); From 19a1d19c657ce002189a267b67981e1f402c1b44 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Fri, 26 Jan 2018 13:18:26 +0530 Subject: [PATCH 231/508] drivers: soc: qcom: remove spcom makefile and kconfig entries * driver removed with https://github.com/TheScarastic/priv_kernel_xiaomi_msm8953/commit/4b11968110532cc5fc78201bbe3c3d45880cdddf --- drivers/soc/qcom/Kconfig | 13 ------------- drivers/soc/qcom/Makefile | 1 - 2 files changed, 14 deletions(-) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index c6a119a120fe4..7dd3de81fac8d 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -500,19 +500,6 @@ config MSM_GLINK_BGCOM_XPRT allows for G-Link communication with remote subsystems that are external to the System-on-Chip. -config MSM_SPCOM - depends on MSM_GLINK - bool "Secure Processor Communication over GLINK" - help - spcom driver allows loading Secure Processor Applications and - sending messages to Secure Processor Applications. - spcom provides interface to both user space app and kernel driver. - It is using glink as the transport layer, which provides multiple - logical channels over signle physical channel. - The physical layer is based on shared memory and interrupts. - spcom provides clients/server API, although currently only one client - or server is allowed per logical channel. - config MSM_SMEM_LOGGING depends on MSM_SMEM bool "MSM Shared Memory Logger" diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 9be6bdbe10cb0..484cef674226e 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -45,7 +45,6 @@ obj-$(CONFIG_MSM_GLINK_LOOPBACK_SERVER) += glink_loopback_server.o obj-$(CONFIG_MSM_GLINK_SMD_XPRT) += glink_smd_xprt.o obj-$(CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT) += glink_smem_native_xprt.o obj-$(CONFIG_MSM_GLINK_BGCOM_XPRT) += glink_bgcom_xprt.o -obj-$(CONFIG_MSM_SPCOM) += spcom.o obj-$(CONFIG_MSM_SMEM_LOGGING) += smem_log.o obj-$(CONFIG_MSM_SMP2P) += smp2p.o smp2p_debug.o smp2p_sleepstate.o obj-$(CONFIG_MSM_SMP2P_TEST) += smp2p_loopback.o smp2p_test.o smp2p_spinlock_test.o From d55d3c158e8941bd18bd3643eedfb0bbdac082e3 Mon Sep 17 00:00:00 2001 From: fluxi Date: Sat, 27 Aug 2016 12:13:33 +0200 Subject: [PATCH 232/508] soc: Fix Kconfig warnings drivers/soc/qcom/Kconfig:368:warning: choice value used outside its choice group drivers/soc/qcom/Kconfig:373:warning: choice value used outside its choice group Change-Id: I710d6e534ac0a5a94f2a3cf38c987ddf74841446 --- drivers/soc/qcom/Kconfig | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 7dd3de81fac8d..55ad4a0e43452 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -362,10 +362,6 @@ menuconfig MSM_SCM_XPU if MSM_SCM_XPU -choice - prompt "XPU Violation Behavior" - default MSM_XPU_ERR_FATAL - config MSM_XPU_ERR_FATAL bool "Configure XPU violations as fatal errors" help @@ -376,8 +372,6 @@ config MSM_XPU_ERR_NONFATAL help Select if XPU violations have to be configured as non-fatal errors. -endchoice - endif config MSM_SCM_ERRATA From 50ea192493c4931177fb35f161fa6f3885b4e1be Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Thu, 20 Oct 2016 13:53:58 -0700 Subject: [PATCH 233/508] firmware_class: make firmware caching configurable Because firmware caching generates uevent messages that are sent over a netlink socket, it can prevent suspend on many platforms. It's also not always useful, so make it a configurable option. bug 32180327 Change-Id: I1250512b27edb56caa78d536e5ccf1fb669476ad --- drivers/base/Kconfig | 5 +++++ drivers/base/firmware_class.c | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index df04227d00cfa..b78013a17cf04 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -165,6 +165,11 @@ config FW_LOADER_USER_HELPER_FALLBACK If you are unsure about this, say N here. +config FW_CACHE + bool "Enable firmware caching during suspend" + depends on PM_SLEEP + default n + config WANT_DEV_COREDUMP bool help diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 2f23c4bf07c82..49878415a0700 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -1118,7 +1118,7 @@ static int fw_load_from_user_helper(struct firmware *firmware, return _request_firmware_load(fw_priv, desc->opt_flags, timeout); } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_FW_CACHE /* kill pending requests without uevent to avoid blocking suspend */ static void kill_requests_without_uevent(void) { @@ -1596,7 +1596,7 @@ request_firmware_nowait_into_buf( } EXPORT_SYMBOL_GPL(request_firmware_nowait_into_buf); -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_FW_CACHE static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain); /** @@ -1936,7 +1936,7 @@ static void __init fw_cache_init(void) INIT_LIST_HEAD(&fw_cache.head); fw_cache.state = FW_LOADER_NO_CACHE; -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_FW_CACHE spin_lock_init(&fw_cache.name_lock); INIT_LIST_HEAD(&fw_cache.fw_names); @@ -1963,7 +1963,7 @@ static int __init firmware_class_init(void) static void __exit firmware_class_exit(void) { -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_FW_CACHE unregister_syscore_ops(&fw_syscore_ops); unregister_pm_notifier(&fw_cache.pm_notify); #endif From 4611dbfd66051051ea4e2a775eb9b88d2cf33e40 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Wed, 21 Mar 2018 20:35:38 +0530 Subject: [PATCH 234/508] Revert "ANDROID: Update init/do_mounts_dm.c to the latest ChromiumOS version." This reverts commit 28452be84089473475c0dd91128e1c09905761c4. --- include/linux/device-mapper.h | 7 - init/do_mounts_dm.c | 558 ++++++++++++++++------------------ 2 files changed, 255 insertions(+), 310 deletions(-) diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 082ec600c51e3..2767094aae3d2 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -410,13 +410,6 @@ union map_info *dm_get_rq_mapinfo(struct request *rq); struct queue_limits *dm_get_queue_limits(struct mapped_device *md); -void dm_lock_md_type(struct mapped_device *md); -void dm_unlock_md_type(struct mapped_device *md); -void dm_set_md_type(struct mapped_device *md, unsigned type); -unsigned dm_get_md_type(struct mapped_device *md); -int dm_setup_md_queue(struct mapped_device *md); -unsigned dm_table_get_type(struct dm_table *t); - /* * Geometry functions. */ diff --git a/init/do_mounts_dm.c b/init/do_mounts_dm.c index 53dc2c8316252..ecda58df9a19e 100644 --- a/init/do_mounts_dm.c +++ b/init/do_mounts_dm.c @@ -5,18 +5,13 @@ * * This file is released under the GPL. */ -#include -#include #include #include #include -#include #include "do_mounts.h" #include "../drivers/md/dm.h" -#define DM_MAX_DEVICES 256 -#define DM_MAX_TARGETS 256 #define DM_MAX_NAME 32 #define DM_MAX_UUID 129 #define DM_NO_UUID "none" @@ -24,47 +19,14 @@ #define DM_MSG_PREFIX "init" /* Separators used for parsing the dm= argument. */ -#define DM_FIELD_SEP " " -#define DM_LINE_SEP "," -#define DM_ANY_SEP DM_FIELD_SEP DM_LINE_SEP +#define DM_FIELD_SEP ' ' +#define DM_LINE_SEP ',' /* * When the device-mapper and any targets are compiled into the kernel - * (not a module), one or more device-mappers may be created and used - * as the root device at boot time with the parameters given with the - * boot line dm=... - * - * Multiple device-mappers can be stacked specifing the number of - * devices. A device can have multiple targets if the the number of - * targets is specified. - * - * TODO(taysom:defect 32847) - * In the future, the field will be mandatory. - * - * ::= [] + - * ::= "," + - * ::= [] - * ::= "," - * ::= "ro" | "rw" - * ::= xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | "none" - * ::= "verity" | "bootcache" | ... - * - * Example: - * 2 vboot none ro 1, - * 0 1768000 bootcache - * device=aa55b119-2a47-8c45-946a-5ac57765011f+1 - * signature=76e9be054b15884a9fa85973e9cb274c93afadb6 - * cache_start=1768000 max_blocks=100000 size_limit=23 max_trace=20000, - * vroot none ro 1, - * 0 1740800 verity payload=254:0 hashtree=254:0 hashstart=1740800 alg=sha1 - * root_hexdigest=76e9be054b15884a9fa85973e9cb274c93afadb6 - * salt=5b3549d54d6c7a3837b9b81ed72e49463a64c03680c47835bef94d768e5646fe - * - * Notes: - * 1. uuid is a label for the device and we set it to "none". - * 2. The field will be optional initially and assumed to be 1. - * Once all the scripts that set these fields have been set, it will - * be made mandatory. + * (not a module), one target may be created and used as the root device at + * boot time with the parameters given with the boot line dm=... + * The code for that is here. */ struct dm_setup_target { @@ -76,391 +38,381 @@ struct dm_setup_target { struct dm_setup_target *next; }; -struct dm_device { +static struct { int minor; int ro; char name[DM_MAX_NAME]; char uuid[DM_MAX_UUID]; - unsigned long num_targets; + char *targets; struct dm_setup_target *target; int target_count; - struct dm_device *next; -}; - -struct dm_option { - char *start; - char *next; - size_t len; - char delim; -}; - -static struct { - unsigned long num_devices; - char *str; } dm_setup_args __initdata; static __initdata int dm_early_setup; -static int __init get_dm_option(struct dm_option *opt, const char *accept) +static size_t __init get_dm_option(char *str, char **next, char sep) { - char *str = opt->next; - char *endp; + size_t len = 0; + char *endp = NULL; if (!str) return 0; - str = skip_spaces(str); - opt->start = str; - endp = strpbrk(str, accept); + endp = strchr(str, sep); if (!endp) { /* act like strchrnul */ - opt->len = strlen(str); - endp = str + opt->len; + len = strlen(str); + endp = str + len; } else { - opt->len = endp - str; + len = endp - str; } - opt->delim = *endp; + + if (endp == str) + return 0; + + if (!next) + return len; + if (*endp == 0) { /* Don't advance past the nul. */ - opt->next = endp; + *next = endp; } else { - opt->next = endp + 1; + *next = endp + 1; } - return opt->len != 0; + return len; } -static int __init dm_setup_cleanup(struct dm_device *devices) +static int __init dm_setup_args_init(void) { - struct dm_device *dev = devices; - - while (dev) { - struct dm_device *old_dev = dev; - struct dm_setup_target *target = dev->target; - while (target) { - struct dm_setup_target *old_target = target; - kfree(target->type); - kfree(target->params); - target = target->next; - kfree(old_target); - dev->target_count--; - } - BUG_ON(dev->target_count); - dev = dev->next; - kfree(old_dev); + dm_setup_args.minor = 0; + dm_setup_args.ro = 0; + dm_setup_args.target = NULL; + dm_setup_args.target_count = 0; + return 0; +} + +static int __init dm_setup_cleanup(void) +{ + struct dm_setup_target *target = dm_setup_args.target; + struct dm_setup_target *old_target = NULL; + while (target) { + kfree(target->type); + kfree(target->params); + old_target = target; + target = target->next; + kfree(old_target); + dm_setup_args.target_count--; } + BUG_ON(dm_setup_args.target_count); return 0; } -static char * __init dm_parse_device(struct dm_device *dev, char *str) +static char * __init dm_setup_parse_device_args(char *str) { - struct dm_option opt; - size_t len; + char *next = NULL; + size_t len = 0; /* Grab the logical name of the device to be exported to udev */ - opt.next = str; - if (!get_dm_option(&opt, DM_FIELD_SEP)) { + len = get_dm_option(str, &next, DM_FIELD_SEP); + if (!len) { DMERR("failed to parse device name"); goto parse_fail; } - len = min(opt.len + 1, sizeof(dev->name)); - strlcpy(dev->name, opt.start, len); /* includes nul */ + len = min(len + 1, sizeof(dm_setup_args.name)); + strlcpy(dm_setup_args.name, str, len); /* includes nul */ + str = skip_spaces(next); /* Grab the UUID value or "none" */ - if (!get_dm_option(&opt, DM_FIELD_SEP)) { + len = get_dm_option(str, &next, DM_FIELD_SEP); + if (!len) { DMERR("failed to parse device uuid"); goto parse_fail; } - len = min(opt.len + 1, sizeof(dev->uuid)); - strlcpy(dev->uuid, opt.start, len); + len = min(len + 1, sizeof(dm_setup_args.uuid)); + strlcpy(dm_setup_args.uuid, str, len); + str = skip_spaces(next); /* Determine if the table/device will be read only or read-write */ - get_dm_option(&opt, DM_ANY_SEP); - if (!strncmp("ro", opt.start, opt.len)) { - dev->ro = 1; - } else if (!strncmp("rw", opt.start, opt.len)) { - dev->ro = 0; + if (!strncmp("ro,", str, 3)) { + dm_setup_args.ro = 1; + } else if (!strncmp("rw,", str, 3)) { + dm_setup_args.ro = 0; } else { DMERR("failed to parse table mode"); goto parse_fail; } + str = skip_spaces(str + 3); - /* Optional number field */ - /* XXX: The field will be mandatory in the next round */ - if (opt.delim == DM_FIELD_SEP[0]) { - if (!get_dm_option(&opt, DM_LINE_SEP)) - return NULL; - dev->num_targets = simple_strtoul(opt.start, NULL, 10); - } else { - dev->num_targets = 1; - } - if (dev->num_targets > DM_MAX_TARGETS) { - DMERR("too many targets %lu > %d", - dev->num_targets, DM_MAX_TARGETS); - } - return opt.next; + return str; parse_fail: return NULL; } -static char * __init dm_parse_targets(struct dm_device *dev, char *str) +static void __init dm_substitute_devices(char *str, size_t str_len) { - struct dm_option opt; - struct dm_setup_target **target = &dev->target; - unsigned long num_targets = dev->num_targets; - unsigned long i; + char *candidate = str; + char *candidate_end = str; + char old_char; + size_t len = 0; + dev_t dev; + + if (str_len < 3) + return; + + while (str && *str) { + candidate = strchr(str, '/'); + if (!candidate) + break; + + /* Avoid embedded slashes */ + if (candidate != str && *(candidate - 1) != DM_FIELD_SEP) { + str = strchr(candidate, DM_FIELD_SEP); + continue; + } + + len = get_dm_option(candidate, &candidate_end, DM_FIELD_SEP); + str = skip_spaces(candidate_end); + if (len < 3 || len > 37) /* name_to_dev_t max; maj:mix min */ + continue; + + /* Temporarily terminate with a nul */ + if (*candidate_end) + candidate_end--; + old_char = *candidate_end; + *candidate_end = '\0'; + + DMDEBUG("converting candidate device '%s' to dev_t", candidate); + /* Use the boot-time specific device naming */ + dev = name_to_dev_t(candidate); + *candidate_end = old_char; + + DMDEBUG(" -> %u", dev); + /* No suitable replacement found */ + if (!dev) + continue; + + /* Rewrite the /dev/path as a major:minor */ + len = snprintf(candidate, len, "%u:%u", MAJOR(dev), MINOR(dev)); + if (!len) { + DMERR("error substituting device major/minor."); + break; + } + candidate += len; + /* Pad out with spaces (fixing our nul) */ + while (candidate < candidate_end) + *(candidate++) = DM_FIELD_SEP; + } +} + +static int __init dm_setup_parse_targets(char *str) +{ + char *next = NULL; + size_t len = 0; + struct dm_setup_target **target = NULL; /* Targets are defined as per the table format but with a * comma as a newline separator. */ - opt.next = str; - for (i = 0; i < num_targets; i++) { + target = &dm_setup_args.target; + while (str && *str) { *target = kzalloc(sizeof(struct dm_setup_target), GFP_KERNEL); if (!*target) { - DMERR("failed to allocate memory for target %s<%ld>", - dev->name, i); + DMERR("failed to allocate memory for target %d", + dm_setup_args.target_count); goto parse_fail; } - dev->target_count++; + dm_setup_args.target_count++; - if (!get_dm_option(&opt, DM_FIELD_SEP)) { - DMERR("failed to parse starting sector" - " for target %s<%ld>", dev->name, i); + (*target)->begin = simple_strtoull(str, &next, 10); + if (!next || *next != DM_FIELD_SEP) { + DMERR("failed to parse starting sector for target %d", + dm_setup_args.target_count - 1); goto parse_fail; } - (*target)->begin = simple_strtoull(opt.start, NULL, 10); + str = skip_spaces(next + 1); - if (!get_dm_option(&opt, DM_FIELD_SEP)) { - DMERR("failed to parse length for target %s<%ld>", - dev->name, i); + (*target)->length = simple_strtoull(str, &next, 10); + if (!next || *next != DM_FIELD_SEP) { + DMERR("failed to parse length for target %d", + dm_setup_args.target_count - 1); goto parse_fail; } - (*target)->length = simple_strtoull(opt.start, NULL, 10); - - if (get_dm_option(&opt, DM_FIELD_SEP)) - (*target)->type = kstrndup(opt.start, opt.len, - GFP_KERNEL); - if (!((*target)->type)) { - DMERR("failed to parse type for target %s<%ld>", - dev->name, i); + str = skip_spaces(next + 1); + + len = get_dm_option(str, &next, DM_FIELD_SEP); + if (!len || + !((*target)->type = kstrndup(str, len, GFP_KERNEL))) { + DMERR("failed to parse type for target %d", + dm_setup_args.target_count - 1); goto parse_fail; } - if (get_dm_option(&opt, DM_LINE_SEP)) - (*target)->params = kstrndup(opt.start, opt.len, - GFP_KERNEL); - if (!((*target)->params)) { - DMERR("failed to parse params for target %s<%ld>", - dev->name, i); + str = skip_spaces(next); + + len = get_dm_option(str, &next, DM_LINE_SEP); + if (!len || + !((*target)->params = kstrndup(str, len, GFP_KERNEL))) { + DMERR("failed to parse params for target %d", + dm_setup_args.target_count - 1); goto parse_fail; } + str = skip_spaces(next); + + /* Before moving on, walk through the copied target and + * attempt to replace all /dev/xxx with the major:minor number. + * It may not be possible to resolve them traditionally at + * boot-time. */ + dm_substitute_devices((*target)->params, len); + target = &((*target)->next); } - DMDEBUG("parsed %d targets", dev->target_count); + DMDEBUG("parsed %d targets", dm_setup_args.target_count); - return opt.next; + return 0; parse_fail: - return NULL; -} - -static struct dm_device * __init dm_parse_args(void) -{ - struct dm_device *devices = NULL; - struct dm_device **tail = &devices; - struct dm_device *dev; - char *str = dm_setup_args.str; - unsigned long num_devices = dm_setup_args.num_devices; - unsigned long i; - - if (!str) - return NULL; - for (i = 0; i < num_devices; i++) { - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - DMERR("failed to allocated memory for dev"); - goto error; - } - *tail = dev; - tail = &dev->next; - /* - * devices are given minor numbers 0 - n-1 - * in the order they are found in the arg - * string. - */ - dev->minor = i; - str = dm_parse_device(dev, str); - if (!str) /* NULL indicates error in parsing, bail */ - goto error; - - str = dm_parse_targets(dev, str); - if (!str) - goto error; - } - return devices; -error: - dm_setup_cleanup(devices); - return NULL; + return 1; } /* * Parse the command-line parameters given our kernel, but do not * actually try to invoke the DM device now; that is handled by - * dm_setup_drives after the low-level disk drivers have initialised. - * dm format is described at the top of the file. - * - * Because dm minor numbers are assigned in assending order starting with 0, - * You can assume the first device is /dev/dm-0, the next device is /dev/dm-1, - * and so forth. + * dm_setup_drive after the low-level disk drivers have initialised. + * dm format is as follows: + * dm="name uuid fmode,[table line 1],[table line 2],..." + * May be used with root=/dev/dm-0 as it always uses the first dm minor. */ + static int __init dm_setup(char *str) { - struct dm_option opt; - unsigned long num_devices; + dm_setup_args_init(); + str = dm_setup_parse_device_args(str); if (!str) { DMDEBUG("str is NULL"); goto parse_fail; } - opt.next = str; - if (!get_dm_option(&opt, DM_FIELD_SEP)) - goto parse_fail; - if (isdigit(opt.start[0])) { /* XXX: Optional number field */ - num_devices = simple_strtoul(opt.start, NULL, 10); - str = opt.next; - } else { - num_devices = 1; - /* Don't advance str */ - } - if (num_devices > DM_MAX_DEVICES) { - DMDEBUG("too many devices %lu > %d", - num_devices, DM_MAX_DEVICES); - } - dm_setup_args.str = str; - dm_setup_args.num_devices = num_devices; - DMINFO("will configure %lu devices", num_devices); + + /* Target parsing is delayed until we have dynamic memory */ + dm_setup_args.targets = str; + + printk(KERN_INFO "dm: will configure '%s' on dm-%d\n", + dm_setup_args.name, dm_setup_args.minor); + dm_early_setup = 1; return 1; parse_fail: - DMWARN("Invalid arguments supplied to dm=."); + printk(KERN_WARNING "dm: Invalid arguments supplied to dm=.\n"); return 0; } -static void __init dm_setup_drives(void) + +static void __init dm_setup_drive(void) { struct mapped_device *md = NULL; struct dm_table *table = NULL; struct dm_setup_target *target; - struct dm_device *dev; - char *uuid; + char *uuid = dm_setup_args.uuid; fmode_t fmode = FMODE_READ; - struct dm_device *devices; - devices = dm_parse_args(); + /* Finish parsing the targets. */ + if (dm_setup_parse_targets(dm_setup_args.targets)) + goto parse_fail; - for (dev = devices; dev; dev = dev->next) { - if (dm_create(dev->minor, &md)) { - DMDEBUG("failed to create the device"); - goto dm_create_fail; - } - DMDEBUG("created device '%s'", dm_device_name(md)); - - /* - * In addition to flagging the table below, the disk must be - * set explicitly ro/rw. - */ - set_disk_ro(dm_disk(md), dev->ro); - - if (!dev->ro) - fmode |= FMODE_WRITE; - if (dm_table_create(&table, fmode, dev->target_count, md)) { - DMDEBUG("failed to create the table"); - goto dm_table_create_fail; - } + if (dm_create(dm_setup_args.minor, &md)) { + DMDEBUG("failed to create the device"); + goto dm_create_fail; + } + DMDEBUG("created device '%s'", dm_device_name(md)); - dm_lock_md_type(md); - - for (target = dev->target; target; target = target->next) { - DMINFO("adding target '%llu %llu %s %s'", - (unsigned long long) target->begin, - (unsigned long long) target->length, - target->type, target->params); - if (dm_table_add_target(table, target->type, - target->begin, - target->length, - target->params)) { - DMDEBUG("failed to add the target" - " to the table"); - goto add_target_fail; - } - } - if (dm_table_complete(table)) { - DMDEBUG("failed to complete the table"); - goto table_complete_fail; - } + /* In addition to flagging the table below, the disk must be + * set explicitly ro/rw. */ + set_disk_ro(dm_disk(md), dm_setup_args.ro); + + if (!dm_setup_args.ro) + fmode |= FMODE_WRITE; + if (dm_table_create(&table, fmode, dm_setup_args.target_count, md)) { + DMDEBUG("failed to create the table"); + goto dm_table_create_fail; + } - /* Suspend the device so that we can bind it to the table. */ - if (dm_suspend(md, 0)) { - DMDEBUG("failed to suspend the device pre-bind"); - goto suspend_fail; + dm_lock_md_type(md); + target = dm_setup_args.target; + while (target) { + DMINFO("adding target '%llu %llu %s %s'", + (unsigned long long) target->begin, + (unsigned long long) target->length, target->type, + target->params); + if (dm_table_add_target(table, target->type, target->begin, + target->length, target->params)) { + DMDEBUG("failed to add the target to the table"); + goto add_target_fail; } + target = target->next; + } - /* Initial table load: acquire type of table. */ - dm_set_md_type(md, dm_table_get_type(table)); + if (dm_table_complete(table)) { + DMDEBUG("failed to complete the table"); + goto table_complete_fail; + } - /* Setup md->queue to reflect md's type. */ + if (dm_get_md_type(md) == DM_TYPE_NONE) { + dm_set_md_type(md, dm_table_get_type(table)); if (dm_setup_md_queue(md)) { DMWARN("unable to set up device queue for new table."); goto setup_md_queue_fail; } + } else if (dm_get_md_type(md) != dm_table_get_type(table)) { + DMWARN("can't change device type after initial table load."); + goto setup_md_queue_fail; + } + + /* Suspend the device so that we can bind it to the table. */ + if (dm_suspend(md, 0)) { + DMDEBUG("failed to suspend the device pre-bind"); + goto suspend_fail; + } - /* - * Bind the table to the device. This is the only way - * to associate md->map with the table and set the disk - * capacity directly. - */ - if (dm_swap_table(md, table)) { /* should return NULL. */ - DMDEBUG("failed to bind the device to the table"); - goto table_bind_fail; - } - - /* Finally, resume and the device should be ready. */ - if (dm_resume(md)) { - DMDEBUG("failed to resume the device"); - goto resume_fail; - } - - /* Export the dm device via the ioctl interface */ - if (!strcmp(DM_NO_UUID, dev->uuid)){ - uuid = NULL; - } else { - uuid = dev->uuid; - } - if (dm_ioctl_export(md, dev->name, uuid)) { - DMDEBUG("failed to export device with given" - " name and uuid"); - goto export_fail; - } + /* Bind the table to the device. This is the only way to associate + * md->map with the table and set the disk capacity directly. */ + if (dm_swap_table(md, table)) { /* should return NULL. */ + DMDEBUG("failed to bind the device to the table"); + goto table_bind_fail; + } - dm_unlock_md_type(md); + /* Finally, resume and the device should be ready. */ + if (dm_resume(md)) { + DMDEBUG("failed to resume the device"); + goto resume_fail; + } - DMINFO("dm-%d is ready", dev->minor); + /* Export the dm device via the ioctl interface */ + if (!strcmp(DM_NO_UUID, dm_setup_args.uuid)) + uuid = NULL; + if (dm_ioctl_export(md, dm_setup_args.name, uuid)) { + DMDEBUG("failed to export device with given name and uuid"); + goto export_fail; } - dm_setup_cleanup(devices); + printk(KERN_INFO "dm: dm-%d is ready\n", dm_setup_args.minor); + + dm_unlock_md_type(md); + dm_setup_cleanup(); return; export_fail: resume_fail: table_bind_fail: -setup_md_queue_fail: suspend_fail: +setup_md_queue_fail: table_complete_fail: add_target_fail: dm_unlock_md_type(md); dm_table_create_fail: dm_put(md); dm_create_fail: - DMWARN("starting dm-%d (%s) failed", - dev->minor, dev->name); - dm_setup_cleanup(devices); + dm_setup_cleanup(); +parse_fail: + printk(KERN_WARNING "dm: starting dm-%d (%s) failed\n", + dm_setup_args.minor, dm_setup_args.name); } __setup("dm=", dm_setup); @@ -469,6 +421,6 @@ void __init dm_run_setup(void) { if (!dm_early_setup) return; - DMINFO("attempting early device configuration."); - dm_setup_drives(); + printk(KERN_INFO "dm: attempting early device configuration.\n"); + dm_setup_drive(); } From d34ca80b762596bfdfa44a18710a4bd890281eab Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Thu, 26 May 2016 14:10:38 -0700 Subject: [PATCH 235/508] android-verity: add verity key to system keyring This change adds public key to the system keyring. This key is used by the android-verity module to check verity-metadata for the root partition. BUG:28845874 Signed-off-by: Badhri Jagan Sridharan Change-Id: Ib05a9750fac03df231ca888f3a104e760cfd077a --- verity_der.x509 | Bin 0 -> 1025 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 verity_der.x509 diff --git a/verity_der.x509 b/verity_der.x509 new file mode 100644 index 0000000000000000000000000000000000000000..9040f249fb697dac3679d2f06f1e5c4f754d40bd GIT binary patch literal 1025 zcmXqLV*YE;#PoClGZP~d6DPxT{u!2>t2#Xmc-c6$+C196^D;8BvN9MnPBG**;ACSC zWnmL$3Jo?CHV_1HIC!|66LT`t@{95^6Ai@-L_mV zVh|Bg2c=6~6kuArq^rH(TF+ zo|*pS;uGV zaPE@lyI(q|vi!gM_r^SXB|ekiG~l+wS;5VcCwxPT)uNspv+}SCe#>#wyjuIr`hcSg z8I#X1S@brfKAT}*@HsPH_q&VEUYc{hK-uk(Ij6C-QoE4ymXWZ$$`U|p4L ze4ogbUCP1!y%&Cqv@AT4nYD6yh?Rp#YTNR>8FK!Us~z^O+qIl+SG4sSHJ^O zAk4yQz|6?_A34l{i5eK@j10xwO|=gT&p5j0_(F;7pbwHq6EAwXbg1$ix0t6o>72~D z&=&WHX^W5Ec8ok1f81lEN&LUops6kY8Wf&L{eHh@^1~C|Tk^Y_&*w?p*%%pFy$Io#J*n;qC(kdw{BoB{yv3w5C#FwqGdc47xa&om_X|GVTli$_{JAl68>hdN6iN7* zc<+#J$c@T;KO>pSy}YHTI6o$JGK9`8dT1Tex#RHbqkqiA|M2#mw)*yyC2?lU`m3kc zG_W^ayM6rOsyg+c2SLT_o~)=BTYOqqhc}d~g6-YyuZ;04*7Gc~x5%@%F Date: Sun, 25 Feb 2018 13:09:08 +0530 Subject: [PATCH 236/508] tissot: Import miui verity key --- dm-android-verity.x509 | Bin 0 -> 1059 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 dm-android-verity.x509 diff --git a/dm-android-verity.x509 b/dm-android-verity.x509 new file mode 100644 index 0000000000000000000000000000000000000000..74ced635946f3a6863b53ea85c0c281aff99295a GIT binary patch literal 1059 zcmXqLVv#p!VrE~!%*4pV#L3XW^5&=Mj4TraUN%mxHjlRNyo`*jtPBQ?OAWaVIN6v( zS=fY`LW2#34Fo|P4jwM&#GK5u{GzhA$tcbA>oefZqR3oQ>+jZc66 zwe#Zte~V_!Z}Ip0Uvm0@@cD9)bKY}8xJ{38{s`lcGP_Z3=oG5Pvi586>U;C35oA2LU_2EHEax3e($+3rduB~2Fcjd))Ev0&9!&FRKPOCF?8z0B@pI8~(R>2#^xB|(;}`QNx_ zpSaY2e}?P6gOTqi);3Jvw(3CE_IZDKcSvyVn5*-g&-{{n%g+lldfD9OS^kemXHjim zcXCTu^v5_!{IuTWQaQ;$9we>IB4HrbfL#F(NP#d5s{u13uDbGZjLGq9Ru$NIRZH`|HF>yGiSNlA!TyW2 z8Wq_~&MsK@DeObrwfj3}DG60{azy;Oyf1Be8S^{=$>obg@1Kq-cUhgbZieKSt^^Ia zW)to2fiEKUY`krxE^J#?_e3ge!bGj2xZqpz3D^9DtTq=eE(r)&clY{4zQ=D#~)nL{&BI$_qoTK{)b##TC?(I z2yWP=e`xuTwaQ7@&Y-g^%8jvo85lO1gVmv2f<$`#tv$l*41Is2l7y-DWm M2dBNOeYf^E0R7&G{{R30 literal 0 HcmV?d00001 From e8bf56274e8e06c1d1c16197b8e2f0a9ed1846d2 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Fri, 22 Sep 2017 12:30:38 -0700 Subject: [PATCH 237/508] HACK: arm64: add CNTPCT_EL0 trap handler The upstream kernel deliberately blocks EL0 access to CNTPCT. However Qualcomm's time_daemon attempts to read from CNTPCT_EL0, and Qualcomm has forked the ARM architectured timer driver to allow this to succeed. As a workaround, add a trap handler for CNTPCT similar to the existing one for CNTVCT. Bug: 68266545 Change-Id: Id49b60ebdeca84fab655079c8c22afd3171371b0 --- arch/arm64/kernel/traps.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index b42991af2e289..2bcea95c34232 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -419,6 +419,19 @@ static void cntfrq_read_handler(unsigned int esr, struct pt_regs *regs) regs->pc += 4; } +static void cntpct_read_handler(unsigned int esr, struct pt_regs *regs) +{ + int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; + + isb(); + if (rt != 31) + regs->regs[rt] = arch_counter_get_cntpct(); + regs->pc += 4; +} + +#define ESR_ELx_SYS64_ISS_SYS_CNTPCT (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 1, 14, 0) | \ + ESR_ELx_SYS64_ISS_DIR_READ) + asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs) { if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTVCT) { @@ -427,6 +440,9 @@ asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs) } else if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTFRQ) { cntfrq_read_handler(esr, regs); return; + } else if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTPCT) { + cntpct_read_handler(esr, regs); + return; } do_undefinstr(regs); From 92e6c9e310128230c90fc3c25b21a8d823a7caf2 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Sun, 24 Sep 2017 14:33:03 +0300 Subject: [PATCH 238/508] clk: msm: Build the right clock drivers for the right ARCH * Previously shared clock drivers were built under ARCH_MSM8916 flag, which didn't allow disabling ARCH_MSM8916 without breaking everything. Select the right clock drivers for every ARCH so we can disable unused ARCHs in defconfigs. Change-Id: I75b6a103615b52d847e78c48eafa8a81355ac819 --- drivers/clk/msm/Makefile | 69 ++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/drivers/clk/msm/Makefile b/drivers/clk/msm/Makefile index 10ea16e3e2a68..def38f0735c1f 100644 --- a/drivers/clk/msm/Makefile +++ b/drivers/clk/msm/Makefile @@ -12,44 +12,67 @@ obj-$(CONFIG_MSM_CLK_CONTROLLER_V2) += msm-clock-controller.o obj-$(CONFIG_DEBUG_FS) += clock-debug.o -# MSM 8996 -obj-$(CONFIG_ARCH_MSM8996) += clock-gcc-8996.o -obj-$(CONFIG_ARCH_MSM8996) += clock-mmss-8996.o -obj-$(CONFIG_ARCH_MSM8996) += clock-cpu-8996.o -obj-$(CONFIG_ARCH_MSMCOBALT) += clock-osm.o +# MDM9607 +obj-$(CONFIG_ARCH_MDM9607) += clock-a7.o +obj-$(CONFIG_ARCH_MDM9607) += clock-gcc-mdm9607.o -# MSM COBALT -obj-$(CONFIG_ARCH_MSMCOBALT) += clock-gcc-cobalt.o -obj-$(CONFIG_ARCH_MSMCOBALT) += clock-gpu-cobalt.o -obj-$(CONFIG_ARCH_MSMCOBALT) += clock-mmss-cobalt.o +# MDM9640 +obj-$(CONFIG_ARCH_MDM9640) += clock-a7.o # MDM9650 obj-$(CONFIG_ARCH_MDM9650) += clock-gcc-9650.o obj-$(CONFIG_ARCH_SDX20) += clock-gcc-9650.o +obj-$(CONFIG_ARCH_MDM9650) += clock-a7.o -# MDM9607 -obj-$(CONFIG_ARCH_MDM9607) +=clock-gcc-mdm9607.o +# MDMCALIFORNIUM +obj-$(CONFIG_ARCH_MDMCALIFORNIUM) += clock-a7.o +obj-$(CONFIG_ARCH_MDMCALIFORNIUM) += clock-gcc-californium.o # MSM8909 +obj-$(CONFIG_ARCH_MSM8909) += clock-a7.o obj-$(CONFIG_ARCH_MSM8909) += clock-rpm-8909.o obj-$(CONFIG_ARCH_MSM8909) += clock-gcc-8909.o -# ACPU clock -obj-$(CONFIG_ARCH_MDM9640) += clock-a7.o -obj-$(CONFIG_ARCH_MDM9650) += clock-a7.o -obj-$(CONFIG_ARCH_SDX20) += clock-a7.o -obj-$(CONFIG_ARCH_MDM9607) += clock-a7.o -obj-$(CONFIG_ARCH_MSM8916) += clock-a7.o -obj-$(CONFIG_ARCH_MSM8909) += clock-a7.o -obj-$(CONFIG_ARCH_MSM8953) += clock-a7.o +# MSM8917 +obj-$(CONFIG_ARCH_MSM8917) += clock-cpu-8939.o +obj-$(CONFIG_ARCH_MSM8917) += clock-gcc-8952.o + +# MSM8920 +obj-$(CONFIG_ARCH_MSM8920) += clock-cpu-8939.o +obj-$(CONFIG_ARCH_MSM8920) += clock-gcc-8952.o + +# MSM8937 +obj-$(CONFIG_ARCH_MSM8937) += clock-cpu-8939.o +obj-$(CONFIG_ARCH_MSM8937) += clock-gcc-8952.o + +# MSM8940 +obj-$(CONFIG_ARCH_MSM8940) += clock-cpu-8939.o +obj-$(CONFIG_ARCH_MSM8940) += clock-gcc-8952.o + +# MSM8952 obj-$(CONFIG_ARCH_MSM8916) += clock-cpu-8939.o obj-$(CONFIG_ARCH_MSM8916) += clock-gcc-8952.o -obj-$(CONFIG_ARCH_MSM8916) += clock-gcc-8953.o -obj-$(CONFIG_ARCH_MSM8916) += clock-rcgwr.o -obj-$(CONFIG_ARCH_MSM8916) += clock-cpu-8953.o + +# MSM8953 +obj-$(CONFIG_ARCH_MSM8953) += clock-cpu-8953.o obj-$(CONFIG_ARCH_MSM8953) += clock-gcc-8953.o obj-$(CONFIG_ARCH_MSM8953) += clock-rcgwr.o -obj-$(CONFIG_ARCH_MSM8953) += clock-cpu-8953.o + +# MSM8996 +obj-$(CONFIG_ARCH_MSM8996) += clock-gcc-8996.o +obj-$(CONFIG_ARCH_MSM8996) += clock-mmss-8996.o +obj-$(CONFIG_ARCH_MSM8996) += clock-cpu-8996.o + +# MSMCOBALT +obj-$(CONFIG_ARCH_MSMCOBALT) += clock-gcc-cobalt.o +obj-$(CONFIG_ARCH_MSMCOBALT) += clock-gpu-cobalt.o +obj-$(CONFIG_ARCH_MSMCOBALT) += clock-mmss-cobalt.o +obj-$(CONFIG_ARCH_MSMCOBALT) += clock-osm.o + +# SDM450 +obj-$(CONFIG_ARCH_SDM450) += clock-cpu-8953.o +obj-$(CONFIG_ARCH_SDM450) += clock-gcc-8953.o +obj-$(CONFIG_ARCH_SDM450) += clock-rcgwr.o obj-y += gdsc.o obj-y += mdss/ From 52231d98de72e7b115ccb4cd87ca0697e8040149 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Sun, 24 Sep 2017 15:01:41 +0300 Subject: [PATCH 239/508] iommu: Correct ARCH dependencies of MSM_IOMMU_V1 * Allow selecting MSM_IOMMU_V1 for the right platforms. This allows disabling ARCH_MSM8916 without breaking IOMMU on msm8917, msm8920, msm8937, msm8940, msm8953 and sdm450 Change-Id: I0fc592ec271dcf6c5c3dbff32e463d2f9c24b030 --- drivers/iommu/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 9a45ea62f30f9..6584b735a80fb 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -105,7 +105,7 @@ config MSM_IOMMU # MSM IOMMUv1 support config MSM_IOMMU_V1 bool "MSM IOMMUv1 Support" - depends on ARCH_MSM8974 || ARCH_MSM8226 || ARCH_APQ8084 || ARCH_MSM8916 || ARCH_MSM8953 || ARCH_MSM8994 || ARCH_MSM8992 || ARCH_MSM8909 + depends on ARCH_MSM8974 || ARCH_MSM8226 || ARCH_APQ8084 || ARCH_MSM8916 || ARCH_MSM8994 || ARCH_MSM8992 || ARCH_MSM8909 || ARCH_MSM8917 || ARCH_MSM8920 || ARCH_MSM8937 || ARCH_MSM8940 || ARCH_MSM8953 || ARCH_SDM450 select IOMMU_API select MSM_IOMMU help From 5f80c60c333d5564b56fb180e928d89216ae2492 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Sun, 24 Sep 2017 15:45:23 +0300 Subject: [PATCH 240/508] crypto: msm: Select CRYPTO_DEV_QCE50 for the right ARCHs * This allows disabling ARCH_MSM8916/ARCH_MSM8953 without breaking crypto on msm8917, msm8920, msm8937, msm8940 and sdm450 Change-Id: Iac57142cc7a2dcdbed72ed4fb09610217914e06c --- drivers/crypto/Kconfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 45b2317b409f5..ffd4c013471e7 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -337,7 +337,7 @@ config CRYPTO_DEV_QCRYPTO config CRYPTO_DEV_QCOM_MSM_QCE tristate "Qualcomm Crypto Engine (QCE) module" - select CRYPTO_DEV_QCE50 if ARCH_APQ8084 || ARCH_MSM8916 || ARCH_MSM8994 || ARCH_MSM8996 || ARCH_MSM8992 || ARCH_MSM8953 || ARCH_MSM8909 || ARCH_MDM9640 || ARCH_MDM9607 + select CRYPTO_DEV_QCE50 if ARCH_APQ8084 || ARCH_MSM8916 || ARCH_MSM8994 || ARCH_MSM8996 || ARCH_MSM8992 || ARCH_MSM8917 || ARCH_MSM8920 || ARCH_MSM8937 || ARCH_MSM8940 || ARCH_MSM8953 || ARCH_SDM450 || ARCH_MSM8909 || ARCH_MDM9640 default n help This driver supports Qualcomm Crypto Engine in MSM7x30, MSM8660 @@ -347,8 +347,9 @@ config CRYPTO_DEV_QCOM_MSM_QCE To compile this driver as a module, choose M here: the For MSM7x30 MSM8660 and MSM8x55 the module is called qce For MSM8960, APQ8064 and MSM9615 the module is called qce40 - For MSM8974, MSM8916, MSM8994, MSM8996, MSM8992, MSM8953, - MDM9640, MDM9607 and APQ8084 the module is called qce50. + For MSM8974, MSM8916, MSM8994, MSM8996, MSM8992, MSM8917, + MSM8920, MSM8937, MSM8940, MSM8953, SDM450, MSM8909 + MDM9640 and APQ8084 the module is called qce50. config CRYPTO_DEV_QCEDEV tristate "QCEDEV Interface to CE module" From 17bd0fbd330deb1ee7cd4fda86169dce95211965 Mon Sep 17 00:00:00 2001 From: Alec Leamas Date: Thu, 12 Nov 2015 16:03:00 -0200 Subject: [PATCH 241/508] bz#75751: Move internal header file lirc.h to uapi/ The file include/media/lirc.h describes a public interface and should thus be a public header. See kernel bug https://bugzilla.kernel.org/show_bug.cgi?id=75751 which has a manpage describing the interface + an acknowledgment that this info belongs to uapi. Change-Id: I968947c59914bc4353902de552c7079453d6e1de Signed-off-by: Mauro Carvalho Chehab --- include/media/lirc.h | 169 +------------------------------------- include/uapi/linux/lirc.h | 168 +++++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+), 168 deletions(-) create mode 100644 include/uapi/linux/lirc.h diff --git a/include/media/lirc.h b/include/media/lirc.h index 4b3ab2966b5a4..554988c860c1e 100644 --- a/include/media/lirc.h +++ b/include/media/lirc.h @@ -1,168 +1 @@ -/* - * lirc.h - linux infrared remote control header file - * last modified 2010/07/13 by Jarod Wilson - */ - -#ifndef _LINUX_LIRC_H -#define _LINUX_LIRC_H - -#include -#include - -#define PULSE_BIT 0x01000000 -#define PULSE_MASK 0x00FFFFFF - -#define LIRC_MODE2_SPACE 0x00000000 -#define LIRC_MODE2_PULSE 0x01000000 -#define LIRC_MODE2_FREQUENCY 0x02000000 -#define LIRC_MODE2_TIMEOUT 0x03000000 - -#define LIRC_VALUE_MASK 0x00FFFFFF -#define LIRC_MODE2_MASK 0xFF000000 - -#define LIRC_SPACE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_SPACE) -#define LIRC_PULSE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_PULSE) -#define LIRC_FREQUENCY(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_FREQUENCY) -#define LIRC_TIMEOUT(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_TIMEOUT) - -#define LIRC_VALUE(val) ((val)&LIRC_VALUE_MASK) -#define LIRC_MODE2(val) ((val)&LIRC_MODE2_MASK) - -#define LIRC_IS_SPACE(val) (LIRC_MODE2(val) == LIRC_MODE2_SPACE) -#define LIRC_IS_PULSE(val) (LIRC_MODE2(val) == LIRC_MODE2_PULSE) -#define LIRC_IS_FREQUENCY(val) (LIRC_MODE2(val) == LIRC_MODE2_FREQUENCY) -#define LIRC_IS_TIMEOUT(val) (LIRC_MODE2(val) == LIRC_MODE2_TIMEOUT) - -/* used heavily by lirc userspace */ -#define lirc_t int - -/*** lirc compatible hardware features ***/ - -#define LIRC_MODE2SEND(x) (x) -#define LIRC_SEND2MODE(x) (x) -#define LIRC_MODE2REC(x) ((x) << 16) -#define LIRC_REC2MODE(x) ((x) >> 16) - -#define LIRC_MODE_RAW 0x00000001 -#define LIRC_MODE_PULSE 0x00000002 -#define LIRC_MODE_MODE2 0x00000004 -#define LIRC_MODE_LIRCCODE 0x00000010 - - -#define LIRC_CAN_SEND_RAW LIRC_MODE2SEND(LIRC_MODE_RAW) -#define LIRC_CAN_SEND_PULSE LIRC_MODE2SEND(LIRC_MODE_PULSE) -#define LIRC_CAN_SEND_MODE2 LIRC_MODE2SEND(LIRC_MODE_MODE2) -#define LIRC_CAN_SEND_LIRCCODE LIRC_MODE2SEND(LIRC_MODE_LIRCCODE) - -#define LIRC_CAN_SEND_MASK 0x0000003f - -#define LIRC_CAN_SET_SEND_CARRIER 0x00000100 -#define LIRC_CAN_SET_SEND_DUTY_CYCLE 0x00000200 -#define LIRC_CAN_SET_TRANSMITTER_MASK 0x00000400 - -#define LIRC_CAN_REC_RAW LIRC_MODE2REC(LIRC_MODE_RAW) -#define LIRC_CAN_REC_PULSE LIRC_MODE2REC(LIRC_MODE_PULSE) -#define LIRC_CAN_REC_MODE2 LIRC_MODE2REC(LIRC_MODE_MODE2) -#define LIRC_CAN_REC_LIRCCODE LIRC_MODE2REC(LIRC_MODE_LIRCCODE) - -#define LIRC_CAN_REC_MASK LIRC_MODE2REC(LIRC_CAN_SEND_MASK) - -#define LIRC_CAN_SET_REC_CARRIER (LIRC_CAN_SET_SEND_CARRIER << 16) -#define LIRC_CAN_SET_REC_DUTY_CYCLE (LIRC_CAN_SET_SEND_DUTY_CYCLE << 16) - -#define LIRC_CAN_SET_REC_DUTY_CYCLE_RANGE 0x40000000 -#define LIRC_CAN_SET_REC_CARRIER_RANGE 0x80000000 -#define LIRC_CAN_GET_REC_RESOLUTION 0x20000000 -#define LIRC_CAN_SET_REC_TIMEOUT 0x10000000 -#define LIRC_CAN_SET_REC_FILTER 0x08000000 - -#define LIRC_CAN_MEASURE_CARRIER 0x02000000 -#define LIRC_CAN_USE_WIDEBAND_RECEIVER 0x04000000 - -#define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK) -#define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK) - -#define LIRC_CAN_NOTIFY_DECODE 0x01000000 - -/*** IOCTL commands for lirc driver ***/ - -#define LIRC_GET_FEATURES _IOR('i', 0x00000000, __u32) - -#define LIRC_GET_SEND_MODE _IOR('i', 0x00000001, __u32) -#define LIRC_GET_REC_MODE _IOR('i', 0x00000002, __u32) -#define LIRC_GET_SEND_CARRIER _IOR('i', 0x00000003, __u32) -#define LIRC_GET_REC_CARRIER _IOR('i', 0x00000004, __u32) -#define LIRC_GET_SEND_DUTY_CYCLE _IOR('i', 0x00000005, __u32) -#define LIRC_GET_REC_DUTY_CYCLE _IOR('i', 0x00000006, __u32) -#define LIRC_GET_REC_RESOLUTION _IOR('i', 0x00000007, __u32) - -#define LIRC_GET_MIN_TIMEOUT _IOR('i', 0x00000008, __u32) -#define LIRC_GET_MAX_TIMEOUT _IOR('i', 0x00000009, __u32) - -#define LIRC_GET_MIN_FILTER_PULSE _IOR('i', 0x0000000a, __u32) -#define LIRC_GET_MAX_FILTER_PULSE _IOR('i', 0x0000000b, __u32) -#define LIRC_GET_MIN_FILTER_SPACE _IOR('i', 0x0000000c, __u32) -#define LIRC_GET_MAX_FILTER_SPACE _IOR('i', 0x0000000d, __u32) - -/* code length in bits, currently only for LIRC_MODE_LIRCCODE */ -#define LIRC_GET_LENGTH _IOR('i', 0x0000000f, __u32) - -#define LIRC_SET_SEND_MODE _IOW('i', 0x00000011, __u32) -#define LIRC_SET_REC_MODE _IOW('i', 0x00000012, __u32) -/* Note: these can reset the according pulse_width */ -#define LIRC_SET_SEND_CARRIER _IOW('i', 0x00000013, __u32) -#define LIRC_SET_REC_CARRIER _IOW('i', 0x00000014, __u32) -#define LIRC_SET_SEND_DUTY_CYCLE _IOW('i', 0x00000015, __u32) -#define LIRC_SET_REC_DUTY_CYCLE _IOW('i', 0x00000016, __u32) -#define LIRC_SET_TRANSMITTER_MASK _IOW('i', 0x00000017, __u32) - -/* - * when a timeout != 0 is set the driver will send a - * LIRC_MODE2_TIMEOUT data packet, otherwise LIRC_MODE2_TIMEOUT is - * never sent, timeout is disabled by default - */ -#define LIRC_SET_REC_TIMEOUT _IOW('i', 0x00000018, __u32) - -/* 1 enables, 0 disables timeout reports in MODE2 */ -#define LIRC_SET_REC_TIMEOUT_REPORTS _IOW('i', 0x00000019, __u32) - -/* - * pulses shorter than this are filtered out by hardware (software - * emulation in lirc_dev?) - */ -#define LIRC_SET_REC_FILTER_PULSE _IOW('i', 0x0000001a, __u32) -/* - * spaces shorter than this are filtered out by hardware (software - * emulation in lirc_dev?) - */ -#define LIRC_SET_REC_FILTER_SPACE _IOW('i', 0x0000001b, __u32) -/* - * if filter cannot be set independently for pulse/space, this should - * be used - */ -#define LIRC_SET_REC_FILTER _IOW('i', 0x0000001c, __u32) - -/* - * if enabled from the next key press on the driver will send - * LIRC_MODE2_FREQUENCY packets - */ -#define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32) - -/* - * to set a range use - * LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE with the - * lower bound first and later - * LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER with the upper bound - */ - -#define LIRC_SET_REC_DUTY_CYCLE_RANGE _IOW('i', 0x0000001e, __u32) -#define LIRC_SET_REC_CARRIER_RANGE _IOW('i', 0x0000001f, __u32) - -#define LIRC_NOTIFY_DECODE _IO('i', 0x00000020) - -#define LIRC_SETUP_START _IO('i', 0x00000021) -#define LIRC_SETUP_END _IO('i', 0x00000022) - -#define LIRC_SET_WIDEBAND_RECEIVER _IOW('i', 0x00000023, __u32) - -#endif +#include diff --git a/include/uapi/linux/lirc.h b/include/uapi/linux/lirc.h new file mode 100644 index 0000000000000..4b3ab2966b5a4 --- /dev/null +++ b/include/uapi/linux/lirc.h @@ -0,0 +1,168 @@ +/* + * lirc.h - linux infrared remote control header file + * last modified 2010/07/13 by Jarod Wilson + */ + +#ifndef _LINUX_LIRC_H +#define _LINUX_LIRC_H + +#include +#include + +#define PULSE_BIT 0x01000000 +#define PULSE_MASK 0x00FFFFFF + +#define LIRC_MODE2_SPACE 0x00000000 +#define LIRC_MODE2_PULSE 0x01000000 +#define LIRC_MODE2_FREQUENCY 0x02000000 +#define LIRC_MODE2_TIMEOUT 0x03000000 + +#define LIRC_VALUE_MASK 0x00FFFFFF +#define LIRC_MODE2_MASK 0xFF000000 + +#define LIRC_SPACE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_SPACE) +#define LIRC_PULSE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_PULSE) +#define LIRC_FREQUENCY(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_FREQUENCY) +#define LIRC_TIMEOUT(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_TIMEOUT) + +#define LIRC_VALUE(val) ((val)&LIRC_VALUE_MASK) +#define LIRC_MODE2(val) ((val)&LIRC_MODE2_MASK) + +#define LIRC_IS_SPACE(val) (LIRC_MODE2(val) == LIRC_MODE2_SPACE) +#define LIRC_IS_PULSE(val) (LIRC_MODE2(val) == LIRC_MODE2_PULSE) +#define LIRC_IS_FREQUENCY(val) (LIRC_MODE2(val) == LIRC_MODE2_FREQUENCY) +#define LIRC_IS_TIMEOUT(val) (LIRC_MODE2(val) == LIRC_MODE2_TIMEOUT) + +/* used heavily by lirc userspace */ +#define lirc_t int + +/*** lirc compatible hardware features ***/ + +#define LIRC_MODE2SEND(x) (x) +#define LIRC_SEND2MODE(x) (x) +#define LIRC_MODE2REC(x) ((x) << 16) +#define LIRC_REC2MODE(x) ((x) >> 16) + +#define LIRC_MODE_RAW 0x00000001 +#define LIRC_MODE_PULSE 0x00000002 +#define LIRC_MODE_MODE2 0x00000004 +#define LIRC_MODE_LIRCCODE 0x00000010 + + +#define LIRC_CAN_SEND_RAW LIRC_MODE2SEND(LIRC_MODE_RAW) +#define LIRC_CAN_SEND_PULSE LIRC_MODE2SEND(LIRC_MODE_PULSE) +#define LIRC_CAN_SEND_MODE2 LIRC_MODE2SEND(LIRC_MODE_MODE2) +#define LIRC_CAN_SEND_LIRCCODE LIRC_MODE2SEND(LIRC_MODE_LIRCCODE) + +#define LIRC_CAN_SEND_MASK 0x0000003f + +#define LIRC_CAN_SET_SEND_CARRIER 0x00000100 +#define LIRC_CAN_SET_SEND_DUTY_CYCLE 0x00000200 +#define LIRC_CAN_SET_TRANSMITTER_MASK 0x00000400 + +#define LIRC_CAN_REC_RAW LIRC_MODE2REC(LIRC_MODE_RAW) +#define LIRC_CAN_REC_PULSE LIRC_MODE2REC(LIRC_MODE_PULSE) +#define LIRC_CAN_REC_MODE2 LIRC_MODE2REC(LIRC_MODE_MODE2) +#define LIRC_CAN_REC_LIRCCODE LIRC_MODE2REC(LIRC_MODE_LIRCCODE) + +#define LIRC_CAN_REC_MASK LIRC_MODE2REC(LIRC_CAN_SEND_MASK) + +#define LIRC_CAN_SET_REC_CARRIER (LIRC_CAN_SET_SEND_CARRIER << 16) +#define LIRC_CAN_SET_REC_DUTY_CYCLE (LIRC_CAN_SET_SEND_DUTY_CYCLE << 16) + +#define LIRC_CAN_SET_REC_DUTY_CYCLE_RANGE 0x40000000 +#define LIRC_CAN_SET_REC_CARRIER_RANGE 0x80000000 +#define LIRC_CAN_GET_REC_RESOLUTION 0x20000000 +#define LIRC_CAN_SET_REC_TIMEOUT 0x10000000 +#define LIRC_CAN_SET_REC_FILTER 0x08000000 + +#define LIRC_CAN_MEASURE_CARRIER 0x02000000 +#define LIRC_CAN_USE_WIDEBAND_RECEIVER 0x04000000 + +#define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK) +#define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK) + +#define LIRC_CAN_NOTIFY_DECODE 0x01000000 + +/*** IOCTL commands for lirc driver ***/ + +#define LIRC_GET_FEATURES _IOR('i', 0x00000000, __u32) + +#define LIRC_GET_SEND_MODE _IOR('i', 0x00000001, __u32) +#define LIRC_GET_REC_MODE _IOR('i', 0x00000002, __u32) +#define LIRC_GET_SEND_CARRIER _IOR('i', 0x00000003, __u32) +#define LIRC_GET_REC_CARRIER _IOR('i', 0x00000004, __u32) +#define LIRC_GET_SEND_DUTY_CYCLE _IOR('i', 0x00000005, __u32) +#define LIRC_GET_REC_DUTY_CYCLE _IOR('i', 0x00000006, __u32) +#define LIRC_GET_REC_RESOLUTION _IOR('i', 0x00000007, __u32) + +#define LIRC_GET_MIN_TIMEOUT _IOR('i', 0x00000008, __u32) +#define LIRC_GET_MAX_TIMEOUT _IOR('i', 0x00000009, __u32) + +#define LIRC_GET_MIN_FILTER_PULSE _IOR('i', 0x0000000a, __u32) +#define LIRC_GET_MAX_FILTER_PULSE _IOR('i', 0x0000000b, __u32) +#define LIRC_GET_MIN_FILTER_SPACE _IOR('i', 0x0000000c, __u32) +#define LIRC_GET_MAX_FILTER_SPACE _IOR('i', 0x0000000d, __u32) + +/* code length in bits, currently only for LIRC_MODE_LIRCCODE */ +#define LIRC_GET_LENGTH _IOR('i', 0x0000000f, __u32) + +#define LIRC_SET_SEND_MODE _IOW('i', 0x00000011, __u32) +#define LIRC_SET_REC_MODE _IOW('i', 0x00000012, __u32) +/* Note: these can reset the according pulse_width */ +#define LIRC_SET_SEND_CARRIER _IOW('i', 0x00000013, __u32) +#define LIRC_SET_REC_CARRIER _IOW('i', 0x00000014, __u32) +#define LIRC_SET_SEND_DUTY_CYCLE _IOW('i', 0x00000015, __u32) +#define LIRC_SET_REC_DUTY_CYCLE _IOW('i', 0x00000016, __u32) +#define LIRC_SET_TRANSMITTER_MASK _IOW('i', 0x00000017, __u32) + +/* + * when a timeout != 0 is set the driver will send a + * LIRC_MODE2_TIMEOUT data packet, otherwise LIRC_MODE2_TIMEOUT is + * never sent, timeout is disabled by default + */ +#define LIRC_SET_REC_TIMEOUT _IOW('i', 0x00000018, __u32) + +/* 1 enables, 0 disables timeout reports in MODE2 */ +#define LIRC_SET_REC_TIMEOUT_REPORTS _IOW('i', 0x00000019, __u32) + +/* + * pulses shorter than this are filtered out by hardware (software + * emulation in lirc_dev?) + */ +#define LIRC_SET_REC_FILTER_PULSE _IOW('i', 0x0000001a, __u32) +/* + * spaces shorter than this are filtered out by hardware (software + * emulation in lirc_dev?) + */ +#define LIRC_SET_REC_FILTER_SPACE _IOW('i', 0x0000001b, __u32) +/* + * if filter cannot be set independently for pulse/space, this should + * be used + */ +#define LIRC_SET_REC_FILTER _IOW('i', 0x0000001c, __u32) + +/* + * if enabled from the next key press on the driver will send + * LIRC_MODE2_FREQUENCY packets + */ +#define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32) + +/* + * to set a range use + * LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE with the + * lower bound first and later + * LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER with the upper bound + */ + +#define LIRC_SET_REC_DUTY_CYCLE_RANGE _IOW('i', 0x0000001e, __u32) +#define LIRC_SET_REC_CARRIER_RANGE _IOW('i', 0x0000001f, __u32) + +#define LIRC_NOTIFY_DECODE _IO('i', 0x00000020) + +#define LIRC_SETUP_START _IO('i', 0x00000021) +#define LIRC_SETUP_END _IO('i', 0x00000022) + +#define LIRC_SET_WIDEBAND_RECEIVER _IOW('i', 0x00000023, __u32) + +#endif From 776022bcd48921f710273d6444856e27dc807083 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 11 Jul 2016 09:45:32 -0300 Subject: [PATCH 242/508] lirc.h: remove several unused ioctls While reviewing the documentation gaps on LIRC, it was noticed that several ioctls aren't used by any LIRC drivers (nor at staging or mainstream). It doesn't make sense to document them, as they're not used anywhere. So, let's remove those from the lirc header. Change-Id: Iaa49ec4d89612a0c9fb08ef5bd4489d20a0d66ed Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/lirc.h | 39 ++------------------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/include/uapi/linux/lirc.h b/include/uapi/linux/lirc.h index 4b3ab2966b5a4..991ab4570b8ec 100644 --- a/include/uapi/linux/lirc.h +++ b/include/uapi/linux/lirc.h @@ -90,20 +90,11 @@ #define LIRC_GET_SEND_MODE _IOR('i', 0x00000001, __u32) #define LIRC_GET_REC_MODE _IOR('i', 0x00000002, __u32) -#define LIRC_GET_SEND_CARRIER _IOR('i', 0x00000003, __u32) -#define LIRC_GET_REC_CARRIER _IOR('i', 0x00000004, __u32) -#define LIRC_GET_SEND_DUTY_CYCLE _IOR('i', 0x00000005, __u32) -#define LIRC_GET_REC_DUTY_CYCLE _IOR('i', 0x00000006, __u32) #define LIRC_GET_REC_RESOLUTION _IOR('i', 0x00000007, __u32) #define LIRC_GET_MIN_TIMEOUT _IOR('i', 0x00000008, __u32) #define LIRC_GET_MAX_TIMEOUT _IOR('i', 0x00000009, __u32) -#define LIRC_GET_MIN_FILTER_PULSE _IOR('i', 0x0000000a, __u32) -#define LIRC_GET_MAX_FILTER_PULSE _IOR('i', 0x0000000b, __u32) -#define LIRC_GET_MIN_FILTER_SPACE _IOR('i', 0x0000000c, __u32) -#define LIRC_GET_MAX_FILTER_SPACE _IOR('i', 0x0000000d, __u32) - /* code length in bits, currently only for LIRC_MODE_LIRCCODE */ #define LIRC_GET_LENGTH _IOR('i', 0x0000000f, __u32) @@ -113,7 +104,6 @@ #define LIRC_SET_SEND_CARRIER _IOW('i', 0x00000013, __u32) #define LIRC_SET_REC_CARRIER _IOW('i', 0x00000014, __u32) #define LIRC_SET_SEND_DUTY_CYCLE _IOW('i', 0x00000015, __u32) -#define LIRC_SET_REC_DUTY_CYCLE _IOW('i', 0x00000016, __u32) #define LIRC_SET_TRANSMITTER_MASK _IOW('i', 0x00000017, __u32) /* @@ -126,22 +116,6 @@ /* 1 enables, 0 disables timeout reports in MODE2 */ #define LIRC_SET_REC_TIMEOUT_REPORTS _IOW('i', 0x00000019, __u32) -/* - * pulses shorter than this are filtered out by hardware (software - * emulation in lirc_dev?) - */ -#define LIRC_SET_REC_FILTER_PULSE _IOW('i', 0x0000001a, __u32) -/* - * spaces shorter than this are filtered out by hardware (software - * emulation in lirc_dev?) - */ -#define LIRC_SET_REC_FILTER_SPACE _IOW('i', 0x0000001b, __u32) -/* - * if filter cannot be set independently for pulse/space, this should - * be used - */ -#define LIRC_SET_REC_FILTER _IOW('i', 0x0000001c, __u32) - /* * if enabled from the next key press on the driver will send * LIRC_MODE2_FREQUENCY packets @@ -149,20 +123,11 @@ #define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32) /* - * to set a range use - * LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE with the - * lower bound first and later - * LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER with the upper bound + * to set a range use LIRC_SET_REC_CARRIER_RANGE with the + * lower bound first and later LIRC_SET_REC_CARRIER with the upper bound */ - -#define LIRC_SET_REC_DUTY_CYCLE_RANGE _IOW('i', 0x0000001e, __u32) #define LIRC_SET_REC_CARRIER_RANGE _IOW('i', 0x0000001f, __u32) -#define LIRC_NOTIFY_DECODE _IO('i', 0x00000020) - -#define LIRC_SETUP_START _IO('i', 0x00000021) -#define LIRC_SETUP_END _IO('i', 0x00000022) - #define LIRC_SET_WIDEBAND_RECEIVER _IOW('i', 0x00000023, __u32) #endif From 2a774153ff2c36f095432ec8151fe70c3bd5e970 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 14 Jul 2016 12:07:15 -0700 Subject: [PATCH 243/508] uapi: export lirc.h header This header contains the userspace API for lirc. This is a fixup for commit b7be755733dc ("[media] bz#75751: Move internal header file lirc.h to uapi/"). It moved the header to the right place, but it forgot to add it at Kbuild. So, despite being at uapi, it is not copied to the right place. Change-Id: I348f9ba4207504393ae8ab64406dd6e4522d0acb Fixes: b7be755733dc44c72 ("[media] bz#75751: Move internal header file lirc.h to uapi/") Link: http://lkml.kernel.org/r/320c765d32bfc82c582e336d52ffe1026c73c644.1468439021.git.mchehab@s-opensource.com Signed-off-by: Mauro Carvalho Chehab Cc: Alec Leamas Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/uapi/linux/Kbuild | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index c94ec777da534..958c0deeb5507 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild @@ -247,6 +247,7 @@ endif header-y += l2tp.h header-y += libc-compat.h +header-y += lirc.h header-y += limits.h header-y += llc.h header-y += loop.h From 721fa17ead6cf1ab6a2018dcb0a03a6c99e427b3 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Fri, 26 Jan 2018 14:39:21 +0530 Subject: [PATCH 244/508] arch: arm: dtsi: r63350-ebbg: Fix qcom,mdss-dsi-on-command --- .../arm/boot/dts/qcom/mido/dsi-panel-r63350-ebbg-fhd-video.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/qcom/mido/dsi-panel-r63350-ebbg-fhd-video.dtsi b/arch/arm/boot/dts/qcom/mido/dsi-panel-r63350-ebbg-fhd-video.dtsi index f2ac8177424be..6d8f696697ec5 100644 --- a/arch/arm/boot/dts/qcom/mido/dsi-panel-r63350-ebbg-fhd-video.dtsi +++ b/arch/arm/boot/dts/qcom/mido/dsi-panel-r63350-ebbg-fhd-video.dtsi @@ -39,6 +39,8 @@ 39 01 00 00 00 00 02 51 ff 39 01 00 00 00 00 02 53 2c 39 01 00 00 00 00 02 55 00 + 39 01 00 00 0a 00 02 29 00 + 39 01 00 00 78 00 02 11 00 ]; qcom,mdss-dsi-off-command = [05 01 00 00 14 00 02 28 00 05 01 00 00 78 00 02 10 00]; From d0f5b66ee618aa4e5005ae4c43a52b9def9a054b Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Sat, 11 Jul 2015 05:49:30 -0700 Subject: [PATCH 245/508] video: mdss: LiveDisplay driver * Bring in a lightweight version of the LiveDisplay driver which works for this chipset. * This version of the driver does not include the generic RGB offset postprocessing, since we're going to do this using the official QDCM APIs. Change-Id: Ifcaaf93d56933d019d1f469fd70b8466cd4ad3e7 --- drivers/video/msm/mdss/Makefile | 2 + drivers/video/msm/mdss/mdss_dsi.c | 4 + drivers/video/msm/mdss/mdss_dsi_panel.c | 10 +- drivers/video/msm/mdss/mdss_fb.c | 5 +- drivers/video/msm/mdss/mdss_livedisplay.c | 611 ++++++++++++++++++++++ drivers/video/msm/mdss/mdss_livedisplay.h | 117 +++++ drivers/video/msm/mdss/mdss_panel.h | 5 + 7 files changed, 752 insertions(+), 2 deletions(-) create mode 100644 drivers/video/msm/mdss/mdss_livedisplay.c create mode 100644 drivers/video/msm/mdss/mdss_livedisplay.h diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile index ed3ff87458e5a..02ac42bd223c7 100644 --- a/drivers/video/msm/mdss/Makefile +++ b/drivers/video/msm/mdss/Makefile @@ -69,3 +69,5 @@ obj-$(CONFIG_FB_MSM_QPIC_ILI_QVGA_PANEL) += qpic_panel_ili_qvga.o obj-$(CONFIG_FB_MSM_MDSS) += mdss_fb.o mdss_util.o obj-$(CONFIG_COMPAT) += mdss_compat_utils.o + +obj-$(CONFIG_FB_MSM_MDSS) += mdss_livedisplay.o diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c index 693793428095c..a992cda44e58f 100644 --- a/drivers/video/msm/mdss/mdss_dsi.c +++ b/drivers/video/msm/mdss/mdss_dsi.c @@ -33,6 +33,7 @@ #include "mdss_debug.h" #include "mdss_dsi_phy.h" #include "mdss_dba_utils.h" +#include "mdss_livedisplay.h" #define XO_CLK_RATE 19200000 #define CMDLINE_DSI_CTL_NUM_STRING_LEN 2 @@ -2806,6 +2807,9 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, &ctrl_pdata->dba_work, HZ); } break; + case MDSS_EVENT_UPDATE_LIVEDISPLAY: + rc = mdss_livedisplay_update(ctrl_pdata, (int)(unsigned long) arg); + break; default: pr_debug("%s: unhandled event=%d\n", __func__, event); break; diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c index 67be02e8c0501..a936a4d356c8e 100644 --- a/drivers/video/msm/mdss/mdss_dsi_panel.c +++ b/drivers/video/msm/mdss/mdss_dsi_panel.c @@ -27,6 +27,8 @@ #ifdef TARGET_HW_MDSS_HDMI #include "mdss_dba_utils.h" #endif +#include "mdss_livedisplay.h" + #define DT_CMD_HDR 6 #define MIN_REFRESH_RATE 48 #define DEFAULT_MDP_TRANSFER_TIME 14000 @@ -912,6 +914,10 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata) /* Ensure low persistence mode is set as before */ mdss_dsi_panel_apply_display_setting(pdata, pinfo->persist_mode); + if (pdata->event_handler) + pdata->event_handler(pdata, MDSS_EVENT_UPDATE_LIVEDISPLAY, + (void *)(unsigned long) MODE_UPDATE_ALL); + end: pr_debug("%s:-\n", __func__); return ret; @@ -1068,7 +1074,7 @@ static void mdss_dsi_parse_trigger(struct device_node *np, char *trigger, } -static int mdss_dsi_parse_dcs_cmds(struct device_node *np, +int mdss_dsi_parse_dcs_cmds(struct device_node *np, struct dsi_panel_cmds *pcmds, char *cmd_key, char *link_key) { const char *data; @@ -2851,6 +2857,8 @@ static int mdss_panel_parse_dt(struct device_node *np, if (rc) goto error; + mdss_livedisplay_parse_dt(np, pinfo); + return 0; error: diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index d884fe5573bf0..fbcec438dbc47 100644 --- a/drivers/video/msm/mdss/mdss_fb.c +++ b/drivers/video/msm/mdss/mdss_fb.c @@ -60,6 +60,8 @@ #include "mdss_mdp.h" #include "mdp3_ctrl.h" +#include "mdss_livedisplay.h" + #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER #define MDSS_FB_NUM 3 #else @@ -964,7 +966,8 @@ static int mdss_fb_create_sysfs(struct msm_fb_data_type *mfd) rc = sysfs_create_group(&mfd->fbi->dev->kobj, &mdss_fb_attr_group); if (rc) pr_err("sysfs group creation failed, rc=%d\n", rc); - return rc; + + return mdss_livedisplay_create_sysfs(mfd); } static void mdss_fb_remove_sysfs(struct msm_fb_data_type *mfd) diff --git a/drivers/video/msm/mdss/mdss_livedisplay.c b/drivers/video/msm/mdss/mdss_livedisplay.c new file mode 100644 index 0000000000000..f2cd8f2438c86 --- /dev/null +++ b/drivers/video/msm/mdss/mdss_livedisplay.c @@ -0,0 +1,611 @@ +/* + * Copyright (c) 2015 The CyanogenMod Project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "mdss_dsi.h" +#include "mdss_fb.h" +#include "mdss_mdp.h" +#include "mdss_mdp_pp.h" +#include "mdss_livedisplay.h" + +/* + * LiveDisplay is the display management service in CyanogenMod. It uses + * various capabilities of the hardware and software in order to + * optimize the experience for ambient conditions and time of day. + * + * This module is initialized by mdss_fb for each panel, and creates + * several new controls in /sys/class/graphics/fbX based on the + * configuration in the devicetree. + * + * cabc: Content Adaptive Backlight Control. Must be configured + * in the panel devicetree. Up to three levels. + * sre: Sunlight Readability Enhancement. Must be configured in + * the panel devicetree. Up to three levels. + * aco: Automatic Contrast Optimization. Must be configured in + * the panel devicetree. Boolean. + * + * hbm: High Brightness Mode. Common for OLED panels. Boolean. + * + * preset: Arbitrary DSI commands, up to 10 may be configured. + * Useful for gamma calibration. + * + * color_enhance: Hardware color enhancement. Must be configured + * in the panel devicetree. Boolean. + */ + +extern void mdss_dsi_panel_cmds_send(struct mdss_dsi_ctrl_pdata *ctrl, + struct dsi_panel_cmds *pcmds, u32 flags); + +static int parse_dsi_cmds(struct mdss_livedisplay_ctx *mlc, + struct dsi_panel_cmds *pcmds, const uint8_t *cmd, int blen) +{ + int len; + char *buf, *bp; + struct dsi_ctrl_hdr *dchdr; + int i, cnt; + + buf = kzalloc(blen, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + memcpy(buf, cmd, blen); + + /* scan dcs commands */ + bp = buf; + len = blen; + cnt = 0; + while (len >= sizeof(*dchdr)) { + dchdr = (struct dsi_ctrl_hdr *)bp; + dchdr->dlen = ntohs(dchdr->dlen); + if (dchdr->dlen > len) { + pr_err("%s: dtsi cmd=%x error, len=%d\n", + __func__, dchdr->dtype, dchdr->dlen); + goto exit_free; + } + bp += sizeof(*dchdr); + len -= sizeof(*dchdr); + bp += dchdr->dlen; + len -= dchdr->dlen; + cnt++; + } + + if (len != 0) { + pr_err("%s: dcs_cmd=%x len=%d error!\n", + __func__, buf[0], blen); + goto exit_free; + } + + pcmds->cmds = kzalloc(cnt * sizeof(struct dsi_cmd_desc), + GFP_KERNEL); + if (!pcmds->cmds) + goto exit_free; + + pcmds->cmd_cnt = cnt; + pcmds->buf = buf; + pcmds->blen = blen; + + bp = buf; + len = blen; + for (i = 0; i < cnt; i++) { + dchdr = (struct dsi_ctrl_hdr *)bp; + len -= sizeof(*dchdr); + bp += sizeof(*dchdr); + pcmds->cmds[i].dchdr = *dchdr; + pcmds->cmds[i].payload = bp; + bp += dchdr->dlen; + len -= dchdr->dlen; + } + + pcmds->link_state = mlc->link_state; + + pr_debug("%s: dcs_cmd=%x len=%d, cmd_cnt=%d link_state=%d\n", __func__, + pcmds->buf[0], pcmds->blen, pcmds->cmd_cnt, pcmds->link_state); + + return 0; + +exit_free: + kfree(buf); + return -ENOMEM; +} + +/* + * Update all or a subset of parameters + */ +int mdss_livedisplay_update(struct mdss_dsi_ctrl_pdata *ctrl_pdata, + int types) +{ + int ret = 0; + struct mdss_panel_info *pinfo = NULL; + struct mdss_livedisplay_ctx *mlc = NULL; + unsigned int len = 0, dlen = 0; + struct dsi_panel_cmds dsi_cmds; + uint8_t cabc_value = 0; + uint8_t *cmd_buf; + + if (ctrl_pdata == NULL) + return -ENODEV; + + pinfo = &(ctrl_pdata->panel_data.panel_info); + if (pinfo == NULL) + return -ENODEV; + + mlc = pinfo->livedisplay; + if (mlc == NULL) + return -ENODEV; + + if (!mlc->caps || !mdss_panel_is_power_on_interactive(pinfo->panel_power_state)) + return 0; + + // First find the length of the command array + if ((mlc->caps & MODE_PRESET) && (types & MODE_PRESET)) + len += mlc->presets_len[mlc->preset]; + + if ((mlc->caps & MODE_COLOR_ENHANCE) && (types & MODE_COLOR_ENHANCE)) + len += mlc->ce_enabled ? mlc->ce_on_cmds_len : mlc->ce_off_cmds_len; + + if ((mlc->caps & MODE_HIGH_BRIGHTNESS) && (types & MODE_HIGH_BRIGHTNESS)) + len += mlc->hbm_enabled ? mlc->hbm_on_cmds_len : mlc->hbm_off_cmds_len; + + if (is_cabc_cmd(types) && is_cabc_cmd(mlc->caps)) { + + // The CABC command on most modern panels is also responsible for + // other features such as SRE and ACO. The register fields are bits + // and are OR'd together and sent in a single DSI command. + if (mlc->cabc_level == CABC_UI) + cabc_value |= mlc->cabc_ui_value; + else if (mlc->cabc_level == CABC_IMAGE) + cabc_value |= mlc->cabc_image_value; + else if (mlc->cabc_level == CABC_VIDEO) + cabc_value |= mlc->cabc_video_value; + + if (mlc->sre_level == SRE_WEAK) + cabc_value |= mlc->sre_weak_value; + else if (mlc->sre_level == SRE_MEDIUM) + cabc_value |= mlc->sre_medium_value; + else if (mlc->sre_level == SRE_STRONG) + cabc_value |= mlc->sre_strong_value; + + if (mlc->aco_enabled) + cabc_value |= mlc->aco_value; + + len += mlc->cabc_cmds_len; + + pr_info("%s cabc=%d sre=%d aco=%d cmd=%d\n", __func__, + mlc->cabc_level, mlc->sre_level, mlc->aco_enabled, + cabc_value); + } + + len += mlc->post_cmds_len; + + if (len == 0) + return 0; + + memset(&dsi_cmds, 0, sizeof(struct dsi_panel_cmds)); + cmd_buf = kzalloc(len + 1, GFP_KERNEL); + if (!cmd_buf) + return -ENOMEM; + + // Build the command as a single chain, preset first + if ((mlc->caps & MODE_PRESET) && (types & MODE_PRESET)) { + memcpy(cmd_buf, mlc->presets[mlc->preset], mlc->presets_len[mlc->preset]); + dlen += mlc->presets_len[mlc->preset]; + } + + // Color enhancement + if ((mlc->caps & MODE_COLOR_ENHANCE) && (types & MODE_COLOR_ENHANCE)) { + if (mlc->ce_enabled) { + memcpy(cmd_buf + dlen, mlc->ce_on_cmds, mlc->ce_on_cmds_len); + dlen += mlc->ce_on_cmds_len; + } else { + memcpy(cmd_buf + dlen, mlc->ce_off_cmds, mlc->ce_off_cmds_len); + dlen += mlc->ce_off_cmds_len; + } + } + + // High brightness mode + if ((mlc->caps & MODE_HIGH_BRIGHTNESS) && (types & MODE_HIGH_BRIGHTNESS)) { + if (mlc->hbm_enabled) { + memcpy(cmd_buf + dlen, mlc->hbm_on_cmds, mlc->hbm_on_cmds_len); + dlen += mlc->hbm_on_cmds_len; + } else { + memcpy(cmd_buf + dlen, mlc->hbm_off_cmds, mlc->hbm_off_cmds_len); + dlen += mlc->hbm_off_cmds_len; + } + } + + // CABC/SRE/ACO features + if (is_cabc_cmd(types) && mlc->cabc_cmds_len) { + memcpy(cmd_buf + dlen, mlc->cabc_cmds, mlc->cabc_cmds_len); + dlen += mlc->cabc_cmds_len; + // The CABC command parameter is the last value in the sequence + cmd_buf[dlen - 1] = cabc_value; + } + + // And the post_cmd, can be used to turn on the panel + if (mlc->post_cmds_len) { + memcpy(cmd_buf + dlen, mlc->post_cmds, mlc->post_cmds_len); + dlen += mlc->post_cmds_len; + } + + // Parse the command and send it + ret = parse_dsi_cmds(mlc, &dsi_cmds, (const uint8_t *)cmd_buf, len); + if (ret == 0) { + mdss_dsi_panel_cmds_send(ctrl_pdata, &dsi_cmds, CMD_REQ_COMMIT); + } else { + pr_err("%s: error parsing DSI command! ret=%d", __func__, ret); + } + + kfree(cmd_buf); + + return ret; +} + +int mdss_livedisplay_event(struct msm_fb_data_type *mfd, int types) +{ + int rc = 0; + struct mdss_panel_data *pdata; + + pdata = dev_get_platdata(&mfd->pdev->dev); + if (!pdata) + return -ENODEV; + + do { + if (pdata->event_handler) + rc = pdata->event_handler(pdata, MDSS_EVENT_UPDATE_LIVEDISPLAY, + (void *)(unsigned long) types); + + pdata = pdata->next; + } while (!rc && pdata); + + return rc; +} + +static ssize_t mdss_livedisplay_get_cabc(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par; + struct mdss_livedisplay_ctx *mlc = get_ctx(mfd); + + return sprintf(buf, "%d\n", mlc->cabc_level); +} + +static ssize_t mdss_livedisplay_set_cabc(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int level = 0; + struct fb_info *fbi = dev_get_drvdata(dev); + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par; + struct mdss_livedisplay_ctx *mlc = get_ctx(mfd); + + sscanf(buf, "%du", &level); + if (level >= CABC_OFF && level < CABC_MAX && + level != mlc->cabc_level) { + mlc->cabc_level = level; + mdss_livedisplay_event(mfd, MODE_CABC); + } + + return count; +} + +static ssize_t mdss_livedisplay_get_sre(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par; + struct mdss_livedisplay_ctx *mlc = get_ctx(mfd); + + return sprintf(buf, "%d\n", mlc->sre_level); +} + +static ssize_t mdss_livedisplay_set_sre(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int level = 0; + struct fb_info *fbi = dev_get_drvdata(dev); + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par; + struct mdss_livedisplay_ctx *mlc = get_ctx(mfd); + + sscanf(buf, "%du", &level); + if (level >= SRE_OFF && level < SRE_MAX && + level != mlc->sre_level) { + mlc->sre_level = level; + mdss_livedisplay_event(mfd, MODE_SRE); + } + + return count; +} + +static ssize_t mdss_livedisplay_get_hbm(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par; + struct mdss_livedisplay_ctx *mlc = get_ctx(mfd); + + return sprintf(buf, "%d\n", mlc->hbm_enabled); +} + +static ssize_t mdss_livedisplay_set_hbm(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int value = 0; + struct fb_info *fbi = dev_get_drvdata(dev); + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par; + struct mdss_livedisplay_ctx *mlc = get_ctx(mfd); + + sscanf(buf, "%du", &value); + if ((value == 0 || value == 1) + && value != mlc->hbm_enabled) { + mlc->hbm_enabled = value; + mdss_livedisplay_event(mfd, MODE_HIGH_BRIGHTNESS); + } + + return count; +} + +static ssize_t mdss_livedisplay_get_color_enhance(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par; + struct mdss_livedisplay_ctx *mlc = get_ctx(mfd); + + return sprintf(buf, "%d\n", mlc->ce_enabled); +} + +static ssize_t mdss_livedisplay_set_color_enhance(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int value = 0; + struct fb_info *fbi = dev_get_drvdata(dev); + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par; + struct mdss_livedisplay_ctx *mlc = get_ctx(mfd); + + sscanf(buf, "%du", &value); + if ((value == 0 || value == 1) + && value != mlc->ce_enabled) { + mlc->ce_enabled = value; + mdss_livedisplay_event(mfd, MODE_COLOR_ENHANCE); + } + + return count; +} + +static ssize_t mdss_livedisplay_get_aco(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par; + struct mdss_livedisplay_ctx *mlc = get_ctx(mfd); + + return sprintf(buf, "%d\n", mlc->aco_enabled); +} + +static ssize_t mdss_livedisplay_set_aco(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int value = 0; + struct fb_info *fbi = dev_get_drvdata(dev); + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par; + struct mdss_livedisplay_ctx *mlc = get_ctx(mfd); + + sscanf(buf, "%du", &value); + if ((value == 0 || value == 1) + && value != mlc->aco_enabled) { + mlc->aco_enabled = value; + mdss_livedisplay_event(mfd, MODE_AUTO_CONTRAST); + } + + return count; +} + +static ssize_t mdss_livedisplay_get_preset(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par; + struct mdss_livedisplay_ctx *mlc = get_ctx(mfd); + + return sprintf(buf, "%d\n", mlc->preset); +} + +static ssize_t mdss_livedisplay_set_preset(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int value = 0; + struct fb_info *fbi = dev_get_drvdata(dev); + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par; + struct mdss_livedisplay_ctx *mlc = get_ctx(mfd); + + sscanf(buf, "%du", &value); + if (value < 0 || value >= mlc->num_presets) + return -EINVAL; + + mlc->preset = value; + mdss_livedisplay_event(mfd, MODE_PRESET); + + return count; +} + +static ssize_t mdss_livedisplay_get_num_presets(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par; + struct mdss_livedisplay_ctx *mlc = get_ctx(mfd); + + return sprintf(buf, "%d\n", mlc->num_presets); +} + +static DEVICE_ATTR(cabc, S_IRUGO | S_IWUSR | S_IWGRP, mdss_livedisplay_get_cabc, mdss_livedisplay_set_cabc); +static DEVICE_ATTR(sre, S_IRUGO | S_IWUSR | S_IWGRP, mdss_livedisplay_get_sre, mdss_livedisplay_set_sre); +static DEVICE_ATTR(color_enhance, S_IRUGO | S_IWUSR | S_IWGRP, mdss_livedisplay_get_color_enhance, mdss_livedisplay_set_color_enhance); +static DEVICE_ATTR(aco, S_IRUGO | S_IWUSR | S_IWGRP, mdss_livedisplay_get_aco, mdss_livedisplay_set_aco); +static DEVICE_ATTR(preset, S_IRUGO | S_IWUSR | S_IWGRP, mdss_livedisplay_get_preset, mdss_livedisplay_set_preset); +static DEVICE_ATTR(num_presets, S_IRUGO, mdss_livedisplay_get_num_presets, NULL); +static DEVICE_ATTR(hbm, S_IRUGO | S_IWUSR | S_IWGRP, mdss_livedisplay_get_hbm, mdss_livedisplay_set_hbm); + +int mdss_livedisplay_parse_dt(struct device_node *np, struct mdss_panel_info *pinfo) +{ + int rc = 0, i = 0; + struct mdss_livedisplay_ctx *mlc; + char preset_name[64]; + const char *link_state; + uint32_t tmp = 0; + + if (pinfo == NULL) + return -ENODEV; + + mlc = kzalloc(sizeof(struct mdss_livedisplay_ctx), GFP_KERNEL); + mutex_init(&mlc->lock); + + link_state = of_get_property(np, "cm,mdss-livedisplay-command-state", NULL); + if (link_state && !strcmp(link_state, "dsi_lp_mode")) + mlc->link_state = DSI_LP_MODE; + else + mlc->link_state = DSI_HS_MODE; + + mlc->cabc_cmds = of_get_property(np, + "cm,mdss-livedisplay-cabc-cmd", &mlc->cabc_cmds_len); + + if (mlc->cabc_cmds_len > 0) { + rc = of_property_read_u32(np, "cm,mdss-livedisplay-cabc-ui-value", &tmp); + if (rc == 0) { + mlc->caps |= MODE_CABC; + mlc->cabc_ui_value = (uint8_t)(tmp & 0xFF); + of_property_read_u32(np, "cm,mdss-livedisplay-cabc-image-value", &tmp); + mlc->cabc_image_value = (uint8_t)(tmp & 0xFF); + of_property_read_u32(np, "cm,mdss-livedisplay-cabc-video-value", &tmp); + mlc->cabc_video_value = (uint8_t)(tmp & 0xFF); + } + rc = of_property_read_u32(np, "cm,mdss-livedisplay-sre-medium-value", &tmp); + if (rc == 0) { + mlc->caps |= MODE_SRE; + mlc->sre_medium_value = (uint8_t)(tmp & 0xFF); + of_property_read_u32(np, "cm,mdss-livedisplay-sre-weak-value", &tmp); + mlc->sre_weak_value = (uint8_t)(tmp & 0xFF); + of_property_read_u32(np, "cm,mdss-livedisplay-sre-strong-value", &tmp); + mlc->sre_strong_value = (uint8_t)(tmp & 0xFF); + } + rc = of_property_read_u32(np, "cm,mdss-livedisplay-aco-value", &tmp); + if (rc == 0) { + mlc->caps |= MODE_AUTO_CONTRAST; + mlc->aco_value = (uint8_t)(tmp & 0xFF); + } + } + + mlc->hbm_on_cmds = of_get_property(np, + "cm,mdss-livedisplay-hbm-on-cmd", &mlc->hbm_on_cmds_len); + if (mlc->hbm_on_cmds_len) { + mlc->hbm_off_cmds = of_get_property(np, + "cm,mdss-livedisplay-hbm-off-cmd", &mlc->hbm_off_cmds_len); + if (mlc->hbm_off_cmds_len) + mlc->caps |= MODE_HIGH_BRIGHTNESS; + } + + mlc->ce_on_cmds = of_get_property(np, + "cm,mdss-livedisplay-color-enhance-on", &mlc->ce_on_cmds_len); + if (mlc->ce_on_cmds_len) { + mlc->ce_off_cmds = of_get_property(np, + "cm,mdss-livedisplay-color-enhance-off", &mlc->ce_off_cmds_len); + if (mlc->ce_off_cmds_len) + mlc->caps |= MODE_COLOR_ENHANCE; + } + + for (i = 0; i < MAX_PRESETS; i++) { + memset(preset_name, 0, sizeof(preset_name)); + snprintf(preset_name, 64, "%s-%d", "cm,mdss-livedisplay-preset", i); + mlc->presets[mlc->num_presets] = of_get_property(np, preset_name, + &mlc->presets_len[mlc->num_presets]); + if (mlc->presets_len[mlc->num_presets] > 0) + mlc->num_presets++; + } + + if (mlc->num_presets) + mlc->caps |= MODE_PRESET; + + mlc->post_cmds = of_get_property(np, + "cm,mdss-livedisplay-post-cmd", &mlc->post_cmds_len); + + pinfo->livedisplay = mlc; + return 0; +} + +int mdss_livedisplay_create_sysfs(struct msm_fb_data_type *mfd) +{ + int rc = 0; + struct mdss_livedisplay_ctx *mlc = get_ctx(mfd); + + if (mlc == NULL) + return 0; + + if (mlc->caps & MODE_CABC) { + rc = sysfs_create_file(&mfd->fbi->dev->kobj, &dev_attr_cabc.attr); + if (rc) + goto sysfs_err; + } + + if (mlc->caps & MODE_SRE) { + rc = sysfs_create_file(&mfd->fbi->dev->kobj, &dev_attr_sre.attr); + if (rc) + goto sysfs_err; + } + + if (mlc->caps & MODE_AUTO_CONTRAST) { + rc = sysfs_create_file(&mfd->fbi->dev->kobj, &dev_attr_aco.attr); + if (rc) + goto sysfs_err; + } + + if (mlc->caps & MODE_COLOR_ENHANCE) { + rc = sysfs_create_file(&mfd->fbi->dev->kobj, &dev_attr_color_enhance.attr); + if (rc) + goto sysfs_err; + } + + if (mlc->caps & MODE_HIGH_BRIGHTNESS) { + rc = sysfs_create_file(&mfd->fbi->dev->kobj, &dev_attr_hbm.attr); + if (rc) + goto sysfs_err; + } + + if (mlc->caps & MODE_PRESET) { + rc = sysfs_create_file(&mfd->fbi->dev->kobj, &dev_attr_preset.attr); + if (rc) + goto sysfs_err; + rc = sysfs_create_file(&mfd->fbi->dev->kobj, &dev_attr_num_presets.attr); + if (rc) + goto sysfs_err; + } + + mlc->mfd = mfd; + + return rc; + +sysfs_err: + pr_err("%s: sysfs creation failed, rc=%d", __func__, rc); + return rc; +} + diff --git a/drivers/video/msm/mdss/mdss_livedisplay.h b/drivers/video/msm/mdss/mdss_livedisplay.h new file mode 100644 index 0000000000000..099ebe20daf5f --- /dev/null +++ b/drivers/video/msm/mdss/mdss_livedisplay.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015 The CyanogenMod Project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef MDSS_LIVEDISPLAY_H +#define MDSS_LIVEDISPLAY_H + +#include +#include + +#include "mdss_dsi.h" +#include "mdss_fb.h" + +#define MAX_PRESETS 10 + +struct mdss_livedisplay_ctx { + uint8_t cabc_ui_value; + uint8_t cabc_image_value; + uint8_t cabc_video_value; + uint8_t sre_weak_value; + uint8_t sre_medium_value; + uint8_t sre_strong_value; + uint8_t aco_value; + + const uint8_t *ce_off_cmds; + const uint8_t *ce_on_cmds; + unsigned int ce_off_cmds_len; + unsigned int ce_on_cmds_len; + + const uint8_t *hbm_off_cmds; + const uint8_t *hbm_on_cmds; + unsigned int hbm_off_cmds_len; + unsigned int hbm_on_cmds_len; + + const uint8_t *presets[MAX_PRESETS]; + unsigned int presets_len[MAX_PRESETS]; + + const uint8_t *cabc_cmds; + unsigned int cabc_cmds_len; + + const uint8_t *post_cmds; + unsigned int post_cmds_len; + + unsigned int preset; + unsigned int cabc_level; + unsigned int sre_level; + bool aco_enabled; + bool ce_enabled; + bool hbm_enabled; + + unsigned int link_state; + + unsigned int num_presets; + unsigned int caps; + + struct msm_fb_data_type *mfd; + + struct mutex lock; +}; + +enum { + CABC_OFF, + CABC_UI, + CABC_IMAGE, + CABC_VIDEO, + CABC_MAX +}; + +enum { + SRE_OFF, + SRE_WEAK, + SRE_MEDIUM, + SRE_STRONG, + SRE_MAX +}; + +enum { + MODE_CABC = 0x01, + MODE_SRE = 0x02, + MODE_AUTO_CONTRAST = 0x04, + MODE_COLOR_ENHANCE = 0x08, + MODE_PRESET = 0x10, + MODE_HIGH_BRIGHTNESS = 0x20, + MODE_UPDATE_ALL = 0xFF, +}; + +int mdss_livedisplay_update(struct mdss_dsi_ctrl_pdata *ctrl_pdata, int types); +int mdss_livedisplay_parse_dt(struct device_node *np, struct mdss_panel_info *pinfo); +int mdss_livedisplay_create_sysfs(struct msm_fb_data_type *mfd); +int mdss_livedisplay_event(struct msm_fb_data_type *mfd, int types); + +static inline bool is_cabc_cmd(unsigned int value) +{ + return (value & MODE_CABC) || (value & MODE_SRE) || (value & MODE_AUTO_CONTRAST); +} + +static inline struct mdss_livedisplay_ctx* get_ctx(struct msm_fb_data_type *mfd) +{ + return mfd->panel_info->livedisplay; +} + +static inline struct mdss_dsi_ctrl_pdata* get_ctrl(struct msm_fb_data_type *mfd) +{ + struct mdss_panel_data *pdata = dev_get_platdata(&mfd->pdev->dev); + return container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); +} + +#endif diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h index 19dfbce258e4b..a16fabe8eefe6 100644 --- a/drivers/video/msm/mdss/mdss_panel.h +++ b/drivers/video/msm/mdss/mdss_panel.h @@ -272,6 +272,7 @@ enum mdss_intf_events { MDSS_EVENT_PANEL_TIMING_SWITCH, MDSS_EVENT_UPDATE_PARAMS, MDSS_EVENT_MAX, + MDSS_EVENT_UPDATE_LIVEDISPLAY, }; struct lcd_panel_info { @@ -592,6 +593,8 @@ struct mdss_mdp_pp_tear_check { u32 refx100; }; +struct mdss_livedisplay_ctx; + struct mdss_panel_roi_alignment { u32 xstart_pix_align; u32 width_pix_align; @@ -745,6 +748,8 @@ struct mdss_panel_info { */ u32 adjust_timer_delay_ms; + struct mdss_livedisplay_ctx *livedisplay; + /* debugfs structure for the panel */ struct mdss_panel_debugfs_info *debugfs_info; From 48484c63a3ed12571e96c310347dc788f7f1555a Mon Sep 17 00:00:00 2001 From: Sultanxda Date: Sun, 19 Mar 2017 15:15:54 -0700 Subject: [PATCH 246/508] mdss: livedisplay: Fix memory leaks in mdss_livedisplay_update() parse_dsi_cmds() allocates two blocks of memory and stores their addresses in a stack-allocated variable, but they are never freed, so when the function exits, all references to them are gone. Free the allocated memory after using it in order to fix the memory leaks. Change-Id: Ie574848e2429167fc38ed39975feb3df68ed2aed Signed-off-by: Sultanxda --- drivers/video/msm/mdss/mdss_livedisplay.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/msm/mdss/mdss_livedisplay.c b/drivers/video/msm/mdss/mdss_livedisplay.c index f2cd8f2438c86..a3f4d07fe9594 100644 --- a/drivers/video/msm/mdss/mdss_livedisplay.c +++ b/drivers/video/msm/mdss/mdss_livedisplay.c @@ -246,6 +246,8 @@ int mdss_livedisplay_update(struct mdss_dsi_ctrl_pdata *ctrl_pdata, ret = parse_dsi_cmds(mlc, &dsi_cmds, (const uint8_t *)cmd_buf, len); if (ret == 0) { mdss_dsi_panel_cmds_send(ctrl_pdata, &dsi_cmds, CMD_REQ_COMMIT); + kfree(dsi_cmds.buf); + kfree(dsi_cmds.cmds); } else { pr_err("%s: error parsing DSI command! ret=%d", __func__, ret); } From 12844e2799fe622c974532ebf278e808a6ca58cd Mon Sep 17 00:00:00 2001 From: Andres Oportus Date: Thu, 11 May 2017 08:57:39 -0700 Subject: [PATCH 247/508] ANDROID: Fix cpufreq stats table creation cpufreq stats does not correctly supports multiple cpus per profile. For instance Marlin/Sailfish per cpu stats struct does not get created for all cpus (only one per policy). This change does not provide full support for multiple cpus per profile but allows stats creation per cpu to allow b/34133340 to be completed. Bug: 38244231 Bug: 34133340 Test: Boot Sailfish Signed-off-by: Andres Oportus Change-Id: I72ea548a199f57ed841618b08b9c41e99b493376 --- drivers/cpufreq/cpufreq_stats.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 8e093a5d48f90..7fb439a3f0a68 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -359,12 +359,11 @@ static void cpufreq_powerstats_free(void) } static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, - struct cpufreq_frequency_table *table, int count) + int cpu, struct cpufreq_frequency_table *table, int count) { unsigned int i, ret = 0; struct cpufreq_stats *stat; unsigned int alloc_size; - unsigned int cpu = policy->cpu; struct cpufreq_frequency_table *pos; if (per_cpu(cpufreq_stats_table, cpu)) @@ -374,8 +373,6 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, return -ENOMEM; ret = sysfs_create_group(&policy->kobj, &stats_attr_group); - if (ret) - goto error_out; stat->cpu = cpu; per_cpu(cpufreq_stats_table, cpu) = stat; @@ -408,7 +405,6 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, return 0; error_alloc: sysfs_remove_group(&policy->kobj, &stats_attr_group); -error_out: kfree(stat); per_cpu(cpufreq_stats_table, cpu) = NULL; return ret; @@ -586,7 +582,7 @@ static void cpufreq_stats_create_table(unsigned int cpu) if (!per_cpu(cpufreq_power_stats, cpu)) cpufreq_powerstats_create(cpu, table, count); - __cpufreq_stats_create_table(policy, table, count); + __cpufreq_stats_create_table(policy, cpu, table, count); } cpufreq_cpu_put(policy); } @@ -623,7 +619,7 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb, } if (val == CPUFREQ_CREATE_POLICY) - ret = __cpufreq_stats_create_table(policy, table, count); + ret = __cpufreq_stats_create_table(policy, cpu, table, count); return ret; } From cb145094cc66f21be5cc6c9214b021ecd38e6da1 Mon Sep 17 00:00:00 2001 From: Andres Oportus Date: Wed, 1 Feb 2017 13:34:54 -0800 Subject: [PATCH 248/508] ANDROID: cpufreq_stat: add per task/uid/freq stats Adds per process nodes in /proc/PID/time_in_state showing per frequency times and adds a global /proc/uid_time_in_state showing per frequency per uid times. Bug: 34133340 Bug: 38320164 Tests: boot sailfish and reading /proc/uid_time_in_state and /proc/$$/time_in_state Signed-off-by: Andres Oportus Change-Id: Ideb22b608b9a5e7bd2200a3a6df0f110b635f96a --- drivers/cpufreq/cpufreq_stats.c | 356 +++++++++++++++++++++++++++++--- fs/proc/base.c | 7 + include/linux/cpufreq.h | 4 + include/linux/sched.h | 2 + kernel/exit.c | 4 + kernel/sched/core.c | 4 + 6 files changed, 354 insertions(+), 23 deletions(-) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 7fb439a3f0a68..ae0e9b9ce5d32 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -9,24 +9,45 @@ * published by the Free Software Foundation. */ +#include #include #include +#include +#include #include -#include -#include #include +#include +#include #include -#include +#include +#include +#include + +#define UID_HASH_BITS 10 + +DECLARE_HASHTABLE(uid_hash_table, UID_HASH_BITS); static spinlock_t cpufreq_stats_lock; +static DEFINE_RT_MUTEX(uid_lock); /* uid_hash_table */ + +struct uid_entry { + uid_t uid; + unsigned int dead_max_states; + unsigned int alive_max_states; + u64 *dead_time_in_state; + u64 *alive_time_in_state; + struct hlist_node hash; +}; + struct cpufreq_stats { unsigned int cpu; unsigned int total_trans; unsigned long long last_time; unsigned int max_state; unsigned int state_num; - unsigned int last_index; + atomic_t cpu_freq_i; + atomic_t all_freq_i; u64 *time_in_state; unsigned int *freq_table; #ifdef CONFIG_CPU_FREQ_STAT_DETAILS @@ -52,6 +73,7 @@ struct all_freq_table { }; static struct all_freq_table *all_freq_table; +static bool cpufreq_all_freq_init; static DEFINE_PER_CPU(struct all_cpufreq_stats *, all_cpufreq_stats); static DEFINE_PER_CPU(struct cpufreq_stats *, cpufreq_stats_table); @@ -62,6 +84,125 @@ struct cpufreq_stats_attribute { ssize_t(*show) (struct cpufreq_stats *, char *); }; +/* Caller must hold uid lock */ +static struct uid_entry *find_uid_entry(uid_t uid) +{ + struct uid_entry *uid_entry; + + hash_for_each_possible(uid_hash_table, uid_entry, hash, uid) { + if (uid_entry->uid == uid) + return uid_entry; + } + return NULL; +} + +/* Caller must hold uid lock */ +static struct uid_entry *find_or_register_uid(uid_t uid) +{ + struct uid_entry *uid_entry; + + uid_entry = find_uid_entry(uid); + if (uid_entry) + return uid_entry; + + uid_entry = kzalloc(sizeof(struct uid_entry), GFP_ATOMIC); + if (!uid_entry) + return NULL; + + uid_entry->uid = uid; + + hash_add(uid_hash_table, &uid_entry->hash, uid); + + return uid_entry; +} + + +static int uid_time_in_state_show(struct seq_file *m, void *v) +{ + struct uid_entry *uid_entry; + struct task_struct *task, *temp; + unsigned long bkt; + int i; + + if (!all_freq_table || !cpufreq_all_freq_init) + return 0; + + seq_puts(m, "uid:"); + for (i = 0; i < all_freq_table->table_size; ++i) + seq_printf(m, " %d", all_freq_table->freq_table[i]); + seq_putc(m, '\n'); + + rt_mutex_lock(&uid_lock); + + rcu_read_lock(); + do_each_thread(temp, task) { + /* if this task has exited, we have already accounted for all + * time in state + */ + if (!task->time_in_state) + continue; + + uid_entry = find_or_register_uid(from_kuid_munged( + current_user_ns(), task_uid(task))); + if (!uid_entry) + continue; + + if (uid_entry->alive_max_states < task->max_states) { + uid_entry->alive_time_in_state = krealloc( + uid_entry->alive_time_in_state, + task->max_states * + sizeof(uid_entry->alive_time_in_state[0]), + GFP_ATOMIC); + memset(uid_entry->alive_time_in_state + + uid_entry->alive_max_states, + 0, (task->max_states - + uid_entry->alive_max_states) * + sizeof(uid_entry->alive_time_in_state[0])); + uid_entry->alive_max_states = task->max_states; + } + + for (i = 0; i < task->max_states; ++i) { + uid_entry->alive_time_in_state[i] += + atomic_read(&task->time_in_state[i]); + } + } while_each_thread(temp, task); + rcu_read_unlock(); + + hash_for_each(uid_hash_table, bkt, uid_entry, hash) { + int max_states = uid_entry->dead_max_states; + + if (uid_entry->alive_max_states > max_states) + max_states = uid_entry->alive_max_states; + if (max_states) + seq_printf(m, "%d:", uid_entry->uid); + for (i = 0; i < max_states; ++i) { + u64 total_time_in_state = 0; + + if (uid_entry->dead_time_in_state && + i < uid_entry->dead_max_states) { + total_time_in_state = + uid_entry->dead_time_in_state[i]; + } + if (uid_entry->alive_time_in_state && + i < uid_entry->alive_max_states) { + total_time_in_state += + uid_entry->alive_time_in_state[i]; + } + seq_printf(m, " %lu", (unsigned long) + cputime_to_clock_t(total_time_in_state)); + } + if (max_states) + seq_putc(m, '\n'); + + kfree(uid_entry->alive_time_in_state); + uid_entry->alive_time_in_state = NULL; + uid_entry->alive_max_states = 0; + } + + rt_mutex_unlock(&uid_lock); + return 0; +} + static int cpufreq_stats_update(unsigned int cpu) { struct cpufreq_stats *stat; @@ -77,17 +218,66 @@ static int cpufreq_stats_update(unsigned int cpu) return 0; } if (stat->time_in_state) { - stat->time_in_state[stat->last_index] += - cur_time - stat->last_time; + int cpu_freq_i = atomic_read(&stat->cpu_freq_i); + + stat->time_in_state[cpu_freq_i] += cur_time - stat->last_time; if (all_stat) - all_stat->time_in_state[stat->last_index] += - cur_time - stat->last_time; + all_stat->time_in_state[cpu_freq_i] += + cur_time - stat->last_time; } stat->last_time = cur_time; spin_unlock(&cpufreq_stats_lock); return 0; } +void cpufreq_task_stats_init(struct task_struct *p) +{ + size_t alloc_size; + + WRITE_ONCE(p->time_in_state, NULL); + WRITE_ONCE(p->max_states, 0); + + if (!all_freq_table || !cpufreq_all_freq_init) + return; + + WRITE_ONCE(p->max_states, all_freq_table->table_size); + + /* Create all_freq_table for clockticks in all possible freqs in all + * cpus + */ + alloc_size = p->max_states * sizeof(p->time_in_state[0]); + + WRITE_ONCE(p->time_in_state, kzalloc(alloc_size, GFP_KERNEL)); +} + +void cpufreq_task_stats_exit(struct task_struct *p) +{ + void *temp = p->time_in_state; + + WRITE_ONCE(p->time_in_state, NULL); + mb(); /* p->time_in_state */ + kfree(temp); +} + +int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns, + struct pid *pid, struct task_struct *p) +{ + int i; + + if (!all_freq_table || !cpufreq_all_freq_init || !p->time_in_state) + return 0; + + spin_lock(&cpufreq_stats_lock); + for (i = 0; i < p->max_states; ++i) { + seq_printf(m, "%d %lu\n", all_freq_table->freq_table[i], + (unsigned long)cputime_to_clock_t( + atomic_read(&p->time_in_state[i]))); + } + spin_unlock(&cpufreq_stats_lock); + + return 0; +} + static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf) { struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu); @@ -126,20 +316,48 @@ static int get_index_all_cpufreq_stat(struct all_cpufreq_stats *all_stat, return -1; } +/* Called without cpufreq_stats_lock held */ void acct_update_power(struct task_struct *task, cputime_t cputime) { struct cpufreq_power_stats *powerstats; struct cpufreq_stats *stats; unsigned int cpu_num, curr; + int cpu_freq_i; + int all_freq_i; + u64 last_cputime; + atomic64_t *time_in_state; if (!task) return; + cpu_num = task_cpu(task); - powerstats = per_cpu(cpufreq_power_stats, cpu_num); stats = per_cpu(cpufreq_stats_table, cpu_num); - if (!powerstats || !stats) + if (!stats) return; - curr = powerstats->curr[stats->last_index]; + all_freq_i = atomic_read(&stats->all_freq_i); + time_in_state = READ_ONCE(task->time_in_state); + + /* This function is called from a different context + * Interruptions in between reads/assignements are ok + */ + if (all_freq_table && cpufreq_all_freq_init && time_in_state && + !(task->flags & PF_EXITING) && + all_freq_i != -1 && all_freq_i < READ_ONCE(task->max_states)) { + last_cputime = + atomic_read(&time_in_state[all_freq_i]); + atomic_set(&time_in_state[all_freq_i], + last_cputime + cputime); + } + + powerstats = per_cpu(cpufreq_power_stats, cpu_num); + if (!powerstats) + return; + + cpu_freq_i = atomic_read(&stats->cpu_freq_i); + if (cpu_freq_i == -1) + return; + + curr = powerstats->curr[cpu_freq_i]; if (task->cpu_power != ULLONG_MAX) task->cpu_power += curr * cputime_to_usecs(cputime); } @@ -196,7 +414,7 @@ static ssize_t show_all_time_in_state(struct kobject *kobj, index = get_index_all_cpufreq_stat(all_stat, freq); if (index != -1) { len += scnprintf(buf + len, PAGE_SIZE - len, - "%llu\t\t", (unsigned long long) + "%lu\t\t", (unsigned long) cputime64_to_clock_t(all_stat->time_in_state[index])); } else { len += scnprintf(buf + len, PAGE_SIZE - len, @@ -400,7 +618,7 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, stat->state_num = i; spin_lock(&cpufreq_stats_lock); stat->last_time = get_jiffies_64(); - stat->last_index = freq_table_get_index(stat, policy->cur); + atomic_set(&stat->cpu_freq_i, freq_table_get_index(stat, policy->cur)); spin_unlock(&cpufreq_stats_lock); return 0; error_alloc: @@ -501,7 +719,8 @@ static void create_all_freq_table(void) static void add_all_freq_table(unsigned int freq) { unsigned int size; - size = sizeof(unsigned int) * (all_freq_table->table_size + 1); + size = sizeof(all_freq_table->freq_table[0]) * + (all_freq_table->table_size + 1); all_freq_table->freq_table = krealloc(all_freq_table->freq_table, size, GFP_ATOMIC); if (IS_ERR(all_freq_table->freq_table)) { @@ -627,9 +846,11 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb, static int cpufreq_stat_notifier_trans(struct notifier_block *nb, unsigned long val, void *data) { + int i; struct cpufreq_freqs *freq = data; struct cpufreq_stats *stat; - int old_index, new_index; + int cpu_freq_old_i, cpu_freq_new_i; + int all_freq_old_i, all_freq_new_i; if (val != CPUFREQ_POSTCHANGE) return 0; @@ -638,28 +859,101 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb, if (!stat) return 0; - old_index = stat->last_index; - new_index = freq_table_get_index(stat, freq->new); + cpu_freq_old_i = atomic_read(&stat->cpu_freq_i); + cpu_freq_new_i = freq_table_get_index(stat, freq->new); + + all_freq_old_i = atomic_read(&stat->all_freq_i); + for (i = 0; i < all_freq_table->table_size; ++i) { + if (all_freq_table->freq_table[i] == freq->new) + break; + } + if (i != all_freq_table->table_size) + all_freq_new_i = i; + else + all_freq_new_i = -1; /* We can't do stat->time_in_state[-1]= .. */ - if (old_index == -1 || new_index == -1) + if (cpu_freq_old_i == -1 || cpu_freq_new_i == -1) + return 0; + + if (all_freq_old_i == -1 || all_freq_new_i == -1) return 0; cpufreq_stats_update(freq->cpu); - if (old_index == new_index) + if (cpu_freq_old_i == cpu_freq_new_i) + return 0; + + if (all_freq_old_i == all_freq_new_i) return 0; spin_lock(&cpufreq_stats_lock); - stat->last_index = new_index; + atomic_set(&stat->cpu_freq_i, cpu_freq_new_i); + atomic_set(&stat->all_freq_i, all_freq_new_i); #ifdef CONFIG_CPU_FREQ_STAT_DETAILS - stat->trans_table[old_index * stat->max_state + new_index]++; + stat->trans_table[cpu_freq_old_i * stat->max_state + cpu_freq_new_i]++; #endif stat->total_trans++; spin_unlock(&cpufreq_stats_lock); return 0; } + +static int process_notifier(struct notifier_block *self, + unsigned long cmd, void *v) +{ + struct task_struct *task = v; + struct uid_entry *uid_entry; + uid_t uid; + int i; + + if (!task) + return NOTIFY_OK; + + rt_mutex_lock(&uid_lock); + + uid = from_kuid_munged(current_user_ns(), task_uid(task)); + uid_entry = find_or_register_uid(uid); + if (!uid_entry) { + rt_mutex_unlock(&uid_lock); + pr_err("%s: failed to find uid %d\n", __func__, uid); + return NOTIFY_OK; + } + + if (uid_entry->dead_max_states < task->max_states) { + uid_entry->dead_time_in_state = krealloc( + uid_entry->dead_time_in_state, + task->max_states * + sizeof(uid_entry->dead_time_in_state[0]), + GFP_ATOMIC); + memset(uid_entry->dead_time_in_state + + uid_entry->dead_max_states, + 0, (task->max_states - uid_entry->dead_max_states) * + sizeof(uid_entry->dead_time_in_state[0])); + uid_entry->dead_max_states = task->max_states; + } + + for (i = 0; i < task->max_states; ++i) { + uid_entry->dead_time_in_state[i] += + atomic_read(&task->time_in_state[i]); + } + + rt_mutex_unlock(&uid_lock); + return NOTIFY_OK; +} + +static int uid_time_in_state_open(struct inode *inode, struct file *file) +{ + return single_open(file, uid_time_in_state_show, PDE_DATA(inode)); +} + +static const struct file_operations uid_time_in_state_fops = { + .open = uid_time_in_state_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static struct notifier_block notifier_policy_block = { .notifier_call = cpufreq_stat_notifier_policy }; @@ -668,6 +962,10 @@ static struct notifier_block notifier_trans_block = { .notifier_call = cpufreq_stat_notifier_trans }; +static struct notifier_block process_notifier_block = { + .notifier_call = process_notifier, +}; + static int __init cpufreq_stats_init(void) { int ret; @@ -679,11 +977,18 @@ static int __init cpufreq_stats_init(void) if (ret) return ret; + create_all_freq_table(); + get_online_cpus(); for_each_online_cpu(cpu) cpufreq_stats_create_table(cpu); put_online_cpus(); - + /* XXX TODO task support for time_in_state doesn't update freq + * info for tasks already initialized, so tasks initialized early + * (before cpufreq_stat_init is done) do not get time_in_state data + * and CPUFREQ_TRANSITION_NOTIFIER does not update freq info for + * tasks already created + */ ret = cpufreq_register_notifier(¬ifier_trans_block, CPUFREQ_TRANSITION_NOTIFIER); if (ret) { @@ -696,7 +1001,6 @@ static int __init cpufreq_stats_init(void) return ret; } - create_all_freq_table(); WARN_ON(cpufreq_get_global_kobject()); ret = sysfs_create_file(cpufreq_global_kobject, &_attr_all_time_in_state.attr); @@ -708,6 +1012,12 @@ static int __init cpufreq_stats_init(void) if (ret) pr_warn("Cannot create sysfs file for cpufreq current stats\n"); + proc_create_data("uid_time_in_state", 0444, NULL, + &uid_time_in_state_fops, NULL); + + profile_event_register(PROFILE_TASK_EXIT, &process_notifier_block); + + cpufreq_all_freq_init = true; return 0; } static void __exit cpufreq_stats_exit(void) diff --git a/fs/proc/base.c b/fs/proc/base.c index d0747bebd3255..bd915ac5aa73f 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -76,6 +76,7 @@ #include #include #include +#include #include #include #include @@ -2845,6 +2846,9 @@ static const struct pid_entry tgid_base_stuff[] = { #ifdef CONFIG_CHECKPOINT_RESTORE REG("timers", S_IRUGO, proc_timers_operations), #endif +#ifdef CONFIG_CPU_FREQ_STAT + ONE("time_in_state", 0444, proc_time_in_state_show), +#endif }; static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx) @@ -3224,6 +3228,9 @@ static const struct pid_entry tid_base_stuff[] = { REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations), REG("setgroups", S_IRUGO|S_IWUSR, proc_setgroups_operations), #endif +#ifdef CONFIG_CPU_FREQ_STAT + ONE("time_in_state", 0444, proc_time_in_state_show), +#endif }; static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx) diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 5db5b8793d3c5..4efb94e284f7c 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -651,6 +651,10 @@ int cpufreq_generic_init(struct cpufreq_policy *policy, *********************************************************************/ void acct_update_power(struct task_struct *p, cputime_t cputime); +void cpufreq_task_stats_init(struct task_struct *p); +void cpufreq_task_stats_exit(struct task_struct *p); +int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns, + struct pid *pid, struct task_struct *p); struct sched_domain; unsigned long cpufreq_scale_freq_capacity(struct sched_domain *sd, int cpu); diff --git a/include/linux/sched.h b/include/linux/sched.h index 763c21b84c089..0f1b34e18ec0a 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1469,6 +1469,8 @@ struct task_struct { cputime_t utime, stime, utimescaled, stimescaled; cputime_t gtime; + atomic64_t *time_in_state; + unsigned int max_states; unsigned long long cpu_power; #ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE struct cputime prev_cputime; diff --git a/kernel/exit.c b/kernel/exit.c index 2e29c554c2866..b6142e0a1561c 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -174,6 +175,9 @@ void release_task(struct task_struct *p) { struct task_struct *leader; int zap_leader; +#ifdef CONFIG_CPU_FREQ_STAT + cpufreq_task_stats_exit(p); +#endif repeat: /* don't need to get the RCU readlock here - the process is dead and * can't be modifying its own credentials. But shut RCU-lockdep up */ diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 81ce793db58ee..ad4c6d269a4bd 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5250,6 +5250,10 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p) memset(&p->se.statistics, 0, sizeof(p->se.statistics)); #endif +#ifdef CONFIG_CPU_FREQ_STAT + cpufreq_task_stats_init(p); +#endif + RB_CLEAR_NODE(&p->dl.rb_node); hrtimer_init(&p->dl.dl_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); __dl_clear_params(p); From b45016b13859eea7cd77eb59b733f6274cca6056 Mon Sep 17 00:00:00 2001 From: Andres Oportus Date: Mon, 5 Jun 2017 12:46:44 -0700 Subject: [PATCH 249/508] ANDROID: cpufreq: stats: add uid removal for uid_time_in_state Bug: 62295304 Bug: 34133340 Test: Boot and test uid removal by writing to remove_uid_range Signed-off-by: Andres Oportus Change-Id: Ic51fc9480716a8aad88fb55549c2b69021038a11 --- drivers/cpufreq/cpufreq_stats.c | 21 +++++++++++++++++++++ drivers/misc/uid_sys_stats.c | 28 ++++++++++++++++++++++++---- include/linux/cpufreq.h | 3 ++- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index ae0e9b9ce5d32..3196cb61b91fe 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -806,6 +806,27 @@ static void cpufreq_stats_create_table(unsigned int cpu) cpufreq_cpu_put(policy); } +void cpufreq_task_stats_remove_uids(uid_t uid_start, uid_t uid_end) +{ + struct uid_entry *uid_entry; + struct hlist_node *tmp; + + rt_mutex_lock(&uid_lock); + + for (; uid_start <= uid_end; uid_start++) { + hash_for_each_possible_safe(uid_hash_table, uid_entry, tmp, + hash, uid_start) { + if (uid_start == uid_entry->uid) { + hash_del(&uid_entry->hash); + kfree(uid_entry->dead_time_in_state); + kfree(uid_entry); + } + } + } + + rt_mutex_unlock(&uid_lock); +} + static int cpufreq_stat_notifier_policy(struct notifier_block *nb, unsigned long val, void *data) { diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c index b3a076f4f2697..60e80121eff07 100644 --- a/drivers/misc/uid_sys_stats.c +++ b/drivers/misc/uid_sys_stats.c @@ -26,6 +26,7 @@ #include #include #include +#include #define UID_HASH_BITS 10 DECLARE_HASHTABLE(hash_table, UID_HASH_BITS); @@ -178,7 +179,8 @@ static ssize_t uid_remove_write(struct file *file, struct hlist_node *tmp; char uids[128]; char *start_uid, *end_uid = NULL; - long int uid_start = 0, uid_end = 0; + long int start = 0, end = 0; + uid_t uid_start, uid_end; if (count >= sizeof(uids)) count = sizeof(uids) - 1; @@ -193,15 +195,32 @@ static ssize_t uid_remove_write(struct file *file, if (!start_uid || !end_uid) return -EINVAL; - if (kstrtol(start_uid, 10, &uid_start) != 0 || - kstrtol(end_uid, 10, &uid_end) != 0) { + if (kstrtol(start_uid, 10, &start) != 0 || + kstrtol(end_uid, 10, &end) != 0) { return -EINVAL; } + +#define UID_T_MAX (((uid_t)~0U)-1) + if ((start < 0) || (end < 0) || + (start > UID_T_MAX) || (end > UID_T_MAX)) { + return -EINVAL; + } + + uid_start = start; + uid_end = end; + + /* TODO need to unify uid_sys_stats interface with uid_time_in_state. + * Here we are reusing remove_uid_range to reduce the number of + * sys calls made by userspace clients, remove_uid_range removes uids + * from both here as well as from cpufreq uid_time_in_state + */ + cpufreq_task_stats_remove_uids(uid_start, uid_end); + rt_mutex_lock(&uid_lock); for (; uid_start <= uid_end; uid_start++) { hash_for_each_possible_safe(hash_table, uid_entry, tmp, - hash, (uid_t)uid_start) { + hash, uid_start) { if (uid_start == uid_entry->uid) { hash_del(&uid_entry->hash); kfree(uid_entry); @@ -210,6 +229,7 @@ static ssize_t uid_remove_write(struct file *file, } rt_mutex_unlock(&uid_lock); + return count; } diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 4efb94e284f7c..f60edf74ce73a 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -653,8 +653,9 @@ int cpufreq_generic_init(struct cpufreq_policy *policy, void acct_update_power(struct task_struct *p, cputime_t cputime); void cpufreq_task_stats_init(struct task_struct *p); void cpufreq_task_stats_exit(struct task_struct *p); +void cpufreq_task_stats_remove_uids(uid_t uid_start, uid_t uid_end); int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns, - struct pid *pid, struct task_struct *p); + struct pid *pid, struct task_struct *p); struct sched_domain; unsigned long cpufreq_scale_freq_capacity(struct sched_domain *sd, int cpu); From e97b237e2f0e9ada2027ed97e5d6c051a11c93c5 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Wed, 5 Aug 2015 00:52:46 -0700 Subject: [PATCH 250/508] cpu-hotplug: convert cpu_hotplug_disabled to a counter As a prerequisite to exporting cpu_hotplug_enable/cpu_hotplug_disable functions to modules we need to convert cpu_hotplug_disabled to a counter to properly support disable -> disable -> enable call sequences. E.g. after Hyper-V vmbus module (which is supposed to be the first user of exported cpu_hotplug_enable/cpu_hotplug_disable) did cpu_hotplug_disable() hibernate path calls disable_nonboot_cpus() and if we hit an error in _cpu_down() enable_nonboot_cpus() will be called on the failure path (thus making cpu_hotplug_disabled = 0 and leaving cpu hotplug in 'enabled' state). Same problem is possible if more than 1 module use cpu_hotplug_disable/cpu_hotplug_enable on their load/unload paths. When one of these modules is been unloaded it is logical to leave cpu hotplug in 'disabled' state. To support the change we need to increse cpu_hotplug_disabled counter in disable_nonboot_cpus() unconditionally as all users of disable_nonboot_cpus() are supposed to do enable_nonboot_cpus() in case an error was returned. Change-Id: I9b5fa1b99b0ed009c5343fcdc5675cc1bdf70f58 Signed-off-by: Vitaly Kuznetsov Reviewed-by: Thomas Gleixner Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- .../power/suspend-and-cpuhotplug.txt | 6 +++--- kernel/cpu.c | 21 ++++++++++++------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Documentation/power/suspend-and-cpuhotplug.txt b/Documentation/power/suspend-and-cpuhotplug.txt index 2850df3bf957b..2fc909502db59 100644 --- a/Documentation/power/suspend-and-cpuhotplug.txt +++ b/Documentation/power/suspend-and-cpuhotplug.txt @@ -72,7 +72,7 @@ More details follow: | v Disable regular cpu hotplug - by setting cpu_hotplug_disabled=1 + by increasing cpu_hotplug_disabled | v Release cpu_add_remove_lock @@ -89,7 +89,7 @@ Resuming back is likewise, with the counterparts being (in the order of execution during resume): * enable_nonboot_cpus() which involves: | Acquire cpu_add_remove_lock - | Reset cpu_hotplug_disabled to 0, thereby enabling regular cpu hotplug + | Decrease cpu_hotplug_disabled, thereby enabling regular cpu hotplug | Call _cpu_up() [for all those cpus in the frozen_cpus mask, in a loop] | Release cpu_add_remove_lock v @@ -120,7 +120,7 @@ after the entire cycle is complete (i.e., suspend + resume). Acquire cpu_add_remove_lock | v - If cpu_hotplug_disabled is 1 + If cpu_hotplug_disabled > 0 return gracefully | | diff --git a/kernel/cpu.c b/kernel/cpu.c index 8503e5eaa4585..3e878d473a46a 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -192,14 +192,14 @@ void cpu_hotplug_done(void) void cpu_hotplug_disable(void) { cpu_maps_update_begin(); - cpu_hotplug_disabled = 1; + cpu_hotplug_disabled++; cpu_maps_update_done(); } void cpu_hotplug_enable(void) { cpu_maps_update_begin(); - cpu_hotplug_disabled = 0; + WARN_ON(--cpu_hotplug_disabled < 0); cpu_maps_update_done(); } @@ -576,13 +576,18 @@ int disable_nonboot_cpus(void) } } - if (!error) { + if (!error) BUG_ON(num_online_cpus() > 1); - /* Make sure the CPUs won't be enabled by someone else */ - cpu_hotplug_disabled = 1; - } else { + else pr_err("Non-boot CPUs are not disabled\n"); - } + + /* + * Make sure the CPUs won't be enabled by someone else. We need to do + * this even in case of failure as all disable_nonboot_cpus() users are + * supposed to do enable_nonboot_cpus() on the failure path. + */ + cpu_hotplug_disabled++; + cpu_maps_update_done(); return error; } @@ -602,7 +607,7 @@ void __ref enable_nonboot_cpus(void) /* Allow everyone to use the CPU hotplug again */ cpu_maps_update_begin(); - cpu_hotplug_disabled = 0; + WARN_ON(--cpu_hotplug_disabled < 0); if (cpumask_empty(frozen_cpus)) goto out; From eda9a55b4cb853ab38ddeb6072e926570621226e Mon Sep 17 00:00:00 2001 From: Scott Mertz Date: Sun, 20 Mar 2016 20:59:23 -0500 Subject: [PATCH 251/508] staging: prima: Cleanup unused files Change-Id: I23d65bc818a13496ffcebefa8e27a167521857f2 --- drivers/staging/prima/Android.mk | 179 ------ .../staging/prima/firmware_bin/WCNSS_cfg.dat | Bin 11514 -> 0 bytes .../prima/firmware_bin/WCNSS_qcom_cfg.ini | 529 ------------------ .../prima/firmware_bin/WCNSS_qcom_wlan_nv.bin | Bin 29816 -> 0 bytes 4 files changed, 708 deletions(-) delete mode 100644 drivers/staging/prima/Android.mk delete mode 100644 drivers/staging/prima/firmware_bin/WCNSS_cfg.dat delete mode 100644 drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini delete mode 100644 drivers/staging/prima/firmware_bin/WCNSS_qcom_wlan_nv.bin diff --git a/drivers/staging/prima/Android.mk b/drivers/staging/prima/Android.mk deleted file mode 100644 index 1576d0945059e..0000000000000 --- a/drivers/staging/prima/Android.mk +++ /dev/null @@ -1,179 +0,0 @@ -# Android makefile for the WLAN Module - -# Assume no targets will be supported -WLAN_CHIPSET := - -# Build/Package options for 8960 target -ifeq ($(TARGET_BOARD_PLATFORM),msm8960) -WLAN_CHIPSET := prima -WLAN_SELECT := CONFIG_PRIMA_WLAN=m -endif - -# Build/Package options for 8916, 8974, 8226, 8610, 8909, 8952, 8937, 8953 targets -ifneq (,$(filter msm8916 msm8974 msm8226 msm8610 msm8909 msm8952 msm8937 msm8953 titanium,$(TARGET_BOARD_PLATFORM))) -WLAN_CHIPSET := pronto -WLAN_SELECT := CONFIG_PRONTO_WLAN=m -endif - -# Build/Package only in case of supported target -ifneq ($(WLAN_CHIPSET),) - -LOCAL_PATH := $(call my-dir) - -ifeq ($(TARGET_SUPPORTS_WEARABLES),true) -ifneq ($(findstring device,$(LOCAL_PATH)),) - WLAN_DLKM := 1 -else - WLAN_DLKM := 0 -endif # findstring device -else -ifneq ($(findstring vendor,$(LOCAL_PATH)),) - WLAN_DLKM := 1 -else - WLAN_DLKM := 0 -endif # findstring vendor -endif # TARGET_SUPPORTS_WEARABLES - -# This makefile is only for DLKM -ifeq ($(WLAN_DLKM),1) - -# Determine if we are Proprietary or Open Source -ifneq ($(findstring opensource,$(LOCAL_PATH)),) - WLAN_PROPRIETARY := 0 -else - WLAN_PROPRIETARY := 1 -endif - -ifeq ($(WLAN_PROPRIETARY),1) - WLAN_BLD_DIR := vendor/qcom/proprietary/wlan -else -ifneq ($(TARGET_SUPPORTS_WEARABLES),true) -ifneq ($(ANDROID_BUILD_TOP),) - WLAN_BLD_DIR := $(ANDROID_BUILD_TOP)/vendor/qcom/opensource/wlan -else - WLAN_BLD_DIR := vendor/qcom/opensource/wlan -endif -else - WLAN_BLD_DIR := device/qcom/msm8909w/opensource/wlan -endif -endif - -# DLKM_DIR was moved for JELLY_BEAN (PLATFORM_SDK 16) -ifeq (1,$(filter 1,$(shell echo "$$(( $(PLATFORM_SDK_VERSION) >= 16 ))" ))) -ifneq ($(TARGET_SUPPORTS_WEARABLES),true) - DLKM_DIR := $(TOP)/device/qcom/common/dlkm -else - DLKM_DIR := $(BOARD_DLKM_DIR) -endif -else - DLKM_DIR := build/dlkm -endif - -# Copy WCNSS_cfg.dat file from firmware_bin/ folder to target out directory. -ifeq ($(WLAN_PROPRIETARY),0) - -$(shell mkdir -p $(TARGET_OUT_ETC)/firmware/wlan/prima) -$(shell rm -f $(TARGET_OUT_ETC)/firmware/wlan/prima/WCNSS_cfg.dat) -$(shell cp $(LOCAL_PATH)/firmware_bin/WCNSS_cfg.dat $(TARGET_OUT_ETC)/firmware/wlan/prima) - -else - -include $(CLEAR_VARS) -LOCAL_MODULE := WCNSS_qcom_wlan_nv.bin -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(PRODUCT_OUT)/persist -LOCAL_SRC_FILES := firmware_bin/$(LOCAL_MODULE) -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) -LOCAL_MODULE := WCNSS_cfg.dat -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/firmware/wlan/prima -LOCAL_SRC_FILES := firmware_bin/$(LOCAL_MODULE) -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) -LOCAL_MODULE := WCNSS_qcom_cfg.ini -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(PRODUCT_OUT)/persist -LOCAL_SRC_FILES := firmware_bin/$(LOCAL_MODULE) -include $(BUILD_PREBUILT) - -endif - -ifeq ($(TARGET_KERNEL_VERSION),) -$(info "WLAN: TARGET_KERNEL_VERSION is not defined, assuming default") -TARGET_KERNEL_SOURCE := kernel -KERNEL_TO_BUILD_ROOT_OFFSET := ../ -endif - -ifeq ($(KERNEL_TO_BUILD_ROOT_OFFSET),) -$(info "WLAN: KERNEL_TO_BUILD_ROOT_OFFSET is not defined, assuming default") -KERNEL_TO_BUILD_ROOT_OFFSET := ../ -endif - -# Build wlan.ko as either prima_wlan.ko or pronto_wlan.ko -########################################################### - -# This is set once per LOCAL_PATH, not per (kernel) module - -ifneq ($(TARGET_SUPPORTS_WEARABLES),true) -ifneq ($(ANDROID_BUILD_TOP),) -KBUILD_OPTIONS := WLAN_ROOT=$(WLAN_BLD_DIR)/prima -endif -endif - -ifeq ($(KBUILD_OPTIONS),) -KBUILD_OPTIONS := WLAN_ROOT=$(KERNEL_TO_BUILD_ROOT_OFFSET)$(WLAN_BLD_DIR)/prima -endif - -# We are actually building wlan.ko here, as per the -# requirement we are specifying _wlan.ko as LOCAL_MODULE. -# This means we need to rename the module to _wlan.ko -# after wlan.ko is built. -KBUILD_OPTIONS += MODNAME=wlan -KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) -KBUILD_OPTIONS += $(WLAN_SELECT) - - -ifeq ($(KERNEL_TO_BUILD_ROOT_OFFSET),../../) -VERSION=$(shell grep -w "VERSION =" $(TOP)/kernel/msm-$(TARGET_KERNEL_VERSION)/Makefile | sed 's/^VERSION = //' ) -PATCHLEVEL=$(shell grep -w "PATCHLEVEL =" $(TOP)/kernel/msm-$(TARGET_KERNEL_VERSION)/Makefile | sed 's/^PATCHLEVEL = //' ) -else -VERSION=$(shell grep -w "VERSION =" $(TOP)/kernel/Makefile | sed 's/^VERSION = //' ) -PATCHLEVEL=$(shell grep -w "PATCHLEVEL =" $(TOP)/kernel/Makefile | sed 's/^PATCHLEVEL = //' ) -endif - -include $(CLEAR_VARS) -LOCAL_MODULE := $(WLAN_CHIPSET)_wlan.ko -LOCAL_MODULE_KBUILD_NAME := wlan.ko -LOCAL_MODULE_TAGS := debug -LOCAL_MODULE_DEBUG_ENABLE := true -ifeq ($(PRODUCT_VENDOR_MOVE_ENABLED), true) - ifeq ($(WIFI_DRIVER_INSTALL_TO_KERNEL_OUT),true) - LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) - else - LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/modules/$(WLAN_CHIPSET) - endif -else - LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/modules/$(WLAN_CHIPSET) -endif # PRODUCT_VENDOR_MOVE_ENABLED -include $(DLKM_DIR)/AndroidKernelModule.mk -########################################################### - -#Create symbolic link -ifeq ($(PRODUCT_VENDOR_MOVE_ENABLED), true) -$(shell mkdir -p $(TARGET_OUT_VENDOR)/lib/modules; \ - ln -sf /$(TARGET_COPY_OUT_VENDOR)/lib/modules/$(WLAN_CHIPSET)/$(WLAN_CHIPSET)_wlan.ko \ - $(TARGET_OUT_VENDOR)/lib/modules/wlan.ko) -else -$(shell mkdir -p $(TARGET_OUT)/lib/modules; \ - ln -sf /system/lib/modules/$(WLAN_CHIPSET)/$(WLAN_CHIPSET)_wlan.ko \ - $(TARGET_OUT)/lib/modules/wlan.ko) -endif # PRODUCT_VENDOR_MOVE_ENABLED -endif # DLKM check - -endif # supported target check diff --git a/drivers/staging/prima/firmware_bin/WCNSS_cfg.dat b/drivers/staging/prima/firmware_bin/WCNSS_cfg.dat deleted file mode 100644 index 0637816b8238eb9990803e1014ad42a1bd8d2c77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11514 zcmeI137izg6^CE%G&_4Sy(5aZJFdVWAhR3-B1)@-`&h4_MiFF1j0+43ii+CcqG(VD zk07D}Vo*`>zVTS&MLZ%JW8#T1@xlucjRAD?y`HI|ci4&ikZ3d%`|YcK_3Bl1RbTtZ zDhribQeds^AW|SAHnfF4Ek&APYq7K7(}&alhFK!b;Rp>Z?`KPSJ8Y>~P*fh5f|wHv z#Y)AlPDneqwd@1^VK_9acHBY;k96!JD25U!O*v8q%^?C#(vfnA!Zx1cw!m(ibnNY* zC2S8nz>Y8`7LwXzNOnpkWam`EJvA1Wx@24~hRb1>WJ0d?;_j}gQrRu#NCm{iiR~_q zUFkXY9?*(^X7>h!>GV@gGM0aQM0B z#8ym?%NJ03Zd`VU?l1&K!|8AdEP|!*0=x%bLyNk&>Yq!35%xRgOCmPKHxp5=@3u;WU^6r^6X= zCQOC1;A}VtJeUU4;asSL8E_t)4>REcxDb8?v*04Q7%qVnbC?a6CLQ-O?B#F;{5qMC zIn|DPCCr7ZU>;lz*T8S89hnacU?Kb#u7%&hqGZCp4z7nAU@_cC&YO~s`_PQAd$Z@* zOW+o9yLXY}Zny{Th5O)s zXm?TAeE_=@9)ySBVR!`U;Zd&J-?K-L#T@%_cmke;r(hZUA?e7|o+Hn|v+x}Jk@)9f zIlKTb!k^$J_%pl=e}TWkE8JJFlH)aa9p0e-o8rg{c#HPG!Q0~4e}{kIdk5Zy_wc{Z z{62t{@F9GJ?_=6N!F~#>;4^Zr#(oZK;0yQ?{s~{fzi3~JUB~shKIO>Q@C`J8%yz_r z0tiiXTsz9O3xyLMI}Alo3?)zsWyJ6Zm8!`iHCV0dv(}XM#Uh0qC~k$wwpe{8_k!_o zU#ZCZp)||G8|s=z(V~4`4N0hW)4KZfaULwe81?5Ko7kBxm?H-|KSkr1n&`Vk z>uPs~s5%2h+w>ev@n0u#k%oq}$4p)0v|eHYGd8!sx*vHfJ!U4vH@XhGZl;)boUW}F z9nQ>C=cDyn{iP+aDC~0HV!|~bSkKqNoVLa)-!KWKsglocVqGel&x~uVp0`;yvv#IU zZ4lizv+f>sU2L zj!Z?*UvudB>OOHx_(gr%hug(3=9;&hG8SZ1xwu~{dLHFa&%V}AU8YISUXZ)r3+)Nk-X{(PA6 zjnz(WCf@WlZFzGLpN-Abb?MUmj3tI3-;LE=p2qsV##YzYjHTZziXQ8^>NrX@s882H zkB#-)`4z*rK7+2Ij$?BAG5E}J&}y50uc%MgPuEiG+?M|M`VC>eNmI+w5CYWDrbTTq zr^YLFp!bQQF(yvO(7ze9Pw+cKkM*3@>bG&9K9!XsUAmNTRoI~dt0-Kkw+d6!719~% zjL~^ycWGH_7ZgdQwAx{tvf7dTt3+DU)`qsYgqww|LcS)W(R9A<(oU*6v~A_~>e02b zw9qQ(*se{unH?%CDJ~jY6KOtWQnGetoi}yvoGWH6oPW){{d;!n{N;sD;4IzFi8bax>{isaB&lOVB5aP%9YoaolX#C3@ zd9Xs9bYEE(l~Y+mjStHhoMC@Oh4|C*-G zWlvfEWexgM(coWWx}J5^be(hkGlKr24e{sY@t==Bn?DdgGf(^ldHfeP>33w7==Gee z9b4l~oia&g&8$nxm0}fGmStPq09G@r$O>B}REi~cj)0o zWFO-4X~;e4Z#3k6Q;yvW_JjSQH*<8c2QbG2>l0|j3H0N*te+m1KGc29xZaU|^^V;i zI{?s(-9h9WoJ!b3utUMujEOlI4j~4;*glN8X7pki?m1|=4qC2*mg}J9Ix!19czf6j z4uT_L0?dGUa63E&Z@}kJj2>J8d&3|Y1*gG9a4p;q&%-;g4vyxWqBG)h4CgU|@s5R& z%xM&w+;PlhG;^$h<6%s_-jtj1_3ew|kC#2iz$U zxl8!J1~lZmv3+@~^+QAMkA{2?#{ctPhQV43rgVB()dNFP2 z#qMM9I6MJQrqGL-i?0{Q9Q$c_2A+lI0KHhA_Z(RcFTjh?STBx9Rxc*ctMD427u#>Z zo7`I~$bnug=*99j{n3lX*NbU?7v2-}V)y|6O85|by_or-7rW@iE_$*1Su$d;rY%P= zmVjPtuO;6)SPx&rH;mbUl}8h9Rxh6Ihz-r45W;|7>=s88QUV#h*lvz)903Q)AxaES zPyc&uOX$e@HbLa=G79C&f`UM*->eq2|%i{Wt=dA0JPgmAF2A!|w)Z_68qk7DTakiwt z$g+oxD%!`CVBPp~t(m$RdrRrcCZCR{=WW)`tY5yl>E7wzLRviiMF;gYiZ2pzbA22K zi-~9X{Jp=}n#JD~EaO&P+20S{hh-Ve{(Ki*nN-<(MeB`<*^EZcZ$H?~Zr`4G6C=#E zs^K~pL%#08c#Uc5xuAZ%pMU6c(|P>Z%KzJ%nRkz|x?koRY-%k`TT}a*8=rfv>U*H3 zsgC$^V@+7_nXb1R(DvY5wZ5ga=NP$6Zhw6<$GYA+2YZK_AI}ABEgr8U2ZA(E&|3phY7@Z`GoGP5URV UMeEbae{^AZcm5A)(YJK?Hy~E=RR910 diff --git a/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini b/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini deleted file mode 100644 index dbb09688542b8..0000000000000 --- a/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini +++ /dev/null @@ -1,529 +0,0 @@ -# This file allows user to override the factory - -# defaults for the WLAN Driver - - -# Enable IMPS or not -gEnableImps=1 - -# Enable/Disable Idle Scan - -gEnableIdleScan=0 - - -# Enable/Disable vsta based on MAX Assoc limit -gEnableVSTASupport=1 - - -# Increase sleep duration (seconds) during IMPS -# 0 implies no periodic wake up from IMPS. Periodic wakeup is -# unnecessary if Idle Scan is disabled. -gImpsModSleepTime=0 - - -# Enable BMPS or not -gEnableBmps=1 - -# Enable suspend or not - -# 1: Enable standby, 2: Enable Deep sleep, 3: Enable Mcast/Bcast Filter - -gEnableSuspend=3 - -# Phy Mode (auto, b, g, n, etc) -# Valid values are 0-9, with 0 = Auto, 4 = 11n, 9 = 11ac -gDot11Mode=0 - - -# CSR Roaming Enable(1) Disable(0) - -gRoamingTime=0 - - -# Assigned MAC Addresses - This will be used until NV items are in place - -# Each byte of MAC address is represented in Hex format as XX - -Intf0MacAddress=000AF58989FF -Intf1MacAddress=000AF58989FE -Intf2MacAddress=000AF58989FD - -Intf3MacAddress=000AF58989FC - - -# UAPSD service interval for VO,VI, BE, BK traffic - -InfraUapsdVoSrvIntv=0 - -InfraUapsdViSrvIntv=0 - -InfraUapsdBeSrvIntv=0 - -InfraUapsdBkSrvIntv=0 - -# Flag to allow STA send AddTspec even when ACM is Off -gAddTSWhenACMIsOff=1 - -# Make 1x1 the default antenna configuration - -gNumRxAnt=1 - - -# Beacon filtering frequency (unit in beacon intervals) - -gNthBeaconFilter=50 - - -# Enable WAPI or not - -# WAPIIsEnabled=0 - - -# Flags to filter Mcast abd Bcast RX packets. - -# Value 0: No filtering, 1: Filter all Multicast. - -# 2: Filter all Broadcast. 3: Filter all Mcast abd Bcast - -McastBcastFilter=3 - - -#Flag to enable HostARPOffload feature or not - -hostArpOffload=1 - - -#Flag to enable HostNSOffload feature or not - -hostNSOffload=0 - -#SoftAP Related Parameters - -# AP MAc addr - -gAPMacAddr=000AF589dcab - - -# 802.11n Protection flag - -gEnableApProt=1 - - -#Enable OBSS protection - -gEnableApOBSSProt=1 - - -#Enable/Disable UAPSD for SoftAP - -gEnableApUapsd=1 - - -# Fixed Rate - -gFixedRate=0 - - -# Maximum Tx power - -# gTxPowerCap=30 - - -# Fragmentation Threshold - -# gFragmentationThreshold=2346 - - -# RTS threshold - -RTSThreshold=2347 - - -# Intra-BSS forward - -gDisableIntraBssFwd=0 - - -# WMM Enable/Disable - -WmmIsEnabled=0 - - -# 802.11d support - -g11dSupportEnabled=1 - -# 802.11h support - -g11hSupportEnabled=1 - -# ESE Support and fast transition -EseEnabled=0 -ImplicitQosIsEnabled=0 -gNeighborScanTimerPeriod=200 - -gNeighborLookupThreshold=76 -gNeighborReassocThreshold=81 - -gNeighborScanChannelMinTime=20 -gNeighborScanChannelMaxTime=30 -gMaxNeighborReqTries=3 - -# Legacy (non-ESE, non-802.11r) Fast Roaming Support -# To enable, set FastRoamEnabled=1 -# To disable, set FastRoamEnabled=0 -FastRoamEnabled=1 - -#Check if the AP to which we are roaming is better than current AP in terms of RSSI. -#Checking is disabled if set to Zero.Otherwise it will use this value as to how better -#the RSSI of the new/roamable AP should be for roaming -RoamRssiDiff=3 - -# If the RSSI of any available candidate is better than currently associated -# AP by at least gImmediateRoamRssiDiff, then being to roam immediately (without -# registering for reassoc threshold). -# NOTE: Value of 0 means that we would register for reassoc threshold. -gImmediateRoamRssiDiff=10 - -# To enable, set gRoamIntraBand=1 (Roaming within band) -# To disable, set gRoamIntraBand=0 (Roaming across band) - -gRoamIntraBand=0 - -#SAP Country code - -# Default Country Code is 2 bytes, 3rd byte is optional indoor or out door. - -# Example - -# US Indoor, USI - -# Korea Outdoor, KRO - -# Japan without optional byte, JP - -# France without optional byte, FR - -#gAPCntryCode=USI - - -#Short Guard Interval Enable/disable - -gShortGI20Mhz=1 - -gShortGI40Mhz=1 - - -#Auto Shutdown Value in seconds. A value of 0 means Auto shutoff is disabled - -gAPAutoShutOff=0 - - -# SAP auto channel selection configuration - -# 0 = disable auto channel selection - -# 1 = enable auto channel selection, channel provided by supplicant will be ignored - -gApAutoChannelSelection=1 - - -# Listen Energy Detect Mode Configuration - -# Valid values 0-128 - -# 128 means disable Energy Detect feature - -# 0-9 are threshold code and 7 is recommended value from system if feature is to be enabled. - -# 10-128 are reserved. - -# The EDET threshold mapping is as follows in 3dB step: - -# 0 = -60 dBm - -# 1 = -63 dBm - -# 2 = -66 dBm - -# ... - -# 7 = -81 dBm - -# 8 = -84 dBm - -# 9 = -87 dBm - -# Note: Any of these settings are valid. Setting 0 would yield the highest power saving (in a noisy environment) at the cost of more range. The range impact is approximately #calculated as: - -# - -# Range Loss (dB) = EDET threshold level (dBm) + 97 dBm. - -# - -gEnablePhyAgcListenMode=128 - - -#Preferred channel to start BT AMP AP mode (0 means, any channel) - -BtAmpPreferredChannel=0 - - -#Preferred band (both or 2.4 only or 5 only) - -BandCapability=0 - - -#Beacon Early Termination (1 = enable the BET feature, 0 = disable) - -enableBeaconEarlyTermination=0 - -beaconEarlyTerminationWakeInterval=3 - - -#Bluetooth Alternate Mac Phy (1 = enable the BT AMP feature, 0 = disable) - -gEnableBtAmp=0 - - -#SOFTAP Channel Range selection - -gAPChannelSelectStartChannel=1 - -gAPChannelSelectEndChannel=11 - - -#SOFTAP Channel Range selection Operating band - -# 0:2.4GHZ 1: LOW-5GHZ 2:MID-5GHZ 3:HIGH-5GHZ 4: 4.9HZ BAND 5: 5GHZ BAND - -gAPChannelSelectOperatingBand=0 - - -#Channel Bonding -gChannelBondingMode5GHz=1 -gChannelBondingMode24GHz=1 - -#Enable Keep alive with non-zero period value - -#gStaKeepAlivePeriod = 30 - -#Say gGoKeepAlivePeriod(5 seconds) and gGoLinkMonitorPeriod(10 seconds). -#For every 10 seconds DUT send Qos Null frame(i.e., Keep Alive frame if link is idle for last 10 seconds.) -#For both active and power save clients. - -#Power save clients: DUT set TIM bit from 10th second onwards and till client honors TIM bit. -#If doesn't honor for 5 seconds then DUT remove client. - -#Active clients: DUT send Qos Null frame for 10th seconds onwards if it is not success still we try on -#11th second if not tries on 12th and so on till 15th second. Hence before disconnection DUT will send 5 NULL frames. -#Hence in any case DUT will detect client got removed in (10+5) seconds. i.e., (gGoKeepAlivePeriod + gGoLinkMonitorPeriod).. - -#gGoLinkMonitorPeriod/ gApLinkMonitorPeriod is period where link is idle and it is period -#where we send NULL frame. - -#gApLinkMonitorPeriod = 10 - -#gGoLinkMonitorPeriod = 10 - -#gGoKeepAlivePeriod/gApKeepAlivePeriod is time to spend to check whether frame are succeed to send or not. -#Hence total effective detection time is gGoLinkMonitorPeriod+ gGoKeepAlivePeriod/gApLinkMonitorPeriod+ gApKeepAlivePeriod. - - -gGoKeepAlivePeriod=30 - -gApKeepAlivePeriod=10 - - -#If set will start with active scan after driver load, otherwise will start with - -#passive scan to find out the domain - -gEnableBypass11d=1 - - -#If set to 0, will not scan DFS channels - -gEnableDFSChnlScan=1 - - -gVhtChannelWidth=2 -gEnableLogp=1 - - -# Enable Automatic Tx Power control - -gEnableAutomaticTxPowerControl=0 - -# 0 for OLPC 1 for CLPC and SCPC -gEnableCloseLoop=1 - -#Data Inactivity Timeout when in powersave (in ms) -gDataInactivityTimeout=200 - -# VHT Tx/Rx MCS values -# Valid values are 0,1,2. If commented out, the default value is 0. -# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 -gVhtRxMCS=2 -gVhtTxMCS=2 - -# Enable CRDA regulatory support by settings default country code -#gCrdaDefaultCountryCode=TW - -# Scan Timing Parameters -# gPassiveMaxChannelTime=110 -# gPassiveMinChannelTime=60 -# gActiveMaxChannelTime=40 -# gActiveMinChannelTime=20 - -#If set to 0, MCC is not allowed. -gEnableMCCMode=1 - -# 1=enable STBC; 0=disable STBC -gEnableRXSTBC=1 - -# Enable Active mode offload -gEnableActiveModeOffload=1 - -#Enable Scan Results Aging based on timer -#Timer value is in seconds -#If Set to 0 it will not enable the feature -gScanAgingTime=0 - -#Enable Power saving mechanism Based on Android Framework -#If set to 0 Driver internally control the Power saving mechanism -#If set to 1 Android Framwrok control the Power saving mechanism -isAndroidPsEn=0 - -#disable LDPC in STA mode if the AP is TXBF capable -gDisableLDPCWithTxbfAP=1 - -#Enable thermal mitigation -gThermalMitigationEnable=1 - -gEnableFastRoamInConcurrency=1 - -#List of Country codes for which 11ac needs to be disabled -#Each country code must be delimited by comma(,) -gListOfNon11acCountryCode=RU,UA,ZA - -#Maxium Channel time in msec -gMaxMediumTime = 5480 - -# 802.11K support -gRrmEnable=1 -gRrmOperChanMax=8 -gRrmNonOperChanMax=8 -gRrmRandIntvl=100 - -#Scan offload -gEnableDirectedScanOffload=0 - -#FlexConnect Power Factor -#Default is set to 0 (disable) -gFlexConnectPowerFactor=0 - -#SAP/P2P-GO mode traffic monitor -gEnableTrafficMonitor=1 -gTrafficIdleTimeout=3000 - -#Disable/Enable Strict FCC Regulatory -# 0 to disable, 1 to enable -gEnableStrictRegulatoryForFCC=1 - -#Enable/Disable Modulated DTIM feature -gEnableModulatedDTIM=3 - -#max LI value for modulated DTIM -gMaxLIModulatedDTIM=3 - -#Enable/Disable Link Layer Statistics Feature -gEnableLLStats=1 - -#Enable/Disable EXTScan Feature -gEnableEXTScan=1 - -#Enable/Disable TDLS Feature -gEnableTDLSSupport=1 - -#Enable/Disable TDLS Implicit Trigger -gEnableTDLSImplicitTrigger=0 - -#Enable/Disable TDLS Buffer Sta -gEnableTDLSBufferSta=1 - -#Enable/Disable RTS-CTS for HT,VHT -#Bit mask value to enable RTS/CTS for different modes -#For 2.4 GHz, HT20 - 0x0001 i.e 1, for 2.4 GHz, HT40 - 0x0002 i.e 2 -#For 2.4 GHz, VHT20 - 0x0004 i.e 4, for 2.4 GHz, VHT40 - 0x0008 i.e 8 -#For 5 GHz, HT20 - 0x0100 i.e 256, for 5 GHz, HT40 - 0x0200 i.e 512 -#For 5 GHz, VHT20 - 0x0400 i.e 1024, for 5 GHz, VHT40 - 0x0800 i.e 2048 -#For 5 GHz, VHT80 - 0x1000 i.e 4096 -#Can be enabled for multiple modes -#For enabling in both HT20 and HT40 of 2.4 GHz - 0x0003 i.e 3 -#Default is set to 0 (disable) -gEnableRtsCtsHtVht=0 - -#Enable delACK -gEnableDelAck=1 - -#Compute interval for delack -gTcpDelAckComputeInterval=2000 - -#Delack set higher limit -gTcpDelAckThresholdHigh=17000 - -#Delack set lower limit -gTcpDelAckThresholdLow=12000 - -# Enable or Disable DHCP Server offload -# 1=Enable, 0=Disable (default) -gDHCPServerOffloadEnable=0 - -# Set max number of DHCP Clients -# Its value could not be greater than 2(default) -#gDHCPMaxNumClients=2 - -# Set DHCP server IP -# 4th field could not be greater than 99, that is xxx.xxx.xxx.0 ~ xxx.xxx.xxx.99 -# 1st field could not be within the range of 224 ~ 239 (multicast IP address) -# 192.168.1.2(default) -#gDHCPServerIP=192.168.1.2 - -# Set DHCP pool start Lsb -# min 100 (default) -# max 255 -gDHCPStartLsb=100 - -# mDNS enable -gMDNSOffloadEnable=1 -# mDNS FQDN query -gMDNSFqdn="_GoProRemote._tcp.local" -# mDNS UFQDN query -gMDNSUniqueFqdn="service._GoProRemote._tcp.local" -# mDNS response typeA -gMDNSResponseTypeA="goprobp-D89685121212.local" -# mDNS response typeAIpv4Addr -gMDNSResponseTypeAIpv4Addr=0xc0a80102 -# mDNS response typeTXT -gMDNSResponseTypeTXT="GoProBP-D89685121212._GoProRemote._tcp.local" -# mDNS response typeTXTContent -gMDNSResponseTypeTXTContent="Device=HERO 3+-BAWA Model=BAWA Version=HD3.11.02.00 Wifi Version=4.0.36.0 Protocol Version=2" -# mDNS response typePTR -gMDNSResponseTypePTR="_GoProRemote._tcp.local" -# mDNS response typePTRDomainName -gMDNSResponseTypePTRDomainName="GoProBP-D89685121212._GoProRemote._tcp.local" -# mDNS response typeSRV -gMDNSResponseTypeSRV="GoProBP-D89685121212._GoProRemote._tcp.local" -# mDNS response typeSRVTarget -gMDNSResponseTypeSRVTarget="goprobp-D89685121212.local" -# mDNS response typeSRVPriority -gMDNSResponseTypeSRVPriority=0 -# mDNS response typeSRVWeight -gMDNSResponseTypeSRVWeight=0 - -END - -# Note: Configuration parser would not read anything past the END marker - diff --git a/drivers/staging/prima/firmware_bin/WCNSS_qcom_wlan_nv.bin b/drivers/staging/prima/firmware_bin/WCNSS_qcom_wlan_nv.bin deleted file mode 100644 index 14ce361cba9e6d803bc9656b1f97645642f4b039..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29816 zcmeHQS$CDy89pZ=As|D-5F%iJKu`f?lv1QMBBCN9q9URqDk9E;3Wz~(df{b%M1Mkm zf>mnO($&`0i(d2x^vXMjwdni2!`|=S-*8TZgiy};*5RBlXUO;LcY5AolPg!QTxm3# zUCm}A-sE`~|DZemxc=FuuFEqUjjH=w^jd!ZuD8)RL-%=f&tJp2f4z^+^Sgca-#x|G z@ZM|rdfD~icl<#y{GJ}`uJ1fuBX0S7^6Q+)`+i5VY3KX)&uH&`6Zt+tQ~s~5)lOO; zf46J3*YViub^8n+vDUcz&riqK$LJbyv+FdBxK`*i?!aO1gZ|ok@o1O~FJ50%@gBb} z?Y<8>2AwGTo&NjmeS)U^U;7TjXpe@$UdN-ohR3qk?PvZP{O70R>n20HPQ!?6?Z{eW zZgR6V!lV5RkEZ9-{q>tk*5%fI?S2Y!F`4&kcctxp(_~_~7T?`mQaA>igNMeXU$%iDMZbx6-GV(GhPrlPicn>pZ*eE5I@n z$@za5HW%iXW;*5dN1w}ES+AfIdid|-=kXiuyW}zX7Q6}H)VWQ&6{ye^$aaCsP<>0a zU+JPqKnHu4;7dAwW!lO5YA>kSUv_l$(;@a9qEOd>9)%d>b){=qkB+Wft!Sp*=gTyu z*Hr=|AIw>Lra&h zSUIwK^!7XMT)*M&jhnV?-M0N#JAS?M-d(@>?b!YI?|xvq149^L=gfdh{p zeB#idC!c!y>BEPgIdbILqeq{6?)ev9ICkvC7mpu*>7|!ne&v-DufBTn_bBxLan=8)p#KH=m*a=} ztNusvpG(yLdgwpoKd_L@KkC1iKg?hCU*w?L|Gk;~z5PFh0O0gL;D5P7{&4@~|4sjO0RsG~*MG==4&#UaUo~R>&&5B% zuknupppSnMe=2{(KW_jM{>tK?DgeTt#=j}{|ImMne}tdnKm7m3V*JbFzr;U@|33a9 z{%7zt{0ID%{(mYIAhUnrKZyTg0E(Xi02=`FpTq%505}*3km!HC{4@Ro{a5}|l>a2t zpUnS}10eq={BL*#2SD&2*8h99EC2HZC=x(Y0CE6M0RjQ64uA#zcir*#a{Lqir}i)W zPy8R^UkHE?J*@Um@n7U$hCktd;J=anW${1ve;22o|HA)8`}h3M@qg3*g#VZDUl8EH z|4#(|AMuO$o%sj;6WrfqtADEh&6^y5;tadGduH~{o-=oT|G>gUiwB2pB~CcJV&$rl z)oVuAQeH@z0lNl}<83ex&JW2#C`8^j#!2D>d-gm?c@hkTA|<#2l0`NbN*IwbQOFe1 zOj#4>jYOP?IdSep$|LGS0fYi5MNrZqN+KzXL>ftkM2-}(lyV8BlOPn5QL0lVTE%%K zQ7dq(K&~jda&-A5ft;Ll@OR|j(f^M9cl=++|KE)9uh})Dcjhc601Fl_9$Yd+Igt>6 zV*E#W0QFH6h=n5O@t+a}t`#8u6I-TwX&U}fHKnp?2>(<&LHy_PX?gso@Q?VPgnub0 zprjx<6{^Z8DD9er_vYkqr8}kJUNpExMj|~`2!2e z9022o0&LmJ<*`ivqx|Cn2>*@vxn+{$ck~y@Bj8ulUr~R8PswDF{W|$a_AA9D@ZXE| z_%#8bf`HgRDZp)17BmB}1Yq+PN&wjYQ6OLkKnVbvM5_N0e^dZ5f5VTiQ9=Gi^H2DH ziTs89!}?p9zbe4R8vgI>9|6$$KTUwV{@;W42*F2zi1QzT-&+31zf_|E;A_YcHfK#T*S2txRS6HM_l3xXHq1qfbX;v^`;uM|jJV95fA3Ml_+fnONVEvf*ZKp6*+ z1#l!tNg#W{Tmu3PVhw;1Fbz~5m>R)^tw4ETQ3r$sfdmE}2v$HYAl3Nn%oyN2mOtT7 z^`DAhDF+Y*;2;>H02CmjfzAS=38)67aggd@6}SYy(4d$Gngzr}AX$Kr3Fcfte1N3_k_rYg zM3vx56G)h_1i}yrIStVHB2<7=z}Xq_Qwm59uz!FSKpkLG1z)!w9DuWcSOyOsfXm=1 ze#rz=7oZxzCLp;GGXYuv&IO9OP-X&J3eU)3i3+d_j4pr{AVZv6E%Y&|Y5%2@F6eKmot0f1CPWFaA&lG5F5>+p_;T)%G73AY{Q(21prD z;DA;Mq6P4^AS^&^g;^$0N`kxx3<^-`0751lLV!9z3xTP?^D`(wWdKM5VC2Ao0)$Rr z2!SyI?3YX^^a2A7cEu1!0(>r1T!8X?FqlA=3YiDs6&TMEr{@#^&;;WM$W`!!0y+=K zg+L?$E(=f&5E8+(7~o=HwGXUt0+j{PDlbs61XKx1@#be;Apn{O1O~_lhXJ`JEeL0VR>HN2hzjfwc+nImt%)e^YzAymC6W~)i0G-6YMt5ia^`@SG_1eJI z|IYkhXZ}%&-<|o-|I7K;f6?u`fBxg|a=RqAZ~uDv^4~6BzWmKMU;pK+OJDx!^Upv3 z;?kurz6x*Uw|z_Rz?;7Q`l~-*`hwo`<)tq#c@J`9KiBRb*FL%SO?!fFTS19$#r!k# z?X#8Xz7{=o1fVbhLWM6I0Qm*; z&(!^~;-A*Owf1lL*RM}{zd3%b`f%BgcM9`XIhy~P!2FZIC;Zg+;vH17iCDH#aMdqP zKosDk>`VAD{*}V#&85@=#{fW$j#~GNn;&8RE3JE!^uDd}LHN1s>*l{))gR6OAbwZ# zr|!SVpZi|E+);vG$~|!cq;C9;%3eDCuJb=K08xXV3}7Y||K`r89dXkAx7zRM=#u-y-d`BT%2 zwm)dalk8vgANWcCspN_64;X==y1z633jFo`Z|FY;;L-hEjQOXf%S-TM_G1h7e{A2e zV+ZD+iuj}a@t*~V12Fs~eyjII|Htl+;G6lw`c?cV8U86qpL#w(Pq~!9_vp_sdNO~u z{C-;|kz2N`aFn@#Z>)na;gY}E> zb^6Zavw0GW+Hp#3k+@1O$Q{GsMI?UMWL*x1-^y6xGsM_NA` z16TzP&>F}huo18lWHAsra11(d{5TDP(T$bh1p2-wPr?LFonjq$qeKUiHBkSbEP+fw z5&Sy;->~+#&Oc!b)N)wB%8`*ZYu2vS?iXCZCMo^P9w_4g>I5_h&~CXx>rW@ZYzoqk zfO!(&qd?aAg%Q{cG`j$&1zhvC2w2?y1pn6(zqWt1{aH|eJ6-pC+qP}n;RJXHvZw)j zGcN!YfEgS*L}3scC&>>?Tm`%z5I67+yMg!A3Bm^kGk^-H55V?nW&kzu&&|J}{hf@! z3kQqc8yUemDl20fgos;kWKTc>tRKsir~F{RRBc`%hbc zH};0Cj;x1K|R_0qmzR$Ucw_z=(j&|HMEj3IHEyOejV|BLeV(o(IVEi^xA`0nmRL z0_G9W`uIosuk$}}fQSHz0wnEUKmI^0z+52HAQ*tu%asQb5%ffWsDSqX()~^>01I#& z17JxeP(lTa2?`Y`2?N0cumfm0|3fKIAGW~I2>gOYnEzSoB0x|8n*WIkU}NA$17rl$ z?SmyEoG{_Q1=s_?1n@s7kqZdpAL0U>2?Q#vTVdN)fv~?ml;~0-g=M=3HP&7z`!=E+{_0HUWVI%KxxYkKa*XCw~k; z69ZuRy9rR4|3VrZLZDE9BmxvjK#)H|0K33+{)0n6m;tT9&s11bAsB#nff@sI{NwfW zUt#_ynSV0|r1A#^6#b98KrjFa4k+_Kj6aeMQ3?oLIC21||DFaFJ%D$CnhYel zfH(lp0bu`30ot~I9{+F*Fb+Tl3Mkv)w`dw9d649RSOBnK4FPNbk_kr-=oTPo0B;2- zcz`Mkplq<{0Yn4x8PIdN2dLG52>_G=@E#~kfbs-5A|T2jegRAaBm`;*&=?33L?OWC z0jvTX1X%?l4Gb%g=m41j@u2c3AUaU91W*D?hLH>K3RoCyG5^92Q1^i71Tf}bxC&q% zfH@G4z_A7p2@E4}90N2BKru*?K`Dl43@9mw6?jm=35GB@f%zBb17#KL6}TJBr^NztKLKKgu`RPw`FhGo5F@WCb?S-*7wM zbG`?Emugw#T&u4b!5fC$e`!3_9BPg Date: Wed, 2 Sep 2015 12:47:42 -0400 Subject: [PATCH 252/508] staging: prima: Add Kconfig entry for TDLS Change-Id: I670c8d7eb24de9f431d8dd89a8694fa216f4f9ff --- drivers/staging/prima/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/staging/prima/Kconfig b/drivers/staging/prima/Kconfig index 9306175a22900..e3fcf736961b0 100644 --- a/drivers/staging/prima/Kconfig +++ b/drivers/staging/prima/Kconfig @@ -53,4 +53,8 @@ config WLAN_OFFLOAD_PACKETS bool "Enable offload packets feature" default n +config QCOM_TDLS + bool "Enable TDLS feature" + default n + endif # PRIMA_WLAN || PRONTO_WLAN From 861ce115965ca92e8ca7fbb0fbc7d6eb1c1ed9a3 Mon Sep 17 00:00:00 2001 From: Gabriele M Date: Tue, 18 Aug 2015 23:49:13 +0200 Subject: [PATCH 253/508] staging: prima: Fix non-debug build and switch to it Enable the forward declaration of debug functions in non-debug builds and disable a piece of code used only to print some info. -Wno-unused-variable is now required because of all the variables used in debug functions that aren't left out in non-debug builds. Change-Id: I7069f8859e4965ee82ce65c29c35349c887fd673 --- drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c | 2 ++ drivers/staging/prima/CORE/MAC/inc/macTrace.h | 5 ----- drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c | 2 +- drivers/staging/prima/CORE/SME/inc/smsDebug.h | 5 +++++ drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c | 6 ++++-- drivers/staging/prima/CORE/VOSS/inc/vos_trace.h | 1 + drivers/staging/prima/Kbuild | 4 ++-- 7 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c index 9459131730419..97101c2a79b17 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c @@ -7360,6 +7360,7 @@ static int __iw_get_char_setnone(struct net_device *dev, *And currently it only checks P2P_CLIENT adapter. *P2P_DEVICE and P2P_GO have not been added as of now. */ +#ifdef TRACE_RECORD case WE_GET_STATES: { int buf = 0, len = 0; @@ -7496,6 +7497,7 @@ static int __iw_get_char_setnone(struct net_device *dev, wrqu->data.length = strlen(extra)+1; break; } +#endif case WE_GET_CFG: { diff --git a/drivers/staging/prima/CORE/MAC/inc/macTrace.h b/drivers/staging/prima/CORE/MAC/inc/macTrace.h index 2ee4c7fc02cb6..a1c99d31a14c1 100644 --- a/drivers/staging/prima/CORE/MAC/inc/macTrace.h +++ b/drivers/staging/prima/CORE/MAC/inc/macTrace.h @@ -43,9 +43,6 @@ #include "aniGlobal.h" - -#ifdef TRACE_RECORD - #define MAC_TRACE_GET_MODULE_ID(data) ((data >> 8) & 0xff) #define MAC_TRACE_GET_MSG_ID(data) (data & 0xffff) @@ -80,5 +77,3 @@ tANI_U8* macTraceGetTLState(tANI_U16 tlState); #endif -#endif - diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c index d8137ff06be1d..5c7e8e8634910 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c @@ -1076,8 +1076,8 @@ tSirRetStatus peOpen(tpAniSirGlobal pMac, tMacOpenParameters *pMacOpenParam) */ #ifdef LIM_TRACE_RECORD MTRACE(limTraceInit(pMac)); -#endif lim_register_debug_callback(); +#endif return eSIR_SUCCESS; } diff --git a/drivers/staging/prima/CORE/SME/inc/smsDebug.h b/drivers/staging/prima/CORE/SME/inc/smsDebug.h index ec5ae58af8df5..85d495b12c163 100644 --- a/drivers/staging/prima/CORE/SME/inc/smsDebug.h +++ b/drivers/staging/prima/CORE/SME/inc/smsDebug.h @@ -45,10 +45,15 @@ #define __printf(a,b) #endif +#ifdef WLAN_DEBUG void __printf(3,4) smsLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString, ...); void __printf(3,4) pmcLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString, ...); +#else +#define smsLog(arg...) +#define pmcLog(arg...) +#endif #endif // __SMS_DEBUG_H__ diff --git a/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c b/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c index fd5f1db43ae95..cc0cc700652ea 100644 --- a/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c +++ b/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c @@ -1540,7 +1540,9 @@ eHalStatus sme_Open(tHalHandle hHal) sme_p2pOpen(pMac); smeTraceInit(pMac); +#ifdef SME_TRACE_RECORD sme_register_debug_callback(); +#endif }while (0); @@ -6937,6 +6939,7 @@ VOS_STATUS sme_DbgWriteMemory(tHalHandle hHal, v_U32_t memAddr, v_U8_t *pBuf, v_ } +#ifdef WLAN_DEBUG void pmcLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString, ...) { VOS_TRACE_LEVEL vosDebugLevel; @@ -6957,7 +6960,6 @@ void pmcLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString, ...) void smsLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString,...) { -#ifdef WLAN_DEBUG // Verify against current log level if ( loglevel > pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE( SIR_SMS_MODULE_ID )] ) return; @@ -6971,8 +6973,8 @@ void smsLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString,...) va_end( marker ); /* Reset variable arguments. */ } -#endif } +#endif /* --------------------------------------------------------------------------- \fn sme_GetWcnssWlanCompiledVersion diff --git a/drivers/staging/prima/CORE/VOSS/inc/vos_trace.h b/drivers/staging/prima/CORE/VOSS/inc/vos_trace.h index 538f58d022580..a0d10696c9673 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/vos_trace.h +++ b/drivers/staging/prima/CORE/VOSS/inc/vos_trace.h @@ -113,6 +113,7 @@ typedef enum #else #define MTRACE(p) { } +#define CASE_RETURN_STRING( str ) { } #endif diff --git a/drivers/staging/prima/Kbuild b/drivers/staging/prima/Kbuild index baadf2982f169..1db36a6dd78fe 100644 --- a/drivers/staging/prima/Kbuild +++ b/drivers/staging/prima/Kbuild @@ -67,7 +67,7 @@ CONFIG_QCOM_ESE_UPLOAD := n # Feature flags which are not (currently) configurable via Kconfig #Whether to build debug version -BUILD_DEBUG_VERSION := 1 +BUILD_DEBUG_VERSION := 0 #Enable this flag to build driver in diag version BUILD_DIAG_VERSION := 1 @@ -720,7 +720,7 @@ CDEFINES += -DEXISTS_MSM_SMSM endif # Fix build for GCC 4.7 -EXTRA_CFLAGS += -Wno-maybe-uninitialized -Wno-unused-function +EXTRA_CFLAGS += -Wno-maybe-uninitialized -Wno-unused-function -Wno-unused-variable ifeq ($(CONFIG_WLAN_OFFLOAD_PACKETS),y) CDEFINES += -DWLAN_FEATURE_OFFLOAD_PACKETS From 4efc8793175dbe1ab3e9f2e5bb1a76a3b8e2cc69 Mon Sep 17 00:00:00 2001 From: Jongrak Kwon Date: Mon, 6 Apr 2015 11:31:40 -0700 Subject: [PATCH 254/508] staging: include the prima wlan driver Change-Id: I62f544f49a724ccece699290b51717765975c706 Signed-off-by: Jongrak Kwon --- drivers/staging/Kconfig | 2 ++ drivers/staging/Makefile | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 4690ae9a267f3..10f93517b08f0 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -108,4 +108,6 @@ source "drivers/staging/skein/Kconfig" source "drivers/staging/unisys/Kconfig" +source "drivers/staging/prima/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 53503056d747e..49faaa0ee46cb 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -45,3 +45,4 @@ obj-$(CONFIG_MTD_SPINAND_MT29F) += mt29f_spinand/ obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/ obj-$(CONFIG_CRYPTO_SKEIN) += skein/ obj-$(CONFIG_UNISYSSPAR) += unisys/ +obj-$(CONFIG_PRONTO_WLAN) += prima/ From 52ff38acbd7856dc37a220ece5ee714b61e04941 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Fri, 23 Mar 2018 21:00:23 +0530 Subject: [PATCH 255/508] arch: arm64: configs: Add initial mido defconfig --- arch/arm64/configs/mido_defconfig | 4634 +++++++++++++++++++++++++++++ 1 file changed, 4634 insertions(+) create mode 100644 arch/arm64/configs/mido_defconfig diff --git a/arch/arm64/configs/mido_defconfig b/arch/arm64/configs/mido_defconfig new file mode 100644 index 0000000000000..d644b8cf14982 --- /dev/null +++ b/arch/arm64/configs/mido_defconfig @@ -0,0 +1,4634 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm64 3.18.71 Kernel Configuration +# +CONFIG_ARM64=y +CONFIG_64BIT=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_MMU=y +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_HAVE_GENERIC_RCU_GUP=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_ARM64_DMA_USE_IOMMU=y +CONFIG_ARM64_DMA_IOMMU_ALIGNMENT=8 +CONFIG_SMP=y +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=3 +# CONFIG_MSM_GVM_QUIN is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="-perf" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +# CONFIG_FHANDLE is not set +# CONFIG_USELIB is not set +CONFIG_AUDIT=y +CONFIG_HAVE_ARCH_AUDITSYSCALL=y +CONFIG_AUDITSYSCALL=y +CONFIG_AUDIT_WATCH=y +CONFIG_AUDIT_TREE=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_HANDLE_DOMAIN_IRQ=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +# CONFIG_TICK_CPU_ACCOUNTING is not set +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +CONFIG_IRQ_TIME_ACCOUNTING=y +# CONFIG_SCHED_WALT is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set + +# +# RCU Subsystem +# +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +# CONFIG_TASKS_RCU is not set +CONFIG_RCU_STALL_COMMON=y +# CONFIG_RCU_USER_QS is not set +CONFIG_RCU_FANOUT=64 +CONFIG_RCU_FANOUT_LEAF=16 +# CONFIG_RCU_FANOUT_EXACT is not set +CONFIG_RCU_FAST_NO_HZ=y +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_BOOST is not set +CONFIG_RCU_NOCB_CPU=y +# CONFIG_RCU_NOCB_CPU_NONE is not set +# CONFIG_RCU_NOCB_CPU_ZERO is not set +CONFIG_RCU_NOCB_CPU_ALL=y +CONFIG_BUILD_BIN2C=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_CONSOLE_FLUSH_ON_HOTPLUG is not set +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_FREEZER=y +# CONFIG_CGROUP_DEVICE is not set +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_MEMCG_SWAP_ENABLED=y +# CONFIG_MEMCG_KMEM is not set +# CONFIG_CGROUP_PERF is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_RT_GROUP_SCHED=y +# CONFIG_BLK_CGROUP is not set +CONFIG_SCHED_HMP=y +# CONFIG_SCHED_HMP_CSTATE_AWARE is not set +# CONFIG_SCHED_CORE_CTL is not set +# CONFIG_SCHED_QHMP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SCHED_TUNE is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_UID16=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +# CONFIG_BPF_SYSCALL is not set +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_ADVISE_SYSCALLS=y +CONFIG_PCI_QUIRKS=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLUB_CPU_PARTIAL=y +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y +# CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_RCU_TABLE_FREE=y +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP_FILTER=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR_NONE is not set +# CONFIG_CC_STACKPROTECTOR_REGULAR is not set +CONFIG_CC_STACKPROTECTOR_STRONG=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_CMDLINE_PARSER is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_CMDLINE_PARTITION is not set +CONFIG_BLOCK_COMPAT=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_TEST is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_ASN1=y +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# Platform selection +# +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_XGENE is not set +CONFIG_ARCH_MSM=y +# CONFIG_ARCH_MSM8916 is not set +# CONFIG_ARCH_MSM8917 is not set +# CONFIG_ARCH_MSM8920 is not set +# CONFIG_ARCH_MSM8940 is not set +CONFIG_ARCH_MSM8953=y +# CONFIG_ARCH_SDM450 is not set +# CONFIG_ARCH_MSM8937 is not set +# CONFIG_ARCH_MSM8996 is not set +# CONFIG_ARCH_MSMCOBALT is not set + +# +# Bus support +# +CONFIG_ARM_AMBA=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_SYSCALL=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set +CONFIG_PCI_MSM=y +CONFIG_PCI_LABEL=y + +# +# PCI host controller drivers +# +# CONFIG_PCI_HOST_GENERIC is not set +# CONFIG_PCIEPORTBUS is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# Kernel Features +# + +# +# ARM errata workarounds via the alternatives framework +# +CONFIG_ARM64_ERRATUM_826319=y +CONFIG_ARM64_ERRATUM_827319=y +CONFIG_ARM64_ERRATUM_824069=y +CONFIG_ARM64_ERRATUM_819472=y +CONFIG_ARM64_ERRATUM_832075=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_64K_PAGES is not set +# CONFIG_ARM64_DCACHE_DISABLE is not set +# CONFIG_ARM64_ICACHE_DISABLE is not set +CONFIG_ARCH_MSM8953_SOC_SETTINGS=y +CONFIG_ARM64_VA_BITS_39=y +CONFIG_ARM64_VA_BITS=39 +# CONFIG_CPU_BIG_ENDIAN is not set +# CONFIG_ARM64_SEV_IN_LOCK_UNLOCK is not set +CONFIG_SCHED_MC=y +# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=8 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_NR_GPIO=1024 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ=100 +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HW_PERF_EVENTS=y +# CONFIG_PERF_EVENTS_USERMODE is not set +# CONFIG_PERF_EVENTS_RESET_PMU_DEBUGFS is not set +# CONFIG_ARM64_REG_REBALANCE_ON_CTX_SW is not set +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +CONFIG_MEMORY_ISOLATION=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_TRANSPARENT_HUGEPAGE is not set +CONFIG_CLEANCACHE=y +# CONFIG_FRONTSWAP is not set +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set +CONFIG_CMA_DEBUGFS=y +CONFIG_CMA_AREAS=7 +# CONFIG_ZPOOL is not set +CONFIG_ZBUD=y +CONFIG_ZSMALLOC=y +# CONFIG_PGTABLE_MAPPING is not set +# CONFIG_ZSMALLOC_STAT is not set +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_ZCACHE=y +# CONFIG_BALANCE_ANON_FILE_RECLAIM is not set +CONFIG_KSWAPD_CPU_AFFINITY_MASK="" +# CONFIG_FORCE_ALLOC_FROM_DMA_ZONE is not set +CONFIG_PROCESS_RECLAIM=y +CONFIG_SECCOMP=y +# CONFIG_XEN is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_HARDEN_BRANCH_PREDICTOR=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +# CONFIG_ARM64_SW_TTBR0_PAN is not set + +# +# ARMv8.1 architectural features +# +CONFIG_ARM64_PAN=y +CONFIG_ARM64_UAO=y + +# +# Boot options +# +CONFIG_CMDLINE="" +CONFIG_EFI_STUB=y +CONFIG_EFI=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="" +CONFIG_BUILD_ARM64_KERNEL_COMPRESSION_GZIP=y +# CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL is not set +CONFIG_DMI=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y +CONFIG_COMPAT=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_WAKELOCK=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_PM_ADVANCED_DEBUG is not set +# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_PM_SLEEP_DEBUG=y +# CONFIG_DPM_WATCHDOG is not set +CONFIG_PM_OPP=y +CONFIG_PM_CLK=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_CPU_PM=y +CONFIG_SUSPEND_TIME=y +# CONFIG_DEDUCE_WAKEUP_REASONS is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM64_CPU_SUSPEND=y + +# +# CPU Power Management +# + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y + +# +# ARM64 CPU Idle Drivers +# +# CONFIG_ARM64_CPUIDLE is not set +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_SCHED_FREQ_INPUT=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHED is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +# CONFIG_CPU_FREQ_GOV_SCHED is not set + +# +# CPU frequency scaling drivers +# +# CONFIG_CPUFREQ_DT is not set +# CONFIG_CPU_BOOST is not set + +# +# ARM CPU frequency scaling drivers +# +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +CONFIG_CPU_FREQ_MSM=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y +# CONFIG_DISABLE_NET_SKB_FRAG_CACHE is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +CONFIG_XFRM_STATISTICS=y +CONFIG_XFRM_IPCOMP=y +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_ROUTE_MULTIPATH is not set +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=y +# CONFIG_IP_MROUTE is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_NET_IPVTI is not set +CONFIG_NET_UDP_TUNNEL=y +# CONFIG_NET_FOU is not set +# CONFIG_GENEVE is not set +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +CONFIG_INET_DIAG_DESTROY=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_TUNNEL=y +CONFIG_INET6_TUNNEL=y +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_GRE is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETLABEL is not set +CONFIG_ANDROID_PARANOID_NETWORK=y +CONFIG_NET_ACTIVITY_STATS=y +CONFIG_NETWORK_SECMARK=y +# CONFIG_NET_PTP_CLASSIFY is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=y +# CONFIG_NETFILTER_NETLINK_ACCT is not set +CONFIG_NETFILTER_NETLINK_QUEUE=y +CONFIG_NETFILTER_NETLINK_LOG=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_LOG_COMMON=y +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +# CONFIG_NF_CONNTRACK_ZONES is not set +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +CONFIG_NF_CT_PROTO_DCCP=y +CONFIG_NF_CT_PROTO_GRE=y +CONFIG_NF_CT_PROTO_SCTP=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_BROADCAST=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +# CONFIG_NF_CONNTRACK_SNMP is not set +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +# CONFIG_NF_CONNTRACK_SIP is not set +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set +CONFIG_NF_NAT=y +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PROTO_DCCP=y +CONFIG_NF_NAT_PROTO_UDPLITE=y +CONFIG_NF_NAT_PROTO_SCTP=y +CONFIG_NF_NAT_AMANDA=y +CONFIG_NF_NAT_FTP=y +CONFIG_NF_NAT_IRC=y +# CONFIG_NF_NAT_SIP is not set +CONFIG_NF_NAT_TFTP=y +# CONFIG_NF_TABLES is not set +CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=y +CONFIG_NETFILTER_XT_CONNMARK=y + +# +# Xtables targets +# +# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set +# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_CT=y +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_HL is not set +# CONFIG_NETFILTER_XT_TARGET_HMARK is not set +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y +# CONFIG_NETFILTER_XT_TARGET_LED is not set +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_NAT=y +CONFIG_NETFILTER_XT_TARGET_NETMAP=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +CONFIG_NETFILTER_XT_TARGET_REDIRECT=y +CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set + +# +# Xtables matches +# +# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_BPF is not set +# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ECN=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_HL=y +# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_L2TP=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +CONFIG_NETFILTER_XT_MATCH_POLICY=y +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +# CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +# CONFIG_NF_LOG_ARP is not set +CONFIG_NF_LOG_IPV4=y +CONFIG_NF_REJECT_IPV4=y +CONFIG_NF_NAT_IPV4=y +CONFIG_NF_NAT_MASQUERADE_IPV4=y +CONFIG_NF_NAT_PROTO_GRE=y +CONFIG_NF_NAT_PPTP=y +CONFIG_NF_NAT_H323=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +# CONFIG_IP_NF_MATCH_RPFILTER is not set +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +# CONFIG_IP_NF_TARGET_SYNPROXY is not set +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NATTYPE_MODULE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_TTL is not set +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_SECURITY=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_NF_REJECT_IPV6=y +CONFIG_NF_LOG_IPV6=y +# CONFIG_NF_NAT_IPV6 is not set +CONFIG_IP6_NF_IPTABLES=y +# CONFIG_IP6_NF_MATCH_AH is not set +# CONFIG_IP6_NF_MATCH_EUI64 is not set +# CONFIG_IP6_NF_MATCH_FRAG is not set +# CONFIG_IP6_NF_MATCH_OPTS is not set +# CONFIG_IP6_NF_MATCH_HL is not set +# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set +# CONFIG_IP6_NF_MATCH_MH is not set +CONFIG_IP6_NF_MATCH_RPFILTER=y +# CONFIG_IP6_NF_MATCH_RT is not set +# CONFIG_IP6_NF_TARGET_HL is not set +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +# CONFIG_IP6_NF_TARGET_SYNPROXY is not set +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +# CONFIG_IP6_NF_SECURITY is not set +# CONFIG_IP6_NF_NAT is not set +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +# CONFIG_BRIDGE_EBT_T_FILTER is not set +# CONFIG_BRIDGE_EBT_T_NAT is not set +# CONFIG_BRIDGE_EBT_802_3 is not set +# CONFIG_BRIDGE_EBT_AMONG is not set +# CONFIG_BRIDGE_EBT_ARP is not set +# CONFIG_BRIDGE_EBT_IP is not set +# CONFIG_BRIDGE_EBT_IP6 is not set +# CONFIG_BRIDGE_EBT_LIMIT is not set +# CONFIG_BRIDGE_EBT_MARK is not set +# CONFIG_BRIDGE_EBT_PKTTYPE is not set +# CONFIG_BRIDGE_EBT_STP is not set +# CONFIG_BRIDGE_EBT_VLAN is not set +# CONFIG_BRIDGE_EBT_ARPREPLY is not set +# CONFIG_BRIDGE_EBT_DNAT is not set +# CONFIG_BRIDGE_EBT_MARK_T is not set +# CONFIG_BRIDGE_EBT_REDIRECT is not set +# CONFIG_BRIDGE_EBT_SNAT is not set +# CONFIG_BRIDGE_EBT_LOG is not set +# CONFIG_BRIDGE_EBT_NFLOG is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_L2TP=y +CONFIG_L2TP_DEBUGFS=y +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=y +CONFIG_L2TP_ETH=y +CONFIG_STP=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_HAVE_NET_DSA=y +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_6LOWPAN is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_CBQ is not set +CONFIG_NET_SCH_HTB=y +# CONFIG_NET_SCH_HFSC is not set +CONFIG_NET_SCH_PRIO=y +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_CODEL is not set +# CONFIG_NET_SCH_FQ_CODEL is not set +# CONFIG_NET_SCH_FQ is not set +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_PIE is not set +# CONFIG_NET_SCH_INGRESS is not set +# CONFIG_NET_SCH_PLUG is not set + +# +# Classification +# +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +# CONFIG_CLS_U32_PERF is not set +CONFIG_CLS_U32_MARK=y +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +CONFIG_NET_CLS_FLOW=y +# CONFIG_NET_CLS_CGROUP is not set +# CONFIG_NET_CLS_BPF is not set +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +CONFIG_NET_CLS_ACT=y +# CONFIG_NET_ACT_POLICE is not set +# CONFIG_NET_ACT_GACT is not set +# CONFIG_NET_ACT_MIRRED is not set +# CONFIG_NET_ACT_IPT is not set +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_SIMP is not set +# CONFIG_NET_ACT_SKBEDIT is not set +# CONFIG_NET_ACT_CSUM is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +# CONFIG_DNS_RESOLVER is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_NET_MPLS_GSO is not set +# CONFIG_HSR is not set +CONFIG_RMNET_DATA=y +CONFIG_RMNET_DATA_FC=y +CONFIG_RMNET_DATA_DEBUG_PKT=y +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +# CONFIG_CGROUP_NET_PRIO is not set +# CONFIG_CGROUP_NET_CLASSID is not set +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +CONFIG_NET_FLOW_LIMIT=y +CONFIG_SOCKEV_NLMCAST=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_DROP_MONITOR is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y + +# +# Bluetooth device drivers +# +# CONFIG_BT_HCIBTUSB is not set +# CONFIG_BT_HCIBTSDIO is not set +# CONFIG_BT_HCIUART is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_MRVL is not set +CONFIG_MSM_BT_POWER=y +# CONFIG_BTFM_SLIM is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +CONFIG_CFG80211_INTERNAL_REGDB=y +# CONFIG_CFG80211_WEXT is not set +# CONFIG_LIB80211 is not set +# CONFIG_MAC80211 is not set +# CONFIG_WIMAX is not set +CONFIG_RFKILL=y +CONFIG_RFKILL_PM=y +CONFIG_RFKILL_LEDS=y +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +# CONFIG_NFC_NQ is not set +CONFIG_IPC_ROUTER=y +CONFIG_IPC_ROUTER_SECURITY=y +CONFIG_HAVE_BPF_JIT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +# CONFIG_FW_CACHE is not set +CONFIG_WANT_DEV_COREDUMP=y +CONFIG_ALLOW_DEV_COREDUMP=y +CONFIG_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_SOC_BUS=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_SWR=y +CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_FENCE_TRACE is not set +CONFIG_DMA_CMA=y + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=16 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 + +# +# Bus devices +# +# CONFIG_ARM_CCN is not set +# CONFIG_VEXPRESS_CONFIG is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +# CONFIG_OF_UNITTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_OF_SPMI=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_OF_SLIMBUS=y +CONFIG_OF_CORESIGHT=y +CONFIG_OF_BATTERYDATA=y +# CONFIG_OF_OVERLAY is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +CONFIG_ZRAM=y +# CONFIG_ZRAM_LZ4_COMPRESS is not set +# CONFIG_ZRAM_DEBUG is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_BLK_DEV_SKD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_BLK_DEV_RSXX is not set + +# +# Misc devices +# +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_APDS9930 is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +CONFIG_UID_STAT=y +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SRAM is not set +CONFIG_QSEECOM=y +CONFIG_HDCP_QSEECOM=y +# CONFIG_PROFILER is not set +CONFIG_UID_SYS_STATS=y +CONFIG_USB_EXT_TYPE_C_PERICOM=y +# CONFIG_USB_EXT_TYPE_C_TI is not set +# CONFIG_TI_DRV2667 is not set +# CONFIG_QPNP_MISC is not set +# CONFIG_UID_SYS_STATS_DEBUG is not set +# CONFIG_MEMORY_STATE_TIME is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_CB710_CORE is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set +CONFIG_MSM_QDSP6V2_CODECS=y +CONFIG_MSM_ULTRASOUND=y +# CONFIG_MSM_MCU_TIME_SYNC is not set + +# +# Intel MIC Bus Driver +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# +# CONFIG_GENWQE is not set +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_MVUMI is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_SCSI_ESAS2R is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_MPT3SAS is not set +CONFIG_SCSI_UFSHCD=y +# CONFIG_SCSI_UFSHCD_PCI is not set +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFS_QCOM_ICE=y +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_HAVE_PATA_PLATFORM=y +# CONFIG_ATA is not set +CONFIG_MD=y +# CONFIG_BLK_DEV_MD is not set +# CONFIG_BCACHE is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=y +# CONFIG_DM_DEBUG is not set +CONFIG_DM_BUFIO=y +CONFIG_DM_CRYPT=y +CONFIG_DM_REQ_CRYPT=y +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_THIN_PROVISIONING is not set +# CONFIG_DM_CACHE is not set +# CONFIG_DM_ERA is not set +# CONFIG_DM_MIRROR is not set +# CONFIG_DM_RAID is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set +CONFIG_DM_UEVENT=y +# CONFIG_DM_FLAKEY is not set +CONFIG_DM_VERITY=y +# CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE_128 is not set +CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE=1 +CONFIG_DM_VERITY_FEC=y +# CONFIG_DM_SWITCH is not set +# CONFIG_DM_LOG_WRITES is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +CONFIG_MII=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +CONFIG_DUMMY=y +# CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set +# CONFIG_IFB is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +CONFIG_TUN=y +CONFIG_VETH=y +# CONFIG_NLMON is not set +# CONFIG_ARCNET is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +# CONFIG_NET_DSA_MV88E6171 is not set +# CONFIG_NET_DSA_BCM_SF2 is not set +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_3COM=y +# CONFIG_VORTEX is not set +# CONFIG_TYPHOON is not set +CONFIG_NET_VENDOR_ADAPTEC=y +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_NET_VENDOR_AGERE=y +# CONFIG_ET131X is not set +CONFIG_NET_VENDOR_ALTEON=y +# CONFIG_ACENIC is not set +# CONFIG_ALTERA_TSE is not set +CONFIG_NET_VENDOR_AMD=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_PCNET32 is not set +# CONFIG_AMD_XGBE is not set +# CONFIG_NET_XGENE is not set +CONFIG_NET_VENDOR_ARC=y +# CONFIG_ARC_EMAC is not set +# CONFIG_EMAC_ROCKCHIP is not set +CONFIG_NET_VENDOR_ATHEROS=y +# CONFIG_ATL2 is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_ALX is not set +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_BCMGENET is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2X is not set +# CONFIG_SYSTEMPORT is not set +CONFIG_NET_VENDOR_BROCADE=y +# CONFIG_BNA is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +CONFIG_NET_VENDOR_CISCO=y +# CONFIG_ENIC is not set +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DEC=y +# CONFIG_NET_TULIP is not set +CONFIG_NET_VENDOR_DLINK=y +# CONFIG_DL2K is not set +# CONFIG_SUNDANCE is not set +CONFIG_NET_VENDOR_EMULEX=y +# CONFIG_BE2NET is not set +CONFIG_NET_VENDOR_EXAR=y +# CONFIG_S2IO is not set +# CONFIG_VXGE is not set +CONFIG_NET_VENDOR_HP=y +# CONFIG_HP100 is not set +CONFIG_NET_VENDOR_INTEL=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGBEVF is not set +# CONFIG_I40E is not set +# CONFIG_I40EVF is not set +# CONFIG_FM10K is not set +CONFIG_NET_VENDOR_I825XX=y +# CONFIG_IP1000 is not set +# CONFIG_JME is not set +CONFIG_NET_VENDOR_MARVELL=y +# CONFIG_MVMDIO is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLX4_EN is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_MLX5_CORE is not set +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_KSZ884X_PCI is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +# CONFIG_ECM_IPA is not set +CONFIG_RNDIS_IPA=y +# CONFIG_MSM_RMNET_BAM is not set +CONFIG_NET_VENDOR_MYRI=y +# CONFIG_MYRI10GE is not set +# CONFIG_FEALNX is not set +CONFIG_NET_VENDOR_NATSEMI=y +# CONFIG_NATSEMI is not set +# CONFIG_NS83820 is not set +CONFIG_NET_VENDOR_8390=y +# CONFIG_NE2K_PCI is not set +CONFIG_NET_VENDOR_NVIDIA=y +# CONFIG_FORCEDETH is not set +CONFIG_NET_VENDOR_OKI=y +# CONFIG_ETHOC is not set +CONFIG_NET_PACKET_ENGINE=y +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +CONFIG_NET_VENDOR_QLOGIC=y +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_QLGE is not set +# CONFIG_NETXEN_NIC is not set +CONFIG_NET_VENDOR_QUALCOMM=y +# CONFIG_QCA7000 is not set +# CONFIG_QCOM_EMAC is not set +CONFIG_NET_VENDOR_REALTEK=y +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R8169 is not set +CONFIG_NET_VENDOR_RDC=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_SAMSUNG=y +# CONFIG_SXGBE_ETH is not set +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SILAN=y +# CONFIG_SC92031 is not set +CONFIG_NET_VENDOR_SIS=y +# CONFIG_SIS900 is not set +# CONFIG_SIS190 is not set +# CONFIG_SFC is not set +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_SMC91X is not set +# CONFIG_EPIC100 is not set +# CONFIG_SMSC911X is not set +# CONFIG_SMSC9420 is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_SUN=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NIU is not set +CONFIG_NET_VENDOR_TEHUTI=y +# CONFIG_TEHUTI is not set +CONFIG_NET_VENDOR_TI=y +# CONFIG_TLAN is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AT803X_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_AMD_XGBE_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_QCA8337_SWITCH is not set +# CONFIG_NXP_TJA110X_PHY is not set +# CONFIG_MICREL_KS8995MA is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOL2TP=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_SLIP is not set +CONFIG_SLHC=y +CONFIG_USB_NET_DRIVERS=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=y +CONFIG_USB_NET_AX88179_178A=y +CONFIG_USB_NET_CDCETHER=y +# CONFIG_USB_NET_CDC_EEM is not set +CONFIG_USB_NET_CDC_NCM=y +# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set +# CONFIG_USB_NET_CDC_MBIM is not set +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SR9700 is not set +# CONFIG_USB_NET_SR9800 is not set +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_GL620A is not set +CONFIG_USB_NET_NET1080=y +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +CONFIG_USB_NET_CDC_SUBSET=y +# CONFIG_USB_ALI_M5632 is not set +# CONFIG_USB_AN2720 is not set +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +# CONFIG_USB_EPSON2888 is not set +# CONFIG_USB_KC2190 is not set +CONFIG_USB_NET_ZAURUS=y +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_NET_KALMIA is not set +# CONFIG_USB_NET_QMI_WWAN is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_USB_VL600 is not set +# CONFIG_USBNET_IPA_BRIDGE is not set +CONFIG_WLAN=y +# CONFIG_ATMEL is not set +# CONFIG_PRISM54 is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_WIFI_CONTROL_FUNC is not set +CONFIG_WCNSS_CORE=y +CONFIG_WCNSS_CORE_PRONTO=y +CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y +CONFIG_WCNSS_MEM_PRE_ALLOC=y +# CONFIG_WCNSS_SKB_PRE_ALLOC is not set +CONFIG_CNSS_CRYPTO=y +CONFIG_ATH_CARDS=y +# CONFIG_ATH_DEBUG is not set +# CONFIG_ATH5K_PCI is not set +# CONFIG_ATH6KL is not set +CONFIG_WIL6210=y +CONFIG_WIL6210_ISR_COR=y +CONFIG_WIL6210_TRACING=y +# CONFIG_WIL6210_WRITE_IOCTL is not set +CONFIG_WIL6210_PLATFORM_MSM=y +# CONFIG_BRCMFMAC is not set +# CONFIG_HOSTAP is not set +# CONFIG_IPW2100 is not set +# CONFIG_LIBERTAS is not set +# CONFIG_WL_TI is not set +# CONFIG_MWIFIEX is not set +# CONFIG_CNSS is not set +# CONFIG_CLD_DEBUG is not set +# CONFIG_CLD_HL_SDIO_CORE is not set +CONFIG_CLD_LL_CORE=y +# CONFIG_CNSS_LOGGER is not set +# CONFIG_WLAN_FEATURE_RX_WAKELOCK is not set +# CONFIG_CNSS2 is not set +CONFIG_CNSS_UTILS=y + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_VMXNET3 is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_MATRIXKMAP is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_KEYRESET=y +CONFIG_INPUT_KEYCOMBO=y +# CONFIG_SENSORS_HALL is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP1106 is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +# CONFIG_JOYSTICK_ANALOG is not set +# CONFIG_JOYSTICK_A3D is not set +# CONFIG_JOYSTICK_ADI is not set +# CONFIG_JOYSTICK_COBRA is not set +# CONFIG_JOYSTICK_GF2K is not set +# CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set +# CONFIG_JOYSTICK_INTERACT is not set +# CONFIG_JOYSTICK_SIDEWINDER is not set +# CONFIG_JOYSTICK_TMDC is not set +# CONFIG_JOYSTICK_IFORCE is not set +# CONFIG_JOYSTICK_WARRIOR is not set +# CONFIG_JOYSTICK_MAGELLAN is not set +# CONFIG_JOYSTICK_SPACEORB is not set +# CONFIG_JOYSTICK_SPACEBALL is not set +# CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDJOY is not set +# CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set +# CONFIG_JOYSTICK_JOYDUMP is not set +CONFIG_JOYSTICK_XPAD=y +# CONFIG_JOYSTICK_XPAD_FF is not set +# CONFIG_JOYSTICK_XPAD_LEDS is not set +CONFIG_INPUT_TABLET=y +# CONFIG_TABLET_USB_ACECAD is not set +# CONFIG_TABLET_USB_AIPTEK is not set +# CONFIG_TABLET_USB_GTCO is not set +# CONFIG_TABLET_USB_HANWANG is not set +# CONFIG_TABLET_USB_KBTAB is not set +# CONFIG_TABLET_SERIAL_WACOM4 is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_v21=y +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_I2C_v21=y +# CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_SPI_v21 is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21 is not set +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_v26=y +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_I2C_v26=y +# CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_SPI_v26 is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_HID_I2C_v26 is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v26 is not set +# CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26 is not set +CONFIG_OF_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH_TS is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +CONFIG_TOUCHSCREEN_FT5435=y +CONFIG_TOUCHSCREEN_IST3038C=y +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_SUR40 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +# CONFIG_SECURE_TOUCH is not set +# CONFIG_TOUCHSCREEN_IT7260_I2C is not set +# CONFIG_TOUCHSCREEN_GEN_VKEYS is not set +# CONFIG_TOUCHSCREEN_FT5X06 is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +# CONFIG_TOUCHSCREEN_GT9XX is not set +CONFIG_TOUCHSCREEN_GT9XX_MIDO=y +# CONFIG_TOUCHSCREEN_MAXIM_STI is not set +# CONFIG_TOUCHSCREEN_FTS is not set +# CONFIG_TOUCHSCREEN_TD4310 is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_BMA150 is not set +CONFIG_INPUT_HBTP_INPUT=y +# CONFIG_HBTP_INPUT_SECURE_TOUCH is not set +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_MPU3050 is not set +# CONFIG_SENSORS_MPU6050 is not set +# CONFIG_SENSORS_AKM8963 is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +CONFIG_INPUT_KEYCHORD=y +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=y +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set +# CONFIG_INPUT_PIXART_OTS_PAT9125_SWITCH is not set +# CONFIG_SENSORS_LTR553 is not set +# CONFIG_SENSORS_BMA2X2 is not set +CONFIG_INPUT_FINGERPRINT=y +CONFIG_FINGERPRINT_GOODIX_GF3208_MIDO=y +CONFIG_FINGERPRINT_FPC1020_MIDO=y +# CONFIG_FINGERPRINT_GOODIX_GF3208_TISSOT is not set +# CONFIG_FINGERPRINT_FPC1020_TISSOT is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +# CONFIG_VT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SERIAL_MFD_HSU is not set +CONFIG_SERIAL_CORE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_SERIAL_MSM_HS=y +# CONFIG_SERIAL_MSM_HSL is not set +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +CONFIG_SERIAL_MSM_SMD=y +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_RP2 is not set +# CONFIG_SERIAL_FSL_LPUART is not set + +# +# Diag Support +# +CONFIG_DIAG_CHAR=y + +# +# DIAG traffic over USB +# +CONFIG_DIAG_OVER_USB=y + +# +# HSIC/SMUX support for DIAG +# +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_MSM_LEGACY=y +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# PCMCIA character devices +# +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +CONFIG_MSM_SMD_PKT=y +# CONFIG_XILLYBUS is not set +CONFIG_MSM_ADSPRPC=y +# CONFIG_MSM_MDSP_TS is not set +# CONFIG_MSM_RDBG is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set +# CONFIG_I2C_MSM_QUP is not set +CONFIG_I2C_MSM_V2=y + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SLIMBUS=y +# CONFIG_SLIMBUS_MSM_CTRL is not set +CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_SOUNDWIRE=y +CONFIG_SOUNDWIRE_WCD_CTRL=y +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_ROCKCHIP is not set +CONFIG_SPI_QUP=y +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPMI is not set +# CONFIG_HSI is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +# CONFIG_PTP_1588_CLOCK is not set + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_PINCTRL=y + +# +# Pin controllers +# +CONFIG_PINMUX=y +CONFIG_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PINCTRL_MSM=y +# CONFIG_PINCTRL_APQ8064 is not set +# CONFIG_PINCTRL_MDM9607 is not set +# CONFIG_PINCTRL_MDM9640 is not set +# CONFIG_PINCTRL_MDM9650 is not set +# CONFIG_PINCTRL_SDX20 is not set +# CONFIG_PINCTRL_APQ8084 is not set +# CONFIG_PINCTRL_IPQ8064 is not set +# CONFIG_PINCTRL_MSM8960 is not set +# CONFIG_PINCTRL_MSM8X74 is not set +CONFIG_PINCTRL_MSM8953=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_PL061 is not set +CONFIG_GPIO_QPNP_PIN=y +# CONFIG_GPIO_QPNP_PIN_DEBUG is not set +# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_XGENE is not set +# CONFIG_GPIO_VX855 is not set +# CONFIG_GPIO_GRGPIO is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set + +# +# PCI GPIO expanders: +# +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_AMD8111 is not set +# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_RDC321X is not set + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# LPC GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# + +# +# USB GPIO expanders: +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_SMB349_USB_CHARGER is not set +# CONFIG_SMB349_DUAL_CHARGER is not set +CONFIG_SMB1351_USB_CHARGER=y +# CONFIG_SMB350_CHARGER is not set +CONFIG_SMB135X_CHARGER=y +# CONFIG_SMB1360_CHARGER_FG is not set +# CONFIG_SMB358_CHARGER is not set +# CONFIG_SMB23X_CHARGER is not set +# CONFIG_BATTERY_BQ28400 is not set +# CONFIG_QPNP_CHARGER is not set +CONFIG_QPNP_SMBCHARGER=y +# CONFIG_QPNP_SMB2 is not set +# CONFIG_FUELGAUGE_STC3117 is not set +CONFIG_QPNP_FG=y +# CONFIG_QPNP_FG_GEN3 is not set +CONFIG_BATTERY_BCL=y +# CONFIG_QPNP_VM_BMS is not set +# CONFIG_QPNP_BMS is not set +# CONFIG_QPNP_LINEAR_CHARGER is not set +CONFIG_QPNP_TYPEC=y +CONFIG_MSM_BCL_CTL=y +CONFIG_MSM_BCL_PERIPHERAL_CTL=y +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_POWER_RESET_LTC2952 is not set +CONFIG_POWER_RESET_MSM=y +# CONFIG_MSM_DLOAD_MODE is not set +CONFIG_MSM_PRESERVE_MEM=y +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_AVS is not set +CONFIG_MSM_PM=y +CONFIG_APSS_CORE_EA=y +CONFIG_MSM_APM=y +CONFIG_MSM_IDLE_STATS=y +CONFIG_MSM_IDLE_STATS_FIRST_BUCKET=62500 +CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT=2 +CONFIG_MSM_IDLE_STATS_BUCKET_COUNT=10 +CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET=1000000000 +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_HTU21 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_PCF8591 is not set +CONFIG_SENSORS_EPM_ADC=y +CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y +CONFIG_SENSORS_QPNP_ADC_CURRENT=y +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_PWM_FAN is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set +# CONFIG_CPU_THERMAL is not set +# CONFIG_THERMAL_EMULATION is not set +CONFIG_THERMAL_TSENS8974=y +CONFIG_LIMITS_MONITOR=y +CONFIG_LIMITS_LITE_HW=y +CONFIG_THERMAL_MONITOR=y +CONFIG_THERMAL_QPNP=y +CONFIG_THERMAL_QPNP_ADC_TM=y + +# +# Texas Instruments thermal drivers +# +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_AXP20X is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_I2C_PMIC is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RTSX_PCI is not set +# CONFIG_MFD_RTSX_USB is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK808 is not set +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_WCD9306_CODEC is not set +# CONFIG_WCD9320_CODEC is not set +CONFIG_WCD9330_CODEC=y +CONFIG_WCD9335_CODEC=y +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_PROXY_CONSUMER is not set +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +CONFIG_REGULATOR_STUB=y +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +CONFIG_REGULATOR_FAN53555=y +CONFIG_REGULATOR_MSM_GFX_LDO=y +# CONFIG_REGULATOR_GPIO is not set +# CONFIG_REGULATOR_ISL9305 is not set +CONFIG_REGULATOR_MEM_ACC=y +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_ONSEMI_NCP6335D is not set +# CONFIG_REGULATOR_PFUZE100 is not set +# CONFIG_REGULATOR_PWM is not set +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_REGULATOR_RPM_SMD=y +CONFIG_REGULATOR_QPNP=y +CONFIG_REGULATOR_QPNP_LABIBB=y +CONFIG_REGULATOR_SPM=y +CONFIG_REGULATOR_CPR=y +# CONFIG_REGULATOR_CPR2_GFX is not set +CONFIG_REGULATOR_CPR3=y +CONFIG_REGULATOR_CPR3_HMSS=y +CONFIG_REGULATOR_CPR3_MMSS=y +CONFIG_REGULATOR_CPR4_APSS=y +CONFIG_REGULATOR_CPRH_KBSS=y +CONFIG_REGULATOR_KRYO=y +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +CONFIG_MEDIA_RADIO_SUPPORT=y +# CONFIG_MEDIA_SDR_SUPPORT is not set +CONFIG_MEDIA_RC_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_VIDEO_V4L2=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_V4L2_MEM2MEM_DEV=y +CONFIG_VIDEOBUF_GEN=y +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_VMALLOC=y +# CONFIG_TTPCI_EEPROM is not set + +# +# Media drivers +# +CONFIG_RC_CORE=y +# CONFIG_SPI_PEELIR is not set +CONFIG_RC_MAP=y +CONFIG_RC_DECODERS=y +CONFIG_LIRC=y +CONFIG_IR_LIRC_CODEC=y +CONFIG_IR_NEC_DECODER=y +CONFIG_IR_RC5_DECODER=y +CONFIG_IR_RC6_DECODER=y +CONFIG_IR_JVC_DECODER=y +CONFIG_IR_SONY_DECODER=y +CONFIG_IR_SANYO_DECODER=y +CONFIG_IR_SHARP_DECODER=y +# CONFIG_IR_MCE_KBD_DECODER is not set +CONFIG_IR_XMP_DECODER=y +# CONFIG_IR_DUMP_DECODER is not set +CONFIG_RC_DEVICES=y +# CONFIG_RC_ATI_REMOTE is not set +# CONFIG_IR_HIX5HD2 is not set +# CONFIG_IR_IMON is not set +# CONFIG_IR_MCEUSB is not set +# CONFIG_IR_REDRAT3 is not set +# CONFIG_IR_STREAMZAP is not set +# CONFIG_IR_IGUANA is not set +# CONFIG_IR_TTUSBIR is not set +# CONFIG_IR_IMG is not set +# CONFIG_RC_LOOPBACK is not set +# CONFIG_IR_GPIO_CIR is not set +# CONFIG_IR_GPIO is not set +CONFIG_IR_PWM=y +# CONFIG_MEDIA_USB_SUPPORT is not set +# CONFIG_MEDIA_PCI_SUPPORT is not set +CONFIG_V4L_PLATFORM_DRIVERS=y +# CONFIG_VIDEO_CAFE_CCIC is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_PLATFORM=y +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +# CONFIG_V4L_TEST_DRIVERS is not set +CONFIG_MSM_VIDC_V4L2=y +CONFIG_MSM_VIDC_VMEM=y +CONFIG_MSM_VIDC_GOVERNORS=y + +# +# QTI MSM Camera And Video & AIS +# +CONFIG_MSM_CAMERA=y +# CONFIG_MSM_CAMERA_DEBUG is not set +# CONFIG_MSM_CAMERA_AUTOMOTIVE is not set +CONFIG_MSMB_CAMERA=y +# CONFIG_MSMB_CAMERA_DEBUG is not set +CONFIG_MSM_CAMERA_SENSOR=y +CONFIG_MSM_CPP=y +CONFIG_MSM_CCI=y +CONFIG_MSM_CSI20_HEADER=y +CONFIG_MSM_CSI22_HEADER=y +CONFIG_MSM_CSI30_HEADER=y +CONFIG_MSM_CSI31_HEADER=y +CONFIG_MSM_CSIPHY=y +CONFIG_MSM_CSID=y +CONFIG_MSM_EEPROM=y +# CONFIG_MSM_ISP_V1 is not set +CONFIG_MSM_ISPIF=y +# CONFIG_MSM_ISPIF_V1 is not set +# CONFIG_MSM_ISPIF_V2 is not set +CONFIG_IMX134=y +CONFIG_IMX132=y +CONFIG_OV9724=y +CONFIG_OV5648=y +CONFIG_GC0339=y +CONFIG_OV8825=y +CONFIG_OV8865=y +CONFIG_s5k4e1=y +CONFIG_OV12830=y +CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y +CONFIG_MSMB_JPEG=y +CONFIG_MSM_FD=y +# CONFIG_MSM_JPEGDMA is not set +CONFIG_MSM_SEC_CCI_TA_NAME="seccamdemo64" +# CONFIG_MSM_SEC_CCI_DEBUG is not set +# CONFIG_MSM_AIS is not set +# CONFIG_TSPP is not set +CONFIG_MSM_SDE_ROTATOR=y + +# +# Supported MMC/SDIO adapters +# +CONFIG_RADIO_ADAPTERS=y +# CONFIG_RADIO_SI470X is not set +# CONFIG_RADIO_SI4713 is not set +# CONFIG_USB_MR800 is not set +# CONFIG_USB_DSBR is not set +# CONFIG_RADIO_MAXIRADIO is not set +# CONFIG_RADIO_SHARK is not set +# CONFIG_RADIO_SHARK2 is not set +# CONFIG_USB_KEENE is not set +# CONFIG_USB_RAREMONO is not set +# CONFIG_USB_MA901 is not set +# CONFIG_RADIO_TEA5764 is not set +# CONFIG_RADIO_SAA7706H is not set +# CONFIG_RADIO_TEF6862 is not set +# CONFIG_RADIO_WL1273 is not set + +# +# Texas Instruments WL128x FM driver (ST based) +# +# CONFIG_RADIO_WL128X is not set +CONFIG_RADIO_IRIS=y +CONFIG_RADIO_IRIS_TRANSPORT=y +CONFIG_RADIO_SILABS=y +# CONFIG_CYPRESS_FIRMWARE is not set + +# +# Media ancillary drivers (tuners, sensors, i2c, frontends) +# +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y +CONFIG_VIDEO_IR_I2C=y + +# +# Audio decoders, processors and mixers +# + +# +# RDS decoders +# + +# +# Video decoders +# + +# +# Video and audio decoders +# + +# +# Video encoders +# + +# +# Camera sensor devices +# + +# +# Flash devices +# + +# +# Video improvement chips +# + +# +# Audio/Video compression chips +# + +# +# Miscellaneous helper chips +# + +# +# Sensors used on soc_camera driver +# + +# +# soc_camera sensor drivers +# +# CONFIG_SOC_CAMERA_IMX074 is not set +# CONFIG_SOC_CAMERA_MT9M001 is not set +# CONFIG_SOC_CAMERA_MT9M111 is not set +# CONFIG_SOC_CAMERA_MT9T031 is not set +# CONFIG_SOC_CAMERA_MT9T112 is not set +# CONFIG_SOC_CAMERA_MT9V022 is not set +# CONFIG_SOC_CAMERA_OV2640 is not set +# CONFIG_SOC_CAMERA_OV5642 is not set +# CONFIG_SOC_CAMERA_OV6650 is not set +# CONFIG_SOC_CAMERA_OV772X is not set +# CONFIG_SOC_CAMERA_OV9640 is not set +# CONFIG_SOC_CAMERA_OV9740 is not set +# CONFIG_SOC_CAMERA_RJ54N1 is not set +# CONFIG_SOC_CAMERA_TW9910 is not set +CONFIG_MEDIA_TUNER=y +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MC44S803=y + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set + +# +# Graphics support +# +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +CONFIG_MSM_KGSL=y +# CONFIG_MSM_KGSL_CFF_DUMP is not set +CONFIG_MSM_ADRENO_DEFAULT_GOVERNOR="msm-adreno-tz" +CONFIG_MSM_KGSL_IOMMU=y + +# +# Direct Rendering Manager +# +# CONFIG_DRM is not set + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +CONFIG_FB_MSM=y +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_MSM_BA_V4L2 is not set +CONFIG_MSM_DBA=y +CONFIG_MSM_DBA_ADV7533=y +CONFIG_FB_MSM_MDSS_COMMON=y +# CONFIG_FB_MSM_MDP is not set +CONFIG_FB_MSM_MDSS=y +# CONFIG_FB_MSM_MDP_NONE is not set +# CONFIG_FB_MSM_QPIC_ILI_QVGA_PANEL is not set +# CONFIG_FB_MSM_QPIC_PANEL_DETECT is not set +CONFIG_FB_MSM_MDSS_WRITEBACK=y +CONFIG_FB_MSM_MDSS_HDMI_PANEL=y +# CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334 is not set +# CONFIG_FB_MSM_MDSS_MHL3 is not set +# CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS is not set +# CONFIG_FB_MSM_MDSS_EDP_PANEL is not set +# CONFIG_FB_MSM_MDSS_MDP3 is not set +CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y +# CONFIG_FB_MSM_MDSS_FRC_DEBUG is not set +# CONFIG_FB_SSD1307 is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_ADF is not set +# CONFIG_VGASTATE is not set +# CONFIG_LT8912 is not set +# CONFIG_LOGO is not set +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=y +CONFIG_SND_RAWMIDI=y +CONFIG_SND_COMPRESS_OFFLOAD=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_MAX_CARDS=32 +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_PCI=y +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AW2 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_OXYGEN is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CTXFI is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set +# CONFIG_SND_INDIGOIOX is not set +# CONFIG_SND_INDIGODJX is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_LOLA is not set +# CONFIG_SND_LX6464ES is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_YMFPCI is not set + +# +# HD-Audio +# +# CONFIG_SND_HDA_INTEL is not set +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=y +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_BCD2000 is not set +CONFIG_SND_SOC=y +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set + +# +# MSM SoC Audio support +# +CONFIG_SND_SOC_MSM_HOSTLESS_PCM=y +CONFIG_SND_SOC_MSM_QDSP6V2_INTF=y +CONFIG_SND_SOC_QDSP6V2=y +# CONFIG_SND_SOC_QDSP_DEBUG is not set +CONFIG_DOLBY_DAP=y +CONFIG_DOLBY_DS2=y +CONFIG_DTS_EAGLE=y +CONFIG_DTS_SRS_TM=y +CONFIG_QTI_PP=y +CONFIG_SND_SOC_CPE=y +CONFIG_SND_SOC_MSM8X16=y +CONFIG_SND_SOC_I2C_AND_SPI=y + +# +# CODEC drivers +# +# CONFIG_SND_SOC_ADAU1701 is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4554 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_CS35L32 is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_CS42L73 is not set +# CONFIG_SND_SOC_CS4265 is not set +# CONFIG_SND_SOC_CS4270 is not set +# CONFIG_SND_SOC_CS4271 is not set +# CONFIG_SND_SOC_CS42XX8_I2C is not set +# CONFIG_SND_SOC_HDMI_CODEC is not set +# CONFIG_SND_SOC_ES8328 is not set +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1792A is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_SGTL5000 is not set +# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +# CONFIG_SND_SOC_SSM4567 is not set +# CONFIG_SND_SOC_STA350 is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC3X is not set +CONFIG_SND_SOC_WCD9330=y +CONFIG_SND_SOC_WCD9335=y +CONFIG_SND_SOC_WSA881X_SENSORS=y +CONFIG_SND_SOC_WSA881X=y +CONFIG_SND_SOC_WSA881X_ANALOG=y +CONFIG_SND_SOC_MSM8X16_WCD=y +CONFIG_SND_SOC_WCD9XXX=y +CONFIG_SND_SOC_WCD9XXX_V2=y +CONFIG_SND_SOC_WCD_CPE=y +CONFIG_AUDIO_EXT_CLK=y +CONFIG_SND_SOC_WCD_MBHC=y +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +# CONFIG_SND_SOC_WM8580 is not set +# CONFIG_SND_SOC_WM8711 is not set +# CONFIG_SND_SOC_WM8728 is not set +# CONFIG_SND_SOC_WM8731 is not set +# CONFIG_SND_SOC_WM8737 is not set +# CONFIG_SND_SOC_WM8741 is not set +# CONFIG_SND_SOC_WM8750 is not set +# CONFIG_SND_SOC_WM8753 is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8776 is not set +# CONFIG_SND_SOC_WM8804 is not set +# CONFIG_SND_SOC_WM8903 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_TPA6130A2 is not set +CONFIG_SND_SOC_MSM_STUB=y +CONFIG_SND_SOC_MSM_HDMI_DBA_CODEC_RX=y +# CONFIG_SND_SOC_MAX98927 is not set +# CONFIG_SND_SIMPLE_CARD is not set +# CONFIG_SOUND_PRIME is not set + +# +# HID support +# +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CP2112 is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +CONFIG_HID_ELECOM=y +# CONFIG_HID_ELO is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_GT683R is not set +# CONFIG_HID_HUION is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO is not set +# CONFIG_HID_LOGITECH is not set +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MONTEREY is not set +CONFIG_HID_MULTITOUCH=y +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WIIMOTE is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y + +# +# I2C HID support +# +# CONFIG_I2C_HID is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_FSM is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PCI=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_PCI=y +CONFIG_USB_EHCI_MSM=y +CONFIG_USB_EHCI_MSM_HSIC=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FUSBH200_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=y +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +# CONFIG_USB_STORAGE_ONETOUCH is not set +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_USB_MUSB_HDRC is not set +CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_HOST is not set +# CONFIG_USB_DWC3_GADGET is not set +CONFIG_USB_DWC3_DUAL_ROLE=y + +# +# Platform Glue Driver Support +# +CONFIG_USB_DWC3_PCI=y +CONFIG_USB_DWC3_MSM=y + +# +# Debugging features +# +# CONFIG_USB_DWC3_DEBUG is not set +# CONFIG_DWC3_HOST_USB3_LPM_ENABLE is not set +# CONFIG_USB_DWC2 is not set +# CONFIG_USB_CHIPIDEA is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=y +# CONFIG_USB_SERIAL_CONSOLE is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_SIMPLE is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_F81232 is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_METRO is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MXUPORT is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_XSENS_MT is not set +# CONFIG_USB_SERIAL_WISHBONE is not set +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_QT2 is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +CONFIG_USB_EHSET_TEST_FIXTURE=y +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_MICROCHIP_USB2533 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_QTI_KS_BRIDGE is not set + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +# CONFIG_USB_OTG_WAKELOCK is not set +CONFIG_NOP_USB_XCEIV=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +CONFIG_USB_MSM_OTG=y +CONFIG_USB_MSM_HSPHY=y +# CONFIG_USB_MSM_SSPHY is not set +CONFIG_USB_MSM_SSPHY_QMP=y +CONFIG_MSM_QUSB_PHY=y +# CONFIG_USB_ULPI is not set +CONFIG_DUAL_ROLE_USB_INTF=y +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_AMD5536UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET2280 is not set +# CONFIG_USB_GOKU is not set +# CONFIG_USB_EG20T is not set +# CONFIG_USB_GADGET_XILINX is not set +CONFIG_USB_CI13XXX_MSM=y +# CONFIG_USB_CI13XXX_MSM_HSIC is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=y +CONFIG_USB_F_ACM=y +CONFIG_USB_U_SERIAL=y +CONFIG_USB_F_SERIAL=y +CONFIG_USB_F_NCM=y +CONFIG_USB_F_ECM=y +CONFIG_USB_F_MASS_STORAGE=y +CONFIG_USB_F_FS=y +CONFIG_USB_F_UAC1=y +CONFIG_USB_F_UAC2=y +CONFIG_USB_F_UVC=y +CONFIG_USB_F_AUDIO_SRC=y +# CONFIG_USB_CONFIGFS is not set +CONFIG_USB_G_ANDROID=y +# CONFIG_USB_ANDROID_RNDIS_DWORD_ALIGNED is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set +# CONFIG_USB_LED_TRIG is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_PERF_PROFILING=y +CONFIG_MMC_CLKGATE=y +# CONFIG_MMC_RING_BUFFER is not set +# CONFIG_MMC_EMBEDDED_SDIO is not set +CONFIG_MMC_PARANOID_SD_INIT=y + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_SDHCI=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +CONFIG_MMC_SDHCI_MSM=y +CONFIG_MMC_SDHCI_MSM_ICE=y +# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +CONFIG_MMC_CQ_HCI=y +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_INTEL_SS4200 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set +# CONFIG_LEDS_LM355x is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +CONFIG_LEDS_QPNP=y +CONFIG_LEDS_QPNP_FLASH=y +CONFIG_LEDS_QPNP_WLED=y +CONFIG_LEDS_AW2013=y + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_CPU is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +CONFIG_SWITCH=y +# CONFIG_SWITCH_GPIO is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_EDAC_SUPPORT=y +CONFIG_EDAC=y +CONFIG_EDAC_LEGACY_SYSFS=y +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=y +CONFIG_EDAC_CORTEX_ARM64=y +# CONFIG_EDAC_CORTEX_ARM64_PANIC_ON_CE is not set +CONFIG_EDAC_CORTEX_ARM64_DBE_IRQ_ONLY=y +CONFIG_EDAC_CORTEX_ARM64_PANIC_ON_UE=y +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_MCP795 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_EFI is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_SNVS is not set +CONFIG_RTC_DRV_QPNP=y +# CONFIG_RTC_DRV_XGENE is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +# CONFIG_ESOC is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +# CONFIG_AMBA_PL08X is not set +# CONFIG_DW_DMAC_CORE is not set +# CONFIG_DW_DMAC is not set +# CONFIG_DW_DMAC_PCI is not set +CONFIG_QCOM_SPS_DMA=y +# CONFIG_PL330_DMA is not set +# CONFIG_FSL_EDMA is not set +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +CONFIG_UIO=y +# CONFIG_UIO_CIF is not set +# CONFIG_UIO_PDRV_GENIRQ is not set +# CONFIG_UIO_DMEM_GENIRQ is not set +# CONFIG_UIO_AEC is not set +# CONFIG_UIO_SERCOS3 is not set +# CONFIG_UIO_PCI_GENERIC is not set +# CONFIG_UIO_NETX is not set +# CONFIG_UIO_MF624 is not set +CONFIG_UIO_MSM_SHAREDMEM=y +# CONFIG_VFIO is not set +# CONFIG_VIRT_DRIVERS is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_PCI is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_PRISM2_USB is not set +# CONFIG_COMEDI is not set +# CONFIG_RTL8192U is not set +# CONFIG_RTLLIB is not set +# CONFIG_R8712U is not set +# CONFIG_R8188EU is not set +# CONFIG_R8723AU is not set +# CONFIG_RTS5208 is not set +# CONFIG_LINE6_USB is not set +# CONFIG_VT6655 is not set +# CONFIG_FB_XGI is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder,vndbinder" +CONFIG_ASHMEM=y +# CONFIG_ANDROID_LOGGER is not set +CONFIG_ANDROID_TIMED_OUTPUT=y +CONFIG_ANDROID_TIMED_GPIO=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_ONESHOT_SYNC=y +# CONFIG_ONESHOT_SYNC_USER is not set +CONFIG_ION=y +# CONFIG_ION_TEST is not set +# CONFIG_ION_DUMMY is not set +CONFIG_ION_MSM=y +# CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS is not set +# CONFIG_FIQ_DEBUGGER is not set +# CONFIG_FIQ_WATCHDOG is not set +# CONFIG_USB_WPAN_HCD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_DGNC is not set +# CONFIG_DGAP is not set +# CONFIG_GS_FPGABOOT is not set + +# +# Qualcomm Atheros Prima WLAN module +# +# CONFIG_PRIMA_WLAN is not set +CONFIG_PRONTO_WLAN=y +# CONFIG_PRIMA_WLAN_BTAMP is not set +CONFIG_PRIMA_WLAN_LFR=y +CONFIG_PRIMA_WLAN_OKC=y +CONFIG_PRIMA_WLAN_11AC_HIGH_TP=y +CONFIG_WLAN_FEATURE_11W=y +CONFIG_QCOM_VOWIFI_11R=y +CONFIG_ENABLE_LINUX_REG=y +CONFIG_WLAN_OFFLOAD_PACKETS=y +CONFIG_QCOM_TDLS=y +# CONFIG_GOLDFISH is not set + +# +# Qualcomm MSM specific device drivers +# +CONFIG_MSM_AVTIMER=y +CONFIG_MSM_BUS_SCALING=y +CONFIG_BUS_TOPOLOGY_ADHOC=y +# CONFIG_DEBUG_BUS_VOTER is not set +CONFIG_QPNP_POWER_ON=y +CONFIG_QPNP_REVID=y +CONFIG_QPNP_COINCELL=y +CONFIG_SPS=y +# CONFIG_EP_PCIE is not set +CONFIG_USB_BAM=y +# CONFIG_SPS_SUPPORT_BAMDMA is not set +CONFIG_SPS_SUPPORT_NDP_BAM=y +# CONFIG_QPNP_VIBRATOR is not set +CONFIG_IPA=y +# CONFIG_IPA3 is not set +# CONFIG_GSI is not set +CONFIG_RMNET_IPA=y +# CONFIG_SSM is not set +# CONFIG_MSM_MHI is not set +# CONFIG_PFT is not set +# CONFIG_I2C_MSM_PROF_DBG is not set +# CONFIG_SEEMP_CORE is not set +CONFIG_QPNP_HAPTIC=y +# CONFIG_GPIO_USB_DETECT is not set +CONFIG_MSM_11AD=y +# CONFIG_BW_MONITOR is not set +CONFIG_MSM_SPMI=y +CONFIG_MSM_SPMI_PMIC_ARB=y +CONFIG_MSM_QPNP_INT=y +# CONFIG_MSM_SPMI_DEBUGFS_RO is not set +CONFIG_MACH_XIAOMI_MSM8953=y + +# +# Xiaomi board selection +# +CONFIG_MACH_XIAOMI_MIDO=y +# CONFIG_MACH_XIAOMI_TISSOT is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_MSM_CLK_CONTROLLER_V2=y +CONFIG_MSM_MDSS_PLL=y +CONFIG_HWSPINLOCK=y + +# +# Hardware Spinlock drivers +# +CONFIG_REMOTE_SPINLOCK_MSM=y + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set +# CONFIG_ATMEL_PIT is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_EM_TIMER_STI is not set +# CONFIG_CLKSRC_VERSATILE is not set +# CONFIG_MAILBOX is not set +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +CONFIG_IOMMU_IO_PGTABLE=y +CONFIG_IOMMU_IO_PGTABLE_LPAE=y +# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set +# CONFIG_IOMMU_IO_PGTABLE_FAST is not set +CONFIG_OF_IOMMU=y +CONFIG_MSM_IOMMU=y +CONFIG_MSM_IOMMU_V1=y +# CONFIG_IOMMU_LPAE is not set +# CONFIG_IOMMU_AARCH64 is not set +# CONFIG_MSM_IOMMU_VBIF_CHECK is not set +# CONFIG_IOMMU_NON_SECURE is not set +# CONFIG_IOMMU_FORCE_4K_MAPPINGS is not set +CONFIG_ARM_SMMU=y +CONFIG_IOMMU_DEBUG=y +# CONFIG_IOMMU_DEBUG_TRACKING is not set +CONFIG_IOMMU_TESTS=y + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# + +# +# SOC (System On Chip) specific Drivers +# +# CONFIG_MSM_HAB is not set +CONFIG_CP_ACCESS64=y +# CONFIG_MSM_INRUSH_CURRENT_MITIGATION is not set +CONFIG_MSM_QDSP6_APRV2=y +# CONFIG_MSM_GLADIATOR_ERP is not set +# CONFIG_MSM_GLADIATOR_ERP_V2 is not set +# CONFIG_MSM_QDSP6_APRV3 is not set +# CONFIG_MSM_QDSP6_APRV2_GLINK is not set +# CONFIG_MSM_QDSP6_APRV3_GLINK is not set +CONFIG_MSM_ADSP_LOADER=y +# CONFIG_MSM_MEMORY_DUMP is not set +CONFIG_MSM_MEMORY_DUMP_V2=y +# CONFIG_MSM_DEBUG_LAR_UNLOCK is not set +# CONFIG_MSM_JTAG is not set +# CONFIG_MSM_JTAG_MM is not set +# CONFIG_MSM_JTAGV8 is not set +CONFIG_MSM_BOOT_STATS=y +# CONFIG_MSM_BOOT_TIME_MARKER is not set +CONFIG_MSM_CPUSS_DUMP=y +CONFIG_MSM_COMMON_LOG=y +CONFIG_MSM_DDR_HEALTH=y +# CONFIG_MSM_HYP_DEBUG is not set +CONFIG_MSM_WATCHDOG_V2=y +CONFIG_MSM_FORCE_WDOG_BITE_ON_PANIC=y +# CONFIG_MSM_CORE_HANG_DETECT is not set +# CONFIG_MSM_GLADIATOR_HANG_DETECT is not set +CONFIG_MSM_CPU_PWR_CTL=y +# CONFIG_MSM_L2_IA_DEBUG is not set +CONFIG_MSM_RPM_SMD=y +CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y +CONFIG_MSM_RPM_LOG=y +CONFIG_MSM_RPM_STATS_LOG=y +CONFIG_MSM_RUN_QUEUE_STATS=y +CONFIG_MSM_SCM=y +CONFIG_MSM_SCM_XPU=y +CONFIG_MSM_XPU_ERR_FATAL=y +# CONFIG_MSM_XPU_ERR_NONFATAL is not set +# CONFIG_MSM_SCM_ERRATA is not set +# CONFIG_MSM_PFE_WA is not set +CONFIG_MSM_MPM_OF=y +CONFIG_MSM_SMEM=y +# CONFIG_QPNP_PBS is not set +CONFIG_MSM_SMD=y +CONFIG_MSM_SMD_DEBUG=y +CONFIG_MSM_GLINK=y +CONFIG_MSM_GLINK_LOOPBACK_SERVER=y +CONFIG_MSM_GLINK_SMD_XPRT=y +CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y +CONFIG_MSM_SMEM_LOGGING=y +CONFIG_MSM_SMP2P=y +CONFIG_MSM_SMP2P_TEST=y +CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y +CONFIG_MSM_QMI_INTERFACE=y +# CONFIG_MSM_DCC is not set +# CONFIG_MSM_HVC is not set +CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y +CONFIG_MSM_EVENT_TIMER=y +# CONFIG_MSM_SYSMON_GLINK_COMM is not set +# CONFIG_MSM_IPC_ROUTER_GLINK_XPRT is not set +# CONFIG_MSM_SYSTEM_HEALTH_MONITOR is not set +# CONFIG_MSM_GLINK_PKT is not set +CONFIG_MSM_TZ_SMMU=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_SYSMON_COMM=y +CONFIG_MSM_PIL=y +CONFIG_MSM_PIL_SSR_GENERIC=y +# CONFIG_MSM_PIL_SSR_BG is not set +CONFIG_MSM_PIL_MSS_QDSP6V5=y +# CONFIG_MSM_SHARED_HEAP_ACCESS is not set +# CONFIG_TRACER_PKT is not set +CONFIG_MSM_SECURE_BUFFER=y +CONFIG_ICNSS=y +CONFIG_MSM_BAM_DMUX=y +CONFIG_MSM_PERFORMANCE=y +CONFIG_MSM_PERFORMANCE_HOTPLUG_ON=y +# CONFIG_MSM_POWER is not set +# CONFIG_MSM_SERVICE_LOCATOR is not set +# CONFIG_MSM_QBT1000 is not set +# CONFIG_MSM_BGCOM is not set +# CONFIG_MSM_REMOTEQDSS is not set +# CONFIG_QCOM_SMCINVOKE is not set +# CONFIG_QCOM_EARLY_RANDOM is not set +# CONFIG_WCD_DSP_GLINK is not set +CONFIG_SERIAL_NUM=y +CONFIG_MEM_SHARE_QMI_SERVICE=y +# CONFIG_SOC_TI is not set +CONFIG_PM_DEVFREQ=y + +# +# DEVFREQ Governors +# +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_POWERSAVE=y +CONFIG_DEVFREQ_GOV_USERSPACE=y +CONFIG_DEVFREQ_GOV_CPUFREQ=y +CONFIG_DEVFREQ_GOV_MSM_ADRENO_TZ=y +CONFIG_MSM_BIMC_BWMON=y +CONFIG_DEVFREQ_GOV_MSM_GPUBW_MON=y +# CONFIG_ARMBW_HWMON is not set +CONFIG_ARM_MEMLAT_MON=y +CONFIG_MSMCCI_HWMON=y +CONFIG_MSM_M4M_HWMON=y +CONFIG_DEVFREQ_GOV_MSM_BW_HWMON=y +CONFIG_DEVFREQ_GOV_MSM_CACHE_HWMON=y +CONFIG_DEVFREQ_GOV_SPDM_HYP=y +CONFIG_DEVFREQ_GOV_MEMLAT=y + +# +# DEVFREQ Drivers +# +CONFIG_DEVFREQ_SIMPLE_DEV=y +CONFIG_MSM_DEVFREQ_DEVBW=y +CONFIG_SPDM_SCM=y +CONFIG_DEVFREQ_SPDM=y +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +# CONFIG_IIO is not set +# CONFIG_VME_BUS is not set +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +# CONFIG_PWM_FSL_FTM is not set +# CONFIG_PWM_PCA9685 is not set +CONFIG_PWM_QPNP=y +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_PANIC_HANDLER=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ACL=y +# CONFIG_ARM_GIC_V3_NO_ACCESS_CONTROL is not set +CONFIG_MSM_SHOW_RESUME_IRQ=y +CONFIG_MSM_IRQ=y +# CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set +# CONFIG_FMC is not set +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_EVENT=y +CONFIG_HAVE_CORESIGHT_SINK=y +CONFIG_CORESIGHT_FUSE=y +CONFIG_CORESIGHT_CTI=y +CONFIG_CORESIGHT_CTI_SAVE_DISABLE=y +CONFIG_CORESIGHT_CSR=y +CONFIG_CORESIGHT_TMC=y +CONFIG_CORESIGHT_TPIU=y +CONFIG_CORESIGHT_FUNNEL=y +CONFIG_CORESIGHT_REPLICATOR=y +# CONFIG_CORESIGHT_TPDA is not set +# CONFIG_CORESIGHT_TPDM is not set +# CONFIG_CORESIGHT_DBGUI is not set +CONFIG_CORESIGHT_STM=y +# CONFIG_CORESIGHT_STM_DEFAULT_ENABLE is not set +CONFIG_CORESIGHT_HWEVENT=y +# CONFIG_CORESIGHT_ETM is not set +# CONFIG_CORESIGHT_ETMV4 is not set +# CONFIG_CORESIGHT_REMOTE_ETM is not set +# CONFIG_CORESIGHT_QPDI is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_PHY_XGENE is not set +CONFIG_PHY_QCOM_UFS=y +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set +CONFIG_RAS=y +# CONFIG_THUNDERBOLT is not set +# CONFIG_SENSORS is not set +CONFIG_SENSORS_SSC=y + +# +# Firmware Drivers +# +# CONFIG_FIRMWARE_MEMMAP is not set +CONFIG_DMIID=y +# CONFIG_DMI_SYSFS is not set + +# +# EFI (Extensible Firmware Interface) Support +# +# CONFIG_EFI_VARS is not set +CONFIG_EFI_PARAMS_FROM_FDT=y +CONFIG_EFI_RUNTIME_WRAPPERS=y +CONFIG_EFI_ARMSTUB=y +CONFIG_MSM_TZ_LOG=y +# CONFIG_BIF is not set + +# +# Firmware Drivers +# + +# +# EFI (Extensible Firmware Interface) Support +# + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT4_FS=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +CONFIG_FS_ENCRYPTION=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +# CONFIG_PRINT_QUOTA_WARNING is not set +# CONFIG_QUOTA_DEBUG is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set +# CONFIG_OVERLAY_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=y +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +CONFIG_ECRYPT_FS=y +# CONFIG_ECRYPT_FS_MESSAGING is not set +CONFIG_SDCARD_FS=y +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +# CONFIG_PSTORE_PMSG is not set +CONFIG_PSTORE_FTRACE=y +CONFIG_PSTORE_RAM=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_F2FS_FS=y +CONFIG_F2FS_STAT_FS=y +CONFIG_F2FS_FS_XATTR=y +CONFIG_F2FS_FS_POSIX_ACL=y +CONFIG_F2FS_FS_SECURITY=y +# CONFIG_F2FS_CHECK_FS is not set +CONFIG_F2FS_FS_ENCRYPTION=y +# CONFIG_F2FS_IO_TRACE is not set +# CONFIG_F2FS_FAULT_INJECTION is not set +# CONFIG_EFIVAR_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_CEPH_FS is not set +CONFIG_CIFS=y +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +# CONFIG_CIFS_UPCALL is not set +# CONFIG_CIFS_XATTR is not set +CONFIG_CIFS_DEBUG=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_DFS_UPCALL is not set +# CONFIG_CIFS_SMB2 is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +CONFIG_NLS_CODEPAGE_936=y +CONFIG_NLS_CODEPAGE_950=y +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set +# CONFIG_FILE_TABLE_DEBUG is not set +# CONFIG_VIRTUALIZATION is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_LOG_BUF_MAGIC is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_DYNAMIC_DEBUG is not set + +# +# Compile-time checks and compiler options +# +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_INFO_SPLIT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_HAVE_ARCH_KASAN=y +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=5 +CONFIG_PANIC_ON_RECURSIVE_FAULT=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_PANIC_ON_SCHED_BUG is not set +# CONFIG_PANIC_ON_RT_THROTTLING is not set +CONFIG_SCHEDSTATS=y +# CONFIG_SCHED_STACK_END_CHECK is not set +CONFIG_TIMER_STATS=y +CONFIG_DEBUG_PREEMPT=y + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_HAVE_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_CPU_STALL_VERBOSE=y +# CONFIG_RCU_CPU_STALL_INFO is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACE_CLOCK=y +CONFIG_RING_BUFFER=y +CONFIG_EVENT_TRACING=y +CONFIG_CONTEXT_SWITCH_TRACER=y +# CONFIG_MSM_RTB is not set +CONFIG_IPC_LOGGING=y +CONFIG_TRACING=y +CONFIG_GENERIC_TRACER=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +CONFIG_FUNCTION_TRACER=y +CONFIG_FUNCTION_GRAPH_TRACER=y +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_FTRACE_SYSCALLS is not set +# CONFIG_TRACER_SNAPSHOT is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_PROBE_EVENTS is not set +CONFIG_DYNAMIC_FTRACE=y +# CONFIG_FUNCTION_PROFILER is not set +CONFIG_CPU_FREQ_SWITCH_PROFILER=y +CONFIG_FTRACE_MCOUNT_RECORD=y +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_TRACEPOINT_BENCHMARK is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set +# CONFIG_RING_BUFFER_STARTUP_TEST is not set + +# +# Runtime Testing +# +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_PANIC_ON_DATA_CORRUPTION is not set +# CONFIG_MEMTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y +# CONFIG_UBSAN is not set +# CONFIG_ARM64_PTDUMP is not set +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set +# CONFIG_FORCE_PAGES is not set +# CONFIG_FREE_PAGES_RDONLY is not set +CONFIG_DEBUG_RODATA=y +# CONFIG_DEBUG_ALIGN_RODATA is not set +# CONFIG_CORESIGHT_LINKS_AND_SINKS is not set +# CONFIG_CORESIGHT_SOURCE_ETM4X is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +CONFIG_ENCRYPTED_KEYS=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set + +# +# Qualcomm Technologies, Inc Per File Encryption security device drivers +# +# CONFIG_PFK is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y +CONFIG_SECURITY=y +# CONFIG_SECURITYFS is not set +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +# CONFIG_SECURITY_PATH is not set +CONFIG_LSM_MMAP_MIN_ADDR=4096 +CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y +CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y +CONFIG_HARDENED_USERCOPY=y +# CONFIG_HARDENED_USERCOPY_PAGESPAN is not set +CONFIG_SECURITY_SELINUX=y +# CONFIG_SECURITY_SELINUX_BOOTPARAM is not set +# CONFIG_SECURITY_SELINUX_DISABLE is not set +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set +# CONFIG_SECURITY_SMACK is not set +# CONFIG_SECURITY_TOMOYO is not set +# CONFIG_SECURITY_APPARMOR is not set +# CONFIG_SECURITY_YAMA is not set +CONFIG_INTEGRITY=y +# CONFIG_INTEGRITY_SIGNATURE is not set +CONFIG_INTEGRITY_AUDIT=y +# CONFIG_IMA is not set +# CONFIG_EVM is not set +CONFIG_DEFAULT_SECURITY_SELINUX=y +# CONFIG_DEFAULT_SECURITY_DAC is not set +CONFIG_DEFAULT_SECURITY="selinux" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_USER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=y +# CONFIG_CRYPTO_MCRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_ABLK_HELPER=y + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +CONFIG_CRYPTO_SEQIV=y + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_CTS=y +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +CONFIG_CRYPTO_XTS=y + +# +# Hash modes +# +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=y +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRC32=y +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=y +# CONFIG_CRYPTO_DRBG_MENU is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_DEV_QCE50=y +# CONFIG_FIPS_ENABLE is not set +CONFIG_CRYPTO_DEV_QCRYPTO=y +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y +CONFIG_CRYPTO_DEV_QCEDEV=y +CONFIG_CRYPTO_DEV_OTA_CRYPTO=y +CONFIG_CRYPTO_DEV_QCOM_ICE=y +# CONFIG_CRYPTO_DEV_CCP is not set +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +CONFIG_PUBLIC_KEY_ALGO_RSA=y +CONFIG_X509_CERTIFICATE_PARSER=y +# CONFIG_PKCS7_MESSAGE_PARSER is not set +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +CONFIG_BINARY_PRINTF=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +CONFIG_AUDIT_GENERIC=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_AUDIT_COMPAT_GENERIC=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=y +CONFIG_TEXTSEARCH_BM=y +CONFIG_TEXTSEARCH_FSM=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +# CONFIG_AVERAGE is not set +CONFIG_CLZ_TAB=y +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +CONFIG_MPILIB=y +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +CONFIG_UCS2_STRING=y +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_QMI_ENCDEC=y +# CONFIG_QMI_ENCDEC_DEBUG is not set +# CONFIG_STRICT_MEMORY_RWX is not set From 335854c4796098a1e77a6d1c4c67d44a8d99a581 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Fri, 23 Mar 2018 21:02:09 +0530 Subject: [PATCH 256/508] arch: arm64: configs: Add initial tissot defconfig --- arch/arm64/configs/tissot_defconfig | 4518 +++++++++++++++++++++++++++ 1 file changed, 4518 insertions(+) create mode 100644 arch/arm64/configs/tissot_defconfig diff --git a/arch/arm64/configs/tissot_defconfig b/arch/arm64/configs/tissot_defconfig new file mode 100644 index 0000000000000..ae2e94aacad7e --- /dev/null +++ b/arch/arm64/configs/tissot_defconfig @@ -0,0 +1,4518 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm64 3.18.71 Kernel Configuration +# +CONFIG_ARM64=y +CONFIG_64BIT=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_MMU=y +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_HAVE_GENERIC_RCU_GUP=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_ARM64_DMA_USE_IOMMU=y +CONFIG_ARM64_DMA_IOMMU_ALIGNMENT=8 +CONFIG_SMP=y +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=3 +# CONFIG_MSM_GVM_QUIN is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="-perf" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +# CONFIG_FHANDLE is not set +# CONFIG_USELIB is not set +CONFIG_AUDIT=y +CONFIG_HAVE_ARCH_AUDITSYSCALL=y +# CONFIG_AUDITSYSCALL is not set + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_HANDLE_DOMAIN_IRQ=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +# CONFIG_TICK_CPU_ACCOUNTING is not set +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +CONFIG_IRQ_TIME_ACCOUNTING=y +# CONFIG_SCHED_WALT is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_TASKSTATS=y +# CONFIG_TASK_DELAY_ACCT is not set +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y + +# +# RCU Subsystem +# +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +# CONFIG_TASKS_RCU is not set +CONFIG_RCU_STALL_COMMON=y +# CONFIG_RCU_USER_QS is not set +CONFIG_RCU_FANOUT=64 +CONFIG_RCU_FANOUT_LEAF=16 +# CONFIG_RCU_FANOUT_EXACT is not set +CONFIG_RCU_FAST_NO_HZ=y +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=1 +CONFIG_RCU_BOOST_DELAY=500 +CONFIG_RCU_NOCB_CPU=y +# CONFIG_RCU_NOCB_CPU_NONE is not set +# CONFIG_RCU_NOCB_CPU_ZERO is not set +CONFIG_RCU_NOCB_CPU_ALL=y +CONFIG_BUILD_BIN2C=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_CONSOLE_FLUSH_ON_HOTPLUG is not set +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_FREEZER=y +# CONFIG_CGROUP_DEVICE is not set +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +# CONFIG_MEMCG is not set +# CONFIG_CGROUP_PERF is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_CFS_BANDWIDTH is not set +CONFIG_RT_GROUP_SCHED=y +# CONFIG_BLK_CGROUP is not set +CONFIG_SCHED_HMP=y +# CONFIG_SCHED_HMP_CSTATE_AWARE is not set +# CONFIG_SCHED_CORE_CTL is not set +# CONFIG_SCHED_QHMP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SCHED_TUNE is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_UID16=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +# CONFIG_BPF_SYSCALL is not set +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_ADVISE_SYSCALLS=y +CONFIG_PCI_QUIRKS=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLUB_CPU_PARTIAL=y +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y +# CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_RCU_TABLE_FREE=y +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP_FILTER=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR_NONE is not set +# CONFIG_CC_STACKPROTECTOR_REGULAR is not set +CONFIG_CC_STACKPROTECTOR_STRONG=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +# CONFIG_MODULES is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_CMDLINE_PARSER is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_CMDLINE_PARTITION is not set +CONFIG_BLOCK_COMPAT=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_TEST is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_ASN1=y +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# Platform selection +# +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_XGENE is not set +CONFIG_ARCH_MSM=y +# CONFIG_ARCH_MSM8916 is not set +# CONFIG_ARCH_MSM8917 is not set +# CONFIG_ARCH_MSM8920 is not set +# CONFIG_ARCH_MSM8940 is not set +CONFIG_ARCH_MSM8953=y +# CONFIG_ARCH_SDM450 is not set +# CONFIG_ARCH_MSM8937 is not set +# CONFIG_ARCH_MSM8996 is not set +# CONFIG_ARCH_MSMCOBALT is not set + +# +# Bus support +# +CONFIG_ARM_AMBA=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_SYSCALL=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set +CONFIG_PCI_MSM=y +CONFIG_PCI_LABEL=y + +# +# PCI host controller drivers +# +# CONFIG_PCI_HOST_GENERIC is not set +# CONFIG_PCIEPORTBUS is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# Kernel Features +# + +# +# ARM errata workarounds via the alternatives framework +# +CONFIG_ARM64_ERRATUM_826319=y +CONFIG_ARM64_ERRATUM_827319=y +CONFIG_ARM64_ERRATUM_824069=y +CONFIG_ARM64_ERRATUM_819472=y +CONFIG_ARM64_ERRATUM_832075=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_64K_PAGES is not set +# CONFIG_ARM64_DCACHE_DISABLE is not set +# CONFIG_ARM64_ICACHE_DISABLE is not set +CONFIG_ARCH_MSM8953_SOC_SETTINGS=y +CONFIG_ARM64_VA_BITS_39=y +CONFIG_ARM64_VA_BITS=39 +# CONFIG_CPU_BIG_ENDIAN is not set +# CONFIG_ARM64_SEV_IN_LOCK_UNLOCK is not set +CONFIG_SCHED_MC=y +# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=8 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_NR_GPIO=1024 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ=100 +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HW_PERF_EVENTS=y +# CONFIG_PERF_EVENTS_USERMODE is not set +# CONFIG_PERF_EVENTS_RESET_PMU_DEBUGFS is not set +# CONFIG_ARM64_REG_REBALANCE_ON_CTX_SW is not set +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +CONFIG_MEMORY_ISOLATION=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_TRANSPARENT_HUGEPAGE is not set +CONFIG_CLEANCACHE=y +# CONFIG_FRONTSWAP is not set +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set +# CONFIG_CMA_DEBUGFS is not set +CONFIG_CMA_AREAS=7 +# CONFIG_ZPOOL is not set +CONFIG_ZBUD=y +CONFIG_ZSMALLOC=y +# CONFIG_PGTABLE_MAPPING is not set +# CONFIG_ZSMALLOC_STAT is not set +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_ZCACHE=y +# CONFIG_BALANCE_ANON_FILE_RECLAIM is not set +CONFIG_KSWAPD_CPU_AFFINITY_MASK="" +# CONFIG_FORCE_ALLOC_FROM_DMA_ZONE is not set +CONFIG_PROCESS_RECLAIM=y +CONFIG_SECCOMP=y +# CONFIG_XEN is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_HARDEN_BRANCH_PREDICTOR=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +CONFIG_ARM64_SW_TTBR0_PAN=y + +# +# ARMv8.1 architectural features +# +CONFIG_ARM64_PAN=y +CONFIG_ARM64_UAO=y + +# +# Boot options +# +CONFIG_CMDLINE="" +CONFIG_EFI_STUB=y +CONFIG_EFI=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="" +CONFIG_BUILD_ARM64_KERNEL_COMPRESSION_GZIP=y +# CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL is not set +CONFIG_DMI=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y +CONFIG_COMPAT=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_WAKELOCK=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_OPP=y +CONFIG_PM_CLK=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_CPU_PM=y +CONFIG_SUSPEND_TIME=y +# CONFIG_DEDUCE_WAKEUP_REASONS is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM64_CPU_SUSPEND=y + +# +# CPU Power Management +# + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y + +# +# ARM64 CPU Idle Drivers +# +# CONFIG_ARM64_CPUIDLE is not set +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_SCHED_FREQ_INPUT=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHED is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +# CONFIG_CPU_FREQ_GOV_SCHED is not set + +# +# CPU frequency scaling drivers +# +# CONFIG_CPUFREQ_DT is not set +# CONFIG_CPU_BOOST is not set + +# +# ARM CPU frequency scaling drivers +# +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +CONFIG_CPU_FREQ_MSM=y +CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y +# CONFIG_DISABLE_NET_SKB_FRAG_CACHE is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +CONFIG_XFRM_STATISTICS=y +CONFIG_XFRM_IPCOMP=y +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_ROUTE_MULTIPATH is not set +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=y +# CONFIG_IP_MROUTE is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_NET_IPVTI is not set +CONFIG_NET_UDP_TUNNEL=y +# CONFIG_NET_FOU is not set +# CONFIG_GENEVE is not set +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +CONFIG_INET_DIAG_DESTROY=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_TUNNEL=y +CONFIG_INET6_TUNNEL=y +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_GRE is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETLABEL is not set +CONFIG_ANDROID_PARANOID_NETWORK=y +CONFIG_NET_ACTIVITY_STATS=y +CONFIG_NETWORK_SECMARK=y +# CONFIG_NET_PTP_CLASSIFY is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=y +# CONFIG_NETFILTER_NETLINK_ACCT is not set +CONFIG_NETFILTER_NETLINK_QUEUE=y +CONFIG_NETFILTER_NETLINK_LOG=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_LOG_COMMON=y +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +# CONFIG_NF_CONNTRACK_ZONES is not set +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +CONFIG_NF_CT_PROTO_DCCP=y +CONFIG_NF_CT_PROTO_GRE=y +CONFIG_NF_CT_PROTO_SCTP=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_BROADCAST=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +# CONFIG_NF_CONNTRACK_SNMP is not set +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +# CONFIG_NF_CONNTRACK_SIP is not set +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set +CONFIG_NF_NAT=y +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PROTO_DCCP=y +CONFIG_NF_NAT_PROTO_UDPLITE=y +CONFIG_NF_NAT_PROTO_SCTP=y +CONFIG_NF_NAT_AMANDA=y +CONFIG_NF_NAT_FTP=y +CONFIG_NF_NAT_IRC=y +# CONFIG_NF_NAT_SIP is not set +CONFIG_NF_NAT_TFTP=y +# CONFIG_NF_TABLES is not set +CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=y +CONFIG_NETFILTER_XT_CONNMARK=y + +# +# Xtables targets +# +# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set +# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_CT=y +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_HL is not set +# CONFIG_NETFILTER_XT_TARGET_HMARK is not set +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y +# CONFIG_NETFILTER_XT_TARGET_LED is not set +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_NAT=y +CONFIG_NETFILTER_XT_TARGET_NETMAP=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +CONFIG_NETFILTER_XT_TARGET_REDIRECT=y +CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set + +# +# Xtables matches +# +# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_BPF is not set +# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ECN=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_HL=y +# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_L2TP=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +CONFIG_NETFILTER_XT_MATCH_POLICY=y +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +# CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +# CONFIG_NF_LOG_ARP is not set +CONFIG_NF_LOG_IPV4=y +CONFIG_NF_REJECT_IPV4=y +CONFIG_NF_NAT_IPV4=y +CONFIG_NF_NAT_MASQUERADE_IPV4=y +CONFIG_NF_NAT_PROTO_GRE=y +CONFIG_NF_NAT_PPTP=y +CONFIG_NF_NAT_H323=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +# CONFIG_IP_NF_TARGET_SYNPROXY is not set +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NATTYPE_MODULE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_TTL is not set +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_SECURITY=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_NF_REJECT_IPV6=y +CONFIG_NF_LOG_IPV6=y +# CONFIG_NF_NAT_IPV6 is not set +CONFIG_IP6_NF_IPTABLES=y +# CONFIG_IP6_NF_MATCH_AH is not set +# CONFIG_IP6_NF_MATCH_EUI64 is not set +# CONFIG_IP6_NF_MATCH_FRAG is not set +# CONFIG_IP6_NF_MATCH_OPTS is not set +# CONFIG_IP6_NF_MATCH_HL is not set +# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set +# CONFIG_IP6_NF_MATCH_MH is not set +CONFIG_IP6_NF_MATCH_RPFILTER=y +# CONFIG_IP6_NF_MATCH_RT is not set +# CONFIG_IP6_NF_TARGET_HL is not set +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +# CONFIG_IP6_NF_TARGET_SYNPROXY is not set +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +# CONFIG_IP6_NF_SECURITY is not set +# CONFIG_IP6_NF_NAT is not set +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +# CONFIG_BRIDGE_EBT_T_FILTER is not set +# CONFIG_BRIDGE_EBT_T_NAT is not set +# CONFIG_BRIDGE_EBT_802_3 is not set +# CONFIG_BRIDGE_EBT_AMONG is not set +# CONFIG_BRIDGE_EBT_ARP is not set +# CONFIG_BRIDGE_EBT_IP is not set +# CONFIG_BRIDGE_EBT_IP6 is not set +# CONFIG_BRIDGE_EBT_LIMIT is not set +# CONFIG_BRIDGE_EBT_MARK is not set +# CONFIG_BRIDGE_EBT_PKTTYPE is not set +# CONFIG_BRIDGE_EBT_STP is not set +# CONFIG_BRIDGE_EBT_VLAN is not set +# CONFIG_BRIDGE_EBT_ARPREPLY is not set +# CONFIG_BRIDGE_EBT_DNAT is not set +# CONFIG_BRIDGE_EBT_MARK_T is not set +# CONFIG_BRIDGE_EBT_REDIRECT is not set +# CONFIG_BRIDGE_EBT_SNAT is not set +# CONFIG_BRIDGE_EBT_LOG is not set +# CONFIG_BRIDGE_EBT_NFLOG is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_L2TP=y +# CONFIG_L2TP_DEBUGFS is not set +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=y +CONFIG_L2TP_ETH=y +CONFIG_STP=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_HAVE_NET_DSA=y +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_6LOWPAN is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_CBQ is not set +CONFIG_NET_SCH_HTB=y +# CONFIG_NET_SCH_HFSC is not set +CONFIG_NET_SCH_PRIO=y +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_CODEL is not set +# CONFIG_NET_SCH_FQ_CODEL is not set +# CONFIG_NET_SCH_FQ is not set +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_PIE is not set +# CONFIG_NET_SCH_INGRESS is not set +# CONFIG_NET_SCH_PLUG is not set + +# +# Classification +# +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +# CONFIG_CLS_U32_PERF is not set +CONFIG_CLS_U32_MARK=y +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +CONFIG_NET_CLS_FLOW=y +# CONFIG_NET_CLS_CGROUP is not set +# CONFIG_NET_CLS_BPF is not set +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +CONFIG_NET_CLS_ACT=y +# CONFIG_NET_ACT_POLICE is not set +# CONFIG_NET_ACT_GACT is not set +# CONFIG_NET_ACT_MIRRED is not set +# CONFIG_NET_ACT_IPT is not set +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_SIMP is not set +# CONFIG_NET_ACT_SKBEDIT is not set +# CONFIG_NET_ACT_CSUM is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +# CONFIG_DNS_RESOLVER is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_NET_MPLS_GSO is not set +# CONFIG_HSR is not set +CONFIG_RMNET_DATA=y +CONFIG_RMNET_DATA_FC=y +# CONFIG_RMNET_DATA_DEBUG_PKT is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +# CONFIG_CGROUP_NET_PRIO is not set +# CONFIG_CGROUP_NET_CLASSID is not set +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_SOCKEV_NLMCAST=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_DROP_MONITOR is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y + +# +# Bluetooth device drivers +# +# CONFIG_BT_HCIBTUSB is not set +# CONFIG_BT_HCIBTSDIO is not set +# CONFIG_BT_HCIUART is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_MRVL is not set +CONFIG_MSM_BT_POWER=y +# CONFIG_BTFM_SLIM is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +CONFIG_CFG80211_INTERNAL_REGDB=y +# CONFIG_CFG80211_WEXT is not set +# CONFIG_LIB80211 is not set +# CONFIG_MAC80211 is not set +# CONFIG_WIMAX is not set +CONFIG_RFKILL=y +CONFIG_RFKILL_PM=y +CONFIG_RFKILL_LEDS=y +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +# CONFIG_NFC_NQ is not set +CONFIG_IPC_ROUTER=y +CONFIG_IPC_ROUTER_SECURITY=y +CONFIG_HAVE_BPF_JIT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +# CONFIG_FW_CACHE is not set +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_SOC_BUS=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_SWR=y +CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_FENCE_TRACE is not set +CONFIG_DMA_CMA=y + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=16 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 + +# +# Bus devices +# +# CONFIG_ARM_CCN is not set +# CONFIG_VEXPRESS_CONFIG is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +# CONFIG_OF_UNITTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_OF_SPMI=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_OF_SLIMBUS=y +CONFIG_OF_BATTERYDATA=y +# CONFIG_OF_OVERLAY is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +CONFIG_ZRAM=y +# CONFIG_ZRAM_LZ4_COMPRESS is not set +# CONFIG_ZRAM_DEBUG is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_BLK_DEV_SKD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_BLK_DEV_RSXX is not set + +# +# Misc devices +# +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_APDS9930 is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +CONFIG_UID_STAT=y +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SRAM is not set +CONFIG_QSEECOM=y +CONFIG_HDCP_QSEECOM=y +# CONFIG_PROFILER is not set +CONFIG_UID_SYS_STATS=y +CONFIG_USB_EXT_TYPE_C_PERICOM=y +# CONFIG_USB_EXT_TYPE_C_TI is not set +# CONFIG_TI_DRV2667 is not set +# CONFIG_QPNP_MISC is not set +# CONFIG_UID_SYS_STATS_DEBUG is not set +# CONFIG_MEMORY_STATE_TIME is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_CB710_CORE is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set +CONFIG_MSM_QDSP6V2_CODECS=y +CONFIG_MSM_ULTRASOUND=y +# CONFIG_MSM_MCU_TIME_SYNC is not set + +# +# Intel MIC Bus Driver +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# +# CONFIG_GENWQE is not set +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_MVUMI is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_SCSI_ESAS2R is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_MPT3SAS is not set +CONFIG_SCSI_UFSHCD=y +# CONFIG_SCSI_UFSHCD_PCI is not set +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFS_QCOM_ICE=y +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_HAVE_PATA_PLATFORM=y +# CONFIG_ATA is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_AUTODETECT=y +CONFIG_MD_LINEAR=y +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID10 is not set +# CONFIG_MD_RAID456 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set +# CONFIG_BCACHE is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=y +# CONFIG_DM_DEBUG is not set +CONFIG_DM_BUFIO=y +CONFIG_DM_CRYPT=y +CONFIG_DM_REQ_CRYPT=y +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_THIN_PROVISIONING is not set +# CONFIG_DM_CACHE is not set +# CONFIG_DM_ERA is not set +# CONFIG_DM_MIRROR is not set +# CONFIG_DM_RAID is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set +CONFIG_DM_UEVENT=y +# CONFIG_DM_FLAKEY is not set +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE_128=y +CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE=128 +CONFIG_DM_ANDROID_VERITY=y +CONFIG_DM_VERITY_FEC=y +# CONFIG_DM_SWITCH is not set +# CONFIG_DM_LOG_WRITES is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +CONFIG_MII=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +CONFIG_DUMMY=y +# CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set +# CONFIG_IFB is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +CONFIG_TUN=y +# CONFIG_VETH is not set +# CONFIG_NLMON is not set +# CONFIG_ARCNET is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +# CONFIG_NET_DSA_MV88E6171 is not set +# CONFIG_NET_DSA_BCM_SF2 is not set +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_3COM=y +# CONFIG_VORTEX is not set +# CONFIG_TYPHOON is not set +CONFIG_NET_VENDOR_ADAPTEC=y +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_NET_VENDOR_AGERE=y +# CONFIG_ET131X is not set +CONFIG_NET_VENDOR_ALTEON=y +# CONFIG_ACENIC is not set +# CONFIG_ALTERA_TSE is not set +CONFIG_NET_VENDOR_AMD=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_PCNET32 is not set +# CONFIG_AMD_XGBE is not set +# CONFIG_NET_XGENE is not set +CONFIG_NET_VENDOR_ARC=y +# CONFIG_ARC_EMAC is not set +# CONFIG_EMAC_ROCKCHIP is not set +CONFIG_NET_VENDOR_ATHEROS=y +# CONFIG_ATL2 is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_ALX is not set +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_BCMGENET is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2X is not set +# CONFIG_SYSTEMPORT is not set +CONFIG_NET_VENDOR_BROCADE=y +# CONFIG_BNA is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +CONFIG_NET_VENDOR_CISCO=y +# CONFIG_ENIC is not set +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DEC=y +# CONFIG_NET_TULIP is not set +CONFIG_NET_VENDOR_DLINK=y +# CONFIG_DL2K is not set +# CONFIG_SUNDANCE is not set +CONFIG_NET_VENDOR_EMULEX=y +# CONFIG_BE2NET is not set +CONFIG_NET_VENDOR_EXAR=y +# CONFIG_S2IO is not set +# CONFIG_VXGE is not set +CONFIG_NET_VENDOR_HP=y +# CONFIG_HP100 is not set +CONFIG_NET_VENDOR_INTEL=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGBEVF is not set +# CONFIG_I40E is not set +# CONFIG_I40EVF is not set +# CONFIG_FM10K is not set +CONFIG_NET_VENDOR_I825XX=y +# CONFIG_IP1000 is not set +# CONFIG_JME is not set +CONFIG_NET_VENDOR_MARVELL=y +# CONFIG_MVMDIO is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLX4_EN is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_MLX5_CORE is not set +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_KSZ884X_PCI is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +# CONFIG_ECM_IPA is not set +CONFIG_RNDIS_IPA=y +# CONFIG_MSM_RMNET_BAM is not set +CONFIG_NET_VENDOR_MYRI=y +# CONFIG_MYRI10GE is not set +# CONFIG_FEALNX is not set +CONFIG_NET_VENDOR_NATSEMI=y +# CONFIG_NATSEMI is not set +# CONFIG_NS83820 is not set +CONFIG_NET_VENDOR_8390=y +# CONFIG_NE2K_PCI is not set +CONFIG_NET_VENDOR_NVIDIA=y +# CONFIG_FORCEDETH is not set +CONFIG_NET_VENDOR_OKI=y +# CONFIG_ETHOC is not set +CONFIG_NET_PACKET_ENGINE=y +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +CONFIG_NET_VENDOR_QLOGIC=y +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_QLGE is not set +# CONFIG_NETXEN_NIC is not set +CONFIG_NET_VENDOR_QUALCOMM=y +# CONFIG_QCA7000 is not set +# CONFIG_QCOM_EMAC is not set +CONFIG_NET_VENDOR_REALTEK=y +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R8169 is not set +CONFIG_NET_VENDOR_RDC=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_SAMSUNG=y +# CONFIG_SXGBE_ETH is not set +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SILAN=y +# CONFIG_SC92031 is not set +CONFIG_NET_VENDOR_SIS=y +# CONFIG_SIS900 is not set +# CONFIG_SIS190 is not set +# CONFIG_SFC is not set +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_SMC91X is not set +# CONFIG_EPIC100 is not set +# CONFIG_SMSC911X is not set +# CONFIG_SMSC9420 is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_SUN=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NIU is not set +CONFIG_NET_VENDOR_TEHUTI=y +# CONFIG_TEHUTI is not set +CONFIG_NET_VENDOR_TI=y +# CONFIG_TLAN is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AT803X_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_AMD_XGBE_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_QCA8337_SWITCH is not set +# CONFIG_NXP_TJA110X_PHY is not set +# CONFIG_MICREL_KS8995MA is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOL2TP=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_SLIP is not set +CONFIG_SLHC=y +CONFIG_USB_NET_DRIVERS=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=y +CONFIG_USB_NET_AX88179_178A=y +CONFIG_USB_NET_CDCETHER=y +# CONFIG_USB_NET_CDC_EEM is not set +CONFIG_USB_NET_CDC_NCM=y +# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set +# CONFIG_USB_NET_CDC_MBIM is not set +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SR9700 is not set +# CONFIG_USB_NET_SR9800 is not set +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_GL620A is not set +CONFIG_USB_NET_NET1080=y +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +CONFIG_USB_NET_CDC_SUBSET=y +# CONFIG_USB_ALI_M5632 is not set +# CONFIG_USB_AN2720 is not set +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +# CONFIG_USB_EPSON2888 is not set +# CONFIG_USB_KC2190 is not set +CONFIG_USB_NET_ZAURUS=y +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_NET_KALMIA is not set +# CONFIG_USB_NET_QMI_WWAN is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_USB_VL600 is not set +# CONFIG_USBNET_IPA_BRIDGE is not set +CONFIG_WLAN=y +# CONFIG_ATMEL is not set +# CONFIG_PRISM54 is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_WIFI_CONTROL_FUNC is not set +CONFIG_WCNSS_CORE=y +CONFIG_WCNSS_CORE_PRONTO=y +CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y +CONFIG_WCNSS_MEM_PRE_ALLOC=y +# CONFIG_WCNSS_SKB_PRE_ALLOC is not set +CONFIG_CNSS_CRYPTO=y +CONFIG_ATH_CARDS=y +# CONFIG_ATH_DEBUG is not set +# CONFIG_ATH5K_PCI is not set +# CONFIG_ATH6KL is not set +# CONFIG_WIL6210 is not set +# CONFIG_BRCMFMAC is not set +# CONFIG_HOSTAP is not set +# CONFIG_IPW2100 is not set +# CONFIG_LIBERTAS is not set +# CONFIG_WL_TI is not set +# CONFIG_MWIFIEX is not set +# CONFIG_CNSS is not set +# CONFIG_CLD_DEBUG is not set +# CONFIG_CLD_HL_SDIO_CORE is not set +CONFIG_CLD_LL_CORE=y +# CONFIG_CNSS_LOGGER is not set +# CONFIG_WLAN_FEATURE_RX_WAKELOCK is not set +# CONFIG_CNSS2 is not set +CONFIG_CNSS_UTILS=y + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_VMXNET3 is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_MATRIXKMAP is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_KEYRESET=y +CONFIG_INPUT_KEYCOMBO=y +# CONFIG_SENSORS_HALL is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP1106 is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +# CONFIG_JOYSTICK_ANALOG is not set +# CONFIG_JOYSTICK_A3D is not set +# CONFIG_JOYSTICK_ADI is not set +# CONFIG_JOYSTICK_COBRA is not set +# CONFIG_JOYSTICK_GF2K is not set +# CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set +# CONFIG_JOYSTICK_INTERACT is not set +# CONFIG_JOYSTICK_SIDEWINDER is not set +# CONFIG_JOYSTICK_TMDC is not set +# CONFIG_JOYSTICK_IFORCE is not set +# CONFIG_JOYSTICK_WARRIOR is not set +# CONFIG_JOYSTICK_MAGELLAN is not set +# CONFIG_JOYSTICK_SPACEORB is not set +# CONFIG_JOYSTICK_SPACEBALL is not set +# CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDJOY is not set +# CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set +# CONFIG_JOYSTICK_JOYDUMP is not set +CONFIG_JOYSTICK_XPAD=y +# CONFIG_JOYSTICK_XPAD_FF is not set +# CONFIG_JOYSTICK_XPAD_LEDS is not set +CONFIG_INPUT_TABLET=y +# CONFIG_TABLET_USB_ACECAD is not set +# CONFIG_TABLET_USB_AIPTEK is not set +# CONFIG_TABLET_USB_GTCO is not set +# CONFIG_TABLET_USB_HANWANG is not set +# CONFIG_TABLET_USB_KBTAB is not set +# CONFIG_TABLET_SERIAL_WACOM4 is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_v21 is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_v26 is not set +CONFIG_OF_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH_TS is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +CONFIG_TOUCHSCREEN_FT5435=y +# CONFIG_TOUCHSCREEN_IST3038C is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_SUR40 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +# CONFIG_TOUCHSCREEN_IT7260_I2C is not set +# CONFIG_TOUCHSCREEN_GEN_VKEYS is not set +# CONFIG_TOUCHSCREEN_FT5X06 is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +# CONFIG_TOUCHSCREEN_GT9XX is not set +# CONFIG_TOUCHSCREEN_GT9XX_MIDO is not set +# CONFIG_TOUCHSCREEN_MAXIM_STI is not set +CONFIG_TOUCHSCREEN_FTS=y +CONFIG_TOUCHSCREEN_TD4310=y +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_BMA150 is not set +CONFIG_INPUT_HBTP_INPUT=y +# CONFIG_HBTP_INPUT_SECURE_TOUCH is not set +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_MPU3050 is not set +# CONFIG_SENSORS_MPU6050 is not set +# CONFIG_SENSORS_AKM8963 is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +CONFIG_INPUT_KEYCHORD=y +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=y +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set +# CONFIG_INPUT_PIXART_OTS_PAT9125_SWITCH is not set +# CONFIG_SENSORS_LTR553 is not set +# CONFIG_SENSORS_BMA2X2 is not set +CONFIG_INPUT_FINGERPRINT=y +# CONFIG_FINGERPRINT_GOODIX_GF3208_MIDO is not set +# CONFIG_FINGERPRINT_FPC1020_MIDO is not set +CONFIG_FINGERPRINT_GOODIX_GF3208_TISSOT=y +CONFIG_FINGERPRINT_FPC1020_TISSOT=y + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +# CONFIG_VT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SERIAL_MFD_HSU is not set +CONFIG_SERIAL_CORE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_SERIAL_MSM_HS=y +# CONFIG_SERIAL_MSM_HSL is not set +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +CONFIG_SERIAL_MSM_SMD=y +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_RP2 is not set +# CONFIG_SERIAL_FSL_LPUART is not set + +# +# Diag Support +# +CONFIG_DIAG_CHAR=y + +# +# DIAG traffic over USB +# +CONFIG_DIAG_OVER_USB=y + +# +# HSIC/SMUX support for DIAG +# +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_MSM_LEGACY=y +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# PCMCIA character devices +# +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_DEVPORT is not set +CONFIG_MSM_SMD_PKT=y +# CONFIG_XILLYBUS is not set +CONFIG_MSM_ADSPRPC=y +# CONFIG_MSM_MDSP_TS is not set +# CONFIG_MSM_RDBG is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set +# CONFIG_I2C_MSM_QUP is not set +CONFIG_I2C_MSM_V2=y + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SLIMBUS=y +# CONFIG_SLIMBUS_MSM_CTRL is not set +CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_SOUNDWIRE=y +CONFIG_SOUNDWIRE_WCD_CTRL=y +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_ROCKCHIP is not set +CONFIG_SPI_QUP=y +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPMI is not set +# CONFIG_HSI is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +# CONFIG_PTP_1588_CLOCK is not set + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_PINCTRL=y + +# +# Pin controllers +# +CONFIG_PINMUX=y +CONFIG_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PINCTRL_MSM=y +# CONFIG_PINCTRL_APQ8064 is not set +# CONFIG_PINCTRL_MDM9607 is not set +# CONFIG_PINCTRL_MDM9640 is not set +# CONFIG_PINCTRL_MDM9650 is not set +# CONFIG_PINCTRL_SDX20 is not set +# CONFIG_PINCTRL_APQ8084 is not set +# CONFIG_PINCTRL_IPQ8064 is not set +# CONFIG_PINCTRL_MSM8960 is not set +# CONFIG_PINCTRL_MSM8X74 is not set +CONFIG_PINCTRL_MSM8953=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_PL061 is not set +CONFIG_GPIO_QPNP_PIN=y +# CONFIG_GPIO_QPNP_PIN_DEBUG is not set +# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_XGENE is not set +# CONFIG_GPIO_VX855 is not set +# CONFIG_GPIO_GRGPIO is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set + +# +# PCI GPIO expanders: +# +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_AMD8111 is not set +# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_RDC321X is not set + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# LPC GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# + +# +# USB GPIO expanders: +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_SMB349_USB_CHARGER is not set +# CONFIG_SMB349_DUAL_CHARGER is not set +CONFIG_SMB1351_USB_CHARGER=y +# CONFIG_SMB350_CHARGER is not set +CONFIG_SMB135X_CHARGER=y +# CONFIG_SMB1360_CHARGER_FG is not set +# CONFIG_SMB358_CHARGER is not set +# CONFIG_SMB23X_CHARGER is not set +# CONFIG_BATTERY_BQ28400 is not set +# CONFIG_QPNP_CHARGER is not set +CONFIG_QPNP_SMBCHARGER=y +# CONFIG_QPNP_SMB2 is not set +# CONFIG_FUELGAUGE_STC3117 is not set +CONFIG_QPNP_FG=y +# CONFIG_QPNP_FG_GEN3 is not set +CONFIG_BATTERY_BCL=y +# CONFIG_QPNP_VM_BMS is not set +# CONFIG_QPNP_BMS is not set +# CONFIG_QPNP_LINEAR_CHARGER is not set +CONFIG_QPNP_TYPEC=y +CONFIG_MSM_BCL_CTL=y +CONFIG_MSM_BCL_PERIPHERAL_CTL=y +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_POWER_RESET_LTC2952 is not set +CONFIG_POWER_RESET_MSM=y +CONFIG_MSM_DLOAD_MODE=y +# CONFIG_MSM_PRESERVE_MEM is not set +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_AVS is not set +CONFIG_MSM_PM=y +CONFIG_APSS_CORE_EA=y +CONFIG_MSM_APM=y +CONFIG_MSM_IDLE_STATS=y +CONFIG_MSM_IDLE_STATS_FIRST_BUCKET=62500 +CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT=2 +CONFIG_MSM_IDLE_STATS_BUCKET_COUNT=10 +CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET=1000000000 +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_HTU21 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_PCF8591 is not set +CONFIG_SENSORS_EPM_ADC=y +CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y +CONFIG_SENSORS_QPNP_ADC_CURRENT=y +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_PWM_FAN is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set +# CONFIG_CPU_THERMAL is not set +# CONFIG_THERMAL_EMULATION is not set +CONFIG_THERMAL_TSENS8974=y +CONFIG_LIMITS_MONITOR=y +CONFIG_LIMITS_LITE_HW=y +CONFIG_THERMAL_MONITOR=y +CONFIG_THERMAL_QPNP=y +CONFIG_THERMAL_QPNP_ADC_TM=y + +# +# Texas Instruments thermal drivers +# +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_AXP20X is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_I2C_PMIC is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RTSX_PCI is not set +# CONFIG_MFD_RTSX_USB is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK808 is not set +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_WCD9306_CODEC is not set +# CONFIG_WCD9320_CODEC is not set +# CONFIG_WCD9330_CODEC is not set +CONFIG_WCD9335_CODEC=y +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_PROXY_CONSUMER is not set +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +CONFIG_REGULATOR_STUB=y +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +CONFIG_REGULATOR_FAN53555=y +CONFIG_REGULATOR_MSM_GFX_LDO=y +# CONFIG_REGULATOR_GPIO is not set +# CONFIG_REGULATOR_ISL9305 is not set +CONFIG_REGULATOR_MEM_ACC=y +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_ONSEMI_NCP6335D is not set +# CONFIG_REGULATOR_PFUZE100 is not set +# CONFIG_REGULATOR_PWM is not set +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_REGULATOR_RPM_SMD=y +CONFIG_REGULATOR_QPNP=y +CONFIG_REGULATOR_QPNP_LABIBB=y +CONFIG_REGULATOR_SPM=y +CONFIG_REGULATOR_CPR=y +# CONFIG_REGULATOR_CPR2_GFX is not set +CONFIG_REGULATOR_CPR3=y +CONFIG_REGULATOR_CPR3_HMSS=y +CONFIG_REGULATOR_CPR3_MMSS=y +CONFIG_REGULATOR_CPR4_APSS=y +CONFIG_REGULATOR_CPRH_KBSS=y +CONFIG_REGULATOR_KRYO=y +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +CONFIG_MEDIA_RADIO_SUPPORT=y +# CONFIG_MEDIA_SDR_SUPPORT is not set +# CONFIG_MEDIA_RC_SUPPORT is not set +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_VIDEO_V4L2=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_V4L2_MEM2MEM_DEV=y +CONFIG_VIDEOBUF_GEN=y +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_VMALLOC=y +# CONFIG_TTPCI_EEPROM is not set + +# +# Media drivers +# +CONFIG_SPI_PEELIR=y +# CONFIG_MEDIA_USB_SUPPORT is not set +# CONFIG_MEDIA_PCI_SUPPORT is not set +CONFIG_V4L_PLATFORM_DRIVERS=y +# CONFIG_VIDEO_CAFE_CCIC is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_PLATFORM=y +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +# CONFIG_V4L_TEST_DRIVERS is not set +CONFIG_MSM_VIDC_V4L2=y +CONFIG_MSM_VIDC_VMEM=y +CONFIG_MSM_VIDC_GOVERNORS=y + +# +# QTI MSM Camera And Video & AIS +# +CONFIG_MSM_CAMERA=y +# CONFIG_MSM_CAMERA_DEBUG is not set +# CONFIG_MSM_CAMERA_AUTOMOTIVE is not set +CONFIG_MSMB_CAMERA=y +# CONFIG_MSMB_CAMERA_DEBUG is not set +CONFIG_MSM_CAMERA_SENSOR=y +CONFIG_MSM_CPP=y +CONFIG_MSM_CCI=y +CONFIG_MSM_CSI20_HEADER=y +CONFIG_MSM_CSI22_HEADER=y +CONFIG_MSM_CSI30_HEADER=y +CONFIG_MSM_CSI31_HEADER=y +CONFIG_MSM_CSIPHY=y +CONFIG_MSM_CSID=y +CONFIG_MSM_EEPROM=y +# CONFIG_MSM_ISP_V1 is not set +CONFIG_MSM_ISPIF=y +# CONFIG_MSM_ISPIF_V1 is not set +# CONFIG_MSM_ISPIF_V2 is not set +CONFIG_IMX134=y +CONFIG_IMX132=y +CONFIG_OV9724=y +CONFIG_OV5648=y +CONFIG_GC0339=y +CONFIG_OV8825=y +CONFIG_OV8865=y +CONFIG_s5k4e1=y +CONFIG_OV12830=y +CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y +CONFIG_MSMB_JPEG=y +CONFIG_MSM_FD=y +# CONFIG_MSM_JPEGDMA is not set +CONFIG_MSM_SEC_CCI_TA_NAME="seccamdemo64" +# CONFIG_MSM_SEC_CCI_DEBUG is not set +# CONFIG_MSM_AIS is not set +# CONFIG_TSPP is not set +CONFIG_MSM_SDE_ROTATOR=y + +# +# Supported MMC/SDIO adapters +# +CONFIG_RADIO_ADAPTERS=y +# CONFIG_RADIO_SI470X is not set +# CONFIG_RADIO_SI4713 is not set +# CONFIG_USB_MR800 is not set +# CONFIG_USB_DSBR is not set +# CONFIG_RADIO_MAXIRADIO is not set +# CONFIG_RADIO_SHARK is not set +# CONFIG_RADIO_SHARK2 is not set +# CONFIG_USB_KEENE is not set +# CONFIG_USB_RAREMONO is not set +# CONFIG_USB_MA901 is not set +# CONFIG_RADIO_TEA5764 is not set +# CONFIG_RADIO_SAA7706H is not set +# CONFIG_RADIO_TEF6862 is not set +# CONFIG_RADIO_WL1273 is not set + +# +# Texas Instruments WL128x FM driver (ST based) +# +# CONFIG_RADIO_WL128X is not set +CONFIG_RADIO_IRIS=y +CONFIG_RADIO_IRIS_TRANSPORT=y +CONFIG_RADIO_SILABS=y +# CONFIG_CYPRESS_FIRMWARE is not set + +# +# Media ancillary drivers (tuners, sensors, i2c, frontends) +# +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y + +# +# Audio decoders, processors and mixers +# + +# +# RDS decoders +# + +# +# Video decoders +# + +# +# Video and audio decoders +# + +# +# Video encoders +# + +# +# Camera sensor devices +# + +# +# Flash devices +# + +# +# Video improvement chips +# + +# +# Audio/Video compression chips +# + +# +# Miscellaneous helper chips +# + +# +# Sensors used on soc_camera driver +# + +# +# soc_camera sensor drivers +# +# CONFIG_SOC_CAMERA_IMX074 is not set +# CONFIG_SOC_CAMERA_MT9M001 is not set +# CONFIG_SOC_CAMERA_MT9M111 is not set +# CONFIG_SOC_CAMERA_MT9T031 is not set +# CONFIG_SOC_CAMERA_MT9T112 is not set +# CONFIG_SOC_CAMERA_MT9V022 is not set +# CONFIG_SOC_CAMERA_OV2640 is not set +# CONFIG_SOC_CAMERA_OV5642 is not set +# CONFIG_SOC_CAMERA_OV6650 is not set +# CONFIG_SOC_CAMERA_OV772X is not set +# CONFIG_SOC_CAMERA_OV9640 is not set +# CONFIG_SOC_CAMERA_OV9740 is not set +# CONFIG_SOC_CAMERA_RJ54N1 is not set +# CONFIG_SOC_CAMERA_TW9910 is not set +CONFIG_MEDIA_TUNER=y +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MC44S803=y + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set + +# +# Graphics support +# +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +CONFIG_MSM_KGSL=y +# CONFIG_MSM_KGSL_CFF_DUMP is not set +CONFIG_MSM_ADRENO_DEFAULT_GOVERNOR="msm-adreno-tz" +CONFIG_MSM_KGSL_IOMMU=y + +# +# Direct Rendering Manager +# +# CONFIG_DRM is not set + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +CONFIG_FB_MSM=y +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_MSM_BA_V4L2 is not set +CONFIG_MSM_DBA=y +CONFIG_MSM_DBA_ADV7533=y +CONFIG_FB_MSM_MDSS_COMMON=y +# CONFIG_FB_MSM_MDP is not set +CONFIG_FB_MSM_MDSS=y +# CONFIG_FB_MSM_MDP_NONE is not set +# CONFIG_FB_MSM_QPIC_ILI_QVGA_PANEL is not set +# CONFIG_FB_MSM_QPIC_PANEL_DETECT is not set +CONFIG_FB_MSM_MDSS_WRITEBACK=y +CONFIG_FB_MSM_MDSS_HDMI_PANEL=y +# CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334 is not set +# CONFIG_FB_MSM_MDSS_MHL3 is not set +# CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS is not set +# CONFIG_FB_MSM_MDSS_EDP_PANEL is not set +# CONFIG_FB_MSM_MDSS_MDP3 is not set +# CONFIG_FB_MSM_MDSS_XLOG_DEBUG is not set +# CONFIG_FB_MSM_MDSS_FRC_DEBUG is not set +# CONFIG_FB_SSD1307 is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +# CONFIG_BACKLIGHT_CLASS_DEVICE is not set +# CONFIG_ADF is not set +# CONFIG_VGASTATE is not set +# CONFIG_LT8912 is not set +# CONFIG_LOGO is not set +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=y +CONFIG_SND_RAWMIDI=y +CONFIG_SND_COMPRESS_OFFLOAD=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_MAX_CARDS=32 +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_PCI=y +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AW2 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_OXYGEN is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CTXFI is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set +# CONFIG_SND_INDIGOIOX is not set +# CONFIG_SND_INDIGODJX is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_LOLA is not set +# CONFIG_SND_LX6464ES is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_YMFPCI is not set + +# +# HD-Audio +# +# CONFIG_SND_HDA_INTEL is not set +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=y +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_BCD2000 is not set +CONFIG_SND_SOC=y +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set + +# +# MSM SoC Audio support +# +CONFIG_SND_SOC_MSM_HOSTLESS_PCM=y +CONFIG_SND_SOC_MSM_QDSP6V2_INTF=y +CONFIG_SND_SOC_QDSP6V2=y +# CONFIG_SND_SOC_QDSP_DEBUG is not set +CONFIG_DOLBY_DAP=y +CONFIG_DOLBY_DS2=y +CONFIG_DTS_EAGLE=y +CONFIG_DTS_SRS_TM=y +CONFIG_QTI_PP=y +CONFIG_SND_SOC_CPE=y +CONFIG_SND_SOC_MSM8X16=y +CONFIG_SND_SOC_I2C_AND_SPI=y + +# +# CODEC drivers +# +# CONFIG_SND_SOC_ADAU1701 is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4554 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_CS35L32 is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_CS42L73 is not set +# CONFIG_SND_SOC_CS4265 is not set +# CONFIG_SND_SOC_CS4270 is not set +# CONFIG_SND_SOC_CS4271 is not set +# CONFIG_SND_SOC_CS42XX8_I2C is not set +# CONFIG_SND_SOC_HDMI_CODEC is not set +# CONFIG_SND_SOC_ES8328 is not set +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1792A is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_SGTL5000 is not set +# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +# CONFIG_SND_SOC_SSM4567 is not set +# CONFIG_SND_SOC_STA350 is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC3X is not set +CONFIG_SND_SOC_WCD9330=y +CONFIG_SND_SOC_WCD9335=y +CONFIG_SND_SOC_WSA881X_SENSORS=y +CONFIG_SND_SOC_WSA881X=y +CONFIG_SND_SOC_WSA881X_ANALOG=y +CONFIG_SND_SOC_MSM8X16_WCD=y +CONFIG_SND_SOC_WCD9XXX=y +CONFIG_SND_SOC_WCD9XXX_V2=y +CONFIG_SND_SOC_WCD_CPE=y +CONFIG_AUDIO_EXT_CLK=y +CONFIG_SND_SOC_WCD_MBHC=y +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +# CONFIG_SND_SOC_WM8580 is not set +# CONFIG_SND_SOC_WM8711 is not set +# CONFIG_SND_SOC_WM8728 is not set +# CONFIG_SND_SOC_WM8731 is not set +# CONFIG_SND_SOC_WM8737 is not set +# CONFIG_SND_SOC_WM8741 is not set +# CONFIG_SND_SOC_WM8750 is not set +# CONFIG_SND_SOC_WM8753 is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8776 is not set +# CONFIG_SND_SOC_WM8804 is not set +# CONFIG_SND_SOC_WM8903 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_TPA6130A2 is not set +CONFIG_SND_SOC_MSM_STUB=y +CONFIG_SND_SOC_MSM_HDMI_DBA_CODEC_RX=y +CONFIG_SND_SOC_MAX98927=y +# CONFIG_SND_SIMPLE_CARD is not set +# CONFIG_SOUND_PRIME is not set + +# +# HID support +# +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CP2112 is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +CONFIG_HID_ELECOM=y +# CONFIG_HID_ELO is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_GT683R is not set +# CONFIG_HID_HUION is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO is not set +# CONFIG_HID_LOGITECH is not set +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MONTEREY is not set +CONFIG_HID_MULTITOUCH=y +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WIIMOTE is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y + +# +# I2C HID support +# +# CONFIG_I2C_HID is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_FSM is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PCI=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_PCI=y +CONFIG_USB_EHCI_MSM=y +CONFIG_USB_EHCI_MSM_HSIC=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FUSBH200_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=y +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +# CONFIG_USB_STORAGE_ONETOUCH is not set +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_USB_MUSB_HDRC is not set +CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_HOST is not set +# CONFIG_USB_DWC3_GADGET is not set +CONFIG_USB_DWC3_DUAL_ROLE=y + +# +# Platform Glue Driver Support +# +CONFIG_USB_DWC3_PCI=y +CONFIG_USB_DWC3_MSM=y + +# +# Debugging features +# +# CONFIG_USB_DWC3_DEBUG is not set +# CONFIG_DWC3_HOST_USB3_LPM_ENABLE is not set +# CONFIG_USB_DWC2 is not set +# CONFIG_USB_CHIPIDEA is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=y +# CONFIG_USB_SERIAL_CONSOLE is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_SIMPLE is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_F81232 is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_METRO is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MXUPORT is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_XSENS_MT is not set +# CONFIG_USB_SERIAL_WISHBONE is not set +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_QT2 is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +CONFIG_USB_EHSET_TEST_FIXTURE=y +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_MICROCHIP_USB2533 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_QTI_KS_BRIDGE is not set + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +# CONFIG_USB_OTG_WAKELOCK is not set +CONFIG_NOP_USB_XCEIV=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +CONFIG_USB_MSM_OTG=y +CONFIG_USB_MSM_HSPHY=y +# CONFIG_USB_MSM_SSPHY is not set +CONFIG_USB_MSM_SSPHY_QMP=y +CONFIG_MSM_QUSB_PHY=y +# CONFIG_USB_ULPI is not set +CONFIG_DUAL_ROLE_USB_INTF=y +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_AMD5536UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET2280 is not set +# CONFIG_USB_GOKU is not set +# CONFIG_USB_EG20T is not set +# CONFIG_USB_GADGET_XILINX is not set +CONFIG_USB_CI13XXX_MSM=y +# CONFIG_USB_CI13XXX_MSM_HSIC is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=y +CONFIG_USB_F_ACM=y +CONFIG_USB_U_SERIAL=y +CONFIG_USB_F_SERIAL=y +CONFIG_USB_F_NCM=y +CONFIG_USB_F_ECM=y +CONFIG_USB_F_MASS_STORAGE=y +CONFIG_USB_F_FS=y +CONFIG_USB_F_UAC1=y +CONFIG_USB_F_UAC2=y +CONFIG_USB_F_UVC=y +CONFIG_USB_F_AUDIO_SRC=y +# CONFIG_USB_CONFIGFS is not set +CONFIG_USB_G_ANDROID=y +# CONFIG_USB_ANDROID_RNDIS_DWORD_ALIGNED is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set +# CONFIG_USB_LED_TRIG is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_PERF_PROFILING=y +CONFIG_MMC_CLKGATE=y +# CONFIG_MMC_RING_BUFFER is not set +# CONFIG_MMC_EMBEDDED_SDIO is not set +CONFIG_MMC_PARANOID_SD_INIT=y + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_SDHCI=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +CONFIG_MMC_SDHCI_MSM=y +CONFIG_MMC_SDHCI_MSM_ICE=y +# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +CONFIG_MMC_CQ_HCI=y +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_INTEL_SS4200 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set +# CONFIG_LEDS_LM355x is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +CONFIG_LEDS_QPNP=y +CONFIG_LEDS_QPNP_FLASH=y +CONFIG_LEDS_QPNP_WLED=y +CONFIG_LEDS_AW2013=y + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_CPU is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +CONFIG_SWITCH=y +# CONFIG_SWITCH_GPIO is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_EDAC_SUPPORT=y +CONFIG_EDAC=y +CONFIG_EDAC_LEGACY_SYSFS=y +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=y +CONFIG_EDAC_CORTEX_ARM64=y +# CONFIG_EDAC_CORTEX_ARM64_PANIC_ON_CE is not set +CONFIG_EDAC_CORTEX_ARM64_DBE_IRQ_ONLY=y +CONFIG_EDAC_CORTEX_ARM64_PANIC_ON_UE=y +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_MCP795 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_EFI is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_SNVS is not set +CONFIG_RTC_DRV_QPNP=y +# CONFIG_RTC_DRV_XGENE is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +# CONFIG_ESOC is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +# CONFIG_AMBA_PL08X is not set +# CONFIG_DW_DMAC_CORE is not set +# CONFIG_DW_DMAC is not set +# CONFIG_DW_DMAC_PCI is not set +CONFIG_QCOM_SPS_DMA=y +# CONFIG_PL330_DMA is not set +# CONFIG_FSL_EDMA is not set +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +CONFIG_UIO=y +# CONFIG_UIO_CIF is not set +# CONFIG_UIO_PDRV_GENIRQ is not set +# CONFIG_UIO_DMEM_GENIRQ is not set +# CONFIG_UIO_AEC is not set +# CONFIG_UIO_SERCOS3 is not set +# CONFIG_UIO_PCI_GENERIC is not set +# CONFIG_UIO_NETX is not set +# CONFIG_UIO_MF624 is not set +CONFIG_UIO_MSM_SHAREDMEM=y +# CONFIG_VFIO is not set +# CONFIG_VIRT_DRIVERS is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_PCI is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_PRISM2_USB is not set +# CONFIG_R8712U is not set +# CONFIG_R8188EU is not set +# CONFIG_R8723AU is not set +# CONFIG_RTS5208 is not set +# CONFIG_LINE6_USB is not set +# CONFIG_FB_XGI is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder,vndbinder" +CONFIG_ASHMEM=y +# CONFIG_ANDROID_LOGGER is not set +CONFIG_ANDROID_TIMED_OUTPUT=y +CONFIG_ANDROID_TIMED_GPIO=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_ONESHOT_SYNC=y +# CONFIG_ONESHOT_SYNC_USER is not set +CONFIG_ION=y +# CONFIG_ION_TEST is not set +# CONFIG_ION_DUMMY is not set +CONFIG_ION_MSM=y +# CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS is not set +# CONFIG_FIQ_DEBUGGER is not set +# CONFIG_FIQ_WATCHDOG is not set +# CONFIG_USB_WPAN_HCD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_DGNC is not set +# CONFIG_DGAP is not set +# CONFIG_GS_FPGABOOT is not set + +# +# Qualcomm Atheros Prima WLAN module +# +# CONFIG_PRIMA_WLAN is not set +CONFIG_PRONTO_WLAN=y +# CONFIG_PRIMA_WLAN_BTAMP is not set +CONFIG_PRIMA_WLAN_LFR=y +CONFIG_PRIMA_WLAN_OKC=y +CONFIG_PRIMA_WLAN_11AC_HIGH_TP=y +CONFIG_WLAN_FEATURE_11W=y +CONFIG_QCOM_VOWIFI_11R=y +CONFIG_ENABLE_LINUX_REG=y +CONFIG_WLAN_OFFLOAD_PACKETS=y +CONFIG_QCOM_TDLS=y +# CONFIG_GOLDFISH is not set + +# +# Qualcomm MSM specific device drivers +# +CONFIG_MSM_AVTIMER=y +CONFIG_MSM_BUS_SCALING=y +CONFIG_BUS_TOPOLOGY_ADHOC=y +# CONFIG_DEBUG_BUS_VOTER is not set +CONFIG_QPNP_POWER_ON=y +CONFIG_QPNP_REVID=y +CONFIG_QPNP_COINCELL=y +CONFIG_SPS=y +# CONFIG_EP_PCIE is not set +CONFIG_USB_BAM=y +# CONFIG_SPS_SUPPORT_BAMDMA is not set +CONFIG_SPS_SUPPORT_NDP_BAM=y +# CONFIG_QPNP_VIBRATOR is not set +CONFIG_IPA=y +# CONFIG_IPA3 is not set +# CONFIG_GSI is not set +CONFIG_RMNET_IPA=y +# CONFIG_SSM is not set +# CONFIG_MSM_MHI is not set +# CONFIG_PFT is not set +# CONFIG_I2C_MSM_PROF_DBG is not set +# CONFIG_SEEMP_CORE is not set +CONFIG_QPNP_HAPTIC=y +CONFIG_GPIO_USB_DETECT=y +CONFIG_MSM_11AD=y +# CONFIG_BW_MONITOR is not set +CONFIG_MSM_SPMI=y +CONFIG_MSM_SPMI_PMIC_ARB=y +CONFIG_MSM_QPNP_INT=y +CONFIG_MSM_SPMI_DEBUGFS_RO=y +CONFIG_MACH_XIAOMI_MSM8953=y + +# +# Xiaomi board selection +# +# CONFIG_MACH_XIAOMI_MIDO is not set +CONFIG_MACH_XIAOMI_TISSOT=y +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_MSM_CLK_CONTROLLER_V2=y +CONFIG_MSM_MDSS_PLL=y +CONFIG_HWSPINLOCK=y + +# +# Hardware Spinlock drivers +# +CONFIG_REMOTE_SPINLOCK_MSM=y + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set +# CONFIG_ATMEL_PIT is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_EM_TIMER_STI is not set +# CONFIG_CLKSRC_VERSATILE is not set +# CONFIG_MAILBOX is not set +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +CONFIG_IOMMU_IO_PGTABLE=y +CONFIG_IOMMU_IO_PGTABLE_LPAE=y +# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set +# CONFIG_IOMMU_IO_PGTABLE_FAST is not set +CONFIG_OF_IOMMU=y +CONFIG_MSM_IOMMU=y +CONFIG_MSM_IOMMU_V1=y +# CONFIG_IOMMU_LPAE is not set +# CONFIG_IOMMU_AARCH64 is not set +# CONFIG_MSM_IOMMU_VBIF_CHECK is not set +# CONFIG_IOMMU_NON_SECURE is not set +# CONFIG_IOMMU_FORCE_4K_MAPPINGS is not set +CONFIG_ARM_SMMU=y +# CONFIG_IOMMU_DEBUG is not set + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# + +# +# SOC (System On Chip) specific Drivers +# +# CONFIG_MSM_HAB is not set +# CONFIG_CP_ACCESS64 is not set +# CONFIG_MSM_INRUSH_CURRENT_MITIGATION is not set +CONFIG_MSM_QDSP6_APRV2=y +# CONFIG_MSM_GLADIATOR_ERP is not set +# CONFIG_MSM_GLADIATOR_ERP_V2 is not set +# CONFIG_MSM_QDSP6_APRV3 is not set +# CONFIG_MSM_QDSP6_APRV2_GLINK is not set +# CONFIG_MSM_QDSP6_APRV3_GLINK is not set +CONFIG_MSM_ADSP_LOADER=y +# CONFIG_MSM_MEMORY_DUMP is not set +CONFIG_MSM_MEMORY_DUMP_V2=y +# CONFIG_MSM_DEBUG_LAR_UNLOCK is not set +# CONFIG_MSM_JTAG is not set +# CONFIG_MSM_JTAG_MM is not set +# CONFIG_MSM_JTAGV8 is not set +CONFIG_MSM_BOOT_STATS=y +# CONFIG_MSM_BOOT_TIME_MARKER is not set +CONFIG_MSM_CPUSS_DUMP=y +CONFIG_MSM_COMMON_LOG=y +CONFIG_MSM_DDR_HEALTH=y +# CONFIG_MSM_HYP_DEBUG is not set +CONFIG_MSM_WATCHDOG_V2=y +CONFIG_MSM_FORCE_WDOG_BITE_ON_PANIC=y +# CONFIG_MSM_CORE_HANG_DETECT is not set +# CONFIG_MSM_GLADIATOR_HANG_DETECT is not set +CONFIG_MSM_CPU_PWR_CTL=y +# CONFIG_MSM_L2_IA_DEBUG is not set +CONFIG_MSM_RPM_SMD=y +CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y +CONFIG_MSM_RPM_LOG=y +CONFIG_MSM_RPM_STATS_LOG=y +CONFIG_MSM_RUN_QUEUE_STATS=y +CONFIG_MSM_SCM=y +CONFIG_MSM_SCM_XPU=y +CONFIG_MSM_XPU_ERR_FATAL=y +# CONFIG_MSM_XPU_ERR_NONFATAL is not set +# CONFIG_MSM_SCM_ERRATA is not set +# CONFIG_MSM_PFE_WA is not set +CONFIG_MSM_MPM_OF=y +CONFIG_MSM_SMEM=y +# CONFIG_QPNP_PBS is not set +CONFIG_MSM_SMD=y +# CONFIG_MSM_SMD_DEBUG is not set +CONFIG_MSM_GLINK=y +CONFIG_MSM_GLINK_LOOPBACK_SERVER=y +CONFIG_MSM_GLINK_SMD_XPRT=y +CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y +CONFIG_MSM_SMEM_LOGGING=y +CONFIG_MSM_SMP2P=y +CONFIG_MSM_SMP2P_TEST=y +CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y +CONFIG_MSM_QMI_INTERFACE=y +# CONFIG_MSM_DCC is not set +# CONFIG_MSM_HVC is not set +CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y +CONFIG_MSM_EVENT_TIMER=y +# CONFIG_MSM_SYSMON_GLINK_COMM is not set +# CONFIG_MSM_IPC_ROUTER_GLINK_XPRT is not set +# CONFIG_MSM_SYSTEM_HEALTH_MONITOR is not set +# CONFIG_MSM_GLINK_PKT is not set +CONFIG_MSM_TZ_SMMU=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_SYSMON_COMM=y +CONFIG_MSM_PIL=y +CONFIG_MSM_PIL_SSR_GENERIC=y +# CONFIG_MSM_PIL_SSR_BG is not set +CONFIG_MSM_PIL_MSS_QDSP6V5=y +# CONFIG_MSM_SHARED_HEAP_ACCESS is not set +# CONFIG_TRACER_PKT is not set +CONFIG_MSM_SECURE_BUFFER=y +CONFIG_ICNSS=y +CONFIG_MSM_BAM_DMUX=y +CONFIG_MSM_PERFORMANCE=y +CONFIG_MSM_PERFORMANCE_HOTPLUG_ON=y +# CONFIG_MSM_POWER is not set +# CONFIG_MSM_SERVICE_LOCATOR is not set +# CONFIG_MSM_QBT1000 is not set +CONFIG_MSM_KERNEL_PROTECT=y +CONFIG_MSM_KERNEL_PROTECT_MPU=y +# CONFIG_MSM_KERNEL_PROTECT_TEST is not set +# CONFIG_MSM_BGCOM is not set +# CONFIG_MSM_REMOTEQDSS is not set +# CONFIG_QCOM_SMCINVOKE is not set +CONFIG_QCOM_EARLY_RANDOM=y +# CONFIG_WCD_DSP_GLINK is not set +CONFIG_SERIAL_NUM=y +CONFIG_MEM_SHARE_QMI_SERVICE=y +# CONFIG_SOC_TI is not set +CONFIG_PM_DEVFREQ=y + +# +# DEVFREQ Governors +# +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_POWERSAVE=y +CONFIG_DEVFREQ_GOV_USERSPACE=y +CONFIG_DEVFREQ_GOV_CPUFREQ=y +CONFIG_DEVFREQ_GOV_MSM_ADRENO_TZ=y +CONFIG_MSM_BIMC_BWMON=y +CONFIG_DEVFREQ_GOV_MSM_GPUBW_MON=y +# CONFIG_ARMBW_HWMON is not set +CONFIG_ARM_MEMLAT_MON=y +CONFIG_MSMCCI_HWMON=y +CONFIG_MSM_M4M_HWMON=y +CONFIG_DEVFREQ_GOV_MSM_BW_HWMON=y +CONFIG_DEVFREQ_GOV_MSM_CACHE_HWMON=y +CONFIG_DEVFREQ_GOV_SPDM_HYP=y +CONFIG_DEVFREQ_GOV_MEMLAT=y + +# +# DEVFREQ Drivers +# +CONFIG_DEVFREQ_SIMPLE_DEV=y +CONFIG_MSM_DEVFREQ_DEVBW=y +CONFIG_SPDM_SCM=y +CONFIG_DEVFREQ_SPDM=y +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +# CONFIG_IIO is not set +# CONFIG_VME_BUS is not set +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +# CONFIG_PWM_FSL_FTM is not set +# CONFIG_PWM_PCA9685 is not set +CONFIG_PWM_QPNP=y +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_PANIC_HANDLER=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ACL=y +# CONFIG_ARM_GIC_V3_NO_ACCESS_CONTROL is not set +CONFIG_MSM_SHOW_RESUME_IRQ=y +CONFIG_MSM_IRQ=y +# CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set +# CONFIG_FMC is not set +# CONFIG_CORESIGHT is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_PHY_XGENE is not set +CONFIG_PHY_QCOM_UFS=y +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set +CONFIG_RAS=y +# CONFIG_THUNDERBOLT is not set +# CONFIG_SENSORS is not set +CONFIG_SENSORS_SSC=y + +# +# Firmware Drivers +# +# CONFIG_FIRMWARE_MEMMAP is not set +CONFIG_DMIID=y +# CONFIG_DMI_SYSFS is not set + +# +# EFI (Extensible Firmware Interface) Support +# +# CONFIG_EFI_VARS is not set +CONFIG_EFI_PARAMS_FROM_FDT=y +CONFIG_EFI_RUNTIME_WRAPPERS=y +CONFIG_EFI_ARMSTUB=y +CONFIG_MSM_TZ_LOG=y +# CONFIG_BIF is not set + +# +# Firmware Drivers +# + +# +# EFI (Extensible Firmware Interface) Support +# + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT23=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +# CONFIG_FS_ENCRYPTION is not set +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +# CONFIG_QUOTA_DEBUG is not set +CONFIG_QUOTA_TREE=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set +# CONFIG_OVERLAY_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=y +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +CONFIG_SDCARD_FS=y +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set +# CONFIG_FILE_TABLE_DEBUG is not set +# CONFIG_VIRTUALIZATION is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_LOG_BUF_MAGIC is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_DYNAMIC_DEBUG is not set + +# +# Compile-time checks and compiler options +# +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_INFO_SPLIT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_HAVE_ARCH_KASAN=y +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=5 +CONFIG_PANIC_ON_RECURSIVE_FAULT=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_PANIC_ON_SCHED_BUG is not set +# CONFIG_PANIC_ON_RT_THROTTLING is not set +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_STACK_END_CHECK=y +CONFIG_TIMER_STATS=y +CONFIG_DEBUG_PREEMPT=y + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_HAVE_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_CPU_STALL_VERBOSE=y +# CONFIG_RCU_CPU_STALL_INFO is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACE_CLOCK=y +CONFIG_RING_BUFFER=y +CONFIG_EVENT_TRACING=y +CONFIG_CONTEXT_SWITCH_TRACER=y +# CONFIG_MSM_RTB is not set +CONFIG_IPC_LOGGING=y +CONFIG_TRACING=y +CONFIG_GENERIC_TRACER=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_FTRACE_SYSCALLS is not set +# CONFIG_TRACER_SNAPSHOT is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_PROBE_EVENTS is not set +CONFIG_CPU_FREQ_SWITCH_PROFILER=y +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_TRACEPOINT_BENCHMARK is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set +# CONFIG_RING_BUFFER_STARTUP_TEST is not set + +# +# Runtime Testing +# +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_PANIC_ON_DATA_CORRUPTION is not set +# CONFIG_MEMTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y +# CONFIG_UBSAN is not set +# CONFIG_ARM64_PTDUMP is not set +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +# CONFIG_FORCE_PAGES is not set +# CONFIG_FREE_PAGES_RDONLY is not set +# CONFIG_DEBUG_RODATA is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set + +# +# Qualcomm Technologies, Inc Per File Encryption security device drivers +# +# CONFIG_SECURITY_DMESG_RESTRICT is not set +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y +CONFIG_SECURITY=y +# CONFIG_SECURITYFS is not set +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +# CONFIG_SECURITY_PATH is not set +CONFIG_LSM_MMAP_MIN_ADDR=4096 +CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y +CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y +CONFIG_HARDENED_USERCOPY=y +# CONFIG_HARDENED_USERCOPY_PAGESPAN is not set +CONFIG_SECURITY_SELINUX=y +# CONFIG_SECURITY_SELINUX_BOOTPARAM is not set +# CONFIG_SECURITY_SELINUX_DISABLE is not set +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set +# CONFIG_SECURITY_SMACK is not set +# CONFIG_SECURITY_TOMOYO is not set +# CONFIG_SECURITY_APPARMOR is not set +# CONFIG_SECURITY_YAMA is not set +CONFIG_INTEGRITY=y +# CONFIG_INTEGRITY_SIGNATURE is not set +CONFIG_INTEGRITY_AUDIT=y +# CONFIG_IMA is not set +# CONFIG_EVM is not set +CONFIG_DEFAULT_SECURITY_SELINUX=y +# CONFIG_DEFAULT_SECURITY_DAC is not set +CONFIG_DEFAULT_SECURITY="selinux" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_USER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=y +# CONFIG_CRYPTO_MCRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +CONFIG_CRYPTO_ABLK_HELPER=y + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +CONFIG_CRYPTO_SEQIV=y + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +CONFIG_CRYPTO_XTS=y + +# +# Hash modes +# +# CONFIG_CRYPTO_CMAC is not set +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=y +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=y +# CONFIG_CRYPTO_DRBG_MENU is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_DEV_QCE50=y +# CONFIG_FIPS_ENABLE is not set +CONFIG_CRYPTO_DEV_QCRYPTO=y +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y +CONFIG_CRYPTO_DEV_QCEDEV=y +CONFIG_CRYPTO_DEV_OTA_CRYPTO=y +CONFIG_CRYPTO_DEV_QCOM_ICE=y +# CONFIG_CRYPTO_DEV_CCP is not set +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +CONFIG_PUBLIC_KEY_ALGO_RSA=y +CONFIG_X509_CERTIFICATE_PARSER=y +CONFIG_PKCS7_MESSAGE_PARSER=y +CONFIG_PKCS7_TEST_KEY=y +# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +CONFIG_BINARY_PRINTF=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +CONFIG_AUDIT_GENERIC=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_AUDIT_COMPAT_GENERIC=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=y +CONFIG_TEXTSEARCH_BM=y +CONFIG_TEXTSEARCH_FSM=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +# CONFIG_AVERAGE is not set +CONFIG_CLZ_TAB=y +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +CONFIG_MPILIB=y +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +CONFIG_UCS2_STRING=y +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_QMI_ENCDEC=y +# CONFIG_QMI_ENCDEC_DEBUG is not set +# CONFIG_STRICT_MEMORY_RWX is not set From d86f0872d06815faf494659f4553106482c851a1 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Fri, 8 Dec 2017 08:07:25 +0100 Subject: [PATCH 257/508] xfrm: Fix stack-out-of-bounds with misconfigured transport mode policies. On policies with a transport mode template, we pass the addresses from the flowi to xfrm_state_find(), assuming that the IP addresses (and address family) don't change during transformation. Unfortunately our policy template validation is not strict enough. It is possible to configure policies with transport mode template where the address family of the template does not match the selectors address family. This lead to stack-out-of-bound reads because we compare arddesses of the wrong family. Fix this by refusing such a configuration, address family can not change on transport mode. We use the assumption that, on transport mode, the first templates address family must match the address family of the policy selector. Subsequent transport mode templates must mach the address family of the previous template. Change-Id: I33678e32df020045f419f38fc4d955863c42409a Signed-off-by: Steffen Klassert Git-commit: 732706afe1cc46ef48493b3d2b69c98f36314ae4 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Tejaswi Tanikella Acked-by: Sharath Chandra Vurukala --- net/xfrm/xfrm_user.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 959fcb9d03e84..8ada96a066395 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1350,11 +1350,14 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) { + u16 prev_family; int i; if (nr > XFRM_MAX_DEPTH) return -EINVAL; + prev_family = family; + for (i = 0; i < nr; i++) { /* We never validated the ut->family value, so many * applications simply leave it at zero. The check was @@ -1366,6 +1369,12 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) if (!ut[i].family) ut[i].family = family; + if ((ut[i].mode == XFRM_MODE_TRANSPORT) && + (ut[i].family != prev_family)) + return -EINVAL; + + prev_family = ut[i].family; + switch (ut[i].family) { case AF_INET: break; From 6f99986d30891ef68357e6604139f4f4d839dbe0 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Sat, 17 Mar 2018 20:42:28 +0530 Subject: [PATCH 258/508] drivers: soc: qcom: mpm: Do not resend GPIO interrupts Interrupts configured as wakeup capable will be pending at both MPM and TLMM during system level LPMs. Since GPIO summary interrupt is level triggered, do not resend GPIO interrupts when exiting from system level LPMs. Change-Id: I63340396cf2764835d628906aa8e7c1278c88cec Signed-off-by: Maulik Shah --- drivers/soc/qcom/mpm-of.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/mpm-of.c b/drivers/soc/qcom/mpm-of.c index 97e03253b59e8..c1cd245a4506e 100644 --- a/drivers/soc/qcom/mpm-of.c +++ b/drivers/soc/qcom/mpm-of.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2016, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -608,8 +608,13 @@ void msm_mpm_exit_sleep(bool from_idle) unsigned int apps_irq = msm_mpm_get_irq_m2a(mpm_irq); struct irq_desc *desc = apps_irq ? irq_to_desc(apps_irq) : NULL; + struct irq_chip *chip = NULL; - if (desc && !irqd_is_level_type(&desc->irq_data)) { + if (desc) + chip = desc->irq_data.chip; + + if (desc && !irqd_is_level_type(&desc->irq_data) && + (!(chip && !strcmp(chip->name, "msmgpio")))) { irq_set_pending(apps_irq); if (from_idle) { raw_spin_lock(&desc->lock); From 4bc7311e9ea9145a615184626cc43a8b92e7619c Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Tue, 20 Feb 2018 16:01:26 +0530 Subject: [PATCH 259/508] msm: ipa: Fix to handle NULL pointer dereference Header entry deleted but same entry pointer using in routing table not updated. Added checks to confirm header entry present or not before using it to avoid null pointer dereference. Change-Id: Id1d844c60b2dcb0cc7cf18352b78d62fe5a89347 Acked-by: Ashok Vuyyuru Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v2/ipa_rt.c | 65 ++++++++++++++++++++++++ drivers/platform/msm/ipa/ipa_v3/ipa_rt.c | 65 +++++++++++++++++++++++- 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c index 4a68b96ca89a9..7cc3c380ee71b 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c @@ -51,6 +51,7 @@ int __ipa_generate_rt_hw_rule_v2(enum ipa_ip_type ip, u32 tmp[IPA_RT_FLT_HW_RULE_BUF_SIZE/4]; u8 *start; int pipe_idx; + struct ipa_hdr_entry *hdr_entry; if (buf == NULL) { memset(tmp, 0, (IPA_RT_FLT_HW_RULE_BUF_SIZE/4)); @@ -74,6 +75,18 @@ int __ipa_generate_rt_hw_rule_v2(enum ipa_ip_type ip, } rule_hdr->u.hdr.pipe_dest_idx = pipe_idx; rule_hdr->u.hdr.system = !ipa_ctx->hdr_tbl_lcl; + + /* Adding check to confirm still + * header entry present in header table or not + */ + + if (entry->hdr) { + hdr_entry = ipa_id_find(entry->rule.hdr_hdl); + if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL("Header entry already deleted\n"); + return -EPERM; + } + } if (entry->hdr) { if (entry->hdr->cookie == IPA_HDR_COOKIE) { rule_hdr->u.hdr.hdr_offset = @@ -140,6 +153,8 @@ int __ipa_generate_rt_hw_rule_v2_5(enum ipa_ip_type ip, u32 tmp[IPA_RT_FLT_HW_RULE_BUF_SIZE/4]; u8 *start; int pipe_idx; + struct ipa_hdr_entry *hdr_entry; + struct ipa_hdr_proc_ctx_entry *hdr_proc_entry; if (buf == NULL) { memset(tmp, 0, IPA_RT_FLT_HW_RULE_BUF_SIZE); @@ -162,6 +177,24 @@ int __ipa_generate_rt_hw_rule_v2_5(enum ipa_ip_type ip, return -EPERM; } rule_hdr->u.hdr_v2_5.pipe_dest_idx = pipe_idx; + /* Adding check to confirm still + * header entry present in header table or not + */ + + if (entry->hdr) { + hdr_entry = ipa_id_find(entry->rule.hdr_hdl); + if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL("Header entry already deleted\n"); + return -EPERM; + } + } else if (entry->proc_ctx) { + hdr_proc_entry = ipa_id_find(entry->rule.hdr_proc_ctx_hdl); + if (!hdr_proc_entry || + hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) { + IPAERR_RL("Proc header entry already deleted\n"); + return -EPERM; + } + } if (entry->proc_ctx || (entry->hdr && entry->hdr->is_hdr_proc_ctx)) { struct ipa_hdr_proc_ctx_entry *proc_ctx; @@ -1130,6 +1163,8 @@ int __ipa_del_rt_rule(u32 rule_hdl) { struct ipa_rt_entry *entry; int id; + struct ipa_hdr_entry *hdr_entry; + struct ipa_hdr_proc_ctx_entry *hdr_proc_entry; entry = ipa_id_find(rule_hdl); @@ -1151,6 +1186,24 @@ int __ipa_del_rt_rule(u32 rule_hdl) return -EINVAL; } } + /* Adding check to confirm still + * header entry present in header table or not + */ + + if (entry->hdr) { + hdr_entry = ipa_id_find(entry->rule.hdr_hdl); + if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL("Header entry already deleted\n"); + return -EINVAL; + } + } else if (entry->proc_ctx) { + hdr_proc_entry = ipa_id_find(entry->rule.hdr_proc_ctx_hdl); + if (!hdr_proc_entry || + hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) { + IPAERR_RL("Proc header entry already deleted\n"); + return -EINVAL; + } + } if (entry->hdr) __ipa_release_hdr(entry->hdr->id); @@ -1463,6 +1516,7 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) { struct ipa_rt_entry *entry; struct ipa_hdr_entry *hdr = NULL; + struct ipa_hdr_entry *hdr_entry; if (rtrule->rule.hdr_hdl) { hdr = ipa_id_find(rtrule->rule.hdr_hdl); @@ -1483,6 +1537,17 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) goto error; } + /* Adding check to confirm still + * header entry present in header table or not + */ + + if (entry->hdr) { + hdr_entry = ipa_id_find(entry->rule.hdr_hdl); + if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL("Header entry already deleted\n"); + return -EPERM; + } + } if (entry->hdr) entry->hdr->ref_cnt--; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c index f9c08cae466fc..30a1546dcdb7e 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c @@ -54,6 +54,8 @@ int __ipa_generate_rt_hw_rule_v3_0(enum ipa_ip_type ip, u32 tmp[IPA_RT_FLT_HW_RULE_BUF_SIZE/4]; u8 *start; int pipe_idx; + struct ipa3_hdr_entry *hdr_entry; + struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry; if (buf == NULL) { memset(tmp, 0, IPA_RT_FLT_HW_RULE_BUF_SIZE); @@ -80,6 +82,26 @@ int __ipa_generate_rt_hw_rule_v3_0(enum ipa_ip_type ip, return -EPERM; } rule_hdr->u.hdr.pipe_dest_idx = pipe_idx; + /* Adding check to confirm still + * header entry present in header table or not + */ + + if (entry->hdr) { + hdr_entry = ipa3_id_find(entry->rule.hdr_hdl); + if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL("Header entry already deleted\n"); + return -EINVAL; + } + } else if (entry->proc_ctx) { + hdr_proc_entry = ipa3_id_find(entry->rule.hdr_proc_ctx_hdl); + if (!hdr_proc_entry || + hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) { + IPAERR_RL("Proc header entry already deleted\n"); + return -EINVAL; + } + } + + if (entry->proc_ctx || (entry->hdr && entry->hdr->is_hdr_proc_ctx)) { struct ipa3_hdr_proc_ctx_entry *proc_ctx; proc_ctx = (entry->proc_ctx) ? : entry->hdr->proc_ctx; @@ -1443,6 +1465,8 @@ int __ipa3_del_rt_rule(u32 rule_hdl) { struct ipa3_rt_entry *entry; int id; + struct ipa3_hdr_entry *hdr_entry; + struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry; entry = ipa3_id_find(rule_hdl); @@ -1465,6 +1489,25 @@ int __ipa3_del_rt_rule(u32 rule_hdl) } } + /* Adding check to confirm still + * header entry present in header table or not + */ + + if (entry->hdr) { + hdr_entry = ipa3_id_find(entry->rule.hdr_hdl); + if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL("Header entry already deleted\n"); + return -EINVAL; + } + } else if (entry->proc_ctx) { + hdr_proc_entry = ipa3_id_find(entry->rule.hdr_proc_ctx_hdl); + if (!hdr_proc_entry || + hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) { + IPAERR_RL("Proc header entry already deleted\n"); + return -EINVAL; + } + } + if (entry->hdr) __ipa3_release_hdr(entry->hdr->id); else if (entry->proc_ctx) @@ -1784,7 +1827,8 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) struct ipa3_rt_entry *entry; struct ipa3_hdr_entry *hdr = NULL; struct ipa3_hdr_proc_ctx_entry *proc_ctx = NULL; - + struct ipa3_hdr_entry *hdr_entry; + struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry; if (rtrule->rule.hdr_hdl) { hdr = ipa3_id_find(rtrule->rule.hdr_hdl); if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { @@ -1811,6 +1855,25 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) goto error; } + /* Adding check to confirm still + * header entry present in header table or not + */ + + if (entry->hdr) { + hdr_entry = ipa3_id_find(entry->rule.hdr_hdl); + if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL("Header entry already deleted\n"); + return -EPERM; + } + } else if (entry->proc_ctx) { + hdr_proc_entry = ipa3_id_find(entry->rule.hdr_proc_ctx_hdl); + if (!hdr_proc_entry || + hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) { + IPAERR_RL("Proc header entry already deleted\n"); + return -EPERM; + } + } + if (entry->hdr) entry->hdr->ref_cnt--; if (entry->proc_ctx) From 186a6ff61aa59bfbef7ebe57fa3b44fae70a9afb Mon Sep 17 00:00:00 2001 From: Archana Sriram Date: Mon, 26 Mar 2018 13:14:04 +0530 Subject: [PATCH 260/508] msm: kgsl: Enhance reading lm_sequence in _execute_reg_sequence() Modified conditional checks to read lm_sequence so as to avoid the possibility of pointer overflow. CRs-Fixed: 2212443 Change-Id: I72b30e35996c40f23fc81739e27724b1188f1c05 Signed-off-by: Archana Sriram --- drivers/gpu/msm/adreno_a5xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 4156f493fd015..b112b041e8b98 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -1265,13 +1265,13 @@ static int _execute_reg_sequence(struct adreno_device *adreno_dev, /* todo double check the reg writes */ while ((cur - opcode) < length) { - if (cur[0] == 1 && ((cur + 4) - opcode) <= length) { + if (cur[0] == 1 && (length - (cur - opcode) >= 4)) { /* Write a 32 bit value to a 64 bit reg */ reg = cur[2]; reg = (reg << 32) | cur[1]; kgsl_regwrite(KGSL_DEVICE(adreno_dev), reg, cur[3]); cur += 4; - } else if (cur[0] == 2 && ((cur + 5) - opcode) <= length) { + } else if (cur[0] == 2 && (length - (cur - opcode) >= 5)) { /* Write a 64 bit value to a 64 bit reg */ reg = cur[2]; reg = (reg << 32) | cur[1]; @@ -1279,7 +1279,7 @@ static int _execute_reg_sequence(struct adreno_device *adreno_dev, val = (val << 32) | cur[3]; kgsl_regwrite(KGSL_DEVICE(adreno_dev), reg, val); cur += 5; - } else if (cur[0] == 3 && ((cur + 2) - opcode) <= length) { + } else if (cur[0] == 3 && (length - (cur - opcode) >= 2)) { /* Delay for X usec */ udelay(cur[1]); cur += 2; From a0e2a342679d0f69d6ca4708183c4abc2dd470cc Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Wed, 14 Mar 2018 16:03:34 +0530 Subject: [PATCH 261/508] ARM: dts: msm: Disable IPA in SDA450 IPA needs to be kept disabled in SDA450 platform. Change-Id: Ib481332fd0020535d91e09b2379d4bd41d0a514b Acked-by: Ashok Vuyyuru Signed-off-by: Mohammed Javid --- arch/arm/boot/dts/qcom/sda450.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/qcom/sda450.dtsi b/arch/arm/boot/dts/qcom/sda450.dtsi index 7089bb45f52e4..4fa84e2e88b6d 100644 --- a/arch/arm/boot/dts/qcom/sda450.dtsi +++ b/arch/arm/boot/dts/qcom/sda450.dtsi @@ -118,3 +118,13 @@ }; }; }; + +&soc { + qcom,rmnet-ipa { + status = "disabled"; + }; +}; + +&ipa_hw { + status = "disabled"; +}; From 449c452b8ad2cb41ad535aa8cb9cca11ca55ba78 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Thu, 8 Mar 2018 13:21:10 +0530 Subject: [PATCH 262/508] wlan: Send STA authorized status to supplicant for AP Propagation from qcacld-3.0 to prima Currently there is no support from driver to send STA authorized event to supplicant. Use QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES vendor command to send STA authorized event to supplicant. Change-Id: Idfac4d80b9561cf34b65a0529137793fb164f978 CRs-Fixed: 2202232 --- CORE/HDD/inc/wlan_hdd_cfg80211.h | 19 +++++++++ CORE/HDD/src/wlan_hdd_cfg80211.c | 61 ++++++++++++++++++++++++++++ CORE/HDD/src/wlan_hdd_softap_tx_rx.c | 5 ++- 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h index 2e3f2a8fc8335..25424da4f4742 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -475,6 +475,7 @@ enum qca_nl80211_vendor_subcmds_index { QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX, QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX, QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX, + QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX, }; /** @@ -1377,6 +1378,10 @@ enum qca_wlan_vendor_attr_link_properties { QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS = 2, /* Unsigned 32bit value for operating frequency */ QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ = 3, + /* Unsigned 32bit value for STA flags*/ + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS = 4, + /* An array of 6 Unsigned 8bit values for the STA MAC address*/ + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_MAC = 5, /* KEEP LAST */ QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_AFTER_LAST, @@ -1794,4 +1799,18 @@ int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, int wlan_hdd_cfg80211_update_apies(hdd_adapter_t *pHostapdAdapter); int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter); void wlan_hdd_sap_get_sta_rssi(hdd_adapter_t *adapter, uint8_t staid, s8 *rssi); + +/* + *wlan_hdd_send_sta_authorized_event: Function to send station authorized + *event to user space in case of SAP + *@pAdapter: Pointer to the adapter + *@pHddCtx: HDD Context + *@mac_addr: MAC address of the STA for whic the Authorized event needs to + * be sent + *This api is used to send station authorized event to user space + */ +VOS_STATUS wlan_hdd_send_sta_authorized_event(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + const v_MACADDR_t *mac_addr); + #endif diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 55df656770c68..d22eff6a4112a 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -8862,6 +8862,10 @@ struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = .vendor_id = QCA_NL80211_VENDOR_ID, .subcmd = QCA_NL80211_VENDOR_SUBCMD_HANG, }, + [QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES, + }, }; /* @@ -12596,6 +12600,59 @@ static int wlan_hdd_tdls_add_station(struct wiphy *wiphy, } #endif +VOS_STATUS wlan_hdd_send_sta_authorized_event( + hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + const v_MACADDR_t *mac_addr) +{ + struct sk_buff *vendor_event; + uint32_t sta_flags = 0; + VOS_STATUS status; + + ENTER(); + + if (!hdd_ctx) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is null")); + return -EINVAL; + } + + vendor_event = + cfg80211_vendor_event_alloc( + hdd_ctx->wiphy, &adapter->wdev, sizeof(sta_flags) + + VOS_MAC_ADDR_SIZE + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX, + GFP_KERNEL); + if (!vendor_event) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("cfg80211_vendor_event_alloc failed")); + return -EINVAL; + } + + sta_flags |= BIT(NL80211_STA_FLAG_AUTHORIZED); + + status = nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS, + sta_flags); + if (status) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("STA flag put fails")); + kfree_skb(vendor_event); + return VOS_STATUS_E_FAILURE; + } + status = nla_put(vendor_event, + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_MAC, + VOS_MAC_ADDR_SIZE, mac_addr->bytes); + if (status) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("STA MAC put fails")); + kfree_skb(vendor_event); + return VOS_STATUS_E_FAILURE; + } + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + + EXIT(); + return 0; +} + static int __wlan_hdd_change_station(struct wiphy *wiphy, struct net_device *dev, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0)) @@ -12663,6 +12720,10 @@ static int __wlan_hdd_change_station(struct wiphy *wiphy, "%s: Not able to change TL state to AUTHENTICATED", __func__); return -EINVAL; } + status = wlan_hdd_send_sta_authorized_event(pAdapter, pHddCtx, + &STAMacAddress); + if (status != VOS_STATUS_SUCCESS) + return -EINVAL; } } else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) diff --git a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c index d7f8e92be325d..bb22cb52e7ad9 100644 --- a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c +++ b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c @@ -2031,7 +2031,10 @@ VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter, pSapCtx->aStaInfo[staId].tlSTAState = WLANTL_STA_AUTHENTICATED; pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_TRUE; - } + if (!vos_is_macaddr_broadcast(pPeerMacAddress)) + vosStatus = wlan_hdd_send_sta_authorized_event(pAdapter, pHddCtx, + pPeerMacAddress); + } else { From 3d490dfd0a0352d36ad3eeecfb4d9c1fb6beab9e Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Sat, 24 Mar 2018 00:19:46 +0530 Subject: [PATCH 263/508] msm: ipa: rmnet: Update wan IOCTL function in SSR scenario During SSR scenario in IP-PASS through config, IPA driver miss to update lan client info. Which is breaking IPACM functionality, leads to data stall in lan stats enabled with IP-PASS through. Allow wan IOCTL function only for setting and clearing the lan client info during SSR. Change-Id: I391641ac8712aa44c4b26e2ccc8e26d940ffe7bd Signed-off-by: Mohammed Javid --- .../platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c index fe7d8c8751469..6f095b691161f 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c @@ -79,8 +79,17 @@ static long ipa3_wan_ioctl(struct file *filp, DRIVER_NAME); if (!ipa3_process_ioctl) { - IPAWANDBG("modem is in SSR, ignoring ioctl\n"); - return -EAGAIN; + + if ((cmd == WAN_IOC_SET_LAN_CLIENT_INFO) || + (cmd == WAN_IOC_CLEAR_LAN_CLIENT_INFO)) { + IPAWANDBG("Modem is in SSR\n"); + IPAWANDBG("Still allow IOCTL for exceptions (%d)\n", + cmd); + } else { + IPAWANERR("Modem is in SSR, ignoring ioctl (%d)\n", + cmd); + return -EAGAIN; + } } switch (cmd) { From 230f148e303884dec97ae8deba129e67543154aa Mon Sep 17 00:00:00 2001 From: Shadab Naseem Date: Mon, 13 Nov 2017 17:10:32 +0530 Subject: [PATCH 264/508] ARM: dts: msm: Add DT support for APQ8053 Lite dragonboard Add Device Tree support for apq8053 lite dragonboard. Change-Id: I3bf74bf860e08aa7a8a13790f33bebba16dd2149 Signed-off-by: Shadab Naseem Signed-off-by: Vijay Navnath Kamble (cherry picked from commit 801da882d61293337094c9c4adffb35712498c23) --- .../devicetree/bindings/arm/msm/msm.txt | 1 + arch/arm/boot/dts/qcom/Makefile | 1 + .../qcom/apq8053-camera-sensor-dragon.dtsi | 164 ++++++ .../dts/qcom/apq8053-lite-dragon-v1.0.dts | 28 + .../boot/dts/qcom/apq8053-lite-dragon.dtsi | 539 ++++++++++++++++++ arch/arm/boot/dts/qcom/apq8053-lite.dtsi | 120 ++++ 6 files changed, 853 insertions(+) create mode 100644 arch/arm/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi create mode 100644 arch/arm/boot/dts/qcom/apq8053-lite-dragon-v1.0.dts create mode 100644 arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi create mode 100644 arch/arm/boot/dts/qcom/apq8053-lite.dtsi diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt index 05c4f95901210..356028bce78e9 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm.txt @@ -200,6 +200,7 @@ compatible = "qcom,apq8017-mtp" compatible = "qcom,apq8053-cdp" compatible = "qcom,apq8053-mtp" compatible = "qcom,apq8053-ipc" +compatible = "qcom,apq8053-lite-dragonboard" compatible = "qcom,mdm9630-cdp" compatible = "qcom,mdm9630-mtp" compatible = "qcom,mdm9630-sim" diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index acd211987297b..f4d50d5b24292 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -260,6 +260,7 @@ dtb-$(CONFIG_ARCH_MSM8953) += msm8953-sim.dtb \ apq8053-mtp.dtb \ apq8053-ext-audio-mtp.dtb \ apq8053-ext-codec-rcm.dtb \ + apq8053-lite-dragon-v1.0.dtb \ msm8953-cdp-1200p.dtb \ msm8953-iot-mtp.dtb \ apq8053-iot-mtp.dtb \ diff --git a/arch/arm/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi b/arch/arm/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi new file mode 100644 index 0000000000000..3b5225f50907f --- /dev/null +++ b/arch/arm/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&cci { + actuator0: qcom,actuator@0 { + cell-index = <0>; + reg = <0x0>; + compatible = "qcom,actuator"; + qcom,cci-master = <0>; + cam_vaf-supply = <&pm8953_l22>; + qcom,cam-vreg-name = "cam_vaf"; + qcom,cam-vreg-min-voltage = <2850000>; + qcom,cam-vreg-max-voltage = <2850000>; + qcom,cam-vreg-op-mode = <80000>; + }; + + actuator1: qcom,actuator@1 { + cell-index = <1>; + reg = <0x1>; + compatible = "qcom,actuator"; + qcom,cci-master = <0>; + qcam_vaf-supply = <&eldo_cam1_vcm_vreg>; + qcom,cam-vreg-name = "cam_vaf"; + qcom,cam-vreg-min-voltage = <2850000>; + qcom,cam-vreg-max-voltage = <2850000>; + qcom,cam-vreg-op-mode = <80000>; + }; + + camera0: qcom,camera@0 { + cell-index = <0>; + compatible = "qcom,camera"; + reg = <0x0>; + qcom,csiphy-sd-index = <0>; + qcom,csid-sd-index = <0>; + qcom,mount-angle = <0>; + /*qcom,led-flash-src = <&led_flash0>;*/ + qcom,actuator-src = <&actuator0>; + cam_vio-supply = <&pm8953_l6>; + cam_vdig-supply = <&eldo_cam0_vreg>; + cam_vana-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", + "cam_vana"; + qcom,cam-vreg-min-voltage = <1800000 1100000 2850000>; + qcom,cam-vreg-max-voltage = <1800000 1100000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 100000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default + &cam_sensor_rear_vana>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep + &cam_sensor_rear_vana_sleep>; + gpios = <&tlmm 26 0>, + <&tlmm 40 0>, + <&tlmm 39 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_STANDBY0"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <0>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + camera1: qcom,camera@1 { + cell-index = <1>; + compatible = "qcom,camera"; + reg = <0x1>; + qcom,csiphy-sd-index = <1>; + qcom,csid-sd-index = <1>; + qcom,mount-angle = <0>; + qcom,actuator-src = <&actuator1>; + cam_vio-supply = <&pm8953_l6>; + cam_vdig-supply = <&eldo_cam1_vreg>; + cam_vana-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", + "cam_vana"; + qcom,cam-vreg-min-voltage = <1800000 1100000 2850000>; + qcom,cam-vreg-max-voltage = <1800000 1100000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 100000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front1_default>; + pinctrl-1 = <&cam_sensor_mclk1_sleep + &cam_sensor_front1_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 129 0>, + <&tlmm 130 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_STANDBY1"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <0>; + status = "ok"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + camera2: qcom,camera@2 { + cell-index = <2>; + compatible = "qcom,camera"; + reg = <0x02>; + qcom,csiphy-sd-index = <2>; + qcom,csid-sd-index = <2>; + qcom,mount-angle = <0>; + qcom,actuator-src = <&actuator0>; + cam_vio-supply = <&pm8953_l6>; + cam_vdig-supply = <&eldo_cam2_vreg>; + cam_vana-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", + "cam_vana"; + qcom,cam-vreg-min-voltage = <1800000 1100000 2850000>; + qcom,cam-vreg-max-voltage = <1800000 1100000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 100000>; + /*qcom,gpio-no-mux = <0>;*/ + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_default + &cam_sensor_front_default>; + pinctrl-1 = <&cam_sensor_mclk2_sleep + &cam_sensor_front_sleep>; + gpios = <&tlmm 28 0>, + <&tlmm 131 0>, + <&tlmm 132 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_STANDBY2"; + qcom,sensor-position = <1>; + qcom,sensor-mode = <0>; + qcom,cci-master = <0>; + status = "ok"; + clocks = <&clock_gcc clk_mclk2_clk_src>, + <&clock_gcc clk_gcc_camss_mclk2_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/apq8053-lite-dragon-v1.0.dts b/arch/arm/boot/dts/qcom/apq8053-lite-dragon-v1.0.dts new file mode 100644 index 0000000000000..18cdc4345590f --- /dev/null +++ b/arch/arm/boot/dts/qcom/apq8053-lite-dragon-v1.0.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "apq8053-lite.dtsi" +#include "apq8053-lite-dragon.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. APQ8053 Lite DragonBoard"; + compatible = "qcom,apq8053-lite-dragonboard", "qcom,apq8053", + "qcom,dragonboard"; + qcom,board-id = <0x0102000a 0>; +}; + +&blsp2_uart0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi b/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi new file mode 100644 index 0000000000000..6286015ae2c2c --- /dev/null +++ b/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi @@ -0,0 +1,539 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#include "msm8953-mdss-panels.dtsi" +#include "msm-pmi8950.dtsi" +#include "msm8953-pmi8950.dtsi" +#include "msm8953-pinctrl.dtsi" +#include "apq8053-camera-sensor-dragon.dtsi" + +&soc { + vreg_5p0: vreg_5p0 { + compatible = "regulator-fixed"; + regulator-name = "vreg_5p0"; + status = "ok"; + enable-active-high; + }; + + eldo_cam0_vreg: eldo_cam0_vreg { + compatible = "regulator-fixed"; + regulator-name = "eldo_cam0_vreg"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + status = "ok"; + enable-active-high; + vin-supply = <&pm8953_l5>; + }; + + eldo_cam1_vreg: eldo_cam1_vreg { + compatible = "regulator-fixed"; + regulator-name = "eldo_cam1_vreg"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + status = "ok"; + enable-active-high; + vin-supply = <&pm8953_l5>; + }; + + eldo_cam2_vreg: eldo_cam2_vreg { + compatible = "regulator-fixed"; + regulator-name = "eldo_cam2_vreg"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + status = "ok"; + enable-active-high; + vin-supply = <&pm8953_l5>; + }; + + eldo_cam1_vcm_vreg: eldo_cam1_vcm_vreg { + compatible = "regulator-fixed"; + regulator-name = "eldo_cam1_vcm_vreg"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + status = "ok"; + enable-active-high; + }; + + gpio_keys { + compatible = "gpio-keys"; + input-name = "gpio-keys"; + pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend"; + pinctrl-0 = <&gpio_key_active>; + pinctrl-1 = <&gpio_key_suspend>; + + camera_focus { + label = "camera_focus"; + gpios = <&tlmm 87 0x1>; + linux,input-type = <1>; + linux,code = <0x210>; + debounce-interval = <15>; + }; + + camera_snapshot { + label = "camera_snapshot"; + gpios = <&tlmm 86 0x1>; + linux,input-type = <1>; + linux,code = <0x2fe>; + debounce-interval = <15>; + }; + + vol_up { + label = "volume_up"; + gpios = <&tlmm 85 0x1>; + linux,input-type = <1>; + linux,code = <115>; + debounce-interval = <15>; + }; + }; + + cnss_sdio: qcom,cnss_sdio { + compatible = "qcom,cnss_sdio"; + subsys-name = "AR6320"; + + /** + * There is no vdd-wlan on board and this is not for DSRC. + * IO and XTAL share the same vreg. + */ + vdd-wlan-io-supply = <&pm8953_l6>; + qcom,wlan-ramdump-dynamic = <0x200000>; + qcom,msm-bus,name = "msm-cnss"; + qcom,msm-bus,num-cases = <4>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <79 512 0 0>, /* No vote */ + <79 512 6250 200000>, /* 50 Mbps */ + <79 512 25000 200000>, /* 200 Mbps */ + <79 512 2048000 4096000>; /* MAX */ + }; + + bluetooth: bt_qca9379 { + compatible = "qca,qca6174"; + qca,bt-reset-gpio = <&tlmm 76 0>; /* BT_EN */ + }; +}; + +&rpm_bus { + rpm-regulator-ldoa4 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <4>; + qcom,regulator-type = <0>; + qcom,hpm-min-load = <10000>; + status = "okay"; + + pm8953_l4: regulator-l4 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm8953_l4"; + qcom,set = <3>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + qcom,init-voltage = <1800000>; + status = "okay"; + }; + }; +}; + +&int_codec { + status = "ok"; + qcom,model = "msm8953-snd-card-mtp"; + + /delete-property/ qcom,cdc-us-euro-gpios; + qcom,msm-hs-micbias-type = "internal"; + + qcom,audio-routing = + "RX_BIAS", "MCLK", + "SPK_RX_BIAS", "MCLK", + "INT_LDO_H", "MCLK", + "MIC BIAS Internal1", "Handset Mic", + "MIC BIAS Internal2", "Headset Mic", + "MIC BIAS Internal1", "Secondary Mic", + "AMIC1", "MIC BIAS Internal1", + "AMIC2", "MIC BIAS Internal2", + "AMIC3", "MIC BIAS Internal1", + "DMIC1", "MIC BIAS Internal1", + "DMIC1", "Digital Mic1", + "DMIC2", "MIC BIAS Internal1", + "DMIC2", "Digital Mic2"; + + /delete-property/ asoc-wsa-codec-names; + /delete-property/ asoc-wsa-codec-prefixes; + /delete-property/ msm-vdd-wsa-switch-supply; + /delete-property/ qcom,msm-vdd-wsa-switch-voltage; + /delete-property/ qcom,msm-vdd-wsa-switch-current; +}; + +&pm8953_diangu_dig { + status = "ok"; +}; +&pm8953_diangu_analog { + status = "ok"; +}; + +&wsa881x_211 { + /delete-property/ qcom,spkr-sd-n-gpio; +}; +&wsa881x_212 { + /delete-property/ qcom,spkr-sd-n-gpio; +}; +&wsa881x_213 { + /delete-property/ qcom,spkr-sd-n-gpio; +}; +&wsa881x_214 { + /delete-property/ qcom,spkr-sd-n-gpio; +}; + +&spi_3 { + status = "disabled"; +}; + +&i2c_2 { + status = "disabled"; +}; + +&i2c_3 { + status = "ok"; +}; + +&i2c_5 { + status = "disabled"; +}; + + +&mdss_mdp { + qcom,mdss-pref-prim-intf = "dsi"; +}; + +&mdss_dsi { + hw-config = "dual_dsi"; +}; + +&mdss_dsi_active { + mux { + pins = "gpio61", "gpio100"; + function = "gpio"; + }; + + config { + pins = "gpio61", "gpio100"; + drive-strength = <8>; + bias-disable = <0>; + output-high; + }; +}; + +&mdss_dsi_suspend { + mux { + pins = "gpio61", "gpio100"; + function = "gpio"; + }; + + config { + pins = "gpio61", "gpio100"; + drive-strength = <2>; + bias-pull-down; + }; +}; + +&mdss_dsi0 { + qcom,dsi-pref-prim-pan = <&dsi_truly_1080_vid>; + pinctrl-names = "mdss_default", "mdss_sleep"; + pinctrl-0 = <&mdss_dsi_active &mdss_te_active>; + pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>; + + vdd-supply = <&pm8953_l10>; + vddio-supply = <&pm8953_l6>; + /delete-property/ lab-supply; + /delete-property/ ibb-supply; + + qcom,platform-te-gpio = <&tlmm 24 0>; + qcom,platform-reset-gpio = <&tlmm 61 0>; + qcom,platform-bklight-en-gpio = <&tlmm 100 0>; +}; + +&mdss_dsi1 { + qcom,dsi-pref-prim-pan = <&dsi_adv7533_1080p>; + qcom,bridge-index = <0>; + qcom,pluggable; + + vdd-supply = <&pm8953_l4>; + vddio-supply = <&pm8953_l5>; + + /delete-property/ lab-supply; + /delete-property/ ibb-supply; +}; + +&soc { + dsi_panel_pwr_supply_no_labibb: dsi_panel_pwr_supply_no_labibb { + #address-cells = <1>; + #size-cells = <0>; + + qcom,panel-supply-entry@0 { + reg = <0>; + qcom,supply-name = "vdd"; + qcom,supply-min-voltage = <2850000>; + qcom,supply-max-voltage = <2850000>; + qcom,supply-enable-load = <100000>; + qcom,supply-disable-load = <100>; + }; + + qcom,panel-supply-entry@1 { + reg = <1>; + qcom,supply-name = "vddio"; + qcom,supply-min-voltage = <1800000>; + qcom,supply-max-voltage = <1800000>; + qcom,supply-enable-load = <100000>; + qcom,supply-disable-load = <100>; + qcom,supply-post-on-sleep = <20>; + }; + }; +}; + +&blsp1_uart0 { + status = "ok"; + pinctrl-names = "default"; + pinctrl-0 = <&uart_console_active>; +}; + +&mem_client_3_size { + qcom,peripheral-size = <0x500000>; +}; + +&sdhc_1 { + /* device core power supply */ + vdd-supply = <&pm8953_l8>; + qcom,vdd-voltage-level = <2900000 2900000>; + qcom,vdd-current-level = <200 570000>; + + /* device communication power supply */ + vdd-io-supply = <&pm8953_l5>; + qcom,vdd-io-always-on; + qcom,vdd-io-lpm-sup; + qcom,vdd-io-voltage-level = <1800000 1800000>; + qcom,vdd-io-current-level = <200 325000>; + + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>; + pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>; + + qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000 + 384000000>; + qcom,nonremovable; + qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v"; + + status = "ok"; +}; + +&tlmm{ + sdc2_wlan_gpio_on: sdc2_wlan_gpio_on { + mux { + pins = "gpio75"; + function = "gpio"; + }; + config { + pins = "gpio75"; + drive-strength = <10>; + bias-pull-up; + output-high; + }; + }; + sdc2_wlan_gpio_off: sdc2_wlan_gpio_off { + mux { + pins = "gpio75"; + function = "gpio"; + }; + config { + pins = "gpio75"; + drive-strength = <2>; + bias-disable; + output-low; + }; + }; +}; + +&sdhc_2 { + /* device core power supply */ + vdd-supply = <&pm8953_l11>; + qcom,vdd-voltage-level = <2950000 2950000>; + qcom,vdd-current-level = <15000 800000>; + + /* device communication power supply */ + vdd-io-supply = <&pm8953_l12>; + qcom,vdd-io-always-on; + qcom,vdd-io-voltage-level = <1800000 1800000>; + qcom,vdd-io-current-level = <200 22000>; + qcom,core_3_0v_support; + qcom,nonremovable; + + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on \ + &sdc2_cd_on &sdc2_wlan_gpio_on>; + pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off \ + &sdc2_wlan_gpio_off>; + + #address-cells = <0>; + interrupt-parent = <&sdhc_2>; + interrupts = <0 1 2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xffffffff>; + interrupt-map = <0 &intc 0 125 0 + 1 &intc 0 221 0 + 2 &tlmm 133 0>; + interrupt-names = "hc_irq", "pwr_irq", "status_irq"; + + qcom,clk-rates = <400000 20000000 25000000 50000000>; + qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104"; + + status = "ok"; +}; + +&spmi_bus { + qcom,pmi8950@2 { + qcom,leds@a100 { + compatible = "qcom,leds-qpnp"; + reg = <0xa100 0x100>; + label = "mpp"; + + qcom,led_mpp_2 { + label = "mpp"; + linux,name = "green"; + linux,default-trigger = "none"; + qcom,default-state = "off"; + qcom,max-current = <40>; + qcom,current-setting = <5>; + qcom,id = <6>; + qcom,mode = "manual"; + qcom,source-sel = <1>; + qcom,mode-ctrl = <0x60>; + }; + }; + + qcom,leds@a300 { + compatible = "qcom,leds-qpnp"; + reg = <0xa300 0x100>; + label = "mpp"; + + qcom,led_mpp_4 { + label = "mpp"; + linux,name = "blue"; + linux,default-trigger = "none"; + qcom,default-state = "off"; + qcom,max-current = <40>; + qcom,current-setting = <5>; + qcom,id = <6>; + qcom,mode = "manual"; + qcom,source-sel = <1>; + qcom,mode-ctrl = <0x60>; + }; + }; + }; +}; + +&pm8953_typec { + ss-mux-supply = <&pm8953_l13>; + qcom,ssmux-gpio = <&tlmm 139 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&typec_ssmux_config>; +}; + +/{ + mtp_batterydata: qcom,battery-data { + qcom,batt-id-range-pct = <15>; + #include "batterydata-itech-3000mah.dtsi" + #include "batterydata-ascent-3450mAh.dtsi" + }; +}; + +&pmi8950_charger { + qcom,battery-data = <&mtp_batterydata>; + qcom,chg-led-sw-controls; + qcom,chg-led-support; + qcom,external-typec; + qcom,typec-psy-name = "typec"; + status = "ok"; +}; + +&pmi8950_fg { + qcom,battery-data = <&mtp_batterydata>; +}; + +&pmi_haptic{ + status = "disabled"; + qcom,actuator-type = "lra"; + qcom,lra-auto-res-mode="qwd"; + qcom,lra-high-z="opt1"; + qcom,lra-res-cal-period = <0>; + qcom,wave-play-rate-us = <4165>; +}; + +&wled { + status = "disabled"; +}; + +&flash_led { + status = "disabled"; +}; + +&pm8953_pwm { + status = "ok"; +}; + +&pm8953_vadc { + /delete-node/ chan@13; +}; + +&pmi8950_gpios { + gpio@c000 { /* GPIO_1 */ + status = "ok"; + }; +}; + +&pmi8950_mpps { + mpp@a200 { /* MPP_3 */ + qcom,mode = <1>; /* Digital output */ + qcom,output-type = <0>; /* CMOS logic */ + qcom,vin-sel = <2>; /* 1.8V */ + qcom,src-sel = <0>; /* Constant */ + qcom,master-en = <1>; /* Enable GPIO */ + qcom,invert = <0>; + status = "ok"; + }; +}; + +&pm8953_gpios { + gpio@c000 { /* GPIO_1 */ + status = "ok"; + }; +}; + +&pm8953_mpps { + mpp@a000 { /* MPP_1 */ /* VDD_PX */ + status = "disabled"; + }; + mpp@a100 { /* MPP_2 */ + status = "disabled"; + }; + mpp@a200 { /* MPP_3 */ + status = "disabled"; + }; + + mpp@a300 { /* MPP_4 */ /* WLED_PWM_CTRL */ + qcom,mode = <1>; /* Digital output */ + qcom,output-type = <0>; /* CMOS logic */ + qcom,vin-sel = <0>; /* VPH_PWR */ + qcom,src-sel = <4>; /* DTEST1 */ + qcom,master-en = <1>; /* Enable GPIO */ + qcom,invert = <0>; + status = "ok"; + }; +}; diff --git a/arch/arm/boot/dts/qcom/apq8053-lite.dtsi b/arch/arm/boot/dts/qcom/apq8053-lite.dtsi new file mode 100644 index 0000000000000..d9685d06d8372 --- /dev/null +++ b/arch/arm/boot/dts/qcom/apq8053-lite.dtsi @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "skeleton64.dtsi" +#include "msm8953.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. APQ 8953 Lite"; + compatible = "qcom,apq8053"; + qcom,msm-id = <304 0x0>; + interrupt-parent = <&intc>; + + soc: soc { }; +}; + +&clock_gcc_gfx { + compatible = "qcom,gcc-gfx-sdm450"; + qcom,gfxfreq-corner = + < 0 0 >, + < 133330000 1 >, /* Min SVS */ + < 216000000 2 >, /* Low SVS */ + < 320000000 3 >, /* SVS */ + < 400000000 4 >, /* SVS Plus */ + < 510000000 5 >, /* NOM */ + < 560000000 6 >, /* Nom Plus */ + < 600000000 7 >; /* Turbo */ +}; + +/* GPU Overrides*/ +&msm_gpu { + + /delete-node/qcom,gpu-pwrlevels; + + qcom,gpu-pwrlevels { + #address-cells = <1>; + #size-cells = <0>; + + compatible = "qcom,gpu-pwrlevels"; + + /* TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <600000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <10>; + qcom,bus-max = <10>; + }; + + /* NOM+ */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <560000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <8>; + qcom,bus-max = <10>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <510000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <6>; + qcom,bus-max = <10>; + }; + + /* SVS+ */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <400000000>; + qcom,bus-freq = <7>; + qcom,bus-min = <5>; + qcom,bus-max = <8>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <320000000>; + qcom,bus-freq = <4>; + qcom,bus-min = <2>; + qcom,bus-max = <6>; + }; + + /* Low SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <216000000>; + qcom,bus-freq = <1>; + qcom,bus-min = <1>; + qcom,bus-max = <4>; + }; + + /* Min SVS */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <133300000>; + qcom,bus-freq = <1>; + qcom,bus-min = <1>; + qcom,bus-max = <4>; + }; + /* XO */ + qcom,gpu-pwrlevel@7 { + reg = <7>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + }; + }; +}; From 75ae12ccb34dfaace739a8cc029e979ea2b59f6b Mon Sep 17 00:00:00 2001 From: annamraj Date: Wed, 22 Nov 2017 12:21:01 +0530 Subject: [PATCH 265/508] msm: jpegdma: Fix for ASAN issues in jpegdma module Adding Lock mechanism to avoid concurrency issues between reqbufs and streamoff calls. Change-Id: I955b30a7d05554366df3a2e6c44fc21c5367b2c2 Signed-off-by: annamraj --- .../msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c index fad858d7fe89c..ebae1501118e0 100644 --- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c +++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c @@ -756,9 +756,12 @@ static int msm_jpegdma_s_fmt_vid_out(struct file *file, static int msm_jpegdma_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *req) { + int ret = 0; struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh); - - return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, req); + mutex_lock(&ctx->lock); + ret = v4l2_m2m_reqbufs(file, ctx->m2m_ctx, req); + mutex_unlock(&ctx->lock); + return ret; } /* @@ -835,11 +838,11 @@ static int msm_jpegdma_streamoff(struct file *file, { struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh); int ret; - + mutex_lock(&ctx->lock); ret = v4l2_m2m_streamoff(file, ctx->m2m_ctx, buf_type); if (ret < 0) dev_err(ctx->jdma_device->dev, "Stream off fails\n"); - + mutex_unlock(&ctx->lock); return ret; } From 1214306b07de220553dfded1581190e8eada23b6 Mon Sep 17 00:00:00 2001 From: Meera Gande Date: Fri, 23 Mar 2018 16:13:18 +0530 Subject: [PATCH 266/508] mm-camera2:isp2: Avoid use after free buffer In the code, there are certain calls that can try to access the bffer pointer variable after free, as the same pointer can be freed at RELEASE_BUF call at the same time. CRs-Fixed: 2149998 Change-Id: I4f7a48613b614138916ae33e7783b0c172330321 Signed-off-by: Meera Gande Signed-off-by: Vijay Kumar TM --- drivers/media/platform/msm/camera_v2/isp/msm_isp40.c | 6 +++++- drivers/media/platform/msm/camera_v2/isp/msm_isp44.c | 3 ++- drivers/media/platform/msm/camera_v2/isp/msm_isp46.c | 3 ++- drivers/media/platform/msm/camera_v2/isp/msm_isp47.c | 6 +++++- .../media/platform/msm/camera_v2/isp/msm_isp_axi_util.c | 6 +++++- drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c | 8 ++++++++ 6 files changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c index e042ce9b527df..50ed167874bea 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c @@ -1053,15 +1053,18 @@ static int msm_vfe40_start_fetch_engine(struct vfe_device *vfe_dev, fe_cfg->stream_id); vfe_dev->fetch_engine_info.bufq_handle = bufq_handle; + mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); if (rc < 0 || !buf) { pr_err("%s: No fetch buffer rc= %d\n", __func__, rc); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } mapped_info = buf->mapped_info[0]; buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED; + mutex_unlock(&vfe_dev->buf_mgr->lock); } else { rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr, &mapped_info, fe_cfg->fd); @@ -1113,14 +1116,15 @@ static int msm_vfe40_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev, mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); - mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc < 0 || !buf) { pr_err("%s: No fetch buffer rc= %d buf= %pK\n", __func__, rc, buf); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } mapped_info = buf->mapped_info[0]; buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED; + mutex_unlock(&vfe_dev->buf_mgr->lock); } else { rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr, &mapped_info, fe_cfg->fd); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c index aa4690d1e28a9..eec59d454130f 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c @@ -883,13 +883,14 @@ static int msm_vfe44_fetch_engine_start(struct vfe_device *vfe_dev, mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); - mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc < 0) { pr_err("%s: No fetch buffer\n", __func__); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } mapped_info = buf->mapped_info[0]; buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED; + mutex_unlock(&vfe_dev->buf_mgr->lock); } else { rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr, &mapped_info, fe_cfg->fd); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c index 5f4588711a024..8c14e9a33b7d1 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c @@ -827,14 +827,15 @@ static int msm_vfe46_start_fetch_engine(struct vfe_device *vfe_dev, mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); - mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc < 0 || !buf) { pr_err("%s: No fetch buffer rc= %d buf= %pK\n", __func__, rc, buf); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } mapped_info = buf->mapped_info[0]; buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED; + mutex_unlock(&vfe_dev->buf_mgr->lock); } else { rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr, &mapped_info, fe_cfg->fd); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c index fdf9d0c442da0..4170257b7e7e1 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -1055,15 +1055,18 @@ int msm_vfe47_start_fetch_engine(struct vfe_device *vfe_dev, fe_cfg->stream_id); vfe_dev->fetch_engine_info.bufq_handle = bufq_handle; + mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); if (rc < 0 || !buf) { pr_err("%s: No fetch buffer rc= %d buf= %pK\n", __func__, rc, buf); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } mapped_info = buf->mapped_info[0]; buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED; + mutex_unlock(&vfe_dev->buf_mgr->lock); } else { rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr, &mapped_info, fe_cfg->fd); @@ -1116,14 +1119,15 @@ int msm_vfe47_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev, mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); - mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc < 0 || !buf) { pr_err("%s: No fetch buffer rc= %d buf= %pK\n", __func__, rc, buf); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } mapped_info = buf->mapped_info[0]; buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED; + mutex_unlock(&vfe_dev->buf_mgr->lock); } else { rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr, &mapped_info, fe_cfg->fd); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index bd27839576f96..4b7f8017d6724 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -2516,7 +2516,7 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev, j--; continue; } - stream_info->undelivered_request_cnt = 0; + stream_info->undelivered_request_cnt = 0; while (!list_empty(&stream_info->request_q)) { queue_req = list_first_entry_or_null( &stream_info->request_q, @@ -3760,10 +3760,12 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) &update_cmd->update_info[i]; stream_info = &axi_data->stream_info[HANDLE_TO_IDX( update_info->stream_handle)]; + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_request_frame(vfe_dev, stream_info, update_info->user_stream_id, update_info->frame_id, MSM_ISP_INVALID_BUF_INDEX); + mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc) pr_err("%s failed to request frame!\n", __func__); @@ -3835,10 +3837,12 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) } stream_info = &axi_data->stream_info[HANDLE_TO_IDX( req_frm->stream_handle)]; + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_request_frame(vfe_dev, stream_info, req_frm->user_stream_id, req_frm->frame_id, req_frm->buf_index); + mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc) pr_err("%s failed to request frame!\n", __func__); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index a78dec3337385..24bf22795bc95 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -419,8 +419,10 @@ static int msm_isp_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev, 0, 1); msm_isp_reset_framedrop(vfe_dev, stream_info); + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_cfg_offline_ping_pong_address(vfe_dev, stream_info, VFE_PING_FLAG, fe_cfg->output_buf_idx); + mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc < 0) { pr_err("%s: Fetch engine config failed\n", __func__); return -EINVAL; @@ -884,7 +886,9 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, break; case VIDIOC_MSM_ISP_CFG_STREAM: mutex_lock(&vfe_dev->core_mutex); + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_cfg_axi_stream(vfe_dev, arg); + mutex_unlock(&vfe_dev->buf_mgr->lock); mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_CFG_HW_STATE: @@ -914,6 +918,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, break; case VIDIOC_MSM_ISP_AXI_RESTART: mutex_lock(&vfe_dev->core_mutex); + mutex_lock(&vfe_dev->buf_mgr->lock); if (atomic_read(&vfe_dev->error_info.overflow_state) != HALT_ENFORCED) { rc = msm_isp_stats_restart(vfe_dev); @@ -924,6 +929,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, pr_err_ratelimited("%s: no AXI restart, halt enforced.\n", __func__); } + mutex_unlock(&vfe_dev->buf_mgr->lock); mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_INPUT_CFG: @@ -996,7 +1002,9 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, break; case VIDIOC_MSM_ISP_CFG_STATS_STREAM: mutex_lock(&vfe_dev->core_mutex); + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_cfg_stats_stream(vfe_dev, arg); + mutex_unlock(&vfe_dev->buf_mgr->lock); mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_UPDATE_STATS_STREAM: From 1efcd165d25cb411a3bf6738ddaf4f9f8cf9aed5 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Wed, 14 Mar 2018 14:32:27 +0530 Subject: [PATCH 267/508] wlan: Introduce HDD Request Manager infrastructure qcacld-3.0 to prima propagation. Many operations within the wlan driver occur in an asynchronous manner. Requests are received by HDD via one of the kernel interfaces (ioctl, nl80211, virtual file system, etc.). The requests are translated to an internal format and are then passed to lower layers for processing. For requests which require a response, that response comes up from the lower layers in a separate thread of execution, ultimately resulting in a call to a callback function that was provided by HDD as part of the initial request. So a mechanism is needed to synchronize the request and response. Currently there are various mechanisms which perform these synchronizations, but experience with them has revealed some flaws. So a universal mechanism is needed to synchronize the request and response which addresses all of the known flaws. This framework provides that mechanism. Change-Id: If4d5912710f8a3b5e87adf76f828a646b7cc2983 CRs-Fixed: 2205457 --- CORE/HDD/inc/wlan_hdd_request_manager.h | 220 ++++++++++++++++++++++++ CORE/HDD/src/wlan_hdd_main.c | 6 + CORE/HDD/src/wlan_hdd_request_manager.c | 194 +++++++++++++++++++++ Kbuild | 1 + 4 files changed, 421 insertions(+) create mode 100644 CORE/HDD/inc/wlan_hdd_request_manager.h create mode 100644 CORE/HDD/src/wlan_hdd_request_manager.c diff --git a/CORE/HDD/inc/wlan_hdd_request_manager.h b/CORE/HDD/inc/wlan_hdd_request_manager.h new file mode 100644 index 0000000000000..357ef2a12d692 --- /dev/null +++ b/CORE/HDD/inc/wlan_hdd_request_manager.h @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __WLAN_HDD_REQUEST_MANAGER_H__ +#define __WLAN_HDD_REQUEST_MANAGER_H__ + +/** + * DOC: WLAN HDD REQUEST MANAGER + * + * Many operations within the wlan driver occur in an asynchronous + * manner. Requests are received by HDD via one of the kernel + * interfaces (ioctl, nl80211, virtual file system, etc.). The + * requests are translated to an internal format and are then passed + * to lower layers, usually via SME, for processing. For requests + * which require a response, that response comes up from the lower + * layers in a separate thread of execution, ultimately resulting in a + * call to a callback function that was provided by HDD as part of the + * initial request. So a mechanism is needed to synchronize the + * request and response. This framework provides that mechanism. + * + * Once the framework has been initialized, the typical sequence of + * events is as follows: + * + * Request Thread: + * 1. Create a &struct hdd_request_params which describes the request. + * 2. Call hdd_request_alloc() to allocate a &struct hdd_request. + * 3. Call hdd_request_priv() to get a pointer to the private data. + * 4. Place any information which must be shared with the Response + * Callback in the private data area. + * 5. Call hdd_request_cookie() to get the unique cookie assigned + * to the request. + * 6. Call the underlying request handling API, passing the cookie + * as the callback's private context. + * 7. Call hdd_request_wait_for_response() to wait for the response + * (or for the request to time out). + * 8. Use the return status to see if the request was successful. If + * it was, retrieve any response information from the private + * structure and prepare a response for userspace. + * 9. Call hdd_request_put() to relinquish access to the request. + * 10. Return status to the caller. + * + * Response Callback: + * 1. Call hdd_request_get() with the provided cookie to see if the + * request structure is still valid. If it returns %NULL then + * return since this means the request thread has already timed + * out. + * 2. Call hdd_request_priv() to get access to the private data area. + * 3. Write response data into the private data area. + * 4. Call hdd_request_complete() to indicate that the response is + * ready to be processed by the request thread. + * 5. Call hdd_request_put() to relinquish the callback function's + * reference to the request. + */ + +/* this is opaque to clients */ +struct hdd_request; + +/** + * typedef hdd_request_dealloc - Private data deallocation function + */ +typedef void (*hdd_request_dealloc)(void *priv); + +/** + * struct hdd_request_params - HDD request parameters + * @priv_size: Size of the private data area required to pass + * information between the request thread and the response callback. + * @timeout_ms: The amount of time to wait for a response in milliseconds. + * @dealloc: Function to be called when the request is destroyed to + * deallocate any allocations made in the private area of the + * request struct. Can be %NULL if no private allocations are + * made. + */ +struct hdd_request_params { + uint32_t priv_size; + uint32_t timeout_ms; + hdd_request_dealloc dealloc; +}; + +/** + * hdd_request_alloc() - Allocate a request struct + * @params: parameter block that specifies the attributes of the + * request + * + * This function will attempt to allocate a &struct hdd_request with + * the specified @params. If successful, the caller can then use + * request struct to make an asynchronous request. Once the request is + * no longer needed, the reference should be relinquished via a call + * to hdd_request_put(). + * + * Return: A pointer to an allocated &struct hdd_request (which also + * contains room for the private buffer) if the allocation is + * successful, %NULL if the allocation fails. + */ +struct hdd_request *hdd_request_alloc(const struct hdd_request_params *params); + +/** + * hdd_request_priv() - Get pointer to request private data + * @request: The request struct that contains the private data + * + * This function will return a pointer to the private data area that + * is part of the request struct. The caller must already have a valid + * reference to @request from either hdd_request_alloc() or + * hdd_request_get(). + * + * Returns: pointer to the private data area. Note that this pointer + * will always be an offset from the input @request pointer and hence + * this function will never return %NULL. + */ +void *hdd_request_priv(struct hdd_request *request); + +/** + * hdd_request_cookie() - Get cookie of a request + * @request: The request struct associated with the request + * + * This function will return the unique cookie that has been assigned + * to the request. This cookie can subsequently be passed to + * hdd_request_get() to retrieve the request. + * + * Note that the cookie is defined as a void pointer as it is intended + * to be passed as an opaque context pointer from HDD to underlying + * layers when making a request, and subsequently passed back to HDD + * as an opaque pointer in an asynchronous callback. + * + * Returns: The cookie assigned to the request. + */ +void *hdd_request_cookie(struct hdd_request *request); + +/** + * hdd_request_get() - Get a reference to a request struct + * @cookie: The cookie of the request struct that needs to be + * referenced + * + * This function will use the cookie to determine if the associated + * request struct is valid, and if so, will increment the reference + * count of the struct. This means the caller is guaranteed that the + * request struct is valid and the underlying private data can be + * dereferenced. + * + * Returns: The pointer to the request struct associated with @cookie + * if the request is still valid, %NULL if the underlying request + * struct is no longer valid. + */ +struct hdd_request *hdd_request_get(void *cookie); + +/** + * hdd_request_put() - Release a reference to a request struct + * @request: The request struct that no longer needs to be referenced + * + * This function will decrement the reference count of the struct, and + * will clean up the request if this is the last reference. The caller + * must already have a valid reference to @request, either from + * hdd_request_alloc() or hdd_request_get(). + * + * Returns: Nothing + */ +void hdd_request_put(struct hdd_request *request); + +/** + * hdd_request_wait_for_response() - Wait for a response + * @request: The request struct associated with the request + * + * This function will wait until either a response is received and + * communicated via hdd_request_complete(), or until the request + * timeout period expires. + * + * Returns: 0 if a response was received, -ETIMEDOUT if the response + * timed out. + */ +int hdd_request_wait_for_response(struct hdd_request *request); + +/** + * hdd_request_complete() - Complete a request + * @request: The request struct associated with the request + * + * This function is used to indicate that a response has been received + * and that any information required by the request thread has been + * copied into the private data area of the request struct. This will + * unblock any hdd_request_wait_for_response() that is pending on this + * @request. + * + * Returns: Nothing + */ +void hdd_request_complete(struct hdd_request *request); + +/** + * hdd_request_manager_init() - Initialize the HDD Request Manager + * + * This function must be called during system initialization to + * initialize the HDD Request Manager. + * + * Returns: Nothing + */ +void hdd_request_manager_init(void); + +/** + * hdd_request_manager_deinit() - Deinitialize the HDD Request Manager + * + * This function must be called during system shutdown to deinitialize + * the HDD Request Manager. + * + * Returns: Nothing + */ +void hdd_request_manager_deinit(void); + +#endif /* __WLAN_HDD_REQUEST_MANAGER_H__ */ diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 9199439a99b78..0270d8f2ccbf6 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -120,6 +120,7 @@ int wlan_hdd_ftm_start(hdd_context_t *pAdapter); #endif #include "wlan_hdd_debugfs.h" #include "sapInternal.h" +#include "wlan_hdd_request_manager.h" #ifdef MODULE #define WLAN_MODULE_NAME module_name(THIS_MODULE) @@ -11967,6 +11968,8 @@ void hdd_wlan_exit(hdd_context_t *pHddCtx) pHddCtx->cfg_ini= NULL; } + hdd_request_manager_deinit(); + /* FTM/MONITOR mode, WIPHY did not registered If un-register here, system crash will happen */ if (!(VOS_FTM_MODE == hdd_get_conparam() || @@ -12974,6 +12977,8 @@ int hdd_wlan_startup(struct device *dev ) goto err_free_hdd_context; } + hdd_request_manager_init(); + vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t )); // Read and parse the qcom_cfg.ini file @@ -13855,6 +13860,7 @@ int hdd_wlan_startup(struct device *dev ) vos_watchdog_close(pVosContext); err_config: + hdd_request_manager_deinit(); kfree(pHddCtx->cfg_ini); pHddCtx->cfg_ini= NULL; diff --git a/CORE/HDD/src/wlan_hdd_request_manager.c b/CORE/HDD/src/wlan_hdd_request_manager.c new file mode 100644 index 0000000000000..2f96e982d18f6 --- /dev/null +++ b/CORE/HDD/src/wlan_hdd_request_manager.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include "wlan_hdd_request_manager.h" +#include "wlan_hdd_main.h" +#include "wlan_hdd_dp_utils.h" +#include "vos_event.h" +#include "vos_memory.h" + +/* arbitrary value */ +#define MAX_NUM_REQUESTS 20 + +static bool is_initialized; +static hdd_list_t requests; +static spinlock_t spinlock; +static void *cookie; + +struct hdd_request { + hdd_list_node_t node; + void *cookie; + uint32_t reference_count; + struct hdd_request_params params; + vos_event_t completed; +}; + +/* must be called with spinlock held */ +static void hdd_request_unlink(struct hdd_request *request) +{ + hdd_list_remove_node(&requests, &request->node); +} + +static void hdd_request_destroy(struct hdd_request *request) +{ + struct hdd_request_params *params; + + params = &request->params; + if (params->dealloc) { + void *priv = hdd_request_priv(request); + + params->dealloc(priv); + } + vos_event_destroy(&request->completed); + vos_mem_free(request); +} + +/* must be called with spinlock held */ +static struct hdd_request *hdd_request_find(void *cookie) +{ + VOS_STATUS status; + struct hdd_request *request; + hdd_list_node_t *node; + + status = hdd_list_peek_front(&requests, &node); + while (VOS_IS_STATUS_SUCCESS(status)) { + request = container_of(node, struct hdd_request, node); + if (request->cookie == cookie) + return request; + status = hdd_list_peek_next(&requests, node, &node); + } + + return NULL; +} + +struct hdd_request *hdd_request_alloc(const struct hdd_request_params *params) +{ + size_t length; + struct hdd_request *request; + + if (!is_initialized) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("invoked when not initialized from %pS"), + (void *)_RET_IP_); + return NULL; + } + + length = sizeof(*request) + params->priv_size; + request = vos_mem_malloc(length); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("allocation failed for %pS"), + (void *)_RET_IP_); + return NULL; + } + request->reference_count = 1; + request->params = *params; + vos_event_init(&request->completed); + spin_lock_bh(&spinlock); + request->cookie = cookie++; + hdd_list_insert_back(&requests, &request->node); + spin_unlock_bh(&spinlock); + hddLog(VOS_TRACE_LEVEL_INFO, FL("request %pK, cookie %pK, caller %pS"), + request, request->cookie, (void *)_RET_IP_); + + return request; +} + +void *hdd_request_priv(struct hdd_request *request) +{ + /* private data area immediately follows the struct hdd_request */ + return request + 1; +} + +void *hdd_request_cookie(struct hdd_request *request) +{ + return request->cookie; +} + +struct hdd_request *hdd_request_get(void *cookie) +{ + struct hdd_request *request; + + if (!is_initialized) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("invoked when not initialized from %pS"), + (void *)_RET_IP_); + return NULL; + } + spin_lock_bh(&spinlock); + request = hdd_request_find(cookie); + if (request) + request->reference_count++; + spin_unlock_bh(&spinlock); + hddLog(VOS_TRACE_LEVEL_INFO, FL("cookie %pK, request %pK, caller %pS"), + cookie, request, (void *)_RET_IP_); + + return request; +} + +void hdd_request_put(struct hdd_request *request) +{ + bool unlinked = false; + + hddLog(VOS_TRACE_LEVEL_INFO, FL("request %pK, cookie %pK, caller %pS"), + request, request->cookie, (void *)_RET_IP_); + spin_lock_bh(&spinlock); + request->reference_count--; + if (0 == request->reference_count) { + hdd_request_unlink(request); + unlinked = true; + } + spin_unlock_bh(&spinlock); + if (unlinked) + hdd_request_destroy(request); +} + +int hdd_request_wait_for_response(struct hdd_request *request) +{ + return vos_wait_single_event(&request->completed, + request->params.timeout_ms); +} + +void hdd_request_complete(struct hdd_request *request) +{ + (void)vos_event_set(&request->completed); +} + +void hdd_request_manager_init(void) +{ + hddLog(VOS_TRACE_LEVEL_INFO, FL("%pS"), (void *)_RET_IP_); + if (is_initialized) + return; + + hdd_list_init(&requests, MAX_NUM_REQUESTS); + spin_lock_init(&spinlock); + is_initialized = true; +} + +/* + * hdd_request_manager_deinit implementation note: + * It is intentional that we do not destroy the list or the spinlock. + * This allows threads to still access the infrastructure even when it + * has been deinitialized. Since neither lists nor spinlocks consume + * resources this does not result in a resource leak. + */ +void hdd_request_manager_deinit(void) +{ + hddLog(VOS_TRACE_LEVEL_INFO, FL("%pS"), (void *)_RET_IP_); + is_initialized = false; +} diff --git a/Kbuild b/Kbuild index baadf2982f169..d584ae8b04281 100644 --- a/Kbuild +++ b/Kbuild @@ -150,6 +150,7 @@ HDD_OBJS := $(HDD_SRC_DIR)/wlan_hdd_assoc.o \ $(HDD_SRC_DIR)/wlan_hdd_main.o \ $(HDD_SRC_DIR)/wlan_hdd_mib.o \ $(HDD_SRC_DIR)/wlan_hdd_oemdata.o \ + $(HDD_SRC_DIR)/wlan_hdd_request_manager.o \ $(HDD_SRC_DIR)/wlan_hdd_scan.o \ $(HDD_SRC_DIR)/wlan_hdd_softap_tx_rx.o \ $(HDD_SRC_DIR)/wlan_hdd_tx_rx.o \ From 54447615ec8c43e811f0bbfbdbfdd846b6357fbe Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Sirasanagandla Date: Tue, 6 Mar 2018 15:49:56 +0530 Subject: [PATCH 268/508] wlan: Fix SSR failure in STA + MON SCC When SSR is triggered in STA + Mon SCC, during reset all adapters, Monitor adapter is trying to acquire un-initialized sta_hash_lock which is resulting in SSR failure To fix this, initialize sta_hash_lock in hdd_init_mon_mode(). Change-Id: I271b2a9f68fd61250986066ed2217202636665a0 CRs-Fixed: 2201502 --- CORE/HDD/src/wlan_hdd_main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 0270d8f2ccbf6..af0ed7dfab19b 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -9221,8 +9221,11 @@ void hdd_monPostMsgCb(tANI_U32 *magic, struct completion *cmpVar) void hdd_init_mon_mode (hdd_adapter_t *pAdapter) { hdd_mon_ctx_t *pMonCtx = NULL; - pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter); + spin_lock_init(&pAdapter->sta_hash_lock); + pAdapter->is_sta_id_hash_initialized = VOS_FALSE; + + pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter); pMonCtx->state = 0; pMonCtx->ChannelNo = 1; pMonCtx->ChannelBW = 20; @@ -14676,7 +14679,6 @@ void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode) case VOS_P2P_CLIENT_MODE: case VOS_P2P_GO_MODE: case VOS_STA_SAP_MODE: - case VOS_MONITOR_MODE: pHddCtx->no_of_active_sessions[mode]++; break; default: @@ -14711,7 +14713,6 @@ void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode) case VOS_P2P_CLIENT_MODE: case VOS_P2P_GO_MODE: case VOS_STA_SAP_MODE: - case VOS_MONITOR_MODE: if (pHddCtx->no_of_active_sessions[mode] > 0) pHddCtx->no_of_active_sessions[mode]--; else From da449f1e1e4f64bfcb08faf9245da4f0e8821c97 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Tue, 13 Mar 2018 18:19:19 +0530 Subject: [PATCH 269/508] wlan: STA+MON: Initialize monitor mode tx/rx modules during re-init Presently in STA+MON case, monitor mode tx/rx modules which are de-initialized during shutdown are not initialized back during re-init, leading to access of uninitialized data. During WLAN driver re-init, initialize monitor mode adapter's tx/rx objects and register rx callback. Change-Id: I120aa74783c0864ddc5085023b94012d8b3658a6 CRs-Fixed: 2204820 --- CORE/HDD/src/wlan_hdd_main.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index af0ed7dfab19b..d62ec5ebe92a7 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -10486,7 +10486,9 @@ VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx ) } pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE; - pAdapter->sessionCtx.monitor.state = MON_MODE_STOP; + + if (pAdapter->device_mode == WLAN_HDD_MONITOR) + pAdapter->sessionCtx.monitor.state = MON_MODE_STOP; hdd_deinit_tx_rx(pAdapter); @@ -10729,6 +10731,7 @@ VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx ) VOS_STATUS status; hdd_adapter_t *pAdapter; eConnectionState connState; + v_CONTEXT_t pVosContext; ENTER(); @@ -10805,8 +10808,18 @@ VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx ) break; case WLAN_HDD_MONITOR: - /* monitor interface start */ + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + hddLog(VOS_TRACE_LEVEL_INFO, FL("[SSR] monitor mode")); + if (!pVosContext) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("vos context is NULL")); + break; + } + + hdd_init_tx_rx(pAdapter); + WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk); break; + default: break; } From 36dfa52d91409536765dd474f18c999901996886 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Mon, 12 Mar 2018 16:42:08 +0530 Subject: [PATCH 270/508] wlan: Don't process tdls_mgmt cfg operation if tdls context is invalid Return if TDLS context is NULL while processing tdls_mgmt cfg operation to resolve possible NULL pointer dereference. Change-Id: I24f70070365e2969d9aa18e039f3b34e12c0e2ef CRs-Fixed: 2204004 --- CORE/HDD/src/wlan_hdd_cfg80211.c | 1 + 1 file changed, 1 insertion(+) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 40a6177ae8d58..3bc2d0c226efa 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -19824,6 +19824,7 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, if (!pHddTdlsCtx) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: pHddTdlsCtx not valid.", __func__); + return -EINVAL; } if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) From c6c6a44416a27d424df2c870be804021b6c6e9e4 Mon Sep 17 00:00:00 2001 From: Sravan Kumar Kairam Date: Tue, 27 Mar 2018 16:59:13 +0530 Subject: [PATCH 271/508] wlan: Start TX sample timer only for SAP flow control Start TX sample timer only when FW supports the soft AP TX flow buffer allocation control feature. Change-Id: I717e33d56ce50a5b40bf7694916639b101aa2e47 CRs-Fixed: 2213536 --- CORE/TL/src/wlan_qct_tl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c index 845a58d3f0a81..57ddaa9356173 100644 --- a/CORE/TL/src/wlan_qct_tl.c +++ b/CORE/TL/src/wlan_qct_tl.c @@ -843,7 +843,8 @@ WLANTL_Start vos_atomic_set_U8( &pTLCb->ucTxSuspended, 0); pTLCb->uResCount = uResCount; - vos_timer_start(&pTLCb->tx_frames_timer, WLANTL_SAMPLE_INTERVAL); + if (IS_FEATURE_SUPPORTED_BY_FW(SAP_BUFF_ALLOC)) + vos_timer_start(&pTLCb->tx_frames_timer, WLANTL_SAMPLE_INTERVAL); return VOS_STATUS_SUCCESS; }/* WLANTL_Start */ From 68268a3f2766ccb8bb80effc64c80d85e95e2b44 Mon Sep 17 00:00:00 2001 From: Madhukar Sandi Date: Tue, 27 Mar 2018 16:52:41 +0530 Subject: [PATCH 272/508] ARM: dts: msm: Use PM8916 LBC primary charger for apq8009 Dragon Board PM8916 is the primary charger on the apq8009 dragon board, hence remove the 'external-charger' config from it. Change-Id: Ia6620a0aa7c98751fce1a8f8d45b4b95e24aadca Signed-off-by: Madhukar Sandi --- arch/arm/boot/dts/qcom/apq8009-dragon.dts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm/boot/dts/qcom/apq8009-dragon.dts b/arch/arm/boot/dts/qcom/apq8009-dragon.dts index fb21bfee01f42..439e461bdd2c7 100644 --- a/arch/arm/boot/dts/qcom/apq8009-dragon.dts +++ b/arch/arm/boot/dts/qcom/apq8009-dragon.dts @@ -112,11 +112,6 @@ }; }; -&pm8916_chg { - status = "ok"; - qcom,use-external-charger; -}; - &pm8916_bms { status = "ok"; qcom,disable-bms; From 68934264d0bea79fbc5ea767458a9e3932a22b62 Mon Sep 17 00:00:00 2001 From: Siddartha Mohanadoss Date: Mon, 19 Mar 2018 15:43:50 -0700 Subject: [PATCH 273/508] msm: mhi_dev: Add uevent support Clients need notification for connect, disconnect state for the individual channels once they are updated by the host. Send the events for clients listening to uevents such as MBIMD for channel state updates. Client can also poll for the current channel state through MHI ctrl uevent. Change-Id: Ie764b4866e5e41df072a7a76105a740c89f91f17 Signed-off-by: Siddartha Mohanadoss --- drivers/platform/msm/mhi_dev/mhi.c | 56 +++++++++++++++++------ drivers/platform/msm/mhi_dev/mhi.h | 28 ++++++++++-- drivers/platform/msm/mhi_dev/mhi_uci.c | 61 +++++++++++++++++++++++++- 3 files changed, 126 insertions(+), 19 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index a2fe9017152a6..6e3a7790a4b8b 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -72,11 +72,12 @@ static struct mhi_dev *mhi_ctx; static void mhi_hwc_cb(void *priv, enum ipa_mhi_event_type event, unsigned long data); static void mhi_ring_init_cb(void *user_data); -static void mhi_update_state_info(uint32_t info); +static void mhi_update_state_info(uint32_t uevent_idx, enum mhi_ctrl_info info); static int mhi_deinit(struct mhi_dev *mhi); static void mhi_dev_resume_init_with_link_up(struct ep_pcie_notify *notify); static int mhi_dev_pcie_notify_event; static void mhi_dev_transfer_completion_cb(void *mreq); +static struct mhi_dev_uevent_info channel_state_info[MHI_MAX_CHANNELS]; /* * mhi_dev_ring_cache_completion_cb () - Call back function called @@ -466,7 +467,7 @@ static void mhi_hwc_cb(void *priv, enum ipa_mhi_event_type event, return; } - mhi_update_state_info(MHI_STATE_CONNECTED); + mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONNECTED); ep_pcie_mask_irq_event(mhi_ctx->phandle, EP_PCIE_INT_EVT_MHI_A7, true); @@ -927,6 +928,8 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, struct mhi_addr host_addr; struct mhi_dev_channel *ch; struct mhi_dev_ring *ring; + char *connected[2] = { "MHI_CHANNEL_STATE_12=CONNECTED", NULL}; + char *disconnected[2] = { "MHI_CHANNEL_STATE_12=DISCONNECTED", NULL}; ch_id = el->generic.chid; mhi_log(MHI_MSG_VERBOSE, "for channel:%d and cmd:%d\n", @@ -992,6 +995,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, if (rc) pr_err("Error sending command completion event\n"); + mhi_update_state_info(ch_id, MHI_STATE_CONNECTED); + if (ch_id == MHI_CLIENT_MBIM_OUT) + kobject_uevent_env(&mhi_ctx->dev->kobj, + KOBJ_CHANGE, connected); break; case MHI_DEV_RING_EL_STOP: if (ch_id >= HW_CHANNEL_BASE) { @@ -1046,6 +1053,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, pr_err("stop event send failed\n"); mutex_unlock(&ch->ch_lock); + mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED); + if (ch_id == MHI_CLIENT_MBIM_OUT) + kobject_uevent_env(&mhi_ctx->dev->kobj, + KOBJ_CHANGE, disconnected); } break; case MHI_DEV_RING_EL_RESET: @@ -1119,6 +1130,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, if (rc) pr_err("Error sending command completion event\n"); mutex_unlock(&ch->ch_lock); + mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED); + if (ch_id == MHI_CLIENT_MBIM_OUT) + kobject_uevent_env(&mhi_ctx->dev->kobj, + KOBJ_CHANGE, disconnected); } break; default: @@ -1300,7 +1315,7 @@ static int mhi_dev_abort(struct mhi_dev *mhi) } /* Update ctrl node */ - mhi_update_state_info(MHI_STATE_DISCONNECTED); + mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_DISCONNECTED); flush_workqueue(mhi->ring_init_wq); flush_workqueue(mhi->pending_ring_wq); @@ -1781,7 +1796,7 @@ int mhi_dev_resume(struct mhi_dev *mhi) mhi_dev_write_to_host(mhi, &data_transfer, NULL, MHI_DEV_DMA_SYNC); } - mhi_update_state_info(MHI_STATE_CONNECTED); + mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONNECTED); atomic_set(&mhi->is_suspended, 0); @@ -2338,7 +2353,8 @@ static void mhi_dev_enable(struct work_struct *work) if (mhi_ctx->config_iatu || mhi_ctx->mhi_int) enable_irq(mhi_ctx->mhi_irq); - mhi_update_state_info(MHI_STATE_CONNECTED); + mhi_update_state_info(MHI_DEV_UEVENT_CTRL, + MHI_STATE_CONFIGURED); } static void mhi_ring_init_cb(void *data) @@ -2353,25 +2369,36 @@ static void mhi_ring_init_cb(void *data) queue_work(mhi->ring_init_wq, &mhi->ring_init_cb_work); } -static void mhi_update_state_info(uint32_t info) +static void mhi_update_state_info(uint32_t uevent_idx, enum mhi_ctrl_info info) { struct mhi_dev_client_cb_reason reason; - mhi_ctx->ctrl_info = info; + if (uevent_idx == MHI_DEV_UEVENT_CTRL) + mhi_ctx->ctrl_info = info; - reason.reason = MHI_DEV_CTRL_UPDATE; - uci_ctrl_update(&reason); + channel_state_info[uevent_idx].ctrl_info = info; + + if (uevent_idx == MHI_CLIENT_QMI_OUT || + uevent_idx == MHI_CLIENT_QMI_IN) { + /* For legacy reasons for QTI client */ + reason.reason = MHI_DEV_CTRL_UPDATE; + uci_ctrl_update(&reason); + } } -int mhi_ctrl_state_info(uint32_t *info) +int mhi_ctrl_state_info(uint32_t idx, uint32_t *info) { if (!info) { pr_err("Invalid info\n"); return -EINVAL; } - *info = mhi_ctx->ctrl_info; - mhi_log(MHI_MSG_VERBOSE, "ctrl:%d", mhi_ctx->ctrl_info); + if (idx == MHI_DEV_UEVENT_CTRL) + *info = mhi_ctx->ctrl_info; + else + *info = channel_state_info[idx].ctrl_info; + + mhi_log(MHI_MSG_VERBOSE, "idx:%d, ctrl:%d", idx, *info); return 0; } @@ -2866,7 +2893,8 @@ static int mhi_dev_probe(struct platform_device *pdev) "Failed to create IPC logging context\n"); } mhi_uci_init(); - mhi_update_state_info(MHI_STATE_CONFIGURED); + mhi_update_state_info(MHI_DEV_UEVENT_CTRL, + MHI_STATE_CONFIGURED); } INIT_WORK(&mhi_ctx->pcie_event, mhi_dev_pcie_handle_event); diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h index f35c3772c0500..77e592ed839be 100644 --- a/drivers/platform/msm/mhi_dev/mhi.h +++ b/drivers/platform/msm/mhi_dev/mhi.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -273,7 +273,7 @@ struct mhi_config { #define MHI_ENV_VALUE 2 #define MHI_MASK_ROWS_CH_EV_DB 4 #define TRB_MAX_DATA_SIZE 8192 -#define MHI_CTRL_STATE 25 +#define MHI_CTRL_STATE 100 #define IPA_DMA_SYNC 1 #define IPA_DMA_ASYNC 0 @@ -603,6 +603,8 @@ struct mhi_dev { /*Register for interrupt*/ bool mhi_int; + + struct kobj_uevent_env kobj_env; }; struct mhi_req { @@ -708,6 +710,14 @@ enum mhi_client_channel { MHI_MAX_CHANNELS = 102, }; +/* Use ID 0 for legacy /dev/mhi_ctrl. Channel 0 used for internal only */ +#define MHI_DEV_UEVENT_CTRL 0 + +struct mhi_dev_uevent_info { + enum mhi_client_channel channel; + enum mhi_ctrl_info ctrl_info; +}; + struct mhi_dev_iov { void *addr; uint32_t buf_size; @@ -1221,7 +1231,19 @@ int mhi_dev_net_interface_init(void); void mhi_dev_notify_a7_event(struct mhi_dev *mhi); -int mhi_ctrl_state_info(uint32_t *info); +/** + * mhi_ctrl_state_info() - Provide MHI state info + * @idx: Channel number idx. Look at channel_state_info and + * pass the index for the corresponding channel. + * @info: Return the control info. + * MHI_STATE=CONFIGURED - MHI device is present but not ready + * for data traffic. + * MHI_STATE=CONNECTED - MHI device is ready for data transfer. + * MHI_STATE=DISCONNECTED - MHI device has its pipes suspended. + * exposes device nodes for the supported MHI software + * channels. + */ +int mhi_ctrl_state_info(uint32_t idx, uint32_t *info); void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason); diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c index 924bf04685861..4d9aa2e5e83f5 100644 --- a/drivers/platform/msm/mhi_dev/mhi_uci.c +++ b/drivers/platform/msm/mhi_dev/mhi_uci.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015,2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015,2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -441,6 +441,61 @@ static int mhi_uci_client_release(struct inode *mhi_inode, return rc; } +static void mhi_parse_state(char *buf, int *nbytes, uint32_t info) +{ + switch (info) { + case MHI_STATE_CONNECTED: + *nbytes = scnprintf(buf, MHI_CTRL_STATE, + "CONNECTED"); + break; + case MHI_STATE_DISCONNECTED: + *nbytes = scnprintf(buf, MHI_CTRL_STATE, + "DISCONNECTED"); + break; + case MHI_STATE_CONFIGURED: + default: + *nbytes = scnprintf(buf, MHI_CTRL_STATE, + "CONFIGURED"); + break; + } +} + +static int mhi_state_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + int rc, nbytes = 0; + uint32_t info = 0; + char buf[MHI_CTRL_STATE]; + + rc = mhi_ctrl_state_info(MHI_DEV_UEVENT_CTRL, &info); + if (rc) { + pr_err("Failed to obtain MHI_STATE\n"); + return -EINVAL; + } + + mhi_parse_state(buf, &nbytes, info); + add_uevent_var(env, "MHI_STATE=%s", buf); + + rc = mhi_ctrl_state_info(MHI_CLIENT_QMI_OUT, &info); + if (rc) { + pr_err("Failed to obtain channel 14 state\n"); + return -EINVAL; + } + nbytes = 0; + mhi_parse_state(buf, &nbytes, info); + add_uevent_var(env, "MHI_CHANNEL_STATE_14=%s", buf); + + rc = mhi_ctrl_state_info(MHI_CLIENT_MBIM_OUT, &info); + if (rc) { + pr_err("Failed to obtain channel 12 state\n"); + return -EINVAL; + } + nbytes = 0; + mhi_parse_state(buf, &nbytes, info); + add_uevent_var(env, "MHI_CHANNEL_STATE_12=%s", buf); + + return 0; +} + static ssize_t mhi_uci_ctrl_client_read(struct file *file, char __user *user_buf, size_t count, loff_t *offp) @@ -455,7 +510,7 @@ static ssize_t mhi_uci_ctrl_client_read(struct file *file, return -EINVAL; uci_ctrl_handle = file->private_data; - rc = mhi_ctrl_state_info(&info); + rc = mhi_ctrl_state_info(MHI_CLIENT_QMI_OUT, &info); if (rc) return -EINVAL; @@ -983,6 +1038,8 @@ int mhi_uci_init(void) cdev_del(&uci_ctxt.cdev_ctrl); } + uci_ctxt.mhi_uci_class->dev_uevent = mhi_state_uevent; + return 0; failed_char_add: From 401fc3a6ac0f6bdeff3014f12d7ac02904555a73 Mon Sep 17 00:00:00 2001 From: Sreelakshmi Gownipalli Date: Tue, 17 Jan 2017 14:03:54 -0800 Subject: [PATCH 274/508] diag: Prevent NULL pointer dereference while closing logging process Prevent NULL pointer dereference while copying the data to memory device process by adding mutex protection when closing the process. Change-Id: Idaad73fb8b2a0bb5a4983d5e255bfdf702cecf71 Signed-off-by: Sreelakshmi Gownipalli --- drivers/char/diag/diagchar_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index d053013566e6b..39778311c2abc 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -439,8 +439,10 @@ static void diag_close_logging_process(const int pid) driver->mask_clear = 1; mutex_unlock(&driver->diag_maskclear_mutex); + mutex_lock(&driver->diagchar_mutex); session_peripheral_mask = session_info->peripheral_mask; diag_md_session_close(session_info); + mutex_unlock(&driver->diagchar_mutex); for (i = 0; i < NUM_MD_SESSIONS; i++) if (MD_PERIPHERAL_MASK(i) & session_peripheral_mask) diag_mux_close_peripheral(DIAG_LOCAL_PROC, i); From d65da02093648371a5cd8611eeb6672c13ce7b08 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Mon, 19 Mar 2018 16:55:00 +0530 Subject: [PATCH 275/508] msm: ipa: Set ep delay on USB_PROD ep During SSR, set ep delay on USB_PROD ep for RMNET/MBIM config to avoid USB pushing data towards IPA. Change-Id: I51b7048f42fd393110f90939b67354006eb1411f Signed-off-by: Mohammed Javid --- .../platform/msm/ipa/ipa_clients/ipa_usb.c | 19 +++- drivers/platform/msm/ipa/ipa_v3/ipa.c | 4 +- drivers/platform/msm/ipa/ipa_v3/ipa_client.c | 105 +++++++++++++++++- drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 9 +- 4 files changed, 133 insertions(+), 4 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c index 0dc2044722144..aef946b139000 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, 2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2098,6 +2098,18 @@ static void ipa_usb_debugfs_init(void){} static void ipa_usb_debugfs_remove(void){} #endif /* CONFIG_DEBUG_FS */ +static int ipa_usb_set_lock_unlock(bool is_lock) +{ + IPA_USB_DBG("entry\n"); + if (is_lock) + mutex_lock(&ipa3_usb_ctx->general_mutex); + else + mutex_unlock(&ipa3_usb_ctx->general_mutex); + IPA_USB_DBG("exit\n"); + + return 0; +} + int ipa_usb_xdci_connect(struct ipa_usb_xdci_chan_params *ul_chan_params, @@ -2160,6 +2172,9 @@ int ipa_usb_xdci_connect(struct ipa_usb_xdci_chan_params *ul_chan_params, goto connect_fail; } + /* Register for xdci lock/unlock callback with ipa core driver */ + ipa3_register_lock_unlock_callback(&ipa_usb_set_lock_unlock, + ul_out_params->clnt_hdl); IPA_USB_DBG_LOW("exit\n"); mutex_unlock(&ipa3_usb_ctx->general_mutex); return 0; @@ -2236,6 +2251,8 @@ static int ipa_usb_xdci_dismiss_channels(u32 ul_clnt_hdl, u32 dl_clnt_hdl, } } + ipa3_deregister_lock_unlock_callback(ul_clnt_hdl); + /* Change state to STOPPED */ if (!ipa3_usb_set_state(IPA_USB_STOPPED, false, ttype)) IPA_USB_ERR("failed to change state to stopped\n"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index d7bb93b5644a0..f42e17885d9bb 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2597,6 +2597,8 @@ void ipa3_q6_pre_shutdown_cleanup(void) */ ipa3_q6_pipe_delay(false); + ipa3_set_usb_prod_pipe_delay(); + IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); IPADBG_LOW("Exit with success\n"); } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index eaebbaf1f4bd8..519d2a36d70ab 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1167,6 +1167,69 @@ int ipa3_smmu_map_peer_buff(u64 iova, phys_addr_t phys_addr, u32 size, bool map) return 0; } +void ipa3_register_lock_unlock_callback(int (*client_cb)(bool is_lock), + u32 ipa_ep_idx) +{ + struct ipa3_ep_context *ep; + + IPADBG("entry\n"); + + ep = &ipa3_ctx->ep[ipa_ep_idx]; + + if (!ep->valid) { + IPAERR("Invalid EP\n"); + return; + } + + if (client_cb == NULL) { + IPAERR("Bad Param"); + return; + } + + ep->client_lock_unlock = client_cb; + IPADBG("exit\n"); +} + +void ipa3_deregister_lock_unlock_callback(u32 ipa_ep_idx) +{ + struct ipa3_ep_context *ep; + + IPADBG("entry\n"); + + ep = &ipa3_ctx->ep[ipa_ep_idx]; + + if (!ep->valid) { + IPAERR("Invalid EP\n"); + return; + } + + if (ep->client_lock_unlock == NULL) { + IPAERR("client_lock_unlock is already NULL"); + return; + } + + ep->client_lock_unlock = NULL; + IPADBG("exit\n"); +} + +static void client_lock_unlock_cb(u32 ipa_ep_idx, bool is_lock) +{ + struct ipa3_ep_context *ep; + + IPADBG("entry\n"); + + ep = &ipa3_ctx->ep[ipa_ep_idx]; + + if (!ep->valid) { + IPAERR("Invalid EP\n"); + return; + } + + if (ep->client_lock_unlock) + ep->client_lock_unlock(is_lock); + + IPADBG("exit\n"); +} int ipa3_request_gsi_channel(struct ipa_request_gsi_channel_params *params, struct ipa_req_chan_out_params *out_params) @@ -1784,6 +1847,46 @@ static int ipa3_stop_ul_chan_with_data_drain(u32 qmi_req_id, return result; } +/* + * Set USB PROD pipe delay for MBIM/RMNET config + * Clocks, should be voted before calling this API + * locks should be taken before calling this API +*/ + +void ipa3_set_usb_prod_pipe_delay(void) +{ + int result; + int pipe_idx; + struct ipa3_ep_context *ep; + struct ipa_ep_cfg_ctrl ep_ctrl; + + memset(&ep_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); + ep_ctrl.ipa_ep_delay = true; + + + pipe_idx = ipa3_get_ep_mapping(IPA_CLIENT_USB_PROD); + + if (pipe_idx == IPA_EP_NOT_ALLOCATED) { + IPAERR("client (%d) not valid\n", IPA_CLIENT_USB_PROD); + return; + } + + ep = &ipa3_ctx->ep[pipe_idx]; + + /* Setting delay on USB_PROD with skip_ep_cfg */ + client_lock_unlock_cb(pipe_idx, true); + if (ep->valid && ep->skip_ep_cfg) { + ep->ep_delay_set = ep_ctrl.ipa_ep_delay; + result = ipa3_cfg_ep_ctrl(pipe_idx, &ep_ctrl); + if (result) + IPAERR("client (ep: %d) failed result=%d\n", + pipe_idx, result); + else + IPADBG("client (ep: %d) success\n", pipe_idx); + } + client_lock_unlock_cb(pipe_idx, false); +} + void ipa3_xdci_ep_delay_rm(u32 clnt_hdl) { struct ipa3_ep_context *ep; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index 7425442fe2b9d..d8206d606eb3d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -577,6 +577,8 @@ struct ipa3_status_stats { * @disconnect_in_progress: Indicates client disconnect in progress. * @qmi_request_sent: Indicates whether QMI request to enable clear data path * request is sent or not. + * @client_lock_unlock: callback function to take mutex lock/unlock for USB + * clients */ struct ipa3_ep_context { int valid; @@ -615,6 +617,8 @@ struct ipa3_ep_context { u32 qmi_request_sent; bool ep_delay_set; + int (*client_lock_unlock)(bool is_lock); + /* sys MUST be the last element of this struct */ struct ipa3_sys_context *sys; }; @@ -1523,6 +1527,9 @@ int ipa3_xdci_connect(u32 clnt_hdl); int ipa3_xdci_disconnect(u32 clnt_hdl, bool should_force_clear, u32 qmi_req_id); void ipa3_xdci_ep_delay_rm(u32 clnt_hdl); +void ipa3_register_lock_unlock_callback(int (*client_cb)(bool), u32 ipa_ep_idx); +void ipa3_deregister_lock_unlock_callback(u32 ipa_ep_idx); +void ipa3_set_usb_prod_pipe_delay(void); int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool should_force_clear, u32 qmi_req_id, bool is_dpl); From 46a5ddb8ff4cbae6a7db5ba822866b9a398019ab Mon Sep 17 00:00:00 2001 From: Sravan Kumar Kairam Date: Thu, 29 Mar 2018 12:59:56 +0530 Subject: [PATCH 276/508] wlan: Remove DXE excessive logging for ARP packets ARP packet excessive logging in DXE module leads to watchdog bite. In this change reduce the severity of the ARP packet logs in DXE module. Change-Id: Ie315f26a7cc3594dd758211aa758276675c8e66a CRs-Fixed: 2215022 --- CORE/DXE/src/wlan_qct_dxe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CORE/DXE/src/wlan_qct_dxe.c b/CORE/DXE/src/wlan_qct_dxe.c index 8514bb5eadced..968ef91c692be 100644 --- a/CORE/DXE/src/wlan_qct_dxe.c +++ b/CORE/DXE/src/wlan_qct_dxe.c @@ -3448,7 +3448,7 @@ static wpt_status dxeTXPushFrame if(wpalIsArpPkt(palPacket)) { - HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_HIGH, "%s :ARP packet", __func__); } @@ -3705,7 +3705,7 @@ static wpt_status dxeTXCompFrame if(wpalIsArpPkt(currentCtrlBlk->xfrFrame)) { - HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_HIGH, "%s :ARP packet DMA-ed ", __func__); wpalUpdateTXArpFWdeliveredStats(); } From e9103786ae4b2a1518ac6a6f731a2d950676d3bb Mon Sep 17 00:00:00 2001 From: Rama Krishna Phani A Date: Tue, 27 Mar 2018 18:43:02 +0530 Subject: [PATCH 277/508] msm: mhi_dev: Check return value Check return value for the function and update log in case of error. Change-Id: I6b443627c72ee07627cc91e55b51491b53715623 Signed-off-by: Rama Krishna Phani A --- drivers/platform/msm/mhi_dev/mhi.c | 21 +++++++++++++++------ drivers/platform/msm/mhi_dev/mhi.h | 1 - 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 6e3a7790a4b8b..011628b5eee0d 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -996,9 +996,12 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, pr_err("Error sending command completion event\n"); mhi_update_state_info(ch_id, MHI_STATE_CONNECTED); - if (ch_id == MHI_CLIENT_MBIM_OUT) - kobject_uevent_env(&mhi_ctx->dev->kobj, + if (ch_id == MHI_CLIENT_MBIM_OUT) { + rc = kobject_uevent_env(&mhi_ctx->dev->kobj, KOBJ_CHANGE, connected); + if (rc) + pr_err("Error sending uevent %d\n", rc); + } break; case MHI_DEV_RING_EL_STOP: if (ch_id >= HW_CHANNEL_BASE) { @@ -1054,9 +1057,12 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, mutex_unlock(&ch->ch_lock); mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED); - if (ch_id == MHI_CLIENT_MBIM_OUT) - kobject_uevent_env(&mhi_ctx->dev->kobj, + if (ch_id == MHI_CLIENT_MBIM_OUT) { + rc = kobject_uevent_env(&mhi_ctx->dev->kobj, KOBJ_CHANGE, disconnected); + if (rc) + pr_err("Error sending uevent %d\n", rc); + } } break; case MHI_DEV_RING_EL_RESET: @@ -1131,9 +1137,12 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, pr_err("Error sending command completion event\n"); mutex_unlock(&ch->ch_lock); mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED); - if (ch_id == MHI_CLIENT_MBIM_OUT) - kobject_uevent_env(&mhi_ctx->dev->kobj, + if (ch_id == MHI_CLIENT_MBIM_OUT) { + rc = kobject_uevent_env(&mhi_ctx->dev->kobj, KOBJ_CHANGE, disconnected); + if (rc) + pr_err("Error sending uevent %d\n", rc); + } } break; default: diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h index 77e592ed839be..89c7fc99e62c5 100644 --- a/drivers/platform/msm/mhi_dev/mhi.h +++ b/drivers/platform/msm/mhi_dev/mhi.h @@ -714,7 +714,6 @@ enum mhi_client_channel { #define MHI_DEV_UEVENT_CTRL 0 struct mhi_dev_uevent_info { - enum mhi_client_channel channel; enum mhi_ctrl_info ctrl_info; }; From 170fd512d7413245ba7b3cfddd7470d17b3d2daa Mon Sep 17 00:00:00 2001 From: Ganesh Kondabattini Date: Mon, 19 Mar 2018 12:01:23 +0530 Subject: [PATCH 278/508] wlan: Allow TDLS only on STA interface TDLS over p2p is not supported in driver so allow TDLS connection only on STA interface. CRs-Fixed: 2210119 Change-Id: Ie9b878a003d56bf7643cebecd169518bd8e4c3ce --- CORE/HDD/inc/wlan_hdd_main.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index fefbb0b7ba223..fbdf0c9ae5031 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -1410,8 +1410,7 @@ struct hdd_adapter_s #define WLAN_HDD_GET_CFG_STATE_PTR(pAdapter) (&(pAdapter)->cfg80211State) #ifdef FEATURE_WLAN_TDLS #define WLAN_HDD_IS_TDLS_SUPPORTED_ADAPTER(pAdapter) \ - (((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) && \ - (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode)) ? 0 : 1) + ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ? 1 : 0) #define WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter) \ ((WLAN_HDD_IS_TDLS_SUPPORTED_ADAPTER(pAdapter)) ? \ (tdlsCtx_t*)(pAdapter)->sessionCtx.station.pHddTdlsCtx : NULL) From 282d60dfe68d421092898bb1e8707d569be6643c Mon Sep 17 00:00:00 2001 From: Sarada Prasanna Garnayak Date: Fri, 22 Dec 2017 16:58:48 +0530 Subject: [PATCH 279/508] wlan: fix the Prima WLAN driver compilation for wearable target. The Prima WLAN driver source code location is specific to target or vendor. To avoid the compilation error check the driver source code location in the target or vendor location for the wearable target before compiling the driver as a dynamic kernel module. CRs-Fixed: 2163381 Change-Id: Ied570879da5ea6da6a2ec10e29dc7078d1f07558 --- Android.mk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Android.mk b/Android.mk index 1576d0945059e..e43af06fd00cf 100644 --- a/Android.mk +++ b/Android.mk @@ -23,9 +23,13 @@ LOCAL_PATH := $(call my-dir) ifeq ($(TARGET_SUPPORTS_WEARABLES),true) ifneq ($(findstring device,$(LOCAL_PATH)),) WLAN_DLKM := 1 +else +ifneq ($(findstring vendor,$(LOCAL_PATH)),) + WLAN_DLKM := 1 else WLAN_DLKM := 0 endif # findstring device +endif else ifneq ($(findstring vendor,$(LOCAL_PATH)),) WLAN_DLKM := 1 From 4d7dbd20df79c3b9ac5ef39846a06b541758cc1a Mon Sep 17 00:00:00 2001 From: Rama Krishna Phani A Date: Tue, 21 Nov 2017 18:32:08 +0530 Subject: [PATCH 280/508] msm: ep_pcie: Unregister to bus driver in error path Add support to unregister the client from the msm bus driver in error and exit path. Change-Id: I7ec7a17dd2d53f6725a70f4a42758be817576e50 Signed-off-by: Rama Krishna Phani A --- drivers/platform/msm/ep_pcie/ep_pcie_core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c index b1abf7e195169..d648684772e17 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c +++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c @@ -993,6 +993,11 @@ static void ep_pcie_release_resources(struct ep_pcie_dev_t *dev) dev->phy = NULL; dev->mmio = NULL; dev->msi = NULL; + + if (dev->bus_client) { + msm_bus_scale_unregister_client(dev->bus_client); + dev->bus_client = 0; + } } static void ep_pcie_enumeration_complete(struct ep_pcie_dev_t *dev) From 70383366914667b9275d22ba1c3af990a402219f Mon Sep 17 00:00:00 2001 From: Suprith Malligere Shankaregowda Date: Fri, 23 Mar 2018 14:13:28 +0530 Subject: [PATCH 281/508] msm: ais: jpegdma: Fix for ASAN issues in jpegdma module Adding Lock mechanism to avoid concurrency issues between reqbufs and streamoff calls. Change-Id: Ic915d346d0aa60d71007a359760a6a573734b6e5 Signed-off-by: Suprith Malligere Shankaregowda --- .../platform/msm/ais/jpeg_dma/msm_jpeg_dma_dev.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/msm/ais/jpeg_dma/msm_jpeg_dma_dev.c b/drivers/media/platform/msm/ais/jpeg_dma/msm_jpeg_dma_dev.c index 09b4bc66ec80b..d1866701b904a 100644 --- a/drivers/media/platform/msm/ais/jpeg_dma/msm_jpeg_dma_dev.c +++ b/drivers/media/platform/msm/ais/jpeg_dma/msm_jpeg_dma_dev.c @@ -754,9 +754,12 @@ static int msm_jpegdma_s_fmt_vid_out(struct file *file, static int msm_jpegdma_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *req) { + int ret = 0; struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh); - - return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, req); + mutex_lock(&ctx->lock); + ret = v4l2_m2m_reqbufs(file, ctx->m2m_ctx, req); + mutex_unlock(&ctx->lock); + return ret; } /* @@ -833,11 +836,11 @@ static int msm_jpegdma_streamoff(struct file *file, { struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh); int ret; - + mutex_lock(&ctx->lock); ret = v4l2_m2m_streamoff(file, ctx->m2m_ctx, buf_type); if (ret < 0) dev_err(ctx->jdma_device->dev, "Stream off fails\n"); - + mutex_unlock(&ctx->lock); return ret; } From b6726e744f2db4cb6eb0493d1674f4f73e1f530f Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Mon, 29 Jan 2018 21:31:21 -0800 Subject: [PATCH 282/508] ANDROID: sdcardfs: Use lower getattr times/size We now use the lower filesystem's getattr for time and size related information. Change-Id: I3dd05614a0c2837a13eeb033444fbdf070ddce2a Signed-off-by: Daniel Rosenberg Bug: 72007585 Git-Commit: b51a9f0121d8cb633649282566c0c074e0dc448e Git-Repo: https://android.googlesource.com/kernel/common/ Signed-off-by: Ritesh Harjani --- fs/sdcardfs/inode.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 36d54d6fa16d7..1d4cebc609ac1 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -816,8 +816,8 @@ static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct return err; } -static int sdcardfs_fillattr(struct vfsmount *mnt, - struct inode *inode, struct kstat *stat) +static int sdcardfs_fillattr(struct vfsmount *mnt, struct inode *inode, + struct kstat *lower_stat, struct kstat *stat) { struct sdcardfs_inode_info *info = SDCARDFS_I(inode); struct sdcardfs_inode_data *top = top_data_get(info); @@ -832,12 +832,12 @@ static int sdcardfs_fillattr(struct vfsmount *mnt, stat->uid = make_kuid(&init_user_ns, top->d_uid); stat->gid = make_kgid(&init_user_ns, get_gid(mnt, top)); stat->rdev = inode->i_rdev; - stat->size = i_size_read(inode); - stat->atime = inode->i_atime; - stat->mtime = inode->i_mtime; - stat->ctime = inode->i_ctime; - stat->blksize = (1 << inode->i_blkbits); - stat->blocks = inode->i_blocks; + stat->size = lower_stat->size; + stat->atime = lower_stat->atime; + stat->mtime = lower_stat->mtime; + stat->ctime = lower_stat->ctime; + stat->blksize = lower_stat->blksize; + stat->blocks = lower_stat->blocks; data_put(top); return 0; } @@ -863,8 +863,7 @@ static int sdcardfs_getattr(struct vfsmount *mnt, struct dentry *dentry, goto out; sdcardfs_copy_and_fix_attrs(dentry->d_inode, lower_path.dentry->d_inode); - err = sdcardfs_fillattr(mnt, dentry->d_inode, stat); - stat->blocks = lower_stat.blocks; + err = sdcardfs_fillattr(mnt, dentry->d_inode, &lower_stat, stat); out: sdcardfs_put_lower_path(dentry, &lower_path); return err; From a7570eb63a0f30ecc3c9e58a57c4cc9cc89e7f9d Mon Sep 17 00:00:00 2001 From: Harsh Sahu Date: Fri, 23 Mar 2018 00:15:52 -0700 Subject: [PATCH 283/508] msm: mdss: check buffer size before writing to user buffer Check the number of bytes to copy against the size of the user buffer before copy to user to avoid buffer overflow. Change-Id: Icdd3d4e755deca19fa431e903620bd9e4c701c89 Signed-off-by: Harsh Sahu --- drivers/video/msm/mdss/mdss_debug_xlog.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/video/msm/mdss/mdss_debug_xlog.c b/drivers/video/msm/mdss/mdss_debug_xlog.c index 375dc47dd006d..2efa439fbe363 100644 --- a/drivers/video/msm/mdss/mdss_debug_xlog.c +++ b/drivers/video/msm/mdss/mdss_debug_xlog.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -683,6 +683,11 @@ static ssize_t mdss_xlog_dump_read(struct file *file, char __user *buff, if (__mdss_xlog_dump_calc_range()) { len = mdss_xlog_dump_entry(xlog_buf, MDSS_XLOG_BUF_MAX); + if (len < 0 || len > count) { + pr_err("len is more than the size of user buffer\n"); + return 0; + } + if (copy_to_user(buff, xlog_buf, len)) return -EFAULT; *ppos += len; From 7dec6423676d2ac1f4e40f84804c34aec5056156 Mon Sep 17 00:00:00 2001 From: Rashi Bindra Date: Mon, 19 Mar 2018 14:07:27 +0530 Subject: [PATCH 284/508] msm: mdss: Fix for wrong length in copy_to_user The caller could have a small buf passed (less then < blen). Since, the length of count and blen is not checked, it can write beyond the end of buf. Change-Id: I9138cd742b6166937f3cc1cbf1af36f280c94bdb Signed-off-by: Rashi Bindra --- drivers/video/msm/mdss/mdss_dsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c index d786ee88866e4..6813c75697093 100644 --- a/drivers/video/msm/mdss/mdss_dsi.c +++ b/drivers/video/msm/mdss/mdss_dsi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -745,7 +745,7 @@ static ssize_t mdss_dsi_cmd_state_read(struct file *file, char __user *buf, if (blen < 0) return 0; - if (copy_to_user(buf, buffer, blen)) + if (copy_to_user(buf, buffer, min(count, (size_t)blen+1))) return -EFAULT; *ppos += blen; From d273037a26546ee1f7a4f457ef72931a8478181b Mon Sep 17 00:00:00 2001 From: Suprith Malligere Shankaregowda Date: Mon, 2 Apr 2018 14:32:31 +0530 Subject: [PATCH 285/508] msm: ais: isp: Handling buffer use after getting it freed In the code, start_fetch can try to access the buffer pointer variable after free, as the same pointer can can be freed at RELEASE_BUF call too at the same time. Hence fixing this race condition. Change-Id: Id9f33962b57ccf5425a4cbcb5f93f49fa3334112 Signed-off-by: Suprith Malligere Shankaregowda --- drivers/media/platform/msm/ais/isp/msm_isp47.c | 8 +++++++- drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c | 6 +++++- drivers/media/platform/msm/ais/isp/msm_isp_util.c | 10 +++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/ais/isp/msm_isp47.c b/drivers/media/platform/msm/ais/isp/msm_isp47.c index 6dd89ad73c33b..ba879e9e78531 100644 --- a/drivers/media/platform/msm/ais/isp/msm_isp47.c +++ b/drivers/media/platform/msm/ais/isp/msm_isp47.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1032,15 +1032,18 @@ int msm_vfe47_start_fetch_engine(struct vfe_device *vfe_dev, fe_cfg->stream_id); vfe_dev->fetch_engine_info.bufq_handle = bufq_handle; + mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); if (rc < 0 || !buf) { pr_err("%s: No fetch buffer rc= %d buf= %pK\n", __func__, rc, buf); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } mapped_info = buf->mapped_info[0]; buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED; + mutex_unlock(&vfe_dev->buf_mgr->lock); } else { rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr, &mapped_info, fe_cfg->fd); @@ -1090,15 +1093,18 @@ int msm_vfe47_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev, fe_cfg->stream_id); vfe_dev->fetch_engine_info.bufq_handle = bufq_handle; + mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); if (rc < 0 || !buf) { pr_err("%s: No fetch buffer rc= %d buf= %pK\n", __func__, rc, buf); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } mapped_info = buf->mapped_info[0]; buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED; + mutex_unlock(&vfe_dev->buf_mgr->lock); } else { rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr, &mapped_info, fe_cfg->fd); diff --git a/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c index d722d5090ec0f..2639b649c0782 100644 --- a/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -3830,10 +3830,12 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) &update_cmd->update_info[i]; stream_info = &axi_data->stream_info[HANDLE_TO_IDX( update_info->stream_handle)]; + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_request_frame(vfe_dev, stream_info, update_info->user_stream_id, update_info->frame_id, MSM_ISP_INVALID_BUF_INDEX); + mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc) pr_err("%s failed to request frame!\n", __func__); @@ -3906,10 +3908,12 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) stream_info = &axi_data->stream_info[HANDLE_TO_IDX( req_frm->stream_handle)]; + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_request_frame(vfe_dev, stream_info, req_frm->user_stream_id, req_frm->frame_id, req_frm->buf_index); + mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc) pr_err("%s failed to request frame!\n", __func__); diff --git a/drivers/media/platform/msm/ais/isp/msm_isp_util.c b/drivers/media/platform/msm/ais/isp/msm_isp_util.c index 5b15773f8a2b3..2c670eea1852f 100644 --- a/drivers/media/platform/msm/ais/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/ais/isp/msm_isp_util.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -393,8 +393,10 @@ static int msm_isp_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev, 0, 1); msm_isp_reset_framedrop(vfe_dev, stream_info); + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_cfg_offline_ping_pong_address(vfe_dev, stream_info, VFE_PING_FLAG, fe_cfg->output_buf_idx); + mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc < 0) { pr_err("%s: Fetch engine config failed\n", __func__); return -EINVAL; @@ -916,7 +918,9 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, break; case VIDIOC_MSM_ISP_CFG_STREAM: mutex_lock(&vfe_dev->core_mutex); + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_cfg_axi_stream(vfe_dev, arg); + mutex_unlock(&vfe_dev->buf_mgr->lock); mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_CFG_HW_STATE: @@ -946,6 +950,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, break; case VIDIOC_MSM_ISP_AXI_RESTART: mutex_lock(&vfe_dev->core_mutex); + mutex_lock(&vfe_dev->buf_mgr->lock); if (atomic_read(&vfe_dev->error_info.overflow_state) != HALT_ENFORCED) { rc = msm_isp_stats_restart(vfe_dev); @@ -956,6 +961,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, pr_err_ratelimited("%s: no AXI restart, halt enforced.\n", __func__); } + mutex_unlock(&vfe_dev->buf_mgr->lock); mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_INPUT_CFG: @@ -1015,7 +1021,9 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, break; case VIDIOC_MSM_ISP_CFG_STATS_STREAM: mutex_lock(&vfe_dev->core_mutex); + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_cfg_stats_stream(vfe_dev, arg); + mutex_unlock(&vfe_dev->buf_mgr->lock); mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_UPDATE_STATS_STREAM: From 76088af4943518f1186d7757927e6f836cba16b0 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 29 Nov 2017 06:53:55 +0100 Subject: [PATCH 286/508] xfrm: Fix stack-out-of-bounds read on socket policy lookup. When we do tunnel or beet mode, we pass saddr and daddr from the template to xfrm_state_find(), this is ok. On transport mode, we pass the addresses from the flowi, assuming that the IP addresses (and address family) don't change during transformation. This assumption is wrong in the IPv4 mapped IPv6 case, packet is IPv4 and template is IPv6. Fix this by catching address family missmatches of the policy and the flow already before we do the lookup. Change-Id: I4e3da03ed3b8f0cf0fdd01d5cdc8a69e9504240b Reported-by: syzbot Signed-off-by: Steffen Klassert Git-commit: ddc47e4404b58f03e98345398fb12d38fe291512 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Tejaswi Tanikella Acked-by: Sharath Chandra Vurukala --- net/xfrm/xfrm_policy.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 253e7dda287b3..6784161d27078 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1218,9 +1218,15 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, read_lock_bh(&net->xfrm.xfrm_policy_lock); if ((pol = sk->sk_policy[dir]) != NULL) { - bool match = xfrm_selector_match(&pol->selector, fl, family); + bool match; int err = 0; + if (pol->family != family) { + pol = NULL; + goto out; + } + + match = xfrm_selector_match(&pol->selector, fl, family); if (match) { if ((sk->sk_mark & pol->mark.m) != pol->mark.v) { pol = NULL; From 2416e0e7a412e15961797b2744c5f9a44684f318 Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Mon, 5 Mar 2018 18:44:21 +0530 Subject: [PATCH 287/508] wlan: Add support for VOWIFIMODE driver command Add support for sending VOWIFIMODE command in the case when STA is connected to 2.4GHz band. Change-Id: Ifce7705ebf578f8ce49fff53b7a5df10b3ab3355 CRs-Fixed: 2203715 --- CORE/HDD/src/wlan_hdd_main.c | 37 +++++++++++++ CORE/MAC/src/include/sirParams.h | 1 + CORE/SME/inc/sme_Api.h | 1 + CORE/SME/src/sme_common/sme_Api.c | 32 +++++++++++ CORE/WDA/inc/wlan_qct_wda.h | 1 + CORE/WDA/src/wlan_qct_wda.c | 32 +++++++++++ CORE/WDI/CP/inc/wlan_qct_wdi.h | 9 +++ CORE/WDI/CP/inc/wlan_qct_wdi_i.h | 20 ++++++- CORE/WDI/CP/src/wlan_qct_wdi.c | 92 +++++++++++++++++++++++++++++++ 9 files changed, 222 insertions(+), 3 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index d62ec5ebe92a7..07e1a343e4153 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -249,6 +249,7 @@ static int hdd_ParseUserParams(tANI_U8 *pValue, tANI_U8 **ppArg); #endif /* WLAN_FEATURE_RMC */ void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback); void hdd_set_wlan_suspend_mode(bool suspend); +void hdd_set_vowifi_mode(hdd_context_t *hdd_ctx, bool enable); v_U16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb @@ -865,6 +866,26 @@ static int hdd_parse_setrmcactionperiod_command(tANI_U8 *pValue, return 0; } +/* + * hdd_set_vowifi_mode() - Process the VOWIFI command and invoke the SME api + * + * @hHal: context handler + * @enable: Value to be sent as a part of the VOWIFI command + * + * Return: void + */ +void hdd_set_vowifi_mode(hdd_context_t *hdd_ctx, bool enable) +{ + tANI_U8 sta_chan; + + sta_chan = hdd_get_operating_channel(hdd_ctx, WLAN_HDD_INFRA_STATION); + + if (CSR_IS_CHANNEL_24GHZ(sta_chan)) + sme_set_vowifi_mode(hdd_ctx->hHal, enable); + else + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "VoWiFi command rejected as not connected in 2.4GHz"); +} /* Function header left blank Intentionally */ static int hdd_parse_setrmcrate_command(tANI_U8 *pValue, @@ -3654,6 +3675,22 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, ret = sapSetPreferredChannel(ptr); } + + else if (strncmp(command, "VOWIFIMODE", 10) == 0) + { + tANI_U8 *ptr; + + ret = hdd_drv_cmd_validate(command, 10); + if (ret) + goto exit; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Received Command for VOWIFI mode in %s", __func__); + + ptr = (tANI_U8*)command + 11; + hdd_set_vowifi_mode(pHddCtx, *ptr - '0'); + } + else if(strncmp(command, "SETSUSPENDMODE", 14) == 0) { int suspend = 0; diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h index b1bd9c00e5b56..5b936208f2e2b 100644 --- a/CORE/MAC/src/include/sirParams.h +++ b/CORE/MAC/src/include/sirParams.h @@ -811,6 +811,7 @@ typedef struct sSirMbMsgP2p /* ARP Debug stats */ #define SIR_HAL_SET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 303) #define SIR_HAL_GET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 304) +#define SIR_HAL_VOWIFI_MODE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 306) #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h index 6674053d1ac94..d253a9f9b77ab 100644 --- a/CORE/SME/inc/sme_Api.h +++ b/CORE/SME/inc/sme_Api.h @@ -231,6 +231,7 @@ sme_SetLinkLayerStatsIndCB #endif /* WLAN_FEATURE_LINK_LAYER_STATS */ +void sme_set_vowifi_mode(tpAniSirGlobal pMac, bool enable); #ifdef WLAN_FEATURE_EXTSCAN /* --------------------------------------------------------------------------- \fn sme_GetValidChannelsByBand diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c index 272a76f1fe3ba..b0de3d87e0a86 100644 --- a/CORE/SME/src/sme_common/sme_Api.c +++ b/CORE/SME/src/sme_common/sme_Api.c @@ -901,6 +901,38 @@ static void smeProcessNanReq(tpAniSirGlobal pMac, tSmeCmd *pCommand ) } } + +/** + * sme_set_vowifi_mode() - Set VOWIFI mode + * @pMac - context handler + * @enable - boolean value that determines the state + * + * The function sends the VOWIFI to firmware received + * via driver command + */ +void sme_set_vowifi_mode(tpAniSirGlobal pMac, bool enable) +{ + tSirMsgQ msgQ; + tSirRetStatus retCode = eSIR_SUCCESS; + + vos_mem_zero(&msgQ, sizeof(tSirMsgQ)); + msgQ.type = WDA_VOWIFI_MODE; + msgQ.reserved = 0; + msgQ.bodyval = enable; + + retCode = wdaPostCtrlMsg(pMac, &msgQ); + if(eSIR_SUCCESS != retCode) + { + smsLog(pMac, LOGE, + FL("Posting WDA_VOWIFI_MODE to WDA failed, reason=%X"), + retCode); + } + else + { + smsLog(pMac, LOG1, FL("posted WDA_VOWIFI_MODE command")); + } +} + tANI_BOOLEAN smeProcessCommand( tpAniSirGlobal pMac ) { tANI_BOOLEAN fContinue = eANI_BOOLEAN_FALSE; diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h index 9a9a76522b9ee..69a48fd73e672 100644 --- a/CORE/WDA/inc/wlan_qct_wda.h +++ b/CORE/WDA/inc/wlan_qct_wda.h @@ -1110,6 +1110,7 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); #define WDA_EXIT_UAPSD_RSP SIR_HAL_EXIT_UAPSD_RSP #define WDA_LOW_RSSI_IND SIR_HAL_LOW_RSSI_IND #define WDA_BEACON_FILTER_IND SIR_HAL_BEACON_FILTER_IND +#define WDA_VOWIFI_MODE SIR_HAL_VOWIFI_MODE /// PE <-> HAL WOWL messages #define WDA_WOWL_ADD_BCAST_PTRN SIR_HAL_WOWL_ADD_BCAST_PTRN #define WDA_WOWL_DEL_BCAST_PTRN SIR_HAL_WOWL_DEL_BCAST_PTRN diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c index 33ed775597a93..882dc14c139e0 100644 --- a/CORE/WDA/src/wlan_qct_wda.c +++ b/CORE/WDA/src/wlan_qct_wda.c @@ -12028,6 +12028,28 @@ VOS_STATUS WDA_RemBeaconFilterReq(tWDA_CbContext *pWDA, } return status; } + +VOS_STATUS WDA_set_vowifi_ind(tWDA_CbContext *pWDA, + tANI_BOOLEAN enable) +{ + WDI_Status status; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + FL("---> %s"), __func__); + status = WDI_set_vowifi_mode_ind(enable); + if (status == WDI_STATUS_PENDING) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + FL("pending status received ")); + } + else if (status != WDI_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + FL("Failure status %d"), status); + } + return CONVERT_WDI2VOS_STATUS(status); +} + /* * FUNCTION: WDA_SetRSSIThresholdsRespCallback * @@ -17058,6 +17080,16 @@ VOS_STATUS WDA_McProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) WDA_SetBeaconFilterReq(pWDA, (tBeaconFilterMsg *)pMsg->bodyptr); break; } + + case WDA_VOWIFI_MODE : + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO_HIGH, + "Handling msg type WDA_VOWIFI_MODE"); + + WDA_set_vowifi_ind(pWDA, pMsg->bodyval); + break; + } + case WDA_BTC_SET_CFG: { /*TODO: handle this while dealing with BTC */ diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi.h b/CORE/WDI/CP/inc/wlan_qct_wdi.h index 297fba64905c8..4dae584f54027 100644 --- a/CORE/WDI/CP/inc/wlan_qct_wdi.h +++ b/CORE/WDI/CP/inc/wlan_qct_wdi.h @@ -12292,6 +12292,15 @@ WDI_SetRtsCtsHTVhtInd wpt_uint32 rtsCtsVal ); +/** + * WDI_set_vowifi_mode_ind() - Set VOWIFI mode request + * + * @enable - boolean value that determines the state + * + * Return: success if the value is sent + */ +WDI_Status WDI_set_vowifi_mode_ind(wpt_boolean enable); + WDI_Status WDI_FWLoggingDXEdoneInd ( diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h index 5fb24ba072226..796a7076422b0 100644 --- a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h +++ b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h @@ -573,7 +573,8 @@ typedef enum #endif WDI_SET_AP_FIND_IND = WDI_MAX_REQ + 25, - WDI_MAX_UMAC_IND = WDI_MAX_REQ + 26 + WDI_SET_VOWIFI_IND = WDI_MAX_REQ + 26, + WDI_MAX_UMAC_IND = WDI_MAX_REQ + 27, }WDI_RequestEnumType; @@ -891,8 +892,6 @@ typedef enum WDI_CAPTURE_GET_TSF_TSTAMP_RSP = 123, WDI_FW_ARP_STATS_RSP = 124, WDI_FW_GET_ARP_STATS_RSP = 125, - - /*------------------------------------------------------------------------- Indications !! Keep these last in the enum if possible @@ -1894,6 +1893,21 @@ WDI_ProcessEndScanReq ); +/** + * WDI_process_vowifi_request - Sends the vowifi request data to + * the firmware when VOWIFI driver command is invoked + * @pWDICtx: pointer to the WLAN DAL context + * @pEventData: pointer to the event information structure + * + * Return value: status whether the sending is successful or not + */ +WDI_Status +WDI_process_vowifi_request +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData +); + /** @brief Process Finish Scan Request function (called when Main FSM allows it) diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c index 4b4ebd0a98a4e..6b7cbeb418b8f 100644 --- a/CORE/WDI/CP/src/wlan_qct_wdi.c +++ b/CORE/WDI/CP/src/wlan_qct_wdi.c @@ -613,7 +613,11 @@ WDI_ReqProcFuncType pfnReqProcTbl[WDI_MAX_UMAC_IND] = #endif #ifdef WLAN_FEATURE_APFIND WDI_ProcessApFindInd, /* WDI_SET_AP_FIND_IND */ +#else + NULL, #endif + WDI_process_vowifi_request, /* WDI_SET_VOWIFI_IND */ + }; @@ -8988,6 +8992,65 @@ WDI_ProcessStartScanReq }/*WDI_ProcessStartScanReq*/ +WDI_Status +WDI_process_vowifi_request(WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData) +{ + wpt_uint8* pSendBuffer = NULL; + wpt_uint16 usDataOffset = 0; + wpt_uint16 usSendSize = 0; + wpt_boolean *enable; + tHalVoWiFiInd hal_vowifi_msg; + WDI_Status wdiStatus; + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, + "%s", __func__); + + /*------------------------------------------------------------------------- + Sanity check + -------------------------------------------------------------------------*/ + if (( NULL == pEventData ) || ( NULL == pEventData->pEventData ) ) { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + enable = (wpt_boolean*)pEventData->pEventData; + + /*----------------------------------------------------------------------- + Get message buffer + -----------------------------------------------------------------------*/ + if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx, + WDI_SET_VOWIFI_IND, + sizeof(tHalVoWiFiIndParams), + &pSendBuffer, &usDataOffset, &usSendSize))|| + ( usSendSize < (usDataOffset + sizeof(tHalVoWiFiIndParams) ))) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "Unable to get send buffer VOWIFI ind %pK ", + pEventData); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + hal_vowifi_msg.voWiFiIndParams.enable = *enable; + + wpalMemoryCopy( pSendBuffer+usDataOffset, + &hal_vowifi_msg.voWiFiIndParams, + sizeof(hal_vowifi_msg.voWiFiIndParams)); + + pWDICtx->pReqStatusUserData = NULL; + pWDICtx->pfncRspCB = NULL; + + /*------------------------------------------------------------------------- + Send VOWIFI mode Request to HAL + -------------------------------------------------------------------------*/ + wdiStatus = WDI_SendIndication(pWDICtx, pSendBuffer, usSendSize); + return (wdiStatus != WDI_STATUS_SUCCESS) ? wdiStatus:WDI_STATUS_SUCCESS_SYNC; +} + /** @brief Process End Scan Request function (called when Main FSM allows it) @@ -11477,6 +11540,33 @@ WDI_ProcessUpdateEDCAParamsReq WDI_UPD_EDCA_PRMS_RESP); }/*WDI_ProcessUpdateEDCAParamsReq*/ +/** + * WDI_set_vowifi_mode_ind() - Set VOWIFI mode request + * + * @enable - boolean value that determins the state + * + * Return value: status whether the post is successful or not + */ +WDI_Status WDI_set_vowifi_mode_ind(wpt_boolean enable) +{ + WDI_EventInfoType wdiEventData; + + if (eWLAN_PAL_FALSE == gWDIInitialized ) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "WDI API call before module is initialized - Fail request"); + return WDI_STATUS_E_NOT_ALLOWED; + } + + wdiEventData.wdiRequest = WDI_SET_VOWIFI_IND; + wdiEventData.pEventData = (void *) &enable; + wdiEventData.uEventDataSize = sizeof(wpt_boolean); + wdiEventData.pCBfnc = NULL; + wdiEventData.pUserData = NULL; + + return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData); +} + /** @brief Process Add BA Request function (called when Main FSM allows it) @@ -25145,6 +25235,8 @@ WDI_2_HAL_REQ_TYPE return WLAN_HAL_NAN_REQ; case WDI_SET_RTS_CTS_HTVHT_IND: return WLAN_HAL_SET_RTS_CTS_HTVHT_IND; + case WDI_SET_VOWIFI_IND: + return WLAN_HAL_VOWIFI_IND; case WDI_MON_START_REQ: return WLAN_HAL_ENABLE_MONITOR_MODE_REQ; case WDI_MON_STOP_REQ: From 8b14933ce16667976590761f27a3965b503d6962 Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Tue, 6 Mar 2018 14:28:18 +0530 Subject: [PATCH 288/508] wlan: Disable indoor channels only for SAP and not GO In the present scenario, the indoor channels are disabled in both SAP and GO. Disable the indoor channels only in case of SAP. Change-Id: Ic66c3af211bd65846ec0ecaac8375d037f15af9a CRs-Fixed: 2203719 --- CORE/HDD/src/wlan_hdd_cfg80211.c | 6 ++++-- CORE/HDD/src/wlan_hdd_softap_tx_rx.c | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 3bc2d0c226efa..b1ccb19dcc241 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -10830,7 +10830,8 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, iniConfig = pHddCtx->cfg_ini; /* Mark the indoor channel (passive) to disable */ - if (iniConfig->disable_indoor_channel) { + if (iniConfig->disable_indoor_channel && + pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP) { hdd_update_indoor_channel(pHddCtx, true); if (!VOS_IS_STATUS_SUCCESS( @@ -11452,7 +11453,8 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP) wlan_hdd_restore_channels(pHddCtx); /* Revert the indoor to passive marking if START BSS fails */ - if (iniConfig->disable_indoor_channel) { + if (iniConfig->disable_indoor_channel && + pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP) { hdd_update_indoor_channel(pHddCtx, false); sme_update_channel_list((tpAniSirGlobal)pHddCtx->hHal); } diff --git a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c index b5cb8b3c759ac..38416ee035424 100644 --- a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c +++ b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c @@ -2134,7 +2134,8 @@ VOS_STATUS hdd_softap_stop_bss( hdd_adapter_t *pAdapter) wlan_hdd_restore_channels(pHddCtx); /* Mark the indoor channel (passive) to enable */ - if (pHddCtx->cfg_ini->disable_indoor_channel) { + if (pHddCtx->cfg_ini->disable_indoor_channel && + pAdapter->device_mode == WLAN_HDD_SOFTAP) { hdd_update_indoor_channel(pHddCtx, false); sme_update_channel_list((tpAniSirGlobal)pHddCtx->hHal); } From b973f1cfe520b75e8d40b068b2c1833b41172fef Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Thu, 29 Mar 2018 19:35:49 +0530 Subject: [PATCH 289/508] wlan: Send IMPS request to firmware on SAP stop For built in driver, on turning off SAP, SAP stop happens but SAP adapter is not closed. Since SAP adapter is not closed, IMPS does not get enabled and request is not sent to firmware resulting in high power consumption. Fix is to send IMPS request to firmware on SAP stop. Change-Id: I336037f464e7b0706fe396e449d56d917654b42f CRs-Fixed: 2217224 --- CORE/HDD/src/wlan_hdd_hostapd.c | 5 +++++ CORE/SME/inc/sme_Api.h | 8 ++++++++ CORE/SME/src/sme_common/sme_Api.c | 7 +++++++ 3 files changed, 20 insertions(+) diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index 20c34af352e21..9856f96d420ff 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -1727,6 +1727,11 @@ stopbss : if (eSAP_STOP_BSS_EVENT == sapEvent) vos_event_set(&pHostapdState->vosEvent); + if (hdd_is_any_session_connected(pHddCtx) == VOS_STATUS_E_FAILURE) { + hdd_enable_bmps_imps(pHddCtx); + sme_request_imps(pHddCtx->hHal); + } + /* notify userspace that the BSS has stopped */ memset(&we_custom_event, '\0', sizeof(we_custom_event)); memcpy(&we_custom_event, stopBssEvent, event_len); diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h index d253a9f9b77ab..0d4ee2c951a63 100644 --- a/CORE/SME/inc/sme_Api.h +++ b/CORE/SME/inc/sme_Api.h @@ -4066,4 +4066,12 @@ sme_get_cb_phy_mode_from_cb_ini_mode(uint32_t cb_ini_value) return csrConvertCBIniValueToPhyCBState(cb_ini_value); } +/** + * sme_request_imps() - Send IMPS request + * @hal: hal context + * + * Return: void + */ +void sme_request_imps(tHalHandle hal); + #endif //#if !defined( __SME_API_H ) diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c index b0de3d87e0a86..81ae6b8e7da67 100644 --- a/CORE/SME/src/sme_common/sme_Api.c +++ b/CORE/SME/src/sme_common/sme_Api.c @@ -15274,3 +15274,10 @@ sme_get_connect_strt_time(tHalHandle hal, uint8_t session_id) session = CSR_GET_SESSION(mac_ctx, session_id); return session->connect_req_start_time; } + +void sme_request_imps(tHalHandle hal) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + + csrScanStartIdleScan(mac_ctx); +} From 78386c19951abb20a728f3ed19e3330aeea9e412 Mon Sep 17 00:00:00 2001 From: Nachiket Kukade Date: Wed, 28 Mar 2018 15:06:47 +0530 Subject: [PATCH 290/508] wlan: In MGMT Tx, check GO operating channel before scheduling an ROC In some cases, after a peer becomes the GO, upper layer adds a GO adapter instead of using change_iface to change the peer adapter. In such cases, an MGMT frame sent on the peer adapter schedules an ROC even if it is on the same channel as the GO causing additional delays and connection failures. Before scheduling an ROC also check if the GO channel is same as the MGMT frame's Tx channel. Change-Id: Ia2165efe474220a2e05c4920e485a5cfd1d4040d CRs-Fixed: 2214076 --- CORE/HDD/src/wlan_hdd_p2p.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CORE/HDD/src/wlan_hdd_p2p.c b/CORE/HDD/src/wlan_hdd_p2p.c index 0b47a919badc1..d159b9c48f05f 100644 --- a/CORE/HDD/src/wlan_hdd_p2p.c +++ b/CORE/HDD/src/wlan_hdd_p2p.c @@ -1275,6 +1275,7 @@ int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev, struct net_device *dev = wdev->netdev; #endif hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_adapter_t *pGoAdapter; hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); @@ -1443,6 +1444,14 @@ int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev, { home_ch = pAdapter->sessionCtx.station.conn_info.operationChannel; } + else + { + pGoAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO); + if (pGoAdapter && test_bit(SOFTAP_BSS_STARTED, + &pGoAdapter->event_flags)) + home_ch = pGoAdapter->sessionCtx.ap.operatingChannel; + } + //If GO adapter exists and operating on same frequency //then we will not request remain on channel if (ieee80211_frequency_to_channel(chan->center_freq) == home_ch) From 8be45acd3a80cecbe5d6088b5b859041666ec6b9 Mon Sep 17 00:00:00 2001 From: Himanshu Agarwal Date: Tue, 3 Apr 2018 18:51:10 +0530 Subject: [PATCH 291/508] wlan: Check whether pNode is NULL instead of tmp_tx_context When assoc rsp with reject code is sent to fw, an entry is added in assoc rsp completion list. If a race condition happens between tx complete received from fw and TX complete timer timeout, it is possible that one is getting processed and another is queued in the MC thread. In that scenario, as both have same callback to call, the first one will remove the entry from assoc rsp completion list. When second one calls the callback, failure should be returned as no entry is present anymore. But due to NULL check for tmp_tx_context, which would point to the last valid entry, instead of pNode, which would actually be NULL when no entry is found, memory of last valid entry which is not corresponding to this assoc rsp is getting freed but the node is still present in the assoc rsp completion list leaving a dangling pointer. If some other module allocates some memory and gets the same memory which just gets wrongly freed in assoc rsp completion list, any operation on that node in assoc rsp completion list will corrupt the memory for other module causing memory corruption. Replace NULL check for tmp_tx_context with NULL check for pNode as pNode would be NULL if entry is not found in assoc response completion list. Change-Id: Ie122d950a78688360c07b1c738d29284ec73064b CRs-Fixed: 2218212 --- CORE/MAC/src/pe/lim/limUtils.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CORE/MAC/src/pe/lim/limUtils.c b/CORE/MAC/src/pe/lim/limUtils.c index af86449f48a00..96ee524993fd4 100644 --- a/CORE/MAC/src/pe/lim/limUtils.c +++ b/CORE/MAC/src/pe/lim/limUtils.c @@ -8721,6 +8721,7 @@ eHalStatus limAssocRspTxCompleteCnf(tpAniSirGlobal pMac, void *pData) pNode, &pNext ); pNode = pNext; pNext = NULL; + tmp_tx_context = NULL; } else { @@ -8730,7 +8731,7 @@ eHalStatus limAssocRspTxCompleteCnf(tpAniSirGlobal pMac, void *pData) } } - if (!tmp_tx_context) { + if (!pNode) { limLog(pMac, LOGE, FL("context is NULL")); return eHAL_STATUS_SUCCESS; } From 504131c42d7f32d991e5a3fca4d855a015a7da90 Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Tue, 1 Nov 2016 10:37:40 -0400 Subject: [PATCH 292/508] mdss: Fix solid fill unpack pattern Most users expect RGB order instead of RBG. When userspace gives an ARGB color, the blue and green channels are swapped. Adjust pattern to match ARGB instead of ARBG. CRs-Fixed: 1045472 1084507 Change-Id: I413ded858df41496d26362602abf3eb40c3cc1ed Signed-off-by: Naseer Ahmed --- drivers/video/msm/mdss/mdss_mdp_pipe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c index 1f03763b197a2..daed4149c0ae8 100644 --- a/drivers/video/msm/mdss/mdss_mdp_pipe.c +++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2304,7 +2304,7 @@ static int mdss_mdp_pipe_solidfill_setup(struct mdss_mdp_pipe *pipe) /* support ARGB color format only */ unpack = (C3_ALPHA << 24) | (C2_R_Cr << 16) | - (C1_B_Cb << 8) | (C0_G_Y << 0); + (C0_G_Y << 8) | (C1_B_Cb << 0); if (pipe->scaler.enable) opmode |= (1 << 31); From bf1c0f5ab92156bfb2bc1ae11f65c2437e0a5c53 Mon Sep 17 00:00:00 2001 From: Ingrid Gallardo Date: Thu, 18 Aug 2016 19:38:13 -0700 Subject: [PATCH 293/508] msm: mdss: increase mdp hw recovery timeout In some cases, display driver times out waiting for the mdp hw recovery to complete, causing the device to panic; however in some cases hw is able to successfuly complete the recovery after some more time. This change increases the timeout, so driver waits more time for the hw to complete the recovery sequence. CRs-Fixed: 1055875 Change-Id: I31909c45a4fec921da322658ec84d387d0f182ac Signed-off-by: Ingrid Gallardo --- drivers/video/msm/mdss/mdss_mdp_ctl.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c index a6a211dc4a686..e9f5252d5a819 100644 --- a/drivers/video/msm/mdss/mdss_mdp_ctl.c +++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -4328,9 +4328,11 @@ void mdss_mdp_check_ctl_reset_status(struct mdss_mdp_ctl *ctl) return; pr_debug("hw ctl reset is set for ctl:%d\n", ctl->num); - status = mdss_mdp_poll_ctl_reset_status(ctl, 5); + /* poll for at least ~1 frame */ + status = mdss_mdp_poll_ctl_reset_status(ctl, 320); if (status) { - pr_err("hw recovery is not complete for ctl:%d\n", ctl->num); + pr_err("hw recovery is not complete for ctl:%d status:0x%x\n", + ctl->num, status); MDSS_XLOG_TOUT_HANDLER("mdp", "vbif", "vbif_nrt", "dbg_bus", "vbif_dbg_bus", "panic"); } From 663af193e6078fa2a70b13349434dd492487867d Mon Sep 17 00:00:00 2001 From: Sreelakshmi Gownipalli Date: Tue, 17 Jan 2017 14:03:54 -0800 Subject: [PATCH 294/508] diag: Prevent NULL pointer dereference while closing logging process Prevent NULL pointer dereference while copying the data to memory device process by adding mutex protection when closing the process. Change-Id: Idaad73fb8b2a0bb5a4983d5e255bfdf702cecf71 Signed-off-by: Sreelakshmi Gownipalli --- drivers/char/diag/diagchar_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index d053013566e6b..39778311c2abc 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -439,8 +439,10 @@ static void diag_close_logging_process(const int pid) driver->mask_clear = 1; mutex_unlock(&driver->diag_maskclear_mutex); + mutex_lock(&driver->diagchar_mutex); session_peripheral_mask = session_info->peripheral_mask; diag_md_session_close(session_info); + mutex_unlock(&driver->diagchar_mutex); for (i = 0; i < NUM_MD_SESSIONS; i++) if (MD_PERIPHERAL_MASK(i) & session_peripheral_mask) diag_mux_close_peripheral(DIAG_LOCAL_PROC, i); From cb59c729ef0831f253427a2eb87d984d345854ab Mon Sep 17 00:00:00 2001 From: Siena Richard Date: Tue, 30 Aug 2016 18:06:44 -0700 Subject: [PATCH 295/508] msm: qdsp6v2: update CVD version CVD version is updated to 2.3 on ADSP. Update the mapping table in voice driver to allow CVD version 2.3 to be recognized and used. Change-Id: Id6d1c960dc720e8013eb9ba1f07af7662b576e37 CRs-Fixed: 1060201 Signed-off-by: Siena Richard --- sound/soc/msm/qdsp6v2/q6voice.c | 1 + sound/soc/msm/qdsp6v2/q6voice.h | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c index 8292f474a3574..506611d869725 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.c +++ b/sound/soc/msm/qdsp6v2/q6voice.c @@ -48,6 +48,7 @@ struct cvd_version_table cvd_version_table_mapping[CVD_INT_VERSION_MAX] = { {CVD_VERSION_0_0, CVD_INT_VERSION_0_0}, {CVD_VERSION_2_1, CVD_INT_VERSION_2_1}, {CVD_VERSION_2_2, CVD_INT_VERSION_2_2}, + {CVD_VERSION_2_3, CVD_INT_VERSION_2_3}, }; static struct common_data common; diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h index a4c3a4be19ee5..71c0e80464ef0 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.h +++ b/sound/soc/msm/qdsp6v2/q6voice.h @@ -42,12 +42,14 @@ #define CVD_VERSION_0_0 "0.0" #define CVD_VERSION_2_1 "2.1" #define CVD_VERSION_2_2 "2.2" +#define CVD_VERSION_2_3 "2.3" #define CVD_INT_VERSION_DEFAULT 0 #define CVD_INT_VERSION_0_0 1 #define CVD_INT_VERSION_2_1 2 #define CVD_INT_VERSION_2_2 3 -#define CVD_INT_VERSION_LAST CVD_INT_VERSION_2_2 +#define CVD_INT_VERSION_2_3 4 +#define CVD_INT_VERSION_LAST CVD_INT_VERSION_2_3 #define CVD_INT_VERSION_MAX (CVD_INT_VERSION_LAST + 1) struct cvd_version_table { From 41bec8da24d611b3bae4c391ee79b154edce4007 Mon Sep 17 00:00:00 2001 From: Sravan Kumar Kairam Date: Thu, 1 Feb 2018 12:25:28 +0530 Subject: [PATCH 296/508] wlan: Skip PN replay check for TDLS packets If any RX TDLS traffic coming to HOST during or after TDLS tear down as TDLS sta id does not exist the traffic is mapped to AP sta id. This will overwrite the current PN value for AP sta id. As a result after TDLS tear down packets coming via AP will be dropped due to replay check. To avoid this skip PN replay check for TDLS packets when mapped to AP sta id. Change-Id: Ibd24dde465832910fa8158d370c05c32ee8cd519 CRs-Fixed: 2182324 --- CORE/TL/src/wlan_qct_tl.c | 30 +++++++++++++++++++----------- CORE/TL/src/wlan_qct_tli.h | 5 ++++- CORE/VOSS/inc/i_vos_packet.h | 4 +++- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c index 6846f66efb1c3..8dcb520d5667a 100644 --- a/CORE/TL/src/wlan_qct_tl.c +++ b/CORE/TL/src/wlan_qct_tl.c @@ -6493,6 +6493,7 @@ WLANTL_RxFrames seq_no = (uint16_t)WDA_GET_RX_REORDER_CUR_PKT_SEQ_NO(pvBDHeader); pn_num = WDA_GET_RX_REPLAY_COUNT(pvBDHeader); + vosTempBuff->pn_replay_skip = 0; vosTempBuff->pn_num = pn_num; TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, @@ -6624,11 +6625,13 @@ WLANTL_RxFrames } else { - TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN, - "%s: staId %d doesn't exist, but mapped to AP staId %d", __func__, - ucSTAId, ucAddr3STAId)); + VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "staId %d doesn't exist" + " but mapped to AP staId %d PN:[0x%llX]", + ucSTAId, ucAddr3STAId, pn_num); ucSTAId = ucAddr3STAId; pClientSTA = pTLCb->atlSTAClients[ucAddr3STAId]; + vosTempBuff->pn_replay_skip = 1; } } } @@ -9772,10 +9775,10 @@ WLANTL_STARxAuth (v_PVOID_t)STAMetaInfoPtr); } - /*------------------------------------------------------------------------ - Check to see if re-ordering session is in place - ------------------------------------------------------------------------*/ - if ( 0 != pClientSTA->atlBAReorderInfo[ucTid].ucExists ) + /* Check to see if re-ordering session is in place. + Skip add to reorder list for TDLS packet on AP staid*/ + if (0 != pClientSTA->atlBAReorderInfo[ucTid].ucExists && + !vosDataBuff->pn_replay_skip) { WLANTL_MSDUReorder( pTLCb, &vosDataBuff, aucBDHeader, ucSTAId, ucTid ); } @@ -9787,7 +9790,8 @@ if(WLANTL_IS_DATA_FRAME(WDA_GET_RX_TYPE_SUBTYPE(aucBDHeader)) && #endif ) { - /* replay check code : check whether replay check is needed or not */ + /* replay check code : check whether replay check is needed or not + Skip replay check for TDLS traffic with AP sta id */ if(VOS_TRUE == pClientSTA->ucIsReplayCheckValid) { /* replay check is needed for the station */ @@ -9843,6 +9847,7 @@ if(WLANTL_IS_DATA_FRAME(WDA_GET_RX_TYPE_SUBTYPE(aucBDHeader)) && else { v_BOOL_t status; + uint16_t seq_no = (uint16_t)WDA_GET_RX_REORDER_CUR_PKT_SEQ_NO(aucBDHeader); /* Getting 48-bit replay counter from the RX BD */ ullcurrentReplayCounter = WDA_DS_GetReplayCounter(aucBDHeader); @@ -9859,7 +9864,7 @@ if(WLANTL_IS_DATA_FRAME(WDA_GET_RX_TYPE_SUBTYPE(aucBDHeader)) && /* It is not AMSDU frame so perform reaply check for each packet, as each packet contains valid replay counter*/ - if (vosDataBuff != NULL) { + if (vosDataBuff != NULL && !vosDataBuff->pn_replay_skip) { if (vos_is_pkt_chain(vosDataBuff)) { WLANTL_ReorderReplayCheck(pClientSTA, &vosDataBuff, ucTid); } else { @@ -9868,10 +9873,13 @@ if(WLANTL_IS_DATA_FRAME(WDA_GET_RX_TYPE_SUBTYPE(aucBDHeader)) && if(VOS_FALSE == status) { /* Not a replay paket, update previous replay counter in TL CB */ pClientSTA->ullReplayCounter[ucTid] = ullcurrentReplayCounter; + pClientSTA->last_seq_no[ucTid] = seq_no; } else { VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL: Non AMSDU Drop replay packet with PN: [0x%llX], prevPN: [0x%llx]", - ullcurrentReplayCounter, ullpreviousReplayCounter); + "Non AMSDU Drop replay with PN: [0x%llX], prevPN: [0x%llx]" + " seq_no:%d last_seq_no:%d", + ullcurrentReplayCounter, ullpreviousReplayCounter, seq_no, + pClientSTA->last_seq_no[ucTid]); pClientSTA->ulTotalReplayPacketsDetected++; VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, diff --git a/CORE/TL/src/wlan_qct_tli.h b/CORE/TL/src/wlan_qct_tli.h index 15204b5e830d5..868e745d45029 100644 --- a/CORE/TL/src/wlan_qct_tli.h +++ b/CORE/TL/src/wlan_qct_tli.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -703,6 +703,9 @@ typedef struct /* It contains 48-bit replay counter per TID*/ v_U64_t ullReplayCounter[WLANTL_MAX_TID]; + /* Last seq number received on Tid */ + v_U16_t last_seq_no[WLANTL_MAX_TID]; + /* It contains no of replay packets found per STA. It is for debugging purpose only.*/ v_U32_t ulTotalReplayPacketsDetected; diff --git a/CORE/VOSS/inc/i_vos_packet.h b/CORE/VOSS/inc/i_vos_packet.h index 173d792b77faa..ad6b9685cf4af 100644 --- a/CORE/VOSS/inc/i_vos_packet.h +++ b/CORE/VOSS/inc/i_vos_packet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013,2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013,2017-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -129,6 +129,8 @@ struct vos_pkt_t v_U64_t pn_num; + v_U8_t pn_replay_skip; + // magic number for verifying this is really a struct vos_pkt_t v_U32_t magic; }; From 400bc92595b07fecb7050a03cb7dc8083284fb67 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Sat, 17 Mar 2018 20:42:28 +0530 Subject: [PATCH 297/508] drivers : soc: qcom: mpm: Do not resend GPIO interrupts Interrupts configured as wakeup capable will be pending at both MPM and TLMM during system level LPMs. Since GPIO summary interrupt is level triggered, do not resend GPIO interrupts when exiting from system level LPMs. Change-Id: I63340396cf2764835d628906aa8e7c1278c88cec Signed-off-by: Maulik Shah --- drivers/soc/qcom/mpm-of.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/mpm-of.c b/drivers/soc/qcom/mpm-of.c index 97e03253b59e8..c1cd245a4506e 100644 --- a/drivers/soc/qcom/mpm-of.c +++ b/drivers/soc/qcom/mpm-of.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2016, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -608,8 +608,13 @@ void msm_mpm_exit_sleep(bool from_idle) unsigned int apps_irq = msm_mpm_get_irq_m2a(mpm_irq); struct irq_desc *desc = apps_irq ? irq_to_desc(apps_irq) : NULL; + struct irq_chip *chip = NULL; - if (desc && !irqd_is_level_type(&desc->irq_data)) { + if (desc) + chip = desc->irq_data.chip; + + if (desc && !irqd_is_level_type(&desc->irq_data) && + (!(chip && !strcmp(chip->name, "msmgpio")))) { irq_set_pending(apps_irq); if (from_idle) { raw_spin_lock(&desc->lock); From 3662756b6f8cbfab43070b8c62c01a184ba4bfe8 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Thu, 5 Apr 2018 10:44:19 +0530 Subject: [PATCH 298/508] wlan: Remove WDA_SET_MAX_TX_POWER_PER_BAND_RSP msg as its not used WDA_SetMaxTxPowerPerBandCallBack post a msg WDA_SET_MAX_TX_POWER_PER_BAND_RSP to lim but the msg is not handled in lim and only operation done is to free the wdaMsgParam memory. Fix is to remove the WDA_SET_MAX_TX_POWER_PER_BAND_RSP msg as no resp is expected by LIM and free the wdaMsgParam memory in WDA_SetMaxTxPowerPerBandCallBack Change-Id: I235a1aa237dc1fe11ed220c77ab48dd0c2d2b1be CRs-Fixed: 2218939 --- CORE/MAC/src/include/sirParams.h | 2 -- CORE/SYS/legacy/src/utils/src/macTrace.c | 1 - CORE/WDA/inc/wlan_qct_wda.h | 2 -- CORE/WDA/src/wlan_qct_wda.c | 42 ++++-------------------- 4 files changed, 7 insertions(+), 40 deletions(-) diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h index 5b936208f2e2b..ad1a54785bc44 100644 --- a/CORE/MAC/src/include/sirParams.h +++ b/CORE/MAC/src/include/sirParams.h @@ -700,8 +700,6 @@ typedef struct sSirMbMsgP2p #define SIR_HAL_SET_MAX_TX_POWER_PER_BAND_REQ \ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 229) -#define SIR_HAL_SET_MAX_TX_POWER_PER_BAND_RSP \ - (SIR_HAL_ITC_MSG_TYPES_BEGIN + 230) #define SIR_HAL_BCN_MISS_RATE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 231) diff --git a/CORE/SYS/legacy/src/utils/src/macTrace.c b/CORE/SYS/legacy/src/utils/src/macTrace.c index 5c72c1434ce96..c90dbafae7457 100644 --- a/CORE/SYS/legacy/src/utils/src/macTrace.c +++ b/CORE/SYS/legacy/src/utils/src/macTrace.c @@ -786,7 +786,6 @@ tANI_U8* macTraceGetWdaMsgString( tANI_U16 wdaMsg ) #endif //SUPPORT_BEACON_FILTER CASE_RETURN_STRING(WDA_SET_MAX_TX_POWER_REQ); CASE_RETURN_STRING(WDA_SET_MAX_TX_POWER_RSP); - CASE_RETURN_STRING(WDA_SET_MAX_TX_POWER_PER_BAND_RSP); CASE_RETURN_STRING(WDA_SET_MAX_TX_POWER_PER_BAND_REQ); CASE_RETURN_STRING(WDA_SEND_MSG_COMPLETE); CASE_RETURN_STRING(WDA_SET_HOST_OFFLOAD); diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h index 69a48fd73e672..dda8b0468887a 100644 --- a/CORE/WDA/inc/wlan_qct_wda.h +++ b/CORE/WDA/inc/wlan_qct_wda.h @@ -1144,8 +1144,6 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); #define WDA_SET_MAX_TX_POWER_PER_BAND_REQ \ SIR_HAL_SET_MAX_TX_POWER_PER_BAND_REQ -#define WDA_SET_MAX_TX_POWER_PER_BAND_RSP \ - SIR_HAL_SET_MAX_TX_POWER_PER_BAND_RSP #define WDA_SEND_MSG_COMPLETE SIR_HAL_SEND_MSG_COMPLETE diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c index 882dc14c139e0..6124bd41b237f 100644 --- a/CORE/WDA/src/wlan_qct_wda.c +++ b/CORE/WDA/src/wlan_qct_wda.c @@ -8855,8 +8855,6 @@ void WDA_SetMaxTxPowerPerBandCallBack(WDI_SetMaxTxPowerPerBandRspMsg void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; - tWDA_CbContext *pWDA = NULL; - tMaxTxPowerPerBandParams *pMxTxPwrPerBandParams = NULL; VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "<------ %s ", __func__); @@ -8867,38 +8865,14 @@ void WDA_SetMaxTxPowerPerBandCallBack(WDI_SetMaxTxPowerPerBandRspMsg VOS_ASSERT(0); return ; } - pWDA = (tWDA_CbContext *) pWdaParams->pWdaContext; - if (NULL == pWDA) - { - VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, - "%s:pWDA is NULL", __func__); - vos_mem_free(pWdaParams->wdaWdiApiMsgParam); - vos_mem_free(pWdaParams->wdaMsgParam); - vos_mem_free(pWdaParams); - VOS_ASSERT(0); - return ; - } - pMxTxPwrPerBandParams = (tMaxTxPowerPerBandParams*)pWdaParams->wdaMsgParam; - if ( NULL == pMxTxPwrPerBandParams ) - { - VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, - "%s: pMxTxPwrPerBandParams received NULL ", __func__); - VOS_ASSERT(0); - vos_mem_free(pWdaParams->wdaWdiApiMsgParam); - vos_mem_free(pWdaParams); - return; - } - - /*need to free memory for the pointers used in the - WDA Process.Set Max Tx Power Req function*/ + /* + * Need to free memory for the pointers used in the WDA Process.Set Max Tx + * Power Req function + */ vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); vos_mem_free(pWdaParams); - pMxTxPwrPerBandParams->power = pwdiSetMaxTxPowerPerBandRsp->ucPower; - - /* send response to UMAC*/ - WDA_SendMsg(pWDA, WDA_SET_MAX_TX_POWER_PER_BAND_RSP, - pMxTxPwrPerBandParams, 0); return; } @@ -8956,12 +8930,10 @@ void WDA_SetMaxTxPowerPerBandCallBack(WDI_SetMaxTxPowerPerBandRspMsg "Failure in SET MAX TX Power REQ Params WDI API," " free all the memory"); vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); vos_mem_free(pWdaParams); - /* send response to UMAC*/ - WDA_SendMsg(pWDA, - WDA_SET_MAX_TX_POWER_PER_BAND_RSP, - MaxTxPowerPerBandParams, 0); } + return CONVERT_WDI2VOS_STATUS(status); } From e58f3bc405df832a2a0dd4d5ffca4a221814e9c4 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Tue, 3 Apr 2018 12:59:05 +0530 Subject: [PATCH 299/508] wlan: Fix to pass appropriate buffer length to unpack RSN IE In lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message, length passed to unpack RSN IE is total length of WPA and RSN IE. So if only WPA IE is present in assoc request, the RSN IE parser will try to validate the buffer beyond the RSN IE and might fail as the buffer belongs to WPA IE. Pass appropriate length to unpack RSN IE. Change-Id: Ie679e67061e7ac622e8e76b285a32135a60ca6e8 CRs-Fixed: 2217268 --- CORE/MAC/src/pe/lim/limSmeReqUtils.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/CORE/MAC/src/pe/lim/limSmeReqUtils.c b/CORE/MAC/src/pe/lim/limSmeReqUtils.c index 42689a287ff0a..1adc7de2baaab 100644 --- a/CORE/MAC/src/pe/lim/limSmeReqUtils.c +++ b/CORE/MAC/src/pe/lim/limSmeReqUtils.c @@ -335,7 +335,9 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, LOG1, FL("Only RSN IE is present")); dot11fUnpackIeRSN(pMac,&pRSNie->rsnIEdata[2], - (tANI_U8)pRSNie->length,&pSessionEntry->gStartBssRSNIe); + pRSNie->rsnIEdata[1], + &pSessionEntry->gStartBssRSNIe); + return true; } else if ((pRSNie->length == pRSNie->rsnIEdata[1] + 2) && (pRSNie->rsnIEdata[0] == SIR_MAC_WPA_EID)) @@ -344,8 +346,10 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, LOG1, FL("Only WPA IE is present")); - dot11fUnpackIeWPA(pMac,&pRSNie->rsnIEdata[6],(tANI_U8)pRSNie->length-4, - &pSessionEntry->gStartBssWPAIe); + dot11fUnpackIeWPA(pMac,&pRSNie->rsnIEdata[6], + pRSNie->rsnIEdata[1] - 4, + &pSessionEntry->gStartBssWPAIe); + return true; } // Check validity of WPA IE @@ -371,7 +375,7 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, { /* Both RSN and WPA IEs are present */ dot11fUnpackIeRSN(pMac,&pRSNie->rsnIEdata[2], - (tANI_U8)pRSNie->length,&pSessionEntry->gStartBssRSNIe); + pRSNie->rsnIEdata[1], &pSessionEntry->gStartBssRSNIe); dot11fUnpackIeWPA(pMac,&pRSNie->rsnIEdata[wpaIndex + 6], pRSNie->rsnIEdata[wpaIndex + 1]-4, From 1fddb85311cac9698ff835d2a2e835d9740024e3 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Thu, 5 Apr 2018 12:25:05 +0530 Subject: [PATCH 300/508] clk: msm: gcc: Add support for 12MHz for mclk for 8953 mclk[0/1/2/3] requires a new frequency of 12MHz to be supported for client to be able to set the frequency. Add support for the same. Change-Id: If62ec4b559ebefdf3a95390f61e234d7af3ccaca Signed-off-by: Taniya Das --- drivers/clk/msm/clock-gcc-8953.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/clk/msm/clock-gcc-8953.c b/drivers/clk/msm/clock-gcc-8953.c index 64f409bda7710..24f294b12ae87 100644 --- a/drivers/clk/msm/clock-gcc-8953.c +++ b/drivers/clk/msm/clock-gcc-8953.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1177,6 +1177,7 @@ static struct rcg_clk camss_gp1_clk_src = { }; static struct clk_freq_tbl ftbl_mclk0_clk_src[] = { + F( 12000000, gpll6_main_div2, 1, 2, 90), F( 24000000, gpll6_main_div2, 1, 2, 45), F( 33330000, gpll0_main_div2, 12, 0, 0), F( 36610000, gpll6, 1, 2, 59), @@ -1199,6 +1200,7 @@ static struct rcg_clk mclk0_clk_src = { }; static struct clk_freq_tbl ftbl_mclk1_clk_src[] = { + F( 12000000, gpll6_main_div2, 1, 2, 90), F( 24000000, gpll6_main_div2, 1, 2, 45), F( 33330000, gpll0_main_div2, 12, 0, 0), F( 36610000, gpll6, 1, 2, 59), @@ -1221,6 +1223,7 @@ static struct rcg_clk mclk1_clk_src = { }; static struct clk_freq_tbl ftbl_mclk2_clk_src[] = { + F( 12000000, gpll6_main_div2, 1, 2, 90), F( 24000000, gpll6_main_div2, 1, 2, 45), F( 33330000, gpll0_main_div2, 12, 0, 0), F( 36610000, gpll6, 1, 2, 59), @@ -1243,6 +1246,7 @@ static struct rcg_clk mclk2_clk_src = { }; static struct clk_freq_tbl ftbl_mclk3_clk_src[] = { + F( 12000000, gpll6_main_div2, 1, 2, 90), F( 24000000, gpll6_main_div2, 1, 2, 45), F( 33330000, gpll0_main_div2, 12, 0, 0), F( 36610000, gpll6, 1, 2, 59), From 81b4326d5828cd58e476b4860dde8dcc10884b2b Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Thu, 15 Mar 2018 16:57:36 +0530 Subject: [PATCH 301/508] wlan: Use request manager for SNR qcacld-3.0 to prima propagation. We are transitioning to the new request manager framework. Change wlan_hdd_get_snr() and hdd_get_snr_cb() to this framework. Change-Id: Ib7628ee6931450b3b1ee73a0ede6c21ba6427407 CRs-Fixed: 2206396 --- CORE/HDD/inc/wlan_hdd_main.h | 1 - CORE/HDD/src/wlan_hdd_wext.c | 146 +++++++++++++++-------------------- 2 files changed, 61 insertions(+), 86 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index fbdf0c9ae5031..64f9843ef8029 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -347,7 +347,6 @@ extern spinlock_t hdd_context_lock; #define STATS_CONTEXT_MAGIC 0x53544154 //STAT #define RSSI_CONTEXT_MAGIC 0x52535349 //RSSI #define POWER_CONTEXT_MAGIC 0x504F5752 //POWR -#define SNR_CONTEXT_MAGIC 0x534E5200 //SNR #define BCN_MISS_RATE_CONTEXT_MAGIC 0x513F5753 #define FW_STATS_CONTEXT_MAGIC 0x5022474E //FW STATS #define GET_FRAME_LOG_MAGIC 0x464c4f47 //FLOG diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 9459131730419..0e69ae2c34435 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -105,6 +105,7 @@ #include "vos_utils.h" #include "sapInternal.h" +#include "wlan_hdd_request_manager.h" #ifdef CONFIG_HAS_EARLYSUSPEND extern void hdd_suspend_wlan(struct early_suspend *wlan_suspend); @@ -972,62 +973,35 @@ static void hdd_GetRssiCB( v_S7_t rssi, tANI_U32 staId, void *pContext ) spin_unlock(&hdd_context_lock); } -static void hdd_GetSnrCB(tANI_S8 snr, tANI_U32 staId, void *pContext) -{ - struct statsContext *pStatsContext; - hdd_adapter_t *pAdapter; - - if (ioctl_debug) - { - pr_info("%s: snr [%d] STA [%d] pContext [%pK]\n", - __func__, (int)snr, (int)staId, pContext); - } - - if (NULL == pContext) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Bad param, pContext [%pK]", - __func__, pContext); - return; - } - - pStatsContext = pContext; - pAdapter = pStatsContext->pAdapter; - - /* there is a race condition that exists between this callback - function and the caller since the caller could time out either - before or while this code is executing. we use a spinlock to - serialize these actions */ - spin_lock(&hdd_context_lock); - - if ((NULL == pAdapter) || (SNR_CONTEXT_MAGIC != pStatsContext->magic)) - { - /* the caller presumably timed out so there is nothing we can do */ - spin_unlock(&hdd_context_lock); - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter [%pK] magic [%08x]", - __func__, pAdapter, pStatsContext->magic); - if (ioctl_debug) - { - pr_info("%s: Invalid context, pAdapter [%pK] magic [%08x]\n", - __func__, pAdapter, pStatsContext->magic); - } - return; - } - - /* context is valid so caller is still waiting */ - - /* paranoia: invalidate the magic */ - pStatsContext->magic = 0; +struct snr_priv { + int8_t snr; +}; - /* copy over the snr */ - pAdapter->snr = snr; +/** + * hdd_get_snr_cb() - "Get SNR" callback function + * @snr: Current SNR of the station + * @sta_id: ID of the station + * @context: opaque context originally passed to SME. HDD always passes + * a cookie for the request context + * + * Return: None + */ +static void hdd_get_snr_cb(tANI_S8 snr, tANI_U32 staId, void *context) +{ + struct hdd_request *request; + struct snr_priv *priv; - /* notify the caller */ - complete(&pStatsContext->completion); + request = hdd_request_get(context); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); + return; + } - /* serialization is complete */ - spin_unlock(&hdd_context_lock); + /* propagate response back to requesting thread */ + priv = hdd_request_priv(request); + priv->snr = snr; + hdd_request_complete(request); + hdd_request_put(request); } VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value) @@ -1179,12 +1153,17 @@ VOS_STATUS wlan_hdd_get_frame_logs(hdd_adapter_t *pAdapter, v_U8_t flag) VOS_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, v_S7_t *snr) { - struct statsContext context; hdd_context_t *pHddCtx; hdd_station_ctx_t *pHddStaCtx; eHalStatus hstatus; - long lrc; - int valid; + int ret; + void *cookie; + struct hdd_request *request; + struct snr_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; ENTER(); @@ -1197,8 +1176,8 @@ VOS_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, v_S7_t *snr) pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - valid = wlan_hdd_validate_context(pHddCtx); - if (0 != valid) + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { return VOS_STATUS_E_FAULT; } @@ -1210,14 +1189,17 @@ VOS_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, v_S7_t *snr) return VOS_STATUS_E_FAULT; } - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = SNR_CONTEXT_MAGIC; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + return VOS_STATUS_E_FAULT; + } + cookie = hdd_request_cookie(request); - hstatus = sme_GetSnr(pHddCtx->hHal, hdd_GetSnrCB, + hstatus = sme_GetSnr(pHddCtx->hHal, hdd_get_snr_cb, pHddStaCtx->conn_info.staId[ 0 ], pHddStaCtx->conn_info.bssId, - &context); + cookie); if (eHAL_STATUS_SUCCESS != hstatus) { hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to retrieve RSSI", @@ -1227,30 +1209,24 @@ VOS_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, v_S7_t *snr) else { /* request was sent -- wait for the response */ - lrc = wait_for_completion_timeout(&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - if (lrc <= 0) - { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME %s while retrieving SNR", - __func__, (0 == lrc) ? "timeout" : "interrupt"); - /* we'll now returned a cached value below */ - } + ret = hdd_request_wait_for_response(request); + if (ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timed out while retrieving SNR")); + /* we'll now returned a cached value below */ + } else { + /* update the adapter with the fresh results */ + priv = hdd_request_priv(request); + pAdapter->snr = priv->snr; + } } - /* either we never sent a request, we sent a request and received a - response or we sent a request and timed out. if we never sent a - request or if we sent a request and got a response, we want to - clear the magic out of paranoia. if we timed out there is a - race condition such that the callback function could be - executing at the same time we are. of primary concern is if the - callback function had already verified the "magic" but had not - yet set the completion variable when a timeout occurred. we - serialize these activities by invalidating the magic while - holding a shared spinlock which will cause us to block if the - callback is currently executing */ - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); + /* + * either we never sent a request, we sent a request and + * received a response or we sent a request and timed out. + * regardless we are done with the request. + */ + hdd_request_put(request); *snr = pAdapter->snr; From ab9d309f7eae559026920ad5a827e3ac480942f6 Mon Sep 17 00:00:00 2001 From: Dundi Raviteja Date: Thu, 5 Apr 2018 18:24:40 +0530 Subject: [PATCH 302/508] wlan: Start split scan if VOWIFIMODE is enabled Start split scan if VOWIFIMODE is set to 1 and stop if it is set to 0 regardless of traffic. Change-Id: I1b3b7b141b0fdf5ff7b7a920b1c7a3f246f3c1a4 CRs-Fixed: 2219146 --- CORE/HDD/inc/wlan_hdd_main.h | 1 + CORE/HDD/src/wlan_hdd_main.c | 19 +++++++++++++++++-- CORE/HDD/src/wlan_hdd_tx_rx.c | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index 64f9843ef8029..2e3b606bf9bfc 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -1775,6 +1775,7 @@ struct hdd_context_s */ vos_timer_t tx_rx_trafficTmr; v_U8_t drvr_miracast; + bool is_vowifi_enabled; v_U8_t issplitscan_enabled; v_U8_t isTdlsScanCoexistence; diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 07e1a343e4153..784eb778d27b2 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -878,13 +878,28 @@ void hdd_set_vowifi_mode(hdd_context_t *hdd_ctx, bool enable) { tANI_U8 sta_chan; + if (!hdd_ctx->cfg_ini) { + hddLog(LOGE, "cfg_ini got NULL"); + return; + } + sta_chan = hdd_get_operating_channel(hdd_ctx, WLAN_HDD_INFRA_STATION); - if (CSR_IS_CHANNEL_24GHZ(sta_chan)) + if (CSR_IS_CHANNEL_24GHZ(sta_chan)) { sme_set_vowifi_mode(hdd_ctx->hHal, enable); - else + if (enable && hdd_ctx->cfg_ini->dynSplitscan) { + hdd_ctx->is_vowifi_enabled = true; + hdd_ctx->issplitscan_enabled = TRUE; + sme_enable_disable_split_scan(hdd_ctx->hHal, + hdd_ctx->cfg_ini->nNumStaChanCombinedConc, + hdd_ctx->cfg_ini->nNumP2PChanCombinedConc); + } else { + hdd_ctx->is_vowifi_enabled = false; + } + } else { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "VoWiFi command rejected as not connected in 2.4GHz"); + } } /* Function header left blank Intentionally */ diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c index f643e30cbf740..3fadfa5979aa4 100644 --- a/CORE/HDD/src/wlan_hdd_tx_rx.c +++ b/CORE/HDD/src/wlan_hdd_tx_rx.c @@ -3007,7 +3007,7 @@ void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx) cfg_param->txRxThresholdForSplitScan) || (pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count > cfg_param->txRxThresholdForSplitScan) || - pHddCtx->drvr_miracast || + pHddCtx->drvr_miracast || pHddCtx->is_vowifi_enabled || (WLAN_HDD_P2P_GO == pAdapter->device_mode)) { pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0; From 25a6bb5d4dbb00a58b14b3bf7d859b3631901edf Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Tue, 20 Feb 2018 16:20:36 +0530 Subject: [PATCH 303/508] usb: gadget: f_gps: Fix no responses on suspend/resume In the case where the host pc is put to sleep, the device is suspended and the previous gps session is teared down by the modem. Upon host pc wakeup a new session is started by the modem, but the u_glink driver still has the context for the previous session resulting in no communication between the modem and the driver. Fix this by closing the previous session on receiving REMOTE_DISCONNECTED and start a new session on resume if the session is teared now on suspend. Change-Id: Ibf2d9c35b62691e067cc835fd875248b89323df5 Signed-off-by: Sriharsha Allenki --- drivers/usb/gadget/function/f_gps.c | 11 ++++++++++- drivers/usb/gadget/function/u_glink.c | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/function/f_gps.c b/drivers/usb/gadget/function/f_gps.c index 9ea5ae9488686..a208274f2407e 100644 --- a/drivers/usb/gadget/function/f_gps.c +++ b/drivers/usb/gadget/function/f_gps.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -351,6 +351,15 @@ static void gps_resume(struct usb_function *f) return; dev->is_suspended = false; + + /* Check if the previous session is closed as part of suspend + * and try to reconnect to open a new session. + */ + if (!atomic_read(&dev->ctrl_online)) { + pr_debug("%s: ctrl disconnected, reconnect again\n", __func__); + gport_ctrl_connect(dev); + } + spin_lock(&dev->lock); if (list_empty(&dev->cpkt_resp_q)) { spin_unlock(&dev->lock); diff --git a/drivers/usb/gadget/function/u_glink.c b/drivers/usb/gadget/function/u_glink.c index b09ceb31a8d54..5161a0bee3d6e 100644 --- a/drivers/usb/gadget/function/u_glink.c +++ b/drivers/usb/gadget/function/u_glink.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -375,6 +375,15 @@ static void glink_notify_state(void *handle, const void *priv, unsigned event) if (gr && gr->disconnect) gr->disconnect(gr); glink_purge_tx_q(ch_info); + /** + * If the channel is closed on the REMOTE side, the channel + * needs to be closed from the LOCAL as well so that the current + * context is cleared and the channel can be opened afresh. + */ + if (ch_info->handle) { + pr_debug("%s queue disconnect work\n", __func__); + queue_work(glink_ctrl_wq, &ch_info->disconnect_w); + } break; default: pr_err("%s: invalid channel state notification\n", __func__); From 5b2e733746bd8f62423f11f1b1ea91f831d274d7 Mon Sep 17 00:00:00 2001 From: Nachiket Kukade Date: Fri, 6 Apr 2018 14:40:22 +0530 Subject: [PATCH 304/508] wlan: Expose wowlan capability to cfg80211 cfg80211 layer (kernel version 3.10 and above) issues disconnect on connected interfaces during platform suspend if wow is not enabled via nl80211. After disconnection driver can not put the chip into wow mode. This results in increased power consumption and frequent connect/disconnects. To stop cfg80211 issuing disconnect, expose wow capability to cfg80211 and let the user to enable wow via nl80211. Change-Id: I4a2e76ec093e5f0e8fd6b9ba960c09a20c764354 CRs-Fixed: 2219758 --- CORE/HDD/inc/wlan_hdd_cfg80211.h | 3 +++ CORE/HDD/src/wlan_hdd_cfg80211.c | 17 +++++++++++++++++ CORE/HDD/src/wlan_hdd_wowl.c | 3 --- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h index 7d47327b46d30..369477b8b9faa 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -121,6 +121,9 @@ #define NUM_RADIOS 0x1 #endif /* WLAN_FEATURE_LINK_LAYER_STATS */ +#define WOWL_PTRN_MAX_SIZE 128 +#define WOWL_PTRN_MASK_MAX_SIZE 16 +#define WOWL_MAX_PTRNS_ALLOWED 16 typedef struct { u8 element_id; diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index b1ccb19dcc241..e92b5b7dc75ba 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -459,6 +459,15 @@ wlan_hdd_iface_combination[] = { }; #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)) || defined(WITH_BACKPORTS) +static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = { + .flags = WIPHY_WOWLAN_MAGIC_PKT, + .n_patterns = WOWL_MAX_PTRNS_ALLOWED, + .pattern_min_len = 1, + .pattern_max_len = WOWL_PTRN_MAX_SIZE, +}; +#endif + static struct cfg80211_ops wlan_hdd_cfg80211_ops; /* Data rate 100KBPS based on IE Index */ @@ -9019,6 +9028,14 @@ int wlan_hdd_cfg80211_init(struct device *dev, wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS; #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)) || defined(WITH_BACKPORTS) + wiphy->wowlan = &wowlan_support_cfg80211_init; +#else + wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT; + wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED; + wiphy->wowlan.pattern_min_len = 1; + wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE; +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME diff --git a/CORE/HDD/src/wlan_hdd_wowl.c b/CORE/HDD/src/wlan_hdd_wowl.c index 846024b64e55a..73268c5a26e07 100644 --- a/CORE/HDD/src/wlan_hdd_wowl.c +++ b/CORE/HDD/src/wlan_hdd_wowl.c @@ -43,9 +43,6 @@ * Preprocessor Definitions and Constants * -------------------------------------------------------------------------*/ -#define WOWL_PTRN_MAX_SIZE 128 -#define WOWL_PTRN_MASK_MAX_SIZE 16 -#define WOWL_MAX_PTRNS_ALLOWED 16 #define WOWL_INTER_PTRN_TOKENIZER ';' #define WOWL_INTRA_PTRN_TOKENIZER ':' From 877f4c432b9ea76aa86e91804150efaeecc4f62e Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 13 Jan 2017 13:12:29 -0800 Subject: [PATCH 305/508] f2fs: do not preallocate blocks which has wrong buffer Sheng Yong reports needless preallocation if write(small_buffer, large_size) is called. In that case, f2fs preallocates large_size, but vfs returns early due to small_buffer size. Let's detect it before preallocation phase in f2fs. Change-Id: I932f9d442c3bad6576ab67ddca47d500edf905fe Reported-by: Sheng Yong Signed-off-by: Jaegeuk Kim Git-Repo: https://android.googlesource.com/kernel/common/ Git-Commit: b6453fcb2fe808424106cebad7bb6c4a2bd95f00 Signed-off-by: Sahitya Tummala --- fs/f2fs/data.c | 6 +++++- fs/f2fs/f2fs.h | 1 + fs/f2fs/file.c | 10 +++++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 8a26a069d3c97..8b652880cfc4d 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -840,6 +840,9 @@ int f2fs_preallocate_blocks(struct inode *inode, loff_t pos, return err; } + if (is_inode_flag_set(inode, FI_NO_PREALLOC)) + return 0; + map.m_lblk = F2FS_BLK_ALIGN(pos); map.m_len = F2FS_BYTES_TO_BLK(pos + count); if (map.m_len > map.m_lblk) @@ -1865,7 +1868,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, * we already allocated all the blocks, so we don't need to get * the block addresses when there is no need to fill the page. */ - if (!f2fs_has_inline_data(inode) && len == PAGE_SIZE) + if (!f2fs_has_inline_data(inode) && len == PAGE_SIZE && + !is_inode_flag_set(inode, FI_NO_PREALLOC)) return 0; if (f2fs_has_inline_data(inode) || diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index e40eb01797e80..f399a99b27fad 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2200,6 +2200,7 @@ enum { FI_INLINE_DOTS, /* indicate inline dot dentries */ FI_DO_DEFRAG, /* indicate defragment is running */ FI_DIRTY_FILE, /* indicate regular/symlink has dirty pages */ + FI_NO_PREALLOC, /* indicate skipped preallocated blocks */ FI_HOT_DATA, /* indicate file is hot */ FI_EXTRA_ATTR, /* indicate file has extra attribute */ FI_PROJ_INHERIT, /* indicate file inherits projectid */ diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 002a54ba80018..130a74d29073d 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -2536,15 +2537,22 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) inode_lock(inode); ret = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); if (!ret) { - int err = f2fs_preallocate_blocks(inode, pos, count, + int err; + + if (iov_iter_fault_in_readable(from, iov_iter_count(from))) + set_inode_flag(inode, FI_NO_PREALLOC); + + err = f2fs_preallocate_blocks(inode, pos, count, file->f_flags & O_DIRECT); if (err) { + clear_inode_flag(inode, FI_NO_PREALLOC); inode_unlock(inode); return err; } blk_start_plug(&plug); ret = __generic_file_write_iter(iocb, from); blk_finish_plug(&plug); + clear_inode_flag(inode, FI_NO_PREALLOC); if (ret > 0) f2fs_update_iostat(F2FS_I_SB(inode), APP_WRITE_IO, ret); From c3bfe0aa7c9a57c7bc2250a1bef6d3f9cc11c92b Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Mon, 26 Mar 2018 13:11:28 +0800 Subject: [PATCH 306/508] prima: Add BSS if new channel same to current channel in ECSA IE In some special case, reference AP or P2P GO included ECSA IE wrongly, and the new channel is same to current channel. Change-Id: Iae6b55db913a47bf6199ac0d490d1c10017c471b CRs-Fixed: 2209738 --- CORE/MAC/src/pe/lim/limScanResultUtils.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/CORE/MAC/src/pe/lim/limScanResultUtils.c b/CORE/MAC/src/pe/lim/limScanResultUtils.c index 90b5ae020bb49..8af7d6ffed8c4 100644 --- a/CORE/MAC/src/pe/lim/limScanResultUtils.c +++ b/CORE/MAC/src/pe/lim/limScanResultUtils.c @@ -450,11 +450,25 @@ limCheckAndAddBssDescription(tpAniSirGlobal pMac, * caching the scan results for APs which are adverzing the channel-switch * element in their beacons and probe responses. */ - if(pBPR->channelSwitchPresent || pBPR->ecsa_present) + if(pBPR->channelSwitchPresent) { return; } + if(pBPR->ecsa_present) { + limLog(pMac, LOGW, FL("ECSA IE present")); + /* Still add to scan result if ECSA IE present and new channel + * equal to current channel. + */ + if (pBPR->channelNumber!= HAL_INVALID_CHANNEL_ID && + pBPR->ext_chan_switch_ann.new_channel != HAL_INVALID_CHANNEL_ID && + pBPR->channelNumber != pBPR->ext_chan_switch_ann.new_channel) { + limLog(pMac, LOGW, FL("ignore this AP")); + return; + } + + } + /* If beacon/probe resp DS param channel does not match with * RX BD channel then don't save the results. It might be a beacon * from another channel heard as noise on the current scanning channel From ae4cc04332ff4103a91866c77f6b8e5ef8a43a8b Mon Sep 17 00:00:00 2001 From: Siddartha Mohanadoss Date: Mon, 2 Apr 2018 19:52:35 -0700 Subject: [PATCH 307/508] msm: mhi_dev: Send uevents during device reset Notify clients during MHI device reset on channel and device reset. Change-Id: Id3b6f564bd85346e9177b27c8a7647c504998a64 Signed-off-by: Siddartha Mohanadoss --- drivers/platform/msm/mhi_dev/mhi.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 011628b5eee0d..0f6a0d255db61 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -39,6 +39,7 @@ /* Wait time before suspend/resume is complete */ #define MHI_SUSPEND_MIN 100 #define MHI_SUSPEND_TIMEOUT 600 +#define MHI_WAKEUP_TIMEOUT_CNT 20 #define MHI_MASK_CH_EV_LEN 32 #define MHI_RING_CMD_ID 0 #define MHI_RING_PRIMARY_EVT_ID 1 @@ -1310,6 +1311,8 @@ static int mhi_dev_abort(struct mhi_dev *mhi) struct mhi_dev_channel *ch; struct mhi_dev_ring *ring; int ch_id = 0, rc = 0; + char *disconnected_12[2] = { "MHI_CHANNEL_STATE_12=DISCONNECTED", NULL}; + char *disconnected_14[2] = { "MHI_CHANNEL_STATE_14=DISCONNECTED", NULL}; /* Hard stop all the channels */ for (ch_id = 0; ch_id < mhi->cfg.channels; ch_id++) { @@ -1325,6 +1328,17 @@ static int mhi_dev_abort(struct mhi_dev *mhi) /* Update ctrl node */ mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_DISCONNECTED); + mhi_update_state_info(MHI_CLIENT_MBIM_OUT, MHI_STATE_DISCONNECTED); + mhi_update_state_info(MHI_CLIENT_QMI_OUT, MHI_STATE_DISCONNECTED); + rc = kobject_uevent_env(&mhi_ctx->dev->kobj, + KOBJ_CHANGE, disconnected_12); + if (rc) + pr_err("Error sending uevent:%d\n", rc); + + rc = kobject_uevent_env(&mhi_ctx->dev->kobj, + KOBJ_CHANGE, disconnected_14); + if (rc) + pr_err("Error sending uevent:%d\n", rc); flush_workqueue(mhi->ring_init_wq); flush_workqueue(mhi->pending_ring_wq); @@ -2154,11 +2168,19 @@ int mhi_dev_write_channel(struct mhi_req *wreq) } while (atomic_read(&mhi_ctx->is_suspended) && - suspend_wait_timeout < MHI_SUSPEND_TIMEOUT) { + suspend_wait_timeout < MHI_WAKEUP_TIMEOUT_CNT) { /* wait for the suspend to finish */ msleep(MHI_SUSPEND_MIN); suspend_wait_timeout++; } + + if (suspend_wait_timeout >= MHI_WAKEUP_TIMEOUT_CNT || + mhi_ctx->ctrl_info != MHI_STATE_CONNECTED) { + pr_err("Failed to wake up core\n"); + mutex_unlock(&mhi_ctx->mhi_write_test); + return -ENODEV; + } + handle_client = wreq->client; ch = handle_client->channel; ch->wr_request_active = true; From 9ca78a40248bd0a54fb3925516e1b795409e6105 Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Wed, 4 Apr 2018 11:02:28 +0530 Subject: [PATCH 308/508] USB: f_accessory: Check dev pointer before decoding ctrl request In case of poweroff charging mode, accessory function instance is not created and due to this, _acc_dev will be NULL. If target is connected to Accessory dock in poweroff charging mode, there is a chance dev pointer is accessed, which is NULL. Hence add a check before processing control request and return error if it is NULL. Change-Id: I4f1deb9d764b8c0bd1d7837cbc43a2933167f568 Signed-off-by: Vijayavardhan Vennapusa --- drivers/usb/gadget/function/f_accessory.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c index 27b2926f16bec..a58e4ba86ca32 100644 --- a/drivers/usb/gadget/function/f_accessory.c +++ b/drivers/usb/gadget/function/f_accessory.c @@ -878,6 +878,12 @@ int acc_ctrlrequest(struct usb_composite_dev *cdev, u16 w_length = le16_to_cpu(ctrl->wLength); unsigned long flags; + /* + * If instance is not created which is the case in power off charging + * mode, dev will be NULL. Hence return error if it is the case. + */ + if (!dev) + return -ENODEV; /* printk(KERN_INFO "acc_ctrlrequest " "%02x.%02x v%04x i%04x l%u\n", From 8a945424f96eb2b17f14eb669e1548229221d454 Mon Sep 17 00:00:00 2001 From: Nirmal Abraham Date: Thu, 25 Jan 2018 15:18:32 +0530 Subject: [PATCH 309/508] msm: Allocate fd with O_CLOEXEC flag (cherry-pick from 'commit 580ec70acac4 ("fbdev: msm: Allocate fd with O_CLOEXEC flag")') and made similar changes for MDP3. When fd is requested during get_metadata call, create fd using O_CLOEXEC flag. Change-Id: Iaa55927ac04b019ea45fbdfe9c64b10d1f0e3ceb Signed-off-by: Nirmal Abraham --- drivers/video/msm/mdss/mdp3_ctrl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c index 7177c694c3f91..b0c7cb4d77404 100644 --- a/drivers/video/msm/mdss/mdp3_ctrl.c +++ b/drivers/video/msm/mdss/mdp3_ctrl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1723,9 +1723,10 @@ static int mdp3_get_metadata(struct msm_fb_data_type *mfd, } break; case metadata_op_get_ion_fd: - if (mfd->fb_ion_handle) { + if (mfd->fb_ion_handle && mfd->fb_ion_client) { metadata->data.fbmem_ionfd = - dma_buf_fd(mfd->fbmem_buf, 0); + ion_share_dma_buf_fd(mfd->fb_ion_client, + mfd->fb_ion_handle); if (metadata->data.fbmem_ionfd < 0) pr_err("fd allocation failed. fd = %d\n", metadata->data.fbmem_ionfd); From bba4672d87b50afc1979fbc1a0037ca00ccb73e5 Mon Sep 17 00:00:00 2001 From: Nirmal Abraham Date: Tue, 3 Apr 2018 16:06:33 +0530 Subject: [PATCH 310/508] msm: mdss: use vmalloc for sglist allocation In scenarios where system is running low on memory, the sglist allocation during sg_table cloning was failing as there was no order 4 pages available. The cloned list is only used for iommu map/unmap SW ops and not used by HW. So it's safe to use physically noncontinuous sglist. Thus replacing kmalloc with vmalloc for sglist allocation. Change-Id: I80a10377398f90756df9533a78a63f4da3fe9a43 Signed-off-by: Nirmal Abraham --- drivers/video/msm/mdss/mdp3.c | 7 ++++--- drivers/video/msm/mdss/mdss_smmu.c | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c index 0a6ae344b44c2..832a5c7bd112a 100644 --- a/drivers/video/msm/mdss/mdp3.c +++ b/drivers/video/msm/mdss/mdp3.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * Copyright (C) 2007 Google Incorporated * * This software is licensed under the terms of the GNU General Public @@ -46,6 +46,7 @@ #include #include #include +#include #include @@ -1856,7 +1857,7 @@ int mdp3_put_img(struct mdp3_img_data *data, int client) return -EINVAL; } if (client == MDP3_CLIENT_PPP || client == MDP3_CLIENT_DMA_P) { - kfree(data->tab_clone->sgl); + vfree(data->tab_clone->sgl); kfree(data->tab_clone); } return 0; @@ -1985,7 +1986,7 @@ int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data, int client) dma_buf_put(data->srcp_dma_buf); if (client == MDP3_CLIENT_PPP || client == MDP3_CLIENT_DMA_P) { - kfree(data->tab_clone->sgl); + vfree(data->tab_clone->sgl); kfree(data->tab_clone); } return ret; diff --git a/drivers/video/msm/mdss/mdss_smmu.c b/drivers/video/msm/mdss/mdss_smmu.c index e0d0579009a1f..600a44ea006cf 100644 --- a/drivers/video/msm/mdss/mdss_smmu.c +++ b/drivers/video/msm/mdss/mdss_smmu.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2007-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2007-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -495,7 +496,7 @@ static void mdss_smmu_deinit_v2(struct mdss_data_type *mdata) * either sides of sgl. * * Returns: - * Pointer to new kmalloced sg list, ERR_PTR() on error + * Pointer to new vmalloced sg list, ERR_PTR() on error * */ static struct scatterlist *sg_clone(struct scatterlist *orig_sgl, u64 len, @@ -511,7 +512,7 @@ static struct scatterlist *sg_clone(struct scatterlist *orig_sgl, u64 len, if (padding) nents += 2; - head = kmalloc_array(nents, sizeof(struct scatterlist), gfp_mask); + head = vmalloc(nents * sizeof(struct scatterlist)); if (!head) return ERR_PTR(-ENOMEM); From bc686fa8892b1ca07a6104599fd6c4e19b0c75ba Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 22 Sep 2017 11:56:49 -0400 Subject: [PATCH 311/508] USB: uas: fix bug in handling of alternate settings The uas driver has a subtle bug in the way it handles alternate settings. The uas_find_uas_alt_setting() routine returns an altsetting value (the bAlternateSetting number in the descriptor), but uas_use_uas_driver() then treats that value as an index to the intf->altsetting array, which it isn't. Normally this doesn't cause any problems because the various alternate settings have bAlternateSetting values 0, 1, 2, ..., so the value is equal to the index in the array. But this is not guaranteed, and Andrey Konovalov used the syzkaller fuzzer with KASAN to get a slab-out-of-bounds error by violating this assumption. This patch fixes the bug by making uas_find_uas_alt_setting() return a pointer to the altsetting entry rather than either the value or the index. Pointers are less subject to misinterpretation. Change-Id: Ie4edf51381ad64c79ac0f52c2c40bd7335915732 Git-commit: 786de92b3cb26012d3d0f00ee37adf14527f35c4 Git-repo: https://github.com/torvalds/linux/commit Signed-off-by: Alan Stern Reported-by: Andrey Konovalov Tested-by: Andrey Konovalov CC: Oliver Neukum CC: Signed-off-by: Greg Kroah-Hartman Signed-off-by: Srinivasa Rao Kuppala --- drivers/usb/storage/uas-detect.h | 15 ++++++++------- drivers/usb/storage/uas.c | 10 +++++----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h index a451903a6857d..a0b92096f6f16 100644 --- a/drivers/usb/storage/uas-detect.h +++ b/drivers/usb/storage/uas-detect.h @@ -9,7 +9,8 @@ static int uas_is_interface(struct usb_host_interface *intf) intf->desc.bInterfaceProtocol == USB_PR_UAS); } -static int uas_find_uas_alt_setting(struct usb_interface *intf) +static struct usb_host_interface *uas_find_uas_alt_setting( + struct usb_interface *intf) { int i; @@ -17,10 +18,10 @@ static int uas_find_uas_alt_setting(struct usb_interface *intf) struct usb_host_interface *alt = &intf->altsetting[i]; if (uas_is_interface(alt)) - return alt->desc.bAlternateSetting; + return alt; } - return -ENODEV; + return NULL; } static int uas_find_endpoints(struct usb_host_interface *alt, @@ -58,14 +59,14 @@ static int uas_use_uas_driver(struct usb_interface *intf, struct usb_device *udev = interface_to_usbdev(intf); struct usb_hcd *hcd = bus_to_hcd(udev->bus); unsigned long flags = id->driver_info; - int r, alt; - + struct usb_host_interface *alt; + int r; alt = uas_find_uas_alt_setting(intf); - if (alt < 0) + if (!alt) return 0; - r = uas_find_endpoints(&intf->altsetting[alt], eps); + r = uas_find_endpoints(alt, eps); if (r < 0) return 0; diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 2ef0f0abe246a..b7ea35c258527 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -854,14 +854,14 @@ MODULE_DEVICE_TABLE(usb, uas_usb_ids); static int uas_switch_interface(struct usb_device *udev, struct usb_interface *intf) { - int alt; + struct usb_host_interface *alt; alt = uas_find_uas_alt_setting(intf); - if (alt < 0) - return alt; + if (!alt) + return -ENODEV; - return usb_set_interface(udev, - intf->altsetting[0].desc.bInterfaceNumber, alt); + return usb_set_interface(udev, alt->desc.bInterfaceNumber, + alt->desc.bAlternateSetting); } static int uas_configure_endpoints(struct uas_dev_info *devinfo) From 38b935b1ac1f725c56be27216f59b30283529c9f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 18 Oct 2017 12:49:38 -0400 Subject: [PATCH 312/508] USB: core: fix out-of-bounds access bug in usb_get_bos_descriptor() Andrey used the syzkaller fuzzer to find an out-of-bounds memory access in usb_get_bos_descriptor(). The code wasn't checking that the next usb_dev_cap_header structure could fit into the remaining buffer space. This patch fixes the error and also reduces the bNumDeviceCaps field in the header to match the actual number of capabilities found, in cases where there are fewer than expected. Change-Id: I4dcdbd4d5be97a01a6c3bf9020985c7979c04f29 Git-commit: 1c0edc3633b56000e18d82fc241e3995ca18a69e Git-repo: https://github.com/torvalds/linux Reported-by: Andrey Konovalov Signed-off-by: Alan Stern Tested-by: Andrey Konovalov CC: Signed-off-by: Greg Kroah-Hartman Signed-off-by: Srinivasa Rao Kuppala --- drivers/usb/core/config.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index b2a540b43f97c..1840089b4ffe0 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -829,10 +829,12 @@ int usb_get_bos_descriptor(struct usb_device *dev) for (i = 0; i < num; i++) { buffer += length; cap = (struct usb_dev_cap_header *)buffer; - length = cap->bLength; - if (total_len < length) + if (total_len < sizeof(*cap) || total_len < cap->bLength) { + dev->bos->desc->bNumDeviceCaps = i; break; + } + length = cap->bLength; total_len -= length; if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { From 115800aaa327ab986e6d26e33e187c3d3abf78d7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 19 Sep 2017 15:07:17 +0200 Subject: [PATCH 313/508] USB: fix out-of-bounds in usb_set_configuration Andrey Konovalov reported a possible out-of-bounds problem for a USB interface association descriptor. He writes: It seems there's no proper size check of a USB_DT_INTERFACE_ASSOCIATION descriptor. It's only checked that the size is >= 2 in usb_parse_configuration(), so find_iad() might do out-of-bounds access to intf_assoc->bInterfaceCount. And he's right, we don't check for crazy descriptors of this type very well, so resolve this problem. Yet another issue found by syzkaller... Change-Id: Ibe721523465bd15fc746bdfbf3e7aec908e688bb Git-commit: bd7a3fe770ebd8391d1c7d072ff88e9e76d063eb Git-repo: https://github.com/torvalds/linux/commit Reported-by: Andrey Konovalov Tested-by: Andrey Konovalov Cc: stable Signed-off-by: Greg Kroah-Hartman Signed-off-by: Srinivasa Rao Kuppala --- drivers/usb/core/config.c | 14 +++++++++++--- include/uapi/linux/usb/ch9.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index b2a540b43f97c..5fde47c472e03 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -520,15 +520,23 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx, } else if (header->bDescriptorType == USB_DT_INTERFACE_ASSOCIATION) { + struct usb_interface_assoc_descriptor *d; + + d = (struct usb_interface_assoc_descriptor *)header; + if (d->bLength < USB_DT_INTERFACE_ASSOCIATION_SIZE) { + dev_warn(ddev, + "config %d has an invalid interface association descriptor of length %d, skipping\n", + cfgno, d->bLength); + continue; + } + if (iad_num == USB_MAXIADS) { dev_warn(ddev, "found more Interface " "Association Descriptors " "than allocated for in " "configuration %d\n", cfgno); } else { - config->intf_assoc[iad_num] = - (struct usb_interface_assoc_descriptor - *)header; + config->intf_assoc[iad_num] = d; iad_num++; } diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h index aa33fd1b2d4f3..400196c45b3c1 100644 --- a/include/uapi/linux/usb/ch9.h +++ b/include/uapi/linux/usb/ch9.h @@ -705,6 +705,7 @@ struct usb_interface_assoc_descriptor { __u8 iFunction; } __attribute__ ((packed)); +#define USB_DT_INTERFACE_ASSOCIATION_SIZE 8 /*-------------------------------------------------------------------------*/ From d4cc5a446658b113ffbdb0c088877af4ac3182f6 Mon Sep 17 00:00:00 2001 From: Hardik Arya Date: Fri, 10 Nov 2017 16:29:16 +0530 Subject: [PATCH 314/508] diag: Fix possible use-after-free issue for mdlog session info Currently there is a possibility of accessing freed mdlog session info and it's attributes after closing the session. The patch adds protection while accessing mdlog session info for preventing use-after-free issue. CRs-Fixed: 2133028 Change-Id: Iba603bc2d75f84a604df2627e8fcb2a18acf4637 Signed-off-by: Hardik Arya --- drivers/char/diag/diag_masks.c | 270 ++++++++++++++++++++----- drivers/char/diag/diag_masks.h | 5 +- drivers/char/diag/diag_memorydevice.c | 15 +- drivers/char/diag/diag_usb.c | 4 +- drivers/char/diag/diagchar.h | 4 +- drivers/char/diag/diagchar_core.c | 167 ++++++++++----- drivers/char/diag/diagfwd.c | 75 ++++--- drivers/char/diag/diagfwd.h | 11 +- drivers/char/diag/diagfwd_peripheral.c | 5 +- 9 files changed, 407 insertions(+), 149 deletions(-) diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c index 7b2fa58147311..e8f5bceaaa411 100644 --- a/drivers/char/diag/diag_masks.c +++ b/drivers/char/diag/diag_masks.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -482,8 +482,7 @@ static void diag_send_feature_mask_update(uint8_t peripheral) } static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len, - unsigned char *dest_buf, int dest_len, - struct diag_md_session_t *info) + unsigned char *dest_buf, int dest_len, int pid) { int i; int write_len = 0; @@ -491,19 +490,30 @@ static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len, struct diag_msg_ssid_query_t rsp; struct diag_ssid_range_t ssid_range; struct diag_mask_info *mask_info = NULL; + struct diag_md_session_t *info = NULL; + mutex_lock(&driver->md_session_lock); + info = diag_md_session_get_pid(pid); mask_info = (!info) ? &msg_mask : info->msg_mask; if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 || !mask_info) { pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n", __func__, src_buf, src_len, dest_buf, dest_len, mask_info); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } + if (!mask_info->ptr) { + pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n", + __func__, mask_info->ptr); + mutex_unlock(&driver->md_session_lock); return -EINVAL; } - if (!diag_apps_responds()) + if (!diag_apps_responds()) { + mutex_unlock(&driver->md_session_lock); return 0; - + } mutex_lock(&driver->msg_mask_lock); rsp.cmd_code = DIAG_CMD_MSG_CONFIG; rsp.sub_cmd = DIAG_CMD_OP_GET_SSID_RANGE; @@ -525,13 +535,12 @@ static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len, write_len += sizeof(ssid_range); } mutex_unlock(&driver->msg_mask_lock); - + mutex_unlock(&driver->md_session_lock); return write_len; } static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len, - unsigned char *dest_buf, int dest_len, - struct diag_md_session_t *info) + unsigned char *dest_buf, int dest_len, int pid) { int i = 0; int write_len = 0; @@ -586,8 +595,7 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len, } static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len, - unsigned char *dest_buf, int dest_len, - struct diag_md_session_t *info) + unsigned char *dest_buf, int dest_len, int pid) { int i; int write_len = 0; @@ -596,6 +604,10 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len, struct diag_build_mask_req_t *req = NULL; struct diag_msg_build_mask_t rsp; struct diag_mask_info *mask_info = NULL; + struct diag_md_session_t *info = NULL; + + mutex_lock(&driver->md_session_lock); + info = diag_md_session_get_pid(pid); mask_info = (!info) ? &msg_mask : info->msg_mask; if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 || @@ -603,11 +615,19 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len, pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n", __func__, src_buf, src_len, dest_buf, dest_len, mask_info); + mutex_unlock(&driver->md_session_lock); return -EINVAL; } - - if (!diag_apps_responds()) + if (!mask_info->ptr) { + pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n", + __func__, mask_info->ptr); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } + if (!diag_apps_responds()) { + mutex_unlock(&driver->md_session_lock); return 0; + } mutex_lock(&driver->msg_mask_lock); req = (struct diag_build_mask_req_t *)src_buf; @@ -618,6 +638,13 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len, rsp.status = MSG_STATUS_FAIL; rsp.padding = 0; mask = (struct diag_msg_mask_t *)mask_info->ptr; + if (!mask->ptr) { + pr_err("diag: Invalid input in %s, mask->ptr: %pK\n", + __func__, mask->ptr); + mutex_unlock(&driver->msg_mask_lock); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { if ((req->ssid_first < mask->ssid_first) || (req->ssid_first > mask->ssid_last_tools)) { @@ -635,13 +662,12 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len, memcpy(dest_buf, &rsp, sizeof(rsp)); write_len += sizeof(rsp); mutex_unlock(&driver->msg_mask_lock); - + mutex_unlock(&driver->md_session_lock); return write_len; } static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len, - unsigned char *dest_buf, int dest_len, - struct diag_md_session_t *info) + unsigned char *dest_buf, int dest_len, int pid) { int i; int write_len = 0; @@ -655,6 +681,10 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len, struct diag_mask_info *mask_info = NULL; struct diag_msg_mask_t *mask_next = NULL; uint32_t *temp = NULL; + struct diag_md_session_t *info = NULL; + + mutex_lock(&driver->md_session_lock); + info = diag_md_session_get_pid(pid); mask_info = (!info) ? &msg_mask : info->msg_mask; if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 || @@ -662,6 +692,13 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len, pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n", __func__, src_buf, src_len, dest_buf, dest_len, mask_info); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } + if (!mask_info->ptr) { + pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n", + __func__, mask_info->ptr); + mutex_unlock(&driver->md_session_lock); return -EINVAL; } @@ -669,6 +706,14 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len, mutex_lock(&mask_info->lock); mutex_lock(&driver->msg_mask_lock); mask = (struct diag_msg_mask_t *)mask_info->ptr; + if (!mask->ptr) { + pr_err("diag: Invalid input in %s, mask->ptr: %pK\n", + __func__, mask->ptr); + mutex_unlock(&driver->msg_mask_lock); + mutex_unlock(&mask_info->lock); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { if (i < (driver->msg_mask_tbl_count - 1)) { mask_next = mask; @@ -709,6 +754,7 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len, mutex_unlock(&mask->lock); mutex_unlock(&driver->msg_mask_lock); mutex_unlock(&mask_info->lock); + mutex_unlock(&driver->md_session_lock); return -ENOMEM; } mask->ptr = temp; @@ -729,6 +775,7 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len, } mutex_unlock(&driver->msg_mask_lock); mutex_unlock(&mask_info->lock); + mutex_unlock(&driver->md_session_lock); if (diag_check_update(APPS_DATA)) diag_update_userspace_clients(MSG_MASKS_TYPE); @@ -760,8 +807,7 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len, } static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len, - unsigned char *dest_buf, int dest_len, - struct diag_md_session_t *info) + unsigned char *dest_buf, int dest_len, int pid) { int i; int write_len = 0; @@ -770,6 +816,10 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len, struct diag_msg_config_rsp_t *req = NULL; struct diag_msg_mask_t *mask = NULL; struct diag_mask_info *mask_info = NULL; + struct diag_md_session_t *info = NULL; + + mutex_lock(&driver->md_session_lock); + info = diag_md_session_get_pid(pid); mask_info = (!info) ? &msg_mask : info->msg_mask; if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 || @@ -777,6 +827,13 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len, pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n", __func__, src_buf, src_len, dest_buf, dest_len, mask_info); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } + if (!mask_info->ptr) { + pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n", + __func__, mask_info->ptr); + mutex_unlock(&driver->md_session_lock); return -EINVAL; } @@ -786,6 +843,14 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len, mutex_lock(&driver->msg_mask_lock); mask = (struct diag_msg_mask_t *)mask_info->ptr; + if (!mask->ptr) { + pr_err("diag: Invalid input in %s, mask->ptr: %pK\n", + __func__, mask->ptr); + mutex_unlock(&driver->msg_mask_lock); + mutex_unlock(&mask_info->lock); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } mask_info->status = (req->rt_mask) ? DIAG_CTRL_MASK_ALL_ENABLED : DIAG_CTRL_MASK_ALL_DISABLED; for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { @@ -796,7 +861,7 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len, } mutex_unlock(&driver->msg_mask_lock); mutex_unlock(&mask_info->lock); - + mutex_unlock(&driver->md_session_lock); if (diag_check_update(APPS_DATA)) diag_update_userspace_clients(MSG_MASKS_TYPE); @@ -822,8 +887,7 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len, } static int diag_cmd_get_event_mask(unsigned char *src_buf, int src_len, - unsigned char *dest_buf, int dest_len, - struct diag_md_session_t *info) + unsigned char *dest_buf, int dest_len, int pid) { int write_len = 0; uint32_t mask_size; @@ -858,8 +922,7 @@ static int diag_cmd_get_event_mask(unsigned char *src_buf, int src_len, } static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len, - unsigned char *dest_buf, int dest_len, - struct diag_md_session_t *info) + unsigned char *dest_buf, int dest_len, int pid) { int i; int write_len = 0; @@ -868,21 +931,31 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len, struct diag_event_mask_config_t rsp; struct diag_event_mask_config_t *req; struct diag_mask_info *mask_info = NULL; + struct diag_md_session_t *info = NULL; + mutex_lock(&driver->md_session_lock); + info = diag_md_session_get_pid(pid); mask_info = (!info) ? &event_mask : info->event_mask; if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 || !mask_info) { pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n", __func__, src_buf, src_len, dest_buf, dest_len, mask_info); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } + if (!mask_info->ptr) { + pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n", + __func__, mask_info->ptr); + mutex_unlock(&driver->md_session_lock); return -EINVAL; } - req = (struct diag_event_mask_config_t *)src_buf; mask_len = EVENT_COUNT_TO_BYTES(req->num_bits); if (mask_len <= 0 || mask_len > event_mask.mask_len) { pr_err("diag: In %s, invalid event mask len: %d\n", __func__, mask_len); + mutex_unlock(&driver->md_session_lock); return -EIO; } @@ -890,6 +963,7 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len, memcpy(mask_info->ptr, src_buf + header_len, mask_len); mask_info->status = DIAG_CTRL_MASK_VALID; mutex_unlock(&mask_info->lock); + mutex_unlock(&driver->md_session_lock); if (diag_check_update(APPS_DATA)) diag_update_userspace_clients(EVENT_MASKS_TYPE); @@ -916,21 +990,30 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len, } static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len, - unsigned char *dest_buf, int dest_len, - struct diag_md_session_t *info) + unsigned char *dest_buf, int dest_len, int pid) { int i; int write_len = 0; uint8_t toggle = 0; struct diag_event_report_t header; struct diag_mask_info *mask_info = NULL; + struct diag_md_session_t *info = NULL; + mutex_lock(&driver->md_session_lock); + info = diag_md_session_get_pid(pid); mask_info = (!info) ? &event_mask : info->event_mask; if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 || !mask_info) { pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n", __func__, src_buf, src_len, dest_buf, dest_len, mask_info); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } + if (!mask_info->ptr) { + pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n", + __func__, mask_info->ptr); + mutex_unlock(&driver->md_session_lock); return -EINVAL; } @@ -944,6 +1027,7 @@ static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len, memset(mask_info->ptr, 0, mask_info->mask_len); } mutex_unlock(&mask_info->lock); + mutex_unlock(&driver->md_session_lock); if (diag_check_update(APPS_DATA)) diag_update_userspace_clients(EVENT_MASKS_TYPE); @@ -965,8 +1049,7 @@ static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len, } static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len, - unsigned char *dest_buf, int dest_len, - struct diag_md_session_t *info) + unsigned char *dest_buf, int dest_len, int pid) { int i; int status = LOG_STATUS_INVALID; @@ -979,6 +1062,10 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len, struct diag_log_config_req_t *req; struct diag_log_config_rsp_t rsp; struct diag_mask_info *mask_info = NULL; + struct diag_md_session_t *info = NULL; + + mutex_lock(&driver->md_session_lock); + info = diag_md_session_get_pid(pid); mask_info = (!info) ? &log_mask : info->log_mask; if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 || @@ -986,11 +1073,20 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len, pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n", __func__, src_buf, src_len, dest_buf, dest_len, mask_info); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } + if (!mask_info->ptr) { + pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n", + __func__, mask_info->ptr); + mutex_unlock(&driver->md_session_lock); return -EINVAL; } - if (!diag_apps_responds()) + if (!diag_apps_responds()) { + mutex_unlock(&driver->md_session_lock); return 0; + } req = (struct diag_log_config_req_t *)src_buf; read_len += req_header_len; @@ -1007,6 +1103,12 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len, write_len += rsp_header_len; log_item = (struct diag_log_mask_t *)mask_info->ptr; + if (!log_item->ptr) { + pr_err("diag: Invalid input in %s, mask: %pK\n", + __func__, log_item); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } for (i = 0; i < MAX_EQUIP_ID; i++, log_item++) { if (log_item->equip_id != req->equip_id) continue; @@ -1046,28 +1148,27 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len, rsp.status = status; memcpy(dest_buf, &rsp, rsp_header_len); + mutex_unlock(&driver->md_session_lock); return write_len; } static int diag_cmd_get_log_range(unsigned char *src_buf, int src_len, - unsigned char *dest_buf, int dest_len, - struct diag_md_session_t *info) + unsigned char *dest_buf, int dest_len, int pid) { int i; int write_len = 0; struct diag_log_config_rsp_t rsp; - struct diag_mask_info *mask_info = NULL; struct diag_log_mask_t *mask = (struct diag_log_mask_t *)log_mask.ptr; + if (!mask) + return -EINVAL; + if (!diag_apps_responds()) return 0; - mask_info = (!info) ? &log_mask : info->log_mask; - if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 || - !mask_info) { - pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n", - __func__, src_buf, src_len, dest_buf, dest_len, - mask_info); + if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) { + pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d\n", + __func__, src_buf, src_len, dest_buf, dest_len); return -EINVAL; } @@ -1090,7 +1191,7 @@ static int diag_cmd_get_log_range(unsigned char *src_buf, int src_len, static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len, unsigned char *dest_buf, int dest_len, - struct diag_md_session_t *info) + int pid) { int i; int write_len = 0; @@ -1105,6 +1206,10 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len, struct diag_log_mask_t *mask = NULL; unsigned char *temp_buf = NULL; struct diag_mask_info *mask_info = NULL; + struct diag_md_session_t *info = NULL; + + mutex_lock(&driver->md_session_lock); + info = diag_md_session_get_pid(pid); mask_info = (!info) ? &log_mask : info->log_mask; if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 || @@ -1112,13 +1217,25 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len, pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n", __func__, src_buf, src_len, dest_buf, dest_len, mask_info); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } + if (!mask_info->ptr) { + pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n", + __func__, mask_info->ptr); + mutex_unlock(&driver->md_session_lock); return -EINVAL; } req = (struct diag_log_config_req_t *)src_buf; read_len += req_header_len; mask = (struct diag_log_mask_t *)mask_info->ptr; - + if (!mask->ptr) { + pr_err("diag: Invalid input in %s, mask->ptr: %pK\n", + __func__, mask->ptr); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } if (req->equip_id >= MAX_EQUIP_ID) { pr_err("diag: In %s, Invalid logging mask request, equip_id: %d\n", __func__, req->equip_id); @@ -1179,6 +1296,7 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len, break; } mutex_unlock(&mask_info->lock); + mutex_unlock(&driver->md_session_lock); if (diag_check_update(APPS_DATA)) diag_update_userspace_clients(LOG_MASKS_TYPE); @@ -1217,14 +1335,17 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len, } static int diag_cmd_disable_log_mask(unsigned char *src_buf, int src_len, - unsigned char *dest_buf, int dest_len, - struct diag_md_session_t *info) + unsigned char *dest_buf, int dest_len, int pid) { struct diag_mask_info *mask_info = NULL; struct diag_log_mask_t *mask = NULL; struct diag_log_config_rsp_t header; int write_len = 0; int i; + struct diag_md_session_t *info = NULL; + + mutex_lock(&driver->md_session_lock); + info = diag_md_session_get_pid(pid); mask_info = (!info) ? &log_mask : info->log_mask; if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 || @@ -1232,17 +1353,29 @@ static int diag_cmd_disable_log_mask(unsigned char *src_buf, int src_len, pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n", __func__, src_buf, src_len, dest_buf, dest_len, mask_info); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } + if (!mask_info->ptr) { + pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n", + __func__, mask_info->ptr); + mutex_unlock(&driver->md_session_lock); return -EINVAL; } - mask = (struct diag_log_mask_t *)mask_info->ptr; - + if (!mask->ptr) { + pr_err("diag: Invalid input in %s, mask->ptr: %pK\n", + __func__, mask->ptr); + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } for (i = 0; i < MAX_EQUIP_ID; i++, mask++) { mutex_lock(&mask->lock); memset(mask->ptr, 0, mask->range); mutex_unlock(&mask->lock); } mask_info->status = DIAG_CTRL_MASK_ALL_DISABLED; + mutex_unlock(&driver->md_session_lock); if (diag_check_update(APPS_DATA)) diag_update_userspace_clients(LOG_MASKS_TYPE); @@ -1500,7 +1633,7 @@ static int __diag_mask_init(struct diag_mask_info *mask_info, int mask_len, static void __diag_mask_exit(struct diag_mask_info *mask_info) { - if (!mask_info) + if (!mask_info || !mask_info->ptr) return; mutex_lock(&mask_info->lock); @@ -1557,11 +1690,17 @@ void diag_log_mask_free(struct diag_mask_info *mask_info) int i; struct diag_log_mask_t *mask = NULL; - if (!mask_info) + if (!mask_info || !mask_info->ptr) return; mutex_lock(&mask_info->lock); mask = (struct diag_log_mask_t *)mask_info->ptr; + if (!mask->ptr) { + pr_err("diag: Invalid input in %s, mask->ptr: %pK\n", + __func__, mask->ptr); + mutex_unlock(&mask_info->lock); + return; + } for (i = 0; i < MAX_EQUIP_ID; i++, mask++) { kfree(mask->ptr); mask->ptr = NULL; @@ -1636,11 +1775,18 @@ void diag_msg_mask_free(struct diag_mask_info *mask_info) int i; struct diag_msg_mask_t *mask = NULL; - if (!mask_info) + if (!mask_info || !mask_info->ptr) return; mutex_lock(&mask_info->lock); mutex_lock(&driver->msg_mask_lock); mask = (struct diag_msg_mask_t *)mask_info->ptr; + if (!mask->ptr) { + pr_err("diag: Invalid input in %s, mask->ptr: %pK\n", + __func__, mask->ptr); + mutex_unlock(&driver->msg_mask_lock); + mutex_unlock(&mask_info->lock); + return; + } for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { kfree(mask->ptr); mask->ptr = NULL; @@ -1807,6 +1953,11 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count, if (!mask_info) return -EIO; + if (!mask_info->ptr || !mask_info->update_buf) { + pr_err("diag: In %s, invalid input mask_info->ptr: %pK, mask_info->update_buf: %pK\n", + __func__, mask_info->ptr, mask_info->update_buf); + return -EINVAL; + } mutex_lock(&driver->diag_maskclear_mutex); if (driver->mask_clear) { DIAG_LOG(DIAG_DEBUG_PERIPHERALS, @@ -1819,6 +1970,13 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count, mutex_lock(&driver->msg_mask_lock); mask = (struct diag_msg_mask_t *)(mask_info->ptr); + if (!mask->ptr) { + pr_err("diag: Invalid input in %s, mask->ptr: %pK\n", + __func__, mask->ptr); + mutex_unlock(&driver->msg_mask_lock); + mutex_unlock(&mask_info->lock); + return -EINVAL; + } for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { ptr = mask_info->update_buf; len = 0; @@ -1879,8 +2037,20 @@ int diag_copy_to_user_log_mask(char __user *buf, size_t count, if (!mask_info) return -EIO; + if (!mask_info->ptr || !mask_info->update_buf) { + pr_err("diag: In %s, invalid input mask_info->ptr: %pK, mask_info->update_buf: %pK\n", + __func__, mask_info->ptr, mask_info->update_buf); + return -EINVAL; + } + mutex_lock(&mask_info->lock); mask = (struct diag_log_mask_t *)(mask_info->ptr); + if (!mask->ptr) { + pr_err("diag: Invalid input in %s, mask->ptr: %pK\n", + __func__, mask->ptr); + mutex_unlock(&mask_info->lock); + return -EINVAL; + } for (i = 0; i < MAX_EQUIP_ID; i++, mask++) { ptr = mask_info->update_buf; len = 0; @@ -1933,14 +2103,12 @@ void diag_send_updates_peripheral(uint8_t peripheral) &driver->buffering_mode[peripheral]); } -int diag_process_apps_masks(unsigned char *buf, int len, - struct diag_md_session_t *info) +int diag_process_apps_masks(unsigned char *buf, int len, int pid) { int size = 0; int sub_cmd = 0; int (*hdlr)(unsigned char *src_buf, int src_len, - unsigned char *dest_buf, int dest_len, - struct diag_md_session_t *info) = NULL; + unsigned char *dest_buf, int dest_len, int pid) = NULL; if (!buf || len <= 0) return -EINVAL; @@ -1990,7 +2158,7 @@ int diag_process_apps_masks(unsigned char *buf, int len, if (hdlr) size = hdlr(buf, len, driver->apps_rsp_buf, - DIAG_MAX_RSP_SIZE, info); + DIAG_MAX_RSP_SIZE, pid); return (size > 0) ? size : 0; } diff --git a/drivers/char/diag/diag_masks.h b/drivers/char/diag/diag_masks.h index 1a52f946bb09c..6edeee954d74b 100644 --- a/drivers/char/diag/diag_masks.h +++ b/drivers/char/diag/diag_masks.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -167,8 +167,7 @@ int diag_event_mask_copy(struct diag_mask_info *dest, void diag_log_mask_free(struct diag_mask_info *mask_info); void diag_msg_mask_free(struct diag_mask_info *mask_info); void diag_event_mask_free(struct diag_mask_info *mask_info); -int diag_process_apps_masks(unsigned char *buf, int len, - struct diag_md_session_t *info); +int diag_process_apps_masks(unsigned char *buf, int len, int pid); void diag_send_updates_peripheral(uint8_t peripheral); extern int diag_create_msg_mask_table_entry(struct diag_msg_mask_t *msg_mask, diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c index b4153c1961887..aebeba836825d 100644 --- a/drivers/char/diag/diag_memorydevice.c +++ b/drivers/char/diag/diag_memorydevice.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2014-2015, 2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2015, 2016, 2018 The Linux Foundation. + * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -130,7 +131,7 @@ void diag_md_close_all() int diag_md_write(int id, unsigned char *buf, int len, int ctx) { - int i; + int i, pid = 0; uint8_t found = 0; unsigned long flags; struct diag_md_info *ch = NULL; @@ -147,9 +148,14 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx) if (peripheral > NUM_PERIPHERALS) return -EINVAL; + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_peripheral(peripheral); - if (!session_info) + if (!session_info) { + mutex_unlock(&driver->md_session_lock); return -EIO; + } + pid = session_info->pid; + mutex_unlock(&driver->md_session_lock); ch = &diag_md[id]; @@ -187,8 +193,7 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx) found = 0; for (i = 0; i < driver->num_clients && !found; i++) { - if ((driver->client_map[i].pid != - session_info->pid) || + if ((driver->client_map[i].pid != pid) || (driver->client_map[i].pid == 0)) continue; diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c index 0a0fc4400de50..87d021f6a9564 100644 --- a/drivers/char/diag/diag_usb.c +++ b/drivers/char/diag/diag_usb.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2016, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -221,7 +221,7 @@ static void usb_disconnect(struct diag_usb_info *ch) if (!atomic_read(&ch->connected) && driver->usb_connected && diag_mask_param()) - diag_clear_masks(NULL); + diag_clear_masks(0); if (ch && ch->ops && ch->ops->close) ch->ops->close(ch->ctxt, DIAG_USB_MODE); diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h index a0534ebe71624..f265cc7f01b82 100644 --- a/drivers/char/diag/diagchar.h +++ b/drivers/char/diag/diagchar.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -630,7 +630,7 @@ void diag_cmd_remove_reg_by_pid(int pid); void diag_cmd_remove_reg_by_proc(int proc); int diag_cmd_chk_polling(struct diag_cmd_reg_entry_t *entry); int diag_mask_param(void); -void diag_clear_masks(struct diag_md_session_t *info); +void diag_clear_masks(int pid); void diag_record_stats(int type, int flag); diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index 39778311c2abc..b686f5b79f7d4 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -171,7 +171,7 @@ uint16_t diag_debug_mask; void *diag_ipc_log; #endif -static void diag_md_session_close(struct diag_md_session_t *session_info); +static void diag_md_session_close(int pid); /* * Returns the next delayed rsp id. If wrapping is enabled, @@ -210,6 +210,16 @@ do { \ ret += length; \ } while (0) +#define COPY_USER_SPACE_OR_ERR(buf, data, length) \ +do { \ + if ((count < ret+length) || (copy_to_user(buf, \ + (void *)&data, length))) { \ + ret = -EFAULT; \ + break; \ + } \ + ret += length; \ +} while (0) + static void drain_timer_func(unsigned long data) { queue_work(driver->diag_wq , &(driver->diag_drain_work)); @@ -248,12 +258,13 @@ void diag_drain_work_fn(struct work_struct *work) timer_in_progress = 0; mutex_lock(&apps_data_mutex); + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_peripheral(APPS_DATA); if (session_info) hdlc_disabled = session_info->hdlc_disabled; else hdlc_disabled = driver->hdlc_disabled; - + mutex_unlock(&driver->md_session_lock); if (!hdlc_disabled) diag_drain_apps_data(&hdlc_data); else @@ -400,7 +411,8 @@ int diag_mask_param(void) { return diag_mask_clear_param; } -void diag_clear_masks(struct diag_md_session_t *info) + +void diag_clear_masks(int pid) { int ret; char cmd_disable_log_mask[] = { 0x73, 0, 0, 0, 0, 0, 0, 0}; @@ -409,14 +421,14 @@ void diag_clear_masks(struct diag_md_session_t *info) DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "diag: %s: masks clear request upon %s\n", __func__, - ((info) ? "ODL exit" : "USB Disconnection")); + ((pid) ? "ODL exit" : "USB Disconnection")); ret = diag_process_apps_masks(cmd_disable_log_mask, - sizeof(cmd_disable_log_mask), info); + sizeof(cmd_disable_log_mask), pid); ret = diag_process_apps_masks(cmd_disable_msg_mask, - sizeof(cmd_disable_msg_mask), info); + sizeof(cmd_disable_msg_mask), pid); ret = diag_process_apps_masks(cmd_disable_event_mask, - sizeof(cmd_disable_event_mask), info); + sizeof(cmd_disable_event_mask), pid); DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "diag:%s: masks cleared successfully\n", __func__); } @@ -428,12 +440,17 @@ static void diag_close_logging_process(const int pid) struct diag_md_session_t *session_info = NULL; struct diag_logging_mode_param_t params; + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_pid(pid); - if (!session_info) + if (!session_info) { + mutex_unlock(&driver->md_session_lock); return; + } + session_peripheral_mask = session_info->peripheral_mask; + mutex_unlock(&driver->md_session_lock); if (diag_mask_clear_param) - diag_clear_masks(session_info); + diag_clear_masks(pid); mutex_lock(&driver->diag_maskclear_mutex); driver->mask_clear = 1; @@ -441,8 +458,6 @@ static void diag_close_logging_process(const int pid) mutex_lock(&driver->diagchar_mutex); session_peripheral_mask = session_info->peripheral_mask; - diag_md_session_close(session_info); - mutex_unlock(&driver->diagchar_mutex); for (i = 0; i < NUM_MD_SESSIONS; i++) if (MD_PERIPHERAL_MASK(i) & session_peripheral_mask) diag_mux_close_peripheral(DIAG_LOCAL_PROC, i); @@ -451,7 +466,10 @@ static void diag_close_logging_process(const int pid) params.mode_param = 0; params.peripheral_mask = diag_translate_kernel_to_user_mask(session_peripheral_mask); - mutex_lock(&driver->diagchar_mutex); + + mutex_lock(&driver->md_session_lock); + diag_md_session_close(pid); + mutex_unlock(&driver->md_session_lock); diag_switch_logging(¶ms); mutex_unlock(&driver->diagchar_mutex); } @@ -984,11 +1002,13 @@ static int diag_send_raw_data_remote(int proc, void *buf, int len, if (driver->hdlc_encode_buf_len != 0) return -EAGAIN; + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_peripheral(APPS_DATA); if (session_info) hdlc_disabled = session_info->hdlc_disabled; else hdlc_disabled = driver->hdlc_disabled; + mutex_unlock(&driver->md_session_lock); if (hdlc_disabled) { if (len < 4) { pr_err("diag: In %s, invalid len: %d of non_hdlc pkt", @@ -1353,15 +1373,16 @@ int diag_md_session_create(int mode, int peripheral_mask, int proc) return err; } -static void diag_md_session_close(struct diag_md_session_t *session_info) +static void diag_md_session_close(int pid) { int i; uint8_t found = 0; + struct diag_md_session_t *session_info = NULL; + session_info = diag_md_session_get_pid(pid); if (!session_info) return; - mutex_lock(&driver->md_session_lock); for (i = 0; i < NUM_MD_SESSIONS; i++) { if (driver->md_session_map[i] != session_info) continue; @@ -1387,7 +1408,6 @@ static void diag_md_session_close(struct diag_md_session_t *session_info) driver->md_session_mode = (found) ? DIAG_MD_PERIPHERAL : DIAG_MD_NONE; kfree(session_info); session_info = NULL; - mutex_unlock(&driver->md_session_lock); DIAG_LOG(DIAG_DEBUG_USERSPACE, "cleared up session\n"); } @@ -1395,6 +1415,8 @@ struct diag_md_session_t *diag_md_session_get_pid(int pid) { int i; + if (pid <= 0) + return NULL; for (i = 0; i < NUM_MD_SESSIONS; i++) { if (driver->md_session_map[i] && driver->md_session_map[i]->pid == pid) @@ -1410,10 +1432,12 @@ struct diag_md_session_t *diag_md_session_get_peripheral(uint8_t peripheral) return driver->md_session_map[peripheral]; } -static int diag_md_peripheral_switch(struct diag_md_session_t *session_info, +static int diag_md_peripheral_switch(int pid, int peripheral_mask, int req_mode) { int i, bit = 0; + struct diag_md_session_t *session_info = NULL; + session_info = diag_md_session_get_pid(pid); if (!session_info) return -EINVAL; if (req_mode != DIAG_USB_MODE || req_mode != DIAG_MEMORY_DEVICE_MODE) @@ -1423,25 +1447,20 @@ static int diag_md_peripheral_switch(struct diag_md_session_t *session_info, * check that md_session_map for i == session_info, * if not then race condition occurred and bail */ - mutex_lock(&driver->md_session_lock); for (i = 0; i < NUM_MD_SESSIONS; i++) { bit = MD_PERIPHERAL_MASK(i) & peripheral_mask; if (!bit) continue; if (req_mode == DIAG_USB_MODE) { - if (driver->md_session_map[i] != session_info) { - mutex_unlock(&driver->md_session_lock); + if (driver->md_session_map[i] != session_info) return -EINVAL; - } driver->md_session_map[i] = NULL; driver->md_session_mask &= ~bit; session_info->peripheral_mask &= ~bit; } else { - if (driver->md_session_map[i] != NULL) { - mutex_unlock(&driver->md_session_lock); + if (driver->md_session_map[i] != NULL) return -EINVAL; - } driver->md_session_map[i] = session_info; driver->md_session_mask |= bit; session_info->peripheral_mask |= bit; @@ -1450,7 +1469,6 @@ static int diag_md_peripheral_switch(struct diag_md_session_t *session_info, } driver->md_session_mode = DIAG_MD_PERIPHERAL; - mutex_unlock(&driver->md_session_lock); DIAG_LOG(DIAG_DEBUG_USERSPACE, "Changed Peripherals:0x%x to mode:%d\n", peripheral_mask, req_mode); } @@ -1459,7 +1477,7 @@ static int diag_md_session_check(int curr_mode, int req_mode, const struct diag_logging_mode_param_t *param, uint8_t *change_mode) { - int i, bit = 0, err = 0; + int i, bit = 0, err = 0, peripheral_mask = 0; int change_mask = 0; struct diag_md_session_t *session_info = NULL; @@ -1483,12 +1501,13 @@ static int diag_md_session_check(int curr_mode, int req_mode, if (req_mode == DIAG_USB_MODE) { if (curr_mode == DIAG_USB_MODE) return 0; + mutex_lock(&driver->md_session_lock); if (driver->md_session_mode == DIAG_MD_NONE && driver->md_session_mask == 0 && driver->logging_mask) { *change_mode = 1; + mutex_unlock(&driver->md_session_lock); return 0; } - /* * curr_mode is either DIAG_MULTI_MODE or DIAG_MD_MODE * Check if requested peripherals are already in usb mode @@ -1500,8 +1519,10 @@ static int diag_md_session_check(int curr_mode, int req_mode, if (bit & driver->logging_mask) change_mask |= bit; } - if (!change_mask) + if (!change_mask) { + mutex_unlock(&driver->md_session_lock); return 0; + } /* * Change is needed. Check if this md_session has set all the @@ -1513,23 +1534,26 @@ static int diag_md_session_check(int curr_mode, int req_mode, session_info = diag_md_session_get_pid(current->tgid); if (!session_info) { *change_mode = 1; + mutex_unlock(&driver->md_session_lock); return 0; } - if ((change_mask & session_info->peripheral_mask) + peripheral_mask = session_info->peripheral_mask; + if ((change_mask & peripheral_mask) != change_mask) { DIAG_LOG(DIAG_DEBUG_USERSPACE, "Another MD Session owns a requested peripheral\n"); + mutex_unlock(&driver->md_session_lock); return -EINVAL; } *change_mode = 1; /* If all peripherals are being set to USB Mode, call close */ - if (~change_mask & session_info->peripheral_mask) { - err = diag_md_peripheral_switch(session_info, + if (~change_mask & peripheral_mask) { + err = diag_md_peripheral_switch(current->tgid, change_mask, DIAG_USB_MODE); } else - diag_md_session_close(session_info); - + diag_md_session_close(current->tgid); + mutex_unlock(&driver->md_session_lock); return err; } else if (req_mode == DIAG_MEMORY_DEVICE_MODE) { @@ -1538,6 +1562,7 @@ static int diag_md_session_check(int curr_mode, int req_mode, * been set. Check that requested peripherals already set are * owned by this md session */ + mutex_lock(&driver->md_session_lock); change_mask = driver->md_session_mask & param->peripheral_mask; session_info = diag_md_session_get_pid(current->tgid); @@ -1546,11 +1571,14 @@ static int diag_md_session_check(int curr_mode, int req_mode, != change_mask) { DIAG_LOG(DIAG_DEBUG_USERSPACE, "Another MD Session owns a requested peripheral\n"); + mutex_unlock(&driver->md_session_lock); return -EINVAL; } - err = diag_md_peripheral_switch(session_info, + err = diag_md_peripheral_switch(current->tgid, change_mask, DIAG_USB_MODE); + mutex_unlock(&driver->md_session_lock); } else { + mutex_unlock(&driver->md_session_lock); if (change_mask) { DIAG_LOG(DIAG_DEBUG_USERSPACE, "Another MD Session owns a requested peripheral\n"); @@ -1928,17 +1956,17 @@ static int diag_ioctl_hdlc_toggle(unsigned long ioarg) uint8_t hdlc_support; struct diag_md_session_t *session_info = NULL; - session_info = diag_md_session_get_pid(current->tgid); if (copy_from_user(&hdlc_support, (void __user *)ioarg, sizeof(uint8_t))) return -EFAULT; mutex_lock(&driver->hdlc_disable_mutex); - if (session_info) { - mutex_lock(&driver->md_session_lock); + mutex_lock(&driver->md_session_lock); + session_info = diag_md_session_get_pid(current->tgid); + if (session_info) session_info->hdlc_disabled = hdlc_support; - mutex_unlock(&driver->md_session_lock); - } else + else driver->hdlc_disabled = hdlc_support; + mutex_unlock(&driver->md_session_lock); mutex_unlock(&driver->hdlc_disable_mutex); diag_update_md_clients(HDLC_SUPPORT_TYPE); @@ -2589,7 +2617,6 @@ static int diag_user_process_raw_data(const char __user *buf, int len) int remote_proc = 0; const int mempool = POOL_TYPE_COPY; unsigned char *user_space_data = NULL; - struct diag_md_session_t *info = NULL; if (!buf || len <= 0 || len > CALLBACK_BUF_SIZE) { pr_err_ratelimited("diag: In %s, invalid buf %pK len: %d\n", @@ -2640,8 +2667,8 @@ static int diag_user_process_raw_data(const char __user *buf, int len) } else { wait_event_interruptible(driver->wait_q, (driver->in_busy_pktdata == 0)); - info = diag_md_session_get_pid(current->tgid); - ret = diag_process_apps_pkt(user_space_data, len, info); + ret = diag_process_apps_pkt(user_space_data, len, + current->tgid); if (ret == 1) diag_send_error_rsp((void *)(user_space_data), len); } @@ -2707,24 +2734,27 @@ static int diag_user_process_userspace_data(const char __user *buf, int len) /* send masks to local processor now */ if (!remote_proc) { + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_pid(current->tgid); if (!session_info) { pr_err("diag:In %s request came from invalid md session pid:%d", __func__, current->tgid); + mutex_unlock(&driver->md_session_lock); return -EINVAL; } if (session_info) hdlc_disabled = session_info->hdlc_disabled; else hdlc_disabled = driver->hdlc_disabled; + mutex_unlock(&driver->md_session_lock); if (!hdlc_disabled) diag_process_hdlc_pkt((void *) (driver->user_space_data_buf), - len, session_info); + len, current->tgid); else diag_process_non_hdlc_pkt((char *) (driver->user_space_data_buf), - len, session_info); + len, current->tgid); return 0; } @@ -2801,11 +2831,13 @@ static int diag_user_process_apps_data(const char __user *buf, int len, mutex_lock(&apps_data_mutex); mutex_lock(&driver->hdlc_disable_mutex); + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_peripheral(APPS_DATA); if (session_info) hdlc_disabled = session_info->hdlc_disabled; else hdlc_disabled = driver->hdlc_disabled; + mutex_unlock(&driver->md_session_lock); if (hdlc_disabled) ret = diag_process_apps_data_non_hdlc(user_space_data, len, pkt_type); @@ -2880,9 +2912,11 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count, COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int)); /* place holder for number of data field */ ret += sizeof(int); + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_pid(current->tgid); exit_stat = diag_md_copy_to_user(buf, &ret, count, session_info); + mutex_unlock(&driver->md_session_lock); goto exit; } else if (driver->data_ready[index] & USER_SPACE_DATA_TYPE) { /* In case, the thread wakes up and the logging mode is @@ -2894,11 +2928,18 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count, data_type = driver->data_ready[index] & HDLC_SUPPORT_TYPE; driver->data_ready[index] ^= HDLC_SUPPORT_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int)); + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_pid(current->tgid); - if (session_info) - COPY_USER_SPACE_OR_EXIT(buf+4, + if (session_info) { + COPY_USER_SPACE_OR_ERR(buf+4, session_info->hdlc_disabled, sizeof(uint8_t)); + if (ret == -EFAULT) { + mutex_unlock(&driver->md_session_lock); + goto exit; + } + } + mutex_unlock(&driver->md_session_lock); goto exit; } @@ -2915,10 +2956,16 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count, if (driver->data_ready[index] & MSG_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & MSG_MASKS_TYPE; + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_peripheral(APPS_DATA); - COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int)); + COPY_USER_SPACE_OR_ERR(buf, data_type, sizeof(int)); + if (ret == -EFAULT) { + mutex_unlock(&driver->md_session_lock); + goto exit; + } write_len = diag_copy_to_user_msg_mask(buf + ret, count, session_info); + mutex_unlock(&driver->md_session_lock); if (write_len > 0) ret += write_len; driver->data_ready[index] ^= MSG_MASKS_TYPE; @@ -2928,18 +2975,32 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count, if (driver->data_ready[index] & EVENT_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & EVENT_MASKS_TYPE; + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_peripheral(APPS_DATA); - COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); + COPY_USER_SPACE_OR_ERR(buf, data_type, 4); + if (ret == -EFAULT) { + mutex_unlock(&driver->md_session_lock); + goto exit; + } if (session_info && session_info->event_mask && session_info->event_mask->ptr) { - COPY_USER_SPACE_OR_EXIT(buf + sizeof(int), + COPY_USER_SPACE_OR_ERR(buf + sizeof(int), *(session_info->event_mask->ptr), session_info->event_mask->mask_len); + if (ret == -EFAULT) { + mutex_unlock(&driver->md_session_lock); + goto exit; + } } else { - COPY_USER_SPACE_OR_EXIT(buf + sizeof(int), + COPY_USER_SPACE_OR_ERR(buf + sizeof(int), *(event_mask.ptr), event_mask.mask_len); + if (ret == -EFAULT) { + mutex_unlock(&driver->md_session_lock); + goto exit; + } } + mutex_unlock(&driver->md_session_lock); driver->data_ready[index] ^= EVENT_MASKS_TYPE; goto exit; } @@ -2947,10 +3008,16 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count, if (driver->data_ready[index] & LOG_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & LOG_MASKS_TYPE; + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_peripheral(APPS_DATA); - COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int)); + COPY_USER_SPACE_OR_ERR(buf, data_type, sizeof(int)); + if (ret == -EFAULT) { + mutex_unlock(&driver->md_session_lock); + goto exit; + } write_len = diag_copy_to_user_log_mask(buf + ret, count, session_info); + mutex_unlock(&driver->md_session_lock); if (write_len > 0) ret += write_len; driver->data_ready[index] ^= LOG_MASKS_TYPE; diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c index f255266159249..37f4c3c00282f 100644 --- a/drivers/char/diag/diagfwd.c +++ b/drivers/char/diag/diagfwd.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -281,8 +281,11 @@ static void pack_rsp_and_send(unsigned char *buf, int len) * draining responses when we are in Memory Device Mode. */ if (driver->logging_mode == DIAG_MEMORY_DEVICE_MODE || - driver->logging_mode == DIAG_MULTI_MODE) + driver->logging_mode == DIAG_MULTI_MODE) { + mutex_lock(&driver->md_session_lock); chk_logging_wakeup(); + mutex_unlock(&driver->md_session_lock); + } } if (driver->rsp_buf_busy) { pr_err("diag: unable to get hold of response buffer\n"); @@ -350,8 +353,11 @@ static void encode_rsp_and_send(unsigned char *buf, int len) * draining responses when we are in Memory Device Mode. */ if (driver->logging_mode == DIAG_MEMORY_DEVICE_MODE || - driver->logging_mode == DIAG_MULTI_MODE) + driver->logging_mode == DIAG_MULTI_MODE) { + mutex_lock(&driver->md_session_lock); chk_logging_wakeup(); + mutex_unlock(&driver->md_session_lock); + } } if (driver->rsp_buf_busy) { @@ -387,12 +393,13 @@ void diag_send_rsp(unsigned char *buf, int len) struct diag_md_session_t *session_info = NULL; uint8_t hdlc_disabled; + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_peripheral(APPS_DATA); if (session_info) hdlc_disabled = session_info->hdlc_disabled; else hdlc_disabled = driver->hdlc_disabled; - + mutex_unlock(&driver->md_session_lock); if (hdlc_disabled) pack_rsp_and_send(buf, len); else @@ -460,6 +467,7 @@ void diag_update_md_clients(unsigned int type) int i, j; mutex_lock(&driver->diagchar_mutex); + mutex_lock(&driver->md_session_lock); for (i = 0; i < NUM_MD_SESSIONS; i++) { if (driver->md_session_map[i] != NULL) for (j = 0; j < driver->num_clients; j++) { @@ -471,6 +479,7 @@ void diag_update_md_clients(unsigned int type) } } } + mutex_unlock(&driver->md_session_lock); wake_up_interruptible(&driver->wait_q); mutex_unlock(&driver->diagchar_mutex); } @@ -871,22 +880,22 @@ void diag_send_error_rsp(unsigned char *buf, int len) diag_send_rsp(driver->apps_rsp_buf, len + 1); } -int diag_process_apps_pkt(unsigned char *buf, int len, - struct diag_md_session_t *info) +int diag_process_apps_pkt(unsigned char *buf, int len, int pid) { - int i; + int i, p_mask = 0; int mask_ret; int write_len = 0; unsigned char *temp = NULL; struct diag_cmd_reg_entry_t entry; struct diag_cmd_reg_entry_t *temp_entry = NULL; struct diag_cmd_reg_t *reg_item = NULL; + struct diag_md_session_t *info = NULL; if (!buf) return -EIO; /* Check if the command is a supported mask command */ - mask_ret = diag_process_apps_masks(buf, len, info); + mask_ret = diag_process_apps_masks(buf, len, pid); if (mask_ret > 0) { diag_send_rsp(driver->apps_rsp_buf, mask_ret); return 0; @@ -919,11 +928,15 @@ int diag_process_apps_pkt(unsigned char *buf, int len, if (temp_entry) { reg_item = container_of(temp_entry, struct diag_cmd_reg_t, entry); + mutex_lock(&driver->md_session_lock); + info = diag_md_session_get_pid(pid); if (info) { - if (MD_PERIPHERAL_MASK(reg_item->proc) & - info->peripheral_mask) + p_mask = info->peripheral_mask; + mutex_unlock(&driver->md_session_lock); + if (MD_PERIPHERAL_MASK(reg_item->proc) & p_mask) write_len = diag_send_data(reg_item, buf, len); } else { + mutex_unlock(&driver->md_session_lock); if (MD_PERIPHERAL_MASK(reg_item->proc) & driver->logging_mask) diag_send_error_rsp(buf, len); @@ -1088,10 +1101,13 @@ int diag_process_apps_pkt(unsigned char *buf, int len, */ pr_debug("diag: In %s, disabling HDLC encoding\n", __func__); + mutex_lock(&driver->md_session_lock); + info = diag_md_session_get_pid(pid); if (info) info->hdlc_disabled = 1; else driver->hdlc_disabled = 1; + mutex_unlock(&driver->md_session_lock); diag_update_md_clients(HDLC_SUPPORT_TYPE); mutex_unlock(&driver->hdlc_disable_mutex); return 0; @@ -1105,8 +1121,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len, return 0; } -void diag_process_hdlc_pkt(void *data, unsigned len, - struct diag_md_session_t *info) +void diag_process_hdlc_pkt(void *data, unsigned len, int pid) { int err = 0; int ret = 0; @@ -1166,7 +1181,7 @@ void diag_process_hdlc_pkt(void *data, unsigned len, } err = diag_process_apps_pkt(driver->hdlc_buf, - driver->hdlc_buf_len, info); + driver->hdlc_buf_len, pid); if (err < 0) goto fail; } else { @@ -1280,9 +1295,12 @@ static int diagfwd_mux_close(int id, int mode) static uint8_t hdlc_reset; -static void hdlc_reset_timer_start(struct diag_md_session_t *info) +static void hdlc_reset_timer_start(int pid) { + struct diag_md_session_t *info = NULL; + mutex_lock(&driver->md_session_lock); + info = diag_md_session_get_pid(pid); if (!hdlc_timer_in_progress) { hdlc_timer_in_progress = 1; if (info) @@ -1324,15 +1342,16 @@ void diag_md_hdlc_reset_timer_func(unsigned long pid) } static void diag_hdlc_start_recovery(unsigned char *buf, int len, - struct diag_md_session_t *info) + int pid) { int i; static uint32_t bad_byte_counter; unsigned char *start_ptr = NULL; struct diag_pkt_frame_t *actual_pkt = NULL; + struct diag_md_session_t *info = NULL; hdlc_reset = 1; - hdlc_reset_timer_start(info); + hdlc_reset_timer_start(pid); actual_pkt = (struct diag_pkt_frame_t *)buf; for (i = 0; i < len; i++) { @@ -1351,10 +1370,13 @@ static void diag_hdlc_start_recovery(unsigned char *buf, int len, pr_err("diag: In %s, re-enabling HDLC encoding\n", __func__); mutex_lock(&driver->hdlc_disable_mutex); + mutex_lock(&driver->md_session_lock); + info = diag_md_session_get_pid(pid); if (info) info->hdlc_disabled = 0; else driver->hdlc_disabled = 0; + mutex_unlock(&driver->md_session_lock); mutex_unlock(&driver->hdlc_disable_mutex); diag_update_md_clients(HDLC_SUPPORT_TYPE); @@ -1367,12 +1389,11 @@ static void diag_hdlc_start_recovery(unsigned char *buf, int len, mutex_lock(&driver->hdlc_recovery_mutex); driver->incoming_pkt.processing = 0; mutex_unlock(&driver->hdlc_recovery_mutex); - diag_process_non_hdlc_pkt(start_ptr, len - i, info); + diag_process_non_hdlc_pkt(start_ptr, len - i, pid); } } -void diag_process_non_hdlc_pkt(unsigned char *buf, int len, - struct diag_md_session_t *info) +void diag_process_non_hdlc_pkt(unsigned char *buf, int len, int pid) { int err = 0; uint16_t pkt_len = 0; @@ -1428,11 +1449,11 @@ void diag_process_non_hdlc_pkt(unsigned char *buf, int len, if (*(uint8_t *)(data_ptr + actual_pkt->length) != CONTROL_CHAR) { mutex_unlock(&driver->hdlc_recovery_mutex); - diag_hdlc_start_recovery(buf, len, info); + diag_hdlc_start_recovery(buf, len, pid); mutex_lock(&driver->hdlc_recovery_mutex); } err = diag_process_apps_pkt(data_ptr, - actual_pkt->length, info); + actual_pkt->length, pid); if (err) { pr_err("diag: In %s, unable to process incoming data packet, err: %d\n", __func__, err); @@ -1454,7 +1475,7 @@ void diag_process_non_hdlc_pkt(unsigned char *buf, int len, pkt_len = actual_pkt->length; if (actual_pkt->start != CONTROL_CHAR) { - diag_hdlc_start_recovery(buf, len, info); + diag_hdlc_start_recovery(buf, len, pid); diag_send_error_rsp(buf, len); goto end; } @@ -1463,7 +1484,7 @@ void diag_process_non_hdlc_pkt(unsigned char *buf, int len, pr_err("diag: In %s, incoming data is too large for the request buffer %d\n", __func__, pkt_len); mutex_unlock(&driver->hdlc_recovery_mutex); - diag_hdlc_start_recovery(buf, len, info); + diag_hdlc_start_recovery(buf, len, pid); break; } if ((pkt_len + header_len) > (len - read_bytes)) { @@ -1480,13 +1501,13 @@ void diag_process_non_hdlc_pkt(unsigned char *buf, int len, if (*(uint8_t *)(data_ptr + actual_pkt->length) != CONTROL_CHAR) { mutex_unlock(&driver->hdlc_recovery_mutex); - diag_hdlc_start_recovery(buf, len, info); + diag_hdlc_start_recovery(buf, len, pid); mutex_lock(&driver->hdlc_recovery_mutex); } else hdlc_reset = 0; err = diag_process_apps_pkt(data_ptr, - actual_pkt->length, info); + actual_pkt->length, pid); if (err) { mutex_unlock(&driver->hdlc_recovery_mutex); break; @@ -1505,9 +1526,9 @@ static int diagfwd_mux_read_done(unsigned char *buf, int len, int ctxt) return -EINVAL; if (!driver->hdlc_disabled) - diag_process_hdlc_pkt(buf, len, NULL); + diag_process_hdlc_pkt(buf, len, 0); else - diag_process_non_hdlc_pkt(buf, len, NULL); + diag_process_non_hdlc_pkt(buf, len, 0); diag_mux_queue_read(ctxt); return 0; diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h index 0023e0638aa2e..0f98df19cdd27 100644 --- a/drivers/char/diag/diagfwd.h +++ b/drivers/char/diag/diagfwd.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2015, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -28,10 +28,8 @@ int diagfwd_init(void); void diagfwd_exit(void); -void diag_process_hdlc_pkt(void *data, unsigned len, - struct diag_md_session_t *info); -void diag_process_non_hdlc_pkt(unsigned char *data, int len, - struct diag_md_session_t *info); +void diag_process_hdlc_pkt(void *data, unsigned int len, int pid); +void diag_process_non_hdlc_pkt(unsigned char *data, int len, int pid); int chk_config_get_id(void); int chk_apps_only(void); int chk_apps_master(void); @@ -43,8 +41,7 @@ int diag_cmd_get_mobile_id(unsigned char *src_buf, int src_len, int diag_check_common_cmd(struct diag_pkt_header_t *header); void diag_update_userspace_clients(unsigned int type); void diag_update_sleeping_process(int process_id, int data_type); -int diag_process_apps_pkt(unsigned char *buf, int len, - struct diag_md_session_t *info); +int diag_process_apps_pkt(unsigned char *buf, int len, int pid); void diag_send_error_rsp(unsigned char *buf, int len); void diag_update_pkt_buffer(unsigned char *buf, uint32_t len, int type); int diag_process_stm_cmd(unsigned char *buf, unsigned char *dest_buf); diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c index 36f2857545e9b..856e00f05fd19 100644 --- a/drivers/char/diag/diagfwd_peripheral.c +++ b/drivers/char/diag/diagfwd_peripheral.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -240,12 +240,13 @@ static void diagfwd_data_read_done(struct diagfwd_info *fwd_info, mutex_lock(&driver->hdlc_disable_mutex); mutex_lock(&fwd_info->data_mutex); + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_peripheral(fwd_info->peripheral); if (session_info) hdlc_disabled = session_info->hdlc_disabled; else hdlc_disabled = driver->hdlc_disabled; - + mutex_unlock(&driver->md_session_lock); if (!driver->feature[fwd_info->peripheral].encode_hdlc) { if (fwd_info->buf_1 && fwd_info->buf_1->data == buf) { temp_buf = fwd_info->buf_1; From 9641228e3500f4d3736e8412500ed93727e3c3b0 Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Wed, 4 Apr 2018 14:12:55 +0530 Subject: [PATCH 315/508] wlan: Add size to nvtable hwCalValues Add size of uint16 to the validation after subtracting the calData size instead of before to resolve compilation issue. Change-Id: I4c4fa7ce6fb1fc805281df17ed47f75cfaf39272 CRs-Fixed: 2197382 --- CORE/VOSS/src/wlan_nv_template_builtin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CORE/VOSS/src/wlan_nv_template_builtin.c b/CORE/VOSS/src/wlan_nv_template_builtin.c index 14c6eadf52429..8d23e6852e80f 100644 --- a/CORE/VOSS/src/wlan_nv_template_builtin.c +++ b/CORE/VOSS/src/wlan_nv_template_builtin.c @@ -587,8 +587,8 @@ _NV_TEMPLATE_TABLE NvTablesBuiltIn[/*TABLES_MAX*/][TABLE_ENTRIES_MAX] = { ((char *)&(nvDefaults.tables.hwCalValues.calData.psSlpTimeOvrHdxLNA5G) - (char *)&nvDefaults.tables.hwCalValues.calData),"psSlpTimeOvrHdxLNA5G"}, {"ed",_ID_U8,SINGULAR,0,0,0, - (((char *)&(nvDefaults.tables.hwCalValues.calData.psSlpTimeOvrHdxLNA5G) + - sizeof(uint16)) - (char *)&nvDefaults.tables.hwCalValues.calData), + ((char *)&(nvDefaults.tables.hwCalValues.calData.psSlpTimeOvrHdxLNA5G) - + (char *)&nvDefaults.tables.hwCalValues.calData) + sizeof(uint16), "nv_TxBBFSel9MHz"}, {"ee",_ID_U8,SINGULAR,0,0,0, ((char *)&(nvDefaults.tables.hwCalValues.calData.hwParam2) - From c99fbefe4dae68b05bff29576334921a9f5f91d3 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Wed, 11 Apr 2018 12:23:32 +0530 Subject: [PATCH 316/508] wlan: Compilation error for kernel version earlier than 3.18 There is a compilation error in api wlan_hdd_send_avoid_freq_event, when cfg80211_vendor_event_alloc is used for kernel version earlier than 3.18 To address this add a kernel version check in api cfg80211_vendor_event_alloc call. Change-Id: I8bc96f1988bc2d790d5ada4b3158cf4594f547e6 CRs-Fixed: 2222400 --- CORE/HDD/src/wlan_hdd_cfg80211.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index e92b5b7dc75ba..74ce9f5b4aa86 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -12812,7 +12812,11 @@ VOS_STATUS wlan_hdd_send_sta_authorized_event( vendor_event = cfg80211_vendor_event_alloc( - hdd_ctx->wiphy, &adapter->wdev, sizeof(sta_flags) + + hdd_ctx->wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) + &adapter->wdev, +#endif + sizeof(sta_flags) + VOS_MAC_ADDR_SIZE + NLMSG_HDRLEN, QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX, GFP_KERNEL); From 2350901bcac3590b0264e3080ae907fdf9d98af3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 22 Sep 2017 16:18:53 +0200 Subject: [PATCH 317/508] ALSA: usb-audio: Check out-of-bounds access by corrupted buffer descriptor When a USB-audio device receives a maliciously adjusted or corrupted buffer descriptor, the USB-audio driver may access an out-of-bounce value at its parser. This was detected by syzkaller, something like: BUG: KASAN: slab-out-of-bounds in usb_audio_probe+0x27b2/0x2ab0 Read of size 1 at addr ffff88006b83a9e8 by task kworker/0:1/24 CPU: 0 PID: 24 Comm: kworker/0:1 Not tainted 4.14.0-rc1-42251-gebb2c2437d80 #224 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Workqueue: usb_hub_wq hub_event Call Trace: __dump_stack lib/dump_stack.c:16 dump_stack+0x292/0x395 lib/dump_stack.c:52 print_address_description+0x78/0x280 mm/kasan/report.c:252 kasan_report_error mm/kasan/report.c:351 kasan_report+0x22f/0x340 mm/kasan/report.c:409 __asan_report_load1_noabort+0x19/0x20 mm/kasan/report.c:427 snd_usb_create_streams sound/usb/card.c:248 usb_audio_probe+0x27b2/0x2ab0 sound/usb/card.c:605 usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361 really_probe drivers/base/dd.c:413 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 device_add+0xd0b/0x1660 drivers/base/core.c:1835 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266 really_probe drivers/base/dd.c:413 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 device_add+0xd0b/0x1660 drivers/base/core.c:1835 usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457 hub_port_connect drivers/usb/core/hub.c:4903 hub_port_connect_change drivers/usb/core/hub.c:5009 port_event drivers/usb/core/hub.c:5115 hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195 process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119 worker_thread+0x221/0x1850 kernel/workqueue.c:2253 kthread+0x3a1/0x470 kernel/kthread.c:231 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431 This patch adds the checks of out-of-bounce accesses at appropriate places and bails out when it goes out of the given buffer. Change-Id: Ib6aecf7269c30fdb60c70f5bef3ef45ffb4e9577 Git-commit: bfc81a8bc18e3c4ba0cbaa7666ff76be2f998991 Git-repo: https://github.com/torvalds/linux Reported-by: Andrey Konovalov Tested-by: Andrey Konovalov Cc: Signed-off-by: Takashi Iwai Signed-off-by: Srinivasa Rao Kuppala Signed-off-by: Ajay Agarwal --- sound/usb/card.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sound/usb/card.c b/sound/usb/card.c index e2f744b6d5f7c..aca102fd29924 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -221,6 +221,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) struct usb_interface *usb_iface; void *control_header; int i, protocol; + int rest_bytes; usb_iface = usb_ifnum_to_if(dev, ctrlif); if (!usb_iface) { @@ -247,6 +248,15 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) return -EINVAL; } + rest_bytes = (void *)(host_iface->extra + host_iface->extralen) - + control_header; + + /* just to be sure -- this shouldn't hit at all */ + if (rest_bytes <= 0) { + dev_err(&dev->dev, "invalid control header\n"); + return -EINVAL; + } + switch (protocol) { default: dev_warn(&dev->dev, @@ -257,11 +267,21 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) case UAC_VERSION_1: { struct uac1_ac_header_descriptor *h1 = control_header; + if (rest_bytes < sizeof(*h1)) { + dev_err(&dev->dev, "too short v1 buffer descriptor\n"); + return -EINVAL; + } + if (!h1->bInCollection) { dev_info(&dev->dev, "skipping empty audio interface (v1)\n"); return -EINVAL; } + if (rest_bytes < h1->bLength) { + dev_err(&dev->dev, "invalid buffer length (v1)\n"); + return -EINVAL; + } + if (h1->bLength < sizeof(*h1) + h1->bInCollection) { dev_err(&dev->dev, "invalid UAC_HEADER (v1)\n"); return -EINVAL; From 6dfc672c9f4da003b3bf427281b6fe1c028dcbdf Mon Sep 17 00:00:00 2001 From: Jaejoong Kim Date: Thu, 28 Sep 2017 19:16:30 +0900 Subject: [PATCH 318/508] HID: usbhid: fix out-of-bounds bug The hid descriptor identifies the length and type of subordinate descriptors for a device. If the received hid descriptor is smaller than the size of the struct hid_descriptor, it is possible to cause out-of-bounds. In addition, if bNumDescriptors of the hid descriptor have an incorrect value, this can also cause out-of-bounds while approaching hdesc->desc[n]. So check the size of hid descriptor and bNumDescriptors. BUG: KASAN: slab-out-of-bounds in usbhid_parse+0x9b1/0xa20 Read of size 1 at addr ffff88006c5f8edf by task kworker/1:2/1261 CPU: 1 PID: 1261 Comm: kworker/1:2 Not tainted 4.14.0-rc1-42251-gebb2c2437d80 #169 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Workqueue: usb_hub_wq hub_event Call Trace: __dump_stack lib/dump_stack.c:16 dump_stack+0x292/0x395 lib/dump_stack.c:52 print_address_description+0x78/0x280 mm/kasan/report.c:252 kasan_report_error mm/kasan/report.c:351 kasan_report+0x22f/0x340 mm/kasan/report.c:409 __asan_report_load1_noabort+0x19/0x20 mm/kasan/report.c:427 usbhid_parse+0x9b1/0xa20 drivers/hid/usbhid/hid-core.c:1004 hid_add_device+0x16b/0xb30 drivers/hid/hid-core.c:2944 usbhid_probe+0xc28/0x1100 drivers/hid/usbhid/hid-core.c:1369 usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361 really_probe drivers/base/dd.c:413 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 device_add+0xd0b/0x1660 drivers/base/core.c:1835 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266 really_probe drivers/base/dd.c:413 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 device_add+0xd0b/0x1660 drivers/base/core.c:1835 usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457 hub_port_connect drivers/usb/core/hub.c:4903 hub_port_connect_change drivers/usb/core/hub.c:5009 port_event drivers/usb/core/hub.c:5115 hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195 process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119 worker_thread+0x221/0x1850 kernel/workqueue.c:2253 kthread+0x3a1/0x470 kernel/kthread.c:231 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431 Change-Id: I9aa1b3f07a27d78a8e0246c51e9464349b2511cc Git-commit: f043bfc98c193c284e2cd768fefabe18ac2fed9b Git-repo: https://github.com/torvalds/linux Cc: stable@vger.kernel.org Reported-by: Andrey Konovalov Signed-off-by: Jaejoong Kim Tested-by: Andrey Konovalov Acked-by: Alan Stern Signed-off-by: Jiri Kosina Signed-off-by: Srinivasa Rao Kuppala --- drivers/hid/usbhid/hid-core.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index d3fd973e8776e..c96fbb8c80469 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -959,6 +959,8 @@ static int usbhid_parse(struct hid_device *hid) unsigned int rsize = 0; char *rdesc; int ret, n; + int num_descriptors; + size_t offset = offsetof(struct hid_descriptor, desc); quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct)); @@ -981,10 +983,18 @@ static int usbhid_parse(struct hid_device *hid) return -ENODEV; } + if (hdesc->bLength < sizeof(struct hid_descriptor)) { + dbg_hid("hid descriptor is too short\n"); + return -EINVAL; + } + hid->version = le16_to_cpu(hdesc->bcdHID); hid->country = hdesc->bCountryCode; - for (n = 0; n < hdesc->bNumDescriptors; n++) + num_descriptors = min_t(int, hdesc->bNumDescriptors, + (hdesc->bLength - offset) / sizeof(struct hid_class_descriptor)); + + for (n = 0; n < num_descriptors; n++) if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); From 56bb37aa703152aa25128ebb37a942836f1a4904 Mon Sep 17 00:00:00 2001 From: Sravan Kumar Kairam Date: Fri, 29 Dec 2017 17:15:19 +0530 Subject: [PATCH 319/508] wlan: Add ini to toggle PN replay check Add ini configuration item to enable or disable HOST PN replay check for unicast packets. Change-Id: Icb3be010bac587e9d1d542ec2a3221acccc7069f CRs-Fixed: 2223327 --- CORE/HDD/inc/wlan_hdd_cfg.h | 6 ++++++ CORE/HDD/src/wlan_hdd_cfg.c | 7 +++++++ CORE/TL/inc/wlan_qct_tl.h | 4 ++++ CORE/TL/src/wlan_qct_tl.c | 7 ++++++- CORE/VOSS/src/vos_api.c | 1 + 5 files changed, 24 insertions(+), 1 deletion(-) diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index 049df4e84d4b1..aeb035a9d406f 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -1190,6 +1190,11 @@ typedef enum #define CFG_REORDER_TIME_VO_MAX 1000 #define CFG_REORDER_TIME_VO_DEFAULT 40 +#define CFG_ENABLE_PN_REPLAY_NAME "PNreplayCheck" +#define CFG_ENABLE_PN_REPLAY_MIN 0 +#define CFG_ENABLE_PN_REPLAY_MAX 1 +#define CFG_ENABLE_PN_REPLAY_DEFAULT 0 + #if defined WLAN_FEATURE_VOWIFI #define CFG_RRM_ENABLE_NAME "gRrmEnable" #define CFG_RRM_ENABLE_MIN (0) @@ -3456,6 +3461,7 @@ typedef struct v_U16_t BeReorderAgingTime; v_U16_t ViReorderAgingTime; v_U16_t VoReorderAgingTime; + v_BOOL_t enablePNReplay; /* Wowl pattern */ char wowlPattern[1024]; diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index 0292ba099e5b5..e03363d614b11 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -1375,6 +1375,13 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_REORDER_TIME_VO_MIN, CFG_REORDER_TIME_VO_MAX ), + REG_VARIABLE( CFG_ENABLE_PN_REPLAY_NAME , WLAN_PARAM_Integer, + hdd_config_t, enablePNReplay, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_PN_REPLAY_DEFAULT, + CFG_ENABLE_PN_REPLAY_MIN, + CFG_ENABLE_PN_REPLAY_MAX ), + REG_VARIABLE_STRING( CFG_WOWL_PATTERN_NAME, WLAN_PARAM_String, hdd_config_t, wowlPattern, VAR_FLAGS_OPTIONAL, diff --git a/CORE/TL/inc/wlan_qct_tl.h b/CORE/TL/inc/wlan_qct_tl.h index 5a0db0185fc2a..7f0456d89796a 100644 --- a/CORE/TL/inc/wlan_qct_tl.h +++ b/CORE/TL/inc/wlan_qct_tl.h @@ -328,6 +328,10 @@ typedef struct /* Min Threshold for Processing Frames in TL */ v_U8_t uMinFramesProcThres; + /* 1 means replay check enable + 0 means replay check disable */ + v_BOOL_t ucIsReplayCheck; + /* Re-order Aging Time */ v_U16_t ucReorderAgingTime[WLANTL_MAX_AC]; }WLANTL_ConfigInfoType; diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c index 57ddaa9356173..372a6f7b91903 100644 --- a/CORE/TL/src/wlan_qct_tl.c +++ b/CORE/TL/src/wlan_qct_tl.c @@ -722,6 +722,9 @@ WLANTL_Open pTLCb->tlConfigInfo.uDelayedTriggerFrmInt = pTLConfig->uDelayedTriggerFrmInt; + pTLCb->tlConfigInfo.ucIsReplayCheck = + pTLConfig->ucIsReplayCheck; + /*------------------------------------------------------------------------ Allocate internal resources ------------------------------------------------------------------------*/ @@ -1523,7 +1526,9 @@ WLANTL_RegisterSTAClient vos_copy_macaddr( &pClientSTA->wSTADesc.vSelfMACAddress, &pwSTADescType->vSelfMACAddress); /* In volans release L replay check is done at TL */ - pClientSTA->ucIsReplayCheckValid = pwSTADescType->ucIsReplayCheckValid; + if (pTLCb->tlConfigInfo.ucIsReplayCheck) + pClientSTA->ucIsReplayCheckValid = pwSTADescType->ucIsReplayCheckValid; + pClientSTA->ulTotalReplayPacketsDetected = 0; /*Clear replay counters of the STA on all TIDs*/ for(ucTid = 0; ucTid < WLANTL_MAX_TID ; ucTid++) diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c index 36621232cce5f..ca67c919309ca 100644 --- a/CORE/VOSS/src/vos_api.c +++ b/CORE/VOSS/src/vos_api.c @@ -2671,6 +2671,7 @@ vos_fetch_tl_cfg_parms pTLConfig->ucReorderAgingTime[3] = pConfig->VoReorderAgingTime;/*WLANTL_AC_VO*/ pTLConfig->uDelayedTriggerFrmInt = pConfig->DelayedTriggerFrmInt; pTLConfig->uMinFramesProcThres = pConfig->MinFramesProcThres; + pTLConfig->ucIsReplayCheck = pConfig->enablePNReplay; } From 9e9b6cc819457122699ead9a1ef07080f4e19b5c Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Thu, 12 Apr 2018 19:59:17 +0530 Subject: [PATCH 320/508] wlan: HAL interface for ini for different timesharing for WLAN/BT In the case of WLAN/BT sharing while connected with a 2M headset the throughput drops very low. Add ini params which when set to custom values will use different timesharing for WLAN/BT when A2DP is going on with a 2M headset. Change-Id: I096a27073d10f17714ea8bdf613e1ff9f2f572b1 CRs-Fixed: 2224867 --- riva/inc/wlan_hal_cfg.h | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/riva/inc/wlan_hal_cfg.h b/riva/inc/wlan_hal_cfg.h index 22367e45260f7..4367e14db76cd 100644 --- a/riva/inc/wlan_hal_cfg.h +++ b/riva/inc/wlan_hal_cfg.h @@ -282,11 +282,15 @@ #define QWLAN_HAL_CFG_DISABLE_SCAN_DURING_SCO 224 #define QWLAN_HAL_CFG_TRIGGER_NULLFRAME_BEFORE_HB 225 #define QWLAN_HAL_CFG_ENABLE_POWERSAVE_OFFLOAD 226 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_WLAN_LEN 227 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_LEN 228 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN 229 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT 230 -#define QWLAN_HAL_CFG_MAX_PARAMS 227 +#define QWLAN_HAL_CFG_MAX_PARAMS 231 /* Total number of Integer CFGs. This is used while allocating the memory for TLV */ -#define QWLAN_HAL_CFG_INTEGER_PARAM 227 +#define QWLAN_HAL_CFG_INTEGER_PARAM 231 /*------------------------------------------------------------------------- Configuration Parameter min, max, defaults @@ -853,6 +857,26 @@ #define QWLAN_HAL_CFG_BTC_DHCP_PROT_ON_SCO_MAX 1 #define QWLAN_HAL_CFG_BTC_DHCP_PROT_ON_SCO_DEF 0 +/* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_WLAN_LEN */ +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_WLAN_LEN_MIN 15000 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_WLAN_LEN_MAX 55000 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_WLAN_LEN_DEF 35000 + +/* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_LEN */ +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_LEN_MIN 15000 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_LEN_MAX 25000 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_LEN_DEF 25000 + +/* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN */ +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MIN 5000 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MAX 15000 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_DEF 15000 + +/* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT */ +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MIN 5 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MAX 15 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_DEF 15 + /* QWLAN_HAL_CFG_ENABLE_UNICAST_FILTER */ #define QWLAN_HAL_CFG_ENABLE_UNICAST_FILTER_MIN 0 #define QWLAN_HAL_CFG_ENABLE_UNICAST_FILTER_MAX 1 From 1ceb703294e65590e068135f31247beb4d5353e6 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Thu, 5 Apr 2018 19:35:55 +0530 Subject: [PATCH 321/508] wlan: Use request manager for tsm metrics Propagation from qcacld-2.0 to prima We are transitioning to the new request manager framework. Change hdd_get_tsm_stats() and hdd_GetTsmStatsCB() to this framework. Note that this framework provides the infrastructure to pass data from the response thread to the request thread and hence eliminates the need to maintain temporary tsmStats in the HDD adapter struct. Change-Id: I799ec4eb32a37a1edaef6d3c1fcaa10a7a9130af CRs-Fixed: 2213593 --- CORE/HDD/src/wlan_hdd_main.c | 132 +++++++++++------------------------ 1 file changed, 42 insertions(+), 90 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 784eb778d27b2..734cca8db9ee2 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -6912,72 +6912,48 @@ static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue, return VOS_STATUS_SUCCESS; } -static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext ) -{ - struct statsContext *pStatsContext = NULL; - hdd_adapter_t *pAdapter = NULL; - - if (NULL == pContext) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Bad param, pContext [%pK]", - __func__, pContext); - return; - } +struct tsm_priv { + tAniTrafStrmMetrics tsm_metrics; +}; - /* there is a race condition that exists between this callback - function and the caller since the caller could time out either - before or while this code is executing. we use a spinlock to - serialize these actions */ - spin_lock(&hdd_context_lock); +static void hdd_get_tsm_stats_cb(tAniTrafStrmMetrics tsm_metrics, + const tANI_U32 sta_id, void *context ) +{ + struct hdd_request *request; + struct tsm_priv *priv; - pStatsContext = pContext; - pAdapter = pStatsContext->pAdapter; - if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic)) - { - /* the caller presumably timed out so there is nothing we can do */ - spin_unlock(&hdd_context_lock); - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter [%pK] magic [%08x]", - __func__, pAdapter, pStatsContext->magic); - return; - } + ENTER(); - /* context is valid so caller is still waiting */ + request = hdd_request_get(context); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); + return; + } - /* paranoia: invalidate the magic */ - pStatsContext->magic = 0; - - /* copy over the tsm stats */ - pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly; - vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist, - tsmMetrics.UplinkPktQueueDlyHist, - sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/ - sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0])); - pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly; - pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss; - pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount; - pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount; - pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly; + priv = hdd_request_priv(request); + priv->tsm_metrics = tsm_metrics; - /* notify the caller */ - complete(&pStatsContext->completion); + hdd_request_complete(request); + hdd_request_put(request); - /* serialization is complete */ - spin_unlock(&hdd_context_lock); + EXIT(); } - - static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid, tAniTrafStrmMetrics* pTsmMetrics) { hdd_station_ctx_t *pHddStaCtx = NULL; eHalStatus hstatus; VOS_STATUS vstatus = VOS_STATUS_SUCCESS; - long lrc; - struct statsContext context; hdd_context_t *pHddCtx = NULL; + int ret; + void *cookie; + struct hdd_request *request; + struct tsm_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; if (NULL == pAdapter) { @@ -6988,16 +6964,18 @@ static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - /* we are connected prepare our callback context */ - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = STATS_CONTEXT_MAGIC; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + return VOS_STATUS_E_NOMEM; + } + cookie = hdd_request_cookie(request); /* query tsm stats */ - hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB, + hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_get_tsm_stats_cb, pHddStaCtx->conn_info.staId[ 0 ], pHddStaCtx->conn_info.bssId, - &context, pHddCtx->pvosContext, tid); + cookie, pHddCtx->pvosContext, tid); if (eHAL_STATUS_SUCCESS != hstatus) { @@ -7008,45 +6986,19 @@ static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid, else { /* request was sent -- wait for the response */ - lrc = wait_for_completion_interruptible_timeout(&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - if (lrc <= 0) - { + ret = hdd_request_wait_for_response(request); + if (ret) { hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: SME %s while retrieving statistics", - __func__, (0 == lrc) ? "timeout" : "interrupt"); + "SME timeout while retrieving statistics"); vstatus = VOS_STATUS_E_TIMEOUT; + } else { + priv = hdd_request_priv(request); + *pTsmMetrics = priv->tsm_metrics; } } - /* either we never sent a request, we sent a request and received a - response or we sent a request and timed out. if we never sent a - request or if we sent a request and got a response, we want to - clear the magic out of paranoia. if we timed out there is a - race condition such that the callback function could be - executing at the same time we are. of primary concern is if the - callback function had already verified the "magic" but had not - yet set the completion variable when a timeout occurred. we - serialize these activities by invalidating the magic while - holding a shared spinlock which will cause us to block if the - callback is currently executing */ - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); + hdd_request_put(request); - if (VOS_STATUS_SUCCESS == vstatus) - { - pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly; - vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist, - pAdapter->tsmStats.UplinkPktQueueDlyHist, - sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/ - sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0])); - pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly; - pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss; - pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount; - pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount; - pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly; - } return vstatus; } #endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ From 0a5cd899a684f6d531ecd61610f38faa33deab98 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Oct 2017 14:10:32 +0200 Subject: [PATCH 322/508] ALSA: usb-audio: Kill stray URB at exiting USB-audio driver may leave a stray URB for the mixer interrupt when it exits by some error during probe. This leads to a use-after-free error as spotted by syzkaller like: ================================================================== BUG: KASAN: use-after-free in snd_usb_mixer_interrupt+0x604/0x6f0 Call Trace: __dump_stack lib/dump_stack.c:16 dump_stack+0x292/0x395 lib/dump_stack.c:52 print_address_description+0x78/0x280 mm/kasan/report.c:252 kasan_report_error mm/kasan/report.c:351 kasan_report+0x23d/0x350 mm/kasan/report.c:409 __asan_report_load8_noabort+0x19/0x20 mm/kasan/report.c:430 snd_usb_mixer_interrupt+0x604/0x6f0 sound/usb/mixer.c:2490 __usb_hcd_giveback_urb+0x2e0/0x650 drivers/usb/core/hcd.c:1779 .... Allocated by task 1484: save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59 save_stack+0x43/0xd0 mm/kasan/kasan.c:447 set_track mm/kasan/kasan.c:459 kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551 kmem_cache_alloc_trace+0x11e/0x2d0 mm/slub.c:2772 kmalloc ./include/linux/slab.h:493 kzalloc ./include/linux/slab.h:666 snd_usb_create_mixer+0x145/0x1010 sound/usb/mixer.c:2540 create_standard_mixer_quirk+0x58/0x80 sound/usb/quirks.c:516 snd_usb_create_quirk+0x92/0x100 sound/usb/quirks.c:560 create_composite_quirk+0x1c4/0x3e0 sound/usb/quirks.c:59 snd_usb_create_quirk+0x92/0x100 sound/usb/quirks.c:560 usb_audio_probe+0x1040/0x2c10 sound/usb/card.c:618 .... Freed by task 1484: save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59 save_stack+0x43/0xd0 mm/kasan/kasan.c:447 set_track mm/kasan/kasan.c:459 kasan_slab_free+0x72/0xc0 mm/kasan/kasan.c:524 slab_free_hook mm/slub.c:1390 slab_free_freelist_hook mm/slub.c:1412 slab_free mm/slub.c:2988 kfree+0xf6/0x2f0 mm/slub.c:3919 snd_usb_mixer_free+0x11a/0x160 sound/usb/mixer.c:2244 snd_usb_mixer_dev_free+0x36/0x50 sound/usb/mixer.c:2250 __snd_device_free+0x1ff/0x380 sound/core/device.c:91 snd_device_free_all+0x8f/0xe0 sound/core/device.c:244 snd_card_do_free sound/core/init.c:461 release_card_device+0x47/0x170 sound/core/init.c:181 device_release+0x13f/0x210 drivers/base/core.c:814 .... Actually such a URB is killed properly at disconnection when the device gets probed successfully, and what we need is to apply it for the error-path, too. In this patch, we apply snd_usb_mixer_disconnect() at releasing. Also introduce a new flag, disconnected, to struct usb_mixer_interface for not performing the disconnection procedure twice. Change-Id: Ic8b1b10a13b8369e12324210a8351b4ec0335218 Git-commit: 124751d5e63c823092060074bd0abaae61aaa9c4 Git-repo: https://github.com/torvalds/linux/commit Reported-by: Andrey Konovalov Tested-by: Andrey Konovalov Cc: Signed-off-by: Takashi Iwai Signed-off-by: Srinivasa Rao Kuppala Signed-off-by: Ajay Agarwal --- sound/usb/card.c | 4 +++- sound/usb/mixer.c | 17 +++++++++++------ sound/usb/mixer.h | 3 ++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index e2f744b6d5f7c..659a7875d79c1 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -603,6 +603,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, struct snd_usb_audio *chip) { struct snd_card *card; + struct usb_mixer_interface *mixer; struct list_head *p; bool was_shutdown; @@ -634,7 +635,8 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, } /* release mixer resources */ list_for_each(p, &chip->mixer_list) { - snd_usb_mixer_disconnect(p); + mixer = list_entry(p, struct usb_mixer_interface, list); + snd_usb_mixer_disconnect(mixer); } } diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 537ac978c69fa..ffc121c3d14bf 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2169,6 +2169,9 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) { + /* kill pending URBs */ + snd_usb_mixer_disconnect(mixer); + kfree(mixer->id_elems); if (mixer->urb) { kfree(mixer->urb->transfer_buffer); @@ -2500,13 +2503,15 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, return err; } -void snd_usb_mixer_disconnect(struct list_head *p) +void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer) { - struct usb_mixer_interface *mixer; - - mixer = list_entry(p, struct usb_mixer_interface, list); - usb_kill_urb(mixer->urb); - usb_kill_urb(mixer->rc_urb); + if (mixer->disconnected) + return; + if (mixer->urb) + usb_kill_urb(mixer->urb); + if (mixer->rc_urb) + usb_kill_urb(mixer->rc_urb); + mixer->disconnected = true; } #ifdef CONFIG_PM diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index 73b1f649447bd..529d3be45922e 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -23,6 +23,7 @@ struct usb_mixer_interface { u8 audigy2nx_leds[3]; u8 xonar_u1_status; + bool disconnected; }; #define MAX_CHANNELS 16 /* max logical channels */ @@ -57,7 +58,7 @@ struct usb_mixer_elem_info { int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, int ignore_error); -void snd_usb_mixer_disconnect(struct list_head *p); +void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer); void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid); From 2f3c4759d1188f3487354d32ce795e0516e7717a Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Wed, 11 Apr 2018 14:58:53 +0530 Subject: [PATCH 323/508] wlan: Enable WIPHY_FLAG_HAS_CHANNEL_SWITCH capability in wiphy Enable WIPHY_FLAG_HAS_CHANNEL_SWITCH capability to add channel switch support through cfg80211 ops. Change-Id: I64ef8b8e1b41c1b70a90705d5990b1ab60890ce2 CRs-Fixed: 2224125 --- CORE/HDD/inc/wlan_hdd_cfg80211.h | 7 +++++++ CORE/HDD/src/wlan_hdd_cfg80211.c | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h index 369477b8b9faa..43e9acbb5da41 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -100,6 +100,13 @@ #endif #endif +/* + * Max number of supported csa_counters in beacons + * and probe responses. Set to the same value as + * IEEE80211_MAX_CSA_COUNTERS_NUM + */ +#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2 + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) \ || defined(BACKPORTED_CHANNEL_SWITCH_PRESENT) #define CHANNEL_SWITCH_SUPPORTED diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 74ce9f5b4aa86..796019150ff63 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -8989,6 +8989,29 @@ int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand) } return 0; } + +/** + * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported + * @wiphy: Pointer to the wiphy. + * + * This Function adds Channel Switch support flag, if channel switch is + * supported by kernel. + * Return: void. + */ +#ifdef CHANNEL_SWITCH_SUPPORTED +static inline +void hdd_add_channel_switch_support(struct wiphy *wiphy) +{ + wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS; +} +#else +static inline +void hdd_add_channel_switch_support(struct wiphy *wiphy) +{ +} +#endif + /* * FUNCTION: wlan_hdd_cfg80211_init * This function is called by hdd_wlan_startup() @@ -9220,6 +9243,7 @@ int wlan_hdd_cfg80211_init(struct device *dev, wiphy->max_remain_on_channel_duration = 5000; #endif + hdd_add_channel_switch_support(wiphy); wiphy->n_vendor_commands = ARRAY_SIZE(hdd_wiphy_vendor_commands); wiphy->vendor_commands = hdd_wiphy_vendor_commands; wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events; From b36b2ef82dd077750713ede648d4b0e3e7d96afe Mon Sep 17 00:00:00 2001 From: Siba Prasad Date: Wed, 2 Aug 2017 22:32:18 +0530 Subject: [PATCH 324/508] mmc: card: Fix NULL pointer dereference in mmc_blk_ioctl_rpmb_cmd() In mmc_blk_ioctl_rpmb_cmd(), if user data copy fails, the card variable is dereferenced without NULL pointer check. Adding NULL pointer check in this condition. Change-Id: If3fd2175946cccaf838768d45de72bc2f5c32f6b Signed-off-by: Siba Prasad Signed-off-by: Pradeep P V K --- drivers/mmc/card/block.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 630ed50a8b3f0..080c937cef0ba 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -817,7 +817,7 @@ static int mmc_blk_ioctl_rpmb_cmd(struct block_device *bdev, { struct mmc_blk_ioc_rpmb_data *idata; struct mmc_blk_data *md; - struct mmc_card *card; + struct mmc_card *card = NULL; struct mmc_command cmd = {0}; struct mmc_data data = {0}; struct mmc_request mrq = {NULL}; @@ -973,7 +973,7 @@ static int mmc_blk_ioctl_rpmb_cmd(struct block_device *bdev, cmd_done: mmc_blk_put(md); - if (card->cmdq_init) + if (card && card->cmdq_init) wake_up(&card->host->cmdq_ctx.wait); return err; } From f9abab6787057aafc322d906809199e0e13654af Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Oct 2017 11:01:13 +0200 Subject: [PATCH 325/508] USB: serial: console: fix use-after-free after failed setup Make sure to reset the USB-console port pointer when console setup fails in order to avoid having the struct usb_serial be prematurely freed by the console code when the device is later disconnected. Change-Id: I4521740cfd288e745474d0de819a8304b72a2159 Git-commit: 299d7572e46f98534033a9e65973f13ad1ce9047 Git-repo: https://github.com/torvalds/linux/commit Fixes: 73e487fdb75f ("[PATCH] USB console: fix disconnection issues") Cc: stable # 2.6.18 Acked-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Srinivasa Rao Kuppala --- drivers/usb/serial/console.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 29fa1c3d0089b..926c1f2dc962c 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -187,6 +187,7 @@ static int usb_console_setup(struct console *co, char *options) tty_kref_put(tty); reset_open_count: port->port.count = 0; + info->port = NULL; usb_autopm_put_interface(serial->interface); error_get_interface: usb_serial_put(serial); From 73a2ca89ffd7234343bf14ecb6f44d980e69ea01 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Wed, 11 Apr 2018 12:54:39 +0530 Subject: [PATCH 326/508] wlan: Use request manager for setPktFilter IOCTL We are transitioning to the new request manager framework. Change wlan_hdd_set_filter() and hdd_pkt_filter_done to this framework. Change-Id: Ie9dd9d45d46dfde009730e679e1eeb2ca0ad4cbd CRs-Fixed: 2215446 --- CORE/HDD/src/wlan_hdd_wext.c | 68 +++++++++++++++++------------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 0e69ae2c34435..43a699aa1d90c 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -9348,32 +9348,21 @@ static int iw_set_keepalive_params(struct net_device *dev, --------------------------------------------------------------------------*/ static void hdd_pkt_filter_done(void *data, v_U32_t status) { - struct statsContext *cbCtx = (struct statsContext *)data; - - hddLog(VOS_TRACE_LEVEL_INFO, - FL("Pkt Filter Clear Status : %d"), status); + struct hdd_request *request; - if (data == NULL) - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid context")); - return; - } + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Pkt Filter Clear Status : %d"), status); - spin_lock(&hdd_context_lock); - if (cbCtx->magic != CLEAR_FILTER_MAGIC) - { - spin_unlock(&hdd_context_lock); - hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid context, magic %x"), cbCtx->magic); - if (ioctl_debug) - { - pr_info("%s: Invalid context, magic [%08x]\n", - __func__, cbCtx->magic); - } - return; - } + request = hdd_request_get(data); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); + if (ioctl_debug) + pr_info("%s: Obsolete request", __func__); + return; + } - complete(&cbCtx->completion); - spin_unlock(&hdd_context_lock); + hdd_request_complete(request); + hdd_request_put(request); } int wlan_hdd_set_filter(hdd_adapter_t *pAdapter, tpPacketFilterCfg pRequest) @@ -9382,8 +9371,13 @@ int wlan_hdd_set_filter(hdd_adapter_t *pAdapter, tpPacketFilterCfg pRequest) hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station; tSirRcvPktFilterCfgType packetFilterSetReq = {0}; tSirRcvFltPktClearParam packetFilterClrReq = {0}; - struct statsContext cbCtx; int i=0, status; + void *cookie; + struct hdd_request *request; + static const struct hdd_request_params params = { + .priv_size = 0, + .timeout_ms = PKT_FILTER_TIMEOUT, + }; status = wlan_hdd_validate_context(pHddCtx); if (0 != status) @@ -9477,25 +9471,29 @@ int wlan_hdd_set_filter(hdd_adapter_t *pAdapter, tpPacketFilterCfg pRequest) pHddStaCtx->conn_info.staId[0]); } - init_completion(&cbCtx.completion); - cbCtx.magic = CLEAR_FILTER_MAGIC; - cbCtx.pAdapter = pAdapter; - packetFilterClrReq.cbCtx = &cbCtx; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + return VOS_STATUS_E_NOMEM; + } + cookie = hdd_request_cookie(request); + + packetFilterClrReq.cbCtx = cookie; packetFilterClrReq.filterId = pRequest->filterId; packetFilterClrReq.pktFilterCallback = hdd_pkt_filter_done; - if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterClearFilter(pHddCtx->hHal, &packetFilterClrReq, pAdapter->sessionId)) + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterClearFilter( + pHddCtx->hHal, + &packetFilterClrReq, + pAdapter->sessionId)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Clear Filter", __func__); return -EINVAL; } - status = wait_for_completion_interruptible_timeout(&cbCtx.completion, - msecs_to_jiffies(PKT_FILTER_TIMEOUT)); - spin_lock(&hdd_context_lock); - cbCtx.magic = 0; - spin_unlock(&hdd_context_lock); - if (0 >= status) + status = hdd_request_wait_for_response(request); + hdd_request_put(request); + if (status) { hddLog(LOGE, FL("failure waiting for pkt_filter_comp_var %d"), status); From b211b051d7ca226d96b70defe10ac318f768b5b2 Mon Sep 17 00:00:00 2001 From: Arun Kumar Neelakantam Date: Thu, 29 Mar 2018 20:10:02 +0530 Subject: [PATCH 327/508] net: ipc_router: Fix buffer overflow during memcpy The increment logic of u64 pointer in skb_copy_to_log_buf() leads to buffer overflow. Modify the proto type of skb_copy_to_log_buf() function to accept only unsigned char pointer. CRs-Fixed: 2212592 Change-Id: I8affff1316656c1060ec57f2fb10b46f85314358 Signed-off-by: Arun Kumar Neelakantam --- net/ipc_router/ipc_router_core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c index d23799a5b2607..fd2dea170afd9 100644 --- a/net/ipc_router/ipc_router_core.c +++ b/net/ipc_router/ipc_router_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -269,7 +269,7 @@ static uint32_t ipc_router_calc_checksum(union rr_control_msg *msg) */ static void skb_copy_to_log_buf(struct sk_buff_head *skb_head, unsigned int pl_len, unsigned int hdr_offset, - uint64_t *log_buf) + unsigned char *log_buf) { struct sk_buff *temp_skb; unsigned int copied_len = 0, copy_len = 0; @@ -349,7 +349,8 @@ static void ipc_router_log_msg(void *log_ctx, uint32_t xchng_type, else if (hdr->version == IPC_ROUTER_V2) hdr_offset = sizeof(struct rr_header_v2); } - skb_copy_to_log_buf(skb_head, buf_len, hdr_offset, &pl_buf); + skb_copy_to_log_buf(skb_head, buf_len, hdr_offset, + (unsigned char *)&pl_buf); if (port_ptr && rport_ptr && (port_ptr->type == CLIENT_PORT) && (rport_ptr->server != NULL)) { From 8c99e75b1a743f281b566e5c1eac03f2e7c5fcca Mon Sep 17 00:00:00 2001 From: Vijay Navnath Kamble Date: Tue, 13 Mar 2018 18:42:58 +0530 Subject: [PATCH 328/508] ARM: dts: msm: Add DT support for apq8053-lite FEP v2 Add DT support for apq8053-lite FEP v2 with Mini CCB. Supports 8" Innolux panel by default. Change-Id: Iab7ba5a04e61778520c877d4b6cb40530056180c Signed-off-by: Vijay Navnath Kamble --- .../bindings/input/touchscreen/hmxchipset.txt | 47 +++++++++++ .../devicetree/bindings/vendor-prefixes.txt | 2 + arch/arm/boot/dts/qcom/Makefile | 1 + .../dts/qcom/apq8053-lite-dragon-v2.0.dts | 28 +++++++ .../dts/qcom/apq8053-lite-dragon-v2.0.dtsi | 70 ++++++++++++++++ .../qcom/dsi-panel-hx83100a-800p-video.dtsi | 81 +++++++++++++++++++ .../boot/dts/qcom/msm8953-mdss-panels.dtsi | 9 +++ 7 files changed, 238 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/hmxchipset.txt create mode 100644 arch/arm/boot/dts/qcom/apq8053-lite-dragon-v2.0.dts create mode 100644 arch/arm/boot/dts/qcom/apq8053-lite-dragon-v2.0.dtsi create mode 100644 arch/arm/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi diff --git a/Documentation/devicetree/bindings/input/touchscreen/hmxchipset.txt b/Documentation/devicetree/bindings/input/touchscreen/hmxchipset.txt new file mode 100644 index 0000000000000..b1fc17fff80f4 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/hmxchipset.txt @@ -0,0 +1,47 @@ +Himax Touch Controller + +Required properties: + + - compatible : Should be "himax,hxcommon" + - reg : I2C slave address of the device. + - interrupt-parent : Parent of interrupt. + - interrupts : Configuration of touch panel controller interrupt + GPIO. + - interrupt-gpios : Interrupt gpio which is to provide interrupts to + host, same as "interrupts" node. + - reset-gpios : Reset gpio to control the reset of chip. + - himax,display-coords : Display coordinates in pixels. It is a four + tuple consisting of min x, min y, max x and + max y values. + +Optional properties: + + - avdd-supply : Power supply needed to power up the device, this is + for fixed voltage external regulator. + - vdd-supply : Power supply needed to power up the device, when use + external regulator, do not add this property. + - himax,panel-coords : Panel coordinates for the chip in pixels. + It is a four tuple consisting of min x, + min y, max x and max y values. + +Example: +&i2c_3 { + status = "okay"; + himax_ts@48 { + compatible = "himax,hxcommon"; + reg = <0x48>; + interrupt-parent = <&tlmm>; + interrupts = <65 0x2>; + vdd-supply = <&pm8953_l10>; + avdd-supply = <&pm8953_l5>; + pinctrl-names = "pmx_ts_active","pmx_ts_suspend","pmx_ts_release"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + pinctrl-2 = <&ts_release>; + himax,panel-coords = <0 800 0 1280>; + himax,display-coords = <0 800 0 1280>; + himax,irq-gpio = <&tlmm 65 0x2008>; + //himax,rst-gpio = <&tlmm 64 0x0>; + report_type = <1>; + }; +}; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 4ec90277dee99..9f22c1d8be95c 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -200,3 +200,5 @@ zyxel ZyXEL Communications Corp. zarlink Zarlink Semiconductor bosch-sensortec» Bosch Sensortec GmbH lontium Lontium Semiconductor +himax Himax Technologies, Inc. +hxcommon Himax Technologies, Inc. diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index f80dacc7509c0..719ed5d0ceff5 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -261,6 +261,7 @@ dtb-$(CONFIG_ARCH_MSM8953) += msm8953-sim.dtb \ apq8053-ext-audio-mtp.dtb \ apq8053-ext-codec-rcm.dtb \ apq8053-lite-dragon-v1.0.dtb \ + apq8053-lite-dragon-v2.0.dtb \ msm8953-cdp-1200p.dtb \ msm8953-iot-mtp.dtb \ apq8053-iot-mtp.dtb \ diff --git a/arch/arm/boot/dts/qcom/apq8053-lite-dragon-v2.0.dts b/arch/arm/boot/dts/qcom/apq8053-lite-dragon-v2.0.dts new file mode 100644 index 0000000000000..7e38cc40c8e14 --- /dev/null +++ b/arch/arm/boot/dts/qcom/apq8053-lite-dragon-v2.0.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "apq8053-lite.dtsi" +#include "apq8053-lite-dragon-v2.0.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. APQ8053 Lite DragonBoard V2.0"; + compatible = "qcom,apq8053-lite-dragonboard", + "qcom,apq8053", "qcom,dragonboard"; + qcom,board-id = <0x0103000A 0>; +}; + +&blsp2_uart0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/qcom/apq8053-lite-dragon-v2.0.dtsi b/arch/arm/boot/dts/qcom/apq8053-lite-dragon-v2.0.dtsi new file mode 100644 index 0000000000000..1b9cfee783822 --- /dev/null +++ b/arch/arm/boot/dts/qcom/apq8053-lite-dragon-v2.0.dtsi @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "apq8053-lite-dragon.dtsi" + +&i2c_3 { + status = "okay"; + himax_ts@48 { + compatible = "himax,hxcommon"; + reg = <0x48>; + interrupt-parent = <&tlmm>; + interrupts = <65 0x2>; + vdd-supply = <&pm8953_l10>; + avdd-supply = <&pm8953_l5>; + pinctrl-names = "pmx_ts_active","pmx_ts_suspend", + "pmx_ts_release"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + pinctrl-2 = <&ts_release>; + himax,panel-coords = <0 800 0 1280>; + himax,display-coords = <0 800 0 1280>; + himax,irq-gpio = <&tlmm 65 0x2008>; + //himax,rst-gpio = <&tlmm 64 0x0>; + report_type = <1>; + }; +}; + +&mdss_dsi { + hw-config = "single_dsi"; +}; + +&mdss_dsi0 { + qcom,dsi-pref-prim-pan = <&dsi_boyi_hx83100a_800p_video>; + pinctrl-names = "mdss_default", "mdss_sleep"; + pinctrl-0 = <&mdss_dsi_active &mdss_te_active>; + pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>; + + vdd-supply = <&pm8953_l10>; + vddio-supply = <&pm8953_l6>; + lab-supply = <&lab_regulator>; + ibb-supply = <&ibb_regulator>; + + qcom,platform-te-gpio = <&tlmm 24 0>; + qcom,platform-reset-gpio = <&tlmm 61 0>; + qcom,platform-bklight-en-gpio = <&tlmm 100 0>; +}; + +&mdss_dsi1 { + status = "disabled"; +}; + +&labibb { + status = "ok"; + qpnp,qpnp-labibb-mode = "lcd"; +}; + +&wled { + qcom,cons-sync-write-delay-us = <1000>; + qcom,led-strings-list = [00 01 02 03]; +}; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi new file mode 100644 index 0000000000000..9ad11c4cf64d5 --- /dev/null +++ b/arch/arm/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi @@ -0,0 +1,81 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_boyi_hx83100a_800p_video: qcom,mdss_dsi_boyi_hx83100a_800p_video { + qcom,mdss-dsi-panel-name = "hx83100a 800p video mode dsi panel"; + qcom,mdss-dsi-panel-controller = <&mdss_dsi0>; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-destination = "display_2"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <800>; + qcom,mdss-dsi-panel-height = <1280>; + qcom,mdss-dsi-h-front-porch = <40>; + qcom,mdss-dsi-h-back-porch = <40>; + qcom,mdss-dsi-h-pulse-width = <40>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <8>; + qcom,mdss-dsi-v-front-porch = <412>; + qcom,mdss-dsi-v-pulse-width = <4>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-color-order = "rgb_swap_rgb"; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [ + 39 01 00 00 78 00 02 11 00 + 39 01 00 00 14 00 02 29 00 + 39 01 00 00 00 00 04 B9 83 10 0A + 39 01 00 00 00 00 08 C9 1F 00 08 1E 81 1E 00 + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 05 00 02 55 02 + 39 01 00 00 00 00 0A CA 40 3C 38 34 33 32 30 2C 28 + ]; + qcom,mdss-dsi-off-command = [05 01 00 00 96 00 02 28 00 + 05 01 00 00 00 00 02 10 00]; + qcom,mdss-dsi-on-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-lane-map = "lane_map_0123"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-panel-timings = [ + 9B 22 18 00 4A 4E 1C 26 1D 03 04 00 + ]; + qcom,mdss-dsi-t-clk-post = <0x04>; + qcom,mdss-dsi-t-clk-pre = <0x1f>; + qcom,mdss-dsi-bl-min-level = <2>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + //qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>; + //qcom,mdss-dsi-bl-pmic-bank-select = <0>; + //qcom,mdss-dsi-pwm-gpio = <&pm8937_gpios 2 0>; + qcom,mdss-pan-physical-width-dimension = <107>; + qcom,mdss-pan-physical-height-dimension = <172>; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 5>, <1 50>; + qcom,mdss-dsi-lp11-init; + qcom,mdss-dsi-post-init-delay = <1>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8953-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/msm8953-mdss-panels.dtsi index aedcc94e27e1d..a481b684ce5da 100644 --- a/arch/arm/boot/dts/qcom/msm8953-mdss-panels.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-mdss-panels.dtsi @@ -24,6 +24,7 @@ #include "dsi-panel-lt8912-480p-video.dtsi" #include "dsi-panel-lt8912-1080p-video.dtsi" #include "dsi-panel-lgd-incell-sw49106-fhd-video.dtsi" +#include "dsi-panel-hx83100a-800p-video.dtsi" &soc { dsi_panel_pwr_supply: dsi_panel_pwr_supply { @@ -115,3 +116,11 @@ qcom,mdss-dsi-t-clk-post = <0x0d>; qcom,mdss-dsi-t-clk-pre = <0x30>; }; + +&dsi_boyi_hx83100a_800p_video { + qcom,mdss-dsi-panel-timings-phy-v2 = [1f 1c 05 06 03 03 04 a0 + 1f 1c 05 06 03 03 04 a0 + 1f 1c 05 06 03 03 04 a0 + 1f 1c 05 06 03 03 04 a0 + 1f 10 05 06 03 03 04 a0]; +}; From f318d804e53add0ecb40fd086c7390a3b570cdc1 Mon Sep 17 00:00:00 2001 From: Sumit Agrawal Date: Thu, 22 Mar 2018 16:26:08 +0530 Subject: [PATCH 329/508] ARM: dts: msm: Add DT support for apq8053-lite FEP v2 with Ext Codec Add DT support for apq8053-lite based SOM with miniCCB and external codec. Change-Id: If3501eff82887b334ac44ebef8bbcb89021fe32a Signed-off-by: Sumit Agrawal (cherry picked from commit 400ad4d7ece548aa6d0f942d05b367824aa0233e) --- arch/arm/boot/dts/qcom/Makefile | 1 + .../apq8053-lite-ext-codec-dragon-v2.0.dts | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 arch/arm/boot/dts/qcom/apq8053-lite-ext-codec-dragon-v2.0.dts diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index 719ed5d0ceff5..db2682ff39b3b 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -262,6 +262,7 @@ dtb-$(CONFIG_ARCH_MSM8953) += msm8953-sim.dtb \ apq8053-ext-codec-rcm.dtb \ apq8053-lite-dragon-v1.0.dtb \ apq8053-lite-dragon-v2.0.dtb \ + apq8053-lite-ext-codec-dragon-v2.0.dtb \ msm8953-cdp-1200p.dtb \ msm8953-iot-mtp.dtb \ apq8053-iot-mtp.dtb \ diff --git a/arch/arm/boot/dts/qcom/apq8053-lite-ext-codec-dragon-v2.0.dts b/arch/arm/boot/dts/qcom/apq8053-lite-ext-codec-dragon-v2.0.dts new file mode 100644 index 0000000000000..e3c1b449f303a --- /dev/null +++ b/arch/arm/boot/dts/qcom/apq8053-lite-ext-codec-dragon-v2.0.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "apq8053-lite.dtsi" +#include "apq8053-lite-dragon-v2.0.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. APQ8053 Lite + Ext Codec DragonBoard V2.0"; + compatible = "qcom,apq8053-lite-dragonboard", + "qcom,apq8053", "qcom,dragonboard"; + qcom,board-id = <0x0103010A 0>; +}; + +&blsp2_uart0 { + status = "okay"; +}; From 72faa21ab84069290ed33da4d7400528cd5ab107 Mon Sep 17 00:00:00 2001 From: Vijay Navnath Kamble Date: Fri, 23 Mar 2018 13:20:35 +0530 Subject: [PATCH 330/508] ARM: dts: msm: Display bringup changes for apq8053-lite FEP v2 with miniCCB Turn on PM8953_L4 power. This powers the MIPI_DSI switch on the miniCCB. Change GPIO 141 to output low. This sets MIPI-DSI switch to route MIPI DSI to the LCD connector (original state : 141 input, L4 off) Change-Id: I87e9912463f98d6926c96762b6e6421c6e606e81 Signed-off-by: Vijay Navnath Kamble (cherry picked from commit 4066a9c08709c26edc7087b8ba9ee4742e634478) --- .../boot/dts/qcom/apq8053-lite-dragon-v2.0.dtsi | 12 +++++++++--- arch/arm/boot/dts/qcom/msm8953-pinctrl.dtsi | 17 ++++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/qcom/apq8053-lite-dragon-v2.0.dtsi b/arch/arm/boot/dts/qcom/apq8053-lite-dragon-v2.0.dtsi index 1b9cfee783822..c062b20d94425 100644 --- a/arch/arm/boot/dts/qcom/apq8053-lite-dragon-v2.0.dtsi +++ b/arch/arm/boot/dts/qcom/apq8053-lite-dragon-v2.0.dtsi @@ -42,8 +42,8 @@ &mdss_dsi0 { qcom,dsi-pref-prim-pan = <&dsi_boyi_hx83100a_800p_video>; pinctrl-names = "mdss_default", "mdss_sleep"; - pinctrl-0 = <&mdss_dsi_active &mdss_te_active>; - pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>; + pinctrl-0 = <&mdss_dsi_active &mdss_te_active &mdss_dsi_gpio>; + pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend &mdss_dsi_gpio>; vdd-supply = <&pm8953_l10>; vddio-supply = <&pm8953_l6>; @@ -60,11 +60,17 @@ }; &labibb { - status = "ok"; + status = "okay"; qpnp,qpnp-labibb-mode = "lcd"; }; &wled { + status = "okay"; qcom,cons-sync-write-delay-us = <1000>; qcom,led-strings-list = [00 01 02 03]; }; + +&pm8953_l4 { + status = "okay"; + regulator-always-on; +}; diff --git a/arch/arm/boot/dts/qcom/msm8953-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msm8953-pinctrl.dtsi index c3eed191d94fd..4f4324d746079 100644 --- a/arch/arm/boot/dts/qcom/msm8953-pinctrl.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-pinctrl.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -454,6 +454,21 @@ bias-pull-down; /* pull down */ }; }; + + mdss_dsi_gpio: mdss_dsi_gpio { + mux { + pins = "gpio141"; + function = "gpio"; + }; + + config { + pins = "gpio141"; + drive-strength = <8>; + bias-pull-down; + output-low; + }; + }; + }; pmx_mdss_te { From 1045523fb5e3372b33b9c5241c055a7dde007a5c Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Thu, 5 Apr 2018 16:06:04 +0530 Subject: [PATCH 331/508] wlan: Use request manager for station stats propagation from qcacld-2.0 to prima We are transitioning to the new request manager framework. Change wlan_hdd_get_station_stats() and hdd_get_station_statistics_cb() to this framework. Change-Id: I4f0255975e8c37fa91215bcddc7896bb8d309cf8 CRs-Fixed: 2213584 --- CORE/HDD/src/wlan_hdd_wext.c | 145 ++++++++++++++++------------------- 1 file changed, 64 insertions(+), 81 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 43a699aa1d90c..9ce2b3de498ed 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -3505,66 +3505,48 @@ VOS_STATUS wlan_hdd_get_classAstats(hdd_adapter_t *pAdapter) return VOS_STATUS_SUCCESS; } -static void hdd_get_station_statisticsCB(void *pStats, void *pContext) +struct stats_ctx { + tCsrSummaryStatsInfo summary_stats; + tCsrGlobalClassAStatsInfo class_a_stats; +}; + +static void hdd_get_station_statistics_cb(void *stats, void *context) { - struct statsContext *pStatsContext; - tCsrSummaryStatsInfo *pSummaryStats; - tCsrGlobalClassAStatsInfo *pClassAStats; - hdd_adapter_t *pAdapter; + tCsrSummaryStatsInfo *summary_stats; + tCsrGlobalClassAStatsInfo *class_a_stats; + struct hdd_request *request; + struct stats_ctx *priv; - if (ioctl_debug) - { - pr_info("%s: pStats [%pK] pContext [%pK]\n", - __func__, pStats, pContext); - } - if ((NULL == pStats) || (NULL == pContext)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Bad param, pStats [%pK] pContext [%pK]", - __func__, pStats, pContext); - return; - } - - /* there is a race condition that exists between this callback - function and the caller since the caller could time out either - before or while this code is executing. we use a spinlock to - serialize these actions */ - spin_lock(&hdd_context_lock); + if (ioctl_debug) { + pr_info("%s: stats [%pK] context [%pK]\n", + __func__, stats, context); + } - pSummaryStats = (tCsrSummaryStatsInfo *)pStats; - pClassAStats = (tCsrGlobalClassAStatsInfo *)( pSummaryStats + 1 ); - pStatsContext = pContext; - pAdapter = pStatsContext->pAdapter; - if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic)) - { - /* the caller presumably timed out so there is nothing we can do */ - spin_unlock(&hdd_context_lock); - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter [%pK] magic [%08x]", - __func__, pAdapter, pStatsContext->magic); - if (ioctl_debug) - { - pr_info("%s: Invalid context, pAdapter [%pK] magic [%08x]\n", - __func__, pAdapter, pStatsContext->magic); - } - return; - } + if (NULL == stats) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Bad param, stats [%pK]", + __func__, stats); + return; + } - /* context is valid so caller is still waiting */ + request = hdd_request_get(context); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); + return; + } - /* paranoia: invalidate the magic */ - pStatsContext->magic = 0; + summary_stats = (tCsrSummaryStatsInfo *)stats; + class_a_stats = (tCsrGlobalClassAStatsInfo *)(summary_stats + 1); - /* copy over the stats. do so as a struct copy */ - pAdapter->hdd_stats.summary_stat = *pSummaryStats; - pAdapter->hdd_stats.ClassA_stat = *pClassAStats; + priv = hdd_request_priv(request); - /* notify the caller */ - complete(&pStatsContext->completion); + /* copy over the stats. do so as a struct copy */ + priv->summary_stats = *summary_stats; + priv->class_a_stats = *class_a_stats; - /* serialization is complete */ - spin_unlock(&hdd_context_lock); + hdd_request_complete(request); + hdd_request_put(request); } VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter) @@ -3572,9 +3554,15 @@ VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter) hdd_station_ctx_t *pHddStaCtx; hdd_ap_ctx_t *sap_ctx; eHalStatus hstatus; - long lrc; - struct statsContext context; tANI_U8 sta_id; + int ret; + void *cookie; + struct hdd_request *request; + struct stats_ctx *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; if (NULL == pAdapter) { @@ -3590,11 +3578,12 @@ VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter) sta_id = pHddStaCtx->conn_info.staId[0]; } - /* we are connected - prepare our callback context */ - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = STATS_CONTEXT_MAGIC; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + return VOS_STATUS_E_NOMEM; + } + cookie = hdd_request_cookie(request); /* query only for Summary & Class A statistics */ hstatus = sme_GetStatistics(WLAN_HDD_GET_HAL_CTX(pAdapter), @@ -3602,11 +3591,11 @@ VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter) SME_SUMMARY_STATS | SME_GLOBAL_CLASSA_STATS | SME_PER_PKT_STATS, - hdd_get_station_statisticsCB, + hdd_get_station_statistics_cb, 0, // not periodic FALSE, //non-cached results sta_id, - &context); + cookie); if (eHAL_STATUS_SUCCESS != hstatus) { hddLog(VOS_TRACE_LEVEL_ERROR, @@ -3617,37 +3606,31 @@ VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter) else { /* request was sent -- wait for the response */ - lrc = wait_for_completion_interruptible_timeout(&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - - if (lrc <= 0) + ret = hdd_request_wait_for_response(request); + if (ret) { hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: SME %s while retrieving statistics", - __func__, (0 == lrc) ? "timeout" : "interrupt"); + FL("SME timeout while retrieving statistics")); + } + else + { + priv = hdd_request_priv(request); + pAdapter->hdd_stats.summary_stat = priv->summary_stats; + pAdapter->hdd_stats.ClassA_stat = priv->class_a_stats; } } - /* either we never sent a request, we sent a request and received a - response or we sent a request and timed out. if we never sent a - request or if we sent a request and got a response, we want to - clear the magic out of paranoia. if we timed out there is a - race condition such that the callback function could be - executing at the same time we are. of primary concern is if the - callback function had already verified the "magic" but had not - yet set the completion variable when a timeout occurred. we - serialize these activities by invalidating the magic while - holding a shared spinlock which will cause us to block if the - callback is currently executing */ - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); + /* + * either we never sent a request, we sent a request and received a + * response or we sent a request and timed out. Regardless we are + * done with the request. + */ + hdd_request_put(request); /* either callback updated pAdapter stats or it has cached data */ return VOS_STATUS_SUCCESS; } - /* * Support for the LINKSPEED private command * Per the WiFi framework the response must be of the form From 1b8dd4f877892323b55faf8bb2366e09e7f4e0bf Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Mon, 9 Apr 2018 17:19:03 +0530 Subject: [PATCH 332/508] wlan: Use request manager for GETFWSTATS and GETBCNMISSRATE We are transitioning to the new request manager framework. Change hdd_driver_command to this framework. Change-Id: I5a1768be6814c1dae4bdb7deab5bc67315af32da CRs-Fixed: 2215434 --- CORE/HDD/src/wlan_hdd_main.c | 234 +++++++++++++++++------------------ 1 file changed, 112 insertions(+), 122 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 734cca8db9ee2..b3afa6f0f759a 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -2703,106 +2703,54 @@ hdd_parse_reassoc(hdd_adapter_t *pAdapter, const char *command, int total_len) } #endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE FEATURE_WLAN_LFR */ -static void getBcnMissRateCB(VOS_STATUS status, int bcnMissRate, void *data) +static void get_bcn_miss_rate_cb(VOS_STATUS status, int bcnMissRate, void *data) { - bcnMissRateContext_t *pCBCtx; + struct hdd_request *request; - if (NULL == data) - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL")); - return; - } + request = hdd_request_get(data); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); + return; + } - /* there is a race condition that exists between this callback - function and the caller since the caller could time out either - before or while this code is executing. we use a spinlock to - serialize these actions */ - spin_lock(&hdd_context_lock); + if (VOS_STATUS_SUCCESS == status) + gbcnMissRate = bcnMissRate; + else + hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate")); - pCBCtx = (bcnMissRateContext_t *)data; - gbcnMissRate = -1; + hdd_request_complete(request); + hdd_request_put(request); - if (pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - FL("invalid context magic: %08x"), pCBCtx->magic); - spin_unlock(&hdd_context_lock); - return ; - } + return; +} - if (VOS_STATUS_SUCCESS == status) - { - gbcnMissRate = bcnMissRate; - } - else - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate")); - } +struct fw_stats_priv { + tSirFwStatsResult *fw_stats; +}; - complete(&(pCBCtx->completion)); - spin_unlock(&hdd_context_lock); +void hdd_fw_statis_cb(VOS_STATUS status, + tSirFwStatsResult *fwStatsResult, void *context) +{ + struct hdd_request *request; + struct fw_stats_priv *priv; - return; -} + hddLog(VOS_TRACE_LEVEL_INFO, FL("with status = %d"),status); -void hdd_FWStatisCB( VOS_STATUS status, - tSirFwStatsResult *fwStatsResult, void *pContext ) -{ - fwStatsContext_t *fwStatsCtx; - hdd_adapter_t *pAdapter; + request = hdd_request_get(context); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); + return; + } + priv = hdd_request_priv(request); - hddLog(VOS_TRACE_LEVEL_INFO, FL(" with status = %d"),status); + if (VOS_STATUS_SUCCESS != status) + *priv->fw_stats = *fwStatsResult; + else + priv->fw_stats = NULL; - if (NULL == pContext) - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL")); - return; - } - /* there is a race condition that exists between this callback - function and the caller since the caller could time out either - before or while this code is executing. we use a spinlock to - serialize these actions */ - spin_lock(&hdd_context_lock); - fwStatsCtx = (fwStatsContext_t *) pContext; - if (fwStatsCtx->magic != FW_STATS_CONTEXT_MAGIC) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - FL("invalid context magic: %08x"), fwStatsCtx->magic); - spin_unlock(&hdd_context_lock); - return; - } - pAdapter = fwStatsCtx->pAdapter; - if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - FL("pAdapter returned is NULL or invalid")); - spin_unlock(&hdd_context_lock); - return; - } - pAdapter->fwStatsRsp.type = 0; - if ((VOS_STATUS_SUCCESS == status) && (NULL != fwStatsResult)) - { - switch( fwStatsResult->type ) - { - case FW_UBSP_STATS: - { - memcpy(&pAdapter->fwStatsRsp,fwStatsResult,sizeof(tSirFwStatsResult)); - hddLog(VOS_TRACE_LEVEL_INFO, - FL("ubsp_enter_cnt = %d ubsp_jump_ddr_cnt = %d"), - pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_enter_cnt, - pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_jump_ddr_cnt); - } - break; - default: - { - hddLog(VOS_TRACE_LEVEL_ERROR, - FL(" No handling for stats type %d"),fwStatsResult->type); - } - } - } - complete(&(fwStatsCtx->completion)); - spin_unlock(&hdd_context_lock); - return; + hdd_request_complete(request); + hdd_request_put(request); + return; } /* @@ -6316,8 +6264,12 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, { eHalStatus status; char buf[32], len; - long waitRet; - bcnMissRateContext_t getBcnMissRateCtx; + void *cookie; + struct hdd_request *request; + static const struct hdd_request_params params = { + .priv_size = 0, + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); @@ -6328,35 +6280,34 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, ret = -1; goto exit; } - - init_completion(&(getBcnMissRateCtx.completion)); - getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + ret = -ENOMEM; + goto exit; + } + cookie = hdd_request_cookie(request); status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, - (void *)getBcnMissRateCB, - (void *)(&getBcnMissRateCtx)); + (void *)get_bcn_miss_rate_cb, + cookie); if( eHAL_STATUS_SUCCESS != status) { hddLog(VOS_TRACE_LEVEL_INFO, FL("GETBCNMISSRATE: fail to post WDA cmd")); ret = -EINVAL; - goto exit; + goto free_bcn_miss_rate_req; } - waitRet = wait_for_completion_interruptible_timeout - (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME); - if(waitRet <= 0) + ret = hdd_request_wait_for_response(request); + if(ret) { hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to wait on bcnMissRateComp %d"), ret); - //Make magic number to zero so that callback is not called. - spin_lock(&hdd_context_lock); - getBcnMissRateCtx.magic = 0x0; - spin_unlock(&hdd_context_lock); ret = -EINVAL; - goto exit; + goto free_bcn_miss_rate_req; } hddLog(VOS_TRACE_LEVEL_INFO, @@ -6368,9 +6319,12 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to copy data to user buffer", __func__); ret = -EFAULT; - goto exit; + goto free_bcn_miss_rate_req; } ret = len; + +free_bcn_miss_rate_req: + hdd_request_put(request); } #ifdef FEATURE_WLAN_TDLS else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) { @@ -6460,11 +6414,17 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, eHalStatus status; char *buf = NULL; char len; - long waitRet; - fwStatsContext_t fwStatsCtx; - tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp); + tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp), + *fw_stats_result; tANI_U8 *ptr = command; int stats; + void *cookie; + struct hdd_request *request; + struct fw_stats_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; ret = hdd_drv_cmd_validate(command, 10); if (ret) @@ -6488,32 +6448,63 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, goto exit; } - init_completion(&(fwStatsCtx.completion)); - fwStatsCtx.magic = FW_STATS_CONTEXT_MAGIC; - fwStatsCtx.pAdapter = pAdapter; - fwStatsRsp->type = 0; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + ret = -ENOMEM; + goto exit; + } + status = sme_GetFwStats( (tHalHandle)pHddCtx->hHal, stats, - &fwStatsCtx, hdd_FWStatisCB); + cookie, hdd_fw_statis_cb); if (eHAL_STATUS_SUCCESS != status) { hddLog(VOS_TRACE_LEVEL_ERROR, FL(" fail to post WDA cmd status = %d"), status); ret = -EINVAL; + hdd_request_put(request); goto exit; } - waitRet = wait_for_completion_timeout - (&(fwStatsCtx.completion), FW_STATE_WAIT_TIME); - if (waitRet <= 0) + ret = hdd_request_wait_for_response(request); + if (ret) { hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to wait on GwtFwstats")); - //Make magic number to zero so that callback is not executed. - spin_lock(&hdd_context_lock); - fwStatsCtx.magic = 0x0; - spin_unlock(&hdd_context_lock); ret = -EINVAL; + hdd_request_put(request); goto exit; } + + priv = hdd_request_priv(request); + fw_stats_result = priv->fw_stats; + fwStatsRsp->type = 0; + if (NULL != fw_stats_result) + { + switch (fw_stats_result->type ) + { + case FW_UBSP_STATS: + { + tSirUbspFwStats *stats = + &fwStatsRsp->fwStatsData.ubspStats; + memcpy(fwStatsRsp, fw_stats_result, + sizeof(tSirFwStatsResult)); + hddLog(VOS_TRACE_LEVEL_INFO, + FL("ubsp_enter_cnt = %d ubsp_jump_ddr_cnt = %d"), + stats->ubsp_enter_cnt, + stats->ubsp_jump_ddr_cnt); + } + break; + + default: + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("No handling for stats type %d"), + fw_stats_result->type); + } + } + } + hdd_request_put(request); + if (fwStatsRsp->type) { buf = kmalloc(FW_STATE_RSP_LEN, GFP_KERNEL); @@ -6560,7 +6551,6 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, ret = -EFAULT; goto exit; } - } else if (strncasecmp(command, "SET_FCC_CHANNEL", 15) == 0) { From 42981db71ef5932ced51634b3d7d4656b45d0784 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Thu, 5 Apr 2018 17:27:39 +0530 Subject: [PATCH 333/508] wlan: Use request manager for Class A stats propagation from qcacld-2.0 to prima We are transitioning to the new request manager framework. Change wlan_hdd_get_classAstats() and hdd_get_class_a_statistics_cb() to this framework. Change-Id: I6cfa2155187e3d9ac4099f1e4480835917fd9ca6 CRs-Fixed: 2213567 --- CORE/HDD/src/wlan_hdd_wext.c | 102 ++++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 30 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 9ce2b3de498ed..1a855aa63295a 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -3432,14 +3432,58 @@ void hdd_GetClassA_statisticsCB(void *pStats, void *pContext) /* serialization is complete */ spin_unlock(&hdd_context_lock); + +} + +struct stats_class_a_ctx { + tCsrGlobalClassAStatsInfo class_a_stats; +}; + +void hdd_get_class_a_statistics_cb(void *stats, void *context) +{ + struct hdd_request *request; + struct stats_class_a_ctx *priv; + + if (ioctl_debug) { + pr_info("%s: stats [%pK] context [%pK]\n", + __func__, stats, context); + } + + if (NULL == stats) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Bad param, stats [%pK]", + __func__, stats); + return; + } + + request = hdd_request_get(context); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); + return; + } + + priv = hdd_request_priv(request); + + /* copy over the stats. do so as a struct copy */ + priv->class_a_stats = *(tCsrGlobalClassAStatsInfo *)stats; + + hdd_request_complete(request); + hdd_request_put(request); } VOS_STATUS wlan_hdd_get_classAstats(hdd_adapter_t *pAdapter) { hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); eHalStatus hstatus; - long lrc; - struct statsContext context; + int ret; + void *cookie; + struct hdd_request *request; + struct stats_class_a_ctx *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; + if (NULL == pAdapter) { @@ -3452,20 +3496,22 @@ VOS_STATUS wlan_hdd_get_classAstats(hdd_adapter_t *pAdapter) return VOS_STATUS_SUCCESS; } - /* we are connected - prepare our callback context */ - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = STATS_CONTEXT_MAGIC; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + return VOS_STATUS_E_NOMEM; + } + cookie = hdd_request_cookie(request); + /* query only for Class A statistics (which include link speed) */ hstatus = sme_GetStatistics( WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_HDD, SME_GLOBAL_CLASSA_STATS, - hdd_GetClassA_statisticsCB, + hdd_get_class_a_statistics_cb, 0, // not periodic FALSE, //non-cached results pHddStaCtx->conn_info.staId[0], - &context); + cookie); if (eHAL_STATUS_SUCCESS != hstatus) { hddLog(VOS_TRACE_LEVEL_ERROR, @@ -3475,31 +3521,27 @@ VOS_STATUS wlan_hdd_get_classAstats(hdd_adapter_t *pAdapter) } else { - /* request was sent -- wait for the response */ - lrc = wait_for_completion_interruptible_timeout(&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - if (lrc <= 0) - { + /* request was sent -- wait for the response */ + ret = hdd_request_wait_for_response(request); + if (ret) + { hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: SME %s while retrieving Class A statistics", - __func__, (0 == lrc) ? "timeout" : "interrupt"); + FL("SME timeout while retrieving Class A statistics")); + } + else + { + priv = hdd_request_priv(request); + pAdapter->hdd_stats.ClassA_stat = priv->class_a_stats; + } } - /* either we never sent a request, we sent a request and received a - response or we sent a request and timed out. if we never sent a - request or if we sent a request and got a response, we want to - clear the magic out of paranoia. if we timed out there is a - race condition such that the callback function could be - executing at the same time we are. of primary concern is if the - callback function had already verified the "magic" but had not - yet set the completion variable when a timeout occurred. we - serialize these activities by invalidating the magic while - holding a shared spinlock which will cause us to block if the - callback is currently executing */ - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); + /* + * either we never sent a request, we sent a request and received a + * response or we sent a request and timed out. Regardless we are + * done with the request. + */ + hdd_request_put(request); /* either callback updated pAdapter stats or it has cached data */ return VOS_STATUS_SUCCESS; From 084e45b2d1450c42f005774ffd8692587ef1b719 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Thu, 5 Apr 2018 18:02:55 +0530 Subject: [PATCH 334/508] wlan: Use request manager for RSSI propagation from qcacld-2.0 to prima We are transitioning to the new request manager framework. Change wlan_hdd_get_rssi() and hdd_get_rssi_cb() to this framework. Change-Id: Ib0b74e288ad3dc4588440f0de7cfbebc9f88a49a CRs-Fixed: 2213568 --- CORE/HDD/src/wlan_hdd_wext.c | 157 +++++++++++++++-------------------- 1 file changed, 68 insertions(+), 89 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 1a855aa63295a..6e0a5bbeb6070 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -910,68 +910,6 @@ hdd_IsAuthTypeRSN( tHalHandle halHandle, eCsrAuthType authType) return rsnType; } -static void hdd_GetRssiCB( v_S7_t rssi, tANI_U32 staId, void *pContext ) -{ - struct statsContext *pStatsContext; - hdd_adapter_t *pAdapter; - - if (ioctl_debug) - { - pr_info("%s: rssi [%d] STA [%d] pContext [%pK]\n", - __func__, (int)rssi, (int)staId, pContext); - } - - if (NULL == pContext) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Bad param, pContext [%pK]", - __func__, pContext); - return; - } - - pStatsContext = pContext; - pAdapter = pStatsContext->pAdapter; - - /* there is a race condition that exists between this callback - function and the caller since the caller could time out either - before or while this code is executing. we use a spinlock to - serialize these actions */ - spin_lock(&hdd_context_lock); - - if ((NULL == pAdapter) || (RSSI_CONTEXT_MAGIC != pStatsContext->magic)) - { - /* the caller presumably timed out so there is nothing we can do */ - spin_unlock(&hdd_context_lock); - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter [%pK] magic [%08x]", - __func__, pAdapter, pStatsContext->magic); - if (ioctl_debug) - { - pr_info("%s: Invalid context, pAdapter [%pK] magic [%08x]\n", - __func__, pAdapter, pStatsContext->magic); - } - return; - } - - /* context is valid so caller is still waiting */ - - /* paranoia: invalidate the magic */ - pStatsContext->magic = 0; - - /* copy over the rssi.FW will return RSSI as -100 - * if there are no samples to calculate the average - * RSSI - */ - if (rssi != -100) - pAdapter->rssi = rssi; - if (pAdapter->rssi > 0) - pAdapter->rssi = 0; - /* notify the caller */ - complete(&pStatsContext->completion); - - /* serialization is complete */ - spin_unlock(&hdd_context_lock); -} struct snr_priv { int8_t snr; @@ -1004,13 +942,46 @@ static void hdd_get_snr_cb(tANI_S8 snr, tANI_U32 staId, void *context) hdd_request_put(request); } +struct rssi_priv { + v_S7_t rssi; +}; + +static void hdd_get_rssi_cb( v_S7_t rssi, tANI_U32 staId, void *context ) +{ + struct hdd_request *request; + struct rssi_priv *priv; + + if (ioctl_debug) { + pr_info("%s: rssi [%d] STA [%d] context [%pK]\n", + __func__, (int)rssi, (int)staId, context); + } + + request = hdd_request_get(context); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); + return; + } + + priv = hdd_request_priv(request); + priv->rssi = rssi; + + hdd_request_complete(request); + hdd_request_put(request); +} + VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value) { - struct statsContext context; hdd_context_t *pHddCtx; hdd_station_ctx_t *pHddStaCtx; eHalStatus hstatus; - long lrc; + int ret; + void *cookie; + struct hdd_request *request; + struct rssi_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; if (NULL == pAdapter) { @@ -1045,14 +1016,17 @@ VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value) return VOS_STATUS_SUCCESS; } - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = RSSI_CONTEXT_MAGIC; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + return VOS_STATUS_E_NOMEM; + } + cookie = hdd_request_cookie(request); - hstatus = sme_GetRssi(pHddCtx->hHal, hdd_GetRssiCB, + hstatus = sme_GetRssi(pHddCtx->hHal, hdd_get_rssi_cb, pHddStaCtx->conn_info.staId[ 0 ], pHddStaCtx->conn_info.bssId, - &context, pHddCtx->pvosContext); + cookie, pHddCtx->pvosContext); if (eHAL_STATUS_SUCCESS != hstatus) { hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to retrieve RSSI", @@ -1062,35 +1036,40 @@ VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value) else { /* request was sent -- wait for the response */ - lrc = wait_for_completion_interruptible_timeout(&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - if (lrc <= 0) + ret = hdd_request_wait_for_response(request); + if (ret) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME %s while retrieving RSSI", - __func__, (0 == lrc) ? "timeout" : "interrupt"); + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timeout while retrieving RSSI")); /* we'll now returned a cached value below */ } + else + { + priv = hdd_request_priv(request); + pAdapter->rssi = priv->rssi; + /* + * copy over the rssi.FW will return RSSI as -100 if + * there are no samples to calculate the averag RSSI + */ + if (priv->rssi != -100) + pAdapter->rssi = priv->rssi; + + if (pAdapter->rssi > 0) + pAdapter->rssi = 0; + } } - /* either we never sent a request, we sent a request and received a - response or we sent a request and timed out. if we never sent a - request or if we sent a request and got a response, we want to - clear the magic out of paranoia. if we timed out there is a - race condition such that the callback function could be - executing at the same time we are. of primary concern is if the - callback function had already verified the "magic" but had not - yet set the completion variable when a timeout occurred. we - serialize these activities by invalidating the magic while - holding a shared spinlock which will cause us to block if the - callback is currently executing */ - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); - *rssi_value = pAdapter->rssi; hddLog(VOS_TRACE_LEVEL_INFO, "%s: RSSI = %d", __func__, *rssi_value); + /* + * either we never sent a request, we sent a request and received a + * response or we sent a request and timed out. Regardless we are + * done with the request. + */ + hdd_request_put(request); + return VOS_STATUS_SUCCESS; } /**--------------------------------------------------------------------------- From 00022c12e0cad8b735f94d6ee3785a557b4a3df2 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Thu, 5 Apr 2018 18:54:35 +0530 Subject: [PATCH 335/508] wlan: Use request manager to handle WE_SET_POWER requests propagation from qcacld-2.0 to prima. Use the new request manager framework for handling WE_SET_POWER related iw requests. Change-Id: I1d833ced2096a92b855cc861c84a448029e592b7 CRs-Fixed: 2213539 --- CORE/HDD/src/wlan_hdd_wext.c | 125 +++++++++++++++++++---------------- 1 file changed, 69 insertions(+), 56 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 6e0a5bbeb6070..2fcdded2afa5c 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -4074,6 +4074,27 @@ hdd_encrypt_msg_cb(v_VOID_t *pUserData, v_VOID_t *pEncInfoRsp) pEncryptedDataRsp->encryptedPayload.length, 0); } +/** + * iw_power_callback_func() - Callback function registered with PMC + * @context: cookie originally registered with PMC + * @status: status code indicated by PMC state machine + * + * Return: None + */ +static void iw_power_callback_func(void *context, eHalStatus status) +{ + struct hdd_request *request = hdd_request_get(context); + + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Obsolete request", __func__); + return; + } + + hdd_request_complete(request); + hdd_request_put(request); +} + VOS_STATUS wlan_hdd_enter_bmps(hdd_adapter_t *pAdapter, int mode) { struct statsContext context; @@ -5858,6 +5879,8 @@ static int __iw_setint_getnone(struct net_device *dev, #ifdef CONFIG_HAS_EARLYSUSPEND v_U8_t nEnableSuspendOld; #endif + void *cookie; + struct hdd_request *request; ENTER(); pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); @@ -5952,47 +5975,42 @@ static int __iw_setint_getnone(struct net_device *dev, { case 0: //Full Power { - struct statsContext context; eHalStatus status = eHAL_STATUS_FAILURE; - - init_completion(&context.completion); - - context.pAdapter = pAdapter; - context.magic = POWER_CONTEXT_MAGIC; + static const struct hdd_request_params params = { + .priv_size = 0, + .timeout_ms = WLAN_WAIT_TIME_POWER, + }; if (NULL == hHal) return -EINVAL; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Request allocation failure")); + return VOS_STATUS_E_NOMEM; + } + cookie = hdd_request_cookie(request); + status = sme_RequestFullPower(WLAN_HDD_GET_HAL_CTX(pAdapter), - iw_power_callback_fn, &context, + iw_power_callback_func, cookie, eSME_FULL_PWR_NEEDED_BY_HDD); if (eHAL_STATUS_PMC_PENDING == status) { - int lrc = wait_for_completion_interruptible_timeout( - &context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_POWER)); - - if (lrc <= 0) - { + ret = hdd_request_wait_for_response(request); + if (ret) { hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: SME %s while requesting fullpower", - __func__, (0 == lrc) ? - "timeout" : "interrupt"); + FL("SME timeout while requesting bmps")); } } - /* either we have a response or we timed out. if we timed - out there is a race condition such that the callback - function could be executing at the same time we are. of - primary concern is if the callback function had already - verified the "magic" but had not yet set the completion - variable when a timeout occurred. we serialize these - activities by invalidating the magic while holding a - shared spinlock which will cause us to block if the - callback is currently executing */ - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); + + /* + * either we never sent a request, we sent a request and + * received a response or we sent a request and timed out. + * Regardless we are done with the request. + */ + hdd_request_put(request); hddLog(LOGE, "iwpriv Full Power completed"); break; @@ -6011,45 +6029,40 @@ static int __iw_setint_getnone(struct net_device *dev, break; case 3: //Request Bmps { - struct statsContext context; eHalStatus status = eHAL_STATUS_FAILURE; - - init_completion(&context.completion); - - context.pAdapter = pAdapter; - context.magic = POWER_CONTEXT_MAGIC; + static const struct hdd_request_params params = { + .priv_size = 0, + .timeout_ms = WLAN_WAIT_TIME_POWER, + }; if (NULL == hHal) return -EINVAL; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Request allocation failure")); + return VOS_STATUS_E_NOMEM; + } + cookie = hdd_request_cookie(request); + status = sme_RequestBmps(WLAN_HDD_GET_HAL_CTX(pAdapter), - iw_power_callback_fn, &context); + iw_power_callback_func, cookie); if (eHAL_STATUS_PMC_PENDING == status) { - int lrc = wait_for_completion_interruptible_timeout( - &context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_POWER)); - if (lrc <= 0) - { + ret = hdd_request_wait_for_response(request); + if (ret) { hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: SME %s while requesting BMPS", - __func__, (0 == lrc) ? "timeout" : - "interrupt"); + FL("SME timeout while requesting fullpower")); } } - /* either we have a response or we timed out. if we - timed out there is a race condition such that the - callback function could be executing at the same - time we are. of primary concern is if the callback - function had already verified the "magic" but had - not yet set the completion variable when a timeout - occurred. we serialize these activities by - invalidating the magic while holding a shared - spinlock which will cause us to block if the - callback is currently executing */ - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); + + /* + * either we never sent a request, we sent a request and + * received a response or we sent a request and timed out. + * Regardless we are done with the request. + */ + hdd_request_put(request); hddLog(LOGE, "iwpriv Request BMPS completed"); break; From 731ebf70a25ab2cdc32d2626dcebe60fe3b09481 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Fri, 6 Apr 2018 14:34:49 +0530 Subject: [PATCH 336/508] wlan: Use request manager for enter bmps propagation from qcacld-2.0 to prima We are transitioning to the new request manager framework. Change wlan_hdd_enter_bmps to this framework. Change-Id: Ia1ac62b97230a3e4240a039b5c8280c051245579 CRs-Fixed: 2213540 --- CORE/HDD/src/wlan_hdd_wext.c | 113 +++++++++-------------------------- 1 file changed, 29 insertions(+), 84 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 2fcdded2afa5c..c08dd6e8f0fac 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -3287,55 +3287,6 @@ static int iw_get_range(struct net_device *dev, return ret; } -/* Callback function registered with PMC to know status of PMC request */ -static void iw_power_callback_fn (void *pContext, eHalStatus status) -{ - struct statsContext *pStatsContext; - - if (NULL == pContext) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Bad param, pContext [%pK]", - __func__, pContext); - return; - } - - pStatsContext = (struct statsContext *)pContext; - - /* there is a race condition that exists between this callback - function and the caller since the caller could time out either - before or while this code is executing. we use a spinlock to - serialize these actions */ - spin_lock(&hdd_context_lock); - - if (POWER_CONTEXT_MAGIC != pStatsContext->magic) - { - /* the caller presumably timed out so there is nothing we can do */ - spin_unlock(&hdd_context_lock); - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, magic [%08x]", - __func__, pStatsContext->magic); - - if (ioctl_debug) - { - pr_info("%s: Invalid context, magic [%08x]\n", - __func__, pStatsContext->magic); - } - return; - } - - /* context is valid so caller is still waiting */ - - /* paranoia: invalidate the magic */ - pStatsContext->magic = 0; - - /* notify the caller */ - complete(&pStatsContext->completion); - - /* serialization is complete */ - spin_unlock(&hdd_context_lock); -} - /* Callback function for tx per hit */ void hdd_tx_per_hit_cb (void *pCallbackContext) { @@ -4097,10 +4048,16 @@ static void iw_power_callback_func(void *context, eHalStatus status) VOS_STATUS wlan_hdd_enter_bmps(hdd_adapter_t *pAdapter, int mode) { - struct statsContext context; eHalStatus status; hdd_context_t *pHddCtx; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + int ret; + void *cookie; + struct hdd_request *request; + static const struct hdd_request_params params = { + .priv_size = 0, + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; if (NULL == pAdapter) { @@ -4116,32 +4073,31 @@ VOS_STATUS wlan_hdd_enter_bmps(hdd_adapter_t *pAdapter, int mode) return VOS_STATUS_E_FAILURE; } - init_completion(&context.completion); + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + return VOS_STATUS_E_NOMEM; + } + cookie = hdd_request_cookie(request); - context.pAdapter = pAdapter; - context.magic = POWER_CONTEXT_MAGIC; if (DRIVER_POWER_MODE_ACTIVE == mode) { hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s:Wlan driver Entering " "Full Power", __func__); status = sme_RequestFullPower(WLAN_HDD_GET_HAL_CTX(pAdapter), - iw_power_callback_fn, &context, + iw_power_callback_func, cookie, eSME_FULL_PWR_NEEDED_BY_HDD); // Enter Full power command received from GUI this means we are disconnected // Set PMC remainInPowerActiveTillDHCP flag to disable auto BMPS entry by PMC sme_SetDHCPTillPowerActiveFlag(pHddCtx->hHal, TRUE); if (eHAL_STATUS_PMC_PENDING == status) { - /* request was sent -- wait for the response */ - int lrc = wait_for_completion_interruptible_timeout( - &context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_POWER)); - - if (lrc <= 0) + ret = hdd_request_wait_for_response(request); + if (ret) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while requesting fullpower ", - __func__, (0 == lrc) ? "timeout" : "interrupt"); + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timeout while requesting fullpower")); } } } @@ -4173,19 +4129,16 @@ VOS_STATUS wlan_hdd_enter_bmps(hdd_adapter_t *pAdapter, int mode) sme_SetDHCPTillPowerActiveFlag(WLAN_HDD_GET_HAL_CTX(pAdapter), FALSE); status = sme_RequestBmps(WLAN_HDD_GET_HAL_CTX(pAdapter), - iw_power_callback_fn, &context); + iw_power_callback_func, cookie); if (eHAL_STATUS_PMC_PENDING == status) { /* request was sent -- wait for the response */ - int lrc = wait_for_completion_interruptible_timeout( - &context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_POWER)); - if (lrc <= 0) + ret = hdd_request_wait_for_response(request); + if (ret) { hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: SME %s while requesting BMPS", - __func__, (0 == lrc) ? "timeout" : "interrupt"); - } + FL("SME timeout while requesting bmps")); + } } } else @@ -4195,20 +4148,12 @@ VOS_STATUS wlan_hdd_enter_bmps(hdd_adapter_t *pAdapter, int mode) } } - /* either we never sent a request, we sent a request and received a - response or we sent a request and timed out. if we never sent a - request or if we sent a request and got a response, we want to - clear the magic out of paranoia. if we timed out there is a - race condition such that the callback function could be - executing at the same time we are. of primary concern is if the - callback function had already verified the "magic" but had not - yet set the completion variable when a timeout occurred. we - serialize these activities by invalidating the magic while - holding a shared spinlock which will cause us to block if the - callback is currently executing */ - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); + /* + * either we never sent a request, we sent a request and received a + * response or we sent a request and timed out. Regardless we are + * done with the request. + */ + hdd_request_put(request); return VOS_STATUS_SUCCESS; } From a88659ecdcc78a1710ba5c1f44e4b709a639c626 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Mon, 9 Apr 2018 18:45:14 +0530 Subject: [PATCH 337/508] wlan: Use request manager for GET_ROAM_RSSI We are transitioning to the new request manager framework. Change wlan_hdd_get_roam_rssi() to this framework. Change-Id: Ib217939266dbd70e710e6ec2f1570f634e9db7b3 CRs-Fixed: 2215440 --- CORE/HDD/src/wlan_hdd_wext.c | 122 +++++++++-------------------------- 1 file changed, 31 insertions(+), 91 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index c08dd6e8f0fac..ed07452c9ec7c 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -1215,78 +1215,19 @@ VOS_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, v_S7_t *snr) #if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) -static void hdd_GetRoamRssiCB( v_S7_t rssi, tANI_U32 staId, void *pContext ) -{ - struct statsContext *pStatsContext; - hdd_adapter_t *pAdapter; - if (ioctl_debug) - { - pr_info("%s: rssi [%d] STA [%d] pContext [%pK]\n", - __func__, (int)rssi, (int)staId, pContext); - } - - if (NULL == pContext) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Bad param, pContext [%pK]", - __func__, pContext); - return; - } - - pStatsContext = pContext; - pAdapter = pStatsContext->pAdapter; - - /* there is a race condition that exists between this callback - function and the caller since the caller could time out either - before or while this code is executing. we use a spinlock to - serialize these actions */ - spin_lock(&hdd_context_lock); - - if ((NULL == pAdapter) || (RSSI_CONTEXT_MAGIC != pStatsContext->magic)) - { - /* the caller presumably timed out so there is nothing we can do */ - spin_unlock(&hdd_context_lock); - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter [%pK] magic [%08x]", - __func__, pAdapter, pStatsContext->magic); - if (ioctl_debug) - { - pr_info("%s: Invalid context, pAdapter [%pK] magic [%08x]\n", - __func__, pAdapter, pStatsContext->magic); - } - return; - } - - /* context is valid so caller is still waiting */ - - /* paranoia: invalidate the magic */ - pStatsContext->magic = 0; - - /* copy over the rssi.FW will return RSSI as -100 - * if there are no samples to calculate the average - * RSSI - */ - if (rssi != -100) - pAdapter->rssi = rssi; - - if (pAdapter->rssi > 0) - pAdapter->rssi = 0; - /* notify the caller */ - complete(&pStatsContext->completion); - - /* serialization is complete */ - spin_unlock(&hdd_context_lock); -} - - - VOS_STATUS wlan_hdd_get_roam_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value) { - struct statsContext context; hdd_context_t *pHddCtx = NULL; hdd_station_ctx_t *pHddStaCtx = NULL; eHalStatus hstatus; - long lrc; + int ret; + void *cookie; + struct hdd_request *request; + struct rssi_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; if (NULL == pAdapter) { @@ -1321,14 +1262,17 @@ VOS_STATUS wlan_hdd_get_roam_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value) return VOS_STATUS_SUCCESS; } - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = RSSI_CONTEXT_MAGIC; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + return VOS_STATUS_E_NOMEM; + } + cookie = hdd_request_cookie(request); - hstatus = sme_GetRoamRssi(pHddCtx->hHal, hdd_GetRoamRssiCB, + hstatus = sme_GetRoamRssi(pHddCtx->hHal, hdd_get_rssi_cb, pHddStaCtx->conn_info.staId[ 0 ], pHddStaCtx->conn_info.bssId, - &context, pHddCtx->pvosContext); + cookie, pHddCtx->pvosContext); if (eHAL_STATUS_SUCCESS != hstatus) { hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to retrieve RSSI", @@ -1337,31 +1281,27 @@ VOS_STATUS wlan_hdd_get_roam_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value) } else { + ret = hdd_request_wait_for_response(request); + if(ret) /* request was sent -- wait for the response */ - lrc = wait_for_completion_interruptible_timeout(&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - if (lrc <= 0) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while retrieving RSSI", - __func__, (0 == lrc) ? "timeout" : "interrupt"); + hddLog(VOS_TRACE_LEVEL_ERROR, + FL(" SME timeout while retrieving RSSI")); /* we'll now returned a cached value below */ } + else + { + priv = hdd_request_priv(request); + pAdapter->rssi = priv->rssi; + } } - /* either we never sent a request, we sent a request and received a - response or we sent a request and timed out. if we never sent a - request or if we sent a request and got a response, we want to - clear the magic out of paranoia. if we timed out there is a - race condition such that the callback function could be - executing at the same time we are. of primary concern is if the - callback function had already verified the "magic" but had not - yet set the completion variable when a timeout occurred. we - serialize these activities by invalidating the magic while - holding a shared spinlock which will cause us to block if the - callback is currently executing */ - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); + /* + * either we never sent a request, we sent a request and received a + * response or we sent a request and timed out. Regardless we are + * done with the request. + */ + hdd_request_put(request); *rssi_value = pAdapter->rssi; From 308d99d82887220ce34f05f1b90137bac9d556cb Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Mon, 9 Apr 2018 19:14:26 +0530 Subject: [PATCH 338/508] wlan: Use request manager for GET_ANTENA_DIVERSITY_SELECTION We are transitioning to the new request manager framework. Change wlan_hdd_get_current_antenna_index() and hdd_get_current_antenna_index() to this framework. Change-Id: Ibf68072ff93e2916d2bd39a0f91f7f2de17f2492 CRs-Fixed: 2215444 --- CORE/HDD/src/wlan_hdd_wext.c | 103 +++++++++++++++++------------------ 1 file changed, 50 insertions(+), 53 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index ed07452c9ec7c..5c5e7d8cb1fee 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -6692,39 +6692,27 @@ static int iw_setchar_getnone(struct net_device *dev, return ret; } -static void hdd_GetCurrentAntennaIndex(int antennaId, void *pContext) -{ - struct statsContext *context; - hdd_adapter_t *pAdapter; - - if (NULL == pContext) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Bad param, pContext [%pK]", - __func__, pContext); - return; - } +struct get_antenna_idx_priv { + int antenna_id; +}; - context = pContext; - pAdapter = context->pAdapter; +static void hdd_get_current_antenna_index_cb(int antenna_id, void *context) +{ + struct hdd_request *request; + struct get_antenna_idx_priv *priv; - spin_lock(&hdd_context_lock); + request = hdd_request_get(context); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); + return; + } - if ((NULL == pAdapter) || (ANTENNA_CONTEXT_MAGIC != context->magic)) - { - /* the caller presumably timed out so there is nothing we can do */ - spin_unlock(&hdd_context_lock); - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter [%pK] magic [%08x]", - __func__, pAdapter, context->magic); - return; - } + priv = hdd_request_priv(request); + priv->antenna_id = antenna_id; - context->magic = 0; - pAdapter->antennaIndex = antennaId; + hdd_request_complete(request); + hdd_request_put(request); - complete(&context->completion); - spin_unlock(&hdd_context_lock); } static VOS_STATUS wlan_hdd_get_current_antenna_index(hdd_adapter_t *pAdapter, @@ -6732,8 +6720,14 @@ static VOS_STATUS wlan_hdd_get_current_antenna_index(hdd_adapter_t *pAdapter, { hdd_context_t *pHddCtx; eHalStatus halStatus; - struct statsContext context; - long lrc; + int ret; + void *cookie; + struct hdd_request *request; + struct get_antenna_idx_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; ENTER(); if (NULL == pAdapter) @@ -6754,46 +6748,49 @@ static VOS_STATUS wlan_hdd_get_current_antenna_index(hdd_adapter_t *pAdapter, __func__); return VOS_STATUS_E_NOSUPPORT; } - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = ANTENNA_CONTEXT_MAGIC; + + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + return VOS_STATUS_E_NOMEM; + } + cookie = hdd_request_cookie(request); halStatus = sme_GetCurrentAntennaIndex(pHddCtx->hHal, - hdd_GetCurrentAntennaIndex, - &context, pAdapter->sessionId); + hdd_get_current_antenna_index_cb, + cookie, pAdapter->sessionId); if (eHAL_STATUS_SUCCESS != halStatus) { - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to retrieve Antenna Index", __func__); /* we'll returned a cached value below */ *antennaIndex = -1; - return VOS_STATUS_E_FAILURE; } else { /* request was sent -- wait for the response */ - lrc = wait_for_completion_interruptible_timeout(&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - if (lrc <= 0) + if (ret) { - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); - hddLog(VOS_TRACE_LEVEL_ERROR, "%s:SME %s while retrieving Antenna" - " Index", - __func__, (0 == lrc) ? "timeout" : "interrupt"); + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timeout while retrieving Antenna Index")); *antennaIndex = -1; - return VOS_STATUS_E_FAILURE; + } + else + { + priv = hdd_request_priv(request); + pAdapter->antennaIndex = priv->antenna_id; } } - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); - *antennaIndex = pAdapter->antennaIndex; + if (*antennaIndex != -1) + *antennaIndex = pAdapter->antennaIndex; + + /* + * either we never sent a request, we sent a request and received a + * response or we sent a request and timed out. Regardless we are + * done with the request. + */ + hdd_request_put(request); EXIT(); return VOS_STATUS_SUCCESS; From 28a7b34b1b0b6b859cb8079d178ffbd2568b591d Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Sirasanagandla Date: Thu, 12 Apr 2018 14:26:34 +0530 Subject: [PATCH 339/508] wlan: Add support to build wearable targets for msm-4.9 kernel When upgrading wearable targets to support msm-4.9 kernel, if WLAN_BLD_DIR is a relative path then build is failing with the error unable to de-refer header files defined locally. To avoid this, use absolute path for WLAN_BLD_DIR based on ANDROID_BUILD_TOP. Change-Id: Ia3e5691d83dbc6a2bbe84e63cea48e2267b64503 CRs-Fixed: 2225760 --- Android.mk | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Android.mk b/Android.mk index e43af06fd00cf..e582b543b9374 100644 --- a/Android.mk +++ b/Android.mk @@ -57,10 +57,14 @@ ifneq ($(ANDROID_BUILD_TOP),) else WLAN_BLD_DIR := vendor/qcom/opensource/wlan endif +else +ifneq ($(ANDROID_BUILD_TOP),) + WLAN_BLD_DIR := $(ANDROID_BUILD_TOP)/device/qcom/msm8909w/opensource/wlan else WLAN_BLD_DIR := device/qcom/msm8909w/opensource/wlan endif endif +endif # DLKM_DIR was moved for JELLY_BEAN (PLATFORM_SDK 16) ifeq (1,$(filter 1,$(shell echo "$$(( $(PLATFORM_SDK_VERSION) >= 16 ))" ))) @@ -124,11 +128,9 @@ endif # This is set once per LOCAL_PATH, not per (kernel) module -ifneq ($(TARGET_SUPPORTS_WEARABLES),true) ifneq ($(ANDROID_BUILD_TOP),) KBUILD_OPTIONS := WLAN_ROOT=$(WLAN_BLD_DIR)/prima endif -endif ifeq ($(KBUILD_OPTIONS),) KBUILD_OPTIONS := WLAN_ROOT=$(KERNEL_TO_BUILD_ROOT_OFFSET)$(WLAN_BLD_DIR)/prima From c76f065283bbf4656c3f6a1e0ab0df86b5102b43 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Fri, 6 Apr 2018 17:31:52 +0530 Subject: [PATCH 340/508] wlan: sap: Use request manager for Class A stats We are transitioning to the new request manager framework. Change wlan_hdd_get_classAstats_for_station and hdd_GetClassA_statisticsCB() to this framework. Change-Id: I90724ff672bfea7edbba66eb32371dca71bd8681 CRs-Fixed: 2207695 --- CORE/HDD/inc/wlan_hdd_wext.h | 7 +++- CORE/HDD/src/wlan_hdd_hostapd.c | 59 +++++++++++++++++------------- CORE/HDD/src/wlan_hdd_wext.c | 65 --------------------------------- 3 files changed, 39 insertions(+), 92 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_wext.h b/CORE/HDD/inc/wlan_hdd_wext.h index 1a58dc027fdbb..ec12057123d99 100644 --- a/CORE/HDD/inc/wlan_hdd_wext.h +++ b/CORE/HDD/inc/wlan_hdd_wext.h @@ -343,6 +343,11 @@ typedef struct ccp_freq_chan_map_s{ v_U32_t chan; }hdd_freq_chan_map_t; +struct stats_class_a_ctx { + tCsrGlobalClassAStatsInfo class_a_stats; +}; + + #define wlan_hdd_get_wps_ie_ptr(ie, ie_len) \ wlan_hdd_get_vendor_oui_ie_ptr(WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE, ie, ie_len) @@ -421,7 +426,7 @@ extern int hdd_priv_get_data(struct iw_point *p_priv_data, extern void *mem_alloc_copy_from_user_helper(const void *wrqu_data, size_t len); void hdd_clearRoamProfileIe( hdd_adapter_t *pAdapter); -void hdd_GetClassA_statisticsCB(void *pStats, void *pContext); +void hdd_get_class_a_statistics_cb(void *stats, void *context); VOS_STATUS wlan_hdd_check_ula_done(hdd_adapter_t *pAdapter); diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index 9856f96d420ff..463919a03e095 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -81,6 +81,7 @@ #include "wniCfg.h" #include #include "wlan_hdd_hostapd.h" +#include "wlan_hdd_request_manager.h" #ifdef FEATURE_WLAN_CH_AVOID #include "wcnss_wlan.h" @@ -4882,8 +4883,15 @@ static int iw_set_ap_genie(struct net_device *dev, static VOS_STATUS wlan_hdd_get_classAstats_for_station(hdd_adapter_t *pAdapter, u8 staid) { eHalStatus hstatus; - long lrc; - struct statsContext context; + int ret; + void *cookie; + struct hdd_request *request; + struct stats_class_a_ctx *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; + if (NULL == pAdapter) { @@ -4891,17 +4899,21 @@ static VOS_STATUS wlan_hdd_get_classAstats_for_station(hdd_adapter_t *pAdapter, return VOS_STATUS_E_FAULT; } - init_completion(&context.completion); - context.pAdapter = pAdapter; - context.magic = STATS_CONTEXT_MAGIC; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + return VOS_STATUS_E_NOMEM; + } + cookie = hdd_request_cookie(request); + hstatus = sme_GetStatistics( WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_HDD, SME_GLOBAL_CLASSA_STATS, - hdd_GetClassA_statisticsCB, + hdd_get_class_a_statistics_cb, 0, // not periodic FALSE, //non-cached results staid, - &context); + cookie); if (eHAL_STATUS_SUCCESS != hstatus) { hddLog(VOS_TRACE_LEVEL_ERROR, @@ -4910,30 +4922,25 @@ static VOS_STATUS wlan_hdd_get_classAstats_for_station(hdd_adapter_t *pAdapter, } else { - lrc = wait_for_completion_interruptible_timeout(&context.completion, - msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); - if (lrc <= 0) + ret = hdd_request_wait_for_response(request); + if (ret) { hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: SME %s while retrieving link speed", - __func__, (0 == lrc) ? "timeout" : "interrupt"); + FL("SME timeout while retrieving link speed")); + } + else + { + priv = hdd_request_priv(request); + pAdapter->hdd_stats.ClassA_stat = priv->class_a_stats; } } - /* either we never sent a request, we sent a request and received a - response or we sent a request and timed out. if we never sent a - request or if we sent a request and got a response, we want to - clear the magic out of paranoia. if we timed out there is a - race condition such that the callback function could be - executing at the same time we are. of primary concern is if the - callback function had already verified the "magic" but had not - yet set the completion variable when a timeout occurred. we - serialize these activities by invalidating the magic while - holding a shared spinlock which will cause us to block if the - callback is currently executing */ - spin_lock(&hdd_context_lock); - context.magic = 0; - spin_unlock(&hdd_context_lock); + /* + * either we never sent a request, we sent a request and received a + * response or we sent a request and timed out. Regardless we are + * done with the request. + */ + hdd_request_put(request); return VOS_STATUS_SUCCESS; } diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 5c5e7d8cb1fee..2fd9c3b3798ee 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -3244,71 +3244,6 @@ void hdd_tx_per_hit_cb (void *pCallbackContext) wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, tx_fail); } -void hdd_GetClassA_statisticsCB(void *pStats, void *pContext) -{ - struct statsContext *pStatsContext; - tCsrGlobalClassAStatsInfo *pClassAStats; - hdd_adapter_t *pAdapter; - - if (ioctl_debug) - { - pr_info("%s: pStats [%pK] pContext [%pK]\n", - __func__, pStats, pContext); - } - - if ((NULL == pStats) || (NULL == pContext)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Bad param, pStats [%pK] pContext [%pK]", - __func__, pStats, pContext); - return; - } - - pClassAStats = pStats; - pStatsContext = pContext; - pAdapter = pStatsContext->pAdapter; - - /* there is a race condition that exists between this callback - function and the caller since the caller could time out either - before or while this code is executing. we use a spinlock to - serialize these actions */ - spin_lock(&hdd_context_lock); - - if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic)) - { - /* the caller presumably timed out so there is nothing we can do */ - spin_unlock(&hdd_context_lock); - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter [%pK] magic [%08x]", - __func__, pAdapter, pStatsContext->magic); - if (ioctl_debug) - { - pr_info("%s: Invalid context, pAdapter [%pK] magic [%08x]\n", - __func__, pAdapter, pStatsContext->magic); - } - return; - } - - /* context is valid so caller is still waiting */ - - /* paranoia: invalidate the magic */ - pStatsContext->magic = 0; - - /* copy over the stats. do so as a struct copy */ - pAdapter->hdd_stats.ClassA_stat = *pClassAStats; - - /* notify the caller */ - complete(&pStatsContext->completion); - - /* serialization is complete */ - spin_unlock(&hdd_context_lock); - -} - -struct stats_class_a_ctx { - tCsrGlobalClassAStatsInfo class_a_stats; -}; - void hdd_get_class_a_statistics_cb(void *stats, void *context) { struct hdd_request *request; From e856bc2820632edab8e20084ab6a5b9b643c9d84 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Wed, 11 Apr 2018 15:35:36 +0530 Subject: [PATCH 341/508] wlan: Use request manager while requesting fw mem dump We are transitioning to the new request manager framework. Change wlan_hdd_fw_mem_dump_req() and wlan_hdd_fw_mem_dump_cb to this framework. Change-Id: Ia9c1c43a837d391716cc4ac82a47986223854c15 CRs-Fixed: 2215453 --- CORE/HDD/inc/wlan_hdd_main.h | 4 +- CORE/HDD/src/wlan_hdd_main.c | 135 +++++++++++-------- CORE/SVC/src/logging/wlan_logging_sock_svc.c | 5 +- 3 files changed, 79 insertions(+), 65 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index 2e3b606bf9bfc..eca0d144f60fa 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -1483,13 +1483,13 @@ struct hdd_fw_mem_dump_req_ctx { * callback type to check fw mem dump request.Called from SVC * context and update status in HDD. */ -typedef void (*hdd_fw_mem_dump_req_cb)(struct hdd_fw_mem_dump_req_ctx *); +typedef void (*hdd_fw_mem_dump_req_cb)(void *context); int memdump_init(void); int memdump_deinit(void); void wlan_hdd_fw_mem_dump_cb(void *,tAniFwrDumpRsp *); int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx); -void wlan_hdd_fw_mem_dump_req_cb(struct hdd_fw_mem_dump_req_ctx*); +void wlan_hdd_fw_mem_dump_req_cb(void *context); #ifdef WLAN_FEATURE_LINK_LAYER_STATS /** * struct hdd_ll_stats_context - hdd link layer stats context diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index b3afa6f0f759a..62c5f4cd3f9c3 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -15772,6 +15772,10 @@ static const struct file_operations memdump_fops = { read: memdump_read }; +struct fw_mem_dump_priv { + uint32_t status; +}; + /* * wlan_hdd_fw_mem_dump_cb : callback for Fw mem dump request * To be passed by HDD to WDA and called upon receiving of response @@ -15780,34 +15784,42 @@ static const struct file_operations memdump_fops = { * @dump_rsp : dump response from HAL * Returns none */ -void wlan_hdd_fw_mem_dump_cb(void *fwMemDumpReqContext, +void wlan_hdd_fw_mem_dump_cb(void *context, tAniFwrDumpRsp *dump_rsp) { - struct hdd_fw_mem_dump_req_ctx *pHddFwMemDumpCtx = (struct hdd_fw_mem_dump_req_ctx *)fwMemDumpReqContext; + struct hdd_request *request; + struct fw_mem_dump_priv *priv; - ENTER(); - spin_lock(&hdd_context_lock); - if(!pHddFwMemDumpCtx || (FW_MEM_DUMP_MAGIC != pHddFwMemDumpCtx->magic)) { - spin_unlock(&hdd_context_lock); - return; - } - /* report the status to requesting function and free mem.*/ - if (dump_rsp->dump_status != eHAL_STATUS_SUCCESS) { - hddLog(LOGE, FL("fw dump request declined by fwr")); - //set the request completion variable - complete(&(pHddFwMemDumpCtx->req_completion)); - //Free the allocated fwr dump - wlan_free_fwr_mem_dump_buffer(); - wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE); - } - else { - hddLog(LOG1, FL("fw dump request accepted by fwr")); - /* register the HDD callback which will be called by SVC */ - wlan_set_svc_fw_mem_dump_req_cb((void*)wlan_hdd_fw_mem_dump_req_cb,(void*)pHddFwMemDumpCtx); - } - spin_unlock(&hdd_context_lock); - EXIT(); + request = hdd_request_get(context); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); + return; + } + ENTER(); + + priv = hdd_request_priv(request); + priv->status = dump_rsp->dump_status; + + /* report the status to requesting function and free mem.*/ + if (dump_rsp->dump_status != eHAL_STATUS_SUCCESS) { + hddLog(LOGE, FL("fw dump request declined by fwr")); + //set the request completion variable + hdd_request_complete(request); + //Free the allocated fwr dump + wlan_free_fwr_mem_dump_buffer(); + wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE); + } else { + hddLog(LOG1, FL("fw dump request accepted by fwr")); + /* register the HDD callback which will be called by SVC */ + wlan_set_svc_fw_mem_dump_req_cb( + (void*)wlan_hdd_fw_mem_dump_req_cb, + context); + } + + hdd_request_put(request); + + EXIT(); } /** @@ -15942,9 +15954,16 @@ int memdump_deinit(void) int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx) { tAniFwrDumpReq fw_mem_dump_req={0}; - struct hdd_fw_mem_dump_req_ctx fw_mem_dump_ctx; eHalStatus status = eHAL_STATUS_FAILURE; - int ret=0, result; + int ret=0, dump_status; + void *cookie; + struct hdd_request *request; + struct fw_mem_dump_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = FW_MEM_DUMP_TIMEOUT_MS, + }; + ENTER(); /*Check whether a dump request is already going on @@ -15964,12 +15983,16 @@ int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx) hddLog(LOGE, FL("Fwr mem Allocation failed")); return -ENOMEM; } - init_completion(&fw_mem_dump_ctx.req_completion); - fw_mem_dump_ctx.magic = FW_MEM_DUMP_MAGIC; - fw_mem_dump_ctx.status = false; + + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + return VOS_STATUS_E_NOMEM; + } + cookie = hdd_request_cookie(request); fw_mem_dump_req.fwMemDumpReqCallback = wlan_hdd_fw_mem_dump_cb; - fw_mem_dump_req.fwMemDumpReqContext = &fw_mem_dump_ctx; + fw_mem_dump_req.fwMemDumpReqContext = cookie; status = sme_FwMemDumpReq(pHddCtx->hHal, &fw_mem_dump_req); if(eHAL_STATUS_SUCCESS != status) { @@ -15980,21 +16003,20 @@ int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx) goto cleanup; } /*wait for fw mem dump completion to send event to userspace*/ - result = - wait_for_completion_timeout(&fw_mem_dump_ctx.req_completion, - msecs_to_jiffies(FW_MEM_DUMP_TIMEOUT_MS)); - if (0 >= result ) + ret = hdd_request_wait_for_response(request); + if (ret) { hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: fw_mem_dump_req timeout %d ", __func__,result); + "%s: fw_mem_dump_req timeout %d ", __func__,ret); ret = -ETIMEDOUT; + }else { + priv = hdd_request_priv(request); + dump_status = priv->status; } cleanup: - spin_lock(&hdd_context_lock); - fw_mem_dump_ctx.magic = 0; - if(!ret && !fw_mem_dump_ctx.status) + hdd_request_put(request); + if(!ret && !dump_status) ret = -EFAULT; - spin_unlock(&hdd_context_lock); EXIT(); return ret; @@ -16003,27 +16025,22 @@ int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx) /** * HDD callback which will be called by SVC to indicate mem dump completion. */ -void wlan_hdd_fw_mem_dump_req_cb(struct hdd_fw_mem_dump_req_ctx* pHddFwMemDumpCtx) +void wlan_hdd_fw_mem_dump_req_cb(void *context) { - if (!pHddFwMemDumpCtx) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: HDD context not valid ", __func__); - return; - } - spin_lock(&hdd_context_lock); - /* check the req magic and set status */ - if (pHddFwMemDumpCtx->magic == FW_MEM_DUMP_MAGIC) - { - pHddFwMemDumpCtx->status = true; - //signal the completion - complete(&(pHddFwMemDumpCtx->req_completion)); - } - else - { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: fw mem dump request possible timeout ", __func__); - } - spin_unlock(&hdd_context_lock); + struct hdd_request *request; + struct fw_mem_dump_priv *priv; + + request = hdd_request_get(context); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); + return; + } + + priv = hdd_request_priv(request); + priv->status = true; + + hdd_request_complete(request); + hdd_request_put(request); } void hdd_initialize_adapter_common(hdd_adapter_t *pAdapter) diff --git a/CORE/SVC/src/logging/wlan_logging_sock_svc.c b/CORE/SVC/src/logging/wlan_logging_sock_svc.c index ed5f63226981a..246a847c2cd56 100644 --- a/CORE/SVC/src/logging/wlan_logging_sock_svc.c +++ b/CORE/SVC/src/logging/wlan_logging_sock_svc.c @@ -1311,17 +1311,14 @@ static int wlan_logging_thread(void *Arg) * memdump complete. If it's null,then something is * not right. */ - if (gwlan_logging.fw_mem_dump_ctx.svc_fw_mem_dump_req_cb && - gwlan_logging.fw_mem_dump_ctx.svc_fw_mem_dump_req_cb_arg) { + if (gwlan_logging.fw_mem_dump_ctx.svc_fw_mem_dump_req_cb) { ((hdd_fw_mem_dump_req_cb) gwlan_logging.fw_mem_dump_ctx.svc_fw_mem_dump_req_cb)( - (struct hdd_fw_mem_dump_req_ctx*) gwlan_logging.fw_mem_dump_ctx.svc_fw_mem_dump_req_cb_arg); /*invalidate the callback pointers*/ spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock,flags); gwlan_logging.fw_mem_dump_ctx.svc_fw_mem_dump_req_cb = NULL; - gwlan_logging.fw_mem_dump_ctx.svc_fw_mem_dump_req_cb_arg = NULL; spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock,flags); } } From 1f59c248e69381607a233a6269df51f4036aa9d0 Mon Sep 17 00:00:00 2001 From: Vijay Kumar TM Date: Fri, 13 Apr 2018 17:04:00 +0530 Subject: [PATCH 342/508] mm-camera2:isp2: Release buffer lock after use At start axi stream, we are acquiring the buffer lock and releasing after completing the stream configuration operations. In case of live snapshot,this is causing the buffer operations to halt and leading to sof freeze. CRs-Fixed: 2149998 Change-Id: I7f57c8befc85c105a5690ac71e0276f42b9f1929 Signed-off-by: Meera Gande Signed-off-by: Vijay Kumar TM --- .../media/platform/msm/camera_v2/isp/msm_isp_axi_util.c | 6 +++++- .../media/platform/msm/camera_v2/isp/msm_isp_stats_util.c | 8 +++++++- drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c | 4 ---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 4b7f8017d6724..14b1d79ed53d2 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -2880,10 +2880,11 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev, vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id = 0; vfe_dev->axi_data.src_info[VFE_PIX_0].eof_id = 0; } - + mutex_lock(&vfe_dev->buf_mgr->lock); for (i = 0; i < stream_cfg_cmd->num_streams; i++) { if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]) >= VFE_AXI_SRC_MAX) { + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } stream_info = &axi_data->stream_info[ @@ -2893,6 +2894,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev, SRC_TO_INTF(stream_info->stream_src)].active; else { ISP_DBG("%s: invalid src info index\n", __func__); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } @@ -2906,6 +2908,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev, HANDLE_TO_IDX( stream_cfg_cmd->stream_handle[i])); spin_unlock_irqrestore(&stream_info->lock, flags); + mutex_unlock(&vfe_dev->buf_mgr->lock); return rc; } spin_unlock_irqrestore(&stream_info->lock, flags); @@ -2962,6 +2965,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev, } } } + mutex_unlock(&vfe_dev->buf_mgr->lock); msm_isp_update_stream_bandwidth(vfe_dev, stream_cfg_cmd->hw_state); vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev, vfe_dev->vfe_base, wm_reload_mask); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c index efe53cc6e3aca..c77944a0a047f 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -683,6 +683,8 @@ static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev, stream_cfg_cmd->num_streams); return -EINVAL; } + mutex_lock(&vfe_dev->buf_mgr->lock); + num_stats_comp_mask = vfe_dev->hw_info->stats_hw_info->num_stats_comp_mask; rc = vfe_dev->hw_info->vfe_ops.stats_ops.check_streams( @@ -695,6 +697,7 @@ static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev, if (idx >= vfe_dev->hw_info->stats_hw_info->num_stats_type) { pr_err("%s Invalid stats index %d", __func__, idx); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } @@ -710,11 +713,13 @@ static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev, pr_err("%s: comp grp %d exceed max %d\n", __func__, stream_info->composite_flag, num_stats_comp_mask); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } rc = msm_isp_init_stats_ping_pong_reg(vfe_dev, stream_info); if (rc < 0) { pr_err("%s: No buffer for stream%d\n", __func__, idx); + mutex_unlock(&vfe_dev->buf_mgr->lock); return rc; } if (!stream_info->composite_flag) @@ -739,6 +744,7 @@ static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev, stats_data->num_active_stream); } + mutex_unlock(&vfe_dev->buf_mgr->lock); if (vfe_dev->axi_data.src_info[VFE_PIX_0].active) { rc = msm_isp_stats_wait_for_cfg_done(vfe_dev); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 24bf22795bc95..2de68a4536720 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -886,9 +886,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, break; case VIDIOC_MSM_ISP_CFG_STREAM: mutex_lock(&vfe_dev->core_mutex); - mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_cfg_axi_stream(vfe_dev, arg); - mutex_unlock(&vfe_dev->buf_mgr->lock); mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_CFG_HW_STATE: @@ -1002,9 +1000,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, break; case VIDIOC_MSM_ISP_CFG_STATS_STREAM: mutex_lock(&vfe_dev->core_mutex); - mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_cfg_stats_stream(vfe_dev, arg); - mutex_unlock(&vfe_dev->buf_mgr->lock); mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_UPDATE_STATS_STREAM: From e05ac4aa2a9f3085b9ee5e91dc0378e2aeab4ecd Mon Sep 17 00:00:00 2001 From: Mao Jinlong Date: Thu, 12 Oct 2017 11:27:10 +0800 Subject: [PATCH 343/508] rtc: Disable alarm irq if alarm time is in the past If device is boot up by rtc alarm, the alarm irq will still be enabled and the alarm time is smaller than current rtc time before any alarm is set or canceled. If device is powered off now, it will boot up automatically as the alarm irq is enabled. So disable alarm irq if alarm is enabled and alarm time is in the past. CRs-Fixed: 2109666 Change-Id: Ie60bd1222a400cd45a6c5a385faa70190fbe7e3c Signed-off-by: Mao Jinlong --- drivers/rtc/interface.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 5b2717f5dafa7..b12f1694ad00d 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -394,6 +394,14 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) } EXPORT_SYMBOL_GPL(rtc_set_alarm); +static void rtc_alarm_disable(struct rtc_device *rtc) +{ + if (!rtc->ops || !rtc->ops->alarm_irq_enable) + return; + + rtc->ops->alarm_irq_enable(rtc->dev.parent, false); +} + /* Called once per device from rtc_device_register */ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) { @@ -421,7 +429,11 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) rtc->aie_timer.enabled = 1; timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); + } else if (alarm->enabled && (rtc_tm_to_ktime(now).tv64 >= + rtc->aie_timer.node.expires.tv64)){ + rtc_alarm_disable(rtc); } + mutex_unlock(&rtc->ops_lock); return err; } @@ -800,14 +812,6 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) return 0; } -static void rtc_alarm_disable(struct rtc_device *rtc) -{ - if (!rtc->ops || !rtc->ops->alarm_irq_enable) - return; - - rtc->ops->alarm_irq_enable(rtc->dev.parent, false); -} - /** * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue * @rtc rtc device From 1415acefe77fb165c8a635f213d015894f8d2736 Mon Sep 17 00:00:00 2001 From: Suman Mukherjee Date: Tue, 17 Apr 2018 08:33:38 +0530 Subject: [PATCH 344/508] msm: camera: enable eeprom functionality on 8909 Adding required changes to support multi module eeprom design. Change-Id: I1c927e1a12f3c850ef2ef3b6f4a953f13c12205e Signed-off-by: Vijay kumar Tumati --- .../msm/camera_v2/sensor/eeprom/msm_eeprom.c | 400 +++++++++++------- 1 file changed, 241 insertions(+), 159 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c index dd2f9192e32f7..cf181665604fc 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c +++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2016, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -14,6 +14,7 @@ #include #include #include +#include #include "msm_sd.h" #include "msm_cci.h" #include "msm_eeprom.h" @@ -24,6 +25,17 @@ DEFINE_MSM_MUTEX(msm_eeprom_mutex); #ifdef CONFIG_COMPAT static struct v4l2_file_operations msm_eeprom_v4l2_subdev_fops; +static void msm_eeprom_copy_power_settings_compat( + struct msm_sensor_power_setting_array*, + struct msm_sensor_power_setting_array32*); +static int eeprom_config_read_cal_data32(struct msm_eeprom_ctrl_t*, + void __user*); +static int eeprom_init_config32(struct msm_eeprom_ctrl_t*, void __user*); +static int msm_eeprom_config32(struct msm_eeprom_ctrl_t*, void __user*); +static long msm_eeprom_subdev_ioctl32(struct v4l2_subdev*, unsigned int, void*); +static long msm_eeprom_subdev_do_ioctl32(struct file*, unsigned int, void*); +static long msm_eeprom_subdev_fops_ioctl32(struct file*, unsigned int, + unsigned long); #endif /** @@ -768,6 +780,92 @@ static int msm_eeprom_close(struct v4l2_subdev *sd, return rc; } +static int msm_eeprom_get_dt_data(struct msm_eeprom_ctrl_t *e_ctrl) +{ + int rc = 0, i = 0; + struct msm_eeprom_board_info *eb_info; + struct msm_camera_power_ctrl_t *power_info = + &e_ctrl->eboard_info->power_info; + struct device_node *of_node = NULL; + struct msm_camera_gpio_conf *gconf = NULL; + int8_t gpio_array_size = 0; + uint16_t *gpio_array = NULL; + + eb_info = e_ctrl->eboard_info; + if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE) + of_node = e_ctrl->i2c_client. + spi_client->spi_master->dev.of_node; + else if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE) + of_node = e_ctrl->pdev->dev.of_node; + else + of_node = e_ctrl->i2c_client.client->dev.of_node; + + if (!of_node) { + pr_err("%s: %d of_node is NULL\n", __func__ , __LINE__); + return -ENOMEM; + } + rc = msm_camera_get_dt_vreg_data(of_node, &power_info->cam_vreg, + &power_info->num_vreg); + if (rc < 0) + return rc; + + if (e_ctrl->userspace_probe == 0) { + rc = msm_camera_get_dt_power_setting_data(of_node, + power_info->cam_vreg, power_info->num_vreg, + power_info); + if (rc < 0) + goto ERROR1; + } + + power_info->gpio_conf = kzalloc(sizeof(struct msm_camera_gpio_conf), + GFP_KERNEL); + if (!power_info->gpio_conf) { + rc = -ENOMEM; + goto ERROR2; + } + gconf = power_info->gpio_conf; + gpio_array_size = of_gpio_count(of_node); + CDBG("%s gpio count %d\n", __func__, gpio_array_size); + + if (gpio_array_size > 0) { + gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t), + GFP_KERNEL); + if (gpio_array == NULL) + goto ERROR3; + for (i = 0; i < gpio_array_size; i++) { + gpio_array[i] = of_get_gpio(of_node, i); + CDBG("%s gpio_array[%d] = %d\n", __func__, i, + gpio_array[i]); + } + + rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf, + gpio_array, gpio_array_size); + if (rc < 0) { + pr_err("%s failed %d\n", __func__, __LINE__); + goto ERROR4; + } + + rc = msm_camera_init_gpio_pin_tbl(of_node, gconf, + gpio_array, gpio_array_size); + if (rc < 0) { + pr_err("%s failed %d\n", __func__, __LINE__); + goto ERROR4; + } + kfree(gpio_array); + } + + return rc; +ERROR4: + kfree(gpio_array); +ERROR3: + kfree(power_info->gpio_conf); +ERROR2: + kfree(power_info->cam_vreg); +ERROR1: + kfree(power_info->power_setting); + return rc; +} + static const struct v4l2_subdev_internal_ops msm_eeprom_internal_ops = { .open = msm_eeprom_open, .close = msm_eeprom_close, @@ -785,111 +883,173 @@ static int msm_eeprom_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int rc = 0; + int j = 0; + uint32_t temp; + struct msm_eeprom_ctrl_t *e_ctrl = NULL; - CDBG("%s E\n", __func__); + struct msm_eeprom_board_info *eb_info = NULL; + struct device_node *of_node; + struct msm_camera_power_ctrl_t *power_info = NULL; + uint32_t cell_id; - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - pr_err("%s i2c_check_functionality failed\n", __func__); - goto probe_failure; - } + CDBG("%s E\n", __func__); e_ctrl = kzalloc(sizeof(*e_ctrl), GFP_KERNEL); if (!e_ctrl) { - pr_err("%s:%d kzalloc failed\n", __func__, __LINE__); return -ENOMEM; } e_ctrl->eeprom_v4l2_subdev_ops = &msm_eeprom_subdev_ops; e_ctrl->eeprom_mutex = &msm_eeprom_mutex; - CDBG("%s client = 0x%pK\n", __func__, client); - e_ctrl->eboard_info = (struct msm_eeprom_board_info *)(id->driver_data); - if (!e_ctrl->eboard_info) { - pr_err("%s:%d board info NULL\n", __func__, __LINE__); - rc = -EINVAL; - goto ectrl_free; - } e_ctrl->i2c_client.client = client; e_ctrl->cal_data.mapdata = NULL; e_ctrl->cal_data.map = NULL; e_ctrl->userspace_probe = 0; - e_ctrl->is_supported = 1; + e_ctrl->is_supported = 0; + of_node = e_ctrl->i2c_client.client->dev.of_node; + if (!of_node) { + pr_err("%s dev.of_node NULL\n", __func__); + rc = -EINVAL; + goto ectrl_free; + } - /* Set device type as I2C */ + /* Set device type as platform device */ e_ctrl->eeprom_device_type = MSM_CAMERA_I2C_DEVICE; e_ctrl->i2c_client.i2c_func_tbl = &msm_eeprom_qup_func_tbl; - if (e_ctrl->eboard_info->i2c_slaveaddr != 0) - e_ctrl->i2c_client.client->addr = - e_ctrl->eboard_info->i2c_slaveaddr; + e_ctrl->eboard_info = kzalloc(sizeof( + struct msm_eeprom_board_info), GFP_KERNEL); + if (e_ctrl->eboard_info == NULL) { + rc = -ENOMEM; + goto ectrl_free; + } + eb_info = e_ctrl->eboard_info; + power_info = &eb_info->power_info; + power_info->dev = &e_ctrl->i2c_client.client->dev; + /*Get clocks information*/ - rc = msm_camera_i2c_dev_get_clk_info( - &e_ctrl->i2c_client.client->dev, - &e_ctrl->eboard_info->power_info.clk_info, - &e_ctrl->eboard_info->power_info.clk_ptr, - &e_ctrl->eboard_info->power_info.clk_info_size); + rc = msm_camera_i2c_dev_get_clk_info(&e_ctrl->i2c_client.client->dev, + &power_info->clk_info, + &power_info->clk_ptr, + &power_info->clk_info_size); if (rc < 0) { pr_err("failed: msm_camera_get_clk_info rc %d", rc); - goto ectrl_free; + goto board_free; + } + + rc = of_property_read_u32(of_node, "cell-index", + &cell_id); + CDBG("cell-index %d, rc %d\n", cell_id, rc); + if (rc < 0) { + pr_err("failed rc %d\n", rc); + goto board_free; } + e_ctrl->subdev_id = cell_id; - /*IMPLEMENT READING PART*/ - /* Initialize sub device */ - v4l2_i2c_subdev_init(&e_ctrl->msm_sd.sd, - e_ctrl->i2c_client.client, + rc = of_property_read_string(of_node, "qcom,eeprom-name", + &eb_info->eeprom_name); + CDBG("%s qcom,eeprom-name %s, rc %d\n", __func__, + eb_info->eeprom_name, rc); + if (rc < 0) { + pr_err("%s failed %d\n", __func__, __LINE__); + e_ctrl->userspace_probe = 1; + } + + rc = msm_eeprom_get_dt_data(e_ctrl); + if (rc < 0) + goto board_free; + + if (e_ctrl->userspace_probe == 0) { + rc = of_property_read_u32(of_node, "qcom,slave-addr", + &temp); + if (rc < 0) { + pr_err("%s failed rc %d\n", __func__, rc); + goto board_free; + } + + rc = of_property_read_u32(of_node, "qcom,i2c-freq-mode", + &e_ctrl->i2c_freq_mode); + CDBG("qcom,i2c_freq_mode %d, rc %d\n", + e_ctrl->i2c_freq_mode, rc); + if (rc < 0) { + pr_err("%s qcom,i2c-freq-mode read fail. Setting to 0 %d\n", + __func__, rc); + e_ctrl->i2c_freq_mode = 0; + } + if (e_ctrl->i2c_freq_mode >= I2C_MAX_MODES) { + pr_err("%s:%d invalid i2c_freq_mode = %d\n", + __func__, __LINE__, e_ctrl->i2c_freq_mode); + e_ctrl->i2c_freq_mode = 0; + } + eb_info->i2c_slaveaddr = temp; + CDBG("qcom,slave-addr = 0x%X\n", eb_info->i2c_slaveaddr); + eb_info->i2c_freq_mode = e_ctrl->i2c_freq_mode; + + rc = msm_eeprom_parse_memory_map(of_node, &e_ctrl->cal_data); + if (rc < 0) + goto board_free; + + rc = msm_camera_power_up(power_info, e_ctrl->eeprom_device_type, + &e_ctrl->i2c_client); + if (rc) { + pr_err("failed rc %d\n", rc); + goto memdata_free; + } + rc = read_eeprom_memory(e_ctrl, &e_ctrl->cal_data); + if (rc < 0) { + pr_err("%s read_eeprom_memory failed\n", __func__); + goto power_down; + } + for (j = 0; j < e_ctrl->cal_data.num_data; j++) + CDBG("memory_data[%d] = 0x%X\n", j, + e_ctrl->cal_data.mapdata[j]); + + e_ctrl->is_supported |= msm_eeprom_match_crc(&e_ctrl->cal_data); + + rc = msm_camera_power_down(power_info, + e_ctrl->eeprom_device_type, &e_ctrl->i2c_client); + if (rc) { + pr_err("failed rc %d\n", rc); + goto memdata_free; + } + } else { + e_ctrl->is_supported = 1; + } + v4l2_subdev_init(&e_ctrl->msm_sd.sd, e_ctrl->eeprom_v4l2_subdev_ops); v4l2_set_subdevdata(&e_ctrl->msm_sd.sd, e_ctrl); e_ctrl->msm_sd.sd.internal_ops = &msm_eeprom_internal_ops; e_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + snprintf(e_ctrl->msm_sd.sd.name, + ARRAY_SIZE(e_ctrl->msm_sd.sd.name), "msm_eeprom"); media_entity_init(&e_ctrl->msm_sd.sd.entity, 0, NULL, 0); e_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV; e_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_EEPROM; msm_sd_register(&e_ctrl->msm_sd); - CDBG("%s success result=%d X\n", __func__, rc); - return rc; -ectrl_free: - kfree(e_ctrl); -probe_failure: - pr_err("%s failed! rc = %d\n", __func__, rc); - return rc; -} - -static int msm_eeprom_i2c_remove(struct i2c_client *client) -{ - struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct msm_eeprom_ctrl_t *e_ctrl; - if (!sd) { - pr_err("%s: Subdevice is NULL\n", __func__); - return 0; - } - - e_ctrl = (struct msm_eeprom_ctrl_t *)v4l2_get_subdevdata(sd); - if (!e_ctrl) { - pr_err("%s: eeprom device is NULL\n", __func__); - return 0; - } - - if (!e_ctrl->eboard_info) { - pr_err("%s: eboard_info is NULL\n", __func__); - return 0; - } +#ifdef CONFIG_COMPAT + msm_cam_copy_v4l2_subdev_fops(&msm_eeprom_v4l2_subdev_fops); + msm_eeprom_v4l2_subdev_fops.compat_ioctl32 = + msm_eeprom_subdev_fops_ioctl32; + e_ctrl->msm_sd.sd.devnode->fops = &msm_eeprom_v4l2_subdev_fops; +#endif - msm_camera_i2c_dev_put_clk_info(&e_ctrl->i2c_client.client->dev, - &e_ctrl->eboard_info->power_info.clk_info, - &e_ctrl->eboard_info->power_info.clk_ptr, - e_ctrl->eboard_info->power_info.clk_info_size); + e_ctrl->is_supported = (e_ctrl->is_supported << 1) | 1; + CDBG("%s X\n", __func__); + return rc; +power_down: + msm_camera_power_down(power_info, e_ctrl->eeprom_device_type, + &e_ctrl->i2c_client); +memdata_free: kfree(e_ctrl->cal_data.mapdata); kfree(e_ctrl->cal_data.map); - if (e_ctrl->eboard_info) { - kfree(e_ctrl->eboard_info->power_info.gpio_conf); - kfree(e_ctrl->eboard_info); - } - e_ctrl->cal_data.mapdata = NULL; +board_free: + kfree(e_ctrl->eboard_info); +ectrl_free: kfree(e_ctrl); - e_ctrl = NULL; + return rc; - return 0; } #define msm_eeprom_spi_parse_cmd(spic, str, name, out, size) \ @@ -944,93 +1104,6 @@ static int msm_eeprom_match_id(struct msm_eeprom_ctrl_t *e_ctrl) return 0; } -static int msm_eeprom_get_dt_data(struct msm_eeprom_ctrl_t *e_ctrl) -{ - int rc = 0, i = 0; - struct msm_eeprom_board_info *eb_info; - struct msm_camera_power_ctrl_t *power_info = - &e_ctrl->eboard_info->power_info; - struct device_node *of_node = NULL; - struct msm_camera_gpio_conf *gconf = NULL; - int8_t gpio_array_size = 0; - uint16_t *gpio_array = NULL; - - eb_info = e_ctrl->eboard_info; - if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE) - of_node = e_ctrl->i2c_client. - spi_client->spi_master->dev.of_node; - else if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE) - of_node = e_ctrl->pdev->dev.of_node; - - if (!of_node) { - pr_err("%s: %d of_node is NULL\n", __func__ , __LINE__); - return -ENOMEM; - } - rc = msm_camera_get_dt_vreg_data(of_node, &power_info->cam_vreg, - &power_info->num_vreg); - if (rc < 0) - return rc; - - if (e_ctrl->userspace_probe == 0) { - rc = msm_camera_get_dt_power_setting_data(of_node, - power_info->cam_vreg, power_info->num_vreg, - power_info); - if (rc < 0) - goto ERROR1; - } - - power_info->gpio_conf = kzalloc(sizeof(struct msm_camera_gpio_conf), - GFP_KERNEL); - if (!power_info->gpio_conf) { - rc = -ENOMEM; - goto ERROR2; - } - gconf = power_info->gpio_conf; - gpio_array_size = of_gpio_count(of_node); - CDBG("%s gpio count %d\n", __func__, gpio_array_size); - - if (gpio_array_size > 0) { - gpio_array = kzalloc(sizeof(uint16_t) * gpio_array_size, - GFP_KERNEL); - if (!gpio_array) { - pr_err("%s failed %d\n", __func__, __LINE__); - goto ERROR3; - } - for (i = 0; i < gpio_array_size; i++) { - gpio_array[i] = of_get_gpio(of_node, i); - CDBG("%s gpio_array[%d] = %d\n", __func__, i, - gpio_array[i]); - } - - rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf, - gpio_array, gpio_array_size); - if (rc < 0) { - pr_err("%s failed %d\n", __func__, __LINE__); - goto ERROR4; - } - - rc = msm_camera_init_gpio_pin_tbl(of_node, gconf, - gpio_array, gpio_array_size); - if (rc < 0) { - pr_err("%s failed %d\n", __func__, __LINE__); - goto ERROR4; - } - kfree(gpio_array); - } - - return rc; -ERROR4: - kfree(gpio_array); -ERROR3: - kfree(power_info->gpio_conf); -ERROR2: - kfree(power_info->cam_vreg); -ERROR1: - kfree(power_info->power_setting); - return rc; -} - - static int msm_eeprom_cmm_dts(struct msm_eeprom_board_info *eb_info, struct device_node *of_node) { @@ -1292,6 +1365,7 @@ static int msm_eeprom_spi_remove(struct spi_device *sdev) } #ifdef CONFIG_COMPAT + static void msm_eeprom_copy_power_settings_compat( struct msm_sensor_power_setting_array *ps, struct msm_sensor_power_setting_array32 *ps32) @@ -1573,7 +1647,6 @@ static long msm_eeprom_subdev_fops_ioctl32(struct file *file, unsigned int cmd, { return video_usercopy(file, cmd, arg, msm_eeprom_subdev_do_ioctl32); } - #endif static int msm_eeprom_platform_probe(struct platform_device *pdev) @@ -1828,16 +1901,25 @@ static struct platform_driver msm_eeprom_platform_driver = { }; static const struct i2c_device_id msm_eeprom_i2c_id[] = { - { "msm_eeprom", (kernel_ulong_t)NULL}, + { "qcom,eeprom", (kernel_ulong_t)NULL}, + { } +}; + +static const struct of_device_id msm_eeprom_i2c_dt_match[] = { + {.compatible = "qcom,eeprom"}, { } }; +MODULE_DEVICE_TABLE(of, msm_eeprom_i2c_dt_match); + static struct i2c_driver msm_eeprom_i2c_driver = { .id_table = msm_eeprom_i2c_id, .probe = msm_eeprom_i2c_probe, - .remove = msm_eeprom_i2c_remove, + .remove = __exit_p(msm_eeprom_i2c_remove), .driver = { - .name = "msm_eeprom", + .name = "qcom,eeprom", + .owner = THIS_MODULE, + .of_match_table = msm_eeprom_i2c_dt_match, }, }; From e110a0450b4dfc161bbff1efb9164c047d1e4c9a Mon Sep 17 00:00:00 2001 From: Dundi Raviteja Date: Wed, 18 Apr 2018 13:11:37 +0530 Subject: [PATCH 345/508] wlan: Start split scan in 5GHz mode if VOWIFIMODE is enabled Currently, split scan is supported only in 2.4GHz mode if VOWIFIMODE is enabled. Start split scan in 5GHz mode also if VOWIFIMODE is enabled and stop if VOWIFIMODE is diabled. Change-Id: I04139ea5ae7846ef2122e4e4e4797988e0c5c4b0 CRs-Fixed: 2226748 --- CORE/HDD/src/wlan_hdd_main.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 62c5f4cd3f9c3..22ea01b386a91 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -866,12 +866,16 @@ static int hdd_parse_setrmcactionperiod_command(tANI_U8 *pValue, return 0; } -/* - * hdd_set_vowifi_mode() - Process the VOWIFI command and invoke the SME api - * - * @hHal: context handler + +/** + * hdd_set_vowifi_mode() - Process VOWIFI command. + * @hdd_ctx: context handler * @enable: Value to be sent as a part of the VOWIFI command * + * Invoke the SME api if station is connected in 2.4 GHz band. + * Also start split scan if VOWIFIMODE and dynamic split scan + * both are enabled. + * Return: void */ void hdd_set_vowifi_mode(hdd_context_t *hdd_ctx, bool enable) @@ -885,20 +889,20 @@ void hdd_set_vowifi_mode(hdd_context_t *hdd_ctx, bool enable) sta_chan = hdd_get_operating_channel(hdd_ctx, WLAN_HDD_INFRA_STATION); - if (CSR_IS_CHANNEL_24GHZ(sta_chan)) { + if (CSR_IS_CHANNEL_24GHZ(sta_chan)) sme_set_vowifi_mode(hdd_ctx->hHal, enable); - if (enable && hdd_ctx->cfg_ini->dynSplitscan) { - hdd_ctx->is_vowifi_enabled = true; - hdd_ctx->issplitscan_enabled = TRUE; - sme_enable_disable_split_scan(hdd_ctx->hHal, - hdd_ctx->cfg_ini->nNumStaChanCombinedConc, - hdd_ctx->cfg_ini->nNumP2PChanCombinedConc); - } else { - hdd_ctx->is_vowifi_enabled = false; - } - } else { + else VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "VoWiFi command rejected as not connected in 2.4GHz"); + + if (enable && hdd_ctx->cfg_ini->dynSplitscan) { + hdd_ctx->is_vowifi_enabled = true; + hdd_ctx->issplitscan_enabled = TRUE; + sme_enable_disable_split_scan(hdd_ctx->hHal, + hdd_ctx->cfg_ini->nNumStaChanCombinedConc, + hdd_ctx->cfg_ini->nNumP2PChanCombinedConc); + } else { + hdd_ctx->is_vowifi_enabled = false; } } From 12db0e3007ba5b8c5e98bf65e3936ee635899ac2 Mon Sep 17 00:00:00 2001 From: gaurank kathpalia Date: Wed, 18 Apr 2018 12:38:40 +0530 Subject: [PATCH 346/508] wlan: Fix pointer dereference KW issues in connect path Fix KW issues which may cause pointer deference in multiple paths Change-Id: I2c469be3b91eca9f60a247d2d219cad1fb6577fd CRs-Fixed: 2223130 --- CORE/SAP/src/sapFsm.c | 50 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/CORE/SAP/src/sapFsm.c b/CORE/SAP/src/sapFsm.c index fde794e0f345a..5ef89c60269af 100644 --- a/CORE/SAP/src/sapFsm.c +++ b/CORE/SAP/src/sapFsm.c @@ -772,7 +772,11 @@ sapSignalHDDevent case eSAP_STA_ASSOC_IND: // TODO - Indicate the assoc request indication to OS sapApAppEvent.sapHddEventCode = eSAP_STA_ASSOC_IND; - + if (!pCsrRoamInfo) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Got NULL Roam Info in event %d"), eSAP_STA_ASSOC_IND); + return VOS_STATUS_E_INVAL; + } vos_mem_copy( &sapApAppEvent.sapevt.sapAssocIndication.staMac, pCsrRoamInfo->peerMac,sizeof(tSirMacAddr)); sapApAppEvent.sapevt.sapAssocIndication.staId = pCsrRoamInfo->staId; sapApAppEvent.sapevt.sapAssocIndication.status = 0; @@ -820,6 +824,12 @@ sapSignalHDDevent FL("SAP event callback event = %s"), "eSAP_STA_ASSOC_EVENT"); vos_mem_zero(event, sizeof(event)); + if (!pCsrRoamInfo) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Got NULL Roam Info in event %d"), + eSAP_STA_ASSOC_EVENT); + return VOS_STATUS_E_INVAL; + } if (pCsrRoamInfo->fReassocReq) sapApAppEvent.sapHddEventCode = eSAP_STA_REASSOC_EVENT; else @@ -861,7 +871,12 @@ sapSignalHDDevent FL("SAP event callback event = %s"), "eSAP_STA_DISASSOC_EVENT"); sapApAppEvent.sapHddEventCode = eSAP_STA_DISASSOC_EVENT; - + if (!pCsrRoamInfo) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Got NULL Roam Info in event %d"), + eSAP_STA_DISASSOC_EVENT); + return VOS_STATUS_E_INVAL; + } vos_mem_copy( &sapApAppEvent.sapevt.sapStationDisassocCompleteEvent.staMac, pCsrRoamInfo->peerMac, sizeof(tSirMacAddr)); sapApAppEvent.sapevt.sapStationDisassocCompleteEvent.staId = pCsrRoamInfo->staId; @@ -879,6 +894,12 @@ sapSignalHDDevent FL("SAP event callback event = %s"), "eSAP_STA_SET_KEY_EVENT"); sapApAppEvent.sapHddEventCode = eSAP_STA_SET_KEY_EVENT; + if (!pCsrRoamInfo) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Got NULL Roam Info in event %d"), + eSAP_STA_SET_KEY_EVENT); + return VOS_STATUS_E_INVAL; + } sapApAppEvent.sapevt.sapStationSetKeyCompleteEvent.status = (eSapStatus )context; vos_mem_copy(&sapApAppEvent.sapevt.sapStationSetKeyCompleteEvent.peerMacAddr, pCsrRoamInfo->peerMac,sizeof(tSirMacAddr)); @@ -899,6 +920,12 @@ sapSignalHDDevent FL("SAP event callback event = %s"), "eSAP_STA_MIC_FAILURE_EVENT"); sapApAppEvent.sapHddEventCode = eSAP_STA_MIC_FAILURE_EVENT; + if (!pCsrRoamInfo) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Got NULL Roam Info in event %d"), + eSAP_STA_MIC_FAILURE_EVENT); + return VOS_STATUS_E_INVAL; + } vos_mem_copy( &sapApAppEvent.sapevt.sapStationMICFailureEvent.srcMacAddr, pCsrRoamInfo->u.pMICFailureInfo->srcMacAddr, sizeof(tSirMacAddr)); @@ -927,7 +954,12 @@ sapSignalHDDevent FL("SAP event callback event = %s"), "eSAP_WPS_PBC_PROBE_REQ_EVENT"); sapApAppEvent.sapHddEventCode = eSAP_WPS_PBC_PROBE_REQ_EVENT; - + if (!pCsrRoamInfo) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Got NULL Roam Info in event %d"), + eSAP_WPS_PBC_PROBE_REQ_EVENT); + return VOS_STATUS_E_INVAL; + } vos_mem_copy( &sapApAppEvent.sapevt.sapPBCProbeReqEvent.WPSPBCProbeReq, pCsrRoamInfo->u.pWPSPBCProbeReq, sizeof(tSirWPSPBCProbeReq)); @@ -977,6 +1009,12 @@ sapSignalHDDevent FL("SAP event callback event = %s"), "eSAP_MAX_ASSOC_EXCEEDED"); sapApAppEvent.sapHddEventCode = eSAP_MAX_ASSOC_EXCEEDED; + if (!pCsrRoamInfo) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Got NULL Roam Info in event %d"), + eSAP_MAX_ASSOC_EXCEEDED); + return VOS_STATUS_E_INVAL; + } vos_mem_copy((v_PVOID_t)sapApAppEvent.sapevt.sapMaxAssocExceeded.macaddr.bytes, (v_PVOID_t)pCsrRoamInfo->peerMac, sizeof(v_MACADDR_t)); break; @@ -997,6 +1035,12 @@ sapSignalHDDevent __func__, "eSAP_STA_LOSTLINK_DETECTED"); sapApAppEvent.sapHddEventCode = eSAP_STA_LOSTLINK_DETECTED; + if (!pCsrRoamInfo) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Got NULL Roam Info in event %d"), + eSAP_STA_LOSTLINK_DETECTED); + return VOS_STATUS_E_INVAL; + } disassoc_comp = &sapApAppEvent.sapevt.sapStationDisassocCompleteEvent; disassoc_comp->reason = pCsrRoamInfo->reasonCode; From f59c7760061a6888079194e7302914f0a40da7df Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Tue, 10 Apr 2018 17:54:25 +0530 Subject: [PATCH 347/508] wlan: Add support to configure QPOWER with vendor command Add host support to configure QPOWER using vendor command QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION with a new attribute QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER. Change-Id: I00324d87c4cc87adab743d6af2081942685fcbc7 CRs-Fixed: 2221765 --- CORE/HDD/inc/wlan_hdd_cfg80211.h | 3 ++ CORE/HDD/src/wlan_hdd_cfg80211.c | 33 +++++++++++++ CORE/MAC/src/include/sirParams.h | 2 + CORE/SME/inc/sme_Api.h | 2 + CORE/SME/src/sme_common/sme_Api.c | 30 +++++++++++ CORE/WDA/inc/wlan_qct_wda.h | 2 + CORE/WDA/src/wlan_qct_wda.c | 29 +++++++++++ CORE/WDI/CP/inc/wlan_qct_wdi.h | 10 ++++ CORE/WDI/CP/inc/wlan_qct_wdi_i.h | 18 ++++++- CORE/WDI/CP/src/wlan_qct_wdi.c | 82 +++++++++++++++++++++++++++++++ 10 files changed, 210 insertions(+), 1 deletion(-) diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h index 43e9acbb5da41..4ea1c4a64ba90 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -1417,6 +1417,9 @@ enum qca_wlan_vendor_config { QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_RATE, QCA_WLAN_VENDOR_ATTR_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS, + + /* 8-bit unsigned value to trigger QPower: 1-Enable, 0-Disable */ + QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER = 25, /* 8-bit unsigned value to set the beacon miss threshold in 2.4 GHz */ QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_24 = 37, /* 8-bit unsigned value to set the beacon miss threshold in 5 GHz */ diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 796019150ff63..a9df7b105e503 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -7819,6 +7819,23 @@ static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy, #define PARAM_BCNMISS_PENALTY_PARAM_COUNT \ QCA_WLAN_VENDOR_ATTR_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS +/* + * hdd_set_qpower() - Process the qpower command and invoke the SME api + * @hdd_ctx: hdd context + * @enable: Value received in the command, 1 for disable and 2 for enable + * + * Return: void + */ +static void hdd_set_qpower(hdd_context_t *hdd_ctx, uint8_t enable) +{ + if (!hdd_ctx) { + hddLog(LOGE, "hdd_ctx NULL"); + return; + } + + sme_set_qpower(hdd_ctx->hHal, enable); +} + /** * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration * vendor command @@ -7848,6 +7865,7 @@ static int __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, eHalStatus status; int ret_val; uint8_t hb_thresh_val; + uint8_t qpower; static const struct nla_policy policy[PARAM_WIFICONFIG_MAX + 1] = { [PARAM_STATS_AVG_FACTOR] = { .type = NLA_U16 }, @@ -8023,6 +8041,21 @@ static int __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, } } + if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) { + qpower = nla_get_u8( + tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]); + + if(qpower > 1) { + hddLog(LOGE, "Invalid QPOWER value %d", qpower); + vos_mem_free(pReq); + pReq = NULL; + return -EINVAL; + } + /* FW is expacting qpower as 1 for Disable and 2 for enable */ + qpower++; + hdd_set_qpower(pHddCtx, qpower); + } + EXIT(); return ret_val; } diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h index ad1a54785bc44..e834dc8d1e2c2 100644 --- a/CORE/MAC/src/include/sirParams.h +++ b/CORE/MAC/src/include/sirParams.h @@ -810,6 +810,8 @@ typedef struct sSirMbMsgP2p #define SIR_HAL_SET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 303) #define SIR_HAL_GET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 304) #define SIR_HAL_VOWIFI_MODE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 306) +#define SIR_HAL_QPOWER (SIR_HAL_ITC_MSG_TYPES_BEGIN + 307) + #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h index 0d4ee2c951a63..6e1a426b8da0f 100644 --- a/CORE/SME/inc/sme_Api.h +++ b/CORE/SME/inc/sme_Api.h @@ -232,6 +232,8 @@ sme_SetLinkLayerStatsIndCB #endif /* WLAN_FEATURE_LINK_LAYER_STATS */ void sme_set_vowifi_mode(tpAniSirGlobal pMac, bool enable); +void sme_set_qpower(tpAniSirGlobal pMac, uint8_t enable); + #ifdef WLAN_FEATURE_EXTSCAN /* --------------------------------------------------------------------------- \fn sme_GetValidChannelsByBand diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c index 81ae6b8e7da67..b282a77b64f40 100644 --- a/CORE/SME/src/sme_common/sme_Api.c +++ b/CORE/SME/src/sme_common/sme_Api.c @@ -901,6 +901,36 @@ static void smeProcessNanReq(tpAniSirGlobal pMac, tSmeCmd *pCommand ) } } +/** + * sme_set_qpower() - Set Qpower + * @pMac - context handler + * @enable - uint8 value that needs to be sent to FW + * + * The function sends the qpower to firmware received + * via driver command + */ +void sme_set_qpower(tpAniSirGlobal pMac, uint8_t enable) +{ + tSirMsgQ msgQ; + tSirRetStatus retCode = eSIR_SUCCESS; + + vos_mem_zero(&msgQ, sizeof(tSirMsgQ)); + msgQ.type = WDA_QPOWER; + msgQ.reserved = 0; + msgQ.bodyval = enable; + + retCode = wdaPostCtrlMsg(pMac, &msgQ); + if(eSIR_SUCCESS != retCode) + { + smsLog(pMac, LOGE, + FL("Posting WDA_QPOWER to WDA failed, reason=%X"), + retCode); + } + else + { + smsLog(pMac, LOG1, FL("posted WDA_QPOWER command")); + } +} /** * sme_set_vowifi_mode() - Set VOWIFI mode diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h index dda8b0468887a..db75533c948f2 100644 --- a/CORE/WDA/inc/wlan_qct_wda.h +++ b/CORE/WDA/inc/wlan_qct_wda.h @@ -1111,6 +1111,8 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); #define WDA_LOW_RSSI_IND SIR_HAL_LOW_RSSI_IND #define WDA_BEACON_FILTER_IND SIR_HAL_BEACON_FILTER_IND #define WDA_VOWIFI_MODE SIR_HAL_VOWIFI_MODE +#define WDA_QPOWER SIR_HAL_QPOWER + /// PE <-> HAL WOWL messages #define WDA_WOWL_ADD_BCAST_PTRN SIR_HAL_WOWL_ADD_BCAST_PTRN #define WDA_WOWL_DEL_BCAST_PTRN SIR_HAL_WOWL_DEL_BCAST_PTRN diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c index 6124bd41b237f..73aa92157fffd 100644 --- a/CORE/WDA/src/wlan_qct_wda.c +++ b/CORE/WDA/src/wlan_qct_wda.c @@ -12001,6 +12001,27 @@ VOS_STATUS WDA_RemBeaconFilterReq(tWDA_CbContext *pWDA, return status; } +VOS_STATUS WDA_set_qpower(tWDA_CbContext *pWDA, + uint8_t enable) +{ + WDI_Status status; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + FL("---> %s"), __func__); + status = WDI_set_qpower(enable); + if (status == WDI_STATUS_PENDING) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + FL("pending status received ")); + } + else if (status != WDI_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + FL("Failure status %d"), status); + } + return CONVERT_WDI2VOS_STATUS(status); +} + VOS_STATUS WDA_set_vowifi_ind(tWDA_CbContext *pWDA, tANI_BOOLEAN enable) { @@ -17062,6 +17083,14 @@ VOS_STATUS WDA_McProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) break; } + case WDA_QPOWER: + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO_HIGH, + "Handling msg type WDA_QPOWER"); + WDA_set_qpower(pWDA, pMsg->bodyval); + break; + } + case WDA_BTC_SET_CFG: { /*TODO: handle this while dealing with BTC */ diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi.h b/CORE/WDI/CP/inc/wlan_qct_wdi.h index 4dae584f54027..3b6f4f1a15377 100644 --- a/CORE/WDI/CP/inc/wlan_qct_wdi.h +++ b/CORE/WDI/CP/inc/wlan_qct_wdi.h @@ -12301,6 +12301,16 @@ WDI_SetRtsCtsHTVhtInd */ WDI_Status WDI_set_vowifi_mode_ind(wpt_boolean enable); +/** + * WDI_set_qpower() - Set qpower mode request + * + * @enable - uint8_t value that needs to be send + * + * Return: success if the value is sent + */ +WDI_Status WDI_set_qpower(uint8_t enable); + + WDI_Status WDI_FWLoggingDXEdoneInd ( diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h index 796a7076422b0..cc45bf3a071cb 100644 --- a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h +++ b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h @@ -574,7 +574,8 @@ typedef enum WDI_SET_AP_FIND_IND = WDI_MAX_REQ + 25, WDI_SET_VOWIFI_IND = WDI_MAX_REQ + 26, - WDI_MAX_UMAC_IND = WDI_MAX_REQ + 27, + WDI_SET_QPOWER = WDI_MAX_REQ + 27, + WDI_MAX_UMAC_IND = WDI_MAX_REQ + 28, }WDI_RequestEnumType; @@ -1908,6 +1909,21 @@ WDI_process_vowifi_request WDI_EventInfoType* pEventData ); +/** + * WDI_process_qpower_request - Sends the qpower request data to + * the firmware when qpower driver command is invoked + * @pWDICtx: pointer to the WLAN DAL context + * @pEventData: pointer to the event information structure + * + * Return value: status whether the sending is successful or not + */ +WDI_Status +WDI_process_qpower_request +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData +); + /** @brief Process Finish Scan Request function (called when Main FSM allows it) diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c index 6b7cbeb418b8f..e3f78a1052b85 100644 --- a/CORE/WDI/CP/src/wlan_qct_wdi.c +++ b/CORE/WDI/CP/src/wlan_qct_wdi.c @@ -617,6 +617,7 @@ WDI_ReqProcFuncType pfnReqProcTbl[WDI_MAX_UMAC_IND] = NULL, #endif WDI_process_vowifi_request, /* WDI_SET_VOWIFI_IND */ + WDI_process_qpower_request, /* WDI_SET_QPOWER */ }; @@ -9051,6 +9052,65 @@ WDI_process_vowifi_request(WDI_ControlBlockType* pWDICtx, return (wdiStatus != WDI_STATUS_SUCCESS) ? wdiStatus:WDI_STATUS_SUCCESS_SYNC; } +WDI_Status +WDI_process_qpower_request(WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData) +{ + wpt_uint8* pSendBuffer = NULL; + wpt_uint16 usDataOffset = 0; + wpt_uint16 usSendSize = 0; + uint8_t *enable; + tHalQpower hal_qpower_msg; + WDI_Status wdiStatus; + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, + "%s", __func__); + + /*------------------------------------------------------------------------- + Sanity check + -------------------------------------------------------------------------*/ + if (( NULL == pEventData ) || ( NULL == pEventData->pEventData ) ) { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + enable = (uint8_t*)pEventData->pEventData; + + /*----------------------------------------------------------------------- + Get message buffer + -----------------------------------------------------------------------*/ + if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx, + WDI_SET_QPOWER, + sizeof(tHalQpowerParams), + &pSendBuffer, &usDataOffset, &usSendSize))|| + ( usSendSize < (usDataOffset + sizeof(tHalQpowerParams) ))) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "Unable to get send buffer QPOWER ind %pK ", + pEventData); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + hal_qpower_msg.qpowerParams.enable = *enable; + + wpalMemoryCopy( pSendBuffer+usDataOffset, + &hal_qpower_msg.qpowerParams, + sizeof(hal_qpower_msg.qpowerParams)); + + pWDICtx->pReqStatusUserData = NULL; + pWDICtx->pfncRspCB = NULL; + + /*------------------------------------------------------------------------- + Send QPOWER Request to HAL + -------------------------------------------------------------------------*/ + wdiStatus = WDI_SendIndication(pWDICtx, pSendBuffer, usSendSize); + return (wdiStatus != WDI_STATUS_SUCCESS) ? wdiStatus:WDI_STATUS_SUCCESS_SYNC; +} + /** @brief Process End Scan Request function (called when Main FSM allows it) @@ -11567,6 +11627,26 @@ WDI_Status WDI_set_vowifi_mode_ind(wpt_boolean enable) return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData); } +WDI_Status WDI_set_qpower(uint8_t enable) +{ + WDI_EventInfoType wdiEventData; + + if (eWLAN_PAL_FALSE == gWDIInitialized ) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "WDI API call before module is initialized - Fail request"); + return WDI_STATUS_E_NOT_ALLOWED; + } + + wdiEventData.wdiRequest = WDI_SET_QPOWER; + wdiEventData.pEventData = (void *) &enable; + wdiEventData.uEventDataSize = sizeof(uint8_t); + wdiEventData.pCBfnc = NULL; + wdiEventData.pUserData = NULL; + + return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData); +} + /** @brief Process Add BA Request function (called when Main FSM allows it) @@ -25237,6 +25317,8 @@ WDI_2_HAL_REQ_TYPE return WLAN_HAL_SET_RTS_CTS_HTVHT_IND; case WDI_SET_VOWIFI_IND: return WLAN_HAL_VOWIFI_IND; + case WDI_SET_QPOWER: + return WLAN_HAL_QPOWER_ENABLE_BY_HOST_IND; case WDI_MON_START_REQ: return WLAN_HAL_ENABLE_MONITOR_MODE_REQ; case WDI_MON_STOP_REQ: From 3dd5dba03317f1dce9851bd5d685e72bfc4004dd Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Mon, 26 Mar 2018 15:12:47 +0530 Subject: [PATCH 348/508] wlan: Disable channels 12 and 13 when SET_FCC_CHANNEL is set Currently Ch 12/13 are enabled with reduced power when SET_FCC_CHANNEL is issued by framework. To meet customer requirement, the channels are marked as disable. This reverts Ie833804e565f40e28845160452d3245334a34308 Change-Id: I3f4e835320e61ae72821d89b3bed9924d2f40292 CRs-Fixed: 2212633 --- CORE/SME/src/csr/csrApiRoam.c | 17 ----------------- CORE/SME/src/csr/csrApiScan.c | 25 +++++++++++++++++++++++++ CORE/SME/src/csr/csrInsideApi.h | 1 + CORE/SME/src/sme_common/sme_Api.c | 2 +- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c index acdbc6ddc9375..cb131b029adec 100644 --- a/CORE/SME/src/csr/csrApiRoam.c +++ b/CORE/SME/src/csr/csrApiRoam.c @@ -112,8 +112,6 @@ static tANI_BOOLEAN bRoamScanOffloadStarted = VOS_FALSE; #endif -#define MAX_PWR_FCC_CHAN_12 8 -#define MAX_PWR_FCC_CHAN_13 2 /*-------------------------------------------------------------------------- Static Type declarations @@ -606,21 +604,6 @@ eHalStatus csrUpdateChannelList(tpAniSirGlobal pMac) pChanList->chanParam[num_channel].pwr = cfgGetRegulatoryMaxTransmitPower(pMac, pScan->defaultPowerTable[i].chanId); - if (pMac->scan.fcc_constraint) - { - if (pChanList->chanParam[num_channel].chanId == 12) - { - pChanList->chanParam[num_channel].pwr = MAX_PWR_FCC_CHAN_12; - smsLog(pMac, LOG1, - "fcc_constraint is set, txpower for channel 12 is 8db "); - } - if (pChanList->chanParam[num_channel].chanId == 13) - { - pChanList->chanParam[num_channel].pwr = MAX_PWR_FCC_CHAN_13; - smsLog(pMac, LOG1, - "fcc_constraint is set, txpower for channel 13 is 2db "); - } - } if (!pChanList->chanParam[num_channel].pwr) { diff --git a/CORE/SME/src/csr/csrApiScan.c b/CORE/SME/src/csr/csrApiScan.c index 2c7f3e84a6a62..353c036bb40da 100644 --- a/CORE/SME/src/csr/csrApiScan.c +++ b/CORE/SME/src/csr/csrApiScan.c @@ -4139,6 +4139,31 @@ void csrApplyChannelPowerCountryInfo( tpAniSirGlobal pMac, tCsrChannel *pChannel csrSetCfgCountryCode(pMac, countryCode); } +void csrUpdateFCCChannelList(tpAniSirGlobal pMac) +{ + tCsrChannel ChannelList; + tANI_U8 chnlIndx = 0; + int i; + + for ( i = 0; i < pMac->scan.base20MHzChannels.numChannels; i++ ) + { + if (pMac->scan.fcc_constraint && + ((pMac->scan.base20MHzChannels.channelList[i] == 12) || + (pMac->scan.base20MHzChannels.channelList[i] == 13))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("removing channel %d"), + pMac->scan.base20MHzChannels.channelList[i]); + continue; + } + ChannelList.channelList[chnlIndx] = + pMac->scan.base20MHzChannels.channelList[i]; + chnlIndx++; + } + csrSetCfgValidChannelList(pMac, ChannelList.channelList, chnlIndx); + csrScanFilterResults(pMac); +} + void csrResetCountryInformation( tpAniSirGlobal pMac, tANI_BOOLEAN fForce, tANI_BOOLEAN updateRiva ) { if( fForce || (csrIs11dSupported( pMac ) && (!pMac->scan.f11dInfoReset))) diff --git a/CORE/SME/src/csr/csrInsideApi.h b/CORE/SME/src/csr/csrInsideApi.h index 822e38e1e8f12..eee6e9f900eb8 100644 --- a/CORE/SME/src/csr/csrInsideApi.h +++ b/CORE/SME/src/csr/csrInsideApi.h @@ -456,6 +456,7 @@ eCsrCfgDot11Mode csrGetCfgDot11ModeFromCsrPhyMode(tCsrRoamProfile *pProfile, eCs tANI_U32 csrTranslateToWNICfgDot11Mode(tpAniSirGlobal pMac, eCsrCfgDot11Mode csrDot11Mode); void csrSaveChannelPowerForBand( tpAniSirGlobal pMac, tANI_BOOLEAN fPopulate5GBand ); void csrApplyChannelPowerCountryInfo( tpAniSirGlobal pMac, tCsrChannel *pChannelList, tANI_U8 *countryCode, tANI_BOOLEAN updateRiva); +void csrUpdateFCCChannelList(tpAniSirGlobal pMac); void csrApplyPower2Current( tpAniSirGlobal pMac ); void csrAssignRssiForCategory(tpAniSirGlobal pMac, tANI_S8 bestApRssi, tANI_U8 catOffset); tANI_BOOLEAN csrIsMacAddressZero( tpAniSirGlobal pMac, tCsrBssid *pMacAddr ); diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c index b282a77b64f40..97844158998df 100644 --- a/CORE/SME/src/sme_common/sme_Api.c +++ b/CORE/SME/src/sme_common/sme_Api.c @@ -14290,7 +14290,7 @@ tANI_BOOLEAN sme_handleSetFccChannel(tHalHandle hHal, tANI_U8 fcc_constraint, pMac->scan.defer_update_channel_list = true; } else { /* update the channel list to the firmware */ - csrUpdateChannelList(pMac); + csrUpdateFCCChannelList(pMac); } } From 7288ba40f417ab02741cf59461f6f1b3b4f3851c Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Thu, 12 Apr 2018 19:15:57 +0530 Subject: [PATCH 349/508] wlan: Add ini control for different timesharing for WLAN/BT In the case of WLAN/BT sharing while connected with a 2M headset the throughput drops very low. Add ini params which when set to custom values will use different timesharing for WLAN/BT when A2DP is going on with a 2M headset. Change-Id: Ifcffc3eefc6fa2c3680a5d1a3ceb68eb7b9a3598 CRs-Fixed: 2224866 --- CORE/HDD/inc/wlan_hdd_cfg.h | 26 ++++++++++++++ CORE/HDD/src/wlan_hdd_cfg.c | 66 +++++++++++++++++++++++++++++++++++ CORE/MAC/inc/wniCfg.h | 27 ++++++++++++-- CORE/MAC/src/cfg/cfgProcMsg.c | 20 +++++++++++ CORE/WDA/src/wlan_qct_wda.c | 60 +++++++++++++++++++++++++++++++ 5 files changed, 196 insertions(+), 3 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index aeb035a9d406f..bca3e87ff8ebf 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -1748,6 +1748,26 @@ typedef enum #define CFG_ENABLE_TCP_DELACK_MAX (1) #define CFG_ENABLE_TCP_DELACK_DEFAULT (1) +#define CFG_BTC_2M_DYN_LONG_WLAN_LEN_NAME "gBTC2MDynLongWLAN" +#define CFG_BTC_2M_DYN_LONG_WLAN_LEN_MIN (15000) +#define CFG_BTC_2M_DYN_LONG_WLAN_LEN_MAX (55000) +#define CFG_BTC_2M_DYN_LONG_WLAN_LEN_DEFAULT (35000) + +#define CFG_BTC_2M_DYN_LONG_BT_LEN_NAME "gBTC2MDynLongBT" +#define CFG_BTC_2M_DYN_LONG_BT_LEN_MIN (15000) +#define CFG_BTC_2M_DYN_LONG_BT_LEN_MAX (25000) +#define CFG_BTC_2M_DYN_LONG_BT_LEN_DEFAULT (25000) + +#define CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_NAME "gBTC2MDynLongBTExt" +#define CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MIN (5000) +#define CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MAX (15000) +#define CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_DEFAULT (15000) + +#define CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_NAME "gBTC2MDynLongNumBTExt" +#define CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MIN (5) +#define CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MAX (15) +#define CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_DEFAULT (15) + #ifdef SAP_AUTH_OFFLOAD /* Enable/Disable SAP Authentication offload * Default: enable @@ -3183,6 +3203,8 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ #define CFG_ENABLE_POWERSAVE_OFFLOAD_MAX (2) #define CFG_ENABLE_POWERSAVE_OFFLOAD_DEFAULT (1) + + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ @@ -3793,6 +3815,10 @@ typedef struct /* control marking indoor channel passive to disable */ bool disable_indoor_channel; uint32_t enable_power_save_offload; + uint32_t btc_dyn_wlan_len; + uint32_t btc_dyn_bt_len; + uint32_t btc_dyn_bt_ext_len; + uint32_t btc_dyn_num_bt_ext; } hdd_config_t; diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index e03363d614b11..60eeb56819648 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -3991,6 +3991,35 @@ REG_VARIABLE( CFG_EXTSCAN_ENABLE, WLAN_PARAM_Integer, CFG_ENABLE_POWERSAVE_OFFLOAD_DEFAULT, CFG_ENABLE_POWERSAVE_OFFLOAD_MIN, CFG_ENABLE_POWERSAVE_OFFLOAD_MAX), + + REG_VARIABLE(CFG_BTC_2M_DYN_LONG_WLAN_LEN_NAME, WLAN_PARAM_Integer, + hdd_config_t, btc_dyn_wlan_len, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BTC_2M_DYN_LONG_WLAN_LEN_DEFAULT, + CFG_BTC_2M_DYN_LONG_WLAN_LEN_MIN, + CFG_BTC_2M_DYN_LONG_WLAN_LEN_MAX), + + REG_VARIABLE(CFG_BTC_2M_DYN_LONG_BT_LEN_NAME, WLAN_PARAM_Integer, + hdd_config_t, btc_dyn_bt_len, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BTC_2M_DYN_LONG_BT_LEN_DEFAULT, + CFG_BTC_2M_DYN_LONG_BT_LEN_MIN, + CFG_BTC_2M_DYN_LONG_BT_LEN_MAX), + + REG_VARIABLE(CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_NAME, WLAN_PARAM_Integer, + hdd_config_t, btc_dyn_bt_ext_len, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_DEFAULT, + CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MIN, + CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MAX), + + REG_VARIABLE(CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_NAME, WLAN_PARAM_Integer, + hdd_config_t, btc_dyn_num_bt_ext, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_DEFAULT, + CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MIN, + CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MAX), + }; /* @@ -6356,6 +6385,43 @@ v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) fStatus = FALSE; hddLog(LOGE, "Couldn't pass WNI_CFG_ENABLE_POWERSAVE_OFFLOAD to CCM"); } + + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN, + pConfig->btc_dyn_wlan_len, NULL, + eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Couldn't pass WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN to CCM"); + } + + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_BTC_2M_DYN_LONG_BT_LEN, + pConfig->btc_dyn_bt_len, NULL, + eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Couldn't pass WNI_CFG_BTC_2M_DYN_LONG_BT_LEN to CCM"); + } + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN, + pConfig->btc_dyn_bt_ext_len, NULL, + eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Couldn't pass WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN to CCM"); + } + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT, + pConfig->btc_dyn_num_bt_ext, NULL, + eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Couldn't pass WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT to CCM"); + } + + + return fStatus; } diff --git a/CORE/MAC/inc/wniCfg.h b/CORE/MAC/inc/wniCfg.h index a3841b22f6385..06665399e0fc6 100644 --- a/CORE/MAC/inc/wniCfg.h +++ b/CORE/MAC/inc/wniCfg.h @@ -398,7 +398,11 @@ enum { WNI_CFG_DISABLE_SCAN_DURING_SCO, WNI_CFG_ENABLE_TX_RX_AGGREGATION, WNI_CFG_TRIGGER_NULLFRAME_BEFORE_HB, - WNI_CFG_ENABLE_POWERSAVE_OFFLOAD + WNI_CFG_ENABLE_POWERSAVE_OFFLOAD, + WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN, + WNI_CFG_BTC_2M_DYN_LONG_BT_LEN, + WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN, + WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT }; /* @@ -1952,8 +1956,25 @@ enum { #define WNI_CFG_ENABLE_POWERSAVE_OFFLOAD_MAX 2 #define WNI_CFG_ENABLE_POWERSAVE_OFFLOAD_DEF 1 -#define CFG_PARAM_MAX_NUM 365 -#define CFG_STA_IBUF_MAX_SIZE 299 +#define WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN_MIN 15000 +#define WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN_MAX 55000 +#define WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN_DEF 35000 + +#define WNI_CFG_BTC_2M_DYN_LONG_BT_LEN_MIN 15000 +#define WNI_CFG_BTC_2M_DYN_LONG_BT_LEN_MAX 25000 +#define WNI_CFG_BTC_2M_DYN_LONG_BT_LEN_DEF 25000 + +#define WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MIN 5000 +#define WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MAX 15000 +#define WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_DEF 15000 + +#define WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MIN 5 +#define WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MAX 15 +#define WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_DEF 15 + + +#define CFG_PARAM_MAX_NUM 369 +#define CFG_STA_IBUF_MAX_SIZE 303 #define CFG_STA_SBUF_MAX_SIZE 3389 #define CFG_STA_MAGIC_DWORD 0xbeefbeef diff --git a/CORE/MAC/src/cfg/cfgProcMsg.c b/CORE/MAC/src/cfg/cfgProcMsg.c index 840c30f197150..31523271412cb 100644 --- a/CORE/MAC/src/cfg/cfgProcMsg.c +++ b/CORE/MAC/src/cfg/cfgProcMsg.c @@ -1738,6 +1738,26 @@ tAniSirCgStatic cfgStatic[CFG_PARAM_MAX_NUM] = WNI_CFG_ENABLE_POWERSAVE_OFFLOAD_MIN, WNI_CFG_ENABLE_POWERSAVE_OFFLOAD_MAX, WNI_CFG_ENABLE_POWERSAVE_OFFLOAD_DEF}, + {WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN_MIN, + WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN_MAX, + WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN_DEF}, + {WNI_CFG_BTC_2M_DYN_LONG_BT_LEN, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_BTC_2M_DYN_LONG_BT_LEN_MIN, + WNI_CFG_BTC_2M_DYN_LONG_BT_LEN_MAX, + WNI_CFG_BTC_2M_DYN_LONG_BT_LEN_DEF}, + {WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MIN, + WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MAX, + WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_DEF}, + {WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MIN, + WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MAX, + WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_DEF}, }; tAniSirCfgStaticString cfgStaticString[CFG_MAX_STATIC_STRING] = diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c index 73aa92157fffd..0a9384bf5c365 100644 --- a/CORE/WDA/src/wlan_qct_wda.c +++ b/CORE/WDA/src/wlan_qct_wda.c @@ -2481,6 +2481,66 @@ VOS_STATUS WDA_prepareConfigTLV(v_PVOID_t pVosContext, goto handle_failure; } + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + + sizeof(tHalCfg) + tlvStruct->length); + + /* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_WLAN_LEN */ + tlvStruct->type = QWLAN_HAL_CFG_BTC_2M_DYN_LONG_WLAN_LEN; + tlvStruct->length = sizeof(tANI_U32); + configDataValue = (tANI_U32 *)(tlvStruct + 1); + if(wlan_cfgGetInt(pMac, WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN, + configDataValue) != eSIR_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN"); + goto handle_failure; + } + + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + + sizeof(tHalCfg) + tlvStruct->length); + + /* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_LEN */ + tlvStruct->type = QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_LEN; + tlvStruct->length = sizeof(tANI_U32); + configDataValue = (tANI_U32 *)(tlvStruct + 1); + if(wlan_cfgGetInt(pMac, WNI_CFG_BTC_2M_DYN_LONG_BT_LEN, + configDataValue) != eSIR_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_BTC_2M_DYN_LONG_BT_LEN"); + goto handle_failure; + } + + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + + sizeof(tHalCfg) + tlvStruct->length); + + /* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN */ + tlvStruct->type = QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN; + tlvStruct->length = sizeof(tANI_U32); + configDataValue = (tANI_U32 *)(tlvStruct + 1); + if(wlan_cfgGetInt(pMac, WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN, + configDataValue) != eSIR_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN"); + goto handle_failure; + } + + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + + sizeof(tHalCfg) + tlvStruct->length); + + /* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT */ + tlvStruct->type = QWLAN_HAL_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT; + tlvStruct->length = sizeof(tANI_U32); + configDataValue = (tANI_U32 *)(tlvStruct + 1); + if(wlan_cfgGetInt(pMac, WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT, + configDataValue) != eSIR_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT"); + goto handle_failure; + } + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + sizeof(tHalCfg) + tlvStruct->length); wdiStartParams->usConfigBufferLen = (tANI_U8 *)tlvStruct - tlvStructStart; From fb0b19d049ede2e8b102e40e4f7fc3d0c6f3ca9e Mon Sep 17 00:00:00 2001 From: Sravan Kumar Kairam Date: Thu, 1 Feb 2018 12:25:28 +0530 Subject: [PATCH 350/508] wlan: Skip PN replay check for TDLS packets If any RX TDLS traffic coming to HOST during or after TDLS tear down as TDLS sta id does not exist the traffic is mapped to AP sta id. This will overwrite the current PN value for AP sta id. As a result after TDLS tear down packets coming via AP will be dropped due to replay check. To avoid this skip PN replay check for TDLS packets when mapped to AP sta id. Change-Id: Ibd24dde465832910fa8158d370c05c32ee8cd519 CRs-Fixed: 2182324 --- CORE/TL/src/wlan_qct_tl.c | 30 +++++++++++++++++++----------- CORE/TL/src/wlan_qct_tli.h | 5 ++++- CORE/VOSS/inc/i_vos_packet.h | 4 +++- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c index 372a6f7b91903..b125cc183691b 100644 --- a/CORE/TL/src/wlan_qct_tl.c +++ b/CORE/TL/src/wlan_qct_tl.c @@ -6499,6 +6499,7 @@ WLANTL_RxFrames seq_no = (uint16_t)WDA_GET_RX_REORDER_CUR_PKT_SEQ_NO(pvBDHeader); pn_num = WDA_GET_RX_REPLAY_COUNT(pvBDHeader); + vosTempBuff->pn_replay_skip = 0; vosTempBuff->pn_num = pn_num; TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, @@ -6630,11 +6631,13 @@ WLANTL_RxFrames } else { - TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN, - "%s: staId %d doesn't exist, but mapped to AP staId %d", __func__, - ucSTAId, ucAddr3STAId)); + VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "staId %d doesn't exist" + " but mapped to AP staId %d PN:[0x%llX]", + ucSTAId, ucAddr3STAId, pn_num); ucSTAId = ucAddr3STAId; pClientSTA = pTLCb->atlSTAClients[ucAddr3STAId]; + vosTempBuff->pn_replay_skip = 1; } } } @@ -9778,10 +9781,10 @@ WLANTL_STARxAuth (v_PVOID_t)STAMetaInfoPtr); } - /*------------------------------------------------------------------------ - Check to see if re-ordering session is in place - ------------------------------------------------------------------------*/ - if ( 0 != pClientSTA->atlBAReorderInfo[ucTid].ucExists ) + /* Check to see if re-ordering session is in place. + Skip add to reorder list for TDLS packet on AP staid*/ + if (0 != pClientSTA->atlBAReorderInfo[ucTid].ucExists && + !vosDataBuff->pn_replay_skip) { WLANTL_MSDUReorder( pTLCb, &vosDataBuff, aucBDHeader, ucSTAId, ucTid ); } @@ -9793,7 +9796,8 @@ if(WLANTL_IS_DATA_FRAME(WDA_GET_RX_TYPE_SUBTYPE(aucBDHeader)) && #endif ) { - /* replay check code : check whether replay check is needed or not */ + /* replay check code : check whether replay check is needed or not + Skip replay check for TDLS traffic with AP sta id */ if(VOS_TRUE == pClientSTA->ucIsReplayCheckValid) { /* replay check is needed for the station */ @@ -9849,6 +9853,7 @@ if(WLANTL_IS_DATA_FRAME(WDA_GET_RX_TYPE_SUBTYPE(aucBDHeader)) && else { v_BOOL_t status; + uint16_t seq_no = (uint16_t)WDA_GET_RX_REORDER_CUR_PKT_SEQ_NO(aucBDHeader); /* Getting 48-bit replay counter from the RX BD */ ullcurrentReplayCounter = WDA_DS_GetReplayCounter(aucBDHeader); @@ -9865,7 +9870,7 @@ if(WLANTL_IS_DATA_FRAME(WDA_GET_RX_TYPE_SUBTYPE(aucBDHeader)) && /* It is not AMSDU frame so perform reaply check for each packet, as each packet contains valid replay counter*/ - if (vosDataBuff != NULL) { + if (vosDataBuff != NULL && !vosDataBuff->pn_replay_skip) { if (vos_is_pkt_chain(vosDataBuff)) { WLANTL_ReorderReplayCheck(pClientSTA, &vosDataBuff, ucTid); } else { @@ -9874,10 +9879,13 @@ if(WLANTL_IS_DATA_FRAME(WDA_GET_RX_TYPE_SUBTYPE(aucBDHeader)) && if(VOS_FALSE == status) { /* Not a replay paket, update previous replay counter in TL CB */ pClientSTA->ullReplayCounter[ucTid] = ullcurrentReplayCounter; + pClientSTA->last_seq_no[ucTid] = seq_no; } else { VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL: Non AMSDU Drop replay packet with PN: [0x%llX], prevPN: [0x%llx]", - ullcurrentReplayCounter, ullpreviousReplayCounter); + "Non AMSDU Drop replay with PN: [0x%llX], prevPN: [0x%llx]" + " seq_no:%d last_seq_no:%d", + ullcurrentReplayCounter, ullpreviousReplayCounter, seq_no, + pClientSTA->last_seq_no[ucTid]); pClientSTA->ulTotalReplayPacketsDetected++; VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, diff --git a/CORE/TL/src/wlan_qct_tli.h b/CORE/TL/src/wlan_qct_tli.h index 15204b5e830d5..868e745d45029 100644 --- a/CORE/TL/src/wlan_qct_tli.h +++ b/CORE/TL/src/wlan_qct_tli.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -703,6 +703,9 @@ typedef struct /* It contains 48-bit replay counter per TID*/ v_U64_t ullReplayCounter[WLANTL_MAX_TID]; + /* Last seq number received on Tid */ + v_U16_t last_seq_no[WLANTL_MAX_TID]; + /* It contains no of replay packets found per STA. It is for debugging purpose only.*/ v_U32_t ulTotalReplayPacketsDetected; diff --git a/CORE/VOSS/inc/i_vos_packet.h b/CORE/VOSS/inc/i_vos_packet.h index 173d792b77faa..ad6b9685cf4af 100644 --- a/CORE/VOSS/inc/i_vos_packet.h +++ b/CORE/VOSS/inc/i_vos_packet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013,2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013,2017-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -129,6 +129,8 @@ struct vos_pkt_t v_U64_t pn_num; + v_U8_t pn_replay_skip; + // magic number for verifying this is really a struct vos_pkt_t v_U32_t magic; }; From 132df074fc3f4b8fc962929ff20e35ebf5e52664 Mon Sep 17 00:00:00 2001 From: Ritesh Harjani Date: Mon, 19 Mar 2018 15:49:54 +0530 Subject: [PATCH 351/508] sdcardfs: Fix sdcardfs to stop creating cases-sensitive duplicate entries. sdcardfs_name_match gets a 'name' argument from the underlying FS. This need not be null terminated string. So in sdcardfs_name_match -> qstr_case_eq -> we should use str_n_case_eq. This happens because few of the entries in lower level FS may not be NULL terminated and may have some garbage characters passed while doing sdcardfs_name_match. For e.g. # dmesg |grep Download [ 103.646386] sdcardfs_name_match: q1->name=.nomedia, q1->len=8, q2->name=Download\x17\x80\x03, q2->len=8 [ 104.021340] sdcardfs_name_match: q1->name=.nomedia, q1->len=8, q2->name=Download\x17\x80\x03, q2->len=8 [ 105.196864] sdcardfs_name_match: q1->name=.nomedia, q1->len=8, q2->name=Download\x17\x80\x03, q2->len=8 [ 109.113521] sdcardfs_name_match: q1->name=logs, q1->len=4, q2->name=Download\x17\x80\x03, q2->len=8 Now when we try to create a directory with different case for a such files. SDCARDFS creates a entry if it could not find the underlying entry in it's dcache. To reproduce:- 1. bootup the device wait for some time after sdcardfs mounting to complete. 2. cd /storage/emulated/0 3. echo 3 > /proc/sys/vm/drop_caches 4. mkdir download We now start seeing two entries with name. Download & download. Change-Id: I976d92a220a607dd8cdb96c01c2041c5c2bc3326 Signed-off-by: Ritesh Harjani --- fs/sdcardfs/sdcardfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h index 39490322c6098..1b960d6b45943 100644 --- a/fs/sdcardfs/sdcardfs.h +++ b/fs/sdcardfs/sdcardfs.h @@ -656,7 +656,7 @@ static inline bool str_n_case_eq(const char *s1, const char *s2, size_t len) static inline bool qstr_case_eq(const struct qstr *q1, const struct qstr *q2) { - return q1->len == q2->len && str_case_eq(q1->name, q2->name); + return q1->len == q2->len && str_n_case_eq(q1->name, q2->name, q2->len); } /* */ From eb2b38d25ce36cf24041db8e2108e17f6bceada0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Oct 2017 11:01:13 +0200 Subject: [PATCH 352/508] USB: serial: console: fix use-after-free after failed setup Make sure to reset the USB-console port pointer when console setup fails in order to avoid having the struct usb_serial be prematurely freed by the console code when the device is later disconnected. Change-Id: I4521740cfd288e745474d0de819a8304b72a2159 Git-commit: 299d7572e46f98534033a9e65973f13ad1ce9047 Git-repo: https://github.com/torvalds/linux/commit Fixes: 73e487fdb75f ("[PATCH] USB console: fix disconnection issues") Cc: stable # 2.6.18 Acked-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Srinivasa Rao Kuppala --- drivers/usb/serial/console.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 29fa1c3d0089b..926c1f2dc962c 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -187,6 +187,7 @@ static int usb_console_setup(struct console *co, char *options) tty_kref_put(tty); reset_open_count: port->port.count = 0; + info->port = NULL; usb_autopm_put_interface(serial->interface); error_get_interface: usb_serial_put(serial); From d152fe2a706d80e66c08d7ecbb5709c95153cc70 Mon Sep 17 00:00:00 2001 From: Dhanalakshmi Siddani Date: Mon, 16 Apr 2018 14:29:42 +0530 Subject: [PATCH 353/508] ARM: dts: msm: Add support for external codec on apq8053 FEP V2 Add support to enable wcd9335 codec on apq8053 FEP V2 platform. CRs-Fixed: 2223496 Change-Id: Id657db934eb863d03a55530b76ee3a4a595e403c Signed-off-by: Dhanalakshmi Siddani --- .../apq8053-lite-ext-codec-dragon-v2.0.dts | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/arch/arm/boot/dts/qcom/apq8053-lite-ext-codec-dragon-v2.0.dts b/arch/arm/boot/dts/qcom/apq8053-lite-ext-codec-dragon-v2.0.dts index e3c1b449f303a..e34e4961befe8 100644 --- a/arch/arm/boot/dts/qcom/apq8053-lite-ext-codec-dragon-v2.0.dts +++ b/arch/arm/boot/dts/qcom/apq8053-lite-ext-codec-dragon-v2.0.dts @@ -26,3 +26,91 @@ &blsp2_uart0 { status = "okay"; }; + +&int_codec { + status = "disabled"; +}; + +&pm8953_diangu_dig { + status = "disabled"; +}; + +&pm8953_diangu_analog { + status = "disabled"; +}; + +&wsa881x_i2c_e { + status = "disabled"; +}; + +&wsa881x_i2c_44 { + status = "disabled"; +}; + +&wsa881x_i2c_f { + status = "disabled"; +}; + +&wsa881x_i2c_45 { + status = "disabled"; +}; + +&slim_msm { + status = "okay"; + tasha_codec { + swr_master { + compatible = "qcom,swr-wcd"; + #address-cells = <2>; + #size-cells = <0>; + + wsa881x_211: wsa881x@20170211 { + compatible = "qcom,wsa881x"; + reg = <0x00 0x20170211>; + qcom,spkr-sd-n-gpio = <&tlmm 68 0>; + }; + + wsa881x_212: wsa881x@20170212 { + compatible = "qcom,wsa881x"; + reg = <0x00 0x20170212>; + qcom,spkr-sd-n-gpio = <&tlmm 68 0>; + }; + + wsa881x_213: wsa881x@21170213 { + compatible = "qcom,wsa881x"; + reg = <0x00 0x21170213>; + qcom,spkr-sd-n-gpio = <&tlmm 68 0>; + }; + + wsa881x_214: wsa881x@21170214 { + compatible = "qcom,wsa881x"; + reg = <0x00 0x21170214>; + qcom,spkr-sd-n-gpio = <&tlmm 68 0>; + }; + }; + }; +}; + +&dai_slim { + status = "okay"; +}; + +&wcd9xxx_intc { + status = "okay"; +}; + +&clock_audio { + status = "okay"; +}; + +&wcd9335 { + status = "okay"; +}; + +&wcd_rst_gpio { + status = "okay"; +}; + +&ext_codec { + qcom,model = "msm8953-tasha-snd-card"; + status = "okay"; +}; From f23cf04f728a9b0f0a447bbdc73687964e7d9fdf Mon Sep 17 00:00:00 2001 From: Shreyas Narayan Date: Fri, 20 Apr 2018 10:27:07 +0530 Subject: [PATCH 354/508] fix compilation issue. Change-Id: I87fab5ac707f86d5b428a576efba62f09759315e Signed-off-by: Shreyas Narayan --- drivers/char/diag/diagchar_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index 1c793581ca1ab..b686f5b79f7d4 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -458,8 +458,6 @@ static void diag_close_logging_process(const int pid) mutex_lock(&driver->diagchar_mutex); session_peripheral_mask = session_info->peripheral_mask; - diag_md_session_close(session_info); - mutex_unlock(&driver->diagchar_mutex); for (i = 0; i < NUM_MD_SESSIONS; i++) if (MD_PERIPHERAL_MASK(i) & session_peripheral_mask) diag_mux_close_peripheral(DIAG_LOCAL_PROC, i); From b3c75ac4dcc2b40dd46a505a8fa7ea208bfb9d9c Mon Sep 17 00:00:00 2001 From: Sravan Kumar Kairam Date: Fri, 29 Dec 2017 17:15:19 +0530 Subject: [PATCH 355/508] wlan: Add ini to toggle PN replay check Add ini configuration item to enable or disable HOST PN replay check for unicast packets. Change-Id: Icb3be010bac587e9d1d542ec2a3221acccc7069f CRs-Fixed: 2223327 --- CORE/HDD/inc/wlan_hdd_cfg.h | 6 ++++++ CORE/HDD/src/wlan_hdd_cfg.c | 7 +++++++ CORE/TL/inc/wlan_qct_tl.h | 4 ++++ CORE/TL/src/wlan_qct_tl.c | 7 ++++++- CORE/VOSS/src/vos_api.c | 1 + 5 files changed, 24 insertions(+), 1 deletion(-) diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index 049df4e84d4b1..aeb035a9d406f 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -1190,6 +1190,11 @@ typedef enum #define CFG_REORDER_TIME_VO_MAX 1000 #define CFG_REORDER_TIME_VO_DEFAULT 40 +#define CFG_ENABLE_PN_REPLAY_NAME "PNreplayCheck" +#define CFG_ENABLE_PN_REPLAY_MIN 0 +#define CFG_ENABLE_PN_REPLAY_MAX 1 +#define CFG_ENABLE_PN_REPLAY_DEFAULT 0 + #if defined WLAN_FEATURE_VOWIFI #define CFG_RRM_ENABLE_NAME "gRrmEnable" #define CFG_RRM_ENABLE_MIN (0) @@ -3456,6 +3461,7 @@ typedef struct v_U16_t BeReorderAgingTime; v_U16_t ViReorderAgingTime; v_U16_t VoReorderAgingTime; + v_BOOL_t enablePNReplay; /* Wowl pattern */ char wowlPattern[1024]; diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index 0292ba099e5b5..e03363d614b11 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -1375,6 +1375,13 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_REORDER_TIME_VO_MIN, CFG_REORDER_TIME_VO_MAX ), + REG_VARIABLE( CFG_ENABLE_PN_REPLAY_NAME , WLAN_PARAM_Integer, + hdd_config_t, enablePNReplay, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_PN_REPLAY_DEFAULT, + CFG_ENABLE_PN_REPLAY_MIN, + CFG_ENABLE_PN_REPLAY_MAX ), + REG_VARIABLE_STRING( CFG_WOWL_PATTERN_NAME, WLAN_PARAM_String, hdd_config_t, wowlPattern, VAR_FLAGS_OPTIONAL, diff --git a/CORE/TL/inc/wlan_qct_tl.h b/CORE/TL/inc/wlan_qct_tl.h index 5a0db0185fc2a..7f0456d89796a 100644 --- a/CORE/TL/inc/wlan_qct_tl.h +++ b/CORE/TL/inc/wlan_qct_tl.h @@ -328,6 +328,10 @@ typedef struct /* Min Threshold for Processing Frames in TL */ v_U8_t uMinFramesProcThres; + /* 1 means replay check enable + 0 means replay check disable */ + v_BOOL_t ucIsReplayCheck; + /* Re-order Aging Time */ v_U16_t ucReorderAgingTime[WLANTL_MAX_AC]; }WLANTL_ConfigInfoType; diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c index cab3001925e9f..b125cc183691b 100644 --- a/CORE/TL/src/wlan_qct_tl.c +++ b/CORE/TL/src/wlan_qct_tl.c @@ -722,6 +722,9 @@ WLANTL_Open pTLCb->tlConfigInfo.uDelayedTriggerFrmInt = pTLConfig->uDelayedTriggerFrmInt; + pTLCb->tlConfigInfo.ucIsReplayCheck = + pTLConfig->ucIsReplayCheck; + /*------------------------------------------------------------------------ Allocate internal resources ------------------------------------------------------------------------*/ @@ -1523,7 +1526,9 @@ WLANTL_RegisterSTAClient vos_copy_macaddr( &pClientSTA->wSTADesc.vSelfMACAddress, &pwSTADescType->vSelfMACAddress); /* In volans release L replay check is done at TL */ - pClientSTA->ucIsReplayCheckValid = pwSTADescType->ucIsReplayCheckValid; + if (pTLCb->tlConfigInfo.ucIsReplayCheck) + pClientSTA->ucIsReplayCheckValid = pwSTADescType->ucIsReplayCheckValid; + pClientSTA->ulTotalReplayPacketsDetected = 0; /*Clear replay counters of the STA on all TIDs*/ for(ucTid = 0; ucTid < WLANTL_MAX_TID ; ucTid++) diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c index 36621232cce5f..ca67c919309ca 100644 --- a/CORE/VOSS/src/vos_api.c +++ b/CORE/VOSS/src/vos_api.c @@ -2671,6 +2671,7 @@ vos_fetch_tl_cfg_parms pTLConfig->ucReorderAgingTime[3] = pConfig->VoReorderAgingTime;/*WLANTL_AC_VO*/ pTLConfig->uDelayedTriggerFrmInt = pConfig->DelayedTriggerFrmInt; pTLConfig->uMinFramesProcThres = pConfig->MinFramesProcThres; + pTLConfig->ucIsReplayCheck = pConfig->enablePNReplay; } From 10b705fdc9be885c075f6f97aae6b6f15e929e2d Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Thu, 12 Apr 2018 19:59:17 +0530 Subject: [PATCH 356/508] wlan: HAL interface for ini for different timesharing for WLAN/BT In the case of WLAN/BT sharing while connected with a 2M headset the throughput drops very low. Add ini params which when set to custom values will use different timesharing for WLAN/BT when A2DP is going on with a 2M headset. Change-Id: I096a27073d10f17714ea8bdf613e1ff9f2f572b1 CRs-Fixed: 2224867 --- riva/inc/wlan_hal_cfg.h | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/riva/inc/wlan_hal_cfg.h b/riva/inc/wlan_hal_cfg.h index 22367e45260f7..4367e14db76cd 100644 --- a/riva/inc/wlan_hal_cfg.h +++ b/riva/inc/wlan_hal_cfg.h @@ -282,11 +282,15 @@ #define QWLAN_HAL_CFG_DISABLE_SCAN_DURING_SCO 224 #define QWLAN_HAL_CFG_TRIGGER_NULLFRAME_BEFORE_HB 225 #define QWLAN_HAL_CFG_ENABLE_POWERSAVE_OFFLOAD 226 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_WLAN_LEN 227 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_LEN 228 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN 229 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT 230 -#define QWLAN_HAL_CFG_MAX_PARAMS 227 +#define QWLAN_HAL_CFG_MAX_PARAMS 231 /* Total number of Integer CFGs. This is used while allocating the memory for TLV */ -#define QWLAN_HAL_CFG_INTEGER_PARAM 227 +#define QWLAN_HAL_CFG_INTEGER_PARAM 231 /*------------------------------------------------------------------------- Configuration Parameter min, max, defaults @@ -853,6 +857,26 @@ #define QWLAN_HAL_CFG_BTC_DHCP_PROT_ON_SCO_MAX 1 #define QWLAN_HAL_CFG_BTC_DHCP_PROT_ON_SCO_DEF 0 +/* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_WLAN_LEN */ +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_WLAN_LEN_MIN 15000 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_WLAN_LEN_MAX 55000 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_WLAN_LEN_DEF 35000 + +/* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_LEN */ +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_LEN_MIN 15000 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_LEN_MAX 25000 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_LEN_DEF 25000 + +/* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN */ +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MIN 5000 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MAX 15000 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_DEF 15000 + +/* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT */ +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MIN 5 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MAX 15 +#define QWLAN_HAL_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_DEF 15 + /* QWLAN_HAL_CFG_ENABLE_UNICAST_FILTER */ #define QWLAN_HAL_CFG_ENABLE_UNICAST_FILTER_MIN 0 #define QWLAN_HAL_CFG_ENABLE_UNICAST_FILTER_MAX 1 From 04e42dbf031aa2b31e555101cd14366b63cf7e81 Mon Sep 17 00:00:00 2001 From: Pratham Pratap Date: Tue, 10 Apr 2018 15:44:52 +0530 Subject: [PATCH 357/508] usb: gadget: serial: Prevent use-after-free This change prevents use-after-free of dwc3_requests during power on/off with USB connected. Since checking of port->usb means that by that time gserial_disconnect must have been called and as a part of disconnect we will free the request pool. Change-Id: Iee55d9e580e45daaf84e69d89390a3d91b185a80 Signed-off-by: Pratham Pratap --- drivers/usb/gadget/function/u_serial.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index 008c5262a8ec1..1a1e3c0725804 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -4,7 +4,7 @@ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) * Copyright (C) 2008 David Brownell * Copyright (C) 2008 by Nokia Corporation - * Copyright (c) 2013-2015, 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2015, 2017-2018 The Linux Foundation. All rights reserved. * * This code also borrows from usbserial.c, which is * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) @@ -517,11 +517,10 @@ __acquires(&port->port_lock) /* * If port_usb is NULL, gserial disconnect is called * while the spinlock is dropped and all requests are - * freed. Free the current request here. + * freed. */ if (!port->port_usb) { started = 0; - gs_free_req(out, req); break; } if (status) { From 4a7a8a7a0d15995096d4a4bd73ff3cdd11a44b19 Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Thu, 12 Apr 2018 19:15:57 +0530 Subject: [PATCH 358/508] wlan: Add ini control for different timesharing for WLAN/BT In the case of WLAN/BT sharing while connected with a 2M headset the throughput drops very low. Add ini params which when set to custom values will use different timesharing for WLAN/BT when A2DP is going on with a 2M headset. Change-Id: Ifcffc3eefc6fa2c3680a5d1a3ceb68eb7b9a3598 CRs-Fixed: 2224866 --- CORE/HDD/inc/wlan_hdd_cfg.h | 26 ++++++++++++++ CORE/HDD/src/wlan_hdd_cfg.c | 66 +++++++++++++++++++++++++++++++++++ CORE/MAC/inc/wniCfg.h | 27 ++++++++++++-- CORE/MAC/src/cfg/cfgProcMsg.c | 20 +++++++++++ CORE/WDA/src/wlan_qct_wda.c | 60 +++++++++++++++++++++++++++++++ 5 files changed, 196 insertions(+), 3 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index aeb035a9d406f..bca3e87ff8ebf 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -1748,6 +1748,26 @@ typedef enum #define CFG_ENABLE_TCP_DELACK_MAX (1) #define CFG_ENABLE_TCP_DELACK_DEFAULT (1) +#define CFG_BTC_2M_DYN_LONG_WLAN_LEN_NAME "gBTC2MDynLongWLAN" +#define CFG_BTC_2M_DYN_LONG_WLAN_LEN_MIN (15000) +#define CFG_BTC_2M_DYN_LONG_WLAN_LEN_MAX (55000) +#define CFG_BTC_2M_DYN_LONG_WLAN_LEN_DEFAULT (35000) + +#define CFG_BTC_2M_DYN_LONG_BT_LEN_NAME "gBTC2MDynLongBT" +#define CFG_BTC_2M_DYN_LONG_BT_LEN_MIN (15000) +#define CFG_BTC_2M_DYN_LONG_BT_LEN_MAX (25000) +#define CFG_BTC_2M_DYN_LONG_BT_LEN_DEFAULT (25000) + +#define CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_NAME "gBTC2MDynLongBTExt" +#define CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MIN (5000) +#define CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MAX (15000) +#define CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_DEFAULT (15000) + +#define CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_NAME "gBTC2MDynLongNumBTExt" +#define CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MIN (5) +#define CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MAX (15) +#define CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_DEFAULT (15) + #ifdef SAP_AUTH_OFFLOAD /* Enable/Disable SAP Authentication offload * Default: enable @@ -3183,6 +3203,8 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ #define CFG_ENABLE_POWERSAVE_OFFLOAD_MAX (2) #define CFG_ENABLE_POWERSAVE_OFFLOAD_DEFAULT (1) + + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ @@ -3793,6 +3815,10 @@ typedef struct /* control marking indoor channel passive to disable */ bool disable_indoor_channel; uint32_t enable_power_save_offload; + uint32_t btc_dyn_wlan_len; + uint32_t btc_dyn_bt_len; + uint32_t btc_dyn_bt_ext_len; + uint32_t btc_dyn_num_bt_ext; } hdd_config_t; diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index e03363d614b11..60eeb56819648 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -3991,6 +3991,35 @@ REG_VARIABLE( CFG_EXTSCAN_ENABLE, WLAN_PARAM_Integer, CFG_ENABLE_POWERSAVE_OFFLOAD_DEFAULT, CFG_ENABLE_POWERSAVE_OFFLOAD_MIN, CFG_ENABLE_POWERSAVE_OFFLOAD_MAX), + + REG_VARIABLE(CFG_BTC_2M_DYN_LONG_WLAN_LEN_NAME, WLAN_PARAM_Integer, + hdd_config_t, btc_dyn_wlan_len, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BTC_2M_DYN_LONG_WLAN_LEN_DEFAULT, + CFG_BTC_2M_DYN_LONG_WLAN_LEN_MIN, + CFG_BTC_2M_DYN_LONG_WLAN_LEN_MAX), + + REG_VARIABLE(CFG_BTC_2M_DYN_LONG_BT_LEN_NAME, WLAN_PARAM_Integer, + hdd_config_t, btc_dyn_bt_len, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BTC_2M_DYN_LONG_BT_LEN_DEFAULT, + CFG_BTC_2M_DYN_LONG_BT_LEN_MIN, + CFG_BTC_2M_DYN_LONG_BT_LEN_MAX), + + REG_VARIABLE(CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_NAME, WLAN_PARAM_Integer, + hdd_config_t, btc_dyn_bt_ext_len, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_DEFAULT, + CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MIN, + CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MAX), + + REG_VARIABLE(CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_NAME, WLAN_PARAM_Integer, + hdd_config_t, btc_dyn_num_bt_ext, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_DEFAULT, + CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MIN, + CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MAX), + }; /* @@ -6356,6 +6385,43 @@ v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) fStatus = FALSE; hddLog(LOGE, "Couldn't pass WNI_CFG_ENABLE_POWERSAVE_OFFLOAD to CCM"); } + + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN, + pConfig->btc_dyn_wlan_len, NULL, + eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Couldn't pass WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN to CCM"); + } + + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_BTC_2M_DYN_LONG_BT_LEN, + pConfig->btc_dyn_bt_len, NULL, + eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Couldn't pass WNI_CFG_BTC_2M_DYN_LONG_BT_LEN to CCM"); + } + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN, + pConfig->btc_dyn_bt_ext_len, NULL, + eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Couldn't pass WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN to CCM"); + } + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT, + pConfig->btc_dyn_num_bt_ext, NULL, + eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Couldn't pass WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT to CCM"); + } + + + return fStatus; } diff --git a/CORE/MAC/inc/wniCfg.h b/CORE/MAC/inc/wniCfg.h index a3841b22f6385..06665399e0fc6 100644 --- a/CORE/MAC/inc/wniCfg.h +++ b/CORE/MAC/inc/wniCfg.h @@ -398,7 +398,11 @@ enum { WNI_CFG_DISABLE_SCAN_DURING_SCO, WNI_CFG_ENABLE_TX_RX_AGGREGATION, WNI_CFG_TRIGGER_NULLFRAME_BEFORE_HB, - WNI_CFG_ENABLE_POWERSAVE_OFFLOAD + WNI_CFG_ENABLE_POWERSAVE_OFFLOAD, + WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN, + WNI_CFG_BTC_2M_DYN_LONG_BT_LEN, + WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN, + WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT }; /* @@ -1952,8 +1956,25 @@ enum { #define WNI_CFG_ENABLE_POWERSAVE_OFFLOAD_MAX 2 #define WNI_CFG_ENABLE_POWERSAVE_OFFLOAD_DEF 1 -#define CFG_PARAM_MAX_NUM 365 -#define CFG_STA_IBUF_MAX_SIZE 299 +#define WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN_MIN 15000 +#define WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN_MAX 55000 +#define WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN_DEF 35000 + +#define WNI_CFG_BTC_2M_DYN_LONG_BT_LEN_MIN 15000 +#define WNI_CFG_BTC_2M_DYN_LONG_BT_LEN_MAX 25000 +#define WNI_CFG_BTC_2M_DYN_LONG_BT_LEN_DEF 25000 + +#define WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MIN 5000 +#define WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MAX 15000 +#define WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_DEF 15000 + +#define WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MIN 5 +#define WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MAX 15 +#define WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_DEF 15 + + +#define CFG_PARAM_MAX_NUM 369 +#define CFG_STA_IBUF_MAX_SIZE 303 #define CFG_STA_SBUF_MAX_SIZE 3389 #define CFG_STA_MAGIC_DWORD 0xbeefbeef diff --git a/CORE/MAC/src/cfg/cfgProcMsg.c b/CORE/MAC/src/cfg/cfgProcMsg.c index 840c30f197150..31523271412cb 100644 --- a/CORE/MAC/src/cfg/cfgProcMsg.c +++ b/CORE/MAC/src/cfg/cfgProcMsg.c @@ -1738,6 +1738,26 @@ tAniSirCgStatic cfgStatic[CFG_PARAM_MAX_NUM] = WNI_CFG_ENABLE_POWERSAVE_OFFLOAD_MIN, WNI_CFG_ENABLE_POWERSAVE_OFFLOAD_MAX, WNI_CFG_ENABLE_POWERSAVE_OFFLOAD_DEF}, + {WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN_MIN, + WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN_MAX, + WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN_DEF}, + {WNI_CFG_BTC_2M_DYN_LONG_BT_LEN, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_BTC_2M_DYN_LONG_BT_LEN_MIN, + WNI_CFG_BTC_2M_DYN_LONG_BT_LEN_MAX, + WNI_CFG_BTC_2M_DYN_LONG_BT_LEN_DEF}, + {WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MIN, + WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_MAX, + WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN_DEF}, + {WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MIN, + WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MAX, + WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_DEF}, }; tAniSirCfgStaticString cfgStaticString[CFG_MAX_STATIC_STRING] = diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c index 6124bd41b237f..a9744a184ff96 100644 --- a/CORE/WDA/src/wlan_qct_wda.c +++ b/CORE/WDA/src/wlan_qct_wda.c @@ -2481,6 +2481,66 @@ VOS_STATUS WDA_prepareConfigTLV(v_PVOID_t pVosContext, goto handle_failure; } + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + + sizeof(tHalCfg) + tlvStruct->length); + + /* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_WLAN_LEN */ + tlvStruct->type = QWLAN_HAL_CFG_BTC_2M_DYN_LONG_WLAN_LEN; + tlvStruct->length = sizeof(tANI_U32); + configDataValue = (tANI_U32 *)(tlvStruct + 1); + if(wlan_cfgGetInt(pMac, WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN, + configDataValue) != eSIR_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_BTC_2M_DYN_LONG_WLAN_LEN"); + goto handle_failure; + } + + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + + sizeof(tHalCfg) + tlvStruct->length); + + /* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_LEN */ + tlvStruct->type = QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_LEN; + tlvStruct->length = sizeof(tANI_U32); + configDataValue = (tANI_U32 *)(tlvStruct + 1); + if(wlan_cfgGetInt(pMac, WNI_CFG_BTC_2M_DYN_LONG_BT_LEN, + configDataValue) != eSIR_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_BTC_2M_DYN_LONG_BT_LEN"); + goto handle_failure; + } + + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + + sizeof(tHalCfg) + tlvStruct->length); + + /* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN */ + tlvStruct->type = QWLAN_HAL_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN; + tlvStruct->length = sizeof(tANI_U32); + configDataValue = (tANI_U32 *)(tlvStruct + 1); + if(wlan_cfgGetInt(pMac, WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN, + configDataValue) != eSIR_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_BTC_2M_DYN_LONG_BT_EXT_LEN"); + goto handle_failure; + } + + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + + sizeof(tHalCfg) + tlvStruct->length); + + /* QWLAN_HAL_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT */ + tlvStruct->type = QWLAN_HAL_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT; + tlvStruct->length = sizeof(tANI_U32); + configDataValue = (tANI_U32 *)(tlvStruct + 1); + if(wlan_cfgGetInt(pMac, WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT, + configDataValue) != eSIR_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_BTC_2M_DYN_LONG_NUM_BT_EXT"); + goto handle_failure; + } + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + sizeof(tHalCfg) + tlvStruct->length); wdiStartParams->usConfigBufferLen = (tANI_U8 *)tlvStruct - tlvStructStart; From b2041e850a41288050b698ecf5de26e94e628928 Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Wed, 28 Mar 2018 17:14:02 +0530 Subject: [PATCH 359/508] wlan: Check for return codes of dot11f_unpack functions Add checks for return codes of dot11f_unpack functions. Change-Id: I56149a2a767a9f13009710750a0588c0d658eb56 CRs-Fixed: 2213317 --- CORE/HDD/src/wlan_hdd_assoc.c | 10 ++++++- CORE/HDD/src/wlan_hdd_cfg80211.c | 11 ++++++- CORE/HDD/src/wlan_hdd_hostapd.c | 29 +++++++++++++++---- CORE/HDD/src/wlan_hdd_scan.c | 12 ++++++-- CORE/MAC/src/pe/lim/limSmeReqUtils.c | 43 ++++++++++++++++++++++------ 5 files changed, 87 insertions(+), 18 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c index 44000f6c83ea9..e76b50dbe7bfc 100644 --- a/CORE/HDD/src/wlan_hdd_assoc.c +++ b/CORE/HDD/src/wlan_hdd_assoc.c @@ -4631,10 +4631,18 @@ static tANI_S32 hdd_ProcessGENIE(hdd_adapter_t *pAdapter, pRsnIe = gen_ie + 2 + 4; RSNIeLen = gen_ie_len - (2 + 4); // Unpack the WPA IE - dot11fUnpackIeWPA((tpAniSirGlobal) halHandle, + status = dot11fUnpackIeWPA((tpAniSirGlobal) halHandle, pRsnIe, RSNIeLen, &dot11WPAIE); + if (DOT11F_FAILED(status)) + { + hddLog(LOGE, + FL("Parse failure in hdd_ProcessGENIE (0x%08x)"), + status); + return -EINVAL; + } + // Copy out the encryption and authentication types hddLog(LOG1, FL("%s: WPA unicast cipher suite count: %d"), __func__, dot11WPAIE.unicast_cipher_count ); diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index a9df7b105e503..3f8895044ae54 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -17195,6 +17195,7 @@ static int wlan_hdd_cfg80211_set_privacy_ibss( ) { int status = 0; + tANI_U32 ret; hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); @@ -17226,10 +17227,18 @@ static int wlan_hdd_cfg80211_set_privacy_ibss( pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA; // Unpack the WPA IE //Skip past the EID byte and length byte - and four byte WiFi OUI - dot11fUnpackIeWPA((tpAniSirGlobal) halHandle, + ret = dot11fUnpackIeWPA((tpAniSirGlobal) halHandle, &ie[2+4], ie[1] - 4, &dot11WPAIE); + if (DOT11F_FAILED(ret)) + { + hddLog(LOGE, + FL("unpack failed status:(0x%08x)"), + ret); + return -EINVAL; + } + /*Extract the multicast cipher, the encType for unicast cipher for wpa-none is none*/ encryptionType = diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index 463919a03e095..03573ec03a69e 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -1761,6 +1761,7 @@ int hdd_softap_unpackIE( tANI_U8 *pRsnIe; tANI_U16 RSNIeLen; + tANI_U32 status; if (NULL == halHandle) { @@ -1786,10 +1787,18 @@ int hdd_softap_unpackIE( RSNIeLen = gen_ie_len - 2; // Unpack the RSN IE memset(&dot11RSNIE, 0, sizeof(tDot11fIERSN)); - dot11fUnpackIeRSN((tpAniSirGlobal) halHandle, - pRsnIe, - RSNIeLen, + status = dot11fUnpackIeRSN((tpAniSirGlobal) halHandle, + pRsnIe, + RSNIeLen, &dot11RSNIE); + if (DOT11F_FAILED(status)) + { + hddLog(LOGE, + FL("unpack failed for RSN IE status:(0x%08x)"), + status); + return -EINVAL; + } + // Copy out the encryption and authentication types hddLog(LOG1, FL("%s: pairwise cipher suite count: %d"), __func__, dot11RSNIE.pwise_cipher_suite_count ); @@ -1823,10 +1832,18 @@ int hdd_softap_unpackIE( RSNIeLen = gen_ie_len - (2 + 4); // Unpack the WPA IE memset(&dot11WPAIE, 0, sizeof(tDot11fIEWPA)); - dot11fUnpackIeWPA((tpAniSirGlobal) halHandle, - pRsnIe, - RSNIeLen, + status = dot11fUnpackIeWPA((tpAniSirGlobal) halHandle, + pRsnIe, + RSNIeLen, &dot11WPAIE); + if (DOT11F_FAILED(status)) + { + hddLog(LOGE, + FL("unpack failed for WPA IE status:(0x%08x)"), + status); + return -EINVAL; + } + // Copy out the encryption and authentication types hddLog(LOG1, FL("%s: WPA unicast cipher suite count: %d"), __func__, dot11WPAIE.unicast_cipher_count ); diff --git a/CORE/HDD/src/wlan_hdd_scan.c b/CORE/HDD/src/wlan_hdd_scan.c index 33deb6d3bd6eb..ffa45906c0d22 100644 --- a/CORE/HDD/src/wlan_hdd_scan.c +++ b/CORE/HDD/src/wlan_hdd_scan.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -214,6 +214,7 @@ static eHalStatus hdd_IndicateScanResult(hdd_scan_info_t *scanInfo, tCsrScanResu int error; char custom[MAX_CUSTOM_LEN]; char *p; + tANI_U32 status; hddLog( LOG1, "hdd_IndicateScanResult " MAC_ADDRESS_STR, MAC_ADDR_ARRAY(descriptor->bssId)); @@ -342,8 +343,15 @@ static eHalStatus hdd_IndicateScanResult(hdd_scan_info_t *scanInfo, tCsrScanResu pDot11IEHTCaps = NULL; - dot11fUnpackBeaconIEs ((tpAniSirGlobal) + status = dot11fUnpackBeaconIEs ((tpAniSirGlobal) hHal, (tANI_U8 *) descriptor->ieFields, ie_length, &dot11BeaconIEs); + if (DOT11F_FAILED(status)) + { + hddLog(LOGE, + FL("unpack failed for Beacon IE status:(0x%08x)"), + status); + return -EINVAL; + } pDot11SSID = &dot11BeaconIEs.SSID; diff --git a/CORE/MAC/src/pe/lim/limSmeReqUtils.c b/CORE/MAC/src/pe/lim/limSmeReqUtils.c index 1adc7de2baaab..33844ec476ad4 100644 --- a/CORE/MAC/src/pe/lim/limSmeReqUtils.c +++ b/CORE/MAC/src/pe/lim/limSmeReqUtils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2015, 2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -261,6 +261,7 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, { tANI_U8 wpaIndex = 0; tANI_U32 privacy, val; + tANI_U32 status; if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED, &privacy) != eSIR_SUCCESS) @@ -334,10 +335,17 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, limLog(pMac, LOG1, FL("Only RSN IE is present")); - dot11fUnpackIeRSN(pMac,&pRSNie->rsnIEdata[2], + status = dot11fUnpackIeRSN(pMac,&pRSNie->rsnIEdata[2], pRSNie->rsnIEdata[1], &pSessionEntry->gStartBssRSNIe); - return true; + if (DOT11F_FAILED(status)) + { + limLog(pMac, + LOGE,FL("unpack failed for RSN IE (0x%08x)"), + status); + return false; + } + return true; } else if ((pRSNie->length == pRSNie->rsnIEdata[1] + 2) && (pRSNie->rsnIEdata[0] == SIR_MAC_WPA_EID)) @@ -346,10 +354,17 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, LOG1, FL("Only WPA IE is present")); - dot11fUnpackIeWPA(pMac,&pRSNie->rsnIEdata[6], + status = dot11fUnpackIeWPA(pMac,&pRSNie->rsnIEdata[6], pRSNie->rsnIEdata[1] - 4, &pSessionEntry->gStartBssWPAIe); - return true; + if (DOT11F_FAILED(status)) + { + limLog(pMac, + LOGE,FL("unpack failed for WPA IE (0x%08x)"), + status); + return false; + } + return true; } // Check validity of WPA IE @@ -374,12 +389,24 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, else { /* Both RSN and WPA IEs are present */ - dot11fUnpackIeRSN(pMac,&pRSNie->rsnIEdata[2], - pRSNie->rsnIEdata[1], &pSessionEntry->gStartBssRSNIe); + status = dot11fUnpackIeRSN(pMac,&pRSNie->rsnIEdata[2], + pRSNie->rsnIEdata[1], &pSessionEntry->gStartBssRSNIe); + if (DOT11F_FAILED(status)) + { + limLog(pMac,LOGE,FL("unpack failed for RSN IE status:(0x%08x)"), + status); + return false; + } - dot11fUnpackIeWPA(pMac,&pRSNie->rsnIEdata[wpaIndex + 6], + status = dot11fUnpackIeWPA(pMac,&pRSNie->rsnIEdata[wpaIndex + 6], pRSNie->rsnIEdata[wpaIndex + 1]-4, &pSessionEntry->gStartBssWPAIe); + if (DOT11F_FAILED(status)) + { + limLog(pMac, LOGE,FL("unpack failed for WPA IE status:(0x%08x)"), + status); + return false; + } } } From bf87d26a43a3d07a51ae2b75dfae74427060a7b5 Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Tue, 17 Apr 2018 12:11:38 +0530 Subject: [PATCH 360/508] wlan: Fix NULL pointer dereference issue in WLANTL_SampleRxRSSI Add null check for pTLCb->atlSTAClients before dereferencing it. Change-Id: Id3be987092a1d5129d9707fa3145de264a2eb4dd CRs-Fixed: 2225758 --- CORE/TL/src/wlan_qct_tl.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c index b125cc183691b..4668f62a14537 100644 --- a/CORE/TL/src/wlan_qct_tl.c +++ b/CORE/TL/src/wlan_qct_tl.c @@ -6142,10 +6142,18 @@ static void WLANTL_CacheEapol(WLANTL_CbType* pTLCb, vos_pkt_t* vosTempBuff) static void WLANTL_SampleRxRSSI(WLANTL_CbType* pTLCb, void * pBDHeader, uint8_t sta_id) { - WLANTL_STAClientType *pClientSTA = pTLCb->atlSTAClients[sta_id]; - uint8_t count = pClientSTA->rssi_sample_cnt; - uint8_t old_idx = pClientSTA->rssi_stale_idx; + uint8_t count; + uint8_t old_idx; s8 curr_RSSI, curr_RSSI0, curr_RSSI1; + WLANTL_STAClientType *pClientSTA = pTLCb->atlSTAClients[sta_id]; + + if(pClientSTA == NULL) { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + " %s: pClientSTA is NULL", __func__)); + return; + } + count = pClientSTA->rssi_sample_cnt; + old_idx = pClientSTA->rssi_stale_idx; curr_RSSI0 = WLANTL_GETRSSI0(pBDHeader); curr_RSSI1 = WLANTL_GETRSSI1(pBDHeader); From ad4dd9277e1b45113757327ed1f0f7c094914515 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Wed, 18 Apr 2018 11:12:25 -0700 Subject: [PATCH 361/508] msm: ipa: disable prefetch for MHI MHI might be configured to MBIM aggregation. For this to work TX prefetch needs to be disabled. Change-Id: I52510f3a7fbe90d5a472703363136e6e909d301c Acked-by: Ady Abraham Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index f42e17885d9bb..5af391f5fb3b6 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -4438,12 +4438,16 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, /* * IPAv3.5 and above requires to disable prefetch for USB in order - * to allow MBIM to work, currently MBIM is not needed in MHI mode. + * to allow MBIM to work. */ if ((ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5) && (!ipa3_ctx->ipa_config_is_mhi)) ipa3_disable_prefetch(IPA_CLIENT_USB_CONS); + if ((ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5) && + (ipa3_ctx->ipa_config_is_mhi)) + ipa3_disable_prefetch(IPA_CLIENT_MHI_CONS); + if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) { memset(&gsi_props, 0, sizeof(gsi_props)); gsi_props.ver = ipa3_get_gsi_ver(resource_p->ipa_hw_type); From 9c5bd4742537edbab00e00714e2c735f6b112792 Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Thu, 29 Mar 2018 15:11:25 +0530 Subject: [PATCH 362/508] usb: gadget: f_gsi: Set MBIM NTB default size in bind_config Some hosts like Ubuntu does not send USB_CDC_SET_NTB_INPUT_SIZE for setting NTB size for in endpoint. Hence update ntb_input_size to default value in bind_config. Change-Id: I9cb04d28c466069b5b992079199455a61a35a3b9 Signed-off-by: Chandana Kishori Chiluveru --- drivers/usb/gadget/function/f_gsi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index 429535e1e4e65..d1b1190d19a10 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -3245,6 +3245,7 @@ int gsi_bind_config(struct usb_configuration *c, enum ipa_usb_teth_prot prot_id) case IPA_USB_MBIM: gsi->function.name = "mbim"; gsi->function.strings = mbim_gsi_strings; + gsi->d_port.ntb_info.ntb_input_size = MBIM_NTB_DEFAULT_IN_SIZE; break; case IPA_USB_DIAG: gsi->function.name = "dpl"; From 8bcf6392c1af74eceae468d84a709152b95e0456 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Oct 2017 14:10:32 +0200 Subject: [PATCH 363/508] ALSA: usb-audio: Kill stray URB at exiting USB-audio driver may leave a stray URB for the mixer interrupt when it exits by some error during probe. This leads to a use-after-free error as spotted by syzkaller like: ================================================================== BUG: KASAN: use-after-free in snd_usb_mixer_interrupt+0x604/0x6f0 Call Trace: __dump_stack lib/dump_stack.c:16 dump_stack+0x292/0x395 lib/dump_stack.c:52 print_address_description+0x78/0x280 mm/kasan/report.c:252 kasan_report_error mm/kasan/report.c:351 kasan_report+0x23d/0x350 mm/kasan/report.c:409 __asan_report_load8_noabort+0x19/0x20 mm/kasan/report.c:430 snd_usb_mixer_interrupt+0x604/0x6f0 sound/usb/mixer.c:2490 __usb_hcd_giveback_urb+0x2e0/0x650 drivers/usb/core/hcd.c:1779 .... Allocated by task 1484: save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59 save_stack+0x43/0xd0 mm/kasan/kasan.c:447 set_track mm/kasan/kasan.c:459 kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551 kmem_cache_alloc_trace+0x11e/0x2d0 mm/slub.c:2772 kmalloc ./include/linux/slab.h:493 kzalloc ./include/linux/slab.h:666 snd_usb_create_mixer+0x145/0x1010 sound/usb/mixer.c:2540 create_standard_mixer_quirk+0x58/0x80 sound/usb/quirks.c:516 snd_usb_create_quirk+0x92/0x100 sound/usb/quirks.c:560 create_composite_quirk+0x1c4/0x3e0 sound/usb/quirks.c:59 snd_usb_create_quirk+0x92/0x100 sound/usb/quirks.c:560 usb_audio_probe+0x1040/0x2c10 sound/usb/card.c:618 .... Freed by task 1484: save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59 save_stack+0x43/0xd0 mm/kasan/kasan.c:447 set_track mm/kasan/kasan.c:459 kasan_slab_free+0x72/0xc0 mm/kasan/kasan.c:524 slab_free_hook mm/slub.c:1390 slab_free_freelist_hook mm/slub.c:1412 slab_free mm/slub.c:2988 kfree+0xf6/0x2f0 mm/slub.c:3919 snd_usb_mixer_free+0x11a/0x160 sound/usb/mixer.c:2244 snd_usb_mixer_dev_free+0x36/0x50 sound/usb/mixer.c:2250 __snd_device_free+0x1ff/0x380 sound/core/device.c:91 snd_device_free_all+0x8f/0xe0 sound/core/device.c:244 snd_card_do_free sound/core/init.c:461 release_card_device+0x47/0x170 sound/core/init.c:181 device_release+0x13f/0x210 drivers/base/core.c:814 .... Actually such a URB is killed properly at disconnection when the device gets probed successfully, and what we need is to apply it for the error-path, too. In this patch, we apply snd_usb_mixer_disconnect() at releasing. Also introduce a new flag, disconnected, to struct usb_mixer_interface for not performing the disconnection procedure twice. Change-Id: Ic8b1b10a13b8369e12324210a8351b4ec0335218 Git-commit: 124751d5e63c823092060074bd0abaae61aaa9c4 Git-repo: https://github.com/torvalds/linux/commit Reported-by: Andrey Konovalov Tested-by: Andrey Konovalov Cc: Signed-off-by: Takashi Iwai Signed-off-by: Srinivasa Rao Kuppala Signed-off-by: Ajay Agarwal --- sound/usb/card.c | 4 +++- sound/usb/mixer.c | 17 +++++++++++------ sound/usb/mixer.h | 3 ++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index e2f744b6d5f7c..659a7875d79c1 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -603,6 +603,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, struct snd_usb_audio *chip) { struct snd_card *card; + struct usb_mixer_interface *mixer; struct list_head *p; bool was_shutdown; @@ -634,7 +635,8 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, } /* release mixer resources */ list_for_each(p, &chip->mixer_list) { - snd_usb_mixer_disconnect(p); + mixer = list_entry(p, struct usb_mixer_interface, list); + snd_usb_mixer_disconnect(mixer); } } diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 537ac978c69fa..ffc121c3d14bf 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2169,6 +2169,9 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) { + /* kill pending URBs */ + snd_usb_mixer_disconnect(mixer); + kfree(mixer->id_elems); if (mixer->urb) { kfree(mixer->urb->transfer_buffer); @@ -2500,13 +2503,15 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, return err; } -void snd_usb_mixer_disconnect(struct list_head *p) +void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer) { - struct usb_mixer_interface *mixer; - - mixer = list_entry(p, struct usb_mixer_interface, list); - usb_kill_urb(mixer->urb); - usb_kill_urb(mixer->rc_urb); + if (mixer->disconnected) + return; + if (mixer->urb) + usb_kill_urb(mixer->urb); + if (mixer->rc_urb) + usb_kill_urb(mixer->rc_urb); + mixer->disconnected = true; } #ifdef CONFIG_PM diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index 73b1f649447bd..529d3be45922e 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -23,6 +23,7 @@ struct usb_mixer_interface { u8 audigy2nx_leds[3]; u8 xonar_u1_status; + bool disconnected; }; #define MAX_CHANNELS 16 /* max logical channels */ @@ -57,7 +58,7 @@ struct usb_mixer_elem_info { int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, int ignore_error); -void snd_usb_mixer_disconnect(struct list_head *p); +void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer); void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid); From c4c5384ba44d6b4af8b260c592320009dceaed57 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Tue, 10 Apr 2018 18:24:33 +0530 Subject: [PATCH 364/508] wlan: Add HAL support to configure QPOWER Add HAL support to configure QPOWER using vendor command Change-Id: I16b2ce0f2ac57a905e3c770f7172ab867bf13a15 CRs-Fixed: 2221796 --- riva/inc/wlan_hal_msg.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/riva/inc/wlan_hal_msg.h b/riva/inc/wlan_hal_msg.h index e245f0e92a2b7..d0a83fb358caa 100644 --- a/riva/inc/wlan_hal_msg.h +++ b/riva/inc/wlan_hal_msg.h @@ -629,6 +629,7 @@ typedef enum WLAN_HAL_FW_GET_ARP_STATS_RSP = 357, WLAN_HAL_VOWIFI_IND = 360, + WLAN_HAL_QPOWER_ENABLE_BY_HOST_IND = 361, WLAN_HAL_MSG_MAX = WLAN_HAL_MSG_TYPE_MAX_ENUM_SIZE }tHalHostMsgType; @@ -8204,6 +8205,20 @@ typedef PACKED_PRE struct PACKED_POST tHalVoWiFiIndParams voWiFiIndParams; } tHalVoWiFiInd, * tpHalVoWiFiInd; +/*---------------------------------------------------------------- + WLAN_HAL_QPOWER +-----------------------------------------------------------------*/ +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U8 enable; +} tHalQpowerParams, *tpHalQpowerParams; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + tHalQpowerParams qpowerParams; +} tHalQpower, * tpHalQpower; + /*-------------------------------------------------------------------------- * WLAN_HAL_LL_SET_STATS_REQ *---------------------------------------------------------------------------*/ From 6b9771b5e17ce1f5757cf4b47fe315134ae58de2 Mon Sep 17 00:00:00 2001 From: Dhanalakshmi Siddani Date: Sun, 22 Apr 2018 21:21:49 +0530 Subject: [PATCH 365/508] ARM: dts: msm: add afe_loopback_tx back-end dai for apq8053 Add afe_loopback_tx back-end dai to get EC reference data to support Far Field Voice (FFV) algorithm. CRs-Fixed: 2223496 Change-Id: Id85d846d28046174c3891f77e05c26277b3a0c46 Signed-off-by: Dhanalakshmi Siddani --- .../apq8053-lite-ext-codec-dragon-v2.0.dts | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/arch/arm/boot/dts/qcom/apq8053-lite-ext-codec-dragon-v2.0.dts b/arch/arm/boot/dts/qcom/apq8053-lite-ext-codec-dragon-v2.0.dts index e34e4961befe8..1d9641f990ede 100644 --- a/arch/arm/boot/dts/qcom/apq8053-lite-ext-codec-dragon-v2.0.dts +++ b/arch/arm/boot/dts/qcom/apq8053-lite-ext-codec-dragon-v2.0.dts @@ -113,4 +113,33 @@ &ext_codec { qcom,model = "msm8953-tasha-snd-card"; status = "okay"; + qcom,afe-rxtx-lb; + asoc-cpu = <&dai_pri_auxpcm>, + <&dai_mi2s2>, <&dai_mi2s3>, <&dai_mi2s5>, + <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>, + <&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>, + <&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>, + <&afe_pcm_rx>, <&afe_pcm_tx>, + <&afe_proxy_rx>, <&afe_proxy_tx>, + <&incall_record_rx>, <&incall_record_tx>, + <&incall_music_rx>, <&incall_music_2_rx>, + <&sb_5_rx>, <&bt_sco_rx>, + <&bt_sco_tx>, <&int_fm_rx>, <&int_fm_tx>, + <&sb_6_rx>, <&afe_loopback_tx>; + asoc-cpu-names = "msm-dai-q6-auxpcm.1", + "msm-dai-q6-mi2s.2", + "msm-dai-q6-mi2s.3", "msm-dai-q6-mi2s.5", + "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385", + "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387", + "msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389", + "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391", + "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393", + "msm-dai-q6-dev.16395", "msm-dai-q6-dev.224", + "msm-dai-q6-dev.225", "msm-dai-q6-dev.241", + "msm-dai-q6-dev.240", "msm-dai-q6-dev.32771", + "msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773", + "msm-dai-q6-dev.32770", "msm-dai-q6-dev.16394", + "msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289", + "msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293", + "msm-dai-q6-dev.16396", "msm-dai-q6-dev.24577"; }; From 2fa80b56d41acad3000a70b2d5f5fddef72e5b76 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Fri, 6 Apr 2018 18:15:43 +0530 Subject: [PATCH 366/508] voice_svc: Avoid double free in voice_svc driver voice_svc_dev is allocated as a device managed resource and need not be freed since it is freed automatically. Remove the logic to free voice_svc_dev in probe failure and remove functions to avoid double free. CRs-Fixed: 2204285 Change-Id: If4f9ca840b00448b987f5ce443f66b0923b01969 Signed-off-by: Aditya Bavanari --- drivers/soc/qcom/qdsp6v2/voice_svc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c index 40204e104031b..f01ab2499a75a 100644 --- a/drivers/soc/qcom/qdsp6v2/voice_svc.c +++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c @@ -773,7 +773,7 @@ static int voice_svc_probe(struct platform_device *pdev) if (ret) { pr_err("%s: Failed to alloc chrdev\n", __func__); ret = -ENODEV; - goto chrdev_err; + goto done; } voice_svc_dev->major = MAJOR(device_num); @@ -820,8 +820,6 @@ static int voice_svc_probe(struct platform_device *pdev) class_destroy(voice_svc_class); class_err: unregister_chrdev_region(0, MINOR_NUMBER); -chrdev_err: - kfree(voice_svc_dev); done: return ret; } @@ -835,7 +833,6 @@ static int voice_svc_remove(struct platform_device *pdev) device_destroy(voice_svc_class, device_num); class_destroy(voice_svc_class); unregister_chrdev_region(0, MINOR_NUMBER); - kfree(voice_svc_dev); return 0; } From 2a75a4be2bad69ae609e70496565f607de4e8a12 Mon Sep 17 00:00:00 2001 From: Nirmal Abraham Date: Thu, 25 Jan 2018 15:57:58 +0530 Subject: [PATCH 367/508] msm: mdss: Increase fbmem ref count before use (cherry-pick from 'commit a1b61bc46be4 ("msm: mdss: Increase fbmem buf ref count before use")') and made similar changes for MDP3. The reference count for fbmem buf is not incremented before use, which means it can get freed unintentionally when the ref countis decreased to "0". In this case, there is a possibility of use after free. Ensure the fbmem buf refcount is incremented before use. Change-Id: Iab89ac332dd447b29514a6d5c3f251fcd145de4d Signed-off-by: Nirmal Abraham --- drivers/video/msm/mdss/mdp3_ctrl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c index b0c7cb4d77404..c18d9b2ba642d 100644 --- a/drivers/video/msm/mdss/mdp3_ctrl.c +++ b/drivers/video/msm/mdss/mdp3_ctrl.c @@ -1724,12 +1724,15 @@ static int mdp3_get_metadata(struct msm_fb_data_type *mfd, break; case metadata_op_get_ion_fd: if (mfd->fb_ion_handle && mfd->fb_ion_client) { + get_dma_buf(mfd->fbmem_buf); metadata->data.fbmem_ionfd = ion_share_dma_buf_fd(mfd->fb_ion_client, mfd->fb_ion_handle); - if (metadata->data.fbmem_ionfd < 0) + if (metadata->data.fbmem_ionfd < 0) { + dma_buf_put(mfd->fbmem_buf); pr_err("fd allocation failed. fd = %d\n", metadata->data.fbmem_ionfd); + } } break; default: From 6405341904a6fc964faebc5ff7fe3010be7be449 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Tue, 3 Apr 2018 17:15:49 +0530 Subject: [PATCH 368/508] arm: msm: ipa: Add support to get MHI config dynamically Add support to get platform info with respect to MHI dynamically for sdx20. Change-Id: Ie38df2d3bbe80856a0b7cd49511ce64cb9aa4ce8 Signed-off-by: Mohammed Javid --- Documentation/devicetree/bindings/platform/msm/ipa.txt | 2 ++ drivers/platform/msm/ipa/ipa_v3/ipa.c | 9 +++++++++ drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 1 + 3 files changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/platform/msm/ipa.txt b/Documentation/devicetree/bindings/platform/msm/ipa.txt index c8bc8d4c87c9f..13b1a47116ff2 100644 --- a/Documentation/devicetree/bindings/platform/msm/ipa.txt +++ b/Documentation/devicetree/bindings/platform/msm/ipa.txt @@ -37,6 +37,8 @@ Optional: - qcom,smmu-disable-htw: boolean value to turn off SMMU page table caching - qcom,use-a2-service: determine if A2 service will be used - qcom,use-ipa-tethering-bridge: determine if tethering bridge will be used +- qcom,use-ipa-in-mhi-mode: Boolean context flag to indicate whether + device booting in MHI config or not. - qcom,use-ipa-bamdma-a2-bridge: determine if a2/ipa hw bridge will be used - qcom,ee: which EE is assigned to (non-secure) APPS from IPA-BAM POV. This is a number diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index d7bb93b5644a0..ba34032be7641 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -4874,6 +4874,7 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, ipa3_ctx->apply_rg10_wa = resource_p->apply_rg10_wa; ipa3_ctx->gsi_ch20_wa = resource_p->gsi_ch20_wa; ipa3_ctx->ipa3_active_clients_logging.log_rdy = false; + ipa3_ctx->ipa_config_is_mhi = resource_p->ipa_mhi_dynamic_config; if (resource_p->ipa_tz_unlock_reg) { ipa3_ctx->ipa_tz_unlock_reg_num = resource_p->ipa_tz_unlock_reg_num; @@ -5413,6 +5414,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, ipa_drv_res->ipa_bam_remote_mode = false; ipa_drv_res->modem_cfg_emb_pipe_flt = false; ipa_drv_res->ipa_wdi2 = false; + ipa_drv_res->ipa_mhi_dynamic_config = false; ipa_drv_res->use_64_bit_dma_mask = false; ipa_drv_res->wan_rx_ring_size = IPA_GENERIC_RX_POOL_SZ; ipa_drv_res->lan_rx_ring_size = IPA_GENERIC_RX_POOL_SZ; @@ -5475,6 +5477,13 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, ipa_drv_res->use_ipa_teth_bridge ? "True" : "False"); + ipa_drv_res->ipa_mhi_dynamic_config = + of_property_read_bool(pdev->dev.of_node, + "qcom,use-ipa-in-mhi-mode"); + IPADBG(": ipa_mhi_dynamic_config (%s)\n", + ipa_drv_res->ipa_mhi_dynamic_config + ? "True" : "False"); + ipa_drv_res->ipa_bam_remote_mode = of_property_read_bool(pdev->dev.of_node, "qcom,ipa-bam-remote-mode"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index 7425442fe2b9d..c6583e5e7807d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -1381,6 +1381,7 @@ struct ipa3_plat_drv_res { bool apply_rg10_wa; bool gsi_ch20_wa; bool tethered_flow_control; + bool ipa_mhi_dynamic_config; u32 ipa_tz_unlock_reg_num; struct ipa_tz_unlock_reg_info *ipa_tz_unlock_reg; }; From 5c61ba314ab0830b212cdb6a2f37aa019257f510 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Fri, 20 Apr 2018 16:29:06 +0530 Subject: [PATCH 369/508] ARM: dts: msm: Enbale MHI mode boot up flag on sdxpoorwills Enable MHI mode boot up flag in device tree to boot up IPA driver with MHI config. Change-Id: I90994259b2a7346116a20136082fc929813ca088 Signed-off-by: Mohammed Javid --- arch/arm/boot/dts/qcom/sdx20-v2-emmc-pcie-ep-mtp.dts | 6 +++++- arch/arm/boot/dts/qcom/sdx20-v2-nand-pcie-ep-mtp.dts | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/qcom/sdx20-v2-emmc-pcie-ep-mtp.dts b/arch/arm/boot/dts/qcom/sdx20-v2-emmc-pcie-ep-mtp.dts index aecf011e29299..72a82503c2af5 100644 --- a/arch/arm/boot/dts/qcom/sdx20-v2-emmc-pcie-ep-mtp.dts +++ b/arch/arm/boot/dts/qcom/sdx20-v2-emmc-pcie-ep-mtp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -58,6 +58,10 @@ status = "ok"; }; +&ipa_hw { + qcom,use-ipa-in-mhi-mode; +}; + &pcie0 { status = "disabled"; }; diff --git a/arch/arm/boot/dts/qcom/sdx20-v2-nand-pcie-ep-mtp.dts b/arch/arm/boot/dts/qcom/sdx20-v2-nand-pcie-ep-mtp.dts index 2988338e6588f..b8145820d2702 100644 --- a/arch/arm/boot/dts/qcom/sdx20-v2-nand-pcie-ep-mtp.dts +++ b/arch/arm/boot/dts/qcom/sdx20-v2-nand-pcie-ep-mtp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -47,6 +47,10 @@ status = "ok"; }; +&ipa_hw { + qcom,use-ipa-in-mhi-mode; +}; + &pcie0 { status = "disabled"; }; From 6b484a83c857f9181cb670364c0edbb4f092d096 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Tue, 24 Apr 2018 15:11:55 +0530 Subject: [PATCH 370/508] wlan: Reject the unsafe IOCTL's in the WEXT WEXT IOCTL's iw_set_mode and iw_get_mode is very unsafe to the driver and it needs to be rejected. Add changes to reject the IOCTL's iw_set_mode and iw_get_mode. Change-Id: Icba218feadabd5783568a75956a08cea09484be3 CRs-Fixed: 2230144 --- CORE/HDD/src/wlan_hdd_hostapd.c | 46 +------- CORE/HDD/src/wlan_hdd_wext.c | 187 +------------------------------- 2 files changed, 3 insertions(+), 230 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index 03573ec03a69e..f350747aac2e2 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -4565,50 +4565,6 @@ static int iw_get_ap_freq(struct net_device *dev, return ret; } -static int __iw_get_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int status = 0; - hdd_adapter_t *pAdapter; - hdd_context_t *pHddCtx; - - ENTER(); - - pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - if (NULL == pAdapter) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Adapter is NULL",__func__); - return -EINVAL; - } - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) - { - return status; - } - - wrqu->mode = IW_MODE_MASTER; - - EXIT(); - return status; -} - -static int iw_get_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret; - - vos_ssr_protect(__func__); - ret = __iw_get_mode(dev, info, wrqu, extra); - vos_ssr_unprotect(__func__); - - return ret; -} - - static int __iw_softap_stopbss(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, @@ -5103,7 +5059,7 @@ static const iw_handler hostapd_handler[] = (iw_handler) NULL, /* SIOCSIWFREQ */ (iw_handler) iw_get_ap_freq, /* SIOCGIWFREQ */ (iw_handler) NULL, /* SIOCSIWMODE */ - (iw_handler) iw_get_mode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCGIWMODE */ (iw_handler) NULL, /* SIOCSIWSENS */ (iw_handler) NULL, /* SIOCGIWSENS */ (iw_handler) NULL, /* SIOCSIWRANGE */ diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 2fd9c3b3798ee..7ed85bcd11eca 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -1632,189 +1632,6 @@ static int iw_get_name(struct net_device *dev, return ret; } -static int __iw_set_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - hdd_wext_state_t *pWextState; - hdd_adapter_t *pAdapter; - hdd_context_t *pHddCtx; - tCsrRoamProfile *pRoamProfile; - eCsrRoamBssType LastBSSType; - eMib_dot11DesiredBssType connectedBssType; - hdd_config_t *pConfig; - struct wireless_dev *wdev; - int status = 0; - - ENTER(); - - pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - if (NULL == pAdapter) - { - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter", __func__); - return 0; - } - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) - { - return status; - } - - pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - if (pWextState == NULL) - { - hddLog(LOGE, "%s ERROR: Data Storage Corruption", __func__); - return -EINVAL; - } - - wdev = dev->ieee80211_ptr; - pRoamProfile = &pWextState->roamProfile; - LastBSSType = pRoamProfile->BSSType; - - hddLog(LOG1, "%s Old Bss type = %d", __func__, LastBSSType); - - switch (wrqu->mode) - { - case IW_MODE_ADHOC: - hddLog(LOG1, "%s Setting AP Mode as IW_MODE_ADHOC", __func__); - pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS; - // Set the phymode correctly for IBSS. - pConfig = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; - pWextState->roamProfile.phyMode = hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode); - pAdapter->device_mode = WLAN_HDD_IBSS; - wdev->iftype = NL80211_IFTYPE_ADHOC; - break; - case IW_MODE_INFRA: - hddLog(LOG1, "%s Setting AP Mode as IW_MODE_INFRA", __func__); - pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE; - wdev->iftype = NL80211_IFTYPE_STATION; - break; - case IW_MODE_AUTO: - hddLog(LOG1, "%s Setting AP Mode as IW_MODE_AUTO", __func__); - pRoamProfile->BSSType = eCSR_BSS_TYPE_ANY; - break; - default: - hddLog(LOGE, "%s Unknown AP Mode value %d ", __func__, wrqu->mode); - return -EOPNOTSUPP; - } - - if ( LastBSSType != pRoamProfile->BSSType ) - { - //the BSS mode changed - // We need to issue disconnect if connected or in IBSS disconnect state - if ( hdd_connGetConnectedBssType( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) || - ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) ) - { - VOS_STATUS vosStatus; - // need to issue a disconnect to CSR. - INIT_COMPLETION(pAdapter->disconnect_comp_var); - vosStatus = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), - pAdapter->sessionId, - eCSR_DISCONNECT_REASON_IBSS_LEAVE ); - if(VOS_STATUS_SUCCESS == vosStatus) - { - long ret; - ret = wait_for_completion_interruptible_timeout( - &pAdapter->disconnect_comp_var, - msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); - if (ret <= 0) - hddLog(VOS_TRACE_LEVEL_ERROR, - FL("failed wait on disconnect_comp_var %ld"), ret); - } - } - } - - EXIT(); - return 0; -} - -static int iw_set_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret; - - vos_ssr_protect(__func__); - ret = __iw_set_mode(dev, info, wrqu, extra); - vos_ssr_unprotect(__func__); - - return ret; -} - -static int __iw_get_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - - hdd_wext_state_t *pWextState; - hdd_adapter_t *pAdapter; - hdd_context_t *pHddCtx; - int ret = 0; - - ENTER(); - - pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - if (NULL == pAdapter) - { - hddLog(VOS_TRACE_LEVEL_WARN, - "%s: Invalid context, pAdapter", __func__); - return 0; - } - - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) - { - return ret; - } - pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - if (pWextState == NULL) - { - hddLog(LOGE, "%s ERROR: Data Storage Corruption", __func__); - return -EINVAL; - } - - switch (pWextState->roamProfile.BSSType) - { - case eCSR_BSS_TYPE_INFRASTRUCTURE: - hddLog(LOG1, "%s returns IW_MODE_INFRA", __func__); - wrqu->mode = IW_MODE_INFRA; - break; - case eCSR_BSS_TYPE_IBSS: - case eCSR_BSS_TYPE_START_IBSS: - hddLog(LOG1, "%s returns IW_MODE_ADHOC", __func__); - wrqu->mode = IW_MODE_ADHOC; - break; - case eCSR_BSS_TYPE_ANY: - hddLog(LOG1, "%s returns IW_MODE_AUTO", __func__); - wrqu->mode = IW_MODE_AUTO; - break; - default: - hddLog(LOG1, "%s returns APMODE_UNKNOWN", __func__); - break; - } - - EXIT(); - return 0; -} - -static int iw_get_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - int ret; - - vos_ssr_protect(__func__); - ret = __iw_get_mode(dev, info, wrqu, extra); - vos_ssr_unprotect(__func__); - - return ret; -} - static int __iw_set_freq(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -11094,8 +10911,8 @@ static const iw_handler we_handler[] = (iw_handler) NULL, /* SIOCGIWNWID */ (iw_handler) iw_set_freq, /* SIOCSIWFREQ */ (iw_handler) iw_get_freq, /* SIOCGIWFREQ */ - (iw_handler) iw_set_mode, /* SIOCSIWMODE */ - (iw_handler) iw_get_mode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCSIWMODE */ + (iw_handler) NULL, /* SIOCGIWMODE */ (iw_handler) NULL, /* SIOCSIWSENS */ (iw_handler) NULL, /* SIOCGIWSENS */ (iw_handler) NULL, /* SIOCSIWRANGE */ From 81c0cab445d90ced0ab9ee7d01c1c6828e331e0e Mon Sep 17 00:00:00 2001 From: Bala Venkatesh Date: Mon, 16 Apr 2018 19:57:02 +0530 Subject: [PATCH 371/508] wlan: Don't disable tdls link in connect start Currently as part of connect start tdls mode is disabled. Tdls mode is not changed unless scan/bt coex changes the the mode to enable. Don't call the function "wlan_hdd_tdls_disable_offchan_and_ teardown_link" in connect start. CRs-Fixed: 2226583 Change-Id: I73af7c142da442849518fcf42342c04e75493399 --- CORE/HDD/src/wlan_hdd_cfg80211.c | 1 - 1 file changed, 1 deletion(-) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 3f8895044ae54..477f3f809f488 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -15723,7 +15723,6 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, return -EINVAL; } - wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx); pRoamProfile = &pWextState->roamProfile; From 3ad15d5bb7af0b4d4612ff6b8413d6b3602b4340 Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Mon, 16 Apr 2018 14:34:25 +0530 Subject: [PATCH 372/508] wlan: Drop probe resp only if ecsa new chn is different from APs oper chn IOT AP is advertising ecsa with new channel same as the current operating channel in probe response. DUT is dropping these frames based on ecsa present check. This results in connection latency as bss info of this AP is not informed to supplicant. Fix is to drop probe response having ecsa element only if new channel is different from APs current operating channel. Change-Id: Ia42a889b71af14f628cf532b6944322d049f04d5 CRs-Fixed: 2217394 --- CORE/MAC/src/pe/lim/limScanResultUtils.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CORE/MAC/src/pe/lim/limScanResultUtils.c b/CORE/MAC/src/pe/lim/limScanResultUtils.c index 8af7d6ffed8c4..3ba73268ef47b 100644 --- a/CORE/MAC/src/pe/lim/limScanResultUtils.c +++ b/CORE/MAC/src/pe/lim/limScanResultUtils.c @@ -452,7 +452,9 @@ limCheckAndAddBssDescription(tpAniSirGlobal pMac, */ if(pBPR->channelSwitchPresent) { - return; + if (pBPR->ext_chan_switch_ann.new_channel != + limGetChannelFromBeacon(pMac, pBPR)) + return; } if(pBPR->ecsa_present) { From 15757ba2fbc6a8ca4ec2e1fc34b149e131b9a235 Mon Sep 17 00:00:00 2001 From: Vijay Kumar TM Date: Wed, 25 Apr 2018 17:00:17 +0530 Subject: [PATCH 373/508] msm:camera: unlock mutex before return Checking stream status failure will return without unlocking the acquired lock. CRs-Fixed: 2149998 Change-Id: I5ed5cd8a4dfc02d0f6817078c7833b674465c988 Signed-off-by: Vijay Kumar TM --- drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c index c77944a0a047f..0a4b80e5cbe28 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c @@ -689,8 +689,10 @@ static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev, vfe_dev->hw_info->stats_hw_info->num_stats_comp_mask; rc = vfe_dev->hw_info->vfe_ops.stats_ops.check_streams( stats_data->stream_info); - if (rc < 0) + if (rc < 0) { + mutex_unlock(&vfe_dev->buf_mgr->lock); return rc; + } for (i = 0; i < stream_cfg_cmd->num_streams; i++) { idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]); From f01ec75908a5464020364f88ea76454c4bd29242 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Wed, 25 Apr 2018 15:50:15 +0530 Subject: [PATCH 374/508] wlan: Array out of bound in hdd change station There is an array out of bound access in __wlan_hdd_change_station api while filling the supported channels in local variable. Add a check to make sure that supported channels array never indexed beyond SIR_MAC_MAX_SUPP_CHANNELS. Change-Id: If1031196001be3ccc583804ef3661a1afe5422fc CRs-Fixed: 2231005 --- CORE/HDD/src/wlan_hdd_cfg80211.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 477f3f809f488..9f32185bdda18 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -12997,14 +12997,16 @@ static int __wlan_hdd_change_station(struct wiphy *wiphy, */ if (0 != params->supported_channels_len) { int i = 0,j = 0,k = 0, no_of_channels = 0 ; - for ( i = 0 ; i < params->supported_channels_len ; i+=2) + for ( i = 0 ; i < params->supported_channels_len + && j < SIR_MAC_MAX_SUPP_CHANNELS; i+=2) { int wifi_chan_index; StaParams.supported_channels[j] = params->supported_channels[i]; wifi_chan_index = ((StaParams.supported_channels[j] <= HDD_CHANNEL_14 ) ? 1 : 4 ); no_of_channels = params->supported_channels[i+1]; - for(k=1; k <= no_of_channels; k++) + for(k=1; k <= no_of_channels + && j < SIR_MAC_MAX_SUPP_CHANNELS - 1; k++) { StaParams.supported_channels[j+1] = StaParams.supported_channels[j] + wifi_chan_index; From cb6b5edae8b71c97c57ff30ce69e9ddabad91112 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Wed, 4 Oct 2017 15:58:16 -0700 Subject: [PATCH 375/508] net: ipc_router: Validate return from skb_peek The skb_peek and skb_peek_tail functions can return NULL if the skb list is empty. Check the return value before using the skb. CRs-Fixed: 2121368 Change-Id: If14320104ec37b8b7504e930ed8fd06e72d08724 Signed-off-by: Chris Lew --- net/ipc_router/ipc_router_core.c | 12 +++++++++++- net/ipc_router/ipc_router_socket.c | 6 +++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c index fd2dea170afd9..8d74fb7abbaef 100644 --- a/net/ipc_router/ipc_router_core.c +++ b/net/ipc_router/ipc_router_core.c @@ -2924,6 +2924,10 @@ static int loopback_data(struct msm_ipc_port *src, } temp_skb = skb_peek_tail(pkt->pkt_fragment_q); + if (!temp_skb) { + IPC_RTR_ERR("%s: Empty skb\n", __func__); + return -EINVAL; + } align_size = ALIGN_SIZE(pkt->length); skb_put(temp_skb, align_size); pkt->length += align_size; @@ -3085,6 +3089,11 @@ static int msm_ipc_router_write_pkt(struct msm_ipc_port *src, } temp_skb = skb_peek_tail(pkt->pkt_fragment_q); + if (!temp_skb) { + IPC_RTR_ERR("%s: Abort invalid pkt\n", __func__); + ret = -EINVAL; + goto out_write_pkt; + } align_size = ALIGN_SIZE(pkt->length); skb_put(temp_skb, align_size); pkt->length += align_size; @@ -3412,7 +3421,8 @@ int msm_ipc_router_recv_from(struct msm_ipc_port *port_ptr, align_size = ALIGN_SIZE(data_len); if (align_size) { temp_skb = skb_peek_tail((*pkt)->pkt_fragment_q); - skb_trim(temp_skb, (temp_skb->len - align_size)); + if (temp_skb) + skb_trim(temp_skb, (temp_skb->len - align_size)); } return data_len; } diff --git a/net/ipc_router/ipc_router_socket.c b/net/ipc_router/ipc_router_socket.c index 652531a8e592d..8604152dc577a 100644 --- a/net/ipc_router/ipc_router_socket.c +++ b/net/ipc_router/ipc_router_socket.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -150,6 +150,10 @@ static int msm_ipc_router_extract_msg(struct msghdr *m, hdr = &(pkt->hdr); if (addr && (hdr->type == IPC_ROUTER_CTRL_CMD_RESUME_TX)) { temp = skb_peek(pkt->pkt_fragment_q); + if (!temp || !temp->data) { + IPC_RTR_ERR("%s: Invalid skb\n", __func__); + return -EINVAL; + } ctl_msg = (union rr_control_msg *)(temp->data); addr->family = AF_MSM_IPC; addr->address.addrtype = MSM_IPC_ADDR_ID; From cd688c19bf9cb6466fdb5224e012c723edc6ee8e Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Wed, 25 Apr 2018 01:47:22 +0530 Subject: [PATCH 376/508] wlan: Add support for suspend_noirq Before going for suspend, suspend_noirq is called to handle race condition Change-Id: I5d0fd339fddd5cbf19868cb6869439099c74096f CRs-Fixed: 2231816 --- CORE/HDD/src/wlan_hdd_dev_pwr.c | 62 +++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/CORE/HDD/src/wlan_hdd_dev_pwr.c b/CORE/HDD/src/wlan_hdd_dev_pwr.c index 85c3349d10589..92016c3f3bf6b 100644 --- a/CORE/HDD/src/wlan_hdd_dev_pwr.c +++ b/CORE/HDD/src/wlan_hdd_dev_pwr.c @@ -453,6 +453,53 @@ int __hddDevSuspendHdlr(struct device *dev) return 0; } +int __hddDevSuspendNoIrqHdlr(struct device *dev) +{ + int ret = 0; + hdd_context_t* pHddCtx = NULL; + pVosContextType pVosContext; + pVosSchedContext pSchedContext; + + ENTER(); + + pHddCtx = (hdd_context_t*)wcnss_wlan_get_drvdata(dev); + + /* Get the HDD context */ + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + { + return ret; + } + + if(pHddCtx->isWlanSuspended != TRUE) + { + VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL, + "%s: WLAN is not in suspended state",__func__); + return -EPERM; + } + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if(pVosContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL, + "%s: Failed vos_get_global_context",__func__); + return -EPERM; + } + + pSchedContext = &pVosContext->vosSched; + + if (test_bit(RX_POST_EVENT, &pSchedContext->rxEventFlag)) + { + VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_INFO, + "%s: WLAN suspend is not honored",__func__); + return -EPERM; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Suspend No IRQ done successfully",__func__); + EXIT(); + return 0; +} + int hddDevSuspendHdlr(struct device *dev) { int ret; @@ -463,6 +510,19 @@ int hddDevSuspendHdlr(struct device *dev) return ret; } +int hddDevSuspendNoIrqHdlr(struct device *dev) +{ + int ret; + vos_ssr_protect(__func__); + ret = __hddDevSuspendNoIrqHdlr(dev); + vos_ssr_unprotect(__func__); + return ret; +} + +int hddDevResumeNoIrqHdlr(struct device *dev) +{ + return 0; +} /*---------------------------------------------------------------------------- @brief Function to resume the wlan driver. @@ -520,6 +580,8 @@ int hddDevResumeHdlr(struct device *dev) static const struct dev_pm_ops pm_ops = { .suspend = hddDevSuspendHdlr, .resume = hddDevResumeHdlr, + .suspend_noirq = hddDevSuspendNoIrqHdlr, + .resume_noirq = hddDevResumeNoIrqHdlr }; /*---------------------------------------------------------------------------- From 43d66b7f510961180d230dab1839c6054538b56d Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Mon, 19 Jun 2017 15:42:50 -0700 Subject: [PATCH 377/508] diag: Update msg mask tables for new SSID Update the diag headers and msg mask tables to account for a new ssid group. CRs-Fixed: 2055789 Change-Id: I3abd816d5e99bff263b753fb1070a2672ecea46c Signed-off-by: Chris Lew Signed-off-by: Manoj Prabhu B --- drivers/char/diag/diag_masks.c | 3 ++- include/linux/diagchar.h | 23 +++++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c index e8f5bceaaa411..62b6e22d7278c 100644 --- a/drivers/char/diag/diag_masks.c +++ b/drivers/char/diag/diag_masks.c @@ -60,7 +60,8 @@ static const struct diag_ssid_range_t msg_mask_tbl[] = { { .ssid_first = MSG_SSID_21, .ssid_last = MSG_SSID_21_LAST }, { .ssid_first = MSG_SSID_22, .ssid_last = MSG_SSID_22_LAST }, { .ssid_first = MSG_SSID_23, .ssid_last = MSG_SSID_23_LAST }, - { .ssid_first = MSG_SSID_24, .ssid_last = MSG_SSID_24_LAST } + { .ssid_first = MSG_SSID_24, .ssid_last = MSG_SSID_24_LAST }, + { .ssid_first = MSG_SSID_25, .ssid_last = MSG_SSID_25_LAST } }; static int diag_apps_responds(void) diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h index 0ae23ddbc528b..c3364dce7eeaa 100644 --- a/include/linux/diagchar.h +++ b/include/linux/diagchar.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2016, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -143,7 +143,7 @@ the appropriate macros. */ /* This needs to be modified manually now, when we add a new RANGE of SSIDs to the msg_mask_tbl */ -#define MSG_MASK_TBL_CNT 25 +#define MSG_MASK_TBL_CNT 26 #define APPS_EVENT_LAST_ID 0x0B2A #define MSG_SSID_0 0 @@ -194,8 +194,10 @@ the appropriate macros. */ #define MSG_SSID_22_LAST 10377 #define MSG_SSID_23 10400 #define MSG_SSID_23_LAST 10416 -#define MSG_SSID_24 0xC000 -#define MSG_SSID_24_LAST 0xC063 +#define MSG_SSID_24 10500 +#define MSG_SSID_24_LAST 10505 +#define MSG_SSID_25 0xC000 +#define MSG_SSID_25_LAST 0xC063 static const uint32_t msg_bld_masks_0[] = { MSG_LVL_LOW, @@ -855,6 +857,19 @@ static const uint32_t msg_bld_masks_23[] = { MSG_LVL_LOW }; +static const uint32_t msg_bld_masks_24[] = { + MSG_LVL_HIGH, + MSG_LVL_HIGH, + MSG_LVL_HIGH, + MSG_LVL_HIGH, + MSG_LVL_HIGH, + MSG_LVL_HIGH +}; + +static const uint32_t msg_bld_masks_25[] = { + MSG_LVL_LOW +}; + /* LOG CODES */ static const uint32_t log_code_last_tbl[] = { 0x0, /* EQUIP ID 0 */ From 49c3f909e8701d7666574875a33c96fa5fc03e8b Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Fri, 16 Feb 2018 16:01:13 +0530 Subject: [PATCH 378/508] wlan: Support to enhance debug framework Propagation from qcacld-2.0 to prima. Add interface to provide information on supported logger features when requested by the user space application. Change-Id: If70001d431ffc63d54398107bbc685a55cae5011 CRs-Fixed: 2191452 --- CORE/HDD/inc/wlan_hdd_cfg80211.h | 42 ++++++++++++++ CORE/HDD/inc/wlan_hdd_main.h | 10 ++++ CORE/HDD/src/wlan_hdd_cfg80211.c | 95 ++++++++++++++++++++++++++++++++ CORE/HDD/src/wlan_hdd_main.c | 8 +++ 4 files changed, 155 insertions(+) diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h index 4ea1c4a64ba90..8ca4e674ca9b2 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -212,6 +212,9 @@ enum qca_nl80211_vendor_subcmds { /* Wi-Fi Configuration subcommands */ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION = 74, QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION = 75, + + QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET = 76, + QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA = 77, QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI = 80, @@ -1430,6 +1433,27 @@ enum qca_wlan_vendor_config { QCA_WLAN_VENDOR_ATTR_CONFIG_LAST - 1 }; +/** + * enum qca_wlan_vendor_attr_get_logger_features - value for logger + * supported features + * @QCA_WLAN_VENDOR_ATTR_LOGGER_INVALID - Invalid + * @QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED - Indicate the supported features + * @QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST - To keep track of the last enum + * @QCA_WLAN_VENDOR_ATTR_LOGGER_MAX - max value possible for this type + * + * enum values are used for NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET sub command. + */ +enum qca_wlan_vendor_attr_get_logger_features { + QCA_WLAN_VENDOR_ATTR_LOGGER_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED = 1, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_LOGGER_MAX = + QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST - 1, +}; + /* Feature defines */ #define WIFI_FEATURE_INFRA 0x0001 /* Basic infrastructure mode */ #define WIFI_FEATURE_INFRA_5G 0x0002 /* Support for 5 GHz Band */ @@ -1596,6 +1620,24 @@ enum qca_wlan_vendor_attr_offloaded_packets }; #endif +/** + * enum wifi_logger_supported_features - values for supported logger features + * @WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED - Per packet statistics + * @WIFI_LOGGER_CONNECT_EVENT_SUPPORTED - Logging of Connectivity events + * @WIFI_LOGGER_POWER_EVENT_SUPPORTED - Power of driver + * @WIFI_LOGGER_WAKE_LOCK_SUPPORTED - Wakelock of driver + * @WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED - monitor FW health + */ +enum wifi_logger_supported_features { + WIFI_LOGGER_MEMORY_DUMP_SUPPORTED = (1 << (0)), + WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED = (1 << (1)), + WIFI_LOGGER_CONNECT_EVENT_SUPPORTED = (1 << (2)), + WIFI_LOGGER_POWER_EVENT_SUPPORTED = (1 << (3)), + WIFI_LOGGER_WAKE_LOCK_SUPPORTED = (1 << (4)), + WIFI_LOGGER_VERBOSE_SUPPORTED = (1 << (5)), + WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED = (1 << (6)), +}; + struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo ); diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index eca0d144f60fa..ef05de519b2ce 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -2374,4 +2374,14 @@ int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr); int hdd_get_disable_ch_list(hdd_context_t *hdd_ctx, tANI_U8 *buf, tANI_U8 buf_len); +/** + * hdd_is_memdump_supported() - to check if memdump feature support + * + * This function is used to check if memdump feature is supported in + * the host driver + * + * Return: true if supported and false otherwise + */ +bool hdd_is_memdump_supported(void); + #endif // end #if !defined( WLAN_HDD_MAIN_H ) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 9f32185bdda18..8f8de3799f0c9 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -8519,6 +8519,93 @@ static int wlan_hdd_cfg80211_apfind_cmd(struct wiphy *wiphy, return ret; } #endif /* WLAN_FEATURE_APFIND */ + +/** + * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * This is called by userspace to know the supported logger features + * + * Return: Return the Success or Failure code. + */ +static int +__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + int status; + uint32_t features; + struct sk_buff *reply_skb = NULL; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) + return -EINVAL; + + features = 0; + + if (hdd_is_memdump_supported()) + features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED; + + if (hdd_ctx->cfg_ini->wlanLoggingEnable && + hdd_ctx->cfg_ini->enableFatalEvent && + hdd_ctx->is_fatal_event_log_sup) { + features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED; + features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED; + } + + reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN); + if (!reply_skb) { + hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + return -ENOMEM; + } + + hddLog(LOG1, FL("Supported logger features: 0x%0x"), features); + if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED, + features)) { + hddLog(LOGE, FL("nla put fail")); + kfree_skb(reply_skb); + return -EINVAL; + } + + return cfg80211_vendor_cmd_reply(reply_skb); +} + +/** + * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * This is called by userspace to know the supported logger features + * + * Return: Return the Success or Failure code. + */ +static int +wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { { @@ -8782,6 +8869,14 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = WIPHY_VENDOR_CMD_NEED_RUNNING, .doit = hdd_cfg80211_get_station_cmd }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_get_logger_supp_feature + }, }; /* vendor specific events */ diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 22ea01b386a91..bd3e0d1de3847 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -17912,6 +17912,14 @@ void wlan_hdd_tsf_init(hdd_adapter_t *adapter) #endif +bool hdd_is_memdump_supported(void) +{ +#ifdef WLAN_FEATURE_MEMDUMP + return true; +#endif + return false; +} + //Register the module init/exit functions module_init(hdd_module_init); module_exit(hdd_module_exit); From fb3fd97899531545f8f81d7b137851d4c82d1819 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Mon, 30 Apr 2018 12:46:52 +0530 Subject: [PATCH 379/508] wlan: Switch from module_param_call() to module_param_cb() The definition of module_param_call() was changed in 4.15 and in order to have module params that work on the kernel both before and after that change switch to using module_param_cb() since its definition has not changed. Change-Id: I4af7c802ae62041636eda3047805630a16490e75 CRs-Fixed: 2233318 --- CORE/HDD/src/wlan_hdd_main.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index bd3e0d1de3847..8abcdcd8796ca 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -14207,13 +14207,13 @@ static void __exit hdd_module_exit(void) #ifdef MODULE static int fwpath_changed_handler(const char *kmessage, - struct kernel_param *kp) + const struct kernel_param *kp) { return param_set_copystring(kmessage, kp); } static int con_mode_handler(const char *kmessage, - struct kernel_param *kp) + const struct kernel_param *kp) { return param_set_int(kmessage, kp); } @@ -14260,7 +14260,7 @@ static int kickstart_driver(void) --------------------------------------------------------------------------*/ static int fwpath_changed_handler(const char *kmessage, - struct kernel_param *kp) + const struct kernel_param *kp) { int ret; @@ -14283,7 +14283,8 @@ static int fwpath_changed_handler(const char *kmessage, \return - --------------------------------------------------------------------------*/ -static int con_mode_handler(const char *kmessage, struct kernel_param *kp) +static int con_mode_handler(const char *kmessage, + const struct kernel_param *kp) { int ret; @@ -17928,10 +17929,20 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Qualcomm Atheros, Inc."); MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER"); -module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode, +static const struct kernel_param_ops con_mode_ops = { + .set = con_mode_handler, + .get = param_get_int, +}; + +static const struct kernel_param_ops fwpath_ops = { + .set = fwpath_changed_handler, + .get = param_get_string, +}; + +module_param_cb(con_mode, &con_mode_ops, &con_mode, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); -module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath, +module_param_cb(fwpath, &fwpath_ops, &fwpath, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); module_param(enable_dfs_chan_scan, int, From ac589f44c5ae0a0e1a2b48f9ede689264e7b4cde Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Tue, 24 Apr 2018 17:29:18 +0530 Subject: [PATCH 380/508] wlan: Do not start auto bmps timer when aggregation is disabled On receiving disable aggregation indication, device is put to full power and auto bmps timer is stated if there is infra session. This results in enter_bmps request to be sent during SCO which will lead to BT missing interrupts. Fix is to not start auto bmps timer when device is put to full power as part of disable aggregation indication. Change-Id: Ifc1c415bdc3b9ceeedf4e18be7e17f1954f6f659 CRs-Fixed: 2231072 --- CORE/SME/inc/btcApi.h | 4 +++- CORE/SME/src/btc/btcApi.c | 3 ++- CORE/SME/src/pmc/pmc.c | 14 +++++++++++++- CORE/SME/src/sme_common/sme_Api.c | 2 ++ 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CORE/SME/inc/btcApi.h b/CORE/SME/inc/btcApi.h index c6da770b5fff8..444ec2ffca39d 100644 --- a/CORE/SME/inc/btcApi.h +++ b/CORE/SME/inc/btcApi.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2012-2013, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2016, 2018 The Linux Foundation. All rights + * reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -372,6 +373,7 @@ typedef struct sSmeBtcInfo bool btc_scan_compromise_sco; v_U8_t btcBssfordisableaggr[VOS_MAC_ADDRESS_LEN]; vos_timer_t enableUapsdTimer; + bool agg_disabled; } tSmeBtcInfo, *tpSmeBtcInfo; diff --git a/CORE/SME/src/btc/btcApi.c b/CORE/SME/src/btc/btcApi.c index 32c1dd6e34be6..0aec164218a01 100644 --- a/CORE/SME/src/btc/btcApi.c +++ b/CORE/SME/src/btc/btcApi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -98,6 +98,7 @@ VOS_STATUS btcOpen (tHalHandle hHal) pMac->btc.btcHBActive = VOS_TRUE; pMac->btc.btc_scan_compromise_esco = false; pMac->btc.btc_scan_compromise_sco = false; + pMac->btc.agg_disabled = false; for (i = 0; i < MWS_COEX_MAX_VICTIM_TABLE; i++) { diff --git a/CORE/SME/src/pmc/pmc.c b/CORE/SME/src/pmc/pmc.c index f5539ff669276..b391aacea5010 100644 --- a/CORE/SME/src/pmc/pmc.c +++ b/CORE/SME/src/pmc/pmc.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014, 2016, 2018 The Linux Foundation. All rights + * reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -2518,6 +2519,11 @@ eHalStatus pmcEnterBmpsCheck( tpAniSirGlobal pMac ) } } + if (pMac->btc.agg_disabled) { + pmcLog(pMac, LOG1, FL("Aggregation disabled. BMPS can't be started")); + return eHAL_STATUS_FAILURE; + } + return ( eHAL_STATUS_SUCCESS ); } @@ -2558,6 +2564,12 @@ tANI_BOOLEAN pmcShouldBmpsTimerRun( tpAniSirGlobal pMac ) pmcLog(pMac, LOG1, FL("No Infra Session. BMPS can't be started")); return eANI_BOOLEAN_FALSE; } + + if (pMac->btc.agg_disabled) { + pmcLog(pMac, LOG1, FL("Aggregation disabled. BMPS can't be started")); + return eANI_BOOLEAN_FALSE; + } + return eANI_BOOLEAN_TRUE; } diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c index 97844158998df..2f2102066c183 100644 --- a/CORE/SME/src/sme_common/sme_Api.c +++ b/CORE/SME/src/sme_common/sme_Api.c @@ -2737,6 +2737,7 @@ eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg) if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_DISABLE_AGGREGATION_IN_2p4) { + pMac->btc.agg_disabled = true; smsLog( pMac, LOG1, FL("SIR_COEX_IND_TYPE_DISABLE_AGGREGATION_IN_2p4")); sme_RequestFullPower(hHal, NULL, NULL, eSME_REASON_OTHER); pMac->isCoexScoIndSet = 1; @@ -2748,6 +2749,7 @@ eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg) } else if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_ENABLE_AGGREGATION_IN_2p4) { + pMac->btc.agg_disabled = false; smsLog( pMac, LOG1, FL("SIR_COEX_IND_TYPE_ENABLE_AGGREGATION_IN_2p4")); pMac->isCoexScoIndSet = 0; sme_RequestBmps(hHal, NULL, NULL); From 8b6a8d3be90506fa38353eed7248e3dfce3a0965 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Mon, 30 Apr 2018 18:56:17 +0530 Subject: [PATCH 381/508] wlan: Increase MAX_CFG_INI_ITEMS to 1024 propagation from qcacld-2.0 to prima Increase the maximum config ini items from 512 to 1024. Change-Id: I5c4958d5c743f1e0b03a4f7b41e21ff9787ccd07 CRs-Fixed: 2233531 --- CORE/HDD/inc/wlan_hdd_cfg.h | 2 +- CORE/HDD/src/wlan_hdd_cfg.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index bca3e87ff8ebf..7cd3262acd1a6 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -54,7 +54,7 @@ #endif /* DHCP_SERVER_OFFLOAD */ //Number of items that can be configured -#define MAX_CFG_INI_ITEMS 512 +#define MAX_CFG_INI_ITEMS 1024 #ifdef SAP_AUTH_OFFLOAD /* 802.11 pre-share key length */ diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index 60eeb56819648..160c3ee9dfe0e 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -4847,6 +4847,7 @@ static VOS_STATUS hdd_apply_cfg_ini( hdd_context_t *pHddCtx, tCfgIniEntry* iniTa { hddLog(LOGE, "%s: MAX_CFG_INI_ITEMS too small, must be at least %ld", __func__, cRegTableEntries); + VOS_ASSERT(1); } for ( idx = 0; idx < cRegTableEntries; idx++, pRegEntry++ ) From a01494d056bdea5363ba55b9fabe528a2d18fc2f Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Thu, 19 Apr 2018 13:41:16 +0530 Subject: [PATCH 382/508] msm: ipa: rmnet: Make code changes with respect to CR#2046006 Check for CAP_NET_ADMIN capability of the user space application who tries to access rmnet driver IOCTL. Change-Id: If6bb4b54659306c5103b5e34bf02c7234c851e0a CRs-Fixed: 2226355 Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c | 2 ++ drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c index 9253782ad6a9d..abff5aad1bccc 100644 --- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c @@ -1312,6 +1312,8 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /* Extended IOCTLs */ case RMNET_IOCTL_EXTENDED: + if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) + return -EPERM; IPAWANDBG("get ioctl: RMNET_IOCTL_EXTENDED\n"); if (copy_from_user(&extend_ioctl_data, (u8 *)ifr->ifr_ifru.ifru_data, diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index 28a495eb16996..725ad4d240769 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -1449,6 +1449,8 @@ static int ipa3_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /* Extended IOCTLs */ case RMNET_IOCTL_EXTENDED: + if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) + return -EPERM; IPAWANDBG("get ioctl: RMNET_IOCTL_EXTENDED\n"); if (copy_from_user(&extend_ioctl_data, (u8 *)ifr->ifr_ifru.ifru_data, From 596b8b36785ac344c3882743910f6fb6081d5b3c Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Tue, 1 May 2018 20:17:38 +0530 Subject: [PATCH 383/508] wlan: Correctly report 20 MHz bandwidth in Linux 4.x qcacld-3.0 to prima propagation. Linux kernel 4.0 introduced a new way for drivers to report bandwidth information to userspace. Prior to this rate information was indicated by setting an appropriate BW flag in the struct rate_info flags field, and 20MHz bandwidth was assumed if no flag was set. Linux 4.0 introduced a new bw field to struct rate_info, and the driver was updated to set this field in all cases where previously a bandwidth-specific flag had been set. Unfortunately in the 20 MHz bandwidth case the driver was not previously setting a bandwidth-specific flag, and hence in the current case it is not setting the bw field. This manifests itself in the following warning emitted by the kernel when the device is associated to an Access Point with a 20MHz bandwidth: WARNING: at kernel/msm-4.4/net/wireless/util.c:1137 Modules linked in: wlan(O) PC is at cfg80211_calculate_bitrate+0xdc/0x1f0 LR is at nl80211_put_sta_rate+0x64/0x1dc Fix this issue by initializing the rate_info bw field to 20 MHz prior to calculating the bandwidth. If the bandwidth is anything other than 20 MHz then this default value will later be overwritten. Change-Id: I734b05e0e41c7a859939372fe4d8a3668a08c668 CRs-Fixed: 2234166 --- CORE/HDD/src/wlan_hdd_cfg80211.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 8f8de3799f0c9..6d0c72178c636 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -18193,6 +18193,11 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_devic (int) pAdapter->hdd_stats.ClassA_stat.mcs_index); #endif //LINKSPEED_DEBUG_ENABLED +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS) + /* assume basic BW. anything else will override this later */ + sinfo->txrate.bw = RATE_INFO_BW_20; +#endif + if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed) { // we do not want to necessarily report the current speed From ae5adf4b2101d44de78e849dad91e5abf8d5f1c4 Mon Sep 17 00:00:00 2001 From: Dundi Raviteja Date: Mon, 23 Apr 2018 20:44:47 +0530 Subject: [PATCH 384/508] wlan: Add support to dynamically configure BTC and Concurrent dwell time Add new driver commands to dynamically set and get below dwell time parameters. 1. BTC dwell time for both ESCO and SCO 2. Active and Passive concurrent dwell time Change-Id: Ib293f01fe985493e01b67ef04a16c5aa4cdbfcd0 CRs-Fixed: 2230037 --- CORE/HDD/src/wlan_hdd_main.c | 430 +++++++++++++++++++++++++++++++++++ 1 file changed, 430 insertions(+) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 8abcdcd8796ca..d9ef048c01b29 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -2856,6 +2856,67 @@ static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, return ret; } +/** + * hdd_btc_get_dwell_time() - Get BTC dwell time parameters + * @pCfg: Pointer to HDD context + * @command: ASCII text command that is received + * @extra: Pointer to copy data sent to user + * @n: size of 'extra' buffer + * @len: length copied to 'extra' buffer + * + * Driver commands: + * wpa_cli DRIVER BTCGETDWELLTIME ESCO MAX + * wpa_cli DRIVER BTCGETDWELLTIME ESCO MIN + * wpa_cli DRIVER BTCGETDWELLTIME SCO MAX + * wpa_cli DRIVER BTCGETDWELLTIME SCO MIN + * + * Return: 0 for success non-zero for failure + */ + +static int hdd_btc_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, + char *extra, tANI_U8 n, tANI_U8 *len) +{ + int ret = 0; + + if (!pCfg || !command || !extra || !len) + { + hddLog(LOGE, FL("Argument passsed for BTCGETDWELLTIME is incorrect")); + ret = -EINVAL; + return ret; + } + + if (strncmp(command, "BTCGETDWELLTIME ESCO MAX", 24) == 0) + { + *len = scnprintf(extra, n, "BTCGETDWELLTIME ESCO MAX %u\n", + (int)pCfg->max_chntime_btc_esco); + return ret; + } + else if (strncmp(command, "BTCGETDWELLTIME ESCO MIN", 24) == 0) + { + *len = scnprintf(extra, n, "BTCGETDWELLTIME ESCO MIN %u\n", + (int)pCfg->min_chntime_btc_esco); + return ret; + } + else if (strncmp(command, "BTCGETDWELLTIME SCO MAX", 23) == 0) + { + *len = scnprintf(extra, n, "BTCGETDWELLTIME SCO MAX %u\n", + (int)pCfg->max_chntime_btc_sco); + return ret; + } + else if (strncmp(command, "BTCGETDWELLTIME SCO MIN", 23) == 0) + { + *len = scnprintf(extra, n, "BTCGETDWELLTIME SCO MIN %u\n", + (int)pCfg->min_chntime_btc_sco); + return ret; + } + else + { + ret = -EINVAL; + } + + return ret; +} + int hdd_drv_cmd_validate(tANI_U8 *command, int len) { if (command[len] != ' ') @@ -2864,6 +2925,313 @@ int hdd_drv_cmd_validate(tANI_U8 *command, int len) return 0; } +#ifdef WLAN_AP_STA_CONCURRENCY + +/** + * hdd_conc_get_dwell_time() - Get concurrency dwell time parameters + * @pCfg: Pointer to HDD context + * @command: ASCII text command that is received + * @extra: Pointer to copy data sent to user + * @n: size of 'extra' buffer + * @len: length copied to 'extra' buffer + * + * Driver commands: + * wpa_cli DRIVER CONCGETDWELLTIME ACTIVE MAX + * wpa_cli DRIVER CONCGETDWELLTIME ACTIVE MIN + * wpa_cli DRIVER CONCGETDWELLTIME PASSIVE MAX + * wpa_cli DRIVER CONCGETDWELLTIME PASSIVE MIN + * + * Return: 0 for success non-zero for failure + */ + +static int hdd_conc_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, + char *extra, tANI_U8 n, tANI_U8 *len) +{ + int ret = 0; + + if (!pCfg || !command || !extra || !len) + { + hddLog(LOGE, FL("Argument passsed for CONCGETDWELLTIME is incorrect")); + ret = -EINVAL; + return ret; + } + + if (strncmp(command, "CONCGETDWELLTIME ACTIVE MAX", 27) == 0) + { + *len = scnprintf(extra, n, "CONCGETDWELLTIME ACTIVE MAX %u\n", + (int)pCfg->nActiveMaxChnTimeConc); + return ret; + } + else if (strncmp(command, "CONCGETDWELLTIME ACTIVE MIN", 27) == 0) + { + *len = scnprintf(extra, n, "CONCGETDWELLTIME ACTIVE MIN %u\n", + (int)pCfg->nActiveMinChnTimeConc); + return ret; + } + else if (strncmp(command, "CONCGETDWELLTIME PASSIVE MAX", 28) == 0) + { + *len = scnprintf(extra, n, "CONCGETDWELLTIME PASSIVE MAX %u\n", + (int)pCfg->nPassiveMaxChnTimeConc); + return ret; + } + else if (strncmp(command, "CONCGETDWELLTIME PASSIVE MIN", 28) == 0) + { + *len = scnprintf(extra, n, "CONCGETDWELLTIME PASSIVE MIN %u\n", + (int)pCfg->nPassiveMinChnTimeConc); + return ret; + } + else + { + ret = -EINVAL; + } + + return ret; +} + +/** + * hdd_conc_set_dwell_time() - Set concurrency dwell time parameters + * @pAdapter: Adapter upon which the command was received + * @command: ASCII text command that is received + * + * Driver commands: + * wpa_cli DRIVER CONCSETDWELLTIME ACTIVE MAX + * wpa_cli DRIVER CONCSETDWELLTIME ACTIVE MIN + * wpa_cli DRIVER CONCSETDWELLTIME PASSIVE MAX + * + * Return: 0 for success non-zero for failure + */ + +static int hdd_conc_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command) +{ + tHalHandle hHal; + hdd_config_t *pCfg; + tANI_U8 *value = command; + int val = 0, ret = 0, temp = 0; + tSmeConfigParams smeConfig; + + if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini) + || !(hHal = (WLAN_HDD_GET_HAL_CTX(pAdapter)))) + { + hddLog(LOGE, FL("Argument passed for CONCSETDWELLTIME is incorrect")); + ret = -EINVAL; + return ret; + } + + vos_mem_zero(&smeConfig, sizeof(smeConfig)); + sme_GetConfigParam(hHal, &smeConfig); + + if (strncmp(command, "CONCSETDWELLTIME ACTIVE MAX", 27) == 0 ) + { + if (hdd_drv_cmd_validate(command, 27)) { + hddLog(LOGE, FL("Invalid driver command")); + return -EINVAL; + } + + value = value + 28; + temp = kstrtou32(value, 10, &val); + if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_CONC_MIN || + val > CFG_ACTIVE_MAX_CHANNEL_TIME_CONC_MAX) + { + hddLog(LOGE, FL("Argument passed for CONCSETDWELLTIME ACTIVE MAX is incorrect")); + ret = -EFAULT; + return ret; + } + pCfg->nActiveMaxChnTimeConc = val; + smeConfig.csrConfig.nActiveMaxChnTimeConc = val; + sme_UpdateConfig(hHal, &smeConfig); + } + else if (strncmp(command, "CONCSETDWELLTIME ACTIVE MIN", 27) == 0) + { + if (hdd_drv_cmd_validate(command, 27)) { + hddLog(LOGE, FL("Invalid driver command")); + return -EINVAL; + } + + value = value + 28; + temp = kstrtou32(value, 10, &val); + if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_CONC_MIN || + val > CFG_ACTIVE_MIN_CHANNEL_TIME_CONC_MAX) + { + hddLog(LOGE, FL("Argument passsed for CONCSETDWELLTIME ACTIVE MIN is incorrect")); + ret = -EFAULT; + return ret; + } + pCfg->nActiveMinChnTimeConc = val; + smeConfig.csrConfig.nActiveMinChnTimeConc = val; + sme_UpdateConfig(hHal, &smeConfig); + } + else if (strncmp(command, "CONCSETDWELLTIME PASSIVE MAX", 28) == 0) + { + if (hdd_drv_cmd_validate(command, 28)) { + hddLog(LOGE, FL("Invalid driver command")); + return -EINVAL; + } + + value = value + 29; + temp = kstrtou32(value, 10, &val); + if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_MIN || + val > CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_MAX) + { + hddLog(LOGE, FL("Argument passed for CONCSETDWELLTIME PASSIVE MAX is incorrect")); + ret = -EFAULT; + return ret; + } + pCfg->nPassiveMaxChnTimeConc = val; + smeConfig.csrConfig.nPassiveMaxChnTimeConc = val; + sme_UpdateConfig(hHal, &smeConfig); + } + else if (strncmp(command, "CONCSETDWELLTIME PASSIVE MIN", 28) == 0) + { + if (hdd_drv_cmd_validate(command, 28)) { + hddLog(LOGE, FL("Invalid driver command")); + return -EINVAL; + } + + value = value + 29; + temp = kstrtou32(value, 10, &val); + if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_CONC_MIN || + val > CFG_PASSIVE_MIN_CHANNEL_TIME_CONC_MAX ) + { + hddLog(LOGE, FL("Argument passed for CONCSETDWELLTIME PASSIVE MIN is incorrect")); + ret = -EFAULT; + return ret; + } + pCfg->nPassiveMinChnTimeConc = val; + smeConfig.csrConfig.nPassiveMinChnTimeConc = val; + sme_UpdateConfig(hHal, &smeConfig); + } + else + { + ret = -EINVAL; + } + + return ret; +} + +#endif + +/** + * hdd_btc_set_dwell_time() - Set BTC dwell time parameters + * @pAdapter: Adapter upon which the command was received + * @command: ASCII text command that is received + * + * Driver commands: + * wpa_cli DRIVER BTCSETDWELLTIME ESCO MAX + * wpa_cli DRIVER BTCSETDWELLTIME ESCO MIN + * wpa_cli DRIVER BTCSETDWELLTIME SCO MAX + * wpa_cli DRIVER BTCSETDWELLTIME SCO MIN + * + * Return: 0 for success non-zero for failure + */ + +static int hdd_btc_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command) +{ + tHalHandle hHal; + hdd_config_t *pCfg; + tANI_U8 *value = command; + int val = 0, ret = 0, temp = 0; + tSmeConfigParams smeConfig; + + if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini) + || !(hHal = (WLAN_HDD_GET_HAL_CTX(pAdapter)))) + { + hddLog(LOGE, FL("Argument passed for BTCSETDWELLTIME is incorrect")); + ret = -EINVAL; + return ret; + } + + vos_mem_zero(&smeConfig, sizeof(smeConfig)); + sme_GetConfigParam(hHal, &smeConfig); + + if (strncmp(command, "BTCSETDWELLTIME ESCO MAX", 24) == 0) + { + if (hdd_drv_cmd_validate(command, 24)) { + hddLog(LOGE, FL("Invalid driver command")); + return -EINVAL; + } + + value = value + 25; + temp = kstrtou32(value, 10, &val); + if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_BTC_MIN || + val > CFG_ACTIVE_MAX_CHANNEL_TIME_BTC_MAX) + { + hddLog(LOGE, FL("Argument passed for BTCSETDWELLTIME ESCO MAX is incorrect")); + ret = -EFAULT; + return ret; + } + pCfg->max_chntime_btc_esco = val; + smeConfig.csrConfig.max_chntime_btc_esco = val; + sme_UpdateConfig(hHal, &smeConfig); + } + else if (strncmp(command, "BTCSETDWELLTIME ESCO MIN", 24) == 0) + { + if (hdd_drv_cmd_validate(command, 24)) { + hddLog(LOGE, FL("Invalid driver command")); + return -EINVAL; + } + + value = value + 25; + temp = kstrtou32(value, 10, &val); + if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_BTC_MIN || + val > CFG_ACTIVE_MIN_CHANNEL_TIME_BTC_MAX) + { + hddLog(LOGE, FL("Argument passsed for BTCSETDWELLTIME ESCO MIN is incorrect")); + ret = -EFAULT; + return ret; + } + pCfg->min_chntime_btc_esco = val; + smeConfig.csrConfig.min_chntime_btc_esco = val; + sme_UpdateConfig(hHal, &smeConfig); + } + else if (strncmp(command, "BTCSETDWELLTIME SCO MAX", 23) == 0) + { + if (hdd_drv_cmd_validate(command, 23)) { + hddLog(LOGE, FL("Invalid driver command")); + return -EINVAL; + } + + value = value + 24; + temp = kstrtou32(value, 10, &val); + if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_BTC_SCO_MIN || + val > CFG_ACTIVE_MAX_CHANNEL_TIME_BTC_SCO_MAX) + { + hddLog(LOGE, FL("Argument passed for BTCSETDWELLTIME SCO MAX is incorrect")); + ret = -EFAULT; + return ret; + } + pCfg->max_chntime_btc_sco = val; + smeConfig.csrConfig.max_chntime_btc_sco = val; + sme_UpdateConfig(hHal, &smeConfig); + } + else if (strncmp(command, "BTCSETDWELLTIME SCO MIN", 23) == 0) + { + if (hdd_drv_cmd_validate(command, 23)) { + hddLog(LOGE, FL("Invalid driver command")); + return -EINVAL; + } + + value = value + 24; + temp = kstrtou32(value, 10, &val); + if (temp != 0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_BTC_SCO_MIN || + val > CFG_ACTIVE_MIN_CHANNEL_TIME_BTC_SCO_MAX) + { + hddLog(LOGE, FL("Argument passed for BTCSETDWELLTIME SCO MIN is incorrect")); + ret = -EFAULT; + return ret; + } + pCfg->min_chntime_btc_sco = val; + smeConfig.csrConfig.min_chntime_btc_sco = val; + sme_UpdateConfig(hHal, &smeConfig); + } + else + { + ret = -EINVAL; + } + + return ret; +} + static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command) { tHalHandle hHal; @@ -5230,6 +5598,68 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, { ret = hdd_set_dwell_time(pAdapter, command); } + else if (strncmp(command, "BTCGETDWELLTIME", 15) == 0) + { + hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; + char extra[32]; + tANI_U8 len = 0; + + if (hdd_drv_cmd_validate(command, 15)) { + hddLog(LOGE, FL("Invalid driver command")); + return -EINVAL; + } + + memset(extra, 0, sizeof(extra)); + ret = hdd_btc_get_dwell_time(pCfg, command, extra, + sizeof(extra), &len); + len = VOS_MIN(priv_data.total_len, len + 1); + if (ret != 0 || copy_to_user(priv_data.buf, &extra, len)) { + hddLog(LOGE, FL("Failed to copy data to user buffer")); + ret = -EFAULT; + goto exit; + } + ret = len; + } + else if (strncmp(command, "BTCSETDWELLTIME", 15) == 0) + { + if (hdd_drv_cmd_validate(command, 15)) { + hddLog(LOGE, FL("Invalid driver command")); + return -EINVAL; + } + ret = hdd_btc_set_dwell_time(pAdapter, command); + } +#ifdef WLAN_AP_STA_CONCURRENCY + else if (strncmp(command, "CONCGETDWELLTIME", 16) == 0) + { + hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; + char extra[32]; + tANI_U8 len = 0; + + if (hdd_drv_cmd_validate(command, 16)) { + hddLog(LOGE, FL("Invalid driver command")); + return -EINVAL; + } + + memset(extra, 0, sizeof(extra)); + ret = hdd_conc_get_dwell_time(pCfg, command, extra, + sizeof(extra), &len); + len = VOS_MIN(priv_data.total_len, len + 1); + if (ret != 0 || copy_to_user(priv_data.buf, &extra, len)) { + hddLog(LOGE, FL("Failed to copy data to user buffer")); + ret = -EFAULT; + goto exit; + } + ret = len; + } + else if (strncmp(command, "CONCSETDWELLTIME", 16) == 0) + { + if (hdd_drv_cmd_validate(command, 16)) { + hddLog(LOGE, FL("Invalid driver command")); + return -EINVAL; + } + ret = hdd_conc_set_dwell_time(pAdapter, command); + } +#endif else if ( strncasecmp(command, "MIRACAST", 8) == 0 ) { tANI_U8 filterType = 0; From 4585df55bed9e801631dda22f094f1037f4e0b77 Mon Sep 17 00:00:00 2001 From: Kishor PK Date: Mon, 16 Apr 2018 15:07:35 +0530 Subject: [PATCH 385/508] ARM: dts: msm: Secure display ion heap support on msm8909 Add required ion heap and secure cma pool to support secure display usecase. Change-Id: I21bb6d71d4cd25e9b5239251acf73515d3861bde Signed-off-by: Kishor PK --- arch/arm/boot/dts/qcom/msm8909-1gb-cdp.dts | 3 +- arch/arm/boot/dts/qcom/msm8909-1gb-mtp.dts | 3 +- arch/arm/boot/dts/qcom/msm8909-1gb-rcm.dts | 3 +- arch/arm/boot/dts/qcom/msm8909-ion.dtsi | 4 +-- .../arm/boot/dts/qcom/msm8909-mtp_qseev4.dtsi | 29 +++++++++++++++++++ .../boot/dts/qcom/msm8909-pm8916-1gb-rcm.dts | 3 +- arch/arm/boot/dts/qcom/msm8909-pm8916-mtp.dts | 3 +- arch/arm/boot/dts/qcom/msm8909-qrd.dtsi | 3 +- .../arm/boot/dts/qcom/msm8909-qrd_qseev4.dtsi | 29 +++++++++++++++++++ arch/arm/boot/dts/qcom/msm8909.dtsi | 2 +- 10 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 arch/arm/boot/dts/qcom/msm8909-mtp_qseev4.dtsi create mode 100644 arch/arm/boot/dts/qcom/msm8909-qrd_qseev4.dtsi diff --git a/arch/arm/boot/dts/qcom/msm8909-1gb-cdp.dts b/arch/arm/boot/dts/qcom/msm8909-1gb-cdp.dts index bcc2b9049657a..9e522bc8387e2 100644 --- a/arch/arm/boot/dts/qcom/msm8909-1gb-cdp.dts +++ b/arch/arm/boot/dts/qcom/msm8909-1gb-cdp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016,2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -15,6 +15,7 @@ #include "msm8909-cdp.dtsi" #include "msm8909-pm8909.dtsi" #include "msm8909-pm8909-cdp.dtsi" +#include "msm8909-mtp_qseev4.dtsi" / { model = "Qualcomm Technologies, Inc. MSM8909-PM8909 1GB CDP"; diff --git a/arch/arm/boot/dts/qcom/msm8909-1gb-mtp.dts b/arch/arm/boot/dts/qcom/msm8909-1gb-mtp.dts index 3853148057d27..14606fa117136 100644 --- a/arch/arm/boot/dts/qcom/msm8909-1gb-mtp.dts +++ b/arch/arm/boot/dts/qcom/msm8909-1gb-mtp.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016,2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -15,6 +15,7 @@ #include "msm8909-mtp.dtsi" #include "msm8909-pm8909.dtsi" #include "msm8909-pm8909-mtp.dtsi" +#include "msm8909-mtp_qseev4.dtsi" / { model = "Qualcomm Technologies, Inc. MSM8909-PM8909 1GB MTP"; diff --git a/arch/arm/boot/dts/qcom/msm8909-1gb-rcm.dts b/arch/arm/boot/dts/qcom/msm8909-1gb-rcm.dts index a15d8c91287fd..7a46da8db1c6a 100644 --- a/arch/arm/boot/dts/qcom/msm8909-1gb-rcm.dts +++ b/arch/arm/boot/dts/qcom/msm8909-1gb-rcm.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016,2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -16,6 +16,7 @@ #include "msm8909-cdp.dtsi" #include "msm8909-pm8909.dtsi" #include "msm8909-pm8909-cdp.dtsi" +#include "msm8909-mtp_qseev4.dtsi" / { model = "Qualcomm Technologies, Inc. MSM8909-PM8909 1GB RCM"; diff --git a/arch/arm/boot/dts/qcom/msm8909-ion.dtsi b/arch/arm/boot/dts/qcom/msm8909-ion.dtsi index 4655b758f8e58..98561498c82ea 100644 --- a/arch/arm/boot/dts/qcom/msm8909-ion.dtsi +++ b/arch/arm/boot/dts/qcom/msm8909-ion.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014, 2016-2017, Linux Foundation. All rights reserved. +/* Copyright (c) 2014, 2016-2018, Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -11,7 +11,7 @@ */ &soc { - qcom,ion { + ion: qcom,ion { compatible = "qcom,msm-ion"; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/qcom/msm8909-mtp_qseev4.dtsi b/arch/arm/boot/dts/qcom/msm8909-mtp_qseev4.dtsi new file mode 100644 index 0000000000000..67dca943a51ff --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8909-mtp_qseev4.dtsi @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&reserved_mem { + secure_display_memory: secure_region { + compatible = "shared-dma-pool"; + label = "secure_display_mem"; + size = <0 0x1400000>; + reusable; + }; +}; + +&ion { + secure_display_heap: qcom,ion-heap@10 { /* SECURE DISPLAY HEAP */ + reg = <10>; + memory-region = <&secure_display_memory>; + qcom,ion-heap-type = "SECURE_DMA"; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8909-pm8916-1gb-rcm.dts b/arch/arm/boot/dts/qcom/msm8909-pm8916-1gb-rcm.dts index a80bd89c5c030..3c05965f9b902 100644 --- a/arch/arm/boot/dts/qcom/msm8909-pm8916-1gb-rcm.dts +++ b/arch/arm/boot/dts/qcom/msm8909-pm8916-1gb-rcm.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2015,2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -15,6 +15,7 @@ #include "msm8909-cdp.dtsi" #include "msm8909-pm8916-cdp.dtsi" +#include "msm8909-mtp_qseev4.dtsi" / { model = "Qualcomm Technologies, Inc. MSM8909-PM8916 1GB RCM"; diff --git a/arch/arm/boot/dts/qcom/msm8909-pm8916-mtp.dts b/arch/arm/boot/dts/qcom/msm8909-pm8916-mtp.dts index fb37873cc6619..5c5adb73a998d 100644 --- a/arch/arm/boot/dts/qcom/msm8909-pm8916-mtp.dts +++ b/arch/arm/boot/dts/qcom/msm8909-pm8916-mtp.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016,2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -16,6 +16,7 @@ #include "msm8909-mtp.dtsi" #include "msm8909-pm8916.dtsi" #include "msm8909-pm8916-mtp.dtsi" +#include "msm8909-mtp_qseev4.dtsi" / { model = "Qualcomm Technologies, Inc. MSM8909-PM8916 1GB MTP"; diff --git a/arch/arm/boot/dts/qcom/msm8909-qrd.dtsi b/arch/arm/boot/dts/qcom/msm8909-qrd.dtsi index f4b41b4f38ba4..56d22b2045d2f 100644 --- a/arch/arm/boot/dts/qcom/msm8909-qrd.dtsi +++ b/arch/arm/boot/dts/qcom/msm8909-qrd.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016,2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -13,6 +13,7 @@ #include "msm8909.dtsi" #include "msm8909-pm8909.dtsi" #include "msm8909-pinctrl.dtsi" +#include "msm8909-qrd_qseev4.dtsi" / { model = "Qualcomm Technologies, Inc. MSM8909 QRD"; diff --git a/arch/arm/boot/dts/qcom/msm8909-qrd_qseev4.dtsi b/arch/arm/boot/dts/qcom/msm8909-qrd_qseev4.dtsi new file mode 100644 index 0000000000000..8c58d4689b772 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8909-qrd_qseev4.dtsi @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&reserved_mem { + secure_display_memory: secure_region { + compatible = "shared-dma-pool"; + label = "secure_display_mem"; + size = <0 0x800000>; + reusable; + }; +}; + +&ion { + secure_display_heap: qcom,ion-heap@10 { /* SECURE DISPLAY HEAP */ + reg = <10>; + memory-region = <&secure_display_memory>; + qcom,ion-heap-type = "SECURE_DMA"; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8909.dtsi b/arch/arm/boot/dts/qcom/msm8909.dtsi index fd10716b1c6e6..b14f0cb89ed2c 100644 --- a/arch/arm/boot/dts/qcom/msm8909.dtsi +++ b/arch/arm/boot/dts/qcom/msm8909.dtsi @@ -132,7 +132,7 @@ }; }; - reserved-memory { + reserved_mem: reserved-memory { #address-cells = <2>; #size-cells = <2>; ranges; From b8be9ab6385db306c9ea01f810fd4d571b41eaa7 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Thu, 12 Apr 2018 20:03:05 +0530 Subject: [PATCH 386/508] wlan: Use request manager while processing monitor mode start/stop request We are transitioning to the new request manager framework. Implement this infrastructure while processing monitor mode start and stop requests. Change-Id: Ifad372b2f6a7f1c7d2e1e41b721f0c19460fcc86 CRs-Fixed: 2224245 --- CORE/HDD/inc/wlan_hdd_main.h | 6 +- CORE/HDD/src/wlan_hdd_main.c | 116 +++++++++++++---------- CORE/HDD/src/wlan_hdd_wext.c | 177 ++++++++++++++++++++--------------- CORE/MAC/inc/sirApi.h | 5 +- CORE/WDA/src/wlan_qct_wda.c | 4 +- 5 files changed, 176 insertions(+), 132 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index ef05de519b2ce..0cb344bf8a911 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -1997,9 +1997,9 @@ tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx); void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr); v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode ); void wlan_hdd_mon_set_typesubtype( hdd_mon_ctx_t *pMonCtx,int type); -void hdd_monPostMsgCb(tANI_U32 *magic, struct completion *cmpVar); -VOS_STATUS wlan_hdd_mon_postMsg(tANI_U32 *magic, struct completion *cmpVar, - hdd_mon_ctx_t *pMonCtx , void* callback); +void hdd_mon_post_msg_cb(void *context); +VOS_STATUS wlan_hdd_mon_postMsg(void *cookie, hdd_mon_ctx_t *pMonCtx, + void* callback); void hdd_set_conparam ( v_UINT_t newParam ); tVOS_CON_MODE hdd_get_conparam( void ); diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index d9ef048c01b29..98a2c90b6088e 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -9629,23 +9629,21 @@ VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type) return status; } -void hdd_monPostMsgCb(tANI_U32 *magic, struct completion *cmpVar) +void hdd_mon_post_msg_cb(void *context) { - if (magic == NULL || cmpVar == NULL) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - FL("invalid arguments %pK %pK"), magic, cmpVar); - return; - } - if (*magic != MON_MODE_MSG_MAGIC) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - FL("maic: %x"), *magic); - return; - } + struct hdd_request *request; - complete(cmpVar); - return; + request = hdd_request_get(context); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); + return; + } + + hdd_request_complete(request); + hdd_request_put(request); } + void hdd_init_mon_mode (hdd_adapter_t *pAdapter) { hdd_mon_ctx_t *pMonCtx = NULL; @@ -10106,12 +10104,16 @@ VOS_STATUS hdd_cleanup_ap_events(hdd_adapter_t *adapter) int wlan_hdd_stop_mon(hdd_context_t *hdd_ctx, bool wait) { - hdd_mon_ctx_t *mon_ctx; - long ret; - v_U32_t magic; - struct completion cmp_var; - void (*func_ptr)(tANI_U32 *magic, struct completion *cmpVar) = NULL; hdd_adapter_t *adapter; + hdd_mon_ctx_t *mon_ctx; + void (*func_ptr)(void *context) = NULL; + int ret = 0; + void *cookie = NULL; + struct hdd_request *request; + static const struct hdd_request_params params = { + .priv_size = 0, + .timeout_ms = MON_MODE_MSG_TIMEOUT, + }; adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_MONITOR); if (!adapter) { @@ -10128,28 +10130,37 @@ int wlan_hdd_stop_mon(hdd_context_t *hdd_ctx, bool wait) mon_ctx->state = MON_MODE_STOP; if (wait) { - func_ptr = hdd_monPostMsgCb; - magic = MON_MODE_MSG_MAGIC; - init_completion(&cmp_var); + func_ptr = hdd_mon_post_msg_cb; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Request allocation failure")); + return -ENOMEM; + } + cookie = hdd_request_cookie(request); } - if (VOS_STATUS_SUCCESS != wlan_hdd_mon_postMsg(&magic, &cmp_var, + /* + * If func_ptr is NULL, on receiving WDI_MON_START_RSP or + * WDI_MON_STOP_RSP hdd_mon_post_msg_cb() won't be invoked + * and so uninitialized cookie won't be accessed. + */ + if (VOS_STATUS_SUCCESS != wlan_hdd_mon_postMsg(cookie, mon_ctx, - hdd_monPostMsgCb)) { + func_ptr)) { hddLog(LOGE, FL("failed to stop MON MODE")); - mon_ctx->state = MON_MODE_START; - magic = 0; - return -EINVAL; + ret = -EINVAL; } if (!wait) goto bmps_roaming; - ret = wait_for_completion_timeout(&cmp_var, MON_MODE_MSG_TIMEOUT); - magic = 0; - if (ret <= 0 ) { + if (!ret) + ret = hdd_request_wait_for_response(request); + hdd_request_put(request); + if (ret) { hddLog(LOGE, - FL("timeout on stop monitor mode completion %ld"), ret); + FL("timeout on stop monitor mode completion %d"), ret); return -EINVAL; } @@ -11913,8 +11924,8 @@ void wlan_hdd_mon_set_typesubtype( hdd_mon_ctx_t *pMonCtx,int type) pMonCtx->typeSubtypeBitmap |= 0xFFFF00000000; } -VOS_STATUS wlan_hdd_mon_postMsg(tANI_U32 *magic, struct completion *cmpVar, - hdd_mon_ctx_t *pMonCtx , void* callback) +VOS_STATUS wlan_hdd_mon_postMsg(void *context, hdd_mon_ctx_t *pMonCtx, + void* callback) { vos_msg_t monMsg; tSirMonModeReq *pMonModeReq; @@ -11936,8 +11947,7 @@ VOS_STATUS wlan_hdd_mon_postMsg(tANI_U32 *magic, struct completion *cmpVar, return VOS_STATUS_E_FAILURE; } - pMonModeReq->magic = magic; - pMonModeReq->cmpVar = cmpVar; + pMonModeReq->context = context; pMonModeReq->data = pMonCtx; pMonModeReq->callback = callback; @@ -11957,10 +11967,14 @@ void wlan_hdd_mon_close(hdd_context_t *pHddCtx) { VOS_STATUS vosStatus; v_CONTEXT_t pVosContext = pHddCtx->pvosContext; - long ret; hdd_mon_ctx_t *pMonCtx = NULL; - v_U32_t magic; - struct completion cmpVar; + int ret; + void *cookie; + struct hdd_request *request; + static const struct hdd_request_params params = { + .priv_size = 0, + .timeout_ms = MON_MODE_MSG_TIMEOUT, + }; hdd_adapter_t *pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_MONITOR); if(pAdapter == NULL || pVosContext == NULL) @@ -11972,23 +11986,29 @@ void wlan_hdd_mon_close(hdd_context_t *pHddCtx) pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter); if (pMonCtx!= NULL && pMonCtx->state == MON_MODE_START) { pMonCtx->state = MON_MODE_STOP; - magic = MON_MODE_MSG_MAGIC; - init_completion(&cmpVar); + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + return; + } + cookie = hdd_request_cookie(request); + if (VOS_STATUS_SUCCESS != - wlan_hdd_mon_postMsg(&magic, &cmpVar, - pMonCtx, hdd_monPostMsgCb)) { + wlan_hdd_mon_postMsg(cookie, pMonCtx, + hdd_mon_post_msg_cb)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, FL("failed to post MON MODE REQ")); pMonCtx->state = MON_MODE_START; - magic = 0; - return; + goto req_put; } - ret = wait_for_completion_timeout(&cmpVar, MON_MODE_MSG_TIMEOUT); - magic = 0; - if (ret <= 0 ) { + + ret = hdd_request_wait_for_response(request); + if (ret) VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - FL("timeout on monitor mode completion %ld"), ret); - } + FL("timeout on monitor mode completion %d"), ret); + +req_put: + hdd_request_put(request); } hdd_UnregisterWext(pAdapter->dev); diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 7ed85bcd11eca..e94e9f5e6e356 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -5436,9 +5436,12 @@ static int __iw_mon_setint_getnone(struct net_device *dev, case WE_SET_MONITOR_STATE: { - v_U32_t magic = 0; - struct completion cmp_var; - long waitRet = 0; + void *cookie; + struct hdd_request *request; + static const struct hdd_request_params params = { + .priv_size = 0, + .timeout_ms = MON_MODE_MSG_TIMEOUT, + }; mon_ctx = WLAN_HDD_GET_MONITOR_CTX_PTR(adapter); if(!mon_ctx) { @@ -5459,30 +5462,33 @@ static int __iw_mon_setint_getnone(struct net_device *dev, break; mon_ctx->state = set_value; - magic = MON_MODE_MSG_MAGIC; - init_completion(&cmp_var); - if (wlan_hdd_mon_postMsg(&magic, &cmp_var, mon_ctx, - hdd_monPostMsgCb) != VOS_STATUS_SUCCESS) { + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + ret = -ENOMEM; + break; + } + cookie = hdd_request_cookie(request); + if (wlan_hdd_mon_postMsg(cookie, mon_ctx, + hdd_mon_post_msg_cb) + != VOS_STATUS_SUCCESS) { hddLog(LOGE, FL("failed to post MON MODE REQ")); mon_ctx->state = (mon_ctx->state==MON_MODE_START) ? MON_MODE_STOP : MON_MODE_START; - magic = 0; ret = -EIO; - break; - } - - waitRet = wait_for_completion_timeout(&cmp_var, - MON_MODE_MSG_TIMEOUT); - magic = 0; - if (waitRet <= 0 ){ - hddLog(LOGE, FL("failed to wait on monitor mode completion %ld"), - waitRet); - } else if (mon_ctx->state == MON_MODE_STOP) { - hddLog(LOG1, FL("Enable BMPS")); - hdd_enable_bmps_imps(hdd_ctx); - hdd_restore_roaming(hdd_ctx); + } else { + ret = hdd_request_wait_for_response(request); + if (ret){ + hddLog(LOGE, FL("failed to wait on monitor mode completion %d"), + ret); + } else if (mon_ctx->state == MON_MODE_STOP) { + hddLog(LOG1, FL("Enable BMPS")); + hdd_enable_bmps_imps(hdd_ctx); + hdd_restore_roaming(hdd_ctx); + } } + hdd_request_put(request); } break; @@ -6096,10 +6102,14 @@ static int __iw_setint_getnone(struct net_device *dev, } case WE_SET_MONITOR_STATE: { - v_U32_t magic = 0; - struct completion cmpVar; - long waitRet = 0; tVOS_CON_MODE mode = hdd_get_conparam(); + int ret; + void *cookie; + struct hdd_request *request; + static const struct hdd_request_params params = { + .priv_size = 0, + .timeout_ms = MON_MODE_MSG_TIMEOUT, + }; if( VOS_MONITOR_MODE != mode) { @@ -6123,26 +6133,31 @@ static int __iw_setint_getnone(struct net_device *dev, break; } pMonCtx->state = set_value; - magic = MON_MODE_MSG_MAGIC; - init_completion(&cmpVar); + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + ret = -ENOMEM; + break; + } + cookie = hdd_request_cookie(request); + if (VOS_STATUS_SUCCESS != - wlan_hdd_mon_postMsg(&magic, &cmpVar, - pMonCtx, hdd_monPostMsgCb)) { + wlan_hdd_mon_postMsg(cookie, pMonCtx, + hdd_mon_post_msg_cb)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, FL("failed to post MON MODE REQ")); pMonCtx->state = (pMonCtx->state==MON_MODE_START)? MON_MODE_STOP : MON_MODE_START; - magic = 0; ret = -EIO; - break; - } - waitRet = wait_for_completion_timeout(&cmpVar, MON_MODE_MSG_TIMEOUT); - magic = 0; - if (waitRet <= 0 ){ - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - FL("failed to wait on monitor mode completion %ld"), - waitRet); + } else { + ret = hdd_request_wait_for_response(request); + if (ret) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("failed to wait on monitor mode completion %d"), + ret); + } } + hdd_request_put(request); break; } case WE_SET_PKT_STATS_ENABLE_DISABLE: @@ -7900,10 +7915,14 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, #endif case WE_CONFIGURE_MONITOR_MODE: { - v_U32_t magic = 0; - struct completion cmpVar; - long waitRet = 0; tVOS_CON_MODE mode = hdd_get_conparam(); + int ret; + void *cookie; + struct hdd_request *request; + static const struct hdd_request_params params = { + .priv_size = 0, + .timeout_ms = MON_MODE_MSG_TIMEOUT, + }; if (VOS_MONITOR_MODE != mode) { hddLog(LOGE, FL("invalid mode %d"), mode); @@ -7937,34 +7956,41 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, pMonCtx->typeSubtypeBitmap = 0xFFFF00000000; } if (MON_MODE_START == pMonCtx->state) { - magic = MON_MODE_MSG_MAGIC; - init_completion(&cmpVar); + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + return -ENOMEM; + } + cookie = hdd_request_cookie(request); + if (VOS_STATUS_SUCCESS != - wlan_hdd_mon_postMsg(&magic, &cmpVar, - pMonCtx, hdd_monPostMsgCb)) { + wlan_hdd_mon_postMsg(cookie, pMonCtx, + hdd_mon_post_msg_cb)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, FL("failed to post MON MODE REQ")); - magic = 0; - return -EIO; - } - waitRet = wait_for_completion_timeout(&cmpVar, - MON_MODE_MSG_TIMEOUT); - magic = 0; - if (waitRet <= 0 ) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - FL("failed to wait on monitor mode completion %ld"), - waitRet); - } - } + ret = -EIO; + } else { + ret = hdd_request_wait_for_response(request); + if (ret) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("failed to wait on monitor mode completion %d"), + ret); + } + hdd_request_put(request); + } } break; case WE_SET_MONITOR_MODE_FILTER: { - v_U32_t magic = 0; - struct completion cmpVar; - long waitRet = 0; tVOS_CON_MODE mode = hdd_get_conparam(); + int ret; + void *cookie; + struct hdd_request *request; + static const struct hdd_request_params params = { + .priv_size = 0, + .timeout_ms = MON_MODE_MSG_TIMEOUT, + }; if (VOS_MONITOR_MODE != mode) { hddLog(LOGE, FL("invalid mode %d"), mode); @@ -7992,24 +8018,23 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, __func__, pMonCtx->mmFilters[0].macAddr.bytes, apps_args[6], apps_args[7], apps_args[8]); if (MON_MODE_START == pMonCtx->state) { - magic = MON_MODE_MSG_MAGIC; - init_completion(&cmpVar); - if (VOS_STATUS_SUCCESS != - wlan_hdd_mon_postMsg(&magic, &cmpVar, - pMonCtx, hdd_monPostMsgCb)) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - FL("failed to post MON MODE REQ")); - magic = 0; - return -EIO; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + return -ENOMEM; } - waitRet = wait_for_completion_timeout(&cmpVar, - MON_MODE_MSG_TIMEOUT); - magic = 0; - if (waitRet <= 0 ) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - FL("failed to wait on monitor mode completion %ld"), - waitRet); + cookie = hdd_request_cookie(request); + + if (VOS_STATUS_SUCCESS == + wlan_hdd_mon_postMsg(cookie, pMonCtx, + hdd_mon_post_msg_cb)) { + ret = hdd_request_wait_for_response(request); + if (ret) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("failed to wait on monitor mode completion %d"), + ret); } + hdd_request_put(request); } } break; @@ -8022,7 +8047,7 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, break; } EXIT(); - return 0; + return ret; } static int iw_hdd_set_var_ints_getnone(struct net_device *dev, diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h index 4b054bf79c6db..2e8a8ef0239d7 100644 --- a/CORE/MAC/inc/sirApi.h +++ b/CORE/MAC/inc/sirApi.h @@ -6106,12 +6106,11 @@ typedef struct tSirMacAddr bssid; }tSirDelAllTdlsPeers, *ptSirDelAllTdlsPeers; -typedef void (*tSirMonModeCb)(tANI_U32 *magic, struct completion *cmpVar); +typedef void (*tSirMonModeCb)(void *context); typedef struct { - tANI_U32 *magic; - struct completion *cmpVar; void *data; + void *context; tSirMonModeCb callback; }tSirMonModeReq, *ptSirMonModeReq; diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c index 0a9384bf5c365..a3dfa7bef91c6 100644 --- a/CORE/WDA/src/wlan_qct_wda.c +++ b/CORE/WDA/src/wlan_qct_wda.c @@ -22990,8 +22990,8 @@ void WDA_MonModeRspCallback(void *pEventData, void* pUserData) return ; } pData = (tSirMonModeReq *)pWdaParams->wdaMsgParam; - if (pData != NULL) { - pData->callback(pData->magic, pData->cmpVar); + if (pData != NULL && pData->callback != NULL) { + pData->callback(pData->context); vos_mem_free(pWdaParams->wdaMsgParam); } vos_mem_free(pWdaParams) ; From 543559a222ac13dfd6225ccb50de2bf3c7a42a41 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Wed, 2 May 2018 13:06:40 +0530 Subject: [PATCH 387/508] wlan: While processing get current antenna request wait for the WDA response While processing GET_ANTENA_DIVERSITY_SELECTION IOCTL, HDD is not waiting for WDA response after posting WDA request. This leads to return invalid data to upper layer. In HDD, wait for the WDA response after posting WDA request to get current antenna index from firmware. Change-Id: Ib8a679e811209399291189a4afef1f6e55e6a69a CRs-Fixed: 2234665 --- CORE/HDD/src/wlan_hdd_wext.c | 1 + 1 file changed, 1 insertion(+) diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index e94e9f5e6e356..4e70677adfe16 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -6536,6 +6536,7 @@ static VOS_STATUS wlan_hdd_get_current_antenna_index(hdd_adapter_t *pAdapter, else { /* request was sent -- wait for the response */ + ret = hdd_request_wait_for_response(request); if (ret) { hddLog(VOS_TRACE_LEVEL_ERROR, From 02614872045f46d3cece266d7f19cb895592ce6c Mon Sep 17 00:00:00 2001 From: Nirmal Abraham Date: Fri, 27 Apr 2018 12:42:20 +0530 Subject: [PATCH 388/508] msm: mdp3: Correct RGBX_8888 source format configuration For a layer with RGBX_8888 format, the DMA source format was not getting selected correctly due to which wrong bpp value was used while configuring DMA buffer address. This caused screen content to be stretched for RGBX_8888 single layer usecase. Add RGBX_8888 support in get_source_format function to address this. Add same support for MDP_XRGB_8888 and MDP_BRGA_8888 formats also. Change-Id: I1ad22908c1f4c5efddc0cbe5406b2215c0b83e47 Signed-off-by: Nirmal Abraham --- drivers/video/msm/mdss/mdp3_ctrl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c index c18d9b2ba642d..776ba2aa3f92f 100644 --- a/drivers/video/msm/mdss/mdp3_ctrl.c +++ b/drivers/video/msm/mdss/mdp3_ctrl.c @@ -651,8 +651,11 @@ int mdp3_ctrl_get_source_format(u32 imgType) case MDP_RGB_888: format = MDP3_DMA_IBUF_FORMAT_RGB888; break; + case MDP_XRGB_8888: case MDP_ARGB_8888: case MDP_RGBA_8888: + case MDP_BGRA_8888: + case MDP_RGBX_8888: format = MDP3_DMA_IBUF_FORMAT_XRGB8888; break; default: From f7354ef7211a0804a867daf7e66db427e0cb1f05 Mon Sep 17 00:00:00 2001 From: Suman Mukherjee Date: Mon, 7 May 2018 13:22:23 +0530 Subject: [PATCH 389/508] msm: Camera: Add buf entries only after successful mapping If user buf mapping is wrong, then also those entries use to get added in the queue head. That can cause failure in some corner cases. Add buffer in the queue only after mapping is successful. Change-Id: I1c104365b82bc4b9d34613aefff95a7e9f719432 Signed-off-by: Suman Mukherjee --- .../camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c index 4e03a7eac0222..994d9de0e6435 100644 --- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c +++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -74,9 +74,6 @@ static int32_t msm_buf_mngr_get_buf(struct msm_buf_mngr_device *dev, new_entry->session_id = buf_info->session_id; new_entry->stream_id = buf_info->stream_id; new_entry->index = new_entry->vb2_buf->v4l2_buf.index; - spin_lock_irqsave(&dev->buf_q_spinlock, flags); - list_add_tail(&new_entry->entry, &dev->buf_qhead); - spin_unlock_irqrestore(&dev->buf_q_spinlock, flags); buf_info->index = new_entry->vb2_buf->v4l2_buf.index; if (buf_info->type == MSM_CAMERA_BUF_MNGR_BUF_USER) { mutex_lock(&dev->cont_mutex); @@ -89,6 +86,16 @@ static int32_t msm_buf_mngr_get_buf(struct msm_buf_mngr_device *dev, } mutex_unlock(&dev->cont_mutex); } + if (!rc) { + spin_lock_irqsave(&dev->buf_q_spinlock, flags); + list_add_tail(&new_entry->entry, &dev->buf_qhead); + spin_unlock_irqrestore(&dev->buf_q_spinlock, flags); + } else { + pr_err("List not empty or msm_buf_mngr_hdl_cont_get_buf failed %pK\n", + new_entry->vb2_buf); + kfree(new_entry); + } + return rc; } From 51081e60477b8f5f74079e153ad71ecdea152201 Mon Sep 17 00:00:00 2001 From: Suprith Malligere Shankaregowda Date: Tue, 8 May 2018 14:25:31 +0530 Subject: [PATCH 390/508] msm:ais: Remove recursive locks We are trying to acquire the same mutex lock twice in iotcl path and axi/stats start stream. Removed recursive locks. Change-Id: I331f79e5a387aa64600656f6377ba46385d11a83 Signed-off-by: Suprith Malligere Shankaregowda --- drivers/media/platform/msm/ais/isp/msm_isp_util.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/media/platform/msm/ais/isp/msm_isp_util.c b/drivers/media/platform/msm/ais/isp/msm_isp_util.c index 2c670eea1852f..60f0983ad5191 100644 --- a/drivers/media/platform/msm/ais/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/ais/isp/msm_isp_util.c @@ -918,9 +918,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, break; case VIDIOC_MSM_ISP_CFG_STREAM: mutex_lock(&vfe_dev->core_mutex); - mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_cfg_axi_stream(vfe_dev, arg); - mutex_unlock(&vfe_dev->buf_mgr->lock); mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_CFG_HW_STATE: @@ -1021,9 +1019,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, break; case VIDIOC_MSM_ISP_CFG_STATS_STREAM: mutex_lock(&vfe_dev->core_mutex); - mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_cfg_stats_stream(vfe_dev, arg); - mutex_unlock(&vfe_dev->buf_mgr->lock); mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_UPDATE_STATS_STREAM: From d47fcab7dfd3ef5d35133b086ec8d9b6e0532010 Mon Sep 17 00:00:00 2001 From: Abinaya P Date: Fri, 4 May 2018 16:58:41 +0530 Subject: [PATCH 391/508] ARM: dts: msm: Add device tree support for MDM9650 PCIE EP for TTP Add device tree to support EP mode and MHI on MDM9650TTP. Change-Id: Ia6ed9e8fae9055ed87d815b40c1a8fc5fb8d0af5 Signed-off-by: Abinaya P --- arch/arm/boot/dts/qcom/Makefile | 1 + .../arm/boot/dts/qcom/mdm9650-pcie-ep-ttp.dts | 172 ++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 arch/arm/boot/dts/qcom/mdm9650-pcie-ep-ttp.dts diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index db2682ff39b3b..0ee9e79bf3e8c 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -149,6 +149,7 @@ dtb-$(CONFIG_ARCH_MDM9650) += mdm9650-sim.dtb \ mdm9650-emmc-mtp.dtb \ mdm9650-nand-mtp.dtb \ mdm9650-ttp.dtb \ + mdm9650-pcie-ep-ttp.dtb \ mdm9650-nand-dualwifi-mtp.dtb \ mdm9650-v1.1-emmc-cdp.dtb \ mdm9650-v1.1-nand-cdp.dtb \ diff --git a/arch/arm/boot/dts/qcom/mdm9650-pcie-ep-ttp.dts b/arch/arm/boot/dts/qcom/mdm9650-pcie-ep-ttp.dts new file mode 100644 index 0000000000000..2120ab8599890 --- /dev/null +++ b/arch/arm/boot/dts/qcom/mdm9650-pcie-ep-ttp.dts @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "mdm9650-v1.1-mtp.dtsi" +/ { + model = "Qualcomm Technologies, Inc. MDM 9650 PCIE EP TTP"; + compatible = "qcom,mdm9650-ttp", "qcom,mdm9650", "qcom,ttp"; + qcom,board-id = <0x1e 2>; +}; + +&pmd9650_l13 { + regulator-always-on; +}; + +&i2c_1 { + status = "ok"; + bmi160@68{ + compatible = "bosch-sensortec,bmi160"; + reg = <0x68>; + pinctrl-names = "default"; + pinctrl-0 = <&bmi160_int1_default &bmi160_int2_default>; + interrupt-parent = <&tlmm_pinmux>; + interrupts = <0x0 0x2002>; + bmi,init-interval = <200>; + bmi,place = <1>; + bmi,gpio_irq = <&tlmm_pinmux 0x0 0x2002>; + }; +}; + +&i2c_3 { + status = "ok"; + smb1351_otg_supply: smb1351-charger@55{ + status = "disabled"; + }; +}; + +&soc { + tlmm_pinmux: pinctrl@1000000 { + i2c_1 { + i2c_1_active { + config { + pins = "gpio2", "gpio3"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + }; + + usb_detect { + compatible = "qcom,gpio-usbdetect"; + interrupt-parent = <&spmi_bus>; + interrupts = <0x0 0x0d 0x0>; /* PMD9655 VBUS DETECT */ + interrupt-names = "vbus_det_irq"; + }; +}; + +&usb3 { + cpe-gpio = <&tlmm_pinmux 87 0>; +}; + +&spi_2 { + status = "ok"; + + can-controller@0 { + compatible = "fsl,k61"; + spi-max-frequency = <4800000>; + reg = <0>; + interrupt-parent = <&tlmm_pinmux>; + interrupts = <84 0>; + reset-gpio = <&tlmm_pinmux 68 0x1>; + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&can_rst_on>; + pinctrl-1 = <&can_rst_off>; + }; +}; + +&blsp1_uart4b_hs { + status = "ok"; +}; + +&blsp1_uart2_hs { + status = "disabled"; +}; + +&snd_tasha { + pinctrl-names = + "all_off", + "pri_mi2s_aux_master_active", + "pri_mi2s_aux_slave_active", + "invalid_state_1", + "sec_mi2s_aux_master_active", + "pri_master_active_sec_master_active", + "pri_slave_active_sec_master_active", + "invalid_state_2", + "sec_mi2s_aux_slave_active", + "pri_master_active_sec_slave_active", + "pri_slave_active_sec_slave_active"; + pinctrl-0 = <&pri_ws_sleep &pri_sck_sleep + &pri_dout_sleep &pri_din_sleep + &sec_ws_b_sleep &sec_sck_b_sleep + &sec_dout_b_sleep &sec_din_b_sleep>; + pinctrl-1 = <&pri_ws_active_master &pri_sck_active_master + &pri_dout_active &pri_din_active + &sec_ws_b_sleep &sec_sck_b_sleep + &sec_dout_b_sleep &sec_din_b_sleep>; + pinctrl-2 = <&pri_ws_active_slave &pri_sck_active_slave + &pri_dout_active &pri_din_active + &sec_ws_b_sleep &sec_sck_b_sleep + &sec_dout_b_sleep &sec_din_b_sleep>; + pinctrl-3 = <&pri_ws_sleep &pri_sck_sleep + &pri_dout_sleep &pri_din_sleep + &sec_ws_b_sleep &sec_sck_b_sleep + &sec_dout_b_sleep &sec_din_b_sleep>; + pinctrl-4 = <&pri_ws_sleep &pri_sck_sleep + &pri_dout_sleep &pri_din_sleep + &sec_ws_b_active_master &sec_sck_b_active_master + &sec_dout_b_active &sec_din_b_active>; + pinctrl-5 = <&pri_ws_active_master &pri_sck_active_master + &pri_dout_active &pri_din_active + &sec_ws_b_active_master &sec_sck_b_active_master + &sec_dout_b_active &sec_din_b_active>; + pinctrl-6 = <&pri_ws_active_slave &pri_sck_active_slave + &pri_dout_active &pri_din_active + &sec_ws_b_active_master &sec_sck_b_active_master + &sec_dout_b_active &sec_din_b_active>; + pinctrl-7 = <&pri_ws_sleep &pri_sck_sleep + &pri_dout_sleep &pri_din_sleep + &sec_ws_b_sleep &sec_sck_b_sleep + &sec_dout_b_sleep &sec_din_b_sleep>; + pinctrl-8 = <&pri_ws_sleep &pri_sck_sleep + &pri_dout_sleep &pri_din_sleep + &sec_ws_b_active_slave &sec_sck_b_active_slave + &sec_dout_b_active &sec_din_b_active>; + pinctrl-9 = <&pri_ws_active_master &pri_sck_active_master + &pri_dout_active &pri_din_active + &sec_ws_b_active_slave &sec_sck_b_active_slave + &sec_dout_b_active &sec_din_b_active>; + pinctrl-10 = <&pri_ws_active_slave &pri_sck_active_slave + &pri_dout_active &pri_din_active + &sec_ws_b_active_slave &sec_sck_b_active_slave + &sec_dout_b_active &sec_din_b_active>; +}; + +&pcie_ep { + status = "ok"; +}; + +&pcie0 { + status = "disabled"; +}; + +&cnss_pcie { + status = "disabled"; +}; + +&mhi_device { + status = "ok"; +}; + From d0d3c17278d17b5d5fa1c173bd0804ec5df33fd3 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Wed, 2 May 2018 18:53:05 +0530 Subject: [PATCH 392/508] wlan: Revert "wlan: Use request manager for GETFWSTATS and GETBCNMISSRATE" This reverts change-Id: I5a1768be6814c1dae4bdb7deab5bc67315af32da Change-Id: Idd8ed904c8794071330fb931c4449d049d646cae CRs-Fixed: 2234042 --- CORE/HDD/src/wlan_hdd_main.c | 234 ++++++++++++++++++----------------- 1 file changed, 122 insertions(+), 112 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 98a2c90b6088e..74c93992d6b61 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -2707,54 +2707,106 @@ hdd_parse_reassoc(hdd_adapter_t *pAdapter, const char *command, int total_len) } #endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE FEATURE_WLAN_LFR */ -static void get_bcn_miss_rate_cb(VOS_STATUS status, int bcnMissRate, void *data) +static void getBcnMissRateCB(VOS_STATUS status, int bcnMissRate, void *data) { - struct hdd_request *request; + bcnMissRateContext_t *pCBCtx; - request = hdd_request_get(data); - if (!request) { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); - return; - } + if (NULL == data) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL")); + return; + } - if (VOS_STATUS_SUCCESS == status) - gbcnMissRate = bcnMissRate; - else - hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate")); + /* there is a race condition that exists between this callback + function and the caller since the caller could time out either + before or while this code is executing. we use a spinlock to + serialize these actions */ + spin_lock(&hdd_context_lock); - hdd_request_complete(request); - hdd_request_put(request); + pCBCtx = (bcnMissRateContext_t *)data; + gbcnMissRate = -1; - return; -} + if (pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("invalid context magic: %08x"), pCBCtx->magic); + spin_unlock(&hdd_context_lock); + return ; + } -struct fw_stats_priv { - tSirFwStatsResult *fw_stats; -}; + if (VOS_STATUS_SUCCESS == status) + { + gbcnMissRate = bcnMissRate; + } + else + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate")); + } -void hdd_fw_statis_cb(VOS_STATUS status, - tSirFwStatsResult *fwStatsResult, void *context) -{ - struct hdd_request *request; - struct fw_stats_priv *priv; + complete(&(pCBCtx->completion)); + spin_unlock(&hdd_context_lock); - hddLog(VOS_TRACE_LEVEL_INFO, FL("with status = %d"),status); + return; +} - request = hdd_request_get(context); - if (!request) { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); - return; - } - priv = hdd_request_priv(request); +void hdd_FWStatisCB( VOS_STATUS status, + tSirFwStatsResult *fwStatsResult, void *pContext ) +{ + fwStatsContext_t *fwStatsCtx; + hdd_adapter_t *pAdapter; - if (VOS_STATUS_SUCCESS != status) - *priv->fw_stats = *fwStatsResult; - else - priv->fw_stats = NULL; + hddLog(VOS_TRACE_LEVEL_INFO, FL(" with status = %d"),status); - hdd_request_complete(request); - hdd_request_put(request); - return; + if (NULL == pContext) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL")); + return; + } + /* there is a race condition that exists between this callback + function and the caller since the caller could time out either + before or while this code is executing. we use a spinlock to + serialize these actions */ + spin_lock(&hdd_context_lock); + fwStatsCtx = (fwStatsContext_t *) pContext; + if (fwStatsCtx->magic != FW_STATS_CONTEXT_MAGIC) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("invalid context magic: %08x"), fwStatsCtx->magic); + spin_unlock(&hdd_context_lock); + return; + } + pAdapter = fwStatsCtx->pAdapter; + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("pAdapter returned is NULL or invalid")); + spin_unlock(&hdd_context_lock); + return; + } + pAdapter->fwStatsRsp.type = 0; + if ((VOS_STATUS_SUCCESS == status) && (NULL != fwStatsResult)) + { + switch( fwStatsResult->type ) + { + case FW_UBSP_STATS: + { + memcpy(&pAdapter->fwStatsRsp,fwStatsResult,sizeof(tSirFwStatsResult)); + hddLog(VOS_TRACE_LEVEL_INFO, + FL("ubsp_enter_cnt = %d ubsp_jump_ddr_cnt = %d"), + pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_enter_cnt, + pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_jump_ddr_cnt); + } + break; + default: + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL(" No handling for stats type %d"),fwStatsResult->type); + } + } + } + complete(&(fwStatsCtx->completion)); + spin_unlock(&hdd_context_lock); + return; } /* @@ -6698,12 +6750,8 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, { eHalStatus status; char buf[32], len; - void *cookie; - struct hdd_request *request; - static const struct hdd_request_params params = { - .priv_size = 0, - .timeout_ms = WLAN_WAIT_TIME_STATS, - }; + long waitRet; + bcnMissRateContext_t getBcnMissRateCtx; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); @@ -6714,34 +6762,35 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, ret = -1; goto exit; } - request = hdd_request_alloc(¶ms); - if (!request) { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); - ret = -ENOMEM; - goto exit; - } - cookie = hdd_request_cookie(request); + + init_completion(&(getBcnMissRateCtx.completion)); + getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC; status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, - (void *)get_bcn_miss_rate_cb, - cookie); + (void *)getBcnMissRateCB, + (void *)(&getBcnMissRateCtx)); if( eHAL_STATUS_SUCCESS != status) { hddLog(VOS_TRACE_LEVEL_INFO, FL("GETBCNMISSRATE: fail to post WDA cmd")); ret = -EINVAL; - goto free_bcn_miss_rate_req; + goto exit; } - ret = hdd_request_wait_for_response(request); - if(ret) + waitRet = wait_for_completion_interruptible_timeout + (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME); + if(waitRet <= 0) { hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to wait on bcnMissRateComp %d"), ret); + //Make magic number to zero so that callback is not called. + spin_lock(&hdd_context_lock); + getBcnMissRateCtx.magic = 0x0; + spin_unlock(&hdd_context_lock); ret = -EINVAL; - goto free_bcn_miss_rate_req; + goto exit; } hddLog(VOS_TRACE_LEVEL_INFO, @@ -6753,12 +6802,9 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to copy data to user buffer", __func__); ret = -EFAULT; - goto free_bcn_miss_rate_req; + goto exit; } ret = len; - -free_bcn_miss_rate_req: - hdd_request_put(request); } #ifdef FEATURE_WLAN_TDLS else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) { @@ -6848,17 +6894,11 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, eHalStatus status; char *buf = NULL; char len; - tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp), - *fw_stats_result; + long waitRet; + fwStatsContext_t fwStatsCtx; + tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp); tANI_U8 *ptr = command; int stats; - void *cookie; - struct hdd_request *request; - struct fw_stats_priv *priv; - static const struct hdd_request_params params = { - .priv_size = sizeof(*priv), - .timeout_ms = WLAN_WAIT_TIME_STATS, - }; ret = hdd_drv_cmd_validate(command, 10); if (ret) @@ -6882,63 +6922,32 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, goto exit; } - request = hdd_request_alloc(¶ms); - if (!request) { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); - ret = -ENOMEM; - goto exit; - } - + init_completion(&(fwStatsCtx.completion)); + fwStatsCtx.magic = FW_STATS_CONTEXT_MAGIC; + fwStatsCtx.pAdapter = pAdapter; + fwStatsRsp->type = 0; status = sme_GetFwStats( (tHalHandle)pHddCtx->hHal, stats, - cookie, hdd_fw_statis_cb); + &fwStatsCtx, hdd_FWStatisCB); if (eHAL_STATUS_SUCCESS != status) { hddLog(VOS_TRACE_LEVEL_ERROR, FL(" fail to post WDA cmd status = %d"), status); ret = -EINVAL; - hdd_request_put(request); goto exit; } - ret = hdd_request_wait_for_response(request); - if (ret) + waitRet = wait_for_completion_timeout + (&(fwStatsCtx.completion), FW_STATE_WAIT_TIME); + if (waitRet <= 0) { hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to wait on GwtFwstats")); + //Make magic number to zero so that callback is not executed. + spin_lock(&hdd_context_lock); + fwStatsCtx.magic = 0x0; + spin_unlock(&hdd_context_lock); ret = -EINVAL; - hdd_request_put(request); goto exit; } - - priv = hdd_request_priv(request); - fw_stats_result = priv->fw_stats; - fwStatsRsp->type = 0; - if (NULL != fw_stats_result) - { - switch (fw_stats_result->type ) - { - case FW_UBSP_STATS: - { - tSirUbspFwStats *stats = - &fwStatsRsp->fwStatsData.ubspStats; - memcpy(fwStatsRsp, fw_stats_result, - sizeof(tSirFwStatsResult)); - hddLog(VOS_TRACE_LEVEL_INFO, - FL("ubsp_enter_cnt = %d ubsp_jump_ddr_cnt = %d"), - stats->ubsp_enter_cnt, - stats->ubsp_jump_ddr_cnt); - } - break; - - default: - { - hddLog(VOS_TRACE_LEVEL_ERROR, - FL("No handling for stats type %d"), - fw_stats_result->type); - } - } - } - hdd_request_put(request); - if (fwStatsRsp->type) { buf = kmalloc(FW_STATE_RSP_LEN, GFP_KERNEL); @@ -6985,6 +6994,7 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, ret = -EFAULT; goto exit; } + } else if (strncasecmp(command, "SET_FCC_CHANNEL", 15) == 0) { From 2d9cdc3b435f97daaa6e73f862eb6af151bf0f6f Mon Sep 17 00:00:00 2001 From: codeworkx Date: Sat, 7 Jan 2017 19:19:24 +0100 Subject: [PATCH 393/508] prima: overwrite mac address if config file exists Modified from qcacld-2.0 https://source.codeaurora.org/quic/la/platform/vendor/qcom-opensource/wlan/qcacld-2.0/tree/CORE/HDD/src/wlan_hdd_main.c?h=LA.BR.1.3.6.c1-00810-8976.0 Change-Id: Ie1b7fb4e8a37595786c15a444d4e588cf0fdb58a --- .../staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h | 1 + .../staging/prima/CORE/HDD/src/wlan_hdd_cfg.c | 127 ++++++++++++++++++ .../prima/CORE/HDD/src/wlan_hdd_main.c | 16 +++ .../prima/CORE/VOSS/inc/wlan_hdd_misc.h | 2 + 4 files changed, 146 insertions(+) diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h index 049df4e84d4b1..eec0d66427fec 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h @@ -3794,6 +3794,7 @@ typedef struct Function declarations and documenation -------------------------------------------------------------------------*/ VOS_STATUS hdd_parse_config_ini(hdd_context_t *pHddCtx); +VOS_STATUS hdd_update_mac_config(hdd_context_t *pHddCtx); VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ); v_BOOL_t hdd_update_config_dat ( hdd_context_t *pHddCtx ); VOS_STATUS hdd_cfg_get_config(hdd_context_t *pHddCtx, char *pBuf, int buflen); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c index 0292ba099e5b5..3967d7ec25724 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c @@ -4066,6 +4066,133 @@ typedef struct char *value; }tCfgIniEntry; + +/* convert string to 6 bytes mac address + * 00AA00BB00CC -> 0x00 0xAA 0x00 0xBB 0x00 0xCC + */ +static void update_mac_from_string(hdd_context_t *pHddCtx, tCfgIniEntry *macTable, int num) +{ + int i = 0, j = 0, res = 0; + char *candidate = NULL; + v_MACADDR_t macaddr[VOS_MAX_CONCURRENCY_PERSONA]; + + memset(macaddr, 0, sizeof(macaddr)); + + for (i = 0; i < num; i++) + { + candidate = macTable[i].value; + for (j = 0; j < VOS_MAC_ADDR_SIZE; j++) { + res = hex2bin(&macaddr[i].bytes[j], &candidate[(j<<1)], 1); + if (res < 0) + break; + } + if (res == 0 && !vos_is_macaddr_zero(&macaddr[i])) { + vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], + (v_U8_t *)&macaddr[i].bytes[0], VOS_MAC_ADDR_SIZE); + } + } +} + +/* + * This function tries to update mac address from cfg file. + * It overwrites the MAC address if config file exist. + */ +VOS_STATUS hdd_update_mac_config(hdd_context_t *pHddCtx) +{ + int status, i = 0, j = 0; + char * buf; + const struct firmware *fw = NULL; + const char prefix[] = "Intf"; + const char suffix[] = "MacAddress"; + tCfgIniEntry macTable[VOS_MAX_CONCURRENCY_PERSONA]; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + // make sure all pointers in macTable are NULL, so an early jump to config_exit will not crash + memset(macTable, 0, sizeof(macTable)); + + status = request_firmware(&fw, WLAN_MAC_FILE, pHddCtx->parent_dev); + + if (status) + { + hddLog(VOS_TRACE_LEVEL_WARN, "%s: request_firmware failed %d", + __func__, status); + return VOS_STATUS_E_FAILURE; + } + if (fw == NULL || fw->data == NULL || fw->size < (VOS_MAX_CONCURRENCY_PERSONA * NV_FIELD_MAC_ADDR_SIZE)) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: invalid firmware", __func__); + release_firmware(fw); + return VOS_STATUS_E_INVAL; + } + + /* data format: + * 00AA00BB00CA00AA00BB00CB00AA00BB00CC00AA00BB00CD + */ + + for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++) + { + int lenPersona = snprintf(NULL, 0, "%d", i); + + char *persona = (char*)vos_mem_vmalloc(lenPersona + 1); + if (NULL == persona) { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: kmalloc failure", __func__); + vos_status = VOS_STATUS_E_FAILURE; + goto config_exit; + } + + macTable[i].name = (char*)vos_mem_vmalloc((sizeof(prefix) - 1) + lenPersona + (sizeof(suffix) - 1) + 1); + if (NULL == macTable[i].name) { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: kmalloc failure", __func__); + vos_status = VOS_STATUS_E_FAILURE; + vos_mem_vfree(persona); + goto config_exit; + } + + macTable[i].value = (char*)vos_mem_vmalloc(NV_FIELD_MAC_ADDR_SIZE * 2 + 1); + if (NULL == macTable[i].value) { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: kmalloc failure", __func__); + vos_status = VOS_STATUS_E_FAILURE; + vos_mem_vfree(persona); + goto config_exit; + } + + sprintf(persona, "%d", i); + + strcpy(macTable[i].name, prefix); + strcat(macTable[i].name, persona); + strcat(macTable[i].name, suffix); + + buf = macTable[i].value; + for (j = 0; j < NV_FIELD_MAC_ADDR_SIZE; j++) + { + buf += sprintf(buf, "%02X", fw->data[NV_FIELD_MAC_ADDR_SIZE * i + j]); + } + + vos_mem_vfree(persona); + } + + if (i <= VOS_MAX_CONCURRENCY_PERSONA) { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: %d MAC addresses provided", __func__, i); + } + else { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: invalid number of MAC address provided, nMac = %d", + __func__, i); + vos_status = VOS_STATUS_E_INVAL; + goto config_exit; + } + + update_mac_from_string(pHddCtx, &macTable[0], i); + +config_exit: + for(i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++) + { + vos_mem_vfree(macTable[i].name); + vos_mem_vfree(macTable[i].value); + } + release_firmware(fw); + return vos_status; +} + static VOS_STATUS hdd_apply_cfg_ini( hdd_context_t * pHddCtx, tCfgIniEntry* iniTable, unsigned long entries); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c index 46da26c57bff7..7192e0ce25f87 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c @@ -12887,6 +12887,22 @@ int hdd_wlan_startup(struct device *dev ) { eHalStatus halStatus; + /* Overwrite the Mac address if config file exist */ + if (VOS_STATUS_SUCCESS != hdd_update_mac_config(pHddCtx)) + { + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Didn't overwrite MAC from config file", + __func__); + } else { + pr_info("%s: WLAN Mac Addr from config: %02X:%02X:%02X:%02X:%02X:%02X\n", WLAN_MODULE_NAME, + pHddCtx->cfg_ini->intfMacAddr[0].bytes[0], + pHddCtx->cfg_ini->intfMacAddr[0].bytes[1], + pHddCtx->cfg_ini->intfMacAddr[0].bytes[2], + pHddCtx->cfg_ini->intfMacAddr[0].bytes[3], + pHddCtx->cfg_ini->intfMacAddr[0].bytes[4], + pHddCtx->cfg_ini->intfMacAddr[0].bytes[5]); + } + /* Set the MAC Address Currently this is used by HAL to * add self sta. Remove this once self sta is added as * part of session open. diff --git a/drivers/staging/prima/CORE/VOSS/inc/wlan_hdd_misc.h b/drivers/staging/prima/CORE/VOSS/inc/wlan_hdd_misc.h index 7c2d62ad86c36..fc8be7a81faa4 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/wlan_hdd_misc.h +++ b/drivers/staging/prima/CORE/VOSS/inc/wlan_hdd_misc.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2017 The LineageOS Project. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -56,6 +57,7 @@ #define WLAN_HO_CFG_FILE "wlan/wlan_ho_config" #endif // MSM_PLATFORM +#define WLAN_MAC_FILE "wlan/prima/wlan_mac.bin" VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize); From 7aa4bea00fc93d701e0ec0b9eabf195acea729ec Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Mon, 9 Apr 2018 17:19:03 +0530 Subject: [PATCH 394/508] wlan: Use request manager while processing driver commands We are transitioning to the new request manager framework. Change hdd_driver_command() to this framework. Change-Id: Ia486bb4f8a8dd638665b0501d124f5c25f9db99b CRs-Fixed: 2228608 --- CORE/HDD/src/wlan_hdd_main.c | 281 +++++++++++++++++++---------------- 1 file changed, 156 insertions(+), 125 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 74c93992d6b61..41f91f02ae545 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -151,7 +151,6 @@ static struct kparam_string fwpath = { static char *country_code; static int enable_11d = -1; static int enable_dfs_chan_scan = -1; -static int gbcnMissRate = -1; #ifndef MODULE static int wlan_hdd_inited; @@ -2707,106 +2706,86 @@ hdd_parse_reassoc(hdd_adapter_t *pAdapter, const char *command, int total_len) } #endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE FEATURE_WLAN_LFR */ -static void getBcnMissRateCB(VOS_STATUS status, int bcnMissRate, void *data) -{ - bcnMissRateContext_t *pCBCtx; - - if (NULL == data) - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL")); - return; - } +struct bcn_miss_rate_priv { + int bcn_miss_rate; +}; - /* there is a race condition that exists between this callback - function and the caller since the caller could time out either - before or while this code is executing. we use a spinlock to - serialize these actions */ - spin_lock(&hdd_context_lock); +/** + * get_bcn_miss_rate_cb() callback invoked on receiving beacon miss + * rate from firmware + * @status: Status of get beacon miss rate operation + * @bcnMissRate: Beacon miss rate + * @context: Context passed while registering callback + * + * This function is invoked by WDA layer on receiving + * WDI_GET_BCN_MISS_RATE_RSP + * + * Return: None + */ +static void get_bcn_miss_rate_cb(VOS_STATUS status, int bcnMissRate, + void *context) +{ + struct hdd_request *request; + struct bcn_miss_rate_priv *priv; - pCBCtx = (bcnMissRateContext_t *)data; - gbcnMissRate = -1; + request = hdd_request_get(context); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); + return; + } - if (pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - FL("invalid context magic: %08x"), pCBCtx->magic); - spin_unlock(&hdd_context_lock); - return ; - } + priv = hdd_request_priv(request); - if (VOS_STATUS_SUCCESS == status) - { - gbcnMissRate = bcnMissRate; - } - else - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate")); - } + if (VOS_STATUS_SUCCESS == status) + priv->bcn_miss_rate = bcnMissRate; + else + hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate")); - complete(&(pCBCtx->completion)); - spin_unlock(&hdd_context_lock); + hdd_request_complete(request); + hdd_request_put(request); - return; + return; } -void hdd_FWStatisCB( VOS_STATUS status, - tSirFwStatsResult *fwStatsResult, void *pContext ) +struct fw_stats_priv { + tSirFwStatsResult *fw_stats; +}; + +/** + * hdd_fw_stats_cb() callback invoked on receiving firmware stats + * from firmware + * @status: Status of get firmware stats operation + * @fwStatsResult: firmware stats + * @context: Context passed while registering callback + * + * This function is invoked by WDA layer on receiving + * WDI_GET_FW_STATS_RSP + * + * Return: None + */ +static void hdd_fw_stats_cb(VOS_STATUS status, + tSirFwStatsResult *fwStatsResult, void *context) { - fwStatsContext_t *fwStatsCtx; - hdd_adapter_t *pAdapter; + struct hdd_request *request; + struct fw_stats_priv *priv; - hddLog(VOS_TRACE_LEVEL_INFO, FL(" with status = %d"),status); + hddLog(VOS_TRACE_LEVEL_INFO, FL("with status = %d"),status); - if (NULL == pContext) - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL")); - return; - } - /* there is a race condition that exists between this callback - function and the caller since the caller could time out either - before or while this code is executing. we use a spinlock to - serialize these actions */ - spin_lock(&hdd_context_lock); - fwStatsCtx = (fwStatsContext_t *) pContext; - if (fwStatsCtx->magic != FW_STATS_CONTEXT_MAGIC) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - FL("invalid context magic: %08x"), fwStatsCtx->magic); - spin_unlock(&hdd_context_lock); - return; - } - pAdapter = fwStatsCtx->pAdapter; - if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, - FL("pAdapter returned is NULL or invalid")); - spin_unlock(&hdd_context_lock); - return; - } - pAdapter->fwStatsRsp.type = 0; - if ((VOS_STATUS_SUCCESS == status) && (NULL != fwStatsResult)) - { - switch( fwStatsResult->type ) - { - case FW_UBSP_STATS: - { - memcpy(&pAdapter->fwStatsRsp,fwStatsResult,sizeof(tSirFwStatsResult)); - hddLog(VOS_TRACE_LEVEL_INFO, - FL("ubsp_enter_cnt = %d ubsp_jump_ddr_cnt = %d"), - pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_enter_cnt, - pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_jump_ddr_cnt); - } - break; - default: - { - hddLog(VOS_TRACE_LEVEL_ERROR, - FL(" No handling for stats type %d"),fwStatsResult->type); - } - } - } - complete(&(fwStatsCtx->completion)); - spin_unlock(&hdd_context_lock); - return; + request = hdd_request_get(context); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request")); + return; + } + priv = hdd_request_priv(request); + + if (VOS_STATUS_SUCCESS == status) + *priv->fw_stats = *fwStatsResult; + else + priv->fw_stats = NULL; + + hdd_request_complete(request); + hdd_request_put(request); + return; } /* @@ -6750,8 +6729,13 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, { eHalStatus status; char buf[32], len; - long waitRet; - bcnMissRateContext_t getBcnMissRateCtx; + void *cookie; + struct hdd_request *request; + struct bcn_miss_rate_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); @@ -6762,49 +6746,59 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, ret = -1; goto exit; } - - init_completion(&(getBcnMissRateCtx.completion)); - getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + ret = -ENOMEM; + goto exit; + } + cookie = hdd_request_cookie(request); + priv = hdd_request_priv(request); + priv->bcn_miss_rate = -1; status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, - (void *)getBcnMissRateCB, - (void *)(&getBcnMissRateCtx)); + (void *)get_bcn_miss_rate_cb, + cookie); if( eHAL_STATUS_SUCCESS != status) { hddLog(VOS_TRACE_LEVEL_INFO, FL("GETBCNMISSRATE: fail to post WDA cmd")); ret = -EINVAL; - goto exit; + goto free_bcn_miss_rate_req; } - waitRet = wait_for_completion_interruptible_timeout - (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME); - if(waitRet <= 0) + ret = hdd_request_wait_for_response(request); + if(ret) { hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to wait on bcnMissRateComp %d"), ret); - //Make magic number to zero so that callback is not called. - spin_lock(&hdd_context_lock); - getBcnMissRateCtx.magic = 0x0; - spin_unlock(&hdd_context_lock); ret = -EINVAL; - goto exit; + goto free_bcn_miss_rate_req; } hddLog(VOS_TRACE_LEVEL_INFO, - FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate); + FL("GETBCNMISSRATE: bcnMissRate: %d"), priv->bcn_miss_rate); + + if (priv->bcn_miss_rate == -1) { + ret = -EFAULT; + goto free_bcn_miss_rate_req; + } - len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate); + len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", + priv->bcn_miss_rate); if (copy_to_user(priv_data.buf, &buf, len + 1)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to copy data to user buffer", __func__); ret = -EFAULT; - goto exit; + goto free_bcn_miss_rate_req; } ret = len; + +free_bcn_miss_rate_req: + hdd_request_put(request); } #ifdef FEATURE_WLAN_TDLS else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) { @@ -6894,11 +6888,17 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, eHalStatus status; char *buf = NULL; char len; - long waitRet; - fwStatsContext_t fwStatsCtx; - tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp); + tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp), + *fw_stats_result; tANI_U8 *ptr = command; int stats; + void *cookie; + struct hdd_request *request; + struct fw_stats_priv *priv; + static const struct hdd_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = WLAN_WAIT_TIME_STATS, + }; ret = hdd_drv_cmd_validate(command, 10); if (ret) @@ -6922,32 +6922,64 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, goto exit; } - init_completion(&(fwStatsCtx.completion)); - fwStatsCtx.magic = FW_STATS_CONTEXT_MAGIC; - fwStatsCtx.pAdapter = pAdapter; - fwStatsRsp->type = 0; + request = hdd_request_alloc(¶ms); + if (!request) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure")); + ret = -ENOMEM; + goto exit; + } + cookie = hdd_request_cookie(request); + status = sme_GetFwStats( (tHalHandle)pHddCtx->hHal, stats, - &fwStatsCtx, hdd_FWStatisCB); + cookie, hdd_fw_stats_cb); if (eHAL_STATUS_SUCCESS != status) { hddLog(VOS_TRACE_LEVEL_ERROR, FL(" fail to post WDA cmd status = %d"), status); ret = -EINVAL; + hdd_request_put(request); goto exit; } - waitRet = wait_for_completion_timeout - (&(fwStatsCtx.completion), FW_STATE_WAIT_TIME); - if (waitRet <= 0) + ret = hdd_request_wait_for_response(request); + if (ret) { hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to wait on GwtFwstats")); - //Make magic number to zero so that callback is not executed. - spin_lock(&hdd_context_lock); - fwStatsCtx.magic = 0x0; - spin_unlock(&hdd_context_lock); ret = -EINVAL; + hdd_request_put(request); goto exit; } + + priv = hdd_request_priv(request); + fw_stats_result = priv->fw_stats; + fwStatsRsp->type = 0; + if (NULL != fw_stats_result) + { + switch (fw_stats_result->type ) + { + case FW_UBSP_STATS: + { + tSirUbspFwStats *stats = + &fwStatsRsp->fwStatsData.ubspStats; + memcpy(fwStatsRsp, fw_stats_result, + sizeof(tSirFwStatsResult)); + hddLog(VOS_TRACE_LEVEL_INFO, + FL("ubsp_enter_cnt = %d ubsp_jump_ddr_cnt = %d"), + stats->ubsp_enter_cnt, + stats->ubsp_jump_ddr_cnt); + } + break; + + default: + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("No handling for stats type %d"), + fw_stats_result->type); + } + } + } + hdd_request_put(request); + if (fwStatsRsp->type) { buf = kmalloc(FW_STATE_RSP_LEN, GFP_KERNEL); @@ -6994,7 +7026,6 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, ret = -EFAULT; goto exit; } - } else if (strncasecmp(command, "SET_FCC_CHANNEL", 15) == 0) { From d2ce680adc71a5ad9cdb6ed5fbf09fde97f20f55 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Tue, 8 May 2018 15:21:06 +0530 Subject: [PATCH 395/508] Wlan: Do not flush disconnect command from sme on receiving connect If disconnect command is in SME pending queue, when connect command is received, the disconnect command is flushed and as SME is already in connected state the new connect command is handled as reassoc req and as no preauth was done with this new AP, SME does not call proper HDD callback to indicate conenct failure. Thus HDD remains stuck in connecting state leading to scans rejection. To fix this do not flush disconnect command from SME on receiving connect cmd and thus clean up the SME before connect is processed. Change-Id: Icefe8866a24b332688c64d8e69a11642fd7215d9 CRs-Fixed: 2238548 --- CORE/HDD/src/wlan_hdd_assoc.c | 16 +++++++++++----- CORE/SME/src/csr/csrApiRoam.c | 14 +++++++------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c index e76b50dbe7bfc..eea32d0b11d58 100644 --- a/CORE/HDD/src/wlan_hdd_assoc.c +++ b/CORE/HDD/src/wlan_hdd_assoc.c @@ -1678,7 +1678,8 @@ static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo * * to cfg80211_disconnected */ if ((eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState) || - (eConnectionState_NotConnected == pHddStaCtx->conn_info.connState)) + (eConnectionState_NotConnected == pHddStaCtx->conn_info.connState) || + (eConnectionState_Connecting == pHddStaCtx->conn_info.connState)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, FL(" HDD has initiated a disconnect, no need to send" @@ -1909,10 +1910,15 @@ static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo * // Clear saved connection information in HDD hdd_connRemoveConnectInfo( pHddStaCtx ); - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s: Set HDD connState to eConnectionState_NotConnected", - __func__); - hdd_connSetConnectionState( pHddStaCtx, eConnectionState_NotConnected ); + + /* + * eConnectionState_Connecting state mean that connection is in progress so + * no need to set state to eConnectionState_NotConnected + */ + if ((eConnectionState_Connecting != pHddStaCtx->conn_info.connState)) { + hddLog(LOG1, FL("Set HDD connState to eConnectionState_NotConnected")); + hdd_connSetConnectionState(pHddStaCtx, eConnectionState_NotConnected); + } #ifdef WLAN_FEATURE_GTK_OFFLOAD if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c index cb131b029adec..efe8f1cce217e 100644 --- a/CORE/SME/src/csr/csrApiRoam.c +++ b/CORE/SME/src/csr/csrApiRoam.c @@ -2731,12 +2731,11 @@ void csr_roam_remove_duplicate_cmd_from_list(tpAniSirGlobal pMac, pNextEntry = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK); pDupCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); /* - * Remove the previous command if.. - * - the new roam command is for the same RoamReason... - * - the new roam command is a NewProfileList. - * - the new roam command is a Forced Dissoc - * - the new roam command is from an 802.11 OID - * (OID_SSID or OID_BSSID). + * If pCommand is not NULL remove the similar duplicate cmd for same + * reason as pCommand. If pCommand is NULL then check if eRoamReason is + * eCsrForcedDisassoc (disconnect) and remove all roam command for the + * sessionId, else if eRoamReason is eCsrHddIssued (connect) remove all + * connect (non disconenct) commands. */ if ((pCommand && (pCommand->sessionId == pDupCommand->sessionId) && ((pCommand->command == pDupCommand->command) && @@ -2755,7 +2754,8 @@ void csr_roam_remove_duplicate_cmd_from_list(tpAniSirGlobal pMac, ((sessionId == pDupCommand->sessionId) && (eSmeCommandRoam == pDupCommand->command) && ((eCsrForcedDisassoc == eRoamReason) || - (eCsrHddIssued == eRoamReason)))) + (eCsrHddIssued == eRoamReason && + !CSR_IS_DISCONNECT_COMMAND(pDupCommand))))) { smsLog(pMac, LOGW, FL("RoamReason = %d"), pDupCommand->u.roamCmd.roamReason); From 3887107ac5611a444bbe3baabf8446461cb91e86 Mon Sep 17 00:00:00 2001 From: Arun Kumar Neelakantam Date: Thu, 26 Apr 2018 09:27:53 +0530 Subject: [PATCH 396/508] net: ipc_router: Remove wakeup-source for Sensor ports In high speed sensor data stream case system is not entering into suspend state due to edge and port specific wake-up sources. Add flag to check and avoid the wakeup sources for all sensor ports. CRs-Fixed: 2196601 Change-Id: Ibf642619b969925dc96e8a57e11f7e349b85c024 Signed-off-by: Arun Kumar Neelakantam --- include/linux/ipc_router_xprt.h | 4 ++- net/ipc_router/ipc_router_core.c | 60 +++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/include/linux/ipc_router_xprt.h b/include/linux/ipc_router_xprt.h index 276c79ff15918..5baddb80c66ec 100644 --- a/include/linux/ipc_router_xprt.h +++ b/include/linux/ipc_router_xprt.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2015, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -100,6 +100,7 @@ struct rr_opt_hdr { * @pkt_fragment_q: Queue of SKBs containing payload. * @length: Length of data in the chain of SKBs * @ref: Reference count for the packet. + * @ws_need: Flag to check wakeup soruce need */ struct rr_packet { struct list_head list; @@ -108,6 +109,7 @@ struct rr_packet { struct sk_buff_head *pkt_fragment_q; uint32_t length; struct kref ref; + bool ws_need; }; /** diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c index 8d74fb7abbaef..271eafc960301 100644 --- a/net/ipc_router/ipc_router_core.c +++ b/net/ipc_router/ipc_router_core.c @@ -216,6 +216,25 @@ enum { UP, }; +/** + * is_sensor_port() - Check if the remote port is sensor service or not + * @rport: Pointer to the remote port. + * + * Return: true if the remote port is sensor service else false. + */ +static int is_sensor_port(struct msm_ipc_router_remote_port *rport) +{ + u32 svcid = 0; + + if (rport && rport->server) { + svcid = rport->server->name.service; + if (svcid == 400 || (svcid >= 256 && svcid <= 320)) + return true; + } + + return false; +} + static void init_routing_table(void) { int i; @@ -1165,7 +1184,8 @@ static int post_pkt_to_port(struct msm_ipc_port *port_ptr, } mutex_lock(&port_ptr->port_rx_q_lock_lhc3); - __pm_stay_awake(port_ptr->port_rx_ws); + if (pkt->ws_need) + __pm_stay_awake(port_ptr->port_rx_ws); list_add_tail(&temp_pkt->list, &port_ptr->port_rx_q); wake_up(&port_ptr->port_rx_wait_q); notify = port_ptr->notify; @@ -2718,7 +2738,6 @@ static void do_read_data(struct work_struct *work) struct rr_packet *pkt = NULL; struct msm_ipc_port *port_ptr; struct msm_ipc_router_remote_port *rport_ptr; - int ret; struct msm_ipc_router_xprt_info *xprt_info = container_of(work, @@ -2726,16 +2745,7 @@ static void do_read_data(struct work_struct *work) read_data); while ((pkt = rr_read(xprt_info)) != NULL) { - if (pkt->length < calc_rx_header_size(xprt_info) || - pkt->length > MAX_IPC_PKT_SIZE) { - IPC_RTR_ERR("%s: Invalid pkt length %d\n", - __func__, pkt->length); - goto read_next_pkt1; - } - ret = extract_header(pkt); - if (ret < 0) - goto read_next_pkt1; hdr = &(pkt->hdr); if ((hdr->dst_node_id != IPC_ROUTER_NID_LOCAL) && @@ -4177,6 +4187,7 @@ void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt, { struct msm_ipc_router_xprt_info *xprt_info = xprt->priv; struct msm_ipc_router_xprt_work *xprt_work; + struct msm_ipc_router_remote_port *rport_ptr = NULL; struct rr_packet *pkt; int ret; @@ -4229,9 +4240,34 @@ void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt, if (!pkt) return; + if (pkt->length < calc_rx_header_size(xprt_info) || + pkt->length > MAX_IPC_PKT_SIZE) { + IPC_RTR_ERR("%s: Invalid pkt length %d\n", + __func__, pkt->length); + release_pkt(pkt); + return; + } + + ret = extract_header(pkt); + if (ret < 0) { + release_pkt(pkt); + return; + } + + pkt->ws_need = true; + + if (pkt->hdr.type == IPC_ROUTER_CTRL_CMD_DATA) + rport_ptr = ipc_router_get_rport_ref(pkt->hdr.src_node_id, + pkt->hdr.src_port_id); + mutex_lock(&xprt_info->rx_lock_lhb2); list_add_tail(&pkt->list, &xprt_info->pkt_list); - __pm_stay_awake(&xprt_info->ws); + /* check every pkt is from SENSOR services or not*/ + if (is_sensor_port(rport_ptr)) + pkt->ws_need = false; + else + __pm_stay_awake(&xprt_info->ws); + mutex_unlock(&xprt_info->rx_lock_lhb2); queue_work(xprt_info->workqueue, &xprt_info->read_data); } From 5deb9cd3bd97d7d1e321c7e86e4a92156ee48b2c Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Thu, 10 May 2018 11:04:59 +0530 Subject: [PATCH 397/508] wlan: Use max tx power allowed to compute link report power Driver uses max tx power allowed for a particular channel to calculate link report power and updates max tx power allowed with calculated link report power. This can result in usage of MIN_TX_PWR_CAP as max tx power if AP requests power below MIN_TX_PWR_CAP in link request. Once max tx power reaches MIN_TX_PWR_CAP, the driver will always use MIN_TX_PWR_CAP in the link report which could be much less than power allowed for a particular channel. Use max tx power allowed for a particular channel always to compute link report power to fix this issue. Change-Id: I0060500f23e6131481baa00cd76f41419281e41a CRs-Fixed: 2238098 --- CORE/MAC/src/pe/include/limSession.h | 1 + CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c | 2 +- CORE/MAC/src/pe/rrm/rrmApi.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CORE/MAC/src/pe/include/limSession.h b/CORE/MAC/src/pe/include/limSession.h index 5a2a6e0a2fd96..75ff4f4086243 100644 --- a/CORE/MAC/src/pe/include/limSession.h +++ b/CORE/MAC/src/pe/include/limSession.h @@ -371,6 +371,7 @@ typedef struct sPESession // Added to Support BT-AMP tDot11fIEHTInfo ht_operation; tDot11fIEVHTOperation vht_operation; bool force_24ghz_in_ht20; + int8_t def_max_tx_pwr; }tPESession, *tpPESession; #define LIM_MAX_ACTIVE_SESSIONS 4 diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c index 59934c6d0f6c9..65ec3c36e5fcb 100644 --- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c +++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c @@ -2094,7 +2094,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) TX_POWER_DEFAULT); psessionEntry->maxTxPower = TX_POWER_DEFAULT; } - + psessionEntry->def_max_tx_pwr = psessionEntry->maxTxPower; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, "Regulatory max = %d, local power constraint = %d," " max tx = %d", regMax, localPowerConstraint, diff --git a/CORE/MAC/src/pe/rrm/rrmApi.c b/CORE/MAC/src/pe/rrm/rrmApi.c index 5bba7e7df2646..a3970698036c5 100644 --- a/CORE/MAC/src/pe/rrm/rrmApi.c +++ b/CORE/MAC/src/pe/rrm/rrmApi.c @@ -282,7 +282,7 @@ rrmProcessLinkMeasurementRequest( tpAniSirGlobal pMac, return eSIR_FAILURE; } pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo ); - LinkReport.txPower = limGetMaxTxPower (pSessionEntry->maxTxPower, + LinkReport.txPower = limGetMaxTxPower (pSessionEntry->def_max_tx_pwr, pLinkReq->MaxTxPower.maxTxPower, pMac->roam.configParam.nTxPowerCap); From a0cafdd2c7316ffda9ec7397332e7954ef7e45c6 Mon Sep 17 00:00:00 2001 From: Chinmay Sawarkar Date: Fri, 29 Sep 2017 15:51:51 -0700 Subject: [PATCH 398/508] msm: vidc: Fix use after free bug in set_output_buffers When set_buffers fails, binfo is freed and again accessed while freeing smem memory. CRs-Fixed: 2118860 Change-Id: Ifdd683f907862665e34d6d39d5a8634984804c01 Signed-off-by: Chinmay Sawarkar Signed-off-by: Sanjay Singh --- drivers/media/platform/msm/vidc/msm_vidc_common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 909adcc091c41..73c26bb60facf 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -3032,7 +3032,7 @@ static int set_output_buffers(struct msm_vidc_inst *inst, { int rc = 0; struct msm_smem *handle; - struct internal_buf *binfo; + struct internal_buf *binfo = NULL; u32 smem_flags = 0, buffer_size; struct hal_buffer_requirements *output_buf, *extradata_buf; int i; @@ -3138,10 +3138,10 @@ static int set_output_buffers(struct msm_vidc_inst *inst, } return rc; fail_set_buffers: - kfree(binfo); -fail_kzalloc: msm_comm_smem_free(inst, handle); err_no_mem: + kfree(binfo); +fail_kzalloc: return rc; } From 95e5bc20c0a3d3da0ccb48e6019cf54cd8dd4b1d Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Thu, 19 Apr 2018 17:06:33 +0530 Subject: [PATCH 399/508] wlan: Reject invalid subsequent set disable channel command Currently driver accepts subsequent set disable channel list commands and appends all the channels given in subsequnet commnds. On SAP turn on driver disables all these channels, driver should only disable the channels received in the first command. To address this issue reject all the subsequent commands which contains channel list different than the channel list given in the first command. Allow configuration of different disable channel list only after the current disable channel list is restored. Change-Id: I6625ff5215867068c449b39dcb2f397a9fa1c108 CRs-Fixed: 2227758 --- CORE/HDD/inc/wlan_hdd_main.h | 6 +- CORE/HDD/src/wlan_hdd_cfg80211.c | 4 +- CORE/HDD/src/wlan_hdd_hostapd.c | 4 +- CORE/HDD/src/wlan_hdd_main.c | 199 ++++++++++++++++--------------- CORE/HDD/src/wlan_hdd_wext.c | 4 +- CORE/VOSS/inc/vos_nvitem.h | 3 +- CORE/VOSS/src/vos_nvitem.c | 3 +- 7 files changed, 115 insertions(+), 108 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index 0cb344bf8a911..ebf0a8c693dd6 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -1562,7 +1562,7 @@ struct hdd_offloaded_packets_ctx struct hdd_cache_channel_info { int channel_num; - int reg_status; + eNVChannelEnabledType reg_status; int wiphy_status; }; @@ -1859,7 +1859,7 @@ struct hdd_context_s uint32_t track_arp_ip; - struct hdd_cache_channels *orginal_channels; + struct hdd_cache_channels *original_channels; struct mutex cache_channel_lock; }; @@ -2372,7 +2372,7 @@ int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr); * @return: length of data copied to buf */ int hdd_get_disable_ch_list(hdd_context_t *hdd_ctx, tANI_U8 *buf, - tANI_U8 buf_len); + uint32_t buf_len); /** * hdd_is_memdump_supported() - to check if memdump feature support diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 6d0c72178c636..219608307420d 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -10817,7 +10817,7 @@ int wlan_hdd_restore_channels(hdd_context_t *hdd_ctx) mutex_lock(&hdd_ctx->cache_channel_lock); - cache_chann = hdd_ctx->orginal_channels; + cache_chann = hdd_ctx->original_channels; if (!cache_chann || !cache_chann->num_channels) { hddLog(VOS_TRACE_LEVEL_INFO, @@ -10896,7 +10896,7 @@ static int wlan_hdd_disable_channels(hdd_context_t *hdd_ctx) wiphy = hdd_ctx->wiphy; mutex_lock(&hdd_ctx->cache_channel_lock); - cache_chann = hdd_ctx->orginal_channels; + cache_chann = hdd_ctx->original_channels; if (!cache_chann || !cache_chann->num_channels) { hddLog(VOS_TRACE_LEVEL_INFO, diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index f350747aac2e2..7d3037f8d9dbb 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -4524,7 +4524,7 @@ static int __iw_get_ap_freq(struct net_device *dev, else { status = hdd_wlan_get_freq(channel, &freq); - if( TRUE == status) + if( 0 == status) { /* Set Exponent parameter as 6 (MHZ) in struct iw_freq * iwlist & iwconfig command shows frequency into proper @@ -4538,7 +4538,7 @@ static int __iw_get_ap_freq(struct net_device *dev, { channel = pHddApCtx->operatingChannel; status = hdd_wlan_get_freq(channel, &freq); - if( TRUE == status) + if( 0 == status) { /* Set Exponent parameter as 6 (MHZ) in struct iw_freq * iwlist & iwconfig command shows frequency into proper diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 41f91f02ae545..9015a27706571 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -3598,11 +3598,11 @@ static inline void hdd_assign_reassoc_handoff(tCsrHandoffRequest *handoffInfo) static void wlan_hdd_free_cache_channels(hdd_context_t *hdd_ctx) { mutex_lock(&hdd_ctx->cache_channel_lock); - hdd_ctx->orginal_channels->num_channels = 0; - vos_mem_free(hdd_ctx->orginal_channels->channel_info); - hdd_ctx->orginal_channels->channel_info = NULL; - vos_mem_free(hdd_ctx->orginal_channels); - hdd_ctx->orginal_channels = NULL; + hdd_ctx->original_channels->num_channels = 0; + vos_mem_free(hdd_ctx->original_channels->channel_info); + hdd_ctx->original_channels->channel_info = NULL; + vos_mem_free(hdd_ctx->original_channels); + hdd_ctx->original_channels = NULL; mutex_unlock(&hdd_ctx->cache_channel_lock); } @@ -3618,58 +3618,24 @@ static void wlan_hdd_free_cache_channels(hdd_context_t *hdd_ctx) int hdd_alloc_chan_cache(hdd_context_t *hdd_ctx, int num_chan) { - if (NULL == hdd_ctx->orginal_channels) { - hdd_ctx->orginal_channels = + hdd_ctx->original_channels = vos_mem_malloc(sizeof(struct hdd_cache_channels)); - if (NULL == hdd_ctx->orginal_channels) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "In %s, VOS_MALLOC_ERR", __func__); - return -EINVAL; - } - hdd_ctx->orginal_channels->num_channels = num_chan; - hdd_ctx->orginal_channels->channel_info = + if (!hdd_ctx->original_channels) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "In %s, VOS_MALLOC_ERR", __func__); + return -EINVAL; + } + hdd_ctx->original_channels->num_channels = num_chan; + hdd_ctx->original_channels->channel_info = vos_mem_malloc(num_chan * sizeof(struct hdd_cache_channel_info)); - if (NULL == hdd_ctx->orginal_channels->channel_info) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "In %s, VOS_MALLOC_ERR", __func__); - hdd_ctx->orginal_channels->num_channels = 0; - vos_mem_free(hdd_ctx->orginal_channels); - hdd_ctx->orginal_channels = NULL; - return -EINVAL; - } - } else { - /* Same command comes multiple times */ - struct hdd_cache_channel_info *temp_chan_info; - - if (hdd_ctx->orginal_channels->num_channels + num_chan > - MAX_CHANNEL) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Invalid Number of channel received", - __func__); - return -EINVAL; - } - - temp_chan_info = vos_mem_malloc(( - hdd_ctx->orginal_channels-> - num_channels + num_chan) * - sizeof(struct hdd_cache_channel_info)); - if (NULL == temp_chan_info) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "In %s, VOS_MALLOC_ERR", - __func__); - return -EINVAL; - } - - vos_mem_copy(temp_chan_info, hdd_ctx->orginal_channels-> - channel_info, hdd_ctx->orginal_channels-> - num_channels * - sizeof(struct hdd_cache_channel_info)); - - hdd_ctx->orginal_channels->num_channels += num_chan; - vos_mem_free(hdd_ctx->orginal_channels->channel_info); - hdd_ctx->orginal_channels->channel_info = temp_chan_info; - temp_chan_info = NULL; + if (!hdd_ctx->original_channels->channel_info) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "In %s, VOS_MALLOC_ERR", __func__); + hdd_ctx->original_channels->num_channels = 0; + vos_mem_free(hdd_ctx->original_channels); + hdd_ctx->original_channels = NULL; + return -ENOMEM; } return 0; @@ -3681,7 +3647,9 @@ int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr) v_PVOID_t pvosGCtx = vos_get_global_context(VOS_MODULE_ID_HDD, NULL); hdd_context_t *hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, pvosGCtx); tANI_U8 *param; - int j, tempInt, index = 0, ret = 0; + int j, tempInt, ret = 0, i, num_channels; + int parsed_channels[MAX_CHANNEL]; + bool is_command_repeated = false; if (NULL == pvosGCtx) { hddLog(VOS_TRACE_LEVEL_FATAL, @@ -3743,13 +3711,25 @@ int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr) } mutex_lock(&hdd_ctx->cache_channel_lock); - if (hdd_alloc_chan_cache(hdd_ctx, tempInt)) { - ret = -ENOMEM; - goto parse_done; + if (!hdd_ctx->original_channels) { + if (hdd_alloc_chan_cache(hdd_ctx, tempInt)) { + ret = -ENOMEM; + goto mem_alloc_failed; + } + } else if (hdd_ctx->original_channels->num_channels != tempInt) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s, Invalid No of channel provided in the list", + __func__); + ret = -EINVAL; + is_command_repeated = true; + goto parse_failed; + } else { + is_command_repeated = true; } - index = hdd_ctx->orginal_channels->num_channels - tempInt; - for (j = index; j < hdd_ctx->orginal_channels->num_channels; j++) { + num_channels = tempInt; + + for (j = 0; j < num_channels; j++) { /* * param pointing to the beginning of first space * after number of channels @@ -3761,7 +3741,7 @@ int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr) "%s, Invalid No of channel provided in the list", __func__); ret = -EINVAL; - goto parse_done; + goto parse_failed; } param++; @@ -3775,7 +3755,7 @@ int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr) "%s, No channel is provided in the list", __func__); ret = -EINVAL; - goto parse_done; + goto parse_failed; } @@ -3784,7 +3764,7 @@ int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr) "%s: Cannot read channel number", __func__); ret = -EINVAL; - goto parse_done; + goto parse_failed; } @@ -3793,14 +3773,14 @@ int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr) "%s: Invalid channel number received", __func__); ret = -EINVAL; - goto parse_done; + goto parse_failed; } hddLog(VOS_TRACE_LEVEL_INFO, "%s: channel[%d] = %d", __func__, j, tempInt); - hdd_ctx->orginal_channels->channel_info[j].channel_num = - tempInt; + + parsed_channels[j] = tempInt; } /*extra arguments check*/ @@ -3813,48 +3793,70 @@ int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr) hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid argument received", __func__); ret = -EINVAL; - goto parse_done; + goto parse_failed; + } + } + + /* + * If command is received first time, cache the channels to + * be disabled else compare the channels received in the + * command with the cached channels, if channel list matches + * return success otherewise return failure. + */ + if (!is_command_repeated) + for (j = 0; j < num_channels; j++) + hdd_ctx->original_channels-> + channel_info[j].channel_num = + parsed_channels[j]; + else { + for (i = 0; i < num_channels; i++) { + for (j = 0; j < num_channels; j++) + if (hdd_ctx->original_channels-> + channel_info[i].channel_num == + parsed_channels[j]) + break; + if (j == num_channels) { + ret = -EINVAL; + goto parse_failed; + } } + ret = 0; } -parse_done: +mem_alloc_failed: mutex_unlock(&hdd_ctx->cache_channel_lock); EXIT(); return ret; + +parse_failed: + mutex_unlock(&hdd_ctx->cache_channel_lock); + if (!is_command_repeated) + wlan_hdd_free_cache_channels(hdd_ctx); + EXIT(); + return ret; + } int hdd_get_disable_ch_list(hdd_context_t *hdd_ctx, tANI_U8 *buf, - tANI_U8 buf_len) + uint32_t buf_len) { struct hdd_cache_channel_info *ch_list; unsigned char i, num_ch; int len = 0; mutex_lock(&hdd_ctx->cache_channel_lock); - if (hdd_ctx->orginal_channels && - hdd_ctx->orginal_channels->num_channels) { - num_ch = hdd_ctx->orginal_channels->num_channels; - - if (num_ch == 0) { - mutex_unlock(&hdd_ctx->cache_channel_lock); - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - FL("no disable channels programed")); - return 0; - } + if (hdd_ctx->original_channels && + hdd_ctx->original_channels->num_channels && + hdd_ctx->original_channels->channel_info) { + num_ch = hdd_ctx->original_channels->num_channels; len = scnprintf(buf, buf_len, "%s %hhu", "GET_DISABLE_CHANNEL_LIST", num_ch); - ch_list = hdd_ctx->orginal_channels->channel_info; - if (!ch_list) { - mutex_unlock(&hdd_ctx->cache_channel_lock); - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - FL("disable channel list is NULL")); - return 0; - } + ch_list = hdd_ctx->original_channels->channel_info; - for (i = 0; (i < num_ch) && len <= buf_len; i++) { + for (i = 0; (i < num_ch) && (len < buf_len-1); i++) { len += scnprintf(buf + len, buf_len - len, " %d", ch_list[i].channel_num); } @@ -7071,25 +7073,25 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, goto exit; } else if (strncmp(command, "GET_DISABLE_CHANNEL_LIST", 24) == 0) { - char extra[128] = {0}; - int len; + char extra[512] = {0}; + int max_len, copied_length; - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, " Received Command to get disable Channels list %s", __func__); - len = hdd_get_disable_ch_list(pHddCtx, extra, sizeof(extra)); - if (len == 0) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + max_len = VOS_MIN(priv_data.total_len, sizeof(extra)); + copied_length = hdd_get_disable_ch_list(pHddCtx, extra, max_len); + if (copied_length == 0) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, FL("disable channel list are not yet programed")); ret = -EINVAL; goto exit; } - len = VOS_MIN(priv_data.total_len, len + 1); - if (copy_to_user(priv_data.buf, &extra, len)) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: failed to copy data to user buffer", __func__); + if (copy_to_user(priv_data.buf, &extra, copied_length + 1)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); ret = -EFAULT; goto exit; } @@ -12466,6 +12468,9 @@ void hdd_wlan_exit(hdd_context_t *pHddCtx) __func__); } + /* Free the cache channels of the command SET_DISABLE_CHANNEL_LIST */ + wlan_hdd_free_cache_channels(pHddCtx); + //Free up dynamically allocated members inside HDD Adapter if (pHddCtx->cfg_ini) { diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 4e70677adfe16..fb9cd4dfab4ea 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -839,7 +839,7 @@ int hdd_wlan_get_freq(v_U32_t channel, v_U32_t *pfreq) if (channel == freq_chan_map[i].chan) { *pfreq = freq_chan_map[i].freq; - return 1; + return 0; } } } @@ -1841,7 +1841,7 @@ static int __iw_get_freq(struct net_device *dev, else { status = hdd_wlan_get_freq(channel, &freq); - if( TRUE == status ) + if( 0 == status ) { /* Set Exponent parameter as 6 (MHZ) in struct iw_freq * iwlist & iwconfig command shows frequency into proper diff --git a/CORE/VOSS/inc/vos_nvitem.h b/CORE/VOSS/inc/vos_nvitem.h index 3880855fa2e93..f86bf809cba65 100644 --- a/CORE/VOSS/inc/vos_nvitem.h +++ b/CORE/VOSS/inc/vos_nvitem.h @@ -745,7 +745,8 @@ eNVChannelEnabledType vos_nv_getChannelEnabledState * DFS * Return - Void */ -void vos_nv_set_channel_state(v_U32_t rfChannel, int channel_state); +void vos_nv_set_channel_state(v_U32_t rfChannel, + eNVChannelEnabledType channel_state); VOS_STATUS vos_init_wiphy_from_nv_bin(void); diff --git a/CORE/VOSS/src/vos_nvitem.c b/CORE/VOSS/src/vos_nvitem.c index 175bb82cb5115..2251e8a2efcb6 100644 --- a/CORE/VOSS/src/vos_nvitem.c +++ b/CORE/VOSS/src/vos_nvitem.c @@ -2643,7 +2643,8 @@ VOS_STATUS vos_nv_setNVEncodedBuffer(v_U8_t *pNvBuffer, v_SIZE_t size) * DFS * Return - Void */ -void vos_nv_set_channel_state(v_U32_t rfChannel, int channel_state) +void vos_nv_set_channel_state(v_U32_t rfChannel, + eNVChannelEnabledType channel_state) { v_U32_t channelLoop; eRfChannels channelEnum = INVALID_RF_CHANNEL; From c1333e472a200f668ac191ae4461dff51c632a73 Mon Sep 17 00:00:00 2001 From: Jiten Patel Date: Fri, 11 May 2018 12:34:26 +0530 Subject: [PATCH 400/508] qseecom: Add flag to support key wrap in KS Allow to use KS key instead of user key to wrap ICE master key. This is required for devices which don't have provision to modify user key. Change-Id: I2a7f6cd10a9c69b5d5d8a39e31a3d1630136eaa6 Signed-off-by: Jiten Patel --- .../devicetree/bindings/qseecom/qseecom.txt | 3 +++ drivers/misc/qseecom.c | 17 ++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/qseecom/qseecom.txt b/Documentation/devicetree/bindings/qseecom/qseecom.txt index dfc62b78f58dc..1d48c7136a3e6 100644 --- a/Documentation/devicetree/bindings/qseecom/qseecom.txt +++ b/Documentation/devicetree/bindings/qseecom/qseecom.txt @@ -27,6 +27,7 @@ Optional properties: - qcom,qsee-reentrancy-support: indicates the qsee reentrancy phase supported by the target - qcom,commonlib64-loaded-by-uefi: indicates commonlib64 is loaded by uefi already - qcom,fde-key-size: indicates which FDE key size is used in device. + - qcom,enable-key-wrap-in-ks: enables wrapping of ICE key with KS key. Example: qcom,qseecom@fe806000 { @@ -40,6 +41,7 @@ Example: qcom,hlos-ce-hw-instance = <1 2>; qcom,qsee-ce-hw-instance = <0>; qcom,support-fde; + qcom,enable-key-wrap-in-ks; qcom,support-pfe; qcom,msm_bus,name = "qseecom-noc"; qcom,msm_bus,num_cases = <4>; @@ -64,6 +66,7 @@ Example: The following dts setup is the same as the example above. reg = <0x7f00000 0x500000>; reg-names = "secapp-region"; qcom,support-fde; + qcom,enable-key-wrap-in-ks; qcom,full-disk-encrypt-info = <0 1 2>, <0 2 2>; qcom,support-pfe; qcom,per-file-encrypt-info = <0 1 0>, <0 2 0>; diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 84a0a9bbd1256..f2955be618998 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -1,6 +1,6 @@ /*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver * - * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -109,6 +109,9 @@ #define DEFAULT_CE_INFO_UNIT 0 #define DEFAULT_NUM_CE_INFO_UNIT 1 +#define FDE_FLAG_POS 4 +#define ENABLE_KEY_WRAP_IN_KS (1 << FDE_FLAG_POS) + enum qseecom_clk_definitions { CLK_DFAB = 0, CLK_SFPB, @@ -273,6 +276,7 @@ struct qseecom_control { unsigned int ce_opp_freq_hz; bool appsbl_qseecom_support; uint32_t qsee_reentrancy_support; + bool enable_key_wrap_in_ks; uint32_t app_block_ref_cnt; wait_queue_head_t app_block_wq; @@ -5779,6 +5783,9 @@ static int qseecom_create_key(struct qseecom_dev_handle *data, else flags |= QSEECOM_ICE_FDE_KEY_SIZE_16_BYTE; + if (qseecom.enable_key_wrap_in_ks == true) + flags |= ENABLE_KEY_WRAP_IN_KS; + generate_key_ireq.flags = flags; generate_key_ireq.qsee_command_id = QSEOS_GENERATE_KEY; memset((void *)generate_key_ireq.key_id, @@ -8467,6 +8474,14 @@ static int qseecom_probe(struct platform_device *pdev) qseecom.qsee_reentrancy_support); } + qseecom.enable_key_wrap_in_ks = + of_property_read_bool((&pdev->dev)->of_node, + "qcom,enable-key-wrap-in-ks"); + if (qseecom.enable_key_wrap_in_ks) { + pr_warn("qseecom.enable_key_wrap_in_ks = %d\n", + qseecom.enable_key_wrap_in_ks); + } + /* * The qseecom bus scaling flag can not be enabled when * crypto clock is not handled by HLOS. From ccc9b1e83faffe5e9b3288d3c1010f9a9df47f7f Mon Sep 17 00:00:00 2001 From: Jiten Patel Date: Mon, 14 May 2018 19:41:19 +0530 Subject: [PATCH 401/508] ARM: dts: msm: Add qseecom flag to enable key wrapping in KS for apq8053 The flag allows to wrap ICE master key instead of user key. This is required for the devices which don't have provision to modify user key. Change-Id: I826aea9aa37b840ae1c5e610c7db62e6d6a81477 Signed-off-by: Jiten Patel --- arch/arm/boot/dts/qcom/apq8053.dtsi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/qcom/apq8053.dtsi b/arch/arm/boot/dts/qcom/apq8053.dtsi index 48529b041afce..b4aa9ae8b6448 100644 --- a/arch/arm/boot/dts/qcom/apq8053.dtsi +++ b/arch/arm/boot/dts/qcom/apq8053.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -52,3 +52,7 @@ &secure_mem { status = "disabled"; }; + +&qcom_seecom { + qcom,enable-key-wrap-in-ks; +}; From 6e6cbef7d0c0c105ccdb40958fabf5a39555772f Mon Sep 17 00:00:00 2001 From: gaolez Date: Mon, 5 Feb 2018 11:11:22 +0800 Subject: [PATCH 402/508] mmc: core: Card specific custom settings for SDIO Add quirk to modify custom settings for QCA9379 card. Change-Id: Ib2380a5bba50b6b8aec9afde4c6b0681d4b25f38 CRs-Fixed: 2183585 Signed-off-by: Gaole Zhang --- drivers/mmc/core/quirks.c | 10 ++++++++++ drivers/mmc/core/sdio.c | 3 ++- include/linux/mmc/card.h | 7 +++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c index 071adc1011584..1b4e40c0aff6c 100644 --- a/drivers/mmc/core/quirks.c +++ b/drivers/mmc/core/quirks.c @@ -79,6 +79,13 @@ #define SDIO_DEVICE_ID_QCA9377 0x701 #endif +#ifndef SDIO_VENDOR_ID_QCA9379 +#define SDIO_VENDOR_ID_QCA9379 0x271 +#endif + +#ifndef SDIO_DEVICE_ID_QCA9379 +#define SDIO_DEVICE_ID_QCA9379 0x801 +#endif /* * This hook just adds a quirk for all sdio devices @@ -131,6 +138,9 @@ static const struct mmc_fixup mmc_fixup_methods[] = { SDIO_FIXUP(SDIO_VENDOR_ID_QCA9377, SDIO_DEVICE_ID_QCA9377, add_quirk, MMC_QUIRK_QCA9377_SETTINGS), + + SDIO_FIXUP(SDIO_VENDOR_ID_QCA9379, SDIO_DEVICE_ID_QCA9379, + add_quirk, MMC_QUIRK_QCA9379_SETTINGS), END_FIXUP }; diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 5651cf63f8bd7..65425a41a84f1 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -228,7 +228,8 @@ static void sdio_enable_vendor_specific_settings(struct mmc_card *card) u8 settings; if (mmc_enable_qca6574_settings(card) || - mmc_enable_qca9377_settings(card)) { + mmc_enable_qca9377_settings(card) || + mmc_enable_qca9379_settings(card)) { ret = mmc_io_rw_direct(card, 1, 0, 0xF2, 0x0F, NULL); if (ret) { pr_crit("%s: failed to write to fn 0xf2 %d\n", diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index f6cec9c43d98b..9f7cbb375a374 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -393,6 +393,8 @@ struct mmc_card { /* Make sure CMDQ is empty before queuing DCMD */ #define MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD (1 << 17) +#define MMC_QUIRK_QCA9379_SETTINGS (1 << 18) /* QCA9379 card settings*/ + unsigned int erase_size; /* erase size in sectors */ unsigned int erase_shift; /* if erase unit is power 2 */ unsigned int pref_erase; /* in sectors */ @@ -693,6 +695,11 @@ static inline bool mmc_enable_qca9377_settings(const struct mmc_card *c) return c->quirks & MMC_QUIRK_QCA9377_SETTINGS; } +static inline bool mmc_enable_qca9379_settings(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_QCA9379_SETTINGS; +} + #define mmc_card_name(c) ((c)->cid.prod_name) #define mmc_card_id(c) (dev_name(&(c)->dev)) From f8141c089ecd28f94fe2ef87a5c4c3f903b8b244 Mon Sep 17 00:00:00 2001 From: gaolez Date: Fri, 2 Feb 2018 12:24:31 +0800 Subject: [PATCH 403/508] cnss_sdio: Add Naples sdio device id in sdio device list Add Naples sdio device id in sdio device list, so that the Naples wlan card will not be reported as an unknown device. Change-Id: Iaad43aed32082372a0d1bc9f4e9c5c35f0750b19 CRs-Fixed: 2183586 Signed-off-by: Gaole Zhang --- drivers/net/wireless/cnss/cnss_sdio.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/cnss/cnss_sdio.c b/drivers/net/wireless/cnss/cnss_sdio.c index fafab69105707..3177140eadfeb 100644 --- a/drivers/net/wireless/cnss/cnss_sdio.c +++ b/drivers/net/wireless/cnss/cnss_sdio.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -127,6 +127,7 @@ static struct cnss_sdio_data { /* SDIO manufacturer ID and Codes */ #define MANUFACTURER_ID_AR6320_BASE 0x500 #define MANUFACTURER_ID_QCA9377_BASE 0x700 +#define MANUFACTURER_ID_QCA9379_BASE 0x800 #define MANUFACTURER_CODE 0x271 static const struct sdio_device_id ar6k_id_table[] = { @@ -162,6 +163,22 @@ static const struct sdio_device_id ar6k_id_table[] = { {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xD))}, {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xE))}, {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xF))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x0))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x1))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x2))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x3))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x4))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x5))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x6))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x7))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x8))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x9))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xA))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xB))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xC))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xD))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xE))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xF))}, {}, }; MODULE_DEVICE_TABLE(sdio, ar6k_id_table); From a250ed86410a75b7f24946e49e3af39062f42400 Mon Sep 17 00:00:00 2001 From: Archana Sathyakumar Date: Tue, 10 Oct 2017 11:13:41 -0600 Subject: [PATCH 404/508] soc: qcom: rpm_stats: Fix snprintf string format Undefined string lengths could lead to buffer overflows. Format the string correctly to ensure proper usage of snprintf. Change-Id: Ia85754327d342aefce2a67eb7f5aeca857d8fbcf Signed-off-by: Archana Sathyakumar --- drivers/soc/qcom/rpm_stats.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/rpm_stats.c b/drivers/soc/qcom/rpm_stats.c index 30b92657b6bc6..f56cddfa72081 100644 --- a/drivers/soc/qcom/rpm_stats.c +++ b/drivers/soc/qcom/rpm_stats.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2011-2015, 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2015, 2017-2018, The Linux Foundation. + * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -430,7 +431,7 @@ static ssize_t rpmstats_show(struct kobject *kobj, prvdata); } - ret = snprintf(buf, prvdata->len, prvdata->buf); + ret = snprintf(buf, prvdata->len, "%s", prvdata->buf); iounmap(prvdata->reg_base); ioremap_fail: kfree(prvdata); From c6351f8bcb9dfc2c053550436592845776d9f5f2 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Mon, 11 Sep 2017 09:45:40 +0200 Subject: [PATCH 405/508] PCI: Fix race condition with driver_override The driver_override implementation is susceptible to a race condition when different threads are reading vs. storing a different driver override. Add locking to avoid the race condition. This is in close analogy to commit 6265539776a0 ("driver core: platform: fix race condition with driver_override") from Adrian Salido. Change-Id: Ic5ddbe28ba71c4e45892bb1a6bb1d81d3b34a33a Fixes: 782a985d7af2 ("PCI: Introduce new device binding path using pci_dev.driver_override") Signed-off-by: Nicolai Stange Signed-off-by: Bjorn Helgaas Cc: stable@vger.kernel.org # v3.16+ Git-commit: 9561475db680f7144d2223a409dd3d7e322aca03 Git-repo: https://android.googlesource.com/kernel/common Signed-off-by: Srinivasa Rao Kuppala --- drivers/pci/pci-sysfs.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 66ba1ee09a6c7..318707870cb25 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -513,7 +513,7 @@ static ssize_t driver_override_store(struct device *dev, const char *buf, size_t count) { struct pci_dev *pdev = to_pci_dev(dev); - char *driver_override, *old = pdev->driver_override, *cp; + char *driver_override, *old, *cp; /* We need to keep extra room for a newline */ if (count >= (PAGE_SIZE - 1)) @@ -527,12 +527,15 @@ static ssize_t driver_override_store(struct device *dev, if (cp) *cp = '\0'; + device_lock(dev); + old = pdev->driver_override; if (strlen(driver_override)) { pdev->driver_override = driver_override; } else { kfree(driver_override); pdev->driver_override = NULL; } + device_unlock(dev); kfree(old); @@ -543,8 +546,12 @@ static ssize_t driver_override_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pci_dev *pdev = to_pci_dev(dev); + ssize_t len; - return snprintf(buf, PAGE_SIZE, "%s\n", pdev->driver_override); + device_lock(dev); + len = snprintf(buf, PAGE_SIZE, "%s\n", pdev->driver_override); + device_unlock(dev); + return len; } static DEVICE_ATTR_RW(driver_override); From 2648ea0d9115a33a41b03fd34d7345955a43d36b Mon Sep 17 00:00:00 2001 From: Xin Long Date: Wed, 18 Apr 2018 14:36:24 +0530 Subject: [PATCH 406/508] sctp: do not peel off an assoc from one netns to another one Now when peeling off an association to the sock in another netns, all transports in this assoc are not to be rehashed and keep use the old key in hashtable. As a transport uses sk->net as the hash key to insert into hashtable, it would miss removing these transports from hashtable due to the new netns when closing the sock and all transports are being freeed, then later an use-after-free issue could be caused when looking up an asoc and dereferencing those transports. This is a very old issue since very beginning, ChunYu found it with syzkaller fuzz testing with this series: socket$inet6_sctp() bind$inet6() sendto$inet6() unshare(0x40000000) getsockopt$inet_sctp6_SCTP_GET_ASSOC_ID_LIST() getsockopt$inet_sctp6_SCTP_SOCKOPT_PEELOFF() This patch is to block this call when peeling one assoc off from one netns to another one, so that the netns of all transport would not go out-sync with the key in hashtable. Note that this patch didn't fix it by rehashing transports, as it's difficult to handle the situation when the tuple is already in use in the new netns. Besides, no one would like to peel off one assoc to another netns, considering ipaddrs, ifaces, etc. are usually different. Change-Id: Id4da5f2b3347ef35a57ac893868cfa593cf3abfd Reported-by: ChunYu Wang Signed-off-by: Xin Long Acked-by: Marcelo Ricardo Leitner Acked-by: Neil Horman Signed-off-by: David S. Miller Git-commit: df80cd9b28b9ebaa284a41df611dbf3a2d05ca74 Git-repo: https://android.googlesource.com/kernel/common Signed-off-by: Srinivasa Rao Kuppala --- net/sctp/socket.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 92c6eac72ea6c..756f8eb8f0b04 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4436,6 +4436,10 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) struct socket *sock; int err = 0; + /* Do not peel off from one netns to another one. */ + if (!net_eq(current->nsproxy->net_ns, sock_net(sk))) + return -EINVAL; + if (!asoc) return -EINVAL; From 04d0ab9fc987dd7579bd3f948421a59b7f23481f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:48:18 +0100 Subject: [PATCH 407/508] KEYS: encrypted: fix buffer overread in valid_master_desc() With the 'encrypted' key type it was possible for userspace to provide a data blob ending with a master key description shorter than expected, e.g. 'keyctl add encrypted desc "new x" @s'. When validating such a master key description, validate_master_desc() could read beyond the end of the buffer. Fix this by using strncmp() instead of memcmp(). [Also clean up the code to deduplicate some logic.] Change-Id: Ib88f30f89c1854a1650ea2b58c2871a515297d82 Cc: Mimi Zohar Signed-off-by: Eric Biggers Signed-off-by: David Howells Signed-off-by: James Morris Git-commit: 794b4bc292f5d31739d89c0202c54e7dc9bc3add Git-repo: https://android.googlesource.com/kernel/common Signed-off-by: Srinivasa Rao Kuppala --- security/keys/encrypted-keys/encrypted.c | 31 ++++++++++++------------ 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 8e1c0099bb66c..57e578888e0fb 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -141,23 +141,22 @@ static int valid_ecryptfs_desc(const char *ecryptfs_desc) */ static int valid_master_desc(const char *new_desc, const char *orig_desc) { - if (!memcmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) { - if (strlen(new_desc) == KEY_TRUSTED_PREFIX_LEN) - goto out; - if (orig_desc) - if (memcmp(new_desc, orig_desc, KEY_TRUSTED_PREFIX_LEN)) - goto out; - } else if (!memcmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) { - if (strlen(new_desc) == KEY_USER_PREFIX_LEN) - goto out; - if (orig_desc) - if (memcmp(new_desc, orig_desc, KEY_USER_PREFIX_LEN)) - goto out; - } else - goto out; + int prefix_len; + + if (!strncmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) + prefix_len = KEY_TRUSTED_PREFIX_LEN; + else if (!strncmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) + prefix_len = KEY_USER_PREFIX_LEN; + else + return -EINVAL; + + if (!new_desc[prefix_len]) + return -EINVAL; + + if (orig_desc && strncmp(new_desc, orig_desc, prefix_len)) + return -EINVAL; + return 0; -out: - return -EINVAL; } /* From 346434c6c9f99343ec8c3cbfbabe757b79faad24 Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Wed, 6 Dec 2017 12:12:27 -0800 Subject: [PATCH 408/508] netlink: Add netns check on taps [ Upstream commit 93c647643b48f0131f02e45da3bd367d80443291 ] Currently, a nlmon link inside a child namespace can observe systemwide netlink activity. Filter the traffic so that nlmon can only sniff netlink messages from its own netns. Test case: vpnns -- bash -c "ip link add nlmon0 type nlmon; \ ip link set nlmon0 up; \ tcpdump -i nlmon0 -q -w /tmp/nlmon.pcap -U" & sudo ip xfrm state add src 10.1.1.1 dst 10.1.1.2 proto esp \ spi 0x1 mode transport \ auth sha1 0x6162633132330000000000000000000000000000 \ enc aes 0x00000000000000000000000000000000 grep --binary abc123 /tmp/nlmon.pcap Change-Id: Iac724785371047d0af2fb0285c48bb7808b9394f Bug: 70980949 Signed-off-by: Kevin Cernekee Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Git-commit: 04de0650469ab58d5159b29f850fc3c06e6f4975 Git-repo: https://android.googlesource.com/kernel/msm Signed-off-by: Srinivasa Rao Kuppala --- net/netlink/af_netlink.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 4f802a56c50b5..577d9a0d32c8b 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -232,6 +232,9 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb, struct sock *sk = skb->sk; int ret = -ENOMEM; + if (!net_eq(dev_net(dev), sock_net(sk))) + return 0; + dev_hold(dev); if (is_vmalloc_addr(skb->head)) From bac87badec6da8ca3eef1d4a0f8ffdd2b4857851 Mon Sep 17 00:00:00 2001 From: Gustavo Solaira Date: Tue, 15 May 2018 20:23:08 -0700 Subject: [PATCH 409/508] ARM: dts: msm: Use GPIO_85 for IPC on MDM9650 TTP PCIe_EP devices Use GPIO_85 for MDM2AP status on MDM9650 TTP PCIe_EP devices instead of GPIO_16 since this is owned by bluetooth. Change-Id: I4f954664e3782f0a407b721514f0d4ad1a67d86e Signed-off-by: Gustavo Solaira --- arch/arm/boot/dts/qcom/mdm9650-pcie-ep-ttp.dts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/boot/dts/qcom/mdm9650-pcie-ep-ttp.dts b/arch/arm/boot/dts/qcom/mdm9650-pcie-ep-ttp.dts index 2120ab8599890..be1876886d6d7 100644 --- a/arch/arm/boot/dts/qcom/mdm9650-pcie-ep-ttp.dts +++ b/arch/arm/boot/dts/qcom/mdm9650-pcie-ep-ttp.dts @@ -156,6 +156,7 @@ &pcie_ep { status = "ok"; + mdm2apstatus-gpio = <&tlmm_pinmux 85 0>; }; &pcie0 { @@ -170,3 +171,15 @@ status = "ok"; }; +&pcie0_mdm2apstatus_default { + mux { + pins = "gpio85"; + function = "gpio"; + }; + + config { + pins = "gpio85"; + drive-strength = <2>; + bias-pull-down; + }; +}; From 7811a9a1b3ab55f52284ca309b307233b011e97e Mon Sep 17 00:00:00 2001 From: Balachandra C S Date: Thu, 26 Apr 2018 18:10:44 +0530 Subject: [PATCH 410/508] drivers: net: can: ignore the data if command byte is 0xFF Ignore the data from spi if data read happens to be 0xFF. Change-Id: Ib1f28b70ee11e99f73a80166df56132371076f86 Signed-off-by: Balachandra C S --- drivers/net/can/spi/qti-can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/spi/qti-can.c b/drivers/net/can/spi/qti-can.c index 69a3159d34b1c..253e341dbb585 100644 --- a/drivers/net/can/spi/qti-can.c +++ b/drivers/net/can/spi/qti-can.c @@ -445,8 +445,8 @@ static int qti_can_process_rx(struct qti_can *priv_data, char *rx_buf) } else { data = rx_buf + length_processed; resp = (struct spi_miso *)data; - if (resp->cmd == 0) { - /* special case. ignore cmd==0 */ + if (resp->cmd == 0x00 || resp->cmd == 0xFF) { + /* special case. ignore cmd==0x00, 0xFF */ length_processed += 1; continue; } From 72fdce428456ed09cd78b60f01856793391affab Mon Sep 17 00:00:00 2001 From: gaolez Date: Tue, 6 Feb 2018 15:05:44 +0800 Subject: [PATCH 411/508] cnss_sdio: fix wlan card sdio rate can't reach 200M after warm start The wlan card detected as high speed SDIO card after device warm start while it detected as ultra high speed SDIO card after device cold start. Wlan card enable pin not be pulled in the sequence high/low/high will make wlan card detected as high speed SDIO card but not ultra high speed after warm start. Change the wlan vdd regulator check logic for cnss_put_hw_resources and cnss_get_hw_resources, so the function will not return directly if there is no vdd-wlan on board. Change-Id: I741ef1b6e8d9b950b6ebc9b2e64d16ab6d3912f0 CRs-Fixed: 2184824 Signed-off-by: Gaole Zhang --- drivers/net/wireless/cnss/cnss_sdio.c | 28 +++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/cnss/cnss_sdio.c b/drivers/net/wireless/cnss/cnss_sdio.c index 3177140eadfeb..a2ca99f77aa3f 100644 --- a/drivers/net/wireless/cnss/cnss_sdio.c +++ b/drivers/net/wireless/cnss/cnss_sdio.c @@ -278,11 +278,6 @@ static int cnss_put_hw_resources(struct device *dev) return ret; } - if (!cnss_pdata->regulator.wlan_vreg) { - pr_debug("wlan_vreg regulator is invalid\n"); - return 0; - } - ret = mmc_power_save_host(host); if (ret) { pr_err("Failed to Power Save Host err:%d\n", @@ -290,7 +285,11 @@ static int cnss_put_hw_resources(struct device *dev) return ret; } - regulator_disable(cnss_pdata->regulator.wlan_vreg); + if (cnss_pdata->regulator.wlan_vreg) + regulator_disable(cnss_pdata->regulator.wlan_vreg); + else + pr_debug("wlan_vreg regulator is invalid\n"); + info->cnss_hw_state = CNSS_HW_SLEEP; return ret; @@ -324,22 +323,23 @@ static int cnss_get_hw_resources(struct device *dev) return ret; } - if (!cnss_pdata->regulator.wlan_vreg) { + if (cnss_pdata->regulator.wlan_vreg) { + ret = regulator_enable(cnss_pdata->regulator.wlan_vreg); + if (ret) { + pr_err("Failed to enable wlan vreg\n"); + return ret; + } + } else { pr_debug("wlan_vreg regulator is invalid\n"); - return 0; } - ret = regulator_enable(cnss_pdata->regulator.wlan_vreg); - if (ret) { - pr_err("Failed to enable wlan vreg\n"); - return ret; - } ret = mmc_power_restore_host(host); if (ret) { pr_err("Failed to restore host power ret:%d\n", ret); - regulator_disable(cnss_pdata->regulator.wlan_vreg); + if (cnss_pdata->regulator.wlan_vreg) + regulator_disable(cnss_pdata->regulator.wlan_vreg); return ret; } From 5acbfff67bb172a6bb768a96e1e359964187200d Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Fri, 11 May 2018 10:21:22 +0530 Subject: [PATCH 412/508] lpm-levels: Remove kfree for memory allocated with devm_kzalloc Do not use kfree for memory allocated using devm_kzalloc during failures as device memory will get freed in device release. Change-Id: I6c4d3f8ed55ab02e3e70a1fe65452a8817c8b64e Signed-off-by: Maulik Shah --- drivers/cpuidle/lpm-levels-of.c | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/drivers/cpuidle/lpm-levels-of.c b/drivers/cpuidle/lpm-levels-of.c index 41fcee399eeda..df60c3ea077f4 100644 --- a/drivers/cpuidle/lpm-levels-of.c +++ b/drivers/cpuidle/lpm-levels-of.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -423,10 +423,6 @@ static int parse_legacy_cluster_params(struct device_node *node, return 0; failed: pr_err("%s(): Failed reading %s\n", __func__, key); - kfree(c->name); - kfree(c->lpm_dev); - c->name = NULL; - c->lpm_dev = NULL; return ret; } @@ -612,8 +608,6 @@ static int parse_cluster_level(struct device_node *node, return 0; failed: pr_err("Failed %s() key = %s ret = %d\n", __func__, key, ret); - kfree(level->mode); - level->mode = NULL; return ret; } @@ -808,19 +802,12 @@ static int parse_cpu_levels(struct device_node *node, struct lpm_cluster *c) return 0; failed: - for (i = 0; i < c->cpu->nlevels; i++) { - kfree(c->cpu->levels[i].name); - c->cpu->levels[i].name = NULL; - } - kfree(c->cpu); - c->cpu = NULL; pr_err("%s(): Failed with error code:%d\n", __func__, ret); return ret; } void free_cluster_node(struct lpm_cluster *cluster) { - int i; struct lpm_cluster *cl, *m; list_for_each_entry_safe(cl, m, &cluster->child, list) { @@ -828,22 +815,6 @@ void free_cluster_node(struct lpm_cluster *cluster) free_cluster_node(cl); }; - if (cluster->cpu) { - for (i = 0; i < cluster->cpu->nlevels; i++) { - kfree(cluster->cpu->levels[i].name); - cluster->cpu->levels[i].name = NULL; - } - } - for (i = 0; i < cluster->nlevels; i++) { - kfree(cluster->levels[i].mode); - cluster->levels[i].mode = NULL; - } - kfree(cluster->cpu); - kfree(cluster->name); - kfree(cluster->lpm_dev); - cluster->cpu = NULL; - cluster->name = NULL; - cluster->lpm_dev = NULL; cluster->ndevices = 0; } @@ -957,9 +928,7 @@ struct lpm_cluster *parse_cluster(struct device_node *node, list_del(&c->list); free_cluster_node(c); failed_parse_params: - c->parent = NULL; pr_err("Failed parse params\n"); - kfree(c); return NULL; } struct lpm_cluster *lpm_of_parse_cluster(struct platform_device *pdev) From ef0b54d68c3560d5711320322a23fe412f5a3426 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Thu, 5 Apr 2018 16:44:40 +0530 Subject: [PATCH 413/508] ARM: dts: msm: Use bw_vbif as GPU governor on MSM8909 Use bw_vbif as governor on MSM8909 instead of bw_hwmon for GPU and also remove unused bandwidth voting levels for bw_tbl. Change-Id: Ic6df6e8ef867965281ef083f7d81ad62bdb3e7c0 Signed-off-by: Deepak Kumar --- arch/arm/boot/dts/qcom/msm8909-gpu.dtsi | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi index ba87d663a8d43..51529a2ee8b2e 100644 --- a/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/msm8909-gpu.dtsi @@ -19,26 +19,15 @@ /* To use BIMC based bus governor */ gpubw: qcom,gpubw { compatible = "qcom,devbw"; - governor = "bw_hwmon"; + governor = "bw_vbif"; qcom,src-dst-ports = <26 512>; qcom,bw-tbl = < 0 >, /* 9.6 MHz */ - < 381 >, /* 50.0 MHz */ - < 762 >, /* 100.0 MHz */ < 1525 >, /* 200.0 MHz */ < 3051 >, /* 400.0 MHz */ < 4066 >; /* 533.0 MHz */ }; - qcom,gpu-bwmon@410000 { - compatible = "qcom,bimc-bwmon2"; - reg = <0x00410000 0x300>, <0x00401000 0x200>; - reg-names = "base", "global_base"; - interrupts = <0 183 4>; - qcom,mport = <2>; - qcom,target-dev = <&gpubw>; - }; - msm_gpu: qcom,kgsl-3d0@01c00000 { label = "kgsl-3d0"; compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d"; @@ -105,24 +94,32 @@ reg = <0>; qcom,gpu-freq = <456000000>; qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <3>; }; qcom,gpu-pwrlevel@1 { reg = <1>; qcom,gpu-freq = <307200000>; qcom,bus-freq = <2>; + qcom,bus-min = <2>; + qcom,bus-max = <3>; }; qcom,gpu-pwrlevel@2 { reg = <2>; qcom,gpu-freq = <200000000>; - qcom,bus-freq = <1>; + qcom,bus-freq = <2>; + qcom,bus-min = <1>; + qcom,bus-max = <2>; }; qcom,gpu-pwrlevel@3 { reg = <3>; qcom,gpu-freq = <19200000>; qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; }; }; From f9778125f15605759d567336f008d1efad7f55d0 Mon Sep 17 00:00:00 2001 From: John Zhao Date: Tue, 30 Jan 2018 22:41:57 +0800 Subject: [PATCH 414/508] lpm-stats: cleanup lpm stats processing sanity wrapping during list_for_each_entry_reverse iteration, cleanup_stats recursively on current operated stats node could result it will be freed at the end of that cleanup_stats progress. De-referencing it again should not happen. CRs-Fixed: 2182622 Change-Id: Icf837b0aa796fed5fe1721f9fe66fd0dd36ccfd7 Signed-off-by: John Zhao --- drivers/power/qcom/lpm-stats.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/power/qcom/lpm-stats.c b/drivers/power/qcom/lpm-stats.c index 7f1967d432b74..812815da7306f 100644 --- a/drivers/power/qcom/lpm-stats.c +++ b/drivers/power/qcom/lpm-stats.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -685,8 +685,10 @@ static void cleanup_stats(struct lpm_stats *stats) centry = &stats->child; list_for_each_entry_reverse(pos, centry, sibling) { - if (!list_empty(&pos->child)) + if (!list_empty(&pos->child)) { cleanup_stats(pos); + continue; + } list_del_init(&pos->child); From 345db60558ed43bc664ce3387ce262b9e24d9095 Mon Sep 17 00:00:00 2001 From: Veerabhadrarao Badiganti Date: Mon, 7 Aug 2017 14:58:15 +0530 Subject: [PATCH 415/508] mmc: core: Ignore bus resume flags when card removal event is detected Ignore bus resume flags in the resume path if there is an outstanding card removal event. With deferred resume feature enabled, we don't check for card presence (i.e., mmc_detect_change) in the resume path. This is to improve the resume latency. If at all card is removed during suspend state, in some cases we may not detect the card removal immediately but only when a request was issued to it. In some scenarios, card removal in suspend state leading to card suspend to fail (since the card is removed) and which is causing system suspend to fail. And we don't try to resume card because of deferred resume it leading to system suspend to fail continuously. To fix this scenario, ignore the bus resume flag in the resume path only if there an outstanding card removal event. By doing so, we are ensuring that the driver would check for card presence (mmc_detect_change) in the resume path (mmc_pm_notify) and it will mark the card as removed if it finds the card is no more present. Change-Id: I7d075c2a5c2aaba1ff92f4072fdd2541bb98aa95 Signed-off-by: Veerabhadrarao Badiganti --- drivers/mmc/core/core.c | 12 +++++++++++- drivers/mmc/core/sd.c | 5 ++++- include/linux/mmc/host.h | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 36d7b3032ca1d..bac22ef4e0835 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -3002,6 +3002,13 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay, pm_wakeup_event(mmc_dev(host), 5000); host->detect_change = 1; + /* + * Change in cd_gpio state, so make sure detection part is + * not overided because of manual resume. + */ + if (cd_irq && mmc_bus_manual_resume(host)) + host->ignore_bus_resume_flags = true; + mmc_schedule_delayed_work(&host->detect, delay); } @@ -3923,6 +3930,8 @@ void mmc_rescan(struct work_struct *work) host->bus_ops->detect(host); host->detect_change = 0; + if (host->ignore_bus_resume_flags) + host->ignore_bus_resume_flags = false; /* * Let mmc_bus_put() free the bus/bus_ops if we've found that @@ -4176,7 +4185,8 @@ int mmc_pm_notify(struct notifier_block *notify_block, spin_lock_irqsave(&host->lock, flags); host->rescan_disable = 0; - if (mmc_bus_manual_resume(host)) { + if (mmc_bus_manual_resume(host) && + !host->ignore_bus_resume_flags) { spin_unlock_irqrestore(&host->lock, flags); break; } diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index a29c4b2c8e97d..b58bf6d1f5052 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1234,7 +1234,10 @@ static int mmc_sd_suspend(struct mmc_host *host) if (!err) { pm_runtime_disable(&host->card->dev); pm_runtime_set_suspended(&host->card->dev); - } + /* if suspend fails, force mmc_detect_change during resume */ + } else if (mmc_bus_manual_resume(host)) + host->ignore_bus_resume_flags = true; + MMC_TRACE(host, "%s: Exit err: %d\n", __func__, err); return err; diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 3c354aeb69bcb..7de48a57f68f9 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -551,6 +551,7 @@ struct mmc_host { unsigned int bus_resume_flags; #define MMC_BUSRESUME_MANUAL_RESUME (1 << 0) #define MMC_BUSRESUME_NEEDS_RESUME (1 << 1) + bool ignore_bus_resume_flags; unsigned int sdio_irqs; struct task_struct *sdio_irq_thread; From 0c3f722d0c3770cabe23f7fabfe720f503c4d6b4 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Tue, 10 Apr 2018 15:33:48 +0530 Subject: [PATCH 416/508] msm: ipa: Fix to slab out of bounds issue Add changes to verify passed value with in the allocated max array size range or not before accessing structure. Change-Id: If70493e937f6f0bc29bbfe08bf43738bdb4e9cf4 Acked-by: Ashok Vuyyuru Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c | 58 ++++++++++++-- drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c | 75 ++++++++++++++++--- 2 files changed, 114 insertions(+), 19 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c index 16bff82a116dd..0261e857298a0 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c @@ -432,6 +432,8 @@ static ssize_t ipa_read_hdr(struct file *file, char __user *ubuf, size_t count, list_for_each_entry(entry, &ipa_ctx->hdr_tbl.head_hdr_entry_list, link) { + if (entry->cookie != IPA_HDR_COOKIE) + continue; nbytes = scnprintf( dbg_buff, IPA_MAX_MSG_LEN - 1, @@ -597,6 +599,14 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib) if (attrib->protocol_eq_present) pr_err("protocol:%d ", attrib->protocol_eq); + if (attrib->num_ihl_offset_range_16 > + IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS) { + IPAERR_RL("num_ihl_offset_range_16 Max %d passed value %d\n", + IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS, + attrib->num_ihl_offset_range_16); + return -EPERM; + } + for (i = 0; i < attrib->num_ihl_offset_range_16; i++) { pr_err( "(ihl_ofst_range16: ofst:%u lo:%u hi:%u) ", @@ -605,6 +615,12 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib) attrib->ihl_offset_range_16[i].range_high); } + if (attrib->num_offset_meq_32 > IPA_IPFLTR_NUM_MEQ_32_EQNS) { + IPAERR_RL("num_offset_meq_32 Max %d passed value %d\n", + IPA_IPFLTR_NUM_MEQ_32_EQNS, attrib->num_offset_meq_32); + return -EPERM; + } + for (i = 0; i < attrib->num_offset_meq_32; i++) { pr_err( "(ofst_meq32: ofst:%u mask:0x%x val:0x%x) ", @@ -626,6 +642,12 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib) attrib->ihl_offset_eq_16.value); } + if (attrib->num_ihl_offset_meq_32 > IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS) { + IPAERR_RL("num_ihl_offset_meq_32 Max %d passed value %d\n", + IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS, attrib->num_ihl_offset_meq_32); + return -EPERM; + } + for (i = 0; i < attrib->num_ihl_offset_meq_32; i++) { pr_err( "(ihl_ofst_meq32: ofts:%d mask:0x%x val:0x%x) ", @@ -634,6 +656,12 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib) attrib->ihl_offset_meq_32[i].value); } + if (attrib->num_offset_meq_128 > IPA_IPFLTR_NUM_MEQ_128_EQNS) { + IPAERR_RL("num_offset_meq_128 Max %d passed value %d\n", + IPA_IPFLTR_NUM_MEQ_128_EQNS, attrib->num_offset_meq_128); + return -EPERM; + } + for (i = 0; i < attrib->num_offset_meq_128; i++) { for (j = 0; j < 16; j++) { addr[j] = attrib->offset_meq_128[i].value[j]; @@ -803,11 +831,14 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count, u32 rt_tbl_idx; u32 bitmap; bool eq; + int res = 0; tbl = &ipa_ctx->glob_flt_tbl[ip]; mutex_lock(&ipa_ctx->lock); i = 0; list_for_each_entry(entry, &tbl->head_flt_rule_list, link) { + if (entry->cookie != IPA_FLT_COOKIE) + continue; if (entry->rule.eq_attrib_type) { rt_tbl_idx = entry->rule.rt_tbl_idx; bitmap = entry->rule.eq_attrib.rule_eq_bitmap; @@ -826,10 +857,14 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count, i, entry->rule.action, rt_tbl_idx); pr_err("attrib_mask:%08x retain_hdr:%d eq:%d ", bitmap, entry->rule.retain_hdr, eq); - if (eq) - ipa_attrib_dump_eq( + if (eq) { + res = ipa_attrib_dump_eq( &entry->rule.eq_attrib); - else + if (res) { + IPAERR_RL("failed read attrib eq\n"); + goto bail; + } + } else ipa_attrib_dump( &entry->rule.attrib, ip); i++; @@ -839,6 +874,8 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count, tbl = &ipa_ctx->flt_tbl[j][ip]; i = 0; list_for_each_entry(entry, &tbl->head_flt_rule_list, link) { + if (entry->cookie != IPA_FLT_COOKIE) + continue; if (entry->rule.eq_attrib_type) { rt_tbl_idx = entry->rule.rt_tbl_idx; bitmap = entry->rule.eq_attrib.rule_eq_bitmap; @@ -858,18 +895,23 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count, pr_err("attrib_mask:%08x retain_hdr:%d ", bitmap, entry->rule.retain_hdr); pr_err("eq:%d ", eq); - if (eq) - ipa_attrib_dump_eq( - &entry->rule.eq_attrib); - else + if (eq) { + res = ipa_attrib_dump_eq( + &entry->rule.eq_attrib); + if (res) { + IPAERR_RL("failed read attrib eq\n"); + goto bail; + } + } else ipa_attrib_dump( &entry->rule.attrib, ip); i++; } } +bail: mutex_unlock(&ipa_ctx->lock); - return 0; + return res; } static ssize_t ipa_read_stats(struct file *file, char __user *ubuf, diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index 33b0e2187bc28..be6b1a49ddcf9 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -531,6 +531,14 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib) if (attrib->protocol_eq_present) pr_err("protocol:%d ", attrib->protocol_eq); + if (attrib->num_ihl_offset_range_16 > + IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS) { + IPAERR_RL("num_ihl_offset_range_16 Max %d passed value %d\n", + IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS, + attrib->num_ihl_offset_range_16); + return -EPERM; + } + for (i = 0; i < attrib->num_ihl_offset_range_16; i++) { pr_err( "(ihl_ofst_range16: ofst:%u lo:%u hi:%u) ", @@ -539,6 +547,12 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib) attrib->ihl_offset_range_16[i].range_high); } + if (attrib->num_offset_meq_32 > IPA_IPFLTR_NUM_MEQ_32_EQNS) { + IPAERR_RL("num_offset_meq_32 Max %d passed value %d\n", + IPA_IPFLTR_NUM_MEQ_32_EQNS, attrib->num_offset_meq_32); + return -EPERM; + } + for (i = 0; i < attrib->num_offset_meq_32; i++) { pr_err( "(ofst_meq32: ofst:%u mask:0x%x val:0x%x) ", @@ -560,6 +574,13 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib) attrib->ihl_offset_eq_16.value); } + if (attrib->num_ihl_offset_meq_32 > IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS) { + IPAERR_RL("num_ihl_offset_meq_32 Max %d passed value %d\n", + IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS, + attrib->num_ihl_offset_meq_32); + return -EPERM; + } + for (i = 0; i < attrib->num_ihl_offset_meq_32; i++) { pr_err( "(ihl_ofst_meq32: ofts:%d mask:0x%x val:0x%x) ", @@ -568,6 +589,12 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib) attrib->ihl_offset_meq_32[i].value); } + if (attrib->num_offset_meq_128 > IPA_IPFLTR_NUM_MEQ_128_EQNS) { + IPAERR_RL("num_offset_meq_128 Max %d passed value %d\n", + IPA_IPFLTR_NUM_MEQ_128_EQNS, attrib->num_offset_meq_128); + return -EPERM; + } + for (i = 0; i < attrib->num_offset_meq_128; i++) { for (j = 0; j < 16; j++) { addr[j] = attrib->offset_meq_128[i].value[j]; @@ -704,6 +731,7 @@ static ssize_t ipa3_read_rt_hw(struct file *file, char __user *ubuf, struct ipa3_debugfs_rt_entry *entry; enum ipa_ip_type ip = (enum ipa_ip_type)file->private_data; int num_tbls; + int res = 0; if (ip == IPA_IP_v4) num_tbls = IPA_MEM_PART(v4_rt_num_index); @@ -736,7 +764,11 @@ static ssize_t ipa3_read_rt_hw(struct file *file, char __user *ubuf, pr_err("rule_id:%u prio:%u retain_hdr:%u ", entry[i].rule_id, entry[i].prio, entry[i].retain_hdr); - ipa3_attrib_dump_eq(&entry[i].eq_attrib); + res = ipa3_attrib_dump_eq(&entry[i].eq_attrib); + if (res) { + IPAERR_RL("failed read attrib eq\n"); + goto bail; + } } pr_err("== HASHABLE TABLE tbl:%d ==\n", j); @@ -758,14 +790,19 @@ static ssize_t ipa3_read_rt_hw(struct file *file, char __user *ubuf, pr_err("rule_id:%u prio:%u retain_hdr:%u ", entry[i].rule_id, entry[i].prio, entry[i].retain_hdr); - ipa3_attrib_dump_eq(&entry[i].eq_attrib); + res = ipa3_attrib_dump_eq(&entry[i].eq_attrib); + if (res) { + IPAERR_RL("failed read attrib eq\n"); + goto bail; + } } } +bail: mutex_unlock(&ipa3_ctx->lock); kfree(entry); IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); - return 0; + return res; } static ssize_t ipa3_read_proc_ctx(struct file *file, char __user *ubuf, @@ -830,6 +867,7 @@ static ssize_t ipa3_read_flt(struct file *file, char __user *ubuf, size_t count, u32 rt_tbl_idx; u32 bitmap; bool eq; + int res = 0; mutex_lock(&ipa3_ctx->lock); @@ -860,18 +898,23 @@ static ssize_t ipa3_read_flt(struct file *file, char __user *ubuf, size_t count, pr_err("hashable:%u rule_id:%u max_prio:%u prio:%u ", entry->rule.hashable, entry->rule_id, entry->rule.max_prio, entry->prio); - if (eq) - ipa3_attrib_dump_eq( - &entry->rule.eq_attrib); - else + if (eq) { + res = ipa3_attrib_dump_eq( + &entry->rule.eq_attrib); + if (res) { + IPAERR_RL("failed read attrib eq\n"); + goto bail; + } + } else ipa3_attrib_dump( &entry->rule.attrib, ip); i++; } } +bail: mutex_unlock(&ipa3_ctx->lock); - return 0; + return res; } static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf, @@ -884,6 +927,7 @@ static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf, enum ipa_ip_type ip = (enum ipa_ip_type)file->private_data; u32 rt_tbl_idx; u32 bitmap; + int res = 0; entry = kzalloc(sizeof(*entry) * IPA_DBG_MAX_RULE_IN_TBL, GFP_KERNEL); if (!entry) @@ -906,7 +950,11 @@ static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf, bitmap, entry[i].rule.retain_hdr); pr_err("rule_id:%u prio:%u ", entry[i].rule_id, entry[i].prio); - ipa3_attrib_dump_eq(&entry[i].rule.eq_attrib); + res = ipa3_attrib_dump_eq(&entry[i].rule.eq_attrib); + if (res) { + IPAERR_RL("failed read attrib eq\n"); + goto bail; + } } pr_err("== HASHABLE TABLE ep:%d ==\n", j); @@ -922,14 +970,19 @@ static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf, pr_err("rule_id:%u max_prio:%u prio:%u ", entry[i].rule_id, entry[i].rule.max_prio, entry[i].prio); - ipa3_attrib_dump_eq(&entry[i].rule.eq_attrib); + res = ipa3_attrib_dump_eq(&entry[i].rule.eq_attrib); + if (res) { + IPAERR_RL("failed read attrib eq\n"); + goto bail; + } } } +bail: mutex_unlock(&ipa3_ctx->lock); kfree(entry); IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); - return 0; + return res; } static ssize_t ipa3_read_stats(struct file *file, char __user *ubuf, From ad56cac3a06e17b8a3f2d4f063ac2978adaf59b6 Mon Sep 17 00:00:00 2001 From: Veerabhadrarao Badiganti Date: Mon, 7 Aug 2017 14:58:15 +0530 Subject: [PATCH 417/508] mmc: core: Ignore bus resume flags when card removal event is detected Ignore bus resume flags in the resume path if there is an outstanding card removal event. With deferred resume feature enabled, we don't check for card presence (i.e., mmc_detect_change) in the resume path. This is to improve the resume latency. If at all card is removed during suspend state, in some cases we may not detect the card removal immediately but only when a request was issued to it. In some scenarios, card removal in suspend state leading to card suspend to fail (since the card is removed) and which is causing system suspend to fail. And we don't try to resume card because of deferred resume it leading to system suspend to fail continuously. To fix this scenario, ignore the bus resume flag in the resume path only if there an outstanding card removal event. By doing so, we are ensuring that the driver would check for card presence (mmc_detect_change) in the resume path (mmc_pm_notify) and it will mark the card as removed if it finds the card is no more present. Change-Id: I7d075c2a5c2aaba1ff92f4072fdd2541bb98aa95 Signed-off-by: Veerabhadrarao Badiganti --- drivers/mmc/core/core.c | 12 +++++++++++- drivers/mmc/core/sd.c | 5 ++++- include/linux/mmc/host.h | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 36d7b3032ca1d..bac22ef4e0835 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -3002,6 +3002,13 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay, pm_wakeup_event(mmc_dev(host), 5000); host->detect_change = 1; + /* + * Change in cd_gpio state, so make sure detection part is + * not overided because of manual resume. + */ + if (cd_irq && mmc_bus_manual_resume(host)) + host->ignore_bus_resume_flags = true; + mmc_schedule_delayed_work(&host->detect, delay); } @@ -3923,6 +3930,8 @@ void mmc_rescan(struct work_struct *work) host->bus_ops->detect(host); host->detect_change = 0; + if (host->ignore_bus_resume_flags) + host->ignore_bus_resume_flags = false; /* * Let mmc_bus_put() free the bus/bus_ops if we've found that @@ -4176,7 +4185,8 @@ int mmc_pm_notify(struct notifier_block *notify_block, spin_lock_irqsave(&host->lock, flags); host->rescan_disable = 0; - if (mmc_bus_manual_resume(host)) { + if (mmc_bus_manual_resume(host) && + !host->ignore_bus_resume_flags) { spin_unlock_irqrestore(&host->lock, flags); break; } diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index a29c4b2c8e97d..b58bf6d1f5052 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1234,7 +1234,10 @@ static int mmc_sd_suspend(struct mmc_host *host) if (!err) { pm_runtime_disable(&host->card->dev); pm_runtime_set_suspended(&host->card->dev); - } + /* if suspend fails, force mmc_detect_change during resume */ + } else if (mmc_bus_manual_resume(host)) + host->ignore_bus_resume_flags = true; + MMC_TRACE(host, "%s: Exit err: %d\n", __func__, err); return err; diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 3c354aeb69bcb..7de48a57f68f9 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -551,6 +551,7 @@ struct mmc_host { unsigned int bus_resume_flags; #define MMC_BUSRESUME_MANUAL_RESUME (1 << 0) #define MMC_BUSRESUME_NEEDS_RESUME (1 << 1) + bool ignore_bus_resume_flags; unsigned int sdio_irqs; struct task_struct *sdio_irq_thread; From 334c0a3ef6f5833928f09f4e13043c05fbf11dab Mon Sep 17 00:00:00 2001 From: Arun Kumar Neelakantam Date: Thu, 26 Apr 2018 09:27:53 +0530 Subject: [PATCH 418/508] net: ipc_router: Remove wakeup-source for Sensor ports In high speed sensor data stream case system is not entering into suspend state due to edge and port specific wake-up sources. Add flag to check and avoid the wakeup sources for all sensor ports. CRs-Fixed: 2196601 Change-Id: Ibf642619b969925dc96e8a57e11f7e349b85c024 Signed-off-by: Arun Kumar Neelakantam --- include/linux/ipc_router_xprt.h | 4 ++- net/ipc_router/ipc_router_core.c | 60 +++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/include/linux/ipc_router_xprt.h b/include/linux/ipc_router_xprt.h index 276c79ff15918..5baddb80c66ec 100644 --- a/include/linux/ipc_router_xprt.h +++ b/include/linux/ipc_router_xprt.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2015, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -100,6 +100,7 @@ struct rr_opt_hdr { * @pkt_fragment_q: Queue of SKBs containing payload. * @length: Length of data in the chain of SKBs * @ref: Reference count for the packet. + * @ws_need: Flag to check wakeup soruce need */ struct rr_packet { struct list_head list; @@ -108,6 +109,7 @@ struct rr_packet { struct sk_buff_head *pkt_fragment_q; uint32_t length; struct kref ref; + bool ws_need; }; /** diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c index 8d74fb7abbaef..271eafc960301 100644 --- a/net/ipc_router/ipc_router_core.c +++ b/net/ipc_router/ipc_router_core.c @@ -216,6 +216,25 @@ enum { UP, }; +/** + * is_sensor_port() - Check if the remote port is sensor service or not + * @rport: Pointer to the remote port. + * + * Return: true if the remote port is sensor service else false. + */ +static int is_sensor_port(struct msm_ipc_router_remote_port *rport) +{ + u32 svcid = 0; + + if (rport && rport->server) { + svcid = rport->server->name.service; + if (svcid == 400 || (svcid >= 256 && svcid <= 320)) + return true; + } + + return false; +} + static void init_routing_table(void) { int i; @@ -1165,7 +1184,8 @@ static int post_pkt_to_port(struct msm_ipc_port *port_ptr, } mutex_lock(&port_ptr->port_rx_q_lock_lhc3); - __pm_stay_awake(port_ptr->port_rx_ws); + if (pkt->ws_need) + __pm_stay_awake(port_ptr->port_rx_ws); list_add_tail(&temp_pkt->list, &port_ptr->port_rx_q); wake_up(&port_ptr->port_rx_wait_q); notify = port_ptr->notify; @@ -2718,7 +2738,6 @@ static void do_read_data(struct work_struct *work) struct rr_packet *pkt = NULL; struct msm_ipc_port *port_ptr; struct msm_ipc_router_remote_port *rport_ptr; - int ret; struct msm_ipc_router_xprt_info *xprt_info = container_of(work, @@ -2726,16 +2745,7 @@ static void do_read_data(struct work_struct *work) read_data); while ((pkt = rr_read(xprt_info)) != NULL) { - if (pkt->length < calc_rx_header_size(xprt_info) || - pkt->length > MAX_IPC_PKT_SIZE) { - IPC_RTR_ERR("%s: Invalid pkt length %d\n", - __func__, pkt->length); - goto read_next_pkt1; - } - ret = extract_header(pkt); - if (ret < 0) - goto read_next_pkt1; hdr = &(pkt->hdr); if ((hdr->dst_node_id != IPC_ROUTER_NID_LOCAL) && @@ -4177,6 +4187,7 @@ void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt, { struct msm_ipc_router_xprt_info *xprt_info = xprt->priv; struct msm_ipc_router_xprt_work *xprt_work; + struct msm_ipc_router_remote_port *rport_ptr = NULL; struct rr_packet *pkt; int ret; @@ -4229,9 +4240,34 @@ void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt, if (!pkt) return; + if (pkt->length < calc_rx_header_size(xprt_info) || + pkt->length > MAX_IPC_PKT_SIZE) { + IPC_RTR_ERR("%s: Invalid pkt length %d\n", + __func__, pkt->length); + release_pkt(pkt); + return; + } + + ret = extract_header(pkt); + if (ret < 0) { + release_pkt(pkt); + return; + } + + pkt->ws_need = true; + + if (pkt->hdr.type == IPC_ROUTER_CTRL_CMD_DATA) + rport_ptr = ipc_router_get_rport_ref(pkt->hdr.src_node_id, + pkt->hdr.src_port_id); + mutex_lock(&xprt_info->rx_lock_lhb2); list_add_tail(&pkt->list, &xprt_info->pkt_list); - __pm_stay_awake(&xprt_info->ws); + /* check every pkt is from SENSOR services or not*/ + if (is_sensor_port(rport_ptr)) + pkt->ws_need = false; + else + __pm_stay_awake(&xprt_info->ws); + mutex_unlock(&xprt_info->rx_lock_lhb2); queue_work(xprt_info->workqueue, &xprt_info->read_data); } From b2a514ed2697aa72fa2d9024ed7cc347b867ab6c Mon Sep 17 00:00:00 2001 From: Srikanth Uyyala Date: Fri, 4 May 2018 14:23:10 +0530 Subject: [PATCH 419/508] msm: camera: Dont call recovery for inactive streams During Stream-off is in progress and all active streams are zero and that instant if we cause pingpong mismatch, recovery is not expected. Change-Id: Ibdaeb4308f33772fcd330712b0a866aedb7a9486 Signed-off-by: Srikanth Uyyala --- drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 14b1d79ed53d2..68394aa88a1ff 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -1640,7 +1640,9 @@ void msm_isp_halt_send_error(struct vfe_device *vfe_dev, uint32_t event) NO_OVERFLOW) /* Recovery is already in Progress */ return; - + /* if there are no active streams - do not start recovery */ + if (!vfe_dev->axi_data.num_active_stream) + return; if (ISP_EVENT_PING_PONG_MISMATCH == event && vfe_dev->axi_data.recovery_count < MAX_RECOVERY_THRESHOLD) { vfe_dev->hw_info->vfe_ops.irq_ops. From 2bcf650981bead00a0f8dc2fc6a8ea12514d99e2 Mon Sep 17 00:00:00 2001 From: Srikanth Uyyala Date: Tue, 17 Apr 2018 13:12:52 +0530 Subject: [PATCH 420/508] msm: camera: isp : Fix race condition in close sequence Serializing reset_hw and reset_irq, to avoid race condition. Change-Id: I8f21cb816748129bde7f0f1455b203b42603d244 Signed-off-by: Srikanth Uyyala --- .../media/platform/msm/camera_v2/isp/msm_isp.c | 4 +++- .../media/platform/msm/camera_v2/isp/msm_isp.h | 4 +++- .../platform/msm/camera_v2/isp/msm_isp40.c | 18 +++++++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c index 411226242b27f..8772f324b454a 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -679,6 +679,8 @@ int vfe_hw_probe(struct platform_device *pdev) spin_lock_init(&vfe_dev->shared_data_lock); spin_lock_init(&vfe_dev->reg_update_lock); spin_lock_init(&req_history_lock); + spin_lock_init(&vfe_dev->reset_completion_lock); + spin_lock_init(&vfe_dev->halt_completion_lock); media_entity_init(&vfe_dev->subdev.sd.entity, 0, NULL, 0); vfe_dev->subdev.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV; vfe_dev->subdev.sd.entity.group_id = MSM_CAMERA_SUBDEV_VFE; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index d223401d8688e..f1cf72e53b6d7 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -740,6 +740,8 @@ struct vfe_device { struct mutex core_mutex; spinlock_t shared_data_lock; spinlock_t reg_update_lock; + spinlock_t reset_completion_lock; + spinlock_t halt_completion_lock; spinlock_t tasklet_lock; /* Tasklet info */ diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c index 50ed167874bea..41ba4f55fe569 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c @@ -370,15 +370,24 @@ static void msm_vfe40_clear_status_reg(struct vfe_device *vfe_dev) static void msm_vfe40_process_reset_irq(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1) { - if (irq_status0 & (1 << 31)) + unsigned long flags; + + if (irq_status0 & (1 << 31)) { + spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags); complete(&vfe_dev->reset_complete); + spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags); + } } static void msm_vfe40_process_halt_irq(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1) { + unsigned long flags; + if (irq_status1 & (1 << 8)) { + spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags); complete(&vfe_dev->halt_complete); + spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags); msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x2C0); } } @@ -768,7 +777,11 @@ static long msm_vfe40_reset_hardware(struct vfe_device *vfe_dev, uint32_t first_start, uint32_t blocking_call) { long rc = 0; + unsigned long flags; + + spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags); init_completion(&vfe_dev->reset_complete); + spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags); if (first_start) { msm_camera_io_w_mb(0x1FF, vfe_dev->vfe_base + 0xC); @@ -1732,6 +1745,7 @@ static int msm_vfe40_axi_halt(struct vfe_device *vfe_dev, { int rc = 0; enum msm_vfe_input_src i; + unsigned long flags; /* Keep only halt and restart mask */ msm_vfe40_set_halt_restart_mask(vfe_dev); @@ -1766,7 +1780,9 @@ static int msm_vfe40_axi_halt(struct vfe_device *vfe_dev, } if (blocking) { + spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags); init_completion(&vfe_dev->halt_complete); + spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags); /* Halt AXI Bus Bridge */ msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x2C0); rc = wait_for_completion_interruptible_timeout( From a9ff976bfe513f355855d41d6564f9f87343ddae Mon Sep 17 00:00:00 2001 From: Srikanth Uyyala Date: Fri, 4 May 2018 14:30:53 +0530 Subject: [PATCH 421/508] msm: camera: skip recovery during stream off in dual vfe in dual vfe usecase, skip pingpong mismatch recovery if one of the vfe's active stream count is zero. Change-Id: I1b4dce66ad6665e41c4185d3ac510204d40131da Signed-off-by: Srikanth Uyyala --- .../msm/camera_v2/isp/msm_isp_axi_util.c | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 68394aa88a1ff..ff1cfc435c2e9 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -1635,13 +1635,37 @@ void msm_isp_halt_send_error(struct vfe_device *vfe_dev, uint32_t event) struct msm_isp_event_data error_event; struct msm_vfe_axi_halt_cmd halt_cmd; uint32_t irq_status0, irq_status1; + struct vfe_device *vfe_dev_other = NULL; + uint32_t vfe_id_other = 0; + unsigned long flags; if (atomic_read(&vfe_dev->error_info.overflow_state) != NO_OVERFLOW) /* Recovery is already in Progress */ return; /* if there are no active streams - do not start recovery */ - if (!vfe_dev->axi_data.num_active_stream) + if (vfe_dev->is_split) { + if (vfe_dev->pdev->id == ISP_VFE0) + vfe_id_other = ISP_VFE1; + else + vfe_id_other = ISP_VFE0; + + spin_lock_irqsave( + &vfe_dev->common_data->common_dev_data_lock, flags); + vfe_dev_other = vfe_dev->common_data->dual_vfe_res-> + vfe_dev[vfe_id_other]; + if (!vfe_dev->axi_data.num_active_stream || + !vfe_dev_other->axi_data.num_active_stream) { + spin_unlock_irqrestore( + &vfe_dev->common_data->common_dev_data_lock, + flags); + pr_err("%s:skip the recovery as no active streams\n", + __func__); + return; + } + spin_unlock_irqrestore( + &vfe_dev->common_data->common_dev_data_lock, flags); + } else if (!vfe_dev->axi_data.num_active_stream) return; if (ISP_EVENT_PING_PONG_MISMATCH == event && vfe_dev->axi_data.recovery_count < MAX_RECOVERY_THRESHOLD) { From 5dce44c4a635ba99a453538df46c31d39a85b993 Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Tue, 22 May 2018 16:10:01 +0530 Subject: [PATCH 422/508] wlan: Abort ongoing scan on disable agg indication On receiving disable aggregation indication, exit BMPS request is sent to firmware. If there is an ongoing scan when above indication is received, exit BMPS command is not processed immediately since there is an active command. This results in BT missing interrupts. Fix is to abort ongoing scan and then process exit BMPS command. Change-Id: If8ed7dbc47e36e06ac77fd48ec4a4270cab0cd63 CRs-Fixed: 2248007 --- CORE/SME/src/sme_common/sme_Api.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c index 2f2102066c183..1a73933554272 100644 --- a/CORE/SME/src/sme_common/sme_Api.c +++ b/CORE/SME/src/sme_common/sme_Api.c @@ -2538,6 +2538,30 @@ static VOS_STATUS sme_ecsa_msg_processor(tpAniSirGlobal mac_ctx, return VOS_STATUS_SUCCESS; } +static bool sme_get_sessionid_from_scan_cmd(tpAniSirGlobal mac, + tANI_U32 *session_id) +{ + tListElem *entry = NULL; + tSmeCmd *command = NULL; + bool active_scan = false; + + if (!mac->fScanOffload) { + entry = csrLLPeekHead(&mac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + } else { + entry = csrLLPeekHead(&mac->sme.smeScanCmdActiveList, LL_ACCESS_LOCK); + } + + if (entry) { + command = GET_BASE_ADDR(entry, tSmeCmd, Link); + if (command->command == eSmeCommandScan) { + *session_id = command->sessionId; + active_scan = true; + } + } + + return active_scan; +} + /*-------------------------------------------------------------------------- \brief sme_ProcessMsg() - The main message processor for SME. @@ -2734,11 +2758,18 @@ eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg) { tSirSmeCoexInd *pSmeCoexInd = (tSirSmeCoexInd *)pMsg->bodyptr; vos_msg_t vosMessage = {0}; + tANI_U32 session_id = 0; + bool active_scan; if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_DISABLE_AGGREGATION_IN_2p4) { pMac->btc.agg_disabled = true; smsLog( pMac, LOG1, FL("SIR_COEX_IND_TYPE_DISABLE_AGGREGATION_IN_2p4")); + active_scan = sme_get_sessionid_from_scan_cmd(pMac, + &session_id); + if (active_scan) + sme_AbortMacScan(hHal, session_id, + eCSR_SCAN_ABORT_DEFAULT); sme_RequestFullPower(hHal, NULL, NULL, eSME_REASON_OTHER); pMac->isCoexScoIndSet = 1; pMac->scan.fRestartIdleScan = eANI_BOOLEAN_FALSE; From 0175acee838d0e769cf320f3b2ab7d760c78ad87 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Thu, 3 Nov 2016 17:14:03 -0700 Subject: [PATCH 423/508] ipvs: use IPVS_CMD_ATTR_MAX for family.maxattr family.maxattr is the max index for policy[], the size of ops[] is determined with ARRAY_SIZE(). Reported-by: Andrey Konovalov Tested-by: Andrey Konovalov Cc: Pablo Neira Ayuso Signed-off-by: Cong Wang Signed-off-by: Simon Horman Signed-off-by: Pablo Neira Ayuso Git-commit: 8fbfef7f505bba60fb57078b7621270ee57cd1c4 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Change-Id: I4a8cff16935c6b7edb3f4fa86faddd8258b0ef57 CRs-Fixed: 2236015 Signed-off-by: Jeff Johnson --- net/netfilter/ipvs/ip_vs_ctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 9b1452e8e868f..72ebc3f300e53 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2759,7 +2759,7 @@ static struct genl_family ip_vs_genl_family = { .hdrsize = 0, .name = IPVS_GENL_NAME, .version = IPVS_GENL_VERSION, - .maxattr = IPVS_CMD_MAX, + .maxattr = IPVS_CMD_ATTR_MAX, .netnsok = true, /* Make ipvsadm to work on netns */ }; From b31418ba91a3713f009b24af7096db5ad826a3b7 Mon Sep 17 00:00:00 2001 From: VijayaKumar T M Date: Wed, 23 May 2018 11:52:03 +0530 Subject: [PATCH 424/508] msm: ispif: Adding csid version check Check the csid version check before enabling camera clocks to avoid device crash. CRs-Fixed: 2189721 Change-Id: I1028bd776b6722190d0d981c3b63a9d60386152b Signed-off-by: VijayaKumar T M Signed-off-by: Suman Mukherjee --- .../platform/msm/camera_v2/ispif/msm_ispif_32.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_32.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_32.c index 7c12fb9af6c44..9d6c0a9da2776 100644 --- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_32.c +++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_32.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -43,6 +43,8 @@ #define ISPIF_TIMEOUT_SLEEP_US 1000 #define ISPIF_TIMEOUT_ALL_US 1000000 +#define CSID_VERSION_V37 0x30070000 + #undef CDBG #ifdef CONFIG_MSMB_CAMERA_DEBUG #define CDBG(fmt, args...) pr_debug(fmt, ##args) @@ -123,6 +125,11 @@ static int msm_ispif_reset_hw(struct ispif_device *ispif) ispif->clk_idx = 0; + if (ispif->csid_version != CSID_VERSION_V37) { + pr_err("%s:%d error returning\n", __func__, __LINE__); + return -EINVAL; + } + rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8974_reset_clk_info, reset_clk, ARRAY_SIZE(ispif_8974_reset_clk_info), 1); @@ -1255,8 +1262,12 @@ static int msm_ispif_init(struct ispif_device *ispif, goto error_ahb; } - msm_ispif_reset_hw(ispif); - + rc = msm_ispif_reset_hw(ispif); + if (rc < 0) { + pr_err("%s:%d msm_ispif_reset_hw failed\n", __func__, + __LINE__); + goto error_ahb; + } rc = msm_ispif_reset(ispif); if (rc == 0) { ispif->ispif_state = ISPIF_POWER_UP; From b589e5c9ccd640b93f8f1f0d1fb2d91c8283ec99 Mon Sep 17 00:00:00 2001 From: Tim Jiang Date: Thu, 30 Nov 2017 03:33:38 -0500 Subject: [PATCH 425/508] bluetooth: Add QCA9379 power control support To support QCA9379 chipset by Adding corresponding compatible property in relevant OF match table. CRs-fixed: 2241064 Change-Id: If4bf4fc33c065da3ec86fa4ee66446051580ae90 Signed-off-by: Tim Jiang (cherry picked from commit I9fb7b5afb26db1faa3def0c068bc01a143a76c84) Signed-off-by: Zijun Hu --- .../devicetree/bindings/bluetooth/bluetooth_power.txt | 1 + drivers/bluetooth/bluetooth-power.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt b/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt index 7b89497f46382..49233d46a877d 100644 --- a/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt +++ b/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt @@ -6,6 +6,7 @@ Required properties: - compatible: Should be set to one of the following: qca,ar3002 qca,qca6174 + qca,qca9379 qca,wcn3990 - qca,bt-reset-gpio: GPIO pin to bring BT Controller out of reset diff --git a/drivers/bluetooth/bluetooth-power.c b/drivers/bluetooth/bluetooth-power.c index 3f2d53fa5a900..8485481d0c891 100644 --- a/drivers/bluetooth/bluetooth-power.c +++ b/drivers/bluetooth/bluetooth-power.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2010, 2013-2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2009-2010, 2013-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -36,6 +36,7 @@ static struct of_device_id bt_power_match_table[] = { { .compatible = "qca,ar3002" }, { .compatible = "qca,qca6174" }, + { .compatible = "qca,qca9379" }, { .compatible = "qca,wcn3990" }, {} }; From 3d4064861c139fbb6b7dd1927401a7a96258213f Mon Sep 17 00:00:00 2001 From: Suman Mukherjee Date: Wed, 23 May 2018 09:43:21 +0530 Subject: [PATCH 426/508] ARM: dts: msm: camera: Changes to enable flash on 8909 QRD Add GPIO pin control needed for led flash. Change the torch sequence from 1,0 to 0,1 Change-Id: Ib75af8543402ce4e7c94ce7285dc1360c0f41407 Signed-off-by: Suman Mukherjee --- .../dts/qcom/msm8909-camera-sensor-skue.dtsi | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8909-camera-sensor-skue.dtsi b/arch/arm/boot/dts/qcom/msm8909-camera-sensor-skue.dtsi index 8a67a01cfa63a..9e64171a7173a 100644 --- a/arch/arm/boot/dts/qcom/msm8909-camera-sensor-skue.dtsi +++ b/arch/arm/boot/dts/qcom/msm8909-camera-sensor-skue.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-18 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -11,17 +11,20 @@ * GNU General Public License for more details. */ &soc { - SY7803_default: SY7803_default { - mux { - /* CLK, DATA */ - pins = "gpio31", "gpio32"; - function = "gpio"; - }; - config { - pins = "gpio31", "gpio32"; - bias-disable; /* No PULL */ - drive-strength = <2>; /* 2 MA */ + msm_gpio: pinctrl@1000000 { + SY7803_default: SY7803_default { + mux { + /* CLK, DATA */ + pins = "gpio31", "gpio32"; + function = "gpio"; + }; + + config { + pins = "gpio31", "gpio32"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; }; }; @@ -33,7 +36,7 @@ qcom,flash-en = <&msm_gpio 31 0>; qcom,flash-now = <&msm_gpio 32 0>; qcom,op-seq = "flash_en", "flash_now"; - qcom,torch-seq-val = <1 0>; + qcom,torch-seq-val = <0 1>; qcom,flash-seq-val = <1 1>; linux,name = "flashlight"; linux,default-trigger = "flashlight-trigger"; From 07530dcb8d3356e1f64d3339ad2f4c48c012a3e6 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Tue, 28 Nov 2017 16:58:29 +0530 Subject: [PATCH 427/508] msm: kgsl: Move global memory region to 0x100000000 On a 64bit kernel, a 32bit user application is not restricted to 3GB limit of virtual memory. It is allowed to access complete 4GB range. Move global memory region to 0x100000000 outside of 32bit range on 64bit kernel to increase the virtual memory range for a 32bit application running on a 64bit kernel. This will also move secure memory region to 0xF0000000. Change-Id: I017ac0c052b4d9466f9f1a66af4a83f0636450cb Signed-off-by: Deepak Kumar --- drivers/gpu/msm/adreno.c | 4 ++-- drivers/gpu/msm/adreno_a5xx.c | 4 ++-- drivers/gpu/msm/kgsl_iommu.c | 42 ++++++++++++++++++----------------- drivers/gpu/msm/kgsl_iommu.h | 15 ++++++++----- 4 files changed, 36 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 6355831b34bba..0a44f538f1926 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1368,7 +1368,7 @@ static void _set_secvid(struct kgsl_device *device) adreno_writereg64(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE_HI, - KGSL_IOMMU_SECURE_BASE); + KGSL_IOMMU_SECURE_BASE(&device->mmu)); adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_SIZE, KGSL_IOMMU_SECURE_SIZE); @@ -1790,7 +1790,7 @@ static int adreno_getproperty(struct kgsl_device *device, * anything to mmap(). */ shadowprop.gpuaddr = - (unsigned int) device->memstore.gpuaddr; + (unsigned long)device->memstore.gpuaddr; shadowprop.size = device->memstore.size; /* GSL needs this to be set, even if it appears to be meaningless */ diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index b112b041e8b98..0024892268840 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -2441,8 +2441,8 @@ static int a5xx_rb_start(struct adreno_device *adreno_dev, adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_CNTL, A5XX_CP_RB_CNTL_DEFAULT); - adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_BASE, - rb->buffer_desc.gpuaddr); + adreno_writereg64(adreno_dev, ADRENO_REG_CP_RB_BASE, + ADRENO_REG_CP_RB_BASE_HI, rb->buffer_desc.gpuaddr); ret = a5xx_microcode_load(adreno_dev); if (ret) diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 0e9fa9ffdf12c..2fe1fdc0baa0e 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -38,9 +38,10 @@ #define _IOMMU_PRIV(_mmu) (&((_mmu)->priv.iommu)) -#define ADDR_IN_GLOBAL(_a) \ - (((_a) >= KGSL_IOMMU_GLOBAL_MEM_BASE) && \ - ((_a) < (KGSL_IOMMU_GLOBAL_MEM_BASE + KGSL_IOMMU_GLOBAL_MEM_SIZE))) +#define ADDR_IN_GLOBAL(_mmu, _a) \ + (((_a) >= KGSL_IOMMU_GLOBAL_MEM_BASE(_mmu)) && \ + ((_a) < (KGSL_IOMMU_GLOBAL_MEM_BASE(_mmu) + \ + KGSL_IOMMU_GLOBAL_MEM_SIZE))) static struct kgsl_mmu_pt_ops iommu_pt_ops; static bool need_iommu_sync; @@ -197,7 +198,7 @@ static void kgsl_iommu_add_global(struct kgsl_mmu *mmu, BUG_ON(global_pt_count >= GLOBAL_PT_ENTRIES); BUG_ON((global_pt_alloc + memdesc->size) >= KGSL_IOMMU_GLOBAL_MEM_SIZE); - memdesc->gpuaddr = KGSL_IOMMU_GLOBAL_MEM_BASE + global_pt_alloc; + memdesc->gpuaddr = KGSL_IOMMU_GLOBAL_MEM_BASE(mmu) + global_pt_alloc; memdesc->priv |= KGSL_MEMDESC_GLOBAL; global_pt_alloc += memdesc->size; @@ -210,7 +211,7 @@ static void kgsl_iommu_add_global(struct kgsl_mmu *mmu, void kgsl_add_global_secure_entry(struct kgsl_device *device, struct kgsl_memdesc *memdesc) { - memdesc->gpuaddr = KGSL_IOMMU_SECURE_BASE; + memdesc->gpuaddr = KGSL_IOMMU_SECURE_BASE(&device->mmu); kgsl_global_secure_pt_entry = memdesc; } @@ -631,7 +632,7 @@ static void _find_mem_entries(struct kgsl_mmu *mmu, uint64_t faultaddr, /* Set the maximum possible size as an initial value */ nextentry->gpuaddr = (uint64_t) -1; - if (ADDR_IN_GLOBAL(faultaddr)) { + if (ADDR_IN_GLOBAL(mmu, faultaddr)) { _get_global_entries(faultaddr, preventry, nextentry); } else if (context) { private = context->proc_priv; @@ -1001,14 +1002,14 @@ static void setup_64bit_pagetable(struct kgsl_mmu *mmu, unsigned int secure_global_size = kgsl_global_secure_pt_entry != NULL ? kgsl_global_secure_pt_entry->size : 0; if (mmu->secured && pagetable->name == KGSL_MMU_SECURE_PT) { - pt->compat_va_start = KGSL_IOMMU_SECURE_BASE + + pt->compat_va_start = KGSL_IOMMU_SECURE_BASE(mmu) + secure_global_size; - pt->compat_va_end = KGSL_IOMMU_SECURE_END; - pt->va_start = KGSL_IOMMU_SECURE_BASE + secure_global_size; - pt->va_end = KGSL_IOMMU_SECURE_END; + pt->compat_va_end = KGSL_IOMMU_SECURE_END(mmu); + pt->va_start = KGSL_IOMMU_SECURE_BASE(mmu) + secure_global_size; + pt->va_end = KGSL_IOMMU_SECURE_END(mmu); } else { pt->compat_va_start = KGSL_IOMMU_SVM_BASE32; - pt->compat_va_end = KGSL_IOMMU_SVM_END32; + pt->compat_va_end = KGSL_IOMMU_SECURE_BASE(mmu); pt->va_start = KGSL_IOMMU_VA_BASE64; pt->va_end = KGSL_IOMMU_VA_END64; } @@ -1017,7 +1018,7 @@ static void setup_64bit_pagetable(struct kgsl_mmu *mmu, pagetable->name != KGSL_MMU_SECURE_PT) { if ((BITS_PER_LONG == 32) || is_compat_task()) { pt->svm_start = KGSL_IOMMU_SVM_BASE32; - pt->svm_end = KGSL_IOMMU_SVM_END32; + pt->svm_end = KGSL_IOMMU_SECURE_BASE(mmu); } else { pt->svm_start = KGSL_IOMMU_SVM_BASE64; pt->svm_end = KGSL_IOMMU_SVM_END64; @@ -1033,22 +1034,22 @@ static void setup_32bit_pagetable(struct kgsl_mmu *mmu, kgsl_global_secure_pt_entry->size : 0; if (mmu->secured) { if (pagetable->name == KGSL_MMU_SECURE_PT) { - pt->compat_va_start = KGSL_IOMMU_SECURE_BASE + + pt->compat_va_start = KGSL_IOMMU_SECURE_BASE(mmu) + secure_global_size; - pt->compat_va_end = KGSL_IOMMU_SECURE_END; - pt->va_start = KGSL_IOMMU_SECURE_BASE + + pt->compat_va_end = KGSL_IOMMU_SECURE_END(mmu); + pt->va_start = KGSL_IOMMU_SECURE_BASE(mmu) + secure_global_size; - pt->va_end = KGSL_IOMMU_SECURE_END; + pt->va_end = KGSL_IOMMU_SECURE_END(mmu); } else { pt->va_start = KGSL_IOMMU_SVM_BASE32; - pt->va_end = KGSL_IOMMU_SECURE_BASE + + pt->va_end = KGSL_IOMMU_SECURE_BASE(mmu) + secure_global_size; pt->compat_va_start = pt->va_start; pt->compat_va_end = pt->va_end; } } else { pt->va_start = KGSL_IOMMU_SVM_BASE32; - pt->va_end = KGSL_IOMMU_GLOBAL_MEM_BASE; + pt->va_end = KGSL_IOMMU_GLOBAL_MEM_BASE(mmu); pt->compat_va_start = pt->va_start; pt->compat_va_end = pt->va_end; } @@ -2203,7 +2204,8 @@ static int kgsl_iommu_set_svm_region(struct kgsl_pagetable *pagetable, struct rb_node *node; /* Make sure the requested address doesn't fall in the global range */ - if (ADDR_IN_GLOBAL(gpuaddr) || ADDR_IN_GLOBAL(gpuaddr + size)) + if (ADDR_IN_GLOBAL(pagetable->mmu, gpuaddr) || + ADDR_IN_GLOBAL(pagetable->mmu, gpuaddr + size)) return -ENOMEM; spin_lock(&pagetable->lock); diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h index 457522986fce2..a6de179831ba0 100644 --- a/drivers/gpu/msm/kgsl_iommu.h +++ b/drivers/gpu/msm/kgsl_iommu.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016,2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -24,12 +24,17 @@ * are mapped into all pagetables. */ #define KGSL_IOMMU_GLOBAL_MEM_SIZE SZ_8M -#define KGSL_IOMMU_GLOBAL_MEM_BASE 0xf8000000 +#define KGSL_IOMMU_GLOBAL_MEM_BASE32 0xf8000000 +#define KGSL_IOMMU_GLOBAL_MEM_BASE64 0x100000000ULL + +#define KGSL_IOMMU_GLOBAL_MEM_BASE(__mmu) \ + (MMU_FEATURE(__mmu, KGSL_MMU_64BIT) ? \ + KGSL_IOMMU_GLOBAL_MEM_BASE64 : KGSL_IOMMU_GLOBAL_MEM_BASE32) #define KGSL_IOMMU_SECURE_SIZE SZ_256M -#define KGSL_IOMMU_SECURE_END KGSL_IOMMU_GLOBAL_MEM_BASE -#define KGSL_IOMMU_SECURE_BASE \ - (KGSL_IOMMU_GLOBAL_MEM_BASE - KGSL_IOMMU_SECURE_SIZE) +#define KGSL_IOMMU_SECURE_END(_mmu) KGSL_IOMMU_GLOBAL_MEM_BASE(_mmu) +#define KGSL_IOMMU_SECURE_BASE(_mmu) \ + (KGSL_IOMMU_GLOBAL_MEM_BASE(_mmu) - KGSL_IOMMU_SECURE_SIZE) #define KGSL_IOMMU_SVM_BASE32 0x300000 #define KGSL_IOMMU_SVM_END32 (0xC0000000 - SZ_16M) From 541f7ee26f75346ce0e135e2b7381d5d17ed61a6 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Mon, 29 Jan 2018 17:10:18 +0530 Subject: [PATCH 428/508] msm: kgsl: Update global memory base to 0XFC000000 for 64bit kernel KGSL memstore GPU address should be 32bit value for user mode graphics driver to successfully mmap device memstore. Move global memory base to 0XFC000000 from 0X100000000 for 64bit kernel to allow user mode graphics driver to successfully mmap memstore. Change-Id: Iadfbde5e2b13c1be943a272e424f6c5f05cc1b97 Signed-off-by: Deepak Kumar --- drivers/gpu/msm/kgsl_iommu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h index a6de179831ba0..097dfe798bbe7 100644 --- a/drivers/gpu/msm/kgsl_iommu.h +++ b/drivers/gpu/msm/kgsl_iommu.h @@ -25,7 +25,7 @@ */ #define KGSL_IOMMU_GLOBAL_MEM_SIZE SZ_8M #define KGSL_IOMMU_GLOBAL_MEM_BASE32 0xf8000000 -#define KGSL_IOMMU_GLOBAL_MEM_BASE64 0x100000000ULL +#define KGSL_IOMMU_GLOBAL_MEM_BASE64 0xfc000000 #define KGSL_IOMMU_GLOBAL_MEM_BASE(__mmu) \ (MMU_FEATURE(__mmu, KGSL_MMU_64BIT) ? \ From 1980383034c992bdc72978985494228140bafe2e Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Thu, 24 May 2018 19:05:48 +0530 Subject: [PATCH 429/508] wlan: NULL pointer access in wlan_hdd_free_cache_channels original_channels in hdd context is getting allocated when set disable channel command is issued and getting freed in wlan_hdd_free_cache_channels from hdd_wlan_exit api. When wlan_hdd_free_cache_channels api is invoked from hdd_wlan_exit api without invoking set disable channel command, it tries to access the "original_channels" pointer which is not allocated and it leads to NULL pointer access. To fix this issue, add a check to validate "original_channels" pointer in wlan_hdd_free_cache_channels api before accessing it. Change-Id: Id703ad42e39e7de658d4f7c2383f39a69f21047a CRs-Fixed: 2248326 --- CORE/HDD/src/wlan_hdd_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 9015a27706571..b37aa54e0f59a 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -3597,6 +3597,9 @@ static inline void hdd_assign_reassoc_handoff(tCsrHandoffRequest *handoffInfo) static void wlan_hdd_free_cache_channels(hdd_context_t *hdd_ctx) { + if(!hdd_ctx || !hdd_ctx->original_channels) + return; + mutex_lock(&hdd_ctx->cache_channel_lock); hdd_ctx->original_channels->num_channels = 0; vos_mem_free(hdd_ctx->original_channels->channel_info); From 2956956ab4be2a5717fef2a5ce6de156bd326400 Mon Sep 17 00:00:00 2001 From: gaolez Date: Tue, 15 May 2018 12:06:58 +0800 Subject: [PATCH 430/508] ARM: dts: msm: Disable pronto node on APQ8053 Lite dragonboard Disable pronto node to eliminate the side effect to naples wlan card on APQ8053 Lite dragonboard. Change-Id: I6668448627366de6ed3f6c06eca96544e482dd12 Signed-off-by: Gaole Zhang --- arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi b/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi index 6286015ae2c2c..1c3713cbf4918 100644 --- a/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi +++ b/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -537,3 +537,13 @@ status = "ok"; }; }; + +&soc { + qcom,wcnss-wlan@0a000000 { + status = "disabled"; + }; + + qcom,pronto@a21b000 { + status = "disabled"; + }; +}; From e452ce14cc578bc77c192e121588455a2b1f4c7e Mon Sep 17 00:00:00 2001 From: gaolez Date: Thu, 24 May 2018 12:39:43 +0800 Subject: [PATCH 431/508] defconfig: arm: Add naples sdio related config Add naples sdio related config. Change-Id: If0d2bc0f9d018b287282de50fc8b9659367546eb Signed-off-by: Gaole Zhang --- arch/arm/configs/msmcortex-perf_defconfig | 4 +++- arch/arm/configs/msmcortex_defconfig | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/msmcortex-perf_defconfig b/arch/arm/configs/msmcortex-perf_defconfig index 1d28f3770f0d4..0152945efdc6d 100644 --- a/arch/arm/configs/msmcortex-perf_defconfig +++ b/arch/arm/configs/msmcortex-perf_defconfig @@ -285,7 +285,9 @@ CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CNSS_CRYPTO=y CONFIG_ATH_CARDS=y -CONFIG_CLD_LL_CORE=y +CONFIG_CNSS=y +CONFIG_CNSS_SDIO=y +CONFIG_CLD_HL_SDIO_CORE=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_EVBUG=m CONFIG_INPUT_KEYRESET=y diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig index 1357b17ef3bb4..cb620619749af 100644 --- a/arch/arm/configs/msmcortex_defconfig +++ b/arch/arm/configs/msmcortex_defconfig @@ -227,7 +227,6 @@ CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y CONFIG_MSM_BT_POWER=y CONFIG_CFG80211=y -CONFIG_NL80211_TESTMODE=y CONFIG_CFG80211_INTERNAL_REGDB=y CONFIG_RFKILL=y CONFIG_NFC_NQ=y @@ -287,6 +286,9 @@ CONFIG_WCNSS_CORE_PRONTO=y CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CNSS_CRYPTO=y +CONFIG_CNSS=y +CONFIG_CNSS_SDIO=y +CONFIG_CLD_HL_SDIO_CORE=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_EVBUG=m CONFIG_KEYBOARD_GPIO=y From b390666734c246eab75ac396b94a5eb2f92b97dc Mon Sep 17 00:00:00 2001 From: Rama Krishna Phani A Date: Mon, 21 May 2018 16:25:35 +0530 Subject: [PATCH 432/508] msm: mhi_dev: Remove redundant code MHI will be using IPA for all transfers from host to device and viceversa. Remove redundant code for non IPA case. Change-Id: Ibe7146f94dad5baa8faa66a62025a0fae1a48811 Signed-off-by: Rama Krishna Phani A --- drivers/platform/msm/mhi_dev/mhi.c | 89 +++++++++++++----------------- 1 file changed, 39 insertions(+), 50 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 0f6a0d255db61..48edff5a60f65 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -122,22 +122,18 @@ void mhi_dev_read_from_host(struct mhi_dev *mhi, struct mhi_addr *transfer) host_addr_pa = transfer->host_pa | bit_40; } - if (mhi->use_ipa) { - mhi_log(MHI_MSG_VERBOSE, - "device 0x%x <<-- host 0x%llx, size %d\n", - transfer->phy_addr, host_addr_pa, - (int) transfer->size); - rc = ipa_dma_async_memcpy((u64)transfer->phy_addr, host_addr_pa, - (int)transfer->size, - mhi_dev_ring_cache_completion_cb, &ring_req); - if (rc) - pr_err("error while reading from host:%d\n", rc); + mhi_log(MHI_MSG_VERBOSE, + "device 0x%x <<-- host 0x%llx, size %d\n", + transfer->phy_addr, host_addr_pa, + (int) transfer->size); + rc = ipa_dma_async_memcpy((u64)transfer->phy_addr, host_addr_pa, + (int)transfer->size, + mhi_dev_ring_cache_completion_cb, &ring_req); + if (rc) + pr_err("error while reading from host:%d\n", rc); + + wait_for_completion(&done); - wait_for_completion(&done); - } else { - memcpy(transfer->virt_addr, (void *) &transfer->device_va, - (int) transfer->size); - } } EXPORT_SYMBOL(mhi_dev_read_from_host); @@ -160,42 +156,35 @@ void mhi_dev_write_to_host(struct mhi_dev *mhi, struct mhi_addr *transfer, host_addr_pa = transfer->host_pa | bit_40; } - if (mhi->use_ipa) { - mhi_log(MHI_MSG_VERBOSE, - "device 0x%llx --> host 0x%llx, size %d\n", - (uint64_t) mhi->cache_dma_handle, host_addr_pa, - (int) transfer->size); - if (tr_type == MHI_DEV_DMA_ASYNC) { - dma = dma_map_single(&mhi->pdev->dev, - transfer->virt_addr, transfer->size, - DMA_TO_DEVICE); - if (ereq->event_type == SEND_EVENT_BUFFER) { - ereq->dma = dma; - ereq->dma_len = transfer->size; - } else if (ereq->event_type == SEND_EVENT_RD_OFFSET) { - ereq->event_rd_dma = dma; - } - rc = ipa_dma_async_memcpy(host_addr_pa, (uint64_t) dma, - (int)transfer->size, - ereq->client_cb, ereq); - if (rc) - pr_err("error while writing to host:%d\n", rc); - } else if (tr_type == MHI_DEV_DMA_SYNC) { - /* Copy the device content to a local device - * physical address */ - memcpy(mhi->dma_cache, transfer->virt_addr, - transfer->size); - rc = ipa_dma_sync_memcpy(host_addr_pa, - (u64) mhi->cache_dma_handle, - (int) transfer->size); - if (rc) - pr_err("error while writing to host:%d\n", rc); - } - } else { - memcpy((void *) &transfer->device_va, transfer->virt_addr, + mhi_log(MHI_MSG_VERBOSE, + "device 0x%llx --> host 0x%llx, size %d\n", + (uint64_t) mhi->cache_dma_handle, host_addr_pa, + (int) transfer->size); + if (tr_type == MHI_DEV_DMA_ASYNC) { + dma = dma_map_single(&mhi->pdev->dev, + transfer->virt_addr, transfer->size, + DMA_TO_DEVICE); + if (ereq->event_type == SEND_EVENT_BUFFER) { + ereq->dma = dma; + ereq->dma_len = transfer->size; + } else if (ereq->event_type == SEND_EVENT_RD_OFFSET) { + ereq->event_rd_dma = dma; + } + rc = ipa_dma_async_memcpy(host_addr_pa, (uint64_t) dma, + (int)transfer->size, + ereq->client_cb, ereq); + if (rc) + pr_err("error while writing to host:%d\n", rc); + } else if (tr_type == MHI_DEV_DMA_SYNC) { + /* Copy the device content to a local device + * physical address */ + memcpy(mhi->dma_cache, transfer->virt_addr, transfer->size); - /* Update state before sending events */ - wmb(); + rc = ipa_dma_sync_memcpy(host_addr_pa, + (u64) mhi->cache_dma_handle, + (int) transfer->size); + if (rc) + pr_err("error while writing to host:%d\n", rc); } } EXPORT_SYMBOL(mhi_dev_write_to_host); From 9102fbc658a3ba65ef6ce7509662ed81e8b2034a Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Tue, 29 May 2018 13:07:55 +0530 Subject: [PATCH 433/508] wlan: Initialize channel switch completion variable during SAP OPEN Presently, channel switch completion variable is initialized while processing start ap cfg operation, but the WEXT interface is registered during change interface(which is invoked prior to start ap) itself. So, there is a possibility of using the completion variable before its get initialized, if SET_CHANNEL_CHANGE IOCTL is invoked before start ap is invoked. To mitigate this issue initialize channel switch completion variable during SAP OPEN. Change-Id: I84b202be89bfe54084f487e251458834f6472485 CRs-Fixed: 2250046 --- CORE/SAP/src/sapModule.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CORE/SAP/src/sapModule.c b/CORE/SAP/src/sapModule.c index 6268e7de0e9bc..e6109599ec62d 100644 --- a/CORE/SAP/src/sapModule.c +++ b/CORE/SAP/src/sapModule.c @@ -173,6 +173,8 @@ WLANSAP_Open return VOS_STATUS_E_FAULT; } + init_completion(&pSapCtx->ecsa_info.chan_switch_comp); + if (!VOS_IS_STATUS_SUCCESS( vos_spin_lock_init(&pSapCtx->ecsa_info.ecsa_lock))) { @@ -648,7 +650,6 @@ WLANSAP_StartBss pSapCtx->scanBandPreference = pConfig->scanBandPreference; pSapCtx->acsBandSwitchThreshold = pConfig->acsBandSwitchThreshold; pSapCtx->pUsrContext = pUsrContext; - init_completion(&pSapCtx->ecsa_info.chan_switch_comp); //Set the BSSID to your "self MAC Addr" read the mac address from Configuation ITEM received from HDD pSapCtx->csrRoamProfile.BSSIDs.numOfBSSIDs = 1; From 9233e77c01b75bd5c625a9fa5f23108af66c63f9 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 5 Jan 2018 16:26:00 -0800 Subject: [PATCH 434/508] loop: fix concurrent lo_open/lo_release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 范龙飞 reports that KASAN can report a use-after-free in __lock_acquire. The reason is due to insufficient serialization in lo_release(), which will continue to use the loop device even after it has decremented the lo_refcnt to zero. In the meantime, another process can come in, open the loop device again as it is being shut down. Confusion ensues. Reported-by: 范龙飞 Signed-off-by: Linus Torvalds Signed-off-by: Jens Axboe Git-commit: ae6650163c66a7eff1acd6eb8b0f752dcfa8eba5 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Change-Id: I965ddcdc2a9d27fd56a54d2886b7c3861c21b05f Signed-off-by: Srinivasa Rao Kuppala --- drivers/block/loop.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 6cb1beb47c25d..94385b969f675 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1512,9 +1512,8 @@ static int lo_open(struct block_device *bdev, fmode_t mode) return err; } -static void lo_release(struct gendisk *disk, fmode_t mode) +static void __lo_release(struct loop_device *lo) { - struct loop_device *lo = disk->private_data; int err; mutex_lock(&lo->lo_ctl_mutex); @@ -1542,6 +1541,13 @@ static void lo_release(struct gendisk *disk, fmode_t mode) mutex_unlock(&lo->lo_ctl_mutex); } +static void lo_release(struct gendisk *disk, fmode_t mode) +{ + mutex_lock(&loop_index_mutex); + __lo_release(disk->private_data); + mutex_unlock(&loop_index_mutex); +} + static const struct block_device_operations lo_fops = { .owner = THIS_MODULE, .open = lo_open, From 649de266e2b7c26a70ace40231d1d835a4561500 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 23 Oct 2017 16:46:00 -0700 Subject: [PATCH 435/508] Input: gtco - fix potential out-of-bound access parse_hid_report_descriptor() has a while (i < length) loop, which only guarantees that there's at least 1 byte in the buffer, but the loop body can read multiple bytes which causes out-of-bounds access. Reported-by: Andrey Konovalov Reviewed-by: Andrey Konovalov Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov Change-Id: I7b57556c100d28d8f10c03ea5480224e770fb64a Git-commit: a50829479f58416a013a4ccca791336af3c584c7 Git-repo: https://android.googlesource.com/kernel/common Signed-off-by: Srinivasa Rao Kuppala --- drivers/input/tablet/gtco.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index a51de543a0b2f..fe1ab5067b5d4 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -231,13 +231,17 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, /* Walk this report and pull out the info we need */ while (i < length) { - prefix = report[i]; - - /* Skip over prefix */ - i++; + prefix = report[i++]; /* Determine data size and save the data in the proper variable */ - size = PREF_SIZE(prefix); + size = (1U << PREF_SIZE(prefix)) >> 1; + if (i + size > length) { + dev_err(ddev, + "Not enough data (need %d, have %d)\n", + i + size, length); + break; + } + switch (size) { case 1: data = report[i]; @@ -245,8 +249,7 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, case 2: data16 = get_unaligned_le16(&report[i]); break; - case 3: - size = 4; + case 4: data32 = get_unaligned_le32(&report[i]); break; } From f477dc56e5729161f46b16ffb82ea7c89fe041df Mon Sep 17 00:00:00 2001 From: Vijay Navnath Kamble Date: Fri, 23 Mar 2018 12:42:58 +0530 Subject: [PATCH 436/508] input: touchscreen: Add himax touchscreen support apq8053-lite FEP-V2 SOM has 2 variants of display Panel - 8" and 10". For 8" display panel the touch vendor is Himax. Add Himax touchscreen support for 8" Display Panel. Git-Repo: https://github.com/HimaxSoftware/msm-3.18 Change-Id: Icd68acfd4f119da98e928e5b5842866c1c7df2f6 Signed-off-by: Paul Chang (cherry picked from commit aa2965fae3f8d791d0fd4c8105408bee807b540c) (cherry picked from commit 714259e2f1eadeb712fdb9cf6e6619fe6eece156) (cherry picked from commit 788fbe836fcabb5493596a2ccc393645665e47c5) (cherry picked from commit 884851757226bb87dd51c5686ee9935a7cd95403) (cherry picked from commit a2b465b13af90f22233943c492b6f09a4fa892e7) (cherry picked from commit 1f5b2aaafa1d9935b0831b641edebd18cf05eb04) (cherry picked from commit 3f6ec12edd3200d6d3c4c32b93e4ed390160403d) (cherry picked from commit 7bc077d513ac739518734a4ab7fee80ca63a9d02) (cherry picked from commit 97afcbfbca30b5eeb3b8acc10e2d1b430650e7a0) (cherry picked from commit 566ec5a310816f2527a0f06e164a90fca7c04650) (cherry picked from commit c91150831a152e1123902f36194802124b7d8aca) (cherry picked from commit c48e3f6d989efadc818563a154e8c029d6c8acfd) (cherry picked from commit fc785e480943fec46cc85a920592de714c9662e9) Signed-off-by: Vijay Navnath Kamble Signed-off-by: Sumit Agrawal --- .../bindings/input/touchscreen/himax.txt | 22 + drivers/input/touchscreen/Kconfig | 12 + drivers/input/touchscreen/Makefile | 1 + .../hxchipset/HX83100_Amber_0901_030B.i | 0 .../input/touchscreen/hxchipset/HX_CRC_124.i | 0 .../input/touchscreen/hxchipset/HX_CRC_128.i | 0 .../input/touchscreen/hxchipset/HX_CRC_60.i | 0 .../input/touchscreen/hxchipset/HX_CRC_64.i | 0 drivers/input/touchscreen/hxchipset/Kconfig | 21 + drivers/input/touchscreen/hxchipset/Makefile | 3 + .../touchscreen/hxchipset/himax_common.c | 1936 ++++++++++++++ .../touchscreen/hxchipset/himax_common.h | 395 +++ .../input/touchscreen/hxchipset/himax_debug.c | 2329 +++++++++++++++++ .../input/touchscreen/hxchipset/himax_debug.h | 181 ++ .../input/touchscreen/hxchipset/himax_ic.c | 2118 +++++++++++++++ .../input/touchscreen/hxchipset/himax_ic.h | 82 + .../touchscreen/hxchipset/himax_platform.c | 796 ++++++ .../touchscreen/hxchipset/himax_platform.h | 135 + 18 files changed, 8031 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/himax.txt create mode 100644 drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i create mode 100644 drivers/input/touchscreen/hxchipset/HX_CRC_124.i create mode 100644 drivers/input/touchscreen/hxchipset/HX_CRC_128.i create mode 100644 drivers/input/touchscreen/hxchipset/HX_CRC_60.i create mode 100644 drivers/input/touchscreen/hxchipset/HX_CRC_64.i create mode 100644 drivers/input/touchscreen/hxchipset/Kconfig create mode 100644 drivers/input/touchscreen/hxchipset/Makefile create mode 100644 drivers/input/touchscreen/hxchipset/himax_common.c create mode 100644 drivers/input/touchscreen/hxchipset/himax_common.h create mode 100644 drivers/input/touchscreen/hxchipset/himax_debug.c create mode 100644 drivers/input/touchscreen/hxchipset/himax_debug.h create mode 100644 drivers/input/touchscreen/hxchipset/himax_ic.c create mode 100644 drivers/input/touchscreen/hxchipset/himax_ic.h create mode 100644 drivers/input/touchscreen/hxchipset/himax_platform.c create mode 100644 drivers/input/touchscreen/hxchipset/himax_platform.h diff --git a/Documentation/devicetree/bindings/input/touchscreen/himax.txt b/Documentation/devicetree/bindings/input/touchscreen/himax.txt new file mode 100644 index 0000000000000..b54c85971927d --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/himax.txt @@ -0,0 +1,22 @@ +Himax touch controller + +Required properties: + + - compatible : Should be "himax,hxcommon" + - reg : i2c slave address of the device. + - interrupt-parent : parent of interrupt. + - himax,irq-gpio : irq gpio. + - himax,reset-gpio : reset gpio. + - vdd-supply : Power supply needed to power up the device. + - avdd-supply : Power source required to power up i2c bus. + - himax,panel-coords : panel coordinates for the chip in pixels. + It is a four tuple consisting of min x, + min y, max x and max y values. + - himax,display-coords : display coordinates in pixels. It is a four + tuple consisting of min x, min y, max x and + max y values + +Optional properties: + - himax,3v3-gpio : gpio acting as 3.3 v supply. + - report_type : Multi-touch protocol type. Default 0. + 0 for protocol A, 1 for protocol B. diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index dd9b928e36948..769849d2e43c6 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1137,4 +1137,16 @@ config TOUCHSCREEN_MAXIM_STI source "drivers/input/touchscreen/gt9xx/Kconfig" +config TOUCHSCREEN_HIMAX_CHIPSET + bool "Himax touchpanel CHIPSET" + depends on I2C + help + Say Y here if you have a Himax CHIPSET touchscreen. + HIMAX controllers are multi touch controllers which can + report 10 touches at a time. + + If unsure, say N. + +source "drivers/input/touchscreen/hxchipset/Kconfig" + endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index be0eb9b34f5b6..499b8110fe6cc 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -90,3 +90,4 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += synaptics_i2c_rmi4.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV) += synaptics_rmi_dev.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE) += synaptics_fw_update.o obj-$(CONFIG_TOUCHSCREEN_GT9XX) += gt9xx/ +obj-$(CONFIG_TOUCHSCREEN_HIMAX_CHIPSET) += hxchipset/ diff --git a/drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i b/drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_124.i b/drivers/input/touchscreen/hxchipset/HX_CRC_124.i new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_128.i b/drivers/input/touchscreen/hxchipset/HX_CRC_128.i new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_60.i b/drivers/input/touchscreen/hxchipset/HX_CRC_60.i new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_64.i b/drivers/input/touchscreen/hxchipset/HX_CRC_64.i new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/drivers/input/touchscreen/hxchipset/Kconfig b/drivers/input/touchscreen/hxchipset/Kconfig new file mode 100644 index 0000000000000..ebf3aa478af51 --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/Kconfig @@ -0,0 +1,21 @@ +# +# Himax Touchscreen driver configuration +# + +config TOUCHSCREEN_HIMAX_I2C + tristate "HIMAX chipset i2c touchscreen" + depends on TOUCHSCREEN_HIMAX_CHIPSET + help + This enables support for HIMAX CHIPSET over I2C based touchscreens. + +config TOUCHSCREEN_HIMAX_DEBUG + tristate "HIMAX debug function" + depends on TOUCHSCREEN_HIMAX_I2C + help + This enables support for HIMAX debug function. + +config HMX_DB + tristate "HIMAX driver test over Dragon Board" + depends on TOUCHSCREEN_HIMAX_I2C + help + This enables support for HIMAX driver test over Dragon Board. diff --git a/drivers/input/touchscreen/hxchipset/Makefile b/drivers/input/touchscreen/hxchipset/Makefile new file mode 100644 index 0000000000000..509d4913bc39f --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/Makefile @@ -0,0 +1,3 @@ +# Makefile for the Himax touchscreen drivers. + +obj-$(CONFIG_TOUCHSCREEN_HIMAX_I2C) += himax_platform.o himax_ic.o himax_common.o himax_debug.o diff --git a/drivers/input/touchscreen/hxchipset/himax_common.c b/drivers/input/touchscreen/hxchipset/himax_common.c new file mode 100644 index 0000000000000..417b0c08e3615 --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_common.c @@ -0,0 +1,1936 @@ +/* Himax Android Driver Sample Code for Himax chipset +* +* Copyright (C) 2015 Himax Corporation. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#include "himax_common.h" +#include "himax_ic.h" + +#define SUPPORT_FINGER_DATA_CHECKSUM 0x0F +#define TS_WAKE_LOCK_TIMEOUT (2 * HZ) +#define FRAME_COUNT 5 + +#if defined(HX_AUTO_UPDATE_FW) + static unsigned char i_CTPM_FW[]= + { + #include "HX83100_Amber_0901_030B.i" + }; +#endif + +#ifdef HX_ESD_WORKAROUND + extern void HX_report_ESD_event(void); + unsigned char ESD_00_counter = 0; + unsigned char ESD_00_Flag = 0; +#endif + +//static int tpd_keys_local[HX_KEY_MAX_COUNT] = HX_KEY_ARRAY; // for Virtual key array + +struct himax_ts_data *private_ts; +struct himax_ic_data* ic_data; + +static int HX_TOUCH_INFO_POINT_CNT; + +#ifdef HX_AUTO_UPDATE_FW +extern unsigned long FW_VER_MAJ_FLASH_ADDR; +extern unsigned long FW_VER_MIN_FLASH_ADDR; +extern unsigned long CFG_VER_MAJ_FLASH_ADDR; +extern unsigned long CFG_VER_MIN_FLASH_ADDR; +#endif +extern unsigned long FW_VER_MAJ_FLASH_LENG; +extern unsigned long FW_VER_MIN_FLASH_LENG; +extern unsigned long CFG_VER_MAJ_FLASH_LENG; +extern unsigned long CFG_VER_MIN_FLASH_LENG; +extern unsigned char IC_TYPE; +extern unsigned char IC_CHECKSUM; + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) +extern int himax_touch_proc_init(void); +extern void himax_touch_proc_deinit(void); +//PROC-START +#ifdef HX_TP_PROC_FLASH_DUMP +extern void himax_ts_flash_func(void); +extern void setFlashBuffer(void); +extern bool getFlashDumpGoing(void); +extern uint8_t getSysOperation(void); +extern void setSysOperation(uint8_t operation); +#endif + +#ifdef HX_TP_PROC_HITOUCH +extern bool hitouch_is_connect; +#endif + +#ifdef HX_TP_PROC_DIAG + extern int touch_monitor_stop_flag; + extern int touch_monitor_stop_limit; + extern void himax_ts_diag_func(void); + extern int16_t *getMutualBuffer(void); + extern int16_t *getMutualNewBuffer(void); + extern int16_t *getMutualOldBuffer(void); + extern int16_t *getSelfBuffer(void); + extern uint8_t getXChannel(void); + extern uint8_t getYChannel(void); + extern uint8_t getDiagCommand(void); + extern void setXChannel(uint8_t x); + extern void setYChannel(uint8_t y); + extern void setMutualBuffer(void); + extern void setMutualNewBuffer(void); + extern void setMutualOldBuffer(void); + extern uint8_t coordinate_dump_enable; + extern struct file *coordinate_fn; + extern uint8_t diag_coor[128]; +#ifdef HX_TP_PROC_2T2R + extern int16_t *getMutualBuffer_2(void); + extern uint8_t getXChannel_2(void); + extern uint8_t getYChannel_2(void); + extern void setXChannel_2(uint8_t x); + extern void setYChannel_2(uint8_t y); + extern void setMutualBuffer_2(void); +#endif +#endif +//PROC-END +#endif + +extern int himax_parse_dt(struct himax_ts_data *ts, + struct himax_i2c_platform_data *pdata); +extern int himax_ts_pinctrl_init(struct himax_ts_data *ts); + +static uint8_t vk_press; +static uint8_t AA_press; +static uint8_t EN_NoiseFilter; +static uint8_t Last_EN_NoiseFilter; +static int hx_point_num; // for himax_ts_work_func use +static int p_point_num = 0xFFFF; +static int tpd_key; +static int tpd_key_old; +static int probe_fail_flag; +static bool config_load; +static struct himax_config *config_selected; + +//static int iref_number = 11; +//static bool iref_found = false; + +#ifdef HX_USB_DETECT2 +extern bool USB_Flag; +#endif + +#if defined(CONFIG_FB) +int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data); +#elif defined(CONFIG_HAS_EARLYSUSPEND) +static void himax_ts_early_suspend(struct early_suspend *h); +static void himax_ts_late_resume(struct early_suspend *h); +#endif + +int himax_input_register(struct himax_ts_data *ts) +{ + int ret; + ts->input_dev = input_allocate_device(); + if (ts->input_dev == NULL) { + ret = -ENOMEM; + E("%s: Failed to allocate input device\n", __func__); + return ret; + } + ts->input_dev->name = "himax-touchscreen"; + + set_bit(EV_SYN, ts->input_dev->evbit); + set_bit(EV_ABS, ts->input_dev->evbit); + set_bit(EV_KEY, ts->input_dev->evbit); + + set_bit(KEY_BACK, ts->input_dev->keybit); + set_bit(KEY_HOME, ts->input_dev->keybit); + set_bit(KEY_MENU, ts->input_dev->keybit); + set_bit(KEY_SEARCH, ts->input_dev->keybit); +#if defined(HX_SMART_WAKEUP) + set_bit(KEY_POWER, ts->input_dev->keybit); + set_bit(KEY_CUST_01, ts->input_dev->keybit); + set_bit(KEY_CUST_02, ts->input_dev->keybit); + set_bit(KEY_CUST_03, ts->input_dev->keybit); + set_bit(KEY_CUST_04, ts->input_dev->keybit); + set_bit(KEY_CUST_05, ts->input_dev->keybit); + set_bit(KEY_CUST_06, ts->input_dev->keybit); + set_bit(KEY_CUST_07, ts->input_dev->keybit); + set_bit(KEY_CUST_08, ts->input_dev->keybit); + set_bit(KEY_CUST_09, ts->input_dev->keybit); + set_bit(KEY_CUST_10, ts->input_dev->keybit); + set_bit(KEY_CUST_11, ts->input_dev->keybit); + set_bit(KEY_CUST_12, ts->input_dev->keybit); + set_bit(KEY_CUST_13, ts->input_dev->keybit); + set_bit(KEY_CUST_14, ts->input_dev->keybit); + set_bit(KEY_CUST_15, ts->input_dev->keybit); +#endif + set_bit(BTN_TOUCH, ts->input_dev->keybit); + + set_bit(KEY_F10, ts->input_dev->keybit); + + set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); + + if (ts->protocol_type == PROTOCOL_TYPE_A) { + //ts->input_dev->mtsize = ts->nFinger_support; + input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, + 0, 3, 0, 0); + } else {/* PROTOCOL_TYPE_B */ + set_bit(MT_TOOL_FINGER, ts->input_dev->keybit); + input_mt_init_slots(ts->input_dev, ts->nFinger_support,0); + } + + I("input_set_abs_params: mix_x %d, max_x %d, min_y %d, max_y %d\n", + ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max); + + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_x_fuzz, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,ts->pdata->abs_y_min, ts->pdata->abs_y_max, ts->pdata->abs_y_fuzz, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR,ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, ts->pdata->abs_pressure_fuzz, 0); + input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE,ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, ts->pdata->abs_pressure_fuzz, 0); + input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR,ts->pdata->abs_width_min, ts->pdata->abs_width_max, ts->pdata->abs_pressure_fuzz, 0); + +// input_set_abs_params(ts->input_dev, ABS_MT_AMPLITUDE, 0, ((ts->pdata->abs_pressure_max << 16) | ts->pdata->abs_width_max), 0, 0); +// input_set_abs_params(ts->input_dev, ABS_MT_POSITION, 0, (BIT(31) | (ts->pdata->abs_x_max << 16) | ts->pdata->abs_y_max), 0, 0); + + return input_register_device(ts->input_dev); +} + +static void calcDataSize(uint8_t finger_num) +{ + struct himax_ts_data *ts_data = private_ts; + ts_data->coord_data_size = 4 * finger_num; + ts_data->area_data_size = ((finger_num / 4) + (finger_num % 4 ? 1 : 0)) * 4; + ts_data->raw_data_frame_size = 128 - ts_data->coord_data_size - ts_data->area_data_size - 4 - 4 - 1; + ts_data->raw_data_nframes = ((uint32_t)ts_data->x_channel * ts_data->y_channel + + ts_data->x_channel + ts_data->y_channel) / ts_data->raw_data_frame_size + + (((uint32_t)ts_data->x_channel * ts_data->y_channel + + ts_data->x_channel + ts_data->y_channel) % ts_data->raw_data_frame_size)? 1 : 0; + I("%s: coord_data_size: %d, area_data_size:%d, raw_data_frame_size:%d, raw_data_nframes:%d", __func__, ts_data->coord_data_size, ts_data->area_data_size, ts_data->raw_data_frame_size, ts_data->raw_data_nframes); +} + +static void calculate_point_number(void) +{ + HX_TOUCH_INFO_POINT_CNT = ic_data->HX_MAX_PT * 4 ; + + if ( (ic_data->HX_MAX_PT % 4) == 0) + HX_TOUCH_INFO_POINT_CNT += (ic_data->HX_MAX_PT / 4) * 4 ; + else + HX_TOUCH_INFO_POINT_CNT += ((ic_data->HX_MAX_PT / 4) +1) * 4 ; +} + +#if 0 +static int himax_read_Sensor_ID(struct i2c_client *client) +{ + uint8_t val_high[1], val_low[1], ID0=0, ID1=0; + char data[3]; + const int normalRetry = 10; + int sensor_id; + + data[0] = 0x56; data[1] = 0x02; data[2] = 0x02;/*ID pin PULL High*/ + i2c_himax_master_write(client, &data[0],3,normalRetry); + usleep_range(1000, 2000); + + //read id pin high + i2c_himax_read(client, 0x57, val_high, 1, normalRetry); + + data[0] = 0x56; data[1] = 0x01; data[2] = 0x01;/*ID pin PULL Low*/ + i2c_himax_master_write(client, &data[0],3,normalRetry); + usleep_range(1000, 2000); + + //read id pin low + i2c_himax_read(client, 0x57, val_low, 1, normalRetry); + + if((val_high[0] & 0x01) ==0) + ID0=0x02;/*GND*/ + else if((val_low[0] & 0x01) ==0) + ID0=0x01;/*Floating*/ + else + ID0=0x04;/*VCC*/ + + if((val_high[0] & 0x02) ==0) + ID1=0x02;/*GND*/ + else if((val_low[0] & 0x02) ==0) + ID1=0x01;/*Floating*/ + else + ID1=0x04;/*VCC*/ + if((ID0==0x04)&&(ID1!=0x04)) + { + data[0] = 0x56; data[1] = 0x02; data[2] = 0x01;/*ID pin PULL High,Low*/ + i2c_himax_master_write(client, &data[0],3,normalRetry); + usleep_range(1000, 2000); + + } + else if((ID0!=0x04)&&(ID1==0x04)) + { + data[0] = 0x56; data[1] = 0x01; data[2] = 0x02;/*ID pin PULL Low,High*/ + i2c_himax_master_write(client, &data[0],3,normalRetry); + usleep_range(1000, 2000); + + } + else if((ID0==0x04)&&(ID1==0x04)) + { + data[0] = 0x56; data[1] = 0x02; data[2] = 0x02;/*ID pin PULL High,High*/ + i2c_himax_master_write(client, &data[0],3,normalRetry); + usleep_range(1000, 2000); + + } + sensor_id=(ID1<<4)|ID0; + + data[0] = 0xE4; data[1] = sensor_id; + i2c_himax_master_write(client, &data[0],2,normalRetry);/*Write to MCU*/ + usleep_range(1000, 2000); + + return sensor_id; + +} +#endif +static void himax_power_on_initCMD(struct i2c_client *client) +{ + I("%s:\n", __func__); + + himax_touch_information(client); + + //himax_sense_on(private_ts->client, 0x01);//1=Flash, 0=SRAM +} + +#ifdef HX_AUTO_UPDATE_FW +static int i_update_FW(void) +{ + int upgrade_times = 0; + unsigned char* ImageBuffer = i_CTPM_FW; + int fullFileLength = sizeof(i_CTPM_FW); + int i_FW_VER = 0, i_CFG_VER = 0; + uint8_t ret = -1, result = 0; +// uint8_t tmp_addr[4]; +// uint8_t tmp_data[4]; + int CRC_from_FW = 0; + int CRC_Check_result = 0; + + i_FW_VER = i_CTPM_FW[FW_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW[FW_VER_MIN_FLASH_ADDR]; + i_CFG_VER = i_CTPM_FW[CFG_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW[CFG_VER_MIN_FLASH_ADDR]; + + I("%s: i_fullFileLength = %d\n", __func__,fullFileLength); + + himax_sense_off(private_ts->client); + msleep(500); + + CRC_from_FW = himax_check_CRC(private_ts->client,fw_image_64k); + CRC_Check_result = Calculate_CRC_with_AP(ImageBuffer, CRC_from_FW,fw_image_64k); + I("%s: Check sum result = %d\n", __func__,CRC_Check_result); + //I("%s: ic_data->vendor_fw_ver = %X, i_FW_VER = %X,\n", __func__,ic_data->vendor_fw_ver, i_FW_VER); + //I("%s: ic_data->vendor_config_ver = %X, i_CFG_VER = %X,\n", __func__,ic_data->vendor_config_ver, i_CFG_VER); + + if ((CRC_Check_result == 0)|| ( ic_data->vendor_fw_ver < i_FW_VER ) || ( ic_data->vendor_config_ver < i_CFG_VER )) + { + himax_int_enable(private_ts->client->irq,0); +update_retry: + if(fullFileLength == FW_SIZE_60k){ + ret = fts_ctpm_fw_upgrade_with_sys_fs_60k(private_ts->client,ImageBuffer,fullFileLength,false); + }else if (fullFileLength == FW_SIZE_64k){ + ret = fts_ctpm_fw_upgrade_with_sys_fs_64k(private_ts->client,ImageBuffer,fullFileLength,false); + }else if (fullFileLength == FW_SIZE_124k){ + ret = fts_ctpm_fw_upgrade_with_sys_fs_124k(private_ts->client,ImageBuffer,fullFileLength,false); + }else if (fullFileLength == FW_SIZE_128k){ + ret = fts_ctpm_fw_upgrade_with_sys_fs_128k(private_ts->client,ImageBuffer,fullFileLength,false); + } + if(ret == 0){ + upgrade_times++; + E("%s: TP upgrade error, upgrade_times = %d\n", __func__, upgrade_times); + if(upgrade_times < 3) + goto update_retry; + else + { + himax_sense_on(private_ts->client, 0x01); + msleep(120); +#ifdef HX_ESD_WORKAROUND + HX_ESD_RESET_ACTIVATE = 1; +#endif + result = -1;//upgrade fail + } + } + else if(ret == 1){ +/* + // 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver) + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01; + himax_register_write(private_ts->client, tmp_addr, 1, tmp_data); + + // 2. Write driver initial code condition + // write value from AHB I2C : 0x8001_C603 = 0x000000FF + tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xC6; tmp_addr[0] = 0x03; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xFF; + himax_register_write(private_ts->client, tmp_addr, 1, tmp_data); + + // 1. Set DDREG_Req = 0 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver) + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_register_write(private_ts->client, tmp_addr, 1, tmp_data); +*/ + himax_sense_on(private_ts->client, 0x01); + msleep(120); +#ifdef HX_ESD_WORKAROUND + HX_ESD_RESET_ACTIVATE = 1; +#endif + + ic_data->vendor_fw_ver = i_FW_VER; + ic_data->vendor_config_ver = i_CFG_VER; + result = 1;//upgrade success + I("%s: TP upgrade OK\n", __func__); + } + + himax_int_enable(private_ts->client->irq,1); + return result; + } + else + { + himax_sense_on(private_ts->client, 0x01); + return 0;//NO upgrade + } +} +#endif + +#ifdef HX_RST_PIN_FUNC +void himax_HW_reset(uint8_t loadconfig,uint8_t int_off) +{ + struct himax_ts_data *ts = private_ts; + int ret = 0; + + return; + if (ts->rst_gpio) { + if(int_off) + { + if (ts->use_irq) + himax_int_enable(private_ts->client->irq,0); + else { + hrtimer_cancel(&ts->timer); + ret = cancel_work_sync(&ts->work); + } + } + + I("%s: Now reset the Touch chip.\n", __func__); + + himax_rst_gpio_set(ts->rst_gpio, 0); + msleep(20); + himax_rst_gpio_set(ts->rst_gpio, 1); + msleep(20); + + if(loadconfig) + himax_loadSensorConfig(private_ts->client,private_ts->pdata); + + if(int_off) + { + if (ts->use_irq) + himax_int_enable(private_ts->client->irq,1); + else + hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); + } + } +} +#endif + +int himax_loadSensorConfig(struct i2c_client *client, struct himax_i2c_platform_data *pdata) +{ + + if (!client) { + E("%s: Necessary parameters client are null!\n", __func__); + return -EINVAL; + } + + if(config_load == false) + { + config_selected = kzalloc(sizeof(*config_selected), GFP_KERNEL); + if (config_selected == NULL) { + E("%s: alloc config_selected fail!\n", __func__); + return -ENOMEM; + } + } + + himax_power_on_initCMD(client); + + himax_int_enable(client->irq,0); + himax_read_FW_ver(client); +#ifdef HX_RST_PIN_FUNC + himax_HW_reset(true,false); +#endif + himax_int_enable(client->irq,1); + I("FW_VER : %X \n",ic_data->vendor_fw_ver); + + ic_data->vendor_sensor_id=0x2602; + I("sensor_id=%x.\n",ic_data->vendor_sensor_id); + + himax_sense_on(private_ts->client, 0x01);//1=Flash, 0=SRAM + msleep(120); +#ifdef HX_ESD_WORKAROUND + HX_ESD_RESET_ACTIVATE = 1; +#endif + I("%s: initialization complete\n", __func__); + + return 1; +} + +#ifdef HX_ESD_WORKAROUND +void ESD_HW_REST(void) +{ + I("START_Himax TP: ESD - Reset\n"); + + HX_report_ESD_event(); + ESD_00_counter = 0; + ESD_00_Flag = 0; + /*************************************/ + if (private_ts->protocol_type == PROTOCOL_TYPE_A) + input_mt_sync(private_ts->input_dev); + input_report_key(private_ts->input_dev, BTN_TOUCH, 0); + input_sync(private_ts->input_dev); + /*************************************/ + + I("END_Himax TP: ESD - Reset\n"); +} +#endif +#ifdef HX_HIGH_SENSE +void himax_set_HSEN_func(struct i2c_client *client,uint8_t HSEN_enable) +{ + uint8_t tmp_data[4]; + + if(HSEN_enable) + { + I(" %s in", __func__); + HSEN_bit_retry: + himax_set_HSEN_enable(client,HSEN_enable); + msleep(20); + himax_get_HSEN_enable(client,tmp_data); + I("%s: Read HSEN bit data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__ + ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]); + if(tmp_data[0]!= 0x01) + { + I("%s: retry HSEN bit write data[0]=%x \n",__func__,tmp_data[0]); + goto HSEN_bit_retry; + } + } +} + +static void himax_HSEN_func(struct work_struct *work) +{ + struct himax_ts_data *ts = container_of(work, struct himax_ts_data, + hsen_work.work); + + himax_set_HSEN_func(ts->client, ts->HSEN_enable); +} + +#endif + +#ifdef HX_SMART_WAKEUP +#ifdef HX_GESTURE_TRACK +static void gest_pt_log_coordinate(int rx, int tx) +{ + //driver report x y with range 0 - 255 , we scale it up to x/y pixel + gest_pt_x[gest_pt_cnt] = rx*(ic_data->HX_X_RES)/255; + gest_pt_y[gest_pt_cnt] = tx*(ic_data->HX_Y_RES)/255; +} +#endif +static int himax_parse_wake_event(struct himax_ts_data *ts) +{ + uint8_t buf[64]; + unsigned char check_sum_cal = 0; +#ifdef HX_GESTURE_TRACK + int tmp_max_x=0x00,tmp_min_x=0xFFFF,tmp_max_y=0x00,tmp_min_y=0xFFFF; + int gest_len; +#endif + int i=0, check_FC = 0, gesture_flag = 0; + + himax_burst_enable(ts->client, 0); + himax_read_event_stack(ts->client,buf,56); + + for(i=0;igest_pt_x[i]) + tmp_min_x=gest_pt_x[i]; + if(tmp_max_ygest_pt_y[i]) + tmp_min_y=gest_pt_y[i]; + } + I("gest_point x_min= %d, x_max= %d, y_min= %d, y_max= %d\n",tmp_min_x,tmp_max_x,tmp_min_y,tmp_max_y); + gest_start_x=gest_pt_x[0]; + gn_gesture_coor[0] = gest_start_x; + gest_start_y=gest_pt_y[0]; + gn_gesture_coor[1] = gest_start_y; + gest_end_x=gest_pt_x[gest_pt_cnt-1]; + gn_gesture_coor[2] = gest_end_x; + gest_end_y=gest_pt_y[gest_pt_cnt-1]; + gn_gesture_coor[3] = gest_end_y; + gest_width = tmp_max_x - tmp_min_x; + gn_gesture_coor[4] = gest_width; + gest_height = tmp_max_y - tmp_min_y; + gn_gesture_coor[5] = gest_height; + gest_mid_x = (tmp_max_x + tmp_min_x)/2; + gn_gesture_coor[6] = gest_mid_x; + gest_mid_y = (tmp_max_y + tmp_min_y)/2; + gn_gesture_coor[7] = gest_mid_y; + gn_gesture_coor[8] = gest_mid_x;//gest_up_x + gn_gesture_coor[9] = gest_mid_y-gest_height/2;//gest_up_y + gn_gesture_coor[10] = gest_mid_x;//gest_down_x + gn_gesture_coor[11] = gest_mid_y+gest_height/2; //gest_down_y + gn_gesture_coor[12] = gest_mid_x-gest_width/2; //gest_left_x + gn_gesture_coor[13] = gest_mid_y; //gest_left_y + gn_gesture_coor[14] = gest_mid_x+gest_width/2; //gest_right_x + gn_gesture_coor[15] = gest_mid_y; //gest_right_y + + } + + } +#endif + if(gesture_flag != 0x80) + { + if(!ts->gesture_cust_en[gesture_flag]) + { + I("%s NOT report customer key \n ",__func__); + return 0;//NOT report customer key + } + } + else + { + if(!ts->gesture_cust_en[0]) + { + I("%s NOT report report double click \n",__func__); + return 0;//NOT report power key + } + } + + if(gesture_flag == 0x80) + return EV_GESTURE_PWR; + else + return gesture_flag; +} + +void himax_wake_check_func(void) +{ + int ret_event = 0, KEY_EVENT = 0; + + ret_event = himax_parse_wake_event(private_ts); + switch (ret_event) { + case EV_GESTURE_PWR: + KEY_EVENT = KEY_POWER; + break; + case EV_GESTURE_01: + KEY_EVENT = KEY_CUST_01; + break; + case EV_GESTURE_02: + KEY_EVENT = KEY_CUST_02; + break; + case EV_GESTURE_03: + KEY_EVENT = KEY_CUST_03; + break; + case EV_GESTURE_04: + KEY_EVENT = KEY_CUST_04; + break; + case EV_GESTURE_05: + KEY_EVENT = KEY_CUST_05; + break; + case EV_GESTURE_06: + KEY_EVENT = KEY_CUST_06; + break; + case EV_GESTURE_07: + KEY_EVENT = KEY_CUST_07; + break; + case EV_GESTURE_08: + KEY_EVENT = KEY_CUST_08; + break; + case EV_GESTURE_09: + KEY_EVENT = KEY_CUST_09; + break; + case EV_GESTURE_10: + KEY_EVENT = KEY_CUST_10; + break; + case EV_GESTURE_11: + KEY_EVENT = KEY_CUST_11; + break; + case EV_GESTURE_12: + KEY_EVENT = KEY_CUST_12; + break; + case EV_GESTURE_13: + KEY_EVENT = KEY_CUST_13; + break; + case EV_GESTURE_14: + KEY_EVENT = KEY_CUST_14; + break; + case EV_GESTURE_15: + KEY_EVENT = KEY_CUST_15; + break; + } + if(ret_event) + { + I(" %s SMART WAKEUP KEY event %x press\n",__func__,KEY_EVENT); + input_report_key(private_ts->input_dev, KEY_EVENT, 1); + input_sync(private_ts->input_dev); + //msleep(100); + I(" %s SMART WAKEUP KEY event %x release\n",__func__,KEY_EVENT); + input_report_key(private_ts->input_dev, KEY_EVENT, 0); + input_sync(private_ts->input_dev); + FAKE_POWER_KEY_SEND=true; +#ifdef HX_GESTURE_TRACK + I("gest_start_x= %d, gest_start_y= %d, gest_end_x= %d, gest_end_y= %d\n",gest_start_x,gest_start_y, + gest_end_x,gest_end_y); + I("gest_width= %d, gest_height= %d, gest_mid_x= %d, gest_mid_y= %d\n",gest_width,gest_height, + gest_mid_x,gest_mid_y); + I("gest_up_x= %d, gest_up_y= %d, gest_down_x= %d, gest_down_y= %d\n",gn_gesture_coor[8],gn_gesture_coor[9], + gn_gesture_coor[10],gn_gesture_coor[11]); + I("gest_left_x= %d, gest_left_y= %d, gest_right_x= %d, gest_right_y= %d\n",gn_gesture_coor[12],gn_gesture_coor[13], + gn_gesture_coor[14],gn_gesture_coor[15]); +#endif + } +} + +#endif +static void himax_ts_button_func(int tp_key_index,struct himax_ts_data *ts) +{ + uint16_t x_position = 0, y_position = 0; +if ( tp_key_index != 0x00) + { + I("virtual key index =%x\n",tp_key_index); + if ( tp_key_index == 0x01) { + vk_press = 1; + I("back key pressed\n"); + if (ts->pdata->virtual_key) + { + if (ts->button[0].index) { + x_position = (ts->button[0].x_range_min + ts->button[0].x_range_max) / 2; + y_position = (ts->button[0].y_range_min + ts->button[0].y_range_max) / 2; + } + if (ts->protocol_type == PROTOCOL_TYPE_A) { + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, + 100); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, + 100); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, + 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, + x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, + y_position); + input_mt_sync(ts->input_dev); + } else if (ts->protocol_type == PROTOCOL_TYPE_B) { + input_mt_slot(ts->input_dev, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, + 1); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, + 100); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, + 100); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, + 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, + x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, + y_position); + } + } + else + input_report_key(ts->input_dev, KEY_BACK, 1); + } + else if ( tp_key_index == 0x02) { + vk_press = 1; + I("home key pressed\n"); + if (ts->pdata->virtual_key) + { + if (ts->button[1].index) { + x_position = (ts->button[1].x_range_min + ts->button[1].x_range_max) / 2; + y_position = (ts->button[1].y_range_min + ts->button[1].y_range_max) / 2; + } + if (ts->protocol_type == PROTOCOL_TYPE_A) { + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, + 100); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, + 100); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, + 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, + x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, + y_position); + input_mt_sync(ts->input_dev); + } else if (ts->protocol_type == PROTOCOL_TYPE_B) { + input_mt_slot(ts->input_dev, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, + 1); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, + 100); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, + 100); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, + 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, + x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, + y_position); + } + } + else + input_report_key(ts->input_dev, KEY_HOME, 1); + } + else if ( tp_key_index == 0x04) { + vk_press = 1; + I("APP_switch key pressed\n"); + if (ts->pdata->virtual_key) + { + if (ts->button[2].index) { + x_position = (ts->button[2].x_range_min + ts->button[2].x_range_max) / 2; + y_position = (ts->button[2].y_range_min + ts->button[2].y_range_max) / 2; + } + if (ts->protocol_type == PROTOCOL_TYPE_A) { + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, + 100); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, + 100); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, + 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, + x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, + y_position); + input_mt_sync(ts->input_dev); + } else if (ts->protocol_type == PROTOCOL_TYPE_B) { + input_mt_slot(ts->input_dev, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, + 1); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, + 100); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, + 100); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, + 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, + x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, + y_position); + } + } + else + input_report_key(ts->input_dev, KEY_F10, 1); + } + input_sync(ts->input_dev); + } +else/*tp_key_index =0x00*/ + { + I("virtual key released\n"); + vk_press = 0; + if (ts->protocol_type == PROTOCOL_TYPE_A) { + input_mt_sync(ts->input_dev); + } + else if (ts->protocol_type == PROTOCOL_TYPE_B) { + input_mt_slot(ts->input_dev, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); + } + input_report_key(ts->input_dev, KEY_BACK, 0); + input_report_key(ts->input_dev, KEY_HOME, 0); + input_report_key(ts->input_dev, KEY_F10, 0); + input_sync(ts->input_dev); + } +} + +void himax_ts_work(struct himax_ts_data *ts) +{ + int ret = 0; + uint8_t finger_num, hw_reset_check[2]; + uint8_t buf[128]; + uint8_t finger_on = 0; + int32_t loop_i; + uint16_t check_sum_cal = 0; + int raw_cnt_max ; + int raw_cnt_rmd ; + int hx_touch_info_size; + uint8_t coordInfoSize = ts->coord_data_size + ts->area_data_size + 4; + +#ifdef HX_TP_PROC_DIAG + int16_t *mutual_data; + int16_t *self_data; + uint8_t diag_cmd; + int i; + int mul_num; + int self_num; + int RawDataLen = 0; + //coordinate dump start + char coordinate_char[15+(ic_data->HX_MAX_PT+5)*2*5+2]; + //coordinate dump end +#endif + + memset(buf, 0x00, sizeof(buf)); + memset(hw_reset_check, 0x00, sizeof(hw_reset_check)); + + raw_cnt_max = ic_data->HX_MAX_PT/4; + raw_cnt_rmd = ic_data->HX_MAX_PT%4; + +#if defined(HX_USB_DETECT2) + himax_cable_detect_func(); +#endif + + if (raw_cnt_rmd != 0x00) //more than 4 fingers + { + RawDataLen = cal_data_len(raw_cnt_rmd, ic_data->HX_MAX_PT, raw_cnt_max); + hx_touch_info_size = (ic_data->HX_MAX_PT+raw_cnt_max+2)*4; + } + else //less than 4 fingers + { + RawDataLen = cal_data_len(raw_cnt_rmd, ic_data->HX_MAX_PT, raw_cnt_max); + hx_touch_info_size = (ic_data->HX_MAX_PT+raw_cnt_max+1)*4; + } + +#ifdef HX_TP_PROC_DIAG + diag_cmd = getDiagCommand(); + if( diag_cmd ){ + ret = read_event_stack(ts->client, buf, 128); + } + else{ + if(touch_monitor_stop_flag != 0){ + ret = read_event_stack(ts->client, buf, 128); + touch_monitor_stop_flag-- ; + } + else{ + ret = read_event_stack(ts->client, buf, hx_touch_info_size); + } + } + + if (!ret) +#else + if(!read_event_stack(ts->client, buf, hx_touch_info_size)) +#endif + { + E("%s: can't read data from chip!\n", __func__); + goto err_workqueue_out; + } + post_read_event_stack(ts->client); +#ifdef HX_ESD_WORKAROUND + for(i = 0; i < hx_touch_info_size; i++) + { + if(buf[i] == 0xED)/*case 1 ESD recovery flow*/ + { + check_sum_cal = 1; + + }else if(buf[i] == 0x00) + { + ESD_00_Flag = 1; + } + else + { + check_sum_cal = 0; + ESD_00_counter = 0; + ESD_00_Flag = 0; + i = hx_touch_info_size; + break; + } + } + if (ESD_00_Flag == 1){ + ESD_00_counter ++; + } + if (ESD_00_counter > 1){ + check_sum_cal = 2; + } + + if (check_sum_cal == 2 && HX_ESD_RESET_ACTIVATE == 0) + { + I("[HIMAX TP MSG]: ESD event checked - ALL Zero.\n"); + ESD_HW_REST(); + return; + } + + if (check_sum_cal == 1 && HX_ESD_RESET_ACTIVATE == 0) + { + I("[HIMAX TP MSG]: ESD event checked - ALL 0xED.\n"); + ESD_HW_REST(); + return; + } + else if (HX_ESD_RESET_ACTIVATE) + { +#ifdef HX_SMART_WAKEUP + queue_delayed_work(ts->himax_smwp_wq, &ts->smwp_work, msecs_to_jiffies(50)); +#endif +#ifdef HX_HIGH_SENSE + queue_delayed_work(ts->himax_hsen_wq, &ts->hsen_work, msecs_to_jiffies(50)); +#endif + HX_ESD_RESET_ACTIVATE = 0;/*drop 1st interrupts after chip reset*/ + I("[HIMAX TP MSG]:%s: Back from reset, ready to serve.\n", __func__); + } +#endif + for (loop_i = 0, check_sum_cal = 0; loop_i < hx_touch_info_size; loop_i++) + check_sum_cal += buf[loop_i]; + + if ((check_sum_cal % 0x100 != 0) ) + { + I("[HIMAX TP MSG] checksum fail : check_sum_cal: 0x%02X\n", check_sum_cal); + return; + } + + if (ts->debug_log_level & BIT(0)) { + I("%s: raw data:\n", __func__); + for (loop_i = 0; loop_i < hx_touch_info_size; loop_i++) { + I("P %d = 0x%2.2X ", loop_i, buf[loop_i]); + if (loop_i % 8 == 7) + I("\n"); + } + } + + //touch monitor raw data fetch +#ifdef HX_TP_PROC_DIAG + diag_cmd = getDiagCommand(); + if (diag_cmd >= 1 && diag_cmd <= 6) + { + //Check 124th byte CRC + if(!diag_check_sum(hx_touch_info_size, buf)) + { + goto bypass_checksum_failed_packet; + } +#ifdef HX_TP_PROC_2T2R + if(Is_2T2R && diag_cmd == 4) + { + mutual_data = getMutualBuffer_2(); + self_data = getSelfBuffer(); + + // initiallize the block number of mutual and self + mul_num = getXChannel_2() * getYChannel_2(); + +#ifdef HX_EN_SEL_BUTTON + self_num = getXChannel_2() + getYChannel_2() + ic_data->HX_BT_NUM; +#else + self_num = getXChannel_2() + getYChannel_2(); +#endif + } + else +#endif + { + mutual_data = getMutualBuffer(); + self_data = getSelfBuffer(); + + // initiallize the block number of mutual and self + mul_num = getXChannel() * getYChannel(); + +#ifdef HX_EN_SEL_BUTTON + self_num = getXChannel() + getYChannel() + ic_data->HX_BT_NUM; +#else + self_num = getXChannel() + getYChannel(); +#endif + } + + diag_parse_raw_data(hx_touch_info_size, RawDataLen, mul_num, self_num, buf, diag_cmd, mutual_data, self_data); + + } + else if (diag_cmd == 7) + { + memcpy(&(diag_coor[0]), &buf[0], 128); + } + //coordinate dump start + if (coordinate_dump_enable == 1) + { + for(i=0; i<(15 + (ic_data->HX_MAX_PT+5)*2*5); i++) + { + coordinate_char[i] = 0x20; + } + coordinate_char[15 + (ic_data->HX_MAX_PT+5)*2*5] = 0xD; + coordinate_char[15 + (ic_data->HX_MAX_PT+5)*2*5 + 1] = 0xA; + } + //coordinate dump end +bypass_checksum_failed_packet: +#endif + EN_NoiseFilter = (buf[HX_TOUCH_INFO_POINT_CNT+2]>>3); + //I("EN_NoiseFilter=%d\n",EN_NoiseFilter); + EN_NoiseFilter = EN_NoiseFilter & 0x01; + //I("EN_NoiseFilter2=%d\n",EN_NoiseFilter); + +#if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON) + tpd_key = (buf[HX_TOUCH_INFO_POINT_CNT+2]>>4); + if (tpd_key == 0x0F)/*All (VK+AA)leave*/ + { + tpd_key = 0x00; + } + //I("[DEBUG] tpd_key: %x\r\n", tpd_key); +#else + tpd_key = 0x00; +#endif + + p_point_num = hx_point_num; + + if (buf[HX_TOUCH_INFO_POINT_CNT] == 0xff) + hx_point_num = 0; + else + hx_point_num= buf[HX_TOUCH_INFO_POINT_CNT] & 0x0f; + + // Touch Point information + if (hx_point_num != 0 ) { + if(vk_press == 0x00) + { + uint16_t old_finger = ts->pre_finger_mask; + ts->pre_finger_mask = 0; + finger_num = buf[coordInfoSize - 4] & 0x0F; + finger_on = 1; + AA_press = 1; + for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { + int base = loop_i * 4; + int x = buf[base] << 8 | buf[base + 1]; + int y = (buf[base + 2] << 8 | buf[base + 3]); + int w = buf[(ts->nFinger_support * 4) + loop_i]; + if(x >= 0 && x <= ts->pdata->abs_x_max && y >= 0 && y <= ts->pdata->abs_y_max){ + finger_num--; + + if ((ts->debug_log_level & BIT(3)) > 0) + { + if (old_finger >> loop_i == 0) + { + if (ts->useScreenRes) + { + I("status: Screen:F:%02d Down, X:%d, Y:%d, W:%d, N:%d\n", + loop_i+1, x * ts->widthFactor >> SHIFTBITS, + y * ts->heightFactor >> SHIFTBITS, w, EN_NoiseFilter); + } + else + { + I("status: Raw:F:%02d Down, X:%d, Y:%d, W:%d, N:%d\n", + loop_i+1, x, y, w, EN_NoiseFilter); + } + } + } + + if (ts->protocol_type == PROTOCOL_TYPE_B) + { + input_mt_slot(ts->input_dev, loop_i); + } + + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, w); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y); + + if (ts->protocol_type == PROTOCOL_TYPE_A) + { + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, loop_i); + input_mt_sync(ts->input_dev); + } + else + { + ts->last_slot = loop_i; + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1); + } + + if (!ts->first_pressed) + { + ts->first_pressed = 1; + I("S1@%d, %d\n", x, y); + } + + ts->pre_finger_data[loop_i][0] = x; + ts->pre_finger_data[loop_i][1] = y; + + + if (ts->debug_log_level & BIT(1)) + I("Finger %d=> X:%d, Y:%d W:%d, Z:%d, F:%d, N:%d\n", + loop_i + 1, x, y, w, w, loop_i + 1, EN_NoiseFilter); + + ts->pre_finger_mask = ts->pre_finger_mask + (1 << loop_i); + + } else { + if (ts->protocol_type == PROTOCOL_TYPE_B) + { + input_mt_slot(ts->input_dev, loop_i); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); + } + + if (loop_i == 0 && ts->first_pressed == 1) + { + ts->first_pressed = 2; + I("E1@%d, %d\n", + ts->pre_finger_data[0][0] , ts->pre_finger_data[0][1]); + } + if ((ts->debug_log_level & BIT(3)) > 0) + { + if (old_finger >> loop_i == 1) + { + if (ts->useScreenRes) + { + I("status: Screen:F:%02d Up, X:%d, Y:%d, N:%d\n", + loop_i+1, ts->pre_finger_data[loop_i][0] * ts->widthFactor >> SHIFTBITS, + ts->pre_finger_data[loop_i][1] * ts->heightFactor >> SHIFTBITS, Last_EN_NoiseFilter); + } + else + { + I("status: Raw:F:%02d Up, X:%d, Y:%d, N:%d\n", + loop_i+1, ts->pre_finger_data[loop_i][0], + ts->pre_finger_data[loop_i][1], Last_EN_NoiseFilter); + } + } + } + } + } + + }else if ((tpd_key_old != 0x00)&&(tpd_key == 0x00)) { + //temp_x[0] = 0xFFFF; + //temp_y[0] = 0xFFFF; + //temp_x[1] = 0xFFFF; + //temp_y[1] = 0xFFFF; + himax_ts_button_func(tpd_key,ts); + finger_on = 0; + } + input_report_key(ts->input_dev, BTN_TOUCH, finger_on); + input_sync(ts->input_dev); + } else if (hx_point_num == 0){ + if(AA_press) + { + // leave event + finger_on = 0; + AA_press = 0; + if (ts->protocol_type == PROTOCOL_TYPE_A) + input_mt_sync(ts->input_dev); + + for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { + if (((ts->pre_finger_mask >> loop_i) & 1) == 1) { + if (ts->protocol_type == PROTOCOL_TYPE_B) { + input_mt_slot(ts->input_dev, loop_i); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); + } + } + } + if (ts->pre_finger_mask > 0) { + for (loop_i = 0; loop_i < ts->nFinger_support && (ts->debug_log_level & BIT(3)) > 0; loop_i++) { + if (((ts->pre_finger_mask >> loop_i) & 1) == 1) { + if (ts->useScreenRes) { + I("status:%X, Screen:F:%02d Up, X:%d, Y:%d, N:%d\n", 0, loop_i+1, ts->pre_finger_data[loop_i][0] * ts->widthFactor >> SHIFTBITS, + ts->pre_finger_data[loop_i][1] * ts->heightFactor >> SHIFTBITS, Last_EN_NoiseFilter); + } else { + I("status:%X, Raw:F:%02d Up, X:%d, Y:%d, N:%d\n",0, loop_i+1, ts->pre_finger_data[loop_i][0],ts->pre_finger_data[loop_i][1], Last_EN_NoiseFilter); + } + } + } + ts->pre_finger_mask = 0; + } + + if (ts->first_pressed == 1) { + ts->first_pressed = 2; + I("E1@%d, %d\n",ts->pre_finger_data[0][0] , ts->pre_finger_data[0][1]); + } + + if (ts->debug_log_level & BIT(1)) + I("All Finger leave\n"); + + } + else if (tpd_key != 0x00) { + himax_ts_button_func(tpd_key,ts); + finger_on = 1; + } + else if ((tpd_key_old != 0x00)&&(tpd_key == 0x00)) { + himax_ts_button_func(tpd_key,ts); + finger_on = 0; + } + input_report_key(ts->input_dev, BTN_TOUCH, finger_on); + input_sync(ts->input_dev); + } + tpd_key_old = tpd_key; + Last_EN_NoiseFilter = EN_NoiseFilter; + +workqueue_out: + return; + +err_workqueue_out: + I("%s: Now reset the Touch chip.\n", __func__); + +#ifdef HX_RST_PIN_FUNC + himax_HW_reset(true,false); +#endif + + goto workqueue_out; +} +enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer) +{ + struct himax_ts_data *ts; + + ts = container_of(timer, struct himax_ts_data, timer); + queue_work(ts->himax_wq, &ts->work); + hrtimer_start(&ts->timer, ktime_set(0, 12500000), HRTIMER_MODE_REL); + return HRTIMER_NORESTART; +} + +#if defined(HX_USB_DETECT) +static void himax_cable_tp_status_handler_func(int connect_status) +{ + struct himax_ts_data *ts; + I("Touch: cable change to %d\n", connect_status); + ts = private_ts; + if (ts->cable_config) { + if (!atomic_read(&ts->suspend_mode)) { + if ((!!connect_status) != ts->usb_connected) { + if (!!connect_status) { + ts->cable_config[1] = 0x01; + ts->usb_connected = 0x01; + } else { + ts->cable_config[1] = 0x00; + ts->usb_connected = 0x00; + } + + i2c_himax_master_write(ts->client, ts->cable_config, + sizeof(ts->cable_config), HIMAX_I2C_RETRY_TIMES); + + I("%s: Cable status change: 0x%2.2X\n", __func__, ts->cable_config[1]); + } else + I("%s: Cable status is the same as previous one, ignore.\n", __func__); + } else { + if (connect_status) + ts->usb_connected = 0x01; + else + ts->usb_connected = 0x00; + I("%s: Cable status remembered: 0x%2.2X\n", __func__, ts->usb_connected); + } + } +} + +static struct t_cable_status_notifier himax_cable_status_handler = { + .name = "usb_tp_connected", + .func = himax_cable_tp_status_handler_func, +}; + +#endif + +#if defined(HX_USB_DETECT2) +void himax_cable_detect_func(void) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[128]; + struct himax_ts_data *ts; + u32 connect_status = 0; + + connect_status = USB_Flag;//upmu_is_chr_det(); + ts = private_ts; + //I("Touch: cable status=%d, cable_config=%p, usb_connected=%d \n", connect_status,ts->cable_config, ts->usb_connected); + if (ts->cable_config) { + if ((!!connect_status) != ts->usb_connected) { + //notify USB plug/unplug + // 0x9008_8060 ==> 0x0000_0000/0001 + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x60; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; + + if (!!connect_status) { + tmp_data[0] = 0x01; + ts->usb_connected = 0x01; + } else { + tmp_data[0] = 0x00; + ts->usb_connected = 0x00; + } + + himax_flash_write_burst(ts->client, tmp_addr, tmp_data); + + I("%s: Cable status change: 0x%2.2X\n", __func__, ts->usb_connected); + } + //else + //I("%s: Cable status is the same as previous one, ignore.\n", __func__); + } +} +#endif + +#ifdef CONFIG_FB +int himax_fb_register(struct himax_ts_data *ts) +{ + int ret = 0; + + I(" %s in", __func__); + ts->fb_notif.notifier_call = fb_notifier_callback; + ret = fb_register_client(&ts->fb_notif); + if (ret) + E(" Unable to register fb_notifier: %d\n", ret); + + return ret; +} +#endif + +#ifdef HX_SMART_WAKEUP +void himax_set_SMWP_func(struct i2c_client *client,uint8_t SMWP_enable) +{ + uint8_t tmp_data[4]; + + if(SMWP_enable) + { + SMWP_bit_retry: + himax_set_SMWP_enable(client, SMWP_enable); + msleep(20); + himax_get_SMWP_enable(client,tmp_data); + I("%s: Read SMWP bit data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__ + ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]); + if(tmp_data[0]!= 0x01) + { + I("%s: retry SMWP bit write data[0]=%x \n",__func__,tmp_data[0]); + goto SMWP_bit_retry; + } + } +} + +static void himax_SMWP_work(struct work_struct *work) +{ + struct himax_ts_data *ts = container_of(work, struct himax_ts_data, + smwp_work.work); + I(" %s in", __func__); + + himax_set_SMWP_func(ts->client,ts->SMWP_enable); + +} +#endif + +#ifdef HX_TP_PROC_FLASH_DUMP +static void himax_ts_flash_work_func(struct work_struct *work) +{ + himax_ts_flash_func(); +} +#endif + +#ifdef HX_TP_PROC_DIAG +static void himax_ts_diag_work_func(struct work_struct *work) +{ + himax_ts_diag_func(); +} +#endif + +void himax_ts_init(struct himax_ts_data *ts) +{ + int ret = 0, err = 0; + struct himax_i2c_platform_data *pdata; + struct i2c_client *client; + + client = ts->client; + pdata = ts->pdata; + + I("%s: Start.\n", __func__); + + /* Set pinctrl in active state */ + if (ts->ts_pinctrl) { + ret = pinctrl_select_state(ts->ts_pinctrl, + ts->pinctrl_state_active); + if (ret < 0) { + E("Failed to set pin in active state %d",ret); + } + } + + himax_burst_enable(client, 0); + + //Get Himax IC Type / FW information / Calculate the point number + if (himax_check_chip_version(ts->client) == false) { + E("Himax chip doesn NOT EXIST"); + goto err_ic_package_failed; + } + if (himax_ic_package_check(ts->client) == false) { + E("Himax chip doesn NOT EXIST"); + goto err_ic_package_failed; + } + + if (pdata->virtual_key) + ts->button = pdata->virtual_key; +#ifdef HX_TP_PROC_FLASH_DUMP + ts->flash_wq = create_singlethread_workqueue("himax_flash_wq"); + if (!ts->flash_wq) + { + E("%s: create flash workqueue failed\n", __func__); + err = -ENOMEM; + goto err_create_wq_failed; + } + + INIT_WORK(&ts->flash_work, himax_ts_flash_work_func); + + setSysOperation(0); + setFlashBuffer(); +#endif + +#ifdef HX_TP_PROC_DIAG + ts->himax_diag_wq = create_singlethread_workqueue("himax_diag"); + if (!ts->himax_diag_wq) + { + E("%s: create diag workqueue failed\n", __func__); + err = -ENOMEM; + goto err_create_wq_failed; + } + INIT_DELAYED_WORK(&ts->himax_diag_delay_wrok, himax_ts_diag_work_func); +#endif + +himax_read_FW_ver(client); + +#ifdef HX_AUTO_UPDATE_FW + I(" %s in", __func__); + if(i_update_FW() == false) + I("NOT Have new FW=NOT UPDATE=\n"); + else + I("Have new FW=UPDATE=\n"); +#endif + + //Himax Power On and Load Config + if (himax_loadSensorConfig(client, pdata) < 0) { + E("%s: Load Sesnsor configuration failed, unload driver.\n", __func__); + goto err_detect_failed; + } + + calculate_point_number(); +#ifdef HX_TP_PROC_DIAG + setXChannel(ic_data->HX_RX_NUM); // X channel + setYChannel(ic_data->HX_TX_NUM); // Y channel + + setMutualBuffer(); + setMutualNewBuffer(); + setMutualOldBuffer(); + if (getMutualBuffer() == NULL) { + E("%s: mutual buffer allocate fail failed\n", __func__); + return; + } +#ifdef HX_TP_PROC_2T2R + if(Is_2T2R){ + setXChannel_2(ic_data->HX_RX_NUM_2); // X channel + setYChannel_2(ic_data->HX_TX_NUM_2); // Y channel + + setMutualBuffer_2(); + + if (getMutualBuffer_2() == NULL) { + E("%s: mutual buffer 2 allocate fail failed\n", __func__); + return; + } + } +#endif +#endif +#ifdef CONFIG_OF + ts->power = pdata->power; +#endif + ts->pdata = pdata; + + ts->x_channel = ic_data->HX_RX_NUM; + ts->y_channel = ic_data->HX_TX_NUM; + ts->nFinger_support = ic_data->HX_MAX_PT; + //calculate the i2c data size + calcDataSize(ts->nFinger_support); + I("%s: calcDataSize complete\n", __func__); +#ifdef CONFIG_OF + ts->pdata->abs_pressure_min = 0; + ts->pdata->abs_pressure_max = 200; + ts->pdata->abs_width_min = 0; + ts->pdata->abs_width_max = 200; + pdata->cable_config[0] = 0x90; + pdata->cable_config[1] = 0x00; +#endif + ts->suspended = false; +#if defined(HX_USB_DETECT)||defined(HX_USB_DETECT2) + ts->usb_connected = 0x00; + ts->cable_config = pdata->cable_config; +#endif + ts->protocol_type = pdata->protocol_type; + I("%s: Use Protocol Type %c\n", __func__, + ts->protocol_type == PROTOCOL_TYPE_A ? 'A' : 'B'); + + ret = himax_input_register(ts); + if (ret) { + E("%s: Unable to register %s input device\n", + __func__, ts->input_dev->name); + goto err_input_register_device_failed; + } +#ifdef HX_SMART_WAKEUP + ts->SMWP_enable=0; + wake_lock_init(&ts->ts_SMWP_wake_lock, WAKE_LOCK_SUSPEND, HIMAX_common_NAME); + + ts->himax_smwp_wq = create_singlethread_workqueue("HMX_SMWP_WORK"); + if (!ts->himax_smwp_wq) { + E(" allocate himax_smwp_wq failed\n"); + err = -ENOMEM; + goto err_smwp_wq_failed; + } + INIT_DELAYED_WORK(&ts->smwp_work, himax_SMWP_work); +#endif +#ifdef HX_HIGH_SENSE + ts->HSEN_enable=0; + ts->himax_hsen_wq = create_singlethread_workqueue("HMX_HSEN_WORK"); + if (!ts->himax_hsen_wq) { + E(" allocate himax_hsen_wq failed\n"); + err = -ENOMEM; + goto err_hsen_wq_failed; + } + INIT_DELAYED_WORK(&ts->hsen_work, himax_HSEN_func); +#endif + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) + himax_touch_proc_init(); +#endif + +#if defined(HX_USB_DETECT) + if (ts->cable_config) + cable_detect_register_notifier(&himax_cable_status_handler); +#endif + + err = himax_ts_register_interrupt(ts->client); + if (err) + goto err_register_interrupt_failed; + return; + +err_register_interrupt_failed: +#ifdef HX_HIGH_SENSE +err_hsen_wq_failed: +#endif +#ifdef HX_SMART_WAKEUP +err_smwp_wq_failed: + wake_lock_destroy(&ts->ts_SMWP_wake_lock); +#endif +err_input_register_device_failed: + input_free_device(ts->input_dev); +err_detect_failed: +#ifdef HX_TP_PROC_FLASH_DUMP +err_create_wq_failed: +#endif +err_ic_package_failed: + +return; +} + +int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int err = 0; + struct himax_ts_data *ts; + struct himax_i2c_platform_data *pdata; + + //Check I2C functionality + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + E("%s: i2c check functionality error\n", __func__); + err = -ENODEV; + goto err_check_functionality_failed; + } + + ts = kzalloc(sizeof(struct himax_ts_data), GFP_KERNEL); + if (ts == NULL) { + E("%s: allocate himax_ts_data failed\n", __func__); + err = -ENOMEM; + goto err_alloc_data_failed; + } + + i2c_set_clientdata(client, ts); + ts->client = client; + ts->dev = &client->dev; + + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (pdata == NULL) { /*Allocate Platform data space*/ + err = -ENOMEM; + goto err_dt_platform_data_fail; + } + + ic_data = kzalloc(sizeof(*ic_data), GFP_KERNEL); + if (ic_data == NULL) { /*Allocate IC data space*/ + err = -ENOMEM; + goto err_dt_ic_data_fail; + } + +#ifdef CONFIG_OF + if (client->dev.of_node) { /*DeviceTree Init Platform_data*/ + err = himax_parse_dt(ts, pdata); + if (err < 0) { + I(" pdata is NULL for DT\n"); + goto err_alloc_dt_pdata_failed; + } + } +#endif + +#ifdef HX_RST_PIN_FUNC + ts->rst_gpio = pdata->gpio_reset; +#endif + +himax_gpio_power_config(ts->client, pdata); + + err = himax_ts_pinctrl_init(ts); + if (err || ts->ts_pinctrl == NULL) { + E(" Pinctrl init failed\n"); + } + +#ifndef CONFIG_OF + if (pdata->power) { + err = pdata->power(1); + if (err < 0) { + E("%s: power on failed\n", __func__); + goto err_power_failed; + } + } +#endif + ts->pdata = pdata; + private_ts = ts; + + mutex_init(&ts->fb_mutex); + /* ts initialization is deferred till FB_UNBLACK event; + * probe is considered pending till then.*/ + ts->probe_done = false; +#ifdef CONFIG_FB + err = himax_fb_register(ts); + if (err) { + E("Falied to register fb notifier\n"); + err = -ENOMEM; + goto err_fb_notif_wq_create; + } +#endif + + return 0; + +#ifdef CONFIG_FB +err_fb_notif_wq_create: +#endif +#ifdef CONFIG_OF +err_alloc_dt_pdata_failed: +#else +err_power_failed: +err_get_platform_data_fail: +#endif + if (ts->ts_pinctrl) { + if (IS_ERR_OR_NULL(ts->pinctrl_state_release)) { + devm_pinctrl_put(ts->ts_pinctrl); + ts->ts_pinctrl = NULL; + } else { + err = pinctrl_select_state(ts->ts_pinctrl, + ts->pinctrl_state_release); + if (err) + E("failed to select relase pinctrl state %d\n", + err); + } + } + kfree(ic_data); + +err_dt_ic_data_fail: + kfree(pdata); + +err_dt_platform_data_fail: + kfree(ts); + +err_alloc_data_failed: + +err_check_functionality_failed: + probe_fail_flag = 1; + return err; + +} + +int himax_chip_common_remove(struct i2c_client *client) +{ + struct himax_ts_data *ts = i2c_get_clientdata(client); + int ret; +#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) + himax_touch_proc_deinit(); +#endif +#ifdef CONFIG_FB + if (fb_unregister_client(&ts->fb_notif)) + dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n"); +#endif + + if (!ts->use_irq) + hrtimer_cancel(&ts->timer); + + destroy_workqueue(ts->himax_wq); + + if (ts->protocol_type == PROTOCOL_TYPE_B) + input_mt_destroy_slots(ts->input_dev); + + input_unregister_device(ts->input_dev); + + if (ts->ts_pinctrl) { + if (IS_ERR_OR_NULL(ts->pinctrl_state_release)) { + devm_pinctrl_put(ts->ts_pinctrl); + ts->ts_pinctrl = NULL; + } else { + ret = pinctrl_select_state(ts->ts_pinctrl, + ts->pinctrl_state_release); + if (ret) + E("failed to select relase pinctrl state %d\n", + ret); + } + } +#ifdef HX_SMART_WAKEUP + wake_lock_destroy(&ts->ts_SMWP_wake_lock); +#endif + kfree(ts); + + return 0; + +} + +int himax_chip_common_suspend(struct himax_ts_data *ts) +{ + int ret; + + if(ts->suspended) + { + I("%s: Already suspended. Skipped. \n", __func__); + return 0; + } + else + { + ts->suspended = true; + I("%s: enter \n", __func__); + } + +#ifdef HX_TP_PROC_FLASH_DUMP + if (getFlashDumpGoing()) + { + I("[himax] %s: Flash dump is going, reject suspend\n",__func__); + return 0; + } +#endif +#ifdef HX_TP_PROC_HITOUCH + if(hitouch_is_connect) + { + I("[himax] %s: Hitouch connect, reject suspend\n",__func__); + return 0; + } +#endif +#ifdef HX_SMART_WAKEUP + if(ts->SMWP_enable) + { + atomic_set(&ts->suspend_mode, 1); + ts->pre_finger_mask = 0; + FAKE_POWER_KEY_SEND=false; + I("[himax] %s: SMART_WAKEUP enable, reject suspend\n",__func__); + return 0; + } +#endif +#ifdef HX_ESD_WORKAROUND + ESD_00_counter = 0; + ESD_00_Flag = 0; +#endif + if (!ts->use_irq) { + ret = cancel_work_sync(&ts->work); + if (ret) + himax_int_enable(ts->client->irq,1); + } + + //ts->first_pressed = 0; + atomic_set(&ts->suspend_mode, 1); + ts->pre_finger_mask = 0; + + if (ts->ts_pinctrl) { + ret = pinctrl_select_state(ts->ts_pinctrl, + ts->pinctrl_state_suspend); + if (ret < 0) { + E("Failed to get idle pinctrl state %d\n", ret); + } + } + + if (ts->pdata->powerOff3V3 && ts->pdata->power) + ts->pdata->power(0); + + return 0; +} + +int himax_chip_common_resume(struct himax_ts_data *ts) +{ + int retval; + + I("%s: enter \n", __func__); + + if (ts->pdata->powerOff3V3 && ts->pdata->power) + ts->pdata->power(1); + + + /*************************************/ + if (ts->protocol_type == PROTOCOL_TYPE_A) + input_mt_sync(ts->input_dev); + input_report_key(ts->input_dev, BTN_TOUCH, 0); + input_sync(ts->input_dev); + /*************************************/ + + + if (ts->ts_pinctrl) { + retval = pinctrl_select_state(ts->ts_pinctrl, + ts->pinctrl_state_active); + if (retval < 0) { + E("Cannot get default pinctrl state %d\n", retval); + goto err_pinctrl_select_resume; + } + } + + atomic_set(&ts->suspend_mode, 0); + + himax_int_enable(ts->client->irq,1); + + ts->suspended = false; +#if defined(HX_USB_DETECT2) + ts->usb_connected = 0x00; + himax_cable_detect_func(); +#endif +#ifdef HX_SMART_WAKEUP + queue_delayed_work(ts->himax_smwp_wq, &ts->smwp_work, msecs_to_jiffies(1000)); +#endif +#ifdef HX_HIGH_SENSE + queue_delayed_work(ts->himax_hsen_wq, &ts->hsen_work, msecs_to_jiffies(1000)); +#endif + return 0; +err_pinctrl_select_resume: + if (ts->pdata->powerOff3V3 && ts->pdata->power) + ts->pdata->power(0); + return retval; +} + diff --git a/drivers/input/touchscreen/hxchipset/himax_common.h b/drivers/input/touchscreen/hxchipset/himax_common.h new file mode 100644 index 0000000000000..27ce9aafd959c --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_common.h @@ -0,0 +1,395 @@ +/* Himax Android Driver Sample Code for Himax chipset +* +* Copyright (C) 2015 Himax Corporation. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#ifndef HIMAX_COMMON_H +#define HIMAX_COMMON_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "himax_platform.h" + +#if defined(CONFIG_FB) +#include +#include +#elif defined(CONFIG_HAS_EARLYSUSPEND) +#include +#endif + +#ifdef CONFIG_OF +#include +#endif +#define HIMAX_DRIVER_VER "0.2.4.0" + +#define FLASH_DUMP_FILE "/data/user/Flash_Dump.bin" +#define DIAG_COORDINATE_FILE "/sdcard/Coordinate_Dump.csv" + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) + +#define HX_TP_PROC_DIAG +#define HX_TP_PROC_REGISTER +#define HX_TP_PROC_DEBUG +#define HX_TP_PROC_FLASH_DUMP +#define HX_TP_PROC_SELF_TEST +#define HX_TP_PROC_RESET +#define HX_TP_PROC_SENSE_ON_OFF +//#define HX_TP_PROC_2T2R + +int himax_touch_proc_init(void); +void himax_touch_proc_deinit(void); +#endif + +//===========Himax Option function============= +//#define HX_RST_PIN_FUNC +//#define HX_AUTO_UPDATE_FW +//#define HX_HIGH_SENSE +//#define HX_SMART_WAKEUP +//#define HX_USB_DETECT +//#define HX_ESD_WORKAROUND +//#define HX_USB_DETECT2 + +//#define HX_EN_SEL_BUTTON // Support Self Virtual key ,default is close +#define HX_EN_MUT_BUTTON // Support Mutual Virtual Key ,default is close + +#define HX_KEY_MAX_COUNT 4 +#define DEFAULT_RETRY_CNT 3 + +#define HX_VKEY_0 KEY_BACK +#define HX_VKEY_1 KEY_HOME +#define HX_VKEY_2 KEY_RESERVED +#define HX_VKEY_3 KEY_RESERVED +#define HX_KEY_ARRAY {HX_VKEY_0, HX_VKEY_1, HX_VKEY_2, HX_VKEY_3} + +#define SHIFTBITS 5 +//#define FLASH_SIZE 131072 +#define FW_SIZE_60k 61440 +#define FW_SIZE_64k 65536 +#define FW_SIZE_124k 126976 +#define FW_SIZE_128k 131072 + +struct himax_ic_data { + int vendor_fw_ver; + int vendor_config_ver; + int vendor_sensor_id; + int HX_RX_NUM; + int HX_TX_NUM; + int HX_BT_NUM; + int HX_X_RES; + int HX_Y_RES; + int HX_MAX_PT; + bool HX_XY_REVERSE; + bool HX_INT_IS_EDGE; +#ifdef HX_TP_PROC_2T2R + int HX_RX_NUM_2; + int HX_TX_NUM_2; +#endif +}; + +struct himax_virtual_key { + int index; + int keycode; + int x_range_min; + int x_range_max; + int y_range_min; + int y_range_max; +}; + +struct himax_config { + uint8_t default_cfg; + uint8_t sensor_id; + uint8_t fw_ver; + uint16_t length; + uint32_t tw_x_min; + uint32_t tw_x_max; + uint32_t tw_y_min; + uint32_t tw_y_max; + uint32_t pl_x_min; + uint32_t pl_x_max; + uint32_t pl_y_min; + uint32_t pl_y_max; + uint8_t c1[11]; + uint8_t c2[11]; + uint8_t c3[11]; + uint8_t c4[11]; + uint8_t c5[11]; + uint8_t c6[11]; + uint8_t c7[11]; + uint8_t c8[11]; + uint8_t c9[11]; + uint8_t c10[11]; + uint8_t c11[11]; + uint8_t c12[11]; + uint8_t c13[11]; + uint8_t c14[11]; + uint8_t c15[11]; + uint8_t c16[11]; + uint8_t c17[11]; + uint8_t c18[17]; + uint8_t c19[15]; + uint8_t c20[5]; + uint8_t c21[11]; + uint8_t c22[4]; + uint8_t c23[3]; + uint8_t c24[3]; + uint8_t c25[4]; + uint8_t c26[2]; + uint8_t c27[2]; + uint8_t c28[2]; + uint8_t c29[2]; + uint8_t c30[2]; + uint8_t c31[2]; + uint8_t c32[2]; + uint8_t c33[2]; + uint8_t c34[2]; + uint8_t c35[3]; + uint8_t c36[5]; + uint8_t c37[5]; + uint8_t c38[9]; + uint8_t c39[14]; + uint8_t c40[159]; + uint8_t c41[99]; +}; + +struct himax_ts_data { + bool suspended; + bool probe_done; + struct mutex fb_mutex; + atomic_t suspend_mode; + uint8_t x_channel; + uint8_t y_channel; + uint8_t useScreenRes; + uint8_t diag_command; + + uint8_t protocol_type; + uint8_t first_pressed; + uint8_t coord_data_size; + uint8_t area_data_size; + uint8_t raw_data_frame_size; + uint8_t raw_data_nframes; + uint8_t nFinger_support; + uint8_t irq_enabled; + uint8_t diag_self[50]; + + uint16_t finger_pressed; + uint16_t last_slot; + uint16_t pre_finger_mask; + + uint32_t debug_log_level; + uint32_t widthFactor; + uint32_t heightFactor; + uint32_t tw_x_min; + uint32_t tw_x_max; + uint32_t tw_y_min; + uint32_t tw_y_max; + uint32_t pl_x_min; + uint32_t pl_x_max; + uint32_t pl_y_min; + uint32_t pl_y_max; + + int use_irq; + int (*power)(int on); + int pre_finger_data[10][2]; + + struct device *dev; + struct workqueue_struct *himax_wq; + struct work_struct work; + struct input_dev *input_dev; + struct hrtimer timer; + struct i2c_client *client; + struct himax_i2c_platform_data *pdata; + struct himax_virtual_key *button; + +#if defined(CONFIG_FB) + struct notifier_block fb_notif; +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif + +#ifdef HX_TP_PROC_FLASH_DUMP + struct workqueue_struct *flash_wq; + struct work_struct flash_work; +#endif + +#ifdef HX_RST_PIN_FUNC + int rst_gpio; +#endif + +#ifdef HX_TP_PROC_DIAG + struct workqueue_struct *himax_diag_wq; + struct delayed_work himax_diag_delay_wrok; +#endif +#ifdef HX_SMART_WAKEUP + uint8_t SMWP_enable; + uint8_t gesture_cust_en[16]; + struct wake_lock ts_SMWP_wake_lock; + struct workqueue_struct *himax_smwp_wq; + struct delayed_work smwp_work; +#endif + +#ifdef HX_HIGH_SENSE + uint8_t HSEN_enable; + struct workqueue_struct *himax_hsen_wq; + struct delayed_work hsen_work; +#endif + +#if defined(HX_USB_DETECT)||defined(HX_USB_DETECT2) + uint8_t usb_connected; + uint8_t *cable_config; +#endif + + /* pinctrl data */ + struct pinctrl *ts_pinctrl; + struct pinctrl_state *pinctrl_state_active; + struct pinctrl_state *pinctrl_state_suspend; + struct pinctrl_state *pinctrl_state_release; +}; + +#define HX_CMD_NOP 0x00 +#define HX_CMD_SETMICROOFF 0x35 +#define HX_CMD_SETROMRDY 0x36 +#define HX_CMD_TSSLPIN 0x80 +#define HX_CMD_TSSLPOUT 0x81 +#define HX_CMD_TSSOFF 0x82 +#define HX_CMD_TSSON 0x83 +#define HX_CMD_ROE 0x85 +#define HX_CMD_RAE 0x86 +#define HX_CMD_RLE 0x87 +#define HX_CMD_CLRES 0x88 +#define HX_CMD_TSSWRESET 0x9E +#define HX_CMD_SETDEEPSTB 0xD7 +#define HX_CMD_SET_CACHE_FUN 0xDD +#define HX_CMD_SETIDLE 0xF2 +#define HX_CMD_SETIDLEDELAY 0xF3 +#define HX_CMD_SELFTEST_BUFFER 0x8D +#define HX_CMD_MANUALMODE 0x42 +#define HX_CMD_FLASH_ENABLE 0x43 +#define HX_CMD_FLASH_SET_ADDRESS 0x44 +#define HX_CMD_FLASH_WRITE_REGISTER 0x45 +#define HX_CMD_FLASH_SET_COMMAND 0x47 +#define HX_CMD_FLASH_WRITE_BUFFER 0x48 +#define HX_CMD_FLASH_PAGE_ERASE 0x4D +#define HX_CMD_FLASH_SECTOR_ERASE 0x4E +#define HX_CMD_CB 0xCB +#define HX_CMD_EA 0xEA +#define HX_CMD_4A 0x4A +#define HX_CMD_4F 0x4F +#define HX_CMD_B9 0xB9 +#define HX_CMD_76 0x76 + +enum input_protocol_type { + PROTOCOL_TYPE_A = 0x00, + PROTOCOL_TYPE_B = 0x01, +}; + +#ifdef HX_HIGH_SENSE +void himax_set_HSEN_func(struct i2c_client *client,uint8_t HSEN_enable); +#endif + +#ifdef HX_SMART_WAKEUP +#define GEST_PTLG_ID_LEN (4) +#define GEST_PTLG_HDR_LEN (4) +#define GEST_PTLG_HDR_ID1 (0xCC) +#define GEST_PTLG_HDR_ID2 (0x44) +#define GEST_PT_MAX_NUM (128) + +#ifdef HX_GESTURE_TRACK +static int gest_pt_cnt; +static int gest_pt_x[GEST_PT_MAX_NUM]; +static int gest_pt_y[GEST_PT_MAX_NUM]; +static int gest_start_x,gest_start_y,gest_end_x,gest_end_y; +static int gest_width,gest_height,gest_mid_x,gest_mid_y; +static int gn_gesture_coor[16]; +#endif + +void himax_set_SMWP_func(struct i2c_client *client,uint8_t SMWP_enable); +extern bool FAKE_POWER_KEY_SEND; + + enum gesture_event_type { + EV_GESTURE_01 = 0x01, + EV_GESTURE_02, + EV_GESTURE_03, + EV_GESTURE_04, + EV_GESTURE_05, + EV_GESTURE_06, + EV_GESTURE_07, + EV_GESTURE_08, + EV_GESTURE_09, + EV_GESTURE_10, + EV_GESTURE_11, + EV_GESTURE_12, + EV_GESTURE_13, + EV_GESTURE_14, + EV_GESTURE_15, + EV_GESTURE_PWR = 0x80, + }; + +#define KEY_CUST_01 251 +#define KEY_CUST_02 252 +#define KEY_CUST_03 253 +#define KEY_CUST_04 254 +#define KEY_CUST_05 255 +#define KEY_CUST_06 256 +#define KEY_CUST_07 257 +#define KEY_CUST_08 258 +#define KEY_CUST_09 259 +#define KEY_CUST_10 260 +#define KEY_CUST_11 261 +#define KEY_CUST_12 262 +#define KEY_CUST_13 263 +#define KEY_CUST_14 264 +#define KEY_CUST_15 265 +#endif + +#ifdef HX_ESD_WORKAROUND + extern u8 HX_ESD_RESET_ACTIVATE; +#endif + +extern int irq_enable_count; + +#ifdef QCT +irqreturn_t himax_ts_thread(int irq, void *ptr); +int himax_input_register(struct himax_ts_data *ts); +#endif + +extern int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_id *id); +extern int himax_chip_common_remove(struct i2c_client *client); +extern int himax_chip_common_suspend(struct himax_ts_data *ts); +extern int himax_chip_common_resume(struct himax_ts_data *ts); +int himax_loadSensorConfig(struct i2c_client *client, struct himax_i2c_platform_data *pdata); + +#ifdef HX_USB_DETECT2 +//extern kal_bool upmu_is_chr_det(void); +void himax_cable_detect_func(void); +#endif + +#endif + diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.c b/drivers/input/touchscreen/hxchipset/himax_debug.c new file mode 100644 index 0000000000000..f8bee11b43515 --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_debug.c @@ -0,0 +1,2329 @@ +/* Himax Android Driver Sample Code for Himax chipset +* +* Copyright (C) 2015 Himax Corporation. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#include "himax_debug.h" +#include "himax_ic.h" + +//struct himax_debug_data* debug_data; + +extern struct himax_ic_data* ic_data; +extern struct himax_ts_data *private_ts; +extern unsigned char IC_TYPE; +extern unsigned char IC_CHECKSUM; +extern int himax_input_register(struct himax_ts_data *ts); +#ifdef QCT +extern irqreturn_t himax_ts_thread(int irq, void *ptr); +#endif +#ifdef MTK +#ifdef CONFIG_OF_TOUCH +extern irqreturn_t tpd_eint_interrupt_handler(int irq, void *desc); +#else +extern void tpd_eint_interrupt_handler(void); +#endif +#endif + +#ifdef HX_TP_PROC_DIAG +#ifdef HX_TP_PROC_2T2R +int HX_RX_NUM_2 = 0; +int HX_TX_NUM_2 = 0; +#endif +int touch_monitor_stop_flag = 0; +int touch_monitor_stop_limit = 5; +uint8_t g_diag_arr_num = 0; +#endif + +#ifdef HX_ESD_WORKAROUND +u8 HX_ESD_RESET_ACTIVATE; +#endif + +#ifdef HX_SMART_WAKEUP +bool FAKE_POWER_KEY_SEND; +#endif + +//============================================================================================================= +// +// Segment : Himax PROC Debug Function +// +//============================================================================================================= +#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) + +static ssize_t himax_vendor_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + ssize_t ret = 0; + char *temp_buf; + + if(!HX_PROC_SEND_FLAG) + { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + HX_PROC_SEND_FLAG=0; + return ret; + } + + ret += snprintf(temp_buf, len, "%s_FW:%#x_CFG:%#x_SensorId:%#x\n", HIMAX_common_NAME, + ic_data->vendor_fw_ver, ic_data->vendor_config_ver, ic_data->vendor_sensor_id); + HX_PROC_SEND_FLAG=1; + + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + } + else + HX_PROC_SEND_FLAG=0; + + return ret; +} + +static const struct file_operations himax_proc_vendor_ops = +{ + .owner = THIS_MODULE, + .read = himax_vendor_read, +}; + +static ssize_t himax_attn_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + ssize_t ret = 0; + struct himax_ts_data *ts_data; + char *temp_buf; + + ts_data = private_ts; + + if (!HX_PROC_SEND_FLAG) { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + HX_PROC_SEND_FLAG=0; + return ret; + } + ret += snprintf(temp_buf, len, "attn = %x\n", himax_int_gpio_read(ts_data->pdata->gpio_irq)); + + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } + else + HX_PROC_SEND_FLAG=0; + + return ret; +} + + +static const struct file_operations himax_proc_attn_ops = +{ + .owner = THIS_MODULE, + .read = himax_attn_read, +}; + +static ssize_t himax_int_en_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + size_t ret = 0; + char *temp_buf; + + if (!HX_PROC_SEND_FLAG) { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + HX_PROC_SEND_FLAG=0; + return ret; + } + ret += snprintf(temp_buf, len, "%d ", ts->irq_enabled); + ret += snprintf(temp_buf+ret, len-ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } + else + HX_PROC_SEND_FLAG=0; + return ret; +} + +static ssize_t himax_int_en_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + char buf_tmp[12]= {0}; + int value, ret=0; + + if (len >= 12) + { + I("%s: no command exceeds 12 chars.\n", __func__); + return -EFAULT; + } + if (copy_from_user(buf_tmp, buff, len)) + { + return -EFAULT; + } + + if (buf_tmp[0] == '0') + value = false; + else if (buf_tmp[0] == '1') + value = true; + else + return -EINVAL; + + if (value) { + if(ic_data->HX_INT_IS_EDGE) + { +#ifdef MTK +#ifdef CONFIG_OF_TOUCH + himax_int_enable(ts->client->irq,1); +#else + //mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE); + //mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN); + mt_eint_registration(ts->client->irq, EINTF_TRIGGER_FALLING, tpd_eint_interrupt_handler, 1); +#endif +#endif +#ifdef QCT + ret = request_threaded_irq(ts->client->irq, NULL, himax_ts_thread, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, ts->client->name, ts); +#endif + } + else + { +#ifdef MTK +#ifdef CONFIG_OF_TOUCH + himax_int_enable(ts->client->irq,1); +#else + //mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE); + //mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN); + mt_eint_registration(ts->client->irq, EINTF_TRIGGER_LOW, tpd_eint_interrupt_handler, 1); +#endif +#endif +#ifdef QCT + ret = request_threaded_irq(ts->client->irq, NULL, himax_ts_thread, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, ts->client->name, ts); +#endif + } + if (ret == 0) { + ts->irq_enabled = 1; + irq_enable_count = 1; + } + } else { + himax_int_enable(ts->client->irq,0); + free_irq(ts->client->irq, ts); + ts->irq_enabled = 0; + } + + return len; +} + +static const struct file_operations himax_proc_int_en_ops = +{ + .owner = THIS_MODULE, + .read = himax_int_en_read, + .write = himax_int_en_write, +}; + +static ssize_t himax_layout_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + size_t ret = 0; + char *temp_buf; + + if (!HX_PROC_SEND_FLAG) { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + HX_PROC_SEND_FLAG=0; + return ret; + } + ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_x_min); + ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_x_max); + ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_y_min); + ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_y_max); + ret += snprintf(temp_buf+ret, len-ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } + else + HX_PROC_SEND_FLAG=0; + + return ret; +} + +static ssize_t himax_layout_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + char buf_tmp[5]; + int i = 0, j = 0, k = 0, ret; + unsigned long value; + int layout[4] = {0}; + char buf[80] = {0}; + + if (len >= 80) + { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + if (copy_from_user(buf, buff, len)) + { + return -EFAULT; + } + + for (i = 0; i < 20; i++) { + if (buf[i] == ',' || buf[i] == '\n') { + memset(buf_tmp, 0x0, sizeof(buf_tmp)); + if (i - j <= 5) + memcpy(buf_tmp, buf + j, i - j); + else { + I("buffer size is over 5 char\n"); + return len; + } + j = i + 1; + if (k < 4) { + ret = kstrtoul(buf_tmp, 10, &value); + layout[k++] = value; + } + } + } + if (k == 4) { + ts->pdata->abs_x_min=layout[0]; + ts->pdata->abs_x_max=layout[1]; + ts->pdata->abs_y_min=layout[2]; + ts->pdata->abs_y_max=layout[3]; + I("%d, %d, %d, %d\n",ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max); + input_unregister_device(ts->input_dev); + himax_input_register(ts); + } else + I("ERR@%d, %d, %d, %d\n",ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max); + return len; +} + +static const struct file_operations himax_proc_layout_ops = +{ + .owner = THIS_MODULE, + .read = himax_layout_read, + .write = himax_layout_write, +}; + +static ssize_t himax_debug_level_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts_data; + size_t ret = 0; + char *temp_buf; + ts_data = private_ts; + + if (!HX_PROC_SEND_FLAG) { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + HX_PROC_SEND_FLAG=0; + return ret; + } + ret += snprintf(temp_buf, len, "%d\n", ts_data->debug_log_level); + + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } + else + HX_PROC_SEND_FLAG=0; + + return ret; +} + +static ssize_t himax_debug_level_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts; + char buf_tmp[11]; + int i; + ts = private_ts; + + if (len >= 12) + { + I("%s: no command exceeds 12 chars.\n", __func__); + return -EFAULT; + } + if (copy_from_user(buf_tmp, buff, len)) + { + return -EFAULT; + } + + ts->debug_log_level = 0; + for(i=0; i='0' && buf_tmp[i]<='9' ) + ts->debug_log_level |= (buf_tmp[i]-'0'); + else if( buf_tmp[i]>='A' && buf_tmp[i]<='F' ) + ts->debug_log_level |= (buf_tmp[i]-'A'+10); + else if( buf_tmp[i]>='a' && buf_tmp[i]<='f' ) + ts->debug_log_level |= (buf_tmp[i]-'a'+10); + + if(i!=len-2) + ts->debug_log_level <<= 4; + } + + if (ts->debug_log_level & BIT(3)) { + if (ts->pdata->screenWidth > 0 && ts->pdata->screenHeight > 0 && + (ts->pdata->abs_x_max - ts->pdata->abs_x_min) > 0 && + (ts->pdata->abs_y_max - ts->pdata->abs_y_min) > 0) { + ts->widthFactor = (ts->pdata->screenWidth << SHIFTBITS)/(ts->pdata->abs_x_max - ts->pdata->abs_x_min); + ts->heightFactor = (ts->pdata->screenHeight << SHIFTBITS)/(ts->pdata->abs_y_max - ts->pdata->abs_y_min); + if (ts->widthFactor > 0 && ts->heightFactor > 0) + ts->useScreenRes = 1; + else { + ts->heightFactor = 0; + ts->widthFactor = 0; + ts->useScreenRes = 0; + } + } else + I("Enable finger debug with raw position mode!\n"); + } else { + ts->useScreenRes = 0; + ts->widthFactor = 0; + ts->heightFactor = 0; + } + + return len; +} + +static const struct file_operations himax_proc_debug_level_ops = +{ + .owner = THIS_MODULE, + .read = himax_debug_level_read, + .write = himax_debug_level_write, +}; + +#ifdef HX_TP_PROC_REGISTER +static ssize_t himax_proc_register_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + int ret = 0; + uint16_t loop_i; + uint8_t data[128]; + char *temp_buf; + + memset(data, 0x00, sizeof(data)); + + I("himax_register_show: %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]); + if(!HX_PROC_SEND_FLAG) + { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + HX_PROC_SEND_FLAG=0; + return ret; + } + himax_register_read(private_ts->client, register_command, 1, data); + + ret += snprintf(temp_buf, len, "command: %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]); + + for (loop_i = 0; loop_i < 128; loop_i++) { + ret += snprintf(temp_buf+ret, len-ret, "0x%2.2X ", data[loop_i]); + if ((loop_i % 16) == 15) + ret += snprintf(temp_buf+ret, len-ret, "\n"); + } + ret += snprintf(temp_buf+ret, len-ret, "\n"); + HX_PROC_SEND_FLAG=1; + + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + } + else + HX_PROC_SEND_FLAG=0; + return ret; +} + +static ssize_t himax_proc_register_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + char buf_tmp[16], length = 0; + unsigned long result = 0; + uint8_t loop_i = 0; + uint16_t base = 5; + uint8_t write_da[128]; + char buf[80] = {0}; + + if (len >= 80) + { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + if (copy_from_user(buf, buff, len)) + { + return -EFAULT; + } + + memset(buf_tmp, 0x0, sizeof(buf_tmp)); + memset(write_da, 0x0, sizeof(write_da)); + + I("himax %s \n",buf); + + if ((buf[0] == 'r' || buf[0] == 'w') && buf[1] == ':') { + + if (buf[2] == 'x') { + memcpy(buf_tmp, buf + 3, 8); + if (!kstrtoul(buf_tmp, 16, &result)) + { + register_command[0] = (uint8_t)result; + register_command[1] = (uint8_t)(result >> 8); + register_command[2] = (uint8_t)(result >> 16); + register_command[3] = (uint8_t)(result >> 24); + } + base = 11; + I("CMD: %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]); + + for (loop_i = 0; loop_i < 128 && (base+10)<80; loop_i++) { + if (buf[base] == '\n') { + if (buf[0] == 'w') { + himax_register_write(private_ts->client, register_command, 1, write_da); + I("CMD: %x, %x, %x, %x, len=%d\n", write_da[0], write_da[1],write_da[2],write_da[3],length); + } + I("\n"); + return len; + } + if (buf[base + 1] == 'x') { + buf_tmp[10] = '\n'; + buf_tmp[11] = '\0'; + memcpy(buf_tmp, buf + base + 2, 8); + if (!kstrtoul(buf_tmp, 16, &result)) { + write_da[loop_i] = (uint8_t)result; + write_da[loop_i+1] = (uint8_t)(result >> 8); + write_da[loop_i+2] = (uint8_t)(result >> 16); + write_da[loop_i+3] = (uint8_t)(result >> 24); + } + length+=4; + } + base += 10; + } + } + } + return len; +} + +static const struct file_operations himax_proc_register_ops = +{ + .owner = THIS_MODULE, + .read = himax_proc_register_read, + .write = himax_proc_register_write, +}; +#endif + +#ifdef HX_TP_PROC_DIAG +int16_t *getMutualBuffer(void) +{ + return diag_mutual; +} +int16_t *getMutualNewBuffer(void) +{ + return diag_mutual_new; +} +int16_t *getMutualOldBuffer(void) +{ + return diag_mutual_old; +} +int16_t *getSelfBuffer(void) +{ + return &diag_self[0]; +} +uint8_t getXChannel(void) +{ + return x_channel; +} +uint8_t getYChannel(void) +{ + return y_channel; +} +uint8_t getDiagCommand(void) +{ + return diag_command; +} +void setXChannel(uint8_t x) +{ + x_channel = x; +} +void setYChannel(uint8_t y) +{ + y_channel = y; +} +void setMutualBuffer(void) +{ + diag_mutual = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL); +} +void setMutualNewBuffer(void) +{ + diag_mutual_new = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL); +} +void setMutualOldBuffer(void) +{ + diag_mutual_old = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL); +} + +#ifdef HX_TP_PROC_2T2R +int16_t *getMutualBuffer_2(void) +{ + return diag_mutual_2; +} +uint8_t getXChannel_2(void) +{ + return x_channel_2; +} +uint8_t getYChannel_2(void) +{ + return y_channel_2; +} +void setXChannel_2(uint8_t x) +{ + x_channel_2 = x; +} +void setYChannel_2(uint8_t y) +{ + y_channel_2 = y; +} +void setMutualBuffer_2(void) +{ + diag_mutual_2 = kzalloc(x_channel_2 * y_channel_2 * sizeof(int16_t), GFP_KERNEL); +} +#endif + +static ssize_t himax_diag_arrange_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + //struct himax_ts_data *ts = private_ts; + char buf[80] = {0}; + + if (len >= 80) + { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + if (copy_from_user(buf, buff, len)) + { + return -EFAULT; + } + + g_diag_arr_num = buf[0] - '0'; + I("%s: g_diag_arr_num = %d \n", __func__,g_diag_arr_num); + + return len; +} + +static const struct file_operations himax_proc_diag_arrange_ops = +{ + .owner = THIS_MODULE, + .write = himax_diag_arrange_write, +}; + +static void himax_diag_arrange_print(struct seq_file *s, int i, int j, int transpose) +{ + if(transpose) + seq_printf(s, "%6d", diag_mutual[ j + i*x_channel]); + else + seq_printf(s, "%6d", diag_mutual[ i + j*x_channel]); +} + +static void himax_diag_arrange_inloop(struct seq_file *s, int in_init,bool transpose, int j) +{ + int i; + int in_max = 0; + + if(transpose) + in_max = y_channel; + else + in_max = x_channel; + + if (in_init > 0) + { + for(i = in_init-1;i >= 0;i--) + { + himax_diag_arrange_print(s, i, j, transpose); + } + } + else + { + for (i = 0; i < in_max; i++) + { + himax_diag_arrange_print(s, i, j, transpose); + } + } +} + +static void himax_diag_arrange_outloop(struct seq_file *s, int transpose, int out_init, int in_init) +{ + int j; + int out_max = 0; + + if(transpose) + out_max = x_channel; + else + out_max = y_channel; + + if(out_init > 0) + { + for(j = out_init-1;j >= 0;j--) + { + himax_diag_arrange_inloop(s, in_init, transpose, j); + seq_printf(s, " %5d\n", diag_self[j]); + } + } + else + { + for(j = 0;j < out_max;j++) + { + himax_diag_arrange_inloop(s, in_init, transpose, j); + seq_printf(s, " %5d\n", diag_self[j]); + } + } +} + +static void himax_diag_arrange(struct seq_file *s) +{ + int bit2,bit1,bit0; + int i; + + bit2 = g_diag_arr_num >> 2; + bit1 = g_diag_arr_num >> 1 & 0x1; + bit0 = g_diag_arr_num & 0x1; + + if (g_diag_arr_num < 4) + { + himax_diag_arrange_outloop(s, bit2, bit1 * y_channel, bit0 * x_channel); + for (i = y_channel; i < x_channel + y_channel; i++) { + seq_printf(s, "%6d", diag_self[i]); + } + } + else + { + himax_diag_arrange_outloop(s, bit2, bit1 * x_channel, bit0 * y_channel); + for (i = x_channel; i < x_channel + y_channel; i++) { + seq_printf(s, "%6d", diag_self[i]); + } + } +} + +static void *himax_diag_seq_start(struct seq_file *s, loff_t *pos) +{ + if (*pos>=1) return NULL; + return (void *)((unsigned long) *pos+1); +} + +static void *himax_diag_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + return NULL; +} +static void himax_diag_seq_stop(struct seq_file *s, void *v) +{ +} +static int himax_diag_seq_read(struct seq_file *s, void *v) +{ + size_t count = 0; + int32_t loop_i;//,loop_j + uint16_t mutual_num, self_num, width; + +#ifdef HX_TP_PROC_2T2R + if(Is_2T2R && diag_command == 4) + { + mutual_num = x_channel_2 * y_channel_2; + self_num = x_channel_2 + y_channel_2; //don't add KEY_COUNT + width = x_channel_2; + seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_channel_2, y_channel_2); + } + else +#endif + { + mutual_num = x_channel * y_channel; + self_num = x_channel + y_channel; //don't add KEY_COUNT + width = x_channel; + seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_channel, y_channel); + } + + // start to show out the raw data in adb shell + if (diag_command >= 1 && diag_command <= 6) { + if (diag_command <= 3) { + himax_diag_arrange(s); + seq_printf(s, "\n\n"); +#ifdef HX_EN_SEL_BUTTON + seq_printf(s, "\n"); + for (loop_i = 0; loop_i < HX_BT_NUM; loop_i++) + seq_printf(s, "%6d", diag_self[HX_RX_NUM + HX_TX_NUM + loop_i]); +#endif +#ifdef HX_TP_PROC_2T2R + }else if(Is_2T2R && diag_command == 4 ) { + for (loop_i = 0; loop_i < mutual_num; loop_i++) { + seq_printf(s, "%4d", diag_mutual_2[loop_i]); + if ((loop_i % width) == (width - 1)) + seq_printf(s, " %6d\n", diag_self[width + loop_i/width]); + } + seq_printf(s, "\n"); + for (loop_i = 0; loop_i < width; loop_i++) { + seq_printf(s, "%6d", diag_self[loop_i]); + if (((loop_i) % width) == (width - 1)) + seq_printf(s, "\n"); + } +#ifdef HX_EN_SEL_BUTTON + seq_printf(s, "\n"); + for (loop_i = 0; loop_i < HX_BT_NUM; loop_i++) + seq_printf(s, "%4d", diag_self[HX_RX_NUM_2 + HX_TX_NUM_2 + loop_i]); +#endif +#endif + } else if (diag_command > 4) { + for (loop_i = 0; loop_i < self_num; loop_i++) { + seq_printf(s, "%4d", diag_self[loop_i]); + if (((loop_i - mutual_num) % width) == (width - 1)) + seq_printf(s, "\n"); + } + } else { + for (loop_i = 0; loop_i < mutual_num; loop_i++) { + seq_printf(s, "%4d", diag_mutual[loop_i]); + if ((loop_i % width) == (width - 1)) + seq_printf(s, "\n"); + } + } + seq_printf(s, "ChannelEnd"); + seq_printf(s, "\n"); + } else if (diag_command == 7) { + for (loop_i = 0; loop_i < 128 ;loop_i++) { + if ((loop_i % 16) == 0) + seq_printf(s, "LineStart:"); + seq_printf(s, "%4d", diag_coor[loop_i]); + if ((loop_i % 16) == 15) + seq_printf(s, "\n"); + } + } else if (diag_command == 9 || diag_command == 91 || diag_command == 92){ + himax_diag_arrange(s); + seq_printf(s, "\n"); + } + + return count; +} +static const struct seq_operations himax_diag_seq_ops = +{ + .start = himax_diag_seq_start, + .next = himax_diag_seq_next, + .stop = himax_diag_seq_stop, + .show = himax_diag_seq_read, +}; +static int himax_diag_proc_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &himax_diag_seq_ops); +}; +bool DSRAM_Flag; + +//DSRAM thread +void himax_ts_diag_func(void) +{ + int i=0, j=0; + unsigned int index = 0; + int total_size = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM * 2; + uint8_t info_data[total_size]; + int16_t *mutual_data = NULL; + int16_t *mutual_data_new = NULL; + int16_t *mutual_data_old = NULL; + int16_t new_data; + + himax_burst_enable(private_ts->client, 1); + if(diag_command == 9 || diag_command == 91) + { + mutual_data = getMutualBuffer(); + }else if(diag_command == 92){ + mutual_data = getMutualBuffer(); + mutual_data_new = getMutualNewBuffer(); + mutual_data_old = getMutualOldBuffer(); + } + himax_get_DSRAM_data(private_ts->client, info_data); + + index = 0; + for (i = 0; i < ic_data->HX_TX_NUM; i++) + { + for (j = 0; j < ic_data->HX_RX_NUM; j++) + { + new_data = (short)(info_data[index + 1] << 8 | info_data[index]); + if(diag_command == 9){ + mutual_data[i*ic_data->HX_RX_NUM+j] = new_data; + }else if(diag_command == 91){ //Keep max data for 100 frame + if(mutual_data[i * ic_data->HX_RX_NUM + j] < new_data) + mutual_data[i * ic_data->HX_RX_NUM + j] = new_data; + }else if(diag_command == 92){ //Cal data for [N]-[N-1] frame + mutual_data_new[i * ic_data->HX_RX_NUM + j] = new_data; + mutual_data[i * ic_data->HX_RX_NUM + j] = mutual_data_new[i * ic_data->HX_RX_NUM + j] - mutual_data_old[i * ic_data->HX_RX_NUM + j]; + } + index += 2; + } + } + if(diag_command == 92){ + memcpy(mutual_data_old,mutual_data_new,x_channel * y_channel * sizeof(int16_t)); //copy N data to N-1 array + } + diag_max_cnt++; + if(diag_command == 9 || diag_command == 92){ + queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 1/10*HZ); + }else if(diag_command == 91){ + if(diag_max_cnt > 100) //count for 100 frame + { + //Clear DSRAM flag + DSRAM_Flag = false; + + //Enable ISR + himax_int_enable(private_ts->client->irq,1); + + //===================================== + // test result command : 0x8002_0324 ==> 0x00 + //===================================== + himax_diag_register_set(private_ts->client, 0x00); + }else{ + queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 1/10*HZ); + } + } +} + +static ssize_t himax_diag_write(struct file *filp, const char __user *buff, size_t len, loff_t *data) +{ + char messages[80] = {0}; + + uint8_t command[2] = {0x00, 0x00}; + uint8_t receive[1]; + + memset(receive, 0x00, sizeof(receive)); + + if (len >= 80) + { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + if (copy_from_user(messages, buff, len)) + { + return -EFAULT; + } + if (messages[1] == 0x0A){ + diag_command =messages[0] - '0'; + }else{ + diag_command =(messages[0] - '0')*10 + (messages[1] - '0'); + } + + I("[Himax]diag_command=0x%x\n",diag_command); + if (diag_command < 0x04){ + if(DSRAM_Flag) + { + //1. Clear DSRAM flag + DSRAM_Flag = false; + + //2. Stop DSRAM thread + cancel_delayed_work_sync(&private_ts->himax_diag_delay_wrok); + + //3. Enable ISR + himax_int_enable(private_ts->client->irq,1); + } + command[0] = diag_command; + himax_diag_register_set(private_ts->client, command[0]); + } + //coordinate dump start + else if (diag_command == 0x08) { + E("%s: coordinate_dump_file_create error\n", __func__); + } + else if (diag_command == 0x09 || diag_command == 91 || diag_command == 92){ + diag_max_cnt = 0; + memset(diag_mutual, 0x00, x_channel * y_channel * sizeof(int16_t)); //Set data 0 everytime + + //1. Disable ISR + himax_int_enable(private_ts->client->irq,0); + + //2. Start DSRAM thread + //himax_diag_register_set(private_ts->client, 0x0A); + + queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 2*HZ/100); + + I("%s: Start get raw data in DSRAM\n", __func__); + + //3. Set DSRAM flag + DSRAM_Flag = true; + }else{ + command[0] = 0x00; + himax_diag_register_set(private_ts->client, command[0]); + E("[Himax]Diag command error!diag_command=0x%x\n",diag_command); + } + return len; +} + +static const struct file_operations himax_proc_diag_ops = +{ + .owner = THIS_MODULE, + .open = himax_diag_proc_open, + .read = seq_read, + .write = himax_diag_write, +}; +#endif + +#ifdef HX_TP_PROC_RESET +static ssize_t himax_reset_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + char buf_tmp[12]; + + if (len >= 12) + { + I("%s: no command exceeds 12 chars.\n", __func__); + return -EFAULT; + } + if (copy_from_user(buf_tmp, buff, len)) + { + return -EFAULT; + } + //if (buf_tmp[0] == '1') + // ESD_HW_REST(); + + return len; +} + +static const struct file_operations himax_proc_reset_ops = +{ + .owner = THIS_MODULE, + .write = himax_reset_write, +}; +#endif + +#ifdef HX_TP_PROC_DEBUG +static ssize_t himax_debug_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + size_t count = 0; + char *temp_buf; + + if(!HX_PROC_SEND_FLAG) + { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf){ + HX_PROC_SEND_FLAG=0; + return count; + } + + if (debug_level_cmd == 't') + { + if (fw_update_complete) + count += snprintf(temp_buf+count, len-count, "FW Update Complete "); + else + { + count += snprintf(temp_buf+count, len-count, "FW Update Fail "); + } + } + else if (debug_level_cmd == 'h') + { + if (handshaking_result == 0) + { + count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (MCU Running)\n", handshaking_result); + } + else if (handshaking_result == 1) + { + count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (MCU Stop)\n", handshaking_result); + } + else if (handshaking_result == 2) + { + count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (I2C Error)\n", handshaking_result); + } + else + { + count += snprintf(temp_buf+count, len-count, "Handshaking Result = error\n"); + } + } + else if (debug_level_cmd == 'v') + { + count += snprintf(temp_buf+count, len-count, "FW_VER = "); + count += snprintf(temp_buf+count, len-count, "0x%2.2X\n", ic_data->vendor_fw_ver); + count += snprintf(temp_buf+count, len-count, "CONFIG_VER = "); + count += snprintf(temp_buf+count, len-count, "0x%2.2X\n", ic_data->vendor_config_ver); + count += snprintf(temp_buf+count, len-count, "\n"); + } + else if (debug_level_cmd == 'd') + { + count += snprintf(temp_buf+count, len-count, "Himax Touch IC Information :\n"); + if (IC_TYPE == HX_85XX_D_SERIES_PWON) + { + count += snprintf(temp_buf+count, len-count, "IC Type : D\n"); + } + else if (IC_TYPE == HX_85XX_E_SERIES_PWON) + { + count += snprintf(temp_buf+count, len-count, "IC Type : E\n"); + } + else if (IC_TYPE == HX_85XX_ES_SERIES_PWON) + { + count += snprintf(temp_buf+count, len-count, "IC Type : ES\n"); + } + else if (IC_TYPE == HX_85XX_F_SERIES_PWON) + { + count += snprintf(temp_buf+count, len-count, "IC Type : F\n"); + } + else + { + count += snprintf(temp_buf+count, len-count, "IC Type error.\n"); + } + + if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_SW) + { + count += snprintf(temp_buf+count, len-count, "IC Checksum : SW\n"); + } + else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_HW) + { + count += snprintf(temp_buf+count, len-count, "IC Checksum : HW\n"); + } + else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_CRC) + { + count += snprintf(temp_buf+count, len-count, "IC Checksum : CRC\n"); + } + else + { + count += snprintf(temp_buf+count, len-count, "IC Checksum error.\n"); + } + + if (ic_data->HX_INT_IS_EDGE) + { + count += snprintf(temp_buf+count, len-count, "Interrupt : EDGE TIRGGER\n"); + } + else + { + count += snprintf(temp_buf+count, len-count, "Interrupt : LEVEL TRIGGER\n"); + } + + count += snprintf(temp_buf+count, len-count, "RX Num : %d\n", ic_data->HX_RX_NUM); + count += snprintf(temp_buf+count, len-count, "TX Num : %d\n", ic_data->HX_TX_NUM); + count += snprintf(temp_buf+count, len-count, "BT Num : %d\n", ic_data->HX_BT_NUM); + count += snprintf(temp_buf+count, len-count, "X Resolution : %d\n", ic_data->HX_X_RES); + count += snprintf(temp_buf+count, len-count, "Y Resolution : %d\n", ic_data->HX_Y_RES); + count += snprintf(temp_buf+count, len-count, "Max Point : %d\n", ic_data->HX_MAX_PT); + count += snprintf(temp_buf+count, len-count, "XY reverse : %d\n", ic_data->HX_XY_REVERSE); + #ifdef HX_TP_PROC_2T2R + if(Is_2T2R) + { + count += snprintf(temp_buf+count, len-count, "2T2R panel\n"); + count += snprintf(temp_buf+count, len-count, "RX Num_2 : %d\n", HX_RX_NUM_2); + count += snprintf(temp_buf+count, len-count, "TX Num_2 : %d\n", HX_TX_NUM_2); + } + #endif + } + else if (debug_level_cmd == 'i') + { + count += snprintf(temp_buf+count, len-count, "Himax Touch Driver Version:\n"); + count += snprintf(temp_buf+count, len-count, "%s\n", HIMAX_DRIVER_VER); + } + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + HX_PROC_SEND_FLAG=1; + } + else + HX_PROC_SEND_FLAG=0; + return count; +} + +static ssize_t himax_debug_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + const struct firmware *fw = NULL; + unsigned char *fw_data = NULL; + char fileName[128]; + char buf[80] = {0}; + int result; + + if (len >= 80) + { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + if (copy_from_user(buf, buff, len)) + { + return -EFAULT; + } + + if ( buf[0] == 'h') //handshaking + { + debug_level_cmd = buf[0]; + + himax_int_enable(private_ts->client->irq,0); + + handshaking_result = himax_hand_shaking(private_ts->client); //0:Running, 1:Stop, 2:I2C Fail + + himax_int_enable(private_ts->client->irq,1); + + return len; + } + + else if ( buf[0] == 'v') //firmware version + { + debug_level_cmd = buf[0]; + himax_int_enable(private_ts->client->irq,0); +#ifdef HX_RST_PIN_FUNC + himax_HW_reset(false,false); +#endif + himax_read_FW_ver(private_ts->client); + //himax_check_chip_version(); +#ifdef HX_RST_PIN_FUNC + himax_HW_reset(true,false); +#endif + himax_int_enable(private_ts->client->irq,1); + return len; + } + + else if ( buf[0] == 'd') //ic information + { + debug_level_cmd = buf[0]; + return len; + } + + else if ( buf[0] == 'i') //driver version + { + debug_level_cmd = buf[0]; + return len; + } + + else if (buf[0] == 't') + { + + himax_int_enable(private_ts->client->irq,0); + + debug_level_cmd = buf[0]; + fw_update_complete = false; + + memset(fileName, 0, 128); + // parse the file name + snprintf(fileName, len-4, "%s", &buf[4]); + I("%s: upgrade from file(%s) start!\n", __func__, fileName); + // open file + result = request_firmware(&fw, fileName, private_ts->dev); + if (result) { + E("%s: open firmware file failed\n", __func__); + goto firmware_upgrade_done; + //return len; + } + + I("%s: FW len %d\n", __func__, fw->size); + fw_data = (unsigned char *)fw->data; + + I("%s: FW image,len %d: %02X, %02X, %02X, %02X\n", __func__, result, upgrade_fw[0], upgrade_fw[1], upgrade_fw[2], upgrade_fw[3]); + + if (fw_data != NULL) + { + // start to upgrade + himax_int_enable(private_ts->client->irq,0); + + if ((buf[1] == '6') && (buf[2] == '0')) + { + if (fts_ctpm_fw_upgrade_with_sys_fs_60k(private_ts->client,upgrade_fw, result, false) == 0) + { + E("%s: TP upgrade error, line: %d\n", __func__, __LINE__); + fw_update_complete = false; + } + else + { + I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__); + fw_update_complete = true; + } + } + else if ((buf[1] == '6') && (buf[2] == '4')) + { + if (fts_ctpm_fw_upgrade_with_sys_fs_64k(private_ts->client,upgrade_fw, result, false) == 0) + { + E("%s: TP upgrade error, line: %d\n", __func__, __LINE__); + fw_update_complete = false; + } + else + { + I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__); + fw_update_complete = true; + } + } + else if ((buf[1] == '2') && (buf[2] == '4')) + { + if (fts_ctpm_fw_upgrade_with_sys_fs_124k(private_ts->client,upgrade_fw, result, false) == 0) + { + E("%s: TP upgrade error, line: %d\n", __func__, __LINE__); + fw_update_complete = false; + } + else + { + I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__); + fw_update_complete = true; + } + } + else if ((buf[1] == '2') && (buf[2] == '8')) + { + if (fts_ctpm_fw_upgrade_with_sys_fs_128k(private_ts->client,upgrade_fw, result, false) == 0) + { + E("%s: TP upgrade error, line: %d\n", __func__, __LINE__); + fw_update_complete = false; + } + else + { + I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__); + fw_update_complete = true; + } + } + else + { + E("%s: Flash command fail: %d\n", __func__, __LINE__); + fw_update_complete = false; + } + release_firmware(fw); + goto firmware_upgrade_done; + //return count; + } + } + + firmware_upgrade_done: + +#ifdef HX_RST_PIN_FUNC + himax_HW_reset(true,false); +#endif + + himax_sense_on(private_ts->client, 0x01); + msleep(120); +#ifdef HX_ESD_WORKAROUND + HX_ESD_RESET_ACTIVATE = 1; +#endif + himax_int_enable(private_ts->client->irq,1); + + //todo himax_chip->tp_firmware_upgrade_proceed = 0; + //todo himax_chip->suspend_state = 0; + //todo enable_irq(himax_chip->irq); + return len; +} + +static const struct file_operations himax_proc_debug_ops = +{ + .owner = THIS_MODULE, + .read = himax_debug_read, + .write = himax_debug_write, +}; + +#endif + +#ifdef HX_TP_PROC_FLASH_DUMP + +static uint8_t getFlashCommand(void) +{ + return flash_command; +} + +static uint8_t getFlashDumpProgress(void) +{ + return flash_progress; +} + +static uint8_t getFlashDumpComplete(void) +{ + return flash_dump_complete; +} + +static uint8_t getFlashDumpFail(void) +{ + return flash_dump_fail; +} + +uint8_t getSysOperation(void) +{ + return sys_operation; +} + +static uint8_t getFlashReadStep(void) +{ + return flash_read_step; +} +/* +static uint8_t getFlashDumpSector(void) +{ + return flash_dump_sector; +} + +static uint8_t getFlashDumpPage(void) +{ + return flash_dump_page; +} +*/ +bool getFlashDumpGoing(void) +{ + return flash_dump_going; +} + +void setFlashBuffer(void) +{ + flash_buffer = kzalloc(Flash_Size * sizeof(uint8_t), GFP_KERNEL); + if (flash_buffer) + memset(flash_buffer,0x00,Flash_Size); +} + +void setSysOperation(uint8_t operation) +{ + sys_operation = operation; +} + +static void setFlashDumpProgress(uint8_t progress) +{ + flash_progress = progress; + //I("setFlashDumpProgress : progress = %d ,flash_progress = %d \n",progress,flash_progress); +} + +static void setFlashDumpComplete(uint8_t status) +{ + flash_dump_complete = status; +} + +static void setFlashDumpFail(uint8_t fail) +{ + flash_dump_fail = fail; +} + +static void setFlashCommand(uint8_t command) +{ + flash_command = command; +} + +static void setFlashReadStep(uint8_t step) +{ + flash_read_step = step; +} + +static void setFlashDumpSector(uint8_t sector) +{ + flash_dump_sector = sector; +} + +static void setFlashDumpPage(uint8_t page) +{ + flash_dump_page = page; +} + +static void setFlashDumpGoing(bool going) +{ + flash_dump_going = going; +} + +static ssize_t himax_proc_flash_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + int ret = 0; + int loop_i; + uint8_t local_flash_read_step=0; + uint8_t local_flash_complete = 0; + uint8_t local_flash_progress = 0; + uint8_t local_flash_command = 0; + uint8_t local_flash_fail = 0; + char *temp_buf; + local_flash_complete = getFlashDumpComplete(); + local_flash_progress = getFlashDumpProgress(); + local_flash_command = getFlashCommand(); + local_flash_fail = getFlashDumpFail(); + + I("flash_progress = %d \n",local_flash_progress); + if(!HX_PROC_SEND_FLAG) + { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + HX_PROC_SEND_FLAG=0; + return ret; + } + + if (local_flash_fail) + { + ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Fail \n"); + ret += snprintf(temp_buf+ret, len-ret, "FlashEnd"); + ret += snprintf(temp_buf+ret, len-ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + return ret; + } + + if (!local_flash_complete) + { + ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Ongoing:0x%2.2x \n",flash_progress); + ret += snprintf(temp_buf+ret, len-ret, "FlashEnd"); + ret += snprintf(temp_buf+ret, len-ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + return ret; + } + + if (local_flash_command == 1 && local_flash_complete) + { + ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Complete \n"); + ret += snprintf(temp_buf+ret, len-ret, "FlashEnd"); + ret += snprintf(temp_buf+ret, len-ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + return ret; + } + + if (local_flash_command == 3 && local_flash_complete) + { + ret += snprintf(temp_buf+ret, len-ret, "FlashStart: \n"); + for(loop_i = 0; loop_i < 128; loop_i++) + { + ret += snprintf(temp_buf+ret, len-ret, "x%2.2x", flash_buffer[loop_i]); + if ((loop_i % 16) == 15) + { + ret += snprintf(temp_buf+ret, len-ret, "\n"); + } + } + ret += snprintf(temp_buf+ret, len-ret, "FlashEnd"); + ret += snprintf(temp_buf+ret, len-ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + return ret; + } + + //flash command == 0 , report the data + local_flash_read_step = getFlashReadStep(); + + ret += snprintf(temp_buf+ret, len-ret, "FlashStart:%2.2x \n",local_flash_read_step); + + for (loop_i = 0; loop_i < 1024; loop_i++) + { + ret += snprintf(temp_buf+ret, len-ret, "x%2.2X", flash_buffer[local_flash_read_step*1024 + loop_i]); + + if ((loop_i % 16) == 15) + { + ret += snprintf(temp_buf+ret, len-ret, "\n"); + } + } + + ret += snprintf(temp_buf+ret, len-ret, "FlashEnd"); + ret += snprintf(temp_buf+ret, len-ret, "\n"); + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } + else + HX_PROC_SEND_FLAG=0; + return ret; +} + +static ssize_t himax_proc_flash_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + char buf_tmp[6]; + unsigned long result = 0; + uint8_t loop_i = 0; + int base = 0; + char buf[80] = {0}; + + if (len >= 80) + { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + if (copy_from_user(buf, buff, len)) + { + return -EFAULT; + } + memset(buf_tmp, 0x0, sizeof(buf_tmp)); + + I("%s: buf[0] = %s\n", __func__, buf); + + if (getSysOperation() == 1) + { + E("%s: PROC is busy , return!\n", __func__); + return len; + } + + if (buf[0] == '0') + { + setFlashCommand(0); + if (buf[1] == ':' && buf[2] == 'x') + { + memcpy(buf_tmp, buf + 3, 2); + I("%s: read_Step = %s\n", __func__, buf_tmp); + if (!kstrtoul(buf_tmp, 16, &result)) + { + I("%s: read_Step = %lu \n", __func__, result); + setFlashReadStep(result); + } + } + } + else if (buf[0] == '1')// 1_60,1_64,1_24,1_28 for flash size 60k,64k,124k,128k + { + setSysOperation(1); + setFlashCommand(1); + setFlashDumpProgress(0); + setFlashDumpComplete(0); + setFlashDumpFail(0); + if ((buf[1] == '_' ) && (buf[2] == '6' )){ + if (buf[3] == '0'){ + Flash_Size = FW_SIZE_60k; + }else if (buf[3] == '4'){ + Flash_Size = FW_SIZE_64k; + } + }else if ((buf[1] == '_' ) && (buf[2] == '2' )){ + if (buf[3] == '4'){ + Flash_Size = FW_SIZE_124k; + }else if (buf[3] == '8'){ + Flash_Size = FW_SIZE_128k; + } + } + queue_work(private_ts->flash_wq, &private_ts->flash_work); + } + else if (buf[0] == '2') // 2_60,2_64,2_24,2_28 for flash size 60k,64k,124k,128k + { + setSysOperation(1); + setFlashCommand(2); + setFlashDumpProgress(0); + setFlashDumpComplete(0); + setFlashDumpFail(0); + if ((buf[1] == '_' ) && (buf[2] == '6' )){ + if (buf[3] == '0'){ + Flash_Size = FW_SIZE_60k; + }else if (buf[3] == '4'){ + Flash_Size = FW_SIZE_64k; + } + }else if ((buf[1] == '_' ) && (buf[2] == '2' )){ + if (buf[3] == '4'){ + Flash_Size = FW_SIZE_124k; + }else if (buf[3] == '8'){ + Flash_Size = FW_SIZE_128k; + } + } + queue_work(private_ts->flash_wq, &private_ts->flash_work); + } + else if (buf[0] == '3') + { + setSysOperation(1); + setFlashCommand(3); + setFlashDumpProgress(0); + setFlashDumpComplete(0); + setFlashDumpFail(0); + + memcpy(buf_tmp, buf + 3, 2); + if (!kstrtoul(buf_tmp, 16, &result)) + { + setFlashDumpSector(result); + } + + memcpy(buf_tmp, buf + 7, 2); + if (!kstrtoul(buf_tmp, 16, &result)) + { + setFlashDumpPage(result); + } + + queue_work(private_ts->flash_wq, &private_ts->flash_work); + } + else if (buf[0] == '4') + { + I("%s: command 4 enter.\n", __func__); + setSysOperation(1); + setFlashCommand(4); + setFlashDumpProgress(0); + setFlashDumpComplete(0); + setFlashDumpFail(0); + + memcpy(buf_tmp, buf + 3, 2); + if (!kstrtoul(buf_tmp, 16, &result)) + { + setFlashDumpSector(result); + } + else + { + E("%s: command 4 , sector error.\n", __func__); + return len; + } + + memcpy(buf_tmp, buf + 7, 2); + if (!kstrtoul(buf_tmp, 16, &result)) + { + setFlashDumpPage(result); + } + else + { + E("%s: command 4 , page error.\n", __func__); + return len; + } + + base = 11; + + I("=========Himax flash page buffer start=========\n"); + for(loop_i=0;loop_i<128 && base<80;loop_i++) + { + memcpy(buf_tmp, buf + base, 2); + if (!kstrtoul(buf_tmp, 16, &result)) + { + flash_buffer[loop_i] = result; + I("%d ",flash_buffer[loop_i]); + if (loop_i % 16 == 15) + { + I("\n"); + } + } + base += 3; + } + I("=========Himax flash page buffer end=========\n"); + + queue_work(private_ts->flash_wq, &private_ts->flash_work); + } + return len; +} + +static const struct file_operations himax_proc_flash_ops = +{ + .owner = THIS_MODULE, + .read = himax_proc_flash_read, + .write = himax_proc_flash_write, +}; + +void himax_ts_flash_func(void) +{ + uint8_t local_flash_command = 0; + + himax_int_enable(private_ts->client->irq,0); + setFlashDumpGoing(true); + + //sector = getFlashDumpSector(); + //page = getFlashDumpPage(); + + local_flash_command = getFlashCommand(); + + msleep(100); + + I("%s: local_flash_command = %d enter.\n", __func__,local_flash_command); + + if ((local_flash_command == 1 || local_flash_command == 2)|| (local_flash_command==0x0F)) + { + himax_flash_dump_func(private_ts->client, local_flash_command,Flash_Size, flash_buffer); + } + + I("Complete~~~~~~~~~~~~~~~~~~~~~~~\n"); + + if (local_flash_command == 2) + { + E("Flash dump failed\n"); + } + + himax_int_enable(private_ts->client->irq,1); + setFlashDumpGoing(false); + + setFlashDumpComplete(1); + setSysOperation(0); + return; + +/* Flash_Dump_i2c_transfer_error: + + himax_int_enable(private_ts->client->irq,1); + setFlashDumpGoing(false); + setFlashDumpComplete(0); + setFlashDumpFail(1); + setSysOperation(0); + return; +*/ +} + +#endif + +#ifdef HX_TP_PROC_SELF_TEST +static ssize_t himax_self_test_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + int val=0x00; + int ret = 0; + char *temp_buf; + + I("%s: enter, %d \n", __func__, __LINE__); + if(!HX_PROC_SEND_FLAG) + { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + HX_PROC_SEND_FLAG=0; + return ret; + } + himax_int_enable(private_ts->client->irq,0);//disable irq + val = himax_chip_self_test(private_ts->client); +#ifdef HX_ESD_WORKAROUND + HX_ESD_RESET_ACTIVATE = 1; +#endif + himax_int_enable(private_ts->client->irq,1);//enable irq + + if (val == 0x01) { + ret += snprintf(temp_buf+ret, len-ret, "Self_Test Pass\n"); + } else { + ret += snprintf(temp_buf+ret, len-ret, "Self_Test Fail\n"); + } + + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } + else + HX_PROC_SEND_FLAG=0; + return ret; +} + +/* +static ssize_t himax_chip_self_test_store(struct device *dev,struct device_attribute *attr, const char *buf, size_t count) +{ + char buf_tmp[2]; + unsigned long result = 0; + + memset(buf_tmp, 0x0, sizeof(buf_tmp)); + memcpy(buf_tmp, buf, 2); + if(!kstrtoul(buf_tmp, 16, &result)) + { + sel_type = (uint8_t)result; + } + I("sel_type = %x \r\n", sel_type); + return count; +} +*/ + +static const struct file_operations himax_proc_self_test_ops = +{ + .owner = THIS_MODULE, + .read = himax_self_test_read, +}; +#endif + +#ifdef HX_TP_PROC_SENSE_ON_OFF +static ssize_t himax_sense_on_off_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + char buf[80] = {0}; + + if (len >= 80) + { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + if (copy_from_user(buf, buff, len)) + { + return -EFAULT; + } + + if(buf[0] == '0') + { + himax_sense_off(private_ts->client); + I("Sense off \n"); + } + else if(buf[0] == '1') + { + if(buf[1] == '1'){ + himax_sense_on(private_ts->client, 0x01); + I("Sense on re-map off, run flash \n"); + }else if(buf[1] == '0'){ + himax_sense_on(private_ts->client, 0x00); + I("Sense on re-map on, run sram \n"); + }else{ + I("Do nothing \n"); + } + } + else + { + I("Do nothing \n"); + } + return len; +} + +static const struct file_operations himax_proc_sense_on_off_ops = +{ + .owner = THIS_MODULE, + .write = himax_sense_on_off_write, +}; +#endif + +#ifdef HX_HIGH_SENSE +static ssize_t himax_HSEN_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + size_t count = 0; + char *temp_buf; + + if(!HX_PROC_SEND_FLAG) + { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + HX_PROC_SEND_FLAG=0; + return count; + } + count = snprintf(temp_buf, len, "%d\n", ts->HSEN_enable); + HX_PROC_SEND_FLAG=1; + + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + } + else + HX_PROC_SEND_FLAG=0; + return count; +} + +static ssize_t himax_HSEN_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + char buf[80] = {0}; + + + if (len >= 80) + { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + if (copy_from_user(buf, buff, len)) + { + return -EFAULT; + } + + if (buf[0] == '0'){ + ts->HSEN_enable = 0; + } + else if (buf[0] == '1'){ + ts->HSEN_enable = 1; + } + else + return -EINVAL; + + himax_set_HSEN_func(ts->client, ts->HSEN_enable); + + I("%s: HSEN_enable = %d.\n", __func__, ts->HSEN_enable); + + return len; +} + +static const struct file_operations himax_proc_HSEN_ops = +{ + .owner = THIS_MODULE, + .read = himax_HSEN_read, + .write = himax_HSEN_write, +}; +#endif + +#ifdef HX_SMART_WAKEUP +static ssize_t himax_SMWP_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + size_t count = 0; + struct himax_ts_data *ts = private_ts; + char *temp_buf; + + if(!HX_PROC_SEND_FLAG) + { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + HX_PROC_SEND_FLAG=0; + return count; + } + count = snprintf(temp_buf, len, "%d\n", ts->SMWP_enable); + + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + HX_PROC_SEND_FLAG=1; + } + else + HX_PROC_SEND_FLAG=0; + + return count; +} + +static ssize_t himax_SMWP_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + char buf[80] = {0}; + + if (len >= 80) + { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + if (copy_from_user(buf, buff, len)) + { + return -EFAULT; + } + + + if (buf[0] == '0') + { + ts->SMWP_enable = 0; + } + else if (buf[0] == '1') + { + ts->SMWP_enable = 1; + } + else + return -EINVAL; + + himax_set_SMWP_func(ts->client, ts->SMWP_enable); + HX_SMWP_EN = ts->SMWP_enable; + I("%s: SMART_WAKEUP_enable = %d.\n", __func__, HX_SMWP_EN); + + return len; +} + +static const struct file_operations himax_proc_SMWP_ops = +{ + .owner = THIS_MODULE, + .read = himax_SMWP_read, + .write = himax_SMWP_write, +}; + +static ssize_t himax_GESTURE_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + int i =0; + int ret = 0; + char *temp_buf; + + if(!HX_PROC_SEND_FLAG) + { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + HX_PROC_SEND_FLAG=0; + return ret; + } + for(i=0;i<16;i++) + ret += snprintf(temp_buf+ret, len-ret, "ges_en[%d]=%d\n", i, ts->gesture_cust_en[i]); + HX_PROC_SEND_FLAG = 1; + if (copy_to_user(buf, temp_buf, len)) + { + I("%s,here:%d\n", __func__, __LINE__); + } + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } + else + { + HX_PROC_SEND_FLAG = 0; + ret = 0; + } + return ret; +} + +static ssize_t himax_GESTURE_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + int i =0; + char buf[80] = {0}; + + if (len >= 80) + { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + if (copy_from_user(buf, buff, len)) + { + return -EFAULT; + } + + I("himax_GESTURE_store= %s \n",buf); + for (i=0;i<16;i++) + { + if (buf[i] == '0') + ts->gesture_cust_en[i]= 0; + else if (buf[i] == '1') + ts->gesture_cust_en[i]= 1; + else + ts->gesture_cust_en[i]= 0; + I("gesture en[%d]=%d \n", i, ts->gesture_cust_en[i]); + } + return len; +} + +static const struct file_operations himax_proc_Gesture_ops = +{ + .owner = THIS_MODULE, + .read = himax_GESTURE_read, + .write = himax_GESTURE_write, +}; +#endif + +int himax_touch_proc_init(void) +{ + himax_touch_proc_dir = proc_mkdir( HIMAX_PROC_TOUCH_FOLDER, NULL); + if (himax_touch_proc_dir == NULL) + { + E(" %s: himax_touch_proc_dir file create failed!\n", __func__); + return -ENOMEM; + } + + himax_proc_debug_level_file = proc_create(HIMAX_PROC_DEBUG_LEVEL_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_level_ops); + if (himax_proc_debug_level_file == NULL) + { + E(" %s: proc debug_level file create failed!\n", __func__); + goto fail_1; + } + + himax_proc_vendor_file = proc_create(HIMAX_PROC_VENDOR_FILE, (S_IRUGO),himax_touch_proc_dir, &himax_proc_vendor_ops); + if(himax_proc_vendor_file == NULL) + { + E(" %s: proc vendor file create failed!\n", __func__); + goto fail_2; + } + + himax_proc_attn_file = proc_create(HIMAX_PROC_ATTN_FILE, (S_IRUGO),himax_touch_proc_dir, &himax_proc_attn_ops); + if(himax_proc_attn_file == NULL) + { + E(" %s: proc attn file create failed!\n", __func__); + goto fail_3; + } + + himax_proc_int_en_file = proc_create(HIMAX_PROC_INT_EN_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_int_en_ops); + if(himax_proc_int_en_file == NULL) + { + E(" %s: proc int en file create failed!\n", __func__); + goto fail_4; + } + + himax_proc_layout_file = proc_create(HIMAX_PROC_LAYOUT_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_layout_ops); + if(himax_proc_layout_file == NULL) + { + E(" %s: proc layout file create failed!\n", __func__); + goto fail_5; + } + +#ifdef HX_TP_PROC_RESET + himax_proc_reset_file = proc_create(HIMAX_PROC_RESET_FILE, (S_IWUSR), himax_touch_proc_dir, &himax_proc_reset_ops); + if(himax_proc_reset_file == NULL) + { + E(" %s: proc reset file create failed!\n", __func__); + goto fail_6; + } +#endif + +#ifdef HX_TP_PROC_DIAG + himax_proc_diag_file = proc_create(HIMAX_PROC_DIAG_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_diag_ops); + if(himax_proc_diag_file == NULL) + { + E(" %s: proc diag file create failed!\n", __func__); + goto fail_7; + } + himax_proc_diag_arrange_file = proc_create(HIMAX_PROC_DIAG_ARR_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_diag_arrange_ops); + if(himax_proc_diag_arrange_file == NULL) + { + E(" %s: proc diag file create failed!\n", __func__); + goto fail_7_1; + } +#endif + +#ifdef HX_TP_PROC_REGISTER + himax_proc_register_file = proc_create(HIMAX_PROC_REGISTER_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_register_ops); + if(himax_proc_register_file == NULL) + { + E(" %s: proc register file create failed!\n", __func__); + goto fail_8; + } +#endif + +#ifdef HX_TP_PROC_DEBUG + himax_proc_debug_file = proc_create(HIMAX_PROC_DEBUG_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_ops); + if(himax_proc_debug_file == NULL) + { + E(" %s: proc debug file create failed!\n", __func__); + goto fail_9; + } +#endif + +#ifdef HX_TP_PROC_FLASH_DUMP + himax_proc_flash_dump_file = proc_create(HIMAX_PROC_FLASH_DUMP_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_flash_ops); + if(himax_proc_flash_dump_file == NULL) + { + E(" %s: proc flash dump file create failed!\n", __func__); + goto fail_10; + } +#endif + +#ifdef HX_TP_PROC_SELF_TEST + himax_proc_self_test_file = proc_create(HIMAX_PROC_SELF_TEST_FILE, (S_IRUGO), himax_touch_proc_dir, &himax_proc_self_test_ops); + if(himax_proc_self_test_file == NULL) + { + E(" %s: proc self_test file create failed!\n", __func__); + goto fail_11; + } +#endif + +#ifdef HX_HIGH_SENSE + himax_proc_HSEN_file = proc_create(HIMAX_PROC_HSEN_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_HSEN_ops); + if(himax_proc_HSEN_file == NULL) + { + E(" %s: proc HSEN file create failed!\n", __func__); + goto fail_12; + } +#endif + +#ifdef HX_SMART_WAKEUP + himax_proc_SMWP_file = proc_create(HIMAX_PROC_SMWP_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_SMWP_ops); + if(himax_proc_SMWP_file == NULL) + { + E(" %s: proc SMWP file create failed!\n", __func__); + goto fail_13; + } + himax_proc_GESTURE_file = proc_create(HIMAX_PROC_GESTURE_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_Gesture_ops); + if(himax_proc_GESTURE_file == NULL) + { + E(" %s: proc GESTURE file create failed!\n", __func__); + goto fail_14; + } +#endif + +#ifdef HX_TP_PROC_SENSE_ON_OFF + himax_proc_SENSE_ON_OFF_file = proc_create(HIMAX_PROC_SENSE_ON_OFF_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_sense_on_off_ops); + if(himax_proc_SENSE_ON_OFF_file == NULL) + { + E(" %s: proc SENSE_ON_OFF file create failed!\n", __func__); + goto fail_15; + } +#endif + + return 0 ; + +#ifdef HX_TP_PROC_SENSE_ON_OFF + fail_15: +#endif +#ifdef HX_SMART_WAKEUP + remove_proc_entry( HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir ); + fail_14: + remove_proc_entry( HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir ); + fail_13: +#endif +#ifdef HX_HIGH_SENSE + remove_proc_entry( HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir ); + fail_12: +#endif +#ifdef HX_TP_PROC_SELF_TEST + remove_proc_entry( HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir ); + fail_11: +#endif +#ifdef HX_TP_PROC_FLASH_DUMP + remove_proc_entry( HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir ); + fail_10: +#endif +#ifdef HX_TP_PROC_DEBUG + remove_proc_entry( HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir ); + fail_9: +#endif +#ifdef HX_TP_PROC_REGISTER + remove_proc_entry( HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir ); + fail_8: +#endif +#ifdef HX_TP_PROC_DIAG + remove_proc_entry( HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir ); + fail_7: + remove_proc_entry( HIMAX_PROC_DIAG_ARR_FILE, himax_touch_proc_dir ); + fail_7_1: +#endif +#ifdef HX_TP_PROC_RESET + remove_proc_entry( HIMAX_PROC_RESET_FILE, himax_touch_proc_dir ); + fail_6: +#endif + remove_proc_entry( HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir ); + fail_5: remove_proc_entry( HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir ); + fail_4: remove_proc_entry( HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir ); + fail_3: remove_proc_entry( HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir ); + fail_2: remove_proc_entry( HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir ); + fail_1: remove_proc_entry( HIMAX_PROC_TOUCH_FOLDER, NULL ); + return -ENOMEM; +} + +void himax_touch_proc_deinit(void) +{ +#ifdef HX_TP_PROC_SENSE_ON_OFF + remove_proc_entry( HIMAX_PROC_SENSE_ON_OFF_FILE, himax_touch_proc_dir ); +#endif +#ifdef HX_SMART_WAKEUP + remove_proc_entry( HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir ); + remove_proc_entry( HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir ); +#endif +#ifdef HX_DOT_VIEW + remove_proc_entry( HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir ); +#endif +#ifdef HX_TP_PROC_SELF_TEST + remove_proc_entry(HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir); +#endif +#ifdef HX_TP_PROC_FLASH_DUMP + remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir); +#endif +#ifdef HX_TP_PROC_DEBUG + remove_proc_entry( HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir ); +#endif +#ifdef HX_TP_PROC_REGISTER + remove_proc_entry(HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir); +#endif +#ifdef HX_TP_PROC_DIAG + remove_proc_entry(HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir); +#endif +#ifdef HX_TP_PROC_RESET + remove_proc_entry( HIMAX_PROC_RESET_FILE, himax_touch_proc_dir ); +#endif + remove_proc_entry( HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir ); + remove_proc_entry( HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir ); + remove_proc_entry( HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir ); + remove_proc_entry( HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir ); + remove_proc_entry( HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir ); + remove_proc_entry( HIMAX_PROC_TOUCH_FOLDER, NULL ); +} +#endif diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.h b/drivers/input/touchscreen/hxchipset/himax_debug.h new file mode 100644 index 0000000000000..91a7ae2eb7aba --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_debug.h @@ -0,0 +1,181 @@ +/* Himax Android Driver Sample Code for Himax chipset +* +* Copyright (C) 2015 Himax Corporation. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#include "himax_platform.h" +#include "himax_common.h" + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) + #define HIMAX_PROC_TOUCH_FOLDER "android_touch" + #define HIMAX_PROC_DEBUG_LEVEL_FILE "debug_level" + #define HIMAX_PROC_VENDOR_FILE "vendor" + #define HIMAX_PROC_ATTN_FILE "attn" + #define HIMAX_PROC_INT_EN_FILE "int_en" + #define HIMAX_PROC_LAYOUT_FILE "layout" + + static struct proc_dir_entry *himax_touch_proc_dir; + static struct proc_dir_entry *himax_proc_debug_level_file; + static struct proc_dir_entry *himax_proc_vendor_file; + static struct proc_dir_entry *himax_proc_attn_file; + static struct proc_dir_entry *himax_proc_int_en_file; + static struct proc_dir_entry *himax_proc_layout_file; + + uint8_t HX_PROC_SEND_FLAG; + +extern int himax_touch_proc_init(void); +extern void himax_touch_proc_deinit(void); +bool getFlashDumpGoing(void); + +#ifdef HX_TP_PROC_REGISTER + #define HIMAX_PROC_REGISTER_FILE "register" + struct proc_dir_entry *himax_proc_register_file; + uint8_t register_command[4]; +#endif + +#ifdef HX_TP_PROC_DIAG + #define HIMAX_PROC_DIAG_FILE "diag" + struct proc_dir_entry *himax_proc_diag_file; + #define HIMAX_PROC_DIAG_ARR_FILE "diag_arr" + struct proc_dir_entry *himax_proc_diag_arrange_file; + +#ifdef HX_TP_PROC_2T2R + static bool Is_2T2R; + static uint8_t x_channel_2; + static uint8_t y_channel_2; + static uint8_t *diag_mutual_2; + + int16_t *getMutualBuffer_2(void); + uint8_t getXChannel_2(void); + uint8_t getYChannel_2(void); + + void setMutualBuffer_2(void); + void setXChannel_2(uint8_t x); + void setYChannel_2(uint8_t y); +#endif + uint8_t x_channel; + uint8_t y_channel; + int16_t *diag_mutual; + int16_t *diag_mutual_new; + int16_t *diag_mutual_old; + uint8_t diag_max_cnt; + + int diag_command; + uint8_t diag_coor[128];// = {0xFF}; + int16_t diag_self[100] = {0}; + + int16_t *getMutualBuffer(void); + int16_t *getMutualNewBuffer(void); + int16_t *getMutualOldBuffer(void); + int16_t *getSelfBuffer(void); + uint8_t getDiagCommand(void); + uint8_t getXChannel(void); + uint8_t getYChannel(void); + + void setMutualBuffer(void); + void setMutualNewBuffer(void); + void setMutualOldBuffer(void); + void setXChannel(uint8_t x); + void setYChannel(uint8_t y); + uint8_t coordinate_dump_enable = 0; + struct file *coordinate_fn; +#endif + +#ifdef HX_TP_PROC_DEBUG + #define HIMAX_PROC_DEBUG_FILE "debug" + struct proc_dir_entry *himax_proc_debug_file = NULL; + + bool fw_update_complete = false; + int handshaking_result = 0; + unsigned char debug_level_cmd = 0; + unsigned char upgrade_fw[128*1024]; +#endif + +#ifdef HX_TP_PROC_FLASH_DUMP + #define HIMAX_PROC_FLASH_DUMP_FILE "flash_dump" + struct proc_dir_entry *himax_proc_flash_dump_file = NULL; + + static int Flash_Size = 131072; + static uint8_t *flash_buffer = NULL; + static uint8_t flash_command = 0; + static uint8_t flash_read_step = 0; + static uint8_t flash_progress = 0; + static uint8_t flash_dump_complete = 0; + static uint8_t flash_dump_fail = 0; + static uint8_t sys_operation = 0; + static uint8_t flash_dump_sector = 0; + static uint8_t flash_dump_page = 0; + static bool flash_dump_going = false; + + static uint8_t getFlashCommand(void); + static uint8_t getFlashDumpComplete(void); + static uint8_t getFlashDumpFail(void); + static uint8_t getFlashDumpProgress(void); + static uint8_t getFlashReadStep(void); + //static uint8_t getFlashDumpSector(void); + //static uint8_t getFlashDumpPage(void); + + void setFlashBuffer(void); + uint8_t getSysOperation(void); + + static void setFlashCommand(uint8_t command); + static void setFlashReadStep(uint8_t step); + static void setFlashDumpComplete(uint8_t complete); + static void setFlashDumpFail(uint8_t fail); + static void setFlashDumpProgress(uint8_t progress); + void setSysOperation(uint8_t operation); + static void setFlashDumpSector(uint8_t sector); + static void setFlashDumpPage(uint8_t page); + static void setFlashDumpGoing(bool going); + +#endif + +#ifdef HX_TP_PROC_SELF_TEST + #define HIMAX_PROC_SELF_TEST_FILE "self_test" + struct proc_dir_entry *himax_proc_self_test_file = NULL; + uint32_t **raw_data_array; + uint8_t X_NUM = 0, Y_NUM = 0; + uint8_t sel_type = 0x0D; +#endif + +#ifdef HX_TP_PROC_RESET +#define HIMAX_PROC_RESET_FILE "reset" +extern void himax_HW_reset(uint8_t loadconfig,uint8_t int_off); +struct proc_dir_entry *himax_proc_reset_file = NULL; +#endif + +#ifdef HX_HIGH_SENSE + #define HIMAX_PROC_HSEN_FILE "HSEN" + struct proc_dir_entry *himax_proc_HSEN_file = NULL; +#endif + +#ifdef HX_TP_PROC_SENSE_ON_OFF + #define HIMAX_PROC_SENSE_ON_OFF_FILE "SenseOnOff" + struct proc_dir_entry *himax_proc_SENSE_ON_OFF_file = NULL; +#endif + +#ifdef HX_RST_PIN_FUNC + void himax_HW_reset(uint8_t loadconfig,uint8_t int_off); +#endif + +#ifdef HX_SMART_WAKEUP +#define HIMAX_PROC_SMWP_FILE "SMWP" +struct proc_dir_entry *himax_proc_SMWP_file = NULL; +#define HIMAX_PROC_GESTURE_FILE "GESTURE" +struct proc_dir_entry *himax_proc_GESTURE_file = NULL; +uint8_t HX_SMWP_EN = 0; +//extern bool FAKE_POWER_KEY_SEND; +#endif + +#endif + diff --git a/drivers/input/touchscreen/hxchipset/himax_ic.c b/drivers/input/touchscreen/hxchipset/himax_ic.c new file mode 100644 index 0000000000000..6ad8dc03149b4 --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_ic.c @@ -0,0 +1,2118 @@ +/* Himax Android Driver Sample Code for HMX83100 chipset +* +* Copyright (C) 2015 Himax Corporation. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#include "himax_ic.h" + +static unsigned char i_TP_CRC_FW_128K[]= +{ + #include "HX_CRC_128.i" +}; +static unsigned char i_TP_CRC_FW_64K[]= +{ + #include "HX_CRC_64.i" +}; +static unsigned char i_TP_CRC_FW_124K[]= +{ + #include "HX_CRC_124.i" +}; +static unsigned char i_TP_CRC_FW_60K[]= +{ + #include "HX_CRC_60.i" +}; + + +unsigned long FW_VER_MAJ_FLASH_ADDR; +unsigned long FW_VER_MAJ_FLASH_LENG; +unsigned long FW_VER_MIN_FLASH_ADDR; +unsigned long FW_VER_MIN_FLASH_LENG; +unsigned long CFG_VER_MAJ_FLASH_ADDR; +unsigned long CFG_VER_MAJ_FLASH_LENG; +unsigned long CFG_VER_MIN_FLASH_ADDR; +unsigned long CFG_VER_MIN_FLASH_LENG; + +unsigned char IC_TYPE = 0; +unsigned char IC_CHECKSUM = 0; + +extern struct himax_ic_data* ic_data; + +int himax_hand_shaking(struct i2c_client *client) //0:Running, 1:Stop, 2:I2C Fail +{ + int ret, result; + uint8_t hw_reset_check[1]; + uint8_t hw_reset_check_2[1]; + uint8_t buf0[2]; + uint8_t IC_STATUS_CHECK = 0xAA; + + memset(hw_reset_check, 0x00, sizeof(hw_reset_check)); + memset(hw_reset_check_2, 0x00, sizeof(hw_reset_check_2)); + + buf0[0] = 0xF2; + if (IC_STATUS_CHECK == 0xAA) { + buf0[1] = 0xAA; + IC_STATUS_CHECK = 0x55; + } else { + buf0[1] = 0x55; + IC_STATUS_CHECK = 0xAA; + } + + ret = i2c_himax_master_write(client, buf0, 2, HIMAX_I2C_RETRY_TIMES); + if (ret < 0) { + E("[Himax]:write 0xF2 failed line: %d \n",__LINE__); + goto work_func_send_i2c_msg_fail; + } + msleep(50); + + buf0[0] = 0xF2; + buf0[1] = 0x00; + ret = i2c_himax_master_write(client, buf0, 2, HIMAX_I2C_RETRY_TIMES); + if (ret < 0) { + E("[Himax]:write 0x92 failed line: %d \n",__LINE__); + goto work_func_send_i2c_msg_fail; + } + usleep_range(2000, 4000); + + ret = i2c_himax_read(client, 0xD1, hw_reset_check, 1, HIMAX_I2C_RETRY_TIMES); + if (ret < 0) { + E("[Himax]:i2c_himax_read 0xD1 failed line: %d \n",__LINE__); + goto work_func_send_i2c_msg_fail; + } + + if ((IC_STATUS_CHECK != hw_reset_check[0])) { + usleep_range(2000, 4000); + ret = i2c_himax_read(client, 0xD1, hw_reset_check_2, 1, HIMAX_I2C_RETRY_TIMES); + if (ret < 0) { + E("[Himax]:i2c_himax_read 0xD1 failed line: %d \n",__LINE__); + goto work_func_send_i2c_msg_fail; + } + + if (hw_reset_check[0] == hw_reset_check_2[0]) { + result = 1; + } else { + result = 0; + } + } else { + result = 0; + } + + return result; + +work_func_send_i2c_msg_fail: + return 2; +} + +void himax_diag_register_set(struct i2c_client *client, uint8_t diag_command) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + + if(diag_command != 0) + diag_command = diag_command + 5; + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0x80; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = diag_command; + himax_flash_write_burst(client, tmp_addr, tmp_data); +} + +void himax_flash_dump_func(struct i2c_client *client, uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer) +{ + //struct himax_ts_data *ts = container_of(work, struct himax_ts_data, flash_work); + +// uint8_t sector = 0; +// uint8_t page = 0; + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + uint8_t out_buffer[20]; + uint8_t in_buffer[260] = {0}; + int page_prog_start = 0; + int i = 0; + + himax_sense_off(client); + himax_burst_enable(client, 0); + /*=============Dump Flash Start=============*/ + //===================================== + // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + for (page_prog_start = 0; page_prog_start < Flash_Size; page_prog_start = page_prog_start + 256) + { + //================================= + // SPI Transfer Control + // Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF + // Set read start address : 0x8000_0028 ==> 0x0000_0000 + // Set command : 0x8000_0024 ==> 0x0000_003B + //================================= + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x69; tmp_data[2] = 0x40; tmp_data[1] = 0x02; tmp_data[0] = 0xFF; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; + if (page_prog_start < 0x100) + { + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = 0x00; + tmp_data[0] = (uint8_t)page_prog_start; + } + else if (page_prog_start >= 0x100 && page_prog_start < 0x10000) + { + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = (uint8_t)(page_prog_start >> 8); + tmp_data[0] = (uint8_t)page_prog_start; + } + else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000) + { + tmp_data[3] = 0x00; + tmp_data[2] = (uint8_t)(page_prog_start >> 16); + tmp_data[1] = (uint8_t)(page_prog_start >> 8); + tmp_data[0] = (uint8_t)page_prog_start; + } + himax_flash_write_burst(client, tmp_addr, tmp_data); + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x3B; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + //================================== + // AHB_I2C Burst Read + // Set SPI data register : 0x8000_002C ==> 0x00 + //================================== + out_buffer[0] = 0x2C; + out_buffer[1] = 0x00; + out_buffer[2] = 0x00; + out_buffer[3] = 0x80; + i2c_himax_write(client, 0x00 ,out_buffer, 4, 3); + + //================================== + // Read access : 0x0C ==> 0x00 + //================================== + out_buffer[0] = 0x00; + i2c_himax_write(client, 0x0C ,out_buffer, 1, 3); + + //================================== + // Read 128 bytes two times + //================================== + i2c_himax_read(client, 0x08 ,in_buffer, 128, 3); + for (i = 0; i < 128; i++) + flash_buffer[i + page_prog_start] = in_buffer[i]; + + i2c_himax_read(client, 0x08 ,in_buffer, 128, 3); + for (i = 0; i < 128; i++) + flash_buffer[(i + 128) + page_prog_start] = in_buffer[i]; + + I("%s:Verify Progress: %x\n", __func__, page_prog_start); + } + +/*=============Dump Flash End=============*/ + //msleep(100); + /* + for( i=0 ; i<8 ;i++) + { + for(j=0 ; j<64 ; j++) + { + setFlashDumpProgress(i*32 + j); + } + } + */ + himax_sense_on(client, 0x01); + + return; + +} + +int himax_chip_self_test(struct i2c_client *client) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[128]; + int pf_value=0x00; + uint8_t test_result_id = 0; + int j; + + memset(tmp_addr, 0x00, sizeof(tmp_addr)); + memset(tmp_data, 0x00, sizeof(tmp_data)); + + himax_interface_on(client); + himax_sense_off(client); + + //Set criteria + himax_burst_enable(client, 1); + + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x94; + tmp_data[3] = 0x14; tmp_data[2] = 0xC8; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + tmp_data[7] = 0x13; tmp_data[6] = 0x60; tmp_data[5] = 0x0A; tmp_data[4] = 0x99; + + himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 8); + + //start selftest + // 0x9008_805C ==> 0x0000_0001 + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x5C; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + himax_sense_on(client, 1); + + msleep(2000); + + himax_sense_off(client); + msleep(20); + + //===================================== + // Read test result ID : 0x9008_8078 ==> 0xA/0xB/0xC/0xF + //===================================== + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x78; + himax_register_read(client, tmp_addr, 1, tmp_data); + + test_result_id = tmp_data[0]; + + I("%s: check test result, test_result_id=%x, test_result=%x\n", __func__ + ,test_result_id,tmp_data[0]); + + if (test_result_id==0xF) { + I("[Himax]: self-test pass\n"); + pf_value = 0x1; + } else { + E("[Himax]: self-test fail\n"); + pf_value = 0x0; + } + himax_burst_enable(client, 1); + + for (j = 0;j < 10; j++){ + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x06; tmp_addr[1] = 0x00; tmp_addr[0] = 0x0C; + himax_register_read(client, tmp_addr, 1, tmp_data); + I("[Himax]: 9006000C = %d\n", tmp_data[0]); + if (tmp_data[0] != 0){ + tmp_data[3] = 0x90; tmp_data[2] = 0x06; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + if ( i2c_himax_write(client, 0x00 ,tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + } + tmp_data[0] = 0x00; + if ( i2c_himax_write(client, 0x0C ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + } + i2c_himax_read(client, 0x08, tmp_data, 124,HIMAX_I2C_RETRY_TIMES); + }else{ + break; + } + } + + himax_sense_on(client, 1); + msleep(120); + + return pf_value; +} + +void himax_set_HSEN_enable(struct i2c_client *client, uint8_t HSEN_enable) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + + himax_burst_enable(client, 0); + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x50; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = HSEN_enable; + himax_flash_write_burst(client, tmp_addr, tmp_data); +} +void himax_get_HSEN_enable(struct i2c_client *client,uint8_t *tmp_data) +{ + uint8_t tmp_addr[4]; + + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x50; + himax_register_read(client, tmp_addr, 1, tmp_data); +} + +void himax_set_SMWP_enable(struct i2c_client *client, uint8_t SMWP_enable) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x54; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = SMWP_enable; + himax_flash_write_burst(client, tmp_addr, tmp_data); +} + +void himax_get_SMWP_enable(struct i2c_client *client,uint8_t *tmp_data) +{ + uint8_t tmp_addr[4]; + + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x54; + himax_register_read(client, tmp_addr, 1, tmp_data); +} + +int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte) +{ + uint8_t tmp_data[4]; + + tmp_data[0] = 0x31; + if ( i2c_himax_write(client, 0x13 ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return -EBUSY; + } + + tmp_data[0] = (0x10 | auto_add_4_byte); + if ( i2c_himax_write(client, 0x0D ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return -EBUSY; + } + return 0; + +} + +void himax_register_read(struct i2c_client *client, uint8_t *read_addr, int read_length, uint8_t *read_data) +{ + uint8_t tmp_data[4]; + int i = 0; + int address = 0; + + if(read_length>256) + { + E("%s: read len over 256!\n", __func__); + return; + } + if (read_length > 1) + himax_burst_enable(client, 1); + else + himax_burst_enable(client, 0); + address = (read_addr[3] << 24) + (read_addr[2] << 16) + (read_addr[1] << 8) + read_addr[0]; + i = address; + tmp_data[0] = (uint8_t)i; + tmp_data[1] = (uint8_t)(i >> 8); + tmp_data[2] = (uint8_t)(i >> 16); + tmp_data[3] = (uint8_t)(i >> 24); + if ( i2c_himax_write(client, 0x00 ,tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + tmp_data[0] = 0x00; + if ( i2c_himax_write(client, 0x0C ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_read(client, 0x08 ,read_data, read_length * 4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + if (read_length > 1) + himax_burst_enable(client, 0); +} + +void himax_flash_read(struct i2c_client *client, uint8_t *reg_byte, uint8_t *read_data) +{ + uint8_t tmpbyte[2]; + + if ( i2c_himax_write(client, 0x00 ,®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(client, 0x01 ,®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(client, 0x02 ,®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(client, 0x03 ,®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + tmpbyte[0] = 0x00; + if ( i2c_himax_write(client, 0x0C ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_read(client, 0x08 ,&read_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_read(client, 0x09 ,&read_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_read(client, 0x0A ,&read_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_read(client, 0x0B ,&read_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_read(client, 0x18 ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + }// No bus request + + if ( i2c_himax_read(client, 0x0F ,&tmpbyte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + }// idle state + +} + +void himax_flash_write_burst(struct i2c_client *client, uint8_t * reg_byte, uint8_t * write_data) +{ + uint8_t data_byte[8]; + int i = 0, j = 0; + + for (i = 0; i < 4; i++) + { + data_byte[i] = reg_byte[i]; + } + for (j = 4; j < 8; j++) + { + data_byte[j] = write_data[j-4]; + } + + if ( i2c_himax_write(client, 0x00 ,data_byte, 8, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + +} + +int himax_flash_write_burst_lenth(struct i2c_client *client, uint8_t *reg_byte, uint8_t *write_data, int length) +{ + uint8_t data_byte[256]; + int i = 0, j = 0; + + for (i = 0; i < 4; i++) + { + data_byte[i] = reg_byte[i]; + } + for (j = 4; j < length + 4; j++) + { + data_byte[j] = write_data[j - 4]; + } + + if ( i2c_himax_write(client, 0x00 ,data_byte, length + 4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return -EBUSY; + } + + return 0; +} + +int himax_register_write(struct i2c_client *client, uint8_t *write_addr, int write_length, uint8_t *write_data) +{ + int i =0, address = 0; + int ret = 0; + + address = (write_addr[3] << 24) + (write_addr[2] << 16) + (write_addr[1] << 8) + write_addr[0]; + + for (i = address; i < address + write_length * 4; i = i + 4) + { + if (write_length > 1) + { + ret = himax_burst_enable(client, 1); + if(ret) + return ret; + } + else + { + ret = himax_burst_enable(client, 0); + if(ret) + return ret; + } + ret = himax_flash_write_burst_lenth(client, write_addr, write_data, write_length * 4); + if(ret < 0) + return ret; + } + + return 0; +} + +void himax_sense_off(struct i2c_client *client) +{ + uint8_t wdt_off = 0x00; + uint8_t tmp_addr[4]; + uint8_t tmp_data[5]; + + himax_burst_enable(client, 0); + + while(wdt_off == 0x00) + { + // 0x9000_800C ==> 0x0000_AC53 + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0xAC; tmp_data[0] = 0x53; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + //===================================== + // Read Watch Dog disable password : 0x9000_800C ==> 0x0000_AC53 + //===================================== + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C; + himax_register_read(client, tmp_addr, 1, tmp_data); + + //Check WDT + if (tmp_data[0] == 0x53 && tmp_data[1] == 0xAC && tmp_data[2] == 0x00 && tmp_data[3] == 0x00) + wdt_off = 0x01; + else + wdt_off = 0x00; + } + + // VCOM //0x9008_806C ==> 0x0000_0001 + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x6C; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + msleep(20); + + // 0x9000_0010 ==> 0x0000_00DA + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xDA; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + //===================================== + // Read CPU clock off password : 0x9000_0010 ==> 0x0000_00DA + //===================================== + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + himax_register_read(client, tmp_addr, 1, tmp_data); + I("%s: CPU clock off password data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__ + ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]); + +} + +void himax_interface_on(struct i2c_client *client) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[5]; + + //=========================================== + // Any Cmd for ineterface on : 0x9000_0000 ==> 0x0000_0000 + //=========================================== + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; + himax_flash_read(client, tmp_addr, tmp_data); //avoid RD/WR fail +} + +bool wait_wip(struct i2c_client *client, int Timing) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + uint8_t in_buffer[10]; + //uint8_t out_buffer[20]; + int retry_cnt = 0; + + //===================================== + // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + in_buffer[0] = 0x01; + + do + { + //===================================== + // SPI Transfer Control : 0x8000_0020 ==> 0x4200_0003 + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x42; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x03; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + //===================================== + // SPI Command : 0x8000_0024 ==> 0x0000_0005 + // read 0x8000_002C for 0x01, means wait success + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x05; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + in_buffer[0] = in_buffer[1] = in_buffer[2] = in_buffer[3] = 0xFF; + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C; + himax_register_read(client, tmp_addr, 1, in_buffer); + + if ((in_buffer[0] & 0x01) == 0x00) + return true; + + retry_cnt++; + + if (in_buffer[0] != 0x00 || in_buffer[1] != 0x00 || in_buffer[2] != 0x00 || in_buffer[3] != 0x00) + I("%s:Wait wip retry_cnt:%d, buffer[0]=%d, buffer[1]=%d, buffer[2]=%d, buffer[3]=%d \n", __func__, + retry_cnt,in_buffer[0],in_buffer[1],in_buffer[2],in_buffer[3]); + + if (retry_cnt > 100) + { + E("%s: Wait wip error!\n", __func__); + return false; + } + msleep(Timing); + }while ((in_buffer[0] & 0x01) == 0x01); + return true; +} + +void himax_sense_on(struct i2c_client *client, uint8_t FlashMode) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[128]; + + himax_interface_on(client); + himax_burst_enable(client, 0); + //CPU reset + // 0x9000_0014 ==> 0x0000_00CA + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xCA; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + //===================================== + // Read pull low CPU reset signal : 0x9000_0014 ==> 0x0000_00CA + //===================================== + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14; + himax_register_read(client, tmp_addr, 1, tmp_data); + + I("%s: check pull low CPU reset signal data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__ + ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]); + + // 0x9000_0014 ==> 0x0000_0000 + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + //===================================== + // Read revert pull low CPU reset signal : 0x9000_0014 ==> 0x0000_0000 + //===================================== + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14; + himax_register_read(client, tmp_addr, 1, tmp_data); + + I("%s: revert pull low CPU reset signal data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__ + ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]); + + //===================================== + // Reset TCON + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst(client, tmp_addr, tmp_data); + usleep_range(10000, 20000); + tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + if (FlashMode == 0x00) //SRAM + { + //===================================== + // Re-map + //===================================== + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xF1; + himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4); + I("%s:83100_Chip_Re-map ON\n", __func__); + } + else + { + //===================================== + // Re-map off + //===================================== + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4); + I("%s:83100_Chip_Re-map OFF\n", __func__); + } + //===================================== + // CPU clock on + //===================================== + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4); + +} + +void himax_chip_erase(struct i2c_client *client) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + + himax_burst_enable(client, 0); + + //===================================== + // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + //===================================== + // Chip Erase + // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000 + // 2. 0x8000_0024 ==> 0x0000_0006 + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + //===================================== + // Chip Erase + // Erase Command : 0x8000_0024 ==> 0x0000_00C7 + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xC7; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + msleep(2000); + + if (!wait_wip(client, 100)) + E("%s:83100_Chip_Erase Fail\n", __func__); + +} + +bool himax_block_erase(struct i2c_client *client) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + + himax_burst_enable(client, 0); + + //===================================== + // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + //===================================== + // Chip Erase + // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000 + // 2. 0x8000_0024 ==> 0x0000_0006 + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + //===================================== + // Block Erase + // Erase Command : 0x8000_0028 ==> 0x0000_0000 //SPI addr + // 0x8000_0020 ==> 0x6700_0000 //control + // 0x8000_0024 ==> 0x0000_0052 //BE + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x67; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x52; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + msleep(1000); + + if (!wait_wip(client, 100)) + { + E("%s:83100_Erase Fail\n", __func__); + return false; + } + else + { + return true; + } + +} + +bool himax_sector_erase(struct i2c_client *client, int start_addr) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + int page_prog_start = 0; + + himax_burst_enable(client, 0); + + //===================================== + // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80; + himax_flash_write_burst(client, tmp_addr, tmp_data); + for (page_prog_start = start_addr; page_prog_start < start_addr + 0x0F000; page_prog_start = page_prog_start + 0x1000) + { + //===================================== + // Chip Erase + // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000 + // 2. 0x8000_0024 ==> 0x0000_0006 + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + //===================================== + // Sector Erase + // Erase Command : 0x8000_0028 ==> 0x0000_0000 //SPI addr + // 0x8000_0020 ==> 0x6700_0000 //control + // 0x8000_0024 ==> 0x0000_0020 //SE + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; + if (page_prog_start < 0x100) + { + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = (uint8_t)page_prog_start; + } + else if (page_prog_start >= 0x100 && page_prog_start < 0x10000) + { + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = (uint8_t)(page_prog_start >> 8); tmp_data[0] = (uint8_t)page_prog_start; + } + else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000) + { + tmp_data[3] = 0x00; tmp_data[2] = (uint8_t)(page_prog_start >> 16); tmp_data[1] = (uint8_t)(page_prog_start >> 8); tmp_data[0] = (uint8_t)page_prog_start; + } + himax_flash_write_burst(client, tmp_addr, tmp_data); + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x67; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x20; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + msleep(200); + + if (!wait_wip(client, 100)) + { + E("%s:83100_Erase Fail\n", __func__); + return false; + } + } + return true; +} + +void himax_sram_write(struct i2c_client *client, uint8_t *FW_content) +{ + int i = 0; + uint8_t tmp_addr[4]; + uint8_t tmp_data[128]; + int FW_length = 0x4000; // 0x4000 = 16K bin file + + //himax_sense_off(client); + + for (i = 0; i < FW_length; i = i + 128) + { + himax_burst_enable(client, 1); + + if (i < 0x100) + { + tmp_addr[3] = 0x08; + tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; + tmp_addr[0] = i; + } + else if (i >= 0x100 && i < 0x10000) + { + tmp_addr[3] = 0x08; + tmp_addr[2] = 0x00; + tmp_addr[1] = (i >> 8); + tmp_addr[0] = i; + } + + memcpy(&tmp_data[0], &FW_content[i], 128); + himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 128); + + } + + if (!wait_wip(client, 100)) + E("%s:83100_Sram_Write Fail\n", __func__); +} + +bool himax_sram_verify(struct i2c_client *client, uint8_t *FW_File, int FW_Size) +{ + int i = 0; + uint8_t out_buffer[20]; + uint8_t in_buffer[128]; + uint8_t *get_fw_content; + + get_fw_content = kzalloc(0x4000*sizeof(uint8_t), GFP_KERNEL); + if (!get_fw_content) + return false; + + for (i = 0; i < 0x4000; i = i + 128) + { + himax_burst_enable(client, 1); + + //================================== + // AHB_I2C Burst Read + //================================== + if (i < 0x100) + { + out_buffer[3] = 0x08; + out_buffer[2] = 0x00; + out_buffer[1] = 0x00; + out_buffer[0] = i; + } + else if (i >= 0x100 && i < 0x10000) + { + out_buffer[3] = 0x08; + out_buffer[2] = 0x00; + out_buffer[1] = (i >> 8); + out_buffer[0] = i; + } + + if ( i2c_himax_write(client, 0x00 ,out_buffer, 4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + out_buffer[0] = 0x00; + if ( i2c_himax_write(client, 0x0C ,out_buffer, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + if ( i2c_himax_read(client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + memcpy(&get_fw_content[i], &in_buffer[0], 128); + } + + for (i = 0; i < FW_Size; i++) + { + if (FW_File[i] != get_fw_content[i]) + { + E("%s: fail! SRAM[%x]=%x NOT CRC_ifile=%x\n", __func__,i,get_fw_content[i],FW_File[i]); + return false; + } + } + + kfree(get_fw_content); + + return true; +} + +void himax_flash_programming(struct i2c_client *client, uint8_t *FW_content, int FW_Size) +{ + int page_prog_start = 0; + int program_length = 48; + int i = 0, j = 0, k = 0; + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + uint8_t buring_data[256]; // Read for flash data, 128K + // 4 bytes for 0x80002C padding + + //himax_interface_on(client); + himax_burst_enable(client, 0); + + //===================================== + // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + for (page_prog_start = 0; page_prog_start < FW_Size; page_prog_start = page_prog_start + 256) + { + //msleep(5); + //===================================== + // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000 + // 2. 0x8000_0024 ==> 0x0000_0006 + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + //================================= + // SPI Transfer Control + // Set 256 bytes page write : 0x8000_0020 ==> 0x610F_F000 + // Set read start address : 0x8000_0028 ==> 0x0000_0000 + //================================= + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x61; tmp_data[2] = 0x0F; tmp_data[1] = 0xF0; tmp_data[0] = 0x00; + // data bytes should be 0x6100_0000 + ((word_number)*4-1)*4096 = 0x6100_0000 + 0xFF000 = 0x610F_F000 + // Programmable size = 1 page = 256 bytes, word_number = 256 byte / 4 = 64 + himax_flash_write_burst(client, tmp_addr, tmp_data); + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; + //tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; // Flash start address 1st : 0x0000_0000 + + if (page_prog_start < 0x100) + { + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = 0x00; + tmp_data[0] = (uint8_t)page_prog_start; + } + else if (page_prog_start >= 0x100 && page_prog_start < 0x10000) + { + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = (uint8_t)(page_prog_start >> 8); + tmp_data[0] = (uint8_t)page_prog_start; + } + else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000) + { + tmp_data[3] = 0x00; + tmp_data[2] = (uint8_t)(page_prog_start >> 16); + tmp_data[1] = (uint8_t)(page_prog_start >> 8); + tmp_data[0] = (uint8_t)page_prog_start; + } + + himax_flash_write_burst(client, tmp_addr, tmp_data); + + + //================================= + // Send 16 bytes data : 0x8000_002C ==> 16 bytes data + //================================= + buring_data[0] = 0x2C; + buring_data[1] = 0x00; + buring_data[2] = 0x00; + buring_data[3] = 0x80; + + for (i = /*0*/page_prog_start, j = 0; i < 16 + page_prog_start/**/; i++, j++) /// <------ bin file + { + buring_data[j + 4] = FW_content[i]; + } + + + if ( i2c_himax_write(client, 0x00 ,buring_data, 20, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + //================================= + // Write command : 0x8000_0024 ==> 0x0000_0002 + //================================= + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x02; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + //================================= + // Send 240 bytes data : 0x8000_002C ==> 240 bytes data + //================================= + + for (j = 0; j < 5; j++) + { + for (i = (page_prog_start + 16 + (j * 48)), k = 0; i < (page_prog_start + 16 + (j * 48)) + program_length; i++, k++) /// <------ bin file + { + buring_data[k+4] = FW_content[i];//(byte)i; + } + + if ( i2c_himax_write(client, 0x00 ,buring_data, program_length+4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + } + + if (!wait_wip(client, 1)) + E("%s:83100_Flash_Programming Fail\n", __func__); + } +} + +bool himax_check_chip_version(struct i2c_client *client) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + uint8_t ret_data = 0x00; + int i = 0; + int ret = 0; + himax_sense_off(client); + for (i = 0; i < 5; i++) + { + // 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver) + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01; + ret = himax_register_write(client, tmp_addr, 1, tmp_data); + if(ret) + return false; + + // 2. Set bank as 0 (0x8001_BD01 = 0x0000_0000) + tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xBD; tmp_addr[0] = 0x01; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + ret = himax_register_write(client, tmp_addr, 1, tmp_data); + if(ret) + return false; + + // 3. Read driver ID register RF4H 1 byte (0x8001_F401) + // Driver register RF4H 1 byte value = 0x84H, read back value will become 0x84848484 + tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xF4; tmp_addr[0] = 0x01; + himax_register_read(client, tmp_addr, 1, tmp_data); + ret_data = tmp_data[0]; + + I("%s:Read driver IC ID = %X\n", __func__, ret_data); + if (ret_data == 0x84) + { + IC_TYPE = HX_83100_SERIES_PWON; + //himax_sense_on(client, 0x01); + ret_data = true; + break; + } + else + { + ret_data = false; + E("%s:Read driver ID register Fail:\n", __func__); + } + } + // 4. After read finish, set DDREG_Req = 0 (0x9000_0020 = 0x0000_0000) (Unlock register R/W from driver) + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_register_write(client, tmp_addr, 1, tmp_data); + //himax_sense_on(client, 0x01); + return ret_data; +} + +#if 1 +int himax_check_CRC(struct i2c_client *client, int mode) +{ + bool burnFW_success = false; + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + int tmp_value; + int CRC_value = 0; + + memset(tmp_data, 0x00, sizeof(tmp_data)); + + if (1) + { + if(mode == fw_image_60k) + { + himax_sram_write(client, (i_TP_CRC_FW_60K)); + burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_60K, 0x4000); + } + else if(mode == fw_image_64k) + { + himax_sram_write(client, (i_TP_CRC_FW_64K)); + burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_64K, 0x4000); + } + else if(mode == fw_image_124k) + { + himax_sram_write(client, (i_TP_CRC_FW_124K)); + burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_124K, 0x4000); + } + else if(mode == fw_image_128k) + { + himax_sram_write(client, (i_TP_CRC_FW_128K)); + burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_128K, 0x4000); + } + if (burnFW_success) + { + I("%s: Start to do CRC FW mode=%d \n", __func__,mode); + himax_sense_on(client, 0x00); // run CRC firmware + + while(true) + { + msleep(100); + + tmp_addr[3] = 0x90; + tmp_addr[2] = 0x08; + tmp_addr[1] = 0x80; + tmp_addr[0] = 0x94; + himax_register_read(client, tmp_addr, 1, tmp_data); + + I("%s: CRC from firmware is %x, %x, %x, %x \n", __func__,tmp_data[3], + tmp_data[2],tmp_data[1],tmp_data[0]); + + if (tmp_data[3] == 0xFF && tmp_data[2] == 0xFF && tmp_data[1] == 0xFF && tmp_data[0] == 0xFF) + { + } + else + break; + } + + CRC_value = tmp_data[3]; + + tmp_value = tmp_data[2] << 8; + CRC_value += tmp_value; + + tmp_value = tmp_data[1] << 16; + CRC_value += tmp_value; + + tmp_value = tmp_data[0] << 24; + CRC_value += tmp_value; + + I("%s: CRC Value is %x \n", __func__, CRC_value); + + //Close Remapping + //===================================== + // Re-map close + //===================================== + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4); + return CRC_value; + } + else + { + E("%s: SRAM write fail\n", __func__); + return 0; + } + } + else + I("%s: NO CRC Check File \n", __func__); + + return 0; +} + +bool Calculate_CRC_with_AP(unsigned char *FW_content , int CRC_from_FW, int mode) +{ + uint8_t tmp_data[4]; + int i, j; + int fw_data; + int fw_data_2; + int CRC = 0xFFFFFFFF; + int PolyNomial = 0x82F63B78; + int length = 0; + + if (mode == fw_image_128k) + length = 0x8000; + else if (mode == fw_image_124k) + length = 0x7C00; + else if (mode == fw_image_64k) + length = 0x4000; + else //if (mode == fw_image_60k) + length = 0x3C00; + + for (i = 0; i < length; i++) + { + fw_data = FW_content[i * 4 ]; + + for (j = 1; j < 4; j++) + { + fw_data_2 = FW_content[i * 4 + j]; + fw_data += (fw_data_2) << (8 * j); + } + + CRC = fw_data ^ CRC; + + for (j = 0; j < 32; j++) + { + if ((CRC % 2) != 0) + { + CRC = ((CRC >> 1) & 0x7FFFFFFF) ^ PolyNomial; + } + else + { + CRC = (((CRC >> 1) ^ 0x7FFFFFFF)& 0x7FFFFFFF); + } + } + } + + I("%s: CRC calculate from bin file is %x \n", __func__, CRC); + + tmp_data[0] = (uint8_t)(CRC >> 24); + tmp_data[1] = (uint8_t)(CRC >> 16); + tmp_data[2] = (uint8_t)(CRC >> 8); + tmp_data[3] = (uint8_t) CRC; + + CRC = tmp_data[0]; + CRC += tmp_data[1] << 8; + CRC += tmp_data[2] << 16; + CRC += tmp_data[3] << 24; + + I("%s: CRC calculate from bin file REVERSE %x \n", __func__, CRC); + I("%s: CRC calculate from FWis %x \n", __func__, CRC_from_FW); + if (CRC_from_FW == CRC) + return true; + else + return false; +} +#endif + +int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref) +{ + int CRC_from_FW = 0; + int burnFW_success = 0; + + if (len != 0x10000) //64k + { + E("%s: The file size is not 64K bytes\n", __func__); + return false; + } + himax_sense_off(client); + msleep(500); + himax_interface_on(client); + if (!himax_sector_erase(client, 0x00000)) + { + E("%s:Sector erase fail!Please restart the IC.\n", __func__); + return false; + } + himax_flash_programming(client, fw, 0x0F000); + + //burnFW_success = himax_83100_Verify(fw, len); + //if(burnFW_success==false) + // return burnFW_success; + + CRC_from_FW = himax_check_CRC(client,fw_image_60k); + burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_60k); + //himax_sense_on(client, 0x01); + return burnFW_success; +} + +int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref) +{ + int CRC_from_FW = 0; + int burnFW_success = 0; + + if (len != 0x10000) //64k + { + E("%s: The file size is not 64K bytes\n", __func__); + return false; + } + himax_sense_off(client); + msleep(500); + himax_interface_on(client); + himax_chip_erase(client); + himax_flash_programming(client, fw, len); + + //burnFW_success = himax_83100_Verify(fw, len); + //if(burnFW_success==false) + // return burnFW_success; + + CRC_from_FW = himax_check_CRC(client,fw_image_64k); + burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_64k); + //himax_sense_on(client, 0x01); + return burnFW_success; +} + +int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref) +{ + int CRC_from_FW = 0; + int burnFW_success = 0; + + if (len != 0x20000) //128k + { + E("%s: The file size is not 128K bytes\n", __func__); + return false; + } + himax_sense_off(client); + msleep(500); + himax_interface_on(client); + if (!himax_block_erase(client)) + { + E("%s:Block erase fail!Please restart the IC.\n", __func__); + return false; + } + + if (!himax_sector_erase(client, 0x10000)) + { + E("%s:Sector erase fail!Please restart the IC.\n", __func__); + return false; + } + himax_flash_programming(client, fw, 0x1F000); + + + //burnFW_success = himax_83100_Verify(fw, len); + //if(burnFW_success==false) + // return burnFW_success; + + CRC_from_FW = himax_check_CRC(client,fw_image_124k); + burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_124k); + //himax_sense_on(client, 0x01); + return burnFW_success; +} + +int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref) +{ + int CRC_from_FW = 0; + int burnFW_success = 0; + + if (len != 0x20000) //128k + { + E("%s: The file size is not 128K bytes\n", __func__); + return false; + } + himax_sense_off(client); + msleep(500); + himax_interface_on(client); + himax_chip_erase(client); + + himax_flash_programming(client, fw, len); + + //burnFW_success = himax_83100_Verify(fw, len); + //if(burnFW_success==false) + // return burnFW_success; + + CRC_from_FW = himax_check_CRC(client,fw_image_128k); + burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_128k); + //himax_sense_on(client, 0x01); + return burnFW_success; +} + +void himax_touch_information(struct i2c_client *client) +{ + uint8_t cmd[4]; + char data[12] = {0}; + + I("%s:IC_TYPE =%d\n", __func__,IC_TYPE); + + if(IC_TYPE == HX_83100_SERIES_PWON) + { + cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xF8; + himax_register_read(client, cmd, 1, data); + + ic_data->HX_RX_NUM = data[1]; + ic_data->HX_TX_NUM = data[2]; + ic_data->HX_MAX_PT = data[3]; + + cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xFC; + himax_register_read(client, cmd, 1, data); + + if((data[1] & 0x04) == 0x04) { + ic_data->HX_XY_REVERSE = true; + } else { + ic_data->HX_XY_REVERSE = false; + } + ic_data->HX_Y_RES = data[3]*256; + cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x01; cmd[0] = 0x00; + himax_register_read(client, cmd, 1, data); + ic_data->HX_Y_RES = ic_data->HX_Y_RES + data[0]; + ic_data->HX_X_RES = data[1]*256 + data[2]; + cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x8C; + himax_register_read(client, cmd, 1, data); + if((data[0] & 0x01) == 1) { + ic_data->HX_INT_IS_EDGE = true; + } else { + ic_data->HX_INT_IS_EDGE = false; + } + if (ic_data->HX_RX_NUM > 40) + ic_data->HX_RX_NUM = 29; + if (ic_data->HX_TX_NUM > 20) + ic_data->HX_TX_NUM = 16; + if (ic_data->HX_MAX_PT > 10) + ic_data->HX_MAX_PT = 10; + if (ic_data->HX_Y_RES > 2000) + ic_data->HX_Y_RES = 1280; + if (ic_data->HX_X_RES > 2000) + ic_data->HX_X_RES = 720; +#ifdef HX_EN_MUT_BUTTON + cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xE8; + himax_register_read(client, cmd, 1, data); + ic_data->HX_BT_NUM = data[3]; +#endif + I("%s:HX_RX_NUM =%d,HX_TX_NUM =%d,HX_MAX_PT=%d \n", __func__,ic_data->HX_RX_NUM,ic_data->HX_TX_NUM,ic_data->HX_MAX_PT); + I("%s:HX_XY_REVERSE =%d,HX_Y_RES =%d,HX_X_RES=%d \n", __func__,ic_data->HX_XY_REVERSE,ic_data->HX_Y_RES,ic_data->HX_X_RES); + I("%s:HX_INT_IS_EDGE =%d \n", __func__,ic_data->HX_INT_IS_EDGE); + } + else + { + ic_data->HX_RX_NUM = 0; + ic_data->HX_TX_NUM = 0; + ic_data->HX_BT_NUM = 0; + ic_data->HX_X_RES = 0; + ic_data->HX_Y_RES = 0; + ic_data->HX_MAX_PT = 0; + ic_data->HX_XY_REVERSE = false; + ic_data->HX_INT_IS_EDGE = false; + } +} + +void himax_read_FW_ver(struct i2c_client *client) +{ + uint8_t cmd[4]; + uint8_t data[64] = {0}; + + //===================================== + // Read FW version : 0x0000_E303 + //===================================== + cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x00; + himax_register_read(client, cmd, 1, data); + + ic_data->vendor_config_ver = data[3]<<8; + + cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x04; + himax_register_read(client, cmd, 1, data); + + ic_data->vendor_config_ver = data[0] | ic_data->vendor_config_ver; + I("CFG_VER : %X \n",ic_data->vendor_config_ver); + + cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x28; + himax_register_read(client, cmd, 1, data); + + ic_data->vendor_fw_ver = data[0]<<8 | data[1]; + I("FW_VER : %X \n",ic_data->vendor_fw_ver); + + + return; +} + +bool himax_ic_package_check(struct i2c_client *client) +{ +#if 0 + uint8_t cmd[3]; + uint8_t data[3]; + + memset(cmd, 0x00, sizeof(cmd)); + memset(data, 0x00, sizeof(data)); + + if (i2c_himax_read(client, 0xD1, cmd, 3, HIMAX_I2C_RETRY_TIMES) < 0) + return false ; + + if (i2c_himax_read(client, 0x31, data, 3, HIMAX_I2C_RETRY_TIMES) < 0) + return false; + + if((data[0] == 0x85 && data[1] == 0x29)) + { + IC_TYPE = HX_85XX_F_SERIES_PWON; + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; + //Himax: Set FW and CFG Flash Address + FW_VER_MAJ_FLASH_ADDR = 64901; //0xFD85 + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 64902; //0xFD86 + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 64928; //0xFDA0 + CFG_VER_MAJ_FLASH_LENG = 12; + CFG_VER_MIN_FLASH_ADDR = 64940; //0xFDAC + CFG_VER_MIN_FLASH_LENG = 12; + I("Himax IC package 852x F\n"); + } + if((data[0] == 0x85 && data[1] == 0x30) || (cmd[0] == 0x05 && cmd[1] == 0x85 && cmd[2] == 0x29)) + { + IC_TYPE = HX_85XX_E_SERIES_PWON; + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; + //Himax: Set FW and CFG Flash Address + FW_VER_MAJ_FLASH_ADDR = 133; //0x0085 + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 134; //0x0086 + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 160; //0x00A0 + CFG_VER_MAJ_FLASH_LENG = 12; + CFG_VER_MIN_FLASH_ADDR = 172; //0x00AC + CFG_VER_MIN_FLASH_LENG = 12; + I("Himax IC package 852x E\n"); + } + else if((data[0] == 0x85 && data[1] == 0x31)) + { + IC_TYPE = HX_85XX_ES_SERIES_PWON; + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; + //Himax: Set FW and CFG Flash Address + FW_VER_MAJ_FLASH_ADDR = 133; //0x0085 + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 134; //0x0086 + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 160; //0x00A0 + CFG_VER_MAJ_FLASH_LENG = 12; + CFG_VER_MIN_FLASH_ADDR = 172; //0x00AC + CFG_VER_MIN_FLASH_LENG = 12; + I("Himax IC package 852x ES\n"); + } + else if ((data[0] == 0x85 && data[1] == 0x28) || (cmd[0] == 0x04 && cmd[1] == 0x85 && + (cmd[2] == 0x26 || cmd[2] == 0x27 || cmd[2] == 0x28))) { + IC_TYPE = HX_85XX_D_SERIES_PWON; + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; + //Himax: Set FW and CFG Flash Address + FW_VER_MAJ_FLASH_ADDR = 133; // 0x0085 + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 134; // 0x0086 + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 160; // 0x00A0 + CFG_VER_MAJ_FLASH_LENG = 12; + CFG_VER_MIN_FLASH_ADDR = 172; // 0x00AC + CFG_VER_MIN_FLASH_LENG = 12; + I("Himax IC package 852x D\n"); + } else if ((data[0] == 0x85 && data[1] == 0x23) || (cmd[0] == 0x03 && cmd[1] == 0x85 && + (cmd[2] == 0x26 || cmd[2] == 0x27 || cmd[2] == 0x28 || cmd[2] == 0x29))) { + IC_TYPE = HX_85XX_C_SERIES_PWON; + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW; + //Himax: Set FW and CFG Flash Address + FW_VER_MAJ_FLASH_ADDR = 133; // 0x0085 + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 134; // 0x0086 + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 135; // 0x0087 + CFG_VER_MAJ_FLASH_LENG = 12; + CFG_VER_MIN_FLASH_ADDR = 147; // 0x0093 + CFG_VER_MIN_FLASH_LENG = 12; + I("Himax IC package 852x C\n"); + } else if ((data[0] == 0x85 && data[1] == 0x26) || + (cmd[0] == 0x02 && cmd[1] == 0x85 && + (cmd[2] == 0x19 || cmd[2] == 0x25 || cmd[2] == 0x26))) { + IC_TYPE = HX_85XX_B_SERIES_PWON; + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW; + //Himax: Set FW and CFG Flash Address + FW_VER_MAJ_FLASH_ADDR = 133; // 0x0085 + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 728; // 0x02D8 + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 692; // 0x02B4 + CFG_VER_MAJ_FLASH_LENG = 3; + CFG_VER_MIN_FLASH_ADDR = 704; // 0x02C0 + CFG_VER_MIN_FLASH_LENG = 3; + I("Himax IC package 852x B\n"); + } else if ((data[0] == 0x85 && data[1] == 0x20) || (cmd[0] == 0x01 && + cmd[1] == 0x85 && cmd[2] == 0x19)) { + IC_TYPE = HX_85XX_A_SERIES_PWON; + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW; + I("Himax IC package 852x A\n"); + } else { + E("Himax IC package incorrect!!\n"); + }*/ +#else + IC_TYPE = HX_83100_SERIES_PWON; + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; + //Himax: Set FW and CFG Flash Address + FW_VER_MAJ_FLASH_ADDR = 57384; //0xE028 + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 57385; //0xE029 + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 58115; //0xE303 + CFG_VER_MAJ_FLASH_LENG = 1; + CFG_VER_MIN_FLASH_ADDR = 58116; //0xE304 + CFG_VER_MIN_FLASH_LENG = 1; + I("Himax IC package 83100_in\n"); + +#endif + return true; +} + +void himax_read_event_stack(struct i2c_client *client, uint8_t *buf, uint8_t length) +{ + uint8_t cmd[4]; + + cmd[3] = 0x90; cmd[2] = 0x06; cmd[1] = 0x00; cmd[0] = 0x00; + if ( i2c_himax_write(client, 0x00 ,cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + } + + cmd[0] = 0x00; + if ( i2c_himax_write(client, 0x0C ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + } + + i2c_himax_read(client, 0x08, buf, length, HIMAX_I2C_RETRY_TIMES); +} + +#if 0 +static void himax_83100_Flash_Write(uint8_t * reg_byte, uint8_t * write_data) +{ + uint8_t tmpbyte[2]; + + if ( i2c_himax_write(private_ts->client, 0x00 ,®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(private_ts->client, 0x01 ,®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(private_ts->client, 0x02 ,®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(private_ts->client, 0x03 ,®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(private_ts->client, 0x04 ,&write_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(private_ts->client, 0x05 ,&write_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(private_ts->client, 0x06 ,&write_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(private_ts->client, 0x07 ,&write_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if (isBusrtOn == false) + { + tmpbyte[0] = 0x01; + if ( i2c_himax_write(private_ts->client, 0x0C ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + } +} +#endif +#if 0 +static void himax_83100_Flash_Burst_Write(uint8_t * reg_byte, uint8_t * write_data) +{ + //uint8_t tmpbyte[2]; + int i = 0; + + if ( i2c_himax_write(private_ts->client, 0x00 ,®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(private_ts->client, 0x01 ,®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(private_ts->client, 0x02 ,®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(private_ts->client, 0x03 ,®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + // Write 256 bytes with continue burst mode + for (i = 0; i < 256; i = i + 4) + { + if ( i2c_himax_write(private_ts->client, 0x04 ,&write_data[i], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(private_ts->client, 0x05 ,&write_data[i+1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(private_ts->client, 0x06 ,&write_data[i+2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + if ( i2c_himax_write(private_ts->client, 0x07 ,&write_data[i+3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + } + + //if (isBusrtOn == false) + //{ + // tmpbyte[0] = 0x01; + // if ( i2c_himax_write(private_ts->client, 0x0C ,&tmpbyte[0], 1, 3) < 0) { + // E("%s: i2c access fail!\n", __func__); + // return; + // } + //} + +} +#endif + +#if 0 +static bool himax_83100_Verify(uint8_t *FW_File, int FW_Size) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + uint8_t out_buffer[20]; + uint8_t in_buffer[260]; + + int fail_addr=0, fail_cnt=0; + int page_prog_start = 0; + int i = 0; + + himax_interface_on(private_ts->client); + himax_burst_enable(private_ts->client, 0); + + //===================================== + // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + //===================================== + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80; + himax_83100_Flash_Write(tmp_addr, tmp_data); + + for (page_prog_start = 0; page_prog_start < FW_Size; page_prog_start = page_prog_start + 256) + { + //================================= + // SPI Transfer Control + // Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF + // Set read start address : 0x8000_0028 ==> 0x0000_0000 + // Set command : 0x8000_0024 ==> 0x0000_003B + //================================= + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x69; tmp_data[2] = 0x40; tmp_data[1] = 0x02; tmp_data[0] = 0xFF; + himax_83100_Flash_Write(tmp_addr, tmp_data); + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; + if (page_prog_start < 0x100) + { + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = 0x00; + tmp_data[0] = (uint8_t)page_prog_start; + } + else if (page_prog_start >= 0x100 && page_prog_start < 0x10000) + { + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = (uint8_t)(page_prog_start >> 8); + tmp_data[0] = (uint8_t)page_prog_start; + } + else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000) + { + tmp_data[3] = 0x00; + tmp_data[2] = (uint8_t)(page_prog_start >> 16); + tmp_data[1] = (uint8_t)(page_prog_start >> 8); + tmp_data[0] = (uint8_t)page_prog_start; + } + himax_83100_Flash_Write(tmp_addr, tmp_data); + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x3B; + himax_83100_Flash_Write(tmp_addr, tmp_data); + + //================================== + // AHB_I2C Burst Read + // Set SPI data register : 0x8000_002C ==> 0x00 + //================================== + out_buffer[0] = 0x2C; + out_buffer[1] = 0x00; + out_buffer[2] = 0x00; + out_buffer[3] = 0x80; + i2c_himax_write(private_ts->client, 0x00 ,out_buffer, 4, HIMAX_I2C_RETRY_TIMES); + + //================================== + // Read access : 0x0C ==> 0x00 + //================================== + out_buffer[0] = 0x00; + i2c_himax_write(private_ts->client, 0x0C ,out_buffer, 1, HIMAX_I2C_RETRY_TIMES); + + //================================== + // Read 128 bytes two times + //================================== + i2c_himax_read(private_ts->client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES); + for (i = 0; i < 128; i++) + flash_buffer[i + page_prog_start] = in_buffer[i]; + + i2c_himax_read(private_ts->client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES); + for (i = 0; i < 128; i++) + flash_buffer[(i + 128) + page_prog_start] = in_buffer[i]; + + //tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C; + //himax_register_read(tmp_addr, 32, out in_buffer); + //for (int i = 0; i < 128; i++) + // flash_buffer[i + page_prog_start] = in_buffer[i]; + //tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C; + //himax_register_read(tmp_addr, 32, out in_buffer); + //for (int i = 0; i < 128; i++) + // flash_buffer[i + page_prog_start] = in_buffer[i]; + + I("%s:Verify Progress: %x\n", __func__, page_prog_start); + } + + fail_cnt = 0; + for (i = 0; i < FW_Size; i++) + { + if (FW_File[i] != flash_buffer[i]) + { + if (fail_cnt == 0) + fail_addr = i; + + fail_cnt++; + //E("%s Fail Block:%x\n", __func__, i); + //return false; + } + } + if (fail_cnt > 0) + { + E("%s:Start Fail Block:%x and fail block count=%x\n" , __func__,fail_addr,fail_cnt); + return false; + } + + I("%s:Byte read verify pass.\n", __func__); + return true; + +} +#endif + +void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data) +{ + int i; + int cnt = 0; + unsigned char tmp_addr[4]; + unsigned char tmp_data[4]; + uint8_t max_i2c_size = 32; + int total_size = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM * 2; + int total_size_4bytes = total_size / 4; + int total_read_times = 0; + unsigned long address = 0x08000468; + tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x64; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x5A; tmp_data[0] = 0xA5; + himax_flash_write_burst(client, tmp_addr, tmp_data); + do + { + cnt++; + himax_register_read(client, tmp_addr, 1, tmp_data); + usleep_range(10000, 20000); + } while ((tmp_data[1] != 0xA5 || tmp_data[0] != 0x5A) && cnt < 100); + tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x68; + if (total_size_4bytes % max_i2c_size == 0) + { + total_read_times = total_size_4bytes / max_i2c_size; + } + else + { + total_read_times = total_size_4bytes / max_i2c_size + 1; + } + for (i = 0; i < (total_read_times); i++) + { + if ( total_size_4bytes >= max_i2c_size) + { + himax_register_read(client, tmp_addr, max_i2c_size, &info_data[i*max_i2c_size*4]); + total_size_4bytes = total_size_4bytes - max_i2c_size; + } + else + { + himax_register_read(client, tmp_addr, total_size_4bytes % max_i2c_size, &info_data[i*max_i2c_size*4]); + } + address += max_i2c_size*4; + tmp_addr[1] = (uint8_t)((address>>8)&0x00FF); + tmp_addr[0] = (uint8_t)((address)&0x00FF); + } + tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x64; + tmp_data[3] = 0x11; tmp_data[2] = 0x22; tmp_data[1] = 0x33; tmp_data[0] = 0x44; + himax_flash_write_burst(client, tmp_addr, tmp_data); +} +//ts_work +int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max){ + int RawDataLen; + if (raw_cnt_rmd != 0x00) { + RawDataLen = 124 - ((HX_MAX_PT+raw_cnt_max+3)*4) - 1; + }else{ + RawDataLen = 124 - ((HX_MAX_PT+raw_cnt_max+2)*4) - 1; + } + return RawDataLen; +} + +bool read_event_stack(struct i2c_client *client, uint8_t *buf, int length) +{ + uint8_t cmd[4]; + + if(length > 56) + length = 124; + //===================== + //AHB I2C Burst Read + //===================== + cmd[0] = 0x31; + if ( i2c_himax_write(client, 0x13 ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + goto err_workqueue_out; + } + + cmd[0] = 0x10; + if ( i2c_himax_write(client, 0x0D ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + goto err_workqueue_out; + } + //===================== + //Read event stack + //===================== + cmd[3] = 0x90; cmd[2] = 0x06; cmd[1] = 0x00; cmd[0] = 0x00; + if ( i2c_himax_write(client, 0x00 ,cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + goto err_workqueue_out; + } + + cmd[0] = 0x00; + if ( i2c_himax_write(client, 0x0C ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + goto err_workqueue_out; + } + i2c_himax_read(client, 0x08, buf, length,HIMAX_I2C_RETRY_TIMES); + return 1; + + err_workqueue_out: + return 0; +} + +bool post_read_event_stack(struct i2c_client *client) +{ + return 1; +} +bool diag_check_sum( uint8_t hx_touch_info_size, uint8_t *buf) //return checksum value +{ + uint16_t check_sum_cal = 0; + int i; + + //Check 124th byte CRC + for (i = hx_touch_info_size, check_sum_cal = 0; i < 124; i=i+2) + { + check_sum_cal += (buf[i+1]*256 + buf[i]); + } + if (check_sum_cal % 0x10000 != 0) + { + I("%s: diag check sum fail! check_sum_cal=%X, hx_touch_info_size=%d, \n",__func__,check_sum_cal, hx_touch_info_size); + return 0; + } + return 1; +} + + +void diag_parse_raw_data(int hx_touch_info_size, int RawDataLen, int mul_num, int self_num, uint8_t *buf, uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data) +{ + int RawDataLen_word; + int index = 0; + int temp1, temp2,i; + + if (buf[hx_touch_info_size] == 0x3A && buf[hx_touch_info_size+1] == 0xA3 && buf[hx_touch_info_size+2] > 0 && buf[hx_touch_info_size+3] == diag_cmd+5 ) + { + RawDataLen_word = RawDataLen/2; + index = (buf[hx_touch_info_size+2] - 1) * RawDataLen_word; + //I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num); + for (i = 0; i < RawDataLen_word; i++) + { + temp1 = index + i; + + if (temp1 < mul_num) + { //mutual + mutual_data[index + i] = buf[i*2 + hx_touch_info_size+4+1]*256 + buf[i*2 + hx_touch_info_size+4]; //4: RawData Header, 1:HSB + } + else + {//self + temp1 = i + index; + temp2 = self_num + mul_num; + + if (temp1 >= temp2) + { + break; + } + + self_data[i+index-mul_num] = buf[i*2 + hx_touch_info_size+4]; //4: RawData Header + self_data[i+index-mul_num+1] = buf[i*2 + hx_touch_info_size+4+1]; + } + } + } + else + { + I("[HIMAX TP MSG]%s: header format is wrong!\n", __func__); + I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num); + } +} diff --git a/drivers/input/touchscreen/hxchipset/himax_ic.h b/drivers/input/touchscreen/hxchipset/himax_ic.h new file mode 100644 index 0000000000000..18cd12b8b36fe --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_ic.h @@ -0,0 +1,82 @@ +/* Himax Android Driver Sample Code for HMX83100 chipset +* +* Copyright (C) 2015 Himax Corporation. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#include "himax_platform.h" +#include "himax_common.h" + +#include + + +#define HX_85XX_A_SERIES_PWON 1 +#define HX_85XX_B_SERIES_PWON 2 +#define HX_85XX_C_SERIES_PWON 3 +#define HX_85XX_D_SERIES_PWON 4 +#define HX_85XX_E_SERIES_PWON 5 +#define HX_85XX_ES_SERIES_PWON 6 +#define HX_85XX_F_SERIES_PWON 7 +#define HX_83100_SERIES_PWON 8 + +#define HX_TP_BIN_CHECKSUM_SW 1 +#define HX_TP_BIN_CHECKSUM_HW 2 +#define HX_TP_BIN_CHECKSUM_CRC 3 + +enum fw_image_type { + fw_image_60k = 0x01, + fw_image_64k, + fw_image_124k, + fw_image_128k, +}; + +int himax_hand_shaking(struct i2c_client *client); +void himax_set_SMWP_enable(struct i2c_client *client,uint8_t SMWP_enable); +void himax_get_SMWP_enable(struct i2c_client *client,uint8_t *tmp_data); +void himax_set_HSEN_enable(struct i2c_client *client,uint8_t HSEN_enable); +void himax_get_HSEN_enable(struct i2c_client *client,uint8_t *tmp_data); +void himax_diag_register_set(struct i2c_client *client, uint8_t diag_command); +void himax_flash_dump_func(struct i2c_client *client, uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer); +int himax_chip_self_test(struct i2c_client *client); +int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte); ////himax_83100_BURST_INC0_EN +void himax_register_read(struct i2c_client *client, uint8_t *read_addr, int read_length, uint8_t *read_data); ////RegisterRead83100 +void himax_flash_read(struct i2c_client *client, uint8_t *reg_byte, uint8_t *read_data); ////himax_83100_Flash_Read +void himax_flash_write_burst(struct i2c_client *client, uint8_t * reg_byte, uint8_t * write_data); ////himax_83100_Flash_Write_Burst +int himax_flash_write_burst_lenth(struct i2c_client *client, uint8_t *reg_byte, uint8_t *write_data, int length); ////himax_83100_Flash_Write_Burst_lenth +int himax_register_write(struct i2c_client *client, uint8_t *write_addr, int write_length, uint8_t *write_data); ////RegisterWrite83100 +void himax_sense_off(struct i2c_client *client); ////himax_83100_SenseOff +void himax_interface_on(struct i2c_client *client); ////himax_83100_Interface_on +bool wait_wip(struct i2c_client *client, int Timing); +void himax_sense_on(struct i2c_client *client, uint8_t FlashMode); ////himax_83100_SenseOn +void himax_chip_erase(struct i2c_client *client); ////himax_83100_Chip_Erase +bool himax_block_erase(struct i2c_client *client); ////himax_83100_Block_Erase +bool himax_sector_erase(struct i2c_client *client, int start_addr); ////himax_83100_Sector_Erase +void himax_sram_write(struct i2c_client *client, uint8_t *FW_content); ////himax_83100_Sram_Write +bool himax_sram_verify(struct i2c_client *client, uint8_t *FW_File, int FW_Size); ////himax_83100_Sram_Verify +void himax_flash_programming(struct i2c_client *client, uint8_t *FW_content, int FW_Size); ////himax_83100_Flash_Programming +bool himax_check_chip_version(struct i2c_client *client); ////himax_83100_CheckChipVersion +int himax_check_CRC(struct i2c_client *client, int mode); ////himax_83100_Check_CRC +bool Calculate_CRC_with_AP(unsigned char *FW_content , int CRC_from_FW, int mode); +int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref); +int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref); +int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref); +int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref); +void himax_touch_information(struct i2c_client *client); +void himax_read_FW_ver(struct i2c_client *client); +bool himax_ic_package_check(struct i2c_client *client); +void himax_read_event_stack(struct i2c_client *client, uint8_t *buf, uint8_t length); +int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max); +bool read_event_stack(struct i2c_client *client, uint8_t *buf_ts, int length); +bool post_read_event_stack(struct i2c_client *client); +bool diag_check_sum( uint8_t hx_touch_info_size, uint8_t *buf_ts); //return checksum value +void diag_parse_raw_data(int hx_touch_info_size, int RawDataLen, int mul_num, int self_num, uint8_t *buf_ts, uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data); +void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data); \ No newline at end of file diff --git a/drivers/input/touchscreen/hxchipset/himax_platform.c b/drivers/input/touchscreen/hxchipset/himax_platform.c new file mode 100644 index 0000000000000..7e8a1d6572c51 --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_platform.c @@ -0,0 +1,796 @@ +/* Himax Android Driver Sample Code for HIMAX chipset +* +* Copyright (C) 2015 Himax Corporation. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#include "himax_platform.h" +#include "himax_common.h" + +int irq_enable_count = 0; +#ifdef HX_SMART_WAKEUP +#define TS_WAKE_LOCK_TIMEOUT (2 * HZ) +#endif + +#define PINCTRL_STATE_ACTIVE "pmx_ts_active" +#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend" +#define PINCTRL_STATE_RELEASE "pmx_ts_release" + +extern struct himax_ic_data* ic_data; +extern void himax_ts_work(struct himax_ts_data *ts); +extern enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer); +extern int himax_ts_init(struct himax_ts_data *ts); + +extern int tp_rst_gpio; + +#ifdef HX_TP_PROC_DIAG +extern uint8_t getDiagCommand(void); +#endif + +void himax_vk_parser(struct device_node *dt, + struct himax_i2c_platform_data *pdata) +{ + u32 data = 0; + uint8_t cnt = 0, i = 0; + uint32_t coords[4] = {0}; + struct device_node *node, *pp = NULL; + struct himax_virtual_key *vk; + + node = of_parse_phandle(dt, "virtualkey", 0); + if (node == NULL) { + I(" DT-No vk info in DT"); + return; + } else { + while ((pp = of_get_next_child(node, pp))) + cnt++; + if (!cnt) + return; + + vk = kzalloc(cnt * (sizeof *vk), GFP_KERNEL); + if (!vk) + return; + pp = NULL; + while ((pp = of_get_next_child(node, pp))) { + if (of_property_read_u32(pp, "idx", &data) == 0) + vk[i].index = data; + if (of_property_read_u32_array(pp, "range", coords, 4) == 0) { + vk[i].x_range_min = coords[0], vk[i].x_range_max = coords[1]; + vk[i].y_range_min = coords[2], vk[i].y_range_max = coords[3]; + } else + I(" range faile"); + i++; + } + pdata->virtual_key = vk; + for (i = 0; i < cnt; i++) + I(" vk[%d] idx:%d x_min:%d, y_max:%d", i,pdata->virtual_key[i].index, + pdata->virtual_key[i].x_range_min, pdata->virtual_key[i].y_range_max); + } +} + +int himax_parse_dt(struct himax_ts_data *ts, + struct himax_i2c_platform_data *pdata) +{ + int rc, coords_size = 0; + uint32_t coords[4] = {0}; + struct property *prop; + struct device_node *dt = ts->client->dev.of_node; + u32 data = 0; + + prop = of_find_property(dt, "himax,panel-coords", NULL); + if (prop) { + coords_size = prop->length / sizeof(u32); + if (coords_size != 4) + D(" %s:Invalid panel coords size %d", __func__, coords_size); + } + + if (of_property_read_u32_array(dt, "himax,panel-coords", coords, coords_size) == 0) { + pdata->abs_x_min = coords[0], pdata->abs_x_max = coords[1]; + pdata->abs_y_min = coords[2], pdata->abs_y_max = coords[3]; + I(" DT-%s:panel-coords = %d, %d, %d, %d\n", __func__, pdata->abs_x_min, + pdata->abs_x_max, pdata->abs_y_min, pdata->abs_y_max); + } + + prop = of_find_property(dt, "himax,display-coords", NULL); + if (prop) { + coords_size = prop->length / sizeof(u32); + if (coords_size != 4) + D(" %s:Invalid display coords size %d", __func__, coords_size); + } + rc = of_property_read_u32_array(dt, "himax,display-coords", coords, coords_size); + if (rc && (rc != -EINVAL)) { + D(" %s:Fail to read display-coords %d\n", __func__, rc); + return rc; + } + pdata->screenWidth = coords[1]; + pdata->screenHeight = coords[3]; + I(" DT-%s:display-coords = (%d, %d)", __func__, pdata->screenWidth, + pdata->screenHeight); + + pdata->gpio_irq = of_get_named_gpio(dt, "himax,irq-gpio", 0); + if (!gpio_is_valid(pdata->gpio_irq)) { + I(" DT:gpio_irq value is not valid\n"); + } + + pdata->gpio_reset = of_get_named_gpio(dt, "himax,rst-gpio", 0); + if (!gpio_is_valid(pdata->gpio_reset)) { + I(" DT:gpio_rst value is not valid\n"); + } + pdata->gpio_3v3_en = of_get_named_gpio(dt, "himax,3v3-gpio", 0); + if (!gpio_is_valid(pdata->gpio_3v3_en)) { + I(" DT:gpio_3v3_en value is not valid\n"); + } + I(" DT:gpio_irq=%d, gpio_rst=%d, gpio_3v3_en=%d", pdata->gpio_irq, pdata->gpio_reset, pdata->gpio_3v3_en); + + if (of_property_read_u32(dt, "report_type", &data) == 0) { + pdata->protocol_type = data; + I(" DT:protocol_type=%d", pdata->protocol_type); + } + + himax_vk_parser(dt, pdata); + + return 0; +} + +int i2c_himax_read(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry) +{ + int retry; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = &command, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = length, + .buf = data, + } + }; + + for (retry = 0; retry < toRetry; retry++) { + if (i2c_transfer(client->adapter, msg, 2) == 2) + break; + msleep(20); + } + if (retry == toRetry) { + E("%s: i2c_read_block retry over %d\n", + __func__, toRetry); + return -EIO; + } + return 0; + +} + +int i2c_himax_write(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry) +{ + int retry/*, loop_i*/; + uint8_t buf[length + 1]; + + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = length + 1, + .buf = buf, + } + }; + + buf[0] = command; + memcpy(buf+1, data, length); + + for (retry = 0; retry < toRetry; retry++) { + if (i2c_transfer(client->adapter, msg, 1) == 1) + break; + msleep(20); + } + + if (retry == toRetry) { + E("%s: i2c_write_block retry over %d\n", + __func__, toRetry); + return -EIO; + } + return 0; + +} + +int i2c_himax_read_command(struct i2c_client *client, uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry) +{ + int retry; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = length, + .buf = data, + } + }; + + for (retry = 0; retry < toRetry; retry++) { + if (i2c_transfer(client->adapter, msg, 1) == 1) + break; + msleep(20); + } + if (retry == toRetry) { + E("%s: i2c_read_block retry over %d\n", + __func__, toRetry); + return -EIO; + } + return 0; +} + +int i2c_himax_write_command(struct i2c_client *client, uint8_t command, uint8_t toRetry) +{ + return i2c_himax_write(client, command, NULL, 0, toRetry); +} + +int i2c_himax_master_write(struct i2c_client *client, uint8_t *data, uint8_t length, uint8_t toRetry) +{ + int retry/*, loop_i*/; + uint8_t buf[length]; + + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = length, + .buf = buf, + } + }; + + memcpy(buf, data, length); + + for (retry = 0; retry < toRetry; retry++) { + if (i2c_transfer(client->adapter, msg, 1) == 1) + break; + msleep(20); + } + + if (retry == toRetry) { + E("%s: i2c_write_block retry over %d\n", + __func__, toRetry); + return -EIO; + } + return 0; +} + +void himax_int_enable(int irqnum, int enable) +{ + if (enable == 1 && irq_enable_count == 0) { + enable_irq(irqnum); + irq_enable_count++; + } else if (enable == 0 && irq_enable_count == 1) { + disable_irq_nosync(irqnum); + irq_enable_count--; + } + I("irq_enable_count = %d", irq_enable_count); +} + +void himax_rst_gpio_set(int pinnum, uint8_t value) +{ + gpio_direction_output(pinnum, value); +} + +uint8_t himax_int_gpio_read(int pinnum) +{ + return gpio_get_value(pinnum); +} + +#if defined(CONFIG_HMX_DB) +static int himax_regulator_configure(struct i2c_client *client,struct himax_i2c_platform_data *pdata) +{ + int retval; + pdata->vcc_dig = regulator_get(&client->dev, + "vdd"); + if (IS_ERR(pdata->vcc_dig)) + { + E("%s: Failed to get regulator vdd\n", + __func__); + retval = PTR_ERR(pdata->vcc_dig); + return retval; + } + pdata->vcc_ana = regulator_get(&client->dev, + "avdd"); + if (IS_ERR(pdata->vcc_ana)) + { + E("%s: Failed to get regulator avdd\n", + __func__); + retval = PTR_ERR(pdata->vcc_ana); + regulator_put(pdata->vcc_ana); + return retval; + } + + return 0; +}; + +static int himax_power_on(struct himax_i2c_platform_data *pdata, bool on) +{ + int retval; + + if (on) + { + retval = regulator_enable(pdata->vcc_dig); + if (retval) + { + E("%s: Failed to enable regulator vdd\n", + __func__); + return retval; + } + msleep(100); + retval = regulator_enable(pdata->vcc_ana); + if (retval) + { + E("%s: Failed to enable regulator avdd\n", + __func__); + regulator_disable(pdata->vcc_dig); + return retval; + } + } + else + { + regulator_disable(pdata->vcc_dig); + regulator_disable(pdata->vcc_ana); + } + + return 0; +} + +int himax_ts_pinctrl_init(struct himax_ts_data *ts) +{ + int retval; + + /* Get pinctrl if target uses pinctrl */ + ts->ts_pinctrl = devm_pinctrl_get(&(ts->client->dev)); + if (IS_ERR_OR_NULL(ts->ts_pinctrl)) { + retval = PTR_ERR(ts->ts_pinctrl); + dev_dbg(&ts->client->dev, + "Target does not use pinctrl %d\n", retval); + goto err_pinctrl_get; + } + + ts->pinctrl_state_active + = pinctrl_lookup_state(ts->ts_pinctrl, + PINCTRL_STATE_ACTIVE); + if (IS_ERR_OR_NULL(ts->pinctrl_state_active)) { + retval = PTR_ERR(ts->pinctrl_state_active); + dev_err(&ts->client->dev, + "Can not lookup %s pinstate %d\n", + PINCTRL_STATE_ACTIVE, retval); + goto err_pinctrl_lookup; + } + + ts->pinctrl_state_suspend + = pinctrl_lookup_state(ts->ts_pinctrl, + PINCTRL_STATE_SUSPEND); + if (IS_ERR_OR_NULL(ts->pinctrl_state_suspend)) { + retval = PTR_ERR(ts->pinctrl_state_suspend); + dev_err(&ts->client->dev, + "Can not lookup %s pinstate %d\n", + PINCTRL_STATE_SUSPEND, retval); + goto err_pinctrl_lookup; + } + + ts->pinctrl_state_release + = pinctrl_lookup_state(ts->ts_pinctrl, + PINCTRL_STATE_RELEASE); + if (IS_ERR_OR_NULL(ts->pinctrl_state_release)) { + retval = PTR_ERR(ts->pinctrl_state_release); + dev_dbg(&ts->client->dev, + "Can not lookup %s pinstate %d\n", + PINCTRL_STATE_RELEASE, retval); + } + + return 0; + +err_pinctrl_lookup: + devm_pinctrl_put(ts->ts_pinctrl); +err_pinctrl_get: + ts->ts_pinctrl = NULL; + return retval; +} + +int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata) +{ + int error; + + error = himax_regulator_configure(client, pdata); + if (error) + { + E("Failed to intialize hardware\n"); + goto err_regulator_not_on; + } + +#ifdef HX_RST_PIN_FUNC + if (gpio_is_valid(pdata->gpio_reset)) + { + /* configure touchscreen reset out gpio */ + error = gpio_request(pdata->gpio_reset, "hmx_reset_gpio"); + if (error) + { + E("unable to request gpio [%d]\n", + pdata->gpio_reset); + goto err_regulator_on; + } + + error = gpio_direction_output(pdata->gpio_reset, 0); + if (error) + { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + goto err_gpio_reset_req; + } + } +#endif + + error = himax_power_on(pdata, true); + if (error) + { + E("Failed to power on hardware\n"); + goto err_gpio_reset_req; + } +#ifdef HX_IRQ_PIN_FUNC + if (gpio_is_valid(pdata->gpio_irq)) + { + /* configure touchscreen irq gpio */ + error = gpio_request(pdata->gpio_irq, "hmx_gpio_irq"); + if (error) + { + E("unable to request gpio [%d]\n", + pdata->gpio_irq); + goto err_power_on; + } + error = gpio_direction_input(pdata->gpio_irq); + if (error) + { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_irq); + goto err_gpio_irq_req; + } + client->irq = gpio_to_irq(pdata->gpio_irq); + } + else + { + E("irq gpio not provided\n"); + goto err_power_on; + } +#endif + + msleep(20); + +#ifdef HX_RST_PIN_FUNC + if (gpio_is_valid(pdata->gpio_reset)) + { + error = gpio_direction_output(pdata->gpio_reset, 1); + if (error) + { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + goto err_gpio_irq_req; + } + } +#endif + return 0; +#ifdef HX_RST_PIN_FUNC + err_gpio_irq_req: +#endif +#ifdef HX_IRQ_PIN_FUNC + if (gpio_is_valid(pdata->gpio_irq)) + gpio_free(pdata->gpio_irq); + err_power_on: +#endif + himax_power_on(pdata, false); + err_gpio_reset_req: +#ifdef HX_RST_PIN_FUNC + if (gpio_is_valid(pdata->gpio_reset)) + gpio_free(pdata->gpio_reset); + err_regulator_on: +#endif + err_regulator_not_on: + + return error; +} + +#else +int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata) +{ + int error=0; + +#ifdef HX_RST_PIN_FUNC + if (pdata->gpio_reset >= 0) + { + error = gpio_request(pdata->gpio_reset, "himax-reset"); + if (error < 0) + { + E("%s: request reset pin failed\n", __func__); + return error; + } + error = gpio_direction_output(pdata->gpio_reset, 0); + if (error) + { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + return error; + } + } +#endif + if (pdata->gpio_3v3_en >= 0) + { + error = gpio_request(pdata->gpio_3v3_en, "himax-3v3_en"); + if (error < 0) + { + E("%s: request 3v3_en pin failed\n", __func__); + return error; + } + gpio_direction_output(pdata->gpio_3v3_en, 1); + I("3v3_en pin =%d\n", gpio_get_value(pdata->gpio_3v3_en)); + } + +#ifdef HX_IRQ_PIN_FUNC + if (gpio_is_valid(pdata->gpio_irq)) + { + /* configure touchscreen irq gpio */ + error = gpio_request(pdata->gpio_irq, "himax_gpio_irq"); + if (error) + { + E("unable to request gpio [%d]\n",pdata->gpio_irq); + return error; + } + error = gpio_direction_input(pdata->gpio_irq); + if (error) + { + E("unable to set direction for gpio [%d]\n",pdata->gpio_irq); + return error; + } + client->irq = gpio_to_irq(pdata->gpio_irq); + } + else + { + E("irq gpio not provided\n"); + return error; + } +#endif + + msleep(20); + +#ifdef HX_RST_PIN_FUNC + if (pdata->gpio_reset >= 0) + { + error = gpio_direction_output(pdata->gpio_reset, 1); + if (error) + { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + return error; + } + } + msleep(20); +#endif + + return error; + } +#endif + +static void himax_ts_isr_func(struct himax_ts_data *ts) +{ + himax_ts_work(ts); +} + +irqreturn_t himax_ts_thread(int irq, void *ptr) +{ + uint8_t diag_cmd; + struct himax_ts_data *ts = ptr; + struct timespec timeStart, timeEnd, timeDelta; + + diag_cmd = getDiagCommand(); + + if (ts->debug_log_level & BIT(2)) { + getnstimeofday(&timeStart); + usleep_range(5000, 7000); + //I(" Irq start time = %ld.%06ld s\n", + // timeStart.tv_sec, timeStart.tv_nsec/1000); + } + +#ifdef HX_SMART_WAKEUP + if (atomic_read(&ts->suspend_mode)&&(!FAKE_POWER_KEY_SEND)&&(ts->SMWP_enable)&&(!diag_cmd)) { + wake_lock_timeout(&ts->ts_SMWP_wake_lock, TS_WAKE_LOCK_TIMEOUT); + msleep(200); + himax_wake_check_func(); + return IRQ_HANDLED; + } +#endif + himax_ts_isr_func((struct himax_ts_data *)ptr); + if(ts->debug_log_level & BIT(2)) { + getnstimeofday(&timeEnd); + timeDelta.tv_nsec = (timeEnd.tv_sec*1000000000+timeEnd.tv_nsec) + -(timeStart.tv_sec*1000000000+timeStart.tv_nsec); + //I("Irq finish time = %ld.%06ld s\n", + // timeEnd.tv_sec, timeEnd.tv_nsec/1000); + //I("Touch latency = %ld us\n", timeDelta.tv_nsec/1000); + } + return IRQ_HANDLED; +} + +static void himax_ts_work_func(struct work_struct *work) +{ + struct himax_ts_data *ts = container_of(work, struct himax_ts_data, work); + himax_ts_work(ts); +} + +int tp_irq = -1; + +int himax_ts_register_interrupt(struct i2c_client *client) +{ + struct himax_ts_data *ts = i2c_get_clientdata(client); + int ret = 0; + + ts->irq_enabled = 0; + //Work functon + if (client->irq) {/*INT mode*/ + ts->use_irq = 1; + if(ic_data->HX_INT_IS_EDGE) + { + I("%s edge triiger falling\n ",__func__); + ret = request_threaded_irq(client->irq, NULL, himax_ts_thread,IRQF_TRIGGER_FALLING | IRQF_ONESHOT, client->name, ts); + } + else + { + I("%s level trigger low\n ",__func__); + ret = request_threaded_irq(client->irq, NULL, himax_ts_thread,IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, ts); + } + if (ret == 0) { + ts->irq_enabled = 1; + irq_enable_count = 1; + tp_irq = client->irq; + I("%s: irq enabled at qpio: %d\n", __func__, client->irq); +#ifdef HX_SMART_WAKEUP + irq_set_irq_wake(client->irq, 1); +#endif + } else { + ts->use_irq = 0; + E("%s: request_irq failed\n", __func__); + } + } else { + I("%s: client->irq is empty, use polling mode.\n", __func__); + } + + if (!ts->use_irq) {/*if use polling mode need to disable HX_ESD_WORKAROUND function*/ + ts->himax_wq = create_singlethread_workqueue("himax_touch"); + + INIT_WORK(&ts->work, himax_ts_work_func); + + hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + ts->timer.function = himax_ts_timer_func; + hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); + I("%s: polling mode enabled\n", __func__); + } + return ret; +} + +static int himax_common_suspend(struct device *dev) +{ + struct himax_ts_data *ts = dev_get_drvdata(dev); + + I("%s: enter \n", __func__); + + himax_chip_common_suspend(ts); + return 0; +} + +static int himax_common_resume(struct device *dev) +{ + struct himax_ts_data *ts = dev_get_drvdata(dev); + + I("%s: enter \n", __func__); + + himax_chip_common_resume(ts); + return 0; +} + +#if defined(CONFIG_FB) +int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct himax_ts_data *ts= + container_of(self, struct himax_ts_data, fb_notif); + + I(" %s\n", __func__); + if (evdata && evdata->data && event == FB_EVENT_BLANK && ts && + ts->client) { + blank = evdata->data; + + mutex_lock(&ts->fb_mutex); + switch (*blank) { + case FB_BLANK_UNBLANK: + if (!ts->probe_done) { + himax_ts_init(ts); + ts->probe_done = true; + } else { + himax_common_resume(&ts->client->dev); + } + break; + + case FB_BLANK_POWERDOWN: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_NORMAL: + himax_common_suspend(&ts->client->dev); + break; + } + mutex_unlock(&ts->fb_mutex); + } + + return 0; +} +#endif + +static const struct i2c_device_id himax_common_ts_id[] = { + {HIMAX_common_NAME, 0 }, + {} +}; + +static const struct dev_pm_ops himax_common_pm_ops = { +#if (!defined(CONFIG_FB)) + .suspend = himax_common_suspend, + .resume = himax_common_resume, +#endif +}; + +#ifdef CONFIG_OF +static const struct of_device_id himax_match_table[] = { + {.compatible = "himax,hxcommon" }, + {}, +}; +#else +#define himax_match_table NULL +#endif + +static struct i2c_driver himax_common_driver = { + .id_table = himax_common_ts_id, + .probe = himax_chip_common_probe, + .remove = himax_chip_common_remove, + .driver = { + .name = HIMAX_common_NAME, + .owner = THIS_MODULE, + .of_match_table = himax_match_table, +#ifdef CONFIG_PM + .pm = &himax_common_pm_ops, +#endif + }, +}; + +static void __init himax_common_init_async(void *unused, async_cookie_t cookie) +{ + I("%s:Enter \n", __func__); + i2c_add_driver(&himax_common_driver); +} + +static int __init himax_common_init(void) +{ + I("Himax common touch panel driver init\n"); + async_schedule(himax_common_init_async, NULL); + return 0; +} + +static void __exit himax_common_exit(void) +{ + i2c_del_driver(&himax_common_driver); +} + +module_init(himax_common_init); +module_exit(himax_common_exit); + +MODULE_DESCRIPTION("Himax_common driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/input/touchscreen/hxchipset/himax_platform.h b/drivers/input/touchscreen/hxchipset/himax_platform.h new file mode 100644 index 0000000000000..1223685683aa0 --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_platform.h @@ -0,0 +1,135 @@ +/* Himax Android Driver Sample Code for Himax chipset +* +* Copyright (C) 2015 Himax Corporation. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#ifndef HIMAX_PLATFORM_H +#define HIMAX_PLATFORM_H + +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_HMX_DB) +#include +#endif + +#define QCT + +#define HIMAX_I2C_RETRY_TIMES 10 + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) +#define D(x...) pr_debug("[HXTP] " x) +#define I(x...) pr_info("[HXTP] " x) +#define W(x...) pr_warning("[HXTP][WARNING] " x) +#define E(x...) pr_err("[HXTP][ERROR] " x) +#define DIF(x...) \ +do {\ + if (debug_flag) \ + pr_debug("[HXTP][DEBUG] " x) \ +} while(0) +#else +#define D(x...) +#define I(x...) +#define W(x...) +#define E(x...) +#define DIF(x...) +#endif + +#if defined(CONFIG_HMX_DB) +/* Analog voltage @2.7 V */ +#define HX_VTG_MIN_UV 2700000 +#define HX_VTG_MAX_UV 3300000 +#define HX_ACTIVE_LOAD_UA 15000 +#define HX_LPM_LOAD_UA 10 +/* Digital voltage @1.8 V */ +#define HX_VTG_DIG_MIN_UV 1800000 +#define HX_VTG_DIG_MAX_UV 1800000 +#define HX_ACTIVE_LOAD_DIG_UA 10000 +#define HX_LPM_LOAD_DIG_UA 10 + +#define HX_I2C_VTG_MIN_UV 1800000 +#define HX_I2C_VTG_MAX_UV 1800000 +#define HX_I2C_LOAD_UA 10000 +#define HX_I2C_LPM_LOAD_UA 10 +#endif + +#define HIMAX_common_NAME "himax_tp" +#define HIMAX_I2C_ADDR 0x48 +#define INPUT_DEV_NAME "himax-touchscreen" + +struct himax_i2c_platform_data { + int abs_x_min; + int abs_x_max; + int abs_x_fuzz; + int abs_y_min; + int abs_y_max; + int abs_y_fuzz; + int abs_pressure_min; + int abs_pressure_max; + int abs_pressure_fuzz; + int abs_width_min; + int abs_width_max; + int screenWidth; + int screenHeight; + uint8_t fw_version; + uint8_t tw_id; + uint8_t powerOff3V3; + uint8_t cable_config[2]; + uint8_t protocol_type; + int gpio_irq; + int gpio_reset; + int gpio_3v3_en; + int (*power)(int on); + void (*reset)(void); + struct himax_virtual_key *virtual_key; + struct kobject *vk_obj; + struct kobj_attribute *vk2Use; + + struct himax_config *hx_config; + int hx_config_size; +#if defined(CONFIG_HMX_DB) + bool i2c_pull_up; + bool digital_pwr_regulator; + int reset_gpio; + u32 reset_gpio_flags; + int irq_gpio; + u32 irq_gpio_flags; + + struct regulator *vcc_ana; //For Dragon Board + struct regulator *vcc_dig; //For Dragon Board + struct regulator *vcc_i2c; //For Dragon Board +#endif +}; + + +extern int irq_enable_count; +extern int i2c_himax_read(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry); +extern int i2c_himax_write(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry); +extern int i2c_himax_write_command(struct i2c_client *client, uint8_t command, uint8_t toRetry); +extern int i2c_himax_master_write(struct i2c_client *client, uint8_t *data, uint8_t length, uint8_t toRetry); +extern int i2c_himax_read_command(struct i2c_client *client, uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry); +extern void himax_int_enable(int irqnum, int enable); +extern int himax_ts_register_interrupt(struct i2c_client *client); +extern void himax_rst_gpio_set(int pinnum, uint8_t value); +extern uint8_t himax_int_gpio_read(int pinnum); + +extern int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata); + +#if defined(CONFIG_FB) +extern int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data); +#endif + +#endif From cc5a75b5be42ccecfe9264df99be316a32e2e5e6 Mon Sep 17 00:00:00 2001 From: Sumit Agrawal Date: Tue, 29 May 2018 18:43:32 +0530 Subject: [PATCH 437/508] defconfig: msm8953: Add himax touch support Enable himax touch driver in msm8953_defconfig and msm8953-perf_defconfig. Change-Id: I7c135be4f75562c769a3840d6a34d9197785a716 Signed-off-by: Vijay Navnath Kamble Signed-off-by: Sumit Agrawal --- arch/arm/configs/msmcortex-perf_defconfig | 4 ++++ arch/arm/configs/msmcortex_defconfig | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/arch/arm/configs/msmcortex-perf_defconfig b/arch/arm/configs/msmcortex-perf_defconfig index 0152945efdc6d..378119e357a02 100644 --- a/arch/arm/configs/msmcortex-perf_defconfig +++ b/arch/arm/configs/msmcortex-perf_defconfig @@ -307,6 +307,10 @@ CONFIG_TOUCHSCREEN_ATMEL_MXT=y CONFIG_TOUCHSCREEN_GEN_VKEYS=y CONFIG_TOUCHSCREEN_FT5X06=y CONFIG_TOUCHSCREEN_MAXIM_STI=y +CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y +CONFIG_TOUCHSCREEN_HIMAX_I2C=y +CONFIG_TOUCHSCREEN_HIMAX_DEBUG=y +CONFIG_HMX_DB=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y CONFIG_INPUT_KEYCHORD=y diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig index cb620619749af..4e6b91757b5fa 100644 --- a/arch/arm/configs/msmcortex_defconfig +++ b/arch/arm/configs/msmcortex_defconfig @@ -307,6 +307,10 @@ CONFIG_SECURE_TOUCH=y CONFIG_TOUCHSCREEN_GEN_VKEYS=y CONFIG_TOUCHSCREEN_FT5X06=y CONFIG_TOUCHSCREEN_MAXIM_STI=y +CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y +CONFIG_TOUCHSCREEN_HIMAX_I2C=y +CONFIG_TOUCHSCREEN_HIMAX_DEBUG=y +CONFIG_HMX_DB=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y CONFIG_INPUT_UINPUT=y From 249a2b0071ab6b2b5515ae981444177cae9bf68d Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Wed, 30 May 2018 17:04:25 +0530 Subject: [PATCH 438/508] wlan: Resolve memory leak while processing SET_PACKET_FILTER IOCTL While processing SET_PACKET_FILTER IOCTL, request memory is not freed if HDD fails to post respective WDA command. Do request put on fail to post WDA command, to make sure request memory is freed. Change-Id: I83706ab4e4b400e295b719cb0d75097574563bd7 CRs-Fixed: 2249784 --- CORE/HDD/src/wlan_hdd_wext.c | 1 + 1 file changed, 1 insertion(+) diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index fb9cd4dfab4ea..5fef7c7bf1886 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -9165,6 +9165,7 @@ int wlan_hdd_set_filter(hdd_adapter_t *pAdapter, tpPacketFilterCfg pRequest) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Clear Filter", __func__); + hdd_request_put(request); return -EINVAL; } From 1097936670b123dc8944891b253b93a62ca156b8 Mon Sep 17 00:00:00 2001 From: Manu Gautam Date: Fri, 25 May 2018 12:27:18 +0530 Subject: [PATCH 439/508] usb: f_gsi: Allow user to specify MAC address for RNDIS/ECM Driver currently uses random MAC address which gets changed across composition switches or reboots. Allow user to specify MAC address using module parameter to fix this. Change-Id: I96710b3419ff7c016b931195a80ce77cd8c9038c Signed-off-by: Manu Gautam --- drivers/usb/gadget/function/f_gsi.c | 56 ++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index d1b1190d19a10..cec10d66f5bb2 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -50,6 +50,16 @@ static bool qti_packet_debug; module_param(qti_packet_debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(qti_packet_debug, "Print QTI Packet's Raw Data"); +/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */ +static char *gsi_dev_addr; +module_param(gsi_dev_addr, charp, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(gsi_dev_addr, "QC Device Ethernet Address"); + +/* this address is invisible to ifconfig */ +static char *gsi_host_addr; +module_param(gsi_host_addr, charp, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(gsi_host_addr, "QC Host Ethernet Address"); + static struct workqueue_struct *ipa_usb_wq; struct usb_gsi_debugfs { @@ -2915,6 +2925,28 @@ static int gsi_update_function_bind_params(struct f_gsi *gsi, return -ENOMEM; } +static int gsi_get_ether_addr(const char *str, u8 *dev_addr) +{ + if (str) { + unsigned i; + + for (i = 0; i < 6; i++) { + unsigned char num; + + if ((*str == '.') || (*str == ':')) + str++; + num = hex_to_bin(*str++) << 4; + num |= hex_to_bin(*str++); + dev_addr[i] = num; + } + if (is_valid_ether_addr(dev_addr)) + return 0; + } + random_ether_addr(dev_addr); + + return 1; +} + static int gsi_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; @@ -2977,11 +3009,15 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f) rndis_set_param_medium(gsi->config, RNDIS_MEDIUM_802_3, 0); /* export host's Ethernet address in CDC format */ - random_ether_addr(gsi->d_port.ipa_init_params.device_ethaddr); - random_ether_addr(gsi->d_port.ipa_init_params.host_ethaddr); + gsi_get_ether_addr(gsi_dev_addr, + gsi->d_port.ipa_init_params.device_ethaddr); + + gsi_get_ether_addr(gsi_host_addr, + gsi->d_port.ipa_init_params.host_ethaddr); + log_event_dbg("setting host_ethaddr=%pM, device_ethaddr = %pM", - gsi->d_port.ipa_init_params.host_ethaddr, - gsi->d_port.ipa_init_params.device_ethaddr); + gsi->d_port.ipa_init_params.host_ethaddr, + gsi->d_port.ipa_init_params.device_ethaddr); memcpy(gsi->ethaddr, &gsi->d_port.ipa_init_params.host_ethaddr, ETH_ALEN); rndis_set_host_mac(gsi->config, gsi->ethaddr); @@ -3109,11 +3145,15 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f) info.notify_buf_len = GSI_CTRL_NOTIFY_BUFF_LEN; /* export host's Ethernet address in CDC format */ - random_ether_addr(gsi->d_port.ipa_init_params.device_ethaddr); - random_ether_addr(gsi->d_port.ipa_init_params.host_ethaddr); + gsi_get_ether_addr(gsi_dev_addr, + gsi->d_port.ipa_init_params.device_ethaddr); + + gsi_get_ether_addr(gsi_host_addr, + gsi->d_port.ipa_init_params.host_ethaddr); + log_event_dbg("setting host_ethaddr=%pM, device_ethaddr = %pM", - gsi->d_port.ipa_init_params.host_ethaddr, - gsi->d_port.ipa_init_params.device_ethaddr); + gsi->d_port.ipa_init_params.host_ethaddr, + gsi->d_port.ipa_init_params.device_ethaddr); snprintf(gsi->ethaddr, sizeof(gsi->ethaddr), "%02X%02X%02X%02X%02X%02X", From 552b590dfe47b421f56b9a4418fd8c6b7a0237aa Mon Sep 17 00:00:00 2001 From: Naresh Bommena Date: Mon, 14 May 2018 16:33:35 +0530 Subject: [PATCH 440/508] ARM: dts: msm: Use pm8953_l2 as camera vdig supply Enable pm8953_l2 regulator for camera and also enable camera EEPROM device. Sets camera sensor default mount angle to 90 degree. Change-Id: Id21772d93735ae72b5edc699ee69efb876244283 Signed-off-by: Naresh Bommena --- .../qcom/apq8053-camera-sensor-dragon.dtsi | 130 ++++++++++++++++-- .../boot/dts/qcom/apq8053-lite-dragon.dtsi | 17 +++ 2 files changed, 135 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi b/arch/arm/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi index 3b5225f50907f..8230eab26da21 100644 --- a/arch/arm/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi +++ b/arch/arm/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -36,6 +36,109 @@ qcom,cam-vreg-op-mode = <80000>; }; + eeprom0: qcom,eeprom@0 { + cell-index = <0>; + compatible = "qcom,eeprom"; + reg = <0x0>; + qcom,cci-master = <0>; + cam_vio-supply = <&pm8953_l6>; + cam_vdig-supply = <&pm8953_l2>; + cam_vana-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", + "cam_vana"; + qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>; + qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 100000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default + &cam_sensor_rear_vana>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep + &cam_sensor_rear_vana_sleep>; + gpios = <&tlmm 26 0>, + <&tlmm 40 0>, + <&tlmm 39 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_STANDBY0"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom1: qcom,eeprom@1 { + cell-index = <1>; + compatible = "qcom,eeprom"; + reg = <0x1>; + qcom,cci-master = <0>; + cam_vio-supply = <&pm8953_l6>; + cam_vdig-supply = <&pm8953_l2>; + cam_vana-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", + "cam_vana"; + qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>; + qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 100000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front1_default>; + pinctrl-1 = <&cam_sensor_mclk1_sleep + &cam_sensor_front1_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 129 0>, + <&tlmm 130 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_STANDBY1"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom2: qcom,eeprom@2 { + cell-index = <2>; + compatible = "qcom,eeprom"; + reg = <0x2>; + qcom,cci-master = <0>; + cam_vio-supply = <&pm8953_l6>; + cam_vdig-supply = <&pm8953_l2>; + cam_vana-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", + "cam_vana"; + qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>; + qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>; + qcom,cam-vreg-op-mode = <105000 0 100000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_default + &cam_sensor_front_default>; + pinctrl-1 = <&cam_sensor_mclk2_sleep + &cam_sensor_front_sleep>; + gpios = <&tlmm 28 0>, + <&tlmm 131 0>, + <&tlmm 132 0>; + qcom,gpio-reset = <1>; + qcom,gpio-standby = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_STANDBY2"; + clocks = <&clock_gcc clk_mclk2_clk_src>, + <&clock_gcc clk_gcc_camss_mclk2_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + camera0: qcom,camera@0 { cell-index = <0>; compatible = "qcom,camera"; @@ -45,13 +148,14 @@ qcom,mount-angle = <0>; /*qcom,led-flash-src = <&led_flash0>;*/ qcom,actuator-src = <&actuator0>; + qcom,eeprom-src = <&eeprom0>; cam_vio-supply = <&pm8953_l6>; - cam_vdig-supply = <&eldo_cam0_vreg>; + cam_vdig-supply = <&pm8953_l2>; cam_vana-supply = <&pm8953_l17>; qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vana"; - qcom,cam-vreg-min-voltage = <1800000 1100000 2850000>; - qcom,cam-vreg-max-voltage = <1800000 1100000 2850000>; + qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>; + qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>; qcom,cam-vreg-op-mode = <105000 0 100000>; pinctrl-names = "cam_default", "cam_suspend"; pinctrl-0 = <&cam_sensor_mclk0_default @@ -86,14 +190,15 @@ qcom,csiphy-sd-index = <1>; qcom,csid-sd-index = <1>; qcom,mount-angle = <0>; - qcom,actuator-src = <&actuator1>; + qcom,actuator-src = <&actuator0>; + qcom,eeprom-src = <&eeprom1>; cam_vio-supply = <&pm8953_l6>; - cam_vdig-supply = <&eldo_cam1_vreg>; + cam_vdig-supply = <&pm8953_l2>; cam_vana-supply = <&pm8953_l17>; qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vana"; - qcom,cam-vreg-min-voltage = <1800000 1100000 2850000>; - qcom,cam-vreg-max-voltage = <1800000 1100000 2850000>; + qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>; + qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>; qcom,cam-vreg-op-mode = <105000 0 100000>; pinctrl-names = "cam_default", "cam_suspend"; pinctrl-0 = <&cam_sensor_mclk1_default @@ -110,7 +215,7 @@ qcom,gpio-req-tbl-label = "CAMIF_MCLK1", "CAM_RESET1", "CAM_STANDBY1"; - qcom,sensor-position = <0>; + qcom,sensor-position = <1>; qcom,sensor-mode = <0>; qcom,cci-master = <0>; status = "ok"; @@ -128,13 +233,14 @@ qcom,csid-sd-index = <2>; qcom,mount-angle = <0>; qcom,actuator-src = <&actuator0>; + qcom,eeprom-src = <&eeprom2>; cam_vio-supply = <&pm8953_l6>; - cam_vdig-supply = <&eldo_cam2_vreg>; + cam_vdig-supply = <&pm8953_l2>; cam_vana-supply = <&pm8953_l17>; qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vana"; - qcom,cam-vreg-min-voltage = <1800000 1100000 2850000>; - qcom,cam-vreg-max-voltage = <1800000 1100000 2850000>; + qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>; + qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>; qcom,cam-vreg-op-mode = <105000 0 100000>; /*qcom,gpio-no-mux = <0>;*/ pinctrl-names = "cam_default", "cam_suspend"; diff --git a/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi b/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi index 1c3713cbf4918..8649b2000e70f 100644 --- a/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi +++ b/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi @@ -173,6 +173,23 @@ /delete-property/ qcom,msm-vdd-wsa-switch-current; }; +&pm8953_l2 { + status = "okay"; + regulator-always-on; +}; + +&camera0 { + qcom,mount-angle = <90>; +}; + +&camera1 { + qcom,mount-angle = <90>; +}; + +&camera2{ + qcom,mount-angle = <90>; +}; + &pm8953_diangu_dig { status = "ok"; }; From 33548e2569bb8a4b47c698c41ebd66f3a0efb770 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Thu, 31 May 2018 13:28:51 +0530 Subject: [PATCH 441/508] wlan: Use proper length to send the beacon/probe to kernel propagation from qcacld-3.0 to prima. Currently sizeof(struct ieee80211_mgmt) + IE len is used to calculate the total frame length to send the beacon/probe to kernel. struct ieee80211_mgmt contains union to define different frames and thus the sizeof(struct ieee80211_mgmt) may give extra length for beacon/probe if any of the union size is greater than the probe/beacon union size. This result in trail of zeroes at the end of the frame. To fix this use sizeof(mgmt_mac_header) + SIR_MAC_B_PR_SSID_OFFSET + ie len to determine the exact size of the frame. Change-Id: I71e94b111f36fcd4060befcae282f1fcce5e17f1 CRs-Fixed: 2251716 --- CORE/HDD/src/wlan_hdd_cfg80211.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 219608307420d..0f19b58bfe176 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -14257,7 +14257,8 @@ wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, struct ieee80211_channel *chan; struct ieee80211_mgmt *mgmt = NULL; struct cfg80211_bss *bss_status = NULL; - size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length; + size_t frame_len = sizeof(tSirMacMgmtHdr) + SIR_MAC_B_PR_SSID_OFFSET + + ie_length; int rssi = 0; hdd_context_t *pHddCtx; int status; @@ -14273,7 +14274,7 @@ wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, return NULL; } - mgmt = kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL); + mgmt = kzalloc(frame_len, GFP_KERNEL); if (!mgmt) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, From e04e06c5b29d051a4453f80ab8c080827132a921 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Thu, 31 May 2018 14:41:36 +0530 Subject: [PATCH 442/508] wlan: Fix frame lenth information to cfg80211 propagation from qcacld-3.0 to prima. During BSS frame update, frame_len is calculated as size of ieee80211_mgmt and ielen. Since ieee80211_mgmt is a generic frame structure and different frame structures are defined under union this may exceed the actual frame len. Fix by calculatiing offset of variable(ies) and ies length. Change-Id: Ied8e4e604e41de1ac5ccc047ef5cc3cdb05a9445 CRs-Fixed: 2251764 --- CORE/HDD/src/wlan_hdd_cfg80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 0f19b58bfe176..f9ef7a0144c23 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -14257,8 +14257,8 @@ wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, struct ieee80211_channel *chan; struct ieee80211_mgmt *mgmt = NULL; struct cfg80211_bss *bss_status = NULL; - size_t frame_len = sizeof(tSirMacMgmtHdr) + SIR_MAC_B_PR_SSID_OFFSET + - ie_length; + size_t frame_len = ie_length + offsetof(struct ieee80211_mgmt, + u.probe_resp.variable); int rssi = 0; hdd_context_t *pHddCtx; int status; From cb84efaf7f9972ffa0f9e300c329648a2a4455ac Mon Sep 17 00:00:00 2001 From: Mahesh Sivasubramanian Date: Wed, 7 Mar 2018 16:00:07 -0700 Subject: [PATCH 443/508] drivers: qcom: lpm-stats: Fix undefined access error In cleanup_stats(), a freed memory pointer pos might be accessed for list traversal. Switch to using _safe() variant of the list API to prevent undefined accesses. Change-Id: I7d068cb7813ccb9bfdbcab4646b4ec890145828a Signed-off-by: Mahesh Sivasubramanian --- drivers/power/qcom/lpm-stats.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/qcom/lpm-stats.c b/drivers/power/qcom/lpm-stats.c index 812815da7306f..bfd897a4323b0 100644 --- a/drivers/power/qcom/lpm-stats.c +++ b/drivers/power/qcom/lpm-stats.c @@ -682,9 +682,10 @@ static void cleanup_stats(struct lpm_stats *stats) { struct list_head *centry = NULL; struct lpm_stats *pos = NULL; + struct lpm_stats *n = NULL; centry = &stats->child; - list_for_each_entry_reverse(pos, centry, sibling) { + list_for_each_entry_safe_reverse(pos, n, centry, sibling) { if (!list_empty(&pos->child)) { cleanup_stats(pos); continue; From 4a5ebde6086a757aeb5f04d282a1affb8bec30ff Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Thu, 3 Nov 2016 09:42:36 -0700 Subject: [PATCH 444/508] taskstats: fix the length of cgroupstats_cmd_get_policy cgroupstats_cmd_get_policy is [CGROUPSTATS_CMD_ATTR_MAX+1], taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1], but their family.maxattr is TASKSTATS_CMD_ATTR_MAX. CGROUPSTATS_CMD_ATTR_MAX is less than TASKSTATS_CMD_ATTR_MAX, so we could end up accessing out-of-bound. Change cgroupstats_cmd_get_policy to TASKSTATS_CMD_ATTR_MAX+1, this is safe because the rest are initialized to 0's. Reported-by: Andrey Konovalov Tested-by: Andrey Konovalov Signed-off-by: Cong Wang Signed-off-by: David S. Miller Git-commit: 243d52126184b072a18fe2130ce0008f8aa3a340 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Change-Id: Ie03c41de881d8e0e88ba35f5369e4e955d8d8682 CRs-Fixed: 2234354 Signed-off-by: Jeff Johnson --- kernel/taskstats.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/taskstats.c b/kernel/taskstats.c index b312fcc730243..704f82d1f4221 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -54,7 +54,11 @@ static const struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1 [TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING }, [TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },}; -static const struct nla_policy cgroupstats_cmd_get_policy[CGROUPSTATS_CMD_ATTR_MAX+1] = { +/* + * We have to use TASKSTATS_CMD_ATTR_MAX here, it is the maxattr in the family. + * Make sure they are always aligned. + */ +static const struct nla_policy cgroupstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] = { [CGROUPSTATS_CMD_ATTR_FD] = { .type = NLA_U32 }, }; From ab8e1945b398f7867398c676cbe8e7e812384ed2 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Thu, 24 May 2018 18:10:39 +0530 Subject: [PATCH 445/508] wlan: Don't access adapter after netdev is freed In hdd_open_adapter() error case, adapter is dereferenced just after freeing netdev, leading to access invalid memory. Make sure adapter is not accessed after netdev is freed. Change-Id: If50d4007e0da2a6466e9454e3463d5dd7852dcaa CRs-Fixed: 2248340 --- CORE/HDD/src/wlan_hdd_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index b37aa54e0f59a..b57119d262e04 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -10006,9 +10006,9 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, return pAdapter; err_free_netdev: - free_netdev(pAdapter->dev); wlan_hdd_release_intf_addr( pHddCtx, pAdapter->macAddressCurrent.bytes ); + free_netdev(pAdapter->dev); resume_bmps: //If bmps disabled enable it From 9dafc14e287d7057537d02dffc5825f7d29faec2 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 31 May 2015 19:50:57 +0200 Subject: [PATCH 446/508] um: Stop abusing __KERNEL__ Currently UML is abusing __KERNEL__ to distinguish between kernel and host code (os-Linux). It is better to use a custom define such that existing users of __KERNEL__ don't get confused. Change-Id: I37a472e7405405c5da6b23bd3c279e4a0cb76cd0 Signed-off-by: Richard Weinberger Git-commit: 298e20ba8c197e8d429a6c8671550c41c7919033 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Srinivasarao P --- arch/um/Makefile | 7 ++++--- arch/um/drivers/mconsole.h | 2 +- arch/um/include/shared/init.h | 4 ++-- arch/um/include/shared/user.h | 2 +- arch/x86/um/shared/sysdep/tls.h | 6 +++--- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/um/Makefile b/arch/um/Makefile index e4b1a9639c4dd..d902cf8733bf1 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -68,9 +68,10 @@ KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ \ KBUILD_AFLAGS += $(ARCH_INCLUDE) -USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\ - $(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \ - $(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64 -idirafter include +USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \ + $(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \ + -D_FILE_OFFSET_BITS=64 -idirafter include \ + -D__KERNEL__ -D__UM_HOST__ #This will adjust *FLAGS accordingly to the platform. include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) diff --git a/arch/um/drivers/mconsole.h b/arch/um/drivers/mconsole.h index 8b22535c62ceb..44af7379ea19c 100644 --- a/arch/um/drivers/mconsole.h +++ b/arch/um/drivers/mconsole.h @@ -7,7 +7,7 @@ #ifndef __MCONSOLE_H__ #define __MCONSOLE_H__ -#ifndef __KERNEL__ +#ifdef __UM_HOST__ #include #define u32 uint32_t #endif diff --git a/arch/um/include/shared/init.h b/arch/um/include/shared/init.h index b3906f860a87e..031ad1d111e72 100644 --- a/arch/um/include/shared/init.h +++ b/arch/um/include/shared/init.h @@ -40,7 +40,7 @@ typedef int (*initcall_t)(void); typedef void (*exitcall_t)(void); -#ifndef __KERNEL__ +#ifdef __UM_HOST__ #ifndef __section # define __section(S) __attribute__ ((__section__(#S))) #endif @@ -131,7 +131,7 @@ extern struct uml_param __uml_setup_start, __uml_setup_end; #define __uml_postsetup_call __used __section(.uml.postsetup.init) #define __uml_exit_call __used __section(.uml.exitcall.exit) -#ifndef __KERNEL__ +#ifdef __UM_HOST__ #define __define_initcall(level,fn) \ static initcall_t __initcall_##fn __used \ diff --git a/arch/um/include/shared/user.h b/arch/um/include/shared/user.h index cef0685633369..4cff19f6207ac 100644 --- a/arch/um/include/shared/user.h +++ b/arch/um/include/shared/user.h @@ -17,7 +17,7 @@ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) /* This is to get size_t */ -#ifdef __KERNEL__ +#ifndef __UM_HOST__ #include #else #include diff --git a/arch/x86/um/shared/sysdep/tls.h b/arch/x86/um/shared/sysdep/tls.h index 27cce00c6b30c..a682db13df23b 100644 --- a/arch/x86/um/shared/sysdep/tls.h +++ b/arch/x86/um/shared/sysdep/tls.h @@ -1,7 +1,7 @@ #ifndef _SYSDEP_TLS_H #define _SYSDEP_TLS_H -# ifndef __KERNEL__ +#ifdef __UM_HOST__ /* Change name to avoid conflicts with the original one from , which * may be named user_desc (but in 2.4 and in header matching its API was named @@ -22,11 +22,11 @@ typedef struct um_dup_user_desc { #endif } user_desc_t; -# else /* __KERNEL__ */ +#else /* __UM_HOST__ */ typedef struct user_desc user_desc_t; -# endif /* __KERNEL__ */ +#endif /* __UM_HOST__ */ extern int os_set_thread_area(user_desc_t *info, int pid); extern int os_get_thread_area(user_desc_t *info, int pid); From 885cb3b01a08d74609819bc698805d02cc3480c2 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 31 May 2015 22:15:58 +0200 Subject: [PATCH 447/508] um: Remove copy&paste code from init.h As we got rid of the __KERNEL__ abuse, we can directly include linux/compiler.h now. This also allows gcc 5 to build UML. Change-Id: I07de22048076dfb3c191854dc7b70b81a8a84c8c Reported-by: Hans-Werner Hilse Signed-off-by: Richard Weinberger Git-commit: 30b11ee9ae23d78de66b9ae315880af17a64ba83 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Srinivasarao P --- arch/um/include/shared/init.h | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/arch/um/include/shared/init.h b/arch/um/include/shared/init.h index 031ad1d111e72..233e2593eee0f 100644 --- a/arch/um/include/shared/init.h +++ b/arch/um/include/shared/init.h @@ -40,28 +40,8 @@ typedef int (*initcall_t)(void); typedef void (*exitcall_t)(void); -#ifdef __UM_HOST__ -#ifndef __section -# define __section(S) __attribute__ ((__section__(#S))) -#endif - -#if __GNUC__ == 3 - -#if __GNUC_MINOR__ >= 3 -# define __used __attribute__((__used__)) -#else -# define __used __attribute__((__unused__)) -#endif - -#else -#if __GNUC__ == 4 -# define __used __attribute__((__used__)) -#endif -#endif - -#else #include -#endif + /* These are for everybody (although not all archs will actually discard it in modules) */ #define __init __section(.init.text) From 38ec602f8328fdc4de46756c649c3ad675b4f0cc Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 28 Jun 2015 22:55:26 +0200 Subject: [PATCH 448/508] um: Fix out-of-tree build Commit 30b11ee9a (um: Remove copy&paste code from init.h) uncovered an issue wrt. out-of-tree builds. For out-of-tree builds, we must not rely on relative paths. Before 30b11ee9a it worked by chance as no host code included generated header files. Change-Id: I15e55a3db98d51a6340a440a5d07c63c334bd50f Acked-by: Randy Dunlap Signed-off-by: Richard Weinberger Git-commit: 0b5aedfe0e6654ec54f35109e1929a1cf7fc4cdd Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Srinivasarao P --- arch/um/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/um/Makefile b/arch/um/Makefile index d902cf8733bf1..78c32029368ac 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -70,8 +70,8 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE) USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \ $(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \ - -D_FILE_OFFSET_BITS=64 -idirafter include \ - -D__KERNEL__ -D__UM_HOST__ + -D_FILE_OFFSET_BITS=64 -idirafter $(srctree)/include \ + -idirafter $(obj)/include -D__KERNEL__ -D__UM_HOST__ #This will adjust *FLAGS accordingly to the platform. include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) From 1e1b90ed0c57659398aa2c4774e5cd9fff54e3d1 Mon Sep 17 00:00:00 2001 From: Nachiket Kukade Date: Thu, 10 May 2018 15:26:13 +0530 Subject: [PATCH 449/508] wlan: Advertize flag WIPHY_WOWLAN_ANY in wiphy wowlan config Driver currently only advertizes wowlan capability in wiphy to wake up on receiving a magic packet. When hostapd conf sets wowlan_triggers=any kernel sees that driver is incapable of this and makes SAP disconnect with any stations before going to suspend. Given that the device is capable of supporting any triggers this is unexpected behaviour. Advertize wowlan capability in wiphy to wake up on any activity by setting WIPHY_WOWLAN_ANY. Change-Id: I1932263cfb1259bc4ff419316e9f23b6e085cd25 CRs-Fixed: 2239662 --- CORE/HDD/src/wlan_hdd_cfg80211.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index f9ef7a0144c23..8e991a956a048 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -461,7 +461,8 @@ wlan_hdd_iface_combination[] = { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)) || defined(WITH_BACKPORTS) static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = { - .flags = WIPHY_WOWLAN_MAGIC_PKT, + .flags = WIPHY_WOWLAN_ANY | + WIPHY_WOWLAN_MAGIC_PKT, .n_patterns = WOWL_MAX_PTRNS_ALLOWED, .pattern_min_len = 1, .pattern_max_len = WOWL_PTRN_MAX_SIZE, @@ -9182,7 +9183,8 @@ int wlan_hdd_cfg80211_init(struct device *dev, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)) || defined(WITH_BACKPORTS) wiphy->wowlan = &wowlan_support_cfg80211_init; #else - wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT; + wiphy->wowlan.flags = WIPHY_WOWLAN_ANY | + WIPHY_WOWLAN_MAGIC_PKT; wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED; wiphy->wowlan.pattern_min_len = 1; wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE; From 8445854326b5f26354c0cd9c19941219c004624c Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Mon, 14 May 2018 15:03:08 +0530 Subject: [PATCH 450/508] wlan: Update needed_headroom with LIBRA_HW_NEEDED_HEADROOM While allocate network device, hard_header_len is set to ETH_HLEN(14) + LIBRA_HW_NEEDED_HEADROOM(128). From the kernel versions greater than 4.4 onwards, while sending data packet, packet_snd(), kernel making sure that data length must be at least 'hard_header_len', else drop the packet. Due to this check, data packets having length less than 142 will be dropped. To mitigate this issue, in driver, add LIBRA_HW_NEEDED_HEADROOM to 'needed_headroom' instead of updating hard_header_len. Now kernel will ensure that data lenght must be at least ETH_HLEN(14). Change-Id: If8aa52c8554988f8020132802830d581ee01bb31 CRs-Fixed: 2239833 --- CORE/HDD/src/wlan_hdd_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index b57119d262e04..0a5e405a9334a 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -9053,7 +9053,8 @@ static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMac vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr)); vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr)); pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT; - pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM; + + pWlanDev->needed_headroom = LIBRA_HW_NEEDED_HEADROOM; hdd_set_station_ops( pAdapter->dev ); From c9a384d61ffc8596945496ed3e5f9ba8a6fc0e44 Mon Sep 17 00:00:00 2001 From: Krishna Manikandan Date: Fri, 1 Jun 2018 11:28:53 +0530 Subject: [PATCH 451/508] msm: mdss: Add separate function for mapping A separate function is added for mapping the buffer based on the required domain. Change-Id: Ic5daaae9e9426fb076a2c872fb40efc3dc8c3e6f Signed-off-by: Krishna Manikandan --- drivers/video/msm/mdss/mdp3.c | 115 +++++++++++++++++++++++----------- drivers/video/msm/mdss/mdp3.h | 3 +- 2 files changed, 79 insertions(+), 39 deletions(-) diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c index 832a5c7bd112a..fe343ee9d05bf 100644 --- a/drivers/video/msm/mdss/mdp3.c +++ b/drivers/video/msm/mdss/mdp3.c @@ -154,6 +154,18 @@ struct mdp3_iommu_ctx_map mdp3_iommu_contexts[MDP3_IOMMU_CTX_MAX] = { }, }; +static int mdp3_get_domain(u32 flags) +{ + int domain; + + if (flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) + domain = MDSS_IOMMU_DOMAIN_SECURE; + else + domain = MDSS_IOMMU_DOMAIN_UNSECURE; + + return domain; +} + static irqreturn_t mdp3_irq_handler(int irq, void *ptr) { int i = 0; @@ -1820,7 +1832,7 @@ int mdp3_self_map_iommu(struct ion_client *client, struct ion_handle *handle, int mdp3_put_img(struct mdp3_img_data *data, int client) { struct ion_client *iclient = mdp3_res->ion_client; - int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN_UNSECURE)->domain_idx; + int dom = mdp3_get_domain(data->flags); int dir = DMA_BIDIRECTIONAL; if (data->flags & MDP_MEMORY_ID_TYPE_FB) { @@ -1828,8 +1840,9 @@ int mdp3_put_img(struct mdp3_img_data *data, int client) fdput(data->srcp_f); memset(&data->srcp_f, 0, sizeof(struct fd)); } else if (!IS_ERR_OR_NULL(data->srcp_dma_buf)) { - pr_debug("ion hdl = %pK buf=0x%pa\n", data->srcp_dma_buf, - &data->addr); + pr_debug("ion hdl = %pK buf=0x%pa domain = %d\n", + data->srcp_dma_buf, &data->addr, dom); + if (!iclient) { pr_err("invalid ion client\n"); return -ENOMEM; @@ -1863,15 +1876,69 @@ int mdp3_put_img(struct mdp3_img_data *data, int client) return 0; } +int mdp3_map_layer(struct mdp3_img_data *data, int client) +{ + int ret = 0; + int dom = mdp3_get_domain(data->flags); + + if (client == MDP3_CLIENT_PPP || client == MDP3_CLIENT_DMA_P) { + ret = mdss_smmu_map_dma_buf(data->srcp_dma_buf, + data->tab_clone, dom, + &data->addr, &data->len, + DMA_BIDIRECTIONAL); + } else { + ret = mdss_smmu_map_dma_buf(data->srcp_dma_buf, + data->srcp_table, dom, &data->addr, + &data->len, DMA_BIDIRECTIONAL); + } + + if (IS_ERR_VALUE(ret)) { + pr_err("smmu map dma buf failed: (%d)\n", ret); + goto err_unmap; + } + + data->mapped = true; + + if (client == MDP3_CLIENT_PPP || client == MDP3_CLIENT_DMA_P) { + data->addr += data->tab_clone->sgl->length; + data->len -= data->tab_clone->sgl->length; + } + + if (!ret && (data->offset < data->len)) { + data->addr += data->offset; + data->len -= data->offset; + pr_debug("ihdl=%pK buf=0x%pa len=0x%lx domain = %d\n", + data->srcp_dma_buf, &data->addr, data->len, dom); + } else { + mdp3_put_img(data, client); + return -EINVAL; + } + + return ret; + +err_unmap: + dma_buf_unmap_attachment(data->srcp_attachment, data->srcp_table, + mdss_smmu_dma_data_direction(DMA_BIDIRECTIONAL)); + dma_buf_detach(data->srcp_dma_buf, data->srcp_attachment); + dma_buf_put(data->srcp_dma_buf); + + if (client == MDP3_CLIENT_PPP || client == MDP3_CLIENT_DMA_P) { + vfree(data->tab_clone->sgl); + kfree(data->tab_clone); + } + return ret; +} + int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data, int client) { struct fd f; - int ret = -EINVAL; + int ret = 0; int fb_num; struct ion_client *iclient = mdp3_res->ion_client; - int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN_UNSECURE)->domain_idx; + int dom = mdp3_get_domain(data->flags); - data->flags = img->flags; + data->flags |= img->flags; + data->offset = img->offset; if (img->flags & MDP_MEMORY_ID_TYPE_FB) { f = fdget(img->memory_id); @@ -1934,29 +2001,13 @@ int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data, int client) ret = PTR_ERR(data->tab_clone); goto clone_err; } - ret = mdss_smmu_map_dma_buf(data->srcp_dma_buf, - data->tab_clone, dom, - &data->addr, &data->len, - DMA_BIDIRECTIONAL); - } else { - ret = mdss_smmu_map_dma_buf(data->srcp_dma_buf, - data->srcp_table, dom, &data->addr, - &data->len, DMA_BIDIRECTIONAL); - } - - if (IS_ERR_VALUE(ret)) { - pr_err("smmu map dma buf failed: (%d)\n", ret); - goto err_unmap; + data->mapped = false; + data->skip_detach = false; + return ret; } + } - data->mapped = true; - data->skip_detach = false; - } done: - if (client == MDP3_CLIENT_PPP || client == MDP3_CLIENT_DMA_P) { - data->addr += data->tab_clone->sgl->length; - data->len -= data->tab_clone->sgl->length; - } if (!ret && (img->offset < data->len)) { data->addr += img->offset; data->len -= img->offset; @@ -1979,18 +2030,6 @@ int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data, int client) err_put: dma_buf_put(data->srcp_dma_buf); return ret; -err_unmap: - dma_buf_unmap_attachment(data->srcp_attachment, data->srcp_table, - mdss_smmu_dma_data_direction(DMA_BIDIRECTIONAL)); - dma_buf_detach(data->srcp_dma_buf, data->srcp_attachment); - dma_buf_put(data->srcp_dma_buf); - - if (client == MDP3_CLIENT_PPP || client == MDP3_CLIENT_DMA_P) { - vfree(data->tab_clone->sgl); - kfree(data->tab_clone); - } - return ret; - } int mdp3_iommu_enable(int client) diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h index c224416919917..295aff263ca82 100644 --- a/drivers/video/msm/mdss/mdp3.h +++ b/drivers/video/msm/mdss/mdp3.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2014, 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2014, 2016-2018, The Linux Foundation. All rights reserved. * Copyright (C) 2007 Google Incorporated * * This program is free software; you can redistribute it and/or modify @@ -253,6 +253,7 @@ int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota); int mdp3_put_img(struct mdp3_img_data *data, int client); int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data, int client); +int mdp3_map_layer(struct mdp3_img_data *data, int client); int mdp3_iommu_enable(int client); int mdp3_iommu_disable(int client); int mdp3_iommu_is_attached(void); From 391e2508712e6131d79a8cc32f625cddd10718ed Mon Sep 17 00:00:00 2001 From: Krishna Manikandan Date: Fri, 1 Jun 2018 11:29:55 +0530 Subject: [PATCH 452/508] msm: mdss: Add support for handling secure buffer use-cases in MDP3 Support for secure usecase for MDP3 is added. Ensure a NULL buffer commit in case of video mode panels during secure to non secure and vice versa transition. Change-Id: I80669d8b6940c742b6624d9af9efc820d6063e10 Signed-off-by: Krishna Manikandan --- drivers/video/msm/mdss/mdp3.c | 7 +- drivers/video/msm/mdss/mdp3.h | 7 ++ drivers/video/msm/mdss/mdp3_ctrl.c | 159 ++++++++++++++++++++++++++-- drivers/video/msm/mdss/mdp3_ctrl.h | 8 +- drivers/video/msm/mdss/mdp3_dma.c | 137 +++++++++++++++++++----- drivers/video/msm/mdss/mdp3_dma.h | 12 ++- drivers/video/msm/mdss/mdp3_layer.c | 34 ++++-- drivers/video/msm/mdss/mdp3_ppp.c | 57 +++++++++- 8 files changed, 367 insertions(+), 54 deletions(-) diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c index fe343ee9d05bf..42c37a0d3330a 100644 --- a/drivers/video/msm/mdss/mdp3.c +++ b/drivers/video/msm/mdss/mdp3.c @@ -47,6 +47,7 @@ #include #include #include +#include #include @@ -2874,7 +2875,7 @@ int mdp3_panel_get_intf_status(u32 disp_num, u32 intf_type) static int mdp3_probe(struct platform_device *pdev) { - int rc; + int rc, scm_ret = 0; static struct msm_mdp_interface mdp3_interface = { .init_fnc = mdp3_init, .fb_mem_get_iommu_domain = mdp3_fb_mem_get_iommu_domain, @@ -2993,6 +2994,10 @@ static int mdp3_probe(struct platform_device *pdev) __mdp3_set_supported_formats(); + rc = scm_restore_sec_cfg(SEC_DEVICE_MDP3, 0, &scm_ret); + if (rc) + pr_err("Restore secure cfg failed\n"); + mdp3_res->mdss_util->mdp_probe_done = true; pr_debug("%s: END\n", __func__); diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h index 295aff263ca82..d53e8df4cc062 100644 --- a/drivers/video/msm/mdss/mdp3.h +++ b/drivers/video/msm/mdss/mdp3.h @@ -30,6 +30,7 @@ #define MDP_CORE_CLK_RATE_SVS 160000000 #define MDP_CORE_CLK_RATE_SUPER_SVS 200000000 #define MDP_CORE_CLK_RATE_MAX 307200000 +#define SEC_DEVICE_MDP3 1 #define CLK_FUDGE_NUM 12 #define CLK_FUDGE_DEN 10 @@ -94,6 +95,12 @@ enum { DI_MAX, }; +enum mdp3_sd_transition { + NO_TRANSITION, + NONSECURE_TO_SECURE, + SECURE_TO_NONSECURE, +}; + struct mdp3_bus_handle_map { struct msm_bus_vectors *bus_vector; struct msm_bus_paths *usecases; diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c index 776ba2aa3f92f..d3926277592d0 100644 --- a/drivers/video/msm/mdss/mdp3_ctrl.c +++ b/drivers/video/msm/mdss/mdp3_ctrl.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "mdp3_ctrl.h" #include "mdp3.h" @@ -31,6 +32,7 @@ #include "mdss_smmu.h" #define VSYNC_EXPIRE_TICK 4 +#define MEM_PROTECT_SD_CTRL 0xF static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd); static int mdp3_overlay_unset(struct msm_fb_data_type *mfd, int ndx); @@ -363,12 +365,46 @@ void mdp3_vsync_timer_func(unsigned long arg) } } +int config_secure_display(struct mdp3_session_data *mdp3_session) +{ + struct sd_ctrl_req { + unsigned int enable; + } __attribute__ ((__packed__)) request; + unsigned int resp = -1; + int ret = 0; + struct scm_desc desc; + + if (mdp3_session->transition_state == NONSECURE_TO_SECURE) + atomic_inc(&mdp3_session->secure_display); + else if (mdp3_session->transition_state == SECURE_TO_NONSECURE) + atomic_dec(&mdp3_session->secure_display); + + request.enable = atomic_read(&mdp3_session->secure_display); + desc.args[0] = request.enable; + desc.arginfo = SCM_ARGS(1); + + if (!is_scm_armv8()) { + ret = scm_call(SCM_SVC_MP, MEM_PROTECT_SD_CTRL, + &request, sizeof(request), &resp, sizeof(resp)); + } else { + ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, + MEM_PROTECT_SD_CTRL), &desc); + resp = desc.ret[0]; + } + + pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%di resp =%d\n", + request.enable, ret, resp); + + return resp; +} + static int mdp3_ctrl_async_blit_req(struct msm_fb_data_type *mfd, void __user *p) { struct mdp_async_blit_req_list req_list_header; int rc, count; void __user *p_req; + struct mdp3_session_data *session; if (copy_from_user(&req_list_header, p, sizeof(req_list_header))) return -EFAULT; @@ -376,6 +412,23 @@ static int mdp3_ctrl_async_blit_req(struct msm_fb_data_type *mfd, count = req_list_header.count; if (count < 0 || count >= MAX_BLIT_REQ) return -EINVAL; + + if (!mfd || !mfd->mdp.private1) + return -EINVAL; + + session = (struct mdp3_session_data *)mfd->mdp.private1; + + if (atomic_read(&session->secure_display) && + (mdp3_ctrl_get_intf_type(mfd) == + MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)) { + rc = wait_for_completion_timeout(&session->secure_completion, + msecs_to_jiffies(84)); + if (rc) { + pr_err("Timed out waiting for completion of secure display\n"); + return rc; + } + } + rc = mdp3_ppp_parse_req(p_req, &req_list_header, 1); if (!rc) rc = copy_to_user(p, &req_list_header, sizeof(req_list_header)); @@ -838,6 +891,7 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd) int rc = 0; struct mdp3_session_data *mdp3_session; struct mdss_panel_data *panel; + int scm_ret = 0; pr_debug("mdp3_ctrl_on\n"); mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1; @@ -883,6 +937,10 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd) goto end; } + rc = scm_restore_sec_cfg(SEC_DEVICE_MDP3, 0, &scm_ret); + if (rc) + pr_err("Restoring secure cfg failed\n"); + /* * Get a reference to the runtime pm device. * If idle pc feature is enabled, it will be released @@ -1403,6 +1461,8 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd, int rc = 0; static bool splash_done; struct mdss_panel_data *panel; + bool null_commit = false; + bool is_panel_type_cmd = false; if (!mfd || !mfd->mdp.private1) return -EINVAL; @@ -1414,7 +1474,34 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd, if (mdp3_bufq_count(&mdp3_session->bufq_in) == 0) { pr_debug("no buffer in queue yet\n"); - return -EPERM; + null_commit = true; + } + + if (null_commit && mdp3_ctrl_get_intf_type(mfd) == + MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) { + mutex_lock(&mdp3_session->lock); + reinit_completion(&mdp3_session->secure_completion); + mdp3_ctrl_reset_countdown(mdp3_session, mfd); + mdp3_ctrl_clk_enable(mfd, 1); + rc = mdp3_session->dma->handle_null_commit(mdp3_session->dma, + mdp3_session->intf); + + if (atomic_read(&mdp3_session->secure_display)) { + mdp3_session->transition_state = SECURE_TO_NONSECURE; + rc = config_secure_display(mdp3_session); + if (rc) + pr_err("Configuring secure display failed\n"); + } + complete_all(&mdp3_session->secure_completion); + mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_DONE); + if (mdp3_bufq_count(&mdp3_session->bufq_out) > 0) { + data = mdp3_bufq_pop(&mdp3_session->bufq_out); + if (data) + mdp3_put_img(data, MDP3_CLIENT_DMA_P); + } + mdp3_session->vsync_before_commit = 0; + mutex_unlock(&mdp3_session->lock); + return 0; } if (panel_info->partial_update_enabled && @@ -1455,11 +1542,65 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd, return -EPERM; } + if (mfd->panel.type == MIPI_CMD_PANEL) + is_panel_type_cmd = true; + mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_BEGIN); data = mdp3_bufq_pop(&mdp3_session->bufq_in); if (data) { mdp3_ctrl_reset_countdown(mdp3_session, mfd); mdp3_ctrl_clk_enable(mfd, 1); + if (mdp3_session->dma->output_config.out_sel == + MDP3_DMA_OUTPUT_SEL_DSI_CMD) { + rc = mdp3_session->dma->wait_for_dma(mdp3_session->dma, + mdp3_session->intf); + if (!rc && !mdp3_session->first_commit) { + pr_err("dma done timedout\n"); + mutex_unlock(&mdp3_session->lock); + return -ETIMEDOUT; + } + } + + /* For command mode panels, the secure display should be enabled + * only after the previous dma done is completed + */ + + if (mdp3_session->transition_state != NO_TRANSITION) { + rc = config_secure_display(mdp3_session); + if (rc) { + pr_err("Configuring secure display failed\n"); + mutex_unlock(&mdp3_session->lock); + return -EINVAL; + } + } + if (is_panel_type_cmd) { + rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P); + if (rc) { + pr_err("failed to enable iommu\n"); + mdp3_put_img(data, MDP3_CLIENT_DMA_P); + mutex_unlock(&mdp3_session->lock); + return rc; + } + } + + rc = mdp3_map_layer(data, MDP3_CLIENT_DMA_P); + if (data->len < mdp3_session->dma->source_config.stride * + mdp3_session->dma->source_config.height) { + pr_err("buf size(0x%lx) is smaller than dma config(0x%x)\n", + data->len, + (mdp3_session->dma->source_config.stride * + mdp3_session->dma->source_config.height)); + + mdp3_put_img(data, MDP3_CLIENT_DMA_P); + if (is_panel_type_cmd) + mdp3_iommu_disable(MDP3_CLIENT_DMA_P); + mutex_unlock(&mdp3_session->lock); + return -EINVAL; + } + + if (is_panel_type_cmd) + mdp3_iommu_disable(MDP3_CLIENT_DMA_P); + if (mdp3_session->dma->update_src_cfg && panel_info->partial_update_enabled) { panel->panel_info.roi.x = mdp3_session->dma->roi.x; @@ -1467,13 +1608,16 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd, panel->panel_info.roi.w = mdp3_session->dma->roi.w; panel->panel_info.roi.h = mdp3_session->dma->roi.h; rc = mdp3_session->dma->update(mdp3_session->dma, - (void *)(int)data->addr, - mdp3_session->intf, (void *)panel); + (void *)(int)data->addr, mdp3_session->intf, + (void *)panel, + atomic_read(&mdp3_session->secure_display)); } else { rc = mdp3_session->dma->update(mdp3_session->dma, - (void *)(int)data->addr, - mdp3_session->intf, NULL); + (void *)(int)data->addr, mdp3_session->intf, + NULL, + atomic_read(&mdp3_session->secure_display)); } + /* This is for the previous frame */ if (rc < 0) { mdp3_ctrl_notify(mdp3_session, @@ -1622,7 +1766,8 @@ static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd) } rc = mdp3_session->dma->update(mdp3_session->dma, (void *)(int)(mfd->iova + offset), - mdp3_session->intf, NULL); + mdp3_session->intf, NULL, + atomic_read(&mdp3_session->secure_display)); /* This is for the previous frame */ if (rc < 0) { mdp3_ctrl_notify(mdp3_session, @@ -2919,6 +3064,7 @@ int mdp3_ctrl_init(struct msm_fb_data_type *mfd) mdp3_session->histo_status = 0; mdp3_session->lut_sel = 0; BLOCKING_INIT_NOTIFIER_HEAD(&mdp3_session->notifier_head); + atomic_set(&mdp3_session->secure_display, 0); init_timer(&mdp3_session->vsync_timer); mdp3_session->vsync_timer.function = mdp3_vsync_timer_func; @@ -2926,6 +3072,7 @@ int mdp3_ctrl_init(struct msm_fb_data_type *mfd) mdp3_session->vsync_period = 1000 / mfd->panel_info->mipi.frame_rate; mfd->mdp.private1 = mdp3_session; init_completion(&mdp3_session->dma_completion); + init_completion(&mdp3_session->secure_completion); if (intf_type != MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) mdp3_session->wait_for_dma_done = mdp3_wait_for_dma_done; diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h index a3c806a449856..ed37fb3885c58 100644 --- a/drivers/video/msm/mdss/mdp3_ctrl.h +++ b/drivers/video/msm/mdss/mdp3_ctrl.h @@ -1,4 +1,5 @@ -/* Copyright (c) 2013-2014, 2016-2017 The Linux Foundation. All rights reserved. +/* + * Copyright (c) 2013-2014, 2016-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -76,12 +77,16 @@ struct mdp3_session_data { bool dma_active; struct completion dma_completion; + struct completion secure_completion; + int (*wait_for_dma_done)(struct mdp3_session_data *session); /* For retire fence */ struct sw_sync_timeline *vsync_timeline; int retire_cnt; struct work_struct retire_work; + atomic_t secure_display; + int transition_state; }; void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq); @@ -91,5 +96,6 @@ int mdp3_bufq_push(struct mdp3_buffer_queue *bufq, int mdp3_ctrl_get_source_format(u32 imgType); int mdp3_ctrl_get_pack_pattern(u32 imgType); int mdp3_ctrl_reset(struct msm_fb_data_type *mfd); +int config_secure_display(struct mdp3_session_data *mdp3_session); #endif /* MDP3_CTRL_H */ diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c index 50392228fceaf..57f7eb7ee2460 100644 --- a/drivers/video/msm/mdss/mdp3_dma.c +++ b/drivers/video/msm/mdss/mdp3_dma.c @@ -1,5 +1,5 @@ /* Copyright (c) 2013-2014, 2016, The Linux Foundation. All rights reserved. - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. @@ -17,6 +17,7 @@ #include "mdp3_dma.h" #include "mdp3_hwio.h" #include "mdss_debug.h" +#include "mdp3_ctrl.h" #define DMA_STOP_POLL_SLEEP_US 1000 #define DMA_STOP_POLL_TIMEOUT_US 200000 @@ -349,7 +350,7 @@ static int mdp3_dmap_config(struct mdp3_dma *dma, return 0; } -static void mdp3_dmap_config_source(struct mdp3_dma *dma) +static void mdp3_dmap_config_source(struct mdp3_dma *dma, bool enable_secure) { struct mdp3_dma_source *source_config = &dma->source_config; u32 dma_p_cfg_reg, dma_p_size; @@ -362,6 +363,11 @@ static void mdp3_dmap_config_source(struct mdp3_dma *dma) dma_p_size = dma->roi.w | (dma->roi.h << 16); + if (enable_secure) + dma_p_cfg_reg |= BIT(21); + else + dma_p_cfg_reg &= ~BIT(21); + MDP3_REG_WRITE(MDP3_REG_DMA_P_CONFIG, dma_p_cfg_reg); MDP3_REG_WRITE(MDP3_REG_DMA_P_SIZE, dma_p_size); MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_Y_STRIDE, source_config->stride); @@ -404,7 +410,7 @@ static int mdp3_dmas_config(struct mdp3_dma *dma, return 0; } -static void mdp3_dmas_config_source(struct mdp3_dma *dma) +static void mdp3_dmas_config_source(struct mdp3_dma *dma, bool enable_secure) { struct mdp3_dma_source *source_config = &dma->source_config; u32 dma_s_cfg_reg, dma_s_size; @@ -652,45 +658,118 @@ int dma_bpp(int format) return bpp; } +static int mdp3_handle_null_commit(struct mdp3_dma *dma, struct mdp3_intf *intf) +{ + int rc = 0; + int retry_count = 2; + unsigned long flag; + int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC; + + if (!dma->source_config.format && !dma->source_config.stride) { + pr_debug("Null commit already handled\n"); + return 0; + } + + /* + * Size and stride are set to 0 to ensure that DMA pipe does not + * fetch anything whenever we get a null commit. The values will be + * reconfigured to the correct values in the next commit. + */ + + MDP3_REG_WRITE(MDP3_REG_DMA_P_SIZE, 0); + MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_Y_STRIDE, 0); + + spin_lock_irqsave(&dma->dma_lock, flag); + dma->source_config.format = 0; + dma->source_config.stride = 0; + mdp3_irq_disable(MDP3_INTR_LCDC_UNDERFLOW); + MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_UNDERFLOW_CTL, 0x80000000); + + if (!intf->active) { + pr_debug("%s start interface\n", __func__); + intf->start(intf); + } + + /* + * Make sure that all the configurations required for + * null commit is done before waiting for the vsync. + */ + mb(); + dma->vsync_status = MDP3_REG_READ(MDP3_REG_INTR_STATUS) & + (1 << MDP3_INTR_LCDC_START_OF_FRAME); + init_completion(&dma->vsync_comp); + spin_unlock_irqrestore(&dma->dma_lock, flag); + mdp3_dma_callback_enable(dma, cb_type); + +retry_vsync: + pr_debug("wait for vsync_comp started\n"); + rc = wait_for_completion_timeout(&dma->vsync_comp, + KOFF_TIMEOUT); + if (rc <= 0 && --retry_count) { + int vsync = MDP3_REG_READ(MDP3_REG_INTR_STATUS) & + (1 << MDP3_INTR_LCDC_START_OF_FRAME); + if (!vsync) { + pr_err("%s trying again count = %d\n", + __func__, retry_count); + goto retry_vsync; + } + rc = -1; + } + pr_debug("wait for vsync_comp done\n"); + +return rc; + +} + +static int mdp3_wait_for_dma_comp(struct mdp3_dma *dma, struct mdp3_intf *intf) +{ + int vsync_status; + int rc = 0; + int retry_count = 2; + + if (intf->active) { + ATRACE_BEGIN("mdp3_wait_for_dma_comp"); +retry_dma_done: + rc = wait_for_completion_timeout(&dma->dma_comp, + KOFF_TIMEOUT); + if (rc <= 0 && --retry_count) { + vsync_status = (1 << MDP3_INTR_DMA_P_DONE) & + MDP3_REG_READ(MDP3_REG_INTR_STATUS); + if (!vsync_status) { + pr_err("%s: cmd timeout retry cnt %d\n", + __func__, retry_count); + goto retry_dma_done; + } else { + rc = 1; + } + } + ATRACE_END("mdp3_wait_for_dma_comp"); + } + return rc; +} + static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf, - struct mdp3_intf *intf, void *data) + struct mdp3_intf *intf, void *data, bool secure) { unsigned long flag; int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC; struct mdss_panel_data *panel; int rc = 0; int retry_count = 2; + int vsync = 0; ATRACE_BEGIN(__func__); pr_debug("mdp3_dmap_update\n"); if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) { cb_type = MDP3_DMA_CALLBACK_TYPE_DMA_DONE; - if (intf->active) { - ATRACE_BEGIN("mdp3_wait_for_dma_comp"); -retry_dma_done: - rc = wait_for_completion_timeout(&dma->dma_comp, - KOFF_TIMEOUT); - if (rc <= 0 && --retry_count) { - int vsync_status; - - vsync_status = (1 << MDP3_INTR_DMA_P_DONE) & - MDP3_REG_READ(MDP3_REG_INTR_STATUS); - if (!vsync_status) { - pr_err("%s: cmd timeout retry cnt %d\n", - __func__, retry_count); - goto retry_dma_done; - } - rc = -1; - } - ATRACE_END("mdp3_wait_for_dma_comp"); - } } + if (dma->update_src_cfg) { if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO && intf->active) pr_err("configuring dma source while it is active\n"); - dma->dma_config_source(dma); + dma->dma_config_source(dma, secure); if (data) { panel = (struct mdss_panel_data *)data; if (panel->event_handler) { @@ -734,7 +813,7 @@ static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf, rc = wait_for_completion_timeout(&dma->vsync_comp, KOFF_TIMEOUT); if (rc <= 0 && --retry_count) { - int vsync = MDP3_REG_READ(MDP3_REG_INTR_STATUS) & + vsync = MDP3_REG_READ(MDP3_REG_INTR_STATUS) & (1 << MDP3_INTR_LCDC_START_OF_FRAME); if (!vsync) { @@ -745,6 +824,9 @@ static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf, rc = -1; } ATRACE_END("mdp3_wait_for_vsync_comp"); + + if (!mdp3_res->irq_ref_count[MDP3_INTR_LCDC_UNDERFLOW]) + mdp3_irq_enable(MDP3_INTR_LCDC_UNDERFLOW); } pr_debug("$%s wait for vsync_comp out\n", __func__); ATRACE_END(__func__); @@ -752,7 +834,7 @@ static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf, } static int mdp3_dmas_update(struct mdp3_dma *dma, void *buf, - struct mdp3_intf *intf, void *data) + struct mdp3_intf *intf, void *data, bool secure) { unsigned long flag; int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC; @@ -1076,6 +1158,8 @@ int mdp3_dma_init(struct mdp3_dma *dma) dma->config_histo = mdp3_dmap_histo_config; dma->config_lut = mdp3_dmap_lut_config; dma->update = mdp3_dmap_update; + dma->handle_null_commit = mdp3_handle_null_commit; + dma->wait_for_dma = mdp3_wait_for_dma_comp; dma->update_cursor = mdp3_dmap_cursor_update; dma->get_histo = mdp3_dmap_histo_get; dma->histo_op = mdp3_dmap_histo_op; @@ -1094,6 +1178,7 @@ int mdp3_dma_init(struct mdp3_dma *dma) dma->config_ccs = NULL; dma->config_histo = NULL; dma->config_lut = NULL; + dma->handle_null_commit = NULL; dma->update = mdp3_dmas_update; dma->update_cursor = NULL; dma->get_histo = NULL; diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h index 36a3dba9f4c4e..4a9b2d3cc6102 100644 --- a/drivers/video/msm/mdss/mdp3_dma.h +++ b/drivers/video/msm/mdss/mdp3_dma.h @@ -1,5 +1,5 @@ /* Copyright (c) 2013-2014, 2016, The Linux Foundation. All rights reserved. - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. @@ -301,7 +301,7 @@ struct mdp3_dma { int (*dma_sync_config)(struct mdp3_dma *dma, struct mdp3_dma_source *source_config, struct mdp3_tear_check *te); - void (*dma_config_source)(struct mdp3_dma *dma); + void (*dma_config_source)(struct mdp3_dma *dma, bool enable_secure); int (*start)(struct mdp3_dma *dma, struct mdp3_intf *intf); @@ -318,8 +318,8 @@ struct mdp3_dma { struct mdp3_dma_lut_config *config, struct fb_cmap *cmap); - int (*update)(struct mdp3_dma *dma, - void *buf, struct mdp3_intf *intf, void *data); + int (*update)(struct mdp3_dma *dma, void *buf, struct mdp3_intf *intf, + void *data, bool secure); int (*update_cursor)(struct mdp3_dma *dma, int x, int y); @@ -338,6 +338,10 @@ struct mdp3_dma { void (*dma_done_notifier)(struct mdp3_dma *dma, struct mdp3_notification *dma_client); + + int (*wait_for_dma)(struct mdp3_dma *dma, struct mdp3_intf *intf); + + int (*handle_null_commit)(struct mdp3_dma *dma, struct mdp3_intf *intf); }; struct mdp3_video_intf_cfg { diff --git a/drivers/video/msm/mdss/mdp3_layer.c b/drivers/video/msm/mdss/mdp3_layer.c index 81472780d17c3..4c63457dd45fa 100644 --- a/drivers/video/msm/mdss/mdp3_layer.c +++ b/drivers/video/msm/mdss/mdp3_layer.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -188,7 +188,6 @@ static int __mdp3_map_layer_buffer(struct msm_fb_data_type *mfd, struct mdp_input_layer *input_layer) { struct mdp3_session_data *mdp3_session = mfd->mdp.private1; - struct mdp3_dma *dma = mdp3_session->dma; struct mdp_input_layer *layer = NULL; struct mdp_layer_buffer *buffer; struct msmfb_data img; @@ -221,21 +220,15 @@ static int __mdp3_map_layer_buffer(struct msm_fb_data_type *mfd, } } + if (layer->flags & MDP_LAYER_SECURE_DISPLAY_SESSION) + data.flags |= MDP_SECURE_DISPLAY_OVERLAY_SESSION; + rc = mdp3_get_img(&img, &data, MDP3_CLIENT_DMA_P); if (rc) { pr_err("fail to get overlay buffer\n"); goto err; } - if (data.len < dma->source_config.stride * dma->source_config.height) { - pr_err("buf size(0x%lx) is smaller than dma config(0x%x)\n", - data.len, (dma->source_config.stride * - dma->source_config.height)); - mdp3_put_img(&data, MDP3_CLIENT_DMA_P); - rc = -EINVAL; - goto err; - } - rc = mdp3_bufq_push(&mdp3_session->bufq_in, &data); if (rc) { pr_err("fail to queue the overlay buffer, buffer drop\n"); @@ -249,6 +242,23 @@ static int __mdp3_map_layer_buffer(struct msm_fb_data_type *mfd, return rc; } +static void mdp3_validate_secure_layer(struct msm_fb_data_type *mfd, + struct mdp_input_layer *input_layer) +{ + struct mdp3_session_data *mdp3_session = mfd->mdp.private1; + struct mdp_input_layer *layer = &input_layer[0]; + + if (!atomic_read(&mdp3_session->secure_display) && + (layer->flags & MDP_LAYER_SECURE_DISPLAY_SESSION)) { + mdp3_session->transition_state = NONSECURE_TO_SECURE; + } else if (atomic_read(&mdp3_session->secure_display) && + !(layer->flags & MDP_LAYER_SECURE_DISPLAY_SESSION)) { + mdp3_session->transition_state = SECURE_TO_NONSECURE; + } else { + mdp3_session->transition_state = NO_TRANSITION; + } +} + int mdp3_layer_pre_commit(struct msm_fb_data_type *mfd, struct file *file, struct mdp_layer_commit_v1 *commit) { @@ -296,6 +306,8 @@ int mdp3_layer_pre_commit(struct msm_fb_data_type *mfd, return ret; } + mdp3_validate_secure_layer(mfd, layer); + ret = __mdp3_map_layer_buffer(mfd, layer); if (ret) { pr_err("Failed to map buffer\n"); diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c index b45f72f6a7115..469d2667712e7 100644 --- a/drivers/video/msm/mdss/mdp3_ppp.c +++ b/drivers/video/msm/mdss/mdp3_ppp.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2007, 2013-2014, 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2007, 2013-2014, 2016-2018, The Linux Foundation. All rights reserved. * Copyright (C) 2007 Google Incorporated * * This software is licensed under the terms of the GNU General Public @@ -30,6 +30,7 @@ #include "mdp3_hwio.h" #include "mdp3.h" #include "mdss_debug.h" +#include "mdp3_ctrl.h" #define MDP_IS_IMGTYPE_BAD(x) ((x) >= MDP_IMGTYPE_LIMIT) #define MDP_RELEASE_BW_TIMEOUT 50 @@ -1492,7 +1493,7 @@ static bool is_blit_optimization_possible(struct blit_req_list *req, int indx) static void mdp3_ppp_blit_handler(struct kthread_work *work) { struct msm_fb_data_type *mfd = ppp_stat->mfd; - struct blit_req_list *req; + struct blit_req_list *req = NULL; int i, rc = 0; bool smart_blit = false; int smart_blit_fg_index = -1; @@ -1512,7 +1513,20 @@ static void mdp3_ppp_blit_handler(struct kthread_work *work) return; } } + while (req) { + for (i = 0; i < req->count; i++) { + rc = mdp3_map_layer(&req->src_data[i], MDP3_CLIENT_PPP); + if (rc < 0 || req->src_data[i].len == 0) { + pr_err("mdp_ppp: couldn't retrieve src img from mem\n"); + goto map_err; + } + rc = mdp3_map_layer(&req->dst_data[i], MDP3_CLIENT_PPP); + if (rc < 0 || req->dst_data[i].len == 0) { + pr_err("mdp_ppp: couldn't retrieve dest img from mem\n"); + goto map_err; + } + } mdp3_ppp_wait_for_fence(req); mdp3_calc_ppp_res(mfd, req); if (ppp_res.clk_rate != ppp_stat->mdp_clk) { @@ -1575,6 +1589,14 @@ static void mdp3_ppp_blit_handler(struct kthread_work *work) mod_timer(&ppp_stat->free_bw_timer, jiffies + msecs_to_jiffies(MDP_RELEASE_BW_TIMEOUT)); mutex_unlock(&ppp_stat->config_ppp_mutex); + return; + +map_err: + for (i = 0; i < req->count; i++) { + mdp3_put_img(&req->src_data[i], MDP3_CLIENT_PPP); + mdp3_put_img(&req->dst_data[i], MDP3_CLIENT_PPP); + } + mutex_unlock(&ppp_stat->config_ppp_mutex); } int mdp3_ppp_parse_req(void __user *p, @@ -1583,6 +1605,8 @@ int mdp3_ppp_parse_req(void __user *p, { struct blit_req_list *req; struct blit_req_queue *req_q = &ppp_stat->req_q; + struct msm_fb_data_type *mfd = ppp_stat->mfd; + struct mdp3_session_data *mdp3_session = mfd->mdp.private1; struct sync_fence *fence = NULL; int count, rc, idx, i; count = req_list_header->count; @@ -1623,15 +1647,14 @@ int mdp3_ppp_parse_req(void __user *p, for (i = 0; i < count; i++) { rc = mdp3_ppp_get_img(&req->req_list[i].src, &req->req_list[i], &req->src_data[i]); - if (rc < 0 || req->src_data[i].len == 0) { + if (rc) { pr_err("mdp_ppp: couldn't retrieve src img from mem\n"); goto parse_err_1; } rc = mdp3_ppp_get_img(&req->req_list[i].dst, &req->req_list[i], &req->dst_data[i]); - if (rc < 0 || req->dst_data[i].len == 0) { - mdp3_put_img(&req->src_data[i], MDP3_CLIENT_PPP); + if (rc) { pr_err("mdp_ppp: couldn't retrieve dest img from mem\n"); goto parse_err_1; } @@ -1655,6 +1678,30 @@ int mdp3_ppp_parse_req(void __user *p, fence = req->cur_rel_fence; } + /* + * Whenever we get a blit request after a secure session, we need + * to wait for the previous secure dma transfer to complete for command + * mode panels. Since blit requests are always non-secure, add support + * for transition from secure to non-secure after the secure dma is + * completed. + */ + + if (atomic_read(&mdp3_session->secure_display) && + (mfd->panel.type == MDP3_DMA_OUTPUT_SEL_DSI_CMD)) { + rc = mdp3_session->dma->wait_for_dma(mdp3_session->dma, + mdp3_session->intf); + if (rc) { + pr_err("secure dma done not completed\n"); + goto parse_err_2; + } + mdp3_session->transition_state = SECURE_TO_NONSECURE; + rc = config_secure_display(mdp3_session); + if (rc) { + pr_err("Configuring secure display failed\n"); + goto parse_err_2; + } + } + mdp3_ppp_req_push(req_q, req); mutex_unlock(&ppp_stat->req_mutex); queue_kthread_work(&ppp_stat->kworker, &ppp_stat->blit_work); From b68b21bdc28f9c0db119a581ff9b2c5b2091d502 Mon Sep 17 00:00:00 2001 From: Krishna Manikandan Date: Thu, 31 May 2018 17:33:42 +0530 Subject: [PATCH 453/508] msm: mdss: Add support to wait for dma_done in pan display Add support to wait for dma_done for the previous commit before proceeding with the current commit in the pan_display path for command mode panels. Change-Id: Ie933ba547075c97ddb6ddbed2bc3ff08cc645010 Signed-off-by: Krishna Manikandan --- drivers/video/msm/mdss/mdp3_ctrl.c | 11 +++++++++++ drivers/video/msm/mdss/mdp3_ppp.c | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c index d3926277592d0..127ed385f333c 100644 --- a/drivers/video/msm/mdss/mdp3_ctrl.c +++ b/drivers/video/msm/mdss/mdp3_ctrl.c @@ -1764,6 +1764,17 @@ static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd) if (IS_ERR_VALUE(rc)) goto pan_error; } + + if (mdp3_ctrl_get_intf_type(mfd) == + MDP3_DMA_OUTPUT_SEL_DSI_CMD) { + rc = mdp3_session->dma->wait_for_dma(mdp3_session->dma, + mdp3_session->intf); + if (!rc && !mdp3_session->first_commit) { + pr_err("dma done timedout\n"); + goto pan_error; + } + } + rc = mdp3_session->dma->update(mdp3_session->dma, (void *)(int)(mfd->iova + offset), mdp3_session->intf, NULL, diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c index 469d2667712e7..3d3745498fc8b 100644 --- a/drivers/video/msm/mdss/mdp3_ppp.c +++ b/drivers/video/msm/mdss/mdp3_ppp.c @@ -1690,7 +1690,7 @@ int mdp3_ppp_parse_req(void __user *p, (mfd->panel.type == MDP3_DMA_OUTPUT_SEL_DSI_CMD)) { rc = mdp3_session->dma->wait_for_dma(mdp3_session->dma, mdp3_session->intf); - if (rc) { + if (!rc) { pr_err("secure dma done not completed\n"); goto parse_err_2; } From 7bc35f220aa2925de502e7a0f15d8e54571bf2c6 Mon Sep 17 00:00:00 2001 From: Kiran Gunda Date: Thu, 17 May 2018 17:00:34 +0530 Subject: [PATCH 454/508] regulator: core: Fix buffer overflow issue There is a possible buffer overflow in the "reg_debug_volt_get" function. Fix it by passing the appropriate byte count. Change-Id: I30868790c42cdb225af74054532a75c49506fe82 Signed-off-by: Kiran Gunda --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 7b2a4b6ddb870..3bfc88b68a1e1 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3824,7 +3824,7 @@ static ssize_t reg_debug_volt_get(struct file *file, char __user *buf, mutex_lock(&debug_buf_mutex); output = snprintf(debug_buf, MAX_DEBUG_BUF_LEN-1, "%d\n", voltage); - rc = simple_read_from_buffer((void __user *) buf, output, ppos, + rc = simple_read_from_buffer((void __user *) buf, count, ppos, (void *) debug_buf, output); mutex_unlock(&debug_buf_mutex); From ce757d71e63af81c10c4171e4bb181de3bc537d6 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Thu, 14 Sep 2017 17:14:41 -0400 Subject: [PATCH 455/508] packet: hold bind lock when rebinding to fanout hook [ Upstream commit 008ba2a13f2d04c947adc536d19debb8fe66f110 ] Packet socket bind operations must hold the po->bind_lock. This keeps po->running consistent with whether the socket is actually on a ptype list to receive packets. fanout_add unbinds a socket and its packet_rcv/tpacket_rcv call, then binds the fanout object to receive through packet_rcv_fanout. Make it hold the po->bind_lock when testing po->running and rebinding. Else, it can race with other rebind operations, such as that in packet_set_ring from packet_rcv to tpacket_rcv. Concurrent updates can result in a socket being added to a fanout group twice, causing use-after-free KASAN bug reports, among others. Reported independently by both trinity and syzkaller. Verified that the syzkaller reproducer passes after this patch. Change-Id: I085f048f219cf927ce21c26c21da9f0729801503 Fixes: dc99f600698d ("packet: Add fanout support.") Reported-by: nixioaming Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Git-repo: https://android.googlesource.com/kernel/common Git-commit: e4ffdf9ead59a909f2824a4270356909d6d64380 Signed-off-by: Ashwanth Goli --- net/packet/af_packet.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 3878c34b531b1..beab0f9410a7b 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1475,7 +1475,10 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) list_add(&match->list, &fanout_list); } err = -EINVAL; - if (match->type == type && + + spin_lock(&po->bind_lock); + if (po->running && + match->type == type && match->prot_hook.type == po->prot_hook.type && match->prot_hook.dev == po->prot_hook.dev) { err = -ENOSPC; @@ -1487,6 +1490,13 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) err = 0; } } + spin_unlock(&po->bind_lock); + + if (err && !atomic_read(&match->sk_ref)) { + list_del(&match->list); + kfree(match); + } + out: mutex_unlock(&fanout_mutex); return err; From 99c07865823090b8e507484ac3483b4425993145 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Tue, 26 Sep 2017 12:19:37 -0400 Subject: [PATCH 456/508] packet: in packet_do_bind, test fanout with bind_lock held [ Upstream commit 4971613c1639d8e5f102c4e797c3bf8f83a5a69e ] Once a socket has po->fanout set, it remains a member of the group until it is destroyed. The prot_hook must be constant and identical across sockets in the group. If fanout_add races with packet_do_bind between the test of po->fanout and taking the lock, the bind call may make type or dev inconsistent with that of the fanout group. Hold po->bind_lock when testing po->fanout to avoid this race. I had to introduce artificial delay (local_bh_enable) to actually observe the race. Change-Id: I8944e2bb562f72f8e1d50ad4bc60a3bce82cf089 Fixes: dc99f600698d ("packet: Add fanout support.") Signed-off-by: Willem de Bruijn Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Git-repo: https://android.googlesource.com/kernel/common Git-commit: b0763909b4538894bb47614656c75f2a233c40d2 Signed-off-by: Ashwanth Goli --- net/packet/af_packet.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index beab0f9410a7b..1a4ed50b57423 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2687,13 +2687,15 @@ static int packet_do_bind(struct sock *sk, const char *name, int ifindex, int ret = 0; bool unlisted = false; - if (po->fanout) - return -EINVAL; - lock_sock(sk); spin_lock(&po->bind_lock); rcu_read_lock(); + if (po->fanout) { + ret = -EINVAL; + goto out_unlock; + } + if (name) { dev = dev_get_by_name_rcu(sock_net(sk), name); if (!dev) { From 1554c3b1e6ab4f9ae286aaca8b7657a911f75d09 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Fri, 11 May 2018 13:54:54 +0530 Subject: [PATCH 457/508] msm: ipa: fix to not allow NAT DMA command without device initialization Without NAT device initialization sending NAT DMA commands leads to XPU violation. Added checks to verify device initialized or not before sending DMA command. Change-Id: I7440abc14a81e1621573f0e2808a410d60b2458d Acked-by: Ashok Vuyyuru Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v2/ipa_nat.c | 22 +++++++++++++++++++++- drivers/platform/msm/ipa/ipa_v3/ipa_nat.c | 7 ++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c index e7092e9acbc74..1be68b31656b6 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -327,6 +327,11 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init) size_t tmp; gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0); + if (!ipa_ctx->nat_mem.is_dev_init) { + IPAERR_RL("Nat table not initialized\n"); + return -EPERM; + } + IPADBG("\n"); if (init->table_entries == 0) { IPADBG("Table entries is zero\n"); @@ -572,6 +577,11 @@ int ipa2_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) int ret = 0; gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0); + if (!ipa_ctx->nat_mem.is_dev_init) { + IPAERR_RL("Nat table not initialized\n"); + return -EPERM; + } + IPADBG("\n"); if (dma->entries <= 0) { IPAERR_RL("Invalid number of commands %d\n", @@ -758,6 +768,16 @@ int ipa2_nat_del_cmd(struct ipa_ioc_v4_nat_del *del) int result; gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0); + if (!ipa_ctx->nat_mem.is_dev_init) { + IPAERR_RL("Nat table not initialized\n"); + return -EPERM; + } + + if (ipa_ctx->nat_mem.public_ip_addr) { + IPAERR_RL("Public IP addr not assigned and trying to delete\n"); + return -EPERM; + } + IPADBG("\n"); if (ipa_ctx->nat_mem.is_tmp_mem) { IPAERR("using temp memory during nat del\n"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c index a78a0a608cb4e..92cd32d6488ac 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -793,6 +793,11 @@ int ipa3_nat_del_cmd(struct ipa_ioc_v4_nat_del *del) } memset(&desc, 0, sizeof(desc)); + if (!ipa3_ctx->nat_mem.is_dev_init) { + IPAERR_RL("NAT hasn't been initialized\n"); + return -EPERM; + } + /* NO-OP IC for ensuring that IPA pipeline is empty */ nop_cmd_pyld = ipahal_construct_nop_imm_cmd(false, IPAHAL_HPS_CLEAR, false); From 9a4851c0d99182c90f8ef99cad2981cf2bd952f5 Mon Sep 17 00:00:00 2001 From: Rama Krishna Phani A Date: Wed, 21 Mar 2018 15:37:56 +0530 Subject: [PATCH 458/508] msm: pcie: Add proper check before accessing variables Add proper check before accessing variables. Change-Id: Idb4aec6e276d7c82a4311be733fcb13b875ae6c8 Signed-off-by: Rama Krishna Phani A --- drivers/pci/host/pci-msm.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c index 435c502076ac0..d848a41bd1b8d 100644 --- a/drivers/pci/host/pci-msm.c +++ b/drivers/pci/host/pci-msm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2366,6 +2366,13 @@ static void msm_pcie_sel_debug_testcase(struct msm_pcie_dev_t *dev, break; } + if (((base_sel - 1) >= MSM_PCIE_MAX_RES) || + (!dev->res[base_sel - 1].resource)) { + PCIE_DBG_FS(dev, "PCIe: RC%d Resource does not exist\n", + dev->rc_idx); + break; + } + PCIE_DBG_FS(dev, "base: %s: 0x%p\nwr_offset: 0x%x\nwr_mask: 0x%x\nwr_value: 0x%x\n", dev->res[base_sel - 1].name, @@ -2385,6 +2392,13 @@ static void msm_pcie_sel_debug_testcase(struct msm_pcie_dev_t *dev, break; case 13: /* dump all registers of base_sel */ + if (((base_sel - 1) >= MSM_PCIE_MAX_RES) || + (!dev->res[base_sel - 1].resource)) { + PCIE_DBG_FS(dev, "PCIe: RC%d Resource does not exist\n", + dev->rc_idx); + break; + } + if (!base_sel) { PCIE_DBG_FS(dev, "Invalid base_sel: 0x%x\n", base_sel); break; From 151761e8e947bcb50577579aa38ce1c7d8107e2a Mon Sep 17 00:00:00 2001 From: Suprith Malligere Shankaregowda Date: Thu, 24 May 2018 12:39:49 +0530 Subject: [PATCH 459/508] ais: isp2: Release buffer lock after use At start axi stream, we acquire the buffer lock and release after completing stream configuration operations. In case of live snapshot, this causes the buffer operations to halt and leading to sof freeze. Change-Id: Ic646d2f98254574c8647883867036907fd417361 Signed-off-by: Suprith Malligere Shankaregowda --- .../media/platform/msm/ais/isp/msm_isp_axi_util.c | 6 +++++- .../media/platform/msm/ais/isp/msm_isp_stats_util.c | 12 ++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c index 2639b649c0782..8b6cfddfe1582 100644 --- a/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c @@ -2813,10 +2813,11 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev, vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id = 0; vfe_dev->axi_data.src_info[VFE_PIX_0].eof_id = 0; } - + mutex_lock(&vfe_dev->buf_mgr->lock); for (i = 0; i < stream_cfg_cmd->num_streams; i++) { if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]) >= VFE_AXI_SRC_MAX) { + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } stream_info = &axi_data->stream_info[ @@ -2826,6 +2827,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev, SRC_TO_INTF(stream_info->stream_src)].active; else { ISP_DBG("%s: invalid src info index\n", __func__); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } @@ -2840,6 +2842,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev, HANDLE_TO_IDX( stream_cfg_cmd->stream_handle[i])); spin_unlock_irqrestore(&stream_info->lock, flags); + mutex_unlock(&vfe_dev->buf_mgr->lock); return rc; } @@ -2898,6 +2901,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev, } } + mutex_unlock(&vfe_dev->buf_mgr->lock); msm_isp_update_stream_bandwidth(vfe_dev, stream_cfg_cmd->hw_state); vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev, vfe_dev->vfe_base, wm_reload_mask); diff --git a/drivers/media/platform/msm/ais/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/ais/isp/msm_isp_stats_util.c index ba3c32a7b4079..1d39af412bd83 100644 --- a/drivers/media/platform/msm/ais/isp/msm_isp_stats_util.c +++ b/drivers/media/platform/msm/ais/isp/msm_isp_stats_util.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -683,18 +683,23 @@ static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev, stream_cfg_cmd->num_streams); return -EINVAL; } + + mutex_lock(&vfe_dev->buf_mgr->lock); num_stats_comp_mask = vfe_dev->hw_info->stats_hw_info->num_stats_comp_mask; rc = vfe_dev->hw_info->vfe_ops.stats_ops.check_streams( stats_data->stream_info); - if (rc < 0) + if (rc < 0) { + mutex_unlock(&vfe_dev->buf_mgr->lock); return rc; + } for (i = 0; i < stream_cfg_cmd->num_streams; i++) { idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]); if (idx >= vfe_dev->hw_info->stats_hw_info->num_stats_type) { pr_err("%s Invalid stats index %d", __func__, idx); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } @@ -710,11 +715,13 @@ static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev, pr_err("%s: comp grp %d exceed max %d\n", __func__, stream_info->composite_flag, num_stats_comp_mask); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } rc = msm_isp_init_stats_ping_pong_reg(vfe_dev, stream_info); if (rc < 0) { pr_err("%s: No buffer for stream%d\n", __func__, idx); + mutex_unlock(&vfe_dev->buf_mgr->lock); return rc; } if (!stream_info->composite_flag) @@ -739,6 +746,7 @@ static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev, stats_data->num_active_stream); } + mutex_unlock(&vfe_dev->buf_mgr->lock); if (vfe_dev->axi_data.src_info[VFE_PIX_0].active) { rc = msm_isp_stats_wait_for_cfg_done(vfe_dev); From 1d7f207f5799533da4c202caea840f115cc27db6 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Thu, 31 May 2018 19:07:58 +0530 Subject: [PATCH 460/508] msm: ipa: gsi: mhi: Couple of code changes Couple of code changes, - Enable IPC logging for MHI driver. IPC logging was missed to enable on mhi driver, enable it. - Configure appropriate polling mode bit for MHI ep. A. For MHI --> IPA pipe: when resuming due to transition to M0, set the polling mode bit to 0. In other cases, restore it's value form when you stopped the channel. B. For IPA-->MHI pipe: Always restore the polling mode bit. Change-Id: Ibc203e8c9dc8d05107a5eba396c76e29c1646479 Signed-off-by: Mohammed Javid --- drivers/platform/msm/gsi/gsi.c | 62 ++++++++++++++++++- drivers/platform/msm/gsi/gsi.h | 3 +- .../msm/ipa/ipa_clients/ipa_mhi_client.c | 34 ++++++++-- drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c | 34 ++++++++-- include/linux/msm_gsi.h | 21 ++++++- 5 files changed, 142 insertions(+), 12 deletions(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 684e255b2cbd0..60a6101998361 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1742,6 +1742,32 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, } EXPORT_SYMBOL(gsi_alloc_channel); +static void __gsi_read_channel_scratch(unsigned long chan_hdl, + union __packed gsi_channel_scratch * val) +{ + uint32_t reg; + + reg = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_0_OFFS(chan_hdl, + gsi_ctx->per.ee)); + val->data.word1 = reg; + + reg = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_1_OFFS(chan_hdl, + gsi_ctx->per.ee)); + val->data.word2 = reg; + + reg = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_2_OFFS(chan_hdl, + gsi_ctx->per.ee)); + val->data.word3 = reg; + + reg = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_3_OFFS(chan_hdl, + gsi_ctx->per.ee)); + val->data.word4 = reg; +} + static void __gsi_write_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch val) { @@ -1802,6 +1828,40 @@ int gsi_write_channel_scratch(unsigned long chan_hdl, } EXPORT_SYMBOL(gsi_write_channel_scratch); +int gsi_read_channel_scratch(unsigned long chan_hdl, + union __packed gsi_channel_scratch * ch_scratch) +{ + struct gsi_chan_ctx *ctx; + + if (!gsi_ctx) { + pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); + return -GSI_STATUS_NODEV; + } + + if (chan_hdl >= gsi_ctx->max_ch) { + GSIERR("bad params chan_hdl=%lu\n", chan_hdl); + return -GSI_STATUS_INVALID_PARAMS; + } + + if (gsi_ctx->chan[chan_hdl].state != GSI_CHAN_STATE_ALLOCATED && + gsi_ctx->chan[chan_hdl].state != GSI_CHAN_STATE_STARTED && + gsi_ctx->chan[chan_hdl].state != GSI_CHAN_STATE_STOPPED) { + GSIERR("bad state %d\n", + gsi_ctx->chan[chan_hdl].state); + return -GSI_STATUS_UNSUPPORTED_OP; + } + + ctx = &gsi_ctx->chan[chan_hdl]; + + mutex_lock(&ctx->mlock); + __gsi_read_channel_scratch(chan_hdl, ch_scratch); + ctx->restore_scratch = *ch_scratch; + mutex_unlock(&ctx->mlock); + + return GSI_STATUS_SUCCESS; +} +EXPORT_SYMBOL(gsi_read_channel_scratch); + int gsi_query_channel_db_addr(unsigned long chan_hdl, uint32_t *db_addr_wp_lsb, uint32_t *db_addr_wp_msb) { diff --git a/drivers/platform/msm/gsi/gsi.h b/drivers/platform/msm/gsi/gsi.h index 32fb17885fff7..8fe7886b52068 100644 --- a/drivers/platform/msm/gsi/gsi.h +++ b/drivers/platform/msm/gsi/gsi.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -129,6 +129,7 @@ struct gsi_chan_ctx { bool allocated; atomic_t poll_mode; union __packed gsi_channel_scratch scratch; + union __packed gsi_channel_scratch restore_scratch; struct gsi_chan_stats stats; bool enable_dp_stats; bool print_dp_stats; diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c index de944ec0fd096..158be880b953a 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2017-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -21,13 +21,39 @@ #include "../ipa_common_i.h" #define IPA_MHI_DRV_NAME "ipa_mhi_client" + #define IPA_MHI_DBG(fmt, args...) \ - pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \ - __func__, __LINE__, ## args) + do { \ + pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + +#define IPA_MHI_DBG_LOW(fmt, args...) \ + do { \ + pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + + #define IPA_MHI_ERR(fmt, args...) \ - pr_err(IPA_MHI_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) + do { \ + pr_err(IPA_MHI_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + #define IPA_MHI_FUNC_ENTRY() \ IPA_MHI_DBG("ENTRY\n") + #define IPA_MHI_FUNC_EXIT() \ IPA_MHI_DBG("EXIT\n") diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c index 061c3554f434b..c56a60f7a7fcc 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -56,9 +56,9 @@ #define IPA_MHI_FUNC_ENTRY() \ - IPA_MHI_DBG_LOW("ENTRY\n") + IPA_MHI_DBG("ENTRY\n") #define IPA_MHI_FUNC_EXIT() \ - IPA_MHI_DBG_LOW("EXIT\n") + IPA_MHI_DBG("EXIT\n") #define IPA_MHI_MAX_UL_CHANNELS 1 #define IPA_MHI_MAX_DL_CHANNELS 1 @@ -537,6 +537,7 @@ int ipa3_mhi_resume_channels_internal(enum ipa_client_type client, int res; int ipa_ep_idx; struct ipa3_ep_context *ep; + union __packed gsi_channel_scratch gsi_ch_scratch; IPA_MHI_FUNC_ENTRY(); @@ -551,11 +552,34 @@ int ipa3_mhi_resume_channels_internal(enum ipa_client_type client, /* * set polling mode bit to DB mode before * resuming the channel + * + * For MHI-->IPA pipes: + * when resuming due to transition to M0, + * set the polling mode bit to 0. + * In other cases, restore it's value form + * when you stopped the channel. + * Here, after successful resume client move to M0 state. + * So, by default setting polling mode bit to 0. + * + * For IPA-->MHI pipe: + * always restore the polling mode bit. */ + + res = gsi_read_channel_scratch( + ep->gsi_chan_hdl, &gsi_ch_scratch); + if (res) { + IPA_MHI_ERR("Read ch scratch fail %d\n" + , res); + return res; + } + + if (IPA_CLIENT_IS_PROD(client)) + gsi_ch_scratch.mhi.polling_mode = false; + res = gsi_write_channel_scratch( - ep->gsi_chan_hdl, ch_scratch); + ep->gsi_chan_hdl, gsi_ch_scratch); if (res) { - IPA_MHI_ERR("write ch scratch fail %d\n" + IPA_MHI_ERR("Write ch scratch fail %d\n" , res); return res; } diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h index 1d6a1c6d1d068..295211d3983c7 100644 --- a/include/linux/msm_gsi.h +++ b/include/linux/msm_gsi.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -835,6 +835,18 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, int gsi_write_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch val); +/** + * gsi_read_channel_scratch - Peripheral should call this function to + * read the scratch area of the channel context + * + * @chan_hdl: Client handle previously obtained from + * gsi_alloc_channel + * + * @Return gsi_status + */ +int gsi_read_channel_scratch(unsigned long chan_hdl, + union __packed gsi_channel_scratch *ch_scratch); + /** * gsi_start_channel - Peripheral should call this function to * start a channel i.e put into running state @@ -1093,6 +1105,7 @@ int gsi_halt_channel_ee(unsigned int chan_idx, unsigned int ee, int *code); * gsi_alloc_channel (for as many channels as needed; channels can have * no event ring, an exclusive event ring or a shared event ring) * gsi_write_channel_scratch + * gsi_read_channel_scratch * gsi_start_channel * gsi_queue_xfer/gsi_start_xfer * gsi_config_channel_mode/gsi_poll_channel (if clients wants to poll on @@ -1177,6 +1190,12 @@ static inline int gsi_write_channel_scratch(unsigned long chan_hdl, return -GSI_STATUS_UNSUPPORTED_OP; } +static inline int gsi_read_channel_scratch(unsigned long chan_hdl, + union __packed gsi_channel_scratch *ch_scratch) +{ + return -GSI_STATUS_UNSUPPORTED_OP; +} + static inline int gsi_start_channel(unsigned long chan_hdl) { return -GSI_STATUS_UNSUPPORTED_OP; From db07e46cefa1435ee4b2bb62985da1b412b226b3 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Mon, 5 Jun 2017 09:27:48 -0700 Subject: [PATCH 461/508] msm: ipa: ipa_usb: remove SUSPEND_IN_PROGRESS state Remove the usage of SUSPEND_IN_PROGRESS state in IPA USB. This state was introduced to allow USB host suspend without setting USB controller to LPM. As this scenario is not a requirement, SUSPEND_IN_PROGRESS is not supported anymore. Instead IPA USB will go to full suspend state. Change-Id: I7224144fcf6cb70a030657aa59cb858fa3d410d8 CRs-Fixed: 2054613 Acked-by: Ady Abraham Signed-off-by: Skylar Chang --- .../platform/msm/ipa/ipa_clients/ipa_usb.c | 204 +++--------------- drivers/platform/msm/ipa/ipa_v3/ipa_client.c | 20 +- 2 files changed, 43 insertions(+), 181 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c index aef946b139000..f78b7fa852bf3 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c @@ -125,7 +125,6 @@ enum ipa3_usb_state { IPA_USB_CONNECTED, IPA_USB_STOPPED, IPA_USB_SUSPEND_REQUESTED, - IPA_USB_SUSPEND_IN_PROGRESS, IPA_USB_SUSPENDED, IPA_USB_SUSPENDED_NO_RWAKEUP, IPA_USB_RESUME_IN_PROGRESS @@ -146,13 +145,6 @@ enum ipa3_usb_transport_type { #define IPA3_USB_IS_TTYPE_DPL(__ttype) \ ((__ttype) == IPA_USB_TRANSPORT_DPL) -struct finish_suspend_work_context { - struct work_struct work; - enum ipa3_usb_transport_type ttype; - u32 dl_clnt_hdl; - u32 ul_clnt_hdl; -}; - struct ipa3_usb_teth_prot_conn_params { u32 usb_to_ipa_clnt_hdl; u32 ipa_to_usb_clnt_hdl; @@ -168,7 +160,6 @@ struct ipa3_usb_transport_type_ctx { int (*ipa_usb_notify_cb)(enum ipa_usb_notify_event, void *user_data); void *user_data; enum ipa3_usb_state state; - struct finish_suspend_work_context finish_suspend_work; struct ipa_usb_xdci_chan_params ch_params; struct ipa3_usb_teth_prot_conn_params teth_conn_params; }; @@ -221,16 +212,10 @@ struct ipa3_usb_status_dbg_info { static void ipa3_usb_wq_notify_remote_wakeup(struct work_struct *work); static void ipa3_usb_wq_dpl_notify_remote_wakeup(struct work_struct *work); -static void ipa3_usb_wq_notify_suspend_completed(struct work_struct *work); -static void ipa3_usb_wq_dpl_notify_suspend_completed(struct work_struct *work); static DECLARE_WORK(ipa3_usb_notify_remote_wakeup_work, ipa3_usb_wq_notify_remote_wakeup); static DECLARE_WORK(ipa3_usb_dpl_notify_remote_wakeup_work, ipa3_usb_wq_dpl_notify_remote_wakeup); -static DECLARE_WORK(ipa3_usb_notify_suspend_completed_work, - ipa3_usb_wq_notify_suspend_completed); -static DECLARE_WORK(ipa3_usb_dpl_notify_suspend_completed_work, - ipa3_usb_wq_dpl_notify_suspend_completed); struct ipa3_usb_context *ipa3_usb_ctx; @@ -273,8 +258,6 @@ static char *ipa3_usb_state_to_string(enum ipa3_usb_state state) return "IPA_USB_STOPPED"; case IPA_USB_SUSPEND_REQUESTED: return "IPA_USB_SUSPEND_REQUESTED"; - case IPA_USB_SUSPEND_IN_PROGRESS: - return "IPA_USB_SUSPEND_IN_PROGRESS"; case IPA_USB_SUSPENDED: return "IPA_USB_SUSPENDED"; case IPA_USB_SUSPENDED_NO_RWAKEUP: @@ -330,17 +313,11 @@ static bool ipa3_usb_set_state(enum ipa3_usb_state new_state, bool err_permit, * In case of failure during suspend request * handling, state is reverted to connected. */ - (err_permit && state == IPA_USB_SUSPEND_REQUESTED) || - /* - * In case of failure during suspend completing - * handling, state is reverted to connected. - */ - (err_permit && state == IPA_USB_SUSPEND_IN_PROGRESS)) + (err_permit && state == IPA_USB_SUSPEND_REQUESTED)) state_legal = true; break; case IPA_USB_STOPPED: - if (state == IPA_USB_SUSPEND_IN_PROGRESS || - state == IPA_USB_CONNECTED || + if (state == IPA_USB_CONNECTED || state == IPA_USB_SUSPENDED || state == IPA_USB_SUSPENDED_NO_RWAKEUP) state_legal = true; @@ -349,19 +326,8 @@ static bool ipa3_usb_set_state(enum ipa3_usb_state new_state, bool err_permit, if (state == IPA_USB_CONNECTED) state_legal = true; break; - case IPA_USB_SUSPEND_IN_PROGRESS: - if (state == IPA_USB_SUSPEND_REQUESTED || - /* - * In case of failure during resume, state is reverted - * to original, which could be suspend_in_progress. - * Allow it. - */ - (err_permit && state == IPA_USB_RESUME_IN_PROGRESS)) - state_legal = true; - break; case IPA_USB_SUSPENDED: if (state == IPA_USB_SUSPEND_REQUESTED || - state == IPA_USB_SUSPEND_IN_PROGRESS || /* * In case of failure during resume, state is reverted * to original, which could be suspended. Allow it @@ -374,8 +340,7 @@ static bool ipa3_usb_set_state(enum ipa3_usb_state new_state, bool err_permit, state_legal = true; break; case IPA_USB_RESUME_IN_PROGRESS: - if (state == IPA_USB_SUSPEND_IN_PROGRESS || - state == IPA_USB_SUSPENDED) + if (state == IPA_USB_SUSPENDED) state_legal = true; break; default: @@ -452,7 +417,6 @@ static bool ipa3_usb_check_legal_op(enum ipa3_usb_op op, break; case IPA_USB_OP_DISCONNECT: if (state == IPA_USB_CONNECTED || - state == IPA_USB_SUSPEND_IN_PROGRESS || state == IPA_USB_SUSPENDED || state == IPA_USB_SUSPENDED_NO_RWAKEUP) is_legal = true; @@ -483,7 +447,6 @@ static bool ipa3_usb_check_legal_op(enum ipa3_usb_op op, break; case IPA_USB_OP_RESUME: if (state == IPA_USB_SUSPENDED || - state == IPA_USB_SUSPEND_IN_PROGRESS || state == IPA_USB_SUSPENDED_NO_RWAKEUP) is_legal = true; break; @@ -582,71 +545,6 @@ static void ipa3_usb_wq_dpl_notify_remote_wakeup(struct work_struct *work) ipa3_usb_notify_do(IPA_USB_TRANSPORT_DPL, IPA_USB_REMOTE_WAKEUP); } -static void ipa3_usb_wq_notify_suspend_completed(struct work_struct *work) -{ - ipa3_usb_notify_do(IPA_USB_TRANSPORT_TETH, IPA_USB_SUSPEND_COMPLETED); -} - -static void ipa3_usb_wq_dpl_notify_suspend_completed(struct work_struct *work) -{ - ipa3_usb_notify_do(IPA_USB_TRANSPORT_DPL, IPA_USB_SUSPEND_COMPLETED); -} - -static void ipa3_usb_wq_finish_suspend_work(struct work_struct *work) -{ - struct finish_suspend_work_context *finish_suspend_work_ctx; - unsigned long flags; - int result = -EFAULT; - struct ipa3_usb_transport_type_ctx *tctx; - - mutex_lock(&ipa3_usb_ctx->general_mutex); - IPA_USB_DBG_LOW("entry\n"); - finish_suspend_work_ctx = container_of(work, - struct finish_suspend_work_context, work); - tctx = &ipa3_usb_ctx->ttype_ctx[finish_suspend_work_ctx->ttype]; - - spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags); - if (tctx->state != IPA_USB_SUSPEND_IN_PROGRESS) { - spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); - mutex_unlock(&ipa3_usb_ctx->general_mutex); - return; - } - spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); - - /* Stop DL/DPL channel */ - result = ipa3_stop_gsi_channel(finish_suspend_work_ctx->dl_clnt_hdl); - if (result) { - IPAERR("Error stopping DL/DPL channel: %d, resuming channel\n", - result); - ipa3_xdci_resume(finish_suspend_work_ctx->ul_clnt_hdl, - finish_suspend_work_ctx->dl_clnt_hdl, - IPA3_USB_IS_TTYPE_DPL(finish_suspend_work_ctx->ttype)); - /* Change state back to CONNECTED */ - if (!ipa3_usb_set_state(IPA_USB_CONNECTED, true, - finish_suspend_work_ctx->ttype)) - IPA_USB_ERR("failed to change state to connected\n"); - queue_work(ipa3_usb_ctx->wq, - IPA3_USB_IS_TTYPE_DPL(finish_suspend_work_ctx->ttype) ? - &ipa3_usb_dpl_notify_remote_wakeup_work : - &ipa3_usb_notify_remote_wakeup_work); - mutex_unlock(&ipa3_usb_ctx->general_mutex); - return; - } - - /* Change ipa_usb state to SUSPENDED */ - if (!ipa3_usb_set_state(IPA_USB_SUSPENDED, false, - finish_suspend_work_ctx->ttype)) - IPA_USB_ERR("failed to change state to suspended\n"); - - queue_work(ipa3_usb_ctx->wq, - IPA3_USB_IS_TTYPE_DPL(finish_suspend_work_ctx->ttype) ? - &ipa3_usb_dpl_notify_suspend_completed_work : - &ipa3_usb_notify_suspend_completed_work); - - IPA_USB_DBG_LOW("exit\n"); - mutex_unlock(&ipa3_usb_ctx->general_mutex); -} - static int ipa3_usb_cons_request_resource_cb_do( enum ipa3_usb_transport_type ttype, struct work_struct *remote_wakeup_work) @@ -674,17 +572,6 @@ static int ipa3_usb_cons_request_resource_cb_do( else result = -EINPROGRESS; break; - case IPA_USB_SUSPEND_IN_PROGRESS: - /* - * This case happens due to suspend interrupt. - * CONS is granted - */ - if (!rm_ctx->cons_requested) { - rm_ctx->cons_requested = true; - queue_work(ipa3_usb_ctx->wq, remote_wakeup_work); - } - result = 0; - break; case IPA_USB_SUSPENDED: if (!rm_ctx->cons_requested) { rm_ctx->cons_requested = true; @@ -727,15 +614,10 @@ static int ipa3_usb_cons_release_resource_cb_do( ipa3_usb_state_to_string( ipa3_usb_ctx->ttype_ctx[ttype].state)); switch (ipa3_usb_ctx->ttype_ctx[ttype].state) { - case IPA_USB_SUSPEND_IN_PROGRESS: + case IPA_USB_SUSPENDED: /* Proceed with the suspend if no DL/DPL data */ if (rm_ctx->cons_requested) rm_ctx->cons_requested_released = true; - else { - queue_work(ipa3_usb_ctx->wq, - &ipa3_usb_ctx->ttype_ctx[ttype]. - finish_suspend_work.work); - } break; case IPA_USB_SUSPEND_REQUESTED: if (rm_ctx->cons_requested) @@ -2331,8 +2213,7 @@ int ipa_usb_xdci_disconnect(u32 ul_clnt_hdl, u32 dl_clnt_hdl, spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags); orig_state = ipa3_usb_ctx->ttype_ctx[ttype].state; if (!IPA3_USB_IS_TTYPE_DPL(ttype)) { - if (orig_state != IPA_USB_SUSPEND_IN_PROGRESS && - orig_state != IPA_USB_SUSPENDED) { + if (orig_state != IPA_USB_SUSPENDED) { spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); /* Stop UL channel */ @@ -2360,8 +2241,7 @@ int ipa_usb_xdci_disconnect(u32 ul_clnt_hdl, u32 dl_clnt_hdl, if (result) goto bad_params; - if (orig_state != IPA_USB_SUSPEND_IN_PROGRESS && - orig_state != IPA_USB_SUSPENDED) { + if (orig_state != IPA_USB_SUSPENDED) { result = ipa3_usb_release_prod(ttype); if (result) { IPA_USB_ERR("failed to release PROD.\n"); @@ -2567,7 +2447,6 @@ int ipa_usb_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, { int result = 0; unsigned long flags; - enum ipa3_usb_cons_state curr_cons_state; enum ipa3_usb_transport_type ttype; mutex_lock(&ipa3_usb_ctx->general_mutex); @@ -2622,49 +2501,20 @@ int ipa_usb_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, goto release_prod_fail; } + /* Check if DL/DPL data pending */ spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags); - curr_cons_state = ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_state; - spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); - if (curr_cons_state == IPA_USB_CONS_GRANTED) { - /* Change state to SUSPEND_IN_PROGRESS */ - if (!ipa3_usb_set_state(IPA_USB_SUSPEND_IN_PROGRESS, - false, ttype)) - IPA_USB_ERR("fail set state to suspend_in_progress\n"); - - /* Check if DL/DPL data pending */ - spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags); - if (ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_requested) { - IPA_USB_DBG( - "DL/DPL data pending, invoke remote wakeup\n"); - queue_work(ipa3_usb_ctx->wq, - IPA3_USB_IS_TTYPE_DPL(ttype) ? - &ipa3_usb_dpl_notify_remote_wakeup_work : - &ipa3_usb_notify_remote_wakeup_work); - } - spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); + if (ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_state == + IPA_USB_CONS_GRANTED && + ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_requested) { - ipa3_usb_ctx->ttype_ctx[ttype].finish_suspend_work.ttype = - ttype; - ipa3_usb_ctx->ttype_ctx[ttype].finish_suspend_work.dl_clnt_hdl = - dl_clnt_hdl; - ipa3_usb_ctx->ttype_ctx[ttype].finish_suspend_work.ul_clnt_hdl = - ul_clnt_hdl; - INIT_WORK(&ipa3_usb_ctx->ttype_ctx[ttype]. - finish_suspend_work.work, - ipa3_usb_wq_finish_suspend_work); - - result = -EINPROGRESS; - IPA_USB_DBG("exit with suspend_in_progress\n"); - goto bad_params; + IPA_USB_DBG("DL/DPL data pending, invoke remote wakeup\n"); + queue_work(ipa3_usb_ctx->wq, + IPA3_USB_IS_TTYPE_DPL(ttype) ? + &ipa3_usb_dpl_notify_remote_wakeup_work : + &ipa3_usb_notify_remote_wakeup_work); } + spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); - /* Stop DL channel */ - result = ipa3_stop_gsi_channel(dl_clnt_hdl); - if (result) { - IPAERR("Error stopping DL/DPL channel: %d\n", result); - result = -EFAULT; - goto release_prod_fail; - } /* Change state to SUSPENDED */ if (!ipa3_usb_set_state(IPA_USB_SUSPENDED, false, ttype)) IPA_USB_ERR("failed to change state to suspended\n"); @@ -2823,13 +2673,11 @@ int ipa_usb_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, } } - if (prev_state != IPA_USB_SUSPEND_IN_PROGRESS) { - /* Start DL/DPL channel */ - result = ipa3_start_gsi_channel(dl_clnt_hdl); - if (result) { - IPA_USB_ERR("failed to start DL/DPL channel.\n"); - goto start_dl_fail; - } + /* Start DL/DPL channel */ + result = ipa3_start_gsi_channel(dl_clnt_hdl); + if (result) { + IPA_USB_ERR("failed to start DL/DPL channel.\n"); + goto start_dl_fail; } /* Change state to CONNECTED */ @@ -2844,12 +2692,10 @@ int ipa_usb_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, return 0; state_change_connected_fail: - if (prev_state != IPA_USB_SUSPEND_IN_PROGRESS) { - result = ipa3_stop_gsi_channel(dl_clnt_hdl); - if (result) - IPA_USB_ERR("Error stopping DL/DPL channel: %d\n", - result); - } + result = ipa3_stop_gsi_channel(dl_clnt_hdl); + if (result) + IPA_USB_ERR("Error stopping DL/DPL channel: %d\n", + result); start_dl_fail: if (!IPA3_USB_IS_TTYPE_DPL(ttype)) { result = ipa3_stop_gsi_channel(ul_clnt_hdl); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index 519d2a36d70ab..2478baff7ccdd 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -2127,6 +2127,14 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, goto unsuspend_dl_and_exit; } + /* Stop DL channel */ + result = ipa3_stop_gsi_channel(dl_clnt_hdl); + if (result) { + IPAERR("Error stopping DL/DPL channel: %d\n", result); + result = -EFAULT; + goto unsuspend_dl_and_exit; + } + /* STOP UL channel */ if (!is_dpl) { source_pipe_bitmask = 1 << ipa3_get_ep_mapping(ul_ep->client); @@ -2136,7 +2144,7 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, if (result) { IPAERR("Error stopping UL channel: result = %d\n", result); - goto unsuspend_dl_and_exit; + goto start_dl_and_exit; } } @@ -2145,6 +2153,8 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, IPADBG("exit\n"); return 0; +start_dl_and_exit: + gsi_start_channel(dl_ep->gsi_chan_hdl); unsuspend_dl_and_exit: /* Unsuspend the DL EP */ memset(&ep_cfg_ctrl, 0 , sizeof(struct ipa_ep_cfg_ctrl)); @@ -2193,7 +2203,8 @@ int ipa3_start_gsi_channel(u32 clnt_hdl) int ipa3_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool is_dpl) { - struct ipa3_ep_context *ul_ep, *dl_ep; + struct ipa3_ep_context *ul_ep = NULL; + struct ipa3_ep_context *dl_ep = NULL; enum gsi_status gsi_res; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; @@ -2218,6 +2229,11 @@ int ipa3_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool is_dpl) ep_cfg_ctrl.ipa_ep_suspend = false; ipa3_cfg_ep_ctrl(dl_clnt_hdl, &ep_cfg_ctrl); + /* Start DL channel */ + gsi_res = gsi_start_channel(dl_ep->gsi_chan_hdl); + if (gsi_res != GSI_STATUS_SUCCESS) + IPAERR("Error starting DL channel: %d\n", gsi_res); + /* Start UL channel */ if (!is_dpl) { gsi_res = gsi_start_channel(ul_ep->gsi_chan_hdl); From 19442416c14565bfd1623d94220c5fe156d1b32c Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Tue, 8 May 2018 15:22:34 +0530 Subject: [PATCH 462/508] usb: gadget: Send BRK signal to host on flow disable ioctl Currently in u_data_bridge driver, we are not handling the TIOCM_CTS signal generated by SIO_IOCTL_INBOUND_FLOW IOCTL. Hence we are not able to send BRK signal to the host and it keeps sending data leading to data loss. Fix this by handling TIOCM_CTS in the driver. Change-Id: If8e4774e3e0772cb7189f3400d7e53e258b7d5a3 Signed-off-by: Ajay Agarwal --- drivers/usb/gadget/function/u_data_bridge.c | 17 ++++++++++++++++- drivers/usb/gadget/function/u_smd.c | 6 ++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/function/u_data_bridge.c b/drivers/usb/gadget/function/u_data_bridge.c index 39eae3f0f0c71..ad2fb8d424d13 100644 --- a/drivers/usb/gadget/function/u_data_bridge.c +++ b/drivers/usb/gadget/function/u_data_bridge.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2013-2018, The Linux Foundation. All rights reserved. * Linux Foundation chooses to take subject only to the GPLv2 license terms, * and distributes only under these terms. * @@ -636,6 +636,9 @@ static int gbridge_port_tiocmget(struct gbridge_port *port) if (gser->serial_state & TIOCM_DSR) result |= TIOCM_DSR; + + if (gser->serial_state & TIOCM_CTS) + result |= TIOCM_CTS; fail: spin_unlock_irqrestore(&port->port_lock, flags); return result; @@ -689,6 +692,18 @@ static int gbridge_port_tiocmset(struct gbridge_port *port, gser->serial_state |= TIOCM_DSR; if (clear & TIOCM_DSR) gser->serial_state &= ~TIOCM_DSR; + if (set & TIOCM_CTS) { + if (gser->send_break) { + gser->serial_state |= TIOCM_CTS; + status = gser->send_break(gser, 0); + } + } + if (clear & TIOCM_CTS) { + if (gser->send_break) { + gser->serial_state &= ~TIOCM_CTS; + status = gser->send_break(gser, 1); + } + } fail: spin_unlock_irqrestore(&port->port_lock, flags); return status; diff --git a/drivers/usb/gadget/function/u_smd.c b/drivers/usb/gadget/function/u_smd.c index 3efaaf27f6364..18b71ffd00457 100644 --- a/drivers/usb/gadget/function/u_smd.c +++ b/drivers/usb/gadget/function/u_smd.c @@ -1,7 +1,7 @@ /* * u_smd.c - utilities for USB gadget serial over smd * - * Copyright (c) 2011, 2013-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2013-2018, The Linux Foundation. All rights reserved. * * This code also borrows from drivers/usb/gadget/u_serial.c, which is * Copyright (C) 2000 - 2003 Al Borchers (alborchers@steinerpoint.com) @@ -495,7 +495,7 @@ static unsigned int convert_uart_sigs_to_acm(unsigned uart_sig) unsigned int acm_sig = 0; /* should this needs to be in calling functions ??? */ - uart_sig &= (TIOCM_RI | TIOCM_CD | TIOCM_DSR); + uart_sig &= (TIOCM_RI | TIOCM_CD | TIOCM_DSR | TIOCM_CTS); if (uart_sig & TIOCM_RI) acm_sig |= SMD_ACM_CTRL_RI; @@ -503,6 +503,8 @@ static unsigned int convert_uart_sigs_to_acm(unsigned uart_sig) acm_sig |= SMD_ACM_CTRL_DCD; if (uart_sig & TIOCM_DSR) acm_sig |= SMD_ACM_CTRL_DSR; + if (uart_sig & TIOCM_CTS) + acm_sig |= SMD_ACM_CTRL_BRK; return acm_sig; } From 64bf6b859ffed7ddb450e6b3a8d45fe45b3c9cfb Mon Sep 17 00:00:00 2001 From: Venkataraman Nerellapalli Date: Wed, 23 May 2018 13:01:08 +0530 Subject: [PATCH 463/508] ARM: dts: msm: Add WCD9326 support for apq8009 som platform Add external codec-WCD9326 support for apq8009 som platform Move all common nodes to dtsi file. Change-Id: I3931df7d870fd0bc5cf6216484ac079ac9d6297d Signed-off-by: c_vnerel --- arch/arm/boot/dts/qcom/Makefile | 1 + arch/arm/boot/dts/qcom/apq8009-dragon.dts | 99 +--------------- arch/arm/boot/dts/qcom/apq8009-dragon.dtsi | 110 ++++++++++++++++++ .../dts/qcom/apq8009-ext-codec-dragon.dts | 23 ++++ 4 files changed, 136 insertions(+), 97 deletions(-) create mode 100644 arch/arm/boot/dts/qcom/apq8009-dragon.dtsi create mode 100644 arch/arm/boot/dts/qcom/apq8009-ext-codec-dragon.dts diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index 0ee9e79bf3e8c..b716b521c5934 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -352,6 +352,7 @@ dtb-$(CONFIG_ARCH_MSM8909) += msm8909-pm8916-mtp.dtb \ msm8909-1gb-rcm.dtb \ msm8909-pm8916-1gb-rcm.dtb \ msm8909-1gb-cdp.dtb \ + apq8009-ext-codec-dragon.dtb \ apq8009-dragon.dtb ifeq ($(CONFIG_ARM64),y) diff --git a/arch/arm/boot/dts/qcom/apq8009-dragon.dts b/arch/arm/boot/dts/qcom/apq8009-dragon.dts index 439e461bdd2c7..0c57c3638c5b9 100644 --- a/arch/arm/boot/dts/qcom/apq8009-dragon.dts +++ b/arch/arm/boot/dts/qcom/apq8009-dragon.dts @@ -13,106 +13,11 @@ /dts-v1/; -#include "msm8909-mtp.dtsi" -#include "msm8909-pm8916.dtsi" -#include "msm8909-pm8916-mtp.dtsi" -#include "apq8009-audio-external_codec.dtsi" +#include "apq8009-dragon.dtsi" / { model = "Qualcomm Technologies, Inc. APQ8009 Dragon Board"; compatible = "qcom,apq8009-mtp", "qcom,apq8009", "qcom,mtp"; qcom,msm-id = <265 2>; - qcom,board-id= <32 0x0>; -}; - -&soc { - ext-codec { - qcom,msm-mbhc-hphl-swh = <0>; - qcom,audio-routing = - "AIF4 VI", "MCLK", - "RX_BIAS", "MCLK", - "MADINPUT", "MCLK", - "AMIC2", "MIC BIAS2", - "MIC BIAS2", "Headset Mic", - "DMIC0", "MIC BIAS1", - "MIC BIAS1", "Digital Mic0", - "DMIC1", "MIC BIAS1", - "MIC BIAS1", "Digital Mic1", - "DMIC2", "MIC BIAS3", - "MIC BIAS3", "Digital Mic2", - "DMIC3", "MIC BIAS3", - "MIC BIAS3", "Digital Mic3", - "SpkrLeft IN", "SPK1 OUT", - "SpkrRight IN", "SPK2 OUT"; - }; - - sound-9335 { - status = "disabled"; - }; - - i2c@78b8000 { - wcd9xxx_codec@d { - status = "disabled"; - }; - }; - - vph_pwr_vreg: vph_pwr_vreg { - compatible = "regulator-fixed"; - status = "ok"; - regulator-name = "vph_pwr"; - regulator-always-on; - }; - - mdss_mdp: qcom,mdss_mdp@1a00000 { - status = "disabled"; - }; -}; - -&sdhc_2 { - status = "disabled"; -}; - -&usb_otg { - interrupts = <0 134 0>,<0 140 0>,<0 136 0>; - interrupt-names = "core_irq", "async_irq", "phy_irq"; - qcom,hsusb-otg-mode = <3>; - qcom,switch-vbus-w-id; - vbus_otg-supply = <&vph_pwr_vreg>; -}; - -&external_image_mem { - reg = <0x0 0x87a00000 0x0 0x0600000>; -}; - -&modem_adsp_mem { - reg = <0x0 0x88000000 0x0 0x01e00000>; -}; - -&peripheral_mem { - reg = <0x0 0x89e00000 0x0 0x0700000>; -}; - -&i2c_4 { - smb1360_otg_supply: smb1360-chg-fg@14 { - compatible = "qcom,smb1360-chg-fg"; - reg = <0x14>; - interrupt-parent = <&msm_gpio>; - interrupts = <58 8>; - pinctrl-names = "default"; - pinctrl-0 = <&smb_int_default>; - qcom,charging-disabled; - qcom,empty-soc-disabled; - qcom,chg-inhibit-disabled; - qcom,float-voltage-mv = <4200>; - qcom,iterm-ma = <200>; - qcom,recharge-thresh-mv = <100>; - qcom,thermal-mitigation = <1500 700 600 0>; - regulator-name = "smb1360_otg_vreg"; - status= "disabled"; - }; -}; - -&pm8916_bms { - status = "ok"; - qcom,disable-bms; + qcom,board-id= <0x00010020 0>; }; diff --git a/arch/arm/boot/dts/qcom/apq8009-dragon.dtsi b/arch/arm/boot/dts/qcom/apq8009-dragon.dtsi new file mode 100644 index 0000000000000..9e11c1fa860f0 --- /dev/null +++ b/arch/arm/boot/dts/qcom/apq8009-dragon.dtsi @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#include "msm8909-mtp.dtsi" +#include "msm8909-pm8916.dtsi" +#include "msm8909-pm8916-mtp.dtsi" +#include "apq8009-audio-external_codec.dtsi" + +&soc { + ext-codec { + qcom,msm-mbhc-hphl-swh = <0>; + qcom,audio-routing = + "AIF4 VI", "MCLK", + "RX_BIAS", "MCLK", + "MADINPUT", "MCLK", + "AMIC2", "MIC BIAS2", + "MIC BIAS2", "Headset Mic", + "DMIC0", "MIC BIAS1", + "MIC BIAS1", "Digital Mic0", + "DMIC1", "MIC BIAS1", + "MIC BIAS1", "Digital Mic1", + "DMIC2", "MIC BIAS3", + "MIC BIAS3", "Digital Mic2", + "DMIC3", "MIC BIAS3", + "MIC BIAS3", "Digital Mic3", + "SpkrLeft IN", "SPK1 OUT", + "SpkrRight IN", "SPK2 OUT"; + }; + + sound-9335 { + status = "disabled"; + }; + + i2c@78b8000 { + wcd9xxx_codec@d { + status = "disabled"; + }; + }; + + vph_pwr_vreg: vph_pwr_vreg { + compatible = "regulator-fixed"; + status = "ok"; + regulator-name = "vph_pwr"; + regulator-always-on; + }; + + mdss_mdp: qcom,mdss_mdp@1a00000 { + status = "disabled"; + }; +}; + +&sdhc_2 { + status = "disabled"; +}; + +&usb_otg { + interrupts = <0 134 0>,<0 140 0>,<0 136 0>; + interrupt-names = "core_irq", "async_irq", "phy_irq"; + qcom,hsusb-otg-mode = <3>; + qcom,switch-vbus-w-id; + vbus_otg-supply = <&vph_pwr_vreg>; +}; + +&external_image_mem { + reg = <0x0 0x87a00000 0x0 0x0600000>; +}; + +&modem_adsp_mem { + reg = <0x0 0x88000000 0x0 0x01e00000>; +}; + +&peripheral_mem { + reg = <0x0 0x89e00000 0x0 0x0700000>; +}; + +&i2c_4 { + smb1360_otg_supply: smb1360-chg-fg@14 { + compatible = "qcom,smb1360-chg-fg"; + reg = <0x14>; + interrupt-parent = <&msm_gpio>; + interrupts = <58 8>; + pinctrl-names = "default"; + pinctrl-0 = <&smb_int_default>; + qcom,charging-disabled; + qcom,empty-soc-disabled; + qcom,chg-inhibit-disabled; + qcom,float-voltage-mv = <4200>; + qcom,iterm-ma = <200>; + qcom,recharge-thresh-mv = <100>; + qcom,thermal-mitigation = <1500 700 600 0>; + regulator-name = "smb1360_otg_vreg"; + status= "disabled"; + }; +}; + +&pm8916_bms { + status = "ok"; + qcom,disable-bms; +}; diff --git a/arch/arm/boot/dts/qcom/apq8009-ext-codec-dragon.dts b/arch/arm/boot/dts/qcom/apq8009-ext-codec-dragon.dts new file mode 100644 index 0000000000000..f474ac181868d --- /dev/null +++ b/arch/arm/boot/dts/qcom/apq8009-ext-codec-dragon.dts @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "apq8009-dragon.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. APQ8009 + Ext Codec Dragon Board"; + compatible = "qcom,apq8009-mtp", "qcom,apq8009", "qcom,mtp"; + qcom,msm-id = <265 2>; + qcom,board-id= <0x00010120 0>; +}; From 17a1765f691440bbe68c10ffac2b404d86b677b1 Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Wed, 2 May 2018 17:13:41 +0530 Subject: [PATCH 464/508] defconfig: msm: Enable secure touch for MSM8909 devices Enable secure touch feature for MSM8909 devices. Change-Id: Ibdfa10f16f67881c016eea1b5841654d44b0c0fd Signed-off-by: Shantanu Jain --- arch/arm/configs/msm8909-perf_defconfig | 1 + arch/arm/configs/msm8909_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/msm8909-perf_defconfig b/arch/arm/configs/msm8909-perf_defconfig index 1526257a88894..1327a340ec74f 100644 --- a/arch/arm/configs/msm8909-perf_defconfig +++ b/arch/arm/configs/msm8909-perf_defconfig @@ -295,6 +295,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21=y CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y CONFIG_TOUCHSCREEN_ATMEL_MXT=y CONFIG_TOUCHSCREEN_FT5X06_GESTURE=y +CONFIG_SECURE_TOUCH=y CONFIG_TOUCHSCREEN_GEN_VKEYS=y CONFIG_TOUCHSCREEN_FT5X06=y CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y diff --git a/arch/arm/configs/msm8909_defconfig b/arch/arm/configs/msm8909_defconfig index 68ef75ef979d0..7a3fd881ff660 100644 --- a/arch/arm/configs/msm8909_defconfig +++ b/arch/arm/configs/msm8909_defconfig @@ -300,6 +300,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21=y CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y CONFIG_TOUCHSCREEN_ATMEL_MXT=y CONFIG_TOUCHSCREEN_FT5X06_GESTURE=y +CONFIG_SECURE_TOUCH=y CONFIG_TOUCHSCREEN_GEN_VKEYS=y CONFIG_TOUCHSCREEN_FT5X06=y CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y From f493383c69e67f8e93cbe8b0b742d18b2fae1ec1 Mon Sep 17 00:00:00 2001 From: Hardik Arya Date: Fri, 6 Apr 2018 15:10:36 +0530 Subject: [PATCH 465/508] diag: Validate query dci event and log mask size properly Currently there is possibility of out-of-bound read due to incorrect validation of received dci event and log mask for query. The patch update the validation for the same. Change-Id: I4266eb0f69fdbfa48c5aacc17744dec83995e9e6 Signed-off-by: Hardik Arya --- drivers/char/diag/diag_dci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index 4988b2fa37584..e195d9d0931cf 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -656,7 +656,7 @@ int diag_dci_query_log_mask(struct diag_dci_client_tbl *entry, byte_mask = 0x01 << (item_num % 8); offset = equip_id * 514; - if (offset + byte_index > DCI_LOG_MASK_SIZE) { + if (offset + byte_index >= DCI_LOG_MASK_SIZE) { pr_err("diag: In %s, invalid offset: %d, log_code: %d, byte_index: %d\n", __func__, offset, log_code, byte_index); return 0; @@ -683,7 +683,7 @@ int diag_dci_query_event_mask(struct diag_dci_client_tbl *entry, bit_index = event_id % 8; byte_mask = 0x1 << bit_index; - if (byte_index > DCI_EVENT_MASK_SIZE) { + if (byte_index >= DCI_EVENT_MASK_SIZE) { pr_err("diag: In %s, invalid, event_id: %d, byte_index: %d\n", __func__, event_id, byte_index); return 0; From 16c0698bfc82226fefe6b488d278af1c902fde4f Mon Sep 17 00:00:00 2001 From: Devi Sandeep Endluri V V Date: Wed, 9 May 2018 01:58:49 +0530 Subject: [PATCH 466/508] xt_quota2: Send netlink event on quota reach, without fail. When e->quota and skb->len are equal, then e->quota will be set to 0, but kernel uevent will not be triggered. Send netlink event if quota is reduced exactly to 0. Change-Id: I934229ad46349fccab0fb0b1c0ddfafce2b95935 Signed-off-by: Devi Sandeep Endluri V V --- net/netfilter/xt_quota2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/netfilter/xt_quota2.c b/net/netfilter/xt_quota2.c index 0fe5e43eab556..b4e6abe60c9e8 100644 --- a/net/netfilter/xt_quota2.c +++ b/net/netfilter/xt_quota2.c @@ -300,6 +300,10 @@ quota_mt2(const struct sk_buff *skb, struct xt_action_param *par) if (!(q->flags & XT_QUOTA_NO_CHANGE)) e->quota -= (q->flags & XT_QUOTA_PACKET) ? 1 : skb->len; ret = !ret; + /* Send kernel uevent if quota is 0 */ + if (e->quota == 0) { + quota2_log(par->in, par->out, e, q->name); + } } else { /* We are transitioning, log that fact. */ if (e->quota) { From f1778462ac5ad6fbaa50341aa4d557931a24df2e Mon Sep 17 00:00:00 2001 From: Pratham Pratap Date: Tue, 13 Mar 2018 15:17:51 +0530 Subject: [PATCH 467/508] usb: dwc3: Enable evicting endpoint cache after flow control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In 3.00a and 3.20a synopsys release a performance enhancemnet was done to keep the Non Stream capable bulk IN endpoint in cache after flow control. This enhancement causes host mode concurrency issue in which xhci command timeout is happening when mutliple mass storage devices is connected to the device using HUB and simultaneous file transfers are happening to mass storage devices. This failure is caused because if one endpoint flow controlled, other endpoints will not be serviced right. This change sets EnableEpCacheEvict bit which will disable the enhancement. Change-Id: Iafb72f75b81b1bcbe8c5e38ebd6fe40905670e7a Signed-off-by: Pratham Pratap --- drivers/usb/dwc3/core.c | 11 +++++++++++ drivers/usb/dwc3/core.h | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 670cbd0f37bf6..a924711b73d26 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -567,6 +567,17 @@ int dwc3_core_init(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); } + /* + * Enable evicting endpoint cache after flow control for bulk + * endpoints for dwc3 core version 3.00a and 3.20a + */ + if (dwc->revision == DWC3_REVISION_300A || + dwc->revision == DWC3_REVISION_320A) { + reg = dwc3_readl(dwc->regs, DWC3_GUCTL2); + reg |= DWC3_GUCTL2_ENABLE_EP_CACHE_EVICT; + dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); + } + return 0; err2: diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 851fb04986008..df3922feabf81 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -108,6 +108,7 @@ #define DWC3_GPRTBIMAP_HS1 0xc184 #define DWC3_GPRTBIMAP_FS0 0xc188 #define DWC3_GPRTBIMAP_FS1 0xc18c +#define DWC3_GUCTL2 0xc19c #define DWC3_GUSB2PHYCFG(n) (0xc200 + (n * 0x04)) #define DWC3_GUSB2I2CCTL(n) (0xc240 + (n * 0x04)) @@ -194,6 +195,9 @@ /* Global Debug LTSSM Register */ #define DWC3_GDBGLTSSM_LINKSTATE_MASK (0xF << 22) +/* Global User Control 2 Register */ +#define DWC3_GUCTL2_ENABLE_EP_CACHE_EVICT (1 << 12) + /* Global USB2 PHY Configuration Register */ #define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) #define DWC3_GUSB2PHYCFG_ENBLSLPM (1 << 8) @@ -909,6 +913,9 @@ struct dwc3 { #define DWC3_REVISION_260A 0x5533260a #define DWC3_REVISION_270A 0x5533270a #define DWC3_REVISION_280A 0x5533280a +#define DWC3_REVISION_300A 0x5533300a +#define DWC3_REVISION_310A 0x5533310a +#define DWC3_REVISION_320A 0x5533320a enum dwc3_ep0_next ep0_next_event; enum dwc3_ep0_state ep0state; From 8138089f53fd2c0da77de9dddb11350c75a9828e Mon Sep 17 00:00:00 2001 From: Krishna Manikandan Date: Tue, 12 Jun 2018 16:53:10 +0530 Subject: [PATCH 468/508] msm: mdss: Signal the fences when there is a dma_done timeout During kickoff before proceeding with the configuration for the current frame, we wait for the previous dma_done to complete. If there is a dma_done timeout during the kickoff, we are not proceeding with the current request and hence the fences should be signaled before returning. Change-Id: Icb3314cb186a6adbf2fae2489338bfa8e4122f46 Signed-off-by: Krishna Manikandan --- drivers/video/msm/mdss/mdp3_ctrl.c | 7 +++++-- drivers/video/msm/mdss/mdp3_dma.c | 2 +- drivers/video/msm/mdss/mdp3_ppp.c | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c index 127ed385f333c..21295a4b9bddb 100644 --- a/drivers/video/msm/mdss/mdp3_ctrl.c +++ b/drivers/video/msm/mdss/mdp3_ctrl.c @@ -1556,8 +1556,8 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd, mdp3_session->intf); if (!rc && !mdp3_session->first_commit) { pr_err("dma done timedout\n"); - mutex_unlock(&mdp3_session->lock); - return -ETIMEDOUT; + rc = -ETIMEDOUT; + goto frame_done; } } @@ -1618,6 +1618,7 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd, atomic_read(&mdp3_session->secure_display)); } +frame_done: /* This is for the previous frame */ if (rc < 0) { mdp3_ctrl_notify(mdp3_session, @@ -1771,6 +1772,8 @@ static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd) mdp3_session->intf); if (!rc && !mdp3_session->first_commit) { pr_err("dma done timedout\n"); + mdp3_ctrl_notify(mdp3_session, + MDP_NOTIFY_FRAME_TIMEOUT); goto pan_error; } } diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c index 57f7eb7ee2460..ebf3414ccf139 100644 --- a/drivers/video/msm/mdss/mdp3_dma.c +++ b/drivers/video/msm/mdss/mdp3_dma.c @@ -724,7 +724,7 @@ return rc; static int mdp3_wait_for_dma_comp(struct mdp3_dma *dma, struct mdp3_intf *intf) { int vsync_status; - int rc = 0; + int rc = 1; int retry_count = 2; if (intf->active) { diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c index 3d3745498fc8b..d66e41592d233 100644 --- a/drivers/video/msm/mdss/mdp3_ppp.c +++ b/drivers/video/msm/mdss/mdp3_ppp.c @@ -1692,6 +1692,7 @@ int mdp3_ppp_parse_req(void __user *p, mdp3_session->intf); if (!rc) { pr_err("secure dma done not completed\n"); + rc = -ETIMEDOUT; goto parse_err_2; } mdp3_session->transition_state = SECURE_TO_NONSECURE; From 505fb3b200be086de1d0e9730cf078c6f1e02075 Mon Sep 17 00:00:00 2001 From: Tom Marshall Date: Wed, 25 Jan 2017 18:01:03 +0100 Subject: [PATCH 469/508] kernel: Only expose su when daemon is running It has been claimed that the PG implementation of 'su' has security vulnerabilities even when disabled. Unfortunately, the people that find these vulnerabilities often like to keep them private so they can profit from exploits while leaving users exposed to malicious hackers. In order to reduce the attack surface for vulnerabilites, it is therefore necessary to make 'su' completely inaccessible when it is not in use (except by the root and system users). Change-Id: I79716c72f74d0b7af34ec3a8054896c6559a181d --- fs/exec.c | 5 +++++ fs/namei.c | 8 ++++++++ fs/readdir.c | 15 +++++++++++++++ include/linux/dcache.h | 7 +++++++ include/linux/fs.h | 1 + include/linux/sched.h | 8 ++++++++ include/linux/uidgid.h | 3 +++ kernel/exit.c | 4 ++++ kernel/fork.c | 2 ++ kernel/sched/core.c | 32 ++++++++++++++++++++++++++++++++ 10 files changed, 85 insertions(+) diff --git a/fs/exec.c b/fs/exec.c index a552a192d0e3d..07313df4d1a54 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1564,6 +1564,11 @@ static int do_execve_common(struct filename *filename, if (retval < 0) goto out; + if (d_is_su(file->f_dentry) && capable(CAP_SYS_ADMIN)) { + current->flags |= PF_SU; + su_exec(); + } + /* execve succeeded */ current->fs->in_exec = 0; current->in_execve = 0; diff --git a/fs/namei.c b/fs/namei.c index 0b0d7939f4b2c..f476c12e5287c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2025,6 +2025,14 @@ static int path_lookupat(int dfd, const char *name, } } + if (!err) { + struct super_block *sb = nd->inode->i_sb; + if (sb->s_flags & MS_RDONLY) { + if (d_is_su(nd->path.dentry) && !su_visible()) + err = -ENOENT; + } + } + out: if (base) fput(base); diff --git a/fs/readdir.c b/fs/readdir.c index 33fd92208cb75..b3089a19613bc 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -39,6 +39,7 @@ int iterate_dir(struct file *file, struct dir_context *ctx) res = -ENOENT; if (!IS_DEADDIR(inode)) { ctx->pos = file->f_pos; + ctx->romnt = (inode->i_sb->s_flags & MS_RDONLY); res = file->f_op->iterate(file, ctx); file->f_pos = ctx->pos; fsnotify_access(file); @@ -50,6 +51,14 @@ int iterate_dir(struct file *file, struct dir_context *ctx) } EXPORT_SYMBOL(iterate_dir); +static bool hide_name(const char *name, int namlen) +{ + if (namlen == 2 && !memcmp(name, "su", 2)) + if (!su_visible()) + return true; + return false; +} + /* * Traditional linux readdir() handling.. * @@ -88,6 +97,8 @@ static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset buf->result = -EOVERFLOW; return -EOVERFLOW; } + if (hide_name(name, namlen) && buf->ctx.romnt) + return 0; buf->result++; dirent = buf->dirent; if (!access_ok(VERIFY_WRITE, dirent, @@ -165,6 +176,8 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset, buf->error = -EOVERFLOW; return -EOVERFLOW; } + if (hide_name(name, namlen) && buf->ctx.romnt) + return 0; dirent = buf->previous; if (dirent) { if (__put_user(offset, &dirent->d_off)) @@ -243,6 +256,8 @@ static int filldir64(void * __buf, const char * name, int namlen, loff_t offset, buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) return -EINVAL; + if (hide_name(name, namlen) && buf->ctx.romnt) + return 0; dirent = buf->previous; if (dirent) { if (__put_user(offset, &dirent->d_off)) diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 331c1d6950318..0fd2e4885c735 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -467,6 +467,13 @@ static inline bool d_is_positive(const struct dentry *dentry) return !d_is_negative(dentry); } +static inline bool d_is_su(const struct dentry *dentry) +{ + return dentry && + dentry->d_name.len == 2 && + !memcmp(dentry->d_name.name, "su", 2); +} + extern int sysctl_vfs_cache_pressure; static inline unsigned long vfs_pressure_ratio(unsigned long val) diff --git a/include/linux/fs.h b/include/linux/fs.h index b54ad2f2a14ce..47abbbd2c2436 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1498,6 +1498,7 @@ typedef int (*filldir_t)(void *, const char *, int, loff_t, u64, unsigned); struct dir_context { const filldir_t actor; loff_t pos; + bool romnt; }; struct block_device_operations; diff --git a/include/linux/sched.h b/include/linux/sched.h index 0f1b34e18ec0a..9127a410be4b0 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -61,6 +61,12 @@ struct sched_param { #include +int su_instances(void); +bool su_running(void); +bool su_visible(void); +void su_exec(void); +void su_exit(void); + #define SCHED_ATTR_SIZE_VER0 48 /* sizeof first published struct */ /* @@ -2091,6 +2097,8 @@ static inline void sched_set_io_is_busy(int val) {}; #define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezable */ #define PF_SUSPEND_TASK 0x80000000 /* this thread called freeze_processes and should not be frozen */ +#define PF_SU 0x10000000 /* task is su */ + /* * Only the _current_ task can read/write to tsk->flags, but other * tasks can access tsk->flags in readonly mode for example diff --git a/include/linux/uidgid.h b/include/linux/uidgid.h index 2d1f9b627f919..ef26f3f1fdaf5 100644 --- a/include/linux/uidgid.h +++ b/include/linux/uidgid.h @@ -42,6 +42,9 @@ static inline gid_t __kgid_val(kgid_t gid) #define GLOBAL_ROOT_UID KUIDT_INIT(0) #define GLOBAL_ROOT_GID KGIDT_INIT(0) +#define GLOBAL_SYSTEM_UID KUIDT_INIT(1000) +#define GLOBAL_SYSTEM_GID KGIDT_INIT(1000) + #define INVALID_UID KUIDT_INIT(-1) #define INVALID_GID KGIDT_INIT(-1) diff --git a/kernel/exit.c b/kernel/exit.c index b6142e0a1561c..e5b6b2a7b5f4b 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -736,6 +736,10 @@ void do_exit(long code) sched_exit(tsk); + if (tsk->flags & PF_SU) { + su_exit(); + } + /* * tsk->flags are checked in the futex code to protect against * an exiting task cleaning up the robust pi futexes. diff --git a/kernel/fork.c b/kernel/fork.c index 0843f7b5a70a9..d2830db302752 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -340,6 +340,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) if (err) goto free_ti; + tsk->flags &= ~PF_SU; + tsk->stack = ti; #ifdef CONFIG_SECCOMP /* diff --git a/kernel/sched/core.c b/kernel/sched/core.c index ad4c6d269a4bd..dafb7995cd050 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -96,6 +96,38 @@ #define CREATE_TRACE_POINTS #include +static atomic_t __su_instances; + +int su_instances(void) +{ + return atomic_read(&__su_instances); +} + +bool su_running(void) +{ + return su_instances() > 0; +} + +bool su_visible(void) +{ + kuid_t uid = current_uid(); + if (su_running()) + return true; + if (uid_eq(uid, GLOBAL_ROOT_UID) || uid_eq(uid, GLOBAL_SYSTEM_UID)) + return true; + return false; +} + +void su_exec(void) +{ + atomic_inc(&__su_instances); +} + +void su_exit(void) +{ + atomic_dec(&__su_instances); +} + const char *task_event_names[] = {"PUT_PREV_TASK", "PICK_NEXT_TASK", "TASK_WAKE", "TASK_MIGRATE", "TASK_UPDATE", "IRQ_UPDATE"}; From f0d24b83fec6a86c352a7ffd1966b3e657defa05 Mon Sep 17 00:00:00 2001 From: Tom Marshall Date: Thu, 18 May 2017 23:50:22 +0000 Subject: [PATCH 470/508] kernel: Fix potential refcount leak in su check Change-Id: I8d2c8bed65a01eb0928308df638a04449a5bd881 --- fs/namei.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index f476c12e5287c..38de06f671b40 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2028,8 +2028,10 @@ static int path_lookupat(int dfd, const char *name, if (!err) { struct super_block *sb = nd->inode->i_sb; if (sb->s_flags & MS_RDONLY) { - if (d_is_su(nd->path.dentry) && !su_visible()) + if (d_is_su(nd->path.dentry) && !su_visible()) { + path_put(&nd->path); err = -ENOENT; + } } } From c066dc986473cf098ffdc9ad20b9fe4bcc622264 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Tue, 25 Jul 2017 22:22:45 +0200 Subject: [PATCH 471/508] fs/exec: fix use after free in execve "file" can be already freed if bprm->file is NULL after exec_binprm() return. binfmt_script will do exactly that for example. If the VM reuses the file after fput run(), this will result in a use ater free. So obtain d_is_su before exec_binprm() runs. This should explain this crash: [25333.009554] Unable to handle kernel NULL pointer dereference at virtual address 00000185 [..] [25333.009918] [2: am:21861] PC is at do_execve+0x354/0x474 Change-Id: I2a8a814d1c0aa75625be83cb30432cf13f1a0681 Signed-off-by: Kevin F. Haggerty --- fs/exec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/exec.c b/fs/exec.c index 07313df4d1a54..a79780618697d 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1485,6 +1485,7 @@ static int do_execve_common(struct filename *filename, struct file *file; struct files_struct *displaced; int retval; + bool is_su; if (IS_ERR(filename)) return PTR_ERR(filename); @@ -1560,11 +1561,14 @@ static int do_execve_common(struct filename *filename, if (retval < 0) goto out; + /* exec_binprm can release file and it may be freed */ + is_su = d_is_su(file->f_dentry); + retval = exec_binprm(bprm); if (retval < 0) goto out; - if (d_is_su(file->f_dentry) && capable(CAP_SYS_ADMIN)) { + if (is_su && capable(CAP_SYS_ADMIN)) { current->flags |= PF_SU; su_exec(); } From 8f3ed14d3039140d07de97ae94351bf37419ebdd Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Wed, 11 Apr 2018 16:19:10 -0700 Subject: [PATCH 472/508] ANDROID: sdcardfs: Check for private data earlier When an sdcardfs dentry is destroyed, it may not yet have its fsdata initialized. It must be checked before we try to access the paths in its private data. Additionally, when cleaning up the superblock after a failure, we don't have our sb private data, so check for that case. Bug: 77923821 Change-Id: I89caf6e121ed86480b42024664453fe0031bbcf3 Signed-off-by: Daniel Rosenberg --- fs/sdcardfs/dentry.c | 2 ++ fs/sdcardfs/lookup.c | 2 -- fs/sdcardfs/main.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/sdcardfs/dentry.c b/fs/sdcardfs/dentry.c index 0466b55fa25ee..8c265eade67a0 100644 --- a/fs/sdcardfs/dentry.c +++ b/fs/sdcardfs/dentry.c @@ -131,6 +131,8 @@ static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags) static void sdcardfs_d_release(struct dentry *dentry) { + if (!dentry || !dentry->d_fsdata) + return; /* release and reset the lower paths */ if (has_graft_path(dentry)) sdcardfs_put_reset_orig_path(dentry); diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c index ace852390d2a3..3395371c72cae 100644 --- a/fs/sdcardfs/lookup.c +++ b/fs/sdcardfs/lookup.c @@ -41,8 +41,6 @@ void sdcardfs_destroy_dentry_cache(void) void free_dentry_private_data(struct dentry *dentry) { - if (!dentry || !dentry->d_fsdata) - return; kmem_cache_free(sdcardfs_dentry_cachep, dentry->d_fsdata); dentry->d_fsdata = NULL; } diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c index 1c00f0fc0ca52..4f784e09df870 100644 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -422,7 +422,7 @@ void sdcardfs_kill_sb(struct super_block *sb) { struct sdcardfs_sb_info *sbi; - if (sb->s_magic == SDCARDFS_SUPER_MAGIC) { + if (sb->s_magic == SDCARDFS_SUPER_MAGIC && sb->s_fs_info) { sbi = SDCARDFS_SB(sb); mutex_lock(&sdcardfs_super_list_lock); list_del(&sbi->list); From 8b7cff1d60ffd1b914fc1fd56db0f1b274bed1fd Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Wed, 11 Apr 2018 16:24:51 -0700 Subject: [PATCH 473/508] ANDROID: sdcardfs: d_make_root calls iput d_make_root will call iput on failure, so we shouldn't try to do that ourselves. Signed-off-by: Daniel Rosenberg Bug: 77923821 Change-Id: I1abb4afb0f894ab917b7c6be8c833676f436beb7 --- fs/sdcardfs/main.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c index 4f784e09df870..cd6b6e2029131 100644 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -316,7 +316,7 @@ static int sdcardfs_read_super(struct vfsmount *mnt, struct super_block *sb, sb->s_root = d_make_root(inode); if (!sb->s_root) { err = -ENOMEM; - goto out_iput; + goto out_sput; } d_set_d_op(sb->s_root, &sdcardfs_ci_dops); @@ -361,8 +361,6 @@ static int sdcardfs_read_super(struct vfsmount *mnt, struct super_block *sb, /* no longer needed: free_dentry_private_data(sb->s_root); */ out_freeroot: dput(sb->s_root); -out_iput: - iput(inode); out_sput: /* drop refs we took earlier */ atomic_dec(&lower_sb->s_active); From a5f572c0f42f9ee3249b8b1925dded900a9009d3 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Wed, 11 Apr 2018 18:39:43 -0700 Subject: [PATCH 474/508] ANDROID: sdcardfs: Set s_root to NULL after putting Signed-off-by: Daniel Rosenberg Bug: 77923821 Change-Id: I1705bfd146009561d2d1da5f0e6a342ec6932a1c --- fs/sdcardfs/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c index cd6b6e2029131..a2c906eafdfa0 100644 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -361,6 +361,7 @@ static int sdcardfs_read_super(struct vfsmount *mnt, struct super_block *sb, /* no longer needed: free_dentry_private_data(sb->s_root); */ out_freeroot: dput(sb->s_root); + sb->s_root = NULL; out_sput: /* drop refs we took earlier */ atomic_dec(&lower_sb->s_active); From bae5c5445dc67df66e5249c0e830ac649282c285 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Tue, 24 Apr 2018 18:06:56 -0700 Subject: [PATCH 475/508] ANDROID: sdcardfs: Don't d_drop in d_revalidate After d_revalidate returns 0, the vfs will call d_invalidate, which will call d_drop itself, along with other cleanup. Bug: 78262592 Change-Id: Idbb30e008c05d62edf2217679cb6a5517d8d1a2c Signed-off-by: Daniel Rosenberg --- fs/sdcardfs/dentry.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fs/sdcardfs/dentry.c b/fs/sdcardfs/dentry.c index 8c265eade67a0..532757974388b 100644 --- a/fs/sdcardfs/dentry.c +++ b/fs/sdcardfs/dentry.c @@ -51,7 +51,6 @@ static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags) * whether the base obbpath has been changed or not */ if (is_obbpath_invalid(dentry)) { - d_drop(dentry); return 0; } @@ -65,7 +64,6 @@ static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags) if ((lower_dentry->d_flags & DCACHE_OP_REVALIDATE)) { err = lower_dentry->d_op->d_revalidate(lower_dentry, flags); if (err == 0) { - d_drop(dentry); goto out; } } @@ -73,14 +71,12 @@ static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags) spin_lock(&lower_dentry->d_lock); if (d_unhashed(lower_dentry)) { spin_unlock(&lower_dentry->d_lock); - d_drop(dentry); err = 0; goto out; } spin_unlock(&lower_dentry->d_lock); if (parent_lower_dentry != lower_cur_parent_dentry) { - d_drop(dentry); err = 0; goto out; } @@ -94,7 +90,6 @@ static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags) } if (!qstr_case_eq(&dentry->d_name, &lower_dentry->d_name)) { - __d_drop(dentry); err = 0; } @@ -113,7 +108,6 @@ static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags) if (inode) { data = top_data_get(SDCARDFS_I(inode)); if (!data || data->abandoned) { - d_drop(dentry); err = 0; } if (data) From 4a12e29dee379a5f9f1e1cbbe176e086e531c2cd Mon Sep 17 00:00:00 2001 From: Lianjun Huang Date: Sat, 16 Jun 2018 22:59:46 +0800 Subject: [PATCH 476/508] ANDROID: sdcardfs: fix potential crash when reserved_mb is not zero sdcardfs_mkdir() calls check_min_free_space(). When reserved_mb is not zero, a negative dentry will be passed to ext4_statfs() at last and ext4_statfs() will crash. The parent dentry is positive. So we use the parent dentry to check free space. Change-Id: I80ab9623fe59ba911f4cc9f0e029a1c6f7ee421b Signed-off-by: Lianjun Huang --- fs/sdcardfs/inode.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 6f04a18ad503f..d92462ecd1f43 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -270,6 +270,7 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode struct dentry *lower_dentry; struct vfsmount *lower_mnt; struct dentry *lower_parent_dentry = NULL; + struct dentry *parent_dentry = NULL; struct path lower_path; struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); const struct cred *saved_cred = NULL; @@ -289,11 +290,14 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir)); /* check disk space */ - if (!check_min_free_space(dentry, 0, 1)) { + parent_dentry = dget_parent(dentry); + if (!check_min_free_space(parent_dentry, 0, 1)) { pr_err("sdcardfs: No minimum free space.\n"); err = -ENOSPC; + dput(parent_dentry); goto out_revert; } + dput(parent_dentry); /* the lower_dentry is negative here */ sdcardfs_get_lower_path(dentry, &lower_path); From 8c46941e8feecf3af9cb363f6f3c17b87ead4663 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 13 Jan 2017 13:12:29 -0800 Subject: [PATCH 477/508] f2fs: do not preallocate blocks which has wrong buffer Sheng Yong reports needless preallocation if write(small_buffer, large_size) is called. In that case, f2fs preallocates large_size, but vfs returns early due to small_buffer size. Let's detect it before preallocation phase in f2fs. Change-Id: I932f9d442c3bad6576ab67ddca47d500edf905fe Reported-by: Sheng Yong Signed-off-by: Jaegeuk Kim Git-Repo: https://android.googlesource.com/kernel/common/ Git-Commit: b6453fcb2fe808424106cebad7bb6c4a2bd95f00 Signed-off-by: Sahitya Tummala --- fs/f2fs/data.c | 6 +++++- fs/f2fs/f2fs.h | 1 + fs/f2fs/file.c | 10 +++++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 8a26a069d3c97..8b652880cfc4d 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -840,6 +840,9 @@ int f2fs_preallocate_blocks(struct inode *inode, loff_t pos, return err; } + if (is_inode_flag_set(inode, FI_NO_PREALLOC)) + return 0; + map.m_lblk = F2FS_BLK_ALIGN(pos); map.m_len = F2FS_BYTES_TO_BLK(pos + count); if (map.m_len > map.m_lblk) @@ -1865,7 +1868,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, * we already allocated all the blocks, so we don't need to get * the block addresses when there is no need to fill the page. */ - if (!f2fs_has_inline_data(inode) && len == PAGE_SIZE) + if (!f2fs_has_inline_data(inode) && len == PAGE_SIZE && + !is_inode_flag_set(inode, FI_NO_PREALLOC)) return 0; if (f2fs_has_inline_data(inode) || diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index e40eb01797e80..f399a99b27fad 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2200,6 +2200,7 @@ enum { FI_INLINE_DOTS, /* indicate inline dot dentries */ FI_DO_DEFRAG, /* indicate defragment is running */ FI_DIRTY_FILE, /* indicate regular/symlink has dirty pages */ + FI_NO_PREALLOC, /* indicate skipped preallocated blocks */ FI_HOT_DATA, /* indicate file is hot */ FI_EXTRA_ATTR, /* indicate file has extra attribute */ FI_PROJ_INHERIT, /* indicate file inherits projectid */ diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 002a54ba80018..130a74d29073d 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -2536,15 +2537,22 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) inode_lock(inode); ret = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); if (!ret) { - int err = f2fs_preallocate_blocks(inode, pos, count, + int err; + + if (iov_iter_fault_in_readable(from, iov_iter_count(from))) + set_inode_flag(inode, FI_NO_PREALLOC); + + err = f2fs_preallocate_blocks(inode, pos, count, file->f_flags & O_DIRECT); if (err) { + clear_inode_flag(inode, FI_NO_PREALLOC); inode_unlock(inode); return err; } blk_start_plug(&plug); ret = __generic_file_write_iter(iocb, from); blk_finish_plug(&plug); + clear_inode_flag(inode, FI_NO_PREALLOC); if (ret > 0) f2fs_update_iostat(F2FS_I_SB(inode), APP_WRITE_IO, ret); From 2c9626ac38694d12c70ad80dfaf04e8cb159e45c Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 22 Jun 2017 12:14:40 -0700 Subject: [PATCH 478/508] fscrypt: updates on 4.15-rc4 Cherry-picked from origin/upstream-f2fs-stable-linux-3.18.y: f73a1ef7d7b5 fscrypt: resolve some cherry-pick bugs b9dad2c0a3c4 fscrypt: move to generic async completion fb0097fefa09 crypto: introduce crypto wait for async op 89682e2b3157 fscrypt: lock mutex before checking for bounce page pool 16e02cc0ccae fscrypt: new helper function - fscrypt_prepare_setattr() 03c10b3f3762 fscrypt: new helper function - fscrypt_prepare_lookup() 95b5e0ec575d fscrypt: new helper function - fscrypt_prepare_rename() 1b4465a3a7a8 fscrypt: new helper function - fscrypt_prepare_link() 25c01cbc07c1 fscrypt: new helper function - fscrypt_file_open() 63aa02394821 fscrypt: new helper function - fscrypt_require_key() 7fa20786d09a fscrypt: remove unneeded empty fscrypt_operations structs 7319c5ee6274 fscrypt: remove ->is_encrypted() d824e3a72ddc fscrypt: switch from ->is_encrypted() to IS_ENCRYPTED() 12f169fd2683 fs, fscrypt: add an S_ENCRYPTED inode flag 0f461ce2849e fscrypt: clean up include file mess db32474d104c fscrypt: fix dereference of NULL user_key_payload 12cff7c68247 fscrypt: make ->dummy_context() return bool Change-Id: Iaf8f427637741c70f529a7571f9376695d441f1a Signed-off-by: Jaegeuk Kim --- crypto/api.c | 13 ++ fs/crypto/Makefile | 2 +- fs/crypto/crypto.c | 30 +--- fs/crypto/fname.c | 39 +---- fs/crypto/fscrypt_private.h | 12 +- fs/crypto/hooks.c | 112 ++++++++++++ fs/crypto/keyinfo.c | 23 +-- fs/crypto/policy.c | 6 +- fs/f2fs/f2fs.h | 9 +- fs/f2fs/inode.c | 5 +- fs/f2fs/super.c | 7 +- include/linux/crypto.h | 40 +++++ include/linux/fs.h | 2 + include/linux/fscrypt.h | 290 ++++++++++++++++++++++++++++++++ include/linux/fscrypt_common.h | 149 ---------------- include/linux/fscrypt_notsupp.h | 39 ++++- include/linux/fscrypt_supp.h | 17 +- 17 files changed, 539 insertions(+), 256 deletions(-) create mode 100644 fs/crypto/hooks.c create mode 100644 include/linux/fscrypt.h delete mode 100644 include/linux/fscrypt_common.h diff --git a/crypto/api.c b/crypto/api.c index 7db2e89a31141..937f74878a6e5 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "internal.h" LIST_HEAD(crypto_alg_list); @@ -601,5 +602,17 @@ int crypto_has_alg(const char *name, u32 type, u32 mask) } EXPORT_SYMBOL_GPL(crypto_has_alg); +void crypto_req_done(struct crypto_async_request *req, int err) +{ + struct crypto_wait *wait = req->data; + + if (err == -EINPROGRESS) + return; + + wait->err = err; + complete(&wait->completion); +} +EXPORT_SYMBOL_GPL(crypto_req_done); + MODULE_DESCRIPTION("Cryptographic core API"); MODULE_LICENSE("GPL"); diff --git a/fs/crypto/Makefile b/fs/crypto/Makefile index 9f6607f17b53b..cb496989a6b69 100644 --- a/fs/crypto/Makefile +++ b/fs/crypto/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_FS_ENCRYPTION) += fscrypto.o -fscrypto-y := crypto.o fname.o policy.o keyinfo.o +fscrypto-y := crypto.o fname.o hooks.o keyinfo.o policy.o fscrypto-$(CONFIG_BLOCK) += bio.o diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 5182c8e07ebab..b744b40286f85 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -126,21 +126,6 @@ struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode, gfp_t gfp_flags) } EXPORT_SYMBOL(fscrypt_get_ctx); -/** - * page_crypt_complete() - completion callback for page crypto - * @req: The asynchronous cipher request context - * @res: The result of the cipher operation - */ -static void page_crypt_complete(struct crypto_async_request *req, int res) -{ - struct fscrypt_completion_result *ecr = req->data; - - if (res == -EINPROGRESS) - return; - ecr->res = res; - complete(&ecr->completion); -} - int fscrypt_do_page_crypto(const struct inode *inode, fscrypt_direction_t rw, u64 lblk_num, struct page *src_page, struct page *dest_page, unsigned int len, @@ -151,7 +136,7 @@ int fscrypt_do_page_crypto(const struct inode *inode, fscrypt_direction_t rw, u8 padding[FS_IV_SIZE - sizeof(__le64)]; } iv; struct ablkcipher_request *req = NULL; - DECLARE_FS_COMPLETION_RESULT(ecr); + DECLARE_CRYPTO_WAIT(wait); struct scatterlist dst, src; struct fscrypt_info *ci = inode->i_crypt_info; struct crypto_ablkcipher *tfm = ci->ci_ctfm; @@ -179,7 +164,7 @@ int fscrypt_do_page_crypto(const struct inode *inode, fscrypt_direction_t rw, ablkcipher_request_set_callback( req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, - page_crypt_complete, &ecr); + crypto_req_done, &wait); sg_init_table(&dst, 1); sg_set_page(&dst, dest_page, len, offs); @@ -187,14 +172,9 @@ int fscrypt_do_page_crypto(const struct inode *inode, fscrypt_direction_t rw, sg_set_page(&src, src_page, len, offs); ablkcipher_request_set_crypt(req, &src, &dst, len, &iv); if (rw == FS_DECRYPT) - res = crypto_ablkcipher_decrypt(req); + res = crypto_wait_req(crypto_ablkcipher_decrypt(req), &wait); else - res = crypto_ablkcipher_encrypt(req); - if (res == -EINPROGRESS || res == -EBUSY) { - BUG_ON(req->base.data != &ecr); - wait_for_completion(&ecr.completion); - res = ecr.res; - } + res = crypto_wait_req(crypto_ablkcipher_encrypt(req), &wait); ablkcipher_request_free(req); if (res) { printk_ratelimited(KERN_ERR @@ -340,7 +320,7 @@ static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags) return -ECHILD; dir = dget_parent(dentry); - if (!d_inode(dir)->i_sb->s_cop->is_encrypted(d_inode(dir))) { + if (!IS_ENCRYPTED(d_inode(dir))) { dput(dir); return 0; } diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index cef1d3e8c783a..690426912d0ed 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -14,21 +14,6 @@ #include #include "fscrypt_private.h" -/** - * fname_crypt_complete() - completion callback for filename crypto - * @req: The asynchronous cipher request context - * @res: The result of the cipher operation - */ -static void fname_crypt_complete(struct crypto_async_request *req, int res) -{ - struct fscrypt_completion_result *ecr = req->data; - - if (res == -EINPROGRESS) - return; - ecr->res = res; - complete(&ecr->completion); -} - /** * fname_encrypt() - encrypt a filename * @@ -40,7 +25,7 @@ static int fname_encrypt(struct inode *inode, const struct qstr *iname, struct fscrypt_str *oname) { struct ablkcipher_request *req = NULL; - DECLARE_FS_COMPLETION_RESULT(ecr); + DECLARE_CRYPTO_WAIT(wait); struct fscrypt_info *ci = inode->i_crypt_info; struct crypto_ablkcipher *tfm = ci->ci_ctfm; int res = 0; @@ -76,17 +61,12 @@ static int fname_encrypt(struct inode *inode, } ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, - fname_crypt_complete, &ecr); + crypto_req_done, &wait); sg_init_one(&sg, oname->name, cryptlen); ablkcipher_request_set_crypt(req, &sg, &sg, cryptlen, iv); /* Do the encryption */ - res = crypto_ablkcipher_encrypt(req); - if (res == -EINPROGRESS || res == -EBUSY) { - /* Request is being completed asynchronously; wait for it */ - wait_for_completion(&ecr.completion); - res = ecr.res; - } + res = crypto_wait_req(crypto_ablkcipher_encrypt(req), &wait); ablkcipher_request_free(req); if (res < 0) { printk_ratelimited(KERN_ERR @@ -110,7 +90,7 @@ static int fname_decrypt(struct inode *inode, struct fscrypt_str *oname) { struct ablkcipher_request *req = NULL; - DECLARE_FS_COMPLETION_RESULT(ecr); + DECLARE_CRYPTO_WAIT(wait); struct scatterlist src_sg, dst_sg; struct fscrypt_info *ci = inode->i_crypt_info; struct crypto_ablkcipher *tfm = ci->ci_ctfm; @@ -131,7 +111,7 @@ static int fname_decrypt(struct inode *inode, } ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, - fname_crypt_complete, &ecr); + crypto_req_done, &wait); /* Initialize IV */ memset(iv, 0, FS_CRYPTO_BLOCK_SIZE); @@ -140,11 +120,7 @@ static int fname_decrypt(struct inode *inode, sg_init_one(&src_sg, iname->name, iname->len); sg_init_one(&dst_sg, oname->name, oname->len); ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv); - res = crypto_ablkcipher_decrypt(req); - if (res == -EINPROGRESS || res == -EBUSY) { - wait_for_completion(&ecr.completion); - res = ecr.res; - } + res = crypto_wait_req(crypto_ablkcipher_decrypt(req), &wait); ablkcipher_request_free(req); if (res < 0) { printk_ratelimited(KERN_ERR @@ -382,8 +358,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, memset(fname, 0, sizeof(struct fscrypt_name)); fname->usr_fname = iname; - if (!dir->i_sb->s_cop->is_encrypted(dir) || - fscrypt_is_dot_dotdot(iname)) { + if (!IS_ENCRYPTED(dir) || fscrypt_is_dot_dotdot(iname)) { fname->disk_name.name = (unsigned char *)iname->name; fname->disk_name.len = iname->len; return 0; diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 4e4f60f134b44..acb0ccc656985 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -11,7 +11,8 @@ #ifndef _FSCRYPT_PRIVATE_H #define _FSCRYPT_PRIVATE_H -#include +#define __FS_HAS_ENCRYPTION 1 +#include #include /* Encryption parameters */ @@ -69,15 +70,6 @@ typedef enum { #define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001 #define FS_CTX_HAS_BOUNCE_BUFFER_FL 0x00000002 -struct fscrypt_completion_result { - struct completion completion; - int res; -}; - -#define DECLARE_FS_COMPLETION_RESULT(ecr) \ - struct fscrypt_completion_result ecr = { \ - COMPLETION_INITIALIZER_ONSTACK((ecr).completion), 0 } - static inline void inode_lock(struct inode *inode) { mutex_lock(&inode->i_mutex); diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c new file mode 100644 index 0000000000000..396561212dbd5 --- /dev/null +++ b/fs/crypto/hooks.c @@ -0,0 +1,112 @@ +/* + * fs/crypto/hooks.c + * + * Encryption hooks for higher-level filesystem operations. + */ + +#include +#include "fscrypt_private.h" + +/** + * fscrypt_file_open - prepare to open a possibly-encrypted regular file + * @inode: the inode being opened + * @filp: the struct file being set up + * + * Currently, an encrypted regular file can only be opened if its encryption key + * is available; access to the raw encrypted contents is not supported. + * Therefore, we first set up the inode's encryption key (if not already done) + * and return an error if it's unavailable. + * + * We also verify that if the parent directory (from the path via which the file + * is being opened) is encrypted, then the inode being opened uses the same + * encryption policy. This is needed as part of the enforcement that all files + * in an encrypted directory tree use the same encryption policy, as a + * protection against certain types of offline attacks. Note that this check is + * needed even when opening an *unencrypted* file, since it's forbidden to have + * an unencrypted file in an encrypted directory. + * + * Return: 0 on success, -ENOKEY if the key is missing, or another -errno code + */ +int fscrypt_file_open(struct inode *inode, struct file *filp) +{ + int err; + struct dentry *dir; + + err = fscrypt_require_key(inode); + if (err) + return err; + + dir = dget_parent(filp->f_path.dentry); + if (IS_ENCRYPTED(d_inode(dir)) && + !fscrypt_has_permitted_context(d_inode(dir), inode)) { + pr_warn_ratelimited("fscrypt: inconsistent encryption contexts: %lu/%lu", + d_inode(dir)->i_ino, inode->i_ino); + err = -EPERM; + } + dput(dir); + return err; +} +EXPORT_SYMBOL_GPL(fscrypt_file_open); + +int __fscrypt_prepare_link(struct inode *inode, struct inode *dir) +{ + int err; + + err = fscrypt_require_key(dir); + if (err) + return err; + + if (!fscrypt_has_permitted_context(dir, inode)) + return -EPERM; + + return 0; +} +EXPORT_SYMBOL_GPL(__fscrypt_prepare_link); + +int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + unsigned int flags) +{ + int err; + + err = fscrypt_require_key(old_dir); + if (err) + return err; + + err = fscrypt_require_key(new_dir); + if (err) + return err; + + if (old_dir != new_dir) { + if (IS_ENCRYPTED(new_dir) && + !fscrypt_has_permitted_context(new_dir, + d_inode(old_dentry))) + return -EPERM; + + if ((flags & RENAME_EXCHANGE) && + IS_ENCRYPTED(old_dir) && + !fscrypt_has_permitted_context(old_dir, + d_inode(new_dentry))) + return -EPERM; + } + return 0; +} +EXPORT_SYMBOL_GPL(__fscrypt_prepare_rename); + +int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry) +{ + int err = fscrypt_get_encryption_info(dir); + + if (err) + return err; + + if (fscrypt_has_encryption_key(dir)) { + spin_lock(&dentry->d_lock); + dentry->d_flags |= DCACHE_ENCRYPTED_WITH_KEY; + spin_unlock(&dentry->d_lock); + } + + d_set_d_op(dentry, &fscrypt_d_ops); + return 0; +} +EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup); diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index be24dc401ac93..2affed8466e8c 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -17,17 +17,6 @@ static struct crypto_shash *essiv_hash_tfm; -static void derive_crypt_complete(struct crypto_async_request *req, int rc) -{ - struct fscrypt_completion_result *ecr = req->data; - - if (rc == -EINPROGRESS) - return; - - ecr->res = rc; - complete(&ecr->completion); -} - /** * derive_key_aes() - Derive a key using AES-128-ECB * @deriving_key: Encryption key used for derivation. @@ -42,7 +31,7 @@ static int derive_key_aes(u8 deriving_key[FS_AES_128_ECB_KEY_SIZE], { int res = 0; struct ablkcipher_request *req = NULL; - DECLARE_FS_COMPLETION_RESULT(ecr); + DECLARE_CRYPTO_WAIT(wait); struct scatterlist src_sg, dst_sg; struct crypto_ablkcipher *tfm = crypto_alloc_ablkcipher("ecb(aes)", 0, 0); @@ -59,7 +48,7 @@ static int derive_key_aes(u8 deriving_key[FS_AES_128_ECB_KEY_SIZE], } ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, - derive_crypt_complete, &ecr); + crypto_req_done, &wait); res = crypto_ablkcipher_setkey(tfm, deriving_key, FS_AES_128_ECB_KEY_SIZE); if (res < 0) @@ -69,11 +58,7 @@ static int derive_key_aes(u8 deriving_key[FS_AES_128_ECB_KEY_SIZE], sg_init_one(&dst_sg, derived_raw_key, source_key->size); ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, source_key->size, NULL); - res = crypto_ablkcipher_encrypt(req); - if (res == -EINPROGRESS || res == -EBUSY) { - wait_for_completion(&ecr.completion); - res = ecr.res; - } + res = crypto_wait_req(crypto_ablkcipher_encrypt(req), &wait); out: if (req) ablkcipher_request_free(req); @@ -281,7 +266,7 @@ int fscrypt_get_encryption_info(struct inode *inode) res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); if (res < 0) { if (!fscrypt_dummy_context_enabled(inode) || - inode->i_sb->s_cop->is_encrypted(inode)) + IS_ENCRYPTED(inode)) return res; /* Fake up a context for an unencrypted directory */ memset(&ctx, 0, sizeof(ctx)); diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index 9914d51dff863..2f2c53f2e1366 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -109,7 +109,7 @@ int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg) struct fscrypt_policy policy; int res; - if (!inode->i_sb->s_cop->is_encrypted(inode)) + if (!IS_ENCRYPTED(inode)) return -ENODATA; res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); @@ -166,11 +166,11 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) return 1; /* No restrictions if the parent directory is unencrypted */ - if (!cops->is_encrypted(parent)) + if (!IS_ENCRYPTED(parent)) return 1; /* Encrypted directories must not contain unencrypted files */ - if (!cops->is_encrypted(child)) + if (!IS_ENCRYPTED(child)) return 0; /* diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index f399a99b27fad..29ac022d3009b 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -23,14 +23,12 @@ #include #include #include -#ifdef CONFIG_F2FS_FS_ENCRYPTION -#include -#else -#include -#endif #include #include +#define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_F2FS_FS_ENCRYPTION) +#include + #ifdef CONFIG_F2FS_CHECK_FS #define f2fs_bug_on(sbi, condition) BUG_ON(condition) #define f2fs_down_write(x, y) down_write_nest_lock(x, y) @@ -3184,6 +3182,7 @@ static inline void f2fs_set_encrypted_inode(struct inode *inode) { #ifdef CONFIG_F2FS_FS_ENCRYPTION file_set_encrypt(inode); + inode->i_flags |= S_ENCRYPTED; #endif } diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 1ae5b61cf2bcd..9eb3cc2486d4c 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -43,8 +43,11 @@ void f2fs_set_inode_flags(struct inode *inode) new_fl |= S_NOATIME; if (flags & FS_DIRSYNC_FL) new_fl |= S_DIRSYNC; + if (f2fs_encrypted_inode(inode)) + new_fl |= S_ENCRYPTED; inode_set_flags(inode, new_fl, - S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC); + S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC| + S_ENCRYPTED); } static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 3c8dc3ec272f8..114ee51b87d75 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1788,14 +1788,9 @@ static const struct fscrypt_operations f2fs_cryptops = { .key_prefix = "f2fs:", .get_context = f2fs_get_context, .set_context = f2fs_set_context, - .is_encrypted = f2fs_encrypted_inode, .empty_dir = f2fs_empty_dir, .max_namelen = f2fs_max_namelen, }; -#else -static const struct fscrypt_operations f2fs_cryptops = { - .is_encrypted = f2fs_encrypted_inode, -}; #endif static struct inode *f2fs_nfs_get_inode(struct super_block *sb, @@ -2534,7 +2529,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) #endif sb->s_op = &f2fs_sops; +#ifdef CONFIG_F2FS_FS_ENCRYPTION sb->s_cop = &f2fs_cryptops; +#endif sb->s_xattr = f2fs_xattr_handlers; sb->s_export_op = &f2fs_export_ops; sb->s_magic = F2FS_SUPER_MAGIC; diff --git a/include/linux/crypto.h b/include/linux/crypto.h index dc34dfc766b5e..7284dbfcbffde 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -24,6 +24,7 @@ #include #include #include +#include /* * Autoloaded crypto modules should only use a prefixed name to avoid allowing @@ -323,6 +324,45 @@ struct crypto_alg { struct module *cra_module; }; +/* + * A helper struct for waiting for completion of async crypto ops + */ +struct crypto_wait { + struct completion completion; + int err; +}; + +/* + * Macro for declaring a crypto op async wait object on stack + */ +#define DECLARE_CRYPTO_WAIT(_wait) \ + struct crypto_wait _wait = { \ + COMPLETION_INITIALIZER_ONSTACK((_wait).completion), 0 } + +/* + * Async ops completion helper functioons + */ +void crypto_req_done(struct crypto_async_request *req, int err); + +static inline int crypto_wait_req(int err, struct crypto_wait *wait) +{ + switch (err) { + case -EINPROGRESS: + case -EBUSY: + wait_for_completion(&wait->completion); + reinit_completion(&wait->completion); + err = wait->err; + break; + }; + + return err; +} + +static inline void crypto_init_wait(struct crypto_wait *wait) +{ + init_completion(&wait->completion); +} + /* * Algorithm registration interface. */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 47abbbd2c2436..4938894287518 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1645,6 +1645,7 @@ struct super_operations { #define S_IMA 1024 /* Inode has an associated IMA struct */ #define S_AUTOMOUNT 2048 /* Automount/referral quasi-directory */ #define S_NOSEC 4096 /* no suid or xattr security attributes */ +#define S_ENCRYPTED 16384 /* Encrypted file (using fs/crypto/) */ /* * Note that nosuid etc flags are inode-specific: setting some file-system @@ -1682,6 +1683,7 @@ struct super_operations { #define IS_IMA(inode) ((inode)->i_flags & S_IMA) #define IS_AUTOMOUNT(inode) ((inode)->i_flags & S_AUTOMOUNT) #define IS_NOSEC(inode) ((inode)->i_flags & S_NOSEC) +#define IS_ENCRYPTED(inode) ((inode)->i_flags & S_ENCRYPTED) #define IS_WHITEOUT(inode) (S_ISCHR(inode->i_mode) && \ (inode)->i_rdev == WHITEOUT_DEV) diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h new file mode 100644 index 0000000000000..8641e56b8f8a9 --- /dev/null +++ b/include/linux/fscrypt.h @@ -0,0 +1,290 @@ +/* + * fscrypt.h: declarations for per-file encryption + * + * Filesystems that implement per-file encryption include this header + * file with the __FS_HAS_ENCRYPTION set according to whether that filesystem + * is being built with encryption support or not. + * + * Copyright (C) 2015, Google, Inc. + * + * Written by Michael Halcrow, 2015. + * Modified by Jaegeuk Kim, 2015. + */ +#ifndef _LINUX_FSCRYPT_H +#define _LINUX_FSCRYPT_H + +#include +#include +#include +#include +#include +#include +#include + +#define FS_CRYPTO_BLOCK_SIZE 16 + +struct fscrypt_info; + +struct fscrypt_ctx { + union { + struct { + struct page *bounce_page; /* Ciphertext page */ + struct page *control_page; /* Original page */ + } w; + struct { + struct bio *bio; + struct work_struct work; + } r; + struct list_head free_list; /* Free list */ + }; + u8 flags; /* Flags */ +}; + +/** + * For encrypted symlinks, the ciphertext length is stored at the beginning + * of the string in little-endian format. + */ +struct fscrypt_symlink_data { + __le16 len; + char encrypted_path[1]; +} __packed; + +struct fscrypt_str { + unsigned char *name; + u32 len; +}; + +struct fscrypt_name { + const struct qstr *usr_fname; + struct fscrypt_str disk_name; + u32 hash; + u32 minor_hash; + struct fscrypt_str crypto_buf; +}; + +#define FSTR_INIT(n, l) { .name = n, .len = l } +#define FSTR_TO_QSTR(f) QSTR_INIT((f)->name, (f)->len) +#define fname_name(p) ((p)->disk_name.name) +#define fname_len(p) ((p)->disk_name.len) + +/* + * fscrypt superblock flags + */ +#define FS_CFLG_OWN_PAGES (1U << 1) + +/* + * crypto opertions for filesystems + */ +struct fscrypt_operations { + unsigned int flags; + const char *key_prefix; + int (*get_context)(struct inode *, void *, size_t); + int (*set_context)(struct inode *, const void *, size_t, void *); + bool (*dummy_context)(struct inode *); + bool (*empty_dir)(struct inode *); + unsigned (*max_namelen)(struct inode *); +}; + +static inline bool fscrypt_dummy_context_enabled(struct inode *inode) +{ + if (inode->i_sb->s_cop->dummy_context && + inode->i_sb->s_cop->dummy_context(inode)) + return true; + return false; +} + +static inline bool fscrypt_valid_enc_modes(u32 contents_mode, + u32 filenames_mode) +{ + if (contents_mode == FS_ENCRYPTION_MODE_AES_128_CBC && + filenames_mode == FS_ENCRYPTION_MODE_AES_128_CTS) + return true; + + if (contents_mode == FS_ENCRYPTION_MODE_AES_256_XTS && + filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS) + return true; + + return false; +} + +static inline bool fscrypt_is_dot_dotdot(const struct qstr *str) +{ + if (str->len == 1 && str->name[0] == '.') + return true; + + if (str->len == 2 && str->name[0] == '.' && str->name[1] == '.') + return true; + + return false; +} + +#if __FS_HAS_ENCRYPTION + +static inline struct page *fscrypt_control_page(struct page *page) +{ + return ((struct fscrypt_ctx *)page_private(page))->w.control_page; +} + +static inline bool fscrypt_has_encryption_key(const struct inode *inode) +{ + return (inode->i_crypt_info != NULL); +} + +#include + +#else /* !__FS_HAS_ENCRYPTION */ + +static inline struct page *fscrypt_control_page(struct page *page) +{ + WARN_ON_ONCE(1); + return ERR_PTR(-EINVAL); +} + +static inline bool fscrypt_has_encryption_key(const struct inode *inode) +{ + return 0; +} + +#include +#endif /* __FS_HAS_ENCRYPTION */ + +/** + * fscrypt_require_key - require an inode's encryption key + * @inode: the inode we need the key for + * + * If the inode is encrypted, set up its encryption key if not already done. + * Then require that the key be present and return -ENOKEY otherwise. + * + * No locks are needed, and the key will live as long as the struct inode --- so + * it won't go away from under you. + * + * Return: 0 on success, -ENOKEY if the key is missing, or another -errno code + * if a problem occurred while setting up the encryption key. + */ +static inline int fscrypt_require_key(struct inode *inode) +{ + if (IS_ENCRYPTED(inode)) { + int err = fscrypt_get_encryption_info(inode); + + if (err) + return err; + if (!fscrypt_has_encryption_key(inode)) + return -ENOKEY; + } + return 0; +} + +/** + * fscrypt_prepare_link - prepare to link an inode into a possibly-encrypted directory + * @old_dentry: an existing dentry for the inode being linked + * @dir: the target directory + * @dentry: negative dentry for the target filename + * + * A new link can only be added to an encrypted directory if the directory's + * encryption key is available --- since otherwise we'd have no way to encrypt + * the filename. Therefore, we first set up the directory's encryption key (if + * not already done) and return an error if it's unavailable. + * + * We also verify that the link will not violate the constraint that all files + * in an encrypted directory tree use the same encryption policy. + * + * Return: 0 on success, -ENOKEY if the directory's encryption key is missing, + * -EPERM if the link would result in an inconsistent encryption policy, or + * another -errno code. + */ +static inline int fscrypt_prepare_link(struct dentry *old_dentry, + struct inode *dir, + struct dentry *dentry) +{ + if (IS_ENCRYPTED(dir)) + return __fscrypt_prepare_link(d_inode(old_dentry), dir); + return 0; +} + +/** + * fscrypt_prepare_rename - prepare for a rename between possibly-encrypted directories + * @old_dir: source directory + * @old_dentry: dentry for source file + * @new_dir: target directory + * @new_dentry: dentry for target location (may be negative unless exchanging) + * @flags: rename flags (we care at least about %RENAME_EXCHANGE) + * + * Prepare for ->rename() where the source and/or target directories may be + * encrypted. A new link can only be added to an encrypted directory if the + * directory's encryption key is available --- since otherwise we'd have no way + * to encrypt the filename. A rename to an existing name, on the other hand, + * *is* cryptographically possible without the key. However, we take the more + * conservative approach and just forbid all no-key renames. + * + * We also verify that the rename will not violate the constraint that all files + * in an encrypted directory tree use the same encryption policy. + * + * Return: 0 on success, -ENOKEY if an encryption key is missing, -EPERM if the + * rename would cause inconsistent encryption policies, or another -errno code. + */ +static inline int fscrypt_prepare_rename(struct inode *old_dir, + struct dentry *old_dentry, + struct inode *new_dir, + struct dentry *new_dentry, + unsigned int flags) +{ + if (IS_ENCRYPTED(old_dir) || IS_ENCRYPTED(new_dir)) + return __fscrypt_prepare_rename(old_dir, old_dentry, + new_dir, new_dentry, flags); + return 0; +} + +/** + * fscrypt_prepare_lookup - prepare to lookup a name in a possibly-encrypted directory + * @dir: directory being searched + * @dentry: filename being looked up + * @flags: lookup flags + * + * Prepare for ->lookup() in a directory which may be encrypted. Lookups can be + * done with or without the directory's encryption key; without the key, + * filenames are presented in encrypted form. Therefore, we'll try to set up + * the directory's encryption key, but even without it the lookup can continue. + * + * To allow invalidating stale dentries if the directory's encryption key is + * added later, we also install a custom ->d_revalidate() method and use the + * DCACHE_ENCRYPTED_WITH_KEY flag to indicate whether a given dentry is a + * plaintext name (flag set) or a ciphertext name (flag cleared). + * + * Return: 0 on success, -errno if a problem occurred while setting up the + * encryption key + */ +static inline int fscrypt_prepare_lookup(struct inode *dir, + struct dentry *dentry, + unsigned int flags) +{ + if (IS_ENCRYPTED(dir)) + return __fscrypt_prepare_lookup(dir, dentry); + return 0; +} + +/** + * fscrypt_prepare_setattr - prepare to change a possibly-encrypted inode's attributes + * @dentry: dentry through which the inode is being changed + * @attr: attributes to change + * + * Prepare for ->setattr() on a possibly-encrypted inode. On an encrypted file, + * most attribute changes are allowed even without the encryption key. However, + * without the encryption key we do have to forbid truncates. This is needed + * because the size being truncated to may not be a multiple of the filesystem + * block size, and in that case we'd have to decrypt the final block, zero the + * portion past i_size, and re-encrypt it. (We *could* allow truncating to a + * filesystem block boundary, but it's simpler to just forbid all truncates --- + * and we already forbid all other contents modifications without the key.) + * + * Return: 0 on success, -ENOKEY if the key is missing, or another -errno code + * if a problem occurred while setting up the encryption key. + */ +static inline int fscrypt_prepare_setattr(struct dentry *dentry, + struct iattr *attr) +{ + if (attr->ia_valid & ATTR_SIZE) + return fscrypt_require_key(d_inode(dentry)); + return 0; +} + +#endif /* _LINUX_FSCRYPT_H */ diff --git a/include/linux/fscrypt_common.h b/include/linux/fscrypt_common.h deleted file mode 100644 index 768203e248f08..0000000000000 --- a/include/linux/fscrypt_common.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * fscrypt_common.h: common declarations for per-file encryption - * - * Copyright (C) 2015, Google, Inc. - * - * Written by Michael Halcrow, 2015. - * Modified by Jaegeuk Kim, 2015. - */ - -#ifndef _LINUX_FSCRYPT_COMMON_H -#define _LINUX_FSCRYPT_COMMON_H - -#include -#include -#include -#include -#include -#include -#include - -#define FS_CRYPTO_BLOCK_SIZE 16 - -struct fscrypt_info; - -struct fscrypt_ctx { - union { - struct { - struct page *bounce_page; /* Ciphertext page */ - struct page *control_page; /* Original page */ - } w; - struct { - struct bio *bio; - struct work_struct work; - } r; - struct list_head free_list; /* Free list */ - }; - u8 flags; /* Flags */ -}; - -/** - * For encrypted symlinks, the ciphertext length is stored at the beginning - * of the string in little-endian format. - */ -struct fscrypt_symlink_data { - __le16 len; - char encrypted_path[1]; -} __packed; - -/** - * This function is used to calculate the disk space required to - * store a filename of length l in encrypted symlink format. - */ -static inline u32 fscrypt_symlink_data_len(u32 l) -{ - if (l < FS_CRYPTO_BLOCK_SIZE) - l = FS_CRYPTO_BLOCK_SIZE; - return (l + sizeof(struct fscrypt_symlink_data) - 1); -} - -struct fscrypt_str { - unsigned char *name; - u32 len; -}; - -struct fscrypt_name { - const struct qstr *usr_fname; - struct fscrypt_str disk_name; - u32 hash; - u32 minor_hash; - struct fscrypt_str crypto_buf; -}; - -#define FSTR_INIT(n, l) { .name = n, .len = l } -#define FSTR_TO_QSTR(f) QSTR_INIT((f)->name, (f)->len) -#define fname_name(p) ((p)->disk_name.name) -#define fname_len(p) ((p)->disk_name.len) - -/* - * fscrypt superblock flags - */ -#define FS_CFLG_OWN_PAGES (1U << 1) - -/* - * crypto opertions for filesystems - */ -struct fscrypt_operations { - unsigned int flags; - const char *key_prefix; - int (*get_context)(struct inode *, void *, size_t); - int (*set_context)(struct inode *, const void *, size_t, void *); - int (*dummy_context)(struct inode *); - bool (*is_encrypted)(struct inode *); - bool (*empty_dir)(struct inode *); - unsigned (*max_namelen)(struct inode *); -}; - -static inline bool fscrypt_dummy_context_enabled(struct inode *inode) -{ - if (inode->i_sb->s_cop->dummy_context && - inode->i_sb->s_cop->dummy_context(inode)) - return true; - return false; -} - -static inline bool fscrypt_valid_enc_modes(u32 contents_mode, - u32 filenames_mode) -{ - if (contents_mode == FS_ENCRYPTION_MODE_AES_128_CBC && - filenames_mode == FS_ENCRYPTION_MODE_AES_128_CTS) - return true; - - if (contents_mode == FS_ENCRYPTION_MODE_AES_256_XTS && - filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS) - return true; - - return false; -} - -static inline bool fscrypt_is_dot_dotdot(const struct qstr *str) -{ - if (str->len == 1 && str->name[0] == '.') - return true; - - if (str->len == 2 && str->name[0] == '.' && str->name[1] == '.') - return true; - - return false; -} - -static inline struct page *fscrypt_control_page(struct page *page) -{ -#if IS_ENABLED(CONFIG_FS_ENCRYPTION) - return ((struct fscrypt_ctx *)page_private(page))->w.control_page; -#else - WARN_ON_ONCE(1); - return ERR_PTR(-EINVAL); -#endif -} - -static inline int fscrypt_has_encryption_key(const struct inode *inode) -{ -#if IS_ENABLED(CONFIG_FS_ENCRYPTION) - return (inode->i_crypt_info != NULL); -#else - return 0; -#endif -} - -#endif /* _LINUX_FSCRYPT_COMMON_H */ diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h index ec406aed2f2f8..c4c6bf2c390e0 100644 --- a/include/linux/fscrypt_notsupp.h +++ b/include/linux/fscrypt_notsupp.h @@ -3,13 +3,16 @@ * * This stubs out the fscrypt functions for filesystems configured without * encryption support. + * + * Do not include this file directly. Use fscrypt.h instead! */ +#ifndef _LINUX_FSCRYPT_H +#error "Incorrect include of linux/fscrypt_notsupp.h!" +#endif #ifndef _LINUX_FSCRYPT_NOTSUPP_H #define _LINUX_FSCRYPT_NOTSUPP_H -#include - /* crypto.c */ static inline struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode, gfp_t gfp_flags) @@ -97,7 +100,7 @@ static inline int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, int lookup, struct fscrypt_name *fname) { - if (dir->i_sb->s_cop->is_encrypted(dir)) + if (IS_ENCRYPTED(dir)) return -EOPNOTSUPP; memset(fname, 0, sizeof(struct fscrypt_name)); @@ -174,4 +177,34 @@ static inline int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, return -EOPNOTSUPP; } +/* hooks.c */ + +static inline int fscrypt_file_open(struct inode *inode, struct file *filp) +{ + if (IS_ENCRYPTED(inode)) + return -EOPNOTSUPP; + return 0; +} + +static inline int __fscrypt_prepare_link(struct inode *inode, + struct inode *dir) +{ + return -EOPNOTSUPP; +} + +static inline int __fscrypt_prepare_rename(struct inode *old_dir, + struct dentry *old_dentry, + struct inode *new_dir, + struct dentry *new_dentry, + unsigned int flags) +{ + return -EOPNOTSUPP; +} + +static inline int __fscrypt_prepare_lookup(struct inode *dir, + struct dentry *dentry) +{ + return -EOPNOTSUPP; +} + #endif /* _LINUX_FSCRYPT_NOTSUPP_H */ diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h index 6828dc6111fa0..4ccecca367475 100644 --- a/include/linux/fscrypt_supp.h +++ b/include/linux/fscrypt_supp.h @@ -1,14 +1,15 @@ /* * fscrypt_supp.h * - * This is included by filesystems configured with encryption support. + * Do not include this file directly. Use fscrypt.h instead! */ +#ifndef _LINUX_FSCRYPT_H +#error "Incorrect include of linux/fscrypt_supp.h!" +#endif #ifndef _LINUX_FSCRYPT_SUPP_H #define _LINUX_FSCRYPT_SUPP_H -#include - /* crypto.c */ extern struct kmem_cache *fscrypt_info_cachep; extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t); @@ -146,4 +147,14 @@ extern void fscrypt_pullback_bio_page(struct page **, bool); extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t, unsigned int); +/* hooks.c */ +extern int fscrypt_file_open(struct inode *inode, struct file *filp); +extern int __fscrypt_prepare_link(struct inode *inode, struct inode *dir); +extern int __fscrypt_prepare_rename(struct inode *old_dir, + struct dentry *old_dentry, + struct inode *new_dir, + struct dentry *new_dentry, + unsigned int flags); +extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry); + #endif /* _LINUX_FSCRYPT_SUPP_H */ From a7733f4d227d9253cb5c9b4dc294fea1d33dc7e4 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 16 Nov 2017 16:59:14 +0800 Subject: [PATCH 479/508] f2fs: updates on v4.16-rc1 Pull f2fs updates from Jaegeuk Kim: "In this round, we've followed up to support some generic features such as cgroup, block reservation, linking fscrypt_ops, delivering write_hints, and some ioctls. And, we could fix some corner cases in terms of power-cut recovery and subtle deadlocks. Enhancements: - bitmap operations to handle NAT blocks - readahead to improve readdir speed - switch to use fscrypt_* - apply write hints for direct IO - add reserve_root=%u,resuid=%u,resgid=%u to reserve blocks for root/uid/gid - modify b_avail and b_free to consider root reserved blocks - support cgroup writeback - support FIEMAP_FLAG_XATTR for fibmap - add F2FS_IOC_PRECACHE_EXTENTS to pre-cache extents - add F2FS_IOC_{GET/SET}_PIN_FILE to pin LBAs for data blocks - support inode creation time Bug fixs: - sysfile-based quota operations - memory footprint accounting - allow to write data on partial preallocation case - fix deadlock case on fallocate - fix to handle fill_super errors - fix missing inode updates of fsync'ed file - recover renamed file which was fsycn'ed before - drop inmemory pages in corner error case - keep last_disk_size correctly - recover missing i_inline flags during roll-forward Various clean-up patches were added as well" Cherry-pick from origin/upstream-f2fs-stable-linux-3.18.y: b85b2040e29f f2fs: support inode creation time c72ef4727838 f2fs: rebuild sit page from sit info in mem f368156e84cb f2fs: stop issuing discard if fs is readonly be823aa3d5af f2fs: clean up duplicated assignment in init_discard_policy 67ebfab1a0f4 f2fs: use GFP_F2FS_ZERO for cleanup 2ebcc5d82d9a f2fs: allow to recover node blocks given updated checkpoint 2ea7d6f1bf18 f2fs: recover some i_inline flags 2e1f3aa5affb f2fs: correct removexattr behavior for null valued extended attribute c8330bdcc35f f2fs: drop page cache after fs shutdown ef83735b3932 f2fs: stop gc/discard thread after fs shutdown cb472c71d865 f2fs: hanlde error case in f2fs_ioc_shutdown b66b08d969c4 f2fs: split need_inplace_update af69483e9316 f2fs: fix to update last_disk_size correctly dc4b6954c141 f2fs: kill F2FS_INLINE_XATTR_ADDRS for cleanup 13240c90fdcc f2fs: clean up error path of fill_super 2e5c39e53996 f2fs: avoid hungtask when GC encrypted block if io_bits is set a14cced5bf6a f2fs: allow quota to use reserved blocks 859cc83798e0 f2fs: fix to drop all inmem pages correctly 8975d2b938bf f2fs: speed up defragment on sparse file 06e30f6f9cec f2fs: support F2FS_IOC_PRECACHE_EXTENTS f3d5ace5b527 f2fs: add an ioctl to disable GC for specific file 11228b15cfa4 f2fs: prevent newly created inode from being dirtied incorrectly 623e284104f8 f2fs: support FIEMAP_FLAG_XATTR 2075b0e8a63e f2fs: fix to cover f2fs_inline_data_fiemap with inode_lock 0ea602b1ab49 f2fs: check node page again in write end io d503f1e0c9fa f2fs: fix to caclulate required free section correctly e72c42370ccf f2fs: handle newly created page when revoking inmem pages 177018aacbc4 f2fs: add resgid and resuid to reserve root blocks 6ad1915c61d4 f2fs: implement cgroup writeback support 1ee182bcc114 f2fs: remove unused pend_list_tag e732db71ba44 f2fs: avoid high cpu usage in discard thread 647763fa612b f2fs: make local functions static 3f81bf527a5f f2fs: add reserved blocks for root user cb4ea095ee56 f2fs: check segment type in __f2fs_replace_block 2a6f5454a49c f2fs: update inode info to inode page for new file db2e6b82f45d f2fs: show precise # of blocks that user/root can use add96ed3f86b f2fs: clean up unneeded declaration babfbc088938 f2fs: continue to do direct IO if we only preallocate partial blocks f928990854bb f2fs: enable quota at remount from r to w cfee78c6767b f2fs: skip stop_checkpoint for user data writes 29f0297fef9d f2fs: fix missing error number for xattr operation 1e85f5d70912 f2fs: recover directory operations by fsync f1b68a501b21 f2fs: return error during fill_super e913b1903a98 f2fs: fix an error case of missing update inode page 62b6a5f6896a f2fs: fix potential hangtask in f2fs_trace_pid 54c06e52d661 f2fs: no need return value in restore summary process e88ab6696058 f2fs: use unlikely for release case 246018281458 f2fs: don't return value in truncate_data_blocks_range 15f92902926e f2fs: clean up f2fs_map_blocks 8dfee8c44a14 f2fs: clean up hash codes 5d81acf57de6 f2fs: fix error handling in fill_super 3acc2f316ff1 f2fs: spread f2fs_k{m,z}alloc 8c72d9db0e50 f2fs: inject fault to kvmalloc fc42fc2cd84d f2fs: inject fault to kzalloc c821080ddd53 f2fs: remove a redundant conditional expression 612e589b373f f2fs: apply write hints to select the type of segment for direct write 63a9fc8008ed f2fs: switch to fscrypt_prepare_setattr() 16c5bfa10f1f f2fs: switch to fscrypt_prepare_lookup() 5998a21bdab5 f2fs: switch to fscrypt_prepare_rename() dd5ca5fe3666 f2fs: switch to fscrypt_prepare_link() 09c91079d653 f2fs: switch to fscrypt_file_open() 08cae724087a f2fs: remove repeated f2fs_bug_on 7357b4521f50 f2fs: remove an excess variable 6f2915eb151e f2fs: fix lock dependency in between dio_rwsem & i_mmap_sem 8c3b1444df49 f2fs: remove unused parameter 35b94063c4d7 f2fs: still write data if preallocate only partial blocks b6453fcb2fe8 f2fs: do not preallocate blocks which has wrong buffer bee58ad4c31c f2fs: introduce sysfs readdir_ra to readahead inode block in readdir 5b10dbdef98c f2fs: fix concurrent problem for updating free bitmap 2638ff752042 f2fs: remove unneeded memory footprint accounting c569c0b1124b f2fs: no need to read nat block if nat_block_bitmap is set 5321a23c0c19 f2fs: reserve nid resource for quota sysfile Change-Id: I5f95446f4d51232e82f48b716e5796d871e2d9ee Signed-off-by: Jaegeuk Kim --- Documentation/ABI/testing/sysfs-fs-f2fs | 6 + fs/f2fs/checkpoint.c | 10 +- fs/f2fs/data.c | 302 ++++++++++++++++++++---- fs/f2fs/debug.c | 12 +- fs/f2fs/dir.c | 6 + fs/f2fs/f2fs.h | 216 +++++++++++++---- fs/f2fs/file.c | 271 ++++++++++++++++----- fs/f2fs/gc.c | 18 +- fs/f2fs/gc.h | 2 + fs/f2fs/inode.c | 34 ++- fs/f2fs/namei.c | 67 ++---- fs/f2fs/node.c | 149 ++++++------ fs/f2fs/node.h | 4 + fs/f2fs/recovery.c | 27 ++- fs/f2fs/segment.c | 131 +++++----- fs/f2fs/segment.h | 92 ++++---- fs/f2fs/super.c | 145 +++++++++--- fs/f2fs/sysfs.c | 14 +- fs/f2fs/trace.c | 12 +- fs/f2fs/xattr.c | 12 +- include/linux/f2fs_fs.h | 14 +- include/trace/events/f2fs.h | 3 +- 22 files changed, 1102 insertions(+), 445 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs index 2baed1151eac4..db7aab1516dee 100644 --- a/Documentation/ABI/testing/sysfs-fs-f2fs +++ b/Documentation/ABI/testing/sysfs-fs-f2fs @@ -186,3 +186,9 @@ Date: August 2017 Contact: "Jaegeuk Kim" Description: Controls sleep time of GC urgent mode + +What: /sys/fs/f2fs//readdir_ra +Date: November 2017 +Contact: "Sheng Yong" +Description: + Controls readahead inode block in readdir. diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 288966b4c89de..8c7556b7da629 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -238,12 +238,15 @@ static int __f2fs_write_meta_page(struct page *page, trace_f2fs_writepage(page, META); + if (unlikely(f2fs_cp_error(sbi))) { + dec_page_count(sbi, F2FS_DIRTY_META); + unlock_page(page); + return 0; + } if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) goto redirty_out; if (wbc->for_reclaim && page->index < GET_SUM_BLOCK(sbi, 0)) goto redirty_out; - if (unlikely(f2fs_cp_error(sbi))) - goto redirty_out; write_meta_page(sbi, page, io_type); dec_page_count(sbi, F2FS_DIRTY_META); @@ -797,7 +800,7 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi) block_t cp_blk_no; int i; - sbi->ckpt = kzalloc(cp_blks * blk_size, GFP_KERNEL); + sbi->ckpt = f2fs_kzalloc(sbi, cp_blks * blk_size, GFP_KERNEL); if (!sbi->ckpt) return -ENOMEM; /* @@ -1158,6 +1161,7 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc) /* set this flag to activate crc|cp_ver for recovery */ __set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG); + __clear_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG); spin_unlock_irqrestore(&sbi->cp_lock, flags); } diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 8b652880cfc4d..12597399f0d6b 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -112,8 +112,13 @@ static void f2fs_write_end_io(struct bio *bio, int err) if (unlikely(err)) { set_bit(AS_EIO, &page->mapping->flags); - f2fs_stop_checkpoint(sbi, true); + if (type == F2FS_WB_CP_DATA) + f2fs_stop_checkpoint(sbi, true); } + + f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) && + page->index != nid_of_node(page)); + dec_page_count(sbi, type); clear_cold_data(page); end_page_writeback(page); @@ -169,6 +174,7 @@ static bool __same_bdev(struct f2fs_sb_info *sbi, * Low-level block read/write IO operations. */ static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr, + struct writeback_control *wbc, int npages, bool is_read) { struct bio *bio; @@ -178,6 +184,8 @@ static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr, f2fs_target_device(sbi, blk_addr, bio); bio->bi_end_io = is_read ? f2fs_read_end_io : f2fs_write_end_io; bio->bi_private = is_read ? NULL : sbi; + if (wbc) + wbc_init_bio(wbc, bio); return bio; } @@ -373,7 +381,8 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) f2fs_trace_ios(fio, 0); /* Allocate a new bio */ - bio = __bio_alloc(fio->sbi, fio->new_blkaddr, 1, is_read_io(fio->op)); + bio = __bio_alloc(fio->sbi, fio->new_blkaddr, fio->io_wbc, + 1, is_read_io(fio->op)); if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { bio_put(bio); @@ -435,7 +444,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio) dec_page_count(sbi, WB_DATA_TYPE(bio_page)); goto out_fail; } - io->bio = __bio_alloc(sbi, fio->new_blkaddr, + io->bio = __bio_alloc(sbi, fio->new_blkaddr, fio->io_wbc, BIO_MAX_PAGES, false); io->fio = *fio; } @@ -445,6 +454,9 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio) goto alloc_new; } + if (fio->io_wbc) + wbc_account_io(fio->io_wbc, bio_page, PAGE_SIZE); + io->last_block_in_bio = fio->new_blkaddr; f2fs_trace_ios(fio, 0); @@ -783,7 +795,7 @@ struct page *get_new_data_page(struct inode *inode, return page; } -static int __allocate_data_block(struct dnode_of_data *dn) +static int __allocate_data_block(struct dnode_of_data *dn, int seg_type) { struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); struct f2fs_summary sum; @@ -808,7 +820,7 @@ static int __allocate_data_block(struct dnode_of_data *dn) set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); allocate_data_block(sbi, NULL, dn->data_blkaddr, &dn->data_blkaddr, - &sum, CURSEG_WARM_DATA, NULL, false); + &sum, seg_type, NULL, false); set_data_blkaddr(dn); /* update i_size */ @@ -828,13 +840,14 @@ static inline bool __force_buffered_io(struct inode *inode, int rw) } int f2fs_preallocate_blocks(struct inode *inode, loff_t pos, - size_t count, bool dio) + size_t count, bool direct_io) { struct f2fs_map_blocks map; + int flag; int err = 0; /* convert inline data for Direct I/O*/ - if (dio) { + if (direct_io) { err = f2fs_convert_inline_inode(inode); if (err) return err; @@ -851,19 +864,34 @@ int f2fs_preallocate_blocks(struct inode *inode, loff_t pos, map.m_len = 0; map.m_next_pgofs = NULL; + map.m_next_extent = NULL; + map.m_seg_type = NO_CHECK_TYPE; - if (dio) - return f2fs_map_blocks(inode, &map, 1, - __force_buffered_io(inode, WRITE) ? - F2FS_GET_BLOCK_PRE_AIO : - F2FS_GET_BLOCK_PRE_DIO); + if (direct_io) { + /* map.m_seg_type = rw_hint_to_seg_type(iocb->ki_hint); */ + map.m_seg_type = rw_hint_to_seg_type(WRITE_LIFE_NOT_SET); + flag = __force_buffered_io(inode, WRITE) ? + F2FS_GET_BLOCK_PRE_AIO : + F2FS_GET_BLOCK_PRE_DIO; + goto map_blocks; + } if (pos + count > MAX_INLINE_DATA(inode)) { err = f2fs_convert_inline_inode(inode); if (err) return err; } - if (!f2fs_has_inline_data(inode)) - return f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_AIO); + if (f2fs_has_inline_data(inode)) + return err; + + flag = F2FS_GET_BLOCK_PRE_AIO; + +map_blocks: + err = f2fs_map_blocks(inode, &map, 1, flag); + if (map.m_len > 0 && err == -ENOSPC) { + if (!direct_io) + set_inode_flag(inode, FI_NO_PREALLOC); + err = 0; + } return err; } @@ -904,6 +932,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, blkcnt_t prealloc; struct extent_info ei = {0,0,0}; block_t blkaddr; + unsigned int start_pgofs; if (!maxblocks) return 0; @@ -919,6 +948,8 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, map->m_pblk = ei.blk + pgofs - ei.fofs; map->m_len = min((pgoff_t)maxblocks, ei.fofs + ei.len - pgofs); map->m_flags = F2FS_MAP_MAPPED; + if (map->m_next_extent) + *map->m_next_extent = pgofs + map->m_len; goto out; } @@ -937,10 +968,14 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, if (map->m_next_pgofs) *map->m_next_pgofs = get_next_page_offset(&dn, pgofs); + if (map->m_next_extent) + *map->m_next_extent = + get_next_page_offset(&dn, pgofs); } goto unlock_out; } + start_pgofs = pgofs; prealloc = 0; last_ofs_in_node = ofs_in_node = dn.ofs_in_node; end_offset = ADDRS_PER_PAGE(dn.node_page, inode); @@ -960,7 +995,8 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, last_ofs_in_node = dn.ofs_in_node; } } else { - err = __allocate_data_block(&dn); + err = __allocate_data_block(&dn, + map->m_seg_type); if (!err) set_inode_flag(inode, FI_APPEND_WRITE); } @@ -973,14 +1009,20 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, map->m_pblk = 0; goto sync_out; } + if (flag == F2FS_GET_BLOCK_PRECACHE) + goto sync_out; if (flag == F2FS_GET_BLOCK_FIEMAP && blkaddr == NULL_ADDR) { if (map->m_next_pgofs) *map->m_next_pgofs = pgofs + 1; + goto sync_out; } - if (flag != F2FS_GET_BLOCK_FIEMAP || - blkaddr != NEW_ADDR) + if (flag != F2FS_GET_BLOCK_FIEMAP) { + /* for defragment case */ + if (map->m_next_pgofs) + *map->m_next_pgofs = pgofs + 1; goto sync_out; + } } } @@ -1031,6 +1073,16 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, else if (dn.ofs_in_node < end_offset) goto next_block; + if (flag == F2FS_GET_BLOCK_PRECACHE) { + if (map->m_flags & F2FS_MAP_MAPPED) { + unsigned int ofs = start_pgofs - map->m_lblk; + + f2fs_update_extent_cache_range(&dn, + start_pgofs, map->m_pblk + ofs, + map->m_len - ofs); + } + } + f2fs_put_dnode(&dn); if (create) { @@ -1040,6 +1092,17 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, goto next_dnode; sync_out: + if (flag == F2FS_GET_BLOCK_PRECACHE) { + if (map->m_flags & F2FS_MAP_MAPPED) { + unsigned int ofs = start_pgofs - map->m_lblk; + + f2fs_update_extent_cache_range(&dn, + start_pgofs, map->m_pblk + ofs, + map->m_len - ofs); + } + if (map->m_next_extent) + *map->m_next_extent = pgofs + 1; + } f2fs_put_dnode(&dn); unlock_out: if (create) { @@ -1053,7 +1116,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, static int __get_data_block(struct inode *inode, sector_t iblock, struct buffer_head *bh, int create, int flag, - pgoff_t *next_pgofs) + pgoff_t *next_pgofs, int seg_type) { struct f2fs_map_blocks map; int err; @@ -1061,6 +1124,8 @@ static int __get_data_block(struct inode *inode, sector_t iblock, map.m_lblk = iblock; map.m_len = bh->b_size >> inode->i_blkbits; map.m_next_pgofs = next_pgofs; + map.m_next_extent = NULL; + map.m_seg_type = seg_type; err = f2fs_map_blocks(inode, &map, create, flag); if (!err) { @@ -1076,14 +1141,18 @@ static int get_data_block(struct inode *inode, sector_t iblock, pgoff_t *next_pgofs) { return __get_data_block(inode, iblock, bh_result, create, - flag, next_pgofs); + flag, next_pgofs, + NO_CHECK_TYPE); } static int get_data_block_dio(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) { return __get_data_block(inode, iblock, bh_result, create, - F2FS_GET_BLOCK_DEFAULT, NULL); + F2FS_GET_BLOCK_DEFAULT, NULL, + rw_hint_to_seg_type( + WRITE_LIFE_NOT_SET)); + /* inode->i_write_hint)); */ } static int get_data_block_bmap(struct inode *inode, sector_t iblock, @@ -1094,7 +1163,8 @@ static int get_data_block_bmap(struct inode *inode, sector_t iblock, return -EFBIG; return __get_data_block(inode, iblock, bh_result, create, - F2FS_GET_BLOCK_BMAP, NULL); + F2FS_GET_BLOCK_BMAP, NULL, + NO_CHECK_TYPE); } static inline sector_t logical_to_blk(struct inode *inode, loff_t offset) @@ -1107,6 +1177,68 @@ static inline loff_t blk_to_logical(struct inode *inode, sector_t blk) return (blk << inode->i_blkbits); } +static int f2fs_xattr_fiemap(struct inode *inode, + struct fiemap_extent_info *fieinfo) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct page *page; + struct node_info ni; + __u64 phys = 0, len; + __u32 flags; + nid_t xnid = F2FS_I(inode)->i_xattr_nid; + int err = 0; + + if (f2fs_has_inline_xattr(inode)) { + int offset; + + page = f2fs_grab_cache_page(NODE_MAPPING(sbi), + inode->i_ino, false); + if (!page) + return -ENOMEM; + + get_node_info(sbi, inode->i_ino, &ni); + + phys = (__u64)blk_to_logical(inode, ni.blk_addr); + offset = offsetof(struct f2fs_inode, i_addr) + + sizeof(__le32) * (DEF_ADDRS_PER_INODE - + get_inline_xattr_addrs(inode)); + + phys += offset; + len = inline_xattr_size(inode); + + f2fs_put_page(page, 1); + + flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED; + + if (!xnid) + flags |= FIEMAP_EXTENT_LAST; + + err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags); + if (err || err == 1) + return err; + } + + if (xnid) { + page = f2fs_grab_cache_page(NODE_MAPPING(sbi), xnid, false); + if (!page) + return -ENOMEM; + + get_node_info(sbi, xnid, &ni); + + phys = (__u64)blk_to_logical(inode, ni.blk_addr); + len = inode->i_sb->s_blocksize; + + f2fs_put_page(page, 1); + + flags = FIEMAP_EXTENT_LAST; + } + + if (phys) + err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags); + + return (err < 0 ? err : 0); +} + int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len) { @@ -1117,18 +1249,29 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u32 flags = 0; int ret = 0; - ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC); + if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) { + ret = f2fs_precache_extents(inode); + if (ret) + return ret; + } + + ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR); if (ret) return ret; + inode_lock(inode); + + if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) { + ret = f2fs_xattr_fiemap(inode, fieinfo); + goto out; + } + if (f2fs_has_inline_data(inode)) { ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len); if (ret != -EAGAIN) - return ret; + goto out; } - inode_lock(inode); - if (logical_to_blk(inode, len) == 0) len = blk_to_logical(inode, 1); @@ -1198,7 +1341,6 @@ static int f2fs_mpage_readpages(struct address_space *mapping, unsigned nr_pages) { struct bio *bio = NULL; - unsigned page_idx; sector_t last_block_in_bio = 0; struct inode *inode = mapping->host; const unsigned blkbits = inode->i_blkbits; @@ -1214,9 +1356,10 @@ static int f2fs_mpage_readpages(struct address_space *mapping, map.m_len = 0; map.m_flags = 0; map.m_next_pgofs = NULL; + map.m_next_extent = NULL; + map.m_seg_type = NO_CHECK_TYPE; - for (page_idx = 0; nr_pages; page_idx++, nr_pages--) { - + for (; nr_pages; nr_pages--) { if (pages) { page = list_last_entry(pages, struct page, lru); @@ -1375,18 +1518,79 @@ static int encrypt_one_page(struct f2fs_io_info *fio) return PTR_ERR(fio->encrypted_page); } +static inline bool check_inplace_update_policy(struct inode *inode, + struct f2fs_io_info *fio) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + unsigned int policy = SM_I(sbi)->ipu_policy; + + if (policy & (0x1 << F2FS_IPU_FORCE)) + return true; + if (policy & (0x1 << F2FS_IPU_SSR) && need_SSR(sbi)) + return true; + if (policy & (0x1 << F2FS_IPU_UTIL) && + utilization(sbi) > SM_I(sbi)->min_ipu_util) + return true; + if (policy & (0x1 << F2FS_IPU_SSR_UTIL) && need_SSR(sbi) && + utilization(sbi) > SM_I(sbi)->min_ipu_util) + return true; + + /* + * IPU for rewrite async pages + */ + if (policy & (0x1 << F2FS_IPU_ASYNC) && + fio && fio->op == REQ_OP_WRITE && + !(fio->op_flags & REQ_SYNC) && + !f2fs_encrypted_inode(inode)) + return true; + + /* this is only set during fdatasync */ + if (policy & (0x1 << F2FS_IPU_FSYNC) && + is_inode_flag_set(inode, FI_NEED_IPU)) + return true; + + return false; +} + +bool should_update_inplace(struct inode *inode, struct f2fs_io_info *fio) +{ + if (f2fs_is_pinned_file(inode)) + return true; + + /* if this is cold file, we should overwrite to avoid fragmentation */ + if (file_is_cold(inode)) + return true; + + return check_inplace_update_policy(inode, fio); +} + +bool should_update_outplace(struct inode *inode, struct f2fs_io_info *fio) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + + if (test_opt(sbi, LFS)) + return true; + if (S_ISDIR(inode->i_mode)) + return true; + if (f2fs_is_atomic_file(inode)) + return true; + if (fio) { + if (is_cold_data(fio->page)) + return true; + if (IS_ATOMIC_WRITTEN_PAGE(fio->page)) + return true; + } + return false; +} + static inline bool need_inplace_update(struct f2fs_io_info *fio) { struct inode *inode = fio->page->mapping->host; - if (S_ISDIR(inode->i_mode) || f2fs_is_atomic_file(inode)) - return false; - if (is_cold_data(fio->page)) - return false; - if (IS_ATOMIC_WRITTEN_PAGE(fio->page)) + if (should_update_outplace(inode, fio)) return false; - return need_inplace_update_policy(inode, fio); + return should_update_inplace(inode, fio); } static inline bool valid_ipu_blkaddr(struct f2fs_io_info *fio) @@ -1507,10 +1711,17 @@ static int __write_data_page(struct page *page, bool *submitted, .submitted = false, .need_lock = LOCK_RETRY, .io_type = io_type, + .io_wbc = wbc, }; trace_f2fs_writepage(page, DATA); + /* we should bypass data pages to proceed the kworkder jobs */ + if (unlikely(f2fs_cp_error(sbi))) { + mapping_set_error(page->mapping, -EIO); + goto out; + } + if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) goto redirty_out; @@ -1535,12 +1746,6 @@ static int __write_data_page(struct page *page, bool *submitted, available_free_memory(sbi, BASE_CHECK)))) goto redirty_out; - /* we should bypass data pages to proceed the kworkder jobs */ - if (unlikely(f2fs_cp_error(sbi))) { - mapping_set_error(page->mapping, -EIO); - goto out; - } - /* Dentry blocks are controlled by checkpoint */ if (S_ISDIR(inode->i_mode)) { fio.need_lock = LOCK_DONE; @@ -1570,10 +1775,14 @@ static int __write_data_page(struct page *page, bool *submitted, } } - down_write(&F2FS_I(inode)->i_sem); - if (F2FS_I(inode)->last_disk_size < psize) - F2FS_I(inode)->last_disk_size = psize; - up_write(&F2FS_I(inode)->i_sem); + if (err) { + file_set_keep_isize(inode); + } else { + down_write(&F2FS_I(inode)->i_sem); + if (F2FS_I(inode)->last_disk_size < psize) + F2FS_I(inode)->last_disk_size = psize; + up_write(&F2FS_I(inode)->i_sem); + } done: if (err && err != -ENOENT) @@ -1937,7 +2146,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct page *page = NULL; pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT; - bool need_balance = false; + bool need_balance = false, drop_atomic = false; block_t blkaddr = NULL_ADDR; int err = 0; @@ -1956,6 +2165,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, if (f2fs_is_atomic_file(inode) && !available_free_memory(sbi, INMEM_PAGES)) { err = -ENOMEM; + drop_atomic = true; goto fail; } @@ -2036,7 +2246,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, fail: f2fs_put_page(page, 1); f2fs_write_failed(mapping, pos + len); - if (f2fs_is_atomic_file(inode)) + if (drop_atomic) drop_inmem_pages_all(sbi); return err; } diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index 36d6a72779241..7c2ba8b0ee241 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -49,14 +49,7 @@ static void update_general_status(struct f2fs_sb_info *sbi) si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA); si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE]; si->ndirty_files = sbi->ndirty_inode[FILE_INODE]; - - si->nquota_files = 0; - if (f2fs_sb_has_quota_ino(sbi->sb)) { - for (i = 0; i < MAXQUOTAS; i++) { - if (f2fs_qf_ino(sbi->sb, i)) - si->nquota_files++; - } - } + si->nquota_files = sbi->nquota_files; si->ndirty_all = sbi->ndirty_inode[DIRTY_META]; si->inmem_pages = get_pages(sbi, F2FS_INMEM_PAGES); si->aw_cnt = atomic_read(&sbi->aw_cnt); @@ -186,7 +179,6 @@ static void update_mem_info(struct f2fs_sb_info *sbi) si->base_mem += sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize; si->base_mem += 2 * sizeof(struct f2fs_inode_info); si->base_mem += sizeof(*sbi->ckpt); - si->base_mem += sizeof(struct percpu_counter) * NR_COUNT_TYPE; /* build sm */ si->base_mem += sizeof(struct f2fs_sm_info); @@ -449,7 +441,7 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi) struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); struct f2fs_stat_info *si; - si = kzalloc(sizeof(struct f2fs_stat_info), GFP_KERNEL); + si = f2fs_kzalloc(sbi, sizeof(struct f2fs_stat_info), GFP_KERNEL); if (!si) return -ENOMEM; diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 1955707b138b4..bde445e4e6907 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -713,6 +713,8 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, f2fs_update_time(F2FS_I_SB(dir), REQ_TIME); + add_ino_entry(F2FS_I_SB(dir), dir->i_ino, TRANS_DIR_INO); + if (f2fs_has_inline_dentry(dir)) return f2fs_delete_inline_entry(dentry, page, dir, inode); @@ -798,6 +800,7 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d, unsigned int bit_pos; struct f2fs_dir_entry *de = NULL; struct fscrypt_str de_name = FSTR_INIT(NULL, 0); + struct f2fs_sb_info *sbi = F2FS_I_SB(d->inode); bit_pos = ((unsigned long)ctx->pos % d->max); @@ -836,6 +839,9 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d, le32_to_cpu(de->ino), d_type)) return 1; + if (sbi->readdir_ra == 1) + ra_node_page(sbi, le32_to_cpu(de->ino)); + bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); ctx->pos = start_pos + bit_pos; } diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 29ac022d3009b..2ffec50508546 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,7 @@ #ifdef CONFIG_F2FS_FAULT_INJECTION enum { FAULT_KMALLOC, + FAULT_KVMALLOC, FAULT_PAGE_ALLOC, FAULT_PAGE_GET, FAULT_ALLOC_BIO, @@ -96,6 +98,7 @@ extern char *fault_name[FAULT_MAX]; #define F2FS_MOUNT_PRJQUOTA 0x00200000 #define F2FS_MOUNT_QUOTA 0x00400000 #define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 +#define F2FS_MOUNT_RESERVE_ROOT 0x01000000 #define clear_opt(sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option) #define set_opt(sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option) @@ -123,6 +126,7 @@ struct f2fs_mount_info { #define F2FS_FEATURE_INODE_CHKSUM 0x0020 #define F2FS_FEATURE_FLEXIBLE_INLINE_XATTR 0x0040 #define F2FS_FEATURE_QUOTA_INO 0x0080 +#define F2FS_FEATURE_INODE_CRTIME 0x0100 #define F2FS_HAS_FEATURE(sb, mask) \ ((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0) @@ -228,6 +232,12 @@ static inline struct timespec current_time(struct inode *inode) return timespec_trunc(now, inode->i_sb->s_time_gran); } +/* + * Default values for user and/or group using reserved blocks + */ +#define F2FS_DEF_RESUID 0 +#define F2FS_DEF_RESGID 0 + /* * For checkpoint manager */ @@ -278,6 +288,7 @@ enum { ORPHAN_INO, /* for orphan ino list */ APPEND_INO, /* for append ino list */ UPDATE_INO, /* for update ino list */ + TRANS_DIR_INO, /* for trasactions dir ino list */ FLUSH_INO, /* for multiple device flushing */ MAX_INO_ENTRY, /* max. list */ }; @@ -363,7 +374,6 @@ struct discard_cmd_control { struct task_struct *f2fs_issue_discard; /* discard thread */ struct list_head entry_list; /* 4KB discard entry list */ struct list_head pend_list[MAX_PLIST_NUM];/* store pending entries */ - unsigned char pend_list_tag[MAX_PLIST_NUM];/* tag for pending entries */ struct list_head wait_list; /* store on-flushing entries */ struct list_head fstrim_list; /* in-flight discard from fstrim */ wait_queue_head_t discard_wait_queue; /* waiting queue for wake-up */ @@ -446,6 +456,9 @@ static inline bool __has_cursum_space(struct f2fs_journal *journal, #define F2FS_IOC_GARBAGE_COLLECT_RANGE _IOW(F2FS_IOCTL_MAGIC, 11, \ struct f2fs_gc_range) #define F2FS_IOC_GET_FEATURES _IOR(F2FS_IOCTL_MAGIC, 12, __u32) +#define F2FS_IOC_SET_PIN_FILE _IOW(F2FS_IOCTL_MAGIC, 13, __u32) +#define F2FS_IOC_GET_PIN_FILE _IOR(F2FS_IOCTL_MAGIC, 14, __u32) +#define F2FS_IOC_PRECACHE_EXTENTS _IO(F2FS_IOCTL_MAGIC, 15) #define F2FS_IOC_SET_ENCRYPTION_POLICY FS_IOC_SET_ENCRYPTION_POLICY #define F2FS_IOC_GET_ENCRYPTION_POLICY FS_IOC_GET_ENCRYPTION_POLICY @@ -498,10 +511,9 @@ struct f2fs_flush_device { #define DEF_MIN_INLINE_SIZE 1 static inline int get_extra_isize(struct inode *inode); static inline int get_inline_xattr_addrs(struct inode *inode); -#define F2FS_INLINE_XATTR_ADDRS(inode) get_inline_xattr_addrs(inode) #define MAX_INLINE_DATA(inode) (sizeof(__le32) * \ (CUR_ADDRS_PER_INODE(inode) - \ - F2FS_INLINE_XATTR_ADDRS(inode) - \ + get_inline_xattr_addrs(inode) - \ DEF_INLINE_RESERVED_SIZE)) /* for inline dir */ @@ -638,6 +650,8 @@ struct f2fs_map_blocks { unsigned int m_len; unsigned int m_flags; pgoff_t *m_next_pgofs; /* point next possible non-hole pgofs */ + pgoff_t *m_next_extent; /* point to next possible extent */ + int m_seg_type; }; /* for flag in get_data_block */ @@ -647,6 +661,7 @@ enum { F2FS_GET_BLOCK_BMAP, F2FS_GET_BLOCK_PRE_DIO, F2FS_GET_BLOCK_PRE_AIO, + F2FS_GET_BLOCK_PRECACHE, }; /* @@ -679,7 +694,10 @@ struct f2fs_inode_info { unsigned long i_flags; /* keep an inode flags for ioctl */ unsigned char i_advise; /* use to give file attribute hints */ unsigned char i_dir_level; /* use for dentry level for large dir */ - unsigned int i_current_depth; /* use only in directory structure */ + union { + unsigned int i_current_depth; /* only for directory depth */ + unsigned short i_gc_failures; /* only for regular file */ + }; unsigned int i_pino; /* parent inode number */ umode_t i_acl_mode; /* keep file acl mode temporarily */ @@ -712,6 +730,7 @@ struct f2fs_inode_info { int i_extra_isize; /* size of extra space located in i_addr */ kprojid_t i_projid; /* id for project quota */ int i_inline_xattr_size; /* inline xattr size */ + struct timespec i_crtime; /* inode creation time */ }; static inline void get_extent_info(struct extent_info *ext, @@ -1016,6 +1035,7 @@ enum cp_reason_type { CP_NODE_NEED_CP, CP_FASTBOOT_MODE, CP_SPEC_LOG_NUM, + CP_RECOVER_DIR, }; enum iostat_type { @@ -1051,6 +1071,7 @@ struct f2fs_io_info { int need_lock; /* indicate we need to lock cp_rwsem */ bool in_list; /* indicate fio is in io_list */ enum iostat_type io_type; /* io type */ + struct writeback_control *io_wbc; /* writeback control */ }; #define is_read_io(rw) ((rw) == READ) @@ -1191,6 +1212,7 @@ struct f2fs_sb_info { int dir_level; /* directory level */ int inline_xattr_size; /* inline xattr size */ unsigned int trigger_ssr_threshold; /* threshold to trigger ssr */ + int readdir_ra; /* readahead inode in readdir */ block_t user_block_count; /* # of user blocks */ block_t total_valid_block_count; /* # of valid blocks */ @@ -1198,6 +1220,11 @@ struct f2fs_sb_info { block_t last_valid_block_count; /* for recovery */ block_t reserved_blocks; /* configurable reserved blocks */ block_t current_reserved_blocks; /* current reserved blocks */ + block_t root_reserved_blocks; /* root reserved blocks */ + kuid_t s_resuid; /* reserved blocks for uid */ + kgid_t s_resgid; /* reserved blocks for gid */ + + unsigned int nquota_files; /* # of quota sysfile */ u32 s_next_generation; /* for NFS support */ @@ -1222,6 +1249,9 @@ struct f2fs_sb_info { /* threshold for converting bg victims for fg */ u64 fggc_threshold; + /* threshold for gc trials on pinned files */ + u64 gc_pin_file_threshold; + /* maximum # of trials to find a victim segment for SSR and GC */ unsigned int max_victim_search; @@ -1348,30 +1378,7 @@ static inline bool is_idle(struct f2fs_sb_info *sbi) /* * Inline functions */ -static inline u32 f2fs_crc32(struct f2fs_sb_info *sbi, const void *address, - unsigned int length) -{ - SHASH_DESC_ON_STACK(shash, sbi->s_chksum_driver); - u32 *ctx = (u32 *)shash_desc_ctx(shash); - int err; - - shash->tfm = sbi->s_chksum_driver; - shash->flags = 0; - *ctx = F2FS_SUPER_MAGIC; - - err = crypto_shash_update(shash, address, length); - BUG_ON(err); - - return *ctx; -} - -static inline bool f2fs_crc_valid(struct f2fs_sb_info *sbi, __u32 blk_crc, - void *buf, size_t buf_size) -{ - return f2fs_crc32(sbi, buf, buf_size) == blk_crc; -} - -static inline u32 f2fs_chksum(struct f2fs_sb_info *sbi, u32 crc, +static inline u32 __f2fs_crc32(struct f2fs_sb_info *sbi, u32 crc, const void *address, unsigned int length) { struct { @@ -1392,6 +1399,24 @@ static inline u32 f2fs_chksum(struct f2fs_sb_info *sbi, u32 crc, return *(u32 *)desc.ctx; } +static inline u32 f2fs_crc32(struct f2fs_sb_info *sbi, const void *address, + unsigned int length) +{ + return __f2fs_crc32(sbi, F2FS_SUPER_MAGIC, address, length); +} + +static inline bool f2fs_crc_valid(struct f2fs_sb_info *sbi, __u32 blk_crc, + void *buf, size_t buf_size) +{ + return f2fs_crc32(sbi, buf, buf_size) == blk_crc; +} + +static inline u32 f2fs_chksum(struct f2fs_sb_info *sbi, u32 crc, + const void *address, unsigned int length) +{ + return __f2fs_crc32(sbi, crc, address, length); +} + static inline struct f2fs_inode_info *F2FS_I(struct inode *inode) { return container_of(inode, struct f2fs_inode_info, vfs_inode); @@ -1650,6 +1675,25 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs) return ofs == XATTR_NODE_OFFSET; } +static inline bool __allow_reserved_blocks(struct f2fs_sb_info *sbi, + struct inode *inode) +{ + if (!inode) + return true; + if (!test_opt(sbi, RESERVE_ROOT)) + return false; + if (IS_NOQUOTA(inode)) + return true; + if (capable(CAP_SYS_RESOURCE)) + return true; + if (uid_eq(sbi->s_resuid, current_fsuid())) + return true; + if (!gid_eq(sbi->s_resgid, GLOBAL_ROOT_GID) && + in_group_p(sbi->s_resgid)) + return true; + return false; +} + static inline void f2fs_i_blocks_write(struct inode *, block_t, bool, bool); static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, struct inode *inode, blkcnt_t *count) @@ -1679,11 +1723,17 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, sbi->total_valid_block_count += (block_t)(*count); avail_user_block_count = sbi->user_block_count - sbi->current_reserved_blocks; + + if (!__allow_reserved_blocks(sbi, inode)) + avail_user_block_count -= sbi->root_reserved_blocks; + if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) { diff = sbi->total_valid_block_count - avail_user_block_count; + if (diff > *count) + diff = *count; *count -= diff; release = diff; - sbi->total_valid_block_count = avail_user_block_count; + sbi->total_valid_block_count -= diff; if (!*count) { spin_unlock(&sbi->stat_lock); percpu_counter_sub(&sbi->alloc_valid_block_count, diff); @@ -1692,7 +1742,7 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, } spin_unlock(&sbi->stat_lock); - if (release) + if (unlikely(release)) dquot_release_reservation_block(inode, release); f2fs_i_blocks_write(inode, *count, true, true); return 0; @@ -1872,9 +1922,13 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi, spin_lock(&sbi->stat_lock); - valid_block_count = sbi->total_valid_block_count + 1; - if (unlikely(valid_block_count + sbi->current_reserved_blocks > - sbi->user_block_count)) { + valid_block_count = sbi->total_valid_block_count + + sbi->current_reserved_blocks + 1; + + if (!__allow_reserved_blocks(sbi, inode)) + valid_block_count += sbi->root_reserved_blocks; + + if (unlikely(valid_block_count > sbi->user_block_count)) { spin_unlock(&sbi->stat_lock); goto enospc; } @@ -2087,11 +2141,11 @@ static inline block_t datablock_addr(struct inode *inode, raw_node = F2FS_NODE(node_page); /* from GC path only */ - if (!inode) { - if (is_inode) + if (is_inode) { + if (!inode) base = offset_in_addr(&raw_node->i); - } else if (f2fs_has_extra_attr(inode) && is_inode) { - base = get_extra_isize(inode); + else if (f2fs_has_extra_attr(inode)) + base = get_extra_isize(inode); } addr_array = blkaddr_in_node(raw_node); @@ -2202,6 +2256,7 @@ enum { FI_HOT_DATA, /* indicate file is hot */ FI_EXTRA_ATTR, /* indicate file has extra attribute */ FI_PROJ_INHERIT, /* indicate file inherits projectid */ + FI_PIN_FILE, /* indicate file should not be gced */ }; static inline void __mark_inode_dirty_flag(struct inode *inode, @@ -2211,10 +2266,12 @@ static inline void __mark_inode_dirty_flag(struct inode *inode, case FI_INLINE_XATTR: case FI_INLINE_DATA: case FI_INLINE_DENTRY: + case FI_NEW_INODE: if (set) return; case FI_DATA_EXIST: case FI_INLINE_DOTS: + case FI_PIN_FILE: f2fs_mark_inode_dirty_sync(inode, true); } } @@ -2295,6 +2352,13 @@ static inline void f2fs_i_depth_write(struct inode *inode, unsigned int depth) f2fs_mark_inode_dirty_sync(inode, true); } +static inline void f2fs_i_gc_failures_write(struct inode *inode, + unsigned int count) +{ + F2FS_I(inode)->i_gc_failures = count; + f2fs_mark_inode_dirty_sync(inode, true); +} + static inline void f2fs_i_xnid_write(struct inode *inode, nid_t xnid) { F2FS_I(inode)->i_xattr_nid = xnid; @@ -2323,6 +2387,8 @@ static inline void get_inline_info(struct inode *inode, struct f2fs_inode *ri) set_bit(FI_INLINE_DOTS, &fi->flags); if (ri->i_inline & F2FS_EXTRA_ATTR) set_bit(FI_EXTRA_ATTR, &fi->flags); + if (ri->i_inline & F2FS_PIN_FILE) + set_bit(FI_PIN_FILE, &fi->flags); } static inline void set_raw_inline(struct inode *inode, struct f2fs_inode *ri) @@ -2341,6 +2407,8 @@ static inline void set_raw_inline(struct inode *inode, struct f2fs_inode *ri) ri->i_inline |= F2FS_INLINE_DOTS; if (is_inode_flag_set(inode, FI_EXTRA_ATTR)) ri->i_inline |= F2FS_EXTRA_ATTR; + if (is_inode_flag_set(inode, FI_PIN_FILE)) + ri->i_inline |= F2FS_PIN_FILE; } static inline int f2fs_has_extra_attr(struct inode *inode) @@ -2355,7 +2423,7 @@ static inline int f2fs_has_inline_xattr(struct inode *inode) static inline unsigned int addrs_per_inode(struct inode *inode) { - return CUR_ADDRS_PER_INODE(inode) - F2FS_INLINE_XATTR_ADDRS(inode); + return CUR_ADDRS_PER_INODE(inode) - get_inline_xattr_addrs(inode); } static inline void *inline_xattr_addr(struct inode *inode, struct page *page) @@ -2363,7 +2431,7 @@ static inline void *inline_xattr_addr(struct inode *inode, struct page *page) struct f2fs_inode *ri = F2FS_INODE(page); return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE - - F2FS_INLINE_XATTR_ADDRS(inode)]); + get_inline_xattr_addrs(inode)]); } static inline int inline_xattr_size(struct inode *inode) @@ -2386,6 +2454,11 @@ static inline int f2fs_has_inline_dots(struct inode *inode) return is_inode_flag_set(inode, FI_INLINE_DOTS); } +static inline bool f2fs_is_pinned_file(struct inode *inode) +{ + return is_inode_flag_set(inode, FI_PIN_FILE); +} + static inline bool f2fs_is_atomic_file(struct inode *inode) { return is_inode_flag_set(inode, FI_ATOMIC_FILE); @@ -2534,12 +2607,53 @@ static inline void *kvzalloc(size_t size, gfp_t flags) return ret; } +enum rw_hint { + WRITE_LIFE_NOT_SET = 0, + WRITE_LIFE_NONE = 1, /* RWH_WRITE_LIFE_NONE */ + WRITE_LIFE_SHORT = 2, /* RWH_WRITE_LIFE_SHORT */ + WRITE_LIFE_MEDIUM = 3, /* RWH_WRITE_LIFE_MEDIUM */ + WRITE_LIFE_LONG = 4, /* RWH_WRITE_LIFE_LONG */ + WRITE_LIFE_EXTREME = 5, /* RWH_WRITE_LIFE_EXTREME */ +}; + +static inline void wbc_init_bio(struct writeback_control *wbc, struct bio *bio) +{ +} + +static inline void wbc_account_io(struct writeback_control *wbc, + struct page *page, size_t bytes) +{ +} + +static inline void *f2fs_kzalloc(struct f2fs_sb_info *sbi, + size_t size, gfp_t flags) +{ + return f2fs_kmalloc(sbi, size, flags | __GFP_ZERO); +} + +static inline void *f2fs_kvmalloc(struct f2fs_sb_info *sbi, + size_t size, gfp_t flags) +{ +#ifdef CONFIG_F2FS_FAULT_INJECTION + if (time_to_inject(sbi, FAULT_KVMALLOC)) { + f2fs_show_injection_info(FAULT_KVMALLOC); + return NULL; + } +#endif + return kvmalloc(size, flags); +} + +static inline void *f2fs_kvzalloc(struct f2fs_sb_info *sbi, + size_t size, gfp_t flags) +{ + return f2fs_kvmalloc(sbi, size, flags | __GFP_ZERO); +} + static inline int get_extra_isize(struct inode *inode) { return F2FS_I(inode)->i_extra_isize / sizeof(__le32); } -static inline int f2fs_sb_has_flexible_inline_xattr(struct super_block *sb); static inline int get_inline_xattr_addrs(struct inode *inode) { return F2FS_I(inode)->i_inline_xattr_size; @@ -2595,9 +2709,11 @@ int f2fs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); int f2fs_setattr(struct dentry *dentry, struct iattr *attr); int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end); -int truncate_data_blocks_range(struct dnode_of_data *dn, int count); +void truncate_data_blocks_range(struct dnode_of_data *dn, int count); +int f2fs_precache_extents(struct inode *inode); long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +int f2fs_pin_file_control(struct inode *inode, bool inc); /* * inode.c @@ -2608,8 +2724,8 @@ void f2fs_inode_chksum_set(struct f2fs_sb_info *sbi, struct page *page); struct inode *f2fs_iget(struct super_block *sb, unsigned long ino); struct inode *f2fs_iget_retry(struct super_block *sb, unsigned long ino); int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink); -int update_inode(struct inode *inode, struct page *node_page); -int update_inode_page(struct inode *inode); +void update_inode(struct inode *inode, struct page *node_page); +void update_inode_page(struct inode *inode); int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc); void f2fs_evict_inode(struct inode *inode); void handle_failed_inode(struct inode *inode); @@ -2720,10 +2836,9 @@ void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid); void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid); int try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink); void recover_inline_xattr(struct inode *inode, struct page *page); -int recover_xattr_data(struct inode *inode, struct page *page, - block_t blkaddr); +int recover_xattr_data(struct inode *inode, struct page *page); int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page); -int restore_node_summary(struct f2fs_sb_info *sbi, +void restore_node_summary(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summary_block *sum); void flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc); int build_node_manager(struct f2fs_sb_info *sbi); @@ -2750,6 +2865,7 @@ void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr); bool is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr); void init_discard_policy(struct discard_policy *dpolicy, int discard_type, unsigned int granularity); +void drop_discard_cmd(struct f2fs_sb_info *sbi); void stop_discard_thread(struct f2fs_sb_info *sbi); bool f2fs_wait_discard_bios(struct f2fs_sb_info *sbi); void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc); @@ -2788,6 +2904,7 @@ int build_segment_manager(struct f2fs_sb_info *sbi); void destroy_segment_manager(struct f2fs_sb_info *sbi); int __init create_segment_manager_caches(void); void destroy_segment_manager_caches(void); +int rw_hint_to_seg_type(enum rw_hint hint); /* * checkpoint.c @@ -2858,6 +2975,8 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int create, int flag); int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len); +bool should_update_inplace(struct inode *inode, struct f2fs_io_info *fio); +bool should_update_outplace(struct inode *inode, struct f2fs_io_info *fio); void f2fs_set_page_dirty_nobuffers(struct page *page); int __f2fs_write_data_pages(struct address_space *mapping, struct writeback_control *wbc, @@ -3226,6 +3345,11 @@ static inline int f2fs_sb_has_quota_ino(struct super_block *sb) return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_QUOTA_INO); } +static inline int f2fs_sb_has_inode_crtime(struct super_block *sb) +{ + return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_INODE_CRTIME); +} + #ifdef CONFIG_BLK_DEV_ZONED static inline int get_blkz_type(struct f2fs_sb_info *sbi, struct block_device *bdev, block_t blkaddr) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 130a74d29073d..1ed7359cf37dd 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -169,6 +169,9 @@ static inline enum cp_reason_type need_do_checkpoint(struct inode *inode) cp_reason = CP_FASTBOOT_MODE; else if (sbi->active_logs == 2) cp_reason = CP_SPEC_LOG_NUM; + else if (need_dentry_mark(sbi, inode->i_ino) && + exist_written_data(sbi, F2FS_I(inode)->i_pino, TRANS_DIR_INO)) + cp_reason = CP_RECOVER_DIR; return cp_reason; } @@ -475,26 +478,14 @@ static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma) static int f2fs_file_open(struct inode *inode, struct file *filp) { - struct dentry *dir; + int err = fscrypt_file_open(inode, filp); - if (f2fs_encrypted_inode(inode)) { - int ret = fscrypt_get_encryption_info(inode); - if (ret) - return -EACCES; - if (!fscrypt_has_encryption_key(inode)) - return -ENOKEY; - } - dir = dget_parent(file_dentry(filp)); - if (f2fs_encrypted_inode(d_inode(dir)) && - !fscrypt_has_permitted_context(d_inode(dir), inode)) { - dput(dir); - return -EPERM; - } - dput(dir); + if (err) + return err; return dquot_file_open(inode, filp); } -int truncate_data_blocks_range(struct dnode_of_data *dn, int count) +void truncate_data_blocks_range(struct dnode_of_data *dn, int count) { struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); struct f2fs_node *raw_node; @@ -537,7 +528,6 @@ int truncate_data_blocks_range(struct dnode_of_data *dn, int count) f2fs_update_time(sbi, REQ_TIME); trace_f2fs_truncate_data_blocks_range(dn->inode, dn->nid, dn->ofs_in_node, nr_free); - return nr_free; } void truncate_data_blocks(struct dnode_of_data *dn) @@ -684,6 +674,37 @@ int f2fs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { struct inode *inode = d_inode(dentry); +#if 0 + struct f2fs_inode_info *fi = F2FS_I(inode); + struct f2fs_inode *ri; + unsigned int flags; + + if (f2fs_has_extra_attr(inode) && + f2fs_sb_has_inode_crtime(inode->i_sb) && + F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_crtime)) { + stat->result_mask |= STATX_BTIME; + stat->btime.tv_sec = fi->i_crtime.tv_sec; + stat->btime.tv_nsec = fi->i_crtime.tv_nsec; + } + + flags = fi->i_flags & (FS_FL_USER_VISIBLE | FS_PROJINHERIT_FL); + if (flags & FS_APPEND_FL) + stat->attributes |= STATX_ATTR_APPEND; + if (flags & FS_COMPR_FL) + stat->attributes |= STATX_ATTR_COMPRESSED; + if (f2fs_encrypted_inode(inode)) + stat->attributes |= STATX_ATTR_ENCRYPTED; + if (flags & FS_IMMUTABLE_FL) + stat->attributes |= STATX_ATTR_IMMUTABLE; + if (flags & FS_NODUMP_FL) + stat->attributes |= STATX_ATTR_NODUMP; + + stat->attributes_mask |= (STATX_ATTR_APPEND | + STATX_ATTR_COMPRESSED | + STATX_ATTR_ENCRYPTED | + STATX_ATTR_IMMUTABLE | + STATX_ATTR_NODUMP); +#endif generic_fillattr(inode, stat); /* we need to show initial sectors used for inline_data/dentries */ @@ -737,8 +758,13 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr) if (err) return err; + err = fscrypt_prepare_setattr(dentry, attr); + if (err) + return err; + if (is_quota_modification(inode, attr)) dquot_initialize(inode); + if ((attr->ia_valid & ATTR_UID && !uid_eq(attr->ia_uid, inode->i_uid)) || (attr->ia_valid & ATTR_GID && @@ -749,14 +775,6 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr) } if (attr->ia_valid & ATTR_SIZE) { - if (f2fs_encrypted_inode(inode)) { - err = fscrypt_get_encryption_info(inode); - if (err) - return err; - if (!fscrypt_has_encryption_key(inode)) - return -ENOKEY; - } - if (attr->ia_size <= i_size_read(inode)) { down_write(&F2FS_I(inode)->i_mmap_sem); truncate_setsize(inode, attr->ia_size); @@ -1096,11 +1114,13 @@ static int __exchange_data_block(struct inode *src_inode, while (len) { olen = min((pgoff_t)4 * ADDRS_PER_BLOCK, len); - src_blkaddr = kvzalloc(sizeof(block_t) * olen, GFP_KERNEL); + src_blkaddr = f2fs_kvzalloc(F2FS_I_SB(src_inode), + sizeof(block_t) * olen, GFP_KERNEL); if (!src_blkaddr) return -ENOMEM; - do_replace = kvzalloc(sizeof(int) * olen, GFP_KERNEL); + do_replace = f2fs_kvzalloc(F2FS_I_SB(src_inode), + sizeof(int) * olen, GFP_KERNEL); if (!do_replace) { kvfree(src_blkaddr); return -ENOMEM; @@ -1168,14 +1188,14 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len) pg_start = offset >> PAGE_SHIFT; pg_end = (offset + len) >> PAGE_SHIFT; + /* avoid gc operation during block exchange */ + down_write(&F2FS_I(inode)->dio_rwsem[WRITE]); + down_write(&F2FS_I(inode)->i_mmap_sem); /* write out all dirty pages from offset */ ret = filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX); if (ret) - goto out; - - /* avoid gc operation during block exchange */ - down_write(&F2FS_I(inode)->dio_rwsem[WRITE]); + goto out_unlock; truncate_pagecache(inode, offset); @@ -1194,9 +1214,8 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len) if (!ret) f2fs_i_size_write(inode, new_size); out_unlock: - up_write(&F2FS_I(inode)->dio_rwsem[WRITE]); -out: up_write(&F2FS_I(inode)->i_mmap_sem); + up_write(&F2FS_I(inode)->dio_rwsem[WRITE]); return ret; } @@ -1367,6 +1386,9 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len) f2fs_balance_fs(sbi, true); + /* avoid gc operation during block exchange */ + down_write(&F2FS_I(inode)->dio_rwsem[WRITE]); + down_write(&F2FS_I(inode)->i_mmap_sem); ret = truncate_blocks(inode, i_size_read(inode), true); if (ret) @@ -1377,9 +1399,6 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len) if (ret) goto out; - /* avoid gc operation during block exchange */ - down_write(&F2FS_I(inode)->dio_rwsem[WRITE]); - truncate_pagecache(inode, offset); pg_start = offset >> PAGE_SHIFT; @@ -1407,10 +1426,9 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len) if (!ret) f2fs_i_size_write(inode, new_size); - - up_write(&F2FS_I(inode)->dio_rwsem[WRITE]); out: up_write(&F2FS_I(inode)->i_mmap_sem); + up_write(&F2FS_I(inode)->dio_rwsem[WRITE]); return ret; } @@ -1418,7 +1436,8 @@ static int expand_inode_data(struct inode *inode, loff_t offset, loff_t len, int mode) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - struct f2fs_map_blocks map = { .m_next_pgofs = NULL }; + struct f2fs_map_blocks map = { .m_next_pgofs = NULL, + .m_next_extent = NULL, .m_seg_type = NO_CHECK_TYPE }; pgoff_t pg_end; loff_t new_size = i_size_read(inode); loff_t off_end; @@ -1836,14 +1855,20 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) switch (in) { case F2FS_GOING_DOWN_FULLSYNC: sb = freeze_bdev(sb->s_bdev); - if (sb && !IS_ERR(sb)) { + if (IS_ERR(sb)) { + ret = PTR_ERR(sb); + goto out; + } + if (sb) { f2fs_stop_checkpoint(sbi, false); thaw_bdev(sb->s_bdev, sb); } break; case F2FS_GOING_DOWN_METASYNC: /* do checkpoint only */ - f2fs_sync_fs(sb, 1); + ret = f2fs_sync_fs(sb, 1); + if (ret) + goto out; f2fs_stop_checkpoint(sbi, false); break; case F2FS_GOING_DOWN_NOSYNC: @@ -1857,6 +1882,13 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) ret = -EINVAL; goto out; } + + stop_gc_thread(sbi); + stop_discard_thread(sbi); + + drop_discard_cmd(sbi); + clear_opt(sbi, DISCARD); + f2fs_update_time(sbi, REQ_TIME); out: mnt_drop_write_file(filp); @@ -2068,9 +2100,10 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi, struct f2fs_defragment *range) { struct inode *inode = file_inode(filp); - struct f2fs_map_blocks map = { .m_next_pgofs = NULL }; + struct f2fs_map_blocks map = { .m_next_extent = NULL, + .m_seg_type = NO_CHECK_TYPE }; struct extent_info ei = {0,0,0}; - pgoff_t pg_start, pg_end; + pgoff_t pg_start, pg_end, next_pgofs; unsigned int blk_per_seg = sbi->blocks_per_seg; unsigned int total = 0, sec_num; block_t blk_end = 0; @@ -2078,7 +2111,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi, int err; /* if in-place-update policy is enabled, don't waste time here */ - if (need_inplace_update_policy(inode, NULL)) + if (should_update_inplace(inode, NULL)) return -EINVAL; pg_start = range->start >> PAGE_SHIFT; @@ -2104,6 +2137,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi, } map.m_lblk = pg_start; + map.m_next_pgofs = &next_pgofs; /* * lookup mapping info in dnode page cache, skip defragmenting if all @@ -2117,14 +2151,16 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi, goto out; if (!(map.m_flags & F2FS_MAP_FLAGS)) { - map.m_lblk++; + map.m_lblk = next_pgofs; continue; } - if (blk_end && blk_end != map.m_pblk) { + if (blk_end && blk_end != map.m_pblk) fragmented = true; - break; - } + + /* record total count of block that we're going to move */ + total += map.m_len; + blk_end = map.m_pblk + map.m_len; map.m_lblk += map.m_len; @@ -2133,10 +2169,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi, if (!fragmented) goto out; - map.m_lblk = pg_start; - map.m_len = pg_end - pg_start; - - sec_num = (map.m_len + BLKS_PER_SEC(sbi) - 1) / BLKS_PER_SEC(sbi); + sec_num = (total + BLKS_PER_SEC(sbi) - 1) / BLKS_PER_SEC(sbi); /* * make sure there are enough free section for LFS allocation, this can @@ -2148,6 +2181,10 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi, goto out; } + map.m_lblk = pg_start; + map.m_len = pg_end - pg_start; + total = 0; + while (map.m_lblk < pg_end) { pgoff_t idx; int cnt = 0; @@ -2159,7 +2196,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi, goto clear_out; if (!(map.m_flags & F2FS_MAP_FLAGS)) { - map.m_lblk++; + map.m_lblk = next_pgofs; continue; } @@ -2471,6 +2508,125 @@ static int f2fs_ioc_get_features(struct file *filp, unsigned long arg) return put_user(sb_feature, (u32 __user *)arg); } +int f2fs_pin_file_control(struct inode *inode, bool inc) +{ + struct f2fs_inode_info *fi = F2FS_I(inode); + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + + /* Use i_gc_failures for normal file as a risk signal. */ + if (inc) + f2fs_i_gc_failures_write(inode, fi->i_gc_failures + 1); + + if (fi->i_gc_failures > sbi->gc_pin_file_threshold) { + f2fs_msg(sbi->sb, KERN_WARNING, + "%s: Enable GC = ino %lx after %x GC trials\n", + __func__, inode->i_ino, fi->i_gc_failures); + clear_inode_flag(inode, FI_PIN_FILE); + return -EAGAIN; + } + return 0; +} + +static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg) +{ + struct inode *inode = file_inode(filp); + __u32 pin; + int ret = 0; + + if (!inode_owner_or_capable(inode)) + return -EACCES; + + if (get_user(pin, (__u32 __user *)arg)) + return -EFAULT; + + if (!S_ISREG(inode->i_mode)) + return -EINVAL; + + if (f2fs_readonly(F2FS_I_SB(inode)->sb)) + return -EROFS; + + ret = mnt_want_write_file(filp); + if (ret) + return ret; + + inode_lock(inode); + + if (should_update_outplace(inode, NULL)) { + ret = -EINVAL; + goto out; + } + + if (!pin) { + clear_inode_flag(inode, FI_PIN_FILE); + F2FS_I(inode)->i_gc_failures = 1; + goto done; + } + + if (f2fs_pin_file_control(inode, false)) { + ret = -EAGAIN; + goto out; + } + ret = f2fs_convert_inline_inode(inode); + if (ret) + goto out; + + set_inode_flag(inode, FI_PIN_FILE); + ret = F2FS_I(inode)->i_gc_failures; +done: + f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); +out: + inode_unlock(inode); + mnt_drop_write_file(filp); + return ret; +} + +static int f2fs_ioc_get_pin_file(struct file *filp, unsigned long arg) +{ + struct inode *inode = file_inode(filp); + __u32 pin = 0; + + if (is_inode_flag_set(inode, FI_PIN_FILE)) + pin = F2FS_I(inode)->i_gc_failures; + return put_user(pin, (u32 __user *)arg); +} + +int f2fs_precache_extents(struct inode *inode) +{ + struct f2fs_inode_info *fi = F2FS_I(inode); + struct f2fs_map_blocks map; + pgoff_t m_next_extent; + loff_t end; + int err; + + if (is_inode_flag_set(inode, FI_NO_EXTENT)) + return -EOPNOTSUPP; + + map.m_lblk = 0; + map.m_next_pgofs = NULL; + map.m_next_extent = &m_next_extent; + map.m_seg_type = NO_CHECK_TYPE; + end = F2FS_I_SB(inode)->max_file_blocks; + + while (map.m_lblk < end) { + map.m_len = end - map.m_lblk; + + down_write(&fi->dio_rwsem[WRITE]); + err = f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_PRECACHE); + up_write(&fi->dio_rwsem[WRITE]); + if (err) + return err; + + map.m_lblk = m_next_extent; + } + + return err; +} + +static int f2fs_ioc_precache_extents(struct file *filp, unsigned long arg) +{ + return f2fs_precache_extents(file_inode(filp)); +} + long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { if (unlikely(f2fs_cp_error(F2FS_I_SB(file_inode(filp))))) @@ -2517,6 +2673,12 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return f2fs_ioc_flush_device(filp, arg); case F2FS_IOC_GET_FEATURES: return f2fs_ioc_get_features(filp, arg); + case F2FS_IOC_GET_PIN_FILE: + return f2fs_ioc_get_pin_file(filp, arg); + case F2FS_IOC_SET_PIN_FILE: + return f2fs_ioc_set_pin_file(filp, arg); + case F2FS_IOC_PRECACHE_EXTENTS: + return f2fs_ioc_precache_extents(filp, arg); default: return -ENOTTY; } @@ -2598,6 +2760,9 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case F2FS_IOC_MOVE_RANGE: case F2FS_IOC_FLUSH_DEVICE: case F2FS_IOC_GET_FEATURES: + case F2FS_IOC_GET_PIN_FILE: + case F2FS_IOC_SET_PIN_FILE: + case F2FS_IOC_PRECACHE_EXTENTS: break; default: return -ENOIOCTLCMD; diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 5d5bba462f263..3b26aa19430b8 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -624,6 +624,11 @@ static void move_data_block(struct inode *inode, block_t bidx, if (f2fs_is_atomic_file(inode)) goto out; + if (f2fs_is_pinned_file(inode)) { + f2fs_pin_file_control(inode, true); + goto out; + } + set_new_dnode(&dn, inode, NULL, NULL, 0); err = get_dnode_of_data(&dn, bidx, LOOKUP_NODE); if (err) @@ -686,7 +691,12 @@ static void move_data_block(struct inode *inode, block_t bidx, fio.op = REQ_OP_WRITE; fio.op_flags = REQ_SYNC; fio.new_blkaddr = newaddr; - f2fs_submit_page_write(&fio); + err = f2fs_submit_page_write(&fio); + if (err) { + if (PageWriteback(fio.encrypted_page)) + end_page_writeback(fio.encrypted_page); + goto put_page_out; + } f2fs_update_iostat(fio.sbi, FS_GC_DATA_IO, F2FS_BLKSIZE); @@ -720,6 +730,11 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type, if (f2fs_is_atomic_file(inode)) goto out; + if (f2fs_is_pinned_file(inode)) { + if (gc_type == FG_GC) + f2fs_pin_file_control(inode, true); + goto out; + } if (gc_type == BG_GC) { if (PageWriteback(page)) @@ -1091,6 +1106,7 @@ void build_gc_manager(struct f2fs_sb_info *sbi) sbi->fggc_threshold = div64_u64((main_count - ovp_count) * BLKS_PER_SEC(sbi), (main_count - resv_count)); + sbi->gc_pin_file_threshold = DEF_GC_FAILED_PINNED_FILES; /* give warm/cold data area from slower device */ if (sbi->s_ndevs && sbi->segs_per_sec == 1) diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h index 9325191fab2d6..b0045d4c8d1e6 100644 --- a/fs/f2fs/gc.h +++ b/fs/f2fs/gc.h @@ -20,6 +20,8 @@ #define LIMIT_INVALID_BLOCK 40 /* percentage over total user space */ #define LIMIT_FREE_BLOCK 40 /* percentage over invalid + free space */ +#define DEF_GC_FAILED_PINNED_FILES 2048 + /* Search max. number of dirty segments to select a victim segment */ #define DEF_MAX_VICTIM_SEARCH 4096 /* covers 8GB */ diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 9eb3cc2486d4c..94ef24f3e3948 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -22,6 +22,9 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync) { + if (is_inode_flag_set(inode, FI_NEW_INODE)) + return; + if (f2fs_inode_dirtied(inode, sync)) return; @@ -275,6 +278,12 @@ static int do_read_inode(struct inode *inode) i_projid = F2FS_DEF_PROJID; fi->i_projid = make_kprojid(&init_user_ns, i_projid); + if (f2fs_has_extra_attr(inode) && f2fs_sb_has_inode_crtime(sbi->sb) && + F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_crtime)) { + fi->i_crtime.tv_sec = le64_to_cpu(ri->i_crtime); + fi->i_crtime.tv_nsec = le32_to_cpu(ri->i_crtime_nsec); + } + f2fs_put_page(node_page, 1); stat_inc_inline_xattr(inode); @@ -360,14 +369,15 @@ struct inode *f2fs_iget_retry(struct super_block *sb, unsigned long ino) return inode; } -int update_inode(struct inode *inode, struct page *node_page) +void update_inode(struct inode *inode, struct page *node_page) { struct f2fs_inode *ri; struct extent_tree *et = F2FS_I(inode)->extent_tree; - f2fs_inode_synced(inode); - f2fs_wait_on_page_writeback(node_page, NODE, true); + set_page_dirty(node_page); + + f2fs_inode_synced(inode); ri = F2FS_INODE(node_page); @@ -417,6 +427,15 @@ int update_inode(struct inode *inode, struct page *node_page) F2FS_I(inode)->i_projid); ri->i_projid = cpu_to_le32(i_projid); } + + if (f2fs_sb_has_inode_crtime(F2FS_I_SB(inode)->sb) && + F2FS_FITS_IN_INODE(ri, F2FS_I(inode)->i_extra_isize, + i_crtime)) { + ri->i_crtime = + cpu_to_le64(F2FS_I(inode)->i_crtime.tv_sec); + ri->i_crtime_nsec = + cpu_to_le32(F2FS_I(inode)->i_crtime.tv_nsec); + } } __set_inode_rdev(inode, ri); @@ -426,14 +445,12 @@ int update_inode(struct inode *inode, struct page *node_page) if (inode->i_nlink == 0) clear_inline_node(node_page); - return set_page_dirty(node_page); } -int update_inode_page(struct inode *inode) +void update_inode_page(struct inode *inode) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct page *node_page; - int ret = 0; retry: node_page = get_node_page(sbi, inode->i_ino); if (IS_ERR(node_page)) { @@ -444,11 +461,10 @@ int update_inode_page(struct inode *inode) } else if (err != -ENOENT) { f2fs_stop_checkpoint(sbi, false); } - return 0; + return; } - ret = update_inode(inode, node_page); + update_inode(inode, node_page); f2fs_put_page(node_page, 1); - return ret; } int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index eaf7476a09428..4f6adb7f0f313 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -51,7 +51,8 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) inode->i_ino = ino; inode->i_blocks = 0; - inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + inode->i_mtime = inode->i_atime = inode->i_ctime = + F2FS_I(inode)->i_crtime = current_time(inode); inode->i_generation = sbi->s_next_generation++; err = insert_inode_locked(inode); @@ -72,12 +73,12 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) if (err) goto fail_drop; + set_inode_flag(inode, FI_NEW_INODE); + /* If the directory encrypted, then we should encrypt the inode. */ if (f2fs_encrypted_inode(dir) && f2fs_may_encrypt(inode)) f2fs_set_encrypted_inode(inode); - set_inode_flag(inode, FI_NEW_INODE); - if (f2fs_sb_has_extra_attr(sbi->sb)) { set_inode_flag(inode, FI_EXTRA_ATTR); F2FS_I(inode)->i_extra_isize = F2FS_TOTAL_EXTRA_ATTR_SIZE; @@ -236,9 +237,9 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir, if (unlikely(f2fs_cp_error(sbi))) return -EIO; - if (f2fs_encrypted_inode(dir) && - !fscrypt_has_permitted_context(dir, inode)) - return -EPERM; + err = fscrypt_prepare_link(old_dentry, dir, dentry); + if (err) + return err; if (is_inode_flag_set(dir, FI_PROJ_INHERIT) && (!projid_eq(F2FS_I(dir)->i_projid, @@ -349,20 +350,9 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry, trace_f2fs_lookup_start(dir, dentry, flags); - if (f2fs_encrypted_inode(dir)) { - err = fscrypt_get_encryption_info(dir); - - /* - * DCACHE_ENCRYPTED_WITH_KEY is set if the dentry is - * created while the directory was encrypted and we - * don't have access to the key. - */ - if (fscrypt_has_encryption_key(dir)) - fscrypt_set_encrypted_dentry(dentry); - fscrypt_set_d_op(dentry); - if (err && err != -ENOKEY) - goto out; - } + err = fscrypt_prepare_lookup(dir, dentry, flags); + if (err) + goto out; if (dentry->d_name.len > F2FS_NAME_LEN) { err = -ENAMETOOLONG; @@ -538,7 +528,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, struct qstr istr = QSTR_INIT(symname, len); struct fscrypt_str ostr; - sd = kzalloc(disk_link.len, GFP_NOFS); + sd = f2fs_kzalloc(sbi, disk_link.len, GFP_NOFS); if (!sd) { err = -ENOMEM; goto err_out; @@ -790,18 +780,6 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, if (unlikely(f2fs_cp_error(sbi))) return -EIO; - if ((f2fs_encrypted_inode(old_dir) && - !fscrypt_has_encryption_key(old_dir)) || - (f2fs_encrypted_inode(new_dir) && - !fscrypt_has_encryption_key(new_dir))) - return -ENOKEY; - - if ((old_dir != new_dir) && f2fs_encrypted_inode(new_dir) && - !fscrypt_has_permitted_context(new_dir, old_inode)) { - err = -EPERM; - goto out; - } - if (is_inode_flag_set(new_dir, FI_PROJ_INHERIT) && (!projid_eq(F2FS_I(new_dir)->i_projid, F2FS_I(old_dentry->d_inode)->i_projid))) @@ -941,6 +919,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, } f2fs_i_links_write(old_dir, false); } + add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO); f2fs_unlock_op(sbi); @@ -985,18 +964,6 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, if (unlikely(f2fs_cp_error(sbi))) return -EIO; - if ((f2fs_encrypted_inode(old_dir) && - !fscrypt_has_encryption_key(old_dir)) || - (f2fs_encrypted_inode(new_dir) && - !fscrypt_has_encryption_key(new_dir))) - return -ENOKEY; - - if ((f2fs_encrypted_inode(old_dir) || f2fs_encrypted_inode(new_dir)) && - (old_dir != new_dir) && - (!fscrypt_has_permitted_context(new_dir, old_inode) || - !fscrypt_has_permitted_context(old_dir, new_inode))) - return -EPERM; - if ((is_inode_flag_set(new_dir, FI_PROJ_INHERIT) && !projid_eq(F2FS_I(new_dir)->i_projid, F2FS_I(old_dentry->d_inode)->i_projid)) || @@ -1103,6 +1070,9 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, } f2fs_mark_inode_dirty_sync(new_dir, false); + add_ino_entry(sbi, old_dir->i_ino, TRANS_DIR_INO); + add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO); + f2fs_unlock_op(sbi); if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) @@ -1132,9 +1102,16 @@ static int f2fs_rename2(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) { + int err; + if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT)) return -EINVAL; + err = fscrypt_prepare_rename(old_dir, old_dentry, new_dir, new_dentry, + flags); + if (err) + return err; + if (flags & RENAME_EXCHANGE) { return f2fs_cross_rename(old_dir, old_dentry, new_dir, new_dentry); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 57e86a43cbf29..1902530d50b42 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -143,11 +143,9 @@ static struct nat_entry *__alloc_nat_entry(nid_t nid, bool no_fail) struct nat_entry *new; if (no_fail) - new = f2fs_kmem_cache_alloc(nat_entry_slab, - GFP_NOFS | __GFP_ZERO); + new = f2fs_kmem_cache_alloc(nat_entry_slab, GFP_F2FS_ZERO); else - new = kmem_cache_alloc(nat_entry_slab, - GFP_NOFS | __GFP_ZERO); + new = kmem_cache_alloc(nat_entry_slab, GFP_F2FS_ZERO); if (new) { nat_set_nid(new, nid); nat_reset_flag(new); @@ -702,7 +700,6 @@ static void truncate_node(struct dnode_of_data *dn) struct node_info ni; get_node_info(sbi, dn->nid, &ni); - f2fs_bug_on(sbi, ni.blk_addr == NULL_ADDR); /* Deallocate node address */ invalidate_blocks(sbi, ni.blk_addr); @@ -1341,14 +1338,19 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, .encrypted_page = NULL, .submitted = false, .io_type = io_type, + .io_wbc = wbc, }; trace_f2fs_writepage(page, NODE); + if (unlikely(f2fs_cp_error(sbi))) { + dec_page_count(sbi, F2FS_DIRTY_NODES); + unlock_page(page); + return 0; + } + if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) goto redirty_out; - if (unlikely(f2fs_cp_error(sbi))) - goto redirty_out; /* get old block addr of this node page */ nid = nid_of_node(page); @@ -1593,12 +1595,6 @@ int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc, struct page *page = pvec.pages[i]; bool submitted = false; - if (unlikely(f2fs_cp_error(sbi))) { - pagevec_release(&pvec); - ret = -EIO; - goto out; - } - /* * flushing sequence with step: * 0. indirect nodes @@ -1668,9 +1664,12 @@ int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc, step++; goto next_step; } -out: + if (nwritten) f2fs_submit_merged_write(sbi, NODE); + + if (unlikely(f2fs_cp_error(sbi))) + return -EIO; return ret; } @@ -1835,8 +1834,33 @@ static void __move_free_nid(struct f2fs_sb_info *sbi, struct free_nid *i, } } +static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid, + bool set, bool build) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + unsigned int nat_ofs = NAT_BLOCK_OFFSET(nid); + unsigned int nid_ofs = nid - START_NID(nid); + + if (!test_bit_le(nat_ofs, nm_i->nat_block_bitmap)) + return; + + if (set) { + if (test_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs])) + return; + __set_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]); + nm_i->free_nid_count[nat_ofs]++; + } else { + if (!test_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs])) + return; + __clear_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]); + if (!build) + nm_i->free_nid_count[nat_ofs]--; + } +} + /* return if the nid is recognized as free */ -static bool add_free_nid(struct f2fs_sb_info *sbi, nid_t nid, bool build) +static bool add_free_nid(struct f2fs_sb_info *sbi, + nid_t nid, bool build, bool update) { struct f2fs_nm_info *nm_i = NM_I(sbi); struct free_nid *i, *e; @@ -1852,8 +1876,7 @@ static bool add_free_nid(struct f2fs_sb_info *sbi, nid_t nid, bool build) i->nid = nid; i->state = FREE_NID; - if (radix_tree_preload(GFP_NOFS)) - goto err; + radix_tree_preload(GFP_NOFS | __GFP_NOFAIL); spin_lock(&nm_i->nid_list_lock); @@ -1894,9 +1917,14 @@ static bool add_free_nid(struct f2fs_sb_info *sbi, nid_t nid, bool build) ret = true; err = __insert_free_nid(sbi, i, FREE_NID); err_out: + if (update) { + update_free_nid_bitmap(sbi, nid, ret, build); + if (!build) + nm_i->available_nids++; + } spin_unlock(&nm_i->nid_list_lock); radix_tree_preload_end(); -err: + if (err) kmem_cache_free(free_nid_slab, i); return ret; @@ -1920,30 +1948,6 @@ static void remove_free_nid(struct f2fs_sb_info *sbi, nid_t nid) kmem_cache_free(free_nid_slab, i); } -static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid, - bool set, bool build) -{ - struct f2fs_nm_info *nm_i = NM_I(sbi); - unsigned int nat_ofs = NAT_BLOCK_OFFSET(nid); - unsigned int nid_ofs = nid - START_NID(nid); - - if (!test_bit_le(nat_ofs, nm_i->nat_block_bitmap)) - return; - - if (set) { - if (test_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs])) - return; - __set_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]); - nm_i->free_nid_count[nat_ofs]++; - } else { - if (!test_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs])) - return; - __clear_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]); - if (!build) - nm_i->free_nid_count[nat_ofs]--; - } -} - static void scan_nat_page(struct f2fs_sb_info *sbi, struct page *nat_page, nid_t start_nid) { @@ -1953,26 +1957,23 @@ static void scan_nat_page(struct f2fs_sb_info *sbi, unsigned int nat_ofs = NAT_BLOCK_OFFSET(start_nid); int i; - if (test_bit_le(nat_ofs, nm_i->nat_block_bitmap)) - return; - __set_bit_le(nat_ofs, nm_i->nat_block_bitmap); i = start_nid % NAT_ENTRY_PER_BLOCK; for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) { - bool freed = false; - if (unlikely(start_nid >= nm_i->max_nid)) break; blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr); f2fs_bug_on(sbi, blk_addr == NEW_ADDR); - if (blk_addr == NULL_ADDR) - freed = add_free_nid(sbi, start_nid, true); - spin_lock(&NM_I(sbi)->nid_list_lock); - update_free_nid_bitmap(sbi, start_nid, freed, true); - spin_unlock(&NM_I(sbi)->nid_list_lock); + if (blk_addr == NULL_ADDR) { + add_free_nid(sbi, start_nid, true, true); + } else { + spin_lock(&NM_I(sbi)->nid_list_lock); + update_free_nid_bitmap(sbi, start_nid, false, true); + spin_unlock(&NM_I(sbi)->nid_list_lock); + } } } @@ -1990,7 +1991,7 @@ static void scan_curseg_cache(struct f2fs_sb_info *sbi) addr = le32_to_cpu(nat_in_journal(journal, i).block_addr); nid = le32_to_cpu(nid_in_journal(journal, i)); if (addr == NULL_ADDR) - add_free_nid(sbi, nid, true); + add_free_nid(sbi, nid, true, false); else remove_free_nid(sbi, nid); } @@ -2017,7 +2018,7 @@ static void scan_free_nid_bits(struct f2fs_sb_info *sbi) break; nid = i * NAT_ENTRY_PER_BLOCK + idx; - add_free_nid(sbi, nid, true); + add_free_nid(sbi, nid, true, false); if (nm_i->nid_cnt[FREE_NID] >= MAX_FREE_NIDS) goto out; @@ -2060,10 +2061,13 @@ static void __build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount) down_read(&nm_i->nat_tree_lock); while (1) { - struct page *page = get_current_nat_page(sbi, nid); + if (!test_bit_le(NAT_BLOCK_OFFSET(nid), + nm_i->nat_block_bitmap)) { + struct page *page = get_current_nat_page(sbi, nid); - scan_nat_page(sbi, page, nid); - f2fs_put_page(page, 1); + scan_nat_page(sbi, page, nid); + f2fs_put_page(page, 1); + } nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK)); if (unlikely(nid >= nm_i->max_nid)) @@ -2226,7 +2230,9 @@ void recover_inline_xattr(struct inode *inode, struct page *page) f2fs_bug_on(F2FS_I_SB(inode), IS_ERR(ipage)); ri = F2FS_INODE(page); - if (!(ri->i_inline & F2FS_INLINE_XATTR)) { + if (ri->i_inline & F2FS_INLINE_XATTR) { + set_inode_flag(inode, FI_INLINE_XATTR); + } else { clear_inode_flag(inode, FI_INLINE_XATTR); goto update_inode; } @@ -2242,7 +2248,7 @@ void recover_inline_xattr(struct inode *inode, struct page *page) f2fs_put_page(ipage, 1); } -int recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr) +int recover_xattr_data(struct inode *inode, struct page *page) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); nid_t prev_xnid = F2FS_I(inode)->i_xattr_nid; @@ -2256,7 +2262,6 @@ int recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr) /* 1: invalidate the previous xattr nid */ get_node_info(sbi, prev_xnid, &ni); - f2fs_bug_on(sbi, ni.blk_addr == NULL_ADDR); invalidate_blocks(sbi, ni.blk_addr); dec_valid_node_count(sbi, inode, false); set_node_addr(sbi, &ni, NULL_ADDR, false); @@ -2345,7 +2350,7 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) return 0; } -int restore_node_summary(struct f2fs_sb_info *sbi, +void restore_node_summary(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summary_block *sum) { struct f2fs_node *rn; @@ -2378,7 +2383,6 @@ int restore_node_summary(struct f2fs_sb_info *sbi, invalidate_mapping_pages(META_MAPPING(sbi), addr, addr + nrpages); } - return 0; } static void remove_nats_in_journal(struct f2fs_sb_info *sbi) @@ -2520,11 +2524,7 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, nat_reset_flag(ne); __clear_nat_cache_dirty(NM_I(sbi), set, ne); if (nat_get_blkaddr(ne) == NULL_ADDR) { - add_free_nid(sbi, nid, false); - spin_lock(&NM_I(sbi)->nid_list_lock); - NM_I(sbi)->available_nids++; - update_free_nid_bitmap(sbi, nid, true, false); - spin_unlock(&NM_I(sbi)->nid_list_lock); + add_free_nid(sbi, nid, false, true); } else { spin_lock(&NM_I(sbi)->nid_list_lock); update_free_nid_bitmap(sbi, nid, false, false); @@ -2605,8 +2605,8 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi) nm_i->nat_bits_blocks = F2FS_BYTES_TO_BLK((nat_bits_bytes << 1) + 8 + F2FS_BLKSIZE - 1); - nm_i->nat_bits = kzalloc(nm_i->nat_bits_blocks << F2FS_BLKSIZE_BITS, - GFP_KERNEL); + nm_i->nat_bits = f2fs_kzalloc(sbi, + nm_i->nat_bits_blocks << F2FS_BLKSIZE_BITS, GFP_KERNEL); if (!nm_i->nat_bits) return -ENOMEM; @@ -2684,7 +2684,7 @@ static int init_node_manager(struct f2fs_sb_info *sbi) /* not used nids: 0, node, meta, (and root counted as valid node) */ nm_i->available_nids = nm_i->max_nid - sbi->total_valid_node_count - - F2FS_RESERVED_NODE_NUM; + sbi->nquota_files - F2FS_RESERVED_NODE_NUM; nm_i->nid_cnt[FREE_NID] = 0; nm_i->nid_cnt[PREALLOC_NID] = 0; nm_i->nat_cnt = 0; @@ -2731,17 +2731,17 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi) { struct f2fs_nm_info *nm_i = NM_I(sbi); - nm_i->free_nid_bitmap = kvzalloc(nm_i->nat_blocks * + nm_i->free_nid_bitmap = f2fs_kvzalloc(sbi, nm_i->nat_blocks * NAT_ENTRY_BITMAP_SIZE, GFP_KERNEL); if (!nm_i->free_nid_bitmap) return -ENOMEM; - nm_i->nat_block_bitmap = kvzalloc(nm_i->nat_blocks / 8, + nm_i->nat_block_bitmap = f2fs_kvzalloc(sbi, nm_i->nat_blocks / 8, GFP_KERNEL); if (!nm_i->nat_block_bitmap) return -ENOMEM; - nm_i->free_nid_count = kvzalloc(nm_i->nat_blocks * + nm_i->free_nid_count = f2fs_kvzalloc(sbi, nm_i->nat_blocks * sizeof(unsigned short), GFP_KERNEL); if (!nm_i->free_nid_count) return -ENOMEM; @@ -2752,7 +2752,8 @@ int build_node_manager(struct f2fs_sb_info *sbi) { int err; - sbi->nm_info = kzalloc(sizeof(struct f2fs_nm_info), GFP_KERNEL); + sbi->nm_info = f2fs_kzalloc(sbi, sizeof(struct f2fs_nm_info), + GFP_KERNEL); if (!sbi->nm_info) return -ENOMEM; diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h index 0ee3e5ff49a30..081ef0d672bf5 100644 --- a/fs/f2fs/node.h +++ b/fs/f2fs/node.h @@ -305,6 +305,10 @@ static inline bool is_recoverable_dnode(struct page *page) struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_P_SB(page)); __u64 cp_ver = cur_cp_version(ckpt); + /* Don't care crc part, if fsck.f2fs sets it. */ + if (__is_set_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG)) + return (cp_ver << 32) == (cpver_of_node(page) << 32); + if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG)) cp_ver |= (cur_cp_crc(ckpt) << 32); diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 559904e9868fc..1010fc2118dc6 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -189,6 +189,20 @@ static int recover_dentry(struct inode *inode, struct page *ipage, return err; } +static void recover_inline_flags(struct inode *inode, struct f2fs_inode *ri) +{ + if (ri->i_inline & F2FS_PIN_FILE) + set_inode_flag(inode, FI_PIN_FILE); + else + clear_inode_flag(inode, FI_PIN_FILE); + if (ri->i_inline & F2FS_DATA_EXIST) + set_inode_flag(inode, FI_DATA_EXIST); + else + clear_inode_flag(inode, FI_DATA_EXIST); + if (!(ri->i_inline & F2FS_INLINE_DOTS)) + clear_inode_flag(inode, FI_INLINE_DOTS); +} + static void recover_inode(struct inode *inode, struct page *page) { struct f2fs_inode *raw = F2FS_INODE(page); @@ -205,13 +219,16 @@ static void recover_inode(struct inode *inode, struct page *page) F2FS_I(inode)->i_advise = raw->i_advise; + recover_inline_flags(inode, raw); + if (file_enc_name(inode)) name = ""; else name = F2FS_INODE(page)->i_name; - f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode: ino = %x, name = %s", - ino_of_node(page), name); + f2fs_msg(inode->i_sb, KERN_NOTICE, + "recover_inode: ino = %x, name = %s, inline = %x", + ino_of_node(page), name, raw->i_inline); } static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head, @@ -392,7 +409,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, } static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, - struct page *page, block_t blkaddr) + struct page *page) { struct dnode_of_data dn; struct node_info ni; @@ -403,7 +420,7 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, if (IS_INODE(page)) { recover_inline_xattr(inode, page); } else if (f2fs_has_xattr_block(ofs_of_node(page))) { - err = recover_xattr_data(inode, page, blkaddr); + err = recover_xattr_data(inode, page); if (!err) recovered++; goto out; @@ -556,7 +573,7 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list, break; } } - err = do_recover_data(sbi, entry->inode, page, blkaddr); + err = do_recover_data(sbi, entry->inode, page); if (err) { f2fs_put_page(page, 1); break; diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index c126195a993a2..f0d69e6e2650f 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -248,7 +248,11 @@ static int __revoke_inmem_pages(struct inode *inode, goto next; } get_node_info(sbi, dn.nid, &ni); - f2fs_replace_block(sbi, &dn, dn.data_blkaddr, + if (cur->old_addr == NEW_ADDR) { + invalidate_blocks(sbi, dn.data_blkaddr); + f2fs_update_data_blkaddr(&dn, NEW_ADDR); + } else + f2fs_replace_block(sbi, &dn, dn.data_blkaddr, cur->old_addr, ni.version, true, true); f2fs_put_dnode(&dn); } @@ -657,7 +661,7 @@ int create_flush_cmd_control(struct f2fs_sb_info *sbi) goto init_thread; } - fcc = kzalloc(sizeof(struct flush_cmd_control), GFP_KERNEL); + fcc = f2fs_kzalloc(sbi, sizeof(struct flush_cmd_control), GFP_KERNEL); if (!fcc) return -ENOMEM; atomic_set(&fcc->issued_flush, 0); @@ -966,7 +970,7 @@ static int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, return 0; } -void __check_sit_bitmap(struct f2fs_sb_info *sbi, +static void __check_sit_bitmap(struct f2fs_sb_info *sbi, block_t start, block_t end) { #ifdef CONFIG_F2FS_CHECK_FS @@ -1285,6 +1289,8 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi, pend_list = &dcc->pend_list[i]; mutex_lock(&dcc->cmd_lock); + if (list_empty(pend_list)) + goto next; f2fs_bug_on(sbi, !__check_rb_tree_consistence(sbi, &dcc->root)); blk_start_plug(&plug); list_for_each_entry_safe(dc, tmp, pend_list, list) { @@ -1303,6 +1309,7 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi, break; } blk_finish_plug(&plug); +next: mutex_unlock(&dcc->cmd_lock); if (iter >= dpolicy->max_requests) @@ -1337,6 +1344,11 @@ static bool __drop_discard_cmd(struct f2fs_sb_info *sbi) return dropped; } +void drop_discard_cmd(struct f2fs_sb_info *sbi) +{ + __drop_discard_cmd(sbi); +} + static unsigned int __wait_one_discard_bio(struct f2fs_sb_info *sbi, struct discard_cmd *dc) { @@ -1405,7 +1417,7 @@ static void __wait_all_discard_cmd(struct f2fs_sb_info *sbi, } /* This should be covered by global mutex, &sit_i->sentry_lock */ -void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr) +static void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr) { struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; struct discard_cmd *dc; @@ -1475,6 +1487,8 @@ static int issue_discard_thread(void *data) msecs_to_jiffies(wait_ms)); if (try_to_freeze()) continue; + if (f2fs_readonly(sbi->sb)) + continue; if (kthread_should_stop()) return 0; @@ -1784,25 +1798,20 @@ void init_discard_policy(struct discard_policy *dpolicy, dpolicy->sync = true; dpolicy->granularity = granularity; + dpolicy->max_requests = DEF_MAX_DISCARD_REQUEST; + dpolicy->io_aware_gran = MAX_PLIST_NUM; + if (discard_type == DPOLICY_BG) { dpolicy->min_interval = DEF_MIN_DISCARD_ISSUE_TIME; dpolicy->max_interval = DEF_MAX_DISCARD_ISSUE_TIME; - dpolicy->max_requests = DEF_MAX_DISCARD_REQUEST; - dpolicy->io_aware_gran = MAX_PLIST_NUM; dpolicy->io_aware = true; } else if (discard_type == DPOLICY_FORCE) { dpolicy->min_interval = DEF_MIN_DISCARD_ISSUE_TIME; dpolicy->max_interval = DEF_MAX_DISCARD_ISSUE_TIME; - dpolicy->max_requests = DEF_MAX_DISCARD_REQUEST; - dpolicy->io_aware_gran = MAX_PLIST_NUM; dpolicy->io_aware = true; } else if (discard_type == DPOLICY_FSTRIM) { - dpolicy->max_requests = DEF_MAX_DISCARD_REQUEST; - dpolicy->io_aware_gran = MAX_PLIST_NUM; dpolicy->io_aware = false; } else if (discard_type == DPOLICY_UMOUNT) { - dpolicy->max_requests = DEF_MAX_DISCARD_REQUEST; - dpolicy->io_aware_gran = MAX_PLIST_NUM; dpolicy->io_aware = false; } } @@ -1818,7 +1827,7 @@ static int create_discard_cmd_control(struct f2fs_sb_info *sbi) goto init_thread; } - dcc = kzalloc(sizeof(struct discard_cmd_control), GFP_KERNEL); + dcc = f2fs_kzalloc(sbi, sizeof(struct discard_cmd_control), GFP_KERNEL); if (!dcc) return -ENOMEM; @@ -2515,7 +2524,6 @@ static bool __has_curseg_space(struct f2fs_sb_info *sbi, int type) return false; } -#if 0 int rw_hint_to_seg_type(enum rw_hint hint) { switch (hint) { @@ -2527,7 +2535,6 @@ int rw_hint_to_seg_type(enum rw_hint hint) return CURSEG_WARM_DATA; } } -#endif static int __get_segment_type_2(struct f2fs_io_info *fio) { @@ -2824,6 +2831,7 @@ void __f2fs_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, } } + f2fs_bug_on(sbi, !IS_DATASEG(type)); curseg = CURSEG_I(sbi, type); mutex_lock(&curseg->curseg_mutex); @@ -2908,7 +2916,7 @@ void f2fs_wait_on_block_writeback(struct f2fs_sb_info *sbi, block_t blkaddr) } } -static int read_compacted_summaries(struct f2fs_sb_info *sbi) +static void read_compacted_summaries(struct f2fs_sb_info *sbi) { struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); struct curseg_info *seg_i; @@ -2965,7 +2973,6 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi) } } f2fs_put_page(page, 1); - return 0; } static int read_normal_summaries(struct f2fs_sb_info *sbi, int type) @@ -3011,13 +3018,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type) ns->ofs_in_node = 0; } } else { - int err; - - err = restore_node_summary(sbi, segno, sum); - if (err) { - f2fs_put_page(new, 1); - return err; - } + restore_node_summary(sbi, segno, sum); } } @@ -3056,8 +3057,7 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi) META_CP, true); /* restore for compacted data summary */ - if (read_compacted_summaries(sbi)) - return -EINVAL; + read_compacted_summaries(sbi); type = CURSEG_HOT_NODE; } @@ -3193,28 +3193,19 @@ static struct page *get_next_sit_page(struct f2fs_sb_info *sbi, unsigned int start) { struct sit_info *sit_i = SIT_I(sbi); - struct page *src_page, *dst_page; + struct page *page; pgoff_t src_off, dst_off; - void *src_addr, *dst_addr; src_off = current_sit_addr(sbi, start); dst_off = next_sit_addr(sbi, src_off); - /* get current sit block page without lock */ - src_page = get_meta_page(sbi, src_off); - dst_page = grab_meta_page(sbi, dst_off); - f2fs_bug_on(sbi, PageDirty(src_page)); - - src_addr = page_address(src_page); - dst_addr = page_address(dst_page); - memcpy(dst_addr, src_addr, PAGE_SIZE); - - set_page_dirty(dst_page); - f2fs_put_page(src_page, 1); + page = grab_meta_page(sbi, dst_off); + seg_info_to_sit_page(sbi, page, start); + set_page_dirty(page); set_to_next_sit(sit_i, start); - return dst_page; + return page; } static struct sit_entry_set *grab_sit_entry_set(void) @@ -3423,52 +3414,54 @@ static int build_sit_info(struct f2fs_sb_info *sbi) unsigned int bitmap_size; /* allocate memory for SIT information */ - sit_i = kzalloc(sizeof(struct sit_info), GFP_KERNEL); + sit_i = f2fs_kzalloc(sbi, sizeof(struct sit_info), GFP_KERNEL); if (!sit_i) return -ENOMEM; SM_I(sbi)->sit_info = sit_i; - sit_i->sentries = kvzalloc(MAIN_SEGS(sbi) * + sit_i->sentries = f2fs_kvzalloc(sbi, MAIN_SEGS(sbi) * sizeof(struct seg_entry), GFP_KERNEL); if (!sit_i->sentries) return -ENOMEM; bitmap_size = f2fs_bitmap_size(MAIN_SEGS(sbi)); - sit_i->dirty_sentries_bitmap = kvzalloc(bitmap_size, GFP_KERNEL); + sit_i->dirty_sentries_bitmap = f2fs_kvzalloc(sbi, bitmap_size, + GFP_KERNEL); if (!sit_i->dirty_sentries_bitmap) return -ENOMEM; for (start = 0; start < MAIN_SEGS(sbi); start++) { sit_i->sentries[start].cur_valid_map - = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); + = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); sit_i->sentries[start].ckpt_valid_map - = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); + = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); if (!sit_i->sentries[start].cur_valid_map || !sit_i->sentries[start].ckpt_valid_map) return -ENOMEM; #ifdef CONFIG_F2FS_CHECK_FS sit_i->sentries[start].cur_valid_map_mir - = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); + = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); if (!sit_i->sentries[start].cur_valid_map_mir) return -ENOMEM; #endif if (f2fs_discard_en(sbi)) { sit_i->sentries[start].discard_map - = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); + = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, + GFP_KERNEL); if (!sit_i->sentries[start].discard_map) return -ENOMEM; } } - sit_i->tmp_map = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); + sit_i->tmp_map = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); if (!sit_i->tmp_map) return -ENOMEM; if (sbi->segs_per_sec > 1) { - sit_i->sec_entries = kvzalloc(MAIN_SECS(sbi) * + sit_i->sec_entries = f2fs_kvzalloc(sbi, MAIN_SECS(sbi) * sizeof(struct sec_entry), GFP_KERNEL); if (!sit_i->sec_entries) return -ENOMEM; @@ -3512,19 +3505,19 @@ static int build_free_segmap(struct f2fs_sb_info *sbi) unsigned int bitmap_size, sec_bitmap_size; /* allocate memory for free segmap information */ - free_i = kzalloc(sizeof(struct free_segmap_info), GFP_KERNEL); + free_i = f2fs_kzalloc(sbi, sizeof(struct free_segmap_info), GFP_KERNEL); if (!free_i) return -ENOMEM; SM_I(sbi)->free_info = free_i; bitmap_size = f2fs_bitmap_size(MAIN_SEGS(sbi)); - free_i->free_segmap = kvmalloc(bitmap_size, GFP_KERNEL); + free_i->free_segmap = f2fs_kvmalloc(sbi, bitmap_size, GFP_KERNEL); if (!free_i->free_segmap) return -ENOMEM; sec_bitmap_size = f2fs_bitmap_size(MAIN_SECS(sbi)); - free_i->free_secmap = kvmalloc(sec_bitmap_size, GFP_KERNEL); + free_i->free_secmap = f2fs_kvmalloc(sbi, sec_bitmap_size, GFP_KERNEL); if (!free_i->free_secmap) return -ENOMEM; @@ -3545,7 +3538,7 @@ static int build_curseg(struct f2fs_sb_info *sbi) struct curseg_info *array; int i; - array = kcalloc(NR_CURSEG_TYPE, sizeof(*array), GFP_KERNEL); + array = f2fs_kzalloc(sbi, sizeof(*array) * NR_CURSEG_TYPE, GFP_KERNEL); if (!array) return -ENOMEM; @@ -3553,12 +3546,12 @@ static int build_curseg(struct f2fs_sb_info *sbi) for (i = 0; i < NR_CURSEG_TYPE; i++) { mutex_init(&array[i].curseg_mutex); - array[i].sum_blk = kzalloc(PAGE_SIZE, GFP_KERNEL); + array[i].sum_blk = f2fs_kzalloc(sbi, PAGE_SIZE, GFP_KERNEL); if (!array[i].sum_blk) return -ENOMEM; init_rwsem(&array[i].journal_rwsem); - array[i].journal = kzalloc(sizeof(struct f2fs_journal), - GFP_KERNEL); + array[i].journal = f2fs_kzalloc(sbi, + sizeof(struct f2fs_journal), GFP_KERNEL); if (!array[i].journal) return -ENOMEM; array[i].segno = NULL_SEGNO; @@ -3567,7 +3560,7 @@ static int build_curseg(struct f2fs_sb_info *sbi) return restore_curseg_summaries(sbi); } -static void build_sit_entries(struct f2fs_sb_info *sbi) +static int build_sit_entries(struct f2fs_sb_info *sbi) { struct sit_info *sit_i = SIT_I(sbi); struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); @@ -3577,6 +3570,7 @@ static void build_sit_entries(struct f2fs_sb_info *sbi) int sit_blk_cnt = SIT_BLK_CNT(sbi); unsigned int i, start, end; unsigned int readed, start_blk = 0; + int err = 0; do { readed = ra_meta_pages(sbi, start_blk, BIO_MAX_PAGES, @@ -3595,7 +3589,9 @@ static void build_sit_entries(struct f2fs_sb_info *sbi) sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)]; f2fs_put_page(page, 1); - check_block_count(sbi, start, &sit); + err = check_block_count(sbi, start, &sit); + if (err) + return err; seg_info_from_raw_sit(se, &sit); /* build discard map only one time */ @@ -3630,7 +3626,9 @@ static void build_sit_entries(struct f2fs_sb_info *sbi) old_valid_blocks = se->valid_blocks; - check_block_count(sbi, start, &sit); + err = check_block_count(sbi, start, &sit); + if (err) + break; seg_info_from_raw_sit(se, &sit); if (f2fs_discard_en(sbi)) { @@ -3650,6 +3648,7 @@ static void build_sit_entries(struct f2fs_sb_info *sbi) se->valid_blocks - old_valid_blocks; } up_read(&curseg->journal_rwsem); + return err; } static void init_free_segmap(struct f2fs_sb_info *sbi) @@ -3704,7 +3703,7 @@ static int init_victim_secmap(struct f2fs_sb_info *sbi) struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); unsigned int bitmap_size = f2fs_bitmap_size(MAIN_SECS(sbi)); - dirty_i->victim_secmap = kvzalloc(bitmap_size, GFP_KERNEL); + dirty_i->victim_secmap = f2fs_kvzalloc(sbi, bitmap_size, GFP_KERNEL); if (!dirty_i->victim_secmap) return -ENOMEM; return 0; @@ -3716,7 +3715,8 @@ static int build_dirty_segmap(struct f2fs_sb_info *sbi) unsigned int bitmap_size, i; /* allocate memory for dirty segments list information */ - dirty_i = kzalloc(sizeof(struct dirty_seglist_info), GFP_KERNEL); + dirty_i = f2fs_kzalloc(sbi, sizeof(struct dirty_seglist_info), + GFP_KERNEL); if (!dirty_i) return -ENOMEM; @@ -3726,7 +3726,8 @@ static int build_dirty_segmap(struct f2fs_sb_info *sbi) bitmap_size = f2fs_bitmap_size(MAIN_SEGS(sbi)); for (i = 0; i < NR_DIRTY_TYPE; i++) { - dirty_i->dirty_segmap[i] = kvzalloc(bitmap_size, GFP_KERNEL); + dirty_i->dirty_segmap[i] = f2fs_kvzalloc(sbi, bitmap_size, + GFP_KERNEL); if (!dirty_i->dirty_segmap[i]) return -ENOMEM; } @@ -3770,7 +3771,7 @@ int build_segment_manager(struct f2fs_sb_info *sbi) struct f2fs_sm_info *sm_info; int err; - sm_info = kzalloc(sizeof(struct f2fs_sm_info), GFP_KERNEL); + sm_info = f2fs_kzalloc(sbi, sizeof(struct f2fs_sm_info), GFP_KERNEL); if (!sm_info) return -ENOMEM; @@ -3822,7 +3823,9 @@ int build_segment_manager(struct f2fs_sb_info *sbi) return err; /* reinit free segmap based on SIT */ - build_sit_entries(sbi); + err = build_sit_entries(sbi); + if (err) + return err; init_free_segmap(sbi); err = build_dirty_segmap(sbi); diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 806e7b7866df0..87b4ca0c60dad 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -347,16 +347,41 @@ static inline void seg_info_from_raw_sit(struct seg_entry *se, se->mtime = le64_to_cpu(rs->mtime); } -static inline void seg_info_to_raw_sit(struct seg_entry *se, +static inline void __seg_info_to_raw_sit(struct seg_entry *se, struct f2fs_sit_entry *rs) { unsigned short raw_vblocks = (se->type << SIT_VBLOCKS_SHIFT) | se->valid_blocks; rs->vblocks = cpu_to_le16(raw_vblocks); memcpy(rs->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE); + rs->mtime = cpu_to_le64(se->mtime); +} + +static inline void seg_info_to_sit_page(struct f2fs_sb_info *sbi, + struct page *page, unsigned int start) +{ + struct f2fs_sit_block *raw_sit; + struct seg_entry *se; + struct f2fs_sit_entry *rs; + unsigned int end = min(start + SIT_ENTRY_PER_BLOCK, + (unsigned long)MAIN_SEGS(sbi)); + int i; + + raw_sit = (struct f2fs_sit_block *)page_address(page); + for (i = 0; i < end - start; i++) { + rs = &raw_sit->entries[i]; + se = get_seg_entry(sbi, start + i); + __seg_info_to_raw_sit(se, rs); + } +} + +static inline void seg_info_to_raw_sit(struct seg_entry *se, + struct f2fs_sit_entry *rs) +{ + __seg_info_to_raw_sit(se, rs); + memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE); se->ckpt_valid_blocks = se->valid_blocks; - rs->mtime = cpu_to_le64(se->mtime); } static inline unsigned int find_next_inuse(struct free_segmap_info *free_i, @@ -579,47 +604,6 @@ enum { F2FS_IPU_ASYNC, }; -static inline bool need_inplace_update_policy(struct inode *inode, - struct f2fs_io_info *fio) -{ - struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - unsigned int policy = SM_I(sbi)->ipu_policy; - - if (test_opt(sbi, LFS)) - return false; - - /* if this is cold file, we should overwrite to avoid fragmentation */ - if (file_is_cold(inode)) - return true; - - if (policy & (0x1 << F2FS_IPU_FORCE)) - return true; - if (policy & (0x1 << F2FS_IPU_SSR) && need_SSR(sbi)) - return true; - if (policy & (0x1 << F2FS_IPU_UTIL) && - utilization(sbi) > SM_I(sbi)->min_ipu_util) - return true; - if (policy & (0x1 << F2FS_IPU_SSR_UTIL) && need_SSR(sbi) && - utilization(sbi) > SM_I(sbi)->min_ipu_util) - return true; - - /* - * IPU for rewrite async pages - */ - if (policy & (0x1 << F2FS_IPU_ASYNC) && - fio && fio->op == REQ_OP_WRITE && - !(fio->op_flags & REQ_SYNC) && - !f2fs_encrypted_inode(inode)) - return true; - - /* this is only set during fdatasync */ - if (policy & (0x1 << F2FS_IPU_FSYNC) && - is_inode_flag_set(inode, FI_NEED_IPU)) - return true; - - return false; -} - static inline unsigned int curseg_segno(struct f2fs_sb_info *sbi, int type) { @@ -654,7 +638,7 @@ static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr) /* * Summary block is always treated as an invalid block */ -static inline void check_block_count(struct f2fs_sb_info *sbi, +static inline int check_block_count(struct f2fs_sb_info *sbi, int segno, struct f2fs_sit_entry *raw_sit) { #ifdef CONFIG_F2FS_CHECK_FS @@ -676,11 +660,25 @@ static inline void check_block_count(struct f2fs_sb_info *sbi, cur_pos = next_pos; is_valid = !is_valid; } while (cur_pos < sbi->blocks_per_seg); - BUG_ON(GET_SIT_VBLOCKS(raw_sit) != valid_blocks); + + if (unlikely(GET_SIT_VBLOCKS(raw_sit) != valid_blocks)) { + f2fs_msg(sbi->sb, KERN_ERR, + "Mismatch valid blocks %d vs. %d", + GET_SIT_VBLOCKS(raw_sit), valid_blocks); + set_sbi_flag(sbi, SBI_NEED_FSCK); + return -EINVAL; + } #endif /* check segment usage, and check boundary of a given segment number */ - f2fs_bug_on(sbi, GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg - || segno > TOTAL_SEGS(sbi) - 1); + if (unlikely(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg + || segno > TOTAL_SEGS(sbi) - 1)) { + f2fs_msg(sbi->sb, KERN_ERR, + "Wrong valid blocks %d or segno %u", + GET_SIT_VBLOCKS(raw_sit), segno); + set_sbi_flag(sbi, SBI_NEED_FSCK); + return -EINVAL; + } + return 0; } static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi, diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 114ee51b87d75..5f8e5f2249e97 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -46,6 +46,7 @@ static struct kmem_cache *f2fs_inode_cachep; char *fault_name[FAULT_MAX] = { [FAULT_KMALLOC] = "kmalloc", + [FAULT_KVMALLOC] = "kvmalloc", [FAULT_PAGE_ALLOC] = "page alloc", [FAULT_PAGE_GET] = "page get", [FAULT_ALLOC_BIO] = "alloc bio", @@ -109,6 +110,9 @@ enum { Opt_noextent_cache, Opt_noinline_data, Opt_data_flush, + Opt_reserve_root, + Opt_resgid, + Opt_resuid, Opt_mode, Opt_io_size_bits, Opt_fault_injection, @@ -159,6 +163,9 @@ static match_table_t f2fs_tokens = { {Opt_noextent_cache, "noextent_cache"}, {Opt_noinline_data, "noinline_data"}, {Opt_data_flush, "data_flush"}, + {Opt_reserve_root, "reserve_root=%u"}, + {Opt_resgid, "resgid=%u"}, + {Opt_resuid, "resuid=%u"}, {Opt_mode, "mode=%s"}, {Opt_io_size_bits, "io_bits=%u"}, {Opt_fault_injection, "fault_injection=%u"}, @@ -193,6 +200,28 @@ void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...) va_end(args); } +static inline void limit_reserve_root(struct f2fs_sb_info *sbi) +{ + block_t limit = (sbi->user_block_count << 1) / 1000; + + /* limit is 0.2% */ + if (test_opt(sbi, RESERVE_ROOT) && sbi->root_reserved_blocks > limit) { + sbi->root_reserved_blocks = limit; + f2fs_msg(sbi->sb, KERN_INFO, + "Reduce reserved blocks for root = %u", + sbi->root_reserved_blocks); + } + if (!test_opt(sbi, RESERVE_ROOT) && + (!uid_eq(sbi->s_resuid, + make_kuid(&init_user_ns, F2FS_DEF_RESUID)) || + !gid_eq(sbi->s_resgid, + make_kgid(&init_user_ns, F2FS_DEF_RESGID)))) + f2fs_msg(sbi->sb, KERN_INFO, + "Ignore s_resuid=%u, s_resgid=%u w/o reserve_root", + from_kuid_munged(&init_user_ns, sbi->s_resuid), + from_kgid_munged(&init_user_ns, sbi->s_resgid)); +} + static void init_once(void *foo) { struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo; @@ -331,6 +360,8 @@ static int parse_options(struct super_block *sb, char *options) substring_t args[MAX_OPT_ARGS]; char *p, *name; int arg = 0; + kuid_t uid; + kgid_t gid; #ifdef CONFIG_QUOTA int ret; #endif @@ -498,6 +529,40 @@ static int parse_options(struct super_block *sb, char *options) case Opt_data_flush: set_opt(sbi, DATA_FLUSH); break; + case Opt_reserve_root: + if (args->from && match_int(args, &arg)) + return -EINVAL; + if (test_opt(sbi, RESERVE_ROOT)) { + f2fs_msg(sb, KERN_INFO, + "Preserve previous reserve_root=%u", + sbi->root_reserved_blocks); + } else { + sbi->root_reserved_blocks = arg; + set_opt(sbi, RESERVE_ROOT); + } + break; + case Opt_resuid: + if (args->from && match_int(args, &arg)) + return -EINVAL; + uid = make_kuid(current_user_ns(), arg); + if (!uid_valid(uid)) { + f2fs_msg(sb, KERN_ERR, + "Invalid uid value %d", arg); + return -EINVAL; + } + sbi->s_resuid = uid; + break; + case Opt_resgid: + if (args->from && match_int(args, &arg)) + return -EINVAL; + gid = make_kgid(current_user_ns(), arg); + if (!gid_valid(gid)) { + f2fs_msg(sb, KERN_ERR, + "Invalid gid value %d", arg); + return -EINVAL; + } + sbi->s_resgid = gid; + break; case Opt_mode: name = match_strdup(&args[0]); @@ -1009,22 +1074,25 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf) struct super_block *sb = dentry->d_sb; struct f2fs_sb_info *sbi = F2FS_SB(sb); u64 id = huge_encode_dev(sb->s_bdev->bd_dev); - block_t total_count, user_block_count, start_count, ovp_count; + block_t total_count, user_block_count, start_count; u64 avail_node_count; total_count = le64_to_cpu(sbi->raw_super->block_count); user_block_count = sbi->user_block_count; start_count = le32_to_cpu(sbi->raw_super->segment0_blkaddr); - ovp_count = SM_I(sbi)->ovp_segments << sbi->log_blocks_per_seg; buf->f_type = F2FS_SUPER_MAGIC; buf->f_bsize = sbi->blocksize; buf->f_blocks = total_count - start_count; - buf->f_bfree = user_block_count - valid_user_blocks(sbi) + ovp_count; - buf->f_bavail = user_block_count - valid_user_blocks(sbi) - + buf->f_bfree = user_block_count - valid_user_blocks(sbi) - sbi->current_reserved_blocks; + if (buf->f_bfree > sbi->root_reserved_blocks) + buf->f_bavail = buf->f_bfree - sbi->root_reserved_blocks; + else + buf->f_bavail = 0; - avail_node_count = sbi->total_node_count - F2FS_RESERVED_NODE_NUM; + avail_node_count = sbi->total_node_count - sbi->nquota_files - + F2FS_RESERVED_NODE_NUM; if (avail_node_count > user_block_count) { buf->f_files = user_block_count; @@ -1150,6 +1218,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) else if (test_opt(sbi, LFS)) seq_puts(seq, "lfs"); seq_printf(seq, ",active_logs=%u", sbi->active_logs); + if (test_opt(sbi, RESERVE_ROOT)) + seq_printf(seq, ",reserve_root=%u,resuid=%u,resgid=%u", + sbi->root_reserved_blocks, + from_kuid_munged(&init_user_ns, sbi->s_resuid), + from_kgid_munged(&init_user_ns, sbi->s_resgid)); if (F2FS_IO_SIZE_BITS(sbi)) seq_printf(seq, ",io_size=%uKB", F2FS_IO_SIZE_KB(sbi)); #ifdef CONFIG_F2FS_FAULT_INJECTION @@ -1279,7 +1352,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) err = dquot_suspend(sb, -1); if (err < 0) goto restore_opts; - } else { + } else if (f2fs_readonly(sb) && !(*flags & MS_RDONLY)) { /* dquot_resume needs RW */ sb->s_flags &= ~MS_RDONLY; if (sb_any_quota_suspended(sb)) { @@ -1348,6 +1421,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0); + limit_reserve_root(sbi); return 0; restore_gc: if (need_restart_gc) { @@ -1696,11 +1770,13 @@ void f2fs_quota_off_umount(struct super_block *sb) f2fs_quota_off(sb, type); } -int f2fs_get_projid(struct inode *inode, kprojid_t *projid) +#if 0 /* not support */ +static int f2fs_get_projid(struct inode *inode, kprojid_t *projid) { *projid = F2FS_I(inode)->i_projid; return 0; } +#endif static const struct dquot_operations f2fs_quota_operations = { .get_reserved_space = f2fs_get_reserved_space, @@ -2206,14 +2282,15 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi) if (nr_sectors & (bdev_zone_sectors(bdev) - 1)) FDEV(devi).nr_blkz++; - FDEV(devi).blkz_type = kmalloc(FDEV(devi).nr_blkz, GFP_KERNEL); + FDEV(devi).blkz_type = f2fs_kmalloc(sbi, FDEV(devi).nr_blkz, + GFP_KERNEL); if (!FDEV(devi).blkz_type) return -ENOMEM; #define F2FS_REPORT_NR_ZONES 4096 - zones = kcalloc(F2FS_REPORT_NR_ZONES, sizeof(struct blk_zone), - GFP_KERNEL); + zones = f2fs_kzalloc(sbi, sizeof(struct blk_zone) * + F2FS_REPORT_NR_ZONES, GFP_KERNEL); if (!zones) return -ENOMEM; @@ -2357,8 +2434,8 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi) * Initialize multiple devices information, or single * zoned block device information. */ - sbi->devs = kcalloc(max_devices, sizeof(struct f2fs_dev_info), - GFP_KERNEL); + sbi->devs = f2fs_kzalloc(sbi, sizeof(struct f2fs_dev_info) * + max_devices, GFP_KERNEL); if (!sbi->devs) return -ENOMEM; @@ -2481,6 +2558,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sb->s_fs_info = sbi; sbi->raw_super = raw_super; + sbi->s_resuid = make_kuid(&init_user_ns, F2FS_DEF_RESUID); + sbi->s_resgid = make_kgid(&init_user_ns, F2FS_DEF_RESGID); + /* precompute checksum seed for metadata */ if (f2fs_sb_has_inode_chksum(sb)) sbi->s_chksum_seed = f2fs_chksum(sbi, ~0, raw_super->uuid, @@ -2525,6 +2605,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sb->s_qcop = &f2fs_quotactl_ops; #if 0 /* not support */ sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ; + + if (f2fs_sb_has_quota_ino(sbi->sb)) { + for (i = 0; i < MAXQUOTAS; i++) { + if (f2fs_qf_ino(sbi->sb, i)) + sbi->nquota_files++; + } + } #endif #endif @@ -2539,6 +2626,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0); memcpy(sb->s_uuid, raw_super->uuid, sizeof(raw_super->uuid)); + /* FIXME: no cgroup support */ + /* sb->s_iflags |= SB_I_CGROUPWB; */ /* init f2fs-specific super block info */ sbi->valid_super_block = valid_super_block; @@ -2559,8 +2648,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) int n = (i == META) ? 1: NR_TEMP_TYPE; int j; - sbi->write_io[i] = kmalloc(n * sizeof(struct f2fs_bio_info), - GFP_KERNEL); + sbi->write_io[i] = f2fs_kmalloc(sbi, + n * sizeof(struct f2fs_bio_info), + GFP_KERNEL); if (!sbi->write_io[i]) { err = -ENOMEM; goto free_options; @@ -2581,14 +2671,14 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) err = init_percpu_info(sbi); if (err) - goto free_options; + goto free_bio_info; if (F2FS_IO_SIZE(sbi) > 1) { sbi->write_io_dummy = mempool_create_page_pool(2 * (F2FS_IO_SIZE(sbi) - 1), 0); if (!sbi->write_io_dummy) { err = -ENOMEM; - goto free_options; + goto free_percpu; } } @@ -2623,6 +2713,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sbi->last_valid_block_count = sbi->total_valid_block_count; sbi->reserved_blocks = 0; sbi->current_reserved_blocks = 0; + limit_reserve_root(sbi); for (i = 0; i < NR_INODE_TYPE; i++) { INIT_LIST_HEAD(&sbi->inode_list[i]); @@ -2668,18 +2759,16 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) goto free_nm; } - f2fs_join_shrinker(sbi); - err = f2fs_build_stats(sbi); if (err) - goto free_nm; + goto free_node_inode; /* read root inode and dentry */ root = f2fs_iget(sb, F2FS_ROOT_INO(sbi)); if (IS_ERR(root)) { f2fs_msg(sb, KERN_ERR, "Failed to read root inode"); err = PTR_ERR(root); - goto free_node_inode; + goto free_stats; } if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { iput(root); @@ -2775,6 +2864,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sbi->valid_super_block ? 1 : 2, err); } + f2fs_join_shrinker(sbi); + f2fs_msg(sbi->sb, KERN_NOTICE, "Mounted with checkpoint version = %llx", cur_cp_version(F2FS_CKPT(sbi))); f2fs_update_time(sbi, CP_TIME); @@ -2801,14 +2892,12 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) free_root_inode: dput(sb->s_root); sb->s_root = NULL; +free_stats: + f2fs_destroy_stats(sbi); free_node_inode: - truncate_inode_pages_final(NODE_MAPPING(sbi)); - mutex_lock(&sbi->umount_mutex); release_ino_entry(sbi, true); - f2fs_leave_shrinker(sbi); + truncate_inode_pages_final(NODE_MAPPING(sbi)); iput(sbi->node_inode); - mutex_unlock(&sbi->umount_mutex); - f2fs_destroy_stats(sbi); free_nm: destroy_node_manager(sbi); free_sm: @@ -2822,10 +2911,12 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) free_io_dummy: if (sbi->write_io_dummy) mempool_destroy(sbi->write_io_dummy); -free_options: +free_percpu: + destroy_percpu_info(sbi); +free_bio_info: for (i = 0; i < NR_PAGE_TYPE; i++) kfree(sbi->write_io[i]); - destroy_percpu_info(sbi); +free_options: #ifdef CONFIG_QUOTA for (i = 0; i < F2FS_MAXQUOTAS; i++) kfree(sbi->s_qf_names[i]); diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 5c14bcaa19a45..6485a049e7576 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -113,6 +113,9 @@ static ssize_t features_show(struct f2fs_attr *a, if (f2fs_sb_has_quota_ino(sb)) len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", len ? ", " : "", "quota_ino"); + if (f2fs_sb_has_inode_crtime(sb)) + len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", + len ? ", " : "", "inode_crtime"); len += snprintf(buf + len, PAGE_SIZE - len, "\n"); return len; } @@ -162,7 +165,8 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a, #endif if (a->struct_type == RESERVED_BLOCKS) { spin_lock(&sbi->stat_lock); - if (t > (unsigned long)sbi->user_block_count) { + if (t > (unsigned long)(sbi->user_block_count - + sbi->root_reserved_blocks)) { spin_unlock(&sbi->stat_lock); return -EINVAL; } @@ -231,6 +235,7 @@ enum feat_id { FEAT_INODE_CHECKSUM, FEAT_FLEXIBLE_INLINE_XATTR, FEAT_QUOTA_INO, + FEAT_INODE_CRTIME, }; static ssize_t f2fs_feature_show(struct f2fs_attr *a, @@ -245,6 +250,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a, case FEAT_INODE_CHECKSUM: case FEAT_FLEXIBLE_INLINE_XATTR: case FEAT_QUOTA_INO: + case FEAT_INODE_CRTIME: return snprintf(buf, PAGE_SIZE, "supported\n"); } return 0; @@ -299,6 +305,8 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable); +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, readdir_ra, readdir_ra); +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_pin_file_thresh, gc_pin_file_threshold); #ifdef CONFIG_F2FS_FAULT_INJECTION F2FS_RW_ATTR(FAULT_INFO_RATE, f2fs_fault_info, inject_rate, inject_rate); F2FS_RW_ATTR(FAULT_INFO_TYPE, f2fs_fault_info, inject_type, inject_type); @@ -320,6 +328,7 @@ F2FS_FEATURE_RO_ATTR(project_quota, FEAT_PROJECT_QUOTA); F2FS_FEATURE_RO_ATTR(inode_checksum, FEAT_INODE_CHECKSUM); F2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR); F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO); +F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME); #define ATTR_LIST(name) (&f2fs_attr_##name.attr) static struct attribute *f2fs_attrs[] = { @@ -346,6 +355,8 @@ static struct attribute *f2fs_attrs[] = { ATTR_LIST(cp_interval), ATTR_LIST(idle_interval), ATTR_LIST(iostat_enable), + ATTR_LIST(readdir_ra), + ATTR_LIST(gc_pin_file_thresh), #ifdef CONFIG_F2FS_FAULT_INJECTION ATTR_LIST(inject_rate), ATTR_LIST(inject_type), @@ -371,6 +382,7 @@ static struct attribute *f2fs_feat_attrs[] = { ATTR_LIST(inode_checksum), ATTR_LIST(flexible_inline_xattr), ATTR_LIST(quota_ino), + ATTR_LIST(inode_crtime), NULL, }; diff --git a/fs/f2fs/trace.c b/fs/f2fs/trace.c index bccbbf2616d2b..a1fcd00bbb2bd 100644 --- a/fs/f2fs/trace.c +++ b/fs/f2fs/trace.c @@ -17,7 +17,7 @@ #include "trace.h" static RADIX_TREE(pids, GFP_ATOMIC); -static spinlock_t pids_lock; +static struct mutex pids_lock; static struct last_io_info last_io; static inline void __print_last_io(void) @@ -64,7 +64,7 @@ void f2fs_trace_pid(struct page *page) if (radix_tree_preload(GFP_NOFS)) return; - spin_lock(&pids_lock); + mutex_lock(&pids_lock); p = radix_tree_lookup(&pids, pid); if (p == current) goto out; @@ -77,7 +77,7 @@ void f2fs_trace_pid(struct page *page) MAJOR(inode->i_sb->s_dev), MINOR(inode->i_sb->s_dev), pid, current->comm); out: - spin_unlock(&pids_lock); + mutex_unlock(&pids_lock); radix_tree_preload_end(); } @@ -122,7 +122,7 @@ void f2fs_trace_ios(struct f2fs_io_info *fio, int flush) void f2fs_build_trace_ios(void) { - spin_lock_init(&pids_lock); + mutex_init(&pids_lock); } #define PIDVEC_SIZE 128 @@ -150,7 +150,7 @@ void f2fs_destroy_trace_ios(void) pid_t next_pid = 0; unsigned int found; - spin_lock(&pids_lock); + mutex_lock(&pids_lock); while ((found = gang_lookup_pids(pid, next_pid, PIDVEC_SIZE))) { unsigned idx; @@ -158,5 +158,5 @@ void f2fs_destroy_trace_ios(void) for (idx = 0; idx < found; idx++) radix_tree_delete(&pids, pid[idx]); } - spin_unlock(&pids_lock); + mutex_unlock(&pids_lock); } diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 56c80831976b2..967d6996ba02e 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -347,8 +347,8 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage, if (!size && !inline_size) return -ENODATA; - txattr_addr = kzalloc(inline_size + size + XATTR_PADDING_SIZE, - GFP_F2FS_ZERO); + txattr_addr = f2fs_kzalloc(F2FS_I_SB(inode), + inline_size + size + XATTR_PADDING_SIZE, GFP_NOFS); if (!txattr_addr) return -ENOMEM; @@ -400,8 +400,8 @@ static int read_all_xattrs(struct inode *inode, struct page *ipage, void *txattr_addr; int err; - txattr_addr = kzalloc(inline_size + size + XATTR_PADDING_SIZE, - GFP_F2FS_ZERO); + txattr_addr = f2fs_kzalloc(F2FS_I_SB(inode), + inline_size + size + XATTR_PADDING_SIZE, GFP_NOFS); if (!txattr_addr) return -ENOMEM; @@ -482,6 +482,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, if (F2FS_I(inode)->i_xattr_nid) { xpage = get_node_page(sbi, F2FS_I(inode)->i_xattr_nid); if (IS_ERR(xpage)) { + err = PTR_ERR(xpage); alloc_nid_failed(sbi, new_nid); goto in_page_out; } @@ -492,6 +493,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, set_new_dnode(&dn, inode, NULL, NULL, new_nid); xpage = new_node_page(&dn, XATTR_NODE_OFFSET); if (IS_ERR(xpage)) { + err = PTR_ERR(xpage); alloc_nid_failed(sbi, new_nid); goto in_page_out; } @@ -640,7 +642,7 @@ static int __f2fs_setxattr(struct inode *inode, int index, goto exit; } - if (f2fs_xattr_value_same(here, value, size)) + if (value && f2fs_xattr_value_same(here, value, size)) goto exit; } else if ((flags & XATTR_REPLACE)) { error = -ENODATA; diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index 30dc9d69d60e3..9094fd49948bf 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -117,6 +117,7 @@ struct f2fs_super_block { /* * For checkpoint */ +#define CP_NOCRC_RECOVERY_FLAG 0x00000200 #define CP_TRIMMED_FLAG 0x00000100 #define CP_NAT_BITS_FLAG 0x00000080 #define CP_CRC_RECOVERY_FLAG 0x00000040 @@ -212,6 +213,7 @@ struct f2fs_extent { #define F2FS_DATA_EXIST 0x08 /* file inline data exist flag */ #define F2FS_INLINE_DOTS 0x10 /* file having implicit dot dentries */ #define F2FS_EXTRA_ATTR 0x20 /* file having extra attribute */ +#define F2FS_PIN_FILE 0x40 /* file should not be gced */ struct f2fs_inode { __le16 i_mode; /* file mode */ @@ -229,7 +231,13 @@ struct f2fs_inode { __le32 i_ctime_nsec; /* change time in nano scale */ __le32 i_mtime_nsec; /* modification time in nano scale */ __le32 i_generation; /* file version (for NFS) */ - __le32 i_current_depth; /* only for directory depth */ + union { + __le32 i_current_depth; /* only for directory depth */ + __le16 i_gc_failures; /* + * # of gc failures on pinned file. + * only for regular files. + */ + }; __le32 i_xattr_nid; /* nid to save xattr */ __le32 i_flags; /* file attributes */ __le32 i_pino; /* parent inode number */ @@ -245,8 +253,10 @@ struct f2fs_inode { __le16 i_inline_xattr_size; /* inline xattr size, unit: 4 bytes */ __le32 i_projid; /* project id */ __le32 i_inode_checksum;/* inode meta checksum */ + __le64 i_crtime; /* creation time */ + __le32 i_crtime_nsec; /* creation time in nano scale */ __le32 i_extra_end[0]; /* for attribute size calculation */ - }; + } __packed; __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */ }; __le32 i_nid[DEF_NIDS_PER_INODE]; /* direct(2), indirect(2), diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index 7e117885dde50..4a089373838da 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -101,7 +101,8 @@ { CP_NO_SPC_ROLL, "no space roll forward" }, \ { CP_NODE_NEED_CP, "node needs cp" }, \ { CP_FASTBOOT_MODE, "fastboot mode" }, \ - { CP_SPEC_LOG_NUM, "log type is 2" }) + { CP_SPEC_LOG_NUM, "log type is 2" }, \ + { CP_RECOVER_DIR, "dir needs recovery" }) struct victim_sel_policy; struct f2fs_map_blocks; From 55780193118dbff36cd160e217d19d75658cf696 Mon Sep 17 00:00:00 2001 From: Yunlong Song Date: Wed, 28 Feb 2018 20:31:52 +0800 Subject: [PATCH 480/508] FROMLIST: f2fs: don't put dentry page in pagecache into highmem Cherry-pick from origin/upstream-f2fs-stable-linux-3.18.y: d0258fee433b ("f2fs: don't put dentry page in pagecache into highmem") Previous dentry page uses highmem, which will cause panic in platforms using highmem (such as arm), since the address space of dentry pages from highmem directly goes into the decryption path via the function fscrypt_fname_disk_to_usr. But sg_init_one assumes the address is not from highmem, and then cause panic since it doesn't call kmap_high but kunmap_high is triggered at the end. To fix this problem in a simple way, this patch avoids to put dentry page in pagecache into highmem. Change-Id: Ic8d8f7f9a1ea438e61f2f6bb28369c4817bf3506 Signed-off-by: Yunlong Song Reviewed-by: Chao Yu [Jaegeuk Kim: fix coding style] Signed-off-by: Jaegeuk Kim --- fs/f2fs/dir.c | 23 +++++------------------ fs/f2fs/f2fs.h | 6 ------ fs/f2fs/inline.c | 3 +-- fs/f2fs/inode.c | 2 +- fs/f2fs/namei.c | 32 ++++++++------------------------ fs/f2fs/recovery.c | 9 ++++----- include/linux/f2fs_fs.h | 1 - 7 files changed, 19 insertions(+), 57 deletions(-) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index bde445e4e6907..560b707050ca2 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -94,14 +94,12 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, struct f2fs_dir_entry *de; struct f2fs_dentry_ptr d; - dentry_blk = (struct f2fs_dentry_block *)kmap(dentry_page); + dentry_blk = (struct f2fs_dentry_block *)page_address(dentry_page); make_dentry_ptr_block(NULL, &d, dentry_blk); de = find_target_dentry(fname, namehash, max_slots, &d); if (de) *res_page = dentry_page; - else - kunmap(dentry_page); return de; } @@ -287,7 +285,6 @@ ino_t f2fs_inode_by_name(struct inode *dir, const struct qstr *qstr, de = f2fs_find_entry(dir, qstr, page); if (de) { res = le32_to_cpu(de->ino); - f2fs_dentry_kunmap(dir, *page); f2fs_put_page(*page, 0); } @@ -302,7 +299,6 @@ void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de, f2fs_wait_on_page_writeback(page, type, true); de->ino = cpu_to_le32(inode->i_ino); set_de_type(de, inode->i_mode); - f2fs_dentry_kunmap(dir, page); set_page_dirty(page); dir->i_mtime = dir->i_ctime = current_time(dir); @@ -350,13 +346,11 @@ static int make_empty_dir(struct inode *inode, if (IS_ERR(dentry_page)) return PTR_ERR(dentry_page); - dentry_blk = kmap_atomic(dentry_page); + dentry_blk = page_address(dentry_page); make_dentry_ptr_block(NULL, &d, dentry_blk); do_make_empty_dir(inode, parent, &d); - kunmap_atomic(dentry_blk); - set_page_dirty(dentry_page); f2fs_put_page(dentry_page, 1); return 0; @@ -547,13 +541,12 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name, if (IS_ERR(dentry_page)) return PTR_ERR(dentry_page); - dentry_blk = kmap(dentry_page); + dentry_blk = page_address(dentry_page); bit_pos = room_for_filename(&dentry_blk->dentry_bitmap, slots, NR_DENTRY_IN_BLOCK); if (bit_pos < NR_DENTRY_IN_BLOCK) goto add_dentry; - kunmap(dentry_page); f2fs_put_page(dentry_page, 1); } @@ -588,7 +581,6 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name, if (inode) up_write(&F2FS_I(inode)->i_sem); - kunmap(dentry_page); f2fs_put_page(dentry_page, 1); return err; @@ -642,7 +634,6 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, F2FS_I(dir)->task = NULL; } if (de) { - f2fs_dentry_kunmap(dir, page); f2fs_put_page(page, 0); err = -EEXIST; } else if (IS_ERR(page)) { @@ -730,7 +721,6 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap, NR_DENTRY_IN_BLOCK, 0); - kunmap(page); /* kunmap - pair of f2fs_find_entry */ set_page_dirty(page); dir->i_ctime = dir->i_mtime = current_time(dir); @@ -775,7 +765,7 @@ bool f2fs_empty_dir(struct inode *dir) return false; } - dentry_blk = kmap_atomic(dentry_page); + dentry_blk = page_address(dentry_page); if (bidx == 0) bit_pos = 2; else @@ -783,7 +773,6 @@ bool f2fs_empty_dir(struct inode *dir) bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap, NR_DENTRY_IN_BLOCK, bit_pos); - kunmap_atomic(dentry_blk); f2fs_put_page(dentry_page, 1); @@ -901,19 +890,17 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx) } } - dentry_blk = kmap(dentry_page); + dentry_blk = page_address(dentry_page); make_dentry_ptr_block(inode, &d, dentry_blk); err = f2fs_fill_dentries(ctx, &d, n * NR_DENTRY_IN_BLOCK, &fstr); if (err) { - kunmap(dentry_page); f2fs_put_page(dentry_page, 1); break; } - kunmap(dentry_page); f2fs_put_page(dentry_page, 1); } out_free: diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 2ffec50508546..672ef458173e8 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2497,12 +2497,6 @@ static inline int f2fs_has_inline_dentry(struct inode *inode) return is_inode_flag_set(inode, FI_INLINE_DENTRY); } -static inline void f2fs_dentry_kunmap(struct inode *dir, struct page *page) -{ - if (!f2fs_has_inline_dentry(dir)) - kunmap(page); -} - static inline int is_file(struct inode *inode, int type) { return F2FS_I(inode)->i_advise & type; diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 8e2924bb5ca4f..275fd0e3f7a41 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -387,7 +387,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage, f2fs_wait_on_page_writeback(page, DATA, true); zero_user_segment(page, MAX_INLINE_DATA(dir), PAGE_SIZE); - dentry_blk = kmap_atomic(page); + dentry_blk = page_address(page); make_dentry_ptr_inline(dir, &src, inline_dentry); make_dentry_ptr_block(dir, &dst, dentry_blk); @@ -404,7 +404,6 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage, memcpy(dst.dentry, src.dentry, SIZE_OF_DIR_ENTRY * src.max); memcpy(dst.filename, src.filename, src.max * F2FS_SLOT_LEN); - kunmap_atomic(dentry_blk); if (!PageUptodate(page)) SetPageUptodate(page); set_page_dirty(page); diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 94ef24f3e3948..9f57f2867ceea 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -328,7 +328,7 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino) inode->i_op = &f2fs_dir_inode_operations; inode->i_fop = &f2fs_dir_operations; inode->i_mapping->a_ops = &f2fs_dblock_aops; - mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_HIGH_ZERO); + inode_nohighmem(inode); } else if (S_ISLNK(inode->i_mode)) { if (f2fs_encrypted_inode(inode)) inode->i_op = &f2fs_encrypted_symlink_inode_operations; diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 4f6adb7f0f313..3a1e0e91576e6 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -309,7 +309,6 @@ static int __recover_dot_dentries(struct inode *dir, nid_t pino) de = f2fs_find_entry(dir, &dot, &page); if (de) { - f2fs_dentry_kunmap(dir, page); f2fs_put_page(page, 0); } else if (IS_ERR(page)) { err = PTR_ERR(page); @@ -321,14 +320,12 @@ static int __recover_dot_dentries(struct inode *dir, nid_t pino) } de = f2fs_find_entry(dir, &dotdot, &page); - if (de) { - f2fs_dentry_kunmap(dir, page); + if (de) f2fs_put_page(page, 0); - } else if (IS_ERR(page)) { + else if (IS_ERR(page)) err = PTR_ERR(page); - } else { + else err = __f2fs_add_link(dir, &dotdot, NULL, pino, S_IFDIR); - } out: if (!err) clear_inode_flag(dir, FI_INLINE_DOTS); @@ -369,7 +366,6 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry, } ino = le32_to_cpu(de->ino); - f2fs_dentry_kunmap(dir, page); f2fs_put_page(page, 0); inode = f2fs_iget(dir->i_sb, ino); @@ -440,7 +436,6 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) err = acquire_orphan_inode(sbi); if (err) { f2fs_unlock_op(sbi); - f2fs_dentry_kunmap(dir, page); f2fs_put_page(page, 0); goto fail; } @@ -605,7 +600,7 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) inode->i_op = &f2fs_dir_inode_operations; inode->i_fop = &f2fs_dir_operations; inode->i_mapping->a_ops = &f2fs_dblock_aops; - mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_HIGH_ZERO); + inode_nohighmem(inode); set_inode_flag(inode, FI_INC_LINK); f2fs_lock_op(sbi); @@ -910,13 +905,11 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, } if (old_dir_entry) { - if (old_dir != new_dir && !whiteout) { + if (old_dir != new_dir && !whiteout) f2fs_set_link(old_inode, old_dir_entry, old_dir_page, new_dir); - } else { - f2fs_dentry_kunmap(old_inode, old_dir_page); + else f2fs_put_page(old_dir_page, 0); - } f2fs_i_links_write(old_dir, false); } add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO); @@ -929,20 +922,15 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, put_out_dir: f2fs_unlock_op(sbi); - if (new_page) { - f2fs_dentry_kunmap(new_dir, new_page); + if (new_page) f2fs_put_page(new_page, 0); - } out_whiteout: if (whiteout) iput(whiteout); out_dir: - if (old_dir_entry) { - f2fs_dentry_kunmap(old_inode, old_dir_page); + if (old_dir_entry) f2fs_put_page(old_dir_page, 0); - } out_old: - f2fs_dentry_kunmap(old_dir, old_page); f2fs_put_page(old_page, 0); out: return err; @@ -1080,19 +1068,15 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, return 0; out_new_dir: if (new_dir_entry) { - f2fs_dentry_kunmap(new_inode, new_dir_page); f2fs_put_page(new_dir_page, 0); } out_old_dir: if (old_dir_entry) { - f2fs_dentry_kunmap(old_inode, old_dir_page); f2fs_put_page(old_dir_page, 0); } out_new: - f2fs_dentry_kunmap(new_dir, new_page); f2fs_put_page(new_page, 0); out_old: - f2fs_dentry_kunmap(old_dir, old_page); f2fs_put_page(old_page, 0); out: return err; diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 1010fc2118dc6..14653f483a4c8 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -142,7 +142,7 @@ static int recover_dentry(struct inode *inode, struct page *ipage, retry: de = __f2fs_find_entry(dir, &fname, &page); if (de && inode->i_ino == le32_to_cpu(de->ino)) - goto out_unmap_put; + goto out_put; if (de) { einode = f2fs_iget_retry(inode->i_sb, le32_to_cpu(de->ino)); @@ -151,7 +151,7 @@ static int recover_dentry(struct inode *inode, struct page *ipage, err = PTR_ERR(einode); if (err == -ENOENT) err = -EEXIST; - goto out_unmap_put; + goto out_put; } dquot_initialize(einode); @@ -159,7 +159,7 @@ static int recover_dentry(struct inode *inode, struct page *ipage, err = acquire_orphan_inode(F2FS_I_SB(inode)); if (err) { iput(einode); - goto out_unmap_put; + goto out_put; } f2fs_delete_entry(de, page, dir, einode); iput(einode); @@ -174,8 +174,7 @@ static int recover_dentry(struct inode *inode, struct page *ipage, goto retry; goto out; -out_unmap_put: - f2fs_dentry_kunmap(dir, page); +out_put: f2fs_put_page(page, 0); out: if (file_enc_name(inode)) diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index 9094fd49948bf..77743acfe0dc3 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -46,7 +46,6 @@ /* This flag is used by node and meta inodes, and by recovery */ #define GFP_F2FS_ZERO (GFP_NOFS | __GFP_ZERO) -#define GFP_F2FS_HIGH_ZERO (GFP_NOFS | __GFP_ZERO | __GFP_HIGHMEM) /* * For further optimization on multi-head logs, on-disk layout supports maximum From 6c11ef4aa69c78d499038f846fddbe3b3440afc5 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 5 Jan 2018 10:44:52 -0800 Subject: [PATCH 481/508] f2fs/fscrypt: updates to v4.17-rc1 Pull f2fs update from Jaegeuk Kim: "In this round, we've mainly focused on performance tuning and critical bug fixes occurred in low-end devices. Sheng Yong introduced lost_found feature to keep missing files during recovery instead of thrashing them. We're preparing coming fsverity implementation. And, we've got more features to communicate with users for better performance. In low-end devices, some memory-related issues were fixed, and subtle race condtions and corner cases were addressed as well. Enhancements: - large nat bitmaps for more free node ids - add three block allocation policies to pass down write hints given by user - expose extension list to user and introduce hot file extension - tune small devices seamlessly for low-end devices - set readdir_ra by default - give more resources under gc_urgent mode regarding to discard and cleaning - introduce fsync_mode to enforce posix or not - nowait aio support - add lost_found feature to keep dangling inodes - reserve bits for future fsverity feature - add test_dummy_encryption for FBE Bug fixes: - don't use highmem for dentry pages - align memory boundary for bitops - truncate preallocated blocks in write errors - guarantee i_times on fsync call - clear CP_TRIMMED_FLAG correctly - prevent node chain loop during recovery - avoid data race between atomic write and background cleaning - avoid unnecessary selinux violation warnings on resgid option - GFP_NOFS to avoid deadlock in quota and read paths - fix f2fs_skip_inode_update to allow i_size recovery In addition to the above, there are several minor bug fixes and clean-ups" Cherry-pick from origin/upstream-f2fs-stable-linux-3.18.y: 6b863986e0cc f2fs: remain written times to update inode during fsync 7e1903bccf2f f2fs: make assignment of t->dentry_bitmap more readable cb40e79a67cb f2fs: truncate preallocated blocks in error case 61a1f92005be f2fs: fix a wrong condition in f2fs_skip_inode_update 60e88b22fa4b f2fs: reserve bits for fs-verity e9d296fa66db f2fs: Add a segment type check in inplace write a6abda931228 f2fs: no need to initialize zero value for GFP_F2FS_ZERO 6552559b76d4 f2fs: don't track new nat entry in nat set 0a83c6fbc676 f2fs: clean up with F2FS_BLK_ALIGN 561144cbddc6 f2fs: check blkaddr more accuratly before issue a bio f5c308c3fa92 f2fs: Set GF_NOFS in read_cache_page_gfp while doing f2fs_quota_read b6b63b2663d0 f2fs: introduce a new mount option test_dummy_encryption 2a1db739111b f2fs: introduce F2FS_FEATURE_LOST_FOUND feature 8cdc2bd05a7f f2fs: release locks before return in f2fs_ioc_gc_range() 25cbaa648ca2 f2fs: align memory boundary for bitops ef169ce0c97d f2fs: remove unneeded set_cold_node() 893b5cbd6db6 f2fs: wrap all options with f2fs_sb_info.mount_opt e00dfe43a45f f2fs: Don't overwrite all types of node to keep node chain 8b06bd6ab89f f2fs: introduce mount option for fsync mode d4f5f9260431 f2fs: fix to restore old mount option in ->remount_fs 28e06bec820a f2fs: wrap sb_rdonly with f2fs_readonly ac00fbd0bd5f f2fs: avoid selinux denial on CAP_SYS_RESOURCE 62141c39a3e9 f2fs: support hot file extension 94f9b2bd8d3c f2fs: fix to avoid race in between atomic write and background GC 972aa9b77a94 f2fs: do gc in greedy mode for whole range if gc_urgent mode is set 43df79e001a2 f2fs: issue discard aggressively in the gc_urgent mode 820bafa82f61 f2fs: set readdir_ra by default fd867fadc9af f2fs: add auto tuning for small devices 7135d061e65d f2fs: add mount option for segment allocation policy 1010797c1326 f2fs: don't stop GC if GC is contended 07b7ac026eb5 f2fs: expose extension_list sysfs entry d3f1ecce0217 f2fs: fix to set KEEP_SIZE bit in f2fs_zero_range 6a2a51a39561 f2fs: introduce sb_lock to make encrypt pwsalt update exclusive b25cb37a89db f2fs: remove redundant initialization of pointer 'p' f712a5e9f0d9 f2fs: flush cp pack except cp pack 2 page at first 9cc8ab4e3aa1 f2fs: clean up f2fs_sb_has_xxx functions e7e6b338e105 f2fs: remove redundant check of page type when submit bio 00e3ba7fe02e f2fs: fix to handle looped node chain during recovery 878a8d3c55e5 f2fs: handle quota for orphan inodes 5b20df494831 f2fs: support passing down write hints to block layer with F2FS policy 249b112bd06c f2fs: support passing down write hints given by users to block layer 3b8cef6e16c9 f2fs: fix to clear CP_TRIMMED_FLAG f77295576611 f2fs: support large nat bitmap b3fea69dc0cd f2fs: fix to check extent cache in f2fs_drop_extent_tree e01f70867c34 f2fs: restrict inline_xattr_size configuration 956a72d8a04b f2fs: fix heap mode to reset it back 08cdc84117b7 f2fs: fix potential corruption in area before F2FS_SUPER_OFFSET 9c696c1f506e fscrypt: fix build with pre-4.6 gcc versions db4247d1f008 fscrypt: remove 'ci' parameter from fscrypt_put_encryption_info() 29127d3977e5 fscrypt: fix up fscrypt_fname_encrypted_size() for internal use 439466d22a44 fscrypt: define fscrypt_fname_alloc_buffer() to be for presented names e33110200036 fscrypt: calculate NUL-padding length in one place only a7f4d8acd4d1 fscrypt: move fscrypt_symlink_data to fscrypt_private.h 5ea58407aff9 fscrypt: remove fscrypt_fname_usr_to_disk() 81b1614f3186 f2fs: switch to fscrypt_get_symlink() aef534bb13de f2fs: switch to fscrypt ->symlink() helper functions 398293781f68 fscrypt: new helper function - fscrypt_get_symlink() fcc38431ea35 fscrypt: new helper functions for ->symlink() 82b04f2db173 fscrypt: trim down fscrypt.h includes 9b0ef251f46e fscrypt: move fscrypt_is_dot_dotdot() to fs/crypto/fname.c 8319d163e70c fscrypt: move fscrypt_valid_enc_modes() to fscrypt_private.h 02cbbef829e3 fscrypt: move fscrypt_operations declaration to fscrypt_supp.h 646d687ff01c fscrypt: split fscrypt_dummy_context_enabled() into supp/notsupp versions fc0f52e7ab31 fscrypt: move fscrypt_ctx declaration to fscrypt_supp.h 1f8b1364e1f4 fscrypt: move fscrypt_info_cachep declaration to fscrypt_private.h 67a6c99fa311 fscrypt: move fscrypt_control_page() to supp/notsupp headers 2099761dc7ae fscrypt: move fscrypt_has_encryption_key() to supp/notsupp headers Change-Id: I62967cffd629c04f26bd00707fffed2cd75d5377 Signed-off-by: Jaegeuk Kim --- Documentation/ABI/testing/sysfs-fs-f2fs | 11 + Documentation/filesystems/f2fs.txt | 17 ++ fs/crypto/crypto.c | 1 + fs/crypto/fname.c | 140 +++++----- fs/crypto/fscrypt_private.h | 31 +++ fs/crypto/hooks.c | 159 +++++++++++ fs/crypto/keyinfo.c | 17 +- fs/f2fs/checkpoint.c | 97 ++++--- fs/f2fs/data.c | 38 ++- fs/f2fs/dir.c | 9 +- fs/f2fs/extent_cache.c | 5 +- fs/f2fs/f2fs.h | 177 +++++++----- fs/f2fs/file.c | 63 +++-- fs/f2fs/gc.c | 23 +- fs/f2fs/inode.c | 11 +- fs/f2fs/namei.c | 250 ++++++++--------- fs/f2fs/node.c | 55 +++- fs/f2fs/node.h | 5 +- fs/f2fs/recovery.c | 14 + fs/f2fs/segment.c | 133 ++++++++- fs/f2fs/segment.h | 27 +- fs/f2fs/super.c | 347 +++++++++++++++++------- fs/f2fs/sysfs.c | 73 ++++- include/linux/f2fs_fs.h | 19 +- include/linux/fscrypt.h | 173 +++++------- include/linux/fscrypt_notsupp.h | 59 ++-- include/linux/fscrypt_supp.h | 68 ++++- 27 files changed, 1381 insertions(+), 641 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs index db7aab1516dee..b8d0a30f16445 100644 --- a/Documentation/ABI/testing/sysfs-fs-f2fs +++ b/Documentation/ABI/testing/sysfs-fs-f2fs @@ -192,3 +192,14 @@ Date: November 2017 Contact: "Sheng Yong" Description: Controls readahead inode block in readdir. + +What: /sys/fs/f2fs//extension_list +Date: Feburary 2018 +Contact: "Chao Yu" +Description: + Used to control configure extension list: + - Query: cat /sys/fs/f2fs//extension_list + - Add: echo '[h/c]extension' > /sys/fs/f2fs//extension_list + - Del: echo '[h/c]!extension' > /sys/fs/f2fs//extension_list + - [h] means add/del hot file extension + - [c] means add/del cold file extension diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt index 6f9cb3690b571..36cd634f687a2 100644 --- a/Documentation/filesystems/f2fs.txt +++ b/Documentation/filesystems/f2fs.txt @@ -161,6 +161,23 @@ offgrpjquota Turn off group journelled quota. offprjjquota Turn off project journelled quota. quota Enable plain user disk quota accounting. noquota Disable all plain disk quota option. +whint_mode=%s Control which write hints are passed down to block + layer. This supports "off", "user-based", and + "fs-based". In "off" mode (default), f2fs does not pass + down hints. In "user-based" mode, f2fs tries to pass + down hints given by users. And in "fs-based" mode, f2fs + passes down hints with its policy. +alloc_mode=%s Adjust block allocation policy, which supports "reuse" + and "default". +fsync_mode=%s Control the policy of fsync. Currently supports "posix" + and "strict". In "posix" mode, which is default, fsync + will follow POSIX semantics and does a light operation + to improve the filesystem performance. In "strict" mode, + fsync will be heavy and behaves in line with xfs, ext4 + and btrfs, where xfstest generic/342 will pass, but the + performance will regress. +test_dummy_encryption Enable dummy encryption, which provides a fake fscrypt + context. The fake fscrypt context is used by xfstests. ================================================================================ DEBUGFS ENTRIES diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index b744b40286f85..43d2d3688cf42 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "fscrypt_private.h" static unsigned int num_prealloc_crypto_pages = 32; diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 690426912d0ed..0ffff3654117a 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -12,42 +12,46 @@ #include #include +#include #include "fscrypt_private.h" +static inline bool fscrypt_is_dot_dotdot(const struct qstr *str) +{ + if (str->len == 1 && str->name[0] == '.') + return true; + + if (str->len == 2 && str->name[0] == '.' && str->name[1] == '.') + return true; + + return false; +} + /** * fname_encrypt() - encrypt a filename * - * The caller must have allocated sufficient memory for the @oname string. + * The output buffer must be at least as large as the input buffer. + * Any extra space is filled with NUL padding before encryption. * * Return: 0 on success, -errno on failure */ -static int fname_encrypt(struct inode *inode, - const struct qstr *iname, struct fscrypt_str *oname) +int fname_encrypt(struct inode *inode, const struct qstr *iname, + u8 *out, unsigned int olen) { struct ablkcipher_request *req = NULL; DECLARE_CRYPTO_WAIT(wait); - struct fscrypt_info *ci = inode->i_crypt_info; - struct crypto_ablkcipher *tfm = ci->ci_ctfm; + struct crypto_ablkcipher *tfm = inode->i_crypt_info->ci_ctfm; int res = 0; char iv[FS_CRYPTO_BLOCK_SIZE]; struct scatterlist sg; - int padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK); - unsigned int lim; - unsigned int cryptlen; - - lim = inode->i_sb->s_cop->max_namelen(inode); - if (iname->len <= 0 || iname->len > lim) - return -EIO; /* * Copy the filename to the output buffer for encrypting in-place and * pad it with the needed number of NUL bytes. */ - cryptlen = max_t(unsigned int, iname->len, FS_CRYPTO_BLOCK_SIZE); - cryptlen = round_up(cryptlen, padding); - cryptlen = min(cryptlen, lim); - memcpy(oname->name, iname->name, iname->len); - memset(oname->name + iname->len, 0, cryptlen - iname->len); + if (WARN_ON(olen < iname->len)) + return -ENOBUFS; + memcpy(out, iname->name, iname->len); + memset(out + iname->len, 0, olen - iname->len); /* Initialize the IV */ memset(iv, 0, FS_CRYPTO_BLOCK_SIZE); @@ -62,8 +66,8 @@ static int fname_encrypt(struct inode *inode, ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, crypto_req_done, &wait); - sg_init_one(&sg, oname->name, cryptlen); - ablkcipher_request_set_crypt(req, &sg, &sg, cryptlen, iv); + sg_init_one(&sg, out, olen); + ablkcipher_request_set_crypt(req, &sg, &sg, olen, iv); /* Do the encryption */ res = crypto_wait_req(crypto_ablkcipher_encrypt(req), &wait); @@ -74,7 +78,6 @@ static int fname_encrypt(struct inode *inode, return res; } - oname->len = cryptlen; return 0; } @@ -187,50 +190,52 @@ static int digest_decode(const char *src, int len, char *dst) return cp - dst; } -u32 fscrypt_fname_encrypted_size(const struct inode *inode, u32 ilen) +bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, + u32 max_len, u32 *encrypted_len_ret) { - int padding = 32; - struct fscrypt_info *ci = inode->i_crypt_info; - - if (ci) - padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK); - ilen = max(ilen, (u32)FS_CRYPTO_BLOCK_SIZE); - return round_up(ilen, padding); + int padding = 4 << (inode->i_crypt_info->ci_flags & + FS_POLICY_FLAGS_PAD_MASK); + u32 encrypted_len; + + if (orig_len > max_len) + return false; + encrypted_len = max(orig_len, (u32)FS_CRYPTO_BLOCK_SIZE); + encrypted_len = round_up(encrypted_len, padding); + *encrypted_len_ret = min(encrypted_len, max_len); + return true; } -EXPORT_SYMBOL(fscrypt_fname_encrypted_size); /** - * fscrypt_fname_crypto_alloc_obuff() - + * fscrypt_fname_alloc_buffer - allocate a buffer for presented filenames + * + * Allocate a buffer that is large enough to hold any decrypted or encoded + * filename (null-terminated), for the given maximum encrypted filename length. * - * Allocates an output buffer that is sufficient for the crypto operation - * specified by the context and the direction. + * Return: 0 on success, -errno on failure */ int fscrypt_fname_alloc_buffer(const struct inode *inode, - u32 ilen, struct fscrypt_str *crypto_str) + u32 max_encrypted_len, + struct fscrypt_str *crypto_str) { - u32 olen = fscrypt_fname_encrypted_size(inode, ilen); const u32 max_encoded_len = max_t(u32, BASE64_CHARS(FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE), 1 + BASE64_CHARS(sizeof(struct fscrypt_digested_name))); + u32 max_presented_len; - crypto_str->len = olen; - olen = max(olen, max_encoded_len); + max_presented_len = max(max_encoded_len, max_encrypted_len); - /* - * Allocated buffer can hold one more character to null-terminate the - * string - */ - crypto_str->name = kmalloc(olen + 1, GFP_NOFS); - if (!(crypto_str->name)) + crypto_str->name = kmalloc(max_presented_len + 1, GFP_NOFS); + if (!crypto_str->name) return -ENOMEM; + crypto_str->len = max_presented_len; return 0; } EXPORT_SYMBOL(fscrypt_fname_alloc_buffer); /** - * fscrypt_fname_crypto_free_buffer() - + * fscrypt_fname_free_buffer - free the buffer for presented filenames * - * Frees the buffer allocated for crypto operation. + * Free the buffer allocated by fscrypt_fname_alloc_buffer(). */ void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str) { @@ -296,35 +301,6 @@ int fscrypt_fname_disk_to_usr(struct inode *inode, } EXPORT_SYMBOL(fscrypt_fname_disk_to_usr); -/** - * fscrypt_fname_usr_to_disk() - converts a filename from user space to disk - * space - * - * The caller must have allocated sufficient memory for the @oname string. - * - * Return: 0 on success, -errno on failure - */ -int fscrypt_fname_usr_to_disk(struct inode *inode, - const struct qstr *iname, - struct fscrypt_str *oname) -{ - if (fscrypt_is_dot_dotdot(iname)) { - oname->name[0] = '.'; - oname->name[iname->len - 1] = '.'; - oname->len = iname->len; - return 0; - } - if (inode->i_crypt_info) - return fname_encrypt(inode, iname, oname); - /* - * Without a proper key, a user is not allowed to modify the filenames - * in a directory. Consequently, a user space name cannot be mapped to - * a disk-space name - */ - return -ENOKEY; -} -EXPORT_SYMBOL(fscrypt_fname_usr_to_disk); - /** * fscrypt_setup_filename() - prepare to search a possibly encrypted directory * @dir: the directory that will be searched @@ -368,11 +344,17 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, return ret; if (dir->i_crypt_info) { - ret = fscrypt_fname_alloc_buffer(dir, iname->len, - &fname->crypto_buf); - if (ret) - return ret; - ret = fname_encrypt(dir, iname, &fname->crypto_buf); + if (!fscrypt_fname_encrypted_size(dir, iname->len, + dir->i_sb->s_cop->max_namelen(dir), + &fname->crypto_buf.len)) + return -ENAMETOOLONG; + fname->crypto_buf.name = kmalloc(fname->crypto_buf.len, + GFP_NOFS); + if (!fname->crypto_buf.name) + return -ENOMEM; + + ret = fname_encrypt(dir, iname, fname->crypto_buf.name, + fname->crypto_buf.len); if (ret) goto errout; fname->disk_name.name = fname->crypto_buf.name; @@ -424,7 +406,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, return 0; errout: - fscrypt_fname_free_buffer(&fname->crypto_buf); + kfree(fname->crypto_buf.name); return ret; } EXPORT_SYMBOL(fscrypt_setup_filename); diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index acb0ccc656985..7c9484375aeff 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -49,6 +49,15 @@ struct fscrypt_context { #define FS_ENCRYPTION_CONTEXT_FORMAT_V1 1 +/** + * For encrypted symlinks, the ciphertext length is stored at the beginning + * of the string in little-endian format. + */ +struct fscrypt_symlink_data { + __le16 len; + char encrypted_path[1]; +} __packed; + /* * A pointer to this structure is stored in the file system's in-core * representation of an inode. @@ -96,7 +105,22 @@ static inline void bio_set_op_attrs(struct bio *bio, unsigned op, bio->bi_rw = op | op_flags; } +static inline bool fscrypt_valid_enc_modes(u32 contents_mode, + u32 filenames_mode) +{ + if (contents_mode == FS_ENCRYPTION_MODE_AES_128_CBC && + filenames_mode == FS_ENCRYPTION_MODE_AES_128_CTS) + return true; + + if (contents_mode == FS_ENCRYPTION_MODE_AES_256_XTS && + filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS) + return true; + + return false; +} + /* crypto.c */ +extern struct kmem_cache *fscrypt_info_cachep; extern int fscrypt_initialize(unsigned int cop_flags); extern struct workqueue_struct *fscrypt_read_workqueue; extern int fscrypt_do_page_crypto(const struct inode *inode, @@ -108,6 +132,13 @@ extern int fscrypt_do_page_crypto(const struct inode *inode, extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, gfp_t gfp_flags); +/* fname.c */ +extern int fname_encrypt(struct inode *inode, const struct qstr *iname, + u8 *out, unsigned int olen); +extern bool fscrypt_fname_encrypted_size(const struct inode *inode, + u32 orig_len, u32 max_len, + u32 *encrypted_len_ret); + /* keyinfo.c */ extern void __exit fscrypt_essiv_cleanup(void); diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c index 396561212dbd5..da8e671bf9b92 100644 --- a/fs/crypto/hooks.c +++ b/fs/crypto/hooks.c @@ -5,6 +5,7 @@ */ #include +#include #include "fscrypt_private.h" /** @@ -110,3 +111,161 @@ int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry) return 0; } EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup); + +int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len, + unsigned int max_len, + struct fscrypt_str *disk_link) +{ + int err; + + /* + * To calculate the size of the encrypted symlink target we need to know + * the amount of NUL padding, which is determined by the flags set in + * the encryption policy which will be inherited from the directory. + * The easiest way to get access to this is to just load the directory's + * fscrypt_info, since we'll need it to create the dir_entry anyway. + * + * Note: in test_dummy_encryption mode, @dir may be unencrypted. + */ + err = fscrypt_get_encryption_info(dir); + if (err) + return err; + if (!fscrypt_has_encryption_key(dir)) + return -ENOKEY; + + /* + * Calculate the size of the encrypted symlink and verify it won't + * exceed max_len. Note that for historical reasons, encrypted symlink + * targets are prefixed with the ciphertext length, despite this + * actually being redundant with i_size. This decreases by 2 bytes the + * longest symlink target we can accept. + * + * We could recover 1 byte by not counting a null terminator, but + * counting it (even though it is meaningless for ciphertext) is simpler + * for now since filesystems will assume it is there and subtract it. + */ + if (!fscrypt_fname_encrypted_size(dir, len, + max_len - sizeof(struct fscrypt_symlink_data), + &disk_link->len)) + return -ENAMETOOLONG; + disk_link->len += sizeof(struct fscrypt_symlink_data); + + disk_link->name = NULL; + return 0; +} +EXPORT_SYMBOL_GPL(__fscrypt_prepare_symlink); + +int __fscrypt_encrypt_symlink(struct inode *inode, const char *target, + unsigned int len, struct fscrypt_str *disk_link) +{ + int err; + struct qstr iname = QSTR_INIT(target, len); + struct fscrypt_symlink_data *sd; + unsigned int ciphertext_len; + + err = fscrypt_require_key(inode); + if (err) + return err; + + if (disk_link->name) { + /* filesystem-provided buffer */ + sd = (struct fscrypt_symlink_data *)disk_link->name; + } else { + sd = kmalloc(disk_link->len, GFP_NOFS); + if (!sd) + return -ENOMEM; + } + ciphertext_len = disk_link->len - sizeof(*sd); + sd->len = cpu_to_le16(ciphertext_len); + + err = fname_encrypt(inode, &iname, sd->encrypted_path, ciphertext_len); + if (err) { + if (!disk_link->name) + kfree(sd); + return err; + } + /* + * Null-terminating the ciphertext doesn't make sense, but we still + * count the null terminator in the length, so we might as well + * initialize it just in case the filesystem writes it out. + */ + sd->encrypted_path[ciphertext_len] = '\0'; + + if (!disk_link->name) + disk_link->name = (unsigned char *)sd; + return 0; +} +EXPORT_SYMBOL_GPL(__fscrypt_encrypt_symlink); + +/** + * fscrypt_get_symlink - get the target of an encrypted symlink + * @inode: the symlink inode + * @caddr: the on-disk contents of the symlink + * @max_size: size of @caddr buffer + * @done: if successful, will be set up to free the returned target + * + * If the symlink's encryption key is available, we decrypt its target. + * Otherwise, we encode its target for presentation. + * + * This may sleep, so the filesystem must have dropped out of RCU mode already. + * + * Return: the presentable symlink target or an ERR_PTR() + */ +void *fscrypt_get_symlink(struct inode *inode, const void *caddr, + unsigned int max_size, + struct nameidata *nd) +{ + const struct fscrypt_symlink_data *sd; + struct fscrypt_str cstr, pstr; + int err; + + /* This is for encrypted symlinks only */ + if (WARN_ON(!IS_ENCRYPTED(inode))) + return ERR_PTR(-EINVAL); + + /* + * Try to set up the symlink's encryption key, but we can continue + * regardless of whether the key is available or not. + */ + err = fscrypt_get_encryption_info(inode); + if (err) + return ERR_PTR(err); + + /* + * For historical reasons, encrypted symlink targets are prefixed with + * the ciphertext length, even though this is redundant with i_size. + */ + + if (max_size < sizeof(*sd)) + return ERR_PTR(-EUCLEAN); + sd = caddr; + cstr.name = (unsigned char *)sd->encrypted_path; + cstr.len = le16_to_cpu(sd->len); + + if (cstr.len == 0) + return ERR_PTR(-EUCLEAN); + + if (cstr.len + sizeof(*sd) - 1 > max_size) + return ERR_PTR(-EUCLEAN); + + err = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr); + if (err) + return ERR_PTR(err); + + err = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr); + if (err) + goto err_kfree; + + err = -EUCLEAN; + if (pstr.name[0] == '\0') + goto err_kfree; + + pstr.name[pstr.len] = '\0'; + nd_set_link(nd, pstr.name); + return NULL; + +err_kfree: + kfree(pstr.name); + return ERR_PTR(err); +} +EXPORT_SYMBOL_GPL(fscrypt_get_symlink); diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 2affed8466e8c..8b95f1c4bd93b 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "fscrypt_private.h" static struct crypto_shash *essiv_hash_tfm; @@ -361,19 +362,9 @@ int fscrypt_get_encryption_info(struct inode *inode) } EXPORT_SYMBOL(fscrypt_get_encryption_info); -void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci) +void fscrypt_put_encryption_info(struct inode *inode) { - struct fscrypt_info *prev; - - if (ci == NULL) - ci = ACCESS_ONCE(inode->i_crypt_info); - if (ci == NULL) - return; - - prev = cmpxchg(&inode->i_crypt_info, ci, NULL); - if (prev != ci) - return; - - put_crypt_info(ci); + put_crypt_info(inode->i_crypt_info); + inode->i_crypt_info = NULL; } EXPORT_SYMBOL(fscrypt_put_encryption_info); diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 8c7556b7da629..7ad7d858fab68 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -68,6 +68,7 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index, .old_blkaddr = index, .new_blkaddr = index, .encrypted_page = NULL, + .is_meta = is_meta, }; if (unlikely(!is_meta)) @@ -163,6 +164,7 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, .op_flags = sync ? (REQ_META | REQ_PRIO) : REQ_RAHEAD, .encrypted_page = NULL, .in_list = false, + .is_meta = (type != META_POR), }; struct blk_plug plug; @@ -573,13 +575,8 @@ static int recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) struct node_info ni; int err = acquire_orphan_inode(sbi); - if (err) { - set_sbi_flag(sbi, SBI_NEED_FSCK); - f2fs_msg(sbi->sb, KERN_WARNING, - "%s: orphan failed (ino=%x), run fsck to fix.", - __func__, ino); - return err; - } + if (err) + goto err_out; __add_ino_entry(sbi, ino, 0, ORPHAN_INO); @@ -593,6 +590,7 @@ static int recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) return PTR_ERR(inode); } + dquot_initialize(inode); clear_nlink(inode); /* truncate all the data during iput */ @@ -602,14 +600,18 @@ static int recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) /* ENOMEM was fully retried in f2fs_evict_inode. */ if (ni.blk_addr != NULL_ADDR) { - set_sbi_flag(sbi, SBI_NEED_FSCK); - f2fs_msg(sbi->sb, KERN_WARNING, - "%s: orphan failed (ino=%x) by kernel, retry mount.", - __func__, ino); - return -EIO; + err = -EIO; + goto err_out; } __remove_ino_entry(sbi, ino, ORPHAN_INO); return 0; + +err_out: + set_sbi_flag(sbi, SBI_NEED_FSCK); + f2fs_msg(sbi->sb, KERN_WARNING, + "%s: orphan failed (ino=%x), run fsck to fix.", + __func__, ino); + return err; } int recover_orphan_inodes(struct f2fs_sb_info *sbi) @@ -1140,6 +1142,8 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc) if (cpc->reason & CP_TRIMMED) __set_ckpt_flags(ckpt, CP_TRIMMED_FLAG); + else + __clear_ckpt_flags(ckpt, CP_TRIMMED_FLAG); if (cpc->reason & CP_UMOUNT) __set_ckpt_flags(ckpt, CP_UMOUNT_FLAG); @@ -1166,6 +1170,39 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc) spin_unlock_irqrestore(&sbi->cp_lock, flags); } +static void commit_checkpoint(struct f2fs_sb_info *sbi, + void *src, block_t blk_addr) +{ + struct writeback_control wbc = { + .for_reclaim = 0, + }; + + /* + * pagevec_lookup_tag and lock_page again will take + * some extra time. Therefore, update_meta_pages and + * sync_meta_pages are combined in this function. + */ + struct page *page = grab_meta_page(sbi, blk_addr); + int err; + + memcpy(page_address(page), src, PAGE_SIZE); + set_page_dirty(page); + + f2fs_wait_on_page_writeback(page, META, true); + f2fs_bug_on(sbi, PageWriteback(page)); + if (unlikely(!clear_page_dirty_for_io(page))) + f2fs_bug_on(sbi, 1); + + /* writeout cp pack 2 page */ + err = __f2fs_write_meta_page(page, &wbc, FS_CP_META_IO); + f2fs_bug_on(sbi, err); + + f2fs_put_page(page, 0); + + /* submit checkpoint (with barrier if NOBARRIER is not set) */ + f2fs_submit_merged_write(sbi, META_FLUSH); +} + static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) { struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); @@ -1268,16 +1305,6 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) } } - /* need to wait for end_io results */ - wait_on_all_pages_writeback(sbi); - if (unlikely(f2fs_cp_error(sbi))) - return -EIO; - - /* flush all device cache */ - err = f2fs_flush_device_cache(sbi); - if (err) - return err; - /* write out checkpoint buffer at block 0 */ update_meta_page(sbi, ckpt, start_blk++); @@ -1305,26 +1332,26 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) start_blk += NR_CURSEG_NODE_TYPE; } - /* writeout checkpoint block */ - update_meta_page(sbi, ckpt, start_blk); + /* update user_block_counts */ + sbi->last_valid_block_count = sbi->total_valid_block_count; + percpu_counter_set(&sbi->alloc_valid_block_count, 0); - /* wait for previous submitted node/meta pages writeback */ + /* Here, we have one bio having CP pack except cp pack 2 page */ + sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO); + + /* wait for previous submitted meta pages writeback */ wait_on_all_pages_writeback(sbi); if (unlikely(f2fs_cp_error(sbi))) return -EIO; - filemap_fdatawait_range(NODE_MAPPING(sbi), 0, LLONG_MAX); - filemap_fdatawait_range(META_MAPPING(sbi), 0, LLONG_MAX); - - /* update user_block_counts */ - sbi->last_valid_block_count = sbi->total_valid_block_count; - percpu_counter_set(&sbi->alloc_valid_block_count, 0); - - /* Here, we only have one bio having CP pack */ - sync_meta_pages(sbi, META_FLUSH, LONG_MAX, FS_CP_META_IO); + /* flush all device cache */ + err = f2fs_flush_device_cache(sbi); + if (err) + return err; - /* wait for previous submitted meta pages writeback */ + /* barrier and flush checkpoint cp pack 2 page if it can */ + commit_checkpoint(sbi, ckpt, start_blk); wait_on_all_pages_writeback(sbi); release_ino_entry(sbi, false); diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 12597399f0d6b..0408cc3ed4d2a 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -175,15 +175,22 @@ static bool __same_bdev(struct f2fs_sb_info *sbi, */ static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr, struct writeback_control *wbc, - int npages, bool is_read) + int npages, bool is_read, + enum page_type type, enum temp_type temp) { struct bio *bio; bio = f2fs_bio_alloc(sbi, npages, true); f2fs_target_device(sbi, blk_addr, bio); - bio->bi_end_io = is_read ? f2fs_read_end_io : f2fs_write_end_io; - bio->bi_private = is_read ? NULL : sbi; + if (is_read) { + bio->bi_end_io = f2fs_read_end_io; + bio->bi_private = NULL; + } else { + bio->bi_end_io = f2fs_write_end_io; + bio->bi_private = sbi; + /* bio->bi_write_hint = io_type_to_rw_hint(sbi, type, temp); */ + } if (wbc) wbc_init_bio(wbc, bio); @@ -196,13 +203,12 @@ static inline void __submit_bio(struct f2fs_sb_info *sbi, if (!is_read_io(bio_op(bio))) { unsigned int start; - if (f2fs_sb_mounted_blkzoned(sbi->sb) && - current->plug && (type == DATA || type == NODE)) - blk_finish_plug(current->plug); - if (type != DATA && type != NODE) goto submit_io; + if (f2fs_sb_has_blkzoned(sbi->sb) && current->plug) + blk_finish_plug(current->plug); + start = bio->bi_iter.bi_size >> F2FS_BLKSIZE_BITS; start %= F2FS_IO_SIZE(sbi); @@ -377,12 +383,13 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) struct page *page = fio->encrypted_page ? fio->encrypted_page : fio->page; + verify_block_addr(fio, fio->new_blkaddr); trace_f2fs_submit_page_bio(page, fio); f2fs_trace_ios(fio, 0); /* Allocate a new bio */ bio = __bio_alloc(fio->sbi, fio->new_blkaddr, fio->io_wbc, - 1, is_read_io(fio->op)); + 1, is_read_io(fio->op), fio->type, fio->temp); if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { bio_put(bio); @@ -422,8 +429,8 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio) } if (fio->old_blkaddr != NEW_ADDR) - verify_block_addr(sbi, fio->old_blkaddr); - verify_block_addr(sbi, fio->new_blkaddr); + verify_block_addr(fio, fio->old_blkaddr); + verify_block_addr(fio, fio->new_blkaddr); bio_page = fio->encrypted_page ? fio->encrypted_page : fio->page; @@ -445,7 +452,8 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio) goto out_fail; } io->bio = __bio_alloc(sbi, fio->new_blkaddr, fio->io_wbc, - BIO_MAX_PAGES, false); + BIO_MAX_PAGES, false, + fio->type, fio->temp); io->fio = *fio; } @@ -2304,8 +2312,11 @@ static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, { struct address_space *mapping = iocb->ki_filp->f_mapping; struct inode *inode = mapping->host; + /* struct f2fs_sb_info *sbi = F2FS_I_SB(inode); */ size_t count = iov_iter_count(iter); int err; + /* enum rw_hint hint = iocb->ki_hint; + int whint_mode = F2FS_OPTION(sbi).whint_mode; */ err = check_direct_IO(inode, iter, offset); if (err) @@ -2337,11 +2348,16 @@ static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, trace_f2fs_direct_IO_enter(inode, offset, count, rw); + /* if (rw == WRITE && whint_mode == WHINT_MODE_OFF) + iocb->ki_hint = WRITE_LIFE_NOT_SET; */ + down_read(&F2FS_I(inode)->dio_rwsem[rw]); err = blockdev_direct_IO(rw, iocb, inode, iter, offset, get_data_block_dio); up_read(&F2FS_I(inode)->dio_rwsem[rw]); if (rw & WRITE) { + /* if (whint_mode == WHINT_MODE_OFF) + iocb->ki_hint = hint; */ if (err > 0) { f2fs_update_iostat(F2FS_I_SB(inode), APP_DIRECT_IO, err); diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 560b707050ca2..41d32171bd524 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -361,6 +361,7 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir, struct page *dpage) { struct page *page; + int dummy_encrypt = DUMMY_ENCRYPTION_ENABLED(F2FS_I_SB(dir)); int err; if (is_inode_flag_set(inode, FI_NEW_INODE)) { @@ -387,7 +388,8 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir, if (err) goto put_error; - if (f2fs_encrypted_inode(dir) && f2fs_may_encrypt(inode)) { + if ((f2fs_encrypted_inode(dir) || dummy_encrypt) && + f2fs_may_encrypt(inode)) { err = fscrypt_inherit_context(dir, inode, page, false); if (err) goto put_error; @@ -396,8 +398,6 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir, page = get_node_page(F2FS_I_SB(dir), inode->i_ino); if (IS_ERR(page)) return page; - - set_cold_node(inode, page); } if (new_name) { @@ -704,7 +704,8 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, f2fs_update_time(F2FS_I_SB(dir), REQ_TIME); - add_ino_entry(F2FS_I_SB(dir), dir->i_ino, TRANS_DIR_INO); + if (F2FS_OPTION(F2FS_I_SB(dir)).fsync_mode == FSYNC_MODE_STRICT) + add_ino_entry(F2FS_I_SB(dir), dir->i_ino, TRANS_DIR_INO); if (f2fs_has_inline_dentry(dir)) return f2fs_delete_inline_entry(dentry, page, dir, inode); diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c index ff2352a0ed157..d5a861bf2b42a 100644 --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c @@ -460,7 +460,7 @@ static struct extent_node *__insert_extent_tree(struct inode *inode, struct rb_node *insert_parent) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - struct rb_node **p = &et->root.rb_node; + struct rb_node **p; struct rb_node *parent = NULL; struct extent_node *en = NULL; @@ -706,6 +706,9 @@ void f2fs_drop_extent_tree(struct inode *inode) struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct extent_tree *et = F2FS_I(inode)->extent_tree; + if (!f2fs_may_extent_tree(inode)) + return; + set_inode_flag(inode, FI_NO_EXTENT); write_lock(&et->lock); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 672ef458173e8..5782e0677186b 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -100,9 +100,10 @@ extern char *fault_name[FAULT_MAX]; #define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 #define F2FS_MOUNT_RESERVE_ROOT 0x01000000 -#define clear_opt(sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option) -#define set_opt(sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option) -#define test_opt(sbi, option) ((sbi)->mount_opt.opt & F2FS_MOUNT_##option) +#define F2FS_OPTION(sbi) ((sbi)->mount_opt) +#define clear_opt(sbi, option) (F2FS_OPTION(sbi).opt &= ~F2FS_MOUNT_##option) +#define set_opt(sbi, option) (F2FS_OPTION(sbi).opt |= F2FS_MOUNT_##option) +#define test_opt(sbi, option) (F2FS_OPTION(sbi).opt & F2FS_MOUNT_##option) #define ver_after(a, b) (typecheck(unsigned long long, a) && \ typecheck(unsigned long long, b) && \ @@ -114,8 +115,31 @@ typedef u32 block_t; /* */ typedef u32 nid_t; +#ifdef CONFIG_QUOTA +#define F2FS_MAXQUOTAS 2 +#endif + struct f2fs_mount_info { - unsigned int opt; + unsigned int opt; + int write_io_size_bits; /* Write IO size bits */ + block_t root_reserved_blocks; /* root reserved blocks */ + kuid_t s_resuid; /* reserved blocks for uid */ + kgid_t s_resgid; /* reserved blocks for gid */ + int active_logs; /* # of active logs */ + int inline_xattr_size; /* inline xattr size */ +#ifdef CONFIG_F2FS_FAULT_INJECTION + struct f2fs_fault_info fault_info; /* For fault injection */ +#endif +#ifdef CONFIG_QUOTA + /* Names of quota files with journalled quota */ + char *s_qf_names[F2FS_MAXQUOTAS]; + int s_jquota_fmt; /* Format of quota to use */ +#endif + /* For which write hints are passed down to block layer */ + int whint_mode; + int alloc_mode; /* segment allocation policy */ + int fsync_mode; /* fsync policy */ + bool test_dummy_encryption; /* test dummy encryption */ }; #define F2FS_FEATURE_ENCRYPT 0x0001 @@ -127,6 +151,8 @@ struct f2fs_mount_info { #define F2FS_FEATURE_FLEXIBLE_INLINE_XATTR 0x0040 #define F2FS_FEATURE_QUOTA_INO 0x0080 #define F2FS_FEATURE_INODE_CRTIME 0x0100 +#define F2FS_FEATURE_LOST_FOUND 0x0200 +#define F2FS_FEATURE_VERITY 0x0400 /* reserved */ #define F2FS_HAS_FEATURE(sb, mask) \ ((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0) @@ -546,7 +572,7 @@ static inline void make_dentry_ptr_block(struct inode *inode, d->inode = inode; d->max = NR_DENTRY_IN_BLOCK; d->nr_bitmap = SIZE_OF_DENTRY_BITMAP; - d->bitmap = &t->dentry_bitmap; + d->bitmap = t->dentry_bitmap; d->dentry = t->dentry; d->filename = t->filename; } @@ -672,6 +698,8 @@ enum { #define FADVISE_ENCRYPT_BIT 0x04 #define FADVISE_ENC_NAME_BIT 0x08 #define FADVISE_KEEP_SIZE_BIT 0x10 +#define FADVISE_HOT_BIT 0x20 +#define FADVISE_VERITY_BIT 0x40 /* reserved */ #define file_is_cold(inode) is_file(inode, FADVISE_COLD_BIT) #define file_wrong_pino(inode) is_file(inode, FADVISE_LOST_PINO_BIT) @@ -686,6 +714,9 @@ enum { #define file_set_enc_name(inode) set_file(inode, FADVISE_ENC_NAME_BIT) #define file_keep_isize(inode) is_file(inode, FADVISE_KEEP_SIZE_BIT) #define file_set_keep_isize(inode) set_file(inode, FADVISE_KEEP_SIZE_BIT) +#define file_is_hot(inode) is_file(inode, FADVISE_HOT_BIT) +#define file_set_hot(inode) set_file(inode, FADVISE_HOT_BIT) +#define file_clear_hot(inode) clear_file(inode, FADVISE_HOT_BIT) #define DEF_DIR_LEVEL 0 @@ -731,6 +762,7 @@ struct f2fs_inode_info { kprojid_t i_projid; /* id for project quota */ int i_inline_xattr_size; /* inline xattr size */ struct timespec i_crtime; /* inode creation time */ + struct timespec i_disk_time[4]; /* inode disk times */ }; static inline void get_extent_info(struct extent_info *ext, @@ -837,7 +869,7 @@ struct f2fs_nm_info { unsigned int nid_cnt[MAX_NID_STATE]; /* the number of free node id */ spinlock_t nid_list_lock; /* protect nid lists ops */ struct mutex build_lock; /* lock for build free nids */ - unsigned char (*free_nid_bitmap)[NAT_ENTRY_BITMAP_SIZE]; + unsigned char **free_nid_bitmap; unsigned char *nat_block_bitmap; unsigned short *free_nid_count; /* free nid count of NAT block */ @@ -1070,6 +1102,7 @@ struct f2fs_io_info { bool submitted; /* indicate IO submission */ int need_lock; /* indicate we need to lock cp_rwsem */ bool in_list; /* indicate fio is in io_list */ + bool is_meta; /* indicate borrow meta inode mapping or not */ enum iostat_type io_type; /* io type */ struct writeback_control *io_wbc; /* writeback control */ }; @@ -1131,14 +1164,34 @@ enum { MAX_TIME, }; -#ifdef CONFIG_QUOTA -#define F2FS_MAXQUOTAS 2 +enum { + WHINT_MODE_OFF, /* not pass down write hints */ + WHINT_MODE_USER, /* try to pass down hints given by users */ + WHINT_MODE_FS, /* pass down hints with F2FS policy */ +}; + +enum { + ALLOC_MODE_DEFAULT, /* stay default */ + ALLOC_MODE_REUSE, /* reuse segments as much as possible */ +}; + +enum fsync_mode { + FSYNC_MODE_POSIX, /* fsync follows posix semantics */ + FSYNC_MODE_STRICT, /* fsync behaves in line with ext4 */ +}; + +#ifdef CONFIG_F2FS_FS_ENCRYPTION +#define DUMMY_ENCRYPTION_ENABLED(sbi) \ + (unlikely(F2FS_OPTION(sbi).test_dummy_encryption)) +#else +#define DUMMY_ENCRYPTION_ENABLED(sbi) (0) #endif struct f2fs_sb_info { struct super_block *sb; /* pointer to VFS super block */ struct proc_dir_entry *s_proc; /* proc entry */ struct f2fs_super_block *raw_super; /* raw super block pointer */ + struct rw_semaphore sb_lock; /* lock for raw super block */ int valid_super_block; /* valid super block no */ unsigned long s_flag; /* flags for sbi */ @@ -1158,7 +1211,6 @@ struct f2fs_sb_info { struct f2fs_bio_info *write_io[NR_PAGE_TYPE]; /* for write bios */ struct mutex wio_mutex[NR_PAGE_TYPE - 1][NR_TEMP_TYPE]; /* bio ordering for NODE/DATA */ - int write_io_size_bits; /* Write IO size bits */ mempool_t *write_io_dummy; /* Dummy pages */ /* for checkpoint */ @@ -1208,9 +1260,7 @@ struct f2fs_sb_info { unsigned int total_node_count; /* total node block count */ unsigned int total_valid_node_count; /* valid node block count */ loff_t max_file_blocks; /* max block index of file */ - int active_logs; /* # of active logs */ int dir_level; /* directory level */ - int inline_xattr_size; /* inline xattr size */ unsigned int trigger_ssr_threshold; /* threshold to trigger ssr */ int readdir_ra; /* readahead inode in readdir */ @@ -1220,9 +1270,6 @@ struct f2fs_sb_info { block_t last_valid_block_count; /* for recovery */ block_t reserved_blocks; /* configurable reserved blocks */ block_t current_reserved_blocks; /* current reserved blocks */ - block_t root_reserved_blocks; /* root reserved blocks */ - kuid_t s_resuid; /* reserved blocks for uid */ - kgid_t s_resgid; /* reserved blocks for gid */ unsigned int nquota_files; /* # of quota sysfile */ @@ -1307,17 +1354,6 @@ struct f2fs_sb_info { /* Precomputed FS UUID checksum for seeding other checksums */ __u32 s_chksum_seed; - - /* For fault injection */ -#ifdef CONFIG_F2FS_FAULT_INJECTION - struct f2fs_fault_info fault_info; -#endif - -#ifdef CONFIG_QUOTA - /* Names of quota files with journalled quota */ - char *s_qf_names[F2FS_MAXQUOTAS]; - int s_jquota_fmt; /* Format of quota to use */ -#endif }; #ifdef CONFIG_F2FS_FAULT_INJECTION @@ -1327,7 +1363,7 @@ struct f2fs_sb_info { __func__, __builtin_return_address(0)) static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type) { - struct f2fs_fault_info *ffi = &sbi->fault_info; + struct f2fs_fault_info *ffi = &F2FS_OPTION(sbi).fault_info; if (!ffi->inject_rate) return false; @@ -1684,12 +1720,12 @@ static inline bool __allow_reserved_blocks(struct f2fs_sb_info *sbi, return false; if (IS_NOQUOTA(inode)) return true; - if (capable(CAP_SYS_RESOURCE)) + if (uid_eq(F2FS_OPTION(sbi).s_resuid, current_fsuid())) return true; - if (uid_eq(sbi->s_resuid, current_fsuid())) + if (!gid_eq(F2FS_OPTION(sbi).s_resgid, GLOBAL_ROOT_GID) && + in_group_p(F2FS_OPTION(sbi).s_resgid)) return true; - if (!gid_eq(sbi->s_resgid, GLOBAL_ROOT_GID) && - in_group_p(sbi->s_resgid)) + if (capable(CAP_SYS_RESOURCE)) return true; return false; } @@ -1725,7 +1761,7 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, sbi->current_reserved_blocks; if (!__allow_reserved_blocks(sbi, inode)) - avail_user_block_count -= sbi->root_reserved_blocks; + avail_user_block_count -= F2FS_OPTION(sbi).root_reserved_blocks; if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) { diff = sbi->total_valid_block_count - avail_user_block_count; @@ -1860,6 +1896,12 @@ static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag) struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); int offset; + if (is_set_ckpt_flags(sbi, CP_LARGE_NAT_BITMAP_FLAG)) { + offset = (flag == SIT_BITMAP) ? + le32_to_cpu(ckpt->nat_ver_bitmap_bytesize) : 0; + return &ckpt->sit_nat_version_bitmap + offset; + } + if (__cp_payload(sbi) > 0) { if (flag == NAT_BITMAP) return &ckpt->sit_nat_version_bitmap; @@ -1926,7 +1968,7 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi, sbi->current_reserved_blocks + 1; if (!__allow_reserved_blocks(sbi, inode)) - valid_block_count += sbi->root_reserved_blocks; + valid_block_count += F2FS_OPTION(sbi).root_reserved_blocks; if (unlikely(valid_block_count > sbi->user_block_count)) { spin_unlock(&sbi->stat_lock); @@ -2528,7 +2570,17 @@ static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync) } if (!is_inode_flag_set(inode, FI_AUTO_RECOVER) || file_keep_isize(inode) || - i_size_read(inode) & PAGE_MASK) + i_size_read(inode) & ~PAGE_MASK) + return false; + + if (!timespec_equal(F2FS_I(inode)->i_disk_time, &inode->i_atime)) + return false; + if (!timespec_equal(F2FS_I(inode)->i_disk_time + 1, &inode->i_ctime)) + return false; + if (!timespec_equal(F2FS_I(inode)->i_disk_time + 2, &inode->i_mtime)) + return false; + if (!timespec_equal(F2FS_I(inode)->i_disk_time + 3, + &F2FS_I(inode)->i_crtime)) return false; down_read(&F2FS_I(inode)->i_sem); @@ -2538,8 +2590,7 @@ static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync) return ret; } -#define sb_rdonly f2fs_readonly -static inline int f2fs_readonly(struct super_block *sb) +static inline bool f2fs_readonly(struct super_block *sb) { return sb->s_flags & MS_RDONLY; } @@ -2727,6 +2778,8 @@ void handle_failed_inode(struct inode *inode); /* * namei.c */ +int update_extension_list(struct f2fs_sb_info *sbi, const char *name, + bool hot, bool set); struct dentry *f2fs_get_parent(struct dentry *child); /* @@ -2899,6 +2952,8 @@ void destroy_segment_manager(struct f2fs_sb_info *sbi); int __init create_segment_manager_caches(void); void destroy_segment_manager_caches(void); int rw_hint_to_seg_type(enum rw_hint hint); +enum rw_hint io_type_to_rw_hint(struct f2fs_sb_info *sbi, enum page_type type, + enum temp_type temp); /* * checkpoint.c @@ -3304,45 +3359,21 @@ static inline bool f2fs_bio_encrypted(struct bio *bio) return bio->bi_private != NULL; } -static inline int f2fs_sb_has_crypto(struct super_block *sb) -{ - return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_ENCRYPT); -} - -static inline int f2fs_sb_mounted_blkzoned(struct super_block *sb) -{ - return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_BLKZONED); +#define F2FS_FEATURE_FUNCS(name, flagname) \ +static inline int f2fs_sb_has_##name(struct super_block *sb) \ +{ \ + return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_##flagname); \ } -static inline int f2fs_sb_has_extra_attr(struct super_block *sb) -{ - return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_EXTRA_ATTR); -} - -static inline int f2fs_sb_has_project_quota(struct super_block *sb) -{ - return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_PRJQUOTA); -} - -static inline int f2fs_sb_has_inode_chksum(struct super_block *sb) -{ - return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_INODE_CHKSUM); -} - -static inline int f2fs_sb_has_flexible_inline_xattr(struct super_block *sb) -{ - return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_FLEXIBLE_INLINE_XATTR); -} - -static inline int f2fs_sb_has_quota_ino(struct super_block *sb) -{ - return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_QUOTA_INO); -} - -static inline int f2fs_sb_has_inode_crtime(struct super_block *sb) -{ - return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_INODE_CRTIME); -} +F2FS_FEATURE_FUNCS(encrypt, ENCRYPT); +F2FS_FEATURE_FUNCS(blkzoned, BLKZONED); +F2FS_FEATURE_FUNCS(extra_attr, EXTRA_ATTR); +F2FS_FEATURE_FUNCS(project_quota, PRJQUOTA); +F2FS_FEATURE_FUNCS(inode_chksum, INODE_CHKSUM); +F2FS_FEATURE_FUNCS(flexible_inline_xattr, FLEXIBLE_INLINE_XATTR); +F2FS_FEATURE_FUNCS(quota_ino, QUOTA_INO); +F2FS_FEATURE_FUNCS(inode_crtime, INODE_CRTIME); +F2FS_FEATURE_FUNCS(lost_found, LOST_FOUND); #ifdef CONFIG_BLK_DEV_ZONED static inline int get_blkz_type(struct f2fs_sb_info *sbi, @@ -3362,7 +3393,7 @@ static inline bool f2fs_discard_en(struct f2fs_sb_info *sbi) { struct request_queue *q = bdev_get_queue(sbi->sb->s_bdev); - return blk_queue_discard(q) || f2fs_sb_mounted_blkzoned(sbi->sb); + return blk_queue_discard(q) || f2fs_sb_has_blkzoned(sbi->sb); } static inline void set_opt_mode(struct f2fs_sb_info *sbi, unsigned int mt) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 1ed7359cf37dd..42288c6562c2a 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -167,9 +167,10 @@ static inline enum cp_reason_type need_do_checkpoint(struct inode *inode) cp_reason = CP_NODE_NEED_CP; else if (test_opt(sbi, FASTBOOT)) cp_reason = CP_FASTBOOT_MODE; - else if (sbi->active_logs == 2) + else if (F2FS_OPTION(sbi).active_logs == 2) cp_reason = CP_SPEC_LOG_NUM; - else if (need_dentry_mark(sbi, inode->i_ino) && + else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT && + need_dentry_mark(sbi, inode->i_ino) && exist_written_data(sbi, F2FS_I(inode)->i_pino, TRANS_DIR_INO)) cp_reason = CP_RECOVER_DIR; @@ -572,7 +573,6 @@ static int truncate_partial_data_page(struct inode *inode, u64 from, int truncate_blocks(struct inode *inode, u64 from, bool lock) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - unsigned int blocksize = inode->i_sb->s_blocksize; struct dnode_of_data dn; pgoff_t free_from; int count = 0, err = 0; @@ -581,7 +581,7 @@ int truncate_blocks(struct inode *inode, u64 from, bool lock) trace_f2fs_truncate_blocks_enter(inode, from); - free_from = (pgoff_t)F2FS_BYTES_TO_BLK(from + blocksize - 1); + free_from = (pgoff_t)F2FS_BLK_ALIGN(from); if (free_from >= sbi->max_file_blocks) goto free_partial; @@ -1353,8 +1353,12 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len, } out: - if (!(mode & FALLOC_FL_KEEP_SIZE) && i_size_read(inode) < new_size) - f2fs_i_size_write(inode, new_size); + if (new_size > i_size_read(inode)) { + if (mode & FALLOC_FL_KEEP_SIZE) + file_set_keep_isize(inode); + else + f2fs_i_size_write(inode, new_size); + } out_sem: up_write(&F2FS_I(inode)->i_mmap_sem); @@ -1718,6 +1722,8 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp) inode_lock(inode); + down_write(&F2FS_I(inode)->dio_rwsem[WRITE]); + if (f2fs_is_volatile_file(inode)) goto err_out; @@ -1736,6 +1742,7 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp) ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 1, false); } err_out: + up_write(&F2FS_I(inode)->dio_rwsem[WRITE]); inode_unlock(inode); mnt_drop_write_file(filp); return ret; @@ -1945,7 +1952,7 @@ static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg) { struct inode *inode = file_inode(filp); - if (!f2fs_sb_has_crypto(inode->i_sb)) + if (!f2fs_sb_has_encrypt(inode->i_sb)) return -EOPNOTSUPP; f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); @@ -1955,7 +1962,7 @@ static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg) static int f2fs_ioc_get_encryption_policy(struct file *filp, unsigned long arg) { - if (!f2fs_sb_has_crypto(file_inode(filp)->i_sb)) + if (!f2fs_sb_has_encrypt(file_inode(filp)->i_sb)) return -EOPNOTSUPP; return fscrypt_ioctl_get_policy(filp, (void __user *)arg); } @@ -1966,16 +1973,18 @@ static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg) struct f2fs_sb_info *sbi = F2FS_I_SB(inode); int err; - if (!f2fs_sb_has_crypto(inode->i_sb)) + if (!f2fs_sb_has_encrypt(inode->i_sb)) return -EOPNOTSUPP; - if (uuid_is_nonzero(sbi->raw_super->encrypt_pw_salt)) - goto got_it; - err = mnt_want_write_file(filp); if (err) return err; + down_write(&sbi->sb_lock); + + if (uuid_is_nonzero(sbi->raw_super->encrypt_pw_salt)) + goto got_it; + /* update superblock with uuid */ generate_random_uuid(sbi->raw_super->encrypt_pw_salt); @@ -1983,15 +1992,16 @@ static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg) if (err) { /* undo new data */ memset(sbi->raw_super->encrypt_pw_salt, 0, 16); - mnt_drop_write_file(filp); - return err; + goto out_err; } - mnt_drop_write_file(filp); got_it: if (copy_to_user((__u8 __user *)arg, sbi->raw_super->encrypt_pw_salt, 16)) - return -EFAULT; - return 0; + err = -EFAULT; +out_err: + up_write(&sbi->sb_lock); + mnt_drop_write_file(filp); + return err; } static int f2fs_ioc_gc(struct file *filp, unsigned long arg) @@ -2052,8 +2062,10 @@ static int f2fs_ioc_gc_range(struct file *filp, unsigned long arg) return ret; end = range.start + range.len; - if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi)) - return -EINVAL; + if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi)) { + ret = -EINVAL; + goto out; + } do_more: if (!range.sync) { if (!mutex_trylock(&sbi->gc_mutex)) { @@ -2699,11 +2711,16 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) inode_lock(inode); ret = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); if (!ret) { + bool preallocated = false; + size_t target_size = 0; int err; - if (iov_iter_fault_in_readable(from, iov_iter_count(from))) + if (iov_iter_fault_in_readable(from, iov_iter_count(from))) { set_inode_flag(inode, FI_NO_PREALLOC); - + } else { + preallocated = true; + target_size = pos + count; + } err = f2fs_preallocate_blocks(inode, pos, count, file->f_flags & O_DIRECT); if (err) { @@ -2716,6 +2733,10 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) blk_finish_plug(&plug); clear_inode_flag(inode, FI_NO_PREALLOC); + /* if we couldn't write data, we should deallocate blocks. */ + if (preallocated && i_size_read(inode) < target_size) + f2fs_truncate(inode); + if (ret > 0) f2fs_update_iostat(F2FS_I_SB(inode), APP_WRITE_IO, ret); } diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 3b26aa19430b8..0ad8b3a7a74dc 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -76,14 +76,15 @@ static int gc_thread_func(void *data) * invalidated soon after by user update or deletion. * So, I'd like to wait some time to collect dirty segments. */ - if (!mutex_trylock(&sbi->gc_mutex)) - goto next; - if (gc_th->gc_urgent) { wait_ms = gc_th->urgent_sleep_time; + mutex_lock(&sbi->gc_mutex); goto do_gc; } + if (!mutex_trylock(&sbi->gc_mutex)) + goto next; + if (!is_idle(sbi)) { increase_sleep_time(gc_th, &wait_ms); mutex_unlock(&sbi->gc_mutex); @@ -161,12 +162,17 @@ static int select_gc_type(struct f2fs_gc_kthread *gc_th, int gc_type) { int gc_mode = (gc_type == BG_GC) ? GC_CB : GC_GREEDY; - if (gc_th && gc_th->gc_idle) { + if (!gc_th) + return gc_mode; + + if (gc_th->gc_idle) { if (gc_th->gc_idle == 1) gc_mode = GC_CB; else if (gc_th->gc_idle == 2) gc_mode = GC_GREEDY; } + if (gc_th->gc_urgent) + gc_mode = GC_GREEDY; return gc_mode; } @@ -188,11 +194,14 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type, } /* we need to check every dirty segments in the FG_GC case */ - if (gc_type != FG_GC && p->max_search > sbi->max_victim_search) + if (gc_type != FG_GC && + (sbi->gc_thread && !sbi->gc_thread->gc_urgent) && + p->max_search > sbi->max_victim_search) p->max_search = sbi->max_victim_search; - /* let's select beginning hot/small space first */ - if (type == CURSEG_HOT_DATA || IS_NODESEG(type)) + /* let's select beginning hot/small space first in no_heap mode*/ + if (test_opt(sbi, NOHEAP) && + (type == CURSEG_HOT_DATA || IS_NODESEG(type))) p->offset = 0; else p->offset = SIT_I(sbi)->last_victim[p->gc_mode]; diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 9f57f2867ceea..eb11d78702ee3 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -284,6 +284,10 @@ static int do_read_inode(struct inode *inode) fi->i_crtime.tv_nsec = le32_to_cpu(ri->i_crtime_nsec); } + F2FS_I(inode)->i_disk_time[0] = inode->i_atime; + F2FS_I(inode)->i_disk_time[1] = inode->i_ctime; + F2FS_I(inode)->i_disk_time[2] = inode->i_mtime; + F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime; f2fs_put_page(node_page, 1); stat_inc_inline_xattr(inode); @@ -439,12 +443,15 @@ void update_inode(struct inode *inode, struct page *node_page) } __set_inode_rdev(inode, ri); - set_cold_node(inode, node_page); /* deleted inode */ if (inode->i_nlink == 0) clear_inline_node(node_page); + F2FS_I(inode)->i_disk_time[0] = inode->i_atime; + F2FS_I(inode)->i_disk_time[1] = inode->i_ctime; + F2FS_I(inode)->i_disk_time[2] = inode->i_mtime; + F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime; } void update_inode_page(struct inode *inode) @@ -585,7 +592,7 @@ void f2fs_evict_inode(struct inode *inode) !exist_written_data(sbi, inode->i_ino, ORPHAN_INO)); } out_clear: - fscrypt_put_encryption_info(inode, NULL); + fscrypt_put_encryption_info(inode); clear_inode(inode); } diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 3a1e0e91576e6..102bca813f18a 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -76,7 +76,8 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) set_inode_flag(inode, FI_NEW_INODE); /* If the directory encrypted, then we should encrypt the inode. */ - if (f2fs_encrypted_inode(dir) && f2fs_may_encrypt(inode)) + if ((f2fs_encrypted_inode(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) && + f2fs_may_encrypt(inode)) f2fs_set_encrypted_inode(inode); if (f2fs_sb_has_extra_attr(sbi->sb)) { @@ -95,7 +96,7 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) if (f2fs_sb_has_flexible_inline_xattr(sbi->sb)) { f2fs_bug_on(sbi, !f2fs_has_extra_attr(inode)); if (f2fs_has_inline_xattr(inode)) - xattr_size = sbi->inline_xattr_size; + xattr_size = F2FS_OPTION(sbi).inline_xattr_size; /* Otherwise, will be 0 */ } else if (f2fs_has_inline_xattr(inode) || f2fs_has_inline_dentry(inode)) { @@ -140,7 +141,7 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) return ERR_PTR(err); } -static int is_multimedia_file(const unsigned char *s, const char *sub) +static int is_extension_exist(const unsigned char *s, const char *sub) { size_t slen = strlen(s); size_t sublen = strlen(sub); @@ -166,19 +167,94 @@ static int is_multimedia_file(const unsigned char *s, const char *sub) /* * Set multimedia files as cold files for hot/cold data separation */ -static inline void set_cold_files(struct f2fs_sb_info *sbi, struct inode *inode, +static inline void set_file_temperature(struct f2fs_sb_info *sbi, struct inode *inode, const unsigned char *name) { - int i; - __u8 (*extlist)[8] = sbi->raw_super->extension_list; + __u8 (*extlist)[F2FS_EXTENSION_LEN] = sbi->raw_super->extension_list; + int i, cold_count, hot_count; + + down_read(&sbi->sb_lock); + + cold_count = le32_to_cpu(sbi->raw_super->extension_count); + hot_count = sbi->raw_super->hot_ext_count; - int count = le32_to_cpu(sbi->raw_super->extension_count); - for (i = 0; i < count; i++) { - if (is_multimedia_file(name, extlist[i])) { + for (i = 0; i < cold_count + hot_count; i++) { + if (!is_extension_exist(name, extlist[i])) + continue; + if (i < cold_count) file_set_cold(inode); - break; - } + else + file_set_hot(inode); + break; } + + up_read(&sbi->sb_lock); +} + +int update_extension_list(struct f2fs_sb_info *sbi, const char *name, + bool hot, bool set) +{ + __u8 (*extlist)[F2FS_EXTENSION_LEN] = sbi->raw_super->extension_list; + int cold_count = le32_to_cpu(sbi->raw_super->extension_count); + int hot_count = sbi->raw_super->hot_ext_count; + int total_count = cold_count + hot_count; + int start, count; + int i; + + if (set) { + if (total_count == F2FS_MAX_EXTENSION) + return -EINVAL; + } else { + if (!hot && !cold_count) + return -EINVAL; + if (hot && !hot_count) + return -EINVAL; + } + + if (hot) { + start = cold_count; + count = total_count; + } else { + start = 0; + count = cold_count; + } + + for (i = start; i < count; i++) { + if (strcmp(name, extlist[i])) + continue; + + if (set) + return -EINVAL; + + memcpy(extlist[i], extlist[i + 1], + F2FS_EXTENSION_LEN * (total_count - i - 1)); + memset(extlist[total_count - 1], 0, F2FS_EXTENSION_LEN); + if (hot) + sbi->raw_super->hot_ext_count = hot_count - 1; + else + sbi->raw_super->extension_count = + cpu_to_le32(cold_count - 1); + return 0; + } + + if (!set) + return -EINVAL; + + if (hot) { + strncpy(extlist[count], name, strlen(name)); + sbi->raw_super->hot_ext_count = hot_count + 1; + } else { + char buf[F2FS_MAX_EXTENSION][F2FS_EXTENSION_LEN]; + + memcpy(buf, &extlist[cold_count], + F2FS_EXTENSION_LEN * hot_count); + memset(extlist[cold_count], 0, F2FS_EXTENSION_LEN); + strncpy(extlist[cold_count], name, strlen(name)); + memcpy(&extlist[cold_count + 1], buf, + F2FS_EXTENSION_LEN * hot_count); + sbi->raw_super->extension_count = cpu_to_le32(cold_count + 1); + } + return 0; } static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode, @@ -199,7 +275,7 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode, return PTR_ERR(inode); if (!test_opt(sbi, DISABLE_EXT_IDENTIFY)) - set_cold_files(sbi, inode, dentry->d_name.name); + set_file_temperature(sbi, inode, dentry->d_name.name); inode->i_op = &f2fs_file_inode_operations; inode->i_fop = &f2fs_file_operations; @@ -477,27 +553,16 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, struct f2fs_sb_info *sbi = F2FS_I_SB(dir); struct inode *inode; size_t len = strlen(symname); - struct fscrypt_str disk_link = FSTR_INIT((char *)symname, len + 1); - struct fscrypt_symlink_data *sd = NULL; + struct fscrypt_str disk_link; int err; if (unlikely(f2fs_cp_error(sbi))) return -EIO; - if (f2fs_encrypted_inode(dir)) { - err = fscrypt_get_encryption_info(dir); - if (err) - return err; - - if (!fscrypt_has_encryption_key(dir)) - return -ENOKEY; - - disk_link.len = (fscrypt_fname_encrypted_size(dir, len) + - sizeof(struct fscrypt_symlink_data)); - } - - if (disk_link.len > dir->i_sb->s_blocksize) - return -ENAMETOOLONG; + err = fscrypt_prepare_symlink(dir, symname, len, dir->i_sb->s_blocksize, + &disk_link); + if (err) + return err; dquot_initialize(dir); @@ -505,7 +570,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, if (IS_ERR(inode)) return PTR_ERR(inode); - if (f2fs_encrypted_inode(inode)) + if (IS_ENCRYPTED(inode)) inode->i_op = &f2fs_encrypted_symlink_inode_operations; else inode->i_op = &f2fs_symlink_inode_operations; @@ -515,38 +580,13 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, f2fs_lock_op(sbi); err = f2fs_add_link(dentry, inode); if (err) - goto out; + goto out_handle_failed_inode; f2fs_unlock_op(sbi); alloc_nid_done(sbi, inode->i_ino); - if (f2fs_encrypted_inode(inode)) { - struct qstr istr = QSTR_INIT(symname, len); - struct fscrypt_str ostr; - - sd = f2fs_kzalloc(sbi, disk_link.len, GFP_NOFS); - if (!sd) { - err = -ENOMEM; - goto err_out; - } - - err = fscrypt_get_encryption_info(inode); - if (err) - goto err_out; - - if (!fscrypt_has_encryption_key(inode)) { - err = -ENOKEY; - goto err_out; - } - - ostr.name = sd->encrypted_path; - ostr.len = disk_link.len; - err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr); - if (err) - goto err_out; - - sd->len = cpu_to_le16(ostr.len); - disk_link.name = (char *)sd; - } + err = fscrypt_encrypt_symlink(inode, symname, len, &disk_link); + if (err) + goto err_out; err = page_symlink(inode, disk_link.name, disk_link.len); @@ -573,12 +613,14 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, f2fs_unlink(dir, dentry); } - kfree(sd); - f2fs_balance_fs(sbi, true); - return err; -out: + goto out_free_encrypted_link; + +out_handle_failed_inode: handle_failed_inode(inode); +out_free_encrypted_link: + if (disk_link.name != (unsigned char *)symname) + kfree(disk_link.name); return err; } @@ -736,10 +778,12 @@ static int __f2fs_tmpfile(struct inode *dir, struct dentry *dentry, static int f2fs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) { - if (unlikely(f2fs_cp_error(F2FS_I_SB(dir)))) + struct f2fs_sb_info *sbi = F2FS_I_SB(dir); + + if (unlikely(f2fs_cp_error(sbi))) return -EIO; - if (f2fs_encrypted_inode(dir)) { + if (f2fs_encrypted_inode(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) { int err = fscrypt_get_encryption_info(dir); if (err) return err; @@ -912,7 +956,8 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, f2fs_put_page(old_dir_page, 0); f2fs_i_links_write(old_dir, false); } - add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO); + if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT) + add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO); f2fs_unlock_op(sbi); @@ -1058,8 +1103,10 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, } f2fs_mark_inode_dirty_sync(new_dir, false); - add_ino_entry(sbi, old_dir->i_ino, TRANS_DIR_INO); - add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO); + if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT) { + add_ino_entry(sbi, old_dir->i_ino, TRANS_DIR_INO); + add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO); + } f2fs_unlock_op(sbi); @@ -1110,68 +1157,21 @@ static int f2fs_rename2(struct inode *old_dir, struct dentry *old_dentry, static void *f2fs_encrypted_follow_link(struct dentry *dentry, struct nameidata *nd) { - struct page *cpage = NULL; - char *caddr, *paddr = NULL; - struct fscrypt_str cstr = FSTR_INIT(NULL, 0); - struct fscrypt_str pstr = FSTR_INIT(NULL, 0); - struct fscrypt_symlink_data *sd; struct inode *inode = d_inode(dentry); - u32 max_size = inode->i_sb->s_blocksize; - int res; - - res = fscrypt_get_encryption_info(inode); - if (res) - return ERR_PTR(res); - - cpage = read_mapping_page(inode->i_mapping, 0, NULL); - if (IS_ERR(cpage)) - return ERR_CAST(cpage); - caddr = kmap(cpage); - - /* Symlink is encrypted */ - sd = (struct fscrypt_symlink_data *)caddr; - cstr.name = sd->encrypted_path; - cstr.len = le16_to_cpu(sd->len); - - /* this is broken symlink case */ - if (unlikely(cstr.len == 0)) { - res = -ENOENT; - goto errout; - } - - if ((cstr.len + sizeof(struct fscrypt_symlink_data) - 1) > max_size) { - /* Symlink data on the disk is corrupted */ - res = -EIO; - goto errout; - } - res = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr); - if (res) - goto errout; - - res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr); - if (res) - goto errout; - - /* this is broken symlink case */ - if (unlikely(pstr.name[0] == 0)) { - res = -ENOENT; - goto errout; - } + struct page *page; + void *target; - paddr = pstr.name; + if (!dentry) + return ERR_PTR(-ECHILD); - /* Null-terminate the name */ - paddr[pstr.len] = '\0'; - nd_set_link(nd, paddr); + page = read_mapping_page(inode->i_mapping, 0, NULL); + if (IS_ERR(page)) + return ERR_CAST(page); - kunmap(cpage); - page_cache_release(cpage); - return NULL; -errout: - fscrypt_fname_free_buffer(&pstr); - kunmap(cpage); - page_cache_release(cpage); - return ERR_PTR(res); + target = fscrypt_get_symlink(inode, page_address(page), + inode->i_sb->s_blocksize, nd); + put_page(page); + return target; } const struct inode_operations f2fs_encrypted_symlink_inode_operations = { diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 1902530d50b42..ef98dbab58136 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -193,8 +193,8 @@ static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e) __free_nat_entry(e); } -static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i, - struct nat_entry *ne) +static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i, + struct nat_entry *ne) { nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid); struct nat_entry_set *head; @@ -209,15 +209,36 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i, head->entry_cnt = 0; f2fs_radix_tree_insert(&nm_i->nat_set_root, set, head); } + return head; +} + +static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i, + struct nat_entry *ne) +{ + struct nat_entry_set *head; + bool new_ne = nat_get_blkaddr(ne) == NEW_ADDR; + + if (!new_ne) + head = __grab_nat_entry_set(nm_i, ne); + + /* + * update entry_cnt in below condition: + * 1. update NEW_ADDR to valid block address; + * 2. update old block address to new one; + */ + if (!new_ne && (get_nat_flag(ne, IS_PREALLOC) || + !get_nat_flag(ne, IS_DIRTY))) + head->entry_cnt++; + + set_nat_flag(ne, IS_PREALLOC, new_ne); if (get_nat_flag(ne, IS_DIRTY)) goto refresh_list; nm_i->dirty_nat_cnt++; - head->entry_cnt++; set_nat_flag(ne, IS_DIRTY, true); refresh_list: - if (nat_get_blkaddr(ne) == NEW_ADDR) + if (new_ne) list_del_init(&ne->list); else list_move_tail(&ne->list, &head->entry_list); @@ -1076,7 +1097,7 @@ struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs) f2fs_wait_on_page_writeback(page, NODE, true); fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true); - set_cold_node(dn->inode, page); + set_cold_node(page, S_ISDIR(dn->inode->i_mode)); if (!PageUptodate(page)) SetPageUptodate(page); if (set_page_dirty(page)) @@ -2314,6 +2335,7 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) if (!PageUptodate(ipage)) SetPageUptodate(ipage); fill_node_footer(ipage, ino, ino, 0, true); + set_cold_node(page, false); src = F2FS_INODE(page); dst = F2FS_INODE(ipage); @@ -2603,8 +2625,7 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi) if (!enabled_nat_bits(sbi, NULL)) return 0; - nm_i->nat_bits_blocks = F2FS_BYTES_TO_BLK((nat_bits_bytes << 1) + 8 + - F2FS_BLKSIZE - 1); + nm_i->nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8); nm_i->nat_bits = f2fs_kzalloc(sbi, nm_i->nat_bits_blocks << F2FS_BLKSIZE_BITS, GFP_KERNEL); if (!nm_i->nat_bits) @@ -2730,12 +2751,20 @@ static int init_node_manager(struct f2fs_sb_info *sbi) static int init_free_nid_cache(struct f2fs_sb_info *sbi) { struct f2fs_nm_info *nm_i = NM_I(sbi); + int i; - nm_i->free_nid_bitmap = f2fs_kvzalloc(sbi, nm_i->nat_blocks * - NAT_ENTRY_BITMAP_SIZE, GFP_KERNEL); + nm_i->free_nid_bitmap = f2fs_kzalloc(sbi, nm_i->nat_blocks * + sizeof(unsigned char *), GFP_KERNEL); if (!nm_i->free_nid_bitmap) return -ENOMEM; + for (i = 0; i < nm_i->nat_blocks; i++) { + nm_i->free_nid_bitmap[i] = f2fs_kvzalloc(sbi, + NAT_ENTRY_BITMAP_SIZE_ALIGNED, GFP_KERNEL); + if (!nm_i->free_nid_bitmap) + return -ENOMEM; + } + nm_i->nat_block_bitmap = f2fs_kvzalloc(sbi, nm_i->nat_blocks / 8, GFP_KERNEL); if (!nm_i->nat_block_bitmap) @@ -2826,7 +2855,13 @@ void destroy_node_manager(struct f2fs_sb_info *sbi) up_write(&nm_i->nat_tree_lock); kvfree(nm_i->nat_block_bitmap); - kvfree(nm_i->free_nid_bitmap); + if (nm_i->free_nid_bitmap) { + int i; + + for (i = 0; i < nm_i->nat_blocks; i++) + kvfree(nm_i->free_nid_bitmap[i]); + kfree(nm_i->free_nid_bitmap); + } kvfree(nm_i->free_nid_count); kfree(nm_i->nat_bitmap); diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h index 081ef0d672bf5..b95e49e4a928a 100644 --- a/fs/f2fs/node.h +++ b/fs/f2fs/node.h @@ -44,6 +44,7 @@ enum { HAS_FSYNCED_INODE, /* is the inode fsynced before? */ HAS_LAST_FSYNC, /* has the latest node fsync mark? */ IS_DIRTY, /* this nat entry is dirty? */ + IS_PREALLOC, /* nat entry is preallocated */ }; /* @@ -422,12 +423,12 @@ static inline void clear_inline_node(struct page *page) ClearPageChecked(page); } -static inline void set_cold_node(struct inode *inode, struct page *page) +static inline void set_cold_node(struct page *page, bool is_dir) { struct f2fs_node *rn = F2FS_NODE(page); unsigned int flag = le32_to_cpu(rn->footer.flag); - if (S_ISDIR(inode->i_mode)) + if (is_dir) flag &= ~(0x1 << COLD_BIT_SHIFT); else flag |= (0x1 << COLD_BIT_SHIFT); diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 14653f483a4c8..54e9db1fe6b9d 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -236,6 +236,9 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head, struct curseg_info *curseg; struct page *page = NULL; block_t blkaddr; + unsigned int loop_cnt = 0; + unsigned int free_blocks = sbi->user_block_count - + valid_user_blocks(sbi); int err = 0; /* get node pages in the current segment */ @@ -288,6 +291,17 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head, if (IS_INODE(page) && is_dent_dnode(page)) entry->last_dentry = blkaddr; next: + /* sanity check in order to detect looped node chain */ + if (++loop_cnt >= free_blocks || + blkaddr == next_blkaddr_of_node(page)) { + f2fs_msg(sbi->sb, KERN_NOTICE, + "%s: detect looped node chain, " + "blkaddr:%u, next:%u", + __func__, blkaddr, next_blkaddr_of_node(page)); + err = -EINVAL; + break; + } + /* check next segment */ blkaddr = next_blkaddr_of_node(page); f2fs_put_page(page, 1); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index f0d69e6e2650f..127bd4814a616 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -1492,12 +1492,11 @@ static int issue_discard_thread(void *data) if (kthread_should_stop()) return 0; - if (dcc->discard_wake) { + if (dcc->discard_wake) dcc->discard_wake = 0; - if (sbi->gc_thread && sbi->gc_thread->gc_urgent) - init_discard_policy(&dpolicy, - DPOLICY_FORCE, 1); - } + + if (sbi->gc_thread && sbi->gc_thread->gc_urgent) + init_discard_policy(&dpolicy, DPOLICY_FORCE, 1); sb_start_intwrite(sbi->sb); @@ -1566,7 +1565,7 @@ static int __issue_discard_async(struct f2fs_sb_info *sbi, struct block_device *bdev, block_t blkstart, block_t blklen) { #ifdef CONFIG_BLK_DEV_ZONED - if (f2fs_sb_mounted_blkzoned(sbi->sb) && + if (f2fs_sb_has_blkzoned(sbi->sb) && bdev_zoned_model(bdev) != BLK_ZONED_NONE) return __f2fs_issue_discard_zone(sbi, bdev, blkstart, blklen); #endif @@ -1764,7 +1763,7 @@ void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc) sbi->blocks_per_seg, cur_pos); len = next_pos - cur_pos; - if (f2fs_sb_mounted_blkzoned(sbi->sb) || + if (f2fs_sb_has_blkzoned(sbi->sb) || (force && len < cpc->trim_minlen)) goto skip; @@ -1808,7 +1807,7 @@ void init_discard_policy(struct discard_policy *dpolicy, } else if (discard_type == DPOLICY_FORCE) { dpolicy->min_interval = DEF_MIN_DISCARD_ISSUE_TIME; dpolicy->max_interval = DEF_MAX_DISCARD_ISSUE_TIME; - dpolicy->io_aware = true; + dpolicy->io_aware = false; } else if (discard_type == DPOLICY_FSTRIM) { dpolicy->io_aware = false; } else if (discard_type == DPOLICY_UMOUNT) { @@ -1944,7 +1943,7 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) sbi->discard_blks--; /* don't overwrite by SSR to keep node chain */ - if (se->type == CURSEG_WARM_NODE) { + if (IS_NODESEG(se->type)) { if (!f2fs_test_and_set_bit(offset, se->ckpt_valid_map)) se->ckpt_valid_blocks++; } @@ -2245,11 +2244,17 @@ static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type) if (sbi->segs_per_sec != 1) return CURSEG_I(sbi, type)->segno; - if (type == CURSEG_HOT_DATA || IS_NODESEG(type)) + if (test_opt(sbi, NOHEAP) && + (type == CURSEG_HOT_DATA || IS_NODESEG(type))) return 0; if (SIT_I(sbi)->last_victim[ALLOC_NEXT]) return SIT_I(sbi)->last_victim[ALLOC_NEXT]; + + /* find segments from 0 to reuse freed segments */ + if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_REUSE) + return 0; + return CURSEG_I(sbi, type)->segno; } @@ -2536,6 +2541,101 @@ int rw_hint_to_seg_type(enum rw_hint hint) } } +/* This returns write hints for each segment type. This hints will be + * passed down to block layer. There are mapping tables which depend on + * the mount option 'whint_mode'. + * + * 1) whint_mode=off. F2FS only passes down WRITE_LIFE_NOT_SET. + * + * 2) whint_mode=user-based. F2FS tries to pass down hints given by users. + * + * User F2FS Block + * ---- ---- ----- + * META WRITE_LIFE_NOT_SET + * HOT_NODE " + * WARM_NODE " + * COLD_NODE " + * ioctl(COLD) COLD_DATA WRITE_LIFE_EXTREME + * extension list " " + * + * -- buffered io + * WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME + * WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT + * WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_NOT_SET + * WRITE_LIFE_NONE " " + * WRITE_LIFE_MEDIUM " " + * WRITE_LIFE_LONG " " + * + * -- direct io + * WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME + * WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT + * WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_NOT_SET + * WRITE_LIFE_NONE " WRITE_LIFE_NONE + * WRITE_LIFE_MEDIUM " WRITE_LIFE_MEDIUM + * WRITE_LIFE_LONG " WRITE_LIFE_LONG + * + * 3) whint_mode=fs-based. F2FS passes down hints with its policy. + * + * User F2FS Block + * ---- ---- ----- + * META WRITE_LIFE_MEDIUM; + * HOT_NODE WRITE_LIFE_NOT_SET + * WARM_NODE " + * COLD_NODE WRITE_LIFE_NONE + * ioctl(COLD) COLD_DATA WRITE_LIFE_EXTREME + * extension list " " + * + * -- buffered io + * WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME + * WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT + * WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_LONG + * WRITE_LIFE_NONE " " + * WRITE_LIFE_MEDIUM " " + * WRITE_LIFE_LONG " " + * + * -- direct io + * WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME + * WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT + * WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_NOT_SET + * WRITE_LIFE_NONE " WRITE_LIFE_NONE + * WRITE_LIFE_MEDIUM " WRITE_LIFE_MEDIUM + * WRITE_LIFE_LONG " WRITE_LIFE_LONG + */ + +enum rw_hint io_type_to_rw_hint(struct f2fs_sb_info *sbi, + enum page_type type, enum temp_type temp) +{ + if (F2FS_OPTION(sbi).whint_mode == WHINT_MODE_USER) { + if (type == DATA) { + if (temp == WARM) + return WRITE_LIFE_NOT_SET; + else if (temp == HOT) + return WRITE_LIFE_SHORT; + else if (temp == COLD) + return WRITE_LIFE_EXTREME; + } else { + return WRITE_LIFE_NOT_SET; + } + } else if (F2FS_OPTION(sbi).whint_mode == WHINT_MODE_FS) { + if (type == DATA) { + if (temp == WARM) + return WRITE_LIFE_LONG; + else if (temp == HOT) + return WRITE_LIFE_SHORT; + else if (temp == COLD) + return WRITE_LIFE_EXTREME; + } else if (type == NODE) { + if (temp == WARM || temp == HOT) + return WRITE_LIFE_NOT_SET; + else if (temp == COLD) + return WRITE_LIFE_NONE; + } else if (type == META) { + return WRITE_LIFE_MEDIUM; + } + } + return WRITE_LIFE_NOT_SET; +} + static int __get_segment_type_2(struct f2fs_io_info *fio) { if (fio->type == DATA) @@ -2568,7 +2668,8 @@ static int __get_segment_type_6(struct f2fs_io_info *fio) if (is_cold_data(fio->page) || file_is_cold(inode)) return CURSEG_COLD_DATA; - if (is_inode_flag_set(inode, FI_HOT_DATA)) + if (file_is_hot(inode) || + is_inode_flag_set(inode, FI_HOT_DATA)) return CURSEG_HOT_DATA; /* rw_hint_to_seg_type(inode->i_write_hint); */ @@ -2585,7 +2686,7 @@ static int __get_segment_type(struct f2fs_io_info *fio) { int type = 0; - switch (fio->sbi->active_logs) { + switch (F2FS_OPTION(fio->sbi).active_logs) { case 2: type = __get_segment_type_2(fio); break; @@ -2725,6 +2826,7 @@ void write_meta_page(struct f2fs_sb_info *sbi, struct page *page, struct f2fs_io_info fio = { .sbi = sbi, .type = META, + .temp = HOT, .op = REQ_OP_WRITE, .op_flags = REQ_SYNC | REQ_META | REQ_PRIO, .old_blkaddr = page->index, @@ -2771,8 +2873,15 @@ void write_data_page(struct dnode_of_data *dn, struct f2fs_io_info *fio) int rewrite_data_page(struct f2fs_io_info *fio) { int err; + struct f2fs_sb_info *sbi = fio->sbi; fio->new_blkaddr = fio->old_blkaddr; + /* i/o temperature is needed for passing down write hints */ + __get_segment_type(fio); + + f2fs_bug_on(sbi, !IS_DATASEG(get_seg_entry(sbi, + GET_SEGNO(sbi, fio->new_blkaddr))->type)); + stat_inc_inplace_blocks(fio->sbi); err = f2fs_submit_page_bio(fio); diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 87b4ca0c60dad..c22f7a2db7201 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -52,13 +52,19 @@ ((secno) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno / \ (sbi)->segs_per_sec)) \ -#define MAIN_BLKADDR(sbi) (SM_I(sbi)->main_blkaddr) -#define SEG0_BLKADDR(sbi) (SM_I(sbi)->seg0_blkaddr) +#define MAIN_BLKADDR(sbi) \ + (SM_I(sbi) ? SM_I(sbi)->main_blkaddr : \ + le32_to_cpu(F2FS_RAW_SUPER(sbi)->main_blkaddr)) +#define SEG0_BLKADDR(sbi) \ + (SM_I(sbi) ? SM_I(sbi)->seg0_blkaddr : \ + le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment0_blkaddr)) #define MAIN_SEGS(sbi) (SM_I(sbi)->main_segments) #define MAIN_SECS(sbi) ((sbi)->total_sections) -#define TOTAL_SEGS(sbi) (SM_I(sbi)->segment_count) +#define TOTAL_SEGS(sbi) \ + (SM_I(sbi) ? SM_I(sbi)->segment_count : \ + le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count)) #define TOTAL_BLKS(sbi) (TOTAL_SEGS(sbi) << (sbi)->log_blocks_per_seg) #define MAX_BLKADDR(sbi) (SEG0_BLKADDR(sbi) + TOTAL_BLKS(sbi)) @@ -595,6 +601,8 @@ static inline int utilization(struct f2fs_sb_info *sbi) #define DEF_MIN_FSYNC_BLOCKS 8 #define DEF_MIN_HOT_BLOCKS 16 +#define SMALL_VOLUME_SEGMENTS (16 * 512) /* 16GB */ + enum { F2FS_IPU_FORCE, F2FS_IPU_SSR, @@ -629,10 +637,17 @@ static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno) f2fs_bug_on(sbi, segno > TOTAL_SEGS(sbi) - 1); } -static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr) +static inline void verify_block_addr(struct f2fs_io_info *fio, block_t blk_addr) { - BUG_ON(blk_addr < SEG0_BLKADDR(sbi) - || blk_addr >= MAX_BLKADDR(sbi)); + struct f2fs_sb_info *sbi = fio->sbi; + + if (PAGE_TYPE_OF_BIO(fio->type) == META && + (!is_read_io(fio->op) || fio->is_meta)) + BUG_ON(blk_addr < SEG0_BLKADDR(sbi) || + blk_addr >= MAIN_BLKADDR(sbi)); + else + BUG_ON(blk_addr < MAIN_BLKADDR(sbi) || + blk_addr >= MAX_BLKADDR(sbi)); } /* diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 5f8e5f2249e97..949cbe02ec241 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -63,7 +63,7 @@ char *fault_name[FAULT_MAX] = { static void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate) { - struct f2fs_fault_info *ffi = &sbi->fault_info; + struct f2fs_fault_info *ffi = &F2FS_OPTION(sbi).fault_info; if (rate) { atomic_set(&ffi->inject_ops, 0); @@ -132,6 +132,10 @@ enum { Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, + Opt_whint, + Opt_alloc, + Opt_fsync, + Opt_test_dummy_encryption, Opt_err, }; @@ -185,6 +189,10 @@ static match_table_t f2fs_tokens = { {Opt_jqfmt_vfsold, "jqfmt=vfsold"}, {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, {Opt_jqfmt_vfsv1, "jqfmt=vfsv1"}, + {Opt_whint, "whint_mode=%s"}, + {Opt_alloc, "alloc_mode=%s"}, + {Opt_fsync, "fsync_mode=%s"}, + {Opt_test_dummy_encryption, "test_dummy_encryption"}, {Opt_err, NULL}, }; @@ -205,21 +213,24 @@ static inline void limit_reserve_root(struct f2fs_sb_info *sbi) block_t limit = (sbi->user_block_count << 1) / 1000; /* limit is 0.2% */ - if (test_opt(sbi, RESERVE_ROOT) && sbi->root_reserved_blocks > limit) { - sbi->root_reserved_blocks = limit; + if (test_opt(sbi, RESERVE_ROOT) && + F2FS_OPTION(sbi).root_reserved_blocks > limit) { + F2FS_OPTION(sbi).root_reserved_blocks = limit; f2fs_msg(sbi->sb, KERN_INFO, "Reduce reserved blocks for root = %u", - sbi->root_reserved_blocks); + F2FS_OPTION(sbi).root_reserved_blocks); } if (!test_opt(sbi, RESERVE_ROOT) && - (!uid_eq(sbi->s_resuid, + (!uid_eq(F2FS_OPTION(sbi).s_resuid, make_kuid(&init_user_ns, F2FS_DEF_RESUID)) || - !gid_eq(sbi->s_resgid, + !gid_eq(F2FS_OPTION(sbi).s_resgid, make_kgid(&init_user_ns, F2FS_DEF_RESGID)))) f2fs_msg(sbi->sb, KERN_INFO, "Ignore s_resuid=%u, s_resgid=%u w/o reserve_root", - from_kuid_munged(&init_user_ns, sbi->s_resuid), - from_kgid_munged(&init_user_ns, sbi->s_resgid)); + from_kuid_munged(&init_user_ns, + F2FS_OPTION(sbi).s_resuid), + from_kgid_munged(&init_user_ns, + F2FS_OPTION(sbi).s_resgid)); } static void init_once(void *foo) @@ -242,7 +253,7 @@ static int f2fs_set_qf_name(struct super_block *sb, int qtype, if (F2FS_MAXQUOTAS <= 2 && qtype == PRJQUOTA) return -EINVAL; - if (sb_any_quota_loaded(sb) && !sbi->s_qf_names[qtype]) { + if (sb_any_quota_loaded(sb) && !F2FS_OPTION(sbi).s_qf_names[qtype]) { f2fs_msg(sb, KERN_ERR, "Cannot change journaled " "quota options when quota turned on"); @@ -260,8 +271,8 @@ static int f2fs_set_qf_name(struct super_block *sb, int qtype, "Not enough memory for storing quotafile name"); return -EINVAL; } - if (sbi->s_qf_names[qtype]) { - if (strcmp(sbi->s_qf_names[qtype], qname) == 0) + if (F2FS_OPTION(sbi).s_qf_names[qtype]) { + if (strcmp(F2FS_OPTION(sbi).s_qf_names[qtype], qname) == 0) ret = 0; else f2fs_msg(sb, KERN_ERR, @@ -274,7 +285,7 @@ static int f2fs_set_qf_name(struct super_block *sb, int qtype, "quotafile must be on filesystem root"); goto errout; } - sbi->s_qf_names[qtype] = qname; + F2FS_OPTION(sbi).s_qf_names[qtype] = qname; set_opt(sbi, QUOTA); return 0; errout: @@ -289,13 +300,13 @@ static int f2fs_clear_qf_name(struct super_block *sb, int qtype) if (F2FS_MAXQUOTAS <= 2 && qtype == PRJQUOTA) return -EINVAL; - if (sb_any_quota_loaded(sb) && sbi->s_qf_names[qtype]) { + if (sb_any_quota_loaded(sb) && F2FS_OPTION(sbi).s_qf_names[qtype]) { f2fs_msg(sb, KERN_ERR, "Cannot change journaled quota options" " when quota turned on"); return -EINVAL; } - kfree(sbi->s_qf_names[qtype]); - sbi->s_qf_names[qtype] = NULL; + kfree(F2FS_OPTION(sbi).s_qf_names[qtype]); + F2FS_OPTION(sbi).s_qf_names[qtype] = NULL; return 0; } @@ -312,16 +323,20 @@ static int f2fs_check_quota_options(struct f2fs_sb_info *sbi) "Cannot enable project quota enforcement."); return -1; } - if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA] || - (F2FS_MAXQUOTAS > 2 && sbi->s_qf_names[PRJQUOTA])) { - if (test_opt(sbi, USRQUOTA) && sbi->s_qf_names[USRQUOTA]) + if (F2FS_OPTION(sbi).s_qf_names[USRQUOTA] || + F2FS_OPTION(sbi).s_qf_names[GRPQUOTA] || + (F2FS_MAXQUOTAS > 2 && + F2FS_OPTION(sbi).s_qf_names[PRJQUOTA])) { + if (test_opt(sbi, USRQUOTA) && + F2FS_OPTION(sbi).s_qf_names[USRQUOTA]) clear_opt(sbi, USRQUOTA); - if (test_opt(sbi, GRPQUOTA) && sbi->s_qf_names[GRPQUOTA]) + if (test_opt(sbi, GRPQUOTA) && + F2FS_OPTION(sbi).s_qf_names[GRPQUOTA]) clear_opt(sbi, GRPQUOTA); if (F2FS_MAXQUOTAS > 2 && test_opt(sbi, PRJQUOTA) && - sbi->s_qf_names[PRJQUOTA]) + F2FS_OPTION(sbi).s_qf_names[PRJQUOTA]) clear_opt(sbi, PRJQUOTA); if (test_opt(sbi, GRPQUOTA) || test_opt(sbi, USRQUOTA) || @@ -331,19 +346,19 @@ static int f2fs_check_quota_options(struct f2fs_sb_info *sbi) return -1; } - if (!sbi->s_jquota_fmt) { + if (!F2FS_OPTION(sbi).s_jquota_fmt) { f2fs_msg(sbi->sb, KERN_ERR, "journaled quota format " "not specified"); return -1; } } - if (f2fs_sb_has_quota_ino(sbi->sb) && sbi->s_jquota_fmt) { + if (f2fs_sb_has_quota_ino(sbi->sb) && F2FS_OPTION(sbi).s_jquota_fmt) { f2fs_msg(sbi->sb, KERN_INFO, "QUOTA feature is enabled, so ignore jquota_fmt"); - sbi->s_jquota_fmt = 0; + F2FS_OPTION(sbi).s_jquota_fmt = 0; } - if (f2fs_sb_has_quota_ino(sbi->sb) && sb_rdonly(sbi->sb)) { + if (f2fs_sb_has_quota_ino(sbi->sb) && f2fs_readonly(sbi->sb)) { f2fs_msg(sbi->sb, KERN_INFO, "Filesystem with quota feature cannot be mounted RDWR " "without CONFIG_QUOTA"); @@ -414,14 +429,14 @@ static int parse_options(struct super_block *sb, char *options) q = bdev_get_queue(sb->s_bdev); if (blk_queue_discard(q)) { set_opt(sbi, DISCARD); - } else if (!f2fs_sb_mounted_blkzoned(sb)) { + } else if (!f2fs_sb_has_blkzoned(sb)) { f2fs_msg(sb, KERN_WARNING, "mounting with \"discard\" option, but " "the device does not support discard"); } break; case Opt_nodiscard: - if (f2fs_sb_mounted_blkzoned(sb)) { + if (f2fs_sb_has_blkzoned(sb)) { f2fs_msg(sb, KERN_WARNING, "discard is required for zoned block devices"); return -EINVAL; @@ -451,7 +466,7 @@ static int parse_options(struct super_block *sb, char *options) if (args->from && match_int(args, &arg)) return -EINVAL; set_opt(sbi, INLINE_XATTR_SIZE); - sbi->inline_xattr_size = arg; + F2FS_OPTION(sbi).inline_xattr_size = arg; break; #else case Opt_user_xattr: @@ -491,7 +506,7 @@ static int parse_options(struct super_block *sb, char *options) return -EINVAL; if (arg != 2 && arg != 4 && arg != NR_CURSEG_TYPE) return -EINVAL; - sbi->active_logs = arg; + F2FS_OPTION(sbi).active_logs = arg; break; case Opt_disable_ext_identify: set_opt(sbi, DISABLE_EXT_IDENTIFY); @@ -535,9 +550,9 @@ static int parse_options(struct super_block *sb, char *options) if (test_opt(sbi, RESERVE_ROOT)) { f2fs_msg(sb, KERN_INFO, "Preserve previous reserve_root=%u", - sbi->root_reserved_blocks); + F2FS_OPTION(sbi).root_reserved_blocks); } else { - sbi->root_reserved_blocks = arg; + F2FS_OPTION(sbi).root_reserved_blocks = arg; set_opt(sbi, RESERVE_ROOT); } break; @@ -550,7 +565,7 @@ static int parse_options(struct super_block *sb, char *options) "Invalid uid value %d", arg); return -EINVAL; } - sbi->s_resuid = uid; + F2FS_OPTION(sbi).s_resuid = uid; break; case Opt_resgid: if (args->from && match_int(args, &arg)) @@ -561,7 +576,7 @@ static int parse_options(struct super_block *sb, char *options) "Invalid gid value %d", arg); return -EINVAL; } - sbi->s_resgid = gid; + F2FS_OPTION(sbi).s_resgid = gid; break; case Opt_mode: name = match_strdup(&args[0]); @@ -570,7 +585,7 @@ static int parse_options(struct super_block *sb, char *options) return -ENOMEM; if (strlen(name) == 8 && !strncmp(name, "adaptive", 8)) { - if (f2fs_sb_mounted_blkzoned(sb)) { + if (f2fs_sb_has_blkzoned(sb)) { f2fs_msg(sb, KERN_WARNING, "adaptive mode is not allowed with " "zoned block device feature"); @@ -596,7 +611,7 @@ static int parse_options(struct super_block *sb, char *options) 1 << arg, BIO_MAX_PAGES); return -EINVAL; } - sbi->write_io_size_bits = arg; + F2FS_OPTION(sbi).write_io_size_bits = arg; break; case Opt_fault_injection: if (args->from && match_int(args, &arg)) @@ -662,13 +677,13 @@ static int parse_options(struct super_block *sb, char *options) return ret; break; case Opt_jqfmt_vfsold: - sbi->s_jquota_fmt = QFMT_VFS_OLD; + F2FS_OPTION(sbi).s_jquota_fmt = QFMT_VFS_OLD; break; case Opt_jqfmt_vfsv0: - sbi->s_jquota_fmt = QFMT_VFS_V0; + F2FS_OPTION(sbi).s_jquota_fmt = QFMT_VFS_V0; break; case Opt_jqfmt_vfsv1: - sbi->s_jquota_fmt = QFMT_VFS_V1; + F2FS_OPTION(sbi).s_jquota_fmt = QFMT_VFS_V1; break; case Opt_noquota: clear_opt(sbi, QUOTA); @@ -695,6 +710,73 @@ static int parse_options(struct super_block *sb, char *options) "quota operations not supported"); break; #endif + case Opt_whint: + name = match_strdup(&args[0]); + if (!name) + return -ENOMEM; + if (strlen(name) == 10 && + !strncmp(name, "user-based", 10)) { + F2FS_OPTION(sbi).whint_mode = WHINT_MODE_USER; + } else if (strlen(name) == 3 && + !strncmp(name, "off", 3)) { + F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF; + } else if (strlen(name) == 8 && + !strncmp(name, "fs-based", 8)) { + F2FS_OPTION(sbi).whint_mode = WHINT_MODE_FS; + } else { + kfree(name); + return -EINVAL; + } + kfree(name); + break; + case Opt_alloc: + name = match_strdup(&args[0]); + if (!name) + return -ENOMEM; + + if (strlen(name) == 7 && + !strncmp(name, "default", 7)) { + F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT; + } else if (strlen(name) == 5 && + !strncmp(name, "reuse", 5)) { + F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_REUSE; + } else { + kfree(name); + return -EINVAL; + } + kfree(name); + break; + case Opt_fsync: + name = match_strdup(&args[0]); + if (!name) + return -ENOMEM; + if (strlen(name) == 5 && + !strncmp(name, "posix", 5)) { + F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_POSIX; + } else if (strlen(name) == 6 && + !strncmp(name, "strict", 6)) { + F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_STRICT; + } else { + kfree(name); + return -EINVAL; + } + kfree(name); + break; + case Opt_test_dummy_encryption: +#ifdef CONFIG_F2FS_FS_ENCRYPTION + if (!f2fs_sb_has_encrypt(sb)) { + f2fs_msg(sb, KERN_ERR, "Encrypt feature is off"); + return -EINVAL; + } + + F2FS_OPTION(sbi).test_dummy_encryption = true; + f2fs_msg(sb, KERN_INFO, + "Test dummy encryption mode enabled"); +#else + f2fs_msg(sb, KERN_INFO, + "Test dummy encryption mount option ignored"); +#endif + break; default: f2fs_msg(sb, KERN_ERR, "Unrecognized mount option \"%s\" or missing value", @@ -715,14 +797,22 @@ static int parse_options(struct super_block *sb, char *options) } if (test_opt(sbi, INLINE_XATTR_SIZE)) { + if (!f2fs_sb_has_extra_attr(sb) || + !f2fs_sb_has_flexible_inline_xattr(sb)) { + f2fs_msg(sb, KERN_ERR, + "extra_attr or flexible_inline_xattr " + "feature is off"); + return -EINVAL; + } if (!test_opt(sbi, INLINE_XATTR)) { f2fs_msg(sb, KERN_ERR, "inline_xattr_size option should be " "set with inline_xattr option"); return -EINVAL; } - if (!sbi->inline_xattr_size || - sbi->inline_xattr_size >= DEF_ADDRS_PER_INODE - + if (!F2FS_OPTION(sbi).inline_xattr_size || + F2FS_OPTION(sbi).inline_xattr_size >= + DEF_ADDRS_PER_INODE - F2FS_TOTAL_EXTRA_ATTR_SIZE - DEF_INLINE_RESERVED_SIZE - DEF_MIN_INLINE_SIZE) { @@ -731,6 +821,12 @@ static int parse_options(struct super_block *sb, char *options) return -EINVAL; } } + + /* Not pass down write hints if the number of active logs is lesser + * than NR_CURSEG_TYPE. + */ + if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE) + F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF; return 0; } @@ -747,7 +843,6 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) /* Initialize f2fs-specific inode info */ atomic_set(&fi->dirty_pages, 0); fi->i_current_depth = 1; - fi->i_advise = 0; init_rwsem(&fi->i_sem); INIT_LIST_HEAD(&fi->dirty_list); INIT_LIST_HEAD(&fi->gdirty_list); @@ -759,9 +854,6 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) init_rwsem(&fi->i_mmap_sem); init_rwsem(&fi->i_xattr_sem); -#ifdef CONFIG_QUOTA - fi->i_reserved_quota = 0; -#endif /* Will be used by directory only */ fi->i_dir_level = F2FS_SB(sb)->dir_level; @@ -972,7 +1064,7 @@ static void f2fs_put_super(struct super_block *sb) mempool_destroy(sbi->write_io_dummy); #ifdef CONFIG_QUOTA for (i = 0; i < F2FS_MAXQUOTAS; i++) - kfree(sbi->s_qf_names[i]); + kfree(F2FS_OPTION(sbi).s_qf_names[i]); #endif destroy_percpu_info(sbi); for (i = 0; i < NR_PAGE_TYPE; i++) @@ -1086,8 +1178,9 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_blocks = total_count - start_count; buf->f_bfree = user_block_count - valid_user_blocks(sbi) - sbi->current_reserved_blocks; - if (buf->f_bfree > sbi->root_reserved_blocks) - buf->f_bavail = buf->f_bfree - sbi->root_reserved_blocks; + if (buf->f_bfree > F2FS_OPTION(sbi).root_reserved_blocks) + buf->f_bavail = buf->f_bfree - + F2FS_OPTION(sbi).root_reserved_blocks; else buf->f_bavail = 0; @@ -1122,10 +1215,10 @@ static inline void f2fs_show_quota_options(struct seq_file *seq, #ifdef CONFIG_QUOTA struct f2fs_sb_info *sbi = F2FS_SB(sb); - if (sbi->s_jquota_fmt) { + if (F2FS_OPTION(sbi).s_jquota_fmt) { char *fmtname = ""; - switch (sbi->s_jquota_fmt) { + switch (F2FS_OPTION(sbi).s_jquota_fmt) { case QFMT_VFS_OLD: fmtname = "vfsold"; break; @@ -1139,14 +1232,17 @@ static inline void f2fs_show_quota_options(struct seq_file *seq, seq_printf(seq, ",jqfmt=%s", fmtname); } - if (sbi->s_qf_names[USRQUOTA]) - seq_show_option(seq, "usrjquota", sbi->s_qf_names[USRQUOTA]); + if (F2FS_OPTION(sbi).s_qf_names[USRQUOTA]) + seq_show_option(seq, "usrjquota", + F2FS_OPTION(sbi).s_qf_names[USRQUOTA]); - if (sbi->s_qf_names[GRPQUOTA]) - seq_show_option(seq, "grpjquota", sbi->s_qf_names[GRPQUOTA]); + if (F2FS_OPTION(sbi).s_qf_names[GRPQUOTA]) + seq_show_option(seq, "grpjquota", + F2FS_OPTION(sbi).s_qf_names[GRPQUOTA]); - if (F2FS_MAXQUOTAS > 2 && sbi->s_qf_names[PRJQUOTA]) - seq_show_option(seq, "prjjquota", sbi->s_qf_names[PRJQUOTA]); + if (F2FS_MAXQUOTAS > 2 && F2FS_OPTION(sbi).s_qf_names[PRJQUOTA]) + seq_show_option(seq, "prjjquota", + F2FS_OPTION(sbi).s_qf_names[PRJQUOTA]); #endif } @@ -1181,7 +1277,7 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) seq_puts(seq, ",noinline_xattr"); if (test_opt(sbi, INLINE_XATTR_SIZE)) seq_printf(seq, ",inline_xattr_size=%u", - sbi->inline_xattr_size); + F2FS_OPTION(sbi).inline_xattr_size); #endif #ifdef CONFIG_F2FS_FS_POSIX_ACL if (test_opt(sbi, POSIX_ACL)) @@ -1217,18 +1313,20 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) seq_puts(seq, "adaptive"); else if (test_opt(sbi, LFS)) seq_puts(seq, "lfs"); - seq_printf(seq, ",active_logs=%u", sbi->active_logs); + seq_printf(seq, ",active_logs=%u", F2FS_OPTION(sbi).active_logs); if (test_opt(sbi, RESERVE_ROOT)) seq_printf(seq, ",reserve_root=%u,resuid=%u,resgid=%u", - sbi->root_reserved_blocks, - from_kuid_munged(&init_user_ns, sbi->s_resuid), - from_kgid_munged(&init_user_ns, sbi->s_resgid)); + F2FS_OPTION(sbi).root_reserved_blocks, + from_kuid_munged(&init_user_ns, + F2FS_OPTION(sbi).s_resuid), + from_kgid_munged(&init_user_ns, + F2FS_OPTION(sbi).s_resgid)); if (F2FS_IO_SIZE_BITS(sbi)) seq_printf(seq, ",io_size=%uKB", F2FS_IO_SIZE_KB(sbi)); #ifdef CONFIG_F2FS_FAULT_INJECTION if (test_opt(sbi, FAULT_INJECTION)) seq_printf(seq, ",fault_injection=%u", - sbi->fault_info.inject_rate); + F2FS_OPTION(sbi).fault_info.inject_rate); #endif #ifdef CONFIG_QUOTA if (test_opt(sbi, QUOTA)) @@ -1241,15 +1339,37 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) seq_puts(seq, ",prjquota"); #endif f2fs_show_quota_options(seq, sbi->sb); + if (F2FS_OPTION(sbi).whint_mode == WHINT_MODE_USER) + seq_printf(seq, ",whint_mode=%s", "user-based"); + else if (F2FS_OPTION(sbi).whint_mode == WHINT_MODE_FS) + seq_printf(seq, ",whint_mode=%s", "fs-based"); +#ifdef CONFIG_F2FS_FS_ENCRYPTION + if (F2FS_OPTION(sbi).test_dummy_encryption) + seq_puts(seq, ",test_dummy_encryption"); +#endif + + if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_DEFAULT) + seq_printf(seq, ",alloc_mode=%s", "default"); + else if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_REUSE) + seq_printf(seq, ",alloc_mode=%s", "reuse"); + if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_POSIX) + seq_printf(seq, ",fsync_mode=%s", "posix"); + else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT) + seq_printf(seq, ",fsync_mode=%s", "strict"); return 0; } static void default_options(struct f2fs_sb_info *sbi) { /* init some FS parameters */ - sbi->active_logs = NR_CURSEG_TYPE; - sbi->inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS; + F2FS_OPTION(sbi).active_logs = NR_CURSEG_TYPE; + F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS; + F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF; + F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT; + F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_POSIX; + F2FS_OPTION(sbi).test_dummy_encryption = false; + sbi->readdir_ra = 1; set_opt(sbi, BG_GC); set_opt(sbi, INLINE_XATTR); @@ -1259,7 +1379,7 @@ static void default_options(struct f2fs_sb_info *sbi) set_opt(sbi, NOHEAP); sbi->sb->s_flags |= MS_LAZYTIME; set_opt(sbi, FLUSH_MERGE); - if (f2fs_sb_mounted_blkzoned(sbi->sb)) { + if (f2fs_sb_has_blkzoned(sbi->sb)) { set_opt_mode(sbi, F2FS_MOUNT_LFS); set_opt(sbi, DISCARD); } else { @@ -1286,16 +1406,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) struct f2fs_sb_info *sbi = F2FS_SB(sb); struct f2fs_mount_info org_mount_opt; unsigned long old_sb_flags; - int err, active_logs; + int err; bool need_restart_gc = false; bool need_stop_gc = false; bool no_extent_cache = !test_opt(sbi, EXTENT_CACHE); -#ifdef CONFIG_F2FS_FAULT_INJECTION - struct f2fs_fault_info ffi = sbi->fault_info; -#endif #ifdef CONFIG_QUOTA - int s_jquota_fmt; - char *s_qf_names[F2FS_MAXQUOTAS]; int i, j; #endif @@ -1305,21 +1420,21 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) */ org_mount_opt = sbi->mount_opt; old_sb_flags = sb->s_flags; - active_logs = sbi->active_logs; #ifdef CONFIG_QUOTA - s_jquota_fmt = sbi->s_jquota_fmt; + org_mount_opt.s_jquota_fmt = F2FS_OPTION(sbi).s_jquota_fmt; for (i = 0; i < F2FS_MAXQUOTAS; i++) { - if (sbi->s_qf_names[i]) { - s_qf_names[i] = kstrdup(sbi->s_qf_names[i], - GFP_KERNEL); - if (!s_qf_names[i]) { + if (F2FS_OPTION(sbi).s_qf_names[i]) { + org_mount_opt.s_qf_names[i] = + kstrdup(F2FS_OPTION(sbi).s_qf_names[i], + GFP_KERNEL); + if (!org_mount_opt.s_qf_names[i]) { for (j = 0; j < i; j++) - kfree(s_qf_names[j]); + kfree(org_mount_opt.s_qf_names[j]); return -ENOMEM; } } else { - s_qf_names[i] = NULL; + org_mount_opt.s_qf_names[i] = NULL; } } #endif @@ -1389,7 +1504,8 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) need_stop_gc = true; } - if (*flags & MS_RDONLY) { + if (*flags & MS_RDONLY || + F2FS_OPTION(sbi).whint_mode != org_mount_opt.whint_mode) { writeback_inodes_sb(sb, WB_REASON_SYNC); sync_inodes_sb(sb); @@ -1415,7 +1531,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) #ifdef CONFIG_QUOTA /* Release old quota file names */ for (i = 0; i < F2FS_MAXQUOTAS; i++) - kfree(s_qf_names[i]); + kfree(org_mount_opt.s_qf_names[i]); #endif /* Update the POSIXACL Flag */ sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | @@ -1433,18 +1549,14 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) } restore_opts: #ifdef CONFIG_QUOTA - sbi->s_jquota_fmt = s_jquota_fmt; + F2FS_OPTION(sbi).s_jquota_fmt = org_mount_opt.s_jquota_fmt; for (i = 0; i < F2FS_MAXQUOTAS; i++) { - kfree(sbi->s_qf_names[i]); - sbi->s_qf_names[i] = s_qf_names[i]; + kfree(F2FS_OPTION(sbi).s_qf_names[i]); + F2FS_OPTION(sbi).s_qf_names[i] = org_mount_opt.s_qf_names[i]; } #endif sbi->mount_opt = org_mount_opt; - sbi->active_logs = active_logs; sb->s_flags = old_sb_flags; -#ifdef CONFIG_F2FS_FAULT_INJECTION - sbi->fault_info = ffi; -#endif return err; } @@ -1472,7 +1584,7 @@ static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data, while (toread > 0) { tocopy = min_t(unsigned long, sb->s_blocksize - offset, toread); repeat: - page = read_mapping_page(mapping, blkidx, NULL); + page = read_cache_page_gfp(mapping, blkidx, GFP_NOFS); if (IS_ERR(page)) { if (PTR_ERR(page) == -ENOMEM) { congestion_wait(BLK_RW_ASYNC, HZ/50); @@ -1561,8 +1673,8 @@ static qsize_t *f2fs_get_reserved_space(struct inode *inode) static int f2fs_quota_on_mount(struct f2fs_sb_info *sbi, int type) { - return dquot_quota_on_mount(sbi->sb, sbi->s_qf_names[type], - sbi->s_jquota_fmt, type); + return dquot_quota_on_mount(sbi->sb, F2FS_OPTION(sbi).s_qf_names[type], + F2FS_OPTION(sbi).s_jquota_fmt, type); } int f2fs_enable_quota_files(struct f2fs_sb_info *sbi, bool rdonly) @@ -1581,7 +1693,7 @@ int f2fs_enable_quota_files(struct f2fs_sb_info *sbi, bool rdonly) } for (i = 0; i < F2FS_MAXQUOTAS; i++) { - if (sbi->s_qf_names[i]) { + if (F2FS_OPTION(sbi).s_qf_names[i]) { err = f2fs_quota_on_mount(sbi, i); if (!err) { enabled = 1; @@ -1849,11 +1961,28 @@ static int f2fs_get_context(struct inode *inode, void *ctx, size_t len) static int f2fs_set_context(struct inode *inode, const void *ctx, size_t len, void *fs_data) { + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + + /* + * Encrypting the root directory is not allowed because fsck + * expects lost+found directory to exist and remain unencrypted + * if LOST_FOUND feature is enabled. + * + */ + if (f2fs_sb_has_lost_found(sbi->sb) && + inode->i_ino == F2FS_ROOT_INO(sbi)) + return -EPERM; + return f2fs_setxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION, F2FS_XATTR_NAME_ENCRYPTION_CONTEXT, ctx, len, fs_data, XATTR_CREATE); } +static bool f2fs_dummy_context(struct inode *inode) +{ + return DUMMY_ENCRYPTION_ENABLED(F2FS_I_SB(inode)); +} + static unsigned f2fs_max_namelen(struct inode *inode) { return S_ISLNK(inode->i_mode) ? @@ -1864,6 +1993,7 @@ static const struct fscrypt_operations f2fs_cryptops = { .key_prefix = "f2fs:", .get_context = f2fs_get_context, .set_context = f2fs_set_context, + .dummy_context = f2fs_dummy_context, .empty_dir = f2fs_empty_dir, .max_namelen = f2fs_max_namelen, }; @@ -1946,7 +2076,6 @@ static int __f2fs_commit_super(struct buffer_head *bh, lock_buffer(bh); if (super) memcpy(bh->b_data + F2FS_SUPER_OFFSET, super, sizeof(*super)); - set_buffer_uptodate(bh); set_buffer_dirty(bh); unlock_buffer(bh); @@ -2241,6 +2370,8 @@ static void init_sb_info(struct f2fs_sb_info *sbi) sbi->dirty_device = 0; spin_lock_init(&sbi->dev_lock); + + init_rwsem(&sbi->sb_lock); } static int init_percpu_info(struct f2fs_sb_info *sbi) @@ -2266,7 +2397,7 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi) unsigned int n = 0; int err = -EIO; - if (!f2fs_sb_mounted_blkzoned(sbi->sb)) + if (!f2fs_sb_has_blkzoned(sbi->sb)) return 0; if (sbi->blocks_per_blkz && sbi->blocks_per_blkz != @@ -2394,7 +2525,7 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) } /* write back-up superblock first */ - bh = sb_getblk(sbi->sb, sbi->valid_super_block ? 0: 1); + bh = sb_bread(sbi->sb, sbi->valid_super_block ? 0 : 1); if (!bh) return -EIO; err = __f2fs_commit_super(bh, F2FS_RAW_SUPER(sbi)); @@ -2405,7 +2536,7 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) return err; /* write current valid superblock */ - bh = sb_getblk(sbi->sb, sbi->valid_super_block); + bh = sb_bread(sbi->sb, sbi->valid_super_block); if (!bh) return -EIO; err = __f2fs_commit_super(bh, F2FS_RAW_SUPER(sbi)); @@ -2477,7 +2608,7 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi) #ifdef CONFIG_BLK_DEV_ZONED if (bdev_zoned_model(FDEV(i).bdev) == BLK_ZONED_HM && - !f2fs_sb_mounted_blkzoned(sbi->sb)) { + !f2fs_sb_has_blkzoned(sbi->sb)) { f2fs_msg(sbi->sb, KERN_ERR, "Zoned block device feature not enabled\n"); return -EINVAL; @@ -2511,6 +2642,18 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi) return 0; } +static void f2fs_tuning_parameters(struct f2fs_sb_info *sbi) +{ + struct f2fs_sm_info *sm_i = SM_I(sbi); + + /* adjust parameters according to the volume size */ + if (sm_i->main_segments <= SMALL_VOLUME_SEGMENTS) { + F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_REUSE; + sm_i->dcc_info->discard_granularity = 1; + sm_i->ipu_policy = 1 << F2FS_IPU_FORCE; + } +} + static int f2fs_fill_super(struct super_block *sb, void *data, int silent) { struct f2fs_sb_info *sbi; @@ -2558,8 +2701,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sb->s_fs_info = sbi; sbi->raw_super = raw_super; - sbi->s_resuid = make_kuid(&init_user_ns, F2FS_DEF_RESUID); - sbi->s_resgid = make_kgid(&init_user_ns, F2FS_DEF_RESGID); + F2FS_OPTION(sbi).s_resuid = make_kuid(&init_user_ns, F2FS_DEF_RESUID); + F2FS_OPTION(sbi).s_resgid = make_kgid(&init_user_ns, F2FS_DEF_RESGID); /* precompute checksum seed for metadata */ if (f2fs_sb_has_inode_chksum(sb)) @@ -2572,7 +2715,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) * devices, but mandatory for host-managed zoned block devices. */ #ifndef CONFIG_BLK_DEV_ZONED - if (f2fs_sb_mounted_blkzoned(sb)) { + if (f2fs_sb_has_blkzoned(sb)) { f2fs_msg(sb, KERN_ERR, "Zoned block device support is not enabled\n"); err = -EOPNOTSUPP; @@ -2791,7 +2934,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) * Turn on quotas which were not enabled for read-only mounts if * filesystem has quota feature, so that they are updated correctly. */ - if (f2fs_sb_has_quota_ino(sb) && !sb_rdonly(sb)) { + if (f2fs_sb_has_quota_ino(sb) && !f2fs_readonly(sb)) { err = f2fs_enable_quotas(sb); if (err) { f2fs_msg(sb, KERN_ERR, @@ -2866,6 +3009,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) f2fs_join_shrinker(sbi); + f2fs_tuning_parameters(sbi); + f2fs_msg(sbi->sb, KERN_NOTICE, "Mounted with checkpoint version = %llx", cur_cp_version(F2FS_CKPT(sbi))); f2fs_update_time(sbi, CP_TIME); @@ -2874,7 +3019,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) free_meta: #ifdef CONFIG_QUOTA - if (f2fs_sb_has_quota_ino(sb) && !sb_rdonly(sb)) + if (f2fs_sb_has_quota_ino(sb) && !f2fs_readonly(sb)) f2fs_quota_off_umount(sbi->sb); #endif f2fs_sync_inode_meta(sbi); @@ -2919,7 +3064,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) free_options: #ifdef CONFIG_QUOTA for (i = 0; i < F2FS_MAXQUOTAS; i++) - kfree(sbi->s_qf_names[i]); + kfree(F2FS_OPTION(sbi).s_qf_names[i]); #endif kfree(options); free_sb_buf: diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 6485a049e7576..1eb2dfad855b6 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -58,7 +58,7 @@ static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type) #ifdef CONFIG_F2FS_FAULT_INJECTION else if (struct_type == FAULT_INFO_RATE || struct_type == FAULT_INFO_TYPE) - return (unsigned char *)&sbi->fault_info; + return (unsigned char *)&F2FS_OPTION(sbi).fault_info; #endif return NULL; } @@ -92,10 +92,10 @@ static ssize_t features_show(struct f2fs_attr *a, if (!sb->s_bdev->bd_part) return snprintf(buf, PAGE_SIZE, "0\n"); - if (f2fs_sb_has_crypto(sb)) + if (f2fs_sb_has_encrypt(sb)) len += snprintf(buf, PAGE_SIZE - len, "%s", "encryption"); - if (f2fs_sb_mounted_blkzoned(sb)) + if (f2fs_sb_has_blkzoned(sb)) len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", len ? ", " : "", "blkzoned"); if (f2fs_sb_has_extra_attr(sb)) @@ -116,6 +116,9 @@ static ssize_t features_show(struct f2fs_attr *a, if (f2fs_sb_has_inode_crtime(sb)) len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", len ? ", " : "", "inode_crtime"); + if (f2fs_sb_has_lost_found(sb)) + len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", + len ? ", " : "", "lost_found"); len += snprintf(buf + len, PAGE_SIZE - len, "\n"); return len; } @@ -136,6 +139,27 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a, if (!ptr) return -EINVAL; + if (!strcmp(a->attr.name, "extension_list")) { + __u8 (*extlist)[F2FS_EXTENSION_LEN] = + sbi->raw_super->extension_list; + int cold_count = le32_to_cpu(sbi->raw_super->extension_count); + int hot_count = sbi->raw_super->hot_ext_count; + int len = 0, i; + + len += snprintf(buf + len, PAGE_SIZE - len, + "cold file extenstion:\n"); + for (i = 0; i < cold_count; i++) + len += snprintf(buf + len, PAGE_SIZE - len, "%s\n", + extlist[i]); + + len += snprintf(buf + len, PAGE_SIZE - len, + "hot file extenstion:\n"); + for (i = cold_count; i < cold_count + hot_count; i++) + len += snprintf(buf + len, PAGE_SIZE - len, "%s\n", + extlist[i]); + return len; + } + ui = (unsigned int *)(ptr + a->offset); return snprintf(buf, PAGE_SIZE, "%u\n", *ui); @@ -154,6 +178,41 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a, if (!ptr) return -EINVAL; + if (!strcmp(a->attr.name, "extension_list")) { + const char *name = strim((char *)buf); + bool set = true, hot; + + if (!strncmp(name, "[h]", 3)) + hot = true; + else if (!strncmp(name, "[c]", 3)) + hot = false; + else + return -EINVAL; + + name += 3; + + if (*name == '!') { + name++; + set = false; + } + + if (strlen(name) >= F2FS_EXTENSION_LEN) + return -EINVAL; + + down_write(&sbi->sb_lock); + + ret = update_extension_list(sbi, name, hot, set); + if (ret) + goto out; + + ret = f2fs_commit_super(sbi, false); + if (ret) + update_extension_list(sbi, name, hot, !set); +out: + up_write(&sbi->sb_lock); + return ret ? ret : count; + } + ui = (unsigned int *)(ptr + a->offset); ret = kstrtoul(skip_spaces(buf), 0, &t); @@ -166,7 +225,7 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a, if (a->struct_type == RESERVED_BLOCKS) { spin_lock(&sbi->stat_lock); if (t > (unsigned long)(sbi->user_block_count - - sbi->root_reserved_blocks)) { + F2FS_OPTION(sbi).root_reserved_blocks)) { spin_unlock(&sbi->stat_lock); return -EINVAL; } @@ -236,6 +295,7 @@ enum feat_id { FEAT_FLEXIBLE_INLINE_XATTR, FEAT_QUOTA_INO, FEAT_INODE_CRTIME, + FEAT_LOST_FOUND, }; static ssize_t f2fs_feature_show(struct f2fs_attr *a, @@ -251,6 +311,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a, case FEAT_FLEXIBLE_INLINE_XATTR: case FEAT_QUOTA_INO: case FEAT_INODE_CRTIME: + case FEAT_LOST_FOUND: return snprintf(buf, PAGE_SIZE, "supported\n"); } return 0; @@ -307,6 +368,7 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, readdir_ra, readdir_ra); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_pin_file_thresh, gc_pin_file_threshold); +F2FS_RW_ATTR(F2FS_SBI, f2fs_super_block, extension_list, extension_list); #ifdef CONFIG_F2FS_FAULT_INJECTION F2FS_RW_ATTR(FAULT_INFO_RATE, f2fs_fault_info, inject_rate, inject_rate); F2FS_RW_ATTR(FAULT_INFO_TYPE, f2fs_fault_info, inject_type, inject_type); @@ -329,6 +391,7 @@ F2FS_FEATURE_RO_ATTR(inode_checksum, FEAT_INODE_CHECKSUM); F2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR); F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO); F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME); +F2FS_FEATURE_RO_ATTR(lost_found, FEAT_LOST_FOUND); #define ATTR_LIST(name) (&f2fs_attr_##name.attr) static struct attribute *f2fs_attrs[] = { @@ -357,6 +420,7 @@ static struct attribute *f2fs_attrs[] = { ATTR_LIST(iostat_enable), ATTR_LIST(readdir_ra), ATTR_LIST(gc_pin_file_thresh), + ATTR_LIST(extension_list), #ifdef CONFIG_F2FS_FAULT_INJECTION ATTR_LIST(inject_rate), ATTR_LIST(inject_type), @@ -383,6 +447,7 @@ static struct attribute *f2fs_feat_attrs[] = { ATTR_LIST(flexible_inline_xattr), ATTR_LIST(quota_ino), ATTR_LIST(inode_crtime), + ATTR_LIST(lost_found), NULL, }; diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index 77743acfe0dc3..8975c4d08c35c 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -21,6 +21,7 @@ #define F2FS_BLKSIZE 4096 /* support only 4KB block */ #define F2FS_BLKSIZE_BITS 12 /* bits for F2FS_BLKSIZE */ #define F2FS_MAX_EXTENSION 64 /* # of extension entries */ +#define F2FS_EXTENSION_LEN 8 /* max size of extension */ #define F2FS_BLK_ALIGN(x) (((x) + F2FS_BLKSIZE - 1) >> F2FS_BLKSIZE_BITS) #define NULL_ADDR ((block_t)0) /* used as block_t addresses */ @@ -38,10 +39,10 @@ #define F2FS_MAX_QUOTAS 3 -#define F2FS_IO_SIZE(sbi) (1 << (sbi)->write_io_size_bits) /* Blocks */ -#define F2FS_IO_SIZE_KB(sbi) (1 << ((sbi)->write_io_size_bits + 2)) /* KB */ -#define F2FS_IO_SIZE_BYTES(sbi) (1 << ((sbi)->write_io_size_bits + 12)) /* B */ -#define F2FS_IO_SIZE_BITS(sbi) ((sbi)->write_io_size_bits) /* power of 2 */ +#define F2FS_IO_SIZE(sbi) (1 << F2FS_OPTION(sbi).write_io_size_bits) /* Blocks */ +#define F2FS_IO_SIZE_KB(sbi) (1 << (F2FS_OPTION(sbi).write_io_size_bits + 2)) /* KB */ +#define F2FS_IO_SIZE_BYTES(sbi) (1 << (F2FS_OPTION(sbi).write_io_size_bits + 12)) /* B */ +#define F2FS_IO_SIZE_BITS(sbi) (F2FS_OPTION(sbi).write_io_size_bits) /* power of 2 */ #define F2FS_IO_SIZE_MASK(sbi) (F2FS_IO_SIZE(sbi) - 1) /* This flag is used by node and meta inodes, and by recovery */ @@ -101,7 +102,7 @@ struct f2fs_super_block { __u8 uuid[16]; /* 128-bit uuid for volume */ __le16 volume_name[MAX_VOLUME_NAME]; /* volume name */ __le32 extension_count; /* # of extensions below */ - __u8 extension_list[F2FS_MAX_EXTENSION][8]; /* extension array */ + __u8 extension_list[F2FS_MAX_EXTENSION][F2FS_EXTENSION_LEN];/* extension array */ __le32 cp_payload; __u8 version[VERSION_LEN]; /* the kernel version */ __u8 init_version[VERSION_LEN]; /* the initial kernel version */ @@ -110,12 +111,14 @@ struct f2fs_super_block { __u8 encrypt_pw_salt[16]; /* Salt used for string2key algorithm */ struct f2fs_device devs[MAX_DEVICES]; /* device list */ __le32 qf_ino[F2FS_MAX_QUOTAS]; /* quota inode numbers */ - __u8 reserved[315]; /* valid reserved region */ + __u8 hot_ext_count; /* # of hot file extension */ + __u8 reserved[314]; /* valid reserved region */ } __packed; /* * For checkpoint */ +#define CP_LARGE_NAT_BITMAP_FLAG 0x00000400 #define CP_NOCRC_RECOVERY_FLAG 0x00000200 #define CP_TRIMMED_FLAG 0x00000100 #define CP_NAT_BITS_FLAG 0x00000080 @@ -302,6 +305,10 @@ struct f2fs_node { */ #define NAT_ENTRY_PER_BLOCK (PAGE_SIZE / sizeof(struct f2fs_nat_entry)) #define NAT_ENTRY_BITMAP_SIZE ((NAT_ENTRY_PER_BLOCK + 7) / 8) +#define NAT_ENTRY_BITMAP_SIZE_ALIGNED \ + ((NAT_ENTRY_BITMAP_SIZE + BITS_PER_LONG - 1) / \ + BITS_PER_LONG * BITS_PER_LONG) + struct f2fs_nat_entry { __u8 version; /* latest version of cached nat entry */ diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 8641e56b8f8a9..809d9653df1b6 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -15,40 +15,12 @@ #include #include -#include -#include -#include -#include -#include #define FS_CRYPTO_BLOCK_SIZE 16 +struct fscrypt_ctx; struct fscrypt_info; -struct fscrypt_ctx { - union { - struct { - struct page *bounce_page; /* Ciphertext page */ - struct page *control_page; /* Original page */ - } w; - struct { - struct bio *bio; - struct work_struct work; - } r; - struct list_head free_list; /* Free list */ - }; - u8 flags; /* Flags */ -}; - -/** - * For encrypted symlinks, the ciphertext length is stored at the beginning - * of the string in little-endian format. - */ -struct fscrypt_symlink_data { - __le16 len; - char encrypted_path[1]; -} __packed; - struct fscrypt_str { unsigned char *name; u32 len; @@ -67,86 +39,11 @@ struct fscrypt_name { #define fname_name(p) ((p)->disk_name.name) #define fname_len(p) ((p)->disk_name.len) -/* - * fscrypt superblock flags - */ -#define FS_CFLG_OWN_PAGES (1U << 1) - -/* - * crypto opertions for filesystems - */ -struct fscrypt_operations { - unsigned int flags; - const char *key_prefix; - int (*get_context)(struct inode *, void *, size_t); - int (*set_context)(struct inode *, const void *, size_t, void *); - bool (*dummy_context)(struct inode *); - bool (*empty_dir)(struct inode *); - unsigned (*max_namelen)(struct inode *); -}; - -static inline bool fscrypt_dummy_context_enabled(struct inode *inode) -{ - if (inode->i_sb->s_cop->dummy_context && - inode->i_sb->s_cop->dummy_context(inode)) - return true; - return false; -} - -static inline bool fscrypt_valid_enc_modes(u32 contents_mode, - u32 filenames_mode) -{ - if (contents_mode == FS_ENCRYPTION_MODE_AES_128_CBC && - filenames_mode == FS_ENCRYPTION_MODE_AES_128_CTS) - return true; - - if (contents_mode == FS_ENCRYPTION_MODE_AES_256_XTS && - filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS) - return true; - - return false; -} - -static inline bool fscrypt_is_dot_dotdot(const struct qstr *str) -{ - if (str->len == 1 && str->name[0] == '.') - return true; - - if (str->len == 2 && str->name[0] == '.' && str->name[1] == '.') - return true; - - return false; -} - #if __FS_HAS_ENCRYPTION - -static inline struct page *fscrypt_control_page(struct page *page) -{ - return ((struct fscrypt_ctx *)page_private(page))->w.control_page; -} - -static inline bool fscrypt_has_encryption_key(const struct inode *inode) -{ - return (inode->i_crypt_info != NULL); -} - #include - -#else /* !__FS_HAS_ENCRYPTION */ - -static inline struct page *fscrypt_control_page(struct page *page) -{ - WARN_ON_ONCE(1); - return ERR_PTR(-EINVAL); -} - -static inline bool fscrypt_has_encryption_key(const struct inode *inode) -{ - return 0; -} - +#else #include -#endif /* __FS_HAS_ENCRYPTION */ +#endif /** * fscrypt_require_key - require an inode's encryption key @@ -287,4 +184,68 @@ static inline int fscrypt_prepare_setattr(struct dentry *dentry, return 0; } +/** + * fscrypt_prepare_symlink - prepare to create a possibly-encrypted symlink + * @dir: directory in which the symlink is being created + * @target: plaintext symlink target + * @len: length of @target excluding null terminator + * @max_len: space the filesystem has available to store the symlink target + * @disk_link: (out) the on-disk symlink target being prepared + * + * This function computes the size the symlink target will require on-disk, + * stores it in @disk_link->len, and validates it against @max_len. An + * encrypted symlink may be longer than the original. + * + * Additionally, @disk_link->name is set to @target if the symlink will be + * unencrypted, but left NULL if the symlink will be encrypted. For encrypted + * symlinks, the filesystem must call fscrypt_encrypt_symlink() to create the + * on-disk target later. (The reason for the two-step process is that some + * filesystems need to know the size of the symlink target before creating the + * inode, e.g. to determine whether it will be a "fast" or "slow" symlink.) + * + * Return: 0 on success, -ENAMETOOLONG if the symlink target is too long, + * -ENOKEY if the encryption key is missing, or another -errno code if a problem + * occurred while setting up the encryption key. + */ +static inline int fscrypt_prepare_symlink(struct inode *dir, + const char *target, + unsigned int len, + unsigned int max_len, + struct fscrypt_str *disk_link) +{ + if (IS_ENCRYPTED(dir) || fscrypt_dummy_context_enabled(dir)) + return __fscrypt_prepare_symlink(dir, len, max_len, disk_link); + + disk_link->name = (unsigned char *)target; + disk_link->len = len + 1; + if (disk_link->len > max_len) + return -ENAMETOOLONG; + return 0; +} + +/** + * fscrypt_encrypt_symlink - encrypt the symlink target if needed + * @inode: symlink inode + * @target: plaintext symlink target + * @len: length of @target excluding null terminator + * @disk_link: (in/out) the on-disk symlink target being prepared + * + * If the symlink target needs to be encrypted, then this function encrypts it + * into @disk_link->name. fscrypt_prepare_symlink() must have been called + * previously to compute @disk_link->len. If the filesystem did not allocate a + * buffer for @disk_link->name after calling fscrypt_prepare_link(), then one + * will be kmalloc()'ed and the filesystem will be responsible for freeing it. + * + * Return: 0 on success, -errno on failure + */ +static inline int fscrypt_encrypt_symlink(struct inode *inode, + const char *target, + unsigned int len, + struct fscrypt_str *disk_link) +{ + if (IS_ENCRYPTED(inode)) + return __fscrypt_encrypt_symlink(inode, target, len, disk_link); + return 0; +} + #endif /* _LINUX_FSCRYPT_H */ diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h index c4c6bf2c390e0..37c52c74cace1 100644 --- a/include/linux/fscrypt_notsupp.h +++ b/include/linux/fscrypt_notsupp.h @@ -13,6 +13,16 @@ #ifndef _LINUX_FSCRYPT_NOTSUPP_H #define _LINUX_FSCRYPT_NOTSUPP_H +static inline bool fscrypt_has_encryption_key(const struct inode *inode) +{ + return false; +} + +static inline bool fscrypt_dummy_context_enabled(struct inode *inode) +{ + return false; +} + /* crypto.c */ static inline struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode, gfp_t gfp_flags) @@ -42,6 +52,11 @@ static inline int fscrypt_decrypt_page(const struct inode *inode, return -EOPNOTSUPP; } +static inline struct page *fscrypt_control_page(struct page *page) +{ + WARN_ON_ONCE(1); + return ERR_PTR(-EINVAL); +} static inline void fscrypt_restore_control_page(struct page *page) { @@ -89,8 +104,7 @@ static inline int fscrypt_get_encryption_info(struct inode *inode) return -EOPNOTSUPP; } -static inline void fscrypt_put_encryption_info(struct inode *inode, - struct fscrypt_info *ci) +static inline void fscrypt_put_encryption_info(struct inode *inode) { return; } @@ -115,16 +129,8 @@ static inline void fscrypt_free_filename(struct fscrypt_name *fname) return; } -static inline u32 fscrypt_fname_encrypted_size(const struct inode *inode, - u32 ilen) -{ - /* never happens */ - WARN_ON(1); - return 0; -} - static inline int fscrypt_fname_alloc_buffer(const struct inode *inode, - u32 ilen, + u32 max_encrypted_len, struct fscrypt_str *crypto_str) { return -EOPNOTSUPP; @@ -143,13 +149,6 @@ static inline int fscrypt_fname_disk_to_usr(struct inode *inode, return -EOPNOTSUPP; } -static inline int fscrypt_fname_usr_to_disk(struct inode *inode, - const struct qstr *iname, - struct fscrypt_str *oname) -{ - return -EOPNOTSUPP; -} - static inline bool fscrypt_match_name(const struct fscrypt_name *fname, const u8 *de_name, u32 de_name_len) { @@ -207,4 +206,28 @@ static inline int __fscrypt_prepare_lookup(struct inode *dir, return -EOPNOTSUPP; } +static inline int __fscrypt_prepare_symlink(struct inode *dir, + unsigned int len, + unsigned int max_len, + struct fscrypt_str *disk_link) +{ + return -EOPNOTSUPP; +} + +static inline int __fscrypt_encrypt_symlink(struct inode *inode, + const char *target, + unsigned int len, + struct fscrypt_str *disk_link) +{ + return -EOPNOTSUPP; +} + +static inline void *fscrypt_get_symlink(struct inode *inode, + const void *caddr, + unsigned int max_size, + struct nameidata *nd) +{ + return ERR_PTR(-EOPNOTSUPP); +} + #endif /* _LINUX_FSCRYPT_NOTSUPP_H */ diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h index 4ccecca367475..ca06fb3af33a7 100644 --- a/include/linux/fscrypt_supp.h +++ b/include/linux/fscrypt_supp.h @@ -10,8 +10,54 @@ #ifndef _LINUX_FSCRYPT_SUPP_H #define _LINUX_FSCRYPT_SUPP_H +#include +#include + +/* + * fscrypt superblock flags + */ +#define FS_CFLG_OWN_PAGES (1U << 1) + +/* + * crypto operations for filesystems + */ +struct fscrypt_operations { + unsigned int flags; + const char *key_prefix; + int (*get_context)(struct inode *, void *, size_t); + int (*set_context)(struct inode *, const void *, size_t, void *); + bool (*dummy_context)(struct inode *); + bool (*empty_dir)(struct inode *); + unsigned (*max_namelen)(struct inode *); +}; + +struct fscrypt_ctx { + union { + struct { + struct page *bounce_page; /* Ciphertext page */ + struct page *control_page; /* Original page */ + } w; + struct { + struct bio *bio; + struct work_struct work; + } r; + struct list_head free_list; /* Free list */ + }; + u8 flags; /* Flags */ +}; + +static inline bool fscrypt_has_encryption_key(const struct inode *inode) +{ + return (inode->i_crypt_info != NULL); +} + +static inline bool fscrypt_dummy_context_enabled(struct inode *inode) +{ + return inode->i_sb->s_cop->dummy_context && + inode->i_sb->s_cop->dummy_context(inode); +} + /* crypto.c */ -extern struct kmem_cache *fscrypt_info_cachep; extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t); extern void fscrypt_release_ctx(struct fscrypt_ctx *); extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *, @@ -19,6 +65,12 @@ extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *, u64, gfp_t); extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int, unsigned int, u64); + +static inline struct page *fscrypt_control_page(struct page *page) +{ + return ((struct fscrypt_ctx *)page_private(page))->w.control_page; +} + extern void fscrypt_restore_control_page(struct page *); extern const struct dentry_operations fscrypt_d_ops; @@ -43,7 +95,7 @@ extern int fscrypt_inherit_context(struct inode *, struct inode *, void *, bool); /* keyinfo.c */ extern int fscrypt_get_encryption_info(struct inode *); -extern void fscrypt_put_encryption_info(struct inode *, struct fscrypt_info *); +extern void fscrypt_put_encryption_info(struct inode *); /* fname.c */ extern int fscrypt_setup_filename(struct inode *, const struct qstr *, @@ -54,14 +106,11 @@ static inline void fscrypt_free_filename(struct fscrypt_name *fname) kfree(fname->crypto_buf.name); } -extern u32 fscrypt_fname_encrypted_size(const struct inode *, u32); extern int fscrypt_fname_alloc_buffer(const struct inode *, u32, struct fscrypt_str *); extern void fscrypt_fname_free_buffer(struct fscrypt_str *); extern int fscrypt_fname_disk_to_usr(struct inode *, u32, u32, const struct fscrypt_str *, struct fscrypt_str *); -extern int fscrypt_fname_usr_to_disk(struct inode *, const struct qstr *, - struct fscrypt_str *); #define FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE 32 @@ -156,5 +205,14 @@ extern int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *new_dentry, unsigned int flags); extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry); +extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len, + unsigned int max_len, + struct fscrypt_str *disk_link); +extern int __fscrypt_encrypt_symlink(struct inode *inode, const char *target, + unsigned int len, + struct fscrypt_str *disk_link); +extern void *fscrypt_get_symlink(struct inode *inode, const void *caddr, + unsigned int max_size, + struct nameidata *nd); #endif /* _LINUX_FSCRYPT_SUPP_H */ From 84e65af1f490465daabf1617d8484bd41273399a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 18 Apr 2018 11:09:47 -0700 Subject: [PATCH 482/508] FROMLIST: fscrypt: allow synchronous bio decryption Cherry-pick from origin/upstream-f2fs-stable-linux-3.18.y: 10fbe4ee4d1f ("fscrypt: allow synchronous bio decryption") Currently, fscrypt provides fscrypt_decrypt_bio_pages() which decrypts a bio's pages asynchronously, then unlocks them afterwards. But, this assumes that decryption is the last "postprocessing step" for the bio, so it's incompatible with additional postprocessing steps such as authenticity verification after decryption. Therefore, rename the existing fscrypt_decrypt_bio_pages() to fscrypt_enqueue_decrypt_bio(). Then, add fscrypt_decrypt_bio() which decrypts the pages in the bio synchronously without unlocking the pages, nor setting them Uptodate; and add fscrypt_enqueue_decrypt_work(), which enqueues work on the fscrypt_read_workqueue. The new functions will be used by filesystems that support both fscrypt and fs-verity. Change-Id: I6e596473df2c9f1246c7677739520b6d35251d47 Signed-off-by: Eric Biggers Signed-off-by: Jaegeuk Kim --- fs/crypto/bio.c | 35 +++++++++++++++++++++------------ fs/crypto/crypto.c | 8 +++++++- fs/crypto/fscrypt_private.h | 1 - fs/f2fs/data.c | 2 +- include/linux/fscrypt_notsupp.h | 13 +++++++++--- include/linux/fscrypt_supp.h | 5 ++++- 6 files changed, 44 insertions(+), 20 deletions(-) diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c index a91ed46fe503c..c7cf565c434e2 100644 --- a/fs/crypto/bio.c +++ b/fs/crypto/bio.c @@ -25,15 +25,8 @@ #include #include "fscrypt_private.h" -/* - * Call fscrypt_decrypt_page on every single page, reusing the encryption - * context. - */ -static void completion_pages(struct work_struct *work) +static void __fscrypt_decrypt_bio(struct bio *bio, bool done) { - struct fscrypt_ctx *ctx = - container_of(work, struct fscrypt_ctx, r.work); - struct bio *bio = ctx->r.bio; struct bio_vec *bv; int i; @@ -45,22 +38,38 @@ static void completion_pages(struct work_struct *work) if (ret) { WARN_ON_ONCE(1); SetPageError(page); - } else { + } else if (done) { SetPageUptodate(page); } - unlock_page(page); + if (done) + unlock_page(page); } +} + +void fscrypt_decrypt_bio(struct bio *bio) +{ + __fscrypt_decrypt_bio(bio, false); +} +EXPORT_SYMBOL(fscrypt_decrypt_bio); + +static void completion_pages(struct work_struct *work) +{ + struct fscrypt_ctx *ctx = + container_of(work, struct fscrypt_ctx, r.work); + struct bio *bio = ctx->r.bio; + + __fscrypt_decrypt_bio(bio, true); fscrypt_release_ctx(ctx); bio_put(bio); } -void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *ctx, struct bio *bio) +void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, struct bio *bio) { INIT_WORK(&ctx->r.work, completion_pages); ctx->r.bio = bio; - queue_work(fscrypt_read_workqueue, &ctx->r.work); + fscrypt_enqueue_decrypt_work(&ctx->r.work); } -EXPORT_SYMBOL(fscrypt_decrypt_bio_pages); +EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio); void fscrypt_pullback_bio_page(struct page **page, bool restore) { diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 43d2d3688cf42..f3c3f5cea7340 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -45,12 +45,18 @@ static mempool_t *fscrypt_bounce_page_pool = NULL; static LIST_HEAD(fscrypt_free_ctxs); static DEFINE_SPINLOCK(fscrypt_ctx_lock); -struct workqueue_struct *fscrypt_read_workqueue; +static struct workqueue_struct *fscrypt_read_workqueue; static DEFINE_MUTEX(fscrypt_init_mutex); static struct kmem_cache *fscrypt_ctx_cachep; struct kmem_cache *fscrypt_info_cachep; +void fscrypt_enqueue_decrypt_work(struct work_struct *work) +{ + queue_work(fscrypt_read_workqueue, work); +} +EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work); + /** * fscrypt_release_ctx() - Releases an encryption context * @ctx: The encryption context to release. diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 7c9484375aeff..484aac1368d69 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -122,7 +122,6 @@ static inline bool fscrypt_valid_enc_modes(u32 contents_mode, /* crypto.c */ extern struct kmem_cache *fscrypt_info_cachep; extern int fscrypt_initialize(unsigned int cop_flags); -extern struct workqueue_struct *fscrypt_read_workqueue; extern int fscrypt_do_page_crypto(const struct inode *inode, fscrypt_direction_t rw, u64 lblk_num, struct page *src_page, diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 0408cc3ed4d2a..d80c71ec68851 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -67,7 +67,7 @@ static void f2fs_read_end_io(struct bio *bio, int err) if (err) { fscrypt_release_ctx(bio->bi_private); } else { - fscrypt_decrypt_bio_pages(bio->bi_private, bio); + fscrypt_enqueue_decrypt_bio(bio->bi_private, bio); return; } } diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h index 37c52c74cace1..224b6a7630556 100644 --- a/include/linux/fscrypt_notsupp.h +++ b/include/linux/fscrypt_notsupp.h @@ -24,6 +24,10 @@ static inline bool fscrypt_dummy_context_enabled(struct inode *inode) } /* crypto.c */ +static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work) +{ +} + static inline struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode, gfp_t gfp_flags) { @@ -159,10 +163,13 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname, } /* bio.c */ -static inline void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *ctx, - struct bio *bio) +static inline void fscrypt_decrypt_bio(struct bio *bio) +{ +} + +static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, + struct bio *bio) { - return; } static inline void fscrypt_pullback_bio_page(struct page **page, bool restore) diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h index ca06fb3af33a7..791762321a514 100644 --- a/include/linux/fscrypt_supp.h +++ b/include/linux/fscrypt_supp.h @@ -58,6 +58,7 @@ static inline bool fscrypt_dummy_context_enabled(struct inode *inode) } /* crypto.c */ +extern void fscrypt_enqueue_decrypt_work(struct work_struct *); extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t); extern void fscrypt_release_ctx(struct fscrypt_ctx *); extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *, @@ -191,7 +192,9 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname, } /* bio.c */ -extern void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *, struct bio *); +extern void fscrypt_decrypt_bio(struct bio *); +extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, + struct bio *bio); extern void fscrypt_pullback_bio_page(struct page **, bool); extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t, unsigned int); From 2cebc9f909fd11f4349be02c7f22ed2b95fb9a24 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 18 Apr 2018 11:09:48 -0700 Subject: [PATCH 483/508] f2fs: refactor read path to allow multiple postprocessing steps Cherry-pick from origin/upstream-f2fs-stable-linux-3.18.y: 967f45c74ff6 ("f2fs: refactor read path to allow multiple postprocessing steps") Currently f2fs's ->readpage() and ->readpages() assume that either the data undergoes no postprocessing, or decryption only. But with fs-verity, there will be an additional authenticity verification step, and it may be needed either by itself, or combined with decryption. To support this, store a 'struct bio_post_read_ctx' in ->bi_private which contains a work struct, a bitmask of postprocessing steps that are enabled, and an indicator of the current step. The bio completion routine, if there was no I/O error, enqueues the first postprocessing step. When that completes, it continues to the next step. Pages that fail any postprocessing step have PageError set. Once all steps have completed, pages without PageError set are set Uptodate, and all pages are unlocked. Also replace f2fs_encrypted_file() with a new function f2fs_post_read_required() in places like direct I/O and garbage collection that really should be testing whether the file needs special I/O processing, not whether it is encrypted specifically. This may also be useful for other future f2fs features such as compression. Change-Id: Ic5d37fbecab10a0beef80c991b16d2b1b86e009e Signed-off-by: Eric Biggers Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 168 +++++++++++++++++++++++++++++++++++------------ fs/f2fs/f2fs.h | 10 ++- fs/f2fs/file.c | 4 +- fs/f2fs/gc.c | 6 +- fs/f2fs/inline.c | 2 +- fs/f2fs/super.c | 6 ++ 6 files changed, 147 insertions(+), 49 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index d80c71ec68851..948761c9d6f32 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -31,6 +31,11 @@ #include #include +#define NUM_PREALLOC_POST_READ_CTXS 128 + +static struct kmem_cache *bio_post_read_ctx_cache; +static mempool_t *bio_post_read_ctx_pool; + static bool __is_cp_guaranteed(struct page *page) { struct address_space *mapping = page->mapping; @@ -51,11 +56,77 @@ static bool __is_cp_guaranteed(struct page *page) return false; } -static void f2fs_read_end_io(struct bio *bio, int err) +/* postprocessing steps for read bios */ +enum bio_post_read_step { + STEP_INITIAL = 0, + STEP_DECRYPT, +}; + +struct bio_post_read_ctx { + struct bio *bio; + struct work_struct work; + unsigned int cur_step; + unsigned int enabled_steps; +}; + +static void __read_end_io(struct bio *bio, int err) { - struct bio_vec *bvec; + struct page *page; + struct bio_vec *bv; int i; + bio_for_each_segment_all(bv, bio, i) { + page = bv->bv_page; + + /* PG_error was set if any post_read step failed */ + if (err || PageError(page)) { + ClearPageUptodate(page); + SetPageError(page); + } else { + SetPageUptodate(page); + } + unlock_page(page); + } + if (bio->bi_private) + mempool_free(bio->bi_private, bio_post_read_ctx_pool); + bio_put(bio); +} + +static void bio_post_read_processing(struct bio_post_read_ctx *ctx); + +static void decrypt_work(struct work_struct *work) +{ + struct bio_post_read_ctx *ctx = + container_of(work, struct bio_post_read_ctx, work); + + fscrypt_decrypt_bio(ctx->bio); + + bio_post_read_processing(ctx); +} + +static void bio_post_read_processing(struct bio_post_read_ctx *ctx) +{ + switch (++ctx->cur_step) { + case STEP_DECRYPT: + if (ctx->enabled_steps & (1 << STEP_DECRYPT)) { + INIT_WORK(&ctx->work, decrypt_work); + fscrypt_enqueue_decrypt_work(&ctx->work); + return; + } + ctx->cur_step++; + /* fall-through */ + default: + __read_end_io(ctx->bio, 0); + } +} + +static bool f2fs_bio_post_read_required(struct bio *bio, int err) +{ + return bio->bi_private && !err; +} + +static void f2fs_read_end_io(struct bio *bio, int err) +{ #ifdef CONFIG_F2FS_FAULT_INJECTION if (time_to_inject(F2FS_P_SB(bio->bi_io_vec->bv_page), FAULT_IO)) { f2fs_show_injection_info(FAULT_IO); @@ -63,28 +134,15 @@ static void f2fs_read_end_io(struct bio *bio, int err) } #endif - if (f2fs_bio_encrypted(bio)) { - if (err) { - fscrypt_release_ctx(bio->bi_private); - } else { - fscrypt_enqueue_decrypt_bio(bio->bi_private, bio); - return; - } - } - - bio_for_each_segment_all(bvec, bio, i) { - struct page *page = bvec->bv_page; + if (f2fs_bio_post_read_required(bio, err)) { + struct bio_post_read_ctx *ctx = bio->bi_private; - if (!err) { - if (!PageUptodate(page)) - SetPageUptodate(page); - } else { - ClearPageUptodate(page); - SetPageError(page); - } - unlock_page(page); + ctx->cur_step = STEP_INITIAL; + bio_post_read_processing(ctx); + return; } - bio_put(bio); + + __read_end_io(bio, err); } static void f2fs_write_end_io(struct bio *bio, int err) @@ -481,29 +539,33 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, unsigned nr_pages) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - struct fscrypt_ctx *ctx = NULL; struct bio *bio; - - if (f2fs_encrypted_file(inode)) { - ctx = fscrypt_get_ctx(inode, GFP_NOFS); - if (IS_ERR(ctx)) - return ERR_CAST(ctx); - - /* wait the page to be moved by cleaning */ - f2fs_wait_on_block_writeback(sbi, blkaddr); - } + struct bio_post_read_ctx *ctx; + unsigned int post_read_steps = 0; bio = f2fs_bio_alloc(sbi, min_t(int, nr_pages, BIO_MAX_PAGES), false); - if (!bio) { - if (ctx) - fscrypt_release_ctx(ctx); + if (!bio) return ERR_PTR(-ENOMEM); - } f2fs_target_device(sbi, blkaddr, bio); bio->bi_end_io = f2fs_read_end_io; - bio->bi_private = ctx; bio_set_op_attrs(bio, REQ_OP_READ, 0); + if (f2fs_encrypted_file(inode)) + post_read_steps |= 1 << STEP_DECRYPT; + if (post_read_steps) { + ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS); + if (!ctx) { + bio_put(bio); + return ERR_PTR(-ENOMEM); + } + ctx->bio = bio; + ctx->enabled_steps = post_read_steps; + bio->bi_private = ctx; + + /* wait the page to be moved by cleaning */ + f2fs_wait_on_block_writeback(sbi, blkaddr); + } + return bio; } @@ -842,7 +904,7 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type) static inline bool __force_buffered_io(struct inode *inode, int rw) { - return (f2fs_encrypted_file(inode) || + return (f2fs_post_read_required(inode) || (rw == WRITE && test_opt(F2FS_I_SB(inode), LFS)) || F2FS_I_SB(inode)->s_ndevs); } @@ -1507,7 +1569,7 @@ static int encrypt_one_page(struct f2fs_io_info *fio) if (!f2fs_encrypted_file(inode)) return 0; - /* wait for GCed encrypted page writeback */ + /* wait for GCed page writeback via META_MAPPING */ f2fs_wait_on_block_writeback(fio->sbi, fio->old_blkaddr); retry_encrypt: @@ -2219,8 +2281,8 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, f2fs_wait_on_page_writeback(page, DATA, false); - /* wait for GCed encrypted page writeback */ - if (f2fs_encrypted_file(inode)) + /* wait for GCed page writeback via META_MAPPING */ + if (f2fs_post_read_required(inode)) f2fs_wait_on_block_writeback(sbi, blkaddr); if (len == PAGE_SIZE || PageUptodate(page)) @@ -2564,3 +2626,27 @@ const struct address_space_operations f2fs_dblock_aops = { .migratepage = f2fs_migrate_page, #endif }; + +int __init f2fs_init_post_read_processing(void) +{ + bio_post_read_ctx_cache = KMEM_CACHE(bio_post_read_ctx, 0); + if (!bio_post_read_ctx_cache) + goto fail; + bio_post_read_ctx_pool = + mempool_create_slab_pool(NUM_PREALLOC_POST_READ_CTXS, + bio_post_read_ctx_cache); + if (!bio_post_read_ctx_pool) + goto fail_free_cache; + return 0; + +fail_free_cache: + kmem_cache_destroy(bio_post_read_ctx_cache); +fail: + return -ENOMEM; +} + +void __exit f2fs_destroy_post_read_processing(void) +{ + mempool_destroy(bio_post_read_ctx_pool); + kmem_cache_destroy(bio_post_read_ctx_cache); +} diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 5782e0677186b..99eaec83921e5 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2994,6 +2994,8 @@ void destroy_checkpoint_caches(void); /* * data.c */ +int f2fs_init_post_read_processing(void); +void f2fs_destroy_post_read_processing(void); void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type); void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi, struct inode *inode, nid_t ino, pgoff_t idx, @@ -3354,9 +3356,13 @@ static inline void f2fs_set_encrypted_inode(struct inode *inode) #endif } -static inline bool f2fs_bio_encrypted(struct bio *bio) +/* + * Returns true if the reads of the inode's data need to undergo some + * postprocessing step, like decryption or authenticity verification. + */ +static inline bool f2fs_post_read_required(struct inode *inode) { - return bio->bi_private != NULL; + return f2fs_encrypted_file(inode); } #define F2FS_FEATURE_FUNCS(name, flagname) \ diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 42288c6562c2a..7a5f1572cb76a 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -114,8 +114,8 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, /* fill the page */ f2fs_wait_on_page_writeback(page, DATA, false); - /* wait for GCed encrypted page writeback */ - if (f2fs_encrypted_file(inode)) + /* wait for GCed page writeback via META_MAPPING */ + if (f2fs_post_read_required(inode)) f2fs_wait_on_block_writeback(sbi, dn.data_blkaddr); out_sem: diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 0ad8b3a7a74dc..604d3fcb89572 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -850,8 +850,8 @@ static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, if (IS_ERR(inode) || is_bad_inode(inode)) continue; - /* if encrypted inode, let's go phase 3 */ - if (f2fs_encrypted_file(inode)) { + /* if inode uses special I/O path, let's go phase 3 */ + if (f2fs_post_read_required(inode)) { add_gc_inode(gc_list, inode); continue; } @@ -899,7 +899,7 @@ static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, start_bidx = start_bidx_of_node(nofs, inode) + ofs_in_node; - if (f2fs_encrypted_file(inode)) + if (f2fs_post_read_required(inode)) move_data_block(inode, start_bidx, segno, off); else move_data_page(inode, start_bidx, gc_type, diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 275fd0e3f7a41..feb96e6bd4310 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -26,7 +26,7 @@ bool f2fs_may_inline_data(struct inode *inode) if (i_size_read(inode) > MAX_INLINE_DATA(inode)) return false; - if (f2fs_encrypted_file(inode)) + if (f2fs_post_read_required(inode)) return false; return true; diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 949cbe02ec241..5a6b61f44991b 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -3160,8 +3160,13 @@ static int __init init_f2fs_fs(void) err = f2fs_create_root_stats(); if (err) goto free_filesystem; + err = f2fs_init_post_read_processing(); + if (err) + goto free_root_stats; return 0; +free_root_stats: + f2fs_destroy_root_stats(); free_filesystem: unregister_filesystem(&f2fs_fs_type); free_shrinker: @@ -3184,6 +3189,7 @@ static int __init init_f2fs_fs(void) static void __exit exit_f2fs_fs(void) { + f2fs_destroy_post_read_processing(); f2fs_destroy_root_stats(); unregister_filesystem(&f2fs_fs_type); unregister_shrinker(&f2fs_shrinker_info); From dca6d91e064e7106b7b8b95d5cfc593df3de7f7c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 18 Apr 2018 15:48:42 -0700 Subject: [PATCH 484/508] f2fs: call unlock_new_inode() before d_instantiate() Cherry-pick from origin/upstream-f2fs-stable-linux-3.18.y: a5dff6815939 ("f2fs: call unlock_new_inode() before d_instantiate()") xfstest generic/429 sometimes hangs on f2fs, caused by a thread being unable to take a directory's i_rwsem for write in vfs_rmdir(). In the test, one thread repeatedly creates and removes a directory, and other threads repeatedly look up a file in the directory. The bug is that f2fs_mkdir() calls d_instantiate() before unlock_new_inode(), resulting in the directory inode being exposed to lookups before it has been fully initialized. And with CONFIG_DEBUG_LOCK_ALLOC, unlock_new_inode() reinitializes ->i_rwsem, corrupting its state when it is already held. Fix it by calling unlock_new_inode() before d_instantiate(). This matches what other filesystems do. Fixes: 57397d86c62d ("f2fs: add inode operations for special inodes") Change-Id: Ia0a8a38865c3ad17e1f237c878db23ff3a236b4d Signed-off-by: Eric Biggers Signed-off-by: Jaegeuk Kim --- fs/f2fs/namei.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 102bca813f18a..1ca2b6c2486a2 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -290,8 +290,8 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode, alloc_nid_done(sbi, ino); - d_instantiate(dentry, inode); unlock_new_inode(inode); + d_instantiate(dentry, inode); if (IS_DIRSYNC(dir)) f2fs_sync_fs(sbi->sb, 1); @@ -591,8 +591,8 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, err = page_symlink(inode, disk_link.name, disk_link.len); err_out: - d_instantiate(dentry, inode); unlock_new_inode(inode); + d_instantiate(dentry, inode); /* * Let's flush symlink data in order to avoid broken symlink as much as @@ -653,8 +653,8 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) alloc_nid_done(sbi, inode->i_ino); - d_instantiate(dentry, inode); unlock_new_inode(inode); + d_instantiate(dentry, inode); if (IS_DIRSYNC(dir)) f2fs_sync_fs(sbi->sb, 1); @@ -705,8 +705,8 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry, alloc_nid_done(sbi, inode->i_ino); - d_instantiate(dentry, inode); unlock_new_inode(inode); + d_instantiate(dentry, inode); if (IS_DIRSYNC(dir)) f2fs_sync_fs(sbi->sb, 1); From 93acf75f943ead122b76c7d6a645a5af87ccd47c Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 11 Apr 2018 23:09:04 -0700 Subject: [PATCH 485/508] f2fs: clear PageError on writepage Cherry-pick from origin/upstream-f2fs-stable-linux-3.18.y: commit da4febfafff3 ("f2fs: clear PageError on writepage") This patch clears PageError in some pages tagged by read path, but when we write the pages with valid contents, writepage should clear the bit likewise ext4. Change-Id: I3348bb48b333d1336aa6e8e03b12169569f673d5 Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 948761c9d6f32..94a3fc7e3722c 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1719,6 +1719,7 @@ int do_write_data_page(struct f2fs_io_info *fio) goto out_writepage; set_page_writeback(page); + ClearPageError(page); f2fs_put_dnode(&dn); if (fio->need_lock == LOCK_REQ) f2fs_unlock_op(fio->sbi); @@ -1741,6 +1742,7 @@ int do_write_data_page(struct f2fs_io_info *fio) goto out_writepage; set_page_writeback(page); + ClearPageError(page); /* LFS mode write path */ write_data_page(&dn, fio); From 07e6a1f5f4269c78a8cbcc229068c2aade09ad62 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 20 Apr 2018 19:29:52 -0700 Subject: [PATCH 486/508] Revert "f2fs: introduce f2fs_set_page_dirty_nobuffer" Cherry-pick from origin/upstream-f2fs-stable-linux-3.18.y: commit 1e79b9b2ad95 ("Revert "f2fs: introduce f2fs_set_page_dirty_nobuffer") This patch reverts copied f2fs_set_page_dirty_nobuffer to use generic function for stability. This reverts commit fe76b796fc5194cc3d57265002e3a748566d073f. Change-Id: Ie3084e047d91cd1d01eb1cc2cb324654ab908121 Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/checkpoint.c | 2 +- fs/f2fs/data.c | 31 +------------------------------ fs/f2fs/f2fs.h | 1 - fs/f2fs/node.c | 2 +- 4 files changed, 3 insertions(+), 33 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 7ad7d858fab68..7e39554655680 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -386,7 +386,7 @@ static int f2fs_set_meta_page_dirty(struct page *page) if (!PageUptodate(page)) SetPageUptodate(page); if (!PageDirty(page)) { - f2fs_set_page_dirty_nobuffers(page); + __set_page_dirty_nobuffers(page); inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_META); SetPagePrivate(page); f2fs_trace_pid(page); diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 94a3fc7e3722c..18233dc137ec2 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -20,8 +20,6 @@ #include #include #include -#include -#include #include #include "f2fs.h" @@ -2485,33 +2483,6 @@ int f2fs_release_page(struct page *page, gfp_t wait) return 1; } -/* - * This was copied from __set_page_dirty_buffers which gives higher performance - * in very high speed storages. (e.g., pmem) - */ -void f2fs_set_page_dirty_nobuffers(struct page *page) -{ - struct address_space *mapping = page->mapping; - unsigned long flags; - - if (unlikely(!mapping)) - return; - - spin_lock(&mapping->private_lock); - SetPageDirty(page); - spin_unlock(&mapping->private_lock); - - spin_lock_irqsave(&mapping->tree_lock, flags); - WARN_ON_ONCE(!PageUptodate(page)); - account_page_dirtied(page, mapping); - radix_tree_tag_set(&mapping->page_tree, - page_index(page), PAGECACHE_TAG_DIRTY); - spin_unlock_irqrestore(&mapping->tree_lock, flags); - - __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); - return; -} - static int f2fs_set_data_page_dirty(struct page *page) { struct address_space *mapping = page->mapping; @@ -2535,7 +2506,7 @@ static int f2fs_set_data_page_dirty(struct page *page) } if (!PageDirty(page)) { - f2fs_set_page_dirty_nobuffers(page); + __set_page_dirty_nobuffers(page); update_dirty_page(inode, page); return 1; } diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 99eaec83921e5..95d7b353395c1 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3028,7 +3028,6 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len); bool should_update_inplace(struct inode *inode, struct f2fs_io_info *fio); bool should_update_outplace(struct inode *inode, struct f2fs_io_info *fio); -void f2fs_set_page_dirty_nobuffers(struct page *page); int __f2fs_write_data_pages(struct address_space *mapping, struct writeback_control *wbc, enum iostat_type io_type); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index ef98dbab58136..d1503dd1554be 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1776,7 +1776,7 @@ static int f2fs_set_node_page_dirty(struct page *page) if (!PageUptodate(page)) SetPageUptodate(page); if (!PageDirty(page)) { - f2fs_set_page_dirty_nobuffers(page); + __set_page_dirty_nobuffers(page); inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_NODES); SetPagePrivate(page); f2fs_trace_pid(page); From 01d4b118dfadbb3ff6bf555e75ecd6598c1ad8bd Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 20 Apr 2018 23:44:59 -0700 Subject: [PATCH 487/508] f2fs: check cap_resource only for data blocks Cherry-pick from origin/upstream-f2fs-stable-linux-3.18.y: commit dae6d19699ab ("f2fs: check cap_resource only for data blocks") This patch changes the rule to check cap_resource for data blocks, not inode or node blocks in order to avoid selinux denial. Change-Id: I02bc7b9eb78b64323d71cb945850b2c4828dcebd Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 95d7b353395c1..ad1449cd1a051 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1712,7 +1712,7 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs) } static inline bool __allow_reserved_blocks(struct f2fs_sb_info *sbi, - struct inode *inode) + struct inode *inode, bool cap) { if (!inode) return true; @@ -1725,7 +1725,7 @@ static inline bool __allow_reserved_blocks(struct f2fs_sb_info *sbi, if (!gid_eq(F2FS_OPTION(sbi).s_resgid, GLOBAL_ROOT_GID) && in_group_p(F2FS_OPTION(sbi).s_resgid)) return true; - if (capable(CAP_SYS_RESOURCE)) + if (cap && capable(CAP_SYS_RESOURCE)) return true; return false; } @@ -1760,7 +1760,7 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, avail_user_block_count = sbi->user_block_count - sbi->current_reserved_blocks; - if (!__allow_reserved_blocks(sbi, inode)) + if (!__allow_reserved_blocks(sbi, inode, true)) avail_user_block_count -= F2FS_OPTION(sbi).root_reserved_blocks; if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) { @@ -1967,7 +1967,7 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi, valid_block_count = sbi->total_valid_block_count + sbi->current_reserved_blocks + 1; - if (!__allow_reserved_blocks(sbi, inode)) + if (!__allow_reserved_blocks(sbi, inode, false)) valid_block_count += F2FS_OPTION(sbi).root_reserved_blocks; if (unlikely(valid_block_count > sbi->user_block_count)) { From 46be7ed39ed34196c1d3346ed2c292d6aee4e3b4 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 11 Apr 2018 23:09:04 -0700 Subject: [PATCH 488/508] UPSTREAM: f2fs: clear PageError on writepage - part 2 This patch clears PageError in some pages tagged by read path, but when we write the pages with valid contents, writepage should clear the bit likewise ext4. Change-Id: I96f100b7710c18994e8f12b772e929f5664582c8 Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim (cherry picked from commit 61ff7698eb4f2a140d6dc40cc6c1920bedfc64fb) --- fs/f2fs/gc.c | 1 + fs/f2fs/inline.c | 1 + fs/f2fs/node.c | 1 + fs/f2fs/segment.c | 1 + 4 files changed, 4 insertions(+) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 604d3fcb89572..66044faf2b71c 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -693,6 +693,7 @@ static void move_data_block(struct inode *inode, block_t bidx, dec_page_count(fio.sbi, F2FS_DIRTY_META); set_page_writeback(fio.encrypted_page); + ClearPageError(page); /* allocate block address */ f2fs_wait_on_page_writeback(dn.node_page, NODE, true); diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index feb96e6bd4310..3337bfe4989eb 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -157,6 +157,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page) /* write data page to try to make data consistent */ set_page_writeback(page); + ClearPageError(page); fio.old_blkaddr = dn->data_blkaddr; set_inode_flag(dn->inode, FI_HOT_DATA); write_data_page(dn, &fio); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index d1503dd1554be..5c5575d53c149 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1399,6 +1399,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, fio.op_flags |= WRITE_FLUSH_FUA; set_page_writeback(page); + ClearPageError(page); fio.old_blkaddr = ni.blk_addr; write_node_page(nid, &fio); set_node_addr(sbi, &ni, fio.new_blkaddr, is_fsync_dnode(page)); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 127bd4814a616..208bf769f8d01 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2840,6 +2840,7 @@ void write_meta_page(struct f2fs_sb_info *sbi, struct page *page, fio.op_flags &= ~REQ_META; set_page_writeback(page); + ClearPageError(page); f2fs_submit_page_write(&fio); f2fs_update_iostat(sbi, io_type, F2FS_BLKSIZE); From 1701775b27454a32bfb67ad7b65358af62bef959 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 3 May 2018 23:26:02 -0700 Subject: [PATCH 489/508] UPSTREAM: f2fs: avoid fsync() failure caused by EAGAIN in writepage() pageout() in MM traslates EAGAIN, so calls handle_write_error() -> mapping_set_error() -> set_bit(AS_EIO, ...). file_write_and_wait_range() will see EIO error, which is critical to return value of fsync() followed by atomic_write failure to user. Change-Id: I1e1048eb271a58ddcb8a3050922d9e883aa0252c Signed-off-by: Jaegeuk Kim (cherry picked from commit 8c088f40561cb73b8226ef975e66b5285c8943df) --- fs/f2fs/data.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 18233dc137ec2..e2e560e524593 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1886,7 +1886,13 @@ static int __write_data_page(struct page *page, bool *submitted, redirty_out: redirty_page_for_writepage(wbc, page); - if (!err) + /* + * pageout() in MM traslates EAGAIN, so calls handle_write_error() + * -> mapping_set_error() -> set_bit(AS_EIO, ...). + * file_write_and_wait_range() will see EIO error, which is critical + * to return value of fsync() followed by atomic_write failure to user. + */ + if (!err || wbc->for_reclaim) return AOP_WRITEPAGE_ACTIVATE; unlock_page(page); return err; From e82403e275a209a4b861453e22dfd7a6d58e1477 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 24 May 2018 13:57:26 -0700 Subject: [PATCH 490/508] FROMLIST: f2fs: early updates queued for v4.18-rc1 Cherry-picked from: origin/upstream-f2fs-stable-linux-3.18.y 0643d71e87e5 ("f2fs: turn down IO priority of discard from background") 6d854622f61f ("f2fs: don't split checkpoint in fstrim") da639d169ac6 ("f2fs: issue discard commands proactively in high fs utilization") 413fa22b9319 ("f2fs: add fsync_mode=nobarrier for non-atomic files") d7a1b25656a0 ("f2fs: let fstrim issue discard commands in lower priority") Change-Id: Ic83898da3eb921238ec154e839120e825325925c Signed-off-by: Jaegeuk Kim --- Documentation/ABI/testing/sysfs-fs-f2fs | 1 + Documentation/filesystems/f2fs.txt | 16 +- fs/f2fs/f2fs.h | 13 +- fs/f2fs/file.c | 2 +- fs/f2fs/segment.c | 246 ++++++++++++------------ fs/f2fs/super.c | 4 + fs/f2fs/sysfs.c | 3 + 7 files changed, 148 insertions(+), 137 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs index b8d0a30f16445..f82da9bbb1fd7 100644 --- a/Documentation/ABI/testing/sysfs-fs-f2fs +++ b/Documentation/ABI/testing/sysfs-fs-f2fs @@ -101,6 +101,7 @@ Date: February 2015 Contact: "Jaegeuk Kim" Description: Controls the trimming rate in batch mode. + What: /sys/fs/f2fs//cp_interval Date: October 2015 diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt index 36cd634f687a2..9342fde559822 100644 --- a/Documentation/filesystems/f2fs.txt +++ b/Documentation/filesystems/f2fs.txt @@ -169,13 +169,15 @@ whint_mode=%s Control which write hints are passed down to block passes down hints with its policy. alloc_mode=%s Adjust block allocation policy, which supports "reuse" and "default". -fsync_mode=%s Control the policy of fsync. Currently supports "posix" - and "strict". In "posix" mode, which is default, fsync - will follow POSIX semantics and does a light operation - to improve the filesystem performance. In "strict" mode, - fsync will be heavy and behaves in line with xfs, ext4 - and btrfs, where xfstest generic/342 will pass, but the - performance will regress. +fsync_mode=%s Control the policy of fsync. Currently supports "posix", + "strict", and "nobarrier". In "posix" mode, which is + default, fsync will follow POSIX semantics and does a + light operation to improve the filesystem performance. + In "strict" mode, fsync will be heavy and behaves in line + with xfs, ext4 and btrfs, where xfstest generic/342 will + pass, but the performance will regress. "nobarrier" is + based on "posix", but doesn't issue flush command for + non-atomic files likewise "nobarrier" mount option. test_dummy_encryption Enable dummy encryption, which provides a fake fscrypt context. The fake fscrypt context is used by xfstests. diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index ad1449cd1a051..e2f7e857dee20 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -279,15 +279,12 @@ enum { #define CP_DISCARD 0x00000010 #define CP_TRIMMED 0x00000020 -#define DEF_BATCHED_TRIM_SECTIONS 2048 -#define BATCHED_TRIM_SEGMENTS(sbi) \ - (GET_SEG_FROM_SEC(sbi, SM_I(sbi)->trim_sections)) -#define BATCHED_TRIM_BLOCKS(sbi) \ - (BATCHED_TRIM_SEGMENTS(sbi) << (sbi)->log_blocks_per_seg) #define MAX_DISCARD_BLOCKS(sbi) BLKS_PER_SEC(sbi) #define DEF_MAX_DISCARD_REQUEST 8 /* issue 8 discards per round */ +#define DEF_MAX_DISCARD_LEN 512 /* Max. 2MB per discard */ #define DEF_MIN_DISCARD_ISSUE_TIME 50 /* 50 ms, if exists */ #define DEF_MAX_DISCARD_ISSUE_TIME 60000 /* 60 s, if no candidates */ +#define DEF_DISCARD_URGENT_UTIL 80 /* do more discard over 80% */ #define DEF_CP_INTERVAL 60 /* 60 secs */ #define DEF_IDLE_INTERVAL 5 /* 5 secs */ @@ -792,7 +789,8 @@ static inline void set_extent_info(struct extent_info *ei, unsigned int fofs, static inline bool __is_discard_mergeable(struct discard_info *back, struct discard_info *front) { - return back->lstart + back->len == front->lstart; + return (back->lstart + back->len == front->lstart) && + (back->len + front->len < DEF_MAX_DISCARD_LEN); } static inline bool __is_discard_back_mergeable(struct discard_info *cur, @@ -1178,6 +1176,7 @@ enum { enum fsync_mode { FSYNC_MODE_POSIX, /* fsync follows posix semantics */ FSYNC_MODE_STRICT, /* fsync behaves in line with ext4 */ + FSYNC_MODE_NOBARRIER, /* fsync behaves nobarrier based on posix */ }; #ifdef CONFIG_F2FS_FS_ENCRYPTION @@ -2910,8 +2909,6 @@ int f2fs_flush_device_cache(struct f2fs_sb_info *sbi); void destroy_flush_cmd_control(struct f2fs_sb_info *sbi, bool free); void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr); bool is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr); -void init_discard_policy(struct discard_policy *dpolicy, int discard_type, - unsigned int granularity); void drop_discard_cmd(struct f2fs_sb_info *sbi); void stop_discard_thread(struct f2fs_sb_info *sbi); bool f2fs_wait_discard_bios(struct f2fs_sb_info *sbi); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 7a5f1572cb76a..c742a3d67ab3e 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -310,7 +310,7 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end, remove_ino_entry(sbi, ino, APPEND_INO); clear_inode_flag(inode, FI_APPEND_WRITE); flush_out: - if (!atomic) + if (!atomic && F2FS_OPTION(sbi).fsync_mode != FSYNC_MODE_NOBARRIER) ret = f2fs_issue_flush(sbi, inode->i_ino); if (!ret) { remove_ino_entry(sbi, ino, UPDATE_INO); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 208bf769f8d01..37186f6e5429c 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -997,6 +997,39 @@ static void __check_sit_bitmap(struct f2fs_sb_info *sbi, #endif } +static void __init_discard_policy(struct f2fs_sb_info *sbi, + struct discard_policy *dpolicy, + int discard_type, unsigned int granularity) +{ + /* common policy */ + dpolicy->type = discard_type; + dpolicy->sync = true; + dpolicy->granularity = granularity; + + dpolicy->max_requests = DEF_MAX_DISCARD_REQUEST; + dpolicy->io_aware_gran = MAX_PLIST_NUM; + + if (discard_type == DPOLICY_BG) { + dpolicy->min_interval = DEF_MIN_DISCARD_ISSUE_TIME; + dpolicy->max_interval = DEF_MAX_DISCARD_ISSUE_TIME; + dpolicy->io_aware = true; + dpolicy->sync = false; + if (utilization(sbi) > DEF_DISCARD_URGENT_UTIL) { + dpolicy->granularity = 1; + dpolicy->max_interval = DEF_MIN_DISCARD_ISSUE_TIME; + } + } else if (discard_type == DPOLICY_FORCE) { + dpolicy->min_interval = DEF_MIN_DISCARD_ISSUE_TIME; + dpolicy->max_interval = DEF_MAX_DISCARD_ISSUE_TIME; + dpolicy->io_aware = false; + } else if (discard_type == DPOLICY_FSTRIM) { + dpolicy->io_aware = false; + } else if (discard_type == DPOLICY_UMOUNT) { + dpolicy->io_aware = false; + } +} + + /* this function is copied from blkdev_issue_discard from block/blk-lib.c */ static void __submit_discard_cmd(struct f2fs_sb_info *sbi, struct discard_policy *dpolicy, @@ -1211,68 +1244,6 @@ static int __queue_discard_cmd(struct f2fs_sb_info *sbi, return 0; } -static void __issue_discard_cmd_range(struct f2fs_sb_info *sbi, - struct discard_policy *dpolicy, - unsigned int start, unsigned int end) -{ - struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; - struct discard_cmd *prev_dc = NULL, *next_dc = NULL; - struct rb_node **insert_p = NULL, *insert_parent = NULL; - struct discard_cmd *dc; - struct blk_plug plug; - int issued; - -next: - issued = 0; - - mutex_lock(&dcc->cmd_lock); - f2fs_bug_on(sbi, !__check_rb_tree_consistence(sbi, &dcc->root)); - - dc = (struct discard_cmd *)__lookup_rb_tree_ret(&dcc->root, - NULL, start, - (struct rb_entry **)&prev_dc, - (struct rb_entry **)&next_dc, - &insert_p, &insert_parent, true); - if (!dc) - dc = next_dc; - - blk_start_plug(&plug); - - while (dc && dc->lstart <= end) { - struct rb_node *node; - - if (dc->len < dpolicy->granularity) - goto skip; - - if (dc->state != D_PREP) { - list_move_tail(&dc->list, &dcc->fstrim_list); - goto skip; - } - - __submit_discard_cmd(sbi, dpolicy, dc); - - if (++issued >= dpolicy->max_requests) { - start = dc->lstart + dc->len; - - blk_finish_plug(&plug); - mutex_unlock(&dcc->cmd_lock); - - schedule(); - - goto next; - } -skip: - node = rb_next(&dc->rb_node); - dc = rb_entry_safe(node, struct discard_cmd, rb_node); - - if (fatal_signal_pending(current)) - break; - } - - blk_finish_plug(&plug); - mutex_unlock(&dcc->cmd_lock); -} - static int __issue_discard_cmd(struct f2fs_sb_info *sbi, struct discard_policy *dpolicy) { @@ -1413,7 +1384,18 @@ static unsigned int __wait_discard_cmd_range(struct f2fs_sb_info *sbi, static void __wait_all_discard_cmd(struct f2fs_sb_info *sbi, struct discard_policy *dpolicy) { - __wait_discard_cmd_range(sbi, dpolicy, 0, UINT_MAX); + struct discard_policy dp; + + if (dpolicy) { + __wait_discard_cmd_range(sbi, dpolicy, 0, UINT_MAX); + return; + } + + /* wait all */ + __init_discard_policy(sbi, &dp, DPOLICY_FSTRIM, 1); + __wait_discard_cmd_range(sbi, &dp, 0, UINT_MAX); + __init_discard_policy(sbi, &dp, DPOLICY_UMOUNT, 1); + __wait_discard_cmd_range(sbi, &dp, 0, UINT_MAX); } /* This should be covered by global mutex, &sit_i->sentry_lock */ @@ -1458,11 +1440,13 @@ bool f2fs_wait_discard_bios(struct f2fs_sb_info *sbi) struct discard_policy dpolicy; bool dropped; - init_discard_policy(&dpolicy, DPOLICY_UMOUNT, dcc->discard_granularity); + __init_discard_policy(sbi, &dpolicy, DPOLICY_UMOUNT, + dcc->discard_granularity); __issue_discard_cmd(sbi, &dpolicy); dropped = __drop_discard_cmd(sbi); - __wait_all_discard_cmd(sbi, &dpolicy); + /* just to make sure there is no pending discard commands */ + __wait_all_discard_cmd(sbi, NULL); return dropped; } @@ -1478,7 +1462,7 @@ static int issue_discard_thread(void *data) set_freezable(); do { - init_discard_policy(&dpolicy, DPOLICY_BG, + __init_discard_policy(sbi, &dpolicy, DPOLICY_BG, dcc->discard_granularity); wait_event_interruptible_timeout(*q, @@ -1496,7 +1480,7 @@ static int issue_discard_thread(void *data) dcc->discard_wake = 0; if (sbi->gc_thread && sbi->gc_thread->gc_urgent) - init_discard_policy(&dpolicy, DPOLICY_FORCE, 1); + __init_discard_policy(sbi, &dpolicy, DPOLICY_FORCE, 1); sb_start_intwrite(sbi->sb); @@ -1789,32 +1773,6 @@ void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc) wake_up_discard_thread(sbi, false); } -void init_discard_policy(struct discard_policy *dpolicy, - int discard_type, unsigned int granularity) -{ - /* common policy */ - dpolicy->type = discard_type; - dpolicy->sync = true; - dpolicy->granularity = granularity; - - dpolicy->max_requests = DEF_MAX_DISCARD_REQUEST; - dpolicy->io_aware_gran = MAX_PLIST_NUM; - - if (discard_type == DPOLICY_BG) { - dpolicy->min_interval = DEF_MIN_DISCARD_ISSUE_TIME; - dpolicy->max_interval = DEF_MAX_DISCARD_ISSUE_TIME; - dpolicy->io_aware = true; - } else if (discard_type == DPOLICY_FORCE) { - dpolicy->min_interval = DEF_MIN_DISCARD_ISSUE_TIME; - dpolicy->max_interval = DEF_MAX_DISCARD_ISSUE_TIME; - dpolicy->io_aware = false; - } else if (discard_type == DPOLICY_FSTRIM) { - dpolicy->io_aware = false; - } else if (discard_type == DPOLICY_UMOUNT) { - dpolicy->io_aware = false; - } -} - static int create_discard_cmd_control(struct f2fs_sb_info *sbi) { dev_t dev = sbi->sb->s_bdev->bd_dev; @@ -2454,11 +2412,72 @@ bool exist_trim_candidates(struct f2fs_sb_info *sbi, struct cp_control *cpc) return has_candidate; } +static void __issue_discard_cmd_range(struct f2fs_sb_info *sbi, + struct discard_policy *dpolicy, + unsigned int start, unsigned int end) +{ + struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; + struct discard_cmd *prev_dc = NULL, *next_dc = NULL; + struct rb_node **insert_p = NULL, *insert_parent = NULL; + struct discard_cmd *dc; + struct blk_plug plug; + int issued; + +next: + issued = 0; + + mutex_lock(&dcc->cmd_lock); + f2fs_bug_on(sbi, !__check_rb_tree_consistence(sbi, &dcc->root)); + + dc = (struct discard_cmd *)__lookup_rb_tree_ret(&dcc->root, + NULL, start, + (struct rb_entry **)&prev_dc, + (struct rb_entry **)&next_dc, + &insert_p, &insert_parent, true); + if (!dc) + dc = next_dc; + + blk_start_plug(&plug); + + while (dc && dc->lstart <= end) { + struct rb_node *node; + + if (dc->len < dpolicy->granularity) + goto skip; + + if (dc->state != D_PREP) { + list_move_tail(&dc->list, &dcc->fstrim_list); + goto skip; + } + + __submit_discard_cmd(sbi, dpolicy, dc); + + if (++issued >= dpolicy->max_requests) { + start = dc->lstart + dc->len; + + blk_finish_plug(&plug); + mutex_unlock(&dcc->cmd_lock); + __wait_all_discard_cmd(sbi, NULL); + congestion_wait(BLK_RW_ASYNC, HZ/50); + goto next; + } +skip: + node = rb_next(&dc->rb_node); + dc = rb_entry_safe(node, struct discard_cmd, rb_node); + + if (fatal_signal_pending(current)) + break; + } + + blk_finish_plug(&plug); + mutex_unlock(&dcc->cmd_lock); +} + int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) { __u64 start = F2FS_BYTES_TO_BLK(range->start); __u64 end = start + F2FS_BYTES_TO_BLK(range->len) - 1; - unsigned int start_segno, end_segno, cur_segno; + unsigned int start_segno, end_segno; block_t start_block, end_block; struct cp_control cpc; struct discard_policy dpolicy; @@ -2484,40 +2503,27 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) cpc.reason = CP_DISCARD; cpc.trim_minlen = max_t(__u64, 1, F2FS_BYTES_TO_BLK(range->minlen)); + cpc.trim_start = start_segno; + cpc.trim_end = end_segno; - /* do checkpoint to issue discard commands safely */ - for (cur_segno = start_segno; cur_segno <= end_segno; - cur_segno = cpc.trim_end + 1) { - cpc.trim_start = cur_segno; - - if (sbi->discard_blks == 0) - break; - else if (sbi->discard_blks < BATCHED_TRIM_BLOCKS(sbi)) - cpc.trim_end = end_segno; - else - cpc.trim_end = min_t(unsigned int, - rounddown(cur_segno + - BATCHED_TRIM_SEGMENTS(sbi), - sbi->segs_per_sec) - 1, end_segno); - - mutex_lock(&sbi->gc_mutex); - err = write_checkpoint(sbi, &cpc); - mutex_unlock(&sbi->gc_mutex); - if (err) - break; + if (sbi->discard_blks == 0) + goto out; - schedule(); - } + mutex_lock(&sbi->gc_mutex); + err = write_checkpoint(sbi, &cpc); + mutex_unlock(&sbi->gc_mutex); + if (err) + goto out; start_block = START_BLOCK(sbi, start_segno); - end_block = START_BLOCK(sbi, min(cur_segno, end_segno) + 1); + end_block = START_BLOCK(sbi, end_segno + 1); - init_discard_policy(&dpolicy, DPOLICY_FSTRIM, cpc.trim_minlen); + __init_discard_policy(sbi, &dpolicy, DPOLICY_FSTRIM, cpc.trim_minlen); __issue_discard_cmd_range(sbi, &dpolicy, start_block, end_block); trimmed = __wait_discard_cmd_range(sbi, &dpolicy, start_block, end_block); -out: range->len = F2FS_BLK_TO_BYTES(trimmed); +out: return err; } @@ -3906,8 +3912,6 @@ int build_segment_manager(struct f2fs_sb_info *sbi) sm_info->min_hot_blocks = DEF_MIN_HOT_BLOCKS; sm_info->min_ssr_sections = reserved_sections(sbi); - sm_info->trim_sections = DEF_BATCHED_TRIM_SECTIONS; - INIT_LIST_HEAD(&sm_info->sit_entry_set); init_rwsem(&sm_info->curseg_lock); diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 5a6b61f44991b..4597b48283f8d 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -756,6 +756,10 @@ static int parse_options(struct super_block *sb, char *options) } else if (strlen(name) == 6 && !strncmp(name, "strict", 6)) { F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_STRICT; + } else if (strlen(name) == 9 && + !strncmp(name, "nobarrier", 9)) { + F2FS_OPTION(sbi).fsync_mode = + FSYNC_MODE_NOBARRIER; } else { kfree(name); return -EINVAL; diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 1eb2dfad855b6..5a68f5a269560 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -245,6 +245,9 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a, return count; } + if (!strcmp(a->attr.name, "trim_sections")) + return -EINVAL; + *ui = t; if (!strcmp(a->attr.name, "iostat_enable") && *ui == 0) From 5578be680016d9459ad7ddff2eb41669fd995859 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 31 May 2018 10:20:48 -0700 Subject: [PATCH 491/508] FROMLIST: f2fs: run fstrim asynchronously if runtime discard is on Cherry-picked from: origin/upstream-f2fs-stable-linux-3.18.y We don't need to wait for whole bunch of discard candidates in fstrim, since runtime discard will issue them in idle time. Change-Id: I7dab8241370ccbb2222a513fadc50d1b479b32c2 Signed-off-by: Jaegeuk Kim --- fs/f2fs/segment.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 37186f6e5429c..d7d248c6b342e 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2520,9 +2520,18 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) __init_discard_policy(sbi, &dpolicy, DPOLICY_FSTRIM, cpc.trim_minlen); __issue_discard_cmd_range(sbi, &dpolicy, start_block, end_block); - trimmed = __wait_discard_cmd_range(sbi, &dpolicy, + + /* + * We filed discard candidates, but actually we don't need to wait for + * all of them, since they'll be issued in idle time along with runtime + * discard option. User configuration looks like using runtime discard + * or periodic fstrim instead of it. + */ + if (!test_opt(sbi, DISCARD)) { + trimmed = __wait_discard_cmd_range(sbi, &dpolicy, start_block, end_block); - range->len = F2FS_BLK_TO_BYTES(trimmed); + range->len = F2FS_BLK_TO_BYTES(trimmed); + } out: return err; } From f4426d93b22f9beb9d532e98186c71ad6376faf2 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Fri, 29 Jun 2018 18:02:41 +0530 Subject: [PATCH 492/508] mido: enable quota configs * https://source.android.com/devices/storage/faster-stats Change-Id: Iad40e1d941bd6e8d311947d0e06249c334f1c1c4 --- arch/arm64/configs/mido_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/mido_defconfig b/arch/arm64/configs/mido_defconfig index d644b8cf14982..250b02e8d4c74 100644 --- a/arch/arm64/configs/mido_defconfig +++ b/arch/arm64/configs/mido_defconfig @@ -4051,8 +4051,9 @@ CONFIG_QUOTA=y # CONFIG_QUOTA_NETLINK_INTERFACE is not set # CONFIG_PRINT_QUOTA_WARNING is not set # CONFIG_QUOTA_DEBUG is not set +CONFIG_QUOTA_TREE=y # CONFIG_QFMT_V1 is not set -# CONFIG_QFMT_V2 is not set +CONFIG_QFMT_V2=y CONFIG_QUOTACTL=y # CONFIG_AUTOFS4_FS is not set CONFIG_FUSE_FS=y From e95f64bf649512d2c1ee8630d1037782688654e6 Mon Sep 17 00:00:00 2001 From: Bruno Martins Date: Sat, 24 Feb 2018 09:21:27 +0000 Subject: [PATCH 493/508] fs: Import sdFAT driver * Samsung driver version 1.4.16 * From Samsung package version: G950FXXU1CRAP Change-Id: I0a0f7365d432f0e006ecc6ca0d305008cc44444c --- fs/Kconfig | 1 + fs/Makefile | 1 + fs/sdfat/Kconfig | 103 + fs/sdfat/Makefile | 24 + fs/sdfat/amap_smart.c | 1302 +++++++++++ fs/sdfat/amap_smart.h | 137 ++ fs/sdfat/api.c | 629 +++++ fs/sdfat/api.h | 397 ++++ fs/sdfat/blkdev.c | 416 ++++ fs/sdfat/cache.c | 842 +++++++ fs/sdfat/config.h | 146 ++ fs/sdfat/core.c | 3672 ++++++++++++++++++++++++++++++ fs/sdfat/core.h | 219 ++ fs/sdfat/core_exfat.c | 1533 +++++++++++++ fs/sdfat/core_fat.c | 1453 ++++++++++++ fs/sdfat/dfr.c | 1377 +++++++++++ fs/sdfat/dfr.h | 261 +++ fs/sdfat/extent.c | 355 +++ fs/sdfat/fatent.c | 412 ++++ fs/sdfat/misc.c | 380 ++++ fs/sdfat/mpage.c | 607 +++++ fs/sdfat/nls.c | 478 ++++ fs/sdfat/sdfat.c | 5051 +++++++++++++++++++++++++++++++++++++++++ fs/sdfat/sdfat.h | 507 +++++ fs/sdfat/sdfat_fs.h | 416 ++++ fs/sdfat/statistics.c | 262 +++ fs/sdfat/upcase.h | 407 ++++ fs/sdfat/version.h | 25 + fs/sdfat/xattr.c | 132 ++ 29 files changed, 21545 insertions(+) create mode 100644 fs/sdfat/Kconfig create mode 100644 fs/sdfat/Makefile create mode 100644 fs/sdfat/amap_smart.c create mode 100644 fs/sdfat/amap_smart.h create mode 100644 fs/sdfat/api.c create mode 100644 fs/sdfat/api.h create mode 100644 fs/sdfat/blkdev.c create mode 100644 fs/sdfat/cache.c create mode 100644 fs/sdfat/config.h create mode 100644 fs/sdfat/core.c create mode 100644 fs/sdfat/core.h create mode 100644 fs/sdfat/core_exfat.c create mode 100644 fs/sdfat/core_fat.c create mode 100644 fs/sdfat/dfr.c create mode 100644 fs/sdfat/dfr.h create mode 100644 fs/sdfat/extent.c create mode 100644 fs/sdfat/fatent.c create mode 100644 fs/sdfat/misc.c create mode 100644 fs/sdfat/mpage.c create mode 100644 fs/sdfat/nls.c create mode 100644 fs/sdfat/sdfat.c create mode 100644 fs/sdfat/sdfat.h create mode 100644 fs/sdfat/sdfat_fs.h create mode 100644 fs/sdfat/statistics.c create mode 100644 fs/sdfat/upcase.h create mode 100644 fs/sdfat/version.h create mode 100644 fs/sdfat/xattr.c diff --git a/fs/Kconfig b/fs/Kconfig index 2e85aaf8b85fe..20608c99bb065 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -91,6 +91,7 @@ if BLOCK menu "DOS/FAT/NT Filesystems" source "fs/fat/Kconfig" +source "fs/sdfat/Kconfig" source "fs/ntfs/Kconfig" endmenu diff --git a/fs/Makefile b/fs/Makefile index f67fb07a0b68d..0393985d75a61 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ obj-$(CONFIG_MINIX_FS) += minix/ obj-$(CONFIG_FAT_FS) += fat/ +obj-$(CONFIG_SDFAT_FS) += sdfat/ obj-$(CONFIG_BFS_FS) += bfs/ obj-$(CONFIG_ISO9660_FS) += isofs/ obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+ diff --git a/fs/sdfat/Kconfig b/fs/sdfat/Kconfig new file mode 100644 index 0000000000000..73ed755bbef61 --- /dev/null +++ b/fs/sdfat/Kconfig @@ -0,0 +1,103 @@ +config SDFAT_FS + tristate "sdFAT fs support" + default y + select NLS + select NLS_UTF8 + select NLS_CODEPAGE_437 + select NLS_ISO8859_1 + help + If you want to use the sdFAT file system, then you must say Y or M + here to inlucde sdFAT support. + sdFAT is unified FAT-based file system which supports not only fat12/ + 16/32 with vfat but also exfat. sdFAT supports winnt short-name rule. + (winnt: emulate the Windows NT rule for display/create.) + + To compile this as a module, choose M here: the module will be called + sdfat_core and sdfat_fs. + +config SDFAT_DELAYED_META_DIRTY + bool "Enable delayed metadata dirty" + default y + depends on SDFAT_FS + help + If you enable this feature, metadata(FAT/Directory entry) is updated + by flush thread. + +config SDFAT_SUPPORT_DIR_SYNC + bool "Enable supporting dir sync" + default n + depends on SDFAT_FS + help + If you enable this feature, the modification for directory operation + is written to a storage at once. + +config SDFAT_DEFAULT_CODEPAGE + int "Default codepage for sdFAT" + default 437 + depends on SDFAT_FS + help + This option should be set to the codepage of your sdFAT filesystems. + +config SDFAT_DEFAULT_IOCHARSET + string "Default iocharset for sdFAT" + default "utf8" + depends on SDFAT_FS + help + Set this to the default input/output character set you'd + like sdFAT to use. It should probably match the character set + that most of your sdFAT filesystems use, and can be overridden + with the "iocharset" mount option for sdFAT filesystems. + +config SDFAT_CHECK_RO_ATTR + bool "Check read-only attribute" + default n + depends on SDFAT_FS + +config SDFAT_ALIGNED_MPAGE_WRITE + bool "Enable supporting aligned mpage_write" + default y + depends on SDFAT_FS + +config SDFAT_VIRTUAL_XATTR + bool "Virtual xattr support for sdFAT" + default y + depends on SDFAT_FS + help + To support virtual xattr. + +config SDFAT_VIRTUAL_XATTR_SELINUX_LABEL + string "Default string for SELinux label" + default "u:object_r:sdcard_external:s0" + depends on SDFAT_FS && SDFAT_VIRTUAL_XATTR + help + Set this to the default string for SELinux label. + +config SDFAT_SUPPORT_STLOG + bool "Enable storage log" + default y + depends on SDFAT_FS && PROC_STLOG + +config SDFAT_DEBUG + bool "Enable debug features" + depends on SDFAT_FS + default y + +config SDFAT_DBG_IOCTL + bool "Enable debug-ioctl features" + depends on SDFAT_FS && SDFAT_DEBUG + default n + +config SDFAT_DBG_MSG + bool "Enable debug messages" + depends on SDFAT_FS && SDFAT_DEBUG + default y + +config SDFAT_DBG_BUGON + bool "Enable strict BUG_ON() for debugging" + depends on SDFAT_FS && SDFAT_DEBUG + default n + +config SDFAT_STATISTICS + bool "Enable statistics for bigdata" + depends on SDFAT_FS + default y diff --git a/fs/sdfat/Makefile b/fs/sdfat/Makefile new file mode 100644 index 0000000000000..a5cd0858c6caa --- /dev/null +++ b/fs/sdfat/Makefile @@ -0,0 +1,24 @@ +# +# Makefile for the linux FAT12/16/32(VFAT)/64(exFAT) filesystem driver. +# + +obj-$(CONFIG_SDFAT_FS) += sdfat_fs.o + +sdfat_fs-objs := sdfat.o core.o core_fat.o core_exfat.o api.o blkdev.o \ + fatent.o amap_smart.o cache.o dfr.o nls.o misc.o \ + mpage.o extent.o + +sdfat_fs-$(CONFIG_SDFAT_VIRTUAL_XATTR) += xattr.o +sdfat_fs-$(CONFIG_SDFAT_STATISTICS) += statistics.o + + +all: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules + +clean: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean + +cscope: + rm -rf cscope.files cscope.files + find $(PWD) \( -name '*.c' -o -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.s' -o -name '*.S' \) -print > cscope.files + cscope diff --git a/fs/sdfat/amap_smart.c b/fs/sdfat/amap_smart.c new file mode 100644 index 0000000000000..99e32a617c113 --- /dev/null +++ b/fs/sdfat/amap_smart.c @@ -0,0 +1,1302 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : amap_smart.c */ +/* PURPOSE : FAT32 Smart allocation code for sdFAT */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/* */ +/************************************************************************/ + +#include +#include + +#include "sdfat.h" +#include "core.h" +#include "amap_smart.h" + +/* AU list related functions */ +static inline void amap_list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + + /* Will be used to check if the entry is a single entry(selected) */ + entry->prev = NULL; + entry->next = NULL; +} + +static inline int amap_insert_to_list(AU_INFO_T *au, struct slist_head *shead) +{ + struct slist_head *entry = &au->shead; + + ASSERT(!entry->head); + + entry->next = shead->next; + entry->head = shead; + + shead->next = entry; + + return 0; +} + +static inline int amap_remove_from_list(AU_INFO_T *au, struct slist_head *shead) +{ + struct slist_head *entry = &au->shead; + struct slist_head *iter; + + BUG_ON(entry->head != shead); + + iter = shead; + + while (iter->next) { + if (iter->next == entry) { + // iter->next = iter->next->next + iter->next = entry->next; + + entry->next = NULL; + entry->head = NULL; + return 0; + } + iter = iter->next; + } + + BUG_ON("Not reachable"); +} + +/* Full-linear serach => Find AU with max. number of fclu */ +static inline AU_INFO_T *amap_find_hot_au_largest(struct slist_head *shead) +{ + struct slist_head *iter; + uint16_t max_fclu = 0; + AU_INFO_T *entry, *ret = NULL; + + ASSERT(shead->head == shead); /* Singly-list condition */ + ASSERT(shead->next != shead); + + iter = shead->next; + + while (iter) { + entry = list_entry(iter, AU_INFO_T, shead); + + if (entry->free_clusters > max_fclu) { + max_fclu = entry->free_clusters; + ret = entry; + } + + iter = iter->next; + } + + return ret; +} + +/* Find partially used AU with max. number of fclu. + * If there is no partial AU available, pick a clean one + */ +static inline AU_INFO_T *amap_find_hot_au_partial(AMAP_T *amap) +{ + struct slist_head *iter; + uint16_t max_fclu = 0; + AU_INFO_T *entry, *ret = NULL; + + iter = &amap->slist_hot; + ASSERT(iter->head == iter); /* Singly-list condition */ + ASSERT(iter->next != iter); + + iter = iter->next; + + while (iter) { + entry = list_entry(iter, AU_INFO_T, shead); + + if (entry->free_clusters > max_fclu) { + if (entry->free_clusters < amap->clusters_per_au) { + max_fclu = entry->free_clusters; + ret = entry; + } else { + if (!ret) + ret = entry; + } + } + + iter = iter->next; + } + + return ret; +} + + + + +/* + * Size-base AU management functions + */ + +/* + * Add au into cold AU MAP + * au: an isolated (not in a list) AU data structure + */ +int amap_add_cold_au(AMAP_T *amap, AU_INFO_T *au) +{ + FCLU_NODE_T *fclu_node = NULL; + + /* Check if a single entry */ + BUG_ON(au->head.prev); + + /* Ignore if the au is full */ + if (!au->free_clusters) + return 0; + + /* Find entry */ + fclu_node = NODE(au->free_clusters, amap); + + /* Insert to the list */ + list_add_tail(&(au->head), &(fclu_node->head)); + + /* Update fclu_hint (Increase) */ + if (au->free_clusters > amap->fclu_hint) + amap->fclu_hint = au->free_clusters; + + return 0; +} + +/* + * Remove an AU from AU MAP + */ +int amap_remove_cold_au(AMAP_T *amap, AU_INFO_T *au) +{ + struct list_head *prev = au->head.prev; + + /* Single entries are not managed in lists */ + if (!prev) { + BUG_ON(au->free_clusters > 0); + return 0; + } + + /* remove from list */ + amap_list_del(&(au->head)); + + return 0; +} + + +/* "Find" best fit AU + * returns NULL if there is no AU w/ enough free space. + * + * This function doesn't change AU status. + * The caller should call amap_remove_cold_au() if needed. + */ +AU_INFO_T *amap_find_cold_au_bestfit(AMAP_T *amap, uint16_t free_clusters) +{ + AU_INFO_T *au = NULL; + FCLU_NODE_T *fclu_iter; + + if (free_clusters <= 0 || free_clusters > amap->clusters_per_au) { + EMSG("AMAP: amap_find_cold_au_bestfit / unexpected arg. (%d)\n", + free_clusters); + return NULL; + } + + fclu_iter = NODE(free_clusters, amap); + + if (amap->fclu_hint < free_clusters) { + /* There is no AUs with enough free_clusters */ + return NULL; + } + + /* Naive Hash management (++) */ + do { + if (!list_empty(&fclu_iter->head)) { + struct list_head *first = fclu_iter->head.next; + + au = list_entry(first, AU_INFO_T, head); + + break; + } + + fclu_iter++; + } while (fclu_iter < (amap->fclu_nodes + amap->clusters_per_au)); + + + // BUG_ON(au->free_clusters < 0); + BUG_ON(au && (au->free_clusters > amap->clusters_per_au)); + + return au; +} + + +/* "Pop" best fit AU + * + * returns NULL if there is no AU w/ enough free space. + * The returned AU will not be in the list anymore. + */ +AU_INFO_T *amap_pop_cold_au_bestfit(AMAP_T *amap, uint16_t free_clusters) +{ + /* Naive implementation */ + AU_INFO_T *au; + + au = amap_find_cold_au_bestfit(amap, free_clusters); + if (au) + amap_remove_cold_au(amap, au); + + return au; +} + + + +/* Pop the AU with the largest free space + * + * search from 'start_fclu' to 0 + * (target freecluster : -1 for each step) + * start_fclu = 0 means to search from the max. value + */ +AU_INFO_T *amap_pop_cold_au_largest(AMAP_T *amap, uint16_t start_fclu) +{ + AU_INFO_T *au = NULL; + FCLU_NODE_T *fclu_iter; + + if (!start_fclu) + start_fclu = amap->clusters_per_au; + if (start_fclu > amap->clusters_per_au) + start_fclu = amap->clusters_per_au; + + /* Use hint (search start point) */ + if (amap->fclu_hint < start_fclu) + fclu_iter = NODE(amap->fclu_hint, amap); + else + fclu_iter = NODE(start_fclu, amap); + + /* Naive Hash management */ + do { + if (!list_empty(&fclu_iter->head)) { + struct list_head *first = fclu_iter->head.next; + + au = list_entry(first, AU_INFO_T, head); + // BUG_ON((au < amap->entries) || ((amap->entries + amap->n_au) <= au)); + + amap_list_del(first); + + // (Hint) Possible maximum value of free clusters (among cold) + /* if it wasn't the whole search, don't update fclu_hint */ + if (start_fclu == amap->clusters_per_au) + amap->fclu_hint = au->free_clusters; + + break; + } + + fclu_iter--; + } while (amap->fclu_nodes <= fclu_iter); + + return au; +} + + + +/* + * =============================================== + * Allocation Map related functions + * =============================================== + */ + +/* Create AMAP related data structure (mount time) */ +int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hidden_sect) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + AMAP_T *amap; + int total_used_clusters; + int n_au_table = 0; + int i, i_clu, i_au; + int i_au_root = -1, i_au_hot_from = INT_MAX; + u32 misaligned_sect = hidden_sect; + + BUG_ON(!fsi->bd_opened); + + if (fsi->amap) + return -EEXIST; + + /* Check conditions */ + if (fsi->vol_type != FAT32) { + sdfat_msg(sb, KERN_ERR, "smart allocation is only available " + "with fat32-fs"); + return -ENOTSUPP; + } + + if (fsi->num_sectors < AMAP_MIN_SUPPORT_SECTORS) { + sdfat_msg(sb, KERN_ERR, "smart allocation is only available " + "with sectors above %d", AMAP_MIN_SUPPORT_SECTORS); + return -ENOTSUPP; + } + + /* AU size must be a multiple of clu_size */ + if ((sect_per_au <= 0) || (sect_per_au & (fsi->sect_per_clus - 1))) { + sdfat_msg(sb, KERN_ERR, + "invalid AU size (sect_per_au : %u, " + "sect_per_clus : %u) " + "please re-format for performance.", + sect_per_au, fsi->sect_per_clus); + return -EINVAL; + } + + /* the start sector of this partition must be a multiple of clu_size */ + if (misaligned_sect & (fsi->sect_per_clus - 1)) { + sdfat_msg(sb, KERN_ERR, + "misaligned part (start sect : %u, " + "sect_per_clus : %u) " + "please re-format for performance.", + misaligned_sect, fsi->sect_per_clus); + return -EINVAL; + } + + /* data start sector must be a multiple of clu_size */ + if (fsi->data_start_sector & (fsi->sect_per_clus - 1)) { + sdfat_msg(sb, KERN_ERR, + "misaligned data area (start sect : %u, " + "sect_per_clus : %u) " + "please re-format for performance.", + fsi->data_start_sector, fsi->sect_per_clus); + return -EINVAL; + } + + misaligned_sect &= (sect_per_au - 1); + + /* Allocate data structrues */ + amap = kzalloc(sizeof(AMAP_T), GFP_NOIO); + if (!amap) + return -ENOMEM; + + amap->sb = sb; + + amap->n_au = (fsi->num_sectors + misaligned_sect + sect_per_au - 1) / sect_per_au; + amap->n_clean_au = 0; + amap->n_full_au = 0; + + /* Reflect block-partition align first, + * then partition-data_start align + */ + amap->clu_align_bias = (misaligned_sect / fsi->sect_per_clus); + amap->clu_align_bias += (fsi->data_start_sector >> fsi->sect_per_clus_bits) - CLUS_BASE; + amap->clusters_per_au = sect_per_au / fsi->sect_per_clus; + + /* That is, + * the size of cluster is at least 4KB if the size of AU is 4MB + */ + if (amap->clusters_per_au > MAX_CLU_PER_AU) { + sdfat_log_msg(sb, KERN_INFO, + "too many clusters per AU (clus/au:%d > %d).", + amap->clusters_per_au, + MAX_CLU_PER_AU); + } + + /* is it needed? why here? */ + // set_sb_dirty(sb); + + spin_lock_init(&amap->amap_lock); + + amap->option.packing_ratio = pack_ratio; + amap->option.au_size = sect_per_au; + amap->option.au_align_factor = hidden_sect; + + + /* Allocate AU info table */ + n_au_table = (amap->n_au + N_AU_PER_TABLE - 1) / N_AU_PER_TABLE; + amap->au_table = kmalloc(sizeof(AU_INFO_T *) * n_au_table, GFP_NOIO); + if (!amap->au_table) { + sdfat_msg(sb, KERN_ERR, + "failed to alloc amap->au_table\n"); + kfree(amap); + return -ENOMEM; + } + + for (i = 0; i < n_au_table; i++) + amap->au_table[i] = (AU_INFO_T *)get_zeroed_page(GFP_NOIO); + + /* Allocate buckets indexed by # of free clusters */ + amap->fclu_order = get_order(sizeof(FCLU_NODE_T) * amap->clusters_per_au); + + // XXX: amap->clusters_per_au limitation is 512 (w/ 8 byte list_head) + sdfat_log_msg(sb, KERN_INFO, "page orders for AU nodes : %d " + "(clus_per_au : %d, node_size : %lu)", + amap->fclu_order, + amap->clusters_per_au, + (unsigned long)sizeof(FCLU_NODE_T)); + + if (!amap->fclu_order) + amap->fclu_nodes = (FCLU_NODE_T *)get_zeroed_page(GFP_NOIO); + else + amap->fclu_nodes = vzalloc(PAGE_SIZE << amap->fclu_order); + + amap->fclu_hint = amap->clusters_per_au; + + /* Hot AU list, ignored AU list */ + amap->slist_hot.next = NULL; + amap->slist_hot.head = &amap->slist_hot; + amap->total_fclu_hot = 0; + + amap->slist_ignored.next = NULL; + amap->slist_ignored.head = &amap->slist_ignored; + + /* Strategy related vars. */ + amap->cur_cold.au = NULL; + amap->cur_hot.au = NULL; + amap->n_need_packing = 0; + + + /* Build AMAP info */ + total_used_clusters = 0; // Count # of used clusters + + i_au_root = i_AU_of_CLU(amap, fsi->root_dir); + i_au_hot_from = amap->n_au - (SMART_ALLOC_N_HOT_AU - 1); + + for (i = 0; i < amap->clusters_per_au; i++) + INIT_LIST_HEAD(&amap->fclu_nodes[i].head); + + /* + * Thanks to kzalloc() + * amap->entries[i_au].free_clusters = 0; + * amap->entries[i_au].head.prev = NULL; + * amap->entries[i_au].head.next = NULL; + */ + + /* Parse FAT table */ + for (i_clu = CLUS_BASE; i_clu < fsi->num_clusters; i_clu++) { + u32 clu_data; + AU_INFO_T *au; + + if (fat_ent_get(sb, i_clu, &clu_data)) { + sdfat_msg(sb, KERN_ERR, + "failed to read fat entry(%u)\n", i_clu); + goto free_and_eio; + } + + if (IS_CLUS_FREE(clu_data)) { + au = GET_AU(amap, i_AU_of_CLU(amap, i_clu)); + au->free_clusters++; + } else + total_used_clusters++; + } + + /* Build AU list */ + for (i_au = 0; i_au < amap->n_au; i_au++) { + AU_INFO_T *au = GET_AU(amap, i_au); + + au->idx = i_au; + BUG_ON(au->free_clusters > amap->clusters_per_au); + + if (au->free_clusters == amap->clusters_per_au) + amap->n_clean_au++; + else if (au->free_clusters == 0) + amap->n_full_au++; + + /* If hot, insert to the hot list */ + if (i_au >= i_au_hot_from) { + amap_add_hot_au(amap, au); + amap->total_fclu_hot += au->free_clusters; + } else if (i_au != i_au_root || SMART_ALLOC_N_HOT_AU == 0) { + /* Otherwise, insert to the free cluster hash */ + amap_add_cold_au(amap, au); + } + } + + /* Hot list -> (root) -> (last) -> (last - 1) -> ... */ + if (i_au_root >= 0 && SMART_ALLOC_N_HOT_AU > 0) { + amap_add_hot_au(amap, GET_AU(amap, i_au_root)); + amap->total_fclu_hot += GET_AU(amap, i_au_root)->free_clusters; + } + + fsi->amap = amap; + fsi->used_clusters = total_used_clusters; + + sdfat_msg(sb, KERN_INFO, + "AMAP: Smart allocation enabled (opt : %u / %u / %u)", + amap->option.au_size, amap->option.au_align_factor, + amap->option.packing_ratio); + + /* Debug purpose - check */ + //{ + //u32 used_clusters; + //fat_count_used_clusters(sb, &used_clusters) + //ASSERT(used_clusters == total_used_clusters); + //} + + return 0; + + +free_and_eio: + if (amap) { + if (amap->au_table) { + for (i = 0; i < n_au_table; i++) + free_page((unsigned long)amap->au_table[i]); + kfree(amap->au_table); + } + if (amap->fclu_nodes) { + if (!amap->fclu_order) + free_page((unsigned long)amap->fclu_nodes); + else + vfree(amap->fclu_nodes); + } + kfree(amap); + } + return -EIO; +} + + +/* Free AMAP related structure */ +void amap_destroy(struct super_block *sb) +{ + AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; + int n_au_table; + + if (!amap) + return; + + DMSG("%s\n", __func__); + + n_au_table = (amap->n_au + N_AU_PER_TABLE - 1) / N_AU_PER_TABLE; + + if (amap->au_table) { + int i; + + for (i = 0; i < n_au_table; i++) + free_page((unsigned long)amap->au_table[i]); + + kfree(amap->au_table); + } + if (!amap->fclu_order) + free_page((unsigned long)amap->fclu_nodes); + else + vfree(amap->fclu_nodes); + kfree(amap); + SDFAT_SB(sb)->fsi.amap = NULL; +} + + +/* + * Check status of FS + * and change destination if needed to disable AU-aligned alloc. + * (from ALLOC_COLD_ALIGNED to ALLOC_COLD_SEQ) + */ +static inline int amap_update_dest(AMAP_T *amap, int ori_dest) +{ + FS_INFO_T *fsi = &(SDFAT_SB(amap->sb)->fsi); + int n_partial_au, n_partial_freeclus; + + if (ori_dest != ALLOC_COLD_ALIGNED) + return ori_dest; + + /* # of partial AUs and # of clusters in those AUs */ + n_partial_au = amap->n_au - amap->n_clean_au - amap->n_full_au; + n_partial_freeclus = fsi->num_clusters - fsi->used_clusters - + amap->clusters_per_au * amap->n_clean_au; + + /* Status of AUs : Full / Partial / Clean + * If there are many partial (and badly fragmented) AUs, + * the throughput will decrease extremly. + * + * The follow code will treat those worst cases. + */ + + /* XXX: AMAP heuristics */ + if ((amap->n_clean_au * 50 <= amap->n_au) && + (n_partial_freeclus*2) < (n_partial_au*amap->clusters_per_au)) { + /* If clean AUs are fewer than 2% of n_au (80 AUs per 16GB) + * and fragment ratio is more than 2 (AVG free_clusters=half AU) + * + * disable clean-first allocation + * enable VFAT-like sequential allocation + */ + return ALLOC_COLD_SEQ; + } + + return ori_dest; +} + + +#define PACKING_SOFTLIMIT (amap->option.packing_ratio) +#define PACKING_HARDLIMIT (amap->option.packing_ratio * 4) +/* + * Pick a packing AU if needed. + * Otherwise just return NULL + * + * This function includes some heuristics. + */ +static inline AU_INFO_T *amap_get_packing_au(AMAP_T *amap, int dest, int num_to_wb, int *clu_to_skip) +{ + AU_INFO_T *au = NULL; + + if (dest == ALLOC_COLD_PACKING) { + /* ALLOC_COLD_PACKING: + * Packing-first mode for defrag. + * Optimized to save clean AU + * + * 1) best-fit AU + * 2) Smallest AU (w/ minimum free clusters) + */ + if (num_to_wb >= amap->clusters_per_au) + num_to_wb = num_to_wb % amap->clusters_per_au; + + /* ì´ê±° 주ì„처리하면, AU size ë”± ë§žì„때는 clean, 나머지는 ìž‘ì€ê±°ë¶€í„° */ + if (num_to_wb == 0) + num_to_wb = 1; // Don't use clean AUs + + au = amap_find_cold_au_bestfit(amap, num_to_wb); + if (au && au->free_clusters == amap->clusters_per_au && num_to_wb > 1) { + /* if au is clean then get a new partial one */ + au = amap_find_cold_au_bestfit(amap, 1); + } + + if (au) { + amap->n_need_packing = 0; + amap_remove_cold_au(amap, au); + return au; + } + } + + + /* Heuristic packing: + * This will improve QoS greatly. + * + * Count # of AU_ALIGNED allocation. + * If the number exceeds the specific threshold, + * allocate on a partial AU or generate random I/O. + */ + if ((PACKING_SOFTLIMIT > 0) && + (amap->n_need_packing >= PACKING_SOFTLIMIT) && + (num_to_wb < (int)amap->clusters_per_au)) { + /* Best-fit packing: + * If num_to_wb (expected number to be allocated) is smaller + * than AU_SIZE, find a best-fit AU. + */ + + /* Back margin (heuristics) */ + if (num_to_wb < amap->clusters_per_au / 4) + num_to_wb = amap->clusters_per_au / 4; + + au = amap_find_cold_au_bestfit(amap, num_to_wb); + if (au != NULL) { + amap_remove_cold_au(amap, au); + + MMSG("AMAP: packing (cnt: %d) / softlimit, " + "best-fit (num_to_wb: %d))\n", + amap->n_need_packing, num_to_wb); + + if (au->free_clusters > num_to_wb) { // Best-fit search: if 문 무조건 hit + *clu_to_skip = au->free_clusters - num_to_wb; + /* otherwise don't skip */ + } + amap->n_need_packing = 0; + return au; + } + } + + if ((PACKING_HARDLIMIT) && amap->n_need_packing >= PACKING_HARDLIMIT) { + /* Compulsory SLC flushing: + * If there was no chance to do best-fit packing + * and the # of AU-aligned allocation exceeds HARD threshold, + * then pick a clean AU and generate a compulsory random I/O. + */ + au = amap_pop_cold_au_largest(amap, amap->clusters_per_au); + if (au) { + MMSG("AMAP: packing (cnt: %d) / hard-limit, largest)\n", + amap->n_need_packing); + + if (au->free_clusters >= 96) { + *clu_to_skip = au->free_clusters / 2; + MMSG("AMAP: cluster idx re-position\n"); + } + amap->n_need_packing = 0; + return au; + } + } + + /* Update # of clean AU allocation */ + amap->n_need_packing++; + return NULL; +} + + +/* Pick a target AU: + * This function should be called + * only if there are one or more free clusters in the bdev. + */ +TARGET_AU_T *amap_get_target_au(AMAP_T *amap, int dest, int num_to_wb) +{ + int loop_count = 0; + +retry: + if (++loop_count >= 3) { + /* No space available (or AMAP consistency error) + * This could happen because of the ignored AUs but not likely + * (because the defrag daemon will not work if there is no enough space) + */ + BUG_ON(amap->slist_ignored.next == NULL); + return NULL; + } + + /* Hot clusters (DIR) */ + if (dest == ALLOC_HOT) { + + /* Working hot AU exist? */ + if (amap->cur_hot.au == NULL || amap->cur_hot.au->free_clusters == 0) { + AU_INFO_T *au; + + if (amap->total_fclu_hot == 0) { + /* No more hot AU avaialbe */ + dest = ALLOC_COLD; + + goto retry; + } + + au = amap_find_hot_au_partial(amap); + + BUG_ON(au == NULL); + BUG_ON(au->free_clusters <= 0); + + amap->cur_hot.au = au; + amap->cur_hot.idx = 0; + amap->cur_hot.clu_to_skip = 0; + } + + /* Now allocate on a hot AU */ + return &amap->cur_hot; + } + + /* Cold allocation: + * If amap->cur_cold.au has one or more free cluster(s), + * then just return amap->cur_cold + */ + if ((!amap->cur_cold.au) + || (amap->cur_cold.idx == amap->clusters_per_au) + || (amap->cur_cold.au->free_clusters == 0)) { + + AU_INFO_T *au = NULL; + const AU_INFO_T *old_au = amap->cur_cold.au; + int n_clu_to_skip = 0; + + if (old_au) { + ASSERT(!IS_AU_WORKING(old_au, amap)); + /* must be NOT WORKING AU. + * (only for information gathering) + */ + } + + /* Next target AU is needed: + * There are 3 possible ALLOC options for cold AU + * + * ALLOC_COLD_ALIGNED: Clean AU first, but heuristic packing is ON + * ALLOC_COLD_PACKING: Packing AU first (usually for defrag) + * ALLOC_COLD_SEQ : Sequential AU allocation (VFAT-like) + */ + + /* Experimental: Modify allocation destination if needed (ALIGNED => SEQ) */ + // dest = amap_update_dest(amap, dest); + + if ((dest == ALLOC_COLD_SEQ) && old_au) { + int i_au = old_au->idx + 1; + + while (i_au != old_au->idx) { + au = GET_AU(amap, i_au); + + if ((au->free_clusters > 0) && + !IS_AU_HOT(au, amap) && + !IS_AU_IGNORED(au, amap)) { + MMSG("AMAP: new cold AU(%d) with %d " + "clusters (seq)\n", + au->idx, au->free_clusters); + + amap_remove_cold_au(amap, au); + goto ret_new_cold; + } + i_au++; + if (i_au >= amap->n_au) + i_au = 0; + } + + // no cold AUs are available => Hot allocation + dest = ALLOC_HOT; + goto retry; + } + + + /* + * Check if packing is needed + * (ALLOC_COLD_PACKING is treated by this function) + */ + au = amap_get_packing_au(amap, dest, num_to_wb, &n_clu_to_skip); + if (au) { + MMSG("AMAP: new cold AU(%d) with %d clusters " + "(packing)\n", au->idx, au->free_clusters); + goto ret_new_cold; + } + + /* ALLOC_COLD_ALIGNED */ + /* Check if the adjacent AU is clean */ + if (old_au && ((old_au->idx + 1) < amap->n_au)) { + au = GET_AU(amap, old_au->idx + 1); + if ((au->free_clusters == amap->clusters_per_au) && + !IS_AU_HOT(au, amap) && + !IS_AU_IGNORED(au, amap)) { + MMSG("AMAP: new cold AU(%d) with %d clusters " + "(adjacent)\n", au->idx, au->free_clusters); + amap_remove_cold_au(amap, au); + goto ret_new_cold; + } + } + + /* Clean or largest AU */ + au = amap_pop_cold_au_largest(amap, 0); + if (!au) { + //ASSERT(amap->total_fclu_hot == (fsi->num_clusters - fsi->used_clusters - 2)); + dest = ALLOC_HOT; + goto retry; + } + + MMSG("AMAP: New cold AU (%d) with %d clusters\n", + au->idx, au->free_clusters); + +ret_new_cold: + SET_AU_WORKING(au); + + amap->cur_cold.au = au; + amap->cur_cold.idx = 0; + amap->cur_cold.clu_to_skip = n_clu_to_skip; + } + + return &amap->cur_cold; +} + +/* Put and update target AU */ +void amap_put_target_au(AMAP_T *amap, TARGET_AU_T *cur, int num_allocated) +{ + /* Update AMAP info vars. */ + if (num_allocated > 0 && + (cur->au->free_clusters + num_allocated) == amap->clusters_per_au) { + /* if the target AU was a clean AU before this allocation ... */ + amap->n_clean_au--; + } + if (num_allocated > 0 && + cur->au->free_clusters == 0) + amap->n_full_au++; + + if (IS_AU_HOT(cur->au, amap)) { + /* Hot AU */ + MMSG("AMAP: hot allocation at AU %d\n", cur->au->idx); + amap->total_fclu_hot -= num_allocated; + + /* Intra-AU round-robin */ + if (cur->idx >= amap->clusters_per_au) + cur->idx = 0; + + /* No more space available */ + if (cur->au->free_clusters == 0) + cur->au = NULL; + + } else { + /* non-hot AU */ + ASSERT(IS_AU_WORKING(cur->au, amap)); + + if (cur->idx >= amap->clusters_per_au || cur->au->free_clusters == 0) { + /* It should be inserted back to AU MAP */ + cur->au->shead.head = NULL; // SET_AU_NOT_WORKING + amap_add_cold_au(amap, cur->au); + + // cur->au = NULL; // This value will be used for the next AU selection + cur->idx = amap->clusters_per_au; // AU closing + } + } + +} + + +/* Reposition target->idx for packing (Heuristics): + * Skip (num_to_skip) free clusters in (cur->au) + */ +static inline int amap_skip_cluster(struct super_block *sb, TARGET_AU_T *cur, int num_to_skip) +{ + AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; + u32 clu, read_clu; + MMSG_VAR(int num_to_skip_orig = num_to_skip); + + if (num_to_skip >= cur->au->free_clusters) { + EMSG("AMAP(%s): skip mis-use. amap_566\n", __func__); + return -EIO; + } + + clu = CLU_of_i_AU(amap, cur->au->idx, cur->idx); + while (num_to_skip > 0) { + if (clu >= CLUS_BASE) { + /* Cf. + * If AMAP's integrity is okay, + * we don't need to check if (clu < fsi->num_clusters) + */ + + if (fat_ent_get(sb, clu, &read_clu)) + return -EIO; + + if (IS_CLUS_FREE(read_clu)) + num_to_skip--; + } + + // Move clu->idx + clu++; + (cur->idx)++; + + if (cur->idx >= amap->clusters_per_au) { + /* End of AU (Not supposed) */ + EMSG("AMAP: Skip - End of AU?! (amap_596)\n"); + cur->idx = 0; + return -EIO; + } + } + + MMSG("AMAP: Skip_clusters (%d skipped => %d, among %d free clus)\n", + num_to_skip_orig, cur->idx, cur->au->free_clusters); + + return 0; +} + + +/* AMAP-based allocation function for FAT32 */ +s32 amap_fat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p_chain, int dest) +{ + AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; + TARGET_AU_T *cur = NULL; + AU_INFO_T *target_au = NULL; /* Allocation target AU */ + u32 last_clu = CLUS_EOF, read_clu; + s32 new_clu; // Max. 2G ê°œì˜ clusters + s32 num_allocated = 0, num_allocated_each = 0; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + BUG_ON(!amap); + BUG_ON(IS_CLUS_EOF(fsi->used_clusters)); + + p_chain->dir = CLUS_EOF; + + if ((fsi->used_clusters + num_alloc) > (fsi->num_clusters - CLUS_BASE)) { + /* Reserved count management error + * or called by dir. management function on fully filled disk + */ + num_alloc = fsi->num_clusters - fsi->used_clusters - CLUS_BASE; + + if (unlikely(num_alloc < 0)) { + sdfat_fs_error_ratelimit(sb, + "AMAP(%s): invalid used clusters(t:%u,u:%u)\n", + __func__, fsi->num_clusters, fsi->used_clusters); + return -EIO; + } + + if (!num_alloc) + return 0; + } + + set_sb_dirty(sb); + + // spin_lock(&amap->amap_lock); + +retry_alloc: + /* Allocation strategy implemented */ + cur = amap_get_target_au(amap, dest, fsi->reserved_clusters); + if (unlikely(!cur)) { + // There is no available AU (only ignored-AU are left) + sdfat_msg(sb, KERN_ERR, "AMAP Allocator: no avaialble AU."); + return 0; + } + + /* If there are clusters to skip */ + if (cur->clu_to_skip > 0) { + if (amap_skip_cluster(sb, &amap->cur_cold, cur->clu_to_skip)) + return -EIO; + cur->clu_to_skip = 0; + } + + target_au = cur->au; + + /* + * cur->au : target AU info pointer + * cur->idx : the intra-cluster idx in the AU to start from + */ + BUG_ON(!cur->au); + BUG_ON(!cur->au->free_clusters); + BUG_ON(cur->idx >= amap->clusters_per_au); + + num_allocated_each = 0; + new_clu = CLU_of_i_AU(amap, target_au->idx, cur->idx); + + do { + /* Allocate at the target AU */ + if ((new_clu >= CLUS_BASE) && (new_clu < fsi->num_clusters)) { + if (fat_ent_get(sb, new_clu, &read_clu)) + // spin_unlock(&amap->amap_lock); + return -EIO; // goto err_and_return + + if (IS_CLUS_FREE(read_clu)) { + BUG_ON(GET_AU(amap, i_AU_of_CLU(amap, new_clu)) != target_au); + + /* Free cluster found */ + if (fat_ent_set(sb, new_clu, CLUS_EOF)) + return -EIO; + + num_allocated_each++; + + if (IS_CLUS_EOF(p_chain->dir)) + p_chain->dir = new_clu; + else + if (fat_ent_set(sb, last_clu, new_clu)) + return -EIO; + last_clu = new_clu; + + /* Update au info */ + target_au->free_clusters--; + } + + } + + new_clu++; + (cur->idx)++; + + /* End of the AU */ + if ((cur->idx >= amap->clusters_per_au) || !(target_au->free_clusters)) + break; + } while (num_allocated_each < num_alloc); + + /* Update strategy info */ + amap_put_target_au(amap, cur, num_allocated_each); + + + num_allocated += num_allocated_each; + fsi->used_clusters += num_allocated_each; + num_alloc -= num_allocated_each; + + + if (num_alloc > 0) + goto retry_alloc; + + // spin_unlock(&amap->amap_lock); + return num_allocated; +} + + +/* Free cluster for FAT32 (not implemented yet) */ +s32 amap_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_relse) +{ + return -ENOTSUPP; +} + + +/* + * This is called by fat_free_cluster() + * to update AMAP info. + */ +s32 amap_release_cluster(struct super_block *sb, u32 clu) +{ + AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; + AU_INFO_T *au; + int i_au; + + // spin_lock(&amap->amap_lock); + + /* Update AU info */ + i_au = i_AU_of_CLU(amap, clu); + BUG_ON(i_au >= amap->n_au); + au = GET_AU(amap, i_au); + if (au->free_clusters >= amap->clusters_per_au) { + sdfat_fs_error(sb, "%s, au->free_clusters(%hd) is " + "greater than or equal to amap->clusters_per_au(%hd)" + , __func__, au->free_clusters, amap->clusters_per_au); + return -EIO; + } + + if (IS_AU_HOT(au, amap)) { + MMSG("AMAP: Hot cluster freed\n"); + au->free_clusters++; + amap->total_fclu_hot++; + } else if (!IS_AU_WORKING(au, amap) && !IS_AU_IGNORED(au, amap)) { + /* Ordinary AU - update AU tree */ + // Can be optimized by implementing amap_update_au + amap_remove_cold_au(amap, au); + au->free_clusters++; + amap_add_cold_au(amap, au); + } else + au->free_clusters++; + + + /* Update AMAP info */ + if (au->free_clusters == amap->clusters_per_au) + amap->n_clean_au++; + if (au->free_clusters == 1) + amap->n_full_au--; + + // spin_unlock(&amap->amap_lock); + return 0; +} + + +/* + * Check if the cluster is in a working AU + * The caller should hold sb lock. + * This func. should be used only if smart allocation is on + */ +s32 amap_check_working(struct super_block *sb, u32 clu) +{ + AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; + AU_INFO_T *au; + + BUG_ON(!amap); + au = GET_AU(amap, i_AU_of_CLU(amap, clu)); + return IS_AU_WORKING(au, amap); +} + + +/* + * Return the # of free clusters in that AU + */ +s32 amap_get_freeclus(struct super_block *sb, u32 clu) +{ + AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; + AU_INFO_T *au; + + BUG_ON(!amap); + au = GET_AU(amap, i_AU_of_CLU(amap, clu)); + return (s32)au->free_clusters; +} + + +/* + * Add the AU containing 'clu' to the ignored AU list. + * The AU will not be used by the allocator. + * + * XXX: Ignored counter needed + */ +s32 amap_mark_ignore(struct super_block *sb, u32 clu) +{ + AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; + AU_INFO_T *au; + + BUG_ON(!amap); + au = GET_AU(amap, i_AU_of_CLU(amap, clu)); + + if (IS_AU_HOT(au, amap)) { + /* Doesn't work with hot AUs */ + return -EPERM; + } else if (IS_AU_WORKING(au, amap)) { + return -EBUSY; + } + + //BUG_ON(IS_AU_IGNORED(au, amap) && (GET_IGN_CNT(au) == 0)); + if (IS_AU_IGNORED(au, amap)) + return 0; + + amap_remove_cold_au(amap, au); + amap_insert_to_list(au, &amap->slist_ignored); + + BUG_ON(!IS_AU_IGNORED(au, amap)); + + //INC_IGN_CNT(au); + MMSG("AMAP: Mark ignored AU (%d)\n", au->idx); + return 0; +} + + +/* + * This function could be used only on IGNORED AUs. + * The caller should care whether it's ignored or not before using this func. + */ +s32 amap_unmark_ignore(struct super_block *sb, u32 clu) +{ + AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; + AU_INFO_T *au; + + BUG_ON(!amap); + + au = GET_AU(amap, i_AU_of_CLU(amap, clu)); + + BUG_ON(!IS_AU_IGNORED(au, amap)); + // BUG_ON(GET_IGN_CNT(au) == 0); + + amap_remove_from_list(au, &amap->slist_ignored); + amap_add_cold_au(amap, au); + + BUG_ON(IS_AU_IGNORED(au, amap)); + + //DEC_IGN_CNT(au); + + MMSG("AMAP: Unmark ignored AU (%d)\n", au->idx); + + return 0; +} + +/* + * Unmark all ignored AU + * This will return # of unmarked AUs + */ +s32 amap_unmark_ignore_all(struct super_block *sb) +{ + AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; + struct slist_head *entry; + AU_INFO_T *au; + int n = 0; + + BUG_ON(!amap); + entry = amap->slist_ignored.next; + while (entry) { + au = list_entry(entry, AU_INFO_T, shead); + + BUG_ON(au != GET_AU(amap, au->idx)); + BUG_ON(!IS_AU_IGNORED(au, amap)); + + //CLEAR_IGN_CNT(au); + amap_remove_from_list(au, &amap->slist_ignored); + amap_add_cold_au(amap, au); + + MMSG("AMAP: Unmark ignored AU (%d)\n", au->idx); + n++; + + entry = amap->slist_ignored.next; + } + + BUG_ON(amap->slist_ignored.next != NULL); + MMSG("AMAP: unmark_ignore_all, total %d AUs\n", n); + + return n; +} + +/** + * @fn amap_get_au_stat + * @brief report AUs status depending on mode + * @return positive on success, 0 otherwise + * @param sbi super block info + * @param mode TOTAL, CLEAN and FULL + */ +u32 amap_get_au_stat(struct super_block *sb, s32 mode) +{ + AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; + + if (!amap) + return 0; + + if (mode == VOL_AU_STAT_TOTAL) + return amap->n_au; + else if (mode == VOL_AU_STAT_CLEAN) + return amap->n_clean_au; + else if (mode == VOL_AU_STAT_FULL) + return amap->n_full_au; + + return 0; +} + diff --git a/fs/sdfat/amap_smart.h b/fs/sdfat/amap_smart.h new file mode 100644 index 0000000000000..b628ff448df12 --- /dev/null +++ b/fs/sdfat/amap_smart.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _SDFAT_AMAP_H +#define _SDFAT_AMAP_H + +#include +#include +#include + +/* AMAP Configuration Variable */ +#define SMART_ALLOC_N_HOT_AU (5) + +/* Allocating Destination (for smart allocator): + * moved to sdfat.h + */ +/* + * #define ALLOC_COLD_ALIGNED (1) + * #define ALLOC_COLD_PACKING (2) + * #define ALLOC_COLD_SEQ (4) + */ + +/* Minimum sectors for support AMAP create */ +#define AMAP_MIN_SUPPORT_SECTORS (1048576) + +#define amap_add_hot_au(amap, au) amap_insert_to_list(au, &amap->slist_hot) + +/* singly linked list */ +struct slist_head { + struct slist_head *next; + struct slist_head *head; +}; + +/* AU entry type */ +typedef struct __AU_INFO_T { + uint16_t idx; /* the index of the AU (0, 1, 2, ... ) */ + uint16_t free_clusters; /* # of available cluster */ + union { + struct list_head head; + struct slist_head shead;/* singly linked list head for hot list */ + }; +} AU_INFO_T; + + +/* Allocation Target AU */ +typedef struct __TARGET_AU_T { + AU_INFO_T *au; /* Working AU */ + uint16_t idx; /* Intra-AU cluster index */ + uint16_t clu_to_skip; /* Clusters to skip */ +} TARGET_AU_T; + + +/* AMAP free-clusters-based node */ +typedef struct { + struct list_head head; /* the list of AUs */ +} FCLU_NODE_T; + + +/* AMAP options */ +typedef struct { + unsigned int packing_ratio; /* Tunable packing ratio */ + unsigned int au_size; /* AU size in sectors */ + unsigned int au_align_factor; /* Hidden sectors % au_size */ +} AMAP_OPT_T; + +typedef struct __AMAP_T { + spinlock_t amap_lock; /* obsolete */ + struct super_block *sb; + + int n_au; + int n_clean_au, n_full_au; + int clu_align_bias; + uint16_t clusters_per_au; + AU_INFO_T **au_table; /* An array of AU_INFO entries */ + AMAP_OPT_T option; + + /* Size-based AU management pool (cold) */ + FCLU_NODE_T *fclu_nodes; /* An array of listheads */ + int fclu_order; /* Page order that fclu_nodes needs */ + int fclu_hint; /* maximum # of free clusters in an AU */ + + /* Hot AU list */ + int total_fclu_hot; /* Free clusters in hot list */ + struct slist_head slist_hot; /* Hot AU list */ + + /* Ignored AU list */ + struct slist_head slist_ignored; + + /* Allocator variables (keep 2 AUs at maximum) */ + TARGET_AU_T cur_cold; + TARGET_AU_T cur_hot; + int n_need_packing; +} AMAP_T; + + +/* AU table */ +#define N_AU_PER_TABLE (int)(PAGE_SIZE / sizeof(AU_INFO_T)) +#define GET_AU(amap, i_AU) (amap->au_table[(i_AU) / N_AU_PER_TABLE] + ((i_AU) % N_AU_PER_TABLE)) +//#define MAX_CLU_PER_AU (int)(PAGE_SIZE / sizeof(FCLU_NODE_T)) +#define MAX_CLU_PER_AU (1024) + +/* Cold AU bucket <-> # of freeclusters */ +#define NODE_CLEAN(amap) (&amap->fclu_nodes[amap->clusters_per_au - 1]) +#define NODE(fclu, amap) (&amap->fclu_nodes[fclu - 1]) +#define FREE_CLUSTERS(node, amap) ((int)(node - amap->fclu_nodes) + 1) + +/* AU status */ +#define MAGIC_WORKING ((struct slist_head *)0xFFFF5091) +#define IS_AU_HOT(au, amap) (au->shead.head == &amap->slist_hot) +#define IS_AU_IGNORED(au, amap) (au->shead.head == &amap->slist_ignored) +#define IS_AU_WORKING(au, amap) (au->shead.head == MAGIC_WORKING) +#define SET_AU_WORKING(au) (au->shead.head = MAGIC_WORKING) + +/* AU <-> cluster */ +#define i_AU_of_CLU(amap, clu) ((amap->clu_align_bias + clu) / amap->clusters_per_au) +#define CLU_of_i_AU(amap, i_au, idx) \ + ((uint32_t)(i_au) * (uint32_t)amap->clusters_per_au + (idx) - amap->clu_align_bias) + +/* + * NOTE : AMAP internal functions are moved to core.h + */ + +#endif /* _SDFAT_AMAP_H */ diff --git a/fs/sdfat/api.c b/fs/sdfat/api.c new file mode 100644 index 0000000000000..e1f17cc880aa6 --- /dev/null +++ b/fs/sdfat/api.c @@ -0,0 +1,629 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : sdfat_api.c */ +/* PURPOSE : sdFAT volume lock layer */ +/* */ +/************************************************************************/ + +#include +#include +#include +#include + +#include "version.h" +#include "config.h" + +#include "sdfat.h" +#include "core.h" + +/*----------------------------------------------------------------------*/ +/* Internal structures */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ +static DEFINE_MUTEX(_lock_core); + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Local Function Declarations */ +/*----------------------------------------------------------------------*/ + +/*======================================================================*/ +/* Global Function Definitions */ +/* - All functions for global use have same return value format, */ +/* that is, 0 on success and minus error number on */ +/* various error condition. */ +/*======================================================================*/ + +/*----------------------------------------------------------------------*/ +/* sdFAT Filesystem Init & Exit Functions */ +/*----------------------------------------------------------------------*/ + +s32 fsapi_init(void) +{ + return fscore_init(); +} + +s32 fsapi_shutdown(void) +{ + return fscore_shutdown(); +} + +/*----------------------------------------------------------------------*/ +/* Volume Management Functions */ +/*----------------------------------------------------------------------*/ + +/* mount the file system volume */ +s32 fsapi_mount(struct super_block *sb) +{ + s32 err; + + /* acquire the core lock for file system ccritical section */ + mutex_lock(&_lock_core); + + err = meta_cache_init(sb); + if (err) + goto out; + + err = fscore_mount(sb); +out: + if (err) + meta_cache_shutdown(sb); + + /* release the core lock for file system critical section */ + mutex_unlock(&_lock_core); + + return err; +} +EXPORT_SYMBOL(fsapi_mount); + +/* unmount the file system volume */ +s32 fsapi_umount(struct super_block *sb) +{ + s32 err; + + /* acquire the core lock for file system ccritical section */ + mutex_lock(&_lock_core); + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = fscore_umount(sb); + meta_cache_shutdown(sb); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + + /* release the core lock for file system critical section */ + mutex_unlock(&_lock_core); + + return err; +} +EXPORT_SYMBOL(fsapi_umount); + +/* get the information of a file system volume */ +s32 fsapi_statfs(struct super_block *sb, VOL_INFO_T *info) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + /* check the validity of pointer parameters */ + ASSERT(info); + + if (fsi->used_clusters == (u32) ~0) { + s32 err; + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = fscore_statfs(sb, info); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; + } + + info->FatType = fsi->vol_type; + info->ClusterSize = fsi->cluster_size; + info->NumClusters = fsi->num_clusters - 2; /* clu 0 & 1 */ + info->UsedClusters = fsi->used_clusters + fsi->reserved_clusters; + info->FreeClusters = info->NumClusters - info->UsedClusters; + + return 0; +} +EXPORT_SYMBOL(fsapi_statfs); + +/* synchronize a file system volume */ +s32 fsapi_sync_fs(struct super_block *sb, s32 do_sync) +{ + s32 err; + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = fscore_sync_fs(sb, do_sync); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_sync_fs); + +s32 fsapi_set_vol_flags(struct super_block *sb, u16 new_flag, s32 always_sync) +{ + s32 err; + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = fscore_set_vol_flags(sb, new_flag, always_sync); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_set_vol_flags); + +/*----------------------------------------------------------------------*/ +/* File Operation Functions */ +/*----------------------------------------------------------------------*/ + +/* lookup */ +s32 fsapi_lookup(struct inode *inode, u8 *path, FILE_ID_T *fid) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + /* check the validity of pointer parameters */ + ASSERT(fid && path); + + if (unlikely(!strlen(path))) + return -EINVAL; + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = fscore_lookup(inode, path, fid); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_lookup); + +/* create a file */ +s32 fsapi_create(struct inode *inode, u8 *path, u8 mode, FILE_ID_T *fid) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + /* check the validity of pointer parameters */ + ASSERT(fid && path); + + if (unlikely(!strlen(path))) + return -EINVAL; + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = fscore_create(inode, path, mode, fid); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_create); + +/* read the target string of symlink */ +s32 fsapi_read_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *rcount) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + /* check the validity of pointer parameters */ + ASSERT(fid && buffer); + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = fscore_read_link(inode, fid, buffer, count, rcount); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_read_link); + +/* write the target string of symlink */ +s32 fsapi_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *wcount) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + /* check the validity of pointer parameters */ + ASSERT(fid && buffer); + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = fscore_write_link(inode, fid, buffer, count, wcount); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_write_link); + +/* resize the file length */ +s32 fsapi_truncate(struct inode *inode, u64 old_size, u64 new_size) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + TMSG("%s entered (inode %p size %llu)\n", __func__, inode, new_size); + err = fscore_truncate(inode, old_size, new_size); + TMSG("%s exitted (%d)\n", __func__, err); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_truncate); + +/* rename or move a old file into a new file */ +s32 fsapi_rename(struct inode *old_parent_inode, FILE_ID_T *fid, + struct inode *new_parent_inode, struct dentry *new_dentry) +{ + s32 err; + struct super_block *sb = old_parent_inode->i_sb; + + /* check the validity of pointer parameters */ + ASSERT(fid); + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = fscore_rename(old_parent_inode, fid, new_parent_inode, new_dentry); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_rename); + +/* remove a file */ +s32 fsapi_remove(struct inode *inode, FILE_ID_T *fid) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + /* check the validity of pointer parameters */ + ASSERT(fid); + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = fscore_remove(inode, fid); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_remove); + +/* get the information of a given file */ +s32 fsapi_read_inode(struct inode *inode, DIR_ENTRY_T *info) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + TMSG("%s entered (inode %p info %p\n", __func__, inode, info); + err = fscore_read_inode(inode, info); + TMSG("%s exited (err:%d)\n", __func__, err); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_read_inode); + +/* set the information of a given file */ +s32 fsapi_write_inode(struct inode *inode, DIR_ENTRY_T *info, int sync) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + TMSG("%s entered (inode %p info %p sync:%d\n", + __func__, inode, info, sync); + err = fscore_write_inode(inode, info, sync); + TMSG("%s exited (err:%d)\n", __func__, err); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_write_inode); + +/* return the cluster number in the given cluster offset */ +s32 fsapi_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + /* check the validity of pointer parameters */ + ASSERT(clu); + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + TMSG("%s entered (inode:%p clus:%08x dest:%d\n", + __func__, inode, *clu, dest); + err = fscore_map_clus(inode, clu_offset, clu, dest); + TMSG("%s exited (clu:%08x err:%d)\n", __func__, *clu, err); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_map_clus); + +/* reserve a cluster */ +s32 fsapi_reserve_clus(struct inode *inode) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + TMSG("%s entered (inode:%p)\n", __func__, inode); + err = fscore_reserve_clus(inode); + TMSG("%s exited (err:%d)\n", __func__, err); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_reserve_clus); + +/*----------------------------------------------------------------------*/ +/* Directory Operation Functions */ +/*----------------------------------------------------------------------*/ + +/* create(make) a directory */ +s32 fsapi_mkdir(struct inode *inode, u8 *path, FILE_ID_T *fid) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + /* check the validity of pointer parameters */ + ASSERT(fid && path); + + if (unlikely(!strlen(path))) + return -EINVAL; + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = fscore_mkdir(inode, path, fid); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_mkdir); + +/* read a directory entry from the opened directory */ +s32 fsapi_readdir(struct inode *inode, DIR_ENTRY_T *dir_entry) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + /* check the validity of pointer parameters */ + ASSERT(dir_entry); + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = fscore_readdir(inode, dir_entry); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_readdir); + +/* remove a directory */ +s32 fsapi_rmdir(struct inode *inode, FILE_ID_T *fid) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + /* check the validity of pointer parameters */ + ASSERT(fid); + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = fscore_rmdir(inode, fid); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_rmdir); + +/* unlink a file. + * that is, remove an entry from a directory. BUT don't truncate + */ +s32 fsapi_unlink(struct inode *inode, FILE_ID_T *fid) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + /* check the validity of pointer parameters */ + ASSERT(fid); + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = fscore_unlink(inode, fid); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_unlink); + +/* reflect the internal dirty flags to VFS bh dirty flags */ +s32 fsapi_cache_flush(struct super_block *sb, int do_sync) +{ + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + fcache_flush(sb, do_sync); + dcache_flush(sb, do_sync); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return 0; +} +EXPORT_SYMBOL(fsapi_cache_flush); + +/* release FAT & buf cache */ +s32 fsapi_cache_release(struct super_block *sb) +{ +#ifdef CONFIG_SDFAT_DEBUG + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + + fcache_release_all(sb); + dcache_release_all(sb); + + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); +#endif /* CONFIG_SDFAT_DEBUG */ + return 0; +} +EXPORT_SYMBOL(fsapi_cache_release); + +u32 fsapi_get_au_stat(struct super_block *sb, s32 mode) +{ + /* volume lock is not required */ + return fscore_get_au_stat(sb, mode); +} +EXPORT_SYMBOL(fsapi_get_au_stat); + +/* clear extent cache */ +void fsapi_invalidate_extent(struct inode *inode) +{ + /* Volume lock is not required, + * because it is only called by evict_inode. + * If any other function can call it, + * you should check whether volume lock is needed or not. + */ + extent_cache_inval_inode(inode); +} +EXPORT_SYMBOL(fsapi_invalidate_extent); + + + +#ifdef CONFIG_SDFAT_DFR +/*----------------------------------------------------------------------*/ +/* Defragmentation related */ +/*----------------------------------------------------------------------*/ +s32 fsapi_dfr_get_info(struct super_block *sb, void *arg) +{ + /* volume lock is not required */ + return defrag_get_info(sb, (struct defrag_info_arg *)arg); +} +EXPORT_SYMBOL(fsapi_dfr_get_info); + +s32 fsapi_dfr_scan_dir(struct super_block *sb, void *args) +{ + s32 err; + + /* check the validity of pointer parameters */ + ASSERT(args); + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = defrag_scan_dir(sb, (struct defrag_trav_arg *)args); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_dfr_scan_dir); + +s32 fsapi_dfr_validate_clus(struct inode *inode, void *chunk, int skip_prev) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = defrag_validate_cluster(inode, + (struct defrag_chunk_info *)chunk, skip_prev); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_dfr_validate_clus); + +s32 fsapi_dfr_reserve_clus(struct super_block *sb, s32 nr_clus) +{ + s32 err; + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = defrag_reserve_clusters(sb, nr_clus); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + return err; +} +EXPORT_SYMBOL(fsapi_dfr_reserve_clus); + +s32 fsapi_dfr_mark_ignore(struct super_block *sb, unsigned int clus) +{ + /* volume lock is not required */ + return defrag_mark_ignore(sb, clus); +} +EXPORT_SYMBOL(fsapi_dfr_mark_ignore); + +void fsapi_dfr_unmark_ignore_all(struct super_block *sb) +{ + /* volume lock is not required */ + defrag_unmark_ignore_all(sb); +} +EXPORT_SYMBOL(fsapi_dfr_unmark_ignore_all); + +s32 fsapi_dfr_map_clus(struct inode *inode, u32 clu_offset, u32 *clu) +{ + s32 err; + struct super_block *sb = inode->i_sb; + + /* check the validity of pointer parameters */ + ASSERT(clu); + + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + err = defrag_map_cluster(inode, clu_offset, clu); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); + + return err; +} +EXPORT_SYMBOL(fsapi_dfr_map_clus); + +void fsapi_dfr_writepage_endio(struct page *page) +{ + /* volume lock is not required */ + defrag_writepage_end_io(page); +} +EXPORT_SYMBOL(fsapi_dfr_writepage_endio); + +void fsapi_dfr_update_fat_prev(struct super_block *sb, int force) +{ + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + defrag_update_fat_prev(sb, force); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); +} +EXPORT_SYMBOL(fsapi_dfr_update_fat_prev); + +void fsapi_dfr_update_fat_next(struct super_block *sb) +{ + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + defrag_update_fat_next(sb); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); +} +EXPORT_SYMBOL(fsapi_dfr_update_fat_next); + +void fsapi_dfr_check_discard(struct super_block *sb) +{ + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + defrag_check_discard(sb); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); +} +EXPORT_SYMBOL(fsapi_dfr_check_discard); + +void fsapi_dfr_free_clus(struct super_block *sb, u32 clus) +{ + mutex_lock(&(SDFAT_SB(sb)->s_vlock)); + defrag_free_cluster(sb, clus); + mutex_unlock(&(SDFAT_SB(sb)->s_vlock)); +} +EXPORT_SYMBOL(fsapi_dfr_free_clus); + +s32 fsapi_dfr_check_dfr_required(struct super_block *sb, int *totalau, int *cleanau, int *fullau) +{ + /* volume lock is not required */ + return defrag_check_defrag_required(sb, totalau, cleanau, fullau); +} +EXPORT_SYMBOL(fsapi_dfr_check_dfr_required); + +s32 fsapi_dfr_check_dfr_on(struct inode *inode, loff_t start, loff_t end, s32 cancel, const char *caller) +{ + /* volume lock is not required */ + return defrag_check_defrag_on(inode, start, end, cancel, caller); +} +EXPORT_SYMBOL(fsapi_dfr_check_dfr_on); + + + +#ifdef CONFIG_SDFAT_DFR_DEBUG +void fsapi_dfr_spo_test(struct super_block *sb, int flag, const char *caller) +{ + /* volume lock is not required */ + defrag_spo_test(sb, flag, caller); +} +EXPORT_SYMBOL(fsapi_dfr_spo_test); +#endif + + +#endif /* CONFIG_SDFAT_DFR */ + +/* end of sdfat_api.c */ diff --git a/fs/sdfat/api.h b/fs/sdfat/api.h new file mode 100644 index 0000000000000..fb0bf7af5e282 --- /dev/null +++ b/fs/sdfat/api.h @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _SDFAT_API_H +#define _SDFAT_API_H + +#include "config.h" +#include "sdfat_fs.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/*----------------------------------------------------------------------*/ +/* Configure Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ +/* cache size (in number of sectors) */ +/* (should be an exponential value of 2) */ +#define FAT_CACHE_SIZE 128 +#define FAT_CACHE_HASH_SIZE 64 +#define BUF_CACHE_SIZE 256 +#define BUF_CACHE_HASH_SIZE 64 + +/* Read-ahead related */ +/* First config vars. should be pow of 2 */ +#define FCACHE_MAX_RA_SIZE (PAGE_SIZE) +#define DCACHE_MAX_RA_SIZE (128*1024) + +/*----------------------------------------------------------------------*/ +/* Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ +/* type values */ +#define TYPE_UNUSED 0x0000 +#define TYPE_DELETED 0x0001 +#define TYPE_INVALID 0x0002 +#define TYPE_CRITICAL_PRI 0x0100 +#define TYPE_BITMAP 0x0101 +#define TYPE_UPCASE 0x0102 +#define TYPE_VOLUME 0x0103 +#define TYPE_DIR 0x0104 +#define TYPE_FILE 0x011F +#define TYPE_SYMLINK 0x015F +#define TYPE_CRITICAL_SEC 0x0200 +#define TYPE_STREAM 0x0201 +#define TYPE_EXTEND 0x0202 +#define TYPE_ACL 0x0203 +#define TYPE_BENIGN_PRI 0x0400 +#define TYPE_GUID 0x0401 +#define TYPE_PADDING 0x0402 +#define TYPE_ACLTAB 0x0403 +#define TYPE_BENIGN_SEC 0x0800 +#define TYPE_ALL 0x0FFF + +/* eio values */ +#define SDFAT_EIO_NONE (0x00000000) +#define SDFAT_EIO_READ (0x00000001) +#define SDFAT_EIO_WRITE (0x00000002) +#define SDFAT_EIO_BDI (0x00000004) + +/* modes for volume allocation unit status */ +#define VOL_AU_STAT_TOTAL (0) +#define VOL_AU_STAT_CLEAN (1) +#define VOL_AU_STAT_FULL (2) + +/*----------------------------------------------------------------------*/ +/* NLS Type Definitions */ +/*----------------------------------------------------------------------*/ + +/* DOS name structure */ +typedef struct { + u8 name[DOS_NAME_LENGTH]; + u8 name_case; +} DOS_NAME_T; + +/* unicode name structure */ +typedef struct { + u16 name[MAX_NAME_LENGTH+3]; /* +3 for null and for converting */ + u16 name_hash; + u8 name_len; +} UNI_NAME_T; + +/*----------------------------------------------------------------------*/ +/* Type Definitions */ +/*----------------------------------------------------------------------*/ +/* should be merged it to DATE_TIME_T */ +typedef struct { + u16 sec; /* 0 ~ 59 */ + u16 min; /* 0 ~ 59 */ + u16 hour; /* 0 ~ 23 */ + u16 day; /* 1 ~ 31 */ + u16 mon; /* 1 ~ 12 */ + u16 year; /* 0 ~ 127 (since 1980) */ +} TIMESTAMP_T; + + +typedef struct { + u16 Year; + u16 Month; + u16 Day; + u16 Hour; + u16 Minute; + u16 Second; + u16 MilliSecond; +} DATE_TIME_T; + +typedef struct { + u32 Offset; // start sector number of the partition + u32 Size; // in sectors +} PART_INFO_T; + +typedef struct { + u32 SecSize; // sector size in bytes + u32 DevSize; // block device size in sectors +} DEV_INFO_T; + +typedef struct { + u32 FatType; + u32 ClusterSize; + u32 NumClusters; + u32 FreeClusters; + u32 UsedClusters; +} VOL_INFO_T; + +/* directory structure */ +typedef struct { + u32 dir; + s32 size; + u8 flags; +} CHAIN_T; + +/* hint structure */ +typedef struct { + u32 clu; + union { + s32 off; // cluster offset + s32 eidx; // entry index + }; +} HINT_T; + +typedef struct { + spinlock_t cache_lru_lock; + struct list_head cache_lru; + s32 nr_caches; + u32 cache_valid_id; // for avoiding the race between alloc and free +} EXTENT_T; + +/* first empty entry hint information */ +typedef struct { + s32 eidx; // entry index of a directory + s32 count; // count of continuous empty entry + CHAIN_T cur; // the cluster that first empty slot exists in +} HINT_FEMP_T; + +/* file id structure */ +typedef struct { + CHAIN_T dir; + s32 entry; + u32 type; + u32 attr; + u32 start_clu; + u64 size; + u8 flags; + u8 reserved[3]; // padding + u32 version; // the copy of low 32bit of i_version to check the validation of hint_stat + s64 rwoffset; // file offset or dentry index for readdir + EXTENT_T extent; // extent cache for a file + HINT_T hint_bmap; // hint for cluster last accessed + HINT_T hint_stat; // hint for entry index we try to lookup next time + HINT_FEMP_T hint_femp; // hint for first empty entry +} FILE_ID_T; + +typedef struct { + s8 *lfn; + s8 *sfn; + s32 lfnbuf_len; //usally MAX_UNINAME_BUF_SIZE + s32 sfnbuf_len; //usally MAX_DOSNAME_BUF_SIZE, used only for vfat, not for exfat +} DENTRY_NAMEBUF_T; + +typedef struct { + u32 Attr; + u64 Size; + u32 NumSubdirs; + DATE_TIME_T CreateTimestamp; + DATE_TIME_T ModifyTimestamp; + DATE_TIME_T AccessTimestamp; + DENTRY_NAMEBUF_T NameBuf; +} DIR_ENTRY_T; + +/* cache information */ +typedef struct __cache_entry { + struct __cache_entry *next; + struct __cache_entry *prev; + struct { + struct __cache_entry *next; + struct __cache_entry *prev; + } hash; + u32 sec; + u32 flag; + struct buffer_head *bh; +} cache_ent_t; + +/*----------------------------------------------------------------------*/ +/* Type Definitions : Wrapper & In-Core */ +/*----------------------------------------------------------------------*/ +typedef struct __FATENT_OPS_T { + s32 (*ent_get)(struct super_block *sb, u32 loc, u32 *content); + s32 (*ent_set)(struct super_block *sb, u32 loc, u32 content); +} FATENT_OPS_T; + +typedef struct { + s32 (*alloc_cluster)(struct super_block *, s32, CHAIN_T *, int); + s32 (*free_cluster)(struct super_block *, CHAIN_T *, s32); + s32 (*count_used_clusters)(struct super_block *, u32 *); + s32 (*init_dir_entry)(struct super_block *, CHAIN_T *, s32, u32, u32, u64); + s32 (*init_ext_entry)(struct super_block *, CHAIN_T *, s32, s32, UNI_NAME_T *, DOS_NAME_T *); + s32 (*find_dir_entry)(struct super_block *, FILE_ID_T *, CHAIN_T *, UNI_NAME_T *, s32, DOS_NAME_T *, u32); + s32 (*delete_dir_entry)(struct super_block *, CHAIN_T *, s32, s32, s32); + void (*get_uniname_from_ext_entry)(struct super_block *, CHAIN_T *, s32, u16 *); + s32 (*count_ext_entries)(struct super_block *, CHAIN_T *, s32, DENTRY_T *); + s32 (*calc_num_entries)(UNI_NAME_T *); + s32 (*check_max_dentries)(FILE_ID_T *); + u32 (*get_entry_type)(DENTRY_T *); + void (*set_entry_type)(DENTRY_T *, u32); + u32 (*get_entry_attr)(DENTRY_T *); + void (*set_entry_attr)(DENTRY_T *, u32); + u8 (*get_entry_flag)(DENTRY_T *); + void (*set_entry_flag)(DENTRY_T *, u8); + u32 (*get_entry_clu0)(DENTRY_T *); + void (*set_entry_clu0)(DENTRY_T *, u32); + u64 (*get_entry_size)(DENTRY_T *); + void (*set_entry_size)(DENTRY_T *, u64); + void (*get_entry_time)(DENTRY_T *, TIMESTAMP_T *, u8); + void (*set_entry_time)(DENTRY_T *, TIMESTAMP_T *, u8); + u32 (*get_au_stat)(struct super_block *, s32); +} FS_FUNC_T; + +typedef struct __FS_INFO_T { + s32 bd_opened; // opened or not + u32 vol_type; // volume FAT type + u32 vol_id; // volume serial number + u32 num_sectors; // num of sectors in volume + u32 num_clusters; // num of clusters in volume + u32 cluster_size; // cluster size in bytes + u32 cluster_size_bits; + u32 sect_per_clus; // cluster size in sectors + u32 sect_per_clus_bits; + u32 FAT1_start_sector; // FAT1 start sector + u32 FAT2_start_sector; // FAT2 start sector + u32 root_start_sector; // root dir start sector + u32 data_start_sector; // data area start sector + u32 num_FAT_sectors; // num of FAT sectors + u32 root_dir; // root dir cluster + u32 dentries_in_root; // num of dentries in root dir + u32 dentries_per_clu; // num of dentries per cluster + u32 vol_flag; // volume dirty flag + struct buffer_head *pbr_bh; // buffer_head of PBR sector + + u32 map_clu; // allocation bitmap start cluster + u32 map_sectors; // num of allocation bitmap sectors + struct buffer_head **vol_amap; // allocation bitmap + + u16 **vol_utbl; // upcase table + + u32 clu_srch_ptr; // cluster search pointer + u32 used_clusters; // number of used clusters + + u32 prev_eio; // block device operation error flag + + FS_FUNC_T *fs_func; + FATENT_OPS_T *fatent_ops; + + s32 reserved_clusters; // # of reserved clusters (DA) + void *amap; // AU Allocation Map + + /* fat cache */ + struct { + cache_ent_t pool[FAT_CACHE_SIZE]; + cache_ent_t lru_list; + cache_ent_t hash_list[FAT_CACHE_HASH_SIZE]; + } fcache; + + /* meta cache */ + struct { + cache_ent_t pool[BUF_CACHE_SIZE]; + cache_ent_t lru_list; + cache_ent_t keep_list; // CACHEs in this list will not be kicked by normal lru operations + cache_ent_t hash_list[BUF_CACHE_HASH_SIZE]; + } dcache; +} FS_INFO_T; + +/*======================================================================*/ +/* */ +/* API FUNCTION DECLARATIONS */ +/* (CHANGE THIS PART IF REQUIRED) */ +/* */ +/*======================================================================*/ + +/*----------------------------------------------------------------------*/ +/* External Function Declarations */ +/*----------------------------------------------------------------------*/ + +/* file system initialization & shutdown functions */ +s32 fsapi_init(void); +s32 fsapi_shutdown(void); + +/* volume management functions */ +s32 fsapi_mount(struct super_block *sb); +s32 fsapi_umount(struct super_block *sb); +s32 fsapi_statfs(struct super_block *sb, VOL_INFO_T *info); +s32 fsapi_sync_fs(struct super_block *sb, s32 do_sync); +s32 fsapi_set_vol_flags(struct super_block *sb, u16 new_flag, s32 always_sync); + +/* file management functions */ +s32 fsapi_lookup(struct inode *inode, u8 *path, FILE_ID_T *fid); +s32 fsapi_create(struct inode *inode, u8 *path, u8 mode, FILE_ID_T *fid); +s32 fsapi_read_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *rcount); +s32 fsapi_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *wcount); +s32 fsapi_remove(struct inode *inode, FILE_ID_T *fid); /* unlink and truncate */ +s32 fsapi_truncate(struct inode *inode, u64 old_size, u64 new_size); +s32 fsapi_rename(struct inode *old_parent_inode, FILE_ID_T *fid, + struct inode *new_parent_inode, struct dentry *new_dentry); +s32 fsapi_unlink(struct inode *inode, FILE_ID_T *fid); +s32 fsapi_read_inode(struct inode *inode, DIR_ENTRY_T *info); +s32 fsapi_write_inode(struct inode *inode, DIR_ENTRY_T *info, int sync); +s32 fsapi_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest); +s32 fsapi_reserve_clus(struct inode *inode); + +/* directory management functions */ +s32 fsapi_mkdir(struct inode *inode, u8 *path, FILE_ID_T *fid); +s32 fsapi_readdir(struct inode *inode, DIR_ENTRY_T *dir_entry); +s32 fsapi_rmdir(struct inode *inode, FILE_ID_T *fid); + +/* FAT & buf cache functions */ +s32 fsapi_cache_flush(struct super_block *sb, int do_sync); +s32 fsapi_cache_release(struct super_block *sb); + +/* extra info functions */ +u32 fsapi_get_au_stat(struct super_block *sb, s32 mode); + +/* extent cache functions */ +void fsapi_invalidate_extent(struct inode *inode); + +#ifdef CONFIG_SDFAT_DFR +/*----------------------------------------------------------------------*/ +/* Defragmentation related */ +/*----------------------------------------------------------------------*/ + +s32 fsapi_dfr_get_info(struct super_block *sb, void *arg); + +s32 fsapi_dfr_scan_dir(struct super_block *sb, void *args); + +s32 fsapi_dfr_validate_clus(struct inode *inode, void *chunk, int skip_prev); +s32 fsapi_dfr_reserve_clus(struct super_block *sb, s32 nr_clus); +s32 fsapi_dfr_mark_ignore(struct super_block *sb, unsigned int clus); +void fsapi_dfr_unmark_ignore_all(struct super_block *sb); + +s32 fsapi_dfr_map_clus(struct inode *inode, u32 clu_offset, u32 *clu); +void fsapi_dfr_writepage_endio(struct page *page); + +void fsapi_dfr_update_fat_prev(struct super_block *sb, int force); +void fsapi_dfr_update_fat_next(struct super_block *sb); +void fsapi_dfr_check_discard(struct super_block *sb); +void fsapi_dfr_free_clus(struct super_block *sb, u32 clus); + +s32 fsapi_dfr_check_dfr_required(struct super_block *sb, int *totalau, int *cleanau, int *fullau); +s32 fsapi_dfr_check_dfr_on(struct inode *inode, loff_t start, loff_t end, s32 cancel, const char *caller); + + +#ifdef CONFIG_SDFAT_DFR_DEBUG +void fsapi_dfr_spo_test(struct super_block *sb, int flag, const char *caller); +#endif /* CONFIG_SDFAT_DFR_DEBUG */ + +#endif /* CONFIG_SDFAT_DFR */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _SDFAT_API_H */ + +/* end of api.h */ diff --git a/fs/sdfat/blkdev.c b/fs/sdfat/blkdev.c new file mode 100644 index 0000000000000..d0f38db75e273 --- /dev/null +++ b/fs/sdfat/blkdev.c @@ -0,0 +1,416 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : blkdev.c */ +/* PURPOSE : sdFAT Block Device Driver Glue Layer */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/************************************************************************/ + +#include +#include +#include + +#include "sdfat.h" + +/*----------------------------------------------------------------------*/ +/* Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY */ +/************************************************************************/ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) + /* EMPTY */ +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) */ +static struct backing_dev_info *inode_to_bdi(struct inode *bd_inode) +{ + return bd_inode->i_mapping->backing_dev_info; +} +#endif + +/*======================================================================*/ +/* Function Definitions */ +/*======================================================================*/ +s32 bdev_open_dev(struct super_block *sb) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (fsi->bd_opened) + return 0; + + fsi->bd_opened = true; + return 0; +} + +s32 bdev_close_dev(struct super_block *sb) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + fsi->bd_opened = false; + return 0; +} + +static inline s32 block_device_ejected(struct super_block *sb) +{ + struct inode *bd_inode = sb->s_bdev->bd_inode; + struct backing_dev_info *bdi = inode_to_bdi(bd_inode); + + return (bdi->dev == NULL); +} + +s32 bdev_check_bdi_valid(struct super_block *sb) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (block_device_ejected(sb)) { + if (!(fsi->prev_eio & SDFAT_EIO_BDI)) { + fsi->prev_eio |= SDFAT_EIO_BDI; + sdfat_log_msg(sb, KERN_ERR, "%s: block device is " + "eliminated.(bdi:%p)", __func__, sb->s_bdi); + sdfat_debug_warn_on(1); + } + return -ENXIO; + } + + return 0; +} + + +/* Make a readahead request */ +s32 bdev_readahead(struct super_block *sb, u32 secno, u32 num_secs) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + u32 sects_per_page = (PAGE_SIZE >> sb->s_blocksize_bits); + struct blk_plug plug; + u32 i; + + if (!fsi->bd_opened) + return -EIO; + + blk_start_plug(&plug); + for (i = 0; i < num_secs; i++) { + if (i && !(i & (sects_per_page - 1))) + blk_flush_plug(current); + sb_breadahead(sb, secno + i); + } + blk_finish_plug(&plug); + + return 0; +} + +s32 bdev_mread(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 num_secs, s32 read) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + u8 blksize_bits = sb->s_blocksize_bits; +#ifdef CONFIG_SDFAT_DBG_IOCTL + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & SDFAT_DEBUGFLAGS_ERROR_RW) + return -EIO; +#endif /* CONFIG_SDFAT_DBG_IOCTL */ + + if (!fsi->bd_opened) + return -EIO; + + brelse(*bh); + + if (read) + *bh = __bread(sb->s_bdev, secno, num_secs << blksize_bits); + else + *bh = __getblk(sb->s_bdev, secno, num_secs << blksize_bits); + + /* read successfully */ + if (*bh) + return 0; + + /* + * patch 1.2.4 : reset ONCE warning message per volume. + */ + if (!(fsi->prev_eio & SDFAT_EIO_READ)) { + fsi->prev_eio |= SDFAT_EIO_READ; + sdfat_log_msg(sb, KERN_ERR, "%s: No bh. I/O error.", __func__); + sdfat_debug_warn_on(1); + } + + return -EIO; +} + +s32 bdev_mwrite(struct super_block *sb, u32 secno, struct buffer_head *bh, u32 num_secs, s32 sync) +{ + s32 count; + struct buffer_head *bh2; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); +#ifdef CONFIG_SDFAT_DBG_IOCTL + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & SDFAT_DEBUGFLAGS_ERROR_RW) + return -EIO; +#endif /* CONFIG_SDFAT_DBG_IOCTL */ + + if (!fsi->bd_opened) + return -EIO; + + if (secno == bh->b_blocknr) { + set_buffer_uptodate(bh); + mark_buffer_dirty(bh); + if (sync && (sync_dirty_buffer(bh) != 0)) + return -EIO; + } else { + count = num_secs << sb->s_blocksize_bits; + + bh2 = __getblk(sb->s_bdev, secno, count); + + if (!bh2) + goto no_bh; + + lock_buffer(bh2); + memcpy(bh2->b_data, bh->b_data, count); + set_buffer_uptodate(bh2); + mark_buffer_dirty(bh2); + unlock_buffer(bh2); + if (sync && (sync_dirty_buffer(bh2) != 0)) { + __brelse(bh2); + goto no_bh; + } + __brelse(bh2); + } + return 0; +no_bh: + /* + * patch 1.2.4 : reset ONCE warning message per volume. + */ + if (!(fsi->prev_eio & SDFAT_EIO_WRITE)) { + fsi->prev_eio |= SDFAT_EIO_WRITE; + sdfat_log_msg(sb, KERN_ERR, "%s: No bh. I/O error.", __func__); + sdfat_debug_warn_on(1); + } + + return -EIO; +} + +s32 bdev_sync_all(struct super_block *sb) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); +#ifdef CONFIG_SDFAT_DBG_IOCTL + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & SDFAT_DEBUGFLAGS_ERROR_RW) + return -EIO; +#endif /* CONFIG_SDFAT_DBG_IOCTL */ + + if (!fsi->bd_opened) + return -EIO; + + return sync_blockdev(sb->s_bdev); +} + +/* + * Sector Read/Write Functions + */ +s32 read_sect(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 read) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + BUG_ON(!bh); + if ((sec >= fsi->num_sectors) && (fsi->num_sectors > 0)) { + sdfat_fs_error_ratelimit(sb, + "%s: out of range (sect:%u)", __func__, sec); + return -EIO; + } + + if (bdev_mread(sb, sec, bh, 1, read)) { + sdfat_fs_error_ratelimit(sb, + "%s: I/O error (sect:%u)", __func__, sec); + return -EIO; + } + + return 0; +} + +s32 write_sect(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 sync) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + BUG_ON(!bh); + if ((sec >= fsi->num_sectors) && (fsi->num_sectors > 0)) { + sdfat_fs_error_ratelimit(sb, + "%s: out of range (sect:%u)", __func__, sec); + return -EIO; + } + + if (bdev_mwrite(sb, sec, bh, 1, sync)) { + sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%u)", + __func__, sec); + return -EIO; + } + + return 0; +} + +s32 read_msect(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 num_secs, s32 read) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + BUG_ON(!bh); + if (((sec+num_secs) > fsi->num_sectors) && (fsi->num_sectors > 0)) { + sdfat_fs_error_ratelimit(sb, "%s: out of range(sect:%u len:%d)", + __func__, sec, num_secs); + return -EIO; + } + + if (bdev_mread(sb, sec, bh, num_secs, read)) { + sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%u len:%d)", + __func__, sec, num_secs); + return -EIO; + } + + return 0; +} + +s32 write_msect(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 num_secs, s32 sync) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + BUG_ON(!bh); + if (((sec+num_secs) > fsi->num_sectors) && (fsi->num_sectors > 0)) { + sdfat_fs_error_ratelimit(sb, "%s: out of range(sect:%u len:%d)", + __func__, sec, num_secs); + return -EIO; + } + + + if (bdev_mwrite(sb, sec, bh, num_secs, sync)) { + sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%u len:%d)", + __func__, sec, num_secs); + return -EIO; + } + + return 0; +} + +static inline void __blkdev_write_bhs(struct buffer_head **bhs, s32 nr_bhs) +{ + s32 i; + + for (i = 0; i < nr_bhs; i++) + write_dirty_buffer(bhs[i], WRITE); +} + +static inline s32 __blkdev_sync_bhs(struct buffer_head **bhs, s32 nr_bhs) +{ + s32 i, err = 0; + + for (i = 0; i < nr_bhs; i++) { + wait_on_buffer(bhs[i]); + if (!err && !buffer_uptodate(bhs[i])) + err = -EIO; + } + return err; +} + +static inline s32 __buffer_zeroed(struct super_block *sb, u32 blknr, s32 num_secs) +{ + struct buffer_head *bhs[MAX_BUF_PER_PAGE]; + s32 nr_bhs = MAX_BUF_PER_PAGE; + u32 last_blknr = blknr + num_secs; + s32 err, i, n; + struct blk_plug plug; + + /* Zeroing the unused blocks on this cluster */ + n = 0; + blk_start_plug(&plug); + while (blknr < last_blknr) { + bhs[n] = sb_getblk(sb, blknr); + if (!bhs[n]) { + err = -ENOMEM; + blk_finish_plug(&plug); + goto error; + } + memset(bhs[n]->b_data, 0, sb->s_blocksize); + set_buffer_uptodate(bhs[n]); + mark_buffer_dirty(bhs[n]); + + n++; + blknr++; + + if (blknr == last_blknr) + break; + + if (n == nr_bhs) { + __blkdev_write_bhs(bhs, n); + + for (i = 0; i < n; i++) + brelse(bhs[i]); + n = 0; + } + } + __blkdev_write_bhs(bhs, n); + blk_finish_plug(&plug); + + err = __blkdev_sync_bhs(bhs, n); + if (err) + goto error; + + for (i = 0; i < n; i++) + brelse(bhs[i]); + + return 0; + +error: + EMSG("%s: failed zeroed sect %u\n", __func__, blknr); + for (i = 0; i < n; i++) + bforget(bhs[i]); + + return err; +} + +s32 write_msect_zero(struct super_block *sb, u32 sec, s32 num_secs) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (((sec+num_secs) > fsi->num_sectors) && (fsi->num_sectors > 0)) { + sdfat_fs_error_ratelimit(sb, "%s: out of range(sect:%u len:%d)", + __func__, sec, num_secs); + return -EIO; + } + + /* Just return -EAGAIN if it is failed */ + if (__buffer_zeroed(sb, sec, num_secs)) + return -EAGAIN; + + return 0; +} /* end of write_msect_zero */ + +/* end of blkdev.c */ diff --git a/fs/sdfat/cache.c b/fs/sdfat/cache.c new file mode 100644 index 0000000000000..33901fa0ae663 --- /dev/null +++ b/fs/sdfat/cache.c @@ -0,0 +1,842 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : cache.c */ +/* PURPOSE : sdFAT Cache Manager */ +/* (FAT Cache & Buffer Cache) */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/* */ +/************************************************************************/ + +#include /* for mark_page_accessed() */ +#include + +#include "sdfat.h" +#include "core.h" + +#define DEBUG_HASH_LIST +#define DEBUG_HASH_PREV (0xAAAA5555) +#define DEBUG_HASH_NEXT (0x5555AAAA) + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ +/* All buffer structures are protected w/ fsi->v_sem */ + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ +#define LOCKBIT (0x01) +#define DIRTYBIT (0x02) +#define KEEPBIT (0x04) + +/*----------------------------------------------------------------------*/ +/* Cache handling function declarations */ +/*----------------------------------------------------------------------*/ +static cache_ent_t *__fcache_find(struct super_block *sb, u32 sec); +static cache_ent_t *__fcache_get(struct super_block *sb, u32 sec); +static void __fcache_insert_hash(struct super_block *sb, cache_ent_t *bp); +static void __fcache_remove_hash(cache_ent_t *bp); + +static cache_ent_t *__dcache_find(struct super_block *sb, u32 sec); +static cache_ent_t *__dcache_get(struct super_block *sb, u32 sec); +static void __dcache_insert_hash(struct super_block *sb, cache_ent_t *bp); +static void __dcache_remove_hash(cache_ent_t *bp); + +/*----------------------------------------------------------------------*/ +/* Static functions */ +/*----------------------------------------------------------------------*/ +static void push_to_mru(cache_ent_t *bp, cache_ent_t *list) +{ + bp->next = list->next; + bp->prev = list; + list->next->prev = bp; + list->next = bp; +} + +static void push_to_lru(cache_ent_t *bp, cache_ent_t *list) +{ + bp->prev = list->prev; + bp->next = list; + list->prev->next = bp; + list->prev = bp; +} + +static void move_to_mru(cache_ent_t *bp, cache_ent_t *list) +{ + bp->prev->next = bp->next; + bp->next->prev = bp->prev; + push_to_mru(bp, list); +} + +static void move_to_lru(cache_ent_t *bp, cache_ent_t *list) +{ + bp->prev->next = bp->next; + bp->next->prev = bp->prev; + push_to_lru(bp, list); +} + +static inline s32 __check_hash_valid(cache_ent_t *bp) +{ +#ifdef DEBUG_HASH_LIST + if ((bp->hash.next == (cache_ent_t *)DEBUG_HASH_NEXT) || + (bp->hash.prev == (cache_ent_t *)DEBUG_HASH_PREV)) { + return -EINVAL; + } +#endif + if ((bp->hash.next == bp) || (bp->hash.prev == bp)) + return -EINVAL; + + return 0; +} + +static inline void __remove_from_hash(cache_ent_t *bp) +{ + (bp->hash.prev)->hash.next = bp->hash.next; + (bp->hash.next)->hash.prev = bp->hash.prev; + bp->hash.next = bp; + bp->hash.prev = bp; +#ifdef DEBUG_HASH_LIST + bp->hash.next = (cache_ent_t *)DEBUG_HASH_NEXT; + bp->hash.prev = (cache_ent_t *)DEBUG_HASH_PREV; +#endif +} + +/* Do FAT mirroring (don't sync) + * sec: sector No. in FAT1 + * bh: bh of sec. + */ +static inline s32 __fat_copy(struct super_block *sb, u32 sec, struct buffer_head *bh, int sync) +{ +#ifdef CONFIG_SDFAT_FAT_MIRRORING + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + int sec2; + + if (fsi->FAT2_start_sector != fsi->FAT1_start_sector) { + sec2 = sec - fsi->FAT1_start_sector + fsi->FAT2_start_sector; + BUG_ON(sec2 != (sec + fsi->num_FAT_sectors)); + + MMSG("BD: fat mirroring (%d in FAT1, %d in FAT2)\n", sec, sec2); + if (write_sect(sb, sec2, bh, sync)) + return -EIO; + } +#else + /* DO NOTHING */ +#endif + return 0; +} /* end of __fat_copy */ + +/* + * returns 1, if bp is flushed + * returns 0, if bp is not dirty + * returns -1, if error occurs + */ +static s32 __fcache_ent_flush(struct super_block *sb, cache_ent_t *bp, u32 sync) +{ + if (!(bp->flag & DIRTYBIT)) + return 0; +#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY + // Make buffer dirty (XXX: Naive impl.) + if (write_sect(sb, bp->sec, bp->bh, 0)) + return -EIO; + + if (__fat_copy(sb, bp->sec, bp->bh, 0)) + return -EIO; +#endif + bp->flag &= ~(DIRTYBIT); + + if (sync) + sync_dirty_buffer(bp->bh); + + return 1; +} + +static s32 __fcache_ent_discard(struct super_block *sb, cache_ent_t *bp) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + __fcache_remove_hash(bp); + bp->sec = ~0; + bp->flag = 0; + + if (bp->bh) { + __brelse(bp->bh); + bp->bh = NULL; + } + move_to_lru(bp, &fsi->fcache.lru_list); + return 0; +} + +u8 *fcache_getblk(struct super_block *sb, u32 sec) +{ + cache_ent_t *bp; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + u32 page_ra_count = FCACHE_MAX_RA_SIZE >> sb->s_blocksize_bits; + + bp = __fcache_find(sb, sec); + if (bp) { + if (bdev_check_bdi_valid(sb)) { + __fcache_ent_flush(sb, bp, 0); + __fcache_ent_discard(sb, bp); + return NULL; + } + move_to_mru(bp, &fsi->fcache.lru_list); + return bp->bh->b_data; + } + + bp = __fcache_get(sb, sec); + if (!__check_hash_valid(bp)) + __fcache_remove_hash(bp); + + bp->sec = sec; + bp->flag = 0; + __fcache_insert_hash(sb, bp); + + /* Naive FAT read-ahead (increase I/O unit to page_ra_count) */ + if ((sec & (page_ra_count - 1)) == 0) + bdev_readahead(sb, sec, page_ra_count); + + /* + * patch 1.2.4 : buffer_head null pointer exception problem. + * + * When read_sect is failed, fcache should be moved to + * EMPTY hash_list and the first of lru_list. + */ + if (read_sect(sb, sec, &(bp->bh), 1)) { + __fcache_ent_discard(sb, bp); + return NULL; + } + + return bp->bh->b_data; +} + +static inline int __mark_delayed_dirty(struct super_block *sb, cache_ent_t *bp) +{ +#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (fsi->vol_type == EXFAT) + return -ENOTSUPP; + + bp->flag |= DIRTYBIT; + return 0; +#else + return -ENOTSUPP; +#endif +} + + + +s32 fcache_modify(struct super_block *sb, u32 sec) +{ + cache_ent_t *bp; + + bp = __fcache_find(sb, sec); + if (!bp) { + sdfat_fs_error(sb, "Can`t find fcache (sec 0x%08x)", sec); + return -EIO; + } + + if (!__mark_delayed_dirty(sb, bp)) + return 0; + + if (write_sect(sb, sec, bp->bh, 0)) + return -EIO; + + if (__fat_copy(sb, sec, bp->bh, 0)) + return -EIO; + + return 0; +} + +/*======================================================================*/ +/* Cache Initialization Functions */ +/*======================================================================*/ +s32 meta_cache_init(struct super_block *sb) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + s32 i; + + /* LRU list */ + fsi->fcache.lru_list.next = &fsi->fcache.lru_list; + fsi->fcache.lru_list.prev = fsi->fcache.lru_list.next; + + for (i = 0; i < FAT_CACHE_SIZE; i++) { + fsi->fcache.pool[i].sec = ~0; + fsi->fcache.pool[i].flag = 0; + fsi->fcache.pool[i].bh = NULL; + fsi->fcache.pool[i].prev = NULL; + fsi->fcache.pool[i].next = NULL; + push_to_mru(&(fsi->fcache.pool[i]), &fsi->fcache.lru_list); + } + + fsi->dcache.lru_list.next = &fsi->dcache.lru_list; + fsi->dcache.lru_list.prev = fsi->dcache.lru_list.next; + fsi->dcache.keep_list.next = &fsi->dcache.keep_list; + fsi->dcache.keep_list.prev = fsi->dcache.keep_list.next; + + // Initially, all the BUF_CACHEs are in the LRU list + for (i = 0; i < BUF_CACHE_SIZE; i++) { + fsi->dcache.pool[i].sec = ~0; + fsi->dcache.pool[i].flag = 0; + fsi->dcache.pool[i].bh = NULL; + fsi->dcache.pool[i].prev = NULL; + fsi->dcache.pool[i].next = NULL; + push_to_mru(&(fsi->dcache.pool[i]), &fsi->dcache.lru_list); + } + + /* HASH list */ + for (i = 0; i < FAT_CACHE_HASH_SIZE; i++) { + fsi->fcache.hash_list[i].sec = ~0; + fsi->fcache.hash_list[i].hash.next = &(fsi->fcache.hash_list[i]); +; + fsi->fcache.hash_list[i].hash.prev = fsi->fcache.hash_list[i].hash.next; + } + + for (i = 0; i < FAT_CACHE_SIZE; i++) + __fcache_insert_hash(sb, &(fsi->fcache.pool[i])); + + for (i = 0; i < BUF_CACHE_HASH_SIZE; i++) { + fsi->dcache.hash_list[i].sec = ~0; + fsi->dcache.hash_list[i].hash.next = &(fsi->dcache.hash_list[i]); + + fsi->dcache.hash_list[i].hash.prev = fsi->dcache.hash_list[i].hash.next; + } + + for (i = 0; i < BUF_CACHE_SIZE; i++) + __dcache_insert_hash(sb, &(fsi->dcache.pool[i])); + + return 0; +} + +s32 meta_cache_shutdown(struct super_block *sb) +{ + return 0; +} + +/*======================================================================*/ +/* FAT Read/Write Functions */ +/*======================================================================*/ +s32 fcache_release_all(struct super_block *sb) +{ + s32 ret = 0; + cache_ent_t *bp; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + s32 dirtycnt = 0; + + bp = fsi->fcache.lru_list.next; + while (bp != &fsi->fcache.lru_list) { + s32 ret_tmp = __fcache_ent_flush(sb, bp, 0); + + if (ret_tmp < 0) + ret = ret_tmp; + else + dirtycnt += ret_tmp; + + bp->sec = ~0; + bp->flag = 0; + + if (bp->bh) { + __brelse(bp->bh); + bp->bh = NULL; + } + bp = bp->next; + } + + DMSG("BD:Release / dirty fat cache: %d (err:%d)\n", dirtycnt, ret); + return ret; +} + + +/* internal DIRTYBIT marked => bh dirty */ +s32 fcache_flush(struct super_block *sb, u32 sync) +{ + s32 ret = 0; + cache_ent_t *bp; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + s32 dirtycnt = 0; + + bp = fsi->fcache.lru_list.next; + while (bp != &fsi->fcache.lru_list) { + ret = __fcache_ent_flush(sb, bp, sync); + if (ret < 0) + break; + + dirtycnt += ret; + bp = bp->next; + } + + MMSG("BD: flush / dirty fat cache: %d (err:%d)\n", dirtycnt, ret); + return ret; +} + +static cache_ent_t *__fcache_find(struct super_block *sb, u32 sec) +{ + s32 off; + cache_ent_t *bp, *hp; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + off = (sec + (sec >> fsi->sect_per_clus_bits)) & (FAT_CACHE_HASH_SIZE - 1); + hp = &(fsi->fcache.hash_list[off]); + for (bp = hp->hash.next; bp != hp; bp = bp->hash.next) { + if (bp->sec == sec) { + /* + * patch 1.2.4 : for debugging + */ + WARN(!bp->bh, "[SDFAT] fcache has no bh. " + "It will make system panic.\n"); + + touch_buffer(bp->bh); + return bp; + } + } + return NULL; +} + +static cache_ent_t *__fcache_get(struct super_block *sb, u32 sec) +{ + cache_ent_t *bp; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + bp = fsi->fcache.lru_list.prev; +#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY + while (bp->flag & DIRTYBIT) { + cache_ent_t *bp_prev = bp->prev; + + bp = bp_prev; + if (bp == &fsi->fcache.lru_list) { + DMSG("BD: fat cache flooding\n"); + fcache_flush(sb, 0); // flush all dirty FAT caches + bp = fsi->fcache.lru_list.prev; + } + } +#endif +// if (bp->flag & DIRTYBIT) +// sync_dirty_buffer(bp->bh); + + move_to_mru(bp, &fsi->fcache.lru_list); + return bp; +} + +static void __fcache_insert_hash(struct super_block *sb, cache_ent_t *bp) +{ + s32 off; + cache_ent_t *hp; + FS_INFO_T *fsi; + + fsi = &(SDFAT_SB(sb)->fsi); + off = (bp->sec + (bp->sec >> fsi->sect_per_clus_bits)) & (FAT_CACHE_HASH_SIZE-1); + + hp = &(fsi->fcache.hash_list[off]); + bp->hash.next = hp->hash.next; + bp->hash.prev = hp; + hp->hash.next->hash.prev = bp; + hp->hash.next = bp; +} + + +static void __fcache_remove_hash(cache_ent_t *bp) +{ +#ifdef DEBUG_HASH_LIST + if ((bp->hash.next == (cache_ent_t *)DEBUG_HASH_NEXT) || + (bp->hash.prev == (cache_ent_t *)DEBUG_HASH_PREV)) { + EMSG("%s: FATAL: tried to remove already-removed-cache-entry" + "(bp:%p)\n", __func__, bp); + return; + } +#endif + WARN_ON(bp->flag & DIRTYBIT); + __remove_from_hash(bp); +} + +/*======================================================================*/ +/* Buffer Read/Write Functions */ +/*======================================================================*/ +/* Read-ahead a cluster */ +s32 dcache_readahead(struct super_block *sb, u32 sec) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + struct buffer_head *bh; + u32 max_ra_count = DCACHE_MAX_RA_SIZE >> sb->s_blocksize_bits; + u32 page_ra_count = PAGE_SIZE >> sb->s_blocksize_bits; + u32 adj_ra_count = max(fsi->sect_per_clus, page_ra_count); + u32 ra_count = min(adj_ra_count, max_ra_count); + + /* Read-ahead is not required */ + if (fsi->sect_per_clus == 1) + return 0; + + if (sec < fsi->data_start_sector) { + EMSG("BD: %s: requested sector is invalid(sect:%u, root:%u)\n", + __func__, sec, fsi->data_start_sector); + return -EIO; + } + + /* Not sector aligned with ra_count, resize ra_count to page size */ + if ((sec - fsi->data_start_sector) & (ra_count - 1)) + ra_count = page_ra_count; + + bh = sb_find_get_block(sb, sec); + if (!bh || !buffer_uptodate(bh)) + bdev_readahead(sb, sec, ra_count); + + brelse(bh); + + return 0; +} + +/* + * returns 1, if bp is flushed + * returns 0, if bp is not dirty + * returns -1, if error occurs + */ +static s32 __dcache_ent_flush(struct super_block *sb, cache_ent_t *bp, u32 sync) +{ + if (!(bp->flag & DIRTYBIT)) + return 0; +#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY + // Make buffer dirty (XXX: Naive impl.) + if (write_sect(sb, bp->sec, bp->bh, 0)) + return -EIO; +#endif + bp->flag &= ~(DIRTYBIT); + + if (sync) + sync_dirty_buffer(bp->bh); + + return 1; +} + +static s32 __dcache_ent_discard(struct super_block *sb, cache_ent_t *bp) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + MMSG("%s : bp[%p] (sec:%08x flag:%08x bh:%p) list(prev:%p next:%p) " + "hash(prev:%p next:%p)\n", __func__, + bp, bp->sec, bp->flag, bp->bh, bp->prev, bp->next, + bp->hash.prev, bp->hash.next); + + __dcache_remove_hash(bp); + bp->sec = ~0; + bp->flag = 0; + + if (bp->bh) { + __brelse(bp->bh); + bp->bh = NULL; + } + + move_to_lru(bp, &fsi->dcache.lru_list); + return 0; +} + +u8 *dcache_getblk(struct super_block *sb, u32 sec) +{ + cache_ent_t *bp; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + bp = __dcache_find(sb, sec); + if (bp) { + if (bdev_check_bdi_valid(sb)) { + MMSG("%s: found cache(%p, sect:%u). But invalid BDI\n" + , __func__, bp, sec); + __dcache_ent_flush(sb, bp, 0); + __dcache_ent_discard(sb, bp); + return NULL; + } + + if (!(bp->flag & KEEPBIT)) // already in keep list + move_to_mru(bp, &fsi->dcache.lru_list); + + return bp->bh->b_data; + } + + bp = __dcache_get(sb, sec); + + if (!__check_hash_valid(bp)) + __dcache_remove_hash(bp); + + bp->sec = sec; + bp->flag = 0; + __dcache_insert_hash(sb, bp); + + if (read_sect(sb, sec, &(bp->bh), 1)) { + __dcache_ent_discard(sb, bp); + return NULL; + } + + return bp->bh->b_data; + +} + +s32 dcache_modify(struct super_block *sb, u32 sec) +{ + s32 ret = -EIO; + cache_ent_t *bp; + + set_sb_dirty(sb); + + bp = __dcache_find(sb, sec); + if (unlikely(!bp)) { + sdfat_fs_error(sb, "Can`t find dcache (sec 0x%08x)", sec); + return -EIO; + } +#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY + if (SDFAT_SB(sb)->fsi.vol_type != EXFAT) { + bp->flag |= DIRTYBIT; + return 0; + } +#endif + ret = write_sect(sb, sec, bp->bh, 0); + + if (ret) { + DMSG("%s : failed to modify buffer(err:%d, sec:%u, bp:0x%p)\n", + __func__, ret, sec, bp); + } + + return ret; +} + +s32 dcache_lock(struct super_block *sb, u32 sec) +{ + cache_ent_t *bp; + + bp = __dcache_find(sb, sec); + if (likely(bp)) { + bp->flag |= LOCKBIT; + return 0; + } + + EMSG("%s : failed to lock buffer(sec:%u, bp:0x%p)\n", __func__, sec, bp); + return -EIO; +} + +s32 dcache_unlock(struct super_block *sb, u32 sec) +{ + cache_ent_t *bp; + + bp = __dcache_find(sb, sec); + if (likely(bp)) { + bp->flag &= ~(LOCKBIT); + return 0; + } + + EMSG("%s : failed to unlock buffer (sec:%u, bp:0x%p)\n", __func__, sec, bp); + return -EIO; +} + +s32 dcache_release(struct super_block *sb, u32 sec) +{ + cache_ent_t *bp; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + bp = __dcache_find(sb, sec); + if (unlikely(!bp)) + return -ENOENT; + +#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY + if (bp->flag & DIRTYBIT) { + if (write_sect(sb, bp->sec, bp->bh, 0)) + return -EIO; + } +#endif + bp->sec = ~0; + bp->flag = 0; + + if (bp->bh) { + __brelse(bp->bh); + bp->bh = NULL; + } + + move_to_lru(bp, &fsi->dcache.lru_list); + return 0; +} + +s32 dcache_release_all(struct super_block *sb) +{ + s32 ret = 0; + cache_ent_t *bp; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + s32 dirtycnt = 0; + + /* Connect list elements: + * LRU list : (A - B - ... - bp_front) + (bp_first + ... + bp_last) + */ + while (fsi->dcache.keep_list.prev != &fsi->dcache.keep_list) { + cache_ent_t *bp_keep = fsi->dcache.keep_list.prev; + // bp_keep->flag &= ~(KEEPBIT); // Will be 0-ed later + move_to_mru(bp_keep, &fsi->dcache.lru_list); + } + + bp = fsi->dcache.lru_list.next; + while (bp != &fsi->dcache.lru_list) { +#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY + if (bp->flag & DIRTYBIT) { + dirtycnt++; + if (write_sect(sb, bp->sec, bp->bh, 0)) + ret = -EIO; + } +#endif + bp->sec = ~0; + bp->flag = 0; + + if (bp->bh) { + __brelse(bp->bh); + bp->bh = NULL; + } + bp = bp->next; + } + + DMSG("BD:Release / dirty buf cache: %d (err:%d)", dirtycnt, ret); + return ret; +} + + +s32 dcache_flush(struct super_block *sb, u32 sync) +{ + s32 ret = 0; + cache_ent_t *bp; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + s32 dirtycnt = 0; + s32 keepcnt = 0; + + /* Connect list elements: + * LRU list : (A - B - ... - bp_front) + (bp_first + ... + bp_last) + */ + while (fsi->dcache.keep_list.prev != &fsi->dcache.keep_list) { + cache_ent_t *bp_keep = fsi->dcache.keep_list.prev; + + bp_keep->flag &= ~(KEEPBIT); // Will be 0-ed later + move_to_mru(bp_keep, &fsi->dcache.lru_list); + keepcnt++; + } + + bp = fsi->dcache.lru_list.next; + while (bp != &fsi->dcache.lru_list) { + if (bp->flag & DIRTYBIT) { +#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY + // Make buffer dirty (XXX: Naive impl.) + if (write_sect(sb, bp->sec, bp->bh, 0)) { + ret = -EIO; + break; + } + +#endif + bp->flag &= ~(DIRTYBIT); + dirtycnt++; + + if (sync != 0) + sync_dirty_buffer(bp->bh); + } + bp = bp->next; + } + + MMSG("BD: flush / dirty dentry cache: %d (%d from keeplist, err:%d)\n", + dirtycnt, keepcnt, ret); + return ret; +} + +static cache_ent_t *__dcache_find(struct super_block *sb, u32 sec) +{ + s32 off; + cache_ent_t *bp, *hp; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + off = (sec + (sec >> fsi->sect_per_clus_bits)) & (BUF_CACHE_HASH_SIZE - 1); + + hp = &(fsi->dcache.hash_list[off]); + for (bp = hp->hash.next; bp != hp; bp = bp->hash.next) { + if (bp->sec == sec) { + touch_buffer(bp->bh); + return bp; + } + } + return NULL; +} + +static cache_ent_t *__dcache_get(struct super_block *sb, u32 sec) +{ + cache_ent_t *bp; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + bp = fsi->dcache.lru_list.prev; +#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY + while (bp->flag & (DIRTYBIT | LOCKBIT)) { + cache_ent_t *bp_prev = bp->prev; // hold prev + + if (bp->flag & DIRTYBIT) { + MMSG("BD: Buf cache => Keep list\n"); + bp->flag |= KEEPBIT; + move_to_mru(bp, &fsi->dcache.keep_list); + } + bp = bp_prev; + + /* If all dcaches are dirty */ + if (bp == &fsi->dcache.lru_list) { + DMSG("BD: buf cache flooding\n"); + dcache_flush(sb, 0); + bp = fsi->dcache.lru_list.prev; + } + } +#else + while (bp->flag & LOCKBIT) + bp = bp->prev; +#endif +// if (bp->flag & DIRTYBIT) +// sync_dirty_buffer(bp->bh); + + move_to_mru(bp, &fsi->dcache.lru_list); + return bp; +} + +static void __dcache_insert_hash(struct super_block *sb, cache_ent_t *bp) +{ + s32 off; + cache_ent_t *hp; + FS_INFO_T *fsi; + + fsi = &(SDFAT_SB(sb)->fsi); + off = (bp->sec + (bp->sec >> fsi->sect_per_clus_bits)) & (BUF_CACHE_HASH_SIZE-1); + + hp = &(fsi->dcache.hash_list[off]); + bp->hash.next = hp->hash.next; + bp->hash.prev = hp; + hp->hash.next->hash.prev = bp; + hp->hash.next = bp; +} + +static void __dcache_remove_hash(cache_ent_t *bp) +{ +#ifdef DEBUG_HASH_LIST + if ((bp->hash.next == (cache_ent_t *)DEBUG_HASH_NEXT) || + (bp->hash.prev == (cache_ent_t *)DEBUG_HASH_PREV)) { + EMSG("%s: FATAL: tried to remove already-removed-cache-entry" + "(bp:%p)\n", __func__, bp); + return; + } +#endif + WARN_ON(bp->flag & DIRTYBIT); + __remove_from_hash(bp); +} + + +/* end of cache.c */ diff --git a/fs/sdfat/config.h b/fs/sdfat/config.h new file mode 100644 index 0000000000000..6e2a4e80932c6 --- /dev/null +++ b/fs/sdfat/config.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _SDFAT_CONFIG_H +#define _SDFAT_CONFIG_H +/*======================================================================*/ +/* */ +/* FFS CONFIGURATIONS */ +/* (CHANGE THIS PART IF REQUIRED) */ +/* */ +/*======================================================================*/ + +/*----------------------------------------------------------------------*/ +/* Feature Config */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Debug/Experimental Config */ +/*----------------------------------------------------------------------*/ +//#define CONFIG_SDFAT_TRACE_IO +//#define CONFIG_SDFAT_TRACE_LOCK /* Trace elapsed time in lock_super(sb) */ + +/*----------------------------------------------------------------------*/ +/* Defragmentation Config */ +/*----------------------------------------------------------------------*/ +//#define CONFIG_SDFAT_DFR +//#define CONFIG_SDFAT_DFR_PACKING +//#define CONFIG_SDFAT_DFR_DEBUG + +/*----------------------------------------------------------------------*/ +/* Config for Kernel equal or newer than 3.7 */ +/*----------------------------------------------------------------------*/ +#ifndef CONFIG_SDFAT_WRITE_SB_INTERVAL_CSECS +#define CONFIG_SDFAT_WRITE_SB_INTERVAL_CSECS (dirty_writeback_interval) +#endif + +/*----------------------------------------------------------------------*/ +/* Default Kconfig */ +/*----------------------------------------------------------------------*/ +/* default mount options */ +#ifndef CONFIG_SDFAT_DEFAULT_CODEPAGE /* if Kconfig lacked codepage */ +#define CONFIG_SDFAT_DEFAULT_CODEPAGE 437 +#endif + +#ifndef CONFIG_SDFAT_DEFAULT_IOCHARSET /* if Kconfig lacked iocharset */ +#define CONFIG_SDFAT_DEFAULT_IOCHARSET "utf8" +#endif + +#ifndef CONFIG_SDFAT_FAT32_SHORTNAME_SEQ /* Shortname ~1, ... ~9 have higher + * priority (WIN32/VFAT-like) + */ +//#define CONFIG_SDFAT_FAT32_SHORTNAME_SEQ +#endif + +#ifndef CONFIG_SDFAT_ALIGNED_MPAGE_WRITE +//#define CONFIG_SDFAT_ALIGNED_MPAGE_WRITE +#endif + +#ifndef CONFIG_SDFAT_FAT_MIRRORING /* if Kconfig lacked fat-mirroring option */ +#define CONFIG_SDFAT_FAT_MIRRORING /* Write FAT 1, FAT 2 simultaneously */ +#endif + +#ifndef CONFIG_SDFAT_DELAYED_META_DIRTY +//#define CONFIG_SDFAT_DELAYED_META_DIRTY /* delayed DIR/FAT dirty support */ +#endif + +#ifndef CONFIG_SDFAT_SUPPORT_DIR_SYNC +//#define CONFIG_SDFAT_SUPPORT_DIR_SYNC /* support DIR_SYNC */ +#endif + +#ifndef CONFIG_SDFAT_CHECK_RO_ATTR +//#define CONFIG_SDFAT_CHECK_RO_ATTR +#endif + +#ifndef CONFIG_SDFAT_RESTRICT_EXT_ONLY_SFN +#define CONFIG_SDFAT_RESTRICT_EXT_ONLY_SFN +#endif + +#ifndef CONFIG_SDFAT_ALLOW_LOOKUP_LOSSY_SFN +//#define CONFIG_SDFAT_ALLOW_LOOKUP_LOSSY_SFN +#endif + +#ifndef CONFIG_SDFAT_DBG_SHOW_PID +//#define CONFIG_SDFAT_DBG_SHOW_PID +#endif + +#ifndef CONFIG_SDFAT_VIRTUAL_XATTR +//#define CONFIG_SDFAT_VIRTUAL_XATTR +#endif + +#ifndef CONFIG_SDFAT_SUPPORT_STLOG +//#define CONFIG_SDFAT_SUPPORT_STLOG +#endif + +#ifndef CONFIG_SDFAT_DEBUG +//{ +//#define CONFIG_SDFAT_DEBUG + +#ifndef CONFIG_SDFAT_DBG_IOCTL +//#define CONFIG_SDFAT_DBG_IOCTL +#endif + +#ifndef CONFIG_SDFAT_DBG_MSG +//#define CONFIG_SDFAT_DBG_MSG +#endif + +#ifndef CONFIG_SDFAT_DBG_CAREFUL +//#define CONFIG_SDFAT_DBG_CAREFUL +#endif + +#ifndef CONFIG_SDFAT_DBG_BUGON +//#define CONFIG_SDFAT_DBG_BUGON +#endif + +#ifndef CONFIG_SDFAT_DBG_WARNON +//#define CONFIG_SDFAT_DBG_WARNON +#endif +//} +#endif /* CONFIG_SDFAT_DEBUG */ + + +#ifndef CONFIG_SDFAT_TRACE_SB_LOCK +//#define CONFIG_SDFAT_TRACE_SB_LOCK +#endif + +#ifndef CONFIG_SDFAT_TRACE_ELAPSED_TIME +//#define CONFIG_SDFAT_TRACE_ELAPSED_TIME +#endif + +#endif /* _SDFAT_CONFIG_H */ + +/* end of config.h */ diff --git a/fs/sdfat/core.c b/fs/sdfat/core.c new file mode 100644 index 0000000000000..4384816afcf15 --- /dev/null +++ b/fs/sdfat/core.c @@ -0,0 +1,3672 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : core.c */ +/* PURPOSE : FAT & exFAT common core code for sdFAT */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/* */ +/************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "sdfat.h" +#include "core.h" +#include +#include + +/*----------------------------------------------------------------------*/ +/* Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ +static inline void __set_sb_dirty(struct super_block *sb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) + sb->s_dirt = 1; +#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) */ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + + sbi->s_dirt = 1; + /* Insert work */ + spin_lock(&sbi->work_lock); + if (!sbi->write_super_queued) { + unsigned long delay; + + delay = msecs_to_jiffies(CONFIG_SDFAT_WRITE_SB_INTERVAL_CSECS * 10); + queue_delayed_work(system_long_wq, &sbi->write_super_work, delay); + sbi->write_super_queued = 1; + } + spin_unlock(&sbi->work_lock); +#endif +} + +void set_sb_dirty(struct super_block *sb) +{ + __set_sb_dirty(sb); + // XXX: to be removed later, prints too much output + //TMSG("%s finished.\n", __func__); +} + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ + +static s8 *reserved_names[] = { + "AUX ", "CON ", "NUL ", "PRN ", + "COM1 ", "COM2 ", "COM3 ", "COM4 ", + "COM5 ", "COM6 ", "COM7 ", "COM8 ", "COM9 ", + "LPT1 ", "LPT2 ", "LPT3 ", "LPT4 ", + "LPT5 ", "LPT6 ", "LPT7 ", "LPT8 ", "LPT9 ", + NULL +}; + +/*======================================================================*/ +/* Local Function Definitions */ +/*======================================================================*/ + +/* + * File System Management Functions + */ + +static s32 check_type_size(void) +{ + /* critical check for system requirement on size of DENTRY_T structure */ + if (sizeof(DENTRY_T) != DENTRY_SIZE) + return -EINVAL; + + if (sizeof(DOS_DENTRY_T) != DENTRY_SIZE) + return -EINVAL; + + if (sizeof(EXT_DENTRY_T) != DENTRY_SIZE) + return -EINVAL; + + if (sizeof(FILE_DENTRY_T) != DENTRY_SIZE) + return -EINVAL; + + if (sizeof(STRM_DENTRY_T) != DENTRY_SIZE) + return -EINVAL; + + if (sizeof(NAME_DENTRY_T) != DENTRY_SIZE) + return -EINVAL; + + if (sizeof(BMAP_DENTRY_T) != DENTRY_SIZE) + return -EINVAL; + + if (sizeof(CASE_DENTRY_T) != DENTRY_SIZE) + return -EINVAL; + + if (sizeof(VOLM_DENTRY_T) != DENTRY_SIZE) + return -EINVAL; + + return 0; +} + +static s32 __fs_set_vol_flags(struct super_block *sb, u16 new_flag, s32 always_sync) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + s32 err; + s32 sync = 0; + + /* flags are not changed */ + if (fsi->vol_flag == new_flag) + return 0; + + fsi->vol_flag = new_flag; + + /* skip updating volume dirty flag, + * if this volume has been mounted with read-only + */ + if (sb->s_flags & MS_RDONLY) + return 0; + + if (!fsi->pbr_bh) { + err = read_sect(sb, 0, &(fsi->pbr_bh), 1); + if (err) { + EMSG("%s : failed to read boot sector\n", __func__); + return err; + } + } + + if (fsi->vol_type == EXFAT) { + pbr64_t *bpb = (pbr64_t *)fsi->pbr_bh->b_data; + bpb->bsx.vol_flags = cpu_to_le16(new_flag); + } else if (fsi->vol_type == FAT32) { + pbr32_t *bpb = (pbr32_t *)fsi->pbr_bh->b_data; + bpb->bsx.state = new_flag & VOL_DIRTY ? FAT_VOL_DIRTY : 0x00; + } else { /* FAT16/12 */ + pbr16_t *bpb = (pbr16_t *) fsi->pbr_bh->b_data; + bpb->bpb.state = new_flag & VOL_DIRTY ? FAT_VOL_DIRTY : 0x00; + } + + if (always_sync) + sync = 1; + else if ((new_flag == VOL_DIRTY) && (!buffer_dirty(fsi->pbr_bh))) + sync = 1; + else + sync = 0; + + err = write_sect(sb, 0, fsi->pbr_bh, sync); + if (err) + EMSG("%s : failed to modify volume flag\n", __func__); + + return err; +} + +static s32 fs_set_vol_flags(struct super_block *sb, u16 new_flag) +{ + return __fs_set_vol_flags(sb, new_flag, 0); +} + +s32 fscore_set_vol_flags(struct super_block *sb, u16 new_flag, s32 always_sync) +{ + return __fs_set_vol_flags(sb, new_flag, always_sync); +} + +static inline s32 __fs_meta_sync(struct super_block *sb, s32 do_sync) +{ +#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (fsi->vol_type != EXFAT) { + MMSG("meta flush in fs_sync(sync=%d)\n", do_sync); + fcache_flush(sb, 0); + dcache_flush(sb, 0); + } +#else + /* DO NOTHING */ +#endif + return 0; +} + +static s32 fs_sync(struct super_block *sb, s32 do_sync) +{ + s32 err; + + if (!do_sync) + return 0; + + err = __fs_meta_sync(sb, do_sync); + + if (!err) + err = bdev_sync_all(sb); + + if (err) + EMSG("%s : failed to sync. (err:%d)\n", __func__, err); + + return err; +} + +/* + * Cluster Management Functions + */ + +static s32 __clear_cluster(struct inode *inode, u32 clu) +{ + u32 s, n; + struct super_block *sb = inode->i_sb; + u32 sect_size = (u32)sb->s_blocksize; + s32 ret = 0; + struct buffer_head *tmp_bh = NULL; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (IS_CLUS_FREE(clu)) { /* FAT16 root_dir */ + s = fsi->root_start_sector; + n = fsi->data_start_sector; + } else { + s = CLUS_TO_SECT(fsi, clu); + n = s + fsi->sect_per_clus; + } + + if (IS_DIRSYNC(inode)) { + ret = write_msect_zero(sb, s, (s32)fsi->sect_per_clus); + if (ret != -EAGAIN) + return ret; + } + + /* Trying buffered zero writes + * if it doesn't have DIRSYNC or write_msect_zero() returned -EAGAIN + */ + for ( ; s < n; s++) { +#if 0 + dcache_release(sb, s); +#endif + ret = read_sect(sb, s, &tmp_bh, 0); + if (ret) + goto out; + + memset((u8 *)tmp_bh->b_data, 0x0, sect_size); + ret = write_sect(sb, s, tmp_bh, 0); + if (ret) + goto out; + } +out: + brelse(tmp_bh); + return ret; +} /* end of __clear_cluster */ + +static s32 __find_last_cluster(struct super_block *sb, CHAIN_T *p_chain, u32 *ret_clu) +{ + u32 clu, next; + s32 count = 0; + + next = p_chain->dir; + if (p_chain->flags == 0x03) { + *ret_clu = next + p_chain->size - 1; + return 0; + } + + do { + count++; + clu = next; + if (fat_ent_get_safe(sb, clu, &next)) + return -EIO; + } while (!IS_CLUS_EOF(next)); + + if (p_chain->size != count) { + sdfat_fs_error(sb, "bogus directory size " + "(clus : ondisk(%d) != counted(%d))", + p_chain->size, count); + sdfat_debug_bug_on(1); + return -EIO; + } + + *ret_clu = clu; + return 0; +} + + +static s32 __count_num_clusters(struct super_block *sb, CHAIN_T *p_chain, s32 *ret_count) +{ + s32 i, count; + u32 clu; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (!p_chain->dir || IS_CLUS_EOF(p_chain->dir)) { + *ret_count = 0; + return 0; + } + + if (p_chain->flags == 0x03) { + *ret_count = p_chain->size; + return 0; + } + + clu = p_chain->dir; + count = 0; + for (i = CLUS_BASE; i < fsi->num_clusters; i++) { + count++; + if (fat_ent_get_safe(sb, clu, &clu)) + return -EIO; + if (IS_CLUS_EOF(clu)) + break; + } + + *ret_count = count; + return 0; +} + +/* + * Upcase table Management Functions + */ +static void free_upcase_table(struct super_block *sb) +{ + u32 i; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + u16 **upcase_table; + + upcase_table = fsi->vol_utbl; + for (i = 0 ; i < UTBL_COL_COUNT ; i++) { + /* kfree(NULL) is safe */ + kfree(upcase_table[i]); + upcase_table[i] = NULL; + } + + /* kfree(NULL) is safe */ + kfree(fsi->vol_utbl); + fsi->vol_utbl = NULL; +} + +static s32 __load_upcase_table(struct super_block *sb, u32 sector, u32 num_sectors, u32 utbl_checksum) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + struct buffer_head *tmp_bh = NULL; + u32 sect_size = (u32)sb->s_blocksize; + s32 ret = -EIO; + u32 i, j; + + u8 skip = false; + u32 index = 0; + u32 checksum = 0; + u16 **upcase_table = kzalloc((UTBL_COL_COUNT * sizeof(u16 *)), GFP_KERNEL); + + if (!upcase_table) + return -ENOMEM; + /* thanks for kzalloc + * memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *)); + */ + + fsi->vol_utbl = upcase_table; + num_sectors += sector; + + while (sector < num_sectors) { + ret = read_sect(sb, sector, &tmp_bh, 1); + if (ret) { + EMSG("%s: failed to read sector(0x%x)\n", + __func__, sector); + goto error; + } + sector++; + + for (i = 0; i < sect_size && index <= 0xFFFF; i += 2) { + /* FIXME : is __le16 ok? */ + //u16 uni = le16_to_cpu(((__le16*)(tmp_bh->b_data))[i]); + u16 uni = get_unaligned_le16((u8 *)tmp_bh->b_data+i); + + checksum = ((checksum & 1) ? 0x80000000 : 0) + + (checksum >> 1) + *(((u8 *)tmp_bh->b_data)+i); + checksum = ((checksum & 1) ? 0x80000000 : 0) + + (checksum >> 1) + *(((u8 *)tmp_bh->b_data)+(i+1)); + + if (skip) { + MMSG("skip from 0x%X to 0x%X(amount of 0x%X)\n", + index, index+uni, uni); + index += uni; + skip = false; + } else if (uni == index) { + index++; + } else if (uni == 0xFFFF) { + skip = true; + } else { /* uni != index , uni != 0xFFFF */ + u16 col_index = get_col_index(index); + + if (!upcase_table[col_index]) { + upcase_table[col_index] = + kmalloc((UTBL_ROW_COUNT * sizeof(u16)), GFP_KERNEL); + if (!upcase_table[col_index]) { + EMSG("failed to allocate memory" + " for column 0x%X\n", + col_index); + ret = -ENOMEM; + goto error; + } + + for (j = 0; j < UTBL_ROW_COUNT; j++) + upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j; + } + + upcase_table[col_index][get_row_index(index)] = uni; + index++; + } + } + } + if (index >= 0xFFFF && utbl_checksum == checksum) { + DMSG("%s: load upcase table successfully" + "(idx:0x%08x, utbl_chksum:0x%08x)\n", + __func__, index, utbl_checksum); + if (tmp_bh) + brelse(tmp_bh); + return 0; + } + + EMSG("%s: failed to load upcase table" + "(idx:0x%08x, chksum:0x%08x, utbl_chksum:0x%08x)\n", + __func__, index, checksum, utbl_checksum); + + ret = -EINVAL; +error: + if (tmp_bh) + brelse(tmp_bh); + free_upcase_table(sb); + return ret; +} + +static s32 __load_default_upcase_table(struct super_block *sb) +{ + s32 i, ret = -EIO; + u32 j; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + u8 skip = false; + u32 index = 0; + u16 uni = 0; + u16 **upcase_table; + + upcase_table = kmalloc((UTBL_COL_COUNT * sizeof(u16 *)), GFP_KERNEL); + if (!upcase_table) + return -ENOMEM; + + fsi->vol_utbl = upcase_table; + memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *)); + + for (i = 0; index <= 0xFFFF && i < SDFAT_NUM_UPCASE*2; i += 2) { + /* FIXME : is __le16 ok? */ + //uni = le16_to_cpu(((__le16*)uni_def_upcase)[i>>1]); + uni = get_unaligned_le16((u8 *)uni_def_upcase+i); + if (skip) { + MMSG("skip from 0x%x ", index); + index += uni; + MMSG("to 0x%x (amount of 0x%x)\n", index, uni); + skip = false; + } else if (uni == index) { + index++; + } else if (uni == 0xFFFF) { + skip = true; + } else { /* uni != index , uni != 0xFFFF */ + u16 col_index = get_col_index(index); + + if (!upcase_table[col_index]) { + upcase_table[col_index] = kmalloc((UTBL_ROW_COUNT * sizeof(u16)), GFP_KERNEL); + if (!upcase_table[col_index]) { + EMSG("failed to allocate memory for " + "new column 0x%x\n", col_index); + ret = -ENOMEM; + goto error; + } + + for (j = 0; j < UTBL_ROW_COUNT; j++) + upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j; + } + + upcase_table[col_index][get_row_index(index)] = uni; + index++; + } + } + + if (index >= 0xFFFF) + return 0; + +error: + /* FATAL error: default upcase table has error */ + free_upcase_table(sb); + return ret; +} + +static s32 load_upcase_table(struct super_block *sb) +{ + s32 i, ret; + u32 tbl_clu, tbl_size; + u32 type, sector, num_sectors; + u8 blksize_bits = sb->s_blocksize_bits; + CHAIN_T clu; + CASE_DENTRY_T *ep; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + clu.dir = fsi->root_dir; + clu.flags = 0x01; + + if (fsi->vol_type != EXFAT) + goto load_default; + + while (!IS_CLUS_EOF(clu.dir)) { + for (i = 0; i < fsi->dentries_per_clu; i++) { + ep = (CASE_DENTRY_T *) get_dentry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -EIO; + + type = fsi->fs_func->get_entry_type((DENTRY_T *) ep); + + if (type == TYPE_UNUSED) + break; + if (type != TYPE_UPCASE) + continue; + + tbl_clu = le32_to_cpu(ep->start_clu); + tbl_size = (u32) le64_to_cpu(ep->size); + + sector = CLUS_TO_SECT(fsi, tbl_clu); + num_sectors = ((tbl_size-1) >> blksize_bits) + 1; + ret = __load_upcase_table(sb, sector, num_sectors, + le32_to_cpu(ep->checksum)); + + if (ret && (ret != -EIO)) + goto load_default; + + /* load successfully */ + return ret; + } + + if (get_next_clus_safe(sb, &(clu.dir))) + return -EIO; + } + +load_default: + sdfat_log_msg(sb, KERN_INFO, "trying to load default upcase table"); + /* load default upcase table */ + return __load_default_upcase_table(sb); +} /* end of load_upcase_table */ + + +/* + * Directory Entry Management Functions + */ +s32 walk_fat_chain(struct super_block *sb, CHAIN_T *p_dir, s32 byte_offset, u32 *clu) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + s32 clu_offset; + u32 cur_clu; + + clu_offset = byte_offset >> fsi->cluster_size_bits; + cur_clu = p_dir->dir; + + if (p_dir->flags == 0x03) { + cur_clu += clu_offset; + } else { + while (clu_offset > 0) { + if (get_next_clus_safe(sb, &cur_clu)) + return -EIO; + if (IS_CLUS_EOF(cur_clu)) { + sdfat_fs_error(sb, "invalid dentry access " + "beyond EOF (clu : %u, eidx : %d)", + p_dir->dir, + byte_offset >> DENTRY_SIZE_BITS); + return -EIO; + } + clu_offset--; + } + } + + if (clu) + *clu = cur_clu; + return 0; +} + +static s32 find_location(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 *sector, s32 *offset) +{ + s32 ret; + u32 off, clu = 0; + u32 blksize_mask = (u32)(sb->s_blocksize-1); + u8 blksize_bits = sb->s_blocksize_bits; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + off = entry << DENTRY_SIZE_BITS; + + /* FAT16 root_dir */ + if (IS_CLUS_FREE(p_dir->dir)) { + *offset = off & blksize_mask; + *sector = off >> blksize_bits; + *sector += fsi->root_start_sector; + return 0; + } + + ret = walk_fat_chain(sb, p_dir, off, &clu); + if (ret) + return ret; + + /* byte offset in cluster */ + off &= (fsi->cluster_size - 1); + + /* byte offset in sector */ + *offset = off & blksize_mask; + + /* sector offset in cluster */ + *sector = off >> blksize_bits; + *sector += CLUS_TO_SECT(fsi, clu); + return 0; +} /* end of find_location */ + +DENTRY_T *get_dentry_in_dir(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 *sector) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + u32 dentries_per_page = PAGE_SIZE >> DENTRY_SIZE_BITS; + s32 off; + u32 sec; + u8 *buf; + + if (p_dir->dir == DIR_DELETED) { + EMSG("%s : abnormal access to deleted dentry\n", __func__); + BUG_ON(!fsi->prev_eio); + return NULL; + } + + if (find_location(sb, p_dir, entry, &sec, &off)) + return NULL; + + /* DIRECTORY READAHEAD : + * Try to read ahead per a page except root directory of fat12/16 + */ + if ((!IS_CLUS_FREE(p_dir->dir)) && + !(entry & (dentries_per_page - 1))) + dcache_readahead(sb, sec); + + buf = dcache_getblk(sb, sec); + if (!buf) + return NULL; + + if (sector) + *sector = sec; + return (DENTRY_T *)(buf + off); +} /* end of get_dentry_in_dir */ + +/* used only in search empty_slot() */ +#define CNT_UNUSED_NOHIT (-1) +#define CNT_UNUSED_HIT (-2) +/* search EMPTY CONTINUOUS "num_entries" entries */ +static s32 search_empty_slot(struct super_block *sb, HINT_FEMP_T *hint_femp, CHAIN_T *p_dir, s32 num_entries) +{ + s32 i, dentry, num_empty = 0; + s32 dentries_per_clu; + u32 type; + CHAIN_T clu; + DENTRY_T *ep; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (IS_CLUS_FREE(p_dir->dir)) /* FAT16 root_dir */ + dentries_per_clu = fsi->dentries_in_root; + else + dentries_per_clu = fsi->dentries_per_clu; + + ASSERT(-1 <= hint_femp->eidx); + + if (hint_femp->eidx != -1) { + clu.dir = hint_femp->cur.dir; + clu.size = hint_femp->cur.size; + clu.flags = hint_femp->cur.flags; + + dentry = hint_femp->eidx; + + if (num_entries <= hint_femp->count) { + MMSG("%s: empty slot(HIT) - found " + "(clu : 0x%08x eidx : %d)\n", + __func__, hint_femp->cur.dir, hint_femp->eidx); + hint_femp->eidx = -1; + + if (fsi->vol_type == EXFAT) + return dentry; + + return dentry + (num_entries - 1); + } + MMSG("%s: empty slot(HIT) - search from " + "(clu : 0x%08x eidx : %d)\n", + __func__, hint_femp->cur.dir, hint_femp->eidx); + } else { + MMSG("%s: empty slot(MISS) - search from " + "(clu:0x%08x eidx : 0)\n", + __func__, p_dir->dir); + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + dentry = 0; + } + + while (!IS_CLUS_EOF(clu.dir)) { + /* FAT16 root_dir */ + if (IS_CLUS_FREE(p_dir->dir)) + i = dentry % dentries_per_clu; + else + i = dentry & (dentries_per_clu-1); + + for ( ; i < dentries_per_clu; i++, dentry++) { + ep = get_dentry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -EIO; + + type = fsi->fs_func->get_entry_type(ep); + + if ((type == TYPE_UNUSED) || (type == TYPE_DELETED)) { + num_empty++; + if (hint_femp->eidx == -1) { + hint_femp->eidx = dentry; + hint_femp->count = CNT_UNUSED_NOHIT; + + hint_femp->cur.dir = clu.dir; + hint_femp->cur.size = clu.size; + hint_femp->cur.flags = clu.flags; + } + + if ((type == TYPE_UNUSED) && + (hint_femp->count != CNT_UNUSED_HIT)) { + hint_femp->count = CNT_UNUSED_HIT; + } + } else { + if ((hint_femp->eidx != -1) && + (hint_femp->count == CNT_UNUSED_HIT)) { + /* unused empty group means + * an empty group which includes + * unused dentry + */ + sdfat_fs_error(sb, + "found bogus dentry(%d) " + "beyond unused empty group(%d) " + "(start_clu : %u, cur_clu : %u)\n", + dentry, hint_femp->eidx, p_dir->dir, + clu.dir); + return -EIO; + } + + num_empty = 0; + hint_femp->eidx = -1; + } + + if (num_empty >= num_entries) { + /* found and invalidate hint_femp */ + hint_femp->eidx = -1; + + if (fsi->vol_type == EXFAT) + return (dentry - (num_entries-1)); + + return dentry; + } + } + + if (IS_CLUS_FREE(p_dir->dir)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUS_EOF; + } else { + if (get_next_clus_safe(sb, &(clu.dir))) + return -EIO; + } + } + + return -ENOSPC; +} /* end of search_empty_slot */ + +/* find empty directory entry. + * if there isn't any empty slot, expand cluster chain. + */ +static s32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, s32 num_entries) +{ + s32 ret, dentry; + u32 last_clu, sector; + u64 size = 0; + CHAIN_T clu; + DENTRY_T *ep = NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + FILE_ID_T *fid = &(SDFAT_I(inode)->fid); + HINT_FEMP_T hint_femp; + + hint_femp.eidx = -1; + + ASSERT(-1 <= fid->hint_femp.eidx); + + if (fid->hint_femp.eidx != -1) { + memcpy(&hint_femp, &fid->hint_femp, sizeof(HINT_FEMP_T)); + fid->hint_femp.eidx = -1; + } + + /* FAT16 root_dir */ + if (IS_CLUS_FREE(p_dir->dir)) + return search_empty_slot(sb, &hint_femp, p_dir, num_entries); + + while ((dentry = search_empty_slot(sb, &hint_femp, p_dir, num_entries)) < 0) { + if (dentry == -EIO) + break; + + if (fsi->fs_func->check_max_dentries(fid)) + return -ENOSPC; + + /* we trust p_dir->size regardless of FAT type */ + if (__find_last_cluster(sb, p_dir, &last_clu)) + return -EIO; + + /* + * Allocate new cluster to this directory + */ + clu.dir = last_clu + 1; + clu.size = 0; /* UNUSED */ + clu.flags = p_dir->flags; + + /* (0) check if there are reserved clusters + * (create_dir ì˜ ì£¼ì„ ì°¸ê³ ) + */ + if (!IS_CLUS_EOF(fsi->used_clusters) && + ((fsi->used_clusters + fsi->reserved_clusters) >= (fsi->num_clusters - 2))) + return -ENOSPC; + + /* (1) allocate a cluster */ + ret = fsi->fs_func->alloc_cluster(sb, 1, &clu, ALLOC_HOT); + if (!ret) + return -ENOSPC; + if (ret < 0) + return -EIO; + + if (__clear_cluster(inode, clu.dir)) + return -EIO; + + /* (2) append to the FAT chain */ + if (clu.flags != p_dir->flags) { + /* no-fat-chain bit is disabled, + * so fat-chain should be synced with alloc-bmp + */ + chain_cont_cluster(sb, p_dir->dir, p_dir->size); + p_dir->flags = 0x01; + hint_femp.cur.flags = 0x01; + } + + if (clu.flags == 0x01) + if (fat_ent_set(sb, last_clu, clu.dir)) + return -EIO; + + if (hint_femp.eidx == -1) { + /* the special case that new dentry + * should be allocated from the start of new cluster + */ + hint_femp.eidx = p_dir->size << + (fsi->cluster_size_bits - DENTRY_SIZE_BITS); + hint_femp.count = fsi->dentries_per_clu; + + hint_femp.cur.dir = clu.dir; + hint_femp.cur.size = 0; + hint_femp.cur.flags = clu.flags; + } + hint_femp.cur.size++; + p_dir->size++; + size = (p_dir->size << fsi->cluster_size_bits); + + /* (3) update the directory entry */ + if ((fsi->vol_type == EXFAT) && (p_dir->dir != fsi->root_dir)) { + ep = get_dentry_in_dir(sb, + &(fid->dir), fid->entry+1, §or); + if (!ep) + return -EIO; + fsi->fs_func->set_entry_size(ep, size); + fsi->fs_func->set_entry_flag(ep, p_dir->flags); + if (dcache_modify(sb, sector)) + return -EIO; + + if (update_dir_chksum(sb, &(fid->dir), fid->entry)) + return -EIO; + } + + /* directory inode should be updated in here */ + i_size_write(inode, (loff_t)size); + SDFAT_I(inode)->i_size_ondisk += fsi->cluster_size; + SDFAT_I(inode)->i_size_aligned += fsi->cluster_size; + SDFAT_I(inode)->fid.size = size; + SDFAT_I(inode)->fid.flags = p_dir->flags; + inode->i_blocks += 1 << (fsi->cluster_size_bits - sb->s_blocksize_bits); + } + + return dentry; +} /* end of find_empty_entry */ + +#define SDFAT_MIN_SUBDIR (2) +static const char *dot_name[SDFAT_MIN_SUBDIR] = { DOS_CUR_DIR_NAME, DOS_PAR_DIR_NAME }; + +static s32 __count_dos_name_entries(struct super_block *sb, CHAIN_T *p_dir, u32 type, u32 *dotcnt) +{ + s32 i, count = 0, check_dot = 0; + s32 dentries_per_clu; + u32 entry_type; + CHAIN_T clu; + DENTRY_T *ep; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (IS_CLUS_FREE(p_dir->dir)) /* FAT16 root_dir */ + dentries_per_clu = fsi->dentries_in_root; + else + dentries_per_clu = fsi->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + if (dotcnt) { + *dotcnt = 0; + if (fsi->vol_type != EXFAT) + check_dot = 1; + } + + while (!IS_CLUS_EOF(clu.dir)) { + for (i = 0; i < dentries_per_clu; i++) { + ep = get_dentry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -EIO; + + entry_type = fsi->fs_func->get_entry_type(ep); + + if (entry_type == TYPE_UNUSED) + return count; + if (!(type & TYPE_CRITICAL_PRI) && !(type & TYPE_BENIGN_PRI)) + continue; + + if ((type != TYPE_ALL) && (type != entry_type)) + continue; + + count++; + if (check_dot && (i < SDFAT_MIN_SUBDIR)) { + BUG_ON(fsi->vol_type == EXFAT); + /* 11 is DOS_NAME_LENGTH */ + if (!strncmp(ep->dummy, dot_name[i], 11)) + (*dotcnt)++; + } + } + + /* FAT16 root_dir */ + if (IS_CLUS_FREE(p_dir->dir)) + break; + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUS_EOF; + } else { + if (get_next_clus_safe(sb, &(clu.dir))) + return -EIO; + } + + check_dot = 0; + } + + return count; +} + +s32 check_dir_empty(struct super_block *sb, CHAIN_T *p_dir) +{ + s32 i, count = 0; + s32 dentries_per_clu; + u32 type; + CHAIN_T clu; + DENTRY_T *ep; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (IS_CLUS_FREE(p_dir->dir)) /* FAT16 root_dir */ + dentries_per_clu = fsi->dentries_in_root; + else + dentries_per_clu = fsi->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + while (!IS_CLUS_EOF(clu.dir)) { + for (i = 0; i < dentries_per_clu; i++) { + ep = get_dentry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -EIO; + + type = fsi->fs_func->get_entry_type(ep); + + if (type == TYPE_UNUSED) + return 0; + + if ((type != TYPE_FILE) && (type != TYPE_DIR)) + continue; + + /* FAT16 root_dir */ + if (IS_CLUS_FREE(p_dir->dir)) + return -ENOTEMPTY; + + if (fsi->vol_type == EXFAT) + return -ENOTEMPTY; + + if ((p_dir->dir == fsi->root_dir) || (++count > 2)) + return -ENOTEMPTY; + } + + /* FAT16 root_dir */ + if (IS_CLUS_FREE(p_dir->dir)) + return -ENOTEMPTY; + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUS_EOF; + } else { + if (get_next_clus_safe(sb, &(clu.dir))) + return -EIO; + } + } + + return 0; +} + +/* + * Name Conversion Functions + */ +#ifdef CONFIG_SDFAT_ALLOW_LOOKUP_LOSSY_SFN + /* over name length only */ +#define NEED_INVALIDATE_SFN(x) ((x) & NLS_NAME_OVERLEN) +#else + /* all lossy case */ +#define NEED_INVALIDATE_SFN(x) (x) +#endif + +/* NOTE : + * We should keep shortname code compatible with v1.0.15 or lower + * So, we try to check ext-only-name at create-mode only. + * + * i.e. '.mtp' -> + * v1.0.15 : ' MTP' with name_case, 0x10 + * v1.1.0 : 'MT????~?' with name_case, 0x00 and longname. + */ +static inline void preprocess_ext_only_sfn(s32 lookup, u16 first_char, DOS_NAME_T *p_dosname, s32 *lossy) +{ +#ifdef CONFIG_SDFAT_RESTRICT_EXT_ONLY_SFN + int i; + /* check ext-only-name at create-mode */ + if (*lossy || lookup || (first_char != (u16)'.')) + return; + + p_dosname->name_case = 0xFF; + + /* move ext-name to base-name */ + for (i = 0; i < 3; i++) { + p_dosname->name[i] = p_dosname->name[8+i]; + if (p_dosname->name[i] == ' ') + p_dosname->name[i] = '_'; + } + + /* fill remained space with '_' */ + for (i = 3; i < 8; i++) + p_dosname->name[i] = '_'; + + /* eliminate ext-name */ + for (i = 8; i < 11; i++) + p_dosname->name[i] = ' '; + + *lossy = NLS_NAME_LOSSY; +#endif /* CONFIG_SDFAT_CAN_CREATE_EXT_ONLY_SFN */ +} + +/* input : dir, uni_name + * output : num_of_entry, dos_name(format : aaaaaa~1.bbb) + */ +static s32 get_num_entries_and_dos_name(struct super_block *sb, CHAIN_T *p_dir, + UNI_NAME_T *p_uniname, s32 *entries, + DOS_NAME_T *p_dosname, s32 lookup) +{ + s32 ret, num_entries, lossy = NLS_NAME_NO_LOSSY; + s8 **r; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + /* Init null char. */ + p_dosname->name[0] = '\0'; + + num_entries = fsi->fs_func->calc_num_entries(p_uniname); + if (num_entries == 0) + return -EINVAL; + + if (fsi->vol_type == EXFAT) + goto out; + + nls_uni16s_to_sfn(sb, p_uniname, p_dosname, &lossy); + + preprocess_ext_only_sfn(lookup, p_uniname->name[0], p_dosname, &lossy); + + if (!lossy) { + for (r = reserved_names; *r; r++) { + if (!strncmp((void *) p_dosname->name, *r, 8)) + return -EINVAL; + } + + if (p_dosname->name_case != 0xFF) + num_entries = 1; + } else if (!lookup) { + /* create new dos name */ + ret = fat_generate_dos_name_new(sb, p_dir, p_dosname, + num_entries); + if (ret) + return ret; + + } else if (NEED_INVALIDATE_SFN(lossy)) { + /* FIXME : We should check num_entries */ + p_dosname->name[0] = '\0'; + } + + if (num_entries > 1) + p_dosname->name_case = 0x0; +out: + *entries = num_entries; + return 0; +} /* end of get_num_entries_and_dos_name */ + +void get_uniname_from_dos_entry(struct super_block *sb, DOS_DENTRY_T *ep, UNI_NAME_T *p_uniname, u8 mode) +{ + DOS_NAME_T dos_name; + + if (mode == 0x0) + dos_name.name_case = 0x0; + else + dos_name.name_case = ep->lcase; + + memcpy(dos_name.name, ep->name, DOS_NAME_LENGTH); + nls_sfn_to_uni16s(sb, &dos_name, p_uniname); +} /* end of get_uniname_from_dos_entry */ + +/* returns the length of a struct qstr, ignoring trailing dots */ +static inline unsigned int __striptail_len(unsigned int len, const char *name) +{ + while (len && name[len - 1] == '.') + len--; + return len; +} + +/* + * Name Resolution Functions : + * Zero if it was successful; otherwise nonzero. + */ +static s32 __resolve_path(struct inode *inode, const u8 *path, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, int lookup) +{ + s32 namelen; + s32 lossy = NLS_NAME_NO_LOSSY; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + FILE_ID_T *fid = &(SDFAT_I(inode)->fid); + + /* DOT and DOTDOT are handled by VFS layer */ + + /* strip all trailing spaces */ + /* DO NOTHING : Is needed? */ + + /* strip all trailing periods */ + namelen = __striptail_len(strlen(path), path); + if (!namelen) + return -ENOENT; + + /* the limitation of linux? */ + if (strlen(path) > (MAX_NAME_LENGTH * MAX_CHARSET_SIZE)) + return -ENAMETOOLONG; + + /* + * strip all leading spaces : + * "MS windows 7" supports leading spaces. + * So we should skip this preprocessing for compatibility. + */ + + /* file name conversion : + * If lookup case, we allow bad-name for compatibility. + */ + namelen = nls_vfsname_to_uni16s(sb, path, namelen, p_uniname, &lossy); + if (namelen < 0) + return namelen; /* return error value */ + + if ((lossy && !lookup) || !namelen) + return -EINVAL; + + sdfat_debug_bug_on(fid->size != i_size_read(inode)); +// fid->size = i_size_read(inode); + + p_dir->dir = fid->start_clu; + p_dir->size = (s32)(fid->size >> fsi->cluster_size_bits); + p_dir->flags = fid->flags; + + return 0; +} + +static inline s32 resolve_path(struct inode *inode, const u8 *path, CHAIN_T *dir, UNI_NAME_T *uni) +{ + return __resolve_path(inode, path, dir, uni, 0); +} + +static inline s32 resolve_path_for_lookup(struct inode *inode, const u8 *path, CHAIN_T *dir, UNI_NAME_T *uni) +{ + return __resolve_path(inode, path, dir, uni, 1); +} + +static s32 create_dir(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, FILE_ID_T *fid) +{ + s32 ret, dentry, num_entries; + u64 size; + CHAIN_T clu; + DOS_NAME_T dos_name, dot_name; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries, &dos_name, 0); + if (ret) + return ret; + + /* find_empty_entry must be called before alloc_cluster */ + dentry = find_empty_entry(inode, p_dir, num_entries); + if (dentry < 0) + return dentry; /* -EIO or -ENOSPC */ + + clu.dir = CLUS_EOF; + clu.size = 0; + clu.flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01; + + /* (0) Check if there are reserved clusters up to max. */ + if ((fsi->used_clusters != (u32) ~0) && + ((fsi->used_clusters + fsi->reserved_clusters) >= (fsi->num_clusters - 2))) + return -ENOSPC; + + /* (1) allocate a cluster */ + ret = fsi->fs_func->alloc_cluster(sb, 1, &clu, ALLOC_HOT); + + if (!ret) + return -ENOSPC; + + if (ret < 0) + return -EIO; + + ret = __clear_cluster(inode, clu.dir); + if (ret) + return ret; + + size = fsi->cluster_size; + if (fsi->vol_type != EXFAT) { + /* initialize the . and .. entry + * Information for . points to itself + * Information for .. points to parent dir + */ + + dot_name.name_case = 0x0; + memcpy(dot_name.name, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH); + + ret = fsi->fs_func->init_dir_entry(sb, &clu, 0, TYPE_DIR, clu.dir, 0); + if (ret) + return ret; + + ret = fsi->fs_func->init_ext_entry(sb, &clu, 0, 1, NULL, &dot_name); + if (ret) + return ret; + + memcpy(dot_name.name, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH); + + if (p_dir->dir == fsi->root_dir) + ret = fsi->fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR, CLUS_FREE, 0); + else + ret = fsi->fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR, p_dir->dir, 0); + + if (ret) + return ret; + + ret = fsi->fs_func->init_ext_entry(sb, &clu, 1, 1, NULL, &dot_name); + if (ret) + return ret; + } + + /* (2) update the directory entry */ + /* make sub-dir entry in parent directory */ + ret = fsi->fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_DIR, clu.dir, size); + if (ret) + return ret; + + ret = fsi->fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, &dos_name); + if (ret) + return ret; + + fid->dir.dir = p_dir->dir; + fid->dir.size = p_dir->size; + fid->dir.flags = p_dir->flags; + fid->entry = dentry; + + fid->attr = ATTR_SUBDIR; + fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01; + fid->size = size; + fid->start_clu = clu.dir; + + fid->type = TYPE_DIR; + fid->rwoffset = 0; + fid->hint_bmap.off = -1; + + /* hint_stat will be used if this is directory. */ + fid->version = 0; + fid->hint_stat.eidx = 0; + fid->hint_stat.clu = fid->start_clu; + fid->hint_femp.eidx = -1; + + return 0; +} /* end of create_dir */ + +static s32 create_file(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, u8 mode, FILE_ID_T *fid) +{ + s32 ret, dentry, num_entries; + DOS_NAME_T dos_name; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries, &dos_name, 0); + if (ret) + return ret; + + /* find_empty_entry must be called before alloc_cluster() */ + dentry = find_empty_entry(inode, p_dir, num_entries); + if (dentry < 0) + return dentry; /* -EIO or -ENOSPC */ + + /* (1) update the directory entry */ + /* fill the dos name directory entry information of the created file. + * the first cluster is not determined yet. (0) + */ + ret = fsi->fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_FILE | mode, CLUS_FREE, 0); + if (ret) + return ret; + + ret = fsi->fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, &dos_name); + if (ret) + return ret; + + fid->dir.dir = p_dir->dir; + fid->dir.size = p_dir->size; + fid->dir.flags = p_dir->flags; + fid->entry = dentry; + + fid->attr = ATTR_ARCHIVE | mode; + fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01; + fid->size = 0; + fid->start_clu = CLUS_EOF; + + fid->type = TYPE_FILE; + fid->rwoffset = 0; + fid->hint_bmap.off = -1; + + /* hint_stat will be used if this is directory. */ + fid->version = 0; + fid->hint_stat.eidx = 0; + fid->hint_stat.clu = fid->start_clu; + fid->hint_femp.eidx = -1; + + return 0; +} /* end of create_file */ + +static s32 remove_file(struct inode *inode, CHAIN_T *p_dir, s32 entry) +{ + s32 num_entries; + u32 sector; + DENTRY_T *ep; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + ep = get_dentry_in_dir(sb, p_dir, entry, §or); + if (!ep) + return -EIO; + + dcache_lock(sb, sector); + + /* dcache_lock() before call count_ext_entries() */ + num_entries = fsi->fs_func->count_ext_entries(sb, p_dir, entry, ep); + if (num_entries < 0) { + dcache_unlock(sb, sector); + return -EIO; + } + num_entries++; + + dcache_unlock(sb, sector); + + /* (1) update the directory entry */ + return fsi->fs_func->delete_dir_entry(sb, p_dir, entry, 0, num_entries); +} /* end of remove_file */ + +static s32 rename_file(struct inode *inode, CHAIN_T *p_dir, s32 oldentry, UNI_NAME_T *p_uniname, FILE_ID_T *fid) +{ + s32 ret, newentry = -1, num_old_entries, num_new_entries; + u32 sector_old, sector_new; + DOS_NAME_T dos_name; + DENTRY_T *epold, *epnew; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + epold = get_dentry_in_dir(sb, p_dir, oldentry, §or_old); + if (!epold) + return -EIO; + + dcache_lock(sb, sector_old); + + /* dcache_lock() before call count_ext_entries() */ + num_old_entries = fsi->fs_func->count_ext_entries(sb, p_dir, oldentry, epold); + if (num_old_entries < 0) { + dcache_unlock(sb, sector_old); + return -EIO; + } + num_old_entries++; + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_new_entries, &dos_name, 0); + if (ret) { + dcache_unlock(sb, sector_old); + return ret; + } + + if (num_old_entries < num_new_entries) { + newentry = find_empty_entry(inode, p_dir, num_new_entries); + if (newentry < 0) { + dcache_unlock(sb, sector_old); + return newentry; /* -EIO or -ENOSPC */ + } + + epnew = get_dentry_in_dir(sb, p_dir, newentry, §or_new); + if (!epnew) { + dcache_unlock(sb, sector_old); + return -EIO; + } + + memcpy((void *) epnew, (void *) epold, DENTRY_SIZE); + if (fsi->fs_func->get_entry_type(epnew) == TYPE_FILE) { + fsi->fs_func->set_entry_attr(epnew, fsi->fs_func->get_entry_attr(epnew) | ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + dcache_modify(sb, sector_new); + dcache_unlock(sb, sector_old); + + if (fsi->vol_type == EXFAT) { + epold = get_dentry_in_dir(sb, p_dir, oldentry+1, §or_old); + dcache_lock(sb, sector_old); + epnew = get_dentry_in_dir(sb, p_dir, newentry+1, §or_new); + + if (!epold || !epnew) { + dcache_unlock(sb, sector_old); + return -EIO; + } + + memcpy((void *) epnew, (void *) epold, DENTRY_SIZE); + dcache_modify(sb, sector_new); + dcache_unlock(sb, sector_old); + } + + ret = fsi->fs_func->init_ext_entry(sb, p_dir, newentry, num_new_entries, p_uniname, &dos_name); + if (ret) + return ret; + + fsi->fs_func->delete_dir_entry(sb, p_dir, oldentry, 0, num_old_entries); + fid->entry = newentry; + } else { + if (fsi->fs_func->get_entry_type(epold) == TYPE_FILE) { + fsi->fs_func->set_entry_attr(epold, fsi->fs_func->get_entry_attr(epold) | ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + dcache_modify(sb, sector_old); + dcache_unlock(sb, sector_old); + + ret = fsi->fs_func->init_ext_entry(sb, p_dir, oldentry, num_new_entries, p_uniname, &dos_name); + if (ret) + return ret; + + fsi->fs_func->delete_dir_entry(sb, p_dir, oldentry, num_new_entries, num_old_entries); + } + + return 0; +} /* end of rename_file */ + +static s32 move_file(struct inode *inode, CHAIN_T *p_olddir, s32 oldentry, + CHAIN_T *p_newdir, UNI_NAME_T *p_uniname, FILE_ID_T *fid) +{ + s32 ret, newentry, num_new_entries, num_old_entries; + u32 sector_mov, sector_new; + CHAIN_T clu; + DOS_NAME_T dos_name; + DENTRY_T *epmov, *epnew; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + epmov = get_dentry_in_dir(sb, p_olddir, oldentry, §or_mov); + if (!epmov) + return -EIO; + + /* check if the source and target directory is the same */ + if (fsi->fs_func->get_entry_type(epmov) == TYPE_DIR && + fsi->fs_func->get_entry_clu0(epmov) == p_newdir->dir) + return -EINVAL; + + dcache_lock(sb, sector_mov); + + /* dcache_lock() before call count_ext_entries() */ + num_old_entries = fsi->fs_func->count_ext_entries(sb, p_olddir, oldentry, epmov); + if (num_old_entries < 0) { + dcache_unlock(sb, sector_mov); + return -EIO; + } + num_old_entries++; + + ret = get_num_entries_and_dos_name(sb, p_newdir, p_uniname, &num_new_entries, &dos_name, 0); + if (ret) { + dcache_unlock(sb, sector_mov); + return ret; + } + + newentry = find_empty_entry(inode, p_newdir, num_new_entries); + if (newentry < 0) { + dcache_unlock(sb, sector_mov); + return newentry; /* -EIO or -ENOSPC */ + } + + epnew = get_dentry_in_dir(sb, p_newdir, newentry, §or_new); + if (!epnew) { + dcache_unlock(sb, sector_mov); + return -EIO; + } + + memcpy((void *) epnew, (void *) epmov, DENTRY_SIZE); + if (fsi->fs_func->get_entry_type(epnew) == TYPE_FILE) { + fsi->fs_func->set_entry_attr(epnew, fsi->fs_func->get_entry_attr(epnew) | ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + dcache_modify(sb, sector_new); + dcache_unlock(sb, sector_mov); + + if (fsi->vol_type == EXFAT) { + epmov = get_dentry_in_dir(sb, p_olddir, oldentry+1, §or_mov); + dcache_lock(sb, sector_mov); + epnew = get_dentry_in_dir(sb, p_newdir, newentry+1, §or_new); + if (!epmov || !epnew) { + dcache_unlock(sb, sector_mov); + return -EIO; + } + + memcpy((void *) epnew, (void *) epmov, DENTRY_SIZE); + dcache_modify(sb, sector_new); + dcache_unlock(sb, sector_mov); + } else if (fsi->fs_func->get_entry_type(epnew) == TYPE_DIR) { + /* change ".." pointer to new parent dir */ + clu.dir = fsi->fs_func->get_entry_clu0(epnew); + clu.flags = 0x01; + + epnew = get_dentry_in_dir(sb, &clu, 1, §or_new); + if (!epnew) + return -EIO; + + if (p_newdir->dir == fsi->root_dir) + fsi->fs_func->set_entry_clu0(epnew, CLUS_FREE); + else + fsi->fs_func->set_entry_clu0(epnew, p_newdir->dir); + dcache_modify(sb, sector_new); + } + + ret = fsi->fs_func->init_ext_entry(sb, p_newdir, newentry, num_new_entries, p_uniname, &dos_name); + if (ret) + return ret; + + fsi->fs_func->delete_dir_entry(sb, p_olddir, oldentry, 0, num_old_entries); + + fid->dir.dir = p_newdir->dir; + fid->dir.size = p_newdir->size; + fid->dir.flags = p_newdir->flags; + + fid->entry = newentry; + + return 0; +} /* end of move_file */ + + +/*======================================================================*/ +/* Global Function Definitions */ +/*======================================================================*/ +/* roll back to the initial state of the file system */ +s32 fscore_init(void) +{ + s32 ret; + + ret = check_type_size(); + if (ret) + return ret; + + return extent_cache_init(); +} + +/* make free all memory-alloced global buffers */ +s32 fscore_shutdown(void) +{ + extent_cache_shutdown(); + return 0; +} + +static bool is_exfat(pbr_t *pbr) +{ + int i = 53; + + do { + if (pbr->bpb.f64.res_zero[i-1]) + break; + } while (--i); + return i ? false : true; +} + +static bool is_fat32(pbr_t *pbr) +{ + if (le16_to_cpu(pbr->bpb.f16.num_fat_sectors)) + return false; + return true; +} + +inline pbr_t *read_pbr_with_logical_sector(struct super_block *sb, struct buffer_head **prev_bh) +{ + pbr_t *p_pbr = (pbr_t *) (*prev_bh)->b_data; + u16 logical_sect = 0; + + if (is_exfat(p_pbr)) + logical_sect = 1 << p_pbr->bsx.f64.sect_size_bits; + else + logical_sect = get_unaligned_le16(&p_pbr->bpb.f16.sect_size); + + /* is x a power of 2? + * (x) != 0 && (((x) & ((x) - 1)) == 0) + */ + if (!is_power_of_2(logical_sect) + || (logical_sect < 512) + || (logical_sect > 4096)) { + sdfat_log_msg(sb, KERN_ERR, "bogus logical sector size %u", + logical_sect); + return NULL; + } + + if (logical_sect < sb->s_blocksize) { + sdfat_log_msg(sb, KERN_ERR, + "logical sector size too small for device" + " (logical sector size = %u)", logical_sect); + return NULL; + } + + if (logical_sect > sb->s_blocksize) { + struct buffer_head *bh = NULL; + + __brelse(*prev_bh); + *prev_bh = NULL; + + if (!sb_set_blocksize(sb, logical_sect)) { + sdfat_log_msg(sb, KERN_ERR, + "unable to set blocksize %u", logical_sect); + return NULL; + } + bh = sb_bread(sb, 0); + if (!bh) { + sdfat_log_msg(sb, KERN_ERR, + "unable to read boot sector " + "(logical sector size = %lu)", sb->s_blocksize); + return NULL; + } + + *prev_bh = bh; + p_pbr = (pbr_t *) bh->b_data; + } + + sdfat_log_msg(sb, KERN_INFO, + "set logical sector size : %lu", sb->s_blocksize); + + return p_pbr; +} + +/* mount the file system volume */ +s32 fscore_mount(struct super_block *sb) +{ + s32 ret; + pbr_t *p_pbr; + struct buffer_head *tmp_bh = NULL; + struct gendisk *disk = sb->s_bdev->bd_disk; + struct sdfat_mount_options *opts = &(SDFAT_SB(sb)->options); + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + /* initialize previous I/O error */ + fsi->prev_eio = 0; + + /* open the block device */ + if (bdev_open_dev(sb)) + return -EIO; + + /* set block size to read super block */ + sb_min_blocksize(sb, 512); + + /* read boot sector */ + ret = read_sect(sb, 0, &tmp_bh, 1); + if (ret) { + sdfat_log_msg(sb, KERN_ERR, "unable to read boot sector"); + ret = -EIO; + goto bd_close; + } + + /* PRB is read */ + p_pbr = (pbr_t *) tmp_bh->b_data; + + /* check the validity of PBR */ + if (le16_to_cpu((p_pbr->signature)) != PBR_SIGNATURE) { + sdfat_log_msg(sb, KERN_ERR, "invalid boot record signature"); + brelse(tmp_bh); + ret = -EINVAL; + goto bd_close; + } + + /* check logical sector size */ + p_pbr = read_pbr_with_logical_sector(sb, &tmp_bh); + if (!p_pbr) { + brelse(tmp_bh); + ret = -EIO; + goto bd_close; + } + + /* fill fs_struct */ + if (is_exfat(p_pbr)) { + if (opts->fs_type && opts->fs_type != FS_TYPE_EXFAT) { + sdfat_log_msg(sb, KERN_ERR, + "not specified filesystem type " + "(media:exfat, opts:%s)", + FS_TYPE_STR[opts->fs_type]); + ret = -EINVAL; + goto free_bh; + } + /* set maximum file size for exFAT */ + sb->s_maxbytes = 0x7fffffffffffffffLL; + opts->improved_allocation = 0; + opts->defrag = 0; + ret = mount_exfat(sb, p_pbr); + } else if (is_fat32(p_pbr)) { + if (opts->fs_type && opts->fs_type != FS_TYPE_VFAT) { + sdfat_log_msg(sb, KERN_ERR, + "not specified filesystem type " + "(media:vfat, opts:%s)", + FS_TYPE_STR[opts->fs_type]); + ret = -EINVAL; + goto free_bh; + } + /* set maximum file size for FAT */ + sb->s_maxbytes = 0xffffffff; + ret = mount_fat32(sb, p_pbr); + } else { + if (opts->fs_type && opts->fs_type != FS_TYPE_VFAT) { + sdfat_log_msg(sb, KERN_ERR, + "not specified filesystem type " + "(media:vfat, opts:%s)", + FS_TYPE_STR[opts->fs_type]); + ret = -EINVAL; + goto free_bh; + } + /* set maximum file size for FAT */ + sb->s_maxbytes = 0xffffffff; + opts->improved_allocation = 0; + opts->defrag = 0; + ret = mount_fat16(sb, p_pbr); + } +free_bh: + brelse(tmp_bh); + if (ret) { + sdfat_log_msg(sb, KERN_ERR, "failed to mount fs-core"); + goto bd_close; + } + + /* warn misaligned data data start sector must be a multiple of clu_size */ + sdfat_log_msg(sb, KERN_INFO, + "detected volume info : %s " + "(bps : %lu, spc : %u, data start : %u, %s)", + sdfat_get_vol_type_str(fsi->vol_type), + sb->s_blocksize, fsi->sect_per_clus, fsi->data_start_sector, + (fsi->data_start_sector & (fsi->sect_per_clus - 1)) ? + "misaligned" : "aligned"); + + sdfat_log_msg(sb, KERN_INFO, + "detected volume size : %u MB (disk_size : %llu MB)", + fsi->num_sectors >> 11, + disk ? (u64)((disk->part0.nr_sects) >> 11) : 0); + + ret = load_upcase_table(sb); + if (ret) { + sdfat_log_msg(sb, KERN_ERR, "failed to load upcase table"); + goto bd_close; + } + + if (fsi->vol_type != EXFAT) + goto success; + + /* allocate-bitmap is only for exFAT */ + ret = load_alloc_bmp(sb); + if (ret) { + sdfat_log_msg(sb, KERN_ERR, "failed to load alloc-bitmap"); + goto free_upcase; + } +success: + return 0; +free_upcase: + free_upcase_table(sb); +bd_close: + bdev_close_dev(sb); + return ret; +} /* end of fscore_mount */ + +/* umount the file system volume */ +s32 fscore_umount(struct super_block *sb) +{ + s32 ret = 0; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (fs_sync(sb, 0)) + ret = -EIO; + + if (fs_set_vol_flags(sb, VOL_CLEAN)) + ret = -EIO; + + free_upcase_table(sb); + + if (fsi->vol_type == EXFAT) + free_alloc_bmp(sb); + + if (fcache_release_all(sb)) + ret = -EIO; + + if (dcache_release_all(sb)) + ret = -EIO; + + amap_destroy(sb); + + if (fsi->prev_eio) + ret = -EIO; + /* close the block device */ + bdev_close_dev(sb); + return ret; +} + +/* get the information of a file system volume */ +s32 fscore_statfs(struct super_block *sb, VOL_INFO_T *info) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (fsi->used_clusters == (u32) ~0) { + if (fsi->fs_func->count_used_clusters(sb, &fsi->used_clusters)) + return -EIO; + } + + info->FatType = fsi->vol_type; + info->ClusterSize = fsi->cluster_size; + info->NumClusters = fsi->num_clusters - 2; /* clu 0 & 1 */ + info->UsedClusters = fsi->used_clusters + fsi->reserved_clusters; + info->FreeClusters = info->NumClusters - info->UsedClusters; + + return 0; +} + +/* synchronize all file system volumes */ +s32 fscore_sync_fs(struct super_block *sb, s32 do_sync) +{ + /* synchronize the file system */ + if (fs_sync(sb, do_sync)) + return -EIO; + + if (fs_set_vol_flags(sb, VOL_CLEAN)) + return -EIO; + + return 0; +} + +/* stat allocation unit of a file system volume */ +u32 fscore_get_au_stat(struct super_block *sb, s32 mode) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (fsi->fs_func->get_au_stat) + return fsi->fs_func->get_au_stat(sb, mode); + + /* No error, just returns 0 */ + return 0; +} + + +/*----------------------------------------------------------------------*/ +/* File Operation Functions */ +/*----------------------------------------------------------------------*/ +/* lookup a file */ +s32 fscore_lookup(struct inode *inode, u8 *path, FILE_ID_T *fid) +{ + s32 ret, dentry, num_entries; + CHAIN_T dir; + UNI_NAME_T uni_name; + DOS_NAME_T dos_name; + DENTRY_T *ep, *ep2; + ENTRY_SET_CACHE_T *es = NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + FILE_ID_T *dir_fid = &(SDFAT_I(inode)->fid); + + TMSG("%s entered\n", __func__); + + /* check the validity of directory name in the given pathname */ + ret = resolve_path_for_lookup(inode, path, &dir, &uni_name); + if (ret) + return ret; + + ret = get_num_entries_and_dos_name(sb, &dir, &uni_name, &num_entries, &dos_name, 1); + if (ret) + return ret; + + /* check the validation of hint_stat and initialize it if required */ + if (dir_fid->version != (u32)(inode->i_version & 0xffffffff)) { + dir_fid->hint_stat.clu = dir.dir; + dir_fid->hint_stat.eidx = 0; + dir_fid->version = (u32)(inode->i_version & 0xffffffff); + dir_fid->hint_femp.eidx = -1; + } + + /* search the file name for directories */ + dentry = fsi->fs_func->find_dir_entry(sb, dir_fid, &dir, &uni_name, + num_entries, &dos_name, TYPE_ALL); + + if ((dentry < 0) && (dentry != -EEXIST)) + return dentry; /* -error value */ + + fid->dir.dir = dir.dir; + fid->dir.size = dir.size; + fid->dir.flags = dir.flags; + fid->entry = dentry; + + /* root directory itself */ + if (unlikely(dentry == -EEXIST)) { + fid->type = TYPE_DIR; + fid->rwoffset = 0; + fid->hint_bmap.off = -1; + + fid->attr = ATTR_SUBDIR; + fid->flags = 0x01; + fid->size = 0; + fid->start_clu = fsi->root_dir; + } else { + if (fsi->vol_type == EXFAT) { + es = get_dentry_set_in_dir(sb, &dir, dentry, ES_2_ENTRIES, &ep); + if (!es) + return -EIO; + ep2 = ep+1; + } else { + ep = get_dentry_in_dir(sb, &dir, dentry, NULL); + if (!ep) + return -EIO; + ep2 = ep; + } + + fid->type = fsi->fs_func->get_entry_type(ep); + fid->rwoffset = 0; + fid->hint_bmap.off = -1; + fid->attr = fsi->fs_func->get_entry_attr(ep); + + fid->size = fsi->fs_func->get_entry_size(ep2); + if ((fid->type == TYPE_FILE) && (fid->size == 0)) { + fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01; + fid->start_clu = CLUS_EOF; + } else { + fid->flags = fsi->fs_func->get_entry_flag(ep2); + fid->start_clu = fsi->fs_func->get_entry_clu0(ep2); + } + + if ((fid->type == TYPE_DIR) && (fsi->vol_type != EXFAT)) { + s32 num_clu = 0; + CHAIN_T tmp_dir; + + tmp_dir.dir = fid->start_clu; + tmp_dir.flags = fid->flags; + tmp_dir.size = 0; /* UNUSED */ + + if (__count_num_clusters(sb, &tmp_dir, &num_clu)) + return -EIO; + fid->size = (u64)num_clu << fsi->cluster_size_bits; + } + + /* FOR GRACEFUL ERROR HANDLING */ + if (IS_CLUS_FREE(fid->start_clu)) { + sdfat_fs_error(sb, + "non-zero size file starts with zero cluster " + "(size : %llu, p_dir : %u, entry : 0x%08x)", + fid->size, fid->dir.dir, fid->entry); + sdfat_debug_bug_on(1); + return -EIO; + } + + if (fsi->vol_type == EXFAT) + release_dentry_set(es); + } + + /* hint_stat will be used if this is directory. */ + fid->version = 0; + fid->hint_stat.eidx = 0; + fid->hint_stat.clu = fid->start_clu; + fid->hint_femp.eidx = -1; + + TMSG("%s exited successfully\n", __func__); + return 0; +} /* end of fscore_lookup */ + +/* create a file */ +s32 fscore_create(struct inode *inode, u8 *path, u8 mode, FILE_ID_T *fid) +{ + s32 ret/*, dentry*/; + CHAIN_T dir; + UNI_NAME_T uni_name; + struct super_block *sb = inode->i_sb; + + /* check the validity of directory name in the given pathname */ + ret = resolve_path(inode, path, &dir, &uni_name); + if (ret) + return ret; + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* create a new file */ + ret = create_file(inode, &dir, &uni_name, mode, fid); + + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); + + return ret; +} + +/* read data from a opened file */ +s32 fscore_read_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *rcount) +{ + s32 ret = 0; + s32 offset, sec_offset, clu_offset; + u32 clu, LogSector; + u64 oneblkread, read_bytes; + struct buffer_head *tmp_bh = NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + /* check if the given file ID is opened */ + if (fid->type != TYPE_FILE) + return -EPERM; + + if (fid->rwoffset > fid->size) + fid->rwoffset = fid->size; + + if (count > (fid->size - fid->rwoffset)) + count = fid->size - fid->rwoffset; + + if (count == 0) { + if (rcount) + *rcount = 0; + return 0; + } + + read_bytes = 0; + + while (count > 0) { + clu_offset = (s32)(fid->rwoffset >> fsi->cluster_size_bits); + clu = fid->start_clu; + + if (fid->flags == 0x03) { + clu += clu_offset; + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_bmap.off > 0) && + (clu_offset >= fid->hint_bmap.off)) { + clu_offset -= fid->hint_bmap.off; + clu = fid->hint_bmap.clu; + } + + while (clu_offset > 0) { + ret = get_next_clus_safe(sb, &clu); + if (ret) + goto err_out; + + clu_offset--; + } + } + + /* hint information */ + fid->hint_bmap.off = (s32)(fid->rwoffset >> fsi->cluster_size_bits); + fid->hint_bmap.clu = clu; + + offset = (s32)(fid->rwoffset & (fsi->cluster_size - 1)); /* byte offset in cluster */ + sec_offset = offset >> sb->s_blocksize_bits; /* sector offset in cluster */ + offset &= (sb->s_blocksize - 1); /* byte offset in sector */ + + LogSector = CLUS_TO_SECT(fsi, clu) + sec_offset; + + oneblkread = (u64)(sb->s_blocksize - offset); + if (oneblkread > count) + oneblkread = count; + + if ((offset == 0) && (oneblkread == sb->s_blocksize)) { + ret = read_sect(sb, LogSector, &tmp_bh, 1); + if (ret) + goto err_out; + memcpy(((s8 *) buffer)+read_bytes, ((s8 *) tmp_bh->b_data), (s32) oneblkread); + } else { + ret = read_sect(sb, LogSector, &tmp_bh, 1); + if (ret) + goto err_out; + memcpy(((s8 *) buffer)+read_bytes, ((s8 *) tmp_bh->b_data)+offset, (s32) oneblkread); + } + count -= oneblkread; + read_bytes += oneblkread; + fid->rwoffset += oneblkread; + } + +err_out: + brelse(tmp_bh); + + /* set the size of read bytes */ + if (rcount != NULL) + *rcount = read_bytes; + + return ret; +} /* end of fscore_read_link */ + +/* write data into a opened file */ +s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *wcount) +{ + s32 ret = 0; + s32 modified = false, offset, sec_offset, clu_offset; + s32 num_clusters, num_alloc, num_alloced = (s32) ~0; + u32 clu, last_clu, LogSector, sector; + u64 oneblkwrite, write_bytes; + CHAIN_T new_clu; + TIMESTAMP_T tm; + DENTRY_T *ep, *ep2; + ENTRY_SET_CACHE_T *es = NULL; + struct buffer_head *tmp_bh = NULL; + struct super_block *sb = inode->i_sb; + u32 blksize = (u32)sb->s_blocksize; + u32 blksize_mask = (u32)(sb->s_blocksize-1); + u8 blksize_bits = sb->s_blocksize_bits; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + /* check if the given file ID is opened */ + if (fid->type != TYPE_FILE) + return -EPERM; + + if (fid->rwoffset > fid->size) + fid->rwoffset = fid->size; + + if (count == 0) { + if (wcount) + *wcount = 0; + return 0; + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + if (fid->size == 0) + num_clusters = 0; + else + num_clusters = (s32)((fid->size-1) >> fsi->cluster_size_bits) + 1; + + write_bytes = 0; + + while (count > 0) { + clu_offset = (s32)(fid->rwoffset >> fsi->cluster_size_bits); + clu = last_clu = fid->start_clu; + + if (fid->flags == 0x03) { + if ((clu_offset > 0) && (!IS_CLUS_EOF(clu))) { + last_clu += clu_offset - 1; + + if (clu_offset == num_clusters) + clu = CLUS_EOF; + else + clu += clu_offset; + } + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_bmap.off > 0) && + (clu_offset >= fid->hint_bmap.off)) { + clu_offset -= fid->hint_bmap.off; + clu = fid->hint_bmap.clu; + } + + while ((clu_offset > 0) && (!IS_CLUS_EOF(clu))) { + last_clu = clu; + ret = get_next_clus_safe(sb, &clu); + if (ret) + goto err_out; + + clu_offset--; + } + } + + if (IS_CLUS_EOF(clu)) { + num_alloc = (s32)((count-1) >> fsi->cluster_size_bits) + 1; + new_clu.dir = IS_CLUS_EOF(last_clu) ? CLUS_EOF : last_clu+1; + new_clu.size = 0; + new_clu.flags = fid->flags; + + /* (1) allocate a chain of clusters */ + num_alloced = fsi->fs_func->alloc_cluster(sb, num_alloc, &new_clu, ALLOC_COLD); + if (!num_alloced) + break; + + if (num_alloced < 0) { + ret = -EIO; + goto err_out; + } + + /* (2) append to the FAT chain */ + if (IS_CLUS_EOF(last_clu)) { + if (new_clu.flags == 0x01) + fid->flags = 0x01; + fid->start_clu = new_clu.dir; + modified = true; + } else { + if (new_clu.flags != fid->flags) { + /* no-fat-chain bit is disabled, + * so fat-chain should be synced with + * alloc-bmp + */ + chain_cont_cluster(sb, fid->start_clu, num_clusters); + fid->flags = 0x01; + modified = true; + } + if (new_clu.flags == 0x01) { + ret = fat_ent_set(sb, last_clu, new_clu.dir); + if (ret) + goto err_out; + } + } + + num_clusters += num_alloced; + clu = new_clu.dir; + } + + /* hint information */ + fid->hint_bmap.off = (s32)(fid->rwoffset >> fsi->cluster_size_bits); + fid->hint_bmap.clu = clu; + + /* byte offset in cluster */ + offset = (s32)(fid->rwoffset & (fsi->cluster_size-1)); + /* sector offset in cluster */ + sec_offset = offset >> blksize_bits; + /* byte offset in sector */ + offset &= blksize_mask; + LogSector = CLUS_TO_SECT(fsi, clu) + sec_offset; + + oneblkwrite = (u64)(blksize - offset); + if (oneblkwrite > count) + oneblkwrite = count; + + if ((offset == 0) && (oneblkwrite == blksize)) { + ret = read_sect(sb, LogSector, &tmp_bh, 0); + if (ret) + goto err_out; + + memcpy(((s8 *)tmp_bh->b_data), + ((s8 *)buffer)+write_bytes, + (s32)oneblkwrite); + + ret = write_sect(sb, LogSector, tmp_bh, 0); + if (ret) { + brelse(tmp_bh); + goto err_out; + } + } else { + if ((offset > 0) || ((fid->rwoffset+oneblkwrite) < fid->size)) { + ret = read_sect(sb, LogSector, &tmp_bh, 1); + if (ret) + goto err_out; + } else { + ret = read_sect(sb, LogSector, &tmp_bh, 0); + if (ret) + goto err_out; + } + + memcpy(((s8 *) tmp_bh->b_data)+offset, ((s8 *) buffer)+write_bytes, (s32) oneblkwrite); + ret = write_sect(sb, LogSector, tmp_bh, 0); + if (ret) { + brelse(tmp_bh); + goto err_out; + } + } + + count -= oneblkwrite; + write_bytes += oneblkwrite; + fid->rwoffset += oneblkwrite; + + fid->attr |= ATTR_ARCHIVE; + + if (fid->size < fid->rwoffset) { + fid->size = fid->rwoffset; + modified = true; + } + } + + brelse(tmp_bh); + + /* (3) update the direcoty entry */ + /* get_entry_(set_)in_dir shoulb be check DIR_DELETED flag. */ + if (fsi->vol_type == EXFAT) { + es = get_dentry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); + if (!es) { + ret = -EIO; + goto err_out; + } + ep2 = ep+1; + } else { + ep = get_dentry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) { + ret = -EIO; + goto err_out; + } + ep2 = ep; + } + + fsi->fs_func->set_entry_time(ep, tm_now(SDFAT_SB(sb), &tm), TM_MODIFY); + fsi->fs_func->set_entry_attr(ep, fid->attr); + + if (modified) { + if (fsi->fs_func->get_entry_flag(ep2) != fid->flags) + fsi->fs_func->set_entry_flag(ep2, fid->flags); + + if (fsi->fs_func->get_entry_size(ep2) != fid->size) + fsi->fs_func->set_entry_size(ep2, fid->size); + + if (fsi->fs_func->get_entry_clu0(ep2) != fid->start_clu) + fsi->fs_func->set_entry_clu0(ep2, fid->start_clu); + } + + if (fsi->vol_type == EXFAT) { + if (update_dir_chksum_with_entry_set(sb, es)) { + ret = -EIO; + goto err_out; + } + release_dentry_set(es); + } else { + if (dcache_modify(sb, sector)) { + ret = -EIO; + goto err_out; + } + } + + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); + +err_out: + /* set the size of written bytes */ + if (wcount) + *wcount = write_bytes; + + if (!num_alloced) + return -ENOSPC; + + return ret; +} /* end of fscore_write_link */ + +/* resize the file length */ +s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size) +{ + s32 num_clusters_new, num_clusters_da, num_clusters_phys; + u32 last_clu = CLUS_FREE, sector; + CHAIN_T clu; + TIMESTAMP_T tm; + DENTRY_T *ep, *ep2; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + FILE_ID_T *fid = &(SDFAT_I(inode)->fid); + ENTRY_SET_CACHE_T *es = NULL; + s32 evict = (fid->dir.dir == DIR_DELETED) ? 1 : 0; + + /* check if the given file ID is opened */ + if ((fid->type != TYPE_FILE) && (fid->type != TYPE_DIR)) + return -EPERM; + + /* TO CHECK inode type and size */ + MMSG("%s: inode(%p) type(%s) size:%lld->%lld\n", __func__, inode, + (fid->type == TYPE_FILE) ? "file" : "dir", old_size, new_size); + + /* XXX : This is for debugging. */ + + /* It can be when write failed */ +#if 0 + if (fid->size != old_size) { + DMSG("%s: inode(%p) size-mismatch(old:%lld != fid:%lld)\n", + __func__, inode, old_size, fid->size); + WARN_ON(1); + } +#endif + /* + * There is no lock to protect fid->size. + * So, we should get old_size and use it. + */ + if (old_size <= new_size) + return 0; + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* Reserved count update */ + #define num_clusters(v) ((v) ? (s32)(((v) - 1) >> fsi->cluster_size_bits) + 1 : 0) + num_clusters_da = num_clusters(SDFAT_I(inode)->i_size_aligned); + num_clusters_new = num_clusters(i_size_read(inode)); + num_clusters_phys = num_clusters(SDFAT_I(inode)->i_size_ondisk); + + /* num_clusters(i_size_old) should be equal to num_clusters_da */ + BUG_ON((num_clusters(old_size)) != (num_clusters(SDFAT_I(inode)->i_size_aligned))); + + /* for debugging (FIXME: is okay on no-da case?) */ + BUG_ON(num_clusters_da < num_clusters_phys); + + if ((num_clusters_da != num_clusters_phys) && + (num_clusters_new < num_clusters_da)) { + /* Decrement reserved clusters + * n_reserved = num_clusters_da - max(new,phys) + */ + int n_reserved = (num_clusters_new > num_clusters_phys) ? + (num_clusters_da - num_clusters_new) : + (num_clusters_da - num_clusters_phys); + + fsi->reserved_clusters -= n_reserved; + BUG_ON(fsi->reserved_clusters < 0); + } + + clu.dir = fid->start_clu; + /* In no-da case, num_clusters_phys is equal to below value + * clu.size = (s32)((old_size-1) >> fsi->cluster_size_bits) + 1; + */ + clu.size = num_clusters_phys; + clu.flags = fid->flags; + + /* For bigdata */ + sdfat_statistics_set_trunc(clu.flags, &clu); + + if (new_size > 0) { + /* Truncate FAT chain num_clusters after the first cluster + * num_clusters = min(new, phys); + */ + s32 num_clusters = (num_clusters_new < num_clusters_phys) ? + num_clusters_new : num_clusters_phys; + + /* Follow FAT chain + * (defensive coding - works fine even with corrupted FAT table + */ + if (clu.flags == 0x03) { + clu.dir += num_clusters; + clu.size -= num_clusters; +#if 0 + /* extent_get_clus can`t know last_cluster + * when find target cluster in cache. + */ + } else if (fid->type == TYPE_FILE) { + s32 fclus = 0; + s32 err = extent_get_clus(inode, num_clusters, + &fclus, &(clu.dir), &last_clu, 0); + if (err) + return -EIO; + ASSERT(fclus == num_clusters); + + if ((num_clusters > 1) && (last_clu == fid->start_clu)) { + s32 fclus_tmp = 0; + u32 temp = 0; + + err = extent_get_clus(inode, num_clusters - 1, + &fclus_tmp, &last_clu, &temp, 0); + if (err) + return -EIO; + ASSERT(fclus_tmp == (num_clusters - 1)); + } + + num_clusters -= fclus; + clu.size -= fclus; +#endif + } else { + while (num_clusters > 0) { + last_clu = clu.dir; + if (get_next_clus_safe(sb, &(clu.dir))) + return -EIO; + + num_clusters--; + clu.size--; + } + } + + /* Optimization avialable: */ +#if 0 + if (num_clusters_new < num_clusters) { + < loop > + } else { + // num_clusters_new >= num_clusters_phys + // FAT truncation is not necessary + + clu.dir = CLUS_EOF; + clu.size = 0; + } +#endif + } else if (new_size == 0) { + fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01; + fid->start_clu = CLUS_EOF; + } + BUG_ON(clu.size < 0); + fid->size = new_size; + + if (fid->type == TYPE_FILE) + fid->attr |= ATTR_ARCHIVE; + + /* + * clu.dir: free from + * clu.size: # of clusters to free (exFAT, 0x03 only), no fat_free if 0 + * clu.flags: fid->flags (exFAT only) + */ + + /* (1) update the directory entry */ + if (!evict) { + + if (fsi->vol_type == EXFAT) { + es = get_dentry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); + if (!es) + return -EIO; + ep2 = ep+1; + } else { + ep = get_dentry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + return -EIO; + ep2 = ep; + } + + fsi->fs_func->set_entry_time(ep, tm_now(SDFAT_SB(sb), &tm), TM_MODIFY); + fsi->fs_func->set_entry_attr(ep, fid->attr); + + /* + * if (fsi->vol_type != EXFAT) + * dcache_modify(sb, sector); + */ + + /* File size should be zero if there is no cluster allocated */ + if (IS_CLUS_EOF(fid->start_clu)) + fsi->fs_func->set_entry_size(ep2, 0); + else + fsi->fs_func->set_entry_size(ep2, new_size); + + if (new_size == 0) { + /* Any directory can not be truncated to zero */ + BUG_ON(fid->type != TYPE_FILE); + + fsi->fs_func->set_entry_flag(ep2, 0x01); + fsi->fs_func->set_entry_clu0(ep2, CLUS_FREE); + } + + if (fsi->vol_type == EXFAT) { + if (update_dir_chksum_with_entry_set(sb, es)) + return -EIO; + release_dentry_set(es); + } else { + if (dcache_modify(sb, sector)) + return -EIO; + } + + } /* end of if(fid->dir.dir != DIR_DELETED) */ + + /* (2) cut off from the FAT chain */ + if ((fid->flags == 0x01) && + (!IS_CLUS_FREE(last_clu)) && (!IS_CLUS_EOF(last_clu))) { + if (fat_ent_set(sb, last_clu, CLUS_EOF)) + return -EIO; + } + + /* (3) invalidate cache and free the clusters */ + /* clear extent cache */ + extent_cache_inval_inode(inode); + + /* hint information */ + fid->hint_bmap.off = -1; + fid->hint_bmap.clu = CLUS_EOF; + if (fid->rwoffset > fid->size) + fid->rwoffset = fid->size; + + /* hint_stat will be used if this is directory. */ + fid->hint_stat.eidx = 0; + fid->hint_stat.clu = fid->start_clu; + fid->hint_femp.eidx = -1; + + /* free the clusters */ + if (fsi->fs_func->free_cluster(sb, &clu, evict)) + return -EIO; + + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); + + return 0; +} /* end of fscore_truncate */ + +static void update_parent_info(FILE_ID_T *fid, struct inode *parent_inode) +{ + FS_INFO_T *fsi = &(SDFAT_SB(parent_inode->i_sb)->fsi); + FILE_ID_T *parent_fid = &(SDFAT_I(parent_inode)->fid); + + /* + * the problem that FILE_ID_T caches wrong parent info. + * + * because of flag-mismatch of fid->dir, + * there is abnormal traversing cluster chain. + */ + if (unlikely((parent_fid->flags != fid->dir.flags) + || (parent_fid->size != (fid->dir.size<cluster_size_bits)) + || (parent_fid->start_clu != fid->dir.dir))) { + + fid->dir.dir = parent_fid->start_clu; + fid->dir.flags = parent_fid->flags; + fid->dir.size = ((parent_fid->size + (fsi->cluster_size-1)) + >> fsi->cluster_size_bits); + } +} + +/* rename or move a old file into a new file */ +s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid, + struct inode *new_parent_inode, struct dentry *new_dentry) +{ + s32 ret; + s32 dentry; + CHAIN_T olddir, newdir; + CHAIN_T *p_dir = NULL; + UNI_NAME_T uni_name; + DENTRY_T *ep; + struct super_block *sb = old_parent_inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + u8 *new_path = (u8 *) new_dentry->d_name.name; + struct inode *new_inode = new_dentry->d_inode; + int num_entries; + FILE_ID_T *new_fid = NULL; + u32 new_entry_type = TYPE_UNUSED; + s32 new_entry = 0; + + /* check the validity of pointer parameters */ + if ((new_path == NULL) || (strlen(new_path) == 0)) + return -EINVAL; + + if (fid->dir.dir == DIR_DELETED) { + EMSG("%s : abnormal access to deleted source dentry\n", __func__); + return -ENOENT; + } + + /* patch 1.2.4 : the problem that FILE_ID_T caches wrong parent info. */ + update_parent_info(fid, old_parent_inode); + + olddir.dir = fid->dir.dir; + olddir.size = fid->dir.size; + olddir.flags = fid->dir.flags; + + dentry = fid->entry; + + /* check if the old file is "." or ".." */ + if (fsi->vol_type != EXFAT) { + if ((olddir.dir != fsi->root_dir) && (dentry < 2)) + return -EPERM; + } + + ep = get_dentry_in_dir(sb, &olddir, dentry, NULL); + if (!ep) + return -EIO; + +#ifdef CONFIG_SDFAT_CHECK_RO_ATTR + if (fsi->fs_func->get_entry_attr(ep) & ATTR_READONLY) + return -EPERM; +#endif + + /* check whether new dir is existing directory and empty */ + if (new_inode) { + ret = -EIO; + new_fid = &SDFAT_I(new_inode)->fid; + + if (new_fid->dir.dir == DIR_DELETED) { + EMSG("%s : abnormal access to deleted target dentry\n", __func__); + goto out; + } + + /* patch 1.2.4 : + * the problem that FILE_ID_T caches wrong parent info. + * + * FIXME : is needed? + */ + update_parent_info(new_fid, new_parent_inode); + + p_dir = &(new_fid->dir); + new_entry = new_fid->entry; + ep = get_dentry_in_dir(sb, p_dir, new_entry, NULL); + if (!ep) + goto out; + + new_entry_type = fsi->fs_func->get_entry_type(ep); + + /* if new_inode exists, update fid */ + new_fid->size = i_size_read(new_inode); + + if (new_entry_type == TYPE_DIR) { + CHAIN_T new_clu; + + new_clu.dir = new_fid->start_clu; + new_clu.size = (s32)((new_fid->size-1) >> fsi->cluster_size_bits) + 1; + new_clu.flags = new_fid->flags; + + ret = check_dir_empty(sb, &new_clu); + if (ret) + return ret; + } + } + + /* check the validity of directory name in the given new pathname */ + ret = resolve_path(new_parent_inode, new_path, &newdir, &uni_name); + if (ret) + return ret; + + fs_set_vol_flags(sb, VOL_DIRTY); + + if (olddir.dir == newdir.dir) + ret = rename_file(new_parent_inode, &olddir, dentry, &uni_name, fid); + else + ret = move_file(new_parent_inode, &olddir, dentry, &newdir, &uni_name, fid); + + if ((!ret) && new_inode) { + /* delete entries of new_dir */ + ep = get_dentry_in_dir(sb, p_dir, new_entry, NULL); + if (!ep) { + ret = -EIO; + goto del_out; + } + + num_entries = fsi->fs_func->count_ext_entries(sb, p_dir, new_entry, ep); + if (num_entries < 0) { + ret = -EIO; + goto del_out; + } + + + if (fsi->fs_func->delete_dir_entry(sb, p_dir, new_entry, 0, num_entries+1)) { + ret = -EIO; + goto del_out; + } + + /* Free the clusters if new_inode is a dir(as if fscore_rmdir) */ + if (new_entry_type == TYPE_DIR) { + /* new_fid, new_clu_to_free */ + CHAIN_T new_clu_to_free; + + new_clu_to_free.dir = new_fid->start_clu; + new_clu_to_free.size = (s32)((new_fid->size-1) >> fsi->cluster_size_bits) + 1; + new_clu_to_free.flags = new_fid->flags; + + if (fsi->fs_func->free_cluster(sb, &new_clu_to_free, 1)) { + /* just set I/O error only */ + ret = -EIO; + } + + new_fid->size = 0; + new_fid->start_clu = CLUS_EOF; + new_fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01; + } +del_out: + /* Update new_inode fid + * Prevent syncing removed new_inode + * (new_fid is already initialized above code ("if (new_inode)") + */ + new_fid->dir.dir = DIR_DELETED; + } +out: + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); + + return ret; +} /* end of fscore_rename */ + +/* remove a file */ +s32 fscore_remove(struct inode *inode, FILE_ID_T *fid) +{ + s32 ret; + s32 dentry; + CHAIN_T dir, clu_to_free; + DENTRY_T *ep; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + dir.dir = fid->dir.dir; + dir.size = fid->dir.size; + dir.flags = fid->dir.flags; + + dentry = fid->entry; + + if (fid->dir.dir == DIR_DELETED) { + EMSG("%s : abnormal access to deleted dentry\n", __func__); + return -ENOENT; + } + + ep = get_dentry_in_dir(sb, &dir, dentry, NULL); + if (!ep) + return -EIO; + + +#ifdef CONFIG_SDFAT_CHECK_RO_ATTR + if (fsi->fs_func->get_entry_attr(ep) & ATTR_READONLY) + return -EPERM; +#endif + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* (1) update the directory entry */ + ret = remove_file(inode, &dir, dentry); + if (ret) + goto out; + + clu_to_free.dir = fid->start_clu; + clu_to_free.size = (s32)((fid->size-1) >> fsi->cluster_size_bits) + 1; + clu_to_free.flags = fid->flags; + + /* (2) invalidate extent cache and free the clusters + */ + /* clear extent cache */ + extent_cache_inval_inode(inode); + ret = fsi->fs_func->free_cluster(sb, &clu_to_free, 0); + /* WARN : DO NOT RETURN ERROR IN HERE */ + + /* (3) update FILE_ID_T */ + fid->size = 0; + fid->start_clu = CLUS_EOF; + fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01; + fid->dir.dir = DIR_DELETED; + + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +out: + return ret; +} /* end of fscore_remove */ + + +/* + * Get the information of a given file + * REMARK : This function does not need any file name on linux + * + * info.Size means the value saved on disk. + * But root directory doesn`t have real dentry, + * so the size of root directory returns calculated one exceptively. + */ +s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info) +{ + u32 sector; + s32 count; + CHAIN_T dir; + TIMESTAMP_T tm; + DENTRY_T *ep, *ep2; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + FILE_ID_T *fid = &(SDFAT_I(inode)->fid); + ENTRY_SET_CACHE_T *es = NULL; + u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; + + TMSG("%s entered\n", __func__); + + extent_cache_init_inode(inode); + + /* if root directory */ + if (is_dir && (fid->dir.dir == fsi->root_dir) && (fid->entry == -1)) { + info->Attr = ATTR_SUBDIR; + memset((s8 *) &info->CreateTimestamp, 0, sizeof(DATE_TIME_T)); + memset((s8 *) &info->ModifyTimestamp, 0, sizeof(DATE_TIME_T)); + memset((s8 *) &info->AccessTimestamp, 0, sizeof(DATE_TIME_T)); + //strcpy(info->NameBuf.sfn, "."); + //strcpy(info->NameBuf.lfn, "."); + + dir.dir = fsi->root_dir; + dir.flags = 0x01; + dir.size = 0; /* UNUSED */ + + /* FAT16 root_dir */ + if (IS_CLUS_FREE(fsi->root_dir)) { + info->Size = fsi->dentries_in_root << DENTRY_SIZE_BITS; + } else { + s32 num_clu; + + if (__count_num_clusters(sb, &dir, &num_clu)) + return -EIO; + info->Size = (u64)num_clu << fsi->cluster_size_bits; + } + + count = __count_dos_name_entries(sb, &dir, TYPE_DIR, NULL); + if (count < 0) + return -EIO; + info->NumSubdirs = count; + + return 0; + } + + /* get the directory entry of given file or directory */ + if (fsi->vol_type == EXFAT) { + /* es should be released */ + es = get_dentry_set_in_dir(sb, &(fid->dir), fid->entry, ES_2_ENTRIES, &ep); + if (!es) + return -EIO; + ep2 = ep+1; + } else { + ep = get_dentry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + return -EIO; + ep2 = ep; + /* dcache should be unlocked */ + dcache_lock(sb, sector); + } + + /* set FILE_INFO structure using the acquired DENTRY_T */ + info->Attr = fsi->fs_func->get_entry_attr(ep); + + fsi->fs_func->get_entry_time(ep, &tm, TM_CREATE); + info->CreateTimestamp.Year = tm.year; + info->CreateTimestamp.Month = tm.mon; + info->CreateTimestamp.Day = tm.day; + info->CreateTimestamp.Hour = tm.hour; + info->CreateTimestamp.Minute = tm.min; + info->CreateTimestamp.Second = tm.sec; + info->CreateTimestamp.MilliSecond = 0; + + fsi->fs_func->get_entry_time(ep, &tm, TM_MODIFY); + info->ModifyTimestamp.Year = tm.year; + info->ModifyTimestamp.Month = tm.mon; + info->ModifyTimestamp.Day = tm.day; + info->ModifyTimestamp.Hour = tm.hour; + info->ModifyTimestamp.Minute = tm.min; + info->ModifyTimestamp.Second = tm.sec; + info->ModifyTimestamp.MilliSecond = 0; + + memset((s8 *) &info->AccessTimestamp, 0, sizeof(DATE_TIME_T)); + + info->NumSubdirs = 0; + info->Size = fsi->fs_func->get_entry_size(ep2); + + if (fsi->vol_type == EXFAT) + release_dentry_set(es); + else + dcache_unlock(sb, sector); + + if (is_dir) { + u32 dotcnt = 0; + + dir.dir = fid->start_clu; + dir.flags = fid->flags; + dir.size = fid->size >> fsi->cluster_size_bits; + /* + * NOTE : + * If "dir.flags" has 0x01, "dir.size" is meaningless. + */ +#if 0 + if (info->Size == 0) { + s32 num_clu; + + if (__count_num_clusters(sb, &dir, &num_clu)) + return -EIO; + info->Size = (u64)num_clu << fsi->cluster_size_bits; + } +#endif + count = __count_dos_name_entries(sb, &dir, TYPE_DIR, &dotcnt); + if (count < 0) + return -EIO; + + if (fsi->vol_type == EXFAT) { + count += SDFAT_MIN_SUBDIR; + } else { + /* + * if directory has been corrupted, + * we have to adjust subdir count. + */ + BUG_ON(dotcnt > SDFAT_MIN_SUBDIR); + if (dotcnt < SDFAT_MIN_SUBDIR) { + EMSG("%s: contents of the directory has been " + "corrupted (parent clus : %08x, idx : %d)", + __func__, fid->dir.dir, fid->entry); + } + count += (SDFAT_MIN_SUBDIR - dotcnt); + } + info->NumSubdirs = count; + } + + TMSG("%s exited successfully\n", __func__); + return 0; +} /* end of fscore_read_inode */ + +/* set the information of a given file + * REMARK : This function does not need any file name on linux + */ +s32 fscore_write_inode(struct inode *inode, DIR_ENTRY_T *info, s32 sync) +{ + s32 ret = -EIO; + u32 sector; + TIMESTAMP_T tm; + DENTRY_T *ep, *ep2; + ENTRY_SET_CACHE_T *es = NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + FILE_ID_T *fid = &(SDFAT_I(inode)->fid); + u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; + + + /* SKIP WRITING INODE : + * if the indoe is already unlinked, + * there is no need for updating inode + */ + if (fid->dir.dir == DIR_DELETED) + return 0; + + if (is_dir && (fid->dir.dir == fsi->root_dir) && (fid->entry == -1)) + return 0; + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* get the directory entry of given file or directory */ + if (fsi->vol_type == EXFAT) { + es = get_dentry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); + if (!es) + return -EIO; + ep2 = ep+1; + } else { + /* for other than exfat */ + ep = get_dentry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + return -EIO; + ep2 = ep; + } + + + fsi->fs_func->set_entry_attr(ep, info->Attr); + + /* set FILE_INFO structure using the acquired DENTRY_T */ + tm.sec = info->CreateTimestamp.Second; + tm.min = info->CreateTimestamp.Minute; + tm.hour = info->CreateTimestamp.Hour; + tm.day = info->CreateTimestamp.Day; + tm.mon = info->CreateTimestamp.Month; + tm.year = info->CreateTimestamp.Year; + fsi->fs_func->set_entry_time(ep, &tm, TM_CREATE); + + tm.sec = info->ModifyTimestamp.Second; + tm.min = info->ModifyTimestamp.Minute; + tm.hour = info->ModifyTimestamp.Hour; + tm.day = info->ModifyTimestamp.Day; + tm.mon = info->ModifyTimestamp.Month; + tm.year = info->ModifyTimestamp.Year; + fsi->fs_func->set_entry_time(ep, &tm, TM_MODIFY); + + if (is_dir && fsi->vol_type != EXFAT) { + /* overwirte dirsize if FAT32 and dir size != 0 */ + if (fsi->fs_func->get_entry_size(ep2)) + fsi->fs_func->set_entry_size(ep2, 0); + } else { + /* File size should be zero if there is no cluster allocated */ + u64 on_disk_size = info->Size; + + if (IS_CLUS_EOF(fid->start_clu)) + on_disk_size = 0; + + fsi->fs_func->set_entry_size(ep2, on_disk_size); + } + + if (fsi->vol_type == EXFAT) { + ret = update_dir_chksum_with_entry_set(sb, es); + release_dentry_set(es); + } else { + ret = dcache_modify(sb, sector); + } + + fs_sync(sb, sync); + /* Comment below code to prevent super block update frequently */ + //fs_set_vol_flags(sb, VOL_CLEAN); + + return ret; +} /* end of fscore_write_inode */ + + +/* + * Input: inode, (logical) clu_offset, target allocation area + * Output: errcode, cluster number + * *clu = (~0), if it's unable to allocate a new cluster + */ +s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest) +{ + s32 num_clusters, num_alloced, num_to_be_allocated, modified = false; + u32 last_clu, sector; + CHAIN_T new_clu; + DENTRY_T *ep; + ENTRY_SET_CACHE_T *es = NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + FILE_ID_T *fid = &(SDFAT_I(inode)->fid); + s32 local_clu_offset = clu_offset; + s32 reserved_clusters = fsi->reserved_clusters; + + fid->rwoffset = (s64)(clu_offset) << fsi->cluster_size_bits; + + if (SDFAT_I(inode)->i_size_ondisk == 0) + num_clusters = 0; + else + num_clusters = (s32)((SDFAT_I(inode)->i_size_ondisk-1) >> fsi->cluster_size_bits) + 1; + + num_to_be_allocated = clu_offset - num_clusters + 1; + if ((dest == ALLOC_NOWHERE) && (num_to_be_allocated > 0)) { + *clu = CLUS_EOF; + return 0; + } + + sdfat_debug_check_clusters(inode); + + *clu = last_clu = fid->start_clu; + + /* XXX: Defensive code needed. + * what if i_size_ondisk != # of allocated clusters + */ + if (fid->flags == 0x03) { + if ((clu_offset > 0) && (!IS_CLUS_EOF(*clu))) { + last_clu += clu_offset - 1; + + if (clu_offset == num_clusters) + *clu = CLUS_EOF; + else + *clu += clu_offset; + } + } else if (fid->type == TYPE_FILE) { + s32 fclus = 0; + s32 err = extent_get_clus(inode, clu_offset, + &fclus, clu, &last_clu, 1); + if (err) + return -EIO; + + clu_offset -= fclus; + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_bmap.off > 0) && + (clu_offset >= fid->hint_bmap.off)) { + clu_offset -= fid->hint_bmap.off; + /* hint_bmap.clu should be valid */ + ASSERT(fid->hint_bmap.clu >= 2); + *clu = fid->hint_bmap.clu; + } + + while ((clu_offset > 0) && (!IS_CLUS_EOF(*clu))) { + last_clu = *clu; + if (get_next_clus_safe(sb, clu)) + return -EIO; + clu_offset--; + } + } + + if (IS_CLUS_EOF(*clu)) { + fs_set_vol_flags(sb, VOL_DIRTY); + + new_clu.dir = (IS_CLUS_EOF(last_clu)) ? CLUS_EOF : last_clu + 1; + new_clu.size = 0; + new_clu.flags = fid->flags; + + /* (1) allocate a cluster */ + if (num_to_be_allocated < 1) { + /* Broken FAT (i_sze > allocated FAT) */ + EMSG("%s: invalid fat chain : inode(%p) " + "num_to_be_allocated(%d) " + "i_size_ondisk(%lld) fid->flags(%02x) " + "fid->start(%08x) fid->hint_off(%d) " + "fid->hint_clu(%u) fid->rwoffset(%llu) " + "modified_clu_off(%d) last_clu(%08x) " + "new_clu(%08x)", __func__, inode, + num_to_be_allocated, + (SDFAT_I(inode)->i_size_ondisk), + fid->flags, fid->start_clu, + fid->hint_bmap.off, fid->hint_bmap.clu, + fid->rwoffset, clu_offset, + last_clu, new_clu.dir); + sdfat_fs_error(sb, "broken FAT chain."); + return -EIO; + } + + num_alloced = fsi->fs_func->alloc_cluster(sb, num_to_be_allocated, &new_clu, ALLOC_COLD); + if (num_alloced < 0) { + return -EIO; + } else if (num_alloced < num_to_be_allocated) { + if (num_to_be_allocated == 1) { + ASSERT(!num_alloced); + } else { + DMSG("%s : ENOSPC (requested:%d, alloced:%d)\n", + __func__, num_alloced, + num_to_be_allocated); + } + return -ENOSPC; + } + + if (IS_CLUS_EOF(new_clu.dir) || IS_CLUS_FREE(new_clu.dir)) { + sdfat_fs_error(sb, "bogus cluster new allocated" + "(last_clu : %u, new_clu : %u)", + last_clu, new_clu.dir); + ASSERT(0); + return -EIO; + } + + /* Reserved cluster dec. */ + // XXX: Inode DA flag needed + if (SDFAT_SB(sb)->options.improved_allocation & SDFAT_ALLOC_DELAY) { + BUG_ON(reserved_clusters < num_alloced); + reserved_clusters -= num_alloced; + + } + + /* (2) append to the FAT chain */ + if (IS_CLUS_EOF(last_clu)) { + if (new_clu.flags == 0x01) + fid->flags = 0x01; + fid->start_clu = new_clu.dir; + modified = true; + } else { + if (new_clu.flags != fid->flags) { + /* no-fat-chain bit is disabled, + * so fat-chain should be synced with alloc-bmp + */ + chain_cont_cluster(sb, fid->start_clu, num_clusters); + fid->flags = 0x01; + modified = true; + } + if (new_clu.flags == 0x01) + if (fat_ent_set(sb, last_clu, new_clu.dir)) + return -EIO; + } + + num_clusters += num_alloced; + *clu = new_clu.dir; + + if (fid->dir.dir != DIR_DELETED) { + + if (fsi->vol_type == EXFAT) { + es = get_dentry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); + if (!es) + return -EIO; + /* get stream entry */ + ep++; + } + + /* (3) update directory entry */ + if (modified) { + if (fsi->vol_type != EXFAT) { + ep = get_dentry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + return -EIO; + } + + if (fsi->fs_func->get_entry_flag(ep) != fid->flags) + fsi->fs_func->set_entry_flag(ep, fid->flags); + + if (fsi->fs_func->get_entry_clu0(ep) != fid->start_clu) + fsi->fs_func->set_entry_clu0(ep, fid->start_clu); + + fsi->fs_func->set_entry_size(ep, fid->size); + + if (fsi->vol_type != EXFAT) { + if (dcache_modify(sb, sector)) + return -EIO; + } + } + + if (fsi->vol_type == EXFAT) { + if (update_dir_chksum_with_entry_set(sb, es)) + return -EIO; + release_dentry_set(es); + } + + } /* end of if != DIR_DELETED */ + + + /* add number of new blocks to inode (non-DA only) */ + if (!(SDFAT_SB(sb)->options.improved_allocation & SDFAT_ALLOC_DELAY)) { + inode->i_blocks += num_alloced << (fsi->cluster_size_bits - sb->s_blocksize_bits); + } else { + // DAì˜ ê²½ìš°, i_blocksê°€ ì´ë¯¸ ì¦ê°€í•´ìžˆì–´ì•¼ 함. + BUG_ON(clu_offset >= (inode->i_blocks >> (fsi->cluster_size_bits - sb->s_blocksize_bits))); + } +#if 0 + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + /* (4) Move *clu pointer along FAT chains (hole care) + * because the caller of this function expect *clu to be the last cluster. + * This only works when num_to_be_allocated >= 2, + * *clu = (the first cluster of the allocated chain) => (the last cluster of ...) + */ + if (fid->flags == 0x03) { + *clu += num_to_be_allocated - 1; + } else { + while (num_to_be_allocated > 1) { + if (get_next_clus_safe(sb, clu)) + return -EIO; + num_to_be_allocated--; + } + } + + } + + /* update reserved_clusters */ + fsi->reserved_clusters = reserved_clusters; + + /* hint information */ + fid->hint_bmap.off = local_clu_offset; + fid->hint_bmap.clu = *clu; + + return 0; +} /* end of fscore_map_clus */ + +/* allocate reserved cluster */ +s32 fscore_reserve_clus(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + /* used cluster check */ + if (fsi->used_clusters == (u32) ~0) { + if (fsi->fs_func->count_used_clusters(sb, &fsi->used_clusters)) + return -EIO; + } + + if ((fsi->used_clusters + fsi->reserved_clusters) >= (fsi->num_clusters - 2)) + return -ENOSPC; + + if (bdev_check_bdi_valid(sb)) + return -EIO; + + fsi->reserved_clusters++; + + /* inode->i_blocks update */ + inode->i_blocks += 1 << (fsi->cluster_size_bits - sb->s_blocksize_bits); + + sdfat_debug_check_clusters(inode); + + return 0; +} + +/* remove an entry, BUT don't truncate */ +s32 fscore_unlink(struct inode *inode, FILE_ID_T *fid) +{ + s32 dentry; + CHAIN_T dir; + DENTRY_T *ep; + struct super_block *sb = inode->i_sb; + + dir.dir = fid->dir.dir; + dir.size = fid->dir.size; + dir.flags = fid->dir.flags; + + dentry = fid->entry; + + if (fid->dir.dir == DIR_DELETED) { + EMSG("%s : abnormal access to deleted dentry\n", __func__); + return -ENOENT; + } + + ep = get_dentry_in_dir(sb, &dir, dentry, NULL); + if (!ep) + return -EIO; + +#ifdef CONFIG_SDFAT_CHECK_RO_ATTR + if (SDFAT_SB(sb)->fsi.fs_func->get_entry_attr(ep) & ATTR_READONLY) + return -EPERM; +#endif + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* (1) update the directory entry */ + if (remove_file(inode, &dir, dentry)) + return -EIO; + + /* This doesn't modify fid */ + fid->dir.dir = DIR_DELETED; + + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); + + return 0; +} + +/*----------------------------------------------------------------------*/ +/* Directory Operation Functions */ +/*----------------------------------------------------------------------*/ + +/* create a directory */ +s32 fscore_mkdir(struct inode *inode, u8 *path, FILE_ID_T *fid) +{ + s32 ret/*, dentry*/; + CHAIN_T dir; + UNI_NAME_T uni_name; + struct super_block *sb = inode->i_sb; + + TMSG("%s entered\n", __func__); + + /* check the validity of directory name in the given old pathname */ + ret = resolve_path(inode, path, &dir, &uni_name); + if (ret) + goto out; + + fs_set_vol_flags(sb, VOL_DIRTY); + + ret = create_dir(inode, &dir, &uni_name, fid); + + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +out: + TMSG("%s exited with err(%d)\n", __func__, ret); + return ret; +} + +/* read a directory entry from the opened directory */ +s32 fscore_readdir(struct inode *inode, DIR_ENTRY_T *dir_entry) +{ + s32 i, clu_offset; + s32 dentries_per_clu, dentries_per_clu_bits = 0; + u32 type, sector; + CHAIN_T dir, clu; + UNI_NAME_T uni_name; + TIMESTAMP_T tm; + DENTRY_T *ep; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + FILE_ID_T *fid = &(SDFAT_I(inode)->fid); + s32 dentry = (s32) fid->rwoffset; + + /* check if the given file ID is opened */ + if (fid->type != TYPE_DIR) + return -EPERM; + + if (fid->entry == -1) { + dir.dir = fsi->root_dir; + dir.size = 0; /* just initialize, but will not use */ + dir.flags = 0x01; + } else { + dir.dir = fid->start_clu; + dir.size = (s32)(fid->size >> fsi->cluster_size_bits); + dir.flags = fid->flags; + sdfat_debug_bug_on(dentry >= (dir.size * fsi->dentries_per_clu)); + } + + if (IS_CLUS_FREE(dir.dir)) { /* FAT16 root_dir */ + dentries_per_clu = fsi->dentries_in_root; + + /* Prevent readdir over directory size */ + if (dentry >= dentries_per_clu) { + clu.dir = CLUS_EOF; + } else { + clu.dir = dir.dir; + clu.size = dir.size; + clu.flags = dir.flags; + } + } else { + dentries_per_clu = fsi->dentries_per_clu; + dentries_per_clu_bits = ilog2(dentries_per_clu); + + clu_offset = dentry >> dentries_per_clu_bits; + clu.dir = dir.dir; + clu.size = dir.size; + clu.flags = dir.flags; + + if (clu.flags == 0x03) { + clu.dir += clu_offset; + clu.size -= clu_offset; + } else { + /* hint_information */ + if ((clu_offset > 0) && (fid->hint_bmap.off > 0) && + (clu_offset >= fid->hint_bmap.off)) { + clu_offset -= fid->hint_bmap.off; + clu.dir = fid->hint_bmap.clu; + } + + while (clu_offset > 0) { + if (get_next_clus_safe(sb, &(clu.dir))) + return -EIO; + + clu_offset--; + } + } + } + + while (!IS_CLUS_EOF(clu.dir)) { + if (IS_CLUS_FREE(dir.dir)) /* FAT16 root_dir */ + i = dentry % dentries_per_clu; + else + i = dentry & (dentries_per_clu-1); + + for ( ; i < dentries_per_clu; i++, dentry++) { + ep = get_dentry_in_dir(sb, &clu, i, §or); + if (!ep) + return -EIO; + + type = fsi->fs_func->get_entry_type(ep); + + if (type == TYPE_UNUSED) + break; + + if ((type != TYPE_FILE) && (type != TYPE_DIR)) + continue; + + dcache_lock(sb, sector); + dir_entry->Attr = fsi->fs_func->get_entry_attr(ep); + + fsi->fs_func->get_entry_time(ep, &tm, TM_CREATE); + dir_entry->CreateTimestamp.Year = tm.year; + dir_entry->CreateTimestamp.Month = tm.mon; + dir_entry->CreateTimestamp.Day = tm.day; + dir_entry->CreateTimestamp.Hour = tm.hour; + dir_entry->CreateTimestamp.Minute = tm.min; + dir_entry->CreateTimestamp.Second = tm.sec; + dir_entry->CreateTimestamp.MilliSecond = 0; + + fsi->fs_func->get_entry_time(ep, &tm, TM_MODIFY); + dir_entry->ModifyTimestamp.Year = tm.year; + dir_entry->ModifyTimestamp.Month = tm.mon; + dir_entry->ModifyTimestamp.Day = tm.day; + dir_entry->ModifyTimestamp.Hour = tm.hour; + dir_entry->ModifyTimestamp.Minute = tm.min; + dir_entry->ModifyTimestamp.Second = tm.sec; + dir_entry->ModifyTimestamp.MilliSecond = 0; + + memset((s8 *) &dir_entry->AccessTimestamp, 0, sizeof(DATE_TIME_T)); + + *(uni_name.name) = 0x0; + fsi->fs_func->get_uniname_from_ext_entry(sb, &dir, dentry, uni_name.name); + if (*(uni_name.name) == 0x0) + get_uniname_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x1); + nls_uni16s_to_vfsname(sb, &uni_name, + dir_entry->NameBuf.lfn, + dir_entry->NameBuf.lfnbuf_len); + dcache_unlock(sb, sector); + + if (fsi->vol_type == EXFAT) { + ep = get_dentry_in_dir(sb, &clu, i+1, NULL); + if (!ep) + return -EIO; + } else { + get_uniname_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x0); + nls_uni16s_to_vfsname(sb, &uni_name, + dir_entry->NameBuf.sfn, + dir_entry->NameBuf.sfnbuf_len); + } + + dir_entry->Size = fsi->fs_func->get_entry_size(ep); + + /* + * Update hint information : + * fat16 root directory does not need it. + */ + if (!IS_CLUS_FREE(dir.dir)) { + fid->hint_bmap.off = dentry >> dentries_per_clu_bits; + fid->hint_bmap.clu = clu.dir; + } + + fid->rwoffset = (s64) ++dentry; + + return 0; + } + + /* fat16 root directory */ + if (IS_CLUS_FREE(dir.dir)) + break; + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUS_EOF; + } else { + if (get_next_clus_safe(sb, &(clu.dir))) + return -EIO; + } + } + + dir_entry->NameBuf.lfn[0] = '\0'; + + fid->rwoffset = (s64) dentry; + + return 0; +} /* end of fscore_readdir */ + +/* remove a directory */ +s32 fscore_rmdir(struct inode *inode, FILE_ID_T *fid) +{ + s32 ret; + s32 dentry; + DENTRY_T *ep; + CHAIN_T dir, clu_to_free; + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + dir.dir = fid->dir.dir; + dir.size = fid->dir.size; + dir.flags = fid->dir.flags; + + dentry = fid->entry; + + if (fid->dir.dir == DIR_DELETED) { + EMSG("%s : abnormal access to deleted dentry\n", __func__); + return -ENOENT; + } + + /* check if the file is "." or ".." */ + if (fsi->vol_type != EXFAT) { + if ((dir.dir != fsi->root_dir) && (dentry < 2)) + return -EPERM; + } + + ep = get_dentry_in_dir(sb, &dir, dentry, NULL); + if (!ep) + return -EIO; + +#ifdef CONFIG_SDFAT_CHECK_RO_ATTR + if (SDFAT_SB(sb)->fsi.fs_func->get_entry_attr(ep) & ATTR_READONLY) + return -EPERM; +#endif + + clu_to_free.dir = fid->start_clu; + clu_to_free.size = (s32)((fid->size-1) >> fsi->cluster_size_bits) + 1; + clu_to_free.flags = fid->flags; + + ret = check_dir_empty(sb, &clu_to_free); + if (ret) { + if (ret == -EIO) + EMSG("%s : failed to check_dir_empty : err(%d)\n", + __func__, ret); + return ret; + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* (1) update the directory entry */ + ret = remove_file(inode, &dir, dentry); + if (ret) { + EMSG("%s : failed to remove_file : err(%d)\n", __func__, ret); + return ret; + } + + fid->dir.dir = DIR_DELETED; + + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); + + return ret; +} /* end of fscore_rmdir */ + +/* end of core.c */ diff --git a/fs/sdfat/core.h b/fs/sdfat/core.h new file mode 100644 index 0000000000000..303f02d987210 --- /dev/null +++ b/fs/sdfat/core.h @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _SDFAT_CORE_H +#define _SDFAT_CORE_H + +#include + +#include "config.h" +#include "api.h" +#include "upcase.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------*/ +/* Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ +#define get_next_clus(sb, pclu) fat_ent_get(sb, *(pclu), pclu) +#define get_next_clus_safe(sb, pclu) fat_ent_get_safe(sb, *(pclu), pclu) + +/* file status */ +/* this prevents + * fscore_write_inode, fscore_map_clus, ... with the unlinked inodes + * from corrupting on-disk dentry data. + * + * The fid->dir value of unlinked inode will be DIR_DELETED + * and those functions must check if fid->dir is valid prior to + * the calling of get_dentry_in_dir() + */ +#define DIR_DELETED 0xFFFF0321 + +/*----------------------------------------------------------------------*/ +/* Type Definitions */ +/*----------------------------------------------------------------------*/ +#define ES_2_ENTRIES 2 +#define ES_3_ENTRIES 3 +#define ES_ALL_ENTRIES 0 + +typedef struct { + u32 sector; // sector number that contains file_entry + s32 offset; // byte offset in the sector + s32 alloc_flag; // flag in stream entry. 01 for cluster chain, 03 for contig. clusteres. + u32 num_entries; + // __buf should be the last member + void *__buf; +} ENTRY_SET_CACHE_T; + + + +/*----------------------------------------------------------------------*/ +/* External Function Declarations */ +/*----------------------------------------------------------------------*/ + +/* file system initialization & shutdown functions */ +s32 fscore_init(void); +s32 fscore_shutdown(void); + +/* chain management */ +s32 chain_cont_cluster(struct super_block *sb, u32 chain, s32 len); + +/* volume management functions */ +s32 fscore_mount(struct super_block *sb); +s32 fscore_umount(struct super_block *sb); +s32 fscore_statfs(struct super_block *sb, VOL_INFO_T *info); +s32 fscore_sync_fs(struct super_block *sb, s32 do_sync); +s32 fscore_set_vol_flags(struct super_block *sb, u16 new_flag, s32 always_sync); +u32 fscore_get_au_stat(struct super_block *sb, s32 mode); + +/* file management functions */ +s32 fscore_lookup(struct inode *inode, u8 *path, FILE_ID_T *fid); +s32 fscore_create(struct inode *inode, u8 *path, u8 mode, FILE_ID_T *fid); +s32 fscore_read_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *rcount); +s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *wcount); +s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size); +s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid, + struct inode *new_parent_inode, struct dentry *new_dentry); +s32 fscore_remove(struct inode *inode, FILE_ID_T *fid); +s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info); +s32 fscore_write_inode(struct inode *inode, DIR_ENTRY_T *info, int sync); +s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest); +s32 fscore_reserve_clus(struct inode *inode); +s32 fscore_unlink(struct inode *inode, FILE_ID_T *fid); + +/* directory management functions */ +s32 fscore_mkdir(struct inode *inode, u8 *path, FILE_ID_T *fid); +s32 fscore_readdir(struct inode *inode, DIR_ENTRY_T *dir_ent); +s32 fscore_rmdir(struct inode *inode, FILE_ID_T *fid); + + +/*----------------------------------------------------------------------*/ +/* External Function Declarations (NOT TO UPPER LAYER) */ +/*----------------------------------------------------------------------*/ + +/* core.c : core code for common */ +/* dir entry management functions */ +DENTRY_T *get_dentry_in_dir(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 *sector); + +/* name conversion functions */ +void get_uniname_from_dos_entry(struct super_block *sb, DOS_DENTRY_T *ep, UNI_NAME_T *p_uniname, u8 mode); + +/* file operation functions */ +s32 walk_fat_chain(struct super_block *sb, CHAIN_T *p_dir, s32 byte_offset, u32 *clu); + +/* sdfat/cache.c */ +s32 meta_cache_init(struct super_block *sb); +s32 meta_cache_shutdown(struct super_block *sb); +u8 *fcache_getblk(struct super_block *sb, u32 sec); +s32 fcache_modify(struct super_block *sb, u32 sec); +s32 fcache_release_all(struct super_block *sb); +s32 fcache_flush(struct super_block *sb, u32 sync); + +u8 *dcache_getblk(struct super_block *sb, u32 sec); +s32 dcache_modify(struct super_block *sb, u32 sec); +s32 dcache_lock(struct super_block *sb, u32 sec); +s32 dcache_unlock(struct super_block *sb, u32 sec); +s32 dcache_release(struct super_block *sb, u32 sec); +s32 dcache_release_all(struct super_block *sb); +s32 dcache_flush(struct super_block *sb, u32 sync); +s32 dcache_readahead(struct super_block *sb, u32 sec); + + +/* fatent.c */ +s32 fat_ent_ops_init(struct super_block *sb); +s32 fat_ent_get(struct super_block *sb, u32 loc, u32 *content); +s32 fat_ent_set(struct super_block *sb, u32 loc, u32 content); +s32 fat_ent_get_safe(struct super_block *sb, u32 loc, u32 *content); + +/* core_fat.c : core code for fat */ +s32 fat_generate_dos_name_new(struct super_block *sb, CHAIN_T *p_dir, DOS_NAME_T *p_dosname, s32 n_entries); +s32 mount_fat16(struct super_block *sb, pbr_t *p_pbr); +s32 mount_fat32(struct super_block *sb, pbr_t *p_pbr); + +/* core_exfat.c : core code for exfat */ + +s32 load_alloc_bmp(struct super_block *sb); +void free_alloc_bmp(struct super_block *sb); +ENTRY_SET_CACHE_T *get_dentry_set_in_dir(struct super_block *sb, + CHAIN_T *p_dir, s32 entry, u32 type, DENTRY_T **file_ep); +void release_dentry_set(ENTRY_SET_CACHE_T *es); +s32 update_dir_chksum(struct super_block *sb, CHAIN_T *p_dir, s32 entry); +s32 update_dir_chksum_with_entry_set(struct super_block *sb, ENTRY_SET_CACHE_T *es); +bool is_dir_empty(struct super_block *sb, CHAIN_T *p_dir); +s32 mount_exfat(struct super_block *sb, pbr_t *p_pbr); + +/* amap_smart.c : creation on mount / destroy on umount */ +int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hidden_sect); +void amap_destroy(struct super_block *sb); + +/* amap_smart.c : (de)allocation functions */ +s32 amap_fat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p_chain, int dest); +s32 amap_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_relse);/* Not impelmented */ +s32 amap_release_cluster(struct super_block *sb, u32 clu); /* Only update AMAP */ + +/* amap_smart.c : misc (for defrag) */ +s32 amap_mark_ignore(struct super_block *sb, u32 clu); +s32 amap_unmark_ignore(struct super_block *sb, u32 clu); +s32 amap_unmark_ignore_all(struct super_block *sb); +s32 amap_check_working(struct super_block *sb, u32 clu); +s32 amap_get_freeclus(struct super_block *sb, u32 clu); + +/* amap_smart.c : stat AU */ +u32 amap_get_au_stat(struct super_block *sb, s32 mode); + + +/* blkdev.c */ +s32 bdev_open_dev(struct super_block *sb); +s32 bdev_close_dev(struct super_block *sb); +s32 bdev_check_bdi_valid(struct super_block *sb); +s32 bdev_readahead(struct super_block *sb, u32 secno, u32 num_secs); +s32 bdev_mread(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 num_secs, s32 read); +s32 bdev_mwrite(struct super_block *sb, u32 secno, struct buffer_head *bh, u32 num_secs, s32 sync); +s32 bdev_sync_all(struct super_block *sb); + +/* blkdev.c : sector read/write functions */ +s32 read_sect(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 read); +s32 write_sect(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 sync); +s32 read_msect(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 num_secs, s32 read); +s32 write_msect(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 num_secs, s32 sync); +s32 write_msect_zero(struct super_block *sb, u32 sec, s32 num_secs); + +/* misc.c */ +u8 calc_chksum_1byte(void *data, s32 len, u8 chksum); +u16 calc_chksum_2byte(void *data, s32 len, u16 chksum, s32 type); + +/* extent.c */ +s32 extent_cache_init(void); +void extent_cache_shutdown(void); +void extent_cache_init_inode(struct inode *inode); +void extent_cache_inval_inode(struct inode *inode); +s32 extent_get_clus(struct inode *inode, s32 cluster, s32 *fclus, + u32 *dclus, u32 *last_dclus, s32 allow_eof); +/*----------------------------------------------------------------------*/ +/* Wrapper Function */ +/*----------------------------------------------------------------------*/ +void set_sb_dirty(struct super_block *sb); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _SDFAT_CORE_H */ + +/* end of core.h */ diff --git a/fs/sdfat/core_exfat.c b/fs/sdfat/core_exfat.c new file mode 100644 index 0000000000000..f88c488f10b8b --- /dev/null +++ b/fs/sdfat/core_exfat.c @@ -0,0 +1,1533 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : core_exfat.c */ +/* PURPOSE : exFAT-fs core code for sdFAT */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/* */ +/************************************************************************/ + +#include +#include +#include +#include +#include + +#include "sdfat.h" +#include "core.h" +#include +#include + +/*----------------------------------------------------------------------*/ +/* Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ +static u8 free_bit[] = { + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,/* 0 ~ 19*/ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3,/* 20 ~ 39*/ + 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/* 40 ~ 59*/ + 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,/* 60 ~ 79*/ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2,/* 80 ~ 99*/ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3,/*100 ~ 119*/ + 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/*120 ~ 139*/ + 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,/*140 ~ 159*/ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,/*160 ~ 179*/ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3,/*180 ~ 199*/ + 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/*200 ~ 219*/ + 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,/*220 ~ 239*/ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /*240 ~ 254*/ +}; + +static u8 used_bit[] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3,/* 0 ~ 19*/ + 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4,/* 20 ~ 39*/ + 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,/* 40 ~ 59*/ + 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,/* 60 ~ 79*/ + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,/* 80 ~ 99*/ + 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,/*100 ~ 119*/ + 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,/*120 ~ 139*/ + 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,/*140 ~ 159*/ + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5,/*160 ~ 179*/ + 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,/*180 ~ 199*/ + 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,/*200 ~ 219*/ + 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,/*220 ~ 239*/ + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 /*240 ~ 255*/ +}; + + +/*======================================================================*/ +/* Local Function Definitions */ +/*======================================================================*/ +/* + * Directory Entry Management Functions + */ +static u32 exfat_get_entry_type(DENTRY_T *p_entry) +{ + FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry; + + if (ep->type == EXFAT_UNUSED) + return TYPE_UNUSED; + if (ep->type < 0x80) + return TYPE_DELETED; + if (ep->type == 0x80) + return TYPE_INVALID; + if (ep->type < 0xA0) { + if (ep->type == 0x81) + return TYPE_BITMAP; + if (ep->type == 0x82) + return TYPE_UPCASE; + if (ep->type == 0x83) + return TYPE_VOLUME; + if (ep->type == 0x85) { + if (le16_to_cpu(ep->attr) & ATTR_SUBDIR) + return TYPE_DIR; + return TYPE_FILE; + } + return TYPE_CRITICAL_PRI; + } + if (ep->type < 0xC0) { + if (ep->type == 0xA0) + return TYPE_GUID; + if (ep->type == 0xA1) + return TYPE_PADDING; + if (ep->type == 0xA2) + return TYPE_ACLTAB; + return TYPE_BENIGN_PRI; + } + if (ep->type < 0xE0) { + if (ep->type == 0xC0) + return TYPE_STREAM; + if (ep->type == 0xC1) + return TYPE_EXTEND; + if (ep->type == 0xC2) + return TYPE_ACL; + return TYPE_CRITICAL_SEC; + } + return TYPE_BENIGN_SEC; +} /* end of exfat_get_entry_type */ + +static void exfat_set_entry_type(DENTRY_T *p_entry, u32 type) +{ + FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry; + + if (type == TYPE_UNUSED) { + ep->type = 0x0; + } else if (type == TYPE_DELETED) { + ep->type &= ~0x80; + } else if (type == TYPE_STREAM) { + ep->type = 0xC0; + } else if (type == TYPE_EXTEND) { + ep->type = 0xC1; + } else if (type == TYPE_BITMAP) { + ep->type = 0x81; + } else if (type == TYPE_UPCASE) { + ep->type = 0x82; + } else if (type == TYPE_VOLUME) { + ep->type = 0x83; + } else if (type == TYPE_DIR) { + ep->type = 0x85; + ep->attr = cpu_to_le16(ATTR_SUBDIR); + } else if (type == TYPE_FILE) { + ep->type = 0x85; + ep->attr = cpu_to_le16(ATTR_ARCHIVE); + } else if (type == TYPE_SYMLINK) { + ep->type = 0x85; + ep->attr = cpu_to_le16(ATTR_ARCHIVE | ATTR_SYMLINK); + } +} /* end of exfat_set_entry_type */ + +static u32 exfat_get_entry_attr(DENTRY_T *p_entry) +{ + FILE_DENTRY_T *ep = (FILE_DENTRY_T *)p_entry; + + return (u32)le16_to_cpu(ep->attr); +} /* end of exfat_get_entry_attr */ + +static void exfat_set_entry_attr(DENTRY_T *p_entry, u32 attr) +{ + FILE_DENTRY_T *ep = (FILE_DENTRY_T *)p_entry; + + ep->attr = cpu_to_le16((u16) attr); +} /* end of exfat_set_entry_attr */ + +static u8 exfat_get_entry_flag(DENTRY_T *p_entry) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *)p_entry; + + return ep->flags; +} /* end of exfat_get_entry_flag */ + +static void exfat_set_entry_flag(DENTRY_T *p_entry, u8 flags) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *)p_entry; + + ep->flags = flags; +} /* end of exfat_set_entry_flag */ + +static u32 exfat_get_entry_clu0(DENTRY_T *p_entry) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *)p_entry; + + return (u32)le32_to_cpu(ep->start_clu); +} /* end of exfat_get_entry_clu0 */ + +static void exfat_set_entry_clu0(DENTRY_T *p_entry, u32 start_clu) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *)p_entry; + + ep->start_clu = cpu_to_le32(start_clu); +} /* end of exfat_set_entry_clu0 */ + +static u64 exfat_get_entry_size(DENTRY_T *p_entry) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *)p_entry; + + return le64_to_cpu(ep->valid_size); +} /* end of exfat_get_entry_size */ + +static void exfat_set_entry_size(DENTRY_T *p_entry, u64 size) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *)p_entry; + + ep->valid_size = cpu_to_le64(size); + ep->size = cpu_to_le64(size); +} /* end of exfat_set_entry_size */ + +static void exfat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, u8 mode) +{ + u16 t = 0x00, d = 0x21; + FILE_DENTRY_T *ep = (FILE_DENTRY_T *)p_entry; + + switch (mode) { + case TM_CREATE: + t = le16_to_cpu(ep->create_time); + d = le16_to_cpu(ep->create_date); + break; + case TM_MODIFY: + t = le16_to_cpu(ep->modify_time); + d = le16_to_cpu(ep->modify_date); + break; + case TM_ACCESS: + t = le16_to_cpu(ep->access_time); + d = le16_to_cpu(ep->access_date); + break; + } + + tp->sec = (t & 0x001F) << 1; + tp->min = (t >> 5) & 0x003F; + tp->hour = (t >> 11); + tp->day = (d & 0x001F); + tp->mon = (d >> 5) & 0x000F; + tp->year = (d >> 9); +} /* end of exfat_get_entry_time */ + +static void exfat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, u8 mode) +{ + u16 t, d; + FILE_DENTRY_T *ep = (FILE_DENTRY_T *)p_entry; + + t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1); + d = (tp->year << 9) | (tp->mon << 5) | tp->day; + + switch (mode) { + case TM_CREATE: + ep->create_time = cpu_to_le16(t); + ep->create_date = cpu_to_le16(d); + break; + case TM_MODIFY: + ep->modify_time = cpu_to_le16(t); + ep->modify_date = cpu_to_le16(d); + break; + case TM_ACCESS: + ep->access_time = cpu_to_le16(t); + ep->access_date = cpu_to_le16(d); + break; + } +} /* end of exfat_set_entry_time */ + + +static void __init_file_entry(struct super_block *sb, FILE_DENTRY_T *ep, u32 type) +{ + TIMESTAMP_T tm, *tp; + + exfat_set_entry_type((DENTRY_T *) ep, type); + + tp = tm_now(SDFAT_SB(sb), &tm); + exfat_set_entry_time((DENTRY_T *) ep, tp, TM_CREATE); + exfat_set_entry_time((DENTRY_T *) ep, tp, TM_MODIFY); + exfat_set_entry_time((DENTRY_T *) ep, tp, TM_ACCESS); + ep->create_time_ms = 0; + ep->modify_time_ms = 0; + ep->access_time_ms = 0; +} /* end of __init_file_entry */ + +static void __init_strm_entry(STRM_DENTRY_T *ep, u8 flags, u32 start_clu, u64 size) +{ + exfat_set_entry_type((DENTRY_T *) ep, TYPE_STREAM); + ep->flags = flags; + ep->start_clu = cpu_to_le32(start_clu); + ep->valid_size = cpu_to_le64(size); + ep->size = cpu_to_le64(size); +} /* end of __init_strm_entry */ + +static void __init_name_entry(NAME_DENTRY_T *ep, u16 *uniname) +{ + s32 i; + + exfat_set_entry_type((DENTRY_T *) ep, TYPE_EXTEND); + ep->flags = 0x0; + + for (i = 0; i < 15; i++) { + ep->unicode_0_14[i] = cpu_to_le16(*uniname); + if (*uniname == 0x0) + break; + uniname++; + } +} /* end of __init_name_entry */ + +static s32 exfat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 type, u32 start_clu, u64 size) +{ + u32 sector; + u8 flags; + FILE_DENTRY_T *file_ep; + STRM_DENTRY_T *strm_ep; + + flags = (type == TYPE_FILE) ? 0x01 : 0x03; + + /* we cannot use get_dentry_set_in_dir here because file ep is not initialized yet */ + file_ep = (FILE_DENTRY_T *)get_dentry_in_dir(sb, p_dir, entry, §or); + if (!file_ep) + return -EIO; + + strm_ep = (STRM_DENTRY_T *)get_dentry_in_dir(sb, p_dir, entry+1, §or); + if (!strm_ep) + return -EIO; + + __init_file_entry(sb, file_ep, type); + if (dcache_modify(sb, sector)) + return -EIO; + + __init_strm_entry(strm_ep, flags, start_clu, size); + if (dcache_modify(sb, sector)) + return -EIO; + + return 0; +} /* end of exfat_init_dir_entry */ + +s32 update_dir_chksum(struct super_block *sb, CHAIN_T *p_dir, s32 entry) +{ + s32 ret = -EIO; + s32 i, num_entries; + u32 sector; + u16 chksum; + FILE_DENTRY_T *file_ep; + DENTRY_T *ep; + + file_ep = (FILE_DENTRY_T *)get_dentry_in_dir(sb, p_dir, entry, §or); + if (!file_ep) + return -EIO; + + dcache_lock(sb, sector); + + num_entries = (s32) file_ep->num_ext + 1; + chksum = calc_chksum_2byte((void *) file_ep, DENTRY_SIZE, 0, CS_DIR_ENTRY); + + for (i = 1; i < num_entries; i++) { + ep = get_dentry_in_dir(sb, p_dir, entry+i, NULL); + if (!ep) + goto out_unlock; + + chksum = calc_chksum_2byte((void *) ep, DENTRY_SIZE, chksum, CS_DEFAULT); + } + + file_ep->checksum = cpu_to_le16(chksum); + ret = dcache_modify(sb, sector); +out_unlock: + dcache_unlock(sb, sector); + return ret; + +} /* end of update_dir_chksum */ + + +static s32 exfat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32 num_entries, + UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname) +{ + s32 i; + u32 sector; + u16 *uniname = p_uniname->name; + FILE_DENTRY_T *file_ep; + STRM_DENTRY_T *strm_ep; + NAME_DENTRY_T *name_ep; + + file_ep = (FILE_DENTRY_T *)get_dentry_in_dir(sb, p_dir, entry, §or); + if (!file_ep) + return -EIO; + + file_ep->num_ext = (u8)(num_entries - 1); + dcache_modify(sb, sector); + + strm_ep = (STRM_DENTRY_T *)get_dentry_in_dir(sb, p_dir, entry+1, §or); + if (!strm_ep) + return -EIO; + + strm_ep->name_len = p_uniname->name_len; + strm_ep->name_hash = cpu_to_le16(p_uniname->name_hash); + dcache_modify(sb, sector); + + for (i = 2; i < num_entries; i++) { + name_ep = (NAME_DENTRY_T *)get_dentry_in_dir(sb, p_dir, entry+i, §or); + if (!name_ep) + return -EIO; + + __init_name_entry(name_ep, uniname); + dcache_modify(sb, sector); + uniname += 15; + } + + update_dir_chksum(sb, p_dir, entry); + + return 0; +} /* end of exfat_init_ext_entry */ + + +static s32 exfat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32 order, s32 num_entries) +{ + s32 i; + u32 sector; + DENTRY_T *ep; + + for (i = order; i < num_entries; i++) { + ep = get_dentry_in_dir(sb, p_dir, entry+i, §or); + if (!ep) + return -EIO; + + exfat_set_entry_type(ep, TYPE_DELETED); + if (dcache_modify(sb, sector)) + return -EIO; + } + + return 0; +} + +static s32 __write_partial_entries_in_entry_set(struct super_block *sb, + ENTRY_SET_CACHE_T *es, u32 sec, s32 off, u32 count) +{ + s32 num_entries, buf_off = (off - es->offset); + u32 remaining_byte_in_sector, copy_entries; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + u32 clu; + u8 *buf, *esbuf = (u8 *)&(es->__buf); + + TMSG("%s entered\n", __func__); + MMSG("%s: es %p sec %u off %d cnt %d\n", __func__, es, sec, off, count); + num_entries = count; + + while (num_entries) { + /* write per sector base */ + remaining_byte_in_sector = (1 << sb->s_blocksize_bits) - off; + copy_entries = min((s32)(remaining_byte_in_sector >> DENTRY_SIZE_BITS), num_entries); + buf = dcache_getblk(sb, sec); + if (!buf) + goto err_out; + MMSG("es->buf %p buf_off %u\n", esbuf, buf_off); + MMSG("copying %d entries from %p to sector %u\n", copy_entries, (esbuf + buf_off), sec); + memcpy(buf + off, esbuf + buf_off, copy_entries << DENTRY_SIZE_BITS); + dcache_modify(sb, sec); + num_entries -= copy_entries; + + if (num_entries) { + // get next sector + if (IS_LAST_SECT_IN_CLUS(fsi, sec)) { + clu = SECT_TO_CLUS(fsi, sec); + if (es->alloc_flag == 0x03) + clu++; + else if (get_next_clus_safe(sb, &clu)) + goto err_out; + sec = CLUS_TO_SECT(fsi, clu); + } else { + sec++; + } + off = 0; + buf_off += copy_entries << DENTRY_SIZE_BITS; + } + } + + TMSG("%s exited successfully\n", __func__); + return 0; +err_out: + TMSG("%s failed\n", __func__); + return -EIO; +} + +/* write back all entries in entry set */ +static s32 __write_whole_entry_set(struct super_block *sb, ENTRY_SET_CACHE_T *es) +{ + return __write_partial_entries_in_entry_set(sb, es, es->sector, es->offset, es->num_entries); +} + +s32 update_dir_chksum_with_entry_set(struct super_block *sb, ENTRY_SET_CACHE_T *es) +{ + DENTRY_T *ep; + u16 chksum = 0; + s32 chksum_type = CS_DIR_ENTRY, i; + + ep = (DENTRY_T *)&(es->__buf); + for (i = 0; i < es->num_entries; i++) { + MMSG("%s %p\n", __func__, ep); + chksum = calc_chksum_2byte((void *) ep, DENTRY_SIZE, chksum, chksum_type); + ep++; + chksum_type = CS_DEFAULT; + } + + ep = (DENTRY_T *)&(es->__buf); + ((FILE_DENTRY_T *)ep)->checksum = cpu_to_le16(chksum); + return __write_whole_entry_set(sb, es); +} + +/* returns a set of dentries for a file or dir. + * Note that this is a copy (dump) of dentries so that user should call write_entry_set() + * to apply changes made in this entry set to the real device. + * in: + * sb+p_dir+entry: indicates a file/dir + * type: specifies how many dentries should be included. + * out: + * file_ep: will point the first dentry(= file dentry) on success + * return: + * pointer of entry set on success, + * NULL on failure. + */ + +#define ES_MODE_STARTED 0 +#define ES_MODE_GET_FILE_ENTRY 1 +#define ES_MODE_GET_STRM_ENTRY 2 +#define ES_MODE_GET_NAME_ENTRY 3 +#define ES_MODE_GET_CRITICAL_SEC_ENTRY 4 +ENTRY_SET_CACHE_T *get_dentry_set_in_dir(struct super_block *sb, + CHAIN_T *p_dir, s32 entry, u32 type, DENTRY_T **file_ep) +{ + s32 off, ret, byte_offset; + u32 clu = 0; + u32 sec, entry_type; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + ENTRY_SET_CACHE_T *es = NULL; + DENTRY_T *ep, *pos; + u8 *buf; + u8 num_entries; + s32 mode = ES_MODE_STARTED; + + /* FIXME : is available in error case? */ + if (p_dir->dir == DIR_DELETED) { + EMSG("%s : access to deleted dentry\n", __func__); + BUG_ON(!fsi->prev_eio); + return NULL; + } + + TMSG("%s entered\n", __func__); + MMSG("p_dir dir %u flags %x size %d\n", p_dir->dir, p_dir->flags, p_dir->size); + MMSG("entry %d type %d\n", entry, type); + + byte_offset = entry << DENTRY_SIZE_BITS; + ret = walk_fat_chain(sb, p_dir, byte_offset, &clu); + if (ret) + return NULL; + + /* byte offset in cluster */ + byte_offset &= fsi->cluster_size - 1; + + /* byte offset in sector */ + off = byte_offset & (u32)(sb->s_blocksize - 1); + + /* sector offset in cluster */ + sec = byte_offset >> (sb->s_blocksize_bits); + sec += CLUS_TO_SECT(fsi, clu); + + buf = dcache_getblk(sb, sec); + if (!buf) + goto err_out; + + ep = (DENTRY_T *)(buf + off); + entry_type = exfat_get_entry_type(ep); + + if ((entry_type != TYPE_FILE) + && (entry_type != TYPE_DIR)) + goto err_out; + + if (type == ES_ALL_ENTRIES) + num_entries = ((FILE_DENTRY_T *)ep)->num_ext+1; + else + num_entries = type; + + MMSG("trying to malloc %lx bytes for %d entries\n", + (unsigned long)(offsetof(ENTRY_SET_CACHE_T, __buf) + (num_entries) * sizeof(DENTRY_T)), num_entries); + es = kmalloc((offsetof(ENTRY_SET_CACHE_T, __buf) + (num_entries) * sizeof(DENTRY_T)), GFP_KERNEL); + if (!es) { + EMSG("%s: failed to alloc entryset\n", __func__); + goto err_out; + } + + es->num_entries = num_entries; + es->sector = sec; + es->offset = off; + es->alloc_flag = p_dir->flags; + + pos = (DENTRY_T *) &(es->__buf); + + while (num_entries) { + // instead of copying whole sector, we will check every entry. + // this will provide minimum stablity and consistency. + entry_type = exfat_get_entry_type(ep); + + if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) + goto err_out; + + switch (mode) { + case ES_MODE_STARTED: + if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) + mode = ES_MODE_GET_FILE_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_FILE_ENTRY: + if (entry_type == TYPE_STREAM) + mode = ES_MODE_GET_STRM_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_STRM_ENTRY: + if (entry_type == TYPE_EXTEND) + mode = ES_MODE_GET_NAME_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_NAME_ENTRY: + if (entry_type == TYPE_EXTEND) + break; + else if (entry_type == TYPE_STREAM) + goto err_out; + else if (entry_type & TYPE_CRITICAL_SEC) + mode = ES_MODE_GET_CRITICAL_SEC_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_CRITICAL_SEC_ENTRY: + if ((entry_type == TYPE_EXTEND) || (entry_type == TYPE_STREAM)) + goto err_out; + else if ((entry_type & TYPE_CRITICAL_SEC) != TYPE_CRITICAL_SEC) + goto err_out; + break; + } + + /* copy dentry */ + memcpy(pos, ep, sizeof(DENTRY_T)); + + if (--num_entries == 0) + break; + + if (((off + DENTRY_SIZE) & (u32)(sb->s_blocksize - 1)) < + (off & (u32)(sb->s_blocksize - 1))) { + // get the next sector + if (IS_LAST_SECT_IN_CLUS(fsi, sec)) { + if (es->alloc_flag == 0x03) + clu++; + else if (get_next_clus_safe(sb, &clu)) + goto err_out; + sec = CLUS_TO_SECT(fsi, clu); + } else { + sec++; + } + buf = dcache_getblk(sb, sec); + if (!buf) + goto err_out; + off = 0; + ep = (DENTRY_T *)(buf); + } else { + ep++; + off += DENTRY_SIZE; + } + pos++; + } + + if (file_ep) + *file_ep = (DENTRY_T *)&(es->__buf); + + MMSG("es sec %u offset %d flags %d, num_entries %u buf ptr %p\n", + es->sector, es->offset, es->alloc_flag, es->num_entries, &(es->__buf)); + TMSG("%s exited %p\n", __func__, es); + return es; +err_out: + TMSG("%s exited (return NULL) (es %p)\n", __func__, es); + + /* kfree(NULL) is safe */ + kfree(es); + es = NULL; + return NULL; +} + +void release_dentry_set(ENTRY_SET_CACHE_T *es) +{ + TMSG("%s %p\n", __func__, es); + + /* kfree(NULL) is safe */ + kfree(es); + es = NULL; +} + +static s32 __extract_uni_name_from_name_entry(NAME_DENTRY_T *ep, u16 *uniname, s32 order) +{ + s32 i, len = 0; + + for (i = 0; i < 15; i++) { + /* FIXME : unaligned? */ + *uniname = le16_to_cpu(ep->unicode_0_14[i]); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + + *uniname = 0x0; + return len; +} /* end of __extract_uni_name_from_name_entry */ + +#define DIRENT_STEP_FILE (0) +#define DIRENT_STEP_STRM (1) +#define DIRENT_STEP_NAME (2) +#define DIRENT_STEP_SECD (3) + +/* return values of exfat_find_dir_entry() + * >= 0 : return dir entiry position with the name in dir + * -EEXIST : (root dir, ".") it is the root dir itself + * -ENOENT : entry with the name does not exist + * -EIO : I/O error + */ +static s32 exfat_find_dir_entry(struct super_block *sb, FILE_ID_T *fid, + CHAIN_T *p_dir, UNI_NAME_T *p_uniname, s32 num_entries, DOS_NAME_T *unused, u32 type) +{ + s32 i, rewind = 0, dentry = 0, end_eidx = 0, num_ext = 0, len; + s32 order, step, name_len; + s32 dentries_per_clu, num_empty = 0; + u32 entry_type; + u16 entry_uniname[16], *uniname = NULL, unichar; + CHAIN_T clu; + DENTRY_T *ep; + HINT_T *hint_stat = &fid->hint_stat; + HINT_FEMP_T candi_empty; + FILE_DENTRY_T *file_ep; + STRM_DENTRY_T *strm_ep; + NAME_DENTRY_T *name_ep; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + /* + * REMARK: + * DOT and DOTDOT are handled by VFS layer + */ + + if (IS_CLUS_FREE(p_dir->dir)) + return -EIO; + + dentries_per_clu = fsi->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + if (hint_stat->eidx) { + clu.dir = hint_stat->clu; + dentry = hint_stat->eidx; + end_eidx = dentry; + } + + candi_empty.eidx = -1; +rewind: + order = 0; + step = DIRENT_STEP_FILE; + while (!IS_CLUS_EOF(clu.dir)) { + i = dentry & (dentries_per_clu - 1); + for (; i < dentries_per_clu; i++, dentry++) { + if (rewind && (dentry == end_eidx)) + goto not_found; + + ep = get_dentry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -EIO; + + entry_type = exfat_get_entry_type(ep); + + if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) { + step = DIRENT_STEP_FILE; + + num_empty++; + if (candi_empty.eidx == -1) { + if (num_empty == 1) { + candi_empty.cur.dir = clu.dir; + candi_empty.cur.size = clu.size; + candi_empty.cur.flags = clu.flags; + } + + if (num_empty >= num_entries) { + candi_empty.eidx = dentry - (num_empty - 1); + ASSERT(0 <= candi_empty.eidx); + candi_empty.count = num_empty; + + if ((fid->hint_femp.eidx == -1) || + (candi_empty.eidx <= fid->hint_femp.eidx)) { + memcpy(&fid->hint_femp, + &candi_empty, + sizeof(HINT_FEMP_T)); + } + } + } + + if (entry_type == TYPE_UNUSED) + goto not_found; + continue; + } + + num_empty = 0; + candi_empty.eidx = -1; + + if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) { + step = DIRENT_STEP_FILE; + if ((type == TYPE_ALL) || (type == entry_type)) { + file_ep = (FILE_DENTRY_T *) ep; + num_ext = file_ep->num_ext; + step = DIRENT_STEP_STRM; + } + continue; + } + + if (entry_type == TYPE_STREAM) { + if (step != DIRENT_STEP_STRM) { + step = DIRENT_STEP_FILE; + continue; + } + step = DIRENT_STEP_FILE; + strm_ep = (STRM_DENTRY_T *) ep; + if ((p_uniname->name_hash == le16_to_cpu(strm_ep->name_hash)) && + (p_uniname->name_len == strm_ep->name_len)) { + step = DIRENT_STEP_NAME; + order = 1; + name_len = 0; + } + continue; + } + + if (entry_type == TYPE_EXTEND) { + if (step != DIRENT_STEP_NAME) { + step = DIRENT_STEP_FILE; + continue; + } + name_ep = (NAME_DENTRY_T *) ep; + + if ((++order) == 2) + uniname = p_uniname->name; + else + uniname += 15; + + len = __extract_uni_name_from_name_entry(name_ep, entry_uniname, order); + name_len += len; + + unichar = *(uniname+len); + *(uniname+len) = 0x0; + + if (nls_cmp_uniname(sb, uniname, entry_uniname)) { + step = DIRENT_STEP_FILE; + } else if (name_len == p_uniname->name_len) { + if (order == num_ext) { + //fid->hint_femp.eidx = -1; + goto found; + } + step = DIRENT_STEP_SECD; + } + + *(uniname+len) = unichar; + continue; + } + + if (entry_type & (TYPE_CRITICAL_SEC | TYPE_BENIGN_SEC)) { + if (step == DIRENT_STEP_SECD) { + if (++order == num_ext) + goto found; + continue; + } + } + step = DIRENT_STEP_FILE; + } + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUS_EOF; + } else { + if (get_next_clus_safe(sb, &clu.dir)) + return -EIO; + } + } + +not_found: + /* we started at not 0 index,so we should try to find target + * from 0 index to the index we started at. + */ + if (!rewind && end_eidx) { + rewind = 1; + dentry = 0; + clu.dir = p_dir->dir; + /* reset empty hint */ + num_empty = 0; + candi_empty.eidx = -1; + goto rewind; + } + + /* initialized hint_stat */ + hint_stat->clu = p_dir->dir; + hint_stat->eidx = 0; + return -ENOENT; + +found: + /* next dentry we'll find is out of this cluster */ + if (!((dentry + 1) & (dentries_per_clu-1))) { + int ret = 0; + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUS_EOF; + } else { + ret = get_next_clus_safe(sb, &clu.dir); + } + + if (ret || IS_CLUS_EOF(clu.dir)) { + /* just initialized hint_stat */ + hint_stat->clu = p_dir->dir; + hint_stat->eidx = 0; + return (dentry - num_ext); + } + } + + hint_stat->clu = clu.dir; + hint_stat->eidx = dentry + 1; + return (dentry - num_ext); +} /* end of exfat_find_dir_entry */ + +/* returns -EIO on error */ +static s32 exfat_count_ext_entries(struct super_block *sb, CHAIN_T *p_dir, s32 entry, DENTRY_T *p_entry) +{ + s32 i, count = 0; + u32 type; + FILE_DENTRY_T *file_ep = (FILE_DENTRY_T *) p_entry; + DENTRY_T *ext_ep; + + for (i = 0, entry++; i < file_ep->num_ext; i++, entry++) { + ext_ep = get_dentry_in_dir(sb, p_dir, entry, NULL); + if (!ext_ep) + return -EIO; + + type = exfat_get_entry_type(ext_ep); + if ((type == TYPE_EXTEND) || (type == TYPE_STREAM)) + count++; + else + return count; + } + + return count; +} /* end of exfat_count_ext_entries */ + + +/* + * Name Conversion Functions + */ +static void exfat_get_uniname_from_ext_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u16 *uniname) +{ + s32 i; + DENTRY_T *ep; + ENTRY_SET_CACHE_T *es; + + es = get_dentry_set_in_dir(sb, p_dir, entry, ES_ALL_ENTRIES, &ep); + if (!es) + return; + + if (es->num_entries < 3) + goto out; + + ep += 2; + + /* + * First entry : file entry + * Second entry : stream-extension entry + * Third entry : first file-name entry + * So, the index of first file-name dentry should start from 2. + */ + for (i = 2; i < es->num_entries; i++, ep++) { + /* end of name entry */ + if (exfat_get_entry_type(ep) != TYPE_EXTEND) + goto out; + + __extract_uni_name_from_name_entry((NAME_DENTRY_T *)ep, uniname, i); + uniname += 15; + } + +out: + release_dentry_set(es); +} /* end of exfat_get_uniname_from_ext_entry */ + +static s32 exfat_calc_num_entries(UNI_NAME_T *p_uniname) +{ + s32 len; + + len = p_uniname->name_len; + if (len == 0) + return 0; + + /* 1 file entry + 1 stream entry + name entries */ + return((len-1) / 15 + 3); + +} /* end of exfat_calc_num_entries */ + +static s32 exfat_check_max_dentries(FILE_ID_T *fid) +{ + if ((fid->size >> DENTRY_SIZE_BITS) >= MAX_EXFAT_DENTRIES) { + /* exFAT spec allows a dir to grow upto 8388608(256MB) dentries */ + return -ENOSPC; + } + return 0; +} /* end of check_max_dentries */ + + +/* + * Allocation Bitmap Management Functions + */ +s32 load_alloc_bmp(struct super_block *sb) +{ + s32 i, j, ret; + u32 map_size, need_map_size; + u32 type, sector; + CHAIN_T clu; + BMAP_DENTRY_T *ep; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + clu.dir = fsi->root_dir; + clu.flags = 0x01; + + while (!IS_CLUS_EOF(clu.dir)) { + for (i = 0; i < fsi->dentries_per_clu; i++) { + ep = (BMAP_DENTRY_T *) get_dentry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -EIO; + + type = exfat_get_entry_type((DENTRY_T *) ep); + + if (type == TYPE_UNUSED) + break; + if (type != TYPE_BITMAP) + continue; + + if (ep->flags == 0x0) { + fsi->map_clu = le32_to_cpu(ep->start_clu); + map_size = (u32) le64_to_cpu(ep->size); + + need_map_size = (((fsi->num_clusters - CLUS_BASE) - 1) >> 3) + 1; + if (need_map_size != map_size) { + sdfat_log_msg(sb, KERN_ERR, + "bogus allocation bitmap size(need : %u, cur : %u)", + need_map_size, map_size); + /* Only allowed when bogus allocation bitmap size is large */ + if (need_map_size > map_size) + return -EIO; + } + fsi->map_sectors = ((need_map_size - 1) >> (sb->s_blocksize_bits)) + 1; + fsi->vol_amap = + kmalloc((sizeof(struct buffer_head *) * fsi->map_sectors), GFP_KERNEL); + if (!fsi->vol_amap) + return -ENOMEM; + + sector = CLUS_TO_SECT(fsi, fsi->map_clu); + + for (j = 0; j < fsi->map_sectors; j++) { + fsi->vol_amap[j] = NULL; + ret = read_sect(sb, sector+j, &(fsi->vol_amap[j]), 1); + if (ret) { + /* release all buffers and free vol_amap */ + i = 0; + while (i < j) + brelse(fsi->vol_amap[i++]); + + /* kfree(NULL) is safe */ + kfree(fsi->vol_amap); + fsi->vol_amap = NULL; + return ret; + } + } + + fsi->pbr_bh = NULL; + return 0; + } + } + + if (get_next_clus_safe(sb, &clu.dir)) + return -EIO; + } + + return -EINVAL; +} /* end of load_alloc_bmp */ + +void free_alloc_bmp(struct super_block *sb) +{ + s32 i; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + brelse(fsi->pbr_bh); + + for (i = 0; i < fsi->map_sectors; i++) + __brelse(fsi->vol_amap[i]); + + /* kfree(NULL) is safe */ + kfree(fsi->vol_amap); + fsi->vol_amap = NULL; +} + +/* WARN : + * If the value of "clu" is 0, it means cluster 2 which is + * the first cluster of cluster heap. + */ +static s32 set_alloc_bitmap(struct super_block *sb, u32 clu) +{ + s32 i, b; + u32 sector; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + i = clu >> (sb->s_blocksize_bits + 3); + b = clu & (u32)((sb->s_blocksize << 3) - 1); + + sector = CLUS_TO_SECT(fsi, fsi->map_clu) + i; + bitmap_set((unsigned long *)(fsi->vol_amap[i]->b_data), b, 1); + + return write_sect(sb, sector, fsi->vol_amap[i], 0); +} /* end of set_alloc_bitmap */ + +/* WARN : + * If the value of "clu" is 0, it means cluster 2 which is + * the first cluster of cluster heap. + */ +static s32 clr_alloc_bitmap(struct super_block *sb, u32 clu) +{ + s32 ret; + s32 i, b; + u32 sector; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + struct sdfat_mount_options *opts = &sbi->options; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + i = clu >> (sb->s_blocksize_bits + 3); + b = clu & (u32)((sb->s_blocksize << 3) - 1); + + sector = CLUS_TO_SECT(fsi, fsi->map_clu) + i; + + bitmap_clear((unsigned long *)(fsi->vol_amap[i]->b_data), b, 1); + + ret = write_sect(sb, sector, fsi->vol_amap[i], 0); + + if (opts->discard) { + s32 ret_discard; + + TMSG("discard cluster(%08x)\n", clu+2); + ret_discard = sb_issue_discard(sb, CLUS_TO_SECT(fsi, clu+2), + (1 << fsi->sect_per_clus_bits), GFP_NOFS, 0); + + if (ret_discard == -EOPNOTSUPP) { + sdfat_msg(sb, KERN_ERR, + "discard not supported by device, disabling"); + opts->discard = 0; + } + } + + return ret; +} /* end of clr_alloc_bitmap */ + +/* WARN : + * If the value of "clu" is 0, it means cluster 2 which is + * the first cluster of cluster heap. + */ +static u32 test_alloc_bitmap(struct super_block *sb, u32 clu) +{ + u32 i, map_i, map_b; + u32 clu_base, clu_free; + u8 k, clu_mask; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + clu_base = (clu & ~(0x7)) + 2; + clu_mask = (1 << (clu - clu_base + 2)) - 1; + + map_i = clu >> (sb->s_blocksize_bits + 3); + map_b = (clu >> 3) & (u32)(sb->s_blocksize - 1); + + for (i = 2; i < fsi->num_clusters; i += 8) { + k = *(((u8 *) fsi->vol_amap[map_i]->b_data) + map_b); + if (clu_mask > 0) { + k |= clu_mask; + clu_mask = 0; + } + if (k < 0xFF) { + clu_free = clu_base + free_bit[k]; + if (clu_free < fsi->num_clusters) + return clu_free; + } + clu_base += 8; + + if (((++map_b) >= (u32)sb->s_blocksize) || + (clu_base >= fsi->num_clusters)) { + if ((++map_i) >= fsi->map_sectors) { + clu_base = 2; + map_i = 0; + } + map_b = 0; + } + } + + return CLUS_EOF; +} /* end of test_alloc_bitmap */ + +void sync_alloc_bmp(struct super_block *sb) +{ + s32 i; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (fsi->vol_amap == NULL) + return; + + for (i = 0; i < fsi->map_sectors; i++) + sync_dirty_buffer(fsi->vol_amap[i]); +} + +static s32 exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len) +{ + if (!len) + return 0; + + while (len > 1) { + if (fat_ent_set(sb, chain, chain+1)) + return -EIO; + chain++; + len--; + } + + if (fat_ent_set(sb, chain, CLUS_EOF)) + return -EIO; + return 0; +} + +s32 chain_cont_cluster(struct super_block *sb, u32 chain, s32 len) +{ + return exfat_chain_cont_cluster(sb, chain, len); +} + +static s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p_chain, int dest) +{ + s32 num_clusters = 0; + u32 hint_clu, new_clu, last_clu = CLUS_EOF; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + hint_clu = p_chain->dir; + /* find new cluster */ + if (IS_CLUS_EOF(hint_clu)) { + if (fsi->clu_srch_ptr < 2) { + EMSG("%s: fsi->clu_srch_ptr is invalid (%u)\n", + __func__, fsi->clu_srch_ptr); + ASSERT(0); + fsi->clu_srch_ptr = 2; + } + + hint_clu = test_alloc_bitmap(sb, fsi->clu_srch_ptr-2); + if (IS_CLUS_EOF(hint_clu)) + return 0; + } + + /* check cluster validation */ + if ((hint_clu < 2) && (hint_clu >= fsi->num_clusters)) { + EMSG("%s: hint_cluster is invalid (%u)\n", __func__, hint_clu); + ASSERT(0); + hint_clu = 2; + if (p_chain->flags == 0x03) { + if (exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters)) + return -EIO; + p_chain->flags = 0x01; + } + } + + set_sb_dirty(sb); + + p_chain->dir = CLUS_EOF; + + while ((new_clu = test_alloc_bitmap(sb, hint_clu-2)) != CLUS_EOF) { + if ((new_clu != hint_clu) && (p_chain->flags == 0x03)) { + if (exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters)) + return -EIO; + p_chain->flags = 0x01; + } + + /* update allocation bitmap */ + if (set_alloc_bitmap(sb, new_clu-2)) + return -EIO; + + num_clusters++; + + /* update FAT table */ + if (p_chain->flags == 0x01) + if (fat_ent_set(sb, new_clu, CLUS_EOF)) + return -EIO; + + if (IS_CLUS_EOF(p_chain->dir)) { + p_chain->dir = new_clu; + } else if (p_chain->flags == 0x01) { + if (fat_ent_set(sb, last_clu, new_clu)) + return -EIO; + } + last_clu = new_clu; + + if ((--num_alloc) == 0) { + fsi->clu_srch_ptr = hint_clu; + if (fsi->used_clusters != (u32) ~0) + fsi->used_clusters += num_clusters; + + p_chain->size += num_clusters; + return num_clusters; + } + + hint_clu = new_clu + 1; + if (hint_clu >= fsi->num_clusters) { + hint_clu = 2; + + if (p_chain->flags == 0x03) { + if (exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters)) + return -EIO; + p_chain->flags = 0x01; + } + } + } + + fsi->clu_srch_ptr = hint_clu; + if (fsi->used_clusters != (u32) ~0) + fsi->used_clusters += num_clusters; + + p_chain->size += num_clusters; + return num_clusters; +} /* end of exfat_alloc_cluster */ + + +static s32 exfat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_relse) +{ + s32 ret = -EIO; + s32 num_clusters = 0; + u32 clu; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + s32 i; + u32 sector; + + /* invalid cluster number */ + if (IS_CLUS_FREE(p_chain->dir) || IS_CLUS_EOF(p_chain->dir)) + return 0; + + /* no cluster to truncate */ + if (p_chain->size <= 0) { + DMSG("%s: cluster(%u) truncation is not required.", + __func__, p_chain->dir); + return 0; + } + + /* check cluster validation */ + if ((p_chain->dir < 2) && (p_chain->dir >= fsi->num_clusters)) { + EMSG("%s: invalid start cluster (%u)\n", __func__, p_chain->dir); + sdfat_debug_bug_on(1); + return -EIO; + } + + set_sb_dirty(sb); + clu = p_chain->dir; + + if (p_chain->flags == 0x03) { + do { + if (do_relse) { + sector = CLUS_TO_SECT(fsi, clu); + for (i = 0; i < fsi->sect_per_clus; i++) { + if (dcache_release(sb, sector+i) == -EIO) + goto out; + } + } + + if (clr_alloc_bitmap(sb, clu-2)) + goto out; + clu++; + + num_clusters++; + } while (num_clusters < p_chain->size); + } else { + do { + if (do_relse) { + sector = CLUS_TO_SECT(fsi, clu); + for (i = 0; i < fsi->sect_per_clus; i++) { + if (dcache_release(sb, sector+i) == -EIO) + goto out; + } + } + + if (clr_alloc_bitmap(sb, (clu - CLUS_BASE))) + goto out; + + if (get_next_clus_safe(sb, &clu)) + goto out; + + num_clusters++; + } while (!IS_CLUS_EOF(clu)); + } + + /* success */ + ret = 0; +out: + + if (fsi->used_clusters != (u32) ~0) + fsi->used_clusters -= num_clusters; + return ret; +} /* end of exfat_free_cluster */ + +static s32 exfat_count_used_clusters(struct super_block *sb, u32 *ret_count) +{ + u32 count = 0; + u32 i, map_i, map_b; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + u32 total_clus = fsi->num_clusters - 2; + + map_i = map_b = 0; + + for (i = 0; i < total_clus; i += 8) { + u8 k = *(((u8 *) fsi->vol_amap[map_i]->b_data) + map_b); + + count += used_bit[k]; + if ((++map_b) >= (u32)sb->s_blocksize) { + map_i++; + map_b = 0; + } + } + + /* FIXME : abnormal bitmap count should be handled as more smart */ + if (total_clus < count) + count = total_clus; + + *ret_count = count; + return 0; +} /* end of exfat_count_used_clusters */ + + +/* + * File Operation Functions + */ +static FS_FUNC_T exfat_fs_func = { + .alloc_cluster = exfat_alloc_cluster, + .free_cluster = exfat_free_cluster, + .count_used_clusters = exfat_count_used_clusters, + + .init_dir_entry = exfat_init_dir_entry, + .init_ext_entry = exfat_init_ext_entry, + .find_dir_entry = exfat_find_dir_entry, + .delete_dir_entry = exfat_delete_dir_entry, + .get_uniname_from_ext_entry = exfat_get_uniname_from_ext_entry, + .count_ext_entries = exfat_count_ext_entries, + .calc_num_entries = exfat_calc_num_entries, + .check_max_dentries = exfat_check_max_dentries, + + .get_entry_type = exfat_get_entry_type, + .set_entry_type = exfat_set_entry_type, + .get_entry_attr = exfat_get_entry_attr, + .set_entry_attr = exfat_set_entry_attr, + .get_entry_flag = exfat_get_entry_flag, + .set_entry_flag = exfat_set_entry_flag, + .get_entry_clu0 = exfat_get_entry_clu0, + .set_entry_clu0 = exfat_set_entry_clu0, + .get_entry_size = exfat_get_entry_size, + .set_entry_size = exfat_set_entry_size, + .get_entry_time = exfat_get_entry_time, + .set_entry_time = exfat_set_entry_time, +}; + +s32 mount_exfat(struct super_block *sb, pbr_t *p_pbr) +{ + pbr64_t *p_bpb = (pbr64_t *)p_pbr; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (!p_bpb->bsx.num_fats) { + sdfat_msg(sb, KERN_ERR, "bogus number of FAT structure"); + return -EINVAL; + } + + fsi->sect_per_clus = 1 << p_bpb->bsx.sect_per_clus_bits; + fsi->sect_per_clus_bits = p_bpb->bsx.sect_per_clus_bits; + fsi->cluster_size_bits = fsi->sect_per_clus_bits + sb->s_blocksize_bits; + fsi->cluster_size = 1 << fsi->cluster_size_bits; + + fsi->num_FAT_sectors = le32_to_cpu(p_bpb->bsx.fat_length); + + fsi->FAT1_start_sector = le32_to_cpu(p_bpb->bsx.fat_offset); + if (p_bpb->bsx.num_fats == 1) + fsi->FAT2_start_sector = fsi->FAT1_start_sector; + else + fsi->FAT2_start_sector = fsi->FAT1_start_sector + fsi->num_FAT_sectors; + + fsi->root_start_sector = le32_to_cpu(p_bpb->bsx.clu_offset); + fsi->data_start_sector = fsi->root_start_sector; + + fsi->num_sectors = le64_to_cpu(p_bpb->bsx.vol_length); + fsi->num_clusters = le32_to_cpu(p_bpb->bsx.clu_count) + 2; + /* because the cluster index starts with 2 */ + + fsi->vol_type = EXFAT; + fsi->vol_id = le32_to_cpu(p_bpb->bsx.vol_serial); + + fsi->root_dir = le32_to_cpu(p_bpb->bsx.root_cluster); + fsi->dentries_in_root = 0; + fsi->dentries_per_clu = 1 << (fsi->cluster_size_bits - DENTRY_SIZE_BITS); + + fsi->vol_flag = (u32) le16_to_cpu(p_bpb->bsx.vol_flags); + fsi->clu_srch_ptr = 2; + fsi->used_clusters = (u32) ~0; + + fsi->fs_func = &exfat_fs_func; + fat_ent_ops_init(sb); + + if (p_bpb->bsx.vol_flags & VOL_DIRTY) { + fsi->vol_flag |= VOL_DIRTY; + sdfat_log_msg(sb, KERN_WARNING, "Volume was not properly " + "unmounted. Some data may be corrupt. " + "Please run fsck."); + } + + return 0; +} /* end of mount_exfat */ + +/* end of core_exfat.c */ diff --git a/fs/sdfat/core_fat.c b/fs/sdfat/core_fat.c new file mode 100644 index 0000000000000..fc40c6e05d777 --- /dev/null +++ b/fs/sdfat/core_fat.c @@ -0,0 +1,1453 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : core_fat.c */ +/* PURPOSE : FAT-fs core code for sdFAT */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/* */ +/************************************************************************/ + +#include +#include +#include +#include +#include + +#include "sdfat.h" +#include "core.h" +#include +#include + +/*----------------------------------------------------------------------*/ +/* Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ +#define MAX_LFN_ORDER (20) + +/* + * MAX_EST_AU_SECT should be changed according to 32/64bits. + * On 32bit, 4KB page supports 512 clusters per AU. + * But, on 64bit, 4KB page can handle a half of total list_head of 32bit's. + * Bcause the size of list_head structure on 64bit increases twofold over 32bit. + */ +#if (BITS_PER_LONG == 64) +//#define MAX_EST_AU_SECT (16384) /* upto 8MB */ +#define MAX_EST_AU_SECT (32768) /* upto 16MB, used more page for list_head */ +#else +#define MAX_EST_AU_SECT (32768) /* upto 16MB */ +#endif + +/*======================================================================*/ +/* Local Function Declarations */ +/*======================================================================*/ +static s32 __extract_uni_name_from_ext_entry(EXT_DENTRY_T *, u16 *, s32); + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*======================================================================*/ +/* Local Function Definitions */ +/*======================================================================*/ +static u32 __calc_default_au_size(struct super_block *sb) +{ + struct block_device *bdev = sb->s_bdev; + struct gendisk *disk; + struct request_queue *queue; + struct queue_limits *limit; + unsigned int est_au_sect = MAX_EST_AU_SECT; + unsigned int est_au_size = 0; + unsigned int queue_au_size = 0; + sector_t total_sect = 0; + + /* we assumed that sector size is 512 bytes */ + + disk = bdev->bd_disk; + if (!disk) + goto out; + + queue = disk->queue; + if (!queue) + goto out; + + limit = &queue->limits; + queue_au_size = limit->discard_granularity; + + /* estimate function(x) = + * (total_sect / 2) * 512 / 1024 + * => (total_sect >> 1) >> 1) + * => (total_sect >> 2) + * => estimated bytes size + * + * ex1) <= 8GB -> 4MB + * ex2) 16GB -> 8MB + * ex3) >= 32GB -> 16MB + */ + total_sect = disk->part0.nr_sects; + est_au_size = total_sect >> 2; + + /* au_size assumed that bytes per sector is 512 */ + est_au_sect = est_au_size >> 9; + + MMSG("DBG1: total_sect(%llu) est_au_size(%u) est_au_sect(%u)\n", + (u64)total_sect, est_au_size, est_au_sect); + + if (est_au_sect <= 8192) { + /* 4MB */ + est_au_sect = 8192; + } else if (est_au_sect <= 16384) { + /* 8MB */ + est_au_sect = 16384; + } else { + /* 8MB or 16MB */ + est_au_sect = MAX_EST_AU_SECT; + } + + MMSG("DBG2: total_sect(%llu) est_au_size(%u) est_au_sect(%u)\n", + (u64)total_sect, est_au_size, est_au_sect); + + if (est_au_size < queue_au_size && + queue_au_size <= (MAX_EST_AU_SECT << 9)) { + DMSG("use queue_au_size(%u) instead of est_au_size(%u)\n", + queue_au_size, est_au_size); + est_au_sect = queue_au_size >> 9; + } + +out: + if (sb->s_blocksize != 512) { + ASSERT(sb->s_blocksize_bits > 9); + sdfat_log_msg(sb, KERN_INFO, + "adjustment est_au_size by logical block size(%lu)", + sb->s_blocksize); + est_au_sect >>= (sb->s_blocksize_bits - 9); + } + + sdfat_log_msg(sb, KERN_INFO, "set default AU sectors : %u " + "(queue_au_size : %u KB, disk_size : %llu MB)", + est_au_sect, queue_au_size >> 10, (u64)(total_sect >> 11)); + return est_au_sect; +} + + +/* + * Cluster Management Functions + */ +static s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p_chain, int dest) +{ + s32 i, num_clusters = 0; + u32 new_clu, last_clu = CLUS_EOF, read_clu; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + + new_clu = p_chain->dir; + if (IS_CLUS_EOF(new_clu)) + new_clu = fsi->clu_srch_ptr; + else if (new_clu >= fsi->num_clusters) + new_clu = 2; + + set_sb_dirty(sb); + + p_chain->dir = CLUS_EOF; + + for (i = CLUS_BASE; i < fsi->num_clusters; i++) { + if (fat_ent_get(sb, new_clu, &read_clu)) + return -EIO; + + if (IS_CLUS_FREE(read_clu)) { + if (fat_ent_set(sb, new_clu, CLUS_EOF)) + return -EIO; + num_clusters++; + + if (IS_CLUS_EOF(p_chain->dir)) { + p_chain->dir = new_clu; + } else { + if (fat_ent_set(sb, last_clu, new_clu)) + return -EIO; + } + + last_clu = new_clu; + + if ((--num_alloc) == 0) { + fsi->clu_srch_ptr = new_clu; + if (fsi->used_clusters != (u32) ~0) + fsi->used_clusters += num_clusters; + + return num_clusters; + } + } + if ((++new_clu) >= fsi->num_clusters) + new_clu = CLUS_BASE; + } + + fsi->clu_srch_ptr = new_clu; + if (fsi->used_clusters != (u32) ~0) + fsi->used_clusters += num_clusters; + + return num_clusters; +} /* end of fat_alloc_cluster */ + +static s32 fat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_relse) +{ + s32 ret = -EIO; + s32 num_clusters = 0; + u32 clu, prev; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + s32 i; + u32 sector; + + /* invalid cluster number */ + if (IS_CLUS_FREE(p_chain->dir) || IS_CLUS_EOF(p_chain->dir)) + return 0; + + /* no cluster to truncate */ + if (p_chain->size <= 0) { + DMSG("%s: cluster(%u) truncation is not required.", + __func__, p_chain->dir); + return 0; + } + + /* check cluster validation */ + if ((p_chain->dir < 2) && (p_chain->dir >= fsi->num_clusters)) { + EMSG("%s: invalid start cluster (%u)\n", __func__, p_chain->dir); + sdfat_debug_bug_on(1); + return -EIO; + } + + + set_sb_dirty(sb); + clu = p_chain->dir; + + do { + if (do_relse) { + sector = CLUS_TO_SECT(fsi, clu); + for (i = 0; i < fsi->sect_per_clus; i++) { + if (dcache_release(sb, sector+i) == -EIO) + goto out; + } + } + + prev = clu; + if (get_next_clus_safe(sb, &clu)) { + /* print more helpful log */ + if (IS_CLUS_BAD(clu)) { + sdfat_log_msg(sb, KERN_ERR, "%s : " + "deleting bad cluster (clu[%u]->BAD)", + __func__, prev); + } else if (IS_CLUS_FREE(clu)) { + sdfat_log_msg(sb, KERN_ERR, "%s : " + "deleting free cluster (clu[%u]->FREE)", + __func__, prev); + } + goto out; + } + + /* Free FAT chain */ + if (fat_ent_set(sb, prev, CLUS_FREE)) + goto out; + + /* Update AMAP if needed */ + if (fsi->amap) { + if (amap_release_cluster(sb, prev)) + return -EIO; + } + + num_clusters++; + + } while (!IS_CLUS_EOF(clu)); + + /* success */ + ret = 0; +out: + if (fsi->used_clusters != (u32) ~0) + fsi->used_clusters -= num_clusters; + return ret; +} /* end of fat_free_cluster */ + +static s32 fat_count_used_clusters(struct super_block *sb, u32 *ret_count) +{ + s32 i; + u32 clu, count = 0; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + for (i = CLUS_BASE; i < fsi->num_clusters; i++) { + if (fat_ent_get(sb, i, &clu)) + return -EIO; + + if (!IS_CLUS_FREE(clu)) + count++; + } + + *ret_count = count; + return 0; +} /* end of fat_count_used_clusters */ + + +/* + * Directory Entry Management Functions + */ +static u32 fat_get_entry_type(DENTRY_T *p_entry) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry; + + /* first byte of 32bytes dummy */ + if (*(ep->name) == MSDOS_UNUSED) + return TYPE_UNUSED; + + /* 0xE5 of Kanji Japanese is replaced to 0x05 */ + else if (*(ep->name) == MSDOS_DELETED) + return TYPE_DELETED; + + /* 11th byte of 32bytes dummy */ + else if ((ep->attr & ATTR_EXTEND_MASK) == ATTR_EXTEND) + return TYPE_EXTEND; + + else if (!(ep->attr & (ATTR_SUBDIR | ATTR_VOLUME))) + return TYPE_FILE; + + else if ((ep->attr & (ATTR_SUBDIR | ATTR_VOLUME)) == ATTR_SUBDIR) + return TYPE_DIR; + + else if ((ep->attr & (ATTR_SUBDIR | ATTR_VOLUME)) == ATTR_VOLUME) + return TYPE_VOLUME; + + return TYPE_INVALID; +} /* end of fat_get_entry_type */ + +static void fat_set_entry_type(DENTRY_T *p_entry, u32 type) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry; + + if (type == TYPE_UNUSED) + *(ep->name) = MSDOS_UNUSED; /* 0x0 */ + + else if (type == TYPE_DELETED) + *(ep->name) = MSDOS_DELETED; /* 0xE5 */ + + else if (type == TYPE_EXTEND) + ep->attr = ATTR_EXTEND; + + else if (type == TYPE_DIR) + ep->attr = ATTR_SUBDIR; + + else if (type == TYPE_FILE) + ep->attr = ATTR_ARCHIVE; + + else if (type == TYPE_SYMLINK) + ep->attr = ATTR_ARCHIVE | ATTR_SYMLINK; +} /* end of fat_set_entry_type */ + +static u32 fat_get_entry_attr(DENTRY_T *p_entry) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry; + + return (u32)ep->attr; +} /* end of fat_get_entry_attr */ + +static void fat_set_entry_attr(DENTRY_T *p_entry, u32 attr) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry; + + ep->attr = (u8)attr; +} /* end of fat_set_entry_attr */ + +static u8 fat_get_entry_flag(DENTRY_T *p_entry) +{ + return 0x01; +} /* end of fat_get_entry_flag */ + +static void fat_set_entry_flag(DENTRY_T *p_entry, u8 flags) +{ +} /* end of fat_set_entry_flag */ + +static u32 fat_get_entry_clu0(DENTRY_T *p_entry) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry; + /* FIXME : is ok? */ + return(((u32)(le16_to_cpu(ep->start_clu_hi)) << 16) | le16_to_cpu(ep->start_clu_lo)); +} /* end of fat_get_entry_clu0 */ + +static void fat_set_entry_clu0(DENTRY_T *p_entry, u32 start_clu) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry; + + ep->start_clu_lo = cpu_to_le16(CLUSTER_16(start_clu)); + ep->start_clu_hi = cpu_to_le16(CLUSTER_16(start_clu >> 16)); +} /* end of fat_set_entry_clu0 */ + +static u64 fat_get_entry_size(DENTRY_T *p_entry) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry; + + return (u64)le32_to_cpu(ep->size); +} /* end of fat_get_entry_size */ + +static void fat_set_entry_size(DENTRY_T *p_entry, u64 size) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry; + + ep->size = cpu_to_le32((u32)size); +} /* end of fat_set_entry_size */ + +static void fat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, u8 mode) +{ + u16 t = 0x00, d = 0x21; + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + + switch (mode) { + case TM_CREATE: + t = le16_to_cpu(ep->create_time); + d = le16_to_cpu(ep->create_date); + break; + case TM_MODIFY: + t = le16_to_cpu(ep->modify_time); + d = le16_to_cpu(ep->modify_date); + break; + } + + tp->sec = (t & 0x001F) << 1; + tp->min = (t >> 5) & 0x003F; + tp->hour = (t >> 11); + tp->day = (d & 0x001F); + tp->mon = (d >> 5) & 0x000F; + tp->year = (d >> 9); +} /* end of fat_get_entry_time */ + +static void fat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, u8 mode) +{ + u16 t, d; + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + + t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1); + d = (tp->year << 9) | (tp->mon << 5) | tp->day; + + switch (mode) { + case TM_CREATE: + ep->create_time = cpu_to_le16(t); + ep->create_date = cpu_to_le16(d); + break; + case TM_MODIFY: + ep->modify_time = cpu_to_le16(t); + ep->modify_date = cpu_to_le16(d); + break; + } +} /* end of fat_set_entry_time */ + +static void __init_dos_entry(struct super_block *sb, DOS_DENTRY_T *ep, u32 type, u32 start_clu) +{ + TIMESTAMP_T tm, *tp; + + fat_set_entry_type((DENTRY_T *) ep, type); + ep->start_clu_lo = cpu_to_le16(CLUSTER_16(start_clu)); + ep->start_clu_hi = cpu_to_le16(CLUSTER_16(start_clu >> 16)); + ep->size = 0; + + tp = tm_now(SDFAT_SB(sb), &tm); + fat_set_entry_time((DENTRY_T *) ep, tp, TM_CREATE); + fat_set_entry_time((DENTRY_T *) ep, tp, TM_MODIFY); + ep->access_date = 0; + ep->create_time_ms = 0; +} /* end of __init_dos_entry */ + +static void __init_ext_entry(EXT_DENTRY_T *ep, s32 order, u8 chksum, u16 *uniname) +{ + s32 i; + u8 end = false; + + fat_set_entry_type((DENTRY_T *) ep, TYPE_EXTEND); + ep->order = (u8) order; + ep->sysid = 0; + ep->checksum = chksum; + ep->start_clu = 0; + + /* unaligned name */ + for (i = 0; i < 5; i++) { + if (!end) { + put_unaligned_le16(*uniname, &(ep->unicode_0_4[i<<1])); + if (*uniname == 0x0) + end = true; + else + uniname++; + } else { + put_unaligned_le16(0xFFFF, &(ep->unicode_0_4[i<<1])); + } + } + + /* aligned name */ + for (i = 0; i < 6; i++) { + if (!end) { + ep->unicode_5_10[i] = cpu_to_le16(*uniname); + if (*uniname == 0x0) + end = true; + else + uniname++; + } else { + ep->unicode_5_10[i] = cpu_to_le16(0xFFFF); + } + } + + /* aligned name */ + for (i = 0; i < 2; i++) { + if (!end) { + ep->unicode_11_12[i] = cpu_to_le16(*uniname); + if (*uniname == 0x0) + end = true; + else + uniname++; + } else { + ep->unicode_11_12[i] = cpu_to_le16(0xFFFF); + } + } +} /* end of __init_ext_entry */ + +static s32 fat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 type, + u32 start_clu, u64 size) +{ + u32 sector; + DOS_DENTRY_T *dos_ep; + + dos_ep = (DOS_DENTRY_T *) get_dentry_in_dir(sb, p_dir, entry, §or); + if (!dos_ep) + return -EIO; + + __init_dos_entry(sb, dos_ep, type, start_clu); + dcache_modify(sb, sector); + + return 0; +} /* end of fat_init_dir_entry */ + +static s32 fat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32 num_entries, + UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname) +{ + s32 i; + u32 sector; + u8 chksum; + u16 *uniname = p_uniname->name; + DOS_DENTRY_T *dos_ep; + EXT_DENTRY_T *ext_ep; + + dos_ep = (DOS_DENTRY_T *) get_dentry_in_dir(sb, p_dir, entry, §or); + if (!dos_ep) + return -EIO; + + dos_ep->lcase = p_dosname->name_case; + memcpy(dos_ep->name, p_dosname->name, DOS_NAME_LENGTH); + if (dcache_modify(sb, sector)) + return -EIO; + + if ((--num_entries) > 0) { + chksum = calc_chksum_1byte((void *) dos_ep->name, DOS_NAME_LENGTH, 0); + + for (i = 1; i < num_entries; i++) { + ext_ep = (EXT_DENTRY_T *) get_dentry_in_dir(sb, p_dir, entry-i, §or); + if (!ext_ep) + return -EIO; + + __init_ext_entry(ext_ep, i, chksum, uniname); + if (dcache_modify(sb, sector)) + return -EIO; + uniname += 13; + } + + ext_ep = (EXT_DENTRY_T *) get_dentry_in_dir(sb, p_dir, entry-i, §or); + if (!ext_ep) + return -EIO; + + __init_ext_entry(ext_ep, i+MSDOS_LAST_LFN, chksum, uniname); + if (dcache_modify(sb, sector)) + return -EIO; + } + + return 0; +} /* end of fat_init_ext_entry */ + +static s32 fat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32 order, s32 num_entries) +{ + s32 i; + u32 sector; + DENTRY_T *ep; + + for (i = num_entries-1; i >= order; i--) { + ep = get_dentry_in_dir(sb, p_dir, entry-i, §or); + if (!ep) + return -EIO; + + fat_set_entry_type(ep, TYPE_DELETED); + if (dcache_modify(sb, sector)) + return -EIO; + } + + return 0; +} + +/* return values of fat_find_dir_entry() + * >= 0 : return dir entiry position with the name in dir + * -EEXIST : (root dir, ".") it is the root dir itself + * -ENOENT : entry with the name does not exist + * -EIO : I/O error + */ +static inline s32 __get_dentries_per_clu(FS_INFO_T *fsi, s32 clu) +{ + if (IS_CLUS_FREE(clu)) /* FAT16 root_dir */ + return fsi->dentries_in_root; + + return fsi->dentries_per_clu; +} + +static s32 fat_find_dir_entry(struct super_block *sb, FILE_ID_T *fid, + CHAIN_T *p_dir, UNI_NAME_T *p_uniname, s32 num_entries, DOS_NAME_T *p_dosname, u32 type) +{ + s32 i, rewind = 0, dentry = 0, end_eidx = 0; + s32 chksum = 0, lfn_ord = 0, lfn_len = 0; + s32 dentries_per_clu, num_empty = 0; + u32 entry_type; + u16 entry_uniname[14], *uniname = NULL; + CHAIN_T clu; + DENTRY_T *ep; + HINT_T *hint_stat = &fid->hint_stat; + HINT_FEMP_T candi_empty; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + /* + * REMARK: + * DOT and DOTDOT are handled by VFS layer + */ + + dentries_per_clu = __get_dentries_per_clu(fsi, p_dir->dir); + clu.dir = p_dir->dir; + clu.flags = p_dir->flags; + + if (hint_stat->eidx) { + clu.dir = hint_stat->clu; + dentry = hint_stat->eidx; + end_eidx = dentry; + } + + candi_empty.eidx = -1; + + MMSG("lookup dir= %s\n", p_dosname->name); +rewind: + while (!IS_CLUS_EOF(clu.dir)) { + i = dentry % dentries_per_clu; + for (; i < dentries_per_clu; i++, dentry++) { + if (rewind && (dentry == end_eidx)) + goto not_found; + + ep = get_dentry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -EIO; + + entry_type = fat_get_entry_type(ep); + + /* + * Most directory entries have long name, + * So, we check extend directory entry first. + */ + if (entry_type == TYPE_EXTEND) { + EXT_DENTRY_T *ext_ep = (EXT_DENTRY_T *)ep; + u32 cur_ord = (u32)ext_ep->order; + u32 cur_chksum = (s32)ext_ep->checksum; + s32 len = 13; + u16 unichar; + + num_empty = 0; + candi_empty.eidx = -1; + + /* check whether new lfn or not */ + if (cur_ord & MSDOS_LAST_LFN) { + cur_ord &= ~(MSDOS_LAST_LFN); + chksum = cur_chksum; + len = (13 * (cur_ord-1)); + uniname = (p_uniname->name + len); + lfn_ord = cur_ord + 1; + lfn_len = 0; + + /* check minimum name length */ + if (cur_ord && + (len > p_uniname->name_len)) { + /* MISMATCHED NAME LENGTH */ + lfn_len = -1; + } + len = 0; + } + + /* invalid lfn order */ + if (!cur_ord || (cur_ord > MAX_LFN_ORDER) || + ((cur_ord + 1) != lfn_ord)) + goto reset_dentry_set; + + /* check checksum of directory entry set */ + if (cur_chksum != chksum) + goto reset_dentry_set; + + /* update order for next dentry */ + lfn_ord = cur_ord; + + /* check whether mismatched lfn or not */ + if (lfn_len == -1) { + /* MISMATCHED LFN DENTRY SET */ + continue; + } + + if (!uniname) { + sdfat_fs_error(sb, + "%s : abnormal dentry " + "(start_clu[%u], " + "idx[%u])", __func__, + p_dir->dir, dentry); + sdfat_debug_bug_on(1); + return -EIO; + } + + /* update position of name buffer */ + uniname -= len; + + /* get utf16 characters saved on this entry */ + len = __extract_uni_name_from_ext_entry(ext_ep, entry_uniname, lfn_ord); + + /* replace last char to null */ + unichar = *(uniname+len); + *(uniname+len) = (u16)0x0; + + /* uniname ext_dentry unit compare repeatdly */ + if (nls_cmp_uniname(sb, uniname, entry_uniname)) { + /* DO HANDLE WRONG NAME */ + lfn_len = -1; + } else { + /* add matched chars length */ + lfn_len += len; + } + + /* restore previous character */ + *(uniname+len) = unichar; + + /* jump to check next dentry */ + continue; + + } else if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) { + DOS_DENTRY_T *dos_ep = (DOS_DENTRY_T *)ep; + u32 cur_chksum = (s32)calc_chksum_1byte( + (void *) dos_ep->name, + DOS_NAME_LENGTH, 0); + + num_empty = 0; + candi_empty.eidx = -1; + + MMSG("checking dir= %c%c%c%c%c%c%c%c%c%c%c\n", + dos_ep->name[0], dos_ep->name[1], + dos_ep->name[2], dos_ep->name[3], + dos_ep->name[4], dos_ep->name[5], + dos_ep->name[6], dos_ep->name[7], + dos_ep->name[8], dos_ep->name[9], + dos_ep->name[10]); + + /* + * if there is no valid long filename, + * we should check short filename. + */ + if (!lfn_len || (cur_chksum != chksum)) { + /* check shortname */ + if ((p_dosname->name[0] != '\0') && + !nls_cmp_sfn(sb, + p_dosname->name, + dos_ep->name)) { + goto found; + } + /* check name length */ + } else if ((lfn_len > 0) && + ((s32)p_uniname->name_len == + lfn_len)) { + goto found; + } + + /* DO HANDLE MISMATCHED SFN, FALL THROUGH */ + } else if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) { + num_empty++; + if (candi_empty.eidx == -1) { + if (num_empty == 1) { + candi_empty.cur.dir = clu.dir; + candi_empty.cur.size = clu.size; + candi_empty.cur.flags = clu.flags; + } + + if (num_empty >= num_entries) { + candi_empty.eidx = dentry - (num_empty - 1); + ASSERT(0 <= candi_empty.eidx); + candi_empty.count = num_empty; + + if ((fid->hint_femp.eidx == -1) || + (candi_empty.eidx <= fid->hint_femp.eidx)) { + memcpy(&fid->hint_femp, + &candi_empty, + sizeof(HINT_FEMP_T)); + } + } + } + + if (entry_type == TYPE_UNUSED) + goto not_found; + /* FALL THROUGH */ + } +reset_dentry_set: + /* TYPE_DELETED, TYPE_VOLUME OR MISMATCHED SFN */ + lfn_ord = 0; + lfn_len = 0; + chksum = 0; + } + + if (IS_CLUS_FREE(p_dir->dir)) + break; /* FAT16 root_dir */ + + if (get_next_clus_safe(sb, &clu.dir)) + return -EIO; + } + +not_found: + /* we started at not 0 index,so we should try to find target + * from 0 index to the index we started at. + */ + if (!rewind && end_eidx) { + rewind = 1; + dentry = 0; + clu.dir = p_dir->dir; + /* reset dentry set */ + lfn_ord = 0; + lfn_len = 0; + chksum = 0; + /* reset empty hint_*/ + num_empty = 0; + candi_empty.eidx = -1; + goto rewind; + } + + /* initialized hint_stat */ + hint_stat->clu = p_dir->dir; + hint_stat->eidx = 0; + return -ENOENT; + +found: + /* next dentry we'll find is out of this cluster */ + if (!((dentry + 1) % dentries_per_clu)) { + int ret = 0; + /* FAT16 root_dir */ + if (IS_CLUS_FREE(p_dir->dir)) + clu.dir = CLUS_EOF; + else + ret = get_next_clus_safe(sb, &clu.dir); + + if (ret || IS_CLUS_EOF(clu.dir)) { + /* just initialized hint_stat */ + hint_stat->clu = p_dir->dir; + hint_stat->eidx = 0; + return dentry; + } + } + + hint_stat->clu = clu.dir; + hint_stat->eidx = dentry + 1; + return dentry; +} /* end of fat_find_dir_entry */ + +/* returns -EIO on error */ +static s32 fat_count_ext_entries(struct super_block *sb, CHAIN_T *p_dir, s32 entry, DENTRY_T *p_entry) +{ + s32 count = 0; + u8 chksum; + DOS_DENTRY_T *dos_ep = (DOS_DENTRY_T *) p_entry; + EXT_DENTRY_T *ext_ep; + + chksum = calc_chksum_1byte((void *) dos_ep->name, DOS_NAME_LENGTH, 0); + + for (entry--; entry >= 0; entry--) { + ext_ep = (EXT_DENTRY_T *)get_dentry_in_dir(sb, p_dir, entry, NULL); + if (!ext_ep) + return -EIO; + + if ((fat_get_entry_type((DENTRY_T *)ext_ep) == TYPE_EXTEND) && + (ext_ep->checksum == chksum)) { + count++; + if (ext_ep->order > MSDOS_LAST_LFN) + return count; + } else { + return count; + } + } + + return count; +} + + +/* + * Name Conversion Functions + */ +static s32 __extract_uni_name_from_ext_entry(EXT_DENTRY_T *ep, u16 *uniname, s32 order) +{ + s32 i, len = 0; + + for (i = 0; i < 5; i++) { + *uniname = get_unaligned_le16(&(ep->unicode_0_4[i<<1])); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + + if (order < 20) { + for (i = 0; i < 6; i++) { + /* FIXME : unaligned? */ + *uniname = le16_to_cpu(ep->unicode_5_10[i]); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + } else { + for (i = 0; i < 4; i++) { + /* FIXME : unaligned? */ + *uniname = le16_to_cpu(ep->unicode_5_10[i]); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + *uniname = 0x0; /* uniname[MAX_NAME_LENGTH] */ + return len; + } + + for (i = 0; i < 2; i++) { + /* FIXME : unaligned? */ + *uniname = le16_to_cpu(ep->unicode_11_12[i]); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + + *uniname = 0x0; + return len; + +} /* end of __extract_uni_name_from_ext_entry */ + +static void fat_get_uniname_from_ext_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u16 *uniname) +{ + u32 i; + u16 *name = uniname; + u32 chksum; + + DOS_DENTRY_T *dos_ep = + (DOS_DENTRY_T *)get_dentry_in_dir(sb, p_dir, entry, NULL); + + if (unlikely(!dos_ep)) + goto invalid_lfn; + + chksum = (u32)calc_chksum_1byte( + (void *) dos_ep->name, + DOS_NAME_LENGTH, 0); + + for (entry--, i = 1; entry >= 0; entry--, i++) { + EXT_DENTRY_T *ep; + + ep = (EXT_DENTRY_T *)get_dentry_in_dir(sb, p_dir, entry, NULL); + if (!ep) + goto invalid_lfn; + + if (fat_get_entry_type((DENTRY_T *) ep) != TYPE_EXTEND) + goto invalid_lfn; + + if (chksum != (u32)ep->checksum) + goto invalid_lfn; + + if (i != (u32)(ep->order & ~(MSDOS_LAST_LFN))) + goto invalid_lfn; + + __extract_uni_name_from_ext_entry(ep, name, (s32)i); + if (ep->order & MSDOS_LAST_LFN) + return; + + name += 13; + } +invalid_lfn: + *uniname = (u16)0x0; +} /* end of fat_get_uniname_from_ext_entry */ + +/* Find if the shortname exists + * and check if there are free entries + */ +static s32 __fat_find_shortname_entry(struct super_block *sb, CHAIN_T *p_dir, + u8 *p_dosname, s32 *offset, __attribute__((unused))int n_entry_needed) +{ + u32 type; + s32 i, dentry = 0; + s32 dentries_per_clu; + DENTRY_T *ep = NULL; + DOS_DENTRY_T *dos_ep = NULL; + CHAIN_T clu = *p_dir; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (offset) + *offset = -1; + + if (IS_CLUS_FREE(clu.dir)) /* FAT16 root_dir */ + dentries_per_clu = fsi->dentries_in_root; + else + dentries_per_clu = fsi->dentries_per_clu; + + while (!IS_CLUS_EOF(clu.dir)) { + for (i = 0; i < dentries_per_clu; i++, dentry++) { + ep = get_dentry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -EIO; + + type = fat_get_entry_type(ep); + + if ((type == TYPE_FILE) || (type == TYPE_DIR)) { + dos_ep = (DOS_DENTRY_T *)ep; + if (!nls_cmp_sfn(sb, p_dosname, dos_ep->name)) { + if (offset) + *offset = dentry; + return 0; + } + } + } + + /* fat12/16 root dir */ + if (IS_CLUS_FREE(clu.dir)) + break; + + if (get_next_clus_safe(sb, &clu.dir)) + return -EIO; + } + return -ENOENT; +} + +#ifdef CONFIG_SDFAT_FAT32_SHORTNAME_SEQ +static void __fat_attach_count_to_dos_name(u8 *dosname, s32 count) +{ + s32 i, j, length; + s8 str_count[6]; + + snprintf(str_count, sizeof(str_count), "~%d", count); + length = strlen(str_count); + + i = j = 0; + while (j <= (8 - length)) { + i = j; + if (dosname[j] == ' ') + break; + if (dosname[j] & 0x80) + j += 2; + else + j++; + } + + for (j = 0; j < length; i++, j++) + dosname[i] = (u8) str_count[j]; + + if (i == 7) + dosname[7] = ' '; + +} /* end of __fat_attach_count_to_dos_name */ +#endif + +s32 fat_generate_dos_name_new(struct super_block *sb, CHAIN_T *p_dir, DOS_NAME_T *p_dosname, s32 n_entry_needed) +{ + s32 i; + s32 baselen, err; + u8 work[DOS_NAME_LENGTH], buf[5]; + u8 tail; + + baselen = 8; + memset(work, ' ', DOS_NAME_LENGTH); + memcpy(work, p_dosname->name, DOS_NAME_LENGTH); + + while (baselen && (work[--baselen] == ' ')) { + /* DO NOTHING, JUST FOR CHECK_PATCH */ + } + + if (baselen > 6) + baselen = 6; + + BUG_ON(baselen < 0); + +#ifdef CONFIG_SDFAT_FAT32_SHORTNAME_SEQ + /* example) namei_exfat.c -> NAMEI_~1 - NAMEI_~9 */ + work[baselen] = '~'; + for (i = 1; i < 10; i++) { + // '0' + i = 1 ~ 9 ASCII + work[baselen + 1] = '0' + i; + err = __fat_find_shortname_entry(sb, p_dir, work, NULL, n_entry_needed); + if (err == -ENOENT) { + /* void return */ + __fat_attach_count_to_dos_name(p_dosname->name, i); + return 0; + } + + /* any other error */ + if (err) + return err; + } +#endif + + i = jiffies; + tail = (jiffies >> 16) & 0x7; + + if (baselen > 2) + baselen = 2; + + BUG_ON(baselen < 0); + + work[baselen + 4] = '~'; + // 1 ~ 8 ASCII + work[baselen + 5] = '1' + tail; + while (1) { + snprintf(buf, sizeof(buf), "%04X", i & 0xffff); + memcpy(&work[baselen], buf, 4); + err = __fat_find_shortname_entry(sb, p_dir, work, NULL, n_entry_needed); + if (err == -ENOENT) { + memcpy(p_dosname->name, work, DOS_NAME_LENGTH); + break; + } + + /* any other error */ + if (err) + return err; + + i -= 11; + } + return 0; +} /* end of generate_dos_name_new */ + +static s32 fat_calc_num_entries(UNI_NAME_T *p_uniname) +{ + s32 len; + + len = p_uniname->name_len; + if (len == 0) + return 0; + + /* 1 dos name entry + extended entries */ + return((len-1) / 13 + 2); + +} /* end of calc_num_enties */ + +static s32 fat_check_max_dentries(FILE_ID_T *fid) +{ + if ((fid->size >> DENTRY_SIZE_BITS) >= MAX_FAT_DENTRIES) { + /* FAT spec allows a dir to grow upto 65536 dentries */ + return -ENOSPC; + } + return 0; +} /* end of check_max_dentries */ + + +/* + * File Operation Functions + */ +static FS_FUNC_T fat_fs_func = { + .alloc_cluster = fat_alloc_cluster, + .free_cluster = fat_free_cluster, + .count_used_clusters = fat_count_used_clusters, + + .init_dir_entry = fat_init_dir_entry, + .init_ext_entry = fat_init_ext_entry, + .find_dir_entry = fat_find_dir_entry, + .delete_dir_entry = fat_delete_dir_entry, + .get_uniname_from_ext_entry = fat_get_uniname_from_ext_entry, + .count_ext_entries = fat_count_ext_entries, + .calc_num_entries = fat_calc_num_entries, + .check_max_dentries = fat_check_max_dentries, + + .get_entry_type = fat_get_entry_type, + .set_entry_type = fat_set_entry_type, + .get_entry_attr = fat_get_entry_attr, + .set_entry_attr = fat_set_entry_attr, + .get_entry_flag = fat_get_entry_flag, + .set_entry_flag = fat_set_entry_flag, + .get_entry_clu0 = fat_get_entry_clu0, + .set_entry_clu0 = fat_set_entry_clu0, + .get_entry_size = fat_get_entry_size, + .set_entry_size = fat_set_entry_size, + .get_entry_time = fat_get_entry_time, + .set_entry_time = fat_set_entry_time, +}; + +static FS_FUNC_T amap_fat_fs_func = { + .alloc_cluster = amap_fat_alloc_cluster, + .free_cluster = fat_free_cluster, + .count_used_clusters = fat_count_used_clusters, + + .init_dir_entry = fat_init_dir_entry, + .init_ext_entry = fat_init_ext_entry, + .find_dir_entry = fat_find_dir_entry, + .delete_dir_entry = fat_delete_dir_entry, + .get_uniname_from_ext_entry = fat_get_uniname_from_ext_entry, + .count_ext_entries = fat_count_ext_entries, + .calc_num_entries = fat_calc_num_entries, + .check_max_dentries = fat_check_max_dentries, + + .get_entry_type = fat_get_entry_type, + .set_entry_type = fat_set_entry_type, + .get_entry_attr = fat_get_entry_attr, + .set_entry_attr = fat_set_entry_attr, + .get_entry_flag = fat_get_entry_flag, + .set_entry_flag = fat_set_entry_flag, + .get_entry_clu0 = fat_get_entry_clu0, + .set_entry_clu0 = fat_set_entry_clu0, + .get_entry_size = fat_get_entry_size, + .set_entry_size = fat_set_entry_size, + .get_entry_time = fat_get_entry_time, + .set_entry_time = fat_set_entry_time, + + .get_au_stat = amap_get_au_stat, +}; + +s32 mount_fat16(struct super_block *sb, pbr_t *p_pbr) +{ + s32 num_reserved, num_root_sectors; + bpb16_t *p_bpb = &(p_pbr->bpb.f16); + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (!p_bpb->num_fats) { + sdfat_msg(sb, KERN_ERR, "bogus number of FAT structure"); + return -EINVAL; + } + + num_root_sectors = get_unaligned_le16(p_bpb->num_root_entries) << DENTRY_SIZE_BITS; + num_root_sectors = ((num_root_sectors-1) >> sb->s_blocksize_bits) + 1; + + fsi->sect_per_clus = p_bpb->sect_per_clus; + fsi->sect_per_clus_bits = ilog2(p_bpb->sect_per_clus); + fsi->cluster_size_bits = fsi->sect_per_clus_bits + sb->s_blocksize_bits; + fsi->cluster_size = 1 << fsi->cluster_size_bits; + + fsi->num_FAT_sectors = le16_to_cpu(p_bpb->num_fat_sectors); + + fsi->FAT1_start_sector = le16_to_cpu(p_bpb->num_reserved); + if (p_bpb->num_fats == 1) + fsi->FAT2_start_sector = fsi->FAT1_start_sector; + else + fsi->FAT2_start_sector = fsi->FAT1_start_sector + fsi->num_FAT_sectors; + + fsi->root_start_sector = fsi->FAT2_start_sector + fsi->num_FAT_sectors; + fsi->data_start_sector = fsi->root_start_sector + num_root_sectors; + + fsi->num_sectors = get_unaligned_le16(p_bpb->num_sectors); + if (!fsi->num_sectors) + fsi->num_sectors = le32_to_cpu(p_bpb->num_huge_sectors); + + if (!fsi->num_sectors) { + sdfat_msg(sb, KERN_ERR, "bogus number of total sector count"); + return -EINVAL; + } + + num_reserved = fsi->data_start_sector; + fsi->num_clusters = ((fsi->num_sectors - num_reserved) >> fsi->sect_per_clus_bits) + CLUS_BASE; + /* because the cluster index starts with 2 */ + + fsi->vol_type = FAT16; + if (fsi->num_clusters < FAT12_THRESHOLD) + fsi->vol_type = FAT12; + + fsi->vol_id = get_unaligned_le32(p_bpb->vol_serial); + + fsi->root_dir = 0; + fsi->dentries_in_root = get_unaligned_le16(p_bpb->num_root_entries); + if (!fsi->dentries_in_root) { + sdfat_msg(sb, KERN_ERR, "bogus number of max dentry count " + "of the root directory"); + return -EINVAL; + } + + fsi->dentries_per_clu = 1 << (fsi->cluster_size_bits - DENTRY_SIZE_BITS); + + fsi->vol_flag = VOL_CLEAN; + fsi->clu_srch_ptr = 2; + fsi->used_clusters = (u32) ~0; + + fsi->fs_func = &fat_fs_func; + fat_ent_ops_init(sb); + + if (p_bpb->state & FAT_VOL_DIRTY) { + fsi->vol_flag |= VOL_DIRTY; + sdfat_log_msg(sb, KERN_WARNING, "Volume was not properly " + "unmounted. Some data may be corrupt. " + "Please run fsck."); + } + + return 0; +} /* end of mount_fat16 */ + +static sector_t __calc_hidden_sect(struct super_block *sb) +{ + struct block_device *bdev = sb->s_bdev; + sector_t hidden = 0; + + if (!bdev) + goto out; + + hidden = bdev->bd_part->start_sect; + /* a disk device, not a partition */ + if (!hidden) { + ASSERT(bdev == bdev->bd_contains); + ASSERT(!bdev->bd_part->partno); + goto out; + } + + if (sb->s_blocksize_bits != 9) { + ASSERT(sb->s_blocksize_bits > 9); + hidden >>= (sb->s_blocksize_bits - 9); + } + +out: + sdfat_log_msg(sb, KERN_INFO, "start_sect of partition : %lld", + (s64)hidden); + return hidden; + +} + +s32 mount_fat32(struct super_block *sb, pbr_t *p_pbr) +{ + s32 num_reserved; + pbr32_t *p_bpb = (pbr32_t *)p_pbr; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (!p_bpb->bpb.num_fats) { + sdfat_msg(sb, KERN_ERR, "bogus number of FAT structure"); + return -EINVAL; + } + + fsi->sect_per_clus = p_bpb->bpb.sect_per_clus; + fsi->sect_per_clus_bits = ilog2(p_bpb->bpb.sect_per_clus); + fsi->cluster_size_bits = fsi->sect_per_clus_bits + sb->s_blocksize_bits; + fsi->cluster_size = 1 << fsi->cluster_size_bits; + + fsi->num_FAT_sectors = le32_to_cpu(p_bpb->bpb.num_fat32_sectors); + + fsi->FAT1_start_sector = le16_to_cpu(p_bpb->bpb.num_reserved); + if (p_bpb->bpb.num_fats == 1) + fsi->FAT2_start_sector = fsi->FAT1_start_sector; + else + fsi->FAT2_start_sector = fsi->FAT1_start_sector + fsi->num_FAT_sectors; + + fsi->root_start_sector = fsi->FAT2_start_sector + fsi->num_FAT_sectors; + fsi->data_start_sector = fsi->root_start_sector; + + /* SPEC violation for compatibility */ + fsi->num_sectors = get_unaligned_le16(p_bpb->bpb.num_sectors); + if (!fsi->num_sectors) + fsi->num_sectors = le32_to_cpu(p_bpb->bpb.num_huge_sectors); + + /* 2nd check */ + if (!fsi->num_sectors) { + sdfat_msg(sb, KERN_ERR, "bogus number of total sector count"); + return -EINVAL; + } + + num_reserved = fsi->data_start_sector; + + fsi->num_clusters = ((fsi->num_sectors-num_reserved) >> fsi->sect_per_clus_bits) + 2; + /* because the cluster index starts with 2 */ + + fsi->vol_type = FAT32; + fsi->vol_id = get_unaligned_le32(p_bpb->bsx.vol_serial); + + fsi->root_dir = le32_to_cpu(p_bpb->bpb.root_cluster); + fsi->dentries_in_root = 0; + fsi->dentries_per_clu = 1 << (fsi->cluster_size_bits - DENTRY_SIZE_BITS); + + fsi->vol_flag = VOL_CLEAN; + fsi->clu_srch_ptr = 2; + fsi->used_clusters = (u32) ~0; + + fsi->fs_func = &fat_fs_func; + + /* Delayed / smart allocation related init */ + fsi->reserved_clusters = 0; + + /* Should be initialized before calling amap_create() */ + fat_ent_ops_init(sb); + + /* AU Map Creation */ + if (SDFAT_SB(sb)->options.improved_allocation & SDFAT_ALLOC_SMART) { + u32 hidden_sectors = le32_to_cpu(p_bpb->bpb.num_hid_sectors); + u32 calc_hid_sect = 0; + int ret; + + + /* calculate hidden sector size */ + calc_hid_sect = __calc_hidden_sect(sb); + if (calc_hid_sect != hidden_sectors) { + sdfat_log_msg(sb, KERN_WARNING, "abnormal hidden " + "sector : bpb(%u) != ondisk(%u)", + hidden_sectors, calc_hid_sect); + if (SDFAT_SB(sb)->options.adj_hidsect) { + sdfat_log_msg(sb, KERN_INFO, + "adjustment hidden sector : " + "bpb(%u) -> ondisk(%u)", + hidden_sectors, calc_hid_sect); + hidden_sectors = calc_hid_sect; + } + } + + SDFAT_SB(sb)->options.amap_opt.misaligned_sect = hidden_sectors; + + /* calculate AU size if it's not set */ + if (!SDFAT_SB(sb)->options.amap_opt.sect_per_au) { + SDFAT_SB(sb)->options.amap_opt.sect_per_au = + __calc_default_au_size(sb); + } + + ret = amap_create(sb, + SDFAT_SB(sb)->options.amap_opt.pack_ratio, + SDFAT_SB(sb)->options.amap_opt.sect_per_au, + SDFAT_SB(sb)->options.amap_opt.misaligned_sect); + if (ret) { + sdfat_log_msg(sb, KERN_WARNING, "failed to create AMAP." + " disabling smart allocation. (err:%d)", ret); + SDFAT_SB(sb)->options.improved_allocation &= ~(SDFAT_ALLOC_SMART); + } else { + fsi->fs_func = &amap_fat_fs_func; + } + } + + /* Check dependency of mount options */ + if (SDFAT_SB(sb)->options.improved_allocation != + (SDFAT_ALLOC_DELAY | SDFAT_ALLOC_SMART)) { + sdfat_log_msg(sb, KERN_INFO, "disabling defragmentation because" + " smart, delay options are disabled"); + SDFAT_SB(sb)->options.defrag = 0; + } + + if (p_bpb->bsx.state & FAT_VOL_DIRTY) { + fsi->vol_flag |= VOL_DIRTY; + sdfat_log_msg(sb, KERN_WARNING, "Volume was not properly " + "unmounted. Some data may be corrupt. " + "Please run fsck."); + } + + return 0; +} /* end of mount_fat32 */ + +/* end of core_fat.c */ diff --git a/fs/sdfat/dfr.c b/fs/sdfat/dfr.c new file mode 100644 index 0000000000000..b06ae840997ec --- /dev/null +++ b/fs/sdfat/dfr.c @@ -0,0 +1,1377 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/************************************************************************/ +/* */ +/* @PROJECT : exFAT & FAT12/16/32 File System */ +/* @FILE : dfr.c */ +/* @PURPOSE : Defragmentation support for SDFAT32 */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/* */ +/************************************************************************/ + +#include +#include +#include + +#include "sdfat.h" +#include "core.h" +#include "amap_smart.h" + +#ifdef CONFIG_SDFAT_DFR +/** + * @fn defrag_get_info + * @brief get HW params for defrag daemon + * @return 0 on success, -errno otherwise + * @param sb super block + * @param arg defrag info arguments + * @remark protected by super_block + */ +int +defrag_get_info( + IN struct super_block *sb, + OUT struct defrag_info_arg *arg) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; + + if (!arg) + return -EINVAL; + + arg->sec_sz = sb->s_blocksize; + arg->clus_sz = fsi->cluster_size; + arg->total_sec = fsi->num_sectors; + arg->fat_offset_sec = fsi->FAT1_start_sector; + arg->fat_sz_sec = fsi->num_FAT_sectors; + arg->n_fat = (fsi->FAT1_start_sector == fsi->FAT2_start_sector) ? 1 : 2; + + arg->sec_per_au = amap->option.au_size; + arg->hidden_sectors = amap->option.au_align_factor % amap->option.au_size; + + return 0; +} + + +static int +__defrag_scan_dir( + IN struct super_block *sb, + IN DOS_DENTRY_T *dos_ep, + IN loff_t i_pos, + OUT struct defrag_trav_arg *arg) +{ + FS_INFO_T *fsi = NULL; + UNI_NAME_T uniname; + unsigned int type = 0, start_clus = 0; + int err = -EPERM; + + /* Check params */ + ERR_HANDLE2((!sb || !dos_ep || !i_pos || !arg), err, -EINVAL); + fsi = &(SDFAT_SB(sb)->fsi); + + /* Get given entry's type */ + type = fsi->fs_func->get_entry_type((DENTRY_T *) dos_ep); + + /* Check dos_ep */ + if (!strncmp(dos_ep->name, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH)) { + ; + } else if (!strncmp(dos_ep->name, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH)) { + ; + } else if ((type == TYPE_DIR) || (type == TYPE_FILE)) { + + /* Set start_clus */ + SET32_HI(start_clus, le16_to_cpu(dos_ep->start_clu_hi)); + SET32_LO(start_clus, le16_to_cpu(dos_ep->start_clu_lo)); + arg->start_clus = start_clus; + + /* Set type & i_pos */ + if (type == TYPE_DIR) + arg->type = DFR_TRAV_TYPE_DIR; + else + arg->type = DFR_TRAV_TYPE_FILE; + + arg->i_pos = i_pos; + + /* Set name */ + memset(&uniname, 0, sizeof(UNI_NAME_T)); + get_uniname_from_dos_entry(sb, dos_ep, &uniname, 0x1); + /* FIXME : + * we should think that whether the size of arg->name + * is enough or not + */ + nls_uni16s_to_vfsname(sb, &uniname, + arg->name, sizeof(arg->name)); + + err = 0; + /* End case */ + } else if (type == TYPE_UNUSED) { + err = -ENOENT; + } else { + ; + } + +error: + return err; +} + + +/** + * @fn defrag_scan_dir + * @brief scan given directory + * @return 0 on success, -errno otherwise + * @param sb super block + * @param args traverse args + * @remark protected by inode_lock, super_block and volume lock + */ +int +defrag_scan_dir( + IN struct super_block *sb, + INOUT struct defrag_trav_arg *args) +{ + struct sdfat_sb_info *sbi = NULL; + FS_INFO_T *fsi = NULL; + struct defrag_trav_header *header = NULL; + DOS_DENTRY_T *dos_ep; + CHAIN_T chain; + int dot_found = 0, args_idx = DFR_TRAV_HEADER_IDX + 1, clus = 0, index = 0; + int err = 0, j = 0; + + /* Check params */ + ERR_HANDLE2((!sb || !args), err, -EINVAL); + sbi = SDFAT_SB(sb); + fsi = &(sbi->fsi); + header = (struct defrag_trav_header *) args; + + /* Exceptional case for ROOT */ + if (header->i_pos == DFR_TRAV_ROOT_IPOS) { + header->start_clus = fsi->root_dir; + dfr_debug("IOC_DFR_TRAV for ROOT: start_clus %08x", header->start_clus); + dot_found = 1; + } + + chain.dir = header->start_clus; + chain.size = 0; + chain.flags = 0; + + /* Check if this is directory */ + if (!dot_found) { + FAT32_CHECK_CLUSTER(fsi, chain.dir, err); + ERR_HANDLE(err); + dos_ep = (DOS_DENTRY_T *) get_dentry_in_dir(sb, &chain, 0, NULL); + ERR_HANDLE2(!dos_ep, err, -EIO); + + if (strncmp(dos_ep->name, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH)) { + err = -EINVAL; + dfr_err("Scan: Not a directory, err %d", err); + goto error; + } + } + + /* For more-scan case */ + if ((header->stat == DFR_TRAV_STAT_MORE) && + (header->start_clus == sbi->dfr_hint_clus) && + (sbi->dfr_hint_idx > 0)) { + + index = sbi->dfr_hint_idx; + for (j = 0; j < (sbi->dfr_hint_idx / fsi->dentries_per_clu); j++) { + /* Follow FAT-chain */ + FAT32_CHECK_CLUSTER(fsi, chain.dir, err); + ERR_HANDLE(err); + err = fat_ent_get(sb, chain.dir, &(chain.dir)); + ERR_HANDLE(err); + + if (!IS_CLUS_EOF(chain.dir)) { + clus++; + index -= fsi->dentries_per_clu; + } else { + /** + * This directory modified. Stop scanning. + */ + err = -EINVAL; + dfr_err("Scan: SCAN_MORE failed, err %d", err); + goto error; + } + } + + /* For first-scan case */ + } else { + clus = 0; + index = 0; + } + +scan_fat_chain: + /* Scan given directory and get info of children */ + for ( ; index < fsi->dentries_per_clu; index++) { + DOS_DENTRY_T *dos_ep = NULL; + loff_t i_pos = 0; + + /* Get dos_ep */ + FAT32_CHECK_CLUSTER(fsi, chain.dir, err); + ERR_HANDLE(err); + dos_ep = (DOS_DENTRY_T *) get_dentry_in_dir(sb, &chain, index, NULL); + ERR_HANDLE2(!dos_ep, err, -EIO); + + /* Make i_pos for this entry */ + SET64_HI(i_pos, header->start_clus); + SET64_LO(i_pos, clus * fsi->dentries_per_clu + index); + + err = __defrag_scan_dir(sb, dos_ep, i_pos, &args[args_idx]); + if (!err) { + /* More-scan case */ + if (++args_idx >= (PAGE_SIZE / sizeof(struct defrag_trav_arg))) { + sbi->dfr_hint_clus = header->start_clus; + sbi->dfr_hint_idx = clus * fsi->dentries_per_clu + index + 1; + + header->stat = DFR_TRAV_STAT_MORE; + header->nr_entries = args_idx; + goto error; + } + /* Error case */ + } else if (err == -EINVAL) { + sbi->dfr_hint_clus = sbi->dfr_hint_idx = 0; + dfr_err("Scan: err %d", err); + goto error; + /* End case */ + } else if (err == -ENOENT) { + sbi->dfr_hint_clus = sbi->dfr_hint_idx = 0; + err = 0; + goto done; + } else { + /* DO NOTHING */ + } + err = 0; + } + + /* Follow FAT-chain */ + FAT32_CHECK_CLUSTER(fsi, chain.dir, err); + ERR_HANDLE(err); + err = fat_ent_get(sb, chain.dir, &(chain.dir)); + ERR_HANDLE(err); + + if (!IS_CLUS_EOF(chain.dir)) { + index = 0; + clus++; + goto scan_fat_chain; + } + +done: + /* Update header */ + header->stat = DFR_TRAV_STAT_DONE; + header->nr_entries = args_idx; + +error: + return err; +} + + +static int +__defrag_validate_cluster_prev( + IN struct super_block *sb, + IN struct defrag_chunk_info *chunk) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + CHAIN_T dir; + DENTRY_T *ep = NULL; + unsigned int entry = 0, clus = 0; + int err = 0; + + if (chunk->prev_clus == 0) { + /* For the first cluster of a file */ + dir.dir = GET64_HI(chunk->i_pos); + dir.flags = 0x1; // Assume non-continuous + + entry = GET64_LO(chunk->i_pos); + + FAT32_CHECK_CLUSTER(fsi, dir.dir, err); + ERR_HANDLE(err); + ep = get_dentry_in_dir(sb, &dir, entry, NULL); + if (!ep) { + err = -EPERM; + goto error; + } + + /* should call fat_get_entry_clu0(ep) */ + clus = fsi->fs_func->get_entry_clu0(ep); + if (clus != chunk->d_clus) { + err = -ENXIO; + goto error; + } + } else { + /* Normal case */ + FAT32_CHECK_CLUSTER(fsi, chunk->prev_clus, err); + ERR_HANDLE(err); + err = fat_ent_get(sb, chunk->prev_clus, &clus); + if (err) + goto error; + if (chunk->d_clus != clus) + err = -ENXIO; + } + +error: + return err; +} + + +static int +__defrag_validate_cluster_next( + IN struct super_block *sb, + IN struct defrag_chunk_info *chunk) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + unsigned int clus = 0; + int err = 0; + + /* Check next_clus */ + FAT32_CHECK_CLUSTER(fsi, (chunk->d_clus + chunk->nr_clus - 1), err); + ERR_HANDLE(err); + err = fat_ent_get(sb, (chunk->d_clus + chunk->nr_clus - 1), &clus); + if (err) + goto error; + if (chunk->next_clus != (clus & FAT32_EOF)) + err = -ENXIO; + +error: + return err; +} + + +/** + * @fn __defrag_check_au + * @brief check if this AU is in use + * @return 0 if idle, 1 if busy + * @param sb super block + * @param clus physical cluster num + * @param limit # of used clusters from daemon + */ +static int +__defrag_check_au( + struct super_block *sb, + u32 clus, + u32 limit) +{ + unsigned int nr_free = amap_get_freeclus(sb, clus); + +#if defined(CONFIG_SDFAT_DFR_DEBUG) && defined(CONFIG_SDFAT_DBG_MSG) + if (nr_free < limit) { + AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; + AU_INFO_T *au = GET_AU(amap, i_AU_of_CLU(amap, clus)); + + dfr_debug("AU[%d] nr_free %d, limit %d", au->idx, nr_free, limit); + } +#endif + return ((nr_free < limit) ? 1 : 0); +} + + +/** + * @fn defrag_validate_cluster + * @brief validate cluster info of given chunk + * @return 0 on success, -errno otherwise + * @param inode inode of given chunk + * @param chunk given chunk + * @param skip_prev flag to skip checking previous cluster info + * @remark protected by super_block and volume lock + */ +int +defrag_validate_cluster( + IN struct inode *inode, + IN struct defrag_chunk_info *chunk, + IN int skip_prev) +{ + struct super_block *sb = inode->i_sb; + FILE_ID_T *fid = &(SDFAT_I(inode)->fid); + unsigned int clus = 0; + int err = 0, i = 0; + + /* If this inode is unlink-ed, skip it */ + if (fid->dir.dir == DIR_DELETED) + return -ENOENT; + + /* Skip working-AU */ + err = amap_check_working(sb, chunk->d_clus); + if (err) + return -EBUSY; + + /* Check # of free_clus of belonged AU */ + err = __defrag_check_au(inode->i_sb, chunk->d_clus, CLUS_PER_AU(sb) - chunk->au_clus); + if (err) + return -EINVAL; + + /* Check chunk's clusters */ + for (i = 0; i < chunk->nr_clus; i++) { + err = fsapi_map_clus(inode, chunk->f_clus + i, &clus, ALLOC_NOWHERE); + if (err || (chunk->d_clus + i != clus)) { + if (!err) + err = -ENXIO; + goto error; + } + } + + /* Check next_clus */ + err = __defrag_validate_cluster_next(sb, chunk); + ERR_HANDLE(err); + + if (!skip_prev) { + /* Check prev_clus */ + err = __defrag_validate_cluster_prev(sb, chunk); + ERR_HANDLE(err); + } + +error: + return err; +} + + +/** + * @fn defrag_reserve_clusters + * @brief reserve clusters for defrag + * @return 0 on success, -errno otherwise + * @param sb super block + * @param nr_clus # of clusters to reserve + * @remark protected by super_block and volume lock + */ +int +defrag_reserve_clusters( + INOUT struct super_block *sb, + IN int nr_clus) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + FS_INFO_T *fsi = &(sbi->fsi); + + if (!(sbi->options.improved_allocation & SDFAT_ALLOC_DELAY)) + /* Nothing to do */ + return 0; + + /* Update used_clusters */ + if (fsi->used_clusters == (u32) ~0) { + if (fsi->fs_func->count_used_clusters(sb, &fsi->used_clusters)) + return -EIO; + } + + /* Check error case */ + if (fsi->used_clusters + fsi->reserved_clusters + nr_clus >= fsi->num_clusters - 2) { + return -ENOSPC; + } else if (fsi->reserved_clusters + nr_clus < 0) { + dfr_err("Reserve count: reserved_clusters %d, nr_clus %d", + fsi->reserved_clusters, nr_clus); + BUG_ON(fsi->reserved_clusters + nr_clus < 0); + } + + sbi->dfr_reserved_clus += nr_clus; + fsi->reserved_clusters += nr_clus; + + return 0; +} + + +/** + * @fn defrag_mark_ignore + * @brief mark corresponding AU to be ignored + * @return 0 on success, -errno otherwise + * @param sb super block + * @param clus given cluster num + * @remark protected by super_block + */ +int +defrag_mark_ignore( + INOUT struct super_block *sb, + IN unsigned int clus) +{ + int err = 0; + + if (SDFAT_SB(sb)->options.improved_allocation & SDFAT_ALLOC_SMART) + err = amap_mark_ignore(sb, clus); + + if (err) + dfr_debug("err %d", err); + return err; +} + + +/** + * @fn defrag_unmark_ignore_all + * @brief unmark all ignored AUs + * @return void + * @param sb super block + * @remark protected by super_block + */ +void +defrag_unmark_ignore_all(struct super_block *sb) +{ + if (SDFAT_SB(sb)->options.improved_allocation & SDFAT_ALLOC_SMART) + amap_unmark_ignore_all(sb); +} + + +/** + * @fn defrag_map_cluster + * @brief get_block function for defrag dests + * @return 0 on success, -errno otherwise + * @param inode inode + * @param clu_offset logical cluster offset + * @param clu mapped cluster (physical) + * @remark protected by super_block and volume lock + */ +int +defrag_map_cluster( + struct inode *inode, + unsigned int clu_offset, + unsigned int *clu) +{ + struct super_block *sb = inode->i_sb; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); +#ifdef CONFIG_SDFAT_DFR_PACKING + AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; +#endif + FILE_ID_T *fid = &(SDFAT_I(inode)->fid); + struct defrag_info *ino_dfr = &(SDFAT_I(inode)->dfr_info); + struct defrag_chunk_info *chunk = NULL; + CHAIN_T new_clu; + int num = 0, i = 0, nr_new = 0, err = 0; + + /* Get corresponding chunk */ + for (i = 0; i < ino_dfr->nr_chunks; i++) { + chunk = &(ino_dfr->chunks[i]); + + if ((chunk->f_clus <= clu_offset) && (clu_offset < chunk->f_clus + chunk->nr_clus)) { + /* For already allocated new_clus */ + if (sbi->dfr_new_clus[chunk->new_idx + clu_offset - chunk->f_clus]) { + *clu = sbi->dfr_new_clus[chunk->new_idx + clu_offset - chunk->f_clus]; + return 0; + } + break; + } + } + BUG_ON(!chunk); + + fscore_set_vol_flags(sb, VOL_DIRTY, 0); + + new_clu.dir = CLUS_EOF; + new_clu.size = 0; + new_clu.flags = fid->flags; + + /* Allocate new cluster */ +#ifdef CONFIG_SDFAT_DFR_PACKING + if (amap->n_clean_au * DFR_FULL_RATIO <= amap->n_au * DFR_DEFAULT_PACKING_RATIO) + num = fsi->fs_func->alloc_cluster(sb, 1, &new_clu, ALLOC_COLD_PACKING); + else + num = fsi->fs_func->alloc_cluster(sb, 1, &new_clu, ALLOC_COLD_ALIGNED); +#else + num = fsi->fs_func->alloc_cluster(sb, 1, &new_clu, ALLOC_COLD_ALIGNED); +#endif + + if (num != 1) { + dfr_err("Map: num %d", num); + return -EIO; + } + + /* Decrease reserved cluster count */ + defrag_reserve_clusters(sb, -1); + + /* Add new_clus info in ino_dfr */ + sbi->dfr_new_clus[chunk->new_idx + clu_offset - chunk->f_clus] = new_clu.dir; + + /* Make FAT-chain for new_clus */ + for (i = 0; i < chunk->nr_clus; i++) { +#if 0 + if (sbi->dfr_new_clus[chunk->new_idx + i]) + nr_new++; + else + break; +#else + if (!sbi->dfr_new_clus[chunk->new_idx + i]) + break; + nr_new++; +#endif + } + if (nr_new == chunk->nr_clus) { + for (i = 0; i < chunk->nr_clus - 1; i++) { + FAT32_CHECK_CLUSTER(fsi, sbi->dfr_new_clus[chunk->new_idx + i], err); + BUG_ON(err); + if (fat_ent_set(sb, + sbi->dfr_new_clus[chunk->new_idx + i], + sbi->dfr_new_clus[chunk->new_idx + i + 1])) + return -EIO; + } + } + + *clu = new_clu.dir; + return 0; +} + + +/** + * @fn defrag_writepage_end_io + * @brief check WB status of requested page + * @return void + * @param page page + */ +void +defrag_writepage_end_io( + INOUT struct page *page) +{ + struct super_block *sb = page->mapping->host->i_sb; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + struct defrag_info *ino_dfr = &(SDFAT_I(page->mapping->host)->dfr_info); + unsigned int clus_start = 0, clus_end = 0; + int i = 0; + + /* Check if this inode is on defrag */ + if (atomic_read(&ino_dfr->stat) != DFR_INO_STAT_REQ) + return; + + clus_start = page->index / PAGES_PER_CLUS(sb); + clus_end = clus_start + 1; + + /* Check each chunk in given inode */ + for (i = 0; i < ino_dfr->nr_chunks; i++) { + struct defrag_chunk_info *chunk = &(ino_dfr->chunks[i]); + unsigned int chunk_start = 0, chunk_end = 0; + + chunk_start = chunk->f_clus; + chunk_end = chunk->f_clus + chunk->nr_clus; + + if ((clus_start >= chunk_start) && (clus_end <= chunk_end)) { + int off = clus_start - chunk_start; + + clear_bit((page->index & (PAGES_PER_CLUS(sb) - 1)), + (volatile unsigned long *)&(sbi->dfr_page_wb[chunk->new_idx + off])); + } + } +} + + +/** + * @fn __defrag_check_wb + * @brief check if WB for given chunk completed + * @return 0 on success, -errno otherwise + * @param sbi super block info + * @param chunk given chunk + */ +static int +__defrag_check_wb( + IN struct sdfat_sb_info *sbi, + IN struct defrag_chunk_info *chunk) +{ + int err = 0, wb_i = 0, i = 0, nr_new = 0; + + if (!sbi || !chunk) + return -EINVAL; + + /* Check WB complete status first */ + for (wb_i = 0; wb_i < chunk->nr_clus; wb_i++) { + if (atomic_read((atomic_t *)&(sbi->dfr_page_wb[chunk->new_idx + wb_i]))) { + err = -EBUSY; + break; + } + } + + /** + * Check NEW_CLUS status. + * writepage_end_io cannot check whole WB complete status, + * so we need to check NEW_CLUS status. + */ + for (i = 0; i < chunk->nr_clus; i++) + if (sbi->dfr_new_clus[chunk->new_idx + i]) + nr_new++; + + if (nr_new == chunk->nr_clus) { + err = 0; + if ((wb_i != chunk->nr_clus) && (wb_i != chunk->nr_clus - 1)) + dfr_debug("submit_fullpage_bio() called on a page (nr_clus %d, wb_i %d)", + chunk->nr_clus, wb_i); + + BUG_ON(nr_new > chunk->nr_clus); + } else { + dfr_debug("nr_new %d, nr_clus %d", nr_new, chunk->nr_clus); + err = -EBUSY; + } + + /* Update chunk's state */ + if (!err) + chunk->stat |= DFR_CHUNK_STAT_WB; + + return err; +} + + +static void +__defrag_check_fat_old( + IN struct super_block *sb, + IN struct inode *inode, + IN struct defrag_chunk_info *chunk) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + unsigned int clus = 0; + int err = 0, idx = 0, max_idx = 0; + + /* Get start_clus */ + clus = SDFAT_I(inode)->fid.start_clu; + + /* Follow FAT-chain */ + #define num_clusters(val) ((val) ? (s32)((val - 1) >> fsi->cluster_size_bits) + 1 : 0) + max_idx = num_clusters(SDFAT_I(inode)->i_size_ondisk); + for (idx = 0; idx < max_idx; idx++) { + + FAT32_CHECK_CLUSTER(fsi, clus, err); + ERR_HANDLE(err); + err = fat_ent_get(sb, clus, &clus); + ERR_HANDLE(err); + + if ((idx < max_idx - 1) && (IS_CLUS_EOF(clus) || IS_CLUS_FREE(clus))) { + dfr_err("FAT: inode %p, max_idx %d, idx %d, clus %08x, " + "f_clus %d, nr_clus %d", inode, max_idx, + idx, clus, chunk->f_clus, chunk->nr_clus); + BUG_ON(idx < max_idx - 1); + goto error; + } + } + +error: + return; +} + + +static void +__defrag_check_fat_new( + IN struct super_block *sb, + IN struct inode *inode, + IN struct defrag_chunk_info *chunk) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + unsigned int clus = 0; + int i = 0, err = 0; + + /* Check start of FAT-chain */ + if (chunk->prev_clus) { + FAT32_CHECK_CLUSTER(fsi, chunk->prev_clus, err); + BUG_ON(err); + err = fat_ent_get(sb, chunk->prev_clus, &clus); + BUG_ON(err); + } else { + clus = SDFAT_I(inode)->fid.start_clu; + } + if (sbi->dfr_new_clus[chunk->new_idx] != clus) { + dfr_err("FAT: inode %p, start_clus %08x, read_clus %08x", + inode, sbi->dfr_new_clus[chunk->new_idx], clus); + err = EIO; + goto error; + } + + /* Check inside of FAT-chain */ + if (chunk->nr_clus > 1) { + for (i = 0; i < chunk->nr_clus - 1; i++) { + FAT32_CHECK_CLUSTER(fsi, sbi->dfr_new_clus[chunk->new_idx + i], err); + BUG_ON(err); + err = fat_ent_get(sb, sbi->dfr_new_clus[chunk->new_idx + i], &clus); + BUG_ON(err); + if (sbi->dfr_new_clus[chunk->new_idx + i + 1] != clus) { + dfr_err("FAT: inode %p, new_clus %08x, read_clus %08x", + inode, sbi->dfr_new_clus[chunk->new_idx], clus); + err = EIO; + goto error; + } + } + clus = 0; + } + + /* Check end of FAT-chain */ + FAT32_CHECK_CLUSTER(fsi, sbi->dfr_new_clus[chunk->new_idx + chunk->nr_clus - 1], err); + BUG_ON(err); + err = fat_ent_get(sb, sbi->dfr_new_clus[chunk->new_idx + chunk->nr_clus - 1], &clus); + BUG_ON(err); + if ((chunk->next_clus & 0x0FFFFFFF) != (clus & 0x0FFFFFFF)) { + dfr_err("FAT: inode %p, next_clus %08x, read_clus %08x", inode, chunk->next_clus, clus); + err = EIO; + } + +error: + BUG_ON(err); +} + + +/** + * @fn __defrag_update_dirent + * @brief update DIR entry for defrag req + * @return void + * @param sb super block + * @param chunk given chunk + */ +static void +__defrag_update_dirent( + struct super_block *sb, + struct defrag_chunk_info *chunk) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + FS_INFO_T *fsi = &SDFAT_SB(sb)->fsi; + CHAIN_T dir; + DOS_DENTRY_T *dos_ep; + unsigned int entry = 0, sector = 0; + unsigned short hi = 0, lo = 0; + int err = 0; + + dir.dir = GET64_HI(chunk->i_pos); + dir.flags = 0x1; // Assume non-continuous + + entry = GET64_LO(chunk->i_pos); + + FAT32_CHECK_CLUSTER(fsi, dir.dir, err); + BUG_ON(err); + dos_ep = (DOS_DENTRY_T *) get_dentry_in_dir(sb, &dir, entry, §or); + + hi = GET32_HI(sbi->dfr_new_clus[chunk->new_idx]); + lo = GET32_LO(sbi->dfr_new_clus[chunk->new_idx]); + + dos_ep->start_clu_hi = cpu_to_le16(hi); + dos_ep->start_clu_lo = cpu_to_le16(lo); + + dcache_modify(sb, sector); +} + + +/** + * @fn defrag_update_fat_prev + * @brief update FAT chain for defrag requests + * @return void + * @param sb super block + * @param force flag to force FAT update + * @remark protected by super_block and volume lock + */ +void +defrag_update_fat_prev( + struct super_block *sb, + int force) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + FS_INFO_T *fsi = &(sbi->fsi); + struct defrag_info *sb_dfr = &sbi->dfr_info, *ino_dfr = NULL; + int skip = 0, done = 0; + + /* Check if FS_ERROR occurred */ + if (sb->s_flags & MS_RDONLY) { + dfr_err("RDONLY partition (err %d)", -EPERM); + goto out; + } + + list_for_each_entry(ino_dfr, &sb_dfr->entry, entry) { + struct inode *inode = &(container_of(ino_dfr, struct sdfat_inode_info, dfr_info)->vfs_inode); + struct sdfat_inode_info *ino_info = SDFAT_I(inode); + struct defrag_chunk_info *chunk_prev = NULL; + int i = 0, j = 0; + + mutex_lock(&ino_dfr->lock); + BUG_ON(atomic_read(&ino_dfr->stat) != DFR_INO_STAT_REQ); + for (i = 0; i < ino_dfr->nr_chunks; i++) { + struct defrag_chunk_info *chunk = NULL; + int err = 0; + + chunk = &(ino_dfr->chunks[i]); + BUG_ON(!chunk); + + /* Do nothing for already passed chunk */ + if (chunk->stat == DFR_CHUNK_STAT_PASS) { + done++; + continue; + } + + /* Handle error case */ + if (chunk->stat == DFR_CHUNK_STAT_ERR) { + err = -EINVAL; + goto error; + } + + /* Double-check clusters */ + if (chunk_prev && + (chunk->f_clus == chunk_prev->f_clus + chunk_prev->nr_clus) && + (chunk_prev->stat == DFR_CHUNK_STAT_PASS)) { + + err = defrag_validate_cluster(inode, chunk, 1); + + /* Handle continuous chunks in a file */ + if (!err) { + chunk->prev_clus = + sbi->dfr_new_clus[chunk_prev->new_idx + chunk_prev->nr_clus - 1]; + dfr_debug("prev->f_clus %d, prev->nr_clus %d, chunk->f_clus %d", + chunk_prev->f_clus, chunk_prev->nr_clus, chunk->f_clus); + } + } else { + err = defrag_validate_cluster(inode, chunk, 0); + } + + if (err) { + dfr_err("Cluster validation: inode %p, chunk->f_clus %d, err %d", + inode, chunk->f_clus, err); + goto error; + } + + /** + * Skip update_fat_prev if WB or update_fat_next not completed. + * Go to error case if FORCE set. + */ + if (__defrag_check_wb(sbi, chunk) || (chunk->stat != DFR_CHUNK_STAT_PREP)) { + if (force) { + err = -EPERM; + dfr_err("Skip case: inode %p, stat %x, f_clus %d, err %d", + inode, chunk->stat, chunk->f_clus, err); + goto error; + } + skip++; + continue; + } + +#ifdef CONFIG_SDFAT_DFR_DEBUG + /* SPO test */ + defrag_spo_test(sb, DFR_SPO_RANDOM, __func__); +#endif + + /* Update chunk's previous cluster */ + if (chunk->prev_clus == 0) { + /* For the first cluster of a file */ + /* Update ino_info->fid.start_clu */ + ino_info->fid.start_clu = sbi->dfr_new_clus[chunk->new_idx]; + __defrag_update_dirent(sb, chunk); + } else { + FAT32_CHECK_CLUSTER(fsi, chunk->prev_clus, err); + BUG_ON(err); + if (fat_ent_set(sb, + chunk->prev_clus, + sbi->dfr_new_clus[chunk->new_idx])) { + err = -EIO; + goto error; + } + } + + /* Clear extent cache */ + extent_cache_inval_inode(inode); + + /* Update FID info */ + ino_info->fid.hint_bmap.off = -1; + ino_info->fid.hint_bmap.clu = 0; + + /* Clear old FAT-chain */ + for (j = 0; j < chunk->nr_clus; j++) + defrag_free_cluster(sb, chunk->d_clus + j); + + /* Mark this chunk PASS */ + chunk->stat = DFR_CHUNK_STAT_PASS; + __defrag_check_fat_new(sb, inode, chunk); + + done++; + +error: + if (err) { + /** + * chunk->new_idx != 0 means this chunk needs to be cleaned up + */ + if (chunk->new_idx) { + /* Free already allocated clusters */ + for (j = 0; j < chunk->nr_clus; j++) { + if (sbi->dfr_new_clus[chunk->new_idx + j]) { + defrag_free_cluster(sb, sbi->dfr_new_clus[chunk->new_idx + j]); + sbi->dfr_new_clus[chunk->new_idx + j] = 0; + } + } + + __defrag_check_fat_old(sb, inode, chunk); + } + + /** + * chunk->new_idx == 0 means this chunk already cleaned up + */ + chunk->new_idx = 0; + chunk->stat = DFR_CHUNK_STAT_ERR; + } + + chunk_prev = chunk; + } + BUG_ON(!mutex_is_locked(&ino_dfr->lock)); + mutex_unlock(&ino_dfr->lock); + } + +out: + if (skip) { + dfr_debug("%s skipped (nr_reqs %d, done %d, skip %d)", + __func__, sb_dfr->nr_chunks - 1, done, skip); + } else { + /* Make dfr_reserved_clus zero */ + if (sbi->dfr_reserved_clus > 0) { + if (fsi->reserved_clusters < sbi->dfr_reserved_clus) { + dfr_err("Reserved count: reserved_clus %d, dfr_reserved_clus %d", + fsi->reserved_clusters, sbi->dfr_reserved_clus); + BUG_ON(fsi->reserved_clusters < sbi->dfr_reserved_clus); + } + + defrag_reserve_clusters(sb, 0 - sbi->dfr_reserved_clus); + } + + dfr_debug("%s done (nr_reqs %d, done %d)", __func__, sb_dfr->nr_chunks - 1, done); + } +} + + +/** + * @fn defrag_update_fat_next + * @brief update FAT chain for defrag requests + * @return void + * @param sb super block + * @remark protected by super_block and volume lock + */ +void +defrag_update_fat_next( + struct super_block *sb) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + struct defrag_info *sb_dfr = &sbi->dfr_info, *ino_dfr = NULL; + struct defrag_chunk_info *chunk = NULL; + int done = 0, i = 0, j = 0, err = 0; + + /* Check if FS_ERROR occurred */ + if (sb->s_flags & MS_RDONLY) { + dfr_err("RDONLY partition (err %d)", -EROFS); + goto out; + } + + list_for_each_entry(ino_dfr, &sb_dfr->entry, entry) { + + for (i = 0; i < ino_dfr->nr_chunks; i++) { + int skip = 0; + + chunk = &(ino_dfr->chunks[i]); + + /* Do nothing if error occurred or update_fat_next already passed */ + if (chunk->stat == DFR_CHUNK_STAT_ERR) + continue; + if (chunk->stat & DFR_CHUNK_STAT_FAT) { + done++; + continue; + } + + /* Ship this chunk if get_block not passed for this chunk */ + for (j = 0; j < chunk->nr_clus; j++) { + if (sbi->dfr_new_clus[chunk->new_idx + j] == 0) { + skip = 1; + break; + } + } + if (skip) + continue; + + /* Update chunk's next cluster */ + FAT32_CHECK_CLUSTER(fsi, + sbi->dfr_new_clus[chunk->new_idx + chunk->nr_clus - 1], err); + BUG_ON(err); + if (fat_ent_set(sb, + sbi->dfr_new_clus[chunk->new_idx + chunk->nr_clus - 1], + chunk->next_clus)) + goto out; + +#ifdef CONFIG_SDFAT_DFR_DEBUG + /* SPO test */ + defrag_spo_test(sb, DFR_SPO_RANDOM, __func__); +#endif + + /* Update chunk's state */ + chunk->stat |= DFR_CHUNK_STAT_FAT; + done++; + } + } + +out: + dfr_debug("%s done (nr_reqs %d, done %d)", __func__, sb_dfr->nr_chunks - 1, done); +} + + +/** + * @fn defrag_check_discard + * @brief check if we can send discard for this AU, if so, send discard + * @return void + * @param sb super block + * @remark protected by super_block and volume lock + */ +void +defrag_check_discard( + IN struct super_block *sb) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; + AU_INFO_T *au = NULL; + struct defrag_info *sb_dfr = &(SDFAT_SB(sb)->dfr_info); + unsigned int tmp[DFR_MAX_AU_MOVED]; + int i = 0, j = 0; + + BUG_ON(!amap); + + if (!(SDFAT_SB(sb)->options.discard) || + !(SDFAT_SB(sb)->options.improved_allocation & SDFAT_ALLOC_SMART)) + return; + + memset(tmp, 0, sizeof(int) * DFR_MAX_AU_MOVED); + + for (i = REQ_HEADER_IDX + 1; i < sb_dfr->nr_chunks; i++) { + struct defrag_chunk_info *chunk = &(sb_dfr->chunks[i]); + int skip = 0; + + au = GET_AU(amap, i_AU_of_CLU(amap, chunk->d_clus)); + + /* Send DISCARD for free AU */ + if ((IS_AU_IGNORED(au, amap)) && + (amap_get_freeclus(sb, chunk->d_clus) == CLUS_PER_AU(sb))) { + sector_t blk = 0, nr_blks = 0; + unsigned int au_align_factor = amap->option.au_align_factor % amap->option.au_size; + + BUG_ON(au->idx == 0); + + /* Avoid multiple DISCARD */ + for (j = 0; j < DFR_MAX_AU_MOVED; j++) { + if (tmp[j] == au->idx) { + skip = 1; + break; + } + } + if (skip == 1) + continue; + + /* Send DISCARD cmd */ + blk = (sector_t) (((au->idx * CLUS_PER_AU(sb)) << fsi->sect_per_clus_bits) + - au_align_factor); + nr_blks = ((sector_t)CLUS_PER_AU(sb)) << fsi->sect_per_clus_bits; + + dfr_debug("Send DISCARD for AU[%d] (blk %08zx)", au->idx, blk); + sb_issue_discard(sb, blk, nr_blks, GFP_NOFS, 0); + + /* Save previous AU's index */ + for (j = 0; j < DFR_MAX_AU_MOVED; j++) { + if (!tmp[j]) { + tmp[j] = au->idx; + break; + } + } + } + } +} + + +/** + * @fn defrag_free_cluster + * @brief free uneccessary cluster + * @return void + * @param sb super block + * @param clus physical cluster num + * @remark protected by super_block and volume lock + */ +int +defrag_free_cluster( + struct super_block *sb, + unsigned int clus) +{ + FS_INFO_T *fsi = &SDFAT_SB(sb)->fsi; + unsigned int val = 0; + s32 err = 0; + + FAT32_CHECK_CLUSTER(fsi, clus, err); + BUG_ON(err); + if (fat_ent_get(sb, clus, &val)) + return -EIO; + if (val) { + if (fat_ent_set(sb, clus, 0)) + return -EIO; + } else { + dfr_err("Free: Already freed, clus %08x, val %08x", clus, val); + BUG_ON(!val); + } + + set_sb_dirty(sb); + fsi->used_clusters--; + if (fsi->amap) + amap_release_cluster(sb, clus); + + return 0; +} + + +/** + * @fn defrag_check_defrag_required + * @brief check if defrag required + * @return 1 if required, 0 otherwise + * @param sb super block + * @param totalau # of total AUs + * @param cleanau # of clean AUs + * @param fullau # of full AUs + * @remark protected by super_block + */ +int +defrag_check_defrag_required( + IN struct super_block *sb, + OUT int *totalau, + OUT int *cleanau, + OUT int *fullau) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + AMAP_T *amap = NULL; + int clean_ratio = 0, frag_ratio = 0; + int ret = 0; + + if (!sb || !(SDFAT_SB(sb)->options.defrag)) + return 0; + + /* Check DFR_DEFAULT_STOP_RATIO first */ + fsi = &(SDFAT_SB(sb)->fsi); + if (fsi->used_clusters == (unsigned int)(~0)) { + if (fsi->fs_func->count_used_clusters(sb, &fsi->used_clusters)) + return -EIO; + } + if (fsi->used_clusters * DFR_FULL_RATIO >= fsi->num_clusters * DFR_DEFAULT_STOP_RATIO) { + dfr_debug("used_clusters %d, num_clusters %d", fsi->used_clusters, fsi->num_clusters); + return 0; + } + + /* Check clean/frag ratio */ + amap = SDFAT_SB(sb)->fsi.amap; + BUG_ON(!amap); + + clean_ratio = (amap->n_clean_au * 100) / amap->n_au; + if (amap->n_full_au) + frag_ratio = ((amap->n_au - amap->n_clean_au) * 100) / amap->n_full_au; + else + frag_ratio = ((amap->n_au - amap->n_clean_au) * 100) / + (fsi->used_clusters * CLUS_PER_AU(sb)); + + /* + * Wake-up defrag_daemon: + * when # of clean AUs too small, or frag_ratio exceeds the limit + */ + if ((clean_ratio < DFR_DEFAULT_WAKEUP_RATIO) || + ((clean_ratio < DFR_DEFAULT_CLEAN_RATIO) && (frag_ratio >= DFR_DEFAULT_FRAG_RATIO))) { + + if (totalau) + *totalau = amap->n_au; + if (cleanau) + *cleanau = amap->n_clean_au; + if (fullau) + *fullau = amap->n_full_au; + ret = 1; + } + + return ret; +} + + +/** + * @fn defrag_check_defrag_required + * @brief check defrag status on inode + * @return 1 if defrag in on, 0 otherwise + * @param inode inode + * @param start logical start addr + * @param end logical end addr + * @param cancel flag to cancel defrag + * @param caller caller info + */ +int +defrag_check_defrag_on( + INOUT struct inode *inode, + IN loff_t start, + IN loff_t end, + IN int cancel, + IN const char *caller) +{ + struct super_block *sb = inode->i_sb; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + FS_INFO_T *fsi = &(sbi->fsi); + struct defrag_info *ino_dfr = &(SDFAT_I(inode)->dfr_info); + unsigned int clus_start = 0, clus_end = 0; + int ret = 0, i = 0; + + if (!inode || (start == end)) + return 0; + + mutex_lock(&ino_dfr->lock); + /* Check if this inode is on defrag */ + if (atomic_read(&ino_dfr->stat) == DFR_INO_STAT_REQ) { + + clus_start = start >> (fsi->cluster_size_bits); + clus_end = (end >> (fsi->cluster_size_bits)) + + ((end & (fsi->cluster_size - 1)) ? 1 : 0); + + if (!ino_dfr->chunks) + goto error; + + /* Check each chunk in given inode */ + for (i = 0; i < ino_dfr->nr_chunks; i++) { + struct defrag_chunk_info *chunk = &(ino_dfr->chunks[i]); + unsigned int chunk_start = 0, chunk_end = 0; + + /* Skip this chunk when error occurred or it already passed defrag process */ + if ((chunk->stat == DFR_CHUNK_STAT_ERR) || (chunk->stat == DFR_CHUNK_STAT_PASS)) + continue; + + chunk_start = chunk->f_clus; + chunk_end = chunk->f_clus + chunk->nr_clus; + + if (((clus_start >= chunk_start) && (clus_start < chunk_end)) || + ((clus_end > chunk_start) && (clus_end <= chunk_end)) || + ((clus_start < chunk_start) && (clus_end > chunk_end))) { + ret = 1; + if (cancel) { + chunk->stat = DFR_CHUNK_STAT_ERR; + dfr_debug("Defrag canceled: inode %p, start %08x, end %08x, caller %s", + inode, clus_start, clus_end, caller); + } + } + } + } + +error: + BUG_ON(!mutex_is_locked(&ino_dfr->lock)); + mutex_unlock(&ino_dfr->lock); + return ret; +} + + +#ifdef CONFIG_SDFAT_DFR_DEBUG +/** + * @fn defrag_spo_test + * @brief test SPO while defrag running + * @return void + * @param sb super block + * @param flag SPO debug flag + * @param caller caller info + */ +void +defrag_spo_test( + struct super_block *sb, + int flag, + const char *caller) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + + if (!sb || !(SDFAT_SB(sb)->options.defrag)) + return; + + if (flag == sbi->dfr_spo_flag) { + dfr_err("Defrag SPO test (flag %d, caller %s)", flag, caller); + panic("Defrag SPO test"); + } +} +#endif /* CONFIG_SDFAT_DFR_DEBUG */ + + +#endif /* CONFIG_SDFAT_DFR */ diff --git a/fs/sdfat/dfr.h b/fs/sdfat/dfr.h new file mode 100644 index 0000000000000..19edab38ce4ee --- /dev/null +++ b/fs/sdfat/dfr.h @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _SDFAT_DEFRAG_H +#define _SDFAT_DEFRAG_H + +#ifdef CONFIG_SDFAT_DFR + +/* Tuning parameters */ +#define DFR_MIN_TIMEOUT (1 * HZ) // Minimum timeout for forced-sync +#define DFR_DEFAULT_TIMEOUT (10 * HZ) // Default timeout for forced-sync + +#define DFR_DEFAULT_CLEAN_RATIO (50) // Wake-up daemon when clean AU ratio under 50% +#define DFR_DEFAULT_WAKEUP_RATIO (10) // Wake-up daemon when clean AU ratio under 10%, regardless of frag_ratio + +#define DFR_DEFAULT_FRAG_RATIO (130) // Wake-up daemon when frag_ratio over 130% + +#define DFR_DEFAULT_PACKING_RATIO (10) // Call allocator with PACKING flag, when clean AU ratio under 10% + +#define DFR_DEFAULT_STOP_RATIO (98) // Stop defrag_daemon when disk used ratio over 98% +#define DFR_FULL_RATIO (100) + +#define DFR_MAX_AU_MOVED (16) // Maximum # of AUs for a request + + +/* Debugging support*/ +#define dfr_err(fmt, args...) pr_err("DFR: " fmt "\n", args) + +#ifdef CONFIG_SDFAT_DFR_DEBUG +#define dfr_debug(fmt, args...) pr_debug("DFR: " fmt "\n", args) +#else +#define dfr_debug(fmt, args...) +#endif + + +/* Error handling */ +#define ERR_HANDLE(err) { \ + if (err) { \ + dfr_debug("err %d", err); \ + goto error; \ + } \ +} + +#define ERR_HANDLE2(cond, err, val) { \ + if (cond) { \ + err = val; \ + dfr_debug("err %d", err); \ + goto error; \ + } \ +} + + +/* Arguments IN-OUT */ +#define IN +#define OUT +#define INOUT + + +/* Macros */ +#define GET64_HI(var64) ((unsigned int)((var64) >> 32)) +#define GET64_LO(var64) ((unsigned int)(((var64) << 32) >> 32)) +#define SET64_HI(dst64, var32) { (dst64) = ((loff_t)(var32) << 32) | ((dst64) & 0x00000000ffffffffLL); } +#define SET64_LO(dst64, var32) { (dst64) = ((dst64) & 0xffffffff00000000LL) | ((var32) & 0x00000000ffffffffLL); } + +#define GET32_HI(var32) ((unsigned short)((var32) >> 16)) +#define GET32_LO(var32) ((unsigned short)(((var32) << 16) >> 16)) +#define SET32_HI(dst32, var16) { (dst32) = ((unsigned int)(var16) << 16) | ((dst32) & 0x0000ffff); } +#define SET32_LO(dst32, var16) { (dst32) = ((dst32) & 0xffff0000) | ((unsigned int)(var16) & 0x0000ffff); } + + +/* FAT32 related */ +#define FAT32_EOF (0x0fffffff) +#define FAT32_RESERVED (0x0ffffff7) +#define FAT32_UNUSED_CLUS (2) + +#define CLUS_PER_AU(sb) ( \ + (SDFAT_SB(sb)->options.amap_opt.sect_per_au) >> (SDFAT_SB(sb)->fsi.sect_per_clus_bits) \ +) +#define PAGES_PER_AU(sb) ( \ + ((SDFAT_SB(sb)->options.amap_opt.sect_per_au) << ((sb)->s_blocksize_bits)) \ + >> PAGE_SHIFT \ +) +#define PAGES_PER_CLUS(sb) ((SDFAT_SB(sb)->fsi.cluster_size) >> PAGE_SHIFT) + +#define FAT32_CHECK_CLUSTER(fsi, clus, err) \ + { \ + if (((clus) < FAT32_UNUSED_CLUS) || \ + ((clus) > (fsi)->num_clusters) || \ + ((clus) >= FAT32_RESERVED)) { \ + dfr_err("clus %08x, fsi->num_clusters %08x", (clus), (fsi)->num_clusters); \ + err = -EINVAL; \ + } else { \ + err = 0; \ + } \ + } + + +/* IOCTL_DFR_INFO */ +struct defrag_info_arg { + /* PBS info */ + unsigned int sec_sz; + unsigned int clus_sz; + unsigned int total_sec; + unsigned int fat_offset_sec; + unsigned int fat_sz_sec; + unsigned int n_fat; + unsigned int hidden_sectors; + + /* AU info */ + unsigned int sec_per_au; +}; + + +/* IOC_DFR_TRAV */ +#define DFR_TRAV_HEADER_IDX (0) + +#define DFR_TRAV_TYPE_HEADER (0x0000000F) +#define DFR_TRAV_TYPE_DIR (1) +#define DFR_TRAV_TYPE_FILE (2) +#define DFR_TRAV_TYPE_TEST (DFR_TRAV_TYPE_HEADER | 0x10000000) + +#define DFR_TRAV_ROOT_IPOS (0xFFFFFFFFFFFFFFFFLL) + +struct defrag_trav_arg { + int type; + unsigned int start_clus; + loff_t i_pos; + char name[MAX_DOSNAME_BUF_SIZE]; + char dummy1; + int dummy2; +}; + +#define DFR_TRAV_STAT_DONE (0x1) +#define DFR_TRAV_STAT_MORE (0x2) +#define DFR_TRAV_STAT_ERR (0xFF) + +struct defrag_trav_header { + int type; + unsigned int start_clus; + loff_t i_pos; + char name[MAX_DOSNAME_BUF_SIZE]; + char stat; + unsigned int nr_entries; +}; + + +/* IOC_DFR_REQ */ +#define REQ_HEADER_IDX (0) + +#define DFR_CHUNK_STAT_ERR (0xFFFFFFFF) +#define DFR_CHUNK_STAT_REQ (0x1) +#define DFR_CHUNK_STAT_WB (0x2) +#define DFR_CHUNK_STAT_FAT (0x4) +#define DFR_CHUNK_STAT_PREP (DFR_CHUNK_STAT_REQ | DFR_CHUNK_STAT_WB | DFR_CHUNK_STAT_FAT) +#define DFR_CHUNK_STAT_PASS (0x0000000F) + +struct defrag_chunk_header { + int mode; + unsigned int nr_chunks; + loff_t dummy1; + int dummy2[4]; + union { + int *dummy3; + int dummy4; + }; + int dummy5; +}; + +struct defrag_chunk_info { + int stat; + /* File related */ + unsigned int f_clus; + loff_t i_pos; + /* Cluster related */ + unsigned int d_clus; + unsigned int nr_clus; + unsigned int prev_clus; + unsigned int next_clus; + union { + void *dummy; + /* req status */ + unsigned int new_idx; + }; + /* AU related */ + unsigned int au_clus; +}; + + +/* Global info */ +#define DFR_MODE_BACKGROUND (0x1) +#define DFR_MODE_FOREGROUND (0x2) +#define DFR_MODE_ONESHOT (0x4) +#define DFR_MODE_BATCHED (0x8) +#define DFR_MODE_TEST (DFR_MODE_BACKGROUND | 0x10000000) + +#define DFR_SB_STAT_IDLE (0) +#define DFR_SB_STAT_REQ (1) +#define DFR_SB_STAT_VALID (2) + +#define DFR_INO_STAT_IDLE (0) +#define DFR_INO_STAT_REQ (1) +struct defrag_info { + struct mutex lock; + atomic_t stat; + struct defrag_chunk_info *chunks; + unsigned int nr_chunks; + struct list_head entry; +}; + + +/* SPO test flags */ +#define DFR_SPO_NONE (0) +#define DFR_SPO_NORMAL (1) +#define DFR_SPO_DISCARD (2) +#define DFR_SPO_FAT_NEXT (3) +#define DFR_SPO_RANDOM (4) + + +/* Extern functions */ +int defrag_get_info(struct super_block *sb, struct defrag_info_arg *arg); + +int defrag_scan_dir(struct super_block *sb, struct defrag_trav_arg *arg); + +int defrag_validate_cluster(struct inode *inode, struct defrag_chunk_info *chunk, int skip_prev); +int defrag_reserve_clusters(struct super_block *sb, int nr_clus); +int defrag_mark_ignore(struct super_block *sb, unsigned int clus); +void defrag_unmark_ignore_all(struct super_block *sb); + +int defrag_map_cluster(struct inode *inode, unsigned int clu_offset, unsigned int *clu); +void defrag_writepage_end_io(struct page *page); + +void defrag_update_fat_prev(struct super_block *sb, int force); +void defrag_update_fat_next(struct super_block *sb); +void defrag_check_discard(struct super_block *sb); +int defrag_free_cluster(struct super_block *sb, unsigned int clus); + +int defrag_check_defrag_required(struct super_block *sb, int *totalau, int *cleanau, int *fullau); +int defrag_check_defrag_on(struct inode *inode, loff_t start, loff_t end, int cancel, const char *caller); + +#ifdef CONFIG_SDFAT_DFR_DEBUG +void defrag_spo_test(struct super_block *sb, int flag, const char *caller); +#endif + +#endif /* CONFIG_SDFAT_DFR */ + +#endif /* _SDFAT_DEFRAG_H */ + diff --git a/fs/sdfat/extent.c b/fs/sdfat/extent.c new file mode 100644 index 0000000000000..9349a59b4debe --- /dev/null +++ b/fs/sdfat/extent.c @@ -0,0 +1,355 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* + * linux/fs/fat/cache.c + * + * Written 1992,1993 by Werner Almesberger + * + * Mar 1999. AV. Changed cache, so that it uses the starting cluster instead + * of inode number. + * May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : extent.c */ +/* PURPOSE : Improve the performance of traversing fat chain. */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/* */ +/************************************************************************/ + +#include +#include "sdfat.h" +#include "core.h" + +#define EXTENT_CACHE_VALID 0 +/* this must be > 0. */ +#define EXTENT_MAX_CACHE 16 + +struct extent_cache { + struct list_head cache_list; + s32 nr_contig; /* number of contiguous clusters */ + s32 fcluster; /* cluster number in the file. */ + u32 dcluster; /* cluster number on disk. */ +}; + +struct extent_cache_id { + u32 id; + s32 nr_contig; + s32 fcluster; + u32 dcluster; +}; + +static struct kmem_cache *extent_cache_cachep; + +static void init_once(void *c) +{ + struct extent_cache *cache = (struct extent_cache *)c; + + INIT_LIST_HEAD(&cache->cache_list); +} + +s32 extent_cache_init(void) +{ + extent_cache_cachep = kmem_cache_create("sdfat_extent_cache", + sizeof(struct extent_cache), + 0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, + init_once); + if (!extent_cache_cachep) + return -ENOMEM; + return 0; +} + +void extent_cache_shutdown(void) +{ + if (!extent_cache_cachep) + return; + kmem_cache_destroy(extent_cache_cachep); +} + +void extent_cache_init_inode(struct inode *inode) +{ + EXTENT_T *extent = &(SDFAT_I(inode)->fid.extent); + + spin_lock_init(&extent->cache_lru_lock); + extent->nr_caches = 0; + extent->cache_valid_id = EXTENT_CACHE_VALID + 1; + INIT_LIST_HEAD(&extent->cache_lru); +} + +static inline struct extent_cache *extent_cache_alloc(void) +{ + return kmem_cache_alloc(extent_cache_cachep, GFP_NOFS); +} + +static inline void extent_cache_free(struct extent_cache *cache) +{ + BUG_ON(!list_empty(&cache->cache_list)); + kmem_cache_free(extent_cache_cachep, cache); +} + +static inline void extent_cache_update_lru(struct inode *inode, + struct extent_cache *cache) +{ + EXTENT_T *extent = &(SDFAT_I(inode)->fid.extent); + + if (extent->cache_lru.next != &cache->cache_list) + list_move(&cache->cache_list, &extent->cache_lru); +} + +static s32 extent_cache_lookup(struct inode *inode, s32 fclus, + struct extent_cache_id *cid, + s32 *cached_fclus, u32 *cached_dclus) +{ + EXTENT_T *extent = &(SDFAT_I(inode)->fid.extent); + + static struct extent_cache nohit = { .fcluster = 0, }; + + struct extent_cache *hit = &nohit, *p; + s32 offset = -1; + + spin_lock(&extent->cache_lru_lock); + list_for_each_entry(p, &extent->cache_lru, cache_list) { + /* Find the cache of "fclus" or nearest cache. */ + if (p->fcluster <= fclus && hit->fcluster < p->fcluster) { + hit = p; + if ((hit->fcluster + hit->nr_contig) < fclus) { + offset = hit->nr_contig; + } else { + offset = fclus - hit->fcluster; + break; + } + } + } + if (hit != &nohit) { + extent_cache_update_lru(inode, hit); + + cid->id = extent->cache_valid_id; + cid->nr_contig = hit->nr_contig; + cid->fcluster = hit->fcluster; + cid->dcluster = hit->dcluster; + *cached_fclus = cid->fcluster + offset; + *cached_dclus = cid->dcluster + offset; + } + spin_unlock(&extent->cache_lru_lock); + + return offset; +} + +static struct extent_cache *extent_cache_merge(struct inode *inode, + struct extent_cache_id *new) +{ + EXTENT_T *extent = &(SDFAT_I(inode)->fid.extent); + + struct extent_cache *p; + + list_for_each_entry(p, &extent->cache_lru, cache_list) { + /* Find the same part as "new" in cluster-chain. */ + if (p->fcluster == new->fcluster) { + ASSERT(p->dcluster == new->dcluster); + if (new->nr_contig > p->nr_contig) + p->nr_contig = new->nr_contig; + return p; + } + } + return NULL; +} + +static void extent_cache_add(struct inode *inode, struct extent_cache_id *new) +{ + EXTENT_T *extent = &(SDFAT_I(inode)->fid.extent); + + struct extent_cache *cache, *tmp; + + if (new->fcluster == -1) /* dummy cache */ + return; + + spin_lock(&extent->cache_lru_lock); + if (new->id != EXTENT_CACHE_VALID && + new->id != extent->cache_valid_id) + goto out; /* this cache was invalidated */ + + cache = extent_cache_merge(inode, new); + if (cache == NULL) { + if (extent->nr_caches < EXTENT_MAX_CACHE) { + extent->nr_caches++; + spin_unlock(&extent->cache_lru_lock); + + tmp = extent_cache_alloc(); + if (!tmp) { + spin_lock(&extent->cache_lru_lock); + extent->nr_caches--; + spin_unlock(&extent->cache_lru_lock); + return; + } + + spin_lock(&extent->cache_lru_lock); + cache = extent_cache_merge(inode, new); + if (cache != NULL) { + extent->nr_caches--; + extent_cache_free(tmp); + goto out_update_lru; + } + cache = tmp; + } else { + struct list_head *p = extent->cache_lru.prev; + cache = list_entry(p, struct extent_cache, cache_list); + } + cache->fcluster = new->fcluster; + cache->dcluster = new->dcluster; + cache->nr_contig = new->nr_contig; + } +out_update_lru: + extent_cache_update_lru(inode, cache); +out: + spin_unlock(&extent->cache_lru_lock); +} + +/* + * Cache invalidation occurs rarely, thus the LRU chain is not updated. It + * fixes itself after a while. + */ +static void __extent_cache_inval_inode(struct inode *inode) +{ + EXTENT_T *extent = &(SDFAT_I(inode)->fid.extent); + struct extent_cache *cache; + + while (!list_empty(&extent->cache_lru)) { + cache = list_entry(extent->cache_lru.next, + struct extent_cache, cache_list); + list_del_init(&cache->cache_list); + extent->nr_caches--; + extent_cache_free(cache); + } + /* Update. The copy of caches before this id is discarded. */ + extent->cache_valid_id++; + if (extent->cache_valid_id == EXTENT_CACHE_VALID) + extent->cache_valid_id++; +} + +void extent_cache_inval_inode(struct inode *inode) +{ + EXTENT_T *extent = &(SDFAT_I(inode)->fid.extent); + + spin_lock(&extent->cache_lru_lock); + __extent_cache_inval_inode(inode); + spin_unlock(&extent->cache_lru_lock); +} + +static inline s32 cache_contiguous(struct extent_cache_id *cid, u32 dclus) +{ + cid->nr_contig++; + return ((cid->dcluster + cid->nr_contig) == dclus); +} + +static inline void cache_init(struct extent_cache_id *cid, s32 fclus, u32 dclus) +{ + cid->id = EXTENT_CACHE_VALID; + cid->fcluster = fclus; + cid->dcluster = dclus; + cid->nr_contig = 0; +} + +s32 extent_get_clus(struct inode *inode, s32 cluster, s32 *fclus, + u32 *dclus, u32 *last_dclus, s32 allow_eof) +{ + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + s32 limit = (s32)(fsi->num_clusters); + FILE_ID_T *fid = &(SDFAT_I(inode)->fid); + struct extent_cache_id cid; + u32 content; + + /* FOR GRACEFUL ERROR HANDLING */ + if (IS_CLUS_FREE(fid->start_clu)) { + sdfat_fs_error(sb, "invalid access to " + "extent cache (entry 0x%08x)", fid->start_clu); + ASSERT(0); + return -EIO; + } + + /* We allow max clusters per a file upto max of signed integer */ + if (fsi->num_clusters & 0x80000000) + limit = 0x7FFFFFFF; + + *fclus = 0; + *dclus = fid->start_clu; + *last_dclus = *dclus; + + /* + * Don`t use extent_cache if zero offset or non-cluster allocation + */ + if ((cluster == 0) || IS_CLUS_EOF(*dclus)) + return 0; + + cache_init(&cid, -1, -1); + + if (extent_cache_lookup(inode, cluster, &cid, fclus, dclus) < 0) { + /* + * dummy, always not contiguous + * This is reinitialized by cache_init(), later. + */ + ASSERT((cid.id == EXTENT_CACHE_VALID) + && (cid.fcluster == -1) + && (cid.dcluster == -1) + && (cid.nr_contig == 0)); + } + + if (*fclus == cluster) + return 0; + + while (*fclus < cluster) { + /* prevent the infinite loop of cluster chain */ + if (*fclus > limit) { + sdfat_fs_error(sb, + "%s: detected the cluster chain loop" + " (i_pos %d)", __func__, + (*fclus)); + return -EIO; + } + + if (fat_ent_get_safe(sb, *dclus, &content)) + return -EIO; + + *last_dclus = *dclus; + *dclus = content; + (*fclus)++; + + if (IS_CLUS_EOF(content)) { + if (!allow_eof) { + sdfat_fs_error(sb, + "%s: invalid cluster chain (i_pos %d," + "last_clus 0x%08x is EOF)", + __func__, *fclus, (*last_dclus)); + return -EIO; + } + + break; + } + + if (!cache_contiguous(&cid, *dclus)) + cache_init(&cid, *fclus, *dclus); + } + + extent_cache_add(inode, &cid); + return 0; +} diff --git a/fs/sdfat/fatent.c b/fs/sdfat/fatent.c new file mode 100644 index 0000000000000..71d3653dd8051 --- /dev/null +++ b/fs/sdfat/fatent.c @@ -0,0 +1,412 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : fatent.c */ +/* PURPOSE : sdFAT FAT entry manager */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/* */ +/************************************************************************/ + +#include + +#include "sdfat.h" +#include "core.h" + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ +/* All buffer structures are protected w/ fsi->v_sem */ + +/*----------------------------------------------------------------------*/ +/* Static functions */ +/*----------------------------------------------------------------------*/ + +/*======================================================================*/ +/* FAT Read/Write Functions */ +/*======================================================================*/ +/* in : sb, loc + * out: content + * returns 0 on success, -1 on error + */ +static s32 exfat_ent_get(struct super_block *sb, u32 loc, u32 *content) +{ + u32 sec, off, _content; + u8 *fat_sector; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + /* fsi->vol_type == EXFAT */ + sec = fsi->FAT1_start_sector + (loc >> (sb->s_blocksize_bits-2)); + off = (loc << 2) & (u32)(sb->s_blocksize - 1); + + fat_sector = fcache_getblk(sb, sec); + if (!fat_sector) + return -EIO; + + _content = le32_to_cpu(*(__le32 *)(&fat_sector[off])); + + /* remap reserved clusters to simplify code */ + if (_content >= CLUSTER_32(0xFFFFFFF8)) + _content = CLUS_EOF; + + *content = CLUSTER_32(_content); + return 0; +} + +static s32 exfat_ent_set(struct super_block *sb, u32 loc, u32 content) +{ + u32 sec, off; + u8 *fat_sector; + __le32 *fat_entry; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + sec = fsi->FAT1_start_sector + (loc >> (sb->s_blocksize_bits-2)); + off = (loc << 2) & (u32)(sb->s_blocksize - 1); + + fat_sector = fcache_getblk(sb, sec); + if (!fat_sector) + return -EIO; + + fat_entry = (__le32 *)&(fat_sector[off]); + *fat_entry = cpu_to_le32(content); + + return fcache_modify(sb, sec); +} + +#define FATENT_FAT32_VALID_MASK (0x0FFFFFFFU) +#define FATENT_FAT32_IGNORE_MASK (0xF0000000U) +static s32 fat32_ent_get(struct super_block *sb, u32 loc, u32 *content) +{ + u32 sec, off, _content; + u8 *fat_sector; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + sec = fsi->FAT1_start_sector + (loc >> (sb->s_blocksize_bits-2)); + off = (loc << 2) & (u32)(sb->s_blocksize - 1); + + fat_sector = fcache_getblk(sb, sec); + if (!fat_sector) + return -EIO; + + _content = le32_to_cpu(*(__le32 *)(&fat_sector[off])); + _content &= FATENT_FAT32_VALID_MASK; + + /* remap reserved clusters to simplify code */ + if (_content == CLUSTER_32(0x0FFFFFF7U)) + _content = CLUS_BAD; + else if (_content >= CLUSTER_32(0x0FFFFFF8U)) + _content = CLUS_EOF; + + *content = CLUSTER_32(_content); + return 0; +} + +static s32 fat32_ent_set(struct super_block *sb, u32 loc, u32 content) +{ + u32 sec, off; + u8 *fat_sector; + __le32 *fat_entry; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + content &= FATENT_FAT32_VALID_MASK; + + sec = fsi->FAT1_start_sector + (loc >> (sb->s_blocksize_bits-2)); + off = (loc << 2) & (u32)(sb->s_blocksize - 1); + + fat_sector = fcache_getblk(sb, sec); + if (!fat_sector) + return -EIO; + + fat_entry = (__le32 *)&(fat_sector[off]); + content |= (le32_to_cpu(*fat_entry) & FATENT_FAT32_IGNORE_MASK); + *fat_entry = cpu_to_le32(content); + + return fcache_modify(sb, sec); +} + +#define FATENT_FAT16_VALID_MASK (0x0000FFFFU) +static s32 fat16_ent_get(struct super_block *sb, u32 loc, u32 *content) +{ + u32 sec, off, _content; + u8 *fat_sector; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + sec = fsi->FAT1_start_sector + (loc >> (sb->s_blocksize_bits-1)); + off = (loc << 1) & (u32)(sb->s_blocksize - 1); + + fat_sector = fcache_getblk(sb, sec); + if (!fat_sector) + return -EIO; + + _content = (u32)le16_to_cpu(*(__le16 *)(&fat_sector[off])); + _content &= FATENT_FAT16_VALID_MASK; + + /* remap reserved clusters to simplify code */ + if (_content == CLUSTER_16(0xFFF7U)) + _content = CLUS_BAD; + else if (_content >= CLUSTER_16(0xFFF8U)) + _content = CLUS_EOF; + + *content = CLUSTER_32(_content); + return 0; +} + +static s32 fat16_ent_set(struct super_block *sb, u32 loc, u32 content) +{ + u32 sec, off; + u8 *fat_sector; + __le16 *fat_entry; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + content &= FATENT_FAT16_VALID_MASK; + + sec = fsi->FAT1_start_sector + (loc >> (sb->s_blocksize_bits-1)); + off = (loc << 1) & (u32)(sb->s_blocksize - 1); + + fat_sector = fcache_getblk(sb, sec); + if (!fat_sector) + return -EIO; + + fat_entry = (__le16 *)&(fat_sector[off]); + *fat_entry = cpu_to_le16(content); + + return fcache_modify(sb, sec); +} + +#define FATENT_FAT12_VALID_MASK (0x00000FFFU) +static s32 fat12_ent_get(struct super_block *sb, u32 loc, u32 *content) +{ + u32 sec, off, _content; + u8 *fat_sector; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + sec = fsi->FAT1_start_sector + ((loc + (loc >> 1)) >> sb->s_blocksize_bits); + off = (loc + (loc >> 1)) & (u32)(sb->s_blocksize - 1); + + fat_sector = fcache_getblk(sb, sec); + if (!fat_sector) + return -EIO; + + if (off == (u32)(sb->s_blocksize - 1)) { + _content = (u32) fat_sector[off]; + + fat_sector = fcache_getblk(sb, ++sec); + if (!fat_sector) + return -EIO; + + _content |= (u32) fat_sector[0] << 8; + } else { + _content = get_unaligned_le16(&fat_sector[off]); + } + + if (loc & 1) + _content >>= 4; + + _content &= FATENT_FAT12_VALID_MASK; + + /* remap reserved clusters to simplify code */ + if (_content == CLUSTER_16(0x0FF7U)) + _content = CLUS_BAD; + else if (_content >= CLUSTER_16(0x0FF8U)) + _content = CLUS_EOF; + + *content = CLUSTER_32(_content); + return 0; +} + +static s32 fat12_ent_set(struct super_block *sb, u32 loc, u32 content) +{ + u32 sec, off; + u8 *fat_sector, *fat_entry; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + content &= FATENT_FAT12_VALID_MASK; + + sec = fsi->FAT1_start_sector + ((loc + (loc >> 1)) >> sb->s_blocksize_bits); + off = (loc + (loc >> 1)) & (u32)(sb->s_blocksize - 1); + + fat_sector = fcache_getblk(sb, sec); + if (!fat_sector) + return -EIO; + + if (loc & 1) { /* odd */ + + content <<= 4; + + if (off == (u32)(sb->s_blocksize-1)) { + fat_sector[off] = (u8)(content | (fat_sector[off] & 0x0F)); + if (fcache_modify(sb, sec)) + return -EIO; + + fat_sector = fcache_getblk(sb, ++sec); + if (!fat_sector) + return -EIO; + + fat_sector[0] = (u8)(content >> 8); + } else { + fat_entry = &(fat_sector[off]); + content |= 0x000F & get_unaligned_le16(fat_entry); + put_unaligned_le16(content, fat_entry); + } + } else { /* even */ + fat_sector[off] = (u8)(content); + + if (off == (u32)(sb->s_blocksize-1)) { + fat_sector[off] = (u8)(content); + if (fcache_modify(sb, sec)) + return -EIO; + + fat_sector = fcache_getblk(sb, ++sec); + if (!fat_sector) + return -EIO; + + fat_sector[0] = (u8)((fat_sector[0] & 0xF0) | (content >> 8)); + } else { + fat_entry = &(fat_sector[off]); + content |= 0xF000 & get_unaligned_le16(fat_entry); + put_unaligned_le16(content, fat_entry); + } + } + return fcache_modify(sb, sec); +} + + +static FATENT_OPS_T fat12_ent_ops = { + fat12_ent_get, + fat12_ent_set +}; + +static FATENT_OPS_T fat16_ent_ops = { + fat16_ent_get, + fat16_ent_set +}; + +static FATENT_OPS_T fat32_ent_ops = { + fat32_ent_get, + fat32_ent_set +}; + +static FATENT_OPS_T exfat_ent_ops = { + exfat_ent_get, + exfat_ent_set +}; + +s32 fat_ent_ops_init(struct super_block *sb) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + switch (fsi->vol_type) { + case EXFAT: + fsi->fatent_ops = &exfat_ent_ops; + break; + case FAT32: + fsi->fatent_ops = &fat32_ent_ops; + break; + case FAT16: + fsi->fatent_ops = &fat16_ent_ops; + break; + case FAT12: + fsi->fatent_ops = &fat12_ent_ops; + break; + default: + fsi->fatent_ops = NULL; + EMSG("Unknown volume type : %d", (int)fsi->vol_type); + return -ENOTSUPP; + } + + return 0; +} + +static inline bool is_reserved_clus(u32 clus) +{ + if (IS_CLUS_FREE(clus)) + return true; + if (IS_CLUS_EOF(clus)) + return true; + if (IS_CLUS_BAD(clus)) + return true; + return false; +} + +static inline bool is_valid_clus(FS_INFO_T *fsi, u32 clus) +{ + if (clus < CLUS_BASE || fsi->num_clusters <= clus) + return false; + return true; +} + +s32 fat_ent_get(struct super_block *sb, u32 loc, u32 *content) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + s32 err; + + if (!is_valid_clus(fsi, loc)) { + sdfat_fs_error(sb, "invalid access to FAT (entry 0x%08x)", loc); + return -EIO; + } + + err = fsi->fatent_ops->ent_get(sb, loc, content); + if (err) { + sdfat_fs_error(sb, "failed to access to FAT " + "(entry 0x%08x, err:%d)", loc, err); + return err; + } + + if (!is_reserved_clus(*content) && !is_valid_clus(fsi, *content)) { + sdfat_fs_error(sb, "invalid access to FAT (entry 0x%08x) " + "bogus content (0x%08x)", loc, *content); + return -EIO; + } + + return 0; +} + +s32 fat_ent_set(struct super_block *sb, u32 loc, u32 content) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + return fsi->fatent_ops->ent_set(sb, loc, content); +} + +s32 fat_ent_get_safe(struct super_block *sb, u32 loc, u32 *content) +{ + s32 err = fat_ent_get(sb, loc, content); + + if (err) + return err; + + if (IS_CLUS_FREE(*content)) { + sdfat_fs_error(sb, "invalid access to FAT free cluster " + "(entry 0x%08x)", loc); + return -EIO; + } + + if (IS_CLUS_BAD(*content)) { + sdfat_fs_error(sb, "invalid access to FAT bad cluster " + "(entry 0x%08x)", loc); + return -EIO; + } + + return 0; +} + +/* end of fatent.c */ diff --git a/fs/sdfat/misc.c b/fs/sdfat/misc.c new file mode 100644 index 0000000000000..566f99bf2975f --- /dev/null +++ b/fs/sdfat/misc.c @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* + * linux/fs/fat/misc.c + * + * Written 1992,1993 by Werner Almesberger + * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980 + * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru) + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : misc.c */ +/* PURPOSE : Helper function for checksum and handing sdFAT error */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/* */ +/************************************************************************/ + +#include +#include +#include +#include +#include "sdfat.h" +#include "version.h" + +#ifdef CONFIG_SDFAT_SUPPORT_STLOG +#include +#else +#define ST_LOG(fmt, ...) +#endif + +/* + * sdfat_fs_error reports a file system problem that might indicate fa data + * corruption/inconsistency. Depending on 'errors' mount option the + * panic() is called, or error message is printed FAT and nothing is done, + * or filesystem is remounted read-only (default behavior). + * In case the file system is remounted read-only, it can be made writable + * again by remounting it. + */ +void __sdfat_fs_error(struct super_block *sb, int report, const char *fmt, ...) +{ + struct sdfat_mount_options *opts = &SDFAT_SB(sb)->options; + va_list args; + struct va_format vaf; + struct block_device *bdev = sb->s_bdev; + dev_t bd_dev = bdev ? bdev->bd_dev : 0; + + if (report) { + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + pr_err("[SDFAT](%s[%d:%d]):ERR: %pV\n", + sb->s_id, MAJOR(bd_dev), MINOR(bd_dev), &vaf); +#ifdef CONFIG_SDFAT_SUPPORT_STLOG + if (opts->errors == SDFAT_ERRORS_RO && !(sb->s_flags & MS_RDONLY)) { + ST_LOG("[SDFAT](%s[%d:%d]):ERR: %pV\n", + sb->s_id, MAJOR(bd_dev), MINOR(bd_dev), &vaf); + } +#endif + va_end(args); + } + + if (opts->errors == SDFAT_ERRORS_PANIC) { + panic("[SDFAT](%s[%d:%d]): fs panic from previous error\n", + sb->s_id, MAJOR(bd_dev), MINOR(bd_dev)); + } else if (opts->errors == SDFAT_ERRORS_RO && !(sb->s_flags & MS_RDONLY)) { + sb->s_flags |= MS_RDONLY; + pr_err("[SDFAT](%s[%d:%d]): Filesystem has been set " + "read-only\n", sb->s_id, MAJOR(bd_dev), MINOR(bd_dev)); +#ifdef CONFIG_SDFAT_SUPPORT_STLOG + ST_LOG("[SDFAT](%s[%d:%d]): Filesystem has been set read-only\n", + sb->s_id, MAJOR(bd_dev), MINOR(bd_dev)); +#endif + } +} +EXPORT_SYMBOL(__sdfat_fs_error); + +/** + * __sdfat_msg() - print preformated SDFAT specific messages. + * All logs except what uses sdfat_fs_error() should be written by __sdfat_msg() + * If 'st' is set, the log is propagated to ST_LOG. + */ +void __sdfat_msg(struct super_block *sb, const char *level, int st, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + struct block_device *bdev = sb->s_bdev; + dev_t bd_dev = bdev ? bdev->bd_dev : 0; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + /* level means KERN_ pacility level */ + printk("%s[SDFAT](%s[%d:%d]): %pV\n", level, + sb->s_id, MAJOR(bd_dev), MINOR(bd_dev), &vaf); +#ifdef CONFIG_SDFAT_SUPPORT_STLOG + if (st) { + ST_LOG("[SDFAT](%s[%d:%d]): %pV\n", + sb->s_id, MAJOR(bd_dev), MINOR(bd_dev), &vaf); + } +#endif + va_end(args); +} +EXPORT_SYMBOL(__sdfat_msg); + +void sdfat_log_version(void) +{ + pr_info("[SDFAT] Filesystem version %s\n", SDFAT_VERSION); +#ifdef CONFIG_SDFAT_SUPPORT_STLOG + ST_LOG("[SDFAT] Filesystem version %s\n", SDFAT_VERSION); +#endif +} +EXPORT_SYMBOL(sdfat_log_version); + +/* externs sys_tz + * extern struct timezone sys_tz; + */ +#define UNIX_SECS_1980 315532800L + +#if BITS_PER_LONG == 64 +#define UNIX_SECS_2108 4354819200L +#endif + +/* days between 1970/01/01 and 1980/01/01 (2 leap days) */ +#define DAYS_DELTA_DECADE (365 * 10 + 2) +/* 120 (2100 - 1980) isn't leap year */ +#define NO_LEAP_YEAR_2100 (120) +#define IS_LEAP_YEAR(y) (!((y) & 0x3) && (y) != NO_LEAP_YEAR_2100) + +#define SECS_PER_MIN (60) +#define SECS_PER_HOUR (60 * SECS_PER_MIN) +#define SECS_PER_DAY (24 * SECS_PER_HOUR) + +#define MAKE_LEAP_YEAR(leap_year, year) \ + do { \ + /* 2100 isn't leap year */ \ + if (unlikely(year > NO_LEAP_YEAR_2100)) \ + leap_year = ((year + 3) / 4) - 1; \ + else \ + leap_year = ((year + 3) / 4); \ + } while (0) + +/* Linear day numbers of the respective 1sts in non-leap years. */ +static time_t accum_days_in_year[] = { + /* Month : N 01 02 03 04 05 06 07 08 09 10 11 12 */ + 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, +}; + +/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */ +void sdfat_time_fat2unix(struct sdfat_sb_info *sbi, struct timespec *ts, + DATE_TIME_T *tp) +{ + time_t year = tp->Year; + time_t ld; /* leap day */ + + MAKE_LEAP_YEAR(ld, year); + + if (IS_LEAP_YEAR(year) && (tp->Month) > 2) + ld++; + + ts->tv_sec = tp->Second + tp->Minute * SECS_PER_MIN + + tp->Hour * SECS_PER_HOUR + + (year * 365 + ld + accum_days_in_year[tp->Month] + + (tp->Day - 1) + DAYS_DELTA_DECADE) * SECS_PER_DAY; + + if (!sbi->options.tz_utc) + ts->tv_sec += sys_tz.tz_minuteswest * SECS_PER_MIN; + + ts->tv_nsec = 0; +} + +/* Convert linear UNIX date to a FAT time/date pair. */ +void sdfat_time_unix2fat(struct sdfat_sb_info *sbi, struct timespec *ts, + DATE_TIME_T *tp) +{ + time_t second = ts->tv_sec; + time_t day, month, year; + time_t ld; /* leap day */ + + if (!sbi->options.tz_utc) + second -= sys_tz.tz_minuteswest * SECS_PER_MIN; + + /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ + if (second < UNIX_SECS_1980) { + tp->Second = 0; + tp->Minute = 0; + tp->Hour = 0; + tp->Day = 1; + tp->Month = 1; + tp->Year = 0; + return; + } +#if (BITS_PER_LONG == 64) + if (second >= UNIX_SECS_2108) { + tp->Second = 59; + tp->Minute = 59; + tp->Hour = 23; + tp->Day = 31; + tp->Month = 12; + tp->Year = 127; + return; + } +#endif + + day = second / SECS_PER_DAY - DAYS_DELTA_DECADE; + year = day / 365; + + MAKE_LEAP_YEAR(ld, year); + if (year * 365 + ld > day) + year--; + + MAKE_LEAP_YEAR(ld, year); + day -= year * 365 + ld; + + if (IS_LEAP_YEAR(year) && day == accum_days_in_year[3]) { + month = 2; + } else { + if (IS_LEAP_YEAR(year) && day > accum_days_in_year[3]) + day--; + for (month = 1; month < 12; month++) { + if (accum_days_in_year[month + 1] > day) + break; + } + } + day -= accum_days_in_year[month]; + + tp->Second = second % SECS_PER_MIN; + tp->Minute = (second / SECS_PER_MIN) % 60; + tp->Hour = (second / SECS_PER_HOUR) % 24; + tp->Day = day + 1; + tp->Month = month; + tp->Year = year; +} + +TIMESTAMP_T *tm_now(struct sdfat_sb_info *sbi, TIMESTAMP_T *tp) +{ + struct timespec ts = CURRENT_TIME_SEC; + DATE_TIME_T dt; + + sdfat_time_unix2fat(sbi, &ts, &dt); + + tp->year = dt.Year; + tp->mon = dt.Month; + tp->day = dt.Day; + tp->hour = dt.Hour; + tp->min = dt.Minute; + tp->sec = dt.Second; + + return tp; +} + +u8 calc_chksum_1byte(void *data, s32 len, u8 chksum) +{ + s32 i; + u8 *c = (u8 *) data; + + for (i = 0; i < len; i++, c++) + chksum = (((chksum & 1) << 7) | ((chksum & 0xFE) >> 1)) + *c; + + return chksum; +} + +u16 calc_chksum_2byte(void *data, s32 len, u16 chksum, s32 type) +{ + s32 i; + u8 *c = (u8 *) data; + + for (i = 0; i < len; i++, c++) { + if (((i == 2) || (i == 3)) && (type == CS_DIR_ENTRY)) + continue; + chksum = (((chksum & 1) << 15) | ((chksum & 0xFFFE) >> 1)) + (u16) *c; + } + return chksum; +} + +#ifdef CONFIG_SDFAT_TRACE_ELAPSED_TIME +struct timeval __t1, __t2; +u32 sdfat_time_current_usec(struct timeval *tv) +{ + do_gettimeofday(tv); + return (u32)(tv->tv_sec*1000000 + tv->tv_usec); +} +#endif /* CONFIG_SDFAT_TRACE_ELAPSED_TIME */ + +#ifdef CONFIG_SDFAT_DBG_CAREFUL +/* Check the consistency of i_size_ondisk (FAT32, or flags 0x01 only) */ +void sdfat_debug_check_clusters(struct inode *inode) +{ + int num_clusters; + volatile uint32_t tmp_fat_chain[50]; + volatile int num_clusters_org, tmp_i = 0; + CHAIN_T clu; + FILE_ID_T *fid = &(SDFAT_I(inode)->fid); + FS_INFO_T *fsi = &(SDFAT_SB(inode->i_sb)->fsi); + + if (SDFAT_I(inode)->i_size_ondisk == 0) + num_clusters = 0; + else + num_clusters = (s32)((SDFAT_I(inode)->i_size_ondisk-1) >> fsi->cluster_size_bits) + 1; + + clu.dir = fid->start_clu; + clu.size = num_clusters; + clu.flags = fid->flags; + + num_clusters_org = num_clusters; + + if (clu.flags == 0x03) + return; + + while (num_clusters > 0) { + /* FAT chain logging */ + tmp_fat_chain[tmp_i] = clu.dir; + tmp_i++; + if (tmp_i >= 50) + tmp_i = 0; + + BUG_ON(IS_CLUS_EOF(clu.dir) || IS_CLUS_FREE(clu.dir)); + + if (get_next_clus_safe(inode->i_sb, &(clu.dir))) + EMSG("%s: failed to access to FAT\n"); + + num_clusters--; + } + + BUG_ON(!IS_CLUS_EOF(clu.dir)); +} + +#endif /* CONFIG_SDFAT_DBG_CAREFUL */ + +#ifdef CONFIG_SDFAT_DBG_MSG +void __sdfat_dmsg(int level, const char *fmt, ...) +{ +#ifdef CONFIG_SDFAT_DBG_SHOW_PID + struct va_format vaf; + va_list args; + + /* should check type */ + if (level > SDFAT_MSG_LEVEL) + return; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + /* fmt already includes KERN_ pacility level */ + printk("[%u] %pV", current->pid, &vaf); + va_end(args); +#else + va_list args; + + /* should check type */ + if (level > SDFAT_MSG_LEVEL) + return; + + va_start(args, fmt); + /* fmt already includes KERN_ pacility level */ + vprintk(fmt, args); + va_end(args); +#endif +} +#endif + diff --git a/fs/sdfat/mpage.c b/fs/sdfat/mpage.c new file mode 100644 index 0000000000000..8a0ce7f89e729 --- /dev/null +++ b/fs/sdfat/mpage.c @@ -0,0 +1,607 @@ +/* + * fs/mpage.c + * + * Copyright (C) 2002, Linus Torvalds. + * + * Contains functions related to preparing and submitting BIOs which contain + * multiple pagecache pages. + * + * 15May2002 Andrew Morton + * Initial version + * 27Jun2002 axboe@suse.de + * use bio_add_page() to build bio's just the right size + */ + +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : core.c */ +/* PURPOSE : sdFAT glue layer for supporting VFS */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/* */ +/************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for mark_page_accessed() */ +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) +#include +#endif + +#include "sdfat.h" + +#ifdef CONFIG_SDFAT_ALIGNED_MPAGE_WRITE + +/************************************************************************* + * INNER FUNCTIONS FOR FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY + *************************************************************************/ +static void __mpage_write_end_io(struct bio *bio, int err); + +/************************************************************************* + * FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY + *************************************************************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) +static inline void __sdfat_submit_bio_write2(int flags, struct bio *bio) +{ + bio_set_op_attrs(bio, REQ_OP_WRITE, flags); + submit_bio(bio); +} +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) */ +static inline void __sdfat_submit_bio_write2(int flags, struct bio *bio) +{ + submit_bio(WRITE | flags, bio); +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) +static void mpage_write_end_io(struct bio *bio) +{ + __mpage_write_end_io(bio, bio->bi_error); +} +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) */ +static void mpage_write_end_io(struct bio *bio, int err) +{ + if (test_bit(BIO_UPTODATE, &bio->bi_flags)) + err = 0; + __mpage_write_end_io(bio, err); +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) +static inline int bio_get_nr_vecs(struct block_device *bdev) +{ + return BIO_MAX_PAGES; +} +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0) */ + /* EMPTY */ +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) +static inline sector_t __sdfat_bio_sector(struct bio *bio) +{ + return bio->bi_iter.bi_sector; +} + +static inline void __sdfat_set_bio_sector(struct bio *bio, sector_t sector) +{ + bio->bi_iter.bi_sector = sector; +} + +static inline unsigned int __sdfat_bio_size(struct bio *bio) +{ + return bio->bi_iter.bi_size; +} + +static inline void __sdfat_set_bio_size(struct bio *bio, unsigned int size) +{ + bio->bi_iter.bi_size = size; +} +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */ +static inline sector_t __sdfat_bio_sector(struct bio *bio) +{ + return bio->bi_sector; +} + +static inline void __sdfat_set_bio_sector(struct bio *bio, sector_t sector) +{ + bio->bi_sector = sector; +} + +static inline unsigned int __sdfat_bio_size(struct bio *bio) +{ + return bio->bi_size; +} + +static inline void __sdfat_set_bio_size(struct bio *bio, unsigned int size) +{ + bio->bi_size = size; +} +#endif + +/* __check_dfr_on() and __dfr_writepage_end_io() functions + * are copied from sdfat.c + * Each function should be same perfectly + */ +static inline int __check_dfr_on(struct inode *inode, loff_t start, loff_t end, const char *fname) +{ +#ifdef CONFIG_SDFAT_DFR + struct defrag_info *ino_dfr = &(SDFAT_I(inode)->dfr_info); + + if ((atomic_read(&ino_dfr->stat) == DFR_INO_STAT_REQ) && + fsapi_dfr_check_dfr_on(inode, start, end, 0, fname)) + return 1; +#endif + return 0; +} + +static inline int __dfr_writepage_end_io(struct page *page) +{ +#ifdef CONFIG_SDFAT_DFR + struct defrag_info *ino_dfr = &(SDFAT_I(page->mapping->host)->dfr_info); + + if (atomic_read(&ino_dfr->stat) == DFR_INO_STAT_REQ) + fsapi_dfr_writepage_endio(page); +#endif + return 0; +} + + +static inline unsigned int __calc_size_to_align(struct super_block *sb) +{ + struct block_device *bdev = sb->s_bdev; + struct gendisk *disk; + struct request_queue *queue; + struct queue_limits *limit; + unsigned int max_sectors; + unsigned int aligned = 0; + + disk = bdev->bd_disk; + if (!disk) + goto out; + + queue = disk->queue; + if (!queue) + goto out; + + limit = &queue->limits; + max_sectors = limit->max_sectors; + aligned = 1 << ilog2(max_sectors); + + if (aligned && (max_sectors & (aligned - 1))) + aligned = 0; +out: + return aligned; +} + +struct mpage_data { + struct bio *bio; + sector_t last_block_in_bio; + get_block_t *get_block; + unsigned int use_writepage; + unsigned int size_to_align; +}; + +/* + * I/O completion handler for multipage BIOs. + * + * The mpage code never puts partial pages into a BIO (except for end-of-file). + * If a page does not map to a contiguous run of blocks then it simply falls + * back to block_read_full_page(). + * + * Why is this? If a page's completion depends on a number of different BIOs + * which can complete in any order (or at the same time) then determining the + * status of that page is hard. See end_buffer_async_read() for the details. + * There is no point in duplicating all that complexity. + */ +static void __mpage_write_end_io(struct bio *bio, int err) +{ + struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; + + ASSERT(bio_data_dir(bio) == WRITE); /* only write */ + + do { + struct page *page = bvec->bv_page; + + if (--bvec >= bio->bi_io_vec) + prefetchw(&bvec->bv_page->flags); + if (err) { + SetPageError(page); + if (page->mapping) + mapping_set_error(page->mapping, err); + } + + __dfr_writepage_end_io(page); + + end_page_writeback(page); + } while (bvec >= bio->bi_io_vec); + bio_put(bio); +} + +static struct bio *mpage_bio_submit_write(int flags, struct bio *bio) +{ + bio->bi_end_io = mpage_write_end_io; + __sdfat_submit_bio_write2(flags, bio); + return NULL; +} + +static struct bio * +mpage_alloc(struct block_device *bdev, + sector_t first_sector, int nr_vecs, + gfp_t gfp_flags) +{ + struct bio *bio; + + bio = bio_alloc(gfp_flags, nr_vecs); + + if (bio == NULL && (current->flags & PF_MEMALLOC)) { + while (!bio && (nr_vecs /= 2)) + bio = bio_alloc(gfp_flags, nr_vecs); + } + + if (bio) { + bio->bi_bdev = bdev; + __sdfat_set_bio_sector(bio, first_sector); + } + return bio; +} + +static int sdfat_mpage_writepage(struct page *page, + struct writeback_control *wbc, void *data) +{ + struct mpage_data *mpd = data; + struct bio *bio = mpd->bio; + struct address_space *mapping = page->mapping; + struct inode *inode = page->mapping->host; + const unsigned int blkbits = inode->i_blkbits; + const unsigned int blocks_per_page = PAGE_SIZE >> blkbits; + sector_t last_block; + sector_t block_in_file; + sector_t blocks[MAX_BUF_PER_PAGE]; + unsigned int page_block; + unsigned int first_unmapped = blocks_per_page; + struct block_device *bdev = NULL; + int boundary = 0; + sector_t boundary_block = 0; + struct block_device *boundary_bdev = NULL; + int length; + struct buffer_head map_bh; + loff_t i_size = i_size_read(inode); + unsigned long end_index = i_size >> PAGE_SHIFT; + int ret = 0; + + if (page_has_buffers(page)) { + struct buffer_head *head = page_buffers(page); + struct buffer_head *bh = head; + + /* If they're all mapped and dirty, do it */ + page_block = 0; + do { + BUG_ON(buffer_locked(bh)); + if (!buffer_mapped(bh)) { + /* + * unmapped dirty buffers are created by + * __set_page_dirty_buffers -> mmapped data + */ + if (buffer_dirty(bh)) + goto confused; + if (first_unmapped == blocks_per_page) + first_unmapped = page_block; + continue; + } + + if (first_unmapped != blocks_per_page) + goto confused; /* hole -> non-hole */ + + if (!buffer_dirty(bh) || !buffer_uptodate(bh)) + goto confused; + + /* bh should be mapped if delay is set */ + if (buffer_delay(bh)) { + sector_t blk_in_file = + (sector_t)(page->index << (PAGE_SHIFT - blkbits)) + page_block; + + BUG_ON(bh->b_size != (1 << blkbits)); + if (page->index > end_index) { + MMSG("%s(inode:%p) " + "over end with delayed buffer" + "(page_idx:%u, end_idx:%u)\n", + __func__, inode, + (u32)page->index, + (u32)end_index); + goto confused; + } + + ret = mpd->get_block(inode, blk_in_file, bh, 1); + if (ret) { + MMSG("%s(inode:%p) " + "failed to getblk(ret:%d)\n", + __func__, inode, ret); + goto confused; + } + + BUG_ON(buffer_delay(bh)); + + if (buffer_new(bh)) { + clear_buffer_new(bh); + unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr); + } + } + + if (page_block) { + if (bh->b_blocknr != blocks[page_block-1] + 1) { + MMSG("%s(inode:%p) pblk(%d) " + "no_seq(prev:%lld, new:%lld)\n", + __func__, inode, page_block, + (u64)blocks[page_block-1], + (u64)bh->b_blocknr); + goto confused; + } + } + blocks[page_block++] = bh->b_blocknr; + boundary = buffer_boundary(bh); + if (boundary) { + boundary_block = bh->b_blocknr; + boundary_bdev = bh->b_bdev; + } + bdev = bh->b_bdev; + } while ((bh = bh->b_this_page) != head); + + if (first_unmapped) + goto page_is_mapped; + + /* + * Page has buffers, but they are all unmapped. The page was + * created by pagein or read over a hole which was handled by + * block_read_full_page(). If this address_space is also + * using mpage_readpages then this can rarely happen. + */ + goto confused; + } + + /* + * The page has no buffers: map it to disk + */ + BUG_ON(!PageUptodate(page)); + block_in_file = (sector_t)page->index << (PAGE_SHIFT - blkbits); + last_block = (i_size - 1) >> blkbits; + map_bh.b_page = page; + for (page_block = 0; page_block < blocks_per_page; ) { + + map_bh.b_state = 0; + map_bh.b_size = 1 << blkbits; + if (mpd->get_block(inode, block_in_file, &map_bh, 1)) + goto confused; + + if (buffer_new(&map_bh)) + unmap_underlying_metadata(map_bh.b_bdev, + map_bh.b_blocknr); + if (buffer_boundary(&map_bh)) { + boundary_block = map_bh.b_blocknr; + boundary_bdev = map_bh.b_bdev; + } + + if (page_block) { + if (map_bh.b_blocknr != blocks[page_block-1] + 1) + goto confused; + } + blocks[page_block++] = map_bh.b_blocknr; + boundary = buffer_boundary(&map_bh); + bdev = map_bh.b_bdev; + if (block_in_file == last_block) + break; + block_in_file++; + } + BUG_ON(page_block == 0); + + first_unmapped = page_block; + +page_is_mapped: + if (page->index >= end_index) { + /* + * The page straddles i_size. It must be zeroed out on each + * and every writepage invocation because it may be mmapped. + * "A file is mapped in multiples of the page size. For a file + * that is not a multiple of the page size, the remaining memory + * is zeroed when mapped, and writes to that region are not + * written out to the file." + */ + unsigned int offset = i_size & (PAGE_SIZE - 1); + + if (page->index > end_index || !offset) { + MMSG("%s(inode:%p) over end " + "(page_idx:%u, end_idx:%u off:%u)\n", + __func__, inode, (u32)page->index, + (u32)end_index, (u32)offset); + goto confused; + } + zero_user_segment(page, offset, PAGE_SIZE); + } + + /* + * This page will go to BIO. Do we need to send this BIO off first? + * + * REMARK : added ELSE_IF for ALIGNMENT_MPAGE_WRITE of SDFAT + */ + if (bio) { + if (mpd->last_block_in_bio != blocks[0] - 1) { + bio = mpage_bio_submit_write(0, bio); + } else if (mpd->size_to_align) { + unsigned int mask = mpd->size_to_align - 1; + sector_t max_end_block = + (__sdfat_bio_sector(bio) & ~(mask)) + mask; + + if ((__sdfat_bio_size(bio) != (1 << (mask + 1))) && + (mpd->last_block_in_bio == max_end_block)) { + MMSG("%s(inode:%p) alignment mpage_bio_submit" + "(start:%u, len:%u aligned:%u)\n", + __func__, inode, + (unsigned int)__sdfat_bio_sector(bio), + (unsigned int)(mpd->last_block_in_bio - + __sdfat_bio_sector(bio) + 1), + (unsigned int)mpd->size_to_align); + bio = mpage_bio_submit_write(REQ_NOMERGE, bio); + } + } + } + +alloc_new: + if (!bio) { + bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9), + bio_get_nr_vecs(bdev), GFP_NOFS|__GFP_HIGH); + if (!bio) + goto confused; + } + + /* + * Must try to add the page before marking the buffer clean or + * the confused fail path above (OOM) will be very confused when + * it finds all bh marked clean (i.e. it will not write anything) + */ + length = first_unmapped << blkbits; + if (bio_add_page(bio, page, length, 0) < length) { + bio = mpage_bio_submit_write(0, bio); + goto alloc_new; + } + + /* + * OK, we have our BIO, so we can now mark the buffers clean. Make + * sure to only clean buffers which we know we'll be writing. + */ + if (page_has_buffers(page)) { + struct buffer_head *head = page_buffers(page); + struct buffer_head *bh = head; + unsigned int buffer_counter = 0; + + do { + if (buffer_counter++ == first_unmapped) + break; + clear_buffer_dirty(bh); + bh = bh->b_this_page; + } while (bh != head); + + /* + * we cannot drop the bh if the page is not uptodate + * or a concurrent readpage would fail to serialize with the bh + * and it would read from disk before we reach the platter. + */ + if (buffer_heads_over_limit && PageUptodate(page)) + try_to_free_buffers(page); + } + + BUG_ON(PageWriteback(page)); + set_page_writeback(page); + + /* + * FIXME FOR DEFRAGMENTATION : CODE REVIEW IS REQUIRED + * + * Turn off MAPPED flag in victim's bh if defrag on. + * Another write_begin can starts after get_block for defrag victims + * called. + * In this case, write_begin calls get_block and get original block + * number and previous defrag will be canceled. + */ + if (unlikely(__check_dfr_on(inode, (loff_t)(page->index << PAGE_SHIFT), + (loff_t)((page->index + 1) << PAGE_SHIFT), __func__))) { + struct buffer_head *head = page_buffers(page); + struct buffer_head *bh = head; + + do { + clear_buffer_mapped(bh); + bh = bh->b_this_page; + } while (bh != head); + } + + unlock_page(page); + if (boundary || (first_unmapped != blocks_per_page)) { + bio = mpage_bio_submit_write(0, bio); + if (boundary_block) { + write_boundary_block(boundary_bdev, + boundary_block, 1 << blkbits); + } + } else { + mpd->last_block_in_bio = blocks[blocks_per_page - 1]; + } + + goto out; + +confused: + if (bio) + bio = mpage_bio_submit_write(0, bio); + + if (mpd->use_writepage) { + ret = mapping->a_ops->writepage(page, wbc); + } else { + ret = -EAGAIN; + goto out; + } + /* + * The caller has a ref on the inode, so *mapping is stable + */ + mapping_set_error(mapping, ret); +out: + mpd->bio = bio; + return ret; +} + +int sdfat_mpage_writepages(struct address_space *mapping, + struct writeback_control *wbc, get_block_t *get_block) +{ + struct blk_plug plug; + int ret; + struct mpage_data mpd = { + .bio = NULL, + .last_block_in_bio = 0, + .get_block = get_block, + .use_writepage = 1, + .size_to_align = __calc_size_to_align(mapping->host->i_sb), + }; + + BUG_ON(!get_block); + blk_start_plug(&plug); + ret = write_cache_pages(mapping, wbc, sdfat_mpage_writepage, &mpd); + if (mpd.bio) + mpage_bio_submit_write(0, mpd.bio); + blk_finish_plug(&plug); + return ret; +} + +#endif /* CONFIG_SDFAT_ALIGNED_MPAGE_WRITE */ + diff --git a/fs/sdfat/nls.c b/fs/sdfat/nls.c new file mode 100644 index 0000000000000..b65634454c557 --- /dev/null +++ b/fs/sdfat/nls.c @@ -0,0 +1,478 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : nls.c */ +/* PURPOSE : sdFAT NLS Manager */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/* */ +/************************************************************************/ +#include +#include + +#include "sdfat.h" +#include "core.h" + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ + +static u16 bad_dos_chars[] = { + /* + , ; = [ ] */ + 0x002B, 0x002C, 0x003B, 0x003D, 0x005B, 0x005D, + 0xFF0B, 0xFF0C, 0xFF1B, 0xFF1D, 0xFF3B, 0xFF3D, + 0 +}; + +/* + * Allow full-width illegal characters : + * "MS windows 7" supports full-width-invalid-name-characters. + * So we should check half-width-invalid-name-characters(ASCII) only + * for compatibility. + * + * " * / : < > ? \ | + * + * patch 1.2.0 + */ +static u16 bad_uni_chars[] = { + 0x0022, 0x002A, 0x002F, 0x003A, + 0x003C, 0x003E, 0x003F, 0x005C, 0x007C, +#if 0 /* allow full-width characters */ + 0x201C, 0x201D, 0xFF0A, 0xFF0F, 0xFF1A, + 0xFF1C, 0xFF1E, 0xFF1F, 0xFF3C, 0xFF5C, +#endif + 0 +}; + +/*----------------------------------------------------------------------*/ +/* Local Function Declarations */ +/*----------------------------------------------------------------------*/ +static s32 convert_uni_to_ch(struct nls_table *nls, u16 uni, u8 *ch, s32 *lossy); +static s32 convert_ch_to_uni(struct nls_table *nls, u8 *ch, u16 *uni, s32 *lossy); + +static u16 nls_upper(struct super_block *sb, u16 a) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + if (SDFAT_SB(sb)->options.casesensitive) + return a; + if ((fsi->vol_utbl)[get_col_index(a)] != NULL) + return (fsi->vol_utbl)[get_col_index(a)][get_row_index(a)]; + else + return a; +} +/*======================================================================*/ +/* Global Function Definitions */ +/*======================================================================*/ +u16 *nls_wstrchr(u16 *str, u16 wchar) +{ + while (*str) { + if (*(str++) == wchar) + return str; + } + + return 0; +} + +s32 nls_cmp_sfn(struct super_block *sb, u8 *a, u8 *b) +{ + return strncmp((void *)a, (void *)b, DOS_NAME_LENGTH); +} + +s32 nls_cmp_uniname(struct super_block *sb, u16 *a, u16 *b) +{ + s32 i; + + for (i = 0; i < MAX_NAME_LENGTH; i++, a++, b++) { + if (nls_upper(sb, *a) != nls_upper(sb, *b)) + return 1; + if (*a == 0x0) + return 0; + } + return 0; +} + +#define CASE_LOWER_BASE (0x08) /* base is lower case */ +#define CASE_LOWER_EXT (0x10) /* extension is lower case */ + +s32 nls_uni16s_to_sfn(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname, s32 *p_lossy) +{ + s32 i, j, len, lossy = NLS_NAME_NO_LOSSY; + u8 buf[MAX_CHARSET_SIZE]; + u8 lower = 0, upper = 0; + u8 *dosname = p_dosname->name; + u16 *uniname = p_uniname->name; + u16 *p, *last_period; + struct nls_table *nls = SDFAT_SB(sb)->nls_disk; + + /* DOSNAME is filled with space */ + for (i = 0; i < DOS_NAME_LENGTH; i++) + *(dosname+i) = ' '; + + /* DOT and DOTDOT are handled by VFS layer */ + + /* search for the last embedded period */ + last_period = NULL; + for (p = uniname; *p; p++) { + if (*p == (u16) '.') + last_period = p; + } + + i = 0; + while (i < DOS_NAME_LENGTH) { + if (i == 8) { + if (last_period == NULL) + break; + + if (uniname <= last_period) { + if (uniname < last_period) + lossy |= NLS_NAME_OVERLEN; + uniname = last_period + 1; + } + } + + if (*uniname == (u16) '\0') { + break; + } else if (*uniname == (u16) ' ') { + lossy |= NLS_NAME_LOSSY; + } else if (*uniname == (u16) '.') { + if (uniname < last_period) + lossy |= NLS_NAME_LOSSY; + else + i = 8; + } else if (nls_wstrchr(bad_dos_chars, *uniname)) { + lossy |= NLS_NAME_LOSSY; + *(dosname+i) = '_'; + i++; + } else { + len = convert_uni_to_ch(nls, *uniname, buf, &lossy); + + if (len > 1) { + if ((i >= 8) && ((i+len) > DOS_NAME_LENGTH)) + break; + + if ((i < 8) && ((i+len) > 8)) { + i = 8; + continue; + } + + lower = 0xFF; + + for (j = 0; j < len; j++, i++) + *(dosname+i) = *(buf+j); + } else { /* len == 1 */ + if ((*buf >= 'a') && (*buf <= 'z')) { + *(dosname+i) = *buf - ('a' - 'A'); + + lower |= (i < 8) ? + CASE_LOWER_BASE : + CASE_LOWER_EXT; + } else if ((*buf >= 'A') && (*buf <= 'Z')) { + *(dosname+i) = *buf; + + upper |= (i < 8) ? + CASE_LOWER_BASE : + CASE_LOWER_EXT; + } else { + *(dosname+i) = *buf; + } + i++; + } + } + + uniname++; + } + + if (*dosname == 0xE5) + *dosname = 0x05; + if (*uniname != 0x0) + lossy |= NLS_NAME_OVERLEN; + + if (upper & lower) + p_dosname->name_case = 0xFF; + else + p_dosname->name_case = lower; + + if (p_lossy) + *p_lossy = lossy; + return i; +} + +s32 nls_sfn_to_uni16s(struct super_block *sb, DOS_NAME_T *p_dosname, UNI_NAME_T *p_uniname) +{ + s32 i = 0, j, n = 0; + u8 buf[MAX_DOSNAME_BUF_SIZE]; + u8 *dosname = p_dosname->name; + u16 *uniname = p_uniname->name; + struct nls_table *nls = SDFAT_SB(sb)->nls_disk; + + if (*dosname == 0x05) { + *buf = 0xE5; + i++; + n++; + } + + for ( ; i < 8; i++, n++) { + if (*(dosname+i) == ' ') + break; + + if ((*(dosname+i) >= 'A') && (*(dosname+i) <= 'Z') && + (p_dosname->name_case & CASE_LOWER_BASE)) + *(buf+n) = *(dosname+i) + ('a' - 'A'); + else + *(buf+n) = *(dosname+i); + } + if (*(dosname+8) != ' ') { + *(buf+n) = '.'; + n++; + } + + for (i = 8; i < DOS_NAME_LENGTH; i++, n++) { + if (*(dosname+i) == ' ') + break; + + if ((*(dosname+i) >= 'A') && (*(dosname+i) <= 'Z') && + (p_dosname->name_case & CASE_LOWER_EXT)) + *(buf+n) = *(dosname+i) + ('a' - 'A'); + else + *(buf+n) = *(dosname+i); + } + *(buf+n) = '\0'; + + i = j = 0; + while (j < MAX_NAME_LENGTH) { + if (*(buf+i) == '\0') + break; + + i += convert_ch_to_uni(nls, (buf+i), uniname, NULL); + + uniname++; + j++; + } + + *uniname = (u16) '\0'; + return j; +} + +static s32 __nls_utf16s_to_vfsname(struct super_block *sb, UNI_NAME_T *p_uniname, u8 *p_cstring, s32 buflen) +{ + s32 len; + const u16 *uniname = p_uniname->name; + + /* always len >= 0 */ + len = utf16s_to_utf8s(uniname, MAX_NAME_LENGTH, UTF16_HOST_ENDIAN, + p_cstring, buflen); + p_cstring[len] = '\0'; + return len; +} + +static s32 __nls_vfsname_to_utf16s(struct super_block *sb, const u8 *p_cstring, + const s32 len, UNI_NAME_T *p_uniname, s32 *p_lossy) +{ + s32 i, unilen, lossy = NLS_NAME_NO_LOSSY; + u16 upname[MAX_NAME_LENGTH+1]; + u16 *uniname = p_uniname->name; + + BUG_ON(!len); + + unilen = utf8s_to_utf16s(p_cstring, len, UTF16_HOST_ENDIAN, + (wchar_t *)uniname, MAX_NAME_LENGTH+2); + if (unilen < 0) { + MMSG("%s: failed to vfsname_to_utf16(err:%d) " + "vfsnamelen:%d", __func__, unilen, len); + return unilen; + } + + if (unilen > MAX_NAME_LENGTH) { + MMSG("%s: failed to vfsname_to_utf16(estr:ENAMETOOLONG) " + "vfsnamelen:%d, unilen:%d>%d", + __func__, len, unilen, MAX_NAME_LENGTH); + return -ENAMETOOLONG; + } + + p_uniname->name_len = (u8)(unilen & 0xFF); + + for (i = 0; i < unilen; i++) { + if ((*uniname < 0x0020) || nls_wstrchr(bad_uni_chars, *uniname)) + lossy |= NLS_NAME_LOSSY; + + *(upname+i) = nls_upper(sb, *uniname); + uniname++; + } + + *uniname = (u16)'\0'; + p_uniname->name_len = unilen; + p_uniname->name_hash = calc_chksum_2byte((void *) upname, + unilen << 1, 0, CS_DEFAULT); + + if (p_lossy) + *p_lossy = lossy; + + return unilen; +} + +static s32 __nls_uni16s_to_vfsname(struct super_block *sb, UNI_NAME_T *p_uniname, u8 *p_cstring, s32 buflen) +{ + s32 i, j, len, out_len = 0; + u8 buf[MAX_CHARSET_SIZE]; + const u16 *uniname = p_uniname->name; + struct nls_table *nls = SDFAT_SB(sb)->nls_io; + + i = 0; + while ((i < MAX_NAME_LENGTH) && (out_len < (buflen-1))) { + if (*uniname == (u16)'\0') + break; + + len = convert_uni_to_ch(nls, *uniname, buf, NULL); + + if (out_len + len >= buflen) + len = (buflen - 1) - out_len; + + out_len += len; + + if (len > 1) { + for (j = 0; j < len; j++) + *p_cstring++ = (s8) *(buf+j); + } else { /* len == 1 */ + *p_cstring++ = (s8) *buf; + } + + uniname++; + i++; + } + + *p_cstring = '\0'; + return out_len; +} + +static s32 __nls_vfsname_to_uni16s(struct super_block *sb, const u8 *p_cstring, + const s32 len, UNI_NAME_T *p_uniname, s32 *p_lossy) +{ + s32 i, unilen, lossy = NLS_NAME_NO_LOSSY; + u16 upname[MAX_NAME_LENGTH+1]; + u16 *uniname = p_uniname->name; + struct nls_table *nls = SDFAT_SB(sb)->nls_io; + + BUG_ON(!len); + + i = unilen = 0; + while ((unilen < MAX_NAME_LENGTH) && (i < len)) { + i += convert_ch_to_uni(nls, (u8 *)(p_cstring+i), uniname, &lossy); + + if ((*uniname < 0x0020) || nls_wstrchr(bad_uni_chars, *uniname)) + lossy |= NLS_NAME_LOSSY; + + *(upname+unilen) = nls_upper(sb, *uniname); + + uniname++; + unilen++; + } + + if (*(p_cstring+i) != '\0') + lossy |= NLS_NAME_OVERLEN; + + *uniname = (u16)'\0'; + p_uniname->name_len = unilen; + p_uniname->name_hash = + calc_chksum_2byte((void *) upname, unilen<<1, 0, CS_DEFAULT); + + if (p_lossy) + *p_lossy = lossy; + + return unilen; +} + +s32 nls_uni16s_to_vfsname(struct super_block *sb, UNI_NAME_T *uniname, u8 *p_cstring, s32 buflen) +{ + if (SDFAT_SB(sb)->options.utf8) + return __nls_utf16s_to_vfsname(sb, uniname, p_cstring, buflen); + + return __nls_uni16s_to_vfsname(sb, uniname, p_cstring, buflen); +} + +s32 nls_vfsname_to_uni16s(struct super_block *sb, const u8 *p_cstring, const s32 len, UNI_NAME_T *uniname, s32 *p_lossy) +{ + if (SDFAT_SB(sb)->options.utf8) + return __nls_vfsname_to_utf16s(sb, p_cstring, len, uniname, p_lossy); + return __nls_vfsname_to_uni16s(sb, p_cstring, len, uniname, p_lossy); +} + +/*======================================================================*/ +/* Local Function Definitions */ +/*======================================================================*/ + +static s32 convert_ch_to_uni(struct nls_table *nls, u8 *ch, u16 *uni, s32 *lossy) +{ + int len; + + *uni = 0x0; + + if (ch[0] < 0x80) { + *uni = (u16) ch[0]; + return 1; + } + + len = nls->char2uni(ch, MAX_CHARSET_SIZE, uni); + if (len < 0) { + /* conversion failed */ + DMSG("%s: fail to use nls\n", __func__); + if (lossy != NULL) + *lossy |= NLS_NAME_LOSSY; + *uni = (u16) '_'; + if (!strcmp(nls->charset, "utf8")) + return 1; + return 2; + } + + return len; +} /* end of convert_ch_to_uni */ + +static s32 convert_uni_to_ch(struct nls_table *nls, u16 uni, u8 *ch, s32 *lossy) +{ + int len; + + ch[0] = 0x0; + + if (uni < 0x0080) { + ch[0] = (u8) uni; + return 1; + } + + len = nls->uni2char(uni, ch, MAX_CHARSET_SIZE); + if (len < 0) { + /* conversion failed */ + DMSG("%s: fail to use nls\n", __func__); + if (lossy != NULL) + *lossy |= NLS_NAME_LOSSY; + ch[0] = '_'; + return 1; + } + + return len; + +} /* end of convert_uni_to_ch */ + +/* end of nls.c */ diff --git a/fs/sdfat/sdfat.c b/fs/sdfat/sdfat.c new file mode 100644 index 0000000000000..49bc22ff7d634 --- /dev/null +++ b/fs/sdfat/sdfat.c @@ -0,0 +1,5051 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : core.c */ +/* PURPOSE : sdFAT glue layer for supporting VFS */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/* */ +/************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for mark_page_accessed() */ +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) +#include +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0) +#error SDFAT only supports linux kernel version 3.0 or higher +#endif + +#include "sdfat.h" +#include "version.h" + +/* skip iterating emit_dots when dir is empty */ +#define ITER_POS_FILLED_DOTS (2) + +/* type index declare at sdfat.h */ +const char *FS_TYPE_STR[] = { + "auto", + "exfat", + "vfat" +}; + +static struct kset *sdfat_kset; +static struct kmem_cache *sdfat_inode_cachep; + +static int sdfat_default_codepage = CONFIG_SDFAT_DEFAULT_CODEPAGE; +static char sdfat_default_iocharset[] = CONFIG_SDFAT_DEFAULT_IOCHARSET; +static const char sdfat_iocharset_with_utf8[] = "iso8859-1"; + +#ifdef CONFIG_SDFAT_TRACE_SB_LOCK +static unsigned long __lock_jiffies; +#endif + +static void sdfat_truncate(struct inode *inode, loff_t old_size); +static int sdfat_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create); + +static struct inode *sdfat_iget(struct super_block *sb, loff_t i_pos); +static struct inode *sdfat_build_inode(struct super_block *sb, const FILE_ID_T *fid, loff_t i_pos); +static void sdfat_detach(struct inode *inode); +static void sdfat_attach(struct inode *inode, loff_t i_pos); +static inline unsigned long sdfat_hash(loff_t i_pos); +static int __sdfat_write_inode(struct inode *inode, int sync); +static int sdfat_sync_inode(struct inode *inode); +static int sdfat_write_inode(struct inode *inode, struct writeback_control *wbc); +static void sdfat_write_super(struct super_block *sb); +static void sdfat_write_failed(struct address_space *mapping, loff_t to); + +static void sdfat_init_namebuf(DENTRY_NAMEBUF_T *nb); +static int sdfat_alloc_namebuf(DENTRY_NAMEBUF_T *nb); +static void sdfat_free_namebuf(DENTRY_NAMEBUF_T *nb); + +/************************************************************************* + * INNER FUNCTIONS FOR FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY + *************************************************************************/ +static void __sdfat_writepage_end_io(struct bio *bio, int err); +static inline void __lock_super(struct super_block *sb); +static inline void __unlock_super(struct super_block *sb); +static int __sdfat_create(struct inode *dir, struct dentry *dentry); +static int __sdfat_revalidate(struct dentry *dentry); +static int __sdfat_revalidate_ci(struct dentry *dentry, unsigned int flags); +static int __sdfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync); +static struct dentry *__sdfat_lookup(struct inode *dir, struct dentry *dentry); +static int __sdfat_mkdir(struct inode *dir, struct dentry *dentry); +static int __sdfat_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry); +static int __sdfat_show_options(struct seq_file *m, struct super_block *sb); +static inline ssize_t __sdfat_blkdev_direct_IO(int rw, struct kiocb *iocb, + struct inode *inode, void *iov_u, loff_t offset, + unsigned long nr_segs); +static inline ssize_t __sdfat_direct_IO(int rw, struct kiocb *iocb, + struct inode *inode, void *iov_u, loff_t offset, + loff_t count, unsigned long nr_segs); +static int __sdfat_d_hash(const struct dentry *dentry, struct qstr *qstr); +static int __sdfat_d_hashi(const struct dentry *dentry, struct qstr *qstr); +static int __sdfat_cmp(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name); +static int __sdfat_cmpi(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name); + +/************************************************************************* + * FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY + *************************************************************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0) +static int sdfat_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + unsigned int flags) +{ + /* + * The VFS already checks for existence, so for local filesystems + * the RENAME_NOREPLACE implementation is equivalent to plain rename. + * Don't support any other flags + */ + if (flags & ~RENAME_NOREPLACE) + return -EINVAL; + return __sdfat_rename(old_dir, old_dentry, new_dir, new_dentry); +} +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) */ +static int sdfat_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) +{ + return __sdfat_rename(old_dir, old_dentry, new_dir, new_dentry); +} + +static int setattr_prepare(struct dentry *dentry, struct iattr *attr) +{ + struct inode *inode = dentry->d_inode; + + return inode_change_ok(inode, attr); +} +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) +static inline void __sdfat_submit_bio_write(struct bio *bio) +{ + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); + submit_bio(bio); +} + +static inline unsigned int __sdfat_full_name_hash(const struct dentry *dentry, const char *name, unsigned int len) +{ + return full_name_hash(dentry, name, len); +} + +static inline unsigned long __sdfat_init_name_hash(const struct dentry *dentry) +{ + return init_name_hash(dentry); +} +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) */ +static inline void __sdfat_submit_bio_write(struct bio *bio) +{ + submit_bio(WRITE, bio); +} + +static inline unsigned int __sdfat_full_name_hash(const struct dentry *unused, const char *name, unsigned int len) +{ + return full_name_hash(name, len); +} + +static inline unsigned long __sdfat_init_name_hash(const struct dentry *unused) +{ + return init_name_hash(); +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 21) + /* EMPTY */ +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 21) */ +static inline void inode_lock(struct inode *inode) +{ + mutex_lock(&inode->i_mutex); +} + +static inline void inode_unlock(struct inode *inode) +{ + mutex_unlock(&inode->i_mutex); +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) +static void sdfat_writepage_end_io(struct bio *bio) +{ + __sdfat_writepage_end_io(bio, bio->bi_error); +} +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) */ +static void sdfat_writepage_end_io(struct bio *bio, int err) +{ + if (test_bit(BIO_UPTODATE, &bio->bi_flags)) + err = 0; + __sdfat_writepage_end_io(bio, err); +} +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) +static inline int sdfat_remount_syncfs(struct super_block *sb) +{ + sync_filesystem(sb); + return 0; +} +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) */ +static inline int sdfat_remount_syncfs(struct super_block *sb) +{ + /* + * We don`t need to call sync_filesystem(sb), + * Because VFS calls it. + */ + return 0; +} +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) +static inline sector_t __sdfat_bio_sector(struct bio *bio) +{ + return bio->bi_iter.bi_sector; +} + +static inline void __sdfat_set_bio_iterate(struct bio *bio, sector_t sector, + unsigned int size, unsigned int idx, unsigned int done) +{ + struct bvec_iter *iter = &(bio->bi_iter); + + iter->bi_sector = sector; + iter->bi_size = size; + iter->bi_idx = idx; + iter->bi_bvec_done = done; +} + +static void __sdfat_truncate_pagecache(struct inode *inode, + loff_t to, loff_t newsize) +{ + truncate_pagecache(inode, newsize); +} + +static int sdfat_d_hash(const struct dentry *dentry, struct qstr *qstr) +{ + return __sdfat_d_hash(dentry, qstr); +} + +static int sdfat_d_hashi(const struct dentry *dentry, struct qstr *qstr) +{ + return __sdfat_d_hashi(dentry, qstr); +} + +//instead of sdfat_readdir +static int sdfat_iterate(struct file *filp, struct dir_context *ctx) +{ + struct inode *inode = filp->f_path.dentry->d_inode; + struct super_block *sb = inode->i_sb; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + FS_INFO_T *fsi = &(sbi->fsi); + DIR_ENTRY_T de; + DENTRY_NAMEBUF_T *nb = &(de.NameBuf); + unsigned long inum; + loff_t cpos; + int err = 0, fake_offset = 0; + + sdfat_init_namebuf(nb); + __lock_super(sb); + + cpos = ctx->pos; + if ((fsi->vol_type == EXFAT) || (inode->i_ino == SDFAT_ROOT_INO)) { + if (!dir_emit_dots(filp, ctx)) + goto out; + if (ctx->pos == ITER_POS_FILLED_DOTS) { + cpos = 0; + fake_offset = 1; + } + } + if (cpos & (DENTRY_SIZE - 1)) { + err = -ENOENT; + goto out; + } + + /* name buffer should be allocated before use */ + err = sdfat_alloc_namebuf(nb); + if (err) + goto out; +get_new: + SDFAT_I(inode)->fid.size = i_size_read(inode); + SDFAT_I(inode)->fid.rwoffset = cpos >> DENTRY_SIZE_BITS; + + if (cpos >= SDFAT_I(inode)->fid.size) + goto end_of_dir; + + err = fsapi_readdir(inode, &de); + if (err) { + // at least we tried to read a sector + // move cpos to next sector position (should be aligned) + if (err == -EIO) { + cpos += 1 << (sb->s_blocksize_bits); + cpos &= ~((u32)sb->s_blocksize-1); + } + + err = -EIO; + goto end_of_dir; + } + + cpos = SDFAT_I(inode)->fid.rwoffset << DENTRY_SIZE_BITS; + + if (!nb->lfn[0]) + goto end_of_dir; + + if (!memcmp(nb->sfn, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH)) { + inum = inode->i_ino; + } else if (!memcmp(nb->sfn, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH)) { + inum = parent_ino(filp->f_path.dentry); + } else { + loff_t i_pos = ((loff_t) SDFAT_I(inode)->fid.start_clu << 32) | + ((SDFAT_I(inode)->fid.rwoffset-1) & 0xffffffff); + struct inode *tmp = sdfat_iget(sb, i_pos); + + if (tmp) { + inum = tmp->i_ino; + iput(tmp); + } else { + inum = iunique(sb, SDFAT_ROOT_INO); + } + } + + /* Before calling dir_emit(), sb_lock should be released. + * Because page fault can occur in dir_emit() when the size of buffer given + * from user is larger than one page size + */ + __unlock_super(sb); + if (!dir_emit(ctx, nb->lfn, strlen(nb->lfn), inum, + (de.Attr & ATTR_SUBDIR) ? DT_DIR : DT_REG)) + goto out_unlocked; + __lock_super(sb); + + ctx->pos = cpos; + goto get_new; + +end_of_dir: + if (!cpos && fake_offset) + cpos = ITER_POS_FILLED_DOTS; + ctx->pos = cpos; +out: + __unlock_super(sb); +out_unlocked: + /* + * To improve performance, free namebuf after unlock sb_lock. + * If namebuf is not allocated, this function do nothing + */ + sdfat_free_namebuf(nb); + return err; +} +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */ +static inline sector_t __sdfat_bio_sector(struct bio *bio) +{ + return bio->bi_sector; +} + +static inline void __sdfat_set_bio_iterate(struct bio *bio, sector_t sector, + unsigned int size, unsigned int idx, unsigned int done) +{ + bio->bi_sector = sector; + bio->bi_idx = idx; + bio->bi_size = size; //PAGE_SIZE; +} + +static void __sdfat_truncate_pagecache(struct inode *inode, + loff_t to, loff_t newsize) +{ + truncate_pagecache(inode, to, newsize); +} + +static int sdfat_d_hash(const struct dentry *dentry, + const struct inode *inode, struct qstr *qstr) +{ + return __sdfat_d_hash(dentry, qstr); +} + +static int sdfat_d_hashi(const struct dentry *dentry, + const struct inode *inode, struct qstr *qstr) +{ + return __sdfat_d_hashi(dentry, qstr); +} + +static int sdfat_readdir(struct file *filp, void *dirent, filldir_t filldir) +{ + struct inode *inode = filp->f_path.dentry->d_inode; + struct super_block *sb = inode->i_sb; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + FS_INFO_T *fsi = &(sbi->fsi); + DIR_ENTRY_T de; + DENTRY_NAMEBUF_T *nb = &(de.NameBuf); + unsigned long inum; + loff_t cpos; + int err = 0, fake_offset = 0; + + sdfat_init_namebuf(nb); + __lock_super(sb); + + cpos = filp->f_pos; + /* Fake . and .. for the root directory. */ + if ((fsi->vol_type == EXFAT) || (inode->i_ino == SDFAT_ROOT_INO)) { + while (cpos < ITER_POS_FILLED_DOTS) { + if (inode->i_ino == SDFAT_ROOT_INO) + inum = SDFAT_ROOT_INO; + else if (cpos == 0) + inum = inode->i_ino; + else /* (cpos == 1) */ + inum = parent_ino(filp->f_path.dentry); + + if (filldir(dirent, "..", cpos+1, cpos, inum, DT_DIR) < 0) + goto out; + cpos++; + filp->f_pos++; + } + if (cpos == ITER_POS_FILLED_DOTS) { + cpos = 0; + fake_offset = 1; + } + } + if (cpos & (DENTRY_SIZE - 1)) { + err = -ENOENT; + goto out; + } + + /* name buffer should be allocated before use */ + err = sdfat_alloc_namebuf(nb); + if (err) + goto out; +get_new: + SDFAT_I(inode)->fid.size = i_size_read(inode); + SDFAT_I(inode)->fid.rwoffset = cpos >> DENTRY_SIZE_BITS; + + if (cpos >= SDFAT_I(inode)->fid.size) + goto end_of_dir; + + err = fsapi_readdir(inode, &de); + if (err) { + // at least we tried to read a sector + // move cpos to next sector position (should be aligned) + if (err == -EIO) { + cpos += 1 << (sb->s_blocksize_bits); + cpos &= ~((u32)sb->s_blocksize-1); + } + + err = -EIO; + goto end_of_dir; + } + + cpos = SDFAT_I(inode)->fid.rwoffset << DENTRY_SIZE_BITS; + + if (!nb->lfn[0]) + goto end_of_dir; + + if (!memcmp(nb->sfn, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH)) { + inum = inode->i_ino; + } else if (!memcmp(nb->sfn, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH)) { + inum = parent_ino(filp->f_path.dentry); + } else { + loff_t i_pos = ((loff_t) SDFAT_I(inode)->fid.start_clu << 32) | + ((SDFAT_I(inode)->fid.rwoffset-1) & 0xffffffff); + struct inode *tmp = sdfat_iget(sb, i_pos); + + if (tmp) { + inum = tmp->i_ino; + iput(tmp); + } else { + inum = iunique(sb, SDFAT_ROOT_INO); + } + } + + /* Before calling dir_emit(), sb_lock should be released. + * Because page fault can occur in dir_emit() when the size of buffer given + * from user is larger than one page size + */ + __unlock_super(sb); + if (filldir(dirent, nb->lfn, strlen(nb->lfn), cpos, inum, + (de.Attr & ATTR_SUBDIR) ? DT_DIR : DT_REG) < 0) + goto out_unlocked; + __lock_super(sb); + + filp->f_pos = cpos; + goto get_new; + +end_of_dir: + if (!cpos && fake_offset) + cpos = ITER_POS_FILLED_DOTS; + filp->f_pos = cpos; +out: + __unlock_super(sb); +out_unlocked: + /* + * To improve performance, free namebuf after unlock sb_lock. + * If namebuf is not allocated, this function do nothing + */ + sdfat_free_namebuf(nb); + return err; +} +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) + /* EMPTY */ +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0) */ +static inline struct inode *file_inode(const struct file *f) +{ + return f->f_dentry->d_inode; +} +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) +static inline int __is_sb_dirty(struct super_block *sb) +{ + return SDFAT_SB(sb)->s_dirt; +} + +static inline void __set_sb_clean(struct super_block *sb) +{ + SDFAT_SB(sb)->s_dirt = 0; +} + +/* Workqueue wrapper for sdfat_write_super () */ +static void __write_super_delayed(struct work_struct *work) +{ + struct sdfat_sb_info *sbi; + struct super_block *sb; + + sbi = container_of(work, struct sdfat_sb_info, write_super_work.work); + sb = sbi->host_sb; + + /* XXX: Is this needed? */ + if (!sb || !down_read_trylock(&sb->s_umount)) { + DMSG("%s: skip delayed work(write_super).\n", __func__); + return; + } + + DMSG("%s: do delayed_work(write_super).\n", __func__); + + spin_lock(&sbi->work_lock); + sbi->write_super_queued = 0; + spin_unlock(&sbi->work_lock); + + sdfat_write_super(sb); + + up_read(&sb->s_umount); +} + +static void setup_sdfat_sync_super_wq(struct super_block *sb) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + + mutex_init(&sbi->s_lock); + spin_lock_init(&sbi->work_lock); + INIT_DELAYED_WORK(&sbi->write_super_work, __write_super_delayed); + sbi->host_sb = sb; +} + +static inline bool __cancel_delayed_work_sync(struct sdfat_sb_info *sbi) +{ + return cancel_delayed_work_sync(&sbi->write_super_work); +} + +static inline void lock_super(struct super_block *sb) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + + mutex_lock(&sbi->s_lock); +} + +static inline void unlock_super(struct super_block *sb) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + + mutex_unlock(&sbi->s_lock); +} + +static int sdfat_revalidate(struct dentry *dentry, unsigned int flags) +{ + if (flags & LOOKUP_RCU) + return -ECHILD; + + return __sdfat_revalidate(dentry); +} + +static int sdfat_revalidate_ci(struct dentry *dentry, unsigned int flags) +{ + if (flags & LOOKUP_RCU) + return -ECHILD; + + return __sdfat_revalidate_ci(dentry, flags); +} + +static struct inode *sdfat_iget(struct super_block *sb, loff_t i_pos) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + struct sdfat_inode_info *info; + struct hlist_head *head = sbi->inode_hashtable + sdfat_hash(i_pos); + struct inode *inode = NULL; + + spin_lock(&sbi->inode_hash_lock); + hlist_for_each_entry(info, head, i_hash_fat) { + BUG_ON(info->vfs_inode.i_sb != sb); + + if (i_pos != info->i_pos) + continue; + inode = igrab(&info->vfs_inode); + if (inode) + break; + } + spin_unlock(&sbi->inode_hash_lock); + return inode; +} +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) */ +static inline int __is_sb_dirty(struct super_block *sb) +{ + return sb->s_dirt; +} + +static inline void __set_sb_clean(struct super_block *sb) +{ + sb->s_dirt = 0; +} + +static void setup_sdfat_sync_super_wq(struct super_block *sb) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + + sbi->host_sb = sb; +} + +static inline bool __cancel_delayed_work_sync(struct sdfat_sb_info *sbi) +{ + /* DO NOTHING */ + return 0; +} + +static inline void clear_inode(struct inode *inode) +{ + end_writeback(inode); +} + +static int sdfat_revalidate(struct dentry *dentry, struct nameidata *nd) +{ + if (nd && nd->flags & LOOKUP_RCU) + return -ECHILD; + + return __sdfat_revalidate(dentry); +} + +static int sdfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd) +{ + if (nd && nd->flags & LOOKUP_RCU) + return -ECHILD; + + return __sdfat_revalidate_ci(dentry, nd ? nd->flags : 0); + +} + +static struct inode *sdfat_iget(struct super_block *sb, loff_t i_pos) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + struct sdfat_inode_info *info; + struct hlist_node *node; + struct hlist_head *head = sbi->inode_hashtable + sdfat_hash(i_pos); + struct inode *inode = NULL; + + spin_lock(&sbi->inode_hash_lock); + hlist_for_each_entry(info, node, head, i_hash_fat) { + BUG_ON(info->vfs_inode.i_sb != sb); + + if (i_pos != info->i_pos) + continue; + inode = igrab(&info->vfs_inode); + if (inode) + break; + } + spin_unlock(&sbi->inode_hash_lock); + return inode; +} +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) +static struct dentry *sdfat_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags) +{ + return __sdfat_lookup(dir, dentry); +} +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) */ +static struct dentry *sdfat_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) +{ + return __sdfat_lookup(dir, dentry); +} +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + /* NOTHING NOW */ +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) */ +#define GLOBAL_ROOT_UID (0) +#define GLOBAL_ROOT_GID (0) + +static inline bool uid_eq(uid_t left, uid_t right) +{ + return left == right; +} + +static inline bool gid_eq(gid_t left, gid_t right) +{ + return left == right; +} + +static inline uid_t from_kuid_munged(struct user_namespace *to, uid_t kuid) +{ + return kuid; +} + +static inline gid_t from_kgid_munged(struct user_namespace *to, gid_t kgid) +{ + return kgid; +} + +static inline uid_t make_kuid(struct user_namespace *from, uid_t uid) +{ + return uid; +} + +static inline gid_t make_kgid(struct user_namespace *from, gid_t gid) +{ + return gid; +} +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +static struct dentry *__d_make_root(struct inode *root_inode) +{ + return d_make_root(root_inode); +} + +static void __sdfat_do_truncate(struct inode *inode, loff_t old, loff_t new) +{ + down_write(&SDFAT_I(inode)->truncate_lock); + truncate_setsize(inode, new); + sdfat_truncate(inode, old); + up_write(&SDFAT_I(inode)->truncate_lock); +} + +static sector_t sdfat_aop_bmap(struct address_space *mapping, sector_t block) +{ + sector_t blocknr; + + /* sdfat_get_cluster() assumes the requested blocknr isn't truncated. */ + down_read(&SDFAT_I(mapping->host)->truncate_lock); + blocknr = generic_block_bmap(mapping, block, sdfat_get_block); + up_read(&SDFAT_I(mapping->host)->truncate_lock); + return blocknr; +} + +static int sdfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + return __sdfat_mkdir(dir, dentry); +} + +static int sdfat_show_options(struct seq_file *m, struct dentry *root) +{ + return __sdfat_show_options(m, root->d_sb); +} +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */ +static inline void set_nlink(struct inode *inode, unsigned int nlink) +{ + inode->i_nlink = nlink; +} + +static struct dentry *__d_make_root(struct inode *root_inode) +{ + return d_alloc_root(root_inode); +} + +static void __sdfat_do_truncate(struct inode *inode, loff_t old, loff_t new) +{ + truncate_setsize(inode, new); + sdfat_truncate(inode, old); +} + +static sector_t sdfat_aop_bmap(struct address_space *mapping, sector_t block) +{ + sector_t blocknr; + + /* sdfat_get_cluster() assumes the requested blocknr isn't truncated. */ + down_read(&mapping->host->i_alloc_sem); + blocknr = generic_block_bmap(mapping, block, sdfat_get_block); + up_read(&mapping->host->i_alloc_sem); + return blocknr; +} + +static int sdfat_mkdir(struct inode *dir, struct dentry *dentry, int mode) +{ + return __sdfat_mkdir(dir, dentry); +} + +static int sdfat_show_options(struct seq_file *m, struct vfsmount *mnt) +{ + return __sdfat_show_options(m, mnt->mnt_sb); +} +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) +#define __sdfat_generic_file_fsync(filp, start, end, datasync) \ + generic_file_fsync(filp, start, end, datasync) + +static int sdfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync) +{ + return __sdfat_file_fsync(filp, start, end, datasync); +} +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) */ +#define __sdfat_generic_file_fsync(filp, start, end, datasync) \ + generic_file_fsync(filp, datasync) +static int sdfat_file_fsync(struct file *filp, int datasync) +{ + return __sdfat_file_fsync(filp, 0, 0, datasync); +} +#endif + +/************************************************************************* + * MORE FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY + *************************************************************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) +static int sdfat_cmp(const struct dentry *dentry, + unsigned int len, const char *str, const struct qstr *name) +{ + return __sdfat_cmp(dentry, len, str, name); +} + +static int sdfat_cmpi(const struct dentry *dentry, + unsigned int len, const char *str, const struct qstr *name) +{ + return __sdfat_cmpi(dentry, len, str, name); +} +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) +static int sdfat_cmp(const struct dentry *parent, const struct dentry *dentry, + unsigned int len, const char *str, const struct qstr *name) +{ + return __sdfat_cmp(dentry, len, str, name); +} + +static int sdfat_cmpi(const struct dentry *parent, const struct dentry *dentry, + unsigned int len, const char *str, const struct qstr *name) +{ + return __sdfat_cmpi(dentry, len, str, name); +} +#else +static int sdfat_cmp(const struct dentry *parent, const struct inode *pinode, + const struct dentry *dentry, const struct inode *inode, + unsigned int len, const char *str, const struct qstr *name) +{ + return __sdfat_cmp(dentry, len, str, name); +} + +static int sdfat_cmpi(const struct dentry *parent, const struct inode *pinode, + const struct dentry *dentry, const struct inode *inode, + unsigned int len, const char *str, const struct qstr *name) +{ + return __sdfat_cmpi(dentry, len, str, name); +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) +static const char *sdfat_follow_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done) +{ + struct sdfat_inode_info *ei = SDFAT_I(inode); + + return (char *)(ei->target); +} +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) +static const char *sdfat_follow_link(struct dentry *dentry, void **cookie) +{ + struct sdfat_inode_info *ei = SDFAT_I(dentry->d_inode); + + return *cookie = (char *)(ei->target); +} +#else +static void *sdfat_follow_link(struct dentry *dentry, struct nameidata *nd) +{ + struct sdfat_inode_info *ei = SDFAT_I(dentry->d_inode); + + nd_set_link(nd, (char *)(ei->target)); + return NULL; +} +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) +static ssize_t sdfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter) +{ + struct file *file = iocb->ki_filp; + struct address_space *mapping = file->f_mapping; + struct inode *inode = mapping->host; + size_t count = iov_iter_count(iter); + int rw = iov_iter_rw(iter); + loff_t offset = iocb->ki_pos; + + return __sdfat_direct_IO(rw, iocb, inode, + (void *)iter, offset, count, 0 /* UNUSED */); +} +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) +static ssize_t sdfat_direct_IO(struct kiocb *iocb, + struct iov_iter *iter, + loff_t offset) +{ + struct file *file = iocb->ki_filp; + struct address_space *mapping = file->f_mapping; + struct inode *inode = mapping->host; + size_t count = iov_iter_count(iter); + int rw = iov_iter_rw(iter); + + return __sdfat_direct_IO(rw, iocb, inode, + (void *)iter, offset, count, 0 /* UNUSED */); +} +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) +static ssize_t sdfat_direct_IO(int rw, struct kiocb *iocb, + struct iov_iter *iter, + loff_t offset) +{ + struct file *file = iocb->ki_filp; + struct address_space *mapping = file->f_mapping; + struct inode *inode = mapping->host; + size_t count = iov_iter_count(iter); + + return __sdfat_direct_IO(rw, iocb, inode, + (void *)iter, offset, count, 0 /* UNUSED */); +} +#else +static ssize_t sdfat_direct_IO(int rw, struct kiocb *iocb, + const struct iovec *iov, loff_t offset, unsigned long nr_segs) +{ + struct file *file = iocb->ki_filp; + struct address_space *mapping = file->f_mapping; + struct inode *inode = mapping->host; + size_t count = iov_length(iov, nr_segs); + + return __sdfat_direct_IO(rw, iocb, inode, + (void *)iov, offset, count, nr_segs); +} +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) +static inline ssize_t __sdfat_blkdev_direct_IO(int unused, struct kiocb *iocb, + struct inode *inode, void *iov_u, loff_t unused_1, + unsigned long nr_segs) +{ + struct iov_iter *iter = (struct iov_iter *)iov_u; + + return blockdev_direct_IO(iocb, inode, iter, sdfat_get_block); +} +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) +static inline ssize_t __sdfat_blkdev_direct_IO(int unused, struct kiocb *iocb, + struct inode *inode, void *iov_u, loff_t offset, + unsigned long nr_segs) +{ + struct iov_iter *iter = (struct iov_iter *)iov_u; + + return blockdev_direct_IO(iocb, inode, iter, offset, sdfat_get_block); +} +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) +static inline ssize_t __sdfat_blkdev_direct_IO(int rw, struct kiocb *iocb, + struct inode *inode, void *iov_u, loff_t offset, + unsigned long nr_segs) +{ + struct iov_iter *iter = (struct iov_iter *)iov_u; + + return blockdev_direct_IO(rw, iocb, inode, iter, + offset, sdfat_get_block); +} +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +static inline ssize_t __sdfat_blkdev_direct_IO(int rw, struct kiocb *iocb, + struct inode *inode, void *iov_u, loff_t offset, + unsigned long nr_segs) +{ + const struct iovec *iov = (const struct iovec *)iov_u; + + return blockdev_direct_IO(rw, iocb, inode, iov, + offset, nr_segs, sdfat_get_block); +} +#else +static inline ssize_t __sdfat_blkdev_direct_IO(int rw, struct kiocb *iocb, + struct inode *inode, void *iov_u, loff_t offset, + unsigned long nr_segs) +{ + const struct iovec *iov = (const struct iovec *)iov_u; + + return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, + offset, nr_segs, sdfat_get_block, NULL); +} +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) +static int sdfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, + bool excl) +{ + return __sdfat_create(dir, dentry); +} +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +static int sdfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, + struct nameidata *nd) +{ + return __sdfat_create(dir, dentry); +} +#else +static int sdfat_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd) +{ + return __sdfat_create(dir, dentry); +} +#endif + + +/************************************************************************* + * WRAP FUNCTIONS FOR DEBUGGING + *************************************************************************/ +#ifdef CONFIG_SDFAT_TRACE_SB_LOCK +static inline void __lock_super(struct super_block *sb) +{ + lock_super(sb); + __lock_jiffies = jiffies; +} + +static inline void __unlock_super(struct super_block *sb) +{ + int time = ((jiffies - __lock_jiffies) * 1000 / HZ); + /* FIXME : error message should be modified */ + if (time > 10) + EMSG("lock_super in %s (%d ms)\n", __func__, time); + + unlock_super(sb); +} +#else /* CONFIG_SDFAT_TRACE_SB_LOCK */ +static inline void __lock_super(struct super_block *sb) +{ + lock_super(sb); +} + +static inline void __unlock_super(struct super_block *sb) +{ + unlock_super(sb); +} +#endif /* CONFIG_SDFAT_TRACE_SB_LOCK */ + +/************************************************************************* + * NORMAL FUNCTIONS + *************************************************************************/ +static inline loff_t sdfat_make_i_pos(FILE_ID_T *fid) +{ + return ((loff_t) fid->dir.dir << 32) | (fid->entry & 0xffffffff); +} + +/*======================================================================*/ +/* Directory Entry Name Buffer Operations */ +/*======================================================================*/ +static void sdfat_init_namebuf(DENTRY_NAMEBUF_T *nb) +{ + nb->lfn = NULL; + nb->sfn = NULL; + nb->lfnbuf_len = 0; + nb->sfnbuf_len = 0; +} + +static int sdfat_alloc_namebuf(DENTRY_NAMEBUF_T *nb) +{ + nb->lfn = __getname(); + if (!nb->lfn) + return -ENOMEM; + nb->sfn = nb->lfn + MAX_VFSNAME_BUF_SIZE; + nb->lfnbuf_len = MAX_VFSNAME_BUF_SIZE; + nb->sfnbuf_len = MAX_VFSNAME_BUF_SIZE; + return 0; +} + +static void sdfat_free_namebuf(DENTRY_NAMEBUF_T *nb) +{ + if (!nb->lfn) + return; + + __putname(nb->lfn); + sdfat_init_namebuf(nb); +} + +/*======================================================================*/ +/* Directory Entry Operations */ +/*======================================================================*/ +#define SDFAT_DSTATE_LOCKED (void *)(0xCAFE2016) +#define SDFAT_DSTATE_UNLOCKED (void *)(0x00000000) + +static inline void __lock_d_revalidate(struct dentry *dentry) +{ + spin_lock(&dentry->d_lock); + dentry->d_fsdata = SDFAT_DSTATE_LOCKED; + spin_unlock(&dentry->d_lock); +} + +static inline void __unlock_d_revalidate(struct dentry *dentry) +{ + spin_lock(&dentry->d_lock); + dentry->d_fsdata = SDFAT_DSTATE_UNLOCKED; + spin_unlock(&dentry->d_lock); +} + +/* __check_dstate_locked requires dentry->d_lock */ +static inline int __check_dstate_locked(struct dentry *dentry) +{ + if (dentry->d_fsdata == SDFAT_DSTATE_LOCKED) + return 1; + + return 0; +} + +/* + * If new entry was created in the parent, it could create the 8.3 + * alias (the shortname of logname). So, the parent may have the + * negative-dentry which matches the created 8.3 alias. + * + * If it happened, the negative dentry isn't actually negative + * anymore. So, drop it. + */ +static int __sdfat_revalidate_common(struct dentry *dentry) +{ + int ret = 1; + + spin_lock(&dentry->d_lock); + if ((!dentry->d_inode) && (!__check_dstate_locked(dentry) && + (dentry->d_time != dentry->d_parent->d_inode->i_version))) { + ret = 0; + } + spin_unlock(&dentry->d_lock); + return ret; +} + +static int __sdfat_revalidate(struct dentry *dentry) +{ + /* This is not negative dentry. Always valid. */ + if (dentry->d_inode) + return 1; + return __sdfat_revalidate_common(dentry); +} + +static int __sdfat_revalidate_ci(struct dentry *dentry, unsigned int flags) +{ + /* + * This is not negative dentry. Always valid. + * + * Note, rename() to existing directory entry will have ->d_inode, + * and will use existing name which isn't specified name by user. + * + * We may be able to drop this positive dentry here. But dropping + * positive dentry isn't good idea. So it's unsupported like + * rename("filename", "FILENAME") for now. + */ + if (dentry->d_inode) + return 1; +#if 0 /* Blocked below code for lookup_one_len() called by stackable FS */ + /* + * This may be nfsd (or something), anyway, we can't see the + * intent of this. So, since this can be for creation, drop it. + */ + if (!flags) + return 0; +#endif + /* + * Drop the negative dentry, in order to make sure to use the + * case sensitive name which is specified by user if this is + * for creation. + */ + if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) + return 0; + return __sdfat_revalidate_common(dentry); +} + + +/* returns the length of a struct qstr, ignoring trailing dots */ +static unsigned int __sdfat_striptail_len(unsigned int len, const char *name) +{ + while (len && name[len - 1] == '.') + len--; + return len; +} + +static unsigned int sdfat_striptail_len(const struct qstr *qstr) +{ + return __sdfat_striptail_len(qstr->len, qstr->name); +} + +/* + * Compute the hash for the sdfat name corresponding to the dentry. + * Note: if the name is invalid, we leave the hash code unchanged so + * that the existing dentry can be used. The sdfat fs routines will + * return ENOENT or EINVAL as appropriate. + */ +static int __sdfat_d_hash(const struct dentry *dentry, struct qstr *qstr) +{ + unsigned int len = sdfat_striptail_len(qstr); + + qstr->hash = __sdfat_full_name_hash(dentry, qstr->name, len); + return 0; +} + +/* + * Compute the hash for the sdfat name corresponding to the dentry. + * Note: if the name is invalid, we leave the hash code unchanged so + * that the existing dentry can be used. The sdfat fs routines will + * return ENOENT or EINVAL as appropriate. + */ +static int __sdfat_d_hashi(const struct dentry *dentry, struct qstr *qstr) +{ + struct nls_table *t = SDFAT_SB(dentry->d_sb)->nls_io; + const unsigned char *name; + unsigned int len; + unsigned long hash; + + name = qstr->name; + len = sdfat_striptail_len(qstr); + + hash = __sdfat_init_name_hash(dentry); + while (len--) + hash = partial_name_hash(nls_tolower(t, *name++), hash); + qstr->hash = end_name_hash(hash); + + return 0; +} + +/* + * Case sensitive compare of two sdfat names. + */ +static int __sdfat_cmp(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name) +{ + unsigned int alen, blen; + + /* A filename cannot end in '.' or we treat it like it has none */ + alen = sdfat_striptail_len(name); + blen = __sdfat_striptail_len(len, str); + if (alen == blen) { + if (strncmp(name->name, str, alen) == 0) + return 0; + } + return 1; +} + +/* + * Case insensitive compare of two sdfat names. + */ +static int __sdfat_cmpi(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name) +{ + struct nls_table *t = SDFAT_SB(dentry->d_sb)->nls_io; + unsigned int alen, blen; + + /* A filename cannot end in '.' or we treat it like it has none */ + alen = sdfat_striptail_len(name); + blen = __sdfat_striptail_len(len, str); + if (alen == blen) { + if (nls_strnicmp(t, name->name, str, alen) == 0) + return 0; + } + return 1; +} + +static const struct dentry_operations sdfat_dentry_ops = { + .d_revalidate = sdfat_revalidate, + .d_hash = sdfat_d_hash, + .d_compare = sdfat_cmp, +}; + +static const struct dentry_operations sdfat_ci_dentry_ops = { + .d_revalidate = sdfat_revalidate_ci, + .d_hash = sdfat_d_hashi, + .d_compare = sdfat_cmpi, +}; + +#ifdef CONFIG_SDFAT_DFR +/*----------------------------------------------------------------------*/ +/* Defragmentation related */ +/*----------------------------------------------------------------------*/ +/** + * @fn defrag_cleanup_reqs + * @brief clean-up defrag info depending on error flag + * @return void + * @param sb super block + * @param error error flag + */ +static void defrag_cleanup_reqs(INOUT struct super_block *sb, IN int error) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + struct defrag_info *sb_dfr = &(sbi->dfr_info); + struct defrag_info *ino_dfr = NULL, *tmp = NULL; + /* sdfat patch 0.96 : sbi->dfr_info crash problem */ + __lock_super(sb); + + /* Clean-up ino_dfr */ + if (!error) { + list_for_each_entry_safe(ino_dfr, tmp, &sb_dfr->entry, entry) { + struct inode *inode = &(container_of(ino_dfr, struct sdfat_inode_info, dfr_info)->vfs_inode); + + mutex_lock(&ino_dfr->lock); + + atomic_set(&ino_dfr->stat, DFR_INO_STAT_IDLE); + + list_del(&ino_dfr->entry); + + ino_dfr->chunks = NULL; + ino_dfr->nr_chunks = 0; + INIT_LIST_HEAD(&ino_dfr->entry); + + BUG_ON(!mutex_is_locked(&ino_dfr->lock)); + mutex_unlock(&ino_dfr->lock); + + iput(inode); + } + } + + /* Clean-up sb_dfr */ + sb_dfr->chunks = NULL; + sb_dfr->nr_chunks = 0; + INIT_LIST_HEAD(&sb_dfr->entry); + + /* Clear dfr_new_clus page */ + memset(sbi->dfr_new_clus, 0, PAGE_SIZE); + sbi->dfr_new_idx = 1; + memset(sbi->dfr_page_wb, 0, PAGE_SIZE); + + sbi->dfr_hint_clus = sbi->dfr_hint_idx = sbi->dfr_reserved_clus = 0; + + __unlock_super(sb); +} + +/** + * @fn defrag_validate_pages + * @brief validate and mark dirty for victiim pages + * @return 0 on success, -errno otherwise + * @param inode inode + * @param chunk given chunk + * @remark protected by inode_lock and super_lock + */ +static int +defrag_validate_pages( + IN struct inode *inode, + IN struct defrag_chunk_info *chunk) +{ + struct super_block *sb = inode->i_sb; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + struct page *page = NULL; + unsigned int i_size = 0, page_off = 0, page_nr = 0; + int buf_i = 0, i = 0, err = 0; + + i_size = i_size_read(inode); + page_off = chunk->f_clus * PAGES_PER_CLUS(sb); + page_nr = (i_size / PAGE_SIZE) + ((i_size % PAGE_SIZE) ? 1 : 0); + if ((i_size <= 0) || (page_nr <= 0)) { + dfr_err("inode %p, i_size %d, page_nr %d", inode, i_size, page_nr); + return -EINVAL; + } + + /* Get victim pages + * and check its dirty/writeback/mapped state + */ + for (i = 0; + i < min((int)(page_nr - page_off), (int)(chunk->nr_clus * PAGES_PER_CLUS(sb))); + i++) { + page = find_get_page(inode->i_mapping, page_off + i); + if (page) + if (!trylock_page(page)) { + put_page(page); + page = NULL; + } + + if (!page) { + dfr_debug("get/lock_page() failed, index %d", i); + err = -EINVAL; + goto error; + } + + sbi->dfr_pagep[buf_i++] = page; + if (PageError(page) || !PageUptodate(page) || PageDirty(page) || + PageWriteback(page) || page_mapped(page)) { + dfr_debug("page %p, err %d, uptodate %d, " + "dirty %d, wb %d, mapped %d", + page, PageError(page), PageUptodate(page), + PageDirty(page), PageWriteback(page), + page_mapped(page)); + err = -EINVAL; + goto error; + } + + set_bit((page->index & (PAGES_PER_CLUS(sb) - 1)), + (volatile unsigned long *)&(sbi->dfr_page_wb[chunk->new_idx + i / PAGES_PER_CLUS(sb)])); + + page = NULL; + } + + /** + * All pages in the chunks are valid. + */ + i_size -= (chunk->f_clus * (sbi->fsi.cluster_size)); + BUG_ON(((i_size / PAGE_SIZE) + ((i_size % PAGE_SIZE) ? 1 : 0)) != (page_nr - page_off)); + + for (i = 0; i < buf_i; i++) { + struct buffer_head *bh = NULL, *head = NULL; + int bh_idx = 0; + + page = sbi->dfr_pagep[i]; + BUG_ON(!page); + + /* Mark dirty in page */ + set_page_dirty(page); + mark_page_accessed(page); + + /* Attach empty BHs */ + if (!page_has_buffers(page)) + create_empty_buffers(page, 1 << inode->i_blkbits, 0); + + /* Mark dirty in BHs */ + bh = head = page_buffers(page); + BUG_ON(!bh && !i_size); + do { + if ((bh_idx >= 1) && (bh_idx >= (i_size >> inode->i_blkbits))) { + clear_buffer_dirty(bh); + } else { + if (PageUptodate(page)) + if (!buffer_uptodate(bh)) + set_buffer_uptodate(bh); + + /* Set this bh as delay */ + set_buffer_new(bh); + set_buffer_delay(bh); + + mark_buffer_dirty(bh); + } + + bh_idx++; + bh = bh->b_this_page; + } while (bh != head); + + /* Mark this page accessed */ + mark_page_accessed(page); + + i_size -= PAGE_SIZE; + } + +error: + /* Unlock and put refs for pages */ + for (i = 0; i < buf_i; i++) { + BUG_ON(!sbi->dfr_pagep[i]); + unlock_page(sbi->dfr_pagep[i]); + put_page(sbi->dfr_pagep[i]); + } + memset(sbi->dfr_pagep, 0, sizeof(PAGE_SIZE)); + + return err; +} + + +/** + * @fn defrag_validate_reqs + * @brief validate defrag requests + * @return negative if all requests not valid, 0 otherwise + * @param sb super block + * @param chunks given chunks + */ +static int +defrag_validate_reqs( + IN struct super_block *sb, + INOUT struct defrag_chunk_info *chunks) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + struct defrag_info *sb_dfr = &(sbi->dfr_info); + int i = 0, err = 0, err_cnt = 0; + + /* Validate all reqs */ + for (i = REQ_HEADER_IDX + 1; i < sb_dfr->nr_chunks; i++) { + struct defrag_chunk_info *chunk = NULL; + struct inode *inode = NULL; + struct defrag_info *ino_dfr = NULL; + + chunk = &chunks[i]; + + /* Check inode */ + __lock_super(sb); + inode = sdfat_iget(sb, chunk->i_pos); + if (!inode) { + dfr_debug("inode not found, i_pos %08llx", chunk->i_pos); + chunk->stat = DFR_CHUNK_STAT_ERR; + err_cnt++; + __unlock_super(sb); + continue; + } + __unlock_super(sb); + + dfr_debug("req[%d] inode %p, i_pos %08llx, f_clus %d, " + "d_clus %08x, nr %d, prev %08x, next %08x", + i, inode, chunk->i_pos, chunk->f_clus, chunk->d_clus, + chunk->nr_clus, chunk->prev_clus, chunk->next_clus); + /** + * Lock ordering: inode_lock -> lock_super + */ + inode_lock(inode); + __lock_super(sb); + + /* Check if enough buffers exist for chunk->new_idx */ + if ((sbi->dfr_new_idx + chunk->nr_clus) >= (PAGE_SIZE / sizeof(int))) { + dfr_err("dfr_new_idx %d, chunk->nr_clus %d", + sbi->dfr_new_idx, chunk->nr_clus); + err = -ENOSPC; + goto unlock; + } + + /* Reserve clusters for defrag with DA */ + err = fsapi_dfr_reserve_clus(sb, chunk->nr_clus); + if (err) + goto unlock; + + /* Check clusters */ + err = fsapi_dfr_validate_clus(inode, chunk, 0); + if (err) { + fsapi_dfr_reserve_clus(sb, 0 - chunk->nr_clus); + dfr_debug("Cluster validation: err %d", err); + goto unlock; + } + + /* Check pages */ + err = defrag_validate_pages(inode, chunk); + if (err) { + fsapi_dfr_reserve_clus(sb, 0 - chunk->nr_clus); + dfr_debug("Page validation: err %d", err); + goto unlock; + } + + /* Mark IGNORE flag to victim AU */ + if (sbi->options.improved_allocation & SDFAT_ALLOC_SMART) + fsapi_dfr_mark_ignore(sb, chunk->d_clus); + + ino_dfr = &(SDFAT_I(inode)->dfr_info); + mutex_lock(&ino_dfr->lock); + + /* Update chunk info */ + chunk->stat = DFR_CHUNK_STAT_REQ; + chunk->new_idx = sbi->dfr_new_idx; + + /* Update ino_dfr info */ + if (list_empty(&(ino_dfr->entry))) { + list_add_tail(&ino_dfr->entry, &sb_dfr->entry); + ino_dfr->chunks = chunk; + igrab(inode); + } + ino_dfr->nr_chunks++; + + atomic_set(&ino_dfr->stat, DFR_INO_STAT_REQ); + + BUG_ON(!mutex_is_locked(&ino_dfr->lock)); + mutex_unlock(&ino_dfr->lock); + + /* Reserved buffers for chunk->new_idx */ + sbi->dfr_new_idx += chunk->nr_clus; + +unlock: + if (err) { + chunk->stat = DFR_CHUNK_STAT_ERR; + err_cnt++; + } + iput(inode); + __unlock_super(sb); + inode_unlock(inode); + } + + /* Return error if all chunks are invalid */ + if (err_cnt == sb_dfr->nr_chunks - 1) { + dfr_debug("%s failed (err_cnt %d)", __func__, err_cnt); + return -ENXIO; + } + + return 0; +} + + +/** + * @fn defrag_check_fs_busy + * @brief check if this module busy + * @return 0 when idle, 1 otherwise + * @param sb super block + * @param reserved_clus # of reserved clusters + * @param queued_pages # of queued pages + */ +static int +defrag_check_fs_busy( + IN struct super_block *sb, + OUT int *reserved_clus, + OUT int *queued_pages) +{ + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + int err = 0; + + *reserved_clus = *queued_pages = 0; + + __lock_super(sb); + *reserved_clus = fsi->reserved_clusters; + *queued_pages = atomic_read(&SDFAT_SB(sb)->stat_n_pages_queued); + + if (*reserved_clus || *queued_pages) + err = 1; + __unlock_super(sb); + + return err; +} + + +/** + * @fn sdfat_ioctl_defrag_req + * @brief ioctl to send defrag requests + * @return 0 on success, -errno otherwise + * @param inode inode + * @param uarg given requests + */ +static int +sdfat_ioctl_defrag_req( + IN struct inode *inode, + INOUT unsigned int *uarg) +{ + struct super_block *sb = inode->i_sb; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + struct defrag_info *sb_dfr = &(sbi->dfr_info); + struct defrag_chunk_header head; + struct defrag_chunk_info *chunks = NULL; + unsigned int len = 0; + int err = 0; + unsigned long timeout = 0; + + /* Check overlapped defrag */ + if (atomic_cmpxchg(&sb_dfr->stat, DFR_SB_STAT_IDLE, DFR_SB_STAT_REQ)) { + dfr_debug("sb_dfr->stat %d", atomic_read(&sb_dfr->stat)); + return -EBUSY; + } + + /* Check if defrag required */ + __lock_super(sb); + if (!fsapi_dfr_check_dfr_required(sb, NULL, NULL, NULL)) { + dfr_debug("Not enough space left for defrag (err %d)", -ENOSPC); + atomic_set(&sb_dfr->stat, DFR_SB_STAT_IDLE); + __unlock_super(sb); + return -ENOSPC; + } + __unlock_super(sb); + + /* Copy args */ + memset(&head, 0, sizeof(struct defrag_chunk_header)); + err = copy_from_user(&head, uarg, sizeof(struct defrag_chunk_info)); + ERR_HANDLE(err); + + /* If FS busy, cancel defrag */ + if (!(head.mode == DFR_MODE_TEST)) { + int reserved_clus = 0, queued_pages = 0; + + err = defrag_check_fs_busy(sb, &reserved_clus, &queued_pages); + if (err) { + dfr_debug("FS busy, cancel defrag (reserved_clus %d, queued_pages %d)", + reserved_clus, queued_pages); + err = -EBUSY; + goto error; + } + } + + /* Total length is saved in the chunk header's nr_chunks field */ + len = head.nr_chunks; + ERR_HANDLE2(!len, err, -EINVAL); + + dfr_debug("IOC_DFR_REQ started (mode %d, nr_req %d)", head.mode, len - 1); + if (get_order(len * sizeof(struct defrag_chunk_info)) > MAX_ORDER) { + dfr_debug("len %u, sizeof(struct defrag_chunk_info) %lu, MAX_ORDER %d", + len, sizeof(struct defrag_chunk_info), MAX_ORDER); + err = -EINVAL; + goto error; + } + chunks = alloc_pages_exact(len * sizeof(struct defrag_chunk_info), + GFP_KERNEL | __GFP_ZERO); + ERR_HANDLE2(!chunks, err, -ENOMEM) + + err = copy_from_user(chunks, uarg, len * sizeof(struct defrag_chunk_info)); + ERR_HANDLE(err); + + /* Initialize sb_dfr */ + sb_dfr->chunks = chunks; + sb_dfr->nr_chunks = len; + + /* Validate reqs & mark defrag/dirty */ + err = defrag_validate_reqs(sb, sb_dfr->chunks); + ERR_HANDLE(err); + + atomic_set(&sb_dfr->stat, DFR_SB_STAT_VALID); + + /* Wait for defrag completion */ + if (head.mode == DFR_MODE_ONESHOT) + timeout = 0; + else if (head.mode & DFR_MODE_BACKGROUND) + timeout = DFR_DEFAULT_TIMEOUT; + else + timeout = DFR_MIN_TIMEOUT; + + dfr_debug("Wait for completion (timeout %ld)", timeout); + init_completion(&sbi->dfr_complete); + timeout = wait_for_completion_timeout(&sbi->dfr_complete, timeout); + + if (!timeout) { + /* Force defrag_updat_fat() after timeout. */ + dfr_debug("Force sync(), mode %d, left-timeout %ld", head.mode, timeout); + + down_read(&sb->s_umount); + + sync_inodes_sb(sb); + + __lock_super(sb); + fsapi_dfr_update_fat_next(sb); + + fsapi_sync_fs(sb, 1); + +#ifdef CONFIG_SDFAT_DFR_DEBUG + /* SPO test */ + fsapi_dfr_spo_test(sb, DFR_SPO_FAT_NEXT, __func__); +#endif + + fsapi_dfr_update_fat_prev(sb, 1); + fsapi_sync_fs(sb, 1); + + __unlock_super(sb); + + up_read(&sb->s_umount); + } + +#ifdef CONFIG_SDFAT_DFR_DEBUG + /* SPO test */ + fsapi_dfr_spo_test(sb, DFR_SPO_NORMAL, __func__); +#endif + + __lock_super(sb); + /* Send DISCARD to clean-ed AUs */ + fsapi_dfr_check_discard(sb); + +#ifdef CONFIG_SDFAT_DFR_DEBUG + /* SPO test */ + fsapi_dfr_spo_test(sb, DFR_SPO_DISCARD, __func__); +#endif + + /* Unmark IGNORE flag to all victim AUs */ + fsapi_dfr_unmark_ignore_all(sb); + __unlock_super(sb); + + err = copy_to_user(uarg, sb_dfr->chunks, sizeof(struct defrag_chunk_info) * len); + ERR_HANDLE(err); + +error: + /* Clean-up sb_dfr & ino_dfr */ + defrag_cleanup_reqs(sb, err); + + if (chunks) + free_pages_exact(chunks, len * sizeof(struct defrag_chunk_info)); + + /* Set sb_dfr's state as IDLE */ + atomic_set(&sb_dfr->stat, DFR_SB_STAT_IDLE); + + dfr_debug("IOC_DFR_REQ done (err %d)", err); + return err; +} + +/** + * @fn sdfat_ioctl_defrag_trav + * @brief ioctl to traverse given directory for defrag + * @return 0 on success, -errno otherwise + * @param inode inode + * @param uarg output buffer + */ +static int +sdfat_ioctl_defrag_trav( + IN struct inode *inode, + INOUT unsigned int *uarg) +{ + struct super_block *sb = inode->i_sb; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + struct defrag_info *sb_dfr = &(sbi->dfr_info); + struct defrag_trav_arg *args = (struct defrag_trav_arg *) sbi->dfr_pagep; + struct defrag_trav_header *header = (struct defrag_trav_header *) args; + int err = 0; + + /* Check overlapped defrag */ + if (atomic_cmpxchg(&sb_dfr->stat, DFR_SB_STAT_IDLE, DFR_SB_STAT_REQ)) { + dfr_debug("sb_dfr->stat %d", atomic_read(&sb_dfr->stat)); + return -EBUSY; + } + + /* Check if defrag required */ + __lock_super(sb); + if (!fsapi_dfr_check_dfr_required(sb, NULL, NULL, NULL)) { + dfr_debug("Not enough space left for defrag (err %d)", -ENOSPC); + atomic_set(&sb_dfr->stat, DFR_SB_STAT_IDLE); + __unlock_super(sb); + return -ENOSPC; + } + __unlock_super(sb); + + /* Copy args */ + err = copy_from_user(args, uarg, PAGE_SIZE); + ERR_HANDLE(err); + + /** + * Check args. + * ROOT directory has i_pos = 0 and start_clus = 0 . + */ + if (!(header->type & DFR_TRAV_TYPE_HEADER)) { + err = -EINVAL; + dfr_debug("type %d, i_pos %08llx, start_clus %08x", + header->type, header->i_pos, header->start_clus); + goto error; + } + + /* If FS busy, cancel defrag */ + if (!(header->type & DFR_TRAV_TYPE_TEST)) { + unsigned int reserved_clus = 0, queued_pages = 0; + + err = defrag_check_fs_busy(sb, &reserved_clus, &queued_pages); + if (err) { + dfr_debug("FS busy, cancel defrag (reserved_clus %d, queued_pages %d)", + reserved_clus, queued_pages); + err = -EBUSY; + goto error; + } + } + + /* Scan given directory and gather info */ + inode_lock(inode); + __lock_super(sb); + err = fsapi_dfr_scan_dir(sb, (void *)args); + __unlock_super(sb); + inode_unlock(inode); + ERR_HANDLE(err); + + /* Copy the result to user */ + err = copy_to_user(uarg, args, PAGE_SIZE); + ERR_HANDLE(err); + +error: + memset(sbi->dfr_pagep, 0, PAGE_SIZE); + + atomic_set(&sb_dfr->stat, DFR_SB_STAT_IDLE); + return err; +} + +/** + * @fn sdfat_ioctl_defrag_info + * @brief ioctl to get HW param info + * @return 0 on success, -errno otherwise + * @param sb super block + * @param uarg output buffer + */ +static int +sdfat_ioctl_defrag_info( + IN struct super_block *sb, + OUT unsigned int *uarg) +{ + struct defrag_info_arg info_arg; + int err = 0; + + memset(&info_arg, 0, sizeof(struct defrag_info_arg)); + + __lock_super(sb); + err = fsapi_dfr_get_info(sb, &info_arg); + __unlock_super(sb); + ERR_HANDLE(err); + dfr_debug("IOC_DFR_INFO: sec_per_au %d, hidden_sectors %d", + info_arg.sec_per_au, info_arg.hidden_sectors); + + err = copy_to_user(uarg, &info_arg, sizeof(struct defrag_info_arg)); +error: + return err; +} + +#endif /* CONFIG_SDFAT_DFR */ + +static inline int __do_dfr_map_cluster(struct inode *inode, u32 clu_offset, unsigned int *clus_ptr) +{ +#ifdef CONFIG_SDFAT_DFR + return fsapi_dfr_map_clus(inode, clu_offset, clus_ptr); +#else + return 0; +#endif +} + +static inline int __check_dfr_on(struct inode *inode, loff_t start, loff_t end, const char *fname) +{ +#ifdef CONFIG_SDFAT_DFR + struct defrag_info *ino_dfr = &(SDFAT_I(inode)->dfr_info); + + if ((atomic_read(&ino_dfr->stat) == DFR_INO_STAT_REQ) && + fsapi_dfr_check_dfr_on(inode, start, end, 0, fname)) + return 1; +#endif + return 0; +} + +static inline int __cancel_dfr_work(struct inode *inode, loff_t start, loff_t end, const char *fname) +{ +#ifdef CONFIG_SDFAT_DFR + struct defrag_info *ino_dfr = &(SDFAT_I(inode)->dfr_info); + /* Cancel DEFRAG */ + if (atomic_read(&ino_dfr->stat) == DFR_INO_STAT_REQ) + fsapi_dfr_check_dfr_on(inode, start, end, 1, fname); +#endif + return 0; +} + +static inline int __dfr_writepage_end_io(struct page *page) +{ +#ifdef CONFIG_SDFAT_DFR + struct defrag_info *ino_dfr = &(SDFAT_I(page->mapping->host)->dfr_info); + + if (atomic_read(&ino_dfr->stat) == DFR_INO_STAT_REQ) + fsapi_dfr_writepage_endio(page); +#endif + return 0; +} + +static inline void __init_dfr_info(struct inode *inode) +{ +#ifdef CONFIG_SDFAT_DFR + memset(&(SDFAT_I(inode)->dfr_info), 0, sizeof(struct defrag_info)); + INIT_LIST_HEAD(&(SDFAT_I(inode)->dfr_info.entry)); + mutex_init(&(SDFAT_I(inode)->dfr_info.lock)); +#endif +} + +static inline int __alloc_dfr_mem_if_required(struct super_block *sb) +{ +#ifdef CONFIG_SDFAT_DFR + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + + if (!sbi->options.defrag) + return 0; + + memset(&sbi->dfr_info, 0, sizeof(struct defrag_info)); + INIT_LIST_HEAD(&(sbi->dfr_info.entry)); + mutex_init(&(sbi->dfr_info.lock)); + + sbi->dfr_new_clus = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!sbi->dfr_new_clus) { + dfr_debug("error %d", -ENOMEM); + return -ENOMEM; + } + sbi->dfr_new_idx = 1; + + sbi->dfr_page_wb = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!sbi->dfr_page_wb) { + dfr_debug("error %d", -ENOMEM); + return -ENOMEM; + } + + sbi->dfr_pagep = alloc_pages_exact(sizeof(struct page *) * + PAGES_PER_AU(sb), GFP_KERNEL | __GFP_ZERO); + if (!sbi->dfr_pagep) { + dfr_debug("error %d", -ENOMEM); + return -ENOMEM; + } +#endif + return 0; +} + +static void __free_dfr_mem_if_required(struct super_block *sb) +{ +#ifdef CONFIG_SDFAT_DFR + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + + if (sbi->dfr_pagep) { + free_pages_exact(sbi->dfr_pagep, sizeof(struct page *) * PAGES_PER_AU(sb)); + sbi->dfr_pagep = NULL; + } + + /* thanks for kfree */ + kfree(sbi->dfr_page_wb); + sbi->dfr_page_wb = NULL; + + kfree(sbi->dfr_new_clus); + sbi->dfr_new_clus = NULL; +#endif +} + + +static int sdfat_file_mmap(struct file *file, struct vm_area_struct *vm_struct) +{ + __cancel_dfr_work(file->f_mapping->host, + (loff_t)vm_struct->vm_start, + (loff_t)(vm_struct->vm_end - 1), + __func__); + + return generic_file_mmap(file, vm_struct); +} + +static int sdfat_ioctl_volume_id(struct inode *dir) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(dir->i_sb); + FS_INFO_T *fsi = &(sbi->fsi); + + return fsi->vol_id; +} + +static int sdfat_dfr_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ +#ifdef CONFIG_SDFAT_DFR + switch (cmd) { + case SDFAT_IOCTL_DFR_INFO: { + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &SDFAT_SB(sb)->fsi; + unsigned int __user *uarg = (unsigned int __user *) arg; + + __lock_super(sb); + /* Check FS type (FAT32 only) */ + if (fsi->vol_type != FAT32) { + dfr_err("Defrag not supported, vol_type %d", fsi->vol_type); + __unlock_super(sb); + return -EPERM; + + } + + /* Check if SB's defrag option enabled */ + if (!(SDFAT_SB(sb)->options.defrag)) { + dfr_err("Defrag not supported, sbi->options.defrag %d", SDFAT_SB(sb)->options.defrag); + __unlock_super(sb); + return -EPERM; + } + + /* Only IOCTL on mount-point allowed */ + if (filp->f_path.mnt->mnt_root != filp->f_path.dentry) { + dfr_err("IOC_DFR_INFO only allowed on ROOT, root %p, dentry %p", + filp->f_path.mnt->mnt_root, filp->f_path.dentry); + __unlock_super(sb); + return -EPERM; + } + __unlock_super(sb); + + return sdfat_ioctl_defrag_info(sb, uarg); + } + case SDFAT_IOCTL_DFR_TRAV: { + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &SDFAT_SB(sb)->fsi; + unsigned int __user *uarg = (unsigned int __user *) arg; + + __lock_super(sb); + /* Check FS type (FAT32 only) */ + if (fsi->vol_type != FAT32) { + dfr_err("Defrag not supported, vol_type %d", fsi->vol_type); + __unlock_super(sb); + return -EPERM; + + } + + /* Check if SB's defrag option enabled */ + if (!(SDFAT_SB(sb)->options.defrag)) { + dfr_err("Defrag not supported, sbi->options.defrag %d", SDFAT_SB(sb)->options.defrag); + __unlock_super(sb); + return -EPERM; + } + __unlock_super(sb); + + return sdfat_ioctl_defrag_trav(inode, uarg); + } + case SDFAT_IOCTL_DFR_REQ: { + struct super_block *sb = inode->i_sb; + FS_INFO_T *fsi = &SDFAT_SB(sb)->fsi; + unsigned int __user *uarg = (unsigned int __user *) arg; + + __lock_super(sb); + + /* Check if FS_ERROR occurred */ + if (sb->s_flags & MS_RDONLY) { + dfr_err("RDONLY partition (err %d)", -EPERM); + __unlock_super(sb); + return -EPERM; + } + + /* Check FS type (FAT32 only) */ + if (fsi->vol_type != FAT32) { + dfr_err("Defrag not supported, vol_type %d", fsi->vol_type); + __unlock_super(sb); + return -EINVAL; + + } + + /* Check if SB's defrag option enabled */ + if (!(SDFAT_SB(sb)->options.defrag)) { + dfr_err("Defrag not supported, sbi->options.defrag %d", SDFAT_SB(sb)->options.defrag); + __unlock_super(sb); + return -EPERM; + } + + /* Only IOCTL on mount-point allowed */ + if (filp->f_path.mnt->mnt_root != filp->f_path.dentry) { + dfr_err("IOC_DFR_INFO only allowed on ROOT, root %p, dentry %p", + filp->f_path.mnt->mnt_root, filp->f_path.dentry); + __unlock_super(sb); + return -EINVAL; + } + __unlock_super(sb); + + return sdfat_ioctl_defrag_req(inode, uarg); + } +#ifdef CONFIG_SDFAT_DFR_DEBUG + case SDFAT_IOCTL_DFR_SPO_FLAG: { + struct sdfat_sb_info *sbi = SDFAT_SB(inode->i_sb); + int ret = 0; + + ret = get_user(sbi->dfr_spo_flag, (int __user *)arg); + dfr_debug("dfr_spo_flag %d", sbi->dfr_spo_flag); + + return ret; + } +#endif /* CONFIG_SDFAT_DFR_DEBUG */ + } +#endif /* CONFIG_SDFAT_DFR */ + + /* Inappropriate ioctl for device */ + return -ENOTTY; +} + +static int sdfat_dbg_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ +#ifdef CONFIG_SDFAT_DBG_IOCTL + struct super_block *sb = inode->i_sb; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + unsigned int flags; + + switch (cmd) { + case SDFAT_IOC_GET_DEBUGFLAGS: + flags = sbi->debug_flags; + return put_user(flags, (int __user *)arg); + case SDFAT_IOC_SET_DEBUGFLAGS: + flags = 0; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (get_user(flags, (int __user *) arg)) + return -EFAULT; + + __lock_super(sb); + sbi->debug_flags = flags; + __unlock_super(sb); + return 0; + case SDFAT_IOCTL_PANIC: + panic("ioctl panic for test"); + + /* COULD NOT REACH HEAR */ + return 0; + } +#endif /* CONFIG_SDFAT_DBG_IOCTL */ + return -ENOTTY; +} + +static long sdfat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct inode *inode = file_inode(filp); + int err; + + if (cmd == SDFAT_IOCTL_GET_VOLUME_ID) + return sdfat_ioctl_volume_id(inode); + + err = sdfat_dfr_ioctl(inode, filp, cmd, arg); + if (err != -ENOTTY) + return err; + + /* -ENOTTY if inappropriate ioctl for device */ + return sdfat_dbg_ioctl(inode, filp, cmd, arg); +} + + +static void __sdfat_writepage_end_io(struct bio *bio, int err) +{ + struct page *page = bio->bi_io_vec->bv_page; + struct super_block *sb = page->mapping->host->i_sb; + + ASSERT(bio->bi_vcnt == 1); /* Single page endio */ + ASSERT(bio_data_dir(bio)); /* Write */ + + if (err) { + SetPageError(page); + mapping_set_error(page->mapping, err); + } + + __dfr_writepage_end_io(page); + +#ifdef CONFIG_SDFAT_TRACE_IO + { + //struct sdfat_sb_info *sbi = SDFAT_SB(bio->bi_bdev->bd_super); + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + + sbi->stat_n_pages_written++; + if (page->mapping->host == sb->s_bdev->bd_inode) + sbi->stat_n_bdev_pages_written++; + + /* 4 MB = 1024 pages => 0.4 sec (approx.) + * 32 KB = 64 pages => 0.025 sec + * Min. average latency b/w msgs. ~= 0.025 sec + */ + if ((sbi->stat_n_pages_written & 63) == 0) { + DMSG("STAT:%u, %u, %u, %u (Sector #: %u)\n", + sbi->stat_n_pages_added, sbi->stat_n_pages_written, + sbi->stat_n_bdev_pages_witten, + sbi->stat_n_pages_confused, + (unsigned int)__sdfat_bio_sector(bio)); + } + } +#endif + end_page_writeback(page); + bio_put(bio); + + // Update trace info. + atomic_dec(&SDFAT_SB(sb)->stat_n_pages_queued); +} + + +static int __support_write_inode_sync(struct super_block *sb) +{ +#ifdef CONFIG_SDFAT_SUPPORT_DIR_SYNC +#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + + if (sbi->fsi.vol_type != EXFAT) + return 0; +#endif + return 1; +#endif + return 0; +} + + +static int __sdfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync) +{ + struct inode *inode = filp->f_mapping->host; + struct super_block *sb = inode->i_sb; + int res, err = 0; + + res = __sdfat_generic_file_fsync(filp, start, end, datasync); + + if (!__support_write_inode_sync(sb)) + err = fsapi_sync_fs(sb, 1); + + return res ? res : err; +} + + +static const struct file_operations sdfat_dir_operations = { + .llseek = generic_file_llseek, + .read = generic_read_dir, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) + .iterate = sdfat_iterate, +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */ + .readdir = sdfat_readdir, +#endif + .fsync = sdfat_file_fsync, + .unlocked_ioctl = sdfat_generic_ioctl, +}; + +static int __sdfat_create(struct inode *dir, struct dentry *dentry) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct timespec ts; + FILE_ID_T fid; + loff_t i_pos; + int err; + + __lock_super(sb); + + TMSG("%s entered\n", __func__); + + ts = CURRENT_TIME_SEC; + + err = fsapi_create(dir, (u8 *) dentry->d_name.name, FM_REGULAR, &fid); + if (err) + goto out; + + __lock_d_revalidate(dentry); + + dir->i_version++; + dir->i_ctime = dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) sdfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + i_pos = sdfat_make_i_pos(&fid); + inode = sdfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + inode->i_version++; + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + d_instantiate(dentry, inode); +out: + __unlock_d_revalidate(dentry); + __unlock_super(sb); + TMSG("%s exited with err(%d)\n", __func__, err); + if (!err) + sdfat_statistics_set_create(fid.flags); + return err; +} + + +static int sdfat_find(struct inode *dir, struct qstr *qname, FILE_ID_T *fid) +{ + int err; + + if (qname->len == 0) + return -ENOENT; + + err = fsapi_lookup(dir, (u8 *) qname->name, fid); + if (err) + return -ENOENT; + + return 0; +} + +static int sdfat_d_anon_disconn(struct dentry *dentry) +{ + return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED); +} + +static struct dentry *__sdfat_lookup(struct inode *dir, struct dentry *dentry) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct dentry *alias; + int err; + FILE_ID_T fid; + loff_t i_pos; + u64 ret; + mode_t i_mode; + + __lock_super(sb); + TMSG("%s entered\n", __func__); + err = sdfat_find(dir, &dentry->d_name, &fid); + if (err) { + if (err == -ENOENT) { + inode = NULL; + goto out; + } + goto error; + } + + i_pos = sdfat_make_i_pos(&fid); + inode = sdfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto error; + } + + i_mode = inode->i_mode; + if (S_ISLNK(i_mode) && !SDFAT_I(inode)->target) { + SDFAT_I(inode)->target = kmalloc((i_size_read(inode)+1), GFP_KERNEL); + if (!SDFAT_I(inode)->target) { + err = -ENOMEM; + goto error; + } + fsapi_read_link(dir, &fid, SDFAT_I(inode)->target, i_size_read(inode), &ret); + *(SDFAT_I(inode)->target + i_size_read(inode)) = '\0'; + } + + alias = d_find_alias(inode); + + /* + * Checking "alias->d_parent == dentry->d_parent" to make sure + * FS is not corrupted (especially double linked dir). + */ + if (alias && alias->d_parent == dentry->d_parent && + !sdfat_d_anon_disconn(alias)) { + + /* + * Unhashed alias is able to exist because of revalidate() + * called by lookup_fast. You can easily make this status + * by calling create and lookup concurrently + * In such case, we reuse an alias instead of new dentry + */ + if (d_unhashed(alias)) { + BUG_ON(alias->d_name.hash_len != dentry->d_name.hash_len); + sdfat_msg(sb, KERN_INFO, "rehashed a dentry(%p) " + "in read lookup", alias); + d_drop(dentry); + d_rehash(alias); + } else if (!S_ISDIR(i_mode)) { + /* + * This inode has non anonymous-DCACHE_DISCONNECTED + * dentry. This means, the user did ->lookup() by an + * another name (longname vs 8.3 alias of it) in past. + * + * Switch to new one for reason of locality if possible. + */ + d_move(alias, dentry); + } + iput(inode); + __unlock_super(sb); + TMSG("%s exited\n", __func__); + return alias; + } + dput(alias); +out: + /* initialize d_time even though it is positive dentry */ + dentry->d_time = dir->i_version; + __unlock_super(sb); + + dentry = d_splice_alias(inode, dentry); + + TMSG("%s exited\n", __func__); + return dentry; +error: + __unlock_super(sb); + TMSG("%s exited with err(%d)\n", __func__, err); + return ERR_PTR(err); +} + + +static int sdfat_unlink(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct super_block *sb = dir->i_sb; + struct timespec ts; + int err; + + __lock_super(sb); + + TMSG("%s entered\n", __func__); + + ts = CURRENT_TIME_SEC; + + SDFAT_I(inode)->fid.size = i_size_read(inode); + + __cancel_dfr_work(inode, 0, SDFAT_I(inode)->fid.size, __func__); + + err = fsapi_unlink(dir, &(SDFAT_I(inode)->fid)); + if (err) + goto out; + + __lock_d_revalidate(dentry); + + dir->i_version++; + dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) sdfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + clear_nlink(inode); + inode->i_mtime = inode->i_atime = ts; + sdfat_detach(inode); + dentry->d_time = dir->i_version; +out: + __unlock_d_revalidate(dentry); + __unlock_super(sb); + TMSG("%s exited with err(%d)\n", __func__, err); + return err; +} + +static int sdfat_symlink(struct inode *dir, struct dentry *dentry, const char *target) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct timespec ts; + FILE_ID_T fid; + loff_t i_pos; + int err; + u64 len = (u64) strlen(target); + u64 ret; + + /* symlink option check */ + if (!SDFAT_SB(sb)->options.symlink) + return -ENOTSUPP; + + __lock_super(sb); + + TMSG("%s entered\n", __func__); + + ts = CURRENT_TIME_SEC; + + err = fsapi_create(dir, (u8 *) dentry->d_name.name, FM_SYMLINK, &fid); + if (err) + goto out; + + err = fsapi_write_link(dir, &fid, (char *) target, len, &ret); + + if (err) { + fsapi_remove(dir, &fid); + goto out; + } + + __lock_d_revalidate(dentry); + + dir->i_version++; + dir->i_ctime = dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) sdfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + i_pos = sdfat_make_i_pos(&fid); + inode = sdfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + inode->i_version++; + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + SDFAT_I(inode)->target = kmalloc((len+1), GFP_KERNEL); + if (!SDFAT_I(inode)->target) { + err = -ENOMEM; + goto out; + } + memcpy(SDFAT_I(inode)->target, target, len+1); + + d_instantiate(dentry, inode); +out: + __unlock_d_revalidate(dentry); + __unlock_super(sb); + TMSG("%s exited with err(%d)\n", __func__, err); + return err; +} + + +static int __sdfat_mkdir(struct inode *dir, struct dentry *dentry) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct timespec ts; + FILE_ID_T fid; + loff_t i_pos; + int err; + + __lock_super(sb); + + TMSG("%s entered\n", __func__); + + ts = CURRENT_TIME_SEC; + + err = fsapi_mkdir(dir, (u8 *) dentry->d_name.name, &fid); + if (err) + goto out; + + __lock_d_revalidate(dentry); + + dir->i_version++; + dir->i_ctime = dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) sdfat_sync_inode(dir); + else + mark_inode_dirty(dir); + inc_nlink(dir); + + i_pos = sdfat_make_i_pos(&fid); + inode = sdfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + inode->i_version++; + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + d_instantiate(dentry, inode); + +out: + __unlock_d_revalidate(dentry); + __unlock_super(sb); + TMSG("%s exited with err(%d)\n", __func__, err); + if (!err) + sdfat_statistics_set_mkdir(fid.flags); + return err; +} + + +static int sdfat_rmdir(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct super_block *sb = dir->i_sb; + struct timespec ts; + int err; + + __lock_super(sb); + + TMSG("%s entered\n", __func__); + + ts = CURRENT_TIME_SEC; + + SDFAT_I(inode)->fid.size = i_size_read(inode); + + err = fsapi_rmdir(dir, &(SDFAT_I(inode)->fid)); + if (err) + goto out; + + __lock_d_revalidate(dentry); + + dir->i_version++; + dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) sdfat_sync_inode(dir); + else + mark_inode_dirty(dir); + drop_nlink(dir); + + clear_nlink(inode); + inode->i_mtime = inode->i_atime = ts; + sdfat_detach(inode); + dentry->d_time = dir->i_version; +out: + __unlock_d_revalidate(dentry); + __unlock_super(sb); + TMSG("%s exited with err(%d)\n", __func__, err); + return err; +} + +static int __sdfat_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) +{ + struct inode *old_inode, *new_inode; + struct super_block *sb = old_dir->i_sb; + struct timespec ts; + loff_t i_pos; + int err; + + __lock_super(sb); + + TMSG("%s entered\n", __func__); + + old_inode = old_dentry->d_inode; + new_inode = new_dentry->d_inode; + + ts = CURRENT_TIME_SEC; + + SDFAT_I(old_inode)->fid.size = i_size_read(old_inode); + + __cancel_dfr_work(old_inode, 0, 1, __func__); + + err = fsapi_rename(old_dir, &(SDFAT_I(old_inode)->fid), new_dir, new_dentry); + if (err) + goto out; + + __lock_d_revalidate(old_dentry); + __lock_d_revalidate(new_dentry); + + new_dir->i_version++; + new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = ts; + if (IS_DIRSYNC(new_dir)) + (void) sdfat_sync_inode(new_dir); + else + mark_inode_dirty(new_dir); + + i_pos = sdfat_make_i_pos(&(SDFAT_I(old_inode)->fid)); + sdfat_detach(old_inode); + sdfat_attach(old_inode, i_pos); + if (IS_DIRSYNC(new_dir)) + (void) sdfat_sync_inode(old_inode); + else + mark_inode_dirty(old_inode); + + if ((S_ISDIR(old_inode->i_mode)) && (old_dir != new_dir)) { + drop_nlink(old_dir); + if (!new_inode) + inc_nlink(new_dir); + } + + old_dir->i_version++; + old_dir->i_ctime = old_dir->i_mtime = ts; + if (IS_DIRSYNC(old_dir)) + (void) sdfat_sync_inode(old_dir); + else + mark_inode_dirty(old_dir); + + if (new_inode) { + sdfat_detach(new_inode); + + /* skip drop_nlink if new_inode already has been dropped */ + if (new_inode->i_nlink) { + drop_nlink(new_inode); + if (S_ISDIR(new_inode->i_mode)) + drop_nlink(new_inode); + } else { + EMSG("%s : abnormal access to an inode dropped\n", + __func__); + WARN_ON(new_inode->i_nlink == 0); + } + new_inode->i_ctime = ts; +#if 0 + (void) sdfat_sync_inode(new_inode); +#endif + } + +out: + __unlock_d_revalidate(old_dentry); + __unlock_d_revalidate(new_dentry); + __unlock_super(sb); + TMSG("%s exited with err(%d)\n", __func__, err); + return err; +} + +static int sdfat_cont_expand(struct inode *inode, loff_t size) +{ + struct address_space *mapping = inode->i_mapping; + loff_t start = i_size_read(inode), count = size - i_size_read(inode); + int err, err2; + + err = generic_cont_expand_simple(inode, size); + if (err) + return err; + + inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; + mark_inode_dirty(inode); + + if (!IS_SYNC(inode)) + return 0; + + err = filemap_fdatawrite_range(mapping, start, start + count - 1); + err2 = sync_mapping_buffers(mapping); + err = (err)?(err):(err2); + err2 = write_inode_now(inode, 1); + err = (err)?(err):(err2); + if (err) + return err; + + return filemap_fdatawait_range(mapping, start, start + count - 1); +} + +static int sdfat_allow_set_time(struct sdfat_sb_info *sbi, struct inode *inode) +{ + mode_t allow_utime = sbi->options.allow_utime; + + if (!uid_eq(current_fsuid(), inode->i_uid)) { + if (in_group_p(inode->i_gid)) + allow_utime >>= 3; + if (allow_utime & MAY_WRITE) + return 1; + } + + /* use a default check */ + return 0; +} + +static int sdfat_sanitize_mode(const struct sdfat_sb_info *sbi, + struct inode *inode, umode_t *mode_ptr) +{ + mode_t i_mode, mask, perm; + + i_mode = inode->i_mode; + + if (S_ISREG(i_mode) || S_ISLNK(i_mode)) + mask = sbi->options.fs_fmask; + else + mask = sbi->options.fs_dmask; + + perm = *mode_ptr & ~(S_IFMT | mask); + + /* Of the r and x bits, all (subject to umask) must be present.*/ + if ((perm & (S_IRUGO | S_IXUGO)) != (i_mode & (S_IRUGO | S_IXUGO))) + return -EPERM; + + if (sdfat_mode_can_hold_ro(inode)) { + /* Of the w bits, either all (subject to umask) or none must be present. */ + if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask))) + return -EPERM; + } else { + /* If sdfat_mode_can_hold_ro(inode) is false, can't change w bits. */ + if ((perm & S_IWUGO) != (S_IWUGO & ~mask)) + return -EPERM; + } + + *mode_ptr &= S_IFMT | perm; + + return 0; +} + +static int sdfat_setattr(struct dentry *dentry, struct iattr *attr) +{ + + struct sdfat_sb_info *sbi = SDFAT_SB(dentry->d_sb); + struct inode *inode = dentry->d_inode; + unsigned int ia_valid; + int error; + loff_t old_size; + + TMSG("%s entered\n", __func__); + + if ((attr->ia_valid & ATTR_SIZE) + && (attr->ia_size > i_size_read(inode))) { + error = sdfat_cont_expand(inode, attr->ia_size); + if (error || attr->ia_valid == ATTR_SIZE) + return error; + attr->ia_valid &= ~ATTR_SIZE; + } + + /* Check for setting the inode time. */ + ia_valid = attr->ia_valid; + if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) + && sdfat_allow_set_time(sbi, inode)) { + attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET); + } + + error = setattr_prepare(dentry, attr); + attr->ia_valid = ia_valid; + if (error) + return error; + + if (((attr->ia_valid & ATTR_UID) && + (!uid_eq(attr->ia_uid, sbi->options.fs_uid))) || + ((attr->ia_valid & ATTR_GID) && + (!gid_eq(attr->ia_gid, sbi->options.fs_gid))) || + ((attr->ia_valid & ATTR_MODE) && + (attr->ia_mode & ~(S_IFREG | S_IFLNK | S_IFDIR | S_IRWXUGO)))) { + return -EPERM; + } + + /* + * We don't return -EPERM here. Yes, strange, but this is too + * old behavior. + */ + if (attr->ia_valid & ATTR_MODE) { + if (sdfat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0) + attr->ia_valid &= ~ATTR_MODE; + } + + SDFAT_I(inode)->fid.size = i_size_read(inode); + + /* patch 1.2.0 : fixed the problem of size mismatch. */ + if (attr->ia_valid & ATTR_SIZE) { + old_size = i_size_read(inode); + + /* TO CHECK evicting directory works correctly */ + MMSG("%s: inode(%p) truncate size (%llu->%llu)\n", __func__, + inode, (u64)old_size, (u64)attr->ia_size); + __sdfat_do_truncate(inode, old_size, attr->ia_size); + } + setattr_copy(inode, attr); + mark_inode_dirty(inode); + + + TMSG("%s exited with err(%d)\n", __func__, error); + return error; +} + +static int sdfat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) +{ + struct inode *inode = dentry->d_inode; + + TMSG("%s entered\n", __func__); + + generic_fillattr(inode, stat); + stat->blksize = SDFAT_SB(inode->i_sb)->fsi.cluster_size; + + TMSG("%s exited\n", __func__); + return 0; +} + +static const struct inode_operations sdfat_dir_inode_operations = { + .create = sdfat_create, + .lookup = sdfat_lookup, + .unlink = sdfat_unlink, + .symlink = sdfat_symlink, + .mkdir = sdfat_mkdir, + .rmdir = sdfat_rmdir, + .rename = sdfat_rename, + .setattr = sdfat_setattr, + .getattr = sdfat_getattr, +#ifdef CONFIG_SDFAT_VIRTUAL_XATTR + .listxattr = sdfat_listxattr, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) + .setxattr = sdfat_setxattr, + .getxattr = sdfat_getxattr, + .removexattr = sdfat_removexattr, +#endif +#endif +}; + +/*======================================================================*/ +/* File Operations */ +/*======================================================================*/ +static const struct inode_operations sdfat_symlink_inode_operations = { + .readlink = generic_readlink, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) + .get_link = sdfat_follow_link, +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0) */ + .follow_link = sdfat_follow_link, +#endif +#ifdef CONFIG_SDFAT_VIRTUAL_XATTR + .listxattr = sdfat_listxattr, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) + .setxattr = sdfat_setxattr, + .getxattr = sdfat_getxattr, + .removexattr = sdfat_removexattr, +#endif +#endif +}; + +static int sdfat_file_release(struct inode *inode, struct file *filp) +{ + struct super_block *sb = inode->i_sb; + + /* Moved below code from sdfat_write_inode + * TO FIX size-mismatch problem. + */ + /* FIXME : Added bug_on to confirm that there is no size mismatch */ + sdfat_debug_bug_on(SDFAT_I(inode)->fid.size != i_size_read(inode)); + SDFAT_I(inode)->fid.size = i_size_read(inode); + fsapi_sync_fs(sb, 0); + return 0; +} + +static const struct file_operations sdfat_file_operations = { + .llseek = generic_file_llseek, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) + .read_iter = generic_file_read_iter, + .write_iter = generic_file_write_iter, +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) + .read = new_sync_read, + .write = new_sync_write, + .read_iter = generic_file_read_iter, + .write_iter = generic_file_write_iter, +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) */ + .read = do_sync_read, + .write = do_sync_write, + .aio_read = generic_file_aio_read, + .aio_write = generic_file_aio_write, +#endif + .mmap = sdfat_file_mmap, + .release = sdfat_file_release, + .unlocked_ioctl = sdfat_generic_ioctl, + .fsync = sdfat_file_fsync, + .splice_read = generic_file_splice_read, +}; + +static const struct address_space_operations sdfat_da_aops; +static const struct address_space_operations sdfat_aops; + +static void sdfat_truncate(struct inode *inode, loff_t old_size) +{ + struct super_block *sb = inode->i_sb; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + FS_INFO_T *fsi = &(sbi->fsi); + unsigned int blocksize = 1 << inode->i_blkbits; + loff_t aligned_size; + int err; + + __lock_super(sb); + + if (SDFAT_I(inode)->fid.start_clu == 0) { + /* Stange statement: + * Empty start_clu != ~0 (not allocated) + */ + sdfat_fs_error(sb, "tried to truncate zeroed cluster."); + goto out; + } + + sdfat_debug_check_clusters(inode); + + __cancel_dfr_work(inode, (loff_t)i_size_read(inode), (loff_t)old_size, __func__); + + err = fsapi_truncate(inode, old_size, i_size_read(inode)); + if (err) + goto out; + + inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; + if (IS_DIRSYNC(inode)) + (void) sdfat_sync_inode(inode); + else + mark_inode_dirty(inode); + + // FIXME: í™•ì¸ ìš”ë§ + // inode->i_blocks = ((SDFAT_I(inode)->i_size_ondisk + (fsi->cluster_size - 1)) + inode->i_blocks = ((i_size_read(inode) + (fsi->cluster_size - 1)) & + ~((loff_t)fsi->cluster_size - 1)) >> inode->i_blkbits; +out: + /* + * This protects against truncating a file bigger than it was then + * trying to write into the hole. + * + * comment by sh.hong: + * This seems to mean 'intra page/block' truncate and writing. + * I couldn't find a reason to change the values prior to fsapi_truncate + * Therefore, I switched the order of operations + * so that it's possible to utilize i_size_ondisk in fsapi_truncate + */ + + aligned_size = i_size_read(inode); + if (aligned_size & (blocksize - 1)) { + aligned_size |= (blocksize - 1); + aligned_size++; + } + + if (SDFAT_I(inode)->i_size_ondisk > i_size_read(inode)) + SDFAT_I(inode)->i_size_ondisk = aligned_size; + + sdfat_debug_check_clusters(inode); + + if (SDFAT_I(inode)->i_size_aligned > i_size_read(inode)) + SDFAT_I(inode)->i_size_aligned = aligned_size; + + /* After truncation : + * 1) Delayed allocation is OFF + * i_size = i_size_ondisk <= i_size_aligned + * (useless size var.) + * (block-aligned) + * 2) Delayed allocation is ON + * i_size = i_size_ondisk = i_size_aligned + * (will be block-aligned after write) + * or + * i_size_ondisk < i_size <= i_size_aligned (block_aligned) + * (will be block-aligned after write) + */ + + __unlock_super(sb); +} + +static const struct inode_operations sdfat_file_inode_operations = { + .setattr = sdfat_setattr, + .getattr = sdfat_getattr, +#ifdef CONFIG_SDFAT_VIRTUAL_XATTR + .listxattr = sdfat_listxattr, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) + .setxattr = sdfat_setxattr, + .getxattr = sdfat_getxattr, + .removexattr = sdfat_removexattr, +#endif +#endif +}; + +/*======================================================================*/ +/* Address Space Operations */ +/*======================================================================*/ +/* 2-level option flag */ +#define BMAP_NOT_CREATE 0 +#define BMAP_ADD_BLOCK 1 +#define BMAP_ADD_CLUSTER 2 +#define BLOCK_ADDED(bmap_ops) (bmap_ops) +static int sdfat_bmap(struct inode *inode, sector_t sector, sector_t *phys, + unsigned long *mapped_blocks, int *create) +{ + struct super_block *sb = inode->i_sb; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + FS_INFO_T *fsi = &(sbi->fsi); + const unsigned long blocksize = sb->s_blocksize; + const unsigned char blocksize_bits = sb->s_blocksize_bits; + sector_t last_block; + unsigned int cluster, clu_offset, sec_offset; + int err = 0; + + *phys = 0; + *mapped_blocks = 0; + + /* core code should handle EIO */ +#if 0 + if (fsi->prev_eio && BLOCK_ADDED(*create)) + return -EIO; +#endif + + if (((fsi->vol_type == FAT12) || (fsi->vol_type == FAT16)) && + (inode->i_ino == SDFAT_ROOT_INO)) { + if (sector < (fsi->dentries_in_root >> + (sb->s_blocksize_bits-DENTRY_SIZE_BITS))) { + *phys = sector + fsi->root_start_sector; + *mapped_blocks = 1; + } + return 0; + } + + last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits; + if ((sector >= last_block) && (*create == BMAP_NOT_CREATE)) + return 0; + + /* Is this block already allocated? */ + clu_offset = sector >> fsi->sect_per_clus_bits; /* cluster offset */ + + SDFAT_I(inode)->fid.size = i_size_read(inode); + + + if (unlikely(__check_dfr_on(inode, + (loff_t)((loff_t)clu_offset << fsi->cluster_size_bits), + (loff_t)((loff_t)(clu_offset + 1) << fsi->cluster_size_bits), + __func__))) { + err = __do_dfr_map_cluster(inode, clu_offset, &cluster); + } else { + if (*create & BMAP_ADD_CLUSTER) + err = fsapi_map_clus(inode, clu_offset, &cluster, 1); + else + err = fsapi_map_clus(inode, clu_offset, &cluster, ALLOC_NOWHERE); + } + + if (err) { + if (err != -ENOSPC) + return -EIO; + return err; + } + + /* FOR BIGDATA */ + sdfat_statistics_set_rw(SDFAT_I(inode)->fid.flags, + clu_offset, *create & BMAP_ADD_CLUSTER); + + if (!IS_CLUS_EOF(cluster)) { + /* sector offset in cluster */ + sec_offset = sector & (fsi->sect_per_clus - 1); + + *phys = CLUS_TO_SECT(fsi, cluster) + sec_offset; + *mapped_blocks = fsi->sect_per_clus - sec_offset; + } +#if 0 + else { + /* Debug purpose (new clu needed) */ + ASSERT((*create & BMAP_ADD_CLUSTER) == 0); + ASSERT(sector >= last_block); + } +#endif + + if (sector < last_block) + *create = BMAP_NOT_CREATE; +#if 0 + else if (sector >= last_block) + *create = non-zero; + + if (iblock <= last mapped-block) + *phys != 0 + *create = BMAP_NOT_CREATE + else if (iblock <= last cluster) + *phys != 0 + *create = non-zero +#endif + return 0; +} + +static int sdfat_da_prep_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) +{ + struct super_block *sb = inode->i_sb; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + FS_INFO_T *fsi = &(sbi->fsi); + unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; + unsigned long mapped_blocks; + sector_t phys; + loff_t pos; + int sec_offset; + int bmap_create = create ? BMAP_ADD_BLOCK : BMAP_NOT_CREATE; + int err = 0; + + __lock_super(sb); + + /* FAT32 only */ + ASSERT(fsi->vol_type == FAT32); + + err = sdfat_bmap(inode, iblock, &phys, &mapped_blocks, &bmap_create); + if (err) { + if (err != -ENOSPC) + sdfat_fs_error_ratelimit(sb, "%s: failed to bmap " + "(iblock:%u, err:%d)", __func__, + (u32)iblock, err); + goto unlock_ret; + } + + sec_offset = iblock & (fsi->sect_per_clus - 1); + + if (phys) { + /* the block in in the mapped cluster boundary */ + max_blocks = min(mapped_blocks, max_blocks); + map_bh(bh_result, sb, phys); + + BUG_ON(BLOCK_ADDED(bmap_create) && (sec_offset == 0)); + + } else if (create == 1) { + /* Not exist: new cluster needed */ + BUG_ON(!BLOCK_ADDED(bmap_create)); + + // Reserved Cluster (only if iblock is the first sector in a clu) + if (sec_offset == 0) { + err = fsapi_reserve_clus(inode); + if (err) { + if (err != -ENOSPC) + sdfat_fs_error_ratelimit(sb, + "%s: failed to bmap " + "(iblock:%u, err:%d)", __func__, + (u32)iblock, err); + + goto unlock_ret; + } + } + + // Delayed mapping + map_bh(bh_result, sb, ~((sector_t) 0xffff)); + set_buffer_new(bh_result); + set_buffer_delay(bh_result); + + } else { + /* get_block on non-existing addr. with create==0 */ + /* + * CHECKME: + * i_size_aligned 보다 작으면 delay ë§¤í•‘ì„ ì¼ë‹¨ + * 켜줘야ë˜ëŠ” 게 아닌가? + * - 0-fill ì„ í•­ìƒ í•˜ê¸°ì—, FAT ì—서는 문제 ì—†ìŒ. + * ì¤‘ê°„ì— ì˜ì—­ì´ 꽉 찼으면, 디스í¬ì— 내려가지 않고는 + * invalidate ë  ì¼ì´ ì—†ìŒ + */ + goto unlock_ret; + } + + + /* Newly added blocks */ + if (BLOCK_ADDED(bmap_create)) { + set_buffer_new(bh_result); + + SDFAT_I(inode)->i_size_aligned += max_blocks << sb->s_blocksize_bits; + if (phys) { + /* i_size_ondisk changes if a block added in the existing cluster */ + #define num_clusters(value) ((value) ? (s32)((value - 1) >> fsi->cluster_size_bits) + 1 : 0) + + /* FOR GRACEFUL ERROR HANDLING */ + if (num_clusters(SDFAT_I(inode)->i_size_aligned) != + num_clusters(SDFAT_I(inode)->i_size_ondisk)) { + EMSG("%s: inode(%p) invalid size (create(%d) " + "bmap_create(%d) phys(%lld) aligned(%lld) " + "on_disk(%lld) iblock(%u) sec_off(%d))\n", + __func__, inode, create, bmap_create, (s64)phys, + (s64)SDFAT_I(inode)->i_size_aligned, + (s64)SDFAT_I(inode)->i_size_ondisk, + (u32)iblock, + (s32)sec_offset); + sdfat_debug_bug_on(1); + } + SDFAT_I(inode)->i_size_ondisk = SDFAT_I(inode)->i_size_aligned; + } + + pos = (iblock + 1) << sb->s_blocksize_bits; + /* Debug purpose - defensive coding */ + ASSERT(SDFAT_I(inode)->i_size_aligned == pos); + if (SDFAT_I(inode)->i_size_aligned < pos) + SDFAT_I(inode)->i_size_aligned = pos; + /* Debug end */ + +#ifdef CONFIG_SDFAT_TRACE_IO + /* New page added (ASSERTION: 8 blocks per page) */ + if ((sec_offset & 7) == 0) + sbi->stat_n_pages_added++; +#endif + } + + /* FOR GRACEFUL ERROR HANDLING */ + if (i_size_read(inode) > SDFAT_I(inode)->i_size_aligned) { + sdfat_fs_error_ratelimit(sb, "%s: invalid size (inode(%p), " + "size(%llu) > aligned(%llu)\n", __func__, inode, + i_size_read(inode), SDFAT_I(inode)->i_size_aligned); + sdfat_debug_bug_on(1); + } + + bh_result->b_size = max_blocks << sb->s_blocksize_bits; + +unlock_ret: + __unlock_super(sb); + return err; +} + +static int sdfat_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) +{ + struct super_block *sb = inode->i_sb; + unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; + int err = 0; + unsigned long mapped_blocks; + sector_t phys; + loff_t pos; + int bmap_create = create ? BMAP_ADD_CLUSTER : BMAP_NOT_CREATE; + + __lock_super(sb); + err = sdfat_bmap(inode, iblock, &phys, &mapped_blocks, &bmap_create); + if (err) { + if (err != -ENOSPC) + sdfat_fs_error_ratelimit(sb, "%s: failed to bmap " + "(inode:%p iblock:%u, err:%d)", + __func__, inode, (u32)iblock, err); + goto unlock_ret; + } + + if (phys) { + max_blocks = min(mapped_blocks, max_blocks); + + /* Treat newly added block / cluster */ + if (BLOCK_ADDED(bmap_create) || buffer_delay(bh_result)) { + + /* Update i_size_ondisk */ + pos = (iblock + 1) << sb->s_blocksize_bits; + if (SDFAT_I(inode)->i_size_ondisk < pos) { + /* Debug purpose */ + if ((pos - SDFAT_I(inode)->i_size_ondisk) > bh_result->b_size) { + /* This never happens without DA */ + MMSG("Jumping get_block\n"); + } + + SDFAT_I(inode)->i_size_ondisk = pos; + sdfat_debug_check_clusters(inode); + } + + if (BLOCK_ADDED(bmap_create)) { + /* Old way (w/o DA) + * create == 1 only if iblock > i_size + * (in block unit) + */ + + /* 20130723 CHECK + * Truncate와 ë™ì‹œì— ë°œìƒí•  경우, + * i_size < (i_block 위치) 면서 buffer_delay()ê°€ + * ì¼œì ¸ìžˆì„ ìˆ˜ 있다. + * + * ê¸°ì¡´ì— í• ë‹¹ëœ ì˜ì—­ì„ 다시 쓸 ë¿ì´ë¯€ë¡œ í° ë¬¸ì œ + * 없지만, ê·¸ 경우, 미리 i_size_aligned ê°€ í™•ìž¥ëœ + * ì˜ì—­ì´ì–´ì•¼ 한다. + */ + + /* FOR GRACEFUL ERROR HANDLING */ + if (buffer_delay(bh_result) && + (pos > SDFAT_I(inode)->i_size_aligned)) { + sdfat_fs_error(sb, "requested for bmap " + "out of range(pos:(%llu)>i_size_aligned(%llu)\n", + pos, SDFAT_I(inode)->i_size_aligned); + sdfat_debug_bug_on(1); + err = -EIO; + goto unlock_ret; + } + set_buffer_new(bh_result); + + /* + * adjust i_size_aligned if i_size_ondisk is + * bigger than it. (i.e. non-DA) + */ + if (SDFAT_I(inode)->i_size_ondisk > + SDFAT_I(inode)->i_size_aligned) { + SDFAT_I(inode)->i_size_aligned = + SDFAT_I(inode)->i_size_ondisk; + } + } + + if (buffer_delay(bh_result)) + clear_buffer_delay(bh_result); + +#if 0 + /* Debug purpose */ + if (SDFAT_I(inode)->i_size_ondisk > + SDFAT_I(inode)->i_size_aligned) { + /* Only after truncate + * and the two size variables should indicate + * same i_block + */ + unsigned int blocksize = 1 << inode->i_blkbits; + BUG_ON(SDFAT_I(inode)->i_size_ondisk - + SDFAT_I(inode)->i_size_aligned >= blocksize); + } +#endif + } + map_bh(bh_result, sb, phys); + } + + bh_result->b_size = max_blocks << sb->s_blocksize_bits; +unlock_ret: + __unlock_super(sb); + return err; +} + +static int sdfat_readpage(struct file *file, struct page *page) +{ + int ret; + + ret = mpage_readpage(page, sdfat_get_block); + return ret; +} + +static int sdfat_readpages(struct file *file, struct address_space *mapping, + struct list_head *pages, unsigned int nr_pages) +{ + int ret; + + ret = mpage_readpages(mapping, pages, nr_pages, sdfat_get_block); + return ret; +} + +static inline void sdfat_submit_fullpage_bio(struct block_device *bdev, + sector_t sector, unsigned int length, struct page *page) +{ + /* Single page bio submit */ + struct bio *bio; + + BUG_ON((length > PAGE_SIZE) || (length == 0)); + + /* + * If __GFP_WAIT is set, then bio_alloc will always be able to allocate + * a bio. This is due to the mempool guarantees. To make this work, callers + * must never allocate more than 1 bio at a time from this pool. + * + * #define GFP_NOIO (__GFP_WAIT) + */ + bio = bio_alloc(GFP_NOIO, 1); + + bio->bi_bdev = bdev; + bio->bi_vcnt = 1; + bio->bi_io_vec[0].bv_page = page; /* Inline vec */ + bio->bi_io_vec[0].bv_len = length; /* PAGE_SIZE */ + bio->bi_io_vec[0].bv_offset = 0; + __sdfat_set_bio_iterate(bio, sector, length, 0, 0); + + bio->bi_end_io = sdfat_writepage_end_io; + __sdfat_submit_bio_write(bio); +} + +static int sdfat_writepage(struct page *page, struct writeback_control *wbc) +{ + struct inode * const inode = page->mapping->host; + struct super_block *sb = inode->i_sb; + loff_t i_size = i_size_read(inode); + const pgoff_t end_index = i_size >> PAGE_SHIFT; + const unsigned int blocks_per_page = PAGE_SIZE >> inode->i_blkbits; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + struct buffer_head *bh, *head; + sector_t block, block_0, last_phys; + int ret; + unsigned int nr_blocks_towrite = blocks_per_page; + + /* Don't distinguish 0-filled/clean block. + * Just write back the whole page + */ + if (fsi->cluster_size < PAGE_SIZE) + goto confused; + + if (!PageUptodate(page)) { + MMSG("%s: Not up-to-date page -> block_write_full_page\n", + __func__); + goto confused; + } + + if (page->index >= end_index) { + /* last page or outside i_size */ + unsigned int offset = i_size & (PAGE_SIZE-1); + + /* If a truncation is in progress */ + if (page->index > end_index || !offset) + goto confused; + + /* 0-fill after i_size */ + zero_user_segment(page, offset, PAGE_SIZE); + } + + if (!page_has_buffers(page)) { + MMSG("WP: No buffers -> block_write_full_page\n"); + goto confused; + } + + block = (sector_t)page->index << (PAGE_SHIFT - inode->i_blkbits); + block_0 = block; /* first block */ + head = page_buffers(page); + bh = head; + + last_phys = 0; + do { + BUG_ON(buffer_locked(bh)); + + if (!buffer_dirty(bh) || !buffer_uptodate(bh)) { + if (nr_blocks_towrite == blocks_per_page) + nr_blocks_towrite = (unsigned int) (block - block_0); + + BUG_ON(nr_blocks_towrite >= blocks_per_page); + + // !uptodate but dirty?? + if (buffer_dirty(bh)) + goto confused; + + // Nothing to writeback in this block + bh = bh->b_this_page; + block++; + continue; + } + + if (nr_blocks_towrite != blocks_per_page) + // Dirty -> Non-dirty -> Dirty again case + goto confused; + + /* Map if needed */ + if (!buffer_mapped(bh) || buffer_delay(bh)) { + BUG_ON(bh->b_size != (1 << (inode->i_blkbits))); + ret = sdfat_get_block(inode, block, bh, 1); + if (ret) + goto confused; + + if (buffer_new(bh)) { + clear_buffer_new(bh); + unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr); + } + } + + /* continuity check */ + if (((last_phys + 1) != bh->b_blocknr) && (last_phys != 0)) { + DMSG("Non-contiguous block mapping in single page"); + goto confused; + } + + last_phys = bh->b_blocknr; + bh = bh->b_this_page; + block++; + } while (bh != head); + + if (nr_blocks_towrite == 0) { + DMSG("Page dirty but no dirty bh? alloc_208\n"); + goto confused; + } + + + /* Write-back */ + do { + clear_buffer_dirty(bh); + bh = bh->b_this_page; + } while (bh != head); + + BUG_ON(PageWriteback(page)); + set_page_writeback(page); + + /** + * Turn off MAPPED flag in victim's bh if defrag on. + * Another write_begin can starts after get_block for defrag victims called. + * In this case, write_begin calls get_block and get original block number + * and previous defrag will be canceled. + */ + if (unlikely(__check_dfr_on(inode, + (loff_t)(page->index << PAGE_SHIFT), + (loff_t)((page->index + 1) << PAGE_SHIFT), + __func__))) { + do { + clear_buffer_mapped(bh); + bh = bh->b_this_page; + } while (bh != head); + } + + // Trace # of pages queued (Approx.) + atomic_inc(&SDFAT_SB(sb)->stat_n_pages_queued); + + sdfat_submit_fullpage_bio(head->b_bdev, + head->b_blocknr << (inode->i_blkbits - sb->s_blocksize_bits), + nr_blocks_towrite << inode->i_blkbits, + page); + + unlock_page(page); + + return 0; + +confused: +#ifdef CONFIG_SDFAT_TRACE_IO + SDFAT_SB(sb)->stat_n_pages_confused++; +#endif + ret = block_write_full_page(page, sdfat_get_block, wbc); + return ret; +} + +static int sdfat_da_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + MMSG("%s(inode:%p) with nr_to_write = 0x%08lx " + "(ku %d, bg %d, tag %d, rc %d )\n", + __func__, mapping->host, wbc->nr_to_write, + wbc->for_kupdate, wbc->for_background, wbc->tagged_writepages, + wbc->for_reclaim); + + ASSERT(mapping->a_ops == &sdfat_da_aops); + +#ifdef CONFIG_SDFAT_ALIGNED_MPAGE_WRITE + if (SDFAT_SB(mapping->host->i_sb)->options.adj_req) + return sdfat_mpage_writepages(mapping, wbc, sdfat_get_block); +#endif + return generic_writepages(mapping, wbc); +} + +static int sdfat_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + MMSG("%s(inode:%p) with nr_to_write = 0x%08lx " + "(ku %d, bg %d, tag %d, rc %d )\n", + __func__, mapping->host, wbc->nr_to_write, + wbc->for_kupdate, wbc->for_background, wbc->tagged_writepages, + wbc->for_reclaim); + + ASSERT(mapping->a_ops == &sdfat_aops); + +#ifdef CONFIG_SDFAT_ALIGNED_MPAGE_WRITE + if (SDFAT_SB(mapping->host->i_sb)->options.adj_req) + return sdfat_mpage_writepages(mapping, wbc, sdfat_get_block); +#endif + return mpage_writepages(mapping, wbc, sdfat_get_block); +} + +static void sdfat_write_failed(struct address_space *mapping, loff_t to) +{ + struct inode *inode = mapping->host; + + if (to > i_size_read(inode)) { + __sdfat_truncate_pagecache(inode, to, i_size_read(inode)); + sdfat_truncate(inode, SDFAT_I(inode)->i_size_aligned); + } +} + +static int __sdfat_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned int len, + unsigned int flags, struct page **pagep, + void **fsdata, get_block_t *get_block, + loff_t *bytes, const char *fname) +{ + int ret; + + __cancel_dfr_work(mapping->host, pos, (loff_t)(pos + len), fname); + + *pagep = NULL; + ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + get_block, bytes); + + if (ret < 0) + sdfat_write_failed(mapping, pos+len); + + return ret; +} + + +static int sdfat_da_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned int len, unsigned int flags, + struct page **pagep, void **fsdata) +{ + return __sdfat_write_begin(file, mapping, pos, len, flags, + pagep, fsdata, sdfat_da_prep_block, + &SDFAT_I(mapping->host)->i_size_aligned, + __func__); +} + + +static int sdfat_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned int len, unsigned int flags, + struct page **pagep, void **fsdata) +{ + return __sdfat_write_begin(file, mapping, pos, len, flags, + pagep, fsdata, sdfat_get_block, + &SDFAT_I(mapping->host)->i_size_ondisk, + __func__); +} + +static int sdfat_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned int len, unsigned int copied, + struct page *pagep, void *fsdata) +{ + struct inode *inode = mapping->host; + FILE_ID_T *fid = &(SDFAT_I(inode)->fid); + int err; + + err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); + + /* FOR GRACEFUL ERROR HANDLING */ + if (SDFAT_I(inode)->i_size_aligned < i_size_read(inode)) { + sdfat_fs_error(inode->i_sb, "invalid size(size(%llu) " + "> aligned(%llu)\n", i_size_read(inode), + SDFAT_I(inode)->i_size_aligned); + sdfat_debug_bug_on(1); + } + + if (err < len) + sdfat_write_failed(mapping, pos+len); + + if (!(err < 0) && !(fid->attr & ATTR_ARCHIVE)) { + inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; + fid->attr |= ATTR_ARCHIVE; + mark_inode_dirty(inode); + } + + return err; +} + +static inline ssize_t __sdfat_direct_IO(int rw, struct kiocb *iocb, + struct inode *inode, void *iov_u, loff_t offset, + loff_t count, unsigned long nr_segs) +{ + struct address_space *mapping = inode->i_mapping; + loff_t size = offset + count; + ssize_t ret; + + if (rw == WRITE) { + /* + * FIXME: blockdev_direct_IO() doesn't use ->write_begin(), + * so we need to update the ->i_size_aligned to block boundary. + * + * But we must fill the remaining area or hole by nul for + * updating ->i_size_aligned + * + * Return 0, and fallback to normal buffered write. + */ + if (SDFAT_I(inode)->i_size_aligned < size) + return 0; + } + + /* + * sdFAT need to use the DIO_LOCKING for avoiding the race + * condition of sdfat_get_block() and ->truncate(). + */ + ret = __sdfat_blkdev_direct_IO(rw, iocb, inode, iov_u, offset, nr_segs); + if (ret < 0 && (rw & WRITE)) + sdfat_write_failed(mapping, size); + + return ret; +} + +static const struct address_space_operations sdfat_aops = { + .readpage = sdfat_readpage, + .readpages = sdfat_readpages, + .writepage = sdfat_writepage, + .writepages = sdfat_writepages, + .write_begin = sdfat_write_begin, + .write_end = sdfat_write_end, + .direct_IO = sdfat_direct_IO, + .bmap = sdfat_aop_bmap +}; + +static const struct address_space_operations sdfat_da_aops = { + .readpage = sdfat_readpage, + .readpages = sdfat_readpages, + .writepage = sdfat_writepage, + .writepages = sdfat_da_writepages, + .write_begin = sdfat_da_write_begin, + .write_end = sdfat_write_end, + .direct_IO = sdfat_direct_IO, + .bmap = sdfat_aop_bmap +}; + +/*======================================================================*/ +/* Super Operations */ +/*======================================================================*/ + +static inline unsigned long sdfat_hash(loff_t i_pos) +{ + return hash_32(i_pos, SDFAT_HASH_BITS); +} + +static void sdfat_attach(struct inode *inode, loff_t i_pos) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(inode->i_sb); + struct hlist_head *head = sbi->inode_hashtable + sdfat_hash(i_pos); + + spin_lock(&sbi->inode_hash_lock); + SDFAT_I(inode)->i_pos = i_pos; + hlist_add_head(&SDFAT_I(inode)->i_hash_fat, head); + spin_unlock(&sbi->inode_hash_lock); +} + +static void sdfat_detach(struct inode *inode) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(inode->i_sb); + + spin_lock(&sbi->inode_hash_lock); + hlist_del_init(&SDFAT_I(inode)->i_hash_fat); + SDFAT_I(inode)->i_pos = 0; + spin_unlock(&sbi->inode_hash_lock); +} + + +/* doesn't deal with root inode */ +static int sdfat_fill_inode(struct inode *inode, const FILE_ID_T *fid) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(inode->i_sb); + FS_INFO_T *fsi = &(sbi->fsi); + DIR_ENTRY_T info; + u64 size = fid->size; + + memcpy(&(SDFAT_I(inode)->fid), fid, sizeof(FILE_ID_T)); + + SDFAT_I(inode)->i_pos = 0; + SDFAT_I(inode)->target = NULL; + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; + inode->i_version++; + inode->i_generation = get_seconds(); + + if (fsapi_read_inode(inode, &info) < 0) { + MMSG("%s: failed to read stat!\n", __func__); + return -EIO; + } + + if (info.Attr & ATTR_SUBDIR) { /* directory */ + inode->i_generation &= ~1; + inode->i_mode = sdfat_make_mode(sbi, info.Attr, S_IRWXUGO); + inode->i_op = &sdfat_dir_inode_operations; + inode->i_fop = &sdfat_dir_operations; + + set_nlink(inode, info.NumSubdirs); + } else if (info.Attr & ATTR_SYMLINK) { /* symbolic link */ + inode->i_op = &sdfat_symlink_inode_operations; + inode->i_generation |= 1; + inode->i_mode = sdfat_make_mode(sbi, info.Attr, S_IRWXUGO); + } else { /* regular file */ + inode->i_generation |= 1; + inode->i_mode = sdfat_make_mode(sbi, info.Attr, S_IRWXUGO); + inode->i_op = &sdfat_file_inode_operations; + inode->i_fop = &sdfat_file_operations; + + if (sbi->options.improved_allocation & SDFAT_ALLOC_DELAY) + inode->i_mapping->a_ops = &sdfat_da_aops; + else + inode->i_mapping->a_ops = &sdfat_aops; + + inode->i_mapping->nrpages = 0; + + } + + /* + * Use fid->size instead of info.Size + * because info.Size means the value saved on disk + */ + i_size_write(inode, size); + + /* ondisk and aligned size should be aligned with block size */ + if (size & (inode->i_sb->s_blocksize - 1)) { + size |= (inode->i_sb->s_blocksize - 1); + size++; + } + + SDFAT_I(inode)->i_size_aligned = size; + SDFAT_I(inode)->i_size_ondisk = size; + sdfat_debug_check_clusters(inode); + + sdfat_save_attr(inode, info.Attr); + + inode->i_blocks = ((i_size_read(inode) + (fsi->cluster_size - 1)) + & ~((loff_t)fsi->cluster_size - 1)) >> inode->i_blkbits; + + sdfat_time_fat2unix(sbi, &inode->i_mtime, &info.ModifyTimestamp); + sdfat_time_fat2unix(sbi, &inode->i_ctime, &info.CreateTimestamp); + sdfat_time_fat2unix(sbi, &inode->i_atime, &info.AccessTimestamp); + + __init_dfr_info(inode); + + return 0; +} + +static struct inode *sdfat_build_inode(struct super_block *sb, + const FILE_ID_T *fid, loff_t i_pos) { + struct inode *inode; + int err; + + inode = sdfat_iget(sb, i_pos); + if (inode) + goto out; + inode = new_inode(sb); + if (!inode) { + inode = ERR_PTR(-ENOMEM); + goto out; + } + inode->i_ino = iunique(sb, SDFAT_ROOT_INO); + inode->i_version = 1; + err = sdfat_fill_inode(inode, fid); + if (err) { + iput(inode); + inode = ERR_PTR(err); + goto out; + } + sdfat_attach(inode, i_pos); + insert_inode_hash(inode); +out: + return inode; +} + +static struct inode *sdfat_alloc_inode(struct super_block *sb) +{ + struct sdfat_inode_info *ei; + + ei = kmem_cache_alloc(sdfat_inode_cachep, GFP_NOFS); + if (!ei) + return NULL; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) + init_rwsem(&ei->truncate_lock); +#endif + return &ei->vfs_inode; +} + +static void sdfat_destroy_inode(struct inode *inode) +{ + if (SDFAT_I(inode)->target) { + kfree(SDFAT_I(inode)->target); + SDFAT_I(inode)->target = NULL; + } + + kmem_cache_free(sdfat_inode_cachep, SDFAT_I(inode)); +} + +static int __sdfat_write_inode(struct inode *inode, int sync) +{ + struct super_block *sb = inode->i_sb; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + DIR_ENTRY_T info; + + if (inode->i_ino == SDFAT_ROOT_INO) + return 0; + + info.Attr = sdfat_make_attr(inode); + info.Size = i_size_read(inode); + + sdfat_time_unix2fat(sbi, &inode->i_mtime, &info.ModifyTimestamp); + sdfat_time_unix2fat(sbi, &inode->i_ctime, &info.CreateTimestamp); + sdfat_time_unix2fat(sbi, &inode->i_atime, &info.AccessTimestamp); + + if (!__support_write_inode_sync(sb)) + sync = 0; + + /* FIXME : Do we need handling error? */ + return fsapi_write_inode(inode, &info, sync); +} + +static int sdfat_sync_inode(struct inode *inode) +{ + return __sdfat_write_inode(inode, 1); +} + +static int sdfat_write_inode(struct inode *inode, struct writeback_control *wbc) +{ + return __sdfat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); +} + +static void sdfat_evict_inode(struct inode *inode) +{ + truncate_inode_pages(&inode->i_data, 0); + + if (!inode->i_nlink) { + loff_t old_size = i_size_read(inode); + + i_size_write(inode, 0); + + SDFAT_I(inode)->fid.size = old_size; + + __cancel_dfr_work(inode, 0, (loff_t)old_size, __func__); + + /* TO CHECK evicting directory works correctly */ + MMSG("%s: inode(%p) evict %s (size(%llu) to zero)\n", + __func__, inode, + S_ISDIR(inode->i_mode) ? "directory" : "file", + (u64)old_size); + fsapi_truncate(inode, old_size, 0); + } + + invalidate_inode_buffers(inode); + clear_inode(inode); + fsapi_invalidate_extent(inode); + sdfat_detach(inode); + + /* after end of this function, caller will remove inode hash */ + /* remove_inode_hash(inode); */ +} + + + +static void sdfat_put_super(struct super_block *sb) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + int err; + + sdfat_log_msg(sb, KERN_INFO, "trying to unmount..."); + + __cancel_delayed_work_sync(sbi); + + if (__is_sb_dirty(sb)) + sdfat_write_super(sb); + + __free_dfr_mem_if_required(sb); + err = fsapi_umount(sb); + + if (sbi->nls_disk) { + unload_nls(sbi->nls_disk); + sbi->nls_disk = NULL; + sbi->options.codepage = sdfat_default_codepage; + } + if (sbi->nls_io) { + unload_nls(sbi->nls_io); + sbi->nls_io = NULL; + } + if (sbi->options.iocharset != sdfat_default_iocharset) { + kfree(sbi->options.iocharset); + sbi->options.iocharset = sdfat_default_iocharset; + } + + sb->s_fs_info = NULL; + + kobject_del(&sbi->sb_kobj); + kobject_put(&sbi->sb_kobj); + if (!sbi->use_vmalloc) + kfree(sbi); + else + vfree(sbi); + + sdfat_log_msg(sb, KERN_INFO, "unmounted successfully! %s", + err ? "(with previous I/O errors)" : ""); +} + +static inline void __flush_delayed_meta(struct super_block *sb, s32 sync) +{ +#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY + fsapi_cache_flush(sb, sync); +#else + /* DO NOTHING */ +#endif +} + +static void sdfat_write_super(struct super_block *sb) +{ + int time = 0; + + __lock_super(sb); + + __set_sb_clean(sb); + +#ifdef CONFIG_SDFAT_DFR + if (atomic_read(&(SDFAT_SB(sb)->dfr_info.stat)) == DFR_SB_STAT_VALID) + fsapi_dfr_update_fat_next(sb); +#endif + + /* flush delayed FAT/DIR dirty */ + __flush_delayed_meta(sb, 0); + + if (!(sb->s_flags & MS_RDONLY)) + fsapi_sync_fs(sb, 0); + + __unlock_super(sb); + + time = jiffies; + + /* Issuing bdev requests is needed + * to guarantee DIR updates in time + * whether w/ or w/o delayed DIR dirty feature. + * (otherwise DIR updates could be delayed for 5 + 5 secs at max.) + */ + sync_blockdev(sb->s_bdev); + +#if (defined(CONFIG_SDFAT_DFR) && defined(CONFIG_SDFAT_DFR_DEBUG)) + /* SPO test */ + fsapi_dfr_spo_test(sb, DFR_SPO_FAT_NEXT, __func__); +#endif + MMSG("BD: sdfat_write_super (bdev_sync for %ld ms)\n", + (jiffies - time) * 1000 / HZ); +} + + +static void __dfr_update_fat_next(struct super_block *sb) +{ +#ifdef CONFIG_SDFAT_DFR + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + + if (sbi->options.defrag && + (atomic_read(&sbi->dfr_info.stat) == DFR_SB_STAT_VALID)) { + fsapi_dfr_update_fat_next(sb); + } +#endif +} + +static void __dfr_update_fat_prev(struct super_block *sb, int wait) +{ +#ifdef CONFIG_SDFAT_DFR + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + struct defrag_info *sb_dfr = &sbi->dfr_info; + /* static time available? */ + static int time; /* initialized by zero */ + int uevent = 0, total = 0, clean = 0, full = 0; + int spent = jiffies - time; + + if (!(sbi->options.defrag && wait)) + return; + + __lock_super(sb); + /* Update FAT for defrag */ + if (atomic_read(&(sbi->dfr_info.stat)) == DFR_SB_STAT_VALID) { + + fsapi_dfr_update_fat_prev(sb, 0); + + /* flush delayed FAT/DIR dirty */ + __flush_delayed_meta(sb, 0); + + /* Complete defrag req */ + fsapi_sync_fs(sb, 1); + atomic_set(&sb_dfr->stat, DFR_SB_STAT_REQ); + complete_all(&sbi->dfr_complete); + } else if (((spent < 0) || (spent > DFR_DEFAULT_TIMEOUT)) && + (atomic_read(&(sbi->dfr_info.stat)) == DFR_SB_STAT_IDLE)) { + uevent = fsapi_dfr_check_dfr_required(sb, &total, &clean, &full); + time = jiffies; + } + __unlock_super(sb); + + if (uevent) { + kobject_uevent(&SDFAT_SB(sb)->sb_kobj, KOBJ_CHANGE); + dfr_debug("uevent for defrag_daemon, total_au %d, " + "clean_au %d, full_au %d", total, clean, full); + } +#endif +} + +static int sdfat_sync_fs(struct super_block *sb, int wait) +{ + int err = 0; + + /* If there are some dirty buffers in the bdev inode */ + if (__is_sb_dirty(sb)) { + __lock_super(sb); + __set_sb_clean(sb); + + __dfr_update_fat_next(sb); + + err = fsapi_sync_fs(sb, 1); + +#if (defined(CONFIG_SDFAT_DFR) && defined(CONFIG_SDFAT_DFR_DEBUG)) + /* SPO test */ + fsapi_dfr_spo_test(sb, DFR_SPO_FAT_NEXT, __func__); +#endif + + __unlock_super(sb); + } + + __dfr_update_fat_prev(sb, wait); + + return err; +} + +static int sdfat_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + /* + * patch 1.2.2 : + * fixed the slow-call problem because of volume-lock contention. + */ + struct super_block *sb = dentry->d_sb; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + VOL_INFO_T info; + + /* fsapi_statfs will try to get a volume lock if needed */ + if (fsapi_statfs(sb, &info)) + return -EIO; + + if (fsi->prev_eio) + sdfat_msg(sb, KERN_INFO, "called statfs with previous" + " I/O error(0x%02X).", fsi->prev_eio); + + buf->f_type = sb->s_magic; + buf->f_bsize = info.ClusterSize; + buf->f_blocks = info.NumClusters; + buf->f_bfree = info.FreeClusters; + buf->f_bavail = info.FreeClusters; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); + buf->f_namelen = 260; + + return 0; +} + +static int sdfat_remount(struct super_block *sb, int *flags, char *data) +{ + unsigned long prev_sb_flags; + char *orig_data = kstrdup(data, GFP_KERNEL); + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + FS_INFO_T *fsi = &(sbi->fsi); + + *flags |= MS_NODIRATIME; + + prev_sb_flags = sb->s_flags; + + sdfat_remount_syncfs(sb); + + fsapi_set_vol_flags(sb, VOL_CLEAN, 1); + + sdfat_log_msg(sb, KERN_INFO, "re-mounted(%s->%s), eio=0x%x, Opts: %s", + (prev_sb_flags & MS_RDONLY) ? "ro" : "rw", + (*flags & MS_RDONLY) ? "ro" : "rw", + fsi->prev_eio, orig_data); + kfree(orig_data); + return 0; +} + +static int __sdfat_show_options(struct seq_file *m, struct super_block *sb) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + struct sdfat_mount_options *opts = &sbi->options; + FS_INFO_T *fsi = &(sbi->fsi); + + /* Show partition info */ + seq_printf(m, ",fs=%s", sdfat_get_vol_type_str(fsi->vol_type)); + if (fsi->prev_eio) + seq_printf(m, ",eio=0x%x", fsi->prev_eio); + if (!uid_eq(opts->fs_uid, GLOBAL_ROOT_UID)) + seq_printf(m, ",uid=%u", + from_kuid_munged(&init_user_ns, opts->fs_uid)); + if (!gid_eq(opts->fs_gid, GLOBAL_ROOT_GID)) + seq_printf(m, ",gid=%u", + from_kgid_munged(&init_user_ns, opts->fs_gid)); + seq_printf(m, ",fmask=%04o", opts->fs_fmask); + seq_printf(m, ",dmask=%04o", opts->fs_dmask); + if (opts->allow_utime) + seq_printf(m, ",allow_utime=%04o", opts->allow_utime); + if (sbi->nls_disk) + seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); + if (sbi->nls_io) + seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); + if (opts->utf8) + seq_puts(m, ",utf8"); + if (sbi->fsi.vol_type != EXFAT) + seq_puts(m, ",shortname=winnt"); + seq_printf(m, ",namecase=%u", opts->casesensitive); + if (opts->tz_utc) + seq_puts(m, ",tz=UTC"); + if (opts->improved_allocation & SDFAT_ALLOC_DELAY) + seq_puts(m, ",delay"); + if (opts->improved_allocation & SDFAT_ALLOC_SMART) + seq_printf(m, ",smart,ausize=%u", opts->amap_opt.sect_per_au); + if (opts->defrag) + seq_puts(m, ",defrag"); + if (opts->adj_hidsect) + seq_puts(m, ",adj_hid"); + if (opts->adj_req) + seq_puts(m, ",adj_req"); + seq_printf(m, ",symlink=%u", opts->symlink); + seq_printf(m, ",bps=%ld", sb->s_blocksize); + if (opts->errors == SDFAT_ERRORS_CONT) + seq_puts(m, ",errors=continue"); + else if (opts->errors == SDFAT_ERRORS_PANIC) + seq_puts(m, ",errors=panic"); + else + seq_puts(m, ",errors=remount-ro"); + if (opts->discard) + seq_puts(m, ",discard"); + + return 0; +} + +static const struct super_operations sdfat_sops = { + .alloc_inode = sdfat_alloc_inode, + .destroy_inode = sdfat_destroy_inode, + .write_inode = sdfat_write_inode, + .evict_inode = sdfat_evict_inode, + .put_super = sdfat_put_super, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) + .write_super = sdfat_write_super, +#endif + .sync_fs = sdfat_sync_fs, + .statfs = sdfat_statfs, + .remount_fs = sdfat_remount, + .show_options = sdfat_show_options, +}; + +/*======================================================================*/ +/* SYSFS Operations */ +/*======================================================================*/ +#define SDFAT_ATTR(name, mode, show, store) \ +static struct sdfat_attr sdfat_attr_##name = __ATTR(name, mode, show, store) + +struct sdfat_attr { + struct attribute attr; + ssize_t (*show)(struct sdfat_sb_info *, char *); + ssize_t (*store)(struct sdfat_sb_info *, const char *, size_t); +}; + +static ssize_t sdfat_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + struct sdfat_sb_info *sbi = container_of(kobj, struct sdfat_sb_info, sb_kobj); + struct sdfat_attr *a = container_of(attr, struct sdfat_attr, attr); + + return a->show ? a->show(sbi, buf) : 0; +} + +static ssize_t sdfat_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t len) +{ + struct sdfat_sb_info *sbi = container_of(kobj, struct sdfat_sb_info, sb_kobj); + struct sdfat_attr *a = container_of(attr, struct sdfat_attr, attr); + + return a->store ? a->store(sbi, buf, len) : len; +} + +static const struct sysfs_ops sdfat_attr_ops = { + .show = sdfat_attr_show, + .store = sdfat_attr_store, +}; + + +static ssize_t type_show(struct sdfat_sb_info *sbi, char *buf) +{ + FS_INFO_T *fsi = &(sbi->fsi); + + return snprintf(buf, PAGE_SIZE, "%s\n", sdfat_get_vol_type_str(fsi->vol_type)); +} +SDFAT_ATTR(type, 0444, type_show, NULL); + +static ssize_t eio_show(struct sdfat_sb_info *sbi, char *buf) +{ + FS_INFO_T *fsi = &(sbi->fsi); + + return snprintf(buf, PAGE_SIZE, "0x%x\n", fsi->prev_eio); +} +SDFAT_ATTR(eio, 0444, eio_show, NULL); + +static ssize_t fratio_show(struct sdfat_sb_info *sbi, char *buf) +{ + unsigned int n_total_au = 0; + unsigned int n_clean_au = 0; + unsigned int n_full_au = 0; + unsigned int n_dirty_au = 0; + unsigned int fr = 0; + + n_total_au = fsapi_get_au_stat(sbi->host_sb, VOL_AU_STAT_TOTAL); + n_clean_au = fsapi_get_au_stat(sbi->host_sb, VOL_AU_STAT_CLEAN); + n_full_au = fsapi_get_au_stat(sbi->host_sb, VOL_AU_STAT_FULL); + n_dirty_au = n_total_au - (n_full_au + n_clean_au); + + if (!n_dirty_au) + fr = 0; + else if (!n_clean_au) + fr = 100; + else + fr = (n_dirty_au * 100) / (n_clean_au + n_dirty_au); + + return snprintf(buf, PAGE_SIZE, "%u\n", fr); +} +SDFAT_ATTR(fratio, 0444, fratio_show, NULL); + +static ssize_t totalau_show(struct sdfat_sb_info *sbi, char *buf) +{ + unsigned int n_au = 0; + + n_au = fsapi_get_au_stat(sbi->host_sb, VOL_AU_STAT_TOTAL); + return snprintf(buf, PAGE_SIZE, "%u\n", n_au); +} +SDFAT_ATTR(totalau, 0444, totalau_show, NULL); + +static ssize_t cleanau_show(struct sdfat_sb_info *sbi, char *buf) +{ + unsigned int n_clean_au = 0; + + n_clean_au = fsapi_get_au_stat(sbi->host_sb, VOL_AU_STAT_CLEAN); + return snprintf(buf, PAGE_SIZE, "%u\n", n_clean_au); +} +SDFAT_ATTR(cleanau, 0444, cleanau_show, NULL); + +static ssize_t fullau_show(struct sdfat_sb_info *sbi, char *buf) +{ + unsigned int n_full_au = 0; + + n_full_au = fsapi_get_au_stat(sbi->host_sb, VOL_AU_STAT_FULL); + return snprintf(buf, PAGE_SIZE, "%u\n", n_full_au); +} +SDFAT_ATTR(fullau, 0444, fullau_show, NULL); + +static struct attribute *sdfat_attrs[] = { + &sdfat_attr_type.attr, + &sdfat_attr_eio.attr, + &sdfat_attr_fratio.attr, + &sdfat_attr_totalau.attr, + &sdfat_attr_cleanau.attr, + &sdfat_attr_fullau.attr, + NULL, +}; + +static struct kobj_type sdfat_ktype = { + .default_attrs = sdfat_attrs, + .sysfs_ops = &sdfat_attr_ops, +}; + +static ssize_t version_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buff) +{ + return snprintf(buff, PAGE_SIZE, "FS Version %s\n", SDFAT_VERSION); +} + +static struct kobj_attribute version_attr = __ATTR_RO(version); + +static struct attribute *attributes[] = { + &version_attr.attr, + NULL, +}; + +static struct attribute_group attr_group = { + .attrs = attributes, +}; + +/*======================================================================*/ +/* Super Block Read Operations */ +/*======================================================================*/ + +enum { + Opt_uid, + Opt_gid, + Opt_umask, + Opt_dmask, + Opt_fmask, + Opt_allow_utime, + Opt_codepage, + Opt_charset, + Opt_utf8, + Opt_namecase, + Opt_tz_utc, + Opt_adj_hidsect, + Opt_delay, + Opt_smart, + Opt_ausize, + Opt_packing, + Opt_defrag, + Opt_symlink, + Opt_debug, + Opt_err_cont, + Opt_err_panic, + Opt_err_ro, + Opt_err, + Opt_discard, + Opt_fs, + Opt_adj_req, +}; + +static const match_table_t sdfat_tokens = { + {Opt_uid, "uid=%u"}, + {Opt_gid, "gid=%u"}, + {Opt_umask, "umask=%o"}, + {Opt_dmask, "dmask=%o"}, + {Opt_fmask, "fmask=%o"}, + {Opt_allow_utime, "allow_utime=%o"}, + {Opt_codepage, "codepage=%u"}, + {Opt_charset, "iocharset=%s"}, + {Opt_utf8, "utf8"}, + {Opt_namecase, "namecase=%u"}, + {Opt_tz_utc, "tz=UTC"}, + {Opt_adj_hidsect, "adj_hid"}, + {Opt_delay, "delay"}, + {Opt_smart, "smart"}, + {Opt_ausize, "ausize=%u"}, + {Opt_packing, "packing=%u"}, + {Opt_defrag, "defrag"}, + {Opt_symlink, "symlink=%u"}, + {Opt_debug, "debug"}, + {Opt_err_cont, "errors=continue"}, + {Opt_err_panic, "errors=panic"}, + {Opt_err_ro, "errors=remount-ro"}, + {Opt_discard, "discard"}, + {Opt_fs, "fs=%s"}, + {Opt_adj_req, "adj_req"}, + {Opt_err, NULL} +}; + +static int parse_options(struct super_block *sb, char *options, int silent, + int *debug, struct sdfat_mount_options *opts) +{ + char *p; + substring_t args[MAX_OPT_ARGS]; + int option, i; + char *tmpstr; + + opts->fs_uid = current_uid(); + opts->fs_gid = current_gid(); + opts->fs_fmask = opts->fs_dmask = current->fs->umask; + opts->allow_utime = (unsigned short) -1; + opts->codepage = sdfat_default_codepage; + opts->iocharset = sdfat_default_iocharset; + opts->casesensitive = 0; + opts->utf8 = 0; + opts->adj_hidsect = 0; + opts->tz_utc = 0; + opts->improved_allocation = 0; + opts->amap_opt.pack_ratio = 0; // Default packing + opts->amap_opt.sect_per_au = 0; + opts->amap_opt.misaligned_sect = 0; + opts->symlink = 0; + opts->errors = SDFAT_ERRORS_RO; + opts->discard = 0; + *debug = 0; + + if (!options) + goto out; + + while ((p = strsep(&options, ",")) != NULL) { + int token; + + if (!*p) + continue; + token = match_token(p, sdfat_tokens, args); + switch (token) { + case Opt_uid: + if (match_int(&args[0], &option)) + return 0; + opts->fs_uid = make_kuid(current_user_ns(), option); + break; + case Opt_gid: + if (match_int(&args[0], &option)) + return 0; + opts->fs_gid = make_kgid(current_user_ns(), option); + break; + case Opt_umask: + case Opt_dmask: + case Opt_fmask: + if (match_octal(&args[0], &option)) + return 0; + if (token != Opt_dmask) + opts->fs_fmask = option; + if (token != Opt_fmask) + opts->fs_dmask = option; + break; + case Opt_allow_utime: + if (match_octal(&args[0], &option)) + return 0; + opts->allow_utime = option & (S_IWGRP | S_IWOTH); + break; + case Opt_codepage: + if (match_int(&args[0], &option)) + return 0; + opts->codepage = option; + break; + case Opt_charset: + if (opts->iocharset != sdfat_default_iocharset) + kfree(opts->iocharset); + tmpstr = match_strdup(&args[0]); + if (!tmpstr) + return -ENOMEM; + opts->iocharset = tmpstr; + break; + case Opt_namecase: + if (match_int(&args[0], &option)) + return 0; + opts->casesensitive = (option > 0) ? 1:0; + break; + case Opt_utf8: + opts->utf8 = 1; + break; + case Opt_adj_hidsect: + opts->adj_hidsect = 1; + break; + case Opt_tz_utc: + opts->tz_utc = 1; + break; + case Opt_symlink: + if (match_int(&args[0], &option)) + return 0; + opts->symlink = option > 0 ? 1 : 0; + break; + case Opt_delay: + opts->improved_allocation |= SDFAT_ALLOC_DELAY; + break; + case Opt_smart: + opts->improved_allocation |= SDFAT_ALLOC_SMART; + break; + case Opt_ausize: + if (match_int(&args[0], &option)) + return -EINVAL; + if (!is_power_of_2(option)) + return -EINVAL; + opts->amap_opt.sect_per_au = option; + IMSG("set AU size by option : %u sectors\n", option); + break; + case Opt_packing: + if (match_int(&args[0], &option)) + return 0; + opts->amap_opt.pack_ratio = option; + break; + case Opt_defrag: +#ifdef CONFIG_SDFAT_DFR + opts->defrag = 1; +#else + IMSG("defragmentation config is not enabled. ignore\n"); +#endif + break; + case Opt_err_cont: + opts->errors = SDFAT_ERRORS_CONT; + break; + case Opt_err_panic: + opts->errors = SDFAT_ERRORS_PANIC; + break; + case Opt_err_ro: + opts->errors = SDFAT_ERRORS_RO; + break; + case Opt_debug: + *debug = 1; + break; + case Opt_discard: + opts->discard = 1; + break; + case Opt_fs: + tmpstr = match_strdup(&args[0]); + if (!tmpstr) + return -ENOMEM; + for (i = 0; i < FS_TYPE_MAX; i++) { + if (!strcmp(tmpstr, FS_TYPE_STR[i])) { + opts->fs_type = (unsigned char)i; + sdfat_log_msg(sb, KERN_ERR, + "set fs-type by option : %s", + FS_TYPE_STR[i]); + break; + } + } + kfree(tmpstr); + if (i == FS_TYPE_MAX) { + sdfat_log_msg(sb, KERN_ERR, + "invalid fs-type, " + "only allow auto, exfat, vfat"); + return -EINVAL; + } + break; + case Opt_adj_req: +#ifdef CONFIG_SDFAT_ALIGNED_MPAGE_WRITE + opts->adj_req = 1; +#else + IMSG("adjust request config is not enabled. ignore\n"); +#endif + break; + default: + if (!silent) { + sdfat_msg(sb, KERN_ERR, + "unrecognized mount option \"%s\" " + "or missing value", p); + } + return -EINVAL; + } + } + +out: + if (opts->allow_utime == (unsigned short) -1) + opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH); + + if (opts->utf8 && strcmp(opts->iocharset, sdfat_iocharset_with_utf8)) { + sdfat_msg(sb, KERN_WARNING, + "utf8 enabled, \"iocharset=%s\" is recommended", + sdfat_iocharset_with_utf8); + } + + if (opts->discard) { + struct request_queue *q = bdev_get_queue(sb->s_bdev); + + if (!blk_queue_discard(q)) + sdfat_msg(sb, KERN_WARNING, + "mounting with \"discard\" option, but " + "the device does not support discard"); + opts->discard = 0; + } + + return 0; +} + +static void sdfat_hash_init(struct super_block *sb) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + int i; + + spin_lock_init(&sbi->inode_hash_lock); + for (i = 0; i < SDFAT_HASH_SIZE; i++) + INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); +} + +static int sdfat_read_root(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + struct timespec ts; + FS_INFO_T *fsi = &(sbi->fsi); + DIR_ENTRY_T info; + + ts = CURRENT_TIME_SEC; + + SDFAT_I(inode)->fid.dir.dir = fsi->root_dir; + SDFAT_I(inode)->fid.dir.flags = 0x01; + SDFAT_I(inode)->fid.entry = -1; + SDFAT_I(inode)->fid.start_clu = fsi->root_dir; + SDFAT_I(inode)->fid.flags = 0x01; + SDFAT_I(inode)->fid.type = TYPE_DIR; + SDFAT_I(inode)->fid.version = 0; + SDFAT_I(inode)->fid.rwoffset = 0; + SDFAT_I(inode)->fid.hint_bmap.off = -1; + SDFAT_I(inode)->fid.hint_stat.eidx = 0; + SDFAT_I(inode)->fid.hint_stat.clu = fsi->root_dir; + SDFAT_I(inode)->fid.hint_femp.eidx = -1; + + SDFAT_I(inode)->target = NULL; + + if (fsapi_read_inode(inode, &info) < 0) + return -EIO; + + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; + inode->i_version++; + inode->i_generation = 0; + inode->i_mode = sdfat_make_mode(sbi, ATTR_SUBDIR, S_IRWXUGO); + inode->i_op = &sdfat_dir_inode_operations; + inode->i_fop = &sdfat_dir_operations; + + i_size_write(inode, info.Size); + SDFAT_I(inode)->fid.size = info.Size; + inode->i_blocks = ((i_size_read(inode) + (fsi->cluster_size - 1)) + & ~((loff_t)fsi->cluster_size - 1)) >> inode->i_blkbits; + SDFAT_I(inode)->i_pos = ((loff_t) fsi->root_dir << 32) | 0xffffffff; + SDFAT_I(inode)->i_size_aligned = i_size_read(inode); + SDFAT_I(inode)->i_size_ondisk = i_size_read(inode); + + sdfat_save_attr(inode, ATTR_SUBDIR); + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; + set_nlink(inode, info.NumSubdirs + 2); + return 0; +} + + + +static void setup_dops(struct super_block *sb) +{ + if (SDFAT_SB(sb)->options.casesensitive == 0) + sb->s_d_op = &sdfat_ci_dentry_ops; + else + sb->s_d_op = &sdfat_dentry_ops; +} + +static int sdfat_fill_super(struct super_block *sb, void *data, int silent) +{ + struct inode *root_inode = NULL; + struct sdfat_sb_info *sbi; + int debug; + int err; + char buf[50]; + struct block_device *bdev = sb->s_bdev; + dev_t bd_dev = bdev ? bdev->bd_dev : 0; + + sdfat_log_msg(sb, KERN_INFO, "trying to mount..."); + + /* + * GFP_KERNEL is ok here, because while we do hold the + * supeblock lock, memory pressure can't call back into + * the filesystem, since we're only just about to mount + * it and have no inodes etc active! + */ + sbi = kzalloc(sizeof(struct sdfat_sb_info), GFP_KERNEL); + if (!sbi) { + sdfat_log_msg(sb, KERN_INFO, + "trying to alloc sbi with vzalloc()"); + sbi = vzalloc(sizeof(struct sdfat_sb_info)); + if (!sbi) { + sdfat_log_msg(sb, KERN_ERR, "failed to mount! (ENOMEM)"); + return -ENOMEM; + } + sbi->use_vmalloc = 1; + } + + mutex_init(&sbi->s_vlock); + sb->s_fs_info = sbi; + sb->s_flags |= MS_NODIRATIME; + sb->s_magic = SDFAT_SUPER_MAGIC; + sb->s_op = &sdfat_sops; + ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL, + DEFAULT_RATELIMIT_BURST); + err = parse_options(sb, data, silent, &debug, &sbi->options); + if (err) { + sdfat_log_msg(sb, KERN_ERR, "failed to parse options"); + goto failed_mount; + } + + setup_sdfat_xattr_handler(sb); + setup_sdfat_sync_super_wq(sb); + setup_dops(sb); + + err = fsapi_mount(sb); + if (err) { + sdfat_log_msg(sb, KERN_ERR, "failed to recognize fat type"); + goto failed_mount; + } + + /* set up enough so that it can read an inode */ + sdfat_hash_init(sb); + + /* + * The low byte of FAT's first entry must have same value with + * media-field. But in real world, too many devices is + * writing wrong value. So, removed that validity check. + * + * if (FAT_FIRST_ENT(sb, media) != first) + */ + + err = -EINVAL; + sprintf(buf, "cp%d", sbi->options.codepage); + sbi->nls_disk = load_nls(buf); + if (!sbi->nls_disk) { + sdfat_log_msg(sb, KERN_ERR, "codepage %s not found", buf); + goto failed_mount2; + } + + sbi->nls_io = load_nls(sbi->options.iocharset); + if (!sbi->nls_io) { + sdfat_log_msg(sb, KERN_ERR, "IO charset %s not found", + sbi->options.iocharset); + goto failed_mount2; + } + + err = __alloc_dfr_mem_if_required(sb); + if (err) { + sdfat_log_msg(sb, KERN_ERR, "failed to initialize a memory for " + "defragmentation"); + goto failed_mount3; + } + + err = -ENOMEM; + root_inode = new_inode(sb); + if (!root_inode) { + sdfat_log_msg(sb, KERN_ERR, "failed to allocate root inode."); + goto failed_mount3; + } + + root_inode->i_ino = SDFAT_ROOT_INO; + root_inode->i_version = 1; + + err = sdfat_read_root(root_inode); + if (err) { + sdfat_log_msg(sb, KERN_ERR, "failed to initialize root inode."); + goto failed_mount3; + } + + sdfat_attach(root_inode, SDFAT_I(root_inode)->i_pos); + insert_inode_hash(root_inode); + + err = -ENOMEM; + sb->s_root = __d_make_root(root_inode); + if (!sb->s_root) { + sdfat_msg(sb, KERN_ERR, "failed to get the root dentry"); + goto failed_mount3; + } + + /* + * Initialize filesystem attributes (for sysfs) + * ex: /sys/fs/sdfat/mmcblk1[179:17] + */ + sbi->sb_kobj.kset = sdfat_kset; + err = kobject_init_and_add(&sbi->sb_kobj, &sdfat_ktype, NULL, + "%s[%d:%d]", sb->s_id, MAJOR(bd_dev), MINOR(bd_dev)); + if (err) { + sdfat_msg(sb, KERN_ERR, "Unable to create sdfat attributes for" + " %s[%d:%d](%d)", sb->s_id, + MAJOR(bd_dev), MINOR(bd_dev), err); + goto failed_mount3; + } + + sdfat_log_msg(sb, KERN_INFO, "mounted successfully!"); + /* FOR BIGDATA */ + sdfat_statistics_set_mnt(&sbi->fsi); + sdfat_statistics_set_vol_size(sb); + return 0; + +failed_mount3: + __free_dfr_mem_if_required(sb); +failed_mount2: + fsapi_umount(sb); +failed_mount: + sdfat_log_msg(sb, KERN_INFO, "failed to mount! (%d)", err); + + if (root_inode) + iput(root_inode); + sb->s_root = NULL; + + if (sbi->nls_io) + unload_nls(sbi->nls_io); + if (sbi->nls_disk) + unload_nls(sbi->nls_disk); + if (sbi->options.iocharset != sdfat_default_iocharset) + kfree(sbi->options.iocharset); + sb->s_fs_info = NULL; + if (!sbi->use_vmalloc) + kfree(sbi); + else + vfree(sbi); + return err; +} + +static struct dentry *sdfat_fs_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) { + return mount_bdev(fs_type, flags, dev_name, data, sdfat_fill_super); +} + +static void init_once(void *foo) +{ + struct sdfat_inode_info *ei = (struct sdfat_inode_info *)foo; + + INIT_HLIST_NODE(&ei->i_hash_fat); + inode_init_once(&ei->vfs_inode); +} + +static int __init sdfat_init_inodecache(void) +{ + sdfat_inode_cachep = kmem_cache_create("sdfat_inode_cache", + sizeof(struct sdfat_inode_info), + 0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD), + init_once); + if (!sdfat_inode_cachep) + return -ENOMEM; + return 0; +} + +static void sdfat_destroy_inodecache(void) +{ + kmem_cache_destroy(sdfat_inode_cachep); +} + +#ifdef CONFIG_SDFAT_DBG_IOCTL +static void sdfat_debug_kill_sb(struct super_block *sb) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(sb); + struct block_device *bdev = sb->s_bdev; + + long flags; + + if (sbi) { + flags = sbi->debug_flags; + + if (flags & SDFAT_DEBUGFLAGS_INVALID_UMOUNT) { + /* invalidate_bdev drops all device cache include dirty. + * we use this to simulate device removal + */ + fsapi_cache_release(sb); + invalidate_bdev(bdev); + } + } + + kill_block_super(sb); +} +#endif /* CONFIG_SDFAT_DBG_IOCTL */ + +static struct file_system_type sdfat_fs_type = { + .owner = THIS_MODULE, + .name = "sdfat", + .mount = sdfat_fs_mount, +#ifdef CONFIG_SDFAT_DBG_IOCTL + .kill_sb = sdfat_debug_kill_sb, +#else + .kill_sb = kill_block_super, +#endif /* CONFIG_SDFAT_DBG_IOCTL */ + .fs_flags = FS_REQUIRES_DEV, +}; + +static int __init init_sdfat_fs(void) +{ + int err; + + sdfat_log_version(); + err = fsapi_init(); + if (err) + goto error; + + sdfat_kset = kset_create_and_add("sdfat", NULL, fs_kobj); + if (!sdfat_kset) { + pr_err("[SDFAT] failed to create fs_kobj\n"); + err = -ENOMEM; + goto error; + } + + err = sysfs_create_group(&sdfat_kset->kobj, &attr_group); + if (err) { + pr_err("[SDFAT] failed to create sdfat version attributes\n"); + goto error; + } + + err = sdfat_statistics_init(sdfat_kset); + if (err) + goto error; + + err = sdfat_init_inodecache(); + if (err) { + pr_err("[SDFAT] failed to initialize inode cache\n"); + goto error; + } + + err = register_filesystem(&sdfat_fs_type); + if (err) { + pr_err("[SDFAT] failed to register filesystem\n"); + goto error; + } + + return 0; +error: + sdfat_statistics_uninit(); + + if (sdfat_kset) { + sysfs_remove_group(&sdfat_kset->kobj, &attr_group); + kset_unregister(sdfat_kset); + sdfat_kset = NULL; + } + + sdfat_destroy_inodecache(); + fsapi_shutdown(); + + pr_err("[SDFAT] failed to initialize FS driver(err:%d)\n", err); + return err; +} + +static void __exit exit_sdfat_fs(void) +{ + sdfat_statistics_uninit(); + + if (sdfat_kset) { + sysfs_remove_group(&sdfat_kset->kobj, &attr_group); + kset_unregister(sdfat_kset); + sdfat_kset = NULL; + } + + sdfat_destroy_inodecache(); + unregister_filesystem(&sdfat_fs_type); + + fsapi_shutdown(); +} + +module_init(init_sdfat_fs); +module_exit(exit_sdfat_fs); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("FAT/exFAT filesystem support"); +MODULE_AUTHOR("Samsung Electronics Co., Ltd."); + diff --git a/fs/sdfat/sdfat.h b/fs/sdfat/sdfat.h new file mode 100644 index 0000000000000..2f10b9603059c --- /dev/null +++ b/fs/sdfat/sdfat.h @@ -0,0 +1,507 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _SDFAT_H +#define _SDFAT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "api.h" + +#ifdef CONFIG_SDFAT_DFR +#include "dfr.h" +#endif + +/* + * sdfat error flags + */ +#define SDFAT_ERRORS_CONT (1) /* ignore error and continue */ +#define SDFAT_ERRORS_PANIC (2) /* panic on error */ +#define SDFAT_ERRORS_RO (3) /* remount r/o on error */ + +/* + * sdfat allocator flags + */ +#define SDFAT_ALLOC_DELAY (1) /* Delayed allocation */ +#define SDFAT_ALLOC_SMART (2) /* Smart allocation */ + +/* + * sdfat allocator destination for smart allocation + */ +#define ALLOC_NOWHERE (0) +#define ALLOC_COLD (1) +#define ALLOC_HOT (16) +#define ALLOC_COLD_ALIGNED (1) +#define ALLOC_COLD_PACKING (2) +#define ALLOC_COLD_SEQ (4) + +/* + * sdfat nls lossy flag + */ +#define NLS_NAME_NO_LOSSY (0x00) /* no lossy */ +#define NLS_NAME_LOSSY (0x01) /* just detected incorrect filename(s) */ +#define NLS_NAME_OVERLEN (0x02) /* the length is over than its limit */ + +/* + * sdfat common MACRO + */ +#define CLUSTER_16(x) ((u16)((x) & 0xFFFFU)) +#define CLUSTER_32(x) ((u32)((x) & 0xFFFFFFFFU)) +#define CLUS_EOF CLUSTER_32(~0) +#define CLUS_BAD (0xFFFFFFF7U) +#define CLUS_FREE (0) +#define CLUS_BASE (2) +#define IS_CLUS_EOF(x) ((x) == CLUS_EOF) +#define IS_CLUS_BAD(x) ((x) == CLUS_BAD) +#define IS_CLUS_FREE(x) ((x) == CLUS_FREE) +#define IS_LAST_SECT_IN_CLUS(fsi, sec) \ + ((((sec) - (fsi)->data_start_sector + 1) \ + & ((1 << (fsi)->sect_per_clus_bits) - 1)) == 0) + +#define CLUS_TO_SECT(fsi, x) \ + ((((x) - CLUS_BASE) << (fsi)->sect_per_clus_bits) + (fsi)->data_start_sector) + +#define SECT_TO_CLUS(fsi, sec) \ + ((((sec) - (fsi)->data_start_sector) >> (fsi)->sect_per_clus_bits) + CLUS_BASE) + +/* variables defined at sdfat.c */ +extern const char *FS_TYPE_STR[]; + +enum { + FS_TYPE_AUTO, + FS_TYPE_EXFAT, + FS_TYPE_VFAT, + FS_TYPE_MAX +}; + +/* + * sdfat mount in-memory data + */ +struct sdfat_mount_options { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + kuid_t fs_uid; + kgid_t fs_gid; +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) */ + uid_t fs_uid; + gid_t fs_gid; +#endif + unsigned short fs_fmask; + unsigned short fs_dmask; + unsigned short allow_utime; /* permission for setting the [am]time */ + unsigned short codepage; /* codepage for shortname conversions */ + char *iocharset; /* charset for filename input/display */ + struct { + unsigned int pack_ratio; + unsigned int sect_per_au; + unsigned int misaligned_sect; + } amap_opt; /* AMAP-related options (see amap.c) */ + + unsigned char utf8; + unsigned char casesensitive; + unsigned char adj_hidsect; + unsigned char tz_utc; + unsigned char improved_allocation; + unsigned char defrag; + unsigned char symlink; /* support symlink operation */ + unsigned char errors; /* on error: continue, panic, remount-ro */ + unsigned char discard; /* flag on if -o dicard specified and device support discard() */ + unsigned char fs_type; /* fs_type that user specified */ + unsigned short adj_req; /* support aligned mpage write */ +}; + +#define SDFAT_HASH_BITS 8 +#define SDFAT_HASH_SIZE (1UL << SDFAT_HASH_BITS) + +/* + * SDFAT file system superblock in-memory data + */ +struct sdfat_sb_info { + FS_INFO_T fsi; /* private filesystem info */ + + struct mutex s_vlock; /* volume lock */ + int use_vmalloc; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) + int s_dirt; + struct mutex s_lock; /* superblock lock */ + int write_super_queued; /* Write_super work is pending? */ + struct delayed_work write_super_work; /* Work_queue data structrue for write_super() */ + spinlock_t work_lock; /* Lock for WQ */ +#endif + struct super_block *host_sb; /* sb pointer */ + struct sdfat_mount_options options; + struct nls_table *nls_disk; /* Codepage used on disk */ + struct nls_table *nls_io; /* Charset used for input and display */ + struct ratelimit_state ratelimit; + + spinlock_t inode_hash_lock; + struct hlist_head inode_hashtable[SDFAT_HASH_SIZE]; + struct kobject sb_kobj; +#ifdef CONFIG_SDFAT_DBG_IOCTL + long debug_flags; +#endif /* CONFIG_SDFAT_DBG_IOCTL */ + +#ifdef CONFIG_SDFAT_DFR + struct defrag_info dfr_info; + struct completion dfr_complete; + unsigned int *dfr_new_clus; + int dfr_new_idx; + unsigned int *dfr_page_wb; + void **dfr_pagep; + unsigned int dfr_hint_clus; + unsigned int dfr_hint_idx; + int dfr_reserved_clus; + +#ifdef CONFIG_SDFAT_DFR_DEBUG + int dfr_spo_flag; +#endif /* CONFIG_SDFAT_DFR_DEBUG */ + +#endif /* CONFIG_SDFAT_DFR */ + +#ifdef CONFIG_SDFAT_TRACE_IO + /* Statistics for allocator */ + unsigned int stat_n_pages_written; /* # of written pages in total */ + unsigned int stat_n_pages_added; /* # of added blocks in total */ + unsigned int stat_n_bdev_pages_written; /* # of written pages owned by bdev inode */ + unsigned int stat_n_pages_confused; +#endif + atomic_t stat_n_pages_queued; /* # of pages in the request queue (approx.) */ +}; + +/* + * SDFAT file system inode in-memory data + */ +struct sdfat_inode_info { + FILE_ID_T fid; + char *target; + /* NOTE: i_size_ondisk is 64bits, so must hold ->inode_lock to access */ + loff_t i_size_ondisk; /* physically allocated size */ + loff_t i_size_aligned; /* block-aligned i_size (used in cont_write_begin) */ + loff_t i_pos; /* on-disk position of directory entry or 0 */ + struct hlist_node i_hash_fat; /* hash by i_location */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) + struct rw_semaphore truncate_lock; /* protect bmap against truncate */ +#endif +#ifdef CONFIG_SDFAT_DFR + struct defrag_info dfr_info; +#endif + struct inode vfs_inode; +}; + +/* + * FIXME : needs on-disk-slot in-memory data + */ + +/* static inline functons */ +static inline const char *sdfat_get_vol_type_str(unsigned int type) +{ + if (type == EXFAT) + return "exfat"; + else if (type == FAT32) + return "vfat:32"; + else if (type == FAT16) + return "vfat:16"; + else if (type == FAT12) + return "vfat:12"; + + return "unknown"; +} + +static inline struct sdfat_sb_info *SDFAT_SB(struct super_block *sb) +{ + return (struct sdfat_sb_info *)sb->s_fs_info; +} + +static inline struct sdfat_inode_info *SDFAT_I(struct inode *inode) +{ + return container_of(inode, struct sdfat_inode_info, vfs_inode); +} + +/* + * If ->i_mode can't hold S_IWUGO (i.e. ATTR_RO), we use ->i_attrs to + * save ATTR_RO instead of ->i_mode. + * + * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only + * bit, it's just used as flag for app. + */ +static inline int sdfat_mode_can_hold_ro(struct inode *inode) +{ + struct sdfat_sb_info *sbi = SDFAT_SB(inode->i_sb); + + if (S_ISDIR(inode->i_mode)) + return 0; + + if ((~sbi->options.fs_fmask) & S_IWUGO) + return 1; + return 0; +} + +/* + * FIXME : needs to check symlink option. + */ +/* Convert attribute bits and a mask to the UNIX mode. */ +static inline mode_t sdfat_make_mode(struct sdfat_sb_info *sbi, + u32 attr, mode_t mode) +{ + if ((attr & ATTR_READONLY) && !(attr & ATTR_SUBDIR)) + mode &= ~S_IWUGO; + + if (attr & ATTR_SUBDIR) + return (mode & ~sbi->options.fs_dmask) | S_IFDIR; + else if (attr & ATTR_SYMLINK) + return (mode & ~sbi->options.fs_dmask) | S_IFLNK; + else + return (mode & ~sbi->options.fs_fmask) | S_IFREG; +} + +/* Return the FAT attribute byte for this inode */ +static inline u32 sdfat_make_attr(struct inode *inode) +{ + u32 attrs = SDFAT_I(inode)->fid.attr; + + if (S_ISDIR(inode->i_mode)) + attrs |= ATTR_SUBDIR; + if (sdfat_mode_can_hold_ro(inode) && !(inode->i_mode & S_IWUGO)) + attrs |= ATTR_READONLY; + return attrs; +} + +static inline void sdfat_save_attr(struct inode *inode, u32 attr) +{ + if (sdfat_mode_can_hold_ro(inode)) + SDFAT_I(inode)->fid.attr = attr & ATTR_RWMASK; + else + SDFAT_I(inode)->fid.attr = attr & (ATTR_RWMASK | ATTR_READONLY); +} + +/* sdfat/statistics.c */ +/* bigdata function */ +#ifdef CONFIG_SDFAT_STATISTICS +extern int sdfat_statistics_init(struct kset *sdfat_kset); +extern void sdfat_statistics_uninit(void); +extern void sdfat_statistics_set_mnt(FS_INFO_T *fsi); +extern void sdfat_statistics_set_mkdir(u8 flags); +extern void sdfat_statistics_set_create(u8 flags); +extern void sdfat_statistics_set_rw(u8 flags, u32 clu_offset, s32 create); +extern void sdfat_statistics_set_trunc(u8 flags, CHAIN_T *clu); +extern void sdfat_statistics_set_vol_size(struct super_block *sb); +#else +static inline int sdfat_statistics_init(struct kset *sdfat_kset) +{ + return 0; +} +static inline void sdfat_statistics_uninit(void) {}; +static inline void sdfat_statistics_set_mnt(FS_INFO_T *fsi) {}; +static inline void sdfat_statistics_set_mkdir(u8 flags) {}; +static inline void sdfat_statistics_set_create(u8 flags) {}; +static inline void sdfat_statistics_set_rw(u8 flags, u32 clu_offset, s32 create) {}; +static inline void sdfat_statistics_set_trunc(u8 flags, CHAIN_T *clu) {}; +static inline void sdfat_statistics_set_vol_size(struct super_block *sb) {}; +#endif + +/* sdfat/nls.c */ +/* NLS management function */ +s32 nls_cmp_sfn(struct super_block *sb, u8 *a, u8 *b); +s32 nls_cmp_uniname(struct super_block *sb, u16 *a, u16 *b); +s32 nls_uni16s_to_sfn(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname, s32 *p_lossy); +s32 nls_sfn_to_uni16s(struct super_block *sb, DOS_NAME_T *p_dosname, UNI_NAME_T *p_uniname); +s32 nls_uni16s_to_vfsname(struct super_block *sb, UNI_NAME_T *uniname, u8 *p_cstring, s32 len); +s32 nls_vfsname_to_uni16s(struct super_block *sb, const u8 *p_cstring, + const s32 len, UNI_NAME_T *uniname, s32 *p_lossy); + +/* sdfat/mpage.c */ +#ifdef CONFIG_SDFAT_ALIGNED_MPAGE_WRITE +int sdfat_mpage_writepages(struct address_space *mapping, + struct writeback_control *wbc, get_block_t *get_block); +#endif + +/* sdfat/xattr.c */ +#ifdef CONFIG_SDFAT_VIRTUAL_XATTR +void setup_sdfat_xattr_handler(struct super_block *sb); +extern int sdfat_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); +extern ssize_t sdfat_getxattr(struct dentry *dentry, const char *name, void *value, size_t size); +extern ssize_t sdfat_listxattr(struct dentry *dentry, char *list, size_t size); +extern int sdfat_removexattr(struct dentry *dentry, const char *name); +#else +static inline void setup_sdfat_xattr_handler(struct super_block *sb) {}; +#endif + +/* sdfat/misc.c */ +extern void +__sdfat_fs_error(struct super_block *sb, int report, const char *fmt, ...) + __printf(3, 4) __cold; +#define sdfat_fs_error(sb, fmt, args...) \ + __sdfat_fs_error(sb, 1, fmt, ## args) +#define sdfat_fs_error_ratelimit(sb, fmt, args...) \ + __sdfat_fs_error(sb, __ratelimit(&SDFAT_SB(sb)->ratelimit), fmt, ## args) +extern void +__sdfat_msg(struct super_block *sb, const char *lv, int st, const char *fmt, ...) + __printf(4, 5) __cold; +#define sdfat_msg(sb, lv, fmt, args...) \ + __sdfat_msg(sb, lv, 0, fmt, ## args) +#define sdfat_log_msg(sb, lv, fmt, args...) \ + __sdfat_msg(sb, lv, 1, fmt, ## args) +extern void sdfat_log_version(void); +extern void sdfat_time_fat2unix(struct sdfat_sb_info *sbi, struct timespec *ts, + DATE_TIME_T *tp); +extern void sdfat_time_unix2fat(struct sdfat_sb_info *sbi, struct timespec *ts, + DATE_TIME_T *tp); +extern TIMESTAMP_T *tm_now(struct sdfat_sb_info *sbi, TIMESTAMP_T *tm); + +#ifdef CONFIG_SDFAT_DEBUG + +#ifdef CONFIG_SDFAT_DBG_CAREFUL +void sdfat_debug_check_clusters(struct inode *inode); +#else +#define sdfat_debug_check_clusters(inode) +#endif /* CONFIG_SDFAT_DBG_CAREFUL */ + +#ifdef CONFIG_SDFAT_DBG_BUGON +#define sdfat_debug_bug_on(expr) BUG_ON(expr) +#else +#define sdfat_debug_bug_on(expr) +#endif + +#ifdef CONFIG_SDFAT_DBG_WARNON +#define sdfat_debug_warn_on(expr) WARN_ON(expr) +#else +#define sdfat_debug_warn_on(expr) +#endif + +#else /* CONFIG_SDFAT_DEBUG */ + +#define sdfat_debug_check_clusters(inode) +#define sdfat_debug_bug_on(expr) + +#endif /* CONFIG_SDFAT_DEBUG */ + +#ifdef CONFIG_SDFAT_TRACE_ELAPSED_TIME +u32 sdfat_time_current_usec(struct timeval *tv); +extern struct timeval __t1; +extern struct timeval __t2; + +#define TIME_GET(tv) sdfat_time_current_usec(tv) +#define TIME_START(s) sdfat_time_current_usec(s) +#define TIME_END(e) sdfat_time_current_usec(e) +#define TIME_ELAPSED(s, e) ((u32)(((e)->tv_sec - (s)->tv_sec) * 1000000 + \ + ((e)->tv_usec - (s)->tv_usec))) +#define PRINT_TIME(n) pr_info("[SDFAT] Elapsed time %d = %d (usec)\n", n, (__t2 - __t1)) +#else /* CONFIG_SDFAT_TRACE_ELAPSED_TIME */ +#define TIME_GET(tv) (0) +#define TIME_START(s) +#define TIME_END(e) +#define TIME_ELAPSED(s, e) (0) +#define PRINT_TIME(n) +#endif /* CONFIG_SDFAT_TRACE_ELAPSED_TIME */ + +#define SDFAT_MSG_LV_NONE (0x00000000) +#define SDFAT_MSG_LV_ERR (0x00000001) +#define SDFAT_MSG_LV_INFO (0x00000002) +#define SDFAT_MSG_LV_DBG (0x00000003) +#define SDFAT_MSG_LV_MORE (0x00000004) +#define SDFAT_MSG_LV_TRACE (0x00000005) +#define SDFAT_MSG_LV_ALL (0x00000006) + +#define SDFAT_MSG_LEVEL SDFAT_MSG_LV_INFO + +#define SDFAT_TAG_NAME "SDFAT" +#define __S(x) #x +#define _S(x) __S(x) + +extern void __sdfat_dmsg(int level, const char *fmt, ...) __printf(2, 3) __cold; + +#define SDFAT_EMSG_T(level, ...) \ + __sdfat_dmsg(level, KERN_ERR "[" SDFAT_TAG_NAME "] [" _S(__FILE__) "(" _S(__LINE__) ")] " __VA_ARGS__) +#define SDFAT_DMSG_T(level, ...) \ + __sdfat_dmsg(level, KERN_INFO "[" SDFAT_TAG_NAME "] " __VA_ARGS__) + +#define SDFAT_EMSG(...) SDFAT_EMSG_T(SDFAT_MSG_LV_ERR, __VA_ARGS__) +#define SDFAT_IMSG(...) SDFAT_DMSG_T(SDFAT_MSG_LV_INFO, __VA_ARGS__) +#define SDFAT_DMSG(...) SDFAT_DMSG_T(SDFAT_MSG_LV_DBG, __VA_ARGS__) +#define SDFAT_MMSG(...) SDFAT_DMSG_T(SDFAT_MSG_LV_MORE, __VA_ARGS__) +#define SDFAT_TMSG(...) SDFAT_DMSG_T(SDFAT_MSG_LV_TRACE, __VA_ARGS__) + +#define EMSG(...) +#define IMSG(...) +#define DMSG(...) +#define MMSG(...) +#define TMSG(...) + +#define EMSG_VAR(exp) +#define IMSG_VAR(exp) +#define DMSG_VAR(exp) +#define MMSG_VAR(exp) +#define TMSG_VAR(exp) + +#ifdef CONFIG_SDFAT_DBG_MSG + + +#if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_ERR) +#undef EMSG +#undef EMSG_VAR +#define EMSG(...) SDFAT_EMSG(__VA_ARGS__) +#define EMSG_VAR(exp) exp +#endif + +#if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_INFO) +#undef IMSG +#undef IMSG_VAR +#define IMSG(...) SDFAT_IMSG(__VA_ARGS__) +#define IMSG_VAR(exp) exp +#endif + +#if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_DBG) +#undef DMSG +#undef DMSG_VAR +#define DMSG(...) SDFAT_DMSG(__VA_ARGS__) +#define DMSG_VAR(exp) exp +#endif + +#if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_MORE) +#undef MMSG +#undef MMSG_VAR +#define MMSG(...) SDFAT_MMSG(__VA_ARGS__) +#define MMSG_VAR(exp) exp +#endif + +/* should replace with trace function */ +#if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_TRACE) +#undef TMSG +#undef TMSG_VAR +#define TMSG(...) SDFAT_TMSG(__VA_ARGS__) +#define TMSG_VAR(exp) exp +#endif + +#endif /* CONFIG_SDFAT_DBG_MSG */ + + +#define ASSERT(expr) { \ + if (!(expr)) { \ + pr_err("Assertion failed! %s\n", #expr); \ + BUG_ON(1); \ + } \ +} + +#endif /* !_SDFAT_H */ + diff --git a/fs/sdfat/sdfat_fs.h b/fs/sdfat/sdfat_fs.h new file mode 100644 index 0000000000000..998ca84c9a6ee --- /dev/null +++ b/fs/sdfat/sdfat_fs.h @@ -0,0 +1,416 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _SDFAT_FS_H +#define _SDFAT_FS_H + +#include +#include +#include + +/*----------------------------------------------------------------------*/ +/* Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ +#ifndef MSDOS_SUPER_MAGIC +#define MSDOS_SUPER_MAGIC 0x4d44 /* MD */ +#endif + +#ifndef EXFAT_SUPER_MAGIC +#define EXFAT_SUPER_MAGIC (0x2011BAB0UL) +#endif /* EXFAT_SUPER_MAGIC */ + +#define SDFAT_SUPER_MAGIC (0x5EC5DFA4UL) +#define SDFAT_ROOT_INO 1 + +/* FAT types */ +#define FAT12 0x01 // FAT12 +#define FAT16 0x0E // Win95 FAT16 (LBA) +#define FAT32 0x0C // Win95 FAT32 (LBA) +#define EXFAT 0x07 // exFAT + +/* directory file name */ +#define DOS_CUR_DIR_NAME ". " +#define DOS_PAR_DIR_NAME ".. " + +#ifdef __LITTLE_ENDIAN +#define UNI_CUR_DIR_NAME ".\0" +#define UNI_PAR_DIR_NAME ".\0.\0" +#else +#define UNI_CUR_DIR_NAME "\0." +#define UNI_PAR_DIR_NAME "\0.\0." +#endif + +/* file name lengths */ +/* NOTE : + * The maximum length of input or output is limited to 256 including NULL, + * But we allocate 4 extra bytes for utf8 translation reside in last position, + * because utf8 can uses memory upto 6 bytes per one character. + * Therefore, MAX_CHARSET_SIZE supports upto 6 bytes for utf8 + */ +#define MAX_UNINAME_BUF_SIZE (((MAX_NAME_LENGTH+1)*2)+4) +#define MAX_DOSNAME_BUF_SIZE ((DOS_NAME_LENGTH+2)+6) +#define MAX_VFSNAME_BUF_SIZE ((MAX_NAME_LENGTH+1)*MAX_CHARSET_SIZE) +#define MAX_CHARSET_SIZE 6 // max size of multi-byte character +#define MAX_NAME_LENGTH 255 // max len of file name excluding NULL +#define DOS_NAME_LENGTH 11 // DOS file name length excluding NULL + +#define DENTRY_SIZE 32 /* directory entry size */ +#define DENTRY_SIZE_BITS 5 + +#define MAX_FAT_DENTRIES 65536 /* FAT allows 65536 directory entries */ +#define MAX_EXFAT_DENTRIES 8388608 /* exFAT allows 8388608(256MB) directory entries */ + +/* PBR entries */ +#define PBR_SIGNATURE 0xAA55 +#define EXT_SIGNATURE 0xAA550000 +#define VOL_LABEL "NO NAME " /* size should be 11 */ +#define OEM_NAME "MSWIN4.1" /* size should be 8 */ +#define STR_FAT12 "FAT12 " /* size should be 8 */ +#define STR_FAT16 "FAT16 " /* size should be 8 */ +#define STR_FAT32 "FAT32 " /* size should be 8 */ +#define STR_EXFAT "EXFAT " /* size should be 8 */ + +#define VOL_CLEAN 0x0000 +#define VOL_DIRTY 0x0002 + +#define FAT_VOL_DIRTY 0x01 + +/* max number of clusters */ +#define FAT12_THRESHOLD 4087 // 2^12 - 1 + 2 (clu 0 & 1) +#define FAT16_THRESHOLD 65527 // 2^16 - 1 + 2 +#define FAT32_THRESHOLD 268435457 // 2^28 - 1 + 2 +#define EXFAT_THRESHOLD 268435457 // 2^28 - 1 + 2 + +/* dentry types */ +#define MSDOS_DELETED 0xE5 /* deleted mark */ +#define MSDOS_UNUSED 0x00 /* end of directory */ + +#define EXFAT_UNUSED 0x00 /* end of directory */ +#define IS_EXFAT_DELETED(x) ((x) < 0x80) /* deleted file (0x01~0x7F) */ +#define EXFAT_INVAL 0x80 /* invalid value */ +#define EXFAT_BITMAP 0x81 /* allocation bitmap */ +#define EXFAT_UPCASE 0x82 /* upcase table */ +#define EXFAT_VOLUME 0x83 /* volume label */ +#define EXFAT_FILE 0x85 /* file or dir */ +#define EXFAT_STREAM 0xC0 /* stream entry */ +#define EXFAT_NAME 0xC1 /* file name entry */ +#define EXFAT_ACL 0xC2 /* stream entry */ + +/* specific flag */ +#define MSDOS_LAST_LFN 0x40 + +/* file attributes */ +#define ATTR_NORMAL 0x0000 +#define ATTR_READONLY 0x0001 +#define ATTR_HIDDEN 0x0002 +#define ATTR_SYSTEM 0x0004 +#define ATTR_VOLUME 0x0008 +#define ATTR_SUBDIR 0x0010 +#define ATTR_ARCHIVE 0x0020 +#define ATTR_SYMLINK 0x0040 +#define ATTR_EXTEND (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | \ + ATTR_VOLUME) /* 0x000F */ + +#define ATTR_EXTEND_MASK (ATTR_EXTEND | ATTR_SUBDIR | ATTR_ARCHIVE) +#define ATTR_RWMASK (ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME | \ + ATTR_SUBDIR | ATTR_ARCHIVE | ATTR_SYMLINK)/* 0x007E */ + +/* file creation modes */ +#define FM_REGULAR 0x00 +#define FM_SYMLINK 0x40 + +/* time modes */ +#define TM_CREATE 0 +#define TM_MODIFY 1 +#define TM_ACCESS 2 + +/* checksum types */ +#define CS_DIR_ENTRY 0 +#define CS_PBR_SECTOR 1 +#define CS_DEFAULT 2 + +/* + * ioctl command + */ +#define SDFAT_IOCTL_GET_VOLUME_ID _IOR('r', 0x12, __u32) +#define SDFAT_IOCTL_DFR_INFO _IOC(_IOC_NONE, 'E', 0x13, sizeof(u32)) +#define SDFAT_IOCTL_DFR_TRAV _IOC(_IOC_NONE, 'E', 0x14, sizeof(u32)) +#define SDFAT_IOCTL_DFR_REQ _IOC(_IOC_NONE, 'E', 0x15, sizeof(u32)) +#define SDFAT_IOCTL_DFR_SPO_FLAG _IOC(_IOC_NONE, 'E', 0x16, sizeof(u32)) +#define SDFAT_IOCTL_PANIC _IOC(_IOC_NONE, 'E', 0x17, sizeof(u32)) + +/* + * ioctl command for debugging + */ + +/* + * IOCTL code 'f' used by + * - file systems typically #0~0x1F + * - embedded terminal devices #128~ + * - exts for debugging purpose #99 + * number 100 and 101 is available now but has possible conflicts + * + * NOTE : This is available only If CONFIG_SDFAT_DVBG_IOCTL is enabled. + * + */ +#define SDFAT_IOC_GET_DEBUGFLAGS _IOR('f', 100, long) +#define SDFAT_IOC_SET_DEBUGFLAGS _IOW('f', 101, long) + +#define SDFAT_DEBUGFLAGS_INVALID_UMOUNT 0x01 +#define SDFAT_DEBUGFLAGS_ERROR_RW 0x02 + +/*----------------------------------------------------------------------*/ +/* On-Disk Type Definitions */ +/*----------------------------------------------------------------------*/ + +/* FAT12/16 BIOS parameter block (64 bytes) */ +typedef struct { + __u8 jmp_boot[3]; + __u8 oem_name[8]; + + __u8 sect_size[2]; /* unaligned */ + __u8 sect_per_clus; + __le16 num_reserved; /* . */ + __u8 num_fats; + __u8 num_root_entries[2]; /* unaligned */ + __u8 num_sectors[2]; /* unaligned */ + __u8 media_type; + __le16 num_fat_sectors; + __le16 sectors_in_track; + __le16 num_heads; + __le32 num_hid_sectors; /* . */ + __le32 num_huge_sectors; + + __u8 phy_drv_no; + __u8 state; /* used by WindowsNT for mount state */ + __u8 ext_signature; + __u8 vol_serial[4]; + __u8 vol_label[11]; + __u8 vol_type[8]; + __le16 dummy; +} bpb16_t; + +/* FAT32 BIOS parameter block (64 bytes) */ +typedef struct { + __u8 jmp_boot[3]; + __u8 oem_name[8]; + + __u8 sect_size[2]; /* unaligned */ + __u8 sect_per_clus; + __le16 num_reserved; + __u8 num_fats; + __u8 num_root_entries[2]; /* unaligned */ + __u8 num_sectors[2]; /* unaligned */ + __u8 media_type; + __le16 num_fat_sectors; /* zero */ + __le16 sectors_in_track; + __le16 num_heads; + __le32 num_hid_sectors; /* . */ + __le32 num_huge_sectors; + + __le32 num_fat32_sectors; + __le16 ext_flags; + __u8 fs_version[2]; + __le32 root_cluster; /* . */ + __le16 fsinfo_sector; + __le16 backup_sector; + __le16 reserved[6]; /* . */ +} bpb32_t; + +/* FAT32 EXTEND BIOS parameter block (32 bytes) */ +typedef struct { + __u8 phy_drv_no; + __u8 state; /* used by WindowsNT for mount state */ + __u8 ext_signature; + __u8 vol_serial[4]; + __u8 vol_label[11]; + __u8 vol_type[8]; + __le16 dummy[3]; +} bsx32_t; + +/* EXFAT BIOS parameter block (64 bytes) */ +typedef struct { + __u8 jmp_boot[3]; + __u8 oem_name[8]; + __u8 res_zero[53]; +} bpb64_t; + +/* EXFAT EXTEND BIOS parameter block (56 bytes) */ +typedef struct { + __le64 vol_offset; + __le64 vol_length; + __le32 fat_offset; + __le32 fat_length; + __le32 clu_offset; + __le32 clu_count; + __le32 root_cluster; + __le32 vol_serial; + __u8 fs_version[2]; + __le16 vol_flags; + __u8 sect_size_bits; + __u8 sect_per_clus_bits; + __u8 num_fats; + __u8 phy_drv_no; + __u8 perc_in_use; + __u8 reserved2[7]; +} bsx64_t; + +/* FAT32 PBR (64 bytes) */ +typedef struct { + bpb16_t bpb; +} pbr16_t; + +/* FAT32 PBR[BPB+BSX] (96 bytes) */ +typedef struct { + bpb32_t bpb; + bsx32_t bsx; +} pbr32_t; + +/* EXFAT PBR[BPB+BSX] (120 bytes) */ +typedef struct { + bpb64_t bpb; + bsx64_t bsx; +} pbr64_t; + +/* Common PBR[Partition Boot Record] (512 bytes) */ +typedef struct { + union { + __u8 raw[64]; + bpb16_t f16; + bpb32_t f32; + bpb64_t f64; + } bpb; + union { + __u8 raw[56]; + bsx32_t f32; + bsx64_t f64; + } bsx; + __u8 boot_code[390]; + __le16 signature; +} pbr_t; + +/* FAT32 filesystem information sector (512 bytes) */ +typedef struct { + __le32 signature1; // aligned + __u8 reserved1[480]; + __le32 signature2; // aligned + __le32 free_cluster; // aligned + __le32 next_cluster; // aligned + __u8 reserved2[14]; + __le16 signature3[2]; +} fat32_fsi_t; + +/* FAT directory entry (32 bytes) */ +typedef struct { + __u8 dummy[32]; +} DENTRY_T; + +typedef struct { + __u8 name[DOS_NAME_LENGTH]; /* 11 chars */ + __u8 attr; + __u8 lcase; + __u8 create_time_ms; + __le16 create_time; // aligned + __le16 create_date; // aligned + __le16 access_date; // aligned + __le16 start_clu_hi; // aligned + __le16 modify_time; // aligned + __le16 modify_date; // aligned + __le16 start_clu_lo; // aligned + __le32 size; // aligned +} DOS_DENTRY_T; + +/* FAT extended directory entry (32 bytes) */ +typedef struct { + __u8 order; + __u8 unicode_0_4[10]; + __u8 attr; + __u8 sysid; + __u8 checksum; + __le16 unicode_5_10[6]; // aligned + __le16 start_clu; // aligned + __le16 unicode_11_12[2]; // aligned +} EXT_DENTRY_T; + +/* EXFAT file directory entry (32 bytes) */ +typedef struct { + __u8 type; + __u8 num_ext; + __le16 checksum; // aligned + __le16 attr; // aligned + __le16 reserved1; + __le16 create_time; // aligned + __le16 create_date; // aligned + __le16 modify_time; // aligned + __le16 modify_date; // aligned + __le16 access_time; // aligned + __le16 access_date; // aligned + __u8 create_time_ms; + __u8 modify_time_ms; + __u8 access_time_ms; + __u8 reserved2[9]; +} FILE_DENTRY_T; + +/* EXFAT stream extension directory entry (32 bytes) */ +typedef struct { + __u8 type; + __u8 flags; + __u8 reserved1; + __u8 name_len; + __le16 name_hash; // aligned + __le16 reserved2; + __le64 valid_size; // aligned + __le32 reserved3; // aligned + __le32 start_clu; // aligned + __le64 size; // aligned +} STRM_DENTRY_T; + +/* EXFAT file name directory entry (32 bytes) */ +typedef struct { + __u8 type; + __u8 flags; + __le16 unicode_0_14[15]; // aligned +} NAME_DENTRY_T; + +/* EXFAT allocation bitmap directory entry (32 bytes) */ +typedef struct { + __u8 type; + __u8 flags; + __u8 reserved[18]; + __le32 start_clu; // aligned + __le64 size; // aligned +} BMAP_DENTRY_T; + +/* EXFAT up-case table directory entry (32 bytes) */ +typedef struct { + __u8 type; + __u8 reserved1[3]; + __le32 checksum; // aligned + __u8 reserved2[12]; + __le32 start_clu; // aligned + __le64 size; // aligned +} CASE_DENTRY_T; + +/* EXFAT volume label directory entry (32 bytes) */ +typedef struct { + __u8 type; + __u8 label_len; + __le16 unicode_0_10[11]; // aligned + __u8 reserved[8]; +} VOLM_DENTRY_T; + +#endif /* _SDFAT_FS_H */ diff --git a/fs/sdfat/statistics.c b/fs/sdfat/statistics.c new file mode 100644 index 0000000000000..cf4baab0edf6a --- /dev/null +++ b/fs/sdfat/statistics.c @@ -0,0 +1,262 @@ +#include "sdfat.h" + +#define SDFAT_VF_CLUS_MAX 7 /* 512 Byte ~ 32 KByte */ +#define SDFAT_EF_CLUS_MAX 17 /* 512 Byte ~ 32 MByte */ + +enum { + SDFAT_MNT_FAT12, + SDFAT_MNT_FAT16, + SDFAT_MNT_FAT32, + SDFAT_MNT_EXFAT, + SDFAT_MNT_MAX +}; + +enum { + SDFAT_OP_EXFAT_MNT, + SDFAT_OP_MKDIR, + SDFAT_OP_CREATE, + SDFAT_OP_READ, + SDFAT_OP_WRITE, + SDFAT_OP_TRUNC, + SDFAT_OP_MAX +}; + +enum { + SDFAT_VOL_4G, + SDFAT_VOL_8G, + SDFAT_VOL_16G, + SDFAT_VOL_32G, + SDFAT_VOL_64G, + SDFAT_VOL_128G, + SDFAT_VOL_256G, + SDFAT_VOL_512G, + SDFAT_VOL_XTB, + SDFAT_VOL_MAX +}; + +static struct sdfat_statistics { + u32 clus_vfat[SDFAT_VF_CLUS_MAX]; + u32 clus_exfat[SDFAT_EF_CLUS_MAX]; + u32 mnt_cnt[SDFAT_MNT_MAX]; + u32 nofat_op[SDFAT_OP_MAX]; + u32 vol_size[SDFAT_VOL_MAX]; +} statistics; + +static struct kset *sdfat_statistics_kset; + +static ssize_t vfat_cl_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buff) +{ + return snprintf(buff, PAGE_SIZE, "VCL_512B_I:%u,VCL_1K_I:%u,VCL_2K_I:%u," + "VCL_4K_I:%u,VCL_8K_I:%u,VCL_16K_I:%u,VCL_32K_I:%u\n", + statistics.clus_vfat[0], statistics.clus_vfat[1], + statistics.clus_vfat[2], statistics.clus_vfat[3], + statistics.clus_vfat[4], statistics.clus_vfat[5], + statistics.clus_vfat[6]); +} + +static ssize_t exfat_cl_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buff) +{ + return snprintf(buff, PAGE_SIZE, "ECL_512B_I:%u,ECL_1K_I:%u,ECL_2K_I:%u," + "ECL_4K_I:%u,ECL_8K_I:%u,ECL_16K_I:%u,ECL_32K_I:%u,ECL_64K_I:%u," + "ECL_128K_I:%u,ECL_256K_I:%u,ECL_512K_I:%u,ECL_1M_I:%u," + "ECL_2M_I:%u,ECL_4M_I:%u,ECL_8M_I:%u,ECL_16M_I:%u,ECL_32M_I:%u\n", + statistics.clus_exfat[0], statistics.clus_exfat[1], + statistics.clus_exfat[2], statistics.clus_exfat[3], + statistics.clus_exfat[4], statistics.clus_exfat[5], + statistics.clus_exfat[6], statistics.clus_exfat[7], + statistics.clus_exfat[8], statistics.clus_exfat[9], + statistics.clus_exfat[10], statistics.clus_exfat[11], + statistics.clus_exfat[12], statistics.clus_exfat[13], + statistics.clus_exfat[14], statistics.clus_exfat[15], + statistics.clus_exfat[16]); +} + +static ssize_t mount_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buff) +{ + return snprintf(buff, PAGE_SIZE, "FAT12_MNT_I:%u,FAT16_MNT_I:%u,FAT32_MNT_I:%u," + "EXFAT_MNT_I:%u\n", + statistics.mnt_cnt[SDFAT_MNT_FAT12], + statistics.mnt_cnt[SDFAT_MNT_FAT16], + statistics.mnt_cnt[SDFAT_MNT_FAT32], + statistics.mnt_cnt[SDFAT_MNT_EXFAT]); +} + +static ssize_t nofat_op_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buff) +{ + return snprintf(buff, PAGE_SIZE, "NOFAT_MOUNT_I:%u,NOFAT_MKDIR_I:%u,NOFAT_CREATE_I:%u," + "NOFAT_READ_I:%u,NOFAT_WRITE_I:%u,NOFAT_TRUNC_I:%u\n", + statistics.nofat_op[SDFAT_OP_EXFAT_MNT], + statistics.nofat_op[SDFAT_OP_MKDIR], + statistics.nofat_op[SDFAT_OP_CREATE], + statistics.nofat_op[SDFAT_OP_READ], + statistics.nofat_op[SDFAT_OP_WRITE], + statistics.nofat_op[SDFAT_OP_TRUNC]); +} + +static ssize_t vol_size_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buff) +{ + return snprintf(buff, PAGE_SIZE, "VOL_4G_I:%u,VOL_8G_I:%u,VOL_16G_I:%u," + "VOL_32G_I:%u,VOL_64G_I:%u,VOL_128G_I:%u,VOL_256G_I:%u," + "VOL_512G_I:%u,VOL_XTB_I:%u\n", + statistics.vol_size[SDFAT_VOL_4G], + statistics.vol_size[SDFAT_VOL_8G], + statistics.vol_size[SDFAT_VOL_16G], + statistics.vol_size[SDFAT_VOL_32G], + statistics.vol_size[SDFAT_VOL_64G], + statistics.vol_size[SDFAT_VOL_128G], + statistics.vol_size[SDFAT_VOL_256G], + statistics.vol_size[SDFAT_VOL_512G], + statistics.vol_size[SDFAT_VOL_XTB]); +} + +static struct kobj_attribute vfat_cl_attr = __ATTR_RO(vfat_cl); +static struct kobj_attribute exfat_cl_attr = __ATTR_RO(exfat_cl); +static struct kobj_attribute mount_attr = __ATTR_RO(mount); +static struct kobj_attribute nofat_op_attr = __ATTR_RO(nofat_op); +static struct kobj_attribute vol_size_attr = __ATTR_RO(vol_size); + +static struct attribute *attributes_statistics[] = { + &vfat_cl_attr.attr, + &exfat_cl_attr.attr, + &mount_attr.attr, + &nofat_op_attr.attr, + &vol_size_attr.attr, + NULL, +}; + +static struct attribute_group attr_group_statistics = { + .attrs = attributes_statistics, +}; + +int sdfat_statistics_init(struct kset *sdfat_kset) +{ + int err; + + sdfat_statistics_kset = kset_create_and_add("statistics", NULL, &sdfat_kset->kobj); + if (!sdfat_statistics_kset) { + pr_err("[SDFAT] failed to create sdfat statistics kobj\n"); + return -ENOMEM; + } + + err = sysfs_create_group(&sdfat_statistics_kset->kobj, &attr_group_statistics); + if (err) { + pr_err("[SDFAT] failed to create sdfat statistics attributes\n"); + kset_unregister(sdfat_statistics_kset); + sdfat_statistics_kset = NULL; + return err; + } + + return 0; +} + +void sdfat_statistics_uninit(void) +{ + if (sdfat_statistics_kset) { + sysfs_remove_group(&sdfat_statistics_kset->kobj, &attr_group_statistics); + kset_unregister(sdfat_statistics_kset); + sdfat_statistics_kset = NULL; + } + memset(&statistics, 0, sizeof(struct sdfat_statistics)); +} + +void sdfat_statistics_set_mnt(FS_INFO_T *fsi) +{ + if (fsi->vol_type == EXFAT) { + statistics.mnt_cnt[SDFAT_MNT_EXFAT]++; + statistics.nofat_op[SDFAT_OP_EXFAT_MNT] = 1; + if (fsi->sect_per_clus_bits < SDFAT_EF_CLUS_MAX) + statistics.clus_exfat[fsi->sect_per_clus_bits]++; + else + statistics.clus_exfat[SDFAT_EF_CLUS_MAX - 1]++; + return; + } + + if (fsi->vol_type == FAT32) + statistics.mnt_cnt[SDFAT_MNT_FAT32]++; + else if (fsi->vol_type == FAT16) + statistics.mnt_cnt[SDFAT_MNT_FAT16]++; + else if (fsi->vol_type == FAT12) + statistics.mnt_cnt[SDFAT_MNT_FAT12]++; + + if (fsi->sect_per_clus_bits < SDFAT_VF_CLUS_MAX) + statistics.clus_vfat[fsi->sect_per_clus_bits]++; + else + statistics.clus_vfat[SDFAT_VF_CLUS_MAX - 1]++; +} + +void sdfat_statistics_set_mkdir(u8 flags) +{ + if (flags != 0x03) + return; + statistics.nofat_op[SDFAT_OP_MKDIR] = 1; +} + +void sdfat_statistics_set_create(u8 flags) +{ + if (flags != 0x03) + return; + statistics.nofat_op[SDFAT_OP_CREATE] = 1; +} + +/* flags : file or dir flgas, 0x03 means no fat-chain. + * clu_offset : file or dir logical cluster offset + * create : BMAP_ADD_CLUSTER or not + * + * File or dir have BMAP_ADD_CLUSTER is no fat-chain write + * when they have 0x03 flag and two or more clusters. + * And don`t have BMAP_ADD_CLUSTER is no fat-chain read + * when above same condition. + */ +void sdfat_statistics_set_rw(u8 flags, u32 clu_offset, s32 create) +{ + if ((flags == 0x03) && (clu_offset > 1)) { + if (create) + statistics.nofat_op[SDFAT_OP_WRITE] = 1; + else + statistics.nofat_op[SDFAT_OP_READ] = 1; + } +} + +/* flags : file or dir flgas, 0x03 means no fat-chain. + * clu : cluster chain + * + * Set no fat-chain trunc when file or dir have 0x03 flag + * and tow or more clusters. + */ +void sdfat_statistics_set_trunc(u8 flags, CHAIN_T *clu) +{ + if ((flags == 0x03) && (clu->size > 1)) + statistics.nofat_op[SDFAT_OP_TRUNC] = 1; +} + +void sdfat_statistics_set_vol_size(struct super_block *sb) +{ + u64 vol_size; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + vol_size = (u64)fsi->num_sectors << sb->s_blocksize_bits; + + if (vol_size <= ((u64)1 << 32)) + statistics.vol_size[SDFAT_VOL_4G]++; + else if (vol_size <= ((u64)1 << 33)) + statistics.vol_size[SDFAT_VOL_8G]++; + else if (vol_size <= ((u64)1 << 34)) + statistics.vol_size[SDFAT_VOL_16G]++; + else if (vol_size <= ((u64)1 << 35)) + statistics.vol_size[SDFAT_VOL_32G]++; + else if (vol_size <= ((u64)1 << 36)) + statistics.vol_size[SDFAT_VOL_64G]++; + else if (vol_size <= ((u64)1 << 37)) + statistics.vol_size[SDFAT_VOL_128G]++; + else if (vol_size <= ((u64)1 << 38)) + statistics.vol_size[SDFAT_VOL_256G]++; + else if (vol_size <= ((u64)1 << 39)) + statistics.vol_size[SDFAT_VOL_512G]++; + else + statistics.vol_size[SDFAT_VOL_XTB]++; +} diff --git a/fs/sdfat/upcase.h b/fs/sdfat/upcase.h new file mode 100644 index 0000000000000..386772c57f8d9 --- /dev/null +++ b/fs/sdfat/upcase.h @@ -0,0 +1,407 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _UPCASE_H +#define _UPCASE_H + +/* Upcase tabel macro */ +#define SDFAT_NUM_UPCASE 2918 +#define HIGH_INDEX_BIT (8) +#define HIGH_INDEX_MASK (0xFF00) +#define LOW_INDEX_BIT (16-HIGH_INDEX_BIT) +#define UTBL_ROW_COUNT (1<> LOW_INDEX_BIT; +} +static inline u16 get_row_index(u16 i) +{ + return i & ~HIGH_INDEX_MASK; +} + + +static const u8 uni_def_upcase[SDFAT_NUM_UPCASE<<1] = { + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, + 0x08, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0B, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00, + 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, + 0x18, 0x00, 0x19, 0x00, 0x1A, 0x00, 0x1B, 0x00, 0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x00, 0x1F, 0x00, + 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, + 0x28, 0x00, 0x29, 0x00, 0x2A, 0x00, 0x2B, 0x00, 0x2C, 0x00, 0x2D, 0x00, 0x2E, 0x00, 0x2F, 0x00, + 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, + 0x38, 0x00, 0x39, 0x00, 0x3A, 0x00, 0x3B, 0x00, 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, + 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, + 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, + 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, + 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x5B, 0x00, 0x5C, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x5F, 0x00, + 0x60, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, + 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, + 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, + 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x7B, 0x00, 0x7C, 0x00, 0x7D, 0x00, 0x7E, 0x00, 0x7F, 0x00, + 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, + 0x88, 0x00, 0x89, 0x00, 0x8A, 0x00, 0x8B, 0x00, 0x8C, 0x00, 0x8D, 0x00, 0x8E, 0x00, 0x8F, 0x00, + 0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, + 0x98, 0x00, 0x99, 0x00, 0x9A, 0x00, 0x9B, 0x00, 0x9C, 0x00, 0x9D, 0x00, 0x9E, 0x00, 0x9F, 0x00, + 0xA0, 0x00, 0xA1, 0x00, 0xA2, 0x00, 0xA3, 0x00, 0xA4, 0x00, 0xA5, 0x00, 0xA6, 0x00, 0xA7, 0x00, + 0xA8, 0x00, 0xA9, 0x00, 0xAA, 0x00, 0xAB, 0x00, 0xAC, 0x00, 0xAD, 0x00, 0xAE, 0x00, 0xAF, 0x00, + 0xB0, 0x00, 0xB1, 0x00, 0xB2, 0x00, 0xB3, 0x00, 0xB4, 0x00, 0xB5, 0x00, 0xB6, 0x00, 0xB7, 0x00, + 0xB8, 0x00, 0xB9, 0x00, 0xBA, 0x00, 0xBB, 0x00, 0xBC, 0x00, 0xBD, 0x00, 0xBE, 0x00, 0xBF, 0x00, + 0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, 0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00, + 0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00, 0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00, + 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, 0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xD7, 0x00, + 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, 0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0xDF, 0x00, + 0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, 0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00, + 0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00, 0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00, + 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, 0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xF7, 0x00, + 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, 0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0x78, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x04, 0x01, 0x04, 0x01, 0x06, 0x01, 0x06, 0x01, + 0x08, 0x01, 0x08, 0x01, 0x0A, 0x01, 0x0A, 0x01, 0x0C, 0x01, 0x0C, 0x01, 0x0E, 0x01, 0x0E, 0x01, + 0x10, 0x01, 0x10, 0x01, 0x12, 0x01, 0x12, 0x01, 0x14, 0x01, 0x14, 0x01, 0x16, 0x01, 0x16, 0x01, + 0x18, 0x01, 0x18, 0x01, 0x1A, 0x01, 0x1A, 0x01, 0x1C, 0x01, 0x1C, 0x01, 0x1E, 0x01, 0x1E, 0x01, + 0x20, 0x01, 0x20, 0x01, 0x22, 0x01, 0x22, 0x01, 0x24, 0x01, 0x24, 0x01, 0x26, 0x01, 0x26, 0x01, + 0x28, 0x01, 0x28, 0x01, 0x2A, 0x01, 0x2A, 0x01, 0x2C, 0x01, 0x2C, 0x01, 0x2E, 0x01, 0x2E, 0x01, + 0x30, 0x01, 0x31, 0x01, 0x32, 0x01, 0x32, 0x01, 0x34, 0x01, 0x34, 0x01, 0x36, 0x01, 0x36, 0x01, + 0x38, 0x01, 0x39, 0x01, 0x39, 0x01, 0x3B, 0x01, 0x3B, 0x01, 0x3D, 0x01, 0x3D, 0x01, 0x3F, 0x01, + 0x3F, 0x01, 0x41, 0x01, 0x41, 0x01, 0x43, 0x01, 0x43, 0x01, 0x45, 0x01, 0x45, 0x01, 0x47, 0x01, + 0x47, 0x01, 0x49, 0x01, 0x4A, 0x01, 0x4A, 0x01, 0x4C, 0x01, 0x4C, 0x01, 0x4E, 0x01, 0x4E, 0x01, + 0x50, 0x01, 0x50, 0x01, 0x52, 0x01, 0x52, 0x01, 0x54, 0x01, 0x54, 0x01, 0x56, 0x01, 0x56, 0x01, + 0x58, 0x01, 0x58, 0x01, 0x5A, 0x01, 0x5A, 0x01, 0x5C, 0x01, 0x5C, 0x01, 0x5E, 0x01, 0x5E, 0x01, + 0x60, 0x01, 0x60, 0x01, 0x62, 0x01, 0x62, 0x01, 0x64, 0x01, 0x64, 0x01, 0x66, 0x01, 0x66, 0x01, + 0x68, 0x01, 0x68, 0x01, 0x6A, 0x01, 0x6A, 0x01, 0x6C, 0x01, 0x6C, 0x01, 0x6E, 0x01, 0x6E, 0x01, + 0x70, 0x01, 0x70, 0x01, 0x72, 0x01, 0x72, 0x01, 0x74, 0x01, 0x74, 0x01, 0x76, 0x01, 0x76, 0x01, + 0x78, 0x01, 0x79, 0x01, 0x79, 0x01, 0x7B, 0x01, 0x7B, 0x01, 0x7D, 0x01, 0x7D, 0x01, 0x7F, 0x01, + 0x43, 0x02, 0x81, 0x01, 0x82, 0x01, 0x82, 0x01, 0x84, 0x01, 0x84, 0x01, 0x86, 0x01, 0x87, 0x01, + 0x87, 0x01, 0x89, 0x01, 0x8A, 0x01, 0x8B, 0x01, 0x8B, 0x01, 0x8D, 0x01, 0x8E, 0x01, 0x8F, 0x01, + 0x90, 0x01, 0x91, 0x01, 0x91, 0x01, 0x93, 0x01, 0x94, 0x01, 0xF6, 0x01, 0x96, 0x01, 0x97, 0x01, + 0x98, 0x01, 0x98, 0x01, 0x3D, 0x02, 0x9B, 0x01, 0x9C, 0x01, 0x9D, 0x01, 0x20, 0x02, 0x9F, 0x01, + 0xA0, 0x01, 0xA0, 0x01, 0xA2, 0x01, 0xA2, 0x01, 0xA4, 0x01, 0xA4, 0x01, 0xA6, 0x01, 0xA7, 0x01, + 0xA7, 0x01, 0xA9, 0x01, 0xAA, 0x01, 0xAB, 0x01, 0xAC, 0x01, 0xAC, 0x01, 0xAE, 0x01, 0xAF, 0x01, + 0xAF, 0x01, 0xB1, 0x01, 0xB2, 0x01, 0xB3, 0x01, 0xB3, 0x01, 0xB5, 0x01, 0xB5, 0x01, 0xB7, 0x01, + 0xB8, 0x01, 0xB8, 0x01, 0xBA, 0x01, 0xBB, 0x01, 0xBC, 0x01, 0xBC, 0x01, 0xBE, 0x01, 0xF7, 0x01, + 0xC0, 0x01, 0xC1, 0x01, 0xC2, 0x01, 0xC3, 0x01, 0xC4, 0x01, 0xC5, 0x01, 0xC4, 0x01, 0xC7, 0x01, + 0xC8, 0x01, 0xC7, 0x01, 0xCA, 0x01, 0xCB, 0x01, 0xCA, 0x01, 0xCD, 0x01, 0xCD, 0x01, 0xCF, 0x01, + 0xCF, 0x01, 0xD1, 0x01, 0xD1, 0x01, 0xD3, 0x01, 0xD3, 0x01, 0xD5, 0x01, 0xD5, 0x01, 0xD7, 0x01, + 0xD7, 0x01, 0xD9, 0x01, 0xD9, 0x01, 0xDB, 0x01, 0xDB, 0x01, 0x8E, 0x01, 0xDE, 0x01, 0xDE, 0x01, + 0xE0, 0x01, 0xE0, 0x01, 0xE2, 0x01, 0xE2, 0x01, 0xE4, 0x01, 0xE4, 0x01, 0xE6, 0x01, 0xE6, 0x01, + 0xE8, 0x01, 0xE8, 0x01, 0xEA, 0x01, 0xEA, 0x01, 0xEC, 0x01, 0xEC, 0x01, 0xEE, 0x01, 0xEE, 0x01, + 0xF0, 0x01, 0xF1, 0x01, 0xF2, 0x01, 0xF1, 0x01, 0xF4, 0x01, 0xF4, 0x01, 0xF6, 0x01, 0xF7, 0x01, + 0xF8, 0x01, 0xF8, 0x01, 0xFA, 0x01, 0xFA, 0x01, 0xFC, 0x01, 0xFC, 0x01, 0xFE, 0x01, 0xFE, 0x01, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x02, + 0x08, 0x02, 0x08, 0x02, 0x0A, 0x02, 0x0A, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x0E, 0x02, 0x0E, 0x02, + 0x10, 0x02, 0x10, 0x02, 0x12, 0x02, 0x12, 0x02, 0x14, 0x02, 0x14, 0x02, 0x16, 0x02, 0x16, 0x02, + 0x18, 0x02, 0x18, 0x02, 0x1A, 0x02, 0x1A, 0x02, 0x1C, 0x02, 0x1C, 0x02, 0x1E, 0x02, 0x1E, 0x02, + 0x20, 0x02, 0x21, 0x02, 0x22, 0x02, 0x22, 0x02, 0x24, 0x02, 0x24, 0x02, 0x26, 0x02, 0x26, 0x02, + 0x28, 0x02, 0x28, 0x02, 0x2A, 0x02, 0x2A, 0x02, 0x2C, 0x02, 0x2C, 0x02, 0x2E, 0x02, 0x2E, 0x02, + 0x30, 0x02, 0x30, 0x02, 0x32, 0x02, 0x32, 0x02, 0x34, 0x02, 0x35, 0x02, 0x36, 0x02, 0x37, 0x02, + 0x38, 0x02, 0x39, 0x02, 0x65, 0x2C, 0x3B, 0x02, 0x3B, 0x02, 0x3D, 0x02, 0x66, 0x2C, 0x3F, 0x02, + 0x40, 0x02, 0x41, 0x02, 0x41, 0x02, 0x43, 0x02, 0x44, 0x02, 0x45, 0x02, 0x46, 0x02, 0x46, 0x02, + 0x48, 0x02, 0x48, 0x02, 0x4A, 0x02, 0x4A, 0x02, 0x4C, 0x02, 0x4C, 0x02, 0x4E, 0x02, 0x4E, 0x02, + 0x50, 0x02, 0x51, 0x02, 0x52, 0x02, 0x81, 0x01, 0x86, 0x01, 0x55, 0x02, 0x89, 0x01, 0x8A, 0x01, + 0x58, 0x02, 0x8F, 0x01, 0x5A, 0x02, 0x90, 0x01, 0x5C, 0x02, 0x5D, 0x02, 0x5E, 0x02, 0x5F, 0x02, + 0x93, 0x01, 0x61, 0x02, 0x62, 0x02, 0x94, 0x01, 0x64, 0x02, 0x65, 0x02, 0x66, 0x02, 0x67, 0x02, + 0x97, 0x01, 0x96, 0x01, 0x6A, 0x02, 0x62, 0x2C, 0x6C, 0x02, 0x6D, 0x02, 0x6E, 0x02, 0x9C, 0x01, + 0x70, 0x02, 0x71, 0x02, 0x9D, 0x01, 0x73, 0x02, 0x74, 0x02, 0x9F, 0x01, 0x76, 0x02, 0x77, 0x02, + 0x78, 0x02, 0x79, 0x02, 0x7A, 0x02, 0x7B, 0x02, 0x7C, 0x02, 0x64, 0x2C, 0x7E, 0x02, 0x7F, 0x02, + 0xA6, 0x01, 0x81, 0x02, 0x82, 0x02, 0xA9, 0x01, 0x84, 0x02, 0x85, 0x02, 0x86, 0x02, 0x87, 0x02, + 0xAE, 0x01, 0x44, 0x02, 0xB1, 0x01, 0xB2, 0x01, 0x45, 0x02, 0x8D, 0x02, 0x8E, 0x02, 0x8F, 0x02, + 0x90, 0x02, 0x91, 0x02, 0xB7, 0x01, 0x93, 0x02, 0x94, 0x02, 0x95, 0x02, 0x96, 0x02, 0x97, 0x02, + 0x98, 0x02, 0x99, 0x02, 0x9A, 0x02, 0x9B, 0x02, 0x9C, 0x02, 0x9D, 0x02, 0x9E, 0x02, 0x9F, 0x02, + 0xA0, 0x02, 0xA1, 0x02, 0xA2, 0x02, 0xA3, 0x02, 0xA4, 0x02, 0xA5, 0x02, 0xA6, 0x02, 0xA7, 0x02, + 0xA8, 0x02, 0xA9, 0x02, 0xAA, 0x02, 0xAB, 0x02, 0xAC, 0x02, 0xAD, 0x02, 0xAE, 0x02, 0xAF, 0x02, + 0xB0, 0x02, 0xB1, 0x02, 0xB2, 0x02, 0xB3, 0x02, 0xB4, 0x02, 0xB5, 0x02, 0xB6, 0x02, 0xB7, 0x02, + 0xB8, 0x02, 0xB9, 0x02, 0xBA, 0x02, 0xBB, 0x02, 0xBC, 0x02, 0xBD, 0x02, 0xBE, 0x02, 0xBF, 0x02, + 0xC0, 0x02, 0xC1, 0x02, 0xC2, 0x02, 0xC3, 0x02, 0xC4, 0x02, 0xC5, 0x02, 0xC6, 0x02, 0xC7, 0x02, + 0xC8, 0x02, 0xC9, 0x02, 0xCA, 0x02, 0xCB, 0x02, 0xCC, 0x02, 0xCD, 0x02, 0xCE, 0x02, 0xCF, 0x02, + 0xD0, 0x02, 0xD1, 0x02, 0xD2, 0x02, 0xD3, 0x02, 0xD4, 0x02, 0xD5, 0x02, 0xD6, 0x02, 0xD7, 0x02, + 0xD8, 0x02, 0xD9, 0x02, 0xDA, 0x02, 0xDB, 0x02, 0xDC, 0x02, 0xDD, 0x02, 0xDE, 0x02, 0xDF, 0x02, + 0xE0, 0x02, 0xE1, 0x02, 0xE2, 0x02, 0xE3, 0x02, 0xE4, 0x02, 0xE5, 0x02, 0xE6, 0x02, 0xE7, 0x02, + 0xE8, 0x02, 0xE9, 0x02, 0xEA, 0x02, 0xEB, 0x02, 0xEC, 0x02, 0xED, 0x02, 0xEE, 0x02, 0xEF, 0x02, + 0xF0, 0x02, 0xF1, 0x02, 0xF2, 0x02, 0xF3, 0x02, 0xF4, 0x02, 0xF5, 0x02, 0xF6, 0x02, 0xF7, 0x02, + 0xF8, 0x02, 0xF9, 0x02, 0xFA, 0x02, 0xFB, 0x02, 0xFC, 0x02, 0xFD, 0x02, 0xFE, 0x02, 0xFF, 0x02, + 0x00, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x03, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x07, 0x03, + 0x08, 0x03, 0x09, 0x03, 0x0A, 0x03, 0x0B, 0x03, 0x0C, 0x03, 0x0D, 0x03, 0x0E, 0x03, 0x0F, 0x03, + 0x10, 0x03, 0x11, 0x03, 0x12, 0x03, 0x13, 0x03, 0x14, 0x03, 0x15, 0x03, 0x16, 0x03, 0x17, 0x03, + 0x18, 0x03, 0x19, 0x03, 0x1A, 0x03, 0x1B, 0x03, 0x1C, 0x03, 0x1D, 0x03, 0x1E, 0x03, 0x1F, 0x03, + 0x20, 0x03, 0x21, 0x03, 0x22, 0x03, 0x23, 0x03, 0x24, 0x03, 0x25, 0x03, 0x26, 0x03, 0x27, 0x03, + 0x28, 0x03, 0x29, 0x03, 0x2A, 0x03, 0x2B, 0x03, 0x2C, 0x03, 0x2D, 0x03, 0x2E, 0x03, 0x2F, 0x03, + 0x30, 0x03, 0x31, 0x03, 0x32, 0x03, 0x33, 0x03, 0x34, 0x03, 0x35, 0x03, 0x36, 0x03, 0x37, 0x03, + 0x38, 0x03, 0x39, 0x03, 0x3A, 0x03, 0x3B, 0x03, 0x3C, 0x03, 0x3D, 0x03, 0x3E, 0x03, 0x3F, 0x03, + 0x40, 0x03, 0x41, 0x03, 0x42, 0x03, 0x43, 0x03, 0x44, 0x03, 0x45, 0x03, 0x46, 0x03, 0x47, 0x03, + 0x48, 0x03, 0x49, 0x03, 0x4A, 0x03, 0x4B, 0x03, 0x4C, 0x03, 0x4D, 0x03, 0x4E, 0x03, 0x4F, 0x03, + 0x50, 0x03, 0x51, 0x03, 0x52, 0x03, 0x53, 0x03, 0x54, 0x03, 0x55, 0x03, 0x56, 0x03, 0x57, 0x03, + 0x58, 0x03, 0x59, 0x03, 0x5A, 0x03, 0x5B, 0x03, 0x5C, 0x03, 0x5D, 0x03, 0x5E, 0x03, 0x5F, 0x03, + 0x60, 0x03, 0x61, 0x03, 0x62, 0x03, 0x63, 0x03, 0x64, 0x03, 0x65, 0x03, 0x66, 0x03, 0x67, 0x03, + 0x68, 0x03, 0x69, 0x03, 0x6A, 0x03, 0x6B, 0x03, 0x6C, 0x03, 0x6D, 0x03, 0x6E, 0x03, 0x6F, 0x03, + 0x70, 0x03, 0x71, 0x03, 0x72, 0x03, 0x73, 0x03, 0x74, 0x03, 0x75, 0x03, 0x76, 0x03, 0x77, 0x03, + 0x78, 0x03, 0x79, 0x03, 0x7A, 0x03, 0xFD, 0x03, 0xFE, 0x03, 0xFF, 0x03, 0x7E, 0x03, 0x7F, 0x03, + 0x80, 0x03, 0x81, 0x03, 0x82, 0x03, 0x83, 0x03, 0x84, 0x03, 0x85, 0x03, 0x86, 0x03, 0x87, 0x03, + 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, 0x8B, 0x03, 0x8C, 0x03, 0x8D, 0x03, 0x8E, 0x03, 0x8F, 0x03, + 0x90, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, + 0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03, 0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03, + 0xA0, 0x03, 0xA1, 0x03, 0xA2, 0x03, 0xA3, 0x03, 0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03, + 0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03, 0x86, 0x03, 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, + 0xB0, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, + 0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03, 0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03, + 0xA0, 0x03, 0xA1, 0x03, 0xA3, 0x03, 0xA3, 0x03, 0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03, + 0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03, 0x8C, 0x03, 0x8E, 0x03, 0x8F, 0x03, 0xCF, 0x03, + 0xD0, 0x03, 0xD1, 0x03, 0xD2, 0x03, 0xD3, 0x03, 0xD4, 0x03, 0xD5, 0x03, 0xD6, 0x03, 0xD7, 0x03, + 0xD8, 0x03, 0xD8, 0x03, 0xDA, 0x03, 0xDA, 0x03, 0xDC, 0x03, 0xDC, 0x03, 0xDE, 0x03, 0xDE, 0x03, + 0xE0, 0x03, 0xE0, 0x03, 0xE2, 0x03, 0xE2, 0x03, 0xE4, 0x03, 0xE4, 0x03, 0xE6, 0x03, 0xE6, 0x03, + 0xE8, 0x03, 0xE8, 0x03, 0xEA, 0x03, 0xEA, 0x03, 0xEC, 0x03, 0xEC, 0x03, 0xEE, 0x03, 0xEE, 0x03, + 0xF0, 0x03, 0xF1, 0x03, 0xF9, 0x03, 0xF3, 0x03, 0xF4, 0x03, 0xF5, 0x03, 0xF6, 0x03, 0xF7, 0x03, + 0xF7, 0x03, 0xF9, 0x03, 0xFA, 0x03, 0xFA, 0x03, 0xFC, 0x03, 0xFD, 0x03, 0xFE, 0x03, 0xFF, 0x03, + 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, + 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04, 0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04, + 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, + 0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04, 0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04, + 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, + 0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04, 0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04, + 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, + 0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04, 0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04, + 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, + 0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04, 0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04, + 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, + 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04, 0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04, + 0x60, 0x04, 0x60, 0x04, 0x62, 0x04, 0x62, 0x04, 0x64, 0x04, 0x64, 0x04, 0x66, 0x04, 0x66, 0x04, + 0x68, 0x04, 0x68, 0x04, 0x6A, 0x04, 0x6A, 0x04, 0x6C, 0x04, 0x6C, 0x04, 0x6E, 0x04, 0x6E, 0x04, + 0x70, 0x04, 0x70, 0x04, 0x72, 0x04, 0x72, 0x04, 0x74, 0x04, 0x74, 0x04, 0x76, 0x04, 0x76, 0x04, + 0x78, 0x04, 0x78, 0x04, 0x7A, 0x04, 0x7A, 0x04, 0x7C, 0x04, 0x7C, 0x04, 0x7E, 0x04, 0x7E, 0x04, + 0x80, 0x04, 0x80, 0x04, 0x82, 0x04, 0x83, 0x04, 0x84, 0x04, 0x85, 0x04, 0x86, 0x04, 0x87, 0x04, + 0x88, 0x04, 0x89, 0x04, 0x8A, 0x04, 0x8A, 0x04, 0x8C, 0x04, 0x8C, 0x04, 0x8E, 0x04, 0x8E, 0x04, + 0x90, 0x04, 0x90, 0x04, 0x92, 0x04, 0x92, 0x04, 0x94, 0x04, 0x94, 0x04, 0x96, 0x04, 0x96, 0x04, + 0x98, 0x04, 0x98, 0x04, 0x9A, 0x04, 0x9A, 0x04, 0x9C, 0x04, 0x9C, 0x04, 0x9E, 0x04, 0x9E, 0x04, + 0xA0, 0x04, 0xA0, 0x04, 0xA2, 0x04, 0xA2, 0x04, 0xA4, 0x04, 0xA4, 0x04, 0xA6, 0x04, 0xA6, 0x04, + 0xA8, 0x04, 0xA8, 0x04, 0xAA, 0x04, 0xAA, 0x04, 0xAC, 0x04, 0xAC, 0x04, 0xAE, 0x04, 0xAE, 0x04, + 0xB0, 0x04, 0xB0, 0x04, 0xB2, 0x04, 0xB2, 0x04, 0xB4, 0x04, 0xB4, 0x04, 0xB6, 0x04, 0xB6, 0x04, + 0xB8, 0x04, 0xB8, 0x04, 0xBA, 0x04, 0xBA, 0x04, 0xBC, 0x04, 0xBC, 0x04, 0xBE, 0x04, 0xBE, 0x04, + 0xC0, 0x04, 0xC1, 0x04, 0xC1, 0x04, 0xC3, 0x04, 0xC3, 0x04, 0xC5, 0x04, 0xC5, 0x04, 0xC7, 0x04, + 0xC7, 0x04, 0xC9, 0x04, 0xC9, 0x04, 0xCB, 0x04, 0xCB, 0x04, 0xCD, 0x04, 0xCD, 0x04, 0xC0, 0x04, + 0xD0, 0x04, 0xD0, 0x04, 0xD2, 0x04, 0xD2, 0x04, 0xD4, 0x04, 0xD4, 0x04, 0xD6, 0x04, 0xD6, 0x04, + 0xD8, 0x04, 0xD8, 0x04, 0xDA, 0x04, 0xDA, 0x04, 0xDC, 0x04, 0xDC, 0x04, 0xDE, 0x04, 0xDE, 0x04, + 0xE0, 0x04, 0xE0, 0x04, 0xE2, 0x04, 0xE2, 0x04, 0xE4, 0x04, 0xE4, 0x04, 0xE6, 0x04, 0xE6, 0x04, + 0xE8, 0x04, 0xE8, 0x04, 0xEA, 0x04, 0xEA, 0x04, 0xEC, 0x04, 0xEC, 0x04, 0xEE, 0x04, 0xEE, 0x04, + 0xF0, 0x04, 0xF0, 0x04, 0xF2, 0x04, 0xF2, 0x04, 0xF4, 0x04, 0xF4, 0x04, 0xF6, 0x04, 0xF6, 0x04, + 0xF8, 0x04, 0xF8, 0x04, 0xFA, 0x04, 0xFA, 0x04, 0xFC, 0x04, 0xFC, 0x04, 0xFE, 0x04, 0xFE, 0x04, + 0x00, 0x05, 0x00, 0x05, 0x02, 0x05, 0x02, 0x05, 0x04, 0x05, 0x04, 0x05, 0x06, 0x05, 0x06, 0x05, + 0x08, 0x05, 0x08, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0C, 0x05, 0x0C, 0x05, 0x0E, 0x05, 0x0E, 0x05, + 0x10, 0x05, 0x10, 0x05, 0x12, 0x05, 0x12, 0x05, 0x14, 0x05, 0x15, 0x05, 0x16, 0x05, 0x17, 0x05, + 0x18, 0x05, 0x19, 0x05, 0x1A, 0x05, 0x1B, 0x05, 0x1C, 0x05, 0x1D, 0x05, 0x1E, 0x05, 0x1F, 0x05, + 0x20, 0x05, 0x21, 0x05, 0x22, 0x05, 0x23, 0x05, 0x24, 0x05, 0x25, 0x05, 0x26, 0x05, 0x27, 0x05, + 0x28, 0x05, 0x29, 0x05, 0x2A, 0x05, 0x2B, 0x05, 0x2C, 0x05, 0x2D, 0x05, 0x2E, 0x05, 0x2F, 0x05, + 0x30, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, + 0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05, 0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05, + 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, + 0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05, 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, + 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0x57, 0x05, + 0x58, 0x05, 0x59, 0x05, 0x5A, 0x05, 0x5B, 0x05, 0x5C, 0x05, 0x5D, 0x05, 0x5E, 0x05, 0x5F, 0x05, + 0x60, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, + 0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05, 0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05, + 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, + 0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05, 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, + 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0xFF, 0xFF, + 0xF6, 0x17, 0x63, 0x2C, 0x7E, 0x1D, 0x7F, 0x1D, 0x80, 0x1D, 0x81, 0x1D, 0x82, 0x1D, 0x83, 0x1D, + 0x84, 0x1D, 0x85, 0x1D, 0x86, 0x1D, 0x87, 0x1D, 0x88, 0x1D, 0x89, 0x1D, 0x8A, 0x1D, 0x8B, 0x1D, + 0x8C, 0x1D, 0x8D, 0x1D, 0x8E, 0x1D, 0x8F, 0x1D, 0x90, 0x1D, 0x91, 0x1D, 0x92, 0x1D, 0x93, 0x1D, + 0x94, 0x1D, 0x95, 0x1D, 0x96, 0x1D, 0x97, 0x1D, 0x98, 0x1D, 0x99, 0x1D, 0x9A, 0x1D, 0x9B, 0x1D, + 0x9C, 0x1D, 0x9D, 0x1D, 0x9E, 0x1D, 0x9F, 0x1D, 0xA0, 0x1D, 0xA1, 0x1D, 0xA2, 0x1D, 0xA3, 0x1D, + 0xA4, 0x1D, 0xA5, 0x1D, 0xA6, 0x1D, 0xA7, 0x1D, 0xA8, 0x1D, 0xA9, 0x1D, 0xAA, 0x1D, 0xAB, 0x1D, + 0xAC, 0x1D, 0xAD, 0x1D, 0xAE, 0x1D, 0xAF, 0x1D, 0xB0, 0x1D, 0xB1, 0x1D, 0xB2, 0x1D, 0xB3, 0x1D, + 0xB4, 0x1D, 0xB5, 0x1D, 0xB6, 0x1D, 0xB7, 0x1D, 0xB8, 0x1D, 0xB9, 0x1D, 0xBA, 0x1D, 0xBB, 0x1D, + 0xBC, 0x1D, 0xBD, 0x1D, 0xBE, 0x1D, 0xBF, 0x1D, 0xC0, 0x1D, 0xC1, 0x1D, 0xC2, 0x1D, 0xC3, 0x1D, + 0xC4, 0x1D, 0xC5, 0x1D, 0xC6, 0x1D, 0xC7, 0x1D, 0xC8, 0x1D, 0xC9, 0x1D, 0xCA, 0x1D, 0xCB, 0x1D, + 0xCC, 0x1D, 0xCD, 0x1D, 0xCE, 0x1D, 0xCF, 0x1D, 0xD0, 0x1D, 0xD1, 0x1D, 0xD2, 0x1D, 0xD3, 0x1D, + 0xD4, 0x1D, 0xD5, 0x1D, 0xD6, 0x1D, 0xD7, 0x1D, 0xD8, 0x1D, 0xD9, 0x1D, 0xDA, 0x1D, 0xDB, 0x1D, + 0xDC, 0x1D, 0xDD, 0x1D, 0xDE, 0x1D, 0xDF, 0x1D, 0xE0, 0x1D, 0xE1, 0x1D, 0xE2, 0x1D, 0xE3, 0x1D, + 0xE4, 0x1D, 0xE5, 0x1D, 0xE6, 0x1D, 0xE7, 0x1D, 0xE8, 0x1D, 0xE9, 0x1D, 0xEA, 0x1D, 0xEB, 0x1D, + 0xEC, 0x1D, 0xED, 0x1D, 0xEE, 0x1D, 0xEF, 0x1D, 0xF0, 0x1D, 0xF1, 0x1D, 0xF2, 0x1D, 0xF3, 0x1D, + 0xF4, 0x1D, 0xF5, 0x1D, 0xF6, 0x1D, 0xF7, 0x1D, 0xF8, 0x1D, 0xF9, 0x1D, 0xFA, 0x1D, 0xFB, 0x1D, + 0xFC, 0x1D, 0xFD, 0x1D, 0xFE, 0x1D, 0xFF, 0x1D, 0x00, 0x1E, 0x00, 0x1E, 0x02, 0x1E, 0x02, 0x1E, + 0x04, 0x1E, 0x04, 0x1E, 0x06, 0x1E, 0x06, 0x1E, 0x08, 0x1E, 0x08, 0x1E, 0x0A, 0x1E, 0x0A, 0x1E, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0E, 0x1E, 0x0E, 0x1E, 0x10, 0x1E, 0x10, 0x1E, 0x12, 0x1E, 0x12, 0x1E, + 0x14, 0x1E, 0x14, 0x1E, 0x16, 0x1E, 0x16, 0x1E, 0x18, 0x1E, 0x18, 0x1E, 0x1A, 0x1E, 0x1A, 0x1E, + 0x1C, 0x1E, 0x1C, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x20, 0x1E, 0x20, 0x1E, 0x22, 0x1E, 0x22, 0x1E, + 0x24, 0x1E, 0x24, 0x1E, 0x26, 0x1E, 0x26, 0x1E, 0x28, 0x1E, 0x28, 0x1E, 0x2A, 0x1E, 0x2A, 0x1E, + 0x2C, 0x1E, 0x2C, 0x1E, 0x2E, 0x1E, 0x2E, 0x1E, 0x30, 0x1E, 0x30, 0x1E, 0x32, 0x1E, 0x32, 0x1E, + 0x34, 0x1E, 0x34, 0x1E, 0x36, 0x1E, 0x36, 0x1E, 0x38, 0x1E, 0x38, 0x1E, 0x3A, 0x1E, 0x3A, 0x1E, + 0x3C, 0x1E, 0x3C, 0x1E, 0x3E, 0x1E, 0x3E, 0x1E, 0x40, 0x1E, 0x40, 0x1E, 0x42, 0x1E, 0x42, 0x1E, + 0x44, 0x1E, 0x44, 0x1E, 0x46, 0x1E, 0x46, 0x1E, 0x48, 0x1E, 0x48, 0x1E, 0x4A, 0x1E, 0x4A, 0x1E, + 0x4C, 0x1E, 0x4C, 0x1E, 0x4E, 0x1E, 0x4E, 0x1E, 0x50, 0x1E, 0x50, 0x1E, 0x52, 0x1E, 0x52, 0x1E, + 0x54, 0x1E, 0x54, 0x1E, 0x56, 0x1E, 0x56, 0x1E, 0x58, 0x1E, 0x58, 0x1E, 0x5A, 0x1E, 0x5A, 0x1E, + 0x5C, 0x1E, 0x5C, 0x1E, 0x5E, 0x1E, 0x5E, 0x1E, 0x60, 0x1E, 0x60, 0x1E, 0x62, 0x1E, 0x62, 0x1E, + 0x64, 0x1E, 0x64, 0x1E, 0x66, 0x1E, 0x66, 0x1E, 0x68, 0x1E, 0x68, 0x1E, 0x6A, 0x1E, 0x6A, 0x1E, + 0x6C, 0x1E, 0x6C, 0x1E, 0x6E, 0x1E, 0x6E, 0x1E, 0x70, 0x1E, 0x70, 0x1E, 0x72, 0x1E, 0x72, 0x1E, + 0x74, 0x1E, 0x74, 0x1E, 0x76, 0x1E, 0x76, 0x1E, 0x78, 0x1E, 0x78, 0x1E, 0x7A, 0x1E, 0x7A, 0x1E, + 0x7C, 0x1E, 0x7C, 0x1E, 0x7E, 0x1E, 0x7E, 0x1E, 0x80, 0x1E, 0x80, 0x1E, 0x82, 0x1E, 0x82, 0x1E, + 0x84, 0x1E, 0x84, 0x1E, 0x86, 0x1E, 0x86, 0x1E, 0x88, 0x1E, 0x88, 0x1E, 0x8A, 0x1E, 0x8A, 0x1E, + 0x8C, 0x1E, 0x8C, 0x1E, 0x8E, 0x1E, 0x8E, 0x1E, 0x90, 0x1E, 0x90, 0x1E, 0x92, 0x1E, 0x92, 0x1E, + 0x94, 0x1E, 0x94, 0x1E, 0x96, 0x1E, 0x97, 0x1E, 0x98, 0x1E, 0x99, 0x1E, 0x9A, 0x1E, 0x9B, 0x1E, + 0x9C, 0x1E, 0x9D, 0x1E, 0x9E, 0x1E, 0x9F, 0x1E, 0xA0, 0x1E, 0xA0, 0x1E, 0xA2, 0x1E, 0xA2, 0x1E, + 0xA4, 0x1E, 0xA4, 0x1E, 0xA6, 0x1E, 0xA6, 0x1E, 0xA8, 0x1E, 0xA8, 0x1E, 0xAA, 0x1E, 0xAA, 0x1E, + 0xAC, 0x1E, 0xAC, 0x1E, 0xAE, 0x1E, 0xAE, 0x1E, 0xB0, 0x1E, 0xB0, 0x1E, 0xB2, 0x1E, 0xB2, 0x1E, + 0xB4, 0x1E, 0xB4, 0x1E, 0xB6, 0x1E, 0xB6, 0x1E, 0xB8, 0x1E, 0xB8, 0x1E, 0xBA, 0x1E, 0xBA, 0x1E, + 0xBC, 0x1E, 0xBC, 0x1E, 0xBE, 0x1E, 0xBE, 0x1E, 0xC0, 0x1E, 0xC0, 0x1E, 0xC2, 0x1E, 0xC2, 0x1E, + 0xC4, 0x1E, 0xC4, 0x1E, 0xC6, 0x1E, 0xC6, 0x1E, 0xC8, 0x1E, 0xC8, 0x1E, 0xCA, 0x1E, 0xCA, 0x1E, + 0xCC, 0x1E, 0xCC, 0x1E, 0xCE, 0x1E, 0xCE, 0x1E, 0xD0, 0x1E, 0xD0, 0x1E, 0xD2, 0x1E, 0xD2, 0x1E, + 0xD4, 0x1E, 0xD4, 0x1E, 0xD6, 0x1E, 0xD6, 0x1E, 0xD8, 0x1E, 0xD8, 0x1E, 0xDA, 0x1E, 0xDA, 0x1E, + 0xDC, 0x1E, 0xDC, 0x1E, 0xDE, 0x1E, 0xDE, 0x1E, 0xE0, 0x1E, 0xE0, 0x1E, 0xE2, 0x1E, 0xE2, 0x1E, + 0xE4, 0x1E, 0xE4, 0x1E, 0xE6, 0x1E, 0xE6, 0x1E, 0xE8, 0x1E, 0xE8, 0x1E, 0xEA, 0x1E, 0xEA, 0x1E, + 0xEC, 0x1E, 0xEC, 0x1E, 0xEE, 0x1E, 0xEE, 0x1E, 0xF0, 0x1E, 0xF0, 0x1E, 0xF2, 0x1E, 0xF2, 0x1E, + 0xF4, 0x1E, 0xF4, 0x1E, 0xF6, 0x1E, 0xF6, 0x1E, 0xF8, 0x1E, 0xF8, 0x1E, 0xFA, 0x1E, 0xFB, 0x1E, + 0xFC, 0x1E, 0xFD, 0x1E, 0xFE, 0x1E, 0xFF, 0x1E, 0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F, + 0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F, 0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F, + 0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F, 0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F, + 0x1C, 0x1F, 0x1D, 0x1F, 0x16, 0x1F, 0x17, 0x1F, 0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F, + 0x1C, 0x1F, 0x1D, 0x1F, 0x1E, 0x1F, 0x1F, 0x1F, 0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F, + 0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F, 0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F, + 0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F, 0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F, + 0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F, 0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F, + 0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F, 0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F, + 0x4C, 0x1F, 0x4D, 0x1F, 0x46, 0x1F, 0x47, 0x1F, 0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F, + 0x4C, 0x1F, 0x4D, 0x1F, 0x4E, 0x1F, 0x4F, 0x1F, 0x50, 0x1F, 0x59, 0x1F, 0x52, 0x1F, 0x5B, 0x1F, + 0x54, 0x1F, 0x5D, 0x1F, 0x56, 0x1F, 0x5F, 0x1F, 0x58, 0x1F, 0x59, 0x1F, 0x5A, 0x1F, 0x5B, 0x1F, + 0x5C, 0x1F, 0x5D, 0x1F, 0x5E, 0x1F, 0x5F, 0x1F, 0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F, + 0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F, 0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F, + 0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F, 0xBA, 0x1F, 0xBB, 0x1F, 0xC8, 0x1F, 0xC9, 0x1F, + 0xCA, 0x1F, 0xCB, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F, 0xF8, 0x1F, 0xF9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F, + 0xFA, 0x1F, 0xFB, 0x1F, 0x7E, 0x1F, 0x7F, 0x1F, 0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F, + 0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F, 0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F, + 0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F, 0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F, + 0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F, 0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F, + 0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F, 0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F, + 0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F, 0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F, + 0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F, 0xB8, 0x1F, 0xB9, 0x1F, 0xB2, 0x1F, 0xBC, 0x1F, + 0xB4, 0x1F, 0xB5, 0x1F, 0xB6, 0x1F, 0xB7, 0x1F, 0xB8, 0x1F, 0xB9, 0x1F, 0xBA, 0x1F, 0xBB, 0x1F, + 0xBC, 0x1F, 0xBD, 0x1F, 0xBE, 0x1F, 0xBF, 0x1F, 0xC0, 0x1F, 0xC1, 0x1F, 0xC2, 0x1F, 0xC3, 0x1F, + 0xC4, 0x1F, 0xC5, 0x1F, 0xC6, 0x1F, 0xC7, 0x1F, 0xC8, 0x1F, 0xC9, 0x1F, 0xCA, 0x1F, 0xCB, 0x1F, + 0xC3, 0x1F, 0xCD, 0x1F, 0xCE, 0x1F, 0xCF, 0x1F, 0xD8, 0x1F, 0xD9, 0x1F, 0xD2, 0x1F, 0xD3, 0x1F, + 0xD4, 0x1F, 0xD5, 0x1F, 0xD6, 0x1F, 0xD7, 0x1F, 0xD8, 0x1F, 0xD9, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F, + 0xDC, 0x1F, 0xDD, 0x1F, 0xDE, 0x1F, 0xDF, 0x1F, 0xE8, 0x1F, 0xE9, 0x1F, 0xE2, 0x1F, 0xE3, 0x1F, + 0xE4, 0x1F, 0xEC, 0x1F, 0xE6, 0x1F, 0xE7, 0x1F, 0xE8, 0x1F, 0xE9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F, + 0xEC, 0x1F, 0xED, 0x1F, 0xEE, 0x1F, 0xEF, 0x1F, 0xF0, 0x1F, 0xF1, 0x1F, 0xF2, 0x1F, 0xF3, 0x1F, + 0xF4, 0x1F, 0xF5, 0x1F, 0xF6, 0x1F, 0xF7, 0x1F, 0xF8, 0x1F, 0xF9, 0x1F, 0xFA, 0x1F, 0xFB, 0x1F, + 0xF3, 0x1F, 0xFD, 0x1F, 0xFE, 0x1F, 0xFF, 0x1F, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x20, + 0x04, 0x20, 0x05, 0x20, 0x06, 0x20, 0x07, 0x20, 0x08, 0x20, 0x09, 0x20, 0x0A, 0x20, 0x0B, 0x20, + 0x0C, 0x20, 0x0D, 0x20, 0x0E, 0x20, 0x0F, 0x20, 0x10, 0x20, 0x11, 0x20, 0x12, 0x20, 0x13, 0x20, + 0x14, 0x20, 0x15, 0x20, 0x16, 0x20, 0x17, 0x20, 0x18, 0x20, 0x19, 0x20, 0x1A, 0x20, 0x1B, 0x20, + 0x1C, 0x20, 0x1D, 0x20, 0x1E, 0x20, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x20, 0x22, 0x20, 0x23, 0x20, + 0x24, 0x20, 0x25, 0x20, 0x26, 0x20, 0x27, 0x20, 0x28, 0x20, 0x29, 0x20, 0x2A, 0x20, 0x2B, 0x20, + 0x2C, 0x20, 0x2D, 0x20, 0x2E, 0x20, 0x2F, 0x20, 0x30, 0x20, 0x31, 0x20, 0x32, 0x20, 0x33, 0x20, + 0x34, 0x20, 0x35, 0x20, 0x36, 0x20, 0x37, 0x20, 0x38, 0x20, 0x39, 0x20, 0x3A, 0x20, 0x3B, 0x20, + 0x3C, 0x20, 0x3D, 0x20, 0x3E, 0x20, 0x3F, 0x20, 0x40, 0x20, 0x41, 0x20, 0x42, 0x20, 0x43, 0x20, + 0x44, 0x20, 0x45, 0x20, 0x46, 0x20, 0x47, 0x20, 0x48, 0x20, 0x49, 0x20, 0x4A, 0x20, 0x4B, 0x20, + 0x4C, 0x20, 0x4D, 0x20, 0x4E, 0x20, 0x4F, 0x20, 0x50, 0x20, 0x51, 0x20, 0x52, 0x20, 0x53, 0x20, + 0x54, 0x20, 0x55, 0x20, 0x56, 0x20, 0x57, 0x20, 0x58, 0x20, 0x59, 0x20, 0x5A, 0x20, 0x5B, 0x20, + 0x5C, 0x20, 0x5D, 0x20, 0x5E, 0x20, 0x5F, 0x20, 0x60, 0x20, 0x61, 0x20, 0x62, 0x20, 0x63, 0x20, + 0x64, 0x20, 0x65, 0x20, 0x66, 0x20, 0x67, 0x20, 0x68, 0x20, 0x69, 0x20, 0x6A, 0x20, 0x6B, 0x20, + 0x6C, 0x20, 0x6D, 0x20, 0x6E, 0x20, 0x6F, 0x20, 0x70, 0x20, 0x71, 0x20, 0x72, 0x20, 0x73, 0x20, + 0x74, 0x20, 0x75, 0x20, 0x76, 0x20, 0x77, 0x20, 0x78, 0x20, 0x79, 0x20, 0x7A, 0x20, 0x7B, 0x20, + 0x7C, 0x20, 0x7D, 0x20, 0x7E, 0x20, 0x7F, 0x20, 0x80, 0x20, 0x81, 0x20, 0x82, 0x20, 0x83, 0x20, + 0x84, 0x20, 0x85, 0x20, 0x86, 0x20, 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x8A, 0x20, 0x8B, 0x20, + 0x8C, 0x20, 0x8D, 0x20, 0x8E, 0x20, 0x8F, 0x20, 0x90, 0x20, 0x91, 0x20, 0x92, 0x20, 0x93, 0x20, + 0x94, 0x20, 0x95, 0x20, 0x96, 0x20, 0x97, 0x20, 0x98, 0x20, 0x99, 0x20, 0x9A, 0x20, 0x9B, 0x20, + 0x9C, 0x20, 0x9D, 0x20, 0x9E, 0x20, 0x9F, 0x20, 0xA0, 0x20, 0xA1, 0x20, 0xA2, 0x20, 0xA3, 0x20, + 0xA4, 0x20, 0xA5, 0x20, 0xA6, 0x20, 0xA7, 0x20, 0xA8, 0x20, 0xA9, 0x20, 0xAA, 0x20, 0xAB, 0x20, + 0xAC, 0x20, 0xAD, 0x20, 0xAE, 0x20, 0xAF, 0x20, 0xB0, 0x20, 0xB1, 0x20, 0xB2, 0x20, 0xB3, 0x20, + 0xB4, 0x20, 0xB5, 0x20, 0xB6, 0x20, 0xB7, 0x20, 0xB8, 0x20, 0xB9, 0x20, 0xBA, 0x20, 0xBB, 0x20, + 0xBC, 0x20, 0xBD, 0x20, 0xBE, 0x20, 0xBF, 0x20, 0xC0, 0x20, 0xC1, 0x20, 0xC2, 0x20, 0xC3, 0x20, + 0xC4, 0x20, 0xC5, 0x20, 0xC6, 0x20, 0xC7, 0x20, 0xC8, 0x20, 0xC9, 0x20, 0xCA, 0x20, 0xCB, 0x20, + 0xCC, 0x20, 0xCD, 0x20, 0xCE, 0x20, 0xCF, 0x20, 0xD0, 0x20, 0xD1, 0x20, 0xD2, 0x20, 0xD3, 0x20, + 0xD4, 0x20, 0xD5, 0x20, 0xD6, 0x20, 0xD7, 0x20, 0xD8, 0x20, 0xD9, 0x20, 0xDA, 0x20, 0xDB, 0x20, + 0xDC, 0x20, 0xDD, 0x20, 0xDE, 0x20, 0xDF, 0x20, 0xE0, 0x20, 0xE1, 0x20, 0xE2, 0x20, 0xE3, 0x20, + 0xE4, 0x20, 0xE5, 0x20, 0xE6, 0x20, 0xE7, 0x20, 0xE8, 0x20, 0xE9, 0x20, 0xEA, 0x20, 0xEB, 0x20, + 0xEC, 0x20, 0xED, 0x20, 0xEE, 0x20, 0xEF, 0x20, 0xF0, 0x20, 0xF1, 0x20, 0xF2, 0x20, 0xF3, 0x20, + 0xF4, 0x20, 0xF5, 0x20, 0xF6, 0x20, 0xF7, 0x20, 0xF8, 0x20, 0xF9, 0x20, 0xFA, 0x20, 0xFB, 0x20, + 0xFC, 0x20, 0xFD, 0x20, 0xFE, 0x20, 0xFF, 0x20, 0x00, 0x21, 0x01, 0x21, 0x02, 0x21, 0x03, 0x21, + 0x04, 0x21, 0x05, 0x21, 0x06, 0x21, 0x07, 0x21, 0x08, 0x21, 0x09, 0x21, 0x0A, 0x21, 0x0B, 0x21, + 0x0C, 0x21, 0x0D, 0x21, 0x0E, 0x21, 0x0F, 0x21, 0x10, 0x21, 0x11, 0x21, 0x12, 0x21, 0x13, 0x21, + 0x14, 0x21, 0x15, 0x21, 0x16, 0x21, 0x17, 0x21, 0x18, 0x21, 0x19, 0x21, 0x1A, 0x21, 0x1B, 0x21, + 0x1C, 0x21, 0x1D, 0x21, 0x1E, 0x21, 0x1F, 0x21, 0x20, 0x21, 0x21, 0x21, 0x22, 0x21, 0x23, 0x21, + 0x24, 0x21, 0x25, 0x21, 0x26, 0x21, 0x27, 0x21, 0x28, 0x21, 0x29, 0x21, 0x2A, 0x21, 0x2B, 0x21, + 0x2C, 0x21, 0x2D, 0x21, 0x2E, 0x21, 0x2F, 0x21, 0x30, 0x21, 0x31, 0x21, 0x32, 0x21, 0x33, 0x21, + 0x34, 0x21, 0x35, 0x21, 0x36, 0x21, 0x37, 0x21, 0x38, 0x21, 0x39, 0x21, 0x3A, 0x21, 0x3B, 0x21, + 0x3C, 0x21, 0x3D, 0x21, 0x3E, 0x21, 0x3F, 0x21, 0x40, 0x21, 0x41, 0x21, 0x42, 0x21, 0x43, 0x21, + 0x44, 0x21, 0x45, 0x21, 0x46, 0x21, 0x47, 0x21, 0x48, 0x21, 0x49, 0x21, 0x4A, 0x21, 0x4B, 0x21, + 0x4C, 0x21, 0x4D, 0x21, 0x32, 0x21, 0x4F, 0x21, 0x50, 0x21, 0x51, 0x21, 0x52, 0x21, 0x53, 0x21, + 0x54, 0x21, 0x55, 0x21, 0x56, 0x21, 0x57, 0x21, 0x58, 0x21, 0x59, 0x21, 0x5A, 0x21, 0x5B, 0x21, + 0x5C, 0x21, 0x5D, 0x21, 0x5E, 0x21, 0x5F, 0x21, 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21, + 0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, 0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21, + 0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21, 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21, + 0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, 0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21, + 0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21, 0x80, 0x21, 0x81, 0x21, 0x82, 0x21, 0x83, 0x21, + 0x83, 0x21, 0xFF, 0xFF, 0x4B, 0x03, 0xB6, 0x24, 0xB7, 0x24, 0xB8, 0x24, 0xB9, 0x24, 0xBA, 0x24, + 0xBB, 0x24, 0xBC, 0x24, 0xBD, 0x24, 0xBE, 0x24, 0xBF, 0x24, 0xC0, 0x24, 0xC1, 0x24, 0xC2, 0x24, + 0xC3, 0x24, 0xC4, 0x24, 0xC5, 0x24, 0xC6, 0x24, 0xC7, 0x24, 0xC8, 0x24, 0xC9, 0x24, 0xCA, 0x24, + 0xCB, 0x24, 0xCC, 0x24, 0xCD, 0x24, 0xCE, 0x24, 0xCF, 0x24, 0xFF, 0xFF, 0x46, 0x07, 0x00, 0x2C, + 0x01, 0x2C, 0x02, 0x2C, 0x03, 0x2C, 0x04, 0x2C, 0x05, 0x2C, 0x06, 0x2C, 0x07, 0x2C, 0x08, 0x2C, + 0x09, 0x2C, 0x0A, 0x2C, 0x0B, 0x2C, 0x0C, 0x2C, 0x0D, 0x2C, 0x0E, 0x2C, 0x0F, 0x2C, 0x10, 0x2C, + 0x11, 0x2C, 0x12, 0x2C, 0x13, 0x2C, 0x14, 0x2C, 0x15, 0x2C, 0x16, 0x2C, 0x17, 0x2C, 0x18, 0x2C, + 0x19, 0x2C, 0x1A, 0x2C, 0x1B, 0x2C, 0x1C, 0x2C, 0x1D, 0x2C, 0x1E, 0x2C, 0x1F, 0x2C, 0x20, 0x2C, + 0x21, 0x2C, 0x22, 0x2C, 0x23, 0x2C, 0x24, 0x2C, 0x25, 0x2C, 0x26, 0x2C, 0x27, 0x2C, 0x28, 0x2C, + 0x29, 0x2C, 0x2A, 0x2C, 0x2B, 0x2C, 0x2C, 0x2C, 0x2D, 0x2C, 0x2E, 0x2C, 0x5F, 0x2C, 0x60, 0x2C, + 0x60, 0x2C, 0x62, 0x2C, 0x63, 0x2C, 0x64, 0x2C, 0x65, 0x2C, 0x66, 0x2C, 0x67, 0x2C, 0x67, 0x2C, + 0x69, 0x2C, 0x69, 0x2C, 0x6B, 0x2C, 0x6B, 0x2C, 0x6D, 0x2C, 0x6E, 0x2C, 0x6F, 0x2C, 0x70, 0x2C, + 0x71, 0x2C, 0x72, 0x2C, 0x73, 0x2C, 0x74, 0x2C, 0x75, 0x2C, 0x75, 0x2C, 0x77, 0x2C, 0x78, 0x2C, + 0x79, 0x2C, 0x7A, 0x2C, 0x7B, 0x2C, 0x7C, 0x2C, 0x7D, 0x2C, 0x7E, 0x2C, 0x7F, 0x2C, 0x80, 0x2C, + 0x80, 0x2C, 0x82, 0x2C, 0x82, 0x2C, 0x84, 0x2C, 0x84, 0x2C, 0x86, 0x2C, 0x86, 0x2C, 0x88, 0x2C, + 0x88, 0x2C, 0x8A, 0x2C, 0x8A, 0x2C, 0x8C, 0x2C, 0x8C, 0x2C, 0x8E, 0x2C, 0x8E, 0x2C, 0x90, 0x2C, + 0x90, 0x2C, 0x92, 0x2C, 0x92, 0x2C, 0x94, 0x2C, 0x94, 0x2C, 0x96, 0x2C, 0x96, 0x2C, 0x98, 0x2C, + 0x98, 0x2C, 0x9A, 0x2C, 0x9A, 0x2C, 0x9C, 0x2C, 0x9C, 0x2C, 0x9E, 0x2C, 0x9E, 0x2C, 0xA0, 0x2C, + 0xA0, 0x2C, 0xA2, 0x2C, 0xA2, 0x2C, 0xA4, 0x2C, 0xA4, 0x2C, 0xA6, 0x2C, 0xA6, 0x2C, 0xA8, 0x2C, + 0xA8, 0x2C, 0xAA, 0x2C, 0xAA, 0x2C, 0xAC, 0x2C, 0xAC, 0x2C, 0xAE, 0x2C, 0xAE, 0x2C, 0xB0, 0x2C, + 0xB0, 0x2C, 0xB2, 0x2C, 0xB2, 0x2C, 0xB4, 0x2C, 0xB4, 0x2C, 0xB6, 0x2C, 0xB6, 0x2C, 0xB8, 0x2C, + 0xB8, 0x2C, 0xBA, 0x2C, 0xBA, 0x2C, 0xBC, 0x2C, 0xBC, 0x2C, 0xBE, 0x2C, 0xBE, 0x2C, 0xC0, 0x2C, + 0xC0, 0x2C, 0xC2, 0x2C, 0xC2, 0x2C, 0xC4, 0x2C, 0xC4, 0x2C, 0xC6, 0x2C, 0xC6, 0x2C, 0xC8, 0x2C, + 0xC8, 0x2C, 0xCA, 0x2C, 0xCA, 0x2C, 0xCC, 0x2C, 0xCC, 0x2C, 0xCE, 0x2C, 0xCE, 0x2C, 0xD0, 0x2C, + 0xD0, 0x2C, 0xD2, 0x2C, 0xD2, 0x2C, 0xD4, 0x2C, 0xD4, 0x2C, 0xD6, 0x2C, 0xD6, 0x2C, 0xD8, 0x2C, + 0xD8, 0x2C, 0xDA, 0x2C, 0xDA, 0x2C, 0xDC, 0x2C, 0xDC, 0x2C, 0xDE, 0x2C, 0xDE, 0x2C, 0xE0, 0x2C, + 0xE0, 0x2C, 0xE2, 0x2C, 0xE2, 0x2C, 0xE4, 0x2C, 0xE5, 0x2C, 0xE6, 0x2C, 0xE7, 0x2C, 0xE8, 0x2C, + 0xE9, 0x2C, 0xEA, 0x2C, 0xEB, 0x2C, 0xEC, 0x2C, 0xED, 0x2C, 0xEE, 0x2C, 0xEF, 0x2C, 0xF0, 0x2C, + 0xF1, 0x2C, 0xF2, 0x2C, 0xF3, 0x2C, 0xF4, 0x2C, 0xF5, 0x2C, 0xF6, 0x2C, 0xF7, 0x2C, 0xF8, 0x2C, + 0xF9, 0x2C, 0xFA, 0x2C, 0xFB, 0x2C, 0xFC, 0x2C, 0xFD, 0x2C, 0xFE, 0x2C, 0xFF, 0x2C, 0xA0, 0x10, + 0xA1, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA4, 0x10, 0xA5, 0x10, 0xA6, 0x10, 0xA7, 0x10, 0xA8, 0x10, + 0xA9, 0x10, 0xAA, 0x10, 0xAB, 0x10, 0xAC, 0x10, 0xAD, 0x10, 0xAE, 0x10, 0xAF, 0x10, 0xB0, 0x10, + 0xB1, 0x10, 0xB2, 0x10, 0xB3, 0x10, 0xB4, 0x10, 0xB5, 0x10, 0xB6, 0x10, 0xB7, 0x10, 0xB8, 0x10, + 0xB9, 0x10, 0xBA, 0x10, 0xBB, 0x10, 0xBC, 0x10, 0xBD, 0x10, 0xBE, 0x10, 0xBF, 0x10, 0xC0, 0x10, + 0xC1, 0x10, 0xC2, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xC5, 0x10, 0xFF, 0xFF, 0x1B, 0xD2, 0x21, 0xFF, + 0x22, 0xFF, 0x23, 0xFF, 0x24, 0xFF, 0x25, 0xFF, 0x26, 0xFF, 0x27, 0xFF, 0x28, 0xFF, 0x29, 0xFF, + 0x2A, 0xFF, 0x2B, 0xFF, 0x2C, 0xFF, 0x2D, 0xFF, 0x2E, 0xFF, 0x2F, 0xFF, 0x30, 0xFF, 0x31, 0xFF, + 0x32, 0xFF, 0x33, 0xFF, 0x34, 0xFF, 0x35, 0xFF, 0x36, 0xFF, 0x37, 0xFF, 0x38, 0xFF, 0x39, 0xFF, + 0x3A, 0xFF, 0x5B, 0xFF, 0x5C, 0xFF, 0x5D, 0xFF, 0x5E, 0xFF, 0x5F, 0xFF, 0x60, 0xFF, 0x61, 0xFF, + 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, 0x66, 0xFF, 0x67, 0xFF, 0x68, 0xFF, 0x69, 0xFF, + 0x6A, 0xFF, 0x6B, 0xFF, 0x6C, 0xFF, 0x6D, 0xFF, 0x6E, 0xFF, 0x6F, 0xFF, 0x70, 0xFF, 0x71, 0xFF, + 0x72, 0xFF, 0x73, 0xFF, 0x74, 0xFF, 0x75, 0xFF, 0x76, 0xFF, 0x77, 0xFF, 0x78, 0xFF, 0x79, 0xFF, + 0x7A, 0xFF, 0x7B, 0xFF, 0x7C, 0xFF, 0x7D, 0xFF, 0x7E, 0xFF, 0x7F, 0xFF, 0x80, 0xFF, 0x81, 0xFF, + 0x82, 0xFF, 0x83, 0xFF, 0x84, 0xFF, 0x85, 0xFF, 0x86, 0xFF, 0x87, 0xFF, 0x88, 0xFF, 0x89, 0xFF, + 0x8A, 0xFF, 0x8B, 0xFF, 0x8C, 0xFF, 0x8D, 0xFF, 0x8E, 0xFF, 0x8F, 0xFF, 0x90, 0xFF, 0x91, 0xFF, + 0x92, 0xFF, 0x93, 0xFF, 0x94, 0xFF, 0x95, 0xFF, 0x96, 0xFF, 0x97, 0xFF, 0x98, 0xFF, 0x99, 0xFF, + 0x9A, 0xFF, 0x9B, 0xFF, 0x9C, 0xFF, 0x9D, 0xFF, 0x9E, 0xFF, 0x9F, 0xFF, 0xA0, 0xFF, 0xA1, 0xFF, + 0xA2, 0xFF, 0xA3, 0xFF, 0xA4, 0xFF, 0xA5, 0xFF, 0xA6, 0xFF, 0xA7, 0xFF, 0xA8, 0xFF, 0xA9, 0xFF, + 0xAA, 0xFF, 0xAB, 0xFF, 0xAC, 0xFF, 0xAD, 0xFF, 0xAE, 0xFF, 0xAF, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, + 0xB2, 0xFF, 0xB3, 0xFF, 0xB4, 0xFF, 0xB5, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB8, 0xFF, 0xB9, 0xFF, + 0xBA, 0xFF, 0xBB, 0xFF, 0xBC, 0xFF, 0xBD, 0xFF, 0xBE, 0xFF, 0xBF, 0xFF, 0xC0, 0xFF, 0xC1, 0xFF, + 0xC2, 0xFF, 0xC3, 0xFF, 0xC4, 0xFF, 0xC5, 0xFF, 0xC6, 0xFF, 0xC7, 0xFF, 0xC8, 0xFF, 0xC9, 0xFF, + 0xCA, 0xFF, 0xCB, 0xFF, 0xCC, 0xFF, 0xCD, 0xFF, 0xCE, 0xFF, 0xCF, 0xFF, 0xD0, 0xFF, 0xD1, 0xFF, + 0xD2, 0xFF, 0xD3, 0xFF, 0xD4, 0xFF, 0xD5, 0xFF, 0xD6, 0xFF, 0xD7, 0xFF, 0xD8, 0xFF, 0xD9, 0xFF, + 0xDA, 0xFF, 0xDB, 0xFF, 0xDC, 0xFF, 0xDD, 0xFF, 0xDE, 0xFF, 0xDF, 0xFF, 0xE0, 0xFF, 0xE1, 0xFF, + 0xE2, 0xFF, 0xE3, 0xFF, 0xE4, 0xFF, 0xE5, 0xFF, 0xE6, 0xFF, 0xE7, 0xFF, 0xE8, 0xFF, 0xE9, 0xFF, + 0xEA, 0xFF, 0xEB, 0xFF, 0xEC, 0xFF, 0xED, 0xFF, 0xEE, 0xFF, 0xEF, 0xFF, 0xF0, 0xFF, 0xF1, 0xFF, + 0xF2, 0xFF, 0xF3, 0xFF, 0xF4, 0xFF, 0xF5, 0xFF, 0xF6, 0xFF, 0xF7, 0xFF, 0xF8, 0xFF, 0xF9, 0xFF, + 0xFA, 0xFF, 0xFB, 0xFF, 0xFC, 0xFF, 0xFD, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF +}; + +#endif /* _UPCASE_H */ diff --git a/fs/sdfat/version.h b/fs/sdfat/version.h new file mode 100644 index 0000000000000..831475e6a0cad --- /dev/null +++ b/fs/sdfat/version.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : version.h */ +/* PURPOSE : sdFAT File Manager */ +/* */ +/************************************************************************/ +#define SDFAT_VERSION "1.4.16" diff --git a/fs/sdfat/xattr.c b/fs/sdfat/xattr.c new file mode 100644 index 0000000000000..40bb850711beb --- /dev/null +++ b/fs/sdfat/xattr.c @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : xattr.c */ +/* PURPOSE : sdFAT code for supporting xattr(Extended File Attributes) */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/* */ +/************************************************************************/ + +#include +#include +#include +#include +#include "sdfat.h" + +#ifndef CONFIG_SDFAT_VIRTUAL_XATTR_SELINUX_LABEL +#define CONFIG_SDFAT_VIRTUAL_XATTR_SELINUX_LABEL ("undefined") +#endif + +static const char default_xattr[] = CONFIG_SDFAT_VIRTUAL_XATTR_SELINUX_LABEL; + +static int can_support(const char *name) +{ + if (!name || strcmp(name, "security.selinux")) + return -1; + return 0; +} + +ssize_t sdfat_listxattr(struct dentry *dentry, char *list, size_t size) +{ + return 0; +} + + +/************************************************************************* + * INNER FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY + *************************************************************************/ +static int __sdfat_xattr_check_support(const char *name) +{ + if (can_support(name)) + return -EOPNOTSUPP; + + return 0; +} + +ssize_t __sdfat_getxattr(const char *name, void *value, size_t size) +{ + if (can_support(name)) + return -EOPNOTSUPP; + + if ((size > strlen(default_xattr)+1) && value) + strcpy(value, default_xattr); + + return strlen(default_xattr); +} + + +/************************************************************************* + * FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY + *************************************************************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0) +static int sdfat_xattr_get(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) +{ + return __sdfat_getxattr(name, buffer, size); +} + +static int sdfat_xattr_set(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, const void *value, size_t size, + int flags) +{ + return __sdfat_xattr_check_support(name); +} + +const struct xattr_handler sdfat_xattr_handler = { + .prefix = "", /* match anything */ + .get = sdfat_xattr_get, + .set = sdfat_xattr_set, +}; + +const struct xattr_handler *sdfat_xattr_handlers[] = { + &sdfat_xattr_handler, + NULL +}; + +void setup_sdfat_xattr_handler(struct super_block *sb) +{ + sb->s_xattr = sdfat_xattr_handlers; +} +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) */ +int sdfat_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) +{ + return __sdfat_xattr_check_support(name); +} + +ssize_t sdfat_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) +{ + return __sdfat_getxattr(name, value, size); +} + +int sdfat_removexattr(struct dentry *dentry, const char *name) +{ + return __sdfat_xattr_check_support(name); +} + +void setup_sdfat_xattr_handler(struct super_block *sb) +{ + /* DO NOTHING */ +} +#endif From 37dc9898c60f2558d5a5057a2f9d251c4b98f9a5 Mon Sep 17 00:00:00 2001 From: Paul Keith Date: Mon, 19 Feb 2018 20:52:10 +0100 Subject: [PATCH 494/508] fs: sdfat: Fix compilation without debugging * And make WARNON debugging optional Change-Id: Id59e908c8a60ded1238d3fd010f3d96cdde95f40 Signed-off-by: Paul Keith --- fs/sdfat/Kconfig | 5 +++++ fs/sdfat/sdfat.h | 1 + 2 files changed, 6 insertions(+) diff --git a/fs/sdfat/Kconfig b/fs/sdfat/Kconfig index 73ed755bbef61..417ff432d8ef7 100644 --- a/fs/sdfat/Kconfig +++ b/fs/sdfat/Kconfig @@ -97,6 +97,11 @@ config SDFAT_DBG_BUGON depends on SDFAT_FS && SDFAT_DEBUG default n +config SDFAT_DBG_WARNON + bool "Enable strict WARN_ON() for debugging" + depends on SDFAT_FS && SDFAT_DEBUG + default n + config SDFAT_STATISTICS bool "Enable statistics for bigdata" depends on SDFAT_FS diff --git a/fs/sdfat/sdfat.h b/fs/sdfat/sdfat.h index 2f10b9603059c..a4b7ed3e16c96 100644 --- a/fs/sdfat/sdfat.h +++ b/fs/sdfat/sdfat.h @@ -393,6 +393,7 @@ void sdfat_debug_check_clusters(struct inode *inode); #define sdfat_debug_check_clusters(inode) #define sdfat_debug_bug_on(expr) +#define sdfat_debug_warn_on(expr) #endif /* CONFIG_SDFAT_DEBUG */ From 841c6b7cad20dfa85251e1c78e8805becbcaa22e Mon Sep 17 00:00:00 2001 From: Bruno Martins Date: Wed, 14 Mar 2018 13:29:33 +0000 Subject: [PATCH 495/508] fs: sdfat: Update to driver version 2.0.6 * From Samsung package version: G960USQU1ARBG Change-Id: Ia4ba42dbd088701c23c09fbb4ba97a5654e19011 --- fs/sdfat/amap_smart.c | 77 ++++++------ fs/sdfat/amap_smart.h | 2 +- fs/sdfat/api.c | 2 +- fs/sdfat/api.h | 26 ++-- fs/sdfat/blkdev.c | 54 ++++----- fs/sdfat/cache.c | 64 +++++----- fs/sdfat/core.c | 274 +++++++++++++++++++++--------------------- fs/sdfat/core.h | 55 +++++---- fs/sdfat/core_exfat.c | 257 +++++++++++++++++++++------------------ fs/sdfat/core_fat.c | 146 +++++++++++----------- fs/sdfat/dfr.c | 25 ++-- fs/sdfat/dfr.h | 4 +- fs/sdfat/extent.c | 36 +++--- fs/sdfat/fatent.c | 24 ++-- fs/sdfat/misc.c | 7 +- fs/sdfat/sdfat.c | 13 +- fs/sdfat/sdfat.h | 4 +- fs/sdfat/statistics.c | 2 +- fs/sdfat/version.h | 2 +- 19 files changed, 555 insertions(+), 519 deletions(-) diff --git a/fs/sdfat/amap_smart.c b/fs/sdfat/amap_smart.c index 99e32a617c113..5a76bd96bd444 100644 --- a/fs/sdfat/amap_smart.c +++ b/fs/sdfat/amap_smart.c @@ -367,7 +367,7 @@ int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hid /* data start sector must be a multiple of clu_size */ if (fsi->data_start_sector & (fsi->sect_per_clus - 1)) { sdfat_msg(sb, KERN_ERR, - "misaligned data area (start sect : %u, " + "misaligned data area (start sect : %llu, " "sect_per_clus : %u) " "please re-format for performance.", fsi->data_start_sector, fsi->sect_per_clus); @@ -882,7 +882,7 @@ TARGET_AU_T *amap_get_target_au(AMAP_T *amap, int dest, int num_to_wb) } /* Put and update target AU */ -void amap_put_target_au(AMAP_T *amap, TARGET_AU_T *cur, int num_allocated) +void amap_put_target_au(AMAP_T *amap, TARGET_AU_T *cur, unsigned int num_allocated) { /* Update AMAP info vars. */ if (num_allocated > 0 && @@ -973,38 +973,34 @@ static inline int amap_skip_cluster(struct super_block *sb, TARGET_AU_T *cur, in /* AMAP-based allocation function for FAT32 */ -s32 amap_fat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p_chain, int dest) +s32 amap_fat_alloc_cluster(struct super_block *sb, u32 num_alloc, CHAIN_T *p_chain, s32 dest) { AMAP_T *amap = SDFAT_SB(sb)->fsi.amap; TARGET_AU_T *cur = NULL; AU_INFO_T *target_au = NULL; /* Allocation target AU */ + s32 ret = -ENOSPC; u32 last_clu = CLUS_EOF, read_clu; - s32 new_clu; // Max. 2G ê°œì˜ clusters - s32 num_allocated = 0, num_allocated_each = 0; + u32 new_clu, total_cnt; + u32 num_allocated = 0, num_allocated_each = 0; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); BUG_ON(!amap); BUG_ON(IS_CLUS_EOF(fsi->used_clusters)); - p_chain->dir = CLUS_EOF; - - if ((fsi->used_clusters + num_alloc) > (fsi->num_clusters - CLUS_BASE)) { - /* Reserved count management error - * or called by dir. management function on fully filled disk - */ - num_alloc = fsi->num_clusters - fsi->used_clusters - CLUS_BASE; + total_cnt = fsi->num_clusters - CLUS_BASE; - if (unlikely(num_alloc < 0)) { - sdfat_fs_error_ratelimit(sb, + if (unlikely(total_cnt < fsi->used_clusters)) { + sdfat_fs_error_ratelimit(sb, "AMAP(%s): invalid used clusters(t:%u,u:%u)\n", - __func__, fsi->num_clusters, fsi->used_clusters); - return -EIO; - } - - if (!num_alloc) - return 0; + __func__, total_cnt, fsi->used_clusters); + return -EIO; } + if (num_alloc > total_cnt - fsi->used_clusters) + return -ENOSPC; + + p_chain->dir = CLUS_EOF; + set_sb_dirty(sb); // spin_lock(&amap->amap_lock); @@ -1015,13 +1011,15 @@ s32 amap_fat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p_cha if (unlikely(!cur)) { // There is no available AU (only ignored-AU are left) sdfat_msg(sb, KERN_ERR, "AMAP Allocator: no avaialble AU."); - return 0; + goto error; } /* If there are clusters to skip */ if (cur->clu_to_skip > 0) { - if (amap_skip_cluster(sb, &amap->cur_cold, cur->clu_to_skip)) - return -EIO; + if (amap_skip_cluster(sb, &amap->cur_cold, cur->clu_to_skip)) { + ret = -EIO; + goto error; + } cur->clu_to_skip = 0; } @@ -1041,24 +1039,31 @@ s32 amap_fat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p_cha do { /* Allocate at the target AU */ if ((new_clu >= CLUS_BASE) && (new_clu < fsi->num_clusters)) { - if (fat_ent_get(sb, new_clu, &read_clu)) + if (fat_ent_get(sb, new_clu, &read_clu)) { // spin_unlock(&amap->amap_lock); - return -EIO; // goto err_and_return + ret = -EIO; + goto error; + } if (IS_CLUS_FREE(read_clu)) { BUG_ON(GET_AU(amap, i_AU_of_CLU(amap, new_clu)) != target_au); /* Free cluster found */ - if (fat_ent_set(sb, new_clu, CLUS_EOF)) - return -EIO; + if (fat_ent_set(sb, new_clu, CLUS_EOF)) { + ret = -EIO; + goto error; + } num_allocated_each++; - if (IS_CLUS_EOF(p_chain->dir)) + if (IS_CLUS_EOF(p_chain->dir)) { p_chain->dir = new_clu; - else - if (fat_ent_set(sb, last_clu, new_clu)) - return -EIO; + } else { + if (fat_ent_set(sb, last_clu, new_clu)) { + ret = -EIO; + goto error; + } + } last_clu = new_clu; /* Update au info */ @@ -1088,7 +1093,11 @@ s32 amap_fat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p_cha goto retry_alloc; // spin_unlock(&amap->amap_lock); - return num_allocated; + return 0; +error: + if (num_allocated) + fsi->fs_func->free_cluster(sb, p_chain, 0); + return ret; } @@ -1117,8 +1126,8 @@ s32 amap_release_cluster(struct super_block *sb, u32 clu) au = GET_AU(amap, i_au); if (au->free_clusters >= amap->clusters_per_au) { sdfat_fs_error(sb, "%s, au->free_clusters(%hd) is " - "greater than or equal to amap->clusters_per_au(%hd)" - , __func__, au->free_clusters, amap->clusters_per_au); + "greater than or equal to amap->clusters_per_au(%hd)", + __func__, au->free_clusters, amap->clusters_per_au); return -EIO; } diff --git a/fs/sdfat/amap_smart.h b/fs/sdfat/amap_smart.h index b628ff448df12..caee6f6b3681d 100644 --- a/fs/sdfat/amap_smart.h +++ b/fs/sdfat/amap_smart.h @@ -94,7 +94,7 @@ typedef struct __AMAP_T { int fclu_hint; /* maximum # of free clusters in an AU */ /* Hot AU list */ - int total_fclu_hot; /* Free clusters in hot list */ + unsigned int total_fclu_hot; /* Free clusters in hot list */ struct slist_head slist_hot; /* Hot AU list */ /* Ignored AU list */ diff --git a/fs/sdfat/api.c b/fs/sdfat/api.c index e1f17cc880aa6..02e0939efeecd 100644 --- a/fs/sdfat/api.c +++ b/fs/sdfat/api.c @@ -328,7 +328,7 @@ s32 fsapi_write_inode(struct inode *inode, DIR_ENTRY_T *info, int sync) EXPORT_SYMBOL(fsapi_write_inode); /* return the cluster number in the given cluster offset */ -s32 fsapi_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest) +s32 fsapi_map_clus(struct inode *inode, u32 clu_offset, u32 *clu, int dest) { s32 err; struct super_block *sb = inode->i_sb; diff --git a/fs/sdfat/api.h b/fs/sdfat/api.h index fb0bf7af5e282..0bd05d700c85e 100644 --- a/fs/sdfat/api.h +++ b/fs/sdfat/api.h @@ -119,13 +119,13 @@ typedef struct { } DATE_TIME_T; typedef struct { - u32 Offset; // start sector number of the partition - u32 Size; // in sectors + u64 Offset; // start sector number of the partition + u64 Size; // in sectors } PART_INFO_T; typedef struct { u32 SecSize; // sector size in bytes - u32 DevSize; // block device size in sectors + u64 DevSize; // block device size in sectors } DEV_INFO_T; typedef struct { @@ -139,7 +139,7 @@ typedef struct { /* directory structure */ typedef struct { u32 dir; - s32 size; + u32 size; u8 flags; } CHAIN_T; @@ -147,7 +147,7 @@ typedef struct { typedef struct { u32 clu; union { - s32 off; // cluster offset + u32 off; // cluster offset s32 eidx; // entry index }; } HINT_T; @@ -209,7 +209,7 @@ typedef struct __cache_entry { struct __cache_entry *next; struct __cache_entry *prev; } hash; - u32 sec; + u64 sec; u32 flag; struct buffer_head *bh; } cache_ent_t; @@ -223,7 +223,7 @@ typedef struct __FATENT_OPS_T { } FATENT_OPS_T; typedef struct { - s32 (*alloc_cluster)(struct super_block *, s32, CHAIN_T *, int); + s32 (*alloc_cluster)(struct super_block *, u32, CHAIN_T *, s32); s32 (*free_cluster)(struct super_block *, CHAIN_T *, s32); s32 (*count_used_clusters)(struct super_block *, u32 *); s32 (*init_dir_entry)(struct super_block *, CHAIN_T *, s32, u32, u32, u64); @@ -253,16 +253,16 @@ typedef struct __FS_INFO_T { s32 bd_opened; // opened or not u32 vol_type; // volume FAT type u32 vol_id; // volume serial number - u32 num_sectors; // num of sectors in volume + u64 num_sectors; // num of sectors in volume u32 num_clusters; // num of clusters in volume u32 cluster_size; // cluster size in bytes u32 cluster_size_bits; u32 sect_per_clus; // cluster size in sectors u32 sect_per_clus_bits; - u32 FAT1_start_sector; // FAT1 start sector - u32 FAT2_start_sector; // FAT2 start sector - u32 root_start_sector; // root dir start sector - u32 data_start_sector; // data area start sector + u64 FAT1_start_sector; // FAT1 start sector + u64 FAT2_start_sector; // FAT2 start sector + u64 root_start_sector; // root dir start sector + u64 data_start_sector; // data area start sector u32 num_FAT_sectors; // num of FAT sectors u32 root_dir; // root dir cluster u32 dentries_in_root; // num of dentries in root dir @@ -337,7 +337,7 @@ s32 fsapi_rename(struct inode *old_parent_inode, FILE_ID_T *fid, s32 fsapi_unlink(struct inode *inode, FILE_ID_T *fid); s32 fsapi_read_inode(struct inode *inode, DIR_ENTRY_T *info); s32 fsapi_write_inode(struct inode *inode, DIR_ENTRY_T *info, int sync); -s32 fsapi_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest); +s32 fsapi_map_clus(struct inode *inode, u32 clu_offset, u32 *clu, int dest); s32 fsapi_reserve_clus(struct inode *inode); /* directory management functions */ diff --git a/fs/sdfat/blkdev.c b/fs/sdfat/blkdev.c index d0f38db75e273..264c670df0f0d 100644 --- a/fs/sdfat/blkdev.c +++ b/fs/sdfat/blkdev.c @@ -106,12 +106,12 @@ s32 bdev_check_bdi_valid(struct super_block *sb) /* Make a readahead request */ -s32 bdev_readahead(struct super_block *sb, u32 secno, u32 num_secs) +s32 bdev_readahead(struct super_block *sb, u64 secno, u64 num_secs) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); u32 sects_per_page = (PAGE_SIZE >> sb->s_blocksize_bits); struct blk_plug plug; - u32 i; + u64 i; if (!fsi->bd_opened) return -EIO; @@ -120,14 +120,14 @@ s32 bdev_readahead(struct super_block *sb, u32 secno, u32 num_secs) for (i = 0; i < num_secs; i++) { if (i && !(i & (sects_per_page - 1))) blk_flush_plug(current); - sb_breadahead(sb, secno + i); + sb_breadahead(sb, (sector_t)(secno + i)); } blk_finish_plug(&plug); return 0; } -s32 bdev_mread(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 num_secs, s32 read) +s32 bdev_mread(struct super_block *sb, u64 secno, struct buffer_head **bh, u64 num_secs, s32 read) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); u8 blksize_bits = sb->s_blocksize_bits; @@ -145,9 +145,9 @@ s32 bdev_mread(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 n brelse(*bh); if (read) - *bh = __bread(sb->s_bdev, secno, num_secs << blksize_bits); + *bh = __bread(sb->s_bdev, (sector_t)secno, num_secs << blksize_bits); else - *bh = __getblk(sb->s_bdev, secno, num_secs << blksize_bits); + *bh = __getblk(sb->s_bdev, (sector_t)secno, num_secs << blksize_bits); /* read successfully */ if (*bh) @@ -165,9 +165,9 @@ s32 bdev_mread(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 n return -EIO; } -s32 bdev_mwrite(struct super_block *sb, u32 secno, struct buffer_head *bh, u32 num_secs, s32 sync) +s32 bdev_mwrite(struct super_block *sb, u64 secno, struct buffer_head *bh, u64 num_secs, s32 sync) { - s32 count; + u64 count; struct buffer_head *bh2; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); #ifdef CONFIG_SDFAT_DBG_IOCTL @@ -189,7 +189,7 @@ s32 bdev_mwrite(struct super_block *sb, u32 secno, struct buffer_head *bh, u32 n } else { count = num_secs << sb->s_blocksize_bits; - bh2 = __getblk(sb->s_bdev, secno, count); + bh2 = __getblk(sb->s_bdev, (sector_t)secno, count); if (!bh2) goto no_bh; @@ -239,39 +239,39 @@ s32 bdev_sync_all(struct super_block *sb) /* * Sector Read/Write Functions */ -s32 read_sect(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 read) +s32 read_sect(struct super_block *sb, u64 sec, struct buffer_head **bh, s32 read) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); BUG_ON(!bh); if ((sec >= fsi->num_sectors) && (fsi->num_sectors > 0)) { sdfat_fs_error_ratelimit(sb, - "%s: out of range (sect:%u)", __func__, sec); + "%s: out of range (sect:%llu)", __func__, sec); return -EIO; } if (bdev_mread(sb, sec, bh, 1, read)) { sdfat_fs_error_ratelimit(sb, - "%s: I/O error (sect:%u)", __func__, sec); + "%s: I/O error (sect:%llu)", __func__, sec); return -EIO; } return 0; } -s32 write_sect(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 sync) +s32 write_sect(struct super_block *sb, u64 sec, struct buffer_head *bh, s32 sync) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); BUG_ON(!bh); if ((sec >= fsi->num_sectors) && (fsi->num_sectors > 0)) { sdfat_fs_error_ratelimit(sb, - "%s: out of range (sect:%u)", __func__, sec); + "%s: out of range (sect:%llu)", __func__, sec); return -EIO; } if (bdev_mwrite(sb, sec, bh, 1, sync)) { - sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%u)", + sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%llu)", __func__, sec); return -EIO; } @@ -279,19 +279,19 @@ s32 write_sect(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 sync return 0; } -s32 read_msect(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 num_secs, s32 read) +s32 read_msect(struct super_block *sb, u64 sec, struct buffer_head **bh, u64 num_secs, s32 read) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); BUG_ON(!bh); if (((sec+num_secs) > fsi->num_sectors) && (fsi->num_sectors > 0)) { - sdfat_fs_error_ratelimit(sb, "%s: out of range(sect:%u len:%d)", + sdfat_fs_error_ratelimit(sb, "%s: out of range(sect:%llu len:%llu)", __func__, sec, num_secs); return -EIO; } if (bdev_mread(sb, sec, bh, num_secs, read)) { - sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%u len:%d)", + sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%llu len:%llu)", __func__, sec, num_secs); return -EIO; } @@ -299,20 +299,20 @@ s32 read_msect(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 num return 0; } -s32 write_msect(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 num_secs, s32 sync) +s32 write_msect(struct super_block *sb, u64 sec, struct buffer_head *bh, u64 num_secs, s32 sync) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); BUG_ON(!bh); if (((sec+num_secs) > fsi->num_sectors) && (fsi->num_sectors > 0)) { - sdfat_fs_error_ratelimit(sb, "%s: out of range(sect:%u len:%d)", + sdfat_fs_error_ratelimit(sb, "%s: out of range(sect:%llu len:%llu)", __func__, sec, num_secs); return -EIO; } if (bdev_mwrite(sb, sec, bh, num_secs, sync)) { - sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%u len:%d)", + sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%llu len:%llu)", __func__, sec, num_secs); return -EIO; } @@ -340,11 +340,11 @@ static inline s32 __blkdev_sync_bhs(struct buffer_head **bhs, s32 nr_bhs) return err; } -static inline s32 __buffer_zeroed(struct super_block *sb, u32 blknr, s32 num_secs) +static inline s32 __buffer_zeroed(struct super_block *sb, u64 blknr, u64 num_secs) { struct buffer_head *bhs[MAX_BUF_PER_PAGE]; s32 nr_bhs = MAX_BUF_PER_PAGE; - u32 last_blknr = blknr + num_secs; + u64 last_blknr = blknr + num_secs; s32 err, i, n; struct blk_plug plug; @@ -352,7 +352,7 @@ static inline s32 __buffer_zeroed(struct super_block *sb, u32 blknr, s32 num_sec n = 0; blk_start_plug(&plug); while (blknr < last_blknr) { - bhs[n] = sb_getblk(sb, blknr); + bhs[n] = sb_getblk(sb, (sector_t)blknr); if (!bhs[n]) { err = -ENOMEM; blk_finish_plug(&plug); @@ -389,19 +389,19 @@ static inline s32 __buffer_zeroed(struct super_block *sb, u32 blknr, s32 num_sec return 0; error: - EMSG("%s: failed zeroed sect %u\n", __func__, blknr); + EMSG("%s: failed zeroed sect %llu\n", __func__, blknr); for (i = 0; i < n; i++) bforget(bhs[i]); return err; } -s32 write_msect_zero(struct super_block *sb, u32 sec, s32 num_secs) +s32 write_msect_zero(struct super_block *sb, u64 sec, u64 num_secs) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); if (((sec+num_secs) > fsi->num_sectors) && (fsi->num_sectors > 0)) { - sdfat_fs_error_ratelimit(sb, "%s: out of range(sect:%u len:%d)", + sdfat_fs_error_ratelimit(sb, "%s: out of range(sect:%llu len:%llu)", __func__, sec, num_secs); return -EIO; } diff --git a/fs/sdfat/cache.c b/fs/sdfat/cache.c index 33901fa0ae663..f0170c5602075 100644 --- a/fs/sdfat/cache.c +++ b/fs/sdfat/cache.c @@ -53,13 +53,13 @@ /*----------------------------------------------------------------------*/ /* Cache handling function declarations */ /*----------------------------------------------------------------------*/ -static cache_ent_t *__fcache_find(struct super_block *sb, u32 sec); -static cache_ent_t *__fcache_get(struct super_block *sb, u32 sec); +static cache_ent_t *__fcache_find(struct super_block *sb, u64 sec); +static cache_ent_t *__fcache_get(struct super_block *sb); static void __fcache_insert_hash(struct super_block *sb, cache_ent_t *bp); static void __fcache_remove_hash(cache_ent_t *bp); -static cache_ent_t *__dcache_find(struct super_block *sb, u32 sec); -static cache_ent_t *__dcache_get(struct super_block *sb, u32 sec); +static cache_ent_t *__dcache_find(struct super_block *sb, u64 sec); +static cache_ent_t *__dcache_get(struct super_block *sb); static void __dcache_insert_hash(struct super_block *sb, cache_ent_t *bp); static void __dcache_remove_hash(cache_ent_t *bp); @@ -126,17 +126,17 @@ static inline void __remove_from_hash(cache_ent_t *bp) * sec: sector No. in FAT1 * bh: bh of sec. */ -static inline s32 __fat_copy(struct super_block *sb, u32 sec, struct buffer_head *bh, int sync) +static inline s32 __fat_copy(struct super_block *sb, u64 sec, struct buffer_head *bh, int sync) { #ifdef CONFIG_SDFAT_FAT_MIRRORING FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); - int sec2; + u64 sec2; if (fsi->FAT2_start_sector != fsi->FAT1_start_sector) { sec2 = sec - fsi->FAT1_start_sector + fsi->FAT2_start_sector; - BUG_ON(sec2 != (sec + fsi->num_FAT_sectors)); + BUG_ON(sec2 != (sec + (u64)fsi->num_FAT_sectors)); - MMSG("BD: fat mirroring (%d in FAT1, %d in FAT2)\n", sec, sec2); + MMSG("BD: fat mirroring (%llu in FAT1, %llu in FAT2)\n", sec, sec2); if (write_sect(sb, sec2, bh, sync)) return -EIO; } @@ -187,7 +187,7 @@ static s32 __fcache_ent_discard(struct super_block *sb, cache_ent_t *bp) return 0; } -u8 *fcache_getblk(struct super_block *sb, u32 sec) +u8 *fcache_getblk(struct super_block *sb, u64 sec) { cache_ent_t *bp; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -204,7 +204,7 @@ u8 *fcache_getblk(struct super_block *sb, u32 sec) return bp->bh->b_data; } - bp = __fcache_get(sb, sec); + bp = __fcache_get(sb); if (!__check_hash_valid(bp)) __fcache_remove_hash(bp); @@ -214,7 +214,7 @@ u8 *fcache_getblk(struct super_block *sb, u32 sec) /* Naive FAT read-ahead (increase I/O unit to page_ra_count) */ if ((sec & (page_ra_count - 1)) == 0) - bdev_readahead(sb, sec, page_ra_count); + bdev_readahead(sb, sec, (u64)page_ra_count); /* * patch 1.2.4 : buffer_head null pointer exception problem. @@ -247,13 +247,13 @@ static inline int __mark_delayed_dirty(struct super_block *sb, cache_ent_t *bp) -s32 fcache_modify(struct super_block *sb, u32 sec) +s32 fcache_modify(struct super_block *sb, u64 sec) { cache_ent_t *bp; bp = __fcache_find(sb, sec); if (!bp) { - sdfat_fs_error(sb, "Can`t find fcache (sec 0x%08x)", sec); + sdfat_fs_error(sb, "Can`t find fcache (sec 0x%016llx)", sec); return -EIO; } @@ -390,7 +390,7 @@ s32 fcache_flush(struct super_block *sb, u32 sync) return ret; } -static cache_ent_t *__fcache_find(struct super_block *sb, u32 sec) +static cache_ent_t *__fcache_find(struct super_block *sb, u64 sec) { s32 off; cache_ent_t *bp, *hp; @@ -413,7 +413,7 @@ static cache_ent_t *__fcache_find(struct super_block *sb, u32 sec) return NULL; } -static cache_ent_t *__fcache_get(struct super_block *sb, u32 sec) +static cache_ent_t *__fcache_get(struct super_block *sb) { cache_ent_t *bp; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -473,7 +473,7 @@ static void __fcache_remove_hash(cache_ent_t *bp) /* Buffer Read/Write Functions */ /*======================================================================*/ /* Read-ahead a cluster */ -s32 dcache_readahead(struct super_block *sb, u32 sec) +s32 dcache_readahead(struct super_block *sb, u64 sec) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); struct buffer_head *bh; @@ -487,7 +487,7 @@ s32 dcache_readahead(struct super_block *sb, u32 sec) return 0; if (sec < fsi->data_start_sector) { - EMSG("BD: %s: requested sector is invalid(sect:%u, root:%u)\n", + EMSG("BD: %s: requested sector is invalid(sect:%llu, root:%llu)\n", __func__, sec, fsi->data_start_sector); return -EIO; } @@ -498,7 +498,7 @@ s32 dcache_readahead(struct super_block *sb, u32 sec) bh = sb_find_get_block(sb, sec); if (!bh || !buffer_uptodate(bh)) - bdev_readahead(sb, sec, ra_count); + bdev_readahead(sb, sec, (u64)ra_count); brelse(bh); @@ -531,7 +531,7 @@ static s32 __dcache_ent_discard(struct super_block *sb, cache_ent_t *bp) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); - MMSG("%s : bp[%p] (sec:%08x flag:%08x bh:%p) list(prev:%p next:%p) " + MMSG("%s : bp[%p] (sec:%016llx flag:%08x bh:%p) list(prev:%p next:%p) " "hash(prev:%p next:%p)\n", __func__, bp, bp->sec, bp->flag, bp->bh, bp->prev, bp->next, bp->hash.prev, bp->hash.next); @@ -549,7 +549,7 @@ static s32 __dcache_ent_discard(struct super_block *sb, cache_ent_t *bp) return 0; } -u8 *dcache_getblk(struct super_block *sb, u32 sec) +u8 *dcache_getblk(struct super_block *sb, u64 sec) { cache_ent_t *bp; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -557,7 +557,7 @@ u8 *dcache_getblk(struct super_block *sb, u32 sec) bp = __dcache_find(sb, sec); if (bp) { if (bdev_check_bdi_valid(sb)) { - MMSG("%s: found cache(%p, sect:%u). But invalid BDI\n" + MMSG("%s: found cache(%p, sect:%llu). But invalid BDI\n" , __func__, bp, sec); __dcache_ent_flush(sb, bp, 0); __dcache_ent_discard(sb, bp); @@ -570,7 +570,7 @@ u8 *dcache_getblk(struct super_block *sb, u32 sec) return bp->bh->b_data; } - bp = __dcache_get(sb, sec); + bp = __dcache_get(sb); if (!__check_hash_valid(bp)) __dcache_remove_hash(bp); @@ -588,7 +588,7 @@ u8 *dcache_getblk(struct super_block *sb, u32 sec) } -s32 dcache_modify(struct super_block *sb, u32 sec) +s32 dcache_modify(struct super_block *sb, u64 sec) { s32 ret = -EIO; cache_ent_t *bp; @@ -597,7 +597,7 @@ s32 dcache_modify(struct super_block *sb, u32 sec) bp = __dcache_find(sb, sec); if (unlikely(!bp)) { - sdfat_fs_error(sb, "Can`t find dcache (sec 0x%08x)", sec); + sdfat_fs_error(sb, "Can`t find dcache (sec 0x%016llx)", sec); return -EIO; } #ifdef CONFIG_SDFAT_DELAYED_META_DIRTY @@ -609,14 +609,14 @@ s32 dcache_modify(struct super_block *sb, u32 sec) ret = write_sect(sb, sec, bp->bh, 0); if (ret) { - DMSG("%s : failed to modify buffer(err:%d, sec:%u, bp:0x%p)\n", + DMSG("%s : failed to modify buffer(err:%d, sec:%llu, bp:0x%p)\n", __func__, ret, sec, bp); } return ret; } -s32 dcache_lock(struct super_block *sb, u32 sec) +s32 dcache_lock(struct super_block *sb, u64 sec) { cache_ent_t *bp; @@ -626,11 +626,11 @@ s32 dcache_lock(struct super_block *sb, u32 sec) return 0; } - EMSG("%s : failed to lock buffer(sec:%u, bp:0x%p)\n", __func__, sec, bp); + EMSG("%s : failed to lock buffer(sec:%llu, bp:0x%p)\n", __func__, sec, bp); return -EIO; } -s32 dcache_unlock(struct super_block *sb, u32 sec) +s32 dcache_unlock(struct super_block *sb, u64 sec) { cache_ent_t *bp; @@ -640,11 +640,11 @@ s32 dcache_unlock(struct super_block *sb, u32 sec) return 0; } - EMSG("%s : failed to unlock buffer (sec:%u, bp:0x%p)\n", __func__, sec, bp); + EMSG("%s : failed to unlock buffer (sec:%llu, bp:0x%p)\n", __func__, sec, bp); return -EIO; } -s32 dcache_release(struct super_block *sb, u32 sec) +s32 dcache_release(struct super_block *sb, u64 sec) { cache_ent_t *bp; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -755,7 +755,7 @@ s32 dcache_flush(struct super_block *sb, u32 sync) return ret; } -static cache_ent_t *__dcache_find(struct super_block *sb, u32 sec) +static cache_ent_t *__dcache_find(struct super_block *sb, u64 sec) { s32 off; cache_ent_t *bp, *hp; @@ -773,7 +773,7 @@ static cache_ent_t *__dcache_find(struct super_block *sb, u32 sec) return NULL; } -static cache_ent_t *__dcache_get(struct super_block *sb, u32 sec) +static cache_ent_t *__dcache_get(struct super_block *sb) { cache_ent_t *bp; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); diff --git a/fs/sdfat/core.c b/fs/sdfat/core.c index 4384816afcf15..357eb0d54f1c9 100644 --- a/fs/sdfat/core.c +++ b/fs/sdfat/core.c @@ -229,7 +229,7 @@ static s32 fs_sync(struct super_block *sb, s32 do_sync) static s32 __clear_cluster(struct inode *inode, u32 clu) { - u32 s, n; + u64 s, n; struct super_block *sb = inode->i_sb; u32 sect_size = (u32)sb->s_blocksize; s32 ret = 0; @@ -245,7 +245,7 @@ static s32 __clear_cluster(struct inode *inode, u32 clu) } if (IS_DIRSYNC(inode)) { - ret = write_msect_zero(sb, s, (s32)fsi->sect_per_clus); + ret = write_msect_zero(sb, s, (u64)fsi->sect_per_clus); if (ret != -EAGAIN) return ret; } @@ -274,7 +274,7 @@ static s32 __clear_cluster(struct inode *inode, u32 clu) static s32 __find_last_cluster(struct super_block *sb, CHAIN_T *p_chain, u32 *ret_clu) { u32 clu, next; - s32 count = 0; + u32 count = 0; next = p_chain->dir; if (p_chain->flags == 0x03) { @@ -302,9 +302,9 @@ static s32 __find_last_cluster(struct super_block *sb, CHAIN_T *p_chain, u32 *re } -static s32 __count_num_clusters(struct super_block *sb, CHAIN_T *p_chain, s32 *ret_count) +static s32 __count_num_clusters(struct super_block *sb, CHAIN_T *p_chain, u32 *ret_count) { - s32 i, count; + u32 i, count; u32 clu; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -353,7 +353,7 @@ static void free_upcase_table(struct super_block *sb) fsi->vol_utbl = NULL; } -static s32 __load_upcase_table(struct super_block *sb, u32 sector, u32 num_sectors, u32 utbl_checksum) +static s32 __load_upcase_table(struct super_block *sb, u64 sector, u64 num_sectors, u32 utbl_checksum) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); struct buffer_head *tmp_bh = NULL; @@ -378,7 +378,7 @@ static s32 __load_upcase_table(struct super_block *sb, u32 sector, u32 num_secto while (sector < num_sectors) { ret = read_sect(sb, sector, &tmp_bh, 1); if (ret) { - EMSG("%s: failed to read sector(0x%x)\n", + EMSG("%s: failed to read sector(0x%llx)\n", __func__, sector); goto error; } @@ -511,8 +511,8 @@ static s32 __load_default_upcase_table(struct super_block *sb) static s32 load_upcase_table(struct super_block *sb) { s32 i, ret; - u32 tbl_clu, tbl_size; - u32 type, sector, num_sectors; + u32 tbl_clu, type; + u64 sector, tbl_size, num_sectors; u8 blksize_bits = sb->s_blocksize_bits; CHAIN_T clu; CASE_DENTRY_T *ep; @@ -538,10 +538,10 @@ static s32 load_upcase_table(struct super_block *sb) continue; tbl_clu = le32_to_cpu(ep->start_clu); - tbl_size = (u32) le64_to_cpu(ep->size); + tbl_size = le64_to_cpu(ep->size); sector = CLUS_TO_SECT(fsi, tbl_clu); - num_sectors = ((tbl_size-1) >> blksize_bits) + 1; + num_sectors = ((tbl_size - 1) >> blksize_bits) + 1; ret = __load_upcase_table(sb, sector, num_sectors, le32_to_cpu(ep->checksum)); @@ -566,10 +566,10 @@ static s32 load_upcase_table(struct super_block *sb) /* * Directory Entry Management Functions */ -s32 walk_fat_chain(struct super_block *sb, CHAIN_T *p_dir, s32 byte_offset, u32 *clu) +s32 walk_fat_chain(struct super_block *sb, CHAIN_T *p_dir, u32 byte_offset, u32 *clu) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); - s32 clu_offset; + u32 clu_offset; u32 cur_clu; clu_offset = byte_offset >> fsi->cluster_size_bits; @@ -597,7 +597,7 @@ s32 walk_fat_chain(struct super_block *sb, CHAIN_T *p_dir, s32 byte_offset, u32 return 0; } -static s32 find_location(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 *sector, s32 *offset) +static s32 find_location(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u64 *sector, s32 *offset) { s32 ret; u32 off, clu = 0; @@ -631,12 +631,12 @@ static s32 find_location(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 return 0; } /* end of find_location */ -DENTRY_T *get_dentry_in_dir(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 *sector) +DENTRY_T *get_dentry_in_dir(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u64 *sector) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); u32 dentries_per_page = PAGE_SIZE >> DENTRY_SIZE_BITS; s32 off; - u32 sec; + u64 sec; u8 *buf; if (p_dir->dir == DIR_DELETED) { @@ -748,7 +748,7 @@ static s32 search_empty_slot(struct super_block *sb, HINT_FEMP_T *hint_femp, CHA } } else { if ((hint_femp->eidx != -1) && - (hint_femp->count == CNT_UNUSED_HIT)) { + (hint_femp->count == CNT_UNUSED_HIT)) { /* unused empty group means * an empty group which includes * unused dentry @@ -756,7 +756,7 @@ static s32 search_empty_slot(struct super_block *sb, HINT_FEMP_T *hint_femp, CHA sdfat_fs_error(sb, "found bogus dentry(%d) " "beyond unused empty group(%d) " - "(start_clu : %u, cur_clu : %u)\n", + "(start_clu : %u, cur_clu : %u)", dentry, hint_femp->eidx, p_dir->dir, clu.dir); return -EIO; @@ -799,8 +799,9 @@ static s32 search_empty_slot(struct super_block *sb, HINT_FEMP_T *hint_femp, CHA */ static s32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, s32 num_entries) { - s32 ret, dentry; - u32 last_clu, sector; + s32 dentry; + u32 ret, last_clu; + u64 sector; u64 size = 0; CHAIN_T clu; DENTRY_T *ep = NULL; @@ -849,10 +850,8 @@ static s32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, s32 num_entries /* (1) allocate a cluster */ ret = fsi->fs_func->alloc_cluster(sb, 1, &clu, ALLOC_HOT); - if (!ret) - return -ENOSPC; - if (ret < 0) - return -EIO; + if (ret) + return ret; if (__clear_cluster(inode, clu.dir)) return -EIO; @@ -875,8 +874,8 @@ static s32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, s32 num_entries /* the special case that new dentry * should be allocated from the start of new cluster */ - hint_femp.eidx = p_dir->size << - (fsi->cluster_size_bits - DENTRY_SIZE_BITS); + hint_femp.eidx = (s32)(p_dir->size << + (fsi->cluster_size_bits - DENTRY_SIZE_BITS)); hint_femp.count = fsi->dentries_per_clu; hint_femp.cur.dir = clu.dir; @@ -1214,7 +1213,7 @@ static s32 __resolve_path(struct inode *inode, const u8 *path, CHAIN_T *p_dir, U // fid->size = i_size_read(inode); p_dir->dir = fid->start_clu; - p_dir->size = (s32)(fid->size >> fsi->cluster_size_bits); + p_dir->size = (u32)(fid->size >> fsi->cluster_size_bits); p_dir->flags = fid->flags; return 0; @@ -1232,7 +1231,8 @@ static inline s32 resolve_path_for_lookup(struct inode *inode, const u8 *path, C static s32 create_dir(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, FILE_ID_T *fid) { - s32 ret, dentry, num_entries; + s32 dentry, num_entries; + u64 ret; u64 size; CHAIN_T clu; DOS_NAME_T dos_name, dot_name; @@ -1253,18 +1253,13 @@ static s32 create_dir(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname clu.flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01; /* (0) Check if there are reserved clusters up to max. */ - if ((fsi->used_clusters != (u32) ~0) && - ((fsi->used_clusters + fsi->reserved_clusters) >= (fsi->num_clusters - 2))) + if ((fsi->used_clusters + fsi->reserved_clusters) >= (fsi->num_clusters - CLUS_BASE)) return -ENOSPC; /* (1) allocate a cluster */ ret = fsi->fs_func->alloc_cluster(sb, 1, &clu, ALLOC_HOT); - - if (!ret) - return -ENOSPC; - - if (ret < 0) - return -EIO; + if (ret) + return ret; ret = __clear_cluster(inode, clu.dir); if (ret) @@ -1325,7 +1320,7 @@ static s32 create_dir(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname fid->type = TYPE_DIR; fid->rwoffset = 0; - fid->hint_bmap.off = -1; + fid->hint_bmap.off = CLUS_EOF; /* hint_stat will be used if this is directory. */ fid->version = 0; @@ -1376,7 +1371,7 @@ static s32 create_file(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uninam fid->type = TYPE_FILE; fid->rwoffset = 0; - fid->hint_bmap.off = -1; + fid->hint_bmap.off = CLUS_EOF; /* hint_stat will be used if this is directory. */ fid->version = 0; @@ -1390,7 +1385,7 @@ static s32 create_file(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uninam static s32 remove_file(struct inode *inode, CHAIN_T *p_dir, s32 entry) { s32 num_entries; - u32 sector; + u64 sector; DENTRY_T *ep; struct super_block *sb = inode->i_sb; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -1418,7 +1413,7 @@ static s32 remove_file(struct inode *inode, CHAIN_T *p_dir, s32 entry) static s32 rename_file(struct inode *inode, CHAIN_T *p_dir, s32 oldentry, UNI_NAME_T *p_uniname, FILE_ID_T *fid) { s32 ret, newentry = -1, num_old_entries, num_new_entries; - u32 sector_old, sector_new; + u64 sector_old, sector_new; DOS_NAME_T dos_name; DENTRY_T *epold, *epnew; struct super_block *sb = inode->i_sb; @@ -1508,7 +1503,7 @@ static s32 move_file(struct inode *inode, CHAIN_T *p_olddir, s32 oldentry, CHAIN_T *p_newdir, UNI_NAME_T *p_uniname, FILE_ID_T *fid) { s32 ret, newentry, num_new_entries, num_old_entries; - u32 sector_mov, sector_new; + u64 sector_mov, sector_new; CHAIN_T clu; DOS_NAME_T dos_name; DENTRY_T *epmov, *epnew; @@ -1800,14 +1795,14 @@ s32 fscore_mount(struct super_block *sb) /* warn misaligned data data start sector must be a multiple of clu_size */ sdfat_log_msg(sb, KERN_INFO, "detected volume info : %s " - "(bps : %lu, spc : %u, data start : %u, %s)", + "(bps : %lu, spc : %u, data start : %llu, %s)", sdfat_get_vol_type_str(fsi->vol_type), sb->s_blocksize, fsi->sect_per_clus, fsi->data_start_sector, (fsi->data_start_sector & (fsi->sect_per_clus - 1)) ? "misaligned" : "aligned"); sdfat_log_msg(sb, KERN_INFO, - "detected volume size : %u MB (disk_size : %llu MB)", + "detected volume size : %llu MB (disk_size : %llu MB)", fsi->num_sectors >> 11, disk ? (u64)((disk->part0.nr_sects) >> 11) : 0); @@ -1818,7 +1813,7 @@ s32 fscore_mount(struct super_block *sb) } if (fsi->vol_type != EXFAT) - goto success; + goto update_used_clus; /* allocate-bitmap is only for exFAT */ ret = load_alloc_bmp(sb); @@ -1826,8 +1821,20 @@ s32 fscore_mount(struct super_block *sb) sdfat_log_msg(sb, KERN_ERR, "failed to load alloc-bitmap"); goto free_upcase; } -success: + +update_used_clus: + if (fsi->used_clusters == (u32) ~0) { + ret = fsi->fs_func->count_used_clusters(sb, &fsi->used_clusters); + if (ret) { + sdfat_log_msg(sb, KERN_ERR, "failed to scan clusters"); + goto free_alloc_bmp; + } + } + return 0; +free_alloc_bmp: + if (fsi->vol_type == EXFAT) + free_alloc_bmp(sb); free_upcase: free_upcase_table(sb); bd_close: @@ -1963,7 +1970,7 @@ s32 fscore_lookup(struct inode *inode, u8 *path, FILE_ID_T *fid) if (unlikely(dentry == -EEXIST)) { fid->type = TYPE_DIR; fid->rwoffset = 0; - fid->hint_bmap.off = -1; + fid->hint_bmap.off = CLUS_EOF; fid->attr = ATTR_SUBDIR; fid->flags = 0x01; @@ -1984,7 +1991,7 @@ s32 fscore_lookup(struct inode *inode, u8 *path, FILE_ID_T *fid) fid->type = fsi->fs_func->get_entry_type(ep); fid->rwoffset = 0; - fid->hint_bmap.off = -1; + fid->hint_bmap.off = CLUS_EOF; fid->attr = fsi->fs_func->get_entry_attr(ep); fid->size = fsi->fs_func->get_entry_size(ep2); @@ -1997,7 +2004,7 @@ s32 fscore_lookup(struct inode *inode, u8 *path, FILE_ID_T *fid) } if ((fid->type == TYPE_DIR) && (fsi->vol_type != EXFAT)) { - s32 num_clu = 0; + u32 num_clu = 0; CHAIN_T tmp_dir; tmp_dir.dir = fid->start_clu; @@ -2061,9 +2068,10 @@ s32 fscore_create(struct inode *inode, u8 *path, u8 mode, FILE_ID_T *fid) s32 fscore_read_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *rcount) { s32 ret = 0; - s32 offset, sec_offset, clu_offset; - u32 clu, LogSector; - u64 oneblkread, read_bytes; + s32 offset, sec_offset; + u32 clu_offset; + u32 clu; + u64 logsector, oneblkread, read_bytes; struct buffer_head *tmp_bh = NULL; struct super_block *sb = inode->i_sb; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -2087,14 +2095,15 @@ s32 fscore_read_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 coun read_bytes = 0; while (count > 0) { - clu_offset = (s32)(fid->rwoffset >> fsi->cluster_size_bits); + clu_offset = fid->rwoffset >> fsi->cluster_size_bits; clu = fid->start_clu; if (fid->flags == 0x03) { clu += clu_offset; } else { /* hint information */ - if ((clu_offset > 0) && (fid->hint_bmap.off > 0) && + if ((clu_offset > 0) && + ((fid->hint_bmap.off != CLUS_EOF) && (fid->hint_bmap.off > 0)) && (clu_offset >= fid->hint_bmap.off)) { clu_offset -= fid->hint_bmap.off; clu = fid->hint_bmap.clu; @@ -2110,26 +2119,26 @@ s32 fscore_read_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 coun } /* hint information */ - fid->hint_bmap.off = (s32)(fid->rwoffset >> fsi->cluster_size_bits); + fid->hint_bmap.off = fid->rwoffset >> fsi->cluster_size_bits; fid->hint_bmap.clu = clu; offset = (s32)(fid->rwoffset & (fsi->cluster_size - 1)); /* byte offset in cluster */ sec_offset = offset >> sb->s_blocksize_bits; /* sector offset in cluster */ offset &= (sb->s_blocksize - 1); /* byte offset in sector */ - LogSector = CLUS_TO_SECT(fsi, clu) + sec_offset; + logsector = CLUS_TO_SECT(fsi, clu) + sec_offset; oneblkread = (u64)(sb->s_blocksize - offset); if (oneblkread > count) oneblkread = count; if ((offset == 0) && (oneblkread == sb->s_blocksize)) { - ret = read_sect(sb, LogSector, &tmp_bh, 1); + ret = read_sect(sb, logsector, &tmp_bh, 1); if (ret) goto err_out; memcpy(((s8 *) buffer)+read_bytes, ((s8 *) tmp_bh->b_data), (s32) oneblkread); } else { - ret = read_sect(sb, LogSector, &tmp_bh, 1); + ret = read_sect(sb, logsector, &tmp_bh, 1); if (ret) goto err_out; memcpy(((s8 *) buffer)+read_bytes, ((s8 *) tmp_bh->b_data)+offset, (s32) oneblkread); @@ -2153,10 +2162,10 @@ s32 fscore_read_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 coun s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *wcount) { s32 ret = 0; - s32 modified = false, offset, sec_offset, clu_offset; - s32 num_clusters, num_alloc, num_alloced = (s32) ~0; - u32 clu, last_clu, LogSector, sector; - u64 oneblkwrite, write_bytes; + s32 modified = false, offset, sec_offset; + u32 clu_offset, num_clusters, num_alloc; + u32 clu, last_clu; + u64 logsector, sector, oneblkwrite, write_bytes; CHAIN_T new_clu; TIMESTAMP_T tm; DENTRY_T *ep, *ep2; @@ -2186,12 +2195,12 @@ s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 cou if (fid->size == 0) num_clusters = 0; else - num_clusters = (s32)((fid->size-1) >> fsi->cluster_size_bits) + 1; + num_clusters = ((fid->size-1) >> fsi->cluster_size_bits) + 1; write_bytes = 0; while (count > 0) { - clu_offset = (s32)(fid->rwoffset >> fsi->cluster_size_bits); + clu_offset = (fid->rwoffset >> fsi->cluster_size_bits); clu = last_clu = fid->start_clu; if (fid->flags == 0x03) { @@ -2205,7 +2214,8 @@ s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 cou } } else { /* hint information */ - if ((clu_offset > 0) && (fid->hint_bmap.off > 0) && + if ((clu_offset > 0) && + ((fid->hint_bmap.off != CLUS_EOF) && (fid->hint_bmap.off > 0)) && (clu_offset >= fid->hint_bmap.off)) { clu_offset -= fid->hint_bmap.off; clu = fid->hint_bmap.clu; @@ -2222,20 +2232,15 @@ s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 cou } if (IS_CLUS_EOF(clu)) { - num_alloc = (s32)((count-1) >> fsi->cluster_size_bits) + 1; + num_alloc = ((count-1) >> fsi->cluster_size_bits) + 1; new_clu.dir = IS_CLUS_EOF(last_clu) ? CLUS_EOF : last_clu+1; new_clu.size = 0; new_clu.flags = fid->flags; /* (1) allocate a chain of clusters */ - num_alloced = fsi->fs_func->alloc_cluster(sb, num_alloc, &new_clu, ALLOC_COLD); - if (!num_alloced) - break; - - if (num_alloced < 0) { - ret = -EIO; + ret = fsi->fs_func->alloc_cluster(sb, num_alloc, &new_clu, ALLOC_COLD); + if (ret) goto err_out; - } /* (2) append to the FAT chain */ if (IS_CLUS_EOF(last_clu)) { @@ -2260,12 +2265,12 @@ s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 cou } } - num_clusters += num_alloced; + num_clusters += num_alloc; clu = new_clu.dir; } /* hint information */ - fid->hint_bmap.off = (s32)(fid->rwoffset >> fsi->cluster_size_bits); + fid->hint_bmap.off = fid->rwoffset >> fsi->cluster_size_bits; fid->hint_bmap.clu = clu; /* byte offset in cluster */ @@ -2274,14 +2279,14 @@ s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 cou sec_offset = offset >> blksize_bits; /* byte offset in sector */ offset &= blksize_mask; - LogSector = CLUS_TO_SECT(fsi, clu) + sec_offset; + logsector = CLUS_TO_SECT(fsi, clu) + sec_offset; oneblkwrite = (u64)(blksize - offset); if (oneblkwrite > count) oneblkwrite = count; if ((offset == 0) && (oneblkwrite == blksize)) { - ret = read_sect(sb, LogSector, &tmp_bh, 0); + ret = read_sect(sb, logsector, &tmp_bh, 0); if (ret) goto err_out; @@ -2289,24 +2294,24 @@ s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 cou ((s8 *)buffer)+write_bytes, (s32)oneblkwrite); - ret = write_sect(sb, LogSector, tmp_bh, 0); + ret = write_sect(sb, logsector, tmp_bh, 0); if (ret) { brelse(tmp_bh); goto err_out; } } else { if ((offset > 0) || ((fid->rwoffset+oneblkwrite) < fid->size)) { - ret = read_sect(sb, LogSector, &tmp_bh, 1); + ret = read_sect(sb, logsector, &tmp_bh, 1); if (ret) goto err_out; } else { - ret = read_sect(sb, LogSector, &tmp_bh, 0); + ret = read_sect(sb, logsector, &tmp_bh, 0); if (ret) goto err_out; } memcpy(((s8 *) tmp_bh->b_data)+offset, ((s8 *) buffer)+write_bytes, (s32) oneblkwrite); - ret = write_sect(sb, LogSector, tmp_bh, 0); + ret = write_sect(sb, logsector, tmp_bh, 0); if (ret) { brelse(tmp_bh); goto err_out; @@ -2380,17 +2385,15 @@ s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 cou if (wcount) *wcount = write_bytes; - if (!num_alloced) - return -ENOSPC; - return ret; } /* end of fscore_write_link */ /* resize the file length */ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size) { - s32 num_clusters_new, num_clusters_da, num_clusters_phys; - u32 last_clu = CLUS_FREE, sector; + u32 num_clusters_new, num_clusters_da, num_clusters_phys; + u32 last_clu = CLUS_FREE; + u64 sector; CHAIN_T clu; TIMESTAMP_T tm; DENTRY_T *ep, *ep2; @@ -2428,7 +2431,7 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size) fs_set_vol_flags(sb, VOL_DIRTY); /* Reserved count update */ - #define num_clusters(v) ((v) ? (s32)(((v) - 1) >> fsi->cluster_size_bits) + 1 : 0) + #define num_clusters(v) ((v) ? (u32)(((v) - 1) >> fsi->cluster_size_bits) + 1 : 0) num_clusters_da = num_clusters(SDFAT_I(inode)->i_size_aligned); num_clusters_new = num_clusters(i_size_read(inode)); num_clusters_phys = num_clusters(SDFAT_I(inode)->i_size_ondisk); @@ -2454,7 +2457,7 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size) clu.dir = fid->start_clu; /* In no-da case, num_clusters_phys is equal to below value - * clu.size = (s32)((old_size-1) >> fsi->cluster_size_bits) + 1; + * clu.size = (u32)((old_size-1) >> fsi->cluster_size_bits) + 1; */ clu.size = num_clusters_phys; clu.flags = fid->flags; @@ -2466,7 +2469,7 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size) /* Truncate FAT chain num_clusters after the first cluster * num_clusters = min(new, phys); */ - s32 num_clusters = (num_clusters_new < num_clusters_phys) ? + u32 num_clusters = (num_clusters_new < num_clusters_phys) ? num_clusters_new : num_clusters_phys; /* Follow FAT chain @@ -2480,7 +2483,7 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size) * when find target cluster in cache. */ } else if (fid->type == TYPE_FILE) { - s32 fclus = 0; + u32 fclus = 0; s32 err = extent_get_clus(inode, num_clusters, &fclus, &(clu.dir), &last_clu, 0); if (err) @@ -2488,7 +2491,7 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size) ASSERT(fclus == num_clusters); if ((num_clusters > 1) && (last_clu == fid->start_clu)) { - s32 fclus_tmp = 0; + u32 fclus_tmp = 0; u32 temp = 0; err = extent_get_clus(inode, num_clusters - 1, @@ -2528,7 +2531,6 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size) fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01; fid->start_clu = CLUS_EOF; } - BUG_ON(clu.size < 0); fid->size = new_size; if (fid->type == TYPE_FILE) @@ -2600,7 +2602,7 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size) extent_cache_inval_inode(inode); /* hint information */ - fid->hint_bmap.off = -1; + fid->hint_bmap.off = CLUS_EOF; fid->hint_bmap.clu = CLUS_EOF; if (fid->rwoffset > fid->size) fid->rwoffset = fid->size; @@ -2726,7 +2728,7 @@ s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid, CHAIN_T new_clu; new_clu.dir = new_fid->start_clu; - new_clu.size = (s32)((new_fid->size-1) >> fsi->cluster_size_bits) + 1; + new_clu.size = ((new_fid->size-1) >> fsi->cluster_size_bits) + 1; new_clu.flags = new_fid->flags; ret = check_dir_empty(sb, &new_clu); @@ -2773,7 +2775,7 @@ s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid, CHAIN_T new_clu_to_free; new_clu_to_free.dir = new_fid->start_clu; - new_clu_to_free.size = (s32)((new_fid->size-1) >> fsi->cluster_size_bits) + 1; + new_clu_to_free.size = ((new_fid->size-1) >> fsi->cluster_size_bits) + 1; new_clu_to_free.flags = new_fid->flags; if (fsi->fs_func->free_cluster(sb, &new_clu_to_free, 1)) { @@ -2838,7 +2840,7 @@ s32 fscore_remove(struct inode *inode, FILE_ID_T *fid) goto out; clu_to_free.dir = fid->start_clu; - clu_to_free.size = (s32)((fid->size-1) >> fsi->cluster_size_bits) + 1; + clu_to_free.size = ((fid->size-1) >> fsi->cluster_size_bits) + 1; clu_to_free.flags = fid->flags; /* (2) invalidate extent cache and free the clusters @@ -2871,7 +2873,7 @@ s32 fscore_remove(struct inode *inode, FILE_ID_T *fid) */ s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info) { - u32 sector; + u64 sector; s32 count; CHAIN_T dir; TIMESTAMP_T tm; @@ -2903,7 +2905,7 @@ s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info) if (IS_CLUS_FREE(fsi->root_dir)) { info->Size = fsi->dentries_in_root << DENTRY_SIZE_BITS; } else { - s32 num_clu; + u32 num_clu; if (__count_num_clusters(sb, &dir, &num_clu)) return -EIO; @@ -3016,7 +3018,7 @@ s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info) s32 fscore_write_inode(struct inode *inode, DIR_ENTRY_T *info, s32 sync) { s32 ret = -EIO; - u32 sector; + u64 sector; TIMESTAMP_T tm; DENTRY_T *ep, *ep2; ENTRY_SET_CACHE_T *es = NULL; @@ -3106,32 +3108,37 @@ s32 fscore_write_inode(struct inode *inode, DIR_ENTRY_T *info, s32 sync) * Output: errcode, cluster number * *clu = (~0), if it's unable to allocate a new cluster */ -s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest) +s32 fscore_map_clus(struct inode *inode, u32 clu_offset, u32 *clu, int dest) { - s32 num_clusters, num_alloced, num_to_be_allocated, modified = false; - u32 last_clu, sector; + s32 ret, modified = false; + u32 last_clu; + u64 sector; CHAIN_T new_clu; DENTRY_T *ep; ENTRY_SET_CACHE_T *es = NULL; struct super_block *sb = inode->i_sb; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); FILE_ID_T *fid = &(SDFAT_I(inode)->fid); - s32 local_clu_offset = clu_offset; + u32 local_clu_offset = clu_offset; s32 reserved_clusters = fsi->reserved_clusters; + u32 num_to_be_allocated = 0, num_clusters = 0; fid->rwoffset = (s64)(clu_offset) << fsi->cluster_size_bits; - if (SDFAT_I(inode)->i_size_ondisk == 0) - num_clusters = 0; - else - num_clusters = (s32)((SDFAT_I(inode)->i_size_ondisk-1) >> fsi->cluster_size_bits) + 1; + if (SDFAT_I(inode)->i_size_ondisk > 0) + num_clusters = (u32)((SDFAT_I(inode)->i_size_ondisk-1) >> fsi->cluster_size_bits) + 1; + + if (clu_offset >= num_clusters) + num_to_be_allocated = clu_offset - num_clusters + 1; - num_to_be_allocated = clu_offset - num_clusters + 1; if ((dest == ALLOC_NOWHERE) && (num_to_be_allocated > 0)) { *clu = CLUS_EOF; return 0; } + /* check always request cluster is 1 */ + //ASSERT(num_to_be_allocated == 1); + sdfat_debug_check_clusters(inode); *clu = last_clu = fid->start_clu; @@ -3149,7 +3156,7 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest) *clu += clu_offset; } } else if (fid->type == TYPE_FILE) { - s32 fclus = 0; + u32 fclus = 0; s32 err = extent_get_clus(inode, clu_offset, &fclus, clu, &last_clu, 1); if (err) @@ -3158,7 +3165,8 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest) clu_offset -= fclus; } else { /* hint information */ - if ((clu_offset > 0) && (fid->hint_bmap.off > 0) && + if ((clu_offset > 0) && + ((fid->hint_bmap.off != CLUS_EOF) && (fid->hint_bmap.off > 0)) && (clu_offset >= fid->hint_bmap.off)) { clu_offset -= fid->hint_bmap.off; /* hint_bmap.clu should be valid */ @@ -3187,7 +3195,7 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest) EMSG("%s: invalid fat chain : inode(%p) " "num_to_be_allocated(%d) " "i_size_ondisk(%lld) fid->flags(%02x) " - "fid->start(%08x) fid->hint_off(%d) " + "fid->start(%08x) fid->hint_off(%u) " "fid->hint_clu(%u) fid->rwoffset(%llu) " "modified_clu_off(%d) last_clu(%08x) " "new_clu(%08x)", __func__, inode, @@ -3201,19 +3209,9 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest) return -EIO; } - num_alloced = fsi->fs_func->alloc_cluster(sb, num_to_be_allocated, &new_clu, ALLOC_COLD); - if (num_alloced < 0) { - return -EIO; - } else if (num_alloced < num_to_be_allocated) { - if (num_to_be_allocated == 1) { - ASSERT(!num_alloced); - } else { - DMSG("%s : ENOSPC (requested:%d, alloced:%d)\n", - __func__, num_alloced, - num_to_be_allocated); - } - return -ENOSPC; - } + ret = fsi->fs_func->alloc_cluster(sb, num_to_be_allocated, &new_clu, ALLOC_COLD); + if (ret) + return ret; if (IS_CLUS_EOF(new_clu.dir) || IS_CLUS_FREE(new_clu.dir)) { sdfat_fs_error(sb, "bogus cluster new allocated" @@ -3226,8 +3224,8 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest) /* Reserved cluster dec. */ // XXX: Inode DA flag needed if (SDFAT_SB(sb)->options.improved_allocation & SDFAT_ALLOC_DELAY) { - BUG_ON(reserved_clusters < num_alloced); - reserved_clusters -= num_alloced; + BUG_ON(reserved_clusters < num_to_be_allocated); + reserved_clusters -= num_to_be_allocated; } @@ -3251,7 +3249,7 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest) return -EIO; } - num_clusters += num_alloced; + num_clusters += num_to_be_allocated; *clu = new_clu.dir; if (fid->dir.dir != DIR_DELETED) { @@ -3297,7 +3295,7 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest) /* add number of new blocks to inode (non-DA only) */ if (!(SDFAT_SB(sb)->options.improved_allocation & SDFAT_ALLOC_DELAY)) { - inode->i_blocks += num_alloced << (fsi->cluster_size_bits - sb->s_blocksize_bits); + inode->i_blocks += num_to_be_allocated << (fsi->cluster_size_bits - sb->s_blocksize_bits); } else { // DAì˜ ê²½ìš°, i_blocksê°€ ì´ë¯¸ ì¦ê°€í•´ìžˆì–´ì•¼ 함. BUG_ON(clu_offset >= (inode->i_blocks >> (fsi->cluster_size_bits - sb->s_blocksize_bits))); @@ -3339,12 +3337,6 @@ s32 fscore_reserve_clus(struct inode *inode) struct super_block *sb = inode->i_sb; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); - /* used cluster check */ - if (fsi->used_clusters == (u32) ~0) { - if (fsi->fs_func->count_used_clusters(sb, &fsi->used_clusters)) - return -EIO; - } - if ((fsi->used_clusters + fsi->reserved_clusters) >= (fsi->num_clusters - 2)) return -ENOSPC; @@ -3437,9 +3429,10 @@ s32 fscore_mkdir(struct inode *inode, u8 *path, FILE_ID_T *fid) /* read a directory entry from the opened directory */ s32 fscore_readdir(struct inode *inode, DIR_ENTRY_T *dir_entry) { - s32 i, clu_offset; + s32 i; s32 dentries_per_clu, dentries_per_clu_bits = 0; - u32 type, sector; + u32 type, clu_offset; + u64 sector; CHAIN_T dir, clu; UNI_NAME_T uni_name; TIMESTAMP_T tm; @@ -3447,7 +3440,7 @@ s32 fscore_readdir(struct inode *inode, DIR_ENTRY_T *dir_entry) struct super_block *sb = inode->i_sb; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); FILE_ID_T *fid = &(SDFAT_I(inode)->fid); - s32 dentry = (s32) fid->rwoffset; + u32 dentry = (u32)(fid->rwoffset & 0xFFFFFFFF); /* u32 is enough for directory */ /* check if the given file ID is opened */ if (fid->type != TYPE_DIR) @@ -3459,7 +3452,7 @@ s32 fscore_readdir(struct inode *inode, DIR_ENTRY_T *dir_entry) dir.flags = 0x01; } else { dir.dir = fid->start_clu; - dir.size = (s32)(fid->size >> fsi->cluster_size_bits); + dir.size = fid->size >> fsi->cluster_size_bits; dir.flags = fid->flags; sdfat_debug_bug_on(dentry >= (dir.size * fsi->dentries_per_clu)); } @@ -3489,7 +3482,8 @@ s32 fscore_readdir(struct inode *inode, DIR_ENTRY_T *dir_entry) clu.size -= clu_offset; } else { /* hint_information */ - if ((clu_offset > 0) && (fid->hint_bmap.off > 0) && + if ((clu_offset > 0) && + ((fid->hint_bmap.off != CLUS_EOF) && (fid->hint_bmap.off > 0)) && (clu_offset >= fid->hint_bmap.off)) { clu_offset -= fid->hint_bmap.off; clu.dir = fid->hint_bmap.clu; @@ -3599,7 +3593,7 @@ s32 fscore_readdir(struct inode *inode, DIR_ENTRY_T *dir_entry) dir_entry->NameBuf.lfn[0] = '\0'; - fid->rwoffset = (s64) dentry; + fid->rwoffset = (s64)dentry; return 0; } /* end of fscore_readdir */ @@ -3641,7 +3635,7 @@ s32 fscore_rmdir(struct inode *inode, FILE_ID_T *fid) #endif clu_to_free.dir = fid->start_clu; - clu_to_free.size = (s32)((fid->size-1) >> fsi->cluster_size_bits) + 1; + clu_to_free.size = ((fid->size-1) >> fsi->cluster_size_bits) + 1; clu_to_free.flags = fid->flags; ret = check_dir_empty(sb, &clu_to_free); diff --git a/fs/sdfat/core.h b/fs/sdfat/core.h index 303f02d987210..00ea2c5e26032 100644 --- a/fs/sdfat/core.h +++ b/fs/sdfat/core.h @@ -53,12 +53,11 @@ extern "C" { #define ES_ALL_ENTRIES 0 typedef struct { - u32 sector; // sector number that contains file_entry - s32 offset; // byte offset in the sector - s32 alloc_flag; // flag in stream entry. 01 for cluster chain, 03 for contig. clusteres. - u32 num_entries; - // __buf should be the last member - void *__buf; + u64 sector; // sector number that contains file_entry + u32 offset; // byte offset in the sector + s32 alloc_flag; // flag in stream entry. 01 for cluster chain, 03 for contig. clusters. + u32 num_entries; + void *__buf; // __buf should be the last member } ENTRY_SET_CACHE_T; @@ -72,7 +71,7 @@ s32 fscore_init(void); s32 fscore_shutdown(void); /* chain management */ -s32 chain_cont_cluster(struct super_block *sb, u32 chain, s32 len); +s32 chain_cont_cluster(struct super_block *sb, u32 chain, u32 len); /* volume management functions */ s32 fscore_mount(struct super_block *sb); @@ -93,7 +92,7 @@ s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid, s32 fscore_remove(struct inode *inode, FILE_ID_T *fid); s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info); s32 fscore_write_inode(struct inode *inode, DIR_ENTRY_T *info, int sync); -s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest); +s32 fscore_map_clus(struct inode *inode, u32 clu_offset, u32 *clu, int dest); s32 fscore_reserve_clus(struct inode *inode); s32 fscore_unlink(struct inode *inode, FILE_ID_T *fid); @@ -109,30 +108,30 @@ s32 fscore_rmdir(struct inode *inode, FILE_ID_T *fid); /* core.c : core code for common */ /* dir entry management functions */ -DENTRY_T *get_dentry_in_dir(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 *sector); +DENTRY_T *get_dentry_in_dir(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u64 *sector); /* name conversion functions */ void get_uniname_from_dos_entry(struct super_block *sb, DOS_DENTRY_T *ep, UNI_NAME_T *p_uniname, u8 mode); /* file operation functions */ -s32 walk_fat_chain(struct super_block *sb, CHAIN_T *p_dir, s32 byte_offset, u32 *clu); +s32 walk_fat_chain(struct super_block *sb, CHAIN_T *p_dir, u32 byte_offset, u32 *clu); /* sdfat/cache.c */ s32 meta_cache_init(struct super_block *sb); s32 meta_cache_shutdown(struct super_block *sb); -u8 *fcache_getblk(struct super_block *sb, u32 sec); -s32 fcache_modify(struct super_block *sb, u32 sec); +u8 *fcache_getblk(struct super_block *sb, u64 sec); +s32 fcache_modify(struct super_block *sb, u64 sec); s32 fcache_release_all(struct super_block *sb); s32 fcache_flush(struct super_block *sb, u32 sync); -u8 *dcache_getblk(struct super_block *sb, u32 sec); -s32 dcache_modify(struct super_block *sb, u32 sec); -s32 dcache_lock(struct super_block *sb, u32 sec); -s32 dcache_unlock(struct super_block *sb, u32 sec); -s32 dcache_release(struct super_block *sb, u32 sec); +u8 *dcache_getblk(struct super_block *sb, u64 sec); +s32 dcache_modify(struct super_block *sb, u64 sec); +s32 dcache_lock(struct super_block *sb, u64 sec); +s32 dcache_unlock(struct super_block *sb, u64 sec); +s32 dcache_release(struct super_block *sb, u64 sec); s32 dcache_release_all(struct super_block *sb); s32 dcache_flush(struct super_block *sb, u32 sync); -s32 dcache_readahead(struct super_block *sb, u32 sec); +s32 dcache_readahead(struct super_block *sb, u64 sec); /* fatent.c */ @@ -163,7 +162,7 @@ int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hid void amap_destroy(struct super_block *sb); /* amap_smart.c : (de)allocation functions */ -s32 amap_fat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p_chain, int dest); +s32 amap_fat_alloc_cluster(struct super_block *sb, u32 num_alloc, CHAIN_T *p_chain, s32 dest); s32 amap_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_relse);/* Not impelmented */ s32 amap_release_cluster(struct super_block *sb, u32 clu); /* Only update AMAP */ @@ -182,17 +181,17 @@ u32 amap_get_au_stat(struct super_block *sb, s32 mode); s32 bdev_open_dev(struct super_block *sb); s32 bdev_close_dev(struct super_block *sb); s32 bdev_check_bdi_valid(struct super_block *sb); -s32 bdev_readahead(struct super_block *sb, u32 secno, u32 num_secs); -s32 bdev_mread(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 num_secs, s32 read); -s32 bdev_mwrite(struct super_block *sb, u32 secno, struct buffer_head *bh, u32 num_secs, s32 sync); +s32 bdev_readahead(struct super_block *sb, u64 secno, u64 num_secs); +s32 bdev_mread(struct super_block *sb, u64 secno, struct buffer_head **bh, u64 num_secs, s32 read); +s32 bdev_mwrite(struct super_block *sb, u64 secno, struct buffer_head *bh, u64 num_secs, s32 sync); s32 bdev_sync_all(struct super_block *sb); /* blkdev.c : sector read/write functions */ -s32 read_sect(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 read); -s32 write_sect(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 sync); -s32 read_msect(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 num_secs, s32 read); -s32 write_msect(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 num_secs, s32 sync); -s32 write_msect_zero(struct super_block *sb, u32 sec, s32 num_secs); +s32 read_sect(struct super_block *sb, u64 sec, struct buffer_head **bh, s32 read); +s32 write_sect(struct super_block *sb, u64 sec, struct buffer_head *bh, s32 sync); +s32 read_msect(struct super_block *sb, u64 sec, struct buffer_head **bh, s64 num_secs, s32 read); +s32 write_msect(struct super_block *sb, u64 sec, struct buffer_head *bh, s64 num_secs, s32 sync); +s32 write_msect_zero(struct super_block *sb, u64 sec, u64 num_secs); /* misc.c */ u8 calc_chksum_1byte(void *data, s32 len, u8 chksum); @@ -203,7 +202,7 @@ s32 extent_cache_init(void); void extent_cache_shutdown(void); void extent_cache_init_inode(struct inode *inode); void extent_cache_inval_inode(struct inode *inode); -s32 extent_get_clus(struct inode *inode, s32 cluster, s32 *fclus, +s32 extent_get_clus(struct inode *inode, u32 cluster, u32 *fclus, u32 *dclus, u32 *last_dclus, s32 allow_eof); /*----------------------------------------------------------------------*/ /* Wrapper Function */ diff --git a/fs/sdfat/core_exfat.c b/fs/sdfat/core_exfat.c index f88c488f10b8b..08c45b09bb78c 100644 --- a/fs/sdfat/core_exfat.c +++ b/fs/sdfat/core_exfat.c @@ -314,7 +314,7 @@ static void __init_name_entry(NAME_DENTRY_T *ep, u16 *uniname) static s32 exfat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 type, u32 start_clu, u64 size) { - u32 sector; + u64 sector; u8 flags; FILE_DENTRY_T *file_ep; STRM_DENTRY_T *strm_ep; @@ -345,7 +345,7 @@ s32 update_dir_chksum(struct super_block *sb, CHAIN_T *p_dir, s32 entry) { s32 ret = -EIO; s32 i, num_entries; - u32 sector; + u64 sector; u16 chksum; FILE_DENTRY_T *file_ep; DENTRY_T *ep; @@ -380,7 +380,7 @@ static s32 exfat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entr UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname) { s32 i; - u32 sector; + u64 sector; u16 *uniname = p_uniname->name; FILE_DENTRY_T *file_ep; STRM_DENTRY_T *strm_ep; @@ -420,7 +420,7 @@ static s32 exfat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entr static s32 exfat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32 order, s32 num_entries) { s32 i; - u32 sector; + u64 sector; DENTRY_T *ep; for (i = order; i < num_entries; i++) { @@ -437,16 +437,17 @@ static s32 exfat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 en } static s32 __write_partial_entries_in_entry_set(struct super_block *sb, - ENTRY_SET_CACHE_T *es, u32 sec, s32 off, u32 count) + ENTRY_SET_CACHE_T *es, u64 sec, u32 off, u32 count) { - s32 num_entries, buf_off = (off - es->offset); + s32 num_entries; + u32 buf_off = (off - es->offset); u32 remaining_byte_in_sector, copy_entries; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); u32 clu; u8 *buf, *esbuf = (u8 *)&(es->__buf); TMSG("%s entered\n", __func__); - MMSG("%s: es %p sec %u off %d cnt %d\n", __func__, es, sec, off, count); + MMSG("%s: es %p sec %llu off %u cnt %d\n", __func__, es, sec, off, count); num_entries = count; while (num_entries) { @@ -457,7 +458,7 @@ static s32 __write_partial_entries_in_entry_set(struct super_block *sb, if (!buf) goto err_out; MMSG("es->buf %p buf_off %u\n", esbuf, buf_off); - MMSG("copying %d entries from %p to sector %u\n", copy_entries, (esbuf + buf_off), sec); + MMSG("copying %d entries from %p to sector %llu\n", copy_entries, (esbuf + buf_off), sec); memcpy(buf + off, esbuf + buf_off, copy_entries << DENTRY_SIZE_BITS); dcache_modify(sb, sec); num_entries -= copy_entries; @@ -532,9 +533,10 @@ s32 update_dir_chksum_with_entry_set(struct super_block *sb, ENTRY_SET_CACHE_T * ENTRY_SET_CACHE_T *get_dentry_set_in_dir(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 type, DENTRY_T **file_ep) { - s32 off, ret, byte_offset; - u32 clu = 0; - u32 sec, entry_type; + s32 ret; + u32 off, byte_offset, clu = 0; + u32 entry_type; + u64 sec; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); ENTRY_SET_CACHE_T *es = NULL; DENTRY_T *ep, *pos; @@ -677,7 +679,7 @@ ENTRY_SET_CACHE_T *get_dentry_set_in_dir(struct super_block *sb, if (file_ep) *file_ep = (DENTRY_T *)&(es->__buf); - MMSG("es sec %u offset %d flags %d, num_entries %u buf ptr %p\n", + MMSG("es sec %llu offset %u flags %d, num_entries %u buf ptr %p\n", es->sector, es->offset, es->alloc_flag, es->num_entries, &(es->__buf)); TMSG("%s exited %p\n", __func__, es); return es; @@ -714,6 +716,7 @@ static s32 __extract_uni_name_from_name_entry(NAME_DENTRY_T *ep, u16 *uniname, s *uniname = 0x0; return len; + } /* end of __extract_uni_name_from_name_entry */ #define DIRENT_STEP_FILE (0) @@ -1021,15 +1024,14 @@ static s32 exfat_check_max_dentries(FILE_ID_T *fid) return 0; } /* end of check_max_dentries */ - /* * Allocation Bitmap Management Functions */ s32 load_alloc_bmp(struct super_block *sb) { - s32 i, j, ret; - u32 map_size, need_map_size; - u32 type, sector; + s32 ret; + u32 i, j, map_size, type, need_map_size; + u64 sector; CHAIN_T clu; BMAP_DENTRY_T *ep; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -1121,7 +1123,7 @@ void free_alloc_bmp(struct super_block *sb) static s32 set_alloc_bitmap(struct super_block *sb, u32 clu) { s32 i, b; - u32 sector; + u64 sector; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); i = clu >> (sb->s_blocksize_bits + 3); @@ -1141,7 +1143,7 @@ static s32 clr_alloc_bitmap(struct super_block *sb, u32 clu) { s32 ret; s32 i, b; - u32 sector; + u64 sector; struct sdfat_sb_info *sbi = SDFAT_SB(sb); struct sdfat_mount_options *opts = &sbi->options; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -1227,7 +1229,7 @@ void sync_alloc_bmp(struct super_block *sb) sync_dirty_buffer(fsi->vol_amap[i]); } -static s32 exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len) +static s32 exfat_chain_cont_cluster(struct super_block *sb, u32 chain, u32 len) { if (!len) return 0; @@ -1244,119 +1246,27 @@ static s32 exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len) return 0; } -s32 chain_cont_cluster(struct super_block *sb, u32 chain, s32 len) +s32 chain_cont_cluster(struct super_block *sb, u32 chain, u32 len) { return exfat_chain_cont_cluster(sb, chain, len); } -static s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p_chain, int dest) -{ - s32 num_clusters = 0; - u32 hint_clu, new_clu, last_clu = CLUS_EOF; - FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); - - hint_clu = p_chain->dir; - /* find new cluster */ - if (IS_CLUS_EOF(hint_clu)) { - if (fsi->clu_srch_ptr < 2) { - EMSG("%s: fsi->clu_srch_ptr is invalid (%u)\n", - __func__, fsi->clu_srch_ptr); - ASSERT(0); - fsi->clu_srch_ptr = 2; - } - - hint_clu = test_alloc_bitmap(sb, fsi->clu_srch_ptr-2); - if (IS_CLUS_EOF(hint_clu)) - return 0; - } - - /* check cluster validation */ - if ((hint_clu < 2) && (hint_clu >= fsi->num_clusters)) { - EMSG("%s: hint_cluster is invalid (%u)\n", __func__, hint_clu); - ASSERT(0); - hint_clu = 2; - if (p_chain->flags == 0x03) { - if (exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters)) - return -EIO; - p_chain->flags = 0x01; - } - } - - set_sb_dirty(sb); - - p_chain->dir = CLUS_EOF; - - while ((new_clu = test_alloc_bitmap(sb, hint_clu-2)) != CLUS_EOF) { - if ((new_clu != hint_clu) && (p_chain->flags == 0x03)) { - if (exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters)) - return -EIO; - p_chain->flags = 0x01; - } - - /* update allocation bitmap */ - if (set_alloc_bitmap(sb, new_clu-2)) - return -EIO; - - num_clusters++; - - /* update FAT table */ - if (p_chain->flags == 0x01) - if (fat_ent_set(sb, new_clu, CLUS_EOF)) - return -EIO; - - if (IS_CLUS_EOF(p_chain->dir)) { - p_chain->dir = new_clu; - } else if (p_chain->flags == 0x01) { - if (fat_ent_set(sb, last_clu, new_clu)) - return -EIO; - } - last_clu = new_clu; - - if ((--num_alloc) == 0) { - fsi->clu_srch_ptr = hint_clu; - if (fsi->used_clusters != (u32) ~0) - fsi->used_clusters += num_clusters; - - p_chain->size += num_clusters; - return num_clusters; - } - - hint_clu = new_clu + 1; - if (hint_clu >= fsi->num_clusters) { - hint_clu = 2; - - if (p_chain->flags == 0x03) { - if (exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters)) - return -EIO; - p_chain->flags = 0x01; - } - } - } - - fsi->clu_srch_ptr = hint_clu; - if (fsi->used_clusters != (u32) ~0) - fsi->used_clusters += num_clusters; - - p_chain->size += num_clusters; - return num_clusters; -} /* end of exfat_alloc_cluster */ - static s32 exfat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_relse) { s32 ret = -EIO; - s32 num_clusters = 0; + u32 num_clusters = 0; u32 clu; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); s32 i; - u32 sector; + u64 sector; /* invalid cluster number */ if (IS_CLUS_FREE(p_chain->dir) || IS_CLUS_EOF(p_chain->dir)) return 0; /* no cluster to truncate */ - if (p_chain->size <= 0) { + if (p_chain->size == 0) { DMSG("%s: cluster(%u) truncation is not required.", __func__, p_chain->dir); return 0; @@ -1412,11 +1322,122 @@ static s32 exfat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_r ret = 0; out: - if (fsi->used_clusters != (u32) ~0) - fsi->used_clusters -= num_clusters; + fsi->used_clusters -= num_clusters; return ret; } /* end of exfat_free_cluster */ +static s32 exfat_alloc_cluster(struct super_block *sb, u32 num_alloc, CHAIN_T *p_chain, s32 dest) +{ + s32 ret = -ENOSPC; + u32 num_clusters = 0, total_cnt; + u32 hint_clu, new_clu, last_clu = CLUS_EOF; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + total_cnt = fsi->num_clusters - CLUS_BASE; + + if (unlikely(total_cnt < fsi->used_clusters)) { + sdfat_fs_error_ratelimit(sb, + "%s: invalid used clusters(t:%u,u:%u)\n", + __func__, total_cnt, fsi->used_clusters); + return -EIO; + } + + if (num_alloc > total_cnt - fsi->used_clusters) + return -ENOSPC; + + hint_clu = p_chain->dir; + /* find new cluster */ + if (IS_CLUS_EOF(hint_clu)) { + if (fsi->clu_srch_ptr < CLUS_BASE) { + EMSG("%s: fsi->clu_srch_ptr is invalid (%u)\n", + __func__, fsi->clu_srch_ptr); + ASSERT(0); + fsi->clu_srch_ptr = CLUS_BASE; + } + + hint_clu = test_alloc_bitmap(sb, fsi->clu_srch_ptr - CLUS_BASE); + if (IS_CLUS_EOF(hint_clu)) + return -ENOSPC; + } + + /* check cluster validation */ + if ((hint_clu < CLUS_BASE) && (hint_clu >= fsi->num_clusters)) { + EMSG("%s: hint_cluster is invalid (%u)\n", __func__, hint_clu); + ASSERT(0); + hint_clu = CLUS_BASE; + if (p_chain->flags == 0x03) { + if (exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters)) + return -EIO; + p_chain->flags = 0x01; + } + } + + set_sb_dirty(sb); + + p_chain->dir = CLUS_EOF; + + while ((new_clu = test_alloc_bitmap(sb, hint_clu - CLUS_BASE)) != CLUS_EOF) { + if ((new_clu != hint_clu) && (p_chain->flags == 0x03)) { + if (exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters)) { + ret = -EIO; + goto error; + } + p_chain->flags = 0x01; + } + + /* update allocation bitmap */ + if (set_alloc_bitmap(sb, new_clu - CLUS_BASE)) { + ret = -EIO; + goto error; + } + + num_clusters++; + + /* update FAT table */ + if (p_chain->flags == 0x01) { + if (fat_ent_set(sb, new_clu, CLUS_EOF)) { + ret = -EIO; + goto error; + } + } + + if (IS_CLUS_EOF(p_chain->dir)) { + p_chain->dir = new_clu; + } else if (p_chain->flags == 0x01) { + if (fat_ent_set(sb, last_clu, new_clu)) { + ret = -EIO; + goto error; + } + } + last_clu = new_clu; + + if ((--num_alloc) == 0) { + fsi->clu_srch_ptr = hint_clu; + fsi->used_clusters += num_clusters; + + p_chain->size += num_clusters; + return 0; + } + + hint_clu = new_clu + 1; + if (hint_clu >= fsi->num_clusters) { + hint_clu = CLUS_BASE; + + if (p_chain->flags == 0x03) { + if (exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters)) { + ret = -EIO; + goto error; + } + p_chain->flags = 0x01; + } + } + } +error: + if (num_clusters) + exfat_free_cluster(sb, p_chain, 0); + return ret; +} /* end of exfat_alloc_cluster */ + static s32 exfat_count_used_clusters(struct super_block *sb, u32 *ret_count) { u32 count = 0; @@ -1514,7 +1535,7 @@ s32 mount_exfat(struct super_block *sb, pbr_t *p_pbr) fsi->dentries_per_clu = 1 << (fsi->cluster_size_bits - DENTRY_SIZE_BITS); fsi->vol_flag = (u32) le16_to_cpu(p_bpb->bsx.vol_flags); - fsi->clu_srch_ptr = 2; + fsi->clu_srch_ptr = CLUS_BASE; fsi->used_clusters = (u32) ~0; fsi->fs_func = &exfat_fs_func; diff --git a/fs/sdfat/core_fat.c b/fs/sdfat/core_fat.c index fc40c6e05d777..493e5cb7e71a4 100644 --- a/fs/sdfat/core_fat.c +++ b/fs/sdfat/core_fat.c @@ -155,60 +155,6 @@ static u32 __calc_default_au_size(struct super_block *sb) /* * Cluster Management Functions */ -static s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p_chain, int dest) -{ - s32 i, num_clusters = 0; - u32 new_clu, last_clu = CLUS_EOF, read_clu; - FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); - - - new_clu = p_chain->dir; - if (IS_CLUS_EOF(new_clu)) - new_clu = fsi->clu_srch_ptr; - else if (new_clu >= fsi->num_clusters) - new_clu = 2; - - set_sb_dirty(sb); - - p_chain->dir = CLUS_EOF; - - for (i = CLUS_BASE; i < fsi->num_clusters; i++) { - if (fat_ent_get(sb, new_clu, &read_clu)) - return -EIO; - - if (IS_CLUS_FREE(read_clu)) { - if (fat_ent_set(sb, new_clu, CLUS_EOF)) - return -EIO; - num_clusters++; - - if (IS_CLUS_EOF(p_chain->dir)) { - p_chain->dir = new_clu; - } else { - if (fat_ent_set(sb, last_clu, new_clu)) - return -EIO; - } - - last_clu = new_clu; - - if ((--num_alloc) == 0) { - fsi->clu_srch_ptr = new_clu; - if (fsi->used_clusters != (u32) ~0) - fsi->used_clusters += num_clusters; - - return num_clusters; - } - } - if ((++new_clu) >= fsi->num_clusters) - new_clu = CLUS_BASE; - } - - fsi->clu_srch_ptr = new_clu; - if (fsi->used_clusters != (u32) ~0) - fsi->used_clusters += num_clusters; - - return num_clusters; -} /* end of fat_alloc_cluster */ - static s32 fat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_relse) { s32 ret = -EIO; @@ -216,14 +162,14 @@ static s32 fat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_rel u32 clu, prev; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); s32 i; - u32 sector; + u64 sector; /* invalid cluster number */ if (IS_CLUS_FREE(p_chain->dir) || IS_CLUS_EOF(p_chain->dir)) return 0; /* no cluster to truncate */ - if (p_chain->size <= 0) { + if (!p_chain->size) { DMSG("%s: cluster(%u) truncation is not required.", __func__, p_chain->dir); return 0; @@ -281,11 +227,79 @@ static s32 fat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_rel /* success */ ret = 0; out: - if (fsi->used_clusters != (u32) ~0) - fsi->used_clusters -= num_clusters; + fsi->used_clusters -= num_clusters; return ret; } /* end of fat_free_cluster */ +static s32 fat_alloc_cluster(struct super_block *sb, u32 num_alloc, CHAIN_T *p_chain, s32 dest) +{ + s32 ret = -ENOSPC; + u32 i, num_clusters = 0, total_cnt; + u32 new_clu, last_clu = CLUS_EOF, read_clu; + FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); + + total_cnt = fsi->num_clusters - CLUS_BASE; + + if (unlikely(total_cnt < fsi->used_clusters)) { + sdfat_fs_error_ratelimit(sb, + "%s : invalid used clusters(t:%u,u:%u)\n", + __func__, total_cnt, fsi->used_clusters); + return -EIO; + } + + if (num_alloc > total_cnt - fsi->used_clusters) + return -ENOSPC; + + new_clu = p_chain->dir; + if (IS_CLUS_EOF(new_clu)) + new_clu = fsi->clu_srch_ptr; + else if (new_clu >= fsi->num_clusters) + new_clu = CLUS_BASE; + + set_sb_dirty(sb); + + p_chain->dir = CLUS_EOF; + + for (i = CLUS_BASE; i < fsi->num_clusters; i++) { + if (fat_ent_get(sb, new_clu, &read_clu)) { + ret = -EIO; + goto error; + } + + if (IS_CLUS_FREE(read_clu)) { + if (fat_ent_set(sb, new_clu, CLUS_EOF)) { + ret = -EIO; + goto error; + } + num_clusters++; + + if (IS_CLUS_EOF(p_chain->dir)) { + p_chain->dir = new_clu; + } else { + if (fat_ent_set(sb, last_clu, new_clu)) { + ret = -EIO; + goto error; + } + } + + last_clu = new_clu; + + if ((--num_alloc) == 0) { + fsi->clu_srch_ptr = new_clu; + fsi->used_clusters += num_clusters; + + return 0; + } + } + if ((++new_clu) >= fsi->num_clusters) + new_clu = CLUS_BASE; + } +error: + if (num_clusters) + fat_free_cluster(sb, p_chain, 0); + return ret; +} /* end of fat_alloc_cluster */ + static s32 fat_count_used_clusters(struct super_block *sb, u32 *ret_count) { s32 i; @@ -525,7 +539,7 @@ static void __init_ext_entry(EXT_DENTRY_T *ep, s32 order, u8 chksum, u16 *uninam static s32 fat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 type, u32 start_clu, u64 size) { - u32 sector; + u64 sector; DOS_DENTRY_T *dos_ep; dos_ep = (DOS_DENTRY_T *) get_dentry_in_dir(sb, p_dir, entry, §or); @@ -542,7 +556,7 @@ static s32 fat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname) { s32 i; - u32 sector; + u64 sector; u8 chksum; u16 *uniname = p_uniname->name; DOS_DENTRY_T *dos_ep; @@ -586,7 +600,7 @@ static s32 fat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, static s32 fat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32 order, s32 num_entries) { s32 i; - u32 sector; + u64 sector; DENTRY_T *ep; for (i = num_entries-1; i >= order; i--) { @@ -1225,7 +1239,7 @@ static FS_FUNC_T amap_fat_fs_func = { s32 mount_fat16(struct super_block *sb, pbr_t *p_pbr) { - s32 num_reserved, num_root_sectors; + s32 num_root_sectors; bpb16_t *p_bpb = &(p_pbr->bpb.f16); FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -1262,8 +1276,7 @@ s32 mount_fat16(struct super_block *sb, pbr_t *p_pbr) return -EINVAL; } - num_reserved = fsi->data_start_sector; - fsi->num_clusters = ((fsi->num_sectors - num_reserved) >> fsi->sect_per_clus_bits) + CLUS_BASE; + fsi->num_clusters = (u32)((fsi->num_sectors - fsi->data_start_sector) >> fsi->sect_per_clus_bits) + CLUS_BASE; /* because the cluster index starts with 2 */ fsi->vol_type = FAT16; @@ -1329,7 +1342,6 @@ static sector_t __calc_hidden_sect(struct super_block *sb) s32 mount_fat32(struct super_block *sb, pbr_t *p_pbr) { - s32 num_reserved; pbr32_t *p_bpb = (pbr32_t *)p_pbr; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -1365,9 +1377,7 @@ s32 mount_fat32(struct super_block *sb, pbr_t *p_pbr) return -EINVAL; } - num_reserved = fsi->data_start_sector; - - fsi->num_clusters = ((fsi->num_sectors-num_reserved) >> fsi->sect_per_clus_bits) + 2; + fsi->num_clusters = (u32)((fsi->num_sectors - fsi->data_start_sector) >> fsi->sect_per_clus_bits) + CLUS_BASE; /* because the cluster index starts with 2 */ fsi->vol_type = FAT32; diff --git a/fs/sdfat/dfr.c b/fs/sdfat/dfr.c index b06ae840997ec..2853fe4251978 100644 --- a/fs/sdfat/dfr.c +++ b/fs/sdfat/dfr.c @@ -458,12 +458,6 @@ defrag_reserve_clusters( /* Nothing to do */ return 0; - /* Update used_clusters */ - if (fsi->used_clusters == (u32) ~0) { - if (fsi->fs_func->count_used_clusters(sb, &fsi->used_clusters)) - return -EIO; - } - /* Check error case */ if (fsi->used_clusters + fsi->reserved_clusters + nr_clus >= fsi->num_clusters - 2) { return -ENOSPC; @@ -544,7 +538,7 @@ defrag_map_cluster( struct defrag_info *ino_dfr = &(SDFAT_I(inode)->dfr_info); struct defrag_chunk_info *chunk = NULL; CHAIN_T new_clu; - int num = 0, i = 0, nr_new = 0, err = 0; + int i = 0, nr_new = 0, err = 0; /* Get corresponding chunk */ for (i = 0; i < ino_dfr->nr_chunks; i++) { @@ -570,16 +564,16 @@ defrag_map_cluster( /* Allocate new cluster */ #ifdef CONFIG_SDFAT_DFR_PACKING if (amap->n_clean_au * DFR_FULL_RATIO <= amap->n_au * DFR_DEFAULT_PACKING_RATIO) - num = fsi->fs_func->alloc_cluster(sb, 1, &new_clu, ALLOC_COLD_PACKING); + err = fsi->fs_func->alloc_cluster(sb, 1, &new_clu, ALLOC_COLD_PACKING); else - num = fsi->fs_func->alloc_cluster(sb, 1, &new_clu, ALLOC_COLD_ALIGNED); + err = fsi->fs_func->alloc_cluster(sb, 1, &new_clu, ALLOC_COLD_ALIGNED); #else - num = fsi->fs_func->alloc_cluster(sb, 1, &new_clu, ALLOC_COLD_ALIGNED); + err = fsi->fs_func->alloc_cluster(sb, 1, &new_clu, ALLOC_COLD_ALIGNED); #endif - if (num != 1) { - dfr_err("Map: num %d", num); - return -EIO; + if (err) { + dfr_err("Map: 1 %d", 0); + return err; } /* Decrease reserved cluster count */ @@ -824,7 +818,8 @@ __defrag_update_dirent( FS_INFO_T *fsi = &SDFAT_SB(sb)->fsi; CHAIN_T dir; DOS_DENTRY_T *dos_ep; - unsigned int entry = 0, sector = 0; + unsigned int entry = 0; + unsigned long long sector = 0; unsigned short hi = 0, lo = 0; int err = 0; @@ -963,7 +958,7 @@ defrag_update_fat_prev( extent_cache_inval_inode(inode); /* Update FID info */ - ino_info->fid.hint_bmap.off = -1; + ino_info->fid.hint_bmap.off = CLUS_EOF; ino_info->fid.hint_bmap.clu = 0; /* Clear old FAT-chain */ diff --git a/fs/sdfat/dfr.h b/fs/sdfat/dfr.h index 19edab38ce4ee..da98605020d34 100644 --- a/fs/sdfat/dfr.h +++ b/fs/sdfat/dfr.h @@ -114,8 +114,8 @@ struct defrag_info_arg { /* PBS info */ unsigned int sec_sz; unsigned int clus_sz; - unsigned int total_sec; - unsigned int fat_offset_sec; + unsigned long long total_sec; + unsigned long long fat_offset_sec; unsigned int fat_sz_sec; unsigned int n_fat; unsigned int hidden_sectors; diff --git a/fs/sdfat/extent.c b/fs/sdfat/extent.c index 9349a59b4debe..59e096530ddad 100644 --- a/fs/sdfat/extent.c +++ b/fs/sdfat/extent.c @@ -47,15 +47,15 @@ struct extent_cache { struct list_head cache_list; - s32 nr_contig; /* number of contiguous clusters */ - s32 fcluster; /* cluster number in the file. */ + u32 nr_contig; /* number of contiguous clusters */ + u32 fcluster; /* cluster number in the file. */ u32 dcluster; /* cluster number on disk. */ }; struct extent_cache_id { u32 id; - s32 nr_contig; - s32 fcluster; + u32 nr_contig; + u32 fcluster; u32 dcluster; }; @@ -116,16 +116,16 @@ static inline void extent_cache_update_lru(struct inode *inode, list_move(&cache->cache_list, &extent->cache_lru); } -static s32 extent_cache_lookup(struct inode *inode, s32 fclus, +static u32 extent_cache_lookup(struct inode *inode, u32 fclus, struct extent_cache_id *cid, - s32 *cached_fclus, u32 *cached_dclus) + u32 *cached_fclus, u32 *cached_dclus) { EXTENT_T *extent = &(SDFAT_I(inode)->fid.extent); static struct extent_cache nohit = { .fcluster = 0, }; struct extent_cache *hit = &nohit, *p; - s32 offset = -1; + u32 offset = CLUS_EOF; spin_lock(&extent->cache_lru_lock); list_for_each_entry(p, &extent->cache_lru, cache_list) { @@ -261,7 +261,7 @@ static inline s32 cache_contiguous(struct extent_cache_id *cid, u32 dclus) return ((cid->dcluster + cid->nr_contig) == dclus); } -static inline void cache_init(struct extent_cache_id *cid, s32 fclus, u32 dclus) +static inline void cache_init(struct extent_cache_id *cid, u32 fclus, u32 dclus) { cid->id = EXTENT_CACHE_VALID; cid->fcluster = fclus; @@ -269,12 +269,12 @@ static inline void cache_init(struct extent_cache_id *cid, s32 fclus, u32 dclus) cid->nr_contig = 0; } -s32 extent_get_clus(struct inode *inode, s32 cluster, s32 *fclus, +s32 extent_get_clus(struct inode *inode, u32 cluster, u32 *fclus, u32 *dclus, u32 *last_dclus, s32 allow_eof) { struct super_block *sb = inode->i_sb; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); - s32 limit = (s32)(fsi->num_clusters); + u32 limit = fsi->num_clusters; FILE_ID_T *fid = &(SDFAT_I(inode)->fid); struct extent_cache_id cid; u32 content; @@ -287,10 +287,6 @@ s32 extent_get_clus(struct inode *inode, s32 cluster, s32 *fclus, return -EIO; } - /* We allow max clusters per a file upto max of signed integer */ - if (fsi->num_clusters & 0x80000000) - limit = 0x7FFFFFFF; - *fclus = 0; *dclus = fid->start_clu; *last_dclus = *dclus; @@ -301,16 +297,16 @@ s32 extent_get_clus(struct inode *inode, s32 cluster, s32 *fclus, if ((cluster == 0) || IS_CLUS_EOF(*dclus)) return 0; - cache_init(&cid, -1, -1); + cache_init(&cid, CLUS_EOF, CLUS_EOF); - if (extent_cache_lookup(inode, cluster, &cid, fclus, dclus) < 0) { + if (extent_cache_lookup(inode, cluster, &cid, fclus, dclus) == CLUS_EOF) { /* * dummy, always not contiguous * This is reinitialized by cache_init(), later. */ ASSERT((cid.id == EXTENT_CACHE_VALID) - && (cid.fcluster == -1) - && (cid.dcluster == -1) + && (cid.fcluster == CLUS_EOF) + && (cid.dcluster == CLUS_EOF) && (cid.nr_contig == 0)); } @@ -322,7 +318,7 @@ s32 extent_get_clus(struct inode *inode, s32 cluster, s32 *fclus, if (*fclus > limit) { sdfat_fs_error(sb, "%s: detected the cluster chain loop" - " (i_pos %d)", __func__, + " (i_pos %u)", __func__, (*fclus)); return -EIO; } @@ -337,7 +333,7 @@ s32 extent_get_clus(struct inode *inode, s32 cluster, s32 *fclus, if (IS_CLUS_EOF(content)) { if (!allow_eof) { sdfat_fs_error(sb, - "%s: invalid cluster chain (i_pos %d," + "%s: invalid cluster chain (i_pos %u," "last_clus 0x%08x is EOF)", __func__, *fclus, (*last_dclus)); return -EIO; diff --git a/fs/sdfat/fatent.c b/fs/sdfat/fatent.c index 71d3653dd8051..fca32a50d3363 100644 --- a/fs/sdfat/fatent.c +++ b/fs/sdfat/fatent.c @@ -50,7 +50,8 @@ */ static s32 exfat_ent_get(struct super_block *sb, u32 loc, u32 *content) { - u32 sec, off, _content; + u32 off, _content; + u64 sec; u8 *fat_sector; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -74,7 +75,8 @@ static s32 exfat_ent_get(struct super_block *sb, u32 loc, u32 *content) static s32 exfat_ent_set(struct super_block *sb, u32 loc, u32 content) { - u32 sec, off; + u32 off; + u64 sec; u8 *fat_sector; __le32 *fat_entry; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -96,7 +98,8 @@ static s32 exfat_ent_set(struct super_block *sb, u32 loc, u32 content) #define FATENT_FAT32_IGNORE_MASK (0xF0000000U) static s32 fat32_ent_get(struct super_block *sb, u32 loc, u32 *content) { - u32 sec, off, _content; + u32 off, _content; + u64 sec; u8 *fat_sector; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -122,7 +125,8 @@ static s32 fat32_ent_get(struct super_block *sb, u32 loc, u32 *content) static s32 fat32_ent_set(struct super_block *sb, u32 loc, u32 content) { - u32 sec, off; + u32 off; + u64 sec; u8 *fat_sector; __le32 *fat_entry; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -146,7 +150,8 @@ static s32 fat32_ent_set(struct super_block *sb, u32 loc, u32 content) #define FATENT_FAT16_VALID_MASK (0x0000FFFFU) static s32 fat16_ent_get(struct super_block *sb, u32 loc, u32 *content) { - u32 sec, off, _content; + u32 off, _content; + u64 sec; u8 *fat_sector; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -172,7 +177,8 @@ static s32 fat16_ent_get(struct super_block *sb, u32 loc, u32 *content) static s32 fat16_ent_set(struct super_block *sb, u32 loc, u32 content) { - u32 sec, off; + u32 off; + u64 sec; u8 *fat_sector; __le16 *fat_entry; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -195,7 +201,8 @@ static s32 fat16_ent_set(struct super_block *sb, u32 loc, u32 content) #define FATENT_FAT12_VALID_MASK (0x00000FFFU) static s32 fat12_ent_get(struct super_block *sb, u32 loc, u32 *content) { - u32 sec, off, _content; + u32 off, _content; + u64 sec; u8 *fat_sector; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); @@ -235,7 +242,8 @@ static s32 fat12_ent_get(struct super_block *sb, u32 loc, u32 *content) static s32 fat12_ent_set(struct super_block *sb, u32 loc, u32 content) { - u32 sec, off; + u32 off; + u64 sec; u8 *fat_sector, *fat_entry; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); diff --git a/fs/sdfat/misc.c b/fs/sdfat/misc.c index 566f99bf2975f..f12096c1f5602 100644 --- a/fs/sdfat/misc.c +++ b/fs/sdfat/misc.c @@ -305,9 +305,10 @@ u32 sdfat_time_current_usec(struct timeval *tv) /* Check the consistency of i_size_ondisk (FAT32, or flags 0x01 only) */ void sdfat_debug_check_clusters(struct inode *inode) { - int num_clusters; + unsigned int num_clusters; volatile uint32_t tmp_fat_chain[50]; - volatile int num_clusters_org, tmp_i = 0; + volatile int tmp_i = 0; + volatile unsigned int num_clusters_org, tmp_i = 0; CHAIN_T clu; FILE_ID_T *fid = &(SDFAT_I(inode)->fid); FS_INFO_T *fsi = &(SDFAT_SB(inode->i_sb)->fsi); @@ -315,7 +316,7 @@ void sdfat_debug_check_clusters(struct inode *inode) if (SDFAT_I(inode)->i_size_ondisk == 0) num_clusters = 0; else - num_clusters = (s32)((SDFAT_I(inode)->i_size_ondisk-1) >> fsi->cluster_size_bits) + 1; + num_clusters = ((SDFAT_I(inode)->i_size_ondisk-1) >> fsi->cluster_size_bits) + 1; clu.dir = fid->start_clu; clu.size = num_clusters; diff --git a/fs/sdfat/sdfat.c b/fs/sdfat/sdfat.c index 49bc22ff7d634..30c0bdf79d335 100644 --- a/fs/sdfat/sdfat.c +++ b/fs/sdfat/sdfat.c @@ -78,6 +78,7 @@ const char *FS_TYPE_STR[] = { static struct kset *sdfat_kset; static struct kmem_cache *sdfat_inode_cachep; + static int sdfat_default_codepage = CONFIG_SDFAT_DEFAULT_CODEPAGE; static char sdfat_default_iocharset[] = CONFIG_SDFAT_DEFAULT_IOCHARSET; static const char sdfat_iocharset_with_utf8[] = "iso8859-1"; @@ -199,20 +200,22 @@ static inline unsigned long __sdfat_init_name_hash(const struct dentry *unused) } #endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 21) - /* EMPTY */ + /* EMPTY */ #else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 21) */ static inline void inode_lock(struct inode *inode) { - mutex_lock(&inode->i_mutex); + mutex_lock(&inode->i_mutex); } static inline void inode_unlock(struct inode *inode) { - mutex_unlock(&inode->i_mutex); + mutex_unlock(&inode->i_mutex); } #endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) static void sdfat_writepage_end_io(struct bio *bio) { @@ -1709,7 +1712,7 @@ sdfat_ioctl_defrag_req( dfr_debug("IOC_DFR_REQ started (mode %d, nr_req %d)", head.mode, len - 1); if (get_order(len * sizeof(struct defrag_chunk_info)) > MAX_ORDER) { - dfr_debug("len %u, sizeof(struct defrag_chunk_info) %lu, MAX_ORDER %d", + dfr_debug("len %d, sizeof(struct defrag_chunk_info) %lu, MAX_ORDER %d", len, sizeof(struct defrag_chunk_info), MAX_ORDER); err = -EINVAL; goto error; @@ -4707,7 +4710,7 @@ static int sdfat_read_root(struct inode *inode) SDFAT_I(inode)->fid.type = TYPE_DIR; SDFAT_I(inode)->fid.version = 0; SDFAT_I(inode)->fid.rwoffset = 0; - SDFAT_I(inode)->fid.hint_bmap.off = -1; + SDFAT_I(inode)->fid.hint_bmap.off = CLUS_EOF; SDFAT_I(inode)->fid.hint_stat.eidx = 0; SDFAT_I(inode)->fid.hint_stat.clu = fsi->root_dir; SDFAT_I(inode)->fid.hint_femp.eidx = -1; diff --git a/fs/sdfat/sdfat.h b/fs/sdfat/sdfat.h index a4b7ed3e16c96..6f764210fe4d7 100644 --- a/fs/sdfat/sdfat.h +++ b/fs/sdfat/sdfat.h @@ -80,10 +80,10 @@ & ((1 << (fsi)->sect_per_clus_bits) - 1)) == 0) #define CLUS_TO_SECT(fsi, x) \ - ((((x) - CLUS_BASE) << (fsi)->sect_per_clus_bits) + (fsi)->data_start_sector) + ((((unsigned long long)(x) - CLUS_BASE) << (fsi)->sect_per_clus_bits) + (fsi)->data_start_sector) #define SECT_TO_CLUS(fsi, sec) \ - ((((sec) - (fsi)->data_start_sector) >> (fsi)->sect_per_clus_bits) + CLUS_BASE) + ((u32)((((sec) - (fsi)->data_start_sector) >> (fsi)->sect_per_clus_bits) + CLUS_BASE)) /* variables defined at sdfat.c */ extern const char *FS_TYPE_STR[]; diff --git a/fs/sdfat/statistics.c b/fs/sdfat/statistics.c index cf4baab0edf6a..00624df5a6364 100644 --- a/fs/sdfat/statistics.c +++ b/fs/sdfat/statistics.c @@ -226,7 +226,7 @@ void sdfat_statistics_set_rw(u8 flags, u32 clu_offset, s32 create) * clu : cluster chain * * Set no fat-chain trunc when file or dir have 0x03 flag - * and tow or more clusters. + * and two or more clusters. */ void sdfat_statistics_set_trunc(u8 flags, CHAIN_T *clu) { diff --git a/fs/sdfat/version.h b/fs/sdfat/version.h index 831475e6a0cad..e245fe16f319a 100644 --- a/fs/sdfat/version.h +++ b/fs/sdfat/version.h @@ -22,4 +22,4 @@ /* PURPOSE : sdFAT File Manager */ /* */ /************************************************************************/ -#define SDFAT_VERSION "1.4.16" +#define SDFAT_VERSION "2.0.6" From b6fe53a43629b5e061ba64387770512d0716c34a Mon Sep 17 00:00:00 2001 From: Bruno Martins Date: Thu, 1 Mar 2018 04:46:00 +0530 Subject: [PATCH 496/508] ARM64: configs: Enable support for sdFAT filesystem * Update default charset for FAT to UTF-8, matching sdFAT's default. Change-Id: I7b33b5f24e079509a47a35b3aeb06b269cdc86eb --- arch/arm64/configs/mido_defconfig | 13 ++++++++++++- arch/arm64/configs/tissot_defconfig | 15 +++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/arch/arm64/configs/mido_defconfig b/arch/arm64/configs/mido_defconfig index 250b02e8d4c74..dca617c0fa069 100644 --- a/arch/arm64/configs/mido_defconfig +++ b/arch/arm64/configs/mido_defconfig @@ -4078,7 +4078,18 @@ CONFIG_FAT_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_FAT_DEFAULT_IOCHARSET="utf8" +CONFIG_SDFAT_FS=y +CONFIG_SDFAT_DELAYED_META_DIRTY=y +CONFIG_SDFAT_SUPPORT_DIR_SYNC=y +CONFIG_SDFAT_DEFAULT_CODEPAGE=437 +CONFIG_SDFAT_DEFAULT_IOCHARSET="utf8" +CONFIG_SDFAT_CHECK_RO_ATTR=y +CONFIG_SDFAT_ALIGNED_MPAGE_WRITE=y +CONFIG_SDFAT_VIRTUAL_XATTR=y +CONFIG_SDFAT_VIRTUAL_XATTR_SELINUX_LABEL="u:object_r:sdcard_external:s0" +# CONFIG_SDFAT_DEBUG is not set +CONFIG_SDFAT_STATISTICS=y # CONFIG_NTFS_FS is not set # diff --git a/arch/arm64/configs/tissot_defconfig b/arch/arm64/configs/tissot_defconfig index ae2e94aacad7e..4fc208b61ac0e 100644 --- a/arch/arm64/configs/tissot_defconfig +++ b/arch/arm64/configs/tissot_defconfig @@ -3994,7 +3994,18 @@ CONFIG_FAT_FS=y # CONFIG_MSDOS_FS is not set CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_FAT_DEFAULT_IOCHARSET="utf8" +CONFIG_SDFAT_FS=y +CONFIG_SDFAT_DELAYED_META_DIRTY=y +CONFIG_SDFAT_SUPPORT_DIR_SYNC=y +CONFIG_SDFAT_DEFAULT_CODEPAGE=437 +CONFIG_SDFAT_DEFAULT_IOCHARSET="utf8" +# CONFIG_SDFAT_CHECK_RO_ATTR is not set +CONFIG_SDFAT_ALIGNED_MPAGE_WRITE=y +CONFIG_SDFAT_VIRTUAL_XATTR=y +CONFIG_SDFAT_VIRTUAL_XATTR_SELINUX_LABEL="u:object_r:sdcard_external:s0" +# CONFIG_SDFAT_DEBUG is not set +CONFIG_SDFAT_STATISTICS=y # CONFIG_NTFS_FS is not set # @@ -4098,7 +4109,7 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_MAC_INUIT is not set # CONFIG_NLS_MAC_ROMANIAN is not set # CONFIG_NLS_MAC_TURKISH is not set -# CONFIG_NLS_UTF8 is not set +CONFIG_NLS_UTF8=y # CONFIG_DLM is not set # CONFIG_FILE_TABLE_DEBUG is not set # CONFIG_VIRTUALIZATION is not set From c54897cb473d8833e248238d141936522ace277f Mon Sep 17 00:00:00 2001 From: Ethan Yonker Date: Tue, 20 Dec 2016 18:54:18 -0500 Subject: [PATCH 497/508] md: disable dm-verity Change-Id: I97f1169a7cfccc78530b9869a407b3a9eade31ab --- drivers/md/dm-android-verity.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/md/dm-android-verity.c b/drivers/md/dm-android-verity.c index a3ad2dd4efee4..cb250a86d635c 100644 --- a/drivers/md/dm-android-verity.c +++ b/drivers/md/dm-android-verity.c @@ -374,6 +374,8 @@ static int verify_header(struct android_metadata_header *header) { int retval = -EINVAL; + return VERITY_STATE_DISABLE; + if (is_userdebug() && le32_to_cpu(header->magic_number) == VERITY_METADATA_MAGIC_DISABLE) return VERITY_STATE_DISABLE; From 700d918b675c7c318f8c0b068530ad2d5a1b17e3 Mon Sep 17 00:00:00 2001 From: Pratap Nirujogi Date: Sun, 18 Mar 2018 17:46:33 +0530 Subject: [PATCH 498/508] ion: ensure valid start address Ensure valid start address to check for vaddress bounds. Change-Id: I02c0ce85d9a495880c133e66553b09159daa8f0c Signed-off-by: Pratap Nirujogi --- drivers/staging/android/ion/msm/msm_ion.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c index e112a4fe66829..836ab66a4683f 100644 --- a/drivers/staging/android/ion/msm/msm_ion.c +++ b/drivers/staging/android/ion/msm/msm_ion.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -717,7 +717,7 @@ long msm_ion_custom_ioctl(struct ion_client *client, data.flush_data.offset; end = start + data.flush_data.length; - if (check_vaddr_bounds(start, end)) { + if (start && check_vaddr_bounds(start, end)) { pr_err("%s: virtual address %pK is out of bounds\n", __func__, data.flush_data.vaddr); ret = -EINVAL; From 6d8da85c64e0cc191b0e91a591c416da8bab87ed Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Mon, 29 Feb 2016 09:57:46 -0800 Subject: [PATCH 499/508] ion: adjust system heap pool orders As part of the change to fix unmovable block migration over time, we need to reduce the orders requested by ion to under order-5 allocations. In a future CL, we can add fixed-size larger-order pools to improve performance when allocating large buffers. Change-Id: I1ca336c8057b984987a5a5c28a86ab36488e08ea --- drivers/staging/android/ion/ion_system_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 062de5ae1738f..10e8a73cee3c1 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -37,7 +37,7 @@ static gfp_t high_order_gfp_flags = (GFP_HIGHUSER | __GFP_NOWARN | static gfp_t low_order_gfp_flags = (GFP_HIGHUSER | __GFP_NOWARN); #ifndef CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS -static const unsigned int orders[] = {9, 8, 4, 0}; +static const unsigned int orders[] = {4, 0}; #else static const unsigned int orders[] = {0}; #endif From 8f346dc6b1299a1740d1a114522542be740dd33a Mon Sep 17 00:00:00 2001 From: dianlujitao Date: Thu, 22 Mar 2018 11:43:49 +0800 Subject: [PATCH 500/508] Revert "ANDROID: Fix cpufreq stats table creation" * We don't need the "fix", per cpu stats is created without it, what's worse, it tried to create duplicated sysfs nodes. This reverts commit f68f1c61baacc8c4a86f71c354f2081d2588d6c7. Change-Id: I408f33609ce85bae9230707d7aad8874e4553cdc --- drivers/cpufreq/cpufreq_stats.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 3196cb61b91fe..56c6c4fed9cc5 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -577,11 +577,12 @@ static void cpufreq_powerstats_free(void) } static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, - int cpu, struct cpufreq_frequency_table *table, int count) + struct cpufreq_frequency_table *table, int count) { unsigned int i, ret = 0; struct cpufreq_stats *stat; unsigned int alloc_size; + unsigned int cpu = policy->cpu; struct cpufreq_frequency_table *pos; if (per_cpu(cpufreq_stats_table, cpu)) @@ -591,6 +592,8 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, return -ENOMEM; ret = sysfs_create_group(&policy->kobj, &stats_attr_group); + if (ret) + goto error_out; stat->cpu = cpu; per_cpu(cpufreq_stats_table, cpu) = stat; @@ -623,6 +626,7 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, return 0; error_alloc: sysfs_remove_group(&policy->kobj, &stats_attr_group); +error_out: kfree(stat); per_cpu(cpufreq_stats_table, cpu) = NULL; return ret; @@ -801,7 +805,7 @@ static void cpufreq_stats_create_table(unsigned int cpu) if (!per_cpu(cpufreq_power_stats, cpu)) cpufreq_powerstats_create(cpu, table, count); - __cpufreq_stats_create_table(policy, cpu, table, count); + __cpufreq_stats_create_table(policy, table, count); } cpufreq_cpu_put(policy); } @@ -859,7 +863,7 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb, } if (val == CPUFREQ_CREATE_POLICY) - ret = __cpufreq_stats_create_table(policy, cpu, table, count); + ret = __cpufreq_stats_create_table(policy, table, count); return ret; } From bf12f097c836518f5ec3c97aba0a6e6fc58cfba7 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Mon, 9 Jul 2018 20:10:34 +0530 Subject: [PATCH 501/508] drivers: input: toucscreen: Fix unbalanced irq <4>[ 1567.351182] ------------[ cut here ]------------ <4>[ 1567.351224] WARNING: CPU: 5 PID: 836 at ../../../../../../kernel/xiaomi/msm8953/kernel/irq/manage.c:451 __enable_irq+0x4c/0x90() <4>[ 1567.351229] Unbalanced enable for IRQ 72 <4>[ 1567.351237] Modules linked in: <4>[ 1567.351253] CPU: 5 PID: 836 Comm: HwBinder:546_2 Tainted: G W 3.18.71-perf-gc0bd711 #3 <4>[ 1567.351258] Hardware name: Qualcomm Technologies, Inc. MSM8953 + PMI8950 QRD SKU3 (DT) <0>[ 1567.351263] Call trace: <4>[ 1567.351283] [] dump_backtrace+0x0/0x258 <4>[ 1567.351292] [] show_stack+0x20/0x28 <4>[ 1567.351311] [] dump_stack+0x80/0xa4 <4>[ 1567.351323] [] warn_slowpath_common+0x90/0xb4 <4>[ 1567.351340] [] __enable_irq+0x4c/0x90 <4>[ 1567.351368] [] ft5435_ts_resume.isra.12+0xb4/0xd8 <4>[ 1567.351392] [] notifier_call_chain+0x58/0x8c <4>[ 1567.351412] [] blocking_notifier_call_chain+0x38/0x44 <4>[ 1567.351432] [] fb_blank+0x9c/0xc4 <4>[ 1567.351447] [] fb_ioctl+0x54/0x64 <4>[ 1586.198413] ------------[ cut here ]------------ Change-Id: Idcc9ef2309dd30518c114deabe9f5f14a7b7b8ee --- drivers/input/touchscreen/ft5435/ft5435_ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/ft5435/ft5435_ts.c b/drivers/input/touchscreen/ft5435/ft5435_ts.c index 0174bd21638d5..7939b9d81f13b 100644 --- a/drivers/input/touchscreen/ft5435/ft5435_ts.c +++ b/drivers/input/touchscreen/ft5435/ft5435_ts.c @@ -1520,8 +1520,8 @@ static int ft5435_ts_resume(struct device *dev) ft5x0x_write_reg(data->client, 0x8c, 0x01); - enable_irq(data->client->irq); data->suspended = false; + enable_irq(data->client->irq); #if defined(USB_CHARGE_DETECT) queue_work(ft5435_wq, &data->work); From ab93ce2d803ae50014fddeeb53495426af7f91c9 Mon Sep 17 00:00:00 2001 From: Paolo Valente Date: Sat, 6 Jun 2015 17:56:31 +0200 Subject: [PATCH 502/508] block: cgroups, kconfig, build bits for BFQ-v7r8-3.18.0 Update Kconfig.iosched and do the related Makefile changes to include kernel configuration options for BFQ. Also add the bfqio controller to the cgroups subsystem. Change-Id: I9a935f01f91d9abdc6813a65fc6bd5cd86fbfc74 Signed-off-by: Paolo Valente Signed-off-by: Arianna Avanzini --- block/Kconfig.iosched | 32 ++++++++++++++++++++++++++++++++ block/Makefile | 1 + include/linux/cgroup_subsys.h | 4 ++++ 3 files changed, 37 insertions(+) diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched index af3d6a3309826..86e3e39fd2e0d 100644 --- a/block/Kconfig.iosched +++ b/block/Kconfig.iosched @@ -50,6 +50,27 @@ config CFQ_GROUP_IOSCHED ---help--- Enable group IO scheduling in CFQ. +config IOSCHED_BFQ + tristate "BFQ I/O scheduler" + default n + ---help--- + The BFQ I/O scheduler tries to distribute bandwidth among + all processes according to their weights. + It aims at distributing the bandwidth as desired, independently of + the disk parameters and with any workload. It also tries to + guarantee low latency to interactive and soft real-time + applications. If compiled built-in (saying Y here), BFQ can + be configured to support hierarchical scheduling. + +config CGROUP_BFQIO + bool "BFQ hierarchical scheduling support" + depends on CGROUPS && IOSCHED_BFQ=y + default n + ---help--- + Enable hierarchical scheduling in BFQ, using the cgroups + filesystem interface. The name of the subsystem will be + bfqio. + choice prompt "Default I/O scheduler" default DEFAULT_CFQ @@ -63,6 +84,16 @@ choice config DEFAULT_CFQ bool "CFQ" if IOSCHED_CFQ=y + config DEFAULT_BFQ + bool "BFQ" if IOSCHED_BFQ=y + help + Selects BFQ as the default I/O scheduler which will be + used by default for all block devices. + The BFQ I/O scheduler aims at distributing the bandwidth + as desired, independently of the disk parameters and with + any workload. It also tries to guarantee low latency to + interactive and soft real-time applications. + config DEFAULT_NOOP bool "No-op" @@ -72,6 +103,7 @@ config DEFAULT_IOSCHED string default "deadline" if DEFAULT_DEADLINE default "cfq" if DEFAULT_CFQ + default "bfq" if DEFAULT_BFQ default "noop" if DEFAULT_NOOP endmenu diff --git a/block/Makefile b/block/Makefile index ba63d68fe91db..f20a761070734 100644 --- a/block/Makefile +++ b/block/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_BLK_DEV_THROTTLING) += blk-throttle.o obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o +obj-$(CONFIG_IOSCHED_BFQ) += bfq-iosched.o obj-$(CONFIG_IOSCHED_TEST) += test-iosched.o obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h index 23befa049e652..e6dc66f4e5bce 100644 --- a/include/linux/cgroup_subsys.h +++ b/include/linux/cgroup_subsys.h @@ -23,6 +23,10 @@ SUBSYS(schedtune) SUBSYS(blkio) #endif +#if IS_ENABLED(CONFIG_CGROUP_BFQIO) +SUBSYS(bfqio) +#endif + #if IS_ENABLED(CONFIG_MEMCG) SUBSYS(memory) #endif From 5a415f36e1cbd3fe8750c9ea9ed4757d042cc9f1 Mon Sep 17 00:00:00 2001 From: Paolo Valente Date: Thu, 9 May 2013 19:10:02 +0200 Subject: [PATCH 503/508] block: introduce the BFQ-v7r8 I/O sched for 3.18.0 Add the BFQ-v7r8 I/O scheduler to 3.18.0. The general structure is borrowed from CFQ, as much of the code for handling I/O contexts. Over time, several useful features have been ported from CFQ as well (details in the changelog in README.BFQ). A (bfq_)queue is associated to each task doing I/O on a device, and each time a scheduling decision has to be made a queue is selected and served until it expires. - Slices are given in the service domain: tasks are assigned budgets, measured in number of sectors. Once got the disk, a task must however consume its assigned budget within a configurable maximum time (by default, the maximum possible value of the budgets is automatically computed to comply with this timeout). This allows the desired latency vs "throughput boosting" tradeoff to be set. - Budgets are scheduled according to a variant of WF2Q+, implemented using an augmented rb-tree to take eligibility into account while preserving an O(log N) overall complexity. - A low-latency tunable is provided; if enabled, both interactive and soft real-time applications are guaranteed a very low latency. - Latency guarantees are preserved also in the presence of NCQ. - Also with flash-based devices, a high throughput is achieved while still preserving latency guarantees. - BFQ features Early Queue Merge (EQM), a sort of fusion of the cooperating-queue-merging and the preemption mechanisms present in CFQ. EQM is in fact a unified mechanism that tries to get a sequential read pattern, and hence a high throughput, with any set of processes performing interleaved I/O over a contiguous sequence of sectors. - BFQ supports full hierarchical scheduling, exporting a cgroups interface. Since each node has a full scheduler, each group can be assigned its own weight. - If the cgroups interface is not used, only I/O priorities can be assigned to processes, with ioprio values mapped to weights with the relation weight = IOPRIO_BE_NR - ioprio. - ioprio classes are served in strict priority order, i.e., lower priority queues are not served as long as there are higher priority queues. Among queues in the same class the bandwidth is distributed in proportion to the weight of each queue. A very thin extra bandwidth is however guaranteed to the Idle class, to prevent it from starving. Change-Id: I8da08487ff332f178a121c3d906f972f37a71da9 Signed-off-by: Paolo Valente Signed-off-by: Arianna Avanzini --- block/bfq-cgroup.c | 936 +++++++++++ block/bfq-ioc.c | 36 + block/bfq-iosched.c | 3898 +++++++++++++++++++++++++++++++++++++++++++ block/bfq-sched.c | 1208 ++++++++++++++ block/bfq.h | 771 +++++++++ 5 files changed, 6849 insertions(+) create mode 100644 block/bfq-cgroup.c create mode 100644 block/bfq-ioc.c create mode 100644 block/bfq-iosched.c create mode 100644 block/bfq-sched.c create mode 100644 block/bfq.h diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c new file mode 100644 index 0000000000000..11e2f1d4e73c7 --- /dev/null +++ b/block/bfq-cgroup.c @@ -0,0 +1,936 @@ +/* + * BFQ: CGROUPS support. + * + * Based on ideas and code from CFQ: + * Copyright (C) 2003 Jens Axboe + * + * Copyright (C) 2008 Fabio Checconi + * Paolo Valente + * + * Copyright (C) 2010 Paolo Valente + * + * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ + * file. + */ + +#ifdef CONFIG_CGROUP_BFQIO + +static DEFINE_MUTEX(bfqio_mutex); + +static bool bfqio_is_removed(struct bfqio_cgroup *bgrp) +{ + return bgrp ? !bgrp->online : false; +} + +static struct bfqio_cgroup bfqio_root_cgroup = { + .weight = BFQ_DEFAULT_GRP_WEIGHT, + .ioprio = BFQ_DEFAULT_GRP_IOPRIO, + .ioprio_class = BFQ_DEFAULT_GRP_CLASS, +}; + +static inline void bfq_init_entity(struct bfq_entity *entity, + struct bfq_group *bfqg) +{ + entity->weight = entity->new_weight; + entity->orig_weight = entity->new_weight; + entity->ioprio = entity->new_ioprio; + entity->ioprio_class = entity->new_ioprio_class; + entity->parent = bfqg->my_entity; + entity->sched_data = &bfqg->sched_data; +} + +static struct bfqio_cgroup *css_to_bfqio(struct cgroup_subsys_state *css) +{ + return css ? container_of(css, struct bfqio_cgroup, css) : NULL; +} + +/* + * Search the bfq_group for bfqd into the hash table (by now only a list) + * of bgrp. Must be called under rcu_read_lock(). + */ +static struct bfq_group *bfqio_lookup_group(struct bfqio_cgroup *bgrp, + struct bfq_data *bfqd) +{ + struct bfq_group *bfqg; + void *key; + + hlist_for_each_entry_rcu(bfqg, &bgrp->group_data, group_node) { + key = rcu_dereference(bfqg->bfqd); + if (key == bfqd) + return bfqg; + } + + return NULL; +} + +static inline void bfq_group_init_entity(struct bfqio_cgroup *bgrp, + struct bfq_group *bfqg) +{ + struct bfq_entity *entity = &bfqg->entity; + + /* + * If the weight of the entity has never been set via the sysfs + * interface, then bgrp->weight == 0. In this case we initialize + * the weight from the current ioprio value. Otherwise, the group + * weight, if set, has priority over the ioprio value. + */ + if (bgrp->weight == 0) { + entity->new_weight = bfq_ioprio_to_weight(bgrp->ioprio); + entity->new_ioprio = bgrp->ioprio; + } else { + if (bgrp->weight < BFQ_MIN_WEIGHT || + bgrp->weight > BFQ_MAX_WEIGHT) { + printk(KERN_CRIT "bfq_group_init_entity: " + "bgrp->weight %d\n", bgrp->weight); + BUG(); + } + entity->new_weight = bgrp->weight; + entity->new_ioprio = bfq_weight_to_ioprio(bgrp->weight); + } + entity->orig_weight = entity->weight = entity->new_weight; + entity->ioprio = entity->new_ioprio; + entity->ioprio_class = entity->new_ioprio_class = bgrp->ioprio_class; + entity->my_sched_data = &bfqg->sched_data; + bfqg->active_entities = 0; +} + +static inline void bfq_group_set_parent(struct bfq_group *bfqg, + struct bfq_group *parent) +{ + struct bfq_entity *entity; + + BUG_ON(parent == NULL); + BUG_ON(bfqg == NULL); + + entity = &bfqg->entity; + entity->parent = parent->my_entity; + entity->sched_data = &parent->sched_data; +} + +/** + * bfq_group_chain_alloc - allocate a chain of groups. + * @bfqd: queue descriptor. + * @css: the leaf cgroup_subsys_state this chain starts from. + * + * Allocate a chain of groups starting from the one belonging to + * @cgroup up to the root cgroup. Stop if a cgroup on the chain + * to the root has already an allocated group on @bfqd. + */ +static struct bfq_group *bfq_group_chain_alloc(struct bfq_data *bfqd, + struct cgroup_subsys_state *css) +{ + struct bfqio_cgroup *bgrp; + struct bfq_group *bfqg, *prev = NULL, *leaf = NULL; + + for (; css != NULL; css = css->parent) { + bgrp = css_to_bfqio(css); + + bfqg = bfqio_lookup_group(bgrp, bfqd); + if (bfqg != NULL) { + /* + * All the cgroups in the path from there to the + * root must have a bfq_group for bfqd, so we don't + * need any more allocations. + */ + break; + } + + bfqg = kzalloc(sizeof(*bfqg), GFP_ATOMIC); + if (bfqg == NULL) + goto cleanup; + + bfq_group_init_entity(bgrp, bfqg); + bfqg->my_entity = &bfqg->entity; + + if (leaf == NULL) { + leaf = bfqg; + prev = leaf; + } else { + bfq_group_set_parent(prev, bfqg); + /* + * Build a list of allocated nodes using the bfqd + * filed, that is still unused and will be + * initialized only after the node will be + * connected. + */ + prev->bfqd = bfqg; + prev = bfqg; + } + } + + return leaf; + +cleanup: + while (leaf != NULL) { + prev = leaf; + leaf = leaf->bfqd; + kfree(prev); + } + + return NULL; +} + +/** + * bfq_group_chain_link - link an allocated group chain to a cgroup + * hierarchy. + * @bfqd: the queue descriptor. + * @css: the leaf cgroup_subsys_state to start from. + * @leaf: the leaf group (to be associated to @cgroup). + * + * Try to link a chain of groups to a cgroup hierarchy, connecting the + * nodes bottom-up, so we can be sure that when we find a cgroup in the + * hierarchy that already as a group associated to @bfqd all the nodes + * in the path to the root cgroup have one too. + * + * On locking: the queue lock protects the hierarchy (there is a hierarchy + * per device) while the bfqio_cgroup lock protects the list of groups + * belonging to the same cgroup. + */ +static void bfq_group_chain_link(struct bfq_data *bfqd, + struct cgroup_subsys_state *css, + struct bfq_group *leaf) +{ + struct bfqio_cgroup *bgrp; + struct bfq_group *bfqg, *next, *prev = NULL; + unsigned long flags; + + assert_spin_locked(bfqd->queue->queue_lock); + + for (; css != NULL && leaf != NULL; css = css->parent) { + bgrp = css_to_bfqio(css); + next = leaf->bfqd; + + bfqg = bfqio_lookup_group(bgrp, bfqd); + BUG_ON(bfqg != NULL); + + spin_lock_irqsave(&bgrp->lock, flags); + + rcu_assign_pointer(leaf->bfqd, bfqd); + hlist_add_head_rcu(&leaf->group_node, &bgrp->group_data); + hlist_add_head(&leaf->bfqd_node, &bfqd->group_list); + + spin_unlock_irqrestore(&bgrp->lock, flags); + + prev = leaf; + leaf = next; + } + + BUG_ON(css == NULL && leaf != NULL); + if (css != NULL && prev != NULL) { + bgrp = css_to_bfqio(css); + bfqg = bfqio_lookup_group(bgrp, bfqd); + bfq_group_set_parent(prev, bfqg); + } +} + +/** + * bfq_find_alloc_group - return the group associated to @bfqd in @cgroup. + * @bfqd: queue descriptor. + * @cgroup: cgroup being searched for. + * + * Return a group associated to @bfqd in @cgroup, allocating one if + * necessary. When a group is returned all the cgroups in the path + * to the root have a group associated to @bfqd. + * + * If the allocation fails, return the root group: this breaks guarantees + * but is a safe fallback. If this loss becomes a problem it can be + * mitigated using the equivalent weight (given by the product of the + * weights of the groups in the path from @group to the root) in the + * root scheduler. + * + * We allocate all the missing nodes in the path from the leaf cgroup + * to the root and we connect the nodes only after all the allocations + * have been successful. + */ +static struct bfq_group *bfq_find_alloc_group(struct bfq_data *bfqd, + struct cgroup_subsys_state *css) +{ + struct bfqio_cgroup *bgrp = css_to_bfqio(css); + struct bfq_group *bfqg; + + bfqg = bfqio_lookup_group(bgrp, bfqd); + if (bfqg != NULL) + return bfqg; + + bfqg = bfq_group_chain_alloc(bfqd, css); + if (bfqg != NULL) + bfq_group_chain_link(bfqd, css, bfqg); + else + bfqg = bfqd->root_group; + + return bfqg; +} + +/** + * bfq_bfqq_move - migrate @bfqq to @bfqg. + * @bfqd: queue descriptor. + * @bfqq: the queue to move. + * @entity: @bfqq's entity. + * @bfqg: the group to move to. + * + * Move @bfqq to @bfqg, deactivating it from its old group and reactivating + * it on the new one. Avoid putting the entity on the old group idle tree. + * + * Must be called under the queue lock; the cgroup owning @bfqg must + * not disappear (by now this just means that we are called under + * rcu_read_lock()). + */ +static void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, + struct bfq_entity *entity, struct bfq_group *bfqg) +{ + int busy, resume; + + busy = bfq_bfqq_busy(bfqq); + resume = !RB_EMPTY_ROOT(&bfqq->sort_list); + + BUG_ON(resume && !entity->on_st); + BUG_ON(busy && !resume && entity->on_st && + bfqq != bfqd->in_service_queue); + + if (busy) { + BUG_ON(atomic_read(&bfqq->ref) < 2); + + if (!resume) + bfq_del_bfqq_busy(bfqd, bfqq, 0); + else + bfq_deactivate_bfqq(bfqd, bfqq, 0); + } else if (entity->on_st) + bfq_put_idle_entity(bfq_entity_service_tree(entity), entity); + + /* + * Here we use a reference to bfqg. We don't need a refcounter + * as the cgroup reference will not be dropped, so that its + * destroy() callback will not be invoked. + */ + entity->parent = bfqg->my_entity; + entity->sched_data = &bfqg->sched_data; + + if (busy && resume) + bfq_activate_bfqq(bfqd, bfqq); + + if (bfqd->in_service_queue == NULL && !bfqd->rq_in_driver) + bfq_schedule_dispatch(bfqd); +} + +/** + * __bfq_bic_change_cgroup - move @bic to @cgroup. + * @bfqd: the queue descriptor. + * @bic: the bic to move. + * @cgroup: the cgroup to move to. + * + * Move bic to cgroup, assuming that bfqd->queue is locked; the caller + * has to make sure that the reference to cgroup is valid across the call. + * + * NOTE: an alternative approach might have been to store the current + * cgroup in bfqq and getting a reference to it, reducing the lookup + * time here, at the price of slightly more complex code. + */ +static struct bfq_group *__bfq_bic_change_cgroup(struct bfq_data *bfqd, + struct bfq_io_cq *bic, + struct cgroup_subsys_state *css) +{ + struct bfq_queue *async_bfqq = bic_to_bfqq(bic, 0); + struct bfq_queue *sync_bfqq = bic_to_bfqq(bic, 1); + struct bfq_entity *entity; + struct bfq_group *bfqg; + struct bfqio_cgroup *bgrp; + + bgrp = css_to_bfqio(css); + + bfqg = bfq_find_alloc_group(bfqd, css); + if (async_bfqq != NULL) { + entity = &async_bfqq->entity; + + if (entity->sched_data != &bfqg->sched_data) { + bic_set_bfqq(bic, NULL, 0); + bfq_log_bfqq(bfqd, async_bfqq, + "bic_change_group: %p %d", + async_bfqq, atomic_read(&async_bfqq->ref)); + bfq_put_queue(async_bfqq); + } + } + + if (sync_bfqq != NULL) { + entity = &sync_bfqq->entity; + if (entity->sched_data != &bfqg->sched_data) + bfq_bfqq_move(bfqd, sync_bfqq, entity, bfqg); + } + + return bfqg; +} + +/** + * bfq_bic_change_cgroup - move @bic to @cgroup. + * @bic: the bic being migrated. + * @cgroup: the destination cgroup. + * + * When the task owning @bic is moved to @cgroup, @bic is immediately + * moved into its new parent group. + */ +static void bfq_bic_change_cgroup(struct bfq_io_cq *bic, + struct cgroup_subsys_state *css) +{ + struct bfq_data *bfqd; + unsigned long uninitialized_var(flags); + + bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data), + &flags); + if (bfqd != NULL) { + __bfq_bic_change_cgroup(bfqd, bic, css); + bfq_put_bfqd_unlock(bfqd, &flags); + } +} + +/** + * bfq_bic_update_cgroup - update the cgroup of @bic. + * @bic: the @bic to update. + * + * Make sure that @bic is enqueued in the cgroup of the current task. + * We need this in addition to moving bics during the cgroup attach + * phase because the task owning @bic could be at its first disk + * access or we may end up in the root cgroup as the result of a + * memory allocation failure and here we try to move to the right + * group. + * + * Must be called under the queue lock. It is safe to use the returned + * value even after the rcu_read_unlock() as the migration/destruction + * paths act under the queue lock too. IOW it is impossible to race with + * group migration/destruction and end up with an invalid group as: + * a) here cgroup has not yet been destroyed, nor its destroy callback + * has started execution, as current holds a reference to it, + * b) if it is destroyed after rcu_read_unlock() [after current is + * migrated to a different cgroup] its attach() callback will have + * taken care of remove all the references to the old cgroup data. + */ +static struct bfq_group *bfq_bic_update_cgroup(struct bfq_io_cq *bic) +{ + struct bfq_data *bfqd = bic_to_bfqd(bic); + struct bfq_group *bfqg; + struct cgroup_subsys_state *css; + + BUG_ON(bfqd == NULL); + + rcu_read_lock(); + css = task_css(current, bfqio_cgrp_id); + bfqg = __bfq_bic_change_cgroup(bfqd, bic, css); + rcu_read_unlock(); + + return bfqg; +} + +/** + * bfq_flush_idle_tree - deactivate any entity on the idle tree of @st. + * @st: the service tree being flushed. + */ +static inline void bfq_flush_idle_tree(struct bfq_service_tree *st) +{ + struct bfq_entity *entity = st->first_idle; + + for (; entity != NULL; entity = st->first_idle) + __bfq_deactivate_entity(entity, 0); +} + +/** + * bfq_reparent_leaf_entity - move leaf entity to the root_group. + * @bfqd: the device data structure with the root group. + * @entity: the entity to move. + */ +static inline void bfq_reparent_leaf_entity(struct bfq_data *bfqd, + struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + + BUG_ON(bfqq == NULL); + bfq_bfqq_move(bfqd, bfqq, entity, bfqd->root_group); + return; +} + +/** + * bfq_reparent_active_entities - move to the root group all active + * entities. + * @bfqd: the device data structure with the root group. + * @bfqg: the group to move from. + * @st: the service tree with the entities. + * + * Needs queue_lock to be taken and reference to be valid over the call. + */ +static inline void bfq_reparent_active_entities(struct bfq_data *bfqd, + struct bfq_group *bfqg, + struct bfq_service_tree *st) +{ + struct rb_root *active = &st->active; + struct bfq_entity *entity = NULL; + + if (!RB_EMPTY_ROOT(&st->active)) + entity = bfq_entity_of(rb_first(active)); + + for (; entity != NULL; entity = bfq_entity_of(rb_first(active))) + bfq_reparent_leaf_entity(bfqd, entity); + + if (bfqg->sched_data.in_service_entity != NULL) + bfq_reparent_leaf_entity(bfqd, + bfqg->sched_data.in_service_entity); + + return; +} + +/** + * bfq_destroy_group - destroy @bfqg. + * @bgrp: the bfqio_cgroup containing @bfqg. + * @bfqg: the group being destroyed. + * + * Destroy @bfqg, making sure that it is not referenced from its parent. + */ +static void bfq_destroy_group(struct bfqio_cgroup *bgrp, struct bfq_group *bfqg) +{ + struct bfq_data *bfqd; + struct bfq_service_tree *st; + struct bfq_entity *entity = bfqg->my_entity; + unsigned long uninitialized_var(flags); + int i; + + hlist_del(&bfqg->group_node); + + /* + * Empty all service_trees belonging to this group before + * deactivating the group itself. + */ + for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) { + st = bfqg->sched_data.service_tree + i; + + /* + * The idle tree may still contain bfq_queues belonging + * to exited task because they never migrated to a different + * cgroup from the one being destroyed now. No one else + * can access them so it's safe to act without any lock. + */ + bfq_flush_idle_tree(st); + + /* + * It may happen that some queues are still active + * (busy) upon group destruction (if the corresponding + * processes have been forced to terminate). We move + * all the leaf entities corresponding to these queues + * to the root_group. + * Also, it may happen that the group has an entity + * in service, which is disconnected from the active + * tree: it must be moved, too. + * There is no need to put the sync queues, as the + * scheduler has taken no reference. + */ + bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags); + if (bfqd != NULL) { + bfq_reparent_active_entities(bfqd, bfqg, st); + bfq_put_bfqd_unlock(bfqd, &flags); + } + BUG_ON(!RB_EMPTY_ROOT(&st->active)); + BUG_ON(!RB_EMPTY_ROOT(&st->idle)); + } + BUG_ON(bfqg->sched_data.next_in_service != NULL); + BUG_ON(bfqg->sched_data.in_service_entity != NULL); + + /* + * We may race with device destruction, take extra care when + * dereferencing bfqg->bfqd. + */ + bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags); + if (bfqd != NULL) { + hlist_del(&bfqg->bfqd_node); + __bfq_deactivate_entity(entity, 0); + bfq_put_async_queues(bfqd, bfqg); + bfq_put_bfqd_unlock(bfqd, &flags); + } + BUG_ON(entity->tree != NULL); + + /* + * No need to defer the kfree() to the end of the RCU grace + * period: we are called from the destroy() callback of our + * cgroup, so we can be sure that no one is a) still using + * this cgroup or b) doing lookups in it. + */ + kfree(bfqg); +} + +static void bfq_end_wr_async(struct bfq_data *bfqd) +{ + struct hlist_node *tmp; + struct bfq_group *bfqg; + + hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) + bfq_end_wr_async_queues(bfqd, bfqg); + bfq_end_wr_async_queues(bfqd, bfqd->root_group); +} + +/** + * bfq_disconnect_groups - disconnect @bfqd from all its groups. + * @bfqd: the device descriptor being exited. + * + * When the device exits we just make sure that no lookup can return + * the now unused group structures. They will be deallocated on cgroup + * destruction. + */ +static void bfq_disconnect_groups(struct bfq_data *bfqd) +{ + struct hlist_node *tmp; + struct bfq_group *bfqg; + + bfq_log(bfqd, "disconnect_groups beginning"); + hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) { + hlist_del(&bfqg->bfqd_node); + + __bfq_deactivate_entity(bfqg->my_entity, 0); + + /* + * Don't remove from the group hash, just set an + * invalid key. No lookups can race with the + * assignment as bfqd is being destroyed; this + * implies also that new elements cannot be added + * to the list. + */ + rcu_assign_pointer(bfqg->bfqd, NULL); + + bfq_log(bfqd, "disconnect_groups: put async for group %p", + bfqg); + bfq_put_async_queues(bfqd, bfqg); + } +} + +static inline void bfq_free_root_group(struct bfq_data *bfqd) +{ + struct bfqio_cgroup *bgrp = &bfqio_root_cgroup; + struct bfq_group *bfqg = bfqd->root_group; + + bfq_put_async_queues(bfqd, bfqg); + + spin_lock_irq(&bgrp->lock); + hlist_del_rcu(&bfqg->group_node); + spin_unlock_irq(&bgrp->lock); + + /* + * No need to synchronize_rcu() here: since the device is gone + * there cannot be any read-side access to its root_group. + */ + kfree(bfqg); +} + +static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node) +{ + struct bfq_group *bfqg; + struct bfqio_cgroup *bgrp; + int i; + + bfqg = kzalloc_node(sizeof(*bfqg), GFP_KERNEL, node); + if (bfqg == NULL) + return NULL; + + bfqg->entity.parent = NULL; + for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) + bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; + + bgrp = &bfqio_root_cgroup; + spin_lock_irq(&bgrp->lock); + rcu_assign_pointer(bfqg->bfqd, bfqd); + hlist_add_head_rcu(&bfqg->group_node, &bgrp->group_data); + spin_unlock_irq(&bgrp->lock); + + return bfqg; +} + +#define SHOW_FUNCTION(__VAR) \ +static u64 bfqio_cgroup_##__VAR##_read(struct cgroup_subsys_state *css, \ + struct cftype *cftype) \ +{ \ + struct bfqio_cgroup *bgrp = css_to_bfqio(css); \ + u64 ret = -ENODEV; \ + \ + mutex_lock(&bfqio_mutex); \ + if (bfqio_is_removed(bgrp)) \ + goto out_unlock; \ + \ + spin_lock_irq(&bgrp->lock); \ + ret = bgrp->__VAR; \ + spin_unlock_irq(&bgrp->lock); \ + \ +out_unlock: \ + mutex_unlock(&bfqio_mutex); \ + return ret; \ +} + +SHOW_FUNCTION(weight); +SHOW_FUNCTION(ioprio); +SHOW_FUNCTION(ioprio_class); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__VAR, __MIN, __MAX) \ +static int bfqio_cgroup_##__VAR##_write(struct cgroup_subsys_state *css,\ + struct cftype *cftype, \ + u64 val) \ +{ \ + struct bfqio_cgroup *bgrp = css_to_bfqio(css); \ + struct bfq_group *bfqg; \ + int ret = -EINVAL; \ + \ + if (val < (__MIN) || val > (__MAX)) \ + return ret; \ + \ + ret = -ENODEV; \ + mutex_lock(&bfqio_mutex); \ + if (bfqio_is_removed(bgrp)) \ + goto out_unlock; \ + ret = 0; \ + \ + spin_lock_irq(&bgrp->lock); \ + bgrp->__VAR = (unsigned short)val; \ + hlist_for_each_entry(bfqg, &bgrp->group_data, group_node) { \ + /* \ + * Setting the ioprio_changed flag of the entity \ + * to 1 with new_##__VAR == ##__VAR would re-set \ + * the value of the weight to its ioprio mapping. \ + * Set the flag only if necessary. \ + */ \ + if ((unsigned short)val != bfqg->entity.new_##__VAR) { \ + bfqg->entity.new_##__VAR = (unsigned short)val; \ + /* \ + * Make sure that the above new value has been \ + * stored in bfqg->entity.new_##__VAR before \ + * setting the ioprio_changed flag. In fact, \ + * this flag may be read asynchronously (in \ + * critical sections protected by a different \ + * lock than that held here), and finding this \ + * flag set may cause the execution of the code \ + * for updating parameters whose value may \ + * depend also on bfqg->entity.new_##__VAR (in \ + * __bfq_entity_update_weight_prio). \ + * This barrier makes sure that the new value \ + * of bfqg->entity.new_##__VAR is correctly \ + * seen in that code. \ + */ \ + smp_wmb(); \ + bfqg->entity.ioprio_changed = 1; \ + } \ + } \ + spin_unlock_irq(&bgrp->lock); \ + \ +out_unlock: \ + mutex_unlock(&bfqio_mutex); \ + return ret; \ +} + +STORE_FUNCTION(weight, BFQ_MIN_WEIGHT, BFQ_MAX_WEIGHT); +STORE_FUNCTION(ioprio, 0, IOPRIO_BE_NR - 1); +STORE_FUNCTION(ioprio_class, IOPRIO_CLASS_RT, IOPRIO_CLASS_IDLE); +#undef STORE_FUNCTION + +static struct cftype bfqio_files[] = { + { + .name = "weight", + .read_u64 = bfqio_cgroup_weight_read, + .write_u64 = bfqio_cgroup_weight_write, + }, + { + .name = "ioprio", + .read_u64 = bfqio_cgroup_ioprio_read, + .write_u64 = bfqio_cgroup_ioprio_write, + }, + { + .name = "ioprio_class", + .read_u64 = bfqio_cgroup_ioprio_class_read, + .write_u64 = bfqio_cgroup_ioprio_class_write, + }, + { }, /* terminate */ +}; + +static struct cgroup_subsys_state *bfqio_create(struct cgroup_subsys_state + *parent_css) +{ + struct bfqio_cgroup *bgrp; + + if (parent_css != NULL) { + bgrp = kzalloc(sizeof(*bgrp), GFP_KERNEL); + if (bgrp == NULL) + return ERR_PTR(-ENOMEM); + } else + bgrp = &bfqio_root_cgroup; + + spin_lock_init(&bgrp->lock); + INIT_HLIST_HEAD(&bgrp->group_data); + bgrp->ioprio = BFQ_DEFAULT_GRP_IOPRIO; + bgrp->ioprio_class = BFQ_DEFAULT_GRP_CLASS; + + return &bgrp->css; +} + +/* + * We cannot support shared io contexts, as we have no means to support + * two tasks with the same ioc in two different groups without major rework + * of the main bic/bfqq data structures. By now we allow a task to change + * its cgroup only if it's the only owner of its ioc; the drawback of this + * behavior is that a group containing a task that forked using CLONE_IO + * will not be destroyed until the tasks sharing the ioc die. + */ +static int bfqio_can_attach(struct cgroup_subsys_state *css, + struct cgroup_taskset *tset) +{ + struct task_struct *task; + struct io_context *ioc; + int ret = 0; + + cgroup_taskset_for_each(task, tset) { + /* + * task_lock() is needed to avoid races with + * exit_io_context() + */ + task_lock(task); + ioc = task->io_context; + if (ioc != NULL && atomic_read(&ioc->nr_tasks) > 1) + /* + * ioc == NULL means that the task is either too + * young or exiting: if it has still no ioc the + * ioc can't be shared, if the task is exiting the + * attach will fail anyway, no matter what we + * return here. + */ + ret = -EINVAL; + task_unlock(task); + if (ret) + break; + } + + return ret; +} + +static void bfqio_attach(struct cgroup_subsys_state *css, + struct cgroup_taskset *tset) +{ + struct task_struct *task; + struct io_context *ioc; + struct io_cq *icq; + + /* + * IMPORTANT NOTE: The move of more than one process at a time to a + * new group has not yet been tested. + */ + cgroup_taskset_for_each(task, tset) { + ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE); + if (ioc) { + /* + * Handle cgroup change here. + */ + rcu_read_lock(); + hlist_for_each_entry_rcu(icq, &ioc->icq_list, ioc_node) + if (!strncmp( + icq->q->elevator->type->elevator_name, + "bfq", ELV_NAME_MAX)) + bfq_bic_change_cgroup(icq_to_bic(icq), + css); + rcu_read_unlock(); + put_io_context(ioc); + } + } +} + +static void bfqio_destroy(struct cgroup_subsys_state *css) +{ + struct bfqio_cgroup *bgrp = css_to_bfqio(css); + struct hlist_node *tmp; + struct bfq_group *bfqg; + + /* + * Since we are destroying the cgroup, there are no more tasks + * referencing it, and all the RCU grace periods that may have + * referenced it are ended (as the destruction of the parent + * cgroup is RCU-safe); bgrp->group_data will not be accessed by + * anything else and we don't need any synchronization. + */ + hlist_for_each_entry_safe(bfqg, tmp, &bgrp->group_data, group_node) + bfq_destroy_group(bgrp, bfqg); + + BUG_ON(!hlist_empty(&bgrp->group_data)); + + kfree(bgrp); +} + +static int bfqio_css_online(struct cgroup_subsys_state *css) +{ + struct bfqio_cgroup *bgrp = css_to_bfqio(css); + + mutex_lock(&bfqio_mutex); + bgrp->online = true; + mutex_unlock(&bfqio_mutex); + + return 0; +} + +static void bfqio_css_offline(struct cgroup_subsys_state *css) +{ + struct bfqio_cgroup *bgrp = css_to_bfqio(css); + + mutex_lock(&bfqio_mutex); + bgrp->online = false; + mutex_unlock(&bfqio_mutex); +} + +struct cgroup_subsys bfqio_cgrp_subsys = { + .css_alloc = bfqio_create, + .css_online = bfqio_css_online, + .css_offline = bfqio_css_offline, + .can_attach = bfqio_can_attach, + .attach = bfqio_attach, + .css_free = bfqio_destroy, + .legacy_cftypes = bfqio_files, +}; +#else +static inline void bfq_init_entity(struct bfq_entity *entity, + struct bfq_group *bfqg) +{ + entity->weight = entity->new_weight; + entity->orig_weight = entity->new_weight; + entity->ioprio = entity->new_ioprio; + entity->ioprio_class = entity->new_ioprio_class; + entity->sched_data = &bfqg->sched_data; +} + +static inline struct bfq_group * +bfq_bic_update_cgroup(struct bfq_io_cq *bic) +{ + struct bfq_data *bfqd = bic_to_bfqd(bic); + return bfqd->root_group; +} + +static inline void bfq_bfqq_move(struct bfq_data *bfqd, + struct bfq_queue *bfqq, + struct bfq_entity *entity, + struct bfq_group *bfqg) +{ +} + +static void bfq_end_wr_async(struct bfq_data *bfqd) +{ + bfq_end_wr_async_queues(bfqd, bfqd->root_group); +} + +static inline void bfq_disconnect_groups(struct bfq_data *bfqd) +{ + bfq_put_async_queues(bfqd, bfqd->root_group); +} + +static inline void bfq_free_root_group(struct bfq_data *bfqd) +{ + kfree(bfqd->root_group); +} + +static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node) +{ + struct bfq_group *bfqg; + int i; + + bfqg = kmalloc_node(sizeof(*bfqg), GFP_KERNEL | __GFP_ZERO, node); + if (bfqg == NULL) + return NULL; + + for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) + bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; + + return bfqg; +} +#endif diff --git a/block/bfq-ioc.c b/block/bfq-ioc.c new file mode 100644 index 0000000000000..7f6b0004ca701 --- /dev/null +++ b/block/bfq-ioc.c @@ -0,0 +1,36 @@ +/* + * BFQ: I/O context handling. + * + * Based on ideas and code from CFQ: + * Copyright (C) 2003 Jens Axboe + * + * Copyright (C) 2008 Fabio Checconi + * Paolo Valente + * + * Copyright (C) 2010 Paolo Valente + */ + +/** + * icq_to_bic - convert iocontext queue structure to bfq_io_cq. + * @icq: the iocontext queue. + */ +static inline struct bfq_io_cq *icq_to_bic(struct io_cq *icq) +{ + /* bic->icq is the first member, %NULL will convert to %NULL */ + return container_of(icq, struct bfq_io_cq, icq); +} + +/** + * bfq_bic_lookup - search into @ioc a bic associated to @bfqd. + * @bfqd: the lookup key. + * @ioc: the io_context of the process doing I/O. + * + * Queue lock must be held. + */ +static inline struct bfq_io_cq *bfq_bic_lookup(struct bfq_data *bfqd, + struct io_context *ioc) +{ + if (ioc) + return icq_to_bic(ioc_lookup_icq(ioc, bfqd->queue)); + return NULL; +} diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c new file mode 100644 index 0000000000000..773b2ee064b23 --- /dev/null +++ b/block/bfq-iosched.c @@ -0,0 +1,3898 @@ +/* + * Budget Fair Queueing (BFQ) disk scheduler. + * + * Based on ideas and code from CFQ: + * Copyright (C) 2003 Jens Axboe + * + * Copyright (C) 2008 Fabio Checconi + * Paolo Valente + * + * Copyright (C) 2010 Paolo Valente + * + * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ + * file. + * + * BFQ is a proportional-share storage-I/O scheduling algorithm based on + * the slice-by-slice service scheme of CFQ. But BFQ assigns budgets, + * measured in number of sectors, to processes instead of time slices. The + * device is not granted to the in-service process for a given time slice, + * but until it has exhausted its assigned budget. This change from the time + * to the service domain allows BFQ to distribute the device throughput + * among processes as desired, without any distortion due to ZBR, workload + * fluctuations or other factors. BFQ uses an ad hoc internal scheduler, + * called B-WF2Q+, to schedule processes according to their budgets. More + * precisely, BFQ schedules queues associated to processes. Thanks to the + * accurate policy of B-WF2Q+, BFQ can afford to assign high budgets to + * I/O-bound processes issuing sequential requests (to boost the + * throughput), and yet guarantee a low latency to interactive and soft + * real-time applications. + * + * BFQ is described in [1], where also a reference to the initial, more + * theoretical paper on BFQ can be found. The interested reader can find + * in the latter paper full details on the main algorithm, as well as + * formulas of the guarantees and formal proofs of all the properties. + * With respect to the version of BFQ presented in these papers, this + * implementation adds a few more heuristics, such as the one that + * guarantees a low latency to soft real-time applications, and a + * hierarchical extension based on H-WF2Q+. + * + * B-WF2Q+ is based on WF2Q+, that is described in [2], together with + * H-WF2Q+, while the augmented tree used to implement B-WF2Q+ with O(log N) + * complexity derives from the one introduced with EEVDF in [3]. + * + * [1] P. Valente and M. Andreolini, ``Improving Application Responsiveness + * with the BFQ Disk I/O Scheduler'', + * Proceedings of the 5th Annual International Systems and Storage + * Conference (SYSTOR '12), June 2012. + * + * http://algogroup.unimo.it/people/paolo/disk_sched/bf1-v1-suite-results.pdf + * + * [2] Jon C.R. Bennett and H. Zhang, ``Hierarchical Packet Fair Queueing + * Algorithms,'' IEEE/ACM Transactions on Networking, 5(5):675-689, + * Oct 1997. + * + * http://www.cs.cmu.edu/~hzhang/papers/TON-97-Oct.ps.gz + * + * [3] I. Stoica and H. Abdel-Wahab, ``Earliest Eligible Virtual Deadline + * First: A Flexible and Accurate Mechanism for Proportional Share + * Resource Allocation,'' technical report. + * + * http://www.cs.berkeley.edu/~istoica/papers/eevdf-tr-95.pdf + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "bfq.h" +#include "blk.h" + +/* Expiration time of sync (0) and async (1) requests, in jiffies. */ +static const int bfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; + +/* Maximum backwards seek, in KiB. */ +static const int bfq_back_max = 16 * 1024; + +/* Penalty of a backwards seek, in number of sectors. */ +static const int bfq_back_penalty = 2; + +/* Idling period duration, in jiffies. */ +static int bfq_slice_idle = HZ / 125; + +/* Default maximum budget values, in sectors and number of requests. */ +static const int bfq_default_max_budget = 16 * 1024; +static const int bfq_max_budget_async_rq = 4; + +/* + * Async to sync throughput distribution is controlled as follows: + * when an async request is served, the entity is charged the number + * of sectors of the request, multiplied by the factor below + */ +static const int bfq_async_charge_factor = 10; + +/* Default timeout values, in jiffies, approximating CFQ defaults. */ +static const int bfq_timeout_sync = HZ / 8; +static int bfq_timeout_async = HZ / 25; + +struct kmem_cache *bfq_pool; + +/* Below this threshold (in ms), we consider thinktime immediate. */ +#define BFQ_MIN_TT 2 + +/* hw_tag detection: parallel requests threshold and min samples needed. */ +#define BFQ_HW_QUEUE_THRESHOLD 4 +#define BFQ_HW_QUEUE_SAMPLES 32 + +#define BFQQ_SEEK_THR (sector_t)(8 * 1024) +#define BFQQ_SEEKY(bfqq) ((bfqq)->seek_mean > BFQQ_SEEK_THR) + +/* Min samples used for peak rate estimation (for autotuning). */ +#define BFQ_PEAK_RATE_SAMPLES 32 + +/* Shift used for peak rate fixed precision calculations. */ +#define BFQ_RATE_SHIFT 16 + +/* + * By default, BFQ computes the duration of the weight raising for + * interactive applications automatically, using the following formula: + * duration = (R / r) * T, where r is the peak rate of the device, and + * R and T are two reference parameters. + * In particular, R is the peak rate of the reference device (see below), + * and T is a reference time: given the systems that are likely to be + * installed on the reference device according to its speed class, T is + * about the maximum time needed, under BFQ and while reading two files in + * parallel, to load typical large applications on these systems. + * In practice, the slower/faster the device at hand is, the more/less it + * takes to load applications with respect to the reference device. + * Accordingly, the longer/shorter BFQ grants weight raising to interactive + * applications. + * + * BFQ uses four different reference pairs (R, T), depending on: + * . whether the device is rotational or non-rotational; + * . whether the device is slow, such as old or portable HDDs, as well as + * SD cards, or fast, such as newer HDDs and SSDs. + * + * The device's speed class is dynamically (re)detected in + * bfq_update_peak_rate() every time the estimated peak rate is updated. + * + * In the following definitions, R_slow[0]/R_fast[0] and T_slow[0]/T_fast[0] + * are the reference values for a slow/fast rotational device, whereas + * R_slow[1]/R_fast[1] and T_slow[1]/T_fast[1] are the reference values for + * a slow/fast non-rotational device. Finally, device_speed_thresh are the + * thresholds used to switch between speed classes. + * Both the reference peak rates and the thresholds are measured in + * sectors/usec, left-shifted by BFQ_RATE_SHIFT. + */ +static int R_slow[2] = {1536, 10752}; +static int R_fast[2] = {17415, 34791}; +/* + * To improve readability, a conversion function is used to initialize the + * following arrays, which entails that they can be initialized only in a + * function. + */ +static int T_slow[2]; +static int T_fast[2]; +static int device_speed_thresh[2]; + +#define BFQ_SERVICE_TREE_INIT ((struct bfq_service_tree) \ + { RB_ROOT, RB_ROOT, NULL, NULL, 0, 0 }) + +#define RQ_BIC(rq) ((struct bfq_io_cq *) (rq)->elv.priv[0]) +#define RQ_BFQQ(rq) ((rq)->elv.priv[1]) + +static inline void bfq_schedule_dispatch(struct bfq_data *bfqd); + +#include "bfq-ioc.c" +#include "bfq-sched.c" +#include "bfq-cgroup.c" + +#define bfq_class_idle(bfqq) ((bfqq)->entity.ioprio_class ==\ + IOPRIO_CLASS_IDLE) +#define bfq_class_rt(bfqq) ((bfqq)->entity.ioprio_class ==\ + IOPRIO_CLASS_RT) + +#define bfq_sample_valid(samples) ((samples) > 80) + +/* + * The following macro groups conditions that need to be evaluated when + * checking if existing queues and groups form a symmetric scenario + * and therefore idling can be reduced or disabled for some of the + * queues. See the comment to the function bfq_bfqq_must_not_expire() + * for further details. + */ +#ifdef CONFIG_CGROUP_BFQIO +#define symmetric_scenario (!bfqd->active_numerous_groups && \ + !bfq_differentiated_weights(bfqd)) +#else +#define symmetric_scenario (!bfq_differentiated_weights(bfqd)) +#endif + +/* + * We regard a request as SYNC, if either it's a read or has the SYNC bit + * set (in which case it could also be a direct WRITE). + */ +static inline int bfq_bio_sync(struct bio *bio) +{ + if (bio_data_dir(bio) == READ || (bio->bi_rw & REQ_SYNC)) + return 1; + + return 0; +} + +/* + * Scheduler run of queue, if there are requests pending and no one in the + * driver that will restart queueing. + */ +static inline void bfq_schedule_dispatch(struct bfq_data *bfqd) +{ + if (bfqd->queued != 0) { + bfq_log(bfqd, "schedule dispatch"); + kblockd_schedule_work(&bfqd->unplug_work); + } +} + +/* + * Lifted from AS - choose which of rq1 and rq2 that is best served now. + * We choose the request that is closesr to the head right now. Distance + * behind the head is penalized and only allowed to a certain extent. + */ +static struct request *bfq_choose_req(struct bfq_data *bfqd, + struct request *rq1, + struct request *rq2, + sector_t last) +{ + sector_t s1, s2, d1 = 0, d2 = 0; + unsigned long back_max; +#define BFQ_RQ1_WRAP 0x01 /* request 1 wraps */ +#define BFQ_RQ2_WRAP 0x02 /* request 2 wraps */ + unsigned wrap = 0; /* bit mask: requests behind the disk head? */ + + if (rq1 == NULL || rq1 == rq2) + return rq2; + if (rq2 == NULL) + return rq1; + + if (rq_is_sync(rq1) && !rq_is_sync(rq2)) + return rq1; + else if (rq_is_sync(rq2) && !rq_is_sync(rq1)) + return rq2; + if ((rq1->cmd_flags & REQ_META) && !(rq2->cmd_flags & REQ_META)) + return rq1; + else if ((rq2->cmd_flags & REQ_META) && !(rq1->cmd_flags & REQ_META)) + return rq2; + + s1 = blk_rq_pos(rq1); + s2 = blk_rq_pos(rq2); + + /* + * By definition, 1KiB is 2 sectors. + */ + back_max = bfqd->bfq_back_max * 2; + + /* + * Strict one way elevator _except_ in the case where we allow + * short backward seeks which are biased as twice the cost of a + * similar forward seek. + */ + if (s1 >= last) + d1 = s1 - last; + else if (s1 + back_max >= last) + d1 = (last - s1) * bfqd->bfq_back_penalty; + else + wrap |= BFQ_RQ1_WRAP; + + if (s2 >= last) + d2 = s2 - last; + else if (s2 + back_max >= last) + d2 = (last - s2) * bfqd->bfq_back_penalty; + else + wrap |= BFQ_RQ2_WRAP; + + /* Found required data */ + + /* + * By doing switch() on the bit mask "wrap" we avoid having to + * check two variables for all permutations: --> faster! + */ + switch (wrap) { + case 0: /* common case for CFQ: rq1 and rq2 not wrapped */ + if (d1 < d2) + return rq1; + else if (d2 < d1) + return rq2; + else { + if (s1 >= s2) + return rq1; + else + return rq2; + } + + case BFQ_RQ2_WRAP: + return rq1; + case BFQ_RQ1_WRAP: + return rq2; + case (BFQ_RQ1_WRAP|BFQ_RQ2_WRAP): /* both rqs wrapped */ + default: + /* + * Since both rqs are wrapped, + * start with the one that's further behind head + * (--> only *one* back seek required), + * since back seek takes more time than forward. + */ + if (s1 <= s2) + return rq1; + else + return rq2; + } +} + +static struct bfq_queue * +bfq_rq_pos_tree_lookup(struct bfq_data *bfqd, struct rb_root *root, + sector_t sector, struct rb_node **ret_parent, + struct rb_node ***rb_link) +{ + struct rb_node **p, *parent; + struct bfq_queue *bfqq = NULL; + + parent = NULL; + p = &root->rb_node; + while (*p) { + struct rb_node **n; + + parent = *p; + bfqq = rb_entry(parent, struct bfq_queue, pos_node); + + /* + * Sort strictly based on sector. Smallest to the left, + * largest to the right. + */ + if (sector > blk_rq_pos(bfqq->next_rq)) + n = &(*p)->rb_right; + else if (sector < blk_rq_pos(bfqq->next_rq)) + n = &(*p)->rb_left; + else + break; + p = n; + bfqq = NULL; + } + + *ret_parent = parent; + if (rb_link) + *rb_link = p; + + bfq_log(bfqd, "rq_pos_tree_lookup %llu: returning %d", + (long long unsigned)sector, + bfqq != NULL ? bfqq->pid : 0); + + return bfqq; +} + +static void bfq_rq_pos_tree_add(struct bfq_data *bfqd, struct bfq_queue *bfqq) +{ + struct rb_node **p, *parent; + struct bfq_queue *__bfqq; + + if (bfqq->pos_root != NULL) { + rb_erase(&bfqq->pos_node, bfqq->pos_root); + bfqq->pos_root = NULL; + } + + if (bfq_class_idle(bfqq)) + return; + if (!bfqq->next_rq) + return; + + bfqq->pos_root = &bfqd->rq_pos_tree; + __bfqq = bfq_rq_pos_tree_lookup(bfqd, bfqq->pos_root, + blk_rq_pos(bfqq->next_rq), &parent, &p); + if (__bfqq == NULL) { + rb_link_node(&bfqq->pos_node, parent, p); + rb_insert_color(&bfqq->pos_node, bfqq->pos_root); + } else + bfqq->pos_root = NULL; +} + +/* + * Tell whether there are active queues or groups with differentiated weights. + */ +static inline bool bfq_differentiated_weights(struct bfq_data *bfqd) +{ + /* + * For weights to differ, at least one of the trees must contain + * at least two nodes. + */ + return (!RB_EMPTY_ROOT(&bfqd->queue_weights_tree) && + (bfqd->queue_weights_tree.rb_node->rb_left || + bfqd->queue_weights_tree.rb_node->rb_right) +#ifdef CONFIG_CGROUP_BFQIO + ) || + (!RB_EMPTY_ROOT(&bfqd->group_weights_tree) && + (bfqd->group_weights_tree.rb_node->rb_left || + bfqd->group_weights_tree.rb_node->rb_right) +#endif + ); +} + +/* + * If the weight-counter tree passed as input contains no counter for + * the weight of the input entity, then add that counter; otherwise just + * increment the existing counter. + * + * Note that weight-counter trees contain few nodes in mostly symmetric + * scenarios. For example, if all queues have the same weight, then the + * weight-counter tree for the queues may contain at most one node. + * This holds even if low_latency is on, because weight-raised queues + * are not inserted in the tree. + * In most scenarios, the rate at which nodes are created/destroyed + * should be low too. + */ +static void bfq_weights_tree_add(struct bfq_data *bfqd, + struct bfq_entity *entity, + struct rb_root *root) +{ + struct rb_node **new = &(root->rb_node), *parent = NULL; + + /* + * Do not insert if the entity is already associated with a + * counter, which happens if: + * 1) the entity is associated with a queue, + * 2) a request arrival has caused the queue to become both + * non-weight-raised, and hence change its weight, and + * backlogged; in this respect, each of the two events + * causes an invocation of this function, + * 3) this is the invocation of this function caused by the + * second event. This second invocation is actually useless, + * and we handle this fact by exiting immediately. More + * efficient or clearer solutions might possibly be adopted. + */ + if (entity->weight_counter) + return; + + while (*new) { + struct bfq_weight_counter *__counter = container_of(*new, + struct bfq_weight_counter, + weights_node); + parent = *new; + + if (entity->weight == __counter->weight) { + entity->weight_counter = __counter; + goto inc_counter; + } + if (entity->weight < __counter->weight) + new = &((*new)->rb_left); + else + new = &((*new)->rb_right); + } + + entity->weight_counter = kzalloc(sizeof(struct bfq_weight_counter), + GFP_ATOMIC); + entity->weight_counter->weight = entity->weight; + rb_link_node(&entity->weight_counter->weights_node, parent, new); + rb_insert_color(&entity->weight_counter->weights_node, root); + +inc_counter: + entity->weight_counter->num_active++; +} + +/* + * Decrement the weight counter associated with the entity, and, if the + * counter reaches 0, remove the counter from the tree. + * See the comments to the function bfq_weights_tree_add() for considerations + * about overhead. + */ +static void bfq_weights_tree_remove(struct bfq_data *bfqd, + struct bfq_entity *entity, + struct rb_root *root) +{ + if (!entity->weight_counter) + return; + + BUG_ON(RB_EMPTY_ROOT(root)); + BUG_ON(entity->weight_counter->weight != entity->weight); + + BUG_ON(!entity->weight_counter->num_active); + entity->weight_counter->num_active--; + if (entity->weight_counter->num_active > 0) + goto reset_entity_pointer; + + rb_erase(&entity->weight_counter->weights_node, root); + kfree(entity->weight_counter); + +reset_entity_pointer: + entity->weight_counter = NULL; +} + +static struct request *bfq_find_next_rq(struct bfq_data *bfqd, + struct bfq_queue *bfqq, + struct request *last) +{ + struct rb_node *rbnext = rb_next(&last->rb_node); + struct rb_node *rbprev = rb_prev(&last->rb_node); + struct request *next = NULL, *prev = NULL; + + BUG_ON(RB_EMPTY_NODE(&last->rb_node)); + + if (rbprev != NULL) + prev = rb_entry_rq(rbprev); + + if (rbnext != NULL) + next = rb_entry_rq(rbnext); + else { + rbnext = rb_first(&bfqq->sort_list); + if (rbnext && rbnext != &last->rb_node) + next = rb_entry_rq(rbnext); + } + + return bfq_choose_req(bfqd, next, prev, blk_rq_pos(last)); +} + +/* see the definition of bfq_async_charge_factor for details */ +static inline unsigned long bfq_serv_to_charge(struct request *rq, + struct bfq_queue *bfqq) +{ + return blk_rq_sectors(rq) * + (1 + ((!bfq_bfqq_sync(bfqq)) * (bfqq->wr_coeff == 1) * + bfq_async_charge_factor)); +} + +/** + * bfq_updated_next_req - update the queue after a new next_rq selection. + * @bfqd: the device data the queue belongs to. + * @bfqq: the queue to update. + * + * If the first request of a queue changes we make sure that the queue + * has enough budget to serve at least its first request (if the + * request has grown). We do this because if the queue has not enough + * budget for its first request, it has to go through two dispatch + * rounds to actually get it dispatched. + */ +static void bfq_updated_next_req(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + struct bfq_entity *entity = &bfqq->entity; + struct bfq_service_tree *st = bfq_entity_service_tree(entity); + struct request *next_rq = bfqq->next_rq; + unsigned long new_budget; + + if (next_rq == NULL) + return; + + if (bfqq == bfqd->in_service_queue) + /* + * In order not to break guarantees, budgets cannot be + * changed after an entity has been selected. + */ + return; + + BUG_ON(entity->tree != &st->active); + BUG_ON(entity == entity->sched_data->in_service_entity); + + new_budget = max_t(unsigned long, bfqq->max_budget, + bfq_serv_to_charge(next_rq, bfqq)); + if (entity->budget != new_budget) { + entity->budget = new_budget; + bfq_log_bfqq(bfqd, bfqq, "updated next rq: new budget %lu", + new_budget); + bfq_activate_bfqq(bfqd, bfqq); + } +} + +static inline unsigned int bfq_wr_duration(struct bfq_data *bfqd) +{ + u64 dur; + + if (bfqd->bfq_wr_max_time > 0) + return bfqd->bfq_wr_max_time; + + dur = bfqd->RT_prod; + do_div(dur, bfqd->peak_rate); + + return dur; +} + +/* Empty burst list and add just bfqq (see comments to bfq_handle_burst) */ +static inline void bfq_reset_burst_list(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + struct bfq_queue *item; + struct hlist_node *n; + + hlist_for_each_entry_safe(item, n, &bfqd->burst_list, burst_list_node) + hlist_del_init(&item->burst_list_node); + hlist_add_head(&bfqq->burst_list_node, &bfqd->burst_list); + bfqd->burst_size = 1; +} + +/* Add bfqq to the list of queues in current burst (see bfq_handle_burst) */ +static void bfq_add_to_burst(struct bfq_data *bfqd, struct bfq_queue *bfqq) +{ + /* Increment burst size to take into account also bfqq */ + bfqd->burst_size++; + + if (bfqd->burst_size == bfqd->bfq_large_burst_thresh) { + struct bfq_queue *pos, *bfqq_item; + struct hlist_node *n; + + /* + * Enough queues have been activated shortly after each + * other to consider this burst as large. + */ + bfqd->large_burst = true; + + /* + * We can now mark all queues in the burst list as + * belonging to a large burst. + */ + hlist_for_each_entry(bfqq_item, &bfqd->burst_list, + burst_list_node) + bfq_mark_bfqq_in_large_burst(bfqq_item); + bfq_mark_bfqq_in_large_burst(bfqq); + + /* + * From now on, and until the current burst finishes, any + * new queue being activated shortly after the last queue + * was inserted in the burst can be immediately marked as + * belonging to a large burst. So the burst list is not + * needed any more. Remove it. + */ + hlist_for_each_entry_safe(pos, n, &bfqd->burst_list, + burst_list_node) + hlist_del_init(&pos->burst_list_node); + } else /* burst not yet large: add bfqq to the burst list */ + hlist_add_head(&bfqq->burst_list_node, &bfqd->burst_list); +} + +/* + * If many queues happen to become active shortly after each other, then, + * to help the processes associated to these queues get their job done as + * soon as possible, it is usually better to not grant either weight-raising + * or device idling to these queues. In this comment we describe, firstly, + * the reasons why this fact holds, and, secondly, the next function, which + * implements the main steps needed to properly mark these queues so that + * they can then be treated in a different way. + * + * As for the terminology, we say that a queue becomes active, i.e., + * switches from idle to backlogged, either when it is created (as a + * consequence of the arrival of an I/O request), or, if already existing, + * when a new request for the queue arrives while the queue is idle. + * Bursts of activations, i.e., activations of different queues occurring + * shortly after each other, are typically caused by services or applications + * that spawn or reactivate many parallel threads/processes. Examples are + * systemd during boot or git grep. + * + * These services or applications benefit mostly from a high throughput: + * the quicker the requests of the activated queues are cumulatively served, + * the sooner the target job of these queues gets completed. As a consequence, + * weight-raising any of these queues, which also implies idling the device + * for it, is almost always counterproductive: in most cases it just lowers + * throughput. + * + * On the other hand, a burst of activations may be also caused by the start + * of an application that does not consist in a lot of parallel I/O-bound + * threads. In fact, with a complex application, the burst may be just a + * consequence of the fact that several processes need to be executed to + * start-up the application. To start an application as quickly as possible, + * the best thing to do is to privilege the I/O related to the application + * with respect to all other I/O. Therefore, the best strategy to start as + * quickly as possible an application that causes a burst of activations is + * to weight-raise all the queues activated during the burst. This is the + * exact opposite of the best strategy for the other type of bursts. + * + * In the end, to take the best action for each of the two cases, the two + * types of bursts need to be distinguished. Fortunately, this seems + * relatively easy to do, by looking at the sizes of the bursts. In + * particular, we found a threshold such that bursts with a larger size + * than that threshold are apparently caused only by services or commands + * such as systemd or git grep. For brevity, hereafter we call just 'large' + * these bursts. BFQ *does not* weight-raise queues whose activations occur + * in a large burst. In addition, for each of these queues BFQ performs or + * does not perform idling depending on which choice boosts the throughput + * most. The exact choice depends on the device and request pattern at + * hand. + * + * Turning back to the next function, it implements all the steps needed + * to detect the occurrence of a large burst and to properly mark all the + * queues belonging to it (so that they can then be treated in a different + * way). This goal is achieved by maintaining a special "burst list" that + * holds, temporarily, the queues that belong to the burst in progress. The + * list is then used to mark these queues as belonging to a large burst if + * the burst does become large. The main steps are the following. + * + * . when the very first queue is activated, the queue is inserted into the + * list (as it could be the first queue in a possible burst) + * + * . if the current burst has not yet become large, and a queue Q that does + * not yet belong to the burst is activated shortly after the last time + * at which a new queue entered the burst list, then the function appends + * Q to the burst list + * + * . if, as a consequence of the previous step, the burst size reaches + * the large-burst threshold, then + * + * . all the queues in the burst list are marked as belonging to a + * large burst + * + * . the burst list is deleted; in fact, the burst list already served + * its purpose (keeping temporarily track of the queues in a burst, + * so as to be able to mark them as belonging to a large burst in the + * previous sub-step), and now is not needed any more + * + * . the device enters a large-burst mode + * + * . if a queue Q that does not belong to the burst is activated while + * the device is in large-burst mode and shortly after the last time + * at which a queue either entered the burst list or was marked as + * belonging to the current large burst, then Q is immediately marked + * as belonging to a large burst. + * + * . if a queue Q that does not belong to the burst is activated a while + * later, i.e., not shortly after, than the last time at which a queue + * either entered the burst list or was marked as belonging to the + * current large burst, then the current burst is deemed as finished and: + * + * . the large-burst mode is reset if set + * + * . the burst list is emptied + * + * . Q is inserted in the burst list, as Q may be the first queue + * in a possible new burst (then the burst list contains just Q + * after this step). + */ +static void bfq_handle_burst(struct bfq_data *bfqd, struct bfq_queue *bfqq, + bool idle_for_long_time) +{ + /* + * If bfqq happened to be activated in a burst, but has been idle + * for at least as long as an interactive queue, then we assume + * that, in the overall I/O initiated in the burst, the I/O + * associated to bfqq is finished. So bfqq does not need to be + * treated as a queue belonging to a burst anymore. Accordingly, + * we reset bfqq's in_large_burst flag if set, and remove bfqq + * from the burst list if it's there. We do not decrement instead + * burst_size, because the fact that bfqq does not need to belong + * to the burst list any more does not invalidate the fact that + * bfqq may have been activated during the current burst. + */ + if (idle_for_long_time) { + hlist_del_init(&bfqq->burst_list_node); + bfq_clear_bfqq_in_large_burst(bfqq); + } + + /* + * If bfqq is already in the burst list or is part of a large + * burst, then there is nothing else to do. + */ + if (!hlist_unhashed(&bfqq->burst_list_node) || + bfq_bfqq_in_large_burst(bfqq)) + return; + + /* + * If bfqq's activation happens late enough, then the current + * burst is finished, and related data structures must be reset. + * + * In this respect, consider the special case where bfqq is the very + * first queue being activated. In this case, last_ins_in_burst is + * not yet significant when we get here. But it is easy to verify + * that, whether or not the following condition is true, bfqq will + * end up being inserted into the burst list. In particular the + * list will happen to contain only bfqq. And this is exactly what + * has to happen, as bfqq may be the first queue in a possible + * burst. + */ + if (time_is_before_jiffies(bfqd->last_ins_in_burst + + bfqd->bfq_burst_interval)) { + bfqd->large_burst = false; + bfq_reset_burst_list(bfqd, bfqq); + return; + } + + /* + * If we get here, then bfqq is being activated shortly after the + * last queue. So, if the current burst is also large, we can mark + * bfqq as belonging to this large burst immediately. + */ + if (bfqd->large_burst) { + bfq_mark_bfqq_in_large_burst(bfqq); + return; + } + + /* + * If we get here, then a large-burst state has not yet been + * reached, but bfqq is being activated shortly after the last + * queue. Then we add bfqq to the burst. + */ + bfq_add_to_burst(bfqd, bfqq); +} + +static void bfq_add_request(struct request *rq) +{ + struct bfq_queue *bfqq = RQ_BFQQ(rq); + struct bfq_entity *entity = &bfqq->entity; + struct bfq_data *bfqd = bfqq->bfqd; + struct request *next_rq, *prev; + unsigned long old_wr_coeff = bfqq->wr_coeff; + bool interactive = false; + + bfq_log_bfqq(bfqd, bfqq, "add_request %d", rq_is_sync(rq)); + bfqq->queued[rq_is_sync(rq)]++; + bfqd->queued++; + + elv_rb_add(&bfqq->sort_list, rq); + + /* + * Check if this request is a better next-serve candidate. + */ + prev = bfqq->next_rq; + next_rq = bfq_choose_req(bfqd, bfqq->next_rq, rq, bfqd->last_position); + BUG_ON(next_rq == NULL); + bfqq->next_rq = next_rq; + + /* + * Adjust priority tree position, if next_rq changes. + */ + if (prev != bfqq->next_rq) + bfq_rq_pos_tree_add(bfqd, bfqq); + + if (!bfq_bfqq_busy(bfqq)) { + bool soft_rt, + idle_for_long_time = time_is_before_jiffies( + bfqq->budget_timeout + + bfqd->bfq_wr_min_idle_time); + + if (bfq_bfqq_sync(bfqq)) { + bool already_in_burst = + !hlist_unhashed(&bfqq->burst_list_node) || + bfq_bfqq_in_large_burst(bfqq); + bfq_handle_burst(bfqd, bfqq, idle_for_long_time); + /* + * If bfqq was not already in the current burst, + * then, at this point, bfqq either has been + * added to the current burst or has caused the + * current burst to terminate. In particular, in + * the second case, bfqq has become the first + * queue in a possible new burst. + * In both cases last_ins_in_burst needs to be + * moved forward. + */ + if (!already_in_burst) + bfqd->last_ins_in_burst = jiffies; + } + + soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && + !bfq_bfqq_in_large_burst(bfqq) && + time_is_before_jiffies(bfqq->soft_rt_next_start); + interactive = !bfq_bfqq_in_large_burst(bfqq) && + idle_for_long_time; + entity->budget = max_t(unsigned long, bfqq->max_budget, + bfq_serv_to_charge(next_rq, bfqq)); + + if (!bfq_bfqq_IO_bound(bfqq)) { + if (time_before(jiffies, + RQ_BIC(rq)->ttime.last_end_request + + bfqd->bfq_slice_idle)) { + bfqq->requests_within_timer++; + if (bfqq->requests_within_timer >= + bfqd->bfq_requests_within_timer) + bfq_mark_bfqq_IO_bound(bfqq); + } else + bfqq->requests_within_timer = 0; + } + + if (!bfqd->low_latency) + goto add_bfqq_busy; + + /* + * If the queue is not being boosted and has been idle + * for enough time, start a weight-raising period + */ + if (old_wr_coeff == 1 && (interactive || soft_rt)) { + bfqq->wr_coeff = bfqd->bfq_wr_coeff; + if (interactive) + bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); + else + bfqq->wr_cur_max_time = + bfqd->bfq_wr_rt_max_time; + bfq_log_bfqq(bfqd, bfqq, + "wrais starting at %lu, rais_max_time %u", + jiffies, + jiffies_to_msecs(bfqq->wr_cur_max_time)); + } else if (old_wr_coeff > 1) { + if (interactive) + bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); + else if (bfq_bfqq_in_large_burst(bfqq) || + (bfqq->wr_cur_max_time == + bfqd->bfq_wr_rt_max_time && + !soft_rt)) { + bfqq->wr_coeff = 1; + bfq_log_bfqq(bfqd, bfqq, + "wrais ending at %lu, rais_max_time %u", + jiffies, + jiffies_to_msecs(bfqq-> + wr_cur_max_time)); + } else if (time_before( + bfqq->last_wr_start_finish + + bfqq->wr_cur_max_time, + jiffies + + bfqd->bfq_wr_rt_max_time) && + soft_rt) { + /* + * + * The remaining weight-raising time is lower + * than bfqd->bfq_wr_rt_max_time, which + * means that the application is enjoying + * weight raising either because deemed soft- + * rt in the near past, or because deemed + * interactive a long ago. In both cases, + * resetting now the current remaining weight- + * raising time for the application to the + * weight-raising duration for soft rt + * applications would not cause any latency + * increase for the application (as the new + * duration would be higher than the remaining + * time). + * + * In addition, the application is now meeting + * the requirements for being deemed soft rt. + * In the end we can correctly and safely + * (re)charge the weight-raising duration for + * the application with the weight-raising + * duration for soft rt applications. + * + * In particular, doing this recharge now, i.e., + * before the weight-raising period for the + * application finishes, reduces the probability + * of the following negative scenario: + * 1) the weight of a soft rt application is + * raised at startup (as for any newly + * created application), + * 2) since the application is not interactive, + * at a certain time weight-raising is + * stopped for the application, + * 3) at that time the application happens to + * still have pending requests, and hence + * is destined to not have a chance to be + * deemed soft rt before these requests are + * completed (see the comments to the + * function bfq_bfqq_softrt_next_start() + * for details on soft rt detection), + * 4) these pending requests experience a high + * latency because the application is not + * weight-raised while they are pending. + */ + bfqq->last_wr_start_finish = jiffies; + bfqq->wr_cur_max_time = + bfqd->bfq_wr_rt_max_time; + } + } + if (old_wr_coeff != bfqq->wr_coeff) + entity->ioprio_changed = 1; +add_bfqq_busy: + bfqq->last_idle_bklogged = jiffies; + bfqq->service_from_backlogged = 0; + bfq_clear_bfqq_softrt_update(bfqq); + bfq_add_bfqq_busy(bfqd, bfqq); + } else { + if (bfqd->low_latency && old_wr_coeff == 1 && !rq_is_sync(rq) && + time_is_before_jiffies( + bfqq->last_wr_start_finish + + bfqd->bfq_wr_min_inter_arr_async)) { + bfqq->wr_coeff = bfqd->bfq_wr_coeff; + bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); + + bfqd->wr_busy_queues++; + entity->ioprio_changed = 1; + bfq_log_bfqq(bfqd, bfqq, + "non-idle wrais starting at %lu, rais_max_time %u", + jiffies, + jiffies_to_msecs(bfqq->wr_cur_max_time)); + } + if (prev != bfqq->next_rq) + bfq_updated_next_req(bfqd, bfqq); + } + + if (bfqd->low_latency && + (old_wr_coeff == 1 || bfqq->wr_coeff == 1 || interactive)) + bfqq->last_wr_start_finish = jiffies; +} + +static struct request *bfq_find_rq_fmerge(struct bfq_data *bfqd, + struct bio *bio) +{ + struct task_struct *tsk = current; + struct bfq_io_cq *bic; + struct bfq_queue *bfqq; + + bic = bfq_bic_lookup(bfqd, tsk->io_context); + if (bic == NULL) + return NULL; + + bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); + if (bfqq != NULL) + return elv_rb_find(&bfqq->sort_list, bio_end_sector(bio)); + + return NULL; +} + +static void bfq_activate_request(struct request_queue *q, struct request *rq) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + + bfqd->rq_in_driver++; + bfqd->last_position = blk_rq_pos(rq) + blk_rq_sectors(rq); + bfq_log(bfqd, "activate_request: new bfqd->last_position %llu", + (long long unsigned)bfqd->last_position); +} + +static inline void bfq_deactivate_request(struct request_queue *q, + struct request *rq) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + + BUG_ON(bfqd->rq_in_driver == 0); + bfqd->rq_in_driver--; +} + +static void bfq_remove_request(struct request *rq) +{ + struct bfq_queue *bfqq = RQ_BFQQ(rq); + struct bfq_data *bfqd = bfqq->bfqd; + const int sync = rq_is_sync(rq); + + if (bfqq->next_rq == rq) { + bfqq->next_rq = bfq_find_next_rq(bfqd, bfqq, rq); + bfq_updated_next_req(bfqd, bfqq); + } + + if (rq->queuelist.prev != &rq->queuelist) + list_del_init(&rq->queuelist); + BUG_ON(bfqq->queued[sync] == 0); + bfqq->queued[sync]--; + bfqd->queued--; + elv_rb_del(&bfqq->sort_list, rq); + + if (RB_EMPTY_ROOT(&bfqq->sort_list)) { + if (bfq_bfqq_busy(bfqq) && bfqq != bfqd->in_service_queue) + bfq_del_bfqq_busy(bfqd, bfqq, 1); + /* + * Remove queue from request-position tree as it is empty. + */ + if (bfqq->pos_root != NULL) { + rb_erase(&bfqq->pos_node, bfqq->pos_root); + bfqq->pos_root = NULL; + } + } + + if (rq->cmd_flags & REQ_META) { + BUG_ON(bfqq->meta_pending == 0); + bfqq->meta_pending--; + } +} + +static int bfq_merge(struct request_queue *q, struct request **req, + struct bio *bio) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct request *__rq; + + __rq = bfq_find_rq_fmerge(bfqd, bio); + if (__rq != NULL && elv_rq_merge_ok(__rq, bio)) { + *req = __rq; + return ELEVATOR_FRONT_MERGE; + } + + return ELEVATOR_NO_MERGE; +} + +static void bfq_merged_request(struct request_queue *q, struct request *req, + int type) +{ + if (type == ELEVATOR_FRONT_MERGE && + rb_prev(&req->rb_node) && + blk_rq_pos(req) < + blk_rq_pos(container_of(rb_prev(&req->rb_node), + struct request, rb_node))) { + struct bfq_queue *bfqq = RQ_BFQQ(req); + struct bfq_data *bfqd = bfqq->bfqd; + struct request *prev, *next_rq; + + /* Reposition request in its sort_list */ + elv_rb_del(&bfqq->sort_list, req); + elv_rb_add(&bfqq->sort_list, req); + /* Choose next request to be served for bfqq */ + prev = bfqq->next_rq; + next_rq = bfq_choose_req(bfqd, bfqq->next_rq, req, + bfqd->last_position); + BUG_ON(next_rq == NULL); + bfqq->next_rq = next_rq; + /* + * If next_rq changes, update both the queue's budget to + * fit the new request and the queue's position in its + * rq_pos_tree. + */ + if (prev != bfqq->next_rq) { + bfq_updated_next_req(bfqd, bfqq); + bfq_rq_pos_tree_add(bfqd, bfqq); + } + } +} + +static void bfq_merged_requests(struct request_queue *q, struct request *rq, + struct request *next) +{ + struct bfq_queue *bfqq = RQ_BFQQ(rq), *next_bfqq = RQ_BFQQ(next); + + /* + * If next and rq belong to the same bfq_queue and next is older + * than rq, then reposition rq in the fifo (by substituting next + * with rq). Otherwise, if next and rq belong to different + * bfq_queues, never reposition rq: in fact, we would have to + * reposition it with respect to next's position in its own fifo, + * which would most certainly be too expensive with respect to + * the benefits. + */ + if (bfqq == next_bfqq && + !list_empty(&rq->queuelist) && !list_empty(&next->queuelist) && + time_before(next->fifo_time, rq->fifo_time)) { + list_del_init(&rq->queuelist); + list_replace_init(&next->queuelist, &rq->queuelist); + rq->fifo_time = next->fifo_time; + } + + if (bfqq->next_rq == next) + bfqq->next_rq = rq; + + bfq_remove_request(next); +} + +/* Must be called with bfqq != NULL */ +static inline void bfq_bfqq_end_wr(struct bfq_queue *bfqq) +{ + BUG_ON(bfqq == NULL); + if (bfq_bfqq_busy(bfqq)) + bfqq->bfqd->wr_busy_queues--; + bfqq->wr_coeff = 1; + bfqq->wr_cur_max_time = 0; + /* Trigger a weight change on the next activation of the queue */ + bfqq->entity.ioprio_changed = 1; +} + +static void bfq_end_wr_async_queues(struct bfq_data *bfqd, + struct bfq_group *bfqg) +{ + int i, j; + + for (i = 0; i < 2; i++) + for (j = 0; j < IOPRIO_BE_NR; j++) + if (bfqg->async_bfqq[i][j] != NULL) + bfq_bfqq_end_wr(bfqg->async_bfqq[i][j]); + if (bfqg->async_idle_bfqq != NULL) + bfq_bfqq_end_wr(bfqg->async_idle_bfqq); +} + +static void bfq_end_wr(struct bfq_data *bfqd) +{ + struct bfq_queue *bfqq; + + spin_lock_irq(bfqd->queue->queue_lock); + + list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) + bfq_bfqq_end_wr(bfqq); + list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) + bfq_bfqq_end_wr(bfqq); + bfq_end_wr_async(bfqd); + + spin_unlock_irq(bfqd->queue->queue_lock); +} + +static int bfq_allow_merge(struct request_queue *q, struct request *rq, + struct bio *bio) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct bfq_io_cq *bic; + struct bfq_queue *bfqq; + + /* + * Disallow merge of a sync bio into an async request. + */ + if (bfq_bio_sync(bio) && !rq_is_sync(rq)) + return 0; + + /* + * Lookup the bfqq that this bio will be queued with. Allow + * merge only if rq is queued there. + * Queue lock is held here. + */ + bic = bfq_bic_lookup(bfqd, current->io_context); + if (bic == NULL) + return 0; + + bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); + return bfqq == RQ_BFQQ(rq); +} + +static void __bfq_set_in_service_queue(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + if (bfqq != NULL) { + bfq_mark_bfqq_must_alloc(bfqq); + bfq_mark_bfqq_budget_new(bfqq); + bfq_clear_bfqq_fifo_expire(bfqq); + + bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; + + bfq_log_bfqq(bfqd, bfqq, + "set_in_service_queue, cur-budget = %lu", + bfqq->entity.budget); + } + + bfqd->in_service_queue = bfqq; +} + +/* + * Get and set a new queue for service. + */ +static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + if (!bfqq) + bfqq = bfq_get_next_queue(bfqd); + else + bfq_get_next_queue_forced(bfqd, bfqq); + + __bfq_set_in_service_queue(bfqd, bfqq); + return bfqq; +} + +static inline sector_t bfq_dist_from_last(struct bfq_data *bfqd, + struct request *rq) +{ + if (blk_rq_pos(rq) >= bfqd->last_position) + return blk_rq_pos(rq) - bfqd->last_position; + else + return bfqd->last_position - blk_rq_pos(rq); +} + +/* + * Return true if bfqq has no request pending and rq is close enough to + * bfqd->last_position, or if rq is closer to bfqd->last_position than + * bfqq->next_rq + */ +static inline int bfq_rq_close(struct bfq_data *bfqd, struct request *rq) +{ + return bfq_dist_from_last(bfqd, rq) <= BFQQ_SEEK_THR; +} + +static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) +{ + struct rb_root *root = &bfqd->rq_pos_tree; + struct rb_node *parent, *node; + struct bfq_queue *__bfqq; + sector_t sector = bfqd->last_position; + + if (RB_EMPTY_ROOT(root)) + return NULL; + + /* + * First, if we find a request starting at the end of the last + * request, choose it. + */ + __bfqq = bfq_rq_pos_tree_lookup(bfqd, root, sector, &parent, NULL); + if (__bfqq != NULL) + return __bfqq; + + /* + * If the exact sector wasn't found, the parent of the NULL leaf + * will contain the closest sector (rq_pos_tree sorted by + * next_request position). + */ + __bfqq = rb_entry(parent, struct bfq_queue, pos_node); + if (bfq_rq_close(bfqd, __bfqq->next_rq)) + return __bfqq; + + if (blk_rq_pos(__bfqq->next_rq) < sector) + node = rb_next(&__bfqq->pos_node); + else + node = rb_prev(&__bfqq->pos_node); + if (node == NULL) + return NULL; + + __bfqq = rb_entry(node, struct bfq_queue, pos_node); + if (bfq_rq_close(bfqd, __bfqq->next_rq)) + return __bfqq; + + return NULL; +} + +/* + * bfqd - obvious + * cur_bfqq - passed in so that we don't decide that the current queue + * is closely cooperating with itself. + * + * We are assuming that cur_bfqq has dispatched at least one request, + * and that bfqd->last_position reflects a position on the disk associated + * with the I/O issued by cur_bfqq. + */ +static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, + struct bfq_queue *cur_bfqq) +{ + struct bfq_queue *bfqq; + + if (bfq_class_idle(cur_bfqq)) + return NULL; + if (!bfq_bfqq_sync(cur_bfqq)) + return NULL; + if (BFQQ_SEEKY(cur_bfqq)) + return NULL; + + /* If device has only one backlogged bfq_queue, don't search. */ + if (bfqd->busy_queues == 1) + return NULL; + + /* + * We should notice if some of the queues are cooperating, e.g. + * working closely on the same area of the disk. In that case, + * we can group them together and don't waste time idling. + */ + bfqq = bfqq_close(bfqd); + if (bfqq == NULL || bfqq == cur_bfqq) + return NULL; + + /* + * Do not merge queues from different bfq_groups. + */ + if (bfqq->entity.parent != cur_bfqq->entity.parent) + return NULL; + + /* + * It only makes sense to merge sync queues. + */ + if (!bfq_bfqq_sync(bfqq)) + return NULL; + if (BFQQ_SEEKY(bfqq)) + return NULL; + + /* + * Do not merge queues of different priority classes. + */ + if (bfq_class_rt(bfqq) != bfq_class_rt(cur_bfqq)) + return NULL; + + return bfqq; +} + +/* + * If enough samples have been computed, return the current max budget + * stored in bfqd, which is dynamically updated according to the + * estimated disk peak rate; otherwise return the default max budget + */ +static inline unsigned long bfq_max_budget(struct bfq_data *bfqd) +{ + if (bfqd->budgets_assigned < 194) + return bfq_default_max_budget; + else + return bfqd->bfq_max_budget; +} + +/* + * Return min budget, which is a fraction of the current or default + * max budget (trying with 1/32) + */ +static inline unsigned long bfq_min_budget(struct bfq_data *bfqd) +{ + if (bfqd->budgets_assigned < 194) + return bfq_default_max_budget / 32; + else + return bfqd->bfq_max_budget / 32; +} + +static void bfq_arm_slice_timer(struct bfq_data *bfqd) +{ + struct bfq_queue *bfqq = bfqd->in_service_queue; + struct bfq_io_cq *bic; + unsigned long sl; + + BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); + + /* Processes have exited, don't wait. */ + bic = bfqd->in_service_bic; + if (bic == NULL || atomic_read(&bic->icq.ioc->active_ref) == 0) + return; + + bfq_mark_bfqq_wait_request(bfqq); + + /* + * We don't want to idle for seeks, but we do want to allow + * fair distribution of slice time for a process doing back-to-back + * seeks. So allow a little bit of time for him to submit a new rq. + * + * To prevent processes with (partly) seeky workloads from + * being too ill-treated, grant them a small fraction of the + * assigned budget before reducing the waiting time to + * BFQ_MIN_TT. This happened to help reduce latency. + */ + sl = bfqd->bfq_slice_idle; + /* + * Unless the queue is being weight-raised or the scenario is + * asymmetric, grant only minimum idle time if the queue either + * has been seeky for long enough or has already proved to be + * constantly seeky. + */ + if (bfq_sample_valid(bfqq->seek_samples) && + ((BFQQ_SEEKY(bfqq) && bfqq->entity.service > + bfq_max_budget(bfqq->bfqd) / 8) || + bfq_bfqq_constantly_seeky(bfqq)) && bfqq->wr_coeff == 1 && + symmetric_scenario) + sl = min(sl, msecs_to_jiffies(BFQ_MIN_TT)); + else if (bfqq->wr_coeff > 1) + sl = sl * 3; + bfqd->last_idling_start = ktime_get(); + mod_timer(&bfqd->idle_slice_timer, jiffies + sl); + bfq_log(bfqd, "arm idle: %u/%u ms", + jiffies_to_msecs(sl), jiffies_to_msecs(bfqd->bfq_slice_idle)); +} + +/* + * Set the maximum time for the in-service queue to consume its + * budget. This prevents seeky processes from lowering the disk + * throughput (always guaranteed with a time slice scheme as in CFQ). + */ +static void bfq_set_budget_timeout(struct bfq_data *bfqd) +{ + struct bfq_queue *bfqq = bfqd->in_service_queue; + unsigned int timeout_coeff; + if (bfqq->wr_cur_max_time == bfqd->bfq_wr_rt_max_time) + timeout_coeff = 1; + else + timeout_coeff = bfqq->entity.weight / bfqq->entity.orig_weight; + + bfqd->last_budget_start = ktime_get(); + + bfq_clear_bfqq_budget_new(bfqq); + bfqq->budget_timeout = jiffies + + bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * timeout_coeff; + + bfq_log_bfqq(bfqd, bfqq, "set budget_timeout %u", + jiffies_to_msecs(bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * + timeout_coeff)); +} + +/* + * Move request from internal lists to the request queue dispatch list. + */ +static void bfq_dispatch_insert(struct request_queue *q, struct request *rq) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct bfq_queue *bfqq = RQ_BFQQ(rq); + + /* + * For consistency, the next instruction should have been executed + * after removing the request from the queue and dispatching it. + * We execute instead this instruction before bfq_remove_request() + * (and hence introduce a temporary inconsistency), for efficiency. + * In fact, in a forced_dispatch, this prevents two counters related + * to bfqq->dispatched to risk to be uselessly decremented if bfqq + * is not in service, and then to be incremented again after + * incrementing bfqq->dispatched. + */ + bfqq->dispatched++; + bfq_remove_request(rq); + elv_dispatch_sort(q, rq); + + if (bfq_bfqq_sync(bfqq)) + bfqd->sync_flight++; +} + +/* + * Return expired entry, or NULL to just start from scratch in rbtree. + */ +static struct request *bfq_check_fifo(struct bfq_queue *bfqq) +{ + struct request *rq = NULL; + + if (bfq_bfqq_fifo_expire(bfqq)) + return NULL; + + bfq_mark_bfqq_fifo_expire(bfqq); + + if (list_empty(&bfqq->fifo)) + return NULL; + + rq = rq_entry_fifo(bfqq->fifo.next); + + if (time_before(jiffies, rq->fifo_time)) + return NULL; + + return rq; +} + +/* Must be called with the queue_lock held. */ +static int bfqq_process_refs(struct bfq_queue *bfqq) +{ + int process_refs, io_refs; + + io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; + process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; + BUG_ON(process_refs < 0); + return process_refs; +} + +static void bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) +{ + int process_refs, new_process_refs; + struct bfq_queue *__bfqq; + + /* + * If there are no process references on the new_bfqq, then it is + * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain + * may have dropped their last reference (not just their last process + * reference). + */ + if (!bfqq_process_refs(new_bfqq)) + return; + + /* Avoid a circular list and skip interim queue merges. */ + while ((__bfqq = new_bfqq->new_bfqq)) { + if (__bfqq == bfqq) + return; + new_bfqq = __bfqq; + } + + process_refs = bfqq_process_refs(bfqq); + new_process_refs = bfqq_process_refs(new_bfqq); + /* + * If the process for the bfqq has gone away, there is no + * sense in merging the queues. + */ + if (process_refs == 0 || new_process_refs == 0) + return; + + /* + * Merge in the direction of the lesser amount of work. + */ + if (new_process_refs >= process_refs) { + bfqq->new_bfqq = new_bfqq; + atomic_add(process_refs, &new_bfqq->ref); + } else { + new_bfqq->new_bfqq = bfqq; + atomic_add(new_process_refs, &bfqq->ref); + } + bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", + new_bfqq->pid); +} + +static inline unsigned long bfq_bfqq_budget_left(struct bfq_queue *bfqq) +{ + struct bfq_entity *entity = &bfqq->entity; + return entity->budget - entity->service; +} + +static void __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq) +{ + BUG_ON(bfqq != bfqd->in_service_queue); + + __bfq_bfqd_reset_in_service(bfqd); + + /* + * If this bfqq is shared between multiple processes, check + * to make sure that those processes are still issuing I/Os + * within the mean seek distance. If not, it may be time to + * break the queues apart again. + */ + if (bfq_bfqq_coop(bfqq) && BFQQ_SEEKY(bfqq)) + bfq_mark_bfqq_split_coop(bfqq); + + if (RB_EMPTY_ROOT(&bfqq->sort_list)) { + /* + * Overloading budget_timeout field to store the time + * at which the queue remains with no backlog; used by + * the weight-raising mechanism. + */ + bfqq->budget_timeout = jiffies; + bfq_del_bfqq_busy(bfqd, bfqq, 1); + } else { + bfq_activate_bfqq(bfqd, bfqq); + /* + * Resort priority tree of potential close cooperators. + */ + bfq_rq_pos_tree_add(bfqd, bfqq); + } +} + +/** + * __bfq_bfqq_recalc_budget - try to adapt the budget to the @bfqq behavior. + * @bfqd: device data. + * @bfqq: queue to update. + * @reason: reason for expiration. + * + * Handle the feedback on @bfqq budget. See the body for detailed + * comments. + */ +static void __bfq_bfqq_recalc_budget(struct bfq_data *bfqd, + struct bfq_queue *bfqq, + enum bfqq_expiration reason) +{ + struct request *next_rq; + unsigned long budget, min_budget; + + budget = bfqq->max_budget; + min_budget = bfq_min_budget(bfqd); + + BUG_ON(bfqq != bfqd->in_service_queue); + + bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last budg %lu, budg left %lu", + bfqq->entity.budget, bfq_bfqq_budget_left(bfqq)); + bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last max_budg %lu, min budg %lu", + budget, bfq_min_budget(bfqd)); + bfq_log_bfqq(bfqd, bfqq, "recalc_budg: sync %d, seeky %d", + bfq_bfqq_sync(bfqq), BFQQ_SEEKY(bfqd->in_service_queue)); + + if (bfq_bfqq_sync(bfqq)) { + switch (reason) { + /* + * Caveat: in all the following cases we trade latency + * for throughput. + */ + case BFQ_BFQQ_TOO_IDLE: + /* + * This is the only case where we may reduce + * the budget: if there is no request of the + * process still waiting for completion, then + * we assume (tentatively) that the timer has + * expired because the batch of requests of + * the process could have been served with a + * smaller budget. Hence, betting that + * process will behave in the same way when it + * becomes backlogged again, we reduce its + * next budget. As long as we guess right, + * this budget cut reduces the latency + * experienced by the process. + * + * However, if there are still outstanding + * requests, then the process may have not yet + * issued its next request just because it is + * still waiting for the completion of some of + * the still outstanding ones. So in this + * subcase we do not reduce its budget, on the + * contrary we increase it to possibly boost + * the throughput, as discussed in the + * comments to the BUDGET_TIMEOUT case. + */ + if (bfqq->dispatched > 0) /* still outstanding reqs */ + budget = min(budget * 2, bfqd->bfq_max_budget); + else { + if (budget > 5 * min_budget) + budget -= 4 * min_budget; + else + budget = min_budget; + } + break; + case BFQ_BFQQ_BUDGET_TIMEOUT: + /* + * We double the budget here because: 1) it + * gives the chance to boost the throughput if + * this is not a seeky process (which may have + * bumped into this timeout because of, e.g., + * ZBR), 2) together with charge_full_budget + * it helps give seeky processes higher + * timestamps, and hence be served less + * frequently. + */ + budget = min(budget * 2, bfqd->bfq_max_budget); + break; + case BFQ_BFQQ_BUDGET_EXHAUSTED: + /* + * The process still has backlog, and did not + * let either the budget timeout or the disk + * idling timeout expire. Hence it is not + * seeky, has a short thinktime and may be + * happy with a higher budget too. So + * definitely increase the budget of this good + * candidate to boost the disk throughput. + */ + budget = min(budget * 4, bfqd->bfq_max_budget); + break; + case BFQ_BFQQ_NO_MORE_REQUESTS: + /* + * Leave the budget unchanged. + */ + default: + return; + } + } else /* async queue */ + /* async queues get always the maximum possible budget + * (their ability to dispatch is limited by + * @bfqd->bfq_max_budget_async_rq). + */ + budget = bfqd->bfq_max_budget; + + bfqq->max_budget = budget; + + if (bfqd->budgets_assigned >= 194 && bfqd->bfq_user_max_budget == 0 && + bfqq->max_budget > bfqd->bfq_max_budget) + bfqq->max_budget = bfqd->bfq_max_budget; + + /* + * Make sure that we have enough budget for the next request. + * Since the finish time of the bfqq must be kept in sync with + * the budget, be sure to call __bfq_bfqq_expire() after the + * update. + */ + next_rq = bfqq->next_rq; + if (next_rq != NULL) + bfqq->entity.budget = max_t(unsigned long, bfqq->max_budget, + bfq_serv_to_charge(next_rq, bfqq)); + else + bfqq->entity.budget = bfqq->max_budget; + + bfq_log_bfqq(bfqd, bfqq, "head sect: %u, new budget %lu", + next_rq != NULL ? blk_rq_sectors(next_rq) : 0, + bfqq->entity.budget); +} + +static unsigned long bfq_calc_max_budget(u64 peak_rate, u64 timeout) +{ + unsigned long max_budget; + + /* + * The max_budget calculated when autotuning is equal to the + * amount of sectors transfered in timeout_sync at the + * estimated peak rate. + */ + max_budget = (unsigned long)(peak_rate * 1000 * + timeout >> BFQ_RATE_SHIFT); + + return max_budget; +} + +/* + * In addition to updating the peak rate, checks whether the process + * is "slow", and returns 1 if so. This slow flag is used, in addition + * to the budget timeout, to reduce the amount of service provided to + * seeky processes, and hence reduce their chances to lower the + * throughput. See the code for more details. + */ +static int bfq_update_peak_rate(struct bfq_data *bfqd, struct bfq_queue *bfqq, + int compensate, enum bfqq_expiration reason) +{ + u64 bw, usecs, expected, timeout; + ktime_t delta; + int update = 0; + + if (!bfq_bfqq_sync(bfqq) || bfq_bfqq_budget_new(bfqq)) + return 0; + + if (compensate) + delta = bfqd->last_idling_start; + else + delta = ktime_get(); + delta = ktime_sub(delta, bfqd->last_budget_start); + usecs = ktime_to_us(delta); + + /* Don't trust short/unrealistic values. */ + if (usecs < 100 || usecs >= LONG_MAX) + return 0; + + /* + * Calculate the bandwidth for the last slice. We use a 64 bit + * value to store the peak rate, in sectors per usec in fixed + * point math. We do so to have enough precision in the estimate + * and to avoid overflows. + */ + bw = (u64)bfqq->entity.service << BFQ_RATE_SHIFT; + do_div(bw, (unsigned long)usecs); + + timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]); + + /* + * Use only long (> 20ms) intervals to filter out spikes for + * the peak rate estimation. + */ + if (usecs > 20000) { + if (bw > bfqd->peak_rate || + (!BFQQ_SEEKY(bfqq) && + reason == BFQ_BFQQ_BUDGET_TIMEOUT)) { + bfq_log(bfqd, "measured bw =%llu", bw); + /* + * To smooth oscillations use a low-pass filter with + * alpha=7/8, i.e., + * new_rate = (7/8) * old_rate + (1/8) * bw + */ + do_div(bw, 8); + if (bw == 0) + return 0; + bfqd->peak_rate *= 7; + do_div(bfqd->peak_rate, 8); + bfqd->peak_rate += bw; + update = 1; + bfq_log(bfqd, "new peak_rate=%llu", bfqd->peak_rate); + } + + update |= bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES - 1; + + if (bfqd->peak_rate_samples < BFQ_PEAK_RATE_SAMPLES) + bfqd->peak_rate_samples++; + + if (bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES && + update) { + int dev_type = blk_queue_nonrot(bfqd->queue); + if (bfqd->bfq_user_max_budget == 0) { + bfqd->bfq_max_budget = + bfq_calc_max_budget(bfqd->peak_rate, + timeout); + bfq_log(bfqd, "new max_budget=%lu", + bfqd->bfq_max_budget); + } + if (bfqd->device_speed == BFQ_BFQD_FAST && + bfqd->peak_rate < device_speed_thresh[dev_type]) { + bfqd->device_speed = BFQ_BFQD_SLOW; + bfqd->RT_prod = R_slow[dev_type] * + T_slow[dev_type]; + } else if (bfqd->device_speed == BFQ_BFQD_SLOW && + bfqd->peak_rate > device_speed_thresh[dev_type]) { + bfqd->device_speed = BFQ_BFQD_FAST; + bfqd->RT_prod = R_fast[dev_type] * + T_fast[dev_type]; + } + } + } + + /* + * If the process has been served for a too short time + * interval to let its possible sequential accesses prevail on + * the initial seek time needed to move the disk head on the + * first sector it requested, then give the process a chance + * and for the moment return false. + */ + if (bfqq->entity.budget <= bfq_max_budget(bfqd) / 8) + return 0; + + /* + * A process is considered ``slow'' (i.e., seeky, so that we + * cannot treat it fairly in the service domain, as it would + * slow down too much the other processes) if, when a slice + * ends for whatever reason, it has received service at a + * rate that would not be high enough to complete the budget + * before the budget timeout expiration. + */ + expected = bw * 1000 * timeout >> BFQ_RATE_SHIFT; + + /* + * Caveat: processes doing IO in the slower disk zones will + * tend to be slow(er) even if not seeky. And the estimated + * peak rate will actually be an average over the disk + * surface. Hence, to not be too harsh with unlucky processes, + * we keep a budget/3 margin of safety before declaring a + * process slow. + */ + return expected > (4 * bfqq->entity.budget) / 3; +} + +/* + * To be deemed as soft real-time, an application must meet two + * requirements. First, the application must not require an average + * bandwidth higher than the approximate bandwidth required to playback or + * record a compressed high-definition video. + * The next function is invoked on the completion of the last request of a + * batch, to compute the next-start time instant, soft_rt_next_start, such + * that, if the next request of the application does not arrive before + * soft_rt_next_start, then the above requirement on the bandwidth is met. + * + * The second requirement is that the request pattern of the application is + * isochronous, i.e., that, after issuing a request or a batch of requests, + * the application stops issuing new requests until all its pending requests + * have been completed. After that, the application may issue a new batch, + * and so on. + * For this reason the next function is invoked to compute + * soft_rt_next_start only for applications that meet this requirement, + * whereas soft_rt_next_start is set to infinity for applications that do + * not. + * + * Unfortunately, even a greedy application may happen to behave in an + * isochronous way if the CPU load is high. In fact, the application may + * stop issuing requests while the CPUs are busy serving other processes, + * then restart, then stop again for a while, and so on. In addition, if + * the disk achieves a low enough throughput with the request pattern + * issued by the application (e.g., because the request pattern is random + * and/or the device is slow), then the application may meet the above + * bandwidth requirement too. To prevent such a greedy application to be + * deemed as soft real-time, a further rule is used in the computation of + * soft_rt_next_start: soft_rt_next_start must be higher than the current + * time plus the maximum time for which the arrival of a request is waited + * for when a sync queue becomes idle, namely bfqd->bfq_slice_idle. + * This filters out greedy applications, as the latter issue instead their + * next request as soon as possible after the last one has been completed + * (in contrast, when a batch of requests is completed, a soft real-time + * application spends some time processing data). + * + * Unfortunately, the last filter may easily generate false positives if + * only bfqd->bfq_slice_idle is used as a reference time interval and one + * or both the following cases occur: + * 1) HZ is so low that the duration of a jiffy is comparable to or higher + * than bfqd->bfq_slice_idle. This happens, e.g., on slow devices with + * HZ=100. + * 2) jiffies, instead of increasing at a constant rate, may stop increasing + * for a while, then suddenly 'jump' by several units to recover the lost + * increments. This seems to happen, e.g., inside virtual machines. + * To address this issue, we do not use as a reference time interval just + * bfqd->bfq_slice_idle, but bfqd->bfq_slice_idle plus a few jiffies. In + * particular we add the minimum number of jiffies for which the filter + * seems to be quite precise also in embedded systems and KVM/QEMU virtual + * machines. + */ +static inline unsigned long bfq_bfqq_softrt_next_start(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + return max(bfqq->last_idle_bklogged + + HZ * bfqq->service_from_backlogged / + bfqd->bfq_wr_max_softrt_rate, + jiffies + bfqq->bfqd->bfq_slice_idle + 4); +} + +/* + * Return the largest-possible time instant such that, for as long as possible, + * the current time will be lower than this time instant according to the macro + * time_is_before_jiffies(). + */ +static inline unsigned long bfq_infinity_from_now(unsigned long now) +{ + return now + ULONG_MAX / 2; +} + +/** + * bfq_bfqq_expire - expire a queue. + * @bfqd: device owning the queue. + * @bfqq: the queue to expire. + * @compensate: if true, compensate for the time spent idling. + * @reason: the reason causing the expiration. + * + * + * If the process associated to the queue is slow (i.e., seeky), or in + * case of budget timeout, or, finally, if it is async, we + * artificially charge it an entire budget (independently of the + * actual service it received). As a consequence, the queue will get + * higher timestamps than the correct ones upon reactivation, and + * hence it will be rescheduled as if it had received more service + * than what it actually received. In the end, this class of processes + * will receive less service in proportion to how slowly they consume + * their budgets (and hence how seriously they tend to lower the + * throughput). + * + * In contrast, when a queue expires because it has been idling for + * too much or because it exhausted its budget, we do not touch the + * amount of service it has received. Hence when the queue will be + * reactivated and its timestamps updated, the latter will be in sync + * with the actual service received by the queue until expiration. + * + * Charging a full budget to the first type of queues and the exact + * service to the others has the effect of using the WF2Q+ policy to + * schedule the former on a timeslice basis, without violating the + * service domain guarantees of the latter. + */ +static void bfq_bfqq_expire(struct bfq_data *bfqd, + struct bfq_queue *bfqq, + int compensate, + enum bfqq_expiration reason) +{ + int slow; + BUG_ON(bfqq != bfqd->in_service_queue); + + /* Update disk peak rate for autotuning and check whether the + * process is slow (see bfq_update_peak_rate). + */ + slow = bfq_update_peak_rate(bfqd, bfqq, compensate, reason); + + /* + * As above explained, 'punish' slow (i.e., seeky), timed-out + * and async queues, to favor sequential sync workloads. + * + * Processes doing I/O in the slower disk zones will tend to be + * slow(er) even if not seeky. Hence, since the estimated peak + * rate is actually an average over the disk surface, these + * processes may timeout just for bad luck. To avoid punishing + * them we do not charge a full budget to a process that + * succeeded in consuming at least 2/3 of its budget. + */ + if (slow || (reason == BFQ_BFQQ_BUDGET_TIMEOUT && + bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3)) + bfq_bfqq_charge_full_budget(bfqq); + + bfqq->service_from_backlogged += bfqq->entity.service; + + if (BFQQ_SEEKY(bfqq) && reason == BFQ_BFQQ_BUDGET_TIMEOUT && + !bfq_bfqq_constantly_seeky(bfqq)) { + bfq_mark_bfqq_constantly_seeky(bfqq); + if (!blk_queue_nonrot(bfqd->queue)) + bfqd->const_seeky_busy_in_flight_queues++; + } + + if (reason == BFQ_BFQQ_TOO_IDLE && + bfqq->entity.service <= 2 * bfqq->entity.budget / 10 ) + bfq_clear_bfqq_IO_bound(bfqq); + + if (bfqd->low_latency && bfqq->wr_coeff == 1) + bfqq->last_wr_start_finish = jiffies; + + if (bfqd->low_latency && bfqd->bfq_wr_max_softrt_rate > 0 && + RB_EMPTY_ROOT(&bfqq->sort_list)) { + /* + * If we get here, and there are no outstanding requests, + * then the request pattern is isochronous (see the comments + * to the function bfq_bfqq_softrt_next_start()). Hence we + * can compute soft_rt_next_start. If, instead, the queue + * still has outstanding requests, then we have to wait + * for the completion of all the outstanding requests to + * discover whether the request pattern is actually + * isochronous. + */ + if (bfqq->dispatched == 0) + bfqq->soft_rt_next_start = + bfq_bfqq_softrt_next_start(bfqd, bfqq); + else { + /* + * The application is still waiting for the + * completion of one or more requests: + * prevent it from possibly being incorrectly + * deemed as soft real-time by setting its + * soft_rt_next_start to infinity. In fact, + * without this assignment, the application + * would be incorrectly deemed as soft + * real-time if: + * 1) it issued a new request before the + * completion of all its in-flight + * requests, and + * 2) at that time, its soft_rt_next_start + * happened to be in the past. + */ + bfqq->soft_rt_next_start = + bfq_infinity_from_now(jiffies); + /* + * Schedule an update of soft_rt_next_start to when + * the task may be discovered to be isochronous. + */ + bfq_mark_bfqq_softrt_update(bfqq); + } + } + + bfq_log_bfqq(bfqd, bfqq, + "expire (%d, slow %d, num_disp %d, idle_win %d)", reason, + slow, bfqq->dispatched, bfq_bfqq_idle_window(bfqq)); + + /* + * Increase, decrease or leave budget unchanged according to + * reason. + */ + __bfq_bfqq_recalc_budget(bfqd, bfqq, reason); + __bfq_bfqq_expire(bfqd, bfqq); +} + +/* + * Budget timeout is not implemented through a dedicated timer, but + * just checked on request arrivals and completions, as well as on + * idle timer expirations. + */ +static int bfq_bfqq_budget_timeout(struct bfq_queue *bfqq) +{ + if (bfq_bfqq_budget_new(bfqq) || + time_before(jiffies, bfqq->budget_timeout)) + return 0; + return 1; +} + +/* + * If we expire a queue that is waiting for the arrival of a new + * request, we may prevent the fictitious timestamp back-shifting that + * allows the guarantees of the queue to be preserved (see [1] for + * this tricky aspect). Hence we return true only if this condition + * does not hold, or if the queue is slow enough to deserve only to be + * kicked off for preserving a high throughput. +*/ +static inline int bfq_may_expire_for_budg_timeout(struct bfq_queue *bfqq) +{ + bfq_log_bfqq(bfqq->bfqd, bfqq, + "may_budget_timeout: wait_request %d left %d timeout %d", + bfq_bfqq_wait_request(bfqq), + bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3, + bfq_bfqq_budget_timeout(bfqq)); + + return (!bfq_bfqq_wait_request(bfqq) || + bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3) + && + bfq_bfqq_budget_timeout(bfqq); +} + +/* + * Device idling is allowed only for the queues for which this function + * returns true. For this reason, the return value of this function plays a + * critical role for both throughput boosting and service guarantees. The + * return value is computed through a logical expression. In this rather + * long comment, we try to briefly describe all the details and motivations + * behind the components of this logical expression. + * + * First, the expression is false if bfqq is not sync, or if: bfqq happened + * to become active during a large burst of queue activations, and the + * pattern of requests bfqq contains boosts the throughput if bfqq is + * expired. In fact, queues that became active during a large burst benefit + * only from throughput, as discussed in the comments to bfq_handle_burst. + * In this respect, expiring bfqq certainly boosts the throughput on NCQ- + * capable flash-based devices, whereas, on rotational devices, it boosts + * the throughput only if bfqq contains random requests. + * + * On the opposite end, if (a) bfqq is sync, (b) the above burst-related + * condition does not hold, and (c) bfqq is being weight-raised, then the + * expression always evaluates to true, as device idling is instrumental + * for preserving low-latency guarantees (see [1]). If, instead, conditions + * (a) and (b) do hold, but (c) does not, then the expression evaluates to + * true only if: (1) bfqq is I/O-bound and has a non-null idle window, and + * (2) at least one of the following two conditions holds. + * The first condition is that the device is not performing NCQ, because + * idling the device most certainly boosts the throughput if this condition + * holds and bfqq is I/O-bound and has been granted a non-null idle window. + * The second compound condition is made of the logical AND of two components. + * + * The first component is true only if there is no weight-raised busy + * queue. This guarantees that the device is not idled for a sync non- + * weight-raised queue when there are busy weight-raised queues. The former + * is then expired immediately if empty. Combined with the timestamping + * rules of BFQ (see [1] for details), this causes sync non-weight-raised + * queues to get a lower number of requests served, and hence to ask for a + * lower number of requests from the request pool, before the busy weight- + * raised queues get served again. + * + * This is beneficial for the processes associated with weight-raised + * queues, when the request pool is saturated (e.g., in the presence of + * write hogs). In fact, if the processes associated with the other queues + * ask for requests at a lower rate, then weight-raised processes have a + * higher probability to get a request from the pool immediately (or at + * least soon) when they need one. Hence they have a higher probability to + * actually get a fraction of the disk throughput proportional to their + * high weight. This is especially true with NCQ-capable drives, which + * enqueue several requests in advance and further reorder internally- + * queued requests. + * + * In the end, mistreating non-weight-raised queues when there are busy + * weight-raised queues seems to mitigate starvation problems in the + * presence of heavy write workloads and NCQ, and hence to guarantee a + * higher application and system responsiveness in these hostile scenarios. + * + * If the first component of the compound condition is instead true, i.e., + * there is no weight-raised busy queue, then the second component of the + * compound condition takes into account service-guarantee and throughput + * issues related to NCQ (recall that the compound condition is evaluated + * only if the device is detected as supporting NCQ). + * + * As for service guarantees, allowing the drive to enqueue more than one + * request at a time, and hence delegating de facto final scheduling + * decisions to the drive's internal scheduler, causes loss of control on + * the actual request service order. In this respect, when the drive is + * allowed to enqueue more than one request at a time, the service + * distribution enforced by the drive's internal scheduler is likely to + * coincide with the desired device-throughput distribution only in the + * following, perfectly symmetric, scenario: + * 1) all active queues have the same weight, + * 2) all active groups at the same level in the groups tree have the same + * weight, + * 3) all active groups at the same level in the groups tree have the same + * number of children. + * + * Even in such a scenario, sequential I/O may still receive a preferential + * treatment, but this is not likely to be a big issue with flash-based + * devices, because of their non-dramatic loss of throughput with random + * I/O. Things do differ with HDDs, for which additional care is taken, as + * explained after completing the discussion for flash-based devices. + * + * Unfortunately, keeping the necessary state for evaluating exactly the + * above symmetry conditions would be quite complex and time-consuming. + * Therefore BFQ evaluates instead the following stronger sub-conditions, + * for which it is much easier to maintain the needed state: + * 1) all active queues have the same weight, + * 2) all active groups have the same weight, + * 3) all active groups have at most one active child each. + * In particular, the last two conditions are always true if hierarchical + * support and the cgroups interface are not enabled, hence no state needs + * to be maintained in this case. + * + * According to the above considerations, the second component of the + * compound condition evaluates to true if any of the above symmetry + * sub-condition does not hold, or the device is not flash-based. Therefore, + * if also the first component is true, then idling is allowed for a sync + * queue. These are the only sub-conditions considered if the device is + * flash-based, as, for such a device, it is sensible to force idling only + * for service-guarantee issues. In fact, as for throughput, idling + * NCQ-capable flash-based devices would not boost the throughput even + * with sequential I/O; rather it would lower the throughput in proportion + * to how fast the device is. In the end, (only) if all the three + * sub-conditions hold and the device is flash-based, the compound + * condition evaluates to false and therefore no idling is performed. + * + * As already said, things change with a rotational device, where idling + * boosts the throughput with sequential I/O (even with NCQ). Hence, for + * such a device the second component of the compound condition evaluates + * to true also if the following additional sub-condition does not hold: + * the queue is constantly seeky. Unfortunately, this different behavior + * with respect to flash-based devices causes an additional asymmetry: if + * some sync queues enjoy idling and some other sync queues do not, then + * the latter get a low share of the device throughput, simply because the + * former get many requests served after being set as in service, whereas + * the latter do not. As a consequence, to guarantee the desired throughput + * distribution, on HDDs the compound expression evaluates to true (and + * hence device idling is performed) also if the following last symmetry + * condition does not hold: no other queue is benefiting from idling. Also + * this last condition is actually replaced with a simpler-to-maintain and + * stronger condition: there is no busy queue which is not constantly seeky + * (and hence may also benefit from idling). + * + * To sum up, when all the required symmetry and throughput-boosting + * sub-conditions hold, the second component of the compound condition + * evaluates to false, and hence no idling is performed. This helps to + * keep the drives' internal queues full on NCQ-capable devices, and hence + * to boost the throughput, without causing 'almost' any loss of service + * guarantees. The 'almost' follows from the fact that, if the internal + * queue of one such device is filled while all the sub-conditions hold, + * but at some point in time some sub-condition stops to hold, then it may + * become impossible to let requests be served in the new desired order + * until all the requests already queued in the device have been served. + */ +static inline bool bfq_bfqq_must_not_expire(struct bfq_queue *bfqq) +{ + struct bfq_data *bfqd = bfqq->bfqd; +#define cond_for_seeky_on_ncq_hdd (bfq_bfqq_constantly_seeky(bfqq) && \ + bfqd->busy_in_flight_queues == \ + bfqd->const_seeky_busy_in_flight_queues) + +#define cond_for_expiring_in_burst (bfq_bfqq_in_large_burst(bfqq) && \ + bfqd->hw_tag && \ + (blk_queue_nonrot(bfqd->queue) || \ + bfq_bfqq_constantly_seeky(bfqq))) + +/* + * Condition for expiring a non-weight-raised queue (and hence not idling + * the device). + */ +#define cond_for_expiring_non_wr (bfqd->hw_tag && \ + (bfqd->wr_busy_queues > 0 || \ + (blk_queue_nonrot(bfqd->queue) || \ + cond_for_seeky_on_ncq_hdd))) + + return bfq_bfqq_sync(bfqq) && + !cond_for_expiring_in_burst && + (bfqq->wr_coeff > 1 || !symmetric_scenario || + (bfq_bfqq_IO_bound(bfqq) && bfq_bfqq_idle_window(bfqq) && + !cond_for_expiring_non_wr) + ); +} + +/* + * If the in-service queue is empty but sync, and the function + * bfq_bfqq_must_not_expire returns true, then: + * 1) the queue must remain in service and cannot be expired, and + * 2) the disk must be idled to wait for the possible arrival of a new + * request for the queue. + * See the comments to the function bfq_bfqq_must_not_expire for the reasons + * why performing device idling is the best choice to boost the throughput + * and preserve service guarantees when bfq_bfqq_must_not_expire itself + * returns true. + */ +static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq) +{ + struct bfq_data *bfqd = bfqq->bfqd; + + return RB_EMPTY_ROOT(&bfqq->sort_list) && bfqd->bfq_slice_idle != 0 && + bfq_bfqq_must_not_expire(bfqq); +} + +/* + * Select a queue for service. If we have a current queue in service, + * check whether to continue servicing it, or retrieve and set a new one. + */ +static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) +{ + struct bfq_queue *bfqq, *new_bfqq = NULL; + struct request *next_rq; + enum bfqq_expiration reason = BFQ_BFQQ_BUDGET_TIMEOUT; + + bfqq = bfqd->in_service_queue; + if (bfqq == NULL) + goto new_queue; + + bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue"); + + /* + * If another queue has a request waiting within our mean seek + * distance, let it run. The expire code will check for close + * cooperators and put the close queue at the front of the + * service tree. If possible, merge the expiring queue with the + * new bfqq. + */ + new_bfqq = bfq_close_cooperator(bfqd, bfqq); + if (new_bfqq != NULL && bfqq->new_bfqq == NULL) + bfq_setup_merge(bfqq, new_bfqq); + + if (bfq_may_expire_for_budg_timeout(bfqq) && + !timer_pending(&bfqd->idle_slice_timer) && + !bfq_bfqq_must_idle(bfqq)) + goto expire; + + next_rq = bfqq->next_rq; + /* + * If bfqq has requests queued and it has enough budget left to + * serve them, keep the queue, otherwise expire it. + */ + if (next_rq != NULL) { + if (bfq_serv_to_charge(next_rq, bfqq) > + bfq_bfqq_budget_left(bfqq)) { + reason = BFQ_BFQQ_BUDGET_EXHAUSTED; + goto expire; + } else { + /* + * The idle timer may be pending because we may + * not disable disk idling even when a new request + * arrives. + */ + if (timer_pending(&bfqd->idle_slice_timer)) { + /* + * If we get here: 1) at least a new request + * has arrived but we have not disabled the + * timer because the request was too small, + * 2) then the block layer has unplugged + * the device, causing the dispatch to be + * invoked. + * + * Since the device is unplugged, now the + * requests are probably large enough to + * provide a reasonable throughput. + * So we disable idling. + */ + bfq_clear_bfqq_wait_request(bfqq); + del_timer(&bfqd->idle_slice_timer); + } + if (new_bfqq == NULL) + goto keep_queue; + else + goto expire; + } + } + + /* + * No requests pending. However, if the in-service queue is idling + * for a new request, or has requests waiting for a completion and + * may idle after their completion, then keep it anyway. + */ + if (new_bfqq == NULL && (timer_pending(&bfqd->idle_slice_timer) || + (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq)))) { + bfqq = NULL; + goto keep_queue; + } else if (new_bfqq != NULL && timer_pending(&bfqd->idle_slice_timer)) { + /* + * Expiring the queue because there is a close cooperator, + * cancel timer. + */ + bfq_clear_bfqq_wait_request(bfqq); + del_timer(&bfqd->idle_slice_timer); + } + + reason = BFQ_BFQQ_NO_MORE_REQUESTS; +expire: + bfq_bfqq_expire(bfqd, bfqq, 0, reason); +new_queue: + bfqq = bfq_set_in_service_queue(bfqd, new_bfqq); + bfq_log(bfqd, "select_queue: new queue %d returned", + bfqq != NULL ? bfqq->pid : 0); +keep_queue: + return bfqq; +} + +static void bfq_update_wr_data(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + if (bfqq->wr_coeff > 1) { /* queue is being boosted */ + struct bfq_entity *entity = &bfqq->entity; + + bfq_log_bfqq(bfqd, bfqq, + "raising period dur %u/%u msec, old coeff %u, w %d(%d)", + jiffies_to_msecs(jiffies - + bfqq->last_wr_start_finish), + jiffies_to_msecs(bfqq->wr_cur_max_time), + bfqq->wr_coeff, + bfqq->entity.weight, bfqq->entity.orig_weight); + + BUG_ON(bfqq != bfqd->in_service_queue && entity->weight != + entity->orig_weight * bfqq->wr_coeff); + if (entity->ioprio_changed) + bfq_log_bfqq(bfqd, bfqq, "WARN: pending prio change"); + /* + * If the queue was activated in a burst, or + * too much time has elapsed from the beginning + * of this weight-raising, then end weight raising. + */ + if (bfq_bfqq_in_large_burst(bfqq) || + time_is_before_jiffies(bfqq->last_wr_start_finish + + bfqq->wr_cur_max_time)) { + bfqq->last_wr_start_finish = jiffies; + bfq_log_bfqq(bfqd, bfqq, + "wrais ending at %lu, rais_max_time %u", + bfqq->last_wr_start_finish, + jiffies_to_msecs(bfqq->wr_cur_max_time)); + bfq_bfqq_end_wr(bfqq); + __bfq_entity_update_weight_prio( + bfq_entity_service_tree(entity), + entity); + } + } +} + +/* + * Dispatch one request from bfqq, moving it to the request queue + * dispatch list. + */ +static int bfq_dispatch_request(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + int dispatched = 0; + struct request *rq; + unsigned long service_to_charge; + + BUG_ON(RB_EMPTY_ROOT(&bfqq->sort_list)); + + /* Follow expired path, else get first next available. */ + rq = bfq_check_fifo(bfqq); + if (rq == NULL) + rq = bfqq->next_rq; + service_to_charge = bfq_serv_to_charge(rq, bfqq); + + if (service_to_charge > bfq_bfqq_budget_left(bfqq)) { + /* + * This may happen if the next rq is chosen in fifo order + * instead of sector order. The budget is properly + * dimensioned to be always sufficient to serve the next + * request only if it is chosen in sector order. The reason + * is that it would be quite inefficient and little useful + * to always make sure that the budget is large enough to + * serve even the possible next rq in fifo order. + * In fact, requests are seldom served in fifo order. + * + * Expire the queue for budget exhaustion, and make sure + * that the next act_budget is enough to serve the next + * request, even if it comes from the fifo expired path. + */ + bfqq->next_rq = rq; + /* + * Since this dispatch is failed, make sure that + * a new one will be performed + */ + if (!bfqd->rq_in_driver) + bfq_schedule_dispatch(bfqd); + goto expire; + } + + /* Finally, insert request into driver dispatch list. */ + bfq_bfqq_served(bfqq, service_to_charge); + bfq_dispatch_insert(bfqd->queue, rq); + + bfq_update_wr_data(bfqd, bfqq); + + bfq_log_bfqq(bfqd, bfqq, + "dispatched %u sec req (%llu), budg left %lu", + blk_rq_sectors(rq), + (long long unsigned)blk_rq_pos(rq), + bfq_bfqq_budget_left(bfqq)); + + dispatched++; + + if (bfqd->in_service_bic == NULL) { + atomic_long_inc(&RQ_BIC(rq)->icq.ioc->refcount); + bfqd->in_service_bic = RQ_BIC(rq); + } + + if (bfqd->busy_queues > 1 && ((!bfq_bfqq_sync(bfqq) && + dispatched >= bfqd->bfq_max_budget_async_rq) || + bfq_class_idle(bfqq))) + goto expire; + + return dispatched; + +expire: + bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_EXHAUSTED); + return dispatched; +} + +static int __bfq_forced_dispatch_bfqq(struct bfq_queue *bfqq) +{ + int dispatched = 0; + + while (bfqq->next_rq != NULL) { + bfq_dispatch_insert(bfqq->bfqd->queue, bfqq->next_rq); + dispatched++; + } + + BUG_ON(!list_empty(&bfqq->fifo)); + return dispatched; +} + +/* + * Drain our current requests. + * Used for barriers and when switching io schedulers on-the-fly. + */ +static int bfq_forced_dispatch(struct bfq_data *bfqd) +{ + struct bfq_queue *bfqq, *n; + struct bfq_service_tree *st; + int dispatched = 0; + + bfqq = bfqd->in_service_queue; + if (bfqq != NULL) + __bfq_bfqq_expire(bfqd, bfqq); + + /* + * Loop through classes, and be careful to leave the scheduler + * in a consistent state, as feedback mechanisms and vtime + * updates cannot be disabled during the process. + */ + list_for_each_entry_safe(bfqq, n, &bfqd->active_list, bfqq_list) { + st = bfq_entity_service_tree(&bfqq->entity); + + dispatched += __bfq_forced_dispatch_bfqq(bfqq); + bfqq->max_budget = bfq_max_budget(bfqd); + + bfq_forget_idle(st); + } + + BUG_ON(bfqd->busy_queues != 0); + + return dispatched; +} + +static int bfq_dispatch_requests(struct request_queue *q, int force) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct bfq_queue *bfqq; + int max_dispatch; + + bfq_log(bfqd, "dispatch requests: %d busy queues", bfqd->busy_queues); + if (bfqd->busy_queues == 0) + return 0; + + if (unlikely(force)) + return bfq_forced_dispatch(bfqd); + + bfqq = bfq_select_queue(bfqd); + if (bfqq == NULL) + return 0; + + if (bfq_class_idle(bfqq)) + max_dispatch = 1; + + if (!bfq_bfqq_sync(bfqq)) + max_dispatch = bfqd->bfq_max_budget_async_rq; + + if (!bfq_bfqq_sync(bfqq) && bfqq->dispatched >= max_dispatch) { + if (bfqd->busy_queues > 1) + return 0; + if (bfqq->dispatched >= 4 * max_dispatch) + return 0; + } + + if (bfqd->sync_flight != 0 && !bfq_bfqq_sync(bfqq)) + return 0; + + bfq_clear_bfqq_wait_request(bfqq); + BUG_ON(timer_pending(&bfqd->idle_slice_timer)); + + if (!bfq_dispatch_request(bfqd, bfqq)) + return 0; + + bfq_log_bfqq(bfqd, bfqq, "dispatched %s request", + bfq_bfqq_sync(bfqq) ? "sync" : "async"); + + return 1; +} + +/* + * Task holds one reference to the queue, dropped when task exits. Each rq + * in-flight on this queue also holds a reference, dropped when rq is freed. + * + * Queue lock must be held here. + */ +static void bfq_put_queue(struct bfq_queue *bfqq) +{ + struct bfq_data *bfqd = bfqq->bfqd; + + BUG_ON(atomic_read(&bfqq->ref) <= 0); + + bfq_log_bfqq(bfqd, bfqq, "put_queue: %p %d", bfqq, + atomic_read(&bfqq->ref)); + if (!atomic_dec_and_test(&bfqq->ref)) + return; + + BUG_ON(rb_first(&bfqq->sort_list) != NULL); + BUG_ON(bfqq->allocated[READ] + bfqq->allocated[WRITE] != 0); + BUG_ON(bfqq->entity.tree != NULL); + BUG_ON(bfq_bfqq_busy(bfqq)); + BUG_ON(bfqd->in_service_queue == bfqq); + + if (bfq_bfqq_sync(bfqq)) + /* + * The fact that this queue is being destroyed does not + * invalidate the fact that this queue may have been + * activated during the current burst. As a consequence, + * although the queue does not exist anymore, and hence + * needs to be removed from the burst list if there, + * the burst size has not to be decremented. + */ + hlist_del_init(&bfqq->burst_list_node); + + bfq_log_bfqq(bfqd, bfqq, "put_queue: %p freed", bfqq); + + kmem_cache_free(bfq_pool, bfqq); +} + +static void bfq_put_cooperator(struct bfq_queue *bfqq) +{ + struct bfq_queue *__bfqq, *next; + + /* + * If this queue was scheduled to merge with another queue, be + * sure to drop the reference taken on that queue (and others in + * the merge chain). See bfq_setup_merge and bfq_merge_bfqqs. + */ + __bfqq = bfqq->new_bfqq; + while (__bfqq) { + if (__bfqq == bfqq) + break; + next = __bfqq->new_bfqq; + bfq_put_queue(__bfqq); + __bfqq = next; + } +} + +static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) +{ + if (bfqq == bfqd->in_service_queue) { + __bfq_bfqq_expire(bfqd, bfqq); + bfq_schedule_dispatch(bfqd); + } + + bfq_log_bfqq(bfqd, bfqq, "exit_bfqq: %p, %d", bfqq, + atomic_read(&bfqq->ref)); + + bfq_put_cooperator(bfqq); + + bfq_put_queue(bfqq); +} + +static inline void bfq_init_icq(struct io_cq *icq) +{ + struct bfq_io_cq *bic = icq_to_bic(icq); + + bic->ttime.last_end_request = jiffies; +} + +static void bfq_exit_icq(struct io_cq *icq) +{ + struct bfq_io_cq *bic = icq_to_bic(icq); + struct bfq_data *bfqd = bic_to_bfqd(bic); + + if (bic->bfqq[BLK_RW_ASYNC]) { + bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_ASYNC]); + bic->bfqq[BLK_RW_ASYNC] = NULL; + } + + if (bic->bfqq[BLK_RW_SYNC]) { + bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_SYNC]); + bic->bfqq[BLK_RW_SYNC] = NULL; + } +} + +/* + * Update the entity prio values; note that the new values will not + * be used until the next (re)activation. + */ +static void bfq_set_next_ioprio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic) +{ + struct task_struct *tsk = current; + int ioprio_class; + + ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); + switch (ioprio_class) { + default: + dev_err(bfqq->bfqd->queue->backing_dev_info.dev, + "bfq: bad prio class %d\n", ioprio_class); + case IOPRIO_CLASS_NONE: + /* + * No prio set, inherit CPU scheduling settings. + */ + bfqq->entity.new_ioprio = task_nice_ioprio(tsk); + bfqq->entity.new_ioprio_class = task_nice_ioclass(tsk); + break; + case IOPRIO_CLASS_RT: + bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); + bfqq->entity.new_ioprio_class = IOPRIO_CLASS_RT; + break; + case IOPRIO_CLASS_BE: + bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); + bfqq->entity.new_ioprio_class = IOPRIO_CLASS_BE; + break; + case IOPRIO_CLASS_IDLE: + bfqq->entity.new_ioprio_class = IOPRIO_CLASS_IDLE; + bfqq->entity.new_ioprio = 7; + bfq_clear_bfqq_idle_window(bfqq); + break; + } + + if (bfqq->entity.new_ioprio < 0 || + bfqq->entity.new_ioprio >= IOPRIO_BE_NR) { + printk(KERN_CRIT "bfq_set_next_ioprio_data: new_ioprio %d\n", + bfqq->entity.new_ioprio); + BUG(); + } + + bfqq->entity.new_weight = bfq_ioprio_to_weight(bfqq->entity.new_ioprio); + bfqq->entity.ioprio_changed = 1; +} + +static void bfq_check_ioprio_change(struct bfq_io_cq *bic) +{ + struct bfq_data *bfqd; + struct bfq_queue *bfqq, *new_bfqq; + struct bfq_group *bfqg; + unsigned long uninitialized_var(flags); + int ioprio = bic->icq.ioc->ioprio; + + bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data), + &flags); + /* + * This condition may trigger on a newly created bic, be sure to + * drop the lock before returning. + */ + if (unlikely(bfqd == NULL) || likely(bic->ioprio == ioprio)) + goto out; + + bic->ioprio = ioprio; + + bfqq = bic->bfqq[BLK_RW_ASYNC]; + if (bfqq != NULL) { + bfqg = container_of(bfqq->entity.sched_data, struct bfq_group, + sched_data); + new_bfqq = bfq_get_queue(bfqd, bfqg, BLK_RW_ASYNC, bic, + GFP_ATOMIC); + if (new_bfqq != NULL) { + bic->bfqq[BLK_RW_ASYNC] = new_bfqq; + bfq_log_bfqq(bfqd, bfqq, + "check_ioprio_change: bfqq %p %d", + bfqq, atomic_read(&bfqq->ref)); + bfq_put_queue(bfqq); + } + } + + bfqq = bic->bfqq[BLK_RW_SYNC]; + if (bfqq != NULL) + bfq_set_next_ioprio_data(bfqq, bic); + +out: + bfq_put_bfqd_unlock(bfqd, &flags); +} + +static void bfq_init_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, + struct bfq_io_cq *bic, pid_t pid, int is_sync) +{ + RB_CLEAR_NODE(&bfqq->entity.rb_node); + INIT_LIST_HEAD(&bfqq->fifo); + INIT_HLIST_NODE(&bfqq->burst_list_node); + + atomic_set(&bfqq->ref, 0); + bfqq->bfqd = bfqd; + + if (bic) + bfq_set_next_ioprio_data(bfqq, bic); + + if (is_sync) { + if (!bfq_class_idle(bfqq)) + bfq_mark_bfqq_idle_window(bfqq); + bfq_mark_bfqq_sync(bfqq); + } + bfq_mark_bfqq_IO_bound(bfqq); + + /* Tentative initial value to trade off between thr and lat */ + bfqq->max_budget = (2 * bfq_max_budget(bfqd)) / 3; + bfqq->pid = pid; + + bfqq->wr_coeff = 1; + bfqq->last_wr_start_finish = 0; + /* + * Set to the value for which bfqq will not be deemed as + * soft rt when it becomes backlogged. + */ + bfqq->soft_rt_next_start = bfq_infinity_from_now(jiffies); +} + +static struct bfq_queue *bfq_find_alloc_queue(struct bfq_data *bfqd, + struct bfq_group *bfqg, + int is_sync, + struct bfq_io_cq *bic, + gfp_t gfp_mask) +{ + struct bfq_queue *bfqq, *new_bfqq = NULL; + +retry: + /* bic always exists here */ + bfqq = bic_to_bfqq(bic, is_sync); + + /* + * Always try a new alloc if we fall back to the OOM bfqq + * originally, since it should just be a temporary situation. + */ + if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { + bfqq = NULL; + if (new_bfqq != NULL) { + bfqq = new_bfqq; + new_bfqq = NULL; + } else if (gfp_mask & __GFP_WAIT) { + spin_unlock_irq(bfqd->queue->queue_lock); + new_bfqq = kmem_cache_alloc_node(bfq_pool, + gfp_mask | __GFP_ZERO, + bfqd->queue->node); + spin_lock_irq(bfqd->queue->queue_lock); + if (new_bfqq != NULL) + goto retry; + } else { + bfqq = kmem_cache_alloc_node(bfq_pool, + gfp_mask | __GFP_ZERO, + bfqd->queue->node); + } + + if (bfqq != NULL) { + bfq_init_bfqq(bfqd, bfqq, bic, current->pid, + is_sync); + bfq_init_entity(&bfqq->entity, bfqg); + bfq_log_bfqq(bfqd, bfqq, "allocated"); + } else { + bfqq = &bfqd->oom_bfqq; + bfq_log_bfqq(bfqd, bfqq, "using oom bfqq"); + } + } + + if (new_bfqq != NULL) + kmem_cache_free(bfq_pool, new_bfqq); + + return bfqq; +} + +static struct bfq_queue **bfq_async_queue_prio(struct bfq_data *bfqd, + struct bfq_group *bfqg, + int ioprio_class, int ioprio) +{ + switch (ioprio_class) { + case IOPRIO_CLASS_RT: + return &bfqg->async_bfqq[0][ioprio]; + case IOPRIO_CLASS_NONE: + ioprio = IOPRIO_NORM; + /* fall through */ + case IOPRIO_CLASS_BE: + return &bfqg->async_bfqq[1][ioprio]; + case IOPRIO_CLASS_IDLE: + return &bfqg->async_idle_bfqq; + default: + BUG(); + } +} + +static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, + struct bfq_group *bfqg, int is_sync, + struct bfq_io_cq *bic, gfp_t gfp_mask) +{ + const int ioprio = IOPRIO_PRIO_DATA(bic->ioprio); + const int ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); + struct bfq_queue **async_bfqq = NULL; + struct bfq_queue *bfqq = NULL; + + if (!is_sync) { + async_bfqq = bfq_async_queue_prio(bfqd, bfqg, ioprio_class, + ioprio); + bfqq = *async_bfqq; + } + + if (bfqq == NULL) + bfqq = bfq_find_alloc_queue(bfqd, bfqg, is_sync, bic, gfp_mask); + + /* + * Pin the queue now that it's allocated, scheduler exit will + * prune it. + */ + if (!is_sync && *async_bfqq == NULL) { + atomic_inc(&bfqq->ref); + bfq_log_bfqq(bfqd, bfqq, "get_queue, bfqq not in async: %p, %d", + bfqq, atomic_read(&bfqq->ref)); + *async_bfqq = bfqq; + } + + atomic_inc(&bfqq->ref); + bfq_log_bfqq(bfqd, bfqq, "get_queue, at end: %p, %d", bfqq, + atomic_read(&bfqq->ref)); + return bfqq; +} + +static void bfq_update_io_thinktime(struct bfq_data *bfqd, + struct bfq_io_cq *bic) +{ + unsigned long elapsed = jiffies - bic->ttime.last_end_request; + unsigned long ttime = min(elapsed, 2UL * bfqd->bfq_slice_idle); + + bic->ttime.ttime_samples = (7*bic->ttime.ttime_samples + 256) / 8; + bic->ttime.ttime_total = (7*bic->ttime.ttime_total + 256*ttime) / 8; + bic->ttime.ttime_mean = (bic->ttime.ttime_total + 128) / + bic->ttime.ttime_samples; +} + +static void bfq_update_io_seektime(struct bfq_data *bfqd, + struct bfq_queue *bfqq, + struct request *rq) +{ + sector_t sdist; + u64 total; + + if (bfqq->last_request_pos < blk_rq_pos(rq)) + sdist = blk_rq_pos(rq) - bfqq->last_request_pos; + else + sdist = bfqq->last_request_pos - blk_rq_pos(rq); + + /* + * Don't allow the seek distance to get too large from the + * odd fragment, pagein, etc. + */ + if (bfqq->seek_samples == 0) /* first request, not really a seek */ + sdist = 0; + else if (bfqq->seek_samples <= 60) /* second & third seek */ + sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*1024); + else + sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*64); + + bfqq->seek_samples = (7*bfqq->seek_samples + 256) / 8; + bfqq->seek_total = (7*bfqq->seek_total + (u64)256*sdist) / 8; + total = bfqq->seek_total + (bfqq->seek_samples/2); + do_div(total, bfqq->seek_samples); + bfqq->seek_mean = (sector_t)total; + + bfq_log_bfqq(bfqd, bfqq, "dist=%llu mean=%llu", (u64)sdist, + (u64)bfqq->seek_mean); +} + +/* + * Disable idle window if the process thinks too long or seeks so much that + * it doesn't matter. + */ +static void bfq_update_idle_window(struct bfq_data *bfqd, + struct bfq_queue *bfqq, + struct bfq_io_cq *bic) +{ + int enable_idle; + + /* Don't idle for async or idle io prio class. */ + if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq)) + return; + + enable_idle = bfq_bfqq_idle_window(bfqq); + + if (atomic_read(&bic->icq.ioc->active_ref) == 0 || + bfqd->bfq_slice_idle == 0 || + (bfqd->hw_tag && BFQQ_SEEKY(bfqq) && + bfqq->wr_coeff == 1)) + enable_idle = 0; + else if (bfq_sample_valid(bic->ttime.ttime_samples)) { + if (bic->ttime.ttime_mean > bfqd->bfq_slice_idle && + bfqq->wr_coeff == 1) + enable_idle = 0; + else + enable_idle = 1; + } + bfq_log_bfqq(bfqd, bfqq, "update_idle_window: enable_idle %d", + enable_idle); + + if (enable_idle) + bfq_mark_bfqq_idle_window(bfqq); + else + bfq_clear_bfqq_idle_window(bfqq); +} + +/* + * Called when a new fs request (rq) is added to bfqq. Check if there's + * something we should do about it. + */ +static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, + struct request *rq) +{ + struct bfq_io_cq *bic = RQ_BIC(rq); + + if (rq->cmd_flags & REQ_META) + bfqq->meta_pending++; + + bfq_update_io_thinktime(bfqd, bic); + bfq_update_io_seektime(bfqd, bfqq, rq); + if (!BFQQ_SEEKY(bfqq) && bfq_bfqq_constantly_seeky(bfqq)) { + bfq_clear_bfqq_constantly_seeky(bfqq); + if (!blk_queue_nonrot(bfqd->queue)) { + BUG_ON(!bfqd->const_seeky_busy_in_flight_queues); + bfqd->const_seeky_busy_in_flight_queues--; + } + } + if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 || + !BFQQ_SEEKY(bfqq)) + bfq_update_idle_window(bfqd, bfqq, bic); + + bfq_log_bfqq(bfqd, bfqq, + "rq_enqueued: idle_window=%d (seeky %d, mean %llu)", + bfq_bfqq_idle_window(bfqq), BFQQ_SEEKY(bfqq), + (long long unsigned)bfqq->seek_mean); + + bfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq); + + if (bfqq == bfqd->in_service_queue && bfq_bfqq_wait_request(bfqq)) { + int small_req = bfqq->queued[rq_is_sync(rq)] == 1 && + blk_rq_sectors(rq) < 32; + int budget_timeout = bfq_bfqq_budget_timeout(bfqq); + + /* + * There is just this request queued: if the request + * is small and the queue is not to be expired, then + * just exit. + * + * In this way, if the disk is being idled to wait for + * a new request from the in-service queue, we avoid + * unplugging the device and committing the disk to serve + * just a small request. On the contrary, we wait for + * the block layer to decide when to unplug the device: + * hopefully, new requests will be merged to this one + * quickly, then the device will be unplugged and + * larger requests will be dispatched. + */ + if (small_req && !budget_timeout) + return; + + /* + * A large enough request arrived, or the queue is to + * be expired: in both cases disk idling is to be + * stopped, so clear wait_request flag and reset + * timer. + */ + bfq_clear_bfqq_wait_request(bfqq); + del_timer(&bfqd->idle_slice_timer); + + /* + * The queue is not empty, because a new request just + * arrived. Hence we can safely expire the queue, in + * case of budget timeout, without risking that the + * timestamps of the queue are not updated correctly. + * See [1] for more details. + */ + if (budget_timeout) + bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT); + + /* + * Let the request rip immediately, or let a new queue be + * selected if bfqq has just been expired. + */ + __blk_run_queue(bfqd->queue); + } +} + +static void bfq_insert_request(struct request_queue *q, struct request *rq) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct bfq_queue *bfqq = RQ_BFQQ(rq); + + assert_spin_locked(bfqd->queue->queue_lock); + + bfq_add_request(rq); + + rq->fifo_time = jiffies + bfqd->bfq_fifo_expire[rq_is_sync(rq)]; + list_add_tail(&rq->queuelist, &bfqq->fifo); + + bfq_rq_enqueued(bfqd, bfqq, rq); +} + +static void bfq_update_hw_tag(struct bfq_data *bfqd) +{ + bfqd->max_rq_in_driver = max(bfqd->max_rq_in_driver, + bfqd->rq_in_driver); + + if (bfqd->hw_tag == 1) + return; + + /* + * This sample is valid if the number of outstanding requests + * is large enough to allow a queueing behavior. Note that the + * sum is not exact, as it's not taking into account deactivated + * requests. + */ + if (bfqd->rq_in_driver + bfqd->queued < BFQ_HW_QUEUE_THRESHOLD) + return; + + if (bfqd->hw_tag_samples++ < BFQ_HW_QUEUE_SAMPLES) + return; + + bfqd->hw_tag = bfqd->max_rq_in_driver > BFQ_HW_QUEUE_THRESHOLD; + bfqd->max_rq_in_driver = 0; + bfqd->hw_tag_samples = 0; +} + +static void bfq_completed_request(struct request_queue *q, struct request *rq) +{ + struct bfq_queue *bfqq = RQ_BFQQ(rq); + struct bfq_data *bfqd = bfqq->bfqd; + bool sync = bfq_bfqq_sync(bfqq); + + bfq_log_bfqq(bfqd, bfqq, "completed one req with %u sects left (%d)", + blk_rq_sectors(rq), sync); + + bfq_update_hw_tag(bfqd); + + BUG_ON(!bfqd->rq_in_driver); + BUG_ON(!bfqq->dispatched); + bfqd->rq_in_driver--; + bfqq->dispatched--; + + if (!bfqq->dispatched && !bfq_bfqq_busy(bfqq)) { + bfq_weights_tree_remove(bfqd, &bfqq->entity, + &bfqd->queue_weights_tree); + if (!blk_queue_nonrot(bfqd->queue)) { + BUG_ON(!bfqd->busy_in_flight_queues); + bfqd->busy_in_flight_queues--; + if (bfq_bfqq_constantly_seeky(bfqq)) { + BUG_ON(!bfqd-> + const_seeky_busy_in_flight_queues); + bfqd->const_seeky_busy_in_flight_queues--; + } + } + } + + if (sync) { + bfqd->sync_flight--; + RQ_BIC(rq)->ttime.last_end_request = jiffies; + } + + /* + * If we are waiting to discover whether the request pattern of the + * task associated with the queue is actually isochronous, and + * both requisites for this condition to hold are satisfied, then + * compute soft_rt_next_start (see the comments to the function + * bfq_bfqq_softrt_next_start()). + */ + if (bfq_bfqq_softrt_update(bfqq) && bfqq->dispatched == 0 && + RB_EMPTY_ROOT(&bfqq->sort_list)) + bfqq->soft_rt_next_start = + bfq_bfqq_softrt_next_start(bfqd, bfqq); + + /* + * If this is the in-service queue, check if it needs to be expired, + * or if we want to idle in case it has no pending requests. + */ + if (bfqd->in_service_queue == bfqq) { + if (bfq_bfqq_budget_new(bfqq)) + bfq_set_budget_timeout(bfqd); + + if (bfq_bfqq_must_idle(bfqq)) { + bfq_arm_slice_timer(bfqd); + goto out; + } else if (bfq_may_expire_for_budg_timeout(bfqq)) + bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT); + else if (RB_EMPTY_ROOT(&bfqq->sort_list) && + (bfqq->dispatched == 0 || + !bfq_bfqq_must_not_expire(bfqq))) + bfq_bfqq_expire(bfqd, bfqq, 0, + BFQ_BFQQ_NO_MORE_REQUESTS); + } + + if (!bfqd->rq_in_driver) + bfq_schedule_dispatch(bfqd); + +out: + return; +} + +static inline int __bfq_may_queue(struct bfq_queue *bfqq) +{ + if (bfq_bfqq_wait_request(bfqq) && bfq_bfqq_must_alloc(bfqq)) { + bfq_clear_bfqq_must_alloc(bfqq); + return ELV_MQUEUE_MUST; + } + + return ELV_MQUEUE_MAY; +} + +static int bfq_may_queue(struct request_queue *q, int rw) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct task_struct *tsk = current; + struct bfq_io_cq *bic; + struct bfq_queue *bfqq; + + /* + * Don't force setup of a queue from here, as a call to may_queue + * does not necessarily imply that a request actually will be + * queued. So just lookup a possibly existing queue, or return + * 'may queue' if that fails. + */ + bic = bfq_bic_lookup(bfqd, tsk->io_context); + if (bic == NULL) + return ELV_MQUEUE_MAY; + + bfqq = bic_to_bfqq(bic, rw_is_sync(rw)); + if (bfqq != NULL) + return __bfq_may_queue(bfqq); + + return ELV_MQUEUE_MAY; +} + +/* + * Queue lock held here. + */ +static void bfq_put_request(struct request *rq) +{ + struct bfq_queue *bfqq = RQ_BFQQ(rq); + + if (bfqq != NULL) { + const int rw = rq_data_dir(rq); + + BUG_ON(!bfqq->allocated[rw]); + bfqq->allocated[rw]--; + + rq->elv.priv[0] = NULL; + rq->elv.priv[1] = NULL; + + bfq_log_bfqq(bfqq->bfqd, bfqq, "put_request %p, %d", + bfqq, atomic_read(&bfqq->ref)); + bfq_put_queue(bfqq); + } +} + +static struct bfq_queue * +bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, + struct bfq_queue *bfqq) +{ + bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", + (long unsigned)bfqq->new_bfqq->pid); + bic_set_bfqq(bic, bfqq->new_bfqq, 1); + bfq_mark_bfqq_coop(bfqq->new_bfqq); + bfq_put_queue(bfqq); + return bic_to_bfqq(bic, 1); +} + +/* + * Returns NULL if a new bfqq should be allocated, or the old bfqq if this + * was the last process referring to said bfqq. + */ +static struct bfq_queue * +bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq) +{ + bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); + if (bfqq_process_refs(bfqq) == 1) { + bfqq->pid = current->pid; + bfq_clear_bfqq_coop(bfqq); + bfq_clear_bfqq_split_coop(bfqq); + return bfqq; + } + + bic_set_bfqq(bic, NULL, 1); + + bfq_put_cooperator(bfqq); + + bfq_put_queue(bfqq); + return NULL; +} + +/* + * Allocate bfq data structures associated with this request. + */ +static int bfq_set_request(struct request_queue *q, struct request *rq, + struct bio *bio, gfp_t gfp_mask) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct bfq_io_cq *bic = icq_to_bic(rq->elv.icq); + const int rw = rq_data_dir(rq); + const int is_sync = rq_is_sync(rq); + struct bfq_queue *bfqq; + struct bfq_group *bfqg; + unsigned long flags; + + might_sleep_if(gfp_mask & __GFP_WAIT); + + bfq_check_ioprio_change(bic); + + spin_lock_irqsave(q->queue_lock, flags); + + if (bic == NULL) + goto queue_fail; + + bfqg = bfq_bic_update_cgroup(bic); + +new_queue: + bfqq = bic_to_bfqq(bic, is_sync); + if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { + bfqq = bfq_get_queue(bfqd, bfqg, is_sync, bic, gfp_mask); + bic_set_bfqq(bic, bfqq, is_sync); + } else { + /* + * If the queue was seeky for too long, break it apart. + */ + if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq)) { + bfq_log_bfqq(bfqd, bfqq, "breaking apart bfqq"); + bfqq = bfq_split_bfqq(bic, bfqq); + if (!bfqq) + goto new_queue; + } + + /* + * Check to see if this queue is scheduled to merge with + * another closely cooperating queue. The merging of queues + * happens here as it must be done in process context. + * The reference on new_bfqq was taken in merge_bfqqs. + */ + if (bfqq->new_bfqq != NULL) + bfqq = bfq_merge_bfqqs(bfqd, bic, bfqq); + } + + bfqq->allocated[rw]++; + atomic_inc(&bfqq->ref); + bfq_log_bfqq(bfqd, bfqq, "set_request: bfqq %p, %d", bfqq, + atomic_read(&bfqq->ref)); + + rq->elv.priv[0] = bic; + rq->elv.priv[1] = bfqq; + + spin_unlock_irqrestore(q->queue_lock, flags); + + return 0; + +queue_fail: + bfq_schedule_dispatch(bfqd); + spin_unlock_irqrestore(q->queue_lock, flags); + + return 1; +} + +static void bfq_kick_queue(struct work_struct *work) +{ + struct bfq_data *bfqd = + container_of(work, struct bfq_data, unplug_work); + struct request_queue *q = bfqd->queue; + + spin_lock_irq(q->queue_lock); + __blk_run_queue(q); + spin_unlock_irq(q->queue_lock); +} + +/* + * Handler of the expiration of the timer running if the in-service queue + * is idling inside its time slice. + */ +static void bfq_idle_slice_timer(unsigned long data) +{ + struct bfq_data *bfqd = (struct bfq_data *)data; + struct bfq_queue *bfqq; + unsigned long flags; + enum bfqq_expiration reason; + + spin_lock_irqsave(bfqd->queue->queue_lock, flags); + + bfqq = bfqd->in_service_queue; + /* + * Theoretical race here: the in-service queue can be NULL or + * different from the queue that was idling if the timer handler + * spins on the queue_lock and a new request arrives for the + * current queue and there is a full dispatch cycle that changes + * the in-service queue. This can hardly happen, but in the worst + * case we just expire a queue too early. + */ + if (bfqq != NULL) { + bfq_log_bfqq(bfqd, bfqq, "slice_timer expired"); + if (bfq_bfqq_budget_timeout(bfqq)) + /* + * Also here the queue can be safely expired + * for budget timeout without wasting + * guarantees + */ + reason = BFQ_BFQQ_BUDGET_TIMEOUT; + else if (bfqq->queued[0] == 0 && bfqq->queued[1] == 0) + /* + * The queue may not be empty upon timer expiration, + * because we may not disable the timer when the + * first request of the in-service queue arrives + * during disk idling. + */ + reason = BFQ_BFQQ_TOO_IDLE; + else + goto schedule_dispatch; + + bfq_bfqq_expire(bfqd, bfqq, 1, reason); + } + +schedule_dispatch: + bfq_schedule_dispatch(bfqd); + + spin_unlock_irqrestore(bfqd->queue->queue_lock, flags); +} + +static void bfq_shutdown_timer_wq(struct bfq_data *bfqd) +{ + del_timer_sync(&bfqd->idle_slice_timer); + cancel_work_sync(&bfqd->unplug_work); +} + +static inline void __bfq_put_async_bfqq(struct bfq_data *bfqd, + struct bfq_queue **bfqq_ptr) +{ + struct bfq_group *root_group = bfqd->root_group; + struct bfq_queue *bfqq = *bfqq_ptr; + + bfq_log(bfqd, "put_async_bfqq: %p", bfqq); + if (bfqq != NULL) { + bfq_bfqq_move(bfqd, bfqq, &bfqq->entity, root_group); + bfq_log_bfqq(bfqd, bfqq, "put_async_bfqq: putting %p, %d", + bfqq, atomic_read(&bfqq->ref)); + bfq_put_queue(bfqq); + *bfqq_ptr = NULL; + } +} + +/* + * Release all the bfqg references to its async queues. If we are + * deallocating the group these queues may still contain requests, so + * we reparent them to the root cgroup (i.e., the only one that will + * exist for sure until all the requests on a device are gone). + */ +static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg) +{ + int i, j; + + for (i = 0; i < 2; i++) + for (j = 0; j < IOPRIO_BE_NR; j++) + __bfq_put_async_bfqq(bfqd, &bfqg->async_bfqq[i][j]); + + __bfq_put_async_bfqq(bfqd, &bfqg->async_idle_bfqq); +} + +static void bfq_exit_queue(struct elevator_queue *e) +{ + struct bfq_data *bfqd = e->elevator_data; + struct request_queue *q = bfqd->queue; + struct bfq_queue *bfqq, *n; + + bfq_shutdown_timer_wq(bfqd); + + spin_lock_irq(q->queue_lock); + + BUG_ON(bfqd->in_service_queue != NULL); + list_for_each_entry_safe(bfqq, n, &bfqd->idle_list, bfqq_list) + bfq_deactivate_bfqq(bfqd, bfqq, 0); + + bfq_disconnect_groups(bfqd); + spin_unlock_irq(q->queue_lock); + + bfq_shutdown_timer_wq(bfqd); + + synchronize_rcu(); + + BUG_ON(timer_pending(&bfqd->idle_slice_timer)); + + bfq_free_root_group(bfqd); + kfree(bfqd); +} + +static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) +{ + struct bfq_group *bfqg; + struct bfq_data *bfqd; + struct elevator_queue *eq; + + eq = elevator_alloc(q, e); + if (eq == NULL) + return -ENOMEM; + + bfqd = kzalloc_node(sizeof(*bfqd), GFP_KERNEL, q->node); + if (bfqd == NULL) { + kobject_put(&eq->kobj); + return -ENOMEM; + } + eq->elevator_data = bfqd; + + /* + * Our fallback bfqq if bfq_find_alloc_queue() runs into OOM issues. + * Grab a permanent reference to it, so that the normal code flow + * will not attempt to free it. + */ + bfq_init_bfqq(bfqd, &bfqd->oom_bfqq, NULL, 1, 0); + atomic_inc(&bfqd->oom_bfqq.ref); + bfqd->oom_bfqq.entity.new_ioprio = BFQ_DEFAULT_QUEUE_IOPRIO; + bfqd->oom_bfqq.entity.new_ioprio_class = IOPRIO_CLASS_BE; + bfqd->oom_bfqq.entity.new_weight = + bfq_ioprio_to_weight(bfqd->oom_bfqq.entity.new_ioprio); + /* + * Trigger weight initialization, according to ioprio, at the + * oom_bfqq's first activation. The oom_bfqq's ioprio and ioprio + * class won't be changed any more. + */ + bfqd->oom_bfqq.entity.ioprio_changed = 1; + + bfqd->queue = q; + + spin_lock_irq(q->queue_lock); + q->elevator = eq; + spin_unlock_irq(q->queue_lock); + + bfqg = bfq_alloc_root_group(bfqd, q->node); + if (bfqg == NULL) { + kfree(bfqd); + kobject_put(&eq->kobj); + return -ENOMEM; + } + + bfqd->root_group = bfqg; + bfq_init_entity(&bfqd->oom_bfqq.entity, bfqd->root_group); +#ifdef CONFIG_CGROUP_BFQIO + bfqd->active_numerous_groups = 0; +#endif + + init_timer(&bfqd->idle_slice_timer); + bfqd->idle_slice_timer.function = bfq_idle_slice_timer; + bfqd->idle_slice_timer.data = (unsigned long)bfqd; + + bfqd->rq_pos_tree = RB_ROOT; + bfqd->queue_weights_tree = RB_ROOT; + bfqd->group_weights_tree = RB_ROOT; + + INIT_WORK(&bfqd->unplug_work, bfq_kick_queue); + + INIT_LIST_HEAD(&bfqd->active_list); + INIT_LIST_HEAD(&bfqd->idle_list); + INIT_HLIST_HEAD(&bfqd->burst_list); + + bfqd->hw_tag = -1; + + bfqd->bfq_max_budget = bfq_default_max_budget; + + bfqd->bfq_fifo_expire[0] = bfq_fifo_expire[0]; + bfqd->bfq_fifo_expire[1] = bfq_fifo_expire[1]; + bfqd->bfq_back_max = bfq_back_max; + bfqd->bfq_back_penalty = bfq_back_penalty; + bfqd->bfq_slice_idle = bfq_slice_idle; + bfqd->bfq_class_idle_last_service = 0; + bfqd->bfq_max_budget_async_rq = bfq_max_budget_async_rq; + bfqd->bfq_timeout[BLK_RW_ASYNC] = bfq_timeout_async; + bfqd->bfq_timeout[BLK_RW_SYNC] = bfq_timeout_sync; + + bfqd->bfq_coop_thresh = 2; + bfqd->bfq_failed_cooperations = 7000; + bfqd->bfq_requests_within_timer = 120; + + bfqd->bfq_large_burst_thresh = 11; + bfqd->bfq_burst_interval = msecs_to_jiffies(500); + + bfqd->low_latency = true; + + bfqd->bfq_wr_coeff = 20; + bfqd->bfq_wr_rt_max_time = msecs_to_jiffies(300); + bfqd->bfq_wr_max_time = 0; + bfqd->bfq_wr_min_idle_time = msecs_to_jiffies(2000); + bfqd->bfq_wr_min_inter_arr_async = msecs_to_jiffies(500); + bfqd->bfq_wr_max_softrt_rate = 7000; /* + * Approximate rate required + * to playback or record a + * high-definition compressed + * video. + */ + bfqd->wr_busy_queues = 0; + bfqd->busy_in_flight_queues = 0; + bfqd->const_seeky_busy_in_flight_queues = 0; + + /* + * Begin by assuming, optimistically, that the device peak rate is + * equal to the highest reference rate. + */ + bfqd->RT_prod = R_fast[blk_queue_nonrot(bfqd->queue)] * + T_fast[blk_queue_nonrot(bfqd->queue)]; + bfqd->peak_rate = R_fast[blk_queue_nonrot(bfqd->queue)]; + bfqd->device_speed = BFQ_BFQD_FAST; + + return 0; +} + +static void bfq_slab_kill(void) +{ + if (bfq_pool != NULL) + kmem_cache_destroy(bfq_pool); +} + +static int __init bfq_slab_setup(void) +{ + bfq_pool = KMEM_CACHE(bfq_queue, 0); + if (bfq_pool == NULL) + return -ENOMEM; + return 0; +} + +static ssize_t bfq_var_show(unsigned int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t bfq_var_store(unsigned long *var, const char *page, + size_t count) +{ + unsigned long new_val; + int ret = kstrtoul(page, 10, &new_val); + + if (ret == 0) + *var = new_val; + + return count; +} + +static ssize_t bfq_wr_max_time_show(struct elevator_queue *e, char *page) +{ + struct bfq_data *bfqd = e->elevator_data; + return sprintf(page, "%d\n", bfqd->bfq_wr_max_time > 0 ? + jiffies_to_msecs(bfqd->bfq_wr_max_time) : + jiffies_to_msecs(bfq_wr_duration(bfqd))); +} + +static ssize_t bfq_weights_show(struct elevator_queue *e, char *page) +{ + struct bfq_queue *bfqq; + struct bfq_data *bfqd = e->elevator_data; + ssize_t num_char = 0; + + num_char += sprintf(page + num_char, "Tot reqs queued %d\n\n", + bfqd->queued); + + spin_lock_irq(bfqd->queue->queue_lock); + + num_char += sprintf(page + num_char, "Active:\n"); + list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) { + num_char += sprintf(page + num_char, + "pid%d: weight %hu, nr_queued %d %d, dur %d/%u\n", + bfqq->pid, + bfqq->entity.weight, + bfqq->queued[0], + bfqq->queued[1], + jiffies_to_msecs(jiffies - bfqq->last_wr_start_finish), + jiffies_to_msecs(bfqq->wr_cur_max_time)); + } + + num_char += sprintf(page + num_char, "Idle:\n"); + list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) { + num_char += sprintf(page + num_char, + "pid%d: weight %hu, dur %d/%u\n", + bfqq->pid, + bfqq->entity.weight, + jiffies_to_msecs(jiffies - + bfqq->last_wr_start_finish), + jiffies_to_msecs(bfqq->wr_cur_max_time)); + } + + spin_unlock_irq(bfqd->queue->queue_lock); + + return num_char; +} + +#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ +{ \ + struct bfq_data *bfqd = e->elevator_data; \ + unsigned int __data = __VAR; \ + if (__CONV) \ + __data = jiffies_to_msecs(__data); \ + return bfq_var_show(__data, (page)); \ +} +SHOW_FUNCTION(bfq_fifo_expire_sync_show, bfqd->bfq_fifo_expire[1], 1); +SHOW_FUNCTION(bfq_fifo_expire_async_show, bfqd->bfq_fifo_expire[0], 1); +SHOW_FUNCTION(bfq_back_seek_max_show, bfqd->bfq_back_max, 0); +SHOW_FUNCTION(bfq_back_seek_penalty_show, bfqd->bfq_back_penalty, 0); +SHOW_FUNCTION(bfq_slice_idle_show, bfqd->bfq_slice_idle, 1); +SHOW_FUNCTION(bfq_max_budget_show, bfqd->bfq_user_max_budget, 0); +SHOW_FUNCTION(bfq_max_budget_async_rq_show, + bfqd->bfq_max_budget_async_rq, 0); +SHOW_FUNCTION(bfq_timeout_sync_show, bfqd->bfq_timeout[BLK_RW_SYNC], 1); +SHOW_FUNCTION(bfq_timeout_async_show, bfqd->bfq_timeout[BLK_RW_ASYNC], 1); +SHOW_FUNCTION(bfq_low_latency_show, bfqd->low_latency, 0); +SHOW_FUNCTION(bfq_wr_coeff_show, bfqd->bfq_wr_coeff, 0); +SHOW_FUNCTION(bfq_wr_rt_max_time_show, bfqd->bfq_wr_rt_max_time, 1); +SHOW_FUNCTION(bfq_wr_min_idle_time_show, bfqd->bfq_wr_min_idle_time, 1); +SHOW_FUNCTION(bfq_wr_min_inter_arr_async_show, bfqd->bfq_wr_min_inter_arr_async, + 1); +SHOW_FUNCTION(bfq_wr_max_softrt_rate_show, bfqd->bfq_wr_max_softrt_rate, 0); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ +static ssize_t \ +__FUNC(struct elevator_queue *e, const char *page, size_t count) \ +{ \ + struct bfq_data *bfqd = e->elevator_data; \ + unsigned long uninitialized_var(__data); \ + int ret = bfq_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + if (__CONV) \ + *(__PTR) = msecs_to_jiffies(__data); \ + else \ + *(__PTR) = __data; \ + return ret; \ +} +STORE_FUNCTION(bfq_fifo_expire_sync_store, &bfqd->bfq_fifo_expire[1], 1, + INT_MAX, 1); +STORE_FUNCTION(bfq_fifo_expire_async_store, &bfqd->bfq_fifo_expire[0], 1, + INT_MAX, 1); +STORE_FUNCTION(bfq_back_seek_max_store, &bfqd->bfq_back_max, 0, INT_MAX, 0); +STORE_FUNCTION(bfq_back_seek_penalty_store, &bfqd->bfq_back_penalty, 1, + INT_MAX, 0); +STORE_FUNCTION(bfq_slice_idle_store, &bfqd->bfq_slice_idle, 0, INT_MAX, 1); +STORE_FUNCTION(bfq_max_budget_async_rq_store, &bfqd->bfq_max_budget_async_rq, + 1, INT_MAX, 0); +STORE_FUNCTION(bfq_timeout_async_store, &bfqd->bfq_timeout[BLK_RW_ASYNC], 0, + INT_MAX, 1); +STORE_FUNCTION(bfq_wr_coeff_store, &bfqd->bfq_wr_coeff, 1, INT_MAX, 0); +STORE_FUNCTION(bfq_wr_max_time_store, &bfqd->bfq_wr_max_time, 0, INT_MAX, 1); +STORE_FUNCTION(bfq_wr_rt_max_time_store, &bfqd->bfq_wr_rt_max_time, 0, INT_MAX, + 1); +STORE_FUNCTION(bfq_wr_min_idle_time_store, &bfqd->bfq_wr_min_idle_time, 0, + INT_MAX, 1); +STORE_FUNCTION(bfq_wr_min_inter_arr_async_store, + &bfqd->bfq_wr_min_inter_arr_async, 0, INT_MAX, 1); +STORE_FUNCTION(bfq_wr_max_softrt_rate_store, &bfqd->bfq_wr_max_softrt_rate, 0, + INT_MAX, 0); +#undef STORE_FUNCTION + +/* do nothing for the moment */ +static ssize_t bfq_weights_store(struct elevator_queue *e, + const char *page, size_t count) +{ + return count; +} + +static inline unsigned long bfq_estimated_max_budget(struct bfq_data *bfqd) +{ + u64 timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]); + + if (bfqd->peak_rate_samples >= BFQ_PEAK_RATE_SAMPLES) + return bfq_calc_max_budget(bfqd->peak_rate, timeout); + else + return bfq_default_max_budget; +} + +static ssize_t bfq_max_budget_store(struct elevator_queue *e, + const char *page, size_t count) +{ + struct bfq_data *bfqd = e->elevator_data; + unsigned long uninitialized_var(__data); + int ret = bfq_var_store(&__data, (page), count); + + if (__data == 0) + bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd); + else { + if (__data > INT_MAX) + __data = INT_MAX; + bfqd->bfq_max_budget = __data; + } + + bfqd->bfq_user_max_budget = __data; + + return ret; +} + +static ssize_t bfq_timeout_sync_store(struct elevator_queue *e, + const char *page, size_t count) +{ + struct bfq_data *bfqd = e->elevator_data; + unsigned long uninitialized_var(__data); + int ret = bfq_var_store(&__data, (page), count); + + if (__data < 1) + __data = 1; + else if (__data > INT_MAX) + __data = INT_MAX; + + bfqd->bfq_timeout[BLK_RW_SYNC] = msecs_to_jiffies(__data); + if (bfqd->bfq_user_max_budget == 0) + bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd); + + return ret; +} + +static ssize_t bfq_low_latency_store(struct elevator_queue *e, + const char *page, size_t count) +{ + struct bfq_data *bfqd = e->elevator_data; + unsigned long uninitialized_var(__data); + int ret = bfq_var_store(&__data, (page), count); + + if (__data > 1) + __data = 1; + if (__data == 0 && bfqd->low_latency != 0) + bfq_end_wr(bfqd); + bfqd->low_latency = __data; + + return ret; +} + +#define BFQ_ATTR(name) \ + __ATTR(name, S_IRUGO|S_IWUSR, bfq_##name##_show, bfq_##name##_store) + +static struct elv_fs_entry bfq_attrs[] = { + BFQ_ATTR(fifo_expire_sync), + BFQ_ATTR(fifo_expire_async), + BFQ_ATTR(back_seek_max), + BFQ_ATTR(back_seek_penalty), + BFQ_ATTR(slice_idle), + BFQ_ATTR(max_budget), + BFQ_ATTR(max_budget_async_rq), + BFQ_ATTR(timeout_sync), + BFQ_ATTR(timeout_async), + BFQ_ATTR(low_latency), + BFQ_ATTR(wr_coeff), + BFQ_ATTR(wr_max_time), + BFQ_ATTR(wr_rt_max_time), + BFQ_ATTR(wr_min_idle_time), + BFQ_ATTR(wr_min_inter_arr_async), + BFQ_ATTR(wr_max_softrt_rate), + BFQ_ATTR(weights), + __ATTR_NULL +}; + +static struct elevator_type iosched_bfq = { + .ops = { + .elevator_merge_fn = bfq_merge, + .elevator_merged_fn = bfq_merged_request, + .elevator_merge_req_fn = bfq_merged_requests, + .elevator_allow_merge_fn = bfq_allow_merge, + .elevator_dispatch_fn = bfq_dispatch_requests, + .elevator_add_req_fn = bfq_insert_request, + .elevator_activate_req_fn = bfq_activate_request, + .elevator_deactivate_req_fn = bfq_deactivate_request, + .elevator_completed_req_fn = bfq_completed_request, + .elevator_former_req_fn = elv_rb_former_request, + .elevator_latter_req_fn = elv_rb_latter_request, + .elevator_init_icq_fn = bfq_init_icq, + .elevator_exit_icq_fn = bfq_exit_icq, + .elevator_set_req_fn = bfq_set_request, + .elevator_put_req_fn = bfq_put_request, + .elevator_may_queue_fn = bfq_may_queue, + .elevator_init_fn = bfq_init_queue, + .elevator_exit_fn = bfq_exit_queue, + }, + .icq_size = sizeof(struct bfq_io_cq), + .icq_align = __alignof__(struct bfq_io_cq), + .elevator_attrs = bfq_attrs, + .elevator_name = "bfq", + .elevator_owner = THIS_MODULE, +}; + +static int __init bfq_init(void) +{ + /* + * Can be 0 on HZ < 1000 setups. + */ + if (bfq_slice_idle == 0) + bfq_slice_idle = 1; + + if (bfq_timeout_async == 0) + bfq_timeout_async = 1; + + if (bfq_slab_setup()) + return -ENOMEM; + + /* + * Times to load large popular applications for the typical systems + * installed on the reference devices (see the comments before the + * definitions of the two arrays). + */ + T_slow[0] = msecs_to_jiffies(2600); + T_slow[1] = msecs_to_jiffies(1000); + T_fast[0] = msecs_to_jiffies(5500); + T_fast[1] = msecs_to_jiffies(2000); + + /* + * Thresholds that determine the switch between speed classes (see + * the comments before the definition of the array). + */ + device_speed_thresh[0] = (R_fast[0] + R_slow[0]) / 2; + device_speed_thresh[1] = (R_fast[1] + R_slow[1]) / 2; + + elv_register(&iosched_bfq); + pr_info("BFQ I/O-scheduler: v7r8"); + + return 0; +} + +static void __exit bfq_exit(void) +{ + elv_unregister(&iosched_bfq); + bfq_slab_kill(); +} + +module_init(bfq_init); +module_exit(bfq_exit); + +MODULE_AUTHOR("Fabio Checconi, Paolo Valente"); +MODULE_LICENSE("GPL"); diff --git a/block/bfq-sched.c b/block/bfq-sched.c new file mode 100644 index 0000000000000..c3430993ec943 --- /dev/null +++ b/block/bfq-sched.c @@ -0,0 +1,1208 @@ +/* + * BFQ: Hierarchical B-WF2Q+ scheduler. + * + * Based on ideas and code from CFQ: + * Copyright (C) 2003 Jens Axboe + * + * Copyright (C) 2008 Fabio Checconi + * Paolo Valente + * + * Copyright (C) 2010 Paolo Valente + */ + +#ifdef CONFIG_CGROUP_BFQIO +#define for_each_entity(entity) \ + for (; entity != NULL; entity = entity->parent) + +#define for_each_entity_safe(entity, parent) \ + for (; entity && ({ parent = entity->parent; 1; }); entity = parent) + +static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, + int extract, + struct bfq_data *bfqd); + +static inline void bfq_update_budget(struct bfq_entity *next_in_service) +{ + struct bfq_entity *bfqg_entity; + struct bfq_group *bfqg; + struct bfq_sched_data *group_sd; + + BUG_ON(next_in_service == NULL); + + group_sd = next_in_service->sched_data; + + bfqg = container_of(group_sd, struct bfq_group, sched_data); + /* + * bfq_group's my_entity field is not NULL only if the group + * is not the root group. We must not touch the root entity + * as it must never become an in-service entity. + */ + bfqg_entity = bfqg->my_entity; + if (bfqg_entity != NULL) + bfqg_entity->budget = next_in_service->budget; +} + +static int bfq_update_next_in_service(struct bfq_sched_data *sd) +{ + struct bfq_entity *next_in_service; + + if (sd->in_service_entity != NULL) + /* will update/requeue at the end of service */ + return 0; + + /* + * NOTE: this can be improved in many ways, such as returning + * 1 (and thus propagating upwards the update) only when the + * budget changes, or caching the bfqq that will be scheduled + * next from this subtree. By now we worry more about + * correctness than about performance... + */ + next_in_service = bfq_lookup_next_entity(sd, 0, NULL); + sd->next_in_service = next_in_service; + + if (next_in_service != NULL) + bfq_update_budget(next_in_service); + + return 1; +} + +static inline void bfq_check_next_in_service(struct bfq_sched_data *sd, + struct bfq_entity *entity) +{ + BUG_ON(sd->next_in_service != entity); +} +#else +#define for_each_entity(entity) \ + for (; entity != NULL; entity = NULL) + +#define for_each_entity_safe(entity, parent) \ + for (parent = NULL; entity != NULL; entity = parent) + +static inline int bfq_update_next_in_service(struct bfq_sched_data *sd) +{ + return 0; +} + +static inline void bfq_check_next_in_service(struct bfq_sched_data *sd, + struct bfq_entity *entity) +{ +} + +static inline void bfq_update_budget(struct bfq_entity *next_in_service) +{ +} +#endif + +/* + * Shift for timestamp calculations. This actually limits the maximum + * service allowed in one timestamp delta (small shift values increase it), + * the maximum total weight that can be used for the queues in the system + * (big shift values increase it), and the period of virtual time + * wraparounds. + */ +#define WFQ_SERVICE_SHIFT 22 + +/** + * bfq_gt - compare two timestamps. + * @a: first ts. + * @b: second ts. + * + * Return @a > @b, dealing with wrapping correctly. + */ +static inline int bfq_gt(u64 a, u64 b) +{ + return (s64)(a - b) > 0; +} + +static inline struct bfq_queue *bfq_entity_to_bfqq(struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = NULL; + + BUG_ON(entity == NULL); + + if (entity->my_sched_data == NULL) + bfqq = container_of(entity, struct bfq_queue, entity); + + return bfqq; +} + + +/** + * bfq_delta - map service into the virtual time domain. + * @service: amount of service. + * @weight: scale factor (weight of an entity or weight sum). + */ +static inline u64 bfq_delta(unsigned long service, + unsigned long weight) +{ + u64 d = (u64)service << WFQ_SERVICE_SHIFT; + + do_div(d, weight); + return d; +} + +/** + * bfq_calc_finish - assign the finish time to an entity. + * @entity: the entity to act upon. + * @service: the service to be charged to the entity. + */ +static inline void bfq_calc_finish(struct bfq_entity *entity, + unsigned long service) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + + BUG_ON(entity->weight == 0); + + entity->finish = entity->start + + bfq_delta(service, entity->weight); + + if (bfqq != NULL) { + bfq_log_bfqq(bfqq->bfqd, bfqq, + "calc_finish: serv %lu, w %d", + service, entity->weight); + bfq_log_bfqq(bfqq->bfqd, bfqq, + "calc_finish: start %llu, finish %llu, delta %llu", + entity->start, entity->finish, + bfq_delta(service, entity->weight)); + } +} + +/** + * bfq_entity_of - get an entity from a node. + * @node: the node field of the entity. + * + * Convert a node pointer to the relative entity. This is used only + * to simplify the logic of some functions and not as the generic + * conversion mechanism because, e.g., in the tree walking functions, + * the check for a %NULL value would be redundant. + */ +static inline struct bfq_entity *bfq_entity_of(struct rb_node *node) +{ + struct bfq_entity *entity = NULL; + + if (node != NULL) + entity = rb_entry(node, struct bfq_entity, rb_node); + + return entity; +} + +/** + * bfq_extract - remove an entity from a tree. + * @root: the tree root. + * @entity: the entity to remove. + */ +static inline void bfq_extract(struct rb_root *root, + struct bfq_entity *entity) +{ + BUG_ON(entity->tree != root); + + entity->tree = NULL; + rb_erase(&entity->rb_node, root); +} + +/** + * bfq_idle_extract - extract an entity from the idle tree. + * @st: the service tree of the owning @entity. + * @entity: the entity being removed. + */ +static void bfq_idle_extract(struct bfq_service_tree *st, + struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + struct rb_node *next; + + BUG_ON(entity->tree != &st->idle); + + if (entity == st->first_idle) { + next = rb_next(&entity->rb_node); + st->first_idle = bfq_entity_of(next); + } + + if (entity == st->last_idle) { + next = rb_prev(&entity->rb_node); + st->last_idle = bfq_entity_of(next); + } + + bfq_extract(&st->idle, entity); + + if (bfqq != NULL) + list_del(&bfqq->bfqq_list); +} + +/** + * bfq_insert - generic tree insertion. + * @root: tree root. + * @entity: entity to insert. + * + * This is used for the idle and the active tree, since they are both + * ordered by finish time. + */ +static void bfq_insert(struct rb_root *root, struct bfq_entity *entity) +{ + struct bfq_entity *entry; + struct rb_node **node = &root->rb_node; + struct rb_node *parent = NULL; + + BUG_ON(entity->tree != NULL); + + while (*node != NULL) { + parent = *node; + entry = rb_entry(parent, struct bfq_entity, rb_node); + + if (bfq_gt(entry->finish, entity->finish)) + node = &parent->rb_left; + else + node = &parent->rb_right; + } + + rb_link_node(&entity->rb_node, parent, node); + rb_insert_color(&entity->rb_node, root); + + entity->tree = root; +} + +/** + * bfq_update_min - update the min_start field of a entity. + * @entity: the entity to update. + * @node: one of its children. + * + * This function is called when @entity may store an invalid value for + * min_start due to updates to the active tree. The function assumes + * that the subtree rooted at @node (which may be its left or its right + * child) has a valid min_start value. + */ +static inline void bfq_update_min(struct bfq_entity *entity, + struct rb_node *node) +{ + struct bfq_entity *child; + + if (node != NULL) { + child = rb_entry(node, struct bfq_entity, rb_node); + if (bfq_gt(entity->min_start, child->min_start)) + entity->min_start = child->min_start; + } +} + +/** + * bfq_update_active_node - recalculate min_start. + * @node: the node to update. + * + * @node may have changed position or one of its children may have moved, + * this function updates its min_start value. The left and right subtrees + * are assumed to hold a correct min_start value. + */ +static inline void bfq_update_active_node(struct rb_node *node) +{ + struct bfq_entity *entity = rb_entry(node, struct bfq_entity, rb_node); + + entity->min_start = entity->start; + bfq_update_min(entity, node->rb_right); + bfq_update_min(entity, node->rb_left); +} + +/** + * bfq_update_active_tree - update min_start for the whole active tree. + * @node: the starting node. + * + * @node must be the deepest modified node after an update. This function + * updates its min_start using the values held by its children, assuming + * that they did not change, and then updates all the nodes that may have + * changed in the path to the root. The only nodes that may have changed + * are the ones in the path or their siblings. + */ +static void bfq_update_active_tree(struct rb_node *node) +{ + struct rb_node *parent; + +up: + bfq_update_active_node(node); + + parent = rb_parent(node); + if (parent == NULL) + return; + + if (node == parent->rb_left && parent->rb_right != NULL) + bfq_update_active_node(parent->rb_right); + else if (parent->rb_left != NULL) + bfq_update_active_node(parent->rb_left); + + node = parent; + goto up; +} + +static void bfq_weights_tree_add(struct bfq_data *bfqd, + struct bfq_entity *entity, + struct rb_root *root); + +static void bfq_weights_tree_remove(struct bfq_data *bfqd, + struct bfq_entity *entity, + struct rb_root *root); + + +/** + * bfq_active_insert - insert an entity in the active tree of its + * group/device. + * @st: the service tree of the entity. + * @entity: the entity being inserted. + * + * The active tree is ordered by finish time, but an extra key is kept + * per each node, containing the minimum value for the start times of + * its children (and the node itself), so it's possible to search for + * the eligible node with the lowest finish time in logarithmic time. + */ +static void bfq_active_insert(struct bfq_service_tree *st, + struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + struct rb_node *node = &entity->rb_node; +#ifdef CONFIG_CGROUP_BFQIO + struct bfq_sched_data *sd = NULL; + struct bfq_group *bfqg = NULL; + struct bfq_data *bfqd = NULL; +#endif + + bfq_insert(&st->active, entity); + + if (node->rb_left != NULL) + node = node->rb_left; + else if (node->rb_right != NULL) + node = node->rb_right; + + bfq_update_active_tree(node); + +#ifdef CONFIG_CGROUP_BFQIO + sd = entity->sched_data; + bfqg = container_of(sd, struct bfq_group, sched_data); + BUG_ON(!bfqg); + bfqd = (struct bfq_data *)bfqg->bfqd; +#endif + if (bfqq != NULL) + list_add(&bfqq->bfqq_list, &bfqq->bfqd->active_list); +#ifdef CONFIG_CGROUP_BFQIO + else { /* bfq_group */ + BUG_ON(!bfqd); + bfq_weights_tree_add(bfqd, entity, &bfqd->group_weights_tree); + } + if (bfqg != bfqd->root_group) { + BUG_ON(!bfqg); + BUG_ON(!bfqd); + bfqg->active_entities++; + if (bfqg->active_entities == 2) + bfqd->active_numerous_groups++; + } +#endif +} + +/** + * bfq_ioprio_to_weight - calc a weight from an ioprio. + * @ioprio: the ioprio value to convert. + */ +static inline unsigned short bfq_ioprio_to_weight(int ioprio) +{ + BUG_ON(ioprio < 0 || ioprio >= IOPRIO_BE_NR); + return IOPRIO_BE_NR - ioprio; +} + +/** + * bfq_weight_to_ioprio - calc an ioprio from a weight. + * @weight: the weight value to convert. + * + * To preserve as mush as possible the old only-ioprio user interface, + * 0 is used as an escape ioprio value for weights (numerically) equal or + * larger than IOPRIO_BE_NR + */ +static inline unsigned short bfq_weight_to_ioprio(int weight) +{ + BUG_ON(weight < BFQ_MIN_WEIGHT || weight > BFQ_MAX_WEIGHT); + return IOPRIO_BE_NR - weight < 0 ? 0 : IOPRIO_BE_NR - weight; +} + +static inline void bfq_get_entity(struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + + if (bfqq != NULL) { + atomic_inc(&bfqq->ref); + bfq_log_bfqq(bfqq->bfqd, bfqq, "get_entity: %p %d", + bfqq, atomic_read(&bfqq->ref)); + } +} + +/** + * bfq_find_deepest - find the deepest node that an extraction can modify. + * @node: the node being removed. + * + * Do the first step of an extraction in an rb tree, looking for the + * node that will replace @node, and returning the deepest node that + * the following modifications to the tree can touch. If @node is the + * last node in the tree return %NULL. + */ +static struct rb_node *bfq_find_deepest(struct rb_node *node) +{ + struct rb_node *deepest; + + if (node->rb_right == NULL && node->rb_left == NULL) + deepest = rb_parent(node); + else if (node->rb_right == NULL) + deepest = node->rb_left; + else if (node->rb_left == NULL) + deepest = node->rb_right; + else { + deepest = rb_next(node); + if (deepest->rb_right != NULL) + deepest = deepest->rb_right; + else if (rb_parent(deepest) != node) + deepest = rb_parent(deepest); + } + + return deepest; +} + +/** + * bfq_active_extract - remove an entity from the active tree. + * @st: the service_tree containing the tree. + * @entity: the entity being removed. + */ +static void bfq_active_extract(struct bfq_service_tree *st, + struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + struct rb_node *node; +#ifdef CONFIG_CGROUP_BFQIO + struct bfq_sched_data *sd = NULL; + struct bfq_group *bfqg = NULL; + struct bfq_data *bfqd = NULL; +#endif + + node = bfq_find_deepest(&entity->rb_node); + bfq_extract(&st->active, entity); + + if (node != NULL) + bfq_update_active_tree(node); + +#ifdef CONFIG_CGROUP_BFQIO + sd = entity->sched_data; + bfqg = container_of(sd, struct bfq_group, sched_data); + BUG_ON(!bfqg); + bfqd = (struct bfq_data *)bfqg->bfqd; +#endif + if (bfqq != NULL) + list_del(&bfqq->bfqq_list); +#ifdef CONFIG_CGROUP_BFQIO + else { /* bfq_group */ + BUG_ON(!bfqd); + bfq_weights_tree_remove(bfqd, entity, + &bfqd->group_weights_tree); + } + if (bfqg != bfqd->root_group) { + BUG_ON(!bfqg); + BUG_ON(!bfqd); + BUG_ON(!bfqg->active_entities); + bfqg->active_entities--; + if (bfqg->active_entities == 1) { + BUG_ON(!bfqd->active_numerous_groups); + bfqd->active_numerous_groups--; + } + } +#endif +} + +/** + * bfq_idle_insert - insert an entity into the idle tree. + * @st: the service tree containing the tree. + * @entity: the entity to insert. + */ +static void bfq_idle_insert(struct bfq_service_tree *st, + struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + struct bfq_entity *first_idle = st->first_idle; + struct bfq_entity *last_idle = st->last_idle; + + if (first_idle == NULL || bfq_gt(first_idle->finish, entity->finish)) + st->first_idle = entity; + if (last_idle == NULL || bfq_gt(entity->finish, last_idle->finish)) + st->last_idle = entity; + + bfq_insert(&st->idle, entity); + + if (bfqq != NULL) + list_add(&bfqq->bfqq_list, &bfqq->bfqd->idle_list); +} + +/** + * bfq_forget_entity - remove an entity from the wfq trees. + * @st: the service tree. + * @entity: the entity being removed. + * + * Update the device status and forget everything about @entity, putting + * the device reference to it, if it is a queue. Entities belonging to + * groups are not refcounted. + */ +static void bfq_forget_entity(struct bfq_service_tree *st, + struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + struct bfq_sched_data *sd; + + BUG_ON(!entity->on_st); + + entity->on_st = 0; + st->wsum -= entity->weight; + if (bfqq != NULL) { + sd = entity->sched_data; + bfq_log_bfqq(bfqq->bfqd, bfqq, "forget_entity: %p %d", + bfqq, atomic_read(&bfqq->ref)); + bfq_put_queue(bfqq); + } +} + +/** + * bfq_put_idle_entity - release the idle tree ref of an entity. + * @st: service tree for the entity. + * @entity: the entity being released. + */ +static void bfq_put_idle_entity(struct bfq_service_tree *st, + struct bfq_entity *entity) +{ + bfq_idle_extract(st, entity); + bfq_forget_entity(st, entity); +} + +/** + * bfq_forget_idle - update the idle tree if necessary. + * @st: the service tree to act upon. + * + * To preserve the global O(log N) complexity we only remove one entry here; + * as the idle tree will not grow indefinitely this can be done safely. + */ +static void bfq_forget_idle(struct bfq_service_tree *st) +{ + struct bfq_entity *first_idle = st->first_idle; + struct bfq_entity *last_idle = st->last_idle; + + if (RB_EMPTY_ROOT(&st->active) && last_idle != NULL && + !bfq_gt(last_idle->finish, st->vtime)) { + /* + * Forget the whole idle tree, increasing the vtime past + * the last finish time of idle entities. + */ + st->vtime = last_idle->finish; + } + + if (first_idle != NULL && !bfq_gt(first_idle->finish, st->vtime)) + bfq_put_idle_entity(st, first_idle); +} + +static struct bfq_service_tree * +__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, + struct bfq_entity *entity) +{ + struct bfq_service_tree *new_st = old_st; + + if (entity->ioprio_changed) { + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + unsigned short prev_weight, new_weight; + struct bfq_data *bfqd = NULL; + struct rb_root *root; +#ifdef CONFIG_CGROUP_BFQIO + struct bfq_sched_data *sd; + struct bfq_group *bfqg; +#endif + + if (bfqq != NULL) + bfqd = bfqq->bfqd; +#ifdef CONFIG_CGROUP_BFQIO + else { + sd = entity->my_sched_data; + bfqg = container_of(sd, struct bfq_group, sched_data); + BUG_ON(!bfqg); + bfqd = (struct bfq_data *)bfqg->bfqd; + BUG_ON(!bfqd); + } +#endif + + BUG_ON(old_st->wsum < entity->weight); + old_st->wsum -= entity->weight; + + if (entity->new_weight != entity->orig_weight) { + if (entity->new_weight < BFQ_MIN_WEIGHT || + entity->new_weight > BFQ_MAX_WEIGHT) { + printk(KERN_CRIT "update_weight_prio: " + "new_weight %d\n", + entity->new_weight); + BUG(); + } + entity->orig_weight = entity->new_weight; + entity->ioprio = + bfq_weight_to_ioprio(entity->orig_weight); + } + + entity->ioprio_class = entity->new_ioprio_class; + entity->ioprio_changed = 0; + + /* + * NOTE: here we may be changing the weight too early, + * this will cause unfairness. The correct approach + * would have required additional complexity to defer + * weight changes to the proper time instants (i.e., + * when entity->finish <= old_st->vtime). + */ + new_st = bfq_entity_service_tree(entity); + + prev_weight = entity->weight; + new_weight = entity->orig_weight * + (bfqq != NULL ? bfqq->wr_coeff : 1); + /* + * If the weight of the entity changes, remove the entity + * from its old weight counter (if there is a counter + * associated with the entity), and add it to the counter + * associated with its new weight. + */ + if (prev_weight != new_weight) { + root = bfqq ? &bfqd->queue_weights_tree : + &bfqd->group_weights_tree; + bfq_weights_tree_remove(bfqd, entity, root); + } + entity->weight = new_weight; + /* + * Add the entity to its weights tree only if it is + * not associated with a weight-raised queue. + */ + if (prev_weight != new_weight && + (bfqq ? bfqq->wr_coeff == 1 : 1)) + /* If we get here, root has been initialized. */ + bfq_weights_tree_add(bfqd, entity, root); + + new_st->wsum += entity->weight; + + if (new_st != old_st) + entity->start = new_st->vtime; + } + + return new_st; +} + +/** + * bfq_bfqq_served - update the scheduler status after selection for + * service. + * @bfqq: the queue being served. + * @served: bytes to transfer. + * + * NOTE: this can be optimized, as the timestamps of upper level entities + * are synchronized every time a new bfqq is selected for service. By now, + * we keep it to better check consistency. + */ +static void bfq_bfqq_served(struct bfq_queue *bfqq, unsigned long served) +{ + struct bfq_entity *entity = &bfqq->entity; + struct bfq_service_tree *st; + + for_each_entity(entity) { + st = bfq_entity_service_tree(entity); + + entity->service += served; + BUG_ON(entity->service > entity->budget); + BUG_ON(st->wsum == 0); + + st->vtime += bfq_delta(served, st->wsum); + bfq_forget_idle(st); + } + bfq_log_bfqq(bfqq->bfqd, bfqq, "bfqq_served %lu secs", served); +} + +/** + * bfq_bfqq_charge_full_budget - set the service to the entity budget. + * @bfqq: the queue that needs a service update. + * + * When it's not possible to be fair in the service domain, because + * a queue is not consuming its budget fast enough (the meaning of + * fast depends on the timeout parameter), we charge it a full + * budget. In this way we should obtain a sort of time-domain + * fairness among all the seeky/slow queues. + */ +static inline void bfq_bfqq_charge_full_budget(struct bfq_queue *bfqq) +{ + struct bfq_entity *entity = &bfqq->entity; + + bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget"); + + bfq_bfqq_served(bfqq, entity->budget - entity->service); +} + +/** + * __bfq_activate_entity - activate an entity. + * @entity: the entity being activated. + * + * Called whenever an entity is activated, i.e., it is not active and one + * of its children receives a new request, or has to be reactivated due to + * budget exhaustion. It uses the current budget of the entity (and the + * service received if @entity is active) of the queue to calculate its + * timestamps. + */ +static void __bfq_activate_entity(struct bfq_entity *entity) +{ + struct bfq_sched_data *sd = entity->sched_data; + struct bfq_service_tree *st = bfq_entity_service_tree(entity); + + if (entity == sd->in_service_entity) { + BUG_ON(entity->tree != NULL); + /* + * If we are requeueing the current entity we have + * to take care of not charging to it service it has + * not received. + */ + bfq_calc_finish(entity, entity->service); + entity->start = entity->finish; + sd->in_service_entity = NULL; + } else if (entity->tree == &st->active) { + /* + * Requeueing an entity due to a change of some + * next_in_service entity below it. We reuse the + * old start time. + */ + bfq_active_extract(st, entity); + } else if (entity->tree == &st->idle) { + /* + * Must be on the idle tree, bfq_idle_extract() will + * check for that. + */ + bfq_idle_extract(st, entity); + entity->start = bfq_gt(st->vtime, entity->finish) ? + st->vtime : entity->finish; + } else { + /* + * The finish time of the entity may be invalid, and + * it is in the past for sure, otherwise the queue + * would have been on the idle tree. + */ + entity->start = st->vtime; + st->wsum += entity->weight; + bfq_get_entity(entity); + + BUG_ON(entity->on_st); + entity->on_st = 1; + } + + st = __bfq_entity_update_weight_prio(st, entity); + bfq_calc_finish(entity, entity->budget); + bfq_active_insert(st, entity); +} + +/** + * bfq_activate_entity - activate an entity and its ancestors if necessary. + * @entity: the entity to activate. + * + * Activate @entity and all the entities on the path from it to the root. + */ +static void bfq_activate_entity(struct bfq_entity *entity) +{ + struct bfq_sched_data *sd; + + for_each_entity(entity) { + __bfq_activate_entity(entity); + + sd = entity->sched_data; + if (!bfq_update_next_in_service(sd)) + /* + * No need to propagate the activation to the + * upper entities, as they will be updated when + * the in-service entity is rescheduled. + */ + break; + } +} + +/** + * __bfq_deactivate_entity - deactivate an entity from its service tree. + * @entity: the entity to deactivate. + * @requeue: if false, the entity will not be put into the idle tree. + * + * Deactivate an entity, independently from its previous state. If the + * entity was not on a service tree just return, otherwise if it is on + * any scheduler tree, extract it from that tree, and if necessary + * and if the caller did not specify @requeue, put it on the idle tree. + * + * Return %1 if the caller should update the entity hierarchy, i.e., + * if the entity was in service or if it was the next_in_service for + * its sched_data; return %0 otherwise. + */ +static int __bfq_deactivate_entity(struct bfq_entity *entity, int requeue) +{ + struct bfq_sched_data *sd = entity->sched_data; + struct bfq_service_tree *st = bfq_entity_service_tree(entity); + int was_in_service = entity == sd->in_service_entity; + int ret = 0; + + if (!entity->on_st) + return 0; + + BUG_ON(was_in_service && entity->tree != NULL); + + if (was_in_service) { + bfq_calc_finish(entity, entity->service); + sd->in_service_entity = NULL; + } else if (entity->tree == &st->active) + bfq_active_extract(st, entity); + else if (entity->tree == &st->idle) + bfq_idle_extract(st, entity); + else if (entity->tree != NULL) + BUG(); + + if (was_in_service || sd->next_in_service == entity) + ret = bfq_update_next_in_service(sd); + + if (!requeue || !bfq_gt(entity->finish, st->vtime)) + bfq_forget_entity(st, entity); + else + bfq_idle_insert(st, entity); + + BUG_ON(sd->in_service_entity == entity); + BUG_ON(sd->next_in_service == entity); + + return ret; +} + +/** + * bfq_deactivate_entity - deactivate an entity. + * @entity: the entity to deactivate. + * @requeue: true if the entity can be put on the idle tree + */ +static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue) +{ + struct bfq_sched_data *sd; + struct bfq_entity *parent; + + for_each_entity_safe(entity, parent) { + sd = entity->sched_data; + + if (!__bfq_deactivate_entity(entity, requeue)) + /* + * The parent entity is still backlogged, and + * we don't need to update it as it is still + * in service. + */ + break; + + if (sd->next_in_service != NULL) + /* + * The parent entity is still backlogged and + * the budgets on the path towards the root + * need to be updated. + */ + goto update; + + /* + * If we reach there the parent is no more backlogged and + * we want to propagate the dequeue upwards. + */ + requeue = 1; + } + + return; + +update: + entity = parent; + for_each_entity(entity) { + __bfq_activate_entity(entity); + + sd = entity->sched_data; + if (!bfq_update_next_in_service(sd)) + break; + } +} + +/** + * bfq_update_vtime - update vtime if necessary. + * @st: the service tree to act upon. + * + * If necessary update the service tree vtime to have at least one + * eligible entity, skipping to its start time. Assumes that the + * active tree of the device is not empty. + * + * NOTE: this hierarchical implementation updates vtimes quite often, + * we may end up with reactivated processes getting timestamps after a + * vtime skip done because we needed a ->first_active entity on some + * intermediate node. + */ +static void bfq_update_vtime(struct bfq_service_tree *st) +{ + struct bfq_entity *entry; + struct rb_node *node = st->active.rb_node; + + entry = rb_entry(node, struct bfq_entity, rb_node); + if (bfq_gt(entry->min_start, st->vtime)) { + st->vtime = entry->min_start; + bfq_forget_idle(st); + } +} + +/** + * bfq_first_active_entity - find the eligible entity with + * the smallest finish time + * @st: the service tree to select from. + * + * This function searches the first schedulable entity, starting from the + * root of the tree and going on the left every time on this side there is + * a subtree with at least one eligible (start >= vtime) entity. The path on + * the right is followed only if a) the left subtree contains no eligible + * entities and b) no eligible entity has been found yet. + */ +static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st) +{ + struct bfq_entity *entry, *first = NULL; + struct rb_node *node = st->active.rb_node; + + while (node != NULL) { + entry = rb_entry(node, struct bfq_entity, rb_node); +left: + if (!bfq_gt(entry->start, st->vtime)) + first = entry; + + BUG_ON(bfq_gt(entry->min_start, st->vtime)); + + if (node->rb_left != NULL) { + entry = rb_entry(node->rb_left, + struct bfq_entity, rb_node); + if (!bfq_gt(entry->min_start, st->vtime)) { + node = node->rb_left; + goto left; + } + } + if (first != NULL) + break; + node = node->rb_right; + } + + BUG_ON(first == NULL && !RB_EMPTY_ROOT(&st->active)); + return first; +} + +/** + * __bfq_lookup_next_entity - return the first eligible entity in @st. + * @st: the service tree. + * + * Update the virtual time in @st and return the first eligible entity + * it contains. + */ +static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st, + bool force) +{ + struct bfq_entity *entity, *new_next_in_service = NULL; + + if (RB_EMPTY_ROOT(&st->active)) + return NULL; + + bfq_update_vtime(st); + entity = bfq_first_active_entity(st); + BUG_ON(bfq_gt(entity->start, st->vtime)); + + /* + * If the chosen entity does not match with the sched_data's + * next_in_service and we are forcedly serving the IDLE priority + * class tree, bubble up budget update. + */ + if (unlikely(force && entity != entity->sched_data->next_in_service)) { + new_next_in_service = entity; + for_each_entity(new_next_in_service) + bfq_update_budget(new_next_in_service); + } + + return entity; +} + +/** + * bfq_lookup_next_entity - return the first eligible entity in @sd. + * @sd: the sched_data. + * @extract: if true the returned entity will be also extracted from @sd. + * + * NOTE: since we cache the next_in_service entity at each level of the + * hierarchy, the complexity of the lookup can be decreased with + * absolutely no effort just returning the cached next_in_service value; + * we prefer to do full lookups to test the consistency of * the data + * structures. + */ +static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, + int extract, + struct bfq_data *bfqd) +{ + struct bfq_service_tree *st = sd->service_tree; + struct bfq_entity *entity; + int i = 0; + + BUG_ON(sd->in_service_entity != NULL); + + if (bfqd != NULL && + jiffies - bfqd->bfq_class_idle_last_service > BFQ_CL_IDLE_TIMEOUT) { + entity = __bfq_lookup_next_entity(st + BFQ_IOPRIO_CLASSES - 1, + true); + if (entity != NULL) { + i = BFQ_IOPRIO_CLASSES - 1; + bfqd->bfq_class_idle_last_service = jiffies; + sd->next_in_service = entity; + } + } + for (; i < BFQ_IOPRIO_CLASSES; i++) { + entity = __bfq_lookup_next_entity(st + i, false); + if (entity != NULL) { + if (extract) { + bfq_check_next_in_service(sd, entity); + bfq_active_extract(st + i, entity); + sd->in_service_entity = entity; + sd->next_in_service = NULL; + } + break; + } + } + + return entity; +} + +/* + * Get next queue for service. + */ +static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) +{ + struct bfq_entity *entity = NULL; + struct bfq_sched_data *sd; + struct bfq_queue *bfqq; + + BUG_ON(bfqd->in_service_queue != NULL); + + if (bfqd->busy_queues == 0) + return NULL; + + sd = &bfqd->root_group->sched_data; + for (; sd != NULL; sd = entity->my_sched_data) { + entity = bfq_lookup_next_entity(sd, 1, bfqd); + BUG_ON(entity == NULL); + entity->service = 0; + } + + bfqq = bfq_entity_to_bfqq(entity); + BUG_ON(bfqq == NULL); + + return bfqq; +} + +/* + * Forced extraction of the given queue. + */ +static void bfq_get_next_queue_forced(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + struct bfq_entity *entity; + struct bfq_sched_data *sd; + + BUG_ON(bfqd->in_service_queue != NULL); + + entity = &bfqq->entity; + /* + * Bubble up extraction/update from the leaf to the root. + */ + for_each_entity(entity) { + sd = entity->sched_data; + bfq_update_budget(entity); + bfq_update_vtime(bfq_entity_service_tree(entity)); + bfq_active_extract(bfq_entity_service_tree(entity), entity); + sd->in_service_entity = entity; + sd->next_in_service = NULL; + entity->service = 0; + } + + return; +} + +static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd) +{ + if (bfqd->in_service_bic != NULL) { + put_io_context(bfqd->in_service_bic->icq.ioc); + bfqd->in_service_bic = NULL; + } + + bfqd->in_service_queue = NULL; + del_timer(&bfqd->idle_slice_timer); +} + +static void bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, + int requeue) +{ + struct bfq_entity *entity = &bfqq->entity; + + if (bfqq == bfqd->in_service_queue) + __bfq_bfqd_reset_in_service(bfqd); + + bfq_deactivate_entity(entity, requeue); +} + +static void bfq_activate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) +{ + struct bfq_entity *entity = &bfqq->entity; + + bfq_activate_entity(entity); +} + +/* + * Called when the bfqq no longer has requests pending, remove it from + * the service tree. + */ +static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq, + int requeue) +{ + BUG_ON(!bfq_bfqq_busy(bfqq)); + BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); + + bfq_log_bfqq(bfqd, bfqq, "del from busy"); + + bfq_clear_bfqq_busy(bfqq); + + BUG_ON(bfqd->busy_queues == 0); + bfqd->busy_queues--; + + if (!bfqq->dispatched) { + bfq_weights_tree_remove(bfqd, &bfqq->entity, + &bfqd->queue_weights_tree); + if (!blk_queue_nonrot(bfqd->queue)) { + BUG_ON(!bfqd->busy_in_flight_queues); + bfqd->busy_in_flight_queues--; + if (bfq_bfqq_constantly_seeky(bfqq)) { + BUG_ON(!bfqd-> + const_seeky_busy_in_flight_queues); + bfqd->const_seeky_busy_in_flight_queues--; + } + } + } + if (bfqq->wr_coeff > 1) + bfqd->wr_busy_queues--; + + bfq_deactivate_bfqq(bfqd, bfqq, requeue); +} + +/* + * Called when an inactive queue receives a new request. + */ +static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq) +{ + BUG_ON(bfq_bfqq_busy(bfqq)); + BUG_ON(bfqq == bfqd->in_service_queue); + + bfq_log_bfqq(bfqd, bfqq, "add to busy"); + + bfq_activate_bfqq(bfqd, bfqq); + + bfq_mark_bfqq_busy(bfqq); + bfqd->busy_queues++; + + if (!bfqq->dispatched) { + if (bfqq->wr_coeff == 1) + bfq_weights_tree_add(bfqd, &bfqq->entity, + &bfqd->queue_weights_tree); + if (!blk_queue_nonrot(bfqd->queue)) { + bfqd->busy_in_flight_queues++; + if (bfq_bfqq_constantly_seeky(bfqq)) + bfqd->const_seeky_busy_in_flight_queues++; + } + } + if (bfqq->wr_coeff > 1) + bfqd->wr_busy_queues++; +} diff --git a/block/bfq.h b/block/bfq.h new file mode 100644 index 0000000000000..3173b35e38536 --- /dev/null +++ b/block/bfq.h @@ -0,0 +1,771 @@ +/* + * BFQ-v7r8 for 3.18.0: data structures and common functions prototypes. + * + * Based on ideas and code from CFQ: + * Copyright (C) 2003 Jens Axboe + * + * Copyright (C) 2008 Fabio Checconi + * Paolo Valente + * + * Copyright (C) 2010 Paolo Valente + */ + +#ifndef _BFQ_H +#define _BFQ_H + +#include +#include +#include +#include + +#define BFQ_IOPRIO_CLASSES 3 +#define BFQ_CL_IDLE_TIMEOUT (HZ/5) + +#define BFQ_MIN_WEIGHT 1 +#define BFQ_MAX_WEIGHT 1000 + +#define BFQ_DEFAULT_QUEUE_IOPRIO 4 + +#define BFQ_DEFAULT_GRP_WEIGHT 10 +#define BFQ_DEFAULT_GRP_IOPRIO 0 +#define BFQ_DEFAULT_GRP_CLASS IOPRIO_CLASS_BE + +struct bfq_entity; + +/** + * struct bfq_service_tree - per ioprio_class service tree. + * @active: tree for active entities (i.e., those backlogged). + * @idle: tree for idle entities (i.e., those not backlogged, with V <= F_i). + * @first_idle: idle entity with minimum F_i. + * @last_idle: idle entity with maximum F_i. + * @vtime: scheduler virtual time. + * @wsum: scheduler weight sum; active and idle entities contribute to it. + * + * Each service tree represents a B-WF2Q+ scheduler on its own. Each + * ioprio_class has its own independent scheduler, and so its own + * bfq_service_tree. All the fields are protected by the queue lock + * of the containing bfqd. + */ +struct bfq_service_tree { + struct rb_root active; + struct rb_root idle; + + struct bfq_entity *first_idle; + struct bfq_entity *last_idle; + + u64 vtime; + unsigned long wsum; +}; + +/** + * struct bfq_sched_data - multi-class scheduler. + * @in_service_entity: entity in service. + * @next_in_service: head-of-the-line entity in the scheduler. + * @service_tree: array of service trees, one per ioprio_class. + * + * bfq_sched_data is the basic scheduler queue. It supports three + * ioprio_classes, and can be used either as a toplevel queue or as + * an intermediate queue on a hierarchical setup. + * @next_in_service points to the active entity of the sched_data + * service trees that will be scheduled next. + * + * The supported ioprio_classes are the same as in CFQ, in descending + * priority order, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE. + * Requests from higher priority queues are served before all the + * requests from lower priority queues; among requests of the same + * queue requests are served according to B-WF2Q+. + * All the fields are protected by the queue lock of the containing bfqd. + */ +struct bfq_sched_data { + struct bfq_entity *in_service_entity; + struct bfq_entity *next_in_service; + struct bfq_service_tree service_tree[BFQ_IOPRIO_CLASSES]; +}; + +/** + * struct bfq_weight_counter - counter of the number of all active entities + * with a given weight. + * @weight: weight of the entities that this counter refers to. + * @num_active: number of active entities with this weight. + * @weights_node: weights tree member (see bfq_data's @queue_weights_tree + * and @group_weights_tree). + */ +struct bfq_weight_counter { + short int weight; + unsigned int num_active; + struct rb_node weights_node; +}; + +/** + * struct bfq_entity - schedulable entity. + * @rb_node: service_tree member. + * @weight_counter: pointer to the weight counter associated with this entity. + * @on_st: flag, true if the entity is on a tree (either the active or + * the idle one of its service_tree). + * @finish: B-WF2Q+ finish timestamp (aka F_i). + * @start: B-WF2Q+ start timestamp (aka S_i). + * @tree: tree the entity is enqueued into; %NULL if not on a tree. + * @min_start: minimum start time of the (active) subtree rooted at + * this entity; used for O(log N) lookups into active trees. + * @service: service received during the last round of service. + * @budget: budget used to calculate F_i; F_i = S_i + @budget / @weight. + * @weight: weight of the queue + * @parent: parent entity, for hierarchical scheduling. + * @my_sched_data: for non-leaf nodes in the cgroup hierarchy, the + * associated scheduler queue, %NULL on leaf nodes. + * @sched_data: the scheduler queue this entity belongs to. + * @ioprio: the ioprio in use. + * @new_weight: when a weight change is requested, the new weight value. + * @orig_weight: original weight, used to implement weight boosting + * @new_ioprio: when an ioprio change is requested, the new ioprio value. + * @ioprio_class: the ioprio_class in use. + * @new_ioprio_class: when an ioprio_class change is requested, the new + * ioprio_class value. + * @ioprio_changed: flag, true when the user requested a weight, ioprio or + * ioprio_class change. + * + * A bfq_entity is used to represent either a bfq_queue (leaf node in the + * cgroup hierarchy) or a bfq_group into the upper level scheduler. Each + * entity belongs to the sched_data of the parent group in the cgroup + * hierarchy. Non-leaf entities have also their own sched_data, stored + * in @my_sched_data. + * + * Each entity stores independently its priority values; this would + * allow different weights on different devices, but this + * functionality is not exported to userspace by now. Priorities and + * weights are updated lazily, first storing the new values into the + * new_* fields, then setting the @ioprio_changed flag. As soon as + * there is a transition in the entity state that allows the priority + * update to take place the effective and the requested priority + * values are synchronized. + * + * Unless cgroups are used, the weight value is calculated from the + * ioprio to export the same interface as CFQ. When dealing with + * ``well-behaved'' queues (i.e., queues that do not spend too much + * time to consume their budget and have true sequential behavior, and + * when there are no external factors breaking anticipation) the + * relative weights at each level of the cgroups hierarchy should be + * guaranteed. All the fields are protected by the queue lock of the + * containing bfqd. + */ +struct bfq_entity { + struct rb_node rb_node; + struct bfq_weight_counter *weight_counter; + + int on_st; + + u64 finish; + u64 start; + + struct rb_root *tree; + + u64 min_start; + + unsigned long service, budget; + unsigned short weight, new_weight; + unsigned short orig_weight; + + struct bfq_entity *parent; + + struct bfq_sched_data *my_sched_data; + struct bfq_sched_data *sched_data; + + unsigned short ioprio, new_ioprio; + unsigned short ioprio_class, new_ioprio_class; + + int ioprio_changed; +}; + +struct bfq_group; + +/** + * struct bfq_queue - leaf schedulable entity. + * @ref: reference counter. + * @bfqd: parent bfq_data. + * @new_bfqq: shared bfq_queue if queue is cooperating with + * one or more other queues. + * @pos_node: request-position tree member (see bfq_data's @rq_pos_tree). + * @pos_root: request-position tree root (see bfq_data's @rq_pos_tree). + * @sort_list: sorted list of pending requests. + * @next_rq: if fifo isn't expired, next request to serve. + * @queued: nr of requests queued in @sort_list. + * @allocated: currently allocated requests. + * @meta_pending: pending metadata requests. + * @fifo: fifo list of requests in sort_list. + * @entity: entity representing this queue in the scheduler. + * @max_budget: maximum budget allowed from the feedback mechanism. + * @budget_timeout: budget expiration (in jiffies). + * @dispatched: number of requests on the dispatch list or inside driver. + * @flags: status flags. + * @bfqq_list: node for active/idle bfqq list inside our bfqd. + * @burst_list_node: node for the device's burst list. + * @seek_samples: number of seeks sampled + * @seek_total: sum of the distances of the seeks sampled + * @seek_mean: mean seek distance + * @last_request_pos: position of the last request enqueued + * @requests_within_timer: number of consecutive pairs of request completion + * and arrival, such that the queue becomes idle + * after the completion, but the next request arrives + * within an idle time slice; used only if the queue's + * IO_bound has been cleared. + * @pid: pid of the process owning the queue, used for logging purposes. + * @last_wr_start_finish: start time of the current weight-raising period if + * the @bfq-queue is being weight-raised, otherwise + * finish time of the last weight-raising period + * @wr_cur_max_time: current max raising time for this queue + * @soft_rt_next_start: minimum time instant such that, only if a new + * request is enqueued after this time instant in an + * idle @bfq_queue with no outstanding requests, then + * the task associated with the queue it is deemed as + * soft real-time (see the comments to the function + * bfq_bfqq_softrt_next_start()). + * @last_idle_bklogged: time of the last transition of the @bfq_queue from + * idle to backlogged + * @service_from_backlogged: cumulative service received from the @bfq_queue + * since the last transition from idle to + * backlogged + * + * A bfq_queue is a leaf request queue; it can be associated with an io_context + * or more, if it is async or shared between cooperating processes. @cgroup + * holds a reference to the cgroup, to be sure that it does not disappear while + * a bfqq still references it (mostly to avoid races between request issuing and + * task migration followed by cgroup destruction). + * All the fields are protected by the queue lock of the containing bfqd. + */ +struct bfq_queue { + atomic_t ref; + struct bfq_data *bfqd; + + /* fields for cooperating queues handling */ + struct bfq_queue *new_bfqq; + struct rb_node pos_node; + struct rb_root *pos_root; + + struct rb_root sort_list; + struct request *next_rq; + int queued[2]; + int allocated[2]; + int meta_pending; + struct list_head fifo; + + struct bfq_entity entity; + + unsigned long max_budget; + unsigned long budget_timeout; + + int dispatched; + + unsigned int flags; + + struct list_head bfqq_list; + + struct hlist_node burst_list_node; + + unsigned int seek_samples; + u64 seek_total; + sector_t seek_mean; + sector_t last_request_pos; + + unsigned int requests_within_timer; + + pid_t pid; + + /* weight-raising fields */ + unsigned long wr_cur_max_time; + unsigned long soft_rt_next_start; + unsigned long last_wr_start_finish; + unsigned int wr_coeff; + unsigned long last_idle_bklogged; + unsigned long service_from_backlogged; +}; + +/** + * struct bfq_ttime - per process thinktime stats. + * @ttime_total: total process thinktime + * @ttime_samples: number of thinktime samples + * @ttime_mean: average process thinktime + */ +struct bfq_ttime { + unsigned long last_end_request; + + unsigned long ttime_total; + unsigned long ttime_samples; + unsigned long ttime_mean; +}; + +/** + * struct bfq_io_cq - per (request_queue, io_context) structure. + * @icq: associated io_cq structure + * @bfqq: array of two process queues, the sync and the async + * @ttime: associated @bfq_ttime struct + */ +struct bfq_io_cq { + struct io_cq icq; /* must be the first member */ + struct bfq_queue *bfqq[2]; + struct bfq_ttime ttime; + int ioprio; +}; + +enum bfq_device_speed { + BFQ_BFQD_FAST, + BFQ_BFQD_SLOW, +}; + +/** + * struct bfq_data - per device data structure. + * @queue: request queue for the managed device. + * @root_group: root bfq_group for the device. + * @rq_pos_tree: rbtree sorted by next_request position, used when + * determining if two or more queues have interleaving + * requests (see bfq_close_cooperator()). + * @active_numerous_groups: number of bfq_groups containing more than one + * active @bfq_entity. + * @queue_weights_tree: rbtree of weight counters of @bfq_queues, sorted by + * weight. Used to keep track of whether all @bfq_queues + * have the same weight. The tree contains one counter + * for each distinct weight associated to some active + * and not weight-raised @bfq_queue (see the comments to + * the functions bfq_weights_tree_[add|remove] for + * further details). + * @group_weights_tree: rbtree of non-queue @bfq_entity weight counters, sorted + * by weight. Used to keep track of whether all + * @bfq_groups have the same weight. The tree contains + * one counter for each distinct weight associated to + * some active @bfq_group (see the comments to the + * functions bfq_weights_tree_[add|remove] for further + * details). + * @busy_queues: number of bfq_queues containing requests (including the + * queue in service, even if it is idling). + * @busy_in_flight_queues: number of @bfq_queues containing pending or + * in-flight requests, plus the @bfq_queue in + * service, even if idle but waiting for the + * possible arrival of its next sync request. This + * field is updated only if the device is rotational, + * but used only if the device is also NCQ-capable. + * The reason why the field is updated also for non- + * NCQ-capable rotational devices is related to the + * fact that the value of @hw_tag may be set also + * later than when busy_in_flight_queues may need to + * be incremented for the first time(s). Taking also + * this possibility into account, to avoid unbalanced + * increments/decrements, would imply more overhead + * than just updating busy_in_flight_queues + * regardless of the value of @hw_tag. + * @const_seeky_busy_in_flight_queues: number of constantly-seeky @bfq_queues + * (that is, seeky queues that expired + * for budget timeout at least once) + * containing pending or in-flight + * requests, including the in-service + * @bfq_queue if constantly seeky. This + * field is updated only if the device + * is rotational, but used only if the + * device is also NCQ-capable (see the + * comments to @busy_in_flight_queues). + * @wr_busy_queues: number of weight-raised busy @bfq_queues. + * @queued: number of queued requests. + * @rq_in_driver: number of requests dispatched and waiting for completion. + * @sync_flight: number of sync requests in the driver. + * @max_rq_in_driver: max number of reqs in driver in the last + * @hw_tag_samples completed requests. + * @hw_tag_samples: nr of samples used to calculate hw_tag. + * @hw_tag: flag set to one if the driver is showing a queueing behavior. + * @budgets_assigned: number of budgets assigned. + * @idle_slice_timer: timer set when idling for the next sequential request + * from the queue in service. + * @unplug_work: delayed work to restart dispatching on the request queue. + * @in_service_queue: bfq_queue in service. + * @in_service_bic: bfq_io_cq (bic) associated with the @in_service_queue. + * @last_position: on-disk position of the last served request. + * @last_budget_start: beginning of the last budget. + * @last_idling_start: beginning of the last idle slice. + * @peak_rate: peak transfer rate observed for a budget. + * @peak_rate_samples: number of samples used to calculate @peak_rate. + * @bfq_max_budget: maximum budget allotted to a bfq_queue before + * rescheduling. + * @group_list: list of all the bfq_groups active on the device. + * @active_list: list of all the bfq_queues active on the device. + * @idle_list: list of all the bfq_queues idle on the device. + * @bfq_fifo_expire: timeout for async/sync requests; when it expires + * requests are served in fifo order. + * @bfq_back_penalty: weight of backward seeks wrt forward ones. + * @bfq_back_max: maximum allowed backward seek. + * @bfq_slice_idle: maximum idling time. + * @bfq_user_max_budget: user-configured max budget value + * (0 for auto-tuning). + * @bfq_max_budget_async_rq: maximum budget (in nr of requests) allotted to + * async queues. + * @bfq_timeout: timeout for bfq_queues to consume their budget; used to + * to prevent seeky queues to impose long latencies to well + * behaved ones (this also implies that seeky queues cannot + * receive guarantees in the service domain; after a timeout + * they are charged for the whole allocated budget, to try + * to preserve a behavior reasonably fair among them, but + * without service-domain guarantees). + * @bfq_coop_thresh: number of queue merges after which a @bfq_queue is + * no more granted any weight-raising. + * @bfq_failed_cooperations: number of consecutive failed cooperation + * chances after which weight-raising is restored + * to a queue subject to more than bfq_coop_thresh + * queue merges. + * @bfq_requests_within_timer: number of consecutive requests that must be + * issued within the idle time slice to set + * again idling to a queue which was marked as + * non-I/O-bound (see the definition of the + * IO_bound flag for further details). + * @last_ins_in_burst: last time at which a queue entered the current + * burst of queues being activated shortly after + * each other; for more details about this and the + * following parameters related to a burst of + * activations, see the comments to the function + * @bfq_handle_burst. + * @bfq_burst_interval: reference time interval used to decide whether a + * queue has been activated shortly after + * @last_ins_in_burst. + * @burst_size: number of queues in the current burst of queue activations. + * @bfq_large_burst_thresh: maximum burst size above which the current + * queue-activation burst is deemed as 'large'. + * @large_burst: true if a large queue-activation burst is in progress. + * @burst_list: head of the burst list (as for the above fields, more details + * in the comments to the function bfq_handle_burst). + * @low_latency: if set to true, low-latency heuristics are enabled. + * @bfq_wr_coeff: maximum factor by which the weight of a weight-raised + * queue is multiplied. + * @bfq_wr_max_time: maximum duration of a weight-raising period (jiffies). + * @bfq_wr_rt_max_time: maximum duration for soft real-time processes. + * @bfq_wr_min_idle_time: minimum idle period after which weight-raising + * may be reactivated for a queue (in jiffies). + * @bfq_wr_min_inter_arr_async: minimum period between request arrivals + * after which weight-raising may be + * reactivated for an already busy queue + * (in jiffies). + * @bfq_wr_max_softrt_rate: max service-rate for a soft real-time queue, + * sectors per seconds. + * @RT_prod: cached value of the product R*T used for computing the maximum + * duration of the weight raising automatically. + * @device_speed: device-speed class for the low-latency heuristic. + * @oom_bfqq: fallback dummy bfqq for extreme OOM conditions. + * + * All the fields are protected by the @queue lock. + */ +struct bfq_data { + struct request_queue *queue; + + struct bfq_group *root_group; + struct rb_root rq_pos_tree; + +#ifdef CONFIG_CGROUP_BFQIO + int active_numerous_groups; +#endif + + struct rb_root queue_weights_tree; + struct rb_root group_weights_tree; + + int busy_queues; + int busy_in_flight_queues; + int const_seeky_busy_in_flight_queues; + int wr_busy_queues; + int queued; + int rq_in_driver; + int sync_flight; + + int max_rq_in_driver; + int hw_tag_samples; + int hw_tag; + + int budgets_assigned; + + struct timer_list idle_slice_timer; + struct work_struct unplug_work; + + struct bfq_queue *in_service_queue; + struct bfq_io_cq *in_service_bic; + + sector_t last_position; + + ktime_t last_budget_start; + ktime_t last_idling_start; + int peak_rate_samples; + u64 peak_rate; + unsigned long bfq_max_budget; + + struct hlist_head group_list; + struct list_head active_list; + struct list_head idle_list; + + unsigned int bfq_fifo_expire[2]; + unsigned int bfq_back_penalty; + unsigned int bfq_back_max; + unsigned int bfq_slice_idle; + u64 bfq_class_idle_last_service; + + unsigned int bfq_user_max_budget; + unsigned int bfq_max_budget_async_rq; + unsigned int bfq_timeout[2]; + + unsigned int bfq_coop_thresh; + unsigned int bfq_failed_cooperations; + unsigned int bfq_requests_within_timer; + + unsigned long last_ins_in_burst; + unsigned long bfq_burst_interval; + int burst_size; + unsigned long bfq_large_burst_thresh; + bool large_burst; + struct hlist_head burst_list; + + bool low_latency; + + /* parameters of the low_latency heuristics */ + unsigned int bfq_wr_coeff; + unsigned int bfq_wr_max_time; + unsigned int bfq_wr_rt_max_time; + unsigned int bfq_wr_min_idle_time; + unsigned long bfq_wr_min_inter_arr_async; + unsigned int bfq_wr_max_softrt_rate; + u64 RT_prod; + enum bfq_device_speed device_speed; + + struct bfq_queue oom_bfqq; +}; + +enum bfqq_state_flags { + BFQ_BFQQ_FLAG_busy = 0, /* has requests or is in service */ + BFQ_BFQQ_FLAG_wait_request, /* waiting for a request */ + BFQ_BFQQ_FLAG_must_alloc, /* must be allowed rq alloc */ + BFQ_BFQQ_FLAG_fifo_expire, /* FIFO checked in this slice */ + BFQ_BFQQ_FLAG_idle_window, /* slice idling enabled */ + BFQ_BFQQ_FLAG_sync, /* synchronous queue */ + BFQ_BFQQ_FLAG_budget_new, /* no completion with this budget */ + BFQ_BFQQ_FLAG_IO_bound, /* + * bfqq has timed-out at least once + * having consumed at most 2/10 of + * its budget + */ + BFQ_BFQQ_FLAG_in_large_burst, /* + * bfqq activated in a large burst, + * see comments to bfq_handle_burst. + */ + BFQ_BFQQ_FLAG_constantly_seeky, /* + * bfqq has proved to be slow and + * seeky until budget timeout + */ + BFQ_BFQQ_FLAG_softrt_update, /* + * may need softrt-next-start + * update + */ + BFQ_BFQQ_FLAG_coop, /* bfqq is shared */ + BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be splitted */ +}; + +#define BFQ_BFQQ_FNS(name) \ +static inline void bfq_mark_bfqq_##name(struct bfq_queue *bfqq) \ +{ \ + (bfqq)->flags |= (1 << BFQ_BFQQ_FLAG_##name); \ +} \ +static inline void bfq_clear_bfqq_##name(struct bfq_queue *bfqq) \ +{ \ + (bfqq)->flags &= ~(1 << BFQ_BFQQ_FLAG_##name); \ +} \ +static inline int bfq_bfqq_##name(const struct bfq_queue *bfqq) \ +{ \ + return ((bfqq)->flags & (1 << BFQ_BFQQ_FLAG_##name)) != 0; \ +} + +BFQ_BFQQ_FNS(busy); +BFQ_BFQQ_FNS(wait_request); +BFQ_BFQQ_FNS(must_alloc); +BFQ_BFQQ_FNS(fifo_expire); +BFQ_BFQQ_FNS(idle_window); +BFQ_BFQQ_FNS(sync); +BFQ_BFQQ_FNS(budget_new); +BFQ_BFQQ_FNS(IO_bound); +BFQ_BFQQ_FNS(in_large_burst); +BFQ_BFQQ_FNS(constantly_seeky); +BFQ_BFQQ_FNS(coop); +BFQ_BFQQ_FNS(split_coop); +BFQ_BFQQ_FNS(softrt_update); +#undef BFQ_BFQQ_FNS + +/* Logging facilities. */ +#define bfq_log_bfqq(bfqd, bfqq, fmt, args...) \ + blk_add_trace_msg((bfqd)->queue, "bfq%d " fmt, (bfqq)->pid, ##args) + +#define bfq_log(bfqd, fmt, args...) \ + blk_add_trace_msg((bfqd)->queue, "bfq " fmt, ##args) + +/* Expiration reasons. */ +enum bfqq_expiration { + BFQ_BFQQ_TOO_IDLE = 0, /* + * queue has been idling for + * too long + */ + BFQ_BFQQ_BUDGET_TIMEOUT, /* budget took too long to be used */ + BFQ_BFQQ_BUDGET_EXHAUSTED, /* budget consumed */ + BFQ_BFQQ_NO_MORE_REQUESTS, /* the queue has no more requests */ +}; + +#ifdef CONFIG_CGROUP_BFQIO +/** + * struct bfq_group - per (device, cgroup) data structure. + * @entity: schedulable entity to insert into the parent group sched_data. + * @sched_data: own sched_data, to contain child entities (they may be + * both bfq_queues and bfq_groups). + * @group_node: node to be inserted into the bfqio_cgroup->group_data + * list of the containing cgroup's bfqio_cgroup. + * @bfqd_node: node to be inserted into the @bfqd->group_list list + * of the groups active on the same device; used for cleanup. + * @bfqd: the bfq_data for the device this group acts upon. + * @async_bfqq: array of async queues for all the tasks belonging to + * the group, one queue per ioprio value per ioprio_class, + * except for the idle class that has only one queue. + * @async_idle_bfqq: async queue for the idle class (ioprio is ignored). + * @my_entity: pointer to @entity, %NULL for the toplevel group; used + * to avoid too many special cases during group creation/ + * migration. + * @active_entities: number of active entities belonging to the group; + * unused for the root group. Used to know whether there + * are groups with more than one active @bfq_entity + * (see the comments to the function + * bfq_bfqq_must_not_expire()). + * + * Each (device, cgroup) pair has its own bfq_group, i.e., for each cgroup + * there is a set of bfq_groups, each one collecting the lower-level + * entities belonging to the group that are acting on the same device. + * + * Locking works as follows: + * o @group_node is protected by the bfqio_cgroup lock, and is accessed + * via RCU from its readers. + * o @bfqd is protected by the queue lock, RCU is used to access it + * from the readers. + * o All the other fields are protected by the @bfqd queue lock. + */ +struct bfq_group { + struct bfq_entity entity; + struct bfq_sched_data sched_data; + + struct hlist_node group_node; + struct hlist_node bfqd_node; + + void *bfqd; + + struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; + struct bfq_queue *async_idle_bfqq; + + struct bfq_entity *my_entity; + + int active_entities; +}; + +/** + * struct bfqio_cgroup - bfq cgroup data structure. + * @css: subsystem state for bfq in the containing cgroup. + * @online: flag marked when the subsystem is inserted. + * @weight: cgroup weight. + * @ioprio: cgroup ioprio. + * @ioprio_class: cgroup ioprio_class. + * @lock: spinlock that protects @ioprio, @ioprio_class and @group_data. + * @group_data: list containing the bfq_group belonging to this cgroup. + * + * @group_data is accessed using RCU, with @lock protecting the updates, + * @ioprio and @ioprio_class are protected by @lock. + */ +struct bfqio_cgroup { + struct cgroup_subsys_state css; + bool online; + + unsigned short weight, ioprio, ioprio_class; + + spinlock_t lock; + struct hlist_head group_data; +}; +#else +struct bfq_group { + struct bfq_sched_data sched_data; + + struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; + struct bfq_queue *async_idle_bfqq; +}; +#endif + +static inline struct bfq_service_tree * +bfq_entity_service_tree(struct bfq_entity *entity) +{ + struct bfq_sched_data *sched_data = entity->sched_data; + unsigned int idx = entity->ioprio_class - 1; + + BUG_ON(idx >= BFQ_IOPRIO_CLASSES); + BUG_ON(sched_data == NULL); + + return sched_data->service_tree + idx; +} + +static inline struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, + bool is_sync) +{ + return bic->bfqq[is_sync]; +} + +static inline void bic_set_bfqq(struct bfq_io_cq *bic, + struct bfq_queue *bfqq, bool is_sync) +{ + bic->bfqq[is_sync] = bfqq; +} + +static inline struct bfq_data *bic_to_bfqd(struct bfq_io_cq *bic) +{ + return bic->icq.q->elevator->elevator_data; +} + +/** + * bfq_get_bfqd_locked - get a lock to a bfqd using a RCU protected pointer. + * @ptr: a pointer to a bfqd. + * @flags: storage for the flags to be saved. + * + * This function allows bfqg->bfqd to be protected by the + * queue lock of the bfqd they reference; the pointer is dereferenced + * under RCU, so the storage for bfqd is assured to be safe as long + * as the RCU read side critical section does not end. After the + * bfqd->queue->queue_lock is taken the pointer is rechecked, to be + * sure that no other writer accessed it. If we raced with a writer, + * the function returns NULL, with the queue unlocked, otherwise it + * returns the dereferenced pointer, with the queue locked. + */ +static inline struct bfq_data *bfq_get_bfqd_locked(void **ptr, + unsigned long *flags) +{ + struct bfq_data *bfqd; + + rcu_read_lock(); + bfqd = rcu_dereference(*(struct bfq_data **)ptr); + + if (bfqd != NULL) { + spin_lock_irqsave(bfqd->queue->queue_lock, *flags); + if (*ptr == bfqd) + goto out; + spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags); + } + + bfqd = NULL; +out: + rcu_read_unlock(); + return bfqd; +} + +static inline void bfq_put_bfqd_unlock(struct bfq_data *bfqd, + unsigned long *flags) +{ + spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags); +} + +static void bfq_check_ioprio_change(struct bfq_io_cq *bic); +static void bfq_put_queue(struct bfq_queue *bfqq); +static void bfq_dispatch_insert(struct request_queue *q, struct request *rq); +static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, + struct bfq_group *bfqg, int is_sync, + struct bfq_io_cq *bic, gfp_t gfp_mask); +static void bfq_end_wr_async_queues(struct bfq_data *bfqd, + struct bfq_group *bfqg); +static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg); +static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq); + +#endif /* _BFQ_H */ From 179a9f686dd9767068ed1efa63d38703391d76bd Mon Sep 17 00:00:00 2001 From: Mauro Andreolini Date: Fri, 5 Jun 2015 17:45:40 +0200 Subject: [PATCH 504/508] block, bfq: add Early Queue Merge (EQM) to BFQ-v7r8 for 3.18.0 A set of processes may happen to perform interleaved reads, i.e.,requests whose union would give rise to a sequential read pattern. There are two typical cases: in the first case, processes read fixed-size chunks of data at a fixed distance from each other, while in the second case processes may read variable-size chunks at variable distances. The latter case occurs for example with QEMU, which splits the I/O generated by the guest into multiple chunks, and lets these chunks be served by a pool of cooperating processes, iteratively assigning the next chunk of I/O to the first available process. CFQ uses actual queue merging for the first type of rocesses, whereas it uses preemption to get a sequential read pattern out of the read requests performed by the second type of processes. In the end it uses two different mechanisms to achieve the same goal: boosting the throughput with interleaved I/O. This patch introduces Early Queue Merge (EQM), a unified mechanism to get a sequential read pattern with both types of processes. The main idea is checking newly arrived requests against the next request of the active queue both in case of actual request insert and in case of request merge. By doing so, both the types of processes can be handled by just merging their queues. EQM is then simpler and more compact than the pair of mechanisms used in CFQ. Finally, EQM also preserves the typical low-latency properties of BFQ, by properly restoring the weight-raising state of a queue when it gets back to a non-merged state. Change-Id: Ie7e0818fe5a7cb58ba84c1605ec6f4cc0414dafd Signed-off-by: Mauro Andreolini Signed-off-by: Arianna Avanzini Signed-off-by: Paolo Valente --- block/bfq-iosched.c | 750 +++++++++++++++++++++++++++++++------------- block/bfq-sched.c | 28 -- block/bfq.h | 54 +++- 3 files changed, 580 insertions(+), 252 deletions(-) diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 773b2ee064b23..71b51c1b436c7 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -573,6 +573,57 @@ static inline unsigned int bfq_wr_duration(struct bfq_data *bfqd) return dur; } +static inline unsigned +bfq_bfqq_cooperations(struct bfq_queue *bfqq) +{ + return bfqq->bic ? bfqq->bic->cooperations : 0; +} + +static inline void +bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_io_cq *bic) +{ + if (bic->saved_idle_window) + bfq_mark_bfqq_idle_window(bfqq); + else + bfq_clear_bfqq_idle_window(bfqq); + if (bic->saved_IO_bound) + bfq_mark_bfqq_IO_bound(bfqq); + else + bfq_clear_bfqq_IO_bound(bfqq); + /* Assuming that the flag in_large_burst is already correctly set */ + if (bic->wr_time_left && bfqq->bfqd->low_latency && + !bfq_bfqq_in_large_burst(bfqq) && + bic->cooperations < bfqq->bfqd->bfq_coop_thresh) { + /* + * Start a weight raising period with the duration given by + * the raising_time_left snapshot. + */ + if (bfq_bfqq_busy(bfqq)) + bfqq->bfqd->wr_busy_queues++; + bfqq->wr_coeff = bfqq->bfqd->bfq_wr_coeff; + bfqq->wr_cur_max_time = bic->wr_time_left; + bfqq->last_wr_start_finish = jiffies; + bfqq->entity.ioprio_changed = 1; + } + /* + * Clear wr_time_left to prevent bfq_bfqq_save_state() from + * getting confused about the queue's need of a weight-raising + * period. + */ + bic->wr_time_left = 0; +} + +/* Must be called with the queue_lock held. */ +static int bfqq_process_refs(struct bfq_queue *bfqq) +{ + int process_refs, io_refs; + + io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; + process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; + BUG_ON(process_refs < 0); + return process_refs; +} + /* Empty burst list and add just bfqq (see comments to bfq_handle_burst) */ static inline void bfq_reset_burst_list(struct bfq_data *bfqd, struct bfq_queue *bfqq) @@ -817,7 +868,7 @@ static void bfq_add_request(struct request *rq) bfq_rq_pos_tree_add(bfqd, bfqq); if (!bfq_bfqq_busy(bfqq)) { - bool soft_rt, + bool soft_rt, coop_or_in_burst, idle_for_long_time = time_is_before_jiffies( bfqq->budget_timeout + bfqd->bfq_wr_min_idle_time); @@ -841,11 +892,12 @@ static void bfq_add_request(struct request *rq) bfqd->last_ins_in_burst = jiffies; } + coop_or_in_burst = bfq_bfqq_in_large_burst(bfqq) || + bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh; soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && - !bfq_bfqq_in_large_burst(bfqq) && + !coop_or_in_burst && time_is_before_jiffies(bfqq->soft_rt_next_start); - interactive = !bfq_bfqq_in_large_burst(bfqq) && - idle_for_long_time; + interactive = !coop_or_in_burst && idle_for_long_time; entity->budget = max_t(unsigned long, bfqq->max_budget, bfq_serv_to_charge(next_rq, bfqq)); @@ -864,11 +916,20 @@ static void bfq_add_request(struct request *rq) if (!bfqd->low_latency) goto add_bfqq_busy; + if (bfq_bfqq_just_split(bfqq)) + goto set_ioprio_changed; + /* - * If the queue is not being boosted and has been idle - * for enough time, start a weight-raising period + * If the queue: + * - is not being boosted, + * - has been idle for enough time, + * - is not a sync queue or is linked to a bfq_io_cq (it is + * shared "for its nature" or it is not shared and its + * requests have not been redirected to a shared queue) + * start a weight-raising period. */ - if (old_wr_coeff == 1 && (interactive || soft_rt)) { + if (old_wr_coeff == 1 && (interactive || soft_rt) && + (!bfq_bfqq_sync(bfqq) || bfqq->bic != NULL)) { bfqq->wr_coeff = bfqd->bfq_wr_coeff; if (interactive) bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); @@ -882,7 +943,7 @@ static void bfq_add_request(struct request *rq) } else if (old_wr_coeff > 1) { if (interactive) bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); - else if (bfq_bfqq_in_large_burst(bfqq) || + else if (coop_or_in_burst || (bfqq->wr_cur_max_time == bfqd->bfq_wr_rt_max_time && !soft_rt)) { @@ -901,18 +962,18 @@ static void bfq_add_request(struct request *rq) /* * * The remaining weight-raising time is lower - * than bfqd->bfq_wr_rt_max_time, which - * means that the application is enjoying - * weight raising either because deemed soft- - * rt in the near past, or because deemed - * interactive a long ago. In both cases, - * resetting now the current remaining weight- - * raising time for the application to the - * weight-raising duration for soft rt - * applications would not cause any latency - * increase for the application (as the new - * duration would be higher than the remaining - * time). + * than bfqd->bfq_wr_rt_max_time, which means + * that the application is enjoying weight + * raising either because deemed soft-rt in + * the near past, or because deemed interactive + * a long ago. + * In both cases, resetting now the current + * remaining weight-raising time for the + * application to the weight-raising duration + * for soft rt applications would not cause any + * latency increase for the application (as the + * new duration would be higher than the + * remaining time). * * In addition, the application is now meeting * the requirements for being deemed soft rt. @@ -947,6 +1008,7 @@ static void bfq_add_request(struct request *rq) bfqd->bfq_wr_rt_max_time; } } +set_ioprio_changed: if (old_wr_coeff != bfqq->wr_coeff) entity->ioprio_changed = 1; add_bfqq_busy: @@ -1167,90 +1229,35 @@ static void bfq_end_wr(struct bfq_data *bfqd) spin_unlock_irq(bfqd->queue->queue_lock); } -static int bfq_allow_merge(struct request_queue *q, struct request *rq, - struct bio *bio) +static inline sector_t bfq_io_struct_pos(void *io_struct, bool request) { - struct bfq_data *bfqd = q->elevator->elevator_data; - struct bfq_io_cq *bic; - struct bfq_queue *bfqq; - - /* - * Disallow merge of a sync bio into an async request. - */ - if (bfq_bio_sync(bio) && !rq_is_sync(rq)) - return 0; - - /* - * Lookup the bfqq that this bio will be queued with. Allow - * merge only if rq is queued there. - * Queue lock is held here. - */ - bic = bfq_bic_lookup(bfqd, current->io_context); - if (bic == NULL) - return 0; - - bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); - return bfqq == RQ_BFQQ(rq); -} - -static void __bfq_set_in_service_queue(struct bfq_data *bfqd, - struct bfq_queue *bfqq) -{ - if (bfqq != NULL) { - bfq_mark_bfqq_must_alloc(bfqq); - bfq_mark_bfqq_budget_new(bfqq); - bfq_clear_bfqq_fifo_expire(bfqq); - - bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; - - bfq_log_bfqq(bfqd, bfqq, - "set_in_service_queue, cur-budget = %lu", - bfqq->entity.budget); - } - - bfqd->in_service_queue = bfqq; -} - -/* - * Get and set a new queue for service. - */ -static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd, - struct bfq_queue *bfqq) -{ - if (!bfqq) - bfqq = bfq_get_next_queue(bfqd); + if (request) + return blk_rq_pos(io_struct); else - bfq_get_next_queue_forced(bfqd, bfqq); - - __bfq_set_in_service_queue(bfqd, bfqq); - return bfqq; + return ((struct bio *)io_struct)->bi_iter.bi_sector; } -static inline sector_t bfq_dist_from_last(struct bfq_data *bfqd, - struct request *rq) +static inline sector_t bfq_dist_from(sector_t pos1, + sector_t pos2) { - if (blk_rq_pos(rq) >= bfqd->last_position) - return blk_rq_pos(rq) - bfqd->last_position; + if (pos1 >= pos2) + return pos1 - pos2; else - return bfqd->last_position - blk_rq_pos(rq); + return pos2 - pos1; } -/* - * Return true if bfqq has no request pending and rq is close enough to - * bfqd->last_position, or if rq is closer to bfqd->last_position than - * bfqq->next_rq - */ -static inline int bfq_rq_close(struct bfq_data *bfqd, struct request *rq) +static inline int bfq_rq_close_to_sector(void *io_struct, bool request, + sector_t sector) { - return bfq_dist_from_last(bfqd, rq) <= BFQQ_SEEK_THR; + return bfq_dist_from(bfq_io_struct_pos(io_struct, request), sector) <= + BFQQ_SEEK_THR; } -static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) +static struct bfq_queue *bfqq_close(struct bfq_data *bfqd, sector_t sector) { struct rb_root *root = &bfqd->rq_pos_tree; struct rb_node *parent, *node; struct bfq_queue *__bfqq; - sector_t sector = bfqd->last_position; if (RB_EMPTY_ROOT(root)) return NULL; @@ -1269,7 +1276,7 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) * next_request position). */ __bfqq = rb_entry(parent, struct bfq_queue, pos_node); - if (bfq_rq_close(bfqd, __bfqq->next_rq)) + if (bfq_rq_close_to_sector(__bfqq->next_rq, true, sector)) return __bfqq; if (blk_rq_pos(__bfqq->next_rq) < sector) @@ -1280,7 +1287,7 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) return NULL; __bfqq = rb_entry(node, struct bfq_queue, pos_node); - if (bfq_rq_close(bfqd, __bfqq->next_rq)) + if (bfq_rq_close_to_sector(__bfqq->next_rq, true, sector)) return __bfqq; return NULL; @@ -1289,14 +1296,12 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) /* * bfqd - obvious * cur_bfqq - passed in so that we don't decide that the current queue - * is closely cooperating with itself. - * - * We are assuming that cur_bfqq has dispatched at least one request, - * and that bfqd->last_position reflects a position on the disk associated - * with the I/O issued by cur_bfqq. + * is closely cooperating with itself + * sector - used as a reference point to search for a close queue */ static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, - struct bfq_queue *cur_bfqq) + struct bfq_queue *cur_bfqq, + sector_t sector) { struct bfq_queue *bfqq; @@ -1316,7 +1321,7 @@ static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, * working closely on the same area of the disk. In that case, * we can group them together and don't waste time idling. */ - bfqq = bfqq_close(bfqd); + bfqq = bfqq_close(bfqd, sector); if (bfqq == NULL || bfqq == cur_bfqq) return NULL; @@ -1343,6 +1348,315 @@ static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, return bfqq; } +static struct bfq_queue * +bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) +{ + int process_refs, new_process_refs; + struct bfq_queue *__bfqq; + + /* + * If there are no process references on the new_bfqq, then it is + * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain + * may have dropped their last reference (not just their last process + * reference). + */ + if (!bfqq_process_refs(new_bfqq)) + return NULL; + + /* Avoid a circular list and skip interim queue merges. */ + while ((__bfqq = new_bfqq->new_bfqq)) { + if (__bfqq == bfqq) + return NULL; + new_bfqq = __bfqq; + } + + process_refs = bfqq_process_refs(bfqq); + new_process_refs = bfqq_process_refs(new_bfqq); + /* + * If the process for the bfqq has gone away, there is no + * sense in merging the queues. + */ + if (process_refs == 0 || new_process_refs == 0) + return NULL; + + bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", + new_bfqq->pid); + + /* + * Merging is just a redirection: the requests of the process + * owning one of the two queues are redirected to the other queue. + * The latter queue, in its turn, is set as shared if this is the + * first time that the requests of some process are redirected to + * it. + * + * We redirect bfqq to new_bfqq and not the opposite, because we + * are in the context of the process owning bfqq, hence we have + * the io_cq of this process. So we can immediately configure this + * io_cq to redirect the requests of the process to new_bfqq. + * + * NOTE, even if new_bfqq coincides with the in-service queue, the + * io_cq of new_bfqq is not available, because, if the in-service + * queue is shared, bfqd->in_service_bic may not point to the + * io_cq of the in-service queue. + * Redirecting the requests of the process owning bfqq to the + * currently in-service queue is in any case the best option, as + * we feed the in-service queue with new requests close to the + * last request served and, by doing so, hopefully increase the + * throughput. + */ + bfqq->new_bfqq = new_bfqq; + atomic_add(process_refs, &new_bfqq->ref); + return new_bfqq; +} + +/* + * Attempt to schedule a merge of bfqq with the currently in-service queue + * or with a close queue among the scheduled queues. + * Return NULL if no merge was scheduled, a pointer to the shared bfq_queue + * structure otherwise. + * + * The OOM queue is not allowed to participate to cooperation: in fact, since + * the requests temporarily redirected to the OOM queue could be redirected + * again to dedicated queues at any time, the state needed to correctly + * handle merging with the OOM queue would be quite complex and expensive + * to maintain. Besides, in such a critical condition as an out of memory, + * the benefits of queue merging may be little relevant, or even negligible. + */ +static struct bfq_queue * +bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq, + void *io_struct, bool request) +{ + struct bfq_queue *in_service_bfqq, *new_bfqq; + + if (bfqq->new_bfqq) + return bfqq->new_bfqq; + + if (!io_struct || unlikely(bfqq == &bfqd->oom_bfqq)) + return NULL; + + in_service_bfqq = bfqd->in_service_queue; + + if (in_service_bfqq == NULL || in_service_bfqq == bfqq || + !bfqd->in_service_bic || + unlikely(in_service_bfqq == &bfqd->oom_bfqq)) + goto check_scheduled; + + if (bfq_class_idle(in_service_bfqq) || bfq_class_idle(bfqq)) + goto check_scheduled; + + if (bfq_class_rt(in_service_bfqq) != bfq_class_rt(bfqq)) + goto check_scheduled; + + if (in_service_bfqq->entity.parent != bfqq->entity.parent) + goto check_scheduled; + + if (bfq_rq_close_to_sector(io_struct, request, bfqd->last_position) && + bfq_bfqq_sync(in_service_bfqq) && bfq_bfqq_sync(bfqq)) { + new_bfqq = bfq_setup_merge(bfqq, in_service_bfqq); + if (new_bfqq != NULL) + return new_bfqq; /* Merge with in-service queue */ + } + + /* + * Check whether there is a cooperator among currently scheduled + * queues. The only thing we need is that the bio/request is not + * NULL, as we need it to establish whether a cooperator exists. + */ +check_scheduled: + new_bfqq = bfq_close_cooperator(bfqd, bfqq, + bfq_io_struct_pos(io_struct, request)); + if (new_bfqq && likely(new_bfqq != &bfqd->oom_bfqq)) + return bfq_setup_merge(bfqq, new_bfqq); + + return NULL; +} + +static inline void +bfq_bfqq_save_state(struct bfq_queue *bfqq) +{ + /* + * If bfqq->bic == NULL, the queue is already shared or its requests + * have already been redirected to a shared queue; both idle window + * and weight raising state have already been saved. Do nothing. + */ + if (bfqq->bic == NULL) + return; + if (bfqq->bic->wr_time_left) + /* + * This is the queue of a just-started process, and would + * deserve weight raising: we set wr_time_left to the full + * weight-raising duration to trigger weight-raising when + * and if the queue is split and the first request of the + * queue is enqueued. + */ + bfqq->bic->wr_time_left = bfq_wr_duration(bfqq->bfqd); + else if (bfqq->wr_coeff > 1) { + unsigned long wr_duration = + jiffies - bfqq->last_wr_start_finish; + /* + * It may happen that a queue's weight raising period lasts + * longer than its wr_cur_max_time, as weight raising is + * handled only when a request is enqueued or dispatched (it + * does not use any timer). If the weight raising period is + * about to end, don't save it. + */ + if (bfqq->wr_cur_max_time <= wr_duration) + bfqq->bic->wr_time_left = 0; + else + bfqq->bic->wr_time_left = + bfqq->wr_cur_max_time - wr_duration; + /* + * The bfq_queue is becoming shared or the requests of the + * process owning the queue are being redirected to a shared + * queue. Stop the weight raising period of the queue, as in + * both cases it should not be owned by an interactive or + * soft real-time application. + */ + bfq_bfqq_end_wr(bfqq); + } else + bfqq->bic->wr_time_left = 0; + bfqq->bic->saved_idle_window = bfq_bfqq_idle_window(bfqq); + bfqq->bic->saved_IO_bound = bfq_bfqq_IO_bound(bfqq); + bfqq->bic->saved_in_large_burst = bfq_bfqq_in_large_burst(bfqq); + bfqq->bic->was_in_burst_list = !hlist_unhashed(&bfqq->burst_list_node); + bfqq->bic->cooperations++; + bfqq->bic->failed_cooperations = 0; +} + +static inline void +bfq_get_bic_reference(struct bfq_queue *bfqq) +{ + /* + * If bfqq->bic has a non-NULL value, the bic to which it belongs + * is about to begin using a shared bfq_queue. + */ + if (bfqq->bic) + atomic_long_inc(&bfqq->bic->icq.ioc->refcount); +} + +static void +bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, + struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) +{ + bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", + (long unsigned)new_bfqq->pid); + /* Save weight raising and idle window of the merged queues */ + bfq_bfqq_save_state(bfqq); + bfq_bfqq_save_state(new_bfqq); + if (bfq_bfqq_IO_bound(bfqq)) + bfq_mark_bfqq_IO_bound(new_bfqq); + bfq_clear_bfqq_IO_bound(bfqq); + /* + * Grab a reference to the bic, to prevent it from being destroyed + * before being possibly touched by a bfq_split_bfqq(). + */ + bfq_get_bic_reference(bfqq); + bfq_get_bic_reference(new_bfqq); + /* + * Merge queues (that is, let bic redirect its requests to new_bfqq) + */ + bic_set_bfqq(bic, new_bfqq, 1); + bfq_mark_bfqq_coop(new_bfqq); + /* + * new_bfqq now belongs to at least two bics (it is a shared queue): + * set new_bfqq->bic to NULL. bfqq either: + * - does not belong to any bic any more, and hence bfqq->bic must + * be set to NULL, or + * - is a queue whose owning bics have already been redirected to a + * different queue, hence the queue is destined to not belong to + * any bic soon and bfqq->bic is already NULL (therefore the next + * assignment causes no harm). + */ + new_bfqq->bic = NULL; + bfqq->bic = NULL; + bfq_put_queue(bfqq); +} + +static inline void bfq_bfqq_increase_failed_cooperations(struct bfq_queue *bfqq) +{ + struct bfq_io_cq *bic = bfqq->bic; + struct bfq_data *bfqd = bfqq->bfqd; + + if (bic && bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh) { + bic->failed_cooperations++; + if (bic->failed_cooperations >= bfqd->bfq_failed_cooperations) + bic->cooperations = 0; + } +} + +static int bfq_allow_merge(struct request_queue *q, struct request *rq, + struct bio *bio) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct bfq_io_cq *bic; + struct bfq_queue *bfqq, *new_bfqq; + + /* + * Disallow merge of a sync bio into an async request. + */ + if (bfq_bio_sync(bio) && !rq_is_sync(rq)) + return 0; + + /* + * Lookup the bfqq that this bio will be queued with. Allow + * merge only if rq is queued there. + * Queue lock is held here. + */ + bic = bfq_bic_lookup(bfqd, current->io_context); + if (bic == NULL) + return 0; + + bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); + /* + * We take advantage of this function to perform an early merge + * of the queues of possible cooperating processes. + */ + if (bfqq != NULL) { + new_bfqq = bfq_setup_cooperator(bfqd, bfqq, bio, false); + if (new_bfqq != NULL) { + bfq_merge_bfqqs(bfqd, bic, bfqq, new_bfqq); + /* + * If we get here, the bio will be queued in the + * shared queue, i.e., new_bfqq, so use new_bfqq + * to decide whether bio and rq can be merged. + */ + bfqq = new_bfqq; + } else + bfq_bfqq_increase_failed_cooperations(bfqq); + } + + return bfqq == RQ_BFQQ(rq); +} + +static void __bfq_set_in_service_queue(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + if (bfqq != NULL) { + bfq_mark_bfqq_must_alloc(bfqq); + bfq_mark_bfqq_budget_new(bfqq); + bfq_clear_bfqq_fifo_expire(bfqq); + + bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; + + bfq_log_bfqq(bfqd, bfqq, + "set_in_service_queue, cur-budget = %lu", + bfqq->entity.budget); + } + + bfqd->in_service_queue = bfqq; +} + +/* + * Get and set a new queue for service. + */ +static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd) +{ + struct bfq_queue *bfqq = bfq_get_next_queue(bfqd); + + __bfq_set_in_service_queue(bfqd, bfqq); + return bfqq; +} + /* * If enough samples have been computed, return the current max budget * stored in bfqd, which is dynamically updated according to the @@ -1488,61 +1802,6 @@ static struct request *bfq_check_fifo(struct bfq_queue *bfqq) return rq; } -/* Must be called with the queue_lock held. */ -static int bfqq_process_refs(struct bfq_queue *bfqq) -{ - int process_refs, io_refs; - - io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; - process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; - BUG_ON(process_refs < 0); - return process_refs; -} - -static void bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) -{ - int process_refs, new_process_refs; - struct bfq_queue *__bfqq; - - /* - * If there are no process references on the new_bfqq, then it is - * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain - * may have dropped their last reference (not just their last process - * reference). - */ - if (!bfqq_process_refs(new_bfqq)) - return; - - /* Avoid a circular list and skip interim queue merges. */ - while ((__bfqq = new_bfqq->new_bfqq)) { - if (__bfqq == bfqq) - return; - new_bfqq = __bfqq; - } - - process_refs = bfqq_process_refs(bfqq); - new_process_refs = bfqq_process_refs(new_bfqq); - /* - * If the process for the bfqq has gone away, there is no - * sense in merging the queues. - */ - if (process_refs == 0 || new_process_refs == 0) - return; - - /* - * Merge in the direction of the lesser amount of work. - */ - if (new_process_refs >= process_refs) { - bfqq->new_bfqq = new_bfqq; - atomic_add(process_refs, &new_bfqq->ref); - } else { - new_bfqq->new_bfqq = bfqq; - atomic_add(new_process_refs, &bfqq->ref); - } - bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", - new_bfqq->pid); -} - static inline unsigned long bfq_bfqq_budget_left(struct bfq_queue *bfqq) { struct bfq_entity *entity = &bfqq->entity; @@ -2269,7 +2528,7 @@ static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq) */ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) { - struct bfq_queue *bfqq, *new_bfqq = NULL; + struct bfq_queue *bfqq; struct request *next_rq; enum bfqq_expiration reason = BFQ_BFQQ_BUDGET_TIMEOUT; @@ -2279,17 +2538,6 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue"); - /* - * If another queue has a request waiting within our mean seek - * distance, let it run. The expire code will check for close - * cooperators and put the close queue at the front of the - * service tree. If possible, merge the expiring queue with the - * new bfqq. - */ - new_bfqq = bfq_close_cooperator(bfqd, bfqq); - if (new_bfqq != NULL && bfqq->new_bfqq == NULL) - bfq_setup_merge(bfqq, new_bfqq); - if (bfq_may_expire_for_budg_timeout(bfqq) && !timer_pending(&bfqd->idle_slice_timer) && !bfq_bfqq_must_idle(bfqq)) @@ -2328,10 +2576,7 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) bfq_clear_bfqq_wait_request(bfqq); del_timer(&bfqd->idle_slice_timer); } - if (new_bfqq == NULL) - goto keep_queue; - else - goto expire; + goto keep_queue; } } @@ -2340,40 +2585,30 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) * for a new request, or has requests waiting for a completion and * may idle after their completion, then keep it anyway. */ - if (new_bfqq == NULL && (timer_pending(&bfqd->idle_slice_timer) || - (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq)))) { + if (timer_pending(&bfqd->idle_slice_timer) || + (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq))) { bfqq = NULL; goto keep_queue; - } else if (new_bfqq != NULL && timer_pending(&bfqd->idle_slice_timer)) { - /* - * Expiring the queue because there is a close cooperator, - * cancel timer. - */ - bfq_clear_bfqq_wait_request(bfqq); - del_timer(&bfqd->idle_slice_timer); } reason = BFQ_BFQQ_NO_MORE_REQUESTS; expire: bfq_bfqq_expire(bfqd, bfqq, 0, reason); new_queue: - bfqq = bfq_set_in_service_queue(bfqd, new_bfqq); + bfqq = bfq_set_in_service_queue(bfqd); bfq_log(bfqd, "select_queue: new queue %d returned", bfqq != NULL ? bfqq->pid : 0); keep_queue: return bfqq; } -static void bfq_update_wr_data(struct bfq_data *bfqd, - struct bfq_queue *bfqq) +static void bfq_update_wr_data(struct bfq_data *bfqd, struct bfq_queue *bfqq) { - if (bfqq->wr_coeff > 1) { /* queue is being boosted */ - struct bfq_entity *entity = &bfqq->entity; - + struct bfq_entity *entity = &bfqq->entity; + if (bfqq->wr_coeff > 1) { /* queue is being weight-raised */ bfq_log_bfqq(bfqd, bfqq, "raising period dur %u/%u msec, old coeff %u, w %d(%d)", - jiffies_to_msecs(jiffies - - bfqq->last_wr_start_finish), + jiffies_to_msecs(jiffies - bfqq->last_wr_start_finish), jiffies_to_msecs(bfqq->wr_cur_max_time), bfqq->wr_coeff, bfqq->entity.weight, bfqq->entity.orig_weight); @@ -2382,12 +2617,16 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, entity->orig_weight * bfqq->wr_coeff); if (entity->ioprio_changed) bfq_log_bfqq(bfqd, bfqq, "WARN: pending prio change"); + /* * If the queue was activated in a burst, or * too much time has elapsed from the beginning - * of this weight-raising, then end weight raising. + * of this weight-raising period, or the queue has + * exceeded the acceptable number of cooperations, + * then end weight raising. */ if (bfq_bfqq_in_large_burst(bfqq) || + bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh || time_is_before_jiffies(bfqq->last_wr_start_finish + bfqq->wr_cur_max_time)) { bfqq->last_wr_start_finish = jiffies; @@ -2396,11 +2635,13 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, bfqq->last_wr_start_finish, jiffies_to_msecs(bfqq->wr_cur_max_time)); bfq_bfqq_end_wr(bfqq); - __bfq_entity_update_weight_prio( - bfq_entity_service_tree(entity), - entity); } } + /* Update weight both if it must be raised and if it must be lowered */ + if ((entity->weight > entity->orig_weight) != (bfqq->wr_coeff > 1)) + __bfq_entity_update_weight_prio( + bfq_entity_service_tree(entity), + entity); } /* @@ -2647,6 +2888,25 @@ static inline void bfq_init_icq(struct io_cq *icq) struct bfq_io_cq *bic = icq_to_bic(icq); bic->ttime.last_end_request = jiffies; + /* + * A newly created bic indicates that the process has just + * started doing I/O, and is probably mapping into memory its + * executable and libraries: it definitely needs weight raising. + * There is however the possibility that the process performs, + * for a while, I/O close to some other process. EQM intercepts + * this behavior and may merge the queue corresponding to the + * process with some other queue, BEFORE the weight of the queue + * is raised. Merged queues are not weight-raised (they are assumed + * to belong to processes that benefit only from high throughput). + * If the merge is basically the consequence of an accident, then + * the queue will be split soon and will get back its old weight. + * It is then important to write down somewhere that this queue + * does need weight raising, even if it did not make it to get its + * weight raised before being merged. To this purpose, we overload + * the field raising_time_left and assign 1 to it, to mark the queue + * as needing weight raising. + */ + bic->wr_time_left = 1; } static void bfq_exit_icq(struct io_cq *icq) @@ -2660,6 +2920,13 @@ static void bfq_exit_icq(struct io_cq *icq) } if (bic->bfqq[BLK_RW_SYNC]) { + /* + * If the bic is using a shared queue, put the reference + * taken on the io_context when the bic started using a + * shared bfq_queue. + */ + if (bfq_bfqq_coop(bic->bfqq[BLK_RW_SYNC])) + put_io_context(icq->ioc); bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_SYNC]); bic->bfqq[BLK_RW_SYNC] = NULL; } @@ -2952,6 +3219,10 @@ static void bfq_update_idle_window(struct bfq_data *bfqd, if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq)) return; + /* Idle window just restored, statistics are meaningless. */ + if (bfq_bfqq_just_split(bfqq)) + return; + enable_idle = bfq_bfqq_idle_window(bfqq); if (atomic_read(&bic->icq.ioc->active_ref) == 0 || @@ -2999,6 +3270,7 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 || !BFQQ_SEEKY(bfqq)) bfq_update_idle_window(bfqd, bfqq, bic); + bfq_clear_bfqq_just_split(bfqq); bfq_log_bfqq(bfqd, bfqq, "rq_enqueued: idle_window=%d (seeky %d, mean %llu)", @@ -3059,12 +3331,47 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, static void bfq_insert_request(struct request_queue *q, struct request *rq) { struct bfq_data *bfqd = q->elevator->elevator_data; - struct bfq_queue *bfqq = RQ_BFQQ(rq); + struct bfq_queue *bfqq = RQ_BFQQ(rq), *new_bfqq; assert_spin_locked(bfqd->queue->queue_lock); + /* + * An unplug may trigger a requeue of a request from the device + * driver: make sure we are in process context while trying to + * merge two bfq_queues. + */ + if (!in_interrupt()) { + new_bfqq = bfq_setup_cooperator(bfqd, bfqq, rq, true); + if (new_bfqq != NULL) { + if (bic_to_bfqq(RQ_BIC(rq), 1) != bfqq) + new_bfqq = bic_to_bfqq(RQ_BIC(rq), 1); + /* + * Release the request's reference to the old bfqq + * and make sure one is taken to the shared queue. + */ + new_bfqq->allocated[rq_data_dir(rq)]++; + bfqq->allocated[rq_data_dir(rq)]--; + atomic_inc(&new_bfqq->ref); + bfq_put_queue(bfqq); + if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq) + bfq_merge_bfqqs(bfqd, RQ_BIC(rq), + bfqq, new_bfqq); + rq->elv.priv[1] = new_bfqq; + bfqq = new_bfqq; + } else + bfq_bfqq_increase_failed_cooperations(bfqq); + } + bfq_add_request(rq); + /* + * Here a newly-created bfq_queue has already started a weight-raising + * period: clear raising_time_left to prevent bfq_bfqq_save_state() + * from assigning it a full weight-raising period. See the detailed + * comments about this field in bfq_init_icq(). + */ + if (bfqq->bic != NULL) + bfqq->bic->wr_time_left = 0; rq->fifo_time = jiffies + bfqd->bfq_fifo_expire[rq_is_sync(rq)]; list_add_tail(&rq->queuelist, &bfqq->fifo); @@ -3226,18 +3533,6 @@ static void bfq_put_request(struct request *rq) } } -static struct bfq_queue * -bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, - struct bfq_queue *bfqq) -{ - bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", - (long unsigned)bfqq->new_bfqq->pid); - bic_set_bfqq(bic, bfqq->new_bfqq, 1); - bfq_mark_bfqq_coop(bfqq->new_bfqq); - bfq_put_queue(bfqq); - return bic_to_bfqq(bic, 1); -} - /* * Returns NULL if a new bfqq should be allocated, or the old bfqq if this * was the last process referring to said bfqq. @@ -3246,6 +3541,9 @@ static struct bfq_queue * bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq) { bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); + + put_io_context(bic->icq.ioc); + if (bfqq_process_refs(bfqq) == 1) { bfqq->pid = current->pid; bfq_clear_bfqq_coop(bfqq); @@ -3274,6 +3572,7 @@ static int bfq_set_request(struct request_queue *q, struct request *rq, struct bfq_queue *bfqq; struct bfq_group *bfqg; unsigned long flags; + bool split = false; might_sleep_if(gfp_mask & __GFP_WAIT); @@ -3291,25 +3590,26 @@ static int bfq_set_request(struct request_queue *q, struct request *rq, if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { bfqq = bfq_get_queue(bfqd, bfqg, is_sync, bic, gfp_mask); bic_set_bfqq(bic, bfqq, is_sync); + if (split && is_sync) { + if ((bic->was_in_burst_list && bfqd->large_burst) || + bic->saved_in_large_burst) + bfq_mark_bfqq_in_large_burst(bfqq); + else { + bfq_clear_bfqq_in_large_burst(bfqq); + if (bic->was_in_burst_list) + hlist_add_head(&bfqq->burst_list_node, + &bfqd->burst_list); + } + } } else { - /* - * If the queue was seeky for too long, break it apart. - */ + /* If the queue was seeky for too long, break it apart. */ if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq)) { bfq_log_bfqq(bfqd, bfqq, "breaking apart bfqq"); bfqq = bfq_split_bfqq(bic, bfqq); + split = true; if (!bfqq) goto new_queue; } - - /* - * Check to see if this queue is scheduled to merge with - * another closely cooperating queue. The merging of queues - * happens here as it must be done in process context. - * The reference on new_bfqq was taken in merge_bfqqs. - */ - if (bfqq->new_bfqq != NULL) - bfqq = bfq_merge_bfqqs(bfqd, bic, bfqq); } bfqq->allocated[rw]++; @@ -3320,6 +3620,26 @@ static int bfq_set_request(struct request_queue *q, struct request *rq, rq->elv.priv[0] = bic; rq->elv.priv[1] = bfqq; + /* + * If a bfq_queue has only one process reference, it is owned + * by only one bfq_io_cq: we can set the bic field of the + * bfq_queue to the address of that structure. Also, if the + * queue has just been split, mark a flag so that the + * information is available to the other scheduler hooks. + */ + if (likely(bfqq != &bfqd->oom_bfqq) && bfqq_process_refs(bfqq) == 1) { + bfqq->bic = bic; + if (split) { + bfq_mark_bfqq_just_split(bfqq); + /* + * If the queue has just been split from a shared + * queue, restore the idle window and the possible + * weight raising period. + */ + bfq_bfqq_resume_state(bfqq, bic); + } + } + spin_unlock_irqrestore(q->queue_lock, flags); return 0; diff --git a/block/bfq-sched.c b/block/bfq-sched.c index c3430993ec943..d0890c6d4c114 100644 --- a/block/bfq-sched.c +++ b/block/bfq-sched.c @@ -1085,34 +1085,6 @@ static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) return bfqq; } -/* - * Forced extraction of the given queue. - */ -static void bfq_get_next_queue_forced(struct bfq_data *bfqd, - struct bfq_queue *bfqq) -{ - struct bfq_entity *entity; - struct bfq_sched_data *sd; - - BUG_ON(bfqd->in_service_queue != NULL); - - entity = &bfqq->entity; - /* - * Bubble up extraction/update from the leaf to the root. - */ - for_each_entity(entity) { - sd = entity->sched_data; - bfq_update_budget(entity); - bfq_update_vtime(bfq_entity_service_tree(entity)); - bfq_active_extract(bfq_entity_service_tree(entity), entity); - sd->in_service_entity = entity; - sd->next_in_service = NULL; - entity->service = 0; - } - - return; -} - static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd) { if (bfqd->in_service_bic != NULL) { diff --git a/block/bfq.h b/block/bfq.h index 3173b35e38536..629c413c16abc 100644 --- a/block/bfq.h +++ b/block/bfq.h @@ -218,18 +218,21 @@ struct bfq_group; * idle @bfq_queue with no outstanding requests, then * the task associated with the queue it is deemed as * soft real-time (see the comments to the function - * bfq_bfqq_softrt_next_start()). + * bfq_bfqq_softrt_next_start()) * @last_idle_bklogged: time of the last transition of the @bfq_queue from * idle to backlogged * @service_from_backlogged: cumulative service received from the @bfq_queue * since the last transition from idle to * backlogged + * @bic: pointer to the bfq_io_cq owning the bfq_queue, set to %NULL if the + * queue is shared * - * A bfq_queue is a leaf request queue; it can be associated with an io_context - * or more, if it is async or shared between cooperating processes. @cgroup - * holds a reference to the cgroup, to be sure that it does not disappear while - * a bfqq still references it (mostly to avoid races between request issuing and - * task migration followed by cgroup destruction). + * A bfq_queue is a leaf request queue; it can be associated with an + * io_context or more, if it is async or shared between cooperating + * processes. @cgroup holds a reference to the cgroup, to be sure that it + * does not disappear while a bfqq still references it (mostly to avoid + * races between request issuing and task migration followed by cgroup + * destruction). * All the fields are protected by the queue lock of the containing bfqd. */ struct bfq_queue { @@ -269,6 +272,7 @@ struct bfq_queue { unsigned int requests_within_timer; pid_t pid; + struct bfq_io_cq *bic; /* weight-raising fields */ unsigned long wr_cur_max_time; @@ -298,12 +302,42 @@ struct bfq_ttime { * @icq: associated io_cq structure * @bfqq: array of two process queues, the sync and the async * @ttime: associated @bfq_ttime struct + * @wr_time_left: snapshot of the time left before weight raising ends + * for the sync queue associated to this process; this + * snapshot is taken to remember this value while the weight + * raising is suspended because the queue is merged with a + * shared queue, and is used to set @raising_cur_max_time + * when the queue is split from the shared queue and its + * weight is raised again + * @saved_idle_window: same purpose as the previous field for the idle + * window + * @saved_IO_bound: same purpose as the previous two fields for the I/O + * bound classification of a queue + * @saved_in_large_burst: same purpose as the previous fields for the + * value of the field keeping the queue's belonging + * to a large burst + * @was_in_burst_list: true if the queue belonged to a burst list + * before its merge with another cooperating queue + * @cooperations: counter of consecutive successful queue merges underwent + * by any of the process' @bfq_queues + * @failed_cooperations: counter of consecutive failed queue merges of any + * of the process' @bfq_queues */ struct bfq_io_cq { struct io_cq icq; /* must be the first member */ struct bfq_queue *bfqq[2]; struct bfq_ttime ttime; int ioprio; + + unsigned int wr_time_left; + bool saved_idle_window; + bool saved_IO_bound; + + bool saved_in_large_burst; + bool was_in_burst_list; + + unsigned int cooperations; + unsigned int failed_cooperations; }; enum bfq_device_speed { @@ -536,7 +570,7 @@ enum bfqq_state_flags { BFQ_BFQQ_FLAG_idle_window, /* slice idling enabled */ BFQ_BFQQ_FLAG_sync, /* synchronous queue */ BFQ_BFQQ_FLAG_budget_new, /* no completion with this budget */ - BFQ_BFQQ_FLAG_IO_bound, /* + BFQ_BFQQ_FLAG_IO_bound, /* * bfqq has timed-out at least once * having consumed at most 2/10 of * its budget @@ -549,12 +583,13 @@ enum bfqq_state_flags { * bfqq has proved to be slow and * seeky until budget timeout */ - BFQ_BFQQ_FLAG_softrt_update, /* + BFQ_BFQQ_FLAG_softrt_update, /* * may need softrt-next-start * update */ BFQ_BFQQ_FLAG_coop, /* bfqq is shared */ - BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be splitted */ + BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be split */ + BFQ_BFQQ_FLAG_just_split, /* queue has just been split */ }; #define BFQ_BFQQ_FNS(name) \ @@ -583,6 +618,7 @@ BFQ_BFQQ_FNS(in_large_burst); BFQ_BFQQ_FNS(constantly_seeky); BFQ_BFQQ_FNS(coop); BFQ_BFQQ_FNS(split_coop); +BFQ_BFQQ_FNS(just_split); BFQ_BFQQ_FNS(softrt_update); #undef BFQ_BFQQ_FNS From 404727b826098a1ca355a307b5a68d66046a7c7f Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Mon, 9 Jul 2018 20:34:03 +0530 Subject: [PATCH 505/508] arm64: configs: Enable bfq Change-Id: I322e8344badc5e8626f99f43d2ea6ecf83eebbd5 --- arch/arm64/configs/mido_defconfig | 3 +++ arch/arm64/configs/tissot_defconfig | 3 +++ 2 files changed, 6 insertions(+) diff --git a/arch/arm64/configs/mido_defconfig b/arch/arm64/configs/mido_defconfig index dca617c0fa069..6b6988e46c8ea 100644 --- a/arch/arm64/configs/mido_defconfig +++ b/arch/arm64/configs/mido_defconfig @@ -301,8 +301,11 @@ CONFIG_IOSCHED_NOOP=y # CONFIG_IOSCHED_TEST is not set CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y +CONFIG_IOSCHED_BFQ=y +CONFIG_CGROUP_BFQIO=y # CONFIG_DEFAULT_DEADLINE is not set CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_BFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" CONFIG_ASN1=y diff --git a/arch/arm64/configs/tissot_defconfig b/arch/arm64/configs/tissot_defconfig index 4fc208b61ac0e..86d6b29610bb2 100644 --- a/arch/arm64/configs/tissot_defconfig +++ b/arch/arm64/configs/tissot_defconfig @@ -294,8 +294,11 @@ CONFIG_IOSCHED_NOOP=y # CONFIG_IOSCHED_TEST is not set CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y +CONFIG_IOSCHED_BFQ=y +CONFIG_CGROUP_BFQIO=y # CONFIG_DEFAULT_DEADLINE is not set CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_BFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" CONFIG_ASN1=y From 38ac7ab45ae8d8cc1251e911aba4666fdb42d5bc Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Wed, 18 Jul 2018 18:35:16 +0530 Subject: [PATCH 506/508] Revert "HACK: arm64: add CNTPCT_EL0 trap handler" This reverts commit e8bf56274e8e06c1d1c16197b8e2f0a9ed1846d2. Change-Id: I6152dc909c40d615385ccc98d9a558debd265c1e --- arch/arm64/kernel/traps.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 2bcea95c34232..b42991af2e289 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -419,19 +419,6 @@ static void cntfrq_read_handler(unsigned int esr, struct pt_regs *regs) regs->pc += 4; } -static void cntpct_read_handler(unsigned int esr, struct pt_regs *regs) -{ - int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; - - isb(); - if (rt != 31) - regs->regs[rt] = arch_counter_get_cntpct(); - regs->pc += 4; -} - -#define ESR_ELx_SYS64_ISS_SYS_CNTPCT (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 1, 14, 0) | \ - ESR_ELx_SYS64_ISS_DIR_READ) - asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs) { if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTVCT) { @@ -440,9 +427,6 @@ asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs) } else if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTFRQ) { cntfrq_read_handler(esr, regs); return; - } else if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTPCT) { - cntpct_read_handler(esr, regs); - return; } do_undefinstr(regs); From c03e0a9ce946e54f3cef660efe9a1760baa25588 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 19 Jan 2018 15:42:09 +0000 Subject: [PATCH 507/508] arm64: Move BP hardening to check_and_switch_context We call arm64_apply_bp_hardening() from post_ttbr_update_workaround, which has the unexpected consequence of being triggered on every exception return to userspace when ARM64_SW_TTBR0_PAN is selected, even if no context switch actually occured. This is a bit suboptimal, and it would be more logical to only invalidate the branch predictor when we actually switch to a different mm. In order to solve this, move the call to arm64_apply_bp_hardening() into check_and_switch_context(), where we're guaranteed to pick a different mm context. Change-Id: I28f2fb09b77544e5ead095e9dad1ad64b2b3ae36 Acked-by: Will Deacon Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas Git-commit: a8e4c0a919ae310944ed2c9ace11cf3ccd8a609b Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Srinivas Ramana --- arch/arm64/mm/context.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c index 9758b3d3e0a37..b277d059575a7 100644 --- a/arch/arm64/mm/context.c +++ b/arch/arm64/mm/context.c @@ -191,6 +191,9 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu) raw_spin_unlock_irqrestore(&cpu_asid_lock, flags); switch_mm_fastpath: + + arm64_apply_bp_hardening(); + /* * Defer TTBR0_EL1 setting for user threads to uaccess_enable() when * emulating PAN. @@ -202,7 +205,6 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu) /* Errata workaround post TTBRx_EL1 update. */ asmlinkage void post_ttbr_update_workaround(void) { - arm64_apply_bp_hardening(); } static int asids_init(void) From 80cb3f607eb78280642c3b9b6e89f676e9c263bf Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Mon, 23 Jul 2018 19:22:59 +0530 Subject: [PATCH 508/508] drivers: power uncomment enable_emergency_dload_mode --- drivers/power/reset/msm-poweroff.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index bbb458fb2a6dc..7e04e78a35f5a 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -203,12 +203,10 @@ static void set_dload_mode(int on) return; } -#if 0 static void enable_emergency_dload_mode(void) { pr_err("dload mode is not enabled on target\n"); } -#endif static bool get_dload_mode(void) {